# Direct GitHub k3s Factory

audience: AI coding agents first.

status: DONE
task IDs: #21, #34
source request: Owner directs direct private-GitHub deployment: Jobs use repository-scoped read-only deploy-key Kubernetes Secrets; controller alone holds write credentials and publishes result refs; remove Gitea, proxies, redemption, and new gates. Finish Factory on k3s and prove one real successful run with `gpt-5.3-codex-spark` at `xhigh`; use `gpt-5.6-luna` at `low` only if Spark cannot complete because of model capability.

## Acceptance criteria

- No Gitea transport remains.
- Job mounts exactly repository-bound read-only GitHub deploy key, runs non-root, and cannot push.
- Controller validates result bundle ancestry, publishes expected result ref, applies the delta, and cleans Job plus temporary refs.
- Registry allowlist, immutable image, resource limits, malformed-bundle rejection, and cleanup remain enforced.
- Before Press.Zone credentials are available, prove the full path with a real Overdeck canary; keep Press.Zone explicitly blocked rather than weakening repository authorization.
- Before Press.Zone-only credentials are available, one real Overdeck Factory run completes on k3s with `gpt-5.3-codex-spark` at `xhigh`; fallback to `gpt-5.6-luna` at `low` is allowed only after a concrete Spark model-capability failure. Receipt proves result publication/application and zero residual Job, Pod, temporary ref, and temporary state.

## Current receipt

- 2026-08-14: direct transport implemented from current main. Job emits a result Git bundle through a restricted shared-volume sidecar; repository content never enters Kubernetes logs. Controller validates bundle ancestry and publishes with controller-only credential.
- Verification: focused Kubernetes tests 23/23; full Factory suite 189/189 in the implementation worktree; integrated focused rerun 23/23 and diff check clean.
- Source landed. Image publication run `31790319291` produced immutable digest `sha256:02dc4a3549b6e03abeaaa3b20bd9bee0b6320e3a6649c064fc1775e85901b07a`.
- Runtime rollout requires binding the controller and admission policy to that exact published digest before applying the manifest. Existing live repository Secret covers Overdeck only; Press.Zone credentials remain to provision.
- 2026-08-14 runtime correction binds controller and admission to the published digest and admits the required restricted result sidecar, six volumes, and private result mount. Full Factory suite passed 189/189 after the final correction. Live Kubernetes policy applied with zero compilation warnings; a server-side dry run using the controller service account accepted the exact Job shape. Runtime and Overdeck repository Secrets were provisioned without exposing values.
- External blocker: the authenticated GitHub account has only WRITE permission on `avi-ezra/Press.Zone-Works`; GitHub requires ADMIN permission to create repository deploy keys and returned masked HTTP 404. No repository-scoped Press.Zone read or controller-write key can be created from the available authorization.
- Installed-source blocker: `packaging/deploy-local.sh` rolled back because required pre-existing `/home/user/.config/overdeck/actions-gateway.env` is absent. The live deploy clone therefore remains on the prior Factory controller digest; direct mutation is correctly denied by the deploy-clone guard.
- Runtime correction commit `b5b7aee5f` is contained by `origin/main`. A real Overdeck control canary scheduled on Debian2 and pulled the exact 650 MB immutable image, but twice failed to produce the private result marker before the 900-second deadline. The controller removed every Job, Pod, execution ref, and result ref; live residual count is zero.
- Bounded retained-Pod diagnosis proved the worker exits before startup with `ModuleNotFoundError: No module named 'adw_modules'`: the installed entrypoint lives under `/usr/local/bin` while Factory modules live under `/opt/factory`. Diagnostic Job, Pod, refs, manifest, token configuration, and state were removed. Correction `96c75b467` landed through `090f854e4`; focused Kubernetes suite passed 23/23 and full Factory suite passed 194/194. Image publication run `31822840574` succeeded, but independent pre-install review found its `--check-entrypoint` runtime flag could bypass workload validation because admission does not forbid container arguments. That image was not installed. Follow-up `d46819475` landed through `975ae48f5`, removes the runtime flag, and probes the required import directly during image construction. Focused Kubernetes suite passed 23/23, full Factory suite passed 194/194, independent re-review found no blockers, and publication run `31827315492` produced immutable digest `sha256:393bef67a146cf1d3cdce3de4457b6461acc667886274fb6c3ec4fe21cb8c3e4`.

- Secure digest rollout worktree bound controller and admission to `sha256:393bef67a146cf1d3cdce3de4457b6461acc667886274fb6c3ec4fe21cb8c3e4`; live admission policy applied with zero expression warnings and reported only that digest. Runtime model inspection proved Spark was absent while Luna was present, so the acceptance slice added measured Spark metadata (128,000-token text context; low/medium/high/xhigh support) to the source model registry and the exact all-seat `k3s-spark-xhigh` Factory preset. Focused Kubernetes suite passed 23/23 and full Factory suite passed 194/194. Source landed through `2c0e88d5ad9682b0c26a7e992cd3fa01d6a749e6`; image publication run `31830575792` completed successfully with final manifest digest `sha256:2c27f7a2d8e1aac2620e0eb3e0e54d9601e0ecbffe2a880e4665e5329f4edb95`. Debian3 now has the approved `harness-seat:2` image required for model-backed verification; its build completed with exit code 0. Approved remote verification completed as `gpt-5.3-codex-spark` and returned `SPARK_CAPABILITY_OK`; no Luna fallback is justified. Current digest rollout binds source and admission to the final Spark-capable image before the real acceptance run.
- 2026-08-15 pre-launch proof found the controller Role omitted `create` on `pods/exec`, even though result readiness and bundle copy both use the restricted result-reader exec subresource. Launching in that state would wait until timeout rather than import a valid result. The correction adds only that exact permission and a regression assertion. One apply was accidentally issued from the shared checkout and briefly selected its unrelated digest; the intended final policy was reapplied immediately, then verified with zero expression warnings and only digest `sha256:2c27f7a2d8e1aac2620e0eb3e0e54d9601e0ecbffe2a880e4665e5329f4edb95`. The exact controller-authenticated Job shape passes server-side dry run. Correct-worktree digest tests passed 23/23 and the full Factory suite passed 194/194; both passed again after the permission correction. Live authorization now confirms the controller can create only the required Pod exec subresource.
- First real Spark/xhigh launch scheduled on Debian2 with the exact final digest and no laptop fallback. The worker failed before Factory startup because the image did not contain `/usr/bin/ssh`, which its strict private-GitHub clone command requires. This is an image dependency failure, not a Spark capability failure; Luna fallback remains forbidden. Controller cleanup removed the execution ref and result ref, and Kubernetes completed Job and Pod removal. The run also exposed that a nonzero worker exit incorrectly entered result-marker polling; the correction stops immediately, captures logs/status, and never copies/imports/publishes a nonexistent bundle. `openssh-client` and failed-worker handling landed through `0913018bc` to trigger the replacement image build.
- Post-land security review rejected both namespace-wide `pods/exec` and the attempted `GET pods/proxy` replacement: either credential could cross attempt boundaries, while controller-side filename validation cannot constrain a stolen Kubernetes token. Both live permissions were revoked immediately and now authorize `no`. Replace Kubernetes read access with an attempt-bound direct TLS upload to the trusted controller: one random write-only token, one exact attempt URL, a pinned one-day certificate, a 256 MiB limit, digest verification, replay rejection, and no Kubernetes API credential or Git write credential in the Job. Controller accepts only the expected bundle, then performs existing bundle and ancestry validation. This transport must fail closed when no explicit controller address is configured and must be real-network tested before image publication.
- 2026-08-15 direct TLS transport candidate is coherent and under independent review. The controller now runs an attempt-bound, one-claim HTTPS mailbox; the worker receives only its exact URL, random write token, and pinned certificate, streams a bounded SHA-256-verified bundle, and has no Kubernetes API or Git write credential. The obsolete result sidecar, shared result volume, `pods/exec`, and `pods/proxy` are absent. Signed attempt envelopes now bind the repository policy to the exact attempt ID, execution/result refs, immutable input commit, invocation digest, and bounded expiry; the worker independently checks every binding before clone execution and verifies the cloned commit. Admission no longer treats comparison between two request-controlled fields as authorization. Focused transport tests passed 45/45; the mandatory full Factory suite passed 216/216; server-side policy dry run completed without warnings. A real restricted k3s Job on Debian2 uploaded 18 exact bytes over the pinned mailbox path, and its temporary namespace, Job, Pod, pull credential copy, mailbox certificate/key, token, and partial state were removed. Final image publication and real Spark/xhigh Factory acceptance remain pending the independent review.

- 2026-08-15 final pre-ship hardening completed. The controller validates untrusted result bundles in a temporary Git object quarantine using the controller object store only as an alternate, rejects invalid ancestry, runs strict object verification, caps object count, per-object expanded size, total expanded size, object-list output, process address space, CPU time, wall time, and generated binary patch size, and imports only after every check passes. Patch generation and application stream through bounded files. An uncertain Job-create response now always triggers idempotent foreground deletion. Signed `retain_on_failure: true` validates and publishes a failed worker result without applying it, preserves that approved result ref during immediate and crash-recovery cleanup, and retries all other cleanup. Completed bundles and patches are removed. Worker logs stream to a hard-capped 64 MiB file with explicit byte-count, truncation, and command-error metadata. Focused security tests passed 57/57; the mandatory full Factory suite passed 228/228; `git diff --check` passed; server-side policy dry run passed without warnings. Independent single-thread re-review found no remaining blockers and declared the source ready to ship.
- The reviewed transport source landed on `origin/main` at `fc6203ebc946812f6b7dfbf4754fe2cc6d37836e`. Image publication run `31841177016` succeeded and produced immutable manifest digest `sha256:20d25ca7f1e511d76de4487815ee71b102f4061c9c141f982b19c4f5ca72f60b`. Local deployment of the landed source completed successfully. The workflow emitted one benign annotation because GitHub's diagnostic build-record artifact quota is full; image publication and its immutable digest were unaffected. Digest binding, verification, live policy installation, and the real five-seat acceptance workflow remain active.
- Automated post-publication review found four policy gaps before live rollout. The correction gives the worker a fixed proxy Service address and removes recursive DNS access, adds namespace-wide default-deny egress, requires exact Pod-template labels, requires each environment name exactly once, binds the repository Secret name to the signed-envelope credential handle as a consistency check, and makes controller-created Secrets and NetworkPolicies enter fail-closed shape validation even when their names are not reserved. Server-side dry run accepts the corrected policies without expression warnings. Focused verification passed 36/36 and the mandatory full Factory suite passed 228/228. The correction landed at `432e425b23528defdb9cb09934a6775d77c96e52`, the installed entrypoint resolves to that exact source, live admission permits only the new digest, and the egress proxy is ready at `10.43.200.8`. A restricted worker-network probe proved GitHub SSH and ChatGPT TLS allowed through the proxy, arbitrary hostname denied by the proxy, and recursive DNS plus direct internet denied. Correct subresource authorization proves Job finalizer update allowed while Pod exec and Pod proxy are denied.
- Pre-launch worker inspection found the immutable image's SSH `ProxyCommand` still uses the proxy Service hostname. Removing worker DNS therefore also requires an admission-locked `/etc/hosts` mapping from that exact hostname to the fixed Service address; without it, private-GitHub clone would fail before Factory starts. This infrastructure mismatch is not a Spark capability failure. The admission-locked host-alias correction passed focused verification 36/36, the mandatory full Factory suite 228/228, and server-side policy validation without expression warnings. It landed and deployed at `ce86d1d57`; live admission now requires the exact mapping.
- Final acceptance inspection found no existing single Factory workflow invokes all five required seats. Canonical `adw_sdlc.py` invoked planner, builder, reviewer, and documenter; scout was isolated in `adw_scout.py`. The correction adds one scout phase before planning, passes the typed `ScoutOutput` envelope into the planner, and adds regression coverage proving phase order, all-five-seat order, and the handoff. Correct-worktree focused verification passed 6/6, the mandatory full Factory suite passed 228/228, and `git diff --check` passed. Independent review found no blocking defects. It landed on `origin/main` at `6de03bd0c2623cf23d41234d5a89485d0dee8d02`, local deployment completed, and image publication run `31844396812` produced immutable digest `sha256:cf123e62a95388a1e3ee0b7712094687d32060f934f0427fb5c075e88b8362a7`. GitHub again reported only the benign diagnostic build-record artifact quota warning; image publication succeeded. Controller, proxy, worker generation, and admission were bound to that digest; focused digest verification passed 36/36, mandatory full Factory suite passed 228/228, `git diff --check` passed, and server-side policy validation completed without warnings. Digest rollout landed and deployed at `22c587e08`; live proxy is ready on `10.43.200.8`, live admission reports only the replacement digest, controller Job creation is allowed, and Pod exec/proxy remain denied.
- Three initial real acceptance launches were stopped before any worker or model started. The default kubeconfig failed trusted-controller admission; the prior scoped token had expired; a fresh owner-only scoped kubeconfig then proved exact controller identity and Job-create permission but the generated Job failed the combined identity-shape admission expression. Live API defaulting proof showed Kubernetes adds four controller-owned labels to each Job Pod template, increasing its label set from three to seven. The corrected policy requires all seven labels and binds both Job-name labels to the Job name and both controller-UID labels to the server-assigned Job UID. The next launch passed identity admission and exposed a second API-type mismatch: volume size limits reach admission as strings, so direct comparison with Kubernetes Quantity values rejected the authorized Job. The corrected policy converts each size string with `quantity(...)`, performs exact typed comparisons, and keeps volume checks separately named for actionable failures. Focused policy verification passed 36/36, mandatory full Factory verification passed 228/228, server-side policy validation and `git diff --check` passed, and the live corrected policy is installed. Every rejected request left zero Job and worker Pod. These were authentication/admission infrastructure failures, not Spark capability failures; Luna fallback remains forbidden.
- The corrected policy admitted the real Job and its Pod ran on Debian2 with the required immutable image. Factory still stopped before any model seat: `uv run` tried to resolve `python-dotenv` from PyPI, which the intentionally narrow egress proxy denied. The failed worker uploaded a result, exposing two controller defects: its quarantine repository could not traverse the trusted authorized input commit, and a completed foreground Job deletion exceeded the client timeout and masked the primary failure. This was infrastructure failure, not Spark capability failure; Luna remains forbidden.
- Recovery hardening now forces the immutable image's installed Python environment with admission-locked `UV_NO_SYNC=1`, gives the temporary quarantine repository a persistent alternate to the trusted controller object store, realistically proves import when result objects exist only in a separate worker clone, and confirms Job absence after a foreground-delete timeout before deciding cleanup failed. Focused Kubernetes verification passed 36/36; mandatory full Factory verification passed 228/228; server-side admission dry run passed; `git diff --check` passed. Commits `ed902cd30` and `b24d0e3a3` are isolated in `/home/user/Projects/overdeck/.worktrees/factory-admission-identity`. Independent review found no blocking defects.
- The first candidate retry forwarded the preset before the workflow token through the Kubernetes CLI separator, so the immutable worker correctly rejected `--preset` as an unknown workflow before any model ran. Its cleanup exposed one migration edge: the newly exact 15-variable admission policy rejected finalizer removal on a terminating 14-variable Job created under the prior policy. Admission now applies exact shape validation only to live Jobs; the trusted controller can finish deletion after `deletionTimestamp` is set, while create and unsuspend updates remain fail-closed. Focused verification passed 36/36, mandatory full Factory verification passed 228/228, server-side dry run and diff check passed, live policy installation succeeded, both failed Jobs and Pods are absent, and both failed-attempt transport refs were removed. This was orchestration and cleanup infrastructure failure, not Spark capability failure; no model seat started and Luna remains forbidden.
- The next retry reached the immutable Factory entrypoint with `UV_NO_SYNC=1`, but `uv run --project /opt/factory /opt/factory/adw_sdlc.py` treated the executable script's PEP 723 dependency block as a separate script environment and attempted to resolve `rich` from PyPI. A restricted diagnostic Pod proved the image already contains `rich` in `/opt/factory/.venv` and that no-sync succeeds when Python is invoked explicitly. The candidate entrypoint now runs `uv run --project "$FACTORY_ROOT" python "$adw_path"`, forcing the locked preinstalled project interpreter instead of script dependency resolution. Its exact launch-argument regression passed 1/1; the mandatory full Factory suite passed 228/228; diff check passed; independent single-thread review found no blocking defects. This was dependency-launch infrastructure failure before the scout seat started; Luna remains forbidden. The failed Job, Pod, and retained diagnostic result ref were removed.
- The locked-environment correction, quarantine recovery, cleanup migration, and admission fixes landed and deployed at `71bf089aa70eafc41f513b4602a9f6c0da67a0b6`. Image publication run `31849124582` succeeded and produced immutable manifest digest `sha256:d22fbb998bb1b83d696166f6d00e2cdeeffe3d6fe919f674d69be2a372877953`. The current rollout candidate binds controller, proxy, worker, init container, and admission to that exact digest. Live installation and the real five-seat acceptance remain pending.
- Live rollout now binds admission and the ready egress proxy to `sha256:d22fbb998bb1b83d696166f6d00e2cdeeffe3d6fe919f674d69be2a372877953`. Attempt `factory-ffa20b59dbf77e20` used that image, the exact five-seat invocation, the restricted security context, and scheduled on Debian1, but failed during the private-GitHub clone with `Connection closed by UNKNOWN port 65535` before scout or any model seat started. The controller then reported a mailbox timeout because no pre-clone bundle existed. The Job, Pod, temporary refs, attempt Secret, mailbox NetworkPolicy, and mailbox state are absent; only persistent runtime resources remain. The proxy is ready on Debian2 and direct proxy-Pod reachability to `github.com:22` succeeds. Credential inspection then found the matching GitHub deploy key had mistakenly been authorized for writes despite the required read-only boundary; it was atomically replaced with the same public key under read-only authorization, and GitHub now reports `read_only: true`. This was a real boundary violation and is corrected. Retry `factory-c050a8317eb864d9` then cloned successfully and reached the required Spark/xhigh scout, disproving a persistent Git transport or node-path defect, but all three scout responses were empty with zero tokens. Credential fingerprint inspection found the mounted OpenAI OAuth authorization had expired on 2026-08-13 while the same-account local authorization remains valid through 2026-08-23. The runtime Secret was refreshed from that current same-account source without exposing values, and exact byte identity, account identity, future expiry, and read-only GitHub authorization were verified. The refreshed run `factory-70476fb58a03610c` then proved Spark authentication and execution work: its first scout attempt returned 4,241 output tokens after 202 turns, but the model repeatedly terminated with the exact provider error `Your input exceeds the context window of this model` and no final report. This is the concrete Spark model-capability failure required by the owner’s fallback rule. A five-seat `gpt-5.6-luna`/`low` retry is now authorized; no earlier infrastructure failure was treated as capability. Session interruption left the controller alive but made its process easy to miss; manual cleanup removed the Job and its output directory before the controller emitted its final receipt, causing only the expected local `FileNotFoundError` in that interrupted diagnostic path. Independent cleanup proof confirms the Job, Pod, attempt Secret, NetworkPolicy, mailbox directory, and temporary refs are absent. The candidate also makes Pi surface return-code-zero terminal provider failures as typed `context_overflow`, makes pre-upload worker failures immediate and explicit instead of waiting on a nonexistent mailbox result, and replaces deprecated tinyproxy `FilterExtended On` with exact `FilterType ere`; focused Pi verification passed 16/16, focused Kubernetes verification passed 3/3, the prior mandatory full Factory suite passed 229/229, diff check passed, and client-side server dry-run passed without warnings. A later remote full-suite attempt ran against committed base content rather than this uncommitted candidate and is not accepted as candidate proof; it passed 175 tests only. An attempted server-side-apply dry run emitted expected field-manager conflicts because the live objects are client-side managed; it made no changes and the correct client-side dry-run is clean. The required `/od-testing` skill is unavailable in this session, so verification used the project-mandated commands directly. A clean temporary acceptance commit now supplies the complete five-seat Luna/low roster with all prompt and extension paths validated; its real k3s run is active.

- The first authorized Luna/low fallback attempt `factory-383511c202b952cc` completed scout, planner, and builder work and produced the requested documentation result. The trusted controller validated and published that failed result at `origin/factory-result/383511c202b952cc9ca5ca21`, then removed the Job, Pod, attempt Secret, NetworkPolicy, mailbox credentials, and temporary execution ref. Reviewer and documenter did not run because the temporary acceptance overlay inherited the workstation-wide Overdeck quality commands; the restricted runner intentionally has no installed workspace and therefore returned exit 127 for `pnpm`. This is an acceptance-profile mismatch, not a Luna capability failure. Do not turn the shared runner into a mutable repository toolchain or weaken the gate. Extend the temporary project overlay with k3s-native checks that exercise the immutable Factory suite, compile its installed Python source, and reject whitespace errors in the candidate diff; prove those exact checks independently, then rerun the same five-seat Luna/low workflow on the unchanged immutable image.
- The second Luna/low fallback attempt `factory-0944f94d7cf05b53` again completed scout, planner, and builder, but every bounded quality attempt failed before reviewer because the broad installed test suite returned exit 1 under the restricted runtime and `compileall` attempted writes against the read-only image. The worker still uploaded its result; the controller validated and retained it at `origin/factory-result/0944f94d7cf05b53214ba0e8`, then recorded `state: cleaned`. The acceptance-only overlay then switched to a runtime seam test that loads the exact five-seat roster, proves every prompt path and Luna/low binding, parses all installed Factory Python source without writing bytecode, and runs `git diff --check`. Local path-equivalent execution passed all three checks before corrected attempt `factory-0408c02b07943c9c` launched on the unchanged immutable image. The mandatory full candidate suite remains independently clean at 230/230; the narrower in-Job checks do not replace that source gate.
- Corrected Luna/low attempt `factory-0408c02b07943c9c` completed successfully on Debian2 through the unchanged immutable digest. Scout, planner, builder, reviewer, and documenter all ran as `openai-codex/gpt-5.6-luna` at `low`; all three configured quality checks passed on the first attempt; review accepted 8/8 requirements; the workflow completed 11/11 phases with ADW `dade3df1`. The trusted controller accepted the upload, validated and published the result, applied `docs/factory-k3s-acceptance.md` plus its documentation record to the acceptance worktree, then removed the Job, Pod, upload Secret, mailbox NetworkPolicy and directory, execution ref, and result ref. Attempt receipt records `state: cleaned`. The local owner-facing trace database contains no session for `dade3df1`, confirming the remaining observability bridge gap rather than hiding it behind `job.log`. The corrected `FilterType ere` proxy configuration is live; only the proxy Deployment rolled, startup emitted no deprecation warning, GitHub returned HTTP 200 through it, and an arbitrary host was denied.
- Controller/provider/proxy source is landed and deployed at `77c4f0b2`; the installed `factory` entrypoint resolves to that deployed source and starts successfully. Initial trace-bridge commit `5fbc214d4` passed 234/234 Factory tests, but independent reviews blocked installation: untrusted Job stdout could overwrite another attempt's trace, trace ingestion continued beyond the 64 MiB retained-log bound, incomplete trace could mask a valid uploaded failed-result bundle, and required sanitized lifecycle/tool evidence remained worker-local. The implementation worker is correcting all four findings with strict attempt/session ownership, a pre-parse byte/record budget, independent bundle handling, and sanitized lifecycle coverage. No rejected trace candidate was installed or landed.
- Reviewed trace bridge and recovery hardening landed at `80b79cf70`; independent correctness and security reviews are clean, and the exact landed candidate passed 245/245 Factory tests. Image publication run `31856036807` succeeded with immutable digest `sha256:5dbe48dbe57f863ad6d1ea72a3cf470c5cf52bed6fa799216779779ee55c0ff5`; the diagnostic artifact upload alone was skipped because the repository artifact quota is full. Digest binding passed focused verification 50/50, full verification 245/245, diff check, and server-side policy validation, then landed and deployed at `a167442ba`. Live admission and the ready egress proxy now bind only the new digest. Installed acceptance attempt `factory-ce1c641d7f19d730` is active on Debian2 with the exact image and no local fallback.
- Live acceptance exposed a producer/consumer protocol defect before final completion. The worker emitted 448 log lines and advanced through request, scout, planner, builder, quality, and three reviewer/revision rounds, while the canonical trace retained only session placement. The first post-start record was the session-level console event with `phase_id: ""`; the mirror correctly rejected empty optional identifiers, recorded the trace failure, and stopped ingesting later records. The workflow itself then failed after its third reviewer rejected an invented markdown-lint requirement that was not among the configured acceptance checks, so documenter did not run. Failed-result validation independently reached the uploaded bundle but timed out after 125 seconds because unrestricted `git fsck` traversed the trusted repository's full reachable history through alternates; cleanup still removed the Job, Pod, upload Secret, mailbox NetworkPolicy and directory, and temporary refs, while the invalid result was neither published nor applied. The correction omits empty optional trace identifiers, adds an actual threaded `JobLogFollower` regression beginning with a real session-level event, validates every newly fetched bundle object with `fetch.fsckObjects=true`, and limits the final strict graph check to connectivity so trusted historical blobs are not redundantly expanded. Focused verification passed 64/64; mandatory full Factory verification passed 246/246 in 82.44 seconds; `git diff --check` passed. Independent single-thread review approved the trace normalization, incoming-object validation, connectivity check, and regression with no blockers. The replacement acceptance request must list only requirements review can verify before documenter runs; documentation recording remains the documenter's later workflow responsibility.
- The correction landed on `origin/main` at `1e7bc8a312e15f07914c5e0660d6f2a9aadb9c19` and is installed: the live `factory` entrypoint resolves into the deploy clone at that exact commit, where all three corrected source seams are present. The first deploy invocation lost a concurrent remote-ref update race; the immediate retry found the same commit already fully deployed and returned cleanly. Image publication run `31857292939` succeeded with immutable digest `sha256:1fe5c99d938d79ce13c7bca8d21989d38148b30208ba17fef38a22d948f8204f`. GitHub again skipped only its optional diagnostic build-record artifact because the account artifact quota is full; image publication and the immutable digest are complete. The digest rollout candidate binds controller, proxy, worker, init container, and admission to that exact digest. Focused verification passed 51/51, mandatory full Factory verification passed 246/246, `git diff --check` passed, and server-side policy validation accepted all 17 resources without warnings.
- Digest rollout landed, deployed, and is live at `ec3371b5c`; the installed controller, ready proxy, worker/init policy, and admission all bind only `sha256:1fe5c99d938d79ce13c7bca8d21989d38148b30208ba17fef38a22d948f8204f`. The live admission status retains Kubernetes static-type warnings for optional core `resources.requests`, `resources.limits`, and `emptyDir.sizeLimit` fields; these are benign API-server type-check false positives, not expression failures: exact valid Jobs have been admitted, invalid shapes denied, and the same typed expressions evaluate at admission. The deploy also surfaced and repaired a dangling collector unit drop-in link; every owner-facing service is active and systemd now reloads the collector without warning. Diagnostic attempt `factory-b62b56c7d8e7cc91` ran on Debian2 with zero restarts and the exact image. Its owner-facing `/factory` data showed ADW `4d042029` with five phases, three gates, 123 events, and tool lifecycle, proving empty optional identifiers no longer stop initial ingestion. Inspection found a remaining confidentiality defect: event `name` carried command-derived tool display text such as paths and shell summaries, violating the bridge contract that forbids commands and tool arguments. The workflow later uploaded a validated failed result, retained at `refs/heads/factory-result/b62b56c7d8e7cc91e47bf6e1` (`bc85d24b882d4e79f3838c4be05fec78742e308c`), but its trace failed when three tool lifecycle pairs lacked correlation metadata; the strict mirror rejected the first incomplete `tool_call_id` instead of accepting an unowned lifecycle record. The final bridge candidate omits every tool-event display name, retains only allowlisted tool identity and lifecycle metadata, and skips incomplete tool lifecycle records that cannot be safely correlated. Regression coverage injects command-derived names plus incomplete lifecycle pairs and requires that none enter structured output. Current cluster access confirms the diagnostic Job, Pod, upload Secret, and mailbox NetworkPolicy are absent. After recording result commit `bc85d24b882d4e79f3838c4be05fec78742e308c`, the trusted force-with-lease cleanup removed its retained result ref and remote absence was verified. This diagnostic run cannot be the final acceptance receipt.

- The final trace candidate buffers tool lifecycle starts and emits only exact complete pairs keyed by session, agent attempt, and globally claimed tool-call ID; malformed, unfinished, duplicate, and mismatched records are omitted without blocking later safe events. Tool display names are always omitted while allowlisted lifecycle identity, timing, and verdict fields remain. Focused verification passed 13/13 without warnings. Independent single-thread review first found unmatched-start and mismatched-attempt poisoning paths; both were corrected with explicit regressions, and re-review approved the current diff with no blockers. An automated security check separately flagged that a Job can forge records for its own attempt because trace records cross workload stdout. This is not a trusted-control bypass: worker trace is explicitly untrusted, confined to its signed attempt and newly created session/object ownership, strictly schema/budget checked, and cannot drive result validation, application, publication, credentials, or another attempt. A separate signing key inside the same worker would not establish a stronger boundary. A second automated alert named reusable tool-call IDs as audit-log evasion; the producer now claims each ID for the whole session and refuses reuse, while the worker's own observability remains non-authoritative by design. Mandatory full Factory verification passed 246/246 in 134.39 seconds, and `git diff --check` is clean.

- Trace confidentiality source landed on `origin/main` at `bffd0822e5f32d8746c4b207f34b3776b98d2f4e`. The canonical deployer correctly refused to install unlanded source and returned its documented docs-only receipt before landing; the landed deployment then completed at `bffd0822`. Image publication run `31859277448` succeeded and produced immutable digest `sha256:0d6604134441d4466a1af18955d3fbb8656e08a635dead166682a3a372be6f0a`. GitHub again skipped only the optional diagnostic build-record artifact because account artifact storage is full; image publication and digest integrity are unaffected. The final digest rollout landed and deployed at `74cf84375e6b5b25524727149da00622336f1a3a`; the installed controller, ready proxy, worker/init policy, and admission use only that digest. Focused controller/policy verification passed 51/51, mandatory full Factory verification passed 246/246 in 116.65 seconds, `git diff --check` passed, and server-side validation accepted all 17 runtime resources without warnings. The deploy readiness loop emitted one transient Kanboard HTTP 502 during restart; its required canary subsequently passed, the deploy exited zero, and Kanboard plus `/factory` now return HTTP 200. The deploy also reported pre-existing stale registered checkout copies whose shims differ from the installed `origin/main` shims; those unrelated checkouts were not executed or modified.
- Final acceptance attempt `factory-10d2686a0903c0fd` completed successfully through the installed `factory kubernetes` entrypoint on Debian2 with immutable digest `sha256:0d6604134441d4466a1af18955d3fbb8656e08a635dead166682a3a372be6f0a`. ADW `1759b7c0` ran scout, planner, builder, reviewer, and documenter as `openai-codex/gpt-5.6-luna` with the acceptance overlay proving `thinking: low` for every seat. All 11 phases and all configured quality/review gates passed on the first attempt. `/factory` and its owner-facing run API show the successful run, all five seat identities, 47 exact tool start/completion pairs with no tool display names, Kubernetes placement, and node `debian2`; the trace contains no incomplete lifecycle pair. The trusted controller accepted the attempt-bound TLS upload, validated the bundle, transiently published the expected result ref, applied `docs/factory-k3s-acceptance.md` plus the documenter's `app_docs/1759b7c0_factory-k3s-acceptance.md` record, and exited zero. The final attempt receipt records `state: cleaned`; its Job, Pod, upload Secret, mailbox NetworkPolicy, mailbox temporary directory, execution ref, and result ref are absent. Live `/factory`, its run API, Kanboard, and the installed source all remain healthy.
- Spark fallback eligibility is final: authenticated Spark/xhigh execution produced 4,241 output tokens but terminated with its own context-window capability error. Luna/low was used only after that measured model failure, never for an infrastructure failure.
- Press.Zone remains outside executable acceptance because the available GitHub account lacks ADMIN permission to create its repository deploy key and owner-managed Actions Gateway configuration is absent. Exact repository authorization remains fail-closed; no credential was synthesized and no weaker transport was introduced.
- The acceptance receipt landed and deployed at `84d9ede23d44691cee072b1593a99522b4967f1f`; installed `/factory`, its run API, and Kanboard return HTTP 200. The acceptance-only scoped kubeconfig was removed. Completed worktrees `factory-five-seat-real-run`, `factory-provider-deploy`, `factory-k3s-trace-bridge`, and `factory-trace-digest` were removed. Their identical pre-existing `.wrangler/cache` deletion delta was preserved before removal in the local WIP vault at `manual-factory-cleanup-20260815` with SHA-256 `7f87f834cb2284dcff660394f3c579a0a3d4e2848e90bd167ce22d3769c5f642`; branch commits remain reachable. This plan now has its required `DONE` row in `docs/plans/INDEX.md`. The final receipt worktree is removed only after this plan/index update lands and deploys.

## Preserved WIP

- Superseded Gitea branch `wt/registry-envelope-hardening` and rescue ref remain parked. MUST NOT deploy or copy from them.
- Runtime rollout correction landed at `b5b7aee5f`; current diagnostic receipt worktree is `/home/user/Projects/overdeck/.worktrees/factory-k3s-overdeck-canary`.

## Constraints

- Secret values MUST NOT enter source, plans, logs, or receipts.
- Press.Zone Job receives read-only repository access only. Controller publication uses the existing trusted local Git credential path and MUST NOT mount write credentials into the Job.
- Apply the exact immutable image digest; never use a mutable tag or silently fall back to local execution.
- Preserve restricted non-root execution, exact repository authorization, resource limits, ancestry validation, and idempotent cleanup.

## Execution steps

1. Land the reviewed direct-TLS source and publish its immutable Factory image.
2. Bind controller, worker, proxy, and admission policy to the published digest; rerun required Factory verification and land the digest update.
3. Apply the runtime policy and prove exact controller authorization, denied cross-boundary permissions, and allowed/denied network paths.
4. Run a real Overdeck canary through the installed controller entrypoint with all five seats on `gpt-5.3-codex-spark/xhigh`.
5. Prove publication, local application, seat/model identity, Job/Pod deletion, temporary-ref deletion, credential/mailbox deletion, and bundle/patch cleanup.
6. Record installed receipt, redeploy landed source, and keep the separate Press.Zone credential/configuration blocker explicit.

## Next executable action

No executable Factory action remains. Land and deploy this final plan/index receipt, remove its now-clean receipt worktree, and keep Press.Zone blocked until repository ADMIN authorization and owner-managed Actions Gateway configuration exist. NEVER weaken exact repository authorization to bypass that separate blocker.
