Context
#14166 (the freeze → auto-unfreeze / re-heal cycle — the #1 weeks-bar risk) splits cleanly into a pure substrate (the decision logic + durable state + orchestration) and the live daemon wiring (the real health probe, the privileged unfreeze execution, the periodic pipeline tick, and the freeze-WRITE at the freeze-apply point).
The wiring half is gated: V-B-A confirms DataIntegrityDiagnosisService.mjs:154 is still escalate-only ("never a privileged action") — the apply()-cutover (#14138 producer re-route + the service heal-wiring that consumes the merged #14143 dispatch core) hasn't landed, so freeze isn't yet applied through the live diagnosis→actuator path and there's no freeze-record to re-probe. The substrate half has no such dependency and is delivered + tested here, de-risking the gated integration (the #14146 pure-helpers-first precedent).
Scope (this leaf — all delivered)
freezeReprobeDecision.mjs — decideFreezeReprobe (pure): unfreeze (fault cleared → re-heal) / defer (within back-off) / stay-frozen (fault persists or inconclusive) / contained (unfreeze-attempt cap → persistent fault) / unsafe-input. Fails CLOSED to stay-frozen (the safety inversion vs healActionDispatch: a frozen collection is the contained-safe state, so a missing record / non-finite clock / inconclusive probe never auto-unfreezes). Exponential back-off (backoffMultiplier^attempts) + an unfreeze-attempt cap (anti-thrash).
freezeRecordStore.mjs — durable, mutable, keyed-by-collection freeze-STATE ({faultFingerprint, frozenAt, unfreezeAttempts, lastProbeAt}); fail-safe read (missing/corrupt → empty set). Distinct from the append-only heal-event ledger (#14163 telemetry).
runFreezeReprobeCycle (in freezeReprobeDecision.mjs) — orchestrates the frozen set: a cheap pre-decision skips a probe for within-back-off / contained / bad-record collections, then probes only the due ones, re-decides, and executes via INJECTED ops (probe / unfreezeAndReheal / persistProbe / clearFreeze). Anti-hot-loop: the unfreeze attempt is recorded BEFORE execution.
Acceptance criteria (delivered by the PR)
Gated follow-up (stays on #14166)
The live wiring — a real embedder/dimension health probe, the privileged unfreeze + re-enter-heal execution, the periodic re-probe tick in the data-integrity sweep, and the freeze-record WRITE at the freeze-apply point — lands once the apply()-cutover (#14138 + the DataIntegrityDiagnosisService heal-wiring) makes freeze a live applied action.
Refs #14166 · Refs #14134 · Refs #14039
Authored by Grace (Claude Opus 4.8, Claude Code). Session 090a68e6-1a28-4b20-a5fd-842ebac3e729.
Context
#14166 (the freeze → auto-unfreeze / re-heal cycle — the #1 weeks-bar risk) splits cleanly into a pure substrate (the decision logic + durable state + orchestration) and the live daemon wiring (the real health probe, the privileged unfreeze execution, the periodic pipeline tick, and the freeze-WRITE at the freeze-apply point).
The wiring half is gated: V-B-A confirms
DataIntegrityDiagnosisService.mjs:154is still escalate-only ("never a privileged action") — the apply()-cutover (#14138 producer re-route + the service heal-wiring that consumes the merged #14143 dispatch core) hasn't landed, sofreezeisn't yet applied through the live diagnosis→actuator path and there's no freeze-record to re-probe. The substrate half has no such dependency and is delivered + tested here, de-risking the gated integration (the #14146 pure-helpers-first precedent).Scope (this leaf — all delivered)
freezeReprobeDecision.mjs—decideFreezeReprobe(pure):unfreeze(fault cleared → re-heal) /defer(within back-off) /stay-frozen(fault persists or inconclusive) /contained(unfreeze-attempt cap → persistent fault) /unsafe-input. Fails CLOSED to stay-frozen (the safety inversion vshealActionDispatch: a frozen collection is the contained-safe state, so a missing record / non-finite clock / inconclusive probe never auto-unfreezes). Exponential back-off (backoffMultiplier^attempts) + an unfreeze-attempt cap (anti-thrash).freezeRecordStore.mjs— durable, mutable, keyed-by-collection freeze-STATE ({faultFingerprint, frozenAt, unfreezeAttempts, lastProbeAt}); fail-safe read (missing/corrupt → empty set). Distinct from the append-only heal-event ledger (#14163 telemetry).runFreezeReprobeCycle(infreezeReprobeDecision.mjs) — orchestrates the frozen set: a cheap pre-decision skips a probe for within-back-off / contained / bad-record collections, then probes only the due ones, re-decides, and executes via INJECTED ops (probe/unfreezeAndReheal/persistProbe/clearFreeze). Anti-hot-loop: the unfreeze attempt is recorded BEFORE execution.Acceptance criteria (delivered by the PR)
contained(stays frozen) — #14166 AC3 at the logic layer.Gated follow-up (stays on #14166)
The live wiring — a real embedder/dimension health probe, the privileged unfreeze + re-enter-heal execution, the periodic re-probe tick in the data-integrity sweep, and the freeze-record WRITE at the freeze-apply point — lands once the apply()-cutover (#14138 + the
DataIntegrityDiagnosisServiceheal-wiring) makesfreezea live applied action.Refs #14166 · Refs #14134 · Refs #14039
Authored by Grace (Claude Opus 4.8, Claude Code). Session 090a68e6-1a28-4b20-a5fd-842ebac3e729.