76 lines
2.7 KiB
Markdown
76 lines
2.7 KiB
Markdown
# R4.2 P1 — Durable Online Agent Execution
|
|
|
|
Status: candidate implementation. This document does not imply protected-main promotion or Production deployment.
|
|
|
|
## State model
|
|
|
|
The generic worker uses two local durable layers:
|
|
|
|
1. `tasks/<task_id>.json`: atomic fast-state cache for compatibility and quick restart.
|
|
2. `checkpoints.sqlite3`: append-only attempt/phase journal with `synchronous=FULL`.
|
|
|
|
Checkpoint identity is bound to:
|
|
|
|
- task_id
|
|
- attempt
|
|
- execution_digest
|
|
- job_id
|
|
- repository
|
|
- base_oid
|
|
- expected_branch_oid
|
|
- target_branch
|
|
- generation
|
|
|
|
A checkpoint from another repository/branch/generation is never reused.
|
|
|
|
Phases are monotonic within an attempt:
|
|
|
|
`claimed → workspace_prepared → verification_passed → source_capture_done|commit_done → result_pending → result_submitted`
|
|
|
|
`reconciliation_required` is an explicit recovery phase.
|
|
|
|
## Attempt-aware result idempotency
|
|
|
|
Result submission idempotency keys include the official Task attempt and the execution digest. The same
|
|
attempt reuses the same key after a timeout/restart; a later official attempt cannot collide with an
|
|
earlier result.
|
|
|
|
Before submitting a result the worker durably writes `result_pending`, including the result hash and
|
|
idempotency key. After a successful or exact-idempotency-reconciled API response it writes
|
|
`result_submitted`.
|
|
|
|
A 409 is accepted only if the Task API already contains the exact same result body and the Task is
|
|
VERIFYING/SUCCEEDED. A conflicting result remains a hard failure.
|
|
|
|
## Resume rules
|
|
|
|
- `source_capture_done` and `result_pending` may be reused across later official attempts only when the
|
|
execution/scope binding is identical. This avoids repeating read-only source capture.
|
|
- A deterministic task that crashed before governed commit replays from a new clean detached worktree.
|
|
This is safe because there is no external side effect yet.
|
|
- `commit_done` is never recommitted. Recovery requires exact Job receipt OID convergence plus exactly
|
|
one ACTIVE WriterLease whose `current_head_oid` equals the governed commit.
|
|
- delayed Git visibility remains `RECONCILIATION_REQUIRED`, preserving an explicit recovery entry.
|
|
|
|
## Crash cleanup
|
|
|
|
On worker startup, stale `task-*` workspaces under the configured workspace root are removed before
|
|
polling begins. The path boundary is verified before deletion.
|
|
|
|
## Contracts
|
|
|
|
P1 gates include:
|
|
|
|
- CHECKPOINT_DURABLE_WRITE
|
|
- RESUME_FROM_CHECKPOINT
|
|
- RETRY_IDEMPOTENT_NO_DUPLICATE_SIDE_EFFECT
|
|
- CRASH_RECOVERY_CONVERGENCE
|
|
- WORKER_RESTART_RESUME
|
|
- CHECKPOINT_SCOPE_ISOLATION
|
|
- RESULT_SUBMISSION_REPLAY_SAFE
|
|
- WORKSPACE_CLEANUP_RECOVERY
|
|
- LEASE_RENEWAL_RECOVERY
|
|
|
|
WriterLease and governed Job authority remain in the existing Bridge/GitOps durable stores; the worker
|
|
checkpoint DB is not a competing authority for Git state.
|