GAMP 5 Qualification System

Audience: Engineers running, interpreting, and extending the IQ/OQ/PQ qualification suite.
Updated: 2026-05-05

---

What GAMP 5 means here

GAMP 5 (Good Automated Manufacturing Practice 5) is borrowed from pharmaceutical

software validation. It gives the sovereign qualification a three-phase structure:

Phase What it proves When it can run
IQ — Installation Qualification All sovereign components are correctly bundled and reachable Immediately at launch; no running stack required
OQ — Operational Qualification The running stack produces correct outputs Requires SovereignStackLauncher.phase == .ready
PQ — Performance Qualification The stack meets latency and throughput budgets Requires full operational stack

---

Test counts

Suite Tests Where
swift test GAMP 5 suites 156 Tests/GAMP5/
In-app IQ/OQ/PQ runner 18 SovereignQualificationRunner.swift

The 156 swift test tests are the build-time gate. The 18 in-app checks are

the live runtime gate — they run inside the shipping Franklin.app against the

actual running stack.

Sovereign loop threshold: ≥155/156 tests passing = CALORIE-eligible.

In-app gate: 18/18 = CALORIE.

---

Running the in-app qualification

1. Launch Franklin.app (from the DMG or directly from .build/)

2. Click the hexagon status bar icon → Run Qualification…

3. The Sovereign Qualification window opens.

4. Click RUN QUALIFICATION (top right, teal button).

5. IQ runs immediately, OQ and PQ follow sequentially.

6. Results are written to ~/Library/Application Support/GaiaFTCL/qualification/.

---

IQ checks (7 total)

ID Check Passes when
IQ-001 Franklin sovereign binary active App is executing (trivially true)
IQ-002 VQbitVM bundled inside Franklin.app Contents/Resources/bin/VQbitVM exists
IQ-003 FranklinConsciousnessService bundled Contents/Resources/bin/FranklinConsciousnessService exists
IQ-004 Sovereign NATS bus live on port 4222 TCP connect to 127.0.0.1:4222 succeeds within 2s
IQ-005 C4MemoryStore schema valid (GRDB) C4MemoryStore.shared.recall(query:limit:) returns without throwing
IQ-006 Quantum algorithm catalog complete SUM(algorithm_count) on active quantum-family contracts == LanguageGameCircuitRegistry.expectedQuantumAlgorithmCount() (registry-derived; currently 21)
IQ-007 S4DeltaWire codec frozen at 53 bytes S4DeltaCodec.encode(wire).count == S4DeltaWire.byteCount

---

OQ checks (7 total)

ID Check Passes when
OQ-001 VQbitVM emitted vm.ready SovereignStackLauncher.phase == .ready
OQ-002 C4 constitutional health measurable mean(c1..c4) > 0 from live ManifoldOverlayStore
OQ-003 Terminal state derivation correct health >= 0.65 → .calorie, 0.35..0.65 → .cure, < 0.35 → .blocked
OQ-004 Sovereign cell quorum met liveCells >= 5 OR stackReady (standalone mode)
OQ-005 Awakening ceremony completed ManifoldState.timestampUTC is non-empty
OQ-006 C4MemoryStore contains genesis record Memory store has a GENESIS event from this session
OQ-007 Quantum proof invariant Same derived count as IQ-006 (GRDB sum when substrate available, else registry)

OQ-004: Cell quorum in standalone mode

OQ-004 has two pass paths:

Path A — External mesh (production deployment with HEL/NBG nodes):

Mesh edge IQ (deploy tooling tracked + staged): scripts/gamp5_mesh_deploy_iq.sh — see MESH_SUBSTRATE_DEPLOY_GAMP5.md.

liveCells >= CellDescriptor.quorumRequired (5)

liveCells is populated in FranklinDriver when gaiaftcl.cell.<id>.heartbeat

messages arrive from HEL-01..HEL-05 / NBG-01..NBG-04 external nodes.

Path B — Standalone sovereign (single-machine DMG deployment):

stackReady == true  (SovereignStackLauncher.phase == .ready)

VQbitVM is the sovereign substrate. When it publishes gaiaftcl.vm.heartbeat,

FranklinDriver marks all 9 mesh cell IDs live (see NATS architecture doc).

After the first heartbeat (~30s post-launch), OQ-004 passes via Path A with

9/9 cells live. Before the first heartbeat, it passes via Path B.

---

PQ checks (4 total)

ID Check Passes when
PQ-001 S4DeltaCodec encode < 1ms 1000-encode mean < 1,000,000 ns
PQ-002 C4MemoryStore recall < 500ms Full event log recall in < 500ms
PQ-003 C4 health formula deterministic mean(c1..c4) stable to 6 decimal places × 1000 samples
PQ-004 MQ gate coverage ≥ 38 invariants mqGateCoverageCount() >= 38

---

Receipt files

After each run, three JSON receipts are written:

~/Library/Application Support/GaiaFTCL/qualification/
  IQ-<timestamp>.json
  OQ-<timestamp>.json
  PQ-<timestamp>.json
  qualification.log          ← human-readable one-line-per-phase summary

qualification.log format:

[2026-05-05T20-30-28Z] IQ: CALORIE — 7/7 pass
[2026-05-05T20-30-28Z] OQ: CALORIE — 7/7 pass
[2026-05-05T20-30-28Z] PQ: CALORIE — 4/4 pass

Each JSON receipt has overallStatus ("CALORIE" or "BLOCKED"), platform,

swiftVersion, and a testResults array with id, name, passed, detail,

and durationMs.

---

Adding a new check

1. Add a record(QualResult(...)) call in SovereignQualificationRunner.swift

inside runIQ(), runOQ(), or runPQ().

2. Update the total count comment in this doc.

3. The check is included automatically in the phase receipt.

4. Never change an existing passed: expression to make a failing check pass.

Fix the implementation; the check is the spec.

---

The swift test GAMP 5 suites

The build-time tests live in Tests/GAMP5/ and cover:

Suite Directory Count
IQ — Architecture invariants Tests/GAMP5/IQ/ ~20
OQ — Operational invariants Tests/GAMP5/OQ/ ~80
PQ — Performance invariants Tests/GAMP5/PQ/ ~20
MQ — Mathematical/constitutional invariants Tests/GAMP5/MQ/ (via FranklinConsciousnessMQTests) ~36
Live game integration Tests/GAMP5/PQ/LiveGameIntegrationTests.swift 2

LiveGameIntegrationTests (PQ-LIVE-001 and PQ-LIVE-002) are the PQ closure tests:

they run the real FranklinDriver.propose() gate against an in-memory SwiftData

container and assert that every domain produces a sealed ClosureReceiptRecord.

---

Sovereign qualification window — implementation notes

SovereignQualificationWindow (Sources/GaiaFTCLApp/SovereignQualificationWindow.swift)

is a SwiftUI view opened via:

// In GaiaFTCLApp.swift:
Window("Sovereign Qualification", id: "qualification") {
    SovereignQualificationWindow(launcher: launcher)
        .environment(franklinDriver)
        .environment(overlay)
}
.defaultSize(width: 620, height: 580)

// In FranklinMenuBarView:
@Environment(\.openWindow) private var openWindow
Button("Run Qualification…") { openWindow(id: "qualification") }

SovereignQualificationRunner is @Observable @MainActor. Its run() method

stores weak references to FranklinDriver, ManifoldOverlayStore, and

SovereignStackLauncher. Results stream into runner.results as each check

completes, driving the live list in SovereignQualificationWindow.

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