@inerrata-corporation/errata 2.0.22-dev.4430 → 2.0.22-dev.4534

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
@@ -17425,6 +17425,12 @@ var init_history_temporal = __esm({
17425
17425
  });
17426
17426
 
17427
17427
  // ../../packages/shared/src/history-revision.ts
17428
+ function settledHistoryReceipt(evidence) {
17429
+ if (!evidence || typeof evidence !== "object") return false;
17430
+ const e = evidence;
17431
+ const review = e["review"];
17432
+ return e["build"] === HISTORY_RECONCILE_BUILD && e["reviewStatus"] !== "failed-provider" && review?.["status"] !== "failed-schema" && (e["reviewStatus"] !== "deferred-budget" || e["reviewPolicy"] === HISTORY_REVIEW_POLICY);
17433
+ }
17428
17434
  function historyDag(records) {
17429
17435
  const graph = new Map(records.map((r) => [r.commit, r.parents]));
17430
17436
  if (graph.size !== records.length) throw new Error("duplicate Git commit in history proof");
@@ -17481,7 +17487,7 @@ function preservedHistoryOccurrence(o, observed, atCommit, ancestor) {
17481
17487
  if (!anchors?.length || anchors.some((a) => a.side !== "after" || !a.bodyHash || !observed.symbols.some((s) => s.symbolId === a.symbolId && s.bodyHash === a.bodyHash))) return false;
17482
17488
  return parsed.data.every((e) => anchors.some((a) => a.blockDigest === e.blockDigest && a.startByte <= e.startByte && a.endByte >= e.endByte));
17483
17489
  }
17484
- var Sha, HistoryRevisionRequestSchema;
17490
+ var Sha, HistoryRevisionRequestSchema, HistoryCarryRequestSchema, HISTORY_REVIEW_BUDGET, HISTORY_REVIEW_POLICY;
17485
17491
  var init_history_revision = __esm({
17486
17492
  "../../packages/shared/src/history-revision.ts"() {
17487
17493
  "use strict";
@@ -17501,6 +17507,17 @@ var init_history_revision = __esm({
17501
17507
  dependencyContext: HistoryDependencyContextSchema.optional()
17502
17508
  })).max(50)
17503
17509
  });
17510
+ HistoryCarryRequestSchema = external_exports.strictObject({
17511
+ fromCommit: Sha,
17512
+ atCommit: Sha,
17513
+ parents: external_exports.array(external_exports.strictObject({ commit: Sha, parents: external_exports.array(Sha).max(32) })).max(8192),
17514
+ /** Every symbol in a file the range changed, both sides; `null` = too many to name, treat all as changed. */
17515
+ changedSymbols: external_exports.array(external_exports.string().regex(/^sym_[a-f0-9]{8,64}$/)).max(5e3).nullable(),
17516
+ /** Manifests the range changed; `null` = a lockfile (or too many manifests) changed, treat all as changed. */
17517
+ changedManifests: external_exports.array(external_exports.string().regex(/^hmanifest_[a-f0-9]{32}$/)).max(512).nullable()
17518
+ });
17519
+ HISTORY_REVIEW_BUDGET = 48e3;
17520
+ HISTORY_REVIEW_POLICY = `reviewer-view-${HISTORY_REVIEW_BUDGET}`;
17504
17521
  }
17505
17522
  });
17506
17523
 
@@ -17608,10 +17625,13 @@ __export(src_exports, {
17608
17625
  HISTORY_MAX_SPINE_DEPS: () => HISTORY_MAX_SPINE_DEPS,
17609
17626
  HISTORY_MAX_TEXT_CHARS: () => HISTORY_MAX_TEXT_CHARS,
17610
17627
  HISTORY_RECONCILE_BUILD: () => HISTORY_RECONCILE_BUILD,
17628
+ HISTORY_REVIEW_BUDGET: () => HISTORY_REVIEW_BUDGET,
17629
+ HISTORY_REVIEW_POLICY: () => HISTORY_REVIEW_POLICY,
17611
17630
  HISTORY_SCRUBBER_VERSION: () => HISTORY_SCRUBBER_VERSION,
17612
17631
  HistoryAnchorSourceSchema: () => HistoryAnchorSourceSchema,
17613
17632
  HistoryCandidateBatchSchema: () => HistoryCandidateBatchSchema,
17614
17633
  HistoryCandidateSchema: () => HistoryCandidateSchema,
17634
+ HistoryCarryRequestSchema: () => HistoryCarryRequestSchema,
17615
17635
  HistoryDependencyContextSchema: () => HistoryDependencyContextSchema,
17616
17636
  HistoryDependencySchema: () => HistoryDependencySchema,
17617
17637
  HistoryEvidenceRefSchema: () => HistoryEvidenceRefSchema,
@@ -17750,6 +17770,7 @@ __export(src_exports, {
17750
17770
  scrubHistoryText: () => scrubHistoryText,
17751
17771
  scrubHistoryValue: () => scrubHistoryValue,
17752
17772
  selectHistoryDependencies: () => selectHistoryDependencies,
17773
+ settledHistoryReceipt: () => settledHistoryReceipt,
17753
17774
  sha256: () => sha256,
17754
17775
  sha256Short: () => sha256Short,
17755
17776
  sidecarDropBucket: () => sidecarDropBucket,
@@ -17826,8 +17847,8 @@ ${endMarker}
17826
17847
  const startM = current.match(START_RE);
17827
17848
  const endM = current.match(END_RE);
17828
17849
  if (!startM || !endM || startM.index === void 0 || endM.index === void 0) {
17829
- const sep6 = current.endsWith("\n") ? "" : "\n";
17830
- writeFileSync(filePath, `${current}${sep6}
17850
+ const sep7 = current.endsWith("\n") ? "" : "\n";
17851
+ writeFileSync(filePath, `${current}${sep7}
17831
17852
  ${blockText}`, "utf8");
17832
17853
  return { kind: "created", newHash };
17833
17854
  }
@@ -19145,6 +19166,129 @@ var init_text_index = __esm({
19145
19166
  }
19146
19167
  });
19147
19168
 
19169
+ // ../../packages/local-graph/src/exposure-attrs.ts
19170
+ var EXPOSURE_ATTRS, EXPOSURE_SCOPE;
19171
+ var init_exposure_attrs = __esm({
19172
+ "../../packages/local-graph/src/exposure-attrs.ts"() {
19173
+ "use strict";
19174
+ EXPOSURE_ATTRS = [
19175
+ "shownCount",
19176
+ "evictedCount",
19177
+ "firstShownAt",
19178
+ "firstEvictedAt",
19179
+ "firstShownAtSeq",
19180
+ "lastShownAtSeq",
19181
+ "lastEvictedAtSeq",
19182
+ "shownSinceTouch",
19183
+ "shownSinceTouchAt",
19184
+ "exposureLog",
19185
+ "exposureLogStart",
19186
+ "exposureLogSince",
19187
+ "exposureFirst",
19188
+ "exposureTrimmed"
19189
+ ];
19190
+ EXPOSURE_SCOPE = "exposure";
19191
+ }
19192
+ });
19193
+
19194
+ // ../../packages/local-graph/src/change-feed.ts
19195
+ function installChangeFeed(db) {
19196
+ if (changeFeedInstalled(db)) return;
19197
+ db.transaction(() => {
19198
+ db.exec("CREATE TABLE IF NOT EXISTS change_seq (scope TEXT PRIMARY KEY, seq INTEGER NOT NULL) WITHOUT ROWID");
19199
+ db.exec(`CREATE TABLE IF NOT EXISTS change_log (change_seq INTEGER PRIMARY KEY, kind TEXT NOT NULL, id TEXT NOT NULL,
19200
+ label TEXT, from_id TEXT, to_id TEXT)`);
19201
+ for (const name2 of ["nodes", "edges"].flatMap((t) => ["insert", "update", "delete"].map((op) => `change_feed_${t}_${op}`))) {
19202
+ db.exec(`DROP TRIGGER IF EXISTS ${name2}`);
19203
+ }
19204
+ const changed = (table) => columns(db, table).map((c) => `OLD."${c}" IS NOT NEW."${c}"`).join(" OR ");
19205
+ const strip3 = (row) => `json_remove(${row}.attrs_json, ${EXPOSURE_ATTRS.map((a) => `'$.${a}'`).join(", ")})`;
19206
+ const exposureOnly = `(${columns(db, "nodes").filter((c) => c !== "attrs_json").map((c) => `OLD."${c}" IS NEW."${c}"`).join(" AND ")}
19207
+ AND CASE WHEN json_valid(OLD.attrs_json) AND json_valid(NEW.attrs_json) THEN ${strip3("OLD")} IS ${strip3("NEW")} ELSE 0 END)`;
19208
+ const bump = (...scopes) => `INSERT INTO change_seq(scope, seq) VALUES ${scopes.map((s) => `(${s}, 1)`).join(", ")}
19209
+ ON CONFLICT(scope) DO UPDATE SET seq = seq + 1;`;
19210
+ const seq = `(SELECT seq FROM change_seq WHERE scope = '*')`;
19211
+ const logNode = (row) => `INSERT INTO change_log(change_seq, kind, id, label) VALUES (${seq}, 'node', ${row}.id, ${row}.label);`;
19212
+ const logEdge = (row) => `INSERT INTO change_log(change_seq, kind, id, label, from_id, to_id) VALUES (${seq}, 'edge', ${row}.id, ${row}.type, ${row}.from_id, ${row}.to_id);`;
19213
+ const node2 = (row) => `'node:' || ${row}.label`;
19214
+ const edge2 = (row) => `'edge:' || ${row}.type`;
19215
+ db.exec(`CREATE TRIGGER change_feed_nodes_insert AFTER INSERT ON nodes BEGIN ${bump(`'*'`, node2("NEW"))} ${logNode("NEW")} END;`);
19216
+ db.exec(`CREATE TRIGGER change_feed_nodes_update AFTER UPDATE ON nodes WHEN ${changed("nodes")} BEGIN
19217
+ ${bump(`'*'`)}
19218
+ INSERT INTO change_seq(scope, seq) SELECT CASE WHEN ${exposureOnly} THEN '${EXPOSURE_SCOPE}' ELSE ${node2("NEW")} END, 1 WHERE 1
19219
+ ON CONFLICT(scope) DO UPDATE SET seq = seq + 1;
19220
+ INSERT INTO change_seq(scope, seq) SELECT ${node2("OLD")}, 1 WHERE OLD.label IS NOT NEW.label
19221
+ ON CONFLICT(scope) DO UPDATE SET seq = seq + 1;
19222
+ ${logNode("NEW")}
19223
+ END;`);
19224
+ db.exec(`CREATE TRIGGER change_feed_nodes_delete AFTER DELETE ON nodes BEGIN ${bump(`'*'`, node2("OLD"))} ${logNode("OLD")} END;`);
19225
+ db.exec(`CREATE TRIGGER change_feed_edges_insert AFTER INSERT ON edges BEGIN ${bump(`'*'`, edge2("NEW"))} ${logEdge("NEW")} END;`);
19226
+ db.exec(`CREATE TRIGGER change_feed_edges_update AFTER UPDATE ON edges WHEN ${changed("edges")} BEGIN
19227
+ ${bump(`'*'`, edge2("NEW"))}
19228
+ INSERT INTO change_seq(scope, seq) SELECT ${edge2("OLD")}, 1 WHERE OLD.type IS NOT NEW.type
19229
+ ON CONFLICT(scope) DO UPDATE SET seq = seq + 1;
19230
+ ${logEdge("NEW")}
19231
+ END;`);
19232
+ db.exec(`CREATE TRIGGER change_feed_edges_delete AFTER DELETE ON edges BEGIN ${bump(`'*'`, edge2("OLD"))} ${logEdge("OLD")} END;`);
19233
+ db.prepare("INSERT OR REPLACE INTO store_meta(key, value) VALUES (?, ?)").run(PRUNED_TO_KEY, String(readChangeSeq(db)));
19234
+ db.prepare("INSERT OR REPLACE INTO store_meta(key, value) VALUES (?, ?)").run(CHANGE_FEED_KEY, columnSignature(db));
19235
+ });
19236
+ }
19237
+ function readChangeSeq(db, scopes = [ANY_CHANGE]) {
19238
+ if (!scopes.length) return 0;
19239
+ const row = db.prepare(`SELECT coalesce(sum(seq), 0) AS n FROM change_seq WHERE scope IN (${scopes.map(() => "?").join(",")})`).get(...scopes);
19240
+ return Number(row?.n ?? 0);
19241
+ }
19242
+ function changeLogCovers(db, sinceSeq) {
19243
+ const prunedTo = Number(db.prepare("SELECT value FROM store_meta WHERE key = ?").get(PRUNED_TO_KEY)?.["value"] ?? NaN);
19244
+ return Number.isFinite(prunedTo) && sinceSeq >= prunedTo;
19245
+ }
19246
+ function readLineageChangedFiles(db, sinceSeq) {
19247
+ if (!changeLogCovers(db, sinceSeq)) return null;
19248
+ const rows = db.prepare(LINEAGE_CHANGED_FILES_SQL).all({ s: sinceSeq });
19249
+ return rows.map((r) => r.id);
19250
+ }
19251
+ function pruneChangeLog(db) {
19252
+ const max = Number(db.prepare("SELECT coalesce(max(change_seq), 0) AS n FROM change_log").get()?.["n"] ?? 0);
19253
+ const cut = max - CHANGE_LOG_KEEP;
19254
+ if (cut <= 0) return 0;
19255
+ let removed = 0;
19256
+ db.transaction(() => {
19257
+ removed = Number(db.prepare("DELETE FROM change_log WHERE change_seq <= ?").run(cut).changes);
19258
+ const prev = Number(db.prepare("SELECT value FROM store_meta WHERE key = ?").get(PRUNED_TO_KEY)?.["value"] ?? 0);
19259
+ db.prepare("INSERT OR REPLACE INTO store_meta(key, value) VALUES (?, ?)").run(PRUNED_TO_KEY, String(Math.max(prev, cut)));
19260
+ });
19261
+ return removed;
19262
+ }
19263
+ function changeFeedInstalled(db) {
19264
+ return db.prepare("SELECT value FROM store_meta WHERE key = ?").get(CHANGE_FEED_KEY)?.["value"] === columnSignature(db);
19265
+ }
19266
+ function columns(db, table) {
19267
+ return db.prepare(`SELECT name FROM pragma_table_info('${table}') ORDER BY cid`).all().map((r) => r.name);
19268
+ }
19269
+ function columnSignature(db) {
19270
+ return `5|${columns(db, "nodes").join(",")}|${columns(db, "edges").join(",")}|${EXPOSURE_ATTRS.join(",")}`;
19271
+ }
19272
+ var CHANGE_FEED_KEY, ANY_CHANGE, nodeScope, edgeScope, CHANGE_LOG_KEEP, PRUNED_TO_KEY, LINEAGE_CHANGED_FILES_SQL;
19273
+ var init_change_feed = __esm({
19274
+ "../../packages/local-graph/src/change-feed.ts"() {
19275
+ "use strict";
19276
+ init_exposure_attrs();
19277
+ CHANGE_FEED_KEY = "change-feed";
19278
+ ANY_CHANGE = "*";
19279
+ nodeScope = (label) => `node:${label}`;
19280
+ edgeScope = (type) => `edge:${type}`;
19281
+ CHANGE_LOG_KEEP = 25e4;
19282
+ PRUNED_TO_KEY = "change-log-pruned-to";
19283
+ LINEAGE_CHANGED_FILES_SQL = `
19284
+ SELECT id FROM change_log WHERE change_seq > :s AND kind = 'node' AND label = 'File'
19285
+ UNION SELECT from_id FROM change_log WHERE change_seq > :s AND kind = 'edge' AND label IN ('DEFINES','CONTAINS')
19286
+ UNION SELECT e.from_id FROM (SELECT DISTINCT id FROM change_log WHERE change_seq > :s AND kind = 'node') c
19287
+ CROSS JOIN edges e ON e.to_id = c.id AND e.type IN ('DEFINES','CONTAINS')
19288
+ `;
19289
+ }
19290
+ });
19291
+
19148
19292
  // ../../packages/local-graph/src/lineage-integrity.ts
19149
19293
  function stmt(db, sql) {
19150
19294
  let byDb = statements.get(db);
@@ -20399,6 +20543,7 @@ function graphStoreNeedsPreparation(path3) {
20399
20543
  for (const match2 of (SCHEMA_SQL + TEMPORAL_INDEX_SQL).matchAll(/CREATE INDEX IF NOT EXISTS (\w+)/g)) {
20400
20544
  if (!indexes.has(match2[1])) return true;
20401
20545
  }
20546
+ if (!changeFeedInstalled(db)) return true;
20402
20547
  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));
20403
20548
  } catch {
20404
20549
  return true;
@@ -20478,6 +20623,7 @@ var init_store = __esm({
20478
20623
  init_cloud_attr_compaction();
20479
20624
  init_history_attr_slim();
20480
20625
  init_text_index();
20626
+ init_change_feed();
20481
20627
  init_lineage_integrity();
20482
20628
  init_src3();
20483
20629
  init_node_select();
@@ -20705,6 +20851,7 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
20705
20851
  });
20706
20852
  }
20707
20853
  installLineageIntegrityRepair(this.db);
20854
+ installChangeFeed(this.db);
20708
20855
  this.stmts = {
20709
20856
  insertNode: this.db.prepare(`
20710
20857
  INSERT INTO nodes (
@@ -21492,12 +21639,39 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
21492
21639
  mutationCount() {
21493
21640
  return this.mutations;
21494
21641
  }
21642
+ changeStamp() {
21643
+ const { data_version } = this.db.pragma("data_version");
21644
+ const { n } = this.db.prepare("SELECT total_changes() AS n").get();
21645
+ return `${data_version}:${n}`;
21646
+ }
21647
+ changeSeq(scopes) {
21648
+ return readChangeSeq(this.db, scopes);
21649
+ }
21650
+ lineageChangedFiles(sinceSeq) {
21651
+ return readLineageChangedFiles(this.db, sinceSeq);
21652
+ }
21653
+ pruneChangeLog() {
21654
+ return pruneChangeLog(this.db);
21655
+ }
21656
+ fileRowStates(ids) {
21657
+ if (ids.length === 0) return [];
21658
+ if (ids.length > 500) throw new RangeError("fileRowStates accepts at most 500 ids per read");
21659
+ return this.db.prepare(`SELECT id, last_updated_at AS lastUpdatedAt, valid_to AS validTo FROM nodes WHERE id IN (${ids.map(() => "?").join(",")})`).all(...ids);
21660
+ }
21661
+ // Read and advanced in SQL, never from a per-connection copy: pass workers and
21662
+ // MCP processes open their own connections and advance the same row, so a
21663
+ // copy loaded at open went stale, and `copy + 1` wrote a duplicate or a
21664
+ // backwards seq from whichever connection had fallen behind.
21495
21665
  currentIngestSeq() {
21666
+ const row = this.db.prepare("SELECT value FROM store_meta WHERE key = 'ingest_seq'").get();
21667
+ this.ingestSeq = row ? Number(row.value) : 0;
21496
21668
  return this.ingestSeq;
21497
21669
  }
21498
21670
  nextIngestSeq() {
21499
- this.ingestSeq += 1;
21500
- this.stmts.setIngestSeq.run({ v: String(this.ingestSeq) });
21671
+ const row = this.db.prepare(
21672
+ "INSERT INTO store_meta (key, value) VALUES ('ingest_seq', '1') ON CONFLICT(key) DO UPDATE SET value = CAST(value AS INTEGER) + 1 RETURNING value"
21673
+ ).get();
21674
+ this.ingestSeq = Number(row.value);
21501
21675
  return this.ingestSeq;
21502
21676
  }
21503
21677
  edgeCount() {
@@ -27128,14 +27302,17 @@ var init_wm_calibration = __esm({
27128
27302
  // ../../packages/local-graph/src/index.ts
27129
27303
  var src_exports2 = {};
27130
27304
  __export(src_exports2, {
27305
+ ANY_CHANGE: () => ANY_CHANGE,
27131
27306
  AUTO_MINT_PREFIX: () => AUTO_MINT_PREFIX,
27132
27307
  CAUSAL_FAMILY: () => CAUSAL_FAMILY,
27133
27308
  CITABLE_PRIOR_LABELS: () => CITABLE_PRIOR_LABELS,
27134
27309
  CODE_REACH_EDGES: () => CODE_REACH_EDGES,
27135
27310
  CREDIT_FAMILY: () => CREDIT_FAMILY,
27136
27311
  DEFAULT_MIN_COVERAGE: () => DEFAULT_MIN_COVERAGE,
27312
+ EXPOSURE_ATTRS: () => EXPOSURE_ATTRS,
27137
27313
  EXPOSURE_LOG_KEYS: () => EXPOSURE_LOG_KEYS,
27138
27314
  EXPOSURE_LOG_MAX: () => EXPOSURE_LOG_MAX,
27315
+ EXPOSURE_SCOPE: () => EXPOSURE_SCOPE,
27139
27316
  FINGERPRINT_INDEXED_LABELS: () => FINGERPRINT_INDEXED_LABELS,
27140
27317
  FIX_CANDIDATE_ASK_LIMIT: () => FIX_CANDIDATE_ASK_LIMIT,
27141
27318
  FOLD_EMBED_AUTO_COSINE: () => FOLD_EMBED_AUTO_COSINE,
@@ -27208,6 +27385,7 @@ __export(src_exports2, {
27208
27385
  designProblemId: () => designProblemId,
27209
27386
  detectLocalCommunities: () => detectLocalCommunities,
27210
27387
  edgeConductance: () => edgeConductance,
27388
+ edgeScope: () => edgeScope,
27211
27389
  evaluateDependency: () => evaluateDependency,
27212
27390
  evaluateFed: () => evaluateFed,
27213
27391
  evaluateMechanisms: () => evaluateMechanisms,
@@ -27261,6 +27439,7 @@ __export(src_exports2, {
27261
27439
  mintDomainNode: () => mintDomainNode,
27262
27440
  mintPatternNode: () => mintPatternNode,
27263
27441
  mintWorkspaceCausalFact: () => mintWorkspaceCausalFact,
27442
+ nodeScope: () => nodeScope,
27264
27443
  openGraphStore: () => openGraphStore,
27265
27444
  osNodeId: () => osNodeId,
27266
27445
  parseAbstractionFences: () => parseAbstractionFences,
@@ -27321,6 +27500,8 @@ var init_src5 = __esm({
27321
27500
  "use strict";
27322
27501
  init_store();
27323
27502
  init_types();
27503
+ init_change_feed();
27504
+ init_exposure_attrs();
27324
27505
  init_traversal();
27325
27506
  init_justification();
27326
27507
  init_credit();
@@ -27374,12 +27555,12 @@ function buildSnapshot(opts) {
27374
27555
  const problems = opts.store.selectNodes({ labels: ["Problem", "Vulnerability"], attrs: PROBLEM_BAND_ATTRS }).filter((p) => p.attrs["mergedInto"] === void 0 && passiveAllowed(p, opts.atCommit));
27375
27556
  const stillOpen = problems.filter((p) => p.attrs["resolvedAt"] == null);
27376
27557
  const allProblems = rankRecentBand(stillOpen.filter((p) => !isConstraintProblem(p)));
27377
- const openPool = allProblems.slice(0, RECENT_OPEN * SCOPE_POOL_FACTOR).map((p) => ({
27558
+ const openPool = allProblems.slice(0, Math.max(RECENT_OPEN * SCOPE_POOL_FACTOR, RECENT_WINDOW_BANDS * RECENT_OPEN)).map((p) => ({
27378
27559
  node: hydrate(p.id),
27379
27560
  anchors: opts.store.outEdges(p.id, ["MANIFESTED_IN", "EVIDENCED_BY"])
27380
27561
  }));
27381
27562
  const recent4 = openPool.slice(0, RECENT_OPEN);
27382
- const constraintPool = rankRecentBand(stillOpen.filter((p) => isConstraintProblem(p)), { window: RECENT_WINDOW_BANDS * RECENT_CONSTRAINTS }).slice(0, RECENT_CONSTRAINTS * SCOPE_POOL_FACTOR).map((p) => hydrate(p.id));
27563
+ const constraintPool = rankRecentBand(stillOpen.filter((p) => isConstraintProblem(p)), { window: RECENT_WINDOW_BANDS * RECENT_CONSTRAINTS }).slice(0, Math.max(RECENT_CONSTRAINTS * SCOPE_POOL_FACTOR, RECENT_WINDOW_BANDS * RECENT_CONSTRAINTS)).map((p) => hydrate(p.id));
27383
27564
  const recentConstraints = constraintPool.slice(0, RECENT_CONSTRAINTS);
27384
27565
  const regressionSources = /* @__PURE__ */ new Set();
27385
27566
  for (const target of opts.store.inDegreeByType(["REGRESSION_OF"]).keys()) {
@@ -27489,6 +27670,22 @@ function rankRecentBand(problems, { quota = RECENT_SHOW_QUOTA, window: window2 =
27489
27670
  const head2 = byRecency.slice(0, window2);
27490
27671
  return [...head2.filter((p) => !spent(p)), ...head2.filter(spent), ...byRecency.slice(window2)];
27491
27672
  }
27673
+ function freshenRecentBands(s, read2) {
27674
+ const pool = s.scopePool;
27675
+ if (!pool) return s;
27676
+ const fresh = (n) => read2(n.id) ?? n;
27677
+ const openRows = pool.open.map((r) => ({ ...r, node: fresh(r.node) }));
27678
+ const openOrder = rankRecentBand(openRows.map((r) => r.node), { window: openRows.length });
27679
+ const byId = new Map(openRows.map((r) => [r.node.id, r]));
27680
+ const open2 = openOrder.map((n) => byId.get(n.id));
27681
+ const constraints = rankRecentBand(pool.constraints.map(fresh), { window: pool.constraints.length });
27682
+ return {
27683
+ ...s,
27684
+ recentProblems: open2.slice(0, RECENT_OPEN),
27685
+ recentConstraints: constraints.slice(0, RECENT_CONSTRAINTS),
27686
+ scopePool: { ...pool, open: open2, constraints }
27687
+ };
27688
+ }
27492
27689
  function scopeSnapshot(s, keep) {
27493
27690
  const pool = s.scopePool;
27494
27691
  if (!pool) return s;
@@ -29363,10 +29560,16 @@ var init_client = __esm({
29363
29560
  async getProjectHistoryCorrections(projectId, since, limit = 200) {
29364
29561
  return this.json("GET", `/v2/projects/${encodeURIComponent(projectId)}/anchors?correctionsOnly=1&correctionSince=${String(since)}&limit=${String(limit)}`);
29365
29562
  }
29366
- async getHistoryOccurrences(projectId, atCommit, after) {
29367
- const query = new URLSearchParams({ atCommit, limit: "50", ...after ? { after } : {} });
29563
+ /** `pendingOnly`: just what a sweep at `atCommit` must post (no settled receipt) or land
29564
+ * (a verdict other than unknown). A cloud that predates the filter returns every occurrence. */
29565
+ async getHistoryOccurrences(projectId, atCommit, after, opts = {}) {
29566
+ const query = new URLSearchParams({ atCommit, limit: "50", ...after ? { after } : {}, ...opts.pendingOnly ? { pending: "1" } : {} });
29368
29567
  return this.json("GET", `/v2/projects/${encodeURIComponent(projectId)}/history/occurrences?${query}`);
29369
29568
  }
29569
+ /** Carry settled verdicts across a commit range; 404 from a cloud that predates the route. */
29570
+ async carryHistory(projectId, carry) {
29571
+ return this.json("POST", `/v2/projects/${encodeURIComponent(projectId)}/history/carry`, carry);
29572
+ }
29370
29573
  async reconcileHistory(projectId, proof) {
29371
29574
  return this.json("POST", `/v2/projects/${encodeURIComponent(projectId)}/history/reconcile`, proof);
29372
29575
  }
@@ -35158,7 +35361,7 @@ function rememberAgentCard(sessionId, agentId, card, now = Date.now()) {
35158
35361
  function subagentRows(body2, now = Date.now()) {
35159
35362
  const sessionId = typeof body2["session_id"] === "string" ? body2["session_id"] : "";
35160
35363
  const tasks = Array.isArray(body2["tasks"]) ? body2["tasks"] : [];
35161
- const columns = typeof body2["columns"] === "number" && body2["columns"] > 20 ? body2["columns"] : 100;
35364
+ const columns2 = typeof body2["columns"] === "number" && body2["columns"] > 20 ? body2["columns"] : 100;
35162
35365
  const lines = [];
35163
35366
  for (const task of tasks) {
35164
35367
  const id = typeof task["id"] === "string" ? task["id"] : "";
@@ -35168,7 +35371,7 @@ function subagentRows(body2, now = Date.now()) {
35168
35371
  const title = String(task["description"] ?? task["label"] ?? "").trim();
35169
35372
  const plain = clip(
35170
35373
  `${title ? `${title} \xB7 ` : ""}\u26A1 errata \xB7 ${hit.card.headline}${lead2 ? ` \u2014 ${labelName(lead2.label)}: ${lead2.text}` : ""}`,
35171
- columns - 2
35374
+ columns2 - 2
35172
35375
  );
35173
35376
  lines.push(JSON.stringify({ id, content: plain.replace("\u26A1", `${AMBER}\u26A1${RESET}`) }));
35174
35377
  }
@@ -38216,8 +38419,8 @@ import { execFileSync as execFileSync3 } from "node:child_process";
38216
38419
  function nowTs() {
38217
38420
  return indexNow ?? Date.now();
38218
38421
  }
38219
- function fingerprintOf(signature, bodyHash) {
38220
- return `${signature ?? ""}|${bodyHash ?? ""}`;
38422
+ function fingerprintOf(signature2, bodyHash) {
38423
+ return `${signature2 ?? ""}|${bodyHash ?? ""}`;
38221
38424
  }
38222
38425
  function sha(s) {
38223
38426
  return createHash7("sha256").update(s).digest("hex").slice(0, 16);
@@ -46733,11 +46936,20 @@ function* walkSource(dir) {
46733
46936
  function listSourceFiles(root) {
46734
46937
  return gitSourceFiles(root) ?? walkSource(root);
46735
46938
  }
46736
- async function findStaleFiles(store, rootPath, workspaceId2) {
46939
+ async function findStaleFiles(store, rootPath, workspaceId2, lineageVerifiedAt) {
46737
46940
  const stale = [];
46941
+ const changed = lineageVerifiedAt !== void 0 && store.fileRowStates ? store.lineageChangedFiles?.(lineageVerifiedAt) : null;
46942
+ const relineage = changed ? new Set(changed) : null;
46738
46943
  let pending = [];
46739
46944
  const check2 = () => {
46740
- const states = new Map(store.fileIndexStates(pending.map((f) => f.id)).map((s) => [s.id, s]));
46945
+ const full = relineage ? pending.filter((f) => relineage.has(f.id)) : pending;
46946
+ const states = new Map(
46947
+ store.fileIndexStates(full.map((f) => f.id)).map((s) => [s.id, s])
46948
+ );
46949
+ if (relineage) {
46950
+ const rowOnly = pending.filter((f) => !relineage.has(f.id)).map((f) => f.id);
46951
+ for (const s of store.fileRowStates(rowOnly)) states.set(s.id, { ...s, complete: true });
46952
+ }
46741
46953
  for (const f of pending) {
46742
46954
  const state = states.get(f.id);
46743
46955
  if (!state || state.validTo !== null || state.lastUpdatedAt < f.mtimeMs || !state.complete) stale.push(f.abs);
@@ -46762,6 +46974,19 @@ async function findStaleFiles(store, rootPath, workspaceId2) {
46762
46974
  function findStrandedSymbols(store) {
46763
46975
  return store.strandedSymbols();
46764
46976
  }
46977
+ function standingStrandedCount(store) {
46978
+ try {
46979
+ const last = JSON.parse(store.getMeta?.(STRANDED_KEY) ?? "null");
46980
+ if (!last) return null;
46981
+ if ((store.changeSeq?.() ?? Infinity) - last.seq > STRANDED_WINDOW_MAX) return null;
46982
+ return store.lineageChangedFiles?.(last.seq)?.length === 0 ? last.count : null;
46983
+ } catch {
46984
+ return null;
46985
+ }
46986
+ }
46987
+ function recordStrandedCount(store, seq, count) {
46988
+ if (seq !== void 0) store.setMeta?.(STRANDED_KEY, JSON.stringify({ seq, count }));
46989
+ }
46765
46990
  function reapOrphanedFiles(store, rootPath, workspaceId2, ignoreDirs = []) {
46766
46991
  const ignores = /* @__PURE__ */ new Set([...DEFAULT_IGNORES, ...ignoreDirs]);
46767
46992
  const listed = gitListRelPaths(rootPath, ignores);
@@ -46800,8 +47025,16 @@ function reapOrphanedFiles(store, rootPath, workspaceId2, ignoreDirs = []) {
46800
47025
  return { reaped: orphans.length, symbolsClosed };
46801
47026
  }
46802
47027
  async function reconcileStaleFiles(store, rootPath, workspaceId2) {
46803
- const stale = await findStaleFiles(store, rootPath, workspaceId2);
46804
- if (stale.length === 0) return 0;
47028
+ const startedAt = store.changeSeq?.();
47029
+ const verified = Number(store.getMeta?.(LINEAGE_VERIFIED_KEY) ?? NaN);
47030
+ const stale = await findStaleFiles(store, rootPath, workspaceId2, Number.isFinite(verified) ? verified : void 0);
47031
+ const verify = () => {
47032
+ if (startedAt !== void 0) store.setMeta?.(LINEAGE_VERIFIED_KEY, String(startedAt));
47033
+ };
47034
+ if (stale.length === 0) {
47035
+ verify();
47036
+ return 0;
47037
+ }
46805
47038
  let total = 0;
46806
47039
  let failedBatches = 0;
46807
47040
  const BATCH = 20;
@@ -46819,10 +47052,12 @@ async function reconcileStaleFiles(store, rootPath, workspaceId2) {
46819
47052
  }
46820
47053
  if (failedBatches > 0) {
46821
47054
  console.warn(`[errata] reconcile: ${failedBatches} batch(es) failed; ${total} file(s) reindexed`);
47055
+ } else {
47056
+ verify();
46822
47057
  }
46823
47058
  return total;
46824
47059
  }
46825
- var IGNORED, SOURCE_RE, SCAN_YIELD_EVERY, ORPHAN_REAP_MAX_FRACTION, ORPHAN_REAP_MIN_ALLOWANCE;
47060
+ var IGNORED, SOURCE_RE, SCAN_YIELD_EVERY, STRANDED_KEY, STRANDED_WINDOW_MAX, ORPHAN_REAP_MAX_FRACTION, ORPHAN_REAP_MIN_ALLOWANCE, LINEAGE_VERIFIED_KEY;
46826
47061
  var init_reconcile = __esm({
46827
47062
  "src/reconcile.ts"() {
46828
47063
  "use strict";
@@ -46830,8 +47065,11 @@ var init_reconcile = __esm({
46830
47065
  IGNORED = /[\\/](?:\.git|node_modules|\.errata|dist|__pycache__)(?:[\\/]|$)/;
46831
47066
  SOURCE_RE = /\.(ts|tsx|js|jsx|mjs|cjs|py)$/i;
46832
47067
  SCAN_YIELD_EVERY = 100;
47068
+ STRANDED_KEY = "pass-inputs:stranded";
47069
+ STRANDED_WINDOW_MAX = 2e4;
46833
47070
  ORPHAN_REAP_MAX_FRACTION = 0.25;
46834
47071
  ORPHAN_REAP_MIN_ALLOWANCE = 50;
47072
+ LINEAGE_VERIFIED_KEY = "pass-inputs:reconcile-lineage";
46835
47073
  }
46836
47074
  });
46837
47075
 
@@ -76471,18 +76709,18 @@ __export(witness_ledger_exports, {
76471
76709
  summarizeWitnessLedger: () => summarizeWitnessLedger,
76472
76710
  witnessLedgerPath: () => witnessLedgerPath
76473
76711
  });
76474
- import { appendFileSync as appendFileSync3, existsSync as existsSync27, readFileSync as readFileSync30, writeFileSync as writeFileSync21 } from "node:fs";
76475
- import { join as join34 } from "node:path";
76712
+ import { appendFileSync as appendFileSync3, existsSync as existsSync27, readFileSync as readFileSync31, writeFileSync as writeFileSync22 } from "node:fs";
76713
+ import { join as join35 } from "node:path";
76476
76714
  function witnessLedgerPath(configDir) {
76477
- return join34(configDir, "witness-ledger.jsonl");
76715
+ return join35(configDir, "witness-ledger.jsonl");
76478
76716
  }
76479
76717
  function appendWitnessLedger(configDir, entry) {
76480
76718
  const path3 = witnessLedgerPath(configDir);
76481
76719
  try {
76482
76720
  appendFileSync3(path3, JSON.stringify(entry) + "\n");
76483
- const lines = readFileSync30(path3, "utf8").split("\n").filter(Boolean);
76721
+ const lines = readFileSync31(path3, "utf8").split("\n").filter(Boolean);
76484
76722
  if (lines.length > LEDGER_MAX_LINES) {
76485
- writeFileSync21(path3, lines.slice(-Math.floor(LEDGER_MAX_LINES / 2)).join("\n") + "\n");
76723
+ writeFileSync22(path3, lines.slice(-Math.floor(LEDGER_MAX_LINES / 2)).join("\n") + "\n");
76486
76724
  }
76487
76725
  } catch {
76488
76726
  }
@@ -76491,7 +76729,7 @@ function readWitnessLedger(configDir) {
76491
76729
  const path3 = witnessLedgerPath(configDir);
76492
76730
  if (!existsSync27(path3)) return [];
76493
76731
  try {
76494
- return readFileSync30(path3, "utf8").split("\n").filter(Boolean).map((l) => JSON.parse(l)).filter((e) => typeof e.ts === "number" && typeof e.channel === "string");
76732
+ return readFileSync31(path3, "utf8").split("\n").filter(Boolean).map((l) => JSON.parse(l)).filter((e) => typeof e.ts === "number" && typeof e.channel === "string");
76495
76733
  } catch {
76496
76734
  return [];
76497
76735
  }
@@ -76930,12 +77168,12 @@ var init_report_render = __esm({
76930
77168
 
76931
77169
  // src/cli.ts
76932
77170
  init_src6();
76933
- import { closeSync as closeSync3, existsSync as existsSync40, openSync as openSync3, readFileSync as readFileSync45, renameSync as renameSync9, statSync as statSync15 } from "node:fs";
76934
- import { join as join53, resolve as pathResolve2 } from "node:path";
77171
+ import { closeSync as closeSync3, existsSync as existsSync40, openSync as openSync3, readFileSync as readFileSync48, renameSync as renameSync10, statSync as statSync16 } from "node:fs";
77172
+ import { join as join56, resolve as pathResolve2 } from "node:path";
76935
77173
  import { spawn as spawn5 } from "node:child_process";
76936
77174
 
76937
77175
  // src/daemon.ts
76938
- import { existsSync as existsSync29, writeFileSync as writeFileSync24 } from "node:fs";
77176
+ import { existsSync as existsSync29, writeFileSync as writeFileSync25 } from "node:fs";
76939
77177
 
76940
77178
  // ../../node_modules/.pnpm/@hono+node-server@1.19.11_hono@4.12.34/node_modules/@hono/node-server/dist/index.mjs
76941
77179
  import { createServer as createServerHTTP } from "http";
@@ -77619,8 +77857,8 @@ function knowledgeTag(label, attrs) {
77619
77857
 
77620
77858
  // src/engine.ts
77621
77859
  import { execFileSync as execFileSync6 } from "node:child_process";
77622
- import { existsSync as existsSync28, statSync as statSync10, appendFileSync as appendFileSync4, readdirSync as readdirSync11, renameSync as renameSync4, readFileSync as readFileSync32, writeFileSync as writeFileSync23 } from "node:fs";
77623
- import { basename as basename8, join as join36, relative as relative7, sep as sep4 } from "node:path";
77860
+ import { existsSync as existsSync28, statSync as statSync11, appendFileSync as appendFileSync4, readdirSync as readdirSync11, renameSync as renameSync5, readFileSync as readFileSync33, writeFileSync as writeFileSync24 } from "node:fs";
77861
+ import { basename as basename8, join as join37, relative as relative6, sep as sep5 } from "node:path";
77624
77862
 
77625
77863
  // src/coalesced-file-pass.ts
77626
77864
  function createCoalescedFilePass(delayMs, run3, onError) {
@@ -77665,7 +77903,7 @@ function createCoalescedFilePass(delayMs, run3, onError) {
77665
77903
  // src/source-watcher.ts
77666
77904
  import { EventEmitter as EventEmitter2 } from "node:events";
77667
77905
  import { readdirSync as readdirSync6, statSync as statSync7, watch as watch2 } from "node:fs";
77668
- import { isAbsolute as isAbsolute5, join as join21, relative as relative6 } from "node:path";
77906
+ import { join as join21, sep as sep4 } from "node:path";
77669
77907
 
77670
77908
  // ../../node_modules/.pnpm/chokidar@4.0.3/node_modules/chokidar/esm/index.js
77671
77909
  import { stat as statcb } from "fs";
@@ -78396,9 +78634,9 @@ var NodeFsHandler = class {
78396
78634
  if (this.fsw.closed) {
78397
78635
  return;
78398
78636
  }
78399
- const dirname19 = sysPath.dirname(file2);
78637
+ const dirname20 = sysPath.dirname(file2);
78400
78638
  const basename10 = sysPath.basename(file2);
78401
- const parent = this.fsw._getWatchedDir(dirname19);
78639
+ const parent = this.fsw._getWatchedDir(dirname20);
78402
78640
  let prevStats = stats;
78403
78641
  if (parent.has(basename10))
78404
78642
  return;
@@ -78425,7 +78663,7 @@ var NodeFsHandler = class {
78425
78663
  prevStats = newStats2;
78426
78664
  }
78427
78665
  } catch (error48) {
78428
- this.fsw._remove(dirname19, basename10);
78666
+ this.fsw._remove(dirname20, basename10);
78429
78667
  }
78430
78668
  } else if (parent.has(basename10)) {
78431
78669
  const at = newStats.atimeMs;
@@ -78674,11 +78912,11 @@ function createPattern(matcher) {
78674
78912
  if (matcher.path === string4)
78675
78913
  return true;
78676
78914
  if (matcher.recursive) {
78677
- const relative9 = sysPath2.relative(matcher.path, string4);
78678
- if (!relative9) {
78915
+ const relative8 = sysPath2.relative(matcher.path, string4);
78916
+ if (!relative8) {
78679
78917
  return false;
78680
78918
  }
78681
- return !relative9.startsWith("..") && !sysPath2.isAbsolute(relative9);
78919
+ return !relative8.startsWith("..") && !sysPath2.isAbsolute(relative8);
78682
78920
  }
78683
78921
  return false;
78684
78922
  };
@@ -79387,7 +79625,9 @@ var NativeSourceWatcher = class extends EventEmitter2 {
79387
79625
  handles = /* @__PURE__ */ new Map();
79388
79626
  pending = /* @__PURE__ */ new Map();
79389
79627
  rescans = /* @__PURE__ */ new Map();
79390
- known = /* @__PURE__ */ new Set();
79628
+ /** Each known file's content signature (mtime and size). A raw event whose
79629
+ * file still has the same signature changed nothing in it. */
79630
+ known = /* @__PURE__ */ new Map();
79391
79631
  closed = false;
79392
79632
  add(target) {
79393
79633
  if (this.closed || this.handles.has(target)) return;
@@ -79441,21 +79681,35 @@ var NativeSourceWatcher = class extends EventEmitter2 {
79441
79681
  this.pending.set(path3, { timer, renamed: renamed || (prev?.renamed ?? false) });
79442
79682
  }
79443
79683
  seedKnown(target, isDir) {
79444
- for (const path3 of this.filesUnder(target, isDir)) this.known.add(path3);
79684
+ for (const [path3, sig] of this.filesUnder(target, isDir)) this.known.set(path3, sig);
79445
79685
  }
79446
79686
  filesUnder(target, isDir) {
79447
- const files = /* @__PURE__ */ new Set();
79687
+ const files = /* @__PURE__ */ new Map();
79688
+ const add = (path3) => {
79689
+ try {
79690
+ files.set(path3, signature(statSync7(path3)));
79691
+ } catch {
79692
+ }
79693
+ };
79448
79694
  if (!isDir) {
79449
- if (!this.ignored(target)) files.add(target);
79695
+ if (!this.ignored(target)) add(target);
79450
79696
  return files;
79451
79697
  }
79452
- try {
79453
- for (const entry of readdirSync6(target, { recursive: true, withFileTypes: true })) {
79454
- if (!entry.isFile()) continue;
79455
- const path3 = join21(entry.parentPath, entry.name);
79456
- if (!this.ignored(path3)) files.add(path3);
79698
+ const dirs = [target];
79699
+ while (dirs.length > 0) {
79700
+ const dir = dirs.pop();
79701
+ let entries;
79702
+ try {
79703
+ entries = readdirSync6(dir, { withFileTypes: true });
79704
+ } catch {
79705
+ continue;
79706
+ }
79707
+ for (const entry of entries) {
79708
+ const path3 = join21(dir, entry.name);
79709
+ if (this.ignored(path3)) continue;
79710
+ if (entry.isDirectory()) dirs.push(path3);
79711
+ else if (entry.isFile()) add(path3);
79457
79712
  }
79458
- } catch {
79459
79713
  }
79460
79714
  return files;
79461
79715
  }
@@ -79466,19 +79720,17 @@ var NativeSourceWatcher = class extends EventEmitter2 {
79466
79720
  this.rescans.delete(target);
79467
79721
  if (this.closed || !this.handles.has(target)) return;
79468
79722
  const current = this.filesUnder(target, isDir);
79469
- const belongsToTarget = (path3) => {
79470
- const rel = relative6(target, path3);
79471
- return rel === "" || !rel.startsWith("..") && !isAbsolute5(rel);
79472
- };
79473
- for (const path3 of [...this.known]) {
79723
+ const prefix = target.endsWith(sep4) ? target : target + sep4;
79724
+ const belongsToTarget = (path3) => path3 === target || path3.startsWith(prefix);
79725
+ for (const path3 of [...this.known.keys()]) {
79474
79726
  if (belongsToTarget(path3) && !current.has(path3)) {
79475
79727
  this.known.delete(path3);
79476
79728
  this.emit("unlink", path3);
79477
79729
  }
79478
79730
  }
79479
- for (const path3 of current) {
79731
+ for (const [path3, sig] of current) {
79480
79732
  if (!this.known.has(path3)) {
79481
- this.known.add(path3);
79733
+ this.known.set(path3, sig);
79482
79734
  this.emit("add", path3);
79483
79735
  }
79484
79736
  }
@@ -79488,21 +79740,27 @@ var NativeSourceWatcher = class extends EventEmitter2 {
79488
79740
  classify(path3, renamed) {
79489
79741
  if (this.closed) return;
79490
79742
  let isFile;
79743
+ let sig;
79491
79744
  try {
79492
79745
  const s = statSync7(path3);
79493
79746
  if (s.isDirectory()) return;
79494
79747
  isFile = s.isFile();
79748
+ sig = signature(s);
79495
79749
  } catch {
79496
79750
  this.known.delete(path3);
79497
79751
  this.emit("unlink", path3);
79498
79752
  return;
79499
79753
  }
79500
79754
  if (!isFile) return;
79501
- const first = !this.known.has(path3);
79502
- this.known.add(path3);
79503
- this.emit(renamed && first ? "add" : "change", path3);
79755
+ const prev = this.known.get(path3);
79756
+ if (prev === sig) return;
79757
+ this.known.set(path3, sig);
79758
+ this.emit(renamed && prev === void 0 ? "add" : "change", path3);
79504
79759
  }
79505
79760
  };
79761
+ function signature(s) {
79762
+ return `${Math.trunc(s.mtimeMs)}:${s.size}:${Math.trunc(s.ctimeMs)}`;
79763
+ }
79506
79764
 
79507
79765
  // src/engine.ts
79508
79766
  init_generalize_graph();
@@ -79756,6 +80014,47 @@ async function chat(req) {
79756
80014
  init_src11();
79757
80015
  init_src6();
79758
80016
  init_session_registry();
80017
+
80018
+ // src/snapshot-reuse.ts
80019
+ import { readFileSync as readFileSync18, renameSync as renameSync3, statSync as statSync8, writeFileSync as writeFileSync14 } from "node:fs";
80020
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
80021
+ import { dirname as dirname11, join as join22 } from "node:path";
80022
+ function snapshotReusable(held, want) {
80023
+ return held !== null && held.key === want.key && held.atCommit === want.atCommit && held.workingFile === want.workingFile;
80024
+ }
80025
+ var codeIdentityMemo;
80026
+ function snapshotCodeIdentity(version3) {
80027
+ if (codeIdentityMemo === void 0) {
80028
+ let built = "unknown";
80029
+ try {
80030
+ built = String(statSync8(fileURLToPath2(import.meta.url)).mtimeMs);
80031
+ } catch {
80032
+ }
80033
+ codeIdentityMemo = `${version3}@${built}`;
80034
+ }
80035
+ return codeIdentityMemo;
80036
+ }
80037
+ function heldSnapshotPath(configDir) {
80038
+ return join22(configDir, "snapshot-held.json");
80039
+ }
80040
+ function loadHeldSnapshot(path3) {
80041
+ try {
80042
+ const held = JSON.parse(readFileSync18(path3, "utf8"));
80043
+ return typeof held?.key === "string" && typeof held.at === "number" ? held : null;
80044
+ } catch {
80045
+ return null;
80046
+ }
80047
+ }
80048
+ function saveHeldSnapshot(path3, held) {
80049
+ try {
80050
+ const tmp = join22(dirname11(path3), `.${process.pid}.snapshot-held.tmp`);
80051
+ writeFileSync14(tmp, JSON.stringify(held));
80052
+ renameSync3(tmp, path3);
80053
+ } catch {
80054
+ }
80055
+ }
80056
+
80057
+ // src/engine.ts
79759
80058
  init_recall_signal();
79760
80059
 
79761
80060
  // src/subagent-state.ts
@@ -79944,8 +80243,8 @@ init_review2();
79944
80243
 
79945
80244
  // src/turn.ts
79946
80245
  init_checkout_root();
79947
- import { closeSync as closeSync2, existsSync as existsSync19, fstatSync, openSync as openSync2, readdirSync as readdirSync7, readSync as readSync2, realpathSync as realpathSync2, statSync as statSync8 } from "node:fs";
79948
- import { basename as basename6, delimiter, dirname as dirname11, join as join22, normalize as normalize3 } from "node:path";
80246
+ import { closeSync as closeSync2, existsSync as existsSync19, fstatSync, openSync as openSync2, readdirSync as readdirSync7, readSync as readSync2, realpathSync as realpathSync2, statSync as statSync9 } from "node:fs";
80247
+ import { basename as basename6, delimiter, dirname as dirname12, join as join23, normalize as normalize3 } from "node:path";
79949
80248
  import { homedir as homedir4 } from "node:os";
79950
80249
  import { createHash as createHash16 } from "node:crypto";
79951
80250
  function completeJsonlPrefix(buf) {
@@ -80333,7 +80632,7 @@ function turnsSince(turns, mark) {
80333
80632
  return at >= 0 ? turns.slice(at + 1) : turns;
80334
80633
  }
80335
80634
  function claudeProjectDir(cwd, home = homedir4()) {
80336
- return join22(home, ".claude", "projects", cwd.replace(/[\\/:.]/g, "-"));
80635
+ return join23(home, ".claude", "projects", cwd.replace(/[\\/:.]/g, "-"));
80337
80636
  }
80338
80637
  function recentTranscripts(cwd, opts = {}) {
80339
80638
  const dir = claudeProjectDir(cwd, opts.home ?? homedir4());
@@ -80348,10 +80647,10 @@ function recentTranscripts(cwd, opts = {}) {
80348
80647
  const refs = [];
80349
80648
  for (const name2 of names) {
80350
80649
  if (!name2.endsWith(".jsonl")) continue;
80351
- const path3 = join22(dir, name2);
80650
+ const path3 = join23(dir, name2);
80352
80651
  let mtimeMs;
80353
80652
  try {
80354
- mtimeMs = statSync8(path3).mtimeMs;
80653
+ mtimeMs = statSync9(path3).mtimeMs;
80355
80654
  } catch {
80356
80655
  continue;
80357
80656
  }
@@ -80363,7 +80662,7 @@ function recentTranscripts(cwd, opts = {}) {
80363
80662
  }
80364
80663
  function subagentTranscripts(mainTranscriptPath, sessionId) {
80365
80664
  if (!mainTranscriptPath || !sessionId) return [];
80366
- const dir = join22(dirname11(mainTranscriptPath), sessionId, "subagents");
80665
+ const dir = join23(dirname12(mainTranscriptPath), sessionId, "subagents");
80367
80666
  if (!existsSync19(dir)) return [];
80368
80667
  let names;
80369
80668
  try {
@@ -80374,10 +80673,10 @@ function subagentTranscripts(mainTranscriptPath, sessionId) {
80374
80673
  const refs = [];
80375
80674
  for (const name2 of names) {
80376
80675
  if (!name2.endsWith(".jsonl")) continue;
80377
- const path3 = join22(dir, name2);
80676
+ const path3 = join23(dir, name2);
80378
80677
  let mtimeMs;
80379
80678
  try {
80380
- mtimeMs = statSync8(path3).mtimeMs;
80679
+ mtimeMs = statSync9(path3).mtimeMs;
80381
80680
  } catch {
80382
80681
  continue;
80383
80682
  }
@@ -80386,15 +80685,15 @@ function subagentTranscripts(mainTranscriptPath, sessionId) {
80386
80685
  refs.sort((a, b) => b.mtimeMs - a.mtimeMs);
80387
80686
  return refs;
80388
80687
  }
80389
- function splitPathList(value, sep6 = delimiter) {
80688
+ function splitPathList(value, sep7 = delimiter) {
80390
80689
  if (!value) return [];
80391
- return value.split(sep6).map((d) => d.trim()).filter(Boolean).map((d) => normalize3(d));
80690
+ return value.split(sep7).map((d) => d.trim()).filter(Boolean).map((d) => normalize3(d));
80392
80691
  }
80393
80692
  function codexSessionRoots(env2 = process.env, home = homedir4()) {
80394
80693
  const roots = /* @__PURE__ */ new Set();
80395
80694
  for (const d of splitPathList(env2["ERRATA_CODEX_SESSIONS_DIRS"])) roots.add(d);
80396
- if (env2["CODEX_HOME"]) roots.add(join22(env2["CODEX_HOME"], "sessions"));
80397
- roots.add(join22(home, ".codex", "sessions"));
80695
+ if (env2["CODEX_HOME"]) roots.add(join23(env2["CODEX_HOME"], "sessions"));
80696
+ roots.add(join23(home, ".codex", "sessions"));
80398
80697
  return [...roots];
80399
80698
  }
80400
80699
  function readCodexRolloutIdentity(path3) {
@@ -80466,10 +80765,10 @@ function codexRolloutsForCwd(cwd, opts = {}) {
80466
80765
  continue;
80467
80766
  }
80468
80767
  for (const name2 of names) {
80469
- const full = join22(dir, name2);
80768
+ const full = join23(dir, name2);
80470
80769
  let st;
80471
80770
  try {
80472
- st = statSync8(full);
80771
+ st = statSync9(full);
80473
80772
  } catch {
80474
80773
  continue;
80475
80774
  }
@@ -80508,8 +80807,8 @@ function codexRolloutsForCwd(cwd, opts = {}) {
80508
80807
  function geminiSessionRoots(env2 = process.env, home = homedir4()) {
80509
80808
  const roots = /* @__PURE__ */ new Set();
80510
80809
  for (const d of splitPathList(env2["ERRATA_GEMINI_SESSIONS_DIRS"])) roots.add(d);
80511
- if (env2["GEMINI_CLI_HOME"]) roots.add(join22(env2["GEMINI_CLI_HOME"], ".gemini", "tmp"));
80512
- roots.add(join22(home, ".gemini", "tmp"));
80810
+ if (env2["GEMINI_CLI_HOME"]) roots.add(join23(env2["GEMINI_CLI_HOME"], ".gemini", "tmp"));
80811
+ roots.add(join23(home, ".gemini", "tmp"));
80513
80812
  return [...roots];
80514
80813
  }
80515
80814
  function geminiProjectHash(cwd) {
@@ -80557,7 +80856,7 @@ function geminiTranscriptsForCwd(cwd, opts = {}) {
80557
80856
  continue;
80558
80857
  }
80559
80858
  for (const slug2 of slugs) {
80560
- const chats = join22(root, slug2, "chats");
80859
+ const chats = join23(root, slug2, "chats");
80561
80860
  let names;
80562
80861
  try {
80563
80862
  names = readdirSync7(chats);
@@ -80566,10 +80865,10 @@ function geminiTranscriptsForCwd(cwd, opts = {}) {
80566
80865
  }
80567
80866
  for (const name2 of names) {
80568
80867
  if (!name2.startsWith("session-") || !name2.endsWith(".jsonl")) continue;
80569
- const full = join22(chats, name2);
80868
+ const full = join23(chats, name2);
80570
80869
  let st;
80571
80870
  try {
80572
- st = statSync8(full);
80871
+ st = statSync9(full);
80573
80872
  } catch {
80574
80873
  continue;
80575
80874
  }
@@ -80586,8 +80885,8 @@ function geminiTranscriptsForCwd(cwd, opts = {}) {
80586
80885
  function opencodeSessionRoots(env2 = process.env, home = homedir4()) {
80587
80886
  const roots = /* @__PURE__ */ new Set();
80588
80887
  for (const d of splitPathList(env2["ERRATA_OPENCODE_SESSIONS_DIRS"])) roots.add(d);
80589
- if (env2["XDG_DATA_HOME"]) roots.add(join22(env2["XDG_DATA_HOME"], "opencode", "errata"));
80590
- roots.add(join22(home, ".local", "share", "opencode", "errata"));
80888
+ if (env2["XDG_DATA_HOME"]) roots.add(join23(env2["XDG_DATA_HOME"], "opencode", "errata"));
80889
+ roots.add(join23(home, ".local", "share", "opencode", "errata"));
80591
80890
  return [...roots];
80592
80891
  }
80593
80892
  function readOpencodeTranscriptDirectory(path3) {
@@ -80629,10 +80928,10 @@ function opencodeTranscriptsForCwd(cwd, opts = {}) {
80629
80928
  }
80630
80929
  for (const name2 of names) {
80631
80930
  if (!name2.endsWith(".jsonl")) continue;
80632
- const full = join22(root, name2);
80931
+ const full = join23(root, name2);
80633
80932
  let st;
80634
80933
  try {
80635
- st = statSync8(full);
80934
+ st = statSync9(full);
80636
80935
  } catch {
80637
80936
  continue;
80638
80937
  }
@@ -80652,7 +80951,7 @@ init_src2();
80652
80951
  init_agent_signals();
80653
80952
  init_tool_index();
80654
80953
  init_src5();
80655
- import { readFileSync as readFileSync18, writeFileSync as writeFileSync14 } from "node:fs";
80954
+ import { readFileSync as readFileSync19, writeFileSync as writeFileSync15 } from "node:fs";
80656
80955
  var NEG = /n['']t|\b(?:not|never|no|none|neither|nor|unrelated|irrelevant|would|might|could|if)\b/i;
80657
80956
  var CITE_GROUP_RE = /\(((?:[^()\n]|\([^()\n]*\)){1,200})\)/g;
80658
80957
  var HANDLE_RE2 = new RegExp(TAG_HANDLE_SOURCE, "gi");
@@ -81452,13 +81751,13 @@ function writePrimingHandles(path3, nodes, now = Date.now()) {
81452
81751
  entries.sort((a, b) => (b[1].seenAt ?? 0) - (a[1].seenAt ?? 0));
81453
81752
  entries.length = HANDLE_MAP_MAX;
81454
81753
  }
81455
- writeFileSync14(path3, JSON.stringify(Object.fromEntries(entries)));
81754
+ writeFileSync15(path3, JSON.stringify(Object.fromEntries(entries)));
81456
81755
  } catch {
81457
81756
  }
81458
81757
  }
81459
81758
  function readPrimingHandles(path3) {
81460
81759
  try {
81461
- return JSON.parse(readFileSync18(path3, "utf8"));
81760
+ return JSON.parse(readFileSync19(path3, "utf8"));
81462
81761
  } catch {
81463
81762
  return {};
81464
81763
  }
@@ -81947,8 +82246,8 @@ ${conversation}` }]
81947
82246
  // src/constraint-backfill.ts
81948
82247
  init_src5();
81949
82248
  init_src2();
81950
- import { existsSync as existsSync20, readFileSync as readFileSync19, readdirSync as readdirSync8, writeFileSync as writeFileSync15 } from "node:fs";
81951
- import { join as join23 } from "node:path";
82249
+ import { existsSync as existsSync20, readFileSync as readFileSync20, readdirSync as readdirSync8, writeFileSync as writeFileSync16 } from "node:fs";
82250
+ import { join as join24 } from "node:path";
81952
82251
  import { homedir as homedir5 } from "node:os";
81953
82252
  var BACKFILL_VERSION = 1;
81954
82253
  var EMPTY = {
@@ -81962,13 +82261,13 @@ var EMPTY = {
81962
82261
  recoverable: 0
81963
82262
  };
81964
82263
  function markerPath(configDir) {
81965
- return join23(configDir, "constraint-backfill.json");
82264
+ return join24(configDir, "constraint-backfill.json");
81966
82265
  }
81967
82266
  function alreadyDone(configDir) {
81968
82267
  const p = markerPath(configDir);
81969
82268
  if (!existsSync20(p)) return false;
81970
82269
  try {
81971
- const raw2 = JSON.parse(readFileSync19(p, "utf8"));
82270
+ const raw2 = JSON.parse(readFileSync20(p, "utf8"));
81972
82271
  return raw2?.version === BACKFILL_VERSION;
81973
82272
  } catch {
81974
82273
  return false;
@@ -81988,7 +82287,7 @@ function replay(root) {
81988
82287
  for (const f of names) {
81989
82288
  let lines;
81990
82289
  try {
81991
- lines = readFileSync19(join23(dir, f), "utf8").split("\n");
82290
+ lines = readFileSync20(join24(dir, f), "utf8").split("\n");
81992
82291
  } catch {
81993
82292
  continue;
81994
82293
  }
@@ -82102,7 +82401,7 @@ function backfillConstraintKind(store, opts) {
82102
82401
  }
82103
82402
  });
82104
82403
  try {
82105
- writeFileSync15(
82404
+ writeFileSync16(
82106
82405
  markerPath(opts.configDir),
82107
82406
  JSON.stringify({ version: BACKFILL_VERSION, at: opts.now, ...report, cloudTwins: report.cloudTwins.length }, null, 2),
82108
82407
  "utf8"
@@ -82115,8 +82414,8 @@ function backfillConstraintKind(store, opts) {
82115
82414
  // src/edge-repair.ts
82116
82415
  init_src();
82117
82416
  init_src5();
82118
- import { existsSync as existsSync21, readFileSync as readFileSync20, writeFileSync as writeFileSync16 } from "node:fs";
82119
- import { join as join24 } from "node:path";
82417
+ import { existsSync as existsSync21, readFileSync as readFileSync21, writeFileSync as writeFileSync17 } from "node:fs";
82418
+ import { join as join25 } from "node:path";
82120
82419
  function citeEdgeId(from, type, to) {
82121
82420
  return `edge_${digest({ from, type, to })}`.slice(0, 24);
82122
82421
  }
@@ -82131,13 +82430,13 @@ var EMPTY2 = {
82131
82430
  byType: {}
82132
82431
  };
82133
82432
  function markerPath2(configDir) {
82134
- return join24(configDir, "edge-repair.json");
82433
+ return join25(configDir, "edge-repair.json");
82135
82434
  }
82136
82435
  function alreadyDone2(configDir) {
82137
82436
  const p = markerPath2(configDir);
82138
82437
  if (!existsSync21(p)) return false;
82139
82438
  try {
82140
- return JSON.parse(readFileSync20(p, "utf8"))?.version === EDGE_REPAIR_VERSION;
82439
+ return JSON.parse(readFileSync21(p, "utf8"))?.version === EDGE_REPAIR_VERSION;
82141
82440
  } catch {
82142
82441
  return false;
82143
82442
  }
@@ -82186,7 +82485,7 @@ function repairInvalidEdges(store, opts) {
82186
82485
  });
82187
82486
  store.pruneEdgeRejections(opts.now - REJECTION_RETENTION_MS);
82188
82487
  try {
82189
- writeFileSync16(
82488
+ writeFileSync17(
82190
82489
  markerPath2(opts.configDir),
82191
82490
  JSON.stringify({ version: EDGE_REPAIR_VERSION, at: opts.now, ...report }, null, 2),
82192
82491
  "utf8"
@@ -82200,8 +82499,8 @@ function repairInvalidEdges(store, opts) {
82200
82499
  init_reconcile();
82201
82500
 
82202
82501
  // src/pass-ledger.ts
82203
- import { appendFileSync as appendFileSync2, existsSync as existsSync22, readFileSync as readFileSync21, writeFileSync as writeFileSync17 } from "node:fs";
82204
- import { join as join25 } from "node:path";
82502
+ import { appendFileSync as appendFileSync2, existsSync as existsSync22, readFileSync as readFileSync22, writeFileSync as writeFileSync18 } from "node:fs";
82503
+ import { join as join26 } from "node:path";
82205
82504
 
82206
82505
  // src/isolate-census.ts
82207
82506
  var live2 = 0;
@@ -82219,6 +82518,11 @@ function isolateCensus() {
82219
82518
  return { live: live2, spawnedTotal, peak };
82220
82519
  }
82221
82520
 
82521
+ // src/io-reads.ts
82522
+ function ioReadOps() {
82523
+ return process.resourceUsage().fsRead;
82524
+ }
82525
+
82222
82526
  // src/pass-ledger.ts
82223
82527
  var PER_KIND_MAX = 100;
82224
82528
  var LEVEL_TAIL_KINDS = /* @__PURE__ */ new Set(["wm-calibration"]);
@@ -82227,7 +82531,7 @@ var HOUR_MS = 36e5;
82227
82531
  var TRIM_EVERY = 50;
82228
82532
  var appendsSinceTrim = /* @__PURE__ */ new Map();
82229
82533
  function passLedgerPath(configDir) {
82230
- return join25(configDir, "pass-ledger.jsonl");
82534
+ return join26(configDir, "pass-ledger.jsonl");
82231
82535
  }
82232
82536
  function appendPassLedger(configDir, kind, durationMs, counts) {
82233
82537
  const path3 = passLedgerPath(configDir);
@@ -82246,7 +82550,10 @@ function appendPassLedger(configDir, kind, durationMs, counts) {
82246
82550
  arrayBuffersMB: Math.round(mem.arrayBuffers / 1048576),
82247
82551
  isolatesLive: census2.live,
82248
82552
  isolatesSpawned: census2.spawnedTotal,
82249
- isolatesPeak: census2.peak
82553
+ isolatesPeak: census2.peak,
82554
+ // Cumulative process-wide file reads (io-reads.ts): the difference
82555
+ // between two rows is what ran between them.
82556
+ ioReadOps: ioReadOps()
82250
82557
  }
82251
82558
  };
82252
82559
  appendFileSync2(path3, JSON.stringify(entry) + "\n");
@@ -82256,7 +82563,7 @@ function appendPassLedger(configDir, kind, durationMs, counts) {
82256
82563
  return;
82257
82564
  }
82258
82565
  appendsSinceTrim.set(path3, 0);
82259
- const lines = readFileSync21(path3, "utf8").split("\n").filter(Boolean);
82566
+ const lines = readFileSync22(path3, "utf8").split("\n").filter(Boolean);
82260
82567
  const keptByKind = /* @__PURE__ */ new Map();
82261
82568
  const tailHours = /* @__PURE__ */ new Map();
82262
82569
  const tailFloor = Date.now() - LEVEL_TAIL_DAYS * 24 * HOUR_MS;
@@ -82284,7 +82591,7 @@ function appendPassLedger(configDir, kind, durationMs, counts) {
82284
82591
  kept.push(lines[i2]);
82285
82592
  }
82286
82593
  if (kept.length < lines.length) {
82287
- writeFileSync17(path3, kept.reverse().join("\n") + "\n");
82594
+ writeFileSync18(path3, kept.reverse().join("\n") + "\n");
82288
82595
  }
82289
82596
  } catch {
82290
82597
  }
@@ -82293,7 +82600,7 @@ function readPassLedger(configDir) {
82293
82600
  const path3 = passLedgerPath(configDir);
82294
82601
  if (!existsSync22(path3)) return [];
82295
82602
  try {
82296
- return readFileSync21(path3, "utf8").split("\n").filter(Boolean).map((l) => JSON.parse(l)).filter(
82603
+ return readFileSync22(path3, "utf8").split("\n").filter(Boolean).map((l) => JSON.parse(l)).filter(
82297
82604
  (e) => typeof e?.ts === "number" && typeof e?.kind === "string" && typeof e?.durationMs === "number"
82298
82605
  ).map((e) => ({ ...e, counts: e.counts ?? {} }));
82299
82606
  } catch {
@@ -82540,6 +82847,7 @@ function withHeavyPassSlot(label, fn) {
82540
82847
  const waited = Date.now() - queuedAt;
82541
82848
  waiting.delete(id);
82542
82849
  const startedAt = Date.now();
82850
+ const readsAtStart = ioReadOps();
82543
82851
  active = { label, startedAt, waitedMs: waited };
82544
82852
  if (waited > QUEUE_WARN_MS) {
82545
82853
  console.warn(`[errata] heavy-pass slot: ${label} waited ${Math.round(waited / 1e3)}s`);
@@ -82551,7 +82859,7 @@ function withHeavyPassSlot(label, fn) {
82551
82859
  failed = true;
82552
82860
  throw err2;
82553
82861
  } finally {
82554
- recent2.push({ label, waitedMs: waited, durationMs: Date.now() - startedAt, failed });
82862
+ recent2.push({ label, waitedMs: waited, durationMs: Date.now() - startedAt, readOps: ioReadOps() - readsAtStart, failed });
82555
82863
  if (recent2.length > 16) recent2.shift();
82556
82864
  active = null;
82557
82865
  }
@@ -82704,11 +83012,11 @@ init_outbox();
82704
83012
  init_src10();
82705
83013
  init_src();
82706
83014
  init_src2();
82707
- import { readFileSync as readFileSync22 } from "node:fs";
82708
- import { join as join26 } from "node:path";
83015
+ import { readFileSync as readFileSync23 } from "node:fs";
83016
+ import { join as join27 } from "node:path";
82709
83017
  function loadClaimIgnorePatterns(workspaceRoot) {
82710
83018
  try {
82711
- return readFileSync22(join26(workspaceRoot, ".errataignore"), "utf8").split(/\r?\n/).map((l) => l.trim()).filter((l) => l.length > 0 && !l.startsWith("#")).map((l) => l.toLowerCase());
83019
+ return readFileSync23(join27(workspaceRoot, ".errataignore"), "utf8").split(/\r?\n/).map((l) => l.trim()).filter((l) => l.length > 0 && !l.startsWith("#")).map((l) => l.toLowerCase());
82712
83020
  } catch {
82713
83021
  return [];
82714
83022
  }
@@ -83091,9 +83399,9 @@ async function pullCloudTriage(shared, cloud, profile, limit = 50) {
83091
83399
  // src/retrieval-stack.ts
83092
83400
  init_src();
83093
83401
  import { execFileSync as execFileSync5 } from "node:child_process";
83094
- import { existsSync as existsSync23, readFileSync as readFileSync23, statSync as statSync9 } from "node:fs";
83402
+ import { existsSync as existsSync23, readFileSync as readFileSync24, statSync as statSync10 } from "node:fs";
83095
83403
  import { homedir as homedir6 } from "node:os";
83096
- import { join as join27 } from "node:path";
83404
+ import { join as join28 } from "node:path";
83097
83405
  var RETRIEVAL_STACK_CAP = 24;
83098
83406
  var MANIFEST_SCAN_CAP = 400;
83099
83407
  var RUNTIME_TOKENS = /* @__PURE__ */ new Set([
@@ -83383,51 +83691,51 @@ function mavenGroupIsSelfDisclosing(name2, selfTokens) {
83383
83691
  function loadRegistryPolicy(root, env2 = process.env, repoLocator) {
83384
83692
  const read2 = (p) => {
83385
83693
  try {
83386
- return readFileSync23(p, "utf8");
83694
+ return readFileSync24(p, "utf8");
83387
83695
  } catch {
83388
83696
  return null;
83389
83697
  }
83390
83698
  };
83391
83699
  const texts = (...paths) => paths.map(read2).filter((t) => t !== null);
83392
83700
  const home = homedir6();
83393
- const npm = parseNpmrcPolicy(texts(join27(root, ".npmrc"), join27(home, ".npmrc")));
83701
+ const npm = parseNpmrcPolicy(texts(join28(root, ".npmrc"), join28(home, ".npmrc")));
83394
83702
  const blocked = /* @__PURE__ */ new Set();
83395
83703
  if (!npm.defaultPublic) blocked.add("npm");
83396
83704
  if (pypiIndexIsPrivate(
83397
83705
  texts(
83398
- join27(root, "pip.conf"),
83399
- join27(root, "pip.ini"),
83400
- join27(root, "pyproject.toml"),
83401
- join27(root, "requirements.txt"),
83402
- join27(home, ".pip", "pip.conf"),
83403
- join27(home, ".config", "pip", "pip.conf"),
83404
- join27(env2["APPDATA"] ?? home, "pip", "pip.ini")
83706
+ join28(root, "pip.conf"),
83707
+ join28(root, "pip.ini"),
83708
+ join28(root, "pyproject.toml"),
83709
+ join28(root, "requirements.txt"),
83710
+ join28(home, ".pip", "pip.conf"),
83711
+ join28(home, ".config", "pip", "pip.conf"),
83712
+ join28(env2["APPDATA"] ?? home, "pip", "pip.ini")
83405
83713
  )
83406
83714
  )) {
83407
83715
  blocked.add("pypi");
83408
83716
  }
83409
83717
  if (cargoRegistryIsPrivate(
83410
83718
  texts(
83411
- join27(root, ".cargo", "config.toml"),
83412
- join27(root, ".cargo", "config"),
83413
- join27(home, ".cargo", "config.toml"),
83414
- join27(home, ".cargo", "config")
83719
+ join28(root, ".cargo", "config.toml"),
83720
+ join28(root, ".cargo", "config"),
83721
+ join28(home, ".cargo", "config.toml"),
83722
+ join28(home, ".cargo", "config")
83415
83723
  )
83416
83724
  )) {
83417
83725
  blocked.add("cargo");
83418
83726
  }
83419
83727
  if (nugetSourcesArePrivate(
83420
83728
  texts(
83421
- join27(root, "NuGet.config"),
83422
- join27(root, "nuget.config"),
83423
- join27(root, "NuGet.Config"),
83424
- join27(env2["APPDATA"] ?? home, "NuGet", "NuGet.Config"),
83425
- join27(home, ".nuget", "NuGet", "NuGet.Config")
83729
+ join28(root, "NuGet.config"),
83730
+ join28(root, "nuget.config"),
83731
+ join28(root, "NuGet.Config"),
83732
+ join28(env2["APPDATA"] ?? home, "NuGet", "NuGet.Config"),
83733
+ join28(home, ".nuget", "NuGet", "NuGet.Config")
83426
83734
  )
83427
83735
  )) {
83428
83736
  blocked.add("nuget");
83429
83737
  }
83430
- const goEnvFile = env2["GOENV"] ?? join27(env2["APPDATA"] ?? join27(home, ".config"), "go", "env");
83738
+ const goEnvFile = env2["GOENV"] ?? join28(env2["APPDATA"] ?? join28(home, ".config"), "go", "env");
83431
83739
  const goEnvText = read2(goEnvFile) ?? "";
83432
83740
  const fromFile = ["GOPRIVATE", "GONOSUMDB", "GONOSUMCHECK"].map(
83433
83741
  (k) => new RegExp(`^${k}=(.*)$`, "m").exec(goEnvText)?.[1]
@@ -83438,10 +83746,10 @@ function loadRegistryPolicy(root, env2 = process.env, repoLocator) {
83438
83746
  env2["GONOSUMCHECK"],
83439
83747
  ...fromFile
83440
83748
  ]);
83441
- const gemfiles = texts(join27(root, "Gemfile"));
83749
+ const gemfiles = texts(join28(root, "Gemfile"));
83442
83750
  if (gemSourceIsPrivate(gemfiles)) blocked.add("gem");
83443
83751
  if (mavenReposArePrivate(
83444
- texts(join27(root, "pom.xml"), join27(home, ".m2", "settings.xml"))
83752
+ texts(join28(root, "pom.xml"), join28(home, ".m2", "settings.xml"))
83445
83753
  )) {
83446
83754
  blocked.add("maven");
83447
83755
  }
@@ -83608,10 +83916,10 @@ function readDirectDependencies(root) {
83608
83916
  const familiesSeen = /* @__PURE__ */ new Set();
83609
83917
  for (const c of LOCKFILES) {
83610
83918
  if (familiesSeen.has(c.family)) continue;
83611
- const p = join27(root, c.file);
83919
+ const p = join28(root, c.file);
83612
83920
  if (!existsSync23(p)) continue;
83613
83921
  try {
83614
- const s = statSync9(p);
83922
+ const s = statSync10(p);
83615
83923
  stamps.push(`${c.file}:${s.mtimeMs}:${s.size}`);
83616
83924
  } catch {
83617
83925
  continue;
@@ -83629,7 +83937,7 @@ function readDirectDependencies(root) {
83629
83937
  const direct = [];
83630
83938
  for (const { c, path: path3 } of found) {
83631
83939
  try {
83632
- direct.push(...c.parse(readFileSync23(path3, "utf8")).direct ?? []);
83940
+ direct.push(...c.parse(readFileSync24(path3, "utf8")).direct ?? []);
83633
83941
  } catch {
83634
83942
  }
83635
83943
  }
@@ -83672,14 +83980,14 @@ function manifestPaths(root) {
83672
83980
  "project.godot"
83673
83981
  ];
83674
83982
  return {
83675
- paths: ROOT_MANIFESTS.filter((f) => existsSync23(join27(root, f))),
83983
+ paths: ROOT_MANIFESTS.filter((f) => existsSync23(join28(root, f))),
83676
83984
  tracked: false,
83677
83985
  truncated: false
83678
83986
  };
83679
83987
  }
83680
83988
  var WORKSPACE_MARKERS = ["pnpm-workspace.yaml", "lerna.json", "go.work", "settings.gradle", "settings.gradle.kts"];
83681
83989
  function rootDeclaresWorkspace(root, texts) {
83682
- if (WORKSPACE_MARKERS.some((f) => existsSync23(join27(root, f)))) return true;
83990
+ if (WORKSPACE_MARKERS.some((f) => existsSync23(join28(root, f)))) return true;
83683
83991
  return /"workspaces"\s*:/.test(texts.get("package.json") ?? "") || /<modules>/.test(texts.get("pom.xml") ?? "") || /^\s*\[workspace\]/m.test(texts.get("Cargo.toml") ?? "");
83684
83992
  }
83685
83993
  var EMPTY_SCAN = { deps: [], self: [], complete: true };
@@ -83693,11 +84001,11 @@ function scanManifests(root) {
83693
84001
  const texts = /* @__PURE__ */ new Map();
83694
84002
  const stamps = [];
83695
84003
  for (const rel of paths) {
83696
- const abs = join27(root, rel);
84004
+ const abs = join28(root, rel);
83697
84005
  try {
83698
- const s = statSync9(abs);
84006
+ const s = statSync10(abs);
83699
84007
  stamps.push(`${rel}:${s.mtimeMs}:${s.size}`);
83700
- texts.set(rel, readFileSync23(abs, "utf8"));
84008
+ texts.set(rel, readFileSync24(abs, "utf8"));
83701
84009
  } catch {
83702
84010
  }
83703
84011
  }
@@ -83733,22 +84041,22 @@ function readRetrievalInputs(root, repoLocator) {
83733
84041
  }
83734
84042
 
83735
84043
  // src/git-sensor.ts
83736
- import { existsSync as existsSync24, readFileSync as readFileSync24, watch as fsWatch } from "node:fs";
83737
- import { join as join28 } from "node:path";
84044
+ import { existsSync as existsSync24, readFileSync as readFileSync25, watch as fsWatch } from "node:fs";
84045
+ import { join as join29 } from "node:path";
83738
84046
  function readFirstLine(path3) {
83739
84047
  try {
83740
- return readFileSync24(path3, "utf8").split(/\r?\n/, 1)[0].trim();
84048
+ return readFileSync25(path3, "utf8").split(/\r?\n/, 1)[0].trim();
83741
84049
  } catch {
83742
84050
  return null;
83743
84051
  }
83744
84052
  }
83745
84053
  function readGitRefState(gitDir) {
83746
- const head2 = readFirstLine(join28(gitDir, "HEAD"));
84054
+ const head2 = readFirstLine(join29(gitDir, "HEAD"));
83747
84055
  const m = head2 ? /^ref:\s*refs\/heads\/(.+)$/.exec(head2) : null;
83748
84056
  const branch = m ? m[1] : null;
83749
84057
  let sha2 = null;
83750
84058
  if (branch) {
83751
- sha2 = readFirstLine(join28(gitDir, "refs", "heads", branch));
84059
+ sha2 = readFirstLine(join29(gitDir, "refs", "heads", branch));
83752
84060
  if (!sha2) sha2 = shaFromPackedRefs(gitDir, `refs/heads/${branch}`);
83753
84061
  } else if (head2 && /^[0-9a-f]{7,40}$/i.test(head2)) {
83754
84062
  sha2 = head2;
@@ -83756,13 +84064,13 @@ function readGitRefState(gitDir) {
83756
84064
  return {
83757
84065
  branch,
83758
84066
  sha: sha2,
83759
- mergeHeadExists: existsSync24(join28(gitDir, "MERGE_HEAD")),
83760
- origHeadExists: existsSync24(join28(gitDir, "ORIG_HEAD"))
84067
+ mergeHeadExists: existsSync24(join29(gitDir, "MERGE_HEAD")),
84068
+ origHeadExists: existsSync24(join29(gitDir, "ORIG_HEAD"))
83761
84069
  };
83762
84070
  }
83763
84071
  function shaFromPackedRefs(gitDir, ref) {
83764
84072
  try {
83765
- for (const line of readFileSync24(join28(gitDir, "packed-refs"), "utf8").split(/\r?\n/)) {
84073
+ for (const line of readFileSync25(join29(gitDir, "packed-refs"), "utf8").split(/\r?\n/)) {
83766
84074
  const [sha2, name2] = line.split(/\s+/);
83767
84075
  if (name2 === ref && sha2) return sha2;
83768
84076
  }
@@ -83796,7 +84104,7 @@ function startGitSensor(gitDir, onEvent, opts = {}) {
83796
84104
  const settle = () => {
83797
84105
  if (timer) clearTimeout(timer);
83798
84106
  timer = setTimeout(() => {
83799
- if (existsSync24(join28(gitDir, "index.lock"))) {
84107
+ if (existsSync24(join29(gitDir, "index.lock"))) {
83800
84108
  settle();
83801
84109
  return;
83802
84110
  }
@@ -83807,7 +84115,7 @@ function startGitSensor(gitDir, onEvent, opts = {}) {
83807
84115
  }, debounceMs);
83808
84116
  };
83809
84117
  for (const sub of ["HEAD", "logs/HEAD", "MERGE_HEAD", "ORIG_HEAD"]) {
83810
- const p = join28(gitDir, sub);
84118
+ const p = join29(gitDir, sub);
83811
84119
  try {
83812
84120
  watchers.push(fsWatch(p, settle));
83813
84121
  } catch {
@@ -84037,8 +84345,8 @@ var TelemetryRecorder = class {
84037
84345
  };
84038
84346
 
84039
84347
  // src/file-activity.ts
84040
- import { readFileSync as readFileSync26 } from "node:fs";
84041
- import { join as join30 } from "node:path";
84348
+ import { readFileSync as readFileSync27 } from "node:fs";
84349
+ import { join as join31 } from "node:path";
84042
84350
  import { createHash as createHash17 } from "node:crypto";
84043
84351
 
84044
84352
  // ../../packages/privacy/src/patterns/credentials.ts
@@ -84790,8 +85098,8 @@ init_git_remote();
84790
85098
  // src/history-bundle.ts
84791
85099
  init_src();
84792
85100
  import { execFile as execFile2 } from "node:child_process";
84793
- import { readFileSync as readFileSync25 } from "node:fs";
84794
- import { join as join29 } from "node:path";
85101
+ import { readFileSync as readFileSync26 } from "node:fs";
85102
+ import { join as join30 } from "node:path";
84795
85103
  var DEFAULT_MAX_TOKENS = 6e3;
84796
85104
  var FILE_LIST_CAP = 60;
84797
85105
  var DIFF_FILE_CAP = 40;
@@ -84830,7 +85138,7 @@ function pathAllowedByFloor(path3) {
84830
85138
  function loadRepoIgnore(root, extraPatterns = []) {
84831
85139
  let source = "";
84832
85140
  try {
84833
- source = readFileSync25(join29(root, ".errataignore"), "utf8");
85141
+ source = readFileSync26(join30(root, ".errataignore"), "utf8");
84834
85142
  } catch {
84835
85143
  source = "";
84836
85144
  }
@@ -85005,24 +85313,28 @@ function headerPaths(diff) {
85005
85313
  }
85006
85314
  return out2.filter((p) => p !== "/dev/null");
85007
85315
  }
85008
- function git2(repoDir, args2) {
85316
+ var GIT_MAX_BUFFER = 64 * 1024 * 1024;
85317
+ function git2(repoDir, args2, maxBuffer = GIT_MAX_BUFFER) {
85009
85318
  return new Promise((resolve10, reject) => {
85010
85319
  execFile2(
85011
85320
  "git",
85012
85321
  ["-C", repoDir, ...args2],
85013
- { encoding: "utf8", maxBuffer: 64 * 1024 * 1024, windowsHide: true },
85322
+ { encoding: "utf8", maxBuffer, windowsHide: true },
85014
85323
  (err2, stdout) => err2 ? reject(err2) : resolve10(stdout)
85015
85324
  );
85016
85325
  });
85017
85326
  }
85018
- async function unitDiff(root, unit, paths) {
85327
+ async function unitDiff(root, unit, paths, maxChars = GIT_MAX_BUFFER) {
85019
85328
  if (paths.length === 0) return "";
85020
85329
  const common = ["--unified=3", "--no-color", "-M", "--no-ext-diff"];
85021
85330
  const firstParent = unit.parents[0];
85022
- if (unit.isMerge && firstParent) {
85023
- return git2(root, ["diff", ...common, firstParent, unit.sha, "--", ...paths]);
85331
+ const args2 = unit.isMerge && firstParent ? ["diff", ...common, firstParent, unit.sha, "--", ...paths] : ["show", "--format=", ...common, unit.sha, "--", ...paths];
85332
+ try {
85333
+ return await git2(root, args2, maxChars);
85334
+ } catch (err2) {
85335
+ if (err2.code === "ERR_CHILD_PROCESS_STDIO_MAXBUFFER" && maxChars < GIT_MAX_BUFFER) return null;
85336
+ throw err2;
85024
85337
  }
85025
- return git2(root, ["show", "--format=", ...common, unit.sha, "--", ...paths]);
85026
85338
  }
85027
85339
  function fileRow(token, f) {
85028
85340
  const tag = f.binary ? "bin" : `+${f.adds}/-${f.dels}`;
@@ -85059,7 +85371,9 @@ async function buildUnitBundle(root, unit, opts = {}) {
85059
85371
  const sourceFiles = ordered.filter(isSourceFile);
85060
85372
  const diffPaths = sourceFiles.slice(0, DIFF_FILE_CAP).map((f) => f.path);
85061
85373
  if (sourceFiles.length > DIFF_FILE_CAP) truncated = true;
85062
- const rawDiff = await unitDiff(root, unit, diffPaths);
85374
+ const cappedDiff = await unitDiff(root, unit, diffPaths, opts.maxRawDiffChars);
85375
+ if (cappedDiff === null) truncated = true;
85376
+ const rawDiff = cappedDiff ?? "";
85063
85377
  for (const p of headerPaths(rawDiff)) tokens.token(p);
85064
85378
  const narrativeRaw = opts.narrative ?? [unit.subject.trim(), stripTrailers(unit.body)].filter((s) => s.length > 0).join("\n\n");
85065
85379
  const n = scrubHistoryText(tokens.apply(stripTrailers(narrativeRaw)));
@@ -85129,7 +85443,7 @@ function readActivityBranch(root) {
85129
85443
  try {
85130
85444
  const gitDir = resolveGitDir(root);
85131
85445
  if (!gitDir) return null;
85132
- const head2 = readFileSync26(join30(gitDir, "HEAD"), "utf8").trim();
85446
+ const head2 = readFileSync27(join31(gitDir, "HEAD"), "utf8").trim();
85133
85447
  const branch = head2.startsWith("ref: refs/heads/") ? head2.slice(16) : /^[a-f0-9]{40,64}$/i.test(head2) ? "HEAD" : null;
85134
85448
  return branch && branch.length <= 256 && !/[\x00-\x1f\x7f]/.test(branch) ? branch : null;
85135
85449
  } catch {
@@ -85288,19 +85602,19 @@ var FileActivityReporter = class {
85288
85602
  import {
85289
85603
  existsSync as existsSync25,
85290
85604
  mkdirSync as mkdirSync7,
85291
- readFileSync as readFileSync27,
85605
+ readFileSync as readFileSync28,
85292
85606
  readdirSync as readdirSync9,
85293
85607
  unlinkSync as unlinkSync4,
85294
- writeFileSync as writeFileSync18
85608
+ writeFileSync as writeFileSync19
85295
85609
  } from "node:fs";
85296
- import { basename as basename7, join as join31 } from "node:path";
85610
+ import { basename as basename7, join as join32 } from "node:path";
85297
85611
  function skillFileName(id) {
85298
85612
  return `${id.replace(/[^A-Za-z0-9_.-]/g, "_")}.md`;
85299
85613
  }
85300
85614
  function readSkillManifest(manifestPath) {
85301
85615
  if (!existsSync25(manifestPath)) return [];
85302
85616
  try {
85303
- const parsed = JSON.parse(readFileSync27(manifestPath, "utf8"));
85617
+ const parsed = JSON.parse(readFileSync28(manifestPath, "utf8"));
85304
85618
  return (parsed.skills ?? []).map((s) => ({
85305
85619
  title: s.title ?? "",
85306
85620
  layer: s.layer ?? "technique",
@@ -85324,7 +85638,7 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
85324
85638
  for (const s of res.skills) {
85325
85639
  const fileName = skillFileName(s.id);
85326
85640
  keep.add(fileName);
85327
- writeFileSync18(join31(paths.skillsDir, fileName), s.markdown, "utf8");
85641
+ writeFileSync19(join32(paths.skillsDir, fileName), s.markdown, "utf8");
85328
85642
  rows.push({
85329
85643
  id: s.id,
85330
85644
  title: s.title,
@@ -85337,7 +85651,7 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
85337
85651
  const fileName = skillFileName(p.id);
85338
85652
  if (keep.has(fileName)) continue;
85339
85653
  keep.add(fileName);
85340
- writeFileSync18(join31(paths.skillsDir, fileName), p.markdown, "utf8");
85654
+ writeFileSync19(join32(paths.skillsDir, fileName), p.markdown, "utf8");
85341
85655
  rows.push({
85342
85656
  id: p.id,
85343
85657
  title: p.title,
@@ -85351,13 +85665,13 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
85351
85665
  if (!f.endsWith(".md")) continue;
85352
85666
  if (keep.has(basename7(f))) continue;
85353
85667
  try {
85354
- unlinkSync4(join31(paths.skillsDir, f));
85668
+ unlinkSync4(join32(paths.skillsDir, f));
85355
85669
  pruned++;
85356
85670
  } catch {
85357
85671
  }
85358
85672
  }
85359
85673
  rows.sort((a, b) => a.id.localeCompare(b.id));
85360
- writeFileSync18(
85674
+ writeFileSync19(
85361
85675
  paths.skillsManifest,
85362
85676
  JSON.stringify({ generatedAt: Date.now(), skills: rows }, null, 2),
85363
85677
  "utf8"
@@ -85372,19 +85686,19 @@ import {
85372
85686
  existsSync as existsSync26,
85373
85687
  lstatSync,
85374
85688
  mkdirSync as mkdirSync8,
85375
- readFileSync as readFileSync28,
85689
+ readFileSync as readFileSync29,
85376
85690
  readdirSync as readdirSync10,
85377
85691
  rmSync as rmSync3,
85378
85692
  symlinkSync,
85379
- writeFileSync as writeFileSync19
85693
+ writeFileSync as writeFileSync20
85380
85694
  } from "node:fs";
85381
- import { join as join32 } from "node:path";
85695
+ import { join as join33 } from "node:path";
85382
85696
  var SKILL_NS = "errata-";
85383
85697
  var HARNESS_SKILL_DIRS = [
85384
- { configDir: ".claude", skillsDir: join32(".claude", "skills") },
85698
+ { configDir: ".claude", skillsDir: join33(".claude", "skills") },
85385
85699
  // Cursor adopted the standard; its exact project dir is still moving — kept
85386
85700
  // best-effort and gated on `.cursor/` presence so we never create it blind.
85387
- { configDir: ".cursor", skillsDir: join32(".cursor", "skills") }
85701
+ { configDir: ".cursor", skillsDir: join33(".cursor", "skills") }
85388
85702
  ];
85389
85703
  function skillSlug(title, id) {
85390
85704
  const base = title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || id.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "skill";
@@ -85434,7 +85748,7 @@ function reconcileNamespaced(dir, keep) {
85434
85748
  for (const name2 of readdirSync10(dir)) {
85435
85749
  if (!name2.startsWith(SKILL_NS) || keep.has(name2)) continue;
85436
85750
  try {
85437
- rmSync3(join32(dir, name2), { recursive: true, force: true });
85751
+ rmSync3(join33(dir, name2), { recursive: true, force: true });
85438
85752
  pruned++;
85439
85753
  } catch {
85440
85754
  }
@@ -85464,7 +85778,7 @@ function safeLstat(p) {
85464
85778
  }
85465
85779
  }
85466
85780
  function emitAndProjectSkills(root, skills) {
85467
- const agentsSkillsDir = join32(root, ".agents", "skills");
85781
+ const agentsSkillsDir = join33(root, ".agents", "skills");
85468
85782
  mkdirSync8(agentsSkillsDir, { recursive: true });
85469
85783
  const slugs = [];
85470
85784
  const keep = /* @__PURE__ */ new Set();
@@ -85472,7 +85786,7 @@ function emitAndProjectSkills(root, skills) {
85472
85786
  for (const s of skills) {
85473
85787
  let body2;
85474
85788
  try {
85475
- body2 = readFileSync28(s.bodyPath, "utf8");
85789
+ body2 = readFileSync29(s.bodyPath, "utf8");
85476
85790
  } catch {
85477
85791
  continue;
85478
85792
  }
@@ -85481,9 +85795,9 @@ function emitAndProjectSkills(root, skills) {
85481
85795
  keep.add(slug2);
85482
85796
  slugs.push(slug2);
85483
85797
  const description = deriveDescription(s.title, s.layer, body2);
85484
- mkdirSync8(join32(agentsSkillsDir, slug2), { recursive: true });
85485
- writeFileSync19(
85486
- join32(agentsSkillsDir, slug2, "SKILL.md"),
85798
+ mkdirSync8(join33(agentsSkillsDir, slug2), { recursive: true });
85799
+ writeFileSync20(
85800
+ join33(agentsSkillsDir, slug2, "SKILL.md"),
85487
85801
  renderSkillMd(slug2, description, body2, skillCiteHandle(s)),
85488
85802
  "utf8"
85489
85803
  );
@@ -85492,11 +85806,11 @@ function emitAndProjectSkills(root, skills) {
85492
85806
  reconcileNamespaced(agentsSkillsDir, keep);
85493
85807
  let projected = 0;
85494
85808
  for (const h of HARNESS_SKILL_DIRS) {
85495
- if (!existsSync26(join32(root, h.configDir))) continue;
85496
- const dir = join32(root, h.skillsDir);
85809
+ if (!existsSync26(join33(root, h.configDir))) continue;
85810
+ const dir = join33(root, h.skillsDir);
85497
85811
  mkdirSync8(dir, { recursive: true });
85498
85812
  for (const slug2 of slugs) {
85499
- linkOrCopy(join32(dir, slug2), join32(agentsSkillsDir, slug2));
85813
+ linkOrCopy(join33(dir, slug2), join33(agentsSkillsDir, slug2));
85500
85814
  projected++;
85501
85815
  }
85502
85816
  reconcileNamespaced(dir, keep);
@@ -85507,13 +85821,13 @@ function emitAndProjectSkills(root, skills) {
85507
85821
  function emitInputsFromManifest(erretaDir, manifestPath) {
85508
85822
  if (!existsSync26(manifestPath)) return [];
85509
85823
  try {
85510
- const parsed = JSON.parse(readFileSync28(manifestPath, "utf8"));
85824
+ const parsed = JSON.parse(readFileSync29(manifestPath, "utf8"));
85511
85825
  return (parsed.skills ?? []).filter((s) => Boolean(s.id && s.file)).map((s) => ({
85512
85826
  id: s.id,
85513
85827
  title: s.title ?? s.id,
85514
85828
  layer: s.layer ?? "technique",
85515
85829
  confidence: s.confidence ?? 0,
85516
- bodyPath: join32(erretaDir, s.file)
85830
+ bodyPath: join33(erretaDir, s.file)
85517
85831
  }));
85518
85832
  } catch {
85519
85833
  return [];
@@ -85527,17 +85841,17 @@ var GITIGNORE_LINES = [
85527
85841
  ".cursor/skills/errata-*/"
85528
85842
  ];
85529
85843
  function ensureSkillGitignore(root) {
85530
- const path3 = join32(root, ".gitignore");
85844
+ const path3 = join33(root, ".gitignore");
85531
85845
  let current = "";
85532
85846
  try {
85533
- current = existsSync26(path3) ? readFileSync28(path3, "utf8") : "";
85847
+ current = existsSync26(path3) ? readFileSync29(path3, "utf8") : "";
85534
85848
  } catch {
85535
85849
  return;
85536
85850
  }
85537
85851
  if (current.includes(GITIGNORE_MARK)) return;
85538
85852
  const prefix = current.length > 0 && !current.endsWith("\n") ? "\n" : "";
85539
85853
  try {
85540
- writeFileSync19(path3, `${current}${prefix}
85854
+ writeFileSync20(path3, `${current}${prefix}
85541
85855
  ${GITIGNORE_LINES.join("\n")}
85542
85856
  `, "utf8");
85543
85857
  } catch {
@@ -85633,18 +85947,18 @@ init_paths();
85633
85947
  init_profile2();
85634
85948
 
85635
85949
  // src/witness-queue.ts
85636
- import { readFileSync as readFileSync29, renameSync as renameSync3, writeFileSync as writeFileSync20 } from "node:fs";
85637
- import { dirname as dirname12, join as join33 } from "node:path";
85950
+ import { readFileSync as readFileSync30, renameSync as renameSync4, writeFileSync as writeFileSync21 } from "node:fs";
85951
+ import { dirname as dirname13, join as join34 } from "node:path";
85638
85952
  var WITNESS_QUEUE_CAP = 500;
85639
85953
  var WITNESS_TTL_MS = 14 * 24 * 60 * 60 * 1e3;
85640
85954
  var WITNESS_MAX_ATTEMPTS = 5;
85641
85955
  function witnessQueuePath(workspaceConfigDir) {
85642
- return join33(workspaceConfigDir, "witness-queue.json");
85956
+ return join34(workspaceConfigDir, "witness-queue.json");
85643
85957
  }
85644
85958
  function loadWitnessQueueWithLosses(path3) {
85645
85959
  let raw2;
85646
85960
  try {
85647
- raw2 = JSON.parse(readFileSync29(path3, "utf8"));
85961
+ raw2 = JSON.parse(readFileSync30(path3, "utf8"));
85648
85962
  } catch (err2) {
85649
85963
  const absent = err2?.code === "ENOENT";
85650
85964
  return { queue: [], fileUnreadable: !absent, malformedEntries: 0 };
@@ -85657,9 +85971,9 @@ function loadWitnessQueueWithLosses(path3) {
85657
85971
  }
85658
85972
  function saveWitnessQueue(path3, queue) {
85659
85973
  try {
85660
- const tmp = join33(dirname12(path3), `.${Date.now()}.witness-queue.tmp`);
85661
- writeFileSync20(tmp, JSON.stringify(queue), "utf8");
85662
- renameSync3(tmp, path3);
85974
+ const tmp = join34(dirname13(path3), `.${Date.now()}.witness-queue.tmp`);
85975
+ writeFileSync21(tmp, JSON.stringify(queue), "utf8");
85976
+ renameSync4(tmp, path3);
85663
85977
  } catch {
85664
85978
  }
85665
85979
  }
@@ -85967,8 +86281,8 @@ function maybeFlushDigests() {
85967
86281
 
85968
86282
  // src/liveness-watch.ts
85969
86283
  init_src5();
85970
- import { readFileSync as readFileSync31, writeFileSync as writeFileSync22 } from "node:fs";
85971
- import { join as join35 } from "node:path";
86284
+ import { readFileSync as readFileSync32, writeFileSync as writeFileSync23 } from "node:fs";
86285
+ import { join as join36 } from "node:path";
85972
86286
 
85973
86287
  // src/loop-lag.ts
85974
86288
  var HEARTBEAT_MS = 500;
@@ -85980,13 +86294,14 @@ var recent3 = [];
85980
86294
  function markPass(name2) {
85981
86295
  const id = nextPassId++;
85982
86296
  const startedAt = Date.now();
86297
+ const readsAtStart = ioReadOps();
85983
86298
  active2.set(id, { name: name2, startedAt });
85984
86299
  let ended = false;
85985
86300
  return () => {
85986
86301
  if (ended) return;
85987
86302
  ended = true;
85988
86303
  active2.delete(id);
85989
- recent3.unshift({ name: name2, ms: Date.now() - startedAt, endedAt: Date.now() });
86304
+ recent3.unshift({ name: name2, ms: Date.now() - startedAt, endedAt: Date.now(), readOps: ioReadOps() - readsAtStart });
85990
86305
  if (recent3.length > RECENT_PASS_LIMIT) recent3.pop();
85991
86306
  };
85992
86307
  }
@@ -86099,11 +86414,11 @@ function watchCensusLine(c = watchCensus(), now = Date.now()) {
86099
86414
  var LIVENESS_WATCH_INTERVAL_MS = 60 * 60 * 1e3;
86100
86415
  var ALARM_RENOTIFY_MS = 24 * 60 * 60 * 1e3;
86101
86416
  function alarmStatePath(configDir) {
86102
- return join35(configDir, "liveness-alarms.json");
86417
+ return join36(configDir, "liveness-alarms.json");
86103
86418
  }
86104
86419
  function loadAlarmState(path3) {
86105
86420
  try {
86106
- const raw2 = JSON.parse(readFileSync31(path3, "utf8"));
86421
+ const raw2 = JSON.parse(readFileSync32(path3, "utf8"));
86107
86422
  return new Map(Object.entries(raw2).filter((e) => typeof e[1] === "number"));
86108
86423
  } catch {
86109
86424
  return /* @__PURE__ */ new Map();
@@ -86111,7 +86426,7 @@ function loadAlarmState(path3) {
86111
86426
  }
86112
86427
  function saveAlarmState(path3, state) {
86113
86428
  try {
86114
- writeFileSync22(path3, JSON.stringify(Object.fromEntries(state)));
86429
+ writeFileSync23(path3, JSON.stringify(Object.fromEntries(state)));
86115
86430
  } catch {
86116
86431
  }
86117
86432
  }
@@ -86141,12 +86456,15 @@ function toastLivenessAlarms(gate, workspace, alarms, deliver, nowMs) {
86141
86456
  return fresh;
86142
86457
  }
86143
86458
  function createLivenessWatch(deps) {
86144
- let lastRunAt = 0;
86459
+ let lastRunAt = null;
86145
86460
  let running = false;
86146
86461
  const lastAlarmedAt = loadAlarmState(alarmStatePath(deps.configDir));
86147
86462
  return {
86148
86463
  async maybeRun(nowMs = Date.now()) {
86149
- if (running || nowMs - lastRunAt < LIVENESS_WATCH_INTERVAL_MS) return null;
86464
+ if (running) return null;
86465
+ lastRunAt ??= summarizePassLedger(deps.configDir).get("liveness-watch")?.lastTs ?? 0;
86466
+ if (lastRunAt > nowMs) lastRunAt = 0;
86467
+ if (nowMs - lastRunAt < LIVENESS_WATCH_INTERVAL_MS) return null;
86150
86468
  lastRunAt = nowMs;
86151
86469
  running = true;
86152
86470
  try {
@@ -86238,6 +86556,25 @@ function runWorkspaceMaintenance(store, workspaceId2) {
86238
86556
  };
86239
86557
  }
86240
86558
 
86559
+ // src/pass-inputs.ts
86560
+ function passInputs(store, pass, scopes) {
86561
+ const key = `pass-inputs:${pass}`;
86562
+ const seq = store.changeSeq?.(scopes);
86563
+ let held = null;
86564
+ try {
86565
+ held = JSON.parse(store.getMeta?.(key) ?? "null");
86566
+ } catch {
86567
+ held = null;
86568
+ }
86569
+ return {
86570
+ unchanged: seq !== void 0 && held !== null && held.seq === seq,
86571
+ last: held?.result ?? null,
86572
+ complete(result) {
86573
+ if (seq !== void 0) store.setMeta?.(key, JSON.stringify({ seq, result }));
86574
+ }
86575
+ };
86576
+ }
86577
+
86241
86578
  // src/watch-breaker.ts
86242
86579
  function numEnv3(key, fallback) {
86243
86580
  const n = Number(process.env[key]);
@@ -86339,7 +86676,7 @@ function createWatchBreaker(deps) {
86339
86676
  }
86340
86677
 
86341
86678
  // src/engine.ts
86342
- var DAEMON_VERSION = true ? "2.0.22-dev.4430" : "2.0.0-alpha.0";
86679
+ var DAEMON_VERSION = true ? "2.0.22-dev.4534" : "2.0.0-alpha.0";
86343
86680
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
86344
86681
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
86345
86682
  var GIT_OP_MUTE_MS = 4e3;
@@ -86351,8 +86688,8 @@ var CODEX_SWEEP_LOOKBACK_MS = 10 * 6e4;
86351
86688
  function appendIdentityAudit(path3, record2, line) {
86352
86689
  if (!record2.accepted && record2.score <= 0) return;
86353
86690
  try {
86354
- if (existsSync28(path3) && statSync10(path3).size >= IDENTITY_AUDIT_MAX_BYTES) {
86355
- renameSync4(path3, `${path3}.1`);
86691
+ if (existsSync28(path3) && statSync11(path3).size >= IDENTITY_AUDIT_MAX_BYTES) {
86692
+ renameSync5(path3, `${path3}.1`);
86356
86693
  }
86357
86694
  appendFileSync4(path3, line);
86358
86695
  } catch {
@@ -86361,7 +86698,7 @@ function appendIdentityAudit(path3, record2, line) {
86361
86698
  var yieldToLoop = () => new Promise((r) => setImmediate(r));
86362
86699
  function loadTurnCursors(path3) {
86363
86700
  try {
86364
- const raw2 = JSON.parse(readFileSync32(path3, "utf8"));
86701
+ const raw2 = JSON.parse(readFileSync33(path3, "utf8"));
86365
86702
  return new Map(
86366
86703
  Object.entries(raw2).map(([k, v]) => [k, typeof v === "string" ? v : String(v?.uuid ?? "")])
86367
86704
  );
@@ -86371,7 +86708,7 @@ function loadTurnCursors(path3) {
86371
86708
  }
86372
86709
  function loadTurnOffsets(path3) {
86373
86710
  try {
86374
- const raw2 = JSON.parse(readFileSync32(path3, "utf8"));
86711
+ const raw2 = JSON.parse(readFileSync33(path3, "utf8"));
86375
86712
  const out2 = /* @__PURE__ */ new Map();
86376
86713
  for (const [k, v] of Object.entries(raw2)) {
86377
86714
  const off2 = typeof v === "object" && v !== null ? v.offset : void 0;
@@ -86387,7 +86724,7 @@ function saveTurnCursors(path3, cursors, offsets) {
86387
86724
  const merged = {};
86388
86725
  for (const [k, uuid3] of cursors) merged[k] = { uuid: uuid3, offset: offsets.get(k) ?? 0 };
86389
86726
  for (const [k, offset] of offsets) if (!merged[k]) merged[k] = { uuid: "", offset };
86390
- writeFileSync23(path3, JSON.stringify(merged), "utf8");
86727
+ writeFileSync24(path3, JSON.stringify(merged), "utf8");
86391
86728
  } catch {
86392
86729
  }
86393
86730
  }
@@ -86409,7 +86746,7 @@ function gitSourceWatchTargets(root) {
86409
86746
  ["-C", root, "ls-files", "--others", "--ignored", "--exclude-standard", "--directory", "-z"],
86410
86747
  { encoding: "utf8", maxBuffer: 256 * 1024 * 1024, windowsHide: true, stdio: ["ignore", "pipe", "ignore"] }
86411
86748
  );
86412
- ignoredDirs = igOut.split("\0").filter(Boolean).map((d) => d.replace(/\/+$/, "")).filter((d) => !IGNORED_PATH.test(join36(root, d) + sep4));
86749
+ ignoredDirs = igOut.split("\0").filter(Boolean).map((d) => d.replace(/\/+$/, "")).filter((d) => !IGNORED_PATH.test(join37(root, d) + sep5));
86413
86750
  } catch {
86414
86751
  }
86415
86752
  const hasIgnoredChild = (dir) => ignoredDirs.some((ig) => ig.startsWith(dir + "/"));
@@ -86421,19 +86758,19 @@ function gitSourceWatchTargets(root) {
86421
86758
  if (!f.startsWith(prefix)) continue;
86422
86759
  const rest2 = f.slice(prefix.length);
86423
86760
  if (rest2.includes("/")) children.add(dir === "" ? rest2.slice(0, rest2.indexOf("/")) : dir + "/" + rest2.slice(0, rest2.indexOf("/")));
86424
- else targets.add(join36(root, f));
86761
+ else targets.add(join37(root, f));
86425
86762
  }
86426
86763
  for (const c of children) {
86427
- if (IGNORED_PATH.test(join36(root, c) + sep4)) continue;
86764
+ if (IGNORED_PATH.test(join37(root, c) + sep5)) continue;
86428
86765
  if (hasIgnoredChild(c)) addUnder(c);
86429
- else targets.add(join36(root, c));
86766
+ else targets.add(join37(root, c));
86430
86767
  }
86431
86768
  };
86432
86769
  addUnder("");
86433
86770
  if (targets.size > 0) return [...targets];
86434
86771
  } catch {
86435
86772
  }
86436
- return readdirSync11(root, { withFileTypes: true }).filter((e) => e.isDirectory() && !IGNORED_PATH.test(join36(root, String(e.name)) + sep4)).map((e) => join36(root, String(e.name)));
86773
+ return readdirSync11(root, { withFileTypes: true }).filter((e) => e.isDirectory() && !IGNORED_PATH.test(join37(root, String(e.name)) + sep5)).map((e) => join37(root, String(e.name)));
86437
86774
  }
86438
86775
  function createWorkspaceEngine(opts) {
86439
86776
  const paths = workspacePaths(opts.workspaceRoot);
@@ -86489,6 +86826,7 @@ function createWorkspaceEngine(opts) {
86489
86826
  let watcher = null;
86490
86827
  let watchBreaker = null;
86491
86828
  let lastActivityTs = Date.now();
86829
+ let storeReconciled = !!opts.skipWatchers;
86492
86830
  let stopGit = null;
86493
86831
  let fsReindex;
86494
86832
  let stopping = false;
@@ -86525,7 +86863,7 @@ function createWorkspaceEngine(opts) {
86525
86863
  }
86526
86864
  let size = 0;
86527
86865
  try {
86528
- size = statSync10(path3).size;
86866
+ size = statSync11(path3).size;
86529
86867
  } catch {
86530
86868
  }
86531
86869
  lastActivityTs = Date.now();
@@ -86572,7 +86910,7 @@ function createWorkspaceEngine(opts) {
86572
86910
  fsReindex = createCoalescedFilePass(REINDEX_DEBOUNCE_MS, async (changed) => {
86573
86911
  if (stopping) return;
86574
86912
  const t = Date.now();
86575
- const relChanged = changed.map((p) => relative7(opts.workspaceRoot, p).split(sep4).join("/"));
86913
+ const relChanged = changed.map((p) => relative6(opts.workspaceRoot, p).split(sep5).join("/"));
86576
86914
  const causal = causalBuffer.correlate(relChanged, t) ?? void 0;
86577
86915
  await runReindexPass(
86578
86916
  `fs-reindex:${profile.name} (${changed.length} files)`,
@@ -86632,7 +86970,7 @@ function createWorkspaceEngine(opts) {
86632
86970
  const srcPaths = diff.changedPaths.filter((p) => /\.(ts|tsx|js|jsx|mjs|cjs|py)$/i.test(p));
86633
86971
  let episodeId2;
86634
86972
  if (srcPaths.length > 0) {
86635
- const abs = srcPaths.map((p) => join36(opts.workspaceRoot, p));
86973
+ const abs = srcPaths.map((p) => join37(opts.workspaceRoot, p));
86636
86974
  try {
86637
86975
  const r = await runReindexPass(
86638
86976
  `git-reindex:${profile.name} (${abs.length} files)`,
@@ -86668,7 +87006,7 @@ function createWorkspaceEngine(opts) {
86668
87006
  `[errata] git: ${ev.kind} ${ev.newSha.slice(0, 7)} by ${meta3.authorName} \u2014 ${diff.changedPaths.length} file(s), ${diff.renames.length} rename(s)`
86669
87007
  );
86670
87008
  };
86671
- const gitDir = join36(opts.workspaceRoot, ".git");
87009
+ const gitDir = join37(opts.workspaceRoot, ".git");
86672
87010
  if (existsSync28(gitDir)) {
86673
87011
  stopGit = startGitSensor(gitDir, (ev) => {
86674
87012
  void handleGitEvent(ev).catch((err2) => {
@@ -86678,6 +87016,10 @@ function createWorkspaceEngine(opts) {
86678
87016
  }
86679
87017
  setImmediate(() => {
86680
87018
  const reconcileStartedAt = Date.now();
87019
+ try {
87020
+ store.pruneChangeLog?.();
87021
+ } catch {
87022
+ }
86681
87023
  const reconcile = passWorker ? passWorker.reconcile().catch(() => reconcileStaleFiles(store, opts.workspaceRoot, profile.id)) : reconcileStaleFiles(store, opts.workspaceRoot, profile.id);
86682
87024
  void reconcile.then((n) => {
86683
87025
  appendPassLedger(paths.configDir, "reconcile", Date.now() - reconcileStartedAt, {
@@ -86712,6 +87054,7 @@ function createWorkspaceEngine(opts) {
86712
87054
  } catch (err2) {
86713
87055
  console.warn("[errata] orphan reap failed:", err2 instanceof Error ? err2.message : err2);
86714
87056
  }
87057
+ storeReconciled = true;
86715
87058
  });
86716
87059
  });
86717
87060
  }
@@ -86725,7 +87068,7 @@ function createWorkspaceEngine(opts) {
86725
87068
  },
86726
87069
  onAlarms: (alarms) => {
86727
87070
  toastLivenessAlarms(
86728
- sharedAlarmToastGate(join36(globalDir(), "liveness-toasts.json")),
87071
+ sharedAlarmToastGate(join37(globalDir(), "liveness-toasts.json")),
86729
87072
  { root: opts.workspaceRoot, name: profile.name },
86730
87073
  alarms,
86731
87074
  (body2, key) => notifyEvent("mechanism-stalled", body2, { key }),
@@ -86742,7 +87085,7 @@ function createWorkspaceEngine(opts) {
86742
87085
  let subagentBase = null;
86743
87086
  let subagentBaseVersion = 0;
86744
87087
  const subagentRenders = /* @__PURE__ */ new Map();
86745
- const sessions = createSessionRegistry({ originsPath: join36(paths.configDir, "session-origins.json") });
87088
+ const sessions = createSessionRegistry({ originsPath: join37(paths.configDir, "session-origins.json") });
86746
87089
  const sessionRenders = /* @__PURE__ */ new Map();
86747
87090
  const selfCiteSkipsBySession = /* @__PURE__ */ new Map();
86748
87091
  const toolRuns = createToolRunState();
@@ -86756,6 +87099,7 @@ function createWorkspaceEngine(opts) {
86756
87099
  let intentRemoteInFlight = false;
86757
87100
  let ctxRefreshInFlight = false;
86758
87101
  let ctxRefreshQueued = false;
87102
+ let lastWorkerSnapshot = null;
86759
87103
  let lastSelfCiteSkips = 0;
86760
87104
  const refreshContextNow = () => {
86761
87105
  void refreshContextAsync().catch((err2) => {
@@ -86834,26 +87178,35 @@ function createWorkspaceEngine(opts) {
86834
87178
  const elicit = isEdgeElicitationEnabled();
86835
87179
  const snapOpts = {
86836
87180
  profile,
86837
- atCommit: readGitRefState(join36(opts.workspaceRoot, ".git")).sha ?? void 0,
87181
+ atCommit: readGitRefState(join37(opts.workspaceRoot, ".git")).sha ?? void 0,
86838
87182
  reviewCount: pendingCount(paths),
86839
87183
  reviewUiUrl: opts.reviewUrl(),
86840
87184
  workingFile: workingFiles.mostRecent() ?? void 0,
86841
87185
  skills: readSkillManifest(paths.skillsManifest),
86842
87186
  ...lastSelfCiteSkips > 0 ? { selfCiteSkips: lastSelfCiteSkips } : {}
86843
87187
  };
86844
- const prebuilt = passWorker ? await passWorker.snapshot(snapOpts).catch((err2) => {
87188
+ const changes = store.changeSeq ? store.changeSeq() - store.changeSeq([EXPOSURE_SCOPE]) : store.changeStamp();
87189
+ const { id, name: name2, stack, languages, domains, goals } = snapOpts.profile;
87190
+ const snapshotKey = `${snapshotCodeIdentity(DAEMON_VERSION)}|${changes}|${JSON.stringify({ ...snapOpts, profile: { id, name: name2, stack, languages, domains, goals } })}`;
87191
+ lastWorkerSnapshot ??= loadHeldSnapshot(heldSnapshotPath(paths.configDir));
87192
+ const held = lastWorkerSnapshot;
87193
+ const prebuilt = snapshotReusable(held, { key: snapshotKey, atCommit: snapOpts.atCommit, workingFile: snapOpts.workingFile }) ? structuredClone(held.snapshot) : passWorker ? await passWorker.snapshot(snapOpts).then((snapshot2) => {
87194
+ lastWorkerSnapshot = { key: snapshotKey, at: Date.now(), atCommit: snapOpts.atCommit, workingFile: snapOpts.workingFile, snapshot: structuredClone(snapshot2) };
87195
+ saveHeldSnapshot(heldSnapshotPath(paths.configDir), lastWorkerSnapshot);
87196
+ return snapshot2;
87197
+ }).catch((err2) => {
86845
87198
  console.warn(
86846
87199
  `[errata] snapshot worker failed \u2014 rendering INLINE on main:`,
86847
87200
  err2 instanceof Error ? err2.message : err2
86848
87201
  );
86849
87202
  return null;
86850
87203
  }) : null;
86851
- if (snapOpts.atCommit !== (readGitRefState(join36(opts.workspaceRoot, ".git")).sha ?? void 0)) {
87204
+ if (snapOpts.atCommit !== (readGitRefState(join37(opts.workspaceRoot, ".git")).sha ?? void 0)) {
86852
87205
  contextDirty = true;
86853
87206
  return;
86854
87207
  }
86855
87208
  const doneRender = markPass(`${prebuilt ? "context-render" : "context-render-inline"}:${profile.name}`);
86856
- const base = prebuilt ?? buildSnapshot({ store, ...snapOpts });
87209
+ const base = freshenRecentBands(prebuilt ?? buildSnapshot({ store, ...snapOpts }), (id2) => store.getNode(id2));
86857
87210
  subagentBase = structuredClone(base);
86858
87211
  subagentBaseVersion++;
86859
87212
  const sharedSnapshot = scopeSnapshot(base, (n) => !isQuarantined(n, sessions));
@@ -86894,10 +87247,10 @@ function createWorkspaceEngine(opts) {
86894
87247
  } catch (err2) {
86895
87248
  console.warn("[errata] context card failed:", err2.message?.slice(0, 120));
86896
87249
  }
86897
- const target = join36(opts.workspaceRoot, "AGENTS.md");
87250
+ const target = join37(opts.workspaceRoot, "AGENTS.md");
86898
87251
  writeManagedBlock(target, { body: AGENTS_POINTER_BODY, stable: true, force: true });
86899
87252
  if (elicit) {
86900
- writePrimingHandles(join36(paths.configDir, "priming-handles.json"), [
87253
+ writePrimingHandles(join37(paths.configDir, "priming-handles.json"), [
86901
87254
  ...snapshot.recentProblems.map((r) => r.node),
86902
87255
  // Resolved-band handles: the ✓ problem AND its Solution are citable
86903
87256
  // (a fix tag on an already-resolved problem no-ops idempotently; the
@@ -87205,8 +87558,8 @@ function createWorkspaceEngine(opts) {
87205
87558
  const cached2 = subagentRenders.get(a.agentId);
87206
87559
  if (cached2?.key === key) return cached2.block;
87207
87560
  const elicit = isEdgeElicitationEnabled();
87208
- const handlesPath = join36(paths.configDir, "priming-handles.json");
87209
- const atCommit = readGitRefState(join36(opts.workspaceRoot, ".git")).sha ?? void 0;
87561
+ const handlesPath = join37(paths.configDir, "priming-handles.json");
87562
+ const atCommit = readGitRefState(join37(opts.workspaceRoot, ".git")).sha ?? void 0;
87210
87563
  const block = renderSubagentBlock({
87211
87564
  store,
87212
87565
  entry,
@@ -87260,7 +87613,7 @@ function createWorkspaceEngine(opts) {
87260
87613
  const cached2 = sessionRenders.get(sessionId);
87261
87614
  if (cached2?.key === key) return cached2.block;
87262
87615
  const elicit = isEdgeElicitationEnabled();
87263
- const atCommit = readGitRefState(join36(opts.workspaceRoot, ".git")).sha ?? void 0;
87616
+ const atCommit = readGitRefState(join37(opts.workspaceRoot, ".git")).sha ?? void 0;
87264
87617
  const scoped = scopeSnapshot(structuredClone(subagentBase), (n) => !hiddenFrom(n, sessionId, sessions, now));
87265
87618
  delete scoped.workingFile;
87266
87619
  if (workingFile) {
@@ -87301,7 +87654,7 @@ function createWorkspaceEngine(opts) {
87301
87654
  ]
87302
87655
  };
87303
87656
  if (elicit && block.handleNodes.length) {
87304
- writePrimingHandles(join36(paths.configDir, "priming-handles.json"), block.handleNodes);
87657
+ writePrimingHandles(join37(paths.configDir, "priming-handles.json"), block.handleNodes);
87305
87658
  }
87306
87659
  sessionRenders.delete(sessionId);
87307
87660
  sessionRenders.set(sessionId, { key, block });
@@ -87361,7 +87714,7 @@ function createWorkspaceEngine(opts) {
87361
87714
  resultSummary: { exitCode: e.exitCode ?? 1, errorTokens: e.errorTokens }
87362
87715
  });
87363
87716
  };
87364
- const turnCursorPath = join36(paths.configDir, "turn-cursors.json");
87717
+ const turnCursorPath = join37(paths.configDir, "turn-cursors.json");
87365
87718
  const lastTurnUuid = loadTurnCursors(turnCursorPath);
87366
87719
  const turnOffset = loadTurnOffsets(turnCursorPath);
87367
87720
  const readLosses = { parseFailures: 0, ioFailures: 0, bytesUnreachable: 0, sliceGuardHits: 0 };
@@ -87423,7 +87776,7 @@ function createWorkspaceEngine(opts) {
87423
87776
  let processedTurns = 0;
87424
87777
  const seqAtStart = store.currentIngestSeq();
87425
87778
  const elicit = isEdgeElicitationEnabled();
87426
- const handleMap = elicit ? readPrimingHandles(join36(paths.configDir, "priming-handles.json")) : {};
87779
+ const handleMap = elicit ? readPrimingHandles(join37(paths.configDir, "priming-handles.json")) : {};
87427
87780
  const wsRoot = (opts.workspaceRoot ?? "").replace(/\\/g, "/");
87428
87781
  const toRel = (abs) => {
87429
87782
  const p = abs.replace(/\\/g, "/");
@@ -87634,7 +87987,7 @@ function createWorkspaceEngine(opts) {
87634
87987
  let anchorReadFailed = false;
87635
87988
  if (p.location) {
87636
87989
  try {
87637
- fileText = readFileSync32(join36(opts.workspaceRoot, p.location.path), "utf8");
87990
+ fileText = readFileSync33(join37(opts.workspaceRoot, p.location.path), "utf8");
87638
87991
  } catch {
87639
87992
  anchorReadFailed = true;
87640
87993
  }
@@ -87796,10 +88149,10 @@ function createWorkspaceEngine(opts) {
87796
88149
  let enclosing = {};
87797
88150
  if (p.location?.line !== void 0) {
87798
88151
  try {
87799
- const headSha = readGitRefState(join36(opts.workspaceRoot, ".git")).sha ?? void 0;
88152
+ const headSha = readGitRefState(join37(opts.workspaceRoot, ".git")).sha ?? void 0;
87800
88153
  enclosing = {
87801
88154
  line: p.location.line,
87802
- fileText: readFileSync32(join36(opts.workspaceRoot, anchorPath), "utf8"),
88155
+ fileText: readFileSync33(join37(opts.workspaceRoot, anchorPath), "utf8"),
87803
88156
  ...headSha ? { headSha } : {}
87804
88157
  };
87805
88158
  } catch {
@@ -88638,7 +88991,7 @@ B: ${b}`,
88638
88991
  try {
88639
88992
  const inputs = emitInputsFromManifest(paths.configDir, paths.skillsManifest);
88640
88993
  emitAndProjectSkills(opts.workspaceRoot, inputs);
88641
- writePrimingHandles(join36(paths.configDir, "priming-handles.json"), skillHandleNodes(inputs));
88994
+ writePrimingHandles(join37(paths.configDir, "priming-handles.json"), skillHandleNodes(inputs));
88642
88995
  } catch (err2) {
88643
88996
  console.warn("[skills] agent-skills projection failed (non-fatal):", err2 instanceof Error ? err2.message : err2);
88644
88997
  }
@@ -88674,6 +89027,7 @@ B: ${b}`,
88674
89027
  lastActivityAt() {
88675
89028
  return lastActivityTs;
88676
89029
  },
89030
+ storeReconciled: () => storeReconciled,
88677
89031
  quarantinedSessions: () => sessions.originSessions(),
88678
89032
  markContextDirty() {
88679
89033
  contextDirty = true;
@@ -88734,7 +89088,46 @@ B: ${b}`,
88734
89088
  return report;
88735
89089
  },
88736
89090
  async semanticMaintenance() {
88737
- const { report, hintUpgrade, seqAdvanced, calibration, calibrationMs } = passWorker ? await passWorker.semanticMaintenance() : runWorkspaceMaintenance(store, profile.id);
89091
+ const inputs = passInputs(store, "semantic-maintenance");
89092
+ if (inputs.unchanged && inputs.last) {
89093
+ const last = inputs.last;
89094
+ const report2 = {
89095
+ ...last.report,
89096
+ designResolved: 0,
89097
+ revisitsCleared: 0,
89098
+ fixCandidatesSettled: 0,
89099
+ claimsEvaluated: 0,
89100
+ claimsDerived: 0,
89101
+ durationMs: 0,
89102
+ fixCandidates: { ...last.report.fixCandidates, answered: 0, ignored: 0, unsubstantiated: 0 }
89103
+ };
89104
+ appendPassLedger(paths.configDir, "semantic-maintenance", 0, {
89105
+ revisitsCleared: 0,
89106
+ revisitsStanding: report2.revisitsStanding,
89107
+ fixCandidatesSettled: 0,
89108
+ fixCandidatesAnswered: 0,
89109
+ fixCandidatesIgnored: 0,
89110
+ fixCandidatesUnsubstantiated: 0,
89111
+ fixCandidatesStanding: report2.fixCandidates.standing,
89112
+ designResolved: 0,
89113
+ claimsEvaluated: 0,
89114
+ seqAdvanced: 0,
89115
+ anchorHintsUpgraded: 0,
89116
+ anchorHintsStanding: last.hintUpgrade.standing,
89117
+ anchorHintsUnresolvable: last.hintUpgrade.unresolvable,
89118
+ anchorHintsBlocked: last.hintUpgrade.blocked,
89119
+ // Telemetry, not a counter: a descriptor must not gate on it.
89120
+ inputsUnchanged: 1
89121
+ });
89122
+ if (last.calibration) {
89123
+ appendPassLedger(paths.configDir, "wm-calibration", 0, { ...last.calibration, inputsUnchanged: 1 });
89124
+ }
89125
+ await livenessWatch.maybeRun();
89126
+ return report2;
89127
+ }
89128
+ const result = passWorker ? await passWorker.semanticMaintenance() : runWorkspaceMaintenance(store, profile.id);
89129
+ inputs.complete(result);
89130
+ const { report, hintUpgrade, seqAdvanced, calibration, calibrationMs } = result;
88738
89131
  appendPassLedger(paths.configDir, "semantic-maintenance", report.durationMs, {
88739
89132
  revisitsCleared: report.revisitsCleared,
88740
89133
  revisitsStanding: report.revisitsStanding,
@@ -89081,7 +89474,7 @@ async function startDaemon(opts) {
89081
89474
  reviewUrl: () => webUiUrl + "/review"
89082
89475
  });
89083
89476
  const writeLockFile = (url2) => {
89084
- writeFileSync24(
89477
+ writeFileSync25(
89085
89478
  engine.paths.daemonLock,
89086
89479
  daemonLockPayload({ pid: process.pid, webUiUrl: url2, processStartedAt, version: DAEMON_VERSION }),
89087
89480
  "utf8"
@@ -89330,8 +89723,8 @@ async function linkRegisteredWorkspaces(cfg, loggedInProfile = cfg.activeInstall
89330
89723
  }
89331
89724
 
89332
89725
  // src/edge-park.ts
89333
- import { readFileSync as readFileSync33, renameSync as renameSync5, writeFileSync as writeFileSync25 } from "node:fs";
89334
- import { dirname as dirname13, join as join37 } from "node:path";
89726
+ import { readFileSync as readFileSync34, renameSync as renameSync6, writeFileSync as writeFileSync26 } from "node:fs";
89727
+ import { dirname as dirname14, join as join38 } from "node:path";
89335
89728
  var EDGE_PARK_CAP = 2e3;
89336
89729
  var EDGE_PARK_TTL_MS = 14 * 24 * 60 * 60 * 1e3;
89337
89730
  var EDGE_PARK_MAX_ATTEMPTS = 6;
@@ -89346,12 +89739,12 @@ function wireEdgeKey(from, type, to) {
89346
89739
  return JSON.stringify([from, type, to]);
89347
89740
  }
89348
89741
  function edgeParkPath(workspaceConfigDir, destinationKey) {
89349
- return join37(workspaceConfigDir, `edge-park.${destinationKey.slice(0, 16)}.json`);
89742
+ return join38(workspaceConfigDir, `edge-park.${destinationKey.slice(0, 16)}.json`);
89350
89743
  }
89351
89744
  function loadEdgePark(path3) {
89352
89745
  let raw2;
89353
89746
  try {
89354
- raw2 = JSON.parse(readFileSync33(path3, "utf8"));
89747
+ raw2 = JSON.parse(readFileSync34(path3, "utf8"));
89355
89748
  } catch {
89356
89749
  return [];
89357
89750
  }
@@ -89362,9 +89755,9 @@ function loadEdgePark(path3) {
89362
89755
  }
89363
89756
  function saveEdgePark(path3, queue) {
89364
89757
  try {
89365
- const tmp = join37(dirname13(path3), `.${Date.now()}.edge-park.tmp`);
89366
- writeFileSync25(tmp, JSON.stringify(queue), "utf8");
89367
- renameSync5(tmp, path3);
89758
+ const tmp = join38(dirname14(path3), `.${Date.now()}.edge-park.tmp`);
89759
+ writeFileSync26(tmp, JSON.stringify(queue), "utf8");
89760
+ renameSync6(tmp, path3);
89368
89761
  } catch {
89369
89762
  }
89370
89763
  }
@@ -89379,6 +89772,14 @@ function edgeHolds(queue, now) {
89379
89772
  }
89380
89773
  return holds;
89381
89774
  }
89775
+ function nextEdgeParkChange(queue) {
89776
+ let next = null;
89777
+ for (const e of queue) {
89778
+ const at = e.state === "dropped" ? (e.droppedAt ?? e.ts) + tombstoneTtl(e) : e.dueAt;
89779
+ if (next === null || at < next) next = at;
89780
+ }
89781
+ return next;
89782
+ }
89382
89783
  function classifyEdgeVerdict(decision, reason) {
89383
89784
  if (decision === "created" || decision === "reinforced") return "landed";
89384
89785
  const why = reason ?? "";
@@ -89676,8 +90077,8 @@ function invalidateInstanceReceipt(current, destination, failedId, mirrorLegacy)
89676
90077
  // src/multi.ts
89677
90078
  init_dist();
89678
90079
  init_src5();
89679
- import { existsSync as existsSync34, writeFileSync as writeFileSync28 } from "node:fs";
89680
- import { resolve as pathResolve } from "node:path";
90080
+ import { existsSync as existsSync34, readFileSync as readFileSync40, writeFileSync as writeFileSync29 } from "node:fs";
90081
+ import { join as join47, resolve as pathResolve } from "node:path";
89681
90082
 
89682
90083
  // src/principle-sync.ts
89683
90084
  init_src5();
@@ -89705,8 +90106,8 @@ init_reconcile();
89705
90106
 
89706
90107
  // src/lockfile-auto.ts
89707
90108
  init_src();
89708
- import { existsSync as existsSync30, readFileSync as readFileSync34 } from "node:fs";
89709
- import { join as join38 } from "node:path";
90109
+ import { existsSync as existsSync30, readFileSync as readFileSync35 } from "node:fs";
90110
+ import { join as join39 } from "node:path";
89710
90111
 
89711
90112
  // src/package-index.ts
89712
90113
  init_src();
@@ -89731,10 +90132,23 @@ function buildContextNode(id, label, description, attrs, ts) {
89731
90132
  attrs
89732
90133
  };
89733
90134
  }
90135
+ function mintContextNode(store, node2) {
90136
+ const existing = store.getNode(node2.id);
90137
+ if (!existing || (existing.validTo ?? null) !== null) {
90138
+ store.mergeNode(node2);
90139
+ return true;
90140
+ }
90141
+ const facts = Object.keys(node2.attrs);
90142
+ const same = existing.label === node2.label && existing.description === node2.description && facts.every((k) => JSON.stringify(existing.attrs[k]) === JSON.stringify(node2.attrs[k]));
90143
+ if (same) return false;
90144
+ store.updateNode(node2.id, { description: node2.description, attrs: { ...existing.attrs, ...node2.attrs }, lastUpdatedAt: node2.lastUpdatedAt });
90145
+ return true;
90146
+ }
89734
90147
  function mintPackageGraph(store, sbom, workspaceId2, ts) {
89735
90148
  const minted = /* @__PURE__ */ new Set();
89736
90149
  for (const c of sbom.components) {
89737
- store.mergeNode(
90150
+ mintContextNode(
90151
+ store,
89738
90152
  buildContextNode(
89739
90153
  c.purl,
89740
90154
  "Package",
@@ -89757,8 +90171,14 @@ function mintPackageGraph(store, sbom, workspaceId2, ts) {
89757
90171
  if (!minted.has(d.ref)) continue;
89758
90172
  for (const to of d.dependsOn) {
89759
90173
  if (!minted.has(to)) continue;
90174
+ const id = `edge_${digest({ from: d.ref, type: "DEPENDS_ON", to })}`.slice(0, 24);
90175
+ const live3 = store.getEdge(id);
90176
+ if (live3 && (live3.validTo ?? null) === null) {
90177
+ edges++;
90178
+ continue;
90179
+ }
89760
90180
  store.mergeEdge({
89761
- id: `edge_${digest({ from: d.ref, type: "DEPENDS_ON", to })}`.slice(0, 24),
90181
+ id,
89762
90182
  from: d.ref,
89763
90183
  to,
89764
90184
  type: "DEPENDS_ON",
@@ -89780,9 +90200,7 @@ function mintLanguageNodes(store, languages, workspaceId2, ts) {
89780
90200
  for (const raw2 of languages) {
89781
90201
  const name2 = raw2.trim();
89782
90202
  if (!name2) continue;
89783
- store.mergeNode(
89784
- buildContextNode(`lang:${name2.toLowerCase()}`, "Language", name2, { name: name2, workspaceId: workspaceId2 }, ts)
89785
- );
90203
+ mintContextNode(store, buildContextNode(`lang:${name2.toLowerCase()}`, "Language", name2, { name: name2, workspaceId: workspaceId2 }, ts));
89786
90204
  n++;
89787
90205
  }
89788
90206
  return n;
@@ -89829,10 +90247,14 @@ function buildContextIngest(store, profile, daemonVersion, ignorePatterns = [],
89829
90247
  }
89830
90248
  }
89831
90249
  if (nodes.length === 0) return null;
90250
+ const contributed = (id) => {
90251
+ const n = store.getNode(id);
90252
+ return !!n && (n.label === "Package" || n.label === "Language") && n.attrs["source"] !== "cloud" && typeof n.attrs["contributedAtSeq"] === "number" && !ignored(n.description) && !ignored(String(n.attrs["name"] ?? ""));
90253
+ };
89832
90254
  const edges = [];
89833
90255
  for (const id of seen) {
89834
90256
  for (const e of store.outEdges(id, ["DEPENDS_ON"])) {
89835
- if (seen.has(e.to)) edges.push({ ...e, attrs: {} });
90257
+ if (seen.has(e.to) || contributed(e.to)) edges.push({ ...e, attrs: {} });
89836
90258
  }
89837
90259
  }
89838
90260
  const base = {
@@ -89858,11 +90280,11 @@ function runLockfilePass(opts) {
89858
90280
  { file: "package-lock.json", parse: parsePackageLockJson }
89859
90281
  ];
89860
90282
  for (const c of candidates) {
89861
- const p = join38(opts.root, c.file);
90283
+ const p = join39(opts.root, c.file);
89862
90284
  if (!existsSync30(p)) continue;
89863
90285
  let sbom;
89864
90286
  try {
89865
- sbom = c.parse(readFileSync34(p, "utf8"));
90287
+ sbom = c.parse(readFileSync35(p, "utf8"));
89866
90288
  } catch {
89867
90289
  continue;
89868
90290
  }
@@ -89923,8 +90345,8 @@ init_profile2();
89923
90345
  init_session_registry();
89924
90346
 
89925
90347
  // src/public-symbols.ts
89926
- import { readFileSync as readFileSync35, readdirSync as readdirSync12, existsSync as existsSync31 } from "node:fs";
89927
- import { join as join39 } from "node:path";
90348
+ import { readFileSync as readFileSync36, readdirSync as readdirSync12, existsSync as existsSync31 } from "node:fs";
90349
+ import { join as join40 } from "node:path";
89928
90350
  var HEAD_BYTES = 8 * 1024;
89929
90351
  var INDEX_TTL_MS = 10 * 60 * 1e3;
89930
90352
  var MIN_SYMBOL_LEN = 4;
@@ -89957,20 +90379,20 @@ function bindingNames(clause) {
89957
90379
  function internalPackageNames(workspaceRoot) {
89958
90380
  const names = /* @__PURE__ */ new Set();
89959
90381
  const tryRead = (dir) => {
89960
- const pj = join39(dir, "package.json");
90382
+ const pj = join40(dir, "package.json");
89961
90383
  if (!existsSync31(pj)) return;
89962
90384
  try {
89963
- const name2 = JSON.parse(readFileSync35(pj, "utf8")).name;
90385
+ const name2 = JSON.parse(readFileSync36(pj, "utf8")).name;
89964
90386
  if (typeof name2 === "string" && name2.length > 0) names.add(name2);
89965
90387
  } catch {
89966
90388
  }
89967
90389
  };
89968
90390
  tryRead(workspaceRoot);
89969
90391
  for (const group of ["packages", "apps"]) {
89970
- const groupDir = join39(workspaceRoot, group);
90392
+ const groupDir = join40(workspaceRoot, group);
89971
90393
  if (!existsSync31(groupDir)) continue;
89972
90394
  try {
89973
- for (const entry of readdirSync12(groupDir)) tryRead(join39(groupDir, entry));
90395
+ for (const entry of readdirSync12(groupDir)) tryRead(join40(groupDir, entry));
89974
90396
  } catch {
89975
90397
  }
89976
90398
  }
@@ -89989,7 +90411,7 @@ function publicSymbolIndex(store, workspaceRoot, deps = {}) {
89989
90411
  }
89990
90412
  const readHead = deps.readHead ?? ((absPath) => {
89991
90413
  try {
89992
- return readFileSync35(absPath, "utf8").slice(0, HEAD_BYTES);
90414
+ return readFileSync36(absPath, "utf8").slice(0, HEAD_BYTES);
89993
90415
  } catch {
89994
90416
  return "";
89995
90417
  }
@@ -90009,7 +90431,7 @@ function publicSymbolIndex(store, workspaceRoot, deps = {}) {
90009
90431
  }
90010
90432
  const symbols = /* @__PURE__ */ new Set();
90011
90433
  for (const rel of files) {
90012
- const head2 = readHead(join39(workspaceRoot, rel));
90434
+ const head2 = readHead(join40(workspaceRoot, rel));
90013
90435
  if (!head2) continue;
90014
90436
  for (const re of [NAMED_IMPORT_RE, REQUIRE_RE]) {
90015
90437
  re.lastIndex = 0;
@@ -90994,7 +91416,7 @@ init_config();
90994
91416
 
90995
91417
  // src/update.ts
90996
91418
  import { spawn as spawn2 } from "node:child_process";
90997
- import { isAbsolute as isAbsolute6, join as join40 } from "node:path";
91419
+ import { isAbsolute as isAbsolute5, join as join41 } from "node:path";
90998
91420
  var PACKAGE_NAME = "@inerrata-corporation/errata";
90999
91421
  function parse3(v) {
91000
91422
  const m = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z][0-9A-Za-z.-]*))?/.exec(v.trim());
@@ -91139,9 +91561,9 @@ async function runInstalledHookRefresh() {
91139
91561
  child.on("error", () => resolve10(""));
91140
91562
  child.on("close", (code) => resolve10(code === 0 ? output.trim() : ""));
91141
91563
  });
91142
- if (!isAbsolute6(root)) return 1;
91564
+ if (!isAbsolute5(root)) return 1;
91143
91565
  return new Promise((resolve10) => {
91144
- const child = spawn2(process.execPath, [join40(root, PACKAGE_NAME, "errata.mjs"), "install-hooks", "codex", "--refresh-existing"], {
91566
+ const child = spawn2(process.execPath, [join41(root, PACKAGE_NAME, "errata.mjs"), "install-hooks", "codex", "--refresh-existing"], {
91145
91567
  windowsHide: true,
91146
91568
  stdio: "inherit",
91147
91569
  timeout: 3e4
@@ -91287,12 +91709,12 @@ function landCloudEdge(store, e, from, to) {
91287
91709
  }
91288
91710
 
91289
91711
  // src/causal-edge-queue.ts
91290
- import { readFileSync as readFileSync36, renameSync as renameSync6, writeFileSync as writeFileSync26 } from "node:fs";
91291
- import { dirname as dirname14, join as join41 } from "node:path";
91712
+ import { readFileSync as readFileSync37, renameSync as renameSync7, writeFileSync as writeFileSync27 } from "node:fs";
91713
+ import { dirname as dirname15, join as join42 } from "node:path";
91292
91714
  var CAUSAL_EDGE_QUEUE_CAP = 5e3;
91293
91715
  var CAUSAL_EDGE_TTL_MS = 30 * 24 * 60 * 60 * 1e3;
91294
91716
  function causalEdgeQueuePath(workspaceConfigDir) {
91295
- return join41(workspaceConfigDir, "causal-edge-queue.json");
91717
+ return join42(workspaceConfigDir, "causal-edge-queue.json");
91296
91718
  }
91297
91719
  function parkedEdgeKey(e) {
91298
91720
  return `${e.from}|${e.type}|${e.to}`;
@@ -91300,7 +91722,7 @@ function parkedEdgeKey(e) {
91300
91722
  function loadCausalEdgeQueue(path3) {
91301
91723
  let raw2;
91302
91724
  try {
91303
- raw2 = JSON.parse(readFileSync36(path3, "utf8"));
91725
+ raw2 = JSON.parse(readFileSync37(path3, "utf8"));
91304
91726
  } catch {
91305
91727
  return [];
91306
91728
  }
@@ -91311,9 +91733,9 @@ function loadCausalEdgeQueue(path3) {
91311
91733
  }
91312
91734
  function saveCausalEdgeQueue(path3, queue) {
91313
91735
  try {
91314
- const tmp = join41(dirname14(path3), `.${Date.now()}.causal-edge-queue.tmp`);
91315
- writeFileSync26(tmp, JSON.stringify(queue), "utf8");
91316
- renameSync6(tmp, path3);
91736
+ const tmp = join42(dirname15(path3), `.${Date.now()}.causal-edge-queue.tmp`);
91737
+ writeFileSync27(tmp, JSON.stringify(queue), "utf8");
91738
+ renameSync7(tmp, path3);
91317
91739
  } catch {
91318
91740
  }
91319
91741
  }
@@ -91449,6 +91871,10 @@ async function lookupLive(store, m, id) {
91449
91871
  const second = (await m.refresh()).get(id);
91450
91872
  return second && isLive(store, second) ? second : null;
91451
91873
  }
91874
+ function reverseSymbolResolver(opts) {
91875
+ const m = cachedMap(reverseCache, opts.store, `${opts.projectId}|${opts.salt}`, () => buildReverseSymbolMap(opts));
91876
+ return (symbolId) => lookupLive(opts.store, m, symbolId);
91877
+ }
91452
91878
  function isLive(store, id) {
91453
91879
  const n = store.getNode(id);
91454
91880
  return n !== null && (n.validTo === null || n.validTo === void 0);
@@ -91739,7 +92165,9 @@ init_src11();
91739
92165
  init_src();
91740
92166
  import { execFile as execFile5 } from "node:child_process";
91741
92167
  import { promisify as promisify4 } from "node:util";
91742
- import { extname as extname3 } from "node:path";
92168
+ import { extname as extname3, join as join43 } from "node:path";
92169
+ import { createHash as createHash19 } from "node:crypto";
92170
+ import { readFileSync as readFileSync38 } from "node:fs";
91743
92171
 
91744
92172
  // src/history-dependency-snapshot.ts
91745
92173
  init_src();
@@ -91750,22 +92178,20 @@ async function readHistoryDependencySnapshot(opts) {
91750
92178
  const git3 = opts.git ?? (async (args2) => (await exec("git", ["-C", opts.root, ...args2], { windowsHide: true, maxBuffer: 16 * 1024 * 1024 })).stdout);
91751
92179
  const read2 = opts.readBlob ?? (async (oid) => git3(["show", oid]));
91752
92180
  let complete = true;
91753
- const tree = await git3(["ls-tree", "-r", opts.commit]).catch(() => null);
92181
+ const tree = await git3(["ls-tree", "-r", "-z", opts.commit]).catch(() => null);
91754
92182
  if (tree === null) return { schemaVersion: "history-deps-1", complete: false, dependencies: [] };
91755
- const entries = tree.split("\n").flatMap((line) => {
91756
- const match2 = /^\d+ blob ([a-f0-9]+)\t(.+)$/.exec(line);
91757
- if (!match2) return [];
91758
- const path3 = match2[2].replace(/^"|"$/g, "");
91759
- if (path3.includes("\\") || /[\r\n]/.test(path3)) {
91760
- complete = false;
91761
- return [];
91762
- }
91763
- return [{ path: path3, oid: match2[1] }];
92183
+ const entries = tree.split("\0").flatMap((row) => {
92184
+ const match2 = /^\d+ blob ([a-f0-9]+)\t([^]+)$/.exec(row);
92185
+ return match2 ? [{ path: match2[2], oid: match2[1] }] : [];
91764
92186
  });
91765
92187
  const manifests = {}, locks = {};
91766
92188
  for (const { path: path3, oid } of entries) {
91767
- const lock = /(?:^|\/)(?:pnpm-lock.yaml|package-lock.json)$/.test(path3);
92189
+ const lock = /(?:^|\/)(?:pnpm-lock\.yaml|package-lock\.json)$/.test(path3);
91768
92190
  if (!lock && (!isManifestPath(path3) || opts.manifestIds && !opts.manifestIds.has(historyManifestId(path3)))) continue;
92191
+ if (path3.includes("\\") || /[\r\n]/.test(path3)) {
92192
+ complete = false;
92193
+ continue;
92194
+ }
91769
92195
  if (opts.paths && !Object.values(opts.paths).some((p) => !path3.includes("/") || p.startsWith(path3.slice(0, path3.lastIndexOf("/") + 1)))) continue;
91770
92196
  if (opts.allowPath && !opts.allowPath(path3)) {
91771
92197
  complete = false;
@@ -91848,6 +92274,46 @@ init_profile2();
91848
92274
  var exec2 = promisify4(execFile5);
91849
92275
  var KINDS = { function: "Function", class: "Class", method: "Method", interface: "Interface", const: "Const", enum: "Enum", typealias: "TypeAlias", namespace: "Namespace", property: "Property" };
91850
92276
  var inFlight = /* @__PURE__ */ new Map();
92277
+ var carryRefused = /* @__PURE__ */ new Set();
92278
+ var carryFailures = /* @__PURE__ */ new Map();
92279
+ var CARRY_ATTEMPTS = 3;
92280
+ var Bounded = class extends Map {
92281
+ constructor(cap) {
92282
+ super();
92283
+ this.cap = cap;
92284
+ }
92285
+ set(key, value) {
92286
+ if (!this.has(key) && this.size >= this.cap) this.delete(this.keys().next().value);
92287
+ return super.set(key, value);
92288
+ }
92289
+ };
92290
+ var DEFAULT_GIT = {};
92291
+ function readFileSafe(path3) {
92292
+ try {
92293
+ return readFileSync38(path3, "utf8");
92294
+ } catch {
92295
+ return "";
92296
+ }
92297
+ }
92298
+ var revisionCaches = /* @__PURE__ */ new WeakMap();
92299
+ function cachesFor(git3) {
92300
+ let caches = revisionCaches.get(git3);
92301
+ if (!caches) {
92302
+ caches = {
92303
+ parents: new Bounded(4),
92304
+ dependencies: new Bounded(8),
92305
+ trees: new Bounded(4),
92306
+ symbols: new Bounded(4e3),
92307
+ diffs: new Bounded(2e3),
92308
+ listings: new Bounded(4),
92309
+ blobs: new Bounded(256)
92310
+ };
92311
+ revisionCaches.set(git3, caches);
92312
+ }
92313
+ return caches;
92314
+ }
92315
+ var REVISION_DIFF_TOKENS = 4e3;
92316
+ var REVISION_RAW_DIFF_CHARS = REVISION_DIFF_TOKENS * 4 * 4;
91851
92317
  async function syncHistoryRevision(opts) {
91852
92318
  const current = inFlight.get(opts.root);
91853
92319
  if (current) return current;
@@ -91855,12 +92321,13 @@ async function syncHistoryRevision(opts) {
91855
92321
  const started2 = Date.now();
91856
92322
  let changed = 0, remaining = false;
91857
92323
  const pages = Math.min(20, Math.max(1, opts.maxPages ?? 10));
92324
+ const resolve10 = opts.profile.projectId ? reverseSymbolResolver({ store: opts.store, salt: opts.salt, projectId: opts.profile.projectId }) : async () => null;
91858
92325
  for (let i2 = 0; i2 < pages; i2++) {
91859
- const result = await syncHistoryRevisionPage(opts);
92326
+ const result = await syncHistoryRevisionPage(opts, resolve10);
91860
92327
  changed += result.changed;
91861
92328
  remaining = result.remaining;
91862
- if (!remaining || Date.now() - started2 >= (opts.budgetMs ?? 45e3)) break;
91863
- await new Promise((resolve10) => setImmediate(resolve10));
92329
+ if (!remaining || result.nextBeat || Date.now() - started2 >= (opts.budgetMs ?? 45e3)) break;
92330
+ await new Promise((resolve11) => setImmediate(resolve11));
91864
92331
  }
91865
92332
  return { changed, remaining };
91866
92333
  })();
@@ -91871,78 +92338,169 @@ async function syncHistoryRevision(opts) {
91871
92338
  if (inFlight.get(opts.root) === work) inFlight.delete(opts.root);
91872
92339
  }
91873
92340
  }
91874
- async function syncHistoryRevisionPage(opts) {
92341
+ async function syncHistoryRevisionPage(opts, resolve10) {
91875
92342
  const { root, profile, store, cloud, salt } = opts;
91876
92343
  if (!profile.projectId) return { changed: 0, remaining: false };
91877
92344
  const projectId = profile.projectId;
91878
92345
  const git3 = opts.git ?? (async (args2) => (await exec2("git", ["-C", root, ...args2], { windowsHide: true, maxBuffer: 8 * 1024 * 1024 })).stdout);
92346
+ const caches = cachesFor(opts.git ?? DEFAULT_GIT);
92347
+ const ignoreKey = createHash19("sha256").update(JSON.stringify(profile.ignoreExtra ?? [])).update(readFileSafe(join43(root, ".errataignore"))).digest("hex").slice(0, 16);
91879
92348
  const atCommit = (await git3(["rev-parse", "--verify", "HEAD"])).trim();
91880
92349
  if (!/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(atCommit)) throw new Error("history revision is not a full Git object id");
91881
92350
  const oldCursor = profile.historyRevisionCursor;
91882
- const same = oldCursor?.atCommit === atCommit;
91883
- if (same && oldCursor.complete && Date.now() - oldCursor.updatedAt < 60 * 6e4) return { changed: 0, remaining: false };
91884
- const after = oldCursor && !oldCursor.complete ? oldCursor.after : void 0;
91885
- const sweepCommit = after ? oldCursor.atCommit : atCommit;
91886
- const page = await cloud.getHistoryOccurrences(projectId, atCommit, after);
92351
+ const save = () => (opts.save ?? ((p) => saveProfile(root, p)))(profile);
92352
+ if (oldCursor && oldCursor.ignoreKey !== ignoreKey && oldCursor.reprove !== ignoreKey) {
92353
+ profile.historyRevisionCursor = { ...oldCursor, atCommit, complete: false, after: void 0, reprove: ignoreKey, updatedAt: Date.now() };
92354
+ delete profile.historyRevisionCursor.after;
92355
+ save();
92356
+ }
92357
+ const cursor = profile.historyRevisionCursor;
92358
+ const head2 = cursor?.head ?? cursor?.atCommit;
92359
+ if (cursor && head2 && head2 !== atCommit && cloud.carryHistory && !carryRefused.has(root)) {
92360
+ const range = `${root}|${head2}|${atCommit}`;
92361
+ try {
92362
+ const carry = await carryRequest({
92363
+ git: git3,
92364
+ caches,
92365
+ root,
92366
+ salt,
92367
+ projectId,
92368
+ providers: defaultProviders(),
92369
+ from: head2,
92370
+ at: atCommit,
92371
+ rulesChanged: cursor.ignoreKey !== ignoreKey
92372
+ });
92373
+ await cloud.carryHistory(projectId, carry);
92374
+ carryFailures.delete(range);
92375
+ } catch (err2) {
92376
+ if (err2.status === 404) {
92377
+ carryRefused.add(root);
92378
+ console.warn(`[errata] the cloud predates history carry; every new commit re-proves all history verdicts for ${profile.name}`);
92379
+ } else {
92380
+ const failures = (carryFailures.get(range) ?? 0) + 1;
92381
+ carryFailures.set(range, failures);
92382
+ console.warn(`[errata] history carry ${head2.slice(0, 12)}..${atCommit.slice(0, 12)} failed (${failures}/${CARRY_ATTEMPTS})${failures >= CARRY_ATTEMPTS ? "; re-proving this commit instead" : ""}: ${err2 instanceof Error ? err2.message : String(err2)}`);
92383
+ if (failures < CARRY_ATTEMPTS) return { changed: 0, remaining: true, nextBeat: true };
92384
+ carryFailures.delete(range);
92385
+ }
92386
+ }
92387
+ profile.historyRevisionCursor = { ...cursor, head: atCommit };
92388
+ save();
92389
+ }
92390
+ const current = profile.historyRevisionCursor;
92391
+ const reproving = current?.reprove === ignoreKey;
92392
+ const same = current?.atCommit === atCommit;
92393
+ if (same && current.complete && Date.now() - current.updatedAt < 60 * 6e4) return { changed: 0, remaining: false };
92394
+ const after = current && !current.complete ? current.after : void 0;
92395
+ const sweepCommit = after ? current.atCommit : atCommit;
92396
+ const page = await cloud.getHistoryOccurrences(projectId, atCommit, after, { pendingOnly: !reproving });
91887
92397
  if (!Array.isArray(page.occurrences) || page.occurrences.length > 50 || page.occurrences.some((o, i2) => o.occurrenceId <= (page.occurrences[i2 - 1]?.occurrenceId ?? after ?? "")) || page.cursor !== null && page.cursor !== page.occurrences.at(-1)?.occurrenceId) throw new Error("invalid history occurrence page");
91888
- const parents = page.occurrences.length ? (await git3(["rev-list", "--parents", "--max-count=8192", atCommit])).trim().split("\n").filter(Boolean).map((row) => {
91889
- const [commit, ...parents2] = row.trim().split(/\s+/);
91890
- return { commit, parents: parents2 };
91891
- }) : [];
91892
- const reverse = page.occurrences.length ? await buildReverseSymbolMap({ store, projectId, salt }) : /* @__PURE__ */ new Map();
92398
+ const toPost = page.occurrences.filter((o) => !settledHistoryReceipt(o.quality["reconciliationEvidence"]) || reproving && o.quality["historicalAnchors"]?.length);
92399
+ let parents = [];
92400
+ if (toPost.length) {
92401
+ const key = `${root}|${atCommit}`;
92402
+ parents = caches.parents.get(key) ?? (await git3(["rev-list", "--parents", "--max-count=8192", atCommit])).trim().split("\n").filter(Boolean).map((row) => {
92403
+ const [commit, ...parents2] = row.trim().split(/\s+/);
92404
+ return { commit, parents: parents2 };
92405
+ });
92406
+ caches.parents.set(key, parents);
92407
+ }
91893
92408
  const ignore2 = loadRepoIgnore(root, profile.ignoreExtra ?? []);
91894
92409
  const providers = defaultProviders();
91895
- const parsedFiles = /* @__PURE__ */ new Map();
91896
92410
  const observations = [];
91897
- const contexts = page.occurrences.map((o) => HistoryDependencyContextSchema.safeParse(o.quality["dependencyContext"]));
92411
+ const contexts = toPost.map((o) => HistoryDependencyContextSchema.safeParse(o.quality["dependencyContext"]));
91898
92412
  const manifestIds = new Set(contexts.flatMap((c) => c.success ? c.data.dependencies.map((d) => d.manifestId) : []));
91899
- const currentDependencies = manifestIds.size ? await readHistoryDependencySnapshot({
91900
- root,
91901
- commit: atCommit,
91902
- side: "after",
91903
- manifestIds,
91904
- git: git3,
91905
- allowPath: (p) => pathAllowedByFloor(p) && !isPathBlocked(ignore2, p)
91906
- }) : void 0;
91907
- for (const occurrence of page.occurrences) {
92413
+ let currentDependencies;
92414
+ if (manifestIds.size) {
92415
+ const key = `${root}|${atCommit}|${ignoreKey}|${[...manifestIds].sort().join(",")}`;
92416
+ let snapshot = caches.dependencies.get(key);
92417
+ if (!snapshot) {
92418
+ const listed = (args2) => {
92419
+ if (args2[0] !== "ls-tree") return git3(args2);
92420
+ const k = `${root}|${args2.join(" ")}`;
92421
+ let out2 = caches.listings.get(k);
92422
+ if (!out2) {
92423
+ out2 = git3(args2);
92424
+ caches.listings.set(k, out2);
92425
+ out2.catch(() => caches.listings.delete(k));
92426
+ }
92427
+ return out2;
92428
+ };
92429
+ const blob = (oid) => {
92430
+ const k = `${root}|${oid}`;
92431
+ let out2 = caches.blobs.get(k);
92432
+ if (!out2) {
92433
+ out2 = git3(["show", oid]);
92434
+ caches.blobs.set(k, out2);
92435
+ out2.catch(() => caches.blobs.delete(k));
92436
+ }
92437
+ return out2;
92438
+ };
92439
+ snapshot = readHistoryDependencySnapshot({
92440
+ root,
92441
+ commit: atCommit,
92442
+ side: "after",
92443
+ manifestIds,
92444
+ git: listed,
92445
+ readBlob: blob,
92446
+ allowPath: (p) => pathAllowedByFloor(p) && !isPathBlocked(ignore2, p)
92447
+ });
92448
+ caches.dependencies.set(key, snapshot);
92449
+ snapshot.catch(() => caches.dependencies.delete(key));
92450
+ }
92451
+ currentDependencies = await snapshot;
92452
+ }
92453
+ const treeKey = `${root}|${atCommit}`;
92454
+ let tree = caches.trees.get(treeKey);
92455
+ if (!tree && toPost.length) {
92456
+ tree = git3(["ls-tree", "-r", "-z", "--full-tree", atCommit]).then((out2) => new Map(out2.split("\0").flatMap((row) => {
92457
+ const tab = row.indexOf(" "), [, type, blob] = row.slice(0, tab).split(" ");
92458
+ return tab > 0 && type === "blob" && blob ? [[row.slice(tab + 1), blob]] : [];
92459
+ })));
92460
+ caches.trees.set(treeKey, tree);
92461
+ tree.catch(() => caches.trees.delete(treeKey));
92462
+ }
92463
+ const blobs = await (tree ?? Promise.resolve(/* @__PURE__ */ new Map())).catch(() => /* @__PURE__ */ new Map());
92464
+ const fileId = (path3) => blobs.get(path3) ?? `commit:${atCommit}`;
92465
+ for (const occurrence of toPost) {
91908
92466
  const anchors = occurrence.quality["historicalAnchors"];
91909
92467
  const paths = /* @__PURE__ */ new Set(), symbols = [];
92468
+ let partial2 = false;
91910
92469
  for (const anchor of anchors ?? []) {
91911
- const localId = reverse.get(anchor.symbolId), local = localId ? store.getNode(localId) : null;
92470
+ const localId = await resolve10(anchor.symbolId), local = localId ? store.getNode(localId) : null;
91912
92471
  const path3 = local?.attrs["relPath"];
91913
92472
  if (typeof path3 !== "string" || !pathAllowedByFloor(path3) || isPathBlocked(ignore2, path3) || /[\r\n]/.test(path3)) continue;
91914
92473
  paths.add(path3);
91915
- if (!parsedFiles.has(path3)) {
91916
- const hashes = /* @__PURE__ */ new Map();
91917
- parsedFiles.set(path3, hashes);
91918
- const provider = providers.find((p) => p.fileExtensions.includes(extname3(path3).toLowerCase()));
91919
- if (!provider) continue;
91920
- const source2 = await git3(["show", `${atCommit}:${path3}`]).catch(() => null);
91921
- if (source2 === null || Buffer.byteLength(source2) > 1e6 || source2.includes("\0")) continue;
91922
- await provider.preload?.();
91923
- for (const symbol2 of provider.extractSymbols(source2, path3)) {
91924
- const kind = KINDS[symbol2.kind];
91925
- if (kind && symbol2.bodyHash) hashes.set(projectSymbolId(salt, projectId, path3, symbol2.qname ?? symbol2.name, kind), symbol2.bodyHash);
91926
- }
91927
- }
91928
- const bodyHash = parsedFiles.get(path3).get(anchor.symbolId);
92474
+ const hashes = await fileSymbols({ caches, providers, root, salt, projectId }, path3, fileId(path3), () => git3(["show", `${atCommit}:${path3}`]));
92475
+ if (!hashes) partial2 = true;
92476
+ const bodyHash = hashes?.get(anchor.symbolId);
91929
92477
  if (bodyHash) symbols.push({ symbolId: anchor.symbolId, bodyHash });
91930
92478
  }
91931
92479
  const source = occurrenceSourceCommit(occurrence);
91932
92480
  let diff;
91933
92481
  if (source && source !== atCommit && paths.size) {
91934
- const bundle = await buildUnitBundle(root, {
91935
- sha: atCommit,
91936
- parents: [source],
91937
- isMerge: true,
91938
- index: 0,
91939
- subIndex: 0,
91940
- subject: "",
91941
- body: "",
91942
- authorDate: "",
91943
- files: [...paths].map((path3) => ({ path: path3, adds: 1, dels: 1, binary: false }))
91944
- }, { maxTokens: 4e3, ignorePatterns: profile.ignoreExtra ?? [] }).catch(() => null);
91945
- if (bundle && !bundle.truncated) diff = bundle.diff;
92482
+ const diffKey = `${root}|${ignoreKey}|${source}|${[...paths].sort().map((path3) => `${path3}\0${fileId(path3)}`).join("\0")}`;
92483
+ if (caches.diffs.has(diffKey)) diff = caches.diffs.get(diffKey);
92484
+ else {
92485
+ const bundle = await buildUnitBundle(
92486
+ root,
92487
+ {
92488
+ sha: atCommit,
92489
+ parents: [source],
92490
+ isMerge: true,
92491
+ index: 0,
92492
+ subIndex: 0,
92493
+ subject: "",
92494
+ body: "",
92495
+ authorDate: "",
92496
+ files: [...paths].map((path3) => ({ path: path3, adds: 1, dels: 1, binary: false }))
92497
+ },
92498
+ { maxTokens: REVISION_DIFF_TOKENS, maxRawDiffChars: REVISION_RAW_DIFF_CHARS, ignorePatterns: profile.ignoreExtra ?? [] }
92499
+ ).catch(() => null);
92500
+ if (bundle && !bundle.truncated) diff = bundle.diff;
92501
+ if (bundle) caches.diffs.set(diffKey, diff);
92502
+ else partial2 = true;
92503
+ }
91946
92504
  }
91947
92505
  const old = HistoryDependencyContextSchema.safeParse(occurrence.quality["dependencyContext"]);
91948
92506
  const dependencyContext = old.success ? {
@@ -91950,16 +92508,24 @@ async function syncHistoryRevisionPage(opts) {
91950
92508
  complete: old.data.dependencies.length === 0 || currentDependencies?.complete === true,
91951
92509
  dependencies: currentDependencies?.dependencies.filter((d) => old.data.dependencies.some((o) => o.packageId === d.packageId && o.manifestId === d.manifestId)) ?? []
91952
92510
  } : void 0;
92511
+ if (partial2) continue;
91953
92512
  observations.push({ occurrenceId: occurrence.occurrenceId, symbols, ...diff ? { diff } : {}, ...dependencyContext ? { dependencyContext } : {} });
91954
92513
  }
91955
- const response = page.occurrences.length ? await cloud.reconcileHistory(projectId, { atCommit, parents, observations }) : { atCommit, receipts: [] };
91956
- if (response.atCommit !== atCommit || response.receipts.length !== page.occurrences.length || new Set(response.receipts.map((r) => r.occurrenceId)).size !== response.receipts.length || response.receipts.some((r) => r.atCommit !== atCommit || !observations.some((o) => o.occurrenceId === r.occurrenceId))) throw new Error("incomplete history reconciliation response");
92514
+ const response = observations.length ? await cloud.reconcileHistory(projectId, { atCommit, parents, observations }) : { atCommit, receipts: [] };
92515
+ if (response.atCommit !== atCommit || response.receipts.length !== observations.length || new Set(response.receipts.map((r) => r.occurrenceId)).size !== response.receipts.length || response.receipts.some((r) => r.atCommit !== atCommit || !observations.some((o) => o.occurrenceId === r.occurrenceId))) throw new Error("incomplete history reconciliation response");
92516
+ const receipts = new Map(response.receipts.map((r) => [r.occurrenceId, r]));
92517
+ for (const o of page.occurrences) {
92518
+ if (!receipts.has(o.occurrenceId) && settledHistoryReceipt(o.quality["reconciliationEvidence"])) {
92519
+ receipts.set(o.occurrenceId, { verdict: o.quality["applicability"], evidence: o.quality["reconciliationEvidence"] });
92520
+ }
92521
+ }
91957
92522
  const headChanged = (await git3(["rev-parse", "--verify", "HEAD"])).trim() !== atCommit;
91958
92523
  let changed = 0;
91959
92524
  for (const occurrence of page.occurrences) {
91960
- const node2 = store.getNode(occurrence.canonicalId) ?? (occurrence.nodeId ? store.getNode(occurrence.nodeId) : null);
92525
+ const node2 = historyNode(store, occurrence);
91961
92526
  if (!node2 || node2.attrs["source"] !== "cloud" || node2.attrs["historyQuality"]?.["sourceSupport"] === "quarantined") continue;
91962
- const receipt = response.receipts.find((r) => r.occurrenceId === occurrence.occurrenceId);
92527
+ const receipt = receipts.get(occurrence.occurrenceId);
92528
+ if (!receipt || unchangedRecord(node2, occurrence, receipt, atCommit)) continue;
91963
92529
  const previous = node2.attrs["historyQuality"];
91964
92530
  if (previous?.["evaluatedAtCommit"] === atCommit && previous["applicability"] === "applicable" && receipt.verdict !== "applicable" && previous["sourceReviewId"] === occurrence.quality["sourceReviewId"] && previous["dependencyReviewId"] === occurrence.quality["dependencyReviewId"] && historyDependencyIdentity(previous["dependencyContext"]) !== null && historyDependencyIdentity(previous["dependencyContext"]) === historyDependencyIdentity(occurrence.quality["dependencyContext"]) && previous["reconciliationEvidence"]?.["build"] === HISTORY_RECONCILE_BUILD) continue;
91965
92531
  const dependencies = HistoryDependencyContextSchema.safeParse(occurrence.quality["dependencyContext"]);
@@ -91975,17 +92541,115 @@ async function syncHistoryRevisionPage(opts) {
91975
92541
  } });
91976
92542
  changed++;
91977
92543
  }
91978
- profile.historyRevisionCursor = { atCommit: sweepCommit, ...page.cursor ? { after: page.cursor } : {}, complete: page.cursor === null, updatedAt: Date.now() };
91979
- (opts.save ?? ((p) => saveProfile(root, p)))(profile);
92544
+ const complete = page.cursor === null;
92545
+ const proven = reproving && complete && sweepCommit === atCommit;
92546
+ const provenKey = proven || !current ? ignoreKey : current.ignoreKey;
92547
+ profile.historyRevisionCursor = {
92548
+ atCommit: sweepCommit,
92549
+ ...page.cursor ? { after: page.cursor } : {},
92550
+ complete,
92551
+ updatedAt: Date.now(),
92552
+ head: atCommit,
92553
+ ...provenKey !== void 0 ? { ignoreKey: provenKey } : {},
92554
+ ...reproving && !proven ? { reprove: ignoreKey } : {}
92555
+ };
92556
+ save();
91980
92557
  return { changed, remaining: page.cursor !== null || headChanged || sweepCommit !== atCommit };
91981
92558
  }
92559
+ function historyNode(store, occurrence) {
92560
+ return store.getNode(occurrence.canonicalId) ?? (occurrence.nodeId ? store.getNode(occurrence.nodeId) : null);
92561
+ }
92562
+ function unchangedRecord(node2, occurrence, receipt, atCommit) {
92563
+ const previous = node2.attrs["historyQuality"];
92564
+ if (!previous) return false;
92565
+ const stamp = receipt.verdict === "unknown" && previous["applicability"] === "unknown" ? previous["evaluatedAtCommit"] : atCommit;
92566
+ const dependencies = HistoryDependencyContextSchema.safeParse(occurrence.quality["dependencyContext"]);
92567
+ const next = compactHistoryQuality({
92568
+ ...occurrence.quality,
92569
+ evaluatedAtCommit: stamp,
92570
+ applicability: receipt.verdict,
92571
+ reconciliationEvidence: receipt.evidence
92572
+ });
92573
+ return digest(JSON.parse(JSON.stringify(next))) === digest(previous) && digest(dependencies.success ? historyDependencyVersions(dependencies.data) : null) === digest(node2.attrs["depVersions"] ?? null);
92574
+ }
92575
+ async function fileSymbols(ctx, path3, fileId, read2) {
92576
+ const fileKey = `${ctx.root}|${ctx.salt}|${ctx.projectId}|${fileId}|${path3}`;
92577
+ const cached2 = ctx.caches.symbols.get(fileKey);
92578
+ if (cached2) return cached2;
92579
+ const hashes = /* @__PURE__ */ new Map();
92580
+ const provider = ctx.providers.find((p) => p.fileExtensions.includes(extname3(path3).toLowerCase()));
92581
+ if (!provider) {
92582
+ ctx.caches.symbols.set(fileKey, hashes);
92583
+ return hashes;
92584
+ }
92585
+ const source = await read2().catch(() => null);
92586
+ if (source === null) return void 0;
92587
+ ctx.caches.symbols.set(fileKey, hashes);
92588
+ if (Buffer.byteLength(source) > 1e6 || source.includes("\0")) return hashes;
92589
+ await provider.preload?.();
92590
+ for (const symbol2 of provider.extractSymbols(source, path3)) {
92591
+ const kind = KINDS[symbol2.kind];
92592
+ if (kind && symbol2.bodyHash) hashes.set(projectSymbolId(ctx.salt, ctx.projectId, path3, symbol2.qname ?? symbol2.name, kind), symbol2.bodyHash);
92593
+ }
92594
+ return hashes;
92595
+ }
92596
+ var CARRY_MAX_CODE_FILES = 400;
92597
+ var CARRY_MAX_SYMBOLS = 5e3;
92598
+ var CARRY_MAX_MANIFESTS = 512;
92599
+ var CARRY_MAX_COMMITS = 8192;
92600
+ var LOCKFILE = /(?:^|\/)(?:pnpm-lock\.yaml|package-lock\.json)$/;
92601
+ var NO_BLOB = /^0+$/;
92602
+ async function carryRequest(o) {
92603
+ const { git: git3, from, at } = o;
92604
+ let parents = [];
92605
+ if (await git3(["merge-base", "--is-ancestor", from, at]).then(() => true, () => false)) {
92606
+ const rows = `${await git3(["rev-list", "--parents", "--ancestry-path", `--max-count=${CARRY_MAX_COMMITS}`, `${from}..${at}`])}
92607
+ ${await git3(["rev-list", "--parents", "-1", from])}`.split("\n").map((row) => row.trim()).filter(Boolean).map((row) => {
92608
+ const [commit, ...parents2] = row.split(/\s+/);
92609
+ return { commit, parents: parents2 };
92610
+ });
92611
+ if (rows.length <= CARRY_MAX_COMMITS) parents = rows;
92612
+ }
92613
+ const fields = (await git3(["diff", "--raw", "--no-renames", "--no-abbrev", "-z", from, at])).split("\0");
92614
+ const changes = [];
92615
+ for (let i2 = 0; i2 + 1 < fields.length; i2 += 2) {
92616
+ const meta3 = fields[i2].trim().split(/\s+/), path3 = fields[i2 + 1];
92617
+ if (meta3.length >= 4 && path3) changes.push({ path: path3, blobs: [meta3[2], meta3[3]].filter((b) => !NO_BLOB.test(b)) });
92618
+ }
92619
+ const manifests = /* @__PURE__ */ new Set(), symbols = /* @__PURE__ */ new Set();
92620
+ let allManifests = o.rulesChanged, allSymbols = o.rulesChanged;
92621
+ const code = changes.filter((c) => o.providers.some((p) => p.fileExtensions.includes(extname3(c.path).toLowerCase())));
92622
+ if (code.length > CARRY_MAX_CODE_FILES) allSymbols = true;
92623
+ for (const change of changes) {
92624
+ if (LOCKFILE.test(change.path)) allManifests = true;
92625
+ else if (isManifestPath(change.path)) manifests.add(historyManifestId(change.path));
92626
+ }
92627
+ for (const change of allSymbols ? [] : code) {
92628
+ for (const blob of change.blobs) {
92629
+ const hashes = await fileSymbols(o, change.path, blob, () => git3(["show", blob]));
92630
+ if (!hashes) {
92631
+ allSymbols = true;
92632
+ break;
92633
+ }
92634
+ for (const id of hashes.keys()) symbols.add(id);
92635
+ }
92636
+ if (allSymbols) break;
92637
+ }
92638
+ return {
92639
+ fromCommit: from,
92640
+ atCommit: at,
92641
+ parents,
92642
+ changedSymbols: allSymbols || symbols.size > CARRY_MAX_SYMBOLS ? null : [...symbols].sort(),
92643
+ changedManifests: allManifests || manifests.size > CARRY_MAX_MANIFESTS ? null : [...manifests].sort()
92644
+ };
92645
+ }
91982
92646
 
91983
92647
  // src/project-history.ts
91984
92648
  init_src7();
91985
92649
  init_src();
91986
92650
  import { execFile as execFile6 } from "node:child_process";
91987
- import { readFileSync as readFileSync37 } from "node:fs";
91988
- import { join as join42 } from "node:path";
92651
+ import { readFileSync as readFileSync39 } from "node:fs";
92652
+ import { join as join44 } from "node:path";
91989
92653
  import { promisify as promisify5 } from "node:util";
91990
92654
 
91991
92655
  // src/history-walk.ts
@@ -92537,7 +93201,7 @@ async function defaultGit(root, args2) {
92537
93201
  function readIgnoreLines(root, profile) {
92538
93202
  let lines = [];
92539
93203
  try {
92540
- lines = readFileSync37(join42(root, ".errataignore"), "utf8").split("\n");
93204
+ lines = readFileSync39(join44(root, ".errataignore"), "utf8").split("\n");
92541
93205
  } catch {
92542
93206
  }
92543
93207
  return [...lines, ...profile.ignoreExtra ?? []].map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
@@ -93111,10 +93775,10 @@ async function startHistoryStage(root, input, client, walk11 = {}) {
93111
93775
 
93112
93776
  // src/link-flow.ts
93113
93777
  init_cloud_auth();
93114
- import { createHash as createHash19 } from "node:crypto";
93778
+ import { createHash as createHash20 } from "node:crypto";
93115
93779
  import { execFileSync as execFileSync7 } from "node:child_process";
93116
- import { existsSync as existsSync32, writeFileSync as writeFileSync27 } from "node:fs";
93117
- import { join as join43 } from "node:path";
93780
+ import { existsSync as existsSync32, writeFileSync as writeFileSync28 } from "node:fs";
93781
+ import { join as join45 } from "node:path";
93118
93782
 
93119
93783
  // src/device-poll.ts
93120
93784
  var THROTTLED_POLL_MIN_WAIT_MS = 11e3;
@@ -93406,7 +94070,7 @@ async function loginOAuthLoopback(opts) {
93406
94070
 
93407
94071
  // src/link-flow.ts
93408
94072
  function remoteFingerprint(locator) {
93409
- return createHash19("sha256").update(locator).digest("hex");
94073
+ return createHash20("sha256").update(locator).digest("hex");
93410
94074
  }
93411
94075
  function isDecision(value) {
93412
94076
  if (!value || typeof value !== "object") return false;
@@ -93573,9 +94237,9 @@ function applyLinkDecision(root, profile, config2, decision, now = Date.now) {
93573
94237
  delete nextProfile.projectLinkHold;
93574
94238
  let wroteIgnore = false;
93575
94239
  if (decision.writeIgnoreStarter !== false) {
93576
- const target = join43(root, ".errataignore");
94240
+ const target = join45(root, ".errataignore");
93577
94241
  if (!existsSync32(target)) {
93578
- writeFileSync27(target, IGNORE_STARTER, "utf8");
94242
+ writeFileSync28(target, IGNORE_STARTER, "utf8");
93579
94243
  wroteIgnore = true;
93580
94244
  }
93581
94245
  }
@@ -93589,12 +94253,12 @@ init_registry();
93589
94253
  // src/adopt.ts
93590
94254
  init_git_remote();
93591
94255
  import { existsSync as existsSync33 } from "node:fs";
93592
- import { dirname as dirname15, join as join44 } from "node:path";
94256
+ import { dirname as dirname16, join as join46 } from "node:path";
93593
94257
  function findGitRoot(absPath) {
93594
94258
  let dir = absPath;
93595
94259
  for (let depth = 0; depth < 64; depth++) {
93596
- if (existsSync33(join44(dir, ".git"))) return dir;
93597
- const parent = dirname15(dir);
94260
+ if (existsSync33(join46(dir, ".git"))) return dir;
94261
+ const parent = dirname16(dir);
93598
94262
  if (parent === dir) return null;
93599
94263
  dir = parent;
93600
94264
  }
@@ -94068,7 +94732,6 @@ async function startMultiDaemon(opts = {}) {
94068
94732
  const boundaryListeners = [];
94069
94733
  let boundaryFlushing = false;
94070
94734
  let pushRequested = false;
94071
- let shippedFingerprint = "";
94072
94735
  let settleRunning = false;
94073
94736
  let boundaryFlushStartedAt = 0;
94074
94737
  let boundaryFlushStage = "";
@@ -94149,16 +94812,63 @@ async function startMultiDaemon(opts = {}) {
94149
94812
  });
94150
94813
  }
94151
94814
  };
94152
- const instanceFingerprint = () => {
94815
+ const SHIP_MARK_KEY = "watermark:instance-ship";
94816
+ const sendableSeq = (store) => store.changeSeq ? store.changeSeq() - store.changeSeq([EXPOSURE_SCOPE]) : null;
94817
+ const shipLanes = () => {
94153
94818
  const cfg2 = loadConfig();
94154
- const parts2 = [];
94819
+ const lanes = [], destinations = [], held = [];
94155
94820
  for (const r of records) {
94156
- if (!effectiveConsent(cfg2, r.engine.profile).sync) continue;
94157
- parts2.push(`${r.id}=${r.engine.store.labelFingerprint?.(INSTANCE_LABELS) ?? `?${Date.now()}`}`);
94821
+ const consent = effectiveConsent(cfg2, r.engine.profile);
94822
+ if (!consent.sync) continue;
94823
+ const identity = identityFor(liveWorkspaceEntry(r.entry));
94824
+ const destination = `${opts.cloudUrl ?? identity.profile?.cloudUrl ?? cfg2.cloudUrl ?? ""}|${identity.profileName ?? ""}`;
94825
+ destinations.push(destination);
94826
+ const quarantined = r.engine.quarantinedSessions().slice().sort();
94827
+ held.push(...quarantined);
94828
+ let ignoreFile = "";
94829
+ try {
94830
+ ignoreFile = readFileSync40(join47(r.root, ".errataignore"), "utf8");
94831
+ } catch {
94832
+ }
94833
+ const retryInputs = JSON.stringify([
94834
+ quarantined,
94835
+ DAEMON_VERSION,
94836
+ ignoreFile,
94837
+ r.engine.profile.ignoreExtra ?? [],
94838
+ r.engine.profile.projectHistoryCorrectionCursor ?? 0
94839
+ ]);
94840
+ const context = JSON.stringify([destination, consent.contributePackages ?? null, loadProfile(r.root)?.projectId ?? r.engine.profile.projectId ?? null]);
94841
+ const fp = r.engine.store.labelFingerprint?.(INSTANCE_LABELS);
94842
+ lanes.push({ store: r.engine.store, fp: fp === void 0 ? null : `${context}#${fp}`, seq: sendableSeq(r.engine.store), held: retryInputs });
94843
+ }
94844
+ if (lanes.length === 0) return lanes;
94845
+ const shared = sharedStore.labelFingerprint?.(["RootCause"]);
94846
+ const sharedContext = JSON.stringify([...new Set(destinations)].sort());
94847
+ lanes.push({ store: sharedStore, fp: shared === void 0 ? null : `${sharedContext}#${shared}`, seq: sendableSeq(sharedStore), held: JSON.stringify([[...new Set(held)].sort(), DAEMON_VERSION]) });
94848
+ return lanes;
94849
+ };
94850
+ const shipMark = (store) => {
94851
+ try {
94852
+ return JSON.parse(store.getMeta?.(SHIP_MARK_KEY) ?? "null");
94853
+ } catch {
94854
+ return null;
94158
94855
  }
94159
- if (parts2.length === 0) return "";
94160
- parts2.push(`shared=${sharedStore.labelFingerprint?.(["RootCause"]) ?? `?${Date.now()}`}`);
94161
- return parts2.join("|");
94856
+ };
94857
+ const unshipped = (lanes, retries) => lanes.filter((l) => {
94858
+ const mark = l.fp === null ? null : shipMark(l.store);
94859
+ if (!mark || mark.fp !== l.fp) return true;
94860
+ if (!retries) return false;
94861
+ return !mark.ok || l.seq === null || mark.seq !== l.seq || mark.held !== l.held || mark.retryAt !== void 0 && mark.retryAt <= Date.now();
94862
+ });
94863
+ const recordShipped = (lanes, result) => {
94864
+ const mark = (l) => ({
94865
+ fp: l.fp,
94866
+ ok: !result.errors?.length,
94867
+ ...result.retryAt !== void 0 ? { retryAt: result.retryAt } : {},
94868
+ ...l.seq !== null ? { seq: l.seq } : {},
94869
+ held: l.held
94870
+ });
94871
+ for (const l of lanes) if (l.fp !== null) l.store.setMeta?.(SHIP_MARK_KEY, JSON.stringify(mark(l)));
94162
94872
  };
94163
94873
  const runSettle = async () => {
94164
94874
  if (settleRunning) return;
@@ -94311,7 +95021,7 @@ async function startMultiDaemon(opts = {}) {
94311
95021
  records.push(rec);
94312
95022
  void ambientLinkAll();
94313
95023
  try {
94314
- writeFileSync28(
95024
+ writeFileSync29(
94315
95025
  rec.engine.paths.daemonLock,
94316
95026
  daemonLockPayload({
94317
95027
  pid: process.pid,
@@ -94380,11 +95090,19 @@ async function startMultiDaemon(opts = {}) {
94380
95090
  const strandedCount = (r) => {
94381
95091
  const hit = strandedCache.get(r.id);
94382
95092
  if (hit && Date.now() - hit.at < STRANDED_TTL_MS) return hit.count;
95093
+ const store = r.engine.store;
95094
+ const standing = standingStrandedCount(store);
95095
+ if (standing !== null) {
95096
+ strandedCache.set(r.id, { at: Date.now(), count: standing });
95097
+ return standing;
95098
+ }
94383
95099
  if (!strandedRefreshing.has(r.id)) {
94384
95100
  strandedRefreshing.add(r.id);
95101
+ const seq = store.changeSeq?.();
94385
95102
  const finish = (count) => {
94386
95103
  strandedCache.set(r.id, { at: Date.now(), count });
94387
95104
  strandedRefreshing.delete(r.id);
95105
+ recordStrandedCount(store, seq, count);
94388
95106
  };
94389
95107
  if (consolidateWorker && r.engine.paths.castalia !== ":memory:") {
94390
95108
  consolidateWorker.run({ kind: "strandedCount", sharedDbPath, castaliaPath: r.engine.paths.castalia }).then((n) => finish(Number(n))).catch(() => {
@@ -94596,10 +95314,13 @@ async function startMultiDaemon(opts = {}) {
94596
95314
  };
94597
95315
  app.all("/ws/:id", dispatchHot);
94598
95316
  app.all("/ws/:id/*", dispatchHot);
95317
+ const anchorPullInFlight = /* @__PURE__ */ new Map();
94599
95318
  const retireWorkspace = async (rec, reason) => {
94600
95319
  const idx = records.indexOf(rec);
94601
95320
  if (idx === -1) return;
94602
95321
  records.splice(idx, 1);
95322
+ await anchorPullInFlight.get(rec.root)?.catch(() => {
95323
+ });
94603
95324
  try {
94604
95325
  await rec.engine.stop();
94605
95326
  } catch (err2) {
@@ -94690,7 +95411,7 @@ async function startMultiDaemon(opts = {}) {
94690
95411
  baseUrl = `http://127.0.0.1:${port}`;
94691
95412
  try {
94692
95413
  ensureDir(globalDir());
94693
- writeFileSync28(
95414
+ writeFileSync29(
94694
95415
  lockPath,
94695
95416
  daemonLockPayload({ pid: process.pid, webUiUrl: baseUrl, processStartedAt: PROCESS_STARTED_AT, entry: SELF_ENTRY, version: DAEMON_VERSION }),
94696
95417
  "utf8"
@@ -94699,7 +95420,7 @@ async function startMultiDaemon(opts = {}) {
94699
95420
  }
94700
95421
  for (const r of records) {
94701
95422
  try {
94702
- writeFileSync28(
95423
+ writeFileSync29(
94703
95424
  r.engine.paths.daemonLock,
94704
95425
  daemonLockPayload({
94705
95426
  pid: process.pid,
@@ -94739,7 +95460,14 @@ async function startMultiDaemon(opts = {}) {
94739
95460
  });
94740
95461
  const revisionBacklog = /* @__PURE__ */ new Set();
94741
95462
  const lastAnchorPull = /* @__PURE__ */ new Map();
94742
- const pullProjectAnchors = async (r, client, salt) => {
95463
+ const pullProjectAnchors = (r, client, salt) => {
95464
+ const running = anchorPullInFlight.get(r.root);
95465
+ if (running) return running;
95466
+ const pull = pullProjectAnchorsOnce(r, client, salt).finally(() => anchorPullInFlight.delete(r.root));
95467
+ anchorPullInFlight.set(r.root, pull);
95468
+ return pull;
95469
+ };
95470
+ const pullProjectAnchorsOnce = async (r, client, salt) => {
94743
95471
  const donePass = markPass(`anchor-pull:${r.engine.profile.name}`);
94744
95472
  const pullStartedAt = Date.now();
94745
95473
  const beforeCorrections = r.engine.profile.projectHistoryCorrectionCursor ?? 0;
@@ -94755,10 +95483,13 @@ async function startMultiDaemon(opts = {}) {
94755
95483
  for (const record2 of records) record2.engine.markContextDirty();
94756
95484
  }
94757
95485
  try {
94758
- const revision = await syncHistoryRevision({ root: r.root, profile: r.engine.profile, store: r.engine.store, cloud: client, salt });
94759
- if (revision.remaining) revisionBacklog.add(r.root);
94760
- else revisionBacklog.delete(r.root);
94761
- if (revision.changed) r.engine.markContextDirty();
95486
+ if (!r.engine.storeReconciled()) revisionBacklog.add(r.root);
95487
+ else {
95488
+ const revision = await syncHistoryRevision({ root: r.root, profile: r.engine.profile, store: r.engine.store, cloud: client, salt });
95489
+ if (revision.remaining) revisionBacklog.add(r.root);
95490
+ else revisionBacklog.delete(r.root);
95491
+ if (revision.changed) r.engine.markContextDirty();
95492
+ }
94762
95493
  } catch (err2) {
94763
95494
  console.warn(`[errata] history revision reconciliation failed for ${r.engine.profile.name}: ${err2 instanceof Error ? err2.message : String(err2)}`);
94764
95495
  }
@@ -95248,6 +95979,10 @@ async function startMultiDaemon(opts = {}) {
95248
95979
  };
95249
95980
  let uploaded = 0;
95250
95981
  const errors = [];
95982
+ let retryAt = null;
95983
+ const retryBy = (at) => {
95984
+ if (at !== null && (retryAt === null || at < retryAt)) retryAt = at;
95985
+ };
95251
95986
  const workerFor = (r) => consolidateWorker && r.engine.paths.castalia !== ":memory:" ? consolidateWorker : null;
95252
95987
  const buildContextBatch = async (r, input) => {
95253
95988
  const w = workerFor(r);
@@ -95371,6 +96106,7 @@ async function startMultiDaemon(opts = {}) {
95371
96106
  }
95372
96107
  });
95373
96108
  if (p.blockedNodeIds?.length) {
96109
+ retryBy(Date.now());
95374
96110
  console.log(
95375
96111
  `[sync\u2192cloud] [${projectName}] context: ${p.blockedNodeIds.length} node(s) refused by an edge/CDN filter on content \u2014 left pending, will retry`
95376
96112
  );
@@ -95402,6 +96138,7 @@ async function startMultiDaemon(opts = {}) {
95402
96138
  });
95403
96139
  const parkPath = edgeParkPath(r.engine.paths.configDir, destinationKey);
95404
96140
  const parkQueue = loadEdgePark(parkPath);
96141
+ retryBy(nextEdgeParkChange(parkQueue));
95405
96142
  const built = await buildInstanceBatch(r, {
95406
96143
  edgeHolds: edgeHolds(parkQueue, Date.now()),
95407
96144
  destinationKey,
@@ -95471,6 +96208,7 @@ async function startMultiDaemon(opts = {}) {
95471
96208
  }
95472
96209
  });
95473
96210
  if (blocked.size > 0) {
96211
+ retryBy(Date.now());
95474
96212
  console.log(
95475
96213
  `[sync\u2192cloud] [${projectName}] instances: ${blocked.size} node(s) refused by an edge/CDN filter on content \u2014 left pending, will retry. First: ${store.getNode([...blocked][0])?.description.slice(0, 120) ?? [...blocked][0]}`
95476
96214
  );
@@ -95506,6 +96244,7 @@ async function startMultiDaemon(opts = {}) {
95506
96244
  Date.now()
95507
96245
  );
95508
96246
  saveEdgePark(parkPath, settled.queue);
96247
+ retryBy(nextEdgeParkChange(settled.queue));
95509
96248
  const edgeCounts = settled.counts;
95510
96249
  if (rejectedEdges.length > 0) {
95511
96250
  const byReason = /* @__PURE__ */ new Map();
@@ -95632,7 +96371,7 @@ async function startMultiDaemon(opts = {}) {
95632
96371
  });
95633
96372
  }
95634
96373
  }
95635
- return { uploaded, ...errors.length > 0 ? { errors } : {} };
96374
+ return { uploaded, ...errors.length > 0 ? { errors } : {}, ...retryAt !== null ? { retryAt } : {} };
95636
96375
  },
95637
96376
  async backfillCausalEdges() {
95638
96377
  if (!loadConfig().consent.sync) return { accepted: 0, rejected: 0, skipped: "consent-off" };
@@ -95707,9 +96446,9 @@ async function startMultiDaemon(opts = {}) {
95707
96446
  beginFlush("instances");
95708
96447
  try {
95709
96448
  flushStage("instances");
95710
- const startedFrom = instanceFingerprint();
95711
- const inst = await daemon.syncInstancesPublic();
95712
- shippedFingerprint = startedFrom;
96449
+ const lanes = shipLanes();
96450
+ const inst = lanes.length > 0 && unshipped(lanes, true).length === 0 ? { uploaded: 0, skipped: "unchanged", errors: void 0 } : await daemon.syncInstancesPublic();
96451
+ if (!inst.skipped) recordShipped(lanes, inst);
95713
96452
  flushStage("skills");
95714
96453
  const skills = await daemon.syncSkillsAll();
95715
96454
  return {
@@ -95723,8 +96462,8 @@ async function startMultiDaemon(opts = {}) {
95723
96462
  }
95724
96463
  },
95725
96464
  pendingLiveFingerprint() {
95726
- const fp = instanceFingerprint();
95727
- return fp && fp !== shippedFingerprint ? fp : null;
96465
+ const pending = unshipped(shipLanes(), false);
96466
+ return pending.length ? pending.map((l) => l.fp ?? `?${Date.now()}`).join("|") : null;
95728
96467
  },
95729
96468
  async liveShip() {
95730
96469
  if (!liveSyncEnabled()) return { uploaded: 0, skipped: "disabled" };
@@ -95740,9 +96479,9 @@ async function startMultiDaemon(opts = {}) {
95740
96479
  }
95741
96480
  beginFlush("live");
95742
96481
  try {
95743
- const startedFrom = instanceFingerprint();
96482
+ const lanes = shipLanes();
95744
96483
  const inst = await daemon.syncInstancesPublic();
95745
- shippedFingerprint = startedFrom;
96484
+ if (!inst.skipped) recordShipped(lanes, inst);
95746
96485
  return {
95747
96486
  uploaded: inst.uploaded,
95748
96487
  ...inst.skipped ? { skipped: inst.skipped } : {},
@@ -95792,7 +96531,9 @@ async function startMultiDaemon(opts = {}) {
95792
96531
  flushStage("triage");
95793
96532
  const triage = await daemon.syncTriagePublic();
95794
96533
  flushStage("instances");
96534
+ const lanes = shipLanes();
95795
96535
  const instances = await daemon.syncInstancesPublic();
96536
+ if (!instances.skipped) recordShipped(lanes, instances);
95796
96537
  flushStage("edge-backfill");
95797
96538
  const edgeBackfill = await daemon.backfillCausalEdges();
95798
96539
  return c.json({ principles, triage, instances, edgeBackfill });
@@ -96217,15 +96958,15 @@ function shouldUseOAuthLogin(flags2, env2 = process.env) {
96217
96958
  import { spawnSync as spawnSync2 } from "node:child_process";
96218
96959
 
96219
96960
  // src/codex-runtime.ts
96220
- import { readdirSync as readdirSync13, statSync as statSync11 } from "node:fs";
96221
- import { join as join45 } from "node:path";
96961
+ import { readdirSync as readdirSync13, statSync as statSync12 } from "node:fs";
96962
+ import { join as join48 } from "node:path";
96222
96963
  function resolveCodexExecutable(options = {}) {
96223
96964
  const platform = options.platform ?? process.platform;
96224
96965
  const env2 = options.env ?? process.env;
96225
96966
  if (platform !== "win32") return "codex";
96226
96967
  const fileTime = (path3) => {
96227
96968
  try {
96228
- const s = statSync11(path3);
96969
+ const s = statSync12(path3);
96229
96970
  return s.isFile() ? s.mtimeMs : null;
96230
96971
  } catch {
96231
96972
  return null;
@@ -96233,13 +96974,13 @@ function resolveCodexExecutable(options = {}) {
96233
96974
  };
96234
96975
  for (const dir of (env2["PATH"] ?? env2["Path"] ?? "").split(";")) {
96235
96976
  if (!dir.trim()) continue;
96236
- const path3 = join45(dir.trim().replace(/^"|"$/g, ""), "codex.exe");
96977
+ const path3 = join48(dir.trim().replace(/^"|"$/g, ""), "codex.exe");
96237
96978
  if (fileTime(path3) !== null) return path3;
96238
96979
  }
96239
96980
  if (!env2["LOCALAPPDATA"]) return "codex";
96240
- const root = join45(env2["LOCALAPPDATA"], "OpenAI", "Codex", "bin");
96981
+ const root = join48(env2["LOCALAPPDATA"], "OpenAI", "Codex", "bin");
96241
96982
  try {
96242
- const candidates = readdirSync13(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join45(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));
96983
+ const candidates = readdirSync13(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join48(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));
96243
96984
  return candidates[0]?.path ?? "codex";
96244
96985
  } catch {
96245
96986
  return "codex";
@@ -96378,14 +97119,14 @@ async function diagnoseInstallation(cfg, dependencies) {
96378
97119
  }
96379
97120
 
96380
97121
  // src/credential-scan.ts
96381
- import { readFileSync as readFileSync39, statSync as statSync12 } from "node:fs";
97122
+ import { readFileSync as readFileSync42, statSync as statSync13 } from "node:fs";
96382
97123
  import { homedir as homedir8 } from "node:os";
96383
- import { join as join47 } from "node:path";
97124
+ import { join as join50 } from "node:path";
96384
97125
 
96385
97126
  // src/claude-statusline.ts
96386
- import { existsSync as existsSync35, mkdirSync as mkdirSync9, readFileSync as readFileSync38, writeFileSync as writeFileSync29 } from "node:fs";
97127
+ import { existsSync as existsSync35, mkdirSync as mkdirSync9, readFileSync as readFileSync41, writeFileSync as writeFileSync30 } from "node:fs";
96387
97128
  import { homedir as homedir7 } from "node:os";
96388
- import { dirname as dirname16, join as join46 } from "node:path";
97129
+ import { dirname as dirname17, join as join49 } from "node:path";
96389
97130
  var STATUSLINE_RELAY_SOURCE = String.raw`// errata-managed: regenerated by errata init / install-hooks claude
96390
97131
  import { readFileSync } from 'node:fs';
96391
97132
 
@@ -96433,8 +97174,8 @@ function isSameInstall(value, relay) {
96433
97174
  return command.includes(relay.replace(/\\/g, "/").toLowerCase());
96434
97175
  }
96435
97176
  function userClaudeSettingsPath() {
96436
- const base = process.env["CLAUDE_CONFIG_DIR"] ?? join46(homedir7(), ".claude");
96437
- return join46(base, "settings.json");
97177
+ const base = process.env["CLAUDE_CONFIG_DIR"] ?? join49(homedir7(), ".claude");
97178
+ return join49(base, "settings.json");
96438
97179
  }
96439
97180
  function ensureUserStatusLine(opts) {
96440
97181
  const env2 = opts.env ?? process.env;
@@ -96444,21 +97185,21 @@ function ensureUserStatusLine(opts) {
96444
97185
  let settings = {};
96445
97186
  if (existsSync35(settingsPath)) {
96446
97187
  try {
96447
- const parsed = JSON.parse(readFileSync38(settingsPath, "utf8"));
97188
+ const parsed = JSON.parse(readFileSync41(settingsPath, "utf8"));
96448
97189
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return "unreadable";
96449
97190
  settings = parsed;
96450
97191
  } catch {
96451
97192
  return "unreadable";
96452
97193
  }
96453
97194
  }
96454
- const relay = join46(opts.relayDir, STATUSLINE_RELAY_FILE);
97195
+ const relay = join49(opts.relayDir, STATUSLINE_RELAY_FILE);
96455
97196
  const keep = (value) => value !== void 0 && (!isErrataStatusLine(value) || !isSameInstall(value, relay));
96456
97197
  const ownMain = keep(settings["statusLine"]);
96457
97198
  const ownRows = keep(settings["subagentStatusLine"]);
96458
97199
  if (ownMain && ownRows) return "kept-own";
96459
97200
  mkdirSync9(opts.relayDir, { recursive: true });
96460
- if (!existsSync35(relay) || readFileSync38(relay, "utf8") !== STATUSLINE_RELAY_SOURCE) {
96461
- writeFileSync29(relay, STATUSLINE_RELAY_SOURCE, "utf8");
97201
+ if (!existsSync35(relay) || readFileSync41(relay, "utf8") !== STATUSLINE_RELAY_SOURCE) {
97202
+ writeFileSync30(relay, STATUSLINE_RELAY_SOURCE, "utf8");
96462
97203
  }
96463
97204
  const nodePath = opts.nodePath ?? process.execPath;
96464
97205
  const next = {
@@ -96469,8 +97210,8 @@ function ensureUserStatusLine(opts) {
96469
97210
  return ownMain ? "kept-own" : "unchanged";
96470
97211
  }
96471
97212
  Object.assign(settings, next);
96472
- mkdirSync9(dirname16(settingsPath), { recursive: true });
96473
- writeFileSync29(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf8");
97213
+ mkdirSync9(dirname17(settingsPath), { recursive: true });
97214
+ writeFileSync30(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf8");
96474
97215
  return "installed";
96475
97216
  }
96476
97217
  function describeStatusLineOutcome(outcome) {
@@ -96511,36 +97252,36 @@ function findCredentialLines(text) {
96511
97252
  function harnessConfigPaths(root) {
96512
97253
  const env2 = process.env;
96513
97254
  const home = homedir8();
96514
- const codexHome = env2["CODEX_HOME"] || join47(home, ".codex");
96515
- const geminiHome = join47(env2["GEMINI_CLI_HOME"] ?? home, ".gemini");
97255
+ const codexHome = env2["CODEX_HOME"] || join50(home, ".codex");
97256
+ const geminiHome = join50(env2["GEMINI_CLI_HOME"] ?? home, ".gemini");
96516
97257
  return [
96517
97258
  // Claude Code: user settings, `claude mcp add` (local/user scope), project.
96518
97259
  userClaudeSettingsPath(),
96519
- join47(env2["CLAUDE_CONFIG_DIR"] ?? home, ".claude.json"),
96520
- join47(root, ".claude", "settings.json"),
96521
- join47(root, ".claude", "settings.local.json"),
96522
- join47(root, ".mcp.json"),
97260
+ join50(env2["CLAUDE_CONFIG_DIR"] ?? home, ".claude.json"),
97261
+ join50(root, ".claude", "settings.json"),
97262
+ join50(root, ".claude", "settings.local.json"),
97263
+ join50(root, ".mcp.json"),
96523
97264
  // Codex
96524
- join47(codexHome, "config.toml"),
96525
- join47(root, ".codex", "config.toml"),
97265
+ join50(codexHome, "config.toml"),
97266
+ join50(root, ".codex", "config.toml"),
96526
97267
  // Gemini CLI
96527
- join47(geminiHome, "settings.json"),
96528
- join47(root, ".gemini", "settings.json"),
97268
+ join50(geminiHome, "settings.json"),
97269
+ join50(root, ".gemini", "settings.json"),
96529
97270
  // Cursor
96530
- join47(home, ".cursor", "mcp.json"),
96531
- join47(root, ".cursor", "mcp.json"),
97271
+ join50(home, ".cursor", "mcp.json"),
97272
+ join50(root, ".cursor", "mcp.json"),
96532
97273
  // VS Code (user profile mcp.json + workspace)
96533
- join47(vscodeUserDir(home, env2), "mcp.json"),
96534
- join47(root, ".vscode", "mcp.json"),
97274
+ join50(vscodeUserDir(home, env2), "mcp.json"),
97275
+ join50(root, ".vscode", "mcp.json"),
96535
97276
  // OpenCode (XDG on every platform; the daemon's installer writes the project one)
96536
- join47(env2["XDG_CONFIG_HOME"] ?? join47(home, ".config"), "opencode", "opencode.json"),
96537
- join47(root, "opencode.json")
97277
+ join50(env2["XDG_CONFIG_HOME"] ?? join50(home, ".config"), "opencode", "opencode.json"),
97278
+ join50(root, "opencode.json")
96538
97279
  ];
96539
97280
  }
96540
97281
  function vscodeUserDir(home, env2) {
96541
- if (process.platform === "win32") return join47(env2["APPDATA"] ?? join47(home, "AppData", "Roaming"), "Code", "User");
96542
- if (process.platform === "darwin") return join47(home, "Library", "Application Support", "Code", "User");
96543
- return join47(env2["XDG_CONFIG_HOME"] ?? join47(home, ".config"), "Code", "User");
97282
+ if (process.platform === "win32") return join50(env2["APPDATA"] ?? join50(home, "AppData", "Roaming"), "Code", "User");
97283
+ if (process.platform === "darwin") return join50(home, "Library", "Application Support", "Code", "User");
97284
+ return join50(env2["XDG_CONFIG_HOME"] ?? join50(home, ".config"), "Code", "User");
96544
97285
  }
96545
97286
  function scanHarnessConfigs(paths, read2 = readBounded) {
96546
97287
  const findings = [];
@@ -96555,9 +97296,9 @@ function scanHarnessConfigs(paths, read2 = readBounded) {
96555
97296
  }
96556
97297
  function readBounded(path3) {
96557
97298
  try {
96558
- const stat4 = statSync12(path3);
97299
+ const stat4 = statSync13(path3);
96559
97300
  if (!stat4.isFile() || stat4.size > MAX_SCAN_BYTES) return null;
96560
- return readFileSync39(path3, "utf8");
97301
+ return readFileSync42(path3, "utf8");
96561
97302
  } catch {
96562
97303
  return null;
96563
97304
  }
@@ -96582,14 +97323,14 @@ function credentialHygieneCheck(scan2) {
96582
97323
 
96583
97324
  // src/codex-doctor.ts
96584
97325
  import { spawn as spawn4 } from "node:child_process";
96585
- import { readFileSync as readFileSync41, statSync as statSync13 } from "node:fs";
96586
- import { join as join49 } from "node:path";
97326
+ import { readFileSync as readFileSync44, statSync as statSync14 } from "node:fs";
97327
+ import { join as join52 } from "node:path";
96587
97328
  import { createInterface } from "node:readline";
96588
97329
 
96589
97330
  // src/codex-hooks.ts
96590
- import { existsSync as existsSync36, mkdirSync as mkdirSync10, readFileSync as readFileSync40, renameSync as renameSync7, unlinkSync as unlinkSync5, writeFileSync as writeFileSync30 } from "node:fs";
97331
+ import { existsSync as existsSync36, mkdirSync as mkdirSync10, readFileSync as readFileSync43, renameSync as renameSync8, unlinkSync as unlinkSync5, writeFileSync as writeFileSync31 } from "node:fs";
96591
97332
  import { homedir as homedir9 } from "node:os";
96592
- import { join as join48 } from "node:path";
97333
+ import { join as join51 } from "node:path";
96593
97334
 
96594
97335
  // src/hook-commands.ts
96595
97336
  function hookCurlCommand(port, path3 = "/api/hook") {
@@ -96793,34 +97534,34 @@ function buildCodexRelaySource(workspaceRoot) {
96793
97534
  init_checkout_root();
96794
97535
  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.";
96795
97536
  function writeRelay(file2, source) {
96796
- if (existsSync36(file2) && readFileSync40(file2, "utf8") === source) return;
97537
+ if (existsSync36(file2) && readFileSync43(file2, "utf8") === source) return;
96797
97538
  const temp = `${file2}.${process.pid}.tmp`;
96798
97539
  try {
96799
- writeFileSync30(temp, source, { encoding: "utf8", mode: 384 });
96800
- renameSync7(temp, file2);
97540
+ writeFileSync31(temp, source, { encoding: "utf8", mode: 384 });
97541
+ renameSync8(temp, file2);
96801
97542
  } finally {
96802
97543
  if (existsSync36(temp)) unlinkSync5(temp);
96803
97544
  }
96804
97545
  }
96805
97546
  function refreshCodexRelay(root) {
96806
- const config2 = join48(root, ".codex", "config.toml");
97547
+ const config2 = join51(root, ".codex", "config.toml");
96807
97548
  if (!existsSync36(config2)) return "absent";
96808
- const existing = readFileSync40(config2, "utf8");
97549
+ const existing = readFileSync43(config2, "utf8");
96809
97550
  if (!existing.includes(CODEX_HOOKS_BEGIN) && !existing.includes(CODEX_HOOKS_END)) return "absent";
96810
97551
  replaceCodexHooks(existing, "");
96811
- const relay = join48(root, ".codex", "hooks", "errata-relay.mjs");
96812
- const prior = existsSync36(relay) ? readFileSync40(relay, "utf8") : "";
97552
+ const relay = join51(root, ".codex", "hooks", "errata-relay.mjs");
97553
+ const prior = existsSync36(relay) ? readFileSync43(relay, "utf8") : "";
96813
97554
  if (prior && !prior.startsWith("// errata-managed: regenerated by errata install-hooks codex")) {
96814
97555
  throw new Error("Codex relay is not Errata-managed; preserved it. Run errata install-hooks codex to explicitly replace it.");
96815
97556
  }
96816
97557
  const source = buildCodexRelaySource(checkoutRootOf(root));
96817
97558
  if (prior === source) return "current";
96818
- mkdirSync10(join48(root, ".codex", "hooks"), { recursive: true });
97559
+ mkdirSync10(join51(root, ".codex", "hooks"), { recursive: true });
96819
97560
  writeRelay(relay, source);
96820
97561
  return "updated";
96821
97562
  }
96822
- function hasCodexConfig(root, codexHome = process.env["CODEX_HOME"] || join48(homedir9(), ".codex")) {
96823
- return existsSync36(join48(root, ".codex")) || existsSync36(codexHome);
97563
+ function hasCodexConfig(root, codexHome = process.env["CODEX_HOME"] || join51(homedir9(), ".codex")) {
97564
+ return existsSync36(join51(root, ".codex")) || existsSync36(codexHome);
96824
97565
  }
96825
97566
  function replaceCodexHooks(existing, block) {
96826
97567
  const begin = existing.indexOf(CODEX_HOOKS_BEGIN);
@@ -96836,14 +97577,14 @@ function replaceCodexHooks(existing, block) {
96836
97577
  return existing.trimEnd() + (existing.trim() ? "\n\n" : "") + block;
96837
97578
  }
96838
97579
  function writeCodexHooks(root, port, nodePath = process.execPath) {
96839
- const dir = join48(root, ".codex");
96840
- const file2 = join48(dir, "config.toml");
96841
- const relay = join48(dir, "hooks", "errata-relay.mjs");
97580
+ const dir = join51(root, ".codex");
97581
+ const file2 = join51(dir, "config.toml");
97582
+ const relay = join51(dir, "hooks", "errata-relay.mjs");
96842
97583
  const block = buildCodexHooksToml(port, { nodePath, relayPath: relay });
96843
- const final = replaceCodexHooks(existsSync36(file2) ? readFileSync40(file2, "utf8") : "", block);
96844
- mkdirSync10(join48(dir, "hooks"), { recursive: true });
97584
+ const final = replaceCodexHooks(existsSync36(file2) ? readFileSync43(file2, "utf8") : "", block);
97585
+ mkdirSync10(join51(dir, "hooks"), { recursive: true });
96845
97586
  writeRelay(relay, buildCodexRelaySource(checkoutRootOf(root)));
96846
- if (!existsSync36(file2) || readFileSync40(file2, "utf8") !== final) writeFileSync30(file2, final, "utf8");
97587
+ if (!existsSync36(file2) || readFileSync43(file2, "utf8") !== final) writeFileSync31(file2, final, "utf8");
96847
97588
  return file2;
96848
97589
  }
96849
97590
 
@@ -96852,7 +97593,7 @@ init_checkout_root();
96852
97593
  function inspectCodexRelay(cwd) {
96853
97594
  const root = nearestGitRoot(cwd) ?? cwd;
96854
97595
  try {
96855
- const source = readFileSync41(join49(root, ".codex", "hooks", "errata-relay.mjs"), "utf8");
97596
+ const source = readFileSync44(join52(root, ".codex", "hooks", "errata-relay.mjs"), "utf8");
96856
97597
  if (source === buildCodexRelaySource(checkoutRootOf(root))) {
96857
97598
  return { id: "codex_relay", status: "pass", detail: "Installed Codex relay matches this Errata version" };
96858
97599
  }
@@ -96863,8 +97604,8 @@ function inspectCodexRelay(cwd) {
96863
97604
  function inspectCodexContext(cwd) {
96864
97605
  const root = checkoutRootOf(nearestGitRoot(cwd) ?? cwd);
96865
97606
  try {
96866
- const file2 = join49(root, ".errata", "context.md");
96867
- if (statSync13(file2).size <= 128 * 1024 && readFileSync41(file2, "utf8").trim()) {
97607
+ const file2 = join52(root, ".errata", "context.md");
97608
+ if (statSync14(file2).size <= 128 * 1024 && readFileSync44(file2, "utf8").trim()) {
96868
97609
  return { id: "codex_context", status: "pass", detail: "Saved workspace context is readable by the relay; this does not prove live daemon freshness" };
96869
97610
  }
96870
97611
  } catch {
@@ -97041,11 +97782,11 @@ function consolidationGapMs(lastPassMs, policy) {
97041
97782
  }
97042
97783
 
97043
97784
  // src/codex-context-plugin.ts
97044
- import { createHash as createHash20 } from "node:crypto";
97045
- import { cpSync as cpSync2, existsSync as existsSync37, mkdirSync as mkdirSync11, readFileSync as readFileSync42, renameSync as renameSync8, writeFileSync as writeFileSync31 } from "node:fs";
97785
+ import { createHash as createHash21 } from "node:crypto";
97786
+ import { cpSync as cpSync2, existsSync as existsSync37, mkdirSync as mkdirSync11, readFileSync as readFileSync45, renameSync as renameSync9, writeFileSync as writeFileSync32 } from "node:fs";
97046
97787
  import { homedir as homedir10 } from "node:os";
97047
- import { join as join50 } from "node:path";
97048
- import { fileURLToPath as fileURLToPath2 } from "node:url";
97788
+ import { join as join53 } from "node:path";
97789
+ import { fileURLToPath as fileURLToPath3 } from "node:url";
97049
97790
 
97050
97791
  // ../../node_modules/.pnpm/smol-toml@1.6.1/node_modules/smol-toml/dist/error.js
97051
97792
  function getLineColFromPtr(string4, ptr) {
@@ -97127,7 +97868,7 @@ function skipVoid(str, ptr, banNewLines, banComments) {
97127
97868
  }
97128
97869
  return ptr;
97129
97870
  }
97130
- function skipUntil(str, ptr, sep6, end, banNewLines = false) {
97871
+ function skipUntil(str, ptr, sep7, end, banNewLines = false) {
97131
97872
  if (!end) {
97132
97873
  ptr = indexOfNewline(str, ptr);
97133
97874
  return ptr < 0 ? str.length : ptr;
@@ -97136,7 +97877,7 @@ function skipUntil(str, ptr, sep6, end, banNewLines = false) {
97136
97877
  let c = str[i2];
97137
97878
  if (c === "#") {
97138
97879
  i2 = indexOfNewline(str, i2);
97139
- } else if (c === sep6) {
97880
+ } else if (c === sep7) {
97140
97881
  return i2 + 1;
97141
97882
  } else if (c === end || banNewLines && (c === "\n" || c === "\r" && str[i2 + 1] === "\n")) {
97142
97883
  return i2;
@@ -97742,23 +98483,23 @@ var NAME = "errata-context";
97742
98483
  var PREFIX2 = `./.errata/plugins/${NAME}/`;
97743
98484
  var object2 = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
97744
98485
  function readText(file2) {
97745
- return existsSync37(file2) ? readFileSync42(file2, "utf8") : "";
98486
+ return existsSync37(file2) ? readFileSync45(file2, "utf8") : "";
97746
98487
  }
97747
98488
  function writeChanged(file2, content) {
97748
98489
  if (readText(file2) === content) return;
97749
98490
  const temp = `${file2}.${process.pid}.tmp`;
97750
- writeFileSync31(temp, content, "utf8");
97751
- renameSync8(temp, file2);
98491
+ writeFileSync32(temp, content, "utf8");
98492
+ renameSync9(temp, file2);
97752
98493
  }
97753
98494
  function bundledContextPlugin() {
97754
- const packaged = fileURLToPath2(new URL("./resources/context-plugin/", import.meta.url));
97755
- if (existsSync37(join50(packaged, ".codex-plugin/plugin.json"))) return packaged;
97756
- return fileURLToPath2(new URL("../dist/resources/context-plugin/", import.meta.url));
98495
+ const packaged = fileURLToPath3(new URL("./resources/context-plugin/", import.meta.url));
98496
+ if (existsSync37(join53(packaged, ".codex-plugin/plugin.json"))) return packaged;
98497
+ return fileURLToPath3(new URL("../dist/resources/context-plugin/", import.meta.url));
97757
98498
  }
97758
98499
  function refreshCodexContextPlugin(root) {
97759
- const file2 = join50(root, ".agents", "plugins", "marketplace.json");
98500
+ const file2 = join53(root, ".agents", "plugins", "marketplace.json");
97760
98501
  if (!existsSync37(file2)) return false;
97761
- const marketplace = JSON.parse(readFileSync42(file2, "utf8"));
98502
+ const marketplace = JSON.parse(readFileSync45(file2, "utf8"));
97762
98503
  const entries = Array.isArray(marketplace.plugins) ? marketplace.plugins : [];
97763
98504
  const entry = entries.map(object2).find((value) => value.name === NAME && String(object2(value.source).path).startsWith(PREFIX2));
97764
98505
  if (!entry) return false;
@@ -97769,24 +98510,24 @@ function refreshCodexContextPlugin(root) {
97769
98510
  function installCodexContextPlugin(root, options = {}) {
97770
98511
  const bundle = options.bundle ?? bundledContextPlugin();
97771
98512
  const manifest = JSON.parse(
97772
- readFileSync42(join50(bundle, ".codex-plugin/plugin.json"), "utf8")
98513
+ readFileSync45(join53(bundle, ".codex-plugin/plugin.json"), "utf8")
97773
98514
  );
97774
98515
  if (manifest.name !== NAME || typeof manifest.version !== "string" || !/^[\w.-]+$/.test(manifest.version)) {
97775
98516
  throw new Error("Invalid bundled Errata Context manifest.");
97776
98517
  }
97777
- const checksums = readFileSync42(join50(bundle, "SHA256SUMS"), "utf8");
98518
+ const checksums = readFileSync45(join53(bundle, "SHA256SUMS"), "utf8");
97778
98519
  for (const line of checksums.trim().split("\n")) {
97779
98520
  const match2 = /^([a-f0-9]{64}) ([\w./-]+)$/.exec(line);
97780
98521
  if (!match2 || match2[2].startsWith("/") || match2[2].split("/").includes("..")) {
97781
98522
  throw new Error("Invalid bundled Errata Context checksum manifest.");
97782
98523
  }
97783
- const actual = createHash20("sha256").update(readFileSync42(join50(bundle, match2[2]))).digest("hex");
98524
+ const actual = createHash21("sha256").update(readFileSync45(join53(bundle, match2[2]))).digest("hex");
97784
98525
  if (actual !== match2[1])
97785
98526
  throw new Error(`Bundled Errata Context checksum mismatch: ${match2[2]}`);
97786
98527
  }
97787
- const release = `${manifest.version}-${createHash20("sha256").update(checksums).digest("hex").slice(0, 12)}`;
97788
- const plugin = join50(root, ".errata", "plugins", NAME, release);
97789
- const marketplaceFile = join50(root, ".agents", "plugins", "marketplace.json");
98528
+ const release = `${manifest.version}-${createHash21("sha256").update(checksums).digest("hex").slice(0, 12)}`;
98529
+ const plugin = join53(root, ".errata", "plugins", NAME, release);
98530
+ const marketplaceFile = join53(root, ".agents", "plugins", "marketplace.json");
97790
98531
  const priorMarketplace = readText(marketplaceFile);
97791
98532
  const marketplace = priorMarketplace ? JSON.parse(priorMarketplace) : {
97792
98533
  name: "errata-local",
@@ -97807,12 +98548,12 @@ function installCodexContextPlugin(root, options = {}) {
97807
98548
  );
97808
98549
  }
97809
98550
  const key = `${NAME}@${marketplace.name}`;
97810
- const configFile = join50(root, ".codex", "config.toml");
98551
+ const configFile = join53(root, ".codex", "config.toml");
97811
98552
  const config2 = readText(configFile);
97812
98553
  const parsed = parse4(config2);
97813
98554
  const plugins = object2(parsed.plugins);
97814
- const codexHome = options.codexHome ?? process.env["CODEX_HOME"] ?? join50(homedir10(), ".codex");
97815
- const globalPlugins = object2(parse4(readText(join50(codexHome, "config.toml"))).plugins);
98555
+ const codexHome = options.codexHome ?? process.env["CODEX_HOME"] ?? join53(homedir10(), ".codex");
98556
+ const globalPlugins = object2(parse4(readText(join53(codexHome, "config.toml"))).plugins);
97816
98557
  const disabledGlobally = Object.entries(globalPlugins).some(
97817
98558
  ([name2, value]) => (name2 === NAME || name2.startsWith(`${NAME}@`)) && object2(value).enabled === false
97818
98559
  );
@@ -97836,13 +98577,13 @@ enabled = ${enabled}
97836
98577
  mkdirSync11(plugin, { recursive: true });
97837
98578
  cpSync2(bundle, plugin, { recursive: true });
97838
98579
  writeChanged(
97839
- join50(plugin, ".mcp.json"),
98580
+ join53(plugin, ".mcp.json"),
97840
98581
  JSON.stringify(
97841
98582
  {
97842
98583
  mcpServers: {
97843
98584
  errata_context: {
97844
98585
  command: options.nodePath ?? process.execPath,
97845
- args: [join50(plugin, "dist", "mcp-server.mjs")],
98586
+ args: [join53(plugin, "dist", "mcp-server.mjs")],
97846
98587
  env: { ERRATA_WORKSPACE: root, ERRATA_CONTEXT_VERSION: manifest.version }
97847
98588
  }
97848
98589
  }
@@ -97851,8 +98592,8 @@ enabled = ${enabled}
97851
98592
  2
97852
98593
  ) + "\n"
97853
98594
  );
97854
- mkdirSync11(join50(root, ".agents", "plugins"), { recursive: true });
97855
- mkdirSync11(join50(root, ".codex"), { recursive: true });
98595
+ mkdirSync11(join53(root, ".agents", "plugins"), { recursive: true });
98596
+ mkdirSync11(join53(root, ".codex"), { recursive: true });
97856
98597
  writeChanged(marketplaceFile, JSON.stringify(marketplace, null, 2) + "\n");
97857
98598
  writeChanged(configFile, nextConfig);
97858
98599
  return { plugin, enabled, marketplace: marketplaceFile };
@@ -97860,15 +98601,15 @@ enabled = ${enabled}
97860
98601
 
97861
98602
  // src/codex-hook-refresh.ts
97862
98603
  init_checkout_root();
97863
- import { existsSync as existsSync38, readdirSync as readdirSync14, readFileSync as readFileSync43 } from "node:fs";
97864
- import { dirname as dirname17, join as join51, resolve as resolve8 } from "node:path";
98604
+ import { existsSync as existsSync38, readdirSync as readdirSync14, readFileSync as readFileSync46 } from "node:fs";
98605
+ import { dirname as dirname18, join as join54, resolve as resolve8 } from "node:path";
97865
98606
  init_registry();
97866
98607
  function codexHookRoots(roots) {
97867
98608
  const found = new Set(roots.map((root) => resolve8(root)));
97868
98609
  for (const root of [...found]) {
97869
98610
  const main2 = mainCheckoutOfWorktree(root) ?? root;
97870
98611
  found.add(main2);
97871
- const dir = join51(main2, ".git", "worktrees");
98612
+ const dir = join54(main2, ".git", "worktrees");
97872
98613
  if (!existsSync38(dir)) continue;
97873
98614
  let names;
97874
98615
  try {
@@ -97878,7 +98619,7 @@ function codexHookRoots(roots) {
97878
98619
  }
97879
98620
  for (const name2 of names) {
97880
98621
  try {
97881
- const checkout = dirname17(readFileSync43(join51(dir, name2, "gitdir"), "utf8").trim());
98622
+ const checkout = dirname18(readFileSync46(join54(dir, name2, "gitdir"), "utf8").trim());
97882
98623
  if (mainCheckoutOfWorktree(checkout) === main2) found.add(checkout);
97883
98624
  } catch {
97884
98625
  }
@@ -97900,50 +98641,50 @@ function refreshInstalledCodexRelays(roots = listWorkspaceEntries().map((entry)
97900
98641
  }
97901
98642
 
97902
98643
  // src/claude-mods.ts
97903
- import { createHash as createHash21 } from "node:crypto";
97904
- import { cpSync as cpSync3, existsSync as existsSync39, mkdirSync as mkdirSync12, readFileSync as readFileSync44, readdirSync as readdirSync15, rmSync as rmSync4, statSync as statSync14, writeFileSync as writeFileSync32 } from "node:fs";
97905
- import { delimiter as delimiter2, dirname as dirname18, join as join52, relative as relative8, resolve as resolve9, sep as sep5 } from "node:path";
97906
- import { fileURLToPath as fileURLToPath3 } from "node:url";
98644
+ import { createHash as createHash22 } from "node:crypto";
98645
+ import { cpSync as cpSync3, existsSync as existsSync39, mkdirSync as mkdirSync12, readFileSync as readFileSync47, readdirSync as readdirSync15, rmSync as rmSync4, statSync as statSync15, writeFileSync as writeFileSync33 } from "node:fs";
98646
+ import { delimiter as delimiter2, dirname as dirname19, join as join55, relative as relative7, resolve as resolve9, sep as sep6 } from "node:path";
98647
+ import { fileURLToPath as fileURLToPath4 } from "node:url";
97907
98648
  var CLAUDE_PLUGIN_DIRS_ENV = "CLAUDE_CODE_PLUGIN_DIRS";
97908
98649
  var HASH_FILE = ".errata-mod-hash";
97909
98650
  function bundledClaudeModsDir() {
97910
98651
  const rel = import.meta.url.endsWith(".mjs") ? "./resources/claude-mods/" : "../claude-mods/";
97911
- return fileURLToPath3(new URL(rel, import.meta.url));
98652
+ return fileURLToPath4(new URL(rel, import.meta.url));
97912
98653
  }
97913
98654
  function isEngineOwned(relPath) {
97914
- const p = relPath.split(sep5).join("/");
98655
+ const p = relPath.split(sep6).join("/");
97915
98656
  return p === ".claude-plugin/types" || p.startsWith(".claude-plugin/types/") || p === HASH_FILE;
97916
98657
  }
97917
98658
  function listFiles(root, dir = root) {
97918
98659
  const out2 = [];
97919
98660
  for (const name2 of readdirSync15(dir)) {
97920
- const abs = join52(dir, name2);
97921
- if (isEngineOwned(relative8(root, abs))) continue;
97922
- if (statSync14(abs).isDirectory()) out2.push(...listFiles(root, abs));
98661
+ const abs = join55(dir, name2);
98662
+ if (isEngineOwned(relative7(root, abs))) continue;
98663
+ if (statSync15(abs).isDirectory()) out2.push(...listFiles(root, abs));
97923
98664
  else out2.push(abs);
97924
98665
  }
97925
98666
  return out2;
97926
98667
  }
97927
98668
  function modHash(dir) {
97928
- const h = createHash21("sha256");
98669
+ const h = createHash22("sha256");
97929
98670
  for (const abs of listFiles(dir).sort()) {
97930
- h.update(relative8(dir, abs).split(sep5).join("/"));
98671
+ h.update(relative7(dir, abs).split(sep6).join("/"));
97931
98672
  h.update("\0");
97932
- h.update(readFileSync44(abs));
98673
+ h.update(readFileSync47(abs));
97933
98674
  h.update("\0");
97934
98675
  }
97935
98676
  return h.digest("hex");
97936
98677
  }
97937
98678
  function bundledMods(bundleDir) {
97938
98679
  if (!existsSync39(bundleDir)) return [];
97939
- return readdirSync15(bundleDir).filter((name2) => existsSync39(join52(bundleDir, name2, ".claude-plugin", "plugin.json")));
98680
+ return readdirSync15(bundleDir).filter((name2) => existsSync39(join55(bundleDir, name2, ".claude-plugin", "plugin.json")));
97940
98681
  }
97941
98682
  function sameDir(a, b) {
97942
98683
  const norm = (p) => resolve9(p).replace(/[\\/]+$/, "").toLowerCase();
97943
98684
  return norm(a) === norm(b);
97944
98685
  }
97945
98686
  function isUnder(path3, root) {
97946
- const rel = relative8(resolve9(root), resolve9(path3));
98687
+ const rel = relative7(resolve9(root), resolve9(path3));
97947
98688
  return rel !== "" && !rel.startsWith("..") && !rel.includes(":");
97948
98689
  }
97949
98690
  function off(env2) {
@@ -97953,7 +98694,7 @@ function off(env2) {
97953
98694
  function readSettings(path3) {
97954
98695
  if (!existsSync39(path3)) return {};
97955
98696
  try {
97956
- const parsed = JSON.parse(readFileSync44(path3, "utf8"));
98697
+ const parsed = JSON.parse(readFileSync47(path3, "utf8"));
97957
98698
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null;
97958
98699
  return parsed;
97959
98700
  } catch {
@@ -97977,13 +98718,13 @@ function currentDirs(settings) {
97977
98718
  return raw2.split(delimiter2).map((s) => s.trim()).filter(Boolean);
97978
98719
  }
97979
98720
  function writeSettings(path3, settings) {
97980
- mkdirSync12(dirname18(path3), { recursive: true });
97981
- writeFileSync32(path3, JSON.stringify(settings, null, 2) + "\n", "utf8");
98721
+ mkdirSync12(dirname19(path3), { recursive: true });
98722
+ writeFileSync33(path3, JSON.stringify(settings, null, 2) + "\n", "utf8");
97982
98723
  }
97983
98724
  function ensureClaudeMods(opts) {
97984
98725
  const env2 = opts.env ?? process.env;
97985
98726
  const settingsPath = opts.userSettingsPath ?? userClaudeSettingsPath();
97986
- const modsRoot = join52(opts.installRoot, "claude-mods");
98727
+ const modsRoot = join55(opts.installRoot, "claude-mods");
97987
98728
  if (off(env2)) {
97988
98729
  const settings2 = readSettings(settingsPath);
97989
98730
  if (!settings2) return { kind: "unreadable" };
@@ -98000,14 +98741,14 @@ function ensureClaudeMods(opts) {
98000
98741
  let changed = false;
98001
98742
  const installed = [];
98002
98743
  for (const name2 of names) {
98003
- const src = join52(bundleDir, name2);
98004
- const dest = join52(modsRoot, name2);
98744
+ const src = join55(bundleDir, name2);
98745
+ const dest = join55(modsRoot, name2);
98005
98746
  const hash2 = modHash(src);
98006
- const hashFile = join52(dest, HASH_FILE);
98007
- if (!existsSync39(hashFile) || readFileSync44(hashFile, "utf8") !== hash2) {
98747
+ const hashFile = join55(dest, HASH_FILE);
98748
+ if (!existsSync39(hashFile) || readFileSync47(hashFile, "utf8") !== hash2) {
98008
98749
  rmSync4(dest, { recursive: true, force: true });
98009
- cpSync3(src, dest, { recursive: true, filter: (p) => !isEngineOwned(relative8(src, p)) });
98010
- writeFileSync32(hashFile, hash2, "utf8");
98750
+ cpSync3(src, dest, { recursive: true, filter: (p) => !isEngineOwned(relative7(src, p)) });
98751
+ writeFileSync33(hashFile, hash2, "utf8");
98011
98752
  changed = true;
98012
98753
  }
98013
98754
  installed.push(dest);
@@ -98426,9 +99167,9 @@ function resolveHookPort(explicit) {
98426
99167
  }
98427
99168
  }
98428
99169
  }
98429
- const settingsPath = join53(ROOT, ".claude", "settings.json");
99170
+ const settingsPath = join56(ROOT, ".claude", "settings.json");
98430
99171
  try {
98431
- if (existsSync40(settingsPath)) return installedHookPort(readFileSync45(settingsPath, "utf8")) ?? 7891;
99172
+ if (existsSync40(settingsPath)) return installedHookPort(readFileSync48(settingsPath, "utf8")) ?? 7891;
98432
99173
  } catch {
98433
99174
  }
98434
99175
  return 7891;
@@ -98454,13 +99195,13 @@ async function cmdInit() {
98454
99195
  console.log("");
98455
99196
  console.log("installing harness hooks...");
98456
99197
  const { existsSync: existsSync41 } = await import("node:fs");
98457
- const { join: join54 } = await import("node:path");
99198
+ const { join: join57 } = await import("node:path");
98458
99199
  try {
98459
99200
  await installClaudeHooks(port);
98460
99201
  } catch (err2) {
98461
99202
  console.warn(` \u26A0\uFE0F Claude hook install failed: ${err2 instanceof Error ? err2.message : err2}`);
98462
99203
  }
98463
- if (existsSync41(join54(ROOT, ".cursor"))) {
99204
+ if (existsSync41(join57(ROOT, ".cursor"))) {
98464
99205
  try {
98465
99206
  await installCursorMcpConfig();
98466
99207
  } catch (err2) {
@@ -99683,7 +100424,7 @@ async function cmdReview() {
99683
100424
  console.log("(review queue empty)");
99684
100425
  return;
99685
100426
  }
99686
- const queue = JSON.parse(readFileSync45(paths.reviewQueue, "utf8"));
100427
+ const queue = JSON.parse(readFileSync48(paths.reviewQueue, "utf8"));
99687
100428
  if (queue.length === 0) {
99688
100429
  console.log("(review queue empty)");
99689
100430
  return;
@@ -100422,7 +101163,7 @@ async function gatherReportData(generatedAt) {
100422
101163
  };
100423
101164
  }
100424
101165
  async function cmdReport(args2) {
100425
- const { mkdirSync: mkdirSync13, writeFileSync: writeFileSync33 } = await import("node:fs");
101166
+ const { mkdirSync: mkdirSync13, writeFileSync: writeFileSync34 } = await import("node:fs");
100426
101167
  const { renderReport: renderReport2 } = await Promise.resolve().then(() => (init_report_render(), report_render_exports));
100427
101168
  const includeFutureVerbs = args2.includes("--future-verbs");
100428
101169
  const now = /* @__PURE__ */ new Date();
@@ -100435,8 +101176,8 @@ async function cmdReport(args2) {
100435
101176
  const outDir = workspacePaths(ROOT).configDir;
100436
101177
  mkdirSync13(outDir, { recursive: true });
100437
101178
  const files = renderReport2(data, { includeFutureVerbs });
100438
- for (const f of files) writeFileSync33(join53(outDir, f.name), f.html, "utf8");
100439
- const indexPath = join53(outDir, "report.html");
101179
+ for (const f of files) writeFileSync34(join56(outDir, f.name), f.html, "utf8");
101180
+ const indexPath = join56(outDir, "report.html");
100440
101181
  console.log(`report \u2192 ${indexPath}`);
100441
101182
  console.log(
100442
101183
  ` ${data.repos.length} repo(s) \xB7 ${files.length} file(s) \xB7 ${data.rollup.nodes.toLocaleString("en-US")} nodes`
@@ -100492,7 +101233,7 @@ function spawnDaemonDetached(options = {}) {
100492
101233
  try {
100493
101234
  const logPath = daemonLogPath();
100494
101235
  try {
100495
- if (statSync15(logPath).size > 5 * 1024 * 1024) renameSync9(logPath, `${logPath}.1`);
101236
+ if (statSync16(logPath).size > 5 * 1024 * 1024) renameSync10(logPath, `${logPath}.1`);
100496
101237
  } catch {
100497
101238
  }
100498
101239
  out2 = openSync3(logPath, "a");
@@ -100561,24 +101302,24 @@ async function cmdInstallHooks(args2) {
100561
101302
  }
100562
101303
  }
100563
101304
  async function installOpencodePlugin(port) {
100564
- const { mkdirSync: mkdirSync13, existsSync: existsSync41, readFileSync: readFileSync46, writeFileSync: writeFileSync33 } = await import("node:fs");
100565
- const { join: join54 } = await import("node:path");
100566
- const dir = join54(ROOT, ".opencode", "plugin");
101305
+ const { mkdirSync: mkdirSync13, existsSync: existsSync41, readFileSync: readFileSync49, writeFileSync: writeFileSync34 } = await import("node:fs");
101306
+ const { join: join57 } = await import("node:path");
101307
+ const dir = join57(ROOT, ".opencode", "plugin");
100567
101308
  if (!existsSync41(dir)) mkdirSync13(dir, { recursive: true });
100568
- const file2 = join54(dir, "inerrata.js");
101309
+ const file2 = join57(dir, "inerrata.js");
100569
101310
  if (existsSync41(file2)) {
100570
- const head2 = readFileSync46(file2, "utf8").split("\n")[0] ?? "";
101311
+ const head2 = readFileSync49(file2, "utf8").split("\n")[0] ?? "";
100571
101312
  if (head2.trim() !== OPENCODE_PLUGIN_MARKER) {
100572
101313
  console.error(`refusing to overwrite ${file2}: not an errata-managed plugin (line 1 lacks the marker)`);
100573
101314
  process.exit(2);
100574
101315
  }
100575
101316
  }
100576
- writeFileSync33(file2, buildOpencodePluginSource(port, { version: DAEMON_VERSION }), "utf8");
100577
- const cfgFile = join54(ROOT, "opencode.json");
101317
+ writeFileSync34(file2, buildOpencodePluginSource(port, { version: DAEMON_VERSION }), "utf8");
101318
+ const cfgFile = join57(ROOT, "opencode.json");
100578
101319
  let cfg = { $schema: "https://opencode.ai/config.json" };
100579
101320
  if (existsSync41(cfgFile)) {
100580
101321
  try {
100581
- cfg = JSON.parse(readFileSync46(cfgFile, "utf8"));
101322
+ cfg = JSON.parse(readFileSync49(cfgFile, "utf8"));
100582
101323
  } catch {
100583
101324
  console.error(`refusing to touch invalid JSON at ${cfgFile} \u2014 fix it and re-run`);
100584
101325
  process.exit(2);
@@ -100589,7 +101330,7 @@ async function installOpencodePlugin(port) {
100589
101330
  if (!hadErrata) {
100590
101331
  const inv = errataMcpInvocation();
100591
101332
  cfg.mcp["errata"] = { type: "local", command: [inv.command, ...inv.args] };
100592
- writeFileSync33(cfgFile, JSON.stringify(cfg, null, 2) + "\n", "utf8");
101333
+ writeFileSync34(cfgFile, JSON.stringify(cfg, null, 2) + "\n", "utf8");
100593
101334
  }
100594
101335
  console.log(`installed OpenCode plugin \u2192 ${file2}`);
100595
101336
  if (hadErrata) console.log(` mcp.errata already present in ${cfgFile} \u2014 left untouched`);
@@ -100624,15 +101365,15 @@ function installClaudeMods() {
100624
101365
  }
100625
101366
  }
100626
101367
  async function installClaudeHooks(port) {
100627
- const { mkdirSync: mkdirSync13, existsSync: existsSync41, readFileSync: readFileSync46, writeFileSync: writeFileSync33 } = await import("node:fs");
100628
- const { join: join54 } = await import("node:path");
100629
- const dir = join54(ROOT, ".claude");
101368
+ const { mkdirSync: mkdirSync13, existsSync: existsSync41, readFileSync: readFileSync49, writeFileSync: writeFileSync34 } = await import("node:fs");
101369
+ const { join: join57 } = await import("node:path");
101370
+ const dir = join57(ROOT, ".claude");
100630
101371
  if (!existsSync41(dir)) mkdirSync13(dir, { recursive: true });
100631
- const file2 = join54(dir, "settings.json");
101372
+ const file2 = join57(dir, "settings.json");
100632
101373
  let settings = {};
100633
101374
  if (existsSync41(file2)) {
100634
101375
  try {
100635
- settings = JSON.parse(readFileSync46(file2, "utf8"));
101376
+ settings = JSON.parse(readFileSync49(file2, "utf8"));
100636
101377
  } catch {
100637
101378
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
100638
101379
  process.exit(2);
@@ -100681,12 +101422,12 @@ async function installClaudeHooks(port) {
100681
101422
  list.push({ hooks: [{ type: "command", command: injectCmd }] });
100682
101423
  }
100683
101424
  removeProjectStatusLine(settings);
100684
- writeFileSync33(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
101425
+ writeFileSync34(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
100685
101426
  console.log(`installed Claude Code hooks \u2192 ${file2}`);
100686
101427
  console.log(` ${ensureStatusLine(port)}`);
100687
101428
  console.log(` ${installClaudeMods().line}`);
100688
101429
  await installClaudeMcpConfig();
100689
- const claudeMd = join54(ROOT, "CLAUDE.md");
101430
+ const claudeMd = join57(ROOT, "CLAUDE.md");
100690
101431
  const recall = writeManagedBlock(claudeMd, { body: RECALL_FIRST_BLOCK });
100691
101432
  if (recall.kind === "collision") {
100692
101433
  console.warn(
@@ -100698,15 +101439,15 @@ async function installClaudeHooks(port) {
100698
101439
  console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
100699
101440
  }
100700
101441
  async function installClaudeMcpConfig() {
100701
- const { mkdirSync: mkdirSync13, existsSync: existsSync41, readFileSync: readFileSync46, writeFileSync: writeFileSync33 } = await import("node:fs");
100702
- const { join: join54, dirname: dirname19 } = await import("node:path");
100703
- const file2 = join54(ROOT, ".mcp.json");
100704
- const dir = dirname19(file2);
101442
+ const { mkdirSync: mkdirSync13, existsSync: existsSync41, readFileSync: readFileSync49, writeFileSync: writeFileSync34 } = await import("node:fs");
101443
+ const { join: join57, dirname: dirname20 } = await import("node:path");
101444
+ const file2 = join57(ROOT, ".mcp.json");
101445
+ const dir = dirname20(file2);
100705
101446
  if (!existsSync41(dir)) mkdirSync13(dir, { recursive: true });
100706
101447
  let cfg = {};
100707
101448
  if (existsSync41(file2)) {
100708
101449
  try {
100709
- cfg = JSON.parse(readFileSync46(file2, "utf8"));
101450
+ cfg = JSON.parse(readFileSync49(file2, "utf8"));
100710
101451
  } catch {
100711
101452
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
100712
101453
  process.exit(2);
@@ -100714,21 +101455,21 @@ async function installClaudeMcpConfig() {
100714
101455
  }
100715
101456
  cfg.mcpServers ??= {};
100716
101457
  cfg.mcpServers["errata"] = errataMcpInvocation();
100717
- writeFileSync33(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
101458
+ writeFileSync34(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
100718
101459
  console.log(`installed Claude Code MCP server config \u2192 ${file2}`);
100719
101460
  console.log(` Claude Code will spawn \`errata mcp\` on workspace open.`);
100720
101461
  console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses / show / similar`);
100721
101462
  }
100722
101463
  async function installCursorMcpConfig() {
100723
- const { mkdirSync: mkdirSync13, existsSync: existsSync41, readFileSync: readFileSync46, writeFileSync: writeFileSync33 } = await import("node:fs");
100724
- const { join: join54 } = await import("node:path");
100725
- const dir = join54(ROOT, ".cursor");
101464
+ const { mkdirSync: mkdirSync13, existsSync: existsSync41, readFileSync: readFileSync49, writeFileSync: writeFileSync34 } = await import("node:fs");
101465
+ const { join: join57 } = await import("node:path");
101466
+ const dir = join57(ROOT, ".cursor");
100726
101467
  if (!existsSync41(dir)) mkdirSync13(dir, { recursive: true });
100727
- const file2 = join54(dir, "mcp.json");
101468
+ const file2 = join57(dir, "mcp.json");
100728
101469
  let cfg = {};
100729
101470
  if (existsSync41(file2)) {
100730
101471
  try {
100731
- cfg = JSON.parse(readFileSync46(file2, "utf8"));
101472
+ cfg = JSON.parse(readFileSync49(file2, "utf8"));
100732
101473
  } catch {
100733
101474
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
100734
101475
  process.exit(2);
@@ -100736,7 +101477,7 @@ async function installCursorMcpConfig() {
100736
101477
  }
100737
101478
  cfg.mcpServers ??= {};
100738
101479
  cfg.mcpServers["errata"] = errataMcpInvocation();
100739
- writeFileSync33(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
101480
+ writeFileSync34(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
100740
101481
  console.log(`installed Cursor MCP server config \u2192 ${file2}`);
100741
101482
  console.log(` Cursor will spawn \`errata mcp\` on workspace open.`);
100742
101483
  console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses`);
@@ -100747,7 +101488,7 @@ async function installCodexHooks(port) {
100747
101488
  const gitRoot = nearestGitRoot(process.cwd());
100748
101489
  const hookRoot = gitRoot && mainCheckoutOfWorktree(gitRoot) ? gitRoot : ROOT;
100749
101490
  const file2 = writeCodexHooks(hookRoot, port);
100750
- const instructions = writeManagedBlock(join53(hookRoot, "AGENTS.md"), {
101491
+ const instructions = writeManagedBlock(join56(hookRoot, "AGENTS.md"), {
100751
101492
  body: AGENTS_POINTER_BODY,
100752
101493
  stable: true
100753
101494
  });
@@ -101193,9 +101934,9 @@ async function cmdDash(args2) {
101193
101934
  await yieldToLoop2();
101194
101935
  try {
101195
101936
  const items = selectDurableMemory(handle2.sharedStore, r.engine.profile, {
101196
- atCommit: readGitRefState(join53(r.root, ".git")).sha ?? void 0
101937
+ atCommit: readGitRefState(join56(r.root, ".git")).sha ?? void 0
101197
101938
  });
101198
- const res = bleedRules(join53(r.root, ".claude", "rules"), items);
101939
+ const res = bleedRules(join56(r.root, ".claude", "rules"), items);
101199
101940
  if (res.written || res.pruned) {
101200
101941
  console.log(
101201
101942
  `[rules:${r.entry.name}] ${res.written} collective principle(s) \u2192 .claude/rules` + (res.pruned ? `, ${res.pruned} pruned` : "")