@hiveai/cli 0.2.4 → 0.2.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.
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
- import { Command as Command24 } from "commander";
4
+ import { Command as Command26 } from "commander";
5
5
 
6
6
  // src/commands/briefing.ts
7
7
  import { existsSync } from "fs";
@@ -54,7 +54,7 @@ function registerBriefing(program2) {
54
54
  "--scope <scope>",
55
55
  "personal | team | module | all (default: team)",
56
56
  "team"
57
- ).option("--include-draft", "include draft memories (excluded by default)").option("-d, --dir <dir>", "project root").action(async (opts) => {
57
+ ).option("--include-draft", "include draft memories (excluded by default)").option("--include-stale", "include stale memories (excluded by default \u2014 may be outdated)").option("-d, --dir <dir>", "project root").action(async (opts) => {
58
58
  const root = findProjectRoot(opts.dir);
59
59
  const paths = resolveHaivePaths(root);
60
60
  if (existsSync(paths.projectContext)) {
@@ -78,6 +78,7 @@ function registerBriefing(program2) {
78
78
  const fm = mem.frontmatter;
79
79
  if (fm.status === "rejected" || fm.status === "deprecated") return false;
80
80
  if (!opts.includeDraft && fm.status === "draft") return false;
81
+ if (!opts.includeStale && fm.status === "stale") return false;
81
82
  if (scopeFilter !== "all" && fm.scope !== scopeFilter) return false;
82
83
  return true;
83
84
  });
@@ -108,8 +109,9 @@ function registerBriefing(program2) {
108
109
  const fm = mem.frontmatter;
109
110
  const badge = ui.statusBadge(fm.status);
110
111
  const draftMarker = fm.status === "draft" ? ui.yellow(" [DRAFT]") : "";
112
+ const unverifiedMarker = fm.status === "proposed" ? ui.yellow(" [UNVERIFIED]") : "";
111
113
  console.log(
112
- `${ui.bold(fm.id)} ${ui.dim(fm.scope + "/" + fm.type)} ${badge}${draftMarker}`
114
+ `${ui.bold(fm.id)} ${ui.dim(fm.scope + "/" + fm.type)} ${badge}${draftMarker}${unverifiedMarker}`
113
115
  );
114
116
  console.log(mem.body.trim());
115
117
  console.log();
@@ -122,15 +124,34 @@ function parseCsv(value) {
122
124
  return value.split(",").map((s) => s.trim()).filter(Boolean);
123
125
  }
124
126
 
127
+ // src/commands/tui.ts
128
+ import "commander";
129
+ import { findProjectRoot as findProjectRoot2 } from "@hiveai/core";
130
+ function registerTui(program2) {
131
+ program2.command("tui").description("Interactive TUI dashboard \u2014 browse, filter, and manage memories in the terminal").option("-d, --dir <dir>", "project root").action(async (opts) => {
132
+ if (!process.stdout.isTTY) {
133
+ console.error("haive tui requires an interactive terminal (TTY).");
134
+ process.exitCode = 1;
135
+ return;
136
+ }
137
+ const root = findProjectRoot2(opts.dir);
138
+ const { render } = await import("ink");
139
+ const { createElement } = await import("react");
140
+ const { Dashboard } = await import("./Dashboard-SRPCHP7Z.js");
141
+ const { waitUntilExit } = render(createElement(Dashboard, { root }));
142
+ await waitUntilExit();
143
+ });
144
+ }
145
+
125
146
  // src/commands/embeddings.ts
126
147
  import { existsSync as existsSync2 } from "fs";
127
148
  import path from "path";
128
149
  import "commander";
129
- import { findProjectRoot as findProjectRoot2, resolveHaivePaths as resolveHaivePaths2 } from "@hiveai/core";
150
+ import { findProjectRoot as findProjectRoot3, resolveHaivePaths as resolveHaivePaths2 } from "@hiveai/core";
130
151
  function registerEmbeddings(program2) {
131
152
  const embeddings = program2.command("embeddings").description("Manage local embeddings index for semantic search");
132
153
  embeddings.command("index").description("Generate or refresh the embeddings index for all memories").option("-d, --dir <dir>", "project root").action(async (opts) => {
133
- const root = findProjectRoot2(opts.dir);
154
+ const root = findProjectRoot3(opts.dir);
134
155
  const paths = resolveHaivePaths2(root);
135
156
  if (!existsSync2(paths.memoriesDir)) {
136
157
  ui.error(`No .ai/memories at ${root}. Run \`haive init\` first.`);
@@ -147,7 +168,7 @@ function registerEmbeddings(program2) {
147
168
  );
148
169
  });
149
170
  embeddings.command("query <text>").description("Run a semantic search against the local embeddings index").option("-d, --dir <dir>", "project root").option("--limit <n>", "max results", "10").option("--min-score <n>", "minimum cosine similarity (0-1)", "0").action(async (text, opts) => {
150
- const root = findProjectRoot2(opts.dir);
171
+ const root = findProjectRoot3(opts.dir);
151
172
  const paths = resolveHaivePaths2(root);
152
173
  const { semanticSearch } = await loadEmbeddings();
153
174
  const result = await semanticSearch(paths, text, {
@@ -170,7 +191,7 @@ function registerEmbeddings(program2) {
170
191
  }
171
192
  });
172
193
  embeddings.command("status").description("Show the embeddings index status").option("-d, --dir <dir>", "project root").action(async (opts) => {
173
- const root = findProjectRoot2(opts.dir);
194
+ const root = findProjectRoot3(opts.dir);
174
195
  const paths = resolveHaivePaths2(root);
175
196
  const { indexStat } = await loadEmbeddings();
176
197
  const stat = await indexStat(paths);
@@ -201,7 +222,7 @@ import "commander";
201
222
  import {
202
223
  buildCodeMap,
203
224
  codeMapPath,
204
- findProjectRoot as findProjectRoot3,
225
+ findProjectRoot as findProjectRoot4,
205
226
  resolveHaivePaths as resolveHaivePaths3,
206
227
  saveCodeMap
207
228
  } from "@hiveai/core";
@@ -213,7 +234,7 @@ function registerIndexCode(program2) {
213
234
  "extra directory names to skip (comma-separated)",
214
235
  ""
215
236
  ).action(async (opts) => {
216
- const root = findProjectRoot3(opts.dir);
237
+ const root = findProjectRoot4(opts.dir);
217
238
  const paths = resolveHaivePaths3(root);
218
239
  const extraExcludes = (opts.exclude ?? "").split(",").map((s) => s.trim()).filter(Boolean);
219
240
  ui.info(`Indexing source files in ${root}\u2026`);
@@ -311,7 +332,7 @@ import { mkdir as mkdir2, writeFile as writeFile2, chmod, readFile as readFile2
311
332
  import { existsSync as existsSync4 } from "fs";
312
333
  import path4 from "path";
313
334
  import "commander";
314
- import { findProjectRoot as findProjectRoot5 } from "@hiveai/core";
335
+ import { findProjectRoot as findProjectRoot6 } from "@hiveai/core";
315
336
  var HOOK_MARKER = "# hAIve auto-generated";
316
337
  var HOOK_BODY = `#!/bin/sh
317
338
  ${HOOK_MARKER} \u2014 keep this block to allow upgrades. Hand-edit anything outside it.
@@ -327,7 +348,7 @@ fi
327
348
  var HOOKS = ["post-merge", "post-rewrite"];
328
349
  function registerInstallHooks(program2) {
329
350
  program2.command("install-hooks").description("Install git hooks that run `haive sync` after pull/merge").option("-d, --dir <dir>", "project root").option("--force", "overwrite existing hooks").action(async (opts) => {
330
- const root = findProjectRoot5(opts.dir);
351
+ const root = findProjectRoot6(opts.dir);
331
352
  const gitDir = path4.join(root, ".git");
332
353
  if (!existsSync4(gitDir)) {
333
354
  ui.error(`No .git directory at ${root}.`);
@@ -364,11 +385,11 @@ import { createRequire } from "module";
364
385
  import path5 from "path";
365
386
  import { fileURLToPath } from "url";
366
387
  import "commander";
367
- import { findProjectRoot as findProjectRoot6 } from "@hiveai/core";
388
+ import { findProjectRoot as findProjectRoot7 } from "@hiveai/core";
368
389
  var require2 = createRequire(import.meta.url);
369
390
  function registerMcp(program2) {
370
391
  program2.command("mcp").description("Start the hAIve MCP server (stdio transport)").option("-d, --dir <dir>", "project root (defaults to nearest .ai/ or .git/)").action((opts) => {
371
- const root = findProjectRoot6(opts.dir);
392
+ const root = findProjectRoot7(opts.dir);
372
393
  const bin = locateMcpBin();
373
394
  if (!bin) {
374
395
  ui.error(
@@ -399,13 +420,13 @@ function locateMcpBin() {
399
420
 
400
421
  // src/commands/sync.ts
401
422
  import { spawnSync } from "child_process";
402
- import { writeFile as writeFile3 } from "fs/promises";
423
+ import { readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
403
424
  import { existsSync as existsSync6 } from "fs";
404
- import "path";
425
+ import path6 from "path";
405
426
  import "commander";
406
427
  import {
407
428
  DEFAULT_AUTO_PROMOTE_RULE,
408
- findProjectRoot as findProjectRoot7,
429
+ findProjectRoot as findProjectRoot8,
409
430
  getUsage,
410
431
  isAutoPromoteEligible,
411
432
  loadMemoriesFromDir as loadMemoriesFromDir2,
@@ -414,12 +435,17 @@ import {
414
435
  serializeMemory,
415
436
  verifyAnchor
416
437
  } from "@hiveai/core";
438
+ var BRIDGE_START = "<!-- haive:memories-start -->";
439
+ var BRIDGE_END = "<!-- haive:memories-end -->";
417
440
  function registerSync(program2) {
418
441
  program2.command("sync").description("Refresh memory state after a pull/merge: verify anchors, auto-promote, report changes").option("-d, --dir <dir>", "project root").option("--quiet", "minimal output (suitable for git hooks)").option(
419
442
  "--since <ref>",
420
443
  "git ref/commit to compare against; report memories added/modified/removed since"
421
- ).option("--no-verify", "skip the anchor verification step").option("--no-promote", "skip the auto-promotion step").action(async (opts) => {
422
- const root = findProjectRoot7(opts.dir);
444
+ ).option("--no-verify", "skip the anchor verification step").option("--no-promote", "skip the auto-promotion step").option(
445
+ "--inject-bridge",
446
+ "inject top validated memories into CLAUDE.md (or --bridge-file) between <!-- haive:memories-start/end --> markers"
447
+ ).option("--bridge-file <path>", "bridge file to inject into (default: CLAUDE.md)").option("--bridge-max-memories <n>", "max memories to inject into bridge file", "5").action(async (opts) => {
448
+ const root = findProjectRoot8(opts.dir);
423
449
  const paths = resolveHaivePaths5(root);
424
450
  if (!existsSync6(paths.memoriesDir)) {
425
451
  if (!opts.quiet) ui.warn(`No .ai/memories at ${root}. Run \`haive init\` first.`);
@@ -510,6 +536,11 @@ function registerSync(program2) {
510
536
  )
511
537
  );
512
538
  }
539
+ if (opts.injectBridge) {
540
+ const bridgeFile = opts.bridgeFile ? path6.resolve(opts.bridgeFile) : path6.join(root, "CLAUDE.md");
541
+ const maxInject = Math.max(1, Number(opts.bridgeMaxMemories ?? 5));
542
+ await injectBridge(bridgeFile, paths.memoriesDir, maxInject, root, opts.quiet);
543
+ }
513
544
  if (sinceReport && !opts.quiet) {
514
545
  if (sinceReport.added.length > 0) {
515
546
  log(ui.bold("\nNew memories:"));
@@ -526,6 +557,47 @@ function registerSync(program2) {
526
557
  }
527
558
  });
528
559
  }
560
+ async function injectBridge(bridgeFile, memoriesDir, maxMemories, root, quiet) {
561
+ if (!existsSync6(memoriesDir)) return;
562
+ const all = await loadMemoriesFromDir2(memoriesDir);
563
+ const top = all.filter(({ memory: memory2 }) => {
564
+ const s = memory2.frontmatter.status;
565
+ return s === "validated" || s === "proposed";
566
+ }).sort((a, b) => {
567
+ const score = (m) => {
568
+ const s = m.memory.frontmatter.status;
569
+ return s === "validated" ? 2 : 1;
570
+ };
571
+ return score(b) - score(a);
572
+ }).slice(0, maxMemories);
573
+ const block = top.map((m) => {
574
+ const fm = m.memory.frontmatter;
575
+ const unverified = fm.status === "proposed" ? " [UNVERIFIED]" : "";
576
+ return `### ${fm.id} (${fm.scope}/${fm.type})${unverified}
577
+ ${m.memory.body.trim()}`;
578
+ }).join("\n\n---\n\n");
579
+ const injected = `${BRIDGE_START}
580
+ <!-- AUTO-GENERATED by haive sync --inject-bridge \u2014 do not edit between these markers -->
581
+
582
+ ` + block + `
583
+
584
+ ${BRIDGE_END}`;
585
+ let existing = existsSync6(bridgeFile) ? await readFile3(bridgeFile, "utf8") : "";
586
+ const startIdx = existing.indexOf(BRIDGE_START);
587
+ const endIdx = existing.indexOf(BRIDGE_END);
588
+ let updated;
589
+ if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {
590
+ updated = existing.slice(0, startIdx) + injected + existing.slice(endIdx + BRIDGE_END.length);
591
+ } else {
592
+ updated = existing + (existing.endsWith("\n") ? "" : "\n") + "\n" + injected + "\n";
593
+ }
594
+ await writeFile3(bridgeFile, updated, "utf8");
595
+ if (!quiet) {
596
+ console.log(
597
+ ui.dim(`bridge: injected ${top.length} memor${top.length === 1 ? "y" : "ies"} into ${path6.relative(root, bridgeFile)}`)
598
+ );
599
+ }
600
+ }
529
601
  function collectSinceChanges(root, ref) {
530
602
  const result = spawnSync(
531
603
  "git",
@@ -552,15 +624,15 @@ import path7 from "path";
552
624
  import "commander";
553
625
  import {
554
626
  buildFrontmatter,
555
- findProjectRoot as findProjectRoot8,
627
+ findProjectRoot as findProjectRoot9,
556
628
  inferModulesFromPaths,
557
629
  memoryFilePath,
558
630
  resolveHaivePaths as resolveHaivePaths6,
559
631
  serializeMemory as serializeMemory2
560
632
  } from "@hiveai/core";
561
633
  function registerMemoryAdd(memory2) {
562
- memory2.command("add").description("Add a new memory (defaults to personal scope)").requiredOption("--type <type>", "convention | decision | gotcha | architecture | glossary").requiredOption("--slug <slug>", "short identifier used in the file name").option("--title <text>", "memory title \u2014 becomes the first heading of the body").option("--scope <scope>", "personal | team | module", "personal").option("--module <name>", "module name (required when scope=module)").option("--tags <csv>", "comma-separated tags").option("--domain <domain>", "domain (e.g. transactions)").option("--author <author>", "author email or handle").option("--paths <csv>", "anchor paths, comma-separated").option("--symbols <csv>", "anchor symbols, comma-separated").option("--commit <sha>", "anchor commit SHA").option("--body <text>", "memory body content (Markdown) \u2014 overrides --title default body").option("--no-auto-tag", "disable automatic tag suggestions inferred from anchor paths").option("-d, --dir <dir>", "project root").action(async (opts) => {
563
- const root = findProjectRoot8(opts.dir);
634
+ memory2.command("add").description("Add a new memory (defaults to personal scope)").requiredOption("--type <type>", "convention | decision | gotcha | architecture | glossary | attempt").requiredOption("--slug <slug>", "short identifier used in the file name").option("--title <text>", "memory title \u2014 becomes the first heading of the body").option("--scope <scope>", "personal | team | module", "personal").option("--module <name>", "module name (required when scope=module)").option("--tags <csv>", "comma-separated tags").option("--domain <domain>", "domain (e.g. transactions)").option("--author <author>", "author email or handle").option("--paths <csv>", "anchor paths, comma-separated").option("--symbols <csv>", "anchor symbols, comma-separated").option("--commit <sha>", "anchor commit SHA").option("--body <text>", "memory body content (Markdown) \u2014 overrides --title default body").option("--no-auto-tag", "disable automatic tag suggestions inferred from anchor paths").option("-d, --dir <dir>", "project root").action(async (opts) => {
635
+ const root = findProjectRoot9(opts.dir);
564
636
  const paths = resolveHaivePaths6(root);
565
637
  if (!existsSync7(paths.haiveDir)) {
566
638
  ui.error(`No .ai/ found at ${root}. Run \`haive init\` first.`);
@@ -631,7 +703,7 @@ function parseCsv2(value) {
631
703
  import { existsSync as existsSync8 } from "fs";
632
704
  import path8 from "path";
633
705
  import "commander";
634
- import { findProjectRoot as findProjectRoot9, resolveHaivePaths as resolveHaivePaths7 } from "@hiveai/core";
706
+ import { findProjectRoot as findProjectRoot10, resolveHaivePaths as resolveHaivePaths7 } from "@hiveai/core";
635
707
 
636
708
  // src/utils/fs.ts
637
709
  import {
@@ -643,7 +715,7 @@ import {
643
715
  // src/commands/memory-list.ts
644
716
  function registerMemoryList(memory2) {
645
717
  memory2.command("list").description("List memories with optional filters").option("--scope <scope>", "personal | team | module").option("--type <type>", "filter by type").option("--tag <tag>", "filter by tag").option("--module <name>", "filter by module name").option("--status <csv>", "filter by status (draft,proposed,validated,stale,rejected,deprecated)").option("--show-rejected", "include rejected memories (hidden by default)").option("-d, --dir <dir>", "project root").action(async (opts) => {
646
- const root = findProjectRoot9(opts.dir);
718
+ const root = findProjectRoot10(opts.dir);
647
719
  const paths = resolveHaivePaths7(root);
648
720
  if (!existsSync8(paths.memoriesDir)) {
649
721
  ui.error(`No memories directory at ${paths.memoriesDir}. Run \`haive init\` first.`);
@@ -717,14 +789,14 @@ import { existsSync as existsSync9 } from "fs";
717
789
  import path9 from "path";
718
790
  import "commander";
719
791
  import {
720
- findProjectRoot as findProjectRoot10,
792
+ findProjectRoot as findProjectRoot11,
721
793
  memoryFilePath as memoryFilePath2,
722
794
  resolveHaivePaths as resolveHaivePaths8,
723
795
  serializeMemory as serializeMemory3
724
796
  } from "@hiveai/core";
725
797
  function registerMemoryPromote(memory2) {
726
798
  memory2.command("promote <id>").description("Promote a personal memory to team scope (status -> proposed)").option("-d, --dir <dir>", "project root").action(async (id, opts) => {
727
- const root = findProjectRoot10(opts.dir);
799
+ const root = findProjectRoot11(opts.dir);
728
800
  const paths = resolveHaivePaths8(root);
729
801
  if (!existsSync9(paths.memoriesDir)) {
730
802
  ui.error(`No memories directory at ${paths.memoriesDir}. Run \`haive init\` first.`);
@@ -776,13 +848,13 @@ import { writeFile as writeFile6 } from "fs/promises";
776
848
  import path10 from "path";
777
849
  import "commander";
778
850
  import {
779
- findProjectRoot as findProjectRoot11,
851
+ findProjectRoot as findProjectRoot12,
780
852
  resolveHaivePaths as resolveHaivePaths9,
781
853
  serializeMemory as serializeMemory4
782
854
  } from "@hiveai/core";
783
855
  function registerMemoryApprove(memory2) {
784
856
  memory2.command("approve [id]").description("Mark a memory as 'validated'. Use --all to bulk-approve all proposed/draft memories.").option("--all", "approve all proposed and draft memories at once").option("--pending", "approve all memories with status 'proposed'").option("-d, --dir <dir>", "project root").action(async (id, opts) => {
785
- const root = findProjectRoot11(opts.dir);
857
+ const root = findProjectRoot12(opts.dir);
786
858
  const paths = resolveHaivePaths9(root);
787
859
  if (!existsSync10(paths.memoriesDir)) {
788
860
  ui.error(`No .ai/memories at ${root}.`);
@@ -847,13 +919,13 @@ import { existsSync as existsSync11 } from "fs";
847
919
  import path11 from "path";
848
920
  import "commander";
849
921
  import {
850
- findProjectRoot as findProjectRoot12,
922
+ findProjectRoot as findProjectRoot13,
851
923
  resolveHaivePaths as resolveHaivePaths10,
852
924
  serializeMemory as serializeMemory5
853
925
  } from "@hiveai/core";
854
926
  function registerMemoryUpdate(memory2) {
855
927
  memory2.command("update <id>").description("Update body, tags, or anchor of an existing memory (preserves id and usage history)").option("--title <text>", "new title \u2014 replaces the first heading of the body").option("--body <text>", "new Markdown body \u2014 replaces the existing body").option("--tags <csv>", "new tags, comma-separated \u2014 fully replaces existing tags").option("--paths <csv>", "new anchor paths, comma-separated").option("--symbols <csv>", "new anchor symbols, comma-separated").option("--commit <sha>", "new anchor commit SHA").option("--domain <domain>", "new domain label").option("--author <author>", "new author handle or email").option("-d, --dir <dir>", "project root").action(async (id, opts) => {
856
- const root = findProjectRoot12(opts.dir);
928
+ const root = findProjectRoot13(opts.dir);
857
929
  const paths = resolveHaivePaths10(root);
858
930
  if (!existsSync11(paths.memoriesDir)) {
859
931
  ui.error(`No .ai/memories at ${root}. Run \`haive init\` first.`);
@@ -932,7 +1004,7 @@ import path12 from "path";
932
1004
  import "commander";
933
1005
  import {
934
1006
  DEFAULT_AUTO_PROMOTE_RULE as DEFAULT_AUTO_PROMOTE_RULE2,
935
- findProjectRoot as findProjectRoot13,
1007
+ findProjectRoot as findProjectRoot14,
936
1008
  getUsage as getUsage2,
937
1009
  isAutoPromoteEligible as isAutoPromoteEligible2,
938
1010
  loadUsageIndex as loadUsageIndex2,
@@ -945,7 +1017,7 @@ function registerMemoryAutoPromote(memory2) {
945
1017
  "memories with more rejections than this are skipped",
946
1018
  String(DEFAULT_AUTO_PROMOTE_RULE2.maxRejections)
947
1019
  ).option("--apply", "actually write status=validated to disk (default: dry-run)").option("-d, --dir <dir>", "project root").action(async (opts) => {
948
- const root = findProjectRoot13(opts.dir);
1020
+ const root = findProjectRoot14(opts.dir);
949
1021
  const paths = resolveHaivePaths11(root);
950
1022
  if (!existsSync12(paths.memoriesDir)) {
951
1023
  ui.error(`No .ai/memories at ${root}.`);
@@ -991,17 +1063,17 @@ function registerMemoryAutoPromote(memory2) {
991
1063
  // src/commands/memory-edit.ts
992
1064
  import { spawn as spawn2 } from "child_process";
993
1065
  import { existsSync as existsSync13 } from "fs";
994
- import { readFile as readFile3 } from "fs/promises";
1066
+ import { readFile as readFile4 } from "fs/promises";
995
1067
  import path13 from "path";
996
1068
  import "commander";
997
1069
  import {
998
- findProjectRoot as findProjectRoot14,
1070
+ findProjectRoot as findProjectRoot15,
999
1071
  parseMemory,
1000
1072
  resolveHaivePaths as resolveHaivePaths12
1001
1073
  } from "@hiveai/core";
1002
1074
  function registerMemoryEdit(memory2) {
1003
1075
  memory2.command("edit <id>").description("Open a memory in $EDITOR and re-validate when you save").option("-e, --editor <cmd>", "editor command (defaults to $EDITOR or 'vi')").option("-d, --dir <dir>", "project root").action(async (id, opts) => {
1004
- const root = findProjectRoot14(opts.dir);
1076
+ const root = findProjectRoot15(opts.dir);
1005
1077
  const paths = resolveHaivePaths12(root);
1006
1078
  if (!existsSync13(paths.memoriesDir)) {
1007
1079
  ui.error(`No .ai/memories at ${root}.`);
@@ -1022,7 +1094,7 @@ function registerMemoryEdit(memory2) {
1022
1094
  ui.warn(`Editor exited with status ${code}.`);
1023
1095
  }
1024
1096
  try {
1025
- const fresh = await readFile3(found.filePath, "utf8");
1097
+ const fresh = await readFile4(found.filePath, "utf8");
1026
1098
  parseMemory(fresh);
1027
1099
  ui.success("Memory still parses cleanly.");
1028
1100
  } catch (err) {
@@ -1048,7 +1120,7 @@ import path14 from "path";
1048
1120
  import "commander";
1049
1121
  import {
1050
1122
  deriveConfidence,
1051
- findProjectRoot as findProjectRoot15,
1123
+ findProjectRoot as findProjectRoot16,
1052
1124
  getUsage as getUsage3,
1053
1125
  inferModulesFromPaths as inferModulesFromPaths2,
1054
1126
  loadUsageIndex as loadUsageIndex3,
@@ -1057,7 +1129,7 @@ import {
1057
1129
  } from "@hiveai/core";
1058
1130
  function registerMemoryForFiles(memory2) {
1059
1131
  memory2.command("for-files <files...>").description("Show memories relevant to the given files (anchor overlap, module, domain)").option("-d, --dir <dir>", "project root").action(async (files, opts) => {
1060
- const root = findProjectRoot15(opts.dir);
1132
+ const root = findProjectRoot16(opts.dir);
1061
1133
  const paths = resolveHaivePaths13(root);
1062
1134
  if (!existsSync14(paths.memoriesDir)) {
1063
1135
  ui.error(`No .ai/memories at ${root}.`);
@@ -1121,14 +1193,14 @@ import { existsSync as existsSync15 } from "fs";
1121
1193
  import path15 from "path";
1122
1194
  import "commander";
1123
1195
  import {
1124
- findProjectRoot as findProjectRoot16,
1196
+ findProjectRoot as findProjectRoot17,
1125
1197
  getUsage as getUsage4,
1126
1198
  loadUsageIndex as loadUsageIndex4,
1127
1199
  resolveHaivePaths as resolveHaivePaths14
1128
1200
  } from "@hiveai/core";
1129
1201
  function registerMemoryHot(memory2) {
1130
1202
  memory2.command("hot").description("List memories actively used but not yet validated (good promotion candidates)").option("--threshold <n>", "minimum read_count to qualify", "3").option("--status <status>", "limit to one status (default: draft + proposed)").option("-d, --dir <dir>", "project root").action(async (opts) => {
1131
- const root = findProjectRoot16(opts.dir);
1203
+ const root = findProjectRoot17(opts.dir);
1132
1204
  const paths = resolveHaivePaths14(root);
1133
1205
  if (!existsSync15(paths.memoriesDir)) {
1134
1206
  ui.error(`No .ai/memories at ${root}.`);
@@ -1166,21 +1238,78 @@ function registerMemoryHot(memory2) {
1166
1238
  });
1167
1239
  }
1168
1240
 
1169
- // src/commands/memory-pending.ts
1241
+ // src/commands/memory-tried.ts
1242
+ import { mkdir as mkdir5, writeFile as writeFile9 } from "fs/promises";
1170
1243
  import { existsSync as existsSync16 } from "fs";
1171
1244
  import path16 from "path";
1172
1245
  import "commander";
1173
1246
  import {
1174
- findProjectRoot as findProjectRoot17,
1247
+ buildFrontmatter as buildFrontmatter2,
1248
+ findProjectRoot as findProjectRoot18,
1249
+ memoryFilePath as memoryFilePath3,
1250
+ resolveHaivePaths as resolveHaivePaths15,
1251
+ serializeMemory as serializeMemory7
1252
+ } from "@hiveai/core";
1253
+ function registerMemoryTried(memory2) {
1254
+ memory2.command("tried").description(
1255
+ "Record a failed approach \u2014 negative knowledge to prevent repeated AI mistakes"
1256
+ ).requiredOption("--what <text>", "what approach was tried").requiredOption("--why-failed <text>", "why it failed or should NOT be used").option("--instead <text>", "recommended alternative").option("--scope <scope>", "personal | team | module", "personal").option("--module <name>", "module name (required when scope=module)").option("--tags <csv>", "comma-separated tags").option("--paths <csv>", "anchor paths, comma-separated").option("--author <author>", "author email or handle").option("-d, --dir <dir>", "project root").action(async (opts) => {
1257
+ const root = findProjectRoot18(opts.dir);
1258
+ const paths = resolveHaivePaths15(root);
1259
+ if (!existsSync16(paths.haiveDir)) {
1260
+ ui.error(`No .ai/ found at ${root}. Run \`haive init\` first.`);
1261
+ process.exitCode = 1;
1262
+ return;
1263
+ }
1264
+ const slug = opts.what.toLowerCase().replace(/[^a-z0-9\s]/g, "").trim().split(/\s+/).slice(0, 5).join("-");
1265
+ const baseFm = buildFrontmatter2({
1266
+ type: "attempt",
1267
+ slug,
1268
+ scope: opts.scope,
1269
+ module: opts.module,
1270
+ tags: parseCsv4(opts.tags),
1271
+ paths: parseCsv4(opts.paths),
1272
+ author: opts.author
1273
+ });
1274
+ const frontmatter = { ...baseFm, status: "validated" };
1275
+ const lines = [`# ${opts.what}`, ""];
1276
+ lines.push(`**Why it failed / do NOT use:** ${opts.whyFailed}`);
1277
+ if (opts.instead) {
1278
+ lines.push("", `**Instead, use:** ${opts.instead}`);
1279
+ }
1280
+ const body = lines.join("\n") + "\n";
1281
+ const file = memoryFilePath3(paths, frontmatter.scope, frontmatter.id, frontmatter.module);
1282
+ await mkdir5(path16.dirname(file), { recursive: true });
1283
+ if (existsSync16(file)) {
1284
+ ui.error(`Memory already exists at ${file}`);
1285
+ process.exitCode = 1;
1286
+ return;
1287
+ }
1288
+ await writeFile9(file, serializeMemory7({ frontmatter, body }), "utf8");
1289
+ ui.success(`Recorded: ${path16.relative(root, file)}`);
1290
+ ui.info(`id=${frontmatter.id} type=attempt status=validated (auto-approved)`);
1291
+ });
1292
+ }
1293
+ function parseCsv4(value) {
1294
+ if (!value) return [];
1295
+ return value.split(",").map((s) => s.trim()).filter(Boolean);
1296
+ }
1297
+
1298
+ // src/commands/memory-pending.ts
1299
+ import { existsSync as existsSync17 } from "fs";
1300
+ import path17 from "path";
1301
+ import "commander";
1302
+ import {
1303
+ findProjectRoot as findProjectRoot19,
1175
1304
  getUsage as getUsage5,
1176
1305
  loadUsageIndex as loadUsageIndex5,
1177
- resolveHaivePaths as resolveHaivePaths15
1306
+ resolveHaivePaths as resolveHaivePaths16
1178
1307
  } from "@hiveai/core";
1179
1308
  function registerMemoryPending(memory2) {
1180
1309
  memory2.command("pending").description("List 'proposed' memories awaiting review (sorted by reads desc)").option("--scope <scope>", "filter by scope (personal | team | module)").option("-d, --dir <dir>", "project root").action(async (opts) => {
1181
- const root = findProjectRoot17(opts.dir);
1182
- const paths = resolveHaivePaths15(root);
1183
- if (!existsSync16(paths.memoriesDir)) {
1310
+ const root = findProjectRoot19(opts.dir);
1311
+ const paths = resolveHaivePaths16(root);
1312
+ if (!existsSync17(paths.memoriesDir)) {
1184
1313
  ui.error(`No .ai/memories at ${root}.`);
1185
1314
  process.exitCode = 1;
1186
1315
  return;
@@ -1208,29 +1337,30 @@ function registerMemoryPending(memory2) {
1208
1337
  console.log(
1209
1338
  `${ui.bold(fm.id)} ${ui.dim(`${fm.scope}/${fm.type}`)} ${ui.dim(`age=${ageStr} reads=${u.read_count} rejections=${u.rejected_count}`)}`
1210
1339
  );
1211
- console.log(` ${ui.dim(path16.relative(root, filePath))}`);
1340
+ console.log(` ${ui.dim(path17.relative(root, filePath))}`);
1212
1341
  }
1213
1342
  ui.info(`${proposed.length} pending`);
1214
1343
  });
1215
1344
  }
1216
1345
 
1217
1346
  // src/commands/memory-query.ts
1218
- import { existsSync as existsSync17 } from "fs";
1219
- import path17 from "path";
1347
+ import { existsSync as existsSync18 } from "fs";
1348
+ import path18 from "path";
1220
1349
  import "commander";
1221
1350
  import {
1222
1351
  extractSnippet,
1223
- findProjectRoot as findProjectRoot18,
1352
+ findProjectRoot as findProjectRoot20,
1224
1353
  literalMatchesAllTokens as literalMatchesAllTokens2,
1354
+ literalMatchesAnyToken,
1225
1355
  pickSnippetNeedle,
1226
- resolveHaivePaths as resolveHaivePaths16,
1356
+ resolveHaivePaths as resolveHaivePaths17,
1227
1357
  tokenizeQuery as tokenizeQuery2
1228
1358
  } from "@hiveai/core";
1229
1359
  function registerMemoryQuery(memory2) {
1230
- memory2.command("query <text>").description("Search memories by id, tag, or substring (multi-word AND)").option("-d, --dir <dir>", "project root").option("--limit <n>", "max results", "20").option("--scope <scope>", "personal | team | module").option("--status <csv>", "filter by status (draft,proposed,validated,stale,rejected)").option("--show-rejected", "include rejected memories (hidden by default)").action(async (text, opts) => {
1231
- const root = findProjectRoot18(opts.dir);
1232
- const paths = resolveHaivePaths16(root);
1233
- if (!existsSync17(paths.memoriesDir)) {
1360
+ memory2.command("query <text>").description("Search memories by id, tag, or substring (AND, OR fallback)").option("-d, --dir <dir>", "project root").option("--limit <n>", "max results", "20").option("--scope <scope>", "personal | team | module").option("--status <csv>", "filter by status (draft,proposed,validated,stale,rejected)").option("--show-rejected", "include rejected memories (hidden by default)").action(async (text, opts) => {
1361
+ const root = findProjectRoot20(opts.dir);
1362
+ const paths = resolveHaivePaths17(root);
1363
+ if (!existsSync18(paths.memoriesDir)) {
1234
1364
  ui.error(`No memories directory at ${paths.memoriesDir}. Run \`haive init\` first.`);
1235
1365
  process.exitCode = 1;
1236
1366
  return;
@@ -1238,25 +1368,35 @@ function registerMemoryQuery(memory2) {
1238
1368
  const tokens = tokenizeQuery2(text);
1239
1369
  const statusFilter = opts.status ? opts.status.split(",").map((s) => s.trim()) : null;
1240
1370
  const all = await loadMemoriesFromDir3(paths.memoriesDir);
1241
- const matches = all.filter(({ memory: mem }) => {
1371
+ const passesFilters = (mem) => {
1242
1372
  const fm = mem.frontmatter;
1243
1373
  if (opts.scope && fm.scope !== opts.scope) return false;
1244
1374
  if (!opts.showRejected && !statusFilter && fm.status === "rejected") return false;
1245
1375
  if (statusFilter && !statusFilter.includes(fm.status)) return false;
1246
- return literalMatchesAllTokens2(mem, tokens);
1247
- });
1376
+ return true;
1377
+ };
1378
+ const eligible = all.filter(({ memory: mem }) => passesFilters(mem));
1379
+ let matches = eligible.filter(({ memory: mem }) => literalMatchesAllTokens2(mem, tokens));
1380
+ let fallback = false;
1381
+ if (matches.length === 0 && tokens.length > 1) {
1382
+ matches = eligible.filter(({ memory: mem }) => literalMatchesAnyToken(mem, tokens));
1383
+ fallback = true;
1384
+ }
1248
1385
  const limit = Math.max(1, Number(opts.limit ?? 20));
1249
1386
  const top = matches.slice(0, limit);
1250
1387
  if (top.length === 0) {
1251
1388
  ui.info(`No matches for "${text}".`);
1252
1389
  return;
1253
1390
  }
1391
+ if (fallback) {
1392
+ ui.info(`No exact match \u2014 showing partial results (OR fallback):`);
1393
+ }
1254
1394
  const snippetNeedle = pickSnippetNeedle(text);
1255
1395
  for (const { memory: mem, filePath } of top) {
1256
1396
  const fm = mem.frontmatter;
1257
1397
  const statusBadge = ui.statusBadge(fm.status);
1258
1398
  console.log(`${ui.bold(fm.id)} ${ui.dim(fm.scope)} ${statusBadge}`);
1259
- console.log(` ${ui.dim(path17.relative(root, filePath))}`);
1399
+ console.log(` ${ui.dim(path18.relative(root, filePath))}`);
1260
1400
  const snippet = extractSnippet(mem.body, snippetNeedle);
1261
1401
  if (snippet) console.log(` ${snippet}`);
1262
1402
  }
@@ -1268,22 +1408,22 @@ ${top.length} of ${matches.length} match${matches.length === 1 ? "" : "es"}`)
1268
1408
  }
1269
1409
 
1270
1410
  // src/commands/memory-reject.ts
1271
- import { writeFile as writeFile9 } from "fs/promises";
1272
- import { existsSync as existsSync18 } from "fs";
1411
+ import { writeFile as writeFile10 } from "fs/promises";
1412
+ import { existsSync as existsSync19 } from "fs";
1273
1413
  import "commander";
1274
1414
  import {
1275
- findProjectRoot as findProjectRoot19,
1415
+ findProjectRoot as findProjectRoot21,
1276
1416
  loadUsageIndex as loadUsageIndex6,
1277
1417
  recordRejection,
1278
- resolveHaivePaths as resolveHaivePaths17,
1418
+ resolveHaivePaths as resolveHaivePaths18,
1279
1419
  saveUsageIndex,
1280
- serializeMemory as serializeMemory7
1420
+ serializeMemory as serializeMemory8
1281
1421
  } from "@hiveai/core";
1282
1422
  function registerMemoryReject(memory2) {
1283
1423
  memory2.command("reject <id>").description("Record a rejection (blocks auto-promotion and lowers confidence)").option("-r, --reason <reason>", "why this memory is being rejected").option("-d, --dir <dir>", "project root").action(async (id, opts) => {
1284
- const root = findProjectRoot19(opts.dir);
1285
- const paths = resolveHaivePaths17(root);
1286
- if (!existsSync18(paths.memoriesDir)) {
1424
+ const root = findProjectRoot21(opts.dir);
1425
+ const paths = resolveHaivePaths18(root);
1426
+ if (!existsSync19(paths.memoriesDir)) {
1287
1427
  ui.error(`No .ai/memories at ${root}.`);
1288
1428
  process.exitCode = 1;
1289
1429
  return;
@@ -1295,9 +1435,9 @@ function registerMemoryReject(memory2) {
1295
1435
  process.exitCode = 1;
1296
1436
  return;
1297
1437
  }
1298
- await writeFile9(
1438
+ await writeFile10(
1299
1439
  loaded.filePath,
1300
- serializeMemory7({
1440
+ serializeMemory8({
1301
1441
  frontmatter: {
1302
1442
  ...loaded.memory.frontmatter,
1303
1443
  status: "rejected",
@@ -1319,22 +1459,22 @@ function registerMemoryReject(memory2) {
1319
1459
  }
1320
1460
 
1321
1461
  // src/commands/memory-rm.ts
1322
- import { existsSync as existsSync19 } from "fs";
1462
+ import { existsSync as existsSync20 } from "fs";
1323
1463
  import { unlink as unlink2 } from "fs/promises";
1324
- import path18 from "path";
1464
+ import path19 from "path";
1325
1465
  import { createInterface } from "readline/promises";
1326
1466
  import "commander";
1327
1467
  import {
1328
- findProjectRoot as findProjectRoot20,
1468
+ findProjectRoot as findProjectRoot22,
1329
1469
  loadUsageIndex as loadUsageIndex7,
1330
- resolveHaivePaths as resolveHaivePaths18,
1470
+ resolveHaivePaths as resolveHaivePaths19,
1331
1471
  saveUsageIndex as saveUsageIndex2
1332
1472
  } from "@hiveai/core";
1333
1473
  function registerMemoryRm(memory2) {
1334
1474
  memory2.command("rm <id>").description("Delete a memory file (and its usage entry by default)").option("-y, --yes", "skip the confirmation prompt").option("--keep-usage", "do not remove the usage.json entry").option("-d, --dir <dir>", "project root").action(async (id, opts) => {
1335
- const root = findProjectRoot20(opts.dir);
1336
- const paths = resolveHaivePaths18(root);
1337
- if (!existsSync19(paths.memoriesDir)) {
1475
+ const root = findProjectRoot22(opts.dir);
1476
+ const paths = resolveHaivePaths19(root);
1477
+ if (!existsSync20(paths.memoriesDir)) {
1338
1478
  ui.error(`No .ai/memories at ${root}.`);
1339
1479
  process.exitCode = 1;
1340
1480
  return;
@@ -1346,7 +1486,7 @@ function registerMemoryRm(memory2) {
1346
1486
  process.exitCode = 1;
1347
1487
  return;
1348
1488
  }
1349
- const rel = path18.relative(root, found.filePath);
1489
+ const rel = path19.relative(root, found.filePath);
1350
1490
  if (!opts.yes) {
1351
1491
  const rl = createInterface({ input: process.stdin, output: process.stdout });
1352
1492
  const answer = (await rl.question(`Delete ${rel}? [y/N] `)).trim().toLowerCase();
@@ -1370,22 +1510,22 @@ function registerMemoryRm(memory2) {
1370
1510
  }
1371
1511
 
1372
1512
  // src/commands/memory-show.ts
1373
- import { existsSync as existsSync20 } from "fs";
1374
- import { readFile as readFile4 } from "fs/promises";
1375
- import path19 from "path";
1513
+ import { existsSync as existsSync21 } from "fs";
1514
+ import { readFile as readFile5 } from "fs/promises";
1515
+ import path20 from "path";
1376
1516
  import "commander";
1377
1517
  import {
1378
1518
  deriveConfidence as deriveConfidence2,
1379
- findProjectRoot as findProjectRoot21,
1519
+ findProjectRoot as findProjectRoot23,
1380
1520
  getUsage as getUsage6,
1381
1521
  loadUsageIndex as loadUsageIndex8,
1382
- resolveHaivePaths as resolveHaivePaths19
1522
+ resolveHaivePaths as resolveHaivePaths20
1383
1523
  } from "@hiveai/core";
1384
1524
  function registerMemoryShow(memory2) {
1385
1525
  memory2.command("show <id>").description("Print a memory's frontmatter, body, and confidence/usage").option("--raw", "print the raw file contents instead of a summary").option("-d, --dir <dir>", "project root").action(async (id, opts) => {
1386
- const root = findProjectRoot21(opts.dir);
1387
- const paths = resolveHaivePaths19(root);
1388
- if (!existsSync20(paths.memoriesDir)) {
1526
+ const root = findProjectRoot23(opts.dir);
1527
+ const paths = resolveHaivePaths20(root);
1528
+ if (!existsSync21(paths.memoriesDir)) {
1389
1529
  ui.error(`No .ai/memories at ${root}.`);
1390
1530
  process.exitCode = 1;
1391
1531
  return;
@@ -1398,7 +1538,7 @@ function registerMemoryShow(memory2) {
1398
1538
  return;
1399
1539
  }
1400
1540
  if (opts.raw) {
1401
- console.log(await readFile4(found.filePath, "utf8"));
1541
+ console.log(await readFile5(found.filePath, "utf8"));
1402
1542
  return;
1403
1543
  }
1404
1544
  const fm = found.memory.frontmatter;
@@ -1414,7 +1554,7 @@ function registerMemoryShow(memory2) {
1414
1554
  if (fm.verified_at) console.log(`${ui.dim("verified:")} ${fm.verified_at}`);
1415
1555
  if (fm.stale_reason) console.log(`${ui.dim("stale:")} ${fm.stale_reason}`);
1416
1556
  console.log(`${ui.dim("reads:")} ${u.read_count} ${ui.dim("rejections:")} ${u.rejected_count}`);
1417
- console.log(`${ui.dim("file:")} ${path19.relative(root, found.filePath)}`);
1557
+ console.log(`${ui.dim("file:")} ${path20.relative(root, found.filePath)}`);
1418
1558
  if (fm.anchor.paths.length || fm.anchor.symbols.length) {
1419
1559
  console.log(ui.dim("anchor:"));
1420
1560
  if (fm.anchor.commit) console.log(` ${ui.dim("commit:")} ${fm.anchor.commit}`);
@@ -1429,21 +1569,21 @@ function registerMemoryShow(memory2) {
1429
1569
  }
1430
1570
 
1431
1571
  // src/commands/memory-stats.ts
1432
- import { existsSync as existsSync21 } from "fs";
1433
- import path20 from "path";
1572
+ import { existsSync as existsSync22 } from "fs";
1573
+ import path21 from "path";
1434
1574
  import "commander";
1435
1575
  import {
1436
1576
  deriveConfidence as deriveConfidence3,
1437
- findProjectRoot as findProjectRoot22,
1577
+ findProjectRoot as findProjectRoot24,
1438
1578
  getUsage as getUsage7,
1439
1579
  loadUsageIndex as loadUsageIndex9,
1440
- resolveHaivePaths as resolveHaivePaths20
1580
+ resolveHaivePaths as resolveHaivePaths21
1441
1581
  } from "@hiveai/core";
1442
1582
  function registerMemoryStats(memory2) {
1443
1583
  memory2.command("stats").description("Show usage stats and confidence levels per memory").option("--id <id>", "show stats for a single memory id").option("-d, --dir <dir>", "project root").action(async (opts) => {
1444
- const root = findProjectRoot22(opts.dir);
1445
- const paths = resolveHaivePaths20(root);
1446
- if (!existsSync21(paths.memoriesDir)) {
1584
+ const root = findProjectRoot24(opts.dir);
1585
+ const paths = resolveHaivePaths21(root);
1586
+ if (!existsSync22(paths.memoriesDir)) {
1447
1587
  ui.error(`No .ai/memories at ${root}. Run \`haive init\` first.`);
1448
1588
  process.exitCode = 1;
1449
1589
  return;
@@ -1468,27 +1608,27 @@ function registerMemoryStats(memory2) {
1468
1608
  console.log(
1469
1609
  ` ${ui.dim("status:")} ${fm.status} ${ui.dim("reads:")} ${u.read_count} ${ui.dim("rejections:")} ${u.rejected_count}`
1470
1610
  );
1471
- console.log(` ${ui.dim(path20.relative(root, filePath))}`);
1611
+ console.log(` ${ui.dim(path21.relative(root, filePath))}`);
1472
1612
  }
1473
1613
  });
1474
1614
  }
1475
1615
 
1476
1616
  // src/commands/memory-verify.ts
1477
- import { writeFile as writeFile10 } from "fs/promises";
1478
- import { existsSync as existsSync22 } from "fs";
1479
- import path21 from "path";
1617
+ import { writeFile as writeFile11 } from "fs/promises";
1618
+ import { existsSync as existsSync23 } from "fs";
1619
+ import path22 from "path";
1480
1620
  import "commander";
1481
1621
  import {
1482
- findProjectRoot as findProjectRoot23,
1483
- resolveHaivePaths as resolveHaivePaths21,
1484
- serializeMemory as serializeMemory8,
1622
+ findProjectRoot as findProjectRoot25,
1623
+ resolveHaivePaths as resolveHaivePaths22,
1624
+ serializeMemory as serializeMemory9,
1485
1625
  verifyAnchor as verifyAnchor2
1486
1626
  } from "@hiveai/core";
1487
1627
  function registerMemoryVerify(memory2) {
1488
1628
  memory2.command("verify").description("Check memory anchors against current code, optionally marking stale ones").option("--id <id>", "verify a single memory by id").option("--all", "verify every memory (default if --id is omitted)").option("--update", "write status=stale (or status=validated for re-freshed) back to disk").option("-d, --dir <dir>", "project root").action(async (opts) => {
1489
- const root = findProjectRoot23(opts.dir);
1490
- const paths = resolveHaivePaths21(root);
1491
- if (!existsSync22(paths.memoriesDir)) {
1629
+ const root = findProjectRoot25(opts.dir);
1630
+ const paths = resolveHaivePaths22(root);
1631
+ if (!existsSync23(paths.memoriesDir)) {
1492
1632
  ui.error(`No .ai/memories at ${root}. Run \`haive init\` first.`);
1493
1633
  process.exitCode = 1;
1494
1634
  return;
@@ -1511,7 +1651,7 @@ function registerMemoryVerify(memory2) {
1511
1651
  anchorless++;
1512
1652
  continue;
1513
1653
  }
1514
- const rel = path21.relative(root, filePath);
1654
+ const rel = path22.relative(root, filePath);
1515
1655
  if (result.stale) {
1516
1656
  staleCount++;
1517
1657
  console.log(`${ui.bold("STALE")} ${mem.frontmatter.id}`);
@@ -1523,7 +1663,7 @@ function registerMemoryVerify(memory2) {
1523
1663
  }
1524
1664
  if (opts.update) {
1525
1665
  const next = applyVerification(mem, result);
1526
- await writeFile10(filePath, serializeMemory8(next), "utf8");
1666
+ await writeFile11(filePath, serializeMemory9(next), "utf8");
1527
1667
  updated++;
1528
1668
  }
1529
1669
  }
@@ -1562,11 +1702,12 @@ function applyVerification(mem, result) {
1562
1702
  }
1563
1703
 
1564
1704
  // src/index.ts
1565
- var program = new Command24();
1566
- program.name("haive").description("hAIve \u2014 team-first persistent memory layer for AI coding agents").version("0.2.4");
1705
+ var program = new Command26();
1706
+ program.name("haive").description("hAIve \u2014 team-first persistent memory layer for AI coding agents").version("0.2.6");
1567
1707
  registerInit(program);
1568
1708
  registerMcp(program);
1569
1709
  registerBriefing(program);
1710
+ registerTui(program);
1570
1711
  registerEmbeddings(program);
1571
1712
  registerSync(program);
1572
1713
  registerInstallHooks(program);
@@ -1588,6 +1729,7 @@ registerMemoryPending(memory);
1588
1729
  registerMemoryApprove(memory);
1589
1730
  registerMemoryUpdate(memory);
1590
1731
  registerMemoryHot(memory);
1732
+ registerMemoryTried(memory);
1591
1733
  program.parseAsync(process.argv).catch((err) => {
1592
1734
  if (isZodError(err)) {
1593
1735
  for (const issue of err.issues) {