@hiveai/cli 0.9.30 → 0.10.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.
package/dist/index.js CHANGED
@@ -253,7 +253,8 @@ import {
253
253
  loadMemoriesFromDir,
254
254
  loadUsageIndex,
255
255
  resolveHaivePaths,
256
- serializeMemory
256
+ serializeMemory,
257
+ specificityScore
257
258
  } from "@hiveai/core";
258
259
  async function lintMemoriesAsync(root, options = {}) {
259
260
  const paths = resolveHaivePaths(root);
@@ -289,6 +290,15 @@ async function lintMemoriesAsync(root, options = {}) {
289
290
  message: "Record does not contain obvious action/rationale words. Add the concrete rule, why it exists, and what to do instead."
290
291
  });
291
292
  }
293
+ if (["decision", "gotcha", "convention", "architecture"].includes(fm.type) && fm.status !== "rejected" && naked.length >= 40 && specificityScore(naked) < 0.2) {
294
+ out.push({
295
+ file: filePath,
296
+ id: fm.id,
297
+ severity: "info",
298
+ code: "LOW_VALUE_GUESSABLE",
299
+ message: "Reads like generic best practice a capable model already follows. hAIve's value is UNGUESSABLE team knowledge \u2014 add the concrete, arbitrary specifics (exact names, values, formats, magic numbers) or consider removing it to keep briefings high-signal."
300
+ });
301
+ }
292
302
  const suggestedAnchors = suggestAnchors(root, { filePath, memory: memory2 }, codeMap, trackedFiles);
293
303
  if (ANCHOR_TYPES.has(fm.type) && fm.anchor.paths.length === 0 && fm.status === "validated") {
294
304
  out.push({
@@ -935,12 +945,10 @@ function registerBriefing(program2) {
935
945
  if (existsSync3(paths.projectContext) && !stopped()) {
936
946
  const ctx = await readFile2(paths.projectContext, "utf8");
937
947
  const isTemplate = ctx.includes("TODO \u2014 high-level overview") || ctx.includes("Generated by `haive init`");
938
- if (isTemplate) {
948
+ const bootstrapUnfilled = /Auto-generated by `haive init/i.test(ctx) && (ctx.match(/TODO —/g)?.length ?? 0) >= 2;
949
+ if (isTemplate || bootstrapUnfilled) {
939
950
  ui.warn(
940
- "project-context.md still contains the default template \u2014 get_briefing will return little value."
941
- );
942
- ui.warn(
943
- "Fix: in your AI client, invoke the MCP prompt bootstrap_project to auto-fill it from your codebase."
951
+ "project-context.md is still auto-generated/unfilled \u2014 skipping it (low value). Fill it in, or invoke the bootstrap_project MCP prompt for real context."
944
952
  );
945
953
  out("");
946
954
  } else {
@@ -3701,6 +3709,7 @@ import { existsSync as existsSync15 } from "fs";
3701
3709
  import path62 from "path";
3702
3710
  import {
3703
3711
  buildFrontmatter as buildFrontmatter3,
3712
+ isLikelyGuessable,
3704
3713
  memoryFilePath as memoryFilePath3,
3705
3714
  serializeMemory as serializeMemory7
3706
3715
  } from "@hiveai/core";
@@ -3750,6 +3759,8 @@ import {
3750
3759
  queryCodeMap as queryCodeMap2,
3751
3760
  resolveBriefingBudget as resolveBriefingBudget2,
3752
3761
  serializeMemory as serializeMemory9,
3762
+ specificityScore as specificityScore2,
3763
+ GUESSABLE_THRESHOLD,
3753
3764
  tokenizeQuery as tokenizeQuery22,
3754
3765
  trackReads as trackReads3,
3755
3766
  truncateToTokens,
@@ -4780,12 +4791,25 @@ var MemObserveInputSchema = {
4780
4791
  scope: z15.enum(["personal", "team", "module"]).default("team").describe("Visibility scope \u2014 defaults to team since discoveries benefit everyone"),
4781
4792
  module: z15.string().optional().describe("Module name (required when scope=module)"),
4782
4793
  tags: z15.array(z15.string()).default([]).describe("Tags for filtering"),
4783
- author: z15.string().optional().describe("Author handle or email")
4794
+ author: z15.string().optional().describe("Author handle or email"),
4795
+ force: z15.boolean().default(false).describe(
4796
+ "Save even if the observation looks like generic, guessable knowledge. By default, low-specificity observations (things a capable model already knows) are SKIPPED to keep the corpus high-signal \u2014 only unguessable, team-specific discoveries are worth storing."
4797
+ )
4784
4798
  };
4785
4799
  async function memObserve(input, ctx) {
4786
4800
  if (!existsSync15(ctx.paths.haiveDir)) {
4787
4801
  throw new Error(`No .ai/ directory at ${ctx.paths.root}. Run 'haive init' first.`);
4788
4802
  }
4803
+ const signalText = [input.what, input.impact, input.fix ?? ""].join(" ");
4804
+ if (!input.force && isLikelyGuessable(signalText)) {
4805
+ return {
4806
+ id: "",
4807
+ scope: input.scope,
4808
+ file_path: "",
4809
+ skipped: true,
4810
+ reason: "Observation looks like generic, guessable knowledge (low specificity) \u2014 not saved. Capture only arbitrary, team-specific facts (exact names, values, formats). Pass force=true to override."
4811
+ };
4812
+ }
4789
4813
  const slug = input.what.toLowerCase().replace(/[^a-z0-9\s]/g, "").trim().split(/\s+/).slice(0, 6).join("-");
4790
4814
  const anchorPaths = input.where.split(/[,\n]/).map((s) => s.trim()).filter(Boolean);
4791
4815
  const baseFm = buildFrontmatter3({
@@ -5472,6 +5496,14 @@ When done, call \`mem_session_end\` to acknowledge \u2014 this clears the pendin
5472
5496
  const memoriesEmpty = outputMemories.length === 0;
5473
5497
  const hasMemoriesDir = existsSync18(ctx.paths.memoriesDir);
5474
5498
  const isColdStart = isTemplateContext && memoriesEmpty && !lastSession && !autoContextGenerated;
5499
+ const hasUnguessableSignal = outputMemories.some(
5500
+ (m) => (m.priority === "must_read" || m.priority === "useful") && specificityScore2(m.body) >= GUESSABLE_THRESHOLD
5501
+ );
5502
+ const briefingValueLow = !hasUnguessableSignal;
5503
+ const adaptiveConfig = await loadConfig3(ctx.paths);
5504
+ const bootstrapUnfilled = /Auto-generated by `haive init/i.test(projectContextRaw) && (projectContextRaw.match(/TODO —/g)?.length ?? 0) >= 2;
5505
+ const contextIsInferable = isTemplateContext || autoContextGenerated || bootstrapUnfilled;
5506
+ const adaptiveTrim = adaptiveConfig.adaptiveBriefing !== false && briefingValueLow && contextIsInferable;
5475
5507
  const hints = [];
5476
5508
  if (isColdStart) {
5477
5509
  hints.push(
@@ -5504,6 +5536,11 @@ When done, call \`mem_session_end\` to acknowledge \u2014 this clears the pendin
5504
5536
  );
5505
5537
  }
5506
5538
  }
5539
+ if (adaptiveTrim) {
5540
+ hints.push(
5541
+ "No team-specific policy matched these files/task \u2014 nothing here a capable model can't infer. The auto-generated project context was trimmed to keep this briefing near-zero-cost; proceed with normal Read/Grep."
5542
+ );
5543
+ }
5507
5544
  if (existsSync18(ctx.paths.haiveDir)) {
5508
5545
  await writeBriefingMarker2(ctx.paths, {
5509
5546
  sessionId: process.env.HAIVE_SESSION_ID,
@@ -5519,7 +5556,12 @@ When done, call \`mem_session_end\` to acknowledge \u2014 this clears the pendin
5519
5556
  search_mode: searchMode,
5520
5557
  inferred_modules: inferred,
5521
5558
  ...lastSession ? { last_session: lastSession } : {},
5522
- project_context: projectContextRaw || autoContextGenerated ? {
5559
+ project_context: adaptiveTrim ? {
5560
+ content: "(adaptive briefing: auto-generated context omitted \u2014 no team-specific policy matched, so a capable model needs nothing extra here)",
5561
+ truncated: false,
5562
+ ...isTemplateContext && !autoContextGenerated ? { is_template: true } : {},
5563
+ ...autoContextGenerated ? { auto_generated: true } : {}
5564
+ } : projectContextRaw || autoContextGenerated ? {
5523
5565
  content: projectSlice.text,
5524
5566
  truncated: projectSlice.truncated,
5525
5567
  ...isTemplateContext && !autoContextGenerated ? { is_template: true } : {},
@@ -5533,6 +5575,7 @@ When done, call \`mem_session_end\` to acknowledge \u2014 this clears the pendin
5533
5575
  decay_warnings: decayWarnings,
5534
5576
  setup_warnings: setupWarnings,
5535
5577
  ...isColdStart ? { low_value: true } : {},
5578
+ briefing_value: briefingValueLow ? "low" : "high",
5536
5579
  ...hints.length > 0 ? { hints } : {},
5537
5580
  estimated_tokens: totalTokens,
5538
5581
  budget: {
@@ -6061,8 +6104,12 @@ var CODE_STOPWORDS = /* @__PURE__ */ new Set([
6061
6104
  "console"
6062
6105
  ]);
6063
6106
  function tokenizeDiffForLiteral(diff) {
6064
- const wsTokens = tokenizeQuery3(diff);
6065
- const wordTokens = diff.toLowerCase().split(/[^a-z0-9]+/).filter((t) => t.length >= 4 && !CODE_STOPWORDS.has(t));
6107
+ const lines = diff.split("\n");
6108
+ const looksLikeDiff = lines.some((l) => /^[+-]/.test(l));
6109
+ const addedOnly = looksLikeDiff ? lines.filter((l) => l.startsWith("+") && !l.startsWith("+++")).join("\n") : diff;
6110
+ const source = addedOnly.trim().length > 0 ? addedOnly : diff;
6111
+ const wsTokens = tokenizeQuery3(source);
6112
+ const wordTokens = source.toLowerCase().split(/[^a-z0-9]+/).filter((t) => t.length >= 4 && !CODE_STOPWORDS.has(t));
6066
6113
  return [.../* @__PURE__ */ new Set([...wsTokens, ...wordTokens])];
6067
6114
  }
6068
6115
  async function antiPatternsCheck(input, ctx) {
@@ -7323,7 +7370,7 @@ When done, respond with: "Imported N memories: [list of IDs]" or "Nothing action
7323
7370
  };
7324
7371
  }
7325
7372
  var SERVER_NAME = "haive";
7326
- var SERVER_VERSION = "0.9.30";
7373
+ var SERVER_VERSION = "0.10.0";
7327
7374
  function jsonResult(data) {
7328
7375
  return {
7329
7376
  content: [
@@ -12043,6 +12090,7 @@ import "commander";
12043
12090
  import {
12044
12091
  findProjectRoot as findProjectRoot41,
12045
12092
  getUsage as getUsage18,
12093
+ loadConfig as loadConfig10,
12046
12094
  loadMemoriesFromDir as loadMemoriesFromDir31,
12047
12095
  loadUsageIndex as loadUsageIndex24,
12048
12096
  resolveHaivePaths as resolveHaivePaths37,
@@ -12052,7 +12100,7 @@ var MS_PER_DAY2 = 24 * 60 * 60 * 1e3;
12052
12100
  function registerMemoryArchive(memory2) {
12053
12101
  memory2.command("archive").description(
12054
12102
  "Archive obsolete memories: marks status='deprecated' for memories not read in N days\n whose anchored paths have all disappeared (or have no anchor at all).\n\n Defaults to a DRY RUN \u2014 pass --apply to actually rewrite files.\n Targets `attempt` memories by default since they age the fastest.\n\n Recover later with `haive memory edit <id>` to set status back to validated."
12055
- ).option("--since <window>", "minimum age since last read (e.g. '180d', '6m')", "180d").option("--type <type>", "limit to a memory type (default 'attempt'). Pass 'all' to scan all types.", "attempt").option("--apply", "actually rewrite files (default: dry run)", false).option("--json", "emit JSON instead of human-readable output", false).option("-d, --dir <dir>", "project root").action(async (opts) => {
12103
+ ).option("--since <window>", "minimum age since last read (e.g. '180d', '6m'). Default: enforcement.decayAfterDays or 180d").option("--type <type>", "limit to a memory type (default 'attempt'). Pass 'all' to scan all types.", "attempt").option("--unread", "decay by unread-age ALONE (ignore anchor status) \u2014 more aggressive corpus hygiene", false).option("--apply", "actually rewrite files (default: dry run)", false).option("--json", "emit JSON instead of human-readable output", false).option("-d, --dir <dir>", "project root").action(async (opts) => {
12056
12104
  const root = findProjectRoot41(opts.dir);
12057
12105
  const paths = resolveHaivePaths37(root);
12058
12106
  if (!existsSync60(paths.memoriesDir)) {
@@ -12060,7 +12108,9 @@ function registerMemoryArchive(memory2) {
12060
12108
  process.exitCode = 1;
12061
12109
  return;
12062
12110
  }
12063
- const minDays = parseDays(opts.since ?? "180d");
12111
+ const config = await loadConfig10(paths);
12112
+ const defaultWindow = config.enforcement?.decayAfterDays ? `${config.enforcement.decayAfterDays}d` : "180d";
12113
+ const minDays = parseDays(opts.since ?? defaultWindow);
12064
12114
  if (minDays === null) {
12065
12115
  ui.error(`Invalid --since value: ${opts.since}. Use formats like '180d', '6m', '1y'.`);
12066
12116
  process.exitCode = 1;
@@ -12074,20 +12124,22 @@ function registerMemoryArchive(memory2) {
12074
12124
  for (const { memory: mem, filePath } of all) {
12075
12125
  const fm = mem.frontmatter;
12076
12126
  if (typeFilter && fm.type !== typeFilter) continue;
12127
+ if (fm.type === "session_recap" || fm.requires_human_approval) continue;
12077
12128
  if (fm.status === "deprecated" || fm.status === "rejected") continue;
12078
12129
  const hasAnyAnchor = fm.anchor.paths.length + fm.anchor.symbols.length > 0;
12079
12130
  const allPathsGone = fm.anchor.paths.length > 0 && fm.anchor.paths.every((p) => !existsSync60(path44.join(paths.root, p)));
12080
12131
  const isAnchorless = !hasAnyAnchor;
12081
- if (!isAnchorless && !allPathsGone) continue;
12132
+ if (!opts.unread && !isAnchorless && !allPathsGone) continue;
12082
12133
  const u = getUsage18(usage, fm.id);
12083
12134
  const lastSeen = u.last_read_at ?? fm.created_at;
12084
12135
  if (Date.parse(lastSeen) >= cutoff) continue;
12136
+ const reason = isAnchorless ? `anchorless and not read since ${lastSeen.slice(0, 10)}` : allPathsGone ? `all ${fm.anchor.paths.length} anchored path(s) missing and not read since ${lastSeen.slice(0, 10)}` : `not read since ${lastSeen.slice(0, 10)} (unread decay)`;
12085
12137
  candidates.push({
12086
12138
  id: fm.id,
12087
12139
  type: fm.type,
12088
12140
  status: fm.status,
12089
12141
  last_seen: lastSeen,
12090
- reason: isAnchorless ? `anchorless and not read since ${lastSeen.slice(0, 10)}` : `all ${fm.anchor.paths.length} anchored path(s) missing and not read since ${lastSeen.slice(0, 10)}`,
12142
+ reason,
12091
12143
  filePath
12092
12144
  });
12093
12145
  }
@@ -12160,7 +12212,7 @@ import {
12160
12212
  findProjectRoot as findProjectRoot42,
12161
12213
  getUsage as getUsage19,
12162
12214
  loadCodeMap as loadCodeMap7,
12163
- loadConfig as loadConfig10,
12215
+ loadConfig as loadConfig11,
12164
12216
  loadMemoriesFromDir as loadMemoriesFromDir33,
12165
12217
  loadUsageIndex as loadUsageIndex25,
12166
12218
  readUsageEvents as readUsageEvents4,
@@ -12175,7 +12227,7 @@ function registerDoctor(program2) {
12175
12227
  const paths = resolveHaivePaths38(root);
12176
12228
  const findings = [];
12177
12229
  const repairs = [];
12178
- const config = await loadConfig10(paths);
12230
+ const config = await loadConfig11(paths);
12179
12231
  if (!existsSync61(paths.haiveDir)) {
12180
12232
  findings.push({
12181
12233
  severity: "error",
@@ -12395,14 +12447,14 @@ function registerDoctor(program2) {
12395
12447
  fix: "Edit .ai/haive.config.json: set autoSessionEnd: true (or re-run `haive init` without --manual)."
12396
12448
  });
12397
12449
  }
12398
- findings.push(...await collectInstallFindings(root, "0.9.30"));
12450
+ findings.push(...await collectInstallFindings(root, "0.10.0"));
12399
12451
  try {
12400
12452
  const legacyRaw = execSync3("haive-mcp --version", {
12401
12453
  encoding: "utf8",
12402
12454
  timeout: 3e3,
12403
12455
  stdio: ["ignore", "pipe", "ignore"]
12404
12456
  }).trim();
12405
- const cliVersion = "0.9.30";
12457
+ const cliVersion = "0.10.0";
12406
12458
  if (legacyRaw && legacyRaw !== cliVersion) {
12407
12459
  findings.push({
12408
12460
  severity: "warn",
@@ -12982,7 +13034,9 @@ function truncate3(text, max) {
12982
13034
  import { spawn as spawn5 } from "child_process";
12983
13035
  import "commander";
12984
13036
  import {
13037
+ antiPatternGateParams,
12985
13038
  findProjectRoot as findProjectRoot44,
13039
+ loadConfig as loadConfig12,
12986
13040
  resolveHaivePaths as resolveHaivePaths40
12987
13041
  } from "@hiveai/core";
12988
13042
  function registerPrecommit(program2) {
@@ -12990,8 +13044,7 @@ function registerPrecommit(program2) {
12990
13044
  "Run a pre-commit safety check: scans `git diff --cached` against known anti-patterns,\n surfaces conventions/decisions anchored to touched files, and warns about stale anchored memories.\n\n Wire it into git as: `.git/hooks/pre-commit` running `haive precommit` (exit 1 = block).\n\n Examples:\n haive precommit # auto-detects staged diff\n haive precommit --block-on any # block on any warning, not just high-confidence\n haive precommit --paths src/auth.ts src/db.ts # explicit paths instead of git diff"
12991
13045
  ).option(
12992
13046
  "--block-on <mode>",
12993
- "'any' | 'high-confidence' (default) | 'never' (report only)",
12994
- "high-confidence"
13047
+ "'any' | 'high-confidence' | 'never' (report only). Default: derived from enforcement.antiPatternGate."
12995
13048
  ).option("--no-semantic", "disable semantic search in anti-patterns matching").option(
12996
13049
  "--no-anchored-blocks",
12997
13050
  "do not block on anchored, diff-corroborated anti-patterns (only block on very strong semantic matches)"
@@ -12999,6 +13052,11 @@ function registerPrecommit(program2) {
12999
13052
  const root = findProjectRoot44(opts.dir);
13000
13053
  const paths = resolveHaivePaths40(root);
13001
13054
  const ctx = { paths };
13055
+ const config = await loadConfig12(paths);
13056
+ const gate = config.enforcement?.antiPatternGate ?? "anchored";
13057
+ const gateParams = antiPatternGateParams(gate);
13058
+ const blockOn = opts.blockOn ?? gateParams.block_on;
13059
+ const anchoredBlocks = opts.anchoredBlocks === false ? false : gateParams.anchored_blocks;
13002
13060
  let diff = "";
13003
13061
  let touchedPaths = opts.paths ?? [];
13004
13062
  if (touchedPaths.length === 0) {
@@ -13036,8 +13094,8 @@ function registerPrecommit(program2) {
13036
13094
  const result = await preCommitCheck({
13037
13095
  diff: diff || void 0,
13038
13096
  paths: touchedPaths,
13039
- block_on: opts.blockOn ?? "high-confidence",
13040
- anchored_blocks: opts.anchoredBlocks !== false,
13097
+ block_on: blockOn,
13098
+ anchored_blocks: anchoredBlocks,
13041
13099
  semantic: opts.noSemantic ? false : true
13042
13100
  }, ctx);
13043
13101
  if (opts.json) {
@@ -13080,7 +13138,7 @@ function registerPrecommit(program2) {
13080
13138
  console.log();
13081
13139
  }
13082
13140
  if (result.should_block) {
13083
- ui.error(`Blocking commit (block_on=${opts.blockOn ?? "high-confidence"}). Address the warnings above or pass --block-on never to bypass.`);
13141
+ ui.error(`Blocking commit (gate=${gate}, block_on=${blockOn}). Address the warnings above or pass --block-on never to bypass.`);
13084
13142
  process.exit(1);
13085
13143
  }
13086
13144
  if (result.warnings.length === 0 && result.stale_anchors.length === 0) {
@@ -13366,10 +13424,11 @@ import { chmod as chmod2, mkdir as mkdir19, readFile as readFile21, readdir as r
13366
13424
  import path50 from "path";
13367
13425
  import "commander";
13368
13426
  import {
13427
+ antiPatternGateParams as antiPatternGateParams2,
13369
13428
  findProjectRoot as findProjectRoot49,
13370
13429
  hasRecentBriefingMarker,
13371
13430
  isFreshIsoDate,
13372
- loadConfig as loadConfig11,
13431
+ loadConfig as loadConfig13,
13373
13432
  loadMemoriesFromDir as loadMemoriesFromDir36,
13374
13433
  memoryMatchesAnchorPaths as memoryMatchesAnchorPaths6,
13375
13434
  readRecentBriefingMarker,
@@ -13390,7 +13449,7 @@ function registerEnforce(program2) {
13390
13449
  const root = findProjectRoot49(opts.dir);
13391
13450
  const paths = resolveHaivePaths45(root);
13392
13451
  await mkdir19(paths.haiveDir, { recursive: true });
13393
- const current = await loadConfig11(paths);
13452
+ const current = await loadConfig13(paths);
13394
13453
  await saveConfig4(paths, {
13395
13454
  ...current,
13396
13455
  enforcement: {
@@ -13663,7 +13722,7 @@ async function buildEnforcementReport(dir, stage, sessionId) {
13663
13722
  const root = findProjectRoot49(dir);
13664
13723
  const paths = resolveHaivePaths45(root);
13665
13724
  const initialized = existsSync68(paths.haiveDir);
13666
- const config = initialized ? await loadConfig11(paths) : {};
13725
+ const config = initialized ? await loadConfig13(paths) : {};
13667
13726
  if (initialized) await applyLightweightRepairs(root, paths);
13668
13727
  const mode = config.enforcement?.mode ?? "strict";
13669
13728
  const findings = [];
@@ -13693,7 +13752,7 @@ async function buildEnforcementReport(dir, stage, sessionId) {
13693
13752
  findings: [{ severity: "info", code: "enforcement-off", message: "hAIve enforcement is disabled." }]
13694
13753
  });
13695
13754
  }
13696
- findings.push(...await inspectIntegrationVersions(root, "0.9.30"));
13755
+ findings.push(...await inspectIntegrationVersions(root, "0.10.0"));
13697
13756
  if (config.enforcement?.requireBriefingFirst !== false && stage !== "ci") {
13698
13757
  const hasBriefing = await hasRecentBriefingMarker(paths, sessionId);
13699
13758
  findings.push(hasBriefing ? { severity: "ok", code: "briefing-loaded", message: "A recent hAIve briefing marker exists." } : {
@@ -13861,11 +13920,12 @@ async function runPrecommitPolicy(paths, gate) {
13861
13920
  return [{ severity: "info", code: "no-staged-changes", message: "No staged changes found for pre-commit policy." }];
13862
13921
  }
13863
13922
  const diff = await runCommand4("git", ["diff", "--cached"], paths.root).catch(() => "");
13923
+ const { block_on, anchored_blocks } = antiPatternGateParams2(gate);
13864
13924
  const result = await preCommitCheck({
13865
13925
  diff,
13866
13926
  paths: touchedPaths,
13867
- block_on: gate === "strict" ? "any" : "high-confidence",
13868
- anchored_blocks: gate === "anchored",
13927
+ block_on,
13928
+ anchored_blocks,
13869
13929
  semantic: true
13870
13930
  }, { paths });
13871
13931
  if (!result.should_block) {
@@ -14304,7 +14364,7 @@ function registerRun(program2) {
14304
14364
 
14305
14365
  // src/index.ts
14306
14366
  var program = new Command52();
14307
- program.name("haive").description("hAIve \u2014 the memory and enforcement layer of your agent harness").version("0.9.30").option("--advanced", "show maintenance and experimental commands in help");
14367
+ program.name("haive").description("hAIve \u2014 the memory and enforcement layer of your agent harness").version("0.10.0").option("--advanced", "show maintenance and experimental commands in help");
14308
14368
  registerInit(program);
14309
14369
  registerWelcome(program);
14310
14370
  registerResolveProject(program);
@@ -14363,17 +14423,14 @@ registerPrecommit(program);
14363
14423
  var CORE_ROOT_COMMANDS = /* @__PURE__ */ new Set([
14364
14424
  "init",
14365
14425
  "doctor",
14366
- "tui",
14367
14426
  "agent",
14427
+ "briefing",
14368
14428
  "enforce",
14369
14429
  "run",
14370
- "briefing",
14371
14430
  "sync",
14372
14431
  "mcp",
14373
14432
  "memory",
14374
- "session",
14375
- "precommit",
14376
- "welcome"
14433
+ "session"
14377
14434
  ]);
14378
14435
  var CORE_MEMORY_COMMANDS = /* @__PURE__ */ new Set([
14379
14436
  "add",