6 September 2026 · Jarvis-owned code only

Jarvis layer implementation and performance review

The main problem is scattered ownership: catalogs, presentation projection, retries and speech lifetime are implemented in several places. Consolidate those responsibilities before adding more abstractions.

Scope

This is a normal review of the current workspace, not a PR comparison. Source links pin the inspected checkout (1668bd598) for reproducibility only. T3 implementations, the inherited sidebar, generic connection infrastructure and TTS model selection are excluded. Every proposed change belongs to Jarvis and uses existing public T3 seams.

Inspected Jarvis core grounding, confirmation, semantic/model selection, task state, identity, vocabulary and presentation; mesh and client adapters; server controller, task desk, aliases, follow-ups, presentation, push and voice compute; web/mobile interaction, settings, onboarding and speech; desktop worker/protocol and Jarvis packaging. This is source review with focused helper checks, not exhaustive runtime certification. No live database, app server, browser, simulator or microphone was used. Device behavior, production latency, heap and bundle impact remain unmeasured.

AGENTS.md now makes Jarvis ownership the default scope, forbids upstream refactoring under a broad “whole app” request, and requires explicit authorization for an upstream seam change.

What I would tackle first

  1. Fix consent, missing broker settlement and desktop decoding. These are small contracts with direct user consequences.
  2. Consolidate presentation projection and reconcile mobile listener lifetime. Their costs amplify each other.
  3. Remove global follow-up retry blocking and stop hydrating every recent task before deciding.
  4. Unify catalog and speech ownership, then share only the interaction transitions that both clients need.
  5. Apply alias indexing and streaming release hashes as smaller, local improvements.

No recommendation requires changing T3 provider, orchestration, persistence-query, terminal or coding-UI implementations.

High priority · Confirmed helper behavior

1. Approval parsing mistakes questions for consent

The positive-keyword regex accepts “should I approve it?”, “maybe allow it” and “allow it only if tests pass”. The pending-reply interpreter uses that decision to construct an approval answer. Negation handling alone does not make consent explicit.

Smaller implementation

Use a small closed grammar for explicit approval answers. Questions, conditions and mixed instructions must remain clarification. Keep the authority in Jarvis’s deterministic interpreter.

Current

Question/conditional → positive keyword → accept

Proposed

Explicit complete answer → deterministic decision

Focused proof

Add negative cases at interpretPendingJarvisReply, then check desktop/mobile/text/voice callers. Existing affirmative and refusal cases must survive.

packages/jarvis-core/src/confirmation.ts:42

High priority · Confirmed source path

2. Presentation projection runs once per subscriber

Every Jarvis presentation subscriber listens to all eligible domain events, loads thread detail and project data, and builds a presentation before filtering by origin. More devices and retained mobile turns multiply identical Jarvis work.

Smaller implementation

One Jarvis-owned live projection should build each presentation once and fan it out through a bounded ephemeral stream. Keep exact origin filtering, scoped shutdown and durable task inspection on reconnect. No replay ledger or T3 event-engine changes.

Current

Each listener → load + build + origin filter

Proposed

One Jarvis projection → origin-filtered listeners

Focused proof

Assert one projection read per event with multiple origins and devices; verify overflow behavior, isolation and no replayed speech.

apps/server/src/jarvis/Layers/JarvisWsRpc.ts:419

High priority · Confirmed source path

3. Follow-up retries block unrelated tasks

One Jarvis worker handles all queued thread wakeups. Its dispatch and markDispatched chain retries twice with 30-second spacing. One failing item can occupy the worker through 60 seconds of retry delay, delaying unrelated tasks. It also hydrates details on ready events before checking whether Jarvis has pending work.

Smaller implementation

Keep per-thread serialization and cancellation ownership, but use a small bounded Jarvis worker pool and coalesced wakeups. Schedule retries without holding global progress. Separate accepted task execution from status cleanup. Check the Jarvis queue before expensive reads.

Current

One retrying thread → all follow-ups wait

Proposed

Bounded workers + per-thread owner → independent progress

Focused proof

Inject a failing A and ready B; B must dispatch without waiting for A’s retry clock. Check stop/claim/dispatch races and restart idempotency with typed drains.

apps/server/src/jarvis/Layers/JarvisFollowUpDispatcher.ts:78

High priority · Confirmed source path

4. Mobile retains listeners after missed completion

Refresh reloads catalog and selected desk, but does not reconcile activeTurns. Terminal live presentations remove retained turns; a completion missed offline does not. Each retained turn mounts another presentation subscription. Forgotten nodes are not pruned from activeTurns in the catalog effect.

Smaller implementation

Reconcile retained node-qualified tasks on reconnect/foreground using existing public task state reads. Retire settled or confirmed-missing tasks and removed nodes, preserve unreachable tasks, and deduplicate lookups. Do not build another completion store.

Current

Missed completion → retained turn → permanent listener

Proposed

Reconnect inspection → settle or retain by durable state

Focused proof

Cover offline completion, removed node, 404, unreachable node and repeated foreground transitions. Subscription count should return to the number of genuinely active interactions.

apps/mobile/src/features/jarvis/JarvisMobileProvider.tsx:219

High priority · Source path and local TCP repro reported by review lane

5. Voice broker clean disconnect leaves a request pending

The socket handler settles on data, error, abort or inactivity timeout, but has no end/close handler. A broker that closes normally before returning a complete response can leave the promise pending after the socket is gone.

Smaller implementation

Use one Jarvis request-lifetime owner for complete response, EOF, close, timeout and abort. Reject incomplete EOF promptly; clean up every listener exactly once.

Current

Clean EOF → no settlement

Proposed

EOF/error/response/abort → one settled request

Focused proof

Use a local broker that closes with no data and with a partial JSON line; both must reject promptly. Also test full response followed by close and abort races.

apps/server/src/jarvis/Services/JarvisVoiceCompute.ts:106

Medium priority · Confirmed Jarvis caller behavior

6. Controller loads every recent conversation before deciding

Before interpreting a request, the controller serially loads details for context, reference and all recent task IDs, up to 22 distinct threads. Most commands only need a task catalog and detail for the selected task. The Jarvis adapter chooses this broad read.

Smaller implementation

Build navigation candidates from existing shell data and bounded Jarvis metadata; defer full detail to the selected task or the exact history-dependent operation. Reuse existing public T3 interfaces. Do not modify upstream projection implementations or invent a second thread store.

Current

Every instruction → all recent details → choose task

Proposed

Shell catalog → choose task → necessary detail

Focused proof

Count detail calls for list/status/stop/start with 20 long recent tasks. Preserve title, objective, pending-input and origin correctness. If an existing seam cannot supply a field, report that constraint separately.

apps/server/src/jarvis/Layers/JarvisController.ts:356

Medium priority · Confirmed source path

7. Catalog ownership differs across Jarvis surfaces

Web creates a fresh mesh for every command while manager, control center and onboarding keep separate catalog state and stale-response bookkeeping. Mobile uses a runtime-owned mesh. Mesh refresh waits for all node reads before publishing its result, so one slow node delays visibility of fast nodes.

Smaller implementation

Give the Jarvis runtime one scoped catalog owner and per-node refresh sharing. Publish node progress independently, reject results from removed/replaced connections, and let UI adapters observe the same state. Keep connection lifecycle in the existing registry.

Current

Private UI catalogs + new mesh per command

Proposed

One Jarvis catalog owner → thin UI adapters

Focused proof

Test overlapping refresh, one slow node, node removal during refresh and simultaneous settings/control surfaces. No repeated reads solely to reconstruct discarded Jarvis state.

apps/web/src/state/jarvisMesh.ts:17

Medium priority · Confirmed source path

8. Speech queue and cancellation have multiple incomplete owners

The renderer appends reports to an unbounded Promise chain. Browser utterances settle only through end/error callbacks. Disable, disconnect and unmount cancel through the desktop bridge only, leaving browser playback without equivalent ownership. Mobile background handling cancels current playback but enqueueSpeech itself has no foreground gate.

Smaller implementation

Use a bounded ephemeral Jarvis speech queue with platform adapters for playback and cancellation. Clear obsolete queued work on disconnect/disable; gate mobile admission by foreground state. Preserve durable visual approvals and task results. This concerns lifecycle, not TTS model choice.

Current

Promise chain + partial platform cleanup

Proposed

Bounded queue → cancellable platform adapter

Focused proof

Test never-settling playback, disable during browser speech, reconnect, overflow and a live presentation arriving after mobile backgrounds. Do not infer cancellation from merely clearing a local ref.

apps/web/src/components/jarvis/JarvisVoiceReporter.tsx:104

Medium priority · Confirmed source path

9. Multi-project clarification has no cancel exit on mobile

The cancellation branch is gated by acceptsAffirmation. A multi-candidate project clarification normally does not accept affirmation, so “cancel” is treated as an unmatched project and the pending route remains.

Smaller implementation

Handle explicit discard before answering any clarification type. Centralize pending-interaction transitions shared by web and mobile, with platform capture/navigation kept outside. Avoid a generic workflow framework.

Current

Ambiguous route + cancel → ask again

Proposed

Any pending clarification + discard → idle

Focused proof

Cover cancel/no/new instruction across one-candidate confirmation and multi-candidate clarification. Preserve the original request identity only while the pending interaction remains active.

apps/mobile/src/features/jarvis/JarvisMobileProvider.tsx:386

Medium priority · Confirmed source ordering; overlap duration unmeasured

10. Desktop voice restart loses ownership before exit

On retry, the host clears the old child handle, sends SIGTERM and immediately spawns a replacement. Signal delivery does not establish that the old worker and its speech child have exited. A slow shutdown can overlap workers and hardware/model ownership.

Smaller implementation

Own restart as stop → observed exit → start, with a bounded shutdown deadline for the captured child PID and scoped child cleanup. Keep one authority for worker lifecycle.

Current

SIGTERM → immediately spawn

Proposed

Stop owned child → await exit → spawn

Focused proof

Use a fake worker that delays exit. Assert replacement cannot acquire voice until cleanup completes and late messages cannot change current state.

apps/desktop/src/voice/DesktopJarvisVoice.ts:399

Medium priority · Confirmed source and byte-split reproduction

11. Desktop transcript decoding corrupts split UTF-8

The worker stdout handler calls chunk.toString("utf8") on each Buffer independently. A non-ASCII character split across pipe chunks becomes replacement characters before JSON parsing; a transcript can remain valid JSON while its project name is corrupted.

Smaller implementation

Use one stateful decoder per worker generation, or set the stream encoding once. Reset decoder and line buffer together on restart. The server voice-broker reader already demonstrates the required stateful behavior.

Current

Independent chunk decode → corrupted name

Proposed

Stateful stream decode → intact transcript

Focused proof

Split serialized transcripts at every byte boundary, including accented and non-Latin names. Verify emitted transcript and subsequent grounding input match the original.

apps/desktop/src/voice/DesktopJarvisVoice.ts:462

Low priority · Measured operation count with synthetic data

12. Vocabulary repeatedly scans the entire alias list

For each project the builder filters all aliases. At 100 projects with 20 aliases each the direct helper check counted 200,000 comparisons; at 1,000 projects it counted 20 million and took about 343 ms in this run. Semantic prompt preparation also repeatedly groups aliases through projectSemanticNames. Typical small catalogs may hide this.

Smaller implementation

Index aliases by project once per catalog construction and reuse the grouping in semantic preparation. Keep a simple Map inside the owning module; no cache invalidation framework is needed.

Current

P projects × all aliases

Proposed

Group aliases once → per-project lookup

Focused proof

Assert identical ordering and content, then compare operation counts for representative catalog sizes. The reported elapsed time is a synthetic check, not production latency.

packages/jarvis-core/src/buildProjectVocabulary.ts:14

Low priority · Confirmed source path; peak memory unmeasured

13. Release verification repeatedly buffers whole installers

The Jarvis release verifier hashes files with readFileSync, buffering complete artifacts. Checksum, alias and provenance paths hash some artifacts repeatedly. Large bundled installers make this unnecessary memory and I/O work.

Smaller implementation

Stream hashes and reuse each digest within a verification invocation. Keep artifact correctness checks; avoid adding more provenance/checklist machinery. This is Jarvis packaging work, not an upstream build refactor.

Current

Repeated full-file buffers

Proposed

One streaming digest per artifact

Focused proof

Check equal digests on fixtures and measure peak RSS/read volume on a large synthetic artifact. Do not regenerate release artifacts for a review.

scripts/verify-jarvis-release.mjs:5

Complexity worth keeping

Keep deterministic grounding, typed clarification and confirmation, execution-node identity, ordinary provider adapters, preset capability checks, cancellation ownership and durable task results with ephemeral speech. Those mechanisms protect real behavior. The presence animation already has finite bursts and visibility/reduced-motion controls; it is not a priority for speculative optimization.

What “simpler” means here

One Jarvis module should own each catalog, queue or lifecycle. Thin platform adapters should handle actual differences in audio, navigation and foreground state. Avoid another generic workflow engine, service locator, parallel task database or delivery ledger. A smaller interface should remove state from callers, not hide the same duplicated state behind more files.

Only AGENTS.md was changed in the application repository. Findings are recommendations, not implemented fixes.