Files
stack/docs/scratchpads/830-compaction-revoke.md
jason.woltje e4d7d4502d
All checks were successful
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
WI-3 (#830): compaction observers → revoke + D4 same-PID generation auto-revoke (#842)
2026-07-19 19:46:28 +00:00

9.5 KiB

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-<broker-session>.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.