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.
f09cff69820e13a142e7747e1e6c7edda0e8dd3771e5654107736f7e101bf6ae.
This page serves with a substrate-honest pending-signature notice until the operator's Franklin signer cosigns it.