@hiveai/cli 0.9.27 → 0.9.28

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
@@ -11,6 +11,7 @@ import "commander";
11
11
  import {
12
12
  extractActionsBriefBody,
13
13
  findProjectRoot as findProjectRoot2,
14
+ isStackPackSeed,
14
15
  literalMatchesAllTokens,
15
16
  literalMatchesAnyToken,
16
17
  loadCodeMap as loadCodeMap3,
@@ -1098,6 +1099,7 @@ function classifyCliPriority(item, filePaths, tokens, exactTaskHit, partialTaskH
1098
1099
  const fm = item.memory.frontmatter;
1099
1100
  const anchored = filePaths.length > 0 && memoryMatchesAnchorPaths(item.memory, filePaths);
1100
1101
  if (anchored || fm.type === "attempt" && exactTaskHit) return "must_read";
1102
+ if (isStackPackSeed(fm)) return "background";
1101
1103
  if (exactTaskHit || partialTaskHit || item.score >= 4 || tokens && fm.tags.some((tag) => tokens.includes(tag))) {
1102
1104
  return "useful";
1103
1105
  }
@@ -2018,7 +2020,8 @@ import path9 from "path";
2018
2020
  import {
2019
2021
  buildFrontmatter,
2020
2022
  memoryFilePath,
2021
- serializeMemory as serializeMemory2
2023
+ serializeMemory as serializeMemory2,
2024
+ STACK_PACK_TAG
2022
2025
  } from "@hiveai/core";
2023
2026
  var PACKS = {
2024
2027
  nestjs: [
@@ -2593,6 +2596,7 @@ new ApolloServer({
2593
2596
  }
2594
2597
  ]
2595
2598
  };
2599
+ var SEED_FOOTER = (stack) => `> _Seeded by \`haive init\` from the **${stack}** stack pack \u2014 generic guidance, not repo-specific. Anchor it to a real file or replace it with a repo-specific note to raise it above background priority._`;
2596
2600
  var SUPPORTED_STACKS = Object.keys(PACKS);
2597
2601
  function isValidStack(name) {
2598
2602
  return name in PACKS;
@@ -2634,11 +2638,15 @@ async function seedStackPack(haivePaths, stack) {
2634
2638
  slug: `${stack}-${mem.slug}`,
2635
2639
  scope: "team",
2636
2640
  status: "validated",
2637
- tags: mem.tags
2641
+ // STACK_PACK_TAG marks this as generic seed knowledge so briefing ranking
2642
+ // keeps it at `background` priority until it earns a repo-specific anchor.
2643
+ tags: [...mem.tags, STACK_PACK_TAG]
2638
2644
  });
2639
2645
  const filePath = memoryFilePath(haivePaths, "team", fm.id);
2640
2646
  if (existsSync8(filePath)) continue;
2641
- const content = serializeMemory2({ frontmatter: fm, body: mem.body });
2647
+ const content = serializeMemory2({ frontmatter: fm, body: `${mem.body}
2648
+
2649
+ ${SEED_FOOTER(stack)}` });
2642
2650
  await mkdir4(path9.dirname(filePath), { recursive: true });
2643
2651
  await writeFile5(filePath, content, "utf8");
2644
2652
  count++;
@@ -2669,30 +2677,25 @@ TODO \u2014 domain terms and what they mean here.
2669
2677
  TODO \u2014 known traps, surprising behavior, things newcomers stub their toes on.
2670
2678
  `;
2671
2679
  var BRIDGE_BODY = `<!-- hAIve bridge file \u2014 do not edit by hand. -->
2672
- <!-- This file points your AI tool at the shared hAIve project context. -->
2673
-
2674
- See \`.ai/project-context.md\` for the full project context.
2675
- Memories live under \`.ai/memories/\` (personal/team/module).
2676
2680
 
2677
- ## hAIve \u2014 mandatory rules for AI agents
2681
+ This repo uses **hAIve** for shared context. The map:
2678
2682
 
2679
- Installing or initializing hAIve in this repository means **the team expects AI agents to drive work through hAIve**, not bypass it.
2683
+ - \`.ai/project-context.md\` \u2014 project overview, architecture, conventions.
2684
+ - \`.ai/memories/\` \u2014 decisions, gotchas, conventions, failed attempts (personal/team/module).
2685
+ - The breadcrumbs injected below (if any) are the top current memories.
2680
2686
 
2681
- ### MCP first (default \u2014 never optional unless the developer says so)
2682
- The **haive** MCP server must be enabled in your client. Until it is unavailable (misconfiguration report to the developer), you **must** use it for substantive work:
2687
+ ## Working through hAIve
2683
2688
 
2684
- - **Before** you edit project source files, configs (\`package.json\`, tooling), or workflows for the current goal, invoke \`get_briefing\` with a short **task** string (and **files** / **symbols** when you know them). If project context was already refreshed in this session and you only need ranked memories, you may call \`mem_relevant_to\` instead\u2014but **still** consult hAIve before trusting ungrounded guesses.
2685
- - **Before** declaring a coding task finished, invoke the MCP prompt \`post_task\` when the session produced learnings or substantive changes worth capturing.
2689
+ 1. **Before editing** for a goal, call \`get_briefing\` (task + files/symbols) to load ranked context \u2014 or \`mem_relevant_to\` if project context is already loaded this session.
2690
+ 2. **When an approach fails**, call \`mem_tried\` right away so the next agent skips the dead end.
2691
+ 3. **Before closing** a substantive session, run the \`post_task\` prompt to capture what was learned.
2686
2692
 
2687
- Do **not** treat these as nice-to-have: they are **default-required** for coding agents here.
2693
+ If the haive MCP server is not available, tell the developer rather than silently skipping it.
2688
2694
 
2689
- ### Session rules
2690
- - **Immediately** when an approach fails (wrong API, wrong pattern, wrong assumption), call \`mem_tried\` \u2014 do not wait until the end of the session.
2695
+ ## Safety
2691
2696
 
2692
- ### Safety rules \u2014 NEVER violate these
2693
- - If \`get_briefing\` returns an \`action_required\` list, **stop and show each item to the developer** before doing anything. Use the exact \`developer_message\` provided. Wait for explicit confirmation.
2694
- - **Never modify code autonomously** because of a breaking change detected in another project (dependency version bump, API contract change, removed field). Always ask first.
2695
- - When in doubt about a cross-repo change: ask, don't act.
2697
+ - If \`get_briefing\` returns \`action_required\`, surface each item to the developer (use its \`developer_message\`) and wait for confirmation before changing code.
2698
+ - Never act autonomously on a cross-repo breaking change (dep bump, contract/API diff) \u2014 ask first.
2696
2699
  `;
2697
2700
  var CURSOR_HAIVE_RULE_MDC = `---
2698
2701
  description: Require hAIve MCP (get_briefing / mem_relevant_to) before substantive repo edits
@@ -2918,7 +2921,10 @@ function registerInit(program2) {
2918
2921
  }
2919
2922
  if (totalSeeded > 0) {
2920
2923
  ui.success(
2921
- `${totalSeeded} validated team memories pre-seeded \u2014 haive is useful from J+0`
2924
+ `${totalSeeded} starter memories seeded (generic stack guidance, kept at background priority)`
2925
+ );
2926
+ ui.info(
2927
+ "Anchor them to real files or replace them with repo-specific notes to make them high-signal."
2922
2928
  );
2923
2929
  }
2924
2930
  }
@@ -3663,6 +3669,7 @@ import {
3663
3669
  isGlobPath,
3664
3670
  isAutoPromoteEligible,
3665
3671
  isDecaying,
3672
+ isStackPackSeed as isStackPackSeed2,
3666
3673
  literalMatchesAllTokens as literalMatchesAllTokens22,
3667
3674
  literalMatchesAnyToken as literalMatchesAnyToken22,
3668
3675
  loadCodeMap as loadCodeMap4,
@@ -3676,7 +3683,8 @@ import {
3676
3683
  serializeMemory as serializeMemory9,
3677
3684
  tokenizeQuery as tokenizeQuery22,
3678
3685
  trackReads as trackReads3,
3679
- truncateToTokens
3686
+ truncateToTokens,
3687
+ writeBriefingMarker as writeBriefingMarker2
3680
3688
  } from "@hiveai/core";
3681
3689
  import { z as z17 } from "zod";
3682
3690
  import { estimateTokens as estimateTokens2, loadCodeMap as loadCodeMap22, queryCodeMap as queryCodeMap22 } from "@hiveai/core";
@@ -5427,6 +5435,16 @@ When done, call \`mem_session_end\` to acknowledge \u2014 this clears the pendin
5427
5435
  );
5428
5436
  }
5429
5437
  }
5438
+ if (existsSync18(ctx.paths.haiveDir)) {
5439
+ await writeBriefingMarker2(ctx.paths, {
5440
+ sessionId: process.env.HAIVE_SESSION_ID,
5441
+ ...input.task ? { task: input.task } : {},
5442
+ source: "mcp-get-briefing",
5443
+ files: input.files,
5444
+ memoryIds: outputMemories.map((m) => m.id)
5445
+ }).catch(() => {
5446
+ });
5447
+ }
5430
5448
  return {
5431
5449
  ...input.task ? { task: input.task } : {},
5432
5450
  search_mode: searchMode,
@@ -5481,6 +5499,9 @@ function classifyMemoryPriority(memory2, loaded, inputFiles, inputSymbols) {
5481
5499
  if (fm?.requires_human_approval || directAnchor || directSymbol || memory2.type === "attempt" && (memory2.match_quality === "exact" || strongSemantic) || memory2.type === "skill" && (memory2.match_quality === "exact" || strongSemantic)) {
5482
5500
  return "must_read";
5483
5501
  }
5502
+ if (isStackPackSeed2(fm)) {
5503
+ return "background";
5504
+ }
5484
5505
  if (memory2.type === "skill" || memory2.reasons.includes("module") || memory2.reasons.includes("domain") || memory2.match_quality === "exact" || usefulSemantic) {
5485
5506
  return "useful";
5486
5507
  }
@@ -5963,6 +5984,8 @@ async function antiPatternsCheck(input, ctx) {
5963
5984
  confidence: deriveConfidence6(fm, u),
5964
5985
  body_preview: body.split("\n").slice(0, 5).join("\n").slice(0, 400),
5965
5986
  reasons: [reason],
5987
+ tags: fm.tags ?? [],
5988
+ anchor_paths: fm.anchor?.paths ?? [],
5966
5989
  ...score !== void 0 ? { semantic_score: score } : {}
5967
5990
  });
5968
5991
  };
@@ -6553,8 +6576,45 @@ function fileTypeDowngradeReason(warning, paths) {
6553
6576
  if (configOnly && !warning.reasons.includes("anchor") && !hasStrongSemantic(warning)) {
6554
6577
  return "package/config-only change; warning has no anchor on these files and no strong semantic match \u2014 downgraded to info.";
6555
6578
  }
6579
+ const touchesBuildFile = paths.some(isPackageOrConfigPath);
6580
+ if (!touchesBuildFile && isBuildScopedWarning(warning) && !warning.reasons.includes("anchor") && !hasStrongSemantic(warning)) {
6581
+ return "build/packaging gotcha, but no package/build file changed \u2014 downgraded to info.";
6582
+ }
6556
6583
  return null;
6557
6584
  }
6585
+ function isBuildScopedWarning(warning) {
6586
+ const tags = warning.tags ?? [];
6587
+ if (tags.some((t) => BUILD_SCOPED_TAGS.has(t.toLowerCase()))) return true;
6588
+ const anchors = warning.anchor_paths ?? [];
6589
+ return anchors.length > 0 && anchors.every(isPackageOrConfigPath);
6590
+ }
6591
+ var BUILD_SCOPED_TAGS = /* @__PURE__ */ new Set([
6592
+ "npm",
6593
+ "pnpm",
6594
+ "yarn",
6595
+ "publish",
6596
+ "install",
6597
+ "packaging",
6598
+ "package",
6599
+ "build",
6600
+ "tsup",
6601
+ "bundler",
6602
+ "monorepo",
6603
+ "workspace",
6604
+ "versioning",
6605
+ "version",
6606
+ "dev-workflow",
6607
+ "hotswap",
6608
+ "ci",
6609
+ "workflow",
6610
+ "release",
6611
+ "changelog",
6612
+ "dependencies",
6613
+ "deps",
6614
+ "dependency",
6615
+ "tooling",
6616
+ "config"
6617
+ ]);
6558
6618
  function hasStrongSemantic(warning) {
6559
6619
  return warning.reasons.includes("semantic") && (warning.semantic_score ?? 0) >= 0.65;
6560
6620
  }
@@ -7130,7 +7190,7 @@ When done, respond with: "Imported N memories: [list of IDs]" or "Nothing action
7130
7190
  };
7131
7191
  }
7132
7192
  var SERVER_NAME = "haive";
7133
- var SERVER_VERSION = "0.9.27";
7193
+ var SERVER_VERSION = "0.9.28";
7134
7194
  function jsonResult(data) {
7135
7195
  return {
7136
7196
  content: [
@@ -8111,6 +8171,7 @@ import {
8111
8171
  getUsage as getUsage10,
8112
8172
  isAutoPromoteEligible as isAutoPromoteEligible2,
8113
8173
  isDecaying as isDecaying2,
8174
+ isStackPackSeed as isStackPackSeed3,
8114
8175
  loadCodeMap as loadCodeMap5,
8115
8176
  loadConfig as loadConfig4,
8116
8177
  loadMemoriesFromDir as loadMemoriesFromDir23,
@@ -8555,12 +8616,18 @@ Attends une **confirmation explicite** avant d'agir.
8555
8616
  }
8556
8617
  });
8557
8618
  }
8619
+ function bridgeSummaryLine(body) {
8620
+ const firstLine = body.split("\n").map((l) => l.replace(/^#+\s*/, "").trim()).find((l) => l.length > 0) ?? "";
8621
+ const oneLine = firstLine.replace(/\s+/g, " ");
8622
+ return oneLine.length > 140 ? oneLine.slice(0, 137) + "\u2026" : oneLine;
8623
+ }
8558
8624
  async function injectBridge(bridgeFile, memoriesDir, maxMemories, root, quiet) {
8559
8625
  if (!existsSync29(memoriesDir)) return;
8560
8626
  const all = await loadMemoriesFromDir23(memoriesDir);
8561
8627
  const top = all.filter(({ memory: memory2 }) => {
8562
8628
  const s = memory2.frontmatter.status;
8563
8629
  if (memory2.frontmatter.type === "session_recap") return false;
8630
+ if (isStackPackSeed3(memory2.frontmatter)) return false;
8564
8631
  return s === "validated" || s === "proposed";
8565
8632
  }).sort((a, b) => {
8566
8633
  const score = (m) => {
@@ -8572,11 +8639,11 @@ async function injectBridge(bridgeFile, memoriesDir, maxMemories, root, quiet) {
8572
8639
  const block = top.map((m) => {
8573
8640
  const fm = m.memory.frontmatter;
8574
8641
  const unverified = fm.status === "proposed" ? " [UNVERIFIED]" : "";
8575
- return `### ${fm.id} (${fm.scope}/${fm.type})${unverified}
8576
- ${m.memory.body.trim()}`;
8577
- }).join("\n\n---\n\n");
8642
+ return `- \`${fm.id}\` (${fm.scope}/${fm.type})${unverified} \u2014 ${bridgeSummaryLine(m.memory.body)}`;
8643
+ }).join("\n");
8578
8644
  const injected = `${BRIDGE_START}
8579
8645
  <!-- AUTO-GENERATED by haive sync --inject-bridge \u2014 do not edit between these markers -->
8646
+ <!-- Top memories \u2014 call get_briefing / mem_get for the full body. -->
8580
8647
 
8581
8648
  ` + block + `
8582
8649
 
@@ -12063,14 +12130,14 @@ function registerDoctor(program2) {
12063
12130
  fix: "Edit .ai/haive.config.json: set autoSessionEnd: true (or re-run `haive init` without --manual)."
12064
12131
  });
12065
12132
  }
12066
- findings.push(...await collectInstallFindings(root, "0.9.27"));
12133
+ findings.push(...await collectInstallFindings(root, "0.9.28"));
12067
12134
  try {
12068
12135
  const legacyRaw = execSync3("haive-mcp --version", {
12069
12136
  encoding: "utf8",
12070
12137
  timeout: 3e3,
12071
12138
  stdio: ["ignore", "pipe", "ignore"]
12072
12139
  }).trim();
12073
- const cliVersion = "0.9.27";
12140
+ const cliVersion = "0.9.28";
12074
12141
  if (legacyRaw && legacyRaw !== cliVersion) {
12075
12142
  findings.push({
12076
12143
  severity: "warn",
@@ -13042,7 +13109,7 @@ import {
13042
13109
  saveConfig as saveConfig4,
13043
13110
  SESSION_RECAP_TTL_MS,
13044
13111
  verifyAnchor as verifyAnchor4,
13045
- writeBriefingMarker as writeBriefingMarker2
13112
+ writeBriefingMarker as writeBriefingMarker3
13046
13113
  } from "@hiveai/core";
13047
13114
  var MAX_STDIN_BYTES2 = 256 * 1024;
13048
13115
  var ENFORCE_HOOK_MARKER = "# hAIve enforcement hook";
@@ -13152,7 +13219,7 @@ function registerEnforce(program2) {
13152
13219
  },
13153
13220
  { paths }
13154
13221
  );
13155
- await writeBriefingMarker2(paths, {
13222
+ await writeBriefingMarker3(paths, {
13156
13223
  sessionId,
13157
13224
  task,
13158
13225
  source: opts.source ?? "claude-session-start",
@@ -13237,7 +13304,7 @@ async function runWithEnforcement(command, args, opts) {
13237
13304
  }
13238
13305
  const sessionId = `haive-run-${process.pid}-${Date.now()}`;
13239
13306
  const task = opts.task ?? `Run agent command: ${[command, ...args].join(" ")}`;
13240
- await writeBriefingMarker2(paths, {
13307
+ await writeBriefingMarker3(paths, {
13241
13308
  sessionId,
13242
13309
  task,
13243
13310
  source: "haive-run"
@@ -13294,7 +13361,7 @@ async function writeWrapperBriefing(paths, sessionId, task) {
13294
13361
  min_semantic_score: 0.25,
13295
13362
  budget_preset: "quick"
13296
13363
  }, { paths });
13297
- await writeBriefingMarker2(paths, {
13364
+ await writeBriefingMarker3(paths, {
13298
13365
  sessionId,
13299
13366
  task,
13300
13367
  source: "haive-run",
@@ -13357,7 +13424,7 @@ async function buildEnforcementReport(dir, stage, sessionId) {
13357
13424
  findings: [{ severity: "info", code: "enforcement-off", message: "hAIve enforcement is disabled." }]
13358
13425
  });
13359
13426
  }
13360
- findings.push(...await inspectIntegrationVersions(root, "0.9.27"));
13427
+ findings.push(...await inspectIntegrationVersions(root, "0.9.28"));
13361
13428
  if (config.enforcement?.requireBriefingFirst !== false && stage !== "ci") {
13362
13429
  const hasBriefing = await hasRecentBriefingMarker(paths, sessionId);
13363
13430
  findings.push(hasBriefing ? { severity: "ok", code: "briefing-loaded", message: "A recent hAIve briefing marker exists." } : {
@@ -13964,7 +14031,7 @@ function registerRun(program2) {
13964
14031
 
13965
14032
  // src/index.ts
13966
14033
  var program = new Command51();
13967
- program.name("haive").description("hAIve \u2014 the memory and enforcement layer of your agent harness").version("0.9.27").option("--advanced", "show maintenance and experimental commands in help");
14034
+ program.name("haive").description("hAIve \u2014 the memory and enforcement layer of your agent harness").version("0.9.28").option("--advanced", "show maintenance and experimental commands in help");
13968
14035
  registerInit(program);
13969
14036
  registerWelcome(program);
13970
14037
  registerResolveProject(program);