# FIRE session harvest — recovered work and the admission-queue wedge

outcome: everything the Aug-12 emergency session carried is either delivered, registered, or recovered to a named ref; the fork-exhaustion wedge its era produced is fixed and its class is closed.
status: ACTIVE (seat authority: built, tested, landed dark — see receipt; install is the next slice)
source request: owner 2026-08-15 — "i want to dig deeper into the recovered tasks from the FIRE session"; "i just want to recover the tasks, dedup against what we already have here. and retire that session"; "need to release the caps. sessions can not work."

## Harvest — from the transcript, not from memory

Source: `~/.claude/projects/-home-user-Projects-overdeck/3ecd0cda-4096-4058-b37e-0db3b0b4011a.jsonl`
(112MB, 13,334 records, 80 owner-typed turns, final compaction summary carried the task state).
Extracts preserved at the session scratchpad: `fire-asks.txt`, `fire-final-tasks.txt`.

The session was the Aug-12 workstation fire (RAM/CPU/disk emergency, `/od-emergency`). Its five
tasks, deduped against the current registry:

| FIRE task | Verdict | Where it lives now |
|---|---|---|
| #1 Relieve workstation load | DELIVERED since | LSP reaper armed (`c74ffba55`), agent.slice quota removed, ledger compacted 2,857→~350, unit-symlink storm fixed; load 75 → ~15 |
| #2 Relocate emergency skill | OPEN, small | = `2026-08-12-localize-od-skills.md` (ACTIVE, 1 landed sha); verify remainder and close |
| #3 Seat authority candidate | **RECOVERED — the real find** | see below |
| #4 Disk space archaeology | DELIVERED since | 0.9GB → 132GB free; tmp_pack sweeper landed (`48d97b00c`) |
| #5 Collector memory leak | DONE by FIRE itself | its own record says completed |

## The recovery: seat authority candidate

The FIRE lineage built a **seat authority** rework — dedicated UID + exact `agent.slice` scope per
hosted session — through an independent security review that rejected it with six findings
(non-transactional installer; local tmux losing `agent.slice`; attach without expected generation;
env-overridable privileged entrypoint (`OVERDECK_SEAT_SCOPE_ENTRY`); raceable manifest/hash reads;
non-authoritative version dir). The implementer's correction pass — including
`seat_authority_installer.py` and transactional-install tests answering those findings — sat
UNCOMMITTED in `.worktrees/tmux-runtime-boundary` when the worktree reaper took the directory.

**It survived.** The salvage snapshot is commit `147c78fb7` (2026-08-14 23:05), held by tag
`archive/wip-Projects-overdeck-.worktrees-tmux-runtime-boundary`: 35 files, +4,528 lines, the full
candidate plus its correction tests. The six findings and the review's required fixes are recorded
verbatim in `fire-final-tasks.txt`.

### Restore receipt (2026-08-15, `wt/seat-authority-restore`, 6 commits)

Restored via `git cherry-pick -n 147c78fb7` onto current main in a fresh worktree, resolved against
main's landed dispatch-idempotency and box-resident-session work (both orthogonal, kept both;
no collision with `modules/harness/seat/seat-resident*` — different directory tree, untouched).

Two real defects found and fixed beyond the merge itself, both dead-on-arrival production bugs in
the salvaged candidate, neither previously caught because no test in the snapshot exercised the
full path:
- `seat_scope_entry.py` `main()` required a `--generation` CLI arg the parser never registered —
  every real launch invocation died at `missing-generation` before the root check. Fixed by
  removing it from `required_scope` (generation is always minted internally, per design).
- `seatRemoteStop` required a trusted persisted generation on every host, including a
  residue-only probe (scope/socket alive, no seat.json) — the exact state `seat-remote stop` is
  told to clean up after a launch fails with `stale-seat-residue`. Fixed by scoping the
  generation requirement to the generation-bound mediator call only; proxy/netns teardown
  (which never binds to a session) still runs unconditionally.

`seat-remote.test.mjs` and its fixtures had never been re-run to green after the six-findings
rewrite (~15 distinct stale assertions/mocks: missing `--generation` on mocks and fixtures,
obsolete flat-install-path regexes, a non-socket-typed mock tmux, missing `/proc/pid/stat`, a
mock cgroup line without the leading slash the parser requires) — all repaired to match the
corrected, real behavior; none weakened.

**Six findings, RED/GREEN receipt:**
1. Transactional installer — `seat-scope-transactional-install.test.mjs`, "faults are injected
   after their named mutation" (15/15 in that file): fault injected after each real staged
   mutation, asserts `rollback=preserved` and prior bytes restored. GREEN.
2. Local tmux in exact `agent.slice` — `agent-session-local-authority.test.sh` (captures the real
   `--local-session` dispatch) + `seat_scope_entry.py:662` `systemd-run --slice=agent.slice
   --service-type=exec`; `agent-session-ledger.test.sh` "tmux-hosted session still lands in
   agent.slice" observed `confine-agent-*.scope`. GREEN.
3. Remote attach/status/stop/receipt carry expected generation — `seat-remote-generation.test.mjs`
   (3/3) + `buildAttachInvocation` now throws without one; new receipt test proves residue-only
   stop (no seat.json) still succeeds without a mediator call, so the gate is scoped to sessions
   it can actually identify. GREEN.
4. No env-overridable entrypoint — `grep -rn OVERDECK_SEAT_SCOPE_ENTRY bin/ lib/` returns nothing;
   `agent-session-local-authority.test.sh` asserts the string's absence as a hard precondition.
   GREEN.
5. Single `O_NOFOLLOW` descriptor for manifest verify+parse — `seat_scope_entry_test.py
   test_install_check_contract`, real (unpatched) `read_installed_file()` runs: one `os.open(...,
   O_NOFOLLOW)`, `fstat` validates owner/mode/type/nlink/size, then hash computed from the same
   read. GREEN.
6. Immutable version activation — `seat-scope-transactional-install.test.mjs` "an existing
   immutable version with mismatched bytes is rejected"; stable wrappers resolve through
   `seat-authority-active` → `versions/<hash>/`, confirmed by the (fixed) installed-layout test.
   GREEN.

Full local receipts (all via `systemd-run --user`, required — nested tmux jail refuses cgroup
reads): JS `seat-remote.test.mjs` + `seat-scope-transactional-install.test.mjs` +
`seat-remote-generation.test.mjs` + `seat-remote-stop-receipt.test.mjs` +
`agent-session-reap.test.mjs` = 21/21. Python `modules/workstation/claude/tests/` full dir =
195 passed, 11 skipped (root-only), 22 subtests. `agent-session-ledger.test.sh` = 87/0 (the
harvest's earlier "92/92" figure covered `seat-contract.test.sh`, not this ledger file — see gap
below). `git diff --check` clean; `py_compile` + `node --check` clean on every touched file.

**Not verified — named gaps:**
- `modules/harness/seat/test/seat-contract.test.sh` (the official 92-case remote suite): fails in
  this environment on a `spine` CLI dependency missing from the local-gate build mirror
  (`/home/user/builds/seat-authority-restore-*/spine/node_modules`), not on seat-authority code —
  a local `bun install` in `spine/` fixed it locally but the mirror doesn't inherit that. Outside
  this lane (`modules/harness/seat`, not `modules/workstation/claude`) and matches the harvest's
  own "retry only when required build host is available, never fall back to local" instruction.
- No live install, no touch to active sessions or sudo rules, per the task's explicit constraint —
  the code is landed **dark**: inert until `buildSeatScopeEntryInstallScript()` / the installer
  path is invoked by a future session. Prove new sessions use the dedicated UID/`agent.slice`,
  owner attach, and exact dispatched exit status all require that install and are NOT proven here.
- TypeScript diagnostic-attribution comparison against exact base (harvest's earlier ask): not
  re-run this session — the restore's own `node --check`/`git diff --check` are clean, but no
  official remote diagnostic-count comparison was performed.

### Next action

Install is a separate owner-visible slice: run the transactional installer for real (root, via
`deck-sudo`), verify the activation pointer + sudoers land, prove a fresh dispatched session lands
in `agent.slice` under the dedicated UID with the expected generation, prove owner attach and exact
exit status, then close the `## Close the class` checklist items below. Do this from a fresh
worktree once landed; never touch the currently-active legacy sessions while doing it.

Overlaps `2026-08-15-laptop-as-terminal.md` (local seat authority vs box-resident sessions —
adjacent, not duplicate, confirmed no file collision); reconcile scope with it before the install
slice starts.

Session retirement: harvest complete from the transcript; the session was asked to write its own
handoff, commit loose edits, and idle. Owner closes the window.

## The wedge this dig exposed (fixed 2026-08-15 ~11:20)

While recovering, every fork on the machine began failing. Chain, fully evidenced:

1. `/run/user/1000/agent-session-slots/queue.lock` was flock-held by dead pid 65299 via an
   inherited descriptor — a **ghost lock** (`/proc/locks` creator dead, zero live fd holders
   findable, yet the lock held).
2. Every agent spawn admission queued behind it forever: 758 waiter jobs, each parking ~3
   processes in a `tmux-spawn-*` scope under `agent.slice` (~300 new/hour).
3. `agent.slice` hit `TasksMax=3072` → every fork inside it failed EAGAIN → git/gh/tests/builds
   died machine-wide → sessions "halted", including uncapped `unsafe.slice` sessions, because the
   tool wrappers route work back into `agent.slice`.

Fix applied: lock file rotated to a fresh inode (wedged one preserved as
`queue.lock.wedged-20260815T112028`); 736 provably-unwakeable scopes (waiting on the orphaned
inode — unwakeable by definition) SIGTERMed, 2,205 pids released; `TasksMax=16384` set at runtime
on agent.slice by explicit owner order. Result: 2,991 → 52 pids, forks and git verified working.
Drain log: scratchpad `tmux-drain.log`.

## Close the class

- [ ] `_agent-session-admission` gets the same ghost-lock rotation `buildslot.sh` already has
      (stamp-based holder liveness; rotate on dead stamp). The queue lock was the ONLY lock in
      that directory without it.
- [ ] Decide the durable `TasksMax` for `agent.slice` in `modules/monitor/systemd/user/agent.slice`
      (runtime 16,384 vs repo 3,072 will drift on next daemon-reload). The cap exists to stop fork
      bombs; the wedge was a leak, not a bomb — but 3,072 was also only ~4h of leak headroom.
- [ ] Admission waiters need a bounded wait: a spawn that cannot be admitted within N minutes must
      fail loudly, never queue forever (the 758 silent waiters are the anti-pattern the
      notifications doctrine already names: no silent absorption).
- [ ] Worktree reaper liveness fix (separate lane, running): never touch a worktree with a live
      session cwd, queued land ticket, or fresh index.lock.
