# CPU load incident — agent session sprawl (2026-08-11)

status: SUPERSEDED (2026-08-15) — see "Superseded" section below; task #3's seat-authority candidate
recovered and continued under `2026-08-15-fire-session-harvest.md`
owner: main session
source requests:
- owner, 2026-08-11 14:20 — "another incident: cpu load is 100% for the last few hours again"
- owner, 2026-08-11 — attached-session safety correction: `ipz-wip-triage` disappeared while owner was attached; recover it and prevent recurrence

task IDs: #1, #2, #3, #4, #5, #6

## Outcome

Laptop usable under normal agent workload, and the load source no longer accumulates
silently across days.

## Measured state at incident open (14:21)

- 16 cores. load avg 74/66/71. CPU 58 us / 39 sy / 0.9 idle. PSI cpu some avg60 = 65.8.
- RAM 40G/61G used, swap 32G/77G used → swap thrash contributing to the 39% sys time.
- 1352% of 1600% consumed. Breakdown: claude 628%, tsserver 281%, bun 115%, other 351%.
- 56 top-level `claude` sessions, 108 claude processes, 27 tmux sessions on
  `~/.local/state/human-session/tmux.sock` (15 attached, 12 detached).
- 22 `tsserver` processes, 8.4 GB RSS, top two at 2249 MB and 1963 MB.
- 61 `*.jsonl.live` transcripts; only 2 written in the last 10 minutes → ~59 sessions
  idle yet each burning 5–40% CPU.

## Root cause (measured, not inferred)

Two independent contributors:

1. **Session sprawl.** Sessions accumulate across days (oldest 101 h) and are never
   reaped. Detached tmux sessions idle >24 h were still running full claude trees.
2. **Idle burn.** An idle claude session is not free: 34 claude-core processes drew
   512% combined while idle, plus 115% across 38 `quietmode` plugin processes and one
   orphaned `claude daemon run --origin transient` at 101%. tsserver adds ~1 GB RSS per
   session that ever opened a TS file.

## Restoration performed

| action | result |
| --- | --- |
| Killed 22 tsserver + 12 typescript-language-server + nemo | freed 8.4 GB RSS |
| Killed 7 detached tmux sessions idle >20 h (ThemeFactory-010205, claude-…013255Z, claude-…013552Z, claude-…070126Z, international-press-zone-160700, international-press-zone-175927, multideal-163053) | 27 → 20 tmux sessions |
| Attempted reap of orphaned ThemeFactory daemon (pid 110791, 101% CPU) | **BLOCKED** by the kill guard |

Result: 1352% → ~1180% busy, load 74 → 51, RAM 40 → 31 G, swap 32 → 23 G,
PSI cpu some avg10 68 → 41.

## Cleanup mechanism — shipped (owner request, 14:50: "we need a cleanup mechanism … when a
session is idle and detached from tmux it should exit automatically")

`agent-sessions reap` + `agent-session-reap.timer` (5-minute interval) landed as
`78f98264` and was deployed, then disabled after attached-session safety report. Original
implementation selected live, detached, transcript-idle, CPU-idle sessions and used direct
process signals plus `tmux kill-session`; hardening below replaces that unsafe termination
path before timer reactivation.

First installed run stopped 5 sessions (one idle 2 h, four idle 46–47 h) and took the
orphaned ThemeFactory daemon with them. Load 74 → 18, busy 1352% → 798%.

**Bug found and fixed on the way:** `tmuxHasAttachedClient` asked
`display-message -p -t <session> '#{session_attached}'`, which resolves its format against a
*client* and so answers empty for any session nobody is looking at — every attached session
read as detached. A dry run flagged two live owner sessions. It now reads `list-sessions -F`
and fails closed: an unreadable tmux server counts as attached, never as reapable.

## Attached-session safety incident — DONE

Manual cleanup terminated `international-press-zone-175927` while owner reports its
`ipz-wip-triage` Claude conversation was attached. Automatic cleanup journal does not list
this IPZ session; unsafe action was manual tmux termination, not a proven timer reap.
Conversation transcript remains intact at Claude session
`19389435-1c18-4602-9935-323388f8b11e`; original tmux process/window is gone.

### Acceptance criteria

1. Disable `agent-session-reap.timer` until every criterion below passes.
2. Relaunch session UUID `19389435-1c18-4602-9935-323388f8b11e` under owner-visible
   `ipz-wip-triage`; prove named tmux session exists and has resumable conversation state.
3. Cleanup MUST bind process identity and tmux session identity across classification and
   termination. PID reuse, missing server/session, malformed output, command failure, or
   changed identity MUST keep session alive.
4. Cleanup MUST atomically prove exact identity and zero attachments before tmux removal.
   Any attachment or identity change MUST abort cleanup; cleanup MUST NOT signal a PID.
5. Deterministic regressions MUST cover real attachment, attachment after classification,
   pane/session/server replacement, simulated PID reuse, unreadable state, and helper crash.
6. Install candidate runtime, prove attached sessions survive through installed entrypoint,
   then and only then re-enable timer.

### Preserved WIP

- Worktree: `/home/user/Projects/overdeck/.worktrees/cpu-load-incident`
- Recovery transcript: `/home/user/.claude/projects/-home-user-Projects-Press-zone-wordpress-wp-content-plugins-international-press-zone/19389435-1c18-4602-9935-323388f8b11e.jsonl`
- Existing landed cleanup: `78f98264`; keep disabled, do not delete ledger/transcripts.

### Execution steps

1. Restoration owner `main`: disable timer; restore named conversation; prove attachability.
2. Hardening owner `main`: reproduce races; implement identity-bound fail-closed checks.
3. Run focused and installed tests; adversarial review; re-enable only after live proof.
4. Full module gates; commit; land; deploy landed source; repeat installed proof.


`tmux-spawn-17d97d5b-…scope` holds only leftovers of the **already-killed**
ThemeFactory tmux session: the transient daemon (101% CPU), two bg-pty hosts, a stale
`versions/2.1.226` process and two quietmode processes. Both `kill` and
`systemctl --user stop <scope>` are refused by the human-slice kill guard, which has no
override. The guard is correct in intent but over-broad: it protects a scope whose
owning tmux session no longer exists. Durable fix = teach the guard (or a reaper) that
a `tmux-spawn-*` scope with no live tmux session is reapable.

## Orphaned tmux scope cleanup — DONE

Source requirement: owner requested a durable cleanup mechanism for `tmux-spawn-*` scopes left
behind after their tmux server dies; future incidents MUST NOT require broad/manual process kills.

Acceptance criteria:

1. Only transient `tmux-spawn-<UUID>.scope` units with the exact tmux-generated description are
   eligible. Missing/malformed properties or unexpected cgroup placement MUST keep the scope.
2. Recorded pane PID MUST be absent from the exact recorded tmux server, or that server MUST be gone,
   before and after recursive scope freeze. Unreadable socket state, non-tmux PID reuse, or any matching
   live pane MUST keep the scope.
3. Bind unit invocation ID, control-group path, and opened cgroup directory before action. Revalidate
   them plus tmux pane absence after freeze; unit/pane replacement or property drift MUST keep scope.
4. Cleanup acts only through the bound cgroup FD; NEVER kill by process name or unresolved PID.
   Normal session reap MUST empty the same bound exclusive scope after atomic tmux removal so
   daemonized descendants cannot survive. Independent watchdog MUST thaw on helper death.
5. Deterministic regressions cover live tmux owner, absent owner, malformed identity, property race,
   helper crash/thaw, dry-run, and successful orphan cleanup.
6. Disable timer before candidate installation; prove installed live-owner survival and orphan cleanup,
   then land/deploy/reinstall and re-arm only after landed installed proof.

## Hardening

1. Reaper for `tmux-spawn-*` scopes whose tmux session is gone — closes the guard gap.
2. DONE — idle+detached session reap, above.
3. Investigate per-session idle burn (claude-core ~15% each while idle; quietmode
   plugin 115% across 38 processes) — this is the multiplier that makes sprawl fatal.
4. Consider a concurrent-session cap; this is at least the third recurrence.
5. LSP policy: tsserver per session on this monorepo costs ~1 GB; disable or share.

## Two defects found, not yet fixed

- `quietmode/start.mjs` (pid 437215) holds a steady 100% of one core inside a live session;
  38 quietmode processes drew 115% combined. Task #2.
- `deckctl units apply` aborts on `agent.slice`, which `packaging/deploy-local.sh` installs as
  a regular file while `units apply` demands a symlink. Two owners for one unit; the reap
  units had to be linked by hand. Pre-existing, unrelated to this incident.
- The kill guard resolves only literal words, so `tmux -S "$S" kill-session` walks straight
  past it while the same command with the socket spelled out is refused. Task #3.

### Task #3 acceptance delta

1. Deny every destructive tmux server/session/window/pane command from agent execution; raw
   tmux destruction has no safe pathname authorization because socket aliases and check/use races
   prevent identity proof.
2. Enforce after shell expansion through the inherited PATH shim, not only by parsing PreToolUse
   source text. Hosted Claude sessions MUST NOT receive the shim's human-at-TTY bypass.
3. Cover variables, quote concatenation, wrappers, nested shells, absolute paths, unique command
   abbreviations, socket aliases, and direct argv. Unknown or malformed destructive forms fail closed.
4. Preserve owner tmux commands outside agent runtimes. Inside agent runtimes, allow only `tmux -V`:
   measured tmux behavior proves custom aliases can shadow both built-in aliases and exact canonical
   command names, so no server command can be classified as non-destructive before execution.
5. Install atomically with rollback, prove the actual installed hook and shim, then land, deploy, and
   repeat installed proof.

## Task #6 — disk-fill notifier CPU/memory burn

Acceptance criteria:

1. Act only on exact `disk-fill-notify.service` after binding its unit, MainPID, cgroup, and command.
   NEVER signal by process name or touch owner sessions.
2. Contain current load by stopping only that service; verify inactive state and measure CPU/memory relief.
3. Locate canonical owning source before changing behavior; NEVER reconstruct deleted code from guesses.
4. Reproduce the retirement defect, add a deterministic regression, install corrected state atomically with
   exact rollback, and prove the obsolete unit remains absent.
5. Land/deploy reviewed source, repeat installed proof, and NEVER re-arm the superseded notifier.

Preserved state and rollback:

- Exact unit: `disk-fill-notify.service`; observed MainPID `2726887`, Python 3.14 executable,
  command `/usr/bin/python3 /home/user/.local/bin/disk-fill-notify`.
- Initial accounting: `MemoryCurrent=11691462656`, `CPUUsageNSec=24755004733000`.
- Original unit target is preserved at
  `~/.local/state/overdeck/rollback/disk-fill-notify-20260812/disk-fill-notify.service`.
- Canonical contract is `modules/monitor/SPEC.md`: system-monitor supersedes and retires both legacy
  notifiers. Correct rollback restores the recorded unit link only; it does not invent the missing script.

## Current receipt

- `ipz-wip-triage` restored with exact Claude UUID; owner attachment proven.
- Timer remained disabled throughout attached-session candidate validation.
- Candidate removes direct PID signals and requires launch-time UUID identity.
- pidfd + `SIGSTOP` candidate was rejected: tmux resumes stopped pane leaders.
- Replacement uses an exact per-session cgroup freezer plus an out-of-scope crash watchdog.
  Helper refuses shared/unrecognized scopes, binds pidfd + start ticks + cgroup + tmux fingerprint,
  freezes before atomic zero-attachment removal, and always thaws.
- New human sessions launch in unique `human-agent-<UUID>.scope`; confined and unsafe launchers
  already create unique eligible scopes. Legacy/shared sessions remain ineligible.
- Exact-worktree regressions pass: reaper safety (including helper `SIGKILL` thaw),
  `run-all.sh agent-session` 5/5, `run-all.sh human-session` 3/3, ledger 85/85, human
  launcher 18/18.
- Review-found ledger collision is fixed: full UUID IDs, exclusive reservation/publication,
  retry on collision, no overwrite. Human launcher now refuses any pre-existing prebound tmux
  target instead of accepting or retagging it. Deterministic regressions cover both paths.
- Review-found runtime replacement race is fixed: helper now binds classified runtime PID + start
  ticks with pidfd, proves scope membership, freezes recursively, and revalidates runtime identity
  before the atomic tmux close. Stale runtime identity regression passes.
- Exact reaper test and both session clusters pass after the fix; independent adversarial review
  is clean.
- Candidate bin/lib runtime was live through `~/.claude`; installed CLI proved a detached eligible
  synthetic session becomes non-reapable while a real tmux client is attached. Candidate service
  ran with `Result=success`; real-ledger dry run found zero eligible sessions.
- A concurrent Overdeck deploy advanced the deploy clone to `dd4b4260` and correctly repointed
  `~/.claude/bin`/`lib` away from the unlanded candidate. Timer was immediately disabled again;
  its one intervening run emitted no reap rows and exited cleanly. At that checkpoint timer state was
  `not-found` / inactive; it remained disabled until landed deployed provenance contained the fix.
- Bare full-suite runner correctly refused on workstation because it includes two exhaustion-class
  dangerlab suites. Both lab-only suites passed in dangerlab (14/14 shim gate plus forkbomb suite).
  Candidate merged 55 current `origin/main` commits without code conflict; both focused clusters
  remain green.
- Broad safe sweep: 71 passed, 13 baseline failures, zero path overlap with this branch's 12-file
  delta. Failures are stale unrelated contracts/config (`agent-build-path`, `agent-unsafe`, CPU/local
  dispatch, remote build, seat slice), six Bun-only prompt tests incorrectly launched by the generic
  Node runner, and Trello timing. `agent-build-path` reproduces unchanged on deployed `origin/main`.
  These do not invalidate the focused reaper/ledger/human-session gates; none is suppressed.
- Hardening landed on main as `dc8b1c473` and deployed successfully from that exact clean commit.
  Installed `~/.claude/bin/agent-sessions`, reader library, service, and timer all resolve into the
  landed deploy clone.
- Final installed-entrypoint attached-client proof passed against landed runtime:
  `installed-entrypoint-attached-survival: ok`.
- Landed service completed with `Result=success`, emitted no reap/error rows, and timer is now
  `enabled` + `active`. Cleanup is armed only after installed proof, satisfying criteria 1–6.
- Post-arm load is 9.88/11.45/12.28 on 16 cores; CPU PSI avg60=18.03 and memory PSI remains zero.
- Orphan-scope candidate binds exact unit invocation/cgroup inode, proves pane absence before and after
  recursive freeze, and empties only the bound cgroup. Normal session reap now empties daemonized
  descendants after atomic tmux close. Recovery watchdog survives its own `SIGKILL`, distinguishes
  clean helper exit from helper `SIGKILL`, thaws when the exact tmux identity remains, and cleans an
  independently re-proven orphan after helper death.
- Deterministic candidate tests cover live panes, pane appearance, malformed/unreadable tmux and
  systemd state, owner PID reuse, unit-property and cgroup-directory replacement, dry-run, recursive
  descendants, helper/watchdog `SIGKILL`, and CLI ledger-write failure after successful cleanup.
  Focused reaper test passes; session clusters pass `5/5` and `3/3` (agent-session cluster required
  its documented out-of-jail invocation; the in-jail refusal was rerun correctly, not suppressed).
- Candidate installed through `~/.claude/bin` + `~/.claude/lib` worktree links after timer removal.
  Installed entrypoint proof created one exact live-pane scope and one absent-owner orphan scope in the
  same run: live scope survived, orphan scope was recursively removed, result
  `installed-reaper-live-pane-and-orphan: ok`. Temporary fixture and proof script were removed.
- Active timer is `not-found` / inactive pending landed deployment. Concurrent deploys may repoint
  Claude runtime links; installed proof asserted candidate realpath before invocation rather than
  trusting link state.
- Independent review required three adversarial rounds. Fixed findings: recovery freezes before
  revalidation; empty/malformed or changed live tmux identity keeps scope; ambiguous cgroup-kill
  failure stays watchdog-armed; ledger intent is locked, file-flushed, rename-atomic, and directory-
  fsynced before destruction; linked windows fail closed through atomic `window_linked=0` predicate.
  Final independent verdict: clean.
- Deploy reported shim drift in unrelated active worktrees. Live shims match `origin/main`, so this
  does not contaminate deployed provenance; do not alter other owners' preserved WIP. Track through
  each owning worktree rather than treating the warning as benign or suppressing it.
- Orphan cleanup landed directly on main as `db23a26d703fea99517914888e9acbd43862bbcf` after
  focused regressions and final independent review passed. Deploy clone resolves to that exact commit.
- Landed installed-entrypoint proof passed: live pane survived and exact absent-owner scope was removed
  (`landed-installed-reaper-proof: ok`). Service completed with `Result=success` / `ExecMainStatus=0`;
  timer is `enabled` and `active`.
- General `packaging/deploy-local.sh` stopped after backing up then removing
  `~/.claude/buildbox-hosts.json`; `deckctl sync apply claude buildbox-hosts.json` failed closed because
  the source was absent. Restored the exact `20260811T151731Z` backup with mode `0600`; linked only the
  landed reaper units manually. This separate deployment defect is unresolved and not suppressed.
- Post-arm load remained excessive: 26 active `tmux-spawn-*` scopes were retained because cleanup
  could not prove them orphaned. Initial consumer sample found active Claude workers plus RustDesk.
- Task #2 root cause is confirmed in QuietContext storage: one worker accumulated a 1.03 GB DB plus
  540 MB WAL, including a 104.7 MB single chunk and 618 MB trigram index, while synchronous FTS
  `optimize` ran every 50 inserts and on close. Its process tree exited naturally; no owner session
  was signalled during this investigation.
- Isolated QuietContext candidate caps sources at 8 MiB before parsing/indexing, byte-caps Markdown,
  plain-text, and JSON chunks, and removes synchronous full-index optimization. Remote focused tests
  pass 3/3; full store suite passes 124/124; TypeScript/build/bundle assertions pass. Independent
  review is executing before atomic installed-runtime proof.
- QuietContext task #2 subsequently landed as `694821f4a4ef49b6495483a796e50fe7e03c833d`;
  landed source is installed and actual MCP entrypoint rejection/index/search proof passed.
- Task #3 candidate now enforces tmux destruction at two layers: PreToolUse catches static and
  absolute-path forms; new inherited `tmux` PATH shim evaluates expanded argv and never grants the
  hosted-human exemption. Regressions pass 82/82; shared shim invariants pass 12/12 with only the
  documented dangerlab-only fork test skipped.
- Final independent review found a remaining custom-alias bypass: tmux accepts abbreviated
  `command-alias` option names, and a pre-existing custom alias can override a trusted built-in alias.
  Isolated-server measurement confirmed both `display` and exact canonical `list-sessions` can be
  shadowed. Therefore no server command spelling is intrinsically safe: candidate must deny every tmux
  server command inside agent runtimes, allow only `tmux -V`, and preserve unguarded owner tmux use only
  when runtime ancestry plus human-session classification prove the caller is outside an agent.
  Candidate remains uninstalled; live runtime and rollback state are unchanged.
- Final independent review rejected the PATH-only design on three grounds: absolute `/usr/bin/tmux`
  bypass, forgeable same-UID `human.slice` classification after reparenting, and fail-open behavior when
  the guard module is missing. Missing-guard execution now fails closed. The first two findings are
  architectural: a same-UID PATH shim is defense-in-depth, not an unbypassable authority boundary.
  Task #3 remains uninstalled and MUST move enforcement to a runtime boundary that absolute paths and
  reparenting cannot escape before shipment.
- Task #6 root cause is confirmed in `modules/monitor/install.sh`: the system-monitor contract retires
  both legacy notifiers, but the installer disabled only `mem-pressure-notify.service`, deleted the
  `disk-fill-notify` script, and left its already-running service alive indefinitely. That deleted-code
  Python process reached 11.7 GB cgroup memory and 24,755 seconds cumulative CPU.
- Exact bound unit `disk-fill-notify.service` / invocation
  `dd23a62b0a3e49ba8629c1965d5a0878` was stopped without touching any other process. The service is now
  `not-found` / inactive / dead. `systemctl disable` removed its repo-owned unit symlink before reporting
  the already-stopped unit not loaded; rollback was immediately reconstructed from the previously read
  exact target at `~/.local/state/overdeck/rollback/disk-fill-notify-20260812/disk-fill-notify.service`.
- Task #6 candidate disables both legacy services before removing both scripts and unit links. Initial
  dry-run regression passed 1/1; monitor tests passed 159/159, agent-guard tests 33/33, compile check and
  installer dry run passed. Independent review then found five blocking gaps: disable failures were
  ignored, dangling symlinks survived, dry-run home differed from live, uninstall restored only one unit,
  and the regression asserted labels rather than effects.
- Shell transaction review is NOT clean despite green tests. Six blocking defects remain: partial staging
  copies can be mistaken for valid backups; archive publication is not transaction-safe; reruns overwrite
  original service-state receipt; pipeline-subshell rollback status is false; restore rollback omits prior
  service state; tests do not inject copy/remove/reload/publication/restore failures or real `not-found`.
- Task #6 stdlib replacement passed 9 focused + 200 monitor + 33 guard tests, but independent review
  rejected shipment on six remaining defects: rollback generation publishes after destructive mutation;
  no post-removal/reload inactivity proof; `linked`/`failed` service rollback is not exact; archived objects
  lose UID/GID; recreated destination directories become root-owned; required removal/publication/enable/
  rollback/crash fault injections are absent. Candidate remains uninstalled.
- Sixth-review corrections implemented: archive flock serializes retire/restore and first receipt publication;
  rollback restores captured originals before services and never publishes stale backup copies; absent directory
  metadata is skipped; symlink timestamps and supported xattrs are copied/restored. Seventeen focused tests pass.
- Seventh adversarial review found three rollback defects: retirement's inner capture failure left captures for
  outer double-restore; failed restore left newly published files whose original destination was absent; capture
  cleanup did not consume entries incrementally, so a later cleanup failure retried deleted captures and could skip
  service rollback. All three are corrected with state-consuming capture helpers, absent-destination unlink, and
  rollback failure aggregation that always attempts service-state restoration. Deterministic regressions added;
  nineteen focused tests pass. Latest broad gates pass: 177 monitor pytest, 33 guard unittest, Python compile,
  installer/uninstaller shell syntax. Eighth independent adversarial review has not inspected code yet: first launch
  lacked its local persona, second parsed the persona delimiter as a CLI option; third launch uses the global persona
  plus explicit option terminator. That reviewer then incorrectly attempted nested dispatch and produced no verdict.
  Direct independent Opus review found two defects: restore rollback can delete a concurrent post-publication
  replacement because it did not bind the published leaf identity; failed restore left transaction-created target
  directories that were originally absent. Both are corrected: publication identities gate rollback unlink; created
  directories are inode-bound and removed deepest-first. Automated security review also flagged pathname re-traversal;
  bound directories now walk from a validated home FD with `openat` + `O_NOFOLLOW` rather than reopening absolute
  paths. Two deterministic regressions added; twenty-one focused tests pass.
- Ninth review found four durability/rollback defects: capture rename can precede unrecorded fsync failure; leaf
  publication can precede unrecorded fsync failure; capture deletion can become irreversible before its fsync; failed
  restore leaves archived metadata on pre-existing directories. Current action: move durability sync to transaction
  state that already records each mutation, make cleanup the commit boundary rather than a rollback-capable phase,
  restore original directory metadata on failure, add fault-injection regressions, then re-review. All four are fixed:
  capture/publication state is recorded before durability sync; capture cleanup is the explicit commit boundary rather
  than a rollback-capable phase; failed restore restores pre-existing directory metadata. Two fault regressions added;
  twenty-three focused tests pass.
- Tenth review found two directory-creation transaction defects: partial creations are lost when `ensure_directories`
  raises before returning its journal; a directory recorded absent may appear concurrently and be accepted/mutated.
  Current action: pass a caller-owned incremental creation journal, exclusively claim every expected-absent component
  with `mkdirat`, reject concurrent presence, add deterministic regressions, and re-review. Both are fixed with a
  caller-owned incremental journal and exclusive expected-absent claims. Two regressions added; twenty-five focused
  tests pass.
- Eleventh review found two remaining directory races: a successful `mkdirat` is journaled after fallible sync/open;
  expected-present directories are not compared to their recorded inode before mutation. Current action: journal the
  created inode immediately after the exclusive claim, validate every expected-present component against its recorded
  identity, retain validated descriptors through publication, add regressions, and re-review. Both are corrected: failed
  post-claim open/fstat removes the exclusive claim; successful claims are journaled before parent sync; every expected-
  present component is dev/inode validated. Two regressions added; twenty-seven focused tests pass.
- Twelfth review found three defects: capture transaction state is memory-only across process crash; object identity can
  miss same-inode/same-size writes with restored mtime; ownership restoration after mode can clear setgid/setuid bits.
  Current action: add a durable fsynced intent manifest recovered under the archive lock, bind content with ctime/digest,
  apply ownership before mode, add crash/content/setgid regressions, and re-review. All three are addressed: a durable
  fsynced manifest records backup/capture/publication/directory/service state and is recovered under the archive lock;
  SHA-256 binds content; ownership precedes mode restoration. Crash/content/setgid regressions added; thirty focused
  tests pass.
- Thirteenth review found three manifest state-machine gaps: capture deletion precedes durable committed phase; restore
  publication precedes durable publication intent; created directories are journaled only after creation completes.
  Current action: persist commit before cleanup, persist expected portable publication identity before rename and
  reconcile both capture/destination states, atomically claim directories through journaled hidden siblings, add crash
  regressions at every boundary, then re-review. All three manifest boundaries are corrected; thirty focused tests
  pass.
- Fourteenth review found two gaps: generic missing-component creation skipped the durable callback; committed cleanup
  did not bind capture identity. Both are corrected: every creation journals before parent sync; every capture's portable
  identity is persisted after capture and verified before deletion. Thirty focused tests pass.
- Fifteenth review found three recovery defects: rollback recovery did not validate persisted capture identity; committed
  cleanup could wedge after an unlink-before-manifest-clear crash; backup validation accepted `..`. Current action:
  validate captures before recovery promotion, persist per-capture cleanup completion/accept proven absence, strictly
  confine backup names/inodes beneath archive, add regressions, and re-review. All three are corrected; thirty focused
  tests pass.
- Sixteenth review found four defects: `current` accepts dot/symlink generations; capture validation+unlink remains
  raceable; cleanup journals before directory sync; recovery accepts unsafe `created` paths. Current action: strictly
  validate/open generation by archive FD, atomically move verified captures to transaction-owned trash before deletion,
  fsync before journaling completion, validate every manifest-relative path, add regressions, and re-review. All four
  are corrected; thirty focused tests pass.
- Seventeenth review found three gaps: expected-absent leaf capture names can be unjournaled; recovery treats a
  journaled-but-not-durable created directory as fatal; directory metadata accepts empty/dot paths targeting home.
  All three are corrected. Capture names are durably journaled before rename and normalized to `None` after a
  proven absent leaf; missing journaled created directories are accepted as already cleaned; empty/dot directory
  receipt paths are rejected. Four direct regressions added. Python compile, 34 focused tests, 192 full monitor
  tests, 84 kill-guard tests, and installer/uninstaller shell syntax pass without warnings. Live service remains
  `not-found` / inactive / dead with `MainPID=0` and empty cgroup. Eighteenth independent adversarial review found
  two shipping blockers outside the transaction owner: root install and uninstall follow user-controlled home symlinks,
  allowing privileged writes/deletion outside home. Both are fixed through descriptor-relative no-follow operations
  with ownership checks; symlink regressions prove no outside write/deletion. Nineteenth review found three remaining
  defects: directory creation can race into `fchown` of a substituted inode; failed first retirement leaves its staged
  generation advertised by `current`; a crash between `mkdir` and journaling leaves residue. Current action: drop helper
  privileges before target-home access, split generation staging from committed `current` publication, and journal
  creation intent. Twentieth review proved those fixes incomplete: crash between `current` publication and committed
  manifest wedges recovery; restored-directory substitution can still receive privileged `fchown`; identity-less intent
  can delete a concurrent directory. Current action: eliminate restore-time directory creation entirely (retirement never
  removes directories), fail closed if externally removed, and add a recoverable publication phase. Twenty-first review
  found four defects, two shipping blockers: temporary-file metadata is applied by pathname after its descriptor closes;
  recovery lacks recorded directory dev/inode and deterministically wedges. It also found identityless managed-link
  deletion and portable-only capture cleanup identity. Twenty-second review found two committed-cleanup defects:
  crash after trash unlink but before manifest update wedges recovery, and committed recovery validates capture names
  too late, allowing absolute-path manifest entries. Those and a later source-backup pathname TOCTOU are fixed with
  early capture validation and retained `O_NOFOLLOW` source descriptors. Latest reviews found three more blockers:
  identities omitted ownership/xattrs; privileged backup copies were unbounded; uninstall left installed user services
  and links active. Ownership/xattr identity, bounded copy, fail-closed managed-link publication, target-directory
  ownership, pre-hash admission, xattr preservation, and absent-empty restore filtering are implemented; 37 focused
  tests pass. The legacy root uninstall receipt gap predates this incident change and is recorded but stays outside the
  exact notifier-retirement scope; changed user-home removals are identity-gated. Twenty-fifth review found three defects:
  exact existing managed symlink ownership was unchecked; symlink xattrs were omitted; regular-file identity hashing
  reopened an admitted path. All three are fixed with uid/gid validation, symlink xattr copy, and descriptor-bound
  O_NOFOLLOW identity hashing with pre/post size checks. Twenty-sixth review found three more defects: managed unlink
  did not validate ownership; restore publication copied regular sources without inode/size binding; symlink xattr errors
  could be ignored. Fixed with uid/gid unlink validation, descriptor-bound 16 MiB exact restore copy, strict object-type
  admission, and fail-closed symlink xattr propagation. Twenty-seventh review found empty restore indexed absent parent
  descriptors and symlink backup still suppressed xattr publication failures. Fixed by explicitly journaling/skipping
  proven absent source+destination pairs and making backup xattr propagation fail closed. Final independent review: CLEAN.
  Latest gates: focused 37/37, monitor 195/195, kill-guard 84/84, Python compile, shell syntax, diff check, and installer
  dry-run clean. Full installer live attempt failed closed before notifier mutation because existing managed user links correctly
  target the deployed checkout rather than this candidate worktree; no object was overwritten. Current action: install only
  the reviewed notifier-retirement seam through its exact privileged entrypoint. Exact seam attempt failed closed before
  mutation because live `mem-pressure-notify.service` has valid `UnitFileState=linked`, previously unsupported. Added exact
  linked-state capture/validation/rollback semantics passed narrow review, but exact install exposed systemd behavior:
  `disable --now` removes a linked unit symlink then exits 5. Transaction rollback could not restore because mutation
  happened inside failed systemctl before capture; exact symlink was manually restored from the immutable backup and
  live state re-proved loaded/linked/inactive. Fixed sequencing: enabled units use disable; linked/disabled units stop only
  when active, leaving file removal to identity-bound capture. Narrow review CLEAN. Exact reviewed transaction then recovered
  the durable manifest and completed live retirement. Installed proof: both units load=not-found, inactive/dead, MainPID=0,
  empty cgroups; all four notifier paths absent; zero notifier processes; immutable current generation
  `generation-3a7cb44ecda047fd98c8024db458bf5a`; no transaction manifest; rerun preserved the same generation. Post-install gates:
  focused 37/37, monitor 195/195, kill-guard 84/84, compile/shell/diff/install-dry-run clean. Committed `2687a8e75`,
  merged current origin/main as `77bb38175`, reran post-merge gates (37/37, 231/231, 84/84), and direct-landed
  `77bb38175` to origin/main. Canonical deploy completed successfully and deployed current origin/main
  `698ff3a7b171a26552d16af61ad7b11a4c815702`; deploy clone HEAD matches origin/main. Buildbox registry SHA-256 remains
  `61cd599c5987be4b738b00e450d66ebd5df1a7ead25d44c799f55f0f37829082`. Landed runtime reproof: both notifier units
  load=not-found, inactive, MainPID=0, empty cgroups; all four notifier paths absent; zero notifier processes; immutable
  generation remains `generation-3a7cb44ecda047fd98c8024db458bf5a`; no transaction manifest. Task #6 DONE.
- Live containment re-proved after tests: `disk-fill-notify.service` is `not-found` / inactive / dead,
  `MainPID=0`, empty cgroup. No owner process/session was signalled.
- Task #6 implementation is replacing the unsafe shell transaction with one stdlib transaction owner.
  Required invariant: stage and verify before mutation; atomically publish immutable first receipt/archive;
  rollback files, daemon-reload, then every prior service state; any rollback failure must be visible.
- 2026-08-13 task #6 is DONE. Task #3 resumed under main in isolated worktree `/home/user/Projects/overdeck/.worktrees/tmux-runtime-boundary`.
- Architecture exploration found that the only robust seam is the existing per-seat UID isolation module. Local hosted sessions currently bypass it and run owner-owned tmux.
- Owner selected the recommended architecture: deepen the seat authority module. Local and remote hosted-session adapters MUST share its dedicated-UID isolation, mediated terminal control, generation-bound exit receipt, root installation checks, and lifecycle ownership. Existing owner-UID sessions remain untouched and attachable during migration.
- 2026-08-13 execution request: implement selected architecture in `/home/user/Projects/overdeck/.worktrees/tmux-runtime-boundary`. Read relevant source/tests completely. Use strict TDD: deterministic RED tests + expected-failure receipt before minimal production changes. Do not spawn agents, commit, install live, or touch active sessions. Run focused tests only. Final handoff MUST list changed files, RED/GREEN receipts, unresolved risks, and exact live-install steps.
- Worker: this session. Status remains ACTIVE while implementation executes.

### Task #3 acceptance delta — seat authority runtime boundary

1. New local hosted sessions MUST run under a dedicated non-owner UID. Owner UID MUST control them only through a mediated terminal interface; direct absolute-path tmux execution inside hosted runtime MUST remain outside owner authority.
2. Terminal create/attach/stop operations MUST bind one declared seat generation. Missing, malformed, stale, replaced, or mismatched generation identity MUST fail closed.
3. Exit receipt MUST bind seat ID, generation, runtime identity, and exact exit status. A stale/replayed receipt MUST NOT finalize a newer generation.
4. Root installation MUST validate source ownership, file type, mode, destination ownership, dedicated account identity, and installed byte identity before activation. Any failed proof MUST leave prior install active and report failure.
5. Migration MUST affect new launches only. Existing owner-UID tmux sessions MUST remain untouched and attachable; tests MUST use isolated fixtures and MUST NOT inspect, signal, stop, rename, or replace active sessions.
6. Local and remote adapters MUST share one seat authority contract. Existing remote validation MUST remain green.
7. Scope this execution to deterministic focused tests. Do not commit or install candidate runtime.

- Coordinator rejected the first fixture-only shell module as a stub. `modules/harness/seat/seat-authority.sh` and its test were deleted completely; no orphan remains. Existing plan history is preserved.
- Corrected architecture deepens existing `seat_scope_entry.py`, `seat_implementer_exec.py`, and `seat_tmux_mediator.py`; no parallel authority module exists.
- RED receipts: real scope test failed import because generation manifest/receipt APIs were absent; tmux retention test failed because existing config lacked `remain-on-exit on`; mediator generation and receipt cases were added before their production wiring.
- GREEN receipt: 58 scope-entry + 12 implementer-exec + 3 mediator tests pass (73 focused tests total). Python compile, JavaScript syntax, and diff whitespace checks pass cleanly.
- Complete vertical slice: root authority writes a strict generation manifest into root-owned per-seat control storage plus an untrusted operator-readable routing hint; implementer exec validates trusted seat/generation/socket/dedicated UID before dropping privileges; tmux starts on the manifest-bound socket under the dedicated implementer UID; mediator `has-session`, `attach-session`, stop, and internal probes require the exact generation; dead panes are retained and mediator `receipt` writes exact tmux `pane_dead_status` into a generation-bound atomic root-owned receipt.
- Legacy owner-UID human-session launcher was not modified, so already-active owner sessions remain untouched and attachable. Candidate remains uninstalled and uncommitted per owner scope.
- Existing monolithic `seat-remote.test.mjs` passed the changed attach fixture after adding its manifest, then stopped at unrelated live host firewall drift `netns-nft-drift`. This external host state is not suppressed; focused deterministic source tests remain green.

- Independent security review rejected shipment with six high/medium blockers: actual local launch still bypasses seat authority; mediator binds only socket pathname; privileged installation is non-atomic; caller controls generation; manifest read is neither root-trust-checked nor inode-stable; exit receipt has no production lifecycle owner. Remote attach also trusts an operator-writable generation hint. Candidate MUST NOT install or land until all are fixed and re-reviewed.
- Full local path and tests were read. `_agent-session-tmux` previously started owner-UID tmux in `agent.slice`, wrote an owner-controlled status file, and accepted arbitrary runtime/cwd. Existing remote scope entry requires account profile, managed checkout, and network namespace. Local adapter now lives inside same root authority; no parallel authority module exists.
- Blocker 1 complete in candidate, uninstalled and uncommitted. Actual `_tmpjail-shim.sh` → `_agent-session-tmux` path delegates new hosted launches to root `seat_scope_entry.py`; authority mints generation, resolves dedicated implementer UID, grants narrow ACL traversal/execution, starts tmux as implementer, publishes generation-bound exact exit receipt, and returns exact pane status. Existing active owner-UID sessions remain untouched.
- Socket path-length RED: full ledger ID in `sock/<id>/tmux.sock` exceeded Linux Unix-socket limit. Fixed with launcher-validated SHA-256 routing key while full ledger ID remains in manifest/receipt. Recovery identity now crosses authority contract and is set in same tmux transaction as session creation.
- RED receipts: ACL regression failed because authority granted no implementer path access; ledger integration initially failed 2/79 because authority fixture was absent; production-shaped integration exposed overlong socket path and missing recovery binding.
- GREEN receipts: Python compile and shell syntax clean; scope/implementer/mediator focused set 74 passed + 10 subtests; launcher authority contract passed; ledger integration 85/85 passed, including terminal survival, recovery identity, socket persistence, detached classification, recovery command, and `agent.slice` confinement.
- Changed blocker-1 files: `modules/workstation/claude/lib/seat_scope_entry.py`, `modules/workstation/claude/bin/_tmpjail-shim.sh`, `modules/workstation/claude/bin/_agent-session-tmux`, `modules/workstation/claude/tests/seat_scope_entry_test.py`, `modules/workstation/claude/tests/agent-session-local-authority.test.sh`, `modules/workstation/claude/tests/agent-session-ledger.test.sh`.
- Deferred review blockers remain: mediator socket/server/cgroup identity binding; atomic privileged install/rollback; descriptor-relative root manifest reads; remote attach generation trust. Candidate MUST NOT install or land until requested follow-on security work completes.

- Coordinator expanded active scope: complete blockers 2, 4, 5, and remote attach trust as one identity-integrity TDD cycle. Preserve blocker-1 local adapter WIP. Root authority MUST mint generation; trusted manifest reads MUST be descriptor-relative with `O_NOFOLLOW` and validate root owner, mode, link count, size, and stable inode; mediator operations MUST bind socket dev/inode, tmux server PID start time, and expected cgroup; remote attach MUST resolve generation only from trusted manifest, NEVER operator hint. Add deterministic substitution, race, and replay RED tests. Do not install or commit.

- Identity-integrity cycle implemented for blockers 2, 4, 5, and remote attach trust. Root authority now mints remote generation and rejects caller `--generation`; trusted manifest reads use parent/leaf descriptors with `O_NOFOLLOW`, require regular file, root owner outside test mode, mode `0600`, link count 1, bounded size, and stable descriptor identity/content metadata before/after parse.
- Trusted manifest finalization now records socket dev/inode, tmux server PID start time, and unified cgroup after launch. Local and remote creation finalize only after tmux/process verification. Mediator requires finalized identity and revalidates socket type/dev/inode, server start time, and cgroup before `attach-session`, `has-session`, `kill-server`, `list-panes`, or receipt publication. Stale generation still fails before tmux.
- Remote attach/status/stop no longer read operator-owned `state_dir/session.json` or pass operator-derived generation. Mediator resolves current generation only from root-owned trusted manifest. Direct generated-command proof: `remote-attach-trusted-manifest: ok`; poisoned operator hint regression added to `seat-remote.test.mjs`.
- RED receipts: hard-linked and group-readable manifests were accepted; replaced socket identity was unsupported; remote launch accepted caller generation; remote attach consumed operator hint. Deterministic server start-time and cgroup replacement tests added.
- GREEN receipts: Python compile and JavaScript syntax clean; focused scope/implementer/mediator suites pass 79 + 10 subtests; direct remote attach trust proof passes. Official `seat-remote.test.mjs` retry remains externally BLOCKED: required `fleet` build host unavailable, gate exit 97, local fallback correctly refused. No finding suppressed.
- Candidate remains uninstalled and uncommitted. Blocker-1 local adapter preserved. Atomic privileged installer blocker remains deferred.

- Coordinator added final blocker 3. Privileged install MUST stage one root-owned immutable version from stable source descriptors; verify source ownership/type/mode/hash stability, staged hashes/modes/ownership, sudoers, manifest, and full install-check before one atomic activation switch. Failure at copy/hash/manifest/sudoers/install-check/switch MUST preserve prior active version and report rollback state. Mixed-version activation MUST be impossible. Add deterministic boundary fault tests. Classify four `seat-remote.test.mjs` unused diagnostics against exact base. Do not install or commit.

- Blocker-3 RED cycle started. Existing `buildSeatScopeEntryInstallScript()` directly overwrites five modules, four executables, manifest, then sudoers before install-check. Any boundary failure leaves mixed active bytes. Existing wrappers hardcode separate `/usr/local/lib/overdeck/*.py` paths; therefore staging alone cannot provide one atomic activation switch.
- Added transactional installer harness controls and `seat-scope-transactional-install.test.mjs`. RED receipt from sandboxed Node runner: status 1; `failure at copy preserves prior active version` fails because current installer ignores fault and mutates direct destinations. Required remote-only Node gate remains unavailable; no local gate bypass used.
- Correct production shape: immutable root-owned version directory containing complete executable/module/manifest set; stable privileged entrypoints MUST all resolve one root-owned activation pointer; sudoers MUST authorize only stable entrypoints; full staged install-check MUST run against candidate before pointer exchange; failed pointer exchange MUST preserve prior target and print rollback state. DO NOT implement per-file rename transaction: it cannot prevent mixed versions.
- Remote diagnostic base comparison: candidate diff in `seat-remote.test.mjs` is confined to attach-generation poisoning coverage (removed now-unused local `generation`; added negative assertions). No four diagnostics are visible in the source diff. Exact runner classification remains pending because official remote test host is unavailable; MUST compare its diagnostics against base with same runner when reachable.

- Local review added blockers A/B. A: local root adapter MUST derive socket from authenticated operator home plus validated seat ID/routing key; reject caller mismatch before unlink/chown/chmod. Cwd and executable ACL targets MUST be confined through fixed-root descriptor-safe validation before root mutation. B: exit receipts MUST be generation-owned; new generation invalidates prior current receipt, stale generation cannot overwrite newer receipt, including manifest-validation/publication race. Preserve installer RED WIP. Do not install or commit.

- Local blockers A/B fixed through RED/GREEN. A: `expected_local_socket()` derives fixed agent-session socket from authenticated operator home + validated seat ID SHA-256 routing key; mismatch fails before user provisioning, unlink, chown, chmod, or ACL. Descriptor-relative `O_NOFOLLOW` walk confines cwd beneath operator home and executable leaves beneath operator home or trusted system executable roots before ACL mutation. B: manifest replacement and receipt publication share root-owned flock; new manifest invalidates current receipt; receipt first publishes immutable `exit-<generation>.json`, revalidates trusted manifest, then updates current `exit.json`. Hostile inode replacement between validation and publish fails without current receipt.
- Final independent review rejected the reported transactional completion: live privileged files still mutate before activation, the activation marker controls no runtime entrypoint, existing version directories are overwritten, and injected failures occur before mutation rather than proving rollback. It also found local tmux lost exact `agent.slice` confinement, remote operations still omit expected generation, the root entrypoint remains environment-overridable, and installed manifest/hash verification remains pathname-raceable. Candidate MUST NOT install or land.

## Next executable action

## Superseded (2026-08-15)

Task #3's open runtime-bound redesign (CPU-load angle) is superseded by [Idle language-server
reaper class](2026-08-14-lsp-reaper-class.md), which found and fixed the same root cause
(idle per-session LSP processes accumulating, not a PATH-interception problem): landed
`c74ffba55`, reaper armed `ENFORCE=1`, 45 idle language servers reaped, load 75 -> ~25.

The seat-authority candidate the review cycle below produced is a separate, still-live thread:
its uncommitted WIP was salvaged (tag `archive/wip-Projects-overdeck-.worktrees-tmux-runtime-boundary`,
commit `147c78fb7`) and restoration/continuation is tracked in
`2026-08-15-fire-session-harvest.md`. This file stays as the record of the incident, the
CPU-load approach that was replaced, and the security-review history for the seat-authority
candidate below.

Fix all final review findings with mutation-boundary fault tests and full focused regression. Require another independent clean review before any live installation.

- Transactional installer GREEN. RED: direct overwrite installer ignored injected `copy` fault, mutated live destinations, and failed prior-version preservation (1 deterministic failing transactional test). GREEN: immutable content-addressed version staging plus one root-owned activation marker; stable wrappers resolve one version; complete candidate manifest/sudoers/install-check validation precedes activation. Transactional suite: 7/7 passed — 6 injected failures (`copy`, `hash`, `manifest`, `sudoers`, `install-check`, `switch`) each exited nonzero, preserved `prior`, and reported `rollback=preserved`; success activated one 64-hex version and reported `rollback=not-needed`. Standalone install harness passed.
- Final focused receipts: Python compile clean; JavaScript syntax clean; authority/implementer/mediator suites exit 0; launcher authority contract passed; ledger integration 85 passed, 0 failed. Ledger idempotency assertion now filters the named fixture session, preventing ambient session rescues from corrupting its count. `git diff --check` clean.
- Remote diagnostics attribution against exact base `7a2e478fc6472483758c5f970475d19bc6e95a8c`: zero unused declarations in base, zero in candidate, zero introduced. Official remote suite remains externally unavailable because required `fleet` host is unavailable; no local fallback or suppression used.
- Candidate remains uninstalled and uncommitted, per owner scope.
- Final review reopened six blockers. MUST prove with deterministic RED/GREEN: (1) publish complete immutable versions exclusively; inject faults after each mutation; use one atomic root-owned activation pointer for every privileged entrypoint; rollback activation/service state after post-mutation failures; NEVER mutate legacy runtime destinations. (2) Local root authority MUST launch tmux in exact `agent.slice` systemd scope and verify recorded cgroup. (3) Remote attach/status/stop/receipt MUST carry expected trusted generation returned by launch, never resolve current generation. (4) Remove `OVERDECK_SEAT_SCOPE_ENTRY`; use canonical root entrypoint only. (5) Read installed authority manifest and each hash through one bounded descriptor using `O_NOFOLLOW` plus stable `fstat` validation. (6) Existing immutable version mismatch MUST fail; publication MUST be exclusive. Preserve all prior fixes. No install or commit.
- Six-blocker RED cycle: transactional suite 9 tests, 6 pass, 3 fail. Failures prove legacy runtime mutation, pre-mutation fault injection, and mismatched immutable-version reuse. Canonical launcher test fails on `OVERDECK_SEAT_SCOPE_ENTRY`; local authority test fails because launch omits `systemd-run --slice=agent.slice`; remote status/stop builders have no trusted-generation parameter. Baseline: authority 63/63 passed; launcher contract passed.
- Production correction WIP: canonical authority override removed; private fixture patches copied launcher. Local authority launches dedicated-UID tmux through `systemd-run --wait --collect --pipe --slice=agent.slice --service-type=exec`; authority suite 63/63 passed. Remote attach/status/stop builders now require explicit trusted generation and pass `--generation` to every mediator call; public status/stop fail closed when absent. Installed manifest, wrappers, all hashed payloads, and sudoers read once through bounded `O_NOFOLLOW` descriptors with root UID/GID, mode, link-count, size, and stable pre/post-`fstat` validation; suite 63/63 passed. Canonical launcher contract passed. Python/JavaScript syntax and `git diff --check` clean.
- Installer and generation blockers GREEN in deterministic suites. Installer publishes complete root-owned candidates under content-addressed versions, rejects mismatched existing versions, performs pointer-only activation, never writes legacy runtime destinations, and injects each fault after named mutation. Transaction suite: 9/9 passed; six rollback boundaries preserved `prior`; success activated one 64-hex version; mismatched version rejected. Standalone installer harness passed. Orphaned `buildLegacySeatScopeEntryInstallScript` removed; no unused production generator remains.
- Trusted generation now emits only after root authority finalizes live identity (`scope-entry-ok generation=<uuid>`), launch parser rejects missing receipt, returned launch result carries generation, and attach/status/stop builders require and pass pinned `--generation`. Operator hint remains unused.
- Complete deterministic verification: transactional 9/9; authority 63/63; implementer suite passed; mediator 6/6; canonical launcher passed; installer harness passed; Python/JavaScript/shell syntax clean; `git diff --check` clean; candidate-introduced unused diagnostics 0.
- Ledger RED diagnosis and GREEN receipt: current-tree integration was 84/85 because its general fake admission path replaced `_agent-build-scope` with a no-op, so the fixture—not production—removed `agent.slice` confinement. The exact assertion remained unchanged. For that case only, fixture admission now invokes installed real `_agent-build-scope`; immediately afterward it restores the no-op fixture to avoid contaminating unrelated cases. Final ledger result: 85 passed, 0 failed. Exact observed scope: `confine-agent-4100371-22438.scope`.
- Final affected verification: transactional 9/9; authority 63/63; implementer suite passed; mediator 6/6; canonical launcher passed; installer harness passed; Python/JavaScript/shell syntax clean; `git diff --check` clean; candidate-introduced unused diagnostics 0. No deterministic blocker remains.
- Official `seat-remote.test.mjs` remains externally unavailable because required `fleet` host is unavailable. No local fallback, bypass, or suppression used.
- Candidate remains uninstalled and uncommitted, per owner scope.

- Independent review correction request: (A) `buildSeatImplementerPrereqScript` MUST install prerequisite directories/tools only and MUST NOT write runtime modules, wrappers, manifests, sudoers, versions, or activation pointers; immutable transactional activation remains sole runtime-byte owner. Add deterministic RED/GREEN proof. (B) mediator `--generation` MUST be mandatory for every operation; remove implicit-current manifest resolution and prove omission fails closed. After exhaustive production-reference checks, surgically remove unreachable `_agent-session-tmux` tail/unused declarations and four untrusted duplicate `session.json` writes only when no production consumer exists. Consolidate install-check validation to one descriptor-safe read per artifact; delete weaker/dead helpers while preserving owner, mode, type, link-count, size, hash, and content checks. Do not perform optional test-only refactor. Run complete focused verification. Do not install or commit.

- Fresh runtime-path review adds mandatory RED/GREEN corrections: unify actual `_tmpjail-shim` → `_agent-session-tmux` → authority local socket contract; replace blocking local `systemd-run --wait` launch with asynchronous readiness plus exact server PID/cgroup verification and later lifecycle wait; provide dedicated UID safe socket ancestry through root-mediated runtime storage or descriptor-safe identity-bound grants; add strict remote CLI `--generation` parsing and propagation with missing/unknown/mismatch failures; execute every staged privileged entrypoint's real `--install-check` plus sudoers validation before activation; pass pinned generation to runtime `has-session`. Preserve prerequisite-only installer and mandatory mediator-generation corrections. Add deterministic RED before each fix. No install or commit.

- Confirmed additional blockers requiring RED/GREEN: all three stable root wrappers MUST fail closed on missing or malformed activation and MUST NOT fall back to mutable legacy modules; mediator MUST descriptor-walk and retain canonical socket ancestry with `O_NOFOLLOW`, validating ownership and modes against parent substitution/symlink races; local launch MUST use exact `agent.slice`; remote slice policy MUST remain its evidenced existing contract, not be homogenized without evidence; candidate-root-aware real staged entrypoint checks MUST complete before activation. Blocking local `systemd-run --wait` and missing pinned generation on `has-session` are independently confirmed. No install or commit.

- Launch ordering/efficiency blockers requiring RED/GREEN: remote `run_scope` MUST finalize trusted socket/server/cgroup identity before generation-bound mediator pane discovery; normal launch MUST not time out. Local root authority MUST replace 50 ms lifetime `list-panes` polling with one blocking/event-driven lifecycle signal, then query exact generation/identity/status once; no resident busy polling. Launcher descendant discovery MUST replace 50 ms full procfs rescans with bounded event/backoff and cached per-pass identity. Already-root authority MUST avoid repeated external mediator launches while retaining one immediate generation/live-identity validation before decisive action. Add deterministic probe-count bounds over a waiting interval. Installer process-count optimization remains optional and MUST NOT expand scope. No install or commit.

- End-to-end boundary additions requiring RED/GREEN: preserve validated provider/config/ledger environment, cwd, and argv across UID transition while removing dangerous variables; use root-owned canonical runtime path so implementer `HOME` cannot break `_agent-build-scope`/confinement; owner reader/reaper MUST use mediated access with pinned generation and MUST NOT directly open implementer-owned `0700` tmux socket; before any exit receipt, revalidate exact generation-bound socket dev/inode, server PID/start time, and cgroup, with replacement failing closed and publishing nothing. Prerequisite cleanup introduced eight unused diagnostics; remove each orphan only after exhaustive reference confirmation. Existing path, lifetime, CLI, activation, and slice requirements remain active. No install or commit.

- Two further trust-boundary blockers require RED/GREEN before simplification: remote exact exit receipt needs durable root-owned lifecycle ownership. Use a foreground scope lifecycle command or generation-bound event-driven finalizer that waits for dead pane, revalidates generation/socket/server/cgroup, publishes exact status, then exits. Operator stop MUST publish a distinct explicit stop terminal result or finalize before kill; it MUST NOT masquerade as pane exit. Prove exit 23 survives client disconnect/restart and prove stop semantics. Admission identity MUST remain descriptor-bound through ACL mutation and execution: retain ancestor/final descriptors, mutate ACL through proven descriptor-stable semantics, and execute by descriptor or reopen and compare complete identity immediately before exec. Ancestor/final replacement races MUST abort without ACL or execution. No install or commit.

- Concrete parser/manager blockers require RED/GREEN: parse `/proc/<pid>/stat` field 22 by locating final `)` before splitting suffix because comm may contain spaces such as `(tmux: server)`; apply consistently in authority and mediator; reject malformed/nonpositive values. Local exact `agent.slice` belongs to owner user manager, not root system manager. Root authority MUST launch through a robust canonical owner-user-manager mechanism into exact `agent.slice`; plain root `systemd-run` is invalid. Add deterministic command-contract test. Installed proof remains explicitly deferred by no-install constraint. No commit.

## Current correction receipt

- GREEN: prerequisite installer is directories/tools only; transactional suite passed 10/10 before later test additions. Runtime-byte ownership remains transactional activation only.
- GREEN: mediator `--generation` is parser-required; mediator focused suite passed 7/7 including omission before authority work.
- GREEN: actual launcher/authority socket contract uses established `~/.local/state/agent-sessions`; integration contract passes. Unreachable `_agent-session-tmux` legacy tail after unconditional `exec` removed.
- GREEN: shared `/proc/<pid>/stat` parser handles `(tmux: server)`, rejects malformed/nonpositive start time, and is used by authority and mediator. Authority suite passed 65/65 after parser and owner-user-manager command corrections.
- GREEN: remote root authority finalizes trusted socket/server/cgroup identity before generation-bound mediator pane discovery; authority suite passed 65/65.
- GREEN: remote CLI strict generation parser implemented; official and narrow JavaScript execution are externally blocked by required unavailable `fleet` host, exit 97. Tests remain and no fallback/bypass was used.
- GREEN by source contract, pending official remote gate: redundant unpinned post-authority `has-session` mediator call removed; authority already verifies live session before emitting generation.
- RED preserved: obsolete remote attach no-generation assertion reversed; attach now requires pinned generation. Full routing-record persistence/discovery/reattach/status/stop tests remain to complete.
- OPEN: faithful local foreground lifecycle ownership; remote durable lifecycle/receipt owner and distinct stop result; descriptor-bound admission through ACL/exec; mediator descriptor-held socket ancestry; collector/reaper mediated adapter with pinned generation plus explicit legacy fallback; complete staged candidate-root entrypoint install-check and fail-closed stable wrappers; environment/canonical confinement path; bounded event-driven probe behavior; duplicate untrusted manifest removal after consumer proof; one-read install-check consolidation; candidate-only diagnostic cleanup.
- GREEN: partial transactional test edit repaired; JavaScript, Python, and shell syntax pass cleanly. Exact merge-base `7a2e478fc6472483758c5f970475d19bc6e95a8c` attribution found one candidate-introduced unused declaration, `installOverdeckModuleLines`; removed. Public exports were not deleted based on single-file false positives.
- OPEN launch contract: root-owned canonical lifecycle entrypoint MUST perform validated UID transition, construct narrow allowlisted implementer environment carrying required ledger/config/runtime identity, drop dangerous variables, invoke root-owned installed guard/confinement path independent of implementer `HOME`/`PATH`, and avoid nested unauthorized `sudo`. Add integration proof for ledger identity, config resolution, dangerous-variable removal, and zero raw nested sudo.
- Constraints unchanged: do not install, commit, touch active sessions, weaken remote-only gate, or suppress diagnostics.

- Latest GREEN: seven reference-proven orphan imports removed; all three stable privileged wrappers fail closed on missing/malformed activation with no mutable fallback; activation wrapper regression 1/1. Mediator revalidates socket/server/cgroup identity after exact pane status collection and before receipt publication; mediator 7/7. Install validation now reads each artifact once through bounded `O_NOFOLLOW` descriptor validation and reuses captured bytes for wrapper binding, hash, and sudoers checks; authority 65/65.

- Collector seam confirmed: `agent-session-reader.mjs` directly runs tmux for state and invokes `_agent-session-reap-close.py` for atomic legacy close. New authority records require a separate explicit adapter keyed by valid `seatId` + pinned `generation`; mediator MUST implement one atomic detached-identity verify-and-close operation. NEVER emulate this with separate mediated list then kill calls. Legacy records without authority metadata continue existing direct helper only.
- Trusted generation persistence implemented in candidate: fresh root-issued generation is atomically written into owner-readable non-authoritative `seat.json` after successful launch; reattach requires discovered valid generation and returns it; status/stop parser requires strict UUID generation. JavaScript syntax clean; required remote behavioral gate remains unavailable at exit 97.
- Latest local verification remains authority 65/65, mediator 7/7, activation wrappers 1/1; no warnings. No install or commit.

- Atomic reap implementation seam confirmed: `_agent-session-reap-close.py` already owns cgroup freeze, pidfds, independent thaw watchdog, exact tmux identity/zero-attachment predicate, atomic close, and recursive scope cleanup. MUST NOT duplicate it in mediator. Add mediator `reap-close` that first validates pinned seat generation and exact live socket/server/cgroup, validates supplied classified identity/runtime fields, then delegates to this helper. Reader chooses this only for authority-tagged records; legacy remains direct helper.

- Latest GREEN: mediator `reap-close` validates pinned generation and exact live identity before delegating nine classified identity fields to the existing atomic freeze/watchdog close helper; mediator 7/7. Remaining activation delta: close helper MUST join immutable version payload/manifest/hash/install-check so mediator never depends on mutable legacy helper path.
- Latest transaction RED: syntax remains clean; transactional installer cases now fail before their intended fault boundaries because fixture omits newly required `_agent-session-reap-close.py`. Update fixture with complete immutable payload, manifest, and real candidate-root check; NEVER weaken candidate validation.
- Generation contract correction: initial launch MUST NOT accept caller authority generation; root mints and returns generation only after trusted identity finalization. Discovery/reattach/status/stop MUST recover valid persisted routing generation when CLI omits it. Explicit `--generation` MUST match persisted value. NEVER fall back to current trusted manifest or operator-readable current hints. Existing launch persistence and generation-bound attach behavior MUST remain.
- GREEN: complete candidate-root transaction now stages and validates `_agent-session-reap-close.py`, full manifest hashes, wrappers, modules, sudoers, and external prerequisite directory before activation. Transaction suite 11/11; every injected boundary preserves prior activation; mismatched immutable version fails closed. Python/JavaScript syntax clean.
- GREEN: initial launch rejects caller generation before dependency/config work; status recovers valid persisted routing generation when omitted and rejects explicit mismatch before mediated operation. Narrow deterministic generation suite 3/3. Persisted value remains routing metadata; root mediator remains authority.
- GREEN: local authority publishes `{kind:"seat", seatId, generation}` into the canonical owner ledger under its existing exclusive lock only after trusted socket/server/cgroup finalization, preserving authenticated owner UID/GID and mode. Reader classification and CLI reap use explicit adapters: authority records invoke the root mediator with pinned generation for `list-panes` and atomic `reap-close`; malformed metadata or mediator refusal fails closed with no legacy fallback; records without authority metadata retain direct legacy behavior. Authority 65/65, reap safety test clean, transaction 11/11, generation 3/3; no warnings.

## Owner interactive attach acceptance delta

- Status: ACTIVE. Current source proves two owner-control blockers: mediator uses captured subprocess output for every operation, so `attach` cannot inherit caller terminal; `agent-sessions` still probes and attaches raw tmux sockets, which new implementer-owned `0700` socket ancestry intentionally makes inaccessible.
- MUST add dedicated interactive mediator attach path. Validate pinned generation plus exact socket/server-start/cgroup identity before execution; then preserve caller stdin/stdout/stderr and terminal control while dropping to authorized owner identity and replacing mediator process with tmux attach. NEVER use `capture_output`, pipes, buffered replay, or shell command construction for attach. Noninteractive `has-session`, list, status, and receipt operations MAY capture bounded output.
- MUST route authority-tagged `agent-sessions` discovery, visibility, `has-session`, and attach through persisted generation-bound mediator operations. Operator-readable metadata remains routing input only; mediator revalidates root authority. NEVER require owner access to raw implementer socket. Raw tmux operation remains an explicit adapter only for records without authority metadata; malformed authority metadata MUST fail closed with no legacy fallback.
- Add deterministic RED before GREEN for command construction and descriptor inheritance. Add real pseudo-terminal integration proving live bidirectional input/output, terminal resize propagation, detach behavior, and owner list visibility while direct raw socket access is unavailable. Preserve all current sessions and legacy records untouched.
- Current receipt: descriptor ownership GREEN. Client tests now use owned real FDs; client closes received descriptors exactly once on validation abort or returning exec boundary; source `LocalPathIdentity` descriptors survive both broker transfers, then all distinct identities close exactly once immediately after broker completion and before pane wait. Broker+authority combined gate passed 88 tests + 12 subtests with warnings as errors. Fast-exit race GREEN: local and remote tmux commands install generation-bound global `pane-died` hook before `new-session`; authority suite passed 76 tests + 12 subtests. Operator stop GREEN: exact generation-bound stop intent is atomically persisted, successful kill and pinned PID absence precede receipt publication, intent is then removed; restart after kill-before-receipt completes from exact matching intent without tmux access. Socket binding GREEN: retained ancestry now also pins socket leaf dev/inode/type and rejects leaf or parent replacement; mediator suite passed 14/14 with warnings as errors. Remote ordering official RED remains preserved; enforced remote-only dispatch unavailable and no remote host contacted. No install, commit, or active-session mutation performed. Next action: restart routing persistence rollback and fresh-host stable wrappers/sudoers, then metadata/link-count, PTY proof, and remaining review blockers.

## Next executable action

Coordinator completion contract: finish without checkpoint. Add deterministic RED/GREEN for (1) durable event-driven local and remote lifecycle owners that survive client disconnect and publish exact generation/socket/server-start/cgroup-bound exit receipts; (2) explicit operator stop publishing a distinct terminal receipt that MUST NOT masquerade as pane exit; (3) mediator retaining descriptor-bound `O_NOFOLLOW` socket ancestry through decisive operation; (4) admission retaining ancestor/leaf identity through ACL and exec, aborting substitution before mutation/execution; (5) narrow validated launch environment using canonical root-owned tooling with zero unauthorized nested sudo; (6) bounded probe-count proof and no 50 ms busy polling. Remove `agent-session-reader.mjs` `tmuxTarget` only after exact zero-reference confirmation. Rerun every focused suite clean. Require independent clean review before install or commit.

Next action: add lifecycle and probe-count RED tests, then implement event-driven finalizer and distinct stop receipt. Continue directly through descriptor and environment blockers; do not stop at another checkpoint.

- GREEN: explicit generation-bound `operator-stop` mediator operation publishes `terminalReason: "operator-stop"` before exact tmux server termination. Remote stop builder calls that operation once, removes direct `kill-server`, removes the 50×100 ms polling loop, and performs one final residue probe. Deterministic remote stop 1/1 and distinct receipt schema 1/1 pass cleanly.
- OPEN: durable remote lifecycle owner; descriptor-bound ACL and executable admission through final exec; complete focused regression and independent clean review. Candidate remains uninstalled and uncommitted.
- Coordinator correction, 2026-08-13: MUST complete descriptor-bound ACL/exec safety and durable remote event-driven lifecycle ownership now. Add deterministic RED/GREEN proving substitution aborts before ACL/exec and client disconnect cannot lose exact identity-bound exit receipt. Then run all focused regressions. Compare four `seat-remote.test.mjs` unused diagnostics against merge-base; fix candidate-caused diagnostics and produce clean output. MUST NOT install or commit. MUST NOT stop before completion unless genuinely externally blocked.
- GREEN focused receipt: authority 68/68; implementer 14/14; mediator 9/9; transaction 11/11; JavaScript focused 5/5; Python/JavaScript syntax and `git diff --check` clean. Merge-base attribution enumerated five candidate-added `seat-remote.test.mjs` declarations; every one has reads (`statePath` 3, `socketPath` 8, `generation` 13, `stopScript` 12, `statusScript` 4). Zero candidate-caused unused declarations.
- FINAL COORDINATOR BLOCKER: MUST hold validated ancestor/final descriptors through ACL mutation and execution. ACL MUST target admitted inode through native fd API or verified inherited `/proc/self/fd/<n>` capability. Execution MUST use fd (`fexecve`/`execveat`, including Python fd-capable `os.execve`) or have no adversary-controlled gap. Mediator MUST use retained canonical socket ancestry through decisive tmux operation or a root-opened socket capability. Add deterministic ancestor/final substitution races proving no ACL or execution of replacement. Run all focused suites and clean diagnostics. MUST NOT install or commit.
- FINAL BLOCKER GREEN: local admission retains root-opened `O_NOFOLLOW` descriptors for cwd, every executable ancestor, and every executable leaf. ACL mutation invokes `setfacl` only against inherited `/proc/self/fd/<n>` capabilities with `pass_fds`; ancestor or leaf replacement before mutation fails before `setfacl`. Root authority passes only `/proc/<authority-pid>/fd/<n>` cwd/runtime capabilities across the manager boundary. Privileged wrapper imports them into its own inheritable descriptors before UID drop and rewrites runtime argv to `/proc/self/fd/<n>`, so later wrapper/scope traversal never reopens operator pathnames and replacement cannot become the executed object.
- FINAL SOCKET GREEN: mediator retains canonical `O_NOFOLLOW` parent descriptors and invokes tmux through `/proc/self/fd/<parentfd>/<socket>` with the fd inherited. The tmux client drops directly to the dedicated implementer UID/GID with empty supplementary groups; decisive lifecycle/status/stop/general operations no longer use the original socket pathname or nested sudo. Parent replacement fails closed before operation.
- RED receipts: missing `LocalPathIdentity.grant_acl`; missing `run_tmux_bound`; launch command exposed admitted executable pathnames. Each failed at the intended boundary before production correction. Deterministic replacement tests prove no ACL subprocess after final-target substitution, descriptor-addressed ACL mutation, capability-only runtime command, and retained-parent socket capability.
- FINAL focused receipt: authority 69/69; implementer 13/13; mediator 10/10; transactional installer 11/11; JavaScript generation/stop/reap 5/5. Python compile, JavaScript syntax, `git diff --check`, and candidate unused-declaration attribution are clean. No warning, traceback, assertion failure, or candidate unused declaration remains.
- BROKER PROTOCOL RED/GREEN: real kernel probe transferred executable script via `SCM_RIGHTS` and fd-executed exact exit 23. Deterministic RED failed on missing `seat_execution_broker`; GREEN 4/4 proves replacement after admission transfers original bytes, stale generation and wrong peer UID send no descriptors, and fd-count mismatch fails closed. New module: `modules/workstation/claude/lib/seat_execution_broker.py`; tests: `modules/workstation/claude/tests/seat_execution_broker_test.py`.
- Coordinator authorization: no user input needed. Complete two-stage broker end to end now. Stage 1 canonical client runs as tmux pane, authenticates to root broker, receives cwd+admission fd, and fd-execs admission with canonical client stage 2 as its runtime argv. Stage 2 survives admission/buildslot/systemd as canonical pathname, authenticates again, receives cwd+runtime fd, and fd-execs exact runtime. Broker serves exactly one request per phase, validates `SO_PEERCRED` implementer UID + seat + generation + phase, revalidates trusted manifest before each transfer, and closes after both transfers. Continue through immutable install/harness/fault tests and focused clean verification. MUST NOT live-install or commit before independent review.
- Candidate remains uninstalled and uncommitted as explicitly required. Next action after corrected GREEN: independent clean security review over complete candidate diff; installation and commit remain prohibited until that review is clean.
- IMMUTABLE BROKER INSTALL RED/GREEN, 2026-08-13: RED 11/12 proved activated immutable version omitted `seat_execution_broker.py`. GREEN transaction 12/12 stages `seat_execution_broker.py`, `seat_execution_client.py`, and executable `overdeck-seat-execution-client`; includes all three hashes in complete 13-artifact version identity; requires all manifest keys; validates regular-file mode, executable bit, exact hash, and wrapper module binding through existing bounded stable `O_NOFOLLOW` reader; candidate-root harness requires installed shape. Existing six mutation fault boundaries preserve prior activation. Existing-version mismatch fixture now targets exact 13-artifact content address and fails closed. Sudoers unchanged: client remains unprivileged; no privilege expansion.
- STRICT BROKER PROTOCOL GREEN, 2026-08-13: broker request/response identity now includes exact `phase`; request schema requires exactly `seatId`, `generation`, `phase`; extra/missing/changed fields send no descriptors. Newline-framed reads accept fragmented delivery, reject oversized/multiple/trailing frames. Broker/client focused suite 7/7 functionally green. Expected rejection stderr MUST be captured before final clean receipt.
- NEXT EXECUTABLE ACTION: replace bare broker thread tuple with root-owned lifecycle object. MUST enforce bounded accept/read deadlines, surface worker exception to authority, close retained descriptors, unlink socket on every path, and prevent successful exit receipt unless both authenticated phases complete. Add deterministic RED/GREEN for timeout, death after phase one, replay/order violation, manifest change between phases, stop race, and cleanup. Then run real isolated tmux two-stage exact-exit-23 proof, full focused suites, clean diagnostics, plan receipt, and independent security review. MUST NOT live-install or commit before clean independent review.
- COORDINATOR COMPLETION DELTA, 2026-08-13: continue with no checkpoint. MUST propagate lifecycle errors; bound every broker accept/read/join; clean broker socket, descriptors, and child/process state after success, malformed/disconnected client, generation mismatch, broker crash, tmux startup failure, and operator stop. Real two-stage tmux proof MUST show admitted fd execution after tmux closes inherited fds, exact status 23 exit receipt, zero polling, zero leaked broker thread/process/socket, and replacement races cannot redirect cwd/admission/runtime. Add deterministic RED/GREEN for each case. Run complete focused verification and clean diagnostics. Return only independent-review-ready candidate or genuine external blocker. MUST NOT live-install or commit.
- LIFECYCLE OWNER RED/GREEN, 2026-08-13: `LocalExecutionBroker` captures worker exceptions, bounds `wait()`, wakes blocked Unix `accept()` during `close()`, bounds cleanup join, closes listener, and unlinks socket on every path. Authority uses owner socket, waits for both broker phases before exit receipt, and calls `close()` in `finally`; tmux startup/lifecycle/status/broker failure cannot publish successful receipt. Broker applies one absolute deadline across both accepts and reads; malformed/disconnected client fails before descriptor transfer. Blocked-accept RED hung until external test timeout; GREEN completes in 1 ms with warnings promoted to errors and no live thread/socket.
- REAL TMUX RED/GREEN, 2026-08-13: RED pane exited 1 because `serve_two_phase` passed trusted manifest instead of authenticated client request into exact request validator. GREEN separately revalidates trusted manifest seat/generation before each phase, validates exact client request schema/phase, and transfers cwd+executable descriptors. Real tmux 3.7b proof passes opened fds into tmux, then requires canonical pane client to reconnect twice after tmux closes inherited descriptors; admission fd executes canonical stage-two client, runtime fd exits exact 23. Event-driven `wait-for`; one final pane probe; zero sleep/poll loop. Broker thread ends; temporary broker/tmux sockets removed; no process/socket leak.
- FINAL CLEAN RECEIPT, 2026-08-13: Python focused 104/104 under `-W error -b`; JavaScript focused 16/16; immutable transaction 12/12 within JavaScript total; real tmux proof included; Python compile, JavaScript syntax, and `git diff --check` clean. No warning, traceback, failed assertion, leaked thread/process/socket, live installation, commit, or active-session mutation.
- INDEPENDENT REVIEW BLOCKERS, 2026-08-13: candidate NOT ready. Fix test-first: (1) broker socket MUST use distinct `implementer_gid`, never assume UID=GID; (2) root authority MUST reconstruct strict client execution environment preserving validated HOME/provider/config/ledger/runtime identity keys while dropping dangerous variables; (3) validate exact two-stage argv contract before ACL/socket mutation: admission/runtime paths present, required positions, absolute, admitted. Missing/relative input MUST fail cleanly without `IndexError`, `KeyError`, or mutation. (4) remote startup MUST query and verify bootstrap tmux socket/server PID/starttime/cgroup through root authority, atomically finalize trusted manifest, then invoke generation-bound mediator; NEVER weaken mediator finalized-field checks. Add end-to-end ordering RED/GREEN. Run full focused clean gate. MUST NOT install or commit; return for re-review only.
- REVIEW-BLOCKER GREEN, 2026-08-13: local sessions use one bounded `local-hosted` implementer UID/GID/home; remote seats retain per-seat identity. Broker socket setup carries distinct implementer UID and GID. Authority reconstructs strict admitted environment and validates complete absolute two-stage argv before ACL, broker socket, tmux, or receipt mutation. Source descriptors remain valid through both transfers and close exactly once after broker completion, before pane lifecycle wait. Complete path identity includes device, inode, mode, UID, GID, size, mtime, ctime, and link count; linked executables and same-inode metadata mutation fail closed.
- OWNER CONTROL GREEN, 2026-08-13: authority-tagged ledger visibility and attach use persisted generation-bound mediator routing; malformed authority fails closed; raw tmux remains only for authority-absent legacy rows. Interactive attach replaces mediator with tmux while inheriting caller terminal descriptors. Real PTY proof covers bidirectional I/O, resize propagation, detach, and surviving session; 5/5 stress runs passed. Operator stop persists exact intent, kills and proves pinned server absence, publishes distinct `operator-stop` receipt, then removes intent; restart recovers kill-before-receipt safely. Retained socket parent and leaf identity reject substitution.
- FINAL LOCAL VERIFICATION, 2026-08-13: Python authority, broker/client, mediator, and real PTY suites passed 106 tests plus 12 subtests with warnings as errors. Isolated ledger integration passed 87/87, including mediated visibility and generation-bound attach with no raw fallback. Strict launcher authority shell contract passed. `seat-runtime.mjs` syntax and `git diff --check` passed. No warning, traceback, failed assertion, live installation, commit, remote-host contact, or active-session mutation occurred.
- REMOTE-ONLY LIMIT, 2026-08-13: production remote create order now provisions checkout, exact persistent implementer identity, account bootstrap, then seat record; restart persists replacement generation only after live doctor success. Deterministic local ordering and transaction REDs exist for fresh-host stable wrappers/live sudoers and failed-upgrade byte/mode rollback. Enforced dispatcher marks official remote and installer suites remote-only, and no approved host is available; policy forbids local bypass and coordinator forbids remote contact. These executions remain external blockers, not claimed GREEN.
- INDEPENDENT REVIEW RECEIPT, 2026-08-13: coordinator reports independent local review clean. Install-before-land authorized. Commit and landing remain prohibited.
- CONTROLLED INSTALL STATUS: ACTIVE. Worker: this session. Snapshot current activation pointer, stable wrappers, sudoers, service state, and active legacy session identities before mutation. Arm atomic rollback to exact snapshot. Run transactional candidate installer only; install new authority runtime without migrating, restarting, stopping, or rewriting active legacy sessions.
- LIVE ACCEPTANCE: invoke installed entrypoints and install-check. Launch one disposable hosted session through normal installed local path. Prove bounded non-owner implementer UID/GID/home, exact `agent.slice`, generation-bound owner list and inherited-terminal live attach, mediated collector/reaper visibility, exact exit 23 receipt, and zero broker/socket/process residue. Recheck every snapshotted legacy session unchanged and attachable. Address every warning. Any failed proof MUST atomically restore prior activation, wrappers, sudoers, and service state before report.
- INSTALLER RE-REVIEW RED, 2026-08-13: independent review found three blockers. (1) Unprivileged installer reads root-owned `0700` stage/target during hash and diff checks. All stage/target verification MUST run under root or consume bounded root-produced results. (2) Rollback arms only after full stable publication; any mid-loop failure can leave mixed versions. Arm before first mutation and track each touched destination incrementally. (3) Rollback hard-codes canonical modes instead of restoring exact prior content, type, mode, owner, and group. Tests MUST seed safe noncanonical prior metadata, inject failure after each stable publication, and enforce real root ownership/access semantics through faithful harness or isolated `deck-sudo` proof.
- INSTALLER SECOND REVIEW RED, 2026-08-13: candidate remains NOT READY. Six blockers: (1) hashes do not authenticate user-writable source; explicit install authorization approves one immutable byte snapshot only. Root MUST descriptor-open every source with `O_NOFOLLOW`, validate regular file/owner/mode/link/size, copy and hash from same held descriptor into exclusive root stage, then execute only verified root-owned staged bytes. Do not claim package provenance. (2) Content-addressed version publication MUST descriptor-walk root-owned non-writable ancestors, reject symlink/writable/wrong-type targets, create exclusively, and accept existing version only after descriptor-safe complete verification. (3) Stable destinations MUST be absent or expected root-owned regular files; reject directory, symlink, and special types; publish atomically. (4) Parent existence/owner/group/mode changes MUST be snapshotted and rolled back. (5) Durable root-owned journal and recovery entrypoint MUST precede new install/runtime; rollback MUST attempt every item despite individual failure, retain recovery data, verify restoration, and never report preserved when incomplete. (6) Every temporary file MUST live inside private transaction storage and be removed on all completed paths.
- REQUIRED RED/GREEN: fault after every mutation; source replacement; unsafe source metadata; existing-version symlink/writable/wrong type/content; stable destination symlink/directory/special/wrong owner; parent creation/mode rollback; rollback operation failure; SIGKILL/power-loss journal recovery; concurrent installer exclusion; temp cleanup. Activation remains final atomic mutation. Live installation MUST remain stopped until full suite and fresh independent review are clean.
- SECURE INSTALLER CONTRACT GREEN, 2026-08-14: dedicated `seat_authority_installer.py` contract passes 24/24. Tests cover descriptor-held source substitution failure, symlink/directory/FIFO/hardlink/writable source rejection, unsafe existing versions, stable destination wrong types, every partial publication rollback, noncanonical modes, fresh-host absence, interrupted-journal recovery, rollback failure continuation, concurrent lock, activation-only success, and temp/journal cleanup. Focused real root probe confirms unprivileged access to root `0700` stage is denied while root hashing and metadata copy work.
- LIVE INSTALL BLOCKED — TRUSTED BOOTSTRAP ABSENT: `/usr/local/bin/overdeck-seat-authority-installer` and `/usr/local/lib/overdeck/seat_authority_installer.py` do not exist. No tracked packaging path provides a preinstalled root-owned installer bootstrap. Executing the candidate module with root, or pathname-copying it into root ownership before descriptor-safe capture, would execute/trust user-writable bytes and violate independent review blocker 1. Explicit install authorization approves one immutable byte snapshot but does not authenticate a mutable pathname or authorize bypassing provenance. Candidate remains uninstalled; active legacy sessions remain untouched.
- TRUST-CHAIN FINDING, 2026-08-14: no signed package, verified-commit installer, root deployment service, or preinstalled seat-authority helper exists. Deploy clone, `packaging/deploy-local.sh`, and installed `deck-sudo` are user-owned; current root installs execute mutable user-owned shell paths and are NOT suitable provenance anchors. Existing root-owned Overdeck files (`/usr/local/lib/notif-gate/notif_gate.py`, `/etc/systemd/system/overdeck-seat-proxy@.service`) are unrelated and cannot safely install this runtime.
- SAFE EXISTING EXTENSION: owner-authorized `deck-sudo` already launches trusted system binaries in a fresh root process. Kernel proof: caller descriptor-opened reviewed bytes, copied them into a sealed `memfd` (`F_SEAL_WRITE|F_SEAL_GROW|F_SEAL_SHRINK|F_SEAL_SEAL`, mask 15), root `/usr/bin/install` copied `/proc/<holder-pid>/fd/<fd>` into a private root-owned destination, root `sha256sum` matched expected bytes, installed file was regular `0600 root:root`, and cleanup succeeded. No repository installer code executed as root during capture. Minimal extension MUST: descriptor-open and validate every reviewed source; compute and require explicit expected digest; seal one installer payload; root-copy exact proc-fd into private root transaction storage; root-verify digest and metadata; execute only that verified root-owned copy; retain rollback/journal contract. Holder MUST remain alive through copy. Any mismatch MUST delete capture and abort.
- SEALED BOOTSTRAP GREEN, 2026-08-14: kernel/root proof and deterministic tests pass. Sealed launcher 11/11; dedicated installer 24/24; combined 35/35; compilation and `git diff --check` clean. Reviewed installer payload SHA-256: `62803fcf62e2e4d99b052b5f53b33642954ffaa4b9456b721e6b8c25b85102df`. No live mutation occurred.
- SEALED BOOTSTRAP REVIEW RED: two high-severity blockers remain. (1) Caller-supplied digest and caller-controlled candidate path do not provide trusted authorization; attacker controlling both can install arbitrary root code. MUST bind fixed destination + digest + release identity to a trusted signed manifest or equivalent pre-existing root-owned authorization. (2) Separate root copy/hash/stat/move commands do not retain staged-inode continuity. MUST use one privileged descriptor-holding helper, or prove every destination ancestor root-owned/non-writable and create a unique exclusive no-follow stage whose inode cannot be replaced before atomic activation. Fixed `.new` path is forbidden.
- DESTINATION MEASUREMENT, 2026-08-14: `/`, `/usr`, `/usr/local`, and `/usr/local/lib` are root:root `0755`, no extra ACL; `/usr/local/lib/overdeck` and `/usr/local/lib/overdeck/bootstrap` do not exist. `/usr/bin/install`, `sha256sum`, `stat`, `mv`, `sync`, `bash`, `cp`, and `dd` are root:root `0755`. Coreutils provide separate pathname operations only; none retains one newly created `O_EXCL|O_NOFOLLOW` descriptor through copy, hash, metadata validation, fsync, and rename. Multiple `deck-sudo` calls therefore cannot prove staged-inode continuity. `deck-sudo /usr/bin/bash -c <caller-string>` could hold a descriptor but would execute caller-controlled root code and cannot establish digest provenance.
- DECISION — NO SAFE CURRENT BOOTSTRAP: existing trusted binaries and privilege bridge cannot establish both machine-authenticated digest authorization and same-inode activation. Rejected sealed launcher remains test evidence only and MUST NOT ship or run; remove production launcher before handoff. Exact missing anchor: one independently installed root-owned executable or signed package verifier whose code/digest authorization is anchored outside user-writable trees and whose fixed command performs descriptor-safe capture and atomic activation.
- ROBUST OPTIONS: (A) distro package signed by a key already trusted by root package manager; package owns `/usr/local/lib/overdeck/bootstrap` equivalent and installer command. Constraint: repository currently has no package/signing pipeline or trusted key. (B) one owner-installed exact reviewed bootstrap binary with digest `62803fcf62e2e4d99b052b5f53b33642954ffaa4b9456b721e6b8c25b85102df`, copied through a human-controlled trusted channel and verified before root install. Constraint: requires explicit owner action outside agent-controlled mutable command shape. (C) preinstall root-owned verifier with embedded public key, then submit signed fixed-destination manifests. Constraint: new key custody, rotation, package/update path, and recovery policy required. Git commit/deploy clone, plan text, chat text, user-owned scripts, and caller-supplied path+digest are NOT trust anchors.
- STATUS: BLOCKED. Owner must choose/provide one robust trust anchor. Until then MUST NOT install, commit, land, execute candidate code as root, contact remote hosts, or touch sessions. After anchor installation: fresh independent review, clean live snapshot, transactional install, installed-entrypoint check, disposable exact-exit-23 session proof, legacy preservation proof, then plan receipt.
