@hiveai/cli 0.9.18 → 0.9.19

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
@@ -6515,7 +6515,7 @@ When done, respond with: "Imported N memories: [list of IDs]" or "Nothing action
6515
6515
  };
6516
6516
  }
6517
6517
  var SERVER_NAME = "haive";
6518
- var SERVER_VERSION = "0.9.18";
6518
+ var SERVER_VERSION = "0.9.19";
6519
6519
  function jsonResult(data) {
6520
6520
  return {
6521
6521
  content: [
@@ -6535,6 +6535,7 @@ var ENFORCEMENT_PROFILE_TOOLS = [
6535
6535
  "mem_verify",
6536
6536
  "mem_relevant_to",
6537
6537
  "code_map",
6538
+ "code_search",
6538
6539
  "pre_commit_check",
6539
6540
  "mem_session_end"
6540
6541
  ];
@@ -11145,6 +11146,7 @@ import {
11145
11146
  aggregateUsage as aggregateUsage2,
11146
11147
  buildFrontmatter as buildFrontmatter11,
11147
11148
  findProjectRoot as findProjectRoot39,
11149
+ loadConfig as loadConfig9,
11148
11150
  loadMemoriesFromDir as loadMemoriesFromDir31,
11149
11151
  memoryFilePath as memoryFilePath10,
11150
11152
  parseSince as parseSince2,
@@ -11158,10 +11160,14 @@ var SEARCH_TOOLS = /* @__PURE__ */ new Set([
11158
11160
  "mem_relevant_to",
11159
11161
  "get_briefing"
11160
11162
  ]);
11163
+ var SYNTHETIC_QUERY_RE = /\b(auto-promote-marker|local enforcement smoke|cli-test-session)\b/i;
11164
+ function isSyntheticSuggestionQuery(query) {
11165
+ return SYNTHETIC_QUERY_RE.test(query);
11166
+ }
11161
11167
  function registerMemorySuggest(memory2) {
11162
11168
  memory2.command("suggest").description(
11163
- "Suggest memories to create based on recurring search queries in the usage log.\n\n Use --auto-save to draft the top-N suggestions as draft memories. They land\n in personal scope by default with status=draft, ready for you to edit and promote."
11164
- ).option("--since <window>", "ISO date or relative (e.g. '7d', '24h')", "30d").option("--min <count>", "minimum repeat count to surface a query", "2").option("--top-n <n>", "with --auto-save, draft this many top suggestions", "3").option("--scope <scope>", "with --auto-save, scope of drafted memories (personal | team)", "personal").option("--auto-save", "draft top-N suggestions as draft memories on disk", false).option("--json", "emit JSON instead of human-readable output", false).option("-d, --dir <dir>", "project root").action(async (opts) => {
11169
+ "Suggest memories to create based on recurring search queries in the usage log.\n\n Use --auto-save to save the top-N suggestions using the project defaults.\n In autopilot, suggestions land as validated team records; in manual mode they stay draft."
11170
+ ).option("--since <window>", "ISO date or relative (e.g. '7d', '24h')", "30d").option("--min <count>", "minimum repeat count to surface a query", "2").option("--top-n <n>", "with --auto-save, draft this many top suggestions", "3").option("--scope <scope>", "with --auto-save, scope of saved memories (personal | team; default: config default)").option("--auto-save", "save top-N suggestions as memories on disk", false).option("--json", "emit JSON instead of human-readable output", false).option("-d, --dir <dir>", "project root").action(async (opts) => {
11165
11171
  const root = findProjectRoot39(opts.dir);
11166
11172
  const paths = resolveHaivePaths35(root);
11167
11173
  const events = await readUsageEvents3(paths);
@@ -11182,6 +11188,7 @@ function registerMemorySuggest(memory2) {
11182
11188
  if (!SEARCH_TOOLS.has(e.tool)) continue;
11183
11189
  const key = (e.summary ?? "").toLowerCase().trim();
11184
11190
  if (!key) continue;
11191
+ if (isSyntheticSuggestionQuery(key)) continue;
11185
11192
  const prior = queries.get(key);
11186
11193
  if (prior) {
11187
11194
  prior.count++;
@@ -11200,11 +11207,13 @@ function registerMemorySuggest(memory2) {
11200
11207
  inferred_type: inferType(v.tools, query)
11201
11208
  })).sort((a, b) => b.count - a.count);
11202
11209
  if (opts.autoSave) {
11210
+ const config = await loadConfig9(paths);
11203
11211
  const topN = Math.max(1, parseInt(opts.topN ?? "3", 10));
11204
- const scope = opts.scope === "team" ? "team" : "personal";
11212
+ const scope = opts.scope === "personal" || opts.scope === "team" ? opts.scope : config.defaultScope ?? "personal";
11213
+ const status = config.defaultStatus === "validated" ? "validated" : "draft";
11205
11214
  const top = suggestions.slice(0, topN);
11206
11215
  if (top.length === 0) {
11207
- ui.warn(`No suggestions met --min=${minCount} \u2014 nothing to draft.`);
11216
+ ui.warn(`No suggestions met --min=${minCount} \u2014 nothing to save.`);
11208
11217
  return;
11209
11218
  }
11210
11219
  const created = [];
@@ -11227,10 +11236,10 @@ function registerMemorySuggest(memory2) {
11227
11236
  scope,
11228
11237
  tags: ["auto-suggested", ...s.tools],
11229
11238
  paths: [],
11230
- symbols: []
11239
+ symbols: [],
11240
+ status
11231
11241
  });
11232
- fm.status = "draft";
11233
- const body = renderTemplate(s);
11242
+ const body = renderTemplate(s, fm.id, status);
11234
11243
  const file = memoryFilePath10(paths, fm.scope, fm.id, fm.module);
11235
11244
  await mkdir18(path41.dirname(file), { recursive: true });
11236
11245
  if (existsSync60(file)) {
@@ -11245,7 +11254,7 @@ function registerMemorySuggest(memory2) {
11245
11254
  return;
11246
11255
  }
11247
11256
  for (const c of created) {
11248
- ui.success(`Drafted ${c.id} \u2192 ${c.file}`);
11257
+ ui.success(`${status === "validated" ? "Saved" : "Drafted"} ${c.id} \u2192 ${c.file}`);
11249
11258
  console.log(` ${ui.dim("from query:")} ${truncate2(c.query, 60)}`);
11250
11259
  }
11251
11260
  for (const s of skipped) {
@@ -11253,7 +11262,11 @@ function registerMemorySuggest(memory2) {
11253
11262
  }
11254
11263
  if (created.length > 0) {
11255
11264
  console.log();
11256
- ui.info("Drafts are status=draft \u2014 edit them, then `haive memory promote` to validate.");
11265
+ if (status === "validated") {
11266
+ ui.info("Autopilot defaults applied: suggestions are status=validated and active.");
11267
+ } else {
11268
+ ui.info("Drafts are status=draft \u2014 edit them, then run `haive memory promote <id>`.");
11269
+ }
11257
11270
  }
11258
11271
  return;
11259
11272
  }
@@ -11278,7 +11291,7 @@ function registerMemorySuggest(memory2) {
11278
11291
  console.log(` ${ui.dim("\u2192")} ${s.reason}`);
11279
11292
  }
11280
11293
  console.log();
11281
- ui.info("Run with --auto-save to draft the top-3 as draft memories.");
11294
+ ui.info("Run with --auto-save to save the top-3 using the project defaults.");
11282
11295
  });
11283
11296
  }
11284
11297
  function chooseReason(tools, count) {
@@ -11299,7 +11312,8 @@ function inferType(tools, query) {
11299
11312
  }
11300
11313
  return "convention";
11301
11314
  }
11302
- function renderTemplate(s) {
11315
+ function renderTemplate(s, id, status) {
11316
+ const nextStep = status === "validated" ? `This record is already active because project autopilot defaults set status=validated. Replace the template body with the actual answer when known.` : `Then run \`haive memory promote ${id}\` to move it into team review.`;
11303
11317
  return [
11304
11318
  `# Auto-drafted from recurring searches`,
11305
11319
  ``,
@@ -11319,7 +11333,7 @@ function renderTemplate(s) {
11319
11333
  `- **Why** \u2014 the rationale or root cause`,
11320
11334
  `- **How to apply** \u2014 what an agent should do when this comes up again`,
11321
11335
  ``,
11322
- `Then run \`haive memory promote ${truncate2(s.query, 30)}\` to mark it validated.`
11336
+ nextStep
11323
11337
  ].join("\n");
11324
11338
  }
11325
11339
  function slugify(s) {
@@ -11455,7 +11469,7 @@ import {
11455
11469
  findProjectRoot as findProjectRoot41,
11456
11470
  getUsage as getUsage20,
11457
11471
  loadCodeMap as loadCodeMap7,
11458
- loadConfig as loadConfig9,
11472
+ loadConfig as loadConfig10,
11459
11473
  loadMemoriesFromDir as loadMemoriesFromDir33,
11460
11474
  loadUsageIndex as loadUsageIndex26,
11461
11475
  readUsageEvents as readUsageEvents4,
@@ -11470,6 +11484,7 @@ function registerDoctor(program2) {
11470
11484
  const paths = resolveHaivePaths37(root);
11471
11485
  const findings = [];
11472
11486
  const repairs = [];
11487
+ const config = await loadConfig10(paths);
11473
11488
  if (!existsSync63(paths.haiveDir)) {
11474
11489
  findings.push({
11475
11490
  severity: "error",
@@ -11573,6 +11588,18 @@ function registerDoctor(program2) {
11573
11588
  });
11574
11589
  }
11575
11590
  }
11591
+ const lintReport = await lintMemoriesAsync(root);
11592
+ if (lintReport.findings.length > 0) {
11593
+ const warnCount = lintReport.findings.filter((finding) => finding.severity === "warn").length;
11594
+ const errorCount = lintReport.findings.filter((finding) => finding.severity === "error").length;
11595
+ const severity = errorCount > 0 ? "error" : warnCount > 0 ? "warn" : "info";
11596
+ findings.push({
11597
+ severity,
11598
+ code: "memory-lint-findings",
11599
+ message: `memory lint reports ${lintReport.findings.length} finding${lintReport.findings.length === 1 ? "" : "s"} (${errorCount} error, ${warnCount} warn, ${lintReport.findings.length - errorCount - warnCount} info).`,
11600
+ fix: "haive memory lint --fix --apply"
11601
+ });
11602
+ }
11576
11603
  const codeMap = await loadCodeMap7(paths);
11577
11604
  if (!codeMap) {
11578
11605
  findings.push({
@@ -11594,6 +11621,7 @@ function registerDoctor(program2) {
11594
11621
  });
11595
11622
  }
11596
11623
  }
11624
+ findings.push(...await collectSemanticIndexFindings(paths, config, memories.length, codeMap));
11597
11625
  const events = await readUsageEvents4(paths);
11598
11626
  if (events.length === 0) {
11599
11627
  findings.push({
@@ -11607,6 +11635,7 @@ function registerDoctor(program2) {
11607
11635
  if (!isSearchTool(e.tool)) continue;
11608
11636
  const key = (e.summary ?? "").toLowerCase().trim();
11609
11637
  if (!key) continue;
11638
+ if (isSyntheticSuggestionQuery(key)) continue;
11610
11639
  queryRepeats.set(key, (queryRepeats.get(key) ?? 0) + 1);
11611
11640
  }
11612
11641
  const repeated = [...queryRepeats.entries()].filter(([, n]) => n >= 3);
@@ -11628,7 +11657,6 @@ function registerDoctor(program2) {
11628
11657
  });
11629
11658
  }
11630
11659
  }
11631
- const config = await loadConfig9(paths);
11632
11660
  if (config.enforcement?.requireBriefingFirst) {
11633
11661
  const claudeSettings = path44.join(root, ".claude", "settings.local.json");
11634
11662
  let hasClaudeEnforcement = false;
@@ -11658,14 +11686,14 @@ function registerDoctor(program2) {
11658
11686
  fix: "Edit .ai/haive.config.json: set autoSessionEnd: true (or re-run `haive init` without --manual)."
11659
11687
  });
11660
11688
  }
11661
- findings.push(...await collectInstallFindings(root, "0.9.18"));
11689
+ findings.push(...await collectInstallFindings(root, "0.9.19"));
11662
11690
  try {
11663
11691
  const legacyRaw = execSync3("haive-mcp --version", {
11664
11692
  encoding: "utf8",
11665
11693
  timeout: 3e3,
11666
11694
  stdio: ["ignore", "pipe", "ignore"]
11667
11695
  }).trim();
11668
- const cliVersion = "0.9.18";
11696
+ const cliVersion = "0.9.19";
11669
11697
  if (legacyRaw && legacyRaw !== cliVersion) {
11670
11698
  findings.push({
11671
11699
  severity: "warn",
@@ -11795,6 +11823,56 @@ function groupBySection(findings) {
11795
11823
  function nextActions(findings) {
11796
11824
  return [...new Set(findings.flatMap((finding) => finding.fix ? finding.fix.split("\n") : []))].filter(Boolean);
11797
11825
  }
11826
+ async function collectSemanticIndexFindings(paths, config, memoryCount, codeMap) {
11827
+ const findings = [];
11828
+ const autoWantsCodeSearch = Boolean(config.autopilot || config.autoRepair?.codeSearch);
11829
+ let mod;
11830
+ try {
11831
+ mod = await import("@hiveai/embeddings");
11832
+ } catch {
11833
+ findings.push({
11834
+ severity: autoWantsCodeSearch ? "warn" : "info",
11835
+ code: "embeddings-unavailable",
11836
+ message: "@hiveai/embeddings is not available, so get_briefing falls back to lexical ranking and code_search cannot run.",
11837
+ fix: "npm install -g @hiveai/cli@latest\nhaive embeddings status",
11838
+ section: "Index health"
11839
+ });
11840
+ return findings;
11841
+ }
11842
+ if (memoryCount > 0) {
11843
+ const stat2 = await mod.indexStat(paths).catch(() => ({ exists: false, count: 0 }));
11844
+ if (!stat2.exists || stat2.count === 0) {
11845
+ findings.push({
11846
+ severity: "warn",
11847
+ code: "semantic-memory-index-missing",
11848
+ message: "Memory embeddings index is missing or empty; get_briefing will report literal_fallback instead of semantic ranking.",
11849
+ fix: "haive embeddings index",
11850
+ section: "Index health"
11851
+ });
11852
+ }
11853
+ }
11854
+ if (autoWantsCodeSearch || codeMap) {
11855
+ const codeIndex = await mod.loadCodeIndex(paths).catch(() => null);
11856
+ if (!codeIndex || codeIndex.entries.length === 0) {
11857
+ findings.push({
11858
+ severity: autoWantsCodeSearch ? "warn" : "info",
11859
+ code: "code-search-index-missing",
11860
+ message: "Code-search embeddings index is missing or empty; MCP code_search is unavailable until it is built.",
11861
+ fix: "haive index code-search",
11862
+ section: "Index health"
11863
+ });
11864
+ } else if (codeMap && codeIndex.source_generated_at !== codeMap.generated_at) {
11865
+ findings.push({
11866
+ severity: "info",
11867
+ code: "code-search-index-outdated",
11868
+ message: "Code-search embeddings index was built from an older code-map; semantic code search may miss recent symbols.",
11869
+ fix: "haive index code-search",
11870
+ section: "Index health"
11871
+ });
11872
+ }
11873
+ }
11874
+ return findings;
11875
+ }
11798
11876
  function isSearchTool(name) {
11799
11877
  return ["mem_search", "code_search", "mem_relevant_to", "get_briefing"].includes(name);
11800
11878
  }
@@ -12381,7 +12459,7 @@ import {
12381
12459
  findProjectRoot as findProjectRoot48,
12382
12460
  hasRecentBriefingMarker,
12383
12461
  isFreshIsoDate,
12384
- loadConfig as loadConfig10,
12462
+ loadConfig as loadConfig11,
12385
12463
  loadMemoriesFromDir as loadMemoriesFromDir36,
12386
12464
  memoryMatchesAnchorPaths as memoryMatchesAnchorPaths6,
12387
12465
  readRecentBriefingMarker,
@@ -12402,7 +12480,7 @@ function registerEnforce(program2) {
12402
12480
  const root = findProjectRoot48(opts.dir);
12403
12481
  const paths = resolveHaivePaths44(root);
12404
12482
  await mkdir19(paths.haiveDir, { recursive: true });
12405
- const current = await loadConfig10(paths);
12483
+ const current = await loadConfig11(paths);
12406
12484
  await saveConfig4(paths, {
12407
12485
  ...current,
12408
12486
  enforcement: {
@@ -12651,7 +12729,7 @@ async function buildEnforcementReport(dir, stage, sessionId) {
12651
12729
  const root = findProjectRoot48(dir);
12652
12730
  const paths = resolveHaivePaths44(root);
12653
12731
  const initialized = existsSync69(paths.haiveDir);
12654
- const config = initialized ? await loadConfig10(paths) : {};
12732
+ const config = initialized ? await loadConfig11(paths) : {};
12655
12733
  const mode = config.enforcement?.mode ?? "strict";
12656
12734
  const findings = [];
12657
12735
  if (!initialized) {
@@ -12680,7 +12758,7 @@ async function buildEnforcementReport(dir, stage, sessionId) {
12680
12758
  findings: [{ severity: "info", code: "enforcement-off", message: "hAIve enforcement is disabled." }]
12681
12759
  });
12682
12760
  }
12683
- findings.push(...await inspectIntegrationVersions(root, "0.9.18"));
12761
+ findings.push(...await inspectIntegrationVersions(root, "0.9.19"));
12684
12762
  if (config.enforcement?.requireBriefingFirst !== false && stage !== "ci") {
12685
12763
  const hasBriefing = await hasRecentBriefingMarker(paths, sessionId);
12686
12764
  findings.push(hasBriefing ? { severity: "ok", code: "briefing-loaded", message: "A recent hAIve briefing marker exists." } : {
@@ -13168,7 +13246,7 @@ function registerRun(program2) {
13168
13246
 
13169
13247
  // src/index.ts
13170
13248
  var program = new Command51();
13171
- program.name("haive").description("hAIve \u2014 policy enforcement layer for AI coding agents").version("0.9.18").option("--advanced", "show maintenance and experimental commands in help");
13249
+ program.name("haive").description("hAIve \u2014 policy enforcement layer for AI coding agents").version("0.9.19").option("--advanced", "show maintenance and experimental commands in help");
13172
13250
  registerInit(program);
13173
13251
  registerWelcome(program);
13174
13252
  registerResolveProject(program);