Files
dh 9542c05ea4 feat(macos): add native desktop controls and hotkey integration
- Introduced MacOsDesktopControlManifest to manage desktop control configurations.
- Implemented MacOsDesktopControlService to handle the lifecycle of the macOS helper process.
- Created MacOsWorkflowRulesEditorWindowService for managing workflow rules through a native window.
- Developed a Swift helper for macOS that integrates with AppKit and Carbon for menu-bar controls and global hotkeys.
- Added support for recording lifecycle actions via HTTP endpoints, maintaining consistency with existing Windows functionality.
- Enhanced user experience by allowing macOS users to start/stop recordings and access settings through a menu-bar interface.
- Documented design decisions, implementation evidence, and verification tasks for the new macOS features.
2026-08-06 08:18:52 +02:00

5.0 KiB

Implementation Evidence

Automated

  • dotnet test MeetingAssistant.Tests/MeetingAssistant.Tests.csproj --filter FullyQualifiedName~MacOsDesktopControlManifestTests --no-restore
    • Passed: 1, Failed: 0.
  • dotnet build MeetingAssistant/MeetingAssistant.csproj -f net10.0 --no-restore
    • Passed and produced Native/macos-desktop-controls as an arm64 Mach-O executable.
  • openspec validate add-macos-desktop-controls --strict
    • Passed.
  • Full portable test project:
    • Passed: 427.
    • Failed: 9 existing macOS/environment-dependent tests: Windows path expectations, unavailable GDI+, and user-environment key resolution.
  • Whole solution:
    • Cannot build the Windows target on macOS without enabling cross-Windows targeting (NETSDK1100).

Runtime

  • Installed the rebuilt application assembly and both native helpers into the existing local LaunchAgent application directory.
  • LaunchAgent restarted successfully.
  • /health returned ok.
  • macos-desktop-controls ran as a child companion process.
  • The helper manifest contained six configured hotkeys, including the unchanged defaults Ctrl+Alt+M, Ctrl+Alt+L, Ctrl+Alt+Z, and Ctrl+Alt+S.
  • A fresh default-profile recording request created the 20260724-2015 meeting note and linked artifacts.
  • Screenshot evidence: tmp/macos-desktop-recording-verification.png.

Live desktop-control proof (2026-07-24)

  • The installed LaunchAgent ran:
    • .NET host PID 23023
    • native macos-desktop-controls PID 23097
  • The native helper manifest exposed:
    • Ctrl+Alt+M -> /profiles/default/recording/toggle
    • Ctrl+Alt+L -> /profiles/english/recording/toggle
    • Ctrl+Alt+Z -> /profiles/default/recording/abort
    • Ctrl+Alt+S -> /profiles/default/meetings/screenshot/capture
  • Accessibility inspection of the real AppKit menu returned:
    • Meeting Assistant — idle
    • Open agent
    • Start meeting recording (default)
    • Start meeting recording (english)
    • Exit
  • Visible menu screenshot:
    • tmp/proof-macos-menu-idle.png
    • The menu visibly displays the macOS equivalents ⌃⌥M and ⌃⌥L.
  • Clicking Start meeting recording (default) through the real menu produced the sampled status transition false,true,false, with launchProfile: default, and created:
    • Meetings/Notes/20260724-2022-note.md
    • Meetings/Transcripts/20260724-2022-transcript.md
    • Meetings/Assistant Context/20260724-2022-context.md
  • Posting the HID-level Ctrl+Alt+M combination produced the sampled status transition false,true,false, with launchProfile: default.
  • Posting the HID-level Ctrl+Alt+L combination produced an active sampled state with launchProfile: english.
  • Raw sampled status evidence:
    • tmp/proof-menu-recording-status.jsonl
    • tmp/proof-hotkey-recording-status.jsonl
    • tmp/proof-english-hotkey-status.jsonl

Runtime limitation

The new recording did not remain active because the local audio capture process stopped shortly after artifact creation. The desktop-control helper, menu-bar item, endpoint routing, and meeting creation were verified; sustained audio capture was not.

Open agent regression and runtime proof

  • Original deterministic regression:
    • MacOsApplicationRegistersARealInteractiveAgentWindow
    • Red result: portable registration resolved exactly NoopWorkflowRulesEditorWindowService.
  • Fix:
    • macOS now registers MacOsWorkflowRulesEditorWindowService.
    • Open agent in the native helper creates an AppKit NSWindow titled Meeting Summary Agent.
    • The window hosts a WebKit chat page backed by the existing WorkflowRulesEditorChatViewModel and agent pipeline.
  • Green regression:
    • Passed: 1, Failed: 0.
  • Live installed runtime:
    • Clicking the actual menu item created an on-screen CoreGraphics window:
      • owner: macos-desktop-controls
      • title: Meeting Summary Agent
      • layer: 0
      • bounds: 756x714
    • GET /diagnostics/settings-and-logs returned the interactive agent HTML page.

Open agent prompt execution proof (2026-07-25)

  • Original live failure:
    • Meeting Summary Agent failed: No workflow rules editor API key configured.
  • Root cause:
    • The LaunchAgent did not inherit the interactive shell's model API key.
    • Its configured 127.0.0.1:4021 model endpoint had no running service.
  • Runtime configuration:
    • The protected LaunchAgent environment file now supplies the local LiteLLM gateway key.
    • MeetingAssistant__WorkflowRulesEditor__Endpoint targets the running local gateway on port 4000.
    • The local gateway exposes the Responses-compatible chatgpt-gpt-5.5 model alias.
  • Event-stream compatibility regression:
    • ClientReconstructsResponseFromServerSentEvents failed before the fix with JsonReaderException.
    • The client now reconstructs completed response items from LiteLLM server-sent events.
    • All 11 LiteLlmResponsesChatClientTests pass.
  • Live installed proof:
    • POST /diagnostics/settings-and-logs/chat with Reply with exactly: key-ok returned {"role":"agent","content":"key-ok"}.
    • /health returned successfully after deployment.