# ChatGPT Execution Continuity / Auto Resume Specification

Status: ready for implementation  
Date: 2026-08-20  
Repository: `alexcodeplace/chatgpt-orchestrator`  
Related authority: `SPEC.md`  
Related provenance contract: `docs/specs/worktree-conversation-ownership.md`

## 1. Purpose

Add first-class execution continuity to `chatgpt-orchestrator` so an orchestrated ChatGPT worker can keep working across ordinary ChatGPT turn/execution boundaries without requiring the user to manually type `continue` after each interrupted or prematurely ended turn.

The feature is named **Execution Continuity**. Its primary user-facing control is **Auto Resume**.

The core invariant is:

> A ChatGPT turn ending is not the same thing as an orchestrator worker finishing.

A logical worker remains active until it explicitly reaches an orchestrator terminal or blocking state. If its managed ChatGPT conversation becomes idle while the worker remains active and Auto Resume is permitted, the orchestrator may schedule another execution attempt in the same managed conversation.

This is not a quota, rate-limit, safety, or entitlement bypass. Every continuation is an ordinary new ChatGPT turn submitted through the same supported user session and is subject to the product's normal availability and restrictions.

## 2. Problem

Today a long engineering objective may span many ChatGPT execution turns:

```text
User assigns objective
      |
      v
ChatGPT turn 1
      |
      | turn stops / execution boundary
      v
conversation idle
      |
      | user manually types "continue"
      v
ChatGPT turn 2
      |
      | turn stops / execution boundary
      v
conversation idle
      |
      | user manually types "continue"
      v
...
```

The project already provides most of the transport required to automate this safely:

- durable runs/workers/assignments/events;
- managed ChatGPT conversation bindings;
- `conversation.send`;
- generating/idle observation;
- command idempotency and journaling;
- per-worker serialization;
- extension reconnect/recovery;
- `worker.complete`, `worker.fail`, `worker.followup`;
- bounded waits instead of correctness depending on one indefinitely open MCP call.

What is missing is the domain-level distinction between:

1. **the worker/job is complete**; and
2. **the current ChatGPT turn has ended but the worker/job is still active**.

Without this distinction, the browser becoming idle has no durable orchestration meaning and the human acts as a manual continuation scheduler.

## 3. Goals

Execution Continuity must:

1. resume an unfinished managed worker automatically after its ChatGPT conversation becomes idle;
2. preserve the same logical worker, assignment, managed conversation and work ownership across resumes;
3. keep continuation policy in the orchestrator backend, not the browser extension;
4. distinguish terminal completion from waiting for human input, waiting for dependencies, pausing and ordinary unfinished work;
5. record every execution attempt/resume durably and observably;
6. submit continuation prompts exactly once or fail closed when delivery is ambiguous;
7. recover correctly after MCP server, executor bridge, extension or browser restart;
8. provide clear operator controls for Auto Resume, Pause, Continue Now and Stop;
9. detect and pause likely runaway/stalled continuation loops based on lack of durable progress rather than arbitrary turn count alone;
10. preserve the existing frontend/executor abstraction so future Codex/API executors can reuse the same execution-continuity semantics.

## 4. Non-goals

Execution Continuity does not:

- bypass ChatGPT usage limits, rate limits, safety controls, confirmation requirements or product restrictions;
- guarantee that one ChatGPT inference/turn runs forever;
- infer hidden internal ChatGPT timeout causes;
- scrape or store arbitrary transcript bodies;
- make the browser extension authoritative for task completion;
- replace durable repository/progress/worktree state with conversation memory;
- turn the extension into a general browser-automation framework;
- automatically recover from ambiguous prompt submission by blindly resending;
- require the system to know *why* ChatGPT became idle before deciding that the worker remains unfinished.

## 5. Design principles

1. **Worker is the durable job.** A logical worker persists across many ChatGPT turns/execution attempts.
2. **Conversation is an execution host.** A managed ChatGPT conversation is bound to the worker but does not define worker completion.
3. **Turn end is an observation, not a terminal state.** `generating -> idle` means the current execution attempt ended.
4. **Backend owns continuation semantics.** The extension reports browser state and executes commands; it does not decide whether work is complete.
5. **Explicit completion wins.** `worker.complete`, `worker.fail`, cancellation, human-wait or dependency-wait states suppress automatic continuation.
6. **Do not detect timeout cause.** If the conversation is idle and the worker remains active, the job is unfinished regardless of whether the prior turn ended due to execution ceiling, model choice, network recovery or another benign reason.
7. **Durable state is authoritative.** A resumed turn must recover assignment/progress state through MCP and repository/worktree state before acting.
8. **Exactly-once prompt intent.** A continuation command has a stable idempotency key and must not be duplicated after reconnect/restart.
9. **No long-lived correctness dependency.** A `conversation.send` command should complete after prompt submission; generation completion is reported asynchronously as later conversation-state events.
10. **Pause is not cancel.** Stopping automatic continuation must not implicitly terminate the worker.
11. **Progress-aware loop protection.** Long tasks may legitimately need many turns. Stall detection is based primarily on lack of durable progress, not a small hard turn limit.
12. **Preserve executor portability.** Execution continuity belongs to the orchestration domain and may later be implemented by non-browser executors.

## 6. Identity hierarchy

Execution Continuity uses the identity model already established by the ownership/provenance specification:

```text
Run
 |
 +-- Logical Worker
      |
      +-- Assignment
      |
      +-- Managed Conversation (ChatGPT executor only)
      |
      +-- Execution Attempt 1
      +-- Execution Attempt 2
      +-- Execution Attempt 3
      |
      +-- Execution-session/worktree ownership provenance
```

These identities are different and must not be conflated.

### 6.1 Logical worker

The logical worker is the durable unit of assigned work. It may span an arbitrary number of execution attempts.

### 6.2 Managed conversation

The ChatGPT conversation is the persistent browser execution context for the worker. Auto Resume normally reuses the same conversation.

### 6.3 Execution attempt

An execution attempt is one orchestrator-observed period of ChatGPT work initiated by an initial bootstrap, automatic resume, manual resume, explicit follow-up or recovery action.

A new execution attempt does **not** imply a new worker, assignment, conversation or worktree owner.

## 7. Domain model additions

### 7.1 ContinuationPolicy

Add a durable policy attached to a worker, with optional run-level defaults.

```text
ContinuationPolicy
  mode: manual | auto
  idleGraceMs: integer
  activeKeepaliveMinMs: integer
  activeKeepaliveMaxMs: integer
  minContinuationSpacingMs: integer
  idleMayBypassMinSpacing: boolean
  requireProgressHeartbeat: boolean
  stallWarningAfterNoProgressAttempts: integer | null
  stallPauseAfterNoProgressAttempts: integer | null
  stallWarningAfterNoProgressMs: integer | null
  stallPauseAfterNoProgressMs: integer | null
```

Recommended defaults:

```text
mode = manual for existing/migrated workers unless explicitly enabled
idleGraceMs = 3000
activeKeepaliveMinMs = 20 minutes
activeKeepaliveMaxMs = 21 minutes
minContinuationSpacingMs = 15 minutes
idleMayBypassMinSpacing = true
requireProgressHeartbeat = false initially
stallWarningAfterNoProgressAttempts = 10
stallPauseAfterNoProgressAttempts = 20
stallWarningAfterNoProgressMs = 30 minutes
stallPauseAfterNoProgressMs = 60 minutes
```

Run creation may later support a default such as `continuation.mode=auto`, inherited by spawned workers unless overridden.

No policy field may attempt to alter or evade upstream usage/rate/safety restrictions.

### 7.2 ExecutionAttempt

Add a durable execution-attempt record.

```text
ExecutionAttempt
  executionId
  runId
  workerId
  conversationId?      // executor-specific binding when available
  sequence             // monotonically increasing per worker
  reason:
    initial
    auto_resume
    manual_resume
    followup
    recovery
  resumeOfExecutionId?
  state:
    scheduled
    submitted
    generating
    idle
    completed
    blocked
    failed
    cancelled
  scheduledAt
  submittedAt?
  generatingAt?
  idleAt?
  terminalAt?
  lastProgressCursor?
  continuationCommandId?
  outcome?
  errorCode?
  errorDetail?
```

The exact storage projection may be compacted later, but the event history must preserve equivalent provenance.

### 7.3 Worker execution disposition

The existing worker lifecycle should not be overloaded with every execution substate. Add an execution disposition or extend the worker state model so the orchestrator can distinguish at least:

```text
active/running
awaiting_execution
awaiting_dependency
awaiting_human
paused
completed
failed
cancelled
```

A compatibility implementation may keep existing `WorkerState` and add a separate `WorkerDisposition` field until a protocol-major migration is appropriate.

Normative semantics:

- `running`: active work is expected/in progress;
- `awaiting_execution`: worker is unfinished and eligible for another turn;
- `awaiting_dependency`: worker cannot progress until a declared dependency changes;
- `awaiting_human`: explicit human input/approval is required;
- `paused`: unfinished, but automatic execution is disabled by operator/policy;
- terminal states suppress all continuation.

## 8. MCP surface additions

The exact names may evolve, but the domain capabilities are required.

### 8.1 Worker disposition

Add:

- `worker.await_human`
- `worker.await_dependency`
- `worker.pause`
- `worker.resume`

`worker.resume` changes orchestration disposition/policy and may schedule execution if the managed conversation is idle.

### 8.2 Continuation policy

Add either worker/run-specific tools or a narrow policy API such as:

- `worker.continuation.get`
- `worker.continuation.set`
- optional `run.continuation.set_default`

Policy changes append durable events.

### 8.3 Continue now

Expose a command suitable for the plugin/operator UI:

- `worker.continue_now`

Semantics:

1. fail if worker is terminal;
2. fail or require explicit transition if awaiting human/dependency;
3. clear a user pause when explicitly requested;
4. if conversation is idle, enqueue a manual-resume execution attempt;
5. if conversation is generating, record intent to resume after current turn only when explicitly requested by UI semantics;
6. never duplicate a currently scheduled/submitted continuation.

### 8.4 Existing worker completion contract

Update worker bootstrap/instructions so before voluntarily ending work the agent should use one of the explicit outcomes:

```text
finished                -> worker.complete
irrecoverable failure   -> worker.fail
needs human             -> worker.await_human
waiting on dependency   -> worker.await_dependency
otherwise               -> remain active
```

The absence of `worker.complete` means the orchestrator must not infer completion from ChatGPT becoming idle.

## 9. Event model additions

Add durable ordered events, for example:

```text
execution.scheduled
execution.submitted
execution.generating
execution.idle
execution.resume_scheduled
execution.resumed
execution.paused
execution.blocked
execution.stalled
execution.completed
execution.failed

worker.awaiting_human
worker.awaiting_dependency
worker.resumed

continuation.policy_changed
continuation.warning
continuation.paused_for_stall
```

Representative trace:

```text
811 execution.submitted        reason=initial
812 execution.generating
813 worker.progress
814 execution.idle
815 execution.resume_scheduled reason=auto_resume
816 execution.submitted
817 execution.generating
818 worker.progress
819 worker.completed
820 execution.idle
```

After event 819, event 820 must **not** trigger another execution attempt.

## 10. Continuation state machine

### 10.1 Normal path

```text
                    +-------------+
                    | GENERATING  |
                    +------+------+
                           |
                           | observed idle
                           v
                   +---------------+
                   | TURN ENDED    |
                   | conversation  |
                   | idle          |
                   +-------+-------+
                           |
                    idle grace period
                           |
                           v
                +---------------------+
                | evaluate durable    |
                | worker disposition  |
                +----------+----------+
                           |
        +------------------+-------------------+
        |                  |                   |
        v                  v                   v
     terminal        blocked/paused        active + auto
        |                  |                   |
       STOP               STOP                 v
                                      schedule continuation
                                                 |
                                                 v
                                       conversation.send
                                                 |
                                                 v
                                           GENERATING
```

### 10.2 Wake classes and evaluation order

Execution Continuity uses three backend-owned wake classes:

1. **event wake** — a relevant durable event such as dependency completion, worker message, progress/commit report, blocker, approval or operator action;
2. **idle wake** — the managed conversation becomes idle while the logical worker remains non-terminal and runnable;
3. **active keepalive wake** — a jittered backend timer fires after approximately 20–21 minutes even if the managed conversation is still generating.

The active keepalive is intentional. Under the current working assumption, sending a fresh user steering message while ChatGPT is still generating may reset or extend the upstream per-turn execution window. This assumption is provisional and must remain explicitly documented until product behavior is independently verified. The scheduler therefore **queues a checkpoint/continuation intent when the 20–21 minute keepalive fires even if the conversation is still generating**; it does not discard the wake merely because generation is in progress.

The keepalive message is not a blind `continue`. It has two jobs: (1) require the worker to send a fresh durable status report to `/root`, and (2) require the worker to continue working to completion after reporting. This keeps the worker productive, keeps root observability current, and gives the receiving turn concrete work rather than an empty liveness ping.

Before delivery, evaluate in this order:

1. run cancelled/failed/completed -> cancel queued continuation;
2. worker completed/failed/cancelled -> cancel queued continuation;
3. worker awaiting human -> hold and surface `Needs you`;
4. worker awaiting unresolved dependency -> hold until dependency event makes it runnable;
5. worker paused -> hold;
6. continuation policy `manual` -> hold unless explicit operator/root action created the intent;
7. stall guard paused worker -> hold;
8. another continuation command is already pending/submitted -> coalesce with it;
9. enforce the anti-spam delivery floor;
10. otherwise submit exactly one fresh continuation command.

### 10.3 Keepalive checkpoint prompt contract

A timer/event keepalive should use a concise, versioned checkpoint instruction equivalent to:

```text
Orchestrator checkpoint.

Send the root conversation a durable update about this assignment now. Include:
- latest checkpoint commit(s), if any;
- what has been completed since the previous report;
- what you are working on now;
- what remains before the full assignment is complete;
- blockers, risks, dependency changes or cross-lane contract changes.

Then continue working on the same assignment to completion.
Do not stop merely because you sent the update.
If fully complete, call worker.complete with the terminal handoff.
If genuinely blocked, report the blocker through the orchestrator and use the appropriate blocking state.
```

The worker should normally emit the report using `worker.progress` plus `message.send` to `/root`, with commit SHA(s) included when available. The root records/consumes the report as durable orchestration state and may route relevant updates to other lanes.

The checkpoint message may include the worker display name, root display name, latest durable progress cursor, last known commit and outstanding acceptance-criteria summary so the worker does not have to infer why it was woken.

A successful checkpoint report is meaningful durable progress/observability, but it is not terminal completion by itself.

### 10.4 Root review and corrective steering

Every material lane checkpoint creates a root review opportunity. `/root` must evaluate the report against the **entire run objective, lane assignment, dependencies, acceptance criteria, cross-lane contracts, already-landed work and current convergence plan**, not merely acknowledge that the lane is alive.

Root may respond with one of these outcomes:

```text
continue_as_planned     // work is aligned; keep going
correct_direction       // implementation is drifting from assignment/architecture
change_priority         // another subgoal must be handled first
provide_dependency      // new commit/contract/result is now available
request_evidence        // root needs tests/diff/proof before accepting direction
pause                   // continuing would create harmful/conflicting work
terminal_reconcile      // lane claims done; root requests final correction/review before acceptance
```

A normal `continue_as_planned` response is subject to the ordinary 15-minute non-idle continuation spacing rule. **Material corrective steering is not a keepalive and must not be delayed by that floor** when delaying it would allow known wrong, conflicting or unsafe work to continue. Corrective steering still requires exactly-once delivery, deduplication/coalescing and durable provenance. Repeated identical corrections must not spam a lane.

Examples of deviations that justify immediate corrective steering include:

- editing outside the lane's owned scope;
- contradicting an authoritative shared contract;
- duplicating work already assigned to another lane;
- implementing against stale dependency state;
- violating repository/testing/landing constraints;
- passing local tests while breaking the run-level integration plan;
- declaring completion without required acceptance evidence.

The checkpoint/control loop therefore gives root an ongoing architecture and plan-review role while implementation is still in progress, instead of discovering divergence only at final convergence.

### 10.5 Anti-spam floor and deferred delivery

Continuation wakes are **durable intents**, not disposable notifications.

Default delivery floor: no two ordinary non-idle checkpoint/continuation messages should be submitted less than 15 minutes apart for the same worker. Material root corrective steering is a separate control action and may bypass this floor when delay would knowingly allow divergence to continue. If an event wake or keepalive fires before the floor expires, retain/coalesce the wake and set `notBefore = lastContinuationSubmittedAt + 15 minutes`. Do not discard it.

Idle is a special case. If the conversation becomes idle while the worker remains active/runnable, the scheduler may bypass the 15-minute floor after the short idle grace because an ended execution turn needs immediate continuation. The implementation must still deduplicate multiple idle events and must never have more than one fresh continuation command in flight for a worker.

When several wake reasons coalesce, preserve all useful provenance in the durable attempt/event record (for example: `event:worker.progress`, `event:dependency_completed`, `active_keepalive`) while delivering only one continuation message.

### 10.6 Active keepalive timer

For every active/runnable worker in Auto mode, maintain a recoverable jittered keepalive deadline uniformly/randomly within the configured 20–21 minute window. A successful continuation submission resets the keepalive deadline. Relevant progress/commit events may also cause root evaluation immediately, but they do not permit lane continuation spam inside the 15-minute floor unless the lane is idle.

The keepalive belongs to durable backend scheduling, not to a browser `setTimeout` and not to an agent prompt. Backend restart must reconstruct pending keepalive deadlines/intents from durable state.

### 10.7 Idle grace

A short configurable idle grace window prevents transient UI state changes from creating unnecessary turns. Default recommendation: 3 seconds.

The grace timer belongs to backend scheduling semantics or a recoverable local scheduler, not to a fragile one-off browser timeout.

If worker state becomes terminal/blocked during the grace period, continuation is cancelled.

## 11. Continuation prompt contract

Do not send a bare `continue` by default.

Use a versioned, concise resume instruction that makes MCP/durable state authoritative:

```text
Continue the current orchestrated worker assignment.

Worker: <worker-id>

Recover authoritative state using ChatGPT Orchestrator MCP before acting.
Do not redo completed work. Inspect durable repository/worktree/progress state as needed.
Continue until the assignment's acceptance criteria are satisfied.

Before ending:
- call worker.complete if finished;
- call worker.fail if irrecoverably failed;
- call worker.await_human only if human input is genuinely required;
- call worker.await_dependency only if an external/dependency condition prevents progress;
- otherwise leave the worker active so execution continuity can resume it.
```

The prompt may include the execution-attempt sequence/reason but should not duplicate the full assignment body.

Full assignment, dependencies, acceptance criteria and messages remain in MCP/control-plane state.

## 12. Executor protocol behavior

### 12.0 Layered continuity / dead-man fallback

Primary continuation scheduling belongs to the durable orchestrator backend. The LibreWolf extension remains the managed-conversation transport/state sensor.

A later/final hardening slice may add a **plugin-side dead-man fallback**. Its purpose is only catastrophic loss of normal wake paths — for example, all relevant ChatGPT root/worker conversations have timed out/errored and therefore no conversation is alive to mutually wake the others while backend/operator recovery is delayed. The plugin fallback must not become a second independent orchestration authority. It may only trigger bounded recovery/rebind/health actions according to durable backend policy and must deduplicate against normal scheduler intents.

This defense-in-depth layer is intentionally deferred until the backend timer/event-wake architecture is proven.

### 12.1 Browser extension is not the scheduler

The extension must never decide:

```text
conversation idle -> therefore send another prompt
```

Instead it reports state:

```text
conversation.state: generating
conversation.state: idle
```

The backend evaluates worker state and may issue a new `conversation.send` command.

### 12.2 Asynchronous lifecycle observation

Keepalive delivery while a conversation is already generating requires a separate safe steering capability. The executor must support an ordinary-UI mid-turn steering submission when ChatGPT exposes that capability, without using private backend APIs. The scheduler marks these commands as checkpoint/steering deliveries so the executor does not wait for `idle` first. If current ChatGPT UI does not expose a safe steering submission seam, the executor must fail closed and preserve the durable intent for retry/recovery rather than silently converting it into a lost ping.

The steering path must retain the same exactly-once journal/deduplication guarantees as ordinary follow-up submission. It must never click `Retry` and must not interrupt/stop generation merely to create room for the checkpoint message.

A `conversation.send` command should mean:

1. wait until submission is safe/idempotent;
2. submit the prompt exactly once;
3. record local journal phase;
4. report command success after submission/observable acceptance;
5. independently observe and publish later `generating`/`idle` state transitions.

It should **not** hold the executor command open for the full duration of a potentially long ChatGPT generation.

This preserves the existing architectural principle that no correctness property depends on a single long-lived MCP/WebSocket/browser request.

### 12.3 State observation

The content/background layer should maintain bounded MutationObserver-based observation and/or periodic reconciliation sufficient to publish meaningful transitions.

Required transitions:

```text
ready -> generating
generating -> idle
any -> error
any -> closed
```

State reporting must be idempotent/coalesced so DOM churn does not flood the control plane.

### 12.4 Exactly-once continuation submission

Each resume attempt receives:

- unique `executionId`;
- unique `commandId`;
- stable idempotency key derived from the execution attempt, e.g. `conversation.resume:<executionId>`.

After extension restart:

- journal `completed` -> return stored result;
- journal `submitted` -> inspect/reconcile, do not blindly resend;
- journal `submission-started` with ambiguous delivery -> fail closed as `AMBIGUOUS_SUBMISSION` unless deterministic proof of non-delivery exists.

## 13. Recovery semantics

### 13.1 MCP/backend restart

On startup:

1. load workers/policies/execution attempts;
2. restore pending scheduler intents;
3. wait for/reconcile executor bindings;
4. inspect active managed conversations if needed;
5. if worker is active + auto + conversation idle + no continuation in flight, schedule a recovery/auto-resume attempt;
6. do not duplicate already submitted attempts.

### 13.2 Extension restart

The extension already persists managed bindings and command journal. It must republish verified bindings and current observed state after reconnect.

The backend then re-evaluates continuation eligibility.

### 13.3 Browser restart / missing tab

If the browser restarts and a managed tab cannot be recovered:

- do not adopt an unrelated ChatGPT tab by guess;
- mark binding unavailable/closed;
- preserve logical worker and execution history;
- surface a recoverable operator state;
- later policy may explicitly recreate/rebind a conversation, but this is separate from automatic same-conversation resume.

### 13.4 Root worker

Execution Continuity must support `/root` as well as child workers when `/root` is bound to a managed conversation.

A coordinating root that becomes idle while the run remains active may be resumed so it can continue `events.wait`, answer worker questions, integrate results and close the run without a manual `continue`.

## 14. Human/dependency blocking semantics

### 14.1 Awaiting human

`worker.await_human` is explicit and durable.

Required fields should include:

```text
reason
question/request
requestedAt
optional choices/context references
```

While awaiting human:

- Auto Resume is suppressed;
- UI displays `Needs you` prominently;
- `Continue now` should require resolving/overriding the human wait rather than silently ignoring it.

### 14.2 Awaiting dependency

`worker.await_dependency` records the dependency condition. It may be released automatically by a relevant orchestrator event or explicitly by root/operator action.

This prevents useless continuation turns while another worker/CI/deploy condition is genuinely pending.

## 15. Pause, Continue and Stop semantics

These must remain distinct throughout API and UI.

### 15.1 Pause after current turn

- current ChatGPT generation may finish;
- do not schedule another execution attempt;
- logical worker remains unfinished;
- worktree/ownership remains intact;
- UI shows `Paused` or `Paused after turn`.

### 15.2 Continue now

- if idle and runnable, submit one manual-resume execution attempt immediately;
- if generating, either queue one post-turn resume intent or disable the button until idle; the chosen UX must be deterministic and visible;
- does not replace the assignment.

### 15.3 Stop worker

- cancels/interrupts the logical worker according to existing lifecycle semantics;
- no future automatic continuation is permitted;
- this is destructive compared with Pause.

### 15.4 Stop current ChatGPT generation

If ever exposed, this is yet another distinct browser action and must not be conflated with `Stop worker` or `Pause Auto Resume`.

It is not required for the initial feature.

## 16. Stall/runaway protection

Auto Resume must not create an invisible infinite loop when an agent repeatedly ends turns without making progress.

### 15.5 Continuous lane-to-root communication

Workers must communicate meaningful progress to the durable control plane throughout execution, not only at terminal handoff. At minimum, implementation workers should report checkpoint commits and milestone progress through `worker.progress` and/or `message.send` to `/root`.

A recommended checkpoint report contains:

```text
commit: <sha or none>
progress: <what changed>
completed: <completed subgoals>
remaining: <remaining subgoals>
blockers: <none or explicit blockers>
contracts: <cross-lane contract changes/requests>
```

The orchestrator records these reports durably. A new commit or material progress event is a wake signal for `/root`: the logical root should be resumed promptly so it can update the run-level view, **review the lane against the larger plan and cross-lane architecture**, route information to dependent lanes and decide whether corrective steering or additional work is necessary.

Root may send a coalesced lane checkpoint such as `commit <sha> observed; send root an updated task/commit/progress report, then continue working to completion` to active lanes. The same 15-minute minimum-spacing rule applies to non-idle lane continuation delivery: if a lane was continued less than 15 minutes ago, queue the wake for the earliest legal time instead of spamming it. If the lane is idle, immediate continuation is allowed.

Git/commit observation is an additional progress signal, **not authoritative completion**. Only durable orchestration state such as `worker.complete`, `worker.fail`, explicit wait state or operator/root transition decides lifecycle state.

### 16.1 Durable progress signals

Progress may be demonstrated by one or more of:

- `worker.progress` event;
- assignment/disposition mutation;
- worker message/review/blocker event;
- artifact/provenance update known to orchestrator;
- worktree/landing integration event when the ownership feature is available;
- explicit checkpoint API added later.

The initial implementation may use orchestrator-native events only and evolve to consume Git/Overdeck progress signals.

### 16.2 No-progress counter

For each worker track:

```text
consecutiveExecutionAttemptsWithoutProgress
lastProgressAt
lastProgressCursor
```

A successful progress event resets the consecutive count.

### 16.3 Warning and pause

Default behavior should be policy-driven:

```text
warning threshold -> surface warning, continue if policy allows
pause threshold   -> set paused-for-stall, suppress further resumes
```

Do not impose a low total-turn maximum. Fifty productive turns may be legitimate.

### 16.4 Operator recovery

UI should offer:

- Continue anyway;
- Pause;
- Open conversation;
- Stop worker.

`Continue anyway` resets/acknowledges the stall pause but preserves history.

## 17. Plugin UI/UX

The plugin should expose Execution Continuity as an operator capability, not as a low-level browser scripting feature.

### 17.1 Terminology

Primary user-facing terms:

- **Execution Continuity** — feature family;
- **Auto Resume** — automatic continuation control;
- **Working** — ChatGPT currently generating;
- **Resuming** — another execution attempt is scheduled/submitting;
- **Needs you** — awaiting human;
- **Waiting** — awaiting dependency;
- **Paused** — unfinished but auto execution disabled;
- **Complete** — worker terminal success.

Avoid presenting `tabId`, command IDs or raw UUIDs in primary UI.

### 17.2 Toolbar popup

Add a primary browser-action popup separate from the existing advanced options page.

Recommended structure:

```text
+-----------------------------------------+
| ChatGPT Orchestrator             * Live |
+-----------------------------------------+
| EXECUTION CONTINUITY                    |
| Auto Resume                    [ ON  ]  |
| Keep unfinished workers running across  |
| ChatGPT turn boundaries.                |
|                                         |
| Active workers                     3    |
| Working                            2    |
| Resuming                           1    |
| Needs you                          0    |
+-----------------------------------------+
| Backend migration                       |
| /root/backend                           |
| * Working                    18m 24s    |
| Attempt 3                               |
|                                         |
| Plugin migration                        |
| /root/plugin                            |
| ~ Resuming                              |
| Attempt 6 · 5 auto resumes              |
|                              [Pause]    |
+-----------------------------------------+
| Current conversation                    |
| /root/plugin                            |
| Auto Resume                      ON     |
|                                         |
| [Pause]             [Continue now]      |
+-----------------------------------------+
| Open dashboard              Settings >  |
+-----------------------------------------+
```

The popup should answer immediately:

1. Is the orchestrator connected?
2. Is Auto Resume on?
3. Which workers are currently working/resuming/blocked?
4. Does anything need the user?
5. What is the current tab's worker and continuation state?

### 17.3 Per-conversation overlay

For managed ChatGPT tabs, add a small extension-owned overlay using an isolated Shadow DOM host so orchestrator controls/styles do not depend on ChatGPT component internals.

Collapsed examples:

```text
* Orchestrated · Auto Resume
* Working · Attempt 4
~ Continuing · Attempt 5
! Needs you
|| Paused
✓ Complete
```

Clicking opens a compact drawer with:

```text
worker name
worker state
attempt number
number of automatic resumes
last durable progress time
Auto Resume state
Pause / Continue now / Stop worker
recent execution-continuity events
```

The overlay must remain restrained and must not cover the composer or important ChatGPT controls.

Provide an option to hide the overlay globally while retaining toolbar/dashboard controls.

### 17.4 Dashboard / options split

Current options UI is configuration-oriented. Preserve endpoint/token/concurrency/managed-worker settings under **Settings / Advanced**.

Add an operator dashboard/panel for:

- run-level continuity control;
- worker table;
- per-worker state;
- execution attempts/resume count;
- last progress;
- `Needs you` items;
- pause/resume actions;
- stall warnings;
- diagnostic drill-down.

Do not overload the advanced settings page with runtime operations.

### 17.5 Run-level controls

Recommended run controls:

```text
Auto Resume unfinished workers       ON/OFF
Pause all after current turns
Resume all unfinished
Stop run
```

A worker-specific override should be visually distinct from the run default.

### 17.6 Accessibility

- keyboard-operable popup, overlay drawer and controls;
- visible focus states;
- ARIA live regions only for meaningful state changes, not noisy DOM churn;
- do not communicate `Working`, `Paused`, `Needs you`, etc. by color alone;
- destructive `Stop worker/run` visually and semantically distinct from non-destructive Pause.

## 18. Plugin/backend data flow

Normal automatic resume:

```text
ChatGPT DOM
   |
   | generating -> idle
   v
content adapter
   |
   v
extension background
   |
   | conversation.state(idle)
   v
executor bridge
   |
   v
orchestrator core
   |
   | durable worker still active?
   | continuation policy auto?
   | not blocked/paused/stalled?
   v
schedule ExecutionAttempt(auto_resume)
   |
   v
enqueue conversation.send
   |
   v
executor bridge -> extension
   |
   v
wait for safe idle + exactly-once submit
   |
   +--> command.result(submitted)
   |
   +--> later conversation.state(generating)
   |
   +--> later conversation.state(idle)
```

The browser never decides whether another turn is warranted.

## 19. Extension local storage

Extension-local durable state should remain minimal:

```text
executor settings
workerId -> managed tab/conversation binding
command journal
last observed conversation state
optional overlay preference/local UI state
```

Do not store authoritative continuation policy only in extension storage. Policy belongs to backend persistence so browser/extension restart does not change job semantics.

## 20. Backend persistence

Persistence must survive process restart and include equivalent state for:

- continuation policy;
- worker execution disposition;
- execution attempts;
- pending/scheduled continuation intent;
- last progress cursor/time;
- consecutive no-progress attempt count;
- stall warning/pause state;
- execution events.

Mutations that change execution state and append corresponding events must be atomic under the repository abstraction.

## 21. Concurrency and idempotency

### 21.1 One active continuation submission per worker

Per worker, only one of these may be in flight at once:

```text
initial create/bootstrap submission
follow-up submission
auto-resume submission
manual-resume submission
```

The extension's current per-worker serial queue is the correct local executor mechanism. Backend must also prevent duplicate logical scheduling.

### 21.2 Multiple workers

Different workers may generate/continue concurrently subject to existing configurable extension/executor concurrency limits.

Continuation scheduling must not serialize unrelated workers globally.

### 21.3 Race: worker completes while idle resume is scheduled

Before dispatch and again before submission where feasible, terminal worker state must invalidate/cancel the pending resume intent.

If a prompt was already unambiguously submitted immediately before completion arrived, preserve the execution event history and suppress any subsequent continuation.

## 22. Error behavior

### 22.1 Host UI changed

`HOST_UI_CHANGED` pauses browser execution for the affected worker and surfaces an actionable error. Do not approximate-click another element.

### 22.2 Ambiguous submission

`AMBIGUOUS_SUBMISSION` suppresses automatic resend and surfaces recovery state. Duplicate user prompts are worse than a temporary pause.

### 22.3 ChatGPT/product error state

If the adapter detects an error state:

- publish the browser error;
- do not spin automatic continuation against the same unchanged error page;
- pause/retry only under an explicit recoverable policy;
- upstream usage/rate/safety/confirmation restrictions, when recognizable, are boundaries to respect rather than targets for circumvention.

### 22.3.1 Message delivery timeout recovery

Treat the ChatGPT UI state whose visible message is equivalent to:

```text
Message delivery timed out. Please try again.
```

as a dedicated recoverable execution-boundary condition, e.g. `MESSAGE_DELIVERY_TIMEOUT`.

Normative behavior:

1. **Never click the ChatGPT `Retry` button for this condition.** The prior delivery/generation state is ambiguous, and replaying the prior request can duplicate work or repeat side effects.
2. Record the prior execution attempt as ended with delivery-timeout outcome while leaving the logical worker non-terminal.
3. Wait until the normal composer is safely usable.
4. Submit a **fresh user turn containing `continue`** through the normal exactly-once `conversation.send` path. This is a new continuation attempt, not a retry of the previous browser action.
5. Continue using the same worker, assignment, managed conversation and durable state. The resumed agent must reconcile MCP/repository/worktree state before repeating any action whose completion is uncertain.
6. If another delivery timeout occurs, the same rule applies subject to the normal Auto Resume, pause, stall and product-boundary policies. Never fall back to clicking `Retry`.

The adapter may identify the condition from stable semantic UI text/role structure, but must fail closed if the UI cannot be distinguished reliably. The plugin must not invoke the retry control merely because a button labeled `Retry` is present.

### 22.4 Executor unavailable

Continuation remains durably scheduled/pending while executor is temporarily unavailable, subject to command deadlines/reconciliation policy. Reconnect must not duplicate the attempt.

## 23. Privacy and security

Execution Continuity does not require storing chat transcript content.

Permitted persisted browser identity/state includes:

- managed conversation URL/UUID;
- worker/execution IDs;
- coarse lifecycle state;
- timestamps;
- orchestrator-generated resume prompt/version or hash if needed for auditing;
- command/result metadata.

Do not persist:

- cookies;
- ChatGPT auth/session tokens;
- arbitrary conversation bodies;
- unrelated tab content;
- browser history outside managed tabs;
- credentials present in prompts or pages.

Extension permissions remain limited to those needed for managed `chatgpt.com` tabs, local storage and loopback executor communication.

## 24. Relationship to worktree/conversation ownership

Execution Continuity must integrate cleanly with `docs/specs/worktree-conversation-ownership.md`.

Expected provenance:

```text
Conversation C17
    |
    +-- Worker /root/backend
          |
          +-- Execution E1 initial
          +-- Execution E2 auto_resume
          +-- Execution E3 auto_resume
          +-- Execution E4 manual_resume
          |
          +-- Worktree impl/backend
```

Automatic resume does not transfer or recreate worktree ownership.

Execution-session provenance should distinguish attempts/sessions where appropriate while retaining the same worker/conversation ownership chain.

A later Overdeck/AWP view should be able to answer:

- which worker owns the worktree;
- which conversation hosts it;
- which execution attempt is active;
- how many automatic resumes occurred;
- whether it is working, paused, blocked or complete.

## 25. Migration and rollout

Existing workers/runs created before this feature should default conservatively to manual continuation unless a run/user explicitly enables Auto Resume.

No attempt should be made to reconstruct historical execution-attempt boundaries from old chat transcripts.

Existing conversation bindings and worker states remain valid.

Rollout order:

1. protocol/persistence support;
2. execution disposition and attempts;
3. asynchronous conversation state reporting;
4. manual `Continue now` backend path;
5. Auto Resume scheduler behind opt-in feature flag/policy;
6. toolbar popup/dashboard controls;
7. managed-tab overlay;
8. stall protection;
9. root-worker auto-resume;
10. default-policy evaluation after qualification.

## 26. Required tests

### 26.1 Core unit tests

- idle + active + auto -> one resume scheduled;
- idle + active + manual -> no resume;
- idle + completed -> no resume;
- idle + failed/cancelled -> no resume;
- idle + awaiting human -> no resume;
- idle + awaiting dependency -> no resume;
- idle + paused -> no resume;
- duplicate idle events -> one resume;
- completion arriving during grace -> pending resume cancelled;
- completion after submission -> no subsequent resume;
- progress resets no-progress counter;
- no-progress thresholds warn/pause correctly;
- policy changes append events and survive restart.

### 26.2 Persistence/restart tests

Kill/restart at:

1. idle event before resume scheduling;
2. resume scheduled before executor enqueue;
3. executor enqueue before ACK;
4. submission-started;
5. submitted before command result;
6. command result before generating observation;
7. generating before idle observation;
8. idle during grace;
9. stall warning/pause mutation.

Every case must converge without duplicate prompt submissions or lost worker state.

### 26.3 Extension tests

- state observer publishes generating/idle transitions without duplicate floods;
- command result does not wait for entire generation;
- per-worker queue serializes create/followup/resume commands;
- unrelated workers remain concurrent;
- restart after `submitted` reconciles without resend;
- `Message delivery timed out` is classified as delivery-timeout recovery;
- the ChatGPT `Retry` control is never clicked for delivery timeout;
- a fresh exactly-once user message `continue` is submitted instead;
- repeated delivery timeouts still use fresh `continue` attempts subject to stall/pause policy;
- managed tab removal reports closed;
- overlay appears only in managed tabs;
- overlay does not intercept unrelated page controls;
- popup reflects backend/extension state correctly.

### 26.4 Isolated browser E2E

Run only on isolated `debian1/2/3` browser profiles/displays as required by the repository plan.

Primary acceptance scenario:

```text
1. Spawn a worker with an assignment deliberately requiring multiple turns.
2. Enable Auto Resume.
3. User sends no additional ChatGPT messages.
4. Attempt 1 ends and conversation becomes idle.
5. Attempt 2 is submitted automatically in the same conversation.
6. Attempt 2 ends; Attempt 3 starts automatically.
7. Worker eventually calls worker.complete.
8. Conversation may become idle.
9. No Attempt 4 is scheduled.
```

Human-block scenario:

```text
1. Worker calls worker.await_human.
2. Turn ends.
3. No auto-resume occurs.
4. UI shows Needs you.
5. User resolves/restarts worker explicitly.
```

Pause scenario:

```text
1. Worker is generating with Auto Resume enabled.
2. User selects Pause after current turn.
3. Generation ends.
4. Worker remains unfinished and paused.
5. No automatic turn starts.
6. User selects Continue now.
7. Same managed conversation resumes exactly once.
```

Restart scenario:

```text
1. Worker completes one attempt and is eligible to resume.
2. Restart extension/backend at selected boundary.
3. Reconcile managed binding and durable attempt state.
4. Resume exactly once or surface ambiguous state; never duplicate submission.
```

Root scenario:

```text
1. /root coordinates two children.
2. Root's ChatGPT turn ends while run remains active.
3. Root auto-resumes and continues event coordination.
4. Children complete.
5. Root integrates and calls worker.complete.
6. No further root continuation occurs.
```

## 27. Agent output contract and responsibility boundary

Execution Continuity must keep the agent-facing skill deliberately small. The agent does its assigned work normally; the skill only emits enough structured end-of-response state for the orchestrator to decide whether another execution is necessary.

### 27.1 Responsibility split

```text
Agent skill                         end-of-response continuation-state only
Worker assignment                   objective + acceptance criteria + scope
Repository/project instructions     project-specific execution policy and gates
Orchestrator/backend                durable worker state, scheduling, continuation decisions
Browser extension                   ChatGPT UI observation/submission and executor protocol
```

The agent skill must not contain browser Retry handling, instructions to send `continue`, execution-boundary detection, auto-resume scheduling, MCP lifecycle mechanics, repository recovery methodology, worktree policy, or browser state. The agent does not own or need to understand those mechanisms.

### 27.2 Canonical reusable skill

The canonical skill is `skills/durable-continuation-output/SKILL.md`; its frontmatter name is `durable-continuation-output`. It is an output contract only.

Every response ends with exactly one block:

```text
<continuation-state>
status: working | complete | blocked
summary: <brief material change this response>
current: <precise current assignment state>
next: <exact next unfinished action, or none>
</continuation-state>
```

`working` means the overall assignment is unfinished and another execution can continue it. `complete` means all requested work and acceptance gates are finished. `blocked` means further progress genuinely requires external input or an unavailable dependency.

The skill does not tell the agent how another execution is created.

### 27.3 Orchestrator interpretation

The orchestrator may parse the continuation-state block as one signal, but durable worker state remains authoritative. In particular:

- `working` makes the worker eligible for continuation according to backend policy;
- `complete` is only accepted when durable lifecycle/acceptance state also permits completion;
- `blocked` is surfaced as a blocker and suppresses automatic continuation until resolved;
- malformed or missing output must fail safe and may fall back to durable worker state plus execution-boundary reconciliation.

The browser/plugin decides whether and when to submit another turn. The agent never instructs the plugin to click Retry and never owns generation of the next continuation message.

### 27.4 Resume and delivery-timeout behavior belongs outside the skill

Automatic/manual resume prompts, delivery-timeout handling, Retry suppression, and fresh continuation-message generation are executor/orchestrator policy defined elsewhere in this specification. They must not be copied into the reusable agent skill.

This separation allows the executor policy to change without changing what every worker agent must know.

### 27.5 Packaging and installation

Release automation should package the canonical skill directory as an uploadable Agent Skills archive. The archive contains no secrets, local state, project-specific policy, conversation content, or browser instructions.

Where ChatGPT supports Personal/Workspace Skills, operators install this output-contract skill once. Correctness must not depend on a browser-only skill-selection seam; the orchestrator can still require/parse the same continuation-state output through its worker bootstrap/execution contract.

### 27.6 Acceptance

The responsibility boundary is accepted when:

- the reusable skill contains output instructions only;
- an agent can perform an arbitrary assigned task without knowing about Retry, `continue`, browser state, or auto-resume scheduling;
- a `working` output gives the orchestrator a precise next action;
- browser/executor continuation logic functions independently of the skill body;
- changing executor continuation policy does not require changing the agent skill.

## 28. Completion definition

Execution Continuity is complete when:

- a non-terminal managed worker can span multiple ChatGPT turns without manual `continue` messages;
- terminal/blocked/paused workers do not auto-resume;
- the same worker/conversation/work ownership survives resumes;
- execution attempts and resume reasons are durably auditable;
- continuation prompts are exactly-once or fail closed on ambiguity;
- backend/extension/browser restart converges correctly;
- long command lifetime is not required to observe generation completion;
- plugin UI clearly exposes Auto Resume, Working, Resuming, Needs you, Paused and Complete states;
- Pause, Continue Now and Stop have distinct semantics;
- no-progress stall protection prevents silent runaway loops without imposing an arbitrary low cap on productive turns;
- root and child workers can both use the mechanism;
- isolated Firefox/Chromium E2E demonstrates a multi-turn job reaching `worker.complete` with zero manual continuation prompts;
- existing usage/rate/safety/product boundaries remain respected.
