Skip to content

fix(discovery): agents/researcher.md declares no tools and its Tool-honesty prose describes a grant it never made #2204

Description

@kyle-sexton

The defect

plugins/discovery/agents/researcher.md declares no tools: key and no disallowedTools: key, so it inherits every tool available to subagents — while its own "Tool honesty" section asserts the opposite. Three independent audit passes found this.

Frontmatter at HEAD (agents/researcher.md:1-9), in full:

---
name: researcher
description: "Runs the full /discovery:research discipline in a fresh context…"
skills:
  - discovery:research
model: inherit
effort: high
maxTurns: 40
---

The false prose (agents/researcher.md:71-72 and :76):

`Edit` is absent from your tool list. State what that buys and nothing more: you cannot mutate an
existing repo file in a single call.
…
`Agent` is listed, but **listing is necessary and not sufficient**

Both sentences are false in that file. There is no tool list. Edit is held.

The sharpest form, which no packet stated: the same paragraph appears in agents/explorer.md:75 and :80, where it is true — the explorer's allowlist at explorer.md:4 (tools: "Read, Grep, Glob, Bash, Write, Skill, Agent") omits Edit and includes Agent. The paragraph was copied to a file whose frontmatter makes both sentences false. The drift is mechanical, not a judgment call.

Docs check

https://code.claude.com/docs/en/sub-agents, fetched 2026-08-11:

  • tools frontmatter row: "Tools the subagent can use. Inherits every tool available to subagents if omitted."
  • disallowedTools row: "Tools to deny, removed from inherited or specified list" — syntax disallowedTools: Write, Edit.
  • Background filter (background is the default since v2.1.198, and both observed runs were background): "a background subagent keeps every MCP tool but only these built-in tools: Read, Grep, Glob, Bash, PowerShell, Edit, Write, NotebookEdit, WebFetch, WebSearch, TodoWrite, Skill, ToolSearch, EnterWorktree, ExitWorktree, Monitor, TaskStop, SendMessage, and Artifact." — Edit is retained.
  • Agent: removed by the first filter "when the subagent is at the depth limit" even when listed — inherited-and-conditionally-removed, never "listed" in this file's frontmatter.
  • isolation row: "Set to worktree to run the subagent in a temporary git worktree, giving it an isolated copy of the repository…"

Inheritance is observed, not only derived. The session transcripts show the researcher calling ToolSearch and WebFetch — neither of which is in the explorer's allowlist.

grep -rni "isolation:" plugins/discovery → no hits. Neither agent adopts isolation, and neither dispatch contract mentions it.

Severity and provenance

HIGH · AUDITOR_VERIFIED (×3 independent passes) · PRESENT_AT_HEAD. An unattended maxTurns: 40 worker whose declared write boundary ("you do not modify repository source") is instruction-held, and whose calibration input for that boundary is a false inventory understated by roughly a dozen tools including a second shell (PowerShell) and the entire session MCP pool. Least-privilege understatement is the dangerous polarity, on an agent whose whole job is fetching untrusted third-party web content.

Adjacent but not the same defect: #1573 (CLOSED) fixed the nesting claim in the same paragraph, which is why the depth-limit half reads accurately today while the Edit half does not.

The fix

Do not add a tools: allowlist. An allowlist strips every MCP tool ("The subagent can't edit files, write files, or use any MCP tools"), and mandatory discipline #3 in /discovery:research requires mixing in doc-MCP servers. The 0.11.3 allowlist removal was correctly motivated; the omission of any replacement declaration is what went wrong.

  1. Rewrite the "Tool honesty" section to state the truth: no allowlist is declared, the pool is inherited, Edit is held, PowerShell is a second shell, Agent is inherited and conditionally filtered at the depth limit, the MCP pool is held, and the memory-tier boundary holds by instruction only.
  2. Add disallowedTools: for what the contract already forbids. NotebookEdit is unambiguously unused. Edit carries a named dependency and is not denied: research-checklist.md rows are marked [ ][x] as phases proceed, which is an Edit-shaped operation, and denying it forces full-file Write rewrites of the coverage ledger.
  3. Make the explorer/researcher asymmetry deliberate and written down rather than accidental, in both files.
  4. Decide EnterWorktree/ExitWorktree and isolation: worktree on purpose for both agents, and record the decision either way.

Not honorable as filed: one packet asks that the write-guard refusal be "backed by the disallowedTools line so the next run's compliance is a property of the definition." It cannot be — you cannot deny "Bash writing a file" without denying Bash, which the research discipline needs for gh api, curl, and local extractors. That boundary stays instruction-held, and the fix should say so rather than imply enforcement it does not have.

Regression test: a check over plugins/discovery/agents/*.md asserting that any agent whose prose says a tool is absent from its tool list actually declares a tools: key omitting it. This class of drift is mechanically detectable and will recur.

Provenance

One defect, three ledgers, implemented once:

  • 20260810-225904-discovery-dispatch-persistence-contractF2 (owner; empirically confirmed against the transcript)
  • 2026-08-10-plugin-quality-audit-four-components (021645Z) — D-F2 ("three false statements about its own grant"; supplies the disallowedTools/Edit-dependency analysis)
  • four-components (023241Z) — B-F2 (supplies the refinement that the depth-limit half should be rewritten, not deleted, since its substantive point matches the documented filter)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions