# I1 Workspace Lifecycle / Durable WIP Gates — 2026-08-23

Status: complete and live-verified.

This slice does not initiate FactoryRun/AgentRun, account login, or GitHub credential provisioning. Builds/tests run only on debian1/debian2/debian3.

## Gates

- [x] **G1 — Content checkpoint identity:** runner derives the Workspace checkpoint from actual `/workspace/repo` contents via an isolated Git index + `git write-tree`. Kubernetes PVC UID/resourceVersion is no longer treated as WIP content identity.
- [x] **G2 — Durable checkpoint state:** Workspace persists `checkpointDigest`, `checkpointedAt`, `checkpointSource`, `checkpointCollectedAt`, and `cleanedAt` through migration `0012_dear_surge.sql`; PostgreSQL/PGlite round-trip normalizes timestamps to canonical ISO strings.
- [x] **G3 — Retry preserves WIP:** failed Attempt remains immutable history; replacement Attempt reuses the same Workspace/PVC and provider/account/model provenance. Content checkpoint persistence + PVC attestation occur before `replaceCompute`, and replay reuses the existing retry Attempt instead of creating another one.
- [x] **G4 — Pod replacement recovery:** Kubernetes provider test proves retained PVC/checkpoint identity across Pod replacement. Native ACP recovery regression proves an existing coder repository is reattached without `reset`, `clean`, `clone`, or reseed; persisted runner state already uses ACP `session.load`/`session.resume` when a session identity is available.
- [x] **G5 — Non-terminal protection:** active/retryable/publication-failed Workspaces are never passed to destructive checkpoint cleanup. Publication failure retains the Workspace; provider cleanup also requires `collected=true` plus exact live PVC checkpoint digest.
- [x] **G6 — Terminal cleanup:** trusted merged ChangeSet discovers producer and assigned reviewer Workspaces, releases disposable compute, requires each durable checkpoint to be collected, deletes each PVC only through exact-digest provider verification, and then records `cleanedAt`. Merge replay converges cleanup idempotently.
- [x] **G7 — Drift refusal:** missing PVC checkpoint attestation or digest mismatch refuses destructive cleanup. A missing already-cleaned PVC is treated idempotently, allowing crash recovery between provider deletion and durable `cleanedAt` persistence.
- [x] **G8 — Canonical U3 truth:** Project hierarchy now includes authoritative Workspace records; live FactoryRun projection reports persisted checkpoint identity/time/collection/cleanup truth. Non-terminal content-attested WIP is shown safe but non-cleanable; terminal collected state can expose cleanup eligibility; cleaned state reports completion.
- [x] **G9 — Remote source gate:** exact source tree passes full `pnpm check` on debian2.
- [x] **G10 — Zero-run live deploy:** source commit `6e5e4da` triggered agent-runner workflow `32618189832`, which completed successfully and published/smoke-tested immutable runner digest `sha256:afed7f0708643f8bc5fa365ef1f7569675eab93fdf607dce312eec26177366e5`; automated desired-state commit `10b5b98` was then the exact deployment candidate. That exact head passed the full debian2 repository gate and was deployed to debian3. Live health is 13/13 migrations with pending=0 and drift=[]; FactoryRun/AgentRun/ChangeSet/Review/evidence/finding/Workspace counts remain zero; accounts remain empty; GitHub publication token/env authority remains absent; Project required-check policy remains `["CI"]`; `AWP_WORKSPACE_IMAGE` is the new immutable runner digest; Subrouter/model-gateway/Fabro are 1/1 Ready on their pinned registry digests; `awp-workspaces` contains no Pods/PVCs. No owner Factory/login/credential action was initiated.

## Implementation evidence

### Content checkpoint and retry ordering

- `infra/agent-runner/runner.mjs` includes `workspaceCheckpointDigest` + `workspaceCheckpointedAt` in coder completion, independent-review completion, and retryable failure callbacks. The digest is the actual Git candidate tree from `/workspace/repo`.
- `WorkspaceExecutionDispatcher.failAttempt()` validates the callback checkpoint, persists it to Workspace, attests it to the PVC, then replaces compute on the same Workspace. `tests/application/execution-retry.test.ts` explicitly asserts provider call order `attest -> replace` and replay creates no duplicate retry Attempt.
- `tests/application/kubernetes-acp-recovery.test.ts` proves an existing coder repo is reattached without destructive initialization.

### Provider attestation / cleanup

- Kubernetes transport now has scoped annotation support.
- WorkspaceProvider PVC annotations hold the control-plane-approved content digest/time/source.
- `checkpoint()` refuses unattested PVCs instead of fabricating a digest from Kubernetes metadata.
- `cleanupCheckpoint()` is idempotent for an already-absent PVC but otherwise requires `collected=true` and exact attested content digest equality.
- `tests/integration/workspace/workspace-kubernetes.test.ts` proves retained digest across Pod replacement, compute-vs-PVC cleanup separation, missing-attestation refusal, `collected=true` enforcement, and digest-drift refusal.

### Durable terminal lifecycle

- Workspace schema/migration: `0012_dear_surge.sql`.
- Successful coder collection and reviewer submission mark the exact checkpoint collected and provider-attested.
- Trusted merge invokes terminal cleanup for producer and reviewer Workspaces only after the ChangeSet is durably `merged`.
- `tests/integration/verification-merge-gate.test.ts` proves publication-failed state preserves WIP and successful merge performs exactly two destructive checkpoint cleanups (producer + reviewer), with both Workspace rows durably marked cleaned; merge replay does not perform another destructive cleanup.
- `tests/integration/persistence.test.ts` proves checkpoint/collection/cleanup state round-trip.

### Canonical UI truth

- `ProjectHierarchy.workspaces` carries authoritative Workspace state to the live web projection.
- `tests/ui/approved-live-factory-wip.test.ts` proves content-attested non-terminal WIP is safe/non-cleanable, collected terminal WIP exposes cleanup eligibility, and cleaned Workspace reports terminal cleanup truth.

## Exact debian2 gate

Scratch tree: `/home/user/runs/awp-i1-workspace-lifecycle`.

Final exact `pnpm check` result:

- typecheck: PASS across 16/17 package projects;
- lint: PASS;
- tests: **43 files passed / 2 skipped; 159 tests passed / 5 intentionally skipped**;
- build: PASS;
- architecture: **6/6 PASS**;
- dependency-cruiser: **zero violations, 111 modules / 194 dependencies**;
- Prettier: all matched files use correct style.

Focused lifecycle gate before the full check: **24/24 tests across five files**; the two new U3/recovery regressions also pass.

## Live deployment evidence

- source commit: `6e5e4dad95247a05aa949ba0cd7cbff4eac2c767`;
- runner publisher workflow: GitHub Actions `32618189832`, conclusion `success`;
- automated digest-lock commit / exact deployed runtime head: `10b5b985bd0f5c0aa19d9aec2b6c8a3cf75dae77`;
- runner image: `ghcr.io/platform-modules/awp-agent-runner@sha256:afed7f0708643f8bc5fa365ef1f7569675eab93fdf607dce312eec26177366e5`;
- exact-head debian2 gate: 43 test files passed / 2 skipped; 159 tests passed / 5 skipped; architecture 6/6; dependency-cruiser zero violations (111 modules / 194 dependencies); Prettier clean;
- debian3 services: control-plane/web/Postgres active;
- health: `applied=13`, `expected=13`, `pending=0`, `drift=[]`;
- live execution state: FactoryRun/AgentRun/ChangeSet/Review/evidence/finding/Workspace counts all zero;
- account inventory: empty; GitHub publication token and env binding absent;
- persisted dogfood Project policy: `required_checks=["CI"]`;
- live workspace runner desired image: exact new immutable digest above;
- awp-system: Subrouter `28b809b6…`, model gateway `36337978…`, Fabro `94e65f3…`, all 1/1 Ready;
- `awp-workspaces`: no Pods/PVCs after zero-run deploy.

G1-G10 are complete.
