Skip to content

Document the repo tool execution contract (docs audit) - #957

Merged
selfcontained merged 1 commit into
mainfrom
docs-audit/repo-tools-deep-dive
Aug 14, 2026
Merged

Document the repo tool execution contract (docs audit)#957
selfcontained merged 1 commit into
mainfrom
docs-audit/repo-tools-deep-dive

Conversation

@selfcontained

Copy link
Copy Markdown
Owner

Nightly docs audit — Repo Tools deep-dive (the next_focus carried over three runs), checked against apps/server/src/shared/mcp/repo-tools.ts, shared/mcp/server.ts, agents/lifecycle-hooks.ts and shared/lib/run-command.ts.

Verified clean: the docs-pane built-in tools list matches AGENT_TOOLS as a set in both directions (63 entries), the repo_ prefixing and dot-sanitization claim, the "runs at the root of the agent's checkout" claim (toolsRoot = worktreeRoot ?? repoRoot), the agent/job scope pair (reviewer remains reachable in VALID_SCOPES but is never set — deliberately undocumented), and the hooks' 15s / best-effort claims.

Fixed — docs-pane tools.tsx:

  • Commands are spawned directly, not through a shell, so pipes/globs/&& don't work.
  • name, description and a non-empty command array are required, and one malformed entry throws during the manifest load, which surfaces as every repo_ tool disappearing rather than as a parse error.
  • New "What agents get back": repo tools allow every exit code (allowedExitCodes 0–255), so stdout is the text result with exit code/stdout/stderr alongside — a non-zero exit is something the agent reads, not an error. Dispatch imposes no timeout on them, unlike hooks.
  • New "Picking up changes": the manifest is re-read per tool listing (only hooks are mtime-cached), but a CLI holds the tool list it fetched at session start — so an edited command runs the new version on the next call while a newly added tool needs a new session.
  • Params: empty-string values are skipped too; name/type/flag required, description is what the agent reads.

Fixed — plugins/dispatch/skills/repo-tools/SKILL.md: the claim that a name colliding with a built-in is "rejected at load" is false — BUILTIN_TOOL_NAMES holds unprefixed names while the check tests the repo_-prefixed one, so it can never fire. Reworded to say the prefix is what prevents collisions. Also tightened "run from the repo root" to the agent's checkout root, and noted the no-shell spawn and the hook's 15s timeout.

Tip (Phase 2b): added an ambient repo-tools tip. .dispatch/tools.json has no UI surface whatsoever and had no tip, which is exactly the discovery gap tips exist for. Links to the Repo Tools docs section.

CLAUDE.md: project tree gains plugins/ (new in #952) and release-notes/ (referenced by a whole section but absent from the tree).

Deferred to next run: the Dispatch plugin (#952) has README coverage but zero in-app docs — a docs-pane section plus a matching install tip is the next focus. Also backlogged: the dead BUILTIN_TOOL_NAMES collision check, and the dead exitCode !== 0 warn branch in lifecycle-hooks.ts (runCommand defaults to allowedExitCodes: [0], so a failing hook rejects before that branch is reached — the documented behavior is unaffected).

Verified: pnpm run format:write, pnpm run check, apps/web tips tests, apps/server plugin-manifest tests.

Repo Tools deep-dive against repo-tools.ts, shared/mcp/server.ts,
lifecycle-hooks.ts and run-command.ts. The built-in tool list checked out
in both directions; the gaps were all in how `.dispatch/tools.json`
actually behaves:

- Commands are spawned directly, not through a shell, so pipes/globs/`&&`
  silently don't work.
- `name`, `description` and a non-empty `command` are required, and one
  malformed entry throws during the manifest load — every `repo_` tool
  disappears, with nothing that reads like a parse error.
- Repo tools allow every exit code (allowedExitCodes 0-255), so stdout
  comes back as the text result with exit code/stdout/stderr alongside;
  a non-zero exit is something the agent reads, not an error. Dispatch
  sets no timeout on them, unlike the 15s lifecycle hooks.
- The manifest is re-read per tool listing (only hooks are mtime-cached),
  but the agent's CLI holds the list it fetched at session start, so a
  newly added tool needs a new session while an edited command does not.

Also adds an ambient tip for `.dispatch/tools.json` — the feature has no
UI surface at all and had no tip — and fixes the plugin skill's claim
that a colliding tool name is rejected at load: BUILTIN_TOOL_NAMES holds
unprefixed names and the check tests the `repo_`-prefixed one, so it can
never fire. The prefix is what prevents collisions.

CLAUDE.md's project tree gains plugins/ and release-notes/.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@selfcontained
selfcontained merged commit 2115185 into main Aug 14, 2026
1 check passed
@selfcontained
selfcontained deleted the docs-audit/repo-tools-deep-dive branch August 14, 2026 04:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant