@remnic/core 9.3.691 → 9.3.693

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 (113) hide show
  1. package/dist/access-boundary.d.ts +6 -5
  2. package/dist/access-boundary.js +12 -12
  3. package/dist/access-cli.js +71 -18
  4. package/dist/access-cli.js.map +1 -1
  5. package/dist/access-http.d.ts +5 -4
  6. package/dist/access-http.js +16 -16
  7. package/dist/access-mcp.d.ts +7 -4
  8. package/dist/access-mcp.js +15 -15
  9. package/dist/access-operations.d.ts +12 -6
  10. package/dist/access-operations.js +16 -14
  11. package/dist/access-schema.js +3 -3
  12. package/dist/{access-service-CKnFdxH-.d.ts → access-service-DxCpgyVW.d.ts} +96 -2
  13. package/dist/access-service.d.ts +5 -4
  14. package/dist/access-service.js +11 -11
  15. package/dist/access-surface-catalog.d.ts +5 -4
  16. package/dist/access-surface-catalog.js +2 -0
  17. package/dist/access-surface-catalog.js.map +1 -1
  18. package/dist/bootstrap.d.ts +4 -3
  19. package/dist/{chunk-QNG35H27.js → chunk-4IQNAOP3.js} +5 -141
  20. package/dist/chunk-4IQNAOP3.js.map +1 -0
  21. package/dist/{chunk-VH2DHBHG.js → chunk-5HGPDRQZ.js} +2 -2
  22. package/dist/chunk-5HGPDRQZ.js.map +1 -0
  23. package/dist/chunk-6C2BMUZA.js +444 -0
  24. package/dist/chunk-6C2BMUZA.js.map +1 -0
  25. package/dist/{chunk-UUMYB3FR.js → chunk-6ZNIUGXB.js} +10 -10
  26. package/dist/{chunk-IPJD7WJH.js → chunk-E6BOD3UJ.js} +2 -2
  27. package/dist/{chunk-TJ5IIQIR.js → chunk-F7BVJ3IE.js} +40 -369
  28. package/dist/chunk-F7BVJ3IE.js.map +1 -0
  29. package/dist/{chunk-D3DNGQNQ.js → chunk-FM7KLRKN.js} +2 -2
  30. package/dist/{chunk-7MOTEVAA.js → chunk-HRUULBBV.js} +3 -1
  31. package/dist/chunk-HRUULBBV.js.map +1 -0
  32. package/dist/chunk-HXNMDPHN.js +149 -0
  33. package/dist/chunk-HXNMDPHN.js.map +1 -0
  34. package/dist/{chunk-7UVDIWLL.js → chunk-JNKH2XWQ.js} +36 -6
  35. package/dist/chunk-JNKH2XWQ.js.map +1 -0
  36. package/dist/{chunk-IPLYGWQF.js → chunk-KQAFEZQX.js} +5 -5
  37. package/dist/{chunk-OOO7ZKOD.js → chunk-KYH53EFD.js} +3 -3
  38. package/dist/{chunk-LQ6JI4VH.js → chunk-LD53WPMU.js} +4 -4
  39. package/dist/{chunk-KO6OL4I7.js → chunk-MQTPUPLP.js} +297 -17
  40. package/dist/chunk-MQTPUPLP.js.map +1 -0
  41. package/dist/{chunk-TSGREOYY.js → chunk-RHWFMBO5.js} +33 -6
  42. package/dist/chunk-RHWFMBO5.js.map +1 -0
  43. package/dist/{chunk-5CEJH5ZN.js → chunk-TAPSNIMA.js} +4 -4
  44. package/dist/{chunk-K7I24ZO2.js → chunk-THKNO6OX.js} +22 -21
  45. package/dist/{chunk-K7I24ZO2.js.map → chunk-THKNO6OX.js.map} +1 -1
  46. package/dist/{chunk-QLRYXOAD.js → chunk-UDJLF3BO.js} +2 -2
  47. package/dist/{chunk-NCRDCTEJ.js → chunk-WYB44HHV.js} +21 -7
  48. package/dist/chunk-WYB44HHV.js.map +1 -0
  49. package/dist/{chunk-WRFKZEO6.js → chunk-YQGHW5ML.js} +4 -4
  50. package/dist/{cli-CrSW_KRq.d.ts → cli-DoQsv4ut.d.ts} +2 -2
  51. package/dist/cli.d.ts +6 -5
  52. package/dist/cli.js +26 -25
  53. package/dist/contradiction/index.js +4 -4
  54. package/dist/explicit-capture.d.ts +4 -3
  55. package/dist/index.d.ts +6 -5
  56. package/dist/index.js +33 -31
  57. package/dist/index.js.map +1 -1
  58. package/dist/mcp-memory-inspector-app.d.ts +5 -4
  59. package/dist/namespaces/migrate.js +8 -8
  60. package/dist/namespaces/search.js +7 -7
  61. package/dist/operator-toolkit.js +11 -10
  62. package/dist/orchestration/maintenance.d.ts +112 -0
  63. package/dist/orchestration/maintenance.js +39 -0
  64. package/dist/orchestration/maintenance.js.map +1 -0
  65. package/dist/{orchestrator-DvswGK76.d.ts → orchestrator-CNJCYjZ1.d.ts} +9 -33
  66. package/dist/orchestrator.d.ts +2 -1
  67. package/dist/orchestrator.js +13 -11
  68. package/dist/schemas.d.ts +28 -28
  69. package/dist/search/factory.js +6 -6
  70. package/dist/search/index.js +11 -11
  71. package/dist/search/lancedb-backend.js +2 -2
  72. package/dist/search/meilisearch-backend.js +2 -2
  73. package/dist/search/orama-backend.js +2 -2
  74. package/dist/transfer/autodetect.js +1 -1
  75. package/dist/transfer/backup.js +1 -1
  76. package/dist/transfer/capsule-export.js +2 -2
  77. package/dist/transfer/types.d.ts +12 -12
  78. package/package.json +12 -2
  79. package/src/access-boundary.ts +2 -1
  80. package/src/access-cli.ts +65 -2
  81. package/src/access-http.ts +20 -0
  82. package/src/access-mcp.ts +29 -0
  83. package/src/access-operations.ts +46 -0
  84. package/src/access-service.ts +55 -0
  85. package/src/access-surface-catalog.test.ts +1 -1
  86. package/src/access-surface-catalog.ts +2 -0
  87. package/src/cli.ts +1 -0
  88. package/src/coding/coding-namespace.ts +1 -1
  89. package/src/coding/session-delta-surfaces.test.ts +383 -0
  90. package/src/coding/session-delta-surfaces.ts +325 -0
  91. package/src/coding/session-delta.test.ts +411 -0
  92. package/src/coding/session-delta.ts +442 -0
  93. package/src/orchestration/maintenance.test.ts +738 -0
  94. package/src/orchestration/maintenance.ts +557 -0
  95. package/src/orchestrator-flush.test.ts +0 -599
  96. package/src/orchestrator.ts +33 -419
  97. package/dist/chunk-7MOTEVAA.js.map +0 -1
  98. package/dist/chunk-7UVDIWLL.js.map +0 -1
  99. package/dist/chunk-KO6OL4I7.js.map +0 -1
  100. package/dist/chunk-NCRDCTEJ.js.map +0 -1
  101. package/dist/chunk-QNG35H27.js.map +0 -1
  102. package/dist/chunk-TJ5IIQIR.js.map +0 -1
  103. package/dist/chunk-TSGREOYY.js.map +0 -1
  104. package/dist/chunk-VH2DHBHG.js.map +0 -1
  105. /package/dist/{chunk-UUMYB3FR.js.map → chunk-6ZNIUGXB.js.map} +0 -0
  106. /package/dist/{chunk-IPJD7WJH.js.map → chunk-E6BOD3UJ.js.map} +0 -0
  107. /package/dist/{chunk-D3DNGQNQ.js.map → chunk-FM7KLRKN.js.map} +0 -0
  108. /package/dist/{chunk-IPLYGWQF.js.map → chunk-KQAFEZQX.js.map} +0 -0
  109. /package/dist/{chunk-OOO7ZKOD.js.map → chunk-KYH53EFD.js.map} +0 -0
  110. /package/dist/{chunk-LQ6JI4VH.js.map → chunk-LD53WPMU.js.map} +0 -0
  111. /package/dist/{chunk-5CEJH5ZN.js.map → chunk-TAPSNIMA.js.map} +0 -0
  112. /package/dist/{chunk-QLRYXOAD.js.map → chunk-UDJLF3BO.js.map} +0 -0
  113. /package/dist/{chunk-WRFKZEO6.js.map → chunk-YQGHW5ML.js.map} +0 -0
package/src/access-cli.ts CHANGED
@@ -15,7 +15,7 @@ import { projectTagProjectId } from "./coding/coding-namespace.js";
15
15
 
16
16
  const OPENCLAW_REMNIC_PLUGIN_IDS = ["openclaw-remnic", "openclaw-engram"] as const;
17
17
 
18
- type CommandName = "browse" | "store" | "decision" | "architecture";
18
+ type CommandName = "browse" | "store" | "decision" | "architecture" | "delta";
19
19
 
20
20
  type ParsedArgs = {
21
21
  command: CommandName;
@@ -138,6 +138,7 @@ function usage(): string {
138
138
  " engram-access store [options]",
139
139
  " engram-access decision [options]",
140
140
  " engram-access architecture [options]",
141
+ " engram-access delta [options]",
141
142
  "",
142
143
  "Browse options:",
143
144
  " --namespace <name>",
@@ -248,6 +249,17 @@ const COMMAND_SPECS: Record<CommandName, CommandSpec> = {
248
249
  ]),
249
250
  flagOptions: new Set(),
250
251
  },
252
+ delta: {
253
+ valueOptions: new Set([
254
+ "subcommand",
255
+ "namespace",
256
+ "session-key",
257
+ "principal",
258
+ "project-tag",
259
+ "repo-root",
260
+ ]),
261
+ flagOptions: new Set(),
262
+ },
251
263
  };
252
264
  const BROWSE_SORT_VALUES = Object.freeze([
253
265
  "updated_desc",
@@ -265,7 +277,7 @@ type BrowseSort = (typeof BROWSE_SORT_VALUES)[number];
265
277
  * `command: commandRaw` assignment below (codex review P2).
266
278
  */
267
279
  function isCommandName(value: string): value is CommandName {
268
- return value === "browse" || value === "store" || value === "decision" || value === "architecture";
280
+ return value === "browse" || value === "store" || value === "decision" || value === "architecture" || value === "delta";
269
281
  }
270
282
 
271
283
  function parseArgs(argv: string[]): ParsedArgs {
@@ -636,6 +648,53 @@ async function runArchitecture(args: ParsedArgs, preferredId?: string): Promise<
636
648
  console.log(JSON.stringify(output.result, null, 2));
637
649
  }
638
650
 
651
+ /**
652
+ * Session-delta surface (issue #1548 Track A PR 4). Dispatches through the
653
+ * same `coding_delta` operation as the MCP tool and HTTP route — one
654
+ * validation boundary, three transports.
655
+ */
656
+ async function runDelta(args: ParsedArgs, preferredId?: string): Promise<void> {
657
+ const subcommand = requireOption(args, "subcommand");
658
+ const { config, service } = buildRuntime(preferredId);
659
+ // Same coding-context attachment as runArchitecture/runDecision: the CLI's
660
+ // fresh Orchestrator has an empty session coding-context map, so attach a
661
+ // context BEFORE dispatching so the gate passes.
662
+ const projectTag = getLastOption(args, "project-tag");
663
+ const sessionKey = getLastOption(args, "session-key");
664
+ if (sessionKey && sessionKey.trim().length > 0) {
665
+ const repoRoot = expandOptionalPath(getLastOption(args, "repo-root")) ?? process.cwd();
666
+ const projectId =
667
+ projectTag && projectTag.trim().length > 0
668
+ ? projectTagProjectId(projectTag.trim())
669
+ : projectTagProjectId(path.basename(repoRoot));
670
+ service.setCodingContext({
671
+ sessionKey,
672
+ codingContext: {
673
+ projectId,
674
+ branch: null,
675
+ rootPath: repoRoot,
676
+ defaultBranch: null,
677
+ },
678
+ });
679
+ }
680
+ const op = getOperation("coding_delta");
681
+ if (!op) {
682
+ throw new Error("access-boundary: operation not registered: coding_delta");
683
+ }
684
+ const output = (await op.run(
685
+ {
686
+ subcommand,
687
+ namespace: getLastOption(args, "namespace"),
688
+ sessionKey,
689
+ },
690
+ {
691
+ service,
692
+ authenticatedPrincipal: getLastOption(args, "principal") ?? config.agentAccessHttp.principal,
693
+ },
694
+ )) as { result: unknown };
695
+ console.log(JSON.stringify(output.result, null, 2));
696
+ }
697
+
639
698
  export async function main(
640
699
  argv: string[] = process.argv.slice(2),
641
700
  options: AccessCliOptions = {},
@@ -653,6 +712,10 @@ export async function main(
653
712
  await runArchitecture(args, options.preferredId);
654
713
  return;
655
714
  }
715
+ if (args.command === "delta") {
716
+ await runDelta(args, options.preferredId);
717
+ return;
718
+ }
656
719
  await runStore(args, options.preferredId);
657
720
  }
658
721
 
@@ -317,6 +317,7 @@ export class EngramAccessHttpServer {
317
317
  emitLegacyTools: options.emitLegacyTools,
318
318
  codingDecisionVisible: this.service.decisionRecordSurfaceVisible,
319
319
  architectureCardVisible: this.service.architectureCardSurfaceVisible,
320
+ sessionDeltaVisible: this.service.sessionDeltaSurfaceVisible,
320
321
  });
321
322
  }
322
323
 
@@ -1386,6 +1387,25 @@ export class EngramAccessHttpServer {
1386
1387
  return;
1387
1388
  }
1388
1389
 
1390
+ if (req.method === "POST" && pathname === "/engram/v1/coding/delta") {
1391
+ // Migrated through the access boundary (issue #1525/#1548 PR4):
1392
+ // get is read-only with respect to user memory content. It DOES write
1393
+ // the operator-side state file (last-seen-head marker), but that is
1394
+ // bookkeeping — the same way calibration.ts writes are uncounted. No
1395
+ // write-quota enforcement.
1396
+ const body = await this.readJsonBody(req);
1397
+ const op = getOperation("coding_delta");
1398
+ if (!op) {
1399
+ throw new EngramAccessInputError("access-boundary: operation not registered: coding_delta");
1400
+ }
1401
+ const output = (await op.run(body, {
1402
+ service: this.service,
1403
+ authenticatedPrincipal: this.resolveRequestPrincipal(req),
1404
+ })) as { result: unknown };
1405
+ this.respondJson(res, 200, output.result);
1406
+ return;
1407
+ }
1408
+
1389
1409
  if (req.method === "POST" && pathname === "/engram/v1/suggestions") {
1390
1410
  const body = await this.readValidatedBody(req, "suggestionSubmit");
1391
1411
  const request = {
package/src/access-mcp.ts CHANGED
@@ -111,6 +111,7 @@ 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
+ "engram.coding_delta": "coding_delta",
114
115
  };
115
116
 
116
117
  function resolveChatGptInspectorRecallSessionKey(
@@ -331,6 +332,7 @@ export class EngramMcpServer {
331
332
  * (issue #1548 Track A PR 3, rule 39).
332
333
  */
333
334
  private readonly architectureCardVisible: boolean;
335
+ private readonly sessionDeltaVisible: boolean;
334
336
 
335
337
  constructor(
336
338
  private readonly service: EngramAccessService,
@@ -341,6 +343,7 @@ export class EngramMcpServer {
341
343
  emitLegacyTools?: boolean;
342
344
  codingDecisionVisible?: boolean;
343
345
  architectureCardVisible?: boolean;
346
+ sessionDeltaVisible?: boolean;
344
347
  } = {},
345
348
  ) {
346
349
  this.citationsEnabled = options.citationsEnabled === true;
@@ -348,6 +351,7 @@ export class EngramMcpServer {
348
351
  this.emitLegacyTools = options.emitLegacyTools !== false;
349
352
  this.codingDecisionVisible = options.codingDecisionVisible === true;
350
353
  this.architectureCardVisible = options.architectureCardVisible === true;
354
+ this.sessionDeltaVisible = options.sessionDeltaVisible === true;
351
355
  this.authenticatedPrincipal =
352
356
  options.principal?.trim() ||
353
357
  readEnvVar("OPENCLAW_ENGRAM_ACCESS_PRINCIPAL")?.trim() ||
@@ -2033,6 +2037,31 @@ export class EngramMcpServer {
2033
2037
  );
2034
2038
  this.tools = [...this.tools, ...architectureTools];
2035
2039
  }
2040
+ if (this.sessionDeltaVisible) {
2041
+ const deltaTools = withToolAliases(
2042
+ {
2043
+ name: "engram.coding_delta",
2044
+ description:
2045
+ "Get the session delta (commits + touched files since last seen) for the session's coding namespace (issue #1548 Track A PR 4). Subcommand: get.",
2046
+ inputSchema: {
2047
+ type: "object",
2048
+ properties: {
2049
+ subcommand: {
2050
+ type: "string",
2051
+ enum: ["get"],
2052
+ description: "Which delta operation to run.",
2053
+ },
2054
+ sessionKey: { type: "string", description: "Session identifier whose coding context scopes the operation." },
2055
+ namespace: { type: "string", description: "Optional explicit namespace (overrides coding-context overlay)." },
2056
+ },
2057
+ required: ["subcommand"],
2058
+ additionalProperties: false,
2059
+ },
2060
+ },
2061
+ this.emitLegacyTools,
2062
+ );
2063
+ this.tools = [...this.tools, ...deltaTools];
2064
+ }
2036
2065
  }
2037
2066
 
2038
2067
  /** Get clientInfo for a specific MCP session. Returns undefined for non-MCP requests. */
@@ -29,6 +29,11 @@ import {
29
29
  type ArchitectureSurfaceRequest,
30
30
  type ArchitectureSurfaceResponse,
31
31
  } from "./coding/architecture-surfaces.js";
32
+ import {
33
+ DELTA_SUBCOMMANDS,
34
+ type DeltaSurfaceRequest,
35
+ type DeltaSurfaceResponse,
36
+ } from "./coding/session-delta-surfaces.js";
32
37
 
33
38
  // ---------------------------------------------------------------------------
34
39
  // memory_get — fetch one memory by id
@@ -250,6 +255,46 @@ export const codingArchitectureOperation = defineOperation<
250
255
  },
251
256
  });
252
257
 
258
+ // ---------------------------------------------------------------------------
259
+ // coding_delta — session-delta surface (issue #1548 Track A PR 4)
260
+ // ---------------------------------------------------------------------------
261
+
262
+ const codingDeltaSchema = z.preprocess(
263
+ (data) => {
264
+ if (data !== null && typeof data === "object" && !Array.isArray(data)) {
265
+ const obj = data as Record<string, unknown>;
266
+ const cleaned: Record<string, unknown> = {};
267
+ for (const [key, value] of Object.entries(obj)) {
268
+ if (value !== null) cleaned[key] = value;
269
+ }
270
+ return cleaned;
271
+ }
272
+ return data;
273
+ },
274
+ z.object({
275
+ subcommand: z.enum(DELTA_SUBCOMMANDS),
276
+ sessionKey: z.string().trim().max(512).optional(),
277
+ namespace: z.string().trim().max(256).optional(),
278
+ }),
279
+ );
280
+
281
+ export type CodingDeltaInput = DeltaSurfaceRequest;
282
+ export type CodingDeltaOutput = { result: DeltaSurfaceResponse };
283
+
284
+ export const codingDeltaOperation = defineOperation<
285
+ CodingDeltaInput,
286
+ CodingDeltaOutput
287
+ >({
288
+ name: "coding_delta",
289
+ description:
290
+ "Get the session delta (commits + touched files since last seen) for the session's coding namespace (issue #1548 Track A PR 4).",
291
+ schema: codingDeltaSchema as z.ZodType<CodingDeltaInput>,
292
+ handler: async (input, ctx) => {
293
+ const result = await ctx.service.codingDelta(input, ctx.authenticatedPrincipal);
294
+ return { result };
295
+ },
296
+ });
297
+
253
298
  // ---------------------------------------------------------------------------
254
299
  // Surface registration map — what each transport calls the pilot ops
255
300
  // ---------------------------------------------------------------------------
@@ -265,4 +310,5 @@ export const REGISTERED_OPERATIONS = [
265
310
  memoryStoreOperation.spec.name,
266
311
  codingDecisionOperation.spec.name,
267
312
  codingArchitectureOperation.spec.name,
313
+ codingDeltaOperation.spec.name,
268
314
  ] as const;
@@ -28,6 +28,13 @@ import {
28
28
  ARCHITECTURE_CARD_TAG,
29
29
  } from "./coding/architecture-surfaces.js";
30
30
  import { buildArchitectureCard, createArchitectureCardSummariser } from "./coding/architecture-card.js";
31
+ import {
32
+ handleCodingDelta,
33
+ type DeltaSurfaceRequest,
34
+ type DeltaSurfaceResponse,
35
+ type DeltaSurfaceStorage,
36
+ } from "./coding/session-delta-surfaces.js";
37
+ import { defaultGitInvoker } from "./coding/git-context.js";
31
38
  import { createVersion } from "./page-versioning.js";
32
39
  import { WorkStorage } from "./work/storage.js";
33
40
  import {
@@ -4545,6 +4552,54 @@ export class EngramAccessService {
4545
4552
  });
4546
4553
  }
4547
4554
 
4555
+ /** Whether the coding_delta tool should appear in tools/list (rule 39). */
4556
+ get sessionDeltaSurfaceVisible(): boolean {
4557
+ return this.orchestrator.config.codingKnowledge?.enabled === true
4558
+ && this.orchestrator.config.codingKnowledge?.sessionDelta === true;
4559
+ }
4560
+ /**
4561
+ * Thin delegate — handler logic in coding/session-delta-surfaces.ts (#1548 PR4).
4562
+ * All three surfaces (MCP/HTTP/CLI) arrive here via the boundary operation.
4563
+ * Namespace resolution uses the SAME coding-scoped read path as the other
4564
+ * coding surfaces; the delta state file lives under
4565
+ * `<memoryDir>/state/coding-knowledge/<namespace>.json`.
4566
+ */
4567
+ async codingDelta(
4568
+ request: DeltaSurfaceRequest,
4569
+ authenticatedPrincipal?: string,
4570
+ ): Promise<DeltaSurfaceResponse> {
4571
+ return handleCodingDelta(request, {
4572
+ codingKnowledge: this.orchestrator.config.codingKnowledge,
4573
+ getCodingContext: (sk) => this.orchestrator.getCodingContextForSession(sk),
4574
+ resolveStorage: async (req) => {
4575
+ const ns = await this.resolveCodingScopedReadableNamespace({
4576
+ namespace: req.namespace,
4577
+ sessionKey: req.sessionKey,
4578
+ authenticatedPrincipal,
4579
+ });
4580
+ const storage = await this.orchestrator.getStorage(ns);
4581
+ // Delta only needs memoryDir + namespace (no readAllMemories). Use the
4582
+ // namespace-ROUTED root (storage.dir), not the global config.memoryDir:
4583
+ // non-default namespaces route to memoryDir/namespaces/<token>, so
4584
+ // session-delta markers must read/write from the routed tree, mirroring
4585
+ // the decision/architecture siblings (cursor review).
4586
+ return {
4587
+ memoryDir: storage.dir,
4588
+ namespace: ns,
4589
+ } satisfies DeltaSurfaceStorage;
4590
+ },
4591
+ gitInvoker: (cwd, args) => {
4592
+ // Reuse the existing defaultGitInvoker (2s timeout, never throws —
4593
+ // the discipline git-context.ts already established). It returns
4594
+ // { stdout, exitCode } so the handler can recover from non-zero
4595
+ // exits without a try/catch.
4596
+ const invoker = defaultGitInvoker();
4597
+ return invoker(cwd, args);
4598
+ },
4599
+ throwInputError: (msg) => { throw new EngramAccessInputError(msg); },
4600
+ });
4601
+ }
4602
+
4548
4603
  async memoryBrowse(
4549
4604
  request: EngramAccessMemoryBrowseRequest = {},
4550
4605
  ): 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, 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>();
@@ -74,6 +74,7 @@ export const MCP_TOOLS: readonly McpToolEntry[] = [
74
74
  { tool: "memory_store", operation: "memory_store" },
75
75
  { tool: "coding_decision", operation: "coding_decision" },
76
76
  { tool: "coding_architecture", operation: "coding_architecture" },
77
+ { tool: "coding_delta", operation: "coding_delta" },
77
78
  { tool: "suggestion_submit", operation: null },
78
79
  { tool: "entity_get", operation: null },
79
80
  { tool: "review_queue_list", operation: null },
@@ -172,6 +173,7 @@ export const HTTP_ROUTES: readonly HttpRouteEntry[] = [
172
173
  { method: "POST", pathname: "/engram/v1/memories", operation: "memory_store" },
173
174
  { method: "POST", pathname: "/engram/v1/coding/decisions", operation: "coding_decision" },
174
175
  { method: "POST", pathname: "/engram/v1/coding/architecture", operation: "coding_architecture" },
176
+ { method: "POST", pathname: "/engram/v1/coding/delta", operation: "coding_delta" },
175
177
  { method: "POST", pathname: "/engram/v1/suggestions", operation: null },
176
178
  { method: "GET", pathname: "/engram/v1/memories", operation: null },
177
179
  { method: "GET", pathname: "/engram/v1/memories/:id", operation: "memory_get" },
package/src/cli.ts CHANGED
@@ -2803,6 +2803,7 @@ export async function runAccessMcpServeCliCommand(
2803
2803
  emitLegacyTools: options.emitLegacyTools,
2804
2804
  codingDecisionVisible: service.decisionRecordSurfaceVisible,
2805
2805
  architectureCardVisible: service.architectureCardSurfaceVisible,
2806
+ sessionDeltaVisible: service.sessionDeltaSurfaceVisible,
2806
2807
  });
2807
2808
  await server.runStdio(options.stdin ?? process.stdin, options.stdout ?? process.stdout);
2808
2809
  return { ok: true };
@@ -66,7 +66,7 @@ export interface CodingNamespaceOverlay {
66
66
  * greedy quantifiers) closes the polynomial-backtracking surface that
67
67
  * CodeQL flagged on patterns like `-+` and `^-+|-+$`.
68
68
  */
69
- function sanitizeFragment(input: string): string {
69
+ export function sanitizeFragment(input: string): string {
70
70
  if (typeof input !== "string") return "";
71
71
  const trimmed = input.trim().toLowerCase();
72
72
  let out = "";