2 Commits
Author SHA1 Message Date
james.maes e9a0bb14d2 feat(01-05): add JarvisEntitlementProbeTests target + EntitlementProbe scheme
- App/Tests/JarvisEntitlementProbeTests/JarvisEntitlementProbeTests.swift:
  one-shot XCTest gated on #if JARVIS_ENTITLEMENT_PROBE. Calls
  SpeechTranscriber(locale:preset:) + AssetInventory.status(forModules:)
  and accepts any of three failure surfaces as confirmation that the
  speech-recognition-assets entitlement is load-bearing:
    (a) NSError SFSpeechErrorDomain code 1 (assetUnavailable)
    (b) NSError SFSpeechErrorDomain code 10 (macOS 26 'unallocated locales')
    (c) AssetInventory.Status description containing 'unavailable' /
        'unsupported'
- App/Tests/JarvisEntitlementProbeTests/Info.plist: standard test bundle.
- project.yml: new JarvisEntitlementProbeTests target (OTHER_SWIFT_FLAGS =
  -DJARVIS_ENTITLEMENT_PROBE) + EntitlementProbe scheme. Default Jarvis
  scheme's test action lists only JarvisAppTests — the probe target is
  opt-in via EntitlementProbe scheme only.
- Jarvis.xcodeproj/xcshareddata/xcschemes/EntitlementProbe.xcscheme: new
  shared scheme referencing JarvisEntitlementProbeTests as its sole
  testable.

Deviations from plan's copy-verbatim XCTest shape:
- Added @available(macOS 26.0, *) to the test class: macOS 26 SpeechModule
  / SpeechTranscriber / AssetInventory are not available pre-Tahoe.
  Deployment target stays at 13.0 for the rest of the project.
- preset: .progressiveLiveTranscription -> .progressiveTranscription
  (actual Apple SDK name on macOS 26.4).
- AssetInventory.status(forModules:) is async non-throwing on macOS 26.4;
  wrapped in a throwing adapter so the historical do/catch shape from
  RESEARCH Q4 (NSError SFSpeechErrorDomain codes 1/10) stays intact.

Also: [Rule 3 - Blocking] extend codesign.sh to handle nested .xctest
plugins under Contents/PlugIns/. When build-for-testing is invoked, the
xctest lives inside Jarvis.app/Contents/PlugIns/ and must be signed
before the main app, or codesign on the parent bundle fails with
'bundle format unrecognized'. Empty xctest shells that materialize
before the test target has been compiled are removed (Xcode recreates
+ populates them in a later iteration).

Task 3 acceptance: xcodebuild -list shows EntitlementProbe scheme +
JarvisEntitlementProbeTests target; EntitlementProbe build-for-testing
succeeds with the full codesign + entitlement verification chain.
2026-04-22 14:42:30 -05:00
james.maes f8da4b7c39 feat(01-03): add MenuBarIconController + MenuBarContextMenu + JarvisAppTests target
- MenuBarIconController (@MainActor) owns NSStatusItem, loads Icon-MenuBar-Template asset with isTemplate=true, re-anchors layer.frame after anchorPoint change (Q7 gotcha #2), transitions across 5 HudStates via CAAnimationFactory with 150ms crossfade + rate-limited VoiceOver announcements (3s limiter per UI-SPEC Surface 3 line 421)
- MenuBarContextMenu builds Setup… / Settings… (disabled) / Show Dev Overlay / Copy State Dump / Quit Jarvis (⌘Q), with a ClosureTarget trampoline for closure-based actions
- Left-click vs right-click disambiguation via NSApp.currentEvent.type inspection (D-16 / UI-SPEC Surface 3 lines 406-409)
- JarvisAppTests Xcode unit-test bundle target added via project.yml; scheme wires test action against JarvisAppTests
- MenuBarIconControllerTests covers state transitions, no-op-on-same-state, context-menu items, and HudState voiceOverLabels (4 tests pass)
- PBXCopyFilesBuildPhase for Contents/Helpers re-applied post-xcodegen (Plan 01 invariant — MCP-05 acceptance-criteria grep)
2026-04-22 13:14:09 -05:00