Skip to content

Prompt-drift check — three agents in two days told a story about themselves their capabilities contradicted #315

Description

@serge-ivo

The recurring failure

Three separate incidents in two days, all the same shape — a prompt string asserting something
about the agent that its resolved capabilities contradict
:

What the prompt said What was true
#254 "NEVER claim you personally ran commands… you do not drive the engine" start_work was in BASE; the agent had just used it
#255 "attach a repository in the Repo tab" the agent declares surfaces: ["coding"] — it has no Repo tab
#247 Coder docs described a tmux pane the engine is a child process; tmux was removed in June

Each was fixed individually. The class is untouched, and the codebase already diagnosed it — from
toolBlurbFor:

Describing tools the agent doesn't have is not cosmetic: it tells the model a story about itself
that its actual tool set contradicts, and the model believes the story.

That comment was written after Local Repo Chat refused to read a repo it could already read. It
is the same lesson, and it keeps being learned one incident at a time.

Why it keeps happening

Capability is datatoolNamesFor(capabilities), capabilities.surfaces,
SELF_WRITABLE_FIELDS. Claims about capability are hardcoded English in agent-think.ts.
Prose cannot be type-checked, so it drifts the moment the data changes, and the drift is invisible
until an agent says something wrong to a user.

There are currently 8+ prompt lines naming UI locations ("the Coding tab", "the Repo tab") that
are not derived from capabilities.surfaces. None are wrong today. That is exactly what was true
of the tmux lines in June.

Proposal: a prompt-drift check, in the shape the repo already uses

scripts/docs-drift.mjs does this for documentation — 8 checks, including "MCP tool table: 124
registered, 124 documented, exact match". instance-config.test.ts does it for a code pattern,
scanning the tree for raw UPDATE agent_instances SET config because "a reviewer cannot be
expected to catch the seventeenth by eye"
.

Same idea for prompts. Build the system prompt for a set of representative capability fixtures and
assert:

Fixtures worth pinning: a Repo Coder (coding, drive:false), Repo Chat (repo), a cloud-only
chat agent (no surfaces, no runtime), and the legacy Coder.

Why this is worth a ticket rather than more care

Care was applied. Every one of those three lines was written by someone who understood the system,
and #254's was written as a correctness fix. The lines went stale because capability moved, not
because anyone was careless — and that is precisely the situation a mechanical check exists for.

Verification

  • Adding a tool to BASE without updating the prompt fails the check with the contradicting line
    named.
  • Renaming or removing a console surface fails any prompt that still names it.
  • The check runs in CI next to docs:drift.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions