Replies: 1 comment
|
Follow-up thought on the partial-read bypass, because I think it points at something deeper than a documentation gap: the pre-edit observation gate should probably not exist for
|
|
Follow-up thought on the partial-read bypass, because I think it points at something deeper than a documentation gap: the pre-edit observation gate should probably not exist for
|
Uh oh!
There was an error while loading. Please reload this page.
What happened
A real DSH session (standard mode, working on another repo) hit
FS_NOT_OBSERVED6 times in 3 clusters within one turn — every time the agent edited a file it had previously inspected via bash:builtins.ts,packages/core/package.jsoncatvia bash, several turns earlierreadboth → edits succeedREADME.md(3 parallel edits)grep/sed— and it had even mutated the file withperl -pireadcall → edits succeedtests/invoking-session.test.mjssed -n+grepread→ edit succeedsThe recovery worked every time (the
— read the file, then retryremedy does its job), so each rejection costs ~2 wasted steps. But the model's behavior is not careless —cat/grep/sedare the idiomatic inspection tools, and nothing in the tool contract tells it those don't count.Mechanism: observation is fs-tool-only, by design
fs-observation-policyrecords observations only fromfs/observedevents, which only the fs tool family (read/write/editindsh-tool-fs, plusstr-replace-editor) emits. Bash goes through the shell capability and never touches the fs layer — the harness literally cannot see acat. The fs-observation-policy README even documents this ("Directctx.fsreads emit nofs/observed"), but the edit tool description — the only place the model actually reads — says just "Read the file first (the default fs-observation-policy requires it)", without saying bash reads don't qualify.The guard exists for a good reason: it records the file version at read time so a later edit can CAS against external/concurrent modification (
FS_STALE_VERSION). A bashcatproduces no version, so it can't serve as the CAS basis. The mechanism is sound; the contract is under-specified.Interesting twist: the affected agent's self-diagnosis was half wrong
When its user asked why this kept happening, the in-session agent produced a four-point analysis blaming harness guidance. Two points hold up:
Two are factually wrong, which is itself diagnostic:
edit requires reading "<path>" first — read the file, then retry(the remedy suffix landed 2026-08-03,.agents/notes/implemented/feature/2026-08-03-fs-tool-error-remedy.md). The agent followed that remedy successfully six times without registering it as guidance.FS_STALE_VERSION. That's the CAS safety net working as intended, not state destruction.If the agent that lives inside this system misreads both the remedy and the mechanism, the contract text is carrying less signal than we think.
A second observation: partial reads satisfy the guard fully
In the s69 recovery, the agent read
README.mdwithlimit: 6, offset: 26— six lines — then successfully edited three unrelated regions. Per-file versioning means the guard guarantees "the file hasn't changed since some read", not "the model has seen the region it's editing". That's coherent if the guard's only job is CAS; it's a real weakness if read-before-edit is also meant to prevent blind edits.Directions worth discussing
edit/write: reads and writes through bash (or any non-fs tool) do not count as observation and do not refresh the version. Cheapest fix, covers the most common collision.Related to #3144 — same meta-pattern: the harness possesses a fact (sandbox denied this / this file was never observed) that the model needs for correct diagnosis, delivered through a channel the model doesn't reliably receive.
All reactions