@kanadego/dsh-heartbeat 1.9.3 → 2.0.0

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 (57) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +103 -110
  3. package/client.js +12 -0
  4. package/config/policy.json +74 -74
  5. package/config/profile-schema.json +306 -306
  6. package/dist/{bindings-225SI7KC.js → bindings-U2M3CO2D.js} +3 -3
  7. package/dist/{chunk-TY6UP74X.js → chunk-3DNGY4DS.js} +2 -2
  8. package/dist/{chunk-CUOSICYJ.js → chunk-544QOJN5.js} +397 -23
  9. package/dist/chunk-544QOJN5.js.map +1 -0
  10. package/dist/{chunk-TRO4E6WG.js → chunk-6MVKWICX.js} +587 -139
  11. package/dist/chunk-6MVKWICX.js.map +1 -0
  12. package/dist/{chunk-WLZSABBH.js → chunk-6XM6KY7M.js} +27 -10
  13. package/dist/chunk-6XM6KY7M.js.map +1 -0
  14. package/dist/chunk-AKIJ4LS2.js +680 -0
  15. package/dist/chunk-AKIJ4LS2.js.map +1 -0
  16. package/dist/{chunk-KB5SMG3F.js → chunk-DC5HMCJC.js} +3 -3
  17. package/dist/{chunk-3MDBU6WY.js → chunk-DZ7YCFGX.js} +37 -7
  18. package/dist/chunk-DZ7YCFGX.js.map +1 -0
  19. package/dist/{chunk-WRUTATW4.js → chunk-IBBAISSW.js} +13 -2
  20. package/dist/chunk-IBBAISSW.js.map +1 -0
  21. package/dist/{chunk-XYYEJK3W.js → chunk-IFRMKVIC.js} +82 -21
  22. package/dist/chunk-IFRMKVIC.js.map +1 -0
  23. package/dist/{chunk-XFNCTOW7.js → chunk-NCPKOWS7.js} +52 -4
  24. package/dist/chunk-NCPKOWS7.js.map +1 -0
  25. package/dist/{chunk-JDH2LDFS.js → chunk-TVX4HV4Y.js} +4 -6
  26. package/dist/{chunk-JDH2LDFS.js.map → chunk-TVX4HV4Y.js.map} +1 -1
  27. package/dist/cli/index.js +149 -26
  28. package/dist/cli/index.js.map +1 -1
  29. package/dist/{inbox-P26DDMWC.js → inbox-OWBK6PE2.js} +8 -7
  30. package/dist/index.d.ts +48 -315
  31. package/dist/index.js +259 -918
  32. package/dist/index.js.map +1 -1
  33. package/dist/migrate-TQ5PB2DI.js +27 -0
  34. package/dist/{orchestrator-ZPRGVDCB.js → orchestrator-P7AEWVYR.js} +23 -12
  35. package/dist/{pool-UTXQJJ5C.js → pool-2T6TVS2L.js} +4 -5
  36. package/dist/{snapshot-K5VHETTK.js → snapshot-F5B2DD56.js} +5 -5
  37. package/package.json +84 -83
  38. package/dist/chunk-3MDBU6WY.js.map +0 -1
  39. package/dist/chunk-CUOSICYJ.js.map +0 -1
  40. package/dist/chunk-IV2ZWQA3.js +0 -56
  41. package/dist/chunk-IV2ZWQA3.js.map +0 -1
  42. package/dist/chunk-K5Y6JP2B.js +0 -399
  43. package/dist/chunk-K5Y6JP2B.js.map +0 -1
  44. package/dist/chunk-TRO4E6WG.js.map +0 -1
  45. package/dist/chunk-WLZSABBH.js.map +0 -1
  46. package/dist/chunk-WRUTATW4.js.map +0 -1
  47. package/dist/chunk-XFNCTOW7.js.map +0 -1
  48. package/dist/chunk-XYYEJK3W.js.map +0 -1
  49. package/dist/migrate-D4VKAKYT.js +0 -21
  50. /package/dist/{bindings-225SI7KC.js.map → bindings-U2M3CO2D.js.map} +0 -0
  51. /package/dist/{chunk-TY6UP74X.js.map → chunk-3DNGY4DS.js.map} +0 -0
  52. /package/dist/{chunk-KB5SMG3F.js.map → chunk-DC5HMCJC.js.map} +0 -0
  53. /package/dist/{inbox-P26DDMWC.js.map → inbox-OWBK6PE2.js.map} +0 -0
  54. /package/dist/{migrate-D4VKAKYT.js.map → migrate-TQ5PB2DI.js.map} +0 -0
  55. /package/dist/{orchestrator-ZPRGVDCB.js.map → orchestrator-P7AEWVYR.js.map} +0 -0
  56. /package/dist/{pool-UTXQJJ5C.js.map → pool-2T6TVS2L.js.map} +0 -0
  57. /package/dist/{snapshot-K5VHETTK.js.map → snapshot-F5B2DD56.js.map} +0 -0
package/dist/cli/index.js CHANGED
@@ -3,16 +3,21 @@ import {
3
3
  collectMigrationEntries,
4
4
  decryptContainer,
5
5
  encryptContainer
6
- } from "../chunk-XFNCTOW7.js";
6
+ } from "../chunk-NCPKOWS7.js";
7
7
  import {
8
8
  BUNDLED_PRESET_ID,
9
+ EXCERPT_HEADER,
10
+ appendExcerpt,
9
11
  conventionalUserPresetRoot,
10
12
  createPathGuard,
11
13
  describeInstall,
14
+ excerptFilePath,
12
15
  installBundledPreset,
13
16
  loadPolicy,
14
- presetStatus
15
- } from "../chunk-XYYEJK3W.js";
17
+ presetStatus,
18
+ readExcerpts,
19
+ removeExcerpt
20
+ } from "../chunk-IFRMKVIC.js";
16
21
  import {
17
22
  adviseWander,
18
23
  appendEntry,
@@ -28,7 +33,7 @@ import {
28
33
  scanPending,
29
34
  sendNewMessageHint,
30
35
  weeklyDirPath
31
- } from "../chunk-WLZSABBH.js";
36
+ } from "../chunk-6XM6KY7M.js";
32
37
  import {
33
38
  activeSeeds,
34
39
  addSeed,
@@ -38,29 +43,33 @@ import {
38
43
  loadPool,
39
44
  seedsFilePath,
40
45
  surfaceSeed
41
- } from "../chunk-JDH2LDFS.js";
42
- import "../chunk-IV2ZWQA3.js";
46
+ } from "../chunk-TVX4HV4Y.js";
43
47
  import {
44
48
  appendAuditLine,
45
49
  loadProfile,
46
50
  profileFilePath,
47
51
  pruneAuditFile,
48
52
  rebuildProfile,
49
- verifyProfile
50
- } from "../chunk-CUOSICYJ.js";
53
+ verifyProfile,
54
+ wipeProfile
55
+ } from "../chunk-544QOJN5.js";
51
56
  import {
57
+ containerKind,
58
+ dshHomeDir,
52
59
  initWorkspace,
60
+ matchFilesRecursive,
61
+ upgradeVaultTree,
62
+ vaultKeyPath,
53
63
  writeText
54
- } from "../chunk-K5Y6JP2B.js";
64
+ } from "../chunk-AKIJ4LS2.js";
55
65
  import {
56
66
  atomicWriteFileSync,
57
67
  shredFileSync
58
- } from "../chunk-WRUTATW4.js";
68
+ } from "../chunk-IBBAISSW.js";
59
69
 
60
70
  // src/cli/index.ts
61
71
  import { spawn } from "child_process";
62
72
  import fs2 from "fs";
63
- import os from "os";
64
73
  import path2 from "path";
65
74
 
66
75
  // src/vault/burn-list.ts
@@ -73,6 +82,12 @@ var BURN_LIST = [
73
82
  // H-19: the rotation shards hold the whole profile history and are written
74
83
  // in PLAINTEXT — a burn that leaves them behind leaves the memory readable.
75
84
  { prefix: "profile_journal.archive-", note: "\u753B\u50CF\u6D41\u6C34\u5F52\u6863\u5206\u7247\uFF08\u660E\u6587\uFF1Bjournal \u8F6E\u8F6C\u4EA7\u7269\uFF09" },
85
+ // HB-07 (2026-10-17): applyMigrationEntries copies every file it overwrites
86
+ // to `${abs}.bak-migrate-${stamp}`. Those copies hold the OLD memory — a burn
87
+ // that left them behind left the thing the user asked to destroy. The
88
+ // `.incoming-` staging files are the same data, only younger.
89
+ { match: /\.bak-migrate-\d{14}$/, note: "\u8FC1\u79FB\u5907\u4EFD\uFF08\u8FC1\u79FB\u5BFC\u5165\u65F6\u7684\u539F\u6587\u4EF6\u526F\u672C\uFF09" },
90
+ { match: /\.incoming-\d{14}$/, note: "\u8FC1\u79FB\u6682\u5B58\u6B8B\u7559\uFF08\u5D29\u6E83\u9057\u7559\u7684\u5BFC\u5165\u526F\u672C\uFF09" },
76
91
  { file: "profile_rhythm.json", note: "\u4F5C\u606F\u805A\u5408\uFF08\u7EAF\u7EDF\u8BA1\uFF09" },
77
92
  { file: "screen.json", note: "\u5C4F\u5E55\u5FEB\u7167\uFF08\u52A0\u5BC6\uFF09" },
78
93
  { file: "screen.jpg", note: "\u622A\u56FE\uFF08\u52A0\u5BC6\uFF09" },
@@ -102,13 +117,22 @@ function prefixMatches(guard, paths, prefix) {
102
117
  return [];
103
118
  }
104
119
  }
120
+ function matchTargets(guard, paths, re) {
121
+ try {
122
+ return matchFilesRecursive(guard.assert(paths.dataDir), re);
123
+ } catch {
124
+ return [];
125
+ }
126
+ }
105
127
  function planBurn(guard, paths, all = false) {
106
128
  const plan = [];
107
129
  for (const t of BURN_LIST) {
108
- const rel = t.file ?? t.dir ?? t.prefix ?? "";
130
+ const rel = t.file ?? t.dir ?? t.prefix ?? String(t.match ?? "");
109
131
  if (!all && rel === SETTINGS_DIR) continue;
110
132
  let exists = false;
111
- if (t.prefix) {
133
+ if (t.match) {
134
+ exists = matchTargets(guard, paths, t.match).length > 0;
135
+ } else if (t.prefix) {
112
136
  exists = prefixMatches(guard, paths, t.prefix).length > 0;
113
137
  } else {
114
138
  try {
@@ -129,6 +153,21 @@ function executeBurn(guard, paths, opts = {}) {
129
153
  const missing = [];
130
154
  const passes = opts.shredPasses ?? 3;
131
155
  for (const t of BURN_LIST) {
156
+ if (t.match) {
157
+ const matches = matchTargets(guard, paths, t.match);
158
+ if (matches.length === 0) {
159
+ missing.push(String(t.match));
160
+ continue;
161
+ }
162
+ for (const f of matches) {
163
+ try {
164
+ shredFileSync(guard.assert(path.join(paths.dataDir, f)), passes);
165
+ burned.push(f);
166
+ } catch {
167
+ }
168
+ }
169
+ continue;
170
+ }
132
171
  if (t.prefix) {
133
172
  const matches = prefixMatches(guard, paths, t.prefix);
134
173
  if (matches.length === 0) {
@@ -144,7 +183,7 @@ function executeBurn(guard, paths, opts = {}) {
144
183
  }
145
184
  continue;
146
185
  }
147
- const rel = t.file ?? t.dir;
186
+ const rel = t.file ?? t.dir ?? String(t.match ?? "");
148
187
  const abs = path.join(paths.dataDir, rel);
149
188
  let absCanon;
150
189
  try {
@@ -197,6 +236,10 @@ function usage() {
197
236
  " ledger list [--pending] list entries",
198
237
  " ledger done <id|substring> mark an entry done",
199
238
  " ledger open open ledger.md in the default editor",
239
+ " excerpt add <text> keep a line in the notebook",
240
+ " excerpt list [n] list entries (newest n if given)",
241
+ " excerpt remove <id|substring> tear a page out",
242
+ " excerpt open open excerpts.md in the default editor",
200
243
  " logs cleanup [--dry-run] apply log retention now",
201
244
  " browse status browse state summary (wander)",
202
245
  " browse dry wander adjudication with forced noon window",
@@ -214,6 +257,8 @@ function usage() {
214
257
  " profile wipe wipe profile data (asks --yes)",
215
258
  " weekly list list generated weekly reports",
216
259
  " weekly show [file] print a report (default: newest)",
260
+ " vault status encryption containers on disk + master key file",
261
+ " vault upgrade rewrite legacy KHBV1 files as KHBV2 (in place)",
217
262
  " migrate export [file] pack memory files into a passphrase container (passphrase: 2 stdin lines)",
218
263
  " migrate import <file> restore a container into this workspace (passphrase: 1 stdin line)",
219
264
  " burn [--yes] [--all] shred runtime data (settings kept unless --all)",
@@ -379,6 +424,57 @@ async function verbLedger(c) {
379
424
  return 1;
380
425
  }
381
426
  }
427
+ async function verbExcerpt(c) {
428
+ const { guard, sub, rest, excerptFile } = c;
429
+ switch (sub) {
430
+ case "add": {
431
+ let text = rest.join(" ").trim();
432
+ if (text === "-") text = readStdinText();
433
+ if (!text) {
434
+ console.error("usage: excerpt add <text|->");
435
+ return 1;
436
+ }
437
+ const e = appendExcerpt(guard, excerptFile, text);
438
+ console.log(`KEPT #${e.id} ${e.text.slice(0, 60)}`);
439
+ return 0;
440
+ }
441
+ case "list": {
442
+ const all = readExcerpts(guard, excerptFile).entries;
443
+ const n = Number.parseInt(rest[0] ?? "", 10);
444
+ const items = Number.isFinite(n) && n > 0 ? all.slice(-n) : all;
445
+ for (const e of items) console.log(`#${e.id} ${e.date} ${e.time} ${e.text.slice(0, 60)}`);
446
+ if (items.length === 0) console.log("(empty)");
447
+ return 0;
448
+ }
449
+ case "remove": {
450
+ const key = rest.join(" ").trim();
451
+ if (!key) {
452
+ console.error("usage: excerpt remove <id|substring>");
453
+ return 1;
454
+ }
455
+ const e = removeExcerpt(guard, excerptFile, key);
456
+ if (!e) {
457
+ console.log("NOT_FOUND");
458
+ return 1;
459
+ }
460
+ console.log(`REMOVED #${e.id}`);
461
+ return 0;
462
+ }
463
+ case "open": {
464
+ const f = excerptFile;
465
+ if (!fs2.existsSync(f)) {
466
+ fs2.mkdirSync(path2.dirname(f), { recursive: true });
467
+ fs2.writeFileSync(f, EXCERPT_HEADER, "utf8");
468
+ }
469
+ spawn("cmd", ["/c", "start", "", f], { detached: true, stdio: "ignore" }).unref();
470
+ console.log(`opened ${f}`);
471
+ return 0;
472
+ }
473
+ default:
474
+ console.error(`unknown excerpt subcommand: ${sub}`);
475
+ return 1;
476
+ }
477
+ }
382
478
  async function verbWeekly(c) {
383
479
  const { guard, paths, sub, rest } = c;
384
480
  const reports = listWeeklyReports(guard, paths.dataDir);
@@ -521,18 +617,16 @@ async function verbProfile(c) {
521
617
  }
522
618
  case "wipe": {
523
619
  if (!rest.includes("--yes")) {
524
- console.log("REFUSED: add --yes to wipe profile data (profile.json/inbox/journal)");
620
+ console.log("REFUSED: add --yes to wipe profile data (live files, snapshot, journal archives, migration copies)");
525
621
  return 1;
526
622
  }
527
- for (const f of ["profile.json", "profile_inbox.jsonl", "profile_journal.jsonl"]) {
528
- const abs = guard.assert(path2.join(paths.dataDir, f));
529
- if (fs2.existsSync(abs)) fs2.rmSync(abs, { force: true });
530
- }
531
- console.log("WIPED (settings preserved; use burn for full shredding)");
623
+ const removed = wipeProfile(guard, paths.dataDir);
624
+ console.log(`WIPED ${removed.length} file(s) (settings preserved; use burn for full shredding)`);
625
+ for (const f of removed) console.log(` - ${f}`);
532
626
  return 0;
533
627
  }
534
628
  case "snapshot": {
535
- const { snapshotDue, snapshotProfile, SNAPSHOT_THRESHOLD } = await import("../snapshot-K5VHETTK.js");
629
+ const { snapshotDue, snapshotProfile, SNAPSHOT_THRESHOLD } = await import("../snapshot-F5B2DD56.js");
536
630
  const { needed, lines } = snapshotDue(guard, paths.dataDir);
537
631
  console.log(`journal ${lines} \u6761\uFF08\u9608\u503C ${SNAPSHOT_THRESHOLD}\uFF09`);
538
632
  if (!needed && !rest.includes("--force")) {
@@ -634,10 +728,10 @@ async function verbMigrate(c) {
634
728
  }
635
729
  async function verbSessions(c) {
636
730
  const { guard, paths } = c;
637
- const root = path2.join(os.homedir(), ".dsh", "sessions");
731
+ const root = path2.join(dshHomeDir(), "sessions");
638
732
  let found = 0;
639
733
  if (fs2.existsSync(root)) {
640
- const { homeSessionId } = await import("../orchestrator-ZPRGVDCB.js");
734
+ const { homeSessionId } = await import("../orchestrator-P7AEWVYR.js");
641
735
  const own = homeSessionId(guard, paths);
642
736
  for (const slug of fs2.readdirSync(root)) {
643
737
  for (const id of fs2.readdirSync(path2.join(root, slug))) {
@@ -652,11 +746,11 @@ async function verbSessions(c) {
652
746
  }
653
747
  async function verbBind(c) {
654
748
  const { guard, paths, sub, rest } = c;
655
- const { loadBindings, addBinding, removeBinding } = await import("../bindings-225SI7KC.js");
749
+ const { loadBindings, addBinding, removeBinding } = await import("../bindings-U2M3CO2D.js");
656
750
  switch (sub) {
657
751
  case "list": {
658
752
  const data = loadBindings(guard, paths.settingsDir);
659
- const { homeSessionId } = await import("../orchestrator-ZPRGVDCB.js");
753
+ const { homeSessionId } = await import("../orchestrator-P7AEWVYR.js");
660
754
  const own = homeSessionId(guard, paths);
661
755
  if (own) console.log(`\u5FC3\u8DF3\u6B63\u8EAB: ${own}\uFF08\u51B3\u7B56\u8F6E\u6B21\u53D1\u751F\u5730\uFF1Bbind remove \u5B83 = \u91CD\u7F6E\u6B63\u8EAB\uFF09`);
662
756
  for (const b of data.bindings) {
@@ -684,7 +778,7 @@ async function verbBind(c) {
684
778
  return 1;
685
779
  }
686
780
  console.log(removeBinding(guard, paths.settingsDir, id) ? `UNBOUND ${id}` : "NOT_FOUND");
687
- const { resetHomeSession } = await import("../orchestrator-ZPRGVDCB.js");
781
+ const { resetHomeSession } = await import("../orchestrator-P7AEWVYR.js");
688
782
  if (resetHomeSession(guard, paths, id)) {
689
783
  console.log("\u6CE8\u610F\uFF1A\u8FD9\u662F\u5FC3\u8DF3\u6B63\u8EAB\u4F1A\u8BDD\u3002\u5DF2\u91CD\u7F6E\u2014\u2014\u4E0B\u6B21\u5FC3\u8DF3\u5C06\u521B\u5EFA\u65B0\u7684\u6B63\u8EAB\u4F1A\u8BDD\uFF08\u65E7\u4F1A\u8BDD\u4E0D\u518D\u6709\u5FC3\u8DF3\uFF09");
690
784
  }
@@ -729,15 +823,43 @@ async function verbPreset(c) {
729
823
  console.error("usage: preset status | install [--force] [--id <presetId>]");
730
824
  return 1;
731
825
  }
826
+ async function verbVault(c) {
827
+ const { guard, paths, sub } = c;
828
+ const keyFile = vaultKeyPath();
829
+ const files = matchFilesRecursive(paths.dataDir, /./).filter(
830
+ (rel) => rel !== "vault.key" && !rel.startsWith("tmp/")
831
+ );
832
+ const counts = { v1: 0, v2: 0, plain: 0 };
833
+ for (const rel of files) {
834
+ counts[containerKind(path2.join(paths.dataDir, rel.split("/").join(path2.sep)))] += 1;
835
+ }
836
+ if (sub === void 0 || sub === "status") {
837
+ console.log(`data dir : ${paths.dataDir}`);
838
+ console.log(`master key : ${keyFile}${fs2.existsSync(keyFile) ? "" : " (not created yet; the next write makes it)"}`);
839
+ console.log(`containers : ${counts.v2} KHBV2 (current), ${counts.v1} KHBV1 (legacy), ${counts.plain} plaintext`);
840
+ if (counts.v1 > 0) console.log("hint: run `vault upgrade` to rewrite the legacy files in place.");
841
+ return 0;
842
+ }
843
+ if (sub === "upgrade") {
844
+ const r = upgradeVaultTree(guard, paths.dataDir);
845
+ console.log(`UPGRADED ${r.upgraded} of ${r.scanned} file(s) to KHBV2`);
846
+ for (const f of r.failed) console.log(` ! ${f.file}: ${f.reason}`);
847
+ return r.failed.length === 0 ? 0 : 1;
848
+ }
849
+ console.error("usage: vault status | upgrade");
850
+ return 1;
851
+ }
732
852
  var VERBS = {
733
853
  status: verbStatus,
734
854
  seeds: verbSeeds,
735
855
  ledger: verbLedger,
856
+ excerpt: verbExcerpt,
736
857
  weekly: verbWeekly,
737
858
  logs: verbLogs,
738
859
  browse: verbBrowse,
739
860
  notify: verbNotify,
740
861
  profile: verbProfile,
862
+ vault: verbVault,
741
863
  burn: verbBurn,
742
864
  migrate: verbMigrate,
743
865
  sessions: verbSessions,
@@ -775,6 +897,7 @@ async function main(argv) {
775
897
  argv,
776
898
  seedsFile: seedsFilePath(paths.dataDir),
777
899
  ledgerFile: ledgerFilePath(paths.dataDir),
900
+ excerptFile: excerptFilePath(paths.dataDir),
778
901
  decisionLog,
779
902
  seedAudit
780
903
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/index.ts","../../src/vault/burn-list.ts"],"sourcesContent":["// Operational CLI (design doc §14). Commands grow per module.\n// Run: node dist/cli/index.js <command> [args] (or via tsx in dev)\n//\n// H-42: `main` used to be a 530-line function with a switch holding every\n// verb's body. The verbs are module-level functions now (see CliCtx below) and\n// `main` only builds the shared context and dispatches — one place to add a\n// command, and each verb is readable on its own.\n\nimport { spawn } from 'node:child_process';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { initWorkspace } from '../core/paths.js';\nimport type { WorkspacePaths } from '../core/paths.js';\nimport { createPathGuard } from '../core/path-guard.js';\nimport type { PathGuard } from '../core/path-guard.js';\nimport { appendAuditLine, pruneAuditFile } from '../core/audit-log.js';\nimport { atomicWriteFileSync } from '../core/atomic-fs.js';\nimport { loadPolicy } from '../config/load.js';\nimport type { Policy } from '../config/schema.js';\nimport {\n addSeed,\n archiveSeedById,\n gcPool,\n loadPool,\n activeSeeds,\n archivedSeeds,\n seedsFilePath,\n surfaceSeed,\n} from '../seeds/pool.js';\nimport type { SeedSource, SeedTag } from '../seeds/types.js';\nimport {\n appendEntry,\n ledgerFilePath,\n markDone,\n readLedger,\n scanPending,\n} from '../ledger/ledger.js';\nimport {\n adviseWander,\n browseStatus,\n completeWander,\n loadInterests,\n} from '../browse/browse.js';\nimport { ensureRegistered, sendNewMessageHint } from '../notify/notify.js';\nimport {\n loadProfile,\n profileFilePath,\n verifyProfile,\n rebuildProfile,\n} from '../profile/store.js';\nimport { planBurn, executeBurn } from '../vault/burn-list.js';\nimport {\n collectMigrationEntries,\n encryptContainer,\n decryptContainer,\n applyMigrationEntries,\n} from '../vault/migrate.js';\nimport { listWeeklyReports, readWeeklyReport, weeklyDirPath } from '../weekly/report.js';\nimport { writeText } from '../vault/vault.js';\nimport {\n BUNDLED_PRESET_ID,\n conventionalUserPresetRoot,\n describeInstall,\n installBundledPreset,\n presetStatus,\n} from '../core/preset-install.js';\n\nfunction usage(): string {\n return [\n 'usage: heartbeat <command> [args]',\n '',\n 'commands:',\n ' status workspace paths + policy summary',\n ' seeds add <text> [--tag t] [--source s] [--topic x] [--confidence n]',\n ' seeds list [--archived] list active (or archived) seeds',\n ' seeds surface <id> count a surfacing (rule 1 accounting)',\n ' seeds archive <id> deliberate retirement (completed)',\n ' seeds gc run deterministic eviction rules 1-3',\n ' seeds stats pool status JSON',\n ' ledger add <text> register an open item',\n ' ledger list [--pending] list entries',\n ' ledger done <id|substring> mark an entry done',\n ' ledger open open ledger.md in the default editor',\n ' logs cleanup [--dry-run] apply log retention now',\n ' browse status browse state summary (wander)',\n ' browse dry wander adjudication with forced noon window',\n ' browse done <focus> CODE-side registration after a wander visit',\n ' bind list list session bindings (D13)',\n ' bind add <sessionId> [--observe] bind a session (deliver by default)',\n ' bind remove <sessionId> unbind a session',\n ' sessions list enumerate persisted sessions (ids)',\n ' notify check|register|send toast channel (D12: hint only, no body)',\n ' profile list [--all] current valid (or all incl. expired) entries',\n ' profile export decrypted Markdown export to data/exports/',\n ' profile verify journal replay vs disk (report only)',\n ' profile rebuild [--check] rebuild materialized view from journal',\n ' profile snapshot [--force] fold the journal into a snapshot + archive shard',\n ' profile wipe wipe profile data (asks --yes)',\n ' weekly list list generated weekly reports',\n ' weekly show [file] print a report (default: newest)',\n ' migrate export [file] pack memory files into a passphrase container (passphrase: 2 stdin lines)',\n ' migrate import <file> restore a container into this workspace (passphrase: 1 stdin line)',\n ' burn [--yes] [--all] shred runtime data (settings kept unless --all)',\n ' preset status bundled agent preset: target dir + installed?',\n ' preset install [--force] install the bundled preset (never overwrites unless --force)',\n ].join('\\n');\n}\n\nfunction readStdinText(): string {\n try {\n return fs.readFileSync(0, 'utf8').trim();\n } catch {\n return '';\n }\n}\n\nfunction flag(argv: string[], name: string): string | undefined {\n const i = argv.indexOf(name);\n return i > -1 ? argv[i + 1] : undefined;\n}\n\n/** H-42: the seed flags used to be written `flag(rest, '--tag') as never` — the\n * escape hatch threw the type away, so a typo landed in the seed record\n * unchecked. Validate against the known sets instead (the `satisfies` clauses\n * keep these lists in step with the types). */\nconst SEED_TAGS = ['news', 'fandom', 'scene', 'promise'] as const satisfies readonly SeedTag[];\nconst SEED_SOURCES = ['chat', 'screen', 'browse', 'hand', 'profile'] as const satisfies readonly SeedSource[];\n\nfunction flagOneOf<T extends string>(argv: string[], name: string, allowed: readonly T[]): T | undefined {\n const v = flag(argv, name);\n if (v === undefined) return undefined;\n return (allowed as readonly string[]).includes(v) ? (v as T) : undefined;\n}\n\n/** Read N lines from stdin (passphrase prompts for migrate). */\nasync function readLines(prompts: string[]): Promise<string[]> {\n const readline = await import('node:readline/promises');\n const it = readline.createInterface({ input: process.stdin });\n const out: string[] = [];\n for (const p of prompts) out.push((await it.question(p)).trim());\n it.close();\n return out;\n}\n\n/** Everything a verb needs. Built once in {@link main}; `sub`/`rest` are the\n * positional split of argv, `argv` stays available for top-level flags. */\ninterface CliCtx {\n paths: WorkspacePaths;\n guard: PathGuard;\n policy: Policy;\n sub: string | undefined;\n rest: string[];\n argv: string[];\n seedsFile: string;\n ledgerFile: string;\n decisionLog: string;\n seedAudit: (entry: Record<string, unknown>) => void;\n}\n\ntype Verb = (c: CliCtx) => Promise<number>;\n\nasync function verbStatus(c: CliCtx): Promise<number> {\n const { paths, policy } = c;\n console.log(JSON.stringify({\n dataDir: paths.dataDir,\n heartbeatIntervalMin: policy.heartbeat.intervalMin,\n maxDailySend: policy.gate.maxDailySend,\n seedsMaxActive: policy.seeds.maxActive,\n psyEnabled: policy.profile.psyEnabled,\n }, null, 2));\n return 0;\n}\n\nasync function verbSeeds(c: CliCtx): Promise<number> {\n const { guard, policy, sub, rest, seedsFile, seedAudit } = c;\n switch (sub) {\n case 'add': {\n let text = rest[0]?.trim() ?? '';\n if (text === '-') text = readStdinText();\n if (!text) {\n console.error('usage: seeds add <text|-> [--tag t] [--source s] [--topic x] [--confidence n]');\n return 1;\n }\n const result = addSeed(guard, seedsFile, policy, {\n text,\n tag: flagOneOf(rest, '--tag', SEED_TAGS),\n source: flagOneOf(rest, '--source', SEED_SOURCES),\n topic: flag(rest, '--topic'),\n confidence: flag(rest, '--confidence') ? Number(flag(rest, '--confidence')) : undefined,\n }, Date.now(), seedAudit);\n if (result.kind === 'duplicate') {\n console.log(`DUPLICATE: active seed ${result.seed.id} has the same text`);\n return 0;\n }\n console.log(`${result.kind.toUpperCase()} ${result.seed.id}` +\n ` (${activeSeeds(loadPool(guard, seedsFile)).length}/${policy.seeds.maxActive})` +\n (result.evicted ? ` [evicted ${result.evicted.id}: ${result.evicted.retireReason}]` : ''));\n return 0;\n }\n case 'list': {\n const db = loadPool(guard, seedsFile);\n const items = rest.includes('--archived') ? archivedSeeds(db) : activeSeeds(db);\n for (const s of items) {\n const ageDays = Math.floor((Date.now() - Date.parse(s.bornAt)) / 86_400_000);\n console.log(`${s.id} [${s.tag}/${s.source}] d${ageDays} used:${s.used}` +\n `${s.protected ? ' *' : ''} ${s.text.slice(0, 60)}`);\n }\n if (items.length === 0) console.log('(empty)');\n return 0;\n }\n case 'surface': {\n const s = surfaceSeed(guard, seedsFile, policy, rest[0] ?? '', Date.now(), seedAudit);\n if (!s) {\n console.log('NOT_FOUND');\n return 1;\n }\n console.log(`SURFACED ${s.id} used:${s.used}${s.status === 'archived' ? ' -> archived (consumed)' : ''}`);\n return 0;\n }\n case 'archive': {\n const s = archiveSeedById(guard, seedsFile, rest[0] ?? '', 'completed', Date.now(), seedAudit);\n if (!s) {\n console.log('NOT_FOUND');\n return 1;\n }\n console.log(`ARCHIVED ${s.id}`);\n return 0;\n }\n case 'gc': {\n const report = gcPool(guard, seedsFile, policy, Date.now(), seedAudit);\n console.log(`GC consumed:${report.consumed} expired:${report.expired} cold_bench:${report.coldBench}` +\n ` archive_trimmed:${report.archiveTrimmed} -> active ${report.activeAfter}/${policy.seeds.maxActive}` +\n ` archive ${archivedSeeds(loadPool(guard, seedsFile)).length}/${policy.seeds.archiveCap}`);\n return 0;\n }\n case 'stats': {\n const db = loadPool(guard, seedsFile);\n console.log(JSON.stringify({\n active: activeSeeds(db).length,\n archived: archivedSeeds(db).length,\n cap: policy.seeds.maxActive,\n seq: db.seq,\n }, null, 2));\n return 0;\n }\n default:\n console.error(`unknown seeds subcommand: ${sub}`);\n return 1;\n }\n}\n\nasync function verbLedger(c: CliCtx): Promise<number> {\n const { guard, sub, rest, ledgerFile } = c;\n switch (sub) {\n case 'add': {\n let text = rest.join(' ').trim();\n if (text === '-') text = readStdinText();\n if (!text) {\n console.error('usage: ledger add <text|->');\n return 1;\n }\n const e = appendEntry(guard, ledgerFile, text);\n console.log(`OPEN #${e.id} ${e.text.slice(0, 60)}`);\n return 0;\n }\n case 'list': {\n const { entries } = readLedger(guard, ledgerFile);\n const items = rest.includes('--pending') ? scanPending(guard, ledgerFile) : entries;\n for (const e of items) console.log(`${e.status === 'open' ? ' ' : 'x'} #${e.id} ${e.date} ${e.text.slice(0, 60)}`);\n if (items.length === 0) console.log('(empty)');\n return 0;\n }\n case 'done': {\n const key = rest.join(' ').trim();\n if (!key) {\n console.error('usage: ledger done <id|substring>');\n return 1;\n }\n const e = markDone(guard, ledgerFile, key);\n if (!e) {\n console.log('NOT_FOUND');\n return 1;\n }\n console.log(`DONE #${e.id}`);\n return 0;\n }\n case 'open': {\n const f = ledgerFile;\n if (!fs.existsSync(f)) {\n console.log(`(ledger will be created at ${f})`);\n }\n spawn('cmd', ['/c', 'start', '', f], { detached: true, stdio: 'ignore' }).unref();\n console.log(`opened ${f}`);\n return 0;\n }\n default:\n console.error(`unknown ledger subcommand: ${sub}`);\n return 1;\n }\n}\n\nasync function verbWeekly(c: CliCtx): Promise<number> {\n const { guard, paths, sub, rest } = c;\n const reports = listWeeklyReports(guard, paths.dataDir);\n if (sub === 'list' || sub === undefined) {\n if (reports.length === 0) console.log('(no reports yet — heartbeat generates one every 7 days)');\n for (const r of reports) console.log(`${r.file} ${r.start.slice(0, 10)} ~ ${r.end.slice(0, 10)} [${r.source}]`);\n return 0;\n }\n if (sub === 'show') {\n const file = rest[0] ?? reports[0]?.file;\n if (!file) {\n console.log('(no reports yet)');\n return 1;\n }\n const rep = readWeeklyReport(guard, paths.dataDir, file);\n if (!rep) {\n console.error(`no such report: ${file} (see: weekly list; files live in ${weeklyDirPath(paths.dataDir)})`);\n return 1;\n }\n console.log(`# ${rep.start.slice(0, 10)} ~ ${rep.end.slice(0, 10)} [${rep.source}]`);\n console.log(rep.text);\n return 0;\n }\n console.error(`unknown weekly subcommand: ${sub}`);\n return 1;\n}\n\nasync function verbLogs(c: CliCtx): Promise<number> {\n const { paths, policy, sub, rest, decisionLog } = c;\n if (sub !== 'cleanup') {\n console.error('usage: logs cleanup [--dry-run]');\n return 1;\n }\n const dry = rest.includes('--dry-run');\n const envPulse = path.join(paths.logsDir, 'envpulse.jsonl');\n const cut1 = policy.retention.envPulseHours * 3600_000;\n const cut2 = policy.retention.decisionLogDays * 86_400_000;\n if (dry) {\n console.log(`(dry-run) would prune ${envPulse} to ${policy.retention.envPulseHours}h` +\n ` and ${decisionLog} to ${policy.retention.decisionLogDays}d`);\n return 0;\n }\n const a = pruneAuditFile(envPulse, cut1);\n const b = pruneAuditFile(decisionLog, cut2);\n appendAuditLine(decisionLog, { event: 'retention', pruned_envpulse: a, pruned_decision: b });\n console.log(`PRUNED envpulse:${a} decision:${b}`);\n return 0;\n}\n\nasync function verbBrowse(c: CliCtx): Promise<number> {\n const { guard, paths, policy, sub, rest } = c;\n switch (sub) {\n case 'status': {\n const st = browseStatus(guard, paths);\n const interests = loadInterests(paths);\n console.log(JSON.stringify({\n lastWanderAt: st.wander.last_wander_at ? new Date(st.wander.last_wander_at).toISOString() : null,\n focusCount: st.wander.focusCount,\n interestCount: interests.interests?.length ?? 0,\n }, null, 2));\n return 0;\n }\n case 'dry': {\n const forced = new Date();\n forced.setHours(12, 0, 0, 0);\n const advice = adviseWander(guard, paths, policy, forced);\n console.log(JSON.stringify(advice, null, 2));\n return 0;\n }\n case 'done': {\n const focus = rest.join(' ').trim();\n if (!focus) {\n console.error('usage: browse done <focus>');\n return 1;\n }\n const r = completeWander(guard, paths, focus);\n console.log(JSON.stringify(r));\n return 0;\n }\n default:\n console.error(`unknown browse subcommand: ${sub}`);\n return 1;\n }\n}\n\nasync function verbNotify(c: CliCtx): Promise<number> {\n const { paths, sub } = c;\n switch (sub) {\n case 'check':\n console.log(await ensureRegistered(paths) ? 'REGISTERED: yes' : 'REGISTERED: no');\n return 0;\n case 'register':\n await ensureRegistered(paths);\n console.log('register attempted');\n return 0;\n case 'send':\n console.log(await sendNewMessageHint(paths) ? 'SENT' : 'FAILED');\n return 0;\n default:\n console.error('usage: notify check|register|send');\n return 1;\n }\n}\n\nasync function verbProfile(c: CliCtx): Promise<number> {\n const { guard, paths, sub, rest } = c;\n const doc = loadProfile(guard, profileFilePath(paths.dataDir));\n const all = rest.includes('--all');\n switch (sub) {\n case 'list': {\n let n = 0;\n for (const p of ['interest', 'projects', 'comm', 'psy'] as const) {\n for (const e of doc.partitions[p]!.entries) {\n if (!all && e.validTo !== null) continue;\n n += 1;\n console.log(`${e.id} [${e.partition}/${e.topic}/${e.subTopic}] ${e.temporal}` +\n ` conf=${e.confidence.toFixed(2)}${e.lowActivity ? ' 久未验证' : ''}${e.validTo ? ' [失效]' : ''}: ${e.content.slice(0, 60)}`);\n }\n }\n if (n === 0) console.log('(empty)');\n return 0;\n }\n case 'export': {\n const lines = [`# 画像导出 ${new Date().toISOString()}`, ''];\n for (const p of ['interest', 'projects', 'comm', 'psy'] as const) {\n lines.push(`## ${p}`);\n for (const e of doc.partitions[p]!.entries) {\n if (e.validTo !== null) continue;\n lines.push(`- [${e.topic}/${e.subTopic}] ${e.content} (conf ${e.confidence.toFixed(2)}, ${e.temporal})`);\n }\n }\n const out = path.join(paths.exportsDir, `profile-export-${Date.now()}.md`);\n writeText(guard, out, lines.join('\\n') + '\\n');\n console.log(`EXPORTED: ${out}`);\n return 0;\n }\n case 'verify': {\n const r = verifyProfile(guard, paths.dataDir);\n console.log(JSON.stringify(r, null, 2));\n return r.ok ? 0 : 1;\n }\n case 'rebuild': {\n const r = rebuildProfile(guard, paths.dataDir, { check: rest.includes('--check') });\n console.log(JSON.stringify(r, null, 2));\n return r.ok ? 0 : 1;\n }\n case 'wipe': {\n if (!rest.includes('--yes')) {\n console.log('REFUSED: add --yes to wipe profile data (profile.json/inbox/journal)');\n return 1;\n }\n for (const f of ['profile.json', 'profile_inbox.jsonl', 'profile_journal.jsonl']) {\n const abs = guard.assert(path.join(paths.dataDir, f));\n if (fs.existsSync(abs)) fs.rmSync(abs, { force: true });\n }\n console.log('WIPED (settings preserved; use burn for full shredding)');\n return 0;\n }\n case 'snapshot': {\n const { snapshotDue, snapshotProfile, SNAPSHOT_THRESHOLD } = await import('../profile/snapshot.js');\n const { needed, lines } = snapshotDue(guard, paths.dataDir);\n console.log(`journal ${lines} 条(阈值 ${SNAPSHOT_THRESHOLD})`);\n if (!needed && !rest.includes('--force')) {\n console.log('未到阈值,未执行(加 --force 强制折叠)。');\n return 0;\n }\n const report = snapshotProfile(guard, paths.dataDir);\n if (!report.ok) {\n console.log(`未执行:${report.reason}`);\n return 0;\n }\n console.log(`已折叠 ${report.folded} 条 → 快照(baseline ${report.baselineTs}),归档 ${report.archiveFile},live journal 已清空。`);\n console.log('verify/rebuild 自动从快照基点重放,无需额外操作。');\n return 0;\n }\n default:\n console.error(`unknown profile subcommand: ${sub}`);\n return 1;\n }\n}\n\nasync function verbBurn(c: CliCtx): Promise<number> {\n const { guard, paths, rest } = c;\n const yes = rest.includes('--yes');\n const all = rest.includes('--all');\n const plan = planBurn(guard, paths, all);\n console.log('预演(不会执行):');\n for (const p of plan) console.log(` [${p.exists ? '存在' : '无 '}] ${p.target.file ?? p.target.dir} ${p.target.note}`);\n if (!yes) {\n console.log('\\n此操作会让心跳 agent 失忆。确认执行请加 --yes(' + (all ? '含 --all 连用户设定' : '用户设定保留') + ')');\n return 0;\n }\n const result = executeBurn(guard, paths, { all });\n console.log(`BURNED: ${result.burned.length} 项;MISSING: ${result.missing.length} 项`);\n return 0;\n}\n\nasync function verbMigrate(c: CliCtx): Promise<number> {\n const { guard, paths, sub, rest } = c;\n if (sub === 'export') {\n const defaultOut = path.join(paths.exportsDir, `heartbeat-memory-${new Date().toISOString().slice(0, 10)}.hbmig`);\n const outfile = rest[0] ?? defaultOut;\n let outCanon: string;\n try {\n outCanon = guard.assert(outfile);\n } catch {\n console.error(`导出文件必须落在插件 data/ 目录内(路径守卫拒绝):${outfile}\\n默认位置:${defaultOut}`);\n return 1;\n }\n const [pw1, pw2] = await readLines(['设置口令(用于加密迁移包): ', '再输入一次确认: ']);\n if (!pw1 || pw1 !== pw2) {\n console.error('两次输入不一致或为空,已取消。');\n return 1;\n }\n const { entries, progress } = collectMigrationEntries(guard, paths);\n if (entries.length === 0) {\n console.log('没有可打包的记忆文件(data/ 是空的)。');\n return 1;\n }\n fs.mkdirSync(path.dirname(outCanon), { recursive: true });\n atomicWriteFileSync(outCanon, encryptContainer(entries, pw1));\n console.log(`已打包 ${entries.length} 个文件 → ${outCanon}`);\n console.log(` 打包:${progress.packed.join(', ')}`);\n if (progress.missing.length > 0) console.log(` 跳过(不存在):${progress.missing.join(', ')}`);\n console.log('容器是口令加密的,可安全拷贝到新机器;DPAPI 会在导入时用新机器重新加密。');\n return 0;\n }\n if (sub === 'import') {\n const infile = rest[0];\n if (!infile) {\n console.error('usage: migrate import <container-file>');\n return 1;\n }\n const [pw] = await readLines(['输入迁移包口令: ']);\n let text: string;\n try {\n text = fs.readFileSync(infile, 'utf8');\n } catch {\n console.error(`读不到迁移包:${infile}`);\n return 1;\n }\n let files;\n try {\n files = decryptContainer(text, pw ?? '');\n } catch (e) {\n console.error(String(e instanceof Error ? e.message : e));\n return 1;\n }\n const result = applyMigrationEntries(guard, paths, files.files);\n console.log(`恢复 ${result.restored.length} 个文件;备份 ${result.backedUp.length} 个被覆盖文件;跳过 ${result.skipped.length} 个。`);\n for (const r of result.restored) console.log(` 恢复: ${r}`);\n for (const b of result.backedUp) console.log(` 备份: ${b}.bak-migrate-*`);\n if (result.skipped.length > 0) console.log(` 跳过: ${result.skipped.join(', ')}`);\n if (result.error) console.log(` 失败并已回滚:${result.error}`);\n console.log('重启 DSH 后生效。');\n return result.error ? 1 : 0;\n }\n console.error(`unknown migrate subcommand: ${sub}`);\n return 1;\n}\n\nasync function verbSessions(c: CliCtx): Promise<number> {\n const { guard, paths } = c;\n // Read-only enumeration of the host's persisted sessions (ids from the\n // on-disk store; titles live server-side and are not listed here).\n const root = path.join(os.homedir(), '.dsh', 'sessions');\n let found = 0;\n if (fs.existsSync(root)) {\n const { homeSessionId } = await import('../core/orchestrator.js');\n const own = homeSessionId(guard, paths);\n for (const slug of fs.readdirSync(root)) {\n for (const id of fs.readdirSync(path.join(root, slug))) {\n found += 1;\n const mark = id === own ? ' ← 心跳正身' : '';\n console.log(`${id} [${slug}]${mark}`);\n }\n }\n }\n if (found === 0) console.log('(no persisted sessions found)');\n return 0;\n}\n\nasync function verbBind(c: CliCtx): Promise<number> {\n const { guard, paths, sub, rest } = c;\n const { loadBindings, addBinding, removeBinding } = await import('../core/bindings.js');\n switch (sub) {\n case 'list': {\n const data = loadBindings(guard, paths.settingsDir);\n const { homeSessionId } = await import('../core/orchestrator.js');\n const own = homeSessionId(guard, paths);\n if (own) console.log(`心跳正身: ${own}(决策轮次发生地;bind remove 它 = 重置正身)`);\n for (const b of data.bindings) {\n console.log(`${b.sessionId} deliver:${b.deliver ? '√' : '×'} observe:${b.observe ? '√' : '×'}`);\n }\n if (data.bindings.length === 0 && !own) console.log('(no bindings — expressions stay in the dedicated heartbeat session)');\n return 0;\n }\n case 'add': {\n const id = rest[0];\n if (!id || !id.startsWith('session-')) {\n console.error('usage: bind add <sessionId> [--observe] [--no-deliver] (see: sessions list)');\n return 1;\n }\n const observe = rest.includes('--observe') || rest.includes('--observe-only');\n const deliver = !rest.includes('--no-deliver') && !rest.includes('--observe-only');\n const b = addBinding(guard, paths.settingsDir, id, { deliver, observe });\n console.log(`BOUND ${b.sessionId} deliver:${b.deliver} observe:${b.observe}`);\n return 0;\n }\n case 'remove': {\n const id = rest[0];\n if (!id) {\n console.error('usage: bind remove <sessionId>');\n return 1;\n }\n console.log(removeBinding(guard, paths.settingsDir, id) ? `UNBOUND ${id}` : 'NOT_FOUND');\n // Unbinding the HOME session resets it: the next beat creates a fresh\n // dedicated session (the old one goes quiet after restart). H-09/H-45:\n // the shared path also drops the orchestrator's cached agent — the\n // inline delete here used to leave it pointing at the released session.\n const { resetHomeSession } = await import('../core/orchestrator.js');\n if (resetHomeSession(guard, paths, id)) {\n console.log('注意:这是心跳正身会话。已重置——下次心跳将创建新的正身会话(旧会话不再有心跳)');\n }\n return 0;\n }\n default:\n console.error('usage: bind list | add <sessionId> | remove <sessionId>');\n return 1;\n }\n}\n\nasync function verbPreset(c: CliCtx): Promise<number> {\n const { sub, rest, argv } = c;\n const id = flag(argv, '--id') ?? BUNDLED_PRESET_ID;\n // The plugin installs into the roster's own user root; the CLI has no\n // roster, so it reports/uses the conventional one ($DSH_HOME or ~/.dsh).\n const root = conventionalUserPresetRoot();\n const status = presetStatus(import.meta.url, id, root);\n if (sub === undefined || sub === 'status') {\n console.log(`preset id : ${status.id}`);\n console.log(`installed : ${status.installed ? 'yes' : 'no'}`);\n console.log(`target dir : ${status.dir}`);\n console.log(`bundled at : ${status.bundledDir ?? '(not found next to the plugin)'}`);\n if (status.installed) {\n console.log(\n `composition : ${status.compositionMatches ? 'matches the bundled template' : 'differs from the bundled template (hand-edited, or an older version)'}`,\n );\n }\n if (!status.installed) {\n console.log('hint: the plugin installs this itself on the next DSH start (installPreset=true, default);');\n console.log(' or run `preset install` now.');\n }\n return status.installed ? 0 : 1;\n }\n if (sub === 'install') {\n const result = installBundledPreset({\n moduleUrl: import.meta.url,\n id,\n root,\n force: rest.includes('--force'),\n });\n console.log(describeInstall(result));\n return result.action === 'error' ? 1 : 0;\n }\n console.error('usage: preset status | install [--force] [--id <presetId>]');\n return 1;\n}\n\n/** Command table. Adding a verb = one function above plus one line here. */\nconst VERBS: Record<string, Verb> = {\n status: verbStatus,\n seeds: verbSeeds,\n ledger: verbLedger,\n weekly: verbWeekly,\n logs: verbLogs,\n browse: verbBrowse,\n notify: verbNotify,\n profile: verbProfile,\n burn: verbBurn,\n migrate: verbMigrate,\n sessions: verbSessions,\n bind: verbBind,\n preset: verbPreset,\n};\n\nexport async function main(argv: string[]): Promise<number> {\n const [cmd, sub, ...rest] = argv;\n if (!cmd || cmd === 'help' || cmd === '--help') {\n console.log(usage());\n return 0;\n }\n const verb = VERBS[cmd];\n if (!verb) {\n console.error(`unknown command: ${cmd}`);\n console.log(usage());\n return 1;\n }\n const paths = initWorkspace();\n const guard = createPathGuard(paths.dataDir);\n const policy = loadPolicy(guard, paths.configDir, paths.settingsDir);\n const decisionLog = path.join(paths.logsDir, 'heartbeat.jsonl');\n /** Seed lifecycle audit (v1.9.0): CLI edits land in the same log as the beat's. */\n const seedAudit = (entry: Record<string, unknown>): void => {\n try {\n appendAuditLine(decisionLog, entry);\n } catch { /* audit must never break the command */ }\n };\n return verb({\n paths,\n guard,\n policy,\n sub,\n rest,\n argv,\n seedsFile: seedsFilePath(paths.dataDir),\n ledgerFile: ledgerFilePath(paths.dataDir),\n decisionLog,\n seedAudit,\n });\n}\n\nif (process.argv[1] && import.meta.url === new URL(`file:///${process.argv[1].replace(/\\\\/g, '/')}`).href) {\n // Direct execution guard; the CLI is also importable for tests.\n void main(process.argv.slice(2))\n .then((code) => { process.exitCode = code; })\n .catch((e: unknown) => {\n // H-44: no unhandled rejection — print and exit non-zero.\n console.error(e);\n process.exitCode = 1;\n });\n}\n","// Burn list - SINGLE SOURCE OF TRUTH (design doc §10.10; v1 shipped two\r\n// hardcoded lists and one drifted). burn and uninstall --purge both consume\r\n// this list. Settings (data/settings/) are NOT burned by default: losing\r\n// memory != losing the charter/gates the user configured (--all overrides).\r\n\r\nimport fs from 'node:fs';\r\nimport path from 'node:path';\r\nimport type { PathGuard } from '../core/path-guard.js';\r\nimport type { WorkspacePaths } from '../core/paths.js';\r\nimport { shredFileSync } from '../core/atomic-fs.js';\r\nimport { appendAuditLine } from '../core/audit-log.js';\r\n\r\nexport interface BurnTarget {\r\n /** Relative to dataDir. Files are shredded (overwrite x3) then deleted. */\r\n file?: string;\r\n /** Every dataDir file whose name starts with this prefix — a family of\r\n * timestamped files a bare `file` cannot name (journal archive shards).\r\n * Shredded like files. */\r\n prefix?: string;\r\n /** Directories are removed recursively (no shred - content is files). */\r\n dir?: string;\r\n note: string;\r\n}\r\n\r\nexport const BURN_LIST: BurnTarget[] = [\r\n { file: 'profile.json', note: '画像物化视图' },\r\n { file: 'profile_inbox.jsonl', note: '观察收件箱' },\r\n { file: 'profile_journal.jsonl', note: '画像操作流水' },\r\n // H-19: the rotation shards hold the whole profile history and are written\r\n // in PLAINTEXT — a burn that leaves them behind leaves the memory readable.\r\n { prefix: 'profile_journal.archive-', note: '画像流水归档分片(明文;journal 轮转产物)' },\r\n { file: 'profile_rhythm.json', note: '作息聚合(纯统计)' },\r\n { file: 'screen.json', note: '屏幕快照(加密)' },\r\n { file: 'screen.jpg', note: '截图(加密)' },\r\n { file: 'sent.json', note: '表达记录(加密)' },\r\n { file: 'browse.json', note: '浏览流状态(加密)' },\r\n { file: 'seeds.jsonl', note: '素材池(加密)' },\r\n { file: 'ledger.md', note: '账本(明文,人可读是设计目标)' },\r\n { file: 'envpulse.json', note: '环境温度计快照' },\r\n { file: 'gate.json', note: '闸门运行时计数' },\r\n // v1.9.0 completion (H-19): these carry memory just as much as the rows\r\n // above — the persona report log records WHAT SHE SAID (spoken / seed_ids /\r\n // profile_ids / reason), so a burn that skips it is a burn that lies.\r\n { file: 'profile_snapshot.json', note: '画像快照(journal 轮转基线)' },\r\n { file: 'cursors.json', note: '观察游标(会话事件位点)' },\r\n { file: 'seed_report.jsonl', note: '投递报账日志(加密)' },\r\n { file: 'preference.json', note: '话题偏好统计' },\r\n { dir: 'weekly', note: '周报(画像与素材散文)' },\r\n { dir: 'tmp', note: '解锁临时文件(崩溃残留的解密明文是最该烧的东西)' },\r\n { dir: 'logs', note: '审计与决策日志' },\r\n { dir: 'exports', note: '导出产物' },\r\n];\r\n\r\nconst SETTINGS_DIR = 'settings'; // excluded unless --all\r\n\r\n/** dataDir files matching a prefix target, name-sorted for stable output. */\r\nfunction prefixMatches(guard: PathGuard, paths: WorkspacePaths, prefix: string): string[] {\r\n try {\r\n return fs.readdirSync(guard.assert(paths.dataDir))\r\n .filter((f) => f.startsWith(prefix))\r\n .sort();\r\n } catch {\r\n return [];\r\n }\r\n}\r\n\r\nexport interface BurnPlanItem {\r\n target: BurnTarget;\r\n exists: boolean;\r\n}\r\n\r\n/** Preview: what exists, what would be removed. No writes. */\r\nexport function planBurn(guard: PathGuard, paths: WorkspacePaths, all = false): BurnPlanItem[] {\r\n const plan: BurnPlanItem[] = [];\r\n for (const t of BURN_LIST) {\r\n const rel = t.file ?? t.dir ?? t.prefix ?? '';\r\n if (!all && rel === SETTINGS_DIR) continue;\r\n let exists = false;\r\n if (t.prefix) {\r\n exists = prefixMatches(guard, paths, t.prefix).length > 0;\r\n } else {\r\n try {\r\n exists = fs.existsSync(guard.assert(path.join(paths.dataDir, rel)));\r\n } catch {\r\n exists = false;\r\n }\r\n }\r\n plan.push({ target: t, exists });\r\n }\r\n if (all) {\r\n plan.push({ target: { dir: SETTINGS_DIR, note: '用户设定(隐私宪章/闸门参数)——仅 --all 连带' }, exists: fs.existsSync(paths.settingsDir) });\r\n }\r\n return plan;\r\n}\r\n\r\n/**\r\n * Execute the burn: overwrite x3 + delete files, remove dirs. Irreversible.\r\n * Returns per-target results and writes a BURN_EVENT into the (recreated)\r\n * journal afterwards - the only trace, on purpose (transparency).\r\n */\r\nexport function executeBurn(\r\n guard: PathGuard,\r\n paths: WorkspacePaths,\r\n opts: { all?: boolean; shredPasses?: number } = {},\r\n): { burned: string[]; missing: string[] } {\r\n const burned: string[] = [];\r\n const missing: string[] = [];\r\n const passes = opts.shredPasses ?? 3;\r\n for (const t of BURN_LIST) {\r\n // H-19: a prefix target is a family of files (timestamped archive shards);\r\n // shred every match individually.\r\n if (t.prefix) {\r\n const matches = prefixMatches(guard, paths, t.prefix);\r\n if (matches.length === 0) {\r\n missing.push(`${t.prefix}*`);\r\n continue;\r\n }\r\n for (const f of matches) {\r\n try {\r\n shredFileSync(guard.assert(path.join(paths.dataDir, f)), passes);\r\n burned.push(f);\r\n } catch { /* vanished between listing and shredding: not fatal */ }\r\n }\r\n continue;\r\n }\r\n const rel = t.file ?? t.dir!;\r\n const abs = path.join(paths.dataDir, rel);\r\n let absCanon: string;\r\n try {\r\n absCanon = guard.assert(abs);\r\n } catch {\r\n missing.push(rel);\r\n continue;\r\n }\r\n if (t.file) {\r\n if (fs.existsSync(absCanon)) {\r\n shredFileSync(absCanon, passes);\r\n burned.push(rel);\r\n } else {\r\n missing.push(rel);\r\n }\r\n } else if (fs.existsSync(absCanon)) {\r\n fs.rmSync(absCanon, { recursive: true, force: true });\r\n burned.push(rel);\r\n } else {\r\n missing.push(rel);\r\n }\r\n }\r\n if (opts.all) {\r\n fs.rmSync(paths.settingsDir, { recursive: true, force: true });\r\n burned.push(SETTINGS_DIR);\r\n }\r\n // BURN_EVENT: recreate the journal; data dir is now re-initializable.\r\n appendAuditLine(guard.assert(path.join(paths.dataDir, 'profile_journal.jsonl')), {\r\n event: 'BURN_EVENT',\r\n burned: burned.length,\r\n missing: missing.length,\r\n settingsPreserved: !opts.all,\r\n });\r\n return { burned, missing };\r\n}\r\n"],"mappings":"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","names":["fs","path","fs","path"]}
1
+ {"version":3,"sources":["../../src/cli/index.ts","../../src/vault/burn-list.ts"],"sourcesContent":["// Operational CLI (design doc §14). Commands grow per module.\n// Run: node dist/cli/index.js <command> [args] (or via tsx in dev)\n//\n// H-42: `main` used to be a 530-line function with a switch holding every\n// verb's body. The verbs are module-level functions now (see CliCtx below) and\n// `main` only builds the shared context and dispatches — one place to add a\n// command, and each verb is readable on its own.\n\nimport { spawn } from 'node:child_process';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { dshHomeDir, initWorkspace } from '../core/paths.js';\nimport type { WorkspacePaths } from '../core/paths.js';\nimport { createPathGuard } from '../core/path-guard.js';\nimport type { PathGuard } from '../core/path-guard.js';\nimport { appendAuditLine, pruneAuditFile } from '../core/audit-log.js';\nimport { atomicWriteFileSync } from '../core/atomic-fs.js';\nimport { loadPolicy } from '../config/load.js';\nimport type { Policy } from '../config/schema.js';\nimport {\n addSeed,\n archiveSeedById,\n gcPool,\n loadPool,\n activeSeeds,\n archivedSeeds,\n seedsFilePath,\n surfaceSeed,\n} from '../seeds/pool.js';\nimport type { SeedSource, SeedTag } from '../seeds/types.js';\nimport {\n appendEntry,\n ledgerFilePath,\n markDone,\n readLedger,\n scanPending,\n} from '../ledger/ledger.js';\nimport {\n EXCERPT_HEADER,\n appendExcerpt,\n excerptFilePath,\n readExcerpts,\n removeExcerpt,\n} from '../excerpt/excerpt.js';\nimport {\n adviseWander,\n browseStatus,\n completeWander,\n loadInterests,\n} from '../browse/browse.js';\nimport { ensureRegistered, sendNewMessageHint } from '../notify/notify.js';\nimport {\n loadProfile,\n profileFilePath,\n verifyProfile,\n rebuildProfile,\n wipeProfile,\n} from '../profile/store.js';\nimport { planBurn, executeBurn } from '../vault/burn-list.js';\nimport {\n collectMigrationEntries,\n encryptContainer,\n decryptContainer,\n applyMigrationEntries,\n} from '../vault/migrate.js';\nimport { listWeeklyReports, readWeeklyReport, weeklyDirPath } from '../weekly/report.js';\nimport {\n containerKind,\n upgradeVaultTree,\n vaultKeyPath,\n writeText,\n} from '../vault/vault.js';\nimport { matchFilesRecursive } from '../core/fs-walk.js';\nimport {\n BUNDLED_PRESET_ID,\n conventionalUserPresetRoot,\n describeInstall,\n installBundledPreset,\n presetStatus,\n} from '../core/preset-install.js';\n\nfunction usage(): string {\n return [\n 'usage: heartbeat <command> [args]',\n '',\n 'commands:',\n ' status workspace paths + policy summary',\n ' seeds add <text> [--tag t] [--source s] [--topic x] [--confidence n]',\n ' seeds list [--archived] list active (or archived) seeds',\n ' seeds surface <id> count a surfacing (rule 1 accounting)',\n ' seeds archive <id> deliberate retirement (completed)',\n ' seeds gc run deterministic eviction rules 1-3',\n ' seeds stats pool status JSON',\n ' ledger add <text> register an open item',\n ' ledger list [--pending] list entries',\n ' ledger done <id|substring> mark an entry done',\n ' ledger open open ledger.md in the default editor',\n ' excerpt add <text> keep a line in the notebook',\n ' excerpt list [n] list entries (newest n if given)',\n ' excerpt remove <id|substring> tear a page out',\n ' excerpt open open excerpts.md in the default editor',\n ' logs cleanup [--dry-run] apply log retention now',\n ' browse status browse state summary (wander)',\n ' browse dry wander adjudication with forced noon window',\n ' browse done <focus> CODE-side registration after a wander visit',\n ' bind list list session bindings (D13)',\n ' bind add <sessionId> [--observe] bind a session (deliver by default)',\n ' bind remove <sessionId> unbind a session',\n ' sessions list enumerate persisted sessions (ids)',\n ' notify check|register|send toast channel (D12: hint only, no body)',\n ' profile list [--all] current valid (or all incl. expired) entries',\n ' profile export decrypted Markdown export to data/exports/',\n ' profile verify journal replay vs disk (report only)',\n ' profile rebuild [--check] rebuild materialized view from journal',\n ' profile snapshot [--force] fold the journal into a snapshot + archive shard',\n ' profile wipe wipe profile data (asks --yes)',\n ' weekly list list generated weekly reports',\n ' weekly show [file] print a report (default: newest)',\n ' vault status encryption containers on disk + master key file',\n ' vault upgrade rewrite legacy KHBV1 files as KHBV2 (in place)',\n ' migrate export [file] pack memory files into a passphrase container (passphrase: 2 stdin lines)',\n ' migrate import <file> restore a container into this workspace (passphrase: 1 stdin line)',\n ' burn [--yes] [--all] shred runtime data (settings kept unless --all)',\n ' preset status bundled agent preset: target dir + installed?',\n ' preset install [--force] install the bundled preset (never overwrites unless --force)',\n ].join('\\n');\n}\n\nfunction readStdinText(): string {\n try {\n return fs.readFileSync(0, 'utf8').trim();\n } catch {\n return '';\n }\n}\n\nfunction flag(argv: string[], name: string): string | undefined {\n const i = argv.indexOf(name);\n return i > -1 ? argv[i + 1] : undefined;\n}\n\n/** H-42: the seed flags used to be written `flag(rest, '--tag') as never` — the\n * escape hatch threw the type away, so a typo landed in the seed record\n * unchecked. Validate against the known sets instead (the `satisfies` clauses\n * keep these lists in step with the types). */\nconst SEED_TAGS = ['news', 'fandom', 'scene', 'promise'] as const satisfies readonly SeedTag[];\nconst SEED_SOURCES = ['chat', 'screen', 'browse', 'hand', 'profile'] as const satisfies readonly SeedSource[];\n\nfunction flagOneOf<T extends string>(argv: string[], name: string, allowed: readonly T[]): T | undefined {\n const v = flag(argv, name);\n if (v === undefined) return undefined;\n return (allowed as readonly string[]).includes(v) ? (v as T) : undefined;\n}\n\n/** Read N lines from stdin (passphrase prompts for migrate). */\nasync function readLines(prompts: string[]): Promise<string[]> {\n const readline = await import('node:readline/promises');\n const it = readline.createInterface({ input: process.stdin });\n const out: string[] = [];\n for (const p of prompts) out.push((await it.question(p)).trim());\n it.close();\n return out;\n}\n\n/** Everything a verb needs. Built once in {@link main}; `sub`/`rest` are the\n * positional split of argv, `argv` stays available for top-level flags. */\ninterface CliCtx {\n paths: WorkspacePaths;\n guard: PathGuard;\n policy: Policy;\n sub: string | undefined;\n rest: string[];\n argv: string[];\n seedsFile: string;\n ledgerFile: string;\n excerptFile: string;\n decisionLog: string;\n seedAudit: (entry: Record<string, unknown>) => void;\n}\n\ntype Verb = (c: CliCtx) => Promise<number>;\n\nasync function verbStatus(c: CliCtx): Promise<number> {\n const { paths, policy } = c;\n console.log(JSON.stringify({\n dataDir: paths.dataDir,\n heartbeatIntervalMin: policy.heartbeat.intervalMin,\n maxDailySend: policy.gate.maxDailySend,\n seedsMaxActive: policy.seeds.maxActive,\n psyEnabled: policy.profile.psyEnabled,\n }, null, 2));\n return 0;\n}\n\nasync function verbSeeds(c: CliCtx): Promise<number> {\n const { guard, policy, sub, rest, seedsFile, seedAudit } = c;\n switch (sub) {\n case 'add': {\n let text = rest[0]?.trim() ?? '';\n if (text === '-') text = readStdinText();\n if (!text) {\n console.error('usage: seeds add <text|-> [--tag t] [--source s] [--topic x] [--confidence n]');\n return 1;\n }\n const result = addSeed(guard, seedsFile, policy, {\n text,\n tag: flagOneOf(rest, '--tag', SEED_TAGS),\n source: flagOneOf(rest, '--source', SEED_SOURCES),\n topic: flag(rest, '--topic'),\n confidence: flag(rest, '--confidence') ? Number(flag(rest, '--confidence')) : undefined,\n }, Date.now(), seedAudit);\n if (result.kind === 'duplicate') {\n console.log(`DUPLICATE: active seed ${result.seed.id} has the same text`);\n return 0;\n }\n console.log(`${result.kind.toUpperCase()} ${result.seed.id}` +\n ` (${activeSeeds(loadPool(guard, seedsFile)).length}/${policy.seeds.maxActive})` +\n (result.evicted ? ` [evicted ${result.evicted.id}: ${result.evicted.retireReason}]` : ''));\n return 0;\n }\n case 'list': {\n const db = loadPool(guard, seedsFile);\n const items = rest.includes('--archived') ? archivedSeeds(db) : activeSeeds(db);\n for (const s of items) {\n const ageDays = Math.floor((Date.now() - Date.parse(s.bornAt)) / 86_400_000);\n console.log(`${s.id} [${s.tag}/${s.source}] d${ageDays} used:${s.used}` +\n `${s.protected ? ' *' : ''} ${s.text.slice(0, 60)}`);\n }\n if (items.length === 0) console.log('(empty)');\n return 0;\n }\n case 'surface': {\n const s = surfaceSeed(guard, seedsFile, policy, rest[0] ?? '', Date.now(), seedAudit);\n if (!s) {\n console.log('NOT_FOUND');\n return 1;\n }\n console.log(`SURFACED ${s.id} used:${s.used}${s.status === 'archived' ? ' -> archived (consumed)' : ''}`);\n return 0;\n }\n case 'archive': {\n const s = archiveSeedById(guard, seedsFile, rest[0] ?? '', 'completed', Date.now(), seedAudit);\n if (!s) {\n console.log('NOT_FOUND');\n return 1;\n }\n console.log(`ARCHIVED ${s.id}`);\n return 0;\n }\n case 'gc': {\n const report = gcPool(guard, seedsFile, policy, Date.now(), seedAudit);\n console.log(`GC consumed:${report.consumed} expired:${report.expired} cold_bench:${report.coldBench}` +\n ` archive_trimmed:${report.archiveTrimmed} -> active ${report.activeAfter}/${policy.seeds.maxActive}` +\n ` archive ${archivedSeeds(loadPool(guard, seedsFile)).length}/${policy.seeds.archiveCap}`);\n return 0;\n }\n case 'stats': {\n const db = loadPool(guard, seedsFile);\n console.log(JSON.stringify({\n active: activeSeeds(db).length,\n archived: archivedSeeds(db).length,\n cap: policy.seeds.maxActive,\n seq: db.seq,\n }, null, 2));\n return 0;\n }\n default:\n console.error(`unknown seeds subcommand: ${sub}`);\n return 1;\n }\n}\n\nasync function verbLedger(c: CliCtx): Promise<number> {\n const { guard, sub, rest, ledgerFile } = c;\n switch (sub) {\n case 'add': {\n let text = rest.join(' ').trim();\n if (text === '-') text = readStdinText();\n if (!text) {\n console.error('usage: ledger add <text|->');\n return 1;\n }\n const e = appendEntry(guard, ledgerFile, text);\n console.log(`OPEN #${e.id} ${e.text.slice(0, 60)}`);\n return 0;\n }\n case 'list': {\n const { entries } = readLedger(guard, ledgerFile);\n const items = rest.includes('--pending') ? scanPending(guard, ledgerFile) : entries;\n for (const e of items) console.log(`${e.status === 'open' ? ' ' : 'x'} #${e.id} ${e.date} ${e.text.slice(0, 60)}`);\n if (items.length === 0) console.log('(empty)');\n return 0;\n }\n case 'done': {\n const key = rest.join(' ').trim();\n if (!key) {\n console.error('usage: ledger done <id|substring>');\n return 1;\n }\n const e = markDone(guard, ledgerFile, key);\n if (!e) {\n console.log('NOT_FOUND');\n return 1;\n }\n console.log(`DONE #${e.id}`);\n return 0;\n }\n case 'open': {\n const f = ledgerFile;\n if (!fs.existsSync(f)) {\n console.log(`(ledger will be created at ${f})`);\n }\n spawn('cmd', ['/c', 'start', '', f], { detached: true, stdio: 'ignore' }).unref();\n console.log(`opened ${f}`);\n return 0;\n }\n default:\n console.error(`unknown ledger subcommand: ${sub}`);\n return 1;\n }\n}\n\nasync function verbExcerpt(c: CliCtx): Promise<number> {\n const { guard, sub, rest, excerptFile } = c;\n switch (sub) {\n case 'add': {\n let text = rest.join(' ').trim();\n if (text === '-') text = readStdinText();\n if (!text) {\n console.error('usage: excerpt add <text|->');\n return 1;\n }\n const e = appendExcerpt(guard, excerptFile, text);\n console.log(`KEPT #${e.id} ${e.text.slice(0, 60)}`);\n return 0;\n }\n case 'list': {\n const all = readExcerpts(guard, excerptFile).entries;\n const n = Number.parseInt(rest[0] ?? '', 10);\n const items = Number.isFinite(n) && n > 0 ? all.slice(-n) : all;\n for (const e of items) console.log(`#${e.id} ${e.date} ${e.time} ${e.text.slice(0, 60)}`);\n if (items.length === 0) console.log('(empty)');\n return 0;\n }\n case 'remove': {\n const key = rest.join(' ').trim();\n if (!key) {\n console.error('usage: excerpt remove <id|substring>');\n return 1;\n }\n const e = removeExcerpt(guard, excerptFile, key);\n if (!e) {\n console.log('NOT_FOUND');\n return 1;\n }\n console.log(`REMOVED #${e.id}`);\n return 0;\n }\n case 'open': {\n const f = excerptFile;\n if (!fs.existsSync(f)) {\n fs.mkdirSync(path.dirname(f), { recursive: true });\n fs.writeFileSync(f, EXCERPT_HEADER, 'utf8');\n }\n spawn('cmd', ['/c', 'start', '', f], { detached: true, stdio: 'ignore' }).unref();\n console.log(`opened ${f}`);\n return 0;\n }\n default:\n console.error(`unknown excerpt subcommand: ${sub}`);\n return 1;\n }\n}\n\nasync function verbWeekly(c: CliCtx): Promise<number> {\n const { guard, paths, sub, rest } = c;\n const reports = listWeeklyReports(guard, paths.dataDir);\n if (sub === 'list' || sub === undefined) {\n if (reports.length === 0) console.log('(no reports yet — heartbeat generates one every 7 days)');\n for (const r of reports) console.log(`${r.file} ${r.start.slice(0, 10)} ~ ${r.end.slice(0, 10)} [${r.source}]`);\n return 0;\n }\n if (sub === 'show') {\n const file = rest[0] ?? reports[0]?.file;\n if (!file) {\n console.log('(no reports yet)');\n return 1;\n }\n const rep = readWeeklyReport(guard, paths.dataDir, file);\n if (!rep) {\n console.error(`no such report: ${file} (see: weekly list; files live in ${weeklyDirPath(paths.dataDir)})`);\n return 1;\n }\n console.log(`# ${rep.start.slice(0, 10)} ~ ${rep.end.slice(0, 10)} [${rep.source}]`);\n console.log(rep.text);\n return 0;\n }\n console.error(`unknown weekly subcommand: ${sub}`);\n return 1;\n}\n\nasync function verbLogs(c: CliCtx): Promise<number> {\n const { paths, policy, sub, rest, decisionLog } = c;\n if (sub !== 'cleanup') {\n console.error('usage: logs cleanup [--dry-run]');\n return 1;\n }\n const dry = rest.includes('--dry-run');\n const envPulse = path.join(paths.logsDir, 'envpulse.jsonl');\n const cut1 = policy.retention.envPulseHours * 3600_000;\n const cut2 = policy.retention.decisionLogDays * 86_400_000;\n if (dry) {\n console.log(`(dry-run) would prune ${envPulse} to ${policy.retention.envPulseHours}h` +\n ` and ${decisionLog} to ${policy.retention.decisionLogDays}d`);\n return 0;\n }\n const a = pruneAuditFile(envPulse, cut1);\n const b = pruneAuditFile(decisionLog, cut2);\n appendAuditLine(decisionLog, { event: 'retention', pruned_envpulse: a, pruned_decision: b });\n console.log(`PRUNED envpulse:${a} decision:${b}`);\n return 0;\n}\n\nasync function verbBrowse(c: CliCtx): Promise<number> {\n const { guard, paths, policy, sub, rest } = c;\n switch (sub) {\n case 'status': {\n const st = browseStatus(guard, paths);\n const interests = loadInterests(paths);\n console.log(JSON.stringify({\n lastWanderAt: st.wander.last_wander_at ? new Date(st.wander.last_wander_at).toISOString() : null,\n focusCount: st.wander.focusCount,\n interestCount: interests.interests?.length ?? 0,\n }, null, 2));\n return 0;\n }\n case 'dry': {\n const forced = new Date();\n forced.setHours(12, 0, 0, 0);\n const advice = adviseWander(guard, paths, policy, forced);\n console.log(JSON.stringify(advice, null, 2));\n return 0;\n }\n case 'done': {\n const focus = rest.join(' ').trim();\n if (!focus) {\n console.error('usage: browse done <focus>');\n return 1;\n }\n const r = completeWander(guard, paths, focus);\n console.log(JSON.stringify(r));\n return 0;\n }\n default:\n console.error(`unknown browse subcommand: ${sub}`);\n return 1;\n }\n}\n\nasync function verbNotify(c: CliCtx): Promise<number> {\n const { paths, sub } = c;\n switch (sub) {\n case 'check':\n console.log(await ensureRegistered(paths) ? 'REGISTERED: yes' : 'REGISTERED: no');\n return 0;\n case 'register':\n await ensureRegistered(paths);\n console.log('register attempted');\n return 0;\n case 'send':\n console.log(await sendNewMessageHint(paths) ? 'SENT' : 'FAILED');\n return 0;\n default:\n console.error('usage: notify check|register|send');\n return 1;\n }\n}\n\nasync function verbProfile(c: CliCtx): Promise<number> {\n const { guard, paths, sub, rest } = c;\n const doc = loadProfile(guard, profileFilePath(paths.dataDir));\n const all = rest.includes('--all');\n switch (sub) {\n case 'list': {\n let n = 0;\n for (const p of ['interest', 'projects', 'comm', 'psy'] as const) {\n for (const e of doc.partitions[p]!.entries) {\n if (!all && e.validTo !== null) continue;\n n += 1;\n console.log(`${e.id} [${e.partition}/${e.topic}/${e.subTopic}] ${e.temporal}` +\n ` conf=${e.confidence.toFixed(2)}${e.lowActivity ? ' 久未验证' : ''}${e.validTo ? ' [失效]' : ''}: ${e.content.slice(0, 60)}`);\n }\n }\n if (n === 0) console.log('(empty)');\n return 0;\n }\n case 'export': {\n const lines = [`# 画像导出 ${new Date().toISOString()}`, ''];\n for (const p of ['interest', 'projects', 'comm', 'psy'] as const) {\n lines.push(`## ${p}`);\n for (const e of doc.partitions[p]!.entries) {\n if (e.validTo !== null) continue;\n lines.push(`- [${e.topic}/${e.subTopic}] ${e.content} (conf ${e.confidence.toFixed(2)}, ${e.temporal})`);\n }\n }\n const out = path.join(paths.exportsDir, `profile-export-${Date.now()}.md`);\n writeText(guard, out, lines.join('\\n') + '\\n');\n console.log(`EXPORTED: ${out}`);\n return 0;\n }\n case 'verify': {\n const r = verifyProfile(guard, paths.dataDir);\n console.log(JSON.stringify(r, null, 2));\n return r.ok ? 0 : 1;\n }\n case 'rebuild': {\n const r = rebuildProfile(guard, paths.dataDir, { check: rest.includes('--check') });\n console.log(JSON.stringify(r, null, 2));\n return r.ok ? 0 : 1;\n }\n case 'wipe': {\n if (!rest.includes('--yes')) {\n console.log('REFUSED: add --yes to wipe profile data (live files, snapshot, journal archives, migration copies)');\n return 1;\n }\n // HB-21: the snapshot and the archive shards replay into the profile, so\n // the old three-file wipe was undone by the next rebuild (and migration\n // backups held yet another copy). wipeProfile covers everything the\n // profile can be rebuilt from — see its comment in profile/store.ts.\n const removed = wipeProfile(guard, paths.dataDir);\n console.log(`WIPED ${removed.length} file(s) (settings preserved; use burn for full shredding)`);\n for (const f of removed) console.log(` - ${f}`);\n return 0;\n }\n case 'snapshot': {\n const { snapshotDue, snapshotProfile, SNAPSHOT_THRESHOLD } = await import('../profile/snapshot.js');\n const { needed, lines } = snapshotDue(guard, paths.dataDir);\n console.log(`journal ${lines} 条(阈值 ${SNAPSHOT_THRESHOLD})`);\n if (!needed && !rest.includes('--force')) {\n console.log('未到阈值,未执行(加 --force 强制折叠)。');\n return 0;\n }\n const report = snapshotProfile(guard, paths.dataDir);\n if (!report.ok) {\n console.log(`未执行:${report.reason}`);\n return 0;\n }\n console.log(`已折叠 ${report.folded} 条 → 快照(baseline ${report.baselineTs}),归档 ${report.archiveFile},live journal 已清空。`);\n console.log('verify/rebuild 自动从快照基点重放,无需额外操作。');\n return 0;\n }\n default:\n console.error(`unknown profile subcommand: ${sub}`);\n return 1;\n }\n}\n\nasync function verbBurn(c: CliCtx): Promise<number> {\n const { guard, paths, rest } = c;\n const yes = rest.includes('--yes');\n const all = rest.includes('--all');\n const plan = planBurn(guard, paths, all);\n console.log('预演(不会执行):');\n for (const p of plan) console.log(` [${p.exists ? '存在' : '无 '}] ${p.target.file ?? p.target.dir} ${p.target.note}`);\n if (!yes) {\n console.log('\\n此操作会让心跳 agent 失忆。确认执行请加 --yes(' + (all ? '含 --all 连用户设定' : '用户设定保留') + ')');\n return 0;\n }\n const result = executeBurn(guard, paths, { all });\n console.log(`BURNED: ${result.burned.length} 项;MISSING: ${result.missing.length} 项`);\n return 0;\n}\n\nasync function verbMigrate(c: CliCtx): Promise<number> {\n const { guard, paths, sub, rest } = c;\n if (sub === 'export') {\n const defaultOut = path.join(paths.exportsDir, `heartbeat-memory-${new Date().toISOString().slice(0, 10)}.hbmig`);\n const outfile = rest[0] ?? defaultOut;\n let outCanon: string;\n try {\n outCanon = guard.assert(outfile);\n } catch {\n console.error(`导出文件必须落在插件 data/ 目录内(路径守卫拒绝):${outfile}\\n默认位置:${defaultOut}`);\n return 1;\n }\n const [pw1, pw2] = await readLines(['设置口令(用于加密迁移包): ', '再输入一次确认: ']);\n if (!pw1 || pw1 !== pw2) {\n console.error('两次输入不一致或为空,已取消。');\n return 1;\n }\n const { entries, progress } = collectMigrationEntries(guard, paths);\n if (entries.length === 0) {\n console.log('没有可打包的记忆文件(data/ 是空的)。');\n return 1;\n }\n fs.mkdirSync(path.dirname(outCanon), { recursive: true });\n atomicWriteFileSync(outCanon, encryptContainer(entries, pw1));\n console.log(`已打包 ${entries.length} 个文件 → ${outCanon}`);\n console.log(` 打包:${progress.packed.join(', ')}`);\n if (progress.missing.length > 0) console.log(` 跳过(不存在):${progress.missing.join(', ')}`);\n console.log('容器是口令加密的,可安全拷贝到新机器;DPAPI 会在导入时用新机器重新加密。');\n return 0;\n }\n if (sub === 'import') {\n const infile = rest[0];\n if (!infile) {\n console.error('usage: migrate import <container-file>');\n return 1;\n }\n const [pw] = await readLines(['输入迁移包口令: ']);\n let text: string;\n try {\n text = fs.readFileSync(infile, 'utf8');\n } catch {\n console.error(`读不到迁移包:${infile}`);\n return 1;\n }\n let files;\n try {\n files = decryptContainer(text, pw ?? '');\n } catch (e) {\n console.error(String(e instanceof Error ? e.message : e));\n return 1;\n }\n const result = applyMigrationEntries(guard, paths, files.files);\n console.log(`恢复 ${result.restored.length} 个文件;备份 ${result.backedUp.length} 个被覆盖文件;跳过 ${result.skipped.length} 个。`);\n for (const r of result.restored) console.log(` 恢复: ${r}`);\n for (const b of result.backedUp) console.log(` 备份: ${b}.bak-migrate-*`);\n if (result.skipped.length > 0) console.log(` 跳过: ${result.skipped.join(', ')}`);\n if (result.error) console.log(` 失败并已回滚:${result.error}`);\n console.log('重启 DSH 后生效。');\n return result.error ? 1 : 0;\n }\n console.error(`unknown migrate subcommand: ${sub}`);\n return 1;\n}\n\nasync function verbSessions(c: CliCtx): Promise<number> {\n const { guard, paths } = c;\n // Read-only enumeration of the host's persisted sessions (ids from the\n // on-disk store; titles live server-side and are not listed here).\n const root = path.join(dshHomeDir(), 'sessions');\n let found = 0;\n if (fs.existsSync(root)) {\n const { homeSessionId } = await import('../core/orchestrator.js');\n const own = homeSessionId(guard, paths);\n for (const slug of fs.readdirSync(root)) {\n for (const id of fs.readdirSync(path.join(root, slug))) {\n found += 1;\n const mark = id === own ? ' ← 心跳正身' : '';\n console.log(`${id} [${slug}]${mark}`);\n }\n }\n }\n if (found === 0) console.log('(no persisted sessions found)');\n return 0;\n}\n\nasync function verbBind(c: CliCtx): Promise<number> {\n const { guard, paths, sub, rest } = c;\n const { loadBindings, addBinding, removeBinding } = await import('../core/bindings.js');\n switch (sub) {\n case 'list': {\n const data = loadBindings(guard, paths.settingsDir);\n const { homeSessionId } = await import('../core/orchestrator.js');\n const own = homeSessionId(guard, paths);\n if (own) console.log(`心跳正身: ${own}(决策轮次发生地;bind remove 它 = 重置正身)`);\n for (const b of data.bindings) {\n console.log(`${b.sessionId} deliver:${b.deliver ? '√' : '×'} observe:${b.observe ? '√' : '×'}`);\n }\n if (data.bindings.length === 0 && !own) console.log('(no bindings — expressions stay in the dedicated heartbeat session)');\n return 0;\n }\n case 'add': {\n const id = rest[0];\n if (!id || !id.startsWith('session-')) {\n console.error('usage: bind add <sessionId> [--observe] [--no-deliver] (see: sessions list)');\n return 1;\n }\n const observe = rest.includes('--observe') || rest.includes('--observe-only');\n const deliver = !rest.includes('--no-deliver') && !rest.includes('--observe-only');\n const b = addBinding(guard, paths.settingsDir, id, { deliver, observe });\n console.log(`BOUND ${b.sessionId} deliver:${b.deliver} observe:${b.observe}`);\n return 0;\n }\n case 'remove': {\n const id = rest[0];\n if (!id) {\n console.error('usage: bind remove <sessionId>');\n return 1;\n }\n console.log(removeBinding(guard, paths.settingsDir, id) ? `UNBOUND ${id}` : 'NOT_FOUND');\n // Unbinding the HOME session resets it: the next beat creates a fresh\n // dedicated session (the old one goes quiet after restart). H-09/H-45:\n // the shared path also drops the orchestrator's cached agent — the\n // inline delete here used to leave it pointing at the released session.\n const { resetHomeSession } = await import('../core/orchestrator.js');\n if (resetHomeSession(guard, paths, id)) {\n console.log('注意:这是心跳正身会话。已重置——下次心跳将创建新的正身会话(旧会话不再有心跳)');\n }\n return 0;\n }\n default:\n console.error('usage: bind list | add <sessionId> | remove <sessionId>');\n return 1;\n }\n}\n\nasync function verbPreset(c: CliCtx): Promise<number> {\n const { sub, rest, argv } = c;\n const id = flag(argv, '--id') ?? BUNDLED_PRESET_ID;\n // The plugin installs into the roster's own user root; the CLI has no\n // roster, so it reports/uses the conventional one ($DSH_HOME or ~/.dsh).\n const root = conventionalUserPresetRoot();\n const status = presetStatus(import.meta.url, id, root);\n if (sub === undefined || sub === 'status') {\n console.log(`preset id : ${status.id}`);\n console.log(`installed : ${status.installed ? 'yes' : 'no'}`);\n console.log(`target dir : ${status.dir}`);\n console.log(`bundled at : ${status.bundledDir ?? '(not found next to the plugin)'}`);\n if (status.installed) {\n console.log(\n `composition : ${status.compositionMatches ? 'matches the bundled template' : 'differs from the bundled template (hand-edited, or an older version)'}`,\n );\n }\n if (!status.installed) {\n console.log('hint: the plugin installs this itself on the next DSH start (installPreset=true, default);');\n console.log(' or run `preset install` now.');\n }\n return status.installed ? 0 : 1;\n }\n if (sub === 'install') {\n const result = installBundledPreset({\n moduleUrl: import.meta.url,\n id,\n root,\n force: rest.includes('--force'),\n });\n console.log(describeInstall(result));\n return result.action === 'error' ? 1 : 0;\n }\n console.error('usage: preset status | install [--force] [--id <presetId>]');\n return 1;\n}\n\n/**\n * Encryption containers on disk. `upgrade` is the migration step v2.0 owes the\n * users of 1.x: reads already accept the legacy container, this rewrites the\n * files so the plugin stops shelling out to PowerShell for each of them.\n */\nasync function verbVault(c: CliCtx): Promise<number> {\n const { guard, paths, sub } = c;\n const keyFile = vaultKeyPath();\n const files = matchFilesRecursive(paths.dataDir, /./).filter(\n (rel) => rel !== 'vault.key' && !rel.startsWith('tmp/'),\n );\n const counts = { v1: 0, v2: 0, plain: 0 };\n for (const rel of files) {\n counts[containerKind(path.join(paths.dataDir, rel.split('/').join(path.sep)))] += 1;\n }\n if (sub === undefined || sub === 'status') {\n console.log(`data dir : ${paths.dataDir}`);\n console.log(`master key : ${keyFile}${fs.existsSync(keyFile) ? '' : ' (not created yet; the next write makes it)'}`);\n console.log(`containers : ${counts.v2} KHBV2 (current), ${counts.v1} KHBV1 (legacy), ${counts.plain} plaintext`);\n if (counts.v1 > 0) console.log('hint: run `vault upgrade` to rewrite the legacy files in place.');\n return 0;\n }\n if (sub === 'upgrade') {\n const r = upgradeVaultTree(guard, paths.dataDir);\n console.log(`UPGRADED ${r.upgraded} of ${r.scanned} file(s) to KHBV2`);\n for (const f of r.failed) console.log(` ! ${f.file}: ${f.reason}`);\n return r.failed.length === 0 ? 0 : 1;\n }\n console.error('usage: vault status | upgrade');\n return 1;\n}\n\n/** Command table. Adding a verb = one function above plus one line here. */\nconst VERBS: Record<string, Verb> = {\n status: verbStatus,\n seeds: verbSeeds,\n ledger: verbLedger,\n excerpt: verbExcerpt,\n weekly: verbWeekly,\n logs: verbLogs,\n browse: verbBrowse,\n notify: verbNotify,\n profile: verbProfile,\n vault: verbVault,\n burn: verbBurn,\n migrate: verbMigrate,\n sessions: verbSessions,\n bind: verbBind,\n preset: verbPreset,\n};\n\nexport async function main(argv: string[]): Promise<number> {\n const [cmd, sub, ...rest] = argv;\n if (!cmd || cmd === 'help' || cmd === '--help') {\n console.log(usage());\n return 0;\n }\n const verb = VERBS[cmd];\n if (!verb) {\n console.error(`unknown command: ${cmd}`);\n console.log(usage());\n return 1;\n }\n const paths = initWorkspace();\n const guard = createPathGuard(paths.dataDir);\n const policy = loadPolicy(guard, paths.configDir, paths.settingsDir);\n const decisionLog = path.join(paths.logsDir, 'heartbeat.jsonl');\n /** Seed lifecycle audit (v1.9.0): CLI edits land in the same log as the beat's. */\n const seedAudit = (entry: Record<string, unknown>): void => {\n try {\n appendAuditLine(decisionLog, entry);\n } catch { /* audit must never break the command */ }\n };\n return verb({\n paths,\n guard,\n policy,\n sub,\n rest,\n argv,\n seedsFile: seedsFilePath(paths.dataDir),\n ledgerFile: ledgerFilePath(paths.dataDir),\n excerptFile: excerptFilePath(paths.dataDir),\n decisionLog,\n seedAudit,\n });\n}\n\nif (process.argv[1] && import.meta.url === new URL(`file:///${process.argv[1].replace(/\\\\/g, '/')}`).href) {\n // Direct execution guard; the CLI is also importable for tests.\n void main(process.argv.slice(2))\n .then((code) => { process.exitCode = code; })\n .catch((e: unknown) => {\n // H-44: no unhandled rejection — print and exit non-zero.\n console.error(e);\n process.exitCode = 1;\n });\n}\n","// Burn list - SINGLE SOURCE OF TRUTH (design doc §10.10; v1 shipped two\n// hardcoded lists and one drifted). burn and uninstall --purge both consume\n// this list. Settings (data/settings/) are NOT burned by default: losing\n// memory != losing the charter/gates the user configured (--all overrides).\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport type { PathGuard } from '../core/path-guard.js';\nimport type { WorkspacePaths } from '../core/paths.js';\nimport { shredFileSync } from '../core/atomic-fs.js';\nimport { appendAuditLine } from '../core/audit-log.js';\nimport { matchFilesRecursive } from '../core/fs-walk.js';\n\nexport interface BurnTarget {\n /** Relative to dataDir. Files are shredded (overwrite x3) then deleted. */\n file?: string;\n /** Every dataDir file whose name starts with this prefix — a family of\n * timestamped files a bare `file` cannot name (journal archive shards).\n * Shredded like files. */\n prefix?: string;\n /** Every file ANYWHERE below dataDir whose NAME matches this pattern. Used for\n * families a prefix cannot reach: `${name}.bak-migrate-${stamp}` and the\n * `.incoming-` staging leftovers sit next to whatever they copied, which may\n * be a subdirectory. Shredded like files. */\n match?: RegExp;\n /** Directories are removed recursively (no shred - content is files). */\n dir?: string;\n note: string;\n}\n\nexport const BURN_LIST: BurnTarget[] = [\n { file: 'profile.json', note: '画像物化视图' },\n { file: 'profile_inbox.jsonl', note: '观察收件箱' },\n { file: 'profile_journal.jsonl', note: '画像操作流水' },\n // H-19: the rotation shards hold the whole profile history and are written\n // in PLAINTEXT — a burn that leaves them behind leaves the memory readable.\n { prefix: 'profile_journal.archive-', note: '画像流水归档分片(明文;journal 轮转产物)' },\n // HB-07 (2026-10-17): applyMigrationEntries copies every file it overwrites\n // to `${abs}.bak-migrate-${stamp}`. Those copies hold the OLD memory — a burn\n // that left them behind left the thing the user asked to destroy. The\n // `.incoming-` staging files are the same data, only younger.\n { match: /\\.bak-migrate-\\d{14}$/, note: '迁移备份(迁移导入时的原文件副本)' },\n { match: /\\.incoming-\\d{14}$/, note: '迁移暂存残留(崩溃遗留的导入副本)' },\n { file: 'profile_rhythm.json', note: '作息聚合(纯统计)' },\n { file: 'screen.json', note: '屏幕快照(加密)' },\n { file: 'screen.jpg', note: '截图(加密)' },\n { file: 'sent.json', note: '表达记录(加密)' },\n { file: 'browse.json', note: '浏览流状态(加密)' },\n { file: 'seeds.jsonl', note: '素材池(加密)' },\n { file: 'ledger.md', note: '账本(明文,人可读是设计目标)' },\n { file: 'envpulse.json', note: '环境温度计快照' },\n { file: 'gate.json', note: '闸门运行时计数' },\n // v1.9.0 completion (H-19): these carry memory just as much as the rows\n // above — the persona report log records WHAT SHE SAID (spoken / seed_ids /\n // profile_ids / reason), so a burn that skips it is a burn that lies.\n { file: 'profile_snapshot.json', note: '画像快照(journal 轮转基线)' },\n { file: 'cursors.json', note: '观察游标(会话事件位点)' },\n { file: 'seed_report.jsonl', note: '投递报账日志(加密)' },\n { file: 'preference.json', note: '话题偏好统计' },\n { dir: 'weekly', note: '周报(画像与素材散文)' },\n { dir: 'tmp', note: '解锁临时文件(崩溃残留的解密明文是最该烧的东西)' },\n { dir: 'logs', note: '审计与决策日志' },\n { dir: 'exports', note: '导出产物' },\n];\n\nconst SETTINGS_DIR = 'settings'; // excluded unless --all\n\n/** dataDir files matching a prefix target, name-sorted for stable output. */\nfunction prefixMatches(guard: PathGuard, paths: WorkspacePaths, prefix: string): string[] {\n try {\n return fs.readdirSync(guard.assert(paths.dataDir))\n .filter((f) => f.startsWith(prefix))\n .sort();\n } catch {\n return [];\n }\n}\n\n/** Same as prefixMatches, but for the recursive `match` family. */\nfunction matchTargets(guard: PathGuard, paths: WorkspacePaths, re: RegExp): string[] {\n try {\n return matchFilesRecursive(guard.assert(paths.dataDir), re);\n } catch {\n return [];\n }\n}\n\nexport interface BurnPlanItem {\n target: BurnTarget;\n exists: boolean;\n}\n\n/** Preview: what exists, what would be removed. No writes. */\nexport function planBurn(guard: PathGuard, paths: WorkspacePaths, all = false): BurnPlanItem[] {\n const plan: BurnPlanItem[] = [];\n for (const t of BURN_LIST) {\n const rel = t.file ?? t.dir ?? t.prefix ?? String(t.match ?? '');\n if (!all && rel === SETTINGS_DIR) continue;\n let exists = false;\n if (t.match) {\n exists = matchTargets(guard, paths, t.match).length > 0;\n } else if (t.prefix) {\n exists = prefixMatches(guard, paths, t.prefix).length > 0;\n } else {\n try {\n exists = fs.existsSync(guard.assert(path.join(paths.dataDir, rel)));\n } catch {\n exists = false;\n }\n }\n plan.push({ target: t, exists });\n }\n if (all) {\n plan.push({ target: { dir: SETTINGS_DIR, note: '用户设定(隐私宪章/闸门参数)——仅 --all 连带' }, exists: fs.existsSync(paths.settingsDir) });\n }\n return plan;\n}\n\n/**\n * Execute the burn: overwrite x3 + delete files, remove dirs. Irreversible.\n * Returns per-target results and writes a BURN_EVENT into the (recreated)\n * journal afterwards - the only trace, on purpose (transparency).\n */\nexport function executeBurn(\n guard: PathGuard,\n paths: WorkspacePaths,\n opts: { all?: boolean; shredPasses?: number } = {},\n): { burned: string[]; missing: string[] } {\n const burned: string[] = [];\n const missing: string[] = [];\n const passes = opts.shredPasses ?? 3;\n for (const t of BURN_LIST) {\n if (t.match) {\n const matches = matchTargets(guard, paths, t.match);\n if (matches.length === 0) {\n missing.push(String(t.match));\n continue;\n }\n for (const f of matches) {\n try {\n shredFileSync(guard.assert(path.join(paths.dataDir, f)), passes);\n burned.push(f);\n } catch { /* vanished between listing and shredding: not fatal */ }\n }\n continue;\n }\n // H-19: a prefix target is a family of files (timestamped archive shards);\n // shred every match individually.\n if (t.prefix) {\n const matches = prefixMatches(guard, paths, t.prefix);\n if (matches.length === 0) {\n missing.push(`${t.prefix}*`);\n continue;\n }\n for (const f of matches) {\n try {\n shredFileSync(guard.assert(path.join(paths.dataDir, f)), passes);\n burned.push(f);\n } catch { /* vanished between listing and shredding: not fatal */ }\n }\n continue;\n }\n const rel = t.file ?? t.dir ?? String(t.match ?? '');\n const abs = path.join(paths.dataDir, rel);\n let absCanon: string;\n try {\n absCanon = guard.assert(abs);\n } catch {\n missing.push(rel);\n continue;\n }\n if (t.file) {\n if (fs.existsSync(absCanon)) {\n shredFileSync(absCanon, passes);\n burned.push(rel);\n } else {\n missing.push(rel);\n }\n } else if (fs.existsSync(absCanon)) {\n fs.rmSync(absCanon, { recursive: true, force: true });\n burned.push(rel);\n } else {\n missing.push(rel);\n }\n }\n if (opts.all) {\n fs.rmSync(paths.settingsDir, { recursive: true, force: true });\n burned.push(SETTINGS_DIR);\n }\n // BURN_EVENT: recreate the journal; data dir is now re-initializable.\n appendAuditLine(guard.assert(path.join(paths.dataDir, 'profile_journal.jsonl')), {\n event: 'BURN_EVENT',\n burned: burned.length,\n missing: missing.length,\n settingsPreserved: !opts.all,\n });\n return { burned, missing };\n}\n"],"mappings":"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","names":["fs","path","fs","path"]}