@inerrata-corporation/errata 2.0.22-dev.4173 → 2.0.22-dev.4186
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/consolidate-worker.mjs +232 -28
- package/errata.mjs +822 -227
- package/generalize-worker.mjs +204 -27
- package/package.json +1 -1
- package/pass-worker.mjs +256 -36
- package/resources/context-plugin/.codex-plugin/plugin.json +1 -1
- package/resources/context-plugin/SHA256SUMS +1 -1
package/errata.mjs
CHANGED
|
@@ -18137,20 +18137,20 @@ function openDatabase(path3, opts) {
|
|
|
18137
18137
|
} catch {
|
|
18138
18138
|
}
|
|
18139
18139
|
}
|
|
18140
|
-
const wrapStmt = (
|
|
18140
|
+
const wrapStmt = (stmt2) => ({
|
|
18141
18141
|
run: (...params) => {
|
|
18142
|
-
const r =
|
|
18142
|
+
const r = stmt2.run(...coerceParams(params));
|
|
18143
18143
|
return {
|
|
18144
18144
|
changes: Number(r.changes),
|
|
18145
18145
|
lastInsertRowid: Number(r.lastInsertRowid)
|
|
18146
18146
|
};
|
|
18147
18147
|
},
|
|
18148
18148
|
get: (...params) => {
|
|
18149
|
-
const r =
|
|
18149
|
+
const r = stmt2.get(...coerceParams(params));
|
|
18150
18150
|
return r;
|
|
18151
18151
|
},
|
|
18152
18152
|
all: (...params) => {
|
|
18153
|
-
const r =
|
|
18153
|
+
const r = stmt2.all(...coerceParams(params));
|
|
18154
18154
|
return r;
|
|
18155
18155
|
}
|
|
18156
18156
|
});
|
|
@@ -19134,6 +19134,175 @@ var init_text_index = __esm({
|
|
|
19134
19134
|
}
|
|
19135
19135
|
});
|
|
19136
19136
|
|
|
19137
|
+
// ../../packages/local-graph/src/lineage-integrity.ts
|
|
19138
|
+
function stmt(db, sql) {
|
|
19139
|
+
let byDb = statements.get(db);
|
|
19140
|
+
if (!byDb) statements.set(db, byDb = /* @__PURE__ */ new Map());
|
|
19141
|
+
let s = byDb.get(sql);
|
|
19142
|
+
if (!s) byDb.set(sql, s = db.prepare(sql));
|
|
19143
|
+
return s;
|
|
19144
|
+
}
|
|
19145
|
+
function countStrandedEdges(db) {
|
|
19146
|
+
const rows = db.prepare(`SELECT e.type AS type, count(*) AS n FROM edges e WHERE ${STRANDED_EDGE_PREDICATE} GROUP BY e.type ORDER BY n DESC`).all();
|
|
19147
|
+
const byType = {};
|
|
19148
|
+
let total = 0;
|
|
19149
|
+
for (const r of rows) {
|
|
19150
|
+
byType[r.type] = Number(r.n);
|
|
19151
|
+
total += Number(r.n);
|
|
19152
|
+
}
|
|
19153
|
+
return { total, byType };
|
|
19154
|
+
}
|
|
19155
|
+
function countLiveHeadConflicts(db) {
|
|
19156
|
+
const row = db.prepare(
|
|
19157
|
+
`SELECT count(*) AS n FROM (
|
|
19158
|
+
SELECT COALESCE(logical_id, id) AS lid FROM nodes
|
|
19159
|
+
WHERE valid_to IS NULL AND ${NOT_HISTORICAL_ROW}
|
|
19160
|
+
GROUP BY lid HAVING count(*) > 1)`
|
|
19161
|
+
).get();
|
|
19162
|
+
return Number(row?.n ?? 0);
|
|
19163
|
+
}
|
|
19164
|
+
function closeIncidentEdges(db, id, t) {
|
|
19165
|
+
let closed = 0;
|
|
19166
|
+
for (const side of ["from_id", "to_id"]) {
|
|
19167
|
+
const r = stmt(db, `UPDATE edges SET valid_to = MAX(valid_from, ?) WHERE ${side} = ? AND valid_to IS NULL AND ${NOT_HISTORY}`).run(t, id);
|
|
19168
|
+
closed += Number(r.changes);
|
|
19169
|
+
}
|
|
19170
|
+
return closed;
|
|
19171
|
+
}
|
|
19172
|
+
function reopenCascadeClosedEdges(db, id, closedAt) {
|
|
19173
|
+
let reopened = 0;
|
|
19174
|
+
for (const [side, other] of [["from_id", "to_id"], ["to_id", "from_id"]]) {
|
|
19175
|
+
const r = stmt(
|
|
19176
|
+
db,
|
|
19177
|
+
`UPDATE edges SET valid_to = NULL
|
|
19178
|
+
WHERE ${side} = ? AND valid_to = ? AND ${NOT_HISTORY}
|
|
19179
|
+
AND EXISTS (SELECT 1 FROM nodes o WHERE o.id = edges.${other} AND o.valid_to IS NULL)`
|
|
19180
|
+
).run(id, closedAt);
|
|
19181
|
+
reopened += Number(r.changes);
|
|
19182
|
+
}
|
|
19183
|
+
return reopened;
|
|
19184
|
+
}
|
|
19185
|
+
function collapseLiveHeads(db, logicalIds, t) {
|
|
19186
|
+
const headsOf = db.prepare(
|
|
19187
|
+
`SELECT id, version, valid_from FROM (
|
|
19188
|
+
SELECT id, version, valid_from, attrs_json FROM nodes WHERE logical_id = ?1 AND valid_to IS NULL
|
|
19189
|
+
UNION
|
|
19190
|
+
SELECT id, version, valid_from, attrs_json FROM nodes WHERE id = ?1 AND logical_id IS NULL AND valid_to IS NULL
|
|
19191
|
+
) WHERE ${NOT_HISTORICAL_ROW}`
|
|
19192
|
+
);
|
|
19193
|
+
const continuesInto = db.prepare(
|
|
19194
|
+
`SELECT to_id FROM edges WHERE from_id = ? AND type = 'CONTINUES' AND valid_to IS NULL`
|
|
19195
|
+
);
|
|
19196
|
+
const rekeyHead = db.prepare(`UPDATE nodes SET logical_id = ?1 WHERE id = ?1`);
|
|
19197
|
+
const rekeyCopies = db.prepare(
|
|
19198
|
+
`UPDATE nodes SET logical_id = ?1 WHERE logical_id = ?2 AND substr(id, 1, length(?1) + 2) = ?1 || '@v'`
|
|
19199
|
+
);
|
|
19200
|
+
const lineageMembers = db.prepare(
|
|
19201
|
+
`SELECT id FROM nodes WHERE logical_id = ?1 UNION SELECT id FROM nodes WHERE id = ?1`
|
|
19202
|
+
);
|
|
19203
|
+
const closeContinues = db.prepare(
|
|
19204
|
+
`UPDATE edges SET valid_to = MAX(valid_from, ?) WHERE from_id = ? AND to_id = ? AND type = 'CONTINUES' AND valid_to IS NULL`
|
|
19205
|
+
);
|
|
19206
|
+
let split = 0;
|
|
19207
|
+
const queue = [...new Set(logicalIds)];
|
|
19208
|
+
for (let i2 = 0; i2 < queue.length; i2++) {
|
|
19209
|
+
const lid = queue[i2];
|
|
19210
|
+
const heads = headsOf.all(lid);
|
|
19211
|
+
if (heads.length < 2) continue;
|
|
19212
|
+
const members = new Set(lineageMembers.all(lid).map((r) => r.id));
|
|
19213
|
+
const splitOff = (h) => {
|
|
19214
|
+
for (const { to_id } of continuesInto.all(h.id)) {
|
|
19215
|
+
if (members.has(to_id)) closeContinues.run(t, h.id, to_id);
|
|
19216
|
+
}
|
|
19217
|
+
rekeyHead.run(h.id);
|
|
19218
|
+
rekeyCopies.run(h.id, lid);
|
|
19219
|
+
queue.push(h.id);
|
|
19220
|
+
split++;
|
|
19221
|
+
};
|
|
19222
|
+
const kept = new Set(heads.map((h) => h.id));
|
|
19223
|
+
for (const h of heads) {
|
|
19224
|
+
if (h.id === lid) continue;
|
|
19225
|
+
const refuted = continuesInto.all(h.id).some(
|
|
19226
|
+
(e) => e.to_id !== h.id && kept.has(e.to_id)
|
|
19227
|
+
);
|
|
19228
|
+
if (refuted && kept.size > 1) {
|
|
19229
|
+
splitOff(h);
|
|
19230
|
+
kept.delete(h.id);
|
|
19231
|
+
}
|
|
19232
|
+
}
|
|
19233
|
+
let remaining = heads.filter((h) => kept.has(h.id));
|
|
19234
|
+
if (remaining.length < 2) continue;
|
|
19235
|
+
remaining = [...remaining].sort(
|
|
19236
|
+
(a, b) => Number(b.id === lid) - Number(a.id === lid) || Number(b.version) - Number(a.version) || Number(b.valid_from) - Number(a.valid_from) || (a.id < b.id ? -1 : 1)
|
|
19237
|
+
);
|
|
19238
|
+
for (const h of remaining.slice(1)) splitOff(h);
|
|
19239
|
+
}
|
|
19240
|
+
return split;
|
|
19241
|
+
}
|
|
19242
|
+
function repairLineageIntegrity(db, now) {
|
|
19243
|
+
const historicalRowsClosed = Number(
|
|
19244
|
+
db.prepare(
|
|
19245
|
+
`UPDATE nodes SET valid_to = MAX(valid_from, COALESCE(
|
|
19246
|
+
(SELECT s.valid_from FROM edges s WHERE s.id = 'edge_superseded_' || nodes.id), ?))
|
|
19247
|
+
WHERE valid_to IS NULL AND json_type(attrs_json, '$.historical') = 'true'`
|
|
19248
|
+
).run(now).changes
|
|
19249
|
+
);
|
|
19250
|
+
const conflicted = db.prepare(
|
|
19251
|
+
`SELECT COALESCE(logical_id, id) AS lid FROM nodes
|
|
19252
|
+
WHERE valid_to IS NULL AND ${NOT_HISTORICAL_ROW}
|
|
19253
|
+
GROUP BY lid HAVING count(*) > 1`
|
|
19254
|
+
).all().map((r) => r.lid);
|
|
19255
|
+
const headsSplit = collapseLiveHeads(db, conflicted, now);
|
|
19256
|
+
const strandedEdgesClosed = Number(
|
|
19257
|
+
db.prepare(
|
|
19258
|
+
`UPDATE edges SET valid_to = MAX(valid_from, COALESCE(
|
|
19259
|
+
(SELECT min(v) FROM (
|
|
19260
|
+
SELECT f.valid_to AS v FROM nodes f WHERE f.id = edges.from_id AND NOT ${PRESENT("f")}
|
|
19261
|
+
UNION ALL
|
|
19262
|
+
SELECT t.valid_to FROM nodes t WHERE t.id = edges.to_id AND NOT ${PRESENT("t")})), ?))
|
|
19263
|
+
WHERE id IN (SELECT e.id FROM edges e WHERE ${STRANDED_EDGE_PREDICATE})`
|
|
19264
|
+
).run(now).changes
|
|
19265
|
+
);
|
|
19266
|
+
return { historicalRowsClosed, headsSplit, strandedEdgesClosed };
|
|
19267
|
+
}
|
|
19268
|
+
function installLineageIntegrityRepair(db, now = Date.now()) {
|
|
19269
|
+
if (db.prepare("SELECT value FROM store_meta WHERE key = ?").get(LINEAGE_INTEGRITY_KEY)) return null;
|
|
19270
|
+
return db.transaction(() => {
|
|
19271
|
+
const report = repairLineageIntegrity(db, now);
|
|
19272
|
+
db.prepare("INSERT OR REPLACE INTO store_meta (key, value) VALUES (?, ?)").run(
|
|
19273
|
+
LINEAGE_INTEGRITY_KEY,
|
|
19274
|
+
JSON.stringify({ at: now, ...report })
|
|
19275
|
+
);
|
|
19276
|
+
return report;
|
|
19277
|
+
});
|
|
19278
|
+
}
|
|
19279
|
+
var statements, HISTORY_EDGE_TYPES, LINEAGE_INTEGRITY_KEY, HISTORY_SQL, NOT_HISTORY, NOT_HISTORICAL_ROW, RETAINS_EDGES, PRESENT, STRANDED_EDGE_PREDICATE;
|
|
19280
|
+
var init_lineage_integrity = __esm({
|
|
19281
|
+
"../../packages/local-graph/src/lineage-integrity.ts"() {
|
|
19282
|
+
"use strict";
|
|
19283
|
+
statements = /* @__PURE__ */ new WeakMap();
|
|
19284
|
+
HISTORY_EDGE_TYPES = [
|
|
19285
|
+
"SUPERSEDED_BY",
|
|
19286
|
+
"CONTINUES",
|
|
19287
|
+
"FORKED_FROM",
|
|
19288
|
+
"REGRESSION_OF",
|
|
19289
|
+
"SPLIT_INTO",
|
|
19290
|
+
"REVEALED_BY"
|
|
19291
|
+
];
|
|
19292
|
+
LINEAGE_INTEGRITY_KEY = "lineage-integrity-v1";
|
|
19293
|
+
HISTORY_SQL = HISTORY_EDGE_TYPES.map((t) => `'${t}'`).join(",");
|
|
19294
|
+
NOT_HISTORY = `type NOT IN (${HISTORY_SQL})`;
|
|
19295
|
+
NOT_HISTORICAL_ROW = `json_type(attrs_json, '$.historical') IS NOT 'true'`;
|
|
19296
|
+
RETAINS_EDGES = (n) => `(${n}.label = 'Problem'
|
|
19297
|
+
AND json_type(${n}.attrs_json, '$.resolvedAt') IS NOT NULL
|
|
19298
|
+
AND COALESCE(json_extract(${n}.attrs_json, '$.resolvedAs'), '') NOT IN ('duplicate', 'false_positive'))`;
|
|
19299
|
+
PRESENT = (n) => `(${n}.valid_to IS NULL OR ${RETAINS_EDGES(n)})`;
|
|
19300
|
+
STRANDED_EDGE_PREDICATE = `e.valid_to IS NULL AND e.${NOT_HISTORY}
|
|
19301
|
+
AND (NOT EXISTS (SELECT 1 FROM nodes f WHERE f.id = e.from_id AND ${PRESENT("f")})
|
|
19302
|
+
OR NOT EXISTS (SELECT 1 FROM nodes t WHERE t.id = e.to_id AND ${PRESENT("t")}))`;
|
|
19303
|
+
}
|
|
19304
|
+
});
|
|
19305
|
+
|
|
19137
19306
|
// ../../packages/math/src/constants.ts
|
|
19138
19307
|
var SURPRISE_MOMENTUM, SURPRISE_LEARNING_RATE, SURPRISE_LEARNING_RATE_SCALING, TIER_HALFLIFE_MULTIPLIER, HIT_RATE_SCALING_ALPHA, BASE_HALF_LIFE_SEQ, MOMENTUM_GATE_FLOOR, SURPRISE_RECENCY_LAMBDA_SEQ, NEMORI_SOFT_WRITE_MIN_COSINE, NEMORI_SOFT_WRITE_MAX_COSINE, NEMORI_DEDUP_COSINE, NEMORI_SOFT_ALPHA_MIN, NEMORI_SOFT_ALPHA_MAX, NEMORI_HIGH_SURPRISE_THRESHOLD, NEMORI_PREDICTION_FLOOR, REVIEW_SURPRISE_THRESHOLD, REVIEW_HITS_THRESHOLD;
|
|
19139
19308
|
var init_constants = __esm({
|
|
@@ -20219,7 +20388,7 @@ function graphStoreNeedsPreparation(path3) {
|
|
|
20219
20388
|
for (const match2 of (SCHEMA_SQL + TEMPORAL_INDEX_SQL).matchAll(/CREATE INDEX IF NOT EXISTS (\w+)/g)) {
|
|
20220
20389
|
if (!indexes.has(match2[1])) return true;
|
|
20221
20390
|
}
|
|
20222
|
-
return [SESSION_REPAIR_KEY, HISTORY_CACHE_FLOOR_KEY, EDIT_PLACEHOLDER_FLOOR_KEY, CLOUD_ATTR_COMPACTION_KEY, HISTORY_ATTR_SLIM_KEY, TEXT_INDEX_KEY].some((key) => !db.prepare("SELECT value FROM store_meta WHERE key = ?").get(key));
|
|
20391
|
+
return [SESSION_REPAIR_KEY, HISTORY_CACHE_FLOOR_KEY, EDIT_PLACEHOLDER_FLOOR_KEY, CLOUD_ATTR_COMPACTION_KEY, HISTORY_ATTR_SLIM_KEY, TEXT_INDEX_KEY, LINEAGE_INTEGRITY_KEY].some((key) => !db.prepare("SELECT value FROM store_meta WHERE key = ?").get(key));
|
|
20223
20392
|
} catch {
|
|
20224
20393
|
return true;
|
|
20225
20394
|
} finally {
|
|
@@ -20298,6 +20467,7 @@ var init_store = __esm({
|
|
|
20298
20467
|
init_cloud_attr_compaction();
|
|
20299
20468
|
init_history_attr_slim();
|
|
20300
20469
|
init_text_index();
|
|
20470
|
+
init_lineage_integrity();
|
|
20301
20471
|
init_src3();
|
|
20302
20472
|
init_node_select();
|
|
20303
20473
|
PAGE_RANK_SCALE_KEY = "pageRankScale.p95.v1";
|
|
@@ -20523,6 +20693,7 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
20523
20693
|
this.db.prepare("INSERT OR REPLACE INTO store_meta (key, value) VALUES (?, 'done')").run(SESSION_REPAIR_KEY);
|
|
20524
20694
|
});
|
|
20525
20695
|
}
|
|
20696
|
+
installLineageIntegrityRepair(this.db);
|
|
20526
20697
|
this.stmts = {
|
|
20527
20698
|
insertNode: this.db.prepare(`
|
|
20528
20699
|
INSERT INTO nodes (
|
|
@@ -20733,6 +20904,12 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
20733
20904
|
AND (t.id IS NULL OR t.valid_to IS NOT NULL)
|
|
20734
20905
|
`).all();
|
|
20735
20906
|
}
|
|
20907
|
+
strandedEdges() {
|
|
20908
|
+
return countStrandedEdges(this.db);
|
|
20909
|
+
}
|
|
20910
|
+
liveHeadConflicts() {
|
|
20911
|
+
return countLiveHeadConflicts(this.db);
|
|
20912
|
+
}
|
|
20736
20913
|
fileIndexStates(ids) {
|
|
20737
20914
|
if (ids.length === 0) return [];
|
|
20738
20915
|
if (ids.length > 500) throw new RangeError("fileIndexStates accepts at most 500 ids per read");
|
|
@@ -20901,15 +21078,15 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
20901
21078
|
findNodeFieldsByLabel(label, attrKeys) {
|
|
20902
21079
|
for (const k of attrKeys) if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(k)) throw new Error(`findNodeFieldsByLabel: bad attr key ${k}`);
|
|
20903
21080
|
const cacheKey2 = attrKeys.join(",");
|
|
20904
|
-
let
|
|
20905
|
-
if (!
|
|
21081
|
+
let stmt2 = this.fieldStmts.get(cacheKey2);
|
|
21082
|
+
if (!stmt2) {
|
|
20906
21083
|
const cols = attrKeys.map((k, i2) => `, ${attrValueSql(`'$.${k}'`)} AS a${i2}, json_type(attrs_json, '$.${k}') AS t${i2}`).join("");
|
|
20907
|
-
|
|
21084
|
+
stmt2 = this.db.prepare(
|
|
20908
21085
|
`SELECT id, description, community, extraction_confidence${cols} FROM nodes WHERE label = ? AND valid_to IS NULL`
|
|
20909
21086
|
);
|
|
20910
|
-
this.fieldStmts.set(cacheKey2,
|
|
21087
|
+
this.fieldStmts.set(cacheKey2, stmt2);
|
|
20911
21088
|
}
|
|
20912
|
-
return
|
|
21089
|
+
return stmt2.all(label).map((r) => {
|
|
20913
21090
|
const attrs = {};
|
|
20914
21091
|
attrKeys.forEach((k, i2) => {
|
|
20915
21092
|
const v = decodeAttr(r[`a${i2}`], r[`t${i2}`]);
|
|
@@ -21029,14 +21206,14 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
21029
21206
|
}
|
|
21030
21207
|
nodeLabels(ids) {
|
|
21031
21208
|
const width = NODE_LABELS_CHUNK;
|
|
21032
|
-
const
|
|
21209
|
+
const stmt2 = this.typedEdgeStmt(
|
|
21033
21210
|
`SELECT id, label FROM nodes WHERE id IN (${Array.from({ length: width }, () => "?").join(",")})`
|
|
21034
21211
|
);
|
|
21035
21212
|
const labels = /* @__PURE__ */ new Map();
|
|
21036
21213
|
for (let i2 = 0; i2 < ids.length; i2 += width) {
|
|
21037
21214
|
const chunk = ids.slice(i2, i2 + width);
|
|
21038
21215
|
while (chunk.length < width) chunk.push(null);
|
|
21039
|
-
for (const row of
|
|
21216
|
+
for (const row of stmt2.all(...chunk)) labels.set(row.id, row.label);
|
|
21040
21217
|
}
|
|
21041
21218
|
return labels;
|
|
21042
21219
|
}
|
|
@@ -21235,12 +21412,12 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
21235
21412
|
return scale;
|
|
21236
21413
|
}
|
|
21237
21414
|
typedEdgeStmt(sql) {
|
|
21238
|
-
let
|
|
21239
|
-
if (!
|
|
21240
|
-
|
|
21241
|
-
this.typedEdgeStmts.set(sql,
|
|
21415
|
+
let stmt2 = this.typedEdgeStmts.get(sql);
|
|
21416
|
+
if (!stmt2) {
|
|
21417
|
+
stmt2 = this.db.prepare(sql);
|
|
21418
|
+
this.typedEdgeStmts.set(sql, stmt2);
|
|
21242
21419
|
}
|
|
21243
|
-
return
|
|
21420
|
+
return stmt2;
|
|
21244
21421
|
}
|
|
21245
21422
|
outEdges(nodeId, types) {
|
|
21246
21423
|
if (!types || types.length === 0) {
|
|
@@ -21441,22 +21618,28 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
21441
21618
|
}
|
|
21442
21619
|
}
|
|
21443
21620
|
reviveReobserved(relPaths, workspaceId2, since) {
|
|
21444
|
-
|
|
21621
|
+
const revived = [];
|
|
21445
21622
|
const CHUNK2 = 400;
|
|
21446
21623
|
for (let i2 = 0; i2 < relPaths.length; i2 += CHUNK2) {
|
|
21447
21624
|
const slice = relPaths.slice(i2, i2 + CHUNK2);
|
|
21448
21625
|
if (slice.length === 0) continue;
|
|
21449
|
-
const
|
|
21450
|
-
`
|
|
21626
|
+
const rows = this.db.prepare(
|
|
21627
|
+
`SELECT id, valid_to AS closedAt, COALESCE(logical_id, id) AS lid FROM nodes
|
|
21451
21628
|
WHERE valid_to IS NOT NULL
|
|
21452
21629
|
AND last_updated_at >= ?
|
|
21453
21630
|
AND json_extract(attrs_json, '$.workspaceId') = ?
|
|
21454
|
-
AND json_extract(attrs_json, '$.relPath') IN (${slice.map(() => "?").join(",")})
|
|
21455
|
-
|
|
21456
|
-
|
|
21457
|
-
|
|
21458
|
-
|
|
21459
|
-
return
|
|
21631
|
+
AND json_extract(attrs_json, '$.relPath') IN (${slice.map(() => "?").join(",")})
|
|
21632
|
+
AND json_type(attrs_json, '$.historical') IS NOT 'true'`
|
|
21633
|
+
).all(since, workspaceId2, ...slice);
|
|
21634
|
+
revived.push(...rows);
|
|
21635
|
+
}
|
|
21636
|
+
if (revived.length === 0) return 0;
|
|
21637
|
+
const reopen = this.db.prepare("UPDATE nodes SET valid_to = NULL WHERE id = ? AND valid_to IS NOT NULL");
|
|
21638
|
+
for (const r of revived) reopen.run(r.id);
|
|
21639
|
+
for (const r of revived) reopenCascadeClosedEdges(this.db, r.id, Number(r.closedAt));
|
|
21640
|
+
collapseLiveHeads(this.db, revived.map((r) => r.lid), since);
|
|
21641
|
+
this.mutations++;
|
|
21642
|
+
return revived.length;
|
|
21460
21643
|
}
|
|
21461
21644
|
incomingEdgeCoverage(label, edgeTypes, cloudOnly) {
|
|
21462
21645
|
if (edgeTypes.length === 0) return { count: 0, total: 0 };
|
|
@@ -21602,8 +21785,9 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
21602
21785
|
this.stmts.advanceLive.run({ live_id: liveId, t });
|
|
21603
21786
|
return frozenId;
|
|
21604
21787
|
}
|
|
21605
|
-
closeNode(id, t) {
|
|
21606
|
-
this.stmts.closeNode.run({ id, t });
|
|
21788
|
+
closeNode(id, t, opts = {}) {
|
|
21789
|
+
const r = this.stmts.closeNode.run({ id, t });
|
|
21790
|
+
if (Number(r.changes) > 0 && !opts.retainEdges) closeIncidentEdges(this.db, id, t);
|
|
21607
21791
|
}
|
|
21608
21792
|
closeEdge(id, t) {
|
|
21609
21793
|
this.stmts.closeEdge.run({ id, t });
|
|
@@ -23579,7 +23763,7 @@ function reinforceSameAnchorProblem(store, relPath, workspaceId2, statement, sou
|
|
|
23579
23763
|
}
|
|
23580
23764
|
function foldSameAnchorProblem(store, relPath, workspaceId2, statement, source, ts, kind = "problem") {
|
|
23581
23765
|
const report = { ...EMPTY_FOLD_REPORT };
|
|
23582
|
-
const
|
|
23766
|
+
const stmt2 = statement.trim();
|
|
23583
23767
|
if (!isAnchorableCodePath(relPath)) {
|
|
23584
23768
|
report.noFile = true;
|
|
23585
23769
|
return report;
|
|
@@ -23589,7 +23773,7 @@ function foldSameAnchorProblem(store, relPath, workspaceId2, statement, source,
|
|
|
23589
23773
|
report.noFile = true;
|
|
23590
23774
|
return report;
|
|
23591
23775
|
}
|
|
23592
|
-
const selfId = identityId({ kind: "DesignProblem", statement:
|
|
23776
|
+
const selfId = identityId({ kind: "DesignProblem", statement: stmt2 });
|
|
23593
23777
|
let stmtVec = null;
|
|
23594
23778
|
let best = null;
|
|
23595
23779
|
let bestScout = null;
|
|
@@ -23603,11 +23787,11 @@ function foldSameAnchorProblem(store, relPath, workspaceId2, statement, source,
|
|
|
23603
23787
|
continue;
|
|
23604
23788
|
}
|
|
23605
23789
|
report.candidates++;
|
|
23606
|
-
const score2 = tokenJaccard(
|
|
23790
|
+
const score2 = tokenJaccard(stmt2, cand.description);
|
|
23607
23791
|
if (score2 > report.bestJaccard) report.bestJaccard = score2;
|
|
23608
23792
|
if (score2 >= SAME_ANCHOR_DEDUP_JACCARD && (!best || score2 > best.score)) best = { node: cand, score: score2 };
|
|
23609
23793
|
if (!best) {
|
|
23610
|
-
stmtVec ??= embed(
|
|
23794
|
+
stmtVec ??= embed(stmt2);
|
|
23611
23795
|
const hc = cosine(stmtVec, embed(cand.description));
|
|
23612
23796
|
if (hc > report.bestHashCos) report.bestHashCos = hc;
|
|
23613
23797
|
if ((hc >= SAME_ANCHOR_SCOUT_MIN_COSINE || score2 >= SAME_ANCHOR_NOMINATE_JACCARD) && (!bestScout || hc > bestScout.hashCos)) {
|
|
@@ -23654,11 +23838,11 @@ function foldSameAnchorProblem(store, relPath, workspaceId2, statement, source,
|
|
|
23654
23838
|
return report;
|
|
23655
23839
|
}
|
|
23656
23840
|
function findResolvedAnchorMatch(store, relPath, workspaceId2, statement, kind = "problem") {
|
|
23657
|
-
const
|
|
23841
|
+
const stmt2 = statement.trim();
|
|
23658
23842
|
if (!isAnchorableCodePath(relPath)) return null;
|
|
23659
23843
|
const file2 = resolveFileNode(store, relPath, workspaceId2);
|
|
23660
23844
|
if (!file2) return null;
|
|
23661
|
-
const selfId = identityId({ kind: "DesignProblem", statement:
|
|
23845
|
+
const selfId = identityId({ kind: "DesignProblem", statement: stmt2 });
|
|
23662
23846
|
let best = null;
|
|
23663
23847
|
for (const e of store.inEdges(file2.id, ["ANCHORED_AT"])) {
|
|
23664
23848
|
const cand = store.getNode(e.from);
|
|
@@ -23668,7 +23852,7 @@ function findResolvedAnchorMatch(store, relPath, workspaceId2, statement, kind =
|
|
|
23668
23852
|
if (cand.id === selfId) continue;
|
|
23669
23853
|
const candKind = cand.attrs["kind"] === "constraint" ? "constraint" : "problem";
|
|
23670
23854
|
if (candKind !== (kind === "constraint" ? "constraint" : "problem")) continue;
|
|
23671
|
-
const score2 = tokenJaccard(
|
|
23855
|
+
const score2 = tokenJaccard(stmt2, cand.description);
|
|
23672
23856
|
if (score2 >= SAME_ANCHOR_DEDUP_JACCARD && (!best || score2 > best.score)) {
|
|
23673
23857
|
best = { id: cand.id, score: score2 };
|
|
23674
23858
|
}
|
|
@@ -26042,6 +26226,20 @@ function clearCandidate(store, node2, ts, rejectTargetId) {
|
|
|
26042
26226
|
}
|
|
26043
26227
|
store.updateNode(node2.id, { attrs, lastUpdatedAt: ts });
|
|
26044
26228
|
}
|
|
26229
|
+
function markStanding(store, node2, mark, reason, ts) {
|
|
26230
|
+
const stamped = {
|
|
26231
|
+
...mark,
|
|
26232
|
+
examinedAtSeq: store.currentIngestSeq(),
|
|
26233
|
+
examinations: (mark.examinations ?? 0) + 1,
|
|
26234
|
+
standingReason: reason
|
|
26235
|
+
};
|
|
26236
|
+
store.updateNode(node2.id, { attrs: { ...node2.attrs, foldCandidate: stamped }, lastUpdatedAt: ts });
|
|
26237
|
+
}
|
|
26238
|
+
function foldCandidateEligible(mark, currentSeq, judgeConfigured) {
|
|
26239
|
+
if (mark.examinedAtSeq === void 0) return true;
|
|
26240
|
+
if (mark.standingReason === "no-judge" && judgeConfigured) return true;
|
|
26241
|
+
return currentSeq - mark.examinedAtSeq >= FOLD_REEXAMINE_SEQ;
|
|
26242
|
+
}
|
|
26045
26243
|
async function resolveFoldCandidates(store, opts) {
|
|
26046
26244
|
const report = {
|
|
26047
26245
|
examined: 0,
|
|
@@ -26051,10 +26249,17 @@ async function resolveFoldCandidates(store, opts) {
|
|
|
26051
26249
|
rejected: 0,
|
|
26052
26250
|
standing: 0,
|
|
26053
26251
|
judgeErrors: 0,
|
|
26054
|
-
retargeted: 0
|
|
26252
|
+
retargeted: 0,
|
|
26253
|
+
pending: 0,
|
|
26254
|
+
neverExamined: 0,
|
|
26255
|
+
firstExamined: 0,
|
|
26256
|
+
waiting: 0,
|
|
26257
|
+
judgeBudgetDeferred: 0
|
|
26055
26258
|
};
|
|
26056
|
-
const limit = opts.limit ??
|
|
26057
|
-
const
|
|
26259
|
+
const limit = opts.limit ?? FOLD_EXAMINE_LIMIT;
|
|
26260
|
+
const judgeBudget = opts.judgeBudget ?? FOLD_JUDGE_BUDGET;
|
|
26261
|
+
const currentSeq = store.currentIngestSeq();
|
|
26262
|
+
const pool = store.selectNodes({
|
|
26058
26263
|
labels: ["Problem"],
|
|
26059
26264
|
attrs: ["foldCandidate"],
|
|
26060
26265
|
where: [
|
|
@@ -26062,16 +26267,35 @@ async function resolveFoldCandidates(store, opts) {
|
|
|
26062
26267
|
{ attr: "mergedInto", absent: true },
|
|
26063
26268
|
{ attr: "foldCandidate", present: true }
|
|
26064
26269
|
]
|
|
26065
|
-
})
|
|
26066
|
-
|
|
26067
|
-
|
|
26068
|
-
|
|
26270
|
+
});
|
|
26271
|
+
const markOf = (n) => n.attrs["foldCandidate"];
|
|
26272
|
+
report.pending = pool.length;
|
|
26273
|
+
let neverExamined = pool.filter((n) => markOf(n).examinedAtSeq === void 0).length;
|
|
26274
|
+
const eligible = pool.filter((n) => foldCandidateEligible(markOf(n), currentSeq, !!opts.judge));
|
|
26275
|
+
report.waiting = pool.length - eligible.length;
|
|
26276
|
+
const marked = eligible.sort((a, b) => {
|
|
26277
|
+
const ma = markOf(a);
|
|
26278
|
+
const mb = markOf(b);
|
|
26279
|
+
const ea = ma.examinedAtSeq ?? -1;
|
|
26280
|
+
const eb = mb.examinedAtSeq ?? -1;
|
|
26281
|
+
if (ea !== eb) return ea - eb;
|
|
26282
|
+
return (ma.ts ?? 0) - (mb.ts ?? 0);
|
|
26069
26283
|
}).slice(0, limit);
|
|
26284
|
+
let judgeCalls = 0;
|
|
26285
|
+
const unseenMark = (n) => {
|
|
26286
|
+
const m = n.attrs["foldCandidate"];
|
|
26287
|
+
return m !== void 0 && m.examinedAtSeq === void 0;
|
|
26288
|
+
};
|
|
26070
26289
|
for (const node2 of marked) {
|
|
26071
26290
|
const fresh = store.getNode(node2.id);
|
|
26072
26291
|
if (!openProblem(fresh)) continue;
|
|
26073
|
-
report.examined++;
|
|
26074
26292
|
const mark = fresh.attrs["foldCandidate"];
|
|
26293
|
+
const firstLook = mark.examinedAtSeq === void 0;
|
|
26294
|
+
report.examined++;
|
|
26295
|
+
if (firstLook) {
|
|
26296
|
+
report.firstExamined++;
|
|
26297
|
+
neverExamined--;
|
|
26298
|
+
}
|
|
26075
26299
|
let target = followMerges(store, mark.targetId);
|
|
26076
26300
|
if (target && target.id !== mark.targetId) report.retargeted++;
|
|
26077
26301
|
if (!openProblem(target)) {
|
|
@@ -26089,6 +26313,7 @@ async function resolveFoldCandidates(store, opts) {
|
|
|
26089
26313
|
cos = cosine(fresh.embedding, target.embedding);
|
|
26090
26314
|
}
|
|
26091
26315
|
if (cos !== null && cos >= FOLD_EMBED_AUTO_COSINE) {
|
|
26316
|
+
if (unseenMark(target)) neverExamined--;
|
|
26092
26317
|
foldPair(store, fresh, target, opts.ts);
|
|
26093
26318
|
report.folded++;
|
|
26094
26319
|
report.foldedEmbedding++;
|
|
@@ -26100,9 +26325,20 @@ async function resolveFoldCandidates(store, opts) {
|
|
|
26100
26325
|
continue;
|
|
26101
26326
|
}
|
|
26102
26327
|
if (!opts.judge) {
|
|
26328
|
+
markStanding(store, fresh, mark, "no-judge", opts.ts);
|
|
26103
26329
|
report.standing++;
|
|
26104
26330
|
continue;
|
|
26105
26331
|
}
|
|
26332
|
+
if (judgeCalls >= judgeBudget) {
|
|
26333
|
+
report.examined--;
|
|
26334
|
+
if (firstLook) {
|
|
26335
|
+
report.firstExamined--;
|
|
26336
|
+
neverExamined++;
|
|
26337
|
+
}
|
|
26338
|
+
report.judgeBudgetDeferred++;
|
|
26339
|
+
continue;
|
|
26340
|
+
}
|
|
26341
|
+
judgeCalls++;
|
|
26106
26342
|
let verdict = null;
|
|
26107
26343
|
try {
|
|
26108
26344
|
verdict = await opts.judge(fresh.description, target.description);
|
|
@@ -26110,6 +26346,7 @@ async function resolveFoldCandidates(store, opts) {
|
|
|
26110
26346
|
verdict = null;
|
|
26111
26347
|
}
|
|
26112
26348
|
if (verdict === "same") {
|
|
26349
|
+
if (unseenMark(target)) neverExamined--;
|
|
26113
26350
|
foldPair(store, fresh, target, opts.ts);
|
|
26114
26351
|
report.folded++;
|
|
26115
26352
|
report.foldedJudge++;
|
|
@@ -26117,10 +26354,12 @@ async function resolveFoldCandidates(store, opts) {
|
|
|
26117
26354
|
clearCandidate(store, fresh, opts.ts, target.id);
|
|
26118
26355
|
report.rejected++;
|
|
26119
26356
|
} else {
|
|
26357
|
+
markStanding(store, fresh, mark, "judge-error", opts.ts);
|
|
26120
26358
|
report.judgeErrors++;
|
|
26121
26359
|
report.standing++;
|
|
26122
26360
|
}
|
|
26123
26361
|
}
|
|
26362
|
+
report.neverExamined = neverExamined;
|
|
26124
26363
|
return report;
|
|
26125
26364
|
}
|
|
26126
26365
|
function foldPair(store, a, b, ts) {
|
|
@@ -26135,7 +26374,7 @@ function foldPair(store, a, b, ts) {
|
|
|
26135
26374
|
if (!freshSurvivor || !freshDup) return;
|
|
26136
26375
|
foldDuplicateProblem(store, freshDup, freshSurvivor, ts);
|
|
26137
26376
|
}
|
|
26138
|
-
var FOLD_SCOUT_AUTO_COSINE, FOLD_SCOUT_MIN_COSINE, FOLD_SCOUT_MIN_JACCARD, FOLD_EMBED_AUTO_COSINE, FOLD_JUDGE_MIN_COSINE, FOLD_REJECTED_CAP, WORKSPACE_SCAN_CAP, openProblem;
|
|
26377
|
+
var FOLD_SCOUT_AUTO_COSINE, FOLD_SCOUT_MIN_COSINE, FOLD_SCOUT_MIN_JACCARD, FOLD_EMBED_AUTO_COSINE, FOLD_JUDGE_MIN_COSINE, FOLD_REJECTED_CAP, FOLD_REEXAMINE_SEQ, FOLD_EXAMINE_LIMIT, FOLD_JUDGE_BUDGET, WORKSPACE_SCAN_CAP, openProblem;
|
|
26139
26378
|
var init_fold_candidates = __esm({
|
|
26140
26379
|
"../../packages/local-graph/src/fold-candidates.ts"() {
|
|
26141
26380
|
"use strict";
|
|
@@ -26148,6 +26387,9 @@ var init_fold_candidates = __esm({
|
|
|
26148
26387
|
FOLD_EMBED_AUTO_COSINE = 0.88;
|
|
26149
26388
|
FOLD_JUDGE_MIN_COSINE = 0.5;
|
|
26150
26389
|
FOLD_REJECTED_CAP = 8;
|
|
26390
|
+
FOLD_REEXAMINE_SEQ = 100;
|
|
26391
|
+
FOLD_EXAMINE_LIMIT = 32;
|
|
26392
|
+
FOLD_JUDGE_BUDGET = 8;
|
|
26151
26393
|
WORKSPACE_SCAN_CAP = 400;
|
|
26152
26394
|
openProblem = (n) => !!n && n.label === "Problem" && n.attrs["resolvedAt"] == null && n.attrs["mergedInto"] === void 0;
|
|
26153
26395
|
}
|
|
@@ -26606,6 +26848,28 @@ var init_mechanism_liveness = __esm({
|
|
|
26606
26848
|
// climbs while `accepted` stays flat is the shape of a silently-closed door.
|
|
26607
26849
|
backlogCounter: "candidates"
|
|
26608
26850
|
},
|
|
26851
|
+
{
|
|
26852
|
+
id: "edge-park-replay",
|
|
26853
|
+
what: "parks causal/anchor edges the door refused as unresolvable, replays them when due, drops them with a disposition",
|
|
26854
|
+
pass: "ship",
|
|
26855
|
+
// FED = a source whose whole binding-edge family LANDED: the digest is
|
|
26856
|
+
// stamped only when every edge in it came back created/reinforced, so it is
|
|
26857
|
+
// the store-side proof that edges (not just nodes) cross. Live dev
|
|
26858
|
+
// 2026-10-12 sat with the same 241 refusals re-sent every drain and this
|
|
26859
|
+
// stamp frozen — nodes crossed, their causal wiring did not.
|
|
26860
|
+
fed: {
|
|
26861
|
+
labels: ["Problem", "RootCause"],
|
|
26862
|
+
attr: "semanticEdgesContributedDigest",
|
|
26863
|
+
minFraction: 0.01
|
|
26864
|
+
},
|
|
26865
|
+
// A parked edge that later LANDED — the replay doing its job.
|
|
26866
|
+
effectCounter: "edgesReplayLanded",
|
|
26867
|
+
// Outstanding parked edges (a level). Flat-and-nonzero while replays keep
|
|
26868
|
+
// re-parking is an endpoint that never resolves; it drains to tombstones
|
|
26869
|
+
// (`edgesDroppedExhausted`) instead of being resent forever.
|
|
26870
|
+
backlogCounter: "edgeParkSize",
|
|
26871
|
+
note: "edge-park.ts; quiet (no-effect) is healthy when nothing is refused \u2014 read edgesParked/edgesDropped* on the ship row"
|
|
26872
|
+
},
|
|
26609
26873
|
{
|
|
26610
26874
|
id: "orphan-reap",
|
|
26611
26875
|
what: "closes File nodes whose path the indexer no longer covers",
|
|
@@ -26660,12 +26924,31 @@ var init_mechanism_liveness = __esm({
|
|
|
26660
26924
|
// the bar is "the field is written at all", the revisit-sweep precedent.
|
|
26661
26925
|
fed: { labels: ["Problem"], attr: "foldCandidate", minFraction: 0 },
|
|
26662
26926
|
effectCounter: "folded",
|
|
26663
|
-
//
|
|
26664
|
-
//
|
|
26665
|
-
|
|
26927
|
+
// The open-nomination POOL is the backlog. It used to be `standing`, which
|
|
26928
|
+
// only counts what the pass examined — capped at the per-run limit — so it
|
|
26929
|
+
// read a flat 8 for weeks while 824 nominations sat open (2026-10-12): the
|
|
26930
|
+
// gauge could not see past the slice it was meant to be measuring.
|
|
26931
|
+
backlogCounter: "pending",
|
|
26666
26932
|
configCounter: "judgeConfigured",
|
|
26667
26933
|
note: "the ambiguous band needs the opt-in judge: set ERRATA_FOLD_JUDGE=1 + a configured chat provider (azure env), or leave it off and the nominations stand"
|
|
26668
26934
|
},
|
|
26935
|
+
{
|
|
26936
|
+
id: "fold-candidate-coverage",
|
|
26937
|
+
what: "rotates the fold-judge pass through every open nomination (never-examined first, standing ones re-examined on new evidence)",
|
|
26938
|
+
// Judge-INDEPENDENT on purpose — no configCounter. The embedding-certain
|
|
26939
|
+
// bands fold/reject with no judge at all, and the defect this watches is
|
|
26940
|
+
// the pass re-reading the same oldest 8 forever (101 runs, 8 distinct
|
|
26941
|
+
// nodes, 816 of 824 nominations never looked at). That starves those
|
|
26942
|
+
// bands on a judge-less daemon exactly as much as on a judged one, so an
|
|
26943
|
+
// opt-in being off must not excuse it.
|
|
26944
|
+
pass: "fold-judge",
|
|
26945
|
+
fed: { labels: ["Problem"], attr: "foldCandidate", minFraction: 0 },
|
|
26946
|
+
effectCounter: "firstExamined",
|
|
26947
|
+
// A LEVEL: open nominations never examined. Flat-and-positive with no
|
|
26948
|
+
// first examinations across the stall window = the rotation is stuck.
|
|
26949
|
+
backlogCounter: "neverExamined",
|
|
26950
|
+
note: "neverExamined must drain while the pass runs; flat means the selection is re-reading the same slice"
|
|
26951
|
+
},
|
|
26669
26952
|
{
|
|
26670
26953
|
id: "cite-anchor-accrual",
|
|
26671
26954
|
what: "accrues cite-context anchor evidence on anchorless cited priors; two distinct sessions promote a cite-confirmed ANCHORED_AT",
|
|
@@ -26845,13 +27128,18 @@ __export(src_exports2, {
|
|
|
26845
27128
|
FINGERPRINT_INDEXED_LABELS: () => FINGERPRINT_INDEXED_LABELS,
|
|
26846
27129
|
FIX_CANDIDATE_ASK_LIMIT: () => FIX_CANDIDATE_ASK_LIMIT,
|
|
26847
27130
|
FOLD_EMBED_AUTO_COSINE: () => FOLD_EMBED_AUTO_COSINE,
|
|
27131
|
+
FOLD_EXAMINE_LIMIT: () => FOLD_EXAMINE_LIMIT,
|
|
27132
|
+
FOLD_JUDGE_BUDGET: () => FOLD_JUDGE_BUDGET,
|
|
26848
27133
|
FOLD_JUDGE_MIN_COSINE: () => FOLD_JUDGE_MIN_COSINE,
|
|
27134
|
+
FOLD_REEXAMINE_SEQ: () => FOLD_REEXAMINE_SEQ,
|
|
26849
27135
|
FOLD_REJECTED_CAP: () => FOLD_REJECTED_CAP,
|
|
26850
27136
|
FOLD_SCOUT_AUTO_COSINE: () => FOLD_SCOUT_AUTO_COSINE,
|
|
26851
27137
|
FOLD_SCOUT_MIN_COSINE: () => FOLD_SCOUT_MIN_COSINE,
|
|
26852
27138
|
FOLD_SCOUT_MIN_JACCARD: () => FOLD_SCOUT_MIN_JACCARD,
|
|
27139
|
+
HISTORY_EDGE_TYPES: () => HISTORY_EDGE_TYPES,
|
|
26853
27140
|
JOINT_COMMUNITY_EDGES: () => JOINT_COMMUNITY_EDGES,
|
|
26854
27141
|
JOINT_COMMUNITY_LABELS: () => JOINT_COMMUNITY_LABELS,
|
|
27142
|
+
LINEAGE_INTEGRITY_KEY: () => LINEAGE_INTEGRITY_KEY,
|
|
26855
27143
|
MAX_ANCHOR_FILES: () => MAX_ANCHOR_FILES,
|
|
26856
27144
|
MECHANISMS: () => MECHANISMS,
|
|
26857
27145
|
MIN_INTENT_TOKENS: () => MIN_INTENT_TOKENS,
|
|
@@ -26893,11 +27181,15 @@ __export(src_exports2, {
|
|
|
26893
27181
|
clearRevisit: () => clearRevisit,
|
|
26894
27182
|
clearSettledFixCandidates: () => clearSettledFixCandidates,
|
|
26895
27183
|
closableByCaller: () => closableByCaller,
|
|
27184
|
+
closeIncidentEdges: () => closeIncidentEdges,
|
|
27185
|
+
collapseLiveHeads: () => collapseLiveHeads,
|
|
26896
27186
|
communityInductionRequests: () => communityInductionRequests,
|
|
26897
27187
|
communitySeeds: () => communitySeeds,
|
|
26898
27188
|
compareSemver: () => compareSemver,
|
|
26899
27189
|
confirmFixHeld: () => confirmFixHeld,
|
|
26900
27190
|
corroborateClaim: () => corroborateClaim,
|
|
27191
|
+
countLiveHeadConflicts: () => countLiveHeadConflicts,
|
|
27192
|
+
countStrandedEdges: () => countStrandedEdges,
|
|
26901
27193
|
creditAssignment: () => creditAssignment,
|
|
26902
27194
|
crystallize: () => crystallize,
|
|
26903
27195
|
deriveContextFromAnchors: () => deriveContextFromAnchors,
|
|
@@ -26916,6 +27208,7 @@ __export(src_exports2, {
|
|
|
26916
27208
|
findReusableSolution: () => findReusableSolution,
|
|
26917
27209
|
findWorkspaceFoldCandidate: () => findWorkspaceFoldCandidate,
|
|
26918
27210
|
flattenCloudCounts: () => flattenCloudCounts,
|
|
27211
|
+
foldCandidateEligible: () => foldCandidateEligible,
|
|
26919
27212
|
foldDuplicateProblem: () => foldDuplicateProblem,
|
|
26920
27213
|
foldSameAnchorProblem: () => foldSameAnchorProblem,
|
|
26921
27214
|
formatMechanismStatus: () => formatMechanismStatus,
|
|
@@ -26928,6 +27221,7 @@ __export(src_exports2, {
|
|
|
26928
27221
|
induceTriage: () => induceTriage,
|
|
26929
27222
|
ingestDesignProblem: () => ingestDesignProblem,
|
|
26930
27223
|
ingestWitnessedVulnerability: () => ingestWitnessedVulnerability,
|
|
27224
|
+
installLineageIntegrityRepair: () => installLineageIntegrityRepair,
|
|
26931
27225
|
isConstraintProblem: () => isConstraintProblem,
|
|
26932
27226
|
isFragmentFixNote: () => isFragmentFixNote,
|
|
26933
27227
|
isPlaceholderStatement: () => isPlaceholderStatement,
|
|
@@ -26983,7 +27277,9 @@ __export(src_exports2, {
|
|
|
26983
27277
|
reinforceSameAnchorProblem: () => reinforceSameAnchorProblem,
|
|
26984
27278
|
relateClaims: () => relateClaims,
|
|
26985
27279
|
reopenAutoClosedProblems: () => reopenAutoClosedProblems,
|
|
27280
|
+
reopenCascadeClosedEdges: () => reopenCascadeClosedEdges,
|
|
26986
27281
|
repairLegacyAnchorsFromStatement: () => repairLegacyAnchorsFromStatement,
|
|
27282
|
+
repairLineageIntegrity: () => repairLineageIntegrity,
|
|
26987
27283
|
resolveDesignProblemById: () => resolveDesignProblemById,
|
|
26988
27284
|
resolveDesignProblemByStatement: () => resolveDesignProblemByStatement,
|
|
26989
27285
|
resolveEnclosingSymbol: () => resolveEnclosingSymbol,
|
|
@@ -27033,6 +27329,7 @@ var init_src5 = __esm({
|
|
|
27033
27329
|
init_tools();
|
|
27034
27330
|
init_principle_sync();
|
|
27035
27331
|
init_mechanism_liveness();
|
|
27332
|
+
init_lineage_integrity();
|
|
27036
27333
|
init_wm_calibration();
|
|
27037
27334
|
}
|
|
27038
27335
|
});
|
|
@@ -28469,7 +28766,7 @@ function parseRestErrorEnvelope(text) {
|
|
|
28469
28766
|
return null;
|
|
28470
28767
|
}
|
|
28471
28768
|
}
|
|
28472
|
-
var asWireCount, INGEST_NODE_CHUNK, INGEST_EDGE_CHUNK, E6B_PUBLIC_CONTEXT_SENTINEL, gzipAsync, CloudClient, CloudError;
|
|
28769
|
+
var asWireCount, INGEST_NODE_CHUNK, INGEST_EDGE_CHUNK, ENDPOINT_NOT_LANDED_PREFIX, E6B_PUBLIC_CONTEXT_SENTINEL, gzipAsync, CloudClient, CloudError;
|
|
28473
28770
|
var init_client = __esm({
|
|
28474
28771
|
"../../packages/cloud-client/src/client.ts"() {
|
|
28475
28772
|
"use strict";
|
|
@@ -28478,6 +28775,7 @@ var init_client = __esm({
|
|
|
28478
28775
|
asWireCount = (n) => typeof n === "number" && Number.isFinite(n) && n >= 0 ? Math.floor(n) : null;
|
|
28479
28776
|
INGEST_NODE_CHUNK = 8;
|
|
28480
28777
|
INGEST_EDGE_CHUNK = 32;
|
|
28778
|
+
ENDPOINT_NOT_LANDED_PREFIX = "endpoint did not land this drain";
|
|
28481
28779
|
E6B_PUBLIC_CONTEXT_SENTINEL = "00000000-0000-4e6b-8000-000000000e6b";
|
|
28482
28780
|
gzipAsync = promisify(gzip);
|
|
28483
28781
|
CloudClient = class {
|
|
@@ -28680,7 +28978,7 @@ var init_client = __esm({
|
|
|
28680
28978
|
pendingEdges = pendingEdges.filter((e) => !shipped.has(e));
|
|
28681
28979
|
return { nodes, edges };
|
|
28682
28980
|
});
|
|
28683
|
-
|
|
28981
|
+
let totalChunks = single ? 1 : nodePlan.length + Math.ceil(pendingEdges.length / INGEST_EDGE_CHUNK);
|
|
28684
28982
|
let chunkIndex = 0;
|
|
28685
28983
|
const blocked = [];
|
|
28686
28984
|
const emit = async (nodeIds, result) => {
|
|
@@ -28707,9 +29005,18 @@ var init_client = __esm({
|
|
|
28707
29005
|
}
|
|
28708
29006
|
const merged = { runId, nodes: [], edges: [] };
|
|
28709
29007
|
const echoedCloudId = /* @__PURE__ */ new Map();
|
|
29008
|
+
const notLanded = /* @__PURE__ */ new Map();
|
|
28710
29009
|
for (const { nodes: nodeChunk, edges: inChunk } of nodePlan) {
|
|
28711
29010
|
const r = await this.ingestWithSplit(batch, nodeChunk, inChunk, blocked);
|
|
29011
|
+
const refusedHere = new Set(blocked);
|
|
28712
29012
|
await emit(nodeChunk.map((n) => n.id), r);
|
|
29013
|
+
const verdict = new Map(r.nodes.map((rn) => [rn.canonicalId, rn]));
|
|
29014
|
+
for (const n of nodeChunk) {
|
|
29015
|
+
const rn = verdict.get(n.id);
|
|
29016
|
+
if (refusedHere.has(n.id)) notLanded.set(n.id, "refused by an intermediary");
|
|
29017
|
+
else if (!rn) notLanded.set(n.id, "no verdict from the door");
|
|
29018
|
+
else if (rn.decision === "rejected") notLanded.set(n.id, rn.reason ?? "rejected");
|
|
29019
|
+
}
|
|
28713
29020
|
merged.nodes.push(...r.nodes);
|
|
28714
29021
|
merged.edges.push(...r.edges);
|
|
28715
29022
|
for (const rn of r.nodes) {
|
|
@@ -28721,6 +29028,19 @@ var init_client = __esm({
|
|
|
28721
29028
|
merged.patternReconciliation = { ...merged.patternReconciliation, ...r.patternReconciliation };
|
|
28722
29029
|
}
|
|
28723
29030
|
}
|
|
29031
|
+
pendingEdges = pendingEdges.filter((e) => {
|
|
29032
|
+
const missing = notLanded.has(e.from) && !echoedCloudId.has(e.from) ? e.from : notLanded.has(e.to) && !echoedCloudId.has(e.to) ? e.to : null;
|
|
29033
|
+
if (missing === null) return true;
|
|
29034
|
+
merged.edges.push({
|
|
29035
|
+
from: e.from,
|
|
29036
|
+
to: e.to,
|
|
29037
|
+
type: e.type,
|
|
29038
|
+
decision: "rejected",
|
|
29039
|
+
reason: `${ENDPOINT_NOT_LANDED_PREFIX} '${missing}' \u2014 ${notLanded.get(missing)}`
|
|
29040
|
+
});
|
|
29041
|
+
return false;
|
|
29042
|
+
});
|
|
29043
|
+
totalChunks = nodePlan.length + Math.ceil(pendingEdges.length / INGEST_EDGE_CHUNK);
|
|
28724
29044
|
for (const edgeChunk of chunkArray(pendingEdges, INGEST_EDGE_CHUNK)) {
|
|
28725
29045
|
const projected = edgeChunk.map((e) => ({
|
|
28726
29046
|
...e,
|
|
@@ -33296,7 +33616,7 @@ function detectResolution(opts, ev) {
|
|
|
33296
33616
|
function closeProblem(store, problemId, t) {
|
|
33297
33617
|
const n = store.getNode(problemId);
|
|
33298
33618
|
if (!n || (n.validTo ?? null) !== null) return false;
|
|
33299
|
-
store.closeNode(problemId, t);
|
|
33619
|
+
store.closeNode(problemId, t, { retainEdges: true });
|
|
33300
33620
|
store.updateNode(problemId, { attrs: { ...n.attrs, resolvedAt: t } });
|
|
33301
33621
|
return true;
|
|
33302
33622
|
}
|
|
@@ -37988,9 +38308,11 @@ async function incrementalReindex(store, rootPath, workspaceId2, changedAbsPaths
|
|
|
37988
38308
|
signatureAfter: a.signature
|
|
37989
38309
|
});
|
|
37990
38310
|
}
|
|
38311
|
+
const repointable = /* @__PURE__ */ new Map();
|
|
37991
38312
|
store.transaction(() => {
|
|
37992
38313
|
for (const nid of changedIds) store.freezeNode(nid, t);
|
|
37993
38314
|
for (const nid of removedIds) {
|
|
38315
|
+
repointable.set(nid, store.inEdges(nid, ["CALLS", "ACCESSES", "ANCHORED_AT"]));
|
|
37994
38316
|
for (const e of store.outEdges(nid)) store.closeEdge(e.id, t);
|
|
37995
38317
|
store.closeNode(nid, t);
|
|
37996
38318
|
}
|
|
@@ -38079,8 +38401,8 @@ async function incrementalReindex(store, rootPath, workspaceId2, changedAbsPaths
|
|
|
38079
38401
|
version: b.version + 1
|
|
38080
38402
|
});
|
|
38081
38403
|
store.mergeEdge(continuesEdge(m, t));
|
|
38082
|
-
for (const e of
|
|
38083
|
-
if (e.
|
|
38404
|
+
for (const e of repointable.get(m.fromNid) ?? []) {
|
|
38405
|
+
if (e.from === m.fromNid || !store.liveNodeIds([e.from]).has(e.from)) continue;
|
|
38084
38406
|
const newId = edgeId(e.from, e.type, m.toNid);
|
|
38085
38407
|
if (!store.getEdge(newId)) {
|
|
38086
38408
|
store.mergeEdge({ ...e, id: newId, to: m.toNid, lastSeenAt: t });
|
|
@@ -44172,10 +44494,10 @@ function collectDocstrings(root, records, out2) {
|
|
|
44172
44494
|
}
|
|
44173
44495
|
}
|
|
44174
44496
|
}
|
|
44175
|
-
function docstringIn(
|
|
44176
|
-
if (!
|
|
44177
|
-
if (
|
|
44178
|
-
const expr =
|
|
44497
|
+
function docstringIn(stmt2) {
|
|
44498
|
+
if (!stmt2) return null;
|
|
44499
|
+
if (stmt2.type !== "expression_statement") return null;
|
|
44500
|
+
const expr = stmt2.namedChild(0);
|
|
44179
44501
|
if (!expr) return null;
|
|
44180
44502
|
if (expr.type !== "string") return null;
|
|
44181
44503
|
const text = expr.text;
|
|
@@ -47773,7 +48095,7 @@ var init_mcp = __esm({
|
|
|
47773
48095
|
},
|
|
47774
48096
|
{
|
|
47775
48097
|
name: "errata.health",
|
|
47776
|
-
description: "Graph-quality + backlog snapshot \u2014 the dashboard's health view, for an agent. Returns counts of: stranded symbols (a live edge points at a non-live node \u2014 invisible to name resolution), open Problems, open Problems with NO proposed fix, retracted false-positives + dissolutions (the agentic-misread rate \u2014 PLAN_RETRACTION \xA7D), ungrounded-but-'derived' Claims (belief-layer noise), and facts needing revisit. Use to triage the workspace's state or sanity-check the graph before trusting a transitive answer.",
|
|
48098
|
+
description: "Graph-quality + backlog snapshot \u2014 the dashboard's health view, for an agent. Returns counts of: stranded symbols (a live File DEFINES/CONTAINS edge points at a non-live node \u2014 invisible to name resolution), stranded edges (ANY live non-history edge with a closed endpoint, by type), lineages with more than one live head, open Problems, open Problems with NO proposed fix, retracted false-positives + dissolutions (the agentic-misread rate \u2014 PLAN_RETRACTION \xA7D), ungrounded-but-'derived' Claims (belief-layer noise), and facts needing revisit. Use to triage the workspace's state or sanity-check the graph before trusting a transitive answer.",
|
|
47777
48099
|
inputSchema: { type: "object", properties: {} },
|
|
47778
48100
|
handler: (_args, store) => {
|
|
47779
48101
|
const unresolved2 = store.selectNodes({
|
|
@@ -47786,10 +48108,16 @@ var init_mcp = __esm({
|
|
|
47786
48108
|
const noFix = open2.filter((p) => store.outEdges(p.id, ["SOLVED_BY"]).length === 0);
|
|
47787
48109
|
const retracted = (resolvedAs) => store.countNodes({ labels: ["Problem"], includeClosed: true, where: [{ attr: "resolvedAs", eq: resolvedAs }] });
|
|
47788
48110
|
const ungroundedDerived = store.selectNodes({ labels: ["Claim"], attrs: ["groundedSupport"], where: [{ attr: "crystallized", eq: "derived" }] }).filter((c) => Number(c.attrs["groundedSupport"] ?? 0) === 0);
|
|
48111
|
+
const stranded = store.strandedEdges();
|
|
47789
48112
|
return {
|
|
47790
48113
|
nodes: store.nodeCount(),
|
|
47791
48114
|
edges: store.edgeCount(),
|
|
47792
48115
|
strandedSymbols: findStrandedSymbols(store).length,
|
|
48116
|
+
// strandedSymbols only sees File-rooted lineage; it read 0 while ~105k
|
|
48117
|
+
// live edges hung off closed nodes (2026-10-12). This counts all of them.
|
|
48118
|
+
strandedEdges: stranded.total,
|
|
48119
|
+
strandedEdgesByType: stranded.byType,
|
|
48120
|
+
liveHeadConflicts: store.liveHeadConflicts(),
|
|
47793
48121
|
openProblems: open2.length,
|
|
47794
48122
|
openProblemsWithoutFix: noFix.length,
|
|
47795
48123
|
designConstraints: constraints.length,
|
|
@@ -48443,10 +48771,15 @@ function formatHotspotsMd(r) {
|
|
|
48443
48771
|
}
|
|
48444
48772
|
return lines.join("\n") + "\n";
|
|
48445
48773
|
}
|
|
48774
|
+
function strandedTypes(byType) {
|
|
48775
|
+
const top = Object.entries(byType ?? {}).sort((a, b) => b[1] - a[1]).slice(0, 3);
|
|
48776
|
+
return top.length ? ` (${top.map(([t, n]) => `${t} ${n}`).join(", ")})` : "";
|
|
48777
|
+
}
|
|
48446
48778
|
function formatHealthMd(r) {
|
|
48447
48779
|
return `${head("health")}
|
|
48448
48780
|
nodes ${r.nodes} \xB7 edges ${r.edges}
|
|
48449
48781
|
stranded symbols: ${r.strandedSymbols}
|
|
48782
|
+
stranded edges: ${r.strandedEdges ?? 0}${strandedTypes(r.strandedEdgesByType)} \xB7 lineages with >1 live head: ${r.liveHeadConflicts ?? 0}
|
|
48450
48783
|
open problems: ${r.openProblems} (${r.openProblemsWithoutFix} without a proposed fix)
|
|
48451
48784
|
retracted: ${r.retractedFalsePositive} false-positive \xB7 ${r.retractedDissolution} dissolution
|
|
48452
48785
|
ungrounded "derived" claims: ${r.ungroundedDerivedClaims}
|
|
@@ -76427,8 +76760,8 @@ var init_report_render = __esm({
|
|
|
76427
76760
|
|
|
76428
76761
|
// src/cli.ts
|
|
76429
76762
|
init_src6();
|
|
76430
|
-
import { closeSync as closeSync3, existsSync as existsSync40, openSync as openSync3, readFileSync as
|
|
76431
|
-
import { join as
|
|
76763
|
+
import { closeSync as closeSync3, existsSync as existsSync40, openSync as openSync3, readFileSync as readFileSync44, renameSync as renameSync9, statSync as statSync13 } from "node:fs";
|
|
76764
|
+
import { join as join51, resolve as pathResolve2 } from "node:path";
|
|
76432
76765
|
import { spawn as spawn5 } from "node:child_process";
|
|
76433
76766
|
|
|
76434
76767
|
// src/daemon.ts
|
|
@@ -77893,9 +78226,9 @@ var NodeFsHandler = class {
|
|
|
77893
78226
|
if (this.fsw.closed) {
|
|
77894
78227
|
return;
|
|
77895
78228
|
}
|
|
77896
|
-
const
|
|
78229
|
+
const dirname19 = sysPath.dirname(file2);
|
|
77897
78230
|
const basename10 = sysPath.basename(file2);
|
|
77898
|
-
const parent = this.fsw._getWatchedDir(
|
|
78231
|
+
const parent = this.fsw._getWatchedDir(dirname19);
|
|
77899
78232
|
let prevStats = stats;
|
|
77900
78233
|
if (parent.has(basename10))
|
|
77901
78234
|
return;
|
|
@@ -77922,7 +78255,7 @@ var NodeFsHandler = class {
|
|
|
77922
78255
|
prevStats = newStats2;
|
|
77923
78256
|
}
|
|
77924
78257
|
} catch (error48) {
|
|
77925
|
-
this.fsw._remove(
|
|
78258
|
+
this.fsw._remove(dirname19, basename10);
|
|
77926
78259
|
}
|
|
77927
78260
|
} else if (parent.has(basename10)) {
|
|
77928
78261
|
const at = newStats.atimeMs;
|
|
@@ -81472,15 +81805,15 @@ function alreadyDone(configDir) {
|
|
|
81472
81805
|
}
|
|
81473
81806
|
}
|
|
81474
81807
|
function replay(root) {
|
|
81475
|
-
const
|
|
81808
|
+
const statements2 = /* @__PURE__ */ new Set();
|
|
81476
81809
|
const citedByFix = /* @__PURE__ */ new Set();
|
|
81477
81810
|
const dir = claudeProjectDir(root, homedir5());
|
|
81478
|
-
if (!existsSync20(dir)) return { statements, citedByFix };
|
|
81811
|
+
if (!existsSync20(dir)) return { statements: statements2, citedByFix };
|
|
81479
81812
|
let names;
|
|
81480
81813
|
try {
|
|
81481
81814
|
names = readdirSync8(dir).filter((n) => n.endsWith(".jsonl"));
|
|
81482
81815
|
} catch {
|
|
81483
|
-
return { statements, citedByFix };
|
|
81816
|
+
return { statements: statements2, citedByFix };
|
|
81484
81817
|
}
|
|
81485
81818
|
for (const f of names) {
|
|
81486
81819
|
let lines;
|
|
@@ -81501,7 +81834,7 @@ function replay(root) {
|
|
|
81501
81834
|
for (const b of rec.message.content) {
|
|
81502
81835
|
if (b?.type !== "text" || typeof b.text !== "string") continue;
|
|
81503
81836
|
for (const tag of parseInlineTags(b.text)) {
|
|
81504
|
-
if (tag.kind === "constraint" && tag.statement)
|
|
81837
|
+
if (tag.kind === "constraint" && tag.statement) statements2.add(tag.statement);
|
|
81505
81838
|
if (tag.kind === "fix") {
|
|
81506
81839
|
const t = tag;
|
|
81507
81840
|
if (t.handle) citedByFix.add(t.handle);
|
|
@@ -81511,11 +81844,11 @@ function replay(root) {
|
|
|
81511
81844
|
}
|
|
81512
81845
|
}
|
|
81513
81846
|
}
|
|
81514
|
-
return { statements, citedByFix };
|
|
81847
|
+
return { statements: statements2, citedByFix };
|
|
81515
81848
|
}
|
|
81516
81849
|
function backfillConstraintKind(store, opts) {
|
|
81517
81850
|
if (!opts.force && !opts.dryRun && alreadyDone(opts.configDir)) return EMPTY;
|
|
81518
|
-
const { statements, citedByFix } = replay(opts.root);
|
|
81851
|
+
const { statements: statements2, citedByFix } = replay(opts.root);
|
|
81519
81852
|
const report = {
|
|
81520
81853
|
skipped: false,
|
|
81521
81854
|
stamped: 0,
|
|
@@ -81529,7 +81862,7 @@ function backfillConstraintKind(store, opts) {
|
|
|
81529
81862
|
const missing = [];
|
|
81530
81863
|
const seen = /* @__PURE__ */ new Set();
|
|
81531
81864
|
const work = [];
|
|
81532
|
-
for (const statement of
|
|
81865
|
+
for (const statement of statements2) {
|
|
81533
81866
|
const id = designProblemId(statement);
|
|
81534
81867
|
if (seen.has(id)) continue;
|
|
81535
81868
|
seen.add(id);
|
|
@@ -85836,7 +86169,7 @@ function createWatchBreaker(deps) {
|
|
|
85836
86169
|
}
|
|
85837
86170
|
|
|
85838
86171
|
// src/engine.ts
|
|
85839
|
-
var DAEMON_VERSION = true ? "2.0.22-dev.
|
|
86172
|
+
var DAEMON_VERSION = true ? "2.0.22-dev.4186" : "2.0.0-alpha.0";
|
|
85840
86173
|
var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
|
|
85841
86174
|
var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
|
|
85842
86175
|
var GIT_OP_MUTE_MS = 4e3;
|
|
@@ -88357,7 +88690,12 @@ B: ${b}`,
|
|
|
88357
88690
|
standing: fj.standing,
|
|
88358
88691
|
judgeErrors: fj.judgeErrors,
|
|
88359
88692
|
retargeted: fj.retargeted,
|
|
88360
|
-
judgeConfigured: foldJudge ? 1 : 0
|
|
88693
|
+
judgeConfigured: foldJudge ? 1 : 0,
|
|
88694
|
+
pending: fj.pending,
|
|
88695
|
+
neverExamined: fj.neverExamined,
|
|
88696
|
+
firstExamined: fj.firstExamined,
|
|
88697
|
+
waiting: fj.waiting,
|
|
88698
|
+
judgeBudgetDeferred: fj.judgeBudgetDeferred
|
|
88361
88699
|
});
|
|
88362
88700
|
if (fj.folded > 0) {
|
|
88363
88701
|
console.log(`[errata] fold-judge: folded ${fj.folded} paraphrase pair(s) (${fj.foldedEmbedding} by embedding, ${fj.foldedJudge} by judge), ${fj.standing} standing`);
|
|
@@ -88821,6 +89159,212 @@ async function linkRegisteredWorkspaces(cfg, loggedInProfile = cfg.activeInstall
|
|
|
88821
89159
|
}
|
|
88822
89160
|
}
|
|
88823
89161
|
|
|
89162
|
+
// src/edge-park.ts
|
|
89163
|
+
import { readFileSync as readFileSync33, renameSync as renameSync5, writeFileSync as writeFileSync25 } from "node:fs";
|
|
89164
|
+
import { dirname as dirname13, join as join36 } from "node:path";
|
|
89165
|
+
var EDGE_PARK_CAP = 2e3;
|
|
89166
|
+
var EDGE_PARK_TTL_MS = 14 * 24 * 60 * 60 * 1e3;
|
|
89167
|
+
var EDGE_PARK_MAX_ATTEMPTS = 6;
|
|
89168
|
+
var EDGE_RETRY_BASE_MS = 30 * 60 * 1e3;
|
|
89169
|
+
var EDGE_RETRY_MAX_MS = 12 * 60 * 60 * 1e3;
|
|
89170
|
+
var EDGE_TOMBSTONE_TTL_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
89171
|
+
var EDGE_EXHAUSTED_TOMBSTONE_TTL_MS = 3 * 24 * 60 * 60 * 1e3;
|
|
89172
|
+
function tombstoneTtl(e) {
|
|
89173
|
+
return e.dropReason === "refused" ? EDGE_TOMBSTONE_TTL_MS : EDGE_EXHAUSTED_TOMBSTONE_TTL_MS;
|
|
89174
|
+
}
|
|
89175
|
+
function wireEdgeKey(from, type, to) {
|
|
89176
|
+
return JSON.stringify([from, type, to]);
|
|
89177
|
+
}
|
|
89178
|
+
function edgeParkPath(workspaceConfigDir, destinationKey) {
|
|
89179
|
+
return join36(workspaceConfigDir, `edge-park.${destinationKey.slice(0, 16)}.json`);
|
|
89180
|
+
}
|
|
89181
|
+
function loadEdgePark(path3) {
|
|
89182
|
+
let raw2;
|
|
89183
|
+
try {
|
|
89184
|
+
raw2 = JSON.parse(readFileSync33(path3, "utf8"));
|
|
89185
|
+
} catch {
|
|
89186
|
+
return [];
|
|
89187
|
+
}
|
|
89188
|
+
if (!Array.isArray(raw2)) return [];
|
|
89189
|
+
return raw2.filter(
|
|
89190
|
+
(e) => !!e && typeof e === "object" && typeof e.key === "string" && typeof e.from === "string" && typeof e.to === "string" && typeof e.type === "string" && (e.state === "parked" || e.state === "dropped")
|
|
89191
|
+
);
|
|
89192
|
+
}
|
|
89193
|
+
function saveEdgePark(path3, queue) {
|
|
89194
|
+
try {
|
|
89195
|
+
const tmp = join36(dirname13(path3), `.${Date.now()}.edge-park.tmp`);
|
|
89196
|
+
writeFileSync25(tmp, JSON.stringify(queue), "utf8");
|
|
89197
|
+
renameSync5(tmp, path3);
|
|
89198
|
+
} catch {
|
|
89199
|
+
}
|
|
89200
|
+
}
|
|
89201
|
+
function edgeHolds(queue, now) {
|
|
89202
|
+
const holds = {};
|
|
89203
|
+
for (const e of queue) {
|
|
89204
|
+
if (e.state === "dropped") {
|
|
89205
|
+
if (now - (e.droppedAt ?? e.ts) < tombstoneTtl(e)) holds[e.key] = "dropped";
|
|
89206
|
+
} else if (e.dueAt > now) {
|
|
89207
|
+
holds[e.key] = "held";
|
|
89208
|
+
}
|
|
89209
|
+
}
|
|
89210
|
+
return holds;
|
|
89211
|
+
}
|
|
89212
|
+
function classifyEdgeVerdict(decision, reason) {
|
|
89213
|
+
if (decision === "created" || decision === "reinforced") return "landed";
|
|
89214
|
+
const why = reason ?? "";
|
|
89215
|
+
if (/^unresolved endpoint\b/.test(why) || /^endpoint did not land this drain\b/.test(why) || /\bretry\b/i.test(why)) {
|
|
89216
|
+
return "park";
|
|
89217
|
+
}
|
|
89218
|
+
return "drop";
|
|
89219
|
+
}
|
|
89220
|
+
function matchEdgeVerdicts(sent, received, echo) {
|
|
89221
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
89222
|
+
for (const r of received) {
|
|
89223
|
+
const k = wireEdgeKey(r.from, r.type, r.to);
|
|
89224
|
+
if (!byKey.has(k) || r.decision === "rejected") byKey.set(k, { decision: r.decision, reason: r.reason });
|
|
89225
|
+
}
|
|
89226
|
+
const out2 = /* @__PURE__ */ new Map();
|
|
89227
|
+
for (const e of sent) {
|
|
89228
|
+
const v = byKey.get(wireEdgeKey(echo.get(e.from) ?? e.from, e.type, echo.get(e.to) ?? e.to)) ?? byKey.get(wireEdgeKey(e.from, e.type, e.to));
|
|
89229
|
+
if (v) out2.set(e.id, v);
|
|
89230
|
+
}
|
|
89231
|
+
return out2;
|
|
89232
|
+
}
|
|
89233
|
+
function zeroEdgeSettleCounts(queue) {
|
|
89234
|
+
const parked = queue.filter((e) => e.state === "parked").length;
|
|
89235
|
+
return {
|
|
89236
|
+
edgesSent: 0,
|
|
89237
|
+
edgesLanded: 0,
|
|
89238
|
+
edgesReplayLanded: 0,
|
|
89239
|
+
edgesReplayed: 0,
|
|
89240
|
+
edgesParked: 0,
|
|
89241
|
+
edgesReparked: 0,
|
|
89242
|
+
edgesDroppedRefused: 0,
|
|
89243
|
+
edgesDroppedExhausted: 0,
|
|
89244
|
+
edgesDroppedExpired: 0,
|
|
89245
|
+
edgesDroppedCapped: 0,
|
|
89246
|
+
edgesNoVerdict: 0,
|
|
89247
|
+
edgeParkSize: parked,
|
|
89248
|
+
edgeTombstones: queue.length - parked
|
|
89249
|
+
};
|
|
89250
|
+
}
|
|
89251
|
+
function backoff(attempts) {
|
|
89252
|
+
return Math.min(EDGE_RETRY_MAX_MS, EDGE_RETRY_BASE_MS * 2 ** Math.max(0, attempts - 1));
|
|
89253
|
+
}
|
|
89254
|
+
function settleEdgeOutcomes(queue, sent, verdicts, now) {
|
|
89255
|
+
const counts = {
|
|
89256
|
+
edgesSent: sent.length,
|
|
89257
|
+
edgesLanded: 0,
|
|
89258
|
+
edgesReplayLanded: 0,
|
|
89259
|
+
edgesReplayed: 0,
|
|
89260
|
+
edgesParked: 0,
|
|
89261
|
+
edgesReparked: 0,
|
|
89262
|
+
edgesDroppedRefused: 0,
|
|
89263
|
+
edgesDroppedExhausted: 0,
|
|
89264
|
+
edgesDroppedExpired: 0,
|
|
89265
|
+
edgesDroppedCapped: 0,
|
|
89266
|
+
edgesNoVerdict: 0,
|
|
89267
|
+
edgeParkSize: 0,
|
|
89268
|
+
edgeTombstones: 0
|
|
89269
|
+
};
|
|
89270
|
+
const byKey = new Map(queue.map((e) => [e.key, { ...e }]));
|
|
89271
|
+
const seen = /* @__PURE__ */ new Set();
|
|
89272
|
+
for (const e of sent) {
|
|
89273
|
+
const key = e.id;
|
|
89274
|
+
if (seen.has(key)) continue;
|
|
89275
|
+
seen.add(key);
|
|
89276
|
+
const prior = byKey.get(key);
|
|
89277
|
+
if (prior?.state === "parked") counts.edgesReplayed++;
|
|
89278
|
+
const v = verdicts.get(key);
|
|
89279
|
+
if (!v) {
|
|
89280
|
+
counts.edgesNoVerdict++;
|
|
89281
|
+
continue;
|
|
89282
|
+
}
|
|
89283
|
+
const disposition = classifyEdgeVerdict(v.decision, v.reason);
|
|
89284
|
+
if (disposition === "landed") {
|
|
89285
|
+
counts.edgesLanded++;
|
|
89286
|
+
if (prior) {
|
|
89287
|
+
byKey.delete(key);
|
|
89288
|
+
if (prior.state === "parked") counts.edgesReplayLanded++;
|
|
89289
|
+
}
|
|
89290
|
+
continue;
|
|
89291
|
+
}
|
|
89292
|
+
const reason = v.reason ?? "rejected";
|
|
89293
|
+
if (prior?.state === "dropped") continue;
|
|
89294
|
+
if (disposition === "drop") {
|
|
89295
|
+
byKey.set(key, {
|
|
89296
|
+
key,
|
|
89297
|
+
from: e.from,
|
|
89298
|
+
type: e.type,
|
|
89299
|
+
to: e.to,
|
|
89300
|
+
ts: prior?.ts ?? now,
|
|
89301
|
+
attempts: (prior?.attempts ?? 0) + 1,
|
|
89302
|
+
lastReason: reason,
|
|
89303
|
+
dueAt: now,
|
|
89304
|
+
state: "dropped",
|
|
89305
|
+
dropReason: "refused",
|
|
89306
|
+
droppedAt: now
|
|
89307
|
+
});
|
|
89308
|
+
counts.edgesDroppedRefused++;
|
|
89309
|
+
continue;
|
|
89310
|
+
}
|
|
89311
|
+
const attempts = (prior?.state === "parked" ? prior.attempts : 0) + 1;
|
|
89312
|
+
const ts = prior?.state === "parked" ? prior.ts : now;
|
|
89313
|
+
if (attempts >= EDGE_PARK_MAX_ATTEMPTS || now - ts >= EDGE_PARK_TTL_MS) {
|
|
89314
|
+
const why = attempts >= EDGE_PARK_MAX_ATTEMPTS ? "exhausted" : "expired";
|
|
89315
|
+
byKey.set(key, {
|
|
89316
|
+
key,
|
|
89317
|
+
from: e.from,
|
|
89318
|
+
type: e.type,
|
|
89319
|
+
to: e.to,
|
|
89320
|
+
ts,
|
|
89321
|
+
attempts,
|
|
89322
|
+
lastReason: reason,
|
|
89323
|
+
dueAt: now,
|
|
89324
|
+
state: "dropped",
|
|
89325
|
+
dropReason: why,
|
|
89326
|
+
droppedAt: now
|
|
89327
|
+
});
|
|
89328
|
+
if (why === "exhausted") counts.edgesDroppedExhausted++;
|
|
89329
|
+
else counts.edgesDroppedExpired++;
|
|
89330
|
+
continue;
|
|
89331
|
+
}
|
|
89332
|
+
byKey.set(key, {
|
|
89333
|
+
key,
|
|
89334
|
+
from: e.from,
|
|
89335
|
+
type: e.type,
|
|
89336
|
+
to: e.to,
|
|
89337
|
+
ts,
|
|
89338
|
+
attempts,
|
|
89339
|
+
lastReason: reason,
|
|
89340
|
+
dueAt: now + backoff(attempts),
|
|
89341
|
+
state: "parked"
|
|
89342
|
+
});
|
|
89343
|
+
if (prior?.state === "parked") counts.edgesReparked++;
|
|
89344
|
+
else counts.edgesParked++;
|
|
89345
|
+
}
|
|
89346
|
+
const live3 = [];
|
|
89347
|
+
for (const e of byKey.values()) {
|
|
89348
|
+
if (e.state === "parked" && now - e.ts >= EDGE_PARK_TTL_MS) {
|
|
89349
|
+
counts.edgesDroppedExpired++;
|
|
89350
|
+
continue;
|
|
89351
|
+
}
|
|
89352
|
+
if (e.state === "dropped" && now - (e.droppedAt ?? e.ts) >= tombstoneTtl(e)) continue;
|
|
89353
|
+
live3.push(e);
|
|
89354
|
+
}
|
|
89355
|
+
let next = live3;
|
|
89356
|
+
if (next.length > EDGE_PARK_CAP) {
|
|
89357
|
+
const over = next.length - EDGE_PARK_CAP;
|
|
89358
|
+
const order = [...next].sort((a, b) => (a.state === b.state ? 0 : a.state === "dropped" ? -1 : 1) || a.ts - b.ts);
|
|
89359
|
+
const evict = new Set(order.slice(0, over).map((e) => e.key));
|
|
89360
|
+
counts.edgesDroppedCapped = order.slice(0, over).filter((e) => e.state === "parked").length;
|
|
89361
|
+
next = next.filter((e) => !evict.has(e.key));
|
|
89362
|
+
}
|
|
89363
|
+
counts.edgeParkSize = next.filter((e) => e.state === "parked").length;
|
|
89364
|
+
counts.edgeTombstones = next.length - counts.edgeParkSize;
|
|
89365
|
+
return { queue: next, counts };
|
|
89366
|
+
}
|
|
89367
|
+
|
|
88824
89368
|
// src/instance-receipts.ts
|
|
88825
89369
|
import { createHash as createHash18 } from "node:crypto";
|
|
88826
89370
|
var INSTANCE_SEMANTIC_EDGE_TYPES = ["CAUSED_BY", "SOLVED_BY"];
|
|
@@ -88962,7 +89506,7 @@ function invalidateInstanceReceipt(current, destination, failedId, mirrorLegacy)
|
|
|
88962
89506
|
// src/multi.ts
|
|
88963
89507
|
init_dist();
|
|
88964
89508
|
init_src5();
|
|
88965
|
-
import { existsSync as existsSync34, writeFileSync as
|
|
89509
|
+
import { existsSync as existsSync34, writeFileSync as writeFileSync28 } from "node:fs";
|
|
88966
89510
|
import { resolve as pathResolve } from "node:path";
|
|
88967
89511
|
|
|
88968
89512
|
// src/principle-sync.ts
|
|
@@ -88991,8 +89535,8 @@ init_reconcile();
|
|
|
88991
89535
|
|
|
88992
89536
|
// src/lockfile-auto.ts
|
|
88993
89537
|
init_src();
|
|
88994
|
-
import { existsSync as existsSync30, readFileSync as
|
|
88995
|
-
import { join as
|
|
89538
|
+
import { existsSync as existsSync30, readFileSync as readFileSync34 } from "node:fs";
|
|
89539
|
+
import { join as join37 } from "node:path";
|
|
88996
89540
|
|
|
88997
89541
|
// src/package-index.ts
|
|
88998
89542
|
init_src();
|
|
@@ -89144,11 +89688,11 @@ function runLockfilePass(opts) {
|
|
|
89144
89688
|
{ file: "package-lock.json", parse: parsePackageLockJson }
|
|
89145
89689
|
];
|
|
89146
89690
|
for (const c of candidates) {
|
|
89147
|
-
const p =
|
|
89691
|
+
const p = join37(opts.root, c.file);
|
|
89148
89692
|
if (!existsSync30(p)) continue;
|
|
89149
89693
|
let sbom;
|
|
89150
89694
|
try {
|
|
89151
|
-
sbom = c.parse(
|
|
89695
|
+
sbom = c.parse(readFileSync34(p, "utf8"));
|
|
89152
89696
|
} catch {
|
|
89153
89697
|
continue;
|
|
89154
89698
|
}
|
|
@@ -89209,8 +89753,8 @@ init_profile2();
|
|
|
89209
89753
|
init_session_registry();
|
|
89210
89754
|
|
|
89211
89755
|
// src/public-symbols.ts
|
|
89212
|
-
import { readFileSync as
|
|
89213
|
-
import { join as
|
|
89756
|
+
import { readFileSync as readFileSync35, readdirSync as readdirSync12, existsSync as existsSync31 } from "node:fs";
|
|
89757
|
+
import { join as join38 } from "node:path";
|
|
89214
89758
|
var HEAD_BYTES = 8 * 1024;
|
|
89215
89759
|
var INDEX_TTL_MS = 10 * 60 * 1e3;
|
|
89216
89760
|
var MIN_SYMBOL_LEN = 4;
|
|
@@ -89243,20 +89787,20 @@ function bindingNames(clause) {
|
|
|
89243
89787
|
function internalPackageNames(workspaceRoot) {
|
|
89244
89788
|
const names = /* @__PURE__ */ new Set();
|
|
89245
89789
|
const tryRead = (dir) => {
|
|
89246
|
-
const pj =
|
|
89790
|
+
const pj = join38(dir, "package.json");
|
|
89247
89791
|
if (!existsSync31(pj)) return;
|
|
89248
89792
|
try {
|
|
89249
|
-
const name2 = JSON.parse(
|
|
89793
|
+
const name2 = JSON.parse(readFileSync35(pj, "utf8")).name;
|
|
89250
89794
|
if (typeof name2 === "string" && name2.length > 0) names.add(name2);
|
|
89251
89795
|
} catch {
|
|
89252
89796
|
}
|
|
89253
89797
|
};
|
|
89254
89798
|
tryRead(workspaceRoot);
|
|
89255
89799
|
for (const group of ["packages", "apps"]) {
|
|
89256
|
-
const groupDir =
|
|
89800
|
+
const groupDir = join38(workspaceRoot, group);
|
|
89257
89801
|
if (!existsSync31(groupDir)) continue;
|
|
89258
89802
|
try {
|
|
89259
|
-
for (const entry of readdirSync12(groupDir)) tryRead(
|
|
89803
|
+
for (const entry of readdirSync12(groupDir)) tryRead(join38(groupDir, entry));
|
|
89260
89804
|
} catch {
|
|
89261
89805
|
}
|
|
89262
89806
|
}
|
|
@@ -89275,7 +89819,7 @@ function publicSymbolIndex(store, workspaceRoot, deps = {}) {
|
|
|
89275
89819
|
}
|
|
89276
89820
|
const readHead = deps.readHead ?? ((absPath) => {
|
|
89277
89821
|
try {
|
|
89278
|
-
return
|
|
89822
|
+
return readFileSync35(absPath, "utf8").slice(0, HEAD_BYTES);
|
|
89279
89823
|
} catch {
|
|
89280
89824
|
return "";
|
|
89281
89825
|
}
|
|
@@ -89295,7 +89839,7 @@ function publicSymbolIndex(store, workspaceRoot, deps = {}) {
|
|
|
89295
89839
|
}
|
|
89296
89840
|
const symbols = /* @__PURE__ */ new Set();
|
|
89297
89841
|
for (const rel of files) {
|
|
89298
|
-
const head2 = readHead(
|
|
89842
|
+
const head2 = readHead(join38(workspaceRoot, rel));
|
|
89299
89843
|
if (!head2) continue;
|
|
89300
89844
|
for (const re of [NAMED_IMPORT_RE, REQUIRE_RE]) {
|
|
89301
89845
|
re.lastIndex = 0;
|
|
@@ -89520,7 +90064,9 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
|
|
|
89520
90064
|
sidecarNoSummary: 0,
|
|
89521
90065
|
fileRefsSubstituted: 0,
|
|
89522
90066
|
fileRefLexiconMisses: 0,
|
|
89523
|
-
collapsedEdges: 0
|
|
90067
|
+
collapsedEdges: 0,
|
|
90068
|
+
edgesHeldParked: 0,
|
|
90069
|
+
edgesHeldDropped: 0
|
|
89524
90070
|
};
|
|
89525
90071
|
const sharedCauses = /* @__PURE__ */ new Map();
|
|
89526
90072
|
const causalQueue = store.findNodeFieldsByLabel("Problem", ["source", "resolvedAs"]).filter((r) => r.attrs["source"] !== "cloud" && r.attrs["resolvedAs"] !== PROBLEM_RESOLUTION.FALSE_POSITIVE).map((r) => r.id).filter((id) => ignorePatterns.length === 0 || !ignored(store.getNode(id)?.description ?? ""));
|
|
@@ -89831,6 +90377,30 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
|
|
|
89831
90377
|
if (count > 0) symbolSummaries = sidecar;
|
|
89832
90378
|
}
|
|
89833
90379
|
edges.push(...anchorEdges);
|
|
90380
|
+
if (opts.edgeHolds && Object.keys(opts.edgeHolds).length > 0) {
|
|
90381
|
+
const holds = opts.edgeHolds;
|
|
90382
|
+
const shipsHere = (wireId) => (endpointSources[wireId] ?? [wireId]).some((localId) => shippedById.has(localId));
|
|
90383
|
+
const kept = [];
|
|
90384
|
+
for (const e of edges) {
|
|
90385
|
+
const hold = holds[e.id];
|
|
90386
|
+
if (!hold || hold === "held" && (shipsHere(e.from) || shipsHere(e.to))) {
|
|
90387
|
+
kept.push(e);
|
|
90388
|
+
continue;
|
|
90389
|
+
}
|
|
90390
|
+
if (hold === "held") {
|
|
90391
|
+
composition.edgesHeldParked++;
|
|
90392
|
+
for (const localId of endpointSources[e.from] ?? [e.from]) {
|
|
90393
|
+
delete anchorDigests[localId];
|
|
90394
|
+
delete semanticEdgeDigests[localId];
|
|
90395
|
+
delete projectAnchorDigests[localId];
|
|
90396
|
+
}
|
|
90397
|
+
} else {
|
|
90398
|
+
composition.edgesHeldDropped++;
|
|
90399
|
+
}
|
|
90400
|
+
}
|
|
90401
|
+
edges.length = 0;
|
|
90402
|
+
edges.push(...kept);
|
|
90403
|
+
}
|
|
89834
90404
|
const bindingEndpoints = /* @__PURE__ */ new Set();
|
|
89835
90405
|
for (const e of edges) {
|
|
89836
90406
|
if (e.type === "CAUSED_BY" || e.type === "SOLVED_BY") {
|
|
@@ -89996,7 +90566,8 @@ function buildDrainInstances(store, sharedStore, input) {
|
|
|
89996
90566
|
...lexicon ? { lexicon } : {},
|
|
89997
90567
|
...fileLexicon ? { fileLexicon } : {},
|
|
89998
90568
|
...input.project ? { project: input.project } : {},
|
|
89999
|
-
...input.quarantinedSessions?.length ? { quarantinedSessions: input.quarantinedSessions } : {}
|
|
90569
|
+
...input.quarantinedSessions?.length ? { quarantinedSessions: input.quarantinedSessions } : {},
|
|
90570
|
+
...input.edgeHolds ? { edgeHolds: input.edgeHolds } : {}
|
|
90000
90571
|
});
|
|
90001
90572
|
return {
|
|
90002
90573
|
batch,
|
|
@@ -90253,7 +90824,7 @@ init_config();
|
|
|
90253
90824
|
|
|
90254
90825
|
// src/update.ts
|
|
90255
90826
|
import { spawn as spawn2 } from "node:child_process";
|
|
90256
|
-
import { isAbsolute as isAbsolute6, join as
|
|
90827
|
+
import { isAbsolute as isAbsolute6, join as join39 } from "node:path";
|
|
90257
90828
|
var PACKAGE_NAME = "@inerrata-corporation/errata";
|
|
90258
90829
|
function parse3(v) {
|
|
90259
90830
|
const m = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z][0-9A-Za-z.-]*))?/.exec(v.trim());
|
|
@@ -90400,7 +90971,7 @@ async function runInstalledHookRefresh() {
|
|
|
90400
90971
|
});
|
|
90401
90972
|
if (!isAbsolute6(root)) return 1;
|
|
90402
90973
|
return new Promise((resolve10) => {
|
|
90403
|
-
const child = spawn2(process.execPath, [
|
|
90974
|
+
const child = spawn2(process.execPath, [join39(root, PACKAGE_NAME, "errata.mjs"), "install-hooks", "codex", "--refresh-existing"], {
|
|
90404
90975
|
windowsHide: true,
|
|
90405
90976
|
stdio: "inherit",
|
|
90406
90977
|
timeout: 3e4
|
|
@@ -90546,12 +91117,12 @@ function landCloudEdge(store, e, from, to) {
|
|
|
90546
91117
|
}
|
|
90547
91118
|
|
|
90548
91119
|
// src/causal-edge-queue.ts
|
|
90549
|
-
import { readFileSync as
|
|
90550
|
-
import { dirname as
|
|
91120
|
+
import { readFileSync as readFileSync36, renameSync as renameSync6, writeFileSync as writeFileSync26 } from "node:fs";
|
|
91121
|
+
import { dirname as dirname14, join as join40 } from "node:path";
|
|
90551
91122
|
var CAUSAL_EDGE_QUEUE_CAP = 5e3;
|
|
90552
91123
|
var CAUSAL_EDGE_TTL_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
90553
91124
|
function causalEdgeQueuePath(workspaceConfigDir) {
|
|
90554
|
-
return
|
|
91125
|
+
return join40(workspaceConfigDir, "causal-edge-queue.json");
|
|
90555
91126
|
}
|
|
90556
91127
|
function parkedEdgeKey(e) {
|
|
90557
91128
|
return `${e.from}|${e.type}|${e.to}`;
|
|
@@ -90559,7 +91130,7 @@ function parkedEdgeKey(e) {
|
|
|
90559
91130
|
function loadCausalEdgeQueue(path3) {
|
|
90560
91131
|
let raw2;
|
|
90561
91132
|
try {
|
|
90562
|
-
raw2 = JSON.parse(
|
|
91133
|
+
raw2 = JSON.parse(readFileSync36(path3, "utf8"));
|
|
90563
91134
|
} catch {
|
|
90564
91135
|
return [];
|
|
90565
91136
|
}
|
|
@@ -90570,9 +91141,9 @@ function loadCausalEdgeQueue(path3) {
|
|
|
90570
91141
|
}
|
|
90571
91142
|
function saveCausalEdgeQueue(path3, queue) {
|
|
90572
91143
|
try {
|
|
90573
|
-
const tmp =
|
|
90574
|
-
|
|
90575
|
-
|
|
91144
|
+
const tmp = join40(dirname14(path3), `.${Date.now()}.causal-edge-queue.tmp`);
|
|
91145
|
+
writeFileSync26(tmp, JSON.stringify(queue), "utf8");
|
|
91146
|
+
renameSync6(tmp, path3);
|
|
90576
91147
|
} catch {
|
|
90577
91148
|
}
|
|
90578
91149
|
}
|
|
@@ -91243,8 +91814,8 @@ async function syncHistoryRevisionPage(opts) {
|
|
|
91243
91814
|
init_src7();
|
|
91244
91815
|
init_src();
|
|
91245
91816
|
import { execFile as execFile6 } from "node:child_process";
|
|
91246
|
-
import { readFileSync as
|
|
91247
|
-
import { join as
|
|
91817
|
+
import { readFileSync as readFileSync37 } from "node:fs";
|
|
91818
|
+
import { join as join41 } from "node:path";
|
|
91248
91819
|
import { promisify as promisify5 } from "node:util";
|
|
91249
91820
|
|
|
91250
91821
|
// src/history-walk.ts
|
|
@@ -91796,7 +92367,7 @@ async function defaultGit(root, args2) {
|
|
|
91796
92367
|
function readIgnoreLines(root, profile) {
|
|
91797
92368
|
let lines = [];
|
|
91798
92369
|
try {
|
|
91799
|
-
lines =
|
|
92370
|
+
lines = readFileSync37(join41(root, ".errataignore"), "utf8").split("\n");
|
|
91800
92371
|
} catch {
|
|
91801
92372
|
}
|
|
91802
92373
|
return [...lines, ...profile.ignoreExtra ?? []].map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
|
|
@@ -92372,8 +92943,8 @@ async function startHistoryStage(root, input, client, walk11 = {}) {
|
|
|
92372
92943
|
init_cloud_auth();
|
|
92373
92944
|
import { createHash as createHash19 } from "node:crypto";
|
|
92374
92945
|
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
92375
|
-
import { existsSync as existsSync32, writeFileSync as
|
|
92376
|
-
import { join as
|
|
92946
|
+
import { existsSync as existsSync32, writeFileSync as writeFileSync27 } from "node:fs";
|
|
92947
|
+
import { join as join42 } from "node:path";
|
|
92377
92948
|
|
|
92378
92949
|
// src/device-poll.ts
|
|
92379
92950
|
var THROTTLED_POLL_MIN_WAIT_MS = 11e3;
|
|
@@ -92832,9 +93403,9 @@ function applyLinkDecision(root, profile, config2, decision, now = Date.now) {
|
|
|
92832
93403
|
delete nextProfile.projectLinkHold;
|
|
92833
93404
|
let wroteIgnore = false;
|
|
92834
93405
|
if (decision.writeIgnoreStarter !== false) {
|
|
92835
|
-
const target =
|
|
93406
|
+
const target = join42(root, ".errataignore");
|
|
92836
93407
|
if (!existsSync32(target)) {
|
|
92837
|
-
|
|
93408
|
+
writeFileSync27(target, IGNORE_STARTER, "utf8");
|
|
92838
93409
|
wroteIgnore = true;
|
|
92839
93410
|
}
|
|
92840
93411
|
}
|
|
@@ -92848,12 +93419,12 @@ init_registry();
|
|
|
92848
93419
|
// src/adopt.ts
|
|
92849
93420
|
init_git_remote();
|
|
92850
93421
|
import { existsSync as existsSync33 } from "node:fs";
|
|
92851
|
-
import { dirname as
|
|
93422
|
+
import { dirname as dirname15, join as join43 } from "node:path";
|
|
92852
93423
|
function findGitRoot(absPath) {
|
|
92853
93424
|
let dir = absPath;
|
|
92854
93425
|
for (let depth = 0; depth < 64; depth++) {
|
|
92855
|
-
if (existsSync33(
|
|
92856
|
-
const parent =
|
|
93426
|
+
if (existsSync33(join43(dir, ".git"))) return dir;
|
|
93427
|
+
const parent = dirname15(dir);
|
|
92857
93428
|
if (parent === dir) return null;
|
|
92858
93429
|
dir = parent;
|
|
92859
93430
|
}
|
|
@@ -93570,7 +94141,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
93570
94141
|
records.push(rec);
|
|
93571
94142
|
void ambientLinkAll();
|
|
93572
94143
|
try {
|
|
93573
|
-
|
|
94144
|
+
writeFileSync28(
|
|
93574
94145
|
rec.engine.paths.daemonLock,
|
|
93575
94146
|
daemonLockPayload({
|
|
93576
94147
|
pid: process.pid,
|
|
@@ -93949,7 +94520,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
93949
94520
|
baseUrl = `http://127.0.0.1:${port}`;
|
|
93950
94521
|
try {
|
|
93951
94522
|
ensureDir(globalDir());
|
|
93952
|
-
|
|
94523
|
+
writeFileSync28(
|
|
93953
94524
|
lockPath,
|
|
93954
94525
|
daemonLockPayload({ pid: process.pid, webUiUrl: baseUrl, processStartedAt: PROCESS_STARTED_AT, entry: SELF_ENTRY, version: DAEMON_VERSION }),
|
|
93955
94526
|
"utf8"
|
|
@@ -93958,7 +94529,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
93958
94529
|
}
|
|
93959
94530
|
for (const r of records) {
|
|
93960
94531
|
try {
|
|
93961
|
-
|
|
94532
|
+
writeFileSync28(
|
|
93962
94533
|
r.engine.paths.daemonLock,
|
|
93963
94534
|
daemonLockPayload({
|
|
93964
94535
|
pid: process.pid,
|
|
@@ -94659,7 +95230,10 @@ async function startMultiDaemon(opts = {}) {
|
|
|
94659
95230
|
projectId: project?.projectId,
|
|
94660
95231
|
writeTarget: project ? null : receiptContext.context.default_write_target
|
|
94661
95232
|
});
|
|
95233
|
+
const parkPath = edgeParkPath(r.engine.paths.configDir, destinationKey);
|
|
95234
|
+
const parkQueue = loadEdgePark(parkPath);
|
|
94662
95235
|
const built = await buildInstanceBatch(r, {
|
|
95236
|
+
edgeHolds: edgeHolds(parkQueue, Date.now()),
|
|
94663
95237
|
destinationKey,
|
|
94664
95238
|
profile: r.engine.profile,
|
|
94665
95239
|
daemonVersion: DAEMON_VERSION,
|
|
@@ -94685,7 +95259,8 @@ async function startMultiDaemon(opts = {}) {
|
|
|
94685
95259
|
// straddle rows where the counter is merely absent.
|
|
94686
95260
|
blockedRepeat: 0,
|
|
94687
95261
|
rejectedRepeat: 0,
|
|
94688
|
-
edgesRejected: 0
|
|
95262
|
+
edgesRejected: 0,
|
|
95263
|
+
...zeroEdgeSettleCounts(parkQueue)
|
|
94689
95264
|
});
|
|
94690
95265
|
}
|
|
94691
95266
|
if (instances) {
|
|
@@ -94750,14 +95325,26 @@ async function startMultiDaemon(opts = {}) {
|
|
|
94750
95325
|
if (typeof cloudId === "string" && cloudId) cloudIds.set(localId, cloudId);
|
|
94751
95326
|
}
|
|
94752
95327
|
const edgeReceipts = instanceEdgeReceipts(instances.edges, res.result.edges, cloudIds);
|
|
95328
|
+
const echo = /* @__PURE__ */ new Map();
|
|
95329
|
+
for (const node2 of res.result.nodes) {
|
|
95330
|
+
if (node2.nodeId && node2.decision !== "rejected") echo.set(node2.canonicalId, node2.nodeId);
|
|
95331
|
+
}
|
|
95332
|
+
const settled = settleEdgeOutcomes(
|
|
95333
|
+
parkQueue,
|
|
95334
|
+
instances.edges,
|
|
95335
|
+
matchEdgeVerdicts(instances.edges, res.result.edges, echo),
|
|
95336
|
+
Date.now()
|
|
95337
|
+
);
|
|
95338
|
+
saveEdgePark(parkPath, settled.queue);
|
|
95339
|
+
const edgeCounts = settled.counts;
|
|
94753
95340
|
if (rejectedEdges.length > 0) {
|
|
94754
95341
|
const byReason = /* @__PURE__ */ new Map();
|
|
94755
95342
|
for (const re of rejectedEdges) {
|
|
94756
|
-
const why = `${re.type}: ${re.reason ?? "no reason given"}`;
|
|
95343
|
+
const why = `${re.type}: ${(re.reason ?? "no reason given").replace(/'[^']*'/g, "'\u2026'")}`;
|
|
94757
95344
|
byReason.set(why, (byReason.get(why) ?? 0) + 1);
|
|
94758
95345
|
}
|
|
94759
95346
|
console.warn(
|
|
94760
|
-
`[sync\u2192cloud] [${projectName}] instances: ${rejectedEdges.length} edge(s) REJECTED by the door: ` + [...byReason.entries()].map(([why, n]) => `${n}\xD7 ${why}`).join(" | ")
|
|
95347
|
+
`[sync\u2192cloud] [${projectName}] instances: ${rejectedEdges.length} edge(s) REJECTED by the door (parked ${edgeCounts.edgesParked}, re-parked ${edgeCounts.edgesReparked}, dropped ${edgeCounts.edgesDroppedRefused + edgeCounts.edgesDroppedExhausted + edgeCounts.edgesDroppedExpired}; park now ${edgeCounts.edgeParkSize}): ` + [...byReason.entries()].map(([why, n]) => `${n}\xD7 ${why}`).join(" | ")
|
|
94761
95348
|
);
|
|
94762
95349
|
}
|
|
94763
95350
|
if (rejected.size > 0) {
|
|
@@ -94834,7 +95421,13 @@ async function startMultiDaemon(opts = {}) {
|
|
|
94834
95421
|
});
|
|
94835
95422
|
});
|
|
94836
95423
|
let invalidatedReceipts = 0;
|
|
95424
|
+
const affirmedThisDrain = new Set(echo.values());
|
|
95425
|
+
let invalidationSkipped = 0;
|
|
94837
95426
|
for (const failedId of invalidInstanceEndpointIds(res.result.edges)) {
|
|
95427
|
+
if (affirmedThisDrain.has(failedId)) {
|
|
95428
|
+
invalidationSkipped++;
|
|
95429
|
+
continue;
|
|
95430
|
+
}
|
|
94838
95431
|
const localIds = new Set(instances.endpointSources[failedId] ?? []);
|
|
94839
95432
|
for (const [wireId, cloudId] of cloudIds) if (cloudId === failedId) {
|
|
94840
95433
|
for (const id of instances.endpointSources[wireId] ?? [instances.contextNodeSources[wireId] ?? wireId]) localIds.add(id);
|
|
@@ -94861,7 +95454,9 @@ async function startMultiDaemon(opts = {}) {
|
|
|
94861
95454
|
// failing every pass. Same total, different bug.
|
|
94862
95455
|
blockedRepeat,
|
|
94863
95456
|
rejectedRepeat,
|
|
94864
|
-
edgesRejected: rejectedEdges.length
|
|
95457
|
+
edgesRejected: rejectedEdges.length,
|
|
95458
|
+
invalidationSkipped,
|
|
95459
|
+
...edgeCounts
|
|
94865
95460
|
});
|
|
94866
95461
|
return res.accepted;
|
|
94867
95462
|
});
|
|
@@ -95453,7 +96048,7 @@ import { spawnSync as spawnSync2 } from "node:child_process";
|
|
|
95453
96048
|
|
|
95454
96049
|
// src/codex-runtime.ts
|
|
95455
96050
|
import { readdirSync as readdirSync13, statSync as statSync10 } from "node:fs";
|
|
95456
|
-
import { join as
|
|
96051
|
+
import { join as join44 } from "node:path";
|
|
95457
96052
|
function resolveCodexExecutable(options = {}) {
|
|
95458
96053
|
const platform = options.platform ?? process.platform;
|
|
95459
96054
|
const env2 = options.env ?? process.env;
|
|
@@ -95468,13 +96063,13 @@ function resolveCodexExecutable(options = {}) {
|
|
|
95468
96063
|
};
|
|
95469
96064
|
for (const dir of (env2["PATH"] ?? env2["Path"] ?? "").split(";")) {
|
|
95470
96065
|
if (!dir.trim()) continue;
|
|
95471
|
-
const path3 =
|
|
96066
|
+
const path3 = join44(dir.trim().replace(/^"|"$/g, ""), "codex.exe");
|
|
95472
96067
|
if (fileTime(path3) !== null) return path3;
|
|
95473
96068
|
}
|
|
95474
96069
|
if (!env2["LOCALAPPDATA"]) return "codex";
|
|
95475
|
-
const root =
|
|
96070
|
+
const root = join44(env2["LOCALAPPDATA"], "OpenAI", "Codex", "bin");
|
|
95476
96071
|
try {
|
|
95477
|
-
const candidates = readdirSync13(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) =>
|
|
96072
|
+
const candidates = readdirSync13(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join44(root, entry.name, "codex.exe")).map((path3) => ({ path: path3, mtime: fileTime(path3) })).filter((candidate) => candidate.mtime !== null).sort((a, b) => b.mtime - a.mtime || a.path.localeCompare(b.path));
|
|
95478
96073
|
return candidates[0]?.path ?? "codex";
|
|
95479
96074
|
} catch {
|
|
95480
96075
|
return "codex";
|
|
@@ -95613,14 +96208,14 @@ async function diagnoseInstallation(cfg, dependencies) {
|
|
|
95613
96208
|
|
|
95614
96209
|
// src/codex-doctor.ts
|
|
95615
96210
|
import { spawn as spawn4 } from "node:child_process";
|
|
95616
|
-
import { readFileSync as
|
|
95617
|
-
import { join as
|
|
96211
|
+
import { readFileSync as readFileSync39, statSync as statSync11 } from "node:fs";
|
|
96212
|
+
import { join as join46 } from "node:path";
|
|
95618
96213
|
import { createInterface } from "node:readline";
|
|
95619
96214
|
|
|
95620
96215
|
// src/codex-hooks.ts
|
|
95621
|
-
import { existsSync as existsSync35, mkdirSync as mkdirSync9, readFileSync as
|
|
96216
|
+
import { existsSync as existsSync35, mkdirSync as mkdirSync9, readFileSync as readFileSync38, renameSync as renameSync7, unlinkSync as unlinkSync5, writeFileSync as writeFileSync29 } from "node:fs";
|
|
95622
96217
|
import { homedir as homedir7 } from "node:os";
|
|
95623
|
-
import { join as
|
|
96218
|
+
import { join as join45 } from "node:path";
|
|
95624
96219
|
|
|
95625
96220
|
// src/hook-commands.ts
|
|
95626
96221
|
function hookCurlCommand(port, path3 = "/api/hook") {
|
|
@@ -95824,34 +96419,34 @@ function buildCodexRelaySource(workspaceRoot) {
|
|
|
95824
96419
|
init_checkout_root();
|
|
95825
96420
|
var CODEX_HOOK_REVIEW_HELP = "Codex desktop: Settings > Hooks, select this project, expand each event and Trust the Errata hook. CLI users can use /hooks.";
|
|
95826
96421
|
function writeRelay(file2, source) {
|
|
95827
|
-
if (existsSync35(file2) &&
|
|
96422
|
+
if (existsSync35(file2) && readFileSync38(file2, "utf8") === source) return;
|
|
95828
96423
|
const temp = `${file2}.${process.pid}.tmp`;
|
|
95829
96424
|
try {
|
|
95830
|
-
|
|
95831
|
-
|
|
96425
|
+
writeFileSync29(temp, source, { encoding: "utf8", mode: 384 });
|
|
96426
|
+
renameSync7(temp, file2);
|
|
95832
96427
|
} finally {
|
|
95833
96428
|
if (existsSync35(temp)) unlinkSync5(temp);
|
|
95834
96429
|
}
|
|
95835
96430
|
}
|
|
95836
96431
|
function refreshCodexRelay(root) {
|
|
95837
|
-
const config2 =
|
|
96432
|
+
const config2 = join45(root, ".codex", "config.toml");
|
|
95838
96433
|
if (!existsSync35(config2)) return "absent";
|
|
95839
|
-
const existing =
|
|
96434
|
+
const existing = readFileSync38(config2, "utf8");
|
|
95840
96435
|
if (!existing.includes(CODEX_HOOKS_BEGIN) && !existing.includes(CODEX_HOOKS_END)) return "absent";
|
|
95841
96436
|
replaceCodexHooks(existing, "");
|
|
95842
|
-
const relay =
|
|
95843
|
-
const prior = existsSync35(relay) ?
|
|
96437
|
+
const relay = join45(root, ".codex", "hooks", "errata-relay.mjs");
|
|
96438
|
+
const prior = existsSync35(relay) ? readFileSync38(relay, "utf8") : "";
|
|
95844
96439
|
if (prior && !prior.startsWith("// errata-managed: regenerated by errata install-hooks codex")) {
|
|
95845
96440
|
throw new Error("Codex relay is not Errata-managed; preserved it. Run errata install-hooks codex to explicitly replace it.");
|
|
95846
96441
|
}
|
|
95847
96442
|
const source = buildCodexRelaySource(checkoutRootOf(root));
|
|
95848
96443
|
if (prior === source) return "current";
|
|
95849
|
-
mkdirSync9(
|
|
96444
|
+
mkdirSync9(join45(root, ".codex", "hooks"), { recursive: true });
|
|
95850
96445
|
writeRelay(relay, source);
|
|
95851
96446
|
return "updated";
|
|
95852
96447
|
}
|
|
95853
|
-
function hasCodexConfig(root, codexHome = process.env["CODEX_HOME"] ||
|
|
95854
|
-
return existsSync35(
|
|
96448
|
+
function hasCodexConfig(root, codexHome = process.env["CODEX_HOME"] || join45(homedir7(), ".codex")) {
|
|
96449
|
+
return existsSync35(join45(root, ".codex")) || existsSync35(codexHome);
|
|
95855
96450
|
}
|
|
95856
96451
|
function replaceCodexHooks(existing, block) {
|
|
95857
96452
|
const begin = existing.indexOf(CODEX_HOOKS_BEGIN);
|
|
@@ -95867,14 +96462,14 @@ function replaceCodexHooks(existing, block) {
|
|
|
95867
96462
|
return existing.trimEnd() + (existing.trim() ? "\n\n" : "") + block;
|
|
95868
96463
|
}
|
|
95869
96464
|
function writeCodexHooks(root, port, nodePath = process.execPath) {
|
|
95870
|
-
const dir =
|
|
95871
|
-
const file2 =
|
|
95872
|
-
const relay =
|
|
96465
|
+
const dir = join45(root, ".codex");
|
|
96466
|
+
const file2 = join45(dir, "config.toml");
|
|
96467
|
+
const relay = join45(dir, "hooks", "errata-relay.mjs");
|
|
95873
96468
|
const block = buildCodexHooksToml(port, { nodePath, relayPath: relay });
|
|
95874
|
-
const final = replaceCodexHooks(existsSync35(file2) ?
|
|
95875
|
-
mkdirSync9(
|
|
96469
|
+
const final = replaceCodexHooks(existsSync35(file2) ? readFileSync38(file2, "utf8") : "", block);
|
|
96470
|
+
mkdirSync9(join45(dir, "hooks"), { recursive: true });
|
|
95876
96471
|
writeRelay(relay, buildCodexRelaySource(checkoutRootOf(root)));
|
|
95877
|
-
if (!existsSync35(file2) ||
|
|
96472
|
+
if (!existsSync35(file2) || readFileSync38(file2, "utf8") !== final) writeFileSync29(file2, final, "utf8");
|
|
95878
96473
|
return file2;
|
|
95879
96474
|
}
|
|
95880
96475
|
|
|
@@ -95883,7 +96478,7 @@ init_checkout_root();
|
|
|
95883
96478
|
function inspectCodexRelay(cwd) {
|
|
95884
96479
|
const root = nearestGitRoot(cwd) ?? cwd;
|
|
95885
96480
|
try {
|
|
95886
|
-
const source =
|
|
96481
|
+
const source = readFileSync39(join46(root, ".codex", "hooks", "errata-relay.mjs"), "utf8");
|
|
95887
96482
|
if (source === buildCodexRelaySource(checkoutRootOf(root))) {
|
|
95888
96483
|
return { id: "codex_relay", status: "pass", detail: "Installed Codex relay matches this Errata version" };
|
|
95889
96484
|
}
|
|
@@ -95894,8 +96489,8 @@ function inspectCodexRelay(cwd) {
|
|
|
95894
96489
|
function inspectCodexContext(cwd) {
|
|
95895
96490
|
const root = checkoutRootOf(nearestGitRoot(cwd) ?? cwd);
|
|
95896
96491
|
try {
|
|
95897
|
-
const file2 =
|
|
95898
|
-
if (statSync11(file2).size <= 128 * 1024 &&
|
|
96492
|
+
const file2 = join46(root, ".errata", "context.md");
|
|
96493
|
+
if (statSync11(file2).size <= 128 * 1024 && readFileSync39(file2, "utf8").trim()) {
|
|
95899
96494
|
return { id: "codex_context", status: "pass", detail: "Saved workspace context is readable by the relay; this does not prove live daemon freshness" };
|
|
95900
96495
|
}
|
|
95901
96496
|
} catch {
|
|
@@ -96073,9 +96668,9 @@ function consolidationGapMs(lastPassMs, policy) {
|
|
|
96073
96668
|
|
|
96074
96669
|
// src/codex-context-plugin.ts
|
|
96075
96670
|
import { createHash as createHash20 } from "node:crypto";
|
|
96076
|
-
import { cpSync as cpSync2, existsSync as existsSync36, mkdirSync as mkdirSync10, readFileSync as
|
|
96671
|
+
import { cpSync as cpSync2, existsSync as existsSync36, mkdirSync as mkdirSync10, readFileSync as readFileSync40, renameSync as renameSync8, writeFileSync as writeFileSync30 } from "node:fs";
|
|
96077
96672
|
import { homedir as homedir8 } from "node:os";
|
|
96078
|
-
import { join as
|
|
96673
|
+
import { join as join47 } from "node:path";
|
|
96079
96674
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
96080
96675
|
|
|
96081
96676
|
// ../../node_modules/.pnpm/smol-toml@1.6.1/node_modules/smol-toml/dist/error.js
|
|
@@ -96773,23 +97368,23 @@ var NAME = "errata-context";
|
|
|
96773
97368
|
var PREFIX2 = `./.errata/plugins/${NAME}/`;
|
|
96774
97369
|
var object2 = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
96775
97370
|
function readText(file2) {
|
|
96776
|
-
return existsSync36(file2) ?
|
|
97371
|
+
return existsSync36(file2) ? readFileSync40(file2, "utf8") : "";
|
|
96777
97372
|
}
|
|
96778
97373
|
function writeChanged(file2, content) {
|
|
96779
97374
|
if (readText(file2) === content) return;
|
|
96780
97375
|
const temp = `${file2}.${process.pid}.tmp`;
|
|
96781
|
-
|
|
96782
|
-
|
|
97376
|
+
writeFileSync30(temp, content, "utf8");
|
|
97377
|
+
renameSync8(temp, file2);
|
|
96783
97378
|
}
|
|
96784
97379
|
function bundledContextPlugin() {
|
|
96785
97380
|
const packaged = fileURLToPath2(new URL("./resources/context-plugin/", import.meta.url));
|
|
96786
|
-
if (existsSync36(
|
|
97381
|
+
if (existsSync36(join47(packaged, ".codex-plugin/plugin.json"))) return packaged;
|
|
96787
97382
|
return fileURLToPath2(new URL("../dist/resources/context-plugin/", import.meta.url));
|
|
96788
97383
|
}
|
|
96789
97384
|
function refreshCodexContextPlugin(root) {
|
|
96790
|
-
const file2 =
|
|
97385
|
+
const file2 = join47(root, ".agents", "plugins", "marketplace.json");
|
|
96791
97386
|
if (!existsSync36(file2)) return false;
|
|
96792
|
-
const marketplace = JSON.parse(
|
|
97387
|
+
const marketplace = JSON.parse(readFileSync40(file2, "utf8"));
|
|
96793
97388
|
const entries = Array.isArray(marketplace.plugins) ? marketplace.plugins : [];
|
|
96794
97389
|
const entry = entries.map(object2).find((value) => value.name === NAME && String(object2(value.source).path).startsWith(PREFIX2));
|
|
96795
97390
|
if (!entry) return false;
|
|
@@ -96800,24 +97395,24 @@ function refreshCodexContextPlugin(root) {
|
|
|
96800
97395
|
function installCodexContextPlugin(root, options = {}) {
|
|
96801
97396
|
const bundle = options.bundle ?? bundledContextPlugin();
|
|
96802
97397
|
const manifest = JSON.parse(
|
|
96803
|
-
|
|
97398
|
+
readFileSync40(join47(bundle, ".codex-plugin/plugin.json"), "utf8")
|
|
96804
97399
|
);
|
|
96805
97400
|
if (manifest.name !== NAME || typeof manifest.version !== "string" || !/^[\w.-]+$/.test(manifest.version)) {
|
|
96806
97401
|
throw new Error("Invalid bundled Errata Context manifest.");
|
|
96807
97402
|
}
|
|
96808
|
-
const checksums =
|
|
97403
|
+
const checksums = readFileSync40(join47(bundle, "SHA256SUMS"), "utf8");
|
|
96809
97404
|
for (const line of checksums.trim().split("\n")) {
|
|
96810
97405
|
const match2 = /^([a-f0-9]{64}) ([\w./-]+)$/.exec(line);
|
|
96811
97406
|
if (!match2 || match2[2].startsWith("/") || match2[2].split("/").includes("..")) {
|
|
96812
97407
|
throw new Error("Invalid bundled Errata Context checksum manifest.");
|
|
96813
97408
|
}
|
|
96814
|
-
const actual = createHash20("sha256").update(
|
|
97409
|
+
const actual = createHash20("sha256").update(readFileSync40(join47(bundle, match2[2]))).digest("hex");
|
|
96815
97410
|
if (actual !== match2[1])
|
|
96816
97411
|
throw new Error(`Bundled Errata Context checksum mismatch: ${match2[2]}`);
|
|
96817
97412
|
}
|
|
96818
97413
|
const release = `${manifest.version}-${createHash20("sha256").update(checksums).digest("hex").slice(0, 12)}`;
|
|
96819
|
-
const plugin =
|
|
96820
|
-
const marketplaceFile =
|
|
97414
|
+
const plugin = join47(root, ".errata", "plugins", NAME, release);
|
|
97415
|
+
const marketplaceFile = join47(root, ".agents", "plugins", "marketplace.json");
|
|
96821
97416
|
const priorMarketplace = readText(marketplaceFile);
|
|
96822
97417
|
const marketplace = priorMarketplace ? JSON.parse(priorMarketplace) : {
|
|
96823
97418
|
name: "errata-local",
|
|
@@ -96838,12 +97433,12 @@ function installCodexContextPlugin(root, options = {}) {
|
|
|
96838
97433
|
);
|
|
96839
97434
|
}
|
|
96840
97435
|
const key = `${NAME}@${marketplace.name}`;
|
|
96841
|
-
const configFile =
|
|
97436
|
+
const configFile = join47(root, ".codex", "config.toml");
|
|
96842
97437
|
const config2 = readText(configFile);
|
|
96843
97438
|
const parsed = parse4(config2);
|
|
96844
97439
|
const plugins = object2(parsed.plugins);
|
|
96845
|
-
const codexHome = options.codexHome ?? process.env["CODEX_HOME"] ??
|
|
96846
|
-
const globalPlugins = object2(parse4(readText(
|
|
97440
|
+
const codexHome = options.codexHome ?? process.env["CODEX_HOME"] ?? join47(homedir8(), ".codex");
|
|
97441
|
+
const globalPlugins = object2(parse4(readText(join47(codexHome, "config.toml"))).plugins);
|
|
96847
97442
|
const disabledGlobally = Object.entries(globalPlugins).some(
|
|
96848
97443
|
([name2, value]) => (name2 === NAME || name2.startsWith(`${NAME}@`)) && object2(value).enabled === false
|
|
96849
97444
|
);
|
|
@@ -96867,13 +97462,13 @@ enabled = ${enabled}
|
|
|
96867
97462
|
mkdirSync10(plugin, { recursive: true });
|
|
96868
97463
|
cpSync2(bundle, plugin, { recursive: true });
|
|
96869
97464
|
writeChanged(
|
|
96870
|
-
|
|
97465
|
+
join47(plugin, ".mcp.json"),
|
|
96871
97466
|
JSON.stringify(
|
|
96872
97467
|
{
|
|
96873
97468
|
mcpServers: {
|
|
96874
97469
|
errata_context: {
|
|
96875
97470
|
command: options.nodePath ?? process.execPath,
|
|
96876
|
-
args: [
|
|
97471
|
+
args: [join47(plugin, "dist", "mcp-server.mjs")],
|
|
96877
97472
|
env: { ERRATA_WORKSPACE: root, ERRATA_CONTEXT_VERSION: manifest.version }
|
|
96878
97473
|
}
|
|
96879
97474
|
}
|
|
@@ -96882,8 +97477,8 @@ enabled = ${enabled}
|
|
|
96882
97477
|
2
|
|
96883
97478
|
) + "\n"
|
|
96884
97479
|
);
|
|
96885
|
-
mkdirSync10(
|
|
96886
|
-
mkdirSync10(
|
|
97480
|
+
mkdirSync10(join47(root, ".agents", "plugins"), { recursive: true });
|
|
97481
|
+
mkdirSync10(join47(root, ".codex"), { recursive: true });
|
|
96887
97482
|
writeChanged(marketplaceFile, JSON.stringify(marketplace, null, 2) + "\n");
|
|
96888
97483
|
writeChanged(configFile, nextConfig);
|
|
96889
97484
|
return { plugin, enabled, marketplace: marketplaceFile };
|
|
@@ -96891,15 +97486,15 @@ enabled = ${enabled}
|
|
|
96891
97486
|
|
|
96892
97487
|
// src/codex-hook-refresh.ts
|
|
96893
97488
|
init_checkout_root();
|
|
96894
|
-
import { existsSync as existsSync37, readdirSync as readdirSync14, readFileSync as
|
|
96895
|
-
import { dirname as
|
|
97489
|
+
import { existsSync as existsSync37, readdirSync as readdirSync14, readFileSync as readFileSync41 } from "node:fs";
|
|
97490
|
+
import { dirname as dirname16, join as join48, resolve as resolve8 } from "node:path";
|
|
96896
97491
|
init_registry();
|
|
96897
97492
|
function codexHookRoots(roots) {
|
|
96898
97493
|
const found = new Set(roots.map((root) => resolve8(root)));
|
|
96899
97494
|
for (const root of [...found]) {
|
|
96900
97495
|
const main2 = mainCheckoutOfWorktree(root) ?? root;
|
|
96901
97496
|
found.add(main2);
|
|
96902
|
-
const dir =
|
|
97497
|
+
const dir = join48(main2, ".git", "worktrees");
|
|
96903
97498
|
if (!existsSync37(dir)) continue;
|
|
96904
97499
|
let names;
|
|
96905
97500
|
try {
|
|
@@ -96909,7 +97504,7 @@ function codexHookRoots(roots) {
|
|
|
96909
97504
|
}
|
|
96910
97505
|
for (const name2 of names) {
|
|
96911
97506
|
try {
|
|
96912
|
-
const checkout =
|
|
97507
|
+
const checkout = dirname16(readFileSync41(join48(dir, name2, "gitdir"), "utf8").trim());
|
|
96913
97508
|
if (mainCheckoutOfWorktree(checkout) === main2) found.add(checkout);
|
|
96914
97509
|
} catch {
|
|
96915
97510
|
}
|
|
@@ -96931,9 +97526,9 @@ function refreshInstalledCodexRelays(roots = listWorkspaceEntries().map((entry)
|
|
|
96931
97526
|
}
|
|
96932
97527
|
|
|
96933
97528
|
// src/claude-statusline.ts
|
|
96934
|
-
import { existsSync as existsSync38, mkdirSync as mkdirSync11, readFileSync as
|
|
97529
|
+
import { existsSync as existsSync38, mkdirSync as mkdirSync11, readFileSync as readFileSync42, writeFileSync as writeFileSync31 } from "node:fs";
|
|
96935
97530
|
import { homedir as homedir9 } from "node:os";
|
|
96936
|
-
import { dirname as
|
|
97531
|
+
import { dirname as dirname17, join as join49 } from "node:path";
|
|
96937
97532
|
var STATUSLINE_RELAY_SOURCE = String.raw`// errata-managed: regenerated by errata init / install-hooks claude
|
|
96938
97533
|
import { readFileSync } from 'node:fs';
|
|
96939
97534
|
|
|
@@ -96981,8 +97576,8 @@ function isSameInstall(value, relay) {
|
|
|
96981
97576
|
return command.includes(relay.replace(/\\/g, "/").toLowerCase());
|
|
96982
97577
|
}
|
|
96983
97578
|
function userClaudeSettingsPath() {
|
|
96984
|
-
const base = process.env["CLAUDE_CONFIG_DIR"] ??
|
|
96985
|
-
return
|
|
97579
|
+
const base = process.env["CLAUDE_CONFIG_DIR"] ?? join49(homedir9(), ".claude");
|
|
97580
|
+
return join49(base, "settings.json");
|
|
96986
97581
|
}
|
|
96987
97582
|
function ensureUserStatusLine(opts) {
|
|
96988
97583
|
const env2 = opts.env ?? process.env;
|
|
@@ -96992,21 +97587,21 @@ function ensureUserStatusLine(opts) {
|
|
|
96992
97587
|
let settings = {};
|
|
96993
97588
|
if (existsSync38(settingsPath)) {
|
|
96994
97589
|
try {
|
|
96995
|
-
const parsed = JSON.parse(
|
|
97590
|
+
const parsed = JSON.parse(readFileSync42(settingsPath, "utf8"));
|
|
96996
97591
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return "unreadable";
|
|
96997
97592
|
settings = parsed;
|
|
96998
97593
|
} catch {
|
|
96999
97594
|
return "unreadable";
|
|
97000
97595
|
}
|
|
97001
97596
|
}
|
|
97002
|
-
const relay =
|
|
97597
|
+
const relay = join49(opts.relayDir, STATUSLINE_RELAY_FILE);
|
|
97003
97598
|
const keep = (value) => value !== void 0 && (!isErrataStatusLine(value) || !isSameInstall(value, relay));
|
|
97004
97599
|
const ownMain = keep(settings["statusLine"]);
|
|
97005
97600
|
const ownRows = keep(settings["subagentStatusLine"]);
|
|
97006
97601
|
if (ownMain && ownRows) return "kept-own";
|
|
97007
97602
|
mkdirSync11(opts.relayDir, { recursive: true });
|
|
97008
|
-
if (!existsSync38(relay) ||
|
|
97009
|
-
|
|
97603
|
+
if (!existsSync38(relay) || readFileSync42(relay, "utf8") !== STATUSLINE_RELAY_SOURCE) {
|
|
97604
|
+
writeFileSync31(relay, STATUSLINE_RELAY_SOURCE, "utf8");
|
|
97010
97605
|
}
|
|
97011
97606
|
const nodePath = opts.nodePath ?? process.execPath;
|
|
97012
97607
|
const next = {
|
|
@@ -97017,8 +97612,8 @@ function ensureUserStatusLine(opts) {
|
|
|
97017
97612
|
return ownMain ? "kept-own" : "unchanged";
|
|
97018
97613
|
}
|
|
97019
97614
|
Object.assign(settings, next);
|
|
97020
|
-
mkdirSync11(
|
|
97021
|
-
|
|
97615
|
+
mkdirSync11(dirname17(settingsPath), { recursive: true });
|
|
97616
|
+
writeFileSync31(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf8");
|
|
97022
97617
|
return "installed";
|
|
97023
97618
|
}
|
|
97024
97619
|
function describeStatusLineOutcome(outcome) {
|
|
@@ -97038,8 +97633,8 @@ function describeStatusLineOutcome(outcome) {
|
|
|
97038
97633
|
|
|
97039
97634
|
// src/claude-mods.ts
|
|
97040
97635
|
import { createHash as createHash21 } from "node:crypto";
|
|
97041
|
-
import { cpSync as cpSync3, existsSync as existsSync39, mkdirSync as mkdirSync12, readFileSync as
|
|
97042
|
-
import { delimiter as delimiter2, dirname as
|
|
97636
|
+
import { cpSync as cpSync3, existsSync as existsSync39, mkdirSync as mkdirSync12, readFileSync as readFileSync43, readdirSync as readdirSync15, rmSync as rmSync4, statSync as statSync12, writeFileSync as writeFileSync32 } from "node:fs";
|
|
97637
|
+
import { delimiter as delimiter2, dirname as dirname18, join as join50, relative as relative8, resolve as resolve9, sep as sep5 } from "node:path";
|
|
97043
97638
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
97044
97639
|
var CLAUDE_PLUGIN_DIRS_ENV = "CLAUDE_CODE_PLUGIN_DIRS";
|
|
97045
97640
|
var HASH_FILE = ".errata-mod-hash";
|
|
@@ -97054,7 +97649,7 @@ function isEngineOwned(relPath) {
|
|
|
97054
97649
|
function listFiles(root, dir = root) {
|
|
97055
97650
|
const out2 = [];
|
|
97056
97651
|
for (const name2 of readdirSync15(dir)) {
|
|
97057
|
-
const abs =
|
|
97652
|
+
const abs = join50(dir, name2);
|
|
97058
97653
|
if (isEngineOwned(relative8(root, abs))) continue;
|
|
97059
97654
|
if (statSync12(abs).isDirectory()) out2.push(...listFiles(root, abs));
|
|
97060
97655
|
else out2.push(abs);
|
|
@@ -97066,14 +97661,14 @@ function modHash(dir) {
|
|
|
97066
97661
|
for (const abs of listFiles(dir).sort()) {
|
|
97067
97662
|
h.update(relative8(dir, abs).split(sep5).join("/"));
|
|
97068
97663
|
h.update("\0");
|
|
97069
|
-
h.update(
|
|
97664
|
+
h.update(readFileSync43(abs));
|
|
97070
97665
|
h.update("\0");
|
|
97071
97666
|
}
|
|
97072
97667
|
return h.digest("hex");
|
|
97073
97668
|
}
|
|
97074
97669
|
function bundledMods(bundleDir) {
|
|
97075
97670
|
if (!existsSync39(bundleDir)) return [];
|
|
97076
|
-
return readdirSync15(bundleDir).filter((name2) => existsSync39(
|
|
97671
|
+
return readdirSync15(bundleDir).filter((name2) => existsSync39(join50(bundleDir, name2, ".claude-plugin", "plugin.json")));
|
|
97077
97672
|
}
|
|
97078
97673
|
function sameDir(a, b) {
|
|
97079
97674
|
const norm = (p) => resolve9(p).replace(/[\\/]+$/, "").toLowerCase();
|
|
@@ -97090,7 +97685,7 @@ function off(env2) {
|
|
|
97090
97685
|
function readSettings(path3) {
|
|
97091
97686
|
if (!existsSync39(path3)) return {};
|
|
97092
97687
|
try {
|
|
97093
|
-
const parsed = JSON.parse(
|
|
97688
|
+
const parsed = JSON.parse(readFileSync43(path3, "utf8"));
|
|
97094
97689
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null;
|
|
97095
97690
|
return parsed;
|
|
97096
97691
|
} catch {
|
|
@@ -97114,13 +97709,13 @@ function currentDirs(settings) {
|
|
|
97114
97709
|
return raw2.split(delimiter2).map((s) => s.trim()).filter(Boolean);
|
|
97115
97710
|
}
|
|
97116
97711
|
function writeSettings(path3, settings) {
|
|
97117
|
-
mkdirSync12(
|
|
97118
|
-
|
|
97712
|
+
mkdirSync12(dirname18(path3), { recursive: true });
|
|
97713
|
+
writeFileSync32(path3, JSON.stringify(settings, null, 2) + "\n", "utf8");
|
|
97119
97714
|
}
|
|
97120
97715
|
function ensureClaudeMods(opts) {
|
|
97121
97716
|
const env2 = opts.env ?? process.env;
|
|
97122
97717
|
const settingsPath = opts.userSettingsPath ?? userClaudeSettingsPath();
|
|
97123
|
-
const modsRoot =
|
|
97718
|
+
const modsRoot = join50(opts.installRoot, "claude-mods");
|
|
97124
97719
|
if (off(env2)) {
|
|
97125
97720
|
const settings2 = readSettings(settingsPath);
|
|
97126
97721
|
if (!settings2) return { kind: "unreadable" };
|
|
@@ -97137,14 +97732,14 @@ function ensureClaudeMods(opts) {
|
|
|
97137
97732
|
let changed = false;
|
|
97138
97733
|
const installed = [];
|
|
97139
97734
|
for (const name2 of names) {
|
|
97140
|
-
const src =
|
|
97141
|
-
const dest =
|
|
97735
|
+
const src = join50(bundleDir, name2);
|
|
97736
|
+
const dest = join50(modsRoot, name2);
|
|
97142
97737
|
const hash2 = modHash(src);
|
|
97143
|
-
const hashFile =
|
|
97144
|
-
if (!existsSync39(hashFile) ||
|
|
97738
|
+
const hashFile = join50(dest, HASH_FILE);
|
|
97739
|
+
if (!existsSync39(hashFile) || readFileSync43(hashFile, "utf8") !== hash2) {
|
|
97145
97740
|
rmSync4(dest, { recursive: true, force: true });
|
|
97146
97741
|
cpSync3(src, dest, { recursive: true, filter: (p) => !isEngineOwned(relative8(src, p)) });
|
|
97147
|
-
|
|
97742
|
+
writeFileSync32(hashFile, hash2, "utf8");
|
|
97148
97743
|
changed = true;
|
|
97149
97744
|
}
|
|
97150
97745
|
installed.push(dest);
|
|
@@ -97565,9 +98160,9 @@ function resolveHookPort(explicit) {
|
|
|
97565
98160
|
}
|
|
97566
98161
|
}
|
|
97567
98162
|
}
|
|
97568
|
-
const settingsPath =
|
|
98163
|
+
const settingsPath = join51(ROOT, ".claude", "settings.json");
|
|
97569
98164
|
try {
|
|
97570
|
-
if (existsSync40(settingsPath)) return installedHookPort(
|
|
98165
|
+
if (existsSync40(settingsPath)) return installedHookPort(readFileSync44(settingsPath, "utf8")) ?? 7891;
|
|
97571
98166
|
} catch {
|
|
97572
98167
|
}
|
|
97573
98168
|
return 7891;
|
|
@@ -97593,13 +98188,13 @@ async function cmdInit() {
|
|
|
97593
98188
|
console.log("");
|
|
97594
98189
|
console.log("installing harness hooks...");
|
|
97595
98190
|
const { existsSync: existsSync41 } = await import("node:fs");
|
|
97596
|
-
const { join:
|
|
98191
|
+
const { join: join52 } = await import("node:path");
|
|
97597
98192
|
try {
|
|
97598
98193
|
await installClaudeHooks(port);
|
|
97599
98194
|
} catch (err2) {
|
|
97600
98195
|
console.warn(` \u26A0\uFE0F Claude hook install failed: ${err2 instanceof Error ? err2.message : err2}`);
|
|
97601
98196
|
}
|
|
97602
|
-
if (existsSync41(
|
|
98197
|
+
if (existsSync41(join52(ROOT, ".cursor"))) {
|
|
97603
98198
|
try {
|
|
97604
98199
|
await installCursorMcpConfig();
|
|
97605
98200
|
} catch (err2) {
|
|
@@ -98821,7 +99416,7 @@ async function cmdReview() {
|
|
|
98821
99416
|
console.log("(review queue empty)");
|
|
98822
99417
|
return;
|
|
98823
99418
|
}
|
|
98824
|
-
const queue = JSON.parse(
|
|
99419
|
+
const queue = JSON.parse(readFileSync44(paths.reviewQueue, "utf8"));
|
|
98825
99420
|
if (queue.length === 0) {
|
|
98826
99421
|
console.log("(review queue empty)");
|
|
98827
99422
|
return;
|
|
@@ -99560,7 +100155,7 @@ async function gatherReportData(generatedAt) {
|
|
|
99560
100155
|
};
|
|
99561
100156
|
}
|
|
99562
100157
|
async function cmdReport(args2) {
|
|
99563
|
-
const { mkdirSync: mkdirSync13, writeFileSync:
|
|
100158
|
+
const { mkdirSync: mkdirSync13, writeFileSync: writeFileSync33 } = await import("node:fs");
|
|
99564
100159
|
const { renderReport: renderReport2 } = await Promise.resolve().then(() => (init_report_render(), report_render_exports));
|
|
99565
100160
|
const includeFutureVerbs = args2.includes("--future-verbs");
|
|
99566
100161
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -99573,8 +100168,8 @@ async function cmdReport(args2) {
|
|
|
99573
100168
|
const outDir = workspacePaths(ROOT).configDir;
|
|
99574
100169
|
mkdirSync13(outDir, { recursive: true });
|
|
99575
100170
|
const files = renderReport2(data, { includeFutureVerbs });
|
|
99576
|
-
for (const f of files)
|
|
99577
|
-
const indexPath =
|
|
100171
|
+
for (const f of files) writeFileSync33(join51(outDir, f.name), f.html, "utf8");
|
|
100172
|
+
const indexPath = join51(outDir, "report.html");
|
|
99578
100173
|
console.log(`report \u2192 ${indexPath}`);
|
|
99579
100174
|
console.log(
|
|
99580
100175
|
` ${data.repos.length} repo(s) \xB7 ${files.length} file(s) \xB7 ${data.rollup.nodes.toLocaleString("en-US")} nodes`
|
|
@@ -99630,7 +100225,7 @@ function spawnDaemonDetached(options = {}) {
|
|
|
99630
100225
|
try {
|
|
99631
100226
|
const logPath = daemonLogPath();
|
|
99632
100227
|
try {
|
|
99633
|
-
if (statSync13(logPath).size > 5 * 1024 * 1024)
|
|
100228
|
+
if (statSync13(logPath).size > 5 * 1024 * 1024) renameSync9(logPath, `${logPath}.1`);
|
|
99634
100229
|
} catch {
|
|
99635
100230
|
}
|
|
99636
100231
|
out2 = openSync3(logPath, "a");
|
|
@@ -99699,24 +100294,24 @@ async function cmdInstallHooks(args2) {
|
|
|
99699
100294
|
}
|
|
99700
100295
|
}
|
|
99701
100296
|
async function installOpencodePlugin(port) {
|
|
99702
|
-
const { mkdirSync: mkdirSync13, existsSync: existsSync41, readFileSync:
|
|
99703
|
-
const { join:
|
|
99704
|
-
const dir =
|
|
100297
|
+
const { mkdirSync: mkdirSync13, existsSync: existsSync41, readFileSync: readFileSync45, writeFileSync: writeFileSync33 } = await import("node:fs");
|
|
100298
|
+
const { join: join52 } = await import("node:path");
|
|
100299
|
+
const dir = join52(ROOT, ".opencode", "plugin");
|
|
99705
100300
|
if (!existsSync41(dir)) mkdirSync13(dir, { recursive: true });
|
|
99706
|
-
const file2 =
|
|
100301
|
+
const file2 = join52(dir, "inerrata.js");
|
|
99707
100302
|
if (existsSync41(file2)) {
|
|
99708
|
-
const head2 =
|
|
100303
|
+
const head2 = readFileSync45(file2, "utf8").split("\n")[0] ?? "";
|
|
99709
100304
|
if (head2.trim() !== OPENCODE_PLUGIN_MARKER) {
|
|
99710
100305
|
console.error(`refusing to overwrite ${file2}: not an errata-managed plugin (line 1 lacks the marker)`);
|
|
99711
100306
|
process.exit(2);
|
|
99712
100307
|
}
|
|
99713
100308
|
}
|
|
99714
|
-
|
|
99715
|
-
const cfgFile =
|
|
100309
|
+
writeFileSync33(file2, buildOpencodePluginSource(port, { version: DAEMON_VERSION }), "utf8");
|
|
100310
|
+
const cfgFile = join52(ROOT, "opencode.json");
|
|
99716
100311
|
let cfg = { $schema: "https://opencode.ai/config.json" };
|
|
99717
100312
|
if (existsSync41(cfgFile)) {
|
|
99718
100313
|
try {
|
|
99719
|
-
cfg = JSON.parse(
|
|
100314
|
+
cfg = JSON.parse(readFileSync45(cfgFile, "utf8"));
|
|
99720
100315
|
} catch {
|
|
99721
100316
|
console.error(`refusing to touch invalid JSON at ${cfgFile} \u2014 fix it and re-run`);
|
|
99722
100317
|
process.exit(2);
|
|
@@ -99727,7 +100322,7 @@ async function installOpencodePlugin(port) {
|
|
|
99727
100322
|
if (!hadErrata) {
|
|
99728
100323
|
const inv = errataMcpInvocation();
|
|
99729
100324
|
cfg.mcp["errata"] = { type: "local", command: [inv.command, ...inv.args] };
|
|
99730
|
-
|
|
100325
|
+
writeFileSync33(cfgFile, JSON.stringify(cfg, null, 2) + "\n", "utf8");
|
|
99731
100326
|
}
|
|
99732
100327
|
console.log(`installed OpenCode plugin \u2192 ${file2}`);
|
|
99733
100328
|
if (hadErrata) console.log(` mcp.errata already present in ${cfgFile} \u2014 left untouched`);
|
|
@@ -99762,15 +100357,15 @@ function installClaudeMods() {
|
|
|
99762
100357
|
}
|
|
99763
100358
|
}
|
|
99764
100359
|
async function installClaudeHooks(port) {
|
|
99765
|
-
const { mkdirSync: mkdirSync13, existsSync: existsSync41, readFileSync:
|
|
99766
|
-
const { join:
|
|
99767
|
-
const dir =
|
|
100360
|
+
const { mkdirSync: mkdirSync13, existsSync: existsSync41, readFileSync: readFileSync45, writeFileSync: writeFileSync33 } = await import("node:fs");
|
|
100361
|
+
const { join: join52 } = await import("node:path");
|
|
100362
|
+
const dir = join52(ROOT, ".claude");
|
|
99768
100363
|
if (!existsSync41(dir)) mkdirSync13(dir, { recursive: true });
|
|
99769
|
-
const file2 =
|
|
100364
|
+
const file2 = join52(dir, "settings.json");
|
|
99770
100365
|
let settings = {};
|
|
99771
100366
|
if (existsSync41(file2)) {
|
|
99772
100367
|
try {
|
|
99773
|
-
settings = JSON.parse(
|
|
100368
|
+
settings = JSON.parse(readFileSync45(file2, "utf8"));
|
|
99774
100369
|
} catch {
|
|
99775
100370
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
99776
100371
|
process.exit(2);
|
|
@@ -99819,12 +100414,12 @@ async function installClaudeHooks(port) {
|
|
|
99819
100414
|
list.push({ hooks: [{ type: "command", command: injectCmd }] });
|
|
99820
100415
|
}
|
|
99821
100416
|
removeProjectStatusLine(settings);
|
|
99822
|
-
|
|
100417
|
+
writeFileSync33(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
|
|
99823
100418
|
console.log(`installed Claude Code hooks \u2192 ${file2}`);
|
|
99824
100419
|
console.log(` ${ensureStatusLine(port)}`);
|
|
99825
100420
|
console.log(` ${installClaudeMods().line}`);
|
|
99826
100421
|
await installClaudeMcpConfig();
|
|
99827
|
-
const claudeMd =
|
|
100422
|
+
const claudeMd = join52(ROOT, "CLAUDE.md");
|
|
99828
100423
|
const recall = writeManagedBlock(claudeMd, { body: RECALL_FIRST_BLOCK });
|
|
99829
100424
|
if (recall.kind === "collision") {
|
|
99830
100425
|
console.warn(
|
|
@@ -99836,15 +100431,15 @@ async function installClaudeHooks(port) {
|
|
|
99836
100431
|
console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
|
|
99837
100432
|
}
|
|
99838
100433
|
async function installClaudeMcpConfig() {
|
|
99839
|
-
const { mkdirSync: mkdirSync13, existsSync: existsSync41, readFileSync:
|
|
99840
|
-
const { join:
|
|
99841
|
-
const file2 =
|
|
99842
|
-
const dir =
|
|
100434
|
+
const { mkdirSync: mkdirSync13, existsSync: existsSync41, readFileSync: readFileSync45, writeFileSync: writeFileSync33 } = await import("node:fs");
|
|
100435
|
+
const { join: join52, dirname: dirname19 } = await import("node:path");
|
|
100436
|
+
const file2 = join52(ROOT, ".mcp.json");
|
|
100437
|
+
const dir = dirname19(file2);
|
|
99843
100438
|
if (!existsSync41(dir)) mkdirSync13(dir, { recursive: true });
|
|
99844
100439
|
let cfg = {};
|
|
99845
100440
|
if (existsSync41(file2)) {
|
|
99846
100441
|
try {
|
|
99847
|
-
cfg = JSON.parse(
|
|
100442
|
+
cfg = JSON.parse(readFileSync45(file2, "utf8"));
|
|
99848
100443
|
} catch {
|
|
99849
100444
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
99850
100445
|
process.exit(2);
|
|
@@ -99852,21 +100447,21 @@ async function installClaudeMcpConfig() {
|
|
|
99852
100447
|
}
|
|
99853
100448
|
cfg.mcpServers ??= {};
|
|
99854
100449
|
cfg.mcpServers["errata"] = errataMcpInvocation();
|
|
99855
|
-
|
|
100450
|
+
writeFileSync33(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
|
|
99856
100451
|
console.log(`installed Claude Code MCP server config \u2192 ${file2}`);
|
|
99857
100452
|
console.log(` Claude Code will spawn \`errata mcp\` on workspace open.`);
|
|
99858
100453
|
console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses / show / similar`);
|
|
99859
100454
|
}
|
|
99860
100455
|
async function installCursorMcpConfig() {
|
|
99861
|
-
const { mkdirSync: mkdirSync13, existsSync: existsSync41, readFileSync:
|
|
99862
|
-
const { join:
|
|
99863
|
-
const dir =
|
|
100456
|
+
const { mkdirSync: mkdirSync13, existsSync: existsSync41, readFileSync: readFileSync45, writeFileSync: writeFileSync33 } = await import("node:fs");
|
|
100457
|
+
const { join: join52 } = await import("node:path");
|
|
100458
|
+
const dir = join52(ROOT, ".cursor");
|
|
99864
100459
|
if (!existsSync41(dir)) mkdirSync13(dir, { recursive: true });
|
|
99865
|
-
const file2 =
|
|
100460
|
+
const file2 = join52(dir, "mcp.json");
|
|
99866
100461
|
let cfg = {};
|
|
99867
100462
|
if (existsSync41(file2)) {
|
|
99868
100463
|
try {
|
|
99869
|
-
cfg = JSON.parse(
|
|
100464
|
+
cfg = JSON.parse(readFileSync45(file2, "utf8"));
|
|
99870
100465
|
} catch {
|
|
99871
100466
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
99872
100467
|
process.exit(2);
|
|
@@ -99874,7 +100469,7 @@ async function installCursorMcpConfig() {
|
|
|
99874
100469
|
}
|
|
99875
100470
|
cfg.mcpServers ??= {};
|
|
99876
100471
|
cfg.mcpServers["errata"] = errataMcpInvocation();
|
|
99877
|
-
|
|
100472
|
+
writeFileSync33(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
|
|
99878
100473
|
console.log(`installed Cursor MCP server config \u2192 ${file2}`);
|
|
99879
100474
|
console.log(` Cursor will spawn \`errata mcp\` on workspace open.`);
|
|
99880
100475
|
console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses`);
|
|
@@ -99885,7 +100480,7 @@ async function installCodexHooks(port) {
|
|
|
99885
100480
|
const gitRoot = nearestGitRoot(process.cwd());
|
|
99886
100481
|
const hookRoot = gitRoot && mainCheckoutOfWorktree(gitRoot) ? gitRoot : ROOT;
|
|
99887
100482
|
const file2 = writeCodexHooks(hookRoot, port);
|
|
99888
|
-
const instructions = writeManagedBlock(
|
|
100483
|
+
const instructions = writeManagedBlock(join51(hookRoot, "AGENTS.md"), {
|
|
99889
100484
|
body: AGENTS_POINTER_BODY,
|
|
99890
100485
|
stable: true
|
|
99891
100486
|
});
|
|
@@ -100331,9 +100926,9 @@ async function cmdDash(args2) {
|
|
|
100331
100926
|
await yieldToLoop2();
|
|
100332
100927
|
try {
|
|
100333
100928
|
const items = selectDurableMemory(handle2.sharedStore, r.engine.profile, {
|
|
100334
|
-
atCommit: readGitRefState(
|
|
100929
|
+
atCommit: readGitRefState(join51(r.root, ".git")).sha ?? void 0
|
|
100335
100930
|
});
|
|
100336
|
-
const res = bleedRules(
|
|
100931
|
+
const res = bleedRules(join51(r.root, ".claude", "rules"), items);
|
|
100337
100932
|
if (res.written || res.pruned) {
|
|
100338
100933
|
console.log(
|
|
100339
100934
|
`[rules:${r.entry.name}] ${res.written} collective principle(s) \u2192 .claude/rules` + (res.pruned ? `, ${res.pruned} pruned` : "")
|