Compose the default coding tool registry

Merged
VA
3d ago
+8909-2572

Problem

GraphCoder needs a complete harness coding toolset with real workspace execution, volume routing, and fenced publication.

Design

  • Export tools::defaults() containing bash, fs, read, write and edit. .tool(..) and .tools(..) are additive; .without_default_tools() opts out. Bindings determine both registration and grants.
  • Native bash uses the task view, relative cwd, timeout, exit status and streaming chunk files. One mount table controls discovery, routing, capture exclusions and authority. File tools publish through the selected mount; fs supports --volume through the shared Git facade and publication lease.
  • Git merges ignore native timestamps, merge executable bits and text separately, and project conflict markers before returning failure. The existing pending join retains conflict paths and identities. Continuation follows renamed files, scans only conflicted entries in bounded ranges, rejects remaining markers, and accepts manual binary/deletion resolutions.
  • Output and client request files share one generation-retry publisher. Each retry authenticates the retained history prefix and rechecks ownership. No new state store or wire message.
  • Scratch mounts are created only when bash is enabled. Missing providers return typed MountUnavailable errors naming the device. Ordinary checkouts without default tools retain directory capture.

Deletions

Remove recursive default-tool constructors, MemoryHarnessStorage additions, old file-tool names, acyclic.read_file_range, redundant adapters and duplicate fuzz paths. PR delta against the merge base of main: +6,320 lines (+8,892 / -2,572).

Decisions

  • Stock bash enables native environment inheritance on the existing process-launch path, then overlays task mount hints. The OS launcher preserves native bytes and applies Windows environment semantics; no host map or Unicode conversion is needed.
  • Recovery leaves inspected conflicted joins pending. Pure repository inspection cannot change that state; checked merge continuation or abort must settle it. Uninspected joins and other pending transitions retain their prior fence.
  • The shared command fuzzer owns quote/parse coverage. The file-tool fuzz target retains only the input and protected-metadata codecs.
  • writes outside the task view are not captured; no OS sandbox in release 1. Retain cwd validation and document host access in bash's description and Rust docs.
  • Mount retirement completes through the existing provider stop/join and physical destination fence before the final owner disappears. LocalHarness::close(self).await awaits unmount and consumes the stream owner. No sleep, reopen retry loop, or new in-process fence registry.
  • Record continuation metadata only after merge projection succeeds. Interruptions before that point retain an uninspected pending join and continuation refuses, preserving clean source changes. A real guard regression rejects the former premature-record ordering.
  • Capture exclusions follow actually attached mounts, so an ordinary .volumes/scratch directory remains captured when bash is disabled. Registry replacement clears earlier queued custom tools while preserving later additions.
  • Private-file reads retain authenticated publication metadata without assuming a literal staging version; the regression checks the actual published reference and bytes using directory authority.
  • Default mount discovery lives in the pinned context-manifest conventions, replacing the former runtime context stage after merging main. A scripted model scenario checks the mount line.
  • Continuation uses one checked resolution result: live tracked paths plus current paths of retained conflict identities. This replaces the former boolean check and separate tracking filter, so renamed resolutions remain tracked through clean. The existing pending Git transition retains stable file identities. Explicit deletion is valid; renaming unresolved markers is not. Git delete/modify selection retains the matching directory binding and exact tracked paths.
  • Disable compaction in the filesystem-only scripted scenarios; they do not script summary-model responses. Dedicated compaction tests retain their policies and coverage. Assert the failed resolution command, rejected continuation, visible markers and final resolved bytes.
  • Recovery tests share setup and mounts, reconstruct production bindings from durable records at every cut, and retain a complete host reopen. Every cut and all four shrinking payload cases remain.
  • The output Loom model runs the production retry loop against a concurrent actual MemoryStream append. Client record preparation occurs before spawning; this removes irrelevant client-index reconstruction schedules. Both retry and ownership models include deliberately broken negative controls and use the instrumented crate-local synchronization shim.

Tests run

  • Final rename delta at signed head f308bfb80: 11 focused Linux tests passed. Resolution/17 MiB tests took 0.064 s, Git views 0.415 s, and stock checkout reconciliation 3.575 s. The shrinking property checks exact tracked sets after resolution, rename and deletion, excluding unrelated files. SDK and stock-tool scenarios rename a conflicted file, resolve it, continue and clean; the resolved bytes survive. The SDK case also verifies that clean removes a genuinely untracked file and includes the former original-name filter as a negative control.
  • Final log: /home/var/log/buildbox/2026-10-16T170406164Z-299832.log, exit 0, 431.7 s including build. Reuse /home/var/targets/gc-tools-17e70fdc/debug/deps/acyclic_harness-df2c9af156190653 and acyclic_fs-c808b28c69295133 in the same directory.
  • Windows: final harness/filesystem cargo check --lib --tests --features acyclic-harness/filesystem-local,acyclic-harness/native-execution,acyclic-harness/objects passed through lb.ps1 in 38.27 s. The first attempt hit disk-full; the unchanged command passed after space recovered. No artifacts were deleted.
  • Unchanged native environment code passed 4 tests in 0.315 s at 310aa4061, including shrinking raw-byte values, HOME, host-only PATH lookup, an unrelated non-UTF-8 key, mount overrides and the inheritance-disabled negative control. Log: /home/var/log/buildbox/2026-10-16T163943086Z-260163.log.
  • Merged base b64b07d03 passed 26 focused tests, including pending-state properties and focused Git history. Baseline review at 9947c748e passed 125 focused tests, including both production-path publication Loom models with negative controls (0.47 s), full recovery cuts (1.67 s), and reopen (1.77 s). These results cover unchanged mount routing, ownership fencing, range, registry and streaming paths.
  • Shrinking properties cover native environment values, generation/history custody, pending transition identity and inspection, registry replacement, renamed/deleted entries and their tracking, Git metadata/binding choices, option-value routing and streaming marker recognition. Shared-source fuzz targets and corpora cover command routing, pending transitions, marker bytes and file-tool codecs; no fuzz campaign was run.
  • git diff --check passes. Searches confirm removed file-tool names and the superseded boolean merge API have no callers; the TypeScript contract explicitly checks the removed ranged tool is absent.

Follow-ups

  • gc-goal (#671) handoff: stock write to .volumes/scratch/GOAL.md publishes into scratch and returns a FileRef with that exact volume and path GOAL.md; read and edit use that reference. Admission can inspect the existing workspace.mounts.mounts() entries by exact volume and call Mount::check(Action::Write, relative_path, now) before constructing the prefixed task path. An absent or denied mount is blocked; never fall back to the project or infer writability from output_volume(). Reuse this table for any reverse-path helper rather than maintaining another mapping.
  • Lazy child views, coordinated with gc-agents (#669), which owns child creation.
  • Foreign-policy mounts and native read-only enforcement, with matching file-tool authority.
  • Agent lifecycle discard, coordinated with gc-agents (#669). Handoff: https://github.com/acyclic-labs/sdk/pull/669#issuecomment-6209942415.

Pre-existing main issue, assigned to gc-context: automatic compaction rejects its authenticated summary reference under the LocalHarness task scope. The context lane will authorize the exact summary reference; it is outside this delta.

ToolSpec catalog work follows after this review. Search, plan and image work belongs to the reassigned lanes.