Harness spec 3.5.0: the watch command's hash puts the exit status after the bytes, so the output is hashed as it streams
ci / check (push) Waiting to run
ci / check (push) Waiting to run
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
3 files changed
+13
-12
No files matched your search
+1
-1
@@ -93,7 +93,7 @@ round (`acp.md` *Scheduled work on a linked computer*, `loop.json` `scheduled`).
|
|||||||
goes on. `ask_user` and `plan_submit` have nobody to answer; `show` is not offered.
|
goes on. `ask_user` and `plan_submit` have nobody to answer; `show` is not offered.
|
||||||
- **Monitor mode, the device's half**: `_lembas/monitor` runs a schedule's watch command in its
|
- **Monitor mode, the device's half**: `_lembas/monitor` runs a schedule's watch command in its
|
||||||
folder, with a timeout, under the mode's permission rules — **a command the mode would ask about
|
folder, with a timeout, under the mode's permission rules — **a command the mode would ask about
|
||||||
is refused** — and answers the output's hash (`sha256:` over the exit status and the bytes) and a
|
is refused** — and answers the output's hash (`sha256:` over the bytes and then the exit status) and a
|
||||||
short excerpt; the server runs the model only when the hash changed, and records `unchanged`
|
short excerpt; the server runs the model only when the hash changed, and records `unchanged`
|
||||||
otherwise.
|
otherwise.
|
||||||
- **Schedules over `/api/v2` with the device's token** (scope `link`): the CLI's `/schedule` lists,
|
- **Schedules over `/api/v2` with the device's token** (scope `link`): the CLI's `/schedule` lists,
|
||||||
|
|||||||
+7
-6
@@ -435,10 +435,11 @@ default rules, the global rules and — in a trusted project — the project's),
|
|||||||
`scheduled.texts.monitor_denied`, both `-32602` with `data: { reason: "permission" }`
|
`scheduled.texts.monitor_denied`, both `-32602` with `data: { reason: "permission" }`
|
||||||
(`conformance/monitor.json`).
|
(`conformance/monitor.json`).
|
||||||
|
|
||||||
**The hash** (`monitor.json` `hash` cases): `sha256:` and the lowercase hex SHA-256 of the exit
|
**The hash** (`monitor.json` `hash` cases): `sha256:` and the lowercase hex SHA-256 of the
|
||||||
status as decimal digits, a newline, and then the output's bytes exactly as read — standard output
|
output's bytes exactly as read — standard output and standard error as one stream, as the `bash`
|
||||||
and standard error as one stream, as the `bash` tool reads them. Nothing is normalised: a watch
|
tool reads them — followed by a newline and the exit status as decimal digits (after the bytes, so
|
||||||
command that prints a time changes every time, and should not.
|
the device hashes the output as it streams, however long). Nothing is normalised: a watch command
|
||||||
|
that prints a time changes every time, and should not.
|
||||||
|
|
||||||
## `_lembas/*` methods
|
## `_lembas/*` methods
|
||||||
|
|
||||||
@@ -499,8 +500,8 @@ with no input; at the timeout the group is stopped.
|
|||||||
Result `{ hash, exit, timed_out, excerpt, truncated, bytes, duration_ms }`: `hash` as above (`null`
|
Result `{ hash, exit, timed_out, excerpt, truncated, bytes, duration_ms }`: `hash` as above (`null`
|
||||||
when it timed out), `exit` the exit status (`null` on a signal or a timeout), `excerpt` the start of
|
when it timed out), `exit` the exit status (`null` on a signal or a timeout), `excerpt` the start of
|
||||||
the output decoded as UTF-8 (invalid bytes replaced), at most `scheduled.monitor.excerpt_chars`
|
the output decoded as UTF-8 (invalid bytes replaced), at most `scheduled.monitor.excerpt_chars`
|
||||||
characters, `truncated` whether there was more, `bytes` the output's length. The device keeps at
|
characters, `truncated` whether there was more, `bytes` the output's length. The device hashes all
|
||||||
most `scheduled.monitor.output_max_bytes` of output and hashes all of it as it streams.
|
of the output as it streams and keeps at most `scheduled.monitor.output_max_bytes` of it.
|
||||||
|
|
||||||
### `_lembas/directories` — client → agent → result
|
### `_lembas/directories` — client → agent → result
|
||||||
|
|
||||||
|
|||||||
@@ -6,35 +6,35 @@
|
|||||||
"kind": "hash",
|
"kind": "hash",
|
||||||
"exit": 0,
|
"exit": 0,
|
||||||
"output": "ok\n",
|
"output": "ok\n",
|
||||||
"expect": "sha256:9dbd5131695af2d8636ea64178344ffcb5d682333c2ac8342153b5f8a999037a"
|
"expect": "sha256:9427ae13c91f98a3af2213b34fb59e4bb5aa9e6101a1f7407f526dde3571e6aa"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"about": "The same output with another exit status is a change.",
|
"about": "The same output with another exit status is a change.",
|
||||||
"kind": "hash",
|
"kind": "hash",
|
||||||
"exit": 1,
|
"exit": 1,
|
||||||
"output": "ok\n",
|
"output": "ok\n",
|
||||||
"expect": "sha256:262115bdbc989849fb45967adac594dde8d45deb291f3a26b38fb2bf4e10512b"
|
"expect": "sha256:21e0bbd37d04094ef29f22d0212bb0f4bedda1b1fab38d51f9b8670b5cf07df4"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"about": "No output.",
|
"about": "No output.",
|
||||||
"kind": "hash",
|
"kind": "hash",
|
||||||
"exit": 0,
|
"exit": 0,
|
||||||
"output": "",
|
"output": "",
|
||||||
"expect": "sha256:9a271f2a916b0b6ee6cecb2426f0b3206ef074578be55d9bc94f6f3fe3ab86aa"
|
"expect": "sha256:c7757c0896cbfe6182d8ea2bda4a8bf94addc428980eedab8609c57ca7ff1763"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"about": "A trailing newline counts: nothing is normalised.",
|
"about": "A trailing newline counts: nothing is normalised.",
|
||||||
"kind": "hash",
|
"kind": "hash",
|
||||||
"exit": 0,
|
"exit": 0,
|
||||||
"output": "ok",
|
"output": "ok",
|
||||||
"expect": "sha256:05df918976ca296956abf9b5fb424bb9bef7c32bb471b1005b417abc696e25a9"
|
"expect": "sha256:b9b8913ecae1ba8190ef1a22cc57afef08ad3933ab4b13a32f8cdccb07bb527b"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"about": "UTF-8 output, hashed as its bytes.",
|
"about": "UTF-8 output, hashed as its bytes.",
|
||||||
"kind": "hash",
|
"kind": "hash",
|
||||||
"exit": 0,
|
"exit": 0,
|
||||||
"output": "lembas · ✓\n",
|
"output": "lembas · ✓\n",
|
||||||
"expect": "sha256:cb00179ad9e36546b1b973ded0903592a6b975552b5596feac573426c67e24e4"
|
"expect": "sha256:3d1c38d3b96ee10d71faac35eb2933ba13b68d6325872fdda3e459c9fbd17d98"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"about": "A read-only command in Edit runs.",
|
"about": "A read-only command in Edit runs.",
|
||||||
|
|||||||
Reference in new issue
Block a user