@hiveai/cli 0.9.20 → 0.9.21
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 +95 -52
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -6516,7 +6516,7 @@ When done, respond with: "Imported N memories: [list of IDs]" or "Nothing action
|
|
|
6516
6516
|
};
|
|
6517
6517
|
}
|
|
6518
6518
|
var SERVER_NAME = "haive";
|
|
6519
|
-
var SERVER_VERSION = "0.9.
|
|
6519
|
+
var SERVER_VERSION = "0.9.21";
|
|
6520
6520
|
function jsonResult(data) {
|
|
6521
6521
|
return {
|
|
6522
6522
|
content: [
|
|
@@ -8718,6 +8718,8 @@ function registerMemoryList(memory2) {
|
|
|
8718
8718
|
console.log(
|
|
8719
8719
|
`${ui.bold(fm.id)} ${ui.dim(fm.scope)}/${ui.dim(fm.type)} ${statusBadge}${moduleStr}${tagStr}`
|
|
8720
8720
|
);
|
|
8721
|
+
const title = mem.body.match(/^#\s+(.+)$/m)?.[1]?.trim();
|
|
8722
|
+
if (title && title !== fm.id) console.log(` ${title}`);
|
|
8721
8723
|
console.log(` ${ui.dim(path17.relative(root, filePath))}`);
|
|
8722
8724
|
}
|
|
8723
8725
|
console.log(ui.dim(`
|
|
@@ -8883,7 +8885,7 @@ function registerMemoryApprove(memory2) {
|
|
|
8883
8885
|
}
|
|
8884
8886
|
|
|
8885
8887
|
// src/commands/memory-update.ts
|
|
8886
|
-
import { writeFile as writeFile19 } from "fs/promises";
|
|
8888
|
+
import { readFile as readFile11, writeFile as writeFile19 } from "fs/promises";
|
|
8887
8889
|
import { existsSync as existsSync37 } from "fs";
|
|
8888
8890
|
import path20 from "path";
|
|
8889
8891
|
import "commander";
|
|
@@ -8893,7 +8895,7 @@ import {
|
|
|
8893
8895
|
serializeMemory as serializeMemory16
|
|
8894
8896
|
} from "@hiveai/core";
|
|
8895
8897
|
function registerMemoryUpdate(memory2) {
|
|
8896
|
-
memory2.command("update <id>").description("Update body, tags, or anchor of an existing memory (preserves id and usage history)").option("--title <text>", "new title \u2014 replaces the first heading of the body").option("--body <text>", "new Markdown body \u2014 replaces the existing body").option("--tags <csv>", "new tags, comma-separated \u2014 fully replaces existing tags").option("--paths <csv>", "new anchor paths, comma-separated").option("--symbols <csv>", "new anchor symbols, comma-separated").option("--commit <sha>", "new anchor commit SHA").option("--domain <domain>", "new domain label").option("--author <author>", "new author handle or email").option("-d, --dir <dir>", "project root").action(async (id, opts) => {
|
|
8898
|
+
memory2.command("update <id>").description("Update body, tags, or anchor of an existing memory (preserves id and usage history)").option("--type <type>", "change the memory type (convention | decision | gotcha | architecture | glossary | skill | attempt)").option("--title <text>", "new title \u2014 replaces the first heading of the body").option("--body <text>", "new Markdown body \u2014 replaces the existing body").option("--body-file <path>", "read new body from a Markdown file \u2014 for long content").option("--tags <csv>", "new tags, comma-separated \u2014 fully replaces existing tags").option("--paths <csv>", "new anchor paths, comma-separated").option("--symbols <csv>", "new anchor symbols, comma-separated").option("--commit <sha>", "new anchor commit SHA").option("--domain <domain>", "new domain label").option("--author <author>", "new author handle or email").option("-d, --dir <dir>", "project root").action(async (id, opts) => {
|
|
8897
8899
|
const root = findProjectRoot17(opts.dir);
|
|
8898
8900
|
const paths = resolveHaivePaths14(root);
|
|
8899
8901
|
if (!existsSync37(paths.memoriesDir)) {
|
|
@@ -8926,19 +8928,34 @@ function registerMemoryUpdate(memory2) {
|
|
|
8926
8928
|
const newFrontmatter = {
|
|
8927
8929
|
...frontmatter,
|
|
8928
8930
|
anchor: newAnchor,
|
|
8931
|
+
...opts.type !== void 0 ? { type: opts.type } : {},
|
|
8929
8932
|
...opts.tags !== void 0 ? { tags: parseCsv3(opts.tags) } : {},
|
|
8930
8933
|
...opts.domain !== void 0 ? { domain: opts.domain } : {},
|
|
8931
8934
|
...opts.author !== void 0 ? { author: opts.author } : {}
|
|
8932
8935
|
};
|
|
8936
|
+
if (opts.type !== void 0) updated.push("type");
|
|
8933
8937
|
if (opts.tags !== void 0) updated.push("tags");
|
|
8934
8938
|
if (opts.domain !== void 0) updated.push("domain");
|
|
8935
8939
|
if (opts.author !== void 0) updated.push("author");
|
|
8936
|
-
let newBody
|
|
8940
|
+
let newBody;
|
|
8941
|
+
if (opts.bodyFile !== void 0) {
|
|
8942
|
+
if (!existsSync37(opts.bodyFile)) {
|
|
8943
|
+
ui.error(`--body-file not found: ${opts.bodyFile}`);
|
|
8944
|
+
process.exitCode = 1;
|
|
8945
|
+
return;
|
|
8946
|
+
}
|
|
8947
|
+
newBody = await readFile11(opts.bodyFile, "utf8");
|
|
8948
|
+
updated.push("body");
|
|
8949
|
+
} else if (opts.body !== void 0) {
|
|
8950
|
+
newBody = opts.body;
|
|
8951
|
+
updated.push("body");
|
|
8952
|
+
} else {
|
|
8953
|
+
newBody = body;
|
|
8954
|
+
}
|
|
8937
8955
|
if (opts.title !== void 0) {
|
|
8938
8956
|
newBody = replaceFirstHeading(newBody, opts.title);
|
|
8939
8957
|
updated.push("title");
|
|
8940
8958
|
}
|
|
8941
|
-
if (opts.body !== void 0) updated.push("body");
|
|
8942
8959
|
if (updated.length === 0) {
|
|
8943
8960
|
ui.warn("Nothing to update \u2014 provide at least one option.");
|
|
8944
8961
|
return;
|
|
@@ -9032,7 +9049,7 @@ function registerMemoryAutoPromote(memory2) {
|
|
|
9032
9049
|
// src/commands/memory-edit.ts
|
|
9033
9050
|
import { spawn as spawn3 } from "child_process";
|
|
9034
9051
|
import { existsSync as existsSync39 } from "fs";
|
|
9035
|
-
import { readFile as
|
|
9052
|
+
import { readFile as readFile12 } from "fs/promises";
|
|
9036
9053
|
import path23 from "path";
|
|
9037
9054
|
import "commander";
|
|
9038
9055
|
import {
|
|
@@ -9063,7 +9080,7 @@ function registerMemoryEdit(memory2) {
|
|
|
9063
9080
|
ui.warn(`Editor exited with status ${code}.`);
|
|
9064
9081
|
}
|
|
9065
9082
|
try {
|
|
9066
|
-
const fresh = await
|
|
9083
|
+
const fresh = await readFile12(found.filePath, "utf8");
|
|
9067
9084
|
parseMemory(fresh);
|
|
9068
9085
|
ui.success("Memory still parses cleanly.");
|
|
9069
9086
|
} catch (err) {
|
|
@@ -9289,7 +9306,7 @@ function registerMemoryTried(memory2) {
|
|
|
9289
9306
|
--instead "use static import in the entry file" \\\\
|
|
9290
9307
|
--paths packages/cli/src/index.ts
|
|
9291
9308
|
`
|
|
9292
|
-
).requiredOption("--what <text>", "what approach was tried (short, descriptive title)").requiredOption("--why-failed <text>", "why it failed or should NOT be used (include the exact error if possible)").option("--instead <text>", "the correct approach to use instead").option("--scope <scope>", "personal | team | module
|
|
9309
|
+
).requiredOption("--what <text>", "what approach was tried (short, descriptive title)").requiredOption("--why-failed <text>", "why it failed or should NOT be used (include the exact error if possible)").option("--instead <text>", "the correct approach to use instead").option("--scope <scope>", "personal | team | module", "personal").option("--module <name>", "module name (required when scope=module)").option("--tags <csv>", "comma-separated tags").option("--paths <csv>", "anchor paths, comma-separated").option("--author <author>", "author email or handle").option("-d, --dir <dir>", "project root").action(async (opts) => {
|
|
9293
9310
|
const root = findProjectRoot22(opts.dir);
|
|
9294
9311
|
const paths = resolveHaivePaths19(root);
|
|
9295
9312
|
if (!existsSync43(paths.haiveDir)) {
|
|
@@ -9342,7 +9359,7 @@ import {
|
|
|
9342
9359
|
resolveHaivePaths as resolveHaivePaths20
|
|
9343
9360
|
} from "@hiveai/core";
|
|
9344
9361
|
function registerMemoryPending(memory2) {
|
|
9345
|
-
memory2.command("pending").description("List
|
|
9362
|
+
memory2.command("pending").description("List draft and proposed memories awaiting review (sorted by reads desc).\n\n draft = created but not yet activated \xB7 proposed = promoted, awaiting team validation").option("--scope <scope>", "filter by scope (personal | team | module)").option("-d, --dir <dir>", "project root").action(async (opts) => {
|
|
9346
9363
|
const root = findProjectRoot23(opts.dir);
|
|
9347
9364
|
const paths = resolveHaivePaths20(root);
|
|
9348
9365
|
if (!existsSync44(paths.memoriesDir)) {
|
|
@@ -9352,30 +9369,53 @@ function registerMemoryPending(memory2) {
|
|
|
9352
9369
|
}
|
|
9353
9370
|
const all = await loadMemoriesFromDir26(paths.memoriesDir);
|
|
9354
9371
|
const usage = await loadUsageIndex17(paths);
|
|
9355
|
-
const
|
|
9356
|
-
if (mem.frontmatter.status !== "proposed") return false;
|
|
9372
|
+
const filterFn = ({ memory: mem }) => {
|
|
9373
|
+
if (mem.frontmatter.status !== "proposed" && mem.frontmatter.status !== "draft") return false;
|
|
9357
9374
|
if (opts.scope && mem.frontmatter.scope !== opts.scope) return false;
|
|
9358
9375
|
return true;
|
|
9359
|
-
}
|
|
9360
|
-
|
|
9361
|
-
|
|
9376
|
+
};
|
|
9377
|
+
const pending = all.filter(filterFn);
|
|
9378
|
+
if (pending.length === 0) {
|
|
9379
|
+
ui.info("No draft or proposed memories awaiting review.");
|
|
9380
|
+
ui.info("Drafts are created by `haive memory add` without `--status validated`.");
|
|
9362
9381
|
return;
|
|
9363
9382
|
}
|
|
9364
|
-
|
|
9383
|
+
pending.sort(
|
|
9365
9384
|
(a, b) => getUsage15(usage, b.memory.frontmatter.id).read_count - getUsage15(usage, a.memory.frontmatter.id).read_count
|
|
9366
9385
|
);
|
|
9367
9386
|
const now = Date.now();
|
|
9368
|
-
|
|
9369
|
-
|
|
9370
|
-
|
|
9371
|
-
|
|
9372
|
-
const
|
|
9373
|
-
|
|
9374
|
-
|
|
9375
|
-
|
|
9376
|
-
|
|
9387
|
+
const drafts = pending.filter((m) => m.memory.frontmatter.status === "draft");
|
|
9388
|
+
const proposed = pending.filter((m) => m.memory.frontmatter.status === "proposed");
|
|
9389
|
+
if (proposed.length > 0) {
|
|
9390
|
+
console.log(ui.bold(`Proposed (${proposed.length}) \u2014 awaiting team validation`));
|
|
9391
|
+
for (const { memory: mem, filePath } of proposed) {
|
|
9392
|
+
const fm = mem.frontmatter;
|
|
9393
|
+
const u = getUsage15(usage, fm.id);
|
|
9394
|
+
const ageDays = Math.floor((now - new Date(fm.created_at).getTime()) / 864e5);
|
|
9395
|
+
const ageStr = ageDays === 0 ? "today" : `${ageDays}d`;
|
|
9396
|
+
console.log(
|
|
9397
|
+
` ${ui.bold(fm.id)} ${ui.dim(`${fm.scope}/${fm.type}`)} ${ui.dim(`age=${ageStr} reads=${u.read_count}`)}`
|
|
9398
|
+
);
|
|
9399
|
+
console.log(` ${ui.dim(path27.relative(root, filePath))}`);
|
|
9400
|
+
}
|
|
9401
|
+
if (proposed.length > 0) console.log(ui.dim(` \u2192 haive memory approve <id> or haive memory auto-promote`));
|
|
9402
|
+
console.log();
|
|
9403
|
+
}
|
|
9404
|
+
if (drafts.length > 0) {
|
|
9405
|
+
console.log(ui.bold(`Draft (${drafts.length}) \u2014 created but not yet activated`));
|
|
9406
|
+
for (const { memory: mem, filePath } of drafts) {
|
|
9407
|
+
const fm = mem.frontmatter;
|
|
9408
|
+
const u = getUsage15(usage, fm.id);
|
|
9409
|
+
const ageDays = Math.floor((now - new Date(fm.created_at).getTime()) / 864e5);
|
|
9410
|
+
const ageStr = ageDays === 0 ? "today" : `${ageDays}d`;
|
|
9411
|
+
console.log(
|
|
9412
|
+
` ${ui.bold(fm.id)} ${ui.dim(`${fm.scope}/${fm.type}`)} ${ui.dim(`age=${ageStr} reads=${u.read_count}`)}`
|
|
9413
|
+
);
|
|
9414
|
+
console.log(` ${ui.dim(path27.relative(root, filePath))}`);
|
|
9415
|
+
}
|
|
9416
|
+
console.log(ui.dim(` \u2192 haive memory approve <id> (activate) | haive memory promote <id> (share with team)`));
|
|
9377
9417
|
}
|
|
9378
|
-
ui.info(`${proposed.length}
|
|
9418
|
+
ui.info(`${pending.length} total pending (${proposed.length} proposed \xB7 ${drafts.length} draft)`);
|
|
9379
9419
|
});
|
|
9380
9420
|
}
|
|
9381
9421
|
|
|
@@ -9558,7 +9598,7 @@ function registerMemoryRm(memory2) {
|
|
|
9558
9598
|
|
|
9559
9599
|
// src/commands/memory-show.ts
|
|
9560
9600
|
import { existsSync as existsSync48 } from "fs";
|
|
9561
|
-
import { readFile as
|
|
9601
|
+
import { readFile as readFile13 } from "fs/promises";
|
|
9562
9602
|
import path30 from "path";
|
|
9563
9603
|
import "commander";
|
|
9564
9604
|
import {
|
|
@@ -9585,7 +9625,7 @@ function registerMemoryShow(memory2) {
|
|
|
9585
9625
|
return;
|
|
9586
9626
|
}
|
|
9587
9627
|
if (opts.raw) {
|
|
9588
|
-
console.log(await
|
|
9628
|
+
console.log(await readFile13(found.filePath, "utf8"));
|
|
9589
9629
|
return;
|
|
9590
9630
|
}
|
|
9591
9631
|
const fm = found.memory.frontmatter;
|
|
@@ -9763,7 +9803,7 @@ function applyVerification2(mem, result) {
|
|
|
9763
9803
|
}
|
|
9764
9804
|
|
|
9765
9805
|
// src/commands/memory-import.ts
|
|
9766
|
-
import { readFile as
|
|
9806
|
+
import { readFile as readFile14 } from "fs/promises";
|
|
9767
9807
|
import { existsSync as existsSync51 } from "fs";
|
|
9768
9808
|
import "commander";
|
|
9769
9809
|
import {
|
|
@@ -9786,7 +9826,7 @@ function registerMemoryImport(memory2) {
|
|
|
9786
9826
|
process.exitCode = 1;
|
|
9787
9827
|
return;
|
|
9788
9828
|
}
|
|
9789
|
-
const content = await
|
|
9829
|
+
const content = await readFile14(opts.from, "utf8");
|
|
9790
9830
|
const scope = opts.scope ?? "team";
|
|
9791
9831
|
ui.info(`Preparing import from: ${opts.from} (scope=${scope})`);
|
|
9792
9832
|
ui.info(`Content length: ${content.length} chars`);
|
|
@@ -9815,7 +9855,7 @@ function registerMemoryImport(memory2) {
|
|
|
9815
9855
|
|
|
9816
9856
|
// src/commands/memory-import-changelog.ts
|
|
9817
9857
|
import { existsSync as existsSync53 } from "fs";
|
|
9818
|
-
import { readFile as
|
|
9858
|
+
import { readFile as readFile15, mkdir as mkdir14, writeFile as writeFile25 } from "fs/promises";
|
|
9819
9859
|
import path34 from "path";
|
|
9820
9860
|
import "commander";
|
|
9821
9861
|
import {
|
|
@@ -9894,7 +9934,7 @@ function registerMemoryImportChangelog(memory2) {
|
|
|
9894
9934
|
process.exitCode = 1;
|
|
9895
9935
|
return;
|
|
9896
9936
|
}
|
|
9897
|
-
const content = await
|
|
9937
|
+
const content = await readFile15(changelogPath, "utf8");
|
|
9898
9938
|
let entries = parseChangelog(content);
|
|
9899
9939
|
if (entries.length === 0) {
|
|
9900
9940
|
ui.warn("No breaking changes, deprecations, or removals found in the CHANGELOG.");
|
|
@@ -10083,7 +10123,7 @@ function registerMemoryDigest(program2) {
|
|
|
10083
10123
|
}
|
|
10084
10124
|
|
|
10085
10125
|
// src/commands/session-end.ts
|
|
10086
|
-
import { writeFile as writeFile27, mkdir as mkdir15, readFile as
|
|
10126
|
+
import { writeFile as writeFile27, mkdir as mkdir15, readFile as readFile16, rm as rm2 } from "fs/promises";
|
|
10087
10127
|
import { existsSync as existsSync55 } from "fs";
|
|
10088
10128
|
import path36 from "path";
|
|
10089
10129
|
import "commander";
|
|
@@ -10098,7 +10138,7 @@ import {
|
|
|
10098
10138
|
async function buildAutoRecap(paths) {
|
|
10099
10139
|
const obsFile = path36.join(paths.haiveDir, ".cache", "observations.jsonl");
|
|
10100
10140
|
if (!existsSync55(obsFile)) return null;
|
|
10101
|
-
const raw = await
|
|
10141
|
+
const raw = await readFile16(obsFile, "utf8").catch(() => "");
|
|
10102
10142
|
if (!raw.trim()) return null;
|
|
10103
10143
|
const lines = raw.split("\n").filter(Boolean);
|
|
10104
10144
|
const obs = [];
|
|
@@ -10443,7 +10483,7 @@ function detectFormat(filePath) {
|
|
|
10443
10483
|
|
|
10444
10484
|
// src/commands/hub.ts
|
|
10445
10485
|
import { existsSync as existsSync57 } from "fs";
|
|
10446
|
-
import { mkdir as mkdir16, readFile as
|
|
10486
|
+
import { mkdir as mkdir16, readFile as readFile17, writeFile as writeFile28, copyFile } from "fs/promises";
|
|
10447
10487
|
import path38 from "path";
|
|
10448
10488
|
import { spawnSync as spawnSync5 } from "child_process";
|
|
10449
10489
|
import "commander";
|
|
@@ -10638,7 +10678,7 @@ Next steps:
|
|
|
10638
10678
|
for (const file of sourceFiles) {
|
|
10639
10679
|
const srcPath = path38.join(sourceDir, file);
|
|
10640
10680
|
const destPath = path38.join(destDir, file);
|
|
10641
|
-
const fileContent = await
|
|
10681
|
+
const fileContent = await readFile17(srcPath, "utf8");
|
|
10642
10682
|
const alreadyTagged = fileContent.includes(`cross-repo:${sourceName}`);
|
|
10643
10683
|
if (!alreadyTagged) {
|
|
10644
10684
|
await copyFile(srcPath, destPath);
|
|
@@ -10690,7 +10730,7 @@ Next steps:
|
|
|
10690
10730
|
if (outgoing.length > 0) {
|
|
10691
10731
|
console.log(ui.dim(" Run `haive hub push` to publish them to the hub."));
|
|
10692
10732
|
}
|
|
10693
|
-
void
|
|
10733
|
+
void readFile17;
|
|
10694
10734
|
void writeFile28;
|
|
10695
10735
|
void saveConfig3;
|
|
10696
10736
|
});
|
|
@@ -10997,7 +11037,7 @@ function summarize(name, t0, payload, notes) {
|
|
|
10997
11037
|
|
|
10998
11038
|
// src/commands/benchmark.ts
|
|
10999
11039
|
import { existsSync as existsSync59 } from "fs";
|
|
11000
|
-
import { readdir as readdir5, readFile as
|
|
11040
|
+
import { readdir as readdir5, readFile as readFile18, writeFile as writeFile30 } from "fs/promises";
|
|
11001
11041
|
import path40 from "path";
|
|
11002
11042
|
import "commander";
|
|
11003
11043
|
import { estimateTokens as estimateTokens4, findProjectRoot as findProjectRoot38 } from "@hiveai/core";
|
|
@@ -11052,7 +11092,7 @@ async function collectRows(root) {
|
|
|
11052
11092
|
const fixtureDir = path40.join(root, entry.name);
|
|
11053
11093
|
const reportFile = path40.join(fixtureDir, "BENCHMARK_AGENT_REPORT.md");
|
|
11054
11094
|
if (!existsSync59(reportFile)) continue;
|
|
11055
|
-
const report = await
|
|
11095
|
+
const report = await readFile18(reportFile, "utf8");
|
|
11056
11096
|
rows.push(parseAgentReport(entry.name, report));
|
|
11057
11097
|
}
|
|
11058
11098
|
return rows.sort((a, b) => a.fixture.localeCompare(b.fixture));
|
|
@@ -11463,7 +11503,7 @@ function parseDays(input) {
|
|
|
11463
11503
|
|
|
11464
11504
|
// src/commands/doctor.ts
|
|
11465
11505
|
import { existsSync as existsSync63 } from "fs";
|
|
11466
|
-
import { readFile as
|
|
11506
|
+
import { readFile as readFile19, stat } from "fs/promises";
|
|
11467
11507
|
import path44 from "path";
|
|
11468
11508
|
import { execFileSync, execSync as execSync3 } from "child_process";
|
|
11469
11509
|
import "commander";
|
|
@@ -11516,8 +11556,8 @@ function registerDoctor(program2) {
|
|
|
11516
11556
|
fix: "haive init"
|
|
11517
11557
|
});
|
|
11518
11558
|
} else {
|
|
11519
|
-
const { readFile:
|
|
11520
|
-
const content = await
|
|
11559
|
+
const { readFile: readFile21 } = await import("fs/promises");
|
|
11560
|
+
const content = await readFile21(paths.projectContext, "utf8");
|
|
11521
11561
|
const isTemplate = content.includes("TODO \u2014 high-level overview") || content.includes("Generated by `haive init`");
|
|
11522
11562
|
if (isTemplate) {
|
|
11523
11563
|
findings.push({
|
|
@@ -11666,8 +11706,8 @@ function registerDoctor(program2) {
|
|
|
11666
11706
|
let hasClaudeEnforcement = false;
|
|
11667
11707
|
if (existsSync63(claudeSettings)) {
|
|
11668
11708
|
try {
|
|
11669
|
-
const { readFile:
|
|
11670
|
-
const raw = await
|
|
11709
|
+
const { readFile: readFile21 } = await import("fs/promises");
|
|
11710
|
+
const raw = await readFile21(claudeSettings, "utf8");
|
|
11671
11711
|
hasClaudeEnforcement = raw.includes("haive enforce session-start") && raw.includes("haive enforce pre-tool-use");
|
|
11672
11712
|
} catch {
|
|
11673
11713
|
hasClaudeEnforcement = false;
|
|
@@ -11690,14 +11730,14 @@ function registerDoctor(program2) {
|
|
|
11690
11730
|
fix: "Edit .ai/haive.config.json: set autoSessionEnd: true (or re-run `haive init` without --manual)."
|
|
11691
11731
|
});
|
|
11692
11732
|
}
|
|
11693
|
-
findings.push(...await collectInstallFindings(root, "0.9.
|
|
11733
|
+
findings.push(...await collectInstallFindings(root, "0.9.21"));
|
|
11694
11734
|
try {
|
|
11695
11735
|
const legacyRaw = execSync3("haive-mcp --version", {
|
|
11696
11736
|
encoding: "utf8",
|
|
11697
11737
|
timeout: 3e3,
|
|
11698
11738
|
stdio: ["ignore", "pipe", "ignore"]
|
|
11699
11739
|
}).trim();
|
|
11700
|
-
const cliVersion = "0.9.
|
|
11740
|
+
const cliVersion = "0.9.21";
|
|
11701
11741
|
if (legacyRaw && legacyRaw !== cliVersion) {
|
|
11702
11742
|
findings.push({
|
|
11703
11743
|
severity: "warn",
|
|
@@ -11960,7 +12000,7 @@ which -a haive`
|
|
|
11960
12000
|
for (const rel of integrationFiles) {
|
|
11961
12001
|
const file = path44.join(root, rel);
|
|
11962
12002
|
if (!existsSync63(file)) continue;
|
|
11963
|
-
const text = await
|
|
12003
|
+
const text = await readFile19(file, "utf8").catch(() => "");
|
|
11964
12004
|
for (const bin of extractAbsoluteHaiveBins(text)) {
|
|
11965
12005
|
const version = versionForBinary(bin);
|
|
11966
12006
|
if (!version) {
|
|
@@ -12494,7 +12534,7 @@ function registerMemoryConflictCandidates(memory2) {
|
|
|
12494
12534
|
// src/commands/enforce.ts
|
|
12495
12535
|
import { execFileSync as execFileSync2, spawn as spawn5 } from "child_process";
|
|
12496
12536
|
import { existsSync as existsSync69 } from "fs";
|
|
12497
|
-
import { chmod as chmod2, mkdir as mkdir19, readFile as
|
|
12537
|
+
import { chmod as chmod2, mkdir as mkdir19, readFile as readFile20, rm as rm3, writeFile as writeFile34 } from "fs/promises";
|
|
12498
12538
|
import path49 from "path";
|
|
12499
12539
|
import "commander";
|
|
12500
12540
|
import {
|
|
@@ -12800,7 +12840,7 @@ async function buildEnforcementReport(dir, stage, sessionId) {
|
|
|
12800
12840
|
findings: [{ severity: "info", code: "enforcement-off", message: "hAIve enforcement is disabled." }]
|
|
12801
12841
|
});
|
|
12802
12842
|
}
|
|
12803
|
-
findings.push(...await inspectIntegrationVersions(root, "0.9.
|
|
12843
|
+
findings.push(...await inspectIntegrationVersions(root, "0.9.21"));
|
|
12804
12844
|
if (config.enforcement?.requireBriefingFirst !== false && stage !== "ci") {
|
|
12805
12845
|
const hasBriefing = await hasRecentBriefingMarker(paths, sessionId);
|
|
12806
12846
|
findings.push(hasBriefing ? { severity: "ok", code: "briefing-loaded", message: "A recent hAIve briefing marker exists." } : {
|
|
@@ -13012,7 +13052,7 @@ async function inspectIntegrationVersions(root, expectedVersion) {
|
|
|
13012
13052
|
for (const rel of files) {
|
|
13013
13053
|
const file = path49.join(root, rel);
|
|
13014
13054
|
if (!existsSync69(file)) continue;
|
|
13015
|
-
const text = await
|
|
13055
|
+
const text = await readFile20(file, "utf8").catch(() => "");
|
|
13016
13056
|
for (const bin of extractAbsoluteHaiveBins2(text)) {
|
|
13017
13057
|
const version = versionForBinary2(bin);
|
|
13018
13058
|
if (!version) {
|
|
@@ -13125,7 +13165,7 @@ haive enforce check --stage pre-push --dir . || exit $?
|
|
|
13125
13165
|
for (const hook of hooks) {
|
|
13126
13166
|
const file = path49.join(hooksDir, hook.name);
|
|
13127
13167
|
if (existsSync69(file)) {
|
|
13128
|
-
const current = await
|
|
13168
|
+
const current = await readFile20(file, "utf8").catch(() => "");
|
|
13129
13169
|
if (current.includes(ENFORCE_HOOK_MARKER)) {
|
|
13130
13170
|
await writeFile34(file, hook.body, "utf8");
|
|
13131
13171
|
} else {
|
|
@@ -13288,7 +13328,7 @@ function registerRun(program2) {
|
|
|
13288
13328
|
|
|
13289
13329
|
// src/index.ts
|
|
13290
13330
|
var program = new Command51();
|
|
13291
|
-
program.name("haive").description("hAIve \u2014 the memory and enforcement layer of your agent harness").version("0.9.
|
|
13331
|
+
program.name("haive").description("hAIve \u2014 the memory and enforcement layer of your agent harness").version("0.9.21").option("--advanced", "show maintenance and experimental commands in help");
|
|
13292
13332
|
registerInit(program);
|
|
13293
13333
|
registerWelcome(program);
|
|
13294
13334
|
registerResolveProject(program);
|
|
@@ -13331,7 +13371,9 @@ registerMemoryTimeline(memory);
|
|
|
13331
13371
|
registerMemoryConflictCandidates(memory);
|
|
13332
13372
|
registerMemoryArchive(memory);
|
|
13333
13373
|
registerMemoryLint(memory);
|
|
13334
|
-
var session = program.command("session").description(
|
|
13374
|
+
var session = program.command("session").description(
|
|
13375
|
+
"Manage session lifecycle.\n\n Session start is automatic \u2014 hAIve loads context via `get_briefing` at the start\n of each agent session (Claude Code SessionStart hook or MCP first call).\n Use `haive session end` to save a rich end-of-session recap for the next session."
|
|
13376
|
+
);
|
|
13335
13377
|
registerSessionEnd(session);
|
|
13336
13378
|
registerSnapshot(program);
|
|
13337
13379
|
registerHub(program);
|
|
@@ -13344,6 +13386,7 @@ registerPrecommit(program);
|
|
|
13344
13386
|
var CORE_ROOT_COMMANDS = /* @__PURE__ */ new Set([
|
|
13345
13387
|
"init",
|
|
13346
13388
|
"doctor",
|
|
13389
|
+
"tui",
|
|
13347
13390
|
"agent",
|
|
13348
13391
|
"enforce",
|
|
13349
13392
|
"run",
|