EA2 enforces one-defines-presentation-per-node — only the first
memory could ever attach because every subsequent
create_edge(role=presentation) from the vault returned 500
[ERR 1650]. Use role=memory for ongoing memories. listAll filter
accepts both for back-compat with the single existing
presentation edge.
- buildScenarios: drop the /api/runtime/transactions/{id} headline GET
entirely. Synthesize the RuntimeTransaction shape from the work-item
data. Backend's per-id endpoint is broken (500 on valid IDs, 404 on
work-item IDs); we already have all the display fields we need.
- store.ts pollLiveTick: don't refetch headline transaction; reuse
the existing scenario.raw.headlineRt synthesized at build time.
- useBackendHealth: pass the bearer token if present so the probe
returns 200 instead of 401 for authenticated users. The probe still
treats 401 as 'up' for unauthenticated landing page.
- agentMemory.remember: track ensureVault result. Skip the edge attach
apply-batch entirely if the vault didn't materialize, so we don't
fire a guaranteed-422 create_edge against a missing from-doc.
Three sources of red errors in scene walk:
1. Mission/Approvals: GET /api/runtime/transactions/{key} 404 storm.
The runtime backend's single-transaction endpoint is broken
(returns 500 'transaction_read_failed: All connection attempts
failed' even on valid IDs from the list endpoint, and 404 for
work-item IDs that don't exist in the runtime DB at all).
Fix in buildScenarios.ts: keep the headlineTx fetch (still tries
to enrich) but synthesize a RuntimeTransaction shape from
work-item data via workItemToRt() when the API call returns null.
Skip the 3x 'recent' GETs entirely — they were always 404ing.
Fix in store.ts pollLiveTick: .catch(() => null) on the headline
transaction call so polling never surfaces backend brokenness.
2. Assistant: POST /api/ea2/apply-batch 422/404 when remembering.
Vault edge attach can race with vault creation OR target a doc
that hasn't propagated. Wrap in try/catch with console.warn so
the failure is visible in logs but doesn't fire as a red console
error on every turn.
Trace showed every Assistant submit triggered 60+ sequential
GET /api/ea2/flow/{key} requests via agentMemory.recall before
llmClient.chat ran. With a slow EA2 demo, recall took longer
than the test wait so the LLM fetch never started, the agent
reply never rendered, and [llm] telemetry never logged.
Two fixes:
1. agentMemory.listAll(cap) - default 200, recall uses 30.
Edges are returned newest-first by EA2 so the 30-cap keeps the
most recent vault entries and drops the long-tail history that
was pinning the network.
2. routeAgentInput wraps recall in a 2s AbortController. If recall
doesn't finish in 2s, hints[] stays empty and llmFallback runs
immediately. Recall is best-effort context, never a blocker.
User explicit ask: 'maybe with a miniature hindsight or a Karpathy
vault behind it as its memory system for each tenant.'
- src/lib/agentMemory.ts: EA2-backed vault per user. Vault root is
flow.kind=value at flow/memory_vault_<email_slug>; each memory is a
flow.kind=value doc linked via defines edge with role=presentation.
- agentMemory.remember/listAll/recall — recall is a simple keyword
overlap score with recency tiebreak.
- agentTools: new 'remember' and 'recall' tools.
matchers: 'remember that ...', 'note ...', 'save ...' /
'recall ...', 'remind me ...', 'what do you know about ...'
- routeAgentInput: every user turn is best-effort persisted as an
episodic memory (fire-and-forget). When no command matches, the
router does a vault recall and surfaces related notes before
showing the help message.
Vault key: deterministic per-user. Owner_email stored on the vault
root + on each memory's config.memory. No raw IDs visible to the user.