@hiveai/cli 0.13.5 → 0.13.7

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
@@ -910,6 +910,10 @@ function registerBriefing(program2) {
910
910
  return;
911
911
  }
912
912
  const ownMemories = await loadMemoriesFromDir3(paths.memoriesDir);
913
+ const POLICY_TYPES = /* @__PURE__ */ new Set(["decision", "gotcha", "architecture", "convention"]);
914
+ const anchoredPolicyIds = markerFiles.length > 0 ? ownMemories.map((m) => m.memory).filter(
915
+ (mem) => POLICY_TYPES.has(mem.frontmatter.type) && mem.frontmatter.status === "validated" && memoryMatchesAnchorPaths(mem, markerFiles)
916
+ ).map((mem) => mem.frontmatter.id) : [];
913
917
  const externalRoots = [];
914
918
  if (opts.include && opts.include.length > 0) {
915
919
  for (const includePath of opts.include) {
@@ -1063,11 +1067,14 @@ function registerBriefing(program2) {
1063
1067
  if (ids.length > 0) {
1064
1068
  await trackReads(paths, ids).catch(() => {
1065
1069
  });
1070
+ }
1071
+ const markerIds = [.../* @__PURE__ */ new Set([...ids, ...anchoredPolicyIds])];
1072
+ if (markerIds.length > 0) {
1066
1073
  await writeBriefingMarker(paths, {
1067
1074
  task: opts.task ?? "CLI briefing",
1068
1075
  source: "haive-briefing-cli",
1069
1076
  sessionId: process.env.HAIVE_SESSION_ID,
1070
- memoryIds: ids,
1077
+ memoryIds: markerIds,
1071
1078
  files: filePaths
1072
1079
  }).catch(() => {
1073
1080
  });
@@ -3012,7 +3019,7 @@ ${SEED_FOOTER(stack)}` });
3012
3019
  }
3013
3020
 
3014
3021
  // src/commands/init.ts
3015
- var HAIVE_GITHUB_ACTION_REF = `v${"0.13.5"}`;
3022
+ var HAIVE_GITHUB_ACTION_REF = `v${"0.13.7"}`;
3016
3023
  var PROJECT_CONTEXT_TEMPLATE = `# Project context
3017
3024
 
3018
3025
  > Generated by \`haive init\`. Run \`haive init --bootstrap\` to auto-fill from your codebase,
@@ -6065,7 +6072,7 @@ ${m.content}`).join("\n\n---\n\n"),
6065
6072
  return {
6066
6073
  id,
6067
6074
  summary,
6068
- developer_message: quoteBlock || `Une modification externe potentiellement incompatible a \xE9t\xE9 d\xE9tect\xE9e (${id}). Veux-tu que j'analyse l'impact et que je propose des mises \xE0 jour ?`
6075
+ developer_message: quoteBlock || `A potentially incompatible external change was detected (${id}). Do you want me to analyze the impact and propose updates?`
6069
6076
  };
6070
6077
  };
6071
6078
  for (const m of outputMemories) {
@@ -7912,7 +7919,7 @@ When done, respond with: "Imported N memories: [list of IDs]" or "Nothing action
7912
7919
  };
7913
7920
  }
7914
7921
  var SERVER_NAME = "haive";
7915
- var SERVER_VERSION = "0.13.5";
7922
+ var SERVER_VERSION = "0.13.7";
7916
7923
  function jsonResult(data) {
7917
7924
  return {
7918
7925
  content: [
@@ -9220,26 +9227,26 @@ function registerSync(program2) {
9220
9227
  const slugParts = result.file.replace(/[^a-z0-9]/gi, "-").toLowerCase();
9221
9228
  const slug = `dep-major-bump-${slugParts}-${Date.now().toString(36)}`;
9222
9229
  const depList = majorBumps.map((c) => `- \u{1F534} **${c.name}** : \`${c.from}\` \u2192 \`${c.to}\``).join("\n");
9223
- const body = `## \u26A0\uFE0F Action requise \u2014 confirmation humaine obligatoire
9230
+ const body = `## \u26A0\uFE0F Action required \u2014 human confirmation required
9224
9231
 
9225
- Des d\xE9pendances dans \`${result.file}\` ont chang\xE9 de version majeure.
9226
- Une version majeure peut contenir des **breaking changes** qui impactent ce projet.
9232
+ Dependencies in \`${result.file}\` changed major version.
9233
+ A major version can contain **breaking changes** that affect this project.
9227
9234
 
9228
9235
  ${depList}
9229
9236
 
9230
9237
  ---
9231
9238
 
9232
- **\u{1F6AB} Ne modifie aucun code de fa\xE7on autonome.**
9239
+ **\u{1F6AB} Do not modify code autonomously.**
9233
9240
 
9234
- Informe le d\xE9veloppeur avec ce message :
9241
+ Inform the developer with this message:
9235
9242
 
9236
- > *\xAB J'ai d\xE9tect\xE9 que ${majorBumps.map((c) => `\`${c.name}\``).join(", ")} a chang\xE9 de version majeure (${majorBumps.map((c) => `${c.from} \u2192 ${c.to}`).join(", ")}). Cela peut introduire des incompatibilit\xE9s dans ce projet. Veux-tu que j'analyse l'impact et que je propose des mises \xE0 jour ? \xBB*
9243
+ > *"I detected that ${majorBumps.map((c) => `\`${c.name}\``).join(", ")} changed major version (${majorBumps.map((c) => `${c.from} \u2192 ${c.to}`).join(", ")}). This can introduce incompatibilities in this project. Do you want me to analyze the impact and propose updates?"*
9237
9244
 
9238
- Attends une **confirmation explicite** avant d'agir.
9245
+ Wait for **explicit confirmation** before acting.
9239
9246
 
9240
- **Prochaines \xE9tapes (si confirm\xE9) :**
9241
- - Consulter le CHANGELOG : \`haive memory import-changelog --from node_modules/<pkg>/CHANGELOG.md\`
9242
- - V\xE9rifier les m\xE9moires ancr\xE9es : \`haive memory verify\``;
9247
+ **Next steps (if confirmed):**
9248
+ - Check the CHANGELOG: \`haive memory import-changelog --from node_modules/<pkg>/CHANGELOG.md\`
9249
+ - Verify anchored memories: \`haive memory verify\``;
9243
9250
  const fm = buildFrontmatter6({
9244
9251
  type: "gotcha",
9245
9252
  slug,
@@ -9287,28 +9294,28 @@ Attends une **confirmation explicite** avant d'agir.
9287
9294
  const breakingList = breaking.map((c) => `- \u{1F534} **${c.kind}** : ${c.description}`).join("\n");
9288
9295
  const addList = additive.length > 0 ? `
9289
9296
 
9290
- ### Changements non-breaking (additifs)
9297
+ ### Non-breaking changes (additive)
9291
9298
  ` + additive.map((c) => `- \u{1F7E2} ${c.description}`).join("\n") : "";
9292
- const body = `## \u26A0\uFE0F Action requise \u2014 confirmation humaine obligatoire
9299
+ const body = `## \u26A0\uFE0F Action required \u2014 human confirmation required
9293
9300
 
9294
- Le contrat **\`${diff.contract}\`** (\`${diff.file}\`) a \xE9t\xE9 modifi\xE9.
9295
- Des **breaking changes** ont \xE9t\xE9 d\xE9tect\xE9s \u2014 ce projet consomme peut-\xEAtre ce contrat.
9301
+ Contract **\`${diff.contract}\`** (\`${diff.file}\`) was modified.
9302
+ **Breaking changes** were detected \u2014 this project may consume that contract.
9296
9303
 
9297
9304
  ${breakingList}${addList}
9298
9305
 
9299
9306
  ---
9300
9307
 
9301
- **\u{1F6AB} Ne modifie aucun code de fa\xE7on autonome.**
9308
+ **\u{1F6AB} Do not modify code autonomously.**
9302
9309
 
9303
- Informe le d\xE9veloppeur avec ce message :
9310
+ Inform the developer with this message:
9304
9311
 
9305
- > *\xAB J'ai d\xE9tect\xE9 que le contrat \`${diff.contract}\` a chang\xE9 : ${breaking.length} breaking change(s) d\xE9tect\xE9(s). Ce projet d\xE9pend peut-\xEAtre de ce contrat. Veux-tu que j'analyse l'impact et que je propose des mises \xE0 jour ? \xBB*
9312
+ > *"I detected that contract \`${diff.contract}\` changed: ${breaking.length} breaking change(s) detected. This project may depend on that contract. Do you want me to analyze the impact and propose updates?"*
9306
9313
 
9307
- Attends une **confirmation explicite** avant d'agir.
9314
+ Wait for **explicit confirmation** before acting.
9308
9315
 
9309
- **Prochaines \xE9tapes (si confirm\xE9) :**
9310
- - Rechercher les usages : \`haive memory for-files <fichiers concern\xE9s>\`
9311
- - V\xE9rifier les m\xE9moires li\xE9es : \`haive memory search ${diff.contract}\``;
9316
+ **Next steps (if confirmed):**
9317
+ - Search usages: \`haive memory for-files <affected files>\`
9318
+ - Check related memories: \`haive memory search ${diff.contract}\``;
9312
9319
  const fm = buildFrontmatter6({
9313
9320
  type: "gotcha",
9314
9321
  slug,
@@ -12671,7 +12678,7 @@ import {
12671
12678
  } from "@hiveai/core";
12672
12679
  function registerEval(program2) {
12673
12680
  program2.command("eval").description(
12674
- "Rigorous, repeatable quality eval: do the right memories surface (retrieval) and do the right sensors fire (catch-rate)? Emits a chiffr\xE9 0\u2013100 score. Uses .ai/eval cases via --spec, or auto-synthesizes cases from anchored memories."
12681
+ "Rigorous, repeatable quality eval: do the right memories surface (retrieval) and do the right sensors fire (catch-rate)? Emits a numeric 0\u2013100 score. Uses .ai/eval cases via --spec, or auto-synthesizes cases from anchored memories."
12675
12682
  ).option("--spec <file>", "JSON eval spec ({ retrieval: [...], sensors: [...] })").option("--semantic-only", "self-eval probes by title alone (no anchor files) \u2014 harder retrieval", false).option("-k, --top <n>", "briefing top-k considered a hit", "8").option("--json", "emit JSON", false).option("--out <file>", "write a Markdown report").option("--fail-under <score>", "exit non-zero if the overall score is below this (0\u2013100) \u2014 for CI gates").option("--baseline", "save this run as the baseline (.ai/eval/baseline.json) for future --compare", false).option("--compare", "diff this run against the saved baseline and print the delta", false).option("--baseline-file <path>", "baseline file to read/write (default: .ai/eval/baseline.json)").option("--fail-on-regression", "with --compare, exit non-zero if the score dropped vs the baseline", false).option("--regression-gate", "CI-safe gate: compare against the baseline IF one exists (fail on regression), else no-op", false).option("-d, --dir <dir>", "project root").action(async (opts) => {
12676
12683
  const root = findProjectRoot42(opts.dir);
12677
12684
  const paths = resolveHaivePaths38(root);
@@ -13481,7 +13488,7 @@ function registerDoctor(program2) {
13481
13488
  fix: "Edit .ai/haive.config.json: set autoSessionEnd: true (or re-run `haive init` without --manual)."
13482
13489
  });
13483
13490
  }
13484
- findings.push(...await collectInstallFindings(root, "0.13.5"));
13491
+ findings.push(...await collectInstallFindings(root, "0.13.7"));
13485
13492
  findings.push(...await collectToolchainFindings(root));
13486
13493
  try {
13487
13494
  const legacyRaw = execSync3("haive-mcp --version", {
@@ -13489,7 +13496,7 @@ function registerDoctor(program2) {
13489
13496
  timeout: 3e3,
13490
13497
  stdio: ["ignore", "pipe", "ignore"]
13491
13498
  }).trim();
13492
- const cliVersion = "0.13.5";
13499
+ const cliVersion = "0.13.7";
13493
13500
  if (legacyRaw && legacyRaw !== cliVersion) {
13494
13501
  findings.push({
13495
13502
  severity: "warn",
@@ -14644,7 +14651,10 @@ function registerEnforce(program2) {
14644
14651
  ).option("-d, --dir <dir>", "project root").option("--explain", "group findings by blocking/review/info and show repair commands", false).option("--json", "emit JSON", false).action(async (opts) => {
14645
14652
  const report = await buildFinishReport(opts.dir);
14646
14653
  printReport(report, Boolean(opts.json), Boolean(opts.explain));
14647
- if (report.should_block) process.exit(2);
14654
+ if (report.should_block) {
14655
+ if (!opts.json) printNextRequiredAction(report);
14656
+ process.exit(2);
14657
+ }
14648
14658
  });
14649
14659
  enforce.command("session-start").description("Claude Code SessionStart hook: inject briefing and write a local briefing marker.").option("-d, --dir <dir>", "project root").option("--task <text>", "task text to rank memories").option("--source <name>", "marker source", "claude-session-start").option("--session-id <id>", "agent session id").action(async (opts) => {
14650
14660
  const payload = await readHookPayload();
@@ -15085,7 +15095,7 @@ async function buildEnforcementReport(dir, stage, sessionId) {
15085
15095
  findings: [{ severity: "info", code: "enforcement-off", message: "hAIve enforcement is disabled." }]
15086
15096
  });
15087
15097
  }
15088
- findings.push(...await inspectIntegrationVersions(root, "0.13.5"));
15098
+ findings.push(...await inspectIntegrationVersions(root, "0.13.7"));
15089
15099
  if (config.enforcement?.requireBriefingFirst !== false && stage !== "ci") {
15090
15100
  const hasBriefing = await hasRecentBriefingMarker2(paths, sessionId);
15091
15101
  findings.push(hasBriefing ? { severity: "ok", code: "briefing-loaded", message: "A recent hAIve briefing marker exists." } : {
@@ -15688,11 +15698,22 @@ async function verifyGithubActionsForHead(root, status) {
15688
15698
  }];
15689
15699
  }
15690
15700
  if (runs.length === 0) {
15701
+ const headMsg = (await runCommand4("git", ["log", "-1", "--pretty=%B"], root).catch(() => "")).trim();
15702
+ if (/\[skip ci\]|\[ci skip\]|\[no ci\]|\*\*\*NO_CI\*\*\*|skip-checks: *true/i.test(headMsg)) {
15703
+ return [{
15704
+ severity: "error",
15705
+ code: "github-actions-skipped-by-message",
15706
+ message: "No GitHub Actions runs for HEAD because the HEAD commit message contains a CI-skip directive ([skip ci] / [ci skip] / [no ci]) \u2014 this skips the WHOLE push, including code.",
15707
+ fix: "Reword the HEAD commit so its message (subject AND body) does not contain the literal skip-ci directive \u2014 write it as 'skip-ci'. Then re-push, or trigger CI manually with `gh workflow run <workflow.yml> --ref <branch>`.",
15708
+ reason: "GitHub scans the entire commit message; a code commit whose message includes a skip-ci directive silently skips CI for the whole push.",
15709
+ impact: 60
15710
+ }];
15711
+ }
15691
15712
  return [{
15692
15713
  severity: "error",
15693
15714
  code: "github-actions-runs-missing",
15694
15715
  message: "No GitHub Actions runs were found for HEAD.",
15695
- fix: "Wait for GitHub to create the workflow runs, or verify that the push was not skipped by a `[skip ci]` head commit; rerun `haive enforce finish` after the runs appear.",
15716
+ fix: "Wait for GitHub to create the workflow runs, or verify that the push was not skipped by a skip-ci head commit; rerun `haive enforce finish` after the runs appear.",
15696
15717
  impact: 50
15697
15718
  }];
15698
15719
  }
@@ -15707,21 +15728,35 @@ async function verifyGithubActionsForHead(root, status) {
15707
15728
  }];
15708
15729
  }
15709
15730
  const failed = runs.filter((run) => run.conclusion !== "success");
15710
- if (failed.length > 0) {
15731
+ const failedCore = failed.filter((run) => !isExternalTransientWorkflow(run));
15732
+ const failedExternal = failed.filter((run) => isExternalTransientWorkflow(run));
15733
+ if (failedCore.length > 0) {
15711
15734
  return [{
15712
15735
  severity: "error",
15713
15736
  code: "github-actions-failed",
15714
- message: `${failed.length}/${runs.length} GitHub Actions workflow run(s) for HEAD did not pass: ${formatGithubRunNames(failed)}.`,
15737
+ message: `${failedCore.length}/${runs.length} GitHub Actions workflow run(s) for HEAD did not pass: ${formatGithubRunNames(failedCore)}.`,
15715
15738
  fix: "Inspect the failed run logs with `gh run view <run-id> --log`, fix the issue, push the fix, then rerun `haive enforce finish`.",
15716
15739
  impact: 80
15717
15740
  }];
15718
15741
  }
15742
+ if (failedExternal.length > 0) {
15743
+ return [{
15744
+ severity: "info",
15745
+ code: "github-actions-external-transient",
15746
+ message: `${failedExternal.length} external/transient workflow run(s) for HEAD did not pass (non-blocking): ${formatGithubRunNames(failedExternal)}. All core workflows passed.`,
15747
+ fix: "External integrations can fail on transient network/timeout. Re-run with `gh run rerun <run-id>` if you want them green \u2014 not required to finish."
15748
+ }];
15749
+ }
15719
15750
  return [{
15720
15751
  severity: "ok",
15721
15752
  code: "github-actions-pass",
15722
15753
  message: `All ${runs.length} GitHub Actions workflow run(s) for HEAD completed successfully.`
15723
15754
  }];
15724
15755
  }
15756
+ function isExternalTransientWorkflow(run) {
15757
+ const label = `${run.workflowName ?? ""} ${run.name ?? ""}`.toLowerCase();
15758
+ return /\bsonar(qube|cloud)?\b|\bcodeql\b|\bsnyk\b|\bcodecov\b/.test(label);
15759
+ }
15725
15760
  async function githubRemoteForCurrentBranch(root) {
15726
15761
  const branch = (await runCommand4("git", ["branch", "--show-current"], root).catch(() => "")).trim();
15727
15762
  const branchRemote = branch ? (await runCommand4("git", ["config", "--get", `branch.${branch}.remote`], root).catch(() => "")).trim() : "";
@@ -15871,6 +15906,13 @@ function printFinding(finding, explain = false) {
15871
15906
  if (explain && finding.memory_ids?.length) console.log(ui.dim(` memories: ${finding.memory_ids.join(", ")}`));
15872
15907
  if (finding.fix) console.log(ui.dim(`${explain ? " repair: " : " fix: "}${finding.fix}`));
15873
15908
  }
15909
+ function printNextRequiredAction(report) {
15910
+ const blocker = report.findings.find((f) => f.severity === "error" && f.fix);
15911
+ if (!blocker) return;
15912
+ console.log("");
15913
+ console.log(ui.bold("\u2192 NEXT REQUIRED ACTION") + ui.dim(` (${blocker.code})`));
15914
+ for (const line of blocker.fix.split("\n")) console.log(` ${line}`);
15915
+ }
15874
15916
  async function applyLightweightRepairs(root, paths) {
15875
15917
  await applyAutopilotRepairs(root, paths, {
15876
15918
  applyConfig: false,
@@ -15974,13 +16016,13 @@ async function readStdin2(maxBytes) {
15974
16016
  setTimeout(finish, 2e3);
15975
16017
  });
15976
16018
  }
16019
+ var ATOMIC_STAGE_EXCLUDE = ["/.usage/", "/.runtime/", "/.cache/"];
15977
16020
  async function stageResyncedArtifacts(root, paths) {
15978
- const rel = path51.relative(root, paths.projectContext);
15979
- const tracked = await runCommand4("git", ["ls-files", "--error-unmatch", "--", rel], root).then(() => true).catch(() => false);
15980
- if (!tracked) return;
15981
- const unchanged = await runCommand4("git", ["diff", "--quiet", "--", rel], root).then(() => true).catch(() => false);
15982
- if (unchanged) return;
15983
- await runCommand4("git", ["add", "--", rel], root).catch(() => {
16021
+ const aiRel = path51.relative(root, paths.haiveDir);
16022
+ const out = await runCommand4("git", ["diff", "--name-only", "--", aiRel], root).catch(() => "");
16023
+ const toStage = out.split("\n").map((line) => line.trim()).filter(Boolean).filter((file) => !ATOMIC_STAGE_EXCLUDE.some((excl) => `/${file}`.includes(excl)));
16024
+ if (toStage.length === 0) return;
16025
+ await runCommand4("git", ["add", "--", ...toStage], root).catch(() => {
15984
16026
  });
15985
16027
  }
15986
16028
  function runCommand4(cmd, args, cwd) {
@@ -16500,7 +16542,7 @@ function warnNum(n) {
16500
16542
 
16501
16543
  // src/index.ts
16502
16544
  var program = new Command58();
16503
- program.name("haive").description("hAIve - repo-native memory and context policy for coding-agent harnesses").version("0.13.5").option("--advanced", "show maintenance and experimental commands in help");
16545
+ program.name("haive").description("hAIve - repo-native memory and context policy for coding-agent harnesses").version("0.13.7").option("--advanced", "show maintenance and experimental commands in help");
16504
16546
  registerInit(program);
16505
16547
  registerWelcome(program);
16506
16548
  registerResolveProject(program);