Recover paused and interrupted work¶
Use the durable plan and journal to determine what happened before continuing a run. The same run can retain partial source, provider and policy snapshots, earlier failed checks, a real checkpoint commit and remote-effect receipts.
Read the records¶
GET /api/v1/runs/{id}/plan returns the current plan revision and task states. GET /api/v1/runs/{id}/journal returns its hash-chain entries and a validity flag. Each intent identifies its task and attempt; each receipt records the outcome actually observed.
| State | Meaning | Action |
|---|---|---|
paused, rate limit |
Provider access was throttled | Wait for an allowed bounded retry, or explicitly resume later |
paused, quota |
The provider reported exhausted credits or quota | Resolve it at the provider or hand off explicitly |
paused, authentication |
The selected access failed | Fix access and choose a fresh configured provider snapshot through handoff |
interrupted |
The worker stopped before completion | Inspect the retained workspace and task journal |
needs_reconciliation |
An intent lacks a trustworthy completion receipt | Establish the actual local or remote outcome first |
failed |
The implementation or verification did not complete successfully | Inspect failure evidence; a fresh retry creates a separate run |
A task marked done has a completion receipt. Inspect its evidence: completing a verification command can record a failing exit status. Overall success requires the final passing checks and matching source snapshot.
The Studio walkthrough shows a fixture failed check and unresolved intent, with the continuation controls in context.
Resume the same run¶
Send POST /api/v1/runs/{id}/resume with {}. Resume preserves the workspace, original brief, policy content and provider revision. Local reconciliation inspects the Git root, authorized origin, HEAD and source tree before continuing an unfinished task.
{}
A completed prepare task does not clone the repository again. Completed implementation work remains in place. A failed check can authorize a new bounded repair attempt, with its previous evidence recorded before the next worker call. Retrieved knowledge context and its digest remain available to the continuing worker.
Hand off to another configured worker¶
Send POST /api/v1/runs/{id}/handoff:
{"agent": "claude"}
Handoff is explicit. It creates a new provider configuration snapshot and immutable plan revision, retains earlier revisions, and continues the existing project source. It does not delete partial files, weaken checks or change the frozen project policies.
Test the new provider before handing off. A fresh snapshot can also renew authentication for the same provider. Quota and authentication pauses are not automatically bypassed by selecting another account.
Reconcile remote work¶
Publication, deployment, rollback and knowledge writes have separate remote task intents. An unknown remote outcome cannot be retried through generic local reconciliation. Inspect the corresponding provider for the recorded branch, job, source or knowledge version. Retain its identity and outcome as evidence before deciding on the next operation.
Retry uses a fresh run and clone; it is separate from resume. It preserves the failed run's history. A new run does not roll back any external effect from the earlier run.
Reconcile worker delivery requests¶
Read GET /api/v1/runs/{id}/execution-requests before repeating publication or cancellation. Each request retains its admitted source, actor, status and hash-chain events. A worker records dispatch before the effect and its observed result afterward. An interruption between those records leaves needs_reconciliation.
An authorized operator can ask the server to reconcile the exact request:
forge execution-requests RUN_ID
forge reconcile-execution-request RUN_ID REQUEST_ID \
--reconciliation-id 0123456789abcdef0123456789abcdef
The HTTP body contains only {"reconciliation_id":"0123456789abcdef0123456789abcdef"}. The caller cannot assert success or absence of an effect. The server rechecks current project authority and matches retained evidence to the admitted and current source. Publication requires a terminal worker receipt or the matching immutable publication intent and receipt, including its branch, checked source and pull-request URL. Mutable task status or run metadata alone cannot establish publication.
If no matching proof exists, the request stays unknown and the server returns HTTP409. Reconciliation makes no provider call and never repeats the effect. Reusing the same reconciliation ID returns its retained result; a different ID for an already reconciled request is rejected. Cancellation also requires a terminal worker receipt proving that work drained.
A retained rejection before dispatch can settle a request as failed. Publication then permits an explicit bounded retry, up to three admitted attempts, provided no earlier publication intent remains unresolved. Any failure after dispatch retains uncertainty until its terminal receipt is established, even if the provider's error sounds like validation or authorization.
Understand automatic limits¶
Eligible rate-limit and transient pauses use their recorded delay and a budget of at most three automatic retries. Other pauses require an operator decision. Local concurrency is bounded globally and per project; work is selected across projects rather than filling both worker slots with one backlog.
The journal's hash chain detects a changed record sequence or payload. It is an integrity check within the operator's PostgreSQL ledger, not an external signature or protection against a database administrator replacing the entire history.
Recover a product conversation¶
Product-design turns have their own persisted ownership records. A turn's ownership includes its process owner, claim_epoch, lease expiry and last heartbeat. The active process renews its lease against PostgreSQL's clock. Only that owner and epoch can retain a response while the lease remains valid. A different API instance can read the conversation without interrupting it.
An expired turn stays processing until an editor explicitly recovers it. Inspect the current turn and use its recovery.expected_epoch:
forge assistant get REPOSITORY_ID CONVERSATION_ID
forge assistant recover REPOSITORY_ID CONVERSATION_ID TURN_ID \
--request-id 0123456789abcdef0123456789abcdef --expected-epoch 1
The server locks the conversation and turn, verifies expiry using database time, increments the epoch and records an immutable recovery receipt. The turn becomes needs_reconciliation. A late reply from the former owner cannot replace this result. Repeating the same recovery ID and body returns the original receipt; a changed body is rejected. No model retry occurs.
Processing turns created before ownership tracking have epoch zero and no owner. They require --legacy-confirmed-stopped as an explicit assertion that their original process has stopped. This assertion is recorded separately from an expiry proof. Do not use it while the original request may still be running.
Graceful factory shutdown stops new dialogue admissions, cancels and drains owned requests, then closes the data layer. An abrupt process loss leaves the durable claim for inspection and explicit recovery. An unknown provider outcome remains unknown even when local ownership has been fenced.