@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/errata.mjs CHANGED
@@ -18137,20 +18137,20 @@ function openDatabase(path3, opts) {
18137
18137
  } catch {
18138
18138
  }
18139
18139
  }
18140
- const wrapStmt = (stmt) => ({
18140
+ const wrapStmt = (stmt2) => ({
18141
18141
  run: (...params) => {
18142
- const r = stmt.run(...coerceParams(params));
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 = stmt.get(...coerceParams(params));
18149
+ const r = stmt2.get(...coerceParams(params));
18150
18150
  return r;
18151
18151
  },
18152
18152
  all: (...params) => {
18153
- const r = stmt.all(...coerceParams(params));
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 stmt = this.fieldStmts.get(cacheKey2);
20905
- if (!stmt) {
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
- stmt = this.db.prepare(
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, stmt);
21087
+ this.fieldStmts.set(cacheKey2, stmt2);
20911
21088
  }
20912
- return stmt.all(label).map((r) => {
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 stmt = this.typedEdgeStmt(
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 stmt.all(...chunk)) labels.set(row.id, row.label);
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 stmt = this.typedEdgeStmts.get(sql);
21239
- if (!stmt) {
21240
- stmt = this.db.prepare(sql);
21241
- this.typedEdgeStmts.set(sql, stmt);
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 stmt;
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
- let revived = 0;
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 r = this.db.prepare(
21450
- `UPDATE nodes SET valid_to = NULL
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
- ).run(since, workspaceId2, ...slice);
21456
- revived += Number(r.changes);
21457
- }
21458
- if (revived > 0) this.mutations++;
21459
- return revived;
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 stmt = statement.trim();
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: stmt });
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(stmt, cand.description);
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(stmt);
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 stmt = statement.trim();
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: stmt });
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(stmt, cand.description);
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 ?? 8;
26057
- const marked = store.selectNodes({
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
- }).sort((a, b) => {
26066
- const ma = a.attrs["foldCandidate"].ts ?? 0;
26067
- const mb = b.attrs["foldCandidate"].ts ?? 0;
26068
- return ma - mb;
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
- // Standing nominations ARE the judge-less backlog — without the gauge a
26664
- // deployment with no judge configured reads as "nothing to fold".
26665
- backlogCounter: "standing",
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
- const totalChunks = single ? 1 : nodePlan.length + Math.ceil(pendingEdges.length / INGEST_EDGE_CHUNK);
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 store.inEdges(m.fromNid, ["CALLS", "ACCESSES", "ANCHORED_AT"])) {
38083
- if (e.validTo != null) continue;
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(stmt) {
44176
- if (!stmt) return null;
44177
- if (stmt.type !== "expression_statement") return null;
44178
- const expr = stmt.namedChild(0);
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 readFileSync43, renameSync as renameSync8, statSync as statSync13 } from "node:fs";
76431
- import { join as join50, resolve as pathResolve2 } from "node:path";
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 dirname18 = sysPath.dirname(file2);
78229
+ const dirname19 = sysPath.dirname(file2);
77897
78230
  const basename10 = sysPath.basename(file2);
77898
- const parent = this.fsw._getWatchedDir(dirname18);
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(dirname18, basename10);
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 statements = /* @__PURE__ */ new Set();
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) statements.add(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 statements) {
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.4173" : "2.0.0-alpha.0";
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 writeFileSync27 } from "node:fs";
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 readFileSync33 } from "node:fs";
88995
- import { join as join36 } from "node:path";
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 = join36(opts.root, c.file);
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(readFileSync33(p, "utf8"));
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 readFileSync34, readdirSync as readdirSync12, existsSync as existsSync31 } from "node:fs";
89213
- import { join as join37 } from "node:path";
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 = join37(dir, "package.json");
89790
+ const pj = join38(dir, "package.json");
89247
89791
  if (!existsSync31(pj)) return;
89248
89792
  try {
89249
- const name2 = JSON.parse(readFileSync34(pj, "utf8")).name;
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 = join37(workspaceRoot, group);
89800
+ const groupDir = join38(workspaceRoot, group);
89257
89801
  if (!existsSync31(groupDir)) continue;
89258
89802
  try {
89259
- for (const entry of readdirSync12(groupDir)) tryRead(join37(groupDir, entry));
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 readFileSync34(absPath, "utf8").slice(0, HEAD_BYTES);
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(join37(workspaceRoot, rel));
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 join38 } from "node:path";
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, [join38(root, PACKAGE_NAME, "errata.mjs"), "install-hooks", "codex", "--refresh-existing"], {
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 readFileSync35, renameSync as renameSync5, writeFileSync as writeFileSync25 } from "node:fs";
90550
- import { dirname as dirname13, join as join39 } from "node:path";
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 join39(workspaceConfigDir, "causal-edge-queue.json");
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(readFileSync35(path3, "utf8"));
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 = join39(dirname13(path3), `.${Date.now()}.causal-edge-queue.tmp`);
90574
- writeFileSync25(tmp, JSON.stringify(queue), "utf8");
90575
- renameSync5(tmp, path3);
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 readFileSync36 } from "node:fs";
91247
- import { join as join40 } from "node:path";
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 = readFileSync36(join40(root, ".errataignore"), "utf8").split("\n");
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 writeFileSync26 } from "node:fs";
92376
- import { join as join41 } from "node:path";
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 = join41(root, ".errataignore");
93406
+ const target = join42(root, ".errataignore");
92836
93407
  if (!existsSync32(target)) {
92837
- writeFileSync26(target, IGNORE_STARTER, "utf8");
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 dirname14, join as join42 } from "node:path";
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(join42(dir, ".git"))) return dir;
92856
- const parent = dirname14(dir);
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
- writeFileSync27(
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
- writeFileSync27(
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
- writeFileSync27(
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 join43 } from "node:path";
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 = join43(dir.trim().replace(/^"|"$/g, ""), "codex.exe");
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 = join43(env2["LOCALAPPDATA"], "OpenAI", "Codex", "bin");
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) => join43(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));
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 readFileSync38, statSync as statSync11 } from "node:fs";
95617
- import { join as join45 } from "node:path";
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 readFileSync37, renameSync as renameSync6, unlinkSync as unlinkSync5, writeFileSync as writeFileSync28 } from "node:fs";
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 join44 } from "node:path";
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) && readFileSync37(file2, "utf8") === source) return;
96422
+ if (existsSync35(file2) && readFileSync38(file2, "utf8") === source) return;
95828
96423
  const temp = `${file2}.${process.pid}.tmp`;
95829
96424
  try {
95830
- writeFileSync28(temp, source, { encoding: "utf8", mode: 384 });
95831
- renameSync6(temp, file2);
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 = join44(root, ".codex", "config.toml");
96432
+ const config2 = join45(root, ".codex", "config.toml");
95838
96433
  if (!existsSync35(config2)) return "absent";
95839
- const existing = readFileSync37(config2, "utf8");
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 = join44(root, ".codex", "hooks", "errata-relay.mjs");
95843
- const prior = existsSync35(relay) ? readFileSync37(relay, "utf8") : "";
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(join44(root, ".codex", "hooks"), { recursive: true });
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"] || join44(homedir7(), ".codex")) {
95854
- return existsSync35(join44(root, ".codex")) || existsSync35(codexHome);
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 = join44(root, ".codex");
95871
- const file2 = join44(dir, "config.toml");
95872
- const relay = join44(dir, "hooks", "errata-relay.mjs");
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) ? readFileSync37(file2, "utf8") : "", block);
95875
- mkdirSync9(join44(dir, "hooks"), { recursive: true });
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) || readFileSync37(file2, "utf8") !== final) writeFileSync28(file2, final, "utf8");
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 = readFileSync38(join45(root, ".codex", "hooks", "errata-relay.mjs"), "utf8");
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 = join45(root, ".errata", "context.md");
95898
- if (statSync11(file2).size <= 128 * 1024 && readFileSync38(file2, "utf8").trim()) {
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 readFileSync39, renameSync as renameSync7, writeFileSync as writeFileSync29 } from "node:fs";
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 join46 } from "node:path";
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) ? readFileSync39(file2, "utf8") : "";
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
- writeFileSync29(temp, content, "utf8");
96782
- renameSync7(temp, file2);
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(join46(packaged, ".codex-plugin/plugin.json"))) return packaged;
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 = join46(root, ".agents", "plugins", "marketplace.json");
97385
+ const file2 = join47(root, ".agents", "plugins", "marketplace.json");
96791
97386
  if (!existsSync36(file2)) return false;
96792
- const marketplace = JSON.parse(readFileSync39(file2, "utf8"));
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
- readFileSync39(join46(bundle, ".codex-plugin/plugin.json"), "utf8")
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 = readFileSync39(join46(bundle, "SHA256SUMS"), "utf8");
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(readFileSync39(join46(bundle, match2[2]))).digest("hex");
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 = join46(root, ".errata", "plugins", NAME, release);
96820
- const marketplaceFile = join46(root, ".agents", "plugins", "marketplace.json");
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 = join46(root, ".codex", "config.toml");
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"] ?? join46(homedir8(), ".codex");
96846
- const globalPlugins = object2(parse4(readText(join46(codexHome, "config.toml"))).plugins);
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
- join46(plugin, ".mcp.json"),
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: [join46(plugin, "dist", "mcp-server.mjs")],
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(join46(root, ".agents", "plugins"), { recursive: true });
96886
- mkdirSync10(join46(root, ".codex"), { recursive: true });
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 readFileSync40 } from "node:fs";
96895
- import { dirname as dirname15, join as join47, resolve as resolve8 } from "node:path";
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 = join47(main2, ".git", "worktrees");
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 = dirname15(readFileSync40(join47(dir, name2, "gitdir"), "utf8").trim());
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 readFileSync41, writeFileSync as writeFileSync30 } from "node:fs";
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 dirname16, join as join48 } from "node:path";
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"] ?? join48(homedir9(), ".claude");
96985
- return join48(base, "settings.json");
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(readFileSync41(settingsPath, "utf8"));
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 = join48(opts.relayDir, STATUSLINE_RELAY_FILE);
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) || readFileSync41(relay, "utf8") !== STATUSLINE_RELAY_SOURCE) {
97009
- writeFileSync30(relay, STATUSLINE_RELAY_SOURCE, "utf8");
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(dirname16(settingsPath), { recursive: true });
97021
- writeFileSync30(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf8");
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 readFileSync42, readdirSync as readdirSync15, rmSync as rmSync4, statSync as statSync12, writeFileSync as writeFileSync31 } from "node:fs";
97042
- import { delimiter as delimiter2, dirname as dirname17, join as join49, relative as relative8, resolve as resolve9, sep as sep5 } from "node:path";
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 = join49(dir, name2);
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(readFileSync42(abs));
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(join49(bundleDir, name2, ".claude-plugin", "plugin.json")));
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(readFileSync42(path3, "utf8"));
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(dirname17(path3), { recursive: true });
97118
- writeFileSync31(path3, JSON.stringify(settings, null, 2) + "\n", "utf8");
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 = join49(opts.installRoot, "claude-mods");
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 = join49(bundleDir, name2);
97141
- const dest = join49(modsRoot, name2);
97735
+ const src = join50(bundleDir, name2);
97736
+ const dest = join50(modsRoot, name2);
97142
97737
  const hash2 = modHash(src);
97143
- const hashFile = join49(dest, HASH_FILE);
97144
- if (!existsSync39(hashFile) || readFileSync42(hashFile, "utf8") !== hash2) {
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
- writeFileSync31(hashFile, hash2, "utf8");
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 = join50(ROOT, ".claude", "settings.json");
98163
+ const settingsPath = join51(ROOT, ".claude", "settings.json");
97569
98164
  try {
97570
- if (existsSync40(settingsPath)) return installedHookPort(readFileSync43(settingsPath, "utf8")) ?? 7891;
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: join51 } = await import("node:path");
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(join51(ROOT, ".cursor"))) {
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(readFileSync43(paths.reviewQueue, "utf8"));
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: writeFileSync32 } = await import("node:fs");
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) writeFileSync32(join50(outDir, f.name), f.html, "utf8");
99577
- const indexPath = join50(outDir, "report.html");
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) renameSync8(logPath, `${logPath}.1`);
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: readFileSync44, writeFileSync: writeFileSync32 } = await import("node:fs");
99703
- const { join: join51 } = await import("node:path");
99704
- const dir = join51(ROOT, ".opencode", "plugin");
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 = join51(dir, "inerrata.js");
100301
+ const file2 = join52(dir, "inerrata.js");
99707
100302
  if (existsSync41(file2)) {
99708
- const head2 = readFileSync44(file2, "utf8").split("\n")[0] ?? "";
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
- writeFileSync32(file2, buildOpencodePluginSource(port, { version: DAEMON_VERSION }), "utf8");
99715
- const cfgFile = join51(ROOT, "opencode.json");
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(readFileSync44(cfgFile, "utf8"));
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
- writeFileSync32(cfgFile, JSON.stringify(cfg, null, 2) + "\n", "utf8");
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: readFileSync44, writeFileSync: writeFileSync32 } = await import("node:fs");
99766
- const { join: join51 } = await import("node:path");
99767
- const dir = join51(ROOT, ".claude");
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 = join51(dir, "settings.json");
100364
+ const file2 = join52(dir, "settings.json");
99770
100365
  let settings = {};
99771
100366
  if (existsSync41(file2)) {
99772
100367
  try {
99773
- settings = JSON.parse(readFileSync44(file2, "utf8"));
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
- writeFileSync32(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
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 = join51(ROOT, "CLAUDE.md");
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: readFileSync44, writeFileSync: writeFileSync32 } = await import("node:fs");
99840
- const { join: join51, dirname: dirname18 } = await import("node:path");
99841
- const file2 = join51(ROOT, ".mcp.json");
99842
- const dir = dirname18(file2);
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(readFileSync44(file2, "utf8"));
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
- writeFileSync32(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
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: readFileSync44, writeFileSync: writeFileSync32 } = await import("node:fs");
99862
- const { join: join51 } = await import("node:path");
99863
- const dir = join51(ROOT, ".cursor");
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 = join51(dir, "mcp.json");
100460
+ const file2 = join52(dir, "mcp.json");
99866
100461
  let cfg = {};
99867
100462
  if (existsSync41(file2)) {
99868
100463
  try {
99869
- cfg = JSON.parse(readFileSync44(file2, "utf8"));
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
- writeFileSync32(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
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(join50(hookRoot, "AGENTS.md"), {
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(join50(r.root, ".git")).sha ?? void 0
100929
+ atCommit: readGitRefState(join51(r.root, ".git")).sha ?? void 0
100335
100930
  });
100336
- const res = bleedRules(join50(r.root, ".claude", "rules"), items);
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` : "")