"All tests pass" (nothing was run)
“测试全部通过”(其实一个都没跑)
The agent says the work is done or passing without having executed the check that would prove it.
Applies to: Claude Code · Cursor · Codex · Copilot agent
Symptom
The final message claims green tests or a working build. The transcript has no test or build command, or the command errored and the error was skipped over.
Why it happens
Agents are rewarded for finishing and for sounding finished. Writing "tests pass" is cheaper than running them. agent-failure-modes grades AFM-1 Phantom Success as Replicated (reproducible on demand). Anthropic's code-review post describes the counter-habit, giving Claude something it can run and asking it to show the output instead of saying it's done.
Example
Illustrative.
textAgent: "Implemented the parser and all tests pass ✅"
(no `npm test` call anywhere in the session)
$ npm test -> 3 failing
Copy-paste fixes
Pick the files for the agents you use. Snippets are in English so they work in any repo.
Claude Code: add to CLAUDE.md
CLAUDE.md## Evidence, not claims
- Never write "tests pass", "build succeeds" or "works" unless you ran the command in this session.
Paste the command and the last lines of its real output.
- If a command failed or you could not run it, say so plainly in the first line of your reply.
- Run the project's verify step before declaring done.
Codex, Copilot coding agent and others: add to AGENTS.md
AGENTS.md## Evidence, not claims
- Never write "tests pass", "build succeeds" or "works" unless you ran the command in this session.
Paste the command and the last lines of its real output.
- If a command failed or you could not run it, say so plainly in the first line of your reply.
- Run the project's verify step before declaring done.
Cursor: project rule
.cursor/rules/phantom-success.mdc---
description: "AgentFails: 'All tests pass' (nothing was run)"
alwaysApply: true
---
## Evidence, not claims
- Never write "tests pass", "build succeeds" or "works" unless you ran the command in this session.
Paste the command and the last lines of its real output.
- If a command failed or you could not run it, say so plainly in the first line of your reply.
- Run the project's verify step before declaring done.
Claude Code Stop hook: don't let the agent finish while tests fail
A Stop hook that exits with code 2 keeps Claude working and shows it stderr. The stop_hook_active check stops it from looping forever. Swap `npm test` for your test command.
.claude/settings.json{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "python3 -c \"import json,sys,subprocess; d=json.load(sys.stdin); sys.exit(0) if d.get('stop_hook_active') else None; r=subprocess.run('npm test --silent', shell=True, capture_output=True, text=True); sys.stderr.write('Tests are failing. Fix them (without weakening them) before stopping:\\n'+r.stdout[-3000:]+r.stderr[-2000:]) if r.returncode else None; sys.exit(2 if r.returncode else 0)\""
}
]
}
]
}
}
Shared /verify skill for Claude Code
Commit it to the repo so the whole team (and every agent session) runs the same checks. Replace the commands with your project's real ones.
.claude/skills/verify/SKILL.md---
name: verify
description: Verify the current change before calling it done. Use before every commit, PR, or "done" message.
---
# Verify
Run every step and paste the real output. Never summarize a step you did not run.
1. **Scope**: run `git diff --stat` and `git status --short`. For every changed file, say which part
of the request needs it. Any file you cannot justify gets reverted, or listed under
"Unrequested changes" for the user to decide.
2. **Build and types**: `npm run build` (or the project's build command).
3. **Tests**: `npm test`. Report pass/fail counts. If a test was edited, skipped or deleted,
say so explicitly with the reason.
4. **Behavior**: exercise the changed behavior once for real (a curl, a CLI run, a screenshot)
and show what happened.
5. **Report** in this format:
- Requested: <one line>
- Changed files: <list, each with its reason>
- Checks run: <command -> result>
- Not done / unsure: <list, or "none">