@remnic/core 9.3.739 → 9.3.740

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 (185) hide show
  1. package/dist/access-boundary.js +13 -13
  2. package/dist/access-cli.js +35 -35
  3. package/dist/access-http.js +18 -18
  4. package/dist/access-mcp.js +17 -17
  5. package/dist/access-operations-batch.js +15 -15
  6. package/dist/access-operations.js +16 -16
  7. package/dist/access-service.js +12 -12
  8. package/dist/active-memory-bridge.js +3 -3
  9. package/dist/briefing.js +2 -2
  10. package/dist/buffer.js +2 -2
  11. package/dist/capabilities.d.ts +97 -1
  12. package/dist/capabilities.js +7 -1
  13. package/dist/causal-consolidation.js +4 -3
  14. package/dist/causal-consolidation.js.map +1 -1
  15. package/dist/{chunk-IFCM6OLK.js → chunk-3TUDKDTQ.js} +7 -7
  16. package/dist/{chunk-A7INTIC5.js → chunk-4J53ZVPQ.js} +3 -3
  17. package/dist/{chunk-XYUFGHUW.js → chunk-56F6EAQ6.js} +2 -2
  18. package/dist/{chunk-F6OEXJQQ.js → chunk-6XG3NQRC.js} +2 -2
  19. package/dist/{chunk-24ZLC5QN.js → chunk-7N7S2RKF.js} +2 -2
  20. package/dist/{chunk-Y5OOHER4.js → chunk-7Y5KKMIP.js} +12 -11
  21. package/dist/chunk-7Y5KKMIP.js.map +1 -0
  22. package/dist/{chunk-VRBBZH4U.js → chunk-AX4TRSRE.js} +3 -3
  23. package/dist/{chunk-66RZ4EIT.js → chunk-BE6NEQLF.js} +3 -3
  24. package/dist/{chunk-YF2MMBKA.js → chunk-BJPL5WAL.js} +3 -3
  25. package/dist/{chunk-EO5QWINU.js → chunk-C3Z5YJSM.js} +5 -2
  26. package/dist/chunk-C3Z5YJSM.js.map +1 -0
  27. package/dist/{chunk-GEXI357K.js → chunk-C7C5WIIF.js} +2 -2
  28. package/dist/{chunk-L3TYGUTH.js → chunk-CMPXLMC3.js} +3 -3
  29. package/dist/{chunk-W2FBVBQ4.js → chunk-DBVBV2RF.js} +4 -4
  30. package/dist/{chunk-JQSP7YBJ.js → chunk-ELL5VYXC.js} +5 -4
  31. package/dist/chunk-ELL5VYXC.js.map +1 -0
  32. package/dist/{chunk-IQOEW5YV.js → chunk-FCQ7ZYCQ.js} +2 -2
  33. package/dist/{chunk-IIBFCZA7.js → chunk-FWXLKH2H.js} +3 -3
  34. package/dist/{chunk-RJBW4EOU.js → chunk-G7Q4D2G3.js} +74 -2
  35. package/dist/{chunk-RJBW4EOU.js.map → chunk-G7Q4D2G3.js.map} +1 -1
  36. package/dist/{chunk-WVAEIKUY.js → chunk-GPX5E36D.js} +5 -4
  37. package/dist/chunk-GPX5E36D.js.map +1 -0
  38. package/dist/{chunk-23PLOBWT.js → chunk-H3WSZWHK.js} +22 -20
  39. package/dist/chunk-H3WSZWHK.js.map +1 -0
  40. package/dist/{chunk-Q6BAA57B.js → chunk-JFCS6PQU.js} +2 -2
  41. package/dist/chunk-JFCS6PQU.js.map +1 -0
  42. package/dist/{chunk-CKHPUOAP.js → chunk-K2N6WIZM.js} +3 -3
  43. package/dist/{chunk-BHJAMSVC.js → chunk-LD6A7XG5.js} +7 -7
  44. package/dist/{chunk-AKKFHN3I.js → chunk-M4WI23X3.js} +2 -2
  45. package/dist/{chunk-N2O23WYA.js → chunk-M5KLYHHI.js} +2 -2
  46. package/dist/{chunk-TNLXCSXV.js → chunk-O4IWVWSW.js} +5 -4
  47. package/dist/chunk-O4IWVWSW.js.map +1 -0
  48. package/dist/{chunk-OQQRWPFZ.js → chunk-OS5RKJOH.js} +2 -2
  49. package/dist/{chunk-MAU7DFCJ.js → chunk-OT5K26NG.js} +5 -4
  50. package/dist/chunk-OT5K26NG.js.map +1 -0
  51. package/dist/{chunk-DS3FZ7GS.js → chunk-OUSOMUFV.js} +2 -2
  52. package/dist/{chunk-7B7IPPN5.js → chunk-OVYBENIJ.js} +3 -3
  53. package/dist/{chunk-5RZOFIDL.js → chunk-PI4JHLDD.js} +6 -3
  54. package/dist/chunk-PI4JHLDD.js.map +1 -0
  55. package/dist/{chunk-EU543UDC.js → chunk-QCO2QFLZ.js} +7 -7
  56. package/dist/chunk-QCO2QFLZ.js.map +1 -0
  57. package/dist/{chunk-YXOXAQ5Y.js → chunk-TQQN64J2.js} +5 -4
  58. package/dist/chunk-TQQN64J2.js.map +1 -0
  59. package/dist/{chunk-WDJCZQB4.js → chunk-UGFPGWJB.js} +2 -2
  60. package/dist/{chunk-75PDC7VT.js → chunk-UOVDO6TC.js} +6 -5
  61. package/dist/chunk-UOVDO6TC.js.map +1 -0
  62. package/dist/{chunk-BVG2IZOB.js → chunk-USHVHI6J.js} +7 -6
  63. package/dist/chunk-USHVHI6J.js.map +1 -0
  64. package/dist/{chunk-56LP72AD.js → chunk-UYYSOMS2.js} +4 -4
  65. package/dist/{chunk-IEWUPZ75.js → chunk-VC7QELR6.js} +77 -74
  66. package/dist/chunk-VC7QELR6.js.map +1 -0
  67. package/dist/{chunk-XIQAOGAA.js → chunk-WGDE2TJP.js} +7 -6
  68. package/dist/chunk-WGDE2TJP.js.map +1 -0
  69. package/dist/{chunk-UFS7OXGL.js → chunk-WHEF76BQ.js} +5 -2
  70. package/dist/chunk-WHEF76BQ.js.map +1 -0
  71. package/dist/{chunk-QTJOORGN.js → chunk-WIMKOTNY.js} +2 -2
  72. package/dist/{chunk-GXTYEG7Q.js → chunk-WO22UEM3.js} +2 -2
  73. package/dist/{chunk-BHQQVUEQ.js → chunk-X5PMDVY4.js} +6 -5
  74. package/dist/{chunk-BHQQVUEQ.js.map → chunk-X5PMDVY4.js.map} +1 -1
  75. package/dist/{chunk-C53JDEH3.js → chunk-Y62QPRKV.js} +2 -2
  76. package/dist/{chunk-WFNH4UDF.js → chunk-Y6PNYJVO.js} +3 -3
  77. package/dist/{chunk-6YKIYQU7.js → chunk-YNHRWFAP.js} +5 -2
  78. package/dist/{chunk-6YKIYQU7.js.map → chunk-YNHRWFAP.js.map} +1 -1
  79. package/dist/cli.js +29 -29
  80. package/dist/compounding/engine.js +4 -4
  81. package/dist/connectors/codex-materialize-runner.js +2 -2
  82. package/dist/connectors/index.js +4 -3
  83. package/dist/contradiction/index.js +2 -2
  84. package/dist/{contradiction-scan-CWO3LIWV.js → contradiction-scan-UERKJESC.js} +3 -3
  85. package/dist/day-summary.js +2 -1
  86. package/dist/embedding-fallback.js +2 -2
  87. package/dist/entity-retrieval.js +3 -3
  88. package/dist/explicit-capture.js +2 -2
  89. package/dist/extraction.js +4 -4
  90. package/dist/{first-start-migration-5DXD3TF2.js → first-start-migration-GQ3UQNIL.js} +2 -2
  91. package/dist/index.js +45 -45
  92. package/dist/local-llm.js +2 -2
  93. package/dist/maintenance/memory-governance.js +2 -2
  94. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +2 -2
  95. package/dist/maintenance/rebuild-memory-projection.js +3 -3
  96. package/dist/namespaces/migrate.js +7 -7
  97. package/dist/namespaces/principal.js +2 -2
  98. package/dist/namespaces/search.js +4 -4
  99. package/dist/namespaces/storage.js +3 -3
  100. package/dist/operator-toolkit.js +13 -13
  101. package/dist/orchestration/compression-guideline-coordinator.js +2 -2
  102. package/dist/orchestration/maintenance.js +7 -7
  103. package/dist/orchestrator.js +29 -29
  104. package/dist/schemas.d.ts +22 -22
  105. package/dist/search/embed-helper.js +2 -2
  106. package/dist/search/factory.js +3 -3
  107. package/dist/search/index.js +3 -3
  108. package/dist/semantic-consolidation.js +4 -3
  109. package/dist/semantic-rule-promotion.js +2 -2
  110. package/dist/semantic-rule-verifier.js +2 -2
  111. package/dist/shared-context/manager.js +2 -1
  112. package/dist/storage.d.ts +1 -1
  113. package/dist/storage.js +1 -1
  114. package/dist/summarizer.js +3 -3
  115. package/dist/{tier-stats-QID73BBB.js → tier-stats-CSKL7BDG.js} +2 -2
  116. package/dist/transfer/types.d.ts +12 -12
  117. package/dist/verified-recall.js +2 -2
  118. package/package.json +2 -2
  119. package/src/access-service.ts +2 -1
  120. package/src/capabilities.test.ts +166 -0
  121. package/src/capabilities.ts +267 -0
  122. package/src/cli/research-status-commands.ts +2 -1
  123. package/src/cli.ts +3 -2
  124. package/src/compounding/engine.ts +2 -1
  125. package/src/connectors/codex-marketplace.ts +2 -1
  126. package/src/day-summary.ts +2 -1
  127. package/src/embedding-fallback.ts +2 -1
  128. package/src/extraction.ts +3 -2
  129. package/src/local-llm.ts +2 -1
  130. package/src/maintenance/namespace-maintenance-fanout.ts +2 -1
  131. package/src/maintenance/namespace-planner.ts +2 -1
  132. package/src/operator-toolkit.ts +1 -0
  133. package/src/orchestration/semantic-consolidation-coordinator.ts +3 -2
  134. package/src/orchestrator.ts +50 -46
  135. package/src/search/embed-helper.ts +2 -1
  136. package/src/search/factory.ts +2 -1
  137. package/src/semantic-consolidation.ts +2 -1
  138. package/src/shared-context/manager.ts +3 -2
  139. package/src/storage.ts +1 -1
  140. package/src/summarizer.ts +3 -2
  141. package/dist/chunk-23PLOBWT.js.map +0 -1
  142. package/dist/chunk-5RZOFIDL.js.map +0 -1
  143. package/dist/chunk-75PDC7VT.js.map +0 -1
  144. package/dist/chunk-BVG2IZOB.js.map +0 -1
  145. package/dist/chunk-EO5QWINU.js.map +0 -1
  146. package/dist/chunk-EU543UDC.js.map +0 -1
  147. package/dist/chunk-IEWUPZ75.js.map +0 -1
  148. package/dist/chunk-JQSP7YBJ.js.map +0 -1
  149. package/dist/chunk-MAU7DFCJ.js.map +0 -1
  150. package/dist/chunk-Q6BAA57B.js.map +0 -1
  151. package/dist/chunk-TNLXCSXV.js.map +0 -1
  152. package/dist/chunk-UFS7OXGL.js.map +0 -1
  153. package/dist/chunk-WVAEIKUY.js.map +0 -1
  154. package/dist/chunk-XIQAOGAA.js.map +0 -1
  155. package/dist/chunk-Y5OOHER4.js.map +0 -1
  156. package/dist/chunk-YXOXAQ5Y.js.map +0 -1
  157. /package/dist/{chunk-IFCM6OLK.js.map → chunk-3TUDKDTQ.js.map} +0 -0
  158. /package/dist/{chunk-A7INTIC5.js.map → chunk-4J53ZVPQ.js.map} +0 -0
  159. /package/dist/{chunk-XYUFGHUW.js.map → chunk-56F6EAQ6.js.map} +0 -0
  160. /package/dist/{chunk-F6OEXJQQ.js.map → chunk-6XG3NQRC.js.map} +0 -0
  161. /package/dist/{chunk-24ZLC5QN.js.map → chunk-7N7S2RKF.js.map} +0 -0
  162. /package/dist/{chunk-VRBBZH4U.js.map → chunk-AX4TRSRE.js.map} +0 -0
  163. /package/dist/{chunk-66RZ4EIT.js.map → chunk-BE6NEQLF.js.map} +0 -0
  164. /package/dist/{chunk-YF2MMBKA.js.map → chunk-BJPL5WAL.js.map} +0 -0
  165. /package/dist/{chunk-GEXI357K.js.map → chunk-C7C5WIIF.js.map} +0 -0
  166. /package/dist/{chunk-L3TYGUTH.js.map → chunk-CMPXLMC3.js.map} +0 -0
  167. /package/dist/{chunk-W2FBVBQ4.js.map → chunk-DBVBV2RF.js.map} +0 -0
  168. /package/dist/{chunk-IQOEW5YV.js.map → chunk-FCQ7ZYCQ.js.map} +0 -0
  169. /package/dist/{chunk-IIBFCZA7.js.map → chunk-FWXLKH2H.js.map} +0 -0
  170. /package/dist/{chunk-CKHPUOAP.js.map → chunk-K2N6WIZM.js.map} +0 -0
  171. /package/dist/{chunk-BHJAMSVC.js.map → chunk-LD6A7XG5.js.map} +0 -0
  172. /package/dist/{chunk-AKKFHN3I.js.map → chunk-M4WI23X3.js.map} +0 -0
  173. /package/dist/{chunk-N2O23WYA.js.map → chunk-M5KLYHHI.js.map} +0 -0
  174. /package/dist/{chunk-OQQRWPFZ.js.map → chunk-OS5RKJOH.js.map} +0 -0
  175. /package/dist/{chunk-DS3FZ7GS.js.map → chunk-OUSOMUFV.js.map} +0 -0
  176. /package/dist/{chunk-7B7IPPN5.js.map → chunk-OVYBENIJ.js.map} +0 -0
  177. /package/dist/{chunk-WDJCZQB4.js.map → chunk-UGFPGWJB.js.map} +0 -0
  178. /package/dist/{chunk-56LP72AD.js.map → chunk-UYYSOMS2.js.map} +0 -0
  179. /package/dist/{chunk-QTJOORGN.js.map → chunk-WIMKOTNY.js.map} +0 -0
  180. /package/dist/{chunk-GXTYEG7Q.js.map → chunk-WO22UEM3.js.map} +0 -0
  181. /package/dist/{chunk-C53JDEH3.js.map → chunk-Y62QPRKV.js.map} +0 -0
  182. /package/dist/{chunk-WFNH4UDF.js.map → chunk-Y6PNYJVO.js.map} +0 -0
  183. /package/dist/{contradiction-scan-CWO3LIWV.js.map → contradiction-scan-UERKJESC.js.map} +0 -0
  184. /package/dist/{first-start-migration-5DXD3TF2.js.map → first-start-migration-GQ3UQNIL.js.map} +0 -0
  185. /package/dist/{tier-stats-QID73BBB.js.map → tier-stats-CSKL7BDG.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/semantic-consolidation.ts"],"sourcesContent":["/**\n * semantic-consolidation.ts — Semantic Consolidation Engine\n *\n * Finds clusters of semantically similar memories using token overlap,\n * synthesizes canonical versions via LLM, and archives the originals.\n * Reduces memory store bloat while preserving all unique information.\n */\n\nimport type { MemoryFile, PluginConfig } from \"./types.js\";\nimport { normalizeRecallTokens, countRecallTokenOverlap } from \"./recall-tokenization.js\";\nimport { runPostConsolidationMaterialize } from \"./connectors/codex-materialize-runner.js\";\nimport type { MaterializeResult, RolloutSummaryInput } from \"./connectors/codex-materialize.js\";\nimport { discoverMemoryExtensions, renderExtensionsBlock, resolveExtensionsRoot } from \"./memory-extension-host/index.js\";\nimport { log } from \"./logger.js\";\n\n// Re-export resolveExtensionsRoot for backward compatibility — existing\n// consumers that import from semantic-consolidation.ts continue to work.\nexport { resolveExtensionsRoot } from \"./memory-extension-host/index.js\";\n\n// Operator vocabulary (issue #561). The types and validators live in a\n// standalone `consolidation-operator.ts` module so `storage.ts` can import\n// them without creating a `storage → semantic-consolidation →\n// codex-materialize-runner → storage` cycle. Re-exported here so existing\n// consumers that reach for `./semantic-consolidation.js` keep working.\nexport {\n CONSOLIDATION_OPERATORS,\n isConsolidationOperator,\n isSemanticConsolidationLlmOperator,\n isValidDerivedFromEntry,\n type ConsolidationOperator,\n type SemanticConsolidationLlmOperator,\n} from \"./consolidation-operator.js\";\n\nimport {\n CONSOLIDATION_OPERATORS as _CONSOLIDATION_OPERATORS,\n isConsolidationOperator as _isConsolidationOperator,\n isSemanticConsolidationLlmOperator as _isSemanticConsolidationLlmOperator,\n type ConsolidationOperator as _ConsolidationOperator,\n type SemanticConsolidationLlmOperator as _SemanticConsolidationLlmOperator,\n} from \"./consolidation-operator.js\";\n\nexport interface ConsolidationCluster {\n category: string;\n memories: MemoryFile[];\n overlapScore: number;\n canonicalContent?: string;\n}\n\nexport interface SemanticConsolidationResult {\n clustersFound: number;\n memoriesConsolidated: number;\n memoriesArchived: number;\n errors: number;\n clusters: ConsolidationCluster[];\n}\n\n/**\n * Find clusters of semantically similar memories using token overlap.\n */\nexport function findSimilarClusters(\n memories: MemoryFile[],\n config: {\n threshold: number;\n minClusterSize: number;\n excludeCategories: string[];\n maxPerRun: number;\n },\n): ConsolidationCluster[] {\n const excluded = new Set(config.excludeCategories);\n\n // Group by category first\n const byCategory = new Map<string, MemoryFile[]>();\n for (const m of memories) {\n const cat = m.frontmatter.category;\n if (excluded.has(cat)) continue;\n if (m.frontmatter.status && m.frontmatter.status !== \"active\") continue;\n const list = byCategory.get(cat) ?? [];\n list.push(m);\n byCategory.set(cat, list);\n }\n\n const clusters: ConsolidationCluster[] = [];\n let totalCandidates = 0;\n\n for (const [category, mems] of byCategory) {\n if (totalCandidates >= config.maxPerRun) break;\n\n // Token-normalize all memories in this category\n const tokenized = mems.map((m) => ({\n memory: m,\n tokens: new Set(normalizeRecallTokens(m.content, [])),\n }));\n\n // Track which memories are already clustered\n const clustered = new Set<string>();\n\n for (let i = 0; i < tokenized.length && totalCandidates < config.maxPerRun; i++) {\n const remainingBudget = config.maxPerRun - totalCandidates;\n if (remainingBudget < config.minClusterSize) break;\n if (clustered.has(tokenized[i].memory.frontmatter.id)) continue;\n\n const cluster: MemoryFile[] = [tokenized[i].memory];\n let totalOverlap = 0;\n let comparisons = 0;\n\n for (let j = i + 1; j < tokenized.length && cluster.length < remainingBudget; j++) {\n if (clustered.has(tokenized[j].memory.frontmatter.id)) continue;\n\n const aTokens = tokenized[i].tokens;\n const bTokens = tokenized[j].tokens;\n if (aTokens.size === 0 || bTokens.size === 0) continue;\n\n // Bidirectional overlap: what fraction of tokens are shared\n const overlap = countRecallTokenOverlap(aTokens, [...bTokens].join(\" \"));\n const maxTokens = Math.max(aTokens.size, bTokens.size);\n const score = maxTokens > 0 ? overlap / maxTokens : 0;\n\n if (score >= config.threshold) {\n cluster.push(tokenized[j].memory);\n totalOverlap += score;\n comparisons++;\n }\n }\n\n if (cluster.length >= config.minClusterSize) {\n for (const m of cluster) clustered.add(m.frontmatter.id);\n clusters.push({\n category,\n memories: cluster,\n overlapScore: comparisons > 0 ? totalOverlap / comparisons : 0,\n });\n totalCandidates += cluster.length;\n }\n }\n }\n\n return clusters;\n}\n\n/**\n * Build the LLM prompt for synthesizing a canonical memory from a cluster.\n */\nexport function buildConsolidationPrompt(cluster: ConsolidationCluster): string {\n const memoryTexts = cluster.memories\n .map(\n (m, i) =>\n `Memory ${i + 1} (${m.frontmatter.id}, created ${m.frontmatter.created}):\\n${m.content}`,\n )\n .join(\"\\n\\n\");\n\n return `You are a memory consolidation system. The following ${cluster.memories.length} memories in the \"${cluster.category}\" category contain overlapping information.\n\nSynthesize them into ONE canonical memory that:\n1. Preserves ALL unique information from every source memory\n2. Removes redundancy and repetition\n3. Uses clear, concise language\n4. Maintains the same category and tone\n5. Does NOT add information that isn't in the sources\n\n${memoryTexts}\n\nWrite ONLY the consolidated memory content (no metadata, no explanation, no preamble):`;\n}\n\n/**\n * Parse the LLM response to extract the canonical content.\n */\nexport function parseConsolidationResponse(response: string): string {\n return response.trim();\n}\n\n// ─── Operator-aware prompt / parse (issue #561 PR 3) ─────────────────────────\n\n/**\n * Structured result from an operator-aware consolidation LLM call.\n *\n * - `operator` — the consolidation operator the LLM chose for this cluster.\n * Falls back to the heuristic default when the LLM omits or returns an\n * unknown value (the parser never surfaces an invalid operator; see\n * `parseOperatorAwareConsolidationResponse`).\n * - `output` — the canonical content (same format the legacy prompt\n * returns). Callers persist this as the body of the new memory.\n */\nexport interface OperatorAwareConsolidationResult {\n // Restricted to the LLM-allowed subset (Cursor Bugbot, PR #730):\n // `pattern-reinforcement` is reserved for the maintenance job and\n // must never reach this struct from a consolidation LLM response.\n operator: _SemanticConsolidationLlmOperator;\n output: string;\n}\n\n/**\n * Heuristic default operator for a cluster. Used as the fallback when the\n * LLM does not return a parseable operator, and as the \"floor\" decision in\n * `parseOperatorAwareConsolidationResponse`.\n *\n * Current heuristic (kept deliberately conservative — PR 3 only):\n *\n * - Two or more memories being collapsed into one canonical blob is a\n * MERGE by definition. This is the path the current clustering\n * pipeline exercises.\n * - A cluster of size 1 that still reaches consolidation (future path,\n * e.g. supersession of a single older memory by a newer value) is an\n * UPDATE.\n * - SPLIT is never selected by the heuristic because the current write\n * path emits exactly one canonical memory per cluster. The prompt\n * reserves SPLIT for future cluster shapes where the LLM decides one\n * logical source actually encodes several distinct facts — at which\n * point the orchestrator would need to write multiple outputs.\n */\nexport function chooseConsolidationOperator(\n cluster: ConsolidationCluster,\n): _SemanticConsolidationLlmOperator {\n if (cluster.memories.length <= 1) return \"update\";\n return \"merge\";\n}\n\n/**\n * Build the operator-aware LLM prompt. The LLM is asked to return a\n * JSON object `{ \"operator\": <split|merge|update>, \"output\": <content> }`.\n *\n * The prompt is additive: it still asks for a single canonical blob under\n * `output`, so the upstream write path does not change. Future expansions\n * (SPLIT emitting multiple outputs) are explicitly documented as\n * out-of-scope for the parser — `parseOperatorAwareConsolidationResponse`\n * collapses any SPLIT response into a single canonical output for now.\n */\nexport function buildOperatorAwareConsolidationPrompt(\n cluster: ConsolidationCluster,\n): string {\n const memoryTexts = cluster.memories\n .map(\n (m, i) =>\n `Memory ${i + 1} (${m.frontmatter.id}, created ${m.frontmatter.created}):\\n${m.content}`,\n )\n .join(\"\\n\\n\");\n\n return `You are a memory consolidation system. The following ${cluster.memories.length} memories in the \"${cluster.category}\" category contain overlapping information.\n\nPick exactly ONE consolidation operator for this cluster and return a JSON object.\n\nOperator vocabulary:\n - \"merge\" — multiple distinct source memories overlap and should be collapsed into one canonical memory (most common).\n - \"update\" — one source memory carries a stale value that a newer source supersedes within the same logical fact.\n - \"split\" — a single logical source really encodes multiple distinct facts that should be separated (rare; if you pick split, still emit ONE canonical body — the write path will chunk it later).\n\nOutput JSON ONLY, no prose before or after. The \"operator\" key MUST be set to exactly one of the three strings \"merge\", \"update\", or \"split\" — never a pipe-separated placeholder like \"merge|update|split\". Example shape:\n {\n \"operator\": \"merge\",\n \"output\": \"<the canonical memory text>\"\n }\n\nThe \"output\" value must:\n1. Preserve ALL unique information from every source memory\n2. Remove redundancy and repetition\n3. Use clear, concise language\n4. Match the \"${cluster.category}\" category and tone\n5. NOT add information that isn't in the sources\n\n${memoryTexts}\n\nReturn ONLY the JSON object:`;\n}\n\n/**\n * Parse an operator-aware consolidation response.\n *\n * Contract:\n * - Accepts strict JSON `{ \"operator\": \"...\", \"output\": \"...\" }`.\n * - Tolerates a JSON payload wrapped in a fenced code block (```json ...```).\n * - Falls back to the heuristic operator when the JSON is malformed,\n * the `operator` field is missing / unknown, or the raw response is\n * a plain blob with no JSON at all. This keeps PR 3 backwards\n * compatible with older models that ignore the JSON instruction.\n * - Never throws. A missing / empty `output` field falls back to the\n * trimmed raw response so the caller still writes something rather\n * than dropping the cluster.\n */\nexport function parseOperatorAwareConsolidationResponse(\n response: string,\n cluster: ConsolidationCluster,\n): OperatorAwareConsolidationResult {\n const fallback: OperatorAwareConsolidationResult = {\n operator: chooseConsolidationOperator(cluster),\n output: response.trim(),\n };\n\n const trimmed = response.trim();\n if (trimmed.length === 0) return fallback;\n\n // Strip a fenced code block if present.\n // Dropped the \\s* groups around the lazy body (they overlapped it and\n // backtracked polynomially — CodeQL js/polynomial-redos). Input is already\n // trimmed and fenced[1] is trimmed below, so matches are identical.\n const fenced = /^```(?:json)?([\\s\\S]*?)```$/u.exec(trimmed);\n const payload = fenced ? fenced[1].trim() : trimmed;\n\n // Find a balanced brace-delimited JSON object that has an `operator`\n // key (PR #632 round-4 review, codex P1). A first/last-brace slice\n // breaks when the model prepends an earlier brace block (e.g.\n // `Example: {\"note\":\"...\"} ... {\"operator\":\"merge\",...}`). Walk the\n // payload tracking nesting + string/escape state and skip past\n // objects that don't look like our target shape.\n const parsed = findLastJsonObjectWithOperator(payload);\n if (parsed === undefined) return fallback;\n if (typeof parsed !== \"object\" || parsed === null) return fallback;\n\n const obj = parsed as Record<string, unknown>;\n const rawOperator = typeof obj.operator === \"string\" ? obj.operator.trim().toLowerCase() : \"\";\n const rawOutput = typeof obj.output === \"string\" ? obj.output : \"\";\n\n // Narrow gate (Cursor Bugbot review on PR #730 head `aa1c2a8`):\n // accept ONLY the legacy split/merge/update LLM vocabulary here.\n // `pattern-reinforcement` joined the broader `ConsolidationOperator`\n // type in #687 PR 2/4 but is reserved for the maintenance job — if\n // an LLM hallucinates that operator we must NOT promote it onto\n // `derived_via`.\n const operator = _isSemanticConsolidationLlmOperator(rawOperator)\n ? rawOperator\n : chooseConsolidationOperator(cluster);\n const output = rawOutput.trim().length > 0 ? rawOutput.trim() : response.trim();\n\n return { operator, output };\n}\n\n/**\n * Walk `text`, find all balanced top-level `{ ... }` blocks whose\n * JSON.parse result is an object with an `operator` key, and return\n * the LAST one (function name reflects this — PR #632 review,\n * cursor Low). Returns `undefined` when nothing matches. Tracks\n * string state + escape sequences so braces inside string values\n * don't throw off the depth counter.\n *\n * Used by `parseOperatorAwareConsolidationResponse` to tolerate models\n * that prepend an explanatory JSON example block before the real\n * payload (PR #632 round-4 + round-5 review, codex P1). We take the\n * LAST candidate so that an instructional example with an `operator`\n * key ahead of the real answer doesn't steal precedence — models\n * typically write the example first and the real answer last.\n */\nfunction findLastJsonObjectWithOperator(text: string): unknown {\n let searchFrom = 0;\n let last: unknown = undefined;\n while (searchFrom < text.length) {\n const start = text.indexOf(\"{\", searchFrom);\n if (start < 0) return last;\n let depth = 0;\n let inString = false;\n let escape = false;\n let closed = false;\n let endIdx = -1;\n for (let i = start; i < text.length; i++) {\n const ch = text[i];\n if (inString) {\n if (escape) {\n escape = false;\n } else if (ch === \"\\\\\") {\n escape = true;\n } else if (ch === '\"') {\n inString = false;\n }\n continue;\n }\n if (ch === '\"') {\n inString = true;\n } else if (ch === \"{\") {\n depth += 1;\n } else if (ch === \"}\") {\n depth -= 1;\n if (depth === 0) {\n closed = true;\n endIdx = i;\n break;\n }\n }\n }\n if (!closed) return last;\n const slice = text.slice(start, endIdx + 1);\n try {\n const parsed = JSON.parse(slice);\n if (\n typeof parsed === \"object\" &&\n parsed !== null &&\n \"operator\" in (parsed as Record<string, unknown>)\n ) {\n last = parsed;\n }\n } catch {\n // Fall through to the next candidate.\n }\n searchFrom = endIdx + 1;\n }\n return last;\n}\n\n// Silence unused-import warnings when tsup tree-shakes: these are used\n// above in chooseConsolidationOperator + parse helpers.\nvoid _CONSOLIDATION_OPERATORS;\n\n/**\n * Discover extensions and build the block to append to a consolidation prompt.\n * Returns \"\" when extensions are disabled or none are found.\n */\nexport async function buildExtensionsBlockForConsolidation(\n config: PluginConfig,\n): Promise<string> {\n if (!config.memoryExtensionsEnabled) return \"\";\n const root = resolveExtensionsRoot(config);\n const extensions = await discoverMemoryExtensions(root, log);\n if (extensions.length === 0) return \"\";\n return renderExtensionsBlock(extensions);\n}\n\n/**\n * Optional post-consolidation hook — materializes the namespace into Codex's\n * native memory layout when the consolidation run finishes. Kept here (rather\n * than in orchestrator.ts) so #378 doesn't conflict with Wave 1 edits.\n *\n * Safe to call regardless of config state: honors `codexMaterializeMemories`\n * and `codexMaterializeOnConsolidation` and silently becomes a no-op when\n * either is disabled.\n */\nexport async function materializeAfterSemanticConsolidation(options: {\n config: PluginConfig;\n namespace?: string;\n memories?: MemoryFile[];\n memoryDir?: string;\n codexHome?: string;\n rolloutSummaries?: RolloutSummaryInput[];\n now?: Date;\n}): Promise<MaterializeResult | null> {\n // Delegates to the shared post-consolidation helper so semantic and causal\n // flows stay in lock-step — any guard/logging change happens in one place.\n return runPostConsolidationMaterialize(\"[semantic-consolidation]\", options);\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/compounding/engine.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { mkdir, readFile, readdir, unlink, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { log } from \"../logger.js\";\nimport { sanitizeMemoryContent } from \"../sanitize.js\";\nimport { StorageManager } from \"../storage.js\";\nimport type { ContinuityIncidentRecord, PluginConfig } from \"../types.js\";\nimport { resolveSharedContextDir, SharedFeedbackEntrySchema, type SharedFeedbackEntry } from \"../shared-context/manager.js\";\nimport { parseContinuityImprovementLoops } from \"../identity-continuity.js\";\nimport { resolveQmdCapabilities, type QmdConfigProjection, resolveConsolidationCapabilities } from \"../capabilities.js\";\n\ntype MistakesFile = {\n version?: number;\n updatedAt: string;\n patterns: string[];\n registry?: MistakeRegistryEntry[];\n};\n\ntype FeedbackEntryWithProvenance = {\n entry: SharedFeedbackEntry;\n sourceLine: number;\n sourcePath: string;\n entryId: string;\n};\n\ntype PatternWithProvenance = {\n pattern: string;\n provenance: string[];\n};\n\ntype ActionOutcomeCounts = {\n applied: number;\n skipped: number;\n failed: number;\n};\n\ntype ActionOutcomeSummary = {\n action: string;\n counts: ActionOutcomeCounts;\n total: number;\n weightedScore: number;\n provenance: string[];\n};\n\ntype PromotionCandidate = {\n id: string;\n sourceType: \"action-outcome\" | \"mistake-pattern\" | \"rubric\" | \"causal-pattern\";\n subject: string;\n category: \"principle\" | \"rule\" | \"preference\";\n content: string;\n score: number;\n rationale: string;\n outcome: ActionOutcomeCounts | null;\n provenance: string[];\n agent: string | null;\n workflow: string | null;\n};\n\ntype CompoundingEntrySeverity = \"low\" | \"medium\" | \"high\";\n\ntype EvidenceWindow = {\n start: string | null;\n end: string | null;\n};\n\ntype MistakeRegistryEntry = {\n id: string;\n pattern: string;\n category: \"feedback\" | \"action\";\n status: \"active\" | \"retired\";\n agent: string | null;\n workflow: string | null;\n tags: string[];\n severity: CompoundingEntrySeverity | null;\n confidence: number | null;\n outcome: string | null;\n provenance: string[];\n firstSeenAt: string;\n lastSeenAt: string;\n recurrenceCount: number;\n lastWeekId: string;\n evidenceWindow: EvidenceWindow;\n mergedFromIds?: string[];\n retiredAt?: string | null;\n};\n\ntype RubricSnapshotEntry = {\n id: string;\n kind: \"agent\" | \"workflow\";\n subject: string;\n observations: string[];\n tags: string[];\n provenance: string[];\n observationEntries?: Array<{\n note: string;\n provenance: string[];\n }>;\n updatedAt: string;\n};\n\ntype RubricSnapshot = {\n updatedAt: string;\n agents: RubricSnapshotEntry[];\n workflows: RubricSnapshotEntry[];\n};\n\ntype WeeklyCompoundingArtifact = {\n version: number;\n generatedAt: string;\n weekId: string;\n feedback: {\n count: number;\n byDecision: Record<\"approved\" | \"approved_with_feedback\" | \"rejected\", number>;\n entries: Array<{\n agent: string;\n workflow: string | null;\n decision: SharedFeedbackEntry[\"decision\"];\n reason: string;\n learning: string | null;\n outcome: string | null;\n severity: CompoundingEntrySeverity | null;\n confidence: number | null;\n tags: string[];\n provenance: string;\n evidenceWindow: EvidenceWindow;\n }>;\n };\n mistakes: {\n count: number;\n patterns: string[];\n registry: MistakeRegistryEntry[];\n };\n rubrics: RubricSnapshot;\n outcomes: ActionOutcomeSummary[];\n promotionCandidates: PromotionCandidate[];\n continuity: { monthId: string; weeklyPath: string | null; monthlyPath: string | null };\n};\n\nexport interface CompoundingPromotionReport {\n enabled: boolean;\n dryRun: boolean;\n weekId: string;\n promoted: Array<{\n id: string;\n candidateId: string;\n category: \"principle\" | \"rule\" | \"preference\";\n content: string;\n confidence: number;\n tags: string[];\n lineage: string[];\n }>;\n skipped: Array<{\n weekId: string;\n candidateId?: string;\n reason: \"disabled\" | \"weekly-artifact-missing\" | \"candidate-not-found\" | \"duplicate-guidance\";\n existingMemoryId?: string;\n }>;\n /**\n * Promotions the #1579 tombstone chokepoint downgraded to pending_review (no\n * active copy). Reported distinctly so callers never treat a blocked write as\n * a successfully promoted active memory (#1645).\n */\n tombstoneBlocked: Array<{\n id: string;\n candidateId: string;\n category: \"principle\" | \"rule\" | \"preference\";\n content: string;\n }>;\n}\n\ntype WeeklyActionEvent = {\n line: number;\n action: string;\n outcome: \"applied\" | \"skipped\" | \"failed\";\n policyDecision: \"deny\" | \"defer\" | null;\n namespace: string;\n reason: string | null;\n};\n\nconst COMPOUNDING_VERSION = 2;\nconst RETIREMENT_WINDOW_WEEKS = 8;\n\nfunction stableSlug(value: string): string {\n return value\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .slice(0, 80) || \"item\";\n}\n\nfunction tokenizeRecallQuery(text: string): string[] {\n const seen = new Set<string>();\n const out: string[] = [];\n for (const token of text\n .toLowerCase()\n .replace(/[^a-z0-9\\s]+/g, \" \")\n .split(/\\s+/)\n .map((part) => part.trim())\n .filter((part) => part.length >= 3)) {\n if (seen.has(token)) continue;\n seen.add(token);\n out.push(token);\n }\n return out;\n}\n\nfunction weekIdToIndex(weekId: string): number {\n const match = weekId.match(/^(\\d{4})-W(\\d{2})$/);\n if (!match) return Number.POSITIVE_INFINITY;\n const year = Number(match[1]);\n const week = Number(match[2]);\n if (!Number.isInteger(year) || !Number.isInteger(week) || week < 1 || week > 53) {\n return Number.POSITIVE_INFINITY;\n }\n const jan4 = new Date(Date.UTC(year, 0, 4));\n const jan4Day = jan4.getUTCDay() || 7;\n const isoWeekOneStart = new Date(jan4);\n isoWeekOneStart.setUTCDate(jan4.getUTCDate() - (jan4Day - 1));\n const targetWeekStart = new Date(isoWeekOneStart);\n targetWeekStart.setUTCDate(isoWeekOneStart.getUTCDate() + ((week - 1) * 7));\n return Math.floor(targetWeekStart.getTime() / (7 * 24 * 60 * 60 * 1000));\n}\n\nfunction normalizeConfidence(value: unknown): number | null {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return null;\n const clamped = Math.max(0, Math.min(1, value));\n return Number(clamped.toFixed(3));\n}\n\nfunction normalizeTags(tags: string[] | undefined): string[] {\n if (!Array.isArray(tags)) return [];\n return [...new Set(tags.map((tag) => String(tag).trim()).filter((tag) => tag.length > 0))].sort();\n}\n\nfunction normalizeEvidenceWindow(start?: string, end?: string): EvidenceWindow {\n const safeStart = typeof start === \"string\" && start.trim().length > 0 ? start : null;\n const safeEnd = typeof end === \"string\" && end.trim().length > 0 ? end : null;\n return { start: safeStart, end: safeEnd };\n}\n\nfunction mergeEvidenceWindows(current: EvidenceWindow, next: EvidenceWindow): EvidenceWindow {\n return {\n start: current.start === null ? next.start : next.start === null ? current.start : current.start <= next.start ? current.start : next.start,\n end: current.end === null ? next.end : next.end === null ? current.end : current.end >= next.end ? current.end : next.end,\n };\n}\n\nfunction stableMistakeId(\n category: \"feedback\" | \"action\",\n pattern: string,\n agent: string | null,\n workflow: string | null,\n): string {\n return [\n category,\n agent ? stableSlug(agent) : \"global\",\n workflow ? stableSlug(workflow) : \"default\",\n stableSlug(pattern).slice(0, 48),\n ].join(\":\");\n}\n\nfunction stableRubricId(kind: \"agent\" | \"workflow\", subject: string): string {\n return `${kind}:${stableSlug(subject)}`;\n}\n\nfunction stablePromotionCandidateId(\n sourceType: PromotionCandidate[\"sourceType\"],\n subject: string,\n content: string,\n): string {\n const digest = createHash(\"sha256\")\n .update(`${sourceType}\\u0000${subject}\\u0000${content}`)\n .digest(\"hex\")\n .slice(0, 12);\n return `${sourceType}:${digest}`;\n}\n\nfunction rubricArtifactFileName(\n entry: Pick<RubricSnapshotEntry, \"kind\" | \"subject\">,\n slugCollisions: ReadonlyMap<string, number>,\n): string {\n const slug = stableSlug(entry.subject);\n if ((slugCollisions.get(slug) ?? 0) <= 1) return `${slug}.md`;\n const suffix = createHash(\"sha256\").update(`${entry.kind}:${entry.subject}`).digest(\"hex\").slice(0, 8);\n return `${slug}-${suffix}.md`;\n}\n\nfunction inferLegacyMistakeScope(pattern: string): { agent: string | null; workflow: string | null } {\n const separatorIndex = pattern.indexOf(\":\");\n if (separatorIndex <= 0) return { agent: null, workflow: null };\n const subject = pattern.slice(0, separatorIndex).trim();\n return {\n agent: subject.length > 0 ? subject : null,\n workflow: null,\n };\n}\n\nfunction inferLegacyMistakeMetadata(pattern: string): {\n category: \"feedback\" | \"action\";\n agent: string | null;\n workflow: string | null;\n} {\n if (pattern.startsWith(\"memory-action/\")) {\n return {\n category: \"action\",\n agent: null,\n workflow: \"memory-actions\",\n };\n }\n const scope = inferLegacyMistakeScope(pattern);\n return {\n category: \"feedback\",\n agent: scope.agent,\n workflow: scope.workflow,\n };\n}\n\nfunction normalizePromotionWhitespace(value: string): string {\n return value.replace(/\\s+/g, \" \").trim();\n}\n\nfunction stripTrailingPromotionPunctuation(value: string): string {\n return value.replace(/[,:;]+$/g, \"\").trim();\n}\n\nfunction extractExplicitIfThenRule(value: string): string | null {\n const normalized = normalizePromotionWhitespace(value);\n const match = normalized.match(/^if\\b([\\s\\S]+?)\\bthen\\b([\\s\\S]+?)(?:[.!?])?$/i);\n if (!match) return null;\n const condition = stripTrailingPromotionPunctuation(normalizePromotionWhitespace(match[1] ?? \"\"));\n const outcome = stripTrailingPromotionPunctuation(normalizePromotionWhitespace(match[2] ?? \"\"));\n if (condition.length === 0 || outcome.length === 0) return null;\n return `IF ${condition} THEN ${outcome}.`;\n}\n\nfunction normalizePromotedGuidanceContent(value: string): string {\n const explicitRule = extractExplicitIfThenRule(value);\n if (explicitRule) return explicitRule;\n const normalized = normalizePromotionWhitespace(value);\n if (normalized.length === 0) return normalized;\n return /[.!?]$/.test(normalized) ? normalized : `${normalized}.`;\n}\n\nfunction canonicalPromotionContentKey(value: string): string {\n return normalizePromotedGuidanceContent(value).toLowerCase();\n}\n\nfunction lessonContentFromPattern(pattern: string, agent: string | null): string {\n if (!agent) return normalizePromotionWhitespace(pattern);\n const prefix = `${agent}:`;\n if (!pattern.startsWith(prefix)) return normalizePromotionWhitespace(pattern);\n const withoutPrefix = pattern.slice(prefix.length).trim();\n return withoutPrefix.length > 0 ? normalizePromotionWhitespace(withoutPrefix) : normalizePromotionWhitespace(pattern);\n}\n\nfunction promotionCategoryForContent(content: string): \"principle\" | \"rule\" {\n return extractExplicitIfThenRule(content) ? \"rule\" : \"principle\";\n}\n\nfunction clampPromotionScore(value: number): number {\n if (!Number.isFinite(value)) return 0.65;\n return Number(Math.max(0.65, Math.min(0.98, value)).toFixed(3));\n}\n\nexport type TierMigrationCycleTrigger = \"extraction\" | \"maintenance\";\nexport interface TierMigrationCycleBudget {\n limit: number;\n scanLimit: number;\n minIntervalMs: number;\n}\n\nexport function defaultTierMigrationCycleBudget(\n config: QmdConfigProjection,\n trigger: TierMigrationCycleTrigger,\n): TierMigrationCycleBudget {\n if (trigger === \"extraction\") {\n const limit = 12;\n return {\n limit,\n scanLimit: limit * 4,\n minIntervalMs: 60_000,\n };\n }\n const limit = resolveQmdCapabilities(config).qmdTierAutoBackfill ? 200 : 50;\n return {\n limit,\n scanLimit: limit * 4,\n minIntervalMs: resolveQmdCapabilities(config).qmdTierAutoBackfill ? 120_000 : 300_000,\n };\n}\n\nfunction isoWeekId(d: Date): string {\n // ISO week based on Thursday\n const dt = new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()));\n const day = dt.getUTCDay() || 7;\n dt.setUTCDate(dt.getUTCDate() + 4 - day);\n const yearStart = new Date(Date.UTC(dt.getUTCFullYear(), 0, 1));\n const week = Math.ceil((((dt.getTime() - yearStart.getTime()) / 86400000) + 1) / 7);\n const yyyy = dt.getUTCFullYear();\n return `${yyyy}-W${String(week).padStart(2, \"0\")}`;\n}\n\nfunction isoMonthId(d: Date): string {\n return `${d.getUTCFullYear()}-${String(d.getUTCMonth() + 1).padStart(2, \"0\")}`;\n}\n\nfunction monthIdFromIsoWeek(weekId: string): string {\n const match = weekId.match(/^(\\d{4})-W(\\d{2})$/);\n if (!match) return isoMonthId(new Date());\n const year = Number(match[1]);\n const week = Number(match[2]);\n const jan4 = new Date(Date.UTC(year, 0, 4));\n const jan4Day = jan4.getUTCDay() || 7;\n const isoWeekOneMonday = new Date(jan4);\n isoWeekOneMonday.setUTCDate(jan4.getUTCDate() - (jan4Day - 1));\n const monday = new Date(isoWeekOneMonday);\n monday.setUTCDate(isoWeekOneMonday.getUTCDate() + (week - 1) * 7);\n return isoMonthId(monday);\n}\n\nfunction cadenceStaleWindowMs(cadence: \"daily\" | \"weekly\" | \"monthly\" | \"quarterly\"): number {\n switch (cadence) {\n case \"daily\":\n return 2 * 24 * 60 * 60 * 1000;\n case \"weekly\":\n return 10 * 24 * 60 * 60 * 1000;\n case \"monthly\":\n return 45 * 24 * 60 * 60 * 1000;\n case \"quarterly\":\n return 120 * 24 * 60 * 60 * 1000;\n default:\n return 45 * 24 * 60 * 60 * 1000;\n }\n}\n\nexport class CompoundingEngine {\n private readonly weeklyDir: string;\n private readonly rubricsDir: string;\n private readonly rubricsIndexPath: string;\n private readonly rubricsAgentsDir: string;\n private readonly rubricsWorkflowsDir: string;\n private readonly rubricsPath: string;\n private readonly mistakesPath: string;\n private readonly feedbackInboxPath: string;\n private readonly identityAuditWeeklyDir: string;\n private readonly identityAuditMonthlyDir: string;\n private readonly memoryActionEventsPath: string;\n\n constructor(\n private readonly config: PluginConfig,\n private readonly storage: StorageManager = new StorageManager(config.memoryDir),\n ) {\n this.weeklyDir = path.join(config.memoryDir, \"compounding\", \"weekly\");\n this.rubricsDir = path.join(config.memoryDir, \"compounding\", \"rubrics\");\n this.rubricsIndexPath = path.join(this.rubricsDir, \"index.json\");\n this.rubricsAgentsDir = path.join(this.rubricsDir, \"agents\");\n this.rubricsWorkflowsDir = path.join(this.rubricsDir, \"workflows\");\n this.rubricsPath = path.join(config.memoryDir, \"compounding\", \"rubrics.md\");\n this.mistakesPath = path.join(config.memoryDir, \"compounding\", \"mistakes.json\");\n this.feedbackInboxPath = path.join(resolveSharedContextDir(config), \"feedback\", \"inbox.jsonl\");\n this.identityAuditWeeklyDir = path.join(config.memoryDir, \"identity\", \"audits\", \"weekly\");\n this.identityAuditMonthlyDir = path.join(config.memoryDir, \"identity\", \"audits\", \"monthly\");\n this.memoryActionEventsPath = path.join(config.memoryDir, \"state\", \"memory-actions.jsonl\");\n }\n\n async ensureDirs(): Promise<void> {\n await mkdir(this.weeklyDir, { recursive: true });\n await mkdir(path.dirname(this.mistakesPath), { recursive: true });\n await mkdir(path.dirname(this.rubricsPath), { recursive: true });\n await mkdir(this.rubricsDir, { recursive: true });\n await mkdir(this.rubricsAgentsDir, { recursive: true });\n await mkdir(this.rubricsWorkflowsDir, { recursive: true });\n }\n\n async synthesizeWeekly(opts?: {\n weekId?: string;\n }): Promise<{\n weekId: string;\n reportPath: string;\n reportJsonPath: string;\n mistakesCount: number;\n rubricsPath: string;\n rubricsIndexPath: string;\n promotionCandidateCount: number;\n }> {\n await this.ensureDirs();\n const weekId = opts?.weekId ?? isoWeekId(new Date());\n\n const entries = await this.readFeedbackEntriesForWeek(weekId);\n const actionEvents = await this.readActionEventsForWeek(weekId);\n const actionPatterns = this.buildActionFailurePatterns(actionEvents);\n const outcomeSummary = this.buildActionOutcomeSummary(actionEvents);\n const previousMistakes = await this.readMistakes();\n const mistakes = this.buildMistakes(entries, actionPatterns, weekId, previousMistakes?.registry ?? []);\n const rubrics = this.buildRubricSnapshot(entries, outcomeSummary);\n let promotionCandidates = resolveConsolidationCapabilities(this.config).compoundingSemantic\n ? this.derivePromotionCandidates(outcomeSummary, mistakes.registry, rubrics)\n : [];\n if (this.config.cmcConsolidationEnabled) {\n try {\n const { deriveCausalPromotionCandidates, materializeAfterCausalConsolidation } = await import(\"../causal-consolidation.js\");\n const causalCandidates = await deriveCausalPromotionCandidates({\n memoryDir: this.config.memoryDir,\n causalTrajectoryStoreDir: this.config.causalTrajectoryStoreDir,\n gatewayConfig: this.config.gatewayConfig,\n gatewayAgentId: this.config.modelSource === \"gateway\" ? (this.config.gatewayAgentId || undefined) : undefined,\n modelChain: this.config.modelSource === \"gateway\" ? this.config.taskModelChain : undefined,\n workspaceDir: this.config.workspaceDir,\n pluginConfig: this.config,\n config: {\n minRecurrence: this.config.cmcConsolidationMinRecurrence,\n minSessions: this.config.cmcConsolidationMinSessions,\n successThreshold: this.config.cmcConsolidationSuccessThreshold,\n },\n });\n if (causalCandidates.length > 0) {\n promotionCandidates = [...promotionCandidates, ...causalCandidates];\n }\n // #378: fire the Codex materialize post-hook so\n // `codexMaterializeOnConsolidation` actually has a runtime effect\n // when the causal consolidation path runs. The helper silently no-ops\n // when the feature flag or the per-trigger toggle is off, when the\n // sentinel is missing, or when nothing has changed since the previous\n // run. Wrapped in its own try/catch so a failed materialize never\n // aborts weekly synthesis.\n try {\n await materializeAfterCausalConsolidation({\n config: this.config,\n memoryDir: this.config.memoryDir,\n });\n } catch (materializeError) {\n log.warn(\n `[cmc] Codex materialize post-hook failed (non-fatal): ${\n materializeError instanceof Error ? materializeError.message : String(materializeError)\n }`,\n );\n }\n } catch (error) {\n log.warn(`[cmc] causal consolidation in synthesizeWeekly failed (non-fatal): ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n // PEDC: Run calibration consolidation during weekly synthesis\n if (resolveConsolidationCapabilities(this.config).calibration) {\n try {\n const { runCalibrationConsolidation } = await import(\"../calibration.js\");\n const calRules = await runCalibrationConsolidation({\n memoryDir: this.config.memoryDir,\n gatewayConfig: this.config.gatewayConfig,\n gatewayAgentId: this.config.modelSource === \"gateway\" ? (this.config.gatewayAgentId || undefined) : undefined,\n modelChain: this.config.modelSource === \"gateway\" ? this.config.taskModelChain : undefined,\n workspaceDir: this.config.workspaceDir,\n });\n log.debug(`[calibration] weekly synthesis produced ${calRules.length} calibration rule(s)`);\n } catch (error) {\n log.warn(`[calibration] weekly consolidation failed (non-fatal): ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n const continuity = resolveConsolidationCapabilities(this.config).continuityAudit\n ? await this.readContinuityAuditReferences(weekId)\n : { monthId: monthIdFromIsoWeek(weekId), weeklyPath: null, monthlyPath: null };\n\n // Write weekly report (always, even if empty: \"day-one outcomes\").\n const reportPath = path.join(this.weeklyDir, `${weekId}.md`);\n const md = this.formatWeeklyReport(weekId, entries, mistakes.patterns, mistakes.details, continuity, outcomeSummary, promotionCandidates);\n await writeFile(reportPath, md, \"utf-8\");\n\n const reportJsonPath = path.join(this.weeklyDir, `${weekId}.json`);\n const weeklyArtifact: WeeklyCompoundingArtifact = {\n version: COMPOUNDING_VERSION,\n generatedAt: mistakes.updatedAt,\n weekId,\n feedback: {\n count: entries.length,\n byDecision: {\n approved: entries.filter((wrapped) => wrapped.entry.decision === \"approved\").length,\n approved_with_feedback: entries.filter((wrapped) => wrapped.entry.decision === \"approved_with_feedback\").length,\n rejected: entries.filter((wrapped) => wrapped.entry.decision === \"rejected\").length,\n },\n entries: entries.map((wrapped) => ({\n agent: wrapped.entry.agent,\n workflow: wrapped.entry.workflow ?? null,\n decision: wrapped.entry.decision,\n reason: wrapped.entry.reason,\n learning: wrapped.entry.learning?.trim() || null,\n outcome: wrapped.entry.outcome?.trim() || null,\n severity: wrapped.entry.severity ?? null,\n confidence: normalizeConfidence(wrapped.entry.confidence),\n tags: normalizeTags(wrapped.entry.tags),\n provenance: `${path.basename(wrapped.sourcePath)}:L${wrapped.sourceLine}#${wrapped.entryId}`,\n evidenceWindow: normalizeEvidenceWindow(wrapped.entry.evidenceWindowStart, wrapped.entry.evidenceWindowEnd),\n })),\n },\n mistakes: {\n count: mistakes.patterns.length,\n patterns: mistakes.patterns,\n registry: mistakes.registry,\n },\n rubrics,\n outcomes: outcomeSummary,\n promotionCandidates,\n continuity,\n };\n await writeFile(reportJsonPath, JSON.stringify(weeklyArtifact, null, 2) + \"\\n\", \"utf-8\");\n\n // Write stable rubric artifact.\n const rubricsMarkdown = this.formatRubrics(outcomeSummary, rubrics);\n await writeFile(this.rubricsPath, rubricsMarkdown, \"utf-8\");\n await writeFile(this.rubricsIndexPath, JSON.stringify(rubrics, null, 2) + \"\\n\", \"utf-8\");\n await this.syncRubricArtifacts(rubrics);\n\n // Update mistakes.json (always).\n await writeFile(\n this.mistakesPath,\n JSON.stringify({\n version: COMPOUNDING_VERSION,\n updatedAt: mistakes.updatedAt,\n patterns: mistakes.patterns,\n registry: mistakes.registry,\n }, null, 2) + \"\\n\",\n \"utf-8\",\n );\n\n log.info(\n `compounding: wrote weekly=${reportPath} weeklyJson=${reportJsonPath} rubrics=${this.rubricsPath} rubricsIndex=${this.rubricsIndexPath} mistakes=${this.mistakesPath}`,\n );\n return {\n weekId,\n reportPath,\n reportJsonPath,\n rubricsPath: this.rubricsPath,\n rubricsIndexPath: this.rubricsIndexPath,\n mistakesCount: mistakes.patterns.length,\n promotionCandidateCount: promotionCandidates.length,\n };\n }\n\n async promoteCandidate(opts: {\n weekId: string;\n candidateId: string;\n dryRun?: boolean;\n storage?: StorageManager;\n }): Promise<CompoundingPromotionReport> {\n const report: CompoundingPromotionReport = {\n enabled: resolveConsolidationCapabilities(this.config).compounding === true && resolveConsolidationCapabilities(this.config).compoundingSemantic === true,\n dryRun: opts.dryRun === true,\n weekId: opts.weekId,\n promoted: [],\n skipped: [],\n tombstoneBlocked: [],\n };\n if (!report.enabled) {\n report.skipped.push({ weekId: opts.weekId, candidateId: opts.candidateId, reason: \"disabled\" });\n return report;\n }\n\n const artifact = await this.readWeeklyArtifact(opts.weekId);\n if (!artifact) {\n report.skipped.push({ weekId: opts.weekId, candidateId: opts.candidateId, reason: \"weekly-artifact-missing\" });\n return report;\n }\n\n const candidate = artifact.promotionCandidates.find((entry) => entry.id === opts.candidateId);\n if (!candidate) {\n report.skipped.push({ weekId: opts.weekId, candidateId: opts.candidateId, reason: \"candidate-not-found\" });\n return report;\n }\n\n const content = normalizePromotedGuidanceContent(candidate.content);\n const persistedContent = sanitizeMemoryContent(content).text;\n const storage = opts.storage ?? new StorageManager(this.config.memoryDir);\n const existing = (await storage.readAllMemories()).find((memory) =>\n memory.frontmatter.category === candidate.category &&\n memory.frontmatter.status !== \"archived\" &&\n memory.frontmatter.status !== \"forgotten\" &&\n canonicalPromotionContentKey(memory.content) === canonicalPromotionContentKey(persistedContent)\n );\n if (existing) {\n report.skipped.push({\n weekId: opts.weekId,\n candidateId: opts.candidateId,\n reason: \"duplicate-guidance\",\n existingMemoryId: existing.frontmatter.id,\n });\n return report;\n }\n\n const tags = [\n \"compounding\",\n \"compounding-promotion\",\n `compounding-source-${candidate.sourceType}`,\n ...(candidate.agent ? [`agent:${stableSlug(candidate.agent)}`] : []),\n ...(candidate.workflow ? [`workflow:${stableSlug(candidate.workflow)}`] : []),\n ];\n const uniqueTags = [...new Set(tags)];\n const lineage = [`compounding:${opts.weekId}:${opts.candidateId}`];\n const confidence = clampPromotionScore(candidate.score);\n\n if (opts.dryRun === true) {\n report.promoted.push({\n id: `dry-run:${opts.weekId}:${opts.candidateId}`,\n candidateId: opts.candidateId,\n category: candidate.category,\n content: persistedContent,\n confidence,\n tags: uniqueTags,\n lineage,\n });\n return report;\n }\n\n const { id, tombstoneBlocked } = await storage.writeMemory(candidate.category, persistedContent, {\n source: \"compounding-promotion\",\n tags: uniqueTags,\n confidence,\n lineage,\n memoryKind: \"note\",\n });\n // #1645: a tombstone-blocked promotion lands pending_review (no active\n // copy) — divert it to the tombstoneBlocked list so the report never\n // claims a blocked write as a successfully promoted active memory.\n if (tombstoneBlocked) {\n report.tombstoneBlocked.push({\n id,\n candidateId: opts.candidateId,\n category: candidate.category,\n content: persistedContent,\n });\n return report;\n }\n report.promoted.push({\n id,\n candidateId: opts.candidateId,\n category: candidate.category,\n content: persistedContent,\n confidence,\n tags: uniqueTags,\n lineage,\n });\n return report;\n }\n\n async synthesizeContinuityAudit(opts?: {\n period?: \"weekly\" | \"monthly\";\n key?: string;\n }): Promise<{ period: \"weekly\" | \"monthly\"; key: string; reportPath: string }> {\n const period = opts?.period === \"monthly\" ? \"monthly\" : \"weekly\";\n const key = opts?.key?.trim() || (period === \"weekly\" ? isoWeekId(new Date()) : isoMonthId(new Date()));\n const nowIso = new Date().toISOString();\n const [identityAnchor, improvementLoopsRaw, openIncidents, closedIncidents, mistakes] = await Promise.all([\n this.readOptionalIdentityAnchorForAudit(),\n this.readOptionalImprovementLoopsForAudit(),\n this.readContinuityIncidentsForAudit(200, \"open\"),\n this.readContinuityIncidentsForAudit(200, \"closed\"),\n this.readMistakes(),\n ]);\n const anchorPresent = (identityAnchor ?? \"\").trim().length > 0;\n const improvementLoops = improvementLoopsRaw ? parseContinuityImprovementLoops(improvementLoopsRaw) : [];\n const activeLoops = improvementLoops.filter((loop) => loop.status === \"active\");\n const staleActiveLoops = activeLoops.filter((loop) => {\n const reviewedAt = Date.parse(loop.lastReviewed);\n if (!Number.isFinite(reviewedAt)) return true;\n return Date.now() - reviewedAt > cadenceStaleWindowMs(loop.cadence);\n });\n const hardeningCandidates: string[] = [];\n if (!anchorPresent) {\n hardeningCandidates.push(\"Create/update identity anchor baseline and verify recovery injection path.\");\n }\n if (openIncidents.length > 0) {\n hardeningCandidates.push(\n `Close or downgrade ${openIncidents.length} open continuity incident${openIncidents.length === 1 ? \"\" : \"s\"}.`,\n );\n }\n if (improvementLoops.length === 0) {\n hardeningCandidates.push(\"Initialize continuity improvement-loops register with cadence and kill conditions.\");\n } else if (staleActiveLoops.length > 0) {\n hardeningCandidates.push(\n `Review stale active continuity loop${staleActiveLoops.length === 1 ? \"\" : \"s\"}: ${staleActiveLoops\n .slice(0, 3)\n .map((loop) => loop.id)\n .join(\", \")}.`,\n );\n }\n if ((mistakes?.patterns.length ?? 0) > 0) {\n hardeningCandidates.push(\"Review latest compounding mistakes and convert one pattern into preventive continuity rule.\");\n }\n const nextAction = hardeningCandidates[0] ?? \"No critical drift detected; keep weekly/monthly continuity audit cadence.\";\n\n const lines: string[] = [\n `# Continuity Audit — ${period} ${key}`,\n \"\",\n `Generated: ${nowIso}`,\n `Scope: ${period}`,\n \"\",\n \"## Signal Summary\",\n `- Identity anchor present: ${anchorPresent ? \"yes\" : \"no\"}`,\n `- Improvement loops tracked: ${improvementLoops.length}`,\n `- Active improvement loops: ${activeLoops.length}`,\n `- Stale active loops: ${staleActiveLoops.length}`,\n `- Open incidents: ${openIncidents.length}`,\n `- Closed incidents: ${closedIncidents.length}`,\n `- Compounding mistake patterns: ${mistakes?.patterns.length ?? 0}`,\n \"\",\n \"## Drift Checks\",\n `- Identity anchor drift: ${anchorPresent ? \"pass\" : \"needs attention\"}`,\n `- Incident backlog: ${openIncidents.length === 0 ? \"pass\" : \"needs attention\"}`,\n `- Improvement-loop coverage: ${improvementLoops.length > 0 ? \"pass\" : \"needs attention\"}`,\n `- Improvement-loop freshness: ${staleActiveLoops.length === 0 ? \"pass\" : \"needs attention\"}`,\n \"\",\n \"## Stale Rule Detection\",\n `- Open incidents older than closure window: ${openIncidents.length > 0 ? \"possible\" : \"none detected\"}`,\n `- Stale active continuity loops: ${staleActiveLoops.length > 0 ? staleActiveLoops.map((l) => l.id).join(\", \") : \"none detected\"}`,\n `- Preventive rule coverage on closed incidents: ${\n closedIncidents.some((i) => (i.preventiveRule ?? \"\").trim().length > 0) ? \"present\" : \"not detected\"\n }`,\n \"\",\n \"## Next Hardening Action\",\n `- ${nextAction}`,\n \"\",\n \"## Open Incident IDs\",\n ...(openIncidents.length > 0 ? openIncidents.slice(0, 20).map((i) => `- ${i.id}`) : [\"- (none)\"]),\n \"\",\n ];\n\n const reportPath = await this.storage.writeIdentityAudit(period, key, lines.join(\"\\n\"));\n return { period, key, reportPath };\n }\n\n async readMistakes(): Promise<MistakesFile | null> {\n try {\n const raw = await readFile(this.mistakesPath, \"utf-8\");\n const parsed = JSON.parse(raw) as MistakesFile;\n if (!parsed || !Array.isArray(parsed.patterns)) return null;\n if (!Array.isArray(parsed.registry)) {\n const updatedAt = typeof parsed.updatedAt === \"string\" && parsed.updatedAt.length > 0\n ? parsed.updatedAt\n : new Date(0).toISOString();\n parsed.registry = parsed.patterns.map((pattern) => {\n const metadata = inferLegacyMistakeMetadata(pattern);\n return {\n id: stableMistakeId(metadata.category, pattern, metadata.agent, metadata.workflow),\n pattern,\n category: metadata.category,\n status: \"active\",\n agent: metadata.agent,\n workflow: metadata.workflow,\n tags: [],\n severity: null,\n confidence: null,\n outcome: null,\n provenance: [],\n firstSeenAt: updatedAt,\n lastSeenAt: updatedAt,\n recurrenceCount: 1,\n lastWeekId: isoWeekId(new Date(updatedAt)),\n evidenceWindow: { start: null, end: null },\n };\n });\n }\n return parsed;\n } catch {\n return null;\n }\n }\n\n async readRubrics(): Promise<RubricSnapshot | null> {\n try {\n const raw = await readFile(this.rubricsIndexPath, \"utf-8\");\n const parsed = JSON.parse(raw) as RubricSnapshot;\n if (!parsed || !Array.isArray(parsed.agents) || !Array.isArray(parsed.workflows)) return null;\n parsed.agents = parsed.agents.map((entry) => this.normalizeRubricEntry(entry));\n parsed.workflows = parsed.workflows.map((entry) => this.normalizeRubricEntry(entry));\n return parsed;\n } catch {\n return null;\n }\n }\n\n async readWeeklyArtifact(weekId: string): Promise<WeeklyCompoundingArtifact | null> {\n try {\n const raw = await readFile(path.join(this.weeklyDir, `${weekId}.json`), \"utf-8\");\n const parsed = JSON.parse(raw) as WeeklyCompoundingArtifact;\n if (\n !parsed ||\n parsed.weekId !== weekId ||\n !Array.isArray(parsed.promotionCandidates)\n ) {\n return null;\n }\n return parsed;\n } catch {\n return null;\n }\n }\n\n async buildRecallSection(\n query: string,\n opts?: { maxPatterns?: number; maxRubrics?: number },\n ): Promise<string | null> {\n const [mistakes, rubrics] = await Promise.all([\n this.readMistakes(),\n this.readRubrics(),\n ]);\n const maxPatterns = Math.max(0, Math.floor(opts?.maxPatterns ?? 40));\n const maxRubrics = Math.max(0, Math.floor(opts?.maxRubrics ?? 4));\n const queryTokens = tokenizeRecallQuery(query);\n\n const activePatterns = (mistakes?.registry ?? [])\n .filter((entry) => entry.status === \"active\")\n .sort((a, b) =>\n b.recurrenceCount - a.recurrenceCount ||\n b.lastSeenAt.localeCompare(a.lastSeenAt) ||\n a.pattern.localeCompare(b.pattern),\n );\n const topPatterns = activePatterns.slice(0, maxPatterns);\n\n const allRubrics = [\n ...(rubrics?.workflows ?? []),\n ...(rubrics?.agents ?? []),\n ];\n const scoredRubrics = allRubrics\n .map((entry) => ({\n entry,\n score: this.scoreRubricForQuery(entry, queryTokens),\n }))\n .sort((a, b) =>\n b.score - a.score ||\n b.entry.observations.length - a.entry.observations.length ||\n a.entry.subject.localeCompare(b.entry.subject),\n );\n const topRubrics = scoredRubrics\n .filter((item) => item.score > 0 || queryTokens.length === 0)\n .slice(0, maxRubrics)\n .map((item) => item.entry);\n\n if (topPatterns.length === 0 && topRubrics.length === 0) return null;\n\n const lines: string[] = [\n \"## Institutional Learning (Compounded)\",\n \"\",\n ];\n\n if (topPatterns.length > 0) {\n lines.push(\"Avoid repeating these patterns:\");\n for (const entry of topPatterns) {\n const scope = entry.workflow ?? entry.agent ?? null;\n const metadata = [`recurrence=${entry.recurrenceCount}`];\n if (scope) metadata.push(`scope=${scope}`);\n lines.push(`- ${entry.pattern} _(${metadata.join(\", \")})_`);\n }\n lines.push(\"\");\n }\n\n if (topRubrics.length > 0) {\n lines.push(\"Active rubrics:\");\n for (const rubric of topRubrics) {\n const notes = rubric.observations.slice(0, 2).join(\"; \");\n lines.push(`- ${rubric.kind} ${rubric.subject}: ${notes}`);\n }\n }\n\n return lines.join(\"\\n\");\n }\n\n tierMigrationCycleBudget(trigger: TierMigrationCycleTrigger): TierMigrationCycleBudget {\n return defaultTierMigrationCycleBudget(this.config, trigger);\n }\n\n private async readFeedbackEntriesForWeek(weekId: string): Promise<FeedbackEntryWithProvenance[]> {\n // Minimal implementation: includes entries where date starts with any day in the ISO week.\n // We approximate by taking all entries and filtering by computed isoWeekId(date).\n const out: FeedbackEntryWithProvenance[] = [];\n try {\n const raw = await readFile(this.feedbackInboxPath, \"utf-8\");\n const lines = raw.split(\"\\n\");\n for (let idx = 0; idx < lines.length; idx += 1) {\n const line = lines[idx];\n if (!line.trim()) continue;\n try {\n const obj = JSON.parse(line);\n const parsed = SharedFeedbackEntrySchema.safeParse(obj);\n if (!parsed.success) continue;\n const d = new Date(parsed.data.date);\n if (!Number.isFinite(d.getTime())) continue;\n if (isoWeekId(d) !== weekId) continue;\n const sourceLine = idx + 1;\n out.push({\n entry: parsed.data,\n sourceLine,\n sourcePath: this.feedbackInboxPath,\n entryId: `${parsed.data.agent}-${parsed.data.date}-${sourceLine}`.replace(/[^a-zA-Z0-9._:-]/g, \"_\"),\n });\n } catch {\n // ignore\n }\n }\n } catch {\n // missing feedback is normal\n }\n return out;\n }\n\n private buildActionFailurePatterns(events: WeeklyActionEvent[]): string[] {\n const out: string[] = [];\n for (const event of events) {\n const failed = event.outcome === \"failed\" || event.outcome === \"skipped\";\n if (!failed && event.policyDecision === null) continue;\n const suffix = event.reason && event.reason.trim().length > 0\n ? ` - ${event.reason.trim().slice(0, 140)}`\n : \"\";\n out.push(\n `memory-action/${event.namespace}: ${event.action} ${event.outcome}${event.policyDecision ? `/${event.policyDecision}` : \"\"}${suffix}`,\n );\n }\n return out;\n }\n\n private async readActionEventsForWeek(weekId: string): Promise<WeeklyActionEvent[]> {\n const out: WeeklyActionEvent[] = [];\n const rows = await this.storage.readMemoryActionEventRows(Number.MAX_SAFE_INTEGER);\n for (const row of rows) {\n const event = row.event;\n const ts = new Date(event.timestamp);\n if (!Number.isFinite(ts.getTime()) || isoWeekId(ts) !== weekId) continue;\n out.push({\n line: row.line,\n action: event.action,\n outcome: event.outcome,\n policyDecision: event.policyDecision === \"deny\" || event.policyDecision === \"defer\"\n ? event.policyDecision\n : null,\n namespace: typeof event.namespace === \"string\" && event.namespace.length > 0 ? event.namespace : \"default\",\n reason: typeof event.reason === \"string\" ? event.reason : null,\n });\n }\n return out;\n }\n\n private buildActionOutcomeSummary(events: WeeklyActionEvent[]): ActionOutcomeSummary[] {\n const byAction = new Map<string, { counts: ActionOutcomeCounts; provenance: Set<string> }>();\n for (const event of events) {\n const key = event.action;\n const acc = byAction.get(key) ?? {\n counts: { applied: 0, skipped: 0, failed: 0 },\n provenance: new Set<string>(),\n };\n if (event.outcome === \"applied\") acc.counts.applied += 1;\n else if (event.outcome === \"skipped\") acc.counts.skipped += 1;\n else acc.counts.failed += 1;\n acc.provenance.add(`${path.basename(this.memoryActionEventsPath)}:L${event.line}`);\n byAction.set(key, acc);\n }\n\n const out: ActionOutcomeSummary[] = [];\n for (const [action, data] of byAction.entries()) {\n const total = data.counts.applied + data.counts.skipped + data.counts.failed;\n if (total <= 0) continue;\n // Conservative weighting: reward applied, penalize skipped/failed.\n const weightedScore = Number((((data.counts.applied * 1) - (data.counts.skipped * 0.5) - (data.counts.failed * 1.5)) / total).toFixed(3));\n out.push({\n action,\n counts: data.counts,\n total,\n weightedScore,\n provenance: [...data.provenance].sort().slice(0, 8),\n });\n }\n out.sort((a, b) => b.total - a.total || b.weightedScore - a.weightedScore || a.action.localeCompare(b.action));\n return out;\n }\n\n private derivePromotionCandidates(\n summary: ActionOutcomeSummary[],\n mistakes: MistakeRegistryEntry[],\n rubrics: RubricSnapshot,\n ): PromotionCandidate[] {\n const deduped = new Map<string, PromotionCandidate>();\n const upsert = (candidate: PromotionCandidate) => {\n const key = `${candidate.category}:${canonicalPromotionContentKey(candidate.content)}`;\n const existing = deduped.get(key);\n if (!existing) {\n deduped.set(key, candidate);\n return;\n }\n const mergedProvenance = [...new Set([...existing.provenance, ...candidate.provenance])];\n if (candidate.score > existing.score) {\n deduped.set(key, {\n ...candidate,\n provenance: mergedProvenance,\n });\n return;\n }\n existing.provenance = mergedProvenance;\n };\n\n for (const item of summary) {\n if (item.total < 3) continue;\n if (item.weightedScore < 0.3) continue;\n const content = normalizePromotedGuidanceContent(\n `Prefer ${item.action} when the same workflow recurs; this week's outcomes were applied=${item.counts.applied}, skipped=${item.counts.skipped}, failed=${item.counts.failed}.`,\n );\n upsert({\n id: stablePromotionCandidateId(\"action-outcome\", item.action, content),\n sourceType: \"action-outcome\",\n subject: item.action,\n category: promotionCategoryForContent(content),\n content,\n score: item.weightedScore,\n rationale: \"High applied ratio with low failure/skips in weekly outcome telemetry.\",\n outcome: item.counts,\n provenance: item.provenance,\n agent: null,\n workflow: \"memory-actions\",\n });\n }\n\n for (const entry of mistakes) {\n if (entry.status !== \"active\") continue;\n if (entry.recurrenceCount < 2) continue;\n const content = normalizePromotedGuidanceContent(lessonContentFromPattern(entry.pattern, entry.agent));\n if (content.length === 0) continue;\n const confidence = entry.confidence ?? 0.75;\n const score = Number(Math.min(0.97, 0.45 + Math.min(entry.recurrenceCount, 6) * 0.08 + confidence * 0.15).toFixed(3));\n upsert({\n id: stablePromotionCandidateId(\"mistake-pattern\", entry.id, content),\n sourceType: \"mistake-pattern\",\n subject: entry.pattern,\n category: promotionCategoryForContent(content),\n content,\n score,\n rationale: `Recurring lesson still active after ${entry.recurrenceCount} confirmations in the mistake registry.`,\n outcome: null,\n provenance: entry.provenance.length > 0 ? entry.provenance : [`mistakes.json#${entry.id}`],\n agent: entry.agent,\n workflow: entry.workflow,\n });\n }\n\n for (const rubric of [...rubrics.workflows, ...rubrics.agents]) {\n for (const observation of this.getRubricObservationEntries(rubric)) {\n if (this.isSyntheticOutcomeRubricObservation(observation.note)) continue;\n const evidenceCount = observation.provenance.length;\n if (evidenceCount < 2) continue;\n const content = normalizePromotedGuidanceContent(observation.note);\n if (content.length === 0) continue;\n const score = Number(Math.min(0.95, 0.5 + Math.min(evidenceCount, 5) * 0.08).toFixed(3));\n upsert({\n id: stablePromotionCandidateId(\"rubric\", `${rubric.id}:${observation.note}`, content),\n sourceType: \"rubric\",\n subject: `${rubric.kind}:${rubric.subject}`,\n category: promotionCategoryForContent(content),\n content,\n score,\n rationale: `Rubric guidance repeated across ${evidenceCount} supporting observations.`,\n outcome: null,\n provenance: observation.provenance,\n agent: rubric.kind === \"agent\" ? rubric.subject : null,\n workflow: rubric.kind === \"workflow\" ? rubric.subject : null,\n });\n }\n }\n\n return [...deduped.values()]\n .sort((a, b) => b.score - a.score || a.subject.localeCompare(b.subject))\n .slice(0, 10);\n }\n\n private buildMistakes(\n entries: FeedbackEntryWithProvenance[],\n actionPatterns: string[] = [],\n weekId: string,\n previousRegistry: MistakeRegistryEntry[] = [],\n ): MistakesFile & { details: PatternWithProvenance[]; registry: MistakeRegistryEntry[] } {\n const patterns: PatternWithProvenance[] = [];\n const evidenceByPattern = new Map<string, {\n category: \"feedback\" | \"action\";\n agent: string | null;\n workflow: string | null;\n tags: Set<string>;\n severity: CompoundingEntrySeverity | null;\n confidence: number | null;\n outcome: string | null;\n timestamps: string[];\n evidenceWindow: EvidenceWindow;\n }>();\n\n for (const wrapped of entries) {\n const e = wrapped.entry;\n const pattern = e.learning && e.learning.trim().length > 0\n ? `${e.agent}: ${e.learning.trim()}`\n : e.decision === \"rejected\"\n ? `${e.agent}: ${e.reason.trim()}`.slice(0, 240)\n : null;\n if (!pattern) continue;\n const provenance = [`${path.basename(wrapped.sourcePath)}:L${wrapped.sourceLine}#${wrapped.entryId}`];\n patterns.push({ pattern, provenance });\n\n const previous = evidenceByPattern.get(pattern) ?? {\n category: \"feedback\" as const,\n agent: e.agent,\n workflow: e.workflow ?? null,\n tags: new Set<string>(),\n severity: e.severity ?? null,\n confidence: normalizeConfidence(e.confidence),\n outcome: e.outcome?.trim() || null,\n timestamps: [],\n evidenceWindow: normalizeEvidenceWindow(e.evidenceWindowStart, e.evidenceWindowEnd),\n };\n for (const tag of normalizeTags(e.tags)) previous.tags.add(tag);\n previous.timestamps.push(e.date);\n if (previous.workflow === null && e.workflow) previous.workflow = e.workflow;\n if (previous.severity === null && e.severity) previous.severity = e.severity;\n if (previous.confidence === null) previous.confidence = normalizeConfidence(e.confidence);\n if (previous.outcome === null && e.outcome) previous.outcome = e.outcome.trim();\n const nextEvidenceWindow = normalizeEvidenceWindow(e.evidenceWindowStart, e.evidenceWindowEnd);\n previous.evidenceWindow = mergeEvidenceWindows(previous.evidenceWindow, nextEvidenceWindow);\n evidenceByPattern.set(pattern, previous);\n }\n\n for (const pattern of actionPatterns) {\n patterns.push({ pattern, provenance: [`${path.basename(this.memoryActionEventsPath)}:*`] });\n const previous = evidenceByPattern.get(pattern) ?? {\n category: \"action\" as const,\n agent: null,\n workflow: \"memory-actions\",\n tags: new Set<string>(),\n severity: \"medium\" as CompoundingEntrySeverity,\n confidence: null,\n outcome: null,\n timestamps: [],\n evidenceWindow: { start: null, end: null },\n };\n evidenceByPattern.set(pattern, previous);\n }\n\n const byPattern = new Map<string, Set<string>>();\n for (const item of patterns) {\n const existing = byPattern.get(item.pattern) ?? new Set<string>();\n for (const provenance of item.provenance) existing.add(provenance);\n byPattern.set(item.pattern, existing);\n }\n\n const details = [...byPattern.entries()]\n .map(([pattern, provenance]) => ({ pattern, provenance: [...provenance].sort() }))\n .slice(0, 500);\n const previousById = new Map(previousRegistry.map((entry) => [entry.id, entry]));\n const previousByPattern = new Map(previousRegistry.map((entry) => [entry.pattern, entry]));\n const registry: MistakeRegistryEntry[] = details.map((detail) => {\n const evidence = evidenceByPattern.get(detail.pattern);\n const id = stableMistakeId(\n evidence?.category ?? \"feedback\",\n detail.pattern,\n evidence?.agent ?? null,\n evidence?.workflow ?? null,\n );\n const previous = previousById.get(id) ?? previousByPattern.get(detail.pattern);\n const timestamps = (evidence?.timestamps ?? []).filter((value) => typeof value === \"string\" && value.length > 0).sort();\n const firstSeenAt = previous?.firstSeenAt ?? timestamps[0] ?? new Date().toISOString();\n const lastSeenAt = timestamps[timestamps.length - 1] ?? previous?.lastSeenAt ?? firstSeenAt;\n return {\n id,\n pattern: detail.pattern,\n category: evidence?.category ?? \"feedback\",\n status: \"active\" as const,\n agent: evidence?.agent ?? null,\n workflow: evidence?.workflow ?? null,\n tags: evidence ? [...evidence.tags].sort() : [],\n severity: evidence?.severity ?? null,\n confidence: evidence?.confidence ?? null,\n outcome: evidence?.outcome ?? null,\n provenance: detail.provenance,\n firstSeenAt,\n lastSeenAt,\n recurrenceCount: previous?.lastWeekId === weekId ? previous.recurrenceCount : (previous?.recurrenceCount ?? 0) + 1,\n lastWeekId: weekId,\n evidenceWindow: evidence?.evidenceWindow ?? { start: null, end: null },\n retiredAt: null,\n } satisfies MistakeRegistryEntry;\n });\n\n const seenIds = new Set(registry.map((entry) => entry.id));\n const seenPatterns = new Set(registry.map((entry) => entry.pattern));\n for (const previous of previousRegistry) {\n if (seenIds.has(previous.id) || seenPatterns.has(previous.pattern)) continue;\n const staleWeeks = weekIdToIndex(weekId) - weekIdToIndex(previous.lastWeekId);\n registry.push({\n ...previous,\n status: staleWeeks >= RETIREMENT_WINDOW_WEEKS ? \"retired\" : previous.status,\n retiredAt: staleWeeks >= RETIREMENT_WINDOW_WEEKS\n ? previous.retiredAt ?? new Date().toISOString()\n : previous.retiredAt ?? null,\n });\n }\n\n registry.sort((a, b) =>\n Number(b.status === \"active\") - Number(a.status === \"active\") ||\n b.recurrenceCount - a.recurrenceCount ||\n b.lastSeenAt.localeCompare(a.lastSeenAt) ||\n a.pattern.localeCompare(b.pattern),\n );\n\n return {\n version: COMPOUNDING_VERSION,\n updatedAt: new Date().toISOString(),\n patterns: details.map((d) => d.pattern),\n details,\n registry,\n };\n }\n\n private formatWeeklyReport(\n weekId: string,\n entries: FeedbackEntryWithProvenance[],\n patterns: string[],\n patternDetails: PatternWithProvenance[],\n continuity: { monthId: string; weeklyPath: string | null; monthlyPath: string | null },\n outcomeSummary: ActionOutcomeSummary[],\n promotionCandidates: PromotionCandidate[],\n ): string {\n const byAgent = new Map<string, FeedbackEntryWithProvenance[]>();\n for (const wrapped of entries) {\n const list = byAgent.get(wrapped.entry.agent) ?? [];\n list.push(wrapped);\n byAgent.set(wrapped.entry.agent, list);\n }\n\n const lines: string[] = [\n `# Weekly Compounding — ${weekId}`,\n \"\",\n \"This file is generated by Engram's compounding engine (v5.0).\",\n \"\",\n \"## Summary\",\n `- Feedback entries: ${entries.length}`,\n `- Mistake patterns: ${patterns.length}`,\n \"\",\n \"## By Agent\",\n ];\n\n if (byAgent.size === 0) {\n lines.push(\"- (none)\");\n } else {\n for (const [agent, list] of Array.from(byAgent.entries()).sort((a, b) => a[0].localeCompare(b[0]))) {\n const approved = list.filter((e) => e.entry.decision === \"approved\").length;\n const awf = list.filter((e) => e.entry.decision === \"approved_with_feedback\").length;\n const rejected = list.filter((e) => e.entry.decision === \"rejected\").length;\n lines.push(`### ${agent}`);\n lines.push(`- approved: ${approved}`);\n lines.push(`- approved_with_feedback: ${awf}`);\n lines.push(`- rejected: ${rejected}`);\n const provenance = list\n .slice(0, 3)\n .map((e) => `${path.basename(e.sourcePath)}:L${e.sourceLine}#${e.entryId}`);\n if (provenance.length > 0) {\n lines.push(`- provenance: ${provenance.join(\", \")}`);\n }\n lines.push(\"\");\n }\n }\n\n lines.push(\"## Patterns (Avoid / Prefer)\");\n if (patterns.length === 0) {\n lines.push(\"- (none yet)\");\n } else {\n const detailMap = new Map(patternDetails.map((d) => [d.pattern, d.provenance]));\n for (const p of patterns.slice(0, 100)) {\n const provenance = detailMap.get(p) ?? [];\n if (provenance.length > 0) {\n lines.push(`- ${p} _(source: ${provenance.join(\", \")})_`);\n } else {\n lines.push(`- ${p}`);\n }\n }\n }\n lines.push(\"\");\n\n lines.push(\"## Outcome Weighting\");\n if (outcomeSummary.length === 0) {\n lines.push(\"- (no action outcomes recorded this week)\");\n } else {\n for (const item of outcomeSummary.slice(0, 20)) {\n lines.push(\n `- ${item.action}: applied=${item.counts.applied}, skipped=${item.counts.skipped}, failed=${item.counts.failed}, weight=${item.weightedScore} _(source: ${item.provenance.join(\", \")})_`,\n );\n }\n }\n lines.push(\"\");\n\n if (resolveConsolidationCapabilities(this.config).compoundingSemantic) {\n lines.push(\"## Promotion Candidates (Advisory)\");\n if (promotionCandidates.length === 0) {\n lines.push(\"- (no advisory promotion candidates this week)\");\n } else {\n for (const candidate of promotionCandidates) {\n const outcomeSummaryText = candidate.outcome\n ? ` outcomes[a=${candidate.outcome.applied}, s=${candidate.outcome.skipped}, f=${candidate.outcome.failed}]`\n : \"\";\n lines.push(\n `- [${candidate.sourceType}] ${candidate.subject} -> ${candidate.content} (category=${candidate.category}, score=${candidate.score}, id=${candidate.id}): ${candidate.rationale}${outcomeSummaryText} _(source: ${candidate.provenance.join(\", \")})_`,\n );\n }\n }\n lines.push(\"\");\n lines.push(\"_Advisory only: no automatic promotion write is performed by this report. Use `compounding_promote_candidate` or `openclaw engram compounding-promote` to persist one manually._\");\n lines.push(\"\");\n }\n\n if (resolveConsolidationCapabilities(this.config).continuityAudit) {\n lines.push(\"## Continuity Audits\");\n if (continuity.weeklyPath) {\n lines.push(`- weekly: ${continuity.weeklyPath}`);\n } else {\n lines.push(`- weekly: (missing for ${weekId})`);\n }\n if (continuity.monthlyPath) {\n lines.push(`- monthly: ${continuity.monthlyPath}`);\n } else {\n lines.push(`- monthly: (missing for ${continuity.monthId})`);\n }\n lines.push(\"\");\n }\n\n return lines.join(\"\\n\");\n }\n\n private buildRubricSnapshot(\n entries: FeedbackEntryWithProvenance[],\n outcomeSummary: ActionOutcomeSummary[],\n ): RubricSnapshot {\n const updatedAt = new Date().toISOString();\n const byAgent = new Map<string, RubricSnapshotEntry>();\n const byWorkflow = new Map<string, RubricSnapshotEntry>();\n\n for (const wrapped of entries) {\n const note = ((wrapped.entry.learning && wrapped.entry.learning.trim().length > 0)\n ? wrapped.entry.learning\n : wrapped.entry.decision === \"rejected\"\n ? wrapped.entry.reason\n : \"\").trim();\n if (!note) continue;\n const provenance = `${path.basename(wrapped.sourcePath)}:L${wrapped.sourceLine}#${wrapped.entryId}`;\n const agentEntry = byAgent.get(wrapped.entry.agent) ?? {\n id: stableRubricId(\"agent\", wrapped.entry.agent),\n kind: \"agent\" as const,\n subject: wrapped.entry.agent,\n observations: [],\n tags: [],\n provenance: [],\n observationEntries: [],\n updatedAt,\n };\n this.addRubricObservation(agentEntry, note, provenance);\n agentEntry.tags = normalizeTags([...agentEntry.tags, ...normalizeTags(wrapped.entry.tags)]);\n byAgent.set(wrapped.entry.agent, agentEntry);\n\n const workflow = wrapped.entry.workflow?.trim();\n if (!workflow) continue;\n const workflowEntry = byWorkflow.get(workflow) ?? {\n id: stableRubricId(\"workflow\", workflow),\n kind: \"workflow\" as const,\n subject: workflow,\n observations: [],\n tags: [],\n provenance: [],\n observationEntries: [],\n updatedAt,\n };\n this.addRubricObservation(workflowEntry, note, provenance);\n workflowEntry.tags = normalizeTags([...workflowEntry.tags, ...normalizeTags(wrapped.entry.tags)]);\n byWorkflow.set(workflow, workflowEntry);\n }\n\n for (const item of outcomeSummary) {\n const workflowEntry = byWorkflow.get(item.action) ?? {\n id: stableRubricId(\"workflow\", item.action),\n kind: \"workflow\" as const,\n subject: item.action,\n observations: [],\n tags: [],\n provenance: [],\n observationEntries: [],\n updatedAt,\n };\n this.addRubricObservation(\n workflowEntry,\n `Outcome weight=${item.weightedScore} (applied=${item.counts.applied}, skipped=${item.counts.skipped}, failed=${item.counts.failed})`,\n ...item.provenance,\n );\n byWorkflow.set(item.action, workflowEntry);\n }\n\n return {\n updatedAt,\n agents: [...byAgent.values()].sort((a, b) => a.subject.localeCompare(b.subject)),\n workflows: [...byWorkflow.values()].sort((a, b) => a.subject.localeCompare(b.subject)),\n };\n }\n\n private formatRubrics(outcomeSummary: ActionOutcomeSummary[], snapshot: RubricSnapshot): string {\n const lines: string[] = [\n \"# Compounding Rubrics\",\n \"\",\n `Generated: ${snapshot.updatedAt}`,\n \"\",\n \"Stable, deterministic rubric snapshot generated from weekly feedback + action outcomes.\",\n \"\",\n ];\n\n lines.push(\"## Agent Rubrics\");\n if (snapshot.agents.length === 0) {\n lines.push(\"- (none yet)\");\n } else {\n for (const rubric of snapshot.agents) {\n lines.push(`### ${rubric.subject}`);\n const observations = this.getRubricObservationEntries(rubric).slice(0, 8);\n if (observations.length === 0) {\n lines.push(\"- No rubric deltas this week.\");\n } else {\n for (const observation of observations) {\n const provenance = observation.provenance.join(\", \");\n lines.push(`- ${observation.note}${provenance ? ` _(source: ${provenance})_` : \"\"}`);\n }\n }\n lines.push(\"\");\n }\n }\n\n lines.push(\"## Workflow Rubrics\");\n if (snapshot.workflows.length === 0) {\n lines.push(\"- (none yet)\");\n } else {\n for (const rubric of snapshot.workflows) {\n lines.push(`### ${rubric.subject}`);\n for (const observation of this.getRubricObservationEntries(rubric).slice(0, 8)) {\n const provenance = observation.provenance.join(\", \");\n lines.push(`- ${observation.note}${provenance ? ` _(source: ${provenance})_` : \"\"}`);\n }\n lines.push(\"\");\n }\n }\n\n lines.push(\"## Action Outcome Signals\");\n if (outcomeSummary.length === 0) {\n lines.push(\"- (none yet)\");\n } else {\n for (const item of outcomeSummary.slice(0, 20)) {\n lines.push(\n `- ${item.action}: weight=${item.weightedScore} (applied=${item.counts.applied}, skipped=${item.counts.skipped}, failed=${item.counts.failed})`,\n );\n }\n }\n lines.push(\"\");\n return lines.join(\"\\n\");\n }\n\n private async syncRubricArtifacts(snapshot: RubricSnapshot): Promise<void> {\n await this.replaceRubricDirectory(this.rubricsAgentsDir, snapshot.agents);\n await this.replaceRubricDirectory(this.rubricsWorkflowsDir, snapshot.workflows);\n }\n\n private async replaceRubricDirectory(dir: string, entries: RubricSnapshotEntry[]): Promise<void> {\n await mkdir(dir, { recursive: true });\n try {\n const names = await readdir(dir);\n await Promise.all(\n names.filter((name) => name.endsWith(\".md\")).map((name) => unlink(path.join(dir, name)).catch(() => undefined)),\n );\n } catch {\n // fail-open\n }\n\n const slugCollisions = new Map<string, number>();\n for (const entry of entries) {\n const slug = stableSlug(entry.subject);\n slugCollisions.set(slug, (slugCollisions.get(slug) ?? 0) + 1);\n }\n\n await Promise.all(entries.map(async (entry) => {\n const observationEntries = this.getRubricObservationEntries(entry);\n const body = [\n `# ${entry.kind === \"agent\" ? \"Agent\" : \"Workflow\"} Rubric — ${entry.subject}`,\n \"\",\n `Updated: ${entry.updatedAt}`,\n \"\",\n \"## Observations\",\n ...(observationEntries.length > 0\n ? observationEntries.map((item) => `- ${item.note}`)\n : [\"- (none yet)\"]),\n \"\",\n \"## Provenance\",\n ...(entry.provenance.length > 0 ? entry.provenance.map((item) => `- ${item}`) : [\"- (none yet)\"]),\n \"\",\n ].join(\"\\n\");\n const fileName = rubricArtifactFileName(entry, slugCollisions);\n await writeFile(path.join(dir, fileName), body, \"utf-8\");\n }));\n }\n\n private scoreRubricForQuery(entry: RubricSnapshotEntry, queryTokens: string[]): number {\n if (queryTokens.length === 0) return entry.observations.length;\n const haystack = [entry.subject, ...entry.observations, ...entry.tags].join(\" \").toLowerCase();\n let score = 0;\n for (const token of queryTokens) {\n if (haystack.includes(token)) score += 2;\n if (entry.subject.toLowerCase().includes(token)) score += 2;\n }\n if (score === 0) return 0;\n return score + Math.min(entry.observations.length, 3);\n }\n\n private normalizeRubricEntry(entry: RubricSnapshotEntry): RubricSnapshotEntry {\n const normalizedEntries = this.getRubricObservationEntries(entry);\n return {\n ...entry,\n observations: normalizedEntries.map((item) => item.note),\n provenance: [...new Set(normalizedEntries.flatMap((item) => item.provenance))],\n observationEntries: normalizedEntries,\n };\n }\n\n private getRubricObservationEntries(entry: RubricSnapshotEntry): Array<{ note: string; provenance: string[] }> {\n if (Array.isArray(entry.observationEntries) && entry.observationEntries.length > 0) {\n return entry.observationEntries.map((item) => ({\n note: item.note,\n provenance: [...new Set(item.provenance)].sort(),\n }));\n }\n\n return entry.observations.map((note, index) => ({\n note,\n provenance: entry.provenance[index] ? [entry.provenance[index]] : (entry.provenance[0] ? [entry.provenance[0]] : []),\n }));\n }\n\n private isSyntheticOutcomeRubricObservation(note: string): boolean {\n return note.trimStart().startsWith(\"Outcome weight=\");\n }\n\n private addRubricObservation(entry: RubricSnapshotEntry, note: string, ...provenance: string[]): void {\n const normalized = this.normalizeRubricEntry(entry);\n const existing = normalized.observationEntries?.find((item) => item.note === note);\n if (existing) {\n existing.provenance = [...new Set([...existing.provenance, ...provenance])].sort();\n } else {\n normalized.observationEntries?.push({\n note,\n provenance: [...new Set(provenance)].sort(),\n });\n }\n entry.observationEntries = normalized.observationEntries;\n entry.observations = normalized.observationEntries?.map((item) => item.note) ?? [];\n entry.provenance = [...new Set((normalized.observationEntries ?? []).flatMap((item) => item.provenance))];\n }\n\n private async readOptionalIdentityAnchorForAudit(): Promise<string | null> {\n try {\n return await this.storage.readIdentityAnchor();\n } catch {\n return null;\n }\n }\n\n private async readOptionalImprovementLoopsForAudit(): Promise<string | null> {\n try {\n return await this.storage.readIdentityImprovementLoops();\n } catch {\n return null;\n }\n }\n\n private async readContinuityIncidentsForAudit(\n limit: number,\n state: \"open\" | \"closed\",\n ): Promise<ContinuityIncidentRecord[]> {\n try {\n return await this.storage.readContinuityIncidents(limit, state);\n } catch {\n return [];\n }\n }\n\n private async readOptionalIdentityAuditForReference(\n period: \"weekly\" | \"monthly\",\n key: string,\n ): Promise<string | null> {\n try {\n return await this.storage.readIdentityAudit(period, key);\n } catch {\n return null;\n }\n }\n\n private async readContinuityAuditReferences(weekId: string): Promise<{\n weekId: string;\n monthId: string;\n weeklyPath: string | null;\n monthlyPath: string | null;\n }> {\n const monthId = monthIdFromIsoWeek(weekId);\n const weeklyPath = path.join(this.identityAuditWeeklyDir, `${weekId}.md`);\n const monthlyPath = path.join(this.identityAuditMonthlyDir, `${monthId}.md`);\n const [weeklyAudit, monthlyAudit] = await Promise.all([\n this.readOptionalIdentityAuditForReference(\"weekly\", weekId),\n this.readOptionalIdentityAuditForReference(\"monthly\", monthId),\n ]);\n const weeklyExists = (weeklyAudit ?? \"\").trim().length > 0;\n const monthlyExists = (monthlyAudit ?? \"\").trim().length > 0;\n return {\n weekId,\n monthId,\n weeklyPath: weeklyExists ? weeklyPath : null,\n monthlyPath: monthlyExists ? monthlyPath : null,\n };\n }\n}\n"],"mappings":"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","names":["limit"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/summarizer.ts"],"sourcesContent":["import { mkdir, readFile, writeFile, readdir } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport { log } from \"./logger.js\";\nimport { LocalLlmClient } from \"./local-llm.js\";\nimport { FallbackLlmClient, fallbackLlmRuntimeContextFromConfig, gatewayTaskChainOptions } from \"./fallback-llm.js\";\nimport { ModelRegistry } from \"./model-registry.js\";\nimport { extractJsonCandidates } from \"./json-extract.js\";\nimport type { HourlySummary, TranscriptEntry, PluginConfig, GatewayConfig } from \"./types.js\";\nimport type { TranscriptManager } from \"./transcript.js\";\nimport { readSummarySnapshot, upsertSummarySnapshot, writeSummarySnapshot } from \"./summary-snapshot.js\";\nimport {\n encodeStoragePathSegment,\n resolveSafeStoragePath,\n} from \"./storage-paths.js\";\nimport { sessionStoragePaths } from \"./session-identity.js\";\nimport { resolveLocalLlmCapabilities } from \"./capabilities.js\";\n\n// Schema for LLM summary output\nconst HourlySummarySchema = z.object({\n bullets: z\n .array(z.string().trim().min(1))\n .min(1)\n .describe(\"3-5 bullet points summarizing the hour's activity\"),\n});\n\ntype HourlySummaryResult = z.infer<typeof HourlySummarySchema>;\n\nconst HourlySummaryExtendedSchema = z.object({\n topics: z.array(z.string()).default([]),\n decisions: z.array(z.string()).default([]),\n actionItems: z.array(z.string()).default([]),\n rejected: z.array(z.string()).default([]),\n});\n\ntype HourlySummaryExtendedResult = z.infer<typeof HourlySummaryExtendedSchema>;\n\ntype HourlySummaryExtendedMeta = {\n userTurns: number;\n assistantTurns: number;\n toolCalls: number;\n toolCounts: Record<string, number>;\n};\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nexport class HourlySummarizer {\n private summariesDir: string;\n private config: PluginConfig;\n private localLlm: LocalLlmClient;\n private fallbackLlm: FallbackLlmClient;\n private modelRegistry: ModelRegistry;\n private transcript?: TranscriptManager;\n\n constructor(config: PluginConfig, gatewayConfig?: GatewayConfig, modelRegistry?: ModelRegistry, transcript?: TranscriptManager) {\n this.config = config;\n this.summariesDir = path.join(config.memoryDir, \"summaries\", \"hourly\");\n this.modelRegistry = modelRegistry ?? new ModelRegistry(config.memoryDir);\n this.transcript = transcript;\n\n // Initialize local LLM client with shared model registry\n this.localLlm = new LocalLlmClient(config, this.modelRegistry);\n\n // Initialize fallback client with gateway config\n this.fallbackLlm = new FallbackLlmClient(\n gatewayConfig,\n fallbackLlmRuntimeContextFromConfig(config),\n );\n\n if (!gatewayConfig?.agents?.defaults?.model?.primary && !resolveLocalLlmCapabilities(config).localLlm && config.modelSource !== \"gateway\") {\n log.warn(\"no gateway default AI and local LLM disabled — hourly summarization disabled\");\n }\n }\n\n private get useGatewayModelSource(): boolean {\n return this.config.modelSource === \"gateway\";\n }\n\n private get shouldUseLocalLlm(): boolean {\n return resolveLocalLlmCapabilities(this.config).localLlm && !this.useGatewayModelSource;\n }\n\n private withGatewayAgent(options: import(\"./fallback-llm.js\").FallbackLlmOptions): import(\"./fallback-llm.js\").FallbackLlmOptions {\n if (!this.useGatewayModelSource) return options;\n // Shared resolution (taskModelChain > gatewayAgentId) — gotcha #22. Issue #1365.\n return { ...options, ...gatewayTaskChainOptions(this.config) };\n }\n\n async initialize(): Promise<void> {\n await mkdir(this.summariesDir, { recursive: true });\n log.info(\"hourly summarizer initialized\");\n }\n\n private async summarySessionDir(sessionKey: string): Promise<string> {\n return resolveSafeStoragePath(\n this.summariesDir,\n encodeStoragePathSegment(sessionKey, \"session\"),\n );\n }\n\n private async legacySummarySessionDir(sessionKey: string): Promise<string | null> {\n if (sessionKey.includes(\"\\0\")) return null;\n try {\n return await resolveSafeStoragePath(this.summariesDir, sessionKey);\n } catch {\n return null;\n }\n }\n\n private summaryDateString(hour: string): string {\n const dateStr = hour.slice(0, 10);\n if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(dateStr)) {\n throw new Error(`invalid hourly summary timestamp: ${hour}`);\n }\n return dateStr;\n }\n\n // Generate summary for a specific hour and session\n async generateSummary(\n sessionKey: string,\n hourStart: Date,\n entries: TranscriptEntry[]\n ): Promise<HourlySummary | null> {\n if (entries.length === 0) return null;\n\n // Format entries for the LLM\n const conversation = entries\n .map((e) => `[${e.role}] ${e.content}`)\n .join(\"\\n\\n\");\n\n if (this.config.hourlySummariesExtendedEnabled) {\n const extended = await this.generateExtended(sessionKey, hourStart, conversation, entries);\n if (!extended) return null;\n const meta: HourlySummaryExtendedMeta = {\n userTurns: entries.filter((e) => e.role === \"user\").length,\n assistantTurns: entries.filter((e) => e.role === \"assistant\").length,\n toolCalls: extended._meta.toolCalls,\n toolCounts: extended._meta.toolCounts,\n };\n // Keep HourlySummary surface stable; encode \"topics\" as bullets for recall injection.\n const base: HourlySummary = {\n hour: hourStart.toISOString(),\n sessionKey,\n bullets: extended.topics.length > 0 ? extended.topics.slice(0, 5) : [\"(summary generated)\"],\n turnCount: entries.length,\n generatedAt: new Date().toISOString(),\n };\n const withExtras = base as any;\n withExtras._extended = extended;\n withExtras._extendedMeta = meta;\n return base;\n }\n\n const hourIso = hourStart.toISOString();\n const startTime = Date.now();\n\n // Try local LLM first if enabled\n if (this.shouldUseLocalLlm) {\n try {\n const localResult = await this.generateWithLocalLlm(conversation);\n if (localResult) {\n const durationMs = Date.now() - startTime;\n log.debug(\n `generated hourly summary for ${sessionKey} at ${hourIso} in ${durationMs}ms using local LLM`\n );\n return {\n hour: hourIso,\n sessionKey,\n bullets: localResult.bullets,\n turnCount: entries.length,\n generatedAt: new Date().toISOString(),\n };\n }\n // Local failed, fall back if allowed\n if (!this.config.localLlmFallback) {\n log.warn(\"summary generation: local LLM failed and fallback disabled\");\n return null;\n }\n log.info(\"summary generation: local LLM unavailable, falling back to gateway default AI\");\n } catch (err) {\n if (!this.config.localLlmFallback) {\n log.warn(\"summary generation: local LLM error and fallback disabled:\", err);\n return null;\n }\n log.info(\"summary generation: local LLM error, falling back to gateway default AI:\", err);\n }\n }\n\n // Fall back to gateway's default AI\n log.info(\"summary generation: falling back to gateway default AI\");\n\n try {\n const messages = [\n {\n role: \"system\" as const,\n content: `You are a conversation summarization system. Summarize the following conversation transcript into 3-5 concise bullet points.\n\nGuidelines:\n- Focus on what was accomplished, decided, or discussed\n- Include specific topics, projects, or entities mentioned\n- Note any significant user requests or agent actions\n- Keep bullets brief but informative (1-2 sentences each)\n- Skip trivial greetings or meta-conversation\n- Use present tense for ongoing work, past for completed items\n\nRespond with valid JSON matching this schema:\n{\n \"bullets\": [\"bullet 1\", \"bullet 2\", \"bullet 3\"]\n}`,\n },\n { role: \"user\" as const, content: `Summarize this conversation:\\n\\n${conversation}` },\n ];\n\n const result = await this.fallbackLlm.parseWithSchema(\n messages,\n HourlySummarySchema,\n this.withGatewayAgent({ temperature: 0.3, maxTokens: 8192 }),\n );\n\n const durationMs = Date.now() - startTime;\n\n if (result) {\n log.debug(\n `generated hourly summary for ${sessionKey} at ${hourIso} in ${durationMs}ms via fallback`,\n );\n return {\n hour: hourIso,\n sessionKey,\n bullets: result.bullets,\n turnCount: entries.length,\n generatedAt: new Date().toISOString(),\n };\n }\n\n log.warn(\"summary generation fallback returned no parsed output\");\n return null;\n } catch (err) {\n log.error(\"summary generation fallback failed\", err);\n return null;\n }\n }\n\n private async generateExtended(\n sessionKey: string,\n hourStart: Date,\n conversation: string,\n entries: TranscriptEntry[],\n ): Promise<(HourlySummaryExtendedResult & { _meta: HourlySummaryExtendedMeta }) | null> {\n const hourIso = hourStart.toISOString();\n const startTime = Date.now();\n\n const hourEnd = new Date(hourStart.getTime() + 60 * 60 * 1000);\n let toolCounts: Record<string, number> = {};\n if (this.config.hourlySummariesIncludeToolStats && this.transcript) {\n const uses = await this.transcript.readToolUse(sessionKey, hourStart, hourEnd);\n for (const u of uses) toolCounts[u.tool] = (toolCounts[u.tool] ?? 0) + 1;\n }\n\n const sys = `You are a conversation summarization system.\\n\\nSummarize the hour into structured sections.\\n\\nReturn valid JSON matching:\\n{\\n \\\"topics\\\": [\\\"...\\\"],\\n \\\"decisions\\\": [\\\"...\\\"],\\n \\\"actionItems\\\": [\\\"...\\\"],\\n \\\"rejected\\\": [\\\"...\\\"]\\n}\\n\\nGuidelines:\\n- Prefer concrete topics and decisions.\\n- Action items should be imperative.\\n- Rejected ideas are things that were explicitly discarded or reversed.\\n- If there are none for a section, return an empty array.\\n`;\n\n const toolStatsLine = Object.keys(toolCounts).length > 0\n ? `Tools used (counts): ${Object.entries(toolCounts).sort((a,b)=>b[1]-a[1]).slice(0,10).map(([k,v])=>`${k}=${v}`).join(\", \")}\\n\\n`\n : \"\";\n const userTurns = entries.filter((e) => e.role === \"user\").length;\n const assistantTurns = entries.filter((e) => e.role === \"assistant\").length;\n const toolCalls = Object.values(toolCounts).reduce((a,b)=>a+b,0);\n const statsLine = `Stats: userTurns=${userTurns}, assistantTurns=${assistantTurns}, toolCalls=${toolCalls}\\n\\n`;\n\n const user = `Hour: ${hourIso}\\nSession: ${sessionKey}\\n\\n${statsLine}${toolStatsLine}Conversation:\\n${conversation}\\n`;\n\n // Try local LLM first if enabled\n if (this.shouldUseLocalLlm) {\n try {\n const contextSizes = this.modelRegistry.calculateContextSizes(this.config.localLlmModel, this.config.localLlmMaxContext);\n const truncated = user.length > contextSizes.maxInputChars ? user.slice(0, contextSizes.maxInputChars) + \"\\n\\n[truncated]\" : user;\n const response = await this.localLlm.chatCompletion(\n [\n { role: \"system\", content: \"Output valid JSON only.\" },\n { role: \"user\", content: sys + \"\\n\\n\" + truncated },\n ],\n {\n temperature: 0.2,\n maxTokens: contextSizes.maxOutputTokens,\n operation: \"hourly_summary_extended\",\n priority: \"background\",\n },\n );\n if (response?.content) {\n const content = response.content.trim();\n for (const candidate of extractJsonCandidates(content)) {\n try {\n const parsed = JSON.parse(candidate);\n const result = HourlySummaryExtendedSchema.parse(parsed);\n log.debug(\n `generated extended hourly summary for ${sessionKey} at ${hourIso} in ${Date.now() - startTime}ms (local)`,\n );\n return { ...result, _meta: { userTurns, assistantTurns, toolCalls, toolCounts } };\n } catch {\n // keep trying candidates\n }\n }\n }\n } catch (err) {\n if (!this.config.localLlmFallback) return null;\n log.info(\"extended summary: local failed, falling back:\", err);\n }\n }\n\n try {\n const result = await this.fallbackLlm.parseWithSchema(\n [\n { role: \"system\" as const, content: sys },\n { role: \"user\" as const, content: user },\n ],\n HourlySummaryExtendedSchema,\n this.withGatewayAgent({ temperature: 0.2, maxTokens: 2048 }),\n );\n if (result) {\n log.debug(`generated extended hourly summary for ${sessionKey} at ${hourIso} in ${Date.now() - startTime}ms (fallback)`);\n return { ...result, _meta: { userTurns, assistantTurns, toolCalls, toolCounts } };\n }\n return null;\n } catch (err) {\n log.error(\"extended summary generation failed\", err);\n return null;\n }\n }\n\n /**\n * Generate summary using local LLM with JSON mode.\n * Uses dynamic context sizing based on model capabilities.\n */\n private async generateWithLocalLlm(conversation: string): Promise<HourlySummaryResult | null> {\n // Get dynamic context sizes based on model capabilities\n const contextSizes = this.modelRegistry.calculateContextSizes(\n this.config.localLlmModel,\n this.config.localLlmMaxContext\n );\n log.debug(`Summarizer model context: ${contextSizes.description}`);\n\n const maxConversationChars = contextSizes.maxInputChars;\n const truncatedConversation = conversation.length > maxConversationChars\n ? conversation.slice(0, maxConversationChars) + \"\\n\\n[truncated]\"\n : conversation;\n\n const instructions = `You are a conversation summarization system. Summarize the following conversation transcript into 3-5 concise bullet points.\n\nGuidelines:\n- Focus on what was accomplished, decided, or discussed\n- Include specific topics, projects, or entities mentioned\n- Note any significant user requests or agent actions\n- Keep bullets brief but informative (1-2 sentences each)\n- Skip trivial greetings or meta-conversation\n- Use present tense for ongoing work, past for completed items\n\nRespond with valid JSON matching this schema:\n{\n \"bullets\": [\"bullet 1\", \"bullet 2\", \"bullet 3\"]\n}`;\n\n const fullPrompt = `${instructions}\\n\\nConversation to summarize:\\n${truncatedConversation}`;\n\n const response = await this.localLlm.chatCompletion(\n [\n { role: \"system\", content: \"You are a conversation summarization system. Output valid JSON only.\" },\n { role: \"user\", content: fullPrompt },\n ],\n {\n temperature: 0.3,\n maxTokens: contextSizes.maxOutputTokens,\n operation: \"hourly_summary\",\n priority: \"background\",\n },\n );\n\n if (!response?.content) {\n return null;\n }\n\n try {\n // Parse JSON response\n const content = response.content.trim();\n for (const candidate of extractJsonCandidates(content)) {\n try {\n const parsed = JSON.parse(candidate);\n return HourlySummarySchema.parse(parsed);\n } catch {\n // keep trying candidates\n }\n }\n return null;\n } catch (err) {\n log.warn(\"local LLM summary: failed to parse JSON response:\", err);\n return null;\n }\n }\n\n // Save summary to file\n async saveSummary(summary: HourlySummary): Promise<void> {\n const sessionDir = await this.summarySessionDir(summary.sessionKey);\n await mkdir(sessionDir, { recursive: true });\n\n // Format date as YYYY-MM-DD for the filename\n const dateStr = this.summaryDateString(summary.hour);\n const filePath = await resolveSafeStoragePath(sessionDir, `${dateStr}.md`);\n\n // Format hour as HH:00 for display\n const hourStr = summary.hour.slice(11, 13);\n\n // Build markdown content\n const lines: string[] = [];\n\n // Check if file exists to append or create\n let existingContent = \"\";\n try {\n existingContent = await readFile(filePath, \"utf-8\");\n } catch {\n // File doesn't exist yet, will create new\n }\n\n // Check if this hour already exists (idempotent)\n const hourHeader = `## ${hourStr}:00`;\n if (existingContent.includes(hourHeader)) {\n // Replace existing hour section\n const headerMatch = new RegExp(`(^|\\\\n)${escapeRegExp(hourHeader)}\\\\n`).exec(existingContent);\n const sectionStart = headerMatch\n ? headerMatch.index + headerMatch[1].length\n : existingContent.indexOf(hourHeader);\n const nextHeaderPattern = /\\n## \\d{2}:00\\n/g;\n nextHeaderPattern.lastIndex = sectionStart + hourHeader.length;\n const nextHeader = nextHeaderPattern.exec(existingContent);\n const beforeHour = existingContent.slice(0, sectionStart);\n const afterHour = nextHeader\n ? existingContent.slice(nextHeader.index + 1)\n : \"\";\n const newSection = this.formatHourSection(summary, hourHeader);\n existingContent = beforeHour + newSection.trimEnd() + (afterHour ? \"\\n\\n\" + afterHour : \"\\n\");\n\n await writeFile(filePath, existingContent, \"utf-8\");\n log.debug(`updated hourly summary for ${summary.sessionKey} at ${hourStr}:00`);\n } else {\n // Append new hour section\n const newSection = this.formatHourSection(summary, hourHeader);\n\n if (existingContent) {\n // Add to existing file\n await writeFile(filePath, existingContent.trimEnd() + \"\\n\\n\" + newSection, \"utf-8\");\n } else {\n // Create new file with header\n const header = `# Hourly Summaries — ${dateStr}\\n\\n*Session: ${summary.sessionKey}*\\n`;\n await writeFile(filePath, header + \"\\n\" + newSection, \"utf-8\");\n }\n log.debug(`saved hourly summary for ${summary.sessionKey} at ${hourStr}:00`);\n }\n try {\n await upsertSummarySnapshot(this.config.memoryDir, summary);\n } catch (error) {\n log.warn(\n `hourly summarizer: failed to update summary snapshot for ${summary.sessionKey} (fail-open): ${String(error)}`,\n );\n }\n }\n\n private formatHourSection(summary: HourlySummary, hourHeader: string): string {\n const ext = (summary as any)._extended as (HourlySummaryExtendedResult & { _meta?: HourlySummaryExtendedMeta }) | undefined;\n const meta = (summary as any)._extendedMeta as HourlySummaryExtendedMeta | undefined;\n const lines: string[] = [hourHeader, \"\"];\n\n if (this.config.hourlySummariesExtendedEnabled && ext) {\n lines.push(\"### Topics Discussed\");\n for (const t of ext.topics) lines.push(`- ${t}`);\n lines.push(\"\");\n lines.push(\"### Decisions Made\");\n for (const d of ext.decisions) lines.push(`- ${d}`);\n lines.push(\"\");\n lines.push(\"### Action Items\");\n for (const a of ext.actionItems) lines.push(`- ${a}`);\n lines.push(\"\");\n lines.push(\"### Rejected Ideas / Reversals\");\n for (const r of ext.rejected) lines.push(`- ${r}`);\n lines.push(\"\");\n if (meta && Object.keys(meta.toolCounts).length > 0) {\n lines.push(\"### Tools Used\");\n const top = Object.entries(meta.toolCounts)\n .sort((a, b) => b[1] - a[1])\n .slice(0, 12);\n for (const [name, count] of top) lines.push(`- ${name}: ${count}`);\n lines.push(\"\");\n }\n lines.push(\"### Stats\");\n lines.push(`- Turns: ${summary.turnCount}`);\n if (meta) {\n lines.push(`- User turns: ${meta.userTurns}`);\n lines.push(`- Assistant turns: ${meta.assistantTurns}`);\n lines.push(`- Tool calls: ${meta.toolCalls}`);\n }\n lines.push(\"\");\n return lines.join(\"\\n\");\n }\n\n for (const bullet of summary.bullets) lines.push(`- ${bullet}`);\n lines.push(` *(${summary.turnCount} turns)*`);\n lines.push(\"\");\n return lines.join(\"\\n\");\n }\n\n // Read recent summaries for recall injection\n async readRecent(sessionKey: string, hours: number): Promise<HourlySummary[]> {\n try {\n const cutoffTime = Date.now() - hours * 60 * 60 * 1000;\n\n const snapshot = await readSummarySnapshot(this.config.memoryDir, sessionKey);\n if (snapshot) {\n return snapshot\n .filter((s) => new Date(s.hour).getTime() >= cutoffTime)\n .sort((a, b) => new Date(b.hour).getTime() - new Date(a.hour).getTime());\n }\n\n const summaries: HourlySummary[] = [];\n const encodedDir = await this.summarySessionDir(sessionKey);\n const legacyDir = await this.legacySummarySessionDir(sessionKey);\n const seenDirs = new Set<string>();\n\n for (const sessionDir of [encodedDir, legacyDir]) {\n if (!sessionDir || seenDirs.has(sessionDir)) continue;\n seenDirs.add(sessionDir);\n const parsed = await this.readSummaryDir(sessionDir, sessionKey);\n summaries.push(...parsed);\n }\n\n const byHour = new Map<string, HourlySummary>();\n for (const summary of summaries) {\n if (!byHour.has(summary.hour)) byHour.set(summary.hour, summary);\n }\n\n const sortedSummaries = Array.from(byHour.values()).sort(\n (a, b) => new Date(b.hour).getTime() - new Date(a.hour).getTime(),\n );\n\n // Filter to recent hours while materializing the full parsed history.\n const recent = sortedSummaries.filter(\n (s) => new Date(s.hour).getTime() >= cutoffTime,\n );\n\n if (sortedSummaries.length > 0) {\n try {\n await writeSummarySnapshot(\n this.config.memoryDir,\n sessionKey,\n sortedSummaries,\n );\n } catch (error) {\n log.warn(\n `hourly summarizer: failed to materialize summary snapshot for ${sessionKey} (fail-open): ${String(error)}`,\n );\n }\n }\n\n return recent;\n } catch {\n // Directory doesn't exist or error reading\n return [];\n }\n }\n\n private async readSummaryDir(\n sessionDir: string,\n sessionKey: string,\n ): Promise<HourlySummary[]> {\n let files: string[];\n try {\n files = await readdir(sessionDir);\n } catch {\n return [];\n }\n\n const summaries: HourlySummary[] = [];\n const mdFiles = files.filter((f) => f.endsWith(\".md\"));\n for (const file of mdFiles) {\n const filePath = await resolveSafeStoragePath(sessionDir, file).catch(() => null);\n if (filePath === null) continue;\n\n try {\n const content = await readFile(filePath, \"utf-8\");\n summaries.push(...this.parseSummaryFile(content, sessionKey, file));\n } catch {\n // Skip unreadable summary files.\n }\n }\n\n return summaries;\n }\n\n private parseSummaryFile(\n content: string,\n sessionKey: string,\n filename: string\n ): HourlySummary[] {\n const summaries: HourlySummary[] = [];\n\n // Extract date from filename (YYYY-MM-DD.md)\n const dateMatch = filename.match(/^(\\d{4}-\\d{2}-\\d{2})\\.md$/);\n if (!dateMatch) return summaries;\n const dateStr = dateMatch[1];\n\n // Split by hour sections\n const hourSections = content.split(/\\n## (\\d{2}):00\\n/);\n\n // First element is the header, skip it\n for (let i = 1; i < hourSections.length; i += 2) {\n const hourStr = hourSections[i];\n const sectionContent = hourSections[i + 1] || \"\";\n\n // Parse bullets\n const bullets: string[] = [];\n const lines = sectionContent.split(\"\\n\");\n let turnCount = 0;\n\n let inTopics = false;\n let sawExtendedTopicsHeader = false;\n for (const line of lines) {\n if (line.startsWith(\"### Topics\")) {\n inTopics = true;\n sawExtendedTopicsHeader = true;\n continue;\n }\n if (line.startsWith(\"### \") && !line.startsWith(\"### Topics\")) {\n inTopics = false;\n }\n const bulletMatch = line.match(/^- (.+)$/);\n if (bulletMatch) {\n // For extended format, only treat topic bullets as recall bullets.\n if (!sawExtendedTopicsHeader || inTopics) bullets.push(bulletMatch[1]);\n }\n const turnMatch = line.match(/\\((\\d+) turns?\\)/);\n if (turnMatch) turnCount = parseInt(turnMatch[1], 10);\n }\n\n if (bullets.length > 0) {\n summaries.push({\n hour: `${dateStr}T${hourStr}:00:00.000Z`,\n sessionKey,\n bullets,\n turnCount,\n generatedAt: \"\", // Not stored in file, not needed for recall\n });\n }\n }\n\n return summaries;\n }\n\n // Format summaries for recall injection\n formatForRecall(summaries: HourlySummary[], maxCount: number): string {\n if (summaries.length === 0) return \"\";\n\n const limited = summaries.slice(0, maxCount);\n const lines: string[] = [`## Recent Activity (last ${limited.length} hours)`];\n\n for (const summary of limited) {\n const hourStr = summary.hour.slice(11, 16); // HH:MM\n for (const bullet of summary.bullets) {\n lines.push(`- ${hourStr}: ${bullet}`);\n }\n }\n\n return lines.join(\"\\n\");\n }\n\n // Main entry point for cron job\n async runHourly(): Promise<void> {\n log.debug(\"running hourly summary generation\");\n\n // Get active sessions from transcript\n const sessions = await this.getActiveSessions();\n\n for (const sessionKey of sessions) {\n // Calculate the hour we want to summarize (previous hour)\n const now = new Date();\n const hourStart = new Date(now.getTime() - 60 * 60 * 1000);\n hourStart.setMinutes(0, 0, 0);\n const hourEnd = new Date(hourStart.getTime() + 60 * 60 * 1000);\n\n // Get entries for this session in the target hour\n const entries = await this.getTranscriptEntries(sessionKey, hourStart, hourEnd);\n\n if (entries.length === 0) {\n log.debug(`no transcript entries for ${sessionKey} at ${hourStart.toISOString()}`);\n continue;\n }\n\n // Generate and save summary\n const summary = await this.generateSummary(sessionKey, hourStart, entries);\n if (summary) {\n await this.saveSummary(summary);\n log.info(`generated hourly summary for ${sessionKey} (${entries.length} turns)`);\n }\n }\n }\n\n // Get list of active sessions from transcript directory\n private async getActiveSessions(): Promise<string[]> {\n const transcriptDir = await resolveSafeStoragePath(\n this.config.memoryDir,\n \"transcripts\",\n ).catch(() => null);\n if (transcriptDir === null) return [];\n\n try {\n const sessionKeys = new Set<string>();\n const typeEntries = await readdir(transcriptDir, { withFileTypes: true });\n for (const typeEnt of typeEntries) {\n if (!typeEnt.isDirectory()) continue;\n const typeDir = await resolveSafeStoragePath(transcriptDir, typeEnt.name).catch(() => null);\n if (typeDir === null) continue;\n const idEntries = await readdir(typeDir, { withFileTypes: true });\n for (const idEnt of idEntries) {\n if (!idEnt.isDirectory()) continue;\n const chanDir = await resolveSafeStoragePath(typeDir, idEnt.name).catch(() => null);\n if (chanDir === null) continue;\n const files = (await readdir(chanDir)).filter((f) => f.endsWith(\".jsonl\")).sort();\n for (const file of files) {\n const transcriptPath = await resolveSafeStoragePath(chanDir, file).catch(() => null);\n if (transcriptPath === null) continue;\n await this.collectTranscriptSessionKeys(transcriptPath, sessionKeys);\n }\n }\n }\n return Array.from(sessionKeys);\n } catch {\n return [];\n }\n }\n\n private async collectTranscriptSessionKeys(\n transcriptPath: string,\n sessionKeys: Set<string>,\n ): Promise<void> {\n try {\n const raw = await readFile(transcriptPath, \"utf-8\");\n for (const line of raw.split(\"\\n\")) {\n if (!line.trim()) continue;\n try {\n const entry = JSON.parse(line) as TranscriptEntry;\n if (typeof entry.sessionKey === \"string\" && entry.sessionKey.length > 0) {\n sessionKeys.add(entry.sessionKey);\n }\n } catch {\n // ignore malformed transcript lines\n }\n }\n } catch {\n // ignore unreadable transcript files\n }\n }\n\n // Get transcript entries for a session within a time range\n private async getTranscriptEntries(\n sessionKey: string,\n startTime: Date,\n endTime: Date\n ): Promise<TranscriptEntry[]> {\n // Shared session-identity layer (issue #1496, rule #22). Arbitrary keys\n // route to `session/<hash>`; legacy `agent:<id>:...` keep their paths. The\n // shared helper also supplies the read-back-only candidate dirs (mirrors\n // TranscriptManager) so legacy `other/default` AND old `parts.length >= 3`\n // data stays discoverable here too.\n const paths = sessionStoragePaths(sessionKey);\n\n try {\n const transcriptRoot = path.join(this.config.memoryDir, \"transcripts\");\n const candidateDirs = new Set(\n [paths.dir, paths.alternateDir, paths.legacyDir, ...paths.readbackDirs].filter(\n (dir): dir is string => typeof dir === \"string\" && dir.length > 0,\n ),\n );\n const entries: TranscriptEntry[] = [];\n // Dedup identical raw rows that a partially-applied migration may have\n // left in both the primary dir and a read-back dir (issue #1496, cursor\n // review). Exact raw JSONL line is the stable identity.\n const seenRawLines = new Set<string>();\n\n // Read all daily transcript files in the directory\n for (const candidateDir of candidateDirs) {\n const transcriptDir = await resolveSafeStoragePath(transcriptRoot, candidateDir).catch(() => null);\n if (transcriptDir === null) continue;\n\n const files = await readdir(transcriptDir).catch(() => []);\n for (const file of files) {\n if (!file.endsWith(\".jsonl\")) continue;\n\n const transcriptPath = await resolveSafeStoragePath(transcriptDir, file).catch(() => null);\n if (transcriptPath === null) continue;\n\n try {\n const content = await readFile(transcriptPath, \"utf-8\");\n const lines = content.trim().split(\"\\n\");\n\n for (const line of lines) {\n if (!line.trim()) continue;\n try {\n const entry = JSON.parse(line) as TranscriptEntry;\n const entryTime = new Date(entry.timestamp).getTime();\n\n if (\n entry.sessionKey === sessionKey &&\n entryTime >= startTime.getTime() &&\n entryTime < endTime.getTime() &&\n !seenRawLines.has(line)\n ) {\n seenRawLines.add(line);\n entries.push(entry);\n }\n } catch {\n // Skip malformed lines\n }\n }\n } catch {\n // Skip unreadable files\n }\n }\n }\n\n return entries;\n } catch {\n return [];\n }\n }\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/day-summary.ts"],"sourcesContent":["import path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { log } from \"./logger.js\";\nimport type { MemoryFile, PluginConfig } from \"./types.js\";\nimport { discoverMemoryExtensions, renderExtensionsFooter, resolveExtensionsRoot } from \"./memory-extension-host/index.js\";\n\nconst PROMPT_RELATIVE_PATH = path.join(\"prompts\", \"day_summary.prompt.md\");\n\n// Embedded fallback prompt for packaged/plugin-install builds where\n// prompts/day_summary.prompt.md may not be present in the runtime bundle.\nconst EMBEDDED_DAY_SUMMARY_PROMPT = `# Baseline day-summary prompt\n\nYou are writing an Engram end-of-day summary.\n\nYour job:\n- compress the day into a short, useful recap\n- prioritize concrete events, decisions, mood/energy signals, and open loops\n- include a few practical next actions for tomorrow\n- avoid hype, fluff, therapy-speak, and invented facts\n\nOutput JSON with these keys:\n- \\`summary\\` — one short paragraph\n- \\`bullets\\` — 2 to 5 bullets with the most important moments\n- \\`next_actions\\` — 1 to 3 concrete actions\n- \\`risks_or_open_loops\\` — 0 to 3 things that still need attention\n\nRules:\n- stay grounded in the input only\n- if the day was mixed, say so plainly\n- do not overstate confidence or importance\n- prefer specific verbs over vague abstractions\n\nBrevity:\n- keep the summary under 90 words\n- keep bullets short and information-dense\n- omit anything that does not change what tomorrow should care about\n\nStructure:\n- \\`summary\\` should be one paragraph only\n- \\`bullets\\` should contain the most important moments, not generic restatements\n- \\`next_actions\\` and \\`risks_or_open_loops\\` should be distinct and non-overlapping\n\nRisk:\n- explicitly surface unresolved blockers, dependencies, or fragile assumptions\n- do not bury open loops inside the summary if they deserve separate attention\n\nTone:\n- sound like a clear internal daily note, not a report template\n- stay natural and direct while remaining compact`;\n\nfunction candidateRoots(): string[] {\n const currentFile = fileURLToPath(import.meta.url);\n const here = path.dirname(currentFile);\n const candidates = [path.resolve(here, \"..\"), path.resolve(here, \"..\", \"..\")];\n\n const seen = new Set<string>();\n return candidates.filter((candidate) => {\n const normalized = path.resolve(candidate);\n if (seen.has(normalized)) return false;\n seen.add(normalized);\n return true;\n });\n}\n\nasync function resolvePromptPath(): Promise<string | null> {\n const { existsSync } = await import(\"node:fs\");\n for (const root of candidateRoots()) {\n const candidate = path.join(root, PROMPT_RELATIVE_PATH);\n if (existsSync(candidate)) {\n return candidate;\n }\n }\n return null;\n}\n\nexport async function loadDaySummaryPrompt(): Promise<string> {\n const promptPath = await resolvePromptPath();\n if (promptPath) {\n try {\n const { readFile } = await import(\"node:fs/promises\");\n const raw = await readFile(promptPath, \"utf-8\");\n // CRLF-compatible regex: allow \\r\\n or \\n line endings\n const match = raw.match(/```(?:[a-zA-Z0-9_-]+)?\\r?\\n([\\s\\S]*?)\\r?\\n```/);\n if (match?.[1]) {\n return match[1].trim();\n }\n log.warn(\"day summary prompt file does not contain a fenced prompt block; using embedded fallback\");\n } catch (err) {\n log.warn(`day summary prompt file read failed; using embedded fallback: ${err}`);\n }\n }\n return EMBEDDED_DAY_SUMMARY_PROMPT;\n}\n\nexport function formatDaySummaryMemories(memories: string | MemoryFile[]): string {\n if (typeof memories === \"string\") {\n return memories.trim();\n }\n\n return memories\n .map((memory) => {\n const category = memory.frontmatter.category || \"fact\";\n const created = memory.frontmatter.created || \"unknown\";\n return `[${memory.frontmatter.id}] (${category}, ${created})\\n${memory.content}`;\n })\n .join(\"\\n\\n\")\n .trim();\n}\n\n/**\n * Build a one-line extension footer for day-summary and summary-snapshot contexts.\n * Returns \"\" when extensions are disabled or none are found.\n */\nexport async function buildExtensionsFooterForSummary(\n config: PluginConfig,\n): Promise<string> {\n if (!config.memoryExtensionsEnabled) return \"\";\n const root = resolveExtensionsRoot(config);\n const extensions = await discoverMemoryExtensions(root, log);\n if (extensions.length === 0) return \"\";\n return renderExtensionsFooter(extensions);\n}\n"],"mappings":";;;;;;;;;;AAAA,OAAO,UAAU;AACjB,SAAS,qBAAqB;AAK9B,IAAM,uBAAuB,KAAK,KAAK,WAAW,uBAAuB;AAIzE,IAAM,8BAA8B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAwCpC,SAAS,iBAA2B;AAClC,QAAM,cAAc,cAAc,YAAY,GAAG;AACjD,QAAM,OAAO,KAAK,QAAQ,WAAW;AACrC,QAAM,aAAa,CAAC,KAAK,QAAQ,MAAM,IAAI,GAAG,KAAK,QAAQ,MAAM,MAAM,IAAI,CAAC;AAE5E,QAAM,OAAO,oBAAI,IAAY;AAC7B,SAAO,WAAW,OAAO,CAAC,cAAc;AACtC,UAAM,aAAa,KAAK,QAAQ,SAAS;AACzC,QAAI,KAAK,IAAI,UAAU,EAAG,QAAO;AACjC,SAAK,IAAI,UAAU;AACnB,WAAO;AAAA,EACT,CAAC;AACH;AAEA,eAAe,oBAA4C;AACzD,QAAM,EAAE,WAAW,IAAI,MAAM,OAAO,IAAS;AAC7C,aAAW,QAAQ,eAAe,GAAG;AACnC,UAAM,YAAY,KAAK,KAAK,MAAM,oBAAoB;AACtD,QAAI,WAAW,SAAS,GAAG;AACzB,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEA,eAAsB,uBAAwC;AAC5D,QAAM,aAAa,MAAM,kBAAkB;AAC3C,MAAI,YAAY;AACd,QAAI;AACF,YAAM,EAAE,SAAS,IAAI,MAAM,OAAO,aAAkB;AACpD,YAAM,MAAM,MAAM,SAAS,YAAY,OAAO;AAE9C,YAAM,QAAQ,IAAI,MAAM,+CAA+C;AACvE,UAAI,QAAQ,CAAC,GAAG;AACd,eAAO,MAAM,CAAC,EAAE,KAAK;AAAA,MACvB;AACA,UAAI,KAAK,yFAAyF;AAAA,IACpG,SAAS,KAAK;AACZ,UAAI,KAAK,iEAAiE,GAAG,EAAE;AAAA,IACjF;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,yBAAyB,UAAyC;AAChF,MAAI,OAAO,aAAa,UAAU;AAChC,WAAO,SAAS,KAAK;AAAA,EACvB;AAEA,SAAO,SACJ,IAAI,CAAC,WAAW;AACf,UAAM,WAAW,OAAO,YAAY,YAAY;AAChD,UAAM,UAAU,OAAO,YAAY,WAAW;AAC9C,WAAO,IAAI,OAAO,YAAY,EAAE,MAAM,QAAQ,KAAK,OAAO;AAAA,EAAM,OAAO,OAAO;AAAA,EAChF,CAAC,EACA,KAAK,MAAM,EACX,KAAK;AACV;AAMA,eAAsB,gCACpB,QACiB;AACjB,MAAI,CAAC,OAAO,wBAAyB,QAAO;AAC5C,QAAM,OAAO,sBAAsB,MAAM;AACzC,QAAM,aAAa,MAAM,yBAAyB,MAAM,GAAG;AAC3D,MAAI,WAAW,WAAW,EAAG,QAAO;AACpC,SAAO,uBAAuB,UAAU;AAC1C;","names":[]}