Address files by workspace path and return numbered text from read and edit
Path-only read and edit replace the model-facing FileRef contract that blocked live finding F5. The shared executor derives stale-edit authority from successful durable tool results, and the line-window reader hashes and validates the full file while retaining only the selected lines.
Problem
Models cannot invent authenticated volume/generation/hash references. Reads and edits exposed those internal references, and the former observation reconstruction repeatedly reloaded every preceding result. A selected large line could also allocate before its budget was admitted.
Design
readaccepts{path, offset?, limit?}and renders numbered text.editaccepts{path, old_string, new_string, replace_all?}. Internal canonical results retain the exact FileRef; model projections expose text.- Path reads pass through the single owner-bound authorization/resolution path. Edits compare the latest successfully observed version and publish with an exact-generation fence. Failed calls never advance authority.
- Each turn exclusively owns its observation fold. Calls borrow it mutably and continue from its journal cursor; a resumed turn reconstructs it from durable records. There is no shared fold lock or replace/take window.
- Selected-window growth claims storage, allocation and copy work on the original ledger before growing the buffer. One streaming scanner validates UTF-8 across chunk boundaries and hashes the complete file.
Deletions
Removed model-facing FileRef/byte-range arguments, e2e reference seeding, repeated observation reconstruction, and the fold mutex. Net diff against the current merge base: +4,791/-2,575 lines (+2,216), including regenerated contracts, fixtures and tests.
Decisions
- Successful
ToolCompletedrecords are the sole observed-version authority. A new turn has its own fold; a restart reconstructs it from the journal. - The new
executor::tests::observedfixture now binds an admitted task context. Tool authority alone did not enter the production observation path. Successful fixture runs must also return their expected final answer. - Main-baseline failures in
bundle::tests,core::authority::effect_root_testsand the recorded baseline/flake list belong to main-green. They are not counted as #895 regressions and are not rerun by the focused gate. - No new concurrency primitive replaces the deleted mutex. Exclusive ownership makes concurrent replacement of a turn's fold impossible.
- A private publication descriptor authenticates its original immutable payload. The shared metadata selector uses the SDK unchanged-payload check; a raw editor or shell overwrite falls back to a new descriptor without invalidating historical pinned reads.
- An initial lazy checkout read promotes only the requested path. It preserves unrelated source files as lazy and does not republish an already authored path.
- Typed model-visible refusals remain a merge prerequisite through #899; no second error-settlement path is introduced here.
Guarantee
- Class: B/E (stale or lost observed authority), F/H (unadmitted allocation and repeated history work), K (model-facing identity and split UTF-8). The shared authorization path, exact publication fence, turn-owned cursor fold, preclaimed growth, and text-only tool schemas remove the duplicate paths that caused these defects.
- Proof: exact journal payload-load assertions cover 0/50/100 calls and repeated folds; resetting the production fold restores the redundant work and violates the same count. Reopen and failed-read controls preserve successful-result authority. Shrinking window/UTF-8 properties compare the production scanner with an independent whole-input oracle. A production append mutant allocates before admission and is detected by the denial oracle; a discarded-carry mutant fails the UTF-8 oracle. The
line_windowfuzz target and checked-in malformed/truncated/split corpus passed 200,000 runs in 3 seconds on Linux GNU. The added GraphCoder subprocess plus HTTP Responses scenario exercises read/edit/read, physical checkout publication and reopen; it passed at 1b8f2f5b6 in 1.354s. New shrinking SDK-transaction and lazy-source properties cover stale metadata, path pinning and repeated reads, with production mutations that restore both defects. - Entry points: default read/write/edit/patch result projections; owner-bound project and mounted-volume path resolution; ordinary and resumed stock-tool dispatch/reconciliation; complete-file hash/range checking; line-window buffer growth; the real CLI and HTTP provider path. Existing scenario assertions are retained.
- Gaps:
READ-errorsremains blocked on integration with #899's typed model-visible refusals. This is a merge prerequisite, not a follow-up. The PR remains draft while that gap is open. The PR's own proof does not wait for the separately owned DST suite.
Validation
- Previously reviewed focused suites: units/properties 20/20 (0.045s), default tools 17/17 (0.078s), portable integration 7/7 (0.099s), read scenarios 24/24 (1.106s), edit scenarios 23/23 (1.295s), bash 14/14 (0.702s), diff 9/9 (0.200s), oracles 2/2 (0.192s).
- Production
line_windowfuzz: 200,000 runs, 3s, Linux GNU. Scanner implementation unchanged since that run. - At 8ac379cae: Windows GNU harness
--lib --testspassed in 5m02s. The lib run exposed the new observation fixture's missing task context and one complete-UTF-8 fixture expectation; both are fixed here. Known main failures are excluded using Q:/lanes/main-gate/1a4eff552.log and Q:/lanes/flakes.txt. - Observation regressions: 3/3 passed (0.158s), including exact payload-load counts and the production reset control. Earlier Windows GNU harness and GraphCoder checks passed; these do not substitute for the current-head check.
- The stock path probe exposed an initial lazy source read returning NotFound before any edit. Signed head 1b8f2f5b6 fixes requested-path promotion and includes its shrinking property and production negative control. The current-head focused Linux gate passed: 23 tests, each suite below 2.1s; Windows GNU harness and GraphCoder checks passed in 6m26s and 3m01s. No broad baseline suites are rerun.
The live CLI/provider tier would have caught F5 before merge; prior tool tests supplied authenticated references internally and bypassed the model-facing contract. The new real CLI/HTTP scenario uses only path/text arguments.
Current-head gate: buildbox job 1792327583915-1751131, rc=0. Stock path tools 2.016s; source pinning 1.396s; omitted-promotion control 0.092s; publication identity 0.008s; reads 9/9 in 0.009s; ranges 8/8 in 0.895s; native overwrite 0.258s; real CLI/HTTP path tools 1.354s. Known main-baseline failures were not rerun.