From 47e63d8bdd34586783550cdc9541ae99e5197129 Mon Sep 17 00:00:00 2001 From: James Maes Date: Tue, 12 May 2026 15:11:19 -0500 Subject: [PATCH 1/2] docs: extract build detail to BUILDING.md The README's Build & run section had grown to cover per-package SPM tests, the xcodebuild wrapper, the webview dev workflow, all 18 boundary-gate linters with a table of what each enforces, and the opt-in JARVIS_REAL_* real-hardware tests. That's reference-doc weight, not first-screen weight. Pulled the detail into BUILDING.md so the README can stay short and a first-time reader hits the architecture before the test matrix. README keeps a four-command quick-start and links here for everything else. Co-Authored-By: Claude Opus 4.7 --- BUILDING.md | 169 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 BUILDING.md diff --git a/BUILDING.md b/BUILDING.md new file mode 100644 index 0000000..13c8deb --- /dev/null +++ b/BUILDING.md @@ -0,0 +1,169 @@ +# Building Jarvis + +This is the long-form build reference. The [README](README.md) has the quick +version; this file covers per-package test loops, the boundary-gate +linters, the webview workflow, and the opt-in real-hardware tests. + +## Requirements + +- **macOS 26 (Tahoe) or later** on Apple Silicon. `SpeechAnalyzer` is a + Tahoe-only API; the agent loop, voice stack, and MLX TTS path all + assume Apple Silicon. +- **Xcode 16+** (project is exercised against the Xcode 26 toolchain). +- **Swift Package Manager** for per-package test loops; **`xcodebuild`** + for the app target. +- **`pnpm`** for the webview workspace. +- **Hardened Runtime entitlements** in `App/Jarvis.entitlements`: + - `com.apple.security.cs.allow-jit` — required for WKWebView's + JavaScriptCore JIT under Hardened Runtime. Without it the webview + crashes in Release builds only. + - `com.apple.developer.speech-recognition-assets` plus the matching + `NSSpeechRecognitionAssetsUsageDescription` Info.plist key — required + for on-device `SpeechAnalyzer` asset download. + +Optional, only for the real-hardware tests: + +- **Ollama** locally with `nomic-embed-text` + `qwen2.5-coder:32b` + (memory regression corpus, Voice TTFA tests). +- **Orpheus MLX weights** (~6 GB) for tier-2 TTS time-to-first-audio + measurement. +- **A real camera + Camera TCC grant** for the camera capture suite. + +## Per-package SPM tests (default loop) + +SPM tests are the fast path — they run offline, in seconds, and cover the +bulk of behavior. The app target is excluded from `swift test` (see +[App target](#app-target) below). + +```bash +swift test --package-path packages/AgentCore +swift test --package-path packages/Bus +swift test --package-path packages/Config +swift test --package-path packages/DevOverlay +swift test --package-path packages/Harness +swift test --package-path packages/Keychain +swift test --package-path packages/Logging +swift test --package-path packages/MCP +swift test --package-path packages/Memory +swift test --package-path packages/Replay +swift test --package-path packages/Shell +swift test --package-path packages/Vision +swift test --package-path packages/Voice +swift test --package-path packages/VoiceLog +``` + +Single-test filter: + +```bash +swift test --package-path packages/ --filter / +``` + +## App target + +`swift test` does not compile the app target on Xcode 26 — the xctest +harness is upstream-broken on ad-hoc Debug bundles. Use the wrapper, which +drives `xcodebuild build -configuration Debug`: + +```bash +bash scripts/check-app-builds.sh +``` + +This is the canonical "does the app compile?" gate. Run it before every +push. + +## Webview (HUD bundle) + +Production build (what gets stamped into the app): + +```bash +bash scripts/build-webview.sh +``` + +Dev loop (Vite, hot reload, talks to the Swift host's bridge when the app +is also running): + +```bash +cd webview && pnpm install && pnpm --filter @jarvis/hud dev +``` + +Webview unit tests (vitest): + +```bash +cd webview && pnpm --filter @jarvis/hud test +``` + +## Boundary-gate linters + +Eighteen grep-based scripts enforce architectural invariants the type +system can't. Each one encodes a *why* the structure is what it is — most +came from a wired-but-dead bug being root-caused into "this isolation +needs to be a gate, not a convention". + +Run them all before pushing: + +```bash +for s in scripts/check-*.sh; do bash "$s" || break; done +``` + +| Script | What it enforces | +|--------|------------------| +| `check-app-builds.sh` | The app target compiles under `xcodebuild`. | +| `check-applescript-confirmation.sh` | AppleScript tool calls route through the HUD-confirmation prompt. | +| `check-bus-harness-parity.sh` | The harness mocks match the live Bus protocol shape. | +| `check-bus-protocol-version.sh` | The Bus protocol version is pinned consistently across Swift + TS. | +| `check-corpus-secrets.sh` | No secrets (API keys, tokens) leak into the eval corpus. | +| `check-embedding-dim-literal.sh` | The 768-dim embedding constant is pinned in one place. | +| `check-install-order.sh` | The `AppDelegate` install DAG awaits subsystems in the correct order. | +| `check-no-evaluate-javascript.sh` | Nothing outside the Bus calls `evaluateJavaScript` on the webview. | +| `check-no-leftover-stubs.sh` | No "TODO stub" placeholders remain in shipped code. | +| `check-no-modal-presentation.sh` | No `.sheet` / `.alert` modals — HUD-native UI only. | +| `check-no-null-voice-adapters.sh` | Voice adapters are never wired to a null implementation. | +| `check-orchestrator-events-single-consumer.sh` | The orchestrator event stream has exactly one consumer (the broadcaster). | +| `check-presence-bus-no-tts-orchestrator.sh` | The presence bus does not call into TTS or the orchestrator. | +| `check-presence-vision-isolation.sh` | The presence subsystem does not import Vision internals. | +| `check-single-memory-mutated-emit.sh` | Exactly one path emits `memory.mutated`. | +| `check-single-memory-used-emit.sh` | Exactly one path emits `memory.used`. | +| `check-single-writer-hudstate.sh` | Exactly one writer for `HUDState`. | +| `check-vision-isolation.sh` | Vision does not import AgentCore / Voice / Memory internals. | + +Codesign + entitlement verification (run as Xcode build phases, also +useful manually): + +```bash +bash scripts/verify-entitlements.sh --pre-codesign +bash scripts/verify-entitlements.sh --post-codesign +bash scripts/verify-codesign-settings.sh +``` + +## Real-hardware / real-network env-flag tests + +These are skipped in the default loop because they need external +resources. Run them interactively when you change the affected subsystem. + +```bash +JARVIS_REAL_MODELS=1 swift test --package-path packages/Memory \ + --filter MemoryRegressionCorpusTests +# Requires: local Ollama serving nomic-embed-text + qwen2.5-coder:32b, +# and a loadable vec0.dylib bundled into the test target. + +JARVIS_REAL_CAMERA=1 swift test --package-path packages/Vision \ + --filter CameraCaptureRealHardwareTests +# Requires: a real AVCaptureDevice with .authorized TCC. + +JARVIS_REAL_MODELS=1 swift test --package-path packages/Voice \ + --filter OrpheusTTFATests +# Requires: ~6 GB Orpheus weights pulled. +# Produces an empirical time-to-first-audio measurement. +``` + +The eval harness — Anthropic + local-model matrix, corpus in +`.planning/evals/` — is pinned to `qwen2.5-coder:32b` for the local-model +lane. + +## Cross-references + +- [README](README.md) — project overview and quick-start. +- [ARCHITECTURE.md](ARCHITECTURE.md) — subsystem deep dives. +- [CONTRIBUTING.md](CONTRIBUTING.md) — dev workflow and commit conventions. +- [CLAUDE.md](CLAUDE.md) — settled architectural decisions and AI-agent + collaboration conventions; the canonical reference for command lists. -- 2.54.0 From ced7a4f17e84d23f36c0fcf49d82456d152424b0 Mon Sep 17 00:00:00 2001 From: James Maes Date: Tue, 12 May 2026 15:13:26 -0500 Subject: [PATCH 2/2] docs(readme): finalize MIT license section (remove stale TODO) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The marketing pass confirmed MIT as the canonical license decision (commit e1fcdc5, rationale at .planning/decisions/license.md). A parallel agent later injected an HTML TODO block + "decision still open" phrasing under that section, contradicting the confirmed choice. The badge at the top of the README was MIT, the body text said "currently MIT," but the TODO comment said "do not commit a final license framing until the human confirms" — already done. Replace the conflicting block with a tight, confident statement: released under MIT, see .planning/decisions/license.md for rationale. --- README.md | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 50bf962..b8f0e1b 100644 --- a/README.md +++ b/README.md @@ -352,17 +352,11 @@ Style, commit conventions, and the GSD workflow live in ## License - - -The [`LICENSE`](LICENSE) file at the repo root is currently **MIT** — see +Jarvis is released under the [MIT License](LICENSE). See [`.planning/decisions/license.md`](.planning/decisions/license.md) for -the rationale that landed it. The public-launch decision is still open; -the open PR carries the discussion. +the rationale (solo personal project; no patent strategy or SaaS +surface to protect; MIT considered against Apache-2.0 / MPL-2.0 / +AGPL-3.0 and chosen for minimum friction). ## Acknowledgments -- 2.54.0