Six-agent design swarm executed end-to-end on 2026-05-07 evening per
.planning/architecture/HANDOFF-2026-05-07.md. The architectural pivot
to API-first reaches lock state: v1.0 = JARVIS-API-DESIGN-v0.1.md +
JARVIS-API-DESIGN-v0.2.md (UQ-1..UQ-5 answered).
Swarm output (.planning/architecture/):
- INVENTORY.md (~190 capabilities, file:line cited; ALIVE/DEAD/
DEFERRED/RETIRED-CANDIDATE classification)
- JARVIS-API-DESIGN-v0.1.md (1036 lines; 7 surfaces — Turn / Voice /
Memory / Vision / Settings / Diagnostics / Self; CQRS framing;
TurnID universal correlation; typed Results)
- REVIEW-API-CORRECTNESS.md (21 findings: 2 BLOCKING, 5 HIGH)
- REVIEW-MIGRATION-RISK.md (19 findings: 1 BLOCKING, 7 HIGH;
M-0..M-7 cutover sequence)
- REVIEW-TEST-CONTRACT.md (16 findings: 2 BLOCKING, 5 HIGH; harness
shape recommendation)
- JARVIS-API-DESIGN-v0.2.md (synthesis delta; every critic finding
dispositioned ACCEPT/DEFER/USER-DECISION; UQ-1..UQ-5 locked in §5)
- JARVIS-API-TEST-CONTRACT.md (~70 scenarios across 7 surfaces +
cross-surface; B-02..B-08 reproduction matrix)
- JARVIS-API-MIGRATION-PLAN.md (M-0..M-7 + B-02 tactical patch;
~52 distinct gates; 19-26 engineer-day estimate)
- README.md (artifact index + reading order)
Locked decisions:
- UQ-1: runtime gate JARVIS_HARNESS=1 (single binary)
- UQ-2: B-02 tactical patch outside migration + streamTruncated
regression test; B-04 stays in M-6
- UQ-3: explicit Voice.synthesizeTurn(turnId:text:tier:) command
- UQ-4: Settings owns ALL configuration mutation; Voice retains only
runtime-control verbs (pttDown/pttUp/cancelTTS/synthesizeTurn);
bargeIn migrates to Turn surface
- UQ-5: parametric harness mandated — every scenario runs
.inProcessActor AND .jsonRoundTripWebView
Tools/jarvis-diag/ — Swift Package skeleton authored by Phase 5:
type signatures + scenario stubs only, no implementation logic.
Compiles green (swift build under Tools/jarvis-diag/). M-0 step 3
wires it against packages/JarvisAPI/ once that package exists.
Constraints honored: zero code changes outside .planning/architecture/
and Tools/jarvis-diag/. No fixes to B-02..B-08 inline. Parallel agents
wrote disjoint files (.continue-here.md anti-pattern preserved).
Next session: cross-AI peer review of v1.0 (GPT-5 Pro / Gemini 2.5 Pro
/ fresh Opus), then B-02 tactical patch on develop, then M-0 (pre-
migration gates), then M-1 (Self surface) on its own feature branch.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
jarvis-diag
Programmatic test harness for the Jarvis API contract (v1.0).
What this is
jarvis-diag is the codified shape of the harness described in
JARVIS-API-TEST-CONTRACT.md.
It is the boundary-level harness — every scenario drives JarvisTestHarness (the
actor in Sources/JarvisDiag/JarvisTestHarness.swift) and asserts on Commands /
Events / Queries from the v1.0 surface set, never on substrate internals.
At Phase 5 (this commit) the package is type-signatures only. Every Swift
file in Sources/JarvisDiag/ is doc-commented with the test-contract scenario IDs
it covers. Method bodies are fatalError("not implemented — IMPL: <scenario-id>").
The package compiles green; tests are empty.
Implementation lands during the migration (M-0 .. M-7) per
.planning/architecture/JARVIS-API-MIGRATION-PLAN.md.
Relation to packages/Harness/
packages/Harness/ is the substrate-level harness — MockLLMProvider,
WakeHysteresisRunner, MCPCrashRunner, AudioGraphRebuildRunner, fixture corpora,
oracles. These types are still useful: most of them get rehoused as concrete
implementations of ProviderOverrides collaborators or as _inject* test seam
adapters that JarvisTestHarness composes. See REVIEW-TEST-CONTRACT §"Relation to
existing packages/Harness/" for the lift plan.
The new Tools/jarvis-diag/ is API-boundary tests, the packages/Harness/
library is substrate runners that jarvis-diag consumes.
Harness mode
All test seams (_injectAudioFrame, _forceTCCStatus, _forceError,
ProviderOverrides, setConfirmationDefault, etc.) are gated by JARVIS_HARNESS=1
runtime env (UQ-1 lock). Production launches don't set the var; the gate fails
closed with a typed HarnessGateClosed error.
When JARVIS_HARNESS=1 is set, the host writes to
~/Library/Application Support/Jarvis-Harness/ so harness runs never touch
production state.
Transport modes
Per UQ-5, every scenario runs in two modes:
.inProcessActor— direct Swift actor calls.jsonRoundTripWebView— Commands as JSON, real WKWebView, Events read viaWKScriptMessageHandler
ScenarioRunner.run(_:in:) parametrizes scenarios across both modes by default.
Mode-restricted scenarios (provider-stub-only, transport-only) declare their
restrictions explicitly. See test contract §9.
Layout
Tools/jarvis-diag/
├── Package.swift
├── README.md (this file)
├── Sources/JarvisDiag/
│ ├── JarvisTestHarness.swift — main actor; surface accessors; test seams
│ ├── ProviderOverrides.swift — mock LLM / embedder / extractor doubles
│ ├── APIClock.swift — APIClock protocol; RealClock + ManualClock
│ ├── ErrorInjector.swift — _forceError plumbing
│ ├── TransportMode.swift — .inProcessActor | .jsonRoundTripWebView
│ └── Scenarios/
│ ├── ScenarioRunner.swift — parametric runner
│ ├── B02HistoryThreading.swift — X-004 + B02-fix
│ ├── B03CameraButton.swift — Vis-001 + B03-fix
│ ├── B04VoiceLoop.swift — V-006 + B04-fix
│ ├── B05TTSSynthesize.swift — X-003 + B05-fix
│ ├── B08ModelParaphrase.swift — Sf-001 + B08-fix
│ ├── CrossSurfaceVoiceTurn.swift — X-001
│ ├── CrossSurfaceVisionTurn.swift — X-002
│ ├── CrossSurfaceMultiTool.swift — X-005
│ ├── CrossSurfaceProviderSwap.swift — X-006
│ ├── CrossSurfaceTCCRevoke.swift — X-007
│ └── ReplayRoundtripOracle.swift — X-008
└── Tests/ — empty at Phase 5
Building
cd Tools/jarvis-diag
swift build # type-check only — bodies are fatalError
swift test # no tests yet