@hiveai/cli 0.9.20 → 0.9.21

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
@@ -6516,7 +6516,7 @@ When done, respond with: "Imported N memories: [list of IDs]" or "Nothing action
6516
6516
  };
6517
6517
  }
6518
6518
  var SERVER_NAME = "haive";
6519
- var SERVER_VERSION = "0.9.20";
6519
+ var SERVER_VERSION = "0.9.21";
6520
6520
  function jsonResult(data) {
6521
6521
  return {
6522
6522
  content: [
@@ -8718,6 +8718,8 @@ function registerMemoryList(memory2) {
8718
8718
  console.log(
8719
8719
  `${ui.bold(fm.id)} ${ui.dim(fm.scope)}/${ui.dim(fm.type)} ${statusBadge}${moduleStr}${tagStr}`
8720
8720
  );
8721
+ const title = mem.body.match(/^#\s+(.+)$/m)?.[1]?.trim();
8722
+ if (title && title !== fm.id) console.log(` ${title}`);
8721
8723
  console.log(` ${ui.dim(path17.relative(root, filePath))}`);
8722
8724
  }
8723
8725
  console.log(ui.dim(`
@@ -8883,7 +8885,7 @@ function registerMemoryApprove(memory2) {
8883
8885
  }
8884
8886
 
8885
8887
  // src/commands/memory-update.ts
8886
- import { writeFile as writeFile19 } from "fs/promises";
8888
+ import { readFile as readFile11, writeFile as writeFile19 } from "fs/promises";
8887
8889
  import { existsSync as existsSync37 } from "fs";
8888
8890
  import path20 from "path";
8889
8891
  import "commander";
@@ -8893,7 +8895,7 @@ import {
8893
8895
  serializeMemory as serializeMemory16
8894
8896
  } from "@hiveai/core";
8895
8897
  function registerMemoryUpdate(memory2) {
8896
- 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) => {
8898
+ memory2.command("update <id>").description("Update body, tags, or anchor of an existing memory (preserves id and usage history)").option("--type <type>", "change the memory type (convention | decision | gotcha | architecture | glossary | skill | attempt)").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("--body-file <path>", "read new body from a Markdown file \u2014 for long content").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) => {
8897
8899
  const root = findProjectRoot17(opts.dir);
8898
8900
  const paths = resolveHaivePaths14(root);
8899
8901
  if (!existsSync37(paths.memoriesDir)) {
@@ -8926,19 +8928,34 @@ function registerMemoryUpdate(memory2) {
8926
8928
  const newFrontmatter = {
8927
8929
  ...frontmatter,
8928
8930
  anchor: newAnchor,
8931
+ ...opts.type !== void 0 ? { type: opts.type } : {},
8929
8932
  ...opts.tags !== void 0 ? { tags: parseCsv3(opts.tags) } : {},
8930
8933
  ...opts.domain !== void 0 ? { domain: opts.domain } : {},
8931
8934
  ...opts.author !== void 0 ? { author: opts.author } : {}
8932
8935
  };
8936
+ if (opts.type !== void 0) updated.push("type");
8933
8937
  if (opts.tags !== void 0) updated.push("tags");
8934
8938
  if (opts.domain !== void 0) updated.push("domain");
8935
8939
  if (opts.author !== void 0) updated.push("author");
8936
- let newBody = opts.body !== void 0 ? opts.body : body;
8940
+ let newBody;
8941
+ if (opts.bodyFile !== void 0) {
8942
+ if (!existsSync37(opts.bodyFile)) {
8943
+ ui.error(`--body-file not found: ${opts.bodyFile}`);
8944
+ process.exitCode = 1;
8945
+ return;
8946
+ }
8947
+ newBody = await readFile11(opts.bodyFile, "utf8");
8948
+ updated.push("body");
8949
+ } else if (opts.body !== void 0) {
8950
+ newBody = opts.body;
8951
+ updated.push("body");
8952
+ } else {
8953
+ newBody = body;
8954
+ }
8937
8955
  if (opts.title !== void 0) {
8938
8956
  newBody = replaceFirstHeading(newBody, opts.title);
8939
8957
  updated.push("title");
8940
8958
  }
8941
- if (opts.body !== void 0) updated.push("body");
8942
8959
  if (updated.length === 0) {
8943
8960
  ui.warn("Nothing to update \u2014 provide at least one option.");
8944
8961
  return;
@@ -9032,7 +9049,7 @@ function registerMemoryAutoPromote(memory2) {
9032
9049
  // src/commands/memory-edit.ts
9033
9050
  import { spawn as spawn3 } from "child_process";
9034
9051
  import { existsSync as existsSync39 } from "fs";
9035
- import { readFile as readFile11 } from "fs/promises";
9052
+ import { readFile as readFile12 } from "fs/promises";
9036
9053
  import path23 from "path";
9037
9054
  import "commander";
9038
9055
  import {
@@ -9063,7 +9080,7 @@ function registerMemoryEdit(memory2) {
9063
9080
  ui.warn(`Editor exited with status ${code}.`);
9064
9081
  }
9065
9082
  try {
9066
- const fresh = await readFile11(found.filePath, "utf8");
9083
+ const fresh = await readFile12(found.filePath, "utf8");
9067
9084
  parseMemory(fresh);
9068
9085
  ui.success("Memory still parses cleanly.");
9069
9086
  } catch (err) {
@@ -9289,7 +9306,7 @@ function registerMemoryTried(memory2) {
9289
9306
  --instead "use static import in the entry file" \\\\
9290
9307
  --paths packages/cli/src/index.ts
9291
9308
  `
9292
- ).requiredOption("--what <text>", "what approach was tried (short, descriptive title)").requiredOption("--why-failed <text>", "why it failed or should NOT be used (include the exact error if possible)").option("--instead <text>", "the correct approach to use instead").option("--scope <scope>", "personal | team | module (default: personal)", "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) => {
9309
+ ).requiredOption("--what <text>", "what approach was tried (short, descriptive title)").requiredOption("--why-failed <text>", "why it failed or should NOT be used (include the exact error if possible)").option("--instead <text>", "the correct approach to use instead").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) => {
9293
9310
  const root = findProjectRoot22(opts.dir);
9294
9311
  const paths = resolveHaivePaths19(root);
9295
9312
  if (!existsSync43(paths.haiveDir)) {
@@ -9342,7 +9359,7 @@ import {
9342
9359
  resolveHaivePaths as resolveHaivePaths20
9343
9360
  } from "@hiveai/core";
9344
9361
  function registerMemoryPending(memory2) {
9345
- 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) => {
9362
+ memory2.command("pending").description("List draft and proposed memories awaiting review (sorted by reads desc).\n\n draft = created but not yet activated \xB7 proposed = promoted, awaiting team validation").option("--scope <scope>", "filter by scope (personal | team | module)").option("-d, --dir <dir>", "project root").action(async (opts) => {
9346
9363
  const root = findProjectRoot23(opts.dir);
9347
9364
  const paths = resolveHaivePaths20(root);
9348
9365
  if (!existsSync44(paths.memoriesDir)) {
@@ -9352,30 +9369,53 @@ function registerMemoryPending(memory2) {
9352
9369
  }
9353
9370
  const all = await loadMemoriesFromDir26(paths.memoriesDir);
9354
9371
  const usage = await loadUsageIndex17(paths);
9355
- const proposed = all.filter(({ memory: mem }) => {
9356
- if (mem.frontmatter.status !== "proposed") return false;
9372
+ const filterFn = ({ memory: mem }) => {
9373
+ if (mem.frontmatter.status !== "proposed" && mem.frontmatter.status !== "draft") return false;
9357
9374
  if (opts.scope && mem.frontmatter.scope !== opts.scope) return false;
9358
9375
  return true;
9359
- });
9360
- if (proposed.length === 0) {
9361
- ui.info("No memories awaiting review.");
9376
+ };
9377
+ const pending = all.filter(filterFn);
9378
+ if (pending.length === 0) {
9379
+ ui.info("No draft or proposed memories awaiting review.");
9380
+ ui.info("Drafts are created by `haive memory add` without `--status validated`.");
9362
9381
  return;
9363
9382
  }
9364
- proposed.sort(
9383
+ pending.sort(
9365
9384
  (a, b) => getUsage15(usage, b.memory.frontmatter.id).read_count - getUsage15(usage, a.memory.frontmatter.id).read_count
9366
9385
  );
9367
9386
  const now = Date.now();
9368
- for (const { memory: mem, filePath } of proposed) {
9369
- const fm = mem.frontmatter;
9370
- const u = getUsage15(usage, fm.id);
9371
- const ageDays = Math.floor((now - new Date(fm.created_at).getTime()) / 864e5);
9372
- const ageStr = ageDays === 0 ? "today" : `${ageDays}d`;
9373
- console.log(
9374
- `${ui.bold(fm.id)} ${ui.dim(`${fm.scope}/${fm.type}`)} ${ui.dim(`age=${ageStr} reads=${u.read_count} rejections=${u.rejected_count}`)}`
9375
- );
9376
- console.log(` ${ui.dim(path27.relative(root, filePath))}`);
9387
+ const drafts = pending.filter((m) => m.memory.frontmatter.status === "draft");
9388
+ const proposed = pending.filter((m) => m.memory.frontmatter.status === "proposed");
9389
+ if (proposed.length > 0) {
9390
+ console.log(ui.bold(`Proposed (${proposed.length}) \u2014 awaiting team validation`));
9391
+ for (const { memory: mem, filePath } of proposed) {
9392
+ const fm = mem.frontmatter;
9393
+ const u = getUsage15(usage, fm.id);
9394
+ const ageDays = Math.floor((now - new Date(fm.created_at).getTime()) / 864e5);
9395
+ const ageStr = ageDays === 0 ? "today" : `${ageDays}d`;
9396
+ console.log(
9397
+ ` ${ui.bold(fm.id)} ${ui.dim(`${fm.scope}/${fm.type}`)} ${ui.dim(`age=${ageStr} reads=${u.read_count}`)}`
9398
+ );
9399
+ console.log(` ${ui.dim(path27.relative(root, filePath))}`);
9400
+ }
9401
+ if (proposed.length > 0) console.log(ui.dim(` \u2192 haive memory approve <id> or haive memory auto-promote`));
9402
+ console.log();
9403
+ }
9404
+ if (drafts.length > 0) {
9405
+ console.log(ui.bold(`Draft (${drafts.length}) \u2014 created but not yet activated`));
9406
+ for (const { memory: mem, filePath } of drafts) {
9407
+ const fm = mem.frontmatter;
9408
+ const u = getUsage15(usage, fm.id);
9409
+ const ageDays = Math.floor((now - new Date(fm.created_at).getTime()) / 864e5);
9410
+ const ageStr = ageDays === 0 ? "today" : `${ageDays}d`;
9411
+ console.log(
9412
+ ` ${ui.bold(fm.id)} ${ui.dim(`${fm.scope}/${fm.type}`)} ${ui.dim(`age=${ageStr} reads=${u.read_count}`)}`
9413
+ );
9414
+ console.log(` ${ui.dim(path27.relative(root, filePath))}`);
9415
+ }
9416
+ console.log(ui.dim(` \u2192 haive memory approve <id> (activate) | haive memory promote <id> (share with team)`));
9377
9417
  }
9378
- ui.info(`${proposed.length} pending`);
9418
+ ui.info(`${pending.length} total pending (${proposed.length} proposed \xB7 ${drafts.length} draft)`);
9379
9419
  });
9380
9420
  }
9381
9421
 
@@ -9558,7 +9598,7 @@ function registerMemoryRm(memory2) {
9558
9598
 
9559
9599
  // src/commands/memory-show.ts
9560
9600
  import { existsSync as existsSync48 } from "fs";
9561
- import { readFile as readFile12 } from "fs/promises";
9601
+ import { readFile as readFile13 } from "fs/promises";
9562
9602
  import path30 from "path";
9563
9603
  import "commander";
9564
9604
  import {
@@ -9585,7 +9625,7 @@ function registerMemoryShow(memory2) {
9585
9625
  return;
9586
9626
  }
9587
9627
  if (opts.raw) {
9588
- console.log(await readFile12(found.filePath, "utf8"));
9628
+ console.log(await readFile13(found.filePath, "utf8"));
9589
9629
  return;
9590
9630
  }
9591
9631
  const fm = found.memory.frontmatter;
@@ -9763,7 +9803,7 @@ function applyVerification2(mem, result) {
9763
9803
  }
9764
9804
 
9765
9805
  // src/commands/memory-import.ts
9766
- import { readFile as readFile13 } from "fs/promises";
9806
+ import { readFile as readFile14 } from "fs/promises";
9767
9807
  import { existsSync as existsSync51 } from "fs";
9768
9808
  import "commander";
9769
9809
  import {
@@ -9786,7 +9826,7 @@ function registerMemoryImport(memory2) {
9786
9826
  process.exitCode = 1;
9787
9827
  return;
9788
9828
  }
9789
- const content = await readFile13(opts.from, "utf8");
9829
+ const content = await readFile14(opts.from, "utf8");
9790
9830
  const scope = opts.scope ?? "team";
9791
9831
  ui.info(`Preparing import from: ${opts.from} (scope=${scope})`);
9792
9832
  ui.info(`Content length: ${content.length} chars`);
@@ -9815,7 +9855,7 @@ function registerMemoryImport(memory2) {
9815
9855
 
9816
9856
  // src/commands/memory-import-changelog.ts
9817
9857
  import { existsSync as existsSync53 } from "fs";
9818
- import { readFile as readFile14, mkdir as mkdir14, writeFile as writeFile25 } from "fs/promises";
9858
+ import { readFile as readFile15, mkdir as mkdir14, writeFile as writeFile25 } from "fs/promises";
9819
9859
  import path34 from "path";
9820
9860
  import "commander";
9821
9861
  import {
@@ -9894,7 +9934,7 @@ function registerMemoryImportChangelog(memory2) {
9894
9934
  process.exitCode = 1;
9895
9935
  return;
9896
9936
  }
9897
- const content = await readFile14(changelogPath, "utf8");
9937
+ const content = await readFile15(changelogPath, "utf8");
9898
9938
  let entries = parseChangelog(content);
9899
9939
  if (entries.length === 0) {
9900
9940
  ui.warn("No breaking changes, deprecations, or removals found in the CHANGELOG.");
@@ -10083,7 +10123,7 @@ function registerMemoryDigest(program2) {
10083
10123
  }
10084
10124
 
10085
10125
  // src/commands/session-end.ts
10086
- import { writeFile as writeFile27, mkdir as mkdir15, readFile as readFile15, rm as rm2 } from "fs/promises";
10126
+ import { writeFile as writeFile27, mkdir as mkdir15, readFile as readFile16, rm as rm2 } from "fs/promises";
10087
10127
  import { existsSync as existsSync55 } from "fs";
10088
10128
  import path36 from "path";
10089
10129
  import "commander";
@@ -10098,7 +10138,7 @@ import {
10098
10138
  async function buildAutoRecap(paths) {
10099
10139
  const obsFile = path36.join(paths.haiveDir, ".cache", "observations.jsonl");
10100
10140
  if (!existsSync55(obsFile)) return null;
10101
- const raw = await readFile15(obsFile, "utf8").catch(() => "");
10141
+ const raw = await readFile16(obsFile, "utf8").catch(() => "");
10102
10142
  if (!raw.trim()) return null;
10103
10143
  const lines = raw.split("\n").filter(Boolean);
10104
10144
  const obs = [];
@@ -10443,7 +10483,7 @@ function detectFormat(filePath) {
10443
10483
 
10444
10484
  // src/commands/hub.ts
10445
10485
  import { existsSync as existsSync57 } from "fs";
10446
- import { mkdir as mkdir16, readFile as readFile16, writeFile as writeFile28, copyFile } from "fs/promises";
10486
+ import { mkdir as mkdir16, readFile as readFile17, writeFile as writeFile28, copyFile } from "fs/promises";
10447
10487
  import path38 from "path";
10448
10488
  import { spawnSync as spawnSync5 } from "child_process";
10449
10489
  import "commander";
@@ -10638,7 +10678,7 @@ Next steps:
10638
10678
  for (const file of sourceFiles) {
10639
10679
  const srcPath = path38.join(sourceDir, file);
10640
10680
  const destPath = path38.join(destDir, file);
10641
- const fileContent = await readFile16(srcPath, "utf8");
10681
+ const fileContent = await readFile17(srcPath, "utf8");
10642
10682
  const alreadyTagged = fileContent.includes(`cross-repo:${sourceName}`);
10643
10683
  if (!alreadyTagged) {
10644
10684
  await copyFile(srcPath, destPath);
@@ -10690,7 +10730,7 @@ Next steps:
10690
10730
  if (outgoing.length > 0) {
10691
10731
  console.log(ui.dim(" Run `haive hub push` to publish them to the hub."));
10692
10732
  }
10693
- void readFile16;
10733
+ void readFile17;
10694
10734
  void writeFile28;
10695
10735
  void saveConfig3;
10696
10736
  });
@@ -10997,7 +11037,7 @@ function summarize(name, t0, payload, notes) {
10997
11037
 
10998
11038
  // src/commands/benchmark.ts
10999
11039
  import { existsSync as existsSync59 } from "fs";
11000
- import { readdir as readdir5, readFile as readFile17, writeFile as writeFile30 } from "fs/promises";
11040
+ import { readdir as readdir5, readFile as readFile18, writeFile as writeFile30 } from "fs/promises";
11001
11041
  import path40 from "path";
11002
11042
  import "commander";
11003
11043
  import { estimateTokens as estimateTokens4, findProjectRoot as findProjectRoot38 } from "@hiveai/core";
@@ -11052,7 +11092,7 @@ async function collectRows(root) {
11052
11092
  const fixtureDir = path40.join(root, entry.name);
11053
11093
  const reportFile = path40.join(fixtureDir, "BENCHMARK_AGENT_REPORT.md");
11054
11094
  if (!existsSync59(reportFile)) continue;
11055
- const report = await readFile17(reportFile, "utf8");
11095
+ const report = await readFile18(reportFile, "utf8");
11056
11096
  rows.push(parseAgentReport(entry.name, report));
11057
11097
  }
11058
11098
  return rows.sort((a, b) => a.fixture.localeCompare(b.fixture));
@@ -11463,7 +11503,7 @@ function parseDays(input) {
11463
11503
 
11464
11504
  // src/commands/doctor.ts
11465
11505
  import { existsSync as existsSync63 } from "fs";
11466
- import { readFile as readFile18, stat } from "fs/promises";
11506
+ import { readFile as readFile19, stat } from "fs/promises";
11467
11507
  import path44 from "path";
11468
11508
  import { execFileSync, execSync as execSync3 } from "child_process";
11469
11509
  import "commander";
@@ -11516,8 +11556,8 @@ function registerDoctor(program2) {
11516
11556
  fix: "haive init"
11517
11557
  });
11518
11558
  } else {
11519
- const { readFile: readFile20 } = await import("fs/promises");
11520
- const content = await readFile20(paths.projectContext, "utf8");
11559
+ const { readFile: readFile21 } = await import("fs/promises");
11560
+ const content = await readFile21(paths.projectContext, "utf8");
11521
11561
  const isTemplate = content.includes("TODO \u2014 high-level overview") || content.includes("Generated by `haive init`");
11522
11562
  if (isTemplate) {
11523
11563
  findings.push({
@@ -11666,8 +11706,8 @@ function registerDoctor(program2) {
11666
11706
  let hasClaudeEnforcement = false;
11667
11707
  if (existsSync63(claudeSettings)) {
11668
11708
  try {
11669
- const { readFile: readFile20 } = await import("fs/promises");
11670
- const raw = await readFile20(claudeSettings, "utf8");
11709
+ const { readFile: readFile21 } = await import("fs/promises");
11710
+ const raw = await readFile21(claudeSettings, "utf8");
11671
11711
  hasClaudeEnforcement = raw.includes("haive enforce session-start") && raw.includes("haive enforce pre-tool-use");
11672
11712
  } catch {
11673
11713
  hasClaudeEnforcement = false;
@@ -11690,14 +11730,14 @@ function registerDoctor(program2) {
11690
11730
  fix: "Edit .ai/haive.config.json: set autoSessionEnd: true (or re-run `haive init` without --manual)."
11691
11731
  });
11692
11732
  }
11693
- findings.push(...await collectInstallFindings(root, "0.9.20"));
11733
+ findings.push(...await collectInstallFindings(root, "0.9.21"));
11694
11734
  try {
11695
11735
  const legacyRaw = execSync3("haive-mcp --version", {
11696
11736
  encoding: "utf8",
11697
11737
  timeout: 3e3,
11698
11738
  stdio: ["ignore", "pipe", "ignore"]
11699
11739
  }).trim();
11700
- const cliVersion = "0.9.20";
11740
+ const cliVersion = "0.9.21";
11701
11741
  if (legacyRaw && legacyRaw !== cliVersion) {
11702
11742
  findings.push({
11703
11743
  severity: "warn",
@@ -11960,7 +12000,7 @@ which -a haive`
11960
12000
  for (const rel of integrationFiles) {
11961
12001
  const file = path44.join(root, rel);
11962
12002
  if (!existsSync63(file)) continue;
11963
- const text = await readFile18(file, "utf8").catch(() => "");
12003
+ const text = await readFile19(file, "utf8").catch(() => "");
11964
12004
  for (const bin of extractAbsoluteHaiveBins(text)) {
11965
12005
  const version = versionForBinary(bin);
11966
12006
  if (!version) {
@@ -12494,7 +12534,7 @@ function registerMemoryConflictCandidates(memory2) {
12494
12534
  // src/commands/enforce.ts
12495
12535
  import { execFileSync as execFileSync2, spawn as spawn5 } from "child_process";
12496
12536
  import { existsSync as existsSync69 } from "fs";
12497
- import { chmod as chmod2, mkdir as mkdir19, readFile as readFile19, rm as rm3, writeFile as writeFile34 } from "fs/promises";
12537
+ import { chmod as chmod2, mkdir as mkdir19, readFile as readFile20, rm as rm3, writeFile as writeFile34 } from "fs/promises";
12498
12538
  import path49 from "path";
12499
12539
  import "commander";
12500
12540
  import {
@@ -12800,7 +12840,7 @@ async function buildEnforcementReport(dir, stage, sessionId) {
12800
12840
  findings: [{ severity: "info", code: "enforcement-off", message: "hAIve enforcement is disabled." }]
12801
12841
  });
12802
12842
  }
12803
- findings.push(...await inspectIntegrationVersions(root, "0.9.20"));
12843
+ findings.push(...await inspectIntegrationVersions(root, "0.9.21"));
12804
12844
  if (config.enforcement?.requireBriefingFirst !== false && stage !== "ci") {
12805
12845
  const hasBriefing = await hasRecentBriefingMarker(paths, sessionId);
12806
12846
  findings.push(hasBriefing ? { severity: "ok", code: "briefing-loaded", message: "A recent hAIve briefing marker exists." } : {
@@ -13012,7 +13052,7 @@ async function inspectIntegrationVersions(root, expectedVersion) {
13012
13052
  for (const rel of files) {
13013
13053
  const file = path49.join(root, rel);
13014
13054
  if (!existsSync69(file)) continue;
13015
- const text = await readFile19(file, "utf8").catch(() => "");
13055
+ const text = await readFile20(file, "utf8").catch(() => "");
13016
13056
  for (const bin of extractAbsoluteHaiveBins2(text)) {
13017
13057
  const version = versionForBinary2(bin);
13018
13058
  if (!version) {
@@ -13125,7 +13165,7 @@ haive enforce check --stage pre-push --dir . || exit $?
13125
13165
  for (const hook of hooks) {
13126
13166
  const file = path49.join(hooksDir, hook.name);
13127
13167
  if (existsSync69(file)) {
13128
- const current = await readFile19(file, "utf8").catch(() => "");
13168
+ const current = await readFile20(file, "utf8").catch(() => "");
13129
13169
  if (current.includes(ENFORCE_HOOK_MARKER)) {
13130
13170
  await writeFile34(file, hook.body, "utf8");
13131
13171
  } else {
@@ -13288,7 +13328,7 @@ function registerRun(program2) {
13288
13328
 
13289
13329
  // src/index.ts
13290
13330
  var program = new Command51();
13291
- program.name("haive").description("hAIve \u2014 the memory and enforcement layer of your agent harness").version("0.9.20").option("--advanced", "show maintenance and experimental commands in help");
13331
+ program.name("haive").description("hAIve \u2014 the memory and enforcement layer of your agent harness").version("0.9.21").option("--advanced", "show maintenance and experimental commands in help");
13292
13332
  registerInit(program);
13293
13333
  registerWelcome(program);
13294
13334
  registerResolveProject(program);
@@ -13331,7 +13371,9 @@ registerMemoryTimeline(memory);
13331
13371
  registerMemoryConflictCandidates(memory);
13332
13372
  registerMemoryArchive(memory);
13333
13373
  registerMemoryLint(memory);
13334
- var session = program.command("session").description("Manage session lifecycle");
13374
+ var session = program.command("session").description(
13375
+ "Manage session lifecycle.\n\n Session start is automatic \u2014 hAIve loads context via `get_briefing` at the start\n of each agent session (Claude Code SessionStart hook or MCP first call).\n Use `haive session end` to save a rich end-of-session recap for the next session."
13376
+ );
13335
13377
  registerSessionEnd(session);
13336
13378
  registerSnapshot(program);
13337
13379
  registerHub(program);
@@ -13344,6 +13386,7 @@ registerPrecommit(program);
13344
13386
  var CORE_ROOT_COMMANDS = /* @__PURE__ */ new Set([
13345
13387
  "init",
13346
13388
  "doctor",
13389
+ "tui",
13347
13390
  "agent",
13348
13391
  "enforce",
13349
13392
  "run",