Repository navigation
Richer emergency handoff note from runtime-reconstructed facts #180
Description
This was generated by AI during triage.
Split out of #159 (part 3). See the glossary term Emergency handoff note in CONTEXT.md.
Agent Brief
Category: enhancement
Summary: When the model reaches a limit without writing a handoff note, the runtime writes an emergency handoff note that carries everything it can reconstruct.
Current behavior:
When model execution ends with MODEL_LIMIT_REACHED and no note commit exists for this attempt, the runtime writes a note with _build_emergency_handoff_note. The note contains:
- the four header fields (
issue,started_at,reason,last_work_commit) - a one-line explanation
- the fixed remaining-work line "Review progress preserved on this branch and continue implementation."
A continuation, as in #155, has nothing to go on. The runtime also discards the seal commit returned by seal(). Model execution doesn't record the last assistant text, the tool calls, or the model's Bash commands and their exit status; these exist only as archived log files.
Desired behavior:
The emergency handoff note keeps its title and four header fields exactly as today, so the note validator still passes. It then contains these sections, in order:
- Provenance: says the runtime wrote this note because the model did not, and which limit fired (the existing reason plus the explanation).
- Changes:
git diff --stat <base>..<seal or HEAD>- the attempt's commits (
git log --oneline <base>..HEAD) - the files that were uncommitted when sealing happened (the files in the seal commit), or "none" when there was no seal commit
- the edited-files list is capped at 50 entries with a
+N moreline
- Last model intent: the last assistant text message, truncated to about 1,500 characters, and whether the
handoffskill was invoked on the main thread (invoked / not invoked). - Activity trail:
- the files the model edited or created (from Edit/Write calls)
- the last 15 tool calls, as the tool name, a short target and an ok/error flag
- the last Bash call whose command contains one of the profile's
checkcommands, with its ok/error flag, or "none recorded"
- Check state: "final check: not run" (the runtime doesn't run it on this path), plus the result of the pre-model baseline check if one ran.
- Budget facts:
budget_tokens,max_budget_tokens- where the soft threshold was crossed, or "not crossed"
peak_main_context_tokens- main-thread prompt-cache hit rate
- number of turns
- elapsed time
- Pointers: the attempt log directory, if there is an archive, and the CLI transcript session id, if known.
- Remaining work: states that the runtime could not determine what remains, that the issue's acceptance criteria are the reference, and that none were verified by the runtime. Don't copy the issue body: the continuation's prompt already includes it.
Each part degrades gracefully: a missing archive, session id or baseline check, or no tool calls, renders as "not available" rather than failing.
Key interfaces:
_build_emergency_handoff_note(...): takes the additional facts and renders the sections above.ModelExecution: gains the last assistant text and a bounded activity record (edited paths, recent tool calls with ok/error, last check-command call). These are recorded in memory by the PreToolUse/PostToolUse hooks, not parsed back from the archive.- The token budget summary (
token_budget): add explicitbudget_tokens, turns and elapsed time if they're not already present. - The runner keeps the commit returned by
seal()so it can name the files that sealing committed.
Acceptance criteria:
- An attempt that hits the token hard ceiling without a model-written note produces an emergency handoff note with all sections above, and it passes
_validate_handoff_note(test). - Same for the turn-limit and cost-limit paths (
reasonisturn_limit/cost_hard_limit). - The tool-call trail is bounded at 15 entries, the edited-files list at 50 entries with
+N more, and the assistant text at about 1,500 characters (unit tests). - With no archive, no session id, no baseline check and no tool calls, the note still renders with "not available" / "none recorded" and validates (test).
- The note says plainly that the runtime wrote it and that the final check was not run.
- A model-written note is never replaced or altered (existing tests keep passing).
Out of scope:
- Running the final check before writing the note.
- Copying acceptance criteria or checklists from the issue body.
- Changing when an emergency note is written, or the four header fields.
- The soft-threshold calculation and the model-facing handoff flow (separate sub-issues).
Activity
lbacik commentedon Oct 8, 2026
Agent Attempt Result: complete
Branch: agent/issue-180
PR: #183
Evidence
/home/agent/target-venv/bin/python -m pytest→ exit code 0Details
Claude SDK completed the implementation workflow.