docs(phase-06): defer launch-driven UAT gates to Phase 8 (signed)

Plan 06-05's six HUMAN-UAT launch-driven gates (VOICE-07/09/12/13/14 + VOICE-10
mic re-grant) are deferred to Phase 8 because attempts to launch the ad-hoc
Debug Jarvis.app surfaced a pre-existing Xcode 26 / Swift 6 / Info.plist /
preview-dylib codesign fragility that is independent of any Plan 06-05 code:

  - `SWIFT_ENABLE_DEBUG_DYLIB: NO` is correctly set in the Debug config
    (commit fde2aad from prior session) but Xcode 26 still produces
    Jarvis.debug.dylib + __preview.dylib next to the main exec.
  - After post-codesign succeeds, `codesign --verify` reports `invalid
    Info.plist (plist or signature have been modified)` — something
    downstream of post-codesign is invalidating the bundle.
  - The pre-codesign script writes JarvisEntitlementsVerified=YES into the
    built Info.plist (build log confirms), but the marker is observed as
    `false` post-build — same downstream mechanism.
  - Runtime entitlement gate hard-blocks at AppDelegate launch with
    "JarvisEntitlementsVerified missing/false — hard-blocking" Logger.critical.

Phase 8 (Hardening) explicitly owns Developer ID Application signing,
notarization, and codesign chain stability per .planning/ROADMAP.md.
The pre-existing CDHash-drift on ad-hoc Debug bundles (noted in STATE.md's
Decisions/context section from the prior session) is the same class of issue.
Continuing to debug this in Phase 6 is scope creep.

What IS verified for Phase 6 close-out:
  - swift test --package-path packages/Voice — 64 cases / 3 env-gated skips /
    0 failed (20 new tests from Plan 06-05)
  - bash scripts/check-app-builds.sh — App target compiles cleanly with the
    new Voice package wiring (project.yml + pbxproj updated for Voice +
    macOS 14 deployment target)
  - All five Plan 06-05 invariants (VOICE-07/09/12/13/14) covered structurally
    by deterministic XCTest cases:
      • VoiceController state machine (VoiceControllerTests)
      • Single cancelAndSubmit per barge-in (BargeInTests)
      • PTT works when wake-word muted (PTTTests + MuteWakeWordTests)
      • AEC banner via native HUDBannerCoordinator, not webview modal
        (AECFallbackBannerTests + Phase 5 modal-lint)
      • App-level wiring graph (VoiceWiringTests)
  - OrpheusTTFATests scaffold-time perf probe ships, env-gated behind
    JARVIS_REAL_MODELS=1, runnable once Phase 8 unblocks Release-archive launch

Updates:
  - .planning/phases/06-voice/06-HUMAN-UAT.md — Summary table fills in
    DEFERRED→Phase 8 for each launch-driven gate; PASS for Pre-flight (the
    code/test gates that don't need launch). Adds "Deferral Note" section
    explaining the fragility and what ships to Phase 8. Tester signature:
    Orchestrator (J.M. session 2026-04-27, agreed via interactive decision).
  - .planning/STATE.md — adds "Phase 6 → Phase 8 Deferred Items" section
    enumerating the launch-fragility fix + the six UAT gates + the empirical
    TTFA probe. Bumps completed_plans 28→29 (Plan 06-05 wiring is shipped;
    UAT execution is the deferred half), percent 97→100. completed_phases
    stays at 5/8 — Phase 6 will flip to 6/8 only after /gsd-verify-phase 6
    confirms the goal-backward audit on the verifiable surface.
This commit is contained in:
james.maes committed 2026-04-27 15:49:14 -05:00
1 parent 722e25b5b5
commit fdd03d62de
2 files changed
+47 -14

No files matched your search

+13 -4
View File
@@ -3,13 +3,13 @@ gsd_state_version: 1.0
milestone: v0.12.0
milestone_name: milestone
status: executing
last_updated: "2026-04-27T18:10:00.000Z"
last_updated: "2026-04-27T19:30:00.000Z"
progress:
total_phases: 8
completed_phases: 5
total_plans: 29
completed_plans: 28
percent: 97
completed_plans: 29
percent: 100
---
# State: Jarvis
@@ -100,12 +100,21 @@ Plan: 1 of 5
None. Ready for `/gsd-plan-phase 1`.
### Phase 6 → Phase 8 Deferred Items (recorded 2026-04-27)
Plan 06-05's six HUMAN-UAT launch-driven gates were deferred to Phase 8 because attempts to launch the ad-hoc Debug `Jarvis.app` surfaced a pre-existing Xcode 26 / Swift 6 / Info.plist / preview-dylib codesign fragility that is independent of Plan 06-05's Voice work. Code-side correctness is fully verified (64 swift tests pass; App target compiles cleanly with the new Voice package wiring; all five VOICE-07/09/12/13/14 invariants covered by deterministic XCTest cases). Sign-off carried in `.planning/phases/06-voice/06-HUMAN-UAT.md` "Deferral Note" section.
Phase 8 (Hardening) inherits:
- [ ] Resolve Xcode 26 ad-hoc-Debug-bundle launch fragility (`SWIFT_ENABLE_DEBUG_DYLIB=NO` is set but ignored; Info.plist marker write is reverted post-build by something downstream of post-codesign; `codesign --verify` reports `invalid Info.plist (plist or signature have been modified)` after a clean build's BUILD SUCCEEDED)
- [ ] Drive Plan 06-05's six UAT gates (VOICE-07 happy path, VOICE-14 barge-in, VOICE-13 PTT, VOICE-12 mute-wake-word + PTT-still-armed, VOICE-09 AEC banner, VOICE-10 mic re-grant) on a Release-signed Developer ID archive
- [ ] Empirical Orpheus TTFA measurement (target 150–250 ms) — once Release archive launches, run `JARVIS_REAL_MODELS=1 swift test --filter OrpheusTTFATests` interactively; if > 250 ms, flip `features.tts.tier2 = "ttskit"` in default config
### Scaffold-Time Verifications (must resolve during their owning phase)
- [ ] **P1**: Release cold-launch with `com.apple.developer.speech-recognition-assets` removed → confirm `SFSpeechErrorCode.assetUnavailable` fires (load-bearing claim).
- [ ] **P1**: Input Monitoring TCC denial surfaces HUD banner, not silent no-op (R4-S2).
- [ ] **P6**: Silero v6.2.1 preserves 512-sample/32ms/16kHz chunk contract from v5.
- [ ] **P6**: Orpheus empirical TTFA measurement on Apple Silicon host lands in 150–250 ms target.
- [ ] **P6**: Orpheus empirical TTFA measurement on Apple Silicon host lands in 150–250 ms target. *(Now grouped with Phase 8 deferred items above; same blocker.)*
- [ ] **P6**: AEC post-format probe on macOS 26 Tahoe resolves 24 kHz (Tahoe) vs 16 kHz (Sonoma) correctly.
### Deferred Research Questions
+34 -10
View File
@@ -115,18 +115,42 @@ Complete all pre-flight items before beginning the UAT session.
| Gate | Result | Notes |
|------|--------|-------|
| Pre-flight | | |
| Gate 1: Happy path (VOICE-07) | | |
| Gate 2: Barge-in (VOICE-14) | | |
| Gate 3: Push-to-talk (VOICE-13) | | |
| Gate 4: Mute wake word (VOICE-12) | | |
| Gate 5: AEC banner (VOICE-09) | | |
| Gate 6: Mic re-grant (VOICE-10) | | |
| Pre-flight (swift test + scripts) | **PASS** | `swift test` 64/3-skipped/0-failed; `bash scripts/check-app-builds.sh` PASS (compile-only). Model fetch + TTFA probes deferred to Phase 8 (require physical-Mac launch) |
| Gate 1: Happy path (VOICE-07) | **DEFERRED → Phase 8** | Blocked by Xcode 26 ad-hoc-Debug bundle launch fragility; see deferral note below |
| Gate 2: Barge-in (VOICE-14) | **DEFERRED → Phase 8** | Same blocker — code-side correctness covered by `BargeInTests` 4/4 + structural assertion of single `cancelAndSubmit` call site |
| Gate 3: Push-to-talk (VOICE-13) | **DEFERRED → Phase 8** | Same blocker — code-side covered by `PTTTests` 3/3 + `NSEvent.addGlobalMonitorForEvents` wiring assertion |
| Gate 4: Mute wake word (VOICE-12) | **DEFERRED → Phase 8** | Same blocker — code-side covered by `MuteWakeWordTests` 3/3 + UserDefaults persistence test |
| Gate 5: AEC banner (VOICE-09) | **DEFERRED → Phase 8** | Same blocker — code-side covered by `AECFallbackBannerTests` 4/4 + structural reuse of `HUDBannerCoordinator` (modal-lint enforced from Phase 5) |
| Gate 6: Mic re-grant (VOICE-10) | **DEFERRED → Phase 8** | Same blocker — additionally couples to AudioGraph rebuildStream which is Phase 1 territory |
**Overall result:** [ ] PASS (all blocking gates pass) [ ] PARTIAL (non-blocking gates failed or skipped) [ ] FAIL
**Overall result:** **PARTIAL — code-side correctness verified, physical-Mac launch UAT deferred to Phase 8**
**Tester signature:** _____________
**Date:** _____________
**Tester signature:** Orchestrator (J.M. session 2026-04-27, agreed via interactive decision)
**Date:** 2026-04-27
---
## Deferral Note: Why the launch-driven gates ship to Phase 8
During Plan 06-05 post-wave validation, attempts to launch the Debug-built `Jarvis.app` revealed a **pre-existing Xcode 26 / Swift 6 / ad-hoc-Debug-codesign fragility** that is independent of any Plan 06-05 code:
1. Even with `SWIFT_ENABLE_DEBUG_DYLIB: NO` set in the Debug config (commit `fde2aad` from the prior session), Xcode 26 still produces `Jarvis.debug.dylib` and `__preview.dylib` next to the main exec.
2. After the build's post-codesign step succeeds, `codesign --verify` reports `invalid Info.plist (plist or signature have been modified)` — something downstream of post-codesign (likely Xcode 26's preview-mode dylib generation OR Info.plist re-stamping for incremental dependencies) is invalidating the bundle after the build claims success.
3. The pre-codesign script writes `JarvisEntitlementsVerified=YES` correctly into the built bundle's Info.plist, but the marker is observed as `false` post-build — same downstream mechanism.
4. Manual re-codesign of the bundle's main exec breaks `Jarvis.debug.dylib`'s Team-ID match, causing dyld to refuse to load the dylib.
**This is Phase 8 (Hardening) territory.** Phase 8 explicitly owns Developer ID Application signing, notarization, and codesign chain stability per `.planning/ROADMAP.md`. The pre-existing CDHash drift on ad-hoc Debug bundles (noted in `.planning/STATE.md`'s Decisions/context section from the prior session) is the same class of issue. Continuing to debug this in Phase 6 is scope creep.
**What IS verified for Phase 6 close-out:**
- `swift test --package-path packages/Voice` — 64 cases / 3 env-gated skips / 0 failed (20 new tests from Plan 06-05: VoiceController, BargeIn, PTT, MuteWakeWord, AECFallbackBanner, VoiceWiring)
- `bash scripts/check-app-builds.sh` — App target compiles cleanly with the new Voice-package wiring
- All five Plan 06-05 invariants (VOICE-07/09/12/13/14) covered structurally by deterministic XCTest cases
- `OrpheusTTFATests` env-gated probe ships and is runnable interactively (`JARVIS_REAL_MODELS=1`) once Phase 8's signing chain unblocks Release-archive launch
**What ships to Phase 8:**
- Resolve Xcode 26 ad-hoc-Debug-bundle launch fragility (Info.plist marker stability + dylib Team-ID consistency)
- Drive the six gates above on a Release-signed archive
- Sign back here with PASS / FAIL / NOTES per gate
---