@hiveai/cli 0.13.0 → 0.13.5
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 +73 -28
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -3012,7 +3012,7 @@ ${SEED_FOOTER(stack)}` });
|
|
|
3012
3012
|
}
|
|
3013
3013
|
|
|
3014
3014
|
// src/commands/init.ts
|
|
3015
|
-
var HAIVE_GITHUB_ACTION_REF = `v${"0.13.
|
|
3015
|
+
var HAIVE_GITHUB_ACTION_REF = `v${"0.13.5"}`;
|
|
3016
3016
|
var PROJECT_CONTEXT_TEMPLATE = `# Project context
|
|
3017
3017
|
|
|
3018
3018
|
> Generated by \`haive init\`. Run \`haive init --bootstrap\` to auto-fill from your codebase,
|
|
@@ -3176,6 +3176,27 @@ jobs:
|
|
|
3176
3176
|
# post-if-empty: 'true' # uncomment to always post (even when no memories found)
|
|
3177
3177
|
# max-memories: '5' # limit memories per file in the comment
|
|
3178
3178
|
|
|
3179
|
+
# On pull request: fail if the harness quality score regressed vs the committed baseline.
|
|
3180
|
+
# Measures whether the right memories still surface and the right sensors still fire.
|
|
3181
|
+
# No-op (passes) when no .ai/eval/baseline.json exists \u2014 safe to keep enabled before you
|
|
3182
|
+
# ever create one. To turn the gate on: run \`haive eval --baseline\` locally and commit
|
|
3183
|
+
# .ai/eval/baseline.json. Needs nothing external \u2014 no secrets, no services.
|
|
3184
|
+
pr-eval-gate:
|
|
3185
|
+
if: github.event_name == 'pull_request'
|
|
3186
|
+
runs-on: ubuntu-latest
|
|
3187
|
+
steps:
|
|
3188
|
+
- uses: actions/checkout@v4
|
|
3189
|
+
|
|
3190
|
+
- uses: actions/setup-node@v4
|
|
3191
|
+
with:
|
|
3192
|
+
node-version: '20'
|
|
3193
|
+
|
|
3194
|
+
- name: install haive
|
|
3195
|
+
run: npm install -g @hiveai/cli
|
|
3196
|
+
|
|
3197
|
+
- name: harness quality regression gate
|
|
3198
|
+
run: haive eval --regression-gate
|
|
3199
|
+
|
|
3179
3200
|
# On push to main: push shared memories to the hub (if hubPath is configured)
|
|
3180
3201
|
# Uncomment and configure hubPath in .ai/haive.config.json to enable.
|
|
3181
3202
|
# hub-push:
|
|
@@ -3728,7 +3749,7 @@ async function installClaudeHooks(opts) {
|
|
|
3728
3749
|
}
|
|
3729
3750
|
function registerInstallHooks(program2) {
|
|
3730
3751
|
program2.command("install-hooks [target]").description(
|
|
3731
|
-
"Install hAIve hooks. Targets:\n\n git (default) post-merge / post-rewrite / pre-push for haive sync + precommit\n claude SessionStart + PreToolUse + PostToolUse + SessionEnd hooks\n for briefing injection, pre-edit blocking, and capture (Claude Code only)\n\n Examples:\n haive install-hooks # git hooks (legacy default)\n haive install-hooks git\n haive install-hooks claude\n haive install-hooks claude --scope project\n haive install-hooks claude --uninstall\n"
|
|
3752
|
+
"Install hAIve hooks (same effect as `haive enforce install`, kept for back-compat). Targets:\n\n git (default) post-merge / post-rewrite / pre-push for haive sync + precommit\n claude SessionStart + PreToolUse + PostToolUse + SessionEnd hooks\n for briefing injection, pre-edit blocking, and capture (Claude Code only)\n\n Examples:\n haive install-hooks # git hooks (legacy default)\n haive install-hooks git\n haive install-hooks claude\n haive install-hooks claude --scope project\n haive install-hooks claude --uninstall\n"
|
|
3732
3753
|
).option("-d, --dir <dir>", "project root").option("--force", "overwrite existing hooks (git target only)").option("--scope <scope>", "claude target: 'user' (~/.claude) or 'project' (.claude/)", "user").option("--uninstall", "remove previously installed hAIve hooks (claude target only)").option("--settings <path>", "explicit path to settings.json (claude target only)").action(async (target, opts) => {
|
|
3733
3754
|
const t = (target ?? "git").toLowerCase();
|
|
3734
3755
|
if (t === "git") {
|
|
@@ -7891,7 +7912,7 @@ When done, respond with: "Imported N memories: [list of IDs]" or "Nothing action
|
|
|
7891
7912
|
};
|
|
7892
7913
|
}
|
|
7893
7914
|
var SERVER_NAME = "haive";
|
|
7894
|
-
var SERVER_VERSION = "0.13.
|
|
7915
|
+
var SERVER_VERSION = "0.13.5";
|
|
7895
7916
|
function jsonResult(data) {
|
|
7896
7917
|
return {
|
|
7897
7918
|
content: [
|
|
@@ -9287,7 +9308,7 @@ Attends une **confirmation explicite** avant d'agir.
|
|
|
9287
9308
|
|
|
9288
9309
|
**Prochaines \xE9tapes (si confirm\xE9) :**
|
|
9289
9310
|
- Rechercher les usages : \`haive memory for-files <fichiers concern\xE9s>\`
|
|
9290
|
-
- V\xE9rifier les m\xE9moires li\xE9es : \`haive memory
|
|
9311
|
+
- V\xE9rifier les m\xE9moires li\xE9es : \`haive memory search ${diff.contract}\``;
|
|
9291
9312
|
const fm = buildFrontmatter6({
|
|
9292
9313
|
type: "gotcha",
|
|
9293
9314
|
slug,
|
|
@@ -9484,8 +9505,8 @@ import {
|
|
|
9484
9505
|
suggestSensorFromMemory as suggestSensorFromMemory3
|
|
9485
9506
|
} from "@hiveai/core";
|
|
9486
9507
|
function registerMemoryAdd(memory2) {
|
|
9487
|
-
memory2.command("add").description(
|
|
9488
|
-
`Save a piece of knowledge as a persistent memory.
|
|
9508
|
+
memory2.command("save").alias("add").description(
|
|
9509
|
+
`Save a piece of knowledge as a persistent memory. Mirrors MCP mem_save. Alias: add.
|
|
9489
9510
|
|
|
9490
9511
|
Memory types:
|
|
9491
9512
|
skill \u2014 reusable procedure/playbook agents follow for a recurring task (e.g. deploy, review)
|
|
@@ -10534,7 +10555,7 @@ function registerMemoryPending(memory2) {
|
|
|
10534
10555
|
const pending = all.filter(filterFn);
|
|
10535
10556
|
if (pending.length === 0) {
|
|
10536
10557
|
ui.info("No draft or proposed memories awaiting review.");
|
|
10537
|
-
ui.info("Drafts are created by `haive memory
|
|
10558
|
+
ui.info("Drafts are created by `haive memory save` without `--status validated`.");
|
|
10538
10559
|
return;
|
|
10539
10560
|
}
|
|
10540
10561
|
pending.sort(
|
|
@@ -10591,7 +10612,7 @@ import {
|
|
|
10591
10612
|
trackReads as trackReads4
|
|
10592
10613
|
} from "@hiveai/core";
|
|
10593
10614
|
function registerMemoryQuery(memory2) {
|
|
10594
|
-
memory2.command("
|
|
10615
|
+
memory2.command("search <text>").alias("query").description("Search memories by id, tag, or substring (AND, OR fallback). Mirrors MCP mem_search. Alias: query").option("-d, --dir <dir>", "project root").option("--limit <n>", "max results", "20").option("--scope <scope>", "personal | team | module").option("--status <csv>", "filter by status (draft,proposed,validated,stale,rejected)").option("--show-rejected", "include rejected memories (hidden by default)").action(async (text, opts) => {
|
|
10595
10616
|
const root = findProjectRoot25(opts.dir);
|
|
10596
10617
|
const paths = resolveHaivePaths22(root);
|
|
10597
10618
|
if (!existsSync47(paths.memoriesDir)) {
|
|
@@ -10715,7 +10736,7 @@ import {
|
|
|
10715
10736
|
saveUsageIndex as saveUsageIndex5
|
|
10716
10737
|
} from "@hiveai/core";
|
|
10717
10738
|
function registerMemoryRm(memory2) {
|
|
10718
|
-
memory2.command("
|
|
10739
|
+
memory2.command("delete <id>").alias("rm").description("Delete a memory file (and its usage entry by default). Mirrors MCP mem_delete. Alias: rm").option("-y, --yes", "skip the confirmation prompt").option("--keep-usage", "do not remove the usage.json entry").option("-d, --dir <dir>", "project root").action(async (id, opts) => {
|
|
10719
10740
|
const root = findProjectRoot27(opts.dir);
|
|
10720
10741
|
const paths = resolveHaivePaths24(root);
|
|
10721
10742
|
if (!existsSync49(paths.memoriesDir)) {
|
|
@@ -10766,7 +10787,7 @@ import {
|
|
|
10766
10787
|
resolveHaivePaths as resolveHaivePaths25
|
|
10767
10788
|
} from "@hiveai/core";
|
|
10768
10789
|
function registerMemoryShow(memory2) {
|
|
10769
|
-
memory2.command("
|
|
10790
|
+
memory2.command("get <id>").alias("show").description("Print a memory's frontmatter, body, and confidence/usage. Mirrors MCP mem_get. Alias: show").option("--raw", "print the raw file contents instead of a summary").option("-d, --dir <dir>", "project root").action(async (id, opts) => {
|
|
10770
10791
|
const root = findProjectRoot28(opts.dir);
|
|
10771
10792
|
const paths = resolveHaivePaths25(root);
|
|
10772
10793
|
if (!existsSync50(paths.memoriesDir)) {
|
|
@@ -12334,7 +12355,7 @@ async function renderMemoryHits(paths, opts) {
|
|
|
12334
12355
|
console.log(ui.bold(`Memory hits (${window})`));
|
|
12335
12356
|
if (entries.length === 0) {
|
|
12336
12357
|
ui.info(
|
|
12337
|
-
`No memory reads recorded in window. Reads are logged when \`haive briefing\` or \`haive memory
|
|
12358
|
+
`No memory reads recorded in window. Reads are logged when \`haive briefing\` or \`haive memory search\` surface a memory.`
|
|
12338
12359
|
);
|
|
12339
12360
|
return;
|
|
12340
12361
|
}
|
|
@@ -12367,7 +12388,7 @@ import {
|
|
|
12367
12388
|
resolveHaivePaths as resolveHaivePaths37
|
|
12368
12389
|
} from "@hiveai/core";
|
|
12369
12390
|
function registerBench(program2) {
|
|
12370
|
-
program2.command("bench").description("Self-test the
|
|
12391
|
+
program2.command("selftest").alias("bench").description("Self-test the LOCAL hAIve install: runs core MCP tools against this project and reports latency + payload size. Different from `benchmark` (which measures hAIve-vs-plain agent value). Alias: bench").option("-t, --task <task>", "task description for ranking-aware tools", "audit dependencies for security risks").option("--json", "emit JSON instead of a table", false).option("-d, --dir <dir>", "project root").action(async (opts) => {
|
|
12371
12392
|
const root = findProjectRoot40(opts.dir);
|
|
12372
12393
|
const paths = resolveHaivePaths37(root);
|
|
12373
12394
|
const ctx = { paths };
|
|
@@ -12494,7 +12515,7 @@ import path41 from "path";
|
|
|
12494
12515
|
import "commander";
|
|
12495
12516
|
import { estimateTokens as estimateTokens4, findProjectRoot as findProjectRoot41 } from "@hiveai/core";
|
|
12496
12517
|
function registerBenchmark(program2) {
|
|
12497
|
-
const benchmark = program2.command("benchmark").description("
|
|
12518
|
+
const benchmark = program2.command("benchmark").description("Measure hAIve's VALUE: paired hAIve-vs-plain agent runs (correctness, tokens, tools). Different from `selftest` (which only checks local install latency).");
|
|
12498
12519
|
benchmark.command("report").description("Summarize BENCHMARK_AGENT_REPORT.md files from a paired hAIve/plain agent benchmark.").option("-d, --dir <dir>", "benchmark root", "benchmarks/agent-benchmark").option("--out <file>", "write a Markdown report").option("--json", "emit JSON", false).action(async (opts) => {
|
|
12499
12520
|
const root = resolveBenchmarkRoot(opts.dir);
|
|
12500
12521
|
const rows = await collectRows(root);
|
|
@@ -13323,7 +13344,7 @@ function registerDoctor(program2) {
|
|
|
13323
13344
|
severity: "warn",
|
|
13324
13345
|
code: "stale-draft-memories",
|
|
13325
13346
|
message: `${oldDrafts.length} draft memor${oldDrafts.length === 1 ? "y has" : "ies have"} been in draft status for 30+ days: ${ids}${more}`,
|
|
13326
|
-
fix: "haive memory approve <id> # activate\nhaive memory
|
|
13347
|
+
fix: "haive memory approve <id> # activate\nhaive memory delete <id> # or delete if obsolete"
|
|
13327
13348
|
});
|
|
13328
13349
|
}
|
|
13329
13350
|
const policyMemories = memories.filter((m) => !isStackPackSeed4(m.memory.frontmatter));
|
|
@@ -13460,7 +13481,7 @@ function registerDoctor(program2) {
|
|
|
13460
13481
|
fix: "Edit .ai/haive.config.json: set autoSessionEnd: true (or re-run `haive init` without --manual)."
|
|
13461
13482
|
});
|
|
13462
13483
|
}
|
|
13463
|
-
findings.push(...await collectInstallFindings(root, "0.13.
|
|
13484
|
+
findings.push(...await collectInstallFindings(root, "0.13.5"));
|
|
13464
13485
|
findings.push(...await collectToolchainFindings(root));
|
|
13465
13486
|
try {
|
|
13466
13487
|
const legacyRaw = execSync3("haive-mcp --version", {
|
|
@@ -13468,7 +13489,7 @@ function registerDoctor(program2) {
|
|
|
13468
13489
|
timeout: 3e3,
|
|
13469
13490
|
stdio: ["ignore", "pipe", "ignore"]
|
|
13470
13491
|
}).trim();
|
|
13471
|
-
const cliVersion = "0.13.
|
|
13492
|
+
const cliVersion = "0.13.5";
|
|
13472
13493
|
if (legacyRaw && legacyRaw !== cliVersion) {
|
|
13473
13494
|
findings.push({
|
|
13474
13495
|
severity: "warn",
|
|
@@ -13684,7 +13705,7 @@ async function collectHarnessCoverageFindings(codeMap, memories) {
|
|
|
13684
13705
|
code: "harness-coverage",
|
|
13685
13706
|
coverage_percent: pct2,
|
|
13686
13707
|
message: `${covered}/${total} code-map files have validated memory anchors (${pct2}%). ` + coverageDesc + uncoveredHint,
|
|
13687
|
-
fix: pct2 < 50 && total > 10 ? `haive memory
|
|
13708
|
+
fix: pct2 < 50 && total > 10 ? `haive memory save --type gotcha|convention|architecture --paths <key-file> --scope team` : void 0,
|
|
13688
13709
|
section: "Harness coverage"
|
|
13689
13710
|
});
|
|
13690
13711
|
return findings;
|
|
@@ -14145,7 +14166,7 @@ import {
|
|
|
14145
14166
|
} from "@hiveai/core";
|
|
14146
14167
|
function registerPrecommit(program2) {
|
|
14147
14168
|
program2.command("precommit").description(
|
|
14148
|
-
"Run a pre-commit safety check
|
|
14169
|
+
"Run a pre-commit safety check (manual variant of `haive enforce check --stage pre-commit`):\n 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"
|
|
14149
14170
|
).option(
|
|
14150
14171
|
"--block-on <mode>",
|
|
14151
14172
|
"'any' | 'high-confidence' | 'never' (report only). Default: derived from enforcement.antiPatternGate."
|
|
@@ -14335,7 +14356,7 @@ function registerWelcome(program2) {
|
|
|
14335
14356
|
console.log(ui.bold(`hAIve welcome \u2014 ${pick.length} team memories (${root})`));
|
|
14336
14357
|
console.log(ui.dim(`Next: invoke get_briefing with your task or run 'haive briefing --task "\u2026"'`));
|
|
14337
14358
|
if (pick.length === 0) {
|
|
14338
|
-
ui.warn("No team memories yet \u2014 add some with 'haive memory
|
|
14359
|
+
ui.warn("No team memories yet \u2014 add some with 'haive memory save' or promote personal ones.");
|
|
14339
14360
|
return;
|
|
14340
14361
|
}
|
|
14341
14362
|
let i = 1;
|
|
@@ -15032,7 +15053,10 @@ async function buildEnforcementReport(dir, stage, sessionId) {
|
|
|
15032
15053
|
const paths = resolveHaivePaths48(root);
|
|
15033
15054
|
const initialized = existsSync75(paths.haiveDir);
|
|
15034
15055
|
const config = initialized ? await loadConfig13(paths) : {};
|
|
15035
|
-
if (initialized)
|
|
15056
|
+
if (initialized) {
|
|
15057
|
+
await applyLightweightRepairs(root, paths);
|
|
15058
|
+
if (stage === "pre-commit") await stageResyncedArtifacts(root, paths);
|
|
15059
|
+
}
|
|
15036
15060
|
const mode = config.enforcement?.mode ?? "strict";
|
|
15037
15061
|
const findings = [];
|
|
15038
15062
|
if (!initialized) {
|
|
@@ -15061,7 +15085,7 @@ async function buildEnforcementReport(dir, stage, sessionId) {
|
|
|
15061
15085
|
findings: [{ severity: "info", code: "enforcement-off", message: "hAIve enforcement is disabled." }]
|
|
15062
15086
|
});
|
|
15063
15087
|
}
|
|
15064
|
-
findings.push(...await inspectIntegrationVersions(root, "0.13.
|
|
15088
|
+
findings.push(...await inspectIntegrationVersions(root, "0.13.5"));
|
|
15065
15089
|
if (config.enforcement?.requireBriefingFirst !== false && stage !== "ci") {
|
|
15066
15090
|
const hasBriefing = await hasRecentBriefingMarker2(paths, sessionId);
|
|
15067
15091
|
findings.push(hasBriefing ? { severity: "ok", code: "briefing-loaded", message: "A recent hAIve briefing marker exists." } : {
|
|
@@ -15950,6 +15974,15 @@ async function readStdin2(maxBytes) {
|
|
|
15950
15974
|
setTimeout(finish, 2e3);
|
|
15951
15975
|
});
|
|
15952
15976
|
}
|
|
15977
|
+
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(() => {
|
|
15984
|
+
});
|
|
15985
|
+
}
|
|
15953
15986
|
function runCommand4(cmd, args, cwd) {
|
|
15954
15987
|
return new Promise((resolve, reject) => {
|
|
15955
15988
|
const proc = spawn6(cmd, args, { cwd, stdio: ["ignore", "pipe", "pipe"] });
|
|
@@ -16467,7 +16500,7 @@ function warnNum(n) {
|
|
|
16467
16500
|
|
|
16468
16501
|
// src/index.ts
|
|
16469
16502
|
var program = new Command58();
|
|
16470
|
-
program.name("haive").description("hAIve - repo-native memory and context policy for coding-agent harnesses").version("0.13.
|
|
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");
|
|
16471
16504
|
registerInit(program);
|
|
16472
16505
|
registerWelcome(program);
|
|
16473
16506
|
registerResolveProject(program);
|
|
@@ -16543,14 +16576,14 @@ var CORE_ROOT_COMMANDS = /* @__PURE__ */ new Set([
|
|
|
16543
16576
|
"session"
|
|
16544
16577
|
]);
|
|
16545
16578
|
var CORE_MEMORY_COMMANDS = /* @__PURE__ */ new Set([
|
|
16546
|
-
"
|
|
16579
|
+
"save",
|
|
16547
16580
|
"list",
|
|
16548
|
-
"
|
|
16549
|
-
"
|
|
16581
|
+
"search",
|
|
16582
|
+
"get",
|
|
16550
16583
|
"verify",
|
|
16551
16584
|
"lint",
|
|
16552
16585
|
"tried",
|
|
16553
|
-
"
|
|
16586
|
+
"delete"
|
|
16554
16587
|
]);
|
|
16555
16588
|
var CORE_SESSION_COMMANDS = /* @__PURE__ */ new Set(["end"]);
|
|
16556
16589
|
applySurfaceVisibility(program);
|
|
@@ -16568,12 +16601,24 @@ program.parseAsync(process.argv).catch((err) => {
|
|
|
16568
16601
|
function applySurfaceVisibility(root) {
|
|
16569
16602
|
const showAdvanced = process.argv.includes("--advanced") || process.env.HAIVE_SHOW_ADVANCED === "1";
|
|
16570
16603
|
if (!showAdvanced) hideNonCoreCommands(root);
|
|
16604
|
+
const familiesBlock = showAdvanced ? [
|
|
16605
|
+
"",
|
|
16606
|
+
"Advanced surface, by family:",
|
|
16607
|
+
" reports: dashboard \xB7 stats \xB7 playback eval: eval \xB7 benchmark \xB7 selftest (alias: bench)",
|
|
16608
|
+
" index: index \xB7 code-search \xB7 embeddings runtime: runtime \xB7 observe \xB7 snapshot",
|
|
16609
|
+
" ops: memory <sub> \xB7 sensors \xB7 ingest \xB7 hub \xB7 sync \xB7 install-hooks (= enforce install) \xB7 precommit (= enforce check)"
|
|
16610
|
+
] : [];
|
|
16571
16611
|
root.addHelpText(
|
|
16572
16612
|
"after",
|
|
16573
16613
|
[
|
|
16574
16614
|
"",
|
|
16575
|
-
"
|
|
16576
|
-
"
|
|
16615
|
+
"Golden path (what you type day to day):",
|
|
16616
|
+
" init \u2192 doctor \u2192 agent setup \u2192 briefing \u2192 memory save/tried \u2192 sensors check \u2192 enforce finish \u2192 sync \u2192 session end",
|
|
16617
|
+
"",
|
|
16618
|
+
"Memory verbs mirror the MCP tools: memory save/search/get/delete <-> mem_save/mem_search/mem_get/mem_delete",
|
|
16619
|
+
"(old verbs add/query/show/rm still work as aliases).",
|
|
16620
|
+
...familiesBlock,
|
|
16621
|
+
"",
|
|
16577
16622
|
"Run `haive --advanced --help` or set HAIVE_SHOW_ADVANCED=1 to show maintenance and experimental commands."
|
|
16578
16623
|
].join("\n")
|
|
16579
16624
|
);
|