chain-insights 0.3.4 → 0.3.6

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 (54) hide show
  1. package/README.md +28 -11
  2. package/dist/canvas-Cn-maEIh.mjs +203 -0
  3. package/dist/canvas-Cn-maEIh.mjs.map +1 -0
  4. package/dist/canvas-p-oKCMjc.cjs +251 -0
  5. package/dist/cases-Bz_9XKEw.cjs +19 -0
  6. package/dist/cases-TVcAifxu.mjs +16 -0
  7. package/dist/cases-TVcAifxu.mjs.map +1 -0
  8. package/dist/cli.cjs +74 -28
  9. package/dist/cli.mjs +74 -28
  10. package/dist/cli.mjs.map +1 -1
  11. package/dist/{data-extractor-DZUJu1Bz.mjs → data-extractor-B4nHw1wZ.mjs} +2 -2
  12. package/dist/{data-extractor-DZUJu1Bz.mjs.map → data-extractor-B4nHw1wZ.mjs.map} +1 -1
  13. package/dist/{data-extractor-Cavd7wHk.cjs → data-extractor-DS4rzy3M.cjs} +1 -1
  14. package/dist/{export-BqTCO9lP.mjs → export-CBhcJuZ6.mjs} +8 -205
  15. package/dist/export-CBhcJuZ6.mjs.map +1 -0
  16. package/dist/{export-DsXgtCwO.cjs → export-D4v4-6F4.cjs} +16 -214
  17. package/dist/index.cjs +1 -1
  18. package/dist/index.mjs +1 -1
  19. package/dist/{init-DLBL_nVG.mjs → init-CKQ6F07J.mjs} +22 -5
  20. package/dist/init-CKQ6F07J.mjs.map +1 -0
  21. package/dist/{init-zqbd7i-_.cjs → init-Dhw8F23z.cjs} +21 -4
  22. package/dist/mcp-proxy.cjs +20 -20
  23. package/dist/mcp-proxy.mjs +20 -20
  24. package/dist/mcp-proxy.mjs.map +1 -1
  25. package/dist/{public-tools-wJoAFDFa.mjs → public-tools-CyUZEz9B.mjs} +3 -3
  26. package/dist/{public-tools-wJoAFDFa.mjs.map → public-tools-CyUZEz9B.mjs.map} +1 -1
  27. package/dist/{public-tools-BvMb3H2P.cjs → public-tools-xfVNz9NE.cjs} +2 -2
  28. package/dist/{runner-BhZ4lnF1.cjs → runner-CVo41fjz.cjs} +2 -2
  29. package/dist/{runner-DIJSbkjc.mjs → runner-DWuSy1Se.mjs} +3 -3
  30. package/dist/{runner-DIJSbkjc.mjs.map → runner-DWuSy1Se.mjs.map} +1 -1
  31. package/dist/{selector-CF2o5gxN.mjs → selector-BvXM9jbe.mjs} +2 -2
  32. package/dist/{selector-CF2o5gxN.mjs.map → selector-BvXM9jbe.mjs.map} +1 -1
  33. package/dist/{selector-DfAMZEC9.cjs → selector-Dps_ZFxq.cjs} +1 -1
  34. package/dist/{store-CTtqQtaE.mjs → store-C2B_AssI.mjs} +2 -2
  35. package/dist/{store-CTtqQtaE.mjs.map → store-C2B_AssI.mjs.map} +1 -1
  36. package/dist/{store-CqPfs47P.cjs → store-CQhU8dz8.cjs} +0 -18
  37. package/dist/vault-B2y78Ypu.cjs +560 -0
  38. package/dist/vault-z35Dohdq.mjs +560 -0
  39. package/dist/vault-z35Dohdq.mjs.map +1 -0
  40. package/dist/{viz-Dqp3C5kb.cjs → viz-D1620cBX.cjs} +3 -3
  41. package/dist/{viz-5y24S5X1.mjs → viz-DB5XFG1z.mjs} +4 -4
  42. package/dist/{viz-5y24S5X1.mjs.map → viz-DB5XFG1z.mjs.map} +1 -1
  43. package/docs/graph-tools.md +24 -8
  44. package/docs/investigation-workspaces.md +36 -10
  45. package/docs/knowledge-exports.md +6 -2
  46. package/docs/mcp-proxy.md +29 -7
  47. package/docs/obsidian-vault.md +130 -0
  48. package/package.json +1 -1
  49. package/skills/chain-insights-developer-experience/SKILL.md +2 -2
  50. package/skills/chain-insights-investigation/SKILL.md +1 -1
  51. package/dist/cases-Cp9DUbEV.mjs +0 -6
  52. package/dist/cases-sTY5aXav.cjs +0 -9
  53. package/dist/export-BqTCO9lP.mjs.map +0 -1
  54. package/dist/init-DLBL_nVG.mjs.map +0 -1
package/dist/cli.cjs CHANGED
@@ -30,7 +30,7 @@ if (rawArgs[0] === "mcp" && [
30
30
  process.exit(1);
31
31
  }
32
32
  async function resolveCaseSelector(input) {
33
- const { resolveCaseSelector } = await Promise.resolve().then(() => require("./selector-DfAMZEC9.cjs"));
33
+ const { resolveCaseSelector } = await Promise.resolve().then(() => require("./selector-Dps_ZFxq.cjs"));
34
34
  return resolveCaseSelector(input);
35
35
  }
36
36
  async function scopeCasesToInvocationDir() {
@@ -39,7 +39,7 @@ async function scopeCasesToInvocationDir() {
39
39
  process.env["CHAIN_INSIGHTS_CASES_ROOT"] = activeCasesRoot();
40
40
  }
41
41
  async function showCaseContext(caseSelector) {
42
- const { CaseStore } = await Promise.resolve().then(() => require("./cases-sTY5aXav.cjs"));
42
+ const { CaseStore } = await Promise.resolve().then(() => require("./cases-Bz_9XKEw.cjs")).then((n) => n.cases_exports);
43
43
  const caseId = await resolveCaseSelector(caseSelector);
44
44
  const ctx = await CaseStore.loadContext(caseId);
45
45
  console.log(`\n=== Case: ${ctx.case.id} ===`);
@@ -129,6 +129,25 @@ program.command("status").description("Show toolkit status and configuration").a
129
129
  console.log("Graph MCP:", graphMcpStatus);
130
130
  console.log("Graph endpoint:", config.graphMcpEndpoint);
131
131
  });
132
+ program.command("obsidian").description("Manage the local Obsidian investigation vault").addCommand(new commander.Command("open").description("Open the current Chain Insights vault in Obsidian").argument("[path]", "Workspace path to open as an Obsidian vault").action(async (workspacePath) => {
133
+ try {
134
+ const { findActiveWorkspace } = await Promise.resolve().then(() => require("./active-BVr55kvW.cjs")).then((n) => n.active_exports);
135
+ const workspace = workspacePath ? node_path.default.resolve(workspacePath) : findActiveWorkspace()?.root;
136
+ if (!workspace) {
137
+ console.error("No Chain Insights workspace found. Run: cia init .");
138
+ process.exit(1);
139
+ }
140
+ const open = (await import("open")).default;
141
+ await open(workspace, {
142
+ app: { name: "obsidian" },
143
+ wait: false
144
+ });
145
+ } catch (err) {
146
+ console.error(err.message);
147
+ console.error("Open Obsidian manually and choose \"Open folder as vault\" for this workspace.");
148
+ process.exit(1);
149
+ }
150
+ }));
132
151
  program.command("debug").description("Configure Graph MCP debug mode").addCommand(new commander.Command("on").description("Enable Graph MCP debug mode without x402 payments").requiredOption("--token <token>", "Debug bearer token").option("--endpoint <url>", "Graph MCP endpoint").action(async (opts) => {
133
152
  try {
134
153
  const { saveConfig } = await Promise.resolve().then(() => require("./config-BwVx19Og.cjs")).then((n) => n.config_exports);
@@ -214,7 +233,7 @@ program.command("access-key").description("Configure Graph MCP test access key m
214
233
  }));
215
234
  program.command("init").description("Initialize an investigation workspace").argument("[dir]", "Workspace directory to initialize", ".").option("--force", "Overwrite existing workspace files").action(async (dir, opts) => {
216
235
  try {
217
- const { initWorkspace } = await Promise.resolve().then(() => require("./init-zqbd7i-_.cjs"));
236
+ const { initWorkspace } = await Promise.resolve().then(() => require("./init-Dhw8F23z.cjs"));
218
237
  const result = await initWorkspace({
219
238
  targetDir: dir,
220
239
  force: opts.force
@@ -403,7 +422,7 @@ program.command("mcp").description("Interact with the Chain Insights MCP endpoin
403
422
  }));
404
423
  return;
405
424
  }
406
- const { addressRisk } = await Promise.resolve().then(() => require("./public-tools-BvMb3H2P.cjs"));
425
+ const { addressRisk } = await Promise.resolve().then(() => require("./public-tools-xfVNz9NE.cjs"));
407
426
  const result = await addressRisk(client, {
408
427
  address: opts.address,
409
428
  network: opts.network,
@@ -431,7 +450,7 @@ program.command("mcp").description("Interact with the Chain Insights MCP endpoin
431
450
  }));
432
451
  return;
433
452
  }
434
- const { traceVictimFunds } = await Promise.resolve().then(() => require("./public-tools-BvMb3H2P.cjs"));
453
+ const { traceVictimFunds } = await Promise.resolve().then(() => require("./public-tools-xfVNz9NE.cjs"));
435
454
  const caseId = opts.case ? await resolveCaseSelector(opts.case) : void 0;
436
455
  const result = await traceVictimFunds(client, config, {
437
456
  victimAddresses: opts.victimAddresses,
@@ -455,7 +474,7 @@ program.command("mcp").description("Interact with the Chain Insights MCP endpoin
455
474
  const { requireWorkspaceRoot } = await Promise.resolve().then(() => require("./output-root-YIbl6PwF.cjs")).then((n) => n.output_root_exports);
456
475
  requireWorkspaceRoot();
457
476
  await withGraphMcpClient("chain-insights-cli-trace-suspect-funds", async (client, config) => {
458
- const { traceSuspectFunds } = await Promise.resolve().then(() => require("./public-tools-BvMb3H2P.cjs"));
477
+ const { traceSuspectFunds } = await Promise.resolve().then(() => require("./public-tools-xfVNz9NE.cjs"));
459
478
  const caseId = opts.case ? await resolveCaseSelector(opts.case) : void 0;
460
479
  const result = await traceSuspectFunds(client, config, {
461
480
  suspectAddresses: opts.suspectAddresses,
@@ -478,7 +497,7 @@ program.command("mcp").description("Interact with the Chain Insights MCP endpoin
478
497
  const { requireWorkspaceRoot } = await Promise.resolve().then(() => require("./output-root-YIbl6PwF.cjs")).then((n) => n.output_root_exports);
479
498
  requireWorkspaceRoot();
480
499
  await withGraphMcpClient("chain-insights-cli-trace-deposit-sources", async (client, config) => {
481
- const { traceDepositSources } = await Promise.resolve().then(() => require("./public-tools-BvMb3H2P.cjs"));
500
+ const { traceDepositSources } = await Promise.resolve().then(() => require("./public-tools-xfVNz9NE.cjs"));
482
501
  const caseId = opts.case ? await resolveCaseSelector(opts.case) : void 0;
483
502
  const result = await traceDepositSources(client, config, {
484
503
  depositAddresses: opts.depositAddresses,
@@ -496,7 +515,7 @@ program.command("mcp").description("Interact with the Chain Insights MCP endpoin
496
515
  })).addCommand(new commander.Command("stake-insights").description("Explain Bittensor staking behavior around an address, coldkey, or hotkey").requiredOption("--network <network>", "Network to query. Run `cia mcp networks` for supported networks.").option("--address <address>", "Full Bittensor address to inspect as either coldkey or hotkey").option("--coldkey <address>", "Full Bittensor coldkey address to inspect").option("--hotkey <address>", "Full Bittensor hotkey address to inspect").option("--netuid <number>", "Optional subnet netuid filter").option("--start-timestamp-ms <milliseconds>", "Optional inclusive lower activity timestamp bound").option("--end-timestamp-ms <milliseconds>", "Optional inclusive upper activity timestamp bound").option("--start-block <number>", "Optional start block. Current stake graph parity may require timestamp windows instead.").option("--end-block <number>", "Optional end block. Current stake graph parity may require timestamp windows instead.").option("--depth <number>", "Optional expansion depth limit, default 1, max 3").action(async (opts) => {
497
516
  try {
498
517
  await withGraphMcpClient("chain-insights-cli-stake-insights", async (client) => {
499
- const { stakeInsights } = await Promise.resolve().then(() => require("./public-tools-BvMb3H2P.cjs"));
518
+ const { stakeInsights } = await Promise.resolve().then(() => require("./public-tools-xfVNz9NE.cjs"));
500
519
  const result = await stakeInsights(client, {
501
520
  network: opts.network,
502
521
  address: opts.address,
@@ -524,7 +543,7 @@ program.command("mcp").description("Interact with the Chain Insights MCP endpoin
524
543
  assertPublicMcpToolName(tool);
525
544
  await withGraphMcpClient("chain-insights-cli-call", async (client, config) => {
526
545
  if (tool === "address_risk") {
527
- const { addressRisk } = await Promise.resolve().then(() => require("./public-tools-BvMb3H2P.cjs"));
546
+ const { addressRisk } = await Promise.resolve().then(() => require("./public-tools-xfVNz9NE.cjs"));
528
547
  const result = await addressRisk(client, {
529
548
  address: String(args["address"] ?? ""),
530
549
  network: String(args["network"] ?? ""),
@@ -534,7 +553,7 @@ program.command("mcp").description("Interact with the Chain Insights MCP endpoin
534
553
  return;
535
554
  }
536
555
  if (tool === "trace_victim_funds") {
537
- const { traceVictimFunds } = await Promise.resolve().then(() => require("./public-tools-BvMb3H2P.cjs"));
556
+ const { traceVictimFunds } = await Promise.resolve().then(() => require("./public-tools-xfVNz9NE.cjs"));
538
557
  const result = await traceVictimFunds(client, config, {
539
558
  victimAddresses: args["victim_addresses"] ?? "",
540
559
  knownSuspectAddresses: args["known_suspect_addresses"],
@@ -550,7 +569,7 @@ program.command("mcp").description("Interact with the Chain Insights MCP endpoin
550
569
  return;
551
570
  }
552
571
  if (tool === "trace_suspect_funds") {
553
- const { traceSuspectFunds } = await Promise.resolve().then(() => require("./public-tools-BvMb3H2P.cjs"));
572
+ const { traceSuspectFunds } = await Promise.resolve().then(() => require("./public-tools-xfVNz9NE.cjs"));
554
573
  const result = await traceSuspectFunds(client, config, {
555
574
  suspectAddresses: args["suspect_addresses"] ?? "",
556
575
  network: String(args["network"] ?? ""),
@@ -565,7 +584,7 @@ program.command("mcp").description("Interact with the Chain Insights MCP endpoin
565
584
  return;
566
585
  }
567
586
  if (tool === "trace_deposit_sources") {
568
- const { traceDepositSources } = await Promise.resolve().then(() => require("./public-tools-BvMb3H2P.cjs"));
587
+ const { traceDepositSources } = await Promise.resolve().then(() => require("./public-tools-xfVNz9NE.cjs"));
569
588
  const result = await traceDepositSources(client, config, {
570
589
  depositAddresses: args["deposit_addresses"] ?? "",
571
590
  network: String(args["network"] ?? ""),
@@ -577,7 +596,7 @@ program.command("mcp").description("Interact with the Chain Insights MCP endpoin
577
596
  return;
578
597
  }
579
598
  if (tool === "stake_insights") {
580
- const { stakeInsights } = await Promise.resolve().then(() => require("./public-tools-BvMb3H2P.cjs"));
599
+ const { stakeInsights } = await Promise.resolve().then(() => require("./public-tools-xfVNz9NE.cjs"));
581
600
  const result = await stakeInsights(client, {
582
601
  network: String(args["network"] ?? ""),
583
602
  address: args["address"] === void 0 ? void 0 : String(args["address"]),
@@ -609,24 +628,36 @@ const caseCommand = new commander.Command("case").description("Manage investigat
609
628
  }).addCommand(new commander.Command("open").description("Open a new investigation case").argument("<name>", "Case name (e.g. \"Tornado Mixer Investigation\")").option("--tags <tags>", "Comma-separated tags (e.g. aml,mixer,defi)", "").option("--description <desc>", "Brief description of the investigation", "").action(async (name, opts) => {
610
629
  try {
611
630
  if (/^[1-9]\d*$/.test(name.trim())) throw new Error("Numeric case names look like list selectors. Use a descriptive case name, e.g. `cia case open \"Tracking stolen funds from <address>\"`.");
612
- const { CaseStore } = await Promise.resolve().then(() => require("./cases-sTY5aXav.cjs"));
631
+ const { CaseStore } = await Promise.resolve().then(() => require("./cases-Bz_9XKEw.cjs")).then((n) => n.cases_exports);
613
632
  const tags = opts.tags ? opts.tags.split(",").map((t) => t.trim()).filter(Boolean) : [];
614
633
  const c = await CaseStore.create({
615
634
  name,
616
635
  tags,
617
636
  description: opts.description
618
637
  });
619
- const { casesRoot } = await Promise.resolve().then(() => require("./store-CqPfs47P.cjs")).then((n) => n.store_exports);
638
+ const { casesRoot } = await Promise.resolve().then(() => require("./store-CQhU8dz8.cjs")).then((n) => n.store_exports);
620
639
  console.log(`Case opened: ${c.id}`);
621
640
  console.log(`Directory: ${node_path.default.join(casesRoot(), c.id)}/`);
622
641
  console.log(`Status: ${c.status}`);
642
+ const { findActiveWorkspace } = await Promise.resolve().then(() => require("./active-BVr55kvW.cjs")).then((n) => n.active_exports);
643
+ if (findActiveWorkspace()) try {
644
+ const { refreshCaseVault } = await Promise.resolve().then(() => require("./vault-B2y78Ypu.cjs"));
645
+ const result = await refreshCaseVault({
646
+ caseId: c.id,
647
+ force: true
648
+ });
649
+ console.log(`Open first: ${result.nextFile}`);
650
+ } catch (refreshErr) {
651
+ console.error(`Warning: live vault refresh failed: ${refreshErr.message}`);
652
+ console.error(`Run: cia case vault refresh ${c.id} --force`);
653
+ }
623
654
  } catch (err) {
624
655
  console.error(err.message);
625
656
  process.exit(1);
626
657
  }
627
658
  })).addCommand(new commander.Command("activate").description("Activate a case (set status to active)").argument("<case-id>", "Case ID to activate").action(async (caseSelector) => {
628
659
  try {
629
- const { CaseStore } = await Promise.resolve().then(() => require("./cases-sTY5aXav.cjs"));
660
+ const { CaseStore } = await Promise.resolve().then(() => require("./cases-Bz_9XKEw.cjs")).then((n) => n.cases_exports);
630
661
  const caseId = await resolveCaseSelector(caseSelector);
631
662
  const c = await CaseStore.setStatus(caseId, "active");
632
663
  console.log(`Case ${c.id} is now: active`);
@@ -636,7 +667,7 @@ const caseCommand = new commander.Command("case").description("Manage investigat
636
667
  }
637
668
  })).addCommand(new commander.Command("suspend").description("Suspend a case (set status to suspended)").argument("<case-id>", "Case ID to suspend").action(async (caseSelector) => {
638
669
  try {
639
- const { CaseStore } = await Promise.resolve().then(() => require("./cases-sTY5aXav.cjs"));
670
+ const { CaseStore } = await Promise.resolve().then(() => require("./cases-Bz_9XKEw.cjs")).then((n) => n.cases_exports);
640
671
  const caseId = await resolveCaseSelector(caseSelector);
641
672
  const c = await CaseStore.setStatus(caseId, "suspended");
642
673
  console.log(`Case ${c.id} is now: suspended`);
@@ -646,7 +677,7 @@ const caseCommand = new commander.Command("case").description("Manage investigat
646
677
  }
647
678
  })).addCommand(new commander.Command("close").description("Close a case permanently").argument("<case-id>", "Case ID to close").action(async (caseSelector) => {
648
679
  try {
649
- const { CaseStore } = await Promise.resolve().then(() => require("./cases-sTY5aXav.cjs"));
680
+ const { CaseStore } = await Promise.resolve().then(() => require("./cases-Bz_9XKEw.cjs")).then((n) => n.cases_exports);
650
681
  const caseId = await resolveCaseSelector(caseSelector);
651
682
  const c = await CaseStore.setStatus(caseId, "closed");
652
683
  console.log(`Case ${c.id} is now: closed`);
@@ -656,7 +687,7 @@ const caseCommand = new commander.Command("case").description("Manage investigat
656
687
  }
657
688
  })).addCommand(new commander.Command("list").description("List all investigation cases").option("--status <status>", "Filter by status (open|active|suspended|closed)").action(async (opts) => {
658
689
  try {
659
- const { CaseStore } = await Promise.resolve().then(() => require("./cases-sTY5aXav.cjs"));
690
+ const { CaseStore } = await Promise.resolve().then(() => require("./cases-Bz_9XKEw.cjs")).then((n) => n.cases_exports);
660
691
  const cases = await CaseStore.list();
661
692
  const filtered = opts.status ? cases.filter((c) => c.status === opts.status) : cases;
662
693
  if (filtered.length === 0) {
@@ -670,7 +701,7 @@ const caseCommand = new commander.Command("case").description("Manage investigat
670
701
  }
671
702
  })).addCommand(new commander.Command("evidence").description("Manage case evidence").addCommand(new commander.Command("add").description("Add evidence to a case from an MCP query result").argument("<case-id>", "Case ID to add evidence to").option("--source <tool>", "MCP tool name that produced this evidence", "manual").option("--content <text>", "Evidence content (MCP response or notes)", "").option("--query-params <params>", "Query parameters used (e.g. address=0x1234)", "").action(async (caseSelector, opts) => {
672
703
  try {
673
- const { EvidenceStore } = await Promise.resolve().then(() => require("./cases-sTY5aXav.cjs"));
704
+ const { EvidenceStore } = await Promise.resolve().then(() => require("./cases-Bz_9XKEw.cjs")).then((n) => n.cases_exports);
674
705
  const caseId = await resolveCaseSelector(caseSelector);
675
706
  const result = await EvidenceStore.append(caseId, {
676
707
  source: opts.source,
@@ -685,7 +716,7 @@ const caseCommand = new commander.Command("case").description("Manage investigat
685
716
  }
686
717
  })).addCommand(new commander.Command("verify").description("Verify evidence manifest integrity for a case").argument("<case-id>", "Case ID to verify").action(async (caseSelector) => {
687
718
  try {
688
- const { EvidenceStore } = await Promise.resolve().then(() => require("./cases-sTY5aXav.cjs"));
719
+ const { EvidenceStore } = await Promise.resolve().then(() => require("./cases-Bz_9XKEw.cjs")).then((n) => n.cases_exports);
689
720
  const caseId = await resolveCaseSelector(caseSelector);
690
721
  const result = await EvidenceStore.verifyManifest(caseId);
691
722
  if (result.ok) console.log(`Manifest OK — ${result.count} evidence file(s) verified`);
@@ -699,7 +730,7 @@ const caseCommand = new commander.Command("case").description("Manage investigat
699
730
  }
700
731
  }))).addCommand(new commander.Command("dossier").description("Manage entity dossiers for a case").addCommand(new commander.Command("update").description("Append a finding to an entity dossier").argument("<case-id>", "Case ID").argument("<address>", "Entity address or identifier").option("--finding <text>", "Finding to append to the dossier", "").option("--type <type>", "Entity type (eoa|contract|exchange|mixer|unknown)", "unknown").action(async (caseSelector, address, opts) => {
701
732
  try {
702
- const { DossierStore } = await Promise.resolve().then(() => require("./cases-sTY5aXav.cjs"));
733
+ const { DossierStore } = await Promise.resolve().then(() => require("./cases-Bz_9XKEw.cjs")).then((n) => n.cases_exports);
703
734
  const caseId = await resolveCaseSelector(caseSelector);
704
735
  const entityType = [
705
736
  "eoa",
@@ -716,7 +747,7 @@ const caseCommand = new commander.Command("case").description("Manage investigat
716
747
  }
717
748
  }))).addCommand(new commander.Command("session").description("Manage investigation sessions").addCommand(new commander.Command("start").description("Start a new investigation session for a case").argument("<case-id>", "Case ID").argument("[title...]", "Optional session title").action(async (caseSelector, titleParts) => {
718
749
  try {
719
- const { SessionStore } = await Promise.resolve().then(() => require("./cases-sTY5aXav.cjs"));
750
+ const { SessionStore } = await Promise.resolve().then(() => require("./cases-Bz_9XKEw.cjs")).then((n) => n.cases_exports);
720
751
  const caseId = await resolveCaseSelector(caseSelector);
721
752
  const title = titleParts.join(" ").trim();
722
753
  const s = await SessionStore.start(caseId, title ? { title } : {});
@@ -727,7 +758,7 @@ const caseCommand = new commander.Command("case").description("Manage investigat
727
758
  }
728
759
  })).addCommand(new commander.Command("end").description("End the current session with findings and next steps").argument("<case-id>", "Case ID").option("--findings <text>", "Key findings from this session", "").option("--next-steps <text>", "Next steps for the investigation", "").action(async (caseSelector, opts) => {
729
760
  try {
730
- const { SessionStore } = await Promise.resolve().then(() => require("./cases-sTY5aXav.cjs"));
761
+ const { SessionStore } = await Promise.resolve().then(() => require("./cases-Bz_9XKEw.cjs")).then((n) => n.cases_exports);
731
762
  const caseId = await resolveCaseSelector(caseSelector);
732
763
  await SessionStore.end(caseId, {
733
764
  findings: opts.findings,
@@ -739,7 +770,22 @@ const caseCommand = new commander.Command("case").description("Manage investigat
739
770
  console.error(err.message);
740
771
  process.exit(1);
741
772
  }
742
- }))).addCommand(new commander.Command("export").description("Export a case for Obsidian, LLMWiki, and agents").argument("<case-id>", "Case ID or case list number to export").option("--target <target>", "Export target: obsidian-llmwiki", "obsidian-llmwiki").option("--mode <mode>", "Redaction mode: private|partner|public", "private").option("--out <directory>", "Output directory. Defaults to published/<case-slug>").action(async (caseSelector, opts) => {
773
+ }))).addCommand(new commander.Command("vault").description("Manage live Obsidian case vault notes").addCommand(new commander.Command("refresh").description("Refresh Obsidian vault notes for a case").argument("<case-id-or-selector>", "Case ID or case list number to refresh").option("--force", "Overwrite existing generated case vault files").action(async (caseSelector, opts) => {
774
+ try {
775
+ const caseId = await resolveCaseSelector(caseSelector);
776
+ const { refreshCaseVault } = await Promise.resolve().then(() => require("./vault-B2y78Ypu.cjs"));
777
+ const result = await refreshCaseVault({
778
+ caseId,
779
+ force: opts.force === true
780
+ });
781
+ console.log(`Case vault refreshed: ${caseId}`);
782
+ console.log(`Files: ${result.filesWritten.length}`);
783
+ console.log(`Open first: ${result.nextFile}`);
784
+ } catch (err) {
785
+ console.error(err.message);
786
+ process.exit(1);
787
+ }
788
+ }))).addCommand(new commander.Command("export").description("Export a case for Obsidian, LLM Wiki, and agents").argument("<case-id>", "Case ID or case list number to export").option("--target <target>", "Export target: obsidian-llmwiki", "obsidian-llmwiki").option("--mode <mode>", "Redaction mode: private|partner|public", "private").option("--out <directory>", "Output directory. Defaults to published/<case-slug>").action(async (caseSelector, opts) => {
743
789
  try {
744
790
  const target = opts.target === "obsidian-llmwiki" ? opts.target : void 0;
745
791
  const mode = [
@@ -750,7 +796,7 @@ const caseCommand = new commander.Command("case").description("Manage investigat
750
796
  if (!target) throw new Error(`Unsupported export target: ${opts.target}`);
751
797
  if (!mode) throw new Error(`Unsupported export mode: ${opts.mode}`);
752
798
  const caseId = await resolveCaseSelector(caseSelector);
753
- const { exportCase } = await Promise.resolve().then(() => require("./export-DsXgtCwO.cjs"));
799
+ const { exportCase } = await Promise.resolve().then(() => require("./export-D4v4-6F4.cjs"));
754
800
  const result = await exportCase({
755
801
  caseId,
756
802
  target,
@@ -804,7 +850,7 @@ program.command("playbook").description("Run and manage investigation playbooks"
804
850
  console.error(`Invalid --from value: "${opts.from}". Must be a positive integer.`);
805
851
  process.exit(1);
806
852
  }
807
- const { PlaybookRunner } = await Promise.resolve().then(() => require("./runner-BhZ4lnF1.cjs"));
853
+ const { PlaybookRunner } = await Promise.resolve().then(() => require("./runner-CVo41fjz.cjs"));
808
854
  await PlaybookRunner.run(definition, {
809
855
  caseId: opts.case,
810
856
  from: fromN,
@@ -854,7 +900,7 @@ program.command("viz").description("Generate money flow visualization").argument
854
900
  console.error("Provide either a case ID or --data <file.json>");
855
901
  process.exit(1);
856
902
  }
857
- const { generateVisualization } = await Promise.resolve().then(() => require("./viz-Dqp3C5kb.cjs")).then((n) => n.viz_exports);
903
+ const { generateVisualization } = await Promise.resolve().then(() => require("./viz-D1620cBX.cjs")).then((n) => n.viz_exports);
858
904
  const result = await generateVisualization({
859
905
  caseId,
860
906
  dataFile: opts.data
package/dist/cli.mjs CHANGED
@@ -28,7 +28,7 @@ if (rawArgs[0] === "mcp" && [
28
28
  process.exit(1);
29
29
  }
30
30
  async function resolveCaseSelector(input) {
31
- const { resolveCaseSelector } = await import("./selector-CF2o5gxN.mjs");
31
+ const { resolveCaseSelector } = await import("./selector-BvXM9jbe.mjs");
32
32
  return resolveCaseSelector(input);
33
33
  }
34
34
  async function scopeCasesToInvocationDir() {
@@ -37,7 +37,7 @@ async function scopeCasesToInvocationDir() {
37
37
  process.env["CHAIN_INSIGHTS_CASES_ROOT"] = activeCasesRoot();
38
38
  }
39
39
  async function showCaseContext(caseSelector) {
40
- const { CaseStore } = await import("./cases-Cp9DUbEV.mjs");
40
+ const { CaseStore } = await import("./cases-TVcAifxu.mjs").then((n) => n.t);
41
41
  const caseId = await resolveCaseSelector(caseSelector);
42
42
  const ctx = await CaseStore.loadContext(caseId);
43
43
  console.log(`\n=== Case: ${ctx.case.id} ===`);
@@ -127,6 +127,25 @@ program.command("status").description("Show toolkit status and configuration").a
127
127
  console.log("Graph MCP:", graphMcpStatus);
128
128
  console.log("Graph endpoint:", config.graphMcpEndpoint);
129
129
  });
130
+ program.command("obsidian").description("Manage the local Obsidian investigation vault").addCommand(new Command("open").description("Open the current Chain Insights vault in Obsidian").argument("[path]", "Workspace path to open as an Obsidian vault").action(async (workspacePath) => {
131
+ try {
132
+ const { findActiveWorkspace } = await import("./active-ByNgjuAg.mjs").then((n) => n.n);
133
+ const workspace = workspacePath ? path.resolve(workspacePath) : findActiveWorkspace()?.root;
134
+ if (!workspace) {
135
+ console.error("No Chain Insights workspace found. Run: cia init .");
136
+ process.exit(1);
137
+ }
138
+ const open = (await import("open")).default;
139
+ await open(workspace, {
140
+ app: { name: "obsidian" },
141
+ wait: false
142
+ });
143
+ } catch (err) {
144
+ console.error(err.message);
145
+ console.error("Open Obsidian manually and choose \"Open folder as vault\" for this workspace.");
146
+ process.exit(1);
147
+ }
148
+ }));
130
149
  program.command("debug").description("Configure Graph MCP debug mode").addCommand(new Command("on").description("Enable Graph MCP debug mode without x402 payments").requiredOption("--token <token>", "Debug bearer token").option("--endpoint <url>", "Graph MCP endpoint").action(async (opts) => {
131
150
  try {
132
151
  const { saveConfig } = await import("./config-Drgc2HuF.mjs").then((n) => n.t);
@@ -212,7 +231,7 @@ program.command("access-key").description("Configure Graph MCP test access key m
212
231
  }));
213
232
  program.command("init").description("Initialize an investigation workspace").argument("[dir]", "Workspace directory to initialize", ".").option("--force", "Overwrite existing workspace files").action(async (dir, opts) => {
214
233
  try {
215
- const { initWorkspace } = await import("./init-DLBL_nVG.mjs");
234
+ const { initWorkspace } = await import("./init-CKQ6F07J.mjs");
216
235
  const result = await initWorkspace({
217
236
  targetDir: dir,
218
237
  force: opts.force
@@ -401,7 +420,7 @@ program.command("mcp").description("Interact with the Chain Insights MCP endpoin
401
420
  }));
402
421
  return;
403
422
  }
404
- const { addressRisk } = await import("./public-tools-wJoAFDFa.mjs");
423
+ const { addressRisk } = await import("./public-tools-CyUZEz9B.mjs");
405
424
  const result = await addressRisk(client, {
406
425
  address: opts.address,
407
426
  network: opts.network,
@@ -429,7 +448,7 @@ program.command("mcp").description("Interact with the Chain Insights MCP endpoin
429
448
  }));
430
449
  return;
431
450
  }
432
- const { traceVictimFunds } = await import("./public-tools-wJoAFDFa.mjs");
451
+ const { traceVictimFunds } = await import("./public-tools-CyUZEz9B.mjs");
433
452
  const caseId = opts.case ? await resolveCaseSelector(opts.case) : void 0;
434
453
  const result = await traceVictimFunds(client, config, {
435
454
  victimAddresses: opts.victimAddresses,
@@ -453,7 +472,7 @@ program.command("mcp").description("Interact with the Chain Insights MCP endpoin
453
472
  const { requireWorkspaceRoot } = await import("./output-root-BRhzhhXZ.mjs").then((n) => n.t);
454
473
  requireWorkspaceRoot();
455
474
  await withGraphMcpClient("chain-insights-cli-trace-suspect-funds", async (client, config) => {
456
- const { traceSuspectFunds } = await import("./public-tools-wJoAFDFa.mjs");
475
+ const { traceSuspectFunds } = await import("./public-tools-CyUZEz9B.mjs");
457
476
  const caseId = opts.case ? await resolveCaseSelector(opts.case) : void 0;
458
477
  const result = await traceSuspectFunds(client, config, {
459
478
  suspectAddresses: opts.suspectAddresses,
@@ -476,7 +495,7 @@ program.command("mcp").description("Interact with the Chain Insights MCP endpoin
476
495
  const { requireWorkspaceRoot } = await import("./output-root-BRhzhhXZ.mjs").then((n) => n.t);
477
496
  requireWorkspaceRoot();
478
497
  await withGraphMcpClient("chain-insights-cli-trace-deposit-sources", async (client, config) => {
479
- const { traceDepositSources } = await import("./public-tools-wJoAFDFa.mjs");
498
+ const { traceDepositSources } = await import("./public-tools-CyUZEz9B.mjs");
480
499
  const caseId = opts.case ? await resolveCaseSelector(opts.case) : void 0;
481
500
  const result = await traceDepositSources(client, config, {
482
501
  depositAddresses: opts.depositAddresses,
@@ -494,7 +513,7 @@ program.command("mcp").description("Interact with the Chain Insights MCP endpoin
494
513
  })).addCommand(new Command("stake-insights").description("Explain Bittensor staking behavior around an address, coldkey, or hotkey").requiredOption("--network <network>", "Network to query. Run `cia mcp networks` for supported networks.").option("--address <address>", "Full Bittensor address to inspect as either coldkey or hotkey").option("--coldkey <address>", "Full Bittensor coldkey address to inspect").option("--hotkey <address>", "Full Bittensor hotkey address to inspect").option("--netuid <number>", "Optional subnet netuid filter").option("--start-timestamp-ms <milliseconds>", "Optional inclusive lower activity timestamp bound").option("--end-timestamp-ms <milliseconds>", "Optional inclusive upper activity timestamp bound").option("--start-block <number>", "Optional start block. Current stake graph parity may require timestamp windows instead.").option("--end-block <number>", "Optional end block. Current stake graph parity may require timestamp windows instead.").option("--depth <number>", "Optional expansion depth limit, default 1, max 3").action(async (opts) => {
495
514
  try {
496
515
  await withGraphMcpClient("chain-insights-cli-stake-insights", async (client) => {
497
- const { stakeInsights } = await import("./public-tools-wJoAFDFa.mjs");
516
+ const { stakeInsights } = await import("./public-tools-CyUZEz9B.mjs");
498
517
  const result = await stakeInsights(client, {
499
518
  network: opts.network,
500
519
  address: opts.address,
@@ -522,7 +541,7 @@ program.command("mcp").description("Interact with the Chain Insights MCP endpoin
522
541
  assertPublicMcpToolName(tool);
523
542
  await withGraphMcpClient("chain-insights-cli-call", async (client, config) => {
524
543
  if (tool === "address_risk") {
525
- const { addressRisk } = await import("./public-tools-wJoAFDFa.mjs");
544
+ const { addressRisk } = await import("./public-tools-CyUZEz9B.mjs");
526
545
  const result = await addressRisk(client, {
527
546
  address: String(args["address"] ?? ""),
528
547
  network: String(args["network"] ?? ""),
@@ -532,7 +551,7 @@ program.command("mcp").description("Interact with the Chain Insights MCP endpoin
532
551
  return;
533
552
  }
534
553
  if (tool === "trace_victim_funds") {
535
- const { traceVictimFunds } = await import("./public-tools-wJoAFDFa.mjs");
554
+ const { traceVictimFunds } = await import("./public-tools-CyUZEz9B.mjs");
536
555
  const result = await traceVictimFunds(client, config, {
537
556
  victimAddresses: args["victim_addresses"] ?? "",
538
557
  knownSuspectAddresses: args["known_suspect_addresses"],
@@ -548,7 +567,7 @@ program.command("mcp").description("Interact with the Chain Insights MCP endpoin
548
567
  return;
549
568
  }
550
569
  if (tool === "trace_suspect_funds") {
551
- const { traceSuspectFunds } = await import("./public-tools-wJoAFDFa.mjs");
570
+ const { traceSuspectFunds } = await import("./public-tools-CyUZEz9B.mjs");
552
571
  const result = await traceSuspectFunds(client, config, {
553
572
  suspectAddresses: args["suspect_addresses"] ?? "",
554
573
  network: String(args["network"] ?? ""),
@@ -563,7 +582,7 @@ program.command("mcp").description("Interact with the Chain Insights MCP endpoin
563
582
  return;
564
583
  }
565
584
  if (tool === "trace_deposit_sources") {
566
- const { traceDepositSources } = await import("./public-tools-wJoAFDFa.mjs");
585
+ const { traceDepositSources } = await import("./public-tools-CyUZEz9B.mjs");
567
586
  const result = await traceDepositSources(client, config, {
568
587
  depositAddresses: args["deposit_addresses"] ?? "",
569
588
  network: String(args["network"] ?? ""),
@@ -575,7 +594,7 @@ program.command("mcp").description("Interact with the Chain Insights MCP endpoin
575
594
  return;
576
595
  }
577
596
  if (tool === "stake_insights") {
578
- const { stakeInsights } = await import("./public-tools-wJoAFDFa.mjs");
597
+ const { stakeInsights } = await import("./public-tools-CyUZEz9B.mjs");
579
598
  const result = await stakeInsights(client, {
580
599
  network: String(args["network"] ?? ""),
581
600
  address: args["address"] === void 0 ? void 0 : String(args["address"]),
@@ -607,24 +626,36 @@ const caseCommand = new Command("case").description("Manage investigation cases"
607
626
  }).addCommand(new Command("open").description("Open a new investigation case").argument("<name>", "Case name (e.g. \"Tornado Mixer Investigation\")").option("--tags <tags>", "Comma-separated tags (e.g. aml,mixer,defi)", "").option("--description <desc>", "Brief description of the investigation", "").action(async (name, opts) => {
608
627
  try {
609
628
  if (/^[1-9]\d*$/.test(name.trim())) throw new Error("Numeric case names look like list selectors. Use a descriptive case name, e.g. `cia case open \"Tracking stolen funds from <address>\"`.");
610
- const { CaseStore } = await import("./cases-Cp9DUbEV.mjs");
629
+ const { CaseStore } = await import("./cases-TVcAifxu.mjs").then((n) => n.t);
611
630
  const tags = opts.tags ? opts.tags.split(",").map((t) => t.trim()).filter(Boolean) : [];
612
631
  const c = await CaseStore.create({
613
632
  name,
614
633
  tags,
615
634
  description: opts.description
616
635
  });
617
- const { casesRoot } = await import("./store-CTtqQtaE.mjs").then((n) => n.r);
636
+ const { casesRoot } = await import("./store-C2B_AssI.mjs").then((n) => n.n);
618
637
  console.log(`Case opened: ${c.id}`);
619
638
  console.log(`Directory: ${path.join(casesRoot(), c.id)}/`);
620
639
  console.log(`Status: ${c.status}`);
640
+ const { findActiveWorkspace } = await import("./active-ByNgjuAg.mjs").then((n) => n.n);
641
+ if (findActiveWorkspace()) try {
642
+ const { refreshCaseVault } = await import("./vault-z35Dohdq.mjs");
643
+ const result = await refreshCaseVault({
644
+ caseId: c.id,
645
+ force: true
646
+ });
647
+ console.log(`Open first: ${result.nextFile}`);
648
+ } catch (refreshErr) {
649
+ console.error(`Warning: live vault refresh failed: ${refreshErr.message}`);
650
+ console.error(`Run: cia case vault refresh ${c.id} --force`);
651
+ }
621
652
  } catch (err) {
622
653
  console.error(err.message);
623
654
  process.exit(1);
624
655
  }
625
656
  })).addCommand(new Command("activate").description("Activate a case (set status to active)").argument("<case-id>", "Case ID to activate").action(async (caseSelector) => {
626
657
  try {
627
- const { CaseStore } = await import("./cases-Cp9DUbEV.mjs");
658
+ const { CaseStore } = await import("./cases-TVcAifxu.mjs").then((n) => n.t);
628
659
  const caseId = await resolveCaseSelector(caseSelector);
629
660
  const c = await CaseStore.setStatus(caseId, "active");
630
661
  console.log(`Case ${c.id} is now: active`);
@@ -634,7 +665,7 @@ const caseCommand = new Command("case").description("Manage investigation cases"
634
665
  }
635
666
  })).addCommand(new Command("suspend").description("Suspend a case (set status to suspended)").argument("<case-id>", "Case ID to suspend").action(async (caseSelector) => {
636
667
  try {
637
- const { CaseStore } = await import("./cases-Cp9DUbEV.mjs");
668
+ const { CaseStore } = await import("./cases-TVcAifxu.mjs").then((n) => n.t);
638
669
  const caseId = await resolveCaseSelector(caseSelector);
639
670
  const c = await CaseStore.setStatus(caseId, "suspended");
640
671
  console.log(`Case ${c.id} is now: suspended`);
@@ -644,7 +675,7 @@ const caseCommand = new Command("case").description("Manage investigation cases"
644
675
  }
645
676
  })).addCommand(new Command("close").description("Close a case permanently").argument("<case-id>", "Case ID to close").action(async (caseSelector) => {
646
677
  try {
647
- const { CaseStore } = await import("./cases-Cp9DUbEV.mjs");
678
+ const { CaseStore } = await import("./cases-TVcAifxu.mjs").then((n) => n.t);
648
679
  const caseId = await resolveCaseSelector(caseSelector);
649
680
  const c = await CaseStore.setStatus(caseId, "closed");
650
681
  console.log(`Case ${c.id} is now: closed`);
@@ -654,7 +685,7 @@ const caseCommand = new Command("case").description("Manage investigation cases"
654
685
  }
655
686
  })).addCommand(new Command("list").description("List all investigation cases").option("--status <status>", "Filter by status (open|active|suspended|closed)").action(async (opts) => {
656
687
  try {
657
- const { CaseStore } = await import("./cases-Cp9DUbEV.mjs");
688
+ const { CaseStore } = await import("./cases-TVcAifxu.mjs").then((n) => n.t);
658
689
  const cases = await CaseStore.list();
659
690
  const filtered = opts.status ? cases.filter((c) => c.status === opts.status) : cases;
660
691
  if (filtered.length === 0) {
@@ -668,7 +699,7 @@ const caseCommand = new Command("case").description("Manage investigation cases"
668
699
  }
669
700
  })).addCommand(new Command("evidence").description("Manage case evidence").addCommand(new Command("add").description("Add evidence to a case from an MCP query result").argument("<case-id>", "Case ID to add evidence to").option("--source <tool>", "MCP tool name that produced this evidence", "manual").option("--content <text>", "Evidence content (MCP response or notes)", "").option("--query-params <params>", "Query parameters used (e.g. address=0x1234)", "").action(async (caseSelector, opts) => {
670
701
  try {
671
- const { EvidenceStore } = await import("./cases-Cp9DUbEV.mjs");
702
+ const { EvidenceStore } = await import("./cases-TVcAifxu.mjs").then((n) => n.t);
672
703
  const caseId = await resolveCaseSelector(caseSelector);
673
704
  const result = await EvidenceStore.append(caseId, {
674
705
  source: opts.source,
@@ -683,7 +714,7 @@ const caseCommand = new Command("case").description("Manage investigation cases"
683
714
  }
684
715
  })).addCommand(new Command("verify").description("Verify evidence manifest integrity for a case").argument("<case-id>", "Case ID to verify").action(async (caseSelector) => {
685
716
  try {
686
- const { EvidenceStore } = await import("./cases-Cp9DUbEV.mjs");
717
+ const { EvidenceStore } = await import("./cases-TVcAifxu.mjs").then((n) => n.t);
687
718
  const caseId = await resolveCaseSelector(caseSelector);
688
719
  const result = await EvidenceStore.verifyManifest(caseId);
689
720
  if (result.ok) console.log(`Manifest OK — ${result.count} evidence file(s) verified`);
@@ -697,7 +728,7 @@ const caseCommand = new Command("case").description("Manage investigation cases"
697
728
  }
698
729
  }))).addCommand(new Command("dossier").description("Manage entity dossiers for a case").addCommand(new Command("update").description("Append a finding to an entity dossier").argument("<case-id>", "Case ID").argument("<address>", "Entity address or identifier").option("--finding <text>", "Finding to append to the dossier", "").option("--type <type>", "Entity type (eoa|contract|exchange|mixer|unknown)", "unknown").action(async (caseSelector, address, opts) => {
699
730
  try {
700
- const { DossierStore } = await import("./cases-Cp9DUbEV.mjs");
731
+ const { DossierStore } = await import("./cases-TVcAifxu.mjs").then((n) => n.t);
701
732
  const caseId = await resolveCaseSelector(caseSelector);
702
733
  const entityType = [
703
734
  "eoa",
@@ -714,7 +745,7 @@ const caseCommand = new Command("case").description("Manage investigation cases"
714
745
  }
715
746
  }))).addCommand(new Command("session").description("Manage investigation sessions").addCommand(new Command("start").description("Start a new investigation session for a case").argument("<case-id>", "Case ID").argument("[title...]", "Optional session title").action(async (caseSelector, titleParts) => {
716
747
  try {
717
- const { SessionStore } = await import("./cases-Cp9DUbEV.mjs");
748
+ const { SessionStore } = await import("./cases-TVcAifxu.mjs").then((n) => n.t);
718
749
  const caseId = await resolveCaseSelector(caseSelector);
719
750
  const title = titleParts.join(" ").trim();
720
751
  const s = await SessionStore.start(caseId, title ? { title } : {});
@@ -725,7 +756,7 @@ const caseCommand = new Command("case").description("Manage investigation cases"
725
756
  }
726
757
  })).addCommand(new Command("end").description("End the current session with findings and next steps").argument("<case-id>", "Case ID").option("--findings <text>", "Key findings from this session", "").option("--next-steps <text>", "Next steps for the investigation", "").action(async (caseSelector, opts) => {
727
758
  try {
728
- const { SessionStore } = await import("./cases-Cp9DUbEV.mjs");
759
+ const { SessionStore } = await import("./cases-TVcAifxu.mjs").then((n) => n.t);
729
760
  const caseId = await resolveCaseSelector(caseSelector);
730
761
  await SessionStore.end(caseId, {
731
762
  findings: opts.findings,
@@ -737,7 +768,22 @@ const caseCommand = new Command("case").description("Manage investigation cases"
737
768
  console.error(err.message);
738
769
  process.exit(1);
739
770
  }
740
- }))).addCommand(new Command("export").description("Export a case for Obsidian, LLMWiki, and agents").argument("<case-id>", "Case ID or case list number to export").option("--target <target>", "Export target: obsidian-llmwiki", "obsidian-llmwiki").option("--mode <mode>", "Redaction mode: private|partner|public", "private").option("--out <directory>", "Output directory. Defaults to published/<case-slug>").action(async (caseSelector, opts) => {
771
+ }))).addCommand(new Command("vault").description("Manage live Obsidian case vault notes").addCommand(new Command("refresh").description("Refresh Obsidian vault notes for a case").argument("<case-id-or-selector>", "Case ID or case list number to refresh").option("--force", "Overwrite existing generated case vault files").action(async (caseSelector, opts) => {
772
+ try {
773
+ const caseId = await resolveCaseSelector(caseSelector);
774
+ const { refreshCaseVault } = await import("./vault-z35Dohdq.mjs");
775
+ const result = await refreshCaseVault({
776
+ caseId,
777
+ force: opts.force === true
778
+ });
779
+ console.log(`Case vault refreshed: ${caseId}`);
780
+ console.log(`Files: ${result.filesWritten.length}`);
781
+ console.log(`Open first: ${result.nextFile}`);
782
+ } catch (err) {
783
+ console.error(err.message);
784
+ process.exit(1);
785
+ }
786
+ }))).addCommand(new Command("export").description("Export a case for Obsidian, LLM Wiki, and agents").argument("<case-id>", "Case ID or case list number to export").option("--target <target>", "Export target: obsidian-llmwiki", "obsidian-llmwiki").option("--mode <mode>", "Redaction mode: private|partner|public", "private").option("--out <directory>", "Output directory. Defaults to published/<case-slug>").action(async (caseSelector, opts) => {
741
787
  try {
742
788
  const target = opts.target === "obsidian-llmwiki" ? opts.target : void 0;
743
789
  const mode = [
@@ -748,7 +794,7 @@ const caseCommand = new Command("case").description("Manage investigation cases"
748
794
  if (!target) throw new Error(`Unsupported export target: ${opts.target}`);
749
795
  if (!mode) throw new Error(`Unsupported export mode: ${opts.mode}`);
750
796
  const caseId = await resolveCaseSelector(caseSelector);
751
- const { exportCase } = await import("./export-BqTCO9lP.mjs");
797
+ const { exportCase } = await import("./export-CBhcJuZ6.mjs");
752
798
  const result = await exportCase({
753
799
  caseId,
754
800
  target,
@@ -802,7 +848,7 @@ program.command("playbook").description("Run and manage investigation playbooks"
802
848
  console.error(`Invalid --from value: "${opts.from}". Must be a positive integer.`);
803
849
  process.exit(1);
804
850
  }
805
- const { PlaybookRunner } = await import("./runner-DIJSbkjc.mjs");
851
+ const { PlaybookRunner } = await import("./runner-DWuSy1Se.mjs");
806
852
  await PlaybookRunner.run(definition, {
807
853
  caseId: opts.case,
808
854
  from: fromN,
@@ -852,7 +898,7 @@ program.command("viz").description("Generate money flow visualization").argument
852
898
  console.error("Provide either a case ID or --data <file.json>");
853
899
  process.exit(1);
854
900
  }
855
- const { generateVisualization } = await import("./viz-5y24S5X1.mjs").then((n) => n.n);
901
+ const { generateVisualization } = await import("./viz-DB5XFG1z.mjs").then((n) => n.n);
856
902
  const result = await generateVisualization({
857
903
  caseId,
858
904
  dataFile: opts.data