Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
7.5 KiB
Interruption Handoff Reference
Field schema, durability rules, validation, and worked examples for the verified-delivery interruption handoff. Load this file when recording, locating, validating, or reconciling a handoff.
Store locations and durability
A handoff is durable when the next re-entry can find and read it without user assistance. Choose the first available store:
- Repository working-tree file (default).
.verified-delivery/handoff.jsonin the repository root. Before writing it, add the exact path to the worktree's private Git exclusion file (.git/info/exclude, resolving the worktree git directory when.gitis a file). Before every commit, verify withgit status --short --untracked-files=allandgit diff --cached --name-onlythat the handoff is neither tracked nor staged. Do not proceed while it appears in either output. This keeps the record out of broad staging commands while allowing it to survive session and worker replacement on the same working tree. - PR description block. A fenced machine-readable block in the PR description, usable when a PR exists and working-tree state may not survive (ephemeral runners, disposable containers). Because this publishes the verbatim directive and watcher metadata to forge readers, confirm the PR target, disclosed scope, and rollback path (restoring the prior description) before writing it. Survives local loss because it lives on the forge.
- Host-provided durable storage, when the host documents a store that survives session and worker replacement.
The handoff's store field names the location actually used. On re-entry,
scan in the same order; the first open handoff found governs. Never rely on
volatile session memory, chat scrollback, or a stale copy in a screenshot or
summary as the handoff store.
Field schema
| Field | Type | Required | Meaning |
|---|---|---|---|
schema |
string | yes | Literal verified-delivery/handoff-v1 |
status |
string | yes | open while steps remain; closed at the delivery boundary or an authorized stop |
store |
string | yes | Where this record lives (path, PR block, or host store name) |
directive |
string | yes | The user's delivery directive, verbatim |
authorization_boundary |
object | yes | authorized: gated steps granted; out_of_scope: steps explicitly withheld |
repository |
string | yes | Remote identity of the repository (remote URL or host/org/repo form) |
pull_request |
string or null | yes | PR identity, or null before a PR exists |
branch |
string | yes | Delivery branch name |
head_sha |
string | yes | Full head SHA at handoff time |
completed_steps |
array | yes | Gates completed; each entry names the gate, its verdict, and SHA-bound evidence |
pending_steps |
array | yes | Next authorized gated steps, in order |
watchers |
array | yes | Active watcher, process, or worker identifiers; empty array when none |
stop_reason |
string | yes | Observed interruption class: tool-limit, context-limit, worker-loss, session-end, user-pause, boundary-stop |
stop_detail |
string | no | Exact reason when stop_reason is boundary-stop |
updated_at |
string | yes | UTC timestamp of the last update |
Example: open handoff at a tool-limit interruption
The directive authorized implementation, PR creation, merge when green, and post-merge verification. The session hit the tool-call limit after opening the PR and starting CI, with a CI watcher running.
{
"schema": "verified-delivery/handoff-v1",
"status": "open",
"store": ".verified-delivery/handoff.json",
"directive": "Implement the retry-backoff fix, open a PR, and run it end to end: merge when CI is green and reviews are satisfied, then verify post-merge state.",
"authorization_boundary": {
"authorized": ["open-pr", "merge-when-green", "post-merge-verify"],
"out_of_scope": []
},
"repository": "git.example.com/example-org/example-repo",
"pull_request": "<pr-number>",
"branch": "fix/retry-backoff",
"head_sha": "<40-character-head-sha>",
"completed_steps": [
{
"gate": "change-ready",
"verdict": "pass",
"evidence": "local verification suite passed at head <40-character-head-sha>"
},
{
"gate": "pr-open",
"verdict": "pass",
"evidence": "PR <pr-number> open with head <40-character-head-sha>"
}
],
"pending_steps": [
"ci-green",
"review-satisfied",
"merge",
"post-merge-verify"
],
"watchers": ["ci-watch:pr-<pr-number>@head-<40-character-head-sha>"],
"stop_reason": "tool-limit",
"updated_at": "<utc-timestamp>"
}
Placeholder values in angle brackets stand in for real identifiers; a real handoff carries the actual values.
Closing the handoff
- Delivery boundary reached: set
statustoclosed, move the post-merge evidence intocompleted_steps, and emptypending_steps. - Authorized stop with steps remaining (for example, the non-convergence
boundary): set
stop_reasontoboundary-stop, describe the exact reason instop_detail, keeppending_stepsas recorded, and leavestatusopenonly if resumption remains authorized; otherwise close it. - A closed handoff never resumes. A new directive is a new delivery.
Validation on re-entry
An open handoff is usable only when all of these hold. Any failure stops the resumption at that boundary with the exact reason reported:
- Parseable and complete — valid JSON; every required field present;
schemaisverified-delivery/handoff-v1. Otherwise: corrupt handoff. - Repository match — the live remote equals
repository. Otherwise: stale handoff. - Authorization current — the recorded
authorization_boundarystill reflects a directive the user has not withdrawn. Otherwise: absent or ambiguous authorization. - Live state consistent — the PR (when recorded) exists and its merge
state is determinable. If it is open, continue normal reconciliation. If it
was merged while
post-merge-verifyremains pending, verify that the merge contains the recorded head and matches the authorized change, record the merge as completed, and resume post-merge verification. A PR closed without that change, a merge containing a conflicting head, or a rolled-back change makes the handoff stale because the recorded pending steps no longer describe reality. - Head reconciliation — if the live branch head differs from
head_sha, head-bound evidence incompleted_stepsis invalid. Re-verify CI and review on the new head, updatehead_shaandcompleted_steps, then continue.
Re-entry scan order
- Check the default store (
.verified-delivery/handoff.json). - If absent or closed, check the PR description block for an open handoff (fetch the PR live; do not trust a remembered copy).
- If absent, check host-provided durable storage when configured.
- If no open handoff exists anywhere, treat the input as a fresh request — there is nothing to resume.
Reconciliation rules
- Read-only verification always precedes mutation on a resume.
- Gate evidence binds to the head it was verified on; a moved head invalidates it until re-verified.
- A live watcher recorded in
watchersis never duplicated; wait on it or supersede it explicitly and record the change. - Every mutation after resumption updates the handoff (
head_sha,completed_steps,pending_steps,updated_at) so the next interruption resumes from an accurate record.