@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
@@ -0,0 +1,325 @@
1
+ /**
2
+ * Session-delta surface contract + handler (issue #1548 Track A PR 4).
3
+ *
4
+ * The single shared implementation behind the MCP, HTTP, and CLI
5
+ * session-delta surfaces. All three transports dispatch through the
6
+ * `coding_delta` boundary operation, which calls {@link handleCodingDelta}
7
+ * via the service delegate.
8
+ *
9
+ * Gate (rule 39): `codingKnowledge.enabled + sessionDelta + coding
10
+ * context` — one predicate, identical on every surface. The tools/list
11
+ * visibility gate checks conditions 1–2 only (config-level).
12
+ *
13
+ * Persistence (rule 25): the new last-seen-head marker is written AFTER
14
+ * the delta is computed from the old one. State writes use temp-file-then-
15
+ * rename (rule 54) via the pure module's `writeLastSeenState`.
16
+ *
17
+ * Subcommand: `get` — computes the delta against the persisted last-seen
18
+ * head and updates the marker in the same call (so the NEXT session sees
19
+ * this one as the baseline). Read-only semantically, but it mutates the
20
+ * state file: it is therefore NOT counted against the write-quota (the
21
+ * state file is operator-side bookkeeping, not user memory content — the
22
+ * same way `calibration.ts` writes are uncounted).
23
+ */
24
+ import type {
25
+ CodingKnowledgeConfig,
26
+ CodingContext,
27
+ } from "../types.js";
28
+ import {
29
+ computeSessionDelta,
30
+ readLastSeenState,
31
+ writeLastSeenState,
32
+ resolveSlice,
33
+ sessionDeltaStatePath,
34
+ type GitLogSlice,
35
+ type LastSeenState,
36
+ type ResolveSliceResult,
37
+ type SessionDeltaGitInvoker,
38
+ type SessionDeltaResult,
39
+ } from "./session-delta.js";
40
+ import { log } from "../logger.js";
41
+
42
+ // ──────────────────────────────────────────────────────────────────────────
43
+ // Subcommands
44
+ // ──────────────────────────────────────────────────────────────────────────
45
+
46
+ export const DELTA_SUBCOMMANDS = ["get"] as const;
47
+
48
+ export type DeltaSubcommand = (typeof DELTA_SUBCOMMANDS)[number];
49
+
50
+ const SUBCOMMAND_VALUES = DELTA_SUBCOMMANDS as readonly string[];
51
+
52
+ /** Type guard — narrows an unknown subcommand string. */
53
+ export function isDeltaSubcommand(value: unknown): value is DeltaSubcommand {
54
+ return typeof value === "string" && SUBCOMMAND_VALUES.includes(value);
55
+ }
56
+
57
+ /** Human-readable subcommand list for error messages (rule 51). */
58
+ export function formatDeltaSubcommands(): string {
59
+ return DELTA_SUBCOMMANDS.join(", ");
60
+ }
61
+
62
+ // ──────────────────────────────────────────────────────────────────────────
63
+ // Gate predicates — rule 39: one predicate, identical on every surface
64
+ // ──────────────────────────────────────────────────────────────────────────
65
+
66
+ /**
67
+ * The single session-delta surface gate. Returns `true` only when:
68
+ * 1. `codingKnowledge.enabled` is true,
69
+ * 2. `codingKnowledge.sessionDelta` is true,
70
+ * 3. a coding context is attached (so a repo root is available).
71
+ */
72
+ export function isSessionDeltaSurfaceEnabled(
73
+ config: CodingKnowledgeConfig,
74
+ codingContext: CodingContext | null | undefined,
75
+ ): boolean {
76
+ return (
77
+ config.enabled === true &&
78
+ config.sessionDelta === true &&
79
+ codingContext !== null &&
80
+ codingContext !== undefined
81
+ );
82
+ }
83
+
84
+ /**
85
+ * Config-only visibility gate — used by the MCP constructor to decide
86
+ * whether to advertise `engram.coding_delta` in `tools/list`. When this
87
+ * returns `false` the tools array is byte-identical to pre-feature (rule 39).
88
+ */
89
+ export function isSessionDeltaSurfaceVisible(
90
+ config: CodingKnowledgeConfig,
91
+ ): boolean {
92
+ return config.enabled === true && config.sessionDelta === true;
93
+ }
94
+
95
+ // ──────────────────────────────────────────────────────────────────────────
96
+ // Surface request / response shapes
97
+ // ──────────────────────────────────────────────────────────────────────────
98
+
99
+ /** Canonical surface request — one shape for all three transports. */
100
+ export interface DeltaSurfaceRequest {
101
+ subcommand: DeltaSubcommand;
102
+ sessionKey?: string;
103
+ namespace?: string;
104
+ }
105
+
106
+ /**
107
+ * Surface response. Mirrors {@link SessionDeltaResult} but flattened for
108
+ * transport: every outcome carries `nextState` so callers can observe the
109
+ * new marker even on failure (the head still advanced).
110
+ */
111
+ export type DeltaSurfaceResponse =
112
+ | {
113
+ subcommand: "get";
114
+ ok: true;
115
+ /** A real delta was computed. */
116
+ kind: "changed";
117
+ delta: {
118
+ commits: ReadonlyArray<{ sha: string; subject: string }>;
119
+ touchedFiles: readonly string[];
120
+ summaryLine: string;
121
+ };
122
+ nextState: LastSeenState;
123
+ }
124
+ | {
125
+ subcommand: "get";
126
+ ok: true;
127
+ /** Prior head equals current — no changes. */
128
+ kind: "unchanged";
129
+ nextState: LastSeenState;
130
+ }
131
+ | {
132
+ subcommand: "get";
133
+ ok: true;
134
+ /** No prior state — first session for this namespace. */
135
+ kind: "first_run";
136
+ nextState: LastSeenState;
137
+ }
138
+ | {
139
+ subcommand: "get";
140
+ /**
141
+ * Delta unavailable. `code` is one of `unreachable_head` (force-push/
142
+ * rebase erased the prior head) or `git_failed` (invoker error). The
143
+ * state file is still advanced when `nextState` is present.
144
+ */
145
+ ok: false;
146
+ code: "unreachable_head" | "git_failed";
147
+ detail: string;
148
+ nextState?: LastSeenState;
149
+ };
150
+
151
+ // ──────────────────────────────────────────────────────────────────────────
152
+ // Storage contract — narrow; the handler needs the memoryDir + namespace only
153
+ // ──────────────────────────────────────────────────────────────────────────
154
+
155
+ /**
156
+ * The resolved namespace context the handler needs. The service produces
157
+ * this through the SAME coding-scoped read path as the other coding surfaces.
158
+ */
159
+ export interface DeltaSurfaceStorage {
160
+ /** The orchestrator's memoryDir — base for the state file path. */
161
+ readonly memoryDir: string;
162
+ /** The resolved coding-scoped namespace — basis for the state filename. */
163
+ readonly namespace: string;
164
+ }
165
+
166
+ /**
167
+ * Dependencies the handler borrows from the service. The service constructs
168
+ * this context per call; the handler never touches the orchestrator directly.
169
+ */
170
+ export interface DeltaSurfaceContext {
171
+ readonly codingKnowledge: CodingKnowledgeConfig;
172
+ getCodingContext(sessionKey: string): CodingContext | null;
173
+ /** Resolve storage (memoryDir + namespace) via the coding-scoped read path. */
174
+ resolveStorage(request: DeltaSurfaceRequest): Promise<DeltaSurfaceStorage>;
175
+ /** Git invoker — drives `rev-parse` + `log`. Defaults to a real invoker. */
176
+ gitInvoker: SessionDeltaGitInvoker;
177
+ /** Throw the surface-appropriate input-validation error. */
178
+ throwInputError(message: string): never;
179
+ }
180
+
181
+ // ──────────────────────────────────────────────────────────────────────────
182
+ // Handler — the single shared implementation behind all three surfaces
183
+ // ──────────────────────────────────────────────────────────────────────────
184
+
185
+ /**
186
+ * The single shared implementation behind the MCP, HTTP, and CLI
187
+ * session-delta surfaces.
188
+ *
189
+ * Order of operations (rule 25 — do not destroy the old marker before the
190
+ * new state is useful):
191
+ * 1. Read the persisted last-seen-head.
192
+ * 2. Resolve the current repo slice via the git invoker.
193
+ * 3. Compute the delta from the OLD state + current slice.
194
+ * 4. Persist the NEW state (temp-file-then-rename).
195
+ * 5. Return the result.
196
+ */
197
+ export async function handleCodingDelta(
198
+ request: DeltaSurfaceRequest,
199
+ ctx: DeltaSurfaceContext,
200
+ ): Promise<DeltaSurfaceResponse> {
201
+ const codingContext = request.sessionKey
202
+ ? ctx.getCodingContext(request.sessionKey)
203
+ : null;
204
+ if (
205
+ codingContext === null ||
206
+ !isSessionDeltaSurfaceEnabled(ctx.codingKnowledge, codingContext)
207
+ ) {
208
+ ctx.throwInputError(
209
+ "coding_delta requires codingKnowledge.enabled, codingKnowledge.sessionDelta, and an attached coding context",
210
+ );
211
+ }
212
+ // `get` is the only subcommand today; the switch keeps the shape forward-
213
+ // compatible if `refresh`/`reset` land later.
214
+ switch (request.subcommand) {
215
+ case "get":
216
+ return deltaGet(request, ctx, codingContext);
217
+ }
218
+ }
219
+
220
+ // ──────────────────────────────────────────────────────────────────────────
221
+ // Subcommand handler
222
+ // ──────────────────────────────────────────────────────────────────────────
223
+
224
+ async function deltaGet(
225
+ request: DeltaSurfaceRequest,
226
+ ctx: DeltaSurfaceContext,
227
+ codingContext: CodingContext,
228
+ ): Promise<DeltaSurfaceResponse> {
229
+ const storage = await ctx.resolveStorage(request);
230
+ const statePath = sessionDeltaStatePath(storage.memoryDir, storage.namespace);
231
+
232
+ // 1. Read prior state. Absent/empty/malformed → null → first_run.
233
+ const lastSeen = await readLastSeenState(statePath);
234
+
235
+ // 2. Resolve the current repo slice. `rootPath` is the repo root the
236
+ // coding context was resolved from; it MUST exist for a delta to make
237
+ // sense. Fall back to `projectId` only as a path hint — refresh is the
238
+ // caller's responsibility (the gate already required a context).
239
+ const repoRoot = codingContext.rootPath ?? codingContext.projectId;
240
+ const sliceResult: ResolveSliceResult = resolveSlice(
241
+ repoRoot,
242
+ lastSeen?.head ?? null,
243
+ ctx.gitInvoker,
244
+ );
245
+
246
+ // 3. Git failure → tagged failure, but advance the state file when we
247
+ // could at least read the current head (so the next call has a chance).
248
+ if (!sliceResult.ok) {
249
+ log.warn(
250
+ `coding_delta/get: slice resolution failed (code=${sliceResult.code}): ${sliceResult.detail}`,
251
+ );
252
+ // Best-effort: still try to advance the state file if the head was readable.
253
+ // On `no_head` we cannot write anything sensible — leave the prior marker.
254
+ return {
255
+ subcommand: "get",
256
+ ok: false,
257
+ code: "git_failed",
258
+ detail: sliceResult.detail,
259
+ };
260
+ }
261
+
262
+ // 4. Compute the delta from the OLD state + the slice.
263
+ const result: SessionDeltaResult = computeSessionDelta(lastSeen, sliceResult.slice);
264
+
265
+ // 5. Persist the new state (rule 25 + rule 54). Failures here are logged
266
+ // but do NOT fail the operation — the delta was computed; the next
267
+ // session may re-derive it. A write failure surfaces in doctor/xray.
268
+ let nextState: LastSeenState | null = null;
269
+ if (result.ok) {
270
+ nextState = result.nextState;
271
+ } else if (result.code === "unreachable_head") {
272
+ nextState = result.nextState;
273
+ }
274
+ if (nextState) {
275
+ try {
276
+ await writeLastSeenState(statePath, nextState);
277
+ } catch (err) {
278
+ log.warn(
279
+ `coding_delta/get: state write failed for ${statePath}: ${err instanceof Error ? err.message : String(err)}`,
280
+ );
281
+ }
282
+ }
283
+
284
+ // 6. Map to the surface response shape.
285
+ if (!result.ok) {
286
+ if (result.code === "unreachable_head") {
287
+ return {
288
+ subcommand: "get",
289
+ ok: false,
290
+ code: result.code,
291
+ detail: result.detail,
292
+ nextState: result.nextState,
293
+ };
294
+ }
295
+ return {
296
+ subcommand: "get",
297
+ ok: false,
298
+ code: result.code,
299
+ detail: result.detail,
300
+ };
301
+ }
302
+ switch (result.kind) {
303
+ case "first_run":
304
+ return { subcommand: "get", ok: true, kind: "first_run", nextState: result.nextState };
305
+ case "unchanged":
306
+ return { subcommand: "get", ok: true, kind: "unchanged", nextState: result.nextState };
307
+ case "changed":
308
+ return {
309
+ subcommand: "get",
310
+ ok: true,
311
+ kind: "changed",
312
+ delta: {
313
+ commits: result.delta.commits,
314
+ touchedFiles: result.delta.touchedFiles,
315
+ summaryLine: result.delta.summaryLine,
316
+ },
317
+ nextState: result.nextState,
318
+ };
319
+ }
320
+ }
321
+
322
+ // Exported for the surface's storage-adapter glue so the service delegate
323
+ // can build the narrow {@link DeltaSurfaceStorage} without re-importing the
324
+ // path helper from the pure module.
325
+ export { sessionDeltaStatePath, type GitLogSlice };