instar 0.28.83 → 0.28.85

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 (114) hide show
  1. package/dashboard/index.html +239 -0
  2. package/dist/cli.js +10 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/intent.d.ts.map +1 -1
  5. package/dist/commands/intent.js +29 -2
  6. package/dist/commands/intent.js.map +1 -1
  7. package/dist/commands/memoryBackfillEvidence.d.ts +69 -0
  8. package/dist/commands/memoryBackfillEvidence.d.ts.map +1 -0
  9. package/dist/commands/memoryBackfillEvidence.js +220 -0
  10. package/dist/commands/memoryBackfillEvidence.js.map +1 -0
  11. package/dist/commands/server.d.ts.map +1 -1
  12. package/dist/commands/server.js +86 -1
  13. package/dist/commands/server.js.map +1 -1
  14. package/dist/core/DecisionJournal.d.ts +66 -3
  15. package/dist/core/DecisionJournal.d.ts.map +1 -1
  16. package/dist/core/DecisionJournal.js +116 -3
  17. package/dist/core/DecisionJournal.js.map +1 -1
  18. package/dist/core/DispatchExecutor.d.ts +74 -1
  19. package/dist/core/DispatchExecutor.d.ts.map +1 -1
  20. package/dist/core/DispatchExecutor.js +120 -1
  21. package/dist/core/DispatchExecutor.js.map +1 -1
  22. package/dist/core/EvolutionManager.d.ts +133 -0
  23. package/dist/core/EvolutionManager.d.ts.map +1 -1
  24. package/dist/core/EvolutionManager.js +494 -0
  25. package/dist/core/EvolutionManager.js.map +1 -1
  26. package/dist/core/InitiativeTracker.d.ts +82 -15
  27. package/dist/core/InitiativeTracker.d.ts.map +1 -1
  28. package/dist/core/InitiativeTracker.js +502 -31
  29. package/dist/core/InitiativeTracker.js.map +1 -1
  30. package/dist/core/LearnSkillBridge.d.ts +119 -0
  31. package/dist/core/LearnSkillBridge.d.ts.map +1 -0
  32. package/dist/core/LearnSkillBridge.js +160 -0
  33. package/dist/core/LearnSkillBridge.js.map +1 -0
  34. package/dist/core/SharedStateLedger.d.ts.map +1 -1
  35. package/dist/core/SharedStateLedger.js +4 -0
  36. package/dist/core/SharedStateLedger.js.map +1 -1
  37. package/dist/core/types.d.ts +124 -1
  38. package/dist/core/types.d.ts.map +1 -1
  39. package/dist/core/types.js +8 -0
  40. package/dist/core/types.js.map +1 -1
  41. package/dist/memory/EvidenceRenderer.d.ts +64 -0
  42. package/dist/memory/EvidenceRenderer.d.ts.map +1 -0
  43. package/dist/memory/EvidenceRenderer.js +119 -0
  44. package/dist/memory/EvidenceRenderer.js.map +1 -0
  45. package/dist/memory/SemanticMemory.d.ts +61 -1
  46. package/dist/memory/SemanticMemory.d.ts.map +1 -1
  47. package/dist/memory/SemanticMemory.js +381 -11
  48. package/dist/memory/SemanticMemory.js.map +1 -1
  49. package/dist/server/AgentServer.d.ts +4 -0
  50. package/dist/server/AgentServer.d.ts.map +1 -1
  51. package/dist/server/AgentServer.js +2 -0
  52. package/dist/server/AgentServer.js.map +1 -1
  53. package/dist/server/routes.d.ts +8 -0
  54. package/dist/server/routes.d.ts.map +1 -1
  55. package/dist/server/routes.js +500 -14
  56. package/dist/server/routes.js.map +1 -1
  57. package/dist/tasks/DivergenceChecker.d.ts +89 -0
  58. package/dist/tasks/DivergenceChecker.d.ts.map +1 -0
  59. package/dist/tasks/DivergenceChecker.js +255 -0
  60. package/dist/tasks/DivergenceChecker.js.map +1 -0
  61. package/dist/tasks/LruCache.d.ts +33 -0
  62. package/dist/tasks/LruCache.d.ts.map +1 -0
  63. package/dist/tasks/LruCache.js +88 -0
  64. package/dist/tasks/LruCache.js.map +1 -0
  65. package/dist/tasks/RateLimiter.d.ts +61 -0
  66. package/dist/tasks/RateLimiter.d.ts.map +1 -0
  67. package/dist/tasks/RateLimiter.js +108 -0
  68. package/dist/tasks/RateLimiter.js.map +1 -0
  69. package/dist/tasks/TaskFlowDueWaker.d.ts +29 -0
  70. package/dist/tasks/TaskFlowDueWaker.d.ts.map +1 -0
  71. package/dist/tasks/TaskFlowDueWaker.js +73 -0
  72. package/dist/tasks/TaskFlowDueWaker.js.map +1 -0
  73. package/dist/tasks/TaskFlowMaintenanceSweeper.d.ts +40 -0
  74. package/dist/tasks/TaskFlowMaintenanceSweeper.d.ts.map +1 -0
  75. package/dist/tasks/TaskFlowMaintenanceSweeper.js +131 -0
  76. package/dist/tasks/TaskFlowMaintenanceSweeper.js.map +1 -0
  77. package/dist/tasks/TaskFlowRegistry.d.ts +180 -0
  78. package/dist/tasks/TaskFlowRegistry.d.ts.map +1 -0
  79. package/dist/tasks/TaskFlowRegistry.js +791 -0
  80. package/dist/tasks/TaskFlowRegistry.js.map +1 -0
  81. package/dist/tasks/ThreadlineFlowBridge.d.ts +54 -0
  82. package/dist/tasks/ThreadlineFlowBridge.d.ts.map +1 -0
  83. package/dist/tasks/ThreadlineFlowBridge.js +129 -0
  84. package/dist/tasks/ThreadlineFlowBridge.js.map +1 -0
  85. package/dist/tasks/task-flow-registry.store.sqlite.d.ts +77 -0
  86. package/dist/tasks/task-flow-registry.store.sqlite.d.ts.map +1 -0
  87. package/dist/tasks/task-flow-registry.store.sqlite.js +350 -0
  88. package/dist/tasks/task-flow-registry.store.sqlite.js.map +1 -0
  89. package/dist/tasks/task-flow-types.d.ts +229 -0
  90. package/dist/tasks/task-flow-types.d.ts.map +1 -0
  91. package/dist/tasks/task-flow-types.js +128 -0
  92. package/dist/tasks/task-flow-types.js.map +1 -0
  93. package/dist/threadline/ThreadlineMCPServer.d.ts +32 -0
  94. package/dist/threadline/ThreadlineMCPServer.d.ts.map +1 -1
  95. package/dist/threadline/ThreadlineMCPServer.js +82 -5
  96. package/dist/threadline/ThreadlineMCPServer.js.map +1 -1
  97. package/dist/threadline/mcp-stdio-entry.js +56 -0
  98. package/dist/threadline/mcp-stdio-entry.js.map +1 -1
  99. package/package.json +1 -1
  100. package/src/data/builtin-manifest.json +78 -78
  101. package/upgrades/0.28.84.md +89 -0
  102. package/upgrades/0.28.85.md +64 -0
  103. package/upgrades/side-effects/0.28.83.md +27 -0
  104. package/upgrades/side-effects/taskflow-phase1.md +130 -0
  105. package/upgrades/side-effects/taskflow-phase2.md +110 -0
  106. package/upgrades/side-effects/taskflow-phase3a.md +138 -0
  107. package/upgrades/side-effects/taskflow-phase4.md +377 -0
  108. package/upgrades/side-effects/taskflow-phase5.md +234 -0
  109. package/upgrades/side-effects/threadline-discover-relay-and-trust.md +122 -0
  110. package/upgrades/side-effects/wikiclaim-evidence-phase1.md +138 -0
  111. package/upgrades/side-effects/wikiclaim-evidence-phase2.md +148 -0
  112. package/upgrades/side-effects/wikiclaim-evidence-phase3.md +125 -0
  113. package/upgrades/side-effects/wikiclaim-evidence-phase4.md +129 -0
  114. package/upgrades/side-effects/wikiclaim-evidence-phase5.md +285 -0
@@ -2527,6 +2527,7 @@
2527
2527
  <button class="tab" data-tab="commitments" onclick="switchTab('commitments')">Commitments <span class="tab-count" id="tabCommitmentCount">0</span></button>
2528
2528
  <button class="tab" data-tab="tokens" onclick="switchTab('tokens')">Tokens</button>
2529
2529
  <button class="tab" data-tab="threadline" onclick="switchTab('threadline')">Threadline</button>
2530
+ <button class="tab" data-tab="evidence" onclick="switchTab('evidence')">Evidence</button>
2530
2531
  </nav>
2531
2532
  </div>
2532
2533
  <div class="vital-signs" id="vitalSigns">
@@ -2990,6 +2991,66 @@
2990
2991
  </div>
2991
2992
  </div>
2992
2993
 
2994
+ <!-- Evidence Tab (WikiClaim Phase 4) — per-entity evidence + reverse "what cites this?" view.
2995
+ Spec: docs/specs/OPENCLAW-IMPORT-WIKICLAIM-EVIDENCE-SPEC.md § Phase 4 (line 343). -->
2996
+ <div id="evidenceTab" style="display:none;flex-direction:column;padding:20px;gap:16px;overflow-y:auto">
2997
+ <div style="display:flex;justify-content:space-between;align-items:center">
2998
+ <h2 style="margin:0">Evidence</h2>
2999
+ <div style="font-size:12px;color:var(--text-dim)">Per-entity evidence + reverse citations</div>
3000
+ </div>
3001
+ <div style="font-size:12px;color:var(--text-dim);line-height:1.4">
3002
+ Inspect the evidence trail behind any memory entity, or ask "what cites this?" given a kind + sourceId.
3003
+ All results are viewer-scope filtered by SemanticMemory before they reach this view.
3004
+ </div>
3005
+
3006
+ <!-- Viewer scope selector (default: private — agent's own data) -->
3007
+ <div style="display:flex;align-items:center;gap:10px;font-size:13px">
3008
+ <label for="evViewerScope" style="color:var(--text-dim)">Viewer scope:</label>
3009
+ <select id="evViewerScope" style="background:var(--bg);color:var(--text);border:1px solid var(--border);padding:4px 8px;border-radius:4px">
3010
+ <option value="private" selected>private (full)</option>
3011
+ <option value="shared-topic">shared-topic</option>
3012
+ <option value="shared-project">shared-project</option>
3013
+ </select>
3014
+ <span style="color:var(--text-dim);font-size:12px">Narrowing-only — controls what a narrower viewer would see.</span>
3015
+ </div>
3016
+
3017
+ <!-- Panel 1: Per-entity evidence lookup -->
3018
+ <div style="border:1px solid var(--border);border-radius:8px;padding:16px;display:flex;flex-direction:column;gap:10px">
3019
+ <div style="font-weight:600">Evidence by entity</div>
3020
+ <div style="display:flex;gap:8px;align-items:center;flex-wrap:wrap">
3021
+ <input id="evEntityId" type="text" placeholder="Entity ID (e.g. ent_abc123)"
3022
+ style="flex:1;min-width:240px;background:var(--bg);color:var(--text);border:1px solid var(--border);padding:6px 10px;border-radius:4px;font-family:monospace" />
3023
+ <button onclick="loadEvidenceByEntity()" style="padding:6px 12px">Lookup</button>
3024
+ </div>
3025
+ <div id="evEntityStatus" style="font-size:12px;color:var(--text-dim);min-height:1em"></div>
3026
+ <div id="evEntityResults" style="display:flex;flex-direction:column;gap:8px"></div>
3027
+ </div>
3028
+
3029
+ <!-- Panel 2: Reverse citation lookup ("what cites this?") -->
3030
+ <div style="border:1px solid var(--border);border-radius:8px;padding:16px;display:flex;flex-direction:column;gap:10px">
3031
+ <div style="font-weight:600">What cites this?</div>
3032
+ <div style="display:flex;gap:8px;align-items:center;flex-wrap:wrap">
3033
+ <select id="evCitationKind" style="background:var(--bg);color:var(--text);border:1px solid var(--border);padding:6px 10px;border-radius:4px">
3034
+ <option value="feedback">feedback</option>
3035
+ <option value="commit">commit</option>
3036
+ <option value="session">session</option>
3037
+ <option value="document">document</option>
3038
+ <option value="message">message</option>
3039
+ <option value="job-run">job-run</option>
3040
+ <option value="ledger-entry">ledger-entry</option>
3041
+ <option value="pattern-entity">pattern-entity</option>
3042
+ <option value="external-url">external-url</option>
3043
+ <option value="supersedes-evidence">supersedes-evidence</option>
3044
+ </select>
3045
+ <input id="evCitationSourceId" type="text" placeholder="sourceId (e.g. fb_abc123)"
3046
+ style="flex:1;min-width:240px;background:var(--bg);color:var(--text);border:1px solid var(--border);padding:6px 10px;border-radius:4px;font-family:monospace" />
3047
+ <button onclick="loadEntitiesByEvidence()" style="padding:6px 12px">Find citing entities</button>
3048
+ </div>
3049
+ <div id="evCitationStatus" style="font-size:12px;color:var(--text-dim);min-height:1em"></div>
3050
+ <div id="evCitationResults" style="display:flex;flex-direction:column;gap:8px"></div>
3051
+ </div>
3052
+ </div>
3053
+
2993
3054
  <!-- Threadline Tab — agent-to-agent conversations + Telegram bridge settings -->
2994
3055
  <div id="threadlineTab" style="display:none;flex-direction:column;padding:20px;gap:16px;overflow-y:auto">
2995
3056
  <div style="display:flex;justify-content:space-between;align-items:center">
@@ -4151,6 +4212,12 @@
4151
4212
  if (typeof tlObsLoadThreads === 'function') tlObsLoadThreads();
4152
4213
  },
4153
4214
  },
4215
+ {
4216
+ id: 'evidence',
4217
+ panels: ['evidenceTab'],
4218
+ display: ['flex'],
4219
+ onActivate: null,
4220
+ },
4154
4221
  {
4155
4222
  id: 'secrets',
4156
4223
  panels: ['secretsPanel'],
@@ -4327,6 +4394,178 @@
4327
4394
  function escapeHtml(s) {
4328
4395
  return String(s ?? '').replace(/[&<>"']/g, c => ({ '&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;' }[c]));
4329
4396
  }
4397
+
4398
+ // ── Evidence Tab (WikiClaim Phase 4) ─────────────────────────────
4399
+ //
4400
+ // All evidence rendering MUST escape user-supplied strings (note,
4401
+ // sourceId, path). The route already viewer-scope-filters via
4402
+ // SemanticMemory — the dashboard never makes a visibility decision.
4403
+
4404
+ function evCurrentViewerScope() {
4405
+ const sel = document.getElementById('evViewerScope');
4406
+ return sel ? sel.value : 'private';
4407
+ }
4408
+
4409
+ function evRenderTierBadge(tier) {
4410
+ const v = tier == null ? 'inherited' : String(tier);
4411
+ const colorMap = {
4412
+ 'public': '#4a9a4a',
4413
+ 'shared-project': '#7aa9d6',
4414
+ 'private': '#e27d3b',
4415
+ 'sensitive': '#c14a4a',
4416
+ 'inherited': 'var(--text-dim)',
4417
+ };
4418
+ const color = colorMap[v] || 'var(--text-dim)';
4419
+ return `<span style="font-size:11px;padding:2px 6px;border-radius:3px;border:1px solid ${color};color:${color}">${escapeHtml(v)}</span>`;
4420
+ }
4421
+
4422
+ function evRenderEvidenceRow(ev) {
4423
+ const kind = escapeHtml(ev?.kind ?? '');
4424
+ const sourceId = escapeHtml(ev?.sourceId ?? '');
4425
+ const path = ev?.path ? escapeHtml(ev.path) : '';
4426
+ const lineStart = ev?.lineStart;
4427
+ const lineEnd = ev?.lineEnd;
4428
+ let fileLine = '';
4429
+ if (path) {
4430
+ let suffix = '';
4431
+ if (Number.isFinite(lineStart)) {
4432
+ suffix = ':' + escapeHtml(String(lineStart));
4433
+ if (Number.isFinite(lineEnd) && lineEnd !== lineStart) {
4434
+ suffix += '-' + escapeHtml(String(lineEnd));
4435
+ }
4436
+ } else if (typeof ev?.lines === 'string') {
4437
+ suffix = ':' + escapeHtml(ev.lines);
4438
+ }
4439
+ fileLine = `<span style="font-family:monospace;font-size:12px;color:var(--text-dim)">${path}${suffix}</span>`;
4440
+ }
4441
+ const weight = (typeof ev?.weight === 'number') ? ev.weight.toFixed(2) : '—';
4442
+ const confidence = (typeof ev?.confidence === 'number') ? ev.confidence.toFixed(2) : '—';
4443
+ const note = ev?.note ? escapeHtml(ev.note) : '';
4444
+ const updatedAt = escapeHtml(ev?.updatedAt ?? '');
4445
+
4446
+ return `
4447
+ <div style="border:1px solid var(--border);border-radius:6px;padding:10px 12px;display:flex;flex-direction:column;gap:6px;background:var(--bg-panel)">
4448
+ <div style="display:flex;align-items:center;gap:8px;flex-wrap:wrap">
4449
+ <span style="font-weight:600;font-size:13px">${kind}</span>
4450
+ <span style="font-family:monospace;font-size:12px;color:var(--text-dim)">${sourceId}</span>
4451
+ ${evRenderTierBadge(ev?.privacyTier)}
4452
+ </div>
4453
+ ${fileLine ? `<div>${fileLine}</div>` : ''}
4454
+ <div style="font-size:12px;color:var(--text-dim);display:flex;gap:12px;flex-wrap:wrap">
4455
+ <span>weight: ${escapeHtml(weight)}</span>
4456
+ <span>confidence: ${escapeHtml(confidence)}</span>
4457
+ <span>updated: ${updatedAt}</span>
4458
+ </div>
4459
+ ${note ? `<div style="font-size:13px;line-height:1.4;white-space:pre-wrap;word-break:break-word">${note}</div>` : ''}
4460
+ </div>
4461
+ `;
4462
+ }
4463
+
4464
+ function evRenderEntityRow(entity) {
4465
+ const id = escapeHtml(entity?.id ?? '');
4466
+ const type = escapeHtml(entity?.type ?? '');
4467
+ const name = escapeHtml(entity?.name ?? '');
4468
+ const content = entity?.content ? escapeHtml(String(entity.content).slice(0, 240)) : '';
4469
+ const scope = escapeHtml(entity?.privacyScope ?? 'shared-project');
4470
+ const confidence = (typeof entity?.confidence === 'number') ? entity.confidence.toFixed(2) : '—';
4471
+ return `
4472
+ <div style="border:1px solid var(--border);border-radius:6px;padding:10px 12px;display:flex;flex-direction:column;gap:6px;background:var(--bg-panel)">
4473
+ <div style="display:flex;align-items:center;gap:8px;flex-wrap:wrap">
4474
+ <span style="font-weight:600;font-size:13px">${type}</span>
4475
+ <span style="font-size:13px">${name}</span>
4476
+ <span style="font-family:monospace;font-size:11px;color:var(--text-dim)">${id}</span>
4477
+ <span style="font-size:11px;padding:2px 6px;border-radius:3px;border:1px solid var(--border);color:var(--text-dim)">${scope}</span>
4478
+ <span style="font-size:11px;color:var(--text-dim)">confidence: ${escapeHtml(confidence)}</span>
4479
+ <button class="ev-inspect-btn" data-entity-id="${id}" style="margin-left:auto;padding:2px 8px;font-size:11px">Inspect evidence</button>
4480
+ </div>
4481
+ ${content ? `<div style="font-size:12px;color:var(--text-dim);line-height:1.4">${content}</div>` : ''}
4482
+ </div>
4483
+ `;
4484
+ }
4485
+
4486
+ async function loadEvidenceByEntity() {
4487
+ const idInput = document.getElementById('evEntityId');
4488
+ const status = document.getElementById('evEntityStatus');
4489
+ const results = document.getElementById('evEntityResults');
4490
+ if (!idInput || !status || !results) return;
4491
+ const id = (idInput.value || '').trim();
4492
+ if (!id) {
4493
+ status.textContent = 'Enter an entity ID.';
4494
+ results.innerHTML = '';
4495
+ return;
4496
+ }
4497
+ status.textContent = 'Loading…';
4498
+ results.innerHTML = '';
4499
+ try {
4500
+ const viewerScope = evCurrentViewerScope();
4501
+ const url = '/memory/evidence/by-entity/' + encodeURIComponent(id)
4502
+ + '?viewerScope=' + encodeURIComponent(viewerScope);
4503
+ const data = await apiFetch(url);
4504
+ const ev = Array.isArray(data.evidence) ? data.evidence : [];
4505
+ if (ev.length === 0) {
4506
+ status.textContent = 'No evidence visible at viewer scope "' + viewerScope + '".';
4507
+ results.innerHTML = '';
4508
+ return;
4509
+ }
4510
+ status.textContent = ev.length + ' evidence row(s) at scope "' + viewerScope + '".';
4511
+ results.innerHTML = ev.map(evRenderEvidenceRow).join('');
4512
+ } catch (err) {
4513
+ const msg = (err && err.message) ? err.message : 'Lookup failed';
4514
+ status.innerHTML = '<span style="color:var(--red)">' + escapeHtml(msg) + '</span>';
4515
+ results.innerHTML = '';
4516
+ }
4517
+ }
4518
+
4519
+ function evLookupFromCitation(entityId) {
4520
+ const idInput = document.getElementById('evEntityId');
4521
+ if (idInput) idInput.value = entityId;
4522
+ loadEvidenceByEntity();
4523
+ }
4524
+
4525
+ async function loadEntitiesByEvidence() {
4526
+ const kindEl = document.getElementById('evCitationKind');
4527
+ const sourceIdEl = document.getElementById('evCitationSourceId');
4528
+ const status = document.getElementById('evCitationStatus');
4529
+ const results = document.getElementById('evCitationResults');
4530
+ if (!kindEl || !sourceIdEl || !status || !results) return;
4531
+ const kind = kindEl.value;
4532
+ const sourceId = (sourceIdEl.value || '').trim();
4533
+ if (!sourceId) {
4534
+ status.textContent = 'Enter a sourceId.';
4535
+ results.innerHTML = '';
4536
+ return;
4537
+ }
4538
+ status.textContent = 'Loading…';
4539
+ results.innerHTML = '';
4540
+ try {
4541
+ const viewerScope = evCurrentViewerScope();
4542
+ const url = '/memory/entities/by-evidence'
4543
+ + '?kind=' + encodeURIComponent(kind)
4544
+ + '&sourceId=' + encodeURIComponent(sourceId)
4545
+ + '&viewerScope=' + encodeURIComponent(viewerScope);
4546
+ const data = await apiFetch(url);
4547
+ const entities = Array.isArray(data.entities) ? data.entities : [];
4548
+ if (entities.length === 0) {
4549
+ status.textContent = 'No entities cite (' + kind + ', ' + sourceId + ') at scope "' + viewerScope + '".';
4550
+ results.innerHTML = '';
4551
+ return;
4552
+ }
4553
+ status.textContent = entities.length + ' entity(ies) cite this source at scope "' + viewerScope + '".';
4554
+ results.innerHTML = entities.map(evRenderEntityRow).join('');
4555
+ // Attach click handlers via data attribute (no inline onclick injection).
4556
+ results.querySelectorAll('button.ev-inspect-btn').forEach((btn) => {
4557
+ btn.addEventListener('click', () => {
4558
+ const targetId = btn.getAttribute('data-entity-id') || '';
4559
+ if (targetId) evLookupFromCitation(targetId);
4560
+ });
4561
+ });
4562
+ } catch (err) {
4563
+ const msg = (err && err.message) ? err.message : 'Lookup failed';
4564
+ status.innerHTML = '<span style="color:var(--red)">' + escapeHtml(msg) + '</span>';
4565
+ results.innerHTML = '';
4566
+ }
4567
+ }
4568
+
4330
4569
  async function loadTokens() {
4331
4570
  const summaryEl = document.getElementById('tokensSummaryBody');
4332
4571
  const sessionsEl = document.getElementById('tokensSessionsBody');
package/dist/cli.js CHANGED
@@ -522,6 +522,16 @@ memoryCmd
522
522
  const { memoryExport } = await import('./commands/memory.js');
523
523
  return memoryExport(opts);
524
524
  });
525
+ memoryCmd
526
+ .command('backfill-evidence')
527
+ .description('One-shot WikiClaim migration: pattern-match legacy MemoryEntity.source ' +
528
+ 'and synthesize typed evidence rows (URL-only — see spec § Migration)')
529
+ .option('-d, --dir <path>', 'Project directory')
530
+ .option('--dry-run', 'Print what would be backfilled without writing')
531
+ .action(async (opts) => {
532
+ const { memoryBackfillEvidence } = await import('./commands/memoryBackfillEvidence.js');
533
+ return memoryBackfillEvidence(opts);
534
+ });
525
535
  // ── Knowledge Base ────────────────────────────────────────────────
526
536
  const knowledgeCmd = program
527
537
  .command('knowledge')