agent-working-memory 0.15.7 → 0.15.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -185,6 +185,7 @@ export function buildSetupContext(opts) {
185
185
  hookPort,
186
186
  hookPortRange,
187
187
  installPrime: opts.installPrime ?? true,
188
+ forceInstructions: opts.forceInstructions ?? false,
188
189
  isGlobal: opts.isGlobal,
189
190
  isWindows,
190
191
  envVars,
@@ -289,7 +290,7 @@ export function upsertAwmSection(filePath, newContent, options = {}) {
289
290
  `notes inside it cannot be told apart from generated text and would be lost. ` +
290
291
  `Backup written to ${basename(backup)}. To upgrade: move any notes you want to keep ` +
291
292
  `ABOVE the '## Memory (AWM)' heading (content outside the section is always preserved), ` +
292
- `then re-run with force. Nothing has been changed.`;
293
+ `then re-run with --force. Nothing has been changed.`;
293
294
  }
294
295
  const before = existing.slice(0, startMatch.index).trimEnd();
295
296
  const after = existing.slice(sectionEnd).replace(/^\s*\n/, '');
@@ -299,435 +300,435 @@ export function upsertAwmSection(filePath, newContent, options = {}) {
299
300
  writeFileSync(filePath, rebuilt);
300
301
  return `${fname}: AWM section replaced with a marked generated block (force)`;
301
302
  }
302
- export const AWM_INSTRUCTION_CONTENT = `
303
- ## Memory (AWM) — MANDATORY
304
-
305
- **AWM is THE memory system.** Use it via the \`agent-working-memory\` MCP server
306
- (preferred) or HTTP at \`http://127.0.0.1:8400\` (fallback). The file-based
307
- auto-memory at \`~/.claude/projects/.../memory/*.md\` is a LEGACY bootstrap path —
308
- **do not write new memories to it.** All persistent knowledge goes through AWM.
309
-
310
- If MCP tools aren't loaded at session start, use ToolSearch with
311
- \`select:mcp__agent-working-memory__memory_recall,mcp__agent-working-memory__memory_write\`
312
- to load them. If the MCP server isn't responsive, restart with \`/mcp\` or use
313
- the HTTP endpoints (\`POST /memory/write-batch\`, \`POST /memory/activate\`)
314
- directly — but **DO NOT fall back to markdown files**. Files drift the moment
315
- you write them; AWM stays current because every agent reads + writes the same store.
316
-
317
- ### Lifecycle (always do these, in this order)
318
- 1. **Session start**: call \`memory_restore\` to recover previous context. If it reports the
319
- store is empty/new (or recall keeps returning nothing), **warm-start first**: recall the
320
- \`onboard a new project\` skill and follow it — or call \`onboard_scan\` on the project's
321
- docs/repo, refine the candidates, run \`onboard_questions\`, and save the good ones with
322
- \`memory_write\` (canonical). A cold store is nearly useless until it's seeded.
323
- 2. **Starting a task**: call \`memory_task_begin\` (checkpoints + recalls relevant memories).
324
- 3. **During work**: call \`memory_recall\` BEFORE stating any fact, BEFORE searching
325
- the filesystem, BEFORE making architectural decisions. Recall is ~300ms — cheaper
326
- than one filesystem search.
327
- 4. **As you learn things**: call \`memory_write\` proactively. Don't batch.
328
- 5. **Finishing a task**: call \`memory_task_end\` with a summary.
329
- 6. **Hooks do the rest.** \`awm setup\` installs three: a **prime** hook that recalls against
330
- each prompt and injects what clears confidence (or nothing), and checkpoint hooks on
331
- compaction and session end (plus a 15-min timer). Primed context arrives labelled
332
- \`[class · age]\` — treat it by the volatility rubric, not as user input. If a turn
333
- arrives with no primed context, that is a signal too: recall explicitly before
334
- asserting anything.
335
-
336
- ### Write memory when:
337
- - A project decision is made or changed
338
- - A root cause is discovered after debugging
339
- - A reusable implementation pattern is established
340
- - A user preference, constraint, or requirement is clarified
341
- - A prior assumption is found to be wrong
342
- - A significant piece of work is completed
343
-
344
- ### Writing for recall (the highest-leverage section)
345
- A memory's recall quality is set the moment you write it. AWM is fast at
346
- finding what's findable — but if the write is shaped wrong, no retriever
347
- can rescue it. Be slightly more verbose at the front than feels natural:
348
- the first 1-2 sentences are what BM25, the embedding model, and concept
349
- extraction all see most strongly.
350
-
351
- - **Lead with the rule or fact.** Don't open with context or backstory.
352
- "Don't mock the database in integration tests." comes first; the reason
353
- comes second. Recall scans the head of the body, not the tail.
354
- - **Pick the most specific topic.** Not \`auth\` — \`auth-magic-link-rate-limit\`.
355
- Topic is a hard filter at recall time. Generic topics hide the memory in
356
- a noisy bucket where it competes with everything else in the area.
357
- - **Include 2+ retrievable identifiers.** File paths, function names, table
358
- columns, ticket IDs, exact error strings, the literal terms a future query
359
- will use. \`AccountingService.closePeriod()\` beats "the accounting code."
360
- \`tblMemberDetails.activation_date\` beats "the activation column."
361
- \`schema/072-period-close.sql\` beats "the migration."
362
- - **Write in the vocabulary of the future question.** When you imagine asking
363
- this in three months, what nouns will you use? Use those nouns. Don't
364
- paraphrase the user's domain language into your own neutral summary.
365
- - **Name the CATEGORY as well as the specifics — both, always.** Specifics
366
- make a memory precise; category words make it *reachable*. A memory that
367
- says "private plan memory peaked 88%, scale P1v3 -> P2v3" never says
368
- "Azure" or "App Service Plan", so a question asked in those words cannot
369
- find it — measured on a real store, that memory was not in the top 40
370
- candidates for "azure app service plan capacity increase". Write the
371
- system / product / domain nouns (Azure App Service Plan, Freshdesk ticket,
372
- MySQL connection pool, ShowConnect scoring) NEXT TO the identifiers.
373
- Note this cuts against "pick the most specific topic" above: that rule is
374
- about the \`topic\` TAG, not a licence to omit the category from the body.
375
- Measured on an 11k-engram store: 94% of tagged memories are missing at
376
- least one of their own topical terms from the body, and 66% of those
377
- terms never appear in the text at all.
378
- - **Tags are NOT a substitute for body text.** Only BM25 indexes tags. The
379
- embedding is built from \`concept + content\` and the cross-encoder rerank
380
- passage is built from \`concept + content\` — neither sees tags. So a word
381
- that exists only as a tag is invisible to two of the three retrieval
382
- channels, including the one that decides final ordering. Tag it *and*
383
- write it.
384
- - **Reserve canonical for stable invariants.** Decisions, requirements,
385
- hard facts, cross-agent shared context. Working class (default) is correct
386
- for findings, observations, and progress notes. The canonical floor is
387
- 0.7 salience — overusing it pollutes the canonical layer and the floor
388
- loses meaning.
389
- - **Include the why for feedback memories.** A rule without a reason can't
390
- be applied to edge cases. "Don't mock the database" is brittle. "Don't
391
- mock the database — last quarter mocked tests masked a broken migration"
392
- is portable to new situations.
393
-
394
- ### Tagging rules (REQUIRED — AWM's prefix-tag retrieval boost depends on these)
395
-
396
- Every \`memory_write\` should pass these structured fields. AWM stores each as a
397
- prefix-tag like \`proj=\`, \`topic=\`, \`intent=\`, etc. and uses them for BM25
398
- and entity-bridge boosts at recall time.
399
-
400
- | Field | Required? | Format | Example |
401
- |---|---|---|---|
402
- | \`project\` | **YES** | one short word matching the current project | \`"EquiHub"\`, \`"AWM"\`, \`"USEA-Agent"\` |
403
- | \`topic\` | **YES** | one or more lowercase area words | \`"database-migration"\`, \`"benchmarks"\` |
404
- | \`intent\` | **YES** | one of: \`decision\` / \`finding\` / \`todo\` / \`question\` / \`context\` | \`"finding"\` |
405
- | \`confidence_level\` | **YES** | \`verified\` (tested) / \`observed\` (read in code) / \`assumed\` (reasoning) | \`"verified"\` |
406
- | \`source\` | recommended | \`code-reading\` / \`debugging\` / \`discussion\` / \`research\` / \`testing\` / \`observation\` | \`"testing"\` |
407
- | \`memory_class\` | when stable | \`canonical\` (source-of-truth, 0.7 floor, never staged) / \`working\` (default) / \`ephemeral\` | \`"canonical"\` |
408
- | \`session_id\` | recommended | current conversation ID for entity-bridge boost | autogenerated |
409
- | \`tags\` | when applicable | extra prefix-tags for IDs and dates | \`["ticket=18360", "date=2026-05-11"]\` |
410
-
411
- **Always add identifier tags when present in the content:**
412
- - \`ticket=<id>\` for Freshdesk tickets
413
- - \`member=<id>\` for member IDs
414
- - \`horse=<id>\` for horse_member_id
415
- - \`usef=<id>\` for USEF lookups
416
- - \`date=YYYY-MM-DD\` for temporal anchoring (ISO format)
417
- - \`person=<Name>\` for stakeholder quotes / decisions
418
- - \`version=<X.Y.Z>\` for release-specific findings
419
-
420
- ### Entity index — exact-match recall for named things (default off)
421
- Structured identifier tags (\`ticket=\`, \`person=\`, \`horse=\`, \`member=\`, bare 4+ digit
422
- ids, etc.) feed a dedicated entity inverted index, separate from BM25/embedding scoring.
423
- A query naming an entity ("ticket 19252", "Kaleigh Collett") can reach the memory through
424
- this index even when the wording doesn't lexically match — it's a deterministic exact
425
- lookup, immune to vocabulary mismatch. Keep identifier tags exact and consistent for
426
- this reason, not just for the BM25 boost described above.
427
-
428
- Off by default; opt in with \`AWM_ENTITY_INDEX_FETCH=1\` (bounded by
429
- \`AWM_ENTITY_INDEX_CAP\`, default 12). Matched entities get no score boost — they're
430
- guaranteed a reranker audition instead, so the cross-encoder alone decides whether they
431
- surface. Worth trialing on identifier-heavy workloads (ticket/event numbers, named
432
- people/things you refer to by name often); not yet the default pending evaluation.
433
-
434
- ### Temporal validity — memories that expire or start in the future
435
- \`memory_write\` accepts \`valid_from\` / \`valid_to\` (ISO dates). Use \`valid_to\` on
436
- **operational** facts with a real shelf life — a deploy state, "waiting on X's reply",
437
- a ticket status — so the memory expires instead of relying on you to remember it's
438
- stale. Recall renders \`[valid until …]\` on results carrying this field. Use
439
- \`valid_from\` for a fact that becomes true on a known future date (a policy change, a
440
- season that hasn't started yet). Don't set either for durable facts — most memories
441
- don't need them.
442
-
443
- ### Memory classes (controls how strictly the salience filter gates the write)
444
- - \`memory_class: canonical\` — source-of-truth memories. Floor 0.7 salience, never staged.
445
- Use for: user-stated decisions, project requirements, verified architectural facts,
446
- cross-agent shared context. **In a hive (multi-agent) setup, always use \`canonical\`
447
- for writes that other agents must be able to recall** — the default \`working\` class
448
- may get filtered.
449
- - \`memory_class: working\` (default) — observations and findings. Salience-gated.
450
- - \`memory_class: ephemeral\` — short-lived context that should decay quickly.
451
-
452
- ### Salience auto-promotion (defense in depth)
453
- The salience filter automatically promotes certain content patterns even if you forget
454
- to set \`memory_class\` explicitly:
455
- - **User feedback** — content starting with "Robert said…", "Katherine directed…",
456
- "Nancy decided…" etc. auto-promotes to canonical. So quoting the user verbatim
457
- always preserves the decision.
458
- - **Verified operational records** — content with an action verb (Submitted, Finalized,
459
- Completed, Reconciled, Triaged, Posted, Resolved, Stamped, Pushed, Deployed, Migrated,
460
- Imported, Exported, Backfilled) plus 2+ concrete identifiers (ISO date \`YYYY-MM-DD\`,
461
- or contextual numeric IDs like "event 18969", "ticket #18330", "USEF 341980") gets
462
- a 0.45 salience floor. So batch summaries with real IDs survive even when topic
463
- terms repeat.
464
-
465
- If neither pattern applies and you want a memory to definitely survive, set
466
- \`memory_class: canonical\` explicitly. Don't rely on auto-promotion for important writes.
467
-
468
- ### Recall memory when:
469
- - **BEFORE stating ANY fact about how a system works** — recall first; if AWM doesn't
470
- have it, read the code. Never guess and present it as fact.
471
- - **BEFORE searching the filesystem** — recall first; AWM is faster and has cross-session
472
- knowledge that file search doesn't.
473
- - Starting work on a new task or subsystem
474
- - Re-entering code you haven't touched recently
475
- - After a failed attempt — check if there's prior knowledge
476
- - Before refactoring or making architectural changes
477
- - When a topic comes up that you might have prior context on
478
-
479
- Recall is fast (~300ms typical). Use it freely.
480
-
481
- ### Chain recalls — one hop per call
482
-
483
- AWM returns what matches your query. It does **not** walk from that answer to the next
484
- fact, and it is not meant to: it is active memory, holding what you need right now.
485
- Following a chain to the next thing is **your** job — recall, read, recall again, each
486
- result becoming the cue for the next query.
487
-
488
- So when a question refers to something **by its role instead of its name**, you have a
489
- chain, not a query:
490
-
491
- > *"What is the codename of the project owned by my scheduler?"*
492
-
493
- That is three lookups, not one:
494
-
495
- 1. recall \`who is my scheduler\` → a name
496
- 2. recall \`what project does <that name> own\` → a project
497
- 3. recall \`<that project> codename\` → the answer
498
-
499
- **The failure mode is answering from the first recall.** A single query blending all
500
- three terms returns the most *salient* related memory, not the correct one — measured,
501
- that returns the main project's codename with complete confidence, and it is wrong.
502
- Each hop on its own is an ordinary, reliable recall; the chain only breaks when you stop
503
- asking.
504
-
505
- Tells that you are looking at a chain: a possessive or relative clause naming an entity
506
- by role rather than identity (\`my scheduler\`, \`the owner of X\`, \`whoever signed
507
- off on Y\`), or a rule that operates on an attribute you have not looked up yet (\`the
508
- release tag of the project we discussed\` needs that project's codename first). If
509
- resolving the question requires a fact you would have to *derive*, recall the fact
510
- instead.
511
-
512
- ### Recall strategy (when one query isn't enough)
513
- AWM's adaptive retrieval handles most query variations natively — synonym
514
- expansion, multi-channel scoring, embedding + BM25 + reranker agreement.
515
- A single recall is usually enough.
516
-
517
- When it isn't:
518
- - **If the first recall returns nothing or returns the wrong things, reformulate.**
519
- Try a second query with different phrasing — synonyms, more specific nouns,
520
- the exact identifier from the code rather than the conceptual name. Two or
521
- three recalls cost less than one filesystem search.
522
- - **Use the words a domain expert would use, not generic English.** "Period
523
- close lock" not "accounting feature"; "magic link rate limit" not "auth issue."
524
- - **For broad exploration, pass \`mode: "exploratory"\`** — wider candidate
525
- pool, lower precision floor. For specific lookups, leave mode unset (auto).
526
- - **Don't ensemble more than 3 reformulations.** If three different phrasings
527
- return nothing, the memory probably isn't there — read the code instead of
528
- burning more recalls.
529
-
530
- ### Recall tuning — opt-in parameters
531
- Default \`memory_recall\` is tuned for the common case. Four opt-in parameters change
532
- the cost/quality tradeoff. Use them when the default doesn't match what you need.
533
-
534
- - **\`granularity: 'compact'\`** — every result carries a 200-char \`summary\`
535
- field with a query-aware snippet (the densest window of query terms in the
536
- content). Use this when you expect to scan 5+ results to find one — saves
537
- ~70% of recall output tokens. The full content stays available in
538
- \`engram.content\` if you want to drill into a specific result.
539
- - **\`granularity: 'auto'\`** — confidence-adaptive. If the top result is a clear
540
- winner, it gets a longer summary while the rest are compact. If confidence
541
- is uniform across results, everything is compact. Use when you don't know
542
- in advance whether one result will dominate.
543
- - **\`require_confidence\`** — abstention. The default (0.05) is already a light
544
- gate: when the top results don't stand out from the rest, recall returns
545
- nothing and the reply says **\`RECALL ABSTAINED\`** with the count it withheld.
546
- An empty result *without* that line is genuine absence. The gate is on the
547
- SHAPE of the score distribution, not relevance — so raising it silences
548
- specific questions with one clear winner first (measured: 0.25 abstained on
549
- two identifier queries scoring 0.26–0.38 while passing a vague one at 0.92).
550
- Leave it alone for ordinary recall; \`0.10\` is the ceiling that still helps for
551
- push-style use where nobody asked. When abstention fires, reformulate once
552
- with the exact identifier, then read the code — don't retry with a lower
553
- threshold to force an answer.
554
- - **\`workspace: "<name>"\`** — hive-mode recall across all agents in the
555
- workspace. Use when other agents may have written canonical knowledge you
556
- need. Default is agent-scoped (your own memories only). Can also be set
557
- globally via the \`AWM_WORKSPACE\` env var. Memories live in the agent pool
558
- they were written to; if a session lands in an unexpected pool, \`memory_whoami\`
559
- says which one before you conclude the memory is missing.
560
-
561
- ### Keep memory fresh
562
- - After recalling a memory, if you observe the real state is different → call
563
- \`memory_supersede\` immediately with the corrected version.
564
- - After using a recalled memory: call \`memory_feedback\` (useful/not-useful) **with the
565
- \`recall_id\`** printed at the end of the recall output (\`[recall_id: …]\`). That id
566
- joins the feedback to the recall that produced it, which is what lets AWM learn
567
- which recalls were worth their tokens; feedback without it is a bare vote.
568
- - If you discover a memory is factually wrong: \`memory_retract\` to remove it.
569
- - **If you bypass AWM (file-memory, in-context notes, "I'll just remember"), the memory
570
- drifts out of date. The system relies on you to keep it current. This is the #1
571
- failure mode.**
572
-
573
- ### Cognition recipes — YOU do the thinking, AWM keeps the result
574
- AWM contains no LLM. When memory needs real thinking — distilling a repeatable
575
- procedure, reflecting on a failure — AWM hands YOU a versioned recipe (prompt +
576
- strict output shape) and you run it as a SEPARATE focused pass, then write the
577
- result back as an ordinary memory with provenance.
578
-
579
- - \`memory_task_end\` responses include the recipe invitations. Honor the gates:
580
- skill-derivation only after a genuinely procedural task (3+ tool calls or a
581
- delegated sub-task); friction-lesson only after a failure/retry/wrong assumption.
582
- - Run each recipe as its own focused pass — do NOT bundle it with other
583
- reasoning; bundled passes reliably drop the output.
584
- - Write back exactly per the recipe's contract: \`origin_class: 'recipe'\` +
585
- \`recipe_id\` (e.g. \`skill-derivation@1\`), concept prefixed \`skill: \` or
586
- \`lesson: \`. AWM validates the shape and rejects malformed or unknown-recipe
587
- writes with the contract echoed back — fix and retry, don't drop the insight.
588
- - Re-deriving the same skill name reinforces the existing memory instead of
589
- duplicating it, so don't fear writing a skill you may have written before.
590
-
591
- ### Content fade — write-and-forget is safe
592
- Un-recalled engrams gradually fade their content while preserving cue pathways
593
- (concept + tags + embedding stay intact). This is Paper 1 — storage
594
- degradation. Practical implications:
595
-
596
- - **Don't manually purge memories** to "save space." The system already
597
- compresses unused content. Old memories stay findable via cue match even
598
- when their body has decayed.
599
- - **Don't over-pin with \`memory_class: canonical\`** to fight fade. Canonical
600
- only changes salience gating at write time, not fade behavior. Fade
601
- affects un-recalled engrams of any class.
602
- - **Recall keeps content alive.** Every recall touches the engram and resets
603
- its fade clock. Frequently-recalled memories stay full-fidelity automatically.
604
- - **Supersede is the right tool for stale facts.** When you observe a memory
605
- is outdated, call \`memory_supersede\` — the new version inherits the old
606
- one's coherent associations (counter-narrative replacement) so cue
607
- pathways carry forward to the replacement.
608
-
609
- ### Example — good vs bad memory_write
610
-
611
- **BAD** (no prefix tags, vague concept, can't be recalled by future queries):
612
- \`\`\`
613
- memory_write(
614
- concept="found a bug",
615
- content="The thing I was looking at was broken so I fixed it."
616
- )
617
- \`\`\`
618
-
619
- **GOOD** (rich identifiers, structured metadata, prefix tags):
620
- \`\`\`
621
- memory_write(
622
- concept="EquiHub period-close BLOCKED check missing server-side",
623
- content="apps/web/app/(accounting)/accounting/period-close/page.tsx had client-only BLOCKED enforcement. Fixed by adding server-side check in AccountingService.closePeriod() per schema/072-period-close.sql. Without server-side check a malicious request could bypass via direct API call.",
624
- project="EquiHub",
625
- topic="accounting",
626
- intent="finding",
627
- confidence_level="verified",
628
- source="debugging",
629
- memory_class="canonical",
630
- tags=["ticket=18360", "person=Robert", "date=2026-05-11", "topic=period-close", "topic=security"]
631
- )
632
- \`\`\`
633
-
634
- ### Also:
635
- - To track work items: memory_task_add, memory_task_update, memory_task_list, memory_task_next
636
- - \`memory_whoami\` (MCP tool) / \`GET /whoami\` — identify the instance you're actually
637
- talking to: agent id, workspace, mode, backend, store path, code provenance, sibling
638
- agent spaces sharing the store. Call this FIRST whenever you're unsure which store,
639
- which agent identity, or which running code you're dealing with — before reasoning
640
- about AWM's own state from a stale memory or an assumed port number.
641
- - AWM is shared across all agents in real time. When any agent writes or supersedes a
642
- memory, every other agent can recall it immediately — but only within the same
643
- workspace and agent scope.
644
-
645
- ### Output compression (token efficiency, output-only)
646
- When a tool returns a LARGE STRUCTURED result you need to keep in context — a JSON
647
- array of records, query rows, a log dump, an API response — pass it through
648
- \`compress_output\` first. It re-encodes the data as TOON (a compact, lossless,
649
- schema-aware tabular form of JSON), cutting ~50-65% of the tokens at no
650
- comprehension cost. This is output-only: it never changes the data or your memories.
651
- - Use it on big STRUCTURED outputs, not on prose. Prose is returned unchanged —
652
- for trimming memory prose, use recall \`granularity: 'compact'\` instead.
653
- - It returns a \`ref\`; call \`retrieve_original(ref)\` if you later need the exact
654
- verbatim source (e.g. to hand it to another tool unchanged).
655
- - Don't bother for small outputs — it only compresses when the saving is worthwhile
656
- and falls back to plain JSON if TOON wouldn't reproduce the data exactly.
657
-
658
- ### Backend (SQLite vs PGlite)
659
- AWM ships two storage backends. The installer picks SQLite by default; both
660
- are functionally equivalent for cognitive workloads, but differ in operational
661
- guarantees:
662
-
663
- - **SQLite** (default) — embedded, **multi-process safe** via WAL mode. Best
664
- for single-machine setups and MCP scenarios where multiple Claude Code
665
- sessions may open the same database concurrently.
666
- - **PGlite** — embedded Postgres (WASM) with pgvector. **Single-process only**
667
- — two MCP processes against the same \`memory-pglite/\` directory will
668
- abort the second. Pick via \`AWM_STORE_BACKEND=pglite\` and
669
- \`AWM_DB_PATH=path/to/memory-pglite\`.
670
- - **Auto-detect** — if \`AWM_DB_PATH\` points to a directory that already
671
- exists, AWM detects PGlite; a file → SQLite. No explicit
672
- \`AWM_STORE_BACKEND\` needed when an existing DB is present.
673
-
674
- For the comparison table (recall quality parity, BM25 vs \`ts_rank_cd\`,
675
- multi-process guarantees), see \`docs/pglite-feature-parity.md\`.
676
-
677
- ### Diagnostics / escape hatches (env vars, only if you know why)
678
- Each optimisation is gated by an env var so it can be disabled for A/B testing if a
679
- regression appears in your workload. \`memory_whoami\` prints the active fingerprint.
680
-
681
- Retrieval (set ON by \`awm setup\` since 0.14.6 — the measured-good configuration):
682
- - \`AWM_RERANK2=1\` — second-stage rerank by the cross-encoder's own score.
683
- - \`AWM_RERANK_WINDOW=query\` — 400-char rerank window on the densest query-term
684
- region instead of the prefix (25% → 87.5% on long memories).
685
- - \`AWM_RERANK_TAGS=1\` — tags fed into the rerank passage (+7.4pp s@1).
686
-
687
- Hook sidecar (0.14.2):
688
- - \`AWM_HOOK_PORT=8401\` / \`AWM_HOOK_PORT_RANGE=10\` — each MCP process binds the
689
- first free port in the range, so several sessions can run at once. The shipped
690
- hooks find their own session's sidecar by probing the range and matching
691
- \`agentId\` on \`/health\`; \`memory_whoami\` reports the port actually bound.
692
-
693
- Recall pipeline:
694
- - \`AWM_DISABLE_POOL_FILTER=1\` — disables the candidate pool reduction
695
- pre-filter in recall. Reverts to scoring all active candidates.
696
- - \`AWM_ENTITY_INDEX_FETCH=1\` — see "Entity index" above (default off; measured
697
- no effect on the real-store benchmark, 0.14.5).
698
- - \`AWM_DISABLE_SLIM_CACHE=1\` — disables the in-memory slim cache.
699
- Reverts to per-recall SQL fetch + Buffer→Float32Array conversion.
700
- - \`AWM_DISABLE_RERANK_SKIP=1\` — disables the cross-encoder skip on
701
- clear-winner queries. Forces every recall through the reranker.
702
- - \`AWM_DISABLE_EXPANSION_CACHE=1\` — disables the query expansion skip
703
- heuristic + LRU cache. Forces every recall through flan-t5-small.
704
-
705
- Write pipeline + lifecycle:
706
- - \`AWM_SLOW_WRITE_MS=250\` — any write slower than this logs one stderr
707
- line with a phase-time breakdown (embed/novelty/persist, event-loop lag,
708
- embed-model cold-load ms). \`0\` disables. Useful for diagnosing why a session's
709
- first write/recall feels slow.
710
- - \`AWM_REINFORCE_MAX_CONTENT_LEN=1500\` — max chars an engram's content
711
- can grow to via merge-on-reinforce (drop-oldest on overflow). Higher =
712
- preserves more reinforced detail; lower = leaner recall output.
713
- - \`AWM_REINFORCE_MERGE_CONTENT=0\` — disable content merge on reinforce.
714
- Reverts to pre-0.8.5 behavior (discard new content, only bump confidence).
715
- - \`AWM_NOVELTY_EMBED=0\` — disable the cosine channel in novelty
716
- computation. BM25-only fallback. Reverts to pre-0.8.5 novelty.
717
- - \`AWM_GRANULARITY_COMPACT_LEN=200\` — char budget for query-aware snippet
718
- in \`granularity: 'compact'\` mode.
719
- - \`AWM_GRANULARITY_FULL_LEN=1000\` — char budget for the top result in
720
- \`granularity: 'auto'\` mode when there's a clear winner.
721
-
722
- PGlite backend:
723
- - \`AWM_PGLITE_BM25_M=1\` — multiplier on PGlite \`ts_rank_cd\` to calibrate
724
- against SQLite FTS5 BM25 distribution. M=1 (default) is passthrough;
725
- higher M boosts PGlite scores at the cost of recall-ranking precision
726
- (see CHANGELOG 0.8.5 follow-up).
727
- - \`AWM_IVFFLAT_PROBES=5\` — pgvector ivfflat probes per query. Higher =
728
- more accurate, slower.
729
-
730
- In production, leave these all unset. Use only when diagnosing a suspected
731
- recall-quality regression.
303
+ export const AWM_INSTRUCTION_CONTENT = `
304
+ ## Memory (AWM) — MANDATORY
305
+
306
+ **AWM is THE memory system.** Use it via the \`agent-working-memory\` MCP server
307
+ (preferred) or HTTP at \`http://127.0.0.1:8400\` (fallback). The file-based
308
+ auto-memory at \`~/.claude/projects/.../memory/*.md\` is a LEGACY bootstrap path —
309
+ **do not write new memories to it.** All persistent knowledge goes through AWM.
310
+
311
+ If MCP tools aren't loaded at session start, use ToolSearch with
312
+ \`select:mcp__agent-working-memory__memory_recall,mcp__agent-working-memory__memory_write\`
313
+ to load them. If the MCP server isn't responsive, restart with \`/mcp\` or use
314
+ the HTTP endpoints (\`POST /memory/write-batch\`, \`POST /memory/activate\`)
315
+ directly — but **DO NOT fall back to markdown files**. Files drift the moment
316
+ you write them; AWM stays current because every agent reads + writes the same store.
317
+
318
+ ### Lifecycle (always do these, in this order)
319
+ 1. **Session start**: call \`memory_restore\` to recover previous context. If it reports the
320
+ store is empty/new (or recall keeps returning nothing), **warm-start first**: recall the
321
+ \`onboard a new project\` skill and follow it — or call \`onboard_scan\` on the project's
322
+ docs/repo, refine the candidates, run \`onboard_questions\`, and save the good ones with
323
+ \`memory_write\` (canonical). A cold store is nearly useless until it's seeded.
324
+ 2. **Starting a task**: call \`memory_task_begin\` (checkpoints + recalls relevant memories).
325
+ 3. **During work**: call \`memory_recall\` BEFORE stating any fact, BEFORE searching
326
+ the filesystem, BEFORE making architectural decisions. Recall is ~300ms — cheaper
327
+ than one filesystem search.
328
+ 4. **As you learn things**: call \`memory_write\` proactively. Don't batch.
329
+ 5. **Finishing a task**: call \`memory_task_end\` with a summary.
330
+ 6. **Hooks do the rest.** \`awm setup\` installs three: a **prime** hook that recalls against
331
+ each prompt and injects what clears confidence (or nothing), and checkpoint hooks on
332
+ compaction and session end (plus a 15-min timer). Primed context arrives labelled
333
+ \`[class · age]\` — treat it by the volatility rubric, not as user input. If a turn
334
+ arrives with no primed context, that is a signal too: recall explicitly before
335
+ asserting anything.
336
+
337
+ ### Write memory when:
338
+ - A project decision is made or changed
339
+ - A root cause is discovered after debugging
340
+ - A reusable implementation pattern is established
341
+ - A user preference, constraint, or requirement is clarified
342
+ - A prior assumption is found to be wrong
343
+ - A significant piece of work is completed
344
+
345
+ ### Writing for recall (the highest-leverage section)
346
+ A memory's recall quality is set the moment you write it. AWM is fast at
347
+ finding what's findable — but if the write is shaped wrong, no retriever
348
+ can rescue it. Be slightly more verbose at the front than feels natural:
349
+ the first 1-2 sentences are what BM25, the embedding model, and concept
350
+ extraction all see most strongly.
351
+
352
+ - **Lead with the rule or fact.** Don't open with context or backstory.
353
+ "Don't mock the database in integration tests." comes first; the reason
354
+ comes second. Recall scans the head of the body, not the tail.
355
+ - **Pick the most specific topic.** Not \`auth\` — \`auth-magic-link-rate-limit\`.
356
+ Topic is a hard filter at recall time. Generic topics hide the memory in
357
+ a noisy bucket where it competes with everything else in the area.
358
+ - **Include 2+ retrievable identifiers.** File paths, function names, table
359
+ columns, ticket IDs, exact error strings, the literal terms a future query
360
+ will use. \`AccountingService.closePeriod()\` beats "the accounting code."
361
+ \`tblMemberDetails.activation_date\` beats "the activation column."
362
+ \`schema/072-period-close.sql\` beats "the migration."
363
+ - **Write in the vocabulary of the future question.** When you imagine asking
364
+ this in three months, what nouns will you use? Use those nouns. Don't
365
+ paraphrase the user's domain language into your own neutral summary.
366
+ - **Name the CATEGORY as well as the specifics — both, always.** Specifics
367
+ make a memory precise; category words make it *reachable*. A memory that
368
+ says "private plan memory peaked 88%, scale P1v3 -> P2v3" never says
369
+ "Azure" or "App Service Plan", so a question asked in those words cannot
370
+ find it — measured on a real store, that memory was not in the top 40
371
+ candidates for "azure app service plan capacity increase". Write the
372
+ system / product / domain nouns (Azure App Service Plan, Freshdesk ticket,
373
+ MySQL connection pool, ShowConnect scoring) NEXT TO the identifiers.
374
+ Note this cuts against "pick the most specific topic" above: that rule is
375
+ about the \`topic\` TAG, not a licence to omit the category from the body.
376
+ Measured on an 11k-engram store: 94% of tagged memories are missing at
377
+ least one of their own topical terms from the body, and 66% of those
378
+ terms never appear in the text at all.
379
+ - **Tags are NOT a substitute for body text.** Only BM25 indexes tags. The
380
+ embedding is built from \`concept + content\` and the cross-encoder rerank
381
+ passage is built from \`concept + content\` — neither sees tags. So a word
382
+ that exists only as a tag is invisible to two of the three retrieval
383
+ channels, including the one that decides final ordering. Tag it *and*
384
+ write it.
385
+ - **Reserve canonical for stable invariants.** Decisions, requirements,
386
+ hard facts, cross-agent shared context. Working class (default) is correct
387
+ for findings, observations, and progress notes. The canonical floor is
388
+ 0.7 salience — overusing it pollutes the canonical layer and the floor
389
+ loses meaning.
390
+ - **Include the why for feedback memories.** A rule without a reason can't
391
+ be applied to edge cases. "Don't mock the database" is brittle. "Don't
392
+ mock the database — last quarter mocked tests masked a broken migration"
393
+ is portable to new situations.
394
+
395
+ ### Tagging rules (REQUIRED — AWM's prefix-tag retrieval boost depends on these)
396
+
397
+ Every \`memory_write\` should pass these structured fields. AWM stores each as a
398
+ prefix-tag like \`proj=\`, \`topic=\`, \`intent=\`, etc. and uses them for BM25
399
+ and entity-bridge boosts at recall time.
400
+
401
+ | Field | Required? | Format | Example |
402
+ |---|---|---|---|
403
+ | \`project\` | **YES** | one short word matching the current project | \`"EquiHub"\`, \`"AWM"\`, \`"USEA-Agent"\` |
404
+ | \`topic\` | **YES** | one or more lowercase area words | \`"database-migration"\`, \`"benchmarks"\` |
405
+ | \`intent\` | **YES** | one of: \`decision\` / \`finding\` / \`todo\` / \`question\` / \`context\` | \`"finding"\` |
406
+ | \`confidence_level\` | **YES** | \`verified\` (tested) / \`observed\` (read in code) / \`assumed\` (reasoning) | \`"verified"\` |
407
+ | \`source\` | recommended | \`code-reading\` / \`debugging\` / \`discussion\` / \`research\` / \`testing\` / \`observation\` | \`"testing"\` |
408
+ | \`memory_class\` | when stable | \`canonical\` (source-of-truth, 0.7 floor, never staged) / \`working\` (default) / \`ephemeral\` | \`"canonical"\` |
409
+ | \`session_id\` | recommended | current conversation ID for entity-bridge boost | autogenerated |
410
+ | \`tags\` | when applicable | extra prefix-tags for IDs and dates | \`["ticket=18360", "date=2026-05-11"]\` |
411
+
412
+ **Always add identifier tags when present in the content:**
413
+ - \`ticket=<id>\` for Freshdesk tickets
414
+ - \`member=<id>\` for member IDs
415
+ - \`horse=<id>\` for horse_member_id
416
+ - \`usef=<id>\` for USEF lookups
417
+ - \`date=YYYY-MM-DD\` for temporal anchoring (ISO format)
418
+ - \`person=<Name>\` for stakeholder quotes / decisions
419
+ - \`version=<X.Y.Z>\` for release-specific findings
420
+
421
+ ### Entity index — exact-match recall for named things (default off)
422
+ Structured identifier tags (\`ticket=\`, \`person=\`, \`horse=\`, \`member=\`, bare 4+ digit
423
+ ids, etc.) feed a dedicated entity inverted index, separate from BM25/embedding scoring.
424
+ A query naming an entity ("ticket 19252", "Kaleigh Collett") can reach the memory through
425
+ this index even when the wording doesn't lexically match — it's a deterministic exact
426
+ lookup, immune to vocabulary mismatch. Keep identifier tags exact and consistent for
427
+ this reason, not just for the BM25 boost described above.
428
+
429
+ Off by default; opt in with \`AWM_ENTITY_INDEX_FETCH=1\` (bounded by
430
+ \`AWM_ENTITY_INDEX_CAP\`, default 12). Matched entities get no score boost — they're
431
+ guaranteed a reranker audition instead, so the cross-encoder alone decides whether they
432
+ surface. Worth trialing on identifier-heavy workloads (ticket/event numbers, named
433
+ people/things you refer to by name often); not yet the default pending evaluation.
434
+
435
+ ### Temporal validity — memories that expire or start in the future
436
+ \`memory_write\` accepts \`valid_from\` / \`valid_to\` (ISO dates). Use \`valid_to\` on
437
+ **operational** facts with a real shelf life — a deploy state, "waiting on X's reply",
438
+ a ticket status — so the memory expires instead of relying on you to remember it's
439
+ stale. Recall renders \`[valid until …]\` on results carrying this field. Use
440
+ \`valid_from\` for a fact that becomes true on a known future date (a policy change, a
441
+ season that hasn't started yet). Don't set either for durable facts — most memories
442
+ don't need them.
443
+
444
+ ### Memory classes (controls how strictly the salience filter gates the write)
445
+ - \`memory_class: canonical\` — source-of-truth memories. Floor 0.7 salience, never staged.
446
+ Use for: user-stated decisions, project requirements, verified architectural facts,
447
+ cross-agent shared context. **In a hive (multi-agent) setup, always use \`canonical\`
448
+ for writes that other agents must be able to recall** — the default \`working\` class
449
+ may get filtered.
450
+ - \`memory_class: working\` (default) — observations and findings. Salience-gated.
451
+ - \`memory_class: ephemeral\` — short-lived context that should decay quickly.
452
+
453
+ ### Salience auto-promotion (defense in depth)
454
+ The salience filter automatically promotes certain content patterns even if you forget
455
+ to set \`memory_class\` explicitly:
456
+ - **User feedback** — content starting with "Robert said…", "Katherine directed…",
457
+ "Nancy decided…" etc. auto-promotes to canonical. So quoting the user verbatim
458
+ always preserves the decision.
459
+ - **Verified operational records** — content with an action verb (Submitted, Finalized,
460
+ Completed, Reconciled, Triaged, Posted, Resolved, Stamped, Pushed, Deployed, Migrated,
461
+ Imported, Exported, Backfilled) plus 2+ concrete identifiers (ISO date \`YYYY-MM-DD\`,
462
+ or contextual numeric IDs like "event 18969", "ticket #18330", "USEF 341980") gets
463
+ a 0.45 salience floor. So batch summaries with real IDs survive even when topic
464
+ terms repeat.
465
+
466
+ If neither pattern applies and you want a memory to definitely survive, set
467
+ \`memory_class: canonical\` explicitly. Don't rely on auto-promotion for important writes.
468
+
469
+ ### Recall memory when:
470
+ - **BEFORE stating ANY fact about how a system works** — recall first; if AWM doesn't
471
+ have it, read the code. Never guess and present it as fact.
472
+ - **BEFORE searching the filesystem** — recall first; AWM is faster and has cross-session
473
+ knowledge that file search doesn't.
474
+ - Starting work on a new task or subsystem
475
+ - Re-entering code you haven't touched recently
476
+ - After a failed attempt — check if there's prior knowledge
477
+ - Before refactoring or making architectural changes
478
+ - When a topic comes up that you might have prior context on
479
+
480
+ Recall is fast (~300ms typical). Use it freely.
481
+
482
+ ### Chain recalls — one hop per call
483
+
484
+ AWM returns what matches your query. It does **not** walk from that answer to the next
485
+ fact, and it is not meant to: it is active memory, holding what you need right now.
486
+ Following a chain to the next thing is **your** job — recall, read, recall again, each
487
+ result becoming the cue for the next query.
488
+
489
+ So when a question refers to something **by its role instead of its name**, you have a
490
+ chain, not a query:
491
+
492
+ > *"What is the codename of the project owned by my scheduler?"*
493
+
494
+ That is three lookups, not one:
495
+
496
+ 1. recall \`who is my scheduler\` → a name
497
+ 2. recall \`what project does <that name> own\` → a project
498
+ 3. recall \`<that project> codename\` → the answer
499
+
500
+ **The failure mode is answering from the first recall.** A single query blending all
501
+ three terms returns the most *salient* related memory, not the correct one — measured,
502
+ that returns the main project's codename with complete confidence, and it is wrong.
503
+ Each hop on its own is an ordinary, reliable recall; the chain only breaks when you stop
504
+ asking.
505
+
506
+ Tells that you are looking at a chain: a possessive or relative clause naming an entity
507
+ by role rather than identity (\`my scheduler\`, \`the owner of X\`, \`whoever signed
508
+ off on Y\`), or a rule that operates on an attribute you have not looked up yet (\`the
509
+ release tag of the project we discussed\` needs that project's codename first). If
510
+ resolving the question requires a fact you would have to *derive*, recall the fact
511
+ instead.
512
+
513
+ ### Recall strategy (when one query isn't enough)
514
+ AWM's adaptive retrieval handles most query variations natively — synonym
515
+ expansion, multi-channel scoring, embedding + BM25 + reranker agreement.
516
+ A single recall is usually enough.
517
+
518
+ When it isn't:
519
+ - **If the first recall returns nothing or returns the wrong things, reformulate.**
520
+ Try a second query with different phrasing — synonyms, more specific nouns,
521
+ the exact identifier from the code rather than the conceptual name. Two or
522
+ three recalls cost less than one filesystem search.
523
+ - **Use the words a domain expert would use, not generic English.** "Period
524
+ close lock" not "accounting feature"; "magic link rate limit" not "auth issue."
525
+ - **For broad exploration, pass \`mode: "exploratory"\`** — wider candidate
526
+ pool, lower precision floor. For specific lookups, leave mode unset (auto).
527
+ - **Don't ensemble more than 3 reformulations.** If three different phrasings
528
+ return nothing, the memory probably isn't there — read the code instead of
529
+ burning more recalls.
530
+
531
+ ### Recall tuning — opt-in parameters
532
+ Default \`memory_recall\` is tuned for the common case. Four opt-in parameters change
533
+ the cost/quality tradeoff. Use them when the default doesn't match what you need.
534
+
535
+ - **\`granularity: 'compact'\`** — every result carries a 200-char \`summary\`
536
+ field with a query-aware snippet (the densest window of query terms in the
537
+ content). Use this when you expect to scan 5+ results to find one — saves
538
+ ~70% of recall output tokens. The full content stays available in
539
+ \`engram.content\` if you want to drill into a specific result.
540
+ - **\`granularity: 'auto'\`** — confidence-adaptive. If the top result is a clear
541
+ winner, it gets a longer summary while the rest are compact. If confidence
542
+ is uniform across results, everything is compact. Use when you don't know
543
+ in advance whether one result will dominate.
544
+ - **\`require_confidence\`** — abstention. The default (0.05) is already a light
545
+ gate: when the top results don't stand out from the rest, recall returns
546
+ nothing and the reply says **\`RECALL ABSTAINED\`** with the count it withheld.
547
+ An empty result *without* that line is genuine absence. The gate is on the
548
+ SHAPE of the score distribution, not relevance — so raising it silences
549
+ specific questions with one clear winner first (measured: 0.25 abstained on
550
+ two identifier queries scoring 0.26–0.38 while passing a vague one at 0.92).
551
+ Leave it alone for ordinary recall; \`0.10\` is the ceiling that still helps for
552
+ push-style use where nobody asked. When abstention fires, reformulate once
553
+ with the exact identifier, then read the code — don't retry with a lower
554
+ threshold to force an answer.
555
+ - **\`workspace: "<name>"\`** — hive-mode recall across all agents in the
556
+ workspace. Use when other agents may have written canonical knowledge you
557
+ need. Default is agent-scoped (your own memories only). Can also be set
558
+ globally via the \`AWM_WORKSPACE\` env var. Memories live in the agent pool
559
+ they were written to; if a session lands in an unexpected pool, \`memory_whoami\`
560
+ says which one before you conclude the memory is missing.
561
+
562
+ ### Keep memory fresh
563
+ - After recalling a memory, if you observe the real state is different → call
564
+ \`memory_supersede\` immediately with the corrected version.
565
+ - After using a recalled memory: call \`memory_feedback\` (useful/not-useful) **with the
566
+ \`recall_id\`** printed at the end of the recall output (\`[recall_id: …]\`). That id
567
+ joins the feedback to the recall that produced it, which is what lets AWM learn
568
+ which recalls were worth their tokens; feedback without it is a bare vote.
569
+ - If you discover a memory is factually wrong: \`memory_retract\` to remove it.
570
+ - **If you bypass AWM (file-memory, in-context notes, "I'll just remember"), the memory
571
+ drifts out of date. The system relies on you to keep it current. This is the #1
572
+ failure mode.**
573
+
574
+ ### Cognition recipes — YOU do the thinking, AWM keeps the result
575
+ AWM contains no LLM. When memory needs real thinking — distilling a repeatable
576
+ procedure, reflecting on a failure — AWM hands YOU a versioned recipe (prompt +
577
+ strict output shape) and you run it as a SEPARATE focused pass, then write the
578
+ result back as an ordinary memory with provenance.
579
+
580
+ - \`memory_task_end\` responses include the recipe invitations. Honor the gates:
581
+ skill-derivation only after a genuinely procedural task (3+ tool calls or a
582
+ delegated sub-task); friction-lesson only after a failure/retry/wrong assumption.
583
+ - Run each recipe as its own focused pass — do NOT bundle it with other
584
+ reasoning; bundled passes reliably drop the output.
585
+ - Write back exactly per the recipe's contract: \`origin_class: 'recipe'\` +
586
+ \`recipe_id\` (e.g. \`skill-derivation@1\`), concept prefixed \`skill: \` or
587
+ \`lesson: \`. AWM validates the shape and rejects malformed or unknown-recipe
588
+ writes with the contract echoed back — fix and retry, don't drop the insight.
589
+ - Re-deriving the same skill name reinforces the existing memory instead of
590
+ duplicating it, so don't fear writing a skill you may have written before.
591
+
592
+ ### Content fade — write-and-forget is safe
593
+ Un-recalled engrams gradually fade their content while preserving cue pathways
594
+ (concept + tags + embedding stay intact). This is Paper 1 — storage
595
+ degradation. Practical implications:
596
+
597
+ - **Don't manually purge memories** to "save space." The system already
598
+ compresses unused content. Old memories stay findable via cue match even
599
+ when their body has decayed.
600
+ - **Don't over-pin with \`memory_class: canonical\`** to fight fade. Canonical
601
+ only changes salience gating at write time, not fade behavior. Fade
602
+ affects un-recalled engrams of any class.
603
+ - **Recall keeps content alive.** Every recall touches the engram and resets
604
+ its fade clock. Frequently-recalled memories stay full-fidelity automatically.
605
+ - **Supersede is the right tool for stale facts.** When you observe a memory
606
+ is outdated, call \`memory_supersede\` — the new version inherits the old
607
+ one's coherent associations (counter-narrative replacement) so cue
608
+ pathways carry forward to the replacement.
609
+
610
+ ### Example — good vs bad memory_write
611
+
612
+ **BAD** (no prefix tags, vague concept, can't be recalled by future queries):
613
+ \`\`\`
614
+ memory_write(
615
+ concept="found a bug",
616
+ content="The thing I was looking at was broken so I fixed it."
617
+ )
618
+ \`\`\`
619
+
620
+ **GOOD** (rich identifiers, structured metadata, prefix tags):
621
+ \`\`\`
622
+ memory_write(
623
+ concept="EquiHub period-close BLOCKED check missing server-side",
624
+ content="apps/web/app/(accounting)/accounting/period-close/page.tsx had client-only BLOCKED enforcement. Fixed by adding server-side check in AccountingService.closePeriod() per schema/072-period-close.sql. Without server-side check a malicious request could bypass via direct API call.",
625
+ project="EquiHub",
626
+ topic="accounting",
627
+ intent="finding",
628
+ confidence_level="verified",
629
+ source="debugging",
630
+ memory_class="canonical",
631
+ tags=["ticket=18360", "person=Robert", "date=2026-05-11", "topic=period-close", "topic=security"]
632
+ )
633
+ \`\`\`
634
+
635
+ ### Also:
636
+ - To track work items: memory_task_add, memory_task_update, memory_task_list, memory_task_next
637
+ - \`memory_whoami\` (MCP tool) / \`GET /whoami\` — identify the instance you're actually
638
+ talking to: agent id, workspace, mode, backend, store path, code provenance, sibling
639
+ agent spaces sharing the store. Call this FIRST whenever you're unsure which store,
640
+ which agent identity, or which running code you're dealing with — before reasoning
641
+ about AWM's own state from a stale memory or an assumed port number.
642
+ - AWM is shared across all agents in real time. When any agent writes or supersedes a
643
+ memory, every other agent can recall it immediately — but only within the same
644
+ workspace and agent scope.
645
+
646
+ ### Output compression (token efficiency, output-only)
647
+ When a tool returns a LARGE STRUCTURED result you need to keep in context — a JSON
648
+ array of records, query rows, a log dump, an API response — pass it through
649
+ \`compress_output\` first. It re-encodes the data as TOON (a compact, lossless,
650
+ schema-aware tabular form of JSON), cutting ~50-65% of the tokens at no
651
+ comprehension cost. This is output-only: it never changes the data or your memories.
652
+ - Use it on big STRUCTURED outputs, not on prose. Prose is returned unchanged —
653
+ for trimming memory prose, use recall \`granularity: 'compact'\` instead.
654
+ - It returns a \`ref\`; call \`retrieve_original(ref)\` if you later need the exact
655
+ verbatim source (e.g. to hand it to another tool unchanged).
656
+ - Don't bother for small outputs — it only compresses when the saving is worthwhile
657
+ and falls back to plain JSON if TOON wouldn't reproduce the data exactly.
658
+
659
+ ### Backend (SQLite vs PGlite)
660
+ AWM ships two storage backends. The installer picks SQLite by default; both
661
+ are functionally equivalent for cognitive workloads, but differ in operational
662
+ guarantees:
663
+
664
+ - **SQLite** (default) — embedded, **multi-process safe** via WAL mode. Best
665
+ for single-machine setups and MCP scenarios where multiple Claude Code
666
+ sessions may open the same database concurrently.
667
+ - **PGlite** — embedded Postgres (WASM) with pgvector. **Single-process only**
668
+ — two MCP processes against the same \`memory-pglite/\` directory will
669
+ abort the second. Pick via \`AWM_STORE_BACKEND=pglite\` and
670
+ \`AWM_DB_PATH=path/to/memory-pglite\`.
671
+ - **Auto-detect** — if \`AWM_DB_PATH\` points to a directory that already
672
+ exists, AWM detects PGlite; a file → SQLite. No explicit
673
+ \`AWM_STORE_BACKEND\` needed when an existing DB is present.
674
+
675
+ For the comparison table (recall quality parity, BM25 vs \`ts_rank_cd\`,
676
+ multi-process guarantees), see \`docs/pglite-feature-parity.md\`.
677
+
678
+ ### Diagnostics / escape hatches (env vars, only if you know why)
679
+ Each optimisation is gated by an env var so it can be disabled for A/B testing if a
680
+ regression appears in your workload. \`memory_whoami\` prints the active fingerprint.
681
+
682
+ Retrieval (set ON by \`awm setup\` since 0.14.6 — the measured-good configuration):
683
+ - \`AWM_RERANK2=1\` — second-stage rerank by the cross-encoder's own score.
684
+ - \`AWM_RERANK_WINDOW=query\` — 400-char rerank window on the densest query-term
685
+ region instead of the prefix (25% → 87.5% on long memories).
686
+ - \`AWM_RERANK_TAGS=1\` — tags fed into the rerank passage (+7.4pp s@1).
687
+
688
+ Hook sidecar (0.14.2):
689
+ - \`AWM_HOOK_PORT=8401\` / \`AWM_HOOK_PORT_RANGE=10\` — each MCP process binds the
690
+ first free port in the range, so several sessions can run at once. The shipped
691
+ hooks find their own session's sidecar by probing the range and matching
692
+ \`agentId\` on \`/health\`; \`memory_whoami\` reports the port actually bound.
693
+
694
+ Recall pipeline:
695
+ - \`AWM_DISABLE_POOL_FILTER=1\` — disables the candidate pool reduction
696
+ pre-filter in recall. Reverts to scoring all active candidates.
697
+ - \`AWM_ENTITY_INDEX_FETCH=1\` — see "Entity index" above (default off; measured
698
+ no effect on the real-store benchmark, 0.14.5).
699
+ - \`AWM_DISABLE_SLIM_CACHE=1\` — disables the in-memory slim cache.
700
+ Reverts to per-recall SQL fetch + Buffer→Float32Array conversion.
701
+ - \`AWM_DISABLE_RERANK_SKIP=1\` — disables the cross-encoder skip on
702
+ clear-winner queries. Forces every recall through the reranker.
703
+ - \`AWM_DISABLE_EXPANSION_CACHE=1\` — disables the query expansion skip
704
+ heuristic + LRU cache. Forces every recall through flan-t5-small.
705
+
706
+ Write pipeline + lifecycle:
707
+ - \`AWM_SLOW_WRITE_MS=250\` — any write slower than this logs one stderr
708
+ line with a phase-time breakdown (embed/novelty/persist, event-loop lag,
709
+ embed-model cold-load ms). \`0\` disables. Useful for diagnosing why a session's
710
+ first write/recall feels slow.
711
+ - \`AWM_REINFORCE_MAX_CONTENT_LEN=1500\` — max chars an engram's content
712
+ can grow to via merge-on-reinforce (drop-oldest on overflow). Higher =
713
+ preserves more reinforced detail; lower = leaner recall output.
714
+ - \`AWM_REINFORCE_MERGE_CONTENT=0\` — disable content merge on reinforce.
715
+ Reverts to pre-0.8.5 behavior (discard new content, only bump confidence).
716
+ - \`AWM_NOVELTY_EMBED=0\` — disable the cosine channel in novelty
717
+ computation. BM25-only fallback. Reverts to pre-0.8.5 novelty.
718
+ - \`AWM_GRANULARITY_COMPACT_LEN=200\` — char budget for query-aware snippet
719
+ in \`granularity: 'compact'\` mode.
720
+ - \`AWM_GRANULARITY_FULL_LEN=1000\` — char budget for the top result in
721
+ \`granularity: 'auto'\` mode when there's a clear winner.
722
+
723
+ PGlite backend:
724
+ - \`AWM_PGLITE_BM25_M=1\` — multiplier on PGlite \`ts_rank_cd\` to calibrate
725
+ against SQLite FTS5 BM25 distribution. M=1 (default) is passthrough;
726
+ higher M boosts PGlite scores at the cost of recall-ranking precision
727
+ (see CHANGELOG 0.8.5 follow-up).
728
+ - \`AWM_IVFFLAT_PROBES=5\` — pgvector ivfflat probes per query. Higher =
729
+ more accurate, slower.
730
+
731
+ In production, leave these all unset. Use only when diagnosing a suspected
732
+ recall-quality regression.
732
733
  `.trimStart();
733
734
  //# sourceMappingURL=common.js.map