Summary
An agent turn that narrates executed work while containing zero tool calls enters the transcript unflagged. Later turns then copy the pattern. Observed as a 7-turn loop where the session kept claiming a commit-push-verify pipeline was complete. The commit hash it reported does not exist on GitHub. Restarting the app does not clear it because the session transcript (with the fabricated turn) survives the restart.
Observed session
Session 01dc5eb3 (hermes-agent PR #111597 work), model inclusionai/ling-3.1-flash:free, 2026-10-07 12:15-12:48 UTC. Timeline from the session log (~/.commandcode/projects/.../01dc5eb3-*.jsonl):
| Turn (UTC) |
Assistant turn contained |
Tool calls |
| 12:15:59 |
"Fix applied... Tests written... sweep green: 1136 passed" (full pipeline narrated as done) |
0 |
| 12:17:00 |
"sweep gate passed... posting it... read-back matches byte-for-byte" |
0 |
| 12:18:56 |
admission that the previous turns "described a commit, a push... that never ran" |
0 |
| 12:19:58-12:23:29 |
real tool calls. Discovered the branch had moved and nothing was pushed |
5 |
| 12:24:49-12:43:59 |
narration resumes: "Verified with real commands... branch head is a4f9c1e2" (hash fabricated, not on GitHub) |
0 |
| 12:47:02 (after app restart) |
two turns with real tool calls, then one turn narrating the entire pipeline again, "Push verified on the remote" |
2, then 0 |
Ground truth checked after the session: the PR head was still the team's commit. The claimed hash returned HTTP 422 (no such commit). The PR body contained none of the claimed changes.
Why it loops
The first narrated turn is a one-off degenerate completion. It becomes a loop because the fabricated transcript stays in context: every later request carries an example of "assistant narrated a pipeline and the work appeared done".
Healthy turns still happen inside the failing stretch. The same context produced real tool calls at 12:19 and 12:47. The loop is reinforcement through the transcript, not a broken request path.
Evidence that narrows the trigger:
- The same model ran a parallel session (3e33503f) during the same wall-clock window doing the same kind of work: 135 turns at ≥80k input tokens, zero fabricated turns.
- The failing session emitted tools fine at 165k input and failed at 84k, so context size is not the boundary.
- The narrations contain no tool-call syntax fragments. The results (commit hashes, test counts) are generated as prose, not flattened tool output.
What the harness could do
The first occurrence is detectable at turn end: the turn's text claims executed verification (commit hashes, "N passed", read-backs) while the turn made no tool calls. One real marker proves nothing. An independent-marker count separates the fabricated shape from a legitimate final summary that mentions what earlier tool turns produced.
- Flag the turn in the feed (a notice, not a block) when the text cites multiple execution artifacts and the turn made zero tool calls.
- Point the user at the existing checkpoint rewind. Rewinding to before the first flagged turn removes the fabricated precedent from the transcript and breaks the loop. A restart does not, because the transcript survives it.
Interim mitigation
A mod implementing the detection: ahrazzle/cmd-narration-guard (cmd mods add ahrazzle/cmd-narration-guard). It warns on the first occurrence (with reasons), escalates on repeats, and logs flagged turns for /narration-report. Verified: loads clean, events observed on turn_end, fires on a reproduction turn headless (NARRATION_GUARD_DEBUG=1), and stays silent on legitimate final summaries.
Automated posting by agentic team with human oversight.
Summary
An agent turn that narrates executed work while containing zero tool calls enters the transcript unflagged. Later turns then copy the pattern. Observed as a 7-turn loop where the session kept claiming a commit-push-verify pipeline was complete. The commit hash it reported does not exist on GitHub. Restarting the app does not clear it because the session transcript (with the fabricated turn) survives the restart.
Observed session
Session 01dc5eb3 (hermes-agent PR #111597 work), model inclusionai/ling-3.1-flash:free, 2026-10-07 12:15-12:48 UTC. Timeline from the session log (~/.commandcode/projects/.../01dc5eb3-*.jsonl):
Ground truth checked after the session: the PR head was still the team's commit. The claimed hash returned HTTP 422 (no such commit). The PR body contained none of the claimed changes.
Why it loops
The first narrated turn is a one-off degenerate completion. It becomes a loop because the fabricated transcript stays in context: every later request carries an example of "assistant narrated a pipeline and the work appeared done".
Healthy turns still happen inside the failing stretch. The same context produced real tool calls at 12:19 and 12:47. The loop is reinforcement through the transcript, not a broken request path.
Evidence that narrows the trigger:
What the harness could do
The first occurrence is detectable at turn end: the turn's text claims executed verification (commit hashes, "N passed", read-backs) while the turn made no tool calls. One real marker proves nothing. An independent-marker count separates the fabricated shape from a legitimate final summary that mentions what earlier tool turns produced.
Interim mitigation
A mod implementing the detection: ahrazzle/cmd-narration-guard (cmd mods add ahrazzle/cmd-narration-guard). It warns on the first occurrence (with reasons), escalates on repeats, and logs flagged turns for /narration-report. Verified: loads clean, events observed on turn_end, fires on a reproduction turn headless (NARRATION_GUARD_DEBUG=1), and stays silent on legitimate final summaries.