# I1 GOLIVE canonical-path reconciliation — 2026-08-23

Status: in progress. No GOLIVE criterion has been re-checked yet; owner-gated account/GitHub/Factory actions remain untouched.

## Baseline before this slice

- dogfood debian3 healthy at 13/13 migrations, pending=0, drift=[];
- FactoryRun/AgentRun/ChangeSet/Review/evidence/finding/Workspace rows all zero;
- Subrouter account inventory empty;
- no GitHub publication token/env authority;
- live runner pin `ghcr.io/platform-modules/awp-agent-runner@sha256:afed7f0708643f8bc5fa365ef1f7569675eab93fdf607dce312eec26177366e5`;
- retry reconciliation committed/pushed at `d382943`.

## Reconciliation findings and repairs

1. **Dead canonical browser asset:** approved-live and legacy Project-list shells referenced `/golive-client.js`, but no source/build artifact exists. Approved-live already used canonical `/client.js`; Project-list creation shell is being switched to `/client.js`. New `tests/ui/live-shell-assets.test.ts` prevents a nonexistent legacy asset from returning to the live shell.
2. **AC-29 durable self-dogfood provenance gap:** trusted GitHub publication metadata carried ChangeSet/idempotency/candidate fidelity but not originating FactoryRun identity. `TrustedPublishRequest`, GitHub publication client/state/readback and commit message now carry `factoryRunId` and emit `AWP-FactoryRun: <id>`. Publication fidelity rejects replay with mismatched FactoryRun provenance.
3. **Stale GOLIVE review semantics:** AC-19 previously described owner self-approval. Canonical runtime assigns an independent reviewer AgentRun; owner only executes protected Merge after independent approval + required checks. Binding spec is being reconciled accordingly.
4. **Stale trusted-merge identity semantics:** old AC-21/AC-29 expected local fixture committer `AWP Control Plane <control-plane@awp.local>`. Canonical GitHub boundary instead proves control-plane authority through repository-scoped credential isolation, durable provider merge reference/result revision, remote-tip readback, and AC-18 agent push denial.
5. **Stale workspace cleanup semantics:** AC-14 now binds to the real two-phase lifecycle: coder/reviewer Git-tree checkpoints are durably collected, compute can be released, and exact-digest PVC cleanup plus durable `cleanedAt` occurs only after trusted merge.
6. **Stale namespace/state assumptions:** AC-12/AC-18 default to `awp-workspaces`; AC-27 starts from current published states (`reviewing`/`verifying`/`ready-to-merge`) rather than obsolete `candidate-ready`. AC-12 additionally requires immutable runner image digest and disabled ServiceAccount token automount.
7. **Canonical account selection:** AC-22 now requires `AWP_AGENT_ACCOUNT_ID` and passes the owner-provisioned Subrouter account on Plan approval instead of silently relying on fixture defaults.

## Additional canonical U1 repair

A deeper owner-path audit found that canonical approved-live Project pages rendered authoritative state but did not expose first-use mutation controls for ProjectVision, Goals, Plans or Task dependencies. The deleted historical `golive-client.ts` had also contained the generic JSON form transport while live shells continued to reference its missing browser output.

Repaired without changing the information-first Overview authority:

- canonical `/client.js` now owns generic `data-live-form` POST transport and error handling;
- `/golive-client.js` is removed from both approved-live and Project-list shells/server assets;
- explicit `/projects` remains the Project list even when exactly one Project exists; root `/` may still redirect to that single Project;
- Vision, Goals and Plans tabs expose compact owner mutation panels; Overview remains read-oriented;
- Plan authoring exposes dependency mutation against canonical Task ids;
- New Plan routes to the canonical Plans authoring anchor;
- empty Projects still expose first-use mutation controls on Vision/Goals/Plans tabs;
- `tests/ui/approved-live-authoring.test.ts` and `tests/ui/live-shell-assets.test.ts` bind these contracts.

## Verification

- first provenance typecheck exposed a misplaced producer lookup; repaired by deriving producer coder AgentRun/FactoryRun inside `publishForReview()`;
- focused GitHub provider/HTTP + authoritative verification/merge gate + live-shell/authoring suites: PASS on debian2;
- exact full post-format `pnpm check`: PASS on debian2;
- 45 test files passed / 2 skipped; 161 tests passed / 5 skipped;
- architecture: 6/6;
- dependency-cruiser: zero violations across 111 modules / 194 dependencies;
- typecheck, lint, build and Prettier all pass.

## Live zero-run baseline before deployment

- debian3 health re-observed at 13/13 migrations, pending=0, drift=[];
- FactoryRun count 0; Workspace count 0;
- no owner FactoryRun was initiated.

## Next

- append a repair-status reconciliation to the historical drift audit;
- commit/push this canonical-path repair;
- inspect automation/remote head and deploy exact settled production head to debian3;
- re-prove 13/13, zero execution/account state, absent GitHub publication authority;
- continue autonomous restart/merge-dispatch durability audit before owner-triggered dogfood.

## Live deployment evidence — exact source `9814074`

Deployment target: debian3 dogfood via `infra/dogfood/deploy-debian3.sh`; exit 0.

Postdeploy evidence:

- `awp-dogfood-control-plane`, `awp-dogfood-web`, `awp-dogfood-postgres`: active;
- `/health`: PostgreSQL, migrations applied=13, expected=13, pending=0, drift=[];
- FactoryRuns=0, AgentRuns=0, ChangeSets=0, Reviews=0, VerificationEvidence=0, ReviewFindings=0, Workspaces=0;
- Subrouter account inventory: `accounts: []`;
- GitHub publication token file absent and `AWP_GITHUB_PUBLICATION_TOKEN_FILE` env absent;
- runner remains `ghcr.io/platform-modules/awp-agent-runner@sha256:afed7f0708643f8bc5fa365ef1f7569675eab93fdf607dce312eec26177366e5`;
- awp-system Subrouter/model-gateway/Fabro deployments each 1/1 available on their immutable registry digests;
- live `/projects` contains Create Project and `/client.js`, with no legacy `golive-client.js`;
- live self Project Vision tab exposes Save ProjectVision; Goals exposes Create Goal; Plans exposes Plan authoring/Create Plan and correctly reports no draft Plan before account/run setup;
- no owner login, GitHub credential provisioning or FactoryRun occurred.

Canonical acceptance/GOLIVE reconciliation is therefore deployed. Remaining autonomous work is restart/reconciliation correctness before asking for the explicit owner-gated dogfood actions.

## Restart / dispatch reconciliation repair — 2026-08-23

Audit after canonical acceptance deployment found two crash windows that could strand durable work:

1. Plan approval committed its approved Plan, `dispatched` root Tasks and FactoryRun before invoking the external dispatcher. A replay could create a second FactoryRun, and a control-plane restart had no generic startup reconciliation for the already-authorized `dispatched` Tasks.
2. Trusted merge committed the ChangeSet as `merged` and marked newly dependency-legal Tasks `dispatched` before invoking their external dispatch. A crash in that gap caused merged replay to run only Workspace cleanup, leaving downstream work stranded.

Repaired canonical behavior:

- FactoryRun now durably owns the explicit selected `accountId` and optional model used for the PlanRevision;
- migration `0013_normal_grandmaster.sql` adds those fields and a unique index on `factory_runs.plan_revision_id`, enforcing one FactoryRun per PlanRevision under concurrent approval;
- `approvePlan()` is replay-safe: an approved/completed PlanRevision must already own exactly one FactoryRun and replay may not rebind account/model provenance;
- `I1LifecycleService.reconcileDispatchedWork()` reconstructs external dispatch requests from durable FactoryRun/Task state and persisted selection provenance;
- control-plane startup reconciles every Project's durably `dispatched` Tasks through the idempotent DBOS dispatcher before serving requests;
- trusted merge and already-merged replay reconcile all `dispatched` Tasks for the originating FactoryRun before terminal Workspace cleanup;
- Workspace dispatch remains idempotent by `(FactoryRun, Task, coder role)` and resumes the same initial Attempt/Workspace after provisioning failure rather than creating a second AgentRun.

Verification on debian2:

- Plan approval replay regression proves one FactoryRun, same FactoryRun identity for all root dispatches, persisted account/model provenance, and rejection of account rebinding;
- persistence regression proves account/model round-trip and database rejection of a second FactoryRun for the same PlanRevision;
- merge crash-window regression injects downstream Workspace provisioning failure after merge persistence, proves ChangeSet remains `merged` with one waiting coder AgentRun/created Attempt, then replays merge and recovers that same AgentRun/Attempt without a second trusted merge;
- focused recovery suite: PASS;
- exact full `pnpm check`: PASS;
- 45 test files passed / 2 skipped; 163 tests passed / 5 skipped;
- architecture 6/6; dependency-cruiser zero violations across 111 modules / 194 dependencies; typecheck, lint, build and Prettier all pass.

Next: commit/push this recovery slice, deploy migration 14 and exact source head to debian3, re-prove zero-run/account/GitHub-authority invariants, then continue remaining autonomous recovery audit before owner-triggered dogfood.

### Live recovery deployment evidence — exact source `0d135f4`

Deployment to debian3 completed with exit 0. Postdeploy proof:

- control-plane/web/PostgreSQL user services active;
- health: migrations applied=14, expected=14, pending=0, drift=[];
- FactoryRuns=0, AgentRuns=0, ChangeSets=0, Reviews=0, VerificationEvidence=0, ReviewFindings=0, Workspaces=0;
- `factory_runs` now includes `account_id` and `model`;
- unique index `factory_runs_plan_revision_unique` exists on `plan_revision_id`;
- Subrouter account inventory remains `accounts: []`;
- GitHub publication token file and env remain absent;
- agent runner digest remains `ghcr.io/platform-modules/awp-agent-runner@sha256:afed7f0708643f8bc5fa365ef1f7569675eab93fdf607dce312eec26177366e5`;
- startup reconciliation created no execution state when no durable dispatched work existed.

The Plan-approval and post-merge dispatch crash windows are therefore repaired and live. Continue audit of publication/reviewer restart windows before owner-triggered dogfood.

## Pending independent-review restart recovery — 2026-08-23

Audit of coder completion/reviewer provisioning found one remaining restart hole after trusted publication: if the Review, reviewer AgentRun, Attempt and Workspace were durably assigned but reviewer Workspace provisioning failed or the control plane restarted before launch completed, coder callback replay observed the existing Review and returned without reprovisioning it.

Repair:

- `publishForReview()` now treats an existing Review as a reconciliation target and calls the idempotent independent-review provisioning path instead of returning immediately;
- `WorkspaceExecutionDispatcher.reconcilePendingReviews()` scans non-terminal published ChangeSets and resumes their exact already-assigned reviewer AgentRun/Attempt;
- control-plane startup best-effort invokes pending-review reconciliation for every Project after dispatched-Task recovery; startup logs provider failures rather than refusing to start, keeping callback endpoints available for the runner's own retry loop;
- native ACP retry remains role-safe because reviewer/coder role, Review identity, candidate digest and materialization are resolved from durable AgentRun/Review/ChangeSet state, not from transient retry input.

Verification on debian2:

- regression injects two reviewer Workspace provisioning failures after trusted publication;
- first coder completion leaves one durable Review with one waiting reviewer AgentRun/created Attempt;
- coder completion replay retries that exact reviewer without republishing or duplicating Review/AgentRun;
- startup reconciliation then activates the same reviewer Attempt with unchanged account/model provenance;
- trusted publication call count stays 1 and Review count stays 1 throughout;
- exact full `pnpm check`: PASS;
- 45 test files passed / 2 skipped; 164 tests passed / 5 skipped;
- architecture 6/6; dependency-cruiser zero violations across 111 modules / 194 dependencies; typecheck, lint, build and Prettier all pass.

Next: commit/push and redeploy this source-only recovery repair on the live 14/14 schema, then continue the remaining publication/merge restart audit.

## Stable provider idempotency and post-provider-merge recovery — 2026-08-23

A deeper restart audit distinguished two classes of idempotency:

- trusted GitHub publication/merge already used deterministic ChangeSet-scoped keys (`changeset:<id>:publish|merge`) and provider reconciliation;
- execution-provider calls still inherited transient HTTP request idempotency keys, so startup/callback replay with a new request context could address a different native Workspace/ACP operation even though the durable Attempt/Workspace identity was unchanged.

Repairs:

- Workspace provisioning key is now `workspace:<workspaceId>:provision`;
- retry compute replacement key is now `workspace:<workspaceId>:retry:<attemptId>:replace-compute`;
- producer Workspace destroy key is now `workspace:<workspaceId>:producer-destroy`;
- reviewer Workspace provisioning key is now `review:<reviewId>:workspace:<workspaceId>:provision`;
- ACP start key is now `attempt:<attemptId>:agent:<phase>`;
- repository required-check observation key is now `changeset:<changeSetId>:required-checks`;
- operation/correlation IDs remain request-scoped for tracing, while provider idempotency is bound only to durable logical mutation identity.

The same audit found a trusted-merge crash window after GitHub completed the merge but before AWP durably recorded it. On replay, AWP previously inspected mutable `main` first; because successful merge necessarily advanced `main`, replay could reject target drift before asking GitHub whether the exact deterministic merge had already completed.

Trusted merge now:

1. validates immutable ChangeSet/request fidelity;
2. reconciles the exact deterministic provider merge first;
3. if already merged, returns that exact immutable provider result without consulting the now-advanced branch head;
4. only when reconciliation says `not-merged` does it inspect the current target and enforce exact pre-mutation target identity before invoking merge;
5. still reconciles ambiguous retryable provider failures after a mutation attempt.

Verification on debian2:

- Workspace/ACP replay regression changes the caller operation/correlation/idempotency context between retries while requiring one Workspace/AgentRun/Attempt and one stable Workspace key plus one stable ACP Attempt key;
- trusted merge regression proves an exact already-completed merge is recovered with zero new merge calls and zero mutable target observations;
- existing target-drift and candidate-fidelity failures remain fail-closed when no prior exact merge exists;
- focused stable-key/merge-recovery suite: 14/14 PASS;
- exact full `pnpm check`: PASS;
- 45 test files passed / 2 skipped; 165 tests passed / 5 skipped;
- architecture 6/6; dependency-cruiser zero violations across 111 modules / 194 dependencies; typecheck, lint, build and Prettier all pass.

Next: commit/push and source-only deploy on the live 14/14 schema, then audit remaining owner-lifecycle harness/binding gaps before requesting explicit owner-gated dogfood actions.

### Live stable-replay deployment evidence — exact source `158991c`

Deployment to debian3 completed with exit 0. Postdeploy proof:

- control-plane/web/PostgreSQL user services active;
- health: migrations applied=14, expected=14, pending=0, drift=[];
- FactoryRuns=0, AgentRuns=0, ChangeSets=0, Reviews=0, VerificationEvidence=0, ReviewFindings=0, Workspaces=0;
- Subrouter account inventory remains `accounts: []`;
- GitHub publication token file and env remain absent;
- no startup reconciliation invented work in the zero-run dogfood state.

## Binding harness false-positive cleanup — 2026-08-23

A sweep of `tests/golive` found two isolated PostgreSQL/bootstrap tests whose names could be mistaken for production GOLIVE proof and one stale owner Playwright journey. Repairs preserve useful lower-level coverage while preventing fixture-era results from satisfying production acceptance by implication:

- `04-owner-lifecycle.spec.ts` now starts from explicit `/projects`, requires `AWP_PROJECT_REMOTE_URL` and `AWP_AGENT_ACCOUNT_ID` (optional `AWP_AGENT_MODEL`), uses canonical Vision/Goals/Plans tabs, exercises Task dependency/cycle rejection, selects the real Subrouter account, invokes `Approve & start FactoryRun`, asserts one FactoryRun per PlanRevision with persisted account/model provenance, and returns through explicit `/projects`;
- binding owner task names no longer use fixture/synthetic terminology;
- `02-control-plane-postgres.test.ts` is explicitly a non-GOLIVE PostgreSQL/Hono transport smoke and no longer performs the execution-disabled Plan approval fallback;
- `28-self-project.test.ts` is explicitly a non-GOLIVE bootstrap persistence smoke; AC-28 remains satisfied only by the live dogfood `psql` assertion defined in `GOLIVE.md`;
- a repository sweep now finds no `GOLIVE AC-`, obsolete `Approve Plan`, old `alexcodeplace/awp`, per-Task FactoryRun SQL, `synthetic`, or `fixture` markers under `tests/golive`.

The owner lifecycle spec was linted and Prettier-checked on debian2 without executing Playwright, because execution would start the owner-gated FactoryRun. Next: run the full static/repository gate with these harness changes, commit/push, then review remaining binding specs for execution-safe static correctness before the explicit owner-gated live journey.
