@hiveai/cli 0.9.31 → 0.10.1
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 +103 -34
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -249,11 +249,13 @@ import "commander";
|
|
|
249
249
|
import {
|
|
250
250
|
findProjectRoot,
|
|
251
251
|
getUsage,
|
|
252
|
+
retirementSignal,
|
|
252
253
|
loadCodeMap,
|
|
253
254
|
loadMemoriesFromDir,
|
|
254
255
|
loadUsageIndex,
|
|
255
256
|
resolveHaivePaths,
|
|
256
|
-
serializeMemory
|
|
257
|
+
serializeMemory,
|
|
258
|
+
specificityScore
|
|
257
259
|
} from "@hiveai/core";
|
|
258
260
|
async function lintMemoriesAsync(root, options = {}) {
|
|
259
261
|
const paths = resolveHaivePaths(root);
|
|
@@ -271,6 +273,16 @@ async function lintMemoriesAsync(root, options = {}) {
|
|
|
271
273
|
if (fm.type === "session_recap") continue;
|
|
272
274
|
const body = memory2.body.trim();
|
|
273
275
|
const naked = body.replace(/^#.*$/gm, "").replace(/```[\s\S]*?```/g, "").trim();
|
|
276
|
+
const retired = retirementSignal(fm, memory2.body);
|
|
277
|
+
if (retired.retired && fm.status !== "deprecated" && fm.status !== "rejected" && fm.status !== "stale") {
|
|
278
|
+
out.push({
|
|
279
|
+
file: filePath,
|
|
280
|
+
id: fm.id,
|
|
281
|
+
severity: "warn",
|
|
282
|
+
code: "RETIRED_ACTIVE_MEMORY",
|
|
283
|
+
message: `Record is still active but lifecycle metadata says it should be retired (${retired.reason}). Mark it deprecated or remove the fixed/superseded marker if it still applies.`
|
|
284
|
+
});
|
|
285
|
+
}
|
|
274
286
|
if (naked.length < 40 && fm.status !== "rejected") {
|
|
275
287
|
out.push({
|
|
276
288
|
file: filePath,
|
|
@@ -289,6 +301,15 @@ async function lintMemoriesAsync(root, options = {}) {
|
|
|
289
301
|
message: "Record does not contain obvious action/rationale words. Add the concrete rule, why it exists, and what to do instead."
|
|
290
302
|
});
|
|
291
303
|
}
|
|
304
|
+
if (["decision", "gotcha", "convention", "architecture"].includes(fm.type) && fm.status !== "rejected" && naked.length >= 40 && specificityScore(naked) < 0.2) {
|
|
305
|
+
out.push({
|
|
306
|
+
file: filePath,
|
|
307
|
+
id: fm.id,
|
|
308
|
+
severity: "info",
|
|
309
|
+
code: "LOW_VALUE_GUESSABLE",
|
|
310
|
+
message: "Reads like generic best practice a capable model already follows. hAIve's value is UNGUESSABLE team knowledge \u2014 add the concrete, arbitrary specifics (exact names, values, formats, magic numbers) or consider removing it to keep briefings high-signal."
|
|
311
|
+
});
|
|
312
|
+
}
|
|
292
313
|
const suggestedAnchors = suggestAnchors(root, { filePath, memory: memory2 }, codeMap, trackedFiles);
|
|
293
314
|
if (ANCHOR_TYPES.has(fm.type) && fm.anchor.paths.length === 0 && fm.status === "validated") {
|
|
294
315
|
out.push({
|
|
@@ -935,12 +956,10 @@ function registerBriefing(program2) {
|
|
|
935
956
|
if (existsSync3(paths.projectContext) && !stopped()) {
|
|
936
957
|
const ctx = await readFile2(paths.projectContext, "utf8");
|
|
937
958
|
const isTemplate = ctx.includes("TODO \u2014 high-level overview") || ctx.includes("Generated by `haive init`");
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
"project-context.md still contains the default template \u2014 get_briefing will return little value."
|
|
941
|
-
);
|
|
959
|
+
const bootstrapUnfilled = /Auto-generated by `haive init/i.test(ctx) && (ctx.match(/TODO —/g)?.length ?? 0) >= 2;
|
|
960
|
+
if (isTemplate || bootstrapUnfilled) {
|
|
942
961
|
ui.warn(
|
|
943
|
-
"
|
|
962
|
+
"project-context.md is still auto-generated/unfilled \u2014 skipping it (low value). Fill it in, or invoke the bootstrap_project MCP prompt for real context."
|
|
944
963
|
);
|
|
945
964
|
out("");
|
|
946
965
|
} else {
|
|
@@ -3701,6 +3720,7 @@ import { existsSync as existsSync15 } from "fs";
|
|
|
3701
3720
|
import path62 from "path";
|
|
3702
3721
|
import {
|
|
3703
3722
|
buildFrontmatter as buildFrontmatter3,
|
|
3723
|
+
isLikelyGuessable,
|
|
3704
3724
|
memoryFilePath as memoryFilePath3,
|
|
3705
3725
|
serializeMemory as serializeMemory7
|
|
3706
3726
|
} from "@hiveai/core";
|
|
@@ -3736,6 +3756,7 @@ import {
|
|
|
3736
3756
|
getUsage as getUsage5,
|
|
3737
3757
|
inferModulesFromPaths as inferModulesFromPaths2,
|
|
3738
3758
|
isGlobPath,
|
|
3759
|
+
isRetiredMemory,
|
|
3739
3760
|
isAutoPromoteEligible,
|
|
3740
3761
|
isDecaying,
|
|
3741
3762
|
isStackPackSeed as isStackPackSeed2,
|
|
@@ -3750,6 +3771,8 @@ import {
|
|
|
3750
3771
|
queryCodeMap as queryCodeMap2,
|
|
3751
3772
|
resolveBriefingBudget as resolveBriefingBudget2,
|
|
3752
3773
|
serializeMemory as serializeMemory9,
|
|
3774
|
+
specificityScore as specificityScore2,
|
|
3775
|
+
GUESSABLE_THRESHOLD,
|
|
3753
3776
|
tokenizeQuery as tokenizeQuery22,
|
|
3754
3777
|
trackReads as trackReads3,
|
|
3755
3778
|
truncateToTokens,
|
|
@@ -3782,6 +3805,7 @@ import { existsSync as existsSync222 } from "fs";
|
|
|
3782
3805
|
import {
|
|
3783
3806
|
deriveConfidence as deriveConfidence6,
|
|
3784
3807
|
getUsage as getUsage7,
|
|
3808
|
+
isRetiredMemory as isRetiredMemory2,
|
|
3785
3809
|
loadMemoriesFromDir as loadMemoriesFromDir17,
|
|
3786
3810
|
loadUsageIndex as loadUsageIndex9,
|
|
3787
3811
|
literalMatchesAnyToken as literalMatchesAnyToken3,
|
|
@@ -4780,12 +4804,25 @@ var MemObserveInputSchema = {
|
|
|
4780
4804
|
scope: z15.enum(["personal", "team", "module"]).default("team").describe("Visibility scope \u2014 defaults to team since discoveries benefit everyone"),
|
|
4781
4805
|
module: z15.string().optional().describe("Module name (required when scope=module)"),
|
|
4782
4806
|
tags: z15.array(z15.string()).default([]).describe("Tags for filtering"),
|
|
4783
|
-
author: z15.string().optional().describe("Author handle or email")
|
|
4807
|
+
author: z15.string().optional().describe("Author handle or email"),
|
|
4808
|
+
force: z15.boolean().default(false).describe(
|
|
4809
|
+
"Save even if the observation looks like generic, guessable knowledge. By default, low-specificity observations (things a capable model already knows) are SKIPPED to keep the corpus high-signal \u2014 only unguessable, team-specific discoveries are worth storing."
|
|
4810
|
+
)
|
|
4784
4811
|
};
|
|
4785
4812
|
async function memObserve(input, ctx) {
|
|
4786
4813
|
if (!existsSync15(ctx.paths.haiveDir)) {
|
|
4787
4814
|
throw new Error(`No .ai/ directory at ${ctx.paths.root}. Run 'haive init' first.`);
|
|
4788
4815
|
}
|
|
4816
|
+
const signalText = [input.what, input.impact, input.fix ?? ""].join(" ");
|
|
4817
|
+
if (!input.force && isLikelyGuessable(signalText)) {
|
|
4818
|
+
return {
|
|
4819
|
+
id: "",
|
|
4820
|
+
scope: input.scope,
|
|
4821
|
+
file_path: "",
|
|
4822
|
+
skipped: true,
|
|
4823
|
+
reason: "Observation looks like generic, guessable knowledge (low specificity) \u2014 not saved. Capture only arbitrary, team-specific facts (exact names, values, formats). Pass force=true to override."
|
|
4824
|
+
};
|
|
4825
|
+
}
|
|
4789
4826
|
const slug = input.what.toLowerCase().replace(/[^a-z0-9\s]/g, "").trim().split(/\s+/).slice(0, 6).join("-");
|
|
4790
4827
|
const anchorPaths = input.where.split(/[,\n]/).map((s) => s.trim()).filter(Boolean);
|
|
4791
4828
|
const baseFm = buildFrontmatter3({
|
|
@@ -5117,6 +5154,7 @@ async function getBriefing(input, ctx) {
|
|
|
5117
5154
|
const s = memory2.frontmatter.status;
|
|
5118
5155
|
if (s === "rejected" || s === "deprecated") return false;
|
|
5119
5156
|
if (!input.include_stale && s === "stale") return false;
|
|
5157
|
+
if (!input.include_stale && isRetiredMemory(memory2.frontmatter, memory2.body)) return false;
|
|
5120
5158
|
if (memory2.frontmatter.type === "session_recap") return false;
|
|
5121
5159
|
return true;
|
|
5122
5160
|
});
|
|
@@ -5472,6 +5510,14 @@ When done, call \`mem_session_end\` to acknowledge \u2014 this clears the pendin
|
|
|
5472
5510
|
const memoriesEmpty = outputMemories.length === 0;
|
|
5473
5511
|
const hasMemoriesDir = existsSync18(ctx.paths.memoriesDir);
|
|
5474
5512
|
const isColdStart = isTemplateContext && memoriesEmpty && !lastSession && !autoContextGenerated;
|
|
5513
|
+
const hasUnguessableSignal = outputMemories.some(
|
|
5514
|
+
(m) => (m.priority === "must_read" || m.priority === "useful") && specificityScore2(m.body) >= GUESSABLE_THRESHOLD
|
|
5515
|
+
);
|
|
5516
|
+
const briefingValueLow = !hasUnguessableSignal;
|
|
5517
|
+
const adaptiveConfig = await loadConfig3(ctx.paths);
|
|
5518
|
+
const bootstrapUnfilled = /Auto-generated by `haive init/i.test(projectContextRaw) && (projectContextRaw.match(/TODO —/g)?.length ?? 0) >= 2;
|
|
5519
|
+
const contextIsInferable = isTemplateContext || autoContextGenerated || bootstrapUnfilled;
|
|
5520
|
+
const adaptiveTrim = adaptiveConfig.adaptiveBriefing !== false && briefingValueLow && contextIsInferable;
|
|
5475
5521
|
const hints = [];
|
|
5476
5522
|
if (isColdStart) {
|
|
5477
5523
|
hints.push(
|
|
@@ -5504,6 +5550,11 @@ When done, call \`mem_session_end\` to acknowledge \u2014 this clears the pendin
|
|
|
5504
5550
|
);
|
|
5505
5551
|
}
|
|
5506
5552
|
}
|
|
5553
|
+
if (adaptiveTrim) {
|
|
5554
|
+
hints.push(
|
|
5555
|
+
"No team-specific policy matched these files/task \u2014 nothing here a capable model can't infer. The auto-generated project context was trimmed to keep this briefing near-zero-cost; proceed with normal Read/Grep."
|
|
5556
|
+
);
|
|
5557
|
+
}
|
|
5507
5558
|
if (existsSync18(ctx.paths.haiveDir)) {
|
|
5508
5559
|
await writeBriefingMarker2(ctx.paths, {
|
|
5509
5560
|
sessionId: process.env.HAIVE_SESSION_ID,
|
|
@@ -5519,7 +5570,12 @@ When done, call \`mem_session_end\` to acknowledge \u2014 this clears the pendin
|
|
|
5519
5570
|
search_mode: searchMode,
|
|
5520
5571
|
inferred_modules: inferred,
|
|
5521
5572
|
...lastSession ? { last_session: lastSession } : {},
|
|
5522
|
-
project_context:
|
|
5573
|
+
project_context: adaptiveTrim ? {
|
|
5574
|
+
content: "(adaptive briefing: auto-generated context omitted \u2014 no team-specific policy matched, so a capable model needs nothing extra here)",
|
|
5575
|
+
truncated: false,
|
|
5576
|
+
...isTemplateContext && !autoContextGenerated ? { is_template: true } : {},
|
|
5577
|
+
...autoContextGenerated ? { auto_generated: true } : {}
|
|
5578
|
+
} : projectContextRaw || autoContextGenerated ? {
|
|
5523
5579
|
content: projectSlice.text,
|
|
5524
5580
|
truncated: projectSlice.truncated,
|
|
5525
5581
|
...isTemplateContext && !autoContextGenerated ? { is_template: true } : {},
|
|
@@ -5533,6 +5589,7 @@ When done, call \`mem_session_end\` to acknowledge \u2014 this clears the pendin
|
|
|
5533
5589
|
decay_warnings: decayWarnings,
|
|
5534
5590
|
setup_warnings: setupWarnings,
|
|
5535
5591
|
...isColdStart ? { low_value: true } : {},
|
|
5592
|
+
briefing_value: briefingValueLow ? "low" : "high",
|
|
5536
5593
|
...hints.length > 0 ? { hints } : {},
|
|
5537
5594
|
estimated_tokens: totalTokens,
|
|
5538
5595
|
budget: {
|
|
@@ -6011,6 +6068,9 @@ var AntiPatternsCheckInputSchema = {
|
|
|
6011
6068
|
limit: z24.number().int().positive().max(20).default(8).describe("Cap on returned warnings."),
|
|
6012
6069
|
semantic: z24.boolean().default(true).describe(
|
|
6013
6070
|
"When true, also use semantic search (requires @hiveai/embeddings + memory index) to find related anti-patterns."
|
|
6071
|
+
),
|
|
6072
|
+
min_semantic_score: z24.number().min(0).max(1).default(0.45).describe(
|
|
6073
|
+
"Minimum cosine score for semantic-only anti-pattern hits. Anchor/literal matches still surface. Default 0.45 keeps broad, weakly-related memories out of review noise."
|
|
6014
6074
|
)
|
|
6015
6075
|
};
|
|
6016
6076
|
var CODE_STOPWORDS = /* @__PURE__ */ new Set([
|
|
@@ -6061,8 +6121,12 @@ var CODE_STOPWORDS = /* @__PURE__ */ new Set([
|
|
|
6061
6121
|
"console"
|
|
6062
6122
|
]);
|
|
6063
6123
|
function tokenizeDiffForLiteral(diff) {
|
|
6064
|
-
const
|
|
6065
|
-
const
|
|
6124
|
+
const lines = diff.split("\n");
|
|
6125
|
+
const looksLikeDiff = lines.some((l) => /^[+-]/.test(l));
|
|
6126
|
+
const addedOnly = looksLikeDiff ? lines.filter((l) => l.startsWith("+") && !l.startsWith("+++")).join("\n") : diff;
|
|
6127
|
+
const source = addedOnly.trim().length > 0 ? addedOnly : diff;
|
|
6128
|
+
const wsTokens = tokenizeQuery3(source);
|
|
6129
|
+
const wordTokens = source.toLowerCase().split(/[^a-z0-9]+/).filter((t) => t.length >= 4 && !CODE_STOPWORDS.has(t));
|
|
6066
6130
|
return [.../* @__PURE__ */ new Set([...wsTokens, ...wordTokens])];
|
|
6067
6131
|
}
|
|
6068
6132
|
async function antiPatternsCheck(input, ctx) {
|
|
@@ -6077,11 +6141,12 @@ async function antiPatternsCheck(input, ctx) {
|
|
|
6077
6141
|
return { scanned: 0, warnings: [], notice: "No .ai/memories directory \u2014 nothing to check against." };
|
|
6078
6142
|
}
|
|
6079
6143
|
const all = await loadMemoriesFromDir17(ctx.paths.memoriesDir);
|
|
6144
|
+
const minSemanticScore = input.min_semantic_score ?? 0.45;
|
|
6080
6145
|
const negative = all.filter(({ memory: memory2 }) => {
|
|
6081
6146
|
const t = memory2.frontmatter.type;
|
|
6082
6147
|
if (t !== "attempt" && t !== "gotcha") return false;
|
|
6083
6148
|
const s = memory2.frontmatter.status;
|
|
6084
|
-
return s !== "rejected" && s !== "deprecated" && s !== "stale";
|
|
6149
|
+
return s !== "rejected" && s !== "deprecated" && s !== "stale" && !isRetiredMemory2(memory2.frontmatter, memory2.body);
|
|
6085
6150
|
});
|
|
6086
6151
|
if (negative.length === 0) {
|
|
6087
6152
|
return { scanned: 0, warnings: [], notice: "No attempt/gotcha memories found yet." };
|
|
@@ -6135,6 +6200,7 @@ async function antiPatternsCheck(input, ctx) {
|
|
|
6135
6200
|
const negativeIds = new Set(negative.map(({ memory: memory2 }) => memory2.frontmatter.id));
|
|
6136
6201
|
for (const hit of result.hits) {
|
|
6137
6202
|
if (!negativeIds.has(hit.id)) continue;
|
|
6203
|
+
if (hit.score < minSemanticScore && !seen.has(hit.id)) continue;
|
|
6138
6204
|
const found = negative.find(({ memory: memory2 }) => memory2.frontmatter.id === hit.id);
|
|
6139
6205
|
if (found) upsert(found.memory.frontmatter, found.memory.body, "semantic", hit.score);
|
|
6140
6206
|
}
|
|
@@ -7323,7 +7389,7 @@ When done, respond with: "Imported N memories: [list of IDs]" or "Nothing action
|
|
|
7323
7389
|
};
|
|
7324
7390
|
}
|
|
7325
7391
|
var SERVER_NAME = "haive";
|
|
7326
|
-
var SERVER_VERSION = "0.
|
|
7392
|
+
var SERVER_VERSION = "0.10.1";
|
|
7327
7393
|
function jsonResult(data) {
|
|
7328
7394
|
return {
|
|
7329
7395
|
content: [
|
|
@@ -7362,7 +7428,6 @@ var MAINTENANCE_PROFILE_TOOLS = [
|
|
|
7362
7428
|
"mem_delete",
|
|
7363
7429
|
"mem_diff",
|
|
7364
7430
|
"get_recap",
|
|
7365
|
-
"code_search",
|
|
7366
7431
|
"anti_patterns_check",
|
|
7367
7432
|
"mem_distill",
|
|
7368
7433
|
"mem_timeline",
|
|
@@ -12043,6 +12108,8 @@ import "commander";
|
|
|
12043
12108
|
import {
|
|
12044
12109
|
findProjectRoot as findProjectRoot41,
|
|
12045
12110
|
getUsage as getUsage18,
|
|
12111
|
+
retirementSignal as retirementSignal2,
|
|
12112
|
+
loadConfig as loadConfig10,
|
|
12046
12113
|
loadMemoriesFromDir as loadMemoriesFromDir31,
|
|
12047
12114
|
loadUsageIndex as loadUsageIndex24,
|
|
12048
12115
|
resolveHaivePaths as resolveHaivePaths37,
|
|
@@ -12052,7 +12119,7 @@ var MS_PER_DAY2 = 24 * 60 * 60 * 1e3;
|
|
|
12052
12119
|
function registerMemoryArchive(memory2) {
|
|
12053
12120
|
memory2.command("archive").description(
|
|
12054
12121
|
"Archive obsolete memories: marks status='deprecated' for memories not read in N days\n whose anchored paths have all disappeared (or have no anchor at all).\n\n Defaults to a DRY RUN \u2014 pass --apply to actually rewrite files.\n Targets `attempt` memories by default since they age the fastest.\n\n Recover later with `haive memory edit <id>` to set status back to validated."
|
|
12055
|
-
).option("--since <window>", "minimum age since last read (e.g. '180d', '6m')
|
|
12122
|
+
).option("--since <window>", "minimum age since last read (e.g. '180d', '6m'). Default: enforcement.decayAfterDays or 180d").option("--type <type>", "limit to a memory type (default 'attempt'). Pass 'all' to scan all types.", "attempt").option("--unread", "decay by unread-age ALONE (ignore anchor status) \u2014 more aggressive corpus hygiene", false).option("--apply", "actually rewrite files (default: dry run)", false).option("--json", "emit JSON instead of human-readable output", false).option("-d, --dir <dir>", "project root").action(async (opts) => {
|
|
12056
12123
|
const root = findProjectRoot41(opts.dir);
|
|
12057
12124
|
const paths = resolveHaivePaths37(root);
|
|
12058
12125
|
if (!existsSync60(paths.memoriesDir)) {
|
|
@@ -12060,7 +12127,9 @@ function registerMemoryArchive(memory2) {
|
|
|
12060
12127
|
process.exitCode = 1;
|
|
12061
12128
|
return;
|
|
12062
12129
|
}
|
|
12063
|
-
const
|
|
12130
|
+
const config = await loadConfig10(paths);
|
|
12131
|
+
const defaultWindow = config.enforcement?.decayAfterDays ? `${config.enforcement.decayAfterDays}d` : "180d";
|
|
12132
|
+
const minDays = parseDays(opts.since ?? defaultWindow);
|
|
12064
12133
|
if (minDays === null) {
|
|
12065
12134
|
ui.error(`Invalid --since value: ${opts.since}. Use formats like '180d', '6m', '1y'.`);
|
|
12066
12135
|
process.exitCode = 1;
|
|
@@ -12074,20 +12143,23 @@ function registerMemoryArchive(memory2) {
|
|
|
12074
12143
|
for (const { memory: mem, filePath } of all) {
|
|
12075
12144
|
const fm = mem.frontmatter;
|
|
12076
12145
|
if (typeFilter && fm.type !== typeFilter) continue;
|
|
12146
|
+
if (fm.type === "session_recap" || fm.requires_human_approval) continue;
|
|
12077
12147
|
if (fm.status === "deprecated" || fm.status === "rejected") continue;
|
|
12148
|
+
const retired = retirementSignal2(fm, mem.body);
|
|
12078
12149
|
const hasAnyAnchor = fm.anchor.paths.length + fm.anchor.symbols.length > 0;
|
|
12079
12150
|
const allPathsGone = fm.anchor.paths.length > 0 && fm.anchor.paths.every((p) => !existsSync60(path44.join(paths.root, p)));
|
|
12080
12151
|
const isAnchorless = !hasAnyAnchor;
|
|
12081
|
-
if (!isAnchorless && !allPathsGone) continue;
|
|
12152
|
+
if (!retired.retired && !opts.unread && !isAnchorless && !allPathsGone) continue;
|
|
12082
12153
|
const u = getUsage18(usage, fm.id);
|
|
12083
12154
|
const lastSeen = u.last_read_at ?? fm.created_at;
|
|
12084
|
-
if (Date.parse(lastSeen) >= cutoff) continue;
|
|
12155
|
+
if (!retired.retired && Date.parse(lastSeen) >= cutoff) continue;
|
|
12156
|
+
const reason = retired.retired ? `retired lifecycle signal: ${retired.reason ?? "unknown"}` : isAnchorless ? `anchorless and not read since ${lastSeen.slice(0, 10)}` : allPathsGone ? `all ${fm.anchor.paths.length} anchored path(s) missing and not read since ${lastSeen.slice(0, 10)}` : `not read since ${lastSeen.slice(0, 10)} (unread decay)`;
|
|
12085
12157
|
candidates.push({
|
|
12086
12158
|
id: fm.id,
|
|
12087
12159
|
type: fm.type,
|
|
12088
12160
|
status: fm.status,
|
|
12089
12161
|
last_seen: lastSeen,
|
|
12090
|
-
reason
|
|
12162
|
+
reason,
|
|
12091
12163
|
filePath
|
|
12092
12164
|
});
|
|
12093
12165
|
}
|
|
@@ -12160,7 +12232,7 @@ import {
|
|
|
12160
12232
|
findProjectRoot as findProjectRoot42,
|
|
12161
12233
|
getUsage as getUsage19,
|
|
12162
12234
|
loadCodeMap as loadCodeMap7,
|
|
12163
|
-
loadConfig as
|
|
12235
|
+
loadConfig as loadConfig11,
|
|
12164
12236
|
loadMemoriesFromDir as loadMemoriesFromDir33,
|
|
12165
12237
|
loadUsageIndex as loadUsageIndex25,
|
|
12166
12238
|
readUsageEvents as readUsageEvents4,
|
|
@@ -12175,7 +12247,7 @@ function registerDoctor(program2) {
|
|
|
12175
12247
|
const paths = resolveHaivePaths38(root);
|
|
12176
12248
|
const findings = [];
|
|
12177
12249
|
const repairs = [];
|
|
12178
|
-
const config = await
|
|
12250
|
+
const config = await loadConfig11(paths);
|
|
12179
12251
|
if (!existsSync61(paths.haiveDir)) {
|
|
12180
12252
|
findings.push({
|
|
12181
12253
|
severity: "error",
|
|
@@ -12395,14 +12467,14 @@ function registerDoctor(program2) {
|
|
|
12395
12467
|
fix: "Edit .ai/haive.config.json: set autoSessionEnd: true (or re-run `haive init` without --manual)."
|
|
12396
12468
|
});
|
|
12397
12469
|
}
|
|
12398
|
-
findings.push(...await collectInstallFindings(root, "0.
|
|
12470
|
+
findings.push(...await collectInstallFindings(root, "0.10.1"));
|
|
12399
12471
|
try {
|
|
12400
12472
|
const legacyRaw = execSync3("haive-mcp --version", {
|
|
12401
12473
|
encoding: "utf8",
|
|
12402
12474
|
timeout: 3e3,
|
|
12403
12475
|
stdio: ["ignore", "pipe", "ignore"]
|
|
12404
12476
|
}).trim();
|
|
12405
|
-
const cliVersion = "0.
|
|
12477
|
+
const cliVersion = "0.10.1";
|
|
12406
12478
|
if (legacyRaw && legacyRaw !== cliVersion) {
|
|
12407
12479
|
findings.push({
|
|
12408
12480
|
severity: "warn",
|
|
@@ -12984,7 +13056,7 @@ import "commander";
|
|
|
12984
13056
|
import {
|
|
12985
13057
|
antiPatternGateParams,
|
|
12986
13058
|
findProjectRoot as findProjectRoot44,
|
|
12987
|
-
loadConfig as
|
|
13059
|
+
loadConfig as loadConfig12,
|
|
12988
13060
|
resolveHaivePaths as resolveHaivePaths40
|
|
12989
13061
|
} from "@hiveai/core";
|
|
12990
13062
|
function registerPrecommit(program2) {
|
|
@@ -13000,7 +13072,7 @@ function registerPrecommit(program2) {
|
|
|
13000
13072
|
const root = findProjectRoot44(opts.dir);
|
|
13001
13073
|
const paths = resolveHaivePaths40(root);
|
|
13002
13074
|
const ctx = { paths };
|
|
13003
|
-
const config = await
|
|
13075
|
+
const config = await loadConfig12(paths);
|
|
13004
13076
|
const gate = config.enforcement?.antiPatternGate ?? "anchored";
|
|
13005
13077
|
const gateParams = antiPatternGateParams(gate);
|
|
13006
13078
|
const blockOn = opts.blockOn ?? gateParams.block_on;
|
|
@@ -13376,7 +13448,7 @@ import {
|
|
|
13376
13448
|
findProjectRoot as findProjectRoot49,
|
|
13377
13449
|
hasRecentBriefingMarker,
|
|
13378
13450
|
isFreshIsoDate,
|
|
13379
|
-
loadConfig as
|
|
13451
|
+
loadConfig as loadConfig13,
|
|
13380
13452
|
loadMemoriesFromDir as loadMemoriesFromDir36,
|
|
13381
13453
|
memoryMatchesAnchorPaths as memoryMatchesAnchorPaths6,
|
|
13382
13454
|
readRecentBriefingMarker,
|
|
@@ -13397,7 +13469,7 @@ function registerEnforce(program2) {
|
|
|
13397
13469
|
const root = findProjectRoot49(opts.dir);
|
|
13398
13470
|
const paths = resolveHaivePaths45(root);
|
|
13399
13471
|
await mkdir19(paths.haiveDir, { recursive: true });
|
|
13400
|
-
const current = await
|
|
13472
|
+
const current = await loadConfig13(paths);
|
|
13401
13473
|
await saveConfig4(paths, {
|
|
13402
13474
|
...current,
|
|
13403
13475
|
enforcement: {
|
|
@@ -13670,7 +13742,7 @@ async function buildEnforcementReport(dir, stage, sessionId) {
|
|
|
13670
13742
|
const root = findProjectRoot49(dir);
|
|
13671
13743
|
const paths = resolveHaivePaths45(root);
|
|
13672
13744
|
const initialized = existsSync68(paths.haiveDir);
|
|
13673
|
-
const config = initialized ? await
|
|
13745
|
+
const config = initialized ? await loadConfig13(paths) : {};
|
|
13674
13746
|
if (initialized) await applyLightweightRepairs(root, paths);
|
|
13675
13747
|
const mode = config.enforcement?.mode ?? "strict";
|
|
13676
13748
|
const findings = [];
|
|
@@ -13700,7 +13772,7 @@ async function buildEnforcementReport(dir, stage, sessionId) {
|
|
|
13700
13772
|
findings: [{ severity: "info", code: "enforcement-off", message: "hAIve enforcement is disabled." }]
|
|
13701
13773
|
});
|
|
13702
13774
|
}
|
|
13703
|
-
findings.push(...await inspectIntegrationVersions(root, "0.
|
|
13775
|
+
findings.push(...await inspectIntegrationVersions(root, "0.10.1"));
|
|
13704
13776
|
if (config.enforcement?.requireBriefingFirst !== false && stage !== "ci") {
|
|
13705
13777
|
const hasBriefing = await hasRecentBriefingMarker(paths, sessionId);
|
|
13706
13778
|
findings.push(hasBriefing ? { severity: "ok", code: "briefing-loaded", message: "A recent hAIve briefing marker exists." } : {
|
|
@@ -14312,7 +14384,7 @@ function registerRun(program2) {
|
|
|
14312
14384
|
|
|
14313
14385
|
// src/index.ts
|
|
14314
14386
|
var program = new Command52();
|
|
14315
|
-
program.name("haive").description("hAIve \u2014 the memory and enforcement layer of your agent harness").version("0.
|
|
14387
|
+
program.name("haive").description("hAIve \u2014 the memory and enforcement layer of your agent harness").version("0.10.1").option("--advanced", "show maintenance and experimental commands in help");
|
|
14316
14388
|
registerInit(program);
|
|
14317
14389
|
registerWelcome(program);
|
|
14318
14390
|
registerResolveProject(program);
|
|
@@ -14371,17 +14443,14 @@ registerPrecommit(program);
|
|
|
14371
14443
|
var CORE_ROOT_COMMANDS = /* @__PURE__ */ new Set([
|
|
14372
14444
|
"init",
|
|
14373
14445
|
"doctor",
|
|
14374
|
-
"tui",
|
|
14375
14446
|
"agent",
|
|
14447
|
+
"briefing",
|
|
14376
14448
|
"enforce",
|
|
14377
14449
|
"run",
|
|
14378
|
-
"briefing",
|
|
14379
14450
|
"sync",
|
|
14380
14451
|
"mcp",
|
|
14381
14452
|
"memory",
|
|
14382
|
-
"session"
|
|
14383
|
-
"precommit",
|
|
14384
|
-
"welcome"
|
|
14453
|
+
"session"
|
|
14385
14454
|
]);
|
|
14386
14455
|
var CORE_MEMORY_COMMANDS = /* @__PURE__ */ new Set([
|
|
14387
14456
|
"add",
|