dotmem 0.0.4 → 0.0.5

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.
package/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { store, hlc, DEV, PROD, idb, session, state, dispatch, temporal } from 'memorio';
1
+ import { store as store$1, hlc, DEV, dispatch, idb, session, state, PROD, temporal } from 'memorio';
2
2
  export { DEV, PROD, dispatch, hlc, idb, session, state, store } from 'memorio';
3
3
 
4
4
  var __defProp = Object.defineProperty;
@@ -5223,13 +5223,13 @@ var init_mem_repository = __esm({
5223
5223
  });
5224
5224
  }
5225
5225
  async loadSources(sourceIds) {
5226
- const { readFile: readFile2 } = await nodeFs4();
5226
+ const { readFile: readFile5 } = await nodeFs4();
5227
5227
  const ids = sourceIds ?? await this.discover();
5228
5228
  const sources = [];
5229
5229
  for (const sourceId of ids) {
5230
5230
  const filePath = memFilePath(this.directoryPath, sourceId);
5231
5231
  try {
5232
- const decoded = await parseMemFile(await readFile2(filePath), sourceId);
5232
+ const decoded = await parseMemFile(await readFile5(filePath), sourceId);
5233
5233
  sources.push({
5234
5234
  id: sourceId,
5235
5235
  filePath,
@@ -5313,10 +5313,10 @@ var init_mem_repository = __esm({
5313
5313
  * valid package, so the backup is always a version this library can read.
5314
5314
  */
5315
5315
  async keepLastValidVersion(filePath) {
5316
- const { readFile: readFile2, copyFile, rename, rm } = await nodeFs4();
5316
+ const { readFile: readFile5, copyFile, rename, rm } = await nodeFs4();
5317
5317
  let current;
5318
5318
  try {
5319
- current = await readFile2(filePath);
5319
+ current = await readFile5(filePath);
5320
5320
  } catch {
5321
5321
  return;
5322
5322
  }
@@ -5349,7 +5349,7 @@ var init_mem_repository = __esm({
5349
5349
  }
5350
5350
  }
5351
5351
  async writeSource(filePath, state3, preserved, preservedPackage) {
5352
- const { mkdir, rename, rm, open: open2, readFile: readFile2 } = await nodeFs4();
5352
+ const { mkdir, rename, rm, open: open2, readFile: readFile5 } = await nodeFs4();
5353
5353
  if (!Number.isInteger(state3.version) || state3.version < 0) throw new Error("Invalid writable .mem knowledge version");
5354
5354
  for (const claim2 of state3.claims) validateClaim(claim2);
5355
5355
  await mkdir(parentPath(filePath), { recursive: true });
@@ -5371,7 +5371,7 @@ var init_mem_repository = __esm({
5371
5371
  } finally {
5372
5372
  await handle.close();
5373
5373
  }
5374
- await decodeMemArtifact(await readFile2(temporary));
5374
+ await decodeMemArtifact(await readFile5(temporary));
5375
5375
  await this.keepLastValidVersion(filePath);
5376
5376
  for (let attempt = 0; attempt < 5; attempt++) {
5377
5377
  try {
@@ -5399,8 +5399,8 @@ var init_mem_repository = __esm({
5399
5399
  // core/knowledge/project-anchor.ts
5400
5400
  async function projectAnchorExists(projectId) {
5401
5401
  try {
5402
- const { readFile: readFile2 } = await import('fs/promises');
5403
- await readFile2(resolveUserProjectMemoryPath(projectId));
5402
+ const { readFile: readFile5 } = await import('fs/promises');
5403
+ await readFile5(resolveUserProjectMemoryPath(projectId));
5404
5404
  return true;
5405
5405
  } catch {
5406
5406
  return false;
@@ -5465,8 +5465,8 @@ var init_user_identity = __esm({
5465
5465
  "core/knowledge/user-identity.ts"() {
5466
5466
  USER_IDENTITY_KEY = "__dotmem_user_identity__";
5467
5467
  identityStore = null;
5468
- configureUserIdentityStore = /* @__PURE__ */ __name((store6) => {
5469
- identityStore = store6;
5468
+ configureUserIdentityStore = /* @__PURE__ */ __name((store7) => {
5469
+ identityStore = store7;
5470
5470
  }, "configureUserIdentityStore");
5471
5471
  requireStore = /* @__PURE__ */ __name(() => {
5472
5472
  if (!identityStore) {
@@ -6081,9 +6081,155 @@ var init_staging = __esm({
6081
6081
  });
6082
6082
 
6083
6083
  // core/knowledge/loops.ts
6084
+ function joinPath3(base, child) {
6085
+ const separator3 = process.platform === "win32" ? "\\" : "/";
6086
+ return `${base.replace(/[\\/]+/g, separator3)}${separator3}${child}`;
6087
+ }
6088
+ function resolveLoopsFilePath() {
6089
+ return joinPath3(resolveUserDotMemPath(), LOOPS_FILE_NAME);
6090
+ }
6091
+ async function readFile(path) {
6092
+ try {
6093
+ const fs = await import('fs/promises');
6094
+ return await fs.readFile(path, "utf8");
6095
+ } catch {
6096
+ return null;
6097
+ }
6098
+ }
6099
+ async function writeFile(path, content) {
6100
+ const fs = await import('fs/promises');
6101
+ const dir = path.replace(/[\\/][^\\/]+$/, "");
6102
+ await fs.mkdir(dir, { recursive: true });
6103
+ const temporary = `${path}.${process.pid}.${Date.now().toString(36)}.tmp`;
6104
+ try {
6105
+ await fs.writeFile(temporary, content, "utf8");
6106
+ await fs.rename(temporary, path);
6107
+ } catch {
6108
+ await fs.rm(temporary, { force: true }).catch(() => void 0);
6109
+ throw new Error(`Failed to write loops file at ${path}`);
6110
+ }
6111
+ }
6112
+ function emptyDocument() {
6113
+ return { version: LOOPS_FORMAT_VERSION, loops: {} };
6114
+ }
6115
+ function validateDocument(value) {
6116
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
6117
+ throw new Error("Loops document must be an object");
6118
+ }
6119
+ const document = value;
6120
+ if (document.version !== LOOPS_FORMAT_VERSION) {
6121
+ throw new Error(`Unsupported loops document version: ${String(document.version)}`);
6122
+ }
6123
+ if (!document.loops || typeof document.loops !== "object" || Array.isArray(document.loops)) {
6124
+ throw new Error("Loops document loops must be an object");
6125
+ }
6126
+ const loops = {};
6127
+ for (const [id, loopValue] of Object.entries(document.loops)) {
6128
+ const loop = validateLoop(loopValue, id);
6129
+ loops[loop.id] = loop;
6130
+ }
6131
+ return { version: LOOPS_FORMAT_VERSION, loops };
6132
+ }
6133
+ function validateLoop(value, id) {
6134
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
6135
+ throw new Error(`Loop ${id} must be an object`);
6136
+ }
6137
+ const loop = value;
6138
+ if (typeof loop.id !== "string" || !loop.id) {
6139
+ throw new Error(`Loop ${id} requires an id`);
6140
+ }
6141
+ if (typeof loop.text !== "string" || !loop.text) {
6142
+ throw new Error(`Loop ${id} requires non-empty text`);
6143
+ }
6144
+ if (typeof loop.waitor !== "string" || !loop.waitor) {
6145
+ throw new Error(`Loop ${id} requires a waitor`);
6146
+ }
6147
+ if (typeof loop.openedAt !== "string" || !loop.openedAt) {
6148
+ throw new Error(`Loop ${id} requires an openedAt timestamp`);
6149
+ }
6150
+ const result = {
6151
+ id: loop.id,
6152
+ text: loop.text,
6153
+ waitor: loop.waitor,
6154
+ openedAt: loop.openedAt
6155
+ };
6156
+ if (typeof loop.closedAt === "string") result.closedAt = loop.closedAt;
6157
+ if (typeof loop.closedBy === "string") result.closedBy = loop.closedBy;
6158
+ if (typeof loop.closeNote === "string") result.closeNote = loop.closeNote;
6159
+ return result;
6160
+ }
6161
+ async function loadLoops() {
6162
+ const raw = await readFile(resolveLoopsFilePath());
6163
+ if (!raw) return emptyDocument();
6164
+ try {
6165
+ return validateDocument(JSON.parse(raw));
6166
+ } catch {
6167
+ return emptyDocument();
6168
+ }
6169
+ }
6170
+ async function saveLoops(document) {
6171
+ await writeFile(resolveLoopsFilePath(), JSON.stringify(document, null, 2) + "\n");
6172
+ }
6173
+ async function addLoop(input2) {
6174
+ const document = await loadLoops();
6175
+ if (document.loops[input2.id]) {
6176
+ throw new Error(`Loop ${input2.id} already exists`);
6177
+ }
6178
+ const loop = {
6179
+ id: input2.id,
6180
+ text: input2.text,
6181
+ waitor: input2.waitor,
6182
+ openedAt: input2.openedAt ?? (/* @__PURE__ */ new Date()).toISOString()
6183
+ };
6184
+ document.loops[loop.id] = loop;
6185
+ await saveLoops(document);
6186
+ return loop;
6187
+ }
6188
+ async function listLoops(openOnly = true) {
6189
+ const document = await loadLoops();
6190
+ const all = Object.values(document.loops);
6191
+ if (openOnly) {
6192
+ return all.filter((loop) => loop.closedAt === void 0);
6193
+ }
6194
+ return all;
6195
+ }
6196
+ async function closeLoop(id, input2) {
6197
+ const document = await loadLoops();
6198
+ const existing = document.loops[id];
6199
+ if (!existing) {
6200
+ throw new Error(`Loop ${id} not found`);
6201
+ }
6202
+ if (existing.closedAt) {
6203
+ throw new Error(`Loop ${id} is already closed`);
6204
+ }
6205
+ const closed = {
6206
+ ...existing,
6207
+ closedAt: input2.closedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
6208
+ closedBy: input2.by,
6209
+ ...input2.note ? { closeNote: input2.note } : {}
6210
+ };
6211
+ document.loops[id] = closed;
6212
+ await saveLoops(document);
6213
+ return closed;
6214
+ }
6215
+ var LOOPS_FILE_NAME, LOOPS_FORMAT_VERSION;
6084
6216
  var init_loops = __esm({
6085
6217
  "core/knowledge/loops.ts"() {
6086
6218
  init_user_paths();
6219
+ LOOPS_FILE_NAME = "loops.json";
6220
+ LOOPS_FORMAT_VERSION = 1;
6221
+ __name(joinPath3, "joinPath");
6222
+ __name(resolveLoopsFilePath, "resolveLoopsFilePath");
6223
+ __name(readFile, "readFile");
6224
+ __name(writeFile, "writeFile");
6225
+ __name(emptyDocument, "emptyDocument");
6226
+ __name(validateDocument, "validateDocument");
6227
+ __name(validateLoop, "validateLoop");
6228
+ __name(loadLoops, "loadLoops");
6229
+ __name(saveLoops, "saveLoops");
6230
+ __name(addLoop, "addLoop");
6231
+ __name(listLoops, "listLoops");
6232
+ __name(closeLoop, "closeLoop");
6087
6233
  }
6088
6234
  });
6089
6235
 
@@ -6161,14 +6307,14 @@ var init_violations = __esm({
6161
6307
  });
6162
6308
 
6163
6309
  // core/knowledge/session.ts
6164
- function joinPath3(base, child) {
6310
+ function joinPath4(base, child) {
6165
6311
  const separator3 = process.platform === "win32" ? "\\" : "/";
6166
6312
  return `${base.replace(/[\\/]+/g, separator3)}${separator3}${child}`;
6167
6313
  }
6168
6314
  function resolveSessionFilePath() {
6169
- return joinPath3(resolveUserDotMemPath(), SESSION_FILE_NAME);
6315
+ return joinPath4(resolveUserDotMemPath(), SESSION_FILE_NAME);
6170
6316
  }
6171
- async function readFile(path) {
6317
+ async function readFile2(path) {
6172
6318
  try {
6173
6319
  const fs = await import('fs/promises');
6174
6320
  return await fs.readFile(path, "utf8");
@@ -6177,7 +6323,7 @@ async function readFile(path) {
6177
6323
  }
6178
6324
  }
6179
6325
  async function loadSession() {
6180
- const raw = await readFile(resolveSessionFilePath());
6326
+ const raw = await readFile2(resolveSessionFilePath());
6181
6327
  if (!raw) return { ...DEFAULT_SESSION };
6182
6328
  try {
6183
6329
  const parsed = JSON.parse(raw);
@@ -6199,9 +6345,9 @@ var init_session = __esm({
6199
6345
  "core/knowledge/session.ts"() {
6200
6346
  init_user_paths();
6201
6347
  SESSION_FILE_NAME = "session.json";
6202
- __name(joinPath3, "joinPath");
6348
+ __name(joinPath4, "joinPath");
6203
6349
  __name(resolveSessionFilePath, "resolveSessionFilePath");
6204
- __name(readFile, "readFile");
6350
+ __name(readFile2, "readFile");
6205
6351
  DEFAULT_SESSION = {
6206
6352
  doing: "",
6207
6353
  changedFiles: [],
@@ -6214,16 +6360,368 @@ var init_session = __esm({
6214
6360
  });
6215
6361
 
6216
6362
  // core/knowledge/exemplars.ts
6363
+ function joinPath5(base, child) {
6364
+ const separator3 = process.platform === "win32" ? "\\" : "/";
6365
+ return `${base.replace(/[\\/]+/g, separator3)}${separator3}${child}`;
6366
+ }
6367
+ function resolveExemplarsPath() {
6368
+ return joinPath5(resolveUserDotMemPath(), EXEMPLARS_FILE_NAME);
6369
+ }
6370
+ async function readFile3(path) {
6371
+ try {
6372
+ const fs = await import('fs/promises');
6373
+ return await fs.readFile(path, "utf8");
6374
+ } catch {
6375
+ return null;
6376
+ }
6377
+ }
6378
+ async function writeFile2(path, content) {
6379
+ const fs = await import('fs/promises');
6380
+ const dir = path.replace(/[\\/][^\\/]+$/, "");
6381
+ await fs.mkdir(dir, { recursive: true });
6382
+ const temporary = `${path}.${process.pid}.${Date.now().toString(36)}.tmp`;
6383
+ try {
6384
+ await fs.writeFile(temporary, content, "utf8");
6385
+ await fs.rename(temporary, path);
6386
+ } catch {
6387
+ await fs.rm(temporary, { force: true }).catch(() => void 0);
6388
+ throw new Error(`Failed to write exemplars file at ${path}`);
6389
+ }
6390
+ }
6391
+ function emptyStore() {
6392
+ return { version: EXEMPLARS_FORMAT_VERSION, exemplars: {} };
6393
+ }
6394
+ function validateExemplar(value) {
6395
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
6396
+ throw new Error("Exemplar must be an object");
6397
+ }
6398
+ const e = value;
6399
+ if (typeof e.id !== "string" || !e.id) throw new Error("Exemplar requires non-empty id");
6400
+ if (typeof e.pattern !== "string" || !e.pattern) {
6401
+ throw new Error(`Exemplar ${e.id} requires non-empty pattern`);
6402
+ }
6403
+ const source = e.source ?? {};
6404
+ if (typeof source.conversationId !== "string" || !source.conversationId) {
6405
+ throw new Error(`Exemplar ${e.id} requires source.conversationId`);
6406
+ }
6407
+ const now2 = (/* @__PURE__ */ new Date()).toISOString();
6408
+ return {
6409
+ id: e.id,
6410
+ type: "interaction-exemplar",
6411
+ source: {
6412
+ conversationId: source.conversationId,
6413
+ messageIds: Array.isArray(source.messageIds) ? source.messageIds.map(String) : [],
6414
+ ...typeof source.timestamp === "string" ? { timestamp: source.timestamp } : {}
6415
+ },
6416
+ pattern: e.pattern,
6417
+ originalContent: typeof e.originalContent === "string" ? e.originalContent : null,
6418
+ sourceReference: typeof e.sourceReference === "string" ? e.sourceReference : null,
6419
+ retrievalHints: Array.isArray(e.retrievalHints) ? e.retrievalHints.map(String) : [],
6420
+ significance: typeof e.significance === "number" && e.significance >= 0 ? e.significance : 0,
6421
+ confidence: typeof e.confidence === "number" && e.confidence >= 0 && e.confidence <= 1 ? e.confidence : 0,
6422
+ provenance: ["human-stated", "observed", "inferred"].includes(
6423
+ e.provenance
6424
+ ) ? e.provenance : "observed",
6425
+ createdAt: typeof e.createdAt === "string" ? e.createdAt : now2,
6426
+ revision: typeof e.revision === "number" && e.revision > 0 ? e.revision : 1
6427
+ };
6428
+ }
6429
+ function validateStore(value) {
6430
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
6431
+ throw new Error("Exemplars document must be an object");
6432
+ }
6433
+ const doc = value;
6434
+ if (doc.version !== EXEMPLARS_FORMAT_VERSION) {
6435
+ throw new Error(`Unsupported exemplars version: ${String(doc.version)}`);
6436
+ }
6437
+ const exemplars = {};
6438
+ if (doc.exemplars && typeof doc.exemplars === "object" && !Array.isArray(doc.exemplars)) {
6439
+ for (const [_, exemplarValue] of Object.entries(doc.exemplars)) {
6440
+ const exemplar = validateExemplar(exemplarValue);
6441
+ exemplars[exemplar.id] = exemplar;
6442
+ }
6443
+ }
6444
+ return { version: EXEMPLARS_FORMAT_VERSION, exemplars };
6445
+ }
6446
+ async function loadExemplars() {
6447
+ const raw = await readFile3(resolveExemplarsPath());
6448
+ if (raw === null) return emptyStore();
6449
+ try {
6450
+ return validateStore(JSON.parse(raw));
6451
+ } catch {
6452
+ return emptyStore();
6453
+ }
6454
+ }
6455
+ async function saveExemplars(store7) {
6456
+ const validated = validateStore(store7);
6457
+ await writeFile2(resolveExemplarsPath(), JSON.stringify(validated, null, 2));
6458
+ }
6459
+ async function addExemplar(exemplar) {
6460
+ const store7 = await loadExemplars();
6461
+ if (store7.exemplars[exemplar.id]) {
6462
+ throw new Error(`Exemplar ${exemplar.id} already exists`);
6463
+ }
6464
+ if (exemplar.sourceReference) {
6465
+ const existingRef = Object.values(store7.exemplars).find(
6466
+ (e) => e.sourceReference === exemplar.sourceReference
6467
+ );
6468
+ if (existingRef) {
6469
+ throw new Error(`Exemplar with source reference ${exemplar.sourceReference} already exists (id: ${existingRef.id})`);
6470
+ }
6471
+ }
6472
+ const full = {
6473
+ ...exemplar,
6474
+ type: "interaction-exemplar",
6475
+ revision: 1
6476
+ };
6477
+ store7.exemplars[exemplar.id] = full;
6478
+ await saveExemplars(store7);
6479
+ return full;
6480
+ }
6481
+ async function updateExemplar(id, updates) {
6482
+ const store7 = await loadExemplars();
6483
+ const existing = store7.exemplars[id];
6484
+ if (!existing) {
6485
+ throw new Error(`Exemplar ${id} not found`);
6486
+ }
6487
+ const updated = {
6488
+ ...existing,
6489
+ ...updates,
6490
+ id: existing.id,
6491
+ type: "interaction-exemplar",
6492
+ createdAt: existing.createdAt,
6493
+ revision: (updates.revision ?? existing.revision) + 1
6494
+ };
6495
+ store7.exemplars[id] = updated;
6496
+ await saveExemplars(store7);
6497
+ return updated;
6498
+ }
6499
+ var EXEMPLARS_FILE_NAME, EXEMPLARS_FORMAT_VERSION;
6217
6500
  var init_exemplars = __esm({
6218
6501
  "core/knowledge/exemplars.ts"() {
6219
6502
  init_user_paths();
6503
+ EXEMPLARS_FILE_NAME = "exemplars.json";
6504
+ EXEMPLARS_FORMAT_VERSION = 1;
6505
+ __name(joinPath5, "joinPath");
6506
+ __name(resolveExemplarsPath, "resolveExemplarsPath");
6507
+ __name(readFile3, "readFile");
6508
+ __name(writeFile2, "writeFile");
6509
+ __name(emptyStore, "emptyStore");
6510
+ __name(validateExemplar, "validateExemplar");
6511
+ __name(validateStore, "validateStore");
6512
+ __name(loadExemplars, "loadExemplars");
6513
+ __name(saveExemplars, "saveExemplars");
6514
+ __name(addExemplar, "addExemplar");
6515
+ __name(updateExemplar, "updateExemplar");
6220
6516
  }
6221
6517
  });
6222
6518
 
6223
6519
  // core/knowledge/personality-anchor.ts
6520
+ function joinPath6(base, child) {
6521
+ const separator3 = process.platform === "win32" ? "\\" : "/";
6522
+ return `${base.replace(/[\\/]+/g, separator3)}${separator3}${child}`;
6523
+ }
6524
+ function resolvePersonalityAnchorPath() {
6525
+ return joinPath6(resolveUserDotMemPath(), PERSONALITY_ANCHOR_FILE_NAME);
6526
+ }
6527
+ async function readFile4(path) {
6528
+ try {
6529
+ const fs = await import('fs/promises');
6530
+ return await fs.readFile(path, "utf8");
6531
+ } catch {
6532
+ return null;
6533
+ }
6534
+ }
6535
+ async function writeFile3(path, content) {
6536
+ const fs = await import('fs/promises');
6537
+ const dir = path.replace(/[\\/][^\\/]+$/, "");
6538
+ await fs.mkdir(dir, { recursive: true });
6539
+ const temporary = `${path}.${process.pid}.${Date.now().toString(36)}.tmp`;
6540
+ try {
6541
+ await fs.writeFile(temporary, content, "utf8");
6542
+ await fs.rename(temporary, path);
6543
+ } catch {
6544
+ await fs.rm(temporary, { force: true }).catch(() => void 0);
6545
+ throw new Error(`Failed to write personality anchor at ${path}`);
6546
+ }
6547
+ }
6548
+ function emptyAnchor() {
6549
+ const epoch = "1970-01-01T00:00:00.000Z";
6550
+ return {
6551
+ version: PERSONALITY_ANCHOR_FORMAT_VERSION,
6552
+ identity: {
6553
+ communicationStyle: [],
6554
+ durablePreferences: [],
6555
+ interactionBoundaries: []
6556
+ },
6557
+ metadata: {
6558
+ createdAt: epoch,
6559
+ updatedAt: epoch,
6560
+ revision: 1,
6561
+ sourceReferences: []
6562
+ }
6563
+ };
6564
+ }
6565
+ function validateCommunicationStyle(value) {
6566
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
6567
+ throw new Error("communicationStyle entry must be an object");
6568
+ }
6569
+ const style = value;
6570
+ if (typeof style.description !== "string" || !style.description) {
6571
+ throw new Error("communicationStyle entry requires non-empty description");
6572
+ }
6573
+ const confidence = style.confidence ?? "inferred";
6574
+ if (!["inferred", "observed", "human-stated"].includes(confidence)) {
6575
+ throw new Error(`Invalid confidence value: ${String(style.confidence)}`);
6576
+ }
6577
+ const evidence = Array.isArray(style.evidence) ? style.evidence.map(String) : [];
6578
+ return {
6579
+ description: style.description,
6580
+ confidence,
6581
+ evidence,
6582
+ lastObserved: typeof style.lastObserved === "string" ? style.lastObserved : (/* @__PURE__ */ new Date()).toISOString()
6583
+ };
6584
+ }
6585
+ function validateDurablePreference(value) {
6586
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
6587
+ throw new Error("durablePreference entry must be an object");
6588
+ }
6589
+ const pref = value;
6590
+ if (typeof pref.id !== "string" || !pref.id) {
6591
+ throw new Error("durablePreference entry requires non-empty id");
6592
+ }
6593
+ if (typeof pref.statement !== "string" || !pref.statement) {
6594
+ throw new Error(`durablePreference ${pref.id} requires non-empty statement`);
6595
+ }
6596
+ const confidence = pref.confidence ?? "inferred";
6597
+ if (!["inferred", "observed", "human-stated"].includes(confidence)) {
6598
+ throw new Error(`Invalid confidence value: ${String(pref.confidence)}`);
6599
+ }
6600
+ const evidence = Array.isArray(pref.evidence) ? pref.evidence.map(String) : [];
6601
+ const now2 = (/* @__PURE__ */ new Date()).toISOString();
6602
+ return {
6603
+ id: pref.id,
6604
+ statement: pref.statement,
6605
+ confidence,
6606
+ evidence,
6607
+ firstObserved: typeof pref.firstObserved === "string" ? pref.firstObserved : now2,
6608
+ lastConfirmed: typeof pref.lastConfirmed === "string" ? pref.lastConfirmed : now2,
6609
+ ...typeof pref.supersededBy === "string" ? { supersededBy: pref.supersededBy } : {}
6610
+ };
6611
+ }
6612
+ function validateInteractionBoundary(value) {
6613
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
6614
+ throw new Error("interactionBoundary entry must be an object");
6615
+ }
6616
+ const boundary = value;
6617
+ if (typeof boundary.id !== "string" || !boundary.id) {
6618
+ throw new Error("interactionBoundary entry requires non-empty id");
6619
+ }
6620
+ if (typeof boundary.rule !== "string" || !boundary.rule) {
6621
+ throw new Error(`interactionBoundary ${boundary.id} requires non-empty rule`);
6622
+ }
6623
+ const confidence = boundary.confidence ?? "inferred";
6624
+ if (!["inferred", "observed", "human-stated"].includes(confidence)) {
6625
+ throw new Error(`Invalid confidence value: ${String(boundary.confidence)}`);
6626
+ }
6627
+ const evidence = Array.isArray(boundary.evidence) ? boundary.evidence.map(String) : [];
6628
+ const source = boundary.source ?? "conversation";
6629
+ if (!["profile", "memory", "conversation"].includes(source)) {
6630
+ throw new Error(`Invalid boundary source: ${String(boundary.source)}`);
6631
+ }
6632
+ return {
6633
+ id: boundary.id,
6634
+ rule: boundary.rule,
6635
+ confidence,
6636
+ evidence,
6637
+ source,
6638
+ lastConfirmed: typeof boundary.lastConfirmed === "string" ? boundary.lastConfirmed : (/* @__PURE__ */ new Date()).toISOString()
6639
+ };
6640
+ }
6641
+ function validateAnchor(value) {
6642
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
6643
+ throw new Error("Personality anchor document must be an object");
6644
+ }
6645
+ const doc = value;
6646
+ if (doc.version !== PERSONALITY_ANCHOR_FORMAT_VERSION) {
6647
+ throw new Error(`Unsupported personality anchor version: ${String(doc.version)}`);
6648
+ }
6649
+ const identity = doc.identity ?? {};
6650
+ const metadata = doc.metadata ?? {};
6651
+ const communicationStyle = Array.isArray(identity.communicationStyle) ? identity.communicationStyle.map(validateCommunicationStyle) : [];
6652
+ const durablePreferences = Array.isArray(identity.durablePreferences) ? identity.durablePreferences.map(validateDurablePreference) : [];
6653
+ const interactionBoundaries = Array.isArray(identity.interactionBoundaries) ? identity.interactionBoundaries.map(validateInteractionBoundary) : [];
6654
+ const sourceRefs = Array.isArray(metadata.sourceReferences) ? metadata.sourceReferences.map(String) : [];
6655
+ return {
6656
+ version: PERSONALITY_ANCHOR_FORMAT_VERSION,
6657
+ identity: {
6658
+ communicationStyle,
6659
+ durablePreferences,
6660
+ interactionBoundaries
6661
+ },
6662
+ metadata: {
6663
+ createdAt: typeof metadata.createdAt === "string" ? metadata.createdAt : (/* @__PURE__ */ new Date()).toISOString(),
6664
+ updatedAt: typeof metadata.updatedAt === "string" ? metadata.updatedAt : (/* @__PURE__ */ new Date()).toISOString(),
6665
+ revision: typeof metadata.revision === "number" && metadata.revision > 0 ? metadata.revision : 1,
6666
+ sourceReferences: sourceRefs
6667
+ }
6668
+ };
6669
+ }
6670
+ async function loadPersonalityAnchor() {
6671
+ const raw = await readFile4(resolvePersonalityAnchorPath());
6672
+ if (raw === null) return emptyAnchor();
6673
+ try {
6674
+ const parsed = JSON.parse(raw);
6675
+ return validateAnchor(parsed);
6676
+ } catch {
6677
+ return emptyAnchor();
6678
+ }
6679
+ }
6680
+ async function savePersonalityAnchor(anchor2) {
6681
+ const validated = validateAnchor(anchor2);
6682
+ const dirPath = resolveUserDotMemPath();
6683
+ const fs = await import('fs/promises');
6684
+ await fs.mkdir(dirPath, { recursive: true });
6685
+ await writeFile3(resolvePersonalityAnchorPath(), JSON.stringify(validated, null, 2));
6686
+ }
6687
+ async function updatePersonalityAnchor(updates) {
6688
+ const existing = await loadPersonalityAnchor();
6689
+ const now2 = (/* @__PURE__ */ new Date()).toISOString();
6690
+ const updated = {
6691
+ ...existing,
6692
+ identity: {
6693
+ communicationStyle: updates.communicationStyle ?? existing.identity.communicationStyle,
6694
+ durablePreferences: updates.durablePreferences ?? existing.identity.durablePreferences,
6695
+ interactionBoundaries: updates.interactionBoundaries ?? existing.identity.interactionBoundaries
6696
+ },
6697
+ metadata: {
6698
+ ...existing.metadata,
6699
+ updatedAt: now2,
6700
+ revision: existing.metadata.revision + 1,
6701
+ sourceReferences: updates.sourceReferences ? [.../* @__PURE__ */ new Set([...existing.metadata.sourceReferences, ...updates.sourceReferences])] : existing.metadata.sourceReferences
6702
+ }
6703
+ };
6704
+ await savePersonalityAnchor(updated);
6705
+ return updated;
6706
+ }
6707
+ var PERSONALITY_ANCHOR_FILE_NAME, PERSONALITY_ANCHOR_FORMAT_VERSION;
6224
6708
  var init_personality_anchor = __esm({
6225
6709
  "core/knowledge/personality-anchor.ts"() {
6226
6710
  init_user_paths();
6711
+ PERSONALITY_ANCHOR_FILE_NAME = "personality-anchor.json";
6712
+ PERSONALITY_ANCHOR_FORMAT_VERSION = 1;
6713
+ __name(joinPath6, "joinPath");
6714
+ __name(resolvePersonalityAnchorPath, "resolvePersonalityAnchorPath");
6715
+ __name(readFile4, "readFile");
6716
+ __name(writeFile3, "writeFile");
6717
+ __name(emptyAnchor, "emptyAnchor");
6718
+ __name(validateCommunicationStyle, "validateCommunicationStyle");
6719
+ __name(validateDurablePreference, "validateDurablePreference");
6720
+ __name(validateInteractionBoundary, "validateInteractionBoundary");
6721
+ __name(validateAnchor, "validateAnchor");
6722
+ __name(loadPersonalityAnchor, "loadPersonalityAnchor");
6723
+ __name(savePersonalityAnchor, "savePersonalityAnchor");
6724
+ __name(updatePersonalityAnchor, "updatePersonalityAnchor");
6227
6725
  }
6228
6726
  });
6229
6727
 
@@ -6975,19 +7473,19 @@ var journal = {
6975
7473
  hlc: entry.hlc || hlc.serialize(hlc.tick())
6976
7474
  };
6977
7475
  const key = `${STORE_PREFIX(ns)}${row.id}`;
6978
- store.set(key, row);
6979
- const idx = store.get(INDEX_KEY(ns)) || [];
7476
+ store$1.set(key, row);
7477
+ const idx = store$1.get(INDEX_KEY(ns)) || [];
6980
7478
  if (!idx.includes(row.id)) idx.push(row.id);
6981
- store.set(INDEX_KEY(ns), idx);
7479
+ store$1.set(INDEX_KEY(ns), idx);
6982
7480
  return row;
6983
7481
  },
6984
7482
  /** All pending (not-yet-synced) entries for the current namespace. */
6985
7483
  async pending() {
6986
7484
  const ns = namespace();
6987
7485
  const out = [];
6988
- const idx = store.get(INDEX_KEY(ns)) || [];
7486
+ const idx = store$1.get(INDEX_KEY(ns)) || [];
6989
7487
  for (const id of idx) {
6990
- const raw = store.get(`${STORE_PREFIX(ns)}${id}`);
7488
+ const raw = store$1.get(`${STORE_PREFIX(ns)}${id}`);
6991
7489
  if (!raw) continue;
6992
7490
  const e = parseEntry(raw);
6993
7491
  if (e && e.sync !== "synced") out.push(e);
@@ -7010,31 +7508,31 @@ var journal = {
7010
7508
  if (!ids.length) return 0;
7011
7509
  const ns = namespace();
7012
7510
  let count = 0;
7013
- const idx = store.get(INDEX_KEY(ns)) || [];
7511
+ const idx = store$1.get(INDEX_KEY(ns)) || [];
7014
7512
  for (const id of idx) {
7015
7513
  if (!ids.includes(id)) continue;
7016
7514
  const key = `${STORE_PREFIX(ns)}${id}`;
7017
- const raw = store.get(key);
7515
+ const raw = store$1.get(key);
7018
7516
  if (!raw) continue;
7019
7517
  const e = parseEntry(raw);
7020
7518
  if (!e || e.sync === "synced") continue;
7021
7519
  e.sync = "synced";
7022
- store.set(key, e);
7520
+ store$1.set(key, e);
7023
7521
  count++;
7024
7522
  }
7025
7523
  return count;
7026
7524
  },
7027
7525
  async get(id) {
7028
7526
  const ns = namespace();
7029
- const raw = store.get(`${STORE_PREFIX(ns)}${id}`);
7527
+ const raw = store$1.get(`${STORE_PREFIX(ns)}${id}`);
7030
7528
  return parseEntry(raw ?? "");
7031
7529
  },
7032
7530
  /** Remove all journal rows for the current namespace. */
7033
7531
  async clear() {
7034
7532
  const ns = namespace();
7035
- const idx = store.get(INDEX_KEY(ns)) || [];
7036
- for (const id of idx) store.remove(`${STORE_PREFIX(ns)}${id}`);
7037
- store.remove(INDEX_KEY(ns));
7533
+ const idx = store$1.get(INDEX_KEY(ns)) || [];
7534
+ for (const id of idx) store$1.remove(`${STORE_PREFIX(ns)}${id}`);
7535
+ store$1.remove(INDEX_KEY(ns));
7038
7536
  },
7039
7537
  /**
7040
7538
  * Reconcile the local journal against the configured provider. Pushes pending
@@ -7113,7 +7611,7 @@ var journal = {
7113
7611
  */
7114
7612
  async status() {
7115
7613
  try {
7116
- const capabilities = store.capabilities?.();
7614
+ const capabilities = store$1.capabilities?.();
7117
7615
  return capabilities?.persistent ? "store" : "memory";
7118
7616
  } catch {
7119
7617
  return "memory";
@@ -7174,7 +7672,7 @@ var StoreKnowledgeRepository = class {
7174
7672
  __name(this, "StoreKnowledgeRepository");
7175
7673
  }
7176
7674
  async load() {
7177
- const raw = store.get(KNOWLEDGE_STATE_KEY);
7675
+ const raw = store$1.get(KNOWLEDGE_STATE_KEY);
7178
7676
  if (!raw) return { version: 0, claims: [] };
7179
7677
  return typeof raw === "string" ? JSON.parse(raw) : raw;
7180
7678
  }
@@ -7184,7 +7682,7 @@ var StoreKnowledgeRepository = class {
7184
7682
  if (current.version !== expectedVersion) {
7185
7683
  throw new Error(`Stale update: expected persisted version ${expectedVersion}, received ${current.version}`);
7186
7684
  }
7187
- store.set(KNOWLEDGE_STATE_KEY, state3);
7685
+ store$1.set(KNOWLEDGE_STATE_KEY, state3);
7188
7686
  }, "write");
7189
7687
  const previous = knowledgeSaveQueue;
7190
7688
  knowledgeSaveQueue = previous.then(write, write);
@@ -7386,27 +7884,27 @@ var auditPolicyAction = /* @__PURE__ */ __name((action, key) => {
7386
7884
  }
7387
7885
  }, "auditPolicyAction");
7388
7886
  var resolveOverrides = /* @__PURE__ */ __name(async (namespace2, now2 = () => /* @__PURE__ */ new Date()) => {
7389
- const store6 = await getPolicyStore();
7887
+ const store7 = await getPolicyStore();
7390
7888
  const namespaces = namespace2 ? [namespace2] : POLICY_NAMESPACES;
7391
- const documents = await Promise.all(namespaces.map((entry) => store6.load(entry)));
7889
+ const documents = await Promise.all(namespaces.map((entry) => store7.load(entry)));
7392
7890
  return documents.flatMap((document) => document.overrides.map(
7393
7891
  (override) => resolveOverrideState(override, document.records.find((record2) => record2.id === override.targetPolicyId), now2)
7394
7892
  )).sort((left, right) => left.override.id.localeCompare(right.override.id));
7395
7893
  }, "resolveOverrides");
7396
7894
  var policy = {
7397
7895
  async assign(input2, namespace2 = "operator", basedOnRevision) {
7398
- const store6 = await getPolicyStore();
7399
- const record2 = await store6.assign(input2, namespace2, basedOnRevision);
7896
+ const store7 = await getPolicyStore();
7897
+ const record2 = await store7.assign(input2, namespace2, basedOnRevision);
7400
7898
  auditPolicyAction("policy.assign", record2.id);
7401
7899
  return record2;
7402
7900
  },
7403
7901
  async list() {
7404
- const store6 = await getPolicyStore();
7405
- return store6.list();
7902
+ const store7 = await getPolicyStore();
7903
+ return store7.list();
7406
7904
  },
7407
7905
  async remove(id, namespace2 = "operator", basedOnRevision) {
7408
- const store6 = await getPolicyStore();
7409
- await store6.remove(id, namespace2, basedOnRevision);
7906
+ const store7 = await getPolicyStore();
7907
+ await store7.remove(id, namespace2, basedOnRevision);
7410
7908
  auditPolicyAction("policy.remove", id);
7411
7909
  },
7412
7910
  /**
@@ -7420,16 +7918,16 @@ var policy = {
7420
7918
  * the durable audit trail with a terminal CLEAR entry.
7421
7919
  */
7422
7920
  async clear(authority) {
7423
- const store6 = await getPolicyStore();
7424
- await store6.clear(authority);
7921
+ const store7 = await getPolicyStore();
7922
+ await store7.clear(authority);
7425
7923
  auditPolicyAction("policy.clear", "policy");
7426
7924
  },
7427
7925
  async evaluate(event, payload) {
7428
- const store6 = await getPolicyStore();
7926
+ const store7 = await getPolicyStore();
7429
7927
  const [state3, policies, overrides] = await Promise.all([
7430
7928
  loadCombinedKnowledgeState(),
7431
- store6.list(),
7432
- store6.listOverrides()
7929
+ store7.list(),
7930
+ store7.listOverrides()
7433
7931
  ]);
7434
7932
  const claims = activeClaims(state3);
7435
7933
  return evaluatePolicies({ event, claims, policies, overrides, payload });
@@ -7451,14 +7949,14 @@ var policy = {
7451
7949
  */
7452
7950
  override: {
7453
7951
  async grant(input2, namespace2 = "operator", basedOnRevision) {
7454
- const store6 = await getPolicyStore();
7455
- const override = await store6.grantOverride(input2, namespace2, basedOnRevision);
7952
+ const store7 = await getPolicyStore();
7953
+ const override = await store7.grantOverride(input2, namespace2, basedOnRevision);
7456
7954
  auditPolicyAction("policy.override", override.id);
7457
7955
  return override;
7458
7956
  },
7459
7957
  async revoke(input2, namespace2 = "operator", basedOnRevision) {
7460
- const store6 = await getPolicyStore();
7461
- const override = await store6.revokeOverride(input2, namespace2, basedOnRevision);
7958
+ const store7 = await getPolicyStore();
7959
+ const override = await store7.revokeOverride(input2, namespace2, basedOnRevision);
7462
7960
  auditPolicyAction("policy.revoke", override.id);
7463
7961
  return override;
7464
7962
  },
@@ -7466,8 +7964,8 @@ var policy = {
7466
7964
  return resolveOverrides(namespace2);
7467
7965
  },
7468
7966
  async effective(event, namespace2) {
7469
- const store6 = await getPolicyStore();
7470
- const states = await store6.effectiveState(namespace2);
7967
+ const store7 = await getPolicyStore();
7968
+ const states = await store7.effectiveState(namespace2);
7471
7969
  if (event === void 0) return states;
7472
7970
  const canonical = event.trim();
7473
7971
  return states.filter((state3) => state3.event === canonical);
@@ -7480,8 +7978,8 @@ var policy = {
7480
7978
  * additional best-effort sink, and this is the durable record.
7481
7979
  */
7482
7980
  async audit(namespace2) {
7483
- const store6 = await getPolicyStore();
7484
- return store6.auditTrail(namespace2);
7981
+ const store7 = await getPolicyStore();
7982
+ return store7.auditTrail(namespace2);
7485
7983
  },
7486
7984
  contract() {
7487
7985
  return MEMORY_PROJECTION_CONTRACT;
@@ -7627,7 +8125,7 @@ async function saveToScope(entry) {
7627
8125
  session.set(storageKey, serialized);
7628
8126
  break;
7629
8127
  case "local":
7630
- store.set(storageKey, serialized);
8128
+ store$1.set(storageKey, serialized);
7631
8129
  break;
7632
8130
  case "durable":
7633
8131
  await idb.set("memories", storageKey, serialized);
@@ -7649,7 +8147,7 @@ async function loadFromScope(id, scope, isSuperseded = false) {
7649
8147
  raw = session.get(storageKey);
7650
8148
  break;
7651
8149
  case "local":
7652
- raw = store.get(storageKey);
8150
+ raw = store$1.get(storageKey);
7653
8151
  break;
7654
8152
  case "durable":
7655
8153
  raw = await idb.get("memories", storageKey);
@@ -7693,7 +8191,7 @@ async function removeFromScope(id, scope, isSuperseded = false) {
7693
8191
  session.remove(storageKey);
7694
8192
  break;
7695
8193
  case "local":
7696
- store.remove(storageKey);
8194
+ store$1.remove(storageKey);
7697
8195
  break;
7698
8196
  case "durable":
7699
8197
  await idb.deleteKey("memories", storageKey);
@@ -7704,7 +8202,7 @@ async function removeFromScope(id, scope, isSuperseded = false) {
7704
8202
  __name(removeFromScope, "removeFromScope");
7705
8203
  async function getAllIndexes() {
7706
8204
  try {
7707
- const raw = store.get(MEMORY_INDEX_KEY);
8205
+ const raw = store$1.get(MEMORY_INDEX_KEY);
7708
8206
  if (!raw) return {};
7709
8207
  return JSON.parse(raw);
7710
8208
  } catch (err2) {
@@ -7716,7 +8214,7 @@ __name(getAllIndexes, "getAllIndexes");
7716
8214
  async function updateIndex(id, scope, isSuperseded = false) {
7717
8215
  const index = await getAllIndexes();
7718
8216
  index[id] = { scope, superseded: isSuperseded };
7719
- store.set(MEMORY_INDEX_KEY, JSON.stringify(index));
8217
+ store$1.set(MEMORY_INDEX_KEY, JSON.stringify(index));
7720
8218
  }
7721
8219
  __name(updateIndex, "updateIndex");
7722
8220
  async function removeFromIndex(id, isSuperseded = false) {
@@ -7729,7 +8227,7 @@ async function removeFromIndex(id, isSuperseded = false) {
7729
8227
  delete index[id];
7730
8228
  }
7731
8229
  }
7732
- store.set(MEMORY_INDEX_KEY, JSON.stringify(index));
8230
+ store$1.set(MEMORY_INDEX_KEY, JSON.stringify(index));
7733
8231
  }
7734
8232
  __name(removeFromIndex, "removeFromIndex");
7735
8233
  async function loadAll() {
@@ -7945,7 +8443,7 @@ var entries = {
7945
8443
  for (const [id, info] of Object.entries(index)) {
7946
8444
  await removeFromScope(id, info.scope, info.superseded);
7947
8445
  }
7948
- store.remove(MEMORY_INDEX_KEY);
8446
+ store$1.remove(MEMORY_INDEX_KEY);
7949
8447
  },
7950
8448
  async _getEntry(key) {
7951
8449
  return getEntry(key);
@@ -8455,6 +8953,778 @@ var injectJoySeed = /* @__PURE__ */ __name(async (opts) => {
8455
8953
  return { id: seedId, action: "stored" };
8456
8954
  }, "injectJoySeed");
8457
8955
 
8956
+ // core/memory/capture-engine.ts
8957
+ init_exemplars();
8958
+ init_loops();
8959
+ init_personality_anchor();
8960
+ var CAPTURE_STATE_KEY = "__dotmem_capture_state__";
8961
+ var DEFAULT_CONFIG = {
8962
+ minSignificance: 0.3,
8963
+ maxItemsPerConversation: 50,
8964
+ dedupSimilarityThreshold: 0.75,
8965
+ preserveConflicts: true,
8966
+ tempContextTtlMs: 24 * 60 * 60 * 1e3,
8967
+ autoCreateExemplars: true,
8968
+ autoCreateLoops: true,
8969
+ autoCreateClaims: true
8970
+ };
8971
+ var CATEGORY_KEYWORDS = {
8972
+ fact: [
8973
+ "is",
8974
+ "are",
8975
+ "was",
8976
+ "were",
8977
+ "uses",
8978
+ "built with",
8979
+ "depends on",
8980
+ "located at",
8981
+ "named",
8982
+ "called",
8983
+ "version",
8984
+ "language",
8985
+ "framework",
8986
+ "test",
8987
+ "testing"
8988
+ ],
8989
+ decision: [
8990
+ "decided",
8991
+ "decision",
8992
+ "agreed",
8993
+ "chose",
8994
+ "selected",
8995
+ "adopt",
8996
+ "going with",
8997
+ "will use",
8998
+ "commit to",
8999
+ "resolve",
9000
+ "settled"
9001
+ ],
9002
+ experience: [
9003
+ "remember when",
9004
+ "we talked about",
9005
+ "discussed",
9006
+ "experienced",
9007
+ "encountered",
9008
+ "faced",
9009
+ "went through",
9010
+ "session",
9011
+ "conversation"
9012
+ ],
9013
+ question: [
9014
+ "?",
9015
+ "how do",
9016
+ "what is",
9017
+ "why",
9018
+ "when",
9019
+ "where",
9020
+ "which",
9021
+ "can you",
9022
+ "should we",
9023
+ "is it possible"
9024
+ ],
9025
+ open_loop: [
9026
+ "still need to",
9027
+ "pending",
9028
+ "waiting for",
9029
+ "todo",
9030
+ "to do",
9031
+ "open",
9032
+ "unresolved",
9033
+ "outstanding",
9034
+ "follow up",
9035
+ "blocked"
9036
+ ],
9037
+ preference: [
9038
+ "prefer",
9039
+ "prefers",
9040
+ "like",
9041
+ "likes",
9042
+ "favorite",
9043
+ "always",
9044
+ "never",
9045
+ "don't like",
9046
+ "dislike",
9047
+ "style",
9048
+ "habit"
9049
+ ],
9050
+ project_context: [
9051
+ "project",
9052
+ "repository",
9053
+ "codebase",
9054
+ "architecture",
9055
+ "stack",
9056
+ "deploy",
9057
+ "ci",
9058
+ "pipeline",
9059
+ "package"
9060
+ ],
9061
+ temporary_context: [
9062
+ "for now",
9063
+ "just for",
9064
+ "temporary",
9065
+ "this session",
9066
+ "currently",
9067
+ "right now",
9068
+ "at the moment",
9069
+ "for this task"
9070
+ ],
9071
+ inference: [
9072
+ "probably",
9073
+ "likely",
9074
+ "maybe",
9075
+ "perhaps",
9076
+ "seems",
9077
+ "appears",
9078
+ "suggests",
9079
+ "indicates",
9080
+ "implies",
9081
+ "might",
9082
+ "could be"
9083
+ ]
9084
+ };
9085
+ var REMEMBER_PATTERNS = [
9086
+ /remember this/i,
9087
+ /remember that/i,
9088
+ /keep this in mind/i,
9089
+ /don't forget/i,
9090
+ /do not forget/i,
9091
+ /store this/i,
9092
+ /save this/i
9093
+ ];
9094
+ var DO_NOT_REMEMBER_PATTERNS = [
9095
+ /don't remember/i,
9096
+ /do not remember/i,
9097
+ /forget this/i,
9098
+ /don't store/i,
9099
+ /do not store/i,
9100
+ /not relevant/i,
9101
+ /ignore this/i,
9102
+ /temporary only/i,
9103
+ /this session only/i
9104
+ ];
9105
+ function generateId() {
9106
+ return `capture-${hlc.serialize(hlc.tick())}-${Math.random().toString(36).slice(2, 10)}`;
9107
+ }
9108
+ __name(generateId, "generateId");
9109
+ function nowIso() {
9110
+ return (/* @__PURE__ */ new Date()).toISOString();
9111
+ }
9112
+ __name(nowIso, "nowIso");
9113
+ function normalizeText(text) {
9114
+ return text.normalize("NFKC").toLocaleLowerCase("en-US").replace(/[^\w\s]/g, " ").replace(/\s+/g, " ").trim();
9115
+ }
9116
+ __name(normalizeText, "normalizeText");
9117
+ function tokenize(text) {
9118
+ return new Set(normalizeText(text).split(" ").filter((t) => t.length > 2));
9119
+ }
9120
+ __name(tokenize, "tokenize");
9121
+ function jaccardSimilarity(a, b) {
9122
+ const ta = tokenize(a);
9123
+ const tb = tokenize(b);
9124
+ if (ta.size === 0 && tb.size === 0) return 1;
9125
+ if (ta.size === 0 || tb.size === 0) return 0;
9126
+ const intersection2 = new Set([...ta].filter((x2) => tb.has(x2)));
9127
+ const union2 = /* @__PURE__ */ new Set([...ta, ...tb]);
9128
+ return intersection2.size / union2.size;
9129
+ }
9130
+ __name(jaccardSimilarity, "jaccardSimilarity");
9131
+ function containsPhrase2(text, phrase) {
9132
+ const t = normalizeText(text);
9133
+ const p = normalizeText(phrase);
9134
+ return t.includes(p);
9135
+ }
9136
+ __name(containsPhrase2, "containsPhrase");
9137
+ function detectExplicitInstructions(text, source) {
9138
+ const instructions = [];
9139
+ for (const pattern of REMEMBER_PATTERNS) {
9140
+ if (pattern.test(text)) {
9141
+ instructions.push({
9142
+ type: "remember",
9143
+ content: text,
9144
+ source,
9145
+ timestamp: nowIso()
9146
+ });
9147
+ break;
9148
+ }
9149
+ }
9150
+ for (const pattern of DO_NOT_REMEMBER_PATTERNS) {
9151
+ if (pattern.test(text)) {
9152
+ instructions.push({
9153
+ type: "do-not-remember",
9154
+ content: text,
9155
+ source,
9156
+ timestamp: nowIso()
9157
+ });
9158
+ break;
9159
+ }
9160
+ }
9161
+ return instructions;
9162
+ }
9163
+ __name(detectExplicitInstructions, "detectExplicitInstructions");
9164
+ function classifyCategory(text, explicitInstructions) {
9165
+ const lower = text.toLocaleLowerCase("en-US");
9166
+ if (explicitInstructions.some((i2) => i2.type === "do-not-remember")) {
9167
+ return "temporary_context";
9168
+ }
9169
+ if (explicitInstructions.some((i2) => i2.type === "remember")) {
9170
+ if (/prefer|prefers|like|likes|favorite|always|never/i.test(lower)) {
9171
+ return "preference";
9172
+ }
9173
+ if (/decided|decision|agreed|chose|adopt/i.test(lower)) {
9174
+ return "decision";
9175
+ }
9176
+ return "fact";
9177
+ }
9178
+ const scores = {};
9179
+ for (const cat of Object.keys(CATEGORY_KEYWORDS)) {
9180
+ scores[cat] = CATEGORY_KEYWORDS[cat].filter((kw) => containsPhrase2(lower, kw)).length;
9181
+ }
9182
+ if (/probably|likely|maybe|perhaps|seems|appears|might|could be/i.test(lower)) {
9183
+ scores.inference += 3;
9184
+ }
9185
+ if (text.includes("?")) {
9186
+ scores.question += 3;
9187
+ }
9188
+ if (/decided|decision|agreed|chose|adopt|will use|going with|resolve|settled/i.test(lower)) {
9189
+ scores.decision += 3;
9190
+ }
9191
+ if (/prefer|prefers|like|likes|favorite|always|never|don.t like|dislike/i.test(lower)) {
9192
+ scores.preference += 3;
9193
+ }
9194
+ if (/still need to|pending|waiting for|todo|to do|unresolved|outstanding|follow.?up|blocked/i.test(lower)) {
9195
+ scores.open_loop += 3;
9196
+ }
9197
+ if (/remember when|we talked about|discussed|experienced|encountered|session|conversation/i.test(lower)) {
9198
+ scores.experience += 2;
9199
+ }
9200
+ if (/repository|architecture|deploy|ci|pipeline/i.test(lower)) {
9201
+ scores.project_context += 2;
9202
+ }
9203
+ if (/just for|this session|for now|temporary/i.test(lower)) {
9204
+ scores.temporary_context += 3;
9205
+ }
9206
+ if (scores.fact > 0 && scores.project_context > 0 && scores.fact === scores.project_context) {
9207
+ scores.fact += 1;
9208
+ }
9209
+ let bestCategory = "fact";
9210
+ let bestScore = -1;
9211
+ for (const [cat, score] of Object.entries(scores)) {
9212
+ if (score > bestScore) {
9213
+ bestScore = score;
9214
+ bestCategory = cat;
9215
+ }
9216
+ }
9217
+ if (bestScore === 0) return "fact";
9218
+ return bestCategory;
9219
+ }
9220
+ __name(classifyCategory, "classifyCategory");
9221
+ function determineEpistemicType(category, text, explicitInstructions) {
9222
+ if (explicitInstructions.some((i2) => i2.type === "remember")) {
9223
+ return "human-stated";
9224
+ }
9225
+ if (category === "inference" || /probably|likely|maybe|perhaps|seems|appears/i.test(text)) {
9226
+ return "inferred";
9227
+ }
9228
+ if (category === "question") return "observed";
9229
+ return "observed";
9230
+ }
9231
+ __name(determineEpistemicType, "determineEpistemicType");
9232
+ function determineConfidence(category, epistemicType, _text) {
9233
+ if (epistemicType === "human-stated") return "high";
9234
+ if (epistemicType === "inferred") return "low";
9235
+ if (category === "decision" || category === "preference") return "medium";
9236
+ if (category === "question") return "medium";
9237
+ if (category === "fact") return "medium";
9238
+ return "low";
9239
+ }
9240
+ __name(determineConfidence, "determineConfidence");
9241
+ function extractEntities(text) {
9242
+ const entities = [];
9243
+ const seen = /* @__PURE__ */ new Set();
9244
+ const capitalizedMatches = text.match(/\b[A-Z][a-zA-Z]+(?:\s+[A-Z][a-zA-Z]+)*\b/g) || [];
9245
+ for (const match of capitalizedMatches) {
9246
+ if (seen.has(match)) continue;
9247
+ seen.add(match);
9248
+ entities.push({
9249
+ id: `entity-${normalizeText(match)}`,
9250
+ type: "concept",
9251
+ name: match,
9252
+ aliases: [],
9253
+ relationships: []
9254
+ });
9255
+ }
9256
+ const quotedMatches = text.match(/["'`]([^"`']{2,})["'`]/g) || [];
9257
+ for (const match of quotedMatches) {
9258
+ const clean = match.replace(/["'`]/g, "");
9259
+ if (seen.has(clean)) continue;
9260
+ seen.add(clean);
9261
+ entities.push({
9262
+ id: `entity-${normalizeText(clean)}`,
9263
+ type: "concept",
9264
+ name: clean,
9265
+ aliases: [],
9266
+ relationships: []
9267
+ });
9268
+ }
9269
+ return entities;
9270
+ }
9271
+ __name(extractEntities, "extractEntities");
9272
+ function extractRelationships(_text, entities) {
9273
+ const relationships = [];
9274
+ if (entities.length < 2) return relationships;
9275
+ for (let i2 = 0; i2 < entities.length - 1; i2++) {
9276
+ for (let j = i2 + 1; j < entities.length; j++) {
9277
+ relationships.push({
9278
+ from: entities[i2].id,
9279
+ to: entities[j].id,
9280
+ type: "related-to",
9281
+ confidence: 0.5
9282
+ });
9283
+ }
9284
+ }
9285
+ return relationships;
9286
+ }
9287
+ __name(extractRelationships, "extractRelationships");
9288
+ async function findExistingSimilarItems(statement, category, existingItems, threshold) {
9289
+ const matches2 = [];
9290
+ for (const existing of existingItems) {
9291
+ if (existing.category !== category) continue;
9292
+ const similarity = jaccardSimilarity(statement, existing.statement);
9293
+ if (similarity >= threshold) {
9294
+ matches2.push({
9295
+ existingId: existing.id,
9296
+ existingStatement: existing.statement,
9297
+ similarity,
9298
+ matchType: similarity >= 0.95 ? "exact" : "semantic",
9299
+ category: existing.category
9300
+ });
9301
+ }
9302
+ }
9303
+ return matches2;
9304
+ }
9305
+ __name(findExistingSimilarItems, "findExistingSimilarItems");
9306
+ async function findExistingMemoryEntries(statement, category) {
9307
+ const matches2 = [];
9308
+ try {
9309
+ const all = await entries._loadAll();
9310
+ for (const entry of all) {
9311
+ if (entry.status !== "active") continue;
9312
+ if (entry.type !== category && entry.type !== "fact") continue;
9313
+ const entryText = typeof entry.value === "string" ? entry.value : JSON.stringify(entry.value);
9314
+ const similarity = jaccardSimilarity(statement, entryText);
9315
+ if (similarity >= DEFAULT_CONFIG.dedupSimilarityThreshold) {
9316
+ matches2.push({
9317
+ existingId: entry.id,
9318
+ existingStatement: entryText,
9319
+ similarity,
9320
+ matchType: similarity >= 0.95 ? "exact" : "semantic",
9321
+ category
9322
+ });
9323
+ }
9324
+ }
9325
+ } catch {
9326
+ }
9327
+ return matches2;
9328
+ }
9329
+ __name(findExistingMemoryEntries, "findExistingMemoryEntries");
9330
+ function shouldStoreInCoreMemory(category, epistemicType) {
9331
+ return category === "preference" && epistemicType === "human-stated";
9332
+ }
9333
+ __name(shouldStoreInCoreMemory, "shouldStoreInCoreMemory");
9334
+ async function routeToStorage(item, adapters, config2) {
9335
+ const { category, epistemicType, statement, entities, provenance, confidence } = item;
9336
+ const memKey = `capture:${item.id}`;
9337
+ await entries.remember(memKey, {
9338
+ id: item.id,
9339
+ category,
9340
+ statement,
9341
+ entities,
9342
+ relationships: item.relationships,
9343
+ provenance,
9344
+ confidence,
9345
+ epistemicType,
9346
+ capturedAt: provenance.capturedAt
9347
+ }, {
9348
+ id: item.id,
9349
+ type: category === "preference" ? "preference" : category === "decision" ? "decision" : category === "fact" ? "fact" : "context",
9350
+ confidence: confidence === "high" ? 1 : confidence === "medium" ? 0.7 : 0.4,
9351
+ scope: category === "temporary_context" ? "session" : "local",
9352
+ tags: [category, provenance.epistemicType, provenance.source.conversationId],
9353
+ source: `capture:${provenance.source.conversationId}`
9354
+ });
9355
+ if (shouldStoreInCoreMemory(category, epistemicType)) {
9356
+ try {
9357
+ const anchor2 = await loadPersonalityAnchor();
9358
+ const existingPref = anchor2.identity.durablePreferences.find((p) => p.statement === statement);
9359
+ if (!existingPref) {
9360
+ await updatePersonalityAnchor({
9361
+ durablePreferences: [
9362
+ ...anchor2.identity.durablePreferences,
9363
+ {
9364
+ id: item.id,
9365
+ statement,
9366
+ confidence: epistemicType,
9367
+ evidence: [provenance.source.conversationId],
9368
+ firstObserved: provenance.capturedAt,
9369
+ lastConfirmed: provenance.capturedAt
9370
+ }
9371
+ ]
9372
+ });
9373
+ }
9374
+ } catch {
9375
+ }
9376
+ }
9377
+ if (category === "open_loop" && config2.autoCreateLoops) {
9378
+ try {
9379
+ const existingLoops = await listLoops(true);
9380
+ const alreadyExists = existingLoops.some((l) => l.text === statement);
9381
+ if (!alreadyExists) {
9382
+ await addLoop({
9383
+ id: item.id,
9384
+ text: statement,
9385
+ waitor: "joy",
9386
+ openedAt: provenance.capturedAt
9387
+ });
9388
+ }
9389
+ } catch {
9390
+ }
9391
+ }
9392
+ if (category === "experience" && config2.autoCreateExemplars) {
9393
+ try {
9394
+ await addExemplar({
9395
+ id: item.id,
9396
+ source: {
9397
+ conversationId: provenance.source.conversationId,
9398
+ messageIds: provenance.source.messageIds
9399
+ },
9400
+ pattern: statement,
9401
+ originalContent: statement,
9402
+ sourceReference: `capture:${item.id}`,
9403
+ retrievalHints: [statement, ...entities.map((e) => e.name)],
9404
+ significance: confidence === "high" ? 0.8 : confidence === "medium" ? 0.5 : 0.3,
9405
+ confidence: confidence === "high" ? 1 : confidence === "medium" ? 0.7 : 0.4,
9406
+ provenance: epistemicType,
9407
+ createdAt: provenance.capturedAt
9408
+ });
9409
+ } catch {
9410
+ }
9411
+ }
9412
+ if (config2.autoCreateClaims && (category === "fact" || category === "decision")) {
9413
+ try {
9414
+ await acquire.acquire({
9415
+ id: `claim-${item.id}`,
9416
+ knowledge: { statement, category },
9417
+ applicability: { area: "project" },
9418
+ evidence: [{
9419
+ id: `ev-${item.id}`,
9420
+ source: provenance.source.conversationId,
9421
+ observedAt: provenance.capturedAt,
9422
+ supports: statement
9423
+ }],
9424
+ epistemicType,
9425
+ provenance: { source: "conversation-capture", detail: `category:${category}` },
9426
+ acquiredAt: provenance.capturedAt,
9427
+ scope: "project"
9428
+ });
9429
+ } catch {
9430
+ }
9431
+ }
9432
+ dispatch.set("dotmem:capture:item-captured", {
9433
+ detail: { id: item.id, category, statement }
9434
+ });
9435
+ }
9436
+ __name(routeToStorage, "routeToStorage");
9437
+ var CaptureEngine = class {
9438
+ static {
9439
+ __name(this, "CaptureEngine");
9440
+ }
9441
+ config;
9442
+ adapters;
9443
+ sessionContexts = /* @__PURE__ */ new Map();
9444
+ constructor(config2 = {}, adapters) {
9445
+ this.config = { ...DEFAULT_CONFIG, ...config2 };
9446
+ this.adapters = {
9447
+ remember: entries.remember.bind(entries),
9448
+ recall: entries.recall.bind(entries),
9449
+ update: entries.update.bind(entries),
9450
+ addExemplar: addExemplar.bind(null),
9451
+ updateExemplar: updateExemplar.bind(null),
9452
+ addLoop: addLoop.bind(null),
9453
+ closeLoop: closeLoop.bind(null),
9454
+ updatePersonalityAnchor: updatePersonalityAnchor.bind(null),
9455
+ ...adapters
9456
+ };
9457
+ }
9458
+ /**
9459
+ * Capture information from a conversation turn.
9460
+ * Processes a single message or turn of conversation.
9461
+ */
9462
+ async captureTurn(text, options) {
9463
+ const source = {
9464
+ conversationId: options.conversationId,
9465
+ messageIds: options.messageIds ?? [],
9466
+ timestamp: nowIso(),
9467
+ turnIndex: 0
9468
+ };
9469
+ const instructions = detectExplicitInstructions(text, source);
9470
+ const hasDoNotRemember = instructions.some((i2) => i2.type === "do-not-remember");
9471
+ const hasExplicitRemember = instructions.some((i2) => i2.type === "remember");
9472
+ let created = 0, linked = 0, ignored = 0;
9473
+ if (hasDoNotRemember && !hasExplicitRemember) {
9474
+ const item2 = {
9475
+ id: generateId(),
9476
+ category: "temporary_context",
9477
+ statement: text,
9478
+ content: { text },
9479
+ entities: [],
9480
+ relationships: [],
9481
+ provenance: {
9482
+ source,
9483
+ classification: "temporary_context",
9484
+ confidence: "low",
9485
+ epistemicType: "observed",
9486
+ capturedAt: nowIso(),
9487
+ method: "automatic"
9488
+ },
9489
+ confidence: "low",
9490
+ epistemicType: "observed"
9491
+ };
9492
+ await this.storeSessionContext(options.conversationId, [item2], instructions);
9493
+ ignored++;
9494
+ return { items: [item2], instructions, created: 0, linked: 0, ignored: 1, dedupMatches: [] };
9495
+ }
9496
+ const category = classifyCategory(text, instructions);
9497
+ const epistemicType = determineEpistemicType(category, text, instructions);
9498
+ const confidence = determineConfidence(category, epistemicType);
9499
+ const entities = extractEntities(text);
9500
+ const relationships = extractRelationships(text, entities);
9501
+ const provenance = {
9502
+ source,
9503
+ classification: category,
9504
+ confidence,
9505
+ epistemicType,
9506
+ capturedAt: nowIso(),
9507
+ method: hasExplicitRemember ? "explicit" : "automatic"
9508
+ };
9509
+ const item = {
9510
+ id: generateId(),
9511
+ category,
9512
+ statement: text,
9513
+ content: { text },
9514
+ entities,
9515
+ relationships,
9516
+ provenance,
9517
+ confidence,
9518
+ epistemicType
9519
+ };
9520
+ const sessionCtx = this.sessionContexts.get(options.conversationId);
9521
+ const existingItems = sessionCtx ? sessionCtx.items : [];
9522
+ const dedupMatches = await findExistingSimilarItems(
9523
+ text,
9524
+ category,
9525
+ existingItems,
9526
+ this.config.dedupSimilarityThreshold
9527
+ );
9528
+ const memoryMatches = await findExistingMemoryEntries(text, category);
9529
+ const allMatches = [...dedupMatches, ...memoryMatches];
9530
+ let decision = "create";
9531
+ if (allMatches.length > 0) {
9532
+ const exactMatch = allMatches.find((m) => m.matchType === "exact");
9533
+ if (exactMatch) {
9534
+ decision = "link";
9535
+ linked++;
9536
+ } else {
9537
+ decision = "create";
9538
+ created++;
9539
+ }
9540
+ } else {
9541
+ created++;
9542
+ }
9543
+ const finalItem = { ...item };
9544
+ const shouldStore = decision === "create" || decision === "link";
9545
+ if (shouldStore) {
9546
+ await routeToStorage(finalItem, this.adapters, this.config);
9547
+ }
9548
+ await this.storeSessionContext(options.conversationId, [finalItem], instructions);
9549
+ return { items: [finalItem], instructions, created, linked, ignored, dedupMatches: allMatches };
9550
+ }
9551
+ /**
9552
+ * Capture information from a full conversation (array of messages).
9553
+ * Processes each message and returns aggregated results.
9554
+ */
9555
+ async captureConversation(messages, options) {
9556
+ const allItems = [];
9557
+ const allInstructions = [];
9558
+ let created = 0, updated = 0, linked = 0, ignored = 0;
9559
+ const allDedupMatches = [];
9560
+ for (const [index, msg] of messages.entries()) {
9561
+ const source = {
9562
+ conversationId: options.conversationId,
9563
+ messageIds: [msg.id ?? `msg-${index}`],
9564
+ timestamp: msg.timestamp ?? nowIso(),
9565
+ turnIndex: index
9566
+ };
9567
+ const instructions = detectExplicitInstructions(msg.content, source);
9568
+ allInstructions.push(...instructions);
9569
+ const hasDoNotRemember = instructions.some((i2) => i2.type === "do-not-remember");
9570
+ const hasExplicitRemember = instructions.some((i2) => i2.type === "remember");
9571
+ if (hasDoNotRemember && !hasExplicitRemember) {
9572
+ const item2 = {
9573
+ id: generateId(),
9574
+ category: "temporary_context",
9575
+ statement: msg.content,
9576
+ content: { text: msg.content, role: msg.role },
9577
+ entities: [],
9578
+ relationships: [],
9579
+ provenance: {
9580
+ source,
9581
+ classification: "temporary_context",
9582
+ confidence: "low",
9583
+ epistemicType: "observed",
9584
+ capturedAt: nowIso(),
9585
+ method: "automatic"
9586
+ },
9587
+ confidence: "low",
9588
+ epistemicType: "observed"
9589
+ };
9590
+ allItems.push(item2);
9591
+ ignored++;
9592
+ continue;
9593
+ }
9594
+ const category = classifyCategory(msg.content, instructions);
9595
+ const epistemicType = determineEpistemicType(category, msg.content, instructions);
9596
+ const confidence = determineConfidence(category, epistemicType, msg.content);
9597
+ const entities = extractEntities(msg.content);
9598
+ const relationships = extractRelationships(msg.content, entities);
9599
+ const provenance = {
9600
+ source,
9601
+ classification: category,
9602
+ confidence,
9603
+ epistemicType,
9604
+ capturedAt: nowIso(),
9605
+ method: hasExplicitRemember ? "explicit" : "automatic"
9606
+ };
9607
+ const item = {
9608
+ id: generateId(),
9609
+ category,
9610
+ statement: msg.content,
9611
+ content: { text: msg.content, role: msg.role },
9612
+ entities,
9613
+ relationships,
9614
+ provenance,
9615
+ confidence,
9616
+ epistemicType
9617
+ };
9618
+ const dedupMatches = await findExistingSimilarItems(
9619
+ msg.content,
9620
+ category,
9621
+ allItems,
9622
+ this.config.dedupSimilarityThreshold
9623
+ );
9624
+ const memoryMatches = await findExistingMemoryEntries(msg.content, category);
9625
+ const allMatches = [...dedupMatches, ...memoryMatches];
9626
+ allDedupMatches.push(...allMatches);
9627
+ let decision = "create";
9628
+ if (allMatches.length > 0) {
9629
+ const exactMatch = allMatches.find((m) => m.matchType === "exact");
9630
+ if (exactMatch) {
9631
+ decision = "link";
9632
+ linked++;
9633
+ } else {
9634
+ decision = "create";
9635
+ created++;
9636
+ }
9637
+ } else {
9638
+ created++;
9639
+ }
9640
+ const shouldStore = decision === "create" || decision === "link";
9641
+ if (shouldStore) {
9642
+ await routeToStorage(item, this.adapters, this.config);
9643
+ }
9644
+ if (!shouldStore) ignored++;
9645
+ allItems.push(item);
9646
+ }
9647
+ await this.storeSessionContext(options.conversationId, allItems, allInstructions);
9648
+ return {
9649
+ items: allItems,
9650
+ created,
9651
+ updated,
9652
+ linked,
9653
+ ignored,
9654
+ dedupMatches: allDedupMatches,
9655
+ provenance: allItems.map((i2) => i2.provenance)
9656
+ };
9657
+ }
9658
+ /**
9659
+ * Retrieve captured items for a conversation.
9660
+ */
9661
+ async getCapturedItems(conversationId) {
9662
+ const ctx = this.sessionContexts.get(conversationId);
9663
+ return ctx ? ctx.items : [];
9664
+ }
9665
+ /**
9666
+ * Get all captured items across all conversations.
9667
+ */
9668
+ async getAllCapturedItems() {
9669
+ const all = [];
9670
+ for (const ctx of this.sessionContexts.values()) {
9671
+ all.push(...ctx.items);
9672
+ }
9673
+ return all;
9674
+ }
9675
+ /**
9676
+ * Clear session context (for testing / cleanup).
9677
+ */
9678
+ clearSession(conversationId) {
9679
+ this.sessionContexts.delete(conversationId);
9680
+ }
9681
+ /**
9682
+ * Get capture engine configuration.
9683
+ */
9684
+ getConfig() {
9685
+ return { ...this.config };
9686
+ }
9687
+ // ---------------------------------------------------------------------------
9688
+ // Private
9689
+ // ---------------------------------------------------------------------------
9690
+ async storeSessionContext(conversationId, items, instructions) {
9691
+ let ctx = this.sessionContexts.get(conversationId);
9692
+ if (!ctx) {
9693
+ ctx = {
9694
+ conversationId,
9695
+ startedAt: nowIso(),
9696
+ items: [],
9697
+ explicitInstructions: []
9698
+ };
9699
+ this.sessionContexts.set(conversationId, ctx);
9700
+ }
9701
+ ctx.items.push(...items);
9702
+ ctx.explicitInstructions.push(...instructions);
9703
+ try {
9704
+ const stateKey = `${CAPTURE_STATE_KEY}:${conversationId}`;
9705
+ const existing = store.get(stateKey);
9706
+ let prior = [];
9707
+ if (existing) {
9708
+ try {
9709
+ prior = JSON.parse(existing);
9710
+ } catch {
9711
+ }
9712
+ }
9713
+ store.set(stateKey, JSON.stringify([...prior, ...items]));
9714
+ } catch {
9715
+ }
9716
+ }
9717
+ };
9718
+ var captureEngine = new CaptureEngine();
9719
+ async function captureConversation(messages, options) {
9720
+ return captureEngine.captureConversation(messages, options);
9721
+ }
9722
+ __name(captureConversation, "captureConversation");
9723
+ async function captureTurn(text, options) {
9724
+ return captureEngine.captureTurn(text, options);
9725
+ }
9726
+ __name(captureTurn, "captureTurn");
9727
+
8458
9728
  // core/memory/index.ts
8459
9729
  init_detection_events();
8460
9730
  init_detection_journal();
@@ -8564,7 +9834,7 @@ var memory = {
8564
9834
  */
8565
9835
  async clear() {
8566
9836
  await entries.clearEntries();
8567
- store.remove("__dotmem_acquired_knowledge_state__");
9837
+ store$1.remove("__dotmem_acquired_knowledge_state__");
8568
9838
  await resetKnowledgeRuntimeCaches();
8569
9839
  resetBrainPathCache();
8570
9840
  resetPolicyStoreCache();
@@ -8642,6 +9912,25 @@ var memory = {
8642
9912
  async getSeedId() {
8643
9913
  return SEED_ID;
8644
9914
  }
9915
+ },
9916
+ /** Automatic conversational capture engine (Phase 2 — Workstream B). */
9917
+ capture: {
9918
+ engine: captureEngine,
9919
+ async conversation(messages, options) {
9920
+ return captureConversation(messages, options);
9921
+ },
9922
+ async turn(text, options) {
9923
+ return captureTurn(text, options);
9924
+ },
9925
+ async getItems(conversationId) {
9926
+ return captureEngine.getCapturedItems(conversationId);
9927
+ },
9928
+ async getAllItems() {
9929
+ return captureEngine.getAllCapturedItems();
9930
+ },
9931
+ clearSession(conversationId) {
9932
+ captureEngine.clearSession(conversationId);
9933
+ }
8645
9934
  }
8646
9935
  };
8647
9936