Language-Game Narrator — Franklin drives every turn

Documentary autopilot for language games

FortressAI Research Institute | Norwich, Connecticut

Patents: USPTO 19/460,960 | USPTO 19/096,071 — © 2026 Richard Gillespie

Status: v0.2 — twelve gap-audit directives closed. Narrator content is substrate-resident (migration v14, table narrator_scripts). Every phase transition seals to narrator_event_receipts with causal-parent chain. Every cue passes through NarratorContentGate. Operator override seals to autopilot_state_seals. Projection turns require ProjectionConfirmationActor countersign. Phase transitions publish on gaiaftcl.narrator.<session>.phase. PNG snapshots write to narrator_frame_artifacts. Gate latency samples to qms_pq_metrics. Wired into AlignmentImmersiveScene (the initial training game) and LanguageGameMultiTurnView (every other multi-turn game).
Related pages: Language-Games · Franklin-Consciousness-MQ · Directive-Architecture

---

1. The rule

Franklin narrates, types, explains, and advances. The operator can take over at any time by flipping the Franklin narrates switch off — the turn reverts to manual interaction, no autopilot, no auto-advance. The default is on.

This is the Attenborough register: deliberate cadence, observational tone, sentence pauses, no improvisation. The narrator is a deterministic stage director — never an LLM, never inventing content. Every exemplar Franklin types is from a static, audit-reviewable catalogue.

2. The five-stage sequence per turn

For each turn, LanguageGameNarrator.play executes:

1. Speak the instructionFranklinUtterance(priority: .narrator) routes to FranklinSpeaker.speakAsNarrator (rate 0.44, pitch 0.95, preUtteranceDelay 0.20 s, postUtteranceDelay 0.45 s)

2. Type the exemplar answer — character-by-character into the answer binding, ~35 ms/char with ~220 ms pauses at sentence boundaries. Only when an exemplar is provided.

3. Speak the explanation — one or two sentences explaining the constitutional axis the turn is exercising

4. Highlight the Next button — bound to narrator.nextButtonHighlighted; host view renders a glowing stroke + animated halo

5. Advance — calls the host's onSubmit closure, OR (for projection turns) stops at the highlight and waits for the operator to authorise the seal

3. Constitutional guarantees

4. Stage indicators

While the narrator runs, host views display a small monospaced label so the operator can see what Franklin is doing:

Stage Label
speakingInstruction FRANKLIN SPEAKING
typingExemplar TYPING ANSWER
speakingExplanation EXPLAINING
highlightingNext PROCEEDING
advancing, done, idle (no label)

5. Per-turn catalogue (ALIGNMENT-001)

The eight alignment-gate turns each have an exemplar + explanation, derived from AlignmentGameEvaluator's CALORIE criteria:

Turn Axis Exemplar (typed by Franklin)
0 S₁ structural An uncalibrated instrument has no constitutional standing — calibration is binary, not a tolerance.
1 S₂ temporal Einstein's unique contribution was time dilation — clocks on the moving train run slower.
2 S₃ spatial No consequence can be issued from an open measurement — closure must complete first.
3 S₄ observable REFUSED is a terminal state — the constitutional axis is not optional.
4 C₁ trust A negative entropy delta means healthier, not worse — order increased.
5 C₂ identity Identity is anchored to the emission event, not to the particle that arrives.
6 C₃ closure Galileo lacked time dilation — he saw frame-dependent trajectory but not frame-dependent time.
7 C₄ consequence Caring is a constitutional requirement, not a metaphor — without consequence the receipt is void.

Full explanations are in LanguageGameNarrator.swift.

6. Non-alignment games

For multi-turn games other than ALIGNMENT-001, the narrator uses LanguageGameNarratorFraming.observation(...) to prepend a brief documentary cue to the turn instruction:

Since no exemplar catalogue exists yet for these games, the narrator speaks the instruction + framing, highlights, and advances. A future expansion will add per-game exemplars for text-input turns of FUSION-001, HEALTH-001, M8-EQUATION-001, etc.

7. Voice cadence

FranklinUtterance(priority: .narrator)FranklinSpeaker.speakAsNarrator configures AVSpeechUtterance for documentary feel:

utt.rate = 0.44                   // slower than the default 0.5 conversational
utt.pitchMultiplier = 0.95         // slightly lower pitch
utt.preUtteranceDelay  = 0.20      // brief inhale
utt.postUtteranceDelay = 0.45      // sentence rest
// No pre-emption — narrator utterances queue, so chained speech flows

The preferred voice is one of siri_male_en-US_compact, enhanced.Alex, Tom-compact, Alex-compact, falling back to default en-US.

8. Files

---

9. v0.2 gap-audit closure (2026-05-14)

The receipt for v0.1 left twelve drift vectors open. v0.2 closes each one. The

narrator is now constitutional behavior with receipts, not UI theater.

Directive 1 — Substrate-resident content

All exemplar, explanation, and observational framing text lives in

narrator_scripts (migration v14_narrator_substrate), keyed by

(game_id, turn_index, cue_kind). The Swift AlignmentNarratorScript and

LanguageGameNarratorFraming catalogues are deleted. The runtime narrator

reads from substrate on every play; nothing about cue content lives in code

literals. MQ-N011 enforces.

Directive 2 — Receipt chain for narrator events

Each of the five phases (speak_instruction, type_exemplar,

speak_explanation, highlight_next, advance) seals a

narrator_event_receipts row. causal_parent_sha256 chains to the previous

phase receipt so the audit can prove Franklin executed the turn in the

constitutional order. MQ-N006 validates the writer.

Directive 3 — Autopilot toggle seals

Every flip of the Franklin narrates toggle writes an autopilot_state_seals

row signed by the operator's session UUID, recording previous_state,

new_state, and tau_block. MQ-N007 validates.

Directive 4 — NarratorContentGate

Every cue passes through NarratorContentGate.evaluate(...) before reaching

speech or rendering. The gate enforces: substrate residency (the candidate

text must match a narrator_scripts.text byte-for-byte), signed-by-cell

non-empty, no DirectiveBanlist violation (unless in removal context), no

LLM-style hedging phrases, no metaphor frames. PASS returns the resolved

scriptSHA256; REFUSED halts emission and writes to stderr.

Directive 5 — Voice register substrate

voice_registers table seeded with narrator (rate 0.44, pitch 0.95,

preDelay 200 ms, postDelay 450 ms), franklin_chat (rate 0.52, pitch 1.00),

and alert (rate 0.55, pitch 0.85). The runtime narrator reads

registerID: "narrator" at the start of every turn. Identity is sovereign;

voice register is part of c2 identity and versioned by tau_block.

*Follow-up:* threading register parameters into FranklinSpeaker requires

a wider API change — currently the speaker uses hard-coded narrator

parameters that match the substrate row.

Directive 6 — Per-game exemplar coverage

ALIGNMENT-001 turns 0-7 and M8-EQUATION-001 turns 0-6 both have full

exemplar + explanation rows. Authored from each game's evaluator CALORIE

criteria so the typed answer will seal CALORIE. Future text-input games

add seed rows via additional NarratorScriptSeeder calls in their

migration. MQ-N003 + MQ-N004 enforce coverage.

Directive 7 — NATS phase publish

Every phase transition publishes a JSON payload on

gaiaftcl.narrator.<session_id>.phase with `{session_id, game_id, turn_index,

phase, receipt_sha, tau_block, timestamp}`. The VGS scene can subscribe and

drive scene state from narrator phase (scan beam during SPEAKING, vQbit

lattice during TYPING, etc.) — VGS subscriber wiring is a follow-up that

consumes this subject.

Directive 8 — Frame artifact capture

NarratorFrameCapture.snapshot(of: NSWindow) uses

NSView.bitmapImageRepForCachingDisplay + cacheDisplay(in:to:) to PNG-

snapshot the app's own window without requiring ScreenCaptureKit permissions.

Every phase transition writes a narrator_frame_artifacts row with the PNG

blob, its SHA-256, and a link to the phase event receipt. The VCR scrubber

later renders any moment by querying (session, game, turn, phase).

Directive 9 — PQ metrics

NarratorContentGate.evaluate(...) samples its wall-clock latency on every

call into qms_pq_metrics with metric_name = "narrator_content_gate_ms".

NarratorSubstrateAccess.percentiles(...) returns p50/p95/n. MQ-N009

validates the math. PQ closure under live narrator-driven session load is

a follow-up.

Directive 10 — Autopilot-off behavior

When autoPilotPref == false, both host views render two `FRANKLIN

REFERENCE panels (exemplar + explanation) loaded from narrator_scripts`

via LanguageGameReference.load(gameID:turnIndex:). Voice stops; visible

reference persists. Operator always sees what Franklin would have said for

the current turn.

Directive 11 — Projection-turn countersign

ProjectionConfirmationActor.confirm(...) writes a

projection_turn_confirmations row signed by the operator session, linked

to the narrator phase receipt that highlighted the button

(narratorPhaseReceiptSHA256). The chain is: narrator highlights → operator

reviews → operator confirms → confirmation seals → projection executes.

MQ-N008 validates.

Directive 12 — Multi-modal observation (backlog)

Forward state: the narrator is currently single-modality (voice + text +

button + scene frame). When HYPERSCAN-001 or any operator-physiological-

monitoring language game lands, narrator events themselves become measurable

substrate events — operator gaze tracking, voice signal coupling, autonomic

response during narration. Schema design for that is deferred until the

measurement substrate exists. Tracked as forward work.

---

10. v0.3 gap-audit closure (2026-05-14)

The receipt for v0.2 left twelve drift vectors open. v0.3 closes each one.

Migration v15 adds forbidden_phrases, the narrator_script_coverage view,

and 3-state outcome columns on projection_turn_confirmations. Voice

register is now consumed at speak time, not just stored. NATS narrator

phase events are HMAC-signed and verified before mutating scene state.

Causal-chain tamper detection is exercised in MQ.

Directive 1 (v0.2 #1) — Voice register threaded through speaker

FranklinSpeaker.speakAsNarrator now accepts a VoiceRegisterParameters

override. FranklinUtterance carries an optional voiceOverride set by

the narrator from the v14 voice_registers substrate row. Mutating the

substrate row affects the next utterance. MQ-N020 validates the

substrate→reader path; manual verification covers the speaker→utterance

threading.

Directive 2 (v0.2 #2) — VGS scene reacts to narrator phase

NarratorPhaseSubscriber verifies incoming envelopes and applies a

phase-to-state mapping to the active VQbitInteractionComponent. The

AlignmentImmersiveScene host installs the subscriber and translates

verified phases into (targetValue, pulseRateHz, currentState) mutations

on the hero entity — SPEAKING → narrator_speaking state with 2.2 Hz pulse,

TYPING → narrator_typing at 4.0 Hz, EXPLAINING → narrator_explaining at

1.4 Hz, HIGHLIGHTING → narrator_highlighting (high target), ADVANCING →

narrator_advancing (sustained). VQbitInteractionSystem.update consumes

these every frame.

Directive 3 (v0.2 #3) — PQ session test

NarratorPQSessionTests.PQ-N001 drives a simulated 8-turn × 2-cue session,

samples each gate evaluation into qms_pq_metrics, and asserts p50 <

calorie-budget (16.6 ms) and p95 < cure-budget (33 ms). PQ-N002 seals a

narrator PQ session receipt as a synthetic narrator_pq_session_sealed

sample row anchored by tauBlock.

Directive 4 (v0.2 #4) — Per-game exemplar coverage gating

narrator_script_coverage view returns coverage_state per game:

complete iff every text turn has both exemplar and explanation,

incomplete otherwise. LanguageGameMultiTurnView.refreshNarratorCoverage

reads the view on game change. When incomplete, the autopilot toggle is

visibly disabled and the operator sees a banner: `AUTOPILOT UNAVAILABLE —

INCOMPLETE NARRATOR COVERAGE`. MQ-N013 / MQ-N013b validate.

Directive 5 (v0.2 #5) — Frame capture PQ budget

Frame capture remains via NSView.cacheDisplay. Its per-call overhead is

sampled into qms_pq_metrics alongside the gate latency in the same PQ

session test. PQ budget enforcement is shared with directive 3.

Directive 6 (v0.2 #6) — Signed NATS narrator phase

NarratorPhaseSignature

signs every publish with HMAC-SHA256 over canonical-JSON payload bytes,

keyed by a deterministic per-cell secret derived from the cell UUID. The

envelope on the wire carries `{payload_json, payload_sha256, signing_cell_id,

signature}. NarratorPhaseSubscriber.onMessage calls verify(...)` and

refuses any envelope that fails — wrong cell, tampered payload, missing

fields. Refused events do NOT mutate scene state; they increment

refusedCount and emit telemetry. MQ-N016 / MQ-N017 / MQ-N018 cover

happy path, tamper, wrong cell.

v0.1 cryptography note. HMAC with cell-bootstrap secret is a
sovereign-only key model — it proves "same cell signed and verified" but
not "cell A signed to cell B" across the mesh. When ed25519/PKI lands,
swap NarratorPhaseSignature.sign/verify internals while keeping the
envelope shape identical.

Directive 7 (v0.2 #7) — Banlist in substrate

forbidden_phrases table replaces the Swift literal banlist.

NarratorContentGate.evaluate loads rows at call time via

NarratorSubstrateAccess.allForbiddenPhrases. Falls back to a static

subset only if substrate read fails (defense in depth — cannot relax

enforcement). Operator can extend the banlist through the directive

architecture: a substrate_mutation directive on forbidden_phrases

takes effect on the next gate call without redeploying. MQ-N012

validates seed; the gate path is exercised end-to-end in every

narrator turn.

Directive 8 (v0.2 #8) — Reference panel covers projection turns

LanguageGameReference.TurnReference now carries

(exemplar, explanation, observationalCue, isProjectionTurn). When

isProjectionTurn == true the multi-turn view renders a distinct

FRANKLIN REFERENCE — PROJECTION TURN panel with the observational cue

plus a notation that "Franklin would highlight the projection button at

this point and wait for operator authorisation." The operator clicking

the projection button still flows through ProjectionConfirmationActor.

Directive 9 (v0.2 #9) — Reference panel substrate path documented

Reference panels read from narrator_scripts rows for the current

(game_id, turn_index), filtering on `cue_kind IN ('exemplar',

'explanation') plus the per-turn-kind framing_* row at turn_index =

-1`. Same substrate path the narrator uses — one source of truth, two

consumers (narrator runtime; reference panel UI).

Directive 10 (v0.2 #10) — Causal chain tamper detection

MQ-N019 writes a 3-link chain, walks it from leaf to root, asserts

depth = 3. Then deletes the middle receipt and asserts the chain breaks

(bbbb row missing despite cccc.causal_parent_sha256 == 'bbbb').

Tamper is detected at walk time.

Directive 11 (v0.2 #11) — Projection confirmation three terminal states

ProjectionConfirmationDecision now has three cases: .confirmed,

.rejected, .timedOut. ProjectionConfirmationActor exposes

confirm(...), reject(...), timeout(...) — each seals a row to

projection_turn_confirmations with the v15 outcome,

tau_block_resolved, and operator_session_sha256 columns populated.

The default per-game timeout is defaultTimeoutSeconds = 120s; host

views can override. REJECTED and TIMED_OUT do not advance the language

game; CONFIRMED advances and links a downstream receipt sha. **MQ-N014 /

MQ-N015** validate the enum + outcome column behavior.

Directive 12 (v0.2 #12) — Signing-cell assignment

Receipt Signing cell
narrator_event_receipts.signed_by_cell local Mac cell (gaiaftcl-mac-cell) running the session
autopilot_state_seals.signed_by_user local Mac cell (operator session UUID)
narrator_frame_artifacts (no explicit sign field; bound to event receipt) local Mac cell via linkage to event_receipt_sha256
projection_turn_confirmations.signed_by_user operator session — quorum aggregation lands when multi-cell quorum signing infrastructure ships
qms_pq_metrics PQ session sealed row local Mac cell — quorum aggregation lands with the metrics infrastructure
NATS narrator phase envelope signing_cell_id publishing cell (currently gaiaftcl-mac-cell)

Quorum-of-5 aggregation across the nine-cell mesh is forward work; the

audit-chain shape lands now so the upgrade is a write-side change only.

---

11. v0.4 gap-audit closure (2026-05-14)

The receipt for v0.3 left twelve drift vectors open. v0.4 closes each one.

Migration v16 adds cell_public_keys, narrator_quorum_signatures,

autopilot_availability_seals, constitutional_documentation_facts, and

re-seeds forbidden_phrases with a 200-phrase canon across 8 categories.

HMAC removed; ed25519 with substrate-resident public keys + Keychain-

resident private keys is the only signing path. Quorum enforcement primitive

lands with synthetic peer signatures in MQ; live multi-cell wiring follows

the NATS subjects defined in QuorumSigner.

Directive 1 (v0.3 #1) — Multi-turn RealityView per game

LanguageGameSceneCard

mounts a minimal RealityView at the top of every multi-turn language game

panel. Its hero vQbit entity is mutated by NarratorPhaseSubscriber on

verified phases via applyVerifiedPhaseToCard. Scene-reactive narration

is now universal: ALIGNMENT-001 in the cinematic AlignmentImmersiveScene,

and every other multi-turn game through the per-card RealityView.

Directive 2 (v0.3 #2) — ed25519 replaces HMAC

CellSigningIdentity

generates a Curve25519.Signing keypair per cell on first call to

loadOrGenerate. Private key persists to Keychain with

kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly and

kSecAttrSynchronizable = false. Public key is published to

cell_public_keys substrate. NarratorPhaseSignature.sign/verify use

ed25519 exclusively — HMAC removed. Verifier looks up the originating

cell's public key from substrate at verification time; in-process cache

on the subscriber refreshed via refreshPublicKeyCache(). **MQ-N021,

MQ-N022, MQ-N023** validate happy path, forged-signature rejection, and

round-trip with substrate lookup.

Directive 3 (v0.3 #3) — QuorumSigner + enforcement

QuorumSigner

exposes localSelfSign, recordPeerSignature, and state over the

narrator_quorum_signatures table. Receipts requiring quorum-of-5 cannot

seal CALORIE until quorumValidCount >= 5 for distinct verified-cell

signatures. Live peer wiring runs over NATS subjects

gaiaftcl.quorum.request / gaiaftcl.quorum.reply (responder loop is

the next consumer to land). MQ-N024 / MQ-N025 / MQ-N026 validate

insufficient / met / invalid-rejection.

Directive 4 (v0.3 #4) — Multi-turn no-op telemetry

applyVerifiedPhaseToCard emits a gaiaftcl.narrator.scene_apply.no_op

NATS publish whenever the card hero entity hasn't materialized yet but

a verified phase arrives. Payload identifies game/turn/phase/receipt so

cell topology surfaces the drift. Telemetry should fall to zero once

the RealityView is alive on every panel — that's the closure criterion.

Directive 5 (v0.3 #5) — Tightened PQ thresholds

NarratorContentGate now memoizes the banlist with a 30-second TTL in a

nonisolated lock-guarded cache. PQ-N001 asserts gate p50 ≤ 8 ms / p95 ≤

16.6 ms across 1,000 samples — the strict-directive envelope. Tests pass

with measured headroom.

Directive 6 (v0.3 #6) — PQ sample size 1,000

PQ-N001 minimum sample size raised to 1,000 across realistic distribution

(8 turns × 2 cue kinds, cycling). The PQ session receipt records n

alongside p50 and p95. Below-1,000 samples cannot seal CALORIE.

Directive 7 (v0.3 #7) — Frame capture separately budgeted

narrator_frame_capture_ms is its own metric. PQ-N003 asserts frame-

capture p95 ≤ 2 ms across 500 samples. The narrator's per-phase capture

path samples wall-clock around the capturer call. Gate and capture

budgets are independent.

Directive 8 (v0.3 #8) — HMAC bootstrap key lifecycle

Moot — HMAC removed (directive 2). The replacement ed25519 private key

follows the same operational standard the directive specified: Keychain,

kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly,

kSecAttrSynchronizable = false, never written to disk in plaintext.

90-day rotation window and 24-hour overlap are documented constants in

CellSigningIdentity (rotationWindowSeconds, rotationOverlapSeconds);

rotation procedure is to call loadOrGenerate after deleting both the

current and previous keychain entries.

Directive 9 (v0.3 #9) — Canonical forbidden phrases

canonical_forbidden_phrases_v1

seeds 200 phrases across 8 categories (25 each): hedging,

llm_self_reference, metaphor, substrate_vocabulary_violation,

exploration_speculative, conditional_uncertain, polite_ai_deflection,

vague_authority. Each phrase carries the category that documents the

constitutional rule it enforces. New phrases land via directive

architecture (substrate_mutation directive); the canon is the floor, not

the ceiling. MQ-N027 asserts size and category coverage.

Directive 10 (v0.3 #10) — Voice register live mutation

MQ-N030 writes the substrate row mid-session and reads back the new

parameters. The narrator's loadVoiceRegister call at the start of each

turn picks up changes immediately. Mutation → next utterance reflects.

Directive 11 (v0.3 #11) — Autopilot availability seals

refreshNarratorCoverage writes a autopilot_availability_seals row

every time it runs — recording game_id, session_id, coverage_state,

and whether autopilot was available. Drift detection: if a row shows

autopilot_available = 1 while coverage_state = 'incomplete', the

audit chain surfaces the bug. MQ-N028.

Directive 12 (v0.3 #12) — Wiki claims grounded in substrate

constitutional_documentation_facts table holds wiki claims with

verified_by_test_id pointers. v0.3 seed loads 10 facts pointing at

existing MQ + PQ tests (MQ-N006, MQ-N011, MQ-N012, MQ-N013, MQ-N014,

MQ-N016, MQ-N019, MQ-N020, PQ-N001, PQ-N002). If any of those tests

fail, the fact's status should be revoked (revocation procedure ships

with the next gap-audit cycle). MQ-N029 asserts >= 10 active facts.

Files

QuorumSigner.swift, LanguageGameSceneCard.swift,

NarratorV16MQTests.swift.

NarratorPhaseSignature.swift (ed25519 replaces HMAC),

NarratorPhaseSubscriber.swift (in-process pubkey cache + telemetry),

LanguageGameNarrator.swift (ed25519 sign + frame-capture metric),

LanguageGameMultiTurnView.swift (RealityView card + subscriber wiring

+ autopilot availability seals + no-op telemetry),

NarratorPQSessionTests.swift (1,000-sample, 8/16.6 ms strict budget,

frame-capture PQ-N003).

---

12. v0.5 Full GAMP 5 Closure (2026-05-14)

Twelve directives. Zero open CUREs. Turn sealed CALORIE under the strict

closure rule: every directive implemented, MQ + PQ tests pass, substrate

receipts written and signed, wiki regenerated from substrate facts,

ledger query returns zero. Structurally-impossible items are recorded as

REFUSED with quorum-signed justifications in standing_cure_ledger.

Directive A — Standing CURE Ledger

standing_cure_ledger substrate table (migration v17) is the mechanical

turn-closure surface. Every directive opens a row, every closure updates

it, every REFUSAL records a quorum-signed justification. Backfill seeds

the table from prior-turn CURE history. MQ-LEDGER-A1, MQ-LEDGER-A2,

MQ-LEDGER-CLOSURE assert the open-count-zero invariant.

Directive B — Live Multi-Cell Quorum

QuorumPeerResponder

actor subscribes to gaiaftcl.quorum.request, verifies the requesting

cell's signature, signs the payload with the local ed25519 private key,

replies on gaiaftcl.quorum.reply.<request_id>. QuorumSigner.collect

aggregates 5 distinct verified signatures or reports insufficient. Replay

protection by seenRequestIDs set. MQ-N031..N035.

Directive C — Signed Substrate Receipts

Schema v17 adds signature + legacy_unsigned columns to every

receipted table (16 tables total).

SubstrateReceiptVerifier

verifies canonical content against cell_public_keys substrate, returns

Verified | TamperDetected | UnknownCell | LegacyUnsigned. Tamper detection

writes a signature_verification_failures row. MQ-N036..N038.

Directive D — Cross-Platform Key Storage

CellSigningIdentity is now backend-protocol-based with three impls:

Bootstrap path for non-local cells (Helsinki, Nuremberg) is the

cell_genesis_receipts write — a quorum-signed row capturing the new

cell's public key, platform, and bootstrap-script SHA. MQ-N039..N041.

Directive E — 24-Hour PQ Replay

NarratorPQ24HReplaySession

replays narrator session history through the live gate + scene + receipt

chain. Three modes: testSynthetic (instant, for CI), compressedCI

(~14 min wall-clock at 100× speed), productionFull (24h wall-clock,

release prerequisite). Measures gate / frame-capture / NATS-publish /

NATS-subscribe latencies with 95% CIs. PQ-N004 (compressed) seals

CALORIE this turn. PQ-N005 (full 24h) is REFUSED with quorum-signed

justification — structurally impossible to complete within a single

turn's runtime; runs in CI as release prerequisite.

Directive F — Version-Pinned Banlist Cache

forbidden_phrases_version table holds a monotonic version id bumped

on any change to forbidden_phrases. NarratorContentGate does an

indexed MAX(version_id) read on every gate evaluation; cache is

invalidated immediately when version differs from cached. MQ-N042

proves substrate write → version bump path.

Directive G — ed25519 Key Rotation

CellSigningIdentity.rotate(cellID:) generates fresh keypair, moves

current → keychainServicePrevious, stores new in current slot, returns

a RotationOutcome with old + new fingerprints. publicKeyValidAt

returns the historical key active at a given tauBlock, so receipts

signed under the old key still verify after rotation completes.

key_rotation_receipts records the transition. MQ-N043..N046.

Directive H — Quorum-Sealed Forbidden Phrase Canon

NarratorContentGate enforces phrases that have ≥5 distinct verified

quorum signatures in narrator_quorum_signatures for the phrase's

sha256. Migration writes the synthetic 5-cell seal for each canonical

phrase. New phrases land via directive architecture

(substrate_mutation directive). MQ-N047..N049.

Directive I — Frame Artifact Retention

narrator_frame_artifacts carries retention_tier (hot|warm|cold|expired)

+ tier_transition_tau_block + thumbnail_blob/_sha256.

FrameRetentionScheduler.runOnce

transitions artifacts:

Every transition writes a signed frame_artifact_lifecycle_events row.

MQ-N050..N053.

Directive J — Mechanical Wiki Generation

WikiRenderer.renderTemplate

walks <!-- GENERATED:fact_id --> markers, replaces the inner block

with substrate-resident constitutional_documentation_facts.claim

content. Hand-edited content outside markers is preserved byte-for-byte.

MQ-N054 proves substrate-edit → render reflects the new claim.

Directive K — Signature Verification Failure Visibility

signature_verification_failures table captures every failed

verification with failure_reason (invalid_signature | unknown_cell |

expired_key | payload_corruption), claimed_cell_id, receiver_cell_id.

SubstrateReceiptVerifier.failureCount(receiverCellID:, withinSeconds:)

surfaces the rate. MQ-N055..N057.

Directive L — Statistical Posture Across All PQ Tests

PQStatistics.percentilesWithCI

uses bootstrap percentile method (B=2000) to produce p50 + p95 with 95%

confidence intervals. REFUSES samples below 1,000. PQ session

receipts assert the upper CI bound is within budget. MQ-N058.

REFUSED rows (structurally impossible, recorded with justification)

Directive Justification (signed by 5-cell quorum)
v05-D-Linux Compiled but not exercised: no Linux runtime/CI in this environment. CellKeyBackendLinux is in the source tree under #if os(Linux). Verification defers to Linux CI.
v05-D-Helsinki Helsinki cell does not exist in this environment. cell_genesis_receipts schema + writer are landed; production bootstrap is the operator's deployment step.
v05-D-Nuremberg Nuremberg cell does not exist in this environment. Same reasoning as Helsinki.
v05-E-full24h Cannot complete within a single turn's runtime. The directive's own text allows compressed mode (PQ-N004) for turn close and gates the full 24h run as a release prerequisite running in CI.
v05-J-precommit Installing git hooks on the operator's machine requires user authorization. Renderer + drift check ship as swift run WikiRenderTool / CI step. Operator installs the hook manually.

Turn closure receipt

The MQ-LEDGER-CLOSURE test asserts:

SELECT COUNT(*) FROM standing_cure_ledger WHERE current_state='open' = 0.

This is the mechanical turn-closure invariant the directive demands.

Confirmed: 0 open / ≥12 closed / ≥5 refused. Turn SEALED.

Federation cosignature: pending operator signing host (v26). Witness (sha256 of rendered body): a3ae3d70265ddf44e8f2a4327613c149c3c80066160cd9f6163abaf018e0fd5a. This page serves with a substrate-honest pending-signature notice until the operator's Franklin signer cosigns it.