@remnic/core 9.3.692 → 9.3.694

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 (268) hide show
  1. package/dist/access-boundary.d.ts +6 -6
  2. package/dist/access-boundary.js +11 -9
  3. package/dist/access-cli.js +76 -23
  4. package/dist/access-cli.js.map +1 -1
  5. package/dist/access-http.d.ts +5 -5
  6. package/dist/access-http.js +14 -12
  7. package/dist/access-mcp.d.ts +14 -5
  8. package/dist/access-mcp.js +13 -11
  9. package/dist/access-operations.d.ts +54 -7
  10. package/dist/access-operations.js +42 -10
  11. package/dist/{access-service-DvApf9LZ.d.ts → access-service-Ceq4TdPO.d.ts} +180 -3
  12. package/dist/access-service.d.ts +5 -5
  13. package/dist/access-service.js +10 -8
  14. package/dist/access-surface-catalog.d.ts +5 -5
  15. package/dist/access-surface-catalog.js +17 -0
  16. package/dist/access-surface-catalog.js.map +1 -1
  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 +1 -1
  21. package/dist/behavior-learner.d.ts +1 -1
  22. package/dist/behavior-signals.d.ts +1 -1
  23. package/dist/bootstrap.d.ts +4 -4
  24. package/dist/briefing.d.ts +1 -1
  25. package/dist/briefing.js +3 -3
  26. package/dist/buffer-surprise-report.d.ts +1 -1
  27. package/dist/buffer.d.ts +1 -1
  28. package/dist/calibration.d.ts +1 -1
  29. package/dist/capabilities.d.ts +1 -1
  30. package/dist/{catalog-BEWLjdOr.d.ts → catalog-Tkb991rg.d.ts} +1 -1
  31. package/dist/causal-behavior.d.ts +1 -1
  32. package/dist/causal-consolidation.d.ts +1 -1
  33. package/dist/causal-consolidation.js +4 -4
  34. package/dist/{chunk-ADUAF5EV.js → chunk-24FCDBJV.js} +2 -2
  35. package/dist/{chunk-V56S3A23.js → chunk-5A35EGHM.js} +1092 -29
  36. package/dist/chunk-5A35EGHM.js.map +1 -0
  37. package/dist/{chunk-3VVH6ZQW.js → chunk-5S53ZBPH.js} +2 -2
  38. package/dist/{chunk-DO7MDZMU.js → chunk-6C4WHMKV.js} +123 -7
  39. package/dist/chunk-6C4WHMKV.js.map +1 -0
  40. package/dist/{chunk-2D27ODNX.js → chunk-B55EAZNF.js} +2 -2
  41. package/dist/{chunk-W4MICQIZ.js → chunk-C5AOVGVC.js} +15 -15
  42. package/dist/chunk-CDOIDOTQ.js +381 -0
  43. package/dist/chunk-CDOIDOTQ.js.map +1 -0
  44. package/dist/{chunk-UOCLRM74.js → chunk-D7PQ7HZL.js} +2 -2
  45. package/dist/{chunk-HXNMDPHN.js → chunk-DT2ZGQT7.js} +2 -2
  46. package/dist/{chunk-QFG23CRE.js → chunk-EPVIBPVE.js} +2 -2
  47. package/dist/{chunk-O4ZIV62T.js → chunk-FCH766FX.js} +21 -19
  48. package/dist/chunk-FCH766FX.js.map +1 -0
  49. package/dist/{chunk-7MOTEVAA.js → chunk-HRUULBBV.js} +3 -1
  50. package/dist/chunk-HRUULBBV.js.map +1 -0
  51. package/dist/{chunk-U2OBZSGG.js → chunk-IZLNJYLX.js} +2 -2
  52. package/dist/{chunk-KYH53EFD.js → chunk-JIKBEDSB.js} +6 -6
  53. package/dist/{chunk-3BRA3N5A.js → chunk-KCRV3HVN.js} +2 -2
  54. package/dist/{chunk-AFWEUTMS.js → chunk-MOGFK2DU.js} +2 -2
  55. package/dist/{chunk-SAC5V6JT.js → chunk-MSUA4KAK.js} +2 -2
  56. package/dist/{chunk-VFVG4NS2.js → chunk-NXNUG7IA.js} +2 -2
  57. package/dist/{chunk-66HROLW5.js → chunk-P7IDNF7H.js} +2 -2
  58. package/dist/{chunk-FM7KLRKN.js → chunk-PILLH262.js} +2 -2
  59. package/dist/{chunk-UTUYAPLY.js → chunk-PNW4KKJX.js} +12 -3
  60. package/dist/{chunk-UTUYAPLY.js.map → chunk-PNW4KKJX.js.map} +1 -1
  61. package/dist/{chunk-2EN5WZQB.js → chunk-PQP6MFPL.js} +2 -2
  62. package/dist/chunk-PQP6MFPL.js.map +1 -0
  63. package/dist/{chunk-6C2BMUZA.js → chunk-QXWQ5V24.js} +2 -2
  64. package/dist/{chunk-SEK4XIDN.js → chunk-SJGTY2TW.js} +35 -9
  65. package/dist/chunk-SJGTY2TW.js.map +1 -0
  66. package/dist/{chunk-4IQNAOP3.js → chunk-SN5DFE34.js} +2 -2
  67. package/dist/{chunk-DQHZA7Y3.js → chunk-U62ZGWU7.js} +1 -1
  68. package/dist/chunk-U62ZGWU7.js.map +1 -0
  69. package/dist/{chunk-WIKNVFBS.js → chunk-UX5QTAFE.js} +2 -2
  70. package/dist/chunk-VQ7B2Q6M.js +112 -0
  71. package/dist/chunk-VQ7B2Q6M.js.map +1 -0
  72. package/dist/{chunk-MCV2DD6F.js → chunk-WVTNZUER.js} +2 -2
  73. package/dist/{chunk-ZLXGFAML.js → chunk-YI3KC2B5.js} +2 -2
  74. package/dist/{chunk-W4ELOUNX.js → chunk-YWYZPKK3.js} +2 -2
  75. package/dist/{chunk-NUZ3N445.js → chunk-YXZPKBFW.js} +3 -3
  76. package/dist/{chunk-GCOSQBQ2.js → chunk-ZKD3UVEO.js} +3 -3
  77. package/dist/{cli-BjsY9Le7.d.ts → cli-CxtZyBLl.d.ts} +3 -3
  78. package/dist/cli.d.ts +6 -6
  79. package/dist/cli.js +28 -26
  80. package/dist/coding/optional-coding-graph.js +7 -104
  81. package/dist/coding/optional-coding-graph.js.map +1 -1
  82. package/dist/compounding/engine.d.ts +1 -1
  83. package/dist/compounding/engine.js +3 -3
  84. package/dist/compounding/preference-consolidator.d.ts +1 -1
  85. package/dist/compression-optimizer.d.ts +1 -1
  86. package/dist/config.d.ts +1 -1
  87. package/dist/config.js +1 -1
  88. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  89. package/dist/connectors/codex-materialize-runner.js +3 -3
  90. package/dist/connectors/codex-materialize.d.ts +1 -1
  91. package/dist/connectors/index.d.ts +1 -1
  92. package/dist/connectors/index.js +3 -3
  93. package/dist/consolidation-provenance-check.d.ts +1 -1
  94. package/dist/consolidation-undo.d.ts +1 -1
  95. package/dist/contradiction/index.d.ts +1 -1
  96. package/dist/conversation-index/backend.d.ts +1 -1
  97. package/dist/conversation-index/chunker.d.ts +1 -1
  98. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  99. package/dist/conversation-index/indexer.d.ts +1 -1
  100. package/dist/conversation-index/search.d.ts +1 -1
  101. package/dist/day-summary.d.ts +1 -1
  102. package/dist/delinearize.d.ts +1 -1
  103. package/dist/direct-answer-wiring.d.ts +1 -1
  104. package/dist/direct-answer.d.ts +1 -1
  105. package/dist/embedding-fallback.d.ts +1 -1
  106. package/dist/enrichment/index.d.ts +1 -1
  107. package/dist/entity-retrieval.d.ts +1 -1
  108. package/dist/entity-retrieval.js +3 -3
  109. package/dist/entity-schema.d.ts +1 -1
  110. package/dist/explicit-capture.d.ts +4 -4
  111. package/dist/extraction-judge-telemetry.d.ts +1 -1
  112. package/dist/extraction-judge-training.d.ts +1 -1
  113. package/dist/extraction-judge.d.ts +1 -1
  114. package/dist/extraction.d.ts +1 -1
  115. package/dist/fallback-llm.d.ts +1 -1
  116. package/dist/identity-continuity.d.ts +1 -1
  117. package/dist/importance.d.ts +1 -1
  118. package/dist/index.d.ts +9 -9
  119. package/dist/index.js +37 -36
  120. package/dist/index.js.map +1 -1
  121. package/dist/intent.d.ts +1 -1
  122. package/dist/lcm/engine.d.ts +1 -1
  123. package/dist/lcm/index.d.ts +1 -1
  124. package/dist/lcm/tools.d.ts +1 -1
  125. package/dist/lifecycle.d.ts +1 -1
  126. package/dist/live-connectors-runner.d.ts +1 -1
  127. package/dist/local-llm.d.ts +1 -1
  128. package/dist/maintenance/memory-governance.d.ts +1 -1
  129. package/dist/maintenance/memory-governance.js +3 -3
  130. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +3 -3
  131. package/dist/maintenance/rebuild-memory-projection.js +4 -4
  132. package/dist/mcp-memory-inspector-app.d.ts +5 -5
  133. package/dist/memory-action-policy.d.ts +1 -1
  134. package/dist/memory-cache.d.ts +1 -1
  135. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  136. package/dist/memory-projection-store.d.ts +1 -1
  137. package/dist/memory-provenance.d.ts +1 -1
  138. package/dist/memory-worth-outcomes.d.ts +1 -1
  139. package/dist/models-json.d.ts +1 -1
  140. package/dist/namespaces/migrate.d.ts +2 -2
  141. package/dist/namespaces/migrate.js +4 -4
  142. package/dist/namespaces/principal.d.ts +1 -1
  143. package/dist/namespaces/search.d.ts +1 -1
  144. package/dist/namespaces/storage.d.ts +2 -2
  145. package/dist/namespaces/storage.js +3 -3
  146. package/dist/native-knowledge.d.ts +1 -1
  147. package/dist/operator-toolkit.d.ts +1 -1
  148. package/dist/operator-toolkit.js +9 -9
  149. package/dist/orchestration/maintenance.d.ts +2 -2
  150. package/dist/orchestration/maintenance.js +5 -5
  151. package/dist/{orchestrator-CNJCYjZ1.d.ts → orchestrator-CnbxRQs8.d.ts} +3 -3
  152. package/dist/orchestrator.d.ts +4 -4
  153. package/dist/orchestrator.js +16 -16
  154. package/dist/patterns-cli.d.ts +1 -1
  155. package/dist/policy-runtime.d.ts +1 -1
  156. package/dist/provenance.d.ts +1 -1
  157. package/dist/qmd-recall-cache.d.ts +1 -1
  158. package/dist/qmd.d.ts +1 -1
  159. package/dist/recall-disclosure-escalation.d.ts +1 -1
  160. package/dist/recall-explain-renderer.d.ts +1 -1
  161. package/dist/recall-explain-renderer.js +3 -3
  162. package/dist/recall-planner-llm.d.ts +1 -1
  163. package/dist/recall-state.d.ts +1 -1
  164. package/dist/recall-tag-filter.d.ts +1 -1
  165. package/dist/recall-xray-cli.d.ts +1 -1
  166. package/dist/recall-xray-cli.js +4 -4
  167. package/dist/recall-xray-renderer.d.ts +1 -1
  168. package/dist/recall-xray-renderer.js +3 -3
  169. package/dist/recall-xray.d.ts +1 -1
  170. package/dist/recall-xray.js +2 -2
  171. package/dist/resolve-auth-token.d.ts +1 -1
  172. package/dist/resume-bundles.js +2 -2
  173. package/dist/retrieval-agents.d.ts +1 -1
  174. package/dist/retrieval-tiers.d.ts +1 -1
  175. package/dist/routing/engine.d.ts +1 -1
  176. package/dist/routing/store.d.ts +1 -1
  177. package/dist/schemas.d.ts +28 -28
  178. package/dist/search/embed-helper.d.ts +1 -1
  179. package/dist/search/factory.d.ts +1 -1
  180. package/dist/search/index.d.ts +1 -1
  181. package/dist/search/lancedb-backend.d.ts +1 -1
  182. package/dist/search/meilisearch-backend.d.ts +1 -1
  183. package/dist/search/noop-backend.d.ts +1 -1
  184. package/dist/search/orama-backend.d.ts +1 -1
  185. package/dist/search/port.d.ts +1 -1
  186. package/dist/search/remote-backend.d.ts +1 -1
  187. package/dist/{semantic-consolidation-D5U0Mrdb.d.ts → semantic-consolidation-DXmtQ_4B.d.ts} +1 -1
  188. package/dist/semantic-consolidation.d.ts +2 -2
  189. package/dist/semantic-consolidation.js +4 -4
  190. package/dist/semantic-rule-promotion.js +3 -3
  191. package/dist/semantic-rule-verifier.d.ts +1 -1
  192. package/dist/semantic-rule-verifier.js +3 -3
  193. package/dist/session-observer-bands.d.ts +1 -1
  194. package/dist/session-observer-state.d.ts +1 -1
  195. package/dist/shared-context/manager.d.ts +1 -1
  196. package/dist/signal.d.ts +1 -1
  197. package/dist/storage.d.ts +1 -1
  198. package/dist/storage.js +2 -2
  199. package/dist/summarizer.d.ts +1 -1
  200. package/dist/summary-snapshot.d.ts +1 -1
  201. package/dist/temporal-supersession.d.ts +1 -1
  202. package/dist/temporal-validity.d.ts +1 -1
  203. package/dist/threading.d.ts +1 -1
  204. package/dist/tier-migration.d.ts +1 -1
  205. package/dist/tier-routing.d.ts +1 -1
  206. package/dist/topics.d.ts +1 -1
  207. package/dist/transcript.d.ts +1 -1
  208. package/dist/transfer/types.d.ts +12 -12
  209. package/dist/{types-2NoBoRBM.d.ts → types-CEWBmjCH.d.ts} +14 -0
  210. package/dist/types.d.ts +1 -1
  211. package/dist/types.js +1 -1
  212. package/dist/utility-runtime.d.ts +1 -1
  213. package/dist/verified-recall.js +3 -3
  214. package/package.json +2 -2
  215. package/src/access-boundary.ts +19 -1
  216. package/src/access-cli.ts +65 -2
  217. package/src/access-http.ts +47 -3
  218. package/src/access-mcp.ts +128 -2
  219. package/src/access-operations.ts +305 -0
  220. package/src/access-service.ts +137 -0
  221. package/src/access-surface-catalog.test.ts +1 -1
  222. package/src/access-surface-catalog.ts +17 -0
  223. package/src/cli.ts +2 -0
  224. package/src/coding/architecture-surfaces.test.ts +2 -0
  225. package/src/coding/codegraph-runtime.ts +773 -0
  226. package/src/coding/codegraph-surfaces.test.ts +880 -0
  227. package/src/coding/codegraph-surfaces.ts +771 -0
  228. package/src/coding/coding-knowledge-config.ts +7 -0
  229. package/src/coding/coding-namespace.ts +1 -1
  230. package/src/coding/decision-surfaces.test.ts +2 -0
  231. package/src/coding/session-delta-surfaces.test.ts +385 -0
  232. package/src/coding/session-delta-surfaces.ts +325 -0
  233. package/src/coding/session-delta.test.ts +411 -0
  234. package/src/coding/session-delta.ts +442 -0
  235. package/src/config.test.ts +2 -0
  236. package/src/types.ts +14 -0
  237. package/dist/chunk-2EN5WZQB.js.map +0 -1
  238. package/dist/chunk-7MOTEVAA.js.map +0 -1
  239. package/dist/chunk-DO7MDZMU.js.map +0 -1
  240. package/dist/chunk-DQHZA7Y3.js.map +0 -1
  241. package/dist/chunk-NEILAC3H.js +0 -153
  242. package/dist/chunk-NEILAC3H.js.map +0 -1
  243. package/dist/chunk-O4ZIV62T.js.map +0 -1
  244. package/dist/chunk-SEK4XIDN.js.map +0 -1
  245. package/dist/chunk-V56S3A23.js.map +0 -1
  246. /package/dist/{chunk-ADUAF5EV.js.map → chunk-24FCDBJV.js.map} +0 -0
  247. /package/dist/{chunk-3VVH6ZQW.js.map → chunk-5S53ZBPH.js.map} +0 -0
  248. /package/dist/{chunk-2D27ODNX.js.map → chunk-B55EAZNF.js.map} +0 -0
  249. /package/dist/{chunk-W4MICQIZ.js.map → chunk-C5AOVGVC.js.map} +0 -0
  250. /package/dist/{chunk-UOCLRM74.js.map → chunk-D7PQ7HZL.js.map} +0 -0
  251. /package/dist/{chunk-HXNMDPHN.js.map → chunk-DT2ZGQT7.js.map} +0 -0
  252. /package/dist/{chunk-QFG23CRE.js.map → chunk-EPVIBPVE.js.map} +0 -0
  253. /package/dist/{chunk-U2OBZSGG.js.map → chunk-IZLNJYLX.js.map} +0 -0
  254. /package/dist/{chunk-KYH53EFD.js.map → chunk-JIKBEDSB.js.map} +0 -0
  255. /package/dist/{chunk-3BRA3N5A.js.map → chunk-KCRV3HVN.js.map} +0 -0
  256. /package/dist/{chunk-AFWEUTMS.js.map → chunk-MOGFK2DU.js.map} +0 -0
  257. /package/dist/{chunk-SAC5V6JT.js.map → chunk-MSUA4KAK.js.map} +0 -0
  258. /package/dist/{chunk-VFVG4NS2.js.map → chunk-NXNUG7IA.js.map} +0 -0
  259. /package/dist/{chunk-66HROLW5.js.map → chunk-P7IDNF7H.js.map} +0 -0
  260. /package/dist/{chunk-FM7KLRKN.js.map → chunk-PILLH262.js.map} +0 -0
  261. /package/dist/{chunk-6C2BMUZA.js.map → chunk-QXWQ5V24.js.map} +0 -0
  262. /package/dist/{chunk-4IQNAOP3.js.map → chunk-SN5DFE34.js.map} +0 -0
  263. /package/dist/{chunk-WIKNVFBS.js.map → chunk-UX5QTAFE.js.map} +0 -0
  264. /package/dist/{chunk-MCV2DD6F.js.map → chunk-WVTNZUER.js.map} +0 -0
  265. /package/dist/{chunk-ZLXGFAML.js.map → chunk-YI3KC2B5.js.map} +0 -0
  266. /package/dist/{chunk-W4ELOUNX.js.map → chunk-YWYZPKK3.js.map} +0 -0
  267. /package/dist/{chunk-NUZ3N445.js.map → chunk-YXZPKBFW.js.map} +0 -0
  268. /package/dist/{chunk-GCOSQBQ2.js.map → chunk-ZKD3UVEO.js.map} +0 -0
package/src/access-mcp.ts CHANGED
@@ -111,6 +111,22 @@ const MCP_MIGRATED_OPERATIONS: Readonly<Record<string, OperationName>> = {
111
111
  "engram.memory_store": "memory_store",
112
112
  "engram.coding_decision": "coding_decision",
113
113
  "engram.coding_architecture": "coding_architecture",
114
+ // codegraph parity tools (issue #1554) — each maps to its boundary op.
115
+ "engram.codegraph_index": "codegraph_index",
116
+ "engram.codegraph_list_projects": "codegraph_list_projects",
117
+ "engram.codegraph_delete_project": "codegraph_delete_project",
118
+ "engram.codegraph_index_status": "codegraph_index_status",
119
+ "engram.codegraph_search_graph": "codegraph_search_graph",
120
+ "engram.codegraph_trace_path": "codegraph_trace_path",
121
+ "engram.codegraph_detect_changes": "codegraph_detect_changes",
122
+ "engram.codegraph_query_graph": "codegraph_query_graph",
123
+ "engram.codegraph_get_schema": "codegraph_get_schema",
124
+ "engram.codegraph_get_snippet": "codegraph_get_snippet",
125
+ "engram.codegraph_get_architecture": "codegraph_get_architecture",
126
+ "engram.codegraph_search_code": "codegraph_search_code",
127
+ "engram.codegraph_manage_adr": "codegraph_manage_adr",
128
+ "engram.codegraph_ingest_traces": "codegraph_ingest_traces",
129
+ "engram.coding_delta": "coding_delta",
114
130
  };
115
131
 
116
132
  function resolveChatGptInspectorRecallSessionKey(
@@ -331,6 +347,13 @@ export class EngramMcpServer {
331
347
  * (issue #1548 Track A PR 3, rule 39).
332
348
  */
333
349
  private readonly architectureCardVisible: boolean;
350
+ /**
351
+ * Whether the 14 codegraph parity tools should appear in `tools/list`
352
+ * (issue #1554). Config-only -- runtime availability is checked at call
353
+ * time. When false the tools array is byte-identical to pre-feature.
354
+ */
355
+ private readonly codegraphVisible: boolean;
356
+ private readonly sessionDeltaVisible: boolean;
334
357
 
335
358
  constructor(
336
359
  private readonly service: EngramAccessService,
@@ -341,6 +364,8 @@ export class EngramMcpServer {
341
364
  emitLegacyTools?: boolean;
342
365
  codingDecisionVisible?: boolean;
343
366
  architectureCardVisible?: boolean;
367
+ codegraphVisible?: boolean;
368
+ sessionDeltaVisible?: boolean;
344
369
  } = {},
345
370
  ) {
346
371
  this.citationsEnabled = options.citationsEnabled === true;
@@ -348,6 +373,8 @@ export class EngramMcpServer {
348
373
  this.emitLegacyTools = options.emitLegacyTools !== false;
349
374
  this.codingDecisionVisible = options.codingDecisionVisible === true;
350
375
  this.architectureCardVisible = options.architectureCardVisible === true;
376
+ this.codegraphVisible = options.codegraphVisible === true;
377
+ this.sessionDeltaVisible = options.sessionDeltaVisible === true;
351
378
  this.authenticatedPrincipal =
352
379
  options.principal?.trim() ||
353
380
  readEnvVar("OPENCLAW_ENGRAM_ACCESS_PRINCIPAL")?.trim() ||
@@ -2033,6 +2060,95 @@ export class EngramMcpServer {
2033
2060
  );
2034
2061
  this.tools = [...this.tools, ...architectureTools];
2035
2062
  }
2063
+ if (this.codegraphVisible) {
2064
+ // The 14 codegraph parity tools (issue #1554). Each delegates to its
2065
+ // boundary operation; the MCP dispatch injects the `tool` field from
2066
+ // the operation name. The inputSchema is intentionally permissive —
2067
+ // the boundary's zod schema owns validation (rule 51).
2068
+ const codegraphToolDefs: Array<{ suffix: string; description: string; required?: string[] }> = [
2069
+ { suffix: "index", description: "Index a repository into the code graph.", required: ["repoRoot"] },
2070
+ { suffix: "list_projects", description: "List code graph projects for the principal." },
2071
+ { suffix: "delete_project", description: "Delete a code graph project (requires confirm: true).", required: ["confirm"] },
2072
+ { suffix: "index_status", description: "Get the indexing status for a project." },
2073
+ { suffix: "search_graph", description: "Search the code graph for symbols.", required: ["query"] },
2074
+ { suffix: "trace_path", description: "Trace call/dependency paths from a starting symbol.", required: ["start"] },
2075
+ { suffix: "detect_changes", description: "Detect changed symbols since a git ref.", required: ["head"] },
2076
+ { suffix: "query_graph", description: "Run a structured query against the code graph.", required: ["structuredQuery"] },
2077
+ { suffix: "get_schema", description: "Get the code graph schema statistics." },
2078
+ { suffix: "get_snippet", description: "Get a source code snippet for a symbol.", required: ["qualifiedName"] },
2079
+ { suffix: "get_architecture", description: "Get the composed architecture card + graph stats." },
2080
+ { suffix: "search_code", description: "Search the code graph for code (functions, classes, methods).", required: ["query"] },
2081
+ { suffix: "manage_adr", description: "Manage ADRs via Track A decision records (list, get, record, supersede).", required: ["subcommand"] },
2082
+ { suffix: "ingest_traces", description: "Ingest call-site traces to upgrade edge confidence.", required: ["traces"] },
2083
+ ];
2084
+ for (const def of codegraphToolDefs) {
2085
+ const tools = withToolAliases(
2086
+ {
2087
+ name: `engram.codegraph_${def.suffix}`,
2088
+ description: def.description,
2089
+ inputSchema: {
2090
+ type: "object",
2091
+ properties: {
2092
+ sessionKey: { type: "string", description: "Session identifier whose coding context scopes the operation." },
2093
+ project: { type: "string", description: "Explicit project id (defaults to session coding context)." },
2094
+ principal: { type: "string", description: "Authenticated principal override." },
2095
+ query: { type: "string" },
2096
+ limit: { type: "number" },
2097
+ start: { type: "string" },
2098
+ direction: { type: "string", enum: ["inbound", "outbound", "both"] },
2099
+ depth: { type: "number" },
2100
+ qualifiedName: { type: "string" },
2101
+ path: { type: "string" },
2102
+ structuredQuery: { type: "object" },
2103
+ head: { type: "string" },
2104
+ repoRoot: { type: "string" },
2105
+ mode: { type: "string", enum: ["auto", "full", "incremental"] },
2106
+ confirm: { type: "boolean" },
2107
+ subcommand: { type: "string", enum: ["list", "get", "record", "supersede"] },
2108
+ id: { type: "string" },
2109
+ title: { type: "string" },
2110
+ status: { type: "string", enum: ["proposed", "accepted", "superseded", "rejected"] },
2111
+ context: { type: "string" },
2112
+ decision: { type: "string" },
2113
+ consequences: { type: "string" },
2114
+ entityRefs: { type: "array", items: { type: "string" } },
2115
+ supersedesId: { type: "string" },
2116
+ traces: { type: "array", items: { type: "object" } },
2117
+ },
2118
+ required: def.required ?? [],
2119
+ additionalProperties: false,
2120
+ },
2121
+ },
2122
+ this.emitLegacyTools,
2123
+ );
2124
+ this.tools = [...this.tools, ...tools];
2125
+ }
2126
+ }
2127
+ if (this.sessionDeltaVisible) {
2128
+ const deltaTools = withToolAliases(
2129
+ {
2130
+ name: "engram.coding_delta",
2131
+ description:
2132
+ "Get the session delta (commits + touched files since last seen) for the session's coding namespace (issue #1548 Track A PR 4). Subcommand: get.",
2133
+ inputSchema: {
2134
+ type: "object",
2135
+ properties: {
2136
+ subcommand: {
2137
+ type: "string",
2138
+ enum: ["get"],
2139
+ description: "Which delta operation to run.",
2140
+ },
2141
+ sessionKey: { type: "string", description: "Session identifier whose coding context scopes the operation." },
2142
+ namespace: { type: "string", description: "Optional explicit namespace (overrides coding-context overlay)." },
2143
+ },
2144
+ required: ["subcommand"],
2145
+ additionalProperties: false,
2146
+ },
2147
+ },
2148
+ this.emitLegacyTools,
2149
+ );
2150
+ this.tools = [...this.tools, ...deltaTools];
2151
+ }
2036
2152
  }
2037
2153
 
2038
2154
  /** Get clientInfo for a specific MCP session. Returns undefined for non-MCP requests. */
@@ -2394,8 +2510,18 @@ export class EngramMcpServer {
2394
2510
  if (!op) {
2395
2511
  throw new EngramAccessInputError(`access-boundary: operation not registered: ${migrated}`);
2396
2512
  }
2397
- const envelope =
2398
- migrated === "memory_store" ? parseMcpRequest("memoryStore", args) : args;
2513
+ let envelope: Record<string, unknown>;
2514
+ if (migrated === "memory_store") {
2515
+ envelope = parseMcpRequest("memoryStore", args);
2516
+ } else if (migrated.startsWith("codegraph_")) {
2517
+ // codegraph parity tools (issue #1554): the surface handler dispatches
2518
+ // on the `tool` field. The MCP tool name encodes it (e.g.
2519
+ // codegraph_search_graph → tool: "search_graph"); inject it so the
2520
+ // client payload does not need to carry the internal dispatch field.
2521
+ envelope = { ...args, tool: migrated.slice("codegraph_".length) };
2522
+ } else {
2523
+ envelope = args;
2524
+ }
2399
2525
  // The registry erases In/Out at the Map boundary; the caller knows the
2400
2526
  // concrete output shape ({ result: <service response> }) so the cast is
2401
2527
  // the type-erasure seam, not a leap of faith.
@@ -29,6 +29,16 @@ import {
29
29
  type ArchitectureSurfaceRequest,
30
30
  type ArchitectureSurfaceResponse,
31
31
  } from "./coding/architecture-surfaces.js";
32
+ import {
33
+ type CodegraphSurfaceRequest,
34
+ type CodegraphSurfaceResponse,
35
+ isCodegraphToolName,
36
+ } from "./coding/codegraph-surfaces.js";
37
+ import {
38
+ DELTA_SUBCOMMANDS,
39
+ type DeltaSurfaceRequest,
40
+ type DeltaSurfaceResponse,
41
+ } from "./coding/session-delta-surfaces.js";
32
42
 
33
43
  // ---------------------------------------------------------------------------
34
44
  // memory_get — fetch one memory by id
@@ -250,6 +260,90 @@ export const codingArchitectureOperation = defineOperation<
250
260
  },
251
261
  });
252
262
 
263
+ const codegraphSurfaceSchema = z.preprocess(
264
+ (data) => {
265
+ if (data !== null && typeof data === "object" && !Array.isArray(data)) {
266
+ const obj = data as Record<string, unknown>;
267
+ const cleaned: Record<string, unknown> = {};
268
+ for (const [key, value] of Object.entries(obj)) {
269
+ if (value !== null) cleaned[key] = value;
270
+ }
271
+ return cleaned;
272
+ }
273
+ return data;
274
+ },
275
+ z.object({
276
+ tool: z.string().refine(isCodegraphToolName, {
277
+ message: "tool must be one of the codegraph tool names",
278
+ }),
279
+ sessionKey: z.string().max(512).optional(),
280
+ principal: z.string().max(256).optional(),
281
+ project: z.string().max(256).optional(),
282
+ query: z.string().max(2048).optional(),
283
+ limit: z.number().int().positive().max(200).optional(),
284
+ start: z.string().max(512).optional(),
285
+ direction: z.string().max(64).optional(),
286
+ depth: z.number().int().positive().max(10).optional(),
287
+ qualifiedName: z.string().max(1024).optional(),
288
+ path: z.string().max(2048).optional(),
289
+ structuredQuery: z.record(z.string(), z.unknown()).optional(),
290
+ head: z.string().max(256).optional(),
291
+ repoRoot: z.string().max(2048).optional(),
292
+ mode: z.string().max(64).optional(),
293
+ confirm: z.boolean().optional(),
294
+ subcommand: z.string().max(64).optional(),
295
+ id: z.string().max(512).optional(),
296
+ title: z.string().max(512).optional(),
297
+ status: z.string().max(64).optional(),
298
+ context: z.string().max(8192).optional(),
299
+ decision: z.string().max(8192).optional(),
300
+ consequences: z.string().max(8192).optional(),
301
+ entityRefs: z.array(z.string().max(256)).optional(),
302
+ supersedesId: z.string().max(512).optional(),
303
+ traces: z.array(z.unknown()).optional(),
304
+ }),
305
+ ) as z.ZodType<CodegraphSurfaceRequest>;
306
+
307
+ // ---------------------------------------------------------------------------
308
+ // coding_delta — session-delta surface (issue #1548 Track A PR 4)
309
+ // ---------------------------------------------------------------------------
310
+
311
+ const codingDeltaSchema = z.preprocess(
312
+ (data) => {
313
+ if (data !== null && typeof data === "object" && !Array.isArray(data)) {
314
+ const obj = data as Record<string, unknown>;
315
+ const cleaned: Record<string, unknown> = {};
316
+ for (const [key, value] of Object.entries(obj)) {
317
+ if (value !== null) cleaned[key] = value;
318
+ }
319
+ return cleaned;
320
+ }
321
+ return data;
322
+ },
323
+ z.object({
324
+ subcommand: z.enum(DELTA_SUBCOMMANDS),
325
+ sessionKey: z.string().trim().max(512).optional(),
326
+ namespace: z.string().trim().max(256).optional(),
327
+ }),
328
+ );
329
+
330
+ export type CodingDeltaInput = DeltaSurfaceRequest;
331
+ export type CodingDeltaOutput = { result: DeltaSurfaceResponse };
332
+
333
+ export const codingDeltaOperation = defineOperation<
334
+ CodingDeltaInput,
335
+ CodingDeltaOutput
336
+ >({
337
+ name: "coding_delta",
338
+ description:
339
+ "Get the session delta (commits + touched files since last seen) for the session's coding namespace (issue #1548 Track A PR 4).",
340
+ schema: codingDeltaSchema as z.ZodType<CodingDeltaInput>,
341
+ handler: async (input, ctx) => {
342
+ const result = await ctx.service.codingDelta(input, ctx.authenticatedPrincipal);
343
+ return { result };
344
+ },
345
+ });
346
+
253
347
  // ---------------------------------------------------------------------------
254
348
  // Surface registration map — what each transport calls the pilot ops
255
349
  // ---------------------------------------------------------------------------
@@ -259,10 +353,221 @@ export const codingArchitectureOperation = defineOperation<
259
353
  * the boundary owns today. The fitness test treats this set as the migrated
260
354
  * set; everything else on a surface is unmigrated and counted by the ratchet.
261
355
  */
356
+ export const codegraphIndexOperation = defineOperation<
357
+ CodegraphSurfaceRequest,
358
+ { result: CodegraphSurfaceResponse }
359
+ >({
360
+ name: "codegraph_index",
361
+ description:
362
+ "Codegraph parity tool (issue #1554): index. Delegates to the shared codegraph surface handler.",
363
+ schema: codegraphSurfaceSchema,
364
+ handler: async (input, ctx) => {
365
+ const result = await ctx.service.codegraphTool(input, ctx.authenticatedPrincipal);
366
+ return { result };
367
+ },
368
+ });
369
+
370
+ export const codegraphListProjectsOperation = defineOperation<
371
+ CodegraphSurfaceRequest,
372
+ { result: CodegraphSurfaceResponse }
373
+ >({
374
+ name: "codegraph_list_projects",
375
+ description:
376
+ "Codegraph parity tool (issue #1554): list_projects. Delegates to the shared codegraph surface handler.",
377
+ schema: codegraphSurfaceSchema,
378
+ handler: async (input, ctx) => {
379
+ const result = await ctx.service.codegraphTool(input, ctx.authenticatedPrincipal);
380
+ return { result };
381
+ },
382
+ });
383
+
384
+ export const codegraphDeleteProjectOperation = defineOperation<
385
+ CodegraphSurfaceRequest,
386
+ { result: CodegraphSurfaceResponse }
387
+ >({
388
+ name: "codegraph_delete_project",
389
+ description:
390
+ "Codegraph parity tool (issue #1554): delete_project. Delegates to the shared codegraph surface handler.",
391
+ schema: codegraphSurfaceSchema,
392
+ handler: async (input, ctx) => {
393
+ const result = await ctx.service.codegraphTool(input, ctx.authenticatedPrincipal);
394
+ return { result };
395
+ },
396
+ });
397
+
398
+ export const codegraphIndexStatusOperation = defineOperation<
399
+ CodegraphSurfaceRequest,
400
+ { result: CodegraphSurfaceResponse }
401
+ >({
402
+ name: "codegraph_index_status",
403
+ description:
404
+ "Codegraph parity tool (issue #1554): index_status. Delegates to the shared codegraph surface handler.",
405
+ schema: codegraphSurfaceSchema,
406
+ handler: async (input, ctx) => {
407
+ const result = await ctx.service.codegraphTool(input, ctx.authenticatedPrincipal);
408
+ return { result };
409
+ },
410
+ });
411
+
412
+ export const codegraphSearchGraphOperation = defineOperation<
413
+ CodegraphSurfaceRequest,
414
+ { result: CodegraphSurfaceResponse }
415
+ >({
416
+ name: "codegraph_search_graph",
417
+ description:
418
+ "Codegraph parity tool (issue #1554): search_graph. Delegates to the shared codegraph surface handler.",
419
+ schema: codegraphSurfaceSchema,
420
+ handler: async (input, ctx) => {
421
+ const result = await ctx.service.codegraphTool(input, ctx.authenticatedPrincipal);
422
+ return { result };
423
+ },
424
+ });
425
+
426
+ export const codegraphTracePathOperation = defineOperation<
427
+ CodegraphSurfaceRequest,
428
+ { result: CodegraphSurfaceResponse }
429
+ >({
430
+ name: "codegraph_trace_path",
431
+ description:
432
+ "Codegraph parity tool (issue #1554): trace_path. Delegates to the shared codegraph surface handler.",
433
+ schema: codegraphSurfaceSchema,
434
+ handler: async (input, ctx) => {
435
+ const result = await ctx.service.codegraphTool(input, ctx.authenticatedPrincipal);
436
+ return { result };
437
+ },
438
+ });
439
+
440
+ export const codegraphDetectChangesOperation = defineOperation<
441
+ CodegraphSurfaceRequest,
442
+ { result: CodegraphSurfaceResponse }
443
+ >({
444
+ name: "codegraph_detect_changes",
445
+ description:
446
+ "Codegraph parity tool (issue #1554): detect_changes. Delegates to the shared codegraph surface handler.",
447
+ schema: codegraphSurfaceSchema,
448
+ handler: async (input, ctx) => {
449
+ const result = await ctx.service.codegraphTool(input, ctx.authenticatedPrincipal);
450
+ return { result };
451
+ },
452
+ });
453
+
454
+ export const codegraphQueryGraphOperation = defineOperation<
455
+ CodegraphSurfaceRequest,
456
+ { result: CodegraphSurfaceResponse }
457
+ >({
458
+ name: "codegraph_query_graph",
459
+ description:
460
+ "Codegraph parity tool (issue #1554): query_graph. Delegates to the shared codegraph surface handler.",
461
+ schema: codegraphSurfaceSchema,
462
+ handler: async (input, ctx) => {
463
+ const result = await ctx.service.codegraphTool(input, ctx.authenticatedPrincipal);
464
+ return { result };
465
+ },
466
+ });
467
+
468
+ export const codegraphGetSchemaOperation = defineOperation<
469
+ CodegraphSurfaceRequest,
470
+ { result: CodegraphSurfaceResponse }
471
+ >({
472
+ name: "codegraph_get_schema",
473
+ description:
474
+ "Codegraph parity tool (issue #1554): get_schema. Delegates to the shared codegraph surface handler.",
475
+ schema: codegraphSurfaceSchema,
476
+ handler: async (input, ctx) => {
477
+ const result = await ctx.service.codegraphTool(input, ctx.authenticatedPrincipal);
478
+ return { result };
479
+ },
480
+ });
481
+
482
+ export const codegraphGetSnippetOperation = defineOperation<
483
+ CodegraphSurfaceRequest,
484
+ { result: CodegraphSurfaceResponse }
485
+ >({
486
+ name: "codegraph_get_snippet",
487
+ description:
488
+ "Codegraph parity tool (issue #1554): get_snippet. Delegates to the shared codegraph surface handler.",
489
+ schema: codegraphSurfaceSchema,
490
+ handler: async (input, ctx) => {
491
+ const result = await ctx.service.codegraphTool(input, ctx.authenticatedPrincipal);
492
+ return { result };
493
+ },
494
+ });
495
+
496
+ export const codegraphGetArchitectureOperation = defineOperation<
497
+ CodegraphSurfaceRequest,
498
+ { result: CodegraphSurfaceResponse }
499
+ >({
500
+ name: "codegraph_get_architecture",
501
+ description:
502
+ "Codegraph parity tool (issue #1554): get_architecture. Delegates to the shared codegraph surface handler.",
503
+ schema: codegraphSurfaceSchema,
504
+ handler: async (input, ctx) => {
505
+ const result = await ctx.service.codegraphTool(input, ctx.authenticatedPrincipal);
506
+ return { result };
507
+ },
508
+ });
509
+
510
+ export const codegraphSearchCodeOperation = defineOperation<
511
+ CodegraphSurfaceRequest,
512
+ { result: CodegraphSurfaceResponse }
513
+ >({
514
+ name: "codegraph_search_code",
515
+ description:
516
+ "Codegraph parity tool (issue #1554): search_code. Delegates to the shared codegraph surface handler.",
517
+ schema: codegraphSurfaceSchema,
518
+ handler: async (input, ctx) => {
519
+ const result = await ctx.service.codegraphTool(input, ctx.authenticatedPrincipal);
520
+ return { result };
521
+ },
522
+ });
523
+
524
+ export const codegraphManageAdrOperation = defineOperation<
525
+ CodegraphSurfaceRequest,
526
+ { result: CodegraphSurfaceResponse }
527
+ >({
528
+ name: "codegraph_manage_adr",
529
+ description:
530
+ "Codegraph parity tool (issue #1554): manage_adr. Delegates to the shared codegraph surface handler.",
531
+ schema: codegraphSurfaceSchema,
532
+ handler: async (input, ctx) => {
533
+ const result = await ctx.service.codegraphTool(input, ctx.authenticatedPrincipal);
534
+ return { result };
535
+ },
536
+ });
537
+
538
+ export const codegraphIngestTracesOperation = defineOperation<
539
+ CodegraphSurfaceRequest,
540
+ { result: CodegraphSurfaceResponse }
541
+ >({
542
+ name: "codegraph_ingest_traces",
543
+ description:
544
+ "Codegraph parity tool (issue #1554): ingest_traces. Delegates to the shared codegraph surface handler.",
545
+ schema: codegraphSurfaceSchema,
546
+ handler: async (input, ctx) => {
547
+ const result = await ctx.service.codegraphTool(input, ctx.authenticatedPrincipal);
548
+ return { result };
549
+ },
550
+ });
551
+
262
552
  export const REGISTERED_OPERATIONS = [
263
553
  memoryGetOperation.spec.name,
264
554
  memorySearchOperation.spec.name,
265
555
  memoryStoreOperation.spec.name,
266
556
  codingDecisionOperation.spec.name,
267
557
  codingArchitectureOperation.spec.name,
558
+ codegraphIndexOperation.spec.name,
559
+ codegraphListProjectsOperation.spec.name,
560
+ codegraphDeleteProjectOperation.spec.name,
561
+ codegraphIndexStatusOperation.spec.name,
562
+ codegraphSearchGraphOperation.spec.name,
563
+ codegraphTracePathOperation.spec.name,
564
+ codegraphDetectChangesOperation.spec.name,
565
+ codegraphQueryGraphOperation.spec.name,
566
+ codegraphGetSchemaOperation.spec.name,
567
+ codegraphGetSnippetOperation.spec.name,
568
+ codegraphGetArchitectureOperation.spec.name,
569
+ codegraphSearchCodeOperation.spec.name,
570
+ codegraphManageAdrOperation.spec.name,
571
+ codegraphIngestTracesOperation.spec.name,
572
+ codingDeltaOperation.spec.name,
268
573
  ] as const;
@@ -1,6 +1,7 @@
1
1
  import { stat } from "node:fs/promises";
2
2
  import * as nodeFs from "node:fs/promises";
3
3
  import { constants as fsConstants } from "node:fs";
4
+ import { readdirSync, unlinkSync } from "node:fs";
4
5
  import { createHash } from "node:crypto";
5
6
  import { ZodError } from "zod";
6
7
  import { AccessIdempotencyStore, hashAccessIdempotencyPayload } from "./access-idempotency.js";
@@ -28,6 +29,26 @@ import {
28
29
  ARCHITECTURE_CARD_TAG,
29
30
  } from "./coding/architecture-surfaces.js";
30
31
  import { buildArchitectureCard, createArchitectureCardSummariser } from "./coding/architecture-card.js";
32
+ import {
33
+ handleCodegraphTool,
34
+ type CodegraphSurfaceContext,
35
+ type CodegraphSurfaceRequest,
36
+ type CodegraphSurfaceResponse,
37
+ } from "./coding/codegraph-surfaces.js";
38
+ import {
39
+ codegraphSurfaceVisible,
40
+ getCodegraphStore,
41
+ makeCodegraphRuntimeDelegates,
42
+ resolveCodegraphProjectId,
43
+ type CodegraphStore,
44
+ } from "./coding/codegraph-runtime.js";
45
+ import {
46
+ handleCodingDelta,
47
+ type DeltaSurfaceRequest,
48
+ type DeltaSurfaceResponse,
49
+ type DeltaSurfaceStorage,
50
+ } from "./coding/session-delta-surfaces.js";
51
+ import { defaultGitInvoker } from "./coding/git-context.js";
31
52
  import { createVersion } from "./page-versioning.js";
32
53
  import { WorkStorage } from "./work/storage.js";
33
54
  import {
@@ -4456,6 +4477,65 @@ export class EngramAccessService {
4456
4477
  };
4457
4478
  }
4458
4479
 
4480
+ /**
4481
+ * Codegraph parity tool delegate (issue #1554). All three surfaces (MCP,
4482
+ * HTTP, CLI) arrive here via the codegraph_* boundary operations. The
4483
+ * handler lives in coding/codegraph-surfaces.ts; this method just wires
4484
+ * the context. Memory dir + principal + coding-context lookup come from
4485
+ * the orchestrator/access-service fabric -- no handler-side state.
4486
+ */
4487
+ async codegraphTool(
4488
+ request: CodegraphSurfaceRequest,
4489
+ authenticatedPrincipal?: string,
4490
+ ): Promise<CodegraphSurfaceResponse> {
4491
+ const principal = authenticatedPrincipal ?? "default";
4492
+ const memoryDir = this.orchestrator.config.memoryDir;
4493
+ const ctx: CodegraphSurfaceContext = {
4494
+ config: this.orchestrator.config,
4495
+ memoryDir,
4496
+ principal,
4497
+ getCodingContext: (sk) => this.orchestrator.getCodingContextForSession(sk),
4498
+ // Project resolution chokepoint lives in codegraph-runtime.ts so every
4499
+ // store-backed tool derives the same id and the tagged error flows back
4500
+ // as a structured response (issue #1554 threads 7/9/11). Thin wiring.
4501
+ resolveStore: async (req) => {
4502
+ const projectId = resolveCodegraphProjectId({
4503
+ request: req,
4504
+ getCodingContext: (sk) => this.orchestrator.getCodingContextForSession(sk),
4505
+ });
4506
+ return getCodegraphStore({
4507
+ config: this.orchestrator.config,
4508
+ memoryDir,
4509
+ principal,
4510
+ projectId,
4511
+ repoRoot: req.repoRoot,
4512
+ }) as Promise<CodegraphStore>;
4513
+ },
4514
+ listDirs: (dir) => {
4515
+ try {
4516
+ return readdirSync(dir) as readonly string[];
4517
+ } catch {
4518
+ return [];
4519
+ }
4520
+ },
4521
+ removeFile: (filePath) => unlinkSync(filePath), // propagate failures → deleteCodegraphProject classifies (thread 7)
4522
+ throwInputError: (msg) => {
4523
+ throw new EngramAccessInputError(msg);
4524
+ },
4525
+ delegateDecisionRecord: async (decisionRequest) => {
4526
+ return this.codingDecision(decisionRequest, authenticatedPrincipal);
4527
+ },
4528
+ buildArchitectureCard: async (repoRoot) => {
4529
+ return buildArchitectureCard(repoRoot, {
4530
+ llmSummary: this.orchestrator.config.codingKnowledge?.architectureCardLlmSummary === true,
4531
+ summariser: createArchitectureCardSummariser(this.fallbackLlmRef ?? this.localLlmRef),
4532
+ });
4533
+ },
4534
+ ...makeCodegraphRuntimeDelegates(),
4535
+ };
4536
+ return handleCodegraphTool(request, ctx);
4537
+ }
4538
+
4459
4539
  /** Whether the coding_decision tool should appear in tools/list (rule 39). */
4460
4540
  get decisionRecordSurfaceVisible(): boolean {
4461
4541
  return this.orchestrator.config.codingKnowledge?.enabled === true
@@ -4500,6 +4580,15 @@ export class EngramAccessService {
4500
4580
  return this.orchestrator.config.codingKnowledge?.enabled === true
4501
4581
  && this.orchestrator.config.codingKnowledge?.architectureCard === true;
4502
4582
  }
4583
+
4584
+ /**
4585
+ * Whether the 14 codegraph parity tools should appear in tools/list
4586
+ * (rule 39). Config-only -- runtime availability is checked at call time.
4587
+ * When false the tools array is byte-identical to pre-feature.
4588
+ */
4589
+ get codegraphSurfaceVisible(): boolean {
4590
+ return codegraphSurfaceVisible(this.orchestrator.config);
4591
+ }
4503
4592
  /**
4504
4593
  * Thin delegate — handler logic in coding/architecture-surfaces.ts (#1548 PR3).
4505
4594
  * All three surfaces (MCP/HTTP/CLI) arrive here via the boundary operation.
@@ -4545,6 +4634,54 @@ export class EngramAccessService {
4545
4634
  });
4546
4635
  }
4547
4636
 
4637
+ /** Whether the coding_delta tool should appear in tools/list (rule 39). */
4638
+ get sessionDeltaSurfaceVisible(): boolean {
4639
+ return this.orchestrator.config.codingKnowledge?.enabled === true
4640
+ && this.orchestrator.config.codingKnowledge?.sessionDelta === true;
4641
+ }
4642
+ /**
4643
+ * Thin delegate — handler logic in coding/session-delta-surfaces.ts (#1548 PR4).
4644
+ * All three surfaces (MCP/HTTP/CLI) arrive here via the boundary operation.
4645
+ * Namespace resolution uses the SAME coding-scoped read path as the other
4646
+ * coding surfaces; the delta state file lives under
4647
+ * `<memoryDir>/state/coding-knowledge/<namespace>.json`.
4648
+ */
4649
+ async codingDelta(
4650
+ request: DeltaSurfaceRequest,
4651
+ authenticatedPrincipal?: string,
4652
+ ): Promise<DeltaSurfaceResponse> {
4653
+ return handleCodingDelta(request, {
4654
+ codingKnowledge: this.orchestrator.config.codingKnowledge,
4655
+ getCodingContext: (sk) => this.orchestrator.getCodingContextForSession(sk),
4656
+ resolveStorage: async (req) => {
4657
+ const ns = await this.resolveCodingScopedReadableNamespace({
4658
+ namespace: req.namespace,
4659
+ sessionKey: req.sessionKey,
4660
+ authenticatedPrincipal,
4661
+ });
4662
+ const storage = await this.orchestrator.getStorage(ns);
4663
+ // Delta only needs memoryDir + namespace (no readAllMemories). Use the
4664
+ // namespace-ROUTED root (storage.dir), not the global config.memoryDir:
4665
+ // non-default namespaces route to memoryDir/namespaces/<token>, so
4666
+ // session-delta markers must read/write from the routed tree, mirroring
4667
+ // the decision/architecture siblings (cursor review).
4668
+ return {
4669
+ memoryDir: storage.dir,
4670
+ namespace: ns,
4671
+ } satisfies DeltaSurfaceStorage;
4672
+ },
4673
+ gitInvoker: (cwd, args) => {
4674
+ // Reuse the existing defaultGitInvoker (2s timeout, never throws —
4675
+ // the discipline git-context.ts already established). It returns
4676
+ // { stdout, exitCode } so the handler can recover from non-zero
4677
+ // exits without a try/catch.
4678
+ const invoker = defaultGitInvoker();
4679
+ return invoker(cwd, args);
4680
+ },
4681
+ throwInputError: (msg) => { throw new EngramAccessInputError(msg); },
4682
+ });
4683
+ }
4684
+
4548
4685
  async memoryBrowse(
4549
4686
  request: EngramAccessMemoryBrowseRequest = {},
4550
4687
  ): Promise<EngramAccessMemoryBrowseResponse> {
@@ -67,7 +67,7 @@ function shortToolName(advertised: string): string {
67
67
  /** Spin up a server with emitLegacyTools=true and read the deduped short names. */
68
68
  async function liveMcpToolShortNames(): Promise<ReadonlySet<string>> {
69
69
  const stub = { briefingEnabled: true } as unknown as EngramAccessService;
70
- const server = new EngramMcpServer(stub, { emitLegacyTools: true, codingDecisionVisible: true, architectureCardVisible: true });
70
+ const server = new EngramMcpServer(stub, { emitLegacyTools: true, codingDecisionVisible: true, architectureCardVisible: true, codegraphVisible: true, sessionDeltaVisible: true });
71
71
  const response = await server.handleRequest({ jsonrpc: "2.0", id: 1, method: "tools/list" });
72
72
  const result = (response as { result?: { tools?: Array<{ name: string }> } }).result;
73
73
  const names = new Set<string>();