Resolve conflicts from master's catalog/doc refactors landing alongside the tool-call timeout work: - knip.json: keep both new workspace entries (util/timeout + support/acp-snapshot). - tool-web/src/fetch.ts: keep the timeout_ms removal, adopt master's richer JSDoc @param/@returns style on parseFetchArgs/presentFetchCall. - tools/README.md: keep the tools/execute pipeline wording, adopt master's flattened docs/tool-catalog.md path. - Regenerate every generated doc (cordis-catalog, tool-catalog, config-catalog, doc-graphs, module-graph) so they carry both master's changes and the tools/execute event + timeout-policy package. - Add @param/@returns to toolTimeoutResult for master's new verify-export-jsdoc gate.
fs/ - filesystem capability family
The filesystem stack: a provider seam (text IO + atomic mutation with an optional version guard), a local implementation, a policy gate plugin (observed-state + read-before-edit + version-guarded write/edit), and the model-facing file tools + executor. All product packages.
| Package | Role | ctx key |
|---|---|---|
fs/ |
Provider seam: text IO + atomic mutation primitives (optional version guard); owns the fs/* policy events |
ctx.fs |
fs-local/ |
Local-filesystem FileSystem implementation |
(registers ctx.fs) |
fs-policy/ |
Policy gate plugin: observed-state + read-before-edit + version-guarded write/edit, via the fs/* event gate |
(no service — fs/* listeners) |
tool-fs/ |
Model-facing read/write/edit tools AND the executor (reads via ctx.fs, owns read windowing, dispatches fs/*) |
(registers on ctx.tools) |
The interface lives at fs/fs/. A sandboxed, remote, or project-scoped filesystem backend can replace fs-local without touching the seam, the policy gate, or the model-facing tool schemas. The policy (fs-policy/) is a plugin that participates only through the fs/* event gate, not a service the tool injects — so dropping it gracefully loses the policy and leaves the unconstrained bare provider rather than breaking the tool. A deployment that loads tool-fs/ is expected to also load it.
No timeouts on file IO
read/write/edit take no timeoutMs, and the provider seam arms no deadline — unlike bash and web, which consume @deepseek-ai/dsh-timeout. A local syscall is best-effort-abortable at most: a timeout could not force an in-progress fsync/rename to stop, so a deadline here would be a knob that cannot deliver on its promise. Adding one would also be an implicit default in the exact place explicit-over-implicit forbids. Both reference agents (Claude Code, Codex) leave file IO untimed for the same reason; cancellation still propagates through the tool-execution signal for best-effort abort at syscall boundaries.