@hivelore/core 0.57.5 → 0.57.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +41 -1
- package/dist/index.js +242 -43
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -50,6 +50,14 @@ var SensorSchema = z.object({
|
|
|
50
50
|
absent: z.string().optional(),
|
|
51
51
|
/** Regex flags (e.g. "i", "m"). Ignored for non-regex kinds. */
|
|
52
52
|
flags: z.string().optional(),
|
|
53
|
+
/**
|
|
54
|
+
* kind=regex only: flip the sensor into a REQUIRED-PRESENCE invariant. `pattern` then names a line
|
|
55
|
+
* that must REMAIN present in the anchored file's final content; the sensor FIRES when a change
|
|
56
|
+
* removes it. A normal regex sensor scans ADDED lines and so structurally cannot see a deletion —
|
|
57
|
+
* this catches the "someone deleted the critical line" class (e.g. a `TimeZone.setDefault(UTC)`
|
|
58
|
+
* guard) that a diff-of-additions sensor misses (field report §3.5).
|
|
59
|
+
*/
|
|
60
|
+
require_present: z.boolean().optional(),
|
|
53
61
|
/** Shell/test command to run (for kind=shell|test). Executed by the CLI, never by core. */
|
|
54
62
|
command: z.string().optional(),
|
|
55
63
|
/** Max runtime for kind=shell|test commands (default 120000). The executor kills on expiry. */
|
|
@@ -936,7 +944,7 @@ function applyFeedbackAdjustment(fm, adjustment, now = /* @__PURE__ */ new Date(
|
|
|
936
944
|
}
|
|
937
945
|
|
|
938
946
|
// src/prevention.ts
|
|
939
|
-
import { appendFile, mkdir as mkdir2, readFile as readFile4 } from "fs/promises";
|
|
947
|
+
import { appendFile, mkdir as mkdir2, readFile as readFile4, writeFile as writeFile2 } from "fs/promises";
|
|
940
948
|
import { existsSync as existsSync4 } from "fs";
|
|
941
949
|
import path6 from "path";
|
|
942
950
|
function preventionLogPath(paths) {
|
|
@@ -964,8 +972,22 @@ async function recordPreventionHits(paths, firedIds, source, now = /* @__PURE__
|
|
|
964
972
|
await appendPreventionEvent(paths, { at, id, source, ...details[id] }).catch(() => {
|
|
965
973
|
});
|
|
966
974
|
}
|
|
975
|
+
await stampSensorLastFired(paths, recordedIds, at).catch(() => {
|
|
976
|
+
});
|
|
967
977
|
return recordedIds;
|
|
968
978
|
}
|
|
979
|
+
async function stampSensorLastFired(paths, ids, at) {
|
|
980
|
+
if (ids.length === 0 || !existsSync4(paths.memoriesDir)) return;
|
|
981
|
+
const wanted = new Set(ids);
|
|
982
|
+
const loaded = await loadMemoriesFromDir(paths.memoriesDir);
|
|
983
|
+
for (const { memory, filePath } of loaded) {
|
|
984
|
+
const fm = memory.frontmatter;
|
|
985
|
+
if (!wanted.has(fm.id) || !fm.sensor || fm.sensor.last_fired === at) continue;
|
|
986
|
+
const next = { ...memory, frontmatter: { ...fm, sensor: { ...fm.sensor, last_fired: at } } };
|
|
987
|
+
await writeFile2(filePath, serializeMemory(next), "utf8").catch(() => {
|
|
988
|
+
});
|
|
989
|
+
}
|
|
990
|
+
}
|
|
969
991
|
function buildPreventionReceipt(events, memories, usage, options) {
|
|
970
992
|
const now = options.now ?? /* @__PURE__ */ new Date();
|
|
971
993
|
const sinceMs = options.since.getTime();
|
|
@@ -1016,6 +1038,11 @@ function buildPreventionReceipt(events, memories, usage, options) {
|
|
|
1016
1038
|
events: rows
|
|
1017
1039
|
};
|
|
1018
1040
|
}
|
|
1041
|
+
function trendClause(total, previous) {
|
|
1042
|
+
const counts = `${total} this window vs ${previous} previous window`;
|
|
1043
|
+
if (total + previous < 3) return counts;
|
|
1044
|
+
return `${counts} (${total <= previous ? "recurrences declining" : "recurrences rising"})`;
|
|
1045
|
+
}
|
|
1019
1046
|
function renderPreventionReceipt(receipt) {
|
|
1020
1047
|
const lines = [
|
|
1021
1048
|
`Hivelore prevention receipt \u2014 last ${receipt.window_days} days`,
|
|
@@ -1033,9 +1060,7 @@ function renderPreventionReceipt(receipt) {
|
|
|
1033
1060
|
const red = row.red_proven ? " \u2713 RED-proven" : "";
|
|
1034
1061
|
lines.push(` \u2717\u2192\u2713 ${row.at.slice(0, 10)} ${row.id.padEnd(32)} (${kind}${exit}${stage})${incident}${red}`);
|
|
1035
1062
|
}
|
|
1036
|
-
lines.push(
|
|
1037
|
-
` Trend: ${receipt.total} this window vs ${receipt.previous_total} previous window (${receipt.total <= receipt.previous_total ? "recurrences declining" : "recurrences rising"}).`
|
|
1038
|
-
);
|
|
1063
|
+
lines.push(` Trend: ${trendClause(receipt.total, receipt.previous_total)}.`);
|
|
1039
1064
|
return lines.join("\n");
|
|
1040
1065
|
}
|
|
1041
1066
|
var HIVELORE_ATTRIBUTION = "\u{1F6E1}\uFE0F Generated by [Hivelore](https://github.com/Doucs91/hivelore) \u2014 the deterministic policy gate for agent-written code.";
|
|
@@ -1062,7 +1087,7 @@ function renderPreventionReceiptShare(receipt) {
|
|
|
1062
1087
|
}
|
|
1063
1088
|
lines.push(
|
|
1064
1089
|
"",
|
|
1065
|
-
`_Trend: ${
|
|
1090
|
+
`_Trend: ${trendClause(receipt.total, receipt.previous_total)}._`
|
|
1066
1091
|
);
|
|
1067
1092
|
}
|
|
1068
1093
|
lines.push("", `<sub>${HIVELORE_ATTRIBUTION}</sub>`);
|
|
@@ -1221,7 +1246,7 @@ function renderCaughtForYou(summary) {
|
|
|
1221
1246
|
|
|
1222
1247
|
// src/context-throttle.ts
|
|
1223
1248
|
import { createHash } from "crypto";
|
|
1224
|
-
import { mkdir as mkdir3, readFile as readFile5, writeFile as
|
|
1249
|
+
import { mkdir as mkdir3, readFile as readFile5, writeFile as writeFile3 } from "fs/promises";
|
|
1225
1250
|
import { existsSync as existsSync5 } from "fs";
|
|
1226
1251
|
import path7 from "path";
|
|
1227
1252
|
var PROJECT_CONTEXT_THROTTLE_MS = 8 * 60 * 1e3;
|
|
@@ -1246,12 +1271,12 @@ async function recordProjectContextEmission(paths, hash, now = Date.now()) {
|
|
|
1246
1271
|
const file = throttleMarkerPath(paths);
|
|
1247
1272
|
await mkdir3(path7.dirname(file), { recursive: true }).catch(() => {
|
|
1248
1273
|
});
|
|
1249
|
-
await
|
|
1274
|
+
await writeFile3(file, JSON.stringify({ hash, at: new Date(now).toISOString() }), "utf8").catch(() => {
|
|
1250
1275
|
});
|
|
1251
1276
|
}
|
|
1252
1277
|
|
|
1253
1278
|
// src/gate-reminder.ts
|
|
1254
|
-
import { mkdir as mkdir4, readFile as readFile6, writeFile as
|
|
1279
|
+
import { mkdir as mkdir4, readFile as readFile6, writeFile as writeFile4 } from "fs/promises";
|
|
1255
1280
|
import { existsSync as existsSync6 } from "fs";
|
|
1256
1281
|
import path8 from "path";
|
|
1257
1282
|
var GATE_REMINDER_WINDOW_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -1280,7 +1305,7 @@ async function recordGateReminder(paths, key, now = Date.now()) {
|
|
|
1280
1305
|
markers[key] = new Date(now).toISOString();
|
|
1281
1306
|
await mkdir4(path8.dirname(file), { recursive: true }).catch(() => {
|
|
1282
1307
|
});
|
|
1283
|
-
await
|
|
1308
|
+
await writeFile4(file, JSON.stringify(markers, null, 2), "utf8").catch(() => {
|
|
1284
1309
|
});
|
|
1285
1310
|
}
|
|
1286
1311
|
|
|
@@ -1821,20 +1846,137 @@ function compileAbsentRegex(sensor) {
|
|
|
1821
1846
|
return null;
|
|
1822
1847
|
}
|
|
1823
1848
|
}
|
|
1849
|
+
var C_FAMILY = { line: ["//"], block: ["/*", "*/"], starContinuation: true };
|
|
1850
|
+
var HASH_FAMILY = { line: ["#"], block: null, starContinuation: false };
|
|
1851
|
+
var CSS_FAMILY = { line: [], block: ["/*", "*/"], starContinuation: true };
|
|
1852
|
+
var SCSS_FAMILY = { line: ["//"], block: ["/*", "*/"], starContinuation: true };
|
|
1853
|
+
var SQL_FAMILY = { line: ["--"], block: ["/*", "*/"], starContinuation: false };
|
|
1854
|
+
var HTML_FAMILY = { line: [], block: ["<!--", "-->"], starContinuation: false };
|
|
1855
|
+
var COMMENT_SYNTAX_BY_EXT = {
|
|
1856
|
+
ts: C_FAMILY,
|
|
1857
|
+
tsx: C_FAMILY,
|
|
1858
|
+
js: C_FAMILY,
|
|
1859
|
+
jsx: C_FAMILY,
|
|
1860
|
+
mjs: C_FAMILY,
|
|
1861
|
+
cjs: C_FAMILY,
|
|
1862
|
+
java: C_FAMILY,
|
|
1863
|
+
c: C_FAMILY,
|
|
1864
|
+
h: C_FAMILY,
|
|
1865
|
+
cpp: C_FAMILY,
|
|
1866
|
+
hpp: C_FAMILY,
|
|
1867
|
+
cc: C_FAMILY,
|
|
1868
|
+
hh: C_FAMILY,
|
|
1869
|
+
cs: C_FAMILY,
|
|
1870
|
+
go: C_FAMILY,
|
|
1871
|
+
rs: C_FAMILY,
|
|
1872
|
+
kt: C_FAMILY,
|
|
1873
|
+
kts: C_FAMILY,
|
|
1874
|
+
swift: C_FAMILY,
|
|
1875
|
+
scala: C_FAMILY,
|
|
1876
|
+
php: C_FAMILY,
|
|
1877
|
+
dart: C_FAMILY,
|
|
1878
|
+
m: C_FAMILY,
|
|
1879
|
+
mm: C_FAMILY,
|
|
1880
|
+
py: HASH_FAMILY,
|
|
1881
|
+
rb: HASH_FAMILY,
|
|
1882
|
+
sh: HASH_FAMILY,
|
|
1883
|
+
bash: HASH_FAMILY,
|
|
1884
|
+
zsh: HASH_FAMILY,
|
|
1885
|
+
yml: HASH_FAMILY,
|
|
1886
|
+
yaml: HASH_FAMILY,
|
|
1887
|
+
toml: HASH_FAMILY,
|
|
1888
|
+
properties: HASH_FAMILY,
|
|
1889
|
+
conf: HASH_FAMILY,
|
|
1890
|
+
cfg: HASH_FAMILY,
|
|
1891
|
+
pl: HASH_FAMILY,
|
|
1892
|
+
pm: HASH_FAMILY,
|
|
1893
|
+
r: HASH_FAMILY,
|
|
1894
|
+
css: CSS_FAMILY,
|
|
1895
|
+
scss: SCSS_FAMILY,
|
|
1896
|
+
less: SCSS_FAMILY,
|
|
1897
|
+
sql: SQL_FAMILY,
|
|
1898
|
+
html: HTML_FAMILY,
|
|
1899
|
+
htm: HTML_FAMILY,
|
|
1900
|
+
xml: HTML_FAMILY,
|
|
1901
|
+
vue: HTML_FAMILY,
|
|
1902
|
+
svelte: HTML_FAMILY,
|
|
1903
|
+
md: HTML_FAMILY,
|
|
1904
|
+
markdown: HTML_FAMILY
|
|
1905
|
+
};
|
|
1906
|
+
function commentSyntaxForPath(path22) {
|
|
1907
|
+
const base = path22.split(/[\\/]/).pop() ?? "";
|
|
1908
|
+
const dot = base.lastIndexOf(".");
|
|
1909
|
+
if (dot < 0) return null;
|
|
1910
|
+
return COMMENT_SYNTAX_BY_EXT[base.slice(dot + 1).toLowerCase()] ?? null;
|
|
1911
|
+
}
|
|
1912
|
+
function blankCommentsOnLine(line, syntax) {
|
|
1913
|
+
if (syntax.starContinuation && /^\*(\s|\/|$)/.test(line.trimStart())) {
|
|
1914
|
+
return " ".repeat(line.length);
|
|
1915
|
+
}
|
|
1916
|
+
let out = "";
|
|
1917
|
+
let stringDelim = null;
|
|
1918
|
+
for (let i = 0; i < line.length; i++) {
|
|
1919
|
+
const ch = line[i];
|
|
1920
|
+
if (stringDelim) {
|
|
1921
|
+
out += ch;
|
|
1922
|
+
if (ch === "\\" && i + 1 < line.length) {
|
|
1923
|
+
out += line[i + 1];
|
|
1924
|
+
i++;
|
|
1925
|
+
continue;
|
|
1926
|
+
}
|
|
1927
|
+
if (ch === stringDelim) stringDelim = null;
|
|
1928
|
+
continue;
|
|
1929
|
+
}
|
|
1930
|
+
if (ch === '"' || ch === "'" || ch === "`") {
|
|
1931
|
+
stringDelim = ch;
|
|
1932
|
+
out += ch;
|
|
1933
|
+
continue;
|
|
1934
|
+
}
|
|
1935
|
+
if (syntax.block) {
|
|
1936
|
+
const [open, close] = syntax.block;
|
|
1937
|
+
if (line.startsWith(open, i)) {
|
|
1938
|
+
const closeIdx = line.indexOf(close, i + open.length);
|
|
1939
|
+
const end = closeIdx === -1 ? line.length : closeIdx + close.length;
|
|
1940
|
+
out += " ".repeat(end - i);
|
|
1941
|
+
if (closeIdx === -1) break;
|
|
1942
|
+
i = end - 1;
|
|
1943
|
+
continue;
|
|
1944
|
+
}
|
|
1945
|
+
}
|
|
1946
|
+
let hitLineComment = false;
|
|
1947
|
+
for (const lc of syntax.line) {
|
|
1948
|
+
if (line.startsWith(lc, i)) {
|
|
1949
|
+
out += " ".repeat(line.length - i);
|
|
1950
|
+
hitLineComment = true;
|
|
1951
|
+
break;
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1954
|
+
if (hitLineComment) break;
|
|
1955
|
+
out += ch;
|
|
1956
|
+
}
|
|
1957
|
+
return out;
|
|
1958
|
+
}
|
|
1959
|
+
function stripCommentsForScan(content, path22) {
|
|
1960
|
+
const syntax = commentSyntaxForPath(path22);
|
|
1961
|
+
if (!syntax) return content;
|
|
1962
|
+
return content.split("\n").map((l) => blankCommentsOnLine(l, syntax)).join("\n");
|
|
1963
|
+
}
|
|
1824
1964
|
function runRegexSensor(memoryId, sensor, target) {
|
|
1825
1965
|
const re = compileRegexSensor(sensor);
|
|
1826
1966
|
if (!re) return null;
|
|
1827
1967
|
const absentRe = compileAbsentRegex(sensor);
|
|
1828
|
-
const
|
|
1829
|
-
|
|
1830
|
-
|
|
1968
|
+
const rawLines = target.content.split("\n");
|
|
1969
|
+
const scanLines = stripCommentsForScan(target.content, target.path).split("\n");
|
|
1970
|
+
for (let i = 0; i < rawLines.length; i++) {
|
|
1971
|
+
const rawLine = rawLines[i];
|
|
1972
|
+
const scanLine = scanLines[i] ?? rawLine;
|
|
1831
1973
|
re.lastIndex = 0;
|
|
1832
|
-
if (!re.test(
|
|
1974
|
+
if (!re.test(scanLine)) continue;
|
|
1833
1975
|
if (absentRe) {
|
|
1834
1976
|
const from = Math.max(0, i - SENSOR_ABSENT_LOOKBACK);
|
|
1835
|
-
const to = Math.min(
|
|
1977
|
+
const to = Math.min(scanLines.length, i + SENSOR_ABSENT_WINDOW + 1);
|
|
1836
1978
|
absentRe.lastIndex = 0;
|
|
1837
|
-
if (absentRe.test(
|
|
1979
|
+
if (absentRe.test(scanLines.slice(from, to).join("\n"))) continue;
|
|
1838
1980
|
}
|
|
1839
1981
|
const brittle = sensor.kind === "regex" && sensor.pattern ? sensorPatternBrittleness(sensor.pattern) : null;
|
|
1840
1982
|
const severity = brittle ? "warn" : sensor.severity;
|
|
@@ -1854,6 +1996,7 @@ function runSensors(memories, targets) {
|
|
|
1854
1996
|
for (const memory of memories) {
|
|
1855
1997
|
const sensor = memory.frontmatter.sensor;
|
|
1856
1998
|
if (!sensor || sensor.kind !== "regex") continue;
|
|
1999
|
+
if (sensor.require_present) continue;
|
|
1857
2000
|
const anchorPaths = memory.frontmatter.anchor.paths;
|
|
1858
2001
|
for (const target of targets) {
|
|
1859
2002
|
if (!sensorAppliesToPath(sensor, anchorPaths, target.path)) continue;
|
|
@@ -1863,6 +2006,47 @@ function runSensors(memories, targets) {
|
|
|
1863
2006
|
}
|
|
1864
2007
|
return hits;
|
|
1865
2008
|
}
|
|
2009
|
+
function changedPathsFromDiff(diff) {
|
|
2010
|
+
const out = /* @__PURE__ */ new Set();
|
|
2011
|
+
for (const m of diff.matchAll(/^diff --git a\/(.+?) b\/(.+)$/gm)) {
|
|
2012
|
+
out.add((m[2] ?? m[1] ?? "").trim());
|
|
2013
|
+
}
|
|
2014
|
+
for (const m of diff.matchAll(/^\+\+\+ b\/(.+)$/gm)) {
|
|
2015
|
+
const p = (m[1] ?? "").trim();
|
|
2016
|
+
if (p && p !== "/dev/null") out.add(p);
|
|
2017
|
+
}
|
|
2018
|
+
return [...out];
|
|
2019
|
+
}
|
|
2020
|
+
function runPresenceSensors(memories, finalTargets) {
|
|
2021
|
+
const hits = [];
|
|
2022
|
+
for (const memory of memories) {
|
|
2023
|
+
const sensor = memory.frontmatter.sensor;
|
|
2024
|
+
if (!sensor || sensor.kind !== "regex" || !sensor.require_present || !sensor.pattern) continue;
|
|
2025
|
+
let re;
|
|
2026
|
+
try {
|
|
2027
|
+
const flags = new Set(["m", ...(sensor.flags ?? "").split("")].filter(Boolean));
|
|
2028
|
+
re = new RegExp(sensor.pattern, [...flags].join(""));
|
|
2029
|
+
} catch {
|
|
2030
|
+
continue;
|
|
2031
|
+
}
|
|
2032
|
+
const anchorPaths = memory.frontmatter.anchor.paths;
|
|
2033
|
+
for (const target of finalTargets) {
|
|
2034
|
+
if (!sensorAppliesToPath(sensor, anchorPaths, target.path)) continue;
|
|
2035
|
+
re.lastIndex = 0;
|
|
2036
|
+
if (!re.test(target.content)) {
|
|
2037
|
+
hits.push({
|
|
2038
|
+
memory_id: memory.frontmatter.id,
|
|
2039
|
+
sensor,
|
|
2040
|
+
file: target.path,
|
|
2041
|
+
message: sensor.message,
|
|
2042
|
+
severity: sensor.severity
|
|
2043
|
+
});
|
|
2044
|
+
break;
|
|
2045
|
+
}
|
|
2046
|
+
}
|
|
2047
|
+
}
|
|
2048
|
+
return hits;
|
|
2049
|
+
}
|
|
1866
2050
|
var COMMAND_ENV_EXACT = /* @__PURE__ */ new Set([
|
|
1867
2051
|
"PATH",
|
|
1868
2052
|
"HOME",
|
|
@@ -2104,14 +2288,14 @@ function sensorSelfCheck(sensor, input) {
|
|
|
2104
2288
|
function judgeProposedSensor(sensor, input) {
|
|
2105
2289
|
const brittle = sensor.kind === "regex" && sensor.pattern ? sensorPatternBrittleness(sensor.pattern) : null;
|
|
2106
2290
|
const self_check = sensorSelfCheck(sensor, input);
|
|
2291
|
+
if (self_check.fires_on_correct === true) {
|
|
2292
|
+
return { accepted: false, reason: "fires-on-correct", self_check, brittle };
|
|
2293
|
+
}
|
|
2107
2294
|
if (sensor.severity === "block") {
|
|
2108
2295
|
if (brittle) return { accepted: false, reason: "brittle", self_check, brittle };
|
|
2109
2296
|
if (input.currentTargets.length > 0 && !self_check.silent_on_current) {
|
|
2110
2297
|
return { accepted: false, reason: "fires-on-current", self_check, brittle };
|
|
2111
2298
|
}
|
|
2112
|
-
if (self_check.fires_on_correct === true) {
|
|
2113
|
-
return { accepted: false, reason: "fires-on-correct", self_check, brittle };
|
|
2114
|
-
}
|
|
2115
2299
|
if (self_check.fires_on_bad === false) {
|
|
2116
2300
|
return { accepted: false, reason: "missed-bad-example", self_check, brittle };
|
|
2117
2301
|
}
|
|
@@ -3099,7 +3283,7 @@ function allocateBudget(parts, maxTokens) {
|
|
|
3099
3283
|
}
|
|
3100
3284
|
|
|
3101
3285
|
// src/code-map.ts
|
|
3102
|
-
import { mkdir as mkdir5, readFile as readFile7, readdir as readdir3, stat as stat2, writeFile as
|
|
3286
|
+
import { mkdir as mkdir5, readFile as readFile7, readdir as readdir3, stat as stat2, writeFile as writeFile5 } from "fs/promises";
|
|
3103
3287
|
import { createHash as createHash2 } from "crypto";
|
|
3104
3288
|
import { existsSync as existsSync7 } from "fs";
|
|
3105
3289
|
import { spawnSync } from "child_process";
|
|
@@ -3542,10 +3726,10 @@ async function saveCodeMap(paths, map) {
|
|
|
3542
3726
|
const current = existsSync7(file) ? await readFile7(file, "utf8").catch(() => null) : null;
|
|
3543
3727
|
if (current === payload) return;
|
|
3544
3728
|
await mkdir5(path9.dirname(file), { recursive: true });
|
|
3545
|
-
await
|
|
3729
|
+
await writeFile5(file, payload, "utf8");
|
|
3546
3730
|
await mkdir5(paths.runtimeDir, { recursive: true }).catch(() => {
|
|
3547
3731
|
});
|
|
3548
|
-
await
|
|
3732
|
+
await writeFile5(
|
|
3549
3733
|
codeMapMetaPath(paths),
|
|
3550
3734
|
`${JSON.stringify({ generated_at: (/* @__PURE__ */ new Date()).toISOString(), content_hash: codeMapContentHash(map) }, null, 2)}
|
|
3551
3735
|
`,
|
|
@@ -3914,7 +4098,7 @@ function queryCodeMap(map, options) {
|
|
|
3914
4098
|
// src/config.ts
|
|
3915
4099
|
import { existsSync as existsSync8 } from "fs";
|
|
3916
4100
|
import { readFileSync } from "fs";
|
|
3917
|
-
import { readFile as readFile8, rm, writeFile as
|
|
4101
|
+
import { readFile as readFile8, rm, writeFile as writeFile6 } from "fs/promises";
|
|
3918
4102
|
import path10 from "path";
|
|
3919
4103
|
var CONFIG_FILE = "hivelore.config.json";
|
|
3920
4104
|
var LEGACY_CONFIG_FILE = "haive.config.json";
|
|
@@ -4046,7 +4230,7 @@ function loadConfigSync(paths) {
|
|
|
4046
4230
|
}
|
|
4047
4231
|
}
|
|
4048
4232
|
async function saveConfig(paths, config) {
|
|
4049
|
-
await
|
|
4233
|
+
await writeFile6(configPath(paths), JSON.stringify(config, null, 2) + "\n", "utf8");
|
|
4050
4234
|
const legacy = path10.join(paths.haiveDir, LEGACY_CONFIG_FILE);
|
|
4051
4235
|
if (existsSync8(legacy)) {
|
|
4052
4236
|
try {
|
|
@@ -4072,7 +4256,7 @@ function mergeConfig(base, override) {
|
|
|
4072
4256
|
|
|
4073
4257
|
// src/cross-repo.ts
|
|
4074
4258
|
import { existsSync as existsSync9 } from "fs";
|
|
4075
|
-
import { mkdir as mkdir6, readFile as readFile9, writeFile as
|
|
4259
|
+
import { mkdir as mkdir6, readFile as readFile9, writeFile as writeFile7 } from "fs/promises";
|
|
4076
4260
|
import path11 from "path";
|
|
4077
4261
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
4078
4262
|
async function loadImportMap(cacheDir) {
|
|
@@ -4085,7 +4269,7 @@ async function loadImportMap(cacheDir) {
|
|
|
4085
4269
|
}
|
|
4086
4270
|
}
|
|
4087
4271
|
async function saveImportMap(cacheDir, map) {
|
|
4088
|
-
await
|
|
4272
|
+
await writeFile7(path11.join(cacheDir, "import-map.json"), JSON.stringify(map, null, 2) + "\n", "utf8");
|
|
4089
4273
|
}
|
|
4090
4274
|
async function pullCrossRepoSources(paths, config, projectRoot) {
|
|
4091
4275
|
const sources = config.crossRepoSources ?? [];
|
|
@@ -4171,7 +4355,7 @@ async function pullFromSource(paths, source, projectRoot) {
|
|
|
4171
4355
|
}
|
|
4172
4356
|
const updatedBody = importedBodyPrefix + memory.body;
|
|
4173
4357
|
if (existingEntry) {
|
|
4174
|
-
await
|
|
4358
|
+
await writeFile7(
|
|
4175
4359
|
existingLocalPath,
|
|
4176
4360
|
serializeMemory({ frontmatter: existingEntry.memory.frontmatter, body: updatedBody }),
|
|
4177
4361
|
"utf8"
|
|
@@ -4196,7 +4380,7 @@ async function pullFromSource(paths, source, projectRoot) {
|
|
|
4196
4380
|
});
|
|
4197
4381
|
const body = importedBodyPrefix + memory.body;
|
|
4198
4382
|
const destPath = path11.join(destDir, `${newFm.id}.md`);
|
|
4199
|
-
await
|
|
4383
|
+
await writeFile7(destPath, serializeMemory({ frontmatter: newFm, body }), "utf8");
|
|
4200
4384
|
importMap[sourceId] = destPath;
|
|
4201
4385
|
dirty = true;
|
|
4202
4386
|
report.imported.push(sourceId);
|
|
@@ -4234,7 +4418,7 @@ async function cloneOrFetchGitSource(source, paths, report) {
|
|
|
4234
4418
|
|
|
4235
4419
|
// src/dep-tracker.ts
|
|
4236
4420
|
import { existsSync as existsSync10 } from "fs";
|
|
4237
|
-
import { readFile as readFile10, writeFile as
|
|
4421
|
+
import { readFile as readFile10, writeFile as writeFile8, mkdir as mkdir7 } from "fs/promises";
|
|
4238
4422
|
import path12 from "path";
|
|
4239
4423
|
function parsePackageJson(content) {
|
|
4240
4424
|
try {
|
|
@@ -4347,7 +4531,7 @@ async function trackDependencies(projectRoot, haiveDir, manifestFiles) {
|
|
|
4347
4531
|
captured_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4348
4532
|
deps: currentDeps
|
|
4349
4533
|
};
|
|
4350
|
-
await
|
|
4534
|
+
await writeFile8(lockPath, JSON.stringify(snapshot2, null, 2) + "\n", "utf8");
|
|
4351
4535
|
continue;
|
|
4352
4536
|
}
|
|
4353
4537
|
const snapshot = JSON.parse(await readFile10(lockPath, "utf8"));
|
|
@@ -4370,7 +4554,7 @@ async function trackDependencies(projectRoot, haiveDir, manifestFiles) {
|
|
|
4370
4554
|
captured_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4371
4555
|
deps: currentDeps
|
|
4372
4556
|
};
|
|
4373
|
-
await
|
|
4557
|
+
await writeFile8(lockPath, JSON.stringify(updated, null, 2) + "\n", "utf8");
|
|
4374
4558
|
}
|
|
4375
4559
|
}
|
|
4376
4560
|
return results;
|
|
@@ -4378,7 +4562,7 @@ async function trackDependencies(projectRoot, haiveDir, manifestFiles) {
|
|
|
4378
4562
|
|
|
4379
4563
|
// src/contract-watcher.ts
|
|
4380
4564
|
import { existsSync as existsSync11 } from "fs";
|
|
4381
|
-
import { readFile as readFile11, writeFile as
|
|
4565
|
+
import { readFile as readFile11, writeFile as writeFile9, mkdir as mkdir8 } from "fs/promises";
|
|
4382
4566
|
import path13 from "path";
|
|
4383
4567
|
import crypto from "crypto";
|
|
4384
4568
|
function sha256(content) {
|
|
@@ -4601,7 +4785,7 @@ async function snapshotContract(projectRoot, haiveDir, contract) {
|
|
|
4601
4785
|
};
|
|
4602
4786
|
const contractsDir = path13.join(haiveDir, "contracts");
|
|
4603
4787
|
await mkdir8(contractsDir, { recursive: true });
|
|
4604
|
-
await
|
|
4788
|
+
await writeFile9(contractLockPath(haiveDir, contract.name), JSON.stringify(snapshot, null, 2) + "\n", "utf8");
|
|
4605
4789
|
return snapshot;
|
|
4606
4790
|
}
|
|
4607
4791
|
async function diffContract(projectRoot, haiveDir, contract) {
|
|
@@ -4625,7 +4809,7 @@ async function diffContract(projectRoot, haiveDir, contract) {
|
|
|
4625
4809
|
};
|
|
4626
4810
|
const changes = diffSnapshots(beforeSnapshot, afterSnapshot);
|
|
4627
4811
|
if (changes.length > 0) {
|
|
4628
|
-
await
|
|
4812
|
+
await writeFile9(lockPath, JSON.stringify(afterSnapshot, null, 2) + "\n", "utf8");
|
|
4629
4813
|
}
|
|
4630
4814
|
return {
|
|
4631
4815
|
contract: contract.name,
|
|
@@ -4719,7 +4903,7 @@ async function usageLogSize(paths) {
|
|
|
4719
4903
|
}
|
|
4720
4904
|
|
|
4721
4905
|
// src/friction.ts
|
|
4722
|
-
import { appendFile as appendFile3, mkdir as mkdir10, readFile as readFile13, writeFile as
|
|
4906
|
+
import { appendFile as appendFile3, mkdir as mkdir10, readFile as readFile13, writeFile as writeFile10 } from "fs/promises";
|
|
4723
4907
|
import { existsSync as existsSync13 } from "fs";
|
|
4724
4908
|
import { createHash as createHash3 } from "crypto";
|
|
4725
4909
|
import path15 from "path";
|
|
@@ -4819,7 +5003,7 @@ async function loadFrictionState(paths) {
|
|
|
4819
5003
|
}
|
|
4820
5004
|
async function saveFrictionState(paths, state) {
|
|
4821
5005
|
if (!existsSync13(paths.runtimeDir)) await mkdir10(paths.runtimeDir, { recursive: true });
|
|
4822
|
-
await
|
|
5006
|
+
await writeFile10(frictionStatePath(paths), JSON.stringify(state, null, 2) + "\n", "utf8");
|
|
4823
5007
|
}
|
|
4824
5008
|
async function setFrictionStatus(paths, fingerprint, status, url) {
|
|
4825
5009
|
const state = await loadFrictionState(paths);
|
|
@@ -4949,8 +5133,20 @@ function extractActionsBriefBody(markdown, maxChars = MAX_DEFAULT_CHARS) {
|
|
|
4949
5133
|
buf.push(t);
|
|
4950
5134
|
}
|
|
4951
5135
|
if (buf.length) paragraphs.push(buf.join(" ").trim());
|
|
4952
|
-
|
|
4953
|
-
|
|
5136
|
+
if (paragraphs.length === 0) {
|
|
5137
|
+
let out2 = stripped.slice(0, maxChars);
|
|
5138
|
+
if (out2.length > maxChars) out2 = out2.slice(0, maxChars).trimEnd() + "\u2026";
|
|
5139
|
+
return out2;
|
|
5140
|
+
}
|
|
5141
|
+
const collected = [];
|
|
5142
|
+
let length = 0;
|
|
5143
|
+
for (const paragraph of paragraphs) {
|
|
5144
|
+
const cost = (collected.length ? 2 : 0) + paragraph.length;
|
|
5145
|
+
if (collected.length > 0 && length + cost > maxChars) break;
|
|
5146
|
+
collected.push(paragraph);
|
|
5147
|
+
length += cost;
|
|
5148
|
+
}
|
|
5149
|
+
let out = collected.join("\n\n");
|
|
4954
5150
|
if (out.length > maxChars) out = out.slice(0, maxChars).trimEnd() + "\u2026";
|
|
4955
5151
|
return out;
|
|
4956
5152
|
}
|
|
@@ -5279,7 +5475,7 @@ async function readRuntimeJournalTail(paths, limit) {
|
|
|
5279
5475
|
}
|
|
5280
5476
|
|
|
5281
5477
|
// src/enforcement.ts
|
|
5282
|
-
import { mkdir as mkdir12, readdir as readdir4, readFile as readFile15, writeFile as
|
|
5478
|
+
import { mkdir as mkdir12, readdir as readdir4, readFile as readFile15, writeFile as writeFile11 } from "fs/promises";
|
|
5283
5479
|
import { existsSync as existsSync16 } from "fs";
|
|
5284
5480
|
import path18 from "path";
|
|
5285
5481
|
var BRIEFING_MARKER_TTL_MS = 12 * 60 * 60 * 1e3;
|
|
@@ -5320,7 +5516,7 @@ async function writeBriefingMarker(paths, input) {
|
|
|
5320
5516
|
root: paths.root
|
|
5321
5517
|
};
|
|
5322
5518
|
await mkdir12(briefingMarkersDir(paths), { recursive: true });
|
|
5323
|
-
await
|
|
5519
|
+
await writeFile11(
|
|
5324
5520
|
briefingMarkerPath(paths, marker.session_id),
|
|
5325
5521
|
JSON.stringify(marker, null, 2) + "\n",
|
|
5326
5522
|
"utf8"
|
|
@@ -5431,7 +5627,7 @@ function isRetiredMemory(fm, body = "", now = /* @__PURE__ */ new Date()) {
|
|
|
5431
5627
|
// src/sensor-ledger.ts
|
|
5432
5628
|
import { createHash as createHash4 } from "crypto";
|
|
5433
5629
|
import { existsSync as existsSync17, readFileSync as readFileSync2 } from "fs";
|
|
5434
|
-
import { appendFile as appendFile5, mkdir as mkdir13, readFile as readFile16, rename, writeFile as
|
|
5630
|
+
import { appendFile as appendFile5, mkdir as mkdir13, readFile as readFile16, rename, writeFile as writeFile12 } from "fs/promises";
|
|
5435
5631
|
import path19 from "path";
|
|
5436
5632
|
var MAX_LINES = 1e4;
|
|
5437
5633
|
var RETAINED_LINES = 8e3;
|
|
@@ -5454,7 +5650,7 @@ async function appendSensorEvaluations(paths, evaluations) {
|
|
|
5454
5650
|
const lines = raw.split("\n").filter(Boolean);
|
|
5455
5651
|
if (lines.length > MAX_LINES) {
|
|
5456
5652
|
const temp = `${file}.${process.pid}.tmp`;
|
|
5457
|
-
await
|
|
5653
|
+
await writeFile12(temp, lines.slice(-RETAINED_LINES).join("\n") + "\n", "utf8");
|
|
5458
5654
|
await rename(temp, file);
|
|
5459
5655
|
}
|
|
5460
5656
|
} catch {
|
|
@@ -7155,7 +7351,7 @@ ${trimmed}`;
|
|
|
7155
7351
|
}
|
|
7156
7352
|
|
|
7157
7353
|
// src/handoff.ts
|
|
7158
|
-
import { writeFile as
|
|
7354
|
+
import { writeFile as writeFile13, readFile as readFile18, stat as stat4 } from "fs/promises";
|
|
7159
7355
|
import { existsSync as existsSync19 } from "fs";
|
|
7160
7356
|
import path21 from "path";
|
|
7161
7357
|
var HANDOFF_FILENAME = "NEXT.md";
|
|
@@ -7209,7 +7405,7 @@ function buildHandoffMarkdown(data) {
|
|
|
7209
7405
|
}
|
|
7210
7406
|
async function writeSessionHandoff(root, data) {
|
|
7211
7407
|
const file = handoffFilePath(root);
|
|
7212
|
-
await
|
|
7408
|
+
await writeFile13(file, buildHandoffMarkdown(data), "utf8");
|
|
7213
7409
|
return file;
|
|
7214
7410
|
}
|
|
7215
7411
|
async function readSessionHandoff(root) {
|
|
@@ -7434,6 +7630,7 @@ export {
|
|
|
7434
7630
|
buildProposeCommand,
|
|
7435
7631
|
buildReport,
|
|
7436
7632
|
bumpRead,
|
|
7633
|
+
changedPathsFromDiff,
|
|
7437
7634
|
churnForAnchors,
|
|
7438
7635
|
classifyGithubRelease,
|
|
7439
7636
|
classifyMemoryPriority,
|
|
@@ -7619,6 +7816,7 @@ export {
|
|
|
7619
7816
|
retirementSignal,
|
|
7620
7817
|
revertedShaFromCommit,
|
|
7621
7818
|
reviewLearningsToDrafts,
|
|
7819
|
+
runPresenceSensors,
|
|
7622
7820
|
runRegexSensor,
|
|
7623
7821
|
runSensors,
|
|
7624
7822
|
runTierContract,
|
|
@@ -7646,6 +7844,7 @@ export {
|
|
|
7646
7844
|
shouldExpandGateReminder,
|
|
7647
7845
|
snapshotContract,
|
|
7648
7846
|
specificityScore,
|
|
7847
|
+
stripCommentsForScan,
|
|
7649
7848
|
stripPrivate,
|
|
7650
7849
|
suggestGate,
|
|
7651
7850
|
suggestSensorFromMemory,
|