@inerrata-corporation/errata 2.0.2-dev.685 → 2.0.2-dev.688
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/errata.mjs +137 -32
- package/package.json +1 -1
package/errata.mjs
CHANGED
|
@@ -52221,23 +52221,38 @@ init_review2();
|
|
|
52221
52221
|
import { closeSync, existsSync as existsSync12, fstatSync, openSync, readdirSync as readdirSync5, readSync, statSync as statSync3 } from "node:fs";
|
|
52222
52222
|
import { basename as basename3, dirname as dirname8, join as join15 } from "node:path";
|
|
52223
52223
|
import { homedir as homedir3 } from "node:os";
|
|
52224
|
-
function readFrom(path2, fromByte) {
|
|
52224
|
+
function readFrom(path2, fromByte, maxBytes) {
|
|
52225
52225
|
let fd;
|
|
52226
52226
|
try {
|
|
52227
52227
|
fd = openSync(path2, "r");
|
|
52228
52228
|
} catch {
|
|
52229
|
-
return { text: "", nextOffset: fromByte };
|
|
52229
|
+
return { text: "", nextOffset: fromByte, more: false };
|
|
52230
52230
|
}
|
|
52231
52231
|
try {
|
|
52232
52232
|
const size = fstatSync(fd).size;
|
|
52233
52233
|
const start2 = fromByte > 0 && fromByte <= size ? fromByte : 0;
|
|
52234
|
-
const
|
|
52235
|
-
if (
|
|
52236
|
-
|
|
52237
|
-
|
|
52238
|
-
|
|
52234
|
+
const remaining = size - start2;
|
|
52235
|
+
if (remaining <= 0) return { text: "", nextOffset: size, more: false };
|
|
52236
|
+
let cap = maxBytes && maxBytes > 0 ? maxBytes : remaining;
|
|
52237
|
+
for (; ; ) {
|
|
52238
|
+
const len = Math.min(cap, remaining);
|
|
52239
|
+
const buf = Buffer.allocUnsafe(len);
|
|
52240
|
+
readSync(fd, buf, 0, len, start2);
|
|
52241
|
+
if (len >= remaining) {
|
|
52242
|
+
return { text: buf.toString("utf8"), nextOffset: size, more: false };
|
|
52243
|
+
}
|
|
52244
|
+
const nl = buf.lastIndexOf(10);
|
|
52245
|
+
if (nl >= 0) {
|
|
52246
|
+
return {
|
|
52247
|
+
text: buf.subarray(0, nl + 1).toString("utf8"),
|
|
52248
|
+
nextOffset: start2 + nl + 1,
|
|
52249
|
+
more: true
|
|
52250
|
+
};
|
|
52251
|
+
}
|
|
52252
|
+
cap *= 2;
|
|
52253
|
+
}
|
|
52239
52254
|
} catch {
|
|
52240
|
-
return { text: "", nextOffset: fromByte };
|
|
52255
|
+
return { text: "", nextOffset: fromByte, more: false };
|
|
52241
52256
|
} finally {
|
|
52242
52257
|
closeSync(fd);
|
|
52243
52258
|
}
|
|
@@ -52333,9 +52348,9 @@ function isUserTurnBoundary(obj) {
|
|
|
52333
52348
|
function readAssistantTurns(transcriptPath, includeThinking = true, maxBytes = 2e6) {
|
|
52334
52349
|
return parseAssistantTurns(readTail(transcriptPath, maxBytes), includeThinking);
|
|
52335
52350
|
}
|
|
52336
|
-
function readAssistantTurnsFrom(transcriptPath, fromByte, includeThinking = true) {
|
|
52337
|
-
const { text, nextOffset } = readFrom(transcriptPath, fromByte);
|
|
52338
|
-
return { turns: parseAssistantTurns(text, includeThinking), nextOffset };
|
|
52351
|
+
function readAssistantTurnsFrom(transcriptPath, fromByte, includeThinking = true, maxBytes) {
|
|
52352
|
+
const { text, nextOffset, more } = readFrom(transcriptPath, fromByte, maxBytes);
|
|
52353
|
+
return { turns: parseAssistantTurns(text, includeThinking), nextOffset, more };
|
|
52339
52354
|
}
|
|
52340
52355
|
function parseAssistantTurns(raw2, includeThinking) {
|
|
52341
52356
|
if (!raw2) return [];
|
|
@@ -53749,18 +53764,38 @@ function recordEpisode(store, workspaceId2, t, delta, causal) {
|
|
|
53749
53764
|
return id;
|
|
53750
53765
|
}
|
|
53751
53766
|
|
|
53767
|
+
// src/footprint.ts
|
|
53768
|
+
function numEnv(key, fallback) {
|
|
53769
|
+
const raw2 = process.env[key];
|
|
53770
|
+
if (raw2 == null || raw2.trim() === "") return fallback;
|
|
53771
|
+
const n = Number(raw2);
|
|
53772
|
+
return Number.isFinite(n) && n > 0 ? n : fallback;
|
|
53773
|
+
}
|
|
53774
|
+
var DAEMON_MAX_HEAP_MB = numEnv("ERRATA_MAX_HEAP_MB", 2048);
|
|
53775
|
+
var WORKER_MAX_HEAP_MB = numEnv("ERRATA_WORKER_MAX_HEAP_MB", 1024);
|
|
53776
|
+
var HARVEST_SLICE_BYTES = numEnv("ERRATA_HARVEST_SLICE_BYTES", 4e6);
|
|
53777
|
+
function workerResourceLimits() {
|
|
53778
|
+
return { maxOldGenerationSizeMb: WORKER_MAX_HEAP_MB };
|
|
53779
|
+
}
|
|
53780
|
+
function isWorkerOom(err2) {
|
|
53781
|
+
const e = err2;
|
|
53782
|
+
if (!e) return false;
|
|
53783
|
+
if (e.code === "ERR_WORKER_OUT_OF_MEMORY") return true;
|
|
53784
|
+
return /out of memory|ERR_WORKER_OUT_OF_MEMORY|heap limit/i.test(e.message ?? "");
|
|
53785
|
+
}
|
|
53786
|
+
|
|
53752
53787
|
// src/episode-retention.ts
|
|
53753
53788
|
var EPISODE_RETAIN_DAYS_DEFAULT = 90;
|
|
53754
53789
|
var EPISODE_RETIRE_BATCH_DEFAULT = 300;
|
|
53755
53790
|
var DAY_MS = 864e5;
|
|
53756
|
-
function
|
|
53791
|
+
function numEnv2(key, fallback) {
|
|
53757
53792
|
const raw2 = process.env[key];
|
|
53758
53793
|
if (raw2 == null || raw2.trim() === "") return fallback;
|
|
53759
53794
|
const n = Number(raw2);
|
|
53760
53795
|
return Number.isFinite(n) && n > 0 ? n : fallback;
|
|
53761
53796
|
}
|
|
53762
53797
|
function retireEpisodeProvenance(store, now, opts = {}) {
|
|
53763
|
-
const retainDays = opts.retainDays ??
|
|
53798
|
+
const retainDays = opts.retainDays ?? numEnv2("ERRATA_EPISODE_RETAIN_DAYS", EPISODE_RETAIN_DAYS_DEFAULT);
|
|
53764
53799
|
const batch = opts.batch ?? EPISODE_RETIRE_BATCH_DEFAULT;
|
|
53765
53800
|
const cutoff = now - retainDays * DAY_MS;
|
|
53766
53801
|
const due = store.findNodesByLabel("Episode").filter((ep) => {
|
|
@@ -53836,7 +53871,15 @@ var PassWorker = class {
|
|
|
53836
53871
|
ensureWorker() {
|
|
53837
53872
|
if (this.worker) return;
|
|
53838
53873
|
const workerUrl = new URL("./pass-worker.mjs", import.meta.url);
|
|
53839
|
-
const worker = new Worker(workerUrl, {
|
|
53874
|
+
const worker = new Worker(workerUrl, {
|
|
53875
|
+
workerData: this.init,
|
|
53876
|
+
execArgv: process.execArgv,
|
|
53877
|
+
// HZ-footprint-cap: hard heap ceiling per isolate. A pass that would
|
|
53878
|
+
// exceed it dies HERE, in the isolate built to be expendable — the
|
|
53879
|
+
// engine's fallback must then SKIP the pass (isWorkerOom), never re-run
|
|
53880
|
+
// it inline where the same allocation would take down the hook server.
|
|
53881
|
+
resourceLimits: workerResourceLimits()
|
|
53882
|
+
});
|
|
53840
53883
|
this.worker = worker;
|
|
53841
53884
|
this.ready = new Promise((resolve6, reject) => {
|
|
53842
53885
|
const onReady = (m) => {
|
|
@@ -55412,7 +55455,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
|
|
|
55412
55455
|
}
|
|
55413
55456
|
|
|
55414
55457
|
// src/engine.ts
|
|
55415
|
-
var DAEMON_VERSION = true ? "2.0.2-dev.
|
|
55458
|
+
var DAEMON_VERSION = true ? "2.0.2-dev.688" : "2.0.0-alpha.0";
|
|
55416
55459
|
var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
|
|
55417
55460
|
var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
|
|
55418
55461
|
var GIT_OP_MUTE_MS = 4e3;
|
|
@@ -55958,6 +56001,36 @@ function createWorkspaceEngine(opts) {
|
|
|
55958
56001
|
}
|
|
55959
56002
|
return { report: r.report, localSkills: r.localSkills };
|
|
55960
56003
|
} catch (err2) {
|
|
56004
|
+
if (isWorkerOom(err2)) {
|
|
56005
|
+
console.warn("[errata] nightly worker hit its heap ceiling \u2014 heavy pass skipped this fire");
|
|
56006
|
+
appendPassLedger(paths.configDir, "graph-rescore", 0, { oomSkipped: 1 });
|
|
56007
|
+
const sem = runSemanticMaintenance(store);
|
|
56008
|
+
return {
|
|
56009
|
+
report: {
|
|
56010
|
+
scoredNodes: 0,
|
|
56011
|
+
iterations: 0,
|
|
56012
|
+
converged: true,
|
|
56013
|
+
landmarks: 0,
|
|
56014
|
+
communities: 0,
|
|
56015
|
+
motifsPromoted: 0,
|
|
56016
|
+
techniques: 0,
|
|
56017
|
+
antipatterns: 0,
|
|
56018
|
+
skillsInduced: 0,
|
|
56019
|
+
skillsRefreshed: 0,
|
|
56020
|
+
pageRankWritten: 0,
|
|
56021
|
+
landmarkFlips: 0,
|
|
56022
|
+
mode: "incremental",
|
|
56023
|
+
regionSize: 0,
|
|
56024
|
+
designResolved: sem.designResolved,
|
|
56025
|
+
revisitsCleared: sem.revisitsCleared,
|
|
56026
|
+
fixCandidatesSettled: sem.fixCandidatesSettled,
|
|
56027
|
+
claimsEvaluated: sem.claimsEvaluated,
|
|
56028
|
+
claimsDerived: sem.claimsDerived,
|
|
56029
|
+
durationMs: sem.durationMs
|
|
56030
|
+
},
|
|
56031
|
+
localSkills: 0
|
|
56032
|
+
};
|
|
56033
|
+
}
|
|
55961
56034
|
console.warn(
|
|
55962
56035
|
"[errata] nightly worker unavailable, running inline:",
|
|
55963
56036
|
err2 instanceof Error ? err2.message : err2
|
|
@@ -56717,20 +56790,38 @@ function createWorkspaceEngine(opts) {
|
|
|
56717
56790
|
turns = readAssistantTurns(transcriptPath);
|
|
56718
56791
|
nextOffset = transcriptSize(transcriptPath);
|
|
56719
56792
|
} else {
|
|
56720
|
-
({ turns, nextOffset } = readAssistantTurnsFrom(transcriptPath, known));
|
|
56793
|
+
({ turns, nextOffset } = readAssistantTurnsFrom(transcriptPath, known, true, HARVEST_SLICE_BYTES));
|
|
56721
56794
|
}
|
|
56722
56795
|
} catch {
|
|
56723
56796
|
return;
|
|
56724
56797
|
}
|
|
56725
|
-
|
|
56726
|
-
|
|
56727
|
-
|
|
56798
|
+
for (let slice = 0; ; slice++) {
|
|
56799
|
+
const fresh = turnsSince(turns, lastTurnUuid.get(sessionId));
|
|
56800
|
+
turnOffset.set(sessionId, nextOffset);
|
|
56801
|
+
if (fresh.length > 0) {
|
|
56802
|
+
lastTurnUuid.set(sessionId, turns[turns.length - 1].uuid);
|
|
56803
|
+
await harvestTexts(sessionId, fresh);
|
|
56804
|
+
}
|
|
56728
56805
|
saveTurnCursors(turnCursorPath, lastTurnUuid, turnOffset);
|
|
56729
|
-
|
|
56806
|
+
if (slice >= 256) {
|
|
56807
|
+
console.warn("[errata] harvest slice guard hit \u2014 backlog resumes next tick");
|
|
56808
|
+
break;
|
|
56809
|
+
}
|
|
56810
|
+
let next;
|
|
56811
|
+
try {
|
|
56812
|
+
next = readAssistantTurnsFrom(transcriptPath, nextOffset, true, HARVEST_SLICE_BYTES);
|
|
56813
|
+
} catch {
|
|
56814
|
+
break;
|
|
56815
|
+
}
|
|
56816
|
+
if (next.turns.length === 0 && !next.more) {
|
|
56817
|
+
turnOffset.set(sessionId, next.nextOffset);
|
|
56818
|
+
saveTurnCursors(turnCursorPath, lastTurnUuid, turnOffset);
|
|
56819
|
+
break;
|
|
56820
|
+
}
|
|
56821
|
+
turns = next.turns;
|
|
56822
|
+
nextOffset = next.nextOffset;
|
|
56823
|
+
await new Promise((resolve6) => setImmediate(resolve6));
|
|
56730
56824
|
}
|
|
56731
|
-
lastTurnUuid.set(sessionId, turns[turns.length - 1].uuid);
|
|
56732
|
-
await harvestTexts(sessionId, fresh);
|
|
56733
|
-
saveTurnCursors(turnCursorPath, lastTurnUuid, turnOffset);
|
|
56734
56825
|
};
|
|
56735
56826
|
const seenMessageIds = /* @__PURE__ */ new Set();
|
|
56736
56827
|
const onMessage = (e) => {
|
|
@@ -58124,7 +58215,12 @@ var ConsolidateWorker = class {
|
|
|
58124
58215
|
ensureWorker() {
|
|
58125
58216
|
if (this.worker) return;
|
|
58126
58217
|
const workerUrl = new URL("./consolidate-worker.mjs", import.meta.url);
|
|
58127
|
-
const worker = new Worker2(workerUrl, {
|
|
58218
|
+
const worker = new Worker2(workerUrl, {
|
|
58219
|
+
workerData: {},
|
|
58220
|
+
execArgv: process.execArgv,
|
|
58221
|
+
// HZ-footprint-cap — see pass-worker-client.ts for the contract.
|
|
58222
|
+
resourceLimits: workerResourceLimits()
|
|
58223
|
+
});
|
|
58128
58224
|
this.worker = worker;
|
|
58129
58225
|
this.ready = new Promise((resolve6, reject) => {
|
|
58130
58226
|
const onReady = (m) => {
|
|
@@ -60253,7 +60349,7 @@ var DEFAULT_CONSOLIDATION_POLICY = {
|
|
|
60253
60349
|
quiescenceMs: 6e4
|
|
60254
60350
|
// sim preferred 60s over 90s (fresher, esp. heavy-code)
|
|
60255
60351
|
};
|
|
60256
|
-
function
|
|
60352
|
+
function numEnv3(env2, key, fallback) {
|
|
60257
60353
|
const raw2 = env2[key];
|
|
60258
60354
|
if (raw2 == null || raw2.trim() === "") return fallback;
|
|
60259
60355
|
const n = Number(raw2);
|
|
@@ -60261,12 +60357,12 @@ function numEnv2(env2, key, fallback) {
|
|
|
60261
60357
|
}
|
|
60262
60358
|
function consolidationPolicyFromEnv(env2 = process.env) {
|
|
60263
60359
|
return {
|
|
60264
|
-
baseFloorMs:
|
|
60265
|
-
dutyFactor:
|
|
60266
|
-
momentumThreshold:
|
|
60267
|
-
momentumRatio:
|
|
60268
|
-
momentumRatioCap:
|
|
60269
|
-
quiescenceMs:
|
|
60360
|
+
baseFloorMs: numEnv3(env2, "ERRATA_CONSOLIDATE_BASE_FLOOR_MS", DEFAULT_CONSOLIDATION_POLICY.baseFloorMs),
|
|
60361
|
+
dutyFactor: numEnv3(env2, "ERRATA_CONSOLIDATE_DUTY_FACTOR", DEFAULT_CONSOLIDATION_POLICY.dutyFactor),
|
|
60362
|
+
momentumThreshold: numEnv3(env2, "ERRATA_CONSOLIDATE_MOMENTUM", DEFAULT_CONSOLIDATION_POLICY.momentumThreshold),
|
|
60363
|
+
momentumRatio: numEnv3(env2, "ERRATA_CONSOLIDATE_MOMENTUM_RATIO", DEFAULT_CONSOLIDATION_POLICY.momentumRatio),
|
|
60364
|
+
momentumRatioCap: numEnv3(env2, "ERRATA_CONSOLIDATE_MOMENTUM_RATIO_CAP", DEFAULT_CONSOLIDATION_POLICY.momentumRatioCap),
|
|
60365
|
+
quiescenceMs: numEnv3(env2, "ERRATA_CONSOLIDATE_QUIESCENCE_MS", DEFAULT_CONSOLIDATION_POLICY.quiescenceMs)
|
|
60270
60366
|
};
|
|
60271
60367
|
}
|
|
60272
60368
|
function consolidationGapMs(lastPassMs, policy) {
|
|
@@ -62165,7 +62261,16 @@ function spawnDaemonDetached() {
|
|
|
62165
62261
|
detached: true,
|
|
62166
62262
|
stdio: ["ignore", out2, out2],
|
|
62167
62263
|
windowsHide: true,
|
|
62168
|
-
cwd: ROOT
|
|
62264
|
+
cwd: ROOT,
|
|
62265
|
+
// HZ-footprint-cap: hard V8 old-space ceiling on the daemon process. The
|
|
62266
|
+
// workers carry their own resourceLimits; this bounds the main isolate
|
|
62267
|
+
// (hook server + capture), whose bursts are slice-capped so the ceiling is
|
|
62268
|
+
// a backstop, not a working limit. NODE_OPTIONS so it applies however the
|
|
62269
|
+
// bundle re-executes.
|
|
62270
|
+
env: {
|
|
62271
|
+
...process.env,
|
|
62272
|
+
NODE_OPTIONS: `${process.env["NODE_OPTIONS"] ?? ""} --max-old-space-size=${DAEMON_MAX_HEAP_MB}`.trim()
|
|
62273
|
+
}
|
|
62169
62274
|
}).unref();
|
|
62170
62275
|
if (out2 !== "ignore") closeSync2(out2);
|
|
62171
62276
|
}
|