Files
Jarvis/docs/SESSION-STATE.md
james.maesandClaude Opus 4.7 71b93898ac docs(handoff): end-of-day 2026-05-12 — round 2/3/4 + audits + tracking migration + roadmap + branding
Closes the session that took Jarvis from "wired-but-dead-everywhere"
to fully-mapped + branded + license-clear + audit-tracked.

Highlights:
- Round 2/3/4 strict-mode boot health shipped (probes → status panel →
  severity model + non-dismissible banners + agent self-awareness preamble +
  red menu-bar icon). Toby fix verified end-to-end mid-dogfood.
- facts.source_turn_id FK dropped (a5999e2) — facts persist now.
- Xcode 26 ProcessInfoPlistFile build race fixed (1557302).
- Dev Overlay shipped with 4 tabs + live log streaming via LogBroadcaster.
- 5-agent audit pass at .planning/audit-2026-05-12/ — ~37 findings.
- 141 GH issues filed across audit findings + carry-forwards + M-0..M-7
  migration epic (54 sub-issues) + comment-cleanup + v1.1 backlog.
- TODO.md deprecated. GitHub Issues canonical.
- Code-commenting style guide locked + applied to AppDelegate as the P0
  exemplar (281b909).
- Roadmap at .planning/ROADMAP-2026-05-12.md with 6 milestones bucketing
  all 141 issues.
- MIT license confirmed; LICENSE/SECURITY/CHANGELOG/issue templates/PR
  template/dependabot all in place.
- README rewritten with mermaid diagrams + acknowledgments + culture
  section. Repo metadata + 12 topics + 3 pinned issues set.

Outstanding: PR #149 (BUILDING.md + README MIT cleanup) draft pending
review. Repo still PRIVATE — public-flip decision is the user's call.

Next session: read this handoff + .planning/ROADMAP-2026-05-12.md, merge
PR #149, decide visibility, then start v0.1 fan-out sprint.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-12 15:45:26 -05:00

31 KiB
Raw Permalink Blame History

Session State

Last Updated: 2026-05-12 end-of-day (Rounds 2/3/4 + audits + tracking migration + roadmap + branding)

Live state lives in GitHub Issues: https://github.com/KofTwentyTwo/Jarvis/issues

This file preserves session-handoff narrative. The bullet-list pending-work sections have been replaced with crosswalks to issue numbers. Read narrative paragraphs for historical context; check GitHub for current state of any item.

▶ Next Session: read docs/HANDOFF-2026-05-12-end-of-day.md FIRST

develop HEAD: 0cc94c6. 141 open issues across 6 milestones. PR #149 is draft and is first action for next session (BUILDING.md + README MIT cleanup).

Shipped today (delta since this file last said "▶ Next Session: M-0"):

  • Rounds 2 + 3 + 4 strict-mode arc — Round 2 boot-phase health probes (NOT FAKED, 687b80b), Round 3 Status… NSPanel (67748f5), Round 4 severity model + non-dismissible banners + agent self-awareness preamble + red menu-bar icon (cfd469f, 79955b6, 23b4ca7, a9531e6). The "Toby fix" — agent refuses to lie about remembering when memory is degraded — validated mid-dogfood.
  • Latent fact-persistence FK fix (a5999e2) — facts.source_turn_id FK incompatible with FNV-hash strategy; dropped FK; facts now persist.
  • Xcode 26 build race fix (1557302) — ProcessInfoPlistFile scheduled after pre-codesign verify, silently reverting JarvisEntitlementsVerified. Declared Info.plist as input.
  • Full audit pass (.planning/audit-2026-05-12/) — 5 parallel agents, ~37 findings filed as issues.
  • Dev Overlay built (8d94c1c → 50c2783 → 6ea2852) — 4-tab AppKit NSPanel + live log stream via LogBroadcaster / BroadcastLogHandler.
  • Tracking migration to GitHub Issues — 141 issues filed; docs/TODO.md deprecated; CLAUDE.md declares Issues canonical.
  • Code-commenting style guide (b763273, 583 lines) + AppDelegate exemplar (281b909).
  • User-outcome milestone roadmap at .planning/ROADMAP-2026-05-12.md (v0.1 / v0.2 / v0.5 / v0.8 / v1.0 / v1.1).
  • MIT license confirmed (.planning/decisions/license.md) + standard repo files (LICENSE, SECURITY, CHANGELOG, issue/PR templates, dependabot, branding).

Next session actions in order:

  1. Read docs/HANDOFF-2026-05-12-end-of-day.md + .planning/ROADMAP-2026-05-12.md to orient.
  2. Merge PR #149 (BUILDING.md + README MIT cleanup).
  3. Decide repo visibility (still PRIVATE; marketing pass assumed public).
  4. Start v0.1 fan-out: Voice CRIT (#28–#36), Memory CRIT (#12–#16), MCP CRIT (#20–#22), Bus/HUD S1 (#40–#42), Vision (#1–#3), B-06 (#51), v1-hole PTT/InputMonitoring/startup (#87/#88/#89).
  5. After v0.1 lands, M-0 starts on its own feature branch.

The pre-existing M-0..M-7 migration plan is unchanged — still locked at .planning/architecture/JARVIS-API-DESIGN-v0.1.md + v0.2.md; epics #4–#11; M-0 directly on develop, M-1+ on feature branches; ~18.5–25.5 engineer-days remaining.

Repo caveats: 5 stashes accumulated (#63), 2 Dependabot moderate vulns flagged, repo still PRIVATE.

▶ 2026-05-11 morning — B-02 tactical patch

develop advances past 46590cd with one commit closing B-02. Substrate gap discovered + addressed in-scope: the turns table was unwritten (schema present, FTS5 trigger ready, but no INSERT site anywhere). Patch adds MemoryStore.appendTurn writer and wires both sides — orchestrator sessionHistoryLookup closure (read) and AppDelegate turnContent (write piggybacked on existing memory-extraction flush path).

  • Patch site (read side): packages/AgentCore/Sources/AgentOrchestrator/AgentOrchestrator.swift — adds PriorTurn struct, SessionHistoryLookup typealias with emptySessionHistoryLookup default (preserves pre-B-02 test setups), ctor parameter, hydration logic that prepends prior turns between system prompt and current user message in chronological order.
  • Patch site (write side): packages/Memory/Sources/Memory/MemoryStore.swift appendTurn(sessionId:role:content:source:createdAt:) + MemoryQueries.turnInsertSQL. Single-row INSERT; FTS5 trigger mirrors content into turns_fts automatically.
  • AppDelegate wiring: App/AppDelegate.swift constructs sessionHistoryLookup closure calling recentTurnsForSession(limit: 10) and reversing DESC → chronological; passes it to AgentOrchestrator init. turnContent closure (existing memory-extraction path) gains a side-effect: write the flushed pair via appendTurn before returning. Assistant row offset by +1 ms so DESC + id-tiebreaker preserves user→assistant order.
  • Regression coverage:
    • HistoryThreadingRegressionTests.HT-1 — three-turn integration; asserts third call's messages array is [system, user("ok"), assistant("ack"), user("yes"), assistant("ack2"), user("why?")].
    • HistoryThreadingRegressionTests.HT-2 — empty-history default produces [system, user] (pre-B-02 baseline preserved).
    • HistoryThreadingRegressionTests.HT-3 — three-turn happy path emits zero LLMProviderError.streamTruncatedFinal events. Pins R-006 / Phase E gate behavior — the patch grows the messages array, not the system prompt, so CacheHints.eligibleForSystemPrompt(finalSystem) is unchanged.
    • MemoryStoreAppendTurnTests.AT-1..4 — append round-trip, user/assistant pair chronological reconstruction, session scoping, FTS5 trigger fires. Env-gated on JARVIS_VEC0_STUB_PATH per existing MemoryStore-test convention; skip without vec0.dylib.
  • Honesty note: in dormant-memory mode (no vec0/no Ollama), turn persistence is also dormant — the appendTurn call is guarded by memoryStore != nil. When D-5/D-6 land and memory comes up live, persistence activates without further code changes.

▶ 2026-05-07 evening — Design swarm output

▶ Earlier this session — Design swarm output (2026-05-07 evening)

develop HEAD was b36e8eb (handoff commit) at swarm start. Tonight's commit adds all .planning/architecture/ artifacts and the Tools/jarvis-diag/ skeleton (compiles green; type-signatures only).

Locked decisions:

  • UQ-1: runtime gate JARVIS_HARNESS=1 (single binary).
  • UQ-2: B-02 tactical patch outside migration + regression test; B-04 stays in M-6.
  • UQ-3: explicit Voice.synthesizeTurn(turnId:text:tier:) command (orchestrator-as-driver visible at API).
  • UQ-4: Settings owns ALL configuration mutation; Voice has only runtime-control verbs; bargeIn migrates to Turn.
  • UQ-5: parametric harness mandated — every scenario runs .inProcessActor AND .jsonRoundTripWebView.

Plus 4 orchestrator-decided defaults (UUIDs for identifiers; ~/Library/Application Support/Jarvis-Harness/ data isolation; Settings._setConfirmationDefault(.deny) default; bus dual-version handshake ["2.3.0", "2.4.0-rc"] during M-0..M-7).

Carry-forward bug status (unchanged tonight; closes during migration per UQ-2 + plan):

  • B-02 → tactical patch BEFORE M-1
  • B-03 → M-5 (Vision)
  • B-04, B-05 → M-6 (Voice)
  • B-06 → M-7 (Turn) [DOM observability gap acknowledged; out of harness scope]
  • B-07 → deferred (Plan 10-05 re-scope)
  • B-08 → M-1 (Self)

▶ 2026-05-07 morning — substrate fixes (pre-pivot)

Current Status (2026-05-07 end-of-session)

develop at 1b7fb81, push pending. Tree clean (only ignorable untracked: .claude/scheduled_tasks.lock, build-devoupload/).

This session's work — substrate fixes for the agent's tool-call pipeline:

  • 260350b..9a59648 — Plan 10-02b: tool catalog enumeration (B-01a) — orchestrator now sources availableTools: from the runtime catalog instead of hardcoded []. Closes the regression that landed silently in commit fdb56d2 (Phase 9 Plan 09-01) and silenced ALL tool calls for ~3 days.
  • a75ae0a — Plan 10-02 SUMMARY recording AC-06 PASS / AC-05 FAIL after the live test surfaced B-01.
  • 3cf0d39..1b7fb81 — Plan 10-02c: dispatch routing (B-01b) — InProcessAwareToolDispatcher composite routes in-process tool calls (memory + four self-knowledge) through InProcessToolRegistry.dispatch; preserves confirmation gating. Live-verified: "what mic are you using?" now returns "Sennheiser SDW 5 BS headset (USB) at 48 kHz, with AEC on" with real tool_use/tool_result round-trip.

Phase 10 status at session-end:

  • 10-01 (4 self-knowledge tools) — shipped, AC-01..04 PASS
  • 10-02 (system prompt preamble) — AC-06 PASS; AC-05 retroactively PASS via 10-02b/c live verification (SUMMARY's FAIL marker not yet flipped — deferred per handoff)
  • 10-02b — shipped, B-01a closed
  • 10-02c — shipped, B-01b closed; SUMMARY missing (only PLAN written; deferred to post-design housekeeping)
  • 10-03 / 10-04 / 10-05 — DEFERRED. They build diagnostic UI on top of subsystems still dead. Re-scope against new API after design lock.

Why the pivot to API-first design: two days of "fix → test green → relaunch → still broken" produced 7 carry-forward bugs (B-02..B-08 — see TODO.md and the handoff). The verification gate has been "executor self-reports green tests + boundary gates," which cannot detect substrate failures. The architectural pivot dissolves this entire bug class by forcing every behavior through a tested API contract. Stopping individual bug fixes until the API design is locked.

Carry-forward bugs (DO NOT fix piecemeal)

Live evidence collected during today's verification. All re-scope against the new API.

ID Symptom
B-02 Conversation continuity broken — prior turn context lost
B-03 HUD camera button click does nothing
B-04 Voice input dead — wake-word + STT silent
B-05 TTS silent — text replies not spoken
B-06 Chat panel doesn't auto-scroll as text streams
B-07 Voice Log menu item missing (Plan 10-05 unrun)
B-08 get_self_state returns correct ID but Claude paraphrases as "Opus 4.5"

Pre-existing carry-forwards (unchanged today)

  • D-5 / D-6 — libsqlite3.dylib + vec0.dylib build-and-bundle (user environment work)
  • D-7 — ollama pull nomic-embed-text + qwen2.5-coder:32b
  • HUMAN-UAT — VOICE-07/09/10/12/13/14 on Release Developer ID archive
  • B-7-followup — AudioLevelEmitter production wiring
  • TTSInterruptTests.testI3 pre-existing 10s flake

Earlier session — 2026-05-04 (preserved below for context)

develop at 0234eaa, push pending. Tree clean. Track A + Track B-1..7 + Cleanup batch + Track C (vision) + Track D code-work (D-1..D-4 + D-5/D-6 skeletons) + audit-2026-05-04 P0/P1/P2/P3-18 fixes + documentation sweep closed. D-5/D-6 binaries + D-7 model pulls remain on the user (environment work the executor cannot do autonomously).

Documentation sweep (this session, 5 commits)

  • 4e1c8a0 — docs: write top-level README.md — replaces the stale "Pre-implementation" stub with a current overview: status table, repo layout, build/test commands, pointers to ARCHITECTURE/CONTRIBUTING.
  • 41b506d — docs: write ARCHITECTURE.md — marquee architecture document (~2300 words). Mermaid top-level diagram of the audio-graph fan-out + agent loop + bus, subsystem deep-dives for the 13 packages, cross-cutting concerns (concurrency, TCC, codesign, the 18 boundary gates), audit-derived anti-pattern list, where-things-live cheat sheet, honest gaps & deferred work.
  • 508cf92 — docs(packages): per-package README files — adds README.md to each of the 13 SPM packages. Each covers purpose, key public types, deps, consumers, invariants, test stack, notable files. Memory README explicitly marks the package functionally OFF until vec0.dylib + Ollama models land.
  • 85b14ce — docs(docstrings): add header docstrings to key public types — AppDelegate (preamble + lifecycle + see-also), VoiceController (// MARK block converted to /// with Threading + Anti-patterns), MCPClient (registry + restart-mutex + relationships). Comment-only; verified via swift build (Voice, MCP) + check-app-builds.sh. Other types listed in the brief already had substantive docstrings — left alone per audit-grade-improvement-only.
  • 0234eaa — docs: write CONTRIBUTING.md — dev environment setup, build/test pointers, GSD workflow, boundary-gate discipline, conventional-commit conventions matching the existing log, test-double naming taxonomy, anti-pattern checklist, step-by-step guides for adding an MCP tool / HUD button + bus event, compaction-recovery section for AI agents.

All 18 boundary gates green; App target builds clean; Voice + MCP packages compile after docstring additions.

What Was Done This Session

  • Six-agent deep audit (voice / HUD / vision / memory / LLM / tests) → .planning/audit-2026-05-03/SYNTHESIS.md. Verdict: nothing worked end-to-end; every modality had ≥1 fatal break.

  • Commit 1f8e03e — Track A (text turn + animated rings):

    • HUD idle ring no longer static (stateUniforms.ts:30).
    • CacheHints.eligibleForSystemPrompt gates extended-cache-ttl on prompts ≥1024 tokens (likely streamTruncated cause).
    • StreamOutcome classifier distinguishes 200+0bytes / 200+0frames / 200+EOF / complete.
    • AnthropicAPIKeyProvider.make propagates KeychainError instead of swallowing.
    • 2 new real-WKWebView e2e tests (chat-turn round-trip both directions).
  • Commit ee7f6d2 — Track B-1..3 (voice foundations):

    • scripts/copy-voice-models.sh bundles ONNX models at runtime path Contents/Resources/Models/{openWakeWord,silero}/. 6 shell tests.
    • WakeWordDAG.swift:93 fixed: production now calls feed(samples:) not feedTest(). 2 unit tests.
    • TTSEngineActor.orpheus is now OrpheusTTS?; App/Voice/VoiceOutputWiring.swift constructs tier-1 (AVSpeechSynthesizer) without Orpheus weights. 4 unit tests including real AVSpeechSynthesizer.
  • Commit e9c0a34 — Track B-4 (audio graph + STT wiring):

    • AudioGraphOwner.setCancelInFlight / setReleaseORTSessions cross-actor setters (Swift 6 mode requires).
    • New PCMBufferBuilder (AudioChunk.pcm16k → AVAudioPCMBuffer + AVAudioConverter resample). Lives outside @available(macOS 26) gate so unit tests run on every supported macOS. +7 tests.
    • LiveSpeechAnalyzerBridge.feed(_:) no longer _ = chunk — full SpeechAnalyzer + SpeechTranscriber wiring: builds analyzer with bestAvailableAudioFormat, opens AsyncStream<AnalyzerInput> pipe, spawns result-drain Task, finalises through end-of-input.
    • installVoice constructs AudioGraphOwner, spawns degradation+rebuild consumers BEFORE open() (so the aec=false retry path is observed), hands ring buffer to WakeWordDAG.start(ring:), sets cancelInFlight for teardown step 1. Fail-soft on graph open failure.
    • VoiceWiringTests testW1 asserts new audioGraphOwner / audioGraphDegradationTask / audioGraphRebuildTask strong properties.
  • Commit 61aed20 — Track B-5 (chunk pump + e2e proof):

    • VoiceController gains a chunkPump: @Sendable (AsyncStream<AudioChunk>.Continuation) async -> Void init parameter (no-op default for back-compat).
    • startSTTSession spawns a detached chunkPumpTask; endSTTSession cancels it before closing the chunk continuation; shutdown cancels it. No leaked Task on session end.
    • AppDelegate's production pump reads audioGraphOwner.ringBuffer in 1024-sample windows (~64 ms @ 16 kHz), 10 ms sleep on starve, exits on Task cancel.
    • VoiceLoopE2ETests (+3): preset-chunks → orchestrator.submit text match (E1); empty pump → no submit + back to idle (E2); pump task exits within 100 ms of pttUp (E3).
  • Commit bce725b — Track B-7 (BufferBroadcaster fan-out):

    • New BufferBroadcaster (packages/Voice/.../AudioGraph/BufferBroadcaster.swift) fans the audio-graph tap output to per-subscriber RingBuffers; consumers no longer race for samples on the legacy SPSC ring.
    • AudioGraph.swift tap callback calls broadcaster.publish(buffer); the legacy public let ringBuffer is now a private "primary" subscription so WakeWordDAG.start(ring:) and the overflow watcher keep working without signature changes.
    • AudioGraphOwner.subscribe(capacityFrames:) actor method added — chunk pump in AppDelegate now subscribes per-session via this and unsubscribes on pump exit.
    • Publish path is wait-free in steady state: OSAllocatedUnfairLock<[Subscription]> snapshot copy, iterate outside lock; per-subscriber RingBuffer.write remains lock-free. Real-time tap-thread safe.
    • 5 new BufferBroadcasterTests (BB-1..5: single sub, multi-sub no theft, unsubscribe stops, late-join skips prior, concurrent stress). All pass.
    • Voice swift-testing 17 → 22 (+5 BB). XCTest 84 unchanged. Pre-existing TTSInterruptTests.testI3 baseline 10s flake unchanged.
    • Anti-patterns enforced: no actor hops on tap thread, NSLock forbidden, T-06-05-03 (no PCM logging) preserved, VOICE-14 single-call-site preserved.
  • Commit ad93dac — BLOCKER-INT-1 (real bus gateway): replaced NoopBusGateway in AppDelegate.swift with MCPBusGatewayAdapter that forwards emitToolCallStart / emitToolCallEnd through OutboundBatcher. Tool-call cards now reach the webview bus. New MCPBusGatewayAdapterTests proves the start→end forward path.

  • Commit 6f6617e — F-A2-01 (stale bus world): WebviewBridgeOutboundTests:80 asserted retired JarvisBusWorld name; production switched to .page in fb41c5f. Test now asserts WKContentWorld.page — load-bearing again.

  • Commit 08125a4 — tests-audit cleanup (5 tautologies): removed/replaced XCTAssertTrue(true) placeholders per .planning/audit-2026-05-03/tests-audit.md section 5. MCPRuntimeWiringTests:260 in-place assertion fix; WebviewBundleLoadTests, InputMonitoringDenialTests, PackageBoundaryTests deleted documentation-as-test funcs; ToolChoiceTests trailing tautology removed (closure compile is the gate). HudStateEnumTests rubber-stamps left as-is (a11y labels are user-facing, load-bearing).

  • Commit 5cd46c9 — F2 linter (scripts/check-no-leftover-stubs.sh): grep-based gate against Replaced in 0…, TODO: Plan|0X-…, 2-line stub function bodies, and production Noop*( / *Stub( instantiations. Self-tested against synthetic fixture; clean on current develop. Allowlists Dormant* (real producer-stream pattern).

  • Commit 7a5543a — Track C-1 (CameraCapture AVCapturePhotoCaptureDelegate): replaces the 1×1 black-JPEG hardcode with the real photoOutput delegate path. New PhotoCaptureProxy (NSObject) bridges the delegate callback into a CheckedThrowingContinuation; retains itself for the lifetime of the capture (AVCapturePhotoOutput holds delegates weakly), breaks the cycle on the first didFinishProcessingPhoto callback. Test seam photoCaptureOverride mirrors authStatusProbe — production tests can exercise captureFrame() end-to-end without hardware. Vision 56 → 59.

  • Commit ea09fd4 — Track C-2 (frameStream fan-out): replaces AsyncStream { cont.finish() } with a real fan-out backed by AVCaptureVideoDataOutputSampleBufferDelegate. New VideoSampleDelegate fans incoming CMSampleBuffers to a UUID-keyed map of registered continuations under an NSLock-guarded snapshot. frameStream(forPresence:) now generates a UUID per subscription, hops into the actor to register against the live delegate, and tears down via cont.onTermination. shutdown() drains the subscription set. Vision 59 → 63.

  • Commit 4159d44 — Track C-3 (HUD camera button): closes vision-audit §4 "HUD button emitter has zero matches". New CameraButton.tsx posts { type: 'frameAttachRequested' } via window.jarvisBus.send; rendered next to the chat input's Send button with matching toolbar chrome. JS path: webview/packages/hud/src/chat/CameraButton.tsx:14. Swift handler at App/AppDelegate.swift:1696-1698 already routed it into FrameAttachController.requestAttach(reason: .hudButton). HUD vitest 94 → 97.

  • Commit df6a4d2 — Track C-4 (explicit T2 missing variant): replaces the silent t2Provider: t1 AppDelegate hardcode with MissingT2Provider whose stream(...) finishes with VisionError.t2ProviderUnavailable. Real vllm-mlx wiring (codesigning + binary bundling + feature flag) is downstream work and out of Track-C scope; the bug being fixed here is "silent T1-as-T2 fallback hides intent" — explicit-missing makes the missing wiring debuggable instead of silent. Production callers must gate on evaluatePostResponse(..., t2Available: false) (already do); MissingT2Provider's stream is never actually invoked in the live flow. Vision 63 → 67.

  • Commit eac16c9 — Track C-5 (confirmSend wired): closes vision-audit §4 "confirmSend has zero non-test callers". handleChatSubmit and handleChatCancelAndSubmit now consult FrameAttachController.hasPendingFrame and, when armed, pull the ImageBlock via confirmSend(userText:) and route through submit(.withImages(...)). Both submit handlers carry the wiring (WARNING-4 parity with the existing phrase-trigger path). Completes the Track C-3 click flow end-to-end. Vision 67 → 70.

  • Commit 19362f6 — Track C-6 (real-hardware integration test): CameraCaptureRealHardwareTests exercises captureFrame() and frameStream() against real AVCaptureSession output. Gated by ALL of: JARVIS_REAL_CAMERA=1 env, AVCaptureDevice.default(for: .video) non-nil, authorizationStatus == .authorized. Test does NOT prompt for TCC — headless test runs skip cleanly. Run interactively: JARVIS_REAL_CAMERA=1 swift test --package-path packages/Vision --filter CameraCaptureRealHardwareTests. Asserts: jpeg byte count > 1000, SOI marker, width/height > 1 (so a regression to the 125-byte 1×1 stub trips immediately); frameStream emits a .sampleBuffer within 2s. Vision 70 → 72 (2 tests, both skip without env+TCC).

  • Commit 75a10be — Track D-1 (installMemory cascade): single return after MemoryStore(databaseURL:) throw left both memoryExtractionOrchestrator AND memoryExtractionCoordinator nil for the process lifetime — extraction was a no-op even though the LLM call to Ollama is independent of SQLite. Restructured: store nil now logs a warning, sets memorySearchAvailable=false, but extractor + orchestrator + coordinator all construct. ApplyOp closure captures [weak self] and routes to debug log when memoryStore is nil (drain loop survives). New MemoryInstallWiringTests proves the cascade is closed. T-06-05-03 preserved: log only turnId hash, never subject/object content.

  • Commit 707c45b — Track D-2 (SearchMemoryTool + ForgetFactTool registration): both tools have lived in packages/MCP/Sources/MCP/InProcess/ since Plan 07-03 with zero production registration — agent loop had no way to call memory. New App/MCP/InProcessMemoryAdapters.swift bridges MCP's tool protocols to Memory's actors (HybridSearchAdapter wraps HybridSearch and translates [FactRef] → [SearchMemoryHit]; ForgetFactStoreAdapter wraps MemoryStore.forgetFact). installMemory builds an InProcessToolRegistry and registers conditionally: forget_fact when memoryStore != nil, search_memory when memorySearchAvailable && embedder init succeeds. Embedder failure degrades to "writes ok, no search" rather than failing the whole subsystem.

  • Commit 51750c1 — Track D-3 (priorFacts wiring): pre-fix MemoryExtractionOrchestrator.process(_:) hardcoded priorFacts: [] — extractor was blind to existing facts, only ever ADDed, never UPDATEd. Added PriorFactsLookup typealias + priorFactsLookup ctor parameter (default emptyPriorFactsLookup preserves pre-D-3 behavior). Lookup throws degrade to empty list with a warning log so the drain task survives. New MemoryStore.recentActiveFacts(limit:) + matching MemoryQueries.recentActiveFactsSQL (server-side cap, active-only). AppDelegate's installMemory passes a closure returning up to 50 recent active facts. Tests: testD3_priorFactsLookupDrivesUpdateOp (stub provider emits UPDATE only when it sees [99] prior fact id in system prompt; asserts applyOp receives .update(supersedes: 99, …)); testD3_priorFactsLookupErrorDegradesToEmpty (lookup throws, job still applies its ADD op). Memory 86 → 88.

  • Commit c3bd0a5 — Track D-4 (remember-Brutus end-to-end): new RememberBrutusEndToEndTests.testExtractionWriteThenSearchFindsBrutus proves the extraction → store → search loop holds. Real MemoryExtractionOrchestrator + MemoryExtractor + HybridSearch; fakes for the vec/Ollama-dependent surfaces (FakeStore actor conforms to both apply path and MemoryReadStore; StubEmbedder returns constant 768-dim vector; BrutusProvider returns one ADD op then messageStop). Scenario: turn 1 "My dog Brutus is a Bernese Mountain Dog." → ADD lands in store → turn 2 "What breed is Brutus?" → search.searchFacts returns one hit with summary "Brutus breed Bernese Mountain Dog". Boundary stops at HybridSearch.searchFacts; MCP-side dispatch covered by InProcessMemoryToolsTests in the MCP package. Memory 86 → 87 (D-3 added via grouping; total Memory tests now 87).

  • Commit 6e249ee — Track D-5/D-6 (deferred build + fetch script skeletons): scripts/build-sqlite-with-extensions.sh (clang flags for SQLITE_ENABLE_LOAD_EXTENSION=1 + FTS5 + RTREE + threadsafe=2; TODO markers for SQLite version, amalgamation URL, SHA256, codesign identity) and scripts/fetch-sqlite-vec.sh (GitHub release tag + SHA256 + asset path; TODO markers for version + hash). Both mode 755, exit 1 with clear "TODO: fill in …" message until pins land — no deceptive successful stub.

  • Commits 57847f2 / f9cd25d / 2d9a25a — audit-2026-05-04 P2 stragglers:

    • 57847f2 (P2-14, test-seam visibility): VoiceController _forceState / _testFireSpeechEnd / _testCurrentSttSessionId (4 seams) flipped from public → internal; MCPClient _testHandle + MCPServerHandle _testProcessIdentifier (2 seams) flipped to @_spi(Testing) public. Voice tests already use @testable import; MCP tests gain @testable @_spi(Testing) import JarvisMCP; Harness's MCPCrashRunner opts in via @_spi(Testing) import JarvisMCP. Public ABI no longer leaks test entry points.
    • f9cd25d (P2-15, mock naming): new CLAUDE.md §"Test naming conventions" (line 127) documents Mock/Stub/Fake taxonomy (records-and-scripts / canned-data / realistic-stateful). 15 worst-mismatch stragglers renamed in older corpus: 6 Stub* → Mock* (HybridSearchTests StubEmbedder/StubStore, SessionHistoryTests StubStore, InProcessMemoryToolsTests StubHybrid/StubHistory/StubForget — all record calls); 8 Mock* → Stub* (STTBackendSwitchTests MockSpeechAnalyzerBridge/MockWhisperKitBridge, VoiceWiringTests Mock*ForW4 ×6 — all canned no-ops); 1 Fake* → Mock* (FakeJSEvaluator in two files — comment already said "Records each call for assertion"). Did NOT touch types added in today's P1+P2 fix commits per audit constraint.
    • 2d9a25a (P3-18 / security LOW-3): scripts/check-applescript-confirmation.sh — defense-in-depth grep gate. For each non-comment/non-test line containing run_applescript, asserts the enclosing register-call body (line + up to 5 following lines, terminated at )) contains requiresConfirmation: true. Verified catches regression: temporarily flipped App/MCP/MCPRuntimeWiring.swift:119 to false → gate FAILed with the file:line citation; reverted; gate PASSes on clean tree. Comment-only references in HudStateIntent.swift:19 + InProcessTool.swift:9 are filtered by is_comment_line.
  • Commit c7f9ece — Track B-6 (VAD-gated session end):

    • VoiceController.startSTTSession now spawns a per-session VAD interceptor task. Pump output flows through it, forwarding every chunk to STT and running Silero VAD per 512-sample window.
    • New private runVADInterceptor: tracks armed state on .speechStart, counts consecutive silence chunks after .speechEnd, and triggers endSTTSession() once the hangover threshold (5 chunks ≈ 160 ms) is reached. Mid-utterance speech resumption cancels the pending finalize.
    • endSTTSession() is now async; pttUp() awaits it. Single non-VAD caller path preserved.
    • 512-sample VAD window builder carries over the partial tail between chunks so it works against both the test pump (512-sample chunks) and the production pump (up to 1024-sample chunks).
    • Anti-patterns enforced: VAD handler does NOT block on await analyzer.finish() — finalize fires inside Task { … } to avoid deadlock on the analyzer completion path. T-06-05-03 preserved (no PCM in logs). VOICE-14 single cancelAndSubmit site preserved.
    • VADGatedSessionTests (+4): VAD-1 .speechEnd + 5×silence → submit; VAD-2 PTT regression with VAD wired; VAD-4 sustained speech → no submit; VAD-5 speech resumption within hangover cancels pending finalize.

Active Branches

Branch Status
develop At 2d9a25a, ahead of origin (push pending). Tree clean.

Pending Work — moved to GitHub Issues

Live tracking has migrated to https://github.com/KofTwentyTwo/Jarvis/issues. Crosswalk for items previously listed here:

  • AudioLevelEmitter production wiring — verified done; consumer still dead — #54 + #44
  • Track C (vision) — CLOSED 2026-05-04 (commits 7a5543a through 19362f6)
  • Track D (memory code-work) — CLOSED 2026-05-04 (commits 75a10be through 6e249ee); environment work #56/#57/#58; memory database now live via 48ad8d6
  • TTSInterruptTests.testI3 flake — #55
  • streamTruncated empirical confirmation — #62
  • Migration M-0..M-7 — epics #4 through #11
  • Carry-forward bugs B-03..B-08 — #48 through #53
  • 2026-05-12 audit findings — see docs/TODO.md crosswalk for the full list

Key Reference

  • Audit reports: .planning/audit-2026-05-03/{SYNTHESIS,voice,voice-audit,hud-audit,vision-audit,memory-audit,llm-audit,tests-audit}.md
  • Plan: .planning/AUDIT-AND-FIX-PLAN.md, findings tracker: .planning/AUDIT-FINDINGS.md
  • Test stack at session end (post P2-14/15/P3-18): Voice 87 XCTest + 23 swift-testing (3 skipped), MCP 85 XCTest, Memory 88 XCTest (19 skipped — vec0/Ollama gating), Bus 58 XCTest, AgentCore 19 + 72 XCTest, Vision 19/72 XCTest, Shell 5+7 XCTest, webview/hud 97 vitest. All 18 boundary gates PASS (17 pre-existing + new check-applescript-confirmation.sh), app builds clean. Pre-existing baseline issues unrelated to this batch: webview/packages/hud/src/hud/SegmentedRing.tsx typecheck warnings, TTSInterruptTests.testI3 10s flake. Flag for follow-up; out of scope here.
  • Next-session orientation: read .planning/audit-2026-05-04/SYNTHESIS.md first, then this file, then git log --oneline 6e249ee..HEAD for the audit P0-P2 fix story.