# AWP I1 drift audit — 2026-08-22

## Status

**I1 is not complete. The prior 30/30 GOLIVE result is invalid as a product-completion claim.**

This audit was triggered after deploying the landed I1 branch and observing that the production live web path rendered a crude alternate UI instead of the owner-approved U1–U6 mockups. The audit treats that UI split as evidence that convergence may have confused implemented seams/fixtures with wired product behavior.

No FactoryRun was started during this audit. The persistent dogfood database still contains zero FactoryRuns.

## Deployment correction made before audit

The persistent dogfood instance is reachable at:

```text
http://100.101.104.41:4173
```

The live web server was changed to render the approved U1 Project composition for the self Project instead of the alternate `live.ts` form renderer. The current live page contains the approved U1 shell/sidebar and the Current Goals / Attention / Blockers, Active Plans / FactoryRuns / Recently Completed, and Queue / Next Up hierarchy.

This is only a visual-path correction. The audit below shows that the approved renderers are not yet fully live-wired.

## Executive finding

The main convergence defect is systematic:

```text
contract/adapter/mockup exists
        ↓
focused test or disposable acceptance harness passes
        ↓
GOLIVE box marked green

BUT

persistent product runtime does not compose that seam
```

That pattern exists across UI, Factory/Agent/Account providers, DBOS, trusted VCS, verification evidence, self-dogfood evidence, and some workspace lifecycle behavior.

## Critical findings

### P0-01 — Live UI and approved UI were two different products

- `apps/web/src/server.ts` production mode used `renderLiveProject()` from `live.ts`.
- `live.ts` contains the crude inline-styled CRUD/timeline UI that was originally deployed.
- The owner-approved U1–U6 implementation lives under `render-project.ts`, `render-factory.ts`, `render-review.ts`, `u1.css`, and `lifecycle.css`.
- The U1–U6 render tests call `renderRequest()` directly and therefore never exercised the production live server path.
- The GOLIVE Playwright suite exercised the separate `live.ts` path.

Result: both suites could be green while production visually violated the binding mockups.

### P0-02 — Approved U1–U6 renderers still contain prototype wiring

The approved rendering code still includes hard-coded prototype identities/data such as:

```text
/projects/project-i1
/factory-runs/FR-001
/changesets/CS-001
Jordan Diaz
platform-modules/awp
C1 deterministic fixture
```

The persistent live server currently has no live routes for:

```text
/projects/:id/queue
/factory-runs/:id
/changesets/:id
```

Those return 404. Project tab query parameters also do not select a distinct live surface in the new adapter. Primary U1 actions such as `New Plan` are prototype `data-command` acknowledgements rather than the live mutation flow that existed in the discarded `live.ts` form UI.

So the currently deployed UI has the correct U1 visual composition, but it is not yet a fully usable implementation of the approved U1–U6 journey.

### P0-03 — The real Factory/Fabro provider is not wired into the product

`apps/control-plane/package.json` has no dependency on `@awp/provider-factory-fabro`, and the control-plane runtime has no `FabroFactoryProvider` reference.

The provider package itself wraps an injected `FabroNativeClient`; its tests use `FakeFabroClient`.

Current Plan approval directly creates AWP FactoryRun rows and calls `WorkspaceExecutionDispatcher`. Fabro is bypassed entirely.

### P0-04 — The real Agent/ACP provider is not wired into the product

`apps/control-plane` has no dependency on `@awp/provider-agent-acp`, and no `AcpAgentProvider` is composed at runtime.

Instead, `server.ts` defines a `golive-native` Kubernetes profile using `busybox:1.36.1`. Its shell command:

- sleeps;
- optionally emits an injected failure;
- manufactures a unified diff with `printf`;
- submits a synthetic `write_patch` tool-call record to the control plane.

This is an execution fixture, not an ACP coding agent. The dogfood deployment still configures this busybox profile.

The provider package tests use `FakeAcpClient`.

### P0-05 — Account/Subrouter routing is not wired; Attempt provenance is label injection

The live dispatcher receives account/model strings from environment variables:

```text
AWP_AGENT_ACCOUNT_ID
AWP_AGENT_MODEL
```

and writes them directly into Attempt provenance. No `SubrouterAccountProvider` is called, no account is selected/resolved through Subrouter, and no provider session is created from that routing decision.

The previous GOLIVE runs used values such as `zync2` and `gpt-5.3-codex-spark`, but those values were runtime labels on the synthetic workspace path, not evidence that Subrouter actually routed the Attempt or that ACP used that account/model.

The Subrouter tests use inline fake `SubrouterNativeClient` implementations.

### P0-06 — DBOS durable workflow ownership is absent from the running I1 path

There are no references to `DbosWorkflowProvider` or `DurableWorkflowProvider` in the running applications or `tests/golive/**`.

The DBOS integration test uses `PersistentFakeDbos`, not the real DBOS runtime.

The restart acceptance tests instead rely on PostgreSQL state plus retrying HTTP callbacks from the workspace pod. That proves useful reconciliation behavior, but it does not satisfy the binding I0/I1 rule that DBOS owns durable workflow mechanics.

### P0-07 — FactoryRun identity is being used as a per-Task execution wrapper

Current `approvePlan()` behavior:

- chooses one first eligible Task;
- creates one FactoryRun with `taskId` set to that Task;
- dispatches one AgentRun;
- after trusted merge, creates a **new FactoryRun** for the next Task.

This conflicts with the I1 FactoryRun authority and approved U2/U3 UI, where one FactoryRun is the orchestration instance for the Plan work graph and shows Task topology plus its AgentRuns.

The current implementation also serializes eligible Tasks instead of representing the approved multi-AgentRun/topology semantics.

### P0-08 — Agent workspace does not contain the Project repository or real source work

The Kubernetes workspace profile launches busybox in `/workspace`, but the control plane never clones/checks out the Project repository into that workspace and does not invoke the Forge/VCS or Agent provider to create real coding context.

The current pod manufactures a patch independently of repository contents. A non-empty diff that happens to pass `git apply --check` in a separate trusted checkout is therefore not proof that an agent edited the Project repository in its durable workspace.

### P0-09 — VerificationEvidence / repository-required checks are not authoritative runtime state

I1 requires:

```text
ChangeSet
 -> VerificationEvidence + repository-required checks
 -> independent Review
 -> trusted Merge
```

The shared read-model code has `I1VerificationEvidence`, findings, and merge-gate conditions, but the PostgreSQL schema has no durable VerificationEvidence/Finding family and the live merge command does not evaluate them.

Current `requestMerge()` requires only an approved Review and `ready-to-merge` ChangeSet before calling the merge adapter.

Thus the approved U4/U5 MergeGate UI describes safety conditions the product does not actually enforce.

### P0-10 — ChangeSet candidate/base identity is not repository identity

Current completion code sets:

- `ChangeSet.baseIdentity = String(factoryRun.projectId)` rather than an immutable repository base revision;
- `candidateDigest = sha256(diff)`;
- `treeDigest = patchDigest`, rather than the candidate tree digest;
- candidate manifest change kind to `add` even when the diff modifies an existing file.

That does not satisfy exact-candidate / expected-base semantics.

### P0-11 — Trusted merge is a single global local checkout, not Project-scoped trusted VCS

The running server accepts one global `AWP_TRUSTED_REPOSITORY_PATH` and constructs one `LocalGitTrustedMergeAdapter`.

Consequences:

- Project.repositoryUrl does not select the trusted merge target;
- a second Project would still use the globally configured AWP checkout;
- GitHub VCS provider adapters are bypassed;
- the adapter does not verify expected repository/base revision/current target head/candidate tree fidelity/required verification evidence before mutation;
- it applies the stored patch to whatever HEAD the local checkout currently has and pushes `origin HEAD`.

This is both a correctness and safety defect for real dogfood use.

### P0-12 — AC-29 was a false positive

AC-29 requires a real AWP-authored change to be merged by AWP and remain present in AWP's own Git history.

The recorded passing run deliberately used a disposable AWP-history checkout plus disposable bare remote, then deleted them. The handoff explicitly states that no real AWP remote branch was mutated.

The recorded commit:

```text
ad9b34a8f0030e06770ed28106052622b2a24abe
```

is not an object in the actual AWP repository.

Therefore AC-29 did not satisfy its own wording and the 30/30 completion claim is invalid.

## High findings

### P1-01 — GOLIVE acceptance and UI fidelity were separate universes

The U1–U6 test named `tests/e2e/ui/lifecycle-render.test.ts` is a deterministic server-render unit/integration test. It does not start the live server or browser against the production route.

The GOLIVE browser specs used the alternate live renderer. There was no acceptance test asserting the production live response matches the approved U1–U6 hierarchy/visual contract.

### P1-02 — Current approved UI is visually correct but functionally incomplete

After switching production to U1 rendering:

- `/` redirects to the one live self Project and renders U1 correctly;
- `/projects/:id/queue` returns 404;
- `/factory-runs/:id` returns 404;
- `/changesets/:id` returns 404;
- hard-coded sidebar links target `project-i1`;
- Factory/Review links target `FR-001` / `CS-001`;
- New Plan / Connections are prototype command acknowledgements rather than real controls;
- Project tabs do not render their distinct live state.

### P1-03 — Workspace retention is incomplete and leaks PVCs

`KubernetesWorkspaceProvider.destroy()` deliberately deletes Pod/Service/NetworkPolicy/ServiceAccount but retains the PVC until an explicit digest/collection handshake.

The I1 execution completion path calls `destroy()` but never calls `cleanupCheckpoint()`. A persistent dogfood run can therefore leave retained PVCs indefinitely.

### P1-04 — WIP checkpoint digest is not a content digest

The current checkpoint digest hashes:

```text
workspaceId + PVC uid + PVC resourceVersion
```

It does not hash or otherwise attest to workspace content. It is a Kubernetes object identity/version fingerprint, not evidence that the actual accepted WIP bytes were checkpointed unchanged.

### P1-05 — Gateway is a stub and is not deployed

`apps/gateway/src/index.ts` only exports a boundary constant and health contract. The dogfood UI directly proxies to the control plane.

The control plane also hard-codes every mutation to `principal:owner` with no caller authentication/Principal resolution. Port 8787 currently listens on all interfaces because agent callbacks require reachability.

The 2026-08-21 governance amendment moves most non-pod security proof post-dogfood, so this does not by itself block the amended I1 proof, but it is real architectural drift and makes the persistent instance unsuitable beyond a trusted internal environment.

### P1-06 — Provider proof requirements were not actually met

The amendment reduced the requirement to one real integration test per provider; it did not replace real-provider integration with fake-client tests.

Current state:

```text
Kubernetes/Workspace   real seam exercised
DBOS                   fake runtime test only; not product-wired
Factory/Fabro          FakeFabroClient tests; not product-wired
Agent/ACP              FakeAcpClient tests; not product-wired
Account/Subrouter      fake client tests; not product-wired
Forge/GitHub           FakeGitHubClient tests; not product-wired
```

### P1-07 — Deployment updater could leave stale code running

The initial dogfood deployment script used `systemctl --user enable --now`. Updating files under the runtime directory did not restart an already-running web process, which is why the first corrected UI deploy still served old code until a manual restart.

The deployment branch has been patched to restart PostgreSQL/control-plane/web explicitly on update; this fix still needs its normal gate/landing path.

## Strong / salvageable implementation areas

The audit is not a conclusion that everything is throwaway. These areas appear materially useful and aligned:

- PostgreSQL/Drizzle authoritative state and migrations;
- transaction pattern writing domain state + business event + audit + outbox together;
- Project/ProjectVision/Goal/Plan/Task persistence;
- hard Task dependency DAG validation and dependency-safe readiness;
- opaque canonical IDs and immutable Attempt retry records;
- Kubernetes WorkspaceProvider resource construction;
- pod containment: non-root, no privilege escalation, RuntimeDefault seccomp, capability drop, per-workspace ServiceAccount, token automount disabled, NetworkPolicy, CPU/memory limits;
- persistent PVC retention across compute replacement;
- signed Attempt completion/failure callbacks and useful idempotency handling;
- owner-approved U1–U6 deterministic renderers and CSS as a recoverable visual implementation base;
- provider interfaces/adapters as reusable seams, even though most still need real native clients and runtime composition.

## GOLIVE impact

The historical `30 / 30` state must not be used as the answer to “is I1 complete?” after this audit.

At minimum the following claims are invalidated by direct evidence and must be re-proven against the canonical live product path after repair:

```text
AC-04..AC-10   approved live UI does not currently expose the verified CRUD/approval journey
AC-14          full workspace cleanup is not performed; retained PVC lifecycle is unfinished
AC-15          synthetic shell patch, not real ACP agent source work
AC-16          provider/account/model labels are not actual routed provider provenance
AC-19          approved live Review route/action not wired
AC-23          approved live UI cannot currently render all six required lifecycle transitions
AC-24          live U4/U5 diff/tool timeline route not wired
AC-25          live U3 failure/retry surface not wired
AC-29          disposable self-change is absent from actual AWP Git history
```

Additional criteria that rely on the synthetic agent/provider path must be rerun after real provider composition because their previous passes do not establish that the repaired system works.

## Owner constraint — Subrouter credential separation

When the real Subrouter/Factory path is wired, do **not** copy, import, mount, or otherwise reuse account authentication from the workstation Systray/Overdeck environment. The owner requires two independent authentication domains:

```text
workstation Subrouter auth/token   independent existing workstation authority
K3s AWP Subrouter auth/token       new token created by a separate owner login
```

AWP/K3s must initially expose no imported user accounts. Provider wiring may be completed up to the explicit authentication boundary, then the owner will log in separately and add the K3s accounts/token. No automated credential migration from Systray/Overdeck is authorized.

## Repair order

Do not start I2. Restore I1 first.

1. **Canonical live UI integration**
   - remove prototype IDs/data from renderers;
   - bind U1 to live project/read-model data;
   - implement live Queue, FactoryRun U2/U3, ChangeSet/Review U4/U5/U6 routes;
   - wire all primary actions to canonical commands;
   - add browser acceptance that starts the real production server and asserts U1–U6 parity/behavior.
2. **Correct FactoryRun orchestration identity**
   - one FactoryRun for the approved work graph;
   - AgentRuns belong to that FactoryRun across Tasks/retries;
   - dependency-legal parallel dispatch inside the run.
3. **Real provider composition**
   - Subrouter AccountProvider -> actual selection/provenance;
   - Fabro FactoryProvider -> actual Factory mechanics;
   - ACP AgentProvider -> real agent session/Attempt;
   - Kubernetes WorkspaceProvider -> workspace for that Agent Attempt;
   - DBOS DurableWorkflowProvider -> durable orchestration;
   - GitHub Forge/VCS provider -> repository/candidate/publication mechanics.
4. **Real source workspace**
   - checkout exact Project repository/base revision into durable workspace;
   - agent edits real files there;
   - candidate manifest/tree identity derived from actual repository state.
5. **Verification and trusted merge**
   - persist VerificationEvidence/findings required by I1;
   - enforce evidence, review, target-head, policy, authority and candidate fidelity at merge time;
   - make trusted VCS repository-scoped, not one global checkout.
6. **Workspace lifecycle**
   - durable checkpoint/content collection;
   - explicit safe PVC cleanup after accepted WIP/artifacts are durable.
7. **Rebuild GOLIVE around the canonical production path**
   - eliminate fixture-only substitutes for product behavior;
   - self-dogfood AC-29 must create a commit that remains in actual AWP history;
   - UI acceptance must hit the same routes the owner uses.
8. **Only then declare I1 complete and begin I2.**
## Owner requirement — Slice 1 account onboarding and selection

Slice 1 is not owner-usable until account onboarding and account selection are available in the owner-facing UI. A real FactoryRun must not depend on hidden CLI-only setup or a fixture account.

Required for Slice 1:

- an owner-visible Add account surface backed by the dedicated K3s Subrouter instance;
- account inventory/status must come from the K3s Subrouter account API, not workstation/Systray/Overdeck state;
- adding an OAuth account must create a fresh server-owned login/credential chain; never import or copy workstation OAuth files;
- an owner-visible account selector must choose the explicit account provenance used by the real FactoryRun/Attempt;
- when no accounts exist, FactoryRun launch must be visibly blocked with a direct Add account action rather than silently using `golive-account` or another fixture identity;
- Slice 1 acceptance requires adding/selecting an account through the UI and then launching a real FactoryRun with that selected account.

## Owner requirement — Slice 1 execution-image convergence

Recorded 2026-08-22 after a runner smoke test exposed node-local image drift. This is binding for Slice 1, not deferred Cluster-product UX:

- an AgentRun execution image resolves to an immutable OCI digest in the configured registry (GHCR for the baseline deployment);
- kubelet/containerd pulls the digest on whichever eligible K3s worker is selected; K3s/Spegel caching is transparent optimization only;
- normal operation must never require `k3s ctr images import`, per-node image copies, or hand-maintained image-readiness labels/selectors;
- private-registry pull authority is a system credential consumed by Kubernetes image pulling, never an AgentRun-mounted credential;
- desired/applied/observed image configuration drift must fail closed with an intelligible AWP error before execution rather than being discovered manually as an `ImagePullBackOff`;
- Slice 1 acceptance must prove a worker with no preloaded AWP runner image reaches `Running` from the same digest through ordinary registry pulling.

The full Machine/Cluster management surface remains I7. Image convergence is I0/I1 execution-substrate correctness because a first real FactoryRun cannot depend on operator-managed node image state.
## Durable checkpoint — 2026-08-22 verification/merge-gate continuation

Exact resumed state after the Slice 1 execution-image convergence repair:

- branch: `ops/i1-dogfood-deploy`; latest pushed cleanup checkpoint before current WIP: `dd46156` (`Remove obsolete runner node metadata`);
- dogfood control plane is live on debian3 with native ACP enabled and `AWP_WORKSPACE_IMAGE=ghcr.io/platform-modules/awp-agent-runner@sha256:4d4641f173fc930feb2ff270500164d1d08e35bd2ce0ea7802d3e7b79fd339a2`;
- clean-worker proof succeeded on debian2: no preload of the new digest, normal Kubernetes/GHCR pull, pod Running/Ready, imageID exactly matched the locked digest, and the in-cluster runner capability IPC returned `codex-acp` with session/tool-call capabilities;
- obsolete per-node `awp.platform/agent-runner*` metadata is removed from all workers and durable deploy cleanup removes it on future deployments;
- live Subrouter, model-gateway and Fabro deployments are all available; control-plane health was clean; persistent dogfood state remained `factory_runs=0`, `agent_runs=0`, `changesets=0`, accounts `[]`; no owner login or FactoryRun was initiated.

Current uncommitted repair-order item 5 WIP:

- adding first-class candidate-bound `VerificationEvidence` and `ReviewFinding` domain/persistence families;
- extending PostgreSQL schema/repositories and lifecycle hierarchy so evidence/findings are authoritative and visible to U4/U5;
- Attempt completion now supplies structured timestamped evidence; ACP runner emits candidate-tree and `git diff --cached --check` evidence;
- review approval and `requestMerge()` are being changed to fail closed unless current required evidence passes and no unresolved blocking finding exists;
- canonical commands for later verification observations/findings are being wired through event/audit/outbox;
- Drizzle migration `0008_purple_scalphunter.sql` is generated with only `verification_evidence` and `review_findings`;
- focused PGlite proof passes: failed evidence blocks merge, newer passing evidence unlocks, blocking finding relocks, resolving it unlocks, and trusted merge executes only afterward;
- exact full remote `pnpm check` is green on this WIP: 39 test files passed / 2 skipped, 135 tests passed / 5 skipped, plus typecheck, lint, build, architecture, dependency-cruiser zero violations, and format check;
- next: commit/push this evidence slice, allow the GHCR workflow to publish the evidence-emitting runner and advance the digest lock, deploy migration 8 plus the new runner/control-plane together, verify live zero-run/account invariants, then continue repository-scoped trusted merge.

Do not mark I1 complete from this checkpoint. Do not initiate the owner login or a real FactoryRun unless the owner explicitly changes the existing instruction.
### Continuation checkpoint — 2026-08-22 13:41 UTC

Pre-change inspection for the VerificationEvidence deployment:

- worktree contains only the expected uncommitted evidence/findings/domain/persistence/runner/UI/migration/test changes from the prior green gate;
- debian3 dogfood control plane is `active`; PostgreSQL execution state remains `factory_runs=0`, `agent_runs=0`, `changesets=0`;
- deployed migration health remains clean at the pre-change baseline `applied=8`, `expected=8`, `pending=0`, `drift=[]`;
- account inventory unexpectedly returned HTTP 400 during this inspection instead of the previously verified empty account list. Treat this as a live regression to diagnose before deploying the evidence slice; do not assume account state changed and do not initiate login.
### Slice 1 system-image convergence discovery — 2026-08-22 13:44 UTC

Diagnosis of the account-inventory HTTP 400 found another instance of the same forbidden node-local image drift:

- debian3 experienced legitimate ephemeral-storage pressure and kubelet evicted the AWP Subrouter, Fabro, and model-gateway pods;
- replacement pods were subsequently scheduled back to debian3 but fail with `ErrImageNeverPull` because all three manifests still reference `localhost/...` images with `imagePullPolicy: Never`;
- account inventory fails because Subrouter is unavailable; this is not an account mutation and no login/import occurred;
- therefore Slice 1 image convergence must cover required `awp-system` runtime images as well as AgentRun/workspace images. Kubelet eviction/restart must recover by ordinary immutable registry pull without operator `k3s ctr images import`;
- repair this through registry-backed immutable Subrouter/model-gateway images and an immutable upstream Fabro digest, then restore all services and the empty account inventory before declaring the evidence deployment healthy.
### Continuation checkpoint — system-image repair staged

- VerificationEvidence slice is pushed at `a5332e1`; its hardened runner publisher succeeded and advanced `infra/dogfood/agent-runner-image.lock` to `ghcr.io/platform-modules/awp-agent-runner@sha256:dfe4f4555a6b441d3a3c87b42bb8649a004605cd93c67e8e0758169bc0698e44`.
- Fabro upstream digest was re-verified directly as `sha256:94e65f3da935a3b269818a0238c8f304fe5cf2aad5db856859d5ba3050eef6e7`.
- staged system-image convergence removes local build/import from normal dogfood deployment, adds GHCR digest publishing/locks for Subrouter and model-gateway, uses the immutable upstream Fabro digest, synchronizes the scoped GHCR pull authority into both `awp-workspaces` and `awp-system`, and changes system pods to ordinary `IfNotPresent` registry pulling.
- `bash -n` passes, all three system manifests pass Kubernetes client dry-run, and no Subrouter/Fabro/model-gateway manifest contains `localhost/awp-*` or `imagePullPolicy: Never`.
- live outage remains intentionally diagnosed rather than hidden: current Subrouter/Fabro/model-gateway replacements were evicted during disk pressure and cannot recover from their previously deployed node-local image configuration. Publish system-image locks and redeploy before considering the live stack restored.
### System-image publisher first-run repair

- first `system-images.yml` run failed before image publication because `pnpm install` could not read private `@platform-modules/db` from GitHub Packages (`401`, no auth header); no digest lock advanced and no live deployment changed;
- workflow repair now configures `actions/setup-node` for the `@platform-modules` GitHub Packages registry and supplies the same `PLATFORM_MODULES_NPM_TOKEN || GITHUB_TOKEN` read authority used by canonical CI. Republish through the workflow; do not bypass it manually.
### System-image publisher green checkpoint

`system-images.yml` completed successfully after the package-auth repair. Both private images were built/published, smoke-tested, and committed as immutable desired state. Exact locks now present on the branch:

- agent runner: `ghcr.io/platform-modules/awp-agent-runner@sha256:dfe4f4555a6b441d3a3c87b42bb8649a004605cd93c67e8e0758169bc0698e44`;
- model gateway: `ghcr.io/platform-modules/awp-model-gateway@sha256:1e572c0593063fe9830dbcf6036b764754643795c48c53cbece8821988447373`;
- Subrouter: `ghcr.io/platform-modules/awp-subrouter@sha256:ad546a6882e5430743e8122a8922115f94017349730f56efbb0062c493e5cd18`;
- Fabro upstream: `ghcr.io/fabro-sh/fabro@sha256:94e65f3da935a3b269818a0238c8f304fe5cf2aad5db856859d5ba3050eef6e7`.

Next operation is the durable debian3 deployment. It must apply migration 8, synchronize pull authority into `awp-system`/`awp-workspaces`, recover all three evicted system services by ordinary registry pull, deploy the evidence-emitting runner/control-plane contract together, and re-prove zero execution rows plus empty account inventory.
### Live deployment proof — VerificationEvidence + system-image convergence

The durable debian3 deployment completed successfully even though the wrapper call returned an intermittent transport exception. Exact post-deploy inspection proved:

- control plane `active`, health `status=ok`, migrations `applied=9`, `expected=9`, `pending=0`, `drift=[]`;
- PostgreSQL contains the new `verification_evidence` and `review_findings` tables;
- `AWP_WORKSPACE_IMAGE` is the matching evidence-emitting runner digest `ghcr.io/platform-modules/awp-agent-runner@sha256:dfe4f4555a6b441d3a3c87b42bb8649a004605cd93c67e8e0758169bc0698e44`;
- Subrouter, model-gateway, and Fabro are each `1/1` available using their immutable registry digests;
- Kubernetes events explicitly show `Pulling` and `Successfully pulled` for all three new system-image digests, proving recovery no longer depends on node-local imports;
- `awp-ghcr-pull` exists as `kubernetes.io/dockerconfigjson` in both `awp-system` and `awp-workspaces`;
- account inventory is restored to `accounts: []`; execution remains `factory_runs=0`, `agent_runs=0`, `changesets=0`; no login/import or FactoryRun occurred;
- obsolete failed/evicted system pods from the node-local-image incident were deleted after replacement deployments were healthy.

VerificationEvidence persistence/merge gating and Slice 1 image convergence are now live. Repair-order item 5 still remains incomplete until trusted VCS merge authority is repository-scoped and target-head/policy/candidate fidelity are enforced through the production runtime rather than one global `AWP_TRUSTED_REPOSITORY_PATH`.


## Reconciliation update — 2026-08-23 canonical I1 repair status

This section preserves the historical audit above while recording which previously-valid defects have since been repaired. It does **not** reinstate the invalidated 30/30 claim and does not mark owner-run GOLIVE criteria complete.

| Historical defect / repair-order item | Current status | Canonical evidence |
| --- | --- | --- |
| Canonical U1–U6 live integration | Repaired through current source path; final owner-run proof still pending | approved-live routes use authoritative lifecycle hierarchy; canonical client handles owner mutation/protected actions; `tests/ui/approved-live-authoring.test.ts`, `tests/ui/live-shell-assets.test.ts`, C1/U1–U6 UI suites |
| One FactoryRun per PlanRevision / shared run identity | Repaired | Factory orchestration and idempotency tests; AC-22 binding requires one FactoryRun for the three-Task Plan |
| Real Subrouter/Fabro/ACP/Kubernetes/DBOS composition | Repaired at wiring/runtime substrate level; owner account/run still pending | live system deployments, native ACP/server composition, provider/DBOS suites and immutable image gates |
| Real source workspace / candidate identity | Repaired | ACP repository recovery plus Git-tree candidate/checkpoint derivation and workspace lifecycle gate |
| Repository-scoped trusted GitHub publication/merge | Repaired | `138a7d5`, trusted publication/merge provider tests, target-head/candidate fidelity gates |
| Independent reviewer AgentRun | Repaired | `e4746b2`, reviewer persistence/runner/application tests; owner self-approval rejected for agent-assigned Review |
| Repository-required GitHub checks | Repaired | `9064252`, canonical required-check gate and live deployment evidence |
| Durable Workspace checkpoint / terminal cleanup | Repaired | `6e5e4da`, exact Git-tree attestation and merge-terminal PVC cleanup tests |
| Retry keeps immutable failed Attempt and new provider identity | Repaired | `d382943`; composed AgentProvider receives the new retry Attempt exactly once |
| Registry-backed immutable execution/system images | Repaired | runner/Subrouter/model-gateway/Fabro digest locks and live ordinary-pull proof |
| AC-29 FactoryRun provenance in actual Git history | Implementation gap repaired in current reconciliation slice | trusted publication commit metadata now carries `AWP-FactoryRun`; owner self-dogfood commit remains unproven until real FactoryRun |
| GOLIVE fixture-era semantics | Reconciled in current slice, but criteria remain unchecked until binding live run | AC-14/19/21/22/27/29 specs now target canonical workspace/reviewer/GitHub/account semantics |

Remaining I1 completion boundary is therefore no longer the historical substrate defects above. It is: (1) any remaining restart/reconciliation correctness defects found before dogfood, and then (2) explicit owner-gated Subrouter login, repository-scoped GitHub publication credential authorization, and owner-triggered FactoryRun followed by the binding canonical GOLIVE journey.
