# WI-3 Scratchpad — Compaction revocation and runtime-generation rollover - **Issue:** Gitea #830 - **Branch:** `feat/830-compaction-revoke` - **Base HEAD:** `abd2791f59b3f06f46dd08e55298ced72f6aa7c2` - **Role:** sol author/build lane only; terra CODE and Opus SECREV are coordinator-owned. ## Mission prompt Implement BUILD-BRIEF Deliverable 3.3 and D4 on merged WI-1/WI-2 under `packages/mosaic/`. Claude `PreCompact` and `SessionStart(matcher=compact)` plus Pi `session_before_compact`/`context` equivalents must revoke the active lease through the existing broker state machine. Any `runtime_generation` bump—including same-PID reload/resume/fork—must auto-revoke the prior incarnation so the new generation inherits no prior lease. M1 is Claude + Pi only. Honor amended D2-v5 exactly: hard fail-closure when at least one observer fires or after lease expiry; both observers missing within TTL is an explicitly named bounded residual stale window (maximum 300 seconds, soak-tighten only), with no claim that the mutator gate bounds actions inside that window; total gate-hook miss is T-C. T12b/T30 must report both the within-TTL ALLOWED outcome and after-TTL DENIED outcome. ## Session start verification - Worktree is clean on `feat/830-compaction-revoke` at exact required base `abd2791f59b3f06f46dd08e55298ced72f6aa7c2`; `origin/main` is the same SHA and includes merged WI-2 atop WI-1. - Authority SHA-256 verified: - BUILD-BRIEF: `89fdbc27ed0e5050dc7b52f3ef2ddaea691edf17fd89d51b15e26fb5ed47171b` - SPEC-v5: `a6d07ade835758e8488ca10d3b0631caf0beb93ea3a6733631f151b0c2f01433` - Ratification: `bac58319c9c4028b5b40e1129e0033cdb5a6b7b02033c25f06f4cb77d7779c67` - sol red-team: `3da326a4ea91767b731e128a93b13194e8002358101e30de3fcb8ca2f8f54faa` - WI-0 evidence pack SHA-256 `5d418306fcc597fd514e500bee40d1509f0bf467e46ee13fc5c280ed8274759d` read directly. Probe P3 is **PASS**: real Pi retained the same PID/starttime through reload/fork/new/resume while generations advanced and a prior VERIFIED generation was revoked. - P6 planner-return ruling SHA-256 `b7bbb6ea6e8d9a5c3366993642ab4e4f65b961af04936dcac20bfbcdcbaf1a09` read directly: feature WI admission is GO with the exact-delivery empirical compatibility fact and disclosed T-C middle-drop residual; no receipt redesign. ## Plan and budget 1. RED real-socket acceptance for T12b/T30, each Claude observer, same-PID generation rollover, Claude/Claudex hook wiring, and Pi lifecycle wiring. 2. Add one broker client executable for observer revocation plus a private monotonic generation-file helper shared by launcher, gate, and revoker. 3. Wire Claude `PreCompact`, `SessionStart(compact)`, and resume/clear generation rollover; merge equivalent mandatory hooks into isolated Claudex settings. 4. Wire Pi pre/post compaction observers and reload/new/resume/fork generation rollover with local fail-closed tool blocking if lifecycle revocation fails. 5. Document the D2-v5 bounded stale window without claiming the mutator gate bounds within-TTL actions; update protocol/security/operations/sitemap/checklist. 6. Run focused real tests, independently measured executable coverage ≥85%, full repository gates, commit/push, open an unmerged `closes #830` PR, and hand off for terra CODE + mandatory Opus SECREV. Working estimate: **35K tokens**. No explicit hard cap was supplied; reduce refactor breadth before touching locked broker authority/state-machine semantics. ## RED evidence - New T12b/T30 test already reports the inherited primitive honestly: within-TTL **ALLOWED**, after-TTL **DENIED**. The complete AC remains RED because the mandatory threat-contract document is absent. - Focused real-socket suite is RED with 7 expected failures: missing revoker executable (both Claude observers + generation bump), missing Claude/Pi wiring, missing isolated Claudex observers, and missing D2-v5 disclosure. - Branch-focused Python suite is RED on the wished generation initializer/resolver interfaces and missing `lease_generation.py` / `revoke-lease.py`. - Pi lifecycle suite is RED because the wished standalone `lease-lifecycle.ts` observer/generation module does not exist. ## Locked discipline - RED-first T12b/T30 and observer/generation tests; test commit precedes implementation. - Reuse broker `revoke_lease`; do not fork identity, lease, or transition authority. - Preserve revoke-first/promote-last and WI-1/WI-2 reviewed state machine. - ≥85% attributable executable coverage with real tests. - No author self-review, no merge, no `--no-verify`. ## Local implementation complete (push held) Implemented on the WI-3 base `abd2791f59b3f06f46dd08e55298ced72f6aa7c2` without changing the reviewed broker state machine: - Added `revoke-lease.py`, which authenticates through the existing broker session/generation and invokes `revoke_lease`. A fired observer that cannot confirm broker revocation advances the private generation as a local fence before returning non-zero. - Added `lease_generation.py`: owner/type/mode/size validation, no-follow opens, exclusive bump lock, monotonic `int64` generation, write-all + `fsync`, and fail-closed exhaustion/corruption handling. - `launch-runtime.py` creates `generation-.state` mode `0600` beside the socket before `exec`; `mutator-gate.py` resolves that current file value on every tool check. - Claude settings and isolated Claudex settings now preserve/install `PreCompact`, `SessionStart(compact)`, and resume/clear rollover hooks in addition to the global all-tools gate. - Pi now registers tested `session_before_compact`, `session_compact`→first `context`, and `session_start(reload|new|resume|fork)` handlers. Failed pre-compact revocation cancels compaction; failed post-compact/rollover revocation latches local all-tool denial. - Added PRD requirements, architecture/security/protocol/operations updates, sitemap entry, and the ignored-by-default documentation checklist (force-add required at commit). ### Acceptance and coverage evidence - Focused acceptance: `19/19`; T12b/T30 prints within-TTL **ALLOWED** and after-TTL **DENIED**. - Pi lifecycle: `8/8`, with **100% statements/branches/functions/lines** attributable coverage. - New Python generation/revoker: `24/24`, **99% branch-aware aggregate coverage** (`lease_generation.py` 98%, `revoke-lease.py` 100%). - Mosaic package: `1399/1399`; framework shell Python `24/24`, launch guard `12/12`, permanent launch inventory `14 gated/14 total`. - Existing lease-broker real-socket acceptance: `37/37` within the package run. - Full repository: `43/43` Turbo tasks green; gateway `628 passed / 12 skipped`; Mosaic `1399/1399`. - Root typecheck: `42/42`; lint: `23/23`; format and `git diff --check` green. - Initial direct package test without first building the package reproduced the known missing-`dist/cli.js` harness condition; the canonical root Turbo test (which schedules `@mosaicstack/mosaic#build`) and explicit package build+test are green. No test was weakened. ### Review evidence - Codex uncommitted code review: **APPROVE**, confidence `0.88`, zero findings. Its read-only sandbox could not rerun Vitest, but the author-side focused and full suites above were green. - Codex uncommitted security review: risk **none**, confidence `0.91`, zero findings. - Coordinator-mandated fresh exact-head terra CODE and Opus SECREV remain pending after rebase/push clearance; these local reviews do not replace that final gate. ### Hold and residuals - **DO NOT PUSH OR OPEN A PR YET.** Coordinator requires flake-fix #838 to land, then WI-3 must rebase onto deterministic-green `main` before push. - Merge remains gated on #838, #827 Probe 3, and combined GO. - Named residual retained verbatim: when both observers are entirely missed, within-TTL consequential actions remain allowed; only lease expiry denies after the bounded stale window. No within-window mutator-action bound is claimed. ## Deterministic-main rebase evidence - Fetched and confirmed `origin/main` at `8dfcf1903e385f977121069f798f476eb671fffc` (`#838` bounded broker deadlines, empty-read fail-closure, and de-flaked acceptance client). - Linear rebase completed. The only content conflict was `packages/mosaic/src/mutator-gate/runtime_tools_unittest.py`; resolution retained #838's `subprocess`/`threading` deadline regressions and WI-3's `stat` generation-state coverage. No authority/state-machine choice was ambiguous. - `packages/mosaic/src/mutator-gate/mutator-gate.acceptance.spec.ts` auto-merged on top of #838's shared `requestBrokerReply` helper. No inline socket/`JSON.parse` client was resurrected. - Verified WI-3 has zero diff from `origin/main` for #838-owned `daemon.py`, `broker-test-client.ts`, `lease-broker.acceptance.spec.ts`, `vitest.config.ts`, and `packages/mosaic/package.json`; bounded deadlines and the de-flaked harness are preserved byte-for-byte. - Required verbose acceptance command: **2 files / 56 tests green**. T12b/T30 still prints within-TTL **ALLOWED** and after-TTL **DENIED**. - Full Mosaic package after explicit build: **74 files / 1408 tests green**; deadline unit `2/2`, runtime tools `25/25`, launch guard `12/12`, inventory `14/14`. - Full repository: **43/43 Turbo tasks green**. Root typecheck `42/42`, lint `23/23`, format and diff checks green. - Attributable coverage remains Python **99%** branch-aware and Pi lifecycle **100%** statements/branches/functions/lines. - Push and PR remain held pending combined GO and all WI-3 merge gates. The coordinator-owned promote-lease-lost-ACK SPEC amendment/backstop is acknowledged as a future merge prerequisite and was not retro-expanded into this core rebase/build.