Skip to content

Force one boot at the compaction boundary - #737

Closed
clkao wants to merge 3 commits into
mainfrom
spacedock-ensign/force-boot-at-compaction-boundary
Closed

Force one boot at the compaction boundary#737
clkao wants to merge 3 commits into
mainfrom
spacedock-ensign/force-boot-at-compaction-boundary

Conversation

@clkao

@clkao clkao commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator

A compacted First Officer session keeps its narrative and loses its bindings. It does not know it is a new session, so it never re-reads durable state. Six failures in one session traced to that, including a bypassed merge mod and four gates reported as presented that were never prepared.

What changed

  • Write a one-line session boot receipt at status --boot.
  • Refuse gate record, gate consume, and merge guard when a compaction postdates the receipt.
  • Derive the verdict from the transcript's durable compact_boundary record only.
  • Fail open on every degradation: no identity, no transcript, unreadable receipt.
  • Key the receipt on the shared git common dir, so a worktree and its main checkout agree.

Evidence

  • go test ./... and -race: green, one pre-existing environment-local failure reproduced identically on main.
  • 24-row degradation matrix correct; 0 of 2000 spurious refusals under concurrent writes.
  • Both refusal call sites proven falsifiable by hand: disabling them turns all three wiring tests red.
  • The boundary was proven by live capture on Claude Code 2.1.226, including this repository's own incident boundary.

The mechanism was chosen after capture disproved two alternatives. A PreCompact hook fires on compactions the host then refuses. Session identity survives compaction, so an identity check can never fire.

Three deferred risks are recorded in the entity with promote conditions, including two one-line hardenings (O_NOFOLLOW, 0o700) recommended without blocking.


4c

🤖 Generated with Claude Code

clkao and others added 3 commits August 18, 2026 21:11
A compacted FO session keeps its session id and transcript but never re-reads
mods/gates/state, because Startup believes it is a continuation. status --boot
now writes a one-line per-session receipt (.spacedock/boot/{session_id}); the
three authority verbs (gate record, gate consume, merge guard) refuse (exit 4,
BOOT_STALE) when the receipt is missing or older than the session's latest
compact_boundary record, naming the exact remedy (re-run status --boot). No
hook, no escape hatch; every degraded condition (no identity, no transcript,
a malformed receipt) fails OPEN, never closed, so a false refusal can never
outrank the guard's real job of stopping authority from landing on stale
bindings.

The Claude-specific transcript-path glob moved into internal/claudeteam's
existing TranscriptProbe seam (mirroring TeamStateProbe) to satisfy the
internal/status host-neutrality invariant. Along the way, fixed a latent
hermeticity gap in three existing test files (merge_test.go,
gate_ceremony_count_test.go, recorded_gate_lifecycle_test.go) that forwarded
the live process's CLAUDE_CODE_SESSION_ID into fixtures with no boot receipt —
harmless before this guard existed, but a spurious failure source once it did.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Validation cycle 2 found one material bug: bootGuardVerdict refused on EVERY
os.ReadFile error, so an unwritable .spacedock/boot (permission denied, a
read-only mount, the receipt path existing as a directory) read as "never
booted" and refused gate record/gate consume/merge guard permanently, while
status --boot exited 0 and silently swallowed the failed write. The guard's
own promised remedy ("one cheap idempotent boot") could never clear it.

Fix: refuse only on errors.Is(err, fs.ErrNotExist); every other read error
fails open with a stderr warning, matching the direction the design already
uses for an unreadable transcript. status --boot now surfaces a failed
receipt write (create or write) as a stderr warning instead of swallowing it,
so a stuck operator can see why re-running boot never helps. Both refusal
messages now name the resolved receipt path.

Also folded in the two one-token deferred risks flagged alongside the main
finding: booted_at is now written and compared at RFC3339Nano precision (a
compaction completing in the same wall-clock second as boot no longer
truncates backwards past it), and the receipt line is split with SplitN
instead of Fields (a transcript path containing a space no longer silently
disables detection). Each has a regression test proven to fail against the
pre-fix code and pass against the fix.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Cycle 3 of force-boot-at-compaction-boundary: addresses the captain's
validation rejection on receipt LOCATION only. The receipt moves from
{gitRoot}/.spacedock/boot/{session_id} to host scratch at
/tmp/spacedock-boot/{session_id}-{repo identity token}, mirroring the
existing internal/dispatch dispatchFileDir convention. This deletes the
.gitignore entry, fixes the read-only-project-root write failure, and
eliminates the cwd/workflow git-root divergence deferred risk by keying
the receipt on the repo's shared git-common-dir rather than a
per-worktree git root.

Also completes a half-finished piece of the inherited work: the
internal/cli wiring tests still wrote fresh receipts at the old in-repo
path, which made all three guarded-verb wiring tests fail after the
relocation. Exported status.BootReceiptPath so the wiring test can
locate the real production path without duplicating the repo-identity
hashing scheme.
@clkao

clkao commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator Author

Closing unmerged. The captain rejected the mechanism, not the diagnosis.

The receipt-plus-guard design was chosen after ideation rejected a host hook on three grounds. Two do not hold: "produced nothing at the incident boundary" is circular, because no hook was installed at the incident; and "PreCompact false-positives on refused compactions" is true of PreCompact but not of SessionStart(source:compact), which the same capture shows firing exactly once on a completed compaction.

That leaves "advisory-only" as the sole real objection, against the standing evidence that the FO's deferred-load contract is entirely advisory and fires reliably at its triggers.

Re-doing this as a SessionStart(source:compact) instruction. The compaction diagnosis, the live capture evidence, and the three-verb scope all stand and are retained in the entity.

@clkao clkao closed this Aug 19, 2026
@clkao
clkao deleted the spacedock-ensign/force-boot-at-compaction-boundary branch August 19, 2026 15:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant