v1.0 API Migration — UI/Backend separation (M-0..M-7) #76

Open
opened 2026-05-12 19:26:53 +00:00 by KofTwentyTwo · 0 comments
KofTwentyTwo commented 2026-05-12 19:26:53 +00:00 (Migrated from github.com)

Goal

Separate the SwiftUI/AppKit + WKWebView UI surface from the Swift backend behind a typed JarvisAPI package, with a parametric harness running every behavioral scenario against BOTH .inProcessActor AND .jsonRoundTripWebView runners. The full v1.0 contract is defined in .planning/architecture/JARVIS-API-DESIGN-v0.1.md + JARVIS-API-DESIGN-v0.2.md and executed via the per-phase migration cards in JARVIS-API-MIGRATION-PLAN.md (M-0..M-7).

Why

The 2026-05-03 / 2026-05-04 audits surfaced 8 carry-forward bugs (B-01..B-08) all rooted in a single class of failure: "verification gate is executor self-reports green tests + boundary gates, which cannot detect substrate failures." Grep-based gates pass while runtime substrate is dead (voice graph nil, camera button no-op, history threading missing, sessionHistory never read). The v1.0 contract dissolves the entire class by forcing every behavior through a typed API surface and running every scenario through a real WKWebView JSON round-trip — making "looks green but is broken" detectable at PR time.

Design artifacts (source of truth)

  • .planning/architecture/README.md — index
  • .planning/architecture/JARVIS-API-DESIGN-v0.1.md — v1.0 contract part 1 (surfaces, commands, events, queries)
  • .planning/architecture/JARVIS-API-DESIGN-v0.2.md — v1.0 contract part 2, UQ-1..UQ-5 answered
  • .planning/architecture/JARVIS-API-MIGRATION-PLAN.md — the spine; per-phase scope/files/tests/AC/dependencies/estimates
  • .planning/architecture/JARVIS-API-TEST-CONTRACT.md — parametric harness contract (UQ-5 mandatory)
  • .planning/architecture/INVENTORY.md — surface inventory
  • .planning/architecture/REVIEW-API-CORRECTNESS.md — correctness review
  • .planning/architecture/REVIEW-MIGRATION-RISK.md — risk findings R-001..R-018 and per-phase cutover risks
  • .planning/architecture/REVIEW-TEST-CONTRACT.md — test contract review
  • .planning/architecture/HANDOFF-2026-05-07.md — design swarm handoff

Locked decisions (UQ-1..UQ-5)

  • UQ-1 — Harness runtime gate: JARVIS_HARNESS=1 env var. Test seams (_injectAudioFrame, _forceTCCStatus, _forceError, ProviderOverrides, setConfirmationDefault) ONLY effective when env var set. Production launches fail closed.
  • UQ-2 — B-02 path: tactical patch on develop (DONE 2026-05-11, commit 48ad8d6) BEFORE M-0 starts. M-4 reframes against the new surface + adds the cache-eligibility regression gate.
  • UQ-3 — TTS contract: (A) explicit-command — orchestrator MUST issue Voice.synthesizeTurn(turnId:text:tier:) on turnEnded(.completed) for voice-source turns. No implicit TTS routing.
  • UQ-4 — Config writer: Settings owns ALL configuration mutation. Voice surface loses setTTSTier, muteWakeWord, unmuteWakeWord, startVoice, shutdownVoice. Voice retains only runtime-control verbs (pttDown, pttUp, cancelTTS, synthesizeTurn).
  • UQ-5 — Parametric harness MANDATORY: every scenario runs in both .inProcessActor AND .jsonRoundTripWebView modes. .jsonRoundTripWebView is non-skippable for B-03-class regressions (M-5 S-VIS-001).

Phase dependency DAG

B-02 tactical patch (DONE 2026-05-11)
        |
       M-0  (substrate: JarvisAPI pkg, harness, behavioral gates, dual-handshake — direct on develop)
        |
       M-1  (Self surface — feature branch, PR to develop)
        |
       M-2  (Settings surface)
        |
       M-3  (Diagnostics surface)
        |
       M-4  (Memory surface)
        |
       M-5  (Vision surface — atomic webview+Swift commit)
        |
       M-6  (Voice surface — highest risk, audio-graph fix)
        |
       M-7  (Turn surface — keystone, OutboundBatcher partition by turnId, atomic webview+Swift, N>=3 day soak)

Each phase (M-1..M-7) lives on a feature branch with a single PR to develop. M-0 lands additively direct on develop. M-7 is the worst rollback in the plan; dual-channel transport (M-0.5) stays active across the soak.

Sub-epics (per-phase)

  • #4 — M-0: pre-migration gates (JarvisAPI package, harness, behavioral gates, dual-handshake)
  • #5 — M-1: Self surface (getSelfState, TCC events, B-08 dissolution)
  • #6 — M-2: Settings surface (canonical config writer; F-001/UQ-4)
  • #7 — M-3: Diagnostics surface (HUD state + banner queue + DevSnapshot + replay stream)
  • #8 — M-4: Memory surface (factMutated/factsRetrieved/searchFacts; cache-eligibility regression gate)
  • #9 — M-5: Vision surface (typed requestFrameAttach; B-03 closure via WKWebView round-trip)
  • #10 — M-6: Voice surface (audio-graph fix + synthesizeTurn; B-04/B-05 closure)
  • #11 — M-7: Turn surface keystone (per-turn batcher + listTurns hydration; B-06 partial)

Total estimate

18.5–25.5 engineer-days (~4–5.5 calendar weeks at solo pace, includes context-switch + PR review overhead + N≥3-day post-M-7 soak as passive observation).

Per-phase breakdown:

Phase Estimate (engineer-days)
B-02 patch (DONE) 0.5
M-0 2.5–3.5
M-1 1.0–1.5
M-2 1.5–2.0
M-3 1.0–1.5
M-4 2.0–3.0
M-5 1.5–2.0
M-6 4.0–5.5
M-7 5.0–7.0

Carry-forward bug dissolution map

Bug Issue Closure phase Notes
B-02 (history threading) — DONE 2026-05-11 Tactical patch, commit 48ad8d6. M-4 reframes against API + pins behavior via S-MEM-CACHE-REGRESSION.
B-03 (camera button no-op) #48 M-5 Typed Result<FrameAttachArmed, FrameAttachError> + non-skippable .jsonRoundTripWebView scenario S-VIS-001.
B-04 (voice input dead) #49 M-6 startVoice() returns audioGraphFailed if ringBuffer nil; behavioral gate ≥10 audioLevelChanged within 500 ms.
B-05 (TTS silent) #50 M-6 Voice.synthesizeTurn explicit-command contract per UQ-3 (A).
B-06 (chat auto-scroll) #51 M-7 (partial) turnTextComplete API event lands; DOM scroll ack stays in webview vitest (out of harness scope per R-014 / G-006).
B-07 (Voice Log menu) #52 DEFERRED to v1.1 Plan §6 + §10. Don't ship until B-04/B-05 land.
B-08 (model paraphrase) #53 M-1 Canonical modelDisplayName typed at API boundary; N=10 anti-paraphrase trials.

v1.0 lock criteria

  • All harness scenarios green in both transport modes (UQ-5)
  • All 20 boundary gates green
  • All 7 carry-forward bugs closed or DEFERRED with explicit milestone
  • Documentation landed (JARVIS-API-DESIGN-v1.0.md single-doc merge, test contract, migration plan, Tools/jarvis-diag/ harness)
  • N≥3 days of live use with dual-channel transport active before M-7.8 strict-version bump

Source

  • .planning/architecture/JARVIS-API-MIGRATION-PLAN.md — full plan (sections 1–10)
  • .planning/architecture/JARVIS-API-DESIGN-v0.1.md + v0.2.md — v1.0 contract
  • .planning/architecture/JARVIS-API-TEST-CONTRACT.md — parametric harness contract
  • docs/SESSION-STATE.md — locked UQ decisions reference
## Goal Separate the SwiftUI/AppKit + WKWebView UI surface from the Swift backend behind a typed `JarvisAPI` package, with a parametric harness running every behavioral scenario against BOTH `.inProcessActor` AND `.jsonRoundTripWebView` runners. The full v1.0 contract is defined in `.planning/architecture/JARVIS-API-DESIGN-v0.1.md` + `JARVIS-API-DESIGN-v0.2.md` and executed via the per-phase migration cards in `JARVIS-API-MIGRATION-PLAN.md` (M-0..M-7). ## Why The 2026-05-03 / 2026-05-04 audits surfaced 8 carry-forward bugs (B-01..B-08) all rooted in a single class of failure: **"verification gate is executor self-reports green tests + boundary gates, which cannot detect substrate failures."** Grep-based gates pass while runtime substrate is dead (voice graph nil, camera button no-op, history threading missing, sessionHistory never read). The v1.0 contract dissolves the entire class by forcing every behavior through a typed API surface and running every scenario through a real WKWebView JSON round-trip — making "looks green but is broken" detectable at PR time. ## Design artifacts (source of truth) - `.planning/architecture/README.md` — index - `.planning/architecture/JARVIS-API-DESIGN-v0.1.md` — v1.0 contract part 1 (surfaces, commands, events, queries) - `.planning/architecture/JARVIS-API-DESIGN-v0.2.md` — v1.0 contract part 2, UQ-1..UQ-5 answered - `.planning/architecture/JARVIS-API-MIGRATION-PLAN.md` — **the spine**; per-phase scope/files/tests/AC/dependencies/estimates - `.planning/architecture/JARVIS-API-TEST-CONTRACT.md` — parametric harness contract (UQ-5 mandatory) - `.planning/architecture/INVENTORY.md` — surface inventory - `.planning/architecture/REVIEW-API-CORRECTNESS.md` — correctness review - `.planning/architecture/REVIEW-MIGRATION-RISK.md` — risk findings R-001..R-018 and per-phase cutover risks - `.planning/architecture/REVIEW-TEST-CONTRACT.md` — test contract review - `.planning/architecture/HANDOFF-2026-05-07.md` — design swarm handoff ## Locked decisions (UQ-1..UQ-5) - **UQ-1 — Harness runtime gate:** `JARVIS_HARNESS=1` env var. Test seams (`_injectAudioFrame`, `_forceTCCStatus`, `_forceError`, `ProviderOverrides`, `setConfirmationDefault`) ONLY effective when env var set. Production launches fail closed. - **UQ-2 — B-02 path:** tactical patch on `develop` (DONE 2026-05-11, commit `48ad8d6`) BEFORE M-0 starts. M-4 reframes against the new surface + adds the cache-eligibility regression gate. - **UQ-3 — TTS contract:** **(A) explicit-command** — orchestrator MUST issue `Voice.synthesizeTurn(turnId:text:tier:)` on `turnEnded(.completed)` for voice-source turns. No implicit TTS routing. - **UQ-4 — Config writer:** `Settings` owns ALL configuration mutation. Voice surface loses `setTTSTier`, `muteWakeWord`, `unmuteWakeWord`, `startVoice`, `shutdownVoice`. Voice retains only runtime-control verbs (`pttDown`, `pttUp`, `cancelTTS`, `synthesizeTurn`). - **UQ-5 — Parametric harness MANDATORY:** every scenario runs in both `.inProcessActor` AND `.jsonRoundTripWebView` modes. `.jsonRoundTripWebView` is non-skippable for B-03-class regressions (M-5 `S-VIS-001`). ## Phase dependency DAG ``` B-02 tactical patch (DONE 2026-05-11) | M-0 (substrate: JarvisAPI pkg, harness, behavioral gates, dual-handshake — direct on develop) | M-1 (Self surface — feature branch, PR to develop) | M-2 (Settings surface) | M-3 (Diagnostics surface) | M-4 (Memory surface) | M-5 (Vision surface — atomic webview+Swift commit) | M-6 (Voice surface — highest risk, audio-graph fix) | M-7 (Turn surface — keystone, OutboundBatcher partition by turnId, atomic webview+Swift, N>=3 day soak) ``` Each phase (M-1..M-7) lives on a feature branch with a single PR to `develop`. M-0 lands additively direct on `develop`. M-7 is the worst rollback in the plan; dual-channel transport (M-0.5) stays active across the soak. ## Sub-epics (per-phase) - #4 — M-0: pre-migration gates (JarvisAPI package, harness, behavioral gates, dual-handshake) - #5 — M-1: Self surface (getSelfState, TCC events, B-08 dissolution) - #6 — M-2: Settings surface (canonical config writer; F-001/UQ-4) - #7 — M-3: Diagnostics surface (HUD state + banner queue + DevSnapshot + replay stream) - #8 — M-4: Memory surface (factMutated/factsRetrieved/searchFacts; cache-eligibility regression gate) - #9 — M-5: Vision surface (typed requestFrameAttach; B-03 closure via WKWebView round-trip) - #10 — M-6: Voice surface (audio-graph fix + synthesizeTurn; B-04/B-05 closure) - #11 — M-7: Turn surface keystone (per-turn batcher + listTurns hydration; B-06 partial) ## Total estimate **18.5–25.5 engineer-days** (~4–5.5 calendar weeks at solo pace, includes context-switch + PR review overhead + N≥3-day post-M-7 soak as passive observation). Per-phase breakdown: | Phase | Estimate (engineer-days) | |---|---| | B-02 patch (DONE) | 0.5 | | M-0 | 2.5–3.5 | | M-1 | 1.0–1.5 | | M-2 | 1.5–2.0 | | M-3 | 1.0–1.5 | | M-4 | 2.0–3.0 | | M-5 | 1.5–2.0 | | M-6 | 4.0–5.5 | | M-7 | 5.0–7.0 | ## Carry-forward bug dissolution map | Bug | Issue | Closure phase | Notes | |---|---|---|---| | B-02 (history threading) | — | DONE 2026-05-11 | Tactical patch, commit `48ad8d6`. M-4 reframes against API + pins behavior via `S-MEM-CACHE-REGRESSION`. | | B-03 (camera button no-op) | #48 | M-5 | Typed `Result<FrameAttachArmed, FrameAttachError>` + non-skippable `.jsonRoundTripWebView` scenario `S-VIS-001`. | | B-04 (voice input dead) | #49 | M-6 | `startVoice()` returns `audioGraphFailed` if ringBuffer nil; behavioral gate ≥10 `audioLevelChanged` within 500 ms. | | B-05 (TTS silent) | #50 | M-6 | `Voice.synthesizeTurn` explicit-command contract per UQ-3 (A). | | B-06 (chat auto-scroll) | #51 | M-7 (partial) | `turnTextComplete` API event lands; DOM scroll ack stays in webview vitest (out of harness scope per R-014 / G-006). | | B-07 (Voice Log menu) | #52 | DEFERRED to v1.1 | Plan §6 + §10. Don't ship until B-04/B-05 land. | | B-08 (model paraphrase) | #53 | M-1 | Canonical `modelDisplayName` typed at API boundary; N=10 anti-paraphrase trials. | ## v1.0 lock criteria - All harness scenarios green in both transport modes (UQ-5) - All 20 boundary gates green - All 7 carry-forward bugs closed or DEFERRED with explicit milestone - Documentation landed (`JARVIS-API-DESIGN-v1.0.md` single-doc merge, test contract, migration plan, `Tools/jarvis-diag/` harness) - N≥3 days of live use with dual-channel transport active before M-7.8 strict-version bump ## Source - `.planning/architecture/JARVIS-API-MIGRATION-PLAN.md` — full plan (sections 1–10) - `.planning/architecture/JARVIS-API-DESIGN-v0.1.md` + `v0.2.md` — v1.0 contract - `.planning/architecture/JARVIS-API-TEST-CONTRACT.md` — parametric harness contract - `docs/SESSION-STATE.md` — locked UQ decisions reference
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: KofTwentyTwo/Jarvis#76