@inerrata-corporation/errata 2.0.2-dev.698 → 2.0.2-dev.704
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 +157 -64
- package/package.json +1 -1
package/errata.mjs
CHANGED
|
@@ -17361,7 +17361,7 @@ CREATE INDEX IF NOT EXISTS nodes_relpath ON nodes(json_extract(attrs_json, '$.re
|
|
|
17361
17361
|
return { count: Number(r.count), total: Number(r.total) };
|
|
17362
17362
|
}
|
|
17363
17363
|
liveNodeIds(ids) {
|
|
17364
|
-
const
|
|
17364
|
+
const live2 = /* @__PURE__ */ new Set();
|
|
17365
17365
|
const CHUNK = 900;
|
|
17366
17366
|
for (let i2 = 0; i2 < ids.length; i2 += CHUNK) {
|
|
17367
17367
|
const slice = ids.slice(i2, i2 + CHUNK);
|
|
@@ -17369,9 +17369,9 @@ CREATE INDEX IF NOT EXISTS nodes_relpath ON nodes(json_extract(attrs_json, '$.re
|
|
|
17369
17369
|
const rows = this.db.prepare(
|
|
17370
17370
|
`SELECT id FROM nodes WHERE valid_to IS NULL AND id IN (${slice.map(() => "?").join(",")})`
|
|
17371
17371
|
).all(...slice);
|
|
17372
|
-
for (const r of rows)
|
|
17372
|
+
for (const r of rows) live2.add(r.id);
|
|
17373
17373
|
}
|
|
17374
|
-
return
|
|
17374
|
+
return live2;
|
|
17375
17375
|
}
|
|
17376
17376
|
/**
|
|
17377
17377
|
* Live edges WITH their endpoint labels and ids, resolved in ONE join.
|
|
@@ -17415,9 +17415,9 @@ CREATE INDEX IF NOT EXISTS nodes_relpath ON nodes(json_extract(attrs_json, '$.re
|
|
|
17415
17415
|
// the indexer calls freezeNode inside its own store.transaction(). So this
|
|
17416
17416
|
// method does NOT open a transaction — callers needing atomicity wrap it.
|
|
17417
17417
|
freezeNode(liveId, t) {
|
|
17418
|
-
const
|
|
17419
|
-
if (!
|
|
17420
|
-
const version2 =
|
|
17418
|
+
const live2 = this.getNode(liveId);
|
|
17419
|
+
if (!live2) return null;
|
|
17420
|
+
const version2 = live2.version ?? 1;
|
|
17421
17421
|
const frozenId = `${liveId}@v${version2}`;
|
|
17422
17422
|
if (this.getNode(frozenId)) {
|
|
17423
17423
|
this.stmts.advanceLive.run({ live_id: liveId, t });
|
|
@@ -20216,8 +20216,8 @@ function applyDataDependentMomentum(previousCumulative, newSignal, seqGapSinceLa
|
|
|
20216
20216
|
);
|
|
20217
20217
|
}
|
|
20218
20218
|
function newPeakSurprise(oldPeak, newCumulative) {
|
|
20219
|
-
const
|
|
20220
|
-
return newCumulative >
|
|
20219
|
+
const peak2 = oldPeak ?? 0;
|
|
20220
|
+
return newCumulative > peak2 ? newCumulative : peak2;
|
|
20221
20221
|
}
|
|
20222
20222
|
var init_momentum = __esm({
|
|
20223
20223
|
"../../packages/math/src/momentum.ts"() {
|
|
@@ -20248,10 +20248,10 @@ function computeAdaptiveHalfLife(stats) {
|
|
|
20248
20248
|
return Math.max(1, halfLife);
|
|
20249
20249
|
}
|
|
20250
20250
|
function momentumHealth(stats) {
|
|
20251
|
-
const
|
|
20252
|
-
if (
|
|
20251
|
+
const peak2 = stats.peakSurprise ?? 0;
|
|
20252
|
+
if (peak2 <= 0) return 1;
|
|
20253
20253
|
const cum = Math.max(0, stats.cumulativeSurprise ?? 0);
|
|
20254
|
-
return Math.max(MOMENTUM_GATE_FLOOR, Math.min(1, cum /
|
|
20254
|
+
return Math.max(MOMENTUM_GATE_FLOOR, Math.min(1, cum / peak2));
|
|
20255
20255
|
}
|
|
20256
20256
|
function computeAdaptiveConfidence(stats, opts) {
|
|
20257
20257
|
if (stats.memoryTier === "persistent") {
|
|
@@ -28482,8 +28482,8 @@ function mergeProblemsByEmbedding(store, opts) {
|
|
|
28482
28482
|
}
|
|
28483
28483
|
function bindCanonicalNeighbors(store, opts) {
|
|
28484
28484
|
const k = opts.k ?? 3;
|
|
28485
|
-
const
|
|
28486
|
-
const problems = store.findNodesByLabel("Problem").filter((p) => p.embedding.length > 0 &&
|
|
28485
|
+
const live2 = (n) => n.attrs["mergedInto"] === void 0;
|
|
28486
|
+
const problems = store.findNodesByLabel("Problem").filter((p) => p.embedding.length > 0 && live2(p));
|
|
28487
28487
|
const patterns = store.findNodesByLabel("Pattern").filter((p) => p.embedding.length > 0);
|
|
28488
28488
|
const candidates = [...problems, ...patterns];
|
|
28489
28489
|
let bound = 0;
|
|
@@ -30869,12 +30869,12 @@ async function incrementalReindex(store, rootPath, workspaceId2, changedAbsPaths
|
|
|
30869
30869
|
if (changedIds.length > 0) {
|
|
30870
30870
|
store.transaction(() => {
|
|
30871
30871
|
for (const nid of changedIds) {
|
|
30872
|
-
const
|
|
30873
|
-
if (!
|
|
30874
|
-
const history = store.nodeHistory(
|
|
30872
|
+
const live2 = store.getNode(nid);
|
|
30873
|
+
if (!live2) continue;
|
|
30874
|
+
const history = store.nodeHistory(live2.logicalId ?? nid);
|
|
30875
30875
|
const birth = history[0];
|
|
30876
30876
|
if (!birth || birth.id === nid) continue;
|
|
30877
|
-
const currentSim =
|
|
30877
|
+
const currentSim = live2.attrs["bodySimhash"];
|
|
30878
30878
|
const birthSim = birth.attrs["bodySimhash"];
|
|
30879
30879
|
if (!hasForkedDrift(currentSim, birthSim)) continue;
|
|
30880
30880
|
const forkId = edgeId(nid, "FORKED_FROM", birth.id);
|
|
@@ -38981,13 +38981,13 @@ async function findStaleFiles(store, rootPath, workspaceId2) {
|
|
|
38981
38981
|
}
|
|
38982
38982
|
}
|
|
38983
38983
|
}
|
|
38984
|
-
const
|
|
38984
|
+
const live2 = /* @__PURE__ */ new Set();
|
|
38985
38985
|
for (let i2 = 0; i2 < allTargets.length; i2 += LIVENESS_CHUNK) {
|
|
38986
|
-
for (const id of store.liveNodeIds(allTargets.slice(i2, i2 + LIVENESS_CHUNK)))
|
|
38986
|
+
for (const id of store.liveNodeIds(allTargets.slice(i2, i2 + LIVENESS_CHUNK))) live2.add(id);
|
|
38987
38987
|
if (i2 + LIVENESS_CHUNK < allTargets.length) await new Promise((r) => setImmediate(r));
|
|
38988
38988
|
}
|
|
38989
38989
|
for (const { abs, targets } of pending) {
|
|
38990
|
-
if (targets.some((id) => !
|
|
38990
|
+
if (targets.some((id) => !live2.has(id))) stale.push(abs);
|
|
38991
38991
|
}
|
|
38992
38992
|
return stale;
|
|
38993
38993
|
}
|
|
@@ -39009,12 +39009,12 @@ function reapOrphanedFiles(store, rootPath, workspaceId2, ignoreDirs = []) {
|
|
|
39009
39009
|
if (listed === null) return { reaped: 0, symbolsClosed: 0, skipped: "no-git-listing" };
|
|
39010
39010
|
if (listed.length === 0) return { reaped: 0, symbolsClosed: 0, skipped: "empty-listing" };
|
|
39011
39011
|
const onDisk = new Set(listed);
|
|
39012
|
-
const
|
|
39013
|
-
const orphans =
|
|
39012
|
+
const live2 = store.findNodesByLabel("File").filter((f) => f.attrs["workspaceId"] === workspaceId2);
|
|
39013
|
+
const orphans = live2.filter((f) => {
|
|
39014
39014
|
const rel = f.attrs["relPath"];
|
|
39015
39015
|
return typeof rel === "string" && !onDisk.has(rel);
|
|
39016
39016
|
});
|
|
39017
|
-
const allowance = Math.max(ORPHAN_REAP_MIN_ALLOWANCE,
|
|
39017
|
+
const allowance = Math.max(ORPHAN_REAP_MIN_ALLOWANCE, live2.length * ORPHAN_REAP_MAX_FRACTION);
|
|
39018
39018
|
if (orphans.length > allowance) {
|
|
39019
39019
|
return {
|
|
39020
39020
|
reaped: 0,
|
|
@@ -49401,11 +49401,11 @@ function isLive2(verb) {
|
|
|
49401
49401
|
function nextHtml(n, opts) {
|
|
49402
49402
|
if (!n) return "";
|
|
49403
49403
|
const cmd2 = `errata ${n.verb}${n.arg ? " " + n.arg : ""}`;
|
|
49404
|
-
const
|
|
49405
|
-
if (!
|
|
49404
|
+
const live2 = isLive2(n.verb);
|
|
49405
|
+
if (!live2 && !opts.includeFutureVerbs) return "";
|
|
49406
49406
|
const hint = n.hint ? ` \u2014 ${esc3(n.hint)}` : "";
|
|
49407
|
-
const cls =
|
|
49408
|
-
const tag =
|
|
49407
|
+
const cls = live2 ? "next" : "next soon";
|
|
49408
|
+
const tag = live2 ? `<code>${esc3(cmd2)}</code>` : `<span class="vsoon">${esc3(cmd2)} \xB7 soon</span>`;
|
|
49409
49409
|
return `<div class="${cls}">next: ${tag}${hint}</div>`;
|
|
49410
49410
|
}
|
|
49411
49411
|
function shell(title, body2) {
|
|
@@ -49770,7 +49770,7 @@ var init_report_render = __esm({
|
|
|
49770
49770
|
|
|
49771
49771
|
// src/cli.ts
|
|
49772
49772
|
init_src6();
|
|
49773
|
-
import { closeSync as closeSync2, existsSync as
|
|
49773
|
+
import { closeSync as closeSync2, existsSync as existsSync30, openSync as openSync2, readFileSync as readFileSync28, renameSync as renameSync4, statSync as statSync6 } from "node:fs";
|
|
49774
49774
|
import { join as join32 } from "node:path";
|
|
49775
49775
|
import { spawn as spawn3 } from "node:child_process";
|
|
49776
49776
|
|
|
@@ -53564,6 +53564,24 @@ init_reconcile();
|
|
|
53564
53564
|
// src/pass-ledger.ts
|
|
53565
53565
|
import { appendFileSync as appendFileSync2, existsSync as existsSync15, readFileSync as readFileSync13, writeFileSync as writeFileSync13 } from "node:fs";
|
|
53566
53566
|
import { join as join18 } from "node:path";
|
|
53567
|
+
|
|
53568
|
+
// src/isolate-census.ts
|
|
53569
|
+
var live = 0;
|
|
53570
|
+
var spawnedTotal = 0;
|
|
53571
|
+
var peak = 0;
|
|
53572
|
+
function noteIsolateSpawned() {
|
|
53573
|
+
live += 1;
|
|
53574
|
+
spawnedTotal += 1;
|
|
53575
|
+
if (live > peak) peak = live;
|
|
53576
|
+
}
|
|
53577
|
+
function noteIsolateExited() {
|
|
53578
|
+
if (live > 0) live -= 1;
|
|
53579
|
+
}
|
|
53580
|
+
function isolateCensus() {
|
|
53581
|
+
return { live, spawnedTotal, peak };
|
|
53582
|
+
}
|
|
53583
|
+
|
|
53584
|
+
// src/pass-ledger.ts
|
|
53567
53585
|
var PER_KIND_MAX = 100;
|
|
53568
53586
|
var TRIM_EVERY = 50;
|
|
53569
53587
|
var appendsSinceTrim = /* @__PURE__ */ new Map();
|
|
@@ -53573,11 +53591,22 @@ function passLedgerPath(configDir) {
|
|
|
53573
53591
|
function appendPassLedger(configDir, kind, durationMs, counts) {
|
|
53574
53592
|
const path2 = passLedgerPath(configDir);
|
|
53575
53593
|
try {
|
|
53594
|
+
const mem = process.memoryUsage();
|
|
53595
|
+
const census = isolateCensus();
|
|
53576
53596
|
const entry = {
|
|
53577
53597
|
ts: Date.now(),
|
|
53578
53598
|
kind,
|
|
53579
53599
|
durationMs,
|
|
53580
|
-
counts: {
|
|
53600
|
+
counts: {
|
|
53601
|
+
...counts,
|
|
53602
|
+
rssMB: Math.round(mem.rss / 1048576),
|
|
53603
|
+
heapUsedMB: Math.round(mem.heapUsed / 1048576),
|
|
53604
|
+
externalMB: Math.round(mem.external / 1048576),
|
|
53605
|
+
arrayBuffersMB: Math.round(mem.arrayBuffers / 1048576),
|
|
53606
|
+
isolatesLive: census.live,
|
|
53607
|
+
isolatesSpawned: census.spawnedTotal,
|
|
53608
|
+
isolatesPeak: census.peak
|
|
53609
|
+
}
|
|
53581
53610
|
};
|
|
53582
53611
|
appendFileSync2(path2, JSON.stringify(entry) + "\n");
|
|
53583
53612
|
const n = (appendsSinceTrim.get(path2) ?? 0) + 1;
|
|
@@ -53751,8 +53780,8 @@ function recordEpisode(store, workspaceId2, t, delta, causal) {
|
|
|
53751
53780
|
minted++;
|
|
53752
53781
|
}
|
|
53753
53782
|
if (s.change === "changed") {
|
|
53754
|
-
const
|
|
53755
|
-
const prev = (
|
|
53783
|
+
const live2 = store.getNode(s.nodeId);
|
|
53784
|
+
const prev = (live2?.version ?? 2) - 1;
|
|
53756
53785
|
const frozenId = `${s.nodeId}@v${prev}`;
|
|
53757
53786
|
if (store.getNode(frozenId)) {
|
|
53758
53787
|
store.mergeEdge(producedEdge(id, frozenId, t));
|
|
@@ -53773,6 +53802,8 @@ function numEnv(key, fallback) {
|
|
|
53773
53802
|
}
|
|
53774
53803
|
var DAEMON_MAX_HEAP_MB = numEnv("ERRATA_MAX_HEAP_MB", 2048);
|
|
53775
53804
|
var WORKER_MAX_HEAP_MB = numEnv("ERRATA_WORKER_MAX_HEAP_MB", 1024);
|
|
53805
|
+
var WORKSPACE_IDLE_TTL_MS = numEnv("ERRATA_WORKSPACE_IDLE_TTL_MS", 15 * 6e4);
|
|
53806
|
+
var WORKSPACE_SWEEP_INTERVAL_MS = numEnv("ERRATA_WORKSPACE_SWEEP_MS", 6e4);
|
|
53776
53807
|
var HARVEST_SLICE_BYTES = numEnv("ERRATA_HARVEST_SLICE_BYTES", 4e6);
|
|
53777
53808
|
function workerResourceLimits() {
|
|
53778
53809
|
return { maxOldGenerationSizeMb: WORKER_MAX_HEAP_MB };
|
|
@@ -53783,6 +53814,11 @@ function isWorkerOom(err2) {
|
|
|
53783
53814
|
if (e.code === "ERR_WORKER_OUT_OF_MEMORY") return true;
|
|
53784
53815
|
return /out of memory|ERR_WORKER_OUT_OF_MEMORY|heap limit/i.test(e.message ?? "");
|
|
53785
53816
|
}
|
|
53817
|
+
function retireDecision(input) {
|
|
53818
|
+
if (!input.exists) return "gone";
|
|
53819
|
+
const ttl = input.ttlMs ?? WORKSPACE_IDLE_TTL_MS;
|
|
53820
|
+
return input.now - input.lastActiveAt > ttl ? "idle" : null;
|
|
53821
|
+
}
|
|
53786
53822
|
|
|
53787
53823
|
// src/episode-retention.ts
|
|
53788
53824
|
var EPISODE_RETAIN_DAYS_DEFAULT = 90;
|
|
@@ -53919,6 +53955,7 @@ var PassWorker = class {
|
|
|
53919
53955
|
// it inline where the same allocation would take down the hook server.
|
|
53920
53956
|
resourceLimits: workerResourceLimits()
|
|
53921
53957
|
});
|
|
53958
|
+
noteIsolateSpawned();
|
|
53922
53959
|
this.worker = worker;
|
|
53923
53960
|
this.ready = new Promise((resolve6, reject) => {
|
|
53924
53961
|
const onReady = (m) => {
|
|
@@ -53948,6 +53985,7 @@ var PassWorker = class {
|
|
|
53948
53985
|
};
|
|
53949
53986
|
worker.on("error", teardown);
|
|
53950
53987
|
worker.on("exit", (code) => {
|
|
53988
|
+
noteIsolateExited();
|
|
53951
53989
|
if (!this.stopped) teardown(new Error(`pass worker exited (code ${code})`));
|
|
53952
53990
|
});
|
|
53953
53991
|
}
|
|
@@ -54662,7 +54700,7 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
|
|
|
54662
54700
|
const res = await client.getSkills(void 0, seed, techSeed);
|
|
54663
54701
|
const staleDaemon = res.staleDaemon && res.latestDaemonVersion ? { latest: res.latestDaemonVersion } : void 0;
|
|
54664
54702
|
mkdirSync6(paths.skillsDir, { recursive: true });
|
|
54665
|
-
if (res.skills.length === 0 && pins.length === 0) {
|
|
54703
|
+
if (res.skills.length === 0 && pins.length === 0 && !res.skillsGated) {
|
|
54666
54704
|
const existing = readdirSync7(paths.skillsDir).filter((f) => f.endsWith(".md"));
|
|
54667
54705
|
if (existing.length > 0) return { written: 0, pruned: 0, ...staleDaemon ? { staleDaemon } : {} };
|
|
54668
54706
|
}
|
|
@@ -54896,7 +54934,7 @@ var INTENT_TTL_MS = 15 * 60 * 1e3;
|
|
|
54896
54934
|
function createIntentState(ttlMs = INTENT_TTL_MS) {
|
|
54897
54935
|
const bySession = /* @__PURE__ */ new Map();
|
|
54898
54936
|
let recent = null;
|
|
54899
|
-
const
|
|
54937
|
+
const live2 = (s, nowMs) => s !== void 0 && nowMs - s.atMs < ttlMs;
|
|
54900
54938
|
return {
|
|
54901
54939
|
set(sessionId, text, nowMs) {
|
|
54902
54940
|
const trimmed = text.trim();
|
|
@@ -54910,7 +54948,7 @@ function createIntentState(ttlMs = INTENT_TTL_MS) {
|
|
|
54910
54948
|
},
|
|
54911
54949
|
get(sessionId, nowMs) {
|
|
54912
54950
|
const s = bySession.get(sessionId);
|
|
54913
|
-
return
|
|
54951
|
+
return live2(s, nowMs) ? s.text : void 0;
|
|
54914
54952
|
},
|
|
54915
54953
|
mostRecent(nowMs) {
|
|
54916
54954
|
if (!recent) return void 0;
|
|
@@ -55159,10 +55197,10 @@ function saveWitnessQueue(path2, queue) {
|
|
|
55159
55197
|
}
|
|
55160
55198
|
}
|
|
55161
55199
|
function pruneWitnessQueue(queue, now) {
|
|
55162
|
-
const
|
|
55200
|
+
const live2 = queue.filter(
|
|
55163
55201
|
(w) => now - w.ts < WITNESS_TTL_MS && w.attempts < WITNESS_MAX_ATTEMPTS
|
|
55164
55202
|
);
|
|
55165
|
-
return
|
|
55203
|
+
return live2.length > WITNESS_QUEUE_CAP ? live2.slice(live2.length - WITNESS_QUEUE_CAP) : live2;
|
|
55166
55204
|
}
|
|
55167
55205
|
function enqueueWitnesses(queue, fresh, now) {
|
|
55168
55206
|
const byKey = new Map(queue.map((w) => [`${w.channel}:${w.witnessKey}`, w]));
|
|
@@ -55494,7 +55532,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
|
|
|
55494
55532
|
}
|
|
55495
55533
|
|
|
55496
55534
|
// src/engine.ts
|
|
55497
|
-
var DAEMON_VERSION = true ? "2.0.2-dev.
|
|
55535
|
+
var DAEMON_VERSION = true ? "2.0.2-dev.704" : "2.0.0-alpha.0";
|
|
55498
55536
|
var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
|
|
55499
55537
|
var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
|
|
55500
55538
|
var GIT_OP_MUTE_MS = 4e3;
|
|
@@ -55616,6 +55654,7 @@ function createWorkspaceEngine(opts) {
|
|
|
55616
55654
|
const cloud = opts.cloud;
|
|
55617
55655
|
const telemetry = new TelemetryRecorder(profile.id, DAEMON_VERSION);
|
|
55618
55656
|
let watcher = null;
|
|
55657
|
+
let lastActivityTs = Date.now();
|
|
55619
55658
|
let stopGit = null;
|
|
55620
55659
|
let flushTimer = null;
|
|
55621
55660
|
if (!opts.skipWatchers) {
|
|
@@ -55634,6 +55673,7 @@ function createWorkspaceEngine(opts) {
|
|
|
55634
55673
|
size = statSync5(path2).size;
|
|
55635
55674
|
} catch {
|
|
55636
55675
|
}
|
|
55676
|
+
lastActivityTs = Date.now();
|
|
55637
55677
|
const base = { ts: Date.now(), kind, workspaceId: profile.id, path: path2, size };
|
|
55638
55678
|
const ev = { ...base, digest: digest(base) };
|
|
55639
55679
|
log.append(ev);
|
|
@@ -57034,8 +57074,12 @@ function createWorkspaceEngine(opts) {
|
|
|
57034
57074
|
onSessionEnd
|
|
57035
57075
|
},
|
|
57036
57076
|
emitEvent(ev) {
|
|
57077
|
+
lastActivityTs = Date.now();
|
|
57037
57078
|
log.append(ev);
|
|
57038
57079
|
},
|
|
57080
|
+
lastActivityAt() {
|
|
57081
|
+
return lastActivityTs;
|
|
57082
|
+
},
|
|
57039
57083
|
markContextDirty() {
|
|
57040
57084
|
contextDirty = true;
|
|
57041
57085
|
refreshContextNow();
|
|
@@ -57497,7 +57541,7 @@ function pidAlive(pid) {
|
|
|
57497
57541
|
// src/multi.ts
|
|
57498
57542
|
init_dist();
|
|
57499
57543
|
init_src5();
|
|
57500
|
-
import { readFileSync as readFileSync27, unlinkSync as unlinkSync3, writeFileSync as writeFileSync22 } from "node:fs";
|
|
57544
|
+
import { existsSync as existsSync29, readFileSync as readFileSync27, unlinkSync as unlinkSync3, writeFileSync as writeFileSync22 } from "node:fs";
|
|
57501
57545
|
|
|
57502
57546
|
// src/principle-sync.ts
|
|
57503
57547
|
init_src5();
|
|
@@ -58282,6 +58326,7 @@ var ConsolidateWorker = class {
|
|
|
58282
58326
|
// HZ-footprint-cap — see pass-worker-client.ts for the contract.
|
|
58283
58327
|
resourceLimits: workerResourceLimits()
|
|
58284
58328
|
});
|
|
58329
|
+
noteIsolateSpawned();
|
|
58285
58330
|
this.worker = worker;
|
|
58286
58331
|
this.ready = new Promise((resolve6, reject) => {
|
|
58287
58332
|
const onReady = (m) => {
|
|
@@ -58314,7 +58359,10 @@ var ConsolidateWorker = class {
|
|
|
58314
58359
|
this.ready = null;
|
|
58315
58360
|
};
|
|
58316
58361
|
worker.on("error", onGone);
|
|
58317
|
-
worker.on("exit", () =>
|
|
58362
|
+
worker.on("exit", () => {
|
|
58363
|
+
noteIsolateExited();
|
|
58364
|
+
onGone();
|
|
58365
|
+
});
|
|
58318
58366
|
}
|
|
58319
58367
|
async stop() {
|
|
58320
58368
|
this.stopped = true;
|
|
@@ -58741,6 +58789,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
58741
58789
|
startLoopLagMonitor();
|
|
58742
58790
|
let baseUrl = "";
|
|
58743
58791
|
const records = [];
|
|
58792
|
+
const mountedIds = /* @__PURE__ */ new Set();
|
|
58744
58793
|
const machineDominantLanguage = () => {
|
|
58745
58794
|
const langCounts = /* @__PURE__ */ new Map();
|
|
58746
58795
|
for (const r of records) {
|
|
@@ -58851,7 +58900,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
58851
58900
|
fireBoundary();
|
|
58852
58901
|
}
|
|
58853
58902
|
});
|
|
58854
|
-
return { entry, engine, webApp, root: entry.path, id };
|
|
58903
|
+
return { entry, engine, webApp, root: entry.path, id, lastHookAt: Date.now() };
|
|
58855
58904
|
};
|
|
58856
58905
|
const pruned = pruneMissingWorkspaces();
|
|
58857
58906
|
if (pruned.length > 0) {
|
|
@@ -58885,7 +58934,10 @@ async function startMultiDaemon(opts = {}) {
|
|
|
58885
58934
|
}
|
|
58886
58935
|
records.push(rec);
|
|
58887
58936
|
void ambientLinkAll();
|
|
58888
|
-
|
|
58937
|
+
if (!mountedIds.has(rec.id)) {
|
|
58938
|
+
mountedIds.add(rec.id);
|
|
58939
|
+
app.route(`/ws/${rec.id}`, rec.webApp);
|
|
58940
|
+
}
|
|
58889
58941
|
try {
|
|
58890
58942
|
writeFileSync22(
|
|
58891
58943
|
rec.engine.paths.daemonLock,
|
|
@@ -59000,11 +59052,20 @@ async function startMultiDaemon(opts = {}) {
|
|
|
59000
59052
|
} catch {
|
|
59001
59053
|
return c.json({ error: "bad-json" }, 400);
|
|
59002
59054
|
}
|
|
59003
|
-
|
|
59055
|
+
let owner = ownerOf(records, pathInBody(body2));
|
|
59056
|
+
if (!owner) {
|
|
59057
|
+
const missPath = pathInBody(body2);
|
|
59058
|
+
const gitRoot = missPath ? findGitRoot(missPath) : null;
|
|
59059
|
+
if (gitRoot && attachWorkspace(gitRoot).attached) {
|
|
59060
|
+
owner = ownerOf(records, missPath) ?? null;
|
|
59061
|
+
if (owner) console.log(`[errata] woke idle workspace ${owner.entry.name}`);
|
|
59062
|
+
}
|
|
59063
|
+
}
|
|
59004
59064
|
if (!owner) {
|
|
59005
59065
|
rootAdopter.noteMiss(pathInBody(body2));
|
|
59006
59066
|
return c.json({ error: "no-matching-project" }, 404);
|
|
59007
59067
|
}
|
|
59068
|
+
owner.lastHookAt = Date.now();
|
|
59008
59069
|
const sub = c.req.path;
|
|
59009
59070
|
const done = markPass(`${sub}:${owner.entry.name}`);
|
|
59010
59071
|
try {
|
|
@@ -59040,7 +59101,37 @@ async function startMultiDaemon(opts = {}) {
|
|
|
59040
59101
|
app.post("/api/message", (c) => forward(c, cwdOf));
|
|
59041
59102
|
app.post("/api/session-end", (c) => forward(c, cwdOf));
|
|
59042
59103
|
app.post("/api/context-inject", (c) => forward(c, cwdOf));
|
|
59043
|
-
for (const r of records)
|
|
59104
|
+
for (const r of records) {
|
|
59105
|
+
mountedIds.add(r.id);
|
|
59106
|
+
app.route(`/ws/${r.id}`, r.webApp);
|
|
59107
|
+
}
|
|
59108
|
+
const retireWorkspace = async (rec, reason) => {
|
|
59109
|
+
const idx = records.indexOf(rec);
|
|
59110
|
+
if (idx === -1) return;
|
|
59111
|
+
records.splice(idx, 1);
|
|
59112
|
+
try {
|
|
59113
|
+
await rec.engine.stop();
|
|
59114
|
+
} catch (err2) {
|
|
59115
|
+
console.warn(`[errata] retire ${rec.entry.name}: engine.stop failed \u2014 ${err2 instanceof Error ? err2.message : err2}`);
|
|
59116
|
+
}
|
|
59117
|
+
console.log(
|
|
59118
|
+
`[errata] retired ${rec.entry.name} (${reason})` + (reason === "idle" ? " \u2014 idle; the next hook from it re-attaches" : "")
|
|
59119
|
+
);
|
|
59120
|
+
};
|
|
59121
|
+
const sweepIdleWorkspaces = () => {
|
|
59122
|
+
const now = Date.now();
|
|
59123
|
+
for (const rec of [...records]) {
|
|
59124
|
+
let lastActiveAt = rec.lastHookAt;
|
|
59125
|
+
try {
|
|
59126
|
+
lastActiveAt = Math.max(lastActiveAt, rec.engine.lastActivityAt());
|
|
59127
|
+
} catch {
|
|
59128
|
+
}
|
|
59129
|
+
const reason = retireDecision({ exists: existsSync29(rec.root), lastActiveAt, now });
|
|
59130
|
+
if (reason) void retireWorkspace(rec, reason);
|
|
59131
|
+
}
|
|
59132
|
+
};
|
|
59133
|
+
const idleSweep = setInterval(sweepIdleWorkspaces, WORKSPACE_SWEEP_INTERVAL_MS);
|
|
59134
|
+
idleSweep.unref?.();
|
|
59044
59135
|
const reindexAll = async (rOpts) => {
|
|
59045
59136
|
const out2 = /* @__PURE__ */ new Map();
|
|
59046
59137
|
const toIndex = records.filter((r) => rOpts?.force || r.engine.store.nodeCount() === 0);
|
|
@@ -59646,6 +59737,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
59646
59737
|
boundaryListeners.push(cb);
|
|
59647
59738
|
},
|
|
59648
59739
|
async stop() {
|
|
59740
|
+
clearInterval(idleSweep);
|
|
59649
59741
|
try {
|
|
59650
59742
|
const cur = readFileSync27(lockPath, "utf8");
|
|
59651
59743
|
if (JSON.parse(cur).pid === process.pid) unlinkSync3(lockPath);
|
|
@@ -60678,21 +60770,21 @@ async function cmdInit() {
|
|
|
60678
60770
|
if (!skipHooks) {
|
|
60679
60771
|
console.log("");
|
|
60680
60772
|
console.log("installing harness hooks...");
|
|
60681
|
-
const { existsSync:
|
|
60773
|
+
const { existsSync: existsSync31 } = await import("node:fs");
|
|
60682
60774
|
const { join: join33 } = await import("node:path");
|
|
60683
60775
|
try {
|
|
60684
60776
|
await installClaudeHooks(port);
|
|
60685
60777
|
} catch (err2) {
|
|
60686
60778
|
console.warn(` \u26A0\uFE0F Claude hook install failed: ${err2 instanceof Error ? err2.message : err2}`);
|
|
60687
60779
|
}
|
|
60688
|
-
if (
|
|
60780
|
+
if (existsSync31(join33(ROOT, ".cursor"))) {
|
|
60689
60781
|
try {
|
|
60690
60782
|
await installCursorMcpConfig();
|
|
60691
60783
|
} catch (err2) {
|
|
60692
60784
|
console.warn(` \u26A0\uFE0F Cursor MCP config failed: ${err2 instanceof Error ? err2.message : err2}`);
|
|
60693
60785
|
}
|
|
60694
60786
|
}
|
|
60695
|
-
if (
|
|
60787
|
+
if (existsSync31(join33(ROOT, ".codex"))) {
|
|
60696
60788
|
try {
|
|
60697
60789
|
await installCodexHooks(port);
|
|
60698
60790
|
} catch (err2) {
|
|
@@ -60849,9 +60941,9 @@ async function cmdStatus() {
|
|
|
60849
60941
|
console.log(` stack: ${profile.stack.join(", ") || "(none)"}`);
|
|
60850
60942
|
console.log(` languages: ${profile.languages.join(", ") || "(none)"}`);
|
|
60851
60943
|
}
|
|
60852
|
-
console.log(` graph db: ${
|
|
60853
|
-
console.log(` event log: ${
|
|
60854
|
-
if (
|
|
60944
|
+
console.log(` graph db: ${existsSync30(paths.castalia) ? "yes" : "no"} (${paths.castalia})`);
|
|
60945
|
+
console.log(` event log: ${existsSync30(paths.eventLog) ? "yes" : "no"} (${paths.eventLog})`);
|
|
60946
|
+
if (existsSync30(paths.castalia)) {
|
|
60855
60947
|
try {
|
|
60856
60948
|
const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src5(), src_exports2));
|
|
60857
60949
|
const store = openGraphStore2({ path: paths.castalia });
|
|
@@ -61532,7 +61624,7 @@ function cmdInstallationProfile(args2) {
|
|
|
61532
61624
|
}
|
|
61533
61625
|
async function cmdReview() {
|
|
61534
61626
|
const paths = workspacePaths(ROOT);
|
|
61535
|
-
if (!
|
|
61627
|
+
if (!existsSync30(paths.reviewQueue)) {
|
|
61536
61628
|
console.log("(review queue empty)");
|
|
61537
61629
|
return;
|
|
61538
61630
|
}
|
|
@@ -62207,7 +62299,7 @@ async function gatherRepo(store, ws) {
|
|
|
62207
62299
|
};
|
|
62208
62300
|
}
|
|
62209
62301
|
async function gatherReportData(generatedAt) {
|
|
62210
|
-
const { existsSync:
|
|
62302
|
+
const { existsSync: existsSync31 } = await import("node:fs");
|
|
62211
62303
|
const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src5(), src_exports2));
|
|
62212
62304
|
const cfg = loadConfig();
|
|
62213
62305
|
const outbound = cfg.consent.sync ? "auto" : "off";
|
|
@@ -62215,7 +62307,7 @@ async function gatherReportData(generatedAt) {
|
|
|
62215
62307
|
for (const ws of listWorkspaces()) {
|
|
62216
62308
|
if (ws.missing) continue;
|
|
62217
62309
|
const dbPath = workspacePaths(ws.path).castalia;
|
|
62218
|
-
if (!
|
|
62310
|
+
if (!existsSync31(dbPath)) continue;
|
|
62219
62311
|
let store = null;
|
|
62220
62312
|
try {
|
|
62221
62313
|
store = openGraphStore2({ path: dbPath });
|
|
@@ -62387,13 +62479,13 @@ function hookRelayCommand(port, path2) {
|
|
|
62387
62479
|
return process.platform === "win32" ? `cmd //c "curl -s --connect-timeout 1 --max-time 2 -X POST -H \\"Content-Type: application/json\\" --data-binary @- ${url2} 2>NUL || echo {}"` : `curl -s --connect-timeout 1 --max-time 2 -X POST -H 'Content-Type: application/json' --data-binary @- ${url2} 2>/dev/null || echo '{}'`;
|
|
62388
62480
|
}
|
|
62389
62481
|
async function installClaudeHooks(port) {
|
|
62390
|
-
const { mkdirSync: mkdirSync8, existsSync:
|
|
62482
|
+
const { mkdirSync: mkdirSync8, existsSync: existsSync31, readFileSync: readFileSync29, writeFileSync: writeFileSync23 } = await import("node:fs");
|
|
62391
62483
|
const { join: join33 } = await import("node:path");
|
|
62392
62484
|
const dir = join33(ROOT, ".claude");
|
|
62393
|
-
if (!
|
|
62485
|
+
if (!existsSync31(dir)) mkdirSync8(dir, { recursive: true });
|
|
62394
62486
|
const file2 = join33(dir, "settings.json");
|
|
62395
62487
|
let settings = {};
|
|
62396
|
-
if (
|
|
62488
|
+
if (existsSync31(file2)) {
|
|
62397
62489
|
try {
|
|
62398
62490
|
settings = JSON.parse(readFileSync29(file2, "utf8"));
|
|
62399
62491
|
} catch {
|
|
@@ -62456,13 +62548,13 @@ async function installClaudeHooks(port) {
|
|
|
62456
62548
|
console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
|
|
62457
62549
|
}
|
|
62458
62550
|
async function installClaudeMcpConfig() {
|
|
62459
|
-
const { mkdirSync: mkdirSync8, existsSync:
|
|
62551
|
+
const { mkdirSync: mkdirSync8, existsSync: existsSync31, readFileSync: readFileSync29, writeFileSync: writeFileSync23 } = await import("node:fs");
|
|
62460
62552
|
const { join: join33, dirname: dirname11 } = await import("node:path");
|
|
62461
62553
|
const file2 = join33(ROOT, ".mcp.json");
|
|
62462
62554
|
const dir = dirname11(file2);
|
|
62463
|
-
if (!
|
|
62555
|
+
if (!existsSync31(dir)) mkdirSync8(dir, { recursive: true });
|
|
62464
62556
|
let cfg = {};
|
|
62465
|
-
if (
|
|
62557
|
+
if (existsSync31(file2)) {
|
|
62466
62558
|
try {
|
|
62467
62559
|
cfg = JSON.parse(readFileSync29(file2, "utf8"));
|
|
62468
62560
|
} catch {
|
|
@@ -62478,13 +62570,13 @@ async function installClaudeMcpConfig() {
|
|
|
62478
62570
|
console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses / show / similar`);
|
|
62479
62571
|
}
|
|
62480
62572
|
async function installCursorMcpConfig() {
|
|
62481
|
-
const { mkdirSync: mkdirSync8, existsSync:
|
|
62573
|
+
const { mkdirSync: mkdirSync8, existsSync: existsSync31, readFileSync: readFileSync29, writeFileSync: writeFileSync23 } = await import("node:fs");
|
|
62482
62574
|
const { join: join33 } = await import("node:path");
|
|
62483
62575
|
const dir = join33(ROOT, ".cursor");
|
|
62484
|
-
if (!
|
|
62576
|
+
if (!existsSync31(dir)) mkdirSync8(dir, { recursive: true });
|
|
62485
62577
|
const file2 = join33(dir, "mcp.json");
|
|
62486
62578
|
let cfg = {};
|
|
62487
|
-
if (
|
|
62579
|
+
if (existsSync31(file2)) {
|
|
62488
62580
|
try {
|
|
62489
62581
|
cfg = JSON.parse(readFileSync29(file2, "utf8"));
|
|
62490
62582
|
} catch {
|
|
@@ -62502,15 +62594,15 @@ async function installCursorMcpConfig() {
|
|
|
62502
62594
|
console.log(` \u26A0\uFE0F reload Cursor (Cmd/Ctrl-Shift-P \u2192 "Reload Window") to pick it up.`);
|
|
62503
62595
|
}
|
|
62504
62596
|
async function installCodexHooks(port) {
|
|
62505
|
-
const { mkdirSync: mkdirSync8, existsSync:
|
|
62597
|
+
const { mkdirSync: mkdirSync8, existsSync: existsSync31, readFileSync: readFileSync29, writeFileSync: writeFileSync23 } = await import("node:fs");
|
|
62506
62598
|
const { join: join33 } = await import("node:path");
|
|
62507
62599
|
const dir = join33(ROOT, ".codex");
|
|
62508
|
-
if (!
|
|
62600
|
+
if (!existsSync31(dir)) mkdirSync8(dir, { recursive: true });
|
|
62509
62601
|
const file2 = join33(dir, "config.toml");
|
|
62510
62602
|
const BEGIN = `# >>> errata hooks (errata-managed)`;
|
|
62511
62603
|
const END = `# <<< errata hooks`;
|
|
62512
62604
|
let existing = "";
|
|
62513
|
-
if (
|
|
62605
|
+
if (existsSync31(file2)) {
|
|
62514
62606
|
existing = readFileSync29(file2, "utf8");
|
|
62515
62607
|
const beginIdx = existing.indexOf(BEGIN);
|
|
62516
62608
|
const endIdx = existing.indexOf(END);
|
|
@@ -62692,6 +62784,7 @@ function installLogTimestamps() {
|
|
|
62692
62784
|
}
|
|
62693
62785
|
}
|
|
62694
62786
|
async function cmdDash(args2) {
|
|
62787
|
+
process.title = "errata-daemon";
|
|
62695
62788
|
installLogTimestamps();
|
|
62696
62789
|
const portIdx = args2.indexOf("--port");
|
|
62697
62790
|
const port = portIdx >= 0 && args2[portIdx + 1] ? Number(args2[portIdx + 1]) : 7891;
|