6 Commits
Author SHA1 Message Date
james.maesandClaude Opus 4.7 14cff7b439 fix(test): InputMonitoringDenialTests — add missing HIDAccessProbe protocol method to MockProbe
`HIDAccessProbe` gained `isListenEventAccessGranted() -> Bool` (the
query-only relaunch path that doesn't re-prompt) but `MockProbe` in
`InputMonitoringDenialTests.swift` was never updated to conform — the
test target failed to compile entirely. Existence on develop indicates
the Shell package isn't covered by pre-merge CI.

Add the conformance with the same `granted` value as
`requestListenEventAccess()` since the tests don't differentiate the
two surfaces.

Verified: `swift test --package-path packages/Shell` compiles + runs
19 tests (1 skipped) green.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-04 15:21:17 -05:00
james.maesandClaude Opus 4.7 08125a46d8 chore(test): remove tautologies and rubber-stamps per tests-audit.md
Per `.planning/audit-2026-05-03/tests-audit.md` section 5, five
`XCTAssertTrue(true)` placeholder tests were identified across the tree
that are mathematically incapable of failing. This commit fixes or
removes each, conservatively. Files touched and disposition:

- App/Tests/AppTests/MCPRuntimeWiringTests.swift:260
  fixed: replaced trailing `XCTAssertTrue(true)` rubber-stamp at end of
  CR-02 channel-drain test with a load-bearing assertion that the drain
  task completed via `finish()`, not cancellation. The implicit `await
  drainTask.value` is the real gate; the new assertion ensures regressions
  that cancel-instead-of-finish surface.

- App/Tests/AppTests/WebviewBundleLoadTests.swift:60
  deleted: `test_assetsDirectoryGitignored_documentedInSmokeScript`. Body
  was `XCTAssertTrue(true)` with comment "intentionally has no assertion
  — it exists to document the split of responsibility". Documentation,
  not a test. Replaced with a top-level comment block documenting the
  same split (smoke-test-hud.sh is the runtime gate).

- packages/AgentCore/Tests/AgentCoreTests/ToolChoiceTests.swift:38
  fixed: removed trailing `XCTAssertTrue(true) // Test compiles → contract
  holds.` from `testLLMProviderStreamRequiresToolChoice`. The closure
  body itself is the contract — if the test compiles, the contract holds.
  Comment updated to make the compile-time semantics explicit.

- packages/Shell/Tests/ShellTests/InputMonitoringDenialTests.swift:36
  deleted: `test_localMonitorOnlyFallback`. Body was `XCTAssertTrue(true)`
  documenting that the real fallback test lives in HotkeyBindingTests.
  Replaced with a top-level comment pointing readers there.

- packages/Vision/Tests/VisionTests/PackageBoundaryTests.swift:14
  deleted: `testVisionModuleCompilesStandalone`. Body was
  `XCTAssertTrue(true)` with comment "compile is the assertion." VISION-03
  isolation is enforced by `scripts/check-vision-isolation.sh` and the
  Package.swift dependency graph, both of which are real gates. Folded
  the documentation into the `testPublicAPISurface` doc-comment so the
  explanation isn't lost.

HudStateEnumTests rubber-stamps (audit items #4–6 in section 5) were
left as-is. The voiceOverLabel literals are user-facing accessibility
text that VoiceOver actually speaks; they are load-bearing in the sense
the audit calls out as worth preserving ("replace with behavioral
assertions if the literal under test is load-bearing"). A regression
that breaks an a11y label IS a real regression. Conservative read; not
worth the blast radius of guessing wrong.

Pre-existing baseline issues unrelated to this batch:
- `packages/Shell/Tests/ShellTests/InputMonitoringDenialTests.swift`
  fails to COMPILE on a clean tree (MockProbe missing
  `isListenEventAccessGranted()`). Verified via `git stash` that the
  failure is independent of this commit. Not addressed here per the
  scope rules — flagged for follow-up.

Net test count: -3 tests (3 deleted, 0 added — the
MCPRuntimeWiringTests assertion replaces the tautology in-place).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-04 12:34:56 -05:00
james.maes cd3b62f672 fix(01-CR-03): detect silent nil global hotkey monitor + wire bind-failed banner
Phase 1 REVIEW.md CR-03 (SHELL-06): `HotkeyBinder.bind` never checked
whether `store.installGlobalMonitor` returned nil — yet
`NSEvent.addGlobalMonitorForEvents` silently returns nil when Input
Monitoring was revoked between launches (common after a codesign
identity change). The result was the exact silent-no-op SHELL-06
exists to prevent: hotkey appears bound, global monitor is dead, no
banner surfaces. Related WR-06: `BannerContent.hotkeyBindFailed`
existed but was never enqueued from production code.

packages/Shell/Sources/Shell/HotkeyBinder.swift
- Add `HotkeyBinder.BannerSink` protocol (mirrors
  `InputMonitoringProbe.BannerSink` pattern).
- `bind(_:inputMonitoringGranted:bindFailedSink:onPress:)` now checks
  the returned token: if nil, sets `isDegraded = true` AND invokes
  `sink.enqueueHotkeyBindFailed()`. Local monitor install is still
  unconditional so the hotkey works while Jarvis is frontmost.

packages/Shell/Tests/ShellTests/HotkeyBindingTests.swift
- Add `DeniedGlobalMonitorStore` fake (returns nil for global install).
- Add `RecordingBindFailedSink` that counts enqueue calls.
- New tests:
  - `test_nilGlobalTokenMarksDegradedAndNotifiesSink` — SHELL-06
    regression guard for the silent-revoke path.
  - `test_deniedInputMonitoringDoesNotEnqueueBindFailed` — asserts the
    priority-2 inputMonitoringDenied banner is not mixed with the
    priority-3 hotkeyBindFailed banner.
  - `test_successfulBindDoesNotEnqueueBindFailed` — no spurious banner
    on the happy path.

App/AppDelegate.swift:233-260
- Add `HotkeyBindFailedSink` adapter (mirrors `AdHocBannerSink`
  pattern) so Shell can enqueue `BannerContent.hotkeyBindFailed` onto
  the `HUDBannerCoordinator` without importing App types.
- `bindHotkeyFromWizard()` now passes the sink into `hotkeyBinder.bind`
  — fixes WR-06 (hotkeyBindFailed preset no longer orphaned).
2026-04-23 16:13:11 -05:00
james.maesandClaude Opus 4.7 5d57d7b5a4 feat(01-04): build hand-rolled ShortcutRecorder + CollisionDetector
- ShortcutRecorderHostView: testable NSView with process(event:) drop-in;
  rejects modifier-only + shift-only keystrokes, aborts on Escape, records
  valid (keyCode + non-shift-only modifiers) per UI-SPEC Surface 2
- ShortcutRecorderView: NSViewRepresentable SwiftUI glue with @Binding
  shortcut + errorMessage, @MainActor-isolated Delegate protocol
- KeyCapView / KeyCapRowView: key-cap chip rendering ([⌘]+[⇧]+[J])
- CollisionDetector: Cmd+Shift+J → Chrome/Slack/VS Code warning,
  Option+Space → Alfred/Raycast warning, uncommon combos pass through
- Tests: 7 passing (modifier-only rejected, shift-only rejected, escape
  aborts, valid capture, cmdShiftJ collision, optionSpace collision,
  uncommon combo no collision)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-22 13:48:31 -05:00
james.maesandClaude Opus 4.7 37f235b8c8 feat(01-04): build Shell core — HotkeyBinder, InputMonitoringProbe, LaunchAtLogin, TCCAlertService
- KeyboardShortcut: Codable/Sendable/Equatable struct for keyCode + modifier mask
- HotkeyBinder: global+local NSEvent monitor pair with local-only degraded mode
  on Input Monitoring denial (D-06/D-07; SHELL-06)
- InputMonitoringProbe: IOHIDRequestAccess(kIOHIDRequestTypeListenEvent) with
  BannerSink callout on denial — silent no-op forbidden per SHELL-06/D-12
- LaunchAtLoginController: SMAppService.mainApp wrapper, macOS 13+ only
  (SHELL-05 scaffolded; no UI in P1)
- TCCAlertService: UI-SPEC Surface 6 hard-blocker NSAlert builder
- Tests: 9 passing (+1 skipped SMAppService live test behind JARVIS_ALLOW_SM_TESTS=1)
- Deleted placeholder source + test from Plan 01

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-22 13:44:09 -05:00
james.maes d8617ffe01 feat(01-01): add four SPM packages with Swift 6 strict concurrency
- packages/Keychain — zero SPM deps (Security.framework at link time only)
- packages/Logging — depends on apple/swift-log 1.5.3+; library product is
  named JarvisLogging to avoid collision with swift-log's own Logging module
- packages/Config — depends on Keychain + Logging (product JarvisLogging)
- packages/Shell — depends on Config + Logging; links AppKit,
  ServiceManagement, IOKit, Carbon for hotkey/launch-at-login surfaces

Every target (main + test) opts into .swiftLanguageMode(.v6) per D-04 so
data-race errors are compile-time failures, not warnings.

Placeholder sources (one per package) plus one trivial XCTest per package
per D-03 so each package builds standalone and has a passing test. Real
sources land in Plan 02 (Keychain/Config/Logging) and Plan 04 (Shell).

Bus/LLM/MCP/Voice/Memory packages NOT pre-created per D-01 — they arrive
in their owning phases (P2/P4/P5/P6/P7) to keep rebuild scope tight.
2026-04-22 12:21:07 -05:00