@hiveai/cli 0.19.0 → 0.20.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 +138 -37
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -262,6 +262,7 @@ import {
|
|
|
262
262
|
loadCodeMap,
|
|
263
263
|
loadMemoriesFromDir,
|
|
264
264
|
loadUsageIndex,
|
|
265
|
+
looksLikeGenericAdvice,
|
|
265
266
|
resolveHaivePaths,
|
|
266
267
|
serializeMemory,
|
|
267
268
|
specificityScore
|
|
@@ -310,7 +311,9 @@ async function lintMemoriesAsync(root, options = {}) {
|
|
|
310
311
|
message: "Record does not contain obvious action/rationale words. Add the concrete rule, why it exists, and what to do instead."
|
|
311
312
|
});
|
|
312
313
|
}
|
|
313
|
-
if (["decision", "gotcha", "convention", "architecture"].includes(fm.type) && fm.status !== "rejected" && naked.length >= 40 && specificityScore(naked) < 0.2
|
|
314
|
+
if (["decision", "gotcha", "convention", "architecture"].includes(fm.type) && fm.status !== "rejected" && naked.length >= 40 && specificityScore(naked) < 0.2 && // High-precision gate: only flag when there is positive evidence of generic advice.
|
|
315
|
+
// A low-density but arbitrary team policy (unguessable prose) must not be flagged.
|
|
316
|
+
looksLikeGenericAdvice(naked)) {
|
|
314
317
|
out.push({
|
|
315
318
|
file: filePath,
|
|
316
319
|
id: fm.id,
|
|
@@ -2219,6 +2222,7 @@ import { existsSync as existsSync10 } from "fs";
|
|
|
2219
2222
|
import path10 from "path";
|
|
2220
2223
|
import {
|
|
2221
2224
|
buildFrontmatter,
|
|
2225
|
+
loadMemoriesFromDir as loadMemoriesFromDir5,
|
|
2222
2226
|
memoryFilePath,
|
|
2223
2227
|
serializeMemory as serializeMemory2,
|
|
2224
2228
|
STACK_PACK_TAG
|
|
@@ -3296,6 +3300,15 @@ async function seedStackPack(haivePaths, stack) {
|
|
|
3296
3300
|
const memories = PACKS[stack];
|
|
3297
3301
|
if (!memories) return { memories: 0, sensors: 0 };
|
|
3298
3302
|
await mkdir5(haivePaths.teamDir, { recursive: true });
|
|
3303
|
+
const DATE_PREFIX = /^\d{4}-\d{2}-\d{2}-/;
|
|
3304
|
+
const existingTopics = /* @__PURE__ */ new Set();
|
|
3305
|
+
const existingSignatures = /* @__PURE__ */ new Set();
|
|
3306
|
+
if (existsSync10(haivePaths.memoriesDir)) {
|
|
3307
|
+
for (const { memory: memory2 } of await loadMemoriesFromDir5(haivePaths.memoriesDir)) {
|
|
3308
|
+
if (memory2.frontmatter.topic) existingTopics.add(memory2.frontmatter.topic);
|
|
3309
|
+
existingSignatures.add(memory2.frontmatter.id.replace(DATE_PREFIX, ""));
|
|
3310
|
+
}
|
|
3311
|
+
}
|
|
3299
3312
|
let memCount = 0;
|
|
3300
3313
|
let sensorCount = 0;
|
|
3301
3314
|
for (const mem of memories) {
|
|
@@ -3309,14 +3322,19 @@ async function seedStackPack(haivePaths, stack) {
|
|
|
3309
3322
|
autogen: false,
|
|
3310
3323
|
last_fired: null
|
|
3311
3324
|
} : void 0;
|
|
3325
|
+
const combinedSlug = mem.slug === stack || mem.slug.startsWith(`${stack}-`) ? mem.slug : `${stack}-${mem.slug}`;
|
|
3326
|
+
const topic = `stack-pack:${stack}:${mem.slug}`;
|
|
3327
|
+
const signature = `${mem.type}-${combinedSlug}`;
|
|
3328
|
+
if (existingTopics.has(topic) || existingSignatures.has(signature)) continue;
|
|
3312
3329
|
const fm = buildFrontmatter({
|
|
3313
3330
|
type: mem.type,
|
|
3314
|
-
slug:
|
|
3331
|
+
slug: combinedSlug,
|
|
3315
3332
|
scope: "team",
|
|
3316
3333
|
status: "validated",
|
|
3317
3334
|
// STACK_PACK_TAG marks this as generic seed knowledge so briefing ranking
|
|
3318
3335
|
// keeps it at `background` priority until it earns a repo-specific anchor.
|
|
3319
3336
|
tags: [...mem.tags, STACK_PACK_TAG],
|
|
3337
|
+
topic,
|
|
3320
3338
|
...sensor ? { sensor } : {}
|
|
3321
3339
|
});
|
|
3322
3340
|
const filePath = memoryFilePath(haivePaths, "team", fm.id);
|
|
@@ -3326,6 +3344,8 @@ async function seedStackPack(haivePaths, stack) {
|
|
|
3326
3344
|
${SEED_FOOTER(stack)}` });
|
|
3327
3345
|
await mkdir5(path10.dirname(filePath), { recursive: true });
|
|
3328
3346
|
await writeFile6(filePath, content, "utf8");
|
|
3347
|
+
existingTopics.add(topic);
|
|
3348
|
+
existingSignatures.add(signature);
|
|
3329
3349
|
memCount++;
|
|
3330
3350
|
if (sensor) sensorCount++;
|
|
3331
3351
|
}
|
|
@@ -3334,7 +3354,7 @@ ${SEED_FOOTER(stack)}` });
|
|
|
3334
3354
|
|
|
3335
3355
|
// src/commands/init.ts
|
|
3336
3356
|
var execFileAsync = promisify2(execFile2);
|
|
3337
|
-
var HAIVE_GITHUB_ACTION_REF = `v${"0.
|
|
3357
|
+
var HAIVE_GITHUB_ACTION_REF = `v${"0.20.1"}`;
|
|
3338
3358
|
var PROJECT_CONTEXT_TEMPLATE = `# Project context
|
|
3339
3359
|
|
|
3340
3360
|
> Generated by \`haive init\`. Run \`haive init --bootstrap\` to auto-fill from your codebase,
|
|
@@ -4455,7 +4475,7 @@ import { existsSync as existsSync22 } from "fs";
|
|
|
4455
4475
|
import path22 from "path";
|
|
4456
4476
|
import { z as z2 } from "zod";
|
|
4457
4477
|
import { existsSync as existsSync32 } from "fs";
|
|
4458
|
-
import { loadMemoriesFromDir as
|
|
4478
|
+
import { loadMemoriesFromDir as loadMemoriesFromDir6 } from "@hiveai/core";
|
|
4459
4479
|
import { z as z3 } from "zod";
|
|
4460
4480
|
import { createHash } from "crypto";
|
|
4461
4481
|
import { mkdir as mkdir22, writeFile as writeFile22 } from "fs/promises";
|
|
@@ -4507,7 +4527,7 @@ import {
|
|
|
4507
4527
|
applyFeedbackAdjustment,
|
|
4508
4528
|
computeImpact,
|
|
4509
4529
|
getUsage as getUsage22,
|
|
4510
|
-
loadMemoriesFromDir as
|
|
4530
|
+
loadMemoriesFromDir as loadMemoriesFromDir62,
|
|
4511
4531
|
loadUsageIndex as loadUsageIndex32,
|
|
4512
4532
|
recordApplied,
|
|
4513
4533
|
recordRejection as recordRejection2,
|
|
@@ -4838,7 +4858,7 @@ async function memList(input, ctx) {
|
|
|
4838
4858
|
if (!existsSync32(ctx.paths.memoriesDir)) {
|
|
4839
4859
|
return { memories: [] };
|
|
4840
4860
|
}
|
|
4841
|
-
const all = await
|
|
4861
|
+
const all = await loadMemoriesFromDir6(ctx.paths.memoriesDir);
|
|
4842
4862
|
const filtered = all.filter(({ memory: memory2 }) => {
|
|
4843
4863
|
const fm = memory2.frontmatter;
|
|
4844
4864
|
if (input.scope && fm.scope !== input.scope) return false;
|
|
@@ -5370,7 +5390,7 @@ async function memFeedback(input, ctx) {
|
|
|
5370
5390
|
if (!existsSync82(ctx.paths.memoriesDir)) {
|
|
5371
5391
|
return { ok: false, id: input.id, error: "No .ai/memories \u2014 run `haive init` first." };
|
|
5372
5392
|
}
|
|
5373
|
-
const all = await
|
|
5393
|
+
const all = await loadMemoriesFromDir62(ctx.paths.memoriesDir);
|
|
5374
5394
|
const target = all.find((m) => m.memory.frontmatter.id === input.id);
|
|
5375
5395
|
if (!target) {
|
|
5376
5396
|
return { ok: false, id: input.id, error: `No memory with id '${input.id}'.` };
|
|
@@ -7894,8 +7914,17 @@ function classifyWarning(warning, paths, anchoredBlocks = false) {
|
|
|
7894
7914
|
repair_command: repairCommand
|
|
7895
7915
|
};
|
|
7896
7916
|
}
|
|
7917
|
+
if (warning.has_sensor && !warning.reasons.includes("sensor") && !warning.reasons.includes("anchor")) {
|
|
7918
|
+
return {
|
|
7919
|
+
...warning,
|
|
7920
|
+
level: "info",
|
|
7921
|
+
rationale: "memory has a deterministic sensor that did not fire and is not anchored to a touched file \u2014 treated as non-violation noise",
|
|
7922
|
+
affected_files: affectedFiles,
|
|
7923
|
+
repair_command: repairCommand
|
|
7924
|
+
};
|
|
7925
|
+
}
|
|
7897
7926
|
const corroborated = warning.reasons.includes("anchor") || warning.distinctive_literal === true;
|
|
7898
|
-
const semanticReviewFloor = corroborated ? 0.45 : 0.
|
|
7927
|
+
const semanticReviewFloor = corroborated ? 0.45 : 0.65;
|
|
7899
7928
|
if (hasSemantic && semanticScore >= semanticReviewFloor || highConfidence && warning.reasons.includes("anchor") && warning.reasons.includes("literal")) {
|
|
7900
7929
|
return {
|
|
7901
7930
|
...warning,
|
|
@@ -8571,7 +8600,7 @@ When done, respond with: "Imported N memories: [list of IDs]" or "Nothing action
|
|
|
8571
8600
|
};
|
|
8572
8601
|
}
|
|
8573
8602
|
var SERVER_NAME = "haive";
|
|
8574
|
-
var SERVER_VERSION = "0.
|
|
8603
|
+
var SERVER_VERSION = "0.20.1";
|
|
8575
8604
|
function jsonResult(data) {
|
|
8576
8605
|
return {
|
|
8577
8606
|
content: [
|
|
@@ -14323,7 +14352,7 @@ function registerDoctor(program2) {
|
|
|
14323
14352
|
fix: "Edit .ai/haive.config.json: set autoSessionEnd: true (or re-run `haive init` without --manual)."
|
|
14324
14353
|
});
|
|
14325
14354
|
}
|
|
14326
|
-
findings.push(...await collectInstallFindings(root, "0.
|
|
14355
|
+
findings.push(...await collectInstallFindings(root, "0.20.1"));
|
|
14327
14356
|
findings.push(...await collectToolchainFindings(root));
|
|
14328
14357
|
try {
|
|
14329
14358
|
const legacyRaw = execSync3("haive-mcp --version", {
|
|
@@ -14331,7 +14360,7 @@ function registerDoctor(program2) {
|
|
|
14331
14360
|
timeout: 3e3,
|
|
14332
14361
|
stdio: ["ignore", "pipe", "ignore"]
|
|
14333
14362
|
}).trim();
|
|
14334
|
-
const cliVersion = "0.
|
|
14363
|
+
const cliVersion = "0.20.1";
|
|
14335
14364
|
if (legacyRaw && legacyRaw !== cliVersion) {
|
|
14336
14365
|
findings.push({
|
|
14337
14366
|
severity: "warn",
|
|
@@ -15411,17 +15440,21 @@ import path53 from "path";
|
|
|
15411
15440
|
import "commander";
|
|
15412
15441
|
import {
|
|
15413
15442
|
antiPatternGateParams as antiPatternGateParams2,
|
|
15443
|
+
BRIDGE_TARGET_PATH as BRIDGE_TARGET_PATH2,
|
|
15414
15444
|
findProjectRoot as findProjectRoot52,
|
|
15415
15445
|
findUncapturedFailures,
|
|
15416
15446
|
hasRecentBriefingMarker as hasRecentBriefingMarker2,
|
|
15417
15447
|
isFreshIsoDate,
|
|
15448
|
+
isRetiredMemory as isRetiredMemory3,
|
|
15418
15449
|
loadConfig as loadConfig14,
|
|
15419
15450
|
loadMemoriesFromDir as loadMemoriesFromDir38,
|
|
15420
15451
|
memoryMatchesAnchorPaths as memoryMatchesAnchorPaths6,
|
|
15421
15452
|
readRecentBriefingMarker,
|
|
15422
15453
|
resolveBriefingBudget as resolveBriefingBudget3,
|
|
15423
15454
|
resolveHaivePaths as resolveHaivePaths48,
|
|
15455
|
+
runSensors as runSensors2,
|
|
15424
15456
|
saveConfig as saveConfig4,
|
|
15457
|
+
sensorTargetsFromDiff as sensorTargetsFromDiff2,
|
|
15425
15458
|
SESSION_RECAP_TTL_MS,
|
|
15426
15459
|
verifyAnchor as verifyAnchor4,
|
|
15427
15460
|
writeBriefingMarker as writeBriefingMarker3
|
|
@@ -16027,7 +16060,7 @@ async function buildEnforcementReport(dir, stage, sessionId) {
|
|
|
16027
16060
|
findings: [{ severity: "info", code: "enforcement-off", message: "hAIve enforcement is disabled." }]
|
|
16028
16061
|
});
|
|
16029
16062
|
}
|
|
16030
|
-
findings.push(...await inspectIntegrationVersions(root, "0.
|
|
16063
|
+
findings.push(...await inspectIntegrationVersions(root, "0.20.1"));
|
|
16031
16064
|
if (config.enforcement?.requireBriefingFirst !== false && stage !== "ci") {
|
|
16032
16065
|
const hasBriefing = await hasRecentBriefingMarker2(paths, sessionId);
|
|
16033
16066
|
findings.push(hasBriefing ? { severity: "ok", code: "briefing-loaded", message: "A recent hAIve briefing marker exists." } : {
|
|
@@ -16150,8 +16183,9 @@ async function verifyDecisionCoverage(paths, stage, sessionId) {
|
|
|
16150
16183
|
return [{ severity: "info", code: "decision-coverage-no-changes", message: "No changed files to match against policy memories." }];
|
|
16151
16184
|
}
|
|
16152
16185
|
const all = await loadMemoriesFromDir38(paths.memoriesDir);
|
|
16186
|
+
const changedSet = new Set(changedFiles);
|
|
16153
16187
|
const policyTypes = /* @__PURE__ */ new Set(["decision", "gotcha", "architecture", "convention"]);
|
|
16154
|
-
const relevant = all.
|
|
16188
|
+
const relevant = all.filter(({ memory: memory2 }) => {
|
|
16155
16189
|
const fm = memory2.frontmatter;
|
|
16156
16190
|
if (!policyTypes.has(fm.type)) return false;
|
|
16157
16191
|
if (fm.status !== "validated") return false;
|
|
@@ -16170,12 +16204,16 @@ async function verifyDecisionCoverage(paths, stage, sessionId) {
|
|
|
16170
16204
|
severity: "ok",
|
|
16171
16205
|
code: "decision-coverage-ci-pass",
|
|
16172
16206
|
message: `CI surfaced ${relevant.length} relevant anchored decision/polic${relevant.length === 1 ? "y" : "ies"} for ${changedFiles.length} changed file(s). Runtime briefing markers are local-only and are not expected on GitHub Actions.`,
|
|
16173
|
-
memory_ids: relevant.slice(0, 20).map((memory2) => memory2.frontmatter.id),
|
|
16207
|
+
memory_ids: relevant.slice(0, 20).map(({ memory: memory2 }) => memory2.frontmatter.id),
|
|
16174
16208
|
affected_files: changedFiles.slice(0, 10)
|
|
16175
16209
|
}];
|
|
16176
16210
|
}
|
|
16177
16211
|
const consulted = new Set(marker?.memory_ids ?? []);
|
|
16178
|
-
const missing = relevant.filter((memory2) =>
|
|
16212
|
+
const missing = relevant.filter(({ memory: memory2, filePath }) => {
|
|
16213
|
+
if (consulted.has(memory2.frontmatter.id)) return false;
|
|
16214
|
+
if (changedSet.has(path53.relative(paths.root, filePath))) return false;
|
|
16215
|
+
return true;
|
|
16216
|
+
}).map(({ memory: memory2 }) => memory2);
|
|
16179
16217
|
if (missing.length === 0) {
|
|
16180
16218
|
return [{
|
|
16181
16219
|
severity: "ok",
|
|
@@ -16213,20 +16251,83 @@ async function runPrecommitPolicy(paths, gate, stage) {
|
|
|
16213
16251
|
anchored_blocks,
|
|
16214
16252
|
semantic: true
|
|
16215
16253
|
}, { paths });
|
|
16254
|
+
const sensorFindings = await runSensorGate(paths, snapshot.diff);
|
|
16216
16255
|
if (!result.should_block) {
|
|
16217
|
-
return [
|
|
16218
|
-
|
|
16219
|
-
|
|
16220
|
-
|
|
16221
|
-
|
|
16256
|
+
return [
|
|
16257
|
+
{
|
|
16258
|
+
severity: "ok",
|
|
16259
|
+
code: "precommit-policy-pass",
|
|
16260
|
+
message: `${stage === "ci" ? "CI" : "Pre-commit"} policy passed for ${touchedPaths.length} changed file(s).`
|
|
16261
|
+
},
|
|
16262
|
+
...sensorFindings
|
|
16263
|
+
];
|
|
16264
|
+
}
|
|
16265
|
+
return [
|
|
16266
|
+
{
|
|
16267
|
+
severity: "error",
|
|
16268
|
+
code: "precommit-policy-block",
|
|
16269
|
+
message: `Pre-commit policy matched ${result.summary.blocking_warnings ?? result.summary.anti_patterns} blocking anti-pattern(s), ${result.summary.stale_anchors} stale anchor(s).`,
|
|
16270
|
+
fix: "Review the hAIve warnings, then update the code or the relevant memories.",
|
|
16271
|
+
impact: 45
|
|
16272
|
+
},
|
|
16273
|
+
...sensorFindings
|
|
16274
|
+
];
|
|
16275
|
+
}
|
|
16276
|
+
var SENSOR_OWNED_FILES = /* @__PURE__ */ new Set([
|
|
16277
|
+
...Object.values(BRIDGE_TARGET_PATH2),
|
|
16278
|
+
"CLAUDE.md",
|
|
16279
|
+
".cursorrules",
|
|
16280
|
+
".gitignore",
|
|
16281
|
+
".mcp.json",
|
|
16282
|
+
".cursor/mcp.json",
|
|
16283
|
+
".vscode/mcp.json",
|
|
16284
|
+
".cursor/rules/haive-mcp-required.mdc"
|
|
16285
|
+
]);
|
|
16286
|
+
function isSensorScannablePath(p) {
|
|
16287
|
+
if (!p) return false;
|
|
16288
|
+
if (p.startsWith(".ai/")) return false;
|
|
16289
|
+
return !SENSOR_OWNED_FILES.has(p);
|
|
16290
|
+
}
|
|
16291
|
+
async function runSensorGate(paths, diff) {
|
|
16292
|
+
if (!diff || !existsSync75(paths.memoriesDir)) return [];
|
|
16293
|
+
try {
|
|
16294
|
+
const loaded = await loadMemoriesFromDir38(paths.memoriesDir);
|
|
16295
|
+
const sensorMemories = loaded.map((l) => l.memory).filter((m) => {
|
|
16296
|
+
const s = m.frontmatter.sensor;
|
|
16297
|
+
return Boolean(s) && s.kind === "regex" && !isRetiredMemory3(m.frontmatter, m.body);
|
|
16298
|
+
});
|
|
16299
|
+
if (sensorMemories.length === 0) return [];
|
|
16300
|
+
const targets = sensorTargetsFromDiff2(diff).filter((t) => isSensorScannablePath(t.path));
|
|
16301
|
+
if (targets.length === 0) return [];
|
|
16302
|
+
const hits = runSensors2(sensorMemories, targets);
|
|
16303
|
+
const findings = [];
|
|
16304
|
+
const seen = /* @__PURE__ */ new Set();
|
|
16305
|
+
for (const hit of hits) {
|
|
16306
|
+
if (seen.has(hit.memory_id)) continue;
|
|
16307
|
+
seen.add(hit.memory_id);
|
|
16308
|
+
const where = hit.file ? ` (${hit.file})` : "";
|
|
16309
|
+
if (hit.severity === "block") {
|
|
16310
|
+
findings.push({
|
|
16311
|
+
severity: "error",
|
|
16312
|
+
code: "sensor-block",
|
|
16313
|
+
message: `Block sensor fired \u2014 ${hit.memory_id}: ${hit.message}${where}`,
|
|
16314
|
+
fix: "Remove the flagged pattern, or run `haive sensors check` to inspect the match.",
|
|
16315
|
+
impact: 45
|
|
16316
|
+
});
|
|
16317
|
+
} else {
|
|
16318
|
+
findings.push({
|
|
16319
|
+
severity: "warn",
|
|
16320
|
+
code: "sensor-warn",
|
|
16321
|
+
message: `Sensor flagged ${hit.memory_id}: ${hit.message}${where}`,
|
|
16322
|
+
fix: "Review the flagged line; `haive sensors check` shows the matched code.",
|
|
16323
|
+
impact: 5
|
|
16324
|
+
});
|
|
16325
|
+
}
|
|
16326
|
+
}
|
|
16327
|
+
return findings;
|
|
16328
|
+
} catch {
|
|
16329
|
+
return [];
|
|
16222
16330
|
}
|
|
16223
|
-
return [{
|
|
16224
|
-
severity: "error",
|
|
16225
|
-
code: "precommit-policy-block",
|
|
16226
|
-
message: `Pre-commit policy matched ${result.summary.blocking_warnings ?? result.summary.anti_patterns} blocking anti-pattern(s), ${result.summary.stale_anchors} stale anchor(s).`,
|
|
16227
|
-
fix: "Review the hAIve warnings, then update the code or the relevant memories.",
|
|
16228
|
-
impact: 45
|
|
16229
|
-
}];
|
|
16230
16331
|
}
|
|
16231
16332
|
async function findGeneratedArtifacts(paths) {
|
|
16232
16333
|
const dirty = await runCommand4("git", ["status", "--short", "--untracked-files=all"], paths.root).catch(() => "");
|
|
@@ -17022,16 +17123,16 @@ import "commander";
|
|
|
17022
17123
|
import {
|
|
17023
17124
|
appendPreventionEvent as appendPreventionEvent2,
|
|
17024
17125
|
findProjectRoot as findProjectRoot53,
|
|
17025
|
-
isRetiredMemory as
|
|
17126
|
+
isRetiredMemory as isRetiredMemory4,
|
|
17026
17127
|
loadConfig as loadConfig15,
|
|
17027
17128
|
loadMemoriesFromDir as loadMemoriesFromDir39,
|
|
17028
17129
|
loadUsageIndex as loadUsageIndex31,
|
|
17029
17130
|
recordPrevention as recordPrevention2,
|
|
17030
17131
|
resolveHaivePaths as resolveHaivePaths49,
|
|
17031
|
-
runSensors as
|
|
17132
|
+
runSensors as runSensors3,
|
|
17032
17133
|
saveUsageIndex as saveUsageIndex8,
|
|
17033
17134
|
selectCommandSensors,
|
|
17034
|
-
sensorTargetsFromDiff as
|
|
17135
|
+
sensorTargetsFromDiff as sensorTargetsFromDiff3,
|
|
17035
17136
|
serializeMemory as serializeMemory29
|
|
17036
17137
|
} from "@hiveai/core";
|
|
17037
17138
|
var exec2 = promisify3(execFile3);
|
|
@@ -17065,8 +17166,8 @@ function registerSensors(program2) {
|
|
|
17065
17166
|
const paths = resolveHaivePaths49(root);
|
|
17066
17167
|
const memories = await runnableSensorMemories(paths);
|
|
17067
17168
|
const diff = opts.diffFile ? await readFile25(path54.resolve(root, opts.diffFile), "utf8") : await stagedDiff(root);
|
|
17068
|
-
const targets =
|
|
17069
|
-
const hits =
|
|
17169
|
+
const targets = sensorTargetsFromDiff3(diff);
|
|
17170
|
+
const hits = runSensors3(memories, targets.length > 0 ? targets : [{ path: "", content: diff }]);
|
|
17070
17171
|
const config = await loadConfig15(paths);
|
|
17071
17172
|
const runCommands = opts.commands || config.enforcement?.runCommandSensors === true;
|
|
17072
17173
|
const changedPaths = targets.map((t) => t.path).filter(Boolean);
|
|
@@ -17222,7 +17323,7 @@ async function runnableSensorMemories(paths, regexOnly = true) {
|
|
|
17222
17323
|
const sensor = memory2.frontmatter.sensor;
|
|
17223
17324
|
if (!sensor) return false;
|
|
17224
17325
|
if (regexOnly && sensor.kind !== "regex") return false;
|
|
17225
|
-
return !
|
|
17326
|
+
return !isRetiredMemory4(memory2.frontmatter, memory2.body);
|
|
17226
17327
|
});
|
|
17227
17328
|
}
|
|
17228
17329
|
async function runCommandSensor(spec, root) {
|
|
@@ -17924,7 +18025,7 @@ import "commander";
|
|
|
17924
18025
|
import {
|
|
17925
18026
|
findProjectRoot as findProjectRoot61,
|
|
17926
18027
|
resolveHaivePaths as resolveHaivePaths55,
|
|
17927
|
-
BRIDGE_TARGET_PATH as
|
|
18028
|
+
BRIDGE_TARGET_PATH as BRIDGE_TARGET_PATH3,
|
|
17928
18029
|
BRIDGE_TARGETS as BRIDGE_TARGETS3
|
|
17929
18030
|
} from "@hiveai/core";
|
|
17930
18031
|
function registerBridges(program2) {
|
|
@@ -17959,7 +18060,7 @@ function registerBridges(program2) {
|
|
|
17959
18060
|
targets = BRIDGE_TARGETS3;
|
|
17960
18061
|
} else {
|
|
17961
18062
|
targets = BRIDGE_TARGETS3.filter(
|
|
17962
|
-
(t) => existsSync84(path59.join(root,
|
|
18063
|
+
(t) => existsSync84(path59.join(root, BRIDGE_TARGET_PATH3[t]))
|
|
17963
18064
|
);
|
|
17964
18065
|
if (targets.length === 0) {
|
|
17965
18066
|
ui.info(
|
|
@@ -17987,7 +18088,7 @@ function registerBridges(program2) {
|
|
|
17987
18088
|
const root = findProjectRoot61(opts.dir);
|
|
17988
18089
|
console.log(ui.bold("hAIve bridge targets:"));
|
|
17989
18090
|
for (const target of BRIDGE_TARGETS3) {
|
|
17990
|
-
const relPath =
|
|
18091
|
+
const relPath = BRIDGE_TARGET_PATH3[target];
|
|
17991
18092
|
const exists = existsSync84(path59.join(root, relPath));
|
|
17992
18093
|
const marker = exists ? ui.dim("\u2713") : ui.dim("\xB7");
|
|
17993
18094
|
console.log(` ${marker} ${target.padEnd(10)} ${relPath}${exists ? "" : " (not present)"}`);
|
|
@@ -17999,7 +18100,7 @@ function registerBridges(program2) {
|
|
|
17999
18100
|
|
|
18000
18101
|
// src/index.ts
|
|
18001
18102
|
var program = new Command64();
|
|
18002
|
-
program.name("haive").description("hAIve - repo-native memory and context policy for coding-agent harnesses").version("0.
|
|
18103
|
+
program.name("haive").description("hAIve - repo-native memory and context policy for coding-agent harnesses").version("0.20.1").option("--advanced", "show maintenance and experimental commands in help");
|
|
18003
18104
|
registerInit(program);
|
|
18004
18105
|
registerWelcome(program);
|
|
18005
18106
|
registerResolveProject(program);
|