agent-working-memory 0.11.0 → 0.12.3

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.
Files changed (115) hide show
  1. package/README.md +71 -297
  2. package/dist/adapters/claude-code.d.ts.map +1 -1
  3. package/dist/adapters/claude-code.js +63 -3
  4. package/dist/adapters/claude-code.js.map +1 -1
  5. package/dist/adapters/common.d.ts.map +1 -1
  6. package/dist/adapters/common.js +358 -306
  7. package/dist/adapters/common.js.map +1 -1
  8. package/dist/api/routes.d.ts.map +1 -1
  9. package/dist/api/routes.js +29 -7
  10. package/dist/api/routes.js.map +1 -1
  11. package/dist/coordination/routes.d.ts.map +1 -1
  12. package/dist/coordination/routes.js +174 -170
  13. package/dist/coordination/routes.js.map +1 -1
  14. package/dist/core/embeddings.d.ts.map +1 -1
  15. package/dist/core/embeddings.js +4 -1
  16. package/dist/core/embeddings.js.map +1 -1
  17. package/dist/core/entity-extract.d.ts +3 -0
  18. package/dist/core/entity-extract.d.ts.map +1 -0
  19. package/dist/core/entity-extract.js +47 -0
  20. package/dist/core/entity-extract.js.map +1 -0
  21. package/dist/core/format-recall.d.ts +16 -0
  22. package/dist/core/format-recall.d.ts.map +1 -0
  23. package/dist/core/format-recall.js +24 -0
  24. package/dist/core/format-recall.js.map +1 -0
  25. package/dist/core/query-expander.js +1 -1
  26. package/dist/core/query-expander.js.map +1 -1
  27. package/dist/core/reranker.js +1 -1
  28. package/dist/core/reranker.js.map +1 -1
  29. package/dist/core/salience.d.ts.map +1 -1
  30. package/dist/core/salience.js +14 -2
  31. package/dist/core/salience.js.map +1 -1
  32. package/dist/core/whoami.d.ts +24 -0
  33. package/dist/core/whoami.d.ts.map +1 -0
  34. package/dist/core/whoami.js +66 -0
  35. package/dist/core/whoami.js.map +1 -0
  36. package/dist/core/write-pipeline.d.ts +9 -0
  37. package/dist/core/write-pipeline.d.ts.map +1 -1
  38. package/dist/core/write-pipeline.js +109 -68
  39. package/dist/core/write-pipeline.js.map +1 -1
  40. package/dist/core/write-telemetry.d.ts +33 -0
  41. package/dist/core/write-telemetry.d.ts.map +1 -0
  42. package/dist/core/write-telemetry.js +110 -0
  43. package/dist/core/write-telemetry.js.map +1 -0
  44. package/dist/engine/activation.d.ts +22 -12
  45. package/dist/engine/activation.d.ts.map +1 -1
  46. package/dist/engine/activation.js +133 -17
  47. package/dist/engine/activation.js.map +1 -1
  48. package/dist/engine/consolidation-scheduler.d.ts +1 -1
  49. package/dist/engine/consolidation-scheduler.js +1 -1
  50. package/dist/engine/consolidation.d.ts +1 -0
  51. package/dist/engine/consolidation.d.ts.map +1 -1
  52. package/dist/engine/consolidation.js +18 -0
  53. package/dist/engine/consolidation.js.map +1 -1
  54. package/dist/engine/eval.d.ts.map +1 -1
  55. package/dist/engine/eval.js +5 -1
  56. package/dist/engine/eval.js.map +1 -1
  57. package/dist/hooks/sidecar.d.ts +26 -0
  58. package/dist/hooks/sidecar.d.ts.map +1 -1
  59. package/dist/hooks/sidecar.js +30 -0
  60. package/dist/hooks/sidecar.js.map +1 -1
  61. package/dist/index.js +20 -2
  62. package/dist/index.js.map +1 -1
  63. package/dist/mcp.d.ts +2 -1
  64. package/dist/mcp.d.ts.map +1 -1
  65. package/dist/mcp.js +222 -108
  66. package/dist/mcp.js.map +1 -1
  67. package/dist/recipes/index.d.ts +57 -0
  68. package/dist/recipes/index.d.ts.map +1 -0
  69. package/dist/recipes/index.js +81 -0
  70. package/dist/recipes/index.js.map +1 -0
  71. package/dist/storage/pglite-schema.d.ts.map +1 -1
  72. package/dist/storage/pglite-schema.js +27 -0
  73. package/dist/storage/pglite-schema.js.map +1 -1
  74. package/dist/storage/pglite.d.ts +5 -0
  75. package/dist/storage/pglite.d.ts.map +1 -1
  76. package/dist/storage/pglite.js +180 -138
  77. package/dist/storage/pglite.js.map +1 -1
  78. package/dist/storage/postgres.d.ts +5 -0
  79. package/dist/storage/postgres.d.ts.map +1 -1
  80. package/dist/storage/postgres.js +180 -138
  81. package/dist/storage/postgres.js.map +1 -1
  82. package/dist/storage/sqlite.d.ts +9 -0
  83. package/dist/storage/sqlite.d.ts.map +1 -1
  84. package/dist/storage/sqlite.js +394 -326
  85. package/dist/storage/sqlite.js.map +1 -1
  86. package/dist/types/engram.d.ts +14 -0
  87. package/dist/types/engram.d.ts.map +1 -1
  88. package/dist/types/engram.js.map +1 -1
  89. package/package.json +1 -1
  90. package/src/adapters/claude-code.ts +66 -3
  91. package/src/adapters/common.ts +567 -515
  92. package/src/api/routes.ts +999 -971
  93. package/src/coordination/routes.ts +2155 -2150
  94. package/src/core/embeddings.ts +4 -1
  95. package/src/core/entity-extract.ts +47 -0
  96. package/src/core/format-recall.ts +25 -0
  97. package/src/core/query-expander.ts +1 -1
  98. package/src/core/reranker.ts +1 -1
  99. package/src/core/salience.ts +529 -514
  100. package/src/core/whoami.ts +92 -0
  101. package/src/core/write-pipeline.ts +60 -8
  102. package/src/core/write-telemetry.ts +131 -0
  103. package/src/engine/activation.ts +1468 -1369
  104. package/src/engine/consolidation-scheduler.ts +1 -1
  105. package/src/engine/consolidation.ts +887 -869
  106. package/src/engine/eval.ts +6 -1
  107. package/src/hooks/sidecar.ts +55 -0
  108. package/src/index.ts +248 -227
  109. package/src/mcp.ts +1387 -1270
  110. package/src/recipes/index.ts +125 -0
  111. package/src/storage/pglite-schema.ts +27 -0
  112. package/src/storage/pglite.ts +1420 -1372
  113. package/src/storage/postgres.ts +1523 -1475
  114. package/src/storage/sqlite.ts +1936 -1861
  115. package/src/types/engram.ts +22 -0
@@ -0,0 +1,110 @@
1
+ // Copyright 2026 Robert Winter / Complete Ideas
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ /**
4
+ * Write-path telemetry (D1, 2026-07-30).
5
+ *
6
+ * Purpose: prove the mechanism behind slow writes before building the
7
+ * serialized write service. Captures, per write:
8
+ * - phase wall times (embed / novelty / persist)
9
+ * - event-loop lag at write completion (was this process's loop blocked?)
10
+ * - whether a consolidation cycle was running IN THIS PROCESS
11
+ * - whether SQLITE_BUSY was hit
12
+ * - embed-model cold-load duration (first inference)
13
+ *
14
+ * Always-on slow-write warning: any write slower than AWM_SLOW_WRITE_MS
15
+ * (default 250ms; set 0 to disable) emits ONE structured stderr line.
16
+ * AWM_PROFILE_WRITE=1 continues to log every write as before.
17
+ *
18
+ * Design notes: additive module — no existing export changes (MWA vendors
19
+ * dist internals; nothing here alters existing paths). All timers are
20
+ * unref'd so they never hold the process open.
21
+ */
22
+ const SLOW_WRITE_MS = (() => {
23
+ const v = Number(process.env.AWM_SLOW_WRITE_MS ?? '250');
24
+ return Number.isFinite(v) ? v : 250;
25
+ })();
26
+ // ---------- Event-loop lag monitor ----------
27
+ const TICK_MS = 500;
28
+ let lastTick = 0;
29
+ let maxLagSinceRead = 0;
30
+ let monitorStarted = false;
31
+ /** Start the loop-lag heartbeat. Idempotent; call once at process boot. */
32
+ export function startLoopLagMonitor() {
33
+ if (monitorStarted)
34
+ return;
35
+ monitorStarted = true;
36
+ lastTick = performance.now();
37
+ const t = setInterval(() => {
38
+ const now = performance.now();
39
+ const lag = now - lastTick - TICK_MS;
40
+ if (lag > maxLagSinceRead)
41
+ maxLagSinceRead = lag;
42
+ lastTick = now;
43
+ }, TICK_MS);
44
+ if (typeof t.unref === 'function')
45
+ t.unref();
46
+ }
47
+ /**
48
+ * Max observed loop lag (ms beyond the expected tick) since the last read.
49
+ * Reading resets the max. A large value means this process's event loop was
50
+ * blocked (in-process ML, consolidation, sync SQL) during the window.
51
+ */
52
+ export function readMaxLoopLag() {
53
+ const v = maxLagSinceRead;
54
+ maxLagSinceRead = 0;
55
+ return Math.max(0, Math.round(v));
56
+ }
57
+ // ---------- In-process consolidation state ----------
58
+ let consolidationActive = false;
59
+ let consolidationAgent = null;
60
+ let consolidationStartedAt = 0;
61
+ export function setConsolidationActive(active, agentId) {
62
+ consolidationActive = active;
63
+ consolidationAgent = active ? (agentId ?? null) : null;
64
+ consolidationStartedAt = active ? performance.now() : 0;
65
+ }
66
+ export function getConsolidationState() {
67
+ return {
68
+ active: consolidationActive,
69
+ agentId: consolidationAgent,
70
+ runningMs: consolidationActive ? Math.round(performance.now() - consolidationStartedAt) : 0,
71
+ };
72
+ }
73
+ // ---------- Model cold-load record ----------
74
+ let modelColdLoadMs = null;
75
+ export function noteModelLoad(ms) {
76
+ if (modelColdLoadMs === null) {
77
+ modelColdLoadMs = Math.round(ms);
78
+ process.stderr.write(`[awm] embed model cold load: ${modelColdLoadMs}ms\n`);
79
+ }
80
+ }
81
+ export function getModelColdLoadMs() {
82
+ return modelColdLoadMs;
83
+ }
84
+ /**
85
+ * Report a completed write. Emits one structured stderr line when the write
86
+ * exceeded the slow threshold (always-on) — including loop lag and in-process
87
+ * consolidation state, the two signals that distinguish "DB lock wait" from
88
+ * "my own event loop was blocked".
89
+ */
90
+ export function reportWrite(t) {
91
+ if (SLOW_WRITE_MS <= 0)
92
+ return;
93
+ if (t.totalMs < SLOW_WRITE_MS)
94
+ return;
95
+ const consol = getConsolidationState();
96
+ const parts = [
97
+ `[awm] SLOW WRITE ${Math.round(t.totalMs)}ms`,
98
+ `agent=${t.agentId}`,
99
+ `action=${t.action}`,
100
+ `embed=${Math.round(t.embedMs)}ms`,
101
+ `novelty=${Math.round(t.noveltyMs)}ms`,
102
+ `persist=${Math.round(t.persistMs)}ms`,
103
+ `loopLagMax=${readMaxLoopLag()}ms`,
104
+ `consolidating=${consol.active ? `yes(${consol.agentId ?? '?'},${consol.runningMs}ms)` : 'no'}`,
105
+ `busy=${t.busyHit ? 'yes' : 'no'}`,
106
+ modelColdLoadMs !== null ? `modelColdLoad=${modelColdLoadMs}ms` : 'modelColdLoad=none',
107
+ ];
108
+ process.stderr.write(parts.join(' ') + '\n');
109
+ }
110
+ //# sourceMappingURL=write-telemetry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write-telemetry.js","sourceRoot":"","sources":["../../src/core/write-telemetry.ts"],"names":[],"mappings":"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"}
@@ -1,18 +1,28 @@
1
1
  /**
2
2
  * Activation Pipeline — the core retrieval engine.
3
3
  *
4
- * 10-phase cognitive retrieval pipeline:
5
- * 0. Query expansion (flan-t5-small synonym generation)
6
- * 1. Vector embedding (MiniLM 384d)
7
- * 2. Parallel retrieval (FTS5/BM25 + vector pool)
8
- * 3. Scoring (BM25, Jaccard, z-score vector, entity-bridge boost)
9
- * 4. Rocchio pseudo-relevance feedback (expand + re-search BM25)
10
- * 5. ACT-R temporal decay
11
- * 6. Hebbian boost (co-activation strength)
12
- * 7. Composite scoring with confidence gating
13
- * 8. Beam search graph walk (depth 2, hop penalty)
14
- * 9. Cross-encoder reranking (ms-marco-MiniLM, adaptive blend)
15
- * 10. Abstention gate
4
+ * Cognitive retrieval pipeline — phases as shipped (D4 honesty pass 2026-07-30;
5
+ * default-OFF phases are marked, since operators tune from this header):
6
+ * -1. Coreference expansion (conditional: query contains pronouns)
7
+ * 0. Query expansion (flan-t5-small; caller-gated, MCP default ON)
8
+ * 1. Vector embedding (bge-small 384d)
9
+ * 2. Parallel retrieval (dual FTS5/BM25 + native vector top-K)
10
+ * 3. Per-candidate scoring (BM25, Jaccard, cosine floor, ACT-R decay,
11
+ * Hebbian boost, confidence gate — computed together in phase 3b)
12
+ * 3.5 Rocchio pseudo-relevance feedback (conditional on BM25 signal)
13
+ * 3.7 Entity-bridge boost (default ON; AWM_DISABLE_ENTITY_BRIDGE=1)
14
+ * 3.5 Entity-index candidate injection (DEFAULT OFF; AWM_ENTITY_INDEX_FETCH=1 —
15
+ * D11 2026-07-30: D9 inverted-index lookup of query-named entities; injected
16
+ * candidates get no boost but a guaranteed rerank audition)
17
+ * 3.75 Query-conditioned entity bridge (DEFAULT OFF; AWM_QUERY_BRIDGE=1)
18
+ * 4/5 Spreading-activation graph walk (DEFAULT OFF; AWM_SPREAD=1 — parked
19
+ * after displacing-gold regressions; see design-proposals D11)
20
+ * 6. Filter + sort into rerank pool (wide pool since 0.9.0)
21
+ * 7. Cross-encoder rerank (ms-marco; clear-winner skip unless
22
+ * AWM_DISABLE_RERANK_SKIP=1)
23
+ * 8. Multi-channel OOD detection + agreement gate; supersession penalty;
24
+ * abstention enforced only when caller passes require_confidence
25
+ * 9. Final sort, granularity, confidence attach
16
26
  *
17
27
  * Logs activation events for eval metrics.
18
28
  */
@@ -1 +1 @@
1
- {"version":3,"file":"activation.d.ts","sourceRoot":"","sources":["../../src/engine/activation.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;GAiBG;AAIH,OAAO,EAA6C,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAKtG,OAAO,KAAK,EACF,gBAAgB,EAAE,eAAe,EAC1C,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,YAAY,IAAI,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAoIvE,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,kBAAkB,CAAqB;IAC/C,QAAQ,CAAC,cAAc,EAAE,qBAAqB,CAAC;gBAEnC,KAAK,EAAE,WAAW;IAM9B;;OAEG;IACG,QAAQ,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAg2BnE;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAKnC;YAEY,SAAS;IA+FvB;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;YACW,gBAAgB;IA4I9B;;;;OAIG;IACG,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAwBhF,OAAO,CAAC,OAAO;CAchB"}
1
+ {"version":3,"file":"activation.d.ts","sourceRoot":"","sources":["../../src/engine/activation.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAIH,OAAO,EAA6C,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAKtG,OAAO,KAAK,EACF,gBAAgB,EAAE,eAAe,EAC1C,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,YAAY,IAAI,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAoIvE,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,kBAAkB,CAAqB;IAC/C,QAAQ,CAAC,cAAc,EAAE,qBAAqB,CAAC;gBAEnC,KAAK,EAAE,WAAW;IAM9B;;OAEG;IACG,QAAQ,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IA66BnE;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAKnC;YAEY,SAAS;IA+FvB;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;YACW,gBAAgB;IAwJ9B;;;;OAIG;IACG,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAwBhF,OAAO,CAAC,OAAO;CAchB"}
@@ -3,18 +3,28 @@
3
3
  /**
4
4
  * Activation Pipeline — the core retrieval engine.
5
5
  *
6
- * 10-phase cognitive retrieval pipeline:
7
- * 0. Query expansion (flan-t5-small synonym generation)
8
- * 1. Vector embedding (MiniLM 384d)
9
- * 2. Parallel retrieval (FTS5/BM25 + vector pool)
10
- * 3. Scoring (BM25, Jaccard, z-score vector, entity-bridge boost)
11
- * 4. Rocchio pseudo-relevance feedback (expand + re-search BM25)
12
- * 5. ACT-R temporal decay
13
- * 6. Hebbian boost (co-activation strength)
14
- * 7. Composite scoring with confidence gating
15
- * 8. Beam search graph walk (depth 2, hop penalty)
16
- * 9. Cross-encoder reranking (ms-marco-MiniLM, adaptive blend)
17
- * 10. Abstention gate
6
+ * Cognitive retrieval pipeline — phases as shipped (D4 honesty pass 2026-07-30;
7
+ * default-OFF phases are marked, since operators tune from this header):
8
+ * -1. Coreference expansion (conditional: query contains pronouns)
9
+ * 0. Query expansion (flan-t5-small; caller-gated, MCP default ON)
10
+ * 1. Vector embedding (bge-small 384d)
11
+ * 2. Parallel retrieval (dual FTS5/BM25 + native vector top-K)
12
+ * 3. Per-candidate scoring (BM25, Jaccard, cosine floor, ACT-R decay,
13
+ * Hebbian boost, confidence gate — computed together in phase 3b)
14
+ * 3.5 Rocchio pseudo-relevance feedback (conditional on BM25 signal)
15
+ * 3.7 Entity-bridge boost (default ON; AWM_DISABLE_ENTITY_BRIDGE=1)
16
+ * 3.5 Entity-index candidate injection (DEFAULT OFF; AWM_ENTITY_INDEX_FETCH=1 —
17
+ * D11 2026-07-30: D9 inverted-index lookup of query-named entities; injected
18
+ * candidates get no boost but a guaranteed rerank audition)
19
+ * 3.75 Query-conditioned entity bridge (DEFAULT OFF; AWM_QUERY_BRIDGE=1)
20
+ * 4/5 Spreading-activation graph walk (DEFAULT OFF; AWM_SPREAD=1 — parked
21
+ * after displacing-gold regressions; see design-proposals D11)
22
+ * 6. Filter + sort into rerank pool (wide pool since 0.9.0)
23
+ * 7. Cross-encoder rerank (ms-marco; clear-winner skip unless
24
+ * AWM_DISABLE_RERANK_SKIP=1)
25
+ * 8. Multi-channel OOD detection + agreement gate; supersession penalty;
26
+ * abstention enforced only when caller passes require_confidence
27
+ * 9. Final sort, granularity, confidence attach
18
28
  *
19
29
  * Logs activation events for eval metrics.
20
30
  */
@@ -255,7 +265,12 @@ export class ActivationEngine {
255
265
  // its slim cache + JS cosine (same as before but encapsulated). Z-score
256
266
  // normalization is replaced with a mode-adaptive raw-cosine floor —
257
267
  // simpler, faster, model-tuned for BGE-small embeddings.
258
- const VECTOR_TOP_K = Math.max(50, limit * 5);
268
+ // D4 (2026-07-30): AWM_DISABLE_POOL_FILTER=1 was documented since 0.7.x but
269
+ // never implemented after the 0.8.x native-vector refactor absorbed the
270
+ // pool pre-filter. Honor its documented semantics: score ALL active
271
+ // candidates (no top-K cut, no similarity floor).
272
+ const POOL_FILTER_DISABLED = process.env.AWM_DISABLE_POOL_FILTER === '1';
273
+ const VECTOR_TOP_K = POOL_FILTER_DISABLED ? Number.MAX_SAFE_INTEGER : Math.max(50, limit * 5);
259
274
  // Tokenize query once (used by scoring)
260
275
  const queryTokens = tokenize(query.context);
261
276
  // Phase 3a: native vector search across agents — top-K by cosine.
@@ -271,9 +286,9 @@ export class ActivationEngine {
271
286
  // entirely. The vectorMatch scoring floor (0.50 targeted / 0.35 exploratory)
272
287
  // still suppresses low-confidence matches in the final score.
273
288
  // Env override: AWM_SIM_CANDIDATE_FLOOR_TARGETED, AWM_SIM_CANDIDATE_FLOOR_EXPLORATORY.
274
- const SIM_CANDIDATE_FLOOR = adaptive.zScoreGate > 0.5
289
+ const SIM_CANDIDATE_FLOOR = POOL_FILTER_DISABLED ? -1 : (adaptive.zScoreGate > 0.5
275
290
  ? Number(process.env.AWM_SIM_CANDIDATE_FLOOR_TARGETED ?? 0.40)
276
- : Number(process.env.AWM_SIM_CANDIDATE_FLOOR_EXPLORATORY ?? 0.30);
291
+ : Number(process.env.AWM_SIM_CANDIDATE_FLOOR_EXPLORATORY ?? 0.30));
277
292
  const rawCosineSims = new Map();
278
293
  const vectorHits = [];
279
294
  if (queryEmbedding) {
@@ -376,6 +391,75 @@ export class ActivationEngine {
376
391
  catch { /* best-effort: entity fetch never breaks recall */ }
377
392
  }
378
393
  }
394
+ // ── D11 (2026-07-30): ENTITY-INDEX CANDIDATE INJECTION (default-OFF, AWM_ENTITY_INDEX_FETCH=1) ──
395
+ // The D9 inverted index resolves query-NAMED entities ("Seetha", "ticket 18999") to every
396
+ // engram indexed under them — deterministic exact lookup, immune to embedding/BM25 vocabulary
397
+ // mismatch. Injected candidates get NO score boost; instead they are GUARANTEED a rerank
398
+ // audition (exempt from the topN cut, the minScore pool filter, the rerank-pool slice, and
399
+ // the rerank-skip heuristic) and the cross-encoder alone decides whether they surface.
400
+ // This is the guarded successor to AWM_ENTITY_FETCH above, whose failure mode was measured:
401
+ // injected gold entered the pool but was cut before the reranker ever scored it. Bounded
402
+ // (AWM_ENTITY_INDEX_CAP, default 12) so the audition costs at most one extra rerank batch.
403
+ const injectedIds = new Set();
404
+ if (process.env.AWM_ENTITY_INDEX_FETCH === '1') {
405
+ try {
406
+ const IDX_CAP = Number(process.env.AWM_ENTITY_INDEX_CAP ?? 12);
407
+ const IDX_QSTOP = new Set(['what', 'who', 'when', 'where', 'why', 'how', 'which', 'whose',
408
+ 'the', 'this', 'that', 'and', 'but', 'for', 'did', 'does', 'is', 'are', 'was', 'were',
409
+ 'tell', 'about', 'they', 'them', 'write', 'reply', 'list', 'please', 'remember', 'confirm']);
410
+ const terms = new Set();
411
+ for (const m of query.context.matchAll(/\b[A-Z][A-Za-z]{2,}\b/g)) {
412
+ const w = m[0].toLowerCase();
413
+ if (!IDX_QSTOP.has(w))
414
+ terms.add(w);
415
+ }
416
+ for (const m of query.context.matchAll(/\b\d{4,}\b/g))
417
+ terms.add(m[0]); // bare ids: tickets, members, events
418
+ let added = 0;
419
+ for (const term of Array.from(terms).slice(0, 4)) {
420
+ if (added >= IDX_CAP)
421
+ break;
422
+ const entities = await this.store.searchEntities(term, 6);
423
+ for (const entity of entities) {
424
+ if (added >= IDX_CAP)
425
+ break;
426
+ for (const agentId of agentIds) {
427
+ if (added >= IDX_CAP)
428
+ break;
429
+ for (const id of await this.store.getEngramIdsByEntity(entity, agentId)) {
430
+ if (added >= IDX_CAP)
431
+ break;
432
+ if (injectedIds.has(id))
433
+ continue;
434
+ // Already a candidate via BM25/vector? Still VOUCH for it: a weak in-pool
435
+ // candidate the index confirms would otherwise die at the minScore/topN
436
+ // cuts unguarded. The audition guarantee is about the index match, not
437
+ // about how the candidate entered the pool.
438
+ const inPool = candidateMap.get(id);
439
+ if (inPool) {
440
+ if (inPool.stage === 'active' && !inPool.retracted && !inPool.supersededBy) {
441
+ injectedIds.add(id);
442
+ added++;
443
+ }
444
+ continue;
445
+ }
446
+ const n = await this.store.getEngram(id);
447
+ if (!n || n.stage !== 'active' || n.retracted || n.supersededBy)
448
+ continue;
449
+ if (query.memoryType && n.memoryType !== query.memoryType)
450
+ continue;
451
+ candidateMap.set(id, n);
452
+ injectedIds.add(id);
453
+ added++;
454
+ }
455
+ }
456
+ }
457
+ }
458
+ if (added > 0)
459
+ candidates = Array.from(candidateMap.values());
460
+ }
461
+ catch { /* index injection never breaks recall */ }
462
+ }
379
463
  if (candidates.length === 0)
380
464
  return [];
381
465
  // Phase 3b: Score each candidate with per-phase breakdown
@@ -692,6 +776,14 @@ export class ActivationEngine {
692
776
  // Tunable via AWM_TOPN_MULT.
693
777
  const topNMult = Number(process.env.AWM_TOPN_MULT ?? 8);
694
778
  const topN = sorted.slice(0, limit * topNMult);
779
+ // D11 guard 1/4: injected entity-index candidates ride into the graph/rerank stages even
780
+ // when their (boost-free) composite fell below the topN cut.
781
+ if (injectedIds.size > 0) {
782
+ for (const item of sorted.slice(limit * topNMult)) {
783
+ if (injectedIds.has(item.engram.id))
784
+ topN.push(item);
785
+ }
786
+ }
695
787
  if (process.env.AWM_SPREAD === '1' && query.spread !== false) {
696
788
  await this.spreadActivation(topN);
697
789
  }
@@ -699,8 +791,9 @@ export class ActivationEngine {
699
791
  await this.graphWalk(topN, 2, adaptive.hopPenalty, adaptive.beamWidth);
700
792
  }
701
793
  // Phase 6: Initial filter and sort for re-ranking pool
794
+ // (D11 guard 2/4: injected entity-index candidates are exempt from the minScore floor.)
702
795
  const pool = topN
703
- .filter(r => r.score >= minScore)
796
+ .filter(r => r.score >= minScore || injectedIds.has(r.engram.id))
704
797
  .sort((a, b) => b.score - a.score);
705
798
  // Phase 7: Cross-encoder re-ranking — scores (query, passage) pairs directly
706
799
  // Widens the pool to find relevant results that keyword matching missed.
@@ -713,6 +806,13 @@ export class ActivationEngine {
713
806
  // the reranker does discrimination on a wide pool. Tunable via AWM_RERANK_POOL.
714
807
  const rerankPoolSize = Number(process.env.AWM_RERANK_POOL ?? Math.max(limit * 4, 40));
715
808
  const rerankPool = pool.slice(0, rerankPoolSize);
809
+ // D11 guard 3/4: injected entity-index candidates always reach the cross-encoder.
810
+ if (injectedIds.size > 0) {
811
+ for (const item of pool.slice(rerankPoolSize)) {
812
+ if (injectedIds.has(item.engram.id))
813
+ rerankPool.push(item);
814
+ }
815
+ }
716
816
  // Reranker skip heuristic (0.7.10+): if BM25 already has a clear winner with
717
817
  // strong absolute score AND a meaningful gap to the runner-up, the cross-encoder
718
818
  // is unlikely to change the top result. Skipping saves ~300ms of wall-clock per
@@ -726,7 +826,9 @@ export class ActivationEngine {
726
826
  // Ambiguous queries (close BM25 scores, weak top-1, large pool) still go through
727
827
  // the reranker. Disable this heuristic via AWM_DISABLE_RERANK_SKIP=1.
728
828
  let rerankSkipped = false;
729
- if (useReranker && rerankPool.length >= 2 && process.env.AWM_DISABLE_RERANK_SKIP !== '1') {
829
+ // (D11 guard 4/4: never skip the reranker when entity-index candidates were injected —
830
+ // the audition IS the rerank; skipping would return them unjudged or drop them.)
831
+ if (useReranker && rerankPool.length >= 2 && injectedIds.size === 0 && process.env.AWM_DISABLE_RERANK_SKIP !== '1') {
730
832
  const top1 = rerankPool[0];
731
833
  const top2 = rerankPool[1];
732
834
  const t1Text = top1.phaseScores.textMatch;
@@ -1186,6 +1288,20 @@ export class ActivationEngine {
1186
1288
  inflow.set(v, (inflow.get(v) ?? 0) + au * share);
1187
1289
  }
1188
1290
  }
1291
+ // D11: SYNAPSE-style lateral inhibition (divisive normalization) — competing
1292
+ // receivers suppress each other WITHIN an iteration: a node keeps its inflow in
1293
+ // proportion to how much of the iteration's total it earned, so a few strongly-
1294
+ // reached nodes stay strong while diffuse spread mass is crushed. This is the
1295
+ // published fix for the displacing-gold regression that parked AWM_SPREAD.
1296
+ // λ=0 (default) disables; enable for the re-test with AWM_SPREAD_INHIBIT=0.3.
1297
+ const INHIBIT = Number(process.env.AWM_SPREAD_INHIBIT ?? 0);
1298
+ if (INHIBIT > 0 && inflow.size > 1) {
1299
+ let total = 0;
1300
+ for (const f of inflow.values())
1301
+ total += f;
1302
+ for (const [v, f] of inflow)
1303
+ inflow.set(v, f * (f / (f + INHIBIT * (total - f))));
1304
+ }
1189
1305
  for (const [v, f] of inflow)
1190
1306
  graphActivation.set(v, (graphActivation.get(v) ?? 0) + f);
1191
1307
  // Restart (PPR): blend propagated inflow with the original seed vector.