@remnic/core 9.3.580 → 9.3.582

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 (31) hide show
  1. package/dist/access-http.js +2 -2
  2. package/dist/access-mcp.js +1 -1
  3. package/dist/access-schema.d.ts +34 -34
  4. package/dist/{chunk-HLAVGJ62.js → chunk-35NN3ZFA.js} +25 -3
  5. package/dist/chunk-35NN3ZFA.js.map +1 -0
  6. package/dist/{chunk-YR7XMOWK.js → chunk-6GMPIJAZ.js} +2 -2
  7. package/dist/{chunk-WP5OWVLZ.js → chunk-LAL7WBLY.js} +5 -5
  8. package/dist/{chunk-QNXFFUWA.js → chunk-QRWZOCJN.js} +7 -7
  9. package/dist/{chunk-XSQ4SGM5.js → chunk-R3PQUPQ4.js} +2 -2
  10. package/dist/{chunk-5WB4C7KM.js → chunk-ZY6UPHNY.js} +6 -6
  11. package/dist/cli.js +3 -3
  12. package/dist/contradiction/index.js +3 -3
  13. package/dist/{contradiction-review-6V2LXXK6.js → contradiction-review-QKJH5DKD.js} +2 -2
  14. package/dist/{contradiction-scan-GIRVC4C7.js → contradiction-scan-GD7KUFWS.js} +3 -3
  15. package/dist/index.js +6 -6
  16. package/dist/{resolution-ZY7VM6WS.js → resolution-3SAP4SH2.js} +3 -3
  17. package/dist/schemas.d.ts +64 -64
  18. package/dist/shared-context/manager.d.ts +2 -2
  19. package/dist/transfer/types.d.ts +12 -12
  20. package/package.json +1 -1
  21. package/src/contradiction/contradiction-review.ts +33 -2
  22. package/src/contradiction/contradiction.test.ts +28 -3
  23. package/dist/chunk-HLAVGJ62.js.map +0 -1
  24. /package/dist/{chunk-YR7XMOWK.js.map → chunk-6GMPIJAZ.js.map} +0 -0
  25. /package/dist/{chunk-WP5OWVLZ.js.map → chunk-LAL7WBLY.js.map} +0 -0
  26. /package/dist/{chunk-QNXFFUWA.js.map → chunk-QRWZOCJN.js.map} +0 -0
  27. /package/dist/{chunk-XSQ4SGM5.js.map → chunk-R3PQUPQ4.js.map} +0 -0
  28. /package/dist/{chunk-5WB4C7KM.js.map → chunk-ZY6UPHNY.js.map} +0 -0
  29. /package/dist/{contradiction-review-6V2LXXK6.js.map → contradiction-review-QKJH5DKD.js.map} +0 -0
  30. /package/dist/{contradiction-scan-GIRVC4C7.js.map → contradiction-scan-GD7KUFWS.js.map} +0 -0
  31. /package/dist/{resolution-ZY7VM6WS.js.map → resolution-3SAP4SH2.js.map} +0 -0
@@ -313,13 +313,13 @@ declare const CapsuleBlockSchema: z.ZodObject<{
313
313
  peerProfiles: boolean;
314
314
  }>;
315
315
  }, "strip", z.ZodTypeAny, {
316
+ schemaVersion: string;
316
317
  includes: {
317
318
  procedural: boolean;
318
319
  taxonomy: boolean;
319
320
  identityAnchors: boolean;
320
321
  peerProfiles: boolean;
321
322
  };
322
- schemaVersion: string;
323
323
  id: string;
324
324
  description: string;
325
325
  version: string;
@@ -334,13 +334,13 @@ declare const CapsuleBlockSchema: z.ZodObject<{
334
334
  directAnswerEnabled: boolean;
335
335
  };
336
336
  }, {
337
+ schemaVersion: string;
337
338
  includes: {
338
339
  procedural: boolean;
339
340
  taxonomy: boolean;
340
341
  identityAnchors: boolean;
341
342
  peerProfiles: boolean;
342
343
  };
343
- schemaVersion: string;
344
344
  id: string;
345
345
  description: string;
346
346
  version: string;
@@ -464,13 +464,13 @@ declare const ExportManifestV2Schema: z.ZodObject<{
464
464
  peerProfiles: boolean;
465
465
  }>;
466
466
  }, "strip", z.ZodTypeAny, {
467
+ schemaVersion: string;
467
468
  includes: {
468
469
  procedural: boolean;
469
470
  taxonomy: boolean;
470
471
  identityAnchors: boolean;
471
472
  peerProfiles: boolean;
472
473
  };
473
- schemaVersion: string;
474
474
  id: string;
475
475
  description: string;
476
476
  version: string;
@@ -485,13 +485,13 @@ declare const ExportManifestV2Schema: z.ZodObject<{
485
485
  directAnswerEnabled: boolean;
486
486
  };
487
487
  }, {
488
+ schemaVersion: string;
488
489
  includes: {
489
490
  procedural: boolean;
490
491
  taxonomy: boolean;
491
492
  identityAnchors: boolean;
492
493
  peerProfiles: boolean;
493
494
  };
494
- schemaVersion: string;
495
495
  id: string;
496
496
  description: string;
497
497
  version: string;
@@ -518,13 +518,13 @@ declare const ExportManifestV2Schema: z.ZodObject<{
518
518
  pluginVersion: string;
519
519
  includesTranscripts: boolean;
520
520
  capsule: {
521
+ schemaVersion: string;
521
522
  includes: {
522
523
  procedural: boolean;
523
524
  taxonomy: boolean;
524
525
  identityAnchors: boolean;
525
526
  peerProfiles: boolean;
526
527
  };
527
- schemaVersion: string;
528
528
  id: string;
529
529
  description: string;
530
530
  version: string;
@@ -551,13 +551,13 @@ declare const ExportManifestV2Schema: z.ZodObject<{
551
551
  pluginVersion: string;
552
552
  includesTranscripts: boolean;
553
553
  capsule: {
554
+ schemaVersion: string;
554
555
  includes: {
555
556
  procedural: boolean;
556
557
  taxonomy: boolean;
557
558
  identityAnchors: boolean;
558
559
  peerProfiles: boolean;
559
560
  };
560
- schemaVersion: string;
561
561
  id: string;
562
562
  description: string;
563
563
  version: string;
@@ -683,13 +683,13 @@ declare const ExportBundleV2Schema: z.ZodObject<{
683
683
  peerProfiles: boolean;
684
684
  }>;
685
685
  }, "strip", z.ZodTypeAny, {
686
+ schemaVersion: string;
686
687
  includes: {
687
688
  procedural: boolean;
688
689
  taxonomy: boolean;
689
690
  identityAnchors: boolean;
690
691
  peerProfiles: boolean;
691
692
  };
692
- schemaVersion: string;
693
693
  id: string;
694
694
  description: string;
695
695
  version: string;
@@ -704,13 +704,13 @@ declare const ExportBundleV2Schema: z.ZodObject<{
704
704
  directAnswerEnabled: boolean;
705
705
  };
706
706
  }, {
707
+ schemaVersion: string;
707
708
  includes: {
708
709
  procedural: boolean;
709
710
  taxonomy: boolean;
710
711
  identityAnchors: boolean;
711
712
  peerProfiles: boolean;
712
713
  };
713
- schemaVersion: string;
714
714
  id: string;
715
715
  description: string;
716
716
  version: string;
@@ -737,13 +737,13 @@ declare const ExportBundleV2Schema: z.ZodObject<{
737
737
  pluginVersion: string;
738
738
  includesTranscripts: boolean;
739
739
  capsule: {
740
+ schemaVersion: string;
740
741
  includes: {
741
742
  procedural: boolean;
742
743
  taxonomy: boolean;
743
744
  identityAnchors: boolean;
744
745
  peerProfiles: boolean;
745
746
  };
746
- schemaVersion: string;
747
747
  id: string;
748
748
  description: string;
749
749
  version: string;
@@ -770,13 +770,13 @@ declare const ExportBundleV2Schema: z.ZodObject<{
770
770
  pluginVersion: string;
771
771
  includesTranscripts: boolean;
772
772
  capsule: {
773
+ schemaVersion: string;
773
774
  includes: {
774
775
  procedural: boolean;
775
776
  taxonomy: boolean;
776
777
  identityAnchors: boolean;
777
778
  peerProfiles: boolean;
778
779
  };
779
- schemaVersion: string;
780
780
  id: string;
781
781
  description: string;
782
782
  version: string;
@@ -815,13 +815,13 @@ declare const ExportBundleV2Schema: z.ZodObject<{
815
815
  pluginVersion: string;
816
816
  includesTranscripts: boolean;
817
817
  capsule: {
818
+ schemaVersion: string;
818
819
  includes: {
819
820
  procedural: boolean;
820
821
  taxonomy: boolean;
821
822
  identityAnchors: boolean;
822
823
  peerProfiles: boolean;
823
824
  };
824
- schemaVersion: string;
825
825
  id: string;
826
826
  description: string;
827
827
  version: string;
@@ -854,13 +854,13 @@ declare const ExportBundleV2Schema: z.ZodObject<{
854
854
  pluginVersion: string;
855
855
  includesTranscripts: boolean;
856
856
  capsule: {
857
+ schemaVersion: string;
857
858
  includes: {
858
859
  procedural: boolean;
859
860
  taxonomy: boolean;
860
861
  identityAnchors: boolean;
861
862
  peerProfiles: boolean;
862
863
  };
863
- schemaVersion: string;
864
864
  id: string;
865
865
  description: string;
866
866
  version: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remnic/core",
3
- "version": "9.3.580",
3
+ "version": "9.3.582",
4
4
  "description": "Framework-agnostic Remnic memory engine — orchestrator, storage, extraction, search, trust zones",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -135,6 +135,30 @@ function isDeferralActive(pair: ContradictionPair): boolean {
135
135
  return deferredUntil !== null && Date.now() < deferredUntil;
136
136
  }
137
137
 
138
+ function isReviewActionable(pair: ContradictionPair): boolean {
139
+ return !isTerminalResolution(pair.resolution)
140
+ && !isDeferralActive(pair)
141
+ && pair.resolution !== "both-valid"
142
+ && pair.verdict !== "independent";
143
+ }
144
+
145
+ function compareReviewPairs(a: ContradictionPair, b: ContradictionPair): number {
146
+ const aActionable = isReviewActionable(a);
147
+ const bActionable = isReviewActionable(b);
148
+ if (aActionable !== bActionable) return aActionable ? -1 : 1;
149
+
150
+ const aDetectedAt = parseIsoMillis(a.detectedAt) ?? Number.POSITIVE_INFINITY;
151
+ const bDetectedAt = parseIsoMillis(b.detectedAt) ?? Number.POSITIVE_INFINITY;
152
+ if (aDetectedAt !== bDetectedAt) return aDetectedAt < bDetectedAt ? -1 : 1;
153
+
154
+ const aPairId = typeof a.pairId === "string" ? a.pairId : "";
155
+ const bPairId = typeof b.pairId === "string" ? b.pairId : "";
156
+ const pairIdOrder = aPairId.localeCompare(bPairId);
157
+ if (pairIdOrder !== 0) return pairIdOrder;
158
+
159
+ return a.memoryIds.join("\0").localeCompare(b.memoryIds.join("\0"));
160
+ }
161
+
138
162
  function reviewStateMillis(pair: ContradictionPair): number {
139
163
  return Math.max(
140
164
  parseIsoMillis(pair.deferredUntil) ?? Number.NEGATIVE_INFINITY,
@@ -390,7 +414,7 @@ export function listPairs(
390
414
  const startTime = Date.now();
391
415
  const dir = reviewDir(memoryDir);
392
416
  const { filter = "all", namespace, includeUnscopedForNamespace = false, limit = 50 } = options ?? {};
393
- const pairs: ContradictionPair[] = [];
417
+ const matchingPairs: ContradictionPair[] = [];
394
418
  let total = 0;
395
419
 
396
420
  if (!fs.existsSync(dir)) {
@@ -423,12 +447,19 @@ export function listPairs(
423
447
  }
424
448
 
425
449
  total++;
426
- if (pairs.length < limit) pairs.push(pair);
450
+ matchingPairs.push(pair);
427
451
  } catch {
428
452
  continue;
429
453
  }
430
454
  }
431
455
 
456
+ matchingPairs.sort(compareReviewPairs);
457
+ const pairs: ContradictionPair[] = [];
458
+ for (const pair of matchingPairs) {
459
+ if (!(pairs.length < limit)) break;
460
+ pairs.push(pair);
461
+ }
462
+
432
463
  return { pairs, total, durationMs: Date.now() - startTime };
433
464
  }
434
465
 
@@ -545,12 +545,37 @@ test("listPairs filters by verdict", async () => {
545
545
  test("listPairs respects limit", async () => {
546
546
  const { dir, cleanup } = await makeTempDir();
547
547
  try {
548
- for (let i = 0; i < 5; i++) {
549
- writePair(dir, makePair({ memoryIds: [`a-${i}`, `b-${i}`] }));
550
- }
548
+ const expectedFirst = writePair(dir, makePair({
549
+ memoryIds: ["a-first", "b-first"],
550
+ detectedAt: "2026-01-01T00:00:00.000Z",
551
+ }));
552
+ const expectedSecond = writePair(dir, makePair({
553
+ memoryIds: ["a-second", "b-second"],
554
+ detectedAt: "2026-01-02T00:00:00.000Z",
555
+ }));
556
+ const terminal = writePair(dir, makePair({
557
+ memoryIds: ["a-terminal", "b-terminal"],
558
+ detectedAt: "2025-01-01T00:00:00.000Z",
559
+ }));
560
+ resolvePair(dir, terminal.pairId, "keep-a");
561
+ writePair(dir, makePair({
562
+ memoryIds: ["a-independent", "b-independent"],
563
+ detectedAt: "2025-01-02T00:00:00.000Z",
564
+ verdict: "independent",
565
+ }));
566
+ writePair(dir, makePair({
567
+ memoryIds: ["a-third", "b-third"],
568
+ detectedAt: "2026-01-03T00:00:00.000Z",
569
+ }));
570
+
551
571
  const result = listPairs(dir, { filter: "all", limit: 2 });
552
572
  assert.equal(result.pairs.length, 2);
553
573
  assert.equal(result.total, 5, "total should reflect all matching pairs, not just returned");
574
+ assert.deepEqual(
575
+ result.pairs.map((pair) => pair.pairId),
576
+ [expectedFirst.pairId, expectedSecond.pairId],
577
+ "limit should apply after deterministic review ordering, not raw directory order",
578
+ );
554
579
  } finally {
555
580
  await cleanup();
556
581
  }
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/contradiction/contradiction-review.ts"],"sourcesContent":["/**\n * Contradiction Review Queue — storage for detected contradiction pairs (issue #520).\n *\n * Stores candidate pairs as JSON files under `memoryDir/.review/contradictions/`.\n * Pair IDs are deterministic (sha256 of sorted memory IDs plus namespace when scoped) so reruns are idempotent.\n *\n * Lifecycle:\n * - `contradicts` → awaiting user review\n * - `duplicates` → auto-flagged for dedup (still needs user approval)\n * - `independent` / `both-valid` → dormant with cooldown\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { createHash, randomUUID } from \"node:crypto\";\nimport type { ContradictionVerdict } from \"./contradiction-judge.js\";\n\n// ── Types ──────────────────────────────────────────────────────────────────────\n\nexport type ResolutionVerb = \"keep-a\" | \"keep-b\" | \"merge\" | \"both-valid\" | \"needs-more-context\";\n\nconst VALID_RESOLUTION_VERBS: readonly ResolutionVerb[] = [\n \"keep-a\",\n \"keep-b\",\n \"merge\",\n \"both-valid\",\n \"needs-more-context\",\n];\n\nexport interface ContradictionPair {\n /** Deterministic pair ID: sha256(sorted(memoryIdA, memoryIdB) plus namespace when scoped). */\n pairId: string;\n /** Memory IDs (sorted). */\n memoryIds: [string, string];\n /** Judge verdict. */\n verdict: ContradictionVerdict;\n /** Judge rationale. */\n rationale: string;\n /** Judge confidence in [0, 1]. */\n confidence: number;\n /** ISO timestamp when detected. */\n detectedAt: string;\n /** ISO timestamp when last reviewed by user. */\n lastReviewedAt?: string;\n /** Resolution verb applied by user. */\n resolution?: ResolutionVerb;\n /** ISO timestamp until which a non-terminal deferral remains hidden from review. */\n deferredUntil?: string;\n /** Content hashes captured for each referenced memory when this pair was judged. */\n memoryContentHashes?: Record<string, string>;\n /** Namespace scope. */\n namespace?: string;\n}\n\nexport interface ContradictionListResult {\n pairs: ContradictionPair[];\n total: number;\n durationMs: number;\n}\n\nexport type ContradictionFilter = ContradictionVerdict | \"all\" | \"unresolved\";\nexport interface WritePairOptions {\n /** Cooldown used by scan callers to preserve still-dormant reviewed pairs. */\n cooldownDays?: number;\n}\nconst NEEDS_MORE_CONTEXT_COOLDOWN_MS = 24 * 60 * 60 * 1000;\nconst UNSCOPED_MIGRATION_MARKER_PREFIX = \".unscoped-migrated-\";\nconst UNSCOPED_MIGRATION_MARKER_SUFFIX = \".done\";\n\n// ── Helpers ────────────────────────────────────────────────────────────────────\n\nexport function computePairId(memoryIdA: string, memoryIdB: string, namespace?: string): string {\n const sorted = [memoryIdA, memoryIdB].sort();\n const normalizedNamespace = namespace?.trim();\n const scope = normalizedNamespace ? `ns:${normalizedNamespace}::` : \"\";\n return createHash(\"sha256\").update(`${scope}${sorted.join(\"::\")}`).digest(\"hex\").slice(0, 24);\n}\n\nexport function isDefaultReviewNamespace(\n defaultNamespace: string,\n requestedNamespace: string | undefined,\n resolvedNamespace: string,\n): boolean {\n const requested = requestedNamespace?.trim();\n return !requested || requested === defaultNamespace || resolvedNamespace === defaultNamespace;\n}\n\nfunction isTerminalResolution(resolution: ResolutionVerb | undefined): boolean {\n return resolution === \"keep-a\" || resolution === \"keep-b\" || resolution === \"merge\";\n}\n\nfunction preservesDirectResolution(resolution: ResolutionVerb | undefined): boolean {\n return isTerminalResolution(resolution) || resolution === \"both-valid\";\n}\n\nfunction isDormantReviewedPair(pair: ContradictionPair): boolean {\n return pair.verdict === \"independent\" || pair.resolution === \"both-valid\";\n}\n\nfunction reviewStateRank(pair: ContradictionPair, cooldownDays?: number): number {\n if (isTerminalResolution(pair.resolution)) return 5;\n if (pair.resolution === \"both-valid\") return 4;\n if (isDeferralActive(pair)) return 3;\n if (isDormantReviewedPair(pair)) {\n if (cooldownDays === undefined) return 2;\n return isCoolingDown(pair, cooldownDays) ? 2 : 0;\n }\n return 1;\n}\n\nfunction parseIsoMillis(value: string | undefined): number | null {\n if (!value) return null;\n const millis = new Date(value).getTime();\n return Number.isFinite(millis) ? millis : null;\n}\n\nfunction isDeferred(pair: Pick<ContradictionPair, \"resolution\" | \"deferredUntil\">): boolean {\n return pair.resolution === \"needs-more-context\" || Boolean(pair.deferredUntil);\n}\n\nfunction deferralUntilMillis(pair: ContradictionPair): number | null {\n const deferredUntil = parseIsoMillis(pair.deferredUntil);\n if (deferredUntil !== null) return deferredUntil;\n\n if (pair.resolution === \"needs-more-context\") {\n const lastReviewed = parseIsoMillis(pair.lastReviewedAt);\n return lastReviewed === null ? null : lastReviewed + NEEDS_MORE_CONTEXT_COOLDOWN_MS;\n }\n\n return null;\n}\n\nfunction isDeferralActive(pair: ContradictionPair): boolean {\n const deferredUntil = deferralUntilMillis(pair);\n return deferredUntil !== null && Date.now() < deferredUntil;\n}\n\nfunction reviewStateMillis(pair: ContradictionPair): number {\n return Math.max(\n parseIsoMillis(pair.deferredUntil) ?? Number.NEGATIVE_INFINITY,\n parseIsoMillis(pair.lastReviewedAt) ?? Number.NEGATIVE_INFINITY,\n parseIsoMillis(pair.detectedAt) ?? Number.NEGATIVE_INFINITY,\n );\n}\n\nfunction mergeMigratedPair(existing: ContradictionPair, migrated: ContradictionPair, options: WritePairOptions): ContradictionPair {\n const existingRank = reviewStateRank(existing, options.cooldownDays);\n const migratedRank = reviewStateRank(migrated, options.cooldownDays);\n const selected = migratedRank > existingRank\n ? migrated\n : migratedRank < existingRank\n ? existing\n : reviewStateMillis(migrated) > reviewStateMillis(existing)\n ? migrated\n : existing;\n\n return {\n ...selected,\n pairId: migrated.pairId,\n namespace: migrated.namespace,\n };\n}\n\nfunction reviewDir(memoryDir: string): string {\n return path.join(memoryDir, \".review\", \"contradictions\");\n}\n\nfunction migrationMarkerPath(memoryDir: string, namespace: string): string {\n const namespaceKey = createHash(\"sha256\").update(namespace).digest(\"hex\").slice(0, 16);\n return path.join(reviewDir(memoryDir), `${UNSCOPED_MIGRATION_MARKER_PREFIX}${namespaceKey}${UNSCOPED_MIGRATION_MARKER_SUFFIX}`);\n}\n\nfunction clearUnscopedMigrationMarkers(memoryDir: string): void {\n const dir = reviewDir(memoryDir);\n if (!fs.existsSync(dir)) return;\n\n try {\n for (const entry of fs.readdirSync(dir)) {\n if (entry.startsWith(UNSCOPED_MIGRATION_MARKER_PREFIX) && entry.endsWith(UNSCOPED_MIGRATION_MARKER_SUFFIX)) {\n fs.rmSync(path.join(dir, entry), { force: true });\n }\n }\n } catch {\n // Marker cleanup is best-effort. The next migration/list call can recover.\n }\n}\n\nfunction pairPath(memoryDir: string, pairId: string): string {\n if (pairId.includes(\"/\") || pairId.includes(\"\\\\\") || pairId.includes(\"..\")) {\n throw new Error(`Invalid pairId: ${pairId}`);\n }\n return path.join(reviewDir(memoryDir), `${pairId}.json`);\n}\n\nfunction isSafeReviewJsonFile(memoryDir: string, filePath: string): boolean {\n const root = path.resolve(reviewDir(memoryDir));\n const resolved = path.resolve(filePath);\n const relative = path.relative(root, resolved);\n if (relative === \"\" || relative.startsWith(\"..\") || path.isAbsolute(relative)) {\n return false;\n }\n\n try {\n return fs.lstatSync(resolved).isFile();\n } catch {\n return false;\n }\n}\n\nfunction ensureDir(memoryDir: string): void {\n const dir = reviewDir(memoryDir);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n}\n\nfunction uniqueTempPath(filePath: string): string {\n return `${filePath}.${process.pid}.${Date.now()}.${randomUUID()}.tmp`;\n}\n\nfunction writePairFile(filePath: string, pair: ContradictionPair): void {\n const tmpPath = uniqueTempPath(filePath);\n try {\n fs.writeFileSync(tmpPath, JSON.stringify(pair, null, 2), \"utf-8\");\n fs.renameSync(tmpPath, filePath);\n } catch (error) {\n try {\n fs.rmSync(tmpPath, { force: true });\n } catch {\n // Best-effort cleanup only; preserve the original write failure.\n }\n throw error;\n }\n}\n\nexport function computeMemoryContentHash(content: string, category?: string): string {\n const normalized = JSON.stringify({\n content: content.trim(),\n category: (category ?? \"\").trim(),\n });\n return createHash(\"sha256\").update(normalized).digest(\"hex\").slice(0, 16);\n}\n\nfunction suppliedMemoryHashesChanged(\n existing: ContradictionPair,\n pair: Omit<ContradictionPair, \"pairId\"> & { memoryIds: [string, string] },\n): boolean {\n if (!existing.memoryContentHashes || !pair.memoryContentHashes) return false;\n return pair.memoryIds.some((memoryId) => {\n const current = pair.memoryContentHashes?.[memoryId];\n return typeof current === \"string\" && existing.memoryContentHashes?.[memoryId] !== current;\n });\n}\n\n// ── Write ──────────────────────────────────────────────────────────────────────\n\n/**\n * Write a contradiction pair to the review queue.\n * Idempotent: if the pair already exists with a higher or equal confidence,\n * the existing entry is preserved.\n */\nexport function writePair(\n memoryDir: string,\n pair: Omit<ContradictionPair, \"pairId\"> & { memoryIds: [string, string] },\n options: WritePairOptions = {},\n): ContradictionPair {\n ensureDir(memoryDir);\n if (pair.namespace === undefined) {\n clearUnscopedMigrationMarkers(memoryDir);\n }\n const pairId = computePairId(pair.memoryIds[0], pair.memoryIds[1], pair.namespace);\n const existing = readPair(memoryDir, pairId);\n\n // Preserve terminal user resolutions if already reviewed.\n if (isTerminalResolution(existing?.resolution)) {\n return existing!;\n }\n const contentChanged = Boolean(existing && suppliedMemoryHashesChanged(existing, pair));\n if (existing?.resolution === \"both-valid\" && options.cooldownDays === undefined && !contentChanged) {\n return existing;\n }\n\n // Preserve active deferrals, but allow expired deferrals to be refreshed.\n const existingDeferralExpired = Boolean(existing && isDeferred(existing) && !isDeferralActive(existing));\n if (existing && isDeferralActive(existing) && !contentChanged) {\n return existing;\n }\n\n // Preserve same-verdict or still-cooling entries, but let expired dormant\n // verdicts refresh when the judge now finds an actionable conflict.\n const existingDormantCooldownActive = Boolean(\n existing\n && isDormantReviewedPair(existing)\n && options.cooldownDays !== undefined\n && isCoolingDown(existing, options.cooldownDays),\n );\n const dormantContentChanged = Boolean(\n existing\n && existingDormantCooldownActive\n && contentChanged,\n );\n const existingDormantExpired = Boolean(\n existing\n && isDormantReviewedPair(existing)\n && options.cooldownDays !== undefined\n && !existingDormantCooldownActive,\n );\n if (\n existing\n && !existingDeferralExpired\n && (\n (existingDormantCooldownActive && !dormantContentChanged)\n || (!existingDormantExpired && !contentChanged && existing.confidence >= pair.confidence)\n )\n ) {\n return existing;\n }\n\n const full: ContradictionPair = {\n ...pair,\n pairId,\n lastReviewedAt: (existingDeferralExpired || existingDormantExpired || contentChanged)\n ? pair.lastReviewedAt\n : (existing?.lastReviewedAt ?? pair.lastReviewedAt),\n resolution: undefined,\n deferredUntil: (existingDeferralExpired || existingDormantExpired || contentChanged)\n ? undefined\n : existing?.deferredUntil,\n };\n\n const filePath = pairPath(memoryDir, pairId);\n writePairFile(filePath, full);\n\n return full;\n}\n\n/**\n * Write multiple pairs, deduplicating inputs first (rule 49).\n */\nexport function writePairs(\n memoryDir: string,\n pairs: Array<Omit<ContradictionPair, \"pairId\"> & { memoryIds: [string, string] }>,\n options: WritePairOptions = {},\n): ContradictionPair[] {\n const seen = new Set<string>();\n const results: ContradictionPair[] = [];\n\n for (const pair of pairs) {\n const key = computePairId(pair.memoryIds[0], pair.memoryIds[1], pair.namespace);\n if (seen.has(key)) continue;\n seen.add(key);\n results.push(writePair(memoryDir, pair, options));\n }\n\n return results;\n}\n\n// ── Read ───────────────────────────────────────────────────────────────────────\n\n/**\n * Read a single pair by ID. Returns null if not found.\n */\nexport function readPair(memoryDir: string, pairId: string): ContradictionPair | null {\n const filePath = pairPath(memoryDir, pairId);\n try {\n if (!isSafeReviewJsonFile(memoryDir, filePath)) return null;\n const raw = fs.readFileSync(filePath, \"utf-8\");\n const parsed = JSON.parse(raw);\n if (typeof parsed === \"object\" && parsed !== null && Array.isArray(parsed.memoryIds)) {\n return parsed as ContradictionPair;\n }\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * List pairs in the review queue, optionally filtered by verdict.\n */\nexport function listPairs(\n memoryDir: string,\n options?: {\n filter?: ContradictionFilter;\n namespace?: string;\n includeUnscopedForNamespace?: boolean;\n limit?: number;\n },\n): ContradictionListResult {\n const startTime = Date.now();\n const dir = reviewDir(memoryDir);\n const { filter = \"all\", namespace, includeUnscopedForNamespace = false, limit = 50 } = options ?? {};\n const pairs: ContradictionPair[] = [];\n let total = 0;\n\n if (!fs.existsSync(dir)) {\n return { pairs: [], total: 0, durationMs: Date.now() - startTime };\n }\n\n for (const entry of fs.readdirSync(dir)) {\n if (!entry.endsWith(\".json\")) continue;\n\n try {\n const filePath = path.join(dir, entry);\n if (!isSafeReviewJsonFile(memoryDir, filePath)) continue;\n const raw = fs.readFileSync(filePath, \"utf-8\");\n const pair = JSON.parse(raw) as ContradictionPair;\n\n if (typeof pair !== \"object\" || pair === null) continue;\n if (!Array.isArray(pair.memoryIds)) continue;\n\n // Namespace filter\n if (namespace && pair.namespace !== namespace && !(includeUnscopedForNamespace && pair.namespace === undefined)) continue;\n\n // Verdict filter\n if (filter === \"unresolved\") {\n if (isTerminalResolution(pair.resolution)) continue;\n if (isDeferralActive(pair)) continue;\n if (pair.resolution === \"both-valid\") continue;\n if (pair.verdict === \"independent\") continue;\n } else if (filter !== \"all\" && pair.verdict !== filter) {\n continue;\n }\n\n total++;\n if (pairs.length < limit) pairs.push(pair);\n } catch {\n continue;\n }\n }\n\n return { pairs, total, durationMs: Date.now() - startTime };\n}\n\nexport function migrateUnscopedPairsToNamespace(memoryDir: string, namespace: string, options: WritePairOptions = {}): number {\n const resolvedNamespace = namespace.trim();\n if (!resolvedNamespace) return 0;\n\n const dir = reviewDir(memoryDir);\n if (!fs.existsSync(dir)) return 0;\n const markerPath = migrationMarkerPath(memoryDir, resolvedNamespace);\n if (fs.existsSync(markerPath)) return 0;\n\n let migrated = 0;\n let hadMigrationFailure = false;\n for (const entry of fs.readdirSync(dir)) {\n if (!entry.endsWith(\".json\")) continue;\n const filePath = path.join(dir, entry);\n\n try {\n if (!isSafeReviewJsonFile(memoryDir, filePath)) continue;\n const raw = fs.readFileSync(filePath, \"utf-8\");\n const pair = JSON.parse(raw) as ContradictionPair;\n if (typeof pair !== \"object\" || pair === null) continue;\n if (!Array.isArray(pair.memoryIds)) continue;\n if (pair.namespace !== undefined) continue;\n\n const pairId = computePairId(pair.memoryIds[0], pair.memoryIds[1], resolvedNamespace);\n const migratedPair = { ...pair, namespace: resolvedNamespace, pairId };\n const targetPath = pairPath(memoryDir, pairId);\n try {\n if (targetPath === filePath) {\n writePairFile(filePath, migratedPair);\n } else if (!fs.existsSync(targetPath)) {\n writePairFile(targetPath, migratedPair);\n fs.rmSync(filePath, { force: true });\n } else {\n if (!isSafeReviewJsonFile(memoryDir, targetPath)) {\n hadMigrationFailure = true;\n continue;\n }\n const existing = readPair(memoryDir, pairId);\n writePairFile(targetPath, existing ? mergeMigratedPair(existing, migratedPair, options) : migratedPair);\n fs.rmSync(filePath, { force: true });\n }\n migrated += 1;\n } catch {\n hadMigrationFailure = true;\n continue;\n }\n } catch {\n continue;\n }\n }\n\n if (!hadMigrationFailure) {\n try {\n fs.writeFileSync(markerPath, `${new Date().toISOString()}\\n`, { encoding: \"utf-8\", flag: \"wx\" });\n } catch {\n // Another caller may have completed the same one-shot migration first.\n }\n }\n\n return migrated;\n}\n\n// ── Cooldown ───────────────────────────────────────────────────────────────────\n\n/**\n * Check if a pair is within its cooldown window.\n * Returns true if the pair should be SKIPPED (still cooling down).\n */\nexport function isCoolingDown(pair: ContradictionPair, cooldownDays: number): boolean {\n if (cooldownDays <= 0) return false; // rule 27: guard against 0\n\n const deferredUntil = deferralUntilMillis(pair);\n if (deferredUntil !== null) {\n return Date.now() < deferredUntil;\n }\n\n if (!pair.lastReviewedAt) return false;\n\n const lastReviewed = parseIsoMillis(pair.lastReviewedAt);\n if (lastReviewed === null) return false;\n\n const cooldownMs = cooldownDays * 24 * 60 * 60 * 1000;\n return Date.now() < lastReviewed + cooldownMs;\n}\n\n/**\n * Mark a pair as reviewed (sets lastReviewedAt and, for terminal verbs, resolution).\n */\nexport function resolvePair(\n memoryDir: string,\n pairId: string,\n verb: ResolutionVerb,\n): ContradictionPair | null {\n if (typeof verb !== \"string\" || !VALID_RESOLUTION_VERBS.includes(verb)) {\n throw new Error(`Invalid contradiction resolution verb: ${String(verb)}`);\n }\n\n if (verb === \"needs-more-context\") {\n return deferPair(memoryDir, pairId);\n }\n\n const existing = readPair(memoryDir, pairId);\n if (!existing) return null;\n if (preservesDirectResolution(existing.resolution)) return existing;\n\n const updated: ContradictionPair = {\n ...existing,\n lastReviewedAt: new Date().toISOString(),\n resolution: verb,\n deferredUntil: undefined,\n };\n\n const filePath = pairPath(memoryDir, pairId);\n writePairFile(filePath, updated);\n\n return updated;\n}\n\n/**\n * Defer a pair without terminally resolving it.\n */\nexport function deferPair(\n memoryDir: string,\n pairId: string,\n deferredUntil = new Date(Date.now() + NEEDS_MORE_CONTEXT_COOLDOWN_MS).toISOString(),\n): ContradictionPair | null {\n const existing = readPair(memoryDir, pairId);\n if (!existing) return null;\n if (preservesDirectResolution(existing.resolution)) return existing;\n\n const updated: ContradictionPair = {\n ...existing,\n lastReviewedAt: new Date().toISOString(),\n resolution: undefined,\n deferredUntil,\n };\n\n const filePath = pairPath(memoryDir, pairId);\n writePairFile(filePath, updated);\n\n return updated;\n}\n\n/**\n * Check whether a pair's referenced memories have changed since detection,\n * which should override cooldown.\n */\nexport function memoryHashesChanged(\n _memoryDir: string,\n pair: ContradictionPair,\n getCurrentHash: (memoryId: string) => string | null,\n): boolean {\n if (!pair.memoryContentHashes) return false;\n\n for (const memoryId of pair.memoryIds) {\n const previousHash = pair.memoryContentHashes[memoryId];\n if (typeof previousHash !== \"string\") continue;\n\n const currentHash = getCurrentHash(memoryId);\n if (currentHash !== null && currentHash !== previousHash) return true;\n }\n\n return false;\n}\n"],"mappings":"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","names":[]}