@remnic/core 9.3.692 → 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 (62) hide show
  1. package/dist/access-boundary.d.ts +2 -2
  2. package/dist/access-boundary.js +3 -3
  3. package/dist/access-cli.js +57 -6
  4. package/dist/access-cli.js.map +1 -1
  5. package/dist/access-http.d.ts +1 -1
  6. package/dist/access-http.js +6 -6
  7. package/dist/access-mcp.d.ts +3 -1
  8. package/dist/access-mcp.js +5 -5
  9. package/dist/access-operations.d.ts +8 -3
  10. package/dist/access-operations.js +6 -4
  11. package/dist/{access-service-DvApf9LZ.d.ts → access-service-DxCpgyVW.d.ts} +95 -1
  12. package/dist/access-service.d.ts +1 -1
  13. package/dist/access-service.js +2 -2
  14. package/dist/access-surface-catalog.d.ts +1 -1
  15. package/dist/access-surface-catalog.js +2 -0
  16. package/dist/access-surface-catalog.js.map +1 -1
  17. package/dist/{chunk-2EN5WZQB.js → chunk-5HGPDRQZ.js} +2 -2
  18. package/dist/chunk-5HGPDRQZ.js.map +1 -0
  19. package/dist/{chunk-W4MICQIZ.js → chunk-F7BVJ3IE.js} +2 -2
  20. package/dist/{chunk-7MOTEVAA.js → chunk-HRUULBBV.js} +3 -1
  21. package/dist/chunk-HRUULBBV.js.map +1 -0
  22. package/dist/{chunk-NEILAC3H.js → chunk-JNKH2XWQ.js} +35 -5
  23. package/dist/chunk-JNKH2XWQ.js.map +1 -0
  24. package/dist/{chunk-V56S3A23.js → chunk-MQTPUPLP.js} +295 -15
  25. package/dist/chunk-MQTPUPLP.js.map +1 -0
  26. package/dist/{chunk-DO7MDZMU.js → chunk-RHWFMBO5.js} +32 -5
  27. package/dist/chunk-RHWFMBO5.js.map +1 -0
  28. package/dist/{chunk-O4ZIV62T.js → chunk-THKNO6OX.js} +6 -5
  29. package/dist/{chunk-O4ZIV62T.js.map → chunk-THKNO6OX.js.map} +1 -1
  30. package/dist/{chunk-SEK4XIDN.js → chunk-WYB44HHV.js} +20 -6
  31. package/dist/chunk-WYB44HHV.js.map +1 -0
  32. package/dist/{cli-BjsY9Le7.d.ts → cli-DoQsv4ut.d.ts} +1 -1
  33. package/dist/cli.d.ts +2 -2
  34. package/dist/cli.js +7 -7
  35. package/dist/index.d.ts +2 -2
  36. package/dist/index.js +8 -8
  37. package/dist/mcp-memory-inspector-app.d.ts +1 -1
  38. package/dist/orchestrator.js +2 -2
  39. package/dist/schemas.d.ts +28 -28
  40. package/dist/transfer/types.d.ts +12 -12
  41. package/package.json +2 -2
  42. package/src/access-boundary.ts +2 -1
  43. package/src/access-cli.ts +65 -2
  44. package/src/access-http.ts +20 -0
  45. package/src/access-mcp.ts +29 -0
  46. package/src/access-operations.ts +46 -0
  47. package/src/access-service.ts +55 -0
  48. package/src/access-surface-catalog.test.ts +1 -1
  49. package/src/access-surface-catalog.ts +2 -0
  50. package/src/cli.ts +1 -0
  51. package/src/coding/coding-namespace.ts +1 -1
  52. package/src/coding/session-delta-surfaces.test.ts +383 -0
  53. package/src/coding/session-delta-surfaces.ts +325 -0
  54. package/src/coding/session-delta.test.ts +411 -0
  55. package/src/coding/session-delta.ts +442 -0
  56. package/dist/chunk-2EN5WZQB.js.map +0 -1
  57. package/dist/chunk-7MOTEVAA.js.map +0 -1
  58. package/dist/chunk-DO7MDZMU.js.map +0 -1
  59. package/dist/chunk-NEILAC3H.js.map +0 -1
  60. package/dist/chunk-SEK4XIDN.js.map +0 -1
  61. package/dist/chunk-V56S3A23.js.map +0 -1
  62. /package/dist/{chunk-W4MICQIZ.js.map → chunk-F7BVJ3IE.js.map} +0 -0
@@ -23,13 +23,15 @@ import {
23
23
  import {
24
24
  clusterByKey,
25
25
  combineNamespaces,
26
+ defaultGitInvoker,
26
27
  expandScopeProfileReadNamespaces,
27
28
  lcmSessionKeyForNamespace,
28
29
  projectTagProjectId,
29
30
  resolveCodingNamespaceOverlay,
30
31
  resolveGitContext,
31
- resolveScopeProfilePlan
32
- } from "./chunk-7MOTEVAA.js";
32
+ resolveScopeProfilePlan,
33
+ sanitizeFragment
34
+ } from "./chunk-HRUULBBV.js";
33
35
  import {
34
36
  getTrustZoneStoreStatus,
35
37
  isTrustZoneName,
@@ -1137,12 +1139,12 @@ async function findArchitectureCardMemory(storage) {
1137
1139
  });
1138
1140
  return cards[0] ?? null;
1139
1141
  }
1140
- function createArchitectureVersioningHook(enabled, maxVersionsPerPage, sidecarDir, memoryDir, readFile3, writeVersion) {
1142
+ function createArchitectureVersioningHook(enabled, maxVersionsPerPage, sidecarDir, memoryDir, readFile4, writeVersion) {
1141
1143
  return {
1142
1144
  async snapshotIfExists(memory) {
1143
1145
  if (!enabled) return;
1144
1146
  try {
1145
- const fullContent = await readFile3(memory.path);
1147
+ const fullContent = await readFile4(memory.path);
1146
1148
  await writeVersion(
1147
1149
  memory.path,
1148
1150
  fullContent,
@@ -1158,10 +1160,251 @@ function createArchitectureVersioningHook(enabled, maxVersionsPerPage, sidecarDi
1158
1160
  };
1159
1161
  }
1160
1162
 
1163
+ // src/coding/session-delta.ts
1164
+ import { readFile as readFile2, writeFile, mkdir, rename } from "fs/promises";
1165
+ import path2 from "path";
1166
+ var MAX_DELTA_COMMITS = 20;
1167
+ var MAX_DELTA_FILES = 50;
1168
+ function computeSessionDelta(lastSeen, current) {
1169
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1170
+ const nextState = { head: current.currentHead, at: now };
1171
+ if (lastSeen === null) {
1172
+ return { ok: true, kind: "first_run", nextState };
1173
+ }
1174
+ if (lastSeen.head === current.currentHead) {
1175
+ return { ok: true, kind: "unchanged", nextState };
1176
+ }
1177
+ if (current.commits.length === 0) {
1178
+ return {
1179
+ ok: false,
1180
+ code: "unreachable_head",
1181
+ detail: `prior head ${lastSeen.head} is not an ancestor of current ${current.currentHead}`,
1182
+ nextState
1183
+ };
1184
+ }
1185
+ const commits = capCommits(current.commits, MAX_DELTA_COMMITS);
1186
+ const touchedFiles = capFiles(current.touchedFiles, MAX_DELTA_FILES);
1187
+ return {
1188
+ ok: true,
1189
+ kind: "changed",
1190
+ delta: {
1191
+ commits,
1192
+ touchedFiles,
1193
+ summaryLine: buildSummaryLine(commits.length, touchedFiles.length, lastSeen.at)
1194
+ },
1195
+ nextState
1196
+ };
1197
+ }
1198
+ function capCommits(commits, max) {
1199
+ if (!Number.isFinite(max) || max <= 0) return [];
1200
+ if (commits.length <= max) return commits;
1201
+ return commits.slice(-max);
1202
+ }
1203
+ function capFiles(files, max) {
1204
+ if (!Number.isFinite(max) || max <= 0) return [];
1205
+ if (files.length <= max) return files;
1206
+ return files.slice(0, max);
1207
+ }
1208
+ function buildSummaryLine(commitCount, fileCount, sinceIso) {
1209
+ const since = formatSinceDate(sinceIso);
1210
+ const commitWord = commitCount === 1 ? "commit" : "commits";
1211
+ const fileWord = fileCount === 1 ? "file" : "files";
1212
+ return `Since ${since}: ${commitCount} ${commitWord}, ${fileCount} ${fileWord} touched.`;
1213
+ }
1214
+ function formatSinceDate(iso) {
1215
+ const match = /^(\d{4}-\d{2}-\d{2})/.exec(iso);
1216
+ return match ? match[1] : iso;
1217
+ }
1218
+ var CODING_KNOWLEDGE_STATE_DIR = path2.join("state", "coding-knowledge");
1219
+ function sessionDeltaStatePath(memoryDir, namespace) {
1220
+ const safe = sanitizeFragment(namespace) || "default";
1221
+ return path2.join(memoryDir, CODING_KNOWLEDGE_STATE_DIR, `${safe}.json`);
1222
+ }
1223
+ async function readLastSeenState(statePath) {
1224
+ try {
1225
+ const raw = await readFile2(statePath, "utf8");
1226
+ const parsed = JSON.parse(raw);
1227
+ if (typeof parsed !== "object" || parsed === null) return null;
1228
+ const obj = parsed;
1229
+ const head = typeof obj.head === "string" ? obj.head : null;
1230
+ const at = typeof obj.at === "string" ? obj.at : null;
1231
+ if (!head || !at) return null;
1232
+ return { head, at };
1233
+ } catch {
1234
+ return null;
1235
+ }
1236
+ }
1237
+ async function writeLastSeenState(statePath, state) {
1238
+ if (!state.head || !state.at) {
1239
+ throw new Error(
1240
+ `writeLastSeenState: invalid state (head=${JSON.stringify(state.head)}, at=${JSON.stringify(state.at)})`
1241
+ );
1242
+ }
1243
+ const dir = path2.dirname(statePath);
1244
+ await mkdir(dir, { recursive: true });
1245
+ const tmp = `${statePath}.tmp-${process.pid}-${Date.now()}`;
1246
+ await writeFile(tmp, JSON.stringify(state, null, 2), "utf8");
1247
+ await rename(tmp, statePath);
1248
+ }
1249
+ function resolveSlice(repoRoot, sinceHead, invoker) {
1250
+ const headResult = invoker(repoRoot, ["rev-parse", "HEAD"]);
1251
+ if (headResult.exitCode !== 0) {
1252
+ return {
1253
+ ok: false,
1254
+ code: headResult.stdout.trim().length === 0 ? "no_head" : "git_failed",
1255
+ detail: `rev-parse HEAD exited ${headResult.exitCode}`
1256
+ };
1257
+ }
1258
+ const currentHead = headResult.stdout.trim();
1259
+ if (!currentHead) {
1260
+ return { ok: false, code: "no_head", detail: "rev-parse HEAD returned empty" };
1261
+ }
1262
+ if (!sinceHead) {
1263
+ return { ok: true, slice: { commits: [], touchedFiles: [], currentHead } };
1264
+ }
1265
+ if (sinceHead === currentHead) {
1266
+ return { ok: true, slice: { commits: [], touchedFiles: [], currentHead } };
1267
+ }
1268
+ const SEP = "";
1269
+ const logResult = invoker(repoRoot, [
1270
+ "log",
1271
+ "--reverse",
1272
+ `--pretty=format:%H${SEP}%s`,
1273
+ "--name-only",
1274
+ `${sinceHead}..${currentHead}`
1275
+ ]);
1276
+ if (logResult.exitCode !== 0) {
1277
+ if (logResult.exitCode === 128) {
1278
+ return { ok: true, slice: { commits: [], touchedFiles: [], currentHead } };
1279
+ }
1280
+ return {
1281
+ ok: false,
1282
+ code: "git_failed",
1283
+ detail: "git log exited " + logResult.exitCode + " (transient \u2014 state marker preserved)"
1284
+ };
1285
+ }
1286
+ const { commits, touchedFiles } = parseLogOutput(logResult.stdout, SEP);
1287
+ return { ok: true, slice: { commits, touchedFiles, currentHead } };
1288
+ }
1289
+ function parseLogOutput(stdout, sep2) {
1290
+ const commits = [];
1291
+ const fileSet = /* @__PURE__ */ new Set();
1292
+ const blocks = stdout.split(/\n\s*\n/);
1293
+ for (const block of blocks) {
1294
+ const lines = block.split("\n").map((l) => l.trim()).filter((l) => l.length > 0);
1295
+ if (lines.length === 0) continue;
1296
+ const header = lines[0];
1297
+ const sepIdx = header.indexOf(sep2);
1298
+ if (sepIdx >= 0) {
1299
+ const sha = header.slice(0, sepIdx);
1300
+ const subject = header.slice(sepIdx + sep2.length);
1301
+ commits.push({ sha, subject });
1302
+ for (let i = 1; i < lines.length; i += 1) {
1303
+ if (lines[i]) fileSet.add(lines[i]);
1304
+ }
1305
+ } else {
1306
+ for (const line of lines) fileSet.add(line);
1307
+ }
1308
+ }
1309
+ const touchedFiles = [...fileSet].sort((a, b) => a.localeCompare(b));
1310
+ return { commits, touchedFiles };
1311
+ }
1312
+
1313
+ // src/coding/session-delta-surfaces.ts
1314
+ var DELTA_SUBCOMMANDS = ["get"];
1315
+ function isSessionDeltaSurfaceEnabled(config, codingContext) {
1316
+ return config.enabled === true && config.sessionDelta === true && codingContext !== null && codingContext !== void 0;
1317
+ }
1318
+ async function handleCodingDelta(request, ctx) {
1319
+ const codingContext = request.sessionKey ? ctx.getCodingContext(request.sessionKey) : null;
1320
+ if (codingContext === null || !isSessionDeltaSurfaceEnabled(ctx.codingKnowledge, codingContext)) {
1321
+ ctx.throwInputError(
1322
+ "coding_delta requires codingKnowledge.enabled, codingKnowledge.sessionDelta, and an attached coding context"
1323
+ );
1324
+ }
1325
+ switch (request.subcommand) {
1326
+ case "get":
1327
+ return deltaGet(request, ctx, codingContext);
1328
+ }
1329
+ }
1330
+ async function deltaGet(request, ctx, codingContext) {
1331
+ const storage = await ctx.resolveStorage(request);
1332
+ const statePath = sessionDeltaStatePath(storage.memoryDir, storage.namespace);
1333
+ const lastSeen = await readLastSeenState(statePath);
1334
+ const repoRoot = codingContext.rootPath ?? codingContext.projectId;
1335
+ const sliceResult = resolveSlice(
1336
+ repoRoot,
1337
+ lastSeen?.head ?? null,
1338
+ ctx.gitInvoker
1339
+ );
1340
+ if (!sliceResult.ok) {
1341
+ log.warn(
1342
+ `coding_delta/get: slice resolution failed (code=${sliceResult.code}): ${sliceResult.detail}`
1343
+ );
1344
+ return {
1345
+ subcommand: "get",
1346
+ ok: false,
1347
+ code: "git_failed",
1348
+ detail: sliceResult.detail
1349
+ };
1350
+ }
1351
+ const result = computeSessionDelta(lastSeen, sliceResult.slice);
1352
+ let nextState = null;
1353
+ if (result.ok) {
1354
+ nextState = result.nextState;
1355
+ } else if (result.code === "unreachable_head") {
1356
+ nextState = result.nextState;
1357
+ }
1358
+ if (nextState) {
1359
+ try {
1360
+ await writeLastSeenState(statePath, nextState);
1361
+ } catch (err) {
1362
+ log.warn(
1363
+ `coding_delta/get: state write failed for ${statePath}: ${err instanceof Error ? err.message : String(err)}`
1364
+ );
1365
+ }
1366
+ }
1367
+ if (!result.ok) {
1368
+ if (result.code === "unreachable_head") {
1369
+ return {
1370
+ subcommand: "get",
1371
+ ok: false,
1372
+ code: result.code,
1373
+ detail: result.detail,
1374
+ nextState: result.nextState
1375
+ };
1376
+ }
1377
+ return {
1378
+ subcommand: "get",
1379
+ ok: false,
1380
+ code: result.code,
1381
+ detail: result.detail
1382
+ };
1383
+ }
1384
+ switch (result.kind) {
1385
+ case "first_run":
1386
+ return { subcommand: "get", ok: true, kind: "first_run", nextState: result.nextState };
1387
+ case "unchanged":
1388
+ return { subcommand: "get", ok: true, kind: "unchanged", nextState: result.nextState };
1389
+ case "changed":
1390
+ return {
1391
+ subcommand: "get",
1392
+ ok: true,
1393
+ kind: "changed",
1394
+ delta: {
1395
+ commits: result.delta.commits,
1396
+ touchedFiles: result.delta.touchedFiles,
1397
+ summaryLine: result.delta.summaryLine
1398
+ },
1399
+ nextState: result.nextState
1400
+ };
1401
+ }
1402
+ }
1403
+
1161
1404
  // src/procedural/procedure-miner.ts
1162
1405
  import { createHash } from "crypto";
1163
- import { mkdir, rm, stat } from "fs/promises";
1164
- import path2 from "path";
1406
+ import { mkdir as mkdir2, rm, stat } from "fs/promises";
1407
+ import path3 from "path";
1165
1408
  var PROCEDURE_CLUSTER_ATTR_MAX = 500;
1166
1409
  var PROCEDURE_CLUSTER_LOCK_STALE_MS = 12e4;
1167
1410
  var PROCEDURE_CLUSTER_LOCK_TIMEOUT_MS = 3e4;
@@ -1181,14 +1424,14 @@ function sleep(ms) {
1181
1424
  return new Promise((resolve2) => setTimeout(resolve2, ms));
1182
1425
  }
1183
1426
  async function acquireClusterWriteLock(memoryDir, clusterHash) {
1184
- const lockRoot = path2.join(path2.resolve(memoryDir), "state", "procedure-miner-locks");
1185
- const lockDir = path2.join(lockRoot, `${clusterHash}.lock`);
1186
- await mkdir(lockRoot, { recursive: true });
1427
+ const lockRoot = path3.join(path3.resolve(memoryDir), "state", "procedure-miner-locks");
1428
+ const lockDir = path3.join(lockRoot, `${clusterHash}.lock`);
1429
+ await mkdir2(lockRoot, { recursive: true });
1187
1430
  const startedAt = Date.now();
1188
1431
  let attempts = 0;
1189
1432
  while (true) {
1190
1433
  try {
1191
- await mkdir(lockDir);
1434
+ await mkdir2(lockDir);
1192
1435
  return async () => {
1193
1436
  await rm(lockDir, { recursive: true, force: true });
1194
1437
  };
@@ -1213,7 +1456,7 @@ async function acquireClusterWriteLock(memoryDir, clusterHash) {
1213
1456
  }
1214
1457
  }
1215
1458
  async function withClusterWriteLock(memoryDir, clusterHash, fn) {
1216
- const inProcessKey = `${path2.resolve(memoryDir)}:${clusterHash}`;
1459
+ const inProcessKey = `${path3.resolve(memoryDir)}:${clusterHash}`;
1217
1460
  const previous = inProcessClusterWriteLocks.get(inProcessKey) ?? Promise.resolve();
1218
1461
  let releaseInProcess;
1219
1462
  const current = previous.catch(() => void 0).then(
@@ -3849,6 +4092,42 @@ var EngramAccessService = class {
3849
4092
  }
3850
4093
  });
3851
4094
  }
4095
+ /** Whether the coding_delta tool should appear in tools/list (rule 39). */
4096
+ get sessionDeltaSurfaceVisible() {
4097
+ return this.orchestrator.config.codingKnowledge?.enabled === true && this.orchestrator.config.codingKnowledge?.sessionDelta === true;
4098
+ }
4099
+ /**
4100
+ * Thin delegate — handler logic in coding/session-delta-surfaces.ts (#1548 PR4).
4101
+ * All three surfaces (MCP/HTTP/CLI) arrive here via the boundary operation.
4102
+ * Namespace resolution uses the SAME coding-scoped read path as the other
4103
+ * coding surfaces; the delta state file lives under
4104
+ * `<memoryDir>/state/coding-knowledge/<namespace>.json`.
4105
+ */
4106
+ async codingDelta(request, authenticatedPrincipal) {
4107
+ return handleCodingDelta(request, {
4108
+ codingKnowledge: this.orchestrator.config.codingKnowledge,
4109
+ getCodingContext: (sk) => this.orchestrator.getCodingContextForSession(sk),
4110
+ resolveStorage: async (req) => {
4111
+ const ns = await this.resolveCodingScopedReadableNamespace({
4112
+ namespace: req.namespace,
4113
+ sessionKey: req.sessionKey,
4114
+ authenticatedPrincipal
4115
+ });
4116
+ const storage = await this.orchestrator.getStorage(ns);
4117
+ return {
4118
+ memoryDir: storage.dir,
4119
+ namespace: ns
4120
+ };
4121
+ },
4122
+ gitInvoker: (cwd, args) => {
4123
+ const invoker = defaultGitInvoker();
4124
+ return invoker(cwd, args);
4125
+ },
4126
+ throwInputError: (msg) => {
4127
+ throw new EngramAccessInputError(msg);
4128
+ }
4129
+ });
4130
+ }
3852
4131
  async memoryBrowse(request = {}) {
3853
4132
  const resolvedNamespace = this.resolveReadableNamespace(
3854
4133
  request.namespace,
@@ -5911,7 +6190,7 @@ ${next}`);
5911
6190
  const resolvedNs = this.resolveWritableNamespace(request.namespace, request.sessionKey, request.principal);
5912
6191
  const storage = await this.orchestrator.getStorage(resolvedNs);
5913
6192
  const storageDir = storage.dir;
5914
- const { writeFile, mkdir: mkdir2 } = await import("fs/promises");
6193
+ const { writeFile: writeFile2, mkdir: mkdir3 } = await import("fs/promises");
5915
6194
  const { join: join2, resolve: resolve2 } = await import("path");
5916
6195
  const safeKey = request.sessionKey.replace(/[^a-zA-Z0-9_-]/g, "_");
5917
6196
  if (!safeKey) throw new EngramAccessInputError("sessionKey is required");
@@ -5920,10 +6199,10 @@ ${next}`);
5920
6199
  if (!resolved.startsWith(resolve2(storageDir))) {
5921
6200
  throw new EngramAccessInputError("Invalid sessionKey");
5922
6201
  }
5923
- await mkdir2(checkpointDir, { recursive: true });
6202
+ await mkdir3(checkpointDir, { recursive: true });
5924
6203
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
5925
6204
  const filePath = join2(checkpointDir, `checkpoint-${ts}.md`);
5926
- await writeFile(filePath, request.context, "utf-8");
6205
+ await writeFile2(filePath, request.context, "utf-8");
5927
6206
  return { saved: true };
5928
6207
  }
5929
6208
  async lcmStatus() {
@@ -6653,6 +6932,7 @@ ${next}`);
6653
6932
 
6654
6933
  export {
6655
6934
  DECISION_SUBCOMMANDS,
6935
+ DELTA_SUBCOMMANDS,
6656
6936
  computeProcedureStats,
6657
6937
  formatProcedureStatsText,
6658
6938
  EngramAccessInputError,
@@ -6660,4 +6940,4 @@ export {
6660
6940
  shapeMemorySummary,
6661
6941
  EngramAccessService
6662
6942
  };
6663
- //# sourceMappingURL=chunk-V56S3A23.js.map
6943
+ //# sourceMappingURL=chunk-MQTPUPLP.js.map