@remnic/core 9.3.729 → 9.3.730

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 (345) hide show
  1. package/dist/access-boundary.d.ts +6 -5
  2. package/dist/access-boundary.js +13 -13
  3. package/dist/access-cli.js +34 -33
  4. package/dist/access-cli.js.map +1 -1
  5. package/dist/access-http.d.ts +6 -5
  6. package/dist/access-http.js +19 -19
  7. package/dist/access-mcp.d.ts +6 -5
  8. package/dist/access-mcp.js +18 -18
  9. package/dist/access-operations-batch.js +16 -16
  10. package/dist/access-operations.d.ts +11 -10
  11. package/dist/access-operations.js +17 -17
  12. package/dist/access-schema.d.ts +42 -42
  13. package/dist/{access-service-BXMJqkTA.d.ts → access-service-Byoe3HsT.d.ts} +18 -3
  14. package/dist/access-service.d.ts +6 -5
  15. package/dist/access-service.js +12 -12
  16. package/dist/access-surface-catalog.d.ts +6 -5
  17. package/dist/action-confidence.d.ts +1 -1
  18. package/dist/active-memory-bridge.d.ts +1 -1
  19. package/dist/active-recall.d.ts +1 -1
  20. package/dist/active-recall.js +2 -2
  21. package/dist/{auto-sync-F3KCSQFJ.js → auto-sync-G3V5AN4C.js} +2 -2
  22. package/dist/behavior-learner.d.ts +1 -1
  23. package/dist/behavior-signals.d.ts +1 -1
  24. package/dist/bootstrap.d.ts +5 -4
  25. package/dist/briefing.d.ts +1 -1
  26. package/dist/briefing.js +3 -3
  27. package/dist/buffer-surprise-report.d.ts +1 -1
  28. package/dist/buffer.d.ts +1 -1
  29. package/dist/calibration.d.ts +1 -1
  30. package/dist/capabilities.d.ts +55 -2
  31. package/dist/capabilities.js +5 -1
  32. package/dist/{catalog-bMczlO2G.d.ts → catalog-DM1nk7cM.d.ts} +1 -1
  33. package/dist/causal-behavior.d.ts +1 -1
  34. package/dist/causal-consolidation.d.ts +1 -1
  35. package/dist/causal-consolidation.js +4 -4
  36. package/dist/causal-trajectory-graph.d.ts +1 -1
  37. package/dist/{chunk-4NOI577P.js → chunk-24ZLC5QN.js} +2 -2
  38. package/dist/{chunk-DMQWV6SQ.js → chunk-5RZOFIDL.js} +2 -2
  39. package/dist/{chunk-UM5AWJNQ.js → chunk-646B5ERJ.js} +62 -37
  40. package/dist/chunk-646B5ERJ.js.map +1 -0
  41. package/dist/{chunk-H5BWGCRZ.js → chunk-6TUWSUUD.js} +51 -47
  42. package/dist/{chunk-H5BWGCRZ.js.map → chunk-6TUWSUUD.js.map} +1 -1
  43. package/dist/{chunk-36SEDFAU.js → chunk-C5WN74HH.js} +2 -2
  44. package/dist/{chunk-MLKWJOAJ.js → chunk-CGPHMNL4.js} +2 -2
  45. package/dist/{chunk-R6OVFAX6.js → chunk-DJECGBBM.js} +7 -2
  46. package/dist/{chunk-R6OVFAX6.js.map → chunk-DJECGBBM.js.map} +1 -1
  47. package/dist/{chunk-3RCBIOOJ.js → chunk-ESF7TRYJ.js} +18 -2
  48. package/dist/{chunk-3RCBIOOJ.js.map → chunk-ESF7TRYJ.js.map} +1 -1
  49. package/dist/{chunk-EY6MDMHK.js → chunk-F6OEXJQQ.js} +2 -2
  50. package/dist/{chunk-M4V2JVSZ.js → chunk-FFUCCKPN.js} +2 -2
  51. package/dist/{chunk-O6YH5F47.js → chunk-FYWUNVFZ.js} +8 -8
  52. package/dist/{chunk-37436GML.js → chunk-GEXI357K.js} +2 -2
  53. package/dist/{chunk-YGIQORJ3.js → chunk-GGL34GCW.js} +3 -3
  54. package/dist/{chunk-4H4F3BFL.js → chunk-GXTYEG7Q.js} +3 -3
  55. package/dist/{chunk-4H4F3BFL.js.map → chunk-GXTYEG7Q.js.map} +1 -1
  56. package/dist/{chunk-WAS3NV46.js → chunk-H3MB3F62.js} +2 -2
  57. package/dist/{chunk-UTHQPSRC.js → chunk-HHNSLPX7.js} +11 -8
  58. package/dist/chunk-HHNSLPX7.js.map +1 -0
  59. package/dist/{chunk-76NHR6ZL.js → chunk-HJWQJUKQ.js} +4 -4
  60. package/dist/{chunk-Y4YD5TYW.js → chunk-IIBFCZA7.js} +3 -3
  61. package/dist/{chunk-UVPL565C.js → chunk-IQOEW5YV.js} +2 -2
  62. package/dist/{chunk-V4GNSDFH.js → chunk-KQYGNGON.js} +2 -2
  63. package/dist/{chunk-CBWI22JN.js → chunk-KSJCXXOU.js} +2 -2
  64. package/dist/{chunk-M4AYVEWS.js → chunk-LUCARK4W.js} +12 -11
  65. package/dist/chunk-LUCARK4W.js.map +1 -0
  66. package/dist/{chunk-I5REUWLH.js → chunk-NIZQH6AU.js} +3 -3
  67. package/dist/{chunk-4ESAR77N.js → chunk-NOU77OHX.js} +2 -2
  68. package/dist/{chunk-BQCHEV7O.js → chunk-O4ZIBPIW.js} +3 -3
  69. package/dist/{chunk-HOHVIVDR.js → chunk-OBJUKYDO.js} +2 -2
  70. package/dist/{chunk-YKBHOBJK.js → chunk-OEHCMALU.js} +56 -4
  71. package/dist/chunk-OEHCMALU.js.map +1 -0
  72. package/dist/{chunk-YOLZS7NY.js → chunk-OTQE66IX.js} +2 -2
  73. package/dist/{chunk-HEDZUSCS.js → chunk-OUITHS6V.js} +246 -368
  74. package/dist/chunk-OUITHS6V.js.map +1 -0
  75. package/dist/{chunk-4T3BMHKD.js → chunk-OZECYVGI.js} +20 -7
  76. package/dist/chunk-OZECYVGI.js.map +1 -0
  77. package/dist/{chunk-C2PG7IEH.js → chunk-P3VJCTVE.js} +2 -2
  78. package/dist/{chunk-EH5ED3C6.js → chunk-PMAQRUN4.js} +4 -4
  79. package/dist/chunk-PMAQRUN4.js.map +1 -0
  80. package/dist/{chunk-7RLCCNHU.js → chunk-Q6BAA57B.js} +4 -3
  81. package/dist/chunk-Q6BAA57B.js.map +1 -0
  82. package/dist/{chunk-HGNOCPZX.js → chunk-QZHF4BWN.js} +6 -6
  83. package/dist/chunk-SYX73XD7.js +283 -0
  84. package/dist/chunk-SYX73XD7.js.map +1 -0
  85. package/dist/{chunk-ASKXIAHD.js → chunk-WDJCZQB4.js} +2 -2
  86. package/dist/{chunk-AQLOP5F4.js → chunk-WNGXQMRI.js} +95 -6
  87. package/dist/chunk-WNGXQMRI.js.map +1 -0
  88. package/dist/{chunk-JYLFZWUX.js → chunk-XYUFGHUW.js} +2 -2
  89. package/dist/{chunk-3TSTGI6F.js → chunk-ZQUAVZNG.js} +2 -2
  90. package/dist/{chunk-4NR2PDZ5.js → chunk-ZVHRSR2R.js} +14 -4
  91. package/dist/chunk-ZVHRSR2R.js.map +1 -0
  92. package/dist/{cli-DmAiDd8A.d.ts → cli-Dt-tuiYH.d.ts} +3 -3
  93. package/dist/cli.d.ts +7 -6
  94. package/dist/cli.js +35 -35
  95. package/dist/compounding/engine.d.ts +12 -1
  96. package/dist/compounding/engine.js +3 -3
  97. package/dist/compounding/preference-consolidator.d.ts +1 -1
  98. package/dist/compression-optimizer.d.ts +1 -1
  99. package/dist/config.d.ts +1 -1
  100. package/dist/config.js +2 -2
  101. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  102. package/dist/connectors/codex-materialize-runner.js +3 -3
  103. package/dist/connectors/codex-materialize.d.ts +1 -1
  104. package/dist/connectors/index.d.ts +1 -1
  105. package/dist/connectors/index.js +3 -3
  106. package/dist/consolidation-provenance-check.d.ts +1 -1
  107. package/dist/consolidation-undo.d.ts +1 -1
  108. package/dist/contradiction/index.d.ts +1 -1
  109. package/dist/contradiction/index.js +1 -1
  110. package/dist/conversation-index/backend.d.ts +1 -1
  111. package/dist/conversation-index/chunker.d.ts +1 -1
  112. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  113. package/dist/conversation-index/indexer.d.ts +1 -1
  114. package/dist/conversation-index/search.d.ts +1 -1
  115. package/dist/day-summary.d.ts +1 -1
  116. package/dist/delinearize.d.ts +1 -1
  117. package/dist/direct-answer-wiring.d.ts +1 -1
  118. package/dist/direct-answer.d.ts +1 -1
  119. package/dist/embedding-fallback.d.ts +1 -1
  120. package/dist/embedding-fallback.js +2 -2
  121. package/dist/enrichment/index.d.ts +1 -1
  122. package/dist/entity-retrieval.d.ts +1 -1
  123. package/dist/entity-retrieval.js +3 -3
  124. package/dist/entity-schema.d.ts +1 -1
  125. package/dist/explicit-capture.d.ts +6 -4
  126. package/dist/explicit-capture.js +1 -1
  127. package/dist/extraction-faithfulness.d.ts +1 -1
  128. package/dist/extraction-judge-telemetry.d.ts +1 -1
  129. package/dist/extraction-judge-training.d.ts +1 -1
  130. package/dist/extraction-judge.d.ts +1 -1
  131. package/dist/extraction.d.ts +1 -1
  132. package/dist/extraction.js +3 -3
  133. package/dist/fallback-llm.d.ts +1 -1
  134. package/dist/{first-start-migration-22LPFHD5.js → first-start-migration-OOR57AYR.js} +2 -2
  135. package/dist/graph-dashboard-diff.d.ts +1 -1
  136. package/dist/graph-dashboard-key.d.ts +1 -1
  137. package/dist/graph-dashboard-parser.d.ts +1 -1
  138. package/dist/graph-edge-reinforcement.d.ts +1 -1
  139. package/dist/graph-snapshot.d.ts +1 -1
  140. package/dist/graph.d.ts +1 -1
  141. package/dist/identity-continuity.d.ts +1 -1
  142. package/dist/importance.d.ts +1 -1
  143. package/dist/index.d.ts +296 -11
  144. package/dist/index.js +359 -47
  145. package/dist/index.js.map +1 -1
  146. package/dist/intent.d.ts +1 -1
  147. package/dist/lcm/engine.d.ts +1 -1
  148. package/dist/lcm/index.d.ts +1 -1
  149. package/dist/lcm/tools.d.ts +1 -1
  150. package/dist/lifecycle.d.ts +1 -1
  151. package/dist/live-connectors-runner.d.ts +1 -1
  152. package/dist/local-llm.d.ts +1 -1
  153. package/dist/local-model-endpoint.d.ts +1 -1
  154. package/dist/maintenance/memory-governance.d.ts +1 -1
  155. package/dist/maintenance/memory-governance.js +3 -3
  156. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +3 -3
  157. package/dist/maintenance/rebuild-memory-projection.js +4 -4
  158. package/dist/mcp-memory-inspector-app.d.ts +6 -5
  159. package/dist/memory-action-policy.d.ts +1 -1
  160. package/dist/memory-cache.d.ts +1 -1
  161. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  162. package/dist/memory-projection-store.d.ts +1 -1
  163. package/dist/memory-provenance.d.ts +1 -1
  164. package/dist/memory-worth-outcomes.d.ts +1 -1
  165. package/dist/models-json.d.ts +1 -1
  166. package/dist/namespaces/migrate.d.ts +2 -2
  167. package/dist/namespaces/migrate.js +9 -9
  168. package/dist/namespaces/principal.d.ts +1 -1
  169. package/dist/namespaces/search.d.ts +1 -1
  170. package/dist/namespaces/search.js +5 -5
  171. package/dist/namespaces/storage.d.ts +2 -2
  172. package/dist/namespaces/storage.js +3 -3
  173. package/dist/native-knowledge.d.ts +1 -1
  174. package/dist/operator-toolkit.d.ts +1 -1
  175. package/dist/operator-toolkit.js +14 -14
  176. package/dist/orchestration/compression-guideline-coordinator.d.ts +105 -0
  177. package/dist/orchestration/compression-guideline-coordinator.js +12 -0
  178. package/dist/orchestration/maintenance.d.ts +2 -2
  179. package/dist/orchestration/maintenance.js +5 -5
  180. package/dist/{orchestrator-BR0sGsME.d.ts → orchestrator-B4KjaOtY.d.ts} +24 -8
  181. package/dist/orchestrator.d.ts +5 -4
  182. package/dist/orchestrator.js +28 -26
  183. package/dist/patterns-cli.d.ts +1 -1
  184. package/dist/policy-runtime.d.ts +1 -1
  185. package/dist/provenance.d.ts +1 -1
  186. package/dist/provenance.js +1 -1
  187. package/dist/qmd-recall-cache.d.ts +1 -1
  188. package/dist/qmd.d.ts +1 -1
  189. package/dist/recall-disclosure-escalation.d.ts +1 -1
  190. package/dist/recall-explain-renderer.d.ts +1 -1
  191. package/dist/recall-planner-llm.d.ts +1 -1
  192. package/dist/recall-state.d.ts +1 -1
  193. package/dist/recall-tag-filter.d.ts +1 -1
  194. package/dist/recall-xray-cli.d.ts +1 -1
  195. package/dist/recall-xray-renderer.d.ts +1 -1
  196. package/dist/recall-xray.d.ts +1 -1
  197. package/dist/{resolution-MN36NW5P.js → resolution-33PIX3TT.js} +2 -2
  198. package/dist/resolution-33PIX3TT.js.map +1 -0
  199. package/dist/resolve-auth-token.d.ts +1 -1
  200. package/dist/resume-bundles.js +3 -3
  201. package/dist/retrieval-agents.d.ts +1 -1
  202. package/dist/retrieval-tiers.d.ts +1 -1
  203. package/dist/routing/engine.d.ts +1 -1
  204. package/dist/routing/store.d.ts +1 -1
  205. package/dist/schemas.d.ts +84 -84
  206. package/dist/search/embed-helper.d.ts +1 -1
  207. package/dist/search/embed-helper.js +2 -2
  208. package/dist/search/factory.d.ts +1 -1
  209. package/dist/search/factory.js +4 -4
  210. package/dist/search/index.d.ts +1 -1
  211. package/dist/search/index.js +8 -8
  212. package/dist/search/lancedb-backend.d.ts +1 -1
  213. package/dist/search/meilisearch-backend.d.ts +1 -1
  214. package/dist/search/noop-backend.d.ts +1 -1
  215. package/dist/search/orama-backend.d.ts +1 -1
  216. package/dist/search/port.d.ts +1 -1
  217. package/dist/search/remote-backend.d.ts +1 -1
  218. package/dist/{semantic-consolidation-Cl15ksZy.d.ts → semantic-consolidation-CstTvHPo.d.ts} +1 -1
  219. package/dist/semantic-consolidation.d.ts +2 -2
  220. package/dist/semantic-consolidation.js +4 -4
  221. package/dist/semantic-rule-promotion.js +3 -3
  222. package/dist/semantic-rule-verifier.d.ts +1 -1
  223. package/dist/semantic-rule-verifier.js +3 -3
  224. package/dist/session-observer-bands.d.ts +1 -1
  225. package/dist/session-observer-state.d.ts +1 -1
  226. package/dist/shared-context/manager.d.ts +3 -3
  227. package/dist/signal.d.ts +1 -1
  228. package/dist/storage.d.ts +22 -3
  229. package/dist/storage.js +2 -2
  230. package/dist/summarizer.d.ts +1 -1
  231. package/dist/summary-snapshot.d.ts +1 -1
  232. package/dist/temporal-supersession.d.ts +1 -1
  233. package/dist/temporal-validity.d.ts +1 -1
  234. package/dist/threading.d.ts +1 -1
  235. package/dist/tier-migration.d.ts +1 -1
  236. package/dist/tier-routing.d.ts +1 -1
  237. package/dist/topics.d.ts +1 -1
  238. package/dist/transcript.d.ts +1 -1
  239. package/dist/transfer/types.d.ts +46 -46
  240. package/dist/trust-score-stage.d.ts +1 -1
  241. package/dist/trust-score.d.ts +1 -1
  242. package/dist/{types-ChQb9D6s.d.ts → types-VkxElCHR.d.ts} +8 -1
  243. package/dist/types.d.ts +1 -1
  244. package/dist/utility-runtime.d.ts +1 -1
  245. package/dist/verified-recall.js +3 -3
  246. package/package.json +12 -2
  247. package/src/access-service-coding-write.test.ts +2 -2
  248. package/src/access-service.ts +33 -14
  249. package/src/bitemporal-dedup-backfill.test.ts +10 -10
  250. package/src/bitemporal-frontmatter.test.ts +3 -3
  251. package/src/capabilities.test.ts +185 -0
  252. package/src/capabilities.ts +110 -0
  253. package/src/cli/creation-ledger-commands.ts +22 -21
  254. package/src/coding/architecture-surfaces.test.ts +25 -1
  255. package/src/coding/architecture-surfaces.ts +47 -19
  256. package/src/coding/decision-surfaces.ts +12 -3
  257. package/src/coding/review-context-structural.test.ts +303 -0
  258. package/src/coding/review-context.ts +79 -0
  259. package/src/coding/structural-context.test.ts +259 -0
  260. package/src/coding/structural-context.ts +315 -0
  261. package/src/coding/structural-subprocess-provider.test.ts +430 -0
  262. package/src/coding/structural-subprocess-provider.ts +355 -0
  263. package/src/compounding/engine.test.ts +90 -0
  264. package/src/compounding/engine.ts +25 -1
  265. package/src/contradiction/contradiction.test.ts +1 -1
  266. package/src/contradiction/resolution.ts +9 -1
  267. package/src/correction/correction-access-wiring.ts +21 -3
  268. package/src/correction/correction-contract.ts +7 -0
  269. package/src/correction/correction-planner.test.ts +231 -0
  270. package/src/correction/correction-planner.ts +73 -0
  271. package/src/correction/correction-service.ts +29 -0
  272. package/src/correction/correction-storage-integration.test.ts +2 -2
  273. package/src/dedup/semantic.test.ts +1 -1
  274. package/src/explicit-capture.ts +7 -4
  275. package/src/extraction-eventtime-wiring.test.ts +3 -3
  276. package/src/extraction-redaction-rules.test.ts +172 -0
  277. package/src/index.ts +29 -0
  278. package/src/maintenance/forget.test.ts +1 -1
  279. package/src/maintenance/memory-governance.test.ts +1 -1
  280. package/src/maintenance/pattern-reinforcement.test.ts +2 -2
  281. package/src/operator-toolkit.ts +4 -3
  282. package/src/orchestration/compression-guideline-coordinator.ts +449 -0
  283. package/src/orchestrator.ts +345 -464
  284. package/src/procedural/procedure-miner.test.ts +2 -2
  285. package/src/provenance-extraction.test.ts +382 -4
  286. package/src/provenance.ts +158 -22
  287. package/src/recall-handles-wiring.test.ts +1 -1
  288. package/src/search/factory.ts +4 -3
  289. package/src/semantic-rule-promotion.ts +1 -1
  290. package/src/source-attribution-roundtrip.test.ts +2 -2
  291. package/src/storage-contract/atomicity.test.ts +1 -1
  292. package/src/storage-contract/cache-coherence.test.ts +2 -2
  293. package/src/storage-contract/content-hash.test.ts +1 -1
  294. package/src/storage-contract/namespace-routing.test.ts +1 -1
  295. package/src/storage-contract/round-trip.test.ts +3 -3
  296. package/src/storage.ts +23 -2
  297. package/src/temporal-supersession.test.ts +12 -11
  298. package/src/temporal-validity.test.ts +11 -11
  299. package/src/wearables/cli.test.ts +30 -0
  300. package/src/wearables/cli.ts +3 -0
  301. package/src/wearables/memory-gen.test.ts +57 -1
  302. package/src/wearables/memory-gen.ts +31 -7
  303. package/src/wearables/pipeline.test.ts +40 -1
  304. package/src/wearables/pipeline.ts +4 -0
  305. package/src/wearables/service.test.ts +2 -2
  306. package/src/wearables/storage-io.test.ts +3 -3
  307. package/src/wearables/types.ts +7 -0
  308. package/dist/chunk-4NR2PDZ5.js.map +0 -1
  309. package/dist/chunk-4T3BMHKD.js.map +0 -1
  310. package/dist/chunk-7RLCCNHU.js.map +0 -1
  311. package/dist/chunk-AQLOP5F4.js.map +0 -1
  312. package/dist/chunk-EH5ED3C6.js.map +0 -1
  313. package/dist/chunk-HEDZUSCS.js.map +0 -1
  314. package/dist/chunk-M4AYVEWS.js.map +0 -1
  315. package/dist/chunk-UM5AWJNQ.js.map +0 -1
  316. package/dist/chunk-UTHQPSRC.js.map +0 -1
  317. package/dist/chunk-YKBHOBJK.js.map +0 -1
  318. /package/dist/{auto-sync-F3KCSQFJ.js.map → auto-sync-G3V5AN4C.js.map} +0 -0
  319. /package/dist/{chunk-4NOI577P.js.map → chunk-24ZLC5QN.js.map} +0 -0
  320. /package/dist/{chunk-DMQWV6SQ.js.map → chunk-5RZOFIDL.js.map} +0 -0
  321. /package/dist/{chunk-36SEDFAU.js.map → chunk-C5WN74HH.js.map} +0 -0
  322. /package/dist/{chunk-MLKWJOAJ.js.map → chunk-CGPHMNL4.js.map} +0 -0
  323. /package/dist/{chunk-EY6MDMHK.js.map → chunk-F6OEXJQQ.js.map} +0 -0
  324. /package/dist/{chunk-M4V2JVSZ.js.map → chunk-FFUCCKPN.js.map} +0 -0
  325. /package/dist/{chunk-O6YH5F47.js.map → chunk-FYWUNVFZ.js.map} +0 -0
  326. /package/dist/{chunk-37436GML.js.map → chunk-GEXI357K.js.map} +0 -0
  327. /package/dist/{chunk-YGIQORJ3.js.map → chunk-GGL34GCW.js.map} +0 -0
  328. /package/dist/{chunk-WAS3NV46.js.map → chunk-H3MB3F62.js.map} +0 -0
  329. /package/dist/{chunk-76NHR6ZL.js.map → chunk-HJWQJUKQ.js.map} +0 -0
  330. /package/dist/{chunk-Y4YD5TYW.js.map → chunk-IIBFCZA7.js.map} +0 -0
  331. /package/dist/{chunk-UVPL565C.js.map → chunk-IQOEW5YV.js.map} +0 -0
  332. /package/dist/{chunk-V4GNSDFH.js.map → chunk-KQYGNGON.js.map} +0 -0
  333. /package/dist/{chunk-CBWI22JN.js.map → chunk-KSJCXXOU.js.map} +0 -0
  334. /package/dist/{chunk-I5REUWLH.js.map → chunk-NIZQH6AU.js.map} +0 -0
  335. /package/dist/{chunk-4ESAR77N.js.map → chunk-NOU77OHX.js.map} +0 -0
  336. /package/dist/{chunk-BQCHEV7O.js.map → chunk-O4ZIBPIW.js.map} +0 -0
  337. /package/dist/{chunk-HOHVIVDR.js.map → chunk-OBJUKYDO.js.map} +0 -0
  338. /package/dist/{chunk-YOLZS7NY.js.map → chunk-OTQE66IX.js.map} +0 -0
  339. /package/dist/{chunk-C2PG7IEH.js.map → chunk-P3VJCTVE.js.map} +0 -0
  340. /package/dist/{chunk-HGNOCPZX.js.map → chunk-QZHF4BWN.js.map} +0 -0
  341. /package/dist/{chunk-ASKXIAHD.js.map → chunk-WDJCZQB4.js.map} +0 -0
  342. /package/dist/{chunk-JYLFZWUX.js.map → chunk-XYUFGHUW.js.map} +0 -0
  343. /package/dist/{chunk-3TSTGI6F.js.map → chunk-ZQUAVZNG.js.map} +0 -0
  344. /package/dist/{first-start-migration-22LPFHD5.js.map → first-start-migration-OOR57AYR.js.map} +0 -0
  345. /package/dist/{resolution-MN36NW5P.js.map → orchestration/compression-guideline-coordinator.js.map} +0 -0
@@ -30,6 +30,7 @@ import type {
30
30
  MemoryStatus,
31
31
  } from "../types.js";
32
32
  import type { VersionTrigger, VersioningConfig } from "../page-versioning.js";
33
+ import type { MemoryWriteResult } from "../storage.js";
33
34
  import { stripAttributesSuffix } from "../structured-attributes.js";
34
35
  import { ARCHITECTURE_CARD_TRUNCATION_MARKER, type ArchitectureCardBuildResult } from "./architecture-card.js";
35
36
  import { log } from "../logger.js";
@@ -118,6 +119,14 @@ export type ArchitectureSurfaceResponse =
118
119
  byteSize: number;
119
120
  truncated: boolean;
120
121
  buildCode?: string;
122
+ /**
123
+ * Present when the refresh was tombstone-blocked (#1579): the new card
124
+ * content landed pending_review (no active overwrite). Callers/UI surface
125
+ * this so operators see why the active card didn't update (#1645).
126
+ */
127
+ blockedReason?: string;
128
+ /** The tombstone id that blocked the write, when `blockedReason` is set. */
129
+ blockedBy?: string;
121
130
  };
122
131
 
123
132
  // ──────────────────────────────────────────────────────────────────────────
@@ -150,7 +159,7 @@ export interface ArchitectureSurfaceStorage {
150
159
  status?: MemoryStatus;
151
160
  structuredAttributes?: Record<string, string>;
152
161
  },
153
- ): Promise<string>;
162
+ ): Promise<MemoryWriteResult>;
154
163
  updateMemory(
155
164
  id: string,
156
165
  newContent: string,
@@ -307,22 +316,16 @@ async function architectureRefresh(
307
316
  log.warn(
308
317
  `coding_architecture/refresh: updateMemory returned false for id=${existing.frontmatter.id} — falling back to writeMemory`,
309
318
  );
310
- const memoryId = await storage.writeMemory("fact", cardContent, {
319
+ const fallbackWrite = await storage.writeMemory("fact", cardContent, {
311
320
  confidence: 1.0,
312
321
  tags,
313
322
  source: "coding-architecture",
314
323
  structuredAttributes: { cardKind: ARCHITECTURE_CARD_KIND },
315
324
  });
316
325
  log.info(
317
- `access-write op=coding_architecture/refresh memoryId=${memoryId} (fallback write) byteSize=${buildResult.card.byteSize}`,
326
+ `access-write op=coding_architecture/refresh memoryId=${fallbackWrite.id} (fallback write) byteSize=${buildResult.card.byteSize}`,
318
327
  );
319
- return {
320
- subcommand: "refresh",
321
- refreshed: true,
322
- memoryId,
323
- byteSize: buildResult.card.byteSize,
324
- truncated: buildResult.card.truncated,
325
- };
328
+ return refreshResponse(fallbackWrite, buildResult.card);
326
329
  }
327
330
  log.info(
328
331
  `access-write op=coding_architecture/refresh memoryId=${existing.frontmatter.id} (updated) byteSize=${buildResult.card.byteSize}`,
@@ -337,28 +340,53 @@ async function architectureRefresh(
337
340
  }
338
341
 
339
342
  // First card for this namespace — write a new memory.
340
- const memoryId = await storage.writeMemory("fact", cardContent, {
343
+ const newWrite = await storage.writeMemory("fact", cardContent, {
341
344
  confidence: 1.0,
342
345
  tags,
343
346
  source: "coding-architecture",
344
347
  structuredAttributes: { cardKind: ARCHITECTURE_CARD_KIND },
345
348
  });
346
349
  log.info(
347
- `access-write op=coding_architecture/refresh memoryId=${memoryId} (new) byteSize=${buildResult.card.byteSize}`,
350
+ `access-write op=coding_architecture/refresh memoryId=${newWrite.id} (new) byteSize=${buildResult.card.byteSize}`,
348
351
  );
349
- return {
350
- subcommand: "refresh",
351
- refreshed: true,
352
- memoryId,
353
- byteSize: buildResult.card.byteSize,
354
- truncated: buildResult.card.truncated,
355
- };
352
+ return refreshResponse(newWrite, buildResult.card);
356
353
  }
357
354
 
358
355
  // ──────────────────────────────────────────────────────────────────────────
359
356
  // Local helpers
360
357
  // ──────────────────────────────────────────────────────────────────────────
361
358
 
359
+ /**
360
+ * Build the refresh response from a write outcome, surfacing a
361
+ * tombstone block (#1579) as `refreshed:false` + a blocked reason so
362
+ * callers/UI see why the active card didn't update (#1645). Mirrors the
363
+ * guard pattern in wearables/memory-gen.ts: a blocked write lands
364
+ * pending_review (no active copy) and must NOT report `refreshed:true`.
365
+ */
366
+ function refreshResponse(
367
+ writeResult: MemoryWriteResult,
368
+ card: { byteSize: number; truncated: boolean },
369
+ ): ArchitectureSurfaceResponse {
370
+ if (writeResult.tombstoneBlocked) {
371
+ return {
372
+ subcommand: "refresh",
373
+ refreshed: false,
374
+ memoryId: writeResult.id,
375
+ byteSize: card.byteSize,
376
+ truncated: card.truncated,
377
+ blockedReason: "tombstone-blocked",
378
+ ...(writeResult.blockedBy !== undefined ? { blockedBy: writeResult.blockedBy } : {}),
379
+ };
380
+ }
381
+ return {
382
+ subcommand: "refresh",
383
+ refreshed: true,
384
+ memoryId: writeResult.id,
385
+ byteSize: card.byteSize,
386
+ truncated: card.truncated,
387
+ };
388
+ }
389
+
362
390
  /**
363
391
  * Find the existing architecture-card memory in the namespace, if any.
364
392
  * Identified by the `architecture-card` tag + `cardKind=architecture`
@@ -22,6 +22,7 @@ import {
22
22
  type DecisionStatus,
23
23
  } from "./decision-records.js";
24
24
  import { log } from "../logger.js";
25
+ import type { MemoryWriteResult } from "../storage.js";
25
26
 
26
27
  // ──────────────────────────────────────────────────────────────────────────
27
28
  // Subcommands
@@ -184,7 +185,7 @@ export interface DecisionSurfaceStorage {
184
185
  * body so the list/get projection has one authoritative source. */
185
186
  structuredAttributes?: Record<string, string>;
186
187
  },
187
- ): Promise<string>;
188
+ ): Promise<MemoryWriteResult>;
188
189
  writeMemoryFrontmatter(
189
190
  memory: MemoryFile,
190
191
  patch: Partial<MemoryFrontmatter>,
@@ -342,7 +343,7 @@ async function decisionRecord(
342
343
  const content = serializeDecisionRecord(record);
343
344
  const storage = await ctx.resolveStorage(request);
344
345
  const isActive = ACTIVE_DECISION_STATUSES.has(status);
345
- const memoryId = await storage.writeMemory("decision", content, {
346
+ const { id: memoryId } = await storage.writeMemory("decision", content, {
346
347
  confidence: 1.0,
347
348
  tags: ["decision-record"],
348
349
  source: "coding-decision",
@@ -407,7 +408,7 @@ async function decisionSupersede(
407
408
  supersedes: targetId,
408
409
  };
409
410
  const replacementContent = serializeDecisionRecord(replacement);
410
- const replacementId = await storage.writeMemory(
411
+ const { id: replacementId, tombstoneBlocked: replacementBlocked } = await storage.writeMemory(
411
412
  "decision",
412
413
  replacementContent,
413
414
  {
@@ -420,6 +421,14 @@ async function decisionSupersede(
420
421
  structuredAttributes: { decisionStatus: "accepted" },
421
422
  },
422
423
  );
424
+ if (replacementBlocked) {
425
+ // #1645: the replacement decision matched a tombstone (pending_review).
426
+ // Don't archive the old record — superseding with a non-active
427
+ // replacement retires the only active decision. Abort; old stays active.
428
+ ctx.throwInputError(
429
+ `replacement decision was tombstone-blocked (pending_review ${replacementId}) — keeping decision ${targetId} active`,
430
+ );
431
+ }
423
432
  // Mark the old record superseded: set BOTH frontmatter.status (so
424
433
  // recall/search/maintenance exclude it from the active corpus — review P2)
425
434
  // AND structuredAttributes.decisionStatus (the decision-specific lifecycle
@@ -0,0 +1,303 @@
1
+ /**
2
+ * Tests for the structural-context-aware review-context path
3
+ * (issue #1548 Track A PR 5).
4
+ *
5
+ * This file is the prove-fail-before characterization for PR 5:
6
+ * 1. GATE-OFF PARITY — with no provider consulted (the pure
7
+ * {@link packReviewContext} path), output is byte-identical to
8
+ * pre-feature behaviour on every input. Captured FIRST, before any
9
+ * assertion about the wired path.
10
+ * 2. PROVIDER-FAILURE FALLBACK — when the provider fails (any code),
11
+ * {@link packReviewContextStructural} ranking falls back to
12
+ * FILE-PATH-ONLY boosting, IDENTICAL to the pure packer, AND surfaces
13
+ * a distinct `structuralDegradation` so the failure is never silent
14
+ * (rule 34).
15
+ * 3. PROVIDER-SUCCESS EXPANSION — when the provider returns symbols,
16
+ * memories mentioning a symbol name float up via the same bounded
17
+ * additive boost.
18
+ *
19
+ * The provider is a fake implementing the port contract; no subprocess.
20
+ */
21
+ import assert from "node:assert/strict";
22
+ import { test } from "node:test";
23
+
24
+ import {
25
+ packReviewContext,
26
+ packReviewContextStructural,
27
+ rankReviewCandidates,
28
+ type ReviewCandidate,
29
+ } from "./review-context.js";
30
+ import type {
31
+ StructuralContextProvider,
32
+ SymbolsForDiffResult,
33
+ } from "./structural-context.js";
34
+
35
+ function c(id: string, score: number, entityRefs?: string[]): ReviewCandidate {
36
+ return { id, score, entityRefs };
37
+ }
38
+
39
+ /** Fake provider whose symbolsForDiff returns a fixed result. */
40
+ function providerReturning(result: SymbolsForDiffResult): StructuralContextProvider {
41
+ return {
42
+ id: "fake",
43
+ async probe() {
44
+ return { available: true };
45
+ },
46
+ async symbolsForDiff() {
47
+ return result;
48
+ },
49
+ };
50
+ }
51
+
52
+ const DIFF_TOUCHING_AUTH = [
53
+ "diff --git a/src/auth.ts b/src/auth.ts",
54
+ "--- a/src/auth.ts",
55
+ "+++ b/src/auth.ts",
56
+ "@@ -1,3 +1,4 @@",
57
+ "+ export function login() {}",
58
+ ].join("\n");
59
+
60
+ // ──────────────────────────────────────────────────────────────────────────
61
+ // 1. GATE-OFF PARITY — pure packReviewContext is byte-identical to today
62
+ // (prove-fail-before: this must pass BEFORE the structural path exists,
63
+ // and must keep passing unchanged after).
64
+ // ──────────────────────────────────────────────────────────────────────────
65
+
66
+ test("gate-off parity: pure packReviewContext boosts only on touched file paths", () => {
67
+ const candidates = [
68
+ c("auth-history", 0.2, ["src/auth.ts"]),
69
+ c("unrelated", 0.9, ["src/other.ts"]),
70
+ c("weak-match", 0.1, ["auth.ts"]),
71
+ ];
72
+ const result = packReviewContext({ diff: DIFF_TOUCHING_AUTH, candidates });
73
+ assert.equal(result.touchedFiles.length, 1);
74
+ assert.equal(result.touchedFiles[0], "src/auth.ts");
75
+ // structuralDegradation is NOT set on the pure path.
76
+ assert.equal(result.structuralDegradation, undefined);
77
+ // strongest unrelated wins; auth-history floats above weak-match via boost.
78
+ const ids = result.rankedRecall.map((r) => r.id);
79
+ assert.deepEqual(ids, ["unrelated", "auth-history", "weak-match"]);
80
+ });
81
+
82
+ test("gate-off parity: pure packReviewContext has no structuralDegradation field effect", () => {
83
+ const result = packReviewContext({ diff: "", candidates: [c("x", 0.5)] });
84
+ assert.equal(result.structuralDegradation, undefined);
85
+ assert.equal(result.rankedRecall[0]!.boost, 0);
86
+ });
87
+
88
+ test("gate-off parity: deterministic ordering matches rankReviewCandidates directly", () => {
89
+ const candidates = [c("b", 0.3, ["a.ts"]), c("a", 0.8), c("c", 0.3, ["a.ts"])];
90
+ const packed = packReviewContext({ diff: "diff --git a/a.ts b/a.ts", candidates });
91
+ const direct = rankReviewCandidates(candidates, ["a.ts"]);
92
+ assert.deepEqual(
93
+ packed.rankedRecall.map((r) => ({ id: r.id, boost: r.boost })),
94
+ direct.map((r) => ({ id: r.id, boost: r.boost })),
95
+ );
96
+ });
97
+
98
+ // ──────────────────────────────────────────────────────────────────────────
99
+ // 2. PROVIDER-FAILURE FALLBACK — ranking identical to pure packer +
100
+ // structuralDegradation populated (rule 34 — never silent)
101
+ // ──────────────────────────────────────────────────────────────────────────
102
+
103
+ test("structural fallback (a) provider_unavailable: ranking == pure packer, degradation set", async () => {
104
+ const candidates = [
105
+ c("auth-history", 0.2, ["src/auth.ts"]),
106
+ c("unrelated", 0.9, ["src/other.ts"]),
107
+ ];
108
+ const provider = providerReturning({
109
+ ok: false,
110
+ code: "provider_unavailable",
111
+ detail: "binary not found",
112
+ });
113
+ const result = await packReviewContextStructural({
114
+ diff: DIFF_TOUCHING_AUTH,
115
+ candidates,
116
+ provider,
117
+ });
118
+ // Ranking must be IDENTICAL to the pure packer (file-path-only).
119
+ const pure = packReviewContext({ diff: DIFF_TOUCHING_AUTH, candidates });
120
+ assert.deepEqual(
121
+ result.rankedRecall.map((r) => ({ id: r.id, boost: r.boost })),
122
+ pure.rankedRecall.map((r) => ({ id: r.id, boost: r.boost })),
123
+ );
124
+ // Degradation surfaced.
125
+ assert.equal(result.structuralDegradation?.backend, "structural-context");
126
+ assert.equal(result.structuralDegradation?.code, "provider_unavailable");
127
+ assert.equal(result.structuralDegradation?.detail, "binary not found");
128
+ });
129
+
130
+ test("structural fallback (c) provider_timeout: ranking == pure packer, degradation code distinct", async () => {
131
+ const candidates = [c("auth-history", 0.2, ["src/auth.ts"])];
132
+ const provider = providerReturning({ ok: false, code: "provider_timeout" });
133
+ const result = await packReviewContextStructural({
134
+ diff: DIFF_TOUCHING_AUTH,
135
+ candidates,
136
+ provider,
137
+ });
138
+ const pure = packReviewContext({ diff: DIFF_TOUCHING_AUTH, candidates });
139
+ assert.deepEqual(
140
+ result.rankedRecall.map((r) => r.id),
141
+ pure.rankedRecall.map((r) => r.id),
142
+ );
143
+ assert.equal(result.structuralDegradation?.code, "provider_timeout");
144
+ });
145
+
146
+ test("structural fallback (d) provider_malformed: ranking == pure packer, degradation code distinct", async () => {
147
+ const candidates = [c("auth-history", 0.2, ["src/auth.ts"])];
148
+ const provider = providerReturning({ ok: false, code: "provider_malformed" });
149
+ const result = await packReviewContextStructural({
150
+ diff: DIFF_TOUCHING_AUTH,
151
+ candidates,
152
+ provider,
153
+ });
154
+ assert.equal(result.structuralDegradation?.code, "provider_malformed");
155
+ // No symbol expansion happened — touched files unchanged.
156
+ assert.deepEqual(result.touchedFiles, ["src/auth.ts"]);
157
+ });
158
+
159
+ test("structural fallback: provider_error code surfaces", async () => {
160
+ const provider = providerReturning({
161
+ ok: false,
162
+ code: "provider_error",
163
+ detail: "exit 2",
164
+ });
165
+ const result = await packReviewContextStructural({
166
+ diff: DIFF_TOUCHING_AUTH,
167
+ candidates: [c("x", 0.5)],
168
+ provider,
169
+ });
170
+ assert.equal(result.structuralDegradation?.code, "provider_error");
171
+ });
172
+
173
+ test("structural fallback: empty diff + failing provider → no boosts, degradation still set", async () => {
174
+ const provider = providerReturning({ ok: false, code: "provider_unavailable" });
175
+ const result = await packReviewContextStructural({
176
+ diff: "",
177
+ candidates: [c("x", 0.5, ["src/auth.ts"])],
178
+ provider,
179
+ });
180
+ assert.equal(result.rankedRecall[0]!.boost, 0);
181
+ assert.equal(result.structuralDegradation?.code, "provider_unavailable");
182
+ });
183
+
184
+ // ──────────────────────────────────────────────────────────────────────────
185
+ // 3. PROVIDER-SUCCESS EXPANSION — symbols widen the match set
186
+ // ──────────────────────────────────────────────────────────────────────────
187
+
188
+ test("structural success: symbol match floats a memory that shares NO file path", async () => {
189
+ // Candidate mentions the SYMBOL but not the touched file path.
190
+ const candidates = [
191
+ c("symbol-memory", 0.1, ["AuthService.login"]),
192
+ c("file-memory", 0.1, ["src/auth.ts"]),
193
+ c("unrelated", 0.9, ["src/other.ts"]),
194
+ ];
195
+ const provider = providerReturning({
196
+ ok: true,
197
+ symbols: [{ symbol: "AuthService.login", path: "src/auth.ts" }],
198
+ });
199
+ const result = await packReviewContextStructural({
200
+ diff: DIFF_TOUCHING_AUTH,
201
+ candidates,
202
+ provider,
203
+ });
204
+ // No degradation on success.
205
+ assert.equal(result.structuralDegradation, undefined);
206
+ // Both symbol- and file-matched memories get the boost; unrelated still wins.
207
+ const symbolMem = result.rankedRecall.find((r) => r.id === "symbol-memory")!;
208
+ const fileMem = result.rankedRecall.find((r) => r.id === "file-memory")!;
209
+ assert.equal(symbolMem.boost, 0.5, "symbol name match yields the same boost as a file match");
210
+ assert.equal(fileMem.boost, 0.5);
211
+ assert.equal(result.rankedRecall[0]!.id, "unrelated");
212
+ });
213
+
214
+ test("structural success: only-file-matched baseline does NOT get a symbol boost", async () => {
215
+ const candidates = [c("only-file", 0.1, ["src/auth.ts"])];
216
+ const provider = providerReturning({
217
+ ok: true,
218
+ symbols: [{ symbol: "CompletelyUnrelated.symbol" }],
219
+ });
220
+ const result = await packReviewContextStructural({
221
+ diff: DIFF_TOUCHING_AUTH,
222
+ candidates,
223
+ provider,
224
+ });
225
+ // The file match still boosts; the unrelated symbol adds nothing for this memory.
226
+ assert.equal(result.rankedRecall[0]!.boost, 0.5);
227
+ });
228
+
229
+ test("structural success: empty symbol list behaves like pure packer (no degradation)", async () => {
230
+ const candidates = [c("auth-history", 0.2, ["src/auth.ts"])];
231
+ const provider = providerReturning({ ok: true, symbols: [] });
232
+ const result = await packReviewContextStructural({
233
+ diff: DIFF_TOUCHING_AUTH,
234
+ candidates,
235
+ provider,
236
+ });
237
+ assert.equal(result.structuralDegradation, undefined);
238
+ const pure = packReviewContext({ diff: DIFF_TOUCHING_AUTH, candidates });
239
+ assert.deepEqual(
240
+ result.rankedRecall.map((r) => ({ id: r.id, boost: r.boost })),
241
+ pure.rankedRecall.map((r) => ({ id: r.id, boost: r.boost })),
242
+ );
243
+ });
244
+
245
+ test("structural success: multiple symbols each contribute to the boost cap", async () => {
246
+ const candidate = c("multi", 0, ["login", "logout", "validateToken", "session"]);
247
+ const provider = providerReturning({
248
+ ok: true,
249
+ symbols: [
250
+ { symbol: "login" },
251
+ { symbol: "logout" },
252
+ { symbol: "validateToken" },
253
+ { symbol: "session" },
254
+ ],
255
+ });
256
+ const result = await packReviewContextStructural({
257
+ diff: DIFF_TOUCHING_AUTH,
258
+ candidates: [candidate],
259
+ provider,
260
+ });
261
+ // Boost caps at MAX_BOOST (1.0) regardless of how many symbols match.
262
+ assert.equal(result.rankedRecall[0]!.boost, 1.0);
263
+ });
264
+
265
+ test("structural success: ranking is deterministic (stable id tie-break preserved)", async () => {
266
+ const candidates = [c("zeta", 0.5, ["x"]), c("alpha", 0.5, ["x"])];
267
+ const provider = providerReturning({ ok: true, symbols: [{ symbol: "x" }] });
268
+ const result = await packReviewContextStructural({
269
+ diff: DIFF_TOUCHING_AUTH,
270
+ candidates,
271
+ provider,
272
+ });
273
+ assert.deepEqual(
274
+ result.rankedRecall.map((r) => r.id),
275
+ ["alpha", "zeta"],
276
+ );
277
+ });
278
+
279
+ // ──────────────────────────────────────────────────────────────────────────
280
+ // AbortSignal is forwarded to the provider (rule 40)
281
+ // ──────────────────────────────────────────────────────────────────────────
282
+
283
+ test("structural: abort signal is forwarded to symbolsForDiff", async () => {
284
+ let observed: AbortSignal | undefined;
285
+ const provider: StructuralContextProvider = {
286
+ id: "fake",
287
+ async probe() {
288
+ return { available: true };
289
+ },
290
+ async symbolsForDiff(_diff, opts) {
291
+ observed = opts?.signal;
292
+ return { ok: true, symbols: [] };
293
+ },
294
+ };
295
+ const ac = new AbortController();
296
+ await packReviewContextStructural({
297
+ diff: "",
298
+ candidates: [],
299
+ provider,
300
+ signal: ac.signal,
301
+ });
302
+ assert.equal(observed, ac.signal);
303
+ });
@@ -20,6 +20,11 @@
20
20
  * surface is what PRs 5/6/7 will call).
21
21
  */
22
22
 
23
+ import type {
24
+ StructuralContextDegradation,
25
+ StructuralContextProvider,
26
+ } from "./structural-context.js";
27
+
23
28
  // ──────────────────────────────────────────────────────────────────────────
24
29
  // Public types
25
30
  // ──────────────────────────────────────────────────────────────────────────
@@ -61,6 +66,15 @@ export interface ReviewContext {
61
66
  * boost is recorded on each entry as `boost` for observability.
62
67
  */
63
68
  rankedRecall: Array<ReviewCandidate & { boost: number }>;
69
+ /**
70
+ * Structural-context provider degradation observed while expanding the
71
+ * diff to touched symbols (issue #1548 Track A PR 5, #1536 pattern).
72
+ * Present only when a provider was consulted AND it failed — a silent
73
+ * provider failure must never look like "no structural matches"
74
+ * (CLAUDE.md rule 34). Undefined when no provider was consulted (the
75
+ * pure {@link packReviewContext} path) or when the provider succeeded.
76
+ */
77
+ structuralDegradation?: StructuralContextDegradation;
64
78
  }
65
79
 
66
80
  // ──────────────────────────────────────────────────────────────────────────
@@ -423,3 +437,68 @@ export function packReviewContext(input: PackReviewContextInput): ReviewContext
423
437
  const rankedRecall = rankReviewCandidates(input.candidates, touchedFiles);
424
438
  return { touchedFiles, rankedRecall };
425
439
  }
440
+
441
+ // ──────────────────────────────────────────────────────────────────────────
442
+ // Structural-context enhancement (issue #1548 Track A PR 5)
443
+ // ──────────────────────────────────────────────────────────────────────────
444
+
445
+ /**
446
+ * Input for the structural-context-aware review-context packer. The pure
447
+ * {@link packReviewContext} stays unchanged (gate-off parity); this async
448
+ * variant consults a {@link StructuralContextProvider} to expand the diff's
449
+ * touched FILE paths into touched SYMBOL names, widening the match set so
450
+ * memories that mention a changed symbol — not just the file path — float
451
+ * up. The gate (`structuralProvider !== "none"`) is checked ONCE by the
452
+ * caller, never inside this function (rule 39).
453
+ */
454
+ export interface PackReviewContextStructuralInput extends PackReviewContextInput {
455
+ /** A probed structural-context provider. Never undefined here. */
456
+ provider: StructuralContextProvider;
457
+ /** Cancellation forwarded to the provider subprocess (rule 40). */
458
+ signal?: AbortSignal;
459
+ }
460
+
461
+ /**
462
+ * Structural-context-aware packer.
463
+ *
464
+ * Contract (issue #1548 Track A PR 5, prove-fail-before characterization):
465
+ * - Provider returns symbols (`ok: true`) → symbol names are ADDED to the
466
+ * match set alongside touched files; memories mentioning a symbol get the
467
+ * same bounded additive boost as a file-path match.
468
+ * - Provider fails (`ok: false`, any code) → ranking falls back to
469
+ * FILE-PATH-ONLY boosting, BYTE-IDENTICAL to {@link packReviewContext}
470
+ * (the match set is exactly the touched files), AND `structuralDegradation`
471
+ * is populated so xray/doctor can surface the failure (rule 34).
472
+ *
473
+ * The underlying ranker ({@link rankReviewCandidates}) is reused unchanged,
474
+ * so the deterministic ordering, boost cap, and tie-break are identical to
475
+ * the pure path.
476
+ */
477
+ export async function packReviewContextStructural(
478
+ input: PackReviewContextStructuralInput,
479
+ ): Promise<ReviewContext> {
480
+ const touchedFiles = parseTouchedFiles(input.diff);
481
+ const diffString = typeof input.diff === "string" ? input.diff : "";
482
+ const result = await input.provider.symbolsForDiff(diffString, {
483
+ signal: input.signal,
484
+ });
485
+
486
+ let matchTerms: string[] = touchedFiles;
487
+ let structuralDegradation: StructuralContextDegradation | undefined;
488
+
489
+ if (result.ok) {
490
+ const symbolNames = result.symbols.map((sym) => sym.symbol);
491
+ matchTerms = symbolNames.length > 0 ? [...touchedFiles, ...symbolNames] : touchedFiles;
492
+ } else {
493
+ // Fallback: file-path-only ranking, identical to the pure packer. The
494
+ // degradation is surfaced so the failure is never silent (rule 34).
495
+ structuralDegradation = {
496
+ backend: "structural-context",
497
+ code: result.code,
498
+ detail: result.detail,
499
+ };
500
+ }
501
+
502
+ const rankedRecall = rankReviewCandidates(input.candidates, matchTerms);
503
+ return { touchedFiles, rankedRecall, structuralDegradation };
504
+ }