@inerrata-corporation/errata 2.0.17-dev.3416 → 2.0.17-dev.3426

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
@@ -960,7 +960,7 @@ function lemma(token) {
960
960
  }
961
961
  return token;
962
962
  }
963
- function tokenize(text, resolve8) {
963
+ function tokenize(text, resolve9) {
964
964
  const matches = text.normalize("NFC").toLowerCase().match(TOKEN_RE) ?? [];
965
965
  const out2 = /* @__PURE__ */ new Set();
966
966
  for (const raw2 of matches) {
@@ -970,7 +970,7 @@ function tokenize(text, resolve8) {
970
970
  out2.add(token);
971
971
  continue;
972
972
  }
973
- const canonical = resolve8(token);
973
+ const canonical = resolve9(token);
974
974
  out2.add(canonical ?? lemma(token));
975
975
  }
976
976
  return [...out2].sort();
@@ -21903,6 +21903,24 @@ function parseIntentFences(text) {
21903
21903
  }
21904
21904
  return out2;
21905
21905
  }
21906
+ function parseShareFence(text) {
21907
+ const m = /```errata-share[^\n]*\n([\s\S]*?)```/.exec(text);
21908
+ if (!m) return null;
21909
+ const parts2 = [];
21910
+ for (const line of m[1].split(/\r?\n/)) {
21911
+ const kv = /^\s*priors\s*:\s*(.*?)\s*$/i.exec(line);
21912
+ if (kv) parts2.push(kv[1]);
21913
+ else if (parts2.length > 0 && line.trim()) parts2.push(line.trim());
21914
+ }
21915
+ const value = parts2.join(" ").trim();
21916
+ if (/^all$/i.test(value)) return { all: true };
21917
+ const priors = [
21918
+ ...new Set(
21919
+ value.split(/[\s,]+/).map((t) => t.replace(/^[`([]+|[`)\]]+$/g, "")).filter((t) => /^[\w.:-]+$/.test(t))
21920
+ )
21921
+ ];
21922
+ return priors.length > 0 ? { all: false, priors } : null;
21923
+ }
21906
21924
  function searchByIntent(store, intent, opts) {
21907
21925
  const limit = opts?.limit ?? 5;
21908
21926
  const minCoverage = opts?.minCoverage ?? DEFAULT_MIN_COVERAGE;
@@ -25010,6 +25028,7 @@ __export(src_exports2, {
25010
25028
  parseAbstractionFences: () => parseAbstractionFences,
25011
25029
  parseIntentFences: () => parseIntentFences,
25012
25030
  parseSemver: () => parseSemver,
25031
+ parseShareFence: () => parseShareFence,
25013
25032
  parseTriageFences: () => parseTriageFences,
25014
25033
  pendingAbstractions: () => pendingAbstractions,
25015
25034
  pendingDiscriminators: () => pendingDiscriminators,
@@ -25100,11 +25119,13 @@ function buildSnapshot(opts) {
25100
25119
  const stillOpen = problems.filter((p) => p.attrs["resolvedAt"] == null);
25101
25120
  const allProblems = stillOpen.filter((p) => !isConstraintProblem(p));
25102
25121
  allProblems.sort((a, b) => b.lastUpdatedAt - a.lastUpdatedAt);
25103
- const recent3 = allProblems.slice(0, 8).map((p) => ({
25122
+ const openPool = allProblems.slice(0, RECENT_OPEN * SCOPE_POOL_FACTOR).map((p) => ({
25104
25123
  node: p,
25105
25124
  anchors: opts.store.outEdges(p.id, ["MANIFESTED_IN", "EVIDENCED_BY"])
25106
25125
  }));
25107
- const recentConstraints = stillOpen.filter((p) => isConstraintProblem(p)).sort((a, b) => b.lastUpdatedAt - a.lastUpdatedAt).slice(0, 3);
25126
+ const recent3 = openPool.slice(0, RECENT_OPEN);
25127
+ const constraintPool = stillOpen.filter((p) => isConstraintProblem(p)).sort((a, b) => b.lastUpdatedAt - a.lastUpdatedAt).slice(0, RECENT_CONSTRAINTS * SCOPE_POOL_FACTOR);
25128
+ const recentConstraints = constraintPool.slice(0, RECENT_CONSTRAINTS);
25108
25129
  const regressions = problems.filter((p) => p.attrs["resolvedAt"] == null && p.attrs["mergedInto"] === void 0).flatMap(
25109
25130
  (open2) => opts.store.outEdges(open2.id, ["REGRESSION_OF"]).flatMap((e) => {
25110
25131
  const closed = opts.store.getNode(e.to);
@@ -25117,11 +25138,12 @@ function buildSnapshot(opts) {
25117
25138
  })
25118
25139
  ).sort((a, b) => Number(b.closed.attrs["recurredAt"] ?? 0) - Number(a.closed.attrs["recurredAt"] ?? 0)).slice(0, 2);
25119
25140
  const regressionClosedIds = new Set(regressions.map((r) => r.closed.id));
25120
- const recentResolved = problems.filter((p) => p.attrs["resolvedAt"] != null && p.attrs["resolvedAs"] == null).filter((p) => !regressionClosedIds.has(p.id)).sort((a, b) => Number(b.attrs["resolvedAt"] ?? 0) - Number(a.attrs["resolvedAt"] ?? 0)).slice(0, 4).map((p) => {
25141
+ const resolvedPool = problems.filter((p) => p.attrs["resolvedAt"] != null && p.attrs["resolvedAs"] == null).filter((p) => !regressionClosedIds.has(p.id)).sort((a, b) => Number(b.attrs["resolvedAt"] ?? 0) - Number(a.attrs["resolvedAt"] ?? 0)).slice(0, RECENT_RESOLVED * SCOPE_POOL_FACTOR).map((p) => {
25121
25142
  const solEdge = opts.store.outEdges(p.id, ["SOLVED_BY"])[0];
25122
25143
  const solution = solEdge ? opts.store.getNode(solEdge.to) ?? void 0 : void 0;
25123
25144
  return { node: p, ...solution ? { solution } : {} };
25124
25145
  });
25146
+ const recentResolved = resolvedPool.slice(0, RECENT_RESOLVED);
25125
25147
  const motifs = [
25126
25148
  ...opts.store.findNodesByLabel("Pattern"),
25127
25149
  ...opts.store.findNodesByLabel("Technique"),
@@ -25199,9 +25221,23 @@ function buildSnapshot(opts) {
25199
25221
  pendingEnrichment,
25200
25222
  skills: opts.skills ?? [],
25201
25223
  needsRevisit,
25224
+ scopePool: { open: openPool, resolved: resolvedPool, constraints: constraintPool },
25202
25225
  generatedAt: (opts.now ?? /* @__PURE__ */ new Date()).toISOString()
25203
25226
  };
25204
25227
  }
25228
+ function scopeSnapshot(s, keep) {
25229
+ const pool = s.scopePool;
25230
+ if (!pool) return s;
25231
+ const open2 = pool.open.filter((r) => keep(r.node));
25232
+ return {
25233
+ ...s,
25234
+ recentProblems: open2.slice(0, RECENT_OPEN),
25235
+ recentResolved: pool.resolved.filter((r) => keep(r.node)).slice(0, RECENT_RESOLVED),
25236
+ recentConstraints: pool.constraints.filter(keep).slice(0, RECENT_CONSTRAINTS),
25237
+ regressions: s.regressions.filter((r) => keep(r.open)),
25238
+ scopePool: { ...pool, open: open2 }
25239
+ };
25240
+ }
25205
25241
  function sliceForFile(store, relPath, atCommit) {
25206
25242
  const candidates = store.findNodesByLabel("File");
25207
25243
  const file2 = candidates.find((n) => n.description === relPath);
@@ -25292,6 +25328,8 @@ function renderSnapshot(s) {
25292
25328
  lines.push(SEARCH_IMPERATIVE_HEADER);
25293
25329
  lines.push(SEARCH_IMPERATIVE_BODY);
25294
25330
  lines.push("");
25331
+ lines.push(s.isolated ? SUBAGENT_OWN_BLOCK_NOTE : SPAWN_SHARE_HINT);
25332
+ lines.push("");
25295
25333
  lines.push(`### Active workspace profile`);
25296
25334
  lines.push(`- **Name:** ${s.profile.name}`);
25297
25335
  const ctxName = (name2) => name2.startsWith("@") ? `\`${name2}\`` : name2;
@@ -25469,6 +25507,12 @@ function renderSnapshot(s) {
25469
25507
  }
25470
25508
  lines.push("");
25471
25509
  }
25510
+ if (s.sharedPriors?.length) {
25511
+ lines.push(`### \u{1F91D} Handed to you by the agent that spawned you`);
25512
+ lines.push("_It chose these for your task \u2014 cite one with its `[handle]` if you lean on it:_");
25513
+ for (const n of s.sharedPriors) lines.push(`- **${n.label}:** ${n.description}${tagOf(n)}`);
25514
+ lines.push("");
25515
+ }
25472
25516
  if (s.statedIntent) {
25473
25517
  const si = s.statedIntent;
25474
25518
  lines.push(`### \u{1F3AF} You said you're working on this`);
@@ -25650,6 +25694,35 @@ function budgetSnapshot(s, maxChars) {
25650
25694
  while (renderSnapshot(s).length > maxChars && dropLowestUnit(s)) dropped++;
25651
25695
  return dropped;
25652
25696
  }
25697
+ function isolateSnapshot(s) {
25698
+ const {
25699
+ workingFile: _workingFile,
25700
+ statedIntent: _statedIntent,
25701
+ selfCiteSkips: _selfCiteSkips,
25702
+ pendingUpdate: _pendingUpdate,
25703
+ daemonDistress: _daemonDistress,
25704
+ reviewItems: _reviewItems,
25705
+ causalNudge: _causalNudge,
25706
+ domainNudge: _domainNudge,
25707
+ sharedPriors: _sharedPriors,
25708
+ scopePool: _scopePool,
25709
+ ...graphWide
25710
+ } = s;
25711
+ return {
25712
+ ...graphWide,
25713
+ isolated: true,
25714
+ recentProblems: [],
25715
+ recentResolved: [],
25716
+ regressions: [],
25717
+ recentConstraints: [],
25718
+ pendingEnrichment: [],
25719
+ needsRevisit: [],
25720
+ reviewCount: 0,
25721
+ motifs: [...s.motifs],
25722
+ skills: [...s.skills],
25723
+ ...s.remote ? { remote: [...s.remote] } : {}
25724
+ };
25725
+ }
25653
25726
  function assembleAgentContext(opts) {
25654
25727
  const snapshot = opts.snapshot ?? buildSnapshot({
25655
25728
  store: opts.store,
@@ -25666,6 +25739,7 @@ function assembleAgentContext(opts) {
25666
25739
  if (opts.daemonDistress) snapshot.daemonDistress = opts.daemonDistress;
25667
25740
  if (opts.reviewItems?.length) snapshot.reviewItems = [...opts.reviewItems];
25668
25741
  if (opts.statedIntent) snapshot.statedIntent = opts.statedIntent;
25742
+ if (opts.sharedPriors?.length) snapshot.sharedPriors = [...opts.sharedPriors];
25669
25743
  if (opts.remote && opts.remote.length > 0) {
25670
25744
  const seen = /* @__PURE__ */ new Set();
25671
25745
  const remote = opts.remote.filter((n) => {
@@ -25717,13 +25791,17 @@ function diffRenderLedger(before, after) {
25717
25791
  for (const i2 of before) (survived.has(key(i2)) ? shown : evicted).push(i2);
25718
25792
  return { shown, evicted };
25719
25793
  }
25720
- var RECALL_FIRST_HEADER, RECALL_FIRST_BODY, RECALL_FIRST_BLOCK, SEARCH_IMPERATIVE_HEADER, SEARCH_IMPERATIVE_BODY, EVICTION_ORDER, MOTIF_FLOOR, REMOTE_FLOOR, PROBLEM_FLOOR, REVIEW_ITEM_FLOOR, DEFAULT_AGENT_CONTEXT_BUDGET;
25794
+ var RECENT_OPEN, RECENT_RESOLVED, RECENT_CONSTRAINTS, SCOPE_POOL_FACTOR, RECALL_FIRST_HEADER, RECALL_FIRST_BODY, RECALL_FIRST_BLOCK, SEARCH_IMPERATIVE_HEADER, SEARCH_IMPERATIVE_BODY, SPAWN_SHARE_HINT, SUBAGENT_OWN_BLOCK_NOTE, EVICTION_ORDER, MOTIF_FLOOR, REMOTE_FLOOR, PROBLEM_FLOOR, REVIEW_ITEM_FLOOR, DEFAULT_AGENT_CONTEXT_BUDGET;
25721
25795
  var init_render = __esm({
25722
25796
  "../../packages/context-writer/src/render.ts"() {
25723
25797
  "use strict";
25724
25798
  init_src5();
25725
25799
  init_src2();
25726
25800
  init_src();
25801
+ RECENT_OPEN = 8;
25802
+ RECENT_RESOLVED = 4;
25803
+ RECENT_CONSTRAINTS = 3;
25804
+ SCOPE_POOL_FACTOR = 3;
25727
25805
  RECALL_FIRST_HEADER = "## errata \u2014 recall before you work";
25728
25806
  RECALL_FIRST_BODY = "Before investigating any bug or error, your FIRST tool call must be `mcp__errata__errata_search` with a few words describing the problem. This machine's knowledge graph records previously solved problems \u2014 the answer may already be recorded. Read what it returns before touching any files.";
25729
25807
  RECALL_FIRST_BLOCK = `${RECALL_FIRST_HEADER}
@@ -25731,6 +25809,8 @@ var init_render = __esm({
25731
25809
  ${RECALL_FIRST_BODY}`;
25732
25810
  SEARCH_IMPERATIVE_HEADER = "### \u{1F50E} PRIORS ARE SEEDS \u2014 a sample, not the whole graph";
25733
25811
  SEARCH_IMPERATIVE_BODY = "Everything below is a budgeted slice of a much larger graph, not all errata knows. Starting a piece of work? Say what it is \u2014 we search on it between your tool calls and put what we find here:\n```errata-intent\nintent: <the work in hand, in your words>\n```\nNarration, not a detour: no tool call, no plan change. It is the one signal we cannot derive from your edits \u2014 everything else here is guessed from the files you touched.";
25812
+ SPAWN_SHARE_HINT = "_Spawning a subagent? It gets its own errata block, seeded from its task \u2014 none of the priors here. To hand it some, put this in its prompt (or `priors: all` for this whole block):_\n```errata-share\npriors: [handle], [handle]\n```";
25813
+ SUBAGENT_OWN_BLOCK_NOTE = "_This block is yours: seeded from the task you were given, then from what you state and touch. The agent that spawned you sees a different one._";
25734
25814
  EVICTION_ORDER = [
25735
25815
  "skills",
25736
25816
  // Review items beyond the floor drop immediately after skills — one naming
@@ -32004,6 +32084,9 @@ function errorCardHeadline(items) {
32004
32084
  const fixes = items.filter((it) => it.label === "Solution").length;
32005
32085
  return fixes > 0 ? `${plural(fixes, "known fix", "known fixes")} for this error` : `${plural(items.length, "prior")} for this error`;
32006
32086
  }
32087
+ function forSubagent(card, agentType) {
32088
+ return { ...card, headline: `\u21B3 ${agentType || "subagent"} \xB7 ${card.headline}` };
32089
+ }
32007
32090
  function leadItem(card) {
32008
32091
  return card.chain?.fix ?? card.items.find((it) => it.label === "Solution") ?? card.single ?? card.items[0];
32009
32092
  }
@@ -32083,6 +32166,29 @@ function rememberCard(sessionId, card, now = Date.now(), since = now) {
32083
32166
  if (current && current.at > since) return;
32084
32167
  remember(latestBySession, sessionId, { card, at: now });
32085
32168
  }
32169
+ function rememberAgentCard(sessionId, agentId, card, now = Date.now()) {
32170
+ if (!sessionId || !agentId) return;
32171
+ remember(latestByAgent, agentKey(sessionId, agentId), { card, at: now });
32172
+ }
32173
+ function subagentRows(body2, now = Date.now()) {
32174
+ const sessionId = typeof body2["session_id"] === "string" ? body2["session_id"] : "";
32175
+ const tasks = Array.isArray(body2["tasks"]) ? body2["tasks"] : [];
32176
+ const columns = typeof body2["columns"] === "number" && body2["columns"] > 20 ? body2["columns"] : 100;
32177
+ const lines = [];
32178
+ for (const task of tasks) {
32179
+ const id = typeof task["id"] === "string" ? task["id"] : "";
32180
+ const hit = id ? latestByAgent.get(agentKey(sessionId, id)) : void 0;
32181
+ if (!hit || now - hit.at > SUBAGENT_ROW_TTL_MS) continue;
32182
+ const lead2 = leadItem(hit.card);
32183
+ const title = String(task["description"] ?? task["label"] ?? "").trim();
32184
+ const plain = clip(
32185
+ `${title ? `${title} \xB7 ` : ""}\u26A1 errata \xB7 ${hit.card.headline}${lead2 ? ` \u2014 ${labelName(lead2.label)}: ${lead2.text}` : ""}`,
32186
+ columns - 2
32187
+ );
32188
+ lines.push(JSON.stringify({ id, content: plain.replace("\u26A1", `${AMBER}\u26A1${RESET}`) }));
32189
+ }
32190
+ return lines.join("\n");
32191
+ }
32086
32192
  function rememberOpenCount(sessionId, open2) {
32087
32193
  if (sessionId) remember(openBySession, sessionId, open2);
32088
32194
  }
@@ -32105,7 +32211,7 @@ function recallCardEnabled(env2 = process.env) {
32105
32211
  const v = (env2["ERRATA_RECALL_CARD"] ?? "").trim().toLowerCase();
32106
32212
  return !(v === "0" || v === "off" || v === "false" || v === "no");
32107
32213
  }
32108
- var LABEL_NAMES, INLINE_TEXT_WIDTH, ESC, RESET, DIM, BOLD, AMBER, MADDER, GREEN, INK, STATUS_ROWS, STATUS_TEXT_WIDTH, LABEL_WIDTH, STATUS_CARD_TTL_MS, IDLE_STATUS, latestBySession, MAX_SESSIONS, openBySession;
32214
+ var LABEL_NAMES, INLINE_TEXT_WIDTH, ESC, RESET, DIM, BOLD, AMBER, MADDER, GREEN, INK, STATUS_ROWS, STATUS_TEXT_WIDTH, LABEL_WIDTH, STATUS_CARD_TTL_MS, IDLE_STATUS, latestBySession, MAX_SESSIONS, latestByAgent, agentKey, SUBAGENT_ROW_TTL_MS, openBySession;
32109
32215
  var init_recall_card = __esm({
32110
32216
  "src/recall-card.ts"() {
32111
32217
  "use strict";
@@ -32129,6 +32235,9 @@ var init_recall_card = __esm({
32129
32235
  IDLE_STATUS = `${AMBER}\u26A1${RESET} ${DIM}errata \xB7 watching${RESET}`;
32130
32236
  latestBySession = /* @__PURE__ */ new Map();
32131
32237
  MAX_SESSIONS = 256;
32238
+ latestByAgent = /* @__PURE__ */ new Map();
32239
+ agentKey = (sessionId, agentId) => `${sessionId}#${agentId}`;
32240
+ SUBAGENT_ROW_TTL_MS = 30 * 6e4;
32132
32241
  openBySession = /* @__PURE__ */ new Map();
32133
32242
  }
32134
32243
  });
@@ -32243,18 +32352,141 @@ var init_recall_signal = __esm({
32243
32352
  }
32244
32353
  });
32245
32354
 
32355
+ // src/session-registry.ts
32356
+ import { existsSync as existsSync8, readFileSync as readFileSync6, realpathSync, writeFileSync as writeFileSync7 } from "node:fs";
32357
+ import { tmpdir as tmpdir2 } from "node:os";
32358
+ import { resolve } from "node:path";
32359
+ function shipsFromWorkspace(root, env2 = process.env) {
32360
+ return Boolean(env2["VITEST"]) || !isScratchWorkspace(root);
32361
+ }
32362
+ function isScratchWorkspace(root, tmp = tmpdir2()) {
32363
+ const norm = (p) => {
32364
+ let real = p;
32365
+ try {
32366
+ real = realpathSync.native(p);
32367
+ } catch {
32368
+ }
32369
+ return resolve(real).replace(/\\/g, "/").replace(/\/+$/, "").toLowerCase();
32370
+ };
32371
+ const r = norm(root);
32372
+ const t = norm(tmp);
32373
+ return r === t || r.startsWith(`${t}/`);
32374
+ }
32375
+ function parseOrigin(raw2) {
32376
+ if (typeof raw2 !== "string") return void 0;
32377
+ const v = raw2.trim();
32378
+ if (!v || v.includes("%")) return void 0;
32379
+ return /^[\w.:-]{1,64}$/.test(v) ? v : void 0;
32380
+ }
32381
+ function createSessionRegistry(opts = {}) {
32382
+ const idleMs = opts.idleMs ?? SESSION_IDLE_MS;
32383
+ const lastSeen = /* @__PURE__ */ new Map();
32384
+ const parentOf = /* @__PURE__ */ new Map();
32385
+ const ended = /* @__PURE__ */ new Set();
32386
+ const origins = new Map(loadOrigins(opts.originsPath));
32387
+ let ver = 0;
32388
+ let lastLiveCount = -1;
32389
+ const persist = () => {
32390
+ if (!opts.originsPath) return;
32391
+ try {
32392
+ while (origins.size > MAX_ORIGINS) origins.delete(origins.keys().next().value);
32393
+ writeFileSync7(opts.originsPath, JSON.stringify(Object.fromEntries(origins)));
32394
+ } catch {
32395
+ }
32396
+ };
32397
+ const ownLive = (id, nowMs) => {
32398
+ const seen = lastSeen.get(id);
32399
+ return seen !== void 0 && !ended.has(id) && nowMs - seen < idleMs;
32400
+ };
32401
+ const registry2 = {
32402
+ touch(sessionId, nowMs, o = {}) {
32403
+ if (!sessionId) return;
32404
+ const wasLive = ownLive(sessionId, nowMs);
32405
+ lastSeen.set(sessionId, nowMs);
32406
+ ended.delete(sessionId);
32407
+ if (o.parent) parentOf.set(sessionId, o.parent);
32408
+ const origin = o.origin ?? (o.parent ? origins.get(o.parent) : void 0);
32409
+ if (origin && origins.get(sessionId) !== origin) {
32410
+ origins.set(sessionId, origin);
32411
+ persist();
32412
+ ver++;
32413
+ }
32414
+ if (!wasLive) ver++;
32415
+ },
32416
+ end(sessionId) {
32417
+ if (!sessionId || ended.has(sessionId)) return;
32418
+ ended.add(sessionId);
32419
+ ver++;
32420
+ },
32421
+ isLive(sessionId, nowMs) {
32422
+ if (ownLive(sessionId, nowMs)) return true;
32423
+ const parent = parentOf.get(sessionId);
32424
+ return parent !== void 0 && ownLive(parent, nowMs);
32425
+ },
32426
+ originOf: (sessionId) => origins.get(sessionId) ?? origins.get(parentOf.get(sessionId) ?? ""),
32427
+ originSessions: () => [...origins.keys()],
32428
+ isOwn: (sessionId, viewer) => sessionId === viewer || parentOf.get(sessionId) === viewer,
32429
+ version(nowMs) {
32430
+ let live3 = 0;
32431
+ for (const id of lastSeen.keys()) if (ownLive(id, nowMs)) live3++;
32432
+ if (live3 !== lastLiveCount) {
32433
+ lastLiveCount = live3;
32434
+ ver++;
32435
+ }
32436
+ return ver;
32437
+ }
32438
+ };
32439
+ return registry2;
32440
+ }
32441
+ function loadOrigins(path2) {
32442
+ if (!path2 || !existsSync8(path2)) return [];
32443
+ try {
32444
+ const raw2 = JSON.parse(readFileSync6(path2, "utf8"));
32445
+ return Object.entries(raw2).flatMap(([k, v]) => typeof v === "string" ? [[k, v]] : []);
32446
+ } catch {
32447
+ return [];
32448
+ }
32449
+ }
32450
+ function sessionsOf(node2) {
32451
+ const s = node2.attrs["sources"];
32452
+ return Array.isArray(s) ? s.filter((x) => typeof x === "string" && x.length > 0) : [];
32453
+ }
32454
+ function capturedOnlyBy(node2, sessions) {
32455
+ const recorded = sessionsOf(node2);
32456
+ return recorded.length > 0 && recorded.every((s) => sessions.has(s));
32457
+ }
32458
+ function isQuarantined(node2, reg) {
32459
+ const sessions = sessionsOf(node2);
32460
+ return sessions.length > 0 && sessions.every((s) => reg.originOf(s) !== void 0);
32461
+ }
32462
+ function hiddenFrom(node2, viewer, reg, nowMs) {
32463
+ const sessions = sessionsOf(node2);
32464
+ if (sessions.length === 0 || sessions.some((s) => reg.isOwn(s, viewer))) return false;
32465
+ if (isQuarantined(node2, reg)) return true;
32466
+ return sessions.every((s) => reg.isLive(s, nowMs));
32467
+ }
32468
+ var ORIGIN_HEADER, SESSION_IDLE_MS, MAX_ORIGINS;
32469
+ var init_session_registry = __esm({
32470
+ "src/session-registry.ts"() {
32471
+ "use strict";
32472
+ ORIGIN_HEADER = "x-errata-origin";
32473
+ SESSION_IDLE_MS = 20 * 6e4;
32474
+ MAX_ORIGINS = 5e4;
32475
+ }
32476
+ });
32477
+
32246
32478
  // src/review.ts
32247
- import { existsSync as existsSync8, readFileSync as readFileSync6, writeFileSync as writeFileSync7 } from "node:fs";
32479
+ import { existsSync as existsSync9, readFileSync as readFileSync7, writeFileSync as writeFileSync8 } from "node:fs";
32248
32480
  function loadReviewQueue(paths) {
32249
- if (!existsSync8(paths.reviewQueue)) return [];
32481
+ if (!existsSync9(paths.reviewQueue)) return [];
32250
32482
  try {
32251
- return JSON.parse(readFileSync6(paths.reviewQueue, "utf8"));
32483
+ return JSON.parse(readFileSync7(paths.reviewQueue, "utf8"));
32252
32484
  } catch {
32253
32485
  return [];
32254
32486
  }
32255
32487
  }
32256
32488
  function saveReviewQueue(paths, queue) {
32257
- writeFileSync7(paths.reviewQueue, JSON.stringify(queue, null, 2), "utf8");
32489
+ writeFileSync8(paths.reviewQueue, JSON.stringify(queue, null, 2), "utf8");
32258
32490
  }
32259
32491
  function addProposal(paths, store, node2, reason, surprise) {
32260
32492
  const queue = loadReviewQueue(paths);
@@ -32324,26 +32556,26 @@ var init_consent = __esm({
32324
32556
  });
32325
32557
 
32326
32558
  // src/git-remote.ts
32327
- import { existsSync as existsSync9, readFileSync as readFileSync7, statSync } from "node:fs";
32328
- import { isAbsolute as isAbsolute2, join as join8, resolve } from "node:path";
32559
+ import { existsSync as existsSync10, readFileSync as readFileSync8, statSync } from "node:fs";
32560
+ import { isAbsolute as isAbsolute2, join as join8, resolve as resolve2 } from "node:path";
32329
32561
  function resolveGitDir(root) {
32330
32562
  const dotGit = join8(root, ".git");
32331
32563
  try {
32332
32564
  const st = statSync(dotGit);
32333
32565
  if (st.isDirectory()) return dotGit;
32334
- const m = /^gitdir:\s*(.+?)\s*$/m.exec(readFileSync7(dotGit, "utf8"));
32566
+ const m = /^gitdir:\s*(.+?)\s*$/m.exec(readFileSync8(dotGit, "utf8"));
32335
32567
  if (!m) return null;
32336
32568
  const dir = m[1];
32337
- return isAbsolute2(dir) ? dir : resolve(root, dir);
32569
+ return isAbsolute2(dir) ? dir : resolve2(root, dir);
32338
32570
  } catch {
32339
32571
  return null;
32340
32572
  }
32341
32573
  }
32342
32574
  function gitConfigPath(gitDir) {
32343
32575
  const commondirFile = join8(gitDir, "commondir");
32344
- if (existsSync9(commondirFile)) {
32345
- const common = readFileSync7(commondirFile, "utf8").trim();
32346
- const commonDir = isAbsolute2(common) ? common : resolve(gitDir, common);
32576
+ if (existsSync10(commondirFile)) {
32577
+ const common = readFileSync8(commondirFile, "utf8").trim();
32578
+ const commonDir = isAbsolute2(common) ? common : resolve2(gitDir, common);
32347
32579
  return join8(commonDir, "config");
32348
32580
  }
32349
32581
  return join8(gitDir, "config");
@@ -32352,10 +32584,10 @@ function readRemotes(root) {
32352
32584
  const gitDir = resolveGitDir(root);
32353
32585
  if (!gitDir) return [];
32354
32586
  const cfgPath = gitConfigPath(gitDir);
32355
- if (!existsSync9(cfgPath)) return [];
32587
+ if (!existsSync10(cfgPath)) return [];
32356
32588
  let txt;
32357
32589
  try {
32358
- txt = readFileSync7(cfgPath, "utf8");
32590
+ txt = readFileSync8(cfgPath, "utf8");
32359
32591
  } catch {
32360
32592
  return [];
32361
32593
  }
@@ -32381,7 +32613,7 @@ var init_git_remote = __esm({
32381
32613
  });
32382
32614
 
32383
32615
  // src/profile.ts
32384
- import { existsSync as existsSync10, readFileSync as readFileSync8, writeFileSync as writeFileSync8 } from "node:fs";
32616
+ import { existsSync as existsSync11, readFileSync as readFileSync9, writeFileSync as writeFileSync9 } from "node:fs";
32385
32617
  import { createHash as createHash5 } from "node:crypto";
32386
32618
  import { join as join9 } from "node:path";
32387
32619
  function workspaceId(root) {
@@ -32406,13 +32638,13 @@ function refreshRepoLocator(root, profile) {
32406
32638
  }
32407
32639
  function loadProfile(root) {
32408
32640
  const p = workspacePaths(root);
32409
- if (!existsSync10(p.workspaceJson)) return null;
32410
- return JSON.parse(readFileSync8(p.workspaceJson, "utf8"));
32641
+ if (!existsSync11(p.workspaceJson)) return null;
32642
+ return JSON.parse(readFileSync9(p.workspaceJson, "utf8"));
32411
32643
  }
32412
32644
  function saveProfile(root, profile) {
32413
32645
  const p = workspacePaths(root);
32414
32646
  ensureDir(p.configDir);
32415
- writeFileSync8(p.workspaceJson, JSON.stringify(profile, null, 2), "utf8");
32647
+ writeFileSync9(p.workspaceJson, JSON.stringify(profile, null, 2), "utf8");
32416
32648
  }
32417
32649
  function autodetectProfile(root) {
32418
32650
  const id = workspaceId(root);
@@ -32421,12 +32653,12 @@ function autodetectProfile(root) {
32421
32653
  const locator = detectRepoLocator(root);
32422
32654
  if (locator) p.repoLocator = locator;
32423
32655
  const pkgPath = join9(root, "package.json");
32424
- if (existsSync10(pkgPath)) {
32656
+ if (existsSync11(pkgPath)) {
32425
32657
  try {
32426
- const pkg = JSON.parse(readFileSync8(pkgPath, "utf8"));
32658
+ const pkg = JSON.parse(readFileSync9(pkgPath, "utf8"));
32427
32659
  const deps = { ...pkg.dependencies ?? {}, ...pkg.devDependencies ?? {} };
32428
32660
  p.languages.push("javascript");
32429
- if (existsSync10(join9(root, "tsconfig.json")) || deps["typescript"]) {
32661
+ if (existsSync11(join9(root, "tsconfig.json")) || deps["typescript"]) {
32430
32662
  p.languages.push("typescript");
32431
32663
  }
32432
32664
  const nodeVer = pkg.engines?.node?.trim();
@@ -32448,9 +32680,9 @@ function autodetectProfile(root) {
32448
32680
  }
32449
32681
  }
32450
32682
  const pyproject = join9(root, "pyproject.toml");
32451
- if (existsSync10(pyproject)) {
32683
+ if (existsSync11(pyproject)) {
32452
32684
  try {
32453
- const txt = readFileSync8(pyproject, "utf8");
32685
+ const txt = readFileSync9(pyproject, "utf8");
32454
32686
  const py = /python\s*=\s*"([^"]+)"/.exec(txt)?.[1];
32455
32687
  p.languages.push("python");
32456
32688
  p.stack.push(`python@${py ?? "3"}`);
@@ -32462,15 +32694,15 @@ function autodetectProfile(root) {
32462
32694
  }
32463
32695
  }
32464
32696
  const reqs = join9(root, "requirements.txt");
32465
- if (existsSync10(reqs)) {
32697
+ if (existsSync11(reqs)) {
32466
32698
  if (!p.languages.includes("python")) p.languages.push("python");
32467
32699
  if (!p.stack.includes("python@3")) p.stack.push("python@3");
32468
32700
  }
32469
- if (existsSync10(join9(root, "go.mod"))) {
32701
+ if (existsSync11(join9(root, "go.mod"))) {
32470
32702
  p.languages.push("go");
32471
32703
  p.stack.push("go");
32472
32704
  }
32473
- if (existsSync10(join9(root, "Cargo.toml"))) {
32705
+ if (existsSync11(join9(root, "Cargo.toml"))) {
32474
32706
  p.languages.push("rust");
32475
32707
  p.stack.push("rust");
32476
32708
  }
@@ -32575,12 +32807,12 @@ var init_identity2 = __esm({
32575
32807
  });
32576
32808
 
32577
32809
  // src/checkout-root.ts
32578
- import { existsSync as existsSync11, readFileSync as readFileSync9 } from "node:fs";
32579
- import { basename as basename2, dirname as dirname6, isAbsolute as isAbsolute3, join as join10, resolve as resolve2 } from "node:path";
32810
+ import { existsSync as existsSync12, readFileSync as readFileSync10 } from "node:fs";
32811
+ import { basename as basename2, dirname as dirname6, isAbsolute as isAbsolute3, join as join10, resolve as resolve3 } from "node:path";
32580
32812
  function nearestGitRoot(dir) {
32581
- let cur = resolve2(dir);
32813
+ let cur = resolve3(dir);
32582
32814
  for (; ; ) {
32583
- if (existsSync11(join10(cur, ".git"))) return cur;
32815
+ if (existsSync12(join10(cur, ".git"))) return cur;
32584
32816
  const parent = dirname6(cur);
32585
32817
  if (parent === cur) return null;
32586
32818
  cur = parent;
@@ -32590,22 +32822,22 @@ function mainCheckoutOfWorktree(root) {
32590
32822
  const gitDir = resolveGitDir(root);
32591
32823
  if (!gitDir || gitDir === join10(root, ".git")) return null;
32592
32824
  const commondirFile = join10(gitDir, "commondir");
32593
- if (!existsSync11(commondirFile)) return null;
32825
+ if (!existsSync12(commondirFile)) return null;
32594
32826
  let common;
32595
32827
  try {
32596
- common = readFileSync9(commondirFile, "utf8").trim();
32828
+ common = readFileSync10(commondirFile, "utf8").trim();
32597
32829
  } catch {
32598
32830
  return null;
32599
32831
  }
32600
- const commonDir = resolve2(isAbsolute3(common) ? common : resolve2(gitDir, common));
32832
+ const commonDir = resolve3(isAbsolute3(common) ? common : resolve3(gitDir, common));
32601
32833
  if (basename2(commonDir) !== ".git") return null;
32602
32834
  const main2 = dirname6(commonDir);
32603
- return existsSync11(join10(main2, ".git")) ? main2 : null;
32835
+ return existsSync12(join10(main2, ".git")) ? main2 : null;
32604
32836
  }
32605
32837
  function checkoutRootOf(cwd) {
32606
32838
  const root = nearestGitRoot(cwd);
32607
32839
  const main2 = root ? mainCheckoutOfWorktree(root) : null;
32608
- return main2 ?? resolve2(cwd);
32840
+ return main2 ?? resolve3(cwd);
32609
32841
  }
32610
32842
  function isLinkedWorktree(root) {
32611
32843
  return mainCheckoutOfWorktree(root) !== null;
@@ -32619,7 +32851,7 @@ var init_checkout_root = __esm({
32619
32851
 
32620
32852
  // src/process-identity.ts
32621
32853
  import { execFileSync } from "node:child_process";
32622
- import { readFileSync as readFileSync10 } from "node:fs";
32854
+ import { readFileSync as readFileSync11 } from "node:fs";
32623
32855
  function readProcessIdentity(pid, fresh = false) {
32624
32856
  if (!Number.isSafeInteger(pid) || pid <= 0) return null;
32625
32857
  if (pid === process.pid && self) return self;
@@ -32644,10 +32876,10 @@ function readProcessIdentity(pid, fresh = false) {
32644
32876
  if (!/^\d+$/.test(ticks)) return null;
32645
32877
  value = { key: `win32:${ticks}`, bornAt: Number((BigInt(ticks) - 621355968000000000n) / 10000n) };
32646
32878
  } else if (process.platform === "linux") {
32647
- const stat4 = readFileSync10(`/proc/${pid}/stat`, "utf8");
32879
+ const stat4 = readFileSync11(`/proc/${pid}/stat`, "utf8");
32648
32880
  const ticks = stat4.slice(stat4.lastIndexOf(")") + 2).split(" ")[19];
32649
- const bootId = readFileSync10("/proc/sys/kernel/random/boot_id", "utf8").trim();
32650
- const boot = /^btime (\d+)$/m.exec(readFileSync10("/proc/stat", "utf8"))?.[1];
32881
+ const bootId = readFileSync11("/proc/sys/kernel/random/boot_id", "utf8").trim();
32882
+ const boot = /^btime (\d+)$/m.exec(readFileSync11("/proc/stat", "utf8"))?.[1];
32651
32883
  const hz = Number(run3("getconf", ["CLK_TCK"]));
32652
32884
  if (!boot || !/^\d+$/.test(ticks) || !Number.isFinite(hz) || hz <= 0) return null;
32653
32885
  value = { key: `linux:${bootId}:${ticks}`, bornAt: Number(boot) * 1e3 + Number(ticks) * 1e3 / hz };
@@ -32673,7 +32905,7 @@ var init_process_identity = __esm({
32673
32905
  });
32674
32906
 
32675
32907
  // src/lock.ts
32676
- import { existsSync as existsSync12, readFileSync as readFileSync11, unlinkSync as unlinkSync2 } from "node:fs";
32908
+ import { existsSync as existsSync13, readFileSync as readFileSync12, unlinkSync as unlinkSync2 } from "node:fs";
32677
32909
  function daemonLockPayload(lock) {
32678
32910
  return JSON.stringify({
32679
32911
  pid: lock.pid,
@@ -32708,9 +32940,9 @@ function isProcessAlive(pid) {
32708
32940
  }
32709
32941
  }
32710
32942
  function readDaemonLock(lockPath) {
32711
- if (!existsSync12(lockPath)) return null;
32943
+ if (!existsSync13(lockPath)) return null;
32712
32944
  try {
32713
- return parseDaemonLock(readFileSync11(lockPath, "utf8"));
32945
+ return parseDaemonLock(readFileSync12(lockPath, "utf8"));
32714
32946
  } catch {
32715
32947
  return null;
32716
32948
  }
@@ -32740,7 +32972,7 @@ function daemonLockBlocksStartup(lockPath) {
32740
32972
  function stopLockedDaemon(lockPath) {
32741
32973
  let original;
32742
32974
  try {
32743
- original = readFileSync11(lockPath, "utf8");
32975
+ original = readFileSync12(lockPath, "utf8");
32744
32976
  } catch {
32745
32977
  return "missing";
32746
32978
  }
@@ -32748,7 +32980,7 @@ function stopLockedDaemon(lockPath) {
32748
32980
  if (!lock) return "unknown";
32749
32981
  const state = daemonLockState(lock, true);
32750
32982
  try {
32751
- if (readFileSync11(lockPath, "utf8") !== original) return "changed";
32983
+ if (readFileSync12(lockPath, "utf8") !== original) return "changed";
32752
32984
  } catch {
32753
32985
  return "changed";
32754
32986
  }
@@ -32773,16 +33005,16 @@ var init_lock = __esm({
32773
33005
  });
32774
33006
 
32775
33007
  // src/registry.ts
32776
- import { existsSync as existsSync13, readFileSync as readFileSync12, writeFileSync as writeFileSync9 } from "node:fs";
33008
+ import { existsSync as existsSync14, readFileSync as readFileSync13, writeFileSync as writeFileSync10 } from "node:fs";
32777
33009
  import { join as join11 } from "node:path";
32778
33010
  function registryPath() {
32779
33011
  return process.env["ERRATA_REGISTRY_PATH"] ?? join11(globalDir(), "workspaces.json");
32780
33012
  }
32781
33013
  function read() {
32782
33014
  const p = registryPath();
32783
- if (!existsSync13(p)) return { version: 1, workspaces: {} };
33015
+ if (!existsSync14(p)) return { version: 1, workspaces: {} };
32784
33016
  try {
32785
- const parsed = JSON.parse(readFileSync12(p, "utf8"));
33017
+ const parsed = JSON.parse(readFileSync13(p, "utf8"));
32786
33018
  return { version: 1, workspaces: parsed.workspaces ?? {} };
32787
33019
  } catch {
32788
33020
  return { version: 1, workspaces: {} };
@@ -32790,9 +33022,9 @@ function read() {
32790
33022
  }
32791
33023
  function registryCorrupt() {
32792
33024
  const p = registryPath();
32793
- if (!existsSync13(p)) return false;
33025
+ if (!existsSync14(p)) return false;
32794
33026
  try {
32795
- JSON.parse(readFileSync12(p, "utf8"));
33027
+ JSON.parse(readFileSync13(p, "utf8"));
32796
33028
  return false;
32797
33029
  } catch {
32798
33030
  return true;
@@ -32800,7 +33032,7 @@ function registryCorrupt() {
32800
33032
  }
32801
33033
  function write(reg) {
32802
33034
  ensureDir(globalDir());
32803
- writeFileSync9(registryPath(), JSON.stringify(reg, null, 2), "utf8");
33035
+ writeFileSync10(registryPath(), JSON.stringify(reg, null, 2), "utf8");
32804
33036
  }
32805
33037
  function registerWorkspace(profile, root, now = Date.now()) {
32806
33038
  if (isLinkedWorktree(root)) return;
@@ -32845,7 +33077,7 @@ function pruneMissingWorkspaces() {
32845
33077
  const reg = read();
32846
33078
  const removed = [];
32847
33079
  for (const [id, entry] of Object.entries(reg.workspaces)) {
32848
- if (!existsSync13(entry.path)) {
33080
+ if (!existsSync14(entry.path)) {
32849
33081
  removed.push(entry);
32850
33082
  delete reg.workspaces[id];
32851
33083
  }
@@ -32854,7 +33086,7 @@ function pruneMissingWorkspaces() {
32854
33086
  return removed;
32855
33087
  }
32856
33088
  function workspaceStatus(entry) {
32857
- const missing = !existsSync13(entry.path);
33089
+ const missing = !existsSync14(entry.path);
32858
33090
  const lockPath = workspacePaths(entry.path).daemonLock;
32859
33091
  let running = false;
32860
33092
  let webUiUrl = null;
@@ -34173,7 +34405,7 @@ var init_dual_augment = __esm({
34173
34405
 
34174
34406
  // ../../packages/indexer/src/parse-cache.ts
34175
34407
  import { createHash as createHash6 } from "node:crypto";
34176
- import { existsSync as existsSync14, mkdirSync as mkdirSync6, readFileSync as readFileSync13, readdirSync as readdirSync2, rmSync as rmSync2, statSync as statSync2, writeFileSync as writeFileSync10 } from "node:fs";
34408
+ import { existsSync as existsSync15, mkdirSync as mkdirSync6, readFileSync as readFileSync14, readdirSync as readdirSync2, rmSync as rmSync2, statSync as statSync2, writeFileSync as writeFileSync11 } from "node:fs";
34177
34409
  import { homedir as homedir3 } from "node:os";
34178
34410
  import { join as join12 } from "node:path";
34179
34411
  function parseCacheDir() {
@@ -34188,7 +34420,7 @@ function entryPath(dir, key) {
34188
34420
  function readParseCache(dir, key) {
34189
34421
  const file2 = entryPath(dir, key);
34190
34422
  try {
34191
- const raw2 = readFileSync13(file2, "utf8");
34423
+ const raw2 = readFileSync14(file2, "utf8");
34192
34424
  const parsed = JSON.parse(raw2);
34193
34425
  if (parsed.v !== PARSE_CACHE_VERSION || !Array.isArray(parsed.symbols)) return null;
34194
34426
  return { symbols: parsed.symbols, reExports: parsed.reExports ?? [] };
@@ -34208,7 +34440,7 @@ function writeParseCache(dir, key, providerId, value) {
34208
34440
  if (body2.length > MAX_ENTRY_BYTES) return;
34209
34441
  const file2 = entryPath(dir, key);
34210
34442
  mkdirSync6(join12(dir, key.slice(0, 2)), { recursive: true });
34211
- writeFileSync10(file2, body2);
34443
+ writeFileSync11(file2, body2);
34212
34444
  } catch {
34213
34445
  }
34214
34446
  }
@@ -34217,7 +34449,7 @@ function sweepParseCacheOnce(dir, now = Date.now()) {
34217
34449
  sweptThisProcess = true;
34218
34450
  let removed = 0;
34219
34451
  try {
34220
- if (!existsSync14(dir)) return 0;
34452
+ if (!existsSync15(dir)) return 0;
34221
34453
  for (const bucket of readdirSync2(dir)) {
34222
34454
  const bucketDir = join12(dir, bucket);
34223
34455
  let names;
@@ -34475,7 +34707,7 @@ var init_identity3 = __esm({
34475
34707
  });
34476
34708
 
34477
34709
  // ../../packages/indexer/src/pipeline.ts
34478
- import { appendFileSync, readFileSync as readFileSync14, statSync as statSync3 } from "node:fs";
34710
+ import { appendFileSync, readFileSync as readFileSync15, statSync as statSync3 } from "node:fs";
34479
34711
  import { readdir } from "node:fs/promises";
34480
34712
  import { extname, join as join13, relative as relative2, sep } from "node:path";
34481
34713
  import { createHash as createHash7 } from "node:crypto";
@@ -34615,7 +34847,7 @@ async function incrementalReindex(store, rootPath, workspaceId2, changedAbsPaths
34615
34847
  for (const rel of [...changedRelPaths]) {
34616
34848
  let h;
34617
34849
  try {
34618
- h = createHash7("sha256").update(readFileSync14(join13(rootPath, rel))).digest("hex");
34850
+ h = createHash7("sha256").update(readFileSync15(join13(rootPath, rel))).digest("hex");
34619
34851
  } catch {
34620
34852
  continue;
34621
34853
  }
@@ -34670,7 +34902,7 @@ async function incrementalReindex(store, rootPath, workspaceId2, changedAbsPaths
34670
34902
  if (!provider) continue;
34671
34903
  let symbols;
34672
34904
  try {
34673
- symbols = provider.extractSymbols(readFileSync14(abs, "utf8"), abs);
34905
+ symbols = provider.extractSymbols(readFileSync15(abs, "utf8"), abs);
34674
34906
  } catch {
34675
34907
  continue;
34676
34908
  }
@@ -34990,7 +35222,7 @@ async function runIndexer(store, opts) {
34990
35222
  report.filesSkipped++;
34991
35223
  continue;
34992
35224
  }
34993
- source = readFileSync14(f.absPath, "utf8");
35225
+ source = readFileSync15(f.absPath, "utf8");
34994
35226
  } catch {
34995
35227
  report.filesSkipped++;
34996
35228
  continue;
@@ -35062,7 +35294,7 @@ async function runIndexer(store, opts) {
35062
35294
  const depth = fileNode.relPath.split("/").length;
35063
35295
  if (depth !== 3) continue;
35064
35296
  try {
35065
- const pkg = JSON.parse(readFileSync14(fileNode.absPath, "utf8"));
35297
+ const pkg = JSON.parse(readFileSync15(fileNode.absPath, "utf8"));
35066
35298
  if (!pkg.name) continue;
35067
35299
  const pkgDir = fileNode.relPath.replace(/\/package\.json$/, "");
35068
35300
  const candidates = [
@@ -35538,7 +35770,7 @@ function upsertFile(store, id, f, workspaceId2, skip) {
35538
35770
  if (existing && fileUnchanged(existing.attrs, f, skip)) return;
35539
35771
  let contentHash;
35540
35772
  try {
35541
- contentHash = createHash7("sha256").update(readFileSync14(f.absPath)).digest("hex");
35773
+ contentHash = createHash7("sha256").update(readFileSync15(f.absPath)).digest("hex");
35542
35774
  } catch {
35543
35775
  }
35544
35776
  const carried = { ...existing?.attrs ?? {} };
@@ -36155,13 +36387,13 @@ async function Module2(moduleArg = {}) {
36155
36387
  }
36156
36388
  readAsync = /* @__PURE__ */ __name(async (url2) => {
36157
36389
  if (isFileURI(url2)) {
36158
- return new Promise((resolve8, reject) => {
36390
+ return new Promise((resolve9, reject) => {
36159
36391
  var xhr = new XMLHttpRequest();
36160
36392
  xhr.open("GET", url2, true);
36161
36393
  xhr.responseType = "arraybuffer";
36162
36394
  xhr.onload = () => {
36163
36395
  if (xhr.status == 200 || xhr.status == 0 && xhr.response) {
36164
- resolve8(xhr.response);
36396
+ resolve9(xhr.response);
36165
36397
  return;
36166
36398
  }
36167
36399
  reject(xhr.status);
@@ -36357,9 +36589,9 @@ async function Module2(moduleArg = {}) {
36357
36589
  __name(receiveInstantiationResult, "receiveInstantiationResult");
36358
36590
  var info2 = getWasmImports();
36359
36591
  if (Module["instantiateWasm"]) {
36360
- return new Promise((resolve8, reject) => {
36592
+ return new Promise((resolve9, reject) => {
36361
36593
  Module["instantiateWasm"](info2, (mod, inst) => {
36362
- resolve8(receiveInstance(mod, inst));
36594
+ resolve9(receiveInstance(mod, inst));
36363
36595
  });
36364
36596
  });
36365
36597
  }
@@ -37690,8 +37922,8 @@ async function Module2(moduleArg = {}) {
37690
37922
  if (runtimeInitialized) {
37691
37923
  moduleRtn = Module;
37692
37924
  } else {
37693
- moduleRtn = new Promise((resolve8, reject) => {
37694
- readyPromiseResolve = resolve8;
37925
+ moduleRtn = new Promise((resolve9, reject) => {
37926
+ readyPromiseResolve = resolve9;
37695
37927
  readyPromiseReject = reject;
37696
37928
  });
37697
37929
  }
@@ -39922,7 +40154,7 @@ ${JSON.stringify(symbolNames, null, 2)}`);
39922
40154
  // ../../packages/indexer/src/languages/tree-sitter-loader.ts
39923
40155
  import { fileURLToPath } from "node:url";
39924
40156
  import { dirname as dirname7, join as join14 } from "node:path";
39925
- import { existsSync as existsSync15, readdirSync as readdirSync3 } from "node:fs";
40157
+ import { existsSync as existsSync16, readdirSync as readdirSync3 } from "node:fs";
39926
40158
  import { createRequire as createRequire2 } from "node:module";
39927
40159
  function entryDir() {
39928
40160
  try {
@@ -39937,7 +40169,7 @@ function entryDir() {
39937
40169
  function findWasmDir() {
39938
40170
  const here = entryDir();
39939
40171
  const seaWasm = join14(here, "resources", "wasm");
39940
- if (existsSync15(join14(seaWasm, "tree-sitter-typescript.wasm"))) return seaWasm;
40172
+ if (existsSync16(join14(seaWasm, "tree-sitter-typescript.wasm"))) return seaWasm;
39941
40173
  let dir = here;
39942
40174
  for (let i2 = 0; i2 < 6; i2++) {
39943
40175
  const flat = join14(
@@ -39947,13 +40179,13 @@ function findWasmDir() {
39947
40179
  "tree-sitter-wasm",
39948
40180
  "wasm"
39949
40181
  );
39950
- if (existsSync15(join14(flat, "tree-sitter-typescript.wasm"))) return flat;
40182
+ if (existsSync16(join14(flat, "tree-sitter-typescript.wasm"))) return flat;
39951
40183
  dir = dirname7(dir);
39952
40184
  }
39953
40185
  let root = here;
39954
40186
  for (let i2 = 0; i2 < 6; i2++) {
39955
40187
  const pnpmDir = join14(root, "node_modules", ".pnpm");
39956
- if (existsSync15(pnpmDir)) {
40188
+ if (existsSync16(pnpmDir)) {
39957
40189
  for (const entry of readdirSync3(pnpmDir)) {
39958
40190
  if (entry.startsWith("@vscode+tree-sitter-wasm@")) {
39959
40191
  const candidate = join14(
@@ -39964,7 +40196,7 @@ function findWasmDir() {
39964
40196
  "tree-sitter-wasm",
39965
40197
  "wasm"
39966
40198
  );
39967
- if (existsSync15(join14(candidate, "tree-sitter-typescript.wasm"))) {
40199
+ if (existsSync16(join14(candidate, "tree-sitter-typescript.wasm"))) {
39968
40200
  return candidate;
39969
40201
  }
39970
40202
  }
@@ -39979,17 +40211,17 @@ function findWasmDir() {
39979
40211
  function findRuntimeDir() {
39980
40212
  const here = entryDir();
39981
40213
  const seaRuntime = join14(here, "resources", "wasm");
39982
- if (existsSync15(join14(seaRuntime, "web-tree-sitter.wasm"))) return seaRuntime;
40214
+ if (existsSync16(join14(seaRuntime, "web-tree-sitter.wasm"))) return seaRuntime;
39983
40215
  let dir = here;
39984
40216
  for (let i2 = 0; i2 < 6; i2++) {
39985
40217
  const flat = join14(dir, "node_modules", "web-tree-sitter");
39986
- if (existsSync15(join14(flat, "web-tree-sitter.wasm"))) return flat;
40218
+ if (existsSync16(join14(flat, "web-tree-sitter.wasm"))) return flat;
39987
40219
  dir = dirname7(dir);
39988
40220
  }
39989
40221
  let root = here;
39990
40222
  for (let i2 = 0; i2 < 6; i2++) {
39991
40223
  const pnpmDir = join14(root, "node_modules", ".pnpm");
39992
- if (existsSync15(pnpmDir)) {
40224
+ if (existsSync16(pnpmDir)) {
39993
40225
  for (const entry of readdirSync3(pnpmDir)) {
39994
40226
  if (entry.startsWith("web-tree-sitter@")) {
39995
40227
  const candidate = join14(
@@ -39998,7 +40230,7 @@ function findRuntimeDir() {
39998
40230
  "node_modules",
39999
40231
  "web-tree-sitter"
40000
40232
  );
40001
- if (existsSync15(join14(candidate, "web-tree-sitter.wasm"))) {
40233
+ if (existsSync16(join14(candidate, "web-tree-sitter.wasm"))) {
40002
40234
  return candidate;
40003
40235
  }
40004
40236
  }
@@ -43137,8 +43369,8 @@ __export(mcp_exports, {
43137
43369
  runTool: () => runTool,
43138
43370
  searchGraph: () => searchGraph
43139
43371
  });
43140
- import { existsSync as existsSync16, readFileSync as readFileSync15 } from "node:fs";
43141
- import { resolve as resolve3 } from "node:path";
43372
+ import { existsSync as existsSync17, readFileSync as readFileSync16 } from "node:fs";
43373
+ import { resolve as resolve4 } from "node:path";
43142
43374
  function collectEnrichmentPulls(store, opts = {}) {
43143
43375
  const pending = store.findNodesByLabel("Solution").filter((s) => s.attrs["enrichmentPending"] === true).filter((s) => !opts.onlyUnsurfaced || s.attrs["enrichmentSurfaced"] !== true);
43144
43376
  const byEpisode = /* @__PURE__ */ new Map();
@@ -43174,7 +43406,7 @@ function takeEnrichmentNudge(store) {
43174
43406
  ` + items;
43175
43407
  }
43176
43408
  function takeDiscriminatorNudge(path2) {
43177
- if (!path2 || !existsSync16(path2)) return null;
43409
+ if (!path2 || !existsSync17(path2)) return null;
43178
43410
  let shared;
43179
43411
  try {
43180
43412
  shared = openGraphStore({ path: path2 });
@@ -43304,11 +43536,11 @@ function showNode(store, node2, maxLines) {
43304
43536
  const relPath = ownerFilePath(store, node2);
43305
43537
  if (!relPath) return { found: false, reason: "no file owner for node" };
43306
43538
  const workspaceRoot = process.cwd();
43307
- const absPath = resolve3(workspaceRoot, relPath);
43308
- if (!existsSync16(absPath)) {
43539
+ const absPath = resolve4(workspaceRoot, relPath);
43540
+ if (!existsSync17(absPath)) {
43309
43541
  return { found: false, reason: `file not found on disk: ${absPath}` };
43310
43542
  }
43311
- const source = readFileSync15(absPath, "utf8");
43543
+ const source = readFileSync16(absPath, "utf8");
43312
43544
  const attrs = node2.attrs;
43313
43545
  let startByte = attrs["bodyStartByte"] ?? attrs["startByte"];
43314
43546
  let endByte = attrs["bodyEndByte"] ?? attrs["endByte"];
@@ -43534,7 +43766,7 @@ function buildToolContext(workspaceRoot) {
43534
43766
  const base = { switchInstallationProfile: useInstallationProfile };
43535
43767
  try {
43536
43768
  const cfg = loadConfig();
43537
- const entry = workspaceRoot ? workspaceEntryForPath(resolve3(workspaceRoot)) : null;
43769
+ const entry = workspaceRoot ? workspaceEntryForPath(resolve4(workspaceRoot)) : null;
43538
43770
  const syncOk = effectiveConsent(cfg, entry ? loadProfile(entry.path) : null).sync;
43539
43771
  const identity = resolveWorkspaceIdentity(cfg, entry);
43540
43772
  if (identity.invalid) {
@@ -44027,7 +44259,7 @@ var init_mcp = __esm({
44027
44259
  const local = causalChain(store, { seedId: id, direction: "both", maxHops, limit });
44028
44260
  try {
44029
44261
  const path2 = sharedStorePath();
44030
- if (!existsSync16(path2)) return { found: true, ...local };
44262
+ if (!existsSync17(path2)) return { found: true, ...local };
44031
44263
  const shared = openGraphStore({ path: path2 });
44032
44264
  try {
44033
44265
  if (!shared.getNode(id)) return { found: true, ...local };
@@ -44630,7 +44862,7 @@ var init_mcp = __esm({
44630
44862
  inputSchema: { type: "object", properties: {} },
44631
44863
  handler: () => {
44632
44864
  const path2 = sharedStorePath();
44633
- if (!existsSync16(path2)) return { count: 0, pending: [] };
44865
+ if (!existsSync17(path2)) return { count: 0, pending: [] };
44634
44866
  const shared = openGraphStore({ path: path2 });
44635
44867
  try {
44636
44868
  const pending = pendingAbstractions(shared);
@@ -44658,7 +44890,7 @@ var init_mcp = __esm({
44658
44890
  },
44659
44891
  handler: (args2) => {
44660
44892
  const path2 = sharedStorePath();
44661
- if (!existsSync16(path2)) return { count: 0, pending: [] };
44893
+ if (!existsSync17(path2)) return { count: 0, pending: [] };
44662
44894
  const shared = openGraphStore({ path: path2 });
44663
44895
  try {
44664
44896
  const pending = pendingDiscriminators(shared, {
@@ -44702,7 +44934,7 @@ var init_mcp = __esm({
44702
44934
  },
44703
44935
  handler: (args2) => {
44704
44936
  const path2 = sharedStorePath();
44705
- if (!existsSync16(path2)) return { count: 0, routes: [] };
44937
+ if (!existsSync17(path2)) return { count: 0, routes: [] };
44706
44938
  const shared = openGraphStore({ path: path2 });
44707
44939
  try {
44708
44940
  const result = triageOf(shared, {
@@ -45087,8 +45319,8 @@ __export(vfile_exports, {
45087
45319
  resolvePath: () => resolvePath,
45088
45320
  segmentsOf: () => segmentsOf
45089
45321
  });
45090
- import { writeFileSync as writeFileSync11 } from "node:fs";
45091
- import { join as join16, resolve as resolve4, sep as sep3 } from "node:path";
45322
+ import { writeFileSync as writeFileSync12 } from "node:fs";
45323
+ import { join as join16, resolve as resolve5, sep as sep3 } from "node:path";
45092
45324
  function segmentsOf(rawPath) {
45093
45325
  let p = rawPath.replace(/\\/g, "/");
45094
45326
  p = p.replace(/^.*\.errata\/g\//, "").replace(/^\/?g\//, "").replace(/^\/+/, "");
@@ -45163,13 +45395,13 @@ async function renderVFile(rawPath, store, ctx = {}) {
45163
45395
  async function materializeVFile(rawPath, workspaceRoot, store, ctx = {}) {
45164
45396
  const segs = segmentsOf(rawPath);
45165
45397
  const gRoot = join16(workspaceRoot, ".errata", "g");
45166
- const abs = resolve4(gRoot, ...segs.length ? segs : ["index"]);
45398
+ const abs = resolve5(gRoot, ...segs.length ? segs : ["index"]);
45167
45399
  if (abs !== gRoot && !abs.startsWith(gRoot + sep3)) {
45168
45400
  throw new Error(`refusing to materialize outside .errata/g: ${rawPath}`);
45169
45401
  }
45170
45402
  const text = await renderVFile(rawPath, store, ctx);
45171
45403
  ensureParent(abs);
45172
- writeFileSync11(abs, text, "utf8");
45404
+ writeFileSync12(abs, text, "utf8");
45173
45405
  return abs;
45174
45406
  }
45175
45407
  async function materializeOverview(workspaceRoot, store, ctx = {}) {
@@ -52589,12 +52821,12 @@ var init_tool_index = __esm({
52589
52821
 
52590
52822
  // src/outbox.ts
52591
52823
  import {
52592
- existsSync as existsSync17,
52824
+ existsSync as existsSync18,
52593
52825
  readdirSync as readdirSync5,
52594
- readFileSync as readFileSync16,
52826
+ readFileSync as readFileSync17,
52595
52827
  renameSync as renameSync2,
52596
52828
  unlinkSync as unlinkSync3,
52597
- writeFileSync as writeFileSync12
52829
+ writeFileSync as writeFileSync13
52598
52830
  } from "node:fs";
52599
52831
  import { join as join17 } from "node:path";
52600
52832
  import { createHash as createHash15 } from "node:crypto";
@@ -52602,12 +52834,12 @@ function enqueueOutbox(paths, payload) {
52602
52834
  ensureDir(paths.outbox);
52603
52835
  const id = createHash15("sha256").update(JSON.stringify(payload)).digest("hex").slice(0, 16);
52604
52836
  const file2 = join17(paths.outbox, `${Date.now()}-${id}.json`);
52605
- writeFileSync12(file2, JSON.stringify(payload, null, 2), "utf8");
52837
+ writeFileSync13(file2, JSON.stringify(payload, null, 2), "utf8");
52606
52838
  return file2;
52607
52839
  }
52608
52840
  async function flushOutbox(paths, client, store) {
52609
52841
  ensureDir(paths.outbox);
52610
- const entries = existsSync17(paths.outbox) ? readdirSync5(paths.outbox) : [];
52842
+ const entries = existsSync18(paths.outbox) ? readdirSync5(paths.outbox) : [];
52611
52843
  let uploaded = 0;
52612
52844
  let failed = 0;
52613
52845
  const quarantine = (abs, reason) => {
@@ -52621,7 +52853,7 @@ async function flushOutbox(paths, client, store) {
52621
52853
  const abs = join17(paths.outbox, f);
52622
52854
  let payload;
52623
52855
  try {
52624
- payload = JSON.parse(readFileSync16(abs, "utf8"));
52856
+ payload = JSON.parse(readFileSync17(abs, "utf8"));
52625
52857
  } catch {
52626
52858
  failed++;
52627
52859
  quarantine(abs, "unparseable JSON");
@@ -52666,7 +52898,7 @@ async function flushOutbox(paths, client, store) {
52666
52898
  }
52667
52899
  }
52668
52900
  }
52669
- const remainingFiles = existsSync17(paths.outbox) ? readdirSync5(paths.outbox).filter((e) => e.endsWith(".json")) : [];
52901
+ const remainingFiles = existsSync18(paths.outbox) ? readdirSync5(paths.outbox).filter((e) => e.endsWith(".json")) : [];
52670
52902
  return { uploaded, failed, remaining: remainingFiles.length };
52671
52903
  }
52672
52904
  var init_outbox = __esm({
@@ -52721,6 +52953,7 @@ var init_message_accumulator = __esm({
52721
52953
  // src/webui.ts
52722
52954
  var webui_exports = {};
52723
52955
  __export(webui_exports, {
52956
+ SUBAGENT_REFRESH_MIN_MS: () => SUBAGENT_REFRESH_MIN_MS,
52724
52957
  asFailedPostToolUse: () => asFailedPostToolUse,
52725
52958
  buildWebUi: () => buildWebUi,
52726
52959
  decideContextInject: () => decideContextInject,
@@ -52728,6 +52961,7 @@ __export(webui_exports, {
52728
52961
  fileRecall: () => fileRecall,
52729
52962
  fileUriToFsPath: () => fileUriToFsPath,
52730
52963
  findFileByPath: () => findFileByPath,
52964
+ hookAudience: () => hookAudience,
52731
52965
  recallForFile: () => recallForFile,
52732
52966
  recallForTool: () => recallForTool
52733
52967
  });
@@ -52874,10 +53108,21 @@ ${lines.join("\n")}`,
52874
53108
  card: { headline: `${plural(items.length, "prior")} before this command runs`, items }
52875
53109
  };
52876
53110
  }
53111
+ function hookAudience(body2) {
53112
+ const sessionId = String(body2["session_id"] ?? "");
53113
+ const agentId = typeof body2["agent_id"] === "string" ? body2["agent_id"] : "";
53114
+ if (!agentId) return { sessionId, contextKey: sessionId, subagent: null, agentId: "" };
53115
+ return {
53116
+ sessionId,
53117
+ contextKey: sessionId ? `${sessionId}#${agentId}` : "",
53118
+ subagent: typeof body2["agent_type"] === "string" ? body2["agent_type"] : "",
53119
+ agentId
53120
+ };
53121
+ }
52877
53122
  function decideContextInject(args2) {
52878
53123
  const { event, sessionId, block, lastInjectedHash } = args2;
52879
53124
  if (!block) return null;
52880
- if (event === "SessionStart") {
53125
+ if (event === "SessionStart" || event === "SubagentStart") {
52881
53126
  if (sessionId) lastInjectedHash.set(sessionId, block.hash);
52882
53127
  } else if (sessionId && lastInjectedHash.get(sessionId) === block.hash) {
52883
53128
  return null;
@@ -52892,6 +53137,21 @@ function buildWebUi(deps) {
52892
53137
  const B = deps.basePath ?? "";
52893
53138
  const lastInjectedHash = /* @__PURE__ */ new Map();
52894
53139
  const fileRecallSeen = /* @__PURE__ */ new Map();
53140
+ const lastSubagentInjectAt = /* @__PURE__ */ new Map();
53141
+ const noteSessionFrom = (headerOrigin, body2, ended = false) => {
53142
+ const { sessionId, agentId } = hookAudience(body2);
53143
+ if (!sessionId || !deps.noteSession) return;
53144
+ const origin = parseOrigin(headerOrigin) ?? parseOrigin(body2["errata_origin"]);
53145
+ try {
53146
+ deps.noteSession({
53147
+ sessionId,
53148
+ ...agentId ? { agentId } : {},
53149
+ ...origin ? { origin } : {},
53150
+ ...ended ? { ended } : {}
53151
+ });
53152
+ } catch {
53153
+ }
53154
+ };
52895
53155
  app.get(
52896
53156
  "/",
52897
53157
  (c) => c.json({
@@ -53034,6 +53294,15 @@ function buildWebUi(deps) {
53034
53294
  if (hookEvent === "PostToolUseFailure") body2 = asFailedPostToolUse(body2);
53035
53295
  const event = hookEvent === "PostToolUseFailure" ? "PostToolUse" : hookEvent;
53036
53296
  let recall = null;
53297
+ const audience = hookAudience(body2);
53298
+ noteSessionFrom(c.req.header(ORIGIN_HEADER), body2);
53299
+ if (event === "PreToolUse" && (tool === "Agent" || tool === "Task") && audience.subagent === null) {
53300
+ try {
53301
+ deps.onSubagentSpawn?.(audience.sessionId, input);
53302
+ } catch {
53303
+ }
53304
+ return c.json({ ok: true, event, tool, spawn: true });
53305
+ }
53037
53306
  if (event === "PreToolUse") {
53038
53307
  const virtual = extractVirtualReads(input);
53039
53308
  if (virtual.length > 0) {
@@ -53062,7 +53331,10 @@ function buildWebUi(deps) {
53062
53331
  const workspaceRoot = (deps.paths.root ?? "").replace(/\\/g, "/");
53063
53332
  const fp = filePath.replace(/\\/g, "/");
53064
53333
  rel = fp.startsWith(workspaceRoot + "/") ? fp.slice(workspaceRoot.length + 1) : fp;
53065
- if (deps.onWorkingFileChanged) deps.onWorkingFileChanged(rel, String(body2["session_id"] ?? ""));
53334
+ if (deps.onWorkingFileChanged) {
53335
+ const agentId = typeof body2["agent_id"] === "string" && body2["agent_id"] ? body2["agent_id"] : void 0;
53336
+ deps.onWorkingFileChanged(rel, audience.sessionId, agentId);
53337
+ }
53066
53338
  }
53067
53339
  if (rel && event === "PostToolUse" && deps.onHookEvent) {
53068
53340
  deps.onHookEvent({
@@ -53130,7 +53402,7 @@ function buildWebUi(deps) {
53130
53402
  }
53131
53403
  }
53132
53404
  if (event === "PostToolUse" && !recall && rel && (tool === "Read" || tool === "Edit" || tool === "Write" || tool === "NotebookEdit")) {
53133
- const sid = String(body2["session_id"] ?? "");
53405
+ const sid = hookAudience(body2).contextKey;
53134
53406
  let seen = fileRecallSeen.get(sid);
53135
53407
  if (!seen) {
53136
53408
  seen = /* @__PURE__ */ new Set();
@@ -53144,13 +53416,46 @@ function buildWebUi(deps) {
53144
53416
  }
53145
53417
  }
53146
53418
  }
53147
- if ((event === "PostToolUse" || event === "PreToolUse") && recall) {
53419
+ let refreshed = null;
53420
+ if (event === "PostToolUse" && audience.subagent !== null && audience.contextKey && deps.subagentContext) {
53421
+ const last = lastSubagentInjectAt.get(audience.contextKey) ?? 0;
53422
+ if (Date.now() - last >= SUBAGENT_REFRESH_MIN_MS) {
53423
+ try {
53424
+ const own = deps.subagentContext({
53425
+ sessionId: audience.sessionId,
53426
+ agentId: audience.agentId,
53427
+ agentType: audience.subagent,
53428
+ start: false
53429
+ });
53430
+ const decision = decideContextInject({
53431
+ event,
53432
+ source: "",
53433
+ sessionId: audience.contextKey,
53434
+ block: own,
53435
+ lastInjectedHash
53436
+ });
53437
+ if (decision) {
53438
+ lastSubagentInjectAt.set(audience.contextKey, Date.now());
53439
+ refreshed = { additionalContext: decision.additionalContext, card: own?.card ?? null };
53440
+ }
53441
+ } catch {
53442
+ }
53443
+ }
53444
+ }
53445
+ if ((event === "PostToolUse" || event === "PreToolUse") && (recall || refreshed)) {
53148
53446
  const showCard = recallCardEnabled();
53149
- if (showCard) rememberCard(String(body2["session_id"] ?? ""), recall.card);
53150
- const line = showCard ? renderRecallLine(recall.card) : null;
53447
+ const { sessionId, subagent } = audience;
53448
+ const raw2 = recall?.card ?? refreshed?.card ?? null;
53449
+ const card = raw2 && subagent !== null ? forSubagent(raw2, subagent) : raw2;
53450
+ if (showCard && raw2 && card) {
53451
+ if (subagent !== null) rememberAgentCard(sessionId, audience.agentId, raw2);
53452
+ else rememberCard(sessionId, card);
53453
+ }
53454
+ const line = showCard && recall && card ? renderRecallLine(card) : null;
53455
+ const additionalContext = [recall?.context, refreshed?.additionalContext].filter(Boolean).join("\n\n");
53151
53456
  return c.json({
53152
53457
  ...line ? { systemMessage: line } : {},
53153
- hookSpecificOutput: { hookEventName: hookEvent, additionalContext: recall.context }
53458
+ hookSpecificOutput: { hookEventName: hookEvent, additionalContext }
53154
53459
  });
53155
53460
  }
53156
53461
  if (event === "PostToolUse") return c.body(null, 204);
@@ -53160,6 +53465,10 @@ function buildWebUi(deps) {
53160
53465
  const body2 = await c.req.json().catch(() => ({}));
53161
53466
  return c.text(statuslineText(String(body2["session_id"] ?? "")));
53162
53467
  });
53468
+ app.post("/api/statusline/subagents", async (c) => {
53469
+ const body2 = await c.req.json().catch(() => ({}));
53470
+ return c.text(subagentRows(body2));
53471
+ });
53163
53472
  app.post("/api/turn", async (c) => {
53164
53473
  let body2;
53165
53474
  try {
@@ -53172,6 +53481,12 @@ function buildWebUi(deps) {
53172
53481
  if (transcriptPath && deps.onTurn) {
53173
53482
  deps.onTurn({ sessionId, transcriptPath });
53174
53483
  }
53484
+ if (body2["hook_event_name"] === "SubagentStop" && typeof body2["agent_id"] === "string" && body2["agent_id"]) {
53485
+ deps.onSubagentStop?.(body2["agent_id"]);
53486
+ noteSessionFrom(c.req.header(ORIGIN_HEADER), body2, true);
53487
+ } else {
53488
+ noteSessionFrom(c.req.header(ORIGIN_HEADER), body2);
53489
+ }
53175
53490
  return c.json({ ok: true });
53176
53491
  });
53177
53492
  app.post("/api/message", async (c) => {
@@ -53183,12 +53498,19 @@ function buildWebUi(deps) {
53183
53498
  }
53184
53499
  const delta = String(body2["delta"] ?? "");
53185
53500
  const sessionId = String(body2["session_id"] ?? "");
53501
+ noteSessionFrom(c.req.header(ORIGIN_HEADER), body2);
53186
53502
  const messageId = typeof body2["message_id"] === "string" ? body2["message_id"] : void 0;
53187
53503
  const index = typeof body2["index"] === "number" ? body2["index"] : 0;
53188
53504
  const isFinal = body2["final"] !== false;
53189
53505
  const whole = accumulateMessageDelta(messageId, index, delta, isFinal, Date.now());
53190
53506
  if (whole !== null && whole.text && sessionId && deps.onMessage) {
53191
- deps.onMessage({ sessionId, text: whole.text, ...messageId ? { messageId } : {} });
53507
+ const agentId = typeof body2["agent_id"] === "string" && body2["agent_id"] ? body2["agent_id"] : void 0;
53508
+ deps.onMessage({
53509
+ sessionId,
53510
+ text: whole.text,
53511
+ ...messageId ? { messageId } : {},
53512
+ ...agentId ? { agentId } : {}
53513
+ });
53192
53514
  }
53193
53515
  return c.json({ ok: true, ...whole === null ? { buffered: true } : {} });
53194
53516
  });
@@ -53204,6 +53526,7 @@ function buildWebUi(deps) {
53204
53526
  if (transcriptPath && deps.onSessionEnd) {
53205
53527
  deps.onSessionEnd({ sessionId, transcriptPath });
53206
53528
  }
53529
+ noteSessionFrom(c.req.header(ORIGIN_HEADER), body2, true);
53207
53530
  return c.json({ ok: true });
53208
53531
  });
53209
53532
  app.post("/api/context-inject", async (c) => {
@@ -53213,9 +53536,10 @@ function buildWebUi(deps) {
53213
53536
  } catch {
53214
53537
  return c.json({});
53215
53538
  }
53216
- const sid = String(body2["session_id"] ?? "");
53539
+ const { sessionId: sid, contextKey: contextKey2, subagent, agentId } = hookAudience(body2);
53540
+ noteSessionFrom(c.req.header(ORIGIN_HEADER), body2);
53217
53541
  const hookEvent = String(body2["hook_event_name"] ?? "UserPromptSubmit");
53218
- const atPrompt = hookEvent === "UserPromptSubmit" || hookEvent === "SessionStart";
53542
+ const atPrompt = hookEvent === "UserPromptSubmit" || hookEvent === "SessionStart" || hookEvent === "SubagentStart";
53219
53543
  if (sid && recallCardEnabled() && atPrompt) {
53220
53544
  setImmediate(() => {
53221
53545
  try {
@@ -53224,20 +53548,39 @@ function buildWebUi(deps) {
53224
53548
  }
53225
53549
  });
53226
53550
  }
53227
- const block = readContextFileWithHash(deps.paths.root);
53551
+ let block;
53552
+ let storedCard = null;
53553
+ if (subagent !== null) {
53554
+ const own = deps.subagentContext?.({
53555
+ sessionId: sid,
53556
+ agentId,
53557
+ agentType: subagent,
53558
+ ...typeof body2["task_description"] === "string" ? { taskDescription: body2["task_description"] } : {},
53559
+ start: hookEvent === "SubagentStart"
53560
+ }) ?? null;
53561
+ block = own;
53562
+ storedCard = own?.card ?? null;
53563
+ } else {
53564
+ const own = sid ? deps.sessionContext?.(sid) ?? null : null;
53565
+ block = own ?? readContextFileWithHash(deps.paths.root);
53566
+ storedCard = own ? own.card : block ? readContextCard(deps.paths.root, block.hash) : null;
53567
+ }
53228
53568
  const decision = decideContextInject({
53229
53569
  event: hookEvent,
53230
53570
  source: String(body2["source"] ?? ""),
53231
- sessionId: sid,
53571
+ sessionId: contextKey2,
53232
53572
  block,
53233
53573
  lastInjectedHash
53234
53574
  });
53575
+ if (decision && subagent !== null) lastSubagentInjectAt.set(contextKey2, Date.now());
53235
53576
  let systemMessage = null;
53236
53577
  if (sid && block && recallCardEnabled() && (decision || atPrompt)) {
53237
- const card = readContextCard(deps.paths.root, block.hash);
53578
+ const card = storedCard && subagent !== null ? forSubagent(storedCard, subagent) : storedCard;
53238
53579
  if (card) {
53239
- rememberCard(sid, card);
53240
- if (decision && sid.startsWith("codex:")) systemMessage = renderRecallLine(card);
53580
+ if (subagent !== null && storedCard) rememberAgentCard(sid, agentId, storedCard);
53581
+ else rememberCard(sid, card);
53582
+ if (decision && hookEvent === "SubagentStart") systemMessage = renderRecallLine(card);
53583
+ else if (decision && sid.startsWith("codex:")) systemMessage = renderRecallLine(card);
53241
53584
  }
53242
53585
  }
53243
53586
  if (!decision) return c.json({});
@@ -53423,7 +53766,7 @@ function proposalToIngest(p, profile, daemonVersion) {
53423
53766
  payloadDigest: p.id
53424
53767
  };
53425
53768
  }
53426
- var messageAccumulator, GENERIC_ERROR_WORDS, wsPackagesCache, WS_PACKAGES_TTL_MS, loggedToolSessions, META_LABELS;
53769
+ var messageAccumulator, GENERIC_ERROR_WORDS, wsPackagesCache, WS_PACKAGES_TTL_MS, loggedToolSessions, SUBAGENT_REFRESH_MIN_MS, META_LABELS;
53427
53770
  var init_webui = __esm({
53428
53771
  "src/webui.ts"() {
53429
53772
  "use strict";
@@ -53434,6 +53777,7 @@ var init_webui = __esm({
53434
53777
  init_agent_signals();
53435
53778
  init_recall_signal();
53436
53779
  init_recall_card();
53780
+ init_session_registry();
53437
53781
  init_review2();
53438
53782
  init_vfile();
53439
53783
  init_tool_index();
@@ -53484,6 +53828,7 @@ var init_webui = __esm({
53484
53828
  wsPackagesCache = /* @__PURE__ */ new WeakMap();
53485
53829
  WS_PACKAGES_TTL_MS = 6e4;
53486
53830
  loggedToolSessions = /* @__PURE__ */ new Set();
53831
+ SUBAGENT_REFRESH_MIN_MS = 6e4;
53487
53832
  META_LABELS = /* @__PURE__ */ new Set([
53488
53833
  "Pattern",
53489
53834
  "Technique",
@@ -54767,7 +55112,7 @@ var require_util = __commonJS({
54767
55112
  }
54768
55113
  return url2;
54769
55114
  }
54770
- function parseOrigin(url2) {
55115
+ function parseOrigin2(url2) {
54771
55116
  url2 = parseURL(url2);
54772
55117
  if (url2.pathname !== "/" || url2.search || url2.hash) {
54773
55118
  throw new InvalidArgumentError("invalid url");
@@ -55102,7 +55447,7 @@ var require_util = __commonJS({
55102
55447
  toUSVString,
55103
55448
  isUSVString,
55104
55449
  isBlobLike,
55105
- parseOrigin,
55450
+ parseOrigin: parseOrigin2,
55106
55451
  parseURL,
55107
55452
  getServerName,
55108
55453
  isStream,
@@ -55760,9 +56105,9 @@ var require_dispatcher_base = __commonJS({
55760
56105
  }
55761
56106
  close(callback) {
55762
56107
  if (callback === void 0) {
55763
- return new Promise((resolve8, reject) => {
56108
+ return new Promise((resolve9, reject) => {
55764
56109
  this.close((err2, data) => {
55765
- return err2 ? reject(err2) : resolve8(data);
56110
+ return err2 ? reject(err2) : resolve9(data);
55766
56111
  });
55767
56112
  });
55768
56113
  }
@@ -55800,12 +56145,12 @@ var require_dispatcher_base = __commonJS({
55800
56145
  err2 = null;
55801
56146
  }
55802
56147
  if (callback === void 0) {
55803
- return new Promise((resolve8, reject) => {
56148
+ return new Promise((resolve9, reject) => {
55804
56149
  this.destroy(err2, (err3, data) => {
55805
56150
  return err3 ? (
55806
56151
  /* istanbul ignore next: should never error */
55807
56152
  reject(err3)
55808
- ) : resolve8(data);
56153
+ ) : resolve9(data);
55809
56154
  });
55810
56155
  });
55811
56156
  }
@@ -58072,8 +58417,8 @@ var require_util2 = __commonJS({
58072
58417
  function createDeferredPromise() {
58073
58418
  let res;
58074
58419
  let rej;
58075
- const promise2 = new Promise((resolve8, reject) => {
58076
- res = resolve8;
58420
+ const promise2 = new Promise((resolve9, reject) => {
58421
+ res = resolve9;
58077
58422
  rej = reject;
58078
58423
  });
58079
58424
  return { promise: promise2, resolve: res, reject: rej };
@@ -60214,12 +60559,12 @@ upgrade: ${upgrade}\r
60214
60559
  cb();
60215
60560
  }
60216
60561
  }
60217
- const waitForDrain = () => new Promise((resolve8, reject) => {
60562
+ const waitForDrain = () => new Promise((resolve9, reject) => {
60218
60563
  assert2(callback === null);
60219
60564
  if (socket[kError]) {
60220
60565
  reject(socket[kError]);
60221
60566
  } else {
60222
- callback = resolve8;
60567
+ callback = resolve9;
60223
60568
  }
60224
60569
  });
60225
60570
  socket.on("close", onDrain).on("drain", onDrain);
@@ -60856,12 +61201,12 @@ var require_client_h2 = __commonJS({
60856
61201
  cb();
60857
61202
  }
60858
61203
  }
60859
- const waitForDrain = () => new Promise((resolve8, reject) => {
61204
+ const waitForDrain = () => new Promise((resolve9, reject) => {
60860
61205
  assert2(callback === null);
60861
61206
  if (socket[kError]) {
60862
61207
  reject(socket[kError]);
60863
61208
  } else {
60864
- callback = resolve8;
61209
+ callback = resolve9;
60865
61210
  }
60866
61211
  });
60867
61212
  h2stream.on("close", onDrain).on("drain", onDrain);
@@ -61338,16 +61683,16 @@ var require_client = __commonJS({
61338
61683
  return this[kNeedDrain] < 2;
61339
61684
  }
61340
61685
  async [kClose]() {
61341
- return new Promise((resolve8) => {
61686
+ return new Promise((resolve9) => {
61342
61687
  if (this[kSize]) {
61343
- this[kClosedResolve] = resolve8;
61688
+ this[kClosedResolve] = resolve9;
61344
61689
  } else {
61345
- resolve8(null);
61690
+ resolve9(null);
61346
61691
  }
61347
61692
  });
61348
61693
  }
61349
61694
  async [kDestroy](err2) {
61350
- return new Promise((resolve8) => {
61695
+ return new Promise((resolve9) => {
61351
61696
  const requests = this[kQueue].splice(this[kPendingIdx]);
61352
61697
  for (let i2 = 0; i2 < requests.length; i2++) {
61353
61698
  const request = requests[i2];
@@ -61358,7 +61703,7 @@ var require_client = __commonJS({
61358
61703
  this[kClosedResolve]();
61359
61704
  this[kClosedResolve] = null;
61360
61705
  }
61361
- resolve8(null);
61706
+ resolve9(null);
61362
61707
  };
61363
61708
  if (this[kHTTPContext]) {
61364
61709
  this[kHTTPContext].destroy(err2, callback);
@@ -61409,7 +61754,7 @@ var require_client = __commonJS({
61409
61754
  });
61410
61755
  }
61411
61756
  try {
61412
- const socket = await new Promise((resolve8, reject) => {
61757
+ const socket = await new Promise((resolve9, reject) => {
61413
61758
  client[kConnector]({
61414
61759
  host,
61415
61760
  hostname: hostname3,
@@ -61421,7 +61766,7 @@ var require_client = __commonJS({
61421
61766
  if (err2) {
61422
61767
  reject(err2);
61423
61768
  } else {
61424
- resolve8(socket2);
61769
+ resolve9(socket2);
61425
61770
  }
61426
61771
  });
61427
61772
  });
@@ -61757,8 +62102,8 @@ var require_pool_base = __commonJS({
61757
62102
  if (this[kQueue].isEmpty()) {
61758
62103
  await Promise.all(this[kClients].map((c) => c.close()));
61759
62104
  } else {
61760
- await new Promise((resolve8) => {
61761
- this[kClosedResolve] = resolve8;
62105
+ await new Promise((resolve9) => {
62106
+ this[kClosedResolve] = resolve9;
61762
62107
  });
61763
62108
  }
61764
62109
  }
@@ -61926,7 +62271,7 @@ var require_balanced_pool = __commonJS({
61926
62271
  } = require_pool_base();
61927
62272
  var Pool = require_pool();
61928
62273
  var { kUrl, kInterceptors } = require_symbols();
61929
- var { parseOrigin } = require_util();
62274
+ var { parseOrigin: parseOrigin2 } = require_util();
61930
62275
  var kFactory = Symbol("factory");
61931
62276
  var kOptions = Symbol("options");
61932
62277
  var kGreatestCommonDivisor = Symbol("kGreatestCommonDivisor");
@@ -61969,7 +62314,7 @@ var require_balanced_pool = __commonJS({
61969
62314
  this._updateBalancedPoolStats();
61970
62315
  }
61971
62316
  addUpstream(upstream) {
61972
- const upstreamOrigin = parseOrigin(upstream).origin;
62317
+ const upstreamOrigin = parseOrigin2(upstream).origin;
61973
62318
  if (this[kClients].find((pool2) => pool2[kUrl].origin === upstreamOrigin && pool2.closed !== true && pool2.destroyed !== true)) {
61974
62319
  return this;
61975
62320
  }
@@ -62003,7 +62348,7 @@ var require_balanced_pool = __commonJS({
62003
62348
  this[kGreatestCommonDivisor] = result;
62004
62349
  }
62005
62350
  removeUpstream(upstream) {
62006
- const upstreamOrigin = parseOrigin(upstream).origin;
62351
+ const upstreamOrigin = parseOrigin2(upstream).origin;
62007
62352
  const pool = this[kClients].find((pool2) => pool2[kUrl].origin === upstreamOrigin && pool2.closed !== true && pool2.destroyed !== true);
62008
62353
  if (pool) {
62009
62354
  this[kRemoveClient](pool);
@@ -62973,7 +63318,7 @@ var require_readable = __commonJS({
62973
63318
  if (this._readableState.closeEmitted) {
62974
63319
  return null;
62975
63320
  }
62976
- return await new Promise((resolve8, reject) => {
63321
+ return await new Promise((resolve9, reject) => {
62977
63322
  if (this[kContentLength] > limit) {
62978
63323
  this.destroy(new AbortError());
62979
63324
  }
@@ -62986,7 +63331,7 @@ var require_readable = __commonJS({
62986
63331
  if (signal?.aborted) {
62987
63332
  reject(signal.reason ?? new AbortError());
62988
63333
  } else {
62989
- resolve8(null);
63334
+ resolve9(null);
62990
63335
  }
62991
63336
  }).on("error", noop).on("data", function(chunk) {
62992
63337
  limit -= chunk.length;
@@ -63005,7 +63350,7 @@ var require_readable = __commonJS({
63005
63350
  }
63006
63351
  async function consume(stream, type) {
63007
63352
  assert2(!stream[kConsume]);
63008
- return new Promise((resolve8, reject) => {
63353
+ return new Promise((resolve9, reject) => {
63009
63354
  if (isUnusable(stream)) {
63010
63355
  const rState = stream._readableState;
63011
63356
  if (rState.destroyed && rState.closeEmitted === false) {
@@ -63022,7 +63367,7 @@ var require_readable = __commonJS({
63022
63367
  stream[kConsume] = {
63023
63368
  type,
63024
63369
  stream,
63025
- resolve: resolve8,
63370
+ resolve: resolve9,
63026
63371
  reject,
63027
63372
  length: 0,
63028
63373
  body: []
@@ -63092,18 +63437,18 @@ var require_readable = __commonJS({
63092
63437
  return buffer;
63093
63438
  }
63094
63439
  function consumeEnd(consume2) {
63095
- const { type, body: body2, resolve: resolve8, stream, length } = consume2;
63440
+ const { type, body: body2, resolve: resolve9, stream, length } = consume2;
63096
63441
  try {
63097
63442
  if (type === "text") {
63098
- resolve8(chunksDecode(body2, length));
63443
+ resolve9(chunksDecode(body2, length));
63099
63444
  } else if (type === "json") {
63100
- resolve8(JSON.parse(chunksDecode(body2, length)));
63445
+ resolve9(JSON.parse(chunksDecode(body2, length)));
63101
63446
  } else if (type === "arrayBuffer") {
63102
- resolve8(chunksConcat(body2, length).buffer);
63447
+ resolve9(chunksConcat(body2, length).buffer);
63103
63448
  } else if (type === "blob") {
63104
- resolve8(new Blob(body2, { type: stream[kContentType] }));
63449
+ resolve9(new Blob(body2, { type: stream[kContentType] }));
63105
63450
  } else if (type === "bytes") {
63106
- resolve8(chunksConcat(body2, length));
63451
+ resolve9(chunksConcat(body2, length));
63107
63452
  }
63108
63453
  consumeFinish(consume2);
63109
63454
  } catch (err2) {
@@ -63360,9 +63705,9 @@ var require_api_request = __commonJS({
63360
63705
  };
63361
63706
  function request(opts, callback) {
63362
63707
  if (callback === void 0) {
63363
- return new Promise((resolve8, reject) => {
63708
+ return new Promise((resolve9, reject) => {
63364
63709
  request.call(this, opts, (err2, data) => {
63365
- return err2 ? reject(err2) : resolve8(data);
63710
+ return err2 ? reject(err2) : resolve9(data);
63366
63711
  });
63367
63712
  });
63368
63713
  }
@@ -63585,9 +63930,9 @@ var require_api_stream = __commonJS({
63585
63930
  };
63586
63931
  function stream(opts, factory, callback) {
63587
63932
  if (callback === void 0) {
63588
- return new Promise((resolve8, reject) => {
63933
+ return new Promise((resolve9, reject) => {
63589
63934
  stream.call(this, opts, factory, (err2, data) => {
63590
- return err2 ? reject(err2) : resolve8(data);
63935
+ return err2 ? reject(err2) : resolve9(data);
63591
63936
  });
63592
63937
  });
63593
63938
  }
@@ -63872,9 +64217,9 @@ var require_api_upgrade = __commonJS({
63872
64217
  };
63873
64218
  function upgrade(opts, callback) {
63874
64219
  if (callback === void 0) {
63875
- return new Promise((resolve8, reject) => {
64220
+ return new Promise((resolve9, reject) => {
63876
64221
  upgrade.call(this, opts, (err2, data) => {
63877
- return err2 ? reject(err2) : resolve8(data);
64222
+ return err2 ? reject(err2) : resolve9(data);
63878
64223
  });
63879
64224
  });
63880
64225
  }
@@ -63966,9 +64311,9 @@ var require_api_connect = __commonJS({
63966
64311
  };
63967
64312
  function connect(opts, callback) {
63968
64313
  if (callback === void 0) {
63969
- return new Promise((resolve8, reject) => {
64314
+ return new Promise((resolve9, reject) => {
63970
64315
  connect.call(this, opts, (err2, data) => {
63971
- return err2 ? reject(err2) : resolve8(data);
64316
+ return err2 ? reject(err2) : resolve9(data);
63972
64317
  });
63973
64318
  });
63974
64319
  }
@@ -67830,7 +68175,7 @@ var require_fetch = __commonJS({
67830
68175
  function dispatch({ body: body2 }) {
67831
68176
  const url2 = requestCurrentURL(request);
67832
68177
  const agent = fetchParams.controller.dispatcher;
67833
- return new Promise((resolve8, reject) => agent.dispatch(
68178
+ return new Promise((resolve9, reject) => agent.dispatch(
67834
68179
  {
67835
68180
  path: url2.pathname + url2.search,
67836
68181
  origin: url2.origin,
@@ -67906,7 +68251,7 @@ var require_fetch = __commonJS({
67906
68251
  }
67907
68252
  }
67908
68253
  const onError = this.onError.bind(this);
67909
- resolve8({
68254
+ resolve9({
67910
68255
  status,
67911
68256
  statusText,
67912
68257
  headersList,
@@ -67952,7 +68297,7 @@ var require_fetch = __commonJS({
67952
68297
  for (let i2 = 0; i2 < rawHeaders.length; i2 += 2) {
67953
68298
  headersList.append(bufferToLowerCasedHeaderName(rawHeaders[i2]), rawHeaders[i2 + 1].toString("latin1"), true);
67954
68299
  }
67955
- resolve8({
68300
+ resolve9({
67956
68301
  status,
67957
68302
  statusText: STATUS_CODES[status],
67958
68303
  headersList,
@@ -71591,8 +71936,8 @@ var require_util8 = __commonJS({
71591
71936
  return true;
71592
71937
  }
71593
71938
  function delay(ms) {
71594
- return new Promise((resolve8) => {
71595
- setTimeout(resolve8, ms).unref();
71939
+ return new Promise((resolve9) => {
71940
+ setTimeout(resolve9, ms).unref();
71596
71941
  });
71597
71942
  }
71598
71943
  module2.exports = {
@@ -72280,7 +72625,7 @@ __export(witness_ledger_exports, {
72280
72625
  summarizeWitnessLedger: () => summarizeWitnessLedger,
72281
72626
  witnessLedgerPath: () => witnessLedgerPath
72282
72627
  });
72283
- import { appendFileSync as appendFileSync3, existsSync as existsSync26, readFileSync as readFileSync29, writeFileSync as writeFileSync20 } from "node:fs";
72628
+ import { appendFileSync as appendFileSync3, existsSync as existsSync27, readFileSync as readFileSync30, writeFileSync as writeFileSync21 } from "node:fs";
72284
72629
  import { join as join33 } from "node:path";
72285
72630
  function witnessLedgerPath(configDir) {
72286
72631
  return join33(configDir, "witness-ledger.jsonl");
@@ -72289,18 +72634,18 @@ function appendWitnessLedger(configDir, entry) {
72289
72634
  const path2 = witnessLedgerPath(configDir);
72290
72635
  try {
72291
72636
  appendFileSync3(path2, JSON.stringify(entry) + "\n");
72292
- const lines = readFileSync29(path2, "utf8").split("\n").filter(Boolean);
72637
+ const lines = readFileSync30(path2, "utf8").split("\n").filter(Boolean);
72293
72638
  if (lines.length > LEDGER_MAX_LINES) {
72294
- writeFileSync20(path2, lines.slice(-Math.floor(LEDGER_MAX_LINES / 2)).join("\n") + "\n");
72639
+ writeFileSync21(path2, lines.slice(-Math.floor(LEDGER_MAX_LINES / 2)).join("\n") + "\n");
72295
72640
  }
72296
72641
  } catch {
72297
72642
  }
72298
72643
  }
72299
72644
  function readWitnessLedger(configDir) {
72300
72645
  const path2 = witnessLedgerPath(configDir);
72301
- if (!existsSync26(path2)) return [];
72646
+ if (!existsSync27(path2)) return [];
72302
72647
  try {
72303
- return readFileSync29(path2, "utf8").split("\n").filter(Boolean).map((l) => JSON.parse(l)).filter((e) => typeof e.ts === "number" && typeof e.channel === "string");
72648
+ return readFileSync30(path2, "utf8").split("\n").filter(Boolean).map((l) => JSON.parse(l)).filter((e) => typeof e.ts === "number" && typeof e.channel === "string");
72304
72649
  } catch {
72305
72650
  return [];
72306
72651
  }
@@ -72739,12 +73084,12 @@ var init_report_render = __esm({
72739
73084
 
72740
73085
  // src/cli.ts
72741
73086
  init_src6();
72742
- import { closeSync as closeSync2, existsSync as existsSync37, openSync as openSync2, readFileSync as readFileSync40, renameSync as renameSync6, statSync as statSync11 } from "node:fs";
73087
+ import { closeSync as closeSync2, existsSync as existsSync38, openSync as openSync2, readFileSync as readFileSync41, renameSync as renameSync6, statSync as statSync11 } from "node:fs";
72743
73088
  import { join as join47, resolve as pathResolve2 } from "node:path";
72744
73089
  import { spawn as spawn5 } from "node:child_process";
72745
73090
 
72746
73091
  // src/daemon.ts
72747
- import { existsSync as existsSync28, writeFileSync as writeFileSync23 } from "node:fs";
73092
+ import { existsSync as existsSync29, writeFileSync as writeFileSync24 } from "node:fs";
72748
73093
 
72749
73094
  // ../../node_modules/.pnpm/@hono+node-server@1.19.11_hono@4.12.8/node_modules/@hono/node-server/dist/index.mjs
72750
73095
  import { createServer as createServerHTTP } from "http";
@@ -73174,7 +73519,7 @@ var responseViaResponseObject = async (res, outgoing, options = {}) => {
73174
73519
  });
73175
73520
  if (!chunk) {
73176
73521
  if (i2 === 1) {
73177
- await new Promise((resolve8) => setTimeout(resolve8));
73522
+ await new Promise((resolve9) => setTimeout(resolve9));
73178
73523
  maxReadCount = 3;
73179
73524
  continue;
73180
73525
  }
@@ -73325,7 +73670,7 @@ init_lock();
73325
73670
 
73326
73671
  // src/engine.ts
73327
73672
  import { execFileSync as execFileSync5 } from "node:child_process";
73328
- import { existsSync as existsSync27, statSync as statSync8, appendFileSync as appendFileSync4, readdirSync as readdirSync10, renameSync as renameSync4, readFileSync as readFileSync31, writeFileSync as writeFileSync22 } from "node:fs";
73673
+ import { existsSync as existsSync28, statSync as statSync8, appendFileSync as appendFileSync4, readdirSync as readdirSync10, renameSync as renameSync4, readFileSync as readFileSync32, writeFileSync as writeFileSync23 } from "node:fs";
73329
73674
  import { basename as basename7, join as join35, relative as relative6, sep as sep4 } from "node:path";
73330
73675
 
73331
73676
  // src/source-watcher.ts
@@ -74187,7 +74532,7 @@ var NodeFsHandler = class {
74187
74532
  this._addToNodeFs(path2, initialAdd, wh, depth + 1);
74188
74533
  }
74189
74534
  }).on(EV.ERROR, this._boundHandleError);
74190
- return new Promise((resolve8, reject) => {
74535
+ return new Promise((resolve9, reject) => {
74191
74536
  if (!stream)
74192
74537
  return reject();
74193
74538
  stream.once(STR_END, () => {
@@ -74196,7 +74541,7 @@ var NodeFsHandler = class {
74196
74541
  return;
74197
74542
  }
74198
74543
  const wasThrottled = throttler ? throttler.clear() : false;
74199
- resolve8(void 0);
74544
+ resolve9(void 0);
74200
74545
  previous.getChildren().filter((item2) => {
74201
74546
  return item2 !== directory && !current.has(item2);
74202
74547
  }).forEach((item2) => {
@@ -75364,13 +75709,162 @@ async function chat(req) {
75364
75709
  // src/engine.ts
75365
75710
  init_src11();
75366
75711
  init_src6();
75712
+ init_session_registry();
75367
75713
  init_recall_signal();
75714
+
75715
+ // src/subagent-state.ts
75716
+ init_src5();
75717
+ var SPAWN_CLAIM_TTL_MS = 2 * 6e4;
75718
+ var SUBAGENT_IDLE_TTL_MS = 60 * 6e4;
75719
+ var MAX_AGENTS = 200;
75720
+ var SEED_INTENT_MAX_CHARS = 400;
75721
+ function seedIntentOf(toolInput) {
75722
+ const prompt = typeof toolInput["prompt"] === "string" ? toolInput["prompt"] : "";
75723
+ const stated = parseIntentFences(prompt)[0]?.intent;
75724
+ if (stated) return stated;
75725
+ const description = typeof toolInput["description"] === "string" ? toolInput["description"].trim() : "";
75726
+ const body2 = prompt.replace(/```errata-[\s\S]*?```/g, " ").replace(/\s+/g, " ").trim();
75727
+ const seed = [description, body2].filter(Boolean).join(" \u2014 ");
75728
+ return seed.length > SEED_INTENT_MAX_CHARS ? `${seed.slice(0, SEED_INTENT_MAX_CHARS - 1)}\u2026` : seed;
75729
+ }
75730
+ function createSubagentState() {
75731
+ const pending = /* @__PURE__ */ new Map();
75732
+ const agents = /* @__PURE__ */ new Map();
75733
+ const sweep = (nowMs) => {
75734
+ for (const [id, a] of agents) if (nowMs - a.lastSeenMs > SUBAGENT_IDLE_TTL_MS) agents.delete(id);
75735
+ while (agents.size > MAX_AGENTS) agents.delete(agents.keys().next().value);
75736
+ for (const [sid, list] of pending) {
75737
+ const live3 = list.filter((s) => nowMs - s.atMs <= SPAWN_CLAIM_TTL_MS);
75738
+ if (live3.length) pending.set(sid, live3);
75739
+ else pending.delete(sid);
75740
+ }
75741
+ };
75742
+ const touch = (agentId, nowMs) => {
75743
+ const a = agents.get(agentId);
75744
+ if (!a) return void 0;
75745
+ if (nowMs - a.lastSeenMs > SUBAGENT_IDLE_TTL_MS) {
75746
+ agents.delete(agentId);
75747
+ return void 0;
75748
+ }
75749
+ a.lastSeenMs = nowMs;
75750
+ return a;
75751
+ };
75752
+ return {
75753
+ noteSpawn(sessionId, toolInput, nowMs) {
75754
+ sweep(nowMs);
75755
+ const prompt = typeof toolInput["prompt"] === "string" ? toolInput["prompt"] : "";
75756
+ const agentType = typeof toolInput["subagent_type"] === "string" ? toolInput["subagent_type"] : "";
75757
+ const list = pending.get(sessionId) ?? [];
75758
+ list.push({ agentType, seedIntent: seedIntentOf(toolInput), share: parseShareFence(prompt), atMs: nowMs });
75759
+ pending.set(sessionId, list);
75760
+ },
75761
+ start({ sessionId, agentId, agentType, taskDescription }, nowMs) {
75762
+ const existing = touch(agentId, nowMs);
75763
+ if (existing) return existing;
75764
+ sweep(nowMs);
75765
+ const list = pending.get(sessionId) ?? [];
75766
+ const i2 = list.findIndex((s) => s.agentType === agentType || s.agentType === "");
75767
+ const spawn6 = i2 >= 0 ? list.splice(i2, 1)[0] : void 0;
75768
+ const seed = spawn6?.seedIntent || (taskDescription ?? "").trim();
75769
+ const entry = {
75770
+ sessionId,
75771
+ agentType,
75772
+ ...seed ? { intent: seed } : {},
75773
+ ownIntent: false,
75774
+ share: spawn6?.share ?? null,
75775
+ lastSeenMs: nowMs
75776
+ };
75777
+ agents.set(agentId, entry);
75778
+ return entry;
75779
+ },
75780
+ get: (agentId, nowMs) => touch(agentId, nowMs),
75781
+ setIntent(agentId, text, nowMs) {
75782
+ const a = touch(agentId, nowMs);
75783
+ const trimmed = text.trim();
75784
+ if (!a || !trimmed) return false;
75785
+ const changed = a.intent !== trimmed;
75786
+ a.intent = trimmed;
75787
+ a.ownIntent = true;
75788
+ return changed;
75789
+ },
75790
+ setWorkingFile(agentId, rel, nowMs) {
75791
+ const a = touch(agentId, nowMs);
75792
+ if (!a || a.workingFile === rel) return false;
75793
+ a.workingFile = rel;
75794
+ return true;
75795
+ },
75796
+ stop(agentId) {
75797
+ agents.delete(agentId);
75798
+ }
75799
+ };
75800
+ }
75801
+
75802
+ // src/subagent-context.ts
75803
+ init_src6();
75804
+ init_src5();
75805
+ init_src2();
75806
+ init_recall_signal();
75807
+ var MAX_SHARED_PRIORS = 8;
75808
+ var INTENT_HITS = 4;
75809
+ function resolveSharedPriors(store, wanted, handleMap, remote) {
75810
+ const out2 = [];
75811
+ const seen = /* @__PURE__ */ new Set();
75812
+ for (const ref of wanted) {
75813
+ const id = handleMap[ref]?.id ?? ref;
75814
+ const node2 = store.getNode(id) ?? remote.find((n) => n.id === id || priorHandle(n) === ref) ?? void 0;
75815
+ if (!node2 || seen.has(node2.id)) continue;
75816
+ seen.add(node2.id);
75817
+ out2.push(node2);
75818
+ if (out2.length >= MAX_SHARED_PRIORS) break;
75819
+ }
75820
+ return out2;
75821
+ }
75822
+ function renderSubagentBlock(args2) {
75823
+ const { store, entry } = args2;
75824
+ const snapshot = isolateSnapshot(structuredClone(args2.base));
75825
+ if (entry.workingFile) {
75826
+ const slice = sliceForFile(store, entry.workingFile, args2.atCommit);
75827
+ if (slice) snapshot.workingFile = slice;
75828
+ }
75829
+ const hits = entry.intent ? searchByIntent(store, entry.intent, { limit: INTENT_HITS }).map((h) => ({
75830
+ id: h.node.id,
75831
+ label: h.node.label,
75832
+ description: h.node.description,
75833
+ coverage: h.coverage
75834
+ })) : [];
75835
+ const shared = entry.share && !entry.share.all ? resolveSharedPriors(store, entry.share.priors, args2.handleMap, args2.remote) : [];
75836
+ const { body: body2, snapshot: shown } = assembleAgentContext({
75837
+ store,
75838
+ profile: args2.profile,
75839
+ ...args2.atCommit ? { atCommit: args2.atCommit } : {},
75840
+ reviewCount: 0,
75841
+ reviewUiUrl: args2.reviewUiUrl,
75842
+ remote: args2.remote,
75843
+ snapshot,
75844
+ ...args2.edgeElicitation ? { edgeElicitation: args2.edgeElicitation } : {},
75845
+ ...entry.intent ? { statedIntent: { text: entry.intent, hits } } : {},
75846
+ ...shared.length ? { sharedPriors: shared } : {}
75847
+ });
75848
+ const profileNodes = [
75849
+ ...shown.profileContext.languages,
75850
+ ...shown.profileContext.packages,
75851
+ ...shown.profileContext.tools
75852
+ ].flatMap((e) => e.node ? [e.node] : []);
75853
+ return {
75854
+ body: body2,
75855
+ hash: contextHash(body2),
75856
+ card: contextCard(store, shown),
75857
+ handleNodes: [...shown.sharedPriors ?? [], ...shown.motifs, ...shown.remote ?? [], ...profileNodes]
75858
+ };
75859
+ }
75860
+
75861
+ // src/engine.ts
75368
75862
  init_src8();
75369
75863
  init_review2();
75370
75864
 
75371
75865
  // src/turn.ts
75372
75866
  init_checkout_root();
75373
- import { closeSync, existsSync as existsSync18, fstatSync, openSync, readdirSync as readdirSync6, readSync, realpathSync, statSync as statSync6 } from "node:fs";
75867
+ import { closeSync, existsSync as existsSync19, fstatSync, openSync, readdirSync as readdirSync6, readSync, realpathSync as realpathSync2, statSync as statSync6 } from "node:fs";
75374
75868
  import { basename as basename5, delimiter, dirname as dirname10, join as join21, normalize as normalize3 } from "node:path";
75375
75869
  import { homedir as homedir4 } from "node:os";
75376
75870
  import { createHash as createHash16 } from "node:crypto";
@@ -75763,7 +76257,7 @@ function claudeProjectDir(cwd, home = homedir4()) {
75763
76257
  }
75764
76258
  function recentTranscripts(cwd, opts = {}) {
75765
76259
  const dir = claudeProjectDir(cwd, opts.home ?? homedir4());
75766
- if (!existsSync18(dir)) return [];
76260
+ if (!existsSync19(dir)) return [];
75767
76261
  let names;
75768
76262
  try {
75769
76263
  names = readdirSync6(dir);
@@ -75790,7 +76284,7 @@ function recentTranscripts(cwd, opts = {}) {
75790
76284
  function subagentTranscripts(mainTranscriptPath, sessionId) {
75791
76285
  if (!mainTranscriptPath || !sessionId) return [];
75792
76286
  const dir = join21(dirname10(mainTranscriptPath), sessionId, "subagents");
75793
- if (!existsSync18(dir)) return [];
76287
+ if (!existsSync19(dir)) return [];
75794
76288
  let names;
75795
76289
  try {
75796
76290
  names = readdirSync6(dir);
@@ -75874,7 +76368,7 @@ function codexRolloutsForCwd(cwd, opts = {}) {
75874
76368
  const owner = checkoutRootOf(cwd);
75875
76369
  const owners = /* @__PURE__ */ new Map();
75876
76370
  for (const root of codexSessionRoots(opts.env, opts.home)) {
75877
- if (!existsSync18(root)) {
76371
+ if (!existsSync19(root)) {
75878
76372
  codexRolloutActivity.delete(root);
75879
76373
  continue;
75880
76374
  }
@@ -75944,7 +76438,7 @@ function geminiProjectHash(cwd) {
75944
76438
  function geminiHashesFor(cwd) {
75945
76439
  const variants = /* @__PURE__ */ new Set([cwd, cwd.replace(/\/+$/, "")]);
75946
76440
  try {
75947
- variants.add(realpathSync(cwd));
76441
+ variants.add(realpathSync2(cwd));
75948
76442
  } catch {
75949
76443
  }
75950
76444
  return new Set([...variants].map(geminiProjectHash));
@@ -75975,7 +76469,7 @@ function geminiTranscriptsForCwd(cwd, opts = {}) {
75975
76469
  const hashes = geminiHashesFor(cwd);
75976
76470
  const out2 = [];
75977
76471
  for (const root of geminiSessionRoots(opts.env, opts.home)) {
75978
- if (!existsSync18(root)) continue;
76472
+ if (!existsSync19(root)) continue;
75979
76473
  let slugs;
75980
76474
  try {
75981
76475
  slugs = readdirSync6(root);
@@ -76041,12 +76535,12 @@ function opencodeTranscriptsForCwd(cwd, opts = {}) {
76041
76535
  const limit = opts.limit ?? 25;
76042
76536
  const want = /* @__PURE__ */ new Set([cwd, cwd.replace(/\/+$/, "")]);
76043
76537
  try {
76044
- want.add(realpathSync(cwd));
76538
+ want.add(realpathSync2(cwd));
76045
76539
  } catch {
76046
76540
  }
76047
76541
  const out2 = [];
76048
76542
  for (const root of opencodeSessionRoots(opts.env, opts.home)) {
76049
- if (!existsSync18(root)) continue;
76543
+ if (!existsSync19(root)) continue;
76050
76544
  let names;
76051
76545
  try {
76052
76546
  names = readdirSync6(root);
@@ -76078,7 +76572,7 @@ init_src2();
76078
76572
  init_agent_signals();
76079
76573
  init_tool_index();
76080
76574
  init_src5();
76081
- import { readFileSync as readFileSync17, writeFileSync as writeFileSync13 } from "node:fs";
76575
+ import { readFileSync as readFileSync18, writeFileSync as writeFileSync14 } from "node:fs";
76082
76576
  var NEG = /n['']t|\b(?:not|never|no|none|neither|nor|unrelated|irrelevant|would|might|could|if)\b/i;
76083
76577
  var CITE_GROUP_RE = /\(((?:[^()\n]|\([^()\n]*\)){1,200})\)/g;
76084
76578
  var HANDLE_RE = /\[([a-z0-9][\w-]{0,80})\]|((?:pat|sol|drc|dcause|dfix|dprob|dvuln|prob|claim|err)_[0-9a-f]{6,})/gi;
@@ -76811,13 +77305,13 @@ function writePrimingHandles(path2, nodes, now = Date.now()) {
76811
77305
  entries.sort((a, b) => (b[1].seenAt ?? 0) - (a[1].seenAt ?? 0));
76812
77306
  entries.length = HANDLE_MAP_MAX;
76813
77307
  }
76814
- writeFileSync13(path2, JSON.stringify(Object.fromEntries(entries)));
77308
+ writeFileSync14(path2, JSON.stringify(Object.fromEntries(entries)));
76815
77309
  } catch {
76816
77310
  }
76817
77311
  }
76818
77312
  function readPrimingHandles(path2) {
76819
77313
  try {
76820
- return JSON.parse(readFileSync17(path2, "utf8"));
77314
+ return JSON.parse(readFileSync18(path2, "utf8"));
76821
77315
  } catch {
76822
77316
  return {};
76823
77317
  }
@@ -77297,7 +77791,7 @@ ${conversation}` }]
77297
77791
  // src/constraint-backfill.ts
77298
77792
  init_src5();
77299
77793
  init_src2();
77300
- import { existsSync as existsSync19, readFileSync as readFileSync18, readdirSync as readdirSync7, writeFileSync as writeFileSync14 } from "node:fs";
77794
+ import { existsSync as existsSync20, readFileSync as readFileSync19, readdirSync as readdirSync7, writeFileSync as writeFileSync15 } from "node:fs";
77301
77795
  import { join as join22 } from "node:path";
77302
77796
  import { homedir as homedir5 } from "node:os";
77303
77797
  var BACKFILL_VERSION = 1;
@@ -77316,9 +77810,9 @@ function markerPath(configDir) {
77316
77810
  }
77317
77811
  function alreadyDone(configDir) {
77318
77812
  const p = markerPath(configDir);
77319
- if (!existsSync19(p)) return false;
77813
+ if (!existsSync20(p)) return false;
77320
77814
  try {
77321
- const raw2 = JSON.parse(readFileSync18(p, "utf8"));
77815
+ const raw2 = JSON.parse(readFileSync19(p, "utf8"));
77322
77816
  return raw2?.version === BACKFILL_VERSION;
77323
77817
  } catch {
77324
77818
  return false;
@@ -77328,7 +77822,7 @@ function replay(root) {
77328
77822
  const statements = /* @__PURE__ */ new Set();
77329
77823
  const citedByFix = /* @__PURE__ */ new Set();
77330
77824
  const dir = claudeProjectDir(root, homedir5());
77331
- if (!existsSync19(dir)) return { statements, citedByFix };
77825
+ if (!existsSync20(dir)) return { statements, citedByFix };
77332
77826
  let names;
77333
77827
  try {
77334
77828
  names = readdirSync7(dir).filter((n) => n.endsWith(".jsonl"));
@@ -77338,7 +77832,7 @@ function replay(root) {
77338
77832
  for (const f of names) {
77339
77833
  let lines;
77340
77834
  try {
77341
- lines = readFileSync18(join22(dir, f), "utf8").split("\n");
77835
+ lines = readFileSync19(join22(dir, f), "utf8").split("\n");
77342
77836
  } catch {
77343
77837
  continue;
77344
77838
  }
@@ -77452,7 +77946,7 @@ function backfillConstraintKind(store, opts) {
77452
77946
  }
77453
77947
  });
77454
77948
  try {
77455
- writeFileSync14(
77949
+ writeFileSync15(
77456
77950
  markerPath(opts.configDir),
77457
77951
  JSON.stringify({ version: BACKFILL_VERSION, at: opts.now, ...report, cloudTwins: report.cloudTwins.length }, null, 2),
77458
77952
  "utf8"
@@ -77465,7 +77959,7 @@ function backfillConstraintKind(store, opts) {
77465
77959
  // src/edge-repair.ts
77466
77960
  init_src();
77467
77961
  init_src5();
77468
- import { existsSync as existsSync20, readFileSync as readFileSync19, writeFileSync as writeFileSync15 } from "node:fs";
77962
+ import { existsSync as existsSync21, readFileSync as readFileSync20, writeFileSync as writeFileSync16 } from "node:fs";
77469
77963
  import { join as join23 } from "node:path";
77470
77964
  function citeEdgeId(from, type, to) {
77471
77965
  return `edge_${digest({ from, type, to })}`.slice(0, 24);
@@ -77485,9 +77979,9 @@ function markerPath2(configDir) {
77485
77979
  }
77486
77980
  function alreadyDone2(configDir) {
77487
77981
  const p = markerPath2(configDir);
77488
- if (!existsSync20(p)) return false;
77982
+ if (!existsSync21(p)) return false;
77489
77983
  try {
77490
- return JSON.parse(readFileSync19(p, "utf8"))?.version === EDGE_REPAIR_VERSION;
77984
+ return JSON.parse(readFileSync20(p, "utf8"))?.version === EDGE_REPAIR_VERSION;
77491
77985
  } catch {
77492
77986
  return false;
77493
77987
  }
@@ -77536,7 +78030,7 @@ function repairInvalidEdges(store, opts) {
77536
78030
  });
77537
78031
  store.pruneEdgeRejections(opts.now - REJECTION_RETENTION_MS);
77538
78032
  try {
77539
- writeFileSync15(
78033
+ writeFileSync16(
77540
78034
  markerPath2(opts.configDir),
77541
78035
  JSON.stringify({ version: EDGE_REPAIR_VERSION, at: opts.now, ...report }, null, 2),
77542
78036
  "utf8"
@@ -77550,7 +78044,7 @@ function repairInvalidEdges(store, opts) {
77550
78044
  init_reconcile();
77551
78045
 
77552
78046
  // src/pass-ledger.ts
77553
- import { appendFileSync as appendFileSync2, existsSync as existsSync21, readFileSync as readFileSync20, writeFileSync as writeFileSync16 } from "node:fs";
78047
+ import { appendFileSync as appendFileSync2, existsSync as existsSync22, readFileSync as readFileSync21, writeFileSync as writeFileSync17 } from "node:fs";
77554
78048
  import { join as join24 } from "node:path";
77555
78049
 
77556
78050
  // src/isolate-census.ts
@@ -77603,7 +78097,7 @@ function appendPassLedger(configDir, kind, durationMs, counts) {
77603
78097
  return;
77604
78098
  }
77605
78099
  appendsSinceTrim.set(path2, 0);
77606
- const lines = readFileSync20(path2, "utf8").split("\n").filter(Boolean);
78100
+ const lines = readFileSync21(path2, "utf8").split("\n").filter(Boolean);
77607
78101
  const keptByKind = /* @__PURE__ */ new Map();
77608
78102
  const kept = [];
77609
78103
  for (let i2 = lines.length - 1; i2 >= 0; i2--) {
@@ -77619,16 +78113,16 @@ function appendPassLedger(configDir, kind, durationMs, counts) {
77619
78113
  kept.push(lines[i2]);
77620
78114
  }
77621
78115
  if (kept.length < lines.length) {
77622
- writeFileSync16(path2, kept.reverse().join("\n") + "\n");
78116
+ writeFileSync17(path2, kept.reverse().join("\n") + "\n");
77623
78117
  }
77624
78118
  } catch {
77625
78119
  }
77626
78120
  }
77627
78121
  function readPassLedger(configDir) {
77628
78122
  const path2 = passLedgerPath(configDir);
77629
- if (!existsSync21(path2)) return [];
78123
+ if (!existsSync22(path2)) return [];
77630
78124
  try {
77631
- return readFileSync20(path2, "utf8").split("\n").filter(Boolean).map((l) => JSON.parse(l)).filter(
78125
+ return readFileSync21(path2, "utf8").split("\n").filter(Boolean).map((l) => JSON.parse(l)).filter(
77632
78126
  (e) => typeof e?.ts === "number" && typeof e?.kind === "string" && typeof e?.durationMs === "number"
77633
78127
  ).map((e) => ({ ...e, counts: e.counts ?? {} }));
77634
78128
  } catch {
@@ -77924,8 +78418,8 @@ var PassWorker = class {
77924
78418
  const id = this.nextId++;
77925
78419
  try {
77926
78420
  await this.ready;
77927
- return await new Promise((resolve8, reject) => {
77928
- this.pending.set(id, { resolve: resolve8, reject });
78421
+ return await new Promise((resolve9, reject) => {
78422
+ this.pending.set(id, { resolve: resolve9, reject });
77929
78423
  this.worker.postMessage({ id, kind, ...payload !== void 0 ? { payload } : {} });
77930
78424
  });
77931
78425
  } finally {
@@ -77959,12 +78453,12 @@ var PassWorker = class {
77959
78453
  });
77960
78454
  noteIsolateSpawned();
77961
78455
  this.worker = worker;
77962
- this.ready = new Promise((resolve8, reject) => {
78456
+ this.ready = new Promise((resolve9, reject) => {
77963
78457
  const onReady = (m) => {
77964
78458
  if (m?.ready) {
77965
78459
  worker.off("message", onReady);
77966
78460
  worker.off("error", onErr);
77967
- resolve8();
78461
+ resolve9();
77968
78462
  }
77969
78463
  };
77970
78464
  const onErr = (err2) => reject(err2);
@@ -78009,11 +78503,11 @@ init_outbox();
78009
78503
  init_src10();
78010
78504
  init_src();
78011
78505
  init_src2();
78012
- import { readFileSync as readFileSync21 } from "node:fs";
78506
+ import { readFileSync as readFileSync22 } from "node:fs";
78013
78507
  import { join as join25 } from "node:path";
78014
78508
  function loadClaimIgnorePatterns(workspaceRoot) {
78015
78509
  try {
78016
- return readFileSync21(join25(workspaceRoot, ".errataignore"), "utf8").split(/\r?\n/).map((l) => l.trim()).filter((l) => l.length > 0 && !l.startsWith("#")).map((l) => l.toLowerCase());
78510
+ return readFileSync22(join25(workspaceRoot, ".errataignore"), "utf8").split(/\r?\n/).map((l) => l.trim()).filter((l) => l.length > 0 && !l.startsWith("#")).map((l) => l.toLowerCase());
78017
78511
  } catch {
78018
78512
  return [];
78019
78513
  }
@@ -78391,7 +78885,7 @@ async function pullCloudTriage(shared, cloud, profile, limit = 50) {
78391
78885
  // src/retrieval-stack.ts
78392
78886
  init_src();
78393
78887
  import { execFileSync as execFileSync4 } from "node:child_process";
78394
- import { existsSync as existsSync22, readFileSync as readFileSync22, statSync as statSync7 } from "node:fs";
78888
+ import { existsSync as existsSync23, readFileSync as readFileSync23, statSync as statSync7 } from "node:fs";
78395
78889
  import { homedir as homedir6 } from "node:os";
78396
78890
  import { join as join26 } from "node:path";
78397
78891
  var RETRIEVAL_STACK_CAP = 24;
@@ -78683,7 +79177,7 @@ function mavenGroupIsSelfDisclosing(name2, selfTokens) {
78683
79177
  function loadRegistryPolicy(root, env2 = process.env, repoLocator) {
78684
79178
  const read2 = (p) => {
78685
79179
  try {
78686
- return readFileSync22(p, "utf8");
79180
+ return readFileSync23(p, "utf8");
78687
79181
  } catch {
78688
79182
  return null;
78689
79183
  }
@@ -78909,7 +79403,7 @@ function readDirectDependencies(root) {
78909
79403
  for (const c of LOCKFILES) {
78910
79404
  if (familiesSeen.has(c.family)) continue;
78911
79405
  const p = join26(root, c.file);
78912
- if (!existsSync22(p)) continue;
79406
+ if (!existsSync23(p)) continue;
78913
79407
  try {
78914
79408
  const s = statSync7(p);
78915
79409
  stamps.push(`${c.file}:${s.mtimeMs}:${s.size}`);
@@ -78929,7 +79423,7 @@ function readDirectDependencies(root) {
78929
79423
  const direct = [];
78930
79424
  for (const { c, path: path2 } of found) {
78931
79425
  try {
78932
- direct.push(...c.parse(readFileSync22(path2, "utf8")).direct ?? []);
79426
+ direct.push(...c.parse(readFileSync23(path2, "utf8")).direct ?? []);
78933
79427
  } catch {
78934
79428
  }
78935
79429
  }
@@ -78972,14 +79466,14 @@ function manifestPaths(root) {
78972
79466
  "project.godot"
78973
79467
  ];
78974
79468
  return {
78975
- paths: ROOT_MANIFESTS.filter((f) => existsSync22(join26(root, f))),
79469
+ paths: ROOT_MANIFESTS.filter((f) => existsSync23(join26(root, f))),
78976
79470
  tracked: false,
78977
79471
  truncated: false
78978
79472
  };
78979
79473
  }
78980
79474
  var WORKSPACE_MARKERS = ["pnpm-workspace.yaml", "lerna.json", "go.work", "settings.gradle", "settings.gradle.kts"];
78981
79475
  function rootDeclaresWorkspace(root, texts) {
78982
- if (WORKSPACE_MARKERS.some((f) => existsSync22(join26(root, f)))) return true;
79476
+ if (WORKSPACE_MARKERS.some((f) => existsSync23(join26(root, f)))) return true;
78983
79477
  return /"workspaces"\s*:/.test(texts.get("package.json") ?? "") || /<modules>/.test(texts.get("pom.xml") ?? "") || /^\s*\[workspace\]/m.test(texts.get("Cargo.toml") ?? "");
78984
79478
  }
78985
79479
  var EMPTY_SCAN = { deps: [], self: [], complete: true };
@@ -78997,7 +79491,7 @@ function scanManifests(root) {
78997
79491
  try {
78998
79492
  const s = statSync7(abs);
78999
79493
  stamps.push(`${rel}:${s.mtimeMs}:${s.size}`);
79000
- texts.set(rel, readFileSync22(abs, "utf8"));
79494
+ texts.set(rel, readFileSync23(abs, "utf8"));
79001
79495
  } catch {
79002
79496
  }
79003
79497
  }
@@ -79033,11 +79527,11 @@ function readRetrievalInputs(root, repoLocator) {
79033
79527
  }
79034
79528
 
79035
79529
  // src/git-sensor.ts
79036
- import { existsSync as existsSync23, readFileSync as readFileSync23, watch as fsWatch } from "node:fs";
79530
+ import { existsSync as existsSync24, readFileSync as readFileSync24, watch as fsWatch } from "node:fs";
79037
79531
  import { join as join27 } from "node:path";
79038
79532
  function readFirstLine(path2) {
79039
79533
  try {
79040
- return readFileSync23(path2, "utf8").split(/\r?\n/, 1)[0].trim();
79534
+ return readFileSync24(path2, "utf8").split(/\r?\n/, 1)[0].trim();
79041
79535
  } catch {
79042
79536
  return null;
79043
79537
  }
@@ -79056,13 +79550,13 @@ function readGitRefState(gitDir) {
79056
79550
  return {
79057
79551
  branch,
79058
79552
  sha: sha2,
79059
- mergeHeadExists: existsSync23(join27(gitDir, "MERGE_HEAD")),
79060
- origHeadExists: existsSync23(join27(gitDir, "ORIG_HEAD"))
79553
+ mergeHeadExists: existsSync24(join27(gitDir, "MERGE_HEAD")),
79554
+ origHeadExists: existsSync24(join27(gitDir, "ORIG_HEAD"))
79061
79555
  };
79062
79556
  }
79063
79557
  function shaFromPackedRefs(gitDir, ref) {
79064
79558
  try {
79065
- for (const line of readFileSync23(join27(gitDir, "packed-refs"), "utf8").split(/\r?\n/)) {
79559
+ for (const line of readFileSync24(join27(gitDir, "packed-refs"), "utf8").split(/\r?\n/)) {
79066
79560
  const [sha2, name2] = line.split(/\s+/);
79067
79561
  if (name2 === ref && sha2) return sha2;
79068
79562
  }
@@ -79096,7 +79590,7 @@ function startGitSensor(gitDir, onEvent, opts = {}) {
79096
79590
  const settle = () => {
79097
79591
  if (timer) clearTimeout(timer);
79098
79592
  timer = setTimeout(() => {
79099
- if (existsSync23(join27(gitDir, "index.lock"))) {
79593
+ if (existsSync24(join27(gitDir, "index.lock"))) {
79100
79594
  settle();
79101
79595
  return;
79102
79596
  }
@@ -79127,7 +79621,7 @@ function startGitSensor(gitDir, onEvent, opts = {}) {
79127
79621
  // src/git-delta.ts
79128
79622
  import { execFile } from "node:child_process";
79129
79623
  function git(repoDir, args2) {
79130
- return new Promise((resolve8, reject) => {
79624
+ return new Promise((resolve9, reject) => {
79131
79625
  execFile(
79132
79626
  "git",
79133
79627
  ["-C", repoDir, ...args2],
@@ -79138,7 +79632,7 @@ function git(repoDir, args2) {
79138
79632
  // git-sensor runs on every commit/checkout.
79139
79633
  windowsHide: true
79140
79634
  },
79141
- (err2, stdout) => err2 ? reject(err2) : resolve8(stdout)
79635
+ (err2, stdout) => err2 ? reject(err2) : resolve9(stdout)
79142
79636
  );
79143
79637
  });
79144
79638
  }
@@ -79331,7 +79825,7 @@ var TelemetryRecorder = class {
79331
79825
  };
79332
79826
 
79333
79827
  // src/file-activity.ts
79334
- import { readFileSync as readFileSync25 } from "node:fs";
79828
+ import { readFileSync as readFileSync26 } from "node:fs";
79335
79829
  import { join as join29 } from "node:path";
79336
79830
  import { createHash as createHash17 } from "node:crypto";
79337
79831
 
@@ -80084,7 +80578,7 @@ init_git_remote();
80084
80578
  // src/history-bundle.ts
80085
80579
  init_src();
80086
80580
  import { execFile as execFile2 } from "node:child_process";
80087
- import { readFileSync as readFileSync24 } from "node:fs";
80581
+ import { readFileSync as readFileSync25 } from "node:fs";
80088
80582
  import { join as join28 } from "node:path";
80089
80583
  var DEFAULT_MAX_TOKENS = 6e3;
80090
80584
  var FILE_LIST_CAP = 60;
@@ -80120,7 +80614,7 @@ function pathAllowedByFloor(path2) {
80120
80614
  function loadRepoIgnore(root, extraPatterns = []) {
80121
80615
  let source = "";
80122
80616
  try {
80123
- source = readFileSync24(join28(root, ".errataignore"), "utf8");
80617
+ source = readFileSync25(join28(root, ".errataignore"), "utf8");
80124
80618
  } catch {
80125
80619
  source = "";
80126
80620
  }
@@ -80296,12 +80790,12 @@ function headerPaths(diff) {
80296
80790
  return out2.filter((p) => p !== "/dev/null");
80297
80791
  }
80298
80792
  function git2(repoDir, args2) {
80299
- return new Promise((resolve8, reject) => {
80793
+ return new Promise((resolve9, reject) => {
80300
80794
  execFile2(
80301
80795
  "git",
80302
80796
  ["-C", repoDir, ...args2],
80303
80797
  { encoding: "utf8", maxBuffer: 64 * 1024 * 1024, windowsHide: true },
80304
- (err2, stdout) => err2 ? reject(err2) : resolve8(stdout)
80798
+ (err2, stdout) => err2 ? reject(err2) : resolve9(stdout)
80305
80799
  );
80306
80800
  });
80307
80801
  }
@@ -80413,7 +80907,7 @@ function readActivityBranch(root) {
80413
80907
  try {
80414
80908
  const gitDir = resolveGitDir(root);
80415
80909
  if (!gitDir) return null;
80416
- const head2 = readFileSync25(join29(gitDir, "HEAD"), "utf8").trim();
80910
+ const head2 = readFileSync26(join29(gitDir, "HEAD"), "utf8").trim();
80417
80911
  const branch = head2.startsWith("ref: refs/heads/") ? head2.slice(16) : /^[a-f0-9]{40,64}$/i.test(head2) ? "HEAD" : null;
80418
80912
  return branch && branch.length <= 256 && !/[\x00-\x1f\x7f]/.test(branch) ? branch : null;
80419
80913
  } catch {
@@ -80570,21 +81064,21 @@ var FileActivityReporter = class {
80570
81064
 
80571
81065
  // src/skills.ts
80572
81066
  import {
80573
- existsSync as existsSync24,
81067
+ existsSync as existsSync25,
80574
81068
  mkdirSync as mkdirSync7,
80575
- readFileSync as readFileSync26,
81069
+ readFileSync as readFileSync27,
80576
81070
  readdirSync as readdirSync8,
80577
81071
  unlinkSync as unlinkSync4,
80578
- writeFileSync as writeFileSync17
81072
+ writeFileSync as writeFileSync18
80579
81073
  } from "node:fs";
80580
81074
  import { basename as basename6, join as join30 } from "node:path";
80581
81075
  function skillFileName(id) {
80582
81076
  return `${id.replace(/[^A-Za-z0-9_.-]/g, "_")}.md`;
80583
81077
  }
80584
81078
  function readSkillManifest(manifestPath) {
80585
- if (!existsSync24(manifestPath)) return [];
81079
+ if (!existsSync25(manifestPath)) return [];
80586
81080
  try {
80587
- const parsed = JSON.parse(readFileSync26(manifestPath, "utf8"));
81081
+ const parsed = JSON.parse(readFileSync27(manifestPath, "utf8"));
80588
81082
  return (parsed.skills ?? []).map((s) => ({
80589
81083
  title: s.title ?? "",
80590
81084
  layer: s.layer ?? "technique",
@@ -80608,7 +81102,7 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
80608
81102
  for (const s of res.skills) {
80609
81103
  const fileName = skillFileName(s.id);
80610
81104
  keep.add(fileName);
80611
- writeFileSync17(join30(paths.skillsDir, fileName), s.markdown, "utf8");
81105
+ writeFileSync18(join30(paths.skillsDir, fileName), s.markdown, "utf8");
80612
81106
  rows.push({
80613
81107
  id: s.id,
80614
81108
  title: s.title,
@@ -80621,7 +81115,7 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
80621
81115
  const fileName = skillFileName(p.id);
80622
81116
  if (keep.has(fileName)) continue;
80623
81117
  keep.add(fileName);
80624
- writeFileSync17(join30(paths.skillsDir, fileName), p.markdown, "utf8");
81118
+ writeFileSync18(join30(paths.skillsDir, fileName), p.markdown, "utf8");
80625
81119
  rows.push({
80626
81120
  id: p.id,
80627
81121
  title: p.title,
@@ -80641,7 +81135,7 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
80641
81135
  }
80642
81136
  }
80643
81137
  rows.sort((a, b) => a.id.localeCompare(b.id));
80644
- writeFileSync17(
81138
+ writeFileSync18(
80645
81139
  paths.skillsManifest,
80646
81140
  JSON.stringify({ generatedAt: Date.now(), skills: rows }, null, 2),
80647
81141
  "utf8"
@@ -80653,14 +81147,14 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
80653
81147
  init_src2();
80654
81148
  import {
80655
81149
  cpSync,
80656
- existsSync as existsSync25,
81150
+ existsSync as existsSync26,
80657
81151
  lstatSync,
80658
81152
  mkdirSync as mkdirSync8,
80659
- readFileSync as readFileSync27,
81153
+ readFileSync as readFileSync28,
80660
81154
  readdirSync as readdirSync9,
80661
81155
  rmSync as rmSync3,
80662
81156
  symlinkSync,
80663
- writeFileSync as writeFileSync18
81157
+ writeFileSync as writeFileSync19
80664
81158
  } from "node:fs";
80665
81159
  import { join as join31 } from "node:path";
80666
81160
  var SKILL_NS = "errata-";
@@ -80713,7 +81207,7 @@ function skillCiteHandle(s) {
80713
81207
  return priorHandle({ id: s.id, description: s.title });
80714
81208
  }
80715
81209
  function reconcileNamespaced(dir, keep) {
80716
- if (!existsSync25(dir)) return 0;
81210
+ if (!existsSync26(dir)) return 0;
80717
81211
  let pruned = 0;
80718
81212
  for (const name2 of readdirSync9(dir)) {
80719
81213
  if (!name2.startsWith(SKILL_NS) || keep.has(name2)) continue;
@@ -80727,7 +81221,7 @@ function reconcileNamespaced(dir, keep) {
80727
81221
  }
80728
81222
  function linkOrCopy(linkPath, target) {
80729
81223
  try {
80730
- if (existsSync25(linkPath) || safeLstat(linkPath)) rmSync3(linkPath, { recursive: true, force: true });
81224
+ if (existsSync26(linkPath) || safeLstat(linkPath)) rmSync3(linkPath, { recursive: true, force: true });
80731
81225
  } catch {
80732
81226
  }
80733
81227
  try {
@@ -80756,7 +81250,7 @@ function emitAndProjectSkills(root, skills) {
80756
81250
  for (const s of skills) {
80757
81251
  let body2;
80758
81252
  try {
80759
- body2 = readFileSync27(s.bodyPath, "utf8");
81253
+ body2 = readFileSync28(s.bodyPath, "utf8");
80760
81254
  } catch {
80761
81255
  continue;
80762
81256
  }
@@ -80766,7 +81260,7 @@ function emitAndProjectSkills(root, skills) {
80766
81260
  slugs.push(slug2);
80767
81261
  const description = deriveDescription(s.title, s.layer, body2);
80768
81262
  mkdirSync8(join31(agentsSkillsDir, slug2), { recursive: true });
80769
- writeFileSync18(
81263
+ writeFileSync19(
80770
81264
  join31(agentsSkillsDir, slug2, "SKILL.md"),
80771
81265
  renderSkillMd(slug2, description, body2, skillCiteHandle(s)),
80772
81266
  "utf8"
@@ -80776,7 +81270,7 @@ function emitAndProjectSkills(root, skills) {
80776
81270
  reconcileNamespaced(agentsSkillsDir, keep);
80777
81271
  let projected = 0;
80778
81272
  for (const h of HARNESS_SKILL_DIRS) {
80779
- if (!existsSync25(join31(root, h.configDir))) continue;
81273
+ if (!existsSync26(join31(root, h.configDir))) continue;
80780
81274
  const dir = join31(root, h.skillsDir);
80781
81275
  mkdirSync8(dir, { recursive: true });
80782
81276
  for (const slug2 of slugs) {
@@ -80789,9 +81283,9 @@ function emitAndProjectSkills(root, skills) {
80789
81283
  return { slugs, emitted, projected };
80790
81284
  }
80791
81285
  function emitInputsFromManifest(erretaDir, manifestPath) {
80792
- if (!existsSync25(manifestPath)) return [];
81286
+ if (!existsSync26(manifestPath)) return [];
80793
81287
  try {
80794
- const parsed = JSON.parse(readFileSync27(manifestPath, "utf8"));
81288
+ const parsed = JSON.parse(readFileSync28(manifestPath, "utf8"));
80795
81289
  return (parsed.skills ?? []).filter((s) => Boolean(s.id && s.file)).map((s) => ({
80796
81290
  id: s.id,
80797
81291
  title: s.title ?? s.id,
@@ -80814,14 +81308,14 @@ function ensureSkillGitignore(root) {
80814
81308
  const path2 = join31(root, ".gitignore");
80815
81309
  let current = "";
80816
81310
  try {
80817
- current = existsSync25(path2) ? readFileSync27(path2, "utf8") : "";
81311
+ current = existsSync26(path2) ? readFileSync28(path2, "utf8") : "";
80818
81312
  } catch {
80819
81313
  return;
80820
81314
  }
80821
81315
  if (current.includes(GITIGNORE_MARK)) return;
80822
81316
  const prefix = current.length > 0 && !current.endsWith("\n") ? "\n" : "";
80823
81317
  try {
80824
- writeFileSync18(path2, `${current}${prefix}
81318
+ writeFileSync19(path2, `${current}${prefix}
80825
81319
  ${GITIGNORE_LINES.join("\n")}
80826
81320
  `, "utf8");
80827
81321
  } catch {
@@ -80917,7 +81411,7 @@ init_paths();
80917
81411
  init_profile2();
80918
81412
 
80919
81413
  // src/witness-queue.ts
80920
- import { readFileSync as readFileSync28, renameSync as renameSync3, writeFileSync as writeFileSync19 } from "node:fs";
81414
+ import { readFileSync as readFileSync29, renameSync as renameSync3, writeFileSync as writeFileSync20 } from "node:fs";
80921
81415
  import { dirname as dirname11, join as join32 } from "node:path";
80922
81416
  var WITNESS_QUEUE_CAP = 500;
80923
81417
  var WITNESS_TTL_MS = 14 * 24 * 60 * 60 * 1e3;
@@ -80928,7 +81422,7 @@ function witnessQueuePath(workspaceConfigDir) {
80928
81422
  function loadWitnessQueueWithLosses(path2) {
80929
81423
  let raw2;
80930
81424
  try {
80931
- raw2 = JSON.parse(readFileSync28(path2, "utf8"));
81425
+ raw2 = JSON.parse(readFileSync29(path2, "utf8"));
80932
81426
  } catch (err2) {
80933
81427
  const absent = err2?.code === "ENOENT";
80934
81428
  return { queue: [], fileUnreadable: !absent, malformedEntries: 0 };
@@ -80942,7 +81436,7 @@ function loadWitnessQueueWithLosses(path2) {
80942
81436
  function saveWitnessQueue(path2, queue) {
80943
81437
  try {
80944
81438
  const tmp = join32(dirname11(path2), `.${Date.now()}.witness-queue.tmp`);
80945
- writeFileSync19(tmp, JSON.stringify(queue), "utf8");
81439
+ writeFileSync20(tmp, JSON.stringify(queue), "utf8");
80946
81440
  renameSync3(tmp, path2);
80947
81441
  } catch {
80948
81442
  }
@@ -81249,7 +81743,7 @@ function maybeFlushDigests() {
81249
81743
 
81250
81744
  // src/liveness-watch.ts
81251
81745
  init_src5();
81252
- import { readFileSync as readFileSync30, writeFileSync as writeFileSync21 } from "node:fs";
81746
+ import { readFileSync as readFileSync31, writeFileSync as writeFileSync22 } from "node:fs";
81253
81747
  import { join as join34 } from "node:path";
81254
81748
 
81255
81749
  // src/loop-lag.ts
@@ -81385,7 +81879,7 @@ function alarmStatePath(configDir) {
81385
81879
  }
81386
81880
  function loadAlarmState(configDir) {
81387
81881
  try {
81388
- const raw2 = JSON.parse(readFileSync30(alarmStatePath(configDir), "utf8"));
81882
+ const raw2 = JSON.parse(readFileSync31(alarmStatePath(configDir), "utf8"));
81389
81883
  return new Map(Object.entries(raw2).filter((e) => typeof e[1] === "number"));
81390
81884
  } catch {
81391
81885
  return /* @__PURE__ */ new Map();
@@ -81393,7 +81887,7 @@ function loadAlarmState(configDir) {
81393
81887
  }
81394
81888
  function saveAlarmState(configDir, state) {
81395
81889
  try {
81396
- writeFileSync21(alarmStatePath(configDir), JSON.stringify(Object.fromEntries(state)));
81890
+ writeFileSync22(alarmStatePath(configDir), JSON.stringify(Object.fromEntries(state)));
81397
81891
  } catch {
81398
81892
  }
81399
81893
  }
@@ -81593,7 +82087,7 @@ function createWatchBreaker(deps) {
81593
82087
  }
81594
82088
 
81595
82089
  // src/engine.ts
81596
- var DAEMON_VERSION = true ? "2.0.17-dev.3416" : "2.0.0-alpha.0";
82090
+ var DAEMON_VERSION = true ? "2.0.17-dev.3426" : "2.0.0-alpha.0";
81597
82091
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
81598
82092
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
81599
82093
  var GIT_OP_MUTE_MS = 4e3;
@@ -81605,7 +82099,7 @@ var CODEX_SWEEP_LOOKBACK_MS = 10 * 6e4;
81605
82099
  function appendIdentityAudit(path2, record2, line) {
81606
82100
  if (!record2.accepted && record2.score <= 0) return;
81607
82101
  try {
81608
- if (existsSync27(path2) && statSync8(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
82102
+ if (existsSync28(path2) && statSync8(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
81609
82103
  renameSync4(path2, `${path2}.1`);
81610
82104
  }
81611
82105
  appendFileSync4(path2, line);
@@ -81615,7 +82109,7 @@ function appendIdentityAudit(path2, record2, line) {
81615
82109
  var yieldToLoop = () => new Promise((r) => setImmediate(r));
81616
82110
  function loadTurnCursors(path2) {
81617
82111
  try {
81618
- const raw2 = JSON.parse(readFileSync31(path2, "utf8"));
82112
+ const raw2 = JSON.parse(readFileSync32(path2, "utf8"));
81619
82113
  return new Map(
81620
82114
  Object.entries(raw2).map(([k, v]) => [k, typeof v === "string" ? v : String(v?.uuid ?? "")])
81621
82115
  );
@@ -81625,7 +82119,7 @@ function loadTurnCursors(path2) {
81625
82119
  }
81626
82120
  function loadTurnOffsets(path2) {
81627
82121
  try {
81628
- const raw2 = JSON.parse(readFileSync31(path2, "utf8"));
82122
+ const raw2 = JSON.parse(readFileSync32(path2, "utf8"));
81629
82123
  const out2 = /* @__PURE__ */ new Map();
81630
82124
  for (const [k, v] of Object.entries(raw2)) {
81631
82125
  const off = typeof v === "object" && v !== null ? v.offset : void 0;
@@ -81641,7 +82135,7 @@ function saveTurnCursors(path2, cursors, offsets) {
81641
82135
  const merged = {};
81642
82136
  for (const [k, uuid3] of cursors) merged[k] = { uuid: uuid3, offset: offsets.get(k) ?? 0 };
81643
82137
  for (const [k, offset] of offsets) if (!merged[k]) merged[k] = { uuid: "", offset };
81644
- writeFileSync22(path2, JSON.stringify(merged), "utf8");
82138
+ writeFileSync23(path2, JSON.stringify(merged), "utf8");
81645
82139
  } catch {
81646
82140
  }
81647
82141
  }
@@ -81930,7 +82424,7 @@ function createWorkspaceEngine(opts) {
81930
82424
  );
81931
82425
  };
81932
82426
  const gitDir = join35(opts.workspaceRoot, ".git");
81933
- if (existsSync27(gitDir)) {
82427
+ if (existsSync28(gitDir)) {
81934
82428
  stopGit = startGitSensor(gitDir, (ev) => {
81935
82429
  void handleGitEvent(ev).catch((err2) => {
81936
82430
  console.warn("[errata] git event handler failed:", err2);
@@ -81991,6 +82485,13 @@ function createWorkspaceEngine(opts) {
81991
82485
  witnessParked: () => witnessQueue.length
81992
82486
  });
81993
82487
  const intents = createIntentState();
82488
+ const subagents = createSubagentState();
82489
+ let subagentBase = null;
82490
+ let subagentBaseVersion = 0;
82491
+ const subagentRenders = /* @__PURE__ */ new Map();
82492
+ const sessions = createSessionRegistry({ originsPath: join35(paths.configDir, "session-origins.json") });
82493
+ const sessionRenders = /* @__PURE__ */ new Map();
82494
+ const selfCiteSkipsBySession = /* @__PURE__ */ new Map();
81994
82495
  const toolRuns = createToolRunState();
81995
82496
  let ctxRefreshTimer = null;
81996
82497
  let contextDirty = false;
@@ -82046,6 +82547,22 @@ function createWorkspaceEngine(opts) {
82046
82547
  return [];
82047
82548
  }
82048
82549
  };
82550
+ const statedIntentFor = (intent) => {
82551
+ const collective = intentRemote?.forIntent === intent ? intentRemote : null;
82552
+ return {
82553
+ text: intent,
82554
+ hits: searchByIntent(store, intent, { limit: 4 }).map((h) => ({
82555
+ id: h.node.id,
82556
+ label: h.node.label,
82557
+ description: h.node.description,
82558
+ coverage: h.coverage
82559
+ })),
82560
+ ...collective && collective.hits.length > 0 ? {
82561
+ remoteHits: collective.hits.slice(0, 4).map((n) => ({ id: n.id, label: n.label, description: n.description }))
82562
+ } : {},
82563
+ ...collective?.voidSignal ? { knownGap: collective.voidSignal } : {}
82564
+ };
82565
+ };
82049
82566
  const refreshContextOnce = async () => {
82050
82567
  const elicit = isEdgeElicitationEnabled();
82051
82568
  const snapOpts = {
@@ -82069,41 +82586,26 @@ function createWorkspaceEngine(opts) {
82069
82586
  return;
82070
82587
  }
82071
82588
  const doneRender = markPass(`${prebuilt ? "context-render" : "context-render-inline"}:${profile.name}`);
82589
+ const base = prebuilt ?? buildSnapshot({ store, ...snapOpts });
82590
+ subagentBase = structuredClone(base);
82591
+ subagentBaseVersion++;
82592
+ const sharedSnapshot = scopeSnapshot(base, (n) => !isQuarantined(n, sessions));
82072
82593
  const pendingUpdate = opts.pendingUpdate?.() ?? null;
82073
82594
  const daemonDistress = opts.daemonDistress?.() ?? null;
82074
82595
  const reviewItems = pickReviewItems();
82075
82596
  const liveIntent = intents.mostRecent(Date.now());
82076
82597
  maybeRefreshIntentPriors(liveIntent ?? null);
82077
- const intentHits = liveIntent ? searchByIntent(store, liveIntent, { limit: 4 }).map((h) => ({
82078
- id: h.node.id,
82079
- label: h.node.label,
82080
- description: h.node.description,
82081
- coverage: h.coverage
82082
- })) : [];
82083
- const intentCollective = liveIntent && intentRemote?.forIntent === liveIntent ? intentRemote : null;
82598
+ const statedIntent = liveIntent ? statedIntentFor(liveIntent) : null;
82084
82599
  const { body: body2, snapshot, ledger } = assembleAgentContext({
82085
82600
  store,
82086
82601
  ...snapOpts,
82087
82602
  remote: remotePriors,
82088
82603
  ...elicit ? { edgeElicitation: { instruction: PRIOR_TAG_INSTRUCTION } } : {},
82089
- ...prebuilt ? { snapshot: prebuilt } : {},
82604
+ snapshot: sharedSnapshot,
82090
82605
  ...pendingUpdate ? { pendingUpdate } : {},
82091
82606
  ...daemonDistress ? { daemonDistress } : {},
82092
82607
  ...reviewItems.length ? { reviewItems } : {},
82093
- ...liveIntent ? {
82094
- statedIntent: {
82095
- text: liveIntent,
82096
- hits: intentHits,
82097
- ...intentCollective && intentCollective.hits.length > 0 ? {
82098
- remoteHits: intentCollective.hits.slice(0, 4).map((n) => ({
82099
- id: n.id,
82100
- label: n.label,
82101
- description: n.description
82102
- }))
82103
- } : {},
82104
- ...intentCollective?.voidSignal ? { knownGap: intentCollective.voidSignal } : {}
82105
- }
82106
- } : {}
82608
+ ...statedIntent ? { statedIntent } : {}
82107
82609
  });
82108
82610
  doneRender();
82109
82611
  try {
@@ -82408,7 +82910,11 @@ function createWorkspaceEngine(opts) {
82408
82910
  }
82409
82911
  return { report, localSkills: 0 };
82410
82912
  };
82411
- const onWorkingFileChanged = (rel, sessionId) => {
82913
+ const onWorkingFileChanged = (rel, sessionId, agentId) => {
82914
+ if (agentId) {
82915
+ subagents.setWorkingFile(agentId, rel, Date.now());
82916
+ return;
82917
+ }
82412
82918
  if (!workingFiles.set(sessionId, rel)) return;
82413
82919
  contextDirty = true;
82414
82920
  if (ctxRefreshTimer) clearTimeout(ctxRefreshTimer);
@@ -82419,6 +82925,125 @@ function createWorkspaceEngine(opts) {
82419
82925
  }
82420
82926
  }, 500);
82421
82927
  };
82928
+ const onSubagentSpawn = (sessionId, toolInput) => {
82929
+ subagents.noteSpawn(sessionId, toolInput, Date.now());
82930
+ };
82931
+ const subagentContext = (a) => {
82932
+ const now = Date.now();
82933
+ const entry = a.start ? subagents.start(a, now) : subagents.get(a.agentId, now);
82934
+ if (!entry) return null;
82935
+ if (entry.share?.all) {
82936
+ const file2 = readContextFileWithHash(opts.workspaceRoot);
82937
+ return file2 ? { body: file2.body, hash: file2.hash, card: readContextCard(opts.workspaceRoot, file2.hash), handleNodes: [] } : null;
82938
+ }
82939
+ if (!subagentBase) {
82940
+ contextDirty = true;
82941
+ return null;
82942
+ }
82943
+ const key = JSON.stringify([subagentBaseVersion, lastRemoteAt, entry.intent, entry.workingFile, entry.share]);
82944
+ const cached2 = subagentRenders.get(a.agentId);
82945
+ if (cached2?.key === key) return cached2.block;
82946
+ const elicit = isEdgeElicitationEnabled();
82947
+ const handlesPath = join35(paths.configDir, "priming-handles.json");
82948
+ const atCommit = readGitRefState(join35(opts.workspaceRoot, ".git")).sha ?? void 0;
82949
+ const block = renderSubagentBlock({
82950
+ store,
82951
+ entry,
82952
+ base: subagentBase,
82953
+ profile,
82954
+ ...atCommit ? { atCommit } : {},
82955
+ reviewUiUrl: opts.reviewUrl(),
82956
+ remote: remotePriors,
82957
+ handleMap: readPrimingHandles(handlesPath),
82958
+ ...elicit ? { edgeElicitation: { instruction: PRIOR_TAG_INSTRUCTION } } : {}
82959
+ });
82960
+ if (elicit && block.handleNodes.length) writePrimingHandles(handlesPath, block.handleNodes);
82961
+ subagentRenders.delete(a.agentId);
82962
+ subagentRenders.set(a.agentId, { key, block });
82963
+ if (subagentRenders.size > 200) subagentRenders.delete(subagentRenders.keys().next().value);
82964
+ return block;
82965
+ };
82966
+ const onSubagentStop = (agentId) => {
82967
+ subagents.stop(agentId);
82968
+ subagentRenders.delete(agentId);
82969
+ };
82970
+ const noteSession = (e) => {
82971
+ const now = Date.now();
82972
+ if (!e.sessionId) return;
82973
+ const origin = e.origin ? { origin: e.origin } : {};
82974
+ if (e.agentId) {
82975
+ const sub = `agent-${e.agentId}`;
82976
+ if (e.ended) sessions.end(sub);
82977
+ else sessions.touch(sub, now, { parent: e.sessionId, ...origin });
82978
+ sessions.touch(e.sessionId, now, origin);
82979
+ return;
82980
+ }
82981
+ if (e.ended) sessions.end(e.sessionId);
82982
+ else sessions.touch(e.sessionId, now, origin);
82983
+ };
82984
+ const sessionContext = (sessionId) => {
82985
+ if (!sessionId || !subagentBase) return null;
82986
+ const now = Date.now();
82987
+ const intent = intents.get(sessionId, now);
82988
+ const workingFile = workingFiles.get(sessionId);
82989
+ const skips = selfCiteSkipsBySession.get(sessionId) ?? 0;
82990
+ const key = JSON.stringify([
82991
+ subagentBaseVersion,
82992
+ lastRemoteAt,
82993
+ sessions.version(now),
82994
+ intent,
82995
+ workingFile,
82996
+ intentRemote?.forIntent === intent ? intentRemote?.hits.length : -1,
82997
+ skips
82998
+ ]);
82999
+ const cached2 = sessionRenders.get(sessionId);
83000
+ if (cached2?.key === key) return cached2.block;
83001
+ const elicit = isEdgeElicitationEnabled();
83002
+ const atCommit = readGitRefState(join35(opts.workspaceRoot, ".git")).sha ?? void 0;
83003
+ const scoped = scopeSnapshot(structuredClone(subagentBase), (n) => !hiddenFrom(n, sessionId, sessions, now));
83004
+ delete scoped.workingFile;
83005
+ if (workingFile) {
83006
+ const slice = sliceForFile(store, workingFile, atCommit);
83007
+ if (slice) scoped.workingFile = slice;
83008
+ }
83009
+ delete scoped.selfCiteSkips;
83010
+ if (skips > 0) scoped.selfCiteSkips = skips;
83011
+ const pendingUpdate = opts.pendingUpdate?.() ?? null;
83012
+ const daemonDistress = opts.daemonDistress?.() ?? null;
83013
+ const reviewItems = pickReviewItems();
83014
+ const { body: body2, snapshot } = assembleAgentContext({
83015
+ store,
83016
+ profile,
83017
+ ...atCommit ? { atCommit } : {},
83018
+ reviewCount: pendingCount(paths),
83019
+ reviewUiUrl: opts.reviewUrl(),
83020
+ remote: remotePriors,
83021
+ snapshot: scoped,
83022
+ ...elicit ? { edgeElicitation: { instruction: PRIOR_TAG_INSTRUCTION } } : {},
83023
+ ...pendingUpdate ? { pendingUpdate } : {},
83024
+ ...daemonDistress ? { daemonDistress } : {},
83025
+ ...reviewItems.length ? { reviewItems } : {},
83026
+ ...intent ? { statedIntent: statedIntentFor(intent) } : {}
83027
+ });
83028
+ const block = {
83029
+ body: body2,
83030
+ hash: contextHash(body2),
83031
+ card: contextCard(store, snapshot),
83032
+ handleNodes: [
83033
+ ...snapshot.recentProblems.map((r) => r.node),
83034
+ ...snapshot.recentResolved.flatMap((r) => r.solution ? [r.node, r.solution] : [r.node]),
83035
+ ...snapshot.motifs,
83036
+ ...snapshot.remote ?? []
83037
+ ]
83038
+ };
83039
+ if (elicit && block.handleNodes.length) {
83040
+ writePrimingHandles(join35(paths.configDir, "priming-handles.json"), block.handleNodes);
83041
+ }
83042
+ sessionRenders.delete(sessionId);
83043
+ sessionRenders.set(sessionId, { key, block });
83044
+ if (sessionRenders.size > 200) sessionRenders.delete(sessionRenders.keys().next().value);
83045
+ return block;
83046
+ };
82422
83047
  const onHookEvent = (e) => {
82423
83048
  const intentHints = deriveIntentHints(e.tool, e.oldString, e.newString);
82424
83049
  const operation = /(?:edit|write|patch)/i.test(e.tool) ? "write" : /read/i.test(e.tool) ? "read" : null;
@@ -82668,8 +83293,10 @@ function createWorkspaceEngine(opts) {
82668
83293
  }
82669
83294
  const touched = new Set(toolRuns.get(sessionId));
82670
83295
  if (touchedFileId) touched.add(touchedFileId);
83296
+ const fenceAgent = turn.agentId ?? (sessionId.startsWith("agent-") ? sessionId.slice(6) : void 0);
82671
83297
  for (const fence of parseIntentFences(turn.text)) {
82672
- if (intents.set(sessionId, fence.intent, t)) refreshContextNow();
83298
+ if (fenceAgent) subagents.setIntent(fenceAgent, fence.intent, t);
83299
+ else if (intents.set(sessionId, fence.intent, t)) refreshContextNow();
82673
83300
  }
82674
83301
  const plan = harvestInlineTags(store, turn.text, {
82675
83302
  sourceId: sessionLastProblem.get(sessionId),
@@ -82736,7 +83363,7 @@ function createWorkspaceEngine(opts) {
82736
83363
  let anchorReadFailed = false;
82737
83364
  if (p.location) {
82738
83365
  try {
82739
- fileText = readFileSync31(join35(opts.workspaceRoot, p.location.path), "utf8");
83366
+ fileText = readFileSync32(join35(opts.workspaceRoot, p.location.path), "utf8");
82740
83367
  } catch {
82741
83368
  anchorReadFailed = true;
82742
83369
  }
@@ -82896,7 +83523,7 @@ function createWorkspaceEngine(opts) {
82896
83523
  const headSha = readGitRefState(join35(opts.workspaceRoot, ".git")).sha ?? void 0;
82897
83524
  enclosing = {
82898
83525
  line: p.location.line,
82899
- fileText: readFileSync31(join35(opts.workspaceRoot, anchorPath), "utf8"),
83526
+ fileText: readFileSync32(join35(opts.workspaceRoot, anchorPath), "utf8"),
82900
83527
  ...headSha ? { headSha } : {}
82901
83528
  };
82902
83529
  } catch {
@@ -83157,6 +83784,12 @@ function createWorkspaceEngine(opts) {
83157
83784
  }
83158
83785
  const citingSession = sessionOriginKey(sessionId);
83159
83786
  const mintedHere = (nodeId) => store.getNode(nodeId)?.attrs["sources"]?.[0] === sessionId;
83787
+ const synthetic = sessions.originOf(sessionId) !== void 0;
83788
+ if (synthetic && plan.corroborations.length + plan.refutes.length > 0) {
83789
+ console.log(
83790
+ `[errata] witnesses: ${plan.corroborations.length + plan.refutes.length} withheld (session ${sessionId.slice(0, 8)} is ${sessions.originOf(sessionId)})`
83791
+ );
83792
+ }
83160
83793
  const sendWitnesses = async (channel, fresh, send) => {
83161
83794
  const isShipped = (nodeId) => {
83162
83795
  const n = store.getNode(nodeId);
@@ -83281,7 +83914,7 @@ function createWorkspaceEngine(opts) {
83281
83914
  if (typeof cloud.reportContradictions === "function") {
83282
83915
  await sendWitnesses(
83283
83916
  "contradict",
83284
- wireWitnessItems(plan.refutes),
83917
+ synthetic ? [] : wireWitnessItems(plan.refutes),
83285
83918
  (items2, session) => cloud.reportContradictions({
83286
83919
  daemonVersion: DAEMON_VERSION,
83287
83920
  projectId: profile.id,
@@ -83291,12 +83924,13 @@ function createWorkspaceEngine(opts) {
83291
83924
  );
83292
83925
  }
83293
83926
  if (typeof cloud.reportCorroborations === "function") {
83294
- const emit = plan.corroborations.filter((c) => !mintedHere(c.nodeId));
83927
+ const emit = synthetic ? [] : plan.corroborations.filter((c) => !mintedHere(c.nodeId));
83295
83928
  const skipped = plan.corroborations.length - emit.length;
83296
83929
  if (skipped > 0) {
83297
83930
  console.log(`[errata] corroborate: ${skipped} skipped (this session authored the node)`);
83298
83931
  appendWitnessLedger(paths.configDir, { ts: Date.now(), channel: "corroborate", clientSelfSkipped: skipped });
83299
83932
  lastSelfCiteSkips = skipped;
83933
+ selfCiteSkipsBySession.set(sessionId, skipped);
83300
83934
  refreshContextNow();
83301
83935
  }
83302
83936
  await sendWitnesses(
@@ -83478,7 +84112,7 @@ function createWorkspaceEngine(opts) {
83478
84112
  }
83479
84113
  turns = next.turns;
83480
84114
  nextOffset = next.nextOffset;
83481
- await new Promise((resolve8) => setImmediate(resolve8));
84115
+ await new Promise((resolve9) => setImmediate(resolve9));
83482
84116
  }
83483
84117
  };
83484
84118
  const seenMessageIds = /* @__PURE__ */ new Set();
@@ -83493,7 +84127,7 @@ function createWorkspaceEngine(opts) {
83493
84127
  }
83494
84128
  }
83495
84129
  }
83496
- setImmediate(() => void harvestTexts(e.sessionId, [{ text: e.text }]));
84130
+ setImmediate(() => void harvestTexts(e.sessionId, [{ text: e.text, ...e.agentId ? { agentId: e.agentId } : {} }]));
83497
84131
  };
83498
84132
  const harvestInFlight = /* @__PURE__ */ new Map();
83499
84133
  const repairedSessions = /* @__PURE__ */ new Set();
@@ -83732,6 +84366,11 @@ B: ${b}`,
83732
84366
  telemetry,
83733
84367
  webHooks: {
83734
84368
  onWorkingFileChanged,
84369
+ onSubagentSpawn,
84370
+ subagentContext,
84371
+ onSubagentStop,
84372
+ noteSession,
84373
+ sessionContext,
83735
84374
  onHook: () => telemetry.count("hooks_fired"),
83736
84375
  onToolsObserved: (sessionId, toolNodeIds) => toolRuns.record(sessionId, toolNodeIds),
83737
84376
  onHookEvent,
@@ -83749,6 +84388,7 @@ B: ${b}`,
83749
84388
  lastActivityAt() {
83750
84389
  return lastActivityTs;
83751
84390
  },
84391
+ quarantinedSessions: () => sessions.originSessions(),
83752
84392
  markContextDirty() {
83753
84393
  contextDirty = true;
83754
84394
  refreshContextNow();
@@ -84013,15 +84653,19 @@ B: ${b}`,
84013
84653
  console.log(
84014
84654
  "[errata] sync skipped \u2014 cloud sync consent is off (enable with `errata consent sync on`)"
84015
84655
  );
84016
- const pending = existsSync27(paths.outbox) ? readdirSync10(paths.outbox).filter((f) => f.endsWith(".json")).length : 0;
84656
+ const pending = existsSync28(paths.outbox) ? readdirSync10(paths.outbox).filter((f) => f.endsWith(".json")).length : 0;
84017
84657
  return { uploaded: 0, failed: 0, remaining: pending };
84018
84658
  }
84659
+ if (!shipsFromWorkspace(opts.workspaceRoot)) {
84660
+ console.log("[errata] sync skipped \u2014 scratch workspace (under the OS temp dir); its captures stay local");
84661
+ return { uploaded: 0, failed: 0, remaining: 0 };
84662
+ }
84019
84663
  const onDisk = loadProfile(opts.workspaceRoot);
84020
84664
  if (!onDisk?.projectId && onDisk?.projectLinkHold) {
84021
84665
  console.log(
84022
84666
  "[errata] sync held \u2014 this repo is already on errata in another workspace; run `errata link` to join it or create your own project"
84023
84667
  );
84024
- const pending = existsSync27(paths.outbox) ? readdirSync10(paths.outbox).filter((f) => f.endsWith(".json")).length : 0;
84668
+ const pending = existsSync28(paths.outbox) ? readdirSync10(paths.outbox).filter((f) => f.endsWith(".json")).length : 0;
84025
84669
  return { uploaded: 0, failed: 0, remaining: pending };
84026
84670
  }
84027
84671
  try {
@@ -84115,7 +84759,7 @@ async function startDaemon(opts) {
84115
84759
  reviewUrl: () => webUiUrl + "/review"
84116
84760
  });
84117
84761
  const writeLockFile = (url2) => {
84118
- writeFileSync23(
84762
+ writeFileSync24(
84119
84763
  engine.paths.daemonLock,
84120
84764
  daemonLockPayload({ pid: process.pid, webUiUrl: url2, processStartedAt, version: DAEMON_VERSION }),
84121
84765
  "utf8"
@@ -84129,6 +84773,11 @@ async function startDaemon(opts) {
84129
84773
  profile: engine.profile,
84130
84774
  daemonVersion: DAEMON_VERSION,
84131
84775
  onWorkingFileChanged: engine.webHooks.onWorkingFileChanged,
84776
+ onSubagentSpawn: engine.webHooks.onSubagentSpawn,
84777
+ subagentContext: engine.webHooks.subagentContext,
84778
+ onSubagentStop: engine.webHooks.onSubagentStop,
84779
+ noteSession: engine.webHooks.noteSession,
84780
+ sessionContext: engine.webHooks.sessionContext,
84132
84781
  onHook: engine.webHooks.onHook,
84133
84782
  onHookEvent: engine.webHooks.onHookEvent,
84134
84783
  onShellEvent: engine.webHooks.onShellEvent,
@@ -84158,7 +84807,7 @@ async function startDaemon(opts) {
84158
84807
  );
84159
84808
  await engine.stop();
84160
84809
  try {
84161
- if (existsSync28(engine.paths.daemonLock)) {
84810
+ if (existsSync29(engine.paths.daemonLock)) {
84162
84811
  }
84163
84812
  } catch {
84164
84813
  }
@@ -84166,9 +84815,9 @@ async function startDaemon(opts) {
84166
84815
  };
84167
84816
  }
84168
84817
  async function listenServer(fetchFn, port) {
84169
- return new Promise((resolve8) => {
84818
+ return new Promise((resolve9) => {
84170
84819
  const server = serve({ fetch: fetchFn, hostname: "127.0.0.1", port }, (info2) => {
84171
- resolve8({ server, port: info2.port });
84820
+ resolve9({ server, port: info2.port });
84172
84821
  });
84173
84822
  });
84174
84823
  }
@@ -84359,7 +85008,7 @@ function instanceReceiptSequence(n) {
84359
85008
  // src/multi.ts
84360
85009
  init_dist();
84361
85010
  init_src5();
84362
- import { existsSync as existsSync33, readFileSync as readFileSync35, unlinkSync as unlinkSync5, writeFileSync as writeFileSync25 } from "node:fs";
85011
+ import { existsSync as existsSync34, readFileSync as readFileSync36, unlinkSync as unlinkSync5, writeFileSync as writeFileSync26 } from "node:fs";
84363
85012
  import { resolve as pathResolve } from "node:path";
84364
85013
 
84365
85014
  // src/principle-sync.ts
@@ -84388,7 +85037,7 @@ init_reconcile();
84388
85037
 
84389
85038
  // src/lockfile-auto.ts
84390
85039
  init_src();
84391
- import { existsSync as existsSync29, readFileSync as readFileSync32 } from "node:fs";
85040
+ import { existsSync as existsSync30, readFileSync as readFileSync33 } from "node:fs";
84392
85041
  import { join as join36 } from "node:path";
84393
85042
 
84394
85043
  // src/package-index.ts
@@ -84539,10 +85188,10 @@ function runLockfilePass(opts) {
84539
85188
  ];
84540
85189
  for (const c of candidates) {
84541
85190
  const p = join36(opts.root, c.file);
84542
- if (!existsSync29(p)) continue;
85191
+ if (!existsSync30(p)) continue;
84543
85192
  let sbom;
84544
85193
  try {
84545
- sbom = c.parse(readFileSync32(p, "utf8"));
85194
+ sbom = c.parse(readFileSync33(p, "utf8"));
84546
85195
  } catch {
84547
85196
  continue;
84548
85197
  }
@@ -84600,9 +85249,10 @@ function noveltyAgainst(node2, neighbors, opts = {}) {
84600
85249
 
84601
85250
  // src/instance-ingest.ts
84602
85251
  init_profile2();
85252
+ init_session_registry();
84603
85253
 
84604
85254
  // src/public-symbols.ts
84605
- import { readFileSync as readFileSync33, readdirSync as readdirSync11, existsSync as existsSync30 } from "node:fs";
85255
+ import { readFileSync as readFileSync34, readdirSync as readdirSync11, existsSync as existsSync31 } from "node:fs";
84606
85256
  import { join as join37 } from "node:path";
84607
85257
  var HEAD_BYTES = 8 * 1024;
84608
85258
  var INDEX_TTL_MS = 10 * 60 * 1e3;
@@ -84637,9 +85287,9 @@ function internalPackageNames(workspaceRoot) {
84637
85287
  const names = /* @__PURE__ */ new Set();
84638
85288
  const tryRead = (dir) => {
84639
85289
  const pj = join37(dir, "package.json");
84640
- if (!existsSync30(pj)) return;
85290
+ if (!existsSync31(pj)) return;
84641
85291
  try {
84642
- const name2 = JSON.parse(readFileSync33(pj, "utf8")).name;
85292
+ const name2 = JSON.parse(readFileSync34(pj, "utf8")).name;
84643
85293
  if (typeof name2 === "string" && name2.length > 0) names.add(name2);
84644
85294
  } catch {
84645
85295
  }
@@ -84647,7 +85297,7 @@ function internalPackageNames(workspaceRoot) {
84647
85297
  tryRead(workspaceRoot);
84648
85298
  for (const group of ["packages", "apps"]) {
84649
85299
  const groupDir = join37(workspaceRoot, group);
84650
- if (!existsSync30(groupDir)) continue;
85300
+ if (!existsSync31(groupDir)) continue;
84651
85301
  try {
84652
85302
  for (const entry of readdirSync11(groupDir)) tryRead(join37(groupDir, entry));
84653
85303
  } catch {
@@ -84668,7 +85318,7 @@ function publicSymbolIndex(store, workspaceRoot, deps = {}) {
84668
85318
  }
84669
85319
  const readHead = deps.readHead ?? ((absPath) => {
84670
85320
  try {
84671
- return readFileSync33(absPath, "utf8").slice(0, HEAD_BYTES);
85321
+ return readFileSync34(absPath, "utf8").slice(0, HEAD_BYTES);
84672
85322
  } catch {
84673
85323
  return "";
84674
85324
  }
@@ -84825,6 +85475,7 @@ function shareableContext(n, wireId) {
84825
85475
  function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [], opts = {}) {
84826
85476
  const level = opts.level ?? 1;
84827
85477
  const noveltyOpts = opts.dedupCosine != null ? { dedupCosine: opts.dedupCosine } : {};
85478
+ const quarantine = opts.quarantinedSessions?.length ? new Set(opts.quarantinedSessions) : null;
84828
85479
  const ignored = (text) => ignorePatterns.length > 0 && ignorePatterns.some((p) => text.toLowerCase().includes(p));
84829
85480
  const originSessionOf = (n) => {
84830
85481
  const key = sessionOriginKey(n.attrs["sources"]?.[0]);
@@ -84893,6 +85544,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
84893
85544
  candidates: 0,
84894
85545
  shipped: 0,
84895
85546
  cloudSourced: 0,
85547
+ quarantined: 0,
84896
85548
  falsePositive: 0,
84897
85549
  ignored: 0,
84898
85550
  watermarked: 0,
@@ -84943,6 +85595,10 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
84943
85595
  composition.cloudSourced++;
84944
85596
  continue;
84945
85597
  }
85598
+ if (quarantine && capturedOnlyBy(n, quarantine)) {
85599
+ composition.quarantined++;
85600
+ continue;
85601
+ }
84946
85602
  if (n.attrs["resolvedAs"] === PROBLEM_RESOLUTION.FALSE_POSITIVE) {
84947
85603
  composition.falsePositive++;
84948
85604
  continue;
@@ -85350,7 +86006,8 @@ function buildDrainInstances(store, sharedStore, input) {
85350
86006
  },
85351
86007
  ...lexicon ? { lexicon } : {},
85352
86008
  ...fileLexicon ? { fileLexicon } : {},
85353
- ...input.project ? { project: input.project } : {}
86009
+ ...input.project ? { project: input.project } : {},
86010
+ ...input.quarantinedSessions?.length ? { quarantinedSessions: input.quarantinedSessions } : {}
85354
86011
  });
85355
86012
  return {
85356
86013
  batch,
@@ -85362,6 +86019,7 @@ function buildDrainInstances(store, sharedStore, input) {
85362
86019
  // src/multi.ts
85363
86020
  init_webui();
85364
86021
  init_recall_card();
86022
+ init_session_registry();
85365
86023
 
85366
86024
  // src/consolidate-worker-client.ts
85367
86025
  import { Worker as Worker2 } from "node:worker_threads";
@@ -85381,8 +86039,8 @@ var ConsolidateWorker = class {
85381
86039
  const id = this.nextId++;
85382
86040
  try {
85383
86041
  await this.ready;
85384
- return await new Promise((resolve8, reject) => {
85385
- this.pending.set(id, { resolve: resolve8, reject });
86042
+ return await new Promise((resolve9, reject) => {
86043
+ this.pending.set(id, { resolve: resolve9, reject });
85386
86044
  this.worker.postMessage({ ...req, id });
85387
86045
  });
85388
86046
  } finally {
@@ -85411,12 +86069,12 @@ var ConsolidateWorker = class {
85411
86069
  });
85412
86070
  noteIsolateSpawned();
85413
86071
  this.worker = worker;
85414
- this.ready = new Promise((resolve8, reject) => {
86072
+ this.ready = new Promise((resolve9, reject) => {
85415
86073
  const onReady = (m) => {
85416
86074
  if (m?.ready) {
85417
86075
  worker.off("message", onReady);
85418
86076
  worker.off("error", onErr);
85419
- resolve8();
86077
+ resolve9();
85420
86078
  }
85421
86079
  };
85422
86080
  const onErr = (err2) => {
@@ -85621,17 +86279,17 @@ function startUpdatePoller(opts) {
85621
86279
  };
85622
86280
  }
85623
86281
  function runNpmInstall(channel) {
85624
- return new Promise((resolve8) => {
86282
+ return new Promise((resolve9) => {
85625
86283
  const child = spawn2("npm", ["install", "-g", `${PACKAGE_NAME}@${channel}`], {
85626
86284
  stdio: "inherit",
85627
86285
  shell: true
85628
86286
  });
85629
- child.on("close", (code) => resolve8(code ?? 1));
85630
- child.on("error", () => resolve8(1));
86287
+ child.on("close", (code) => resolve9(code ?? 1));
86288
+ child.on("error", () => resolve9(1));
85631
86289
  });
85632
86290
  }
85633
86291
  async function runInstalledHookRefresh() {
85634
- const root = await new Promise((resolve8) => {
86292
+ const root = await new Promise((resolve9) => {
85635
86293
  const child = spawn2("npm", ["root", "-g"], {
85636
86294
  shell: true,
85637
86295
  windowsHide: true,
@@ -85643,18 +86301,18 @@ async function runInstalledHookRefresh() {
85643
86301
  output += chunk;
85644
86302
  if (output.length > 32768) child.kill();
85645
86303
  });
85646
- child.on("error", () => resolve8(""));
85647
- child.on("close", (code) => resolve8(code === 0 ? output.trim() : ""));
86304
+ child.on("error", () => resolve9(""));
86305
+ child.on("close", (code) => resolve9(code === 0 ? output.trim() : ""));
85648
86306
  });
85649
86307
  if (!isAbsolute5(root)) return 1;
85650
- return new Promise((resolve8) => {
86308
+ return new Promise((resolve9) => {
85651
86309
  const child = spawn2(process.execPath, [join38(root, PACKAGE_NAME, "errata.mjs"), "install-hooks", "codex", "--refresh-existing"], {
85652
86310
  windowsHide: true,
85653
86311
  stdio: "inherit",
85654
86312
  timeout: 3e4
85655
86313
  });
85656
- child.on("error", () => resolve8(1));
85657
- child.on("close", (code) => resolve8(code ?? 1));
86314
+ child.on("error", () => resolve9(1));
86315
+ child.on("close", (code) => resolve9(code ?? 1));
85658
86316
  });
85659
86317
  }
85660
86318
 
@@ -85669,7 +86327,7 @@ function liveCloudClient(src) {
85669
86327
  let current = null;
85670
86328
  let currentKey = "";
85671
86329
  let checkedAt = -Infinity;
85672
- const resolve8 = () => {
86330
+ const resolve9 = () => {
85673
86331
  const t = now();
85674
86332
  if (current && t - checkedAt < recheckMs) return current;
85675
86333
  checkedAt = t;
@@ -85689,7 +86347,7 @@ function liveCloudClient(src) {
85689
86347
  };
85690
86348
  return new Proxy({}, {
85691
86349
  get(_target, prop) {
85692
- const client = resolve8();
86350
+ const client = resolve9();
85693
86351
  const value = Reflect.get(client, prop, client);
85694
86352
  return typeof value === "function" ? value.bind(client) : value;
85695
86353
  }
@@ -86127,7 +86785,7 @@ async function syncHistoryRevision(opts) {
86127
86785
  changed += result.changed;
86128
86786
  remaining = result.remaining;
86129
86787
  if (!remaining || Date.now() - started2 >= (opts.budgetMs ?? 45e3)) break;
86130
- await new Promise((resolve8) => setImmediate(resolve8));
86788
+ await new Promise((resolve9) => setImmediate(resolve9));
86131
86789
  }
86132
86790
  return { changed, remaining };
86133
86791
  })();
@@ -86230,7 +86888,7 @@ async function syncHistoryRevisionPage(opts) {
86230
86888
  init_src7();
86231
86889
  init_src();
86232
86890
  import { execFile as execFile5 } from "node:child_process";
86233
- import { readFileSync as readFileSync34 } from "node:fs";
86891
+ import { readFileSync as readFileSync35 } from "node:fs";
86234
86892
  import { join as join39 } from "node:path";
86235
86893
  import { promisify as promisify3 } from "node:util";
86236
86894
 
@@ -86631,8 +87289,8 @@ var GitBlobReader = class {
86631
87289
  if (this.failed) return Promise.reject(this.failed);
86632
87290
  if (/[\r\n]/.test(spec)) return Promise.resolve(null);
86633
87291
  const proc = this.start();
86634
- return new Promise((resolve8, reject) => {
86635
- this.queue.push({ resolve: resolve8, reject });
87292
+ return new Promise((resolve9, reject) => {
87293
+ this.queue.push({ resolve: resolve9, reject });
86636
87294
  proc.stdin.write(`${spec}
86637
87295
  `);
86638
87296
  });
@@ -86646,14 +87304,14 @@ var GitBlobReader = class {
86646
87304
  const proc = this.proc;
86647
87305
  this.proc = null;
86648
87306
  if (!proc || proc.exitCode !== null) return Promise.resolve();
86649
- return new Promise((resolve8) => {
87307
+ return new Promise((resolve9) => {
86650
87308
  const timer = setTimeout(() => {
86651
87309
  proc.kill();
86652
- resolve8();
87310
+ resolve9();
86653
87311
  }, timeoutMs);
86654
87312
  proc.once("exit", () => {
86655
87313
  clearTimeout(timer);
86656
- resolve8();
87314
+ resolve9();
86657
87315
  });
86658
87316
  proc.stdin.end();
86659
87317
  });
@@ -86778,7 +87436,7 @@ async function defaultGit(root, args2) {
86778
87436
  function readIgnoreLines(root, profile) {
86779
87437
  let lines = [];
86780
87438
  try {
86781
- lines = readFileSync34(join39(root, ".errataignore"), "utf8").split("\n");
87439
+ lines = readFileSync35(join39(root, ".errataignore"), "utf8").split("\n");
86782
87440
  } catch {
86783
87441
  }
86784
87442
  return [...lines, ...profile.ignoreExtra ?? []].map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
@@ -87243,7 +87901,7 @@ async function startHistoryStage(root, input, client, walk11 = {}) {
87243
87901
  init_cloud_auth();
87244
87902
  import { createHash as createHash19 } from "node:crypto";
87245
87903
  import { execFileSync as execFileSync6 } from "node:child_process";
87246
- import { existsSync as existsSync31, writeFileSync as writeFileSync24 } from "node:fs";
87904
+ import { existsSync as existsSync32, writeFileSync as writeFileSync25 } from "node:fs";
87247
87905
  import { join as join40 } from "node:path";
87248
87906
 
87249
87907
  // src/device-poll.ts
@@ -87333,7 +87991,7 @@ async function loginOAuthDevice(opts) {
87333
87991
  let deviceSession = null;
87334
87992
  let approvedInstallation = null;
87335
87993
  while (Date.now() < deadline) {
87336
- await (opts.sleep ?? ((ms) => new Promise((resolve8) => setTimeout(resolve8, ms))))(waitMs);
87994
+ await (opts.sleep ?? ((ms) => new Promise((resolve9) => setTimeout(resolve9, ms))))(waitMs);
87337
87995
  waitMs = intervalMs;
87338
87996
  const poll = await fetchDevicePoll(fetchFn, device.token, {
87339
87997
  method: "POST",
@@ -87458,7 +88116,7 @@ async function loginOAuthLoopback(opts) {
87458
88116
  const state = randomState();
87459
88117
  const scope = opts.scope ?? DEFAULT_OAUTH_SCOPE;
87460
88118
  const { code, redirectUri, clientId } = await new Promise(
87461
- (resolve8, reject) => {
88119
+ (resolve9, reject) => {
87462
88120
  const server = createServer((req, res) => {
87463
88121
  const u = new URL(req.url ?? "/", "http://127.0.0.1");
87464
88122
  if (u.pathname !== "/callback") {
@@ -87481,7 +88139,7 @@ async function loginOAuthLoopback(opts) {
87481
88139
  res.writeHead(200, { "content-type": "text/html" });
87482
88140
  res.end("<html><body>inErrata: you're logged in. You can close this tab.</body></html>");
87483
88141
  server.close();
87484
- resolve8({ code: code2, redirectUri: `http://127.0.0.1:${port}/callback`, clientId: activeClientId });
88142
+ resolve9({ code: code2, redirectUri: `http://127.0.0.1:${port}/callback`, clientId: activeClientId });
87485
88143
  });
87486
88144
  let activeClientId = oauthClientId();
87487
88145
  server.on("error", reject);
@@ -87580,7 +88238,7 @@ async function linkThroughConsole(opts) {
87580
88238
  const deadline = Date.now() + Math.min(code.expires_in * 1e3, opts.timeoutMs ?? Number.POSITIVE_INFINITY);
87581
88239
  let intervalMs = Math.max(2, code.interval ?? 5) * 1e3;
87582
88240
  let waitMs = intervalMs;
87583
- const sleep = opts.sleep ?? ((ms) => new Promise((resolve8) => setTimeout(resolve8, ms)));
88241
+ const sleep = opts.sleep ?? ((ms) => new Promise((resolve9) => setTimeout(resolve9, ms)));
87584
88242
  while (Date.now() < deadline) {
87585
88243
  await sleep(waitMs);
87586
88244
  waitMs = intervalMs;
@@ -87703,8 +88361,8 @@ function applyLinkDecision(root, profile, config2, decision, now = Date.now) {
87703
88361
  let wroteIgnore = false;
87704
88362
  if (decision.writeIgnoreStarter !== false) {
87705
88363
  const target = join40(root, ".errataignore");
87706
- if (!existsSync31(target)) {
87707
- writeFileSync24(target, IGNORE_STARTER, "utf8");
88364
+ if (!existsSync32(target)) {
88365
+ writeFileSync25(target, IGNORE_STARTER, "utf8");
87708
88366
  wroteIgnore = true;
87709
88367
  }
87710
88368
  }
@@ -87717,12 +88375,12 @@ init_registry();
87717
88375
 
87718
88376
  // src/adopt.ts
87719
88377
  init_git_remote();
87720
- import { existsSync as existsSync32 } from "node:fs";
88378
+ import { existsSync as existsSync33 } from "node:fs";
87721
88379
  import { dirname as dirname12, join as join41 } from "node:path";
87722
88380
  function findGitRoot(absPath) {
87723
88381
  let dir = absPath;
87724
88382
  for (let depth = 0; depth < 64; depth++) {
87725
- if (existsSync32(join41(dir, ".git"))) return dir;
88383
+ if (existsSync33(join41(dir, ".git"))) return dir;
87726
88384
  const parent = dirname12(dir);
87727
88385
  if (parent === dir) return null;
87728
88386
  dir = parent;
@@ -88348,6 +89006,13 @@ async function startMultiDaemon(opts = {}) {
88348
89006
  daemonVersion: DAEMON_VERSION,
88349
89007
  basePath: `/ws/${id}`,
88350
89008
  onWorkingFileChanged: engine.webHooks.onWorkingFileChanged,
89009
+ // CAP-subagent-prime: each Task-tool subagent's own block.
89010
+ onSubagentSpawn: engine.webHooks.onSubagentSpawn,
89011
+ subagentContext: engine.webHooks.subagentContext,
89012
+ onSubagentStop: engine.webHooks.onSubagentStop,
89013
+ // CAP-session-scope: per-session blocks + harness/fixture quarantine.
89014
+ noteSession: engine.webHooks.noteSession,
89015
+ sessionContext: engine.webHooks.sessionContext,
88351
89016
  onHook: engine.webHooks.onHook,
88352
89017
  onHookEvent: engine.webHooks.onHookEvent,
88353
89018
  onShellEvent: engine.webHooks.onShellEvent,
@@ -88415,7 +89080,7 @@ async function startMultiDaemon(opts = {}) {
88415
89080
  records.push(rec);
88416
89081
  void ambientLinkAll();
88417
89082
  try {
88418
- writeFileSync25(
89083
+ writeFileSync26(
88419
89084
  rec.engine.paths.daemonLock,
88420
89085
  daemonLockPayload({
88421
89086
  pid: process.pid,
@@ -88622,7 +89287,12 @@ async function startMultiDaemon(opts = {}) {
88622
89287
  return await owner.webApp.fetch(
88623
89288
  new Request(`http://local${sub}`, {
88624
89289
  method: "POST",
88625
- headers: { "content-type": "application/json" },
89290
+ // The origin header (harness/fixture quarantine, session-registry.ts)
89291
+ // is the one caller header the sub-app needs; nothing else crosses.
89292
+ headers: {
89293
+ "content-type": "application/json",
89294
+ ...c.req.header(ORIGIN_HEADER) ? { [ORIGIN_HEADER]: c.req.header(ORIGIN_HEADER) } : {}
89295
+ },
88626
89296
  body: raw2
88627
89297
  })
88628
89298
  );
@@ -88664,6 +89334,19 @@ async function startMultiDaemon(opts = {}) {
88664
89334
  }
88665
89335
  return c.text(statuslineText(String(body2["session_id"] ?? "")));
88666
89336
  });
89337
+ app.post("/api/statusline/subagents", async (c) => {
89338
+ const body2 = await c.req.json().catch(() => ({}));
89339
+ const dir = statuslineDir(body2);
89340
+ if (dir !== null) {
89341
+ const d = normPath(dir);
89342
+ const known = listWorkspaceEntries().some((e) => {
89343
+ const root = normPath(e.path);
89344
+ return d === root || d.startsWith(`${root}/`);
89345
+ });
89346
+ if (!known) return c.text("");
89347
+ }
89348
+ return c.text(subagentRows(body2));
89349
+ });
88667
89350
  for (const r of records) {
88668
89351
  mountedIds.add(r.id);
88669
89352
  app.route(`/ws/${r.id}`, r.webApp);
@@ -88701,7 +89384,7 @@ async function startMultiDaemon(opts = {}) {
88701
89384
  lastActiveAt = Math.max(lastActiveAt, rec.engine.lastActivityAt());
88702
89385
  } catch {
88703
89386
  }
88704
- const reason = retireDecision({ exists: existsSync33(rec.root), lastActiveAt, now });
89387
+ const reason = retireDecision({ exists: existsSync34(rec.root), lastActiveAt, now });
88705
89388
  if (reason) void retireWorkspace(rec, reason);
88706
89389
  }
88707
89390
  };
@@ -88772,7 +89455,7 @@ async function startMultiDaemon(opts = {}) {
88772
89455
  baseUrl = `http://127.0.0.1:${port}`;
88773
89456
  try {
88774
89457
  ensureDir(globalDir());
88775
- writeFileSync25(
89458
+ writeFileSync26(
88776
89459
  lockPath,
88777
89460
  daemonLockPayload({ pid: process.pid, webUiUrl: baseUrl, processStartedAt: PROCESS_STARTED_AT, entry: SELF_ENTRY, version: DAEMON_VERSION }),
88778
89461
  "utf8"
@@ -88781,7 +89464,7 @@ async function startMultiDaemon(opts = {}) {
88781
89464
  }
88782
89465
  for (const r of records) {
88783
89466
  try {
88784
- writeFileSync25(
89467
+ writeFileSync26(
88785
89468
  r.engine.paths.daemonLock,
88786
89469
  daemonLockPayload({
88787
89470
  pid: process.pid,
@@ -89015,7 +89698,7 @@ async function startMultiDaemon(opts = {}) {
89015
89698
  const packageAutoAll = async () => {
89016
89699
  const out2 = /* @__PURE__ */ new Map();
89017
89700
  for (const r of records) {
89018
- await new Promise((resolve8) => setImmediate(resolve8));
89701
+ await new Promise((resolve9) => setImmediate(resolve9));
89019
89702
  const done = markPass(`package-index:${r.entry.name}`);
89020
89703
  try {
89021
89704
  out2.set(
@@ -89324,7 +90007,9 @@ async function startMultiDaemon(opts = {}) {
89324
90007
  done();
89325
90008
  }
89326
90009
  };
89327
- const buildInstanceBatch = async (r, input) => {
90010
+ const buildInstanceBatch = async (r, laneInput) => {
90011
+ const quarantinedSessions = r.engine.quarantinedSessions();
90012
+ const input = quarantinedSessions.length ? { ...laneInput, quarantinedSessions } : laneInput;
89328
90013
  const w = workerFor(r);
89329
90014
  if (w) {
89330
90015
  try {
@@ -89359,6 +90044,7 @@ async function startMultiDaemon(opts = {}) {
89359
90044
  for (const r of records) {
89360
90045
  const recordConsent = effectiveConsent(cfg2, r.engine.profile);
89361
90046
  if (!recordConsent.sync) continue;
90047
+ if (!shipsFromWorkspace(r.root)) continue;
89362
90048
  const recordIdentity = identityFor(liveWorkspaceEntry(r.entry));
89363
90049
  if (recordIdentity.invalid) {
89364
90050
  noteIdentityBlock(r.id, r.entry.name, recordIdentity);
@@ -89753,7 +90439,7 @@ async function startMultiDaemon(opts = {}) {
89753
90439
  clearInterval(anchorPull);
89754
90440
  clearTimeout(codexWakeBoot);
89755
90441
  try {
89756
- const cur = readFileSync35(lockPath, "utf8");
90442
+ const cur = readFileSync36(lockPath, "utf8");
89757
90443
  if (JSON.parse(cur).pid === process.pid) unlinkSync5(lockPath);
89758
90444
  } catch {
89759
90445
  }
@@ -90314,23 +91000,25 @@ async function diagnoseInstallation(cfg, dependencies) {
90314
91000
 
90315
91001
  // src/codex-doctor.ts
90316
91002
  import { spawn as spawn4 } from "node:child_process";
90317
- import { readFileSync as readFileSync37, statSync as statSync10 } from "node:fs";
91003
+ import { readFileSync as readFileSync38, statSync as statSync10 } from "node:fs";
90318
91004
  import { join as join44 } from "node:path";
90319
91005
  import { createInterface } from "node:readline";
90320
91006
 
90321
91007
  // src/codex-hooks.ts
90322
- import { existsSync as existsSync34, mkdirSync as mkdirSync9, readFileSync as readFileSync36, renameSync as renameSync5, unlinkSync as unlinkSync6, writeFileSync as writeFileSync26 } from "node:fs";
91008
+ import { existsSync as existsSync35, mkdirSync as mkdirSync9, readFileSync as readFileSync37, renameSync as renameSync5, unlinkSync as unlinkSync6, writeFileSync as writeFileSync27 } from "node:fs";
90323
91009
  import { homedir as homedir7 } from "node:os";
90324
91010
  import { join as join43 } from "node:path";
90325
91011
 
90326
91012
  // src/hook-commands.ts
90327
91013
  function hookCurlCommand(port, path2 = "/api/hook") {
90328
91014
  const url2 = `http://127.0.0.1:${port}${path2}`;
90329
- return process.platform === "win32" ? `cmd //c "curl -s --connect-timeout 1 --max-time 3 -X POST -H \\"Content-Type: application/json\\" --data-binary @- ${url2} >NUL 2>NUL || exit /b 0"` : `curl -s --connect-timeout 1 --max-time 3 -X POST -H 'Content-Type: application/json' --data-binary @- ${url2} >/dev/null 2>&1 || true`;
91015
+ return process.platform === "win32" ? `cmd //c "curl -s --connect-timeout 1 --max-time 3 -X POST ${HEADERS_WIN} --data-binary @- ${url2} >NUL 2>NUL || exit /b 0"` : `curl -s --connect-timeout 1 --max-time 3 -X POST -H 'Content-Type: application/json' ${ORIGIN_HEADER_POSIX} --data-binary @- ${url2} >/dev/null 2>&1 || true`;
90330
91016
  }
91017
+ var HEADERS_WIN = `-H Content-Type:application/json -H x-errata-origin:%ERRATA_ORIGIN%`;
91018
+ var ORIGIN_HEADER_POSIX = `-H "x-errata-origin: \${ERRATA_ORIGIN:-}"`;
90331
91019
  function hookRelayCommand(port, path2) {
90332
91020
  const url2 = `http://127.0.0.1:${port}${path2}`;
90333
- return process.platform === "win32" ? `cmd //c "curl -s --connect-timeout 1 --max-time 2 -X POST -H \\"Content-Type: application/json\\" --data-binary @- ${url2} 2>NUL || echo {}"` : `curl -s --connect-timeout 1 --max-time 2 -X POST -H 'Content-Type: application/json' --data-binary @- ${url2} 2>/dev/null || echo '{}'`;
91021
+ return process.platform === "win32" ? `cmd //c "curl -s --connect-timeout 1 --max-time 2 -X POST ${HEADERS_WIN} --data-binary @- ${url2} 2>NUL || echo {}"` : `curl -s --connect-timeout 1 --max-time 2 -X POST -H 'Content-Type: application/json' ${ORIGIN_HEADER_POSIX} --data-binary @- ${url2} 2>/dev/null || echo '{}'`;
90334
91022
  }
90335
91023
  var CODEX_HOOKS_BEGIN = `# >>> errata hooks (errata-managed)`;
90336
91024
  var CODEX_HOOKS_END = `# <<< errata hooks`;
@@ -90467,23 +91155,23 @@ function buildCodexRelaySource(workspaceRoot) {
90467
91155
  init_checkout_root();
90468
91156
  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.";
90469
91157
  function writeRelay(file2, source) {
90470
- if (existsSync34(file2) && readFileSync36(file2, "utf8") === source) return;
91158
+ if (existsSync35(file2) && readFileSync37(file2, "utf8") === source) return;
90471
91159
  const temp = `${file2}.${process.pid}.tmp`;
90472
91160
  try {
90473
- writeFileSync26(temp, source, { encoding: "utf8", mode: 384 });
91161
+ writeFileSync27(temp, source, { encoding: "utf8", mode: 384 });
90474
91162
  renameSync5(temp, file2);
90475
91163
  } finally {
90476
- if (existsSync34(temp)) unlinkSync6(temp);
91164
+ if (existsSync35(temp)) unlinkSync6(temp);
90477
91165
  }
90478
91166
  }
90479
91167
  function refreshCodexRelay(root) {
90480
91168
  const config2 = join43(root, ".codex", "config.toml");
90481
- if (!existsSync34(config2)) return "absent";
90482
- const existing = readFileSync36(config2, "utf8");
91169
+ if (!existsSync35(config2)) return "absent";
91170
+ const existing = readFileSync37(config2, "utf8");
90483
91171
  if (!existing.includes(CODEX_HOOKS_BEGIN) && !existing.includes(CODEX_HOOKS_END)) return "absent";
90484
91172
  replaceCodexHooks(existing, "");
90485
91173
  const relay = join43(root, ".codex", "hooks", "errata-relay.mjs");
90486
- const prior = existsSync34(relay) ? readFileSync36(relay, "utf8") : "";
91174
+ const prior = existsSync35(relay) ? readFileSync37(relay, "utf8") : "";
90487
91175
  if (prior && !prior.startsWith("// errata-managed: regenerated by errata install-hooks codex")) {
90488
91176
  throw new Error("Codex relay is not Errata-managed; preserved it. Run errata install-hooks codex to explicitly replace it.");
90489
91177
  }
@@ -90494,7 +91182,7 @@ function refreshCodexRelay(root) {
90494
91182
  return "updated";
90495
91183
  }
90496
91184
  function hasCodexConfig(root, codexHome = process.env["CODEX_HOME"] || join43(homedir7(), ".codex")) {
90497
- return existsSync34(join43(root, ".codex")) || existsSync34(codexHome);
91185
+ return existsSync35(join43(root, ".codex")) || existsSync35(codexHome);
90498
91186
  }
90499
91187
  function replaceCodexHooks(existing, block) {
90500
91188
  const begin = existing.indexOf(CODEX_HOOKS_BEGIN);
@@ -90514,10 +91202,10 @@ function writeCodexHooks(root, port, nodePath = process.execPath) {
90514
91202
  const file2 = join43(dir, "config.toml");
90515
91203
  const relay = join43(dir, "hooks", "errata-relay.mjs");
90516
91204
  const block = buildCodexHooksToml(port, { nodePath, relayPath: relay });
90517
- const final = replaceCodexHooks(existsSync34(file2) ? readFileSync36(file2, "utf8") : "", block);
91205
+ const final = replaceCodexHooks(existsSync35(file2) ? readFileSync37(file2, "utf8") : "", block);
90518
91206
  mkdirSync9(join43(dir, "hooks"), { recursive: true });
90519
91207
  writeRelay(relay, buildCodexRelaySource(checkoutRootOf(root)));
90520
- if (!existsSync34(file2) || readFileSync36(file2, "utf8") !== final) writeFileSync26(file2, final, "utf8");
91208
+ if (!existsSync35(file2) || readFileSync37(file2, "utf8") !== final) writeFileSync27(file2, final, "utf8");
90521
91209
  return file2;
90522
91210
  }
90523
91211
 
@@ -90526,7 +91214,7 @@ init_checkout_root();
90526
91214
  function inspectCodexRelay(cwd) {
90527
91215
  const root = nearestGitRoot(cwd) ?? cwd;
90528
91216
  try {
90529
- const source = readFileSync37(join44(root, ".codex", "hooks", "errata-relay.mjs"), "utf8");
91217
+ const source = readFileSync38(join44(root, ".codex", "hooks", "errata-relay.mjs"), "utf8");
90530
91218
  if (source === buildCodexRelaySource(checkoutRootOf(root))) {
90531
91219
  return { id: "codex_relay", status: "pass", detail: "Installed Codex relay matches this Errata version" };
90532
91220
  }
@@ -90538,7 +91226,7 @@ function inspectCodexContext(cwd) {
90538
91226
  const root = checkoutRootOf(nearestGitRoot(cwd) ?? cwd);
90539
91227
  try {
90540
91228
  const file2 = join44(root, ".errata", "context.md");
90541
- if (statSync10(file2).size <= 128 * 1024 && readFileSync37(file2, "utf8").trim()) {
91229
+ if (statSync10(file2).size <= 128 * 1024 && readFileSync38(file2, "utf8").trim()) {
90542
91230
  return { id: "codex_context", status: "pass", detail: "Saved workspace context is readable by the relay; this does not prove live daemon freshness" };
90543
91231
  }
90544
91232
  } catch {
@@ -90546,7 +91234,7 @@ function inspectCodexContext(cwd) {
90546
91234
  return { id: "codex_context", status: "fail", detail: "No usable saved workspace context; run errata start here and check the daemon log if context.md remains unavailable" };
90547
91235
  }
90548
91236
  function readCodexHookState(cwd, options = {}) {
90549
- return new Promise((resolve8, reject) => {
91237
+ return new Promise((resolve9, reject) => {
90550
91238
  const child = spawn4(options.bin ?? resolveCodexExecutable(), options.args ?? ["app-server", "--stdio"], {
90551
91239
  cwd,
90552
91240
  windowsHide: true,
@@ -90567,7 +91255,7 @@ function readCodexHookState(cwd, options = {}) {
90567
91255
  child.once("close", () => {
90568
91256
  clearTimeout(reap);
90569
91257
  if (error48) reject(error48);
90570
- else resolve8({ ...hooks, features });
91258
+ else resolve9({ ...hooks, features });
90571
91259
  });
90572
91260
  child.kill();
90573
91261
  };
@@ -90714,16 +91402,16 @@ function consolidationGapMs(lastPassMs, policy) {
90714
91402
 
90715
91403
  // src/codex-hook-refresh.ts
90716
91404
  init_checkout_root();
90717
- import { existsSync as existsSync35, readdirSync as readdirSync13, readFileSync as readFileSync38 } from "node:fs";
90718
- import { dirname as dirname13, join as join45, resolve as resolve7 } from "node:path";
91405
+ import { existsSync as existsSync36, readdirSync as readdirSync13, readFileSync as readFileSync39 } from "node:fs";
91406
+ import { dirname as dirname13, join as join45, resolve as resolve8 } from "node:path";
90719
91407
  init_registry();
90720
91408
  function codexHookRoots(roots) {
90721
- const found = new Set(roots.map((root) => resolve7(root)));
91409
+ const found = new Set(roots.map((root) => resolve8(root)));
90722
91410
  for (const root of [...found]) {
90723
91411
  const main2 = mainCheckoutOfWorktree(root) ?? root;
90724
91412
  found.add(main2);
90725
91413
  const dir = join45(main2, ".git", "worktrees");
90726
- if (!existsSync35(dir)) continue;
91414
+ if (!existsSync36(dir)) continue;
90727
91415
  let names;
90728
91416
  try {
90729
91417
  names = readdirSync13(dir);
@@ -90732,7 +91420,7 @@ function codexHookRoots(roots) {
90732
91420
  }
90733
91421
  for (const name2 of names) {
90734
91422
  try {
90735
- const checkout = dirname13(readFileSync38(join45(dir, name2, "gitdir"), "utf8").trim());
91423
+ const checkout = dirname13(readFileSync39(join45(dir, name2, "gitdir"), "utf8").trim());
90736
91424
  if (mainCheckoutOfWorktree(checkout) === main2) found.add(checkout);
90737
91425
  } catch {
90738
91426
  }
@@ -90754,7 +91442,7 @@ function refreshInstalledCodexRelays(roots = listWorkspaceEntries().map((entry)
90754
91442
  }
90755
91443
 
90756
91444
  // src/claude-statusline.ts
90757
- import { existsSync as existsSync36, mkdirSync as mkdirSync10, readFileSync as readFileSync39, writeFileSync as writeFileSync27 } from "node:fs";
91445
+ import { existsSync as existsSync37, mkdirSync as mkdirSync10, readFileSync as readFileSync40, writeFileSync as writeFileSync28 } from "node:fs";
90758
91446
  import { homedir as homedir8 } from "node:os";
90759
91447
  import { dirname as dirname14, join as join46 } from "node:path";
90760
91448
  var STATUSLINE_RELAY_SOURCE = String.raw`// errata-managed: regenerated by errata init / install-hooks claude
@@ -90762,8 +91450,9 @@ import { readFileSync } from 'node:fs';
90762
91450
 
90763
91451
  try {
90764
91452
  const port = Number(process.argv[2]);
91453
+ const route = process.argv[3] === 'subagents' ? '/api/statusline/subagents' : '/api/statusline';
90765
91454
  if (Number.isInteger(port) && port > 0 && port < 65536) {
90766
- const response = await fetch('http://127.0.0.1:' + port + '/api/statusline', {
91455
+ const response = await fetch('http://127.0.0.1:' + port + route, {
90767
91456
  method: 'POST', headers: { 'Content-Type': 'application/json' },
90768
91457
  body: readFileSync(0, 'utf8') || '{}', signal: AbortSignal.timeout(800),
90769
91458
  });
@@ -90773,20 +91462,30 @@ try {
90773
91462
  `;
90774
91463
  var STATUSLINE_RELAY_FILE = "errata-statusline.mjs";
90775
91464
  function buildStatusLine(port, nodePath, relayPath) {
91465
+ return { type: "command", command: relayCommand(port, nodePath, relayPath), padding: 0 };
91466
+ }
91467
+ function buildSubagentStatusLine(port, nodePath, relayPath) {
91468
+ return { type: "command", command: `${relayCommand(port, nodePath, relayPath)} subagents` };
91469
+ }
91470
+ function relayCommand(port, nodePath, relayPath) {
90776
91471
  if (!Number.isInteger(port) || port < 1 || port > 65535) throw new Error("Invalid status line port");
90777
91472
  const q = (p) => {
90778
91473
  if (/["$`\r\n]/.test(p)) throw new Error("Unsupported character in status line path");
90779
91474
  return `"${p.replace(/\\/g, "/")}"`;
90780
91475
  };
90781
- return { type: "command", command: `${q(nodePath)} ${q(relayPath)} ${port}`, padding: 0 };
91476
+ return `${q(nodePath)} ${q(relayPath)} ${port}`;
90782
91477
  }
90783
91478
  function isErrataStatusLine(value) {
90784
91479
  return !!value && typeof value === "object" && typeof value["command"] === "string" && value["command"].includes(STATUSLINE_RELAY_FILE);
90785
91480
  }
90786
91481
  function removeProjectStatusLine(settings) {
90787
- if (!isErrataStatusLine(settings["statusLine"])) return false;
90788
- delete settings["statusLine"];
90789
- return true;
91482
+ let removed = false;
91483
+ for (const key of ["statusLine", "subagentStatusLine"]) {
91484
+ if (!isErrataStatusLine(settings[key])) continue;
91485
+ delete settings[key];
91486
+ removed = true;
91487
+ }
91488
+ return removed;
90790
91489
  }
90791
91490
  function userClaudeSettingsPath() {
90792
91491
  const base = process.env["CLAUDE_CONFIG_DIR"] ?? join46(homedir8(), ".claude");
@@ -90798,26 +91497,34 @@ function ensureUserStatusLine(opts) {
90798
91497
  if (off === "0" || off === "off" || off === "false" || off === "no") return "disabled";
90799
91498
  const settingsPath = opts.userSettingsPath ?? userClaudeSettingsPath();
90800
91499
  let settings = {};
90801
- if (existsSync36(settingsPath)) {
91500
+ if (existsSync37(settingsPath)) {
90802
91501
  try {
90803
- const parsed = JSON.parse(readFileSync39(settingsPath, "utf8"));
91502
+ const parsed = JSON.parse(readFileSync40(settingsPath, "utf8"));
90804
91503
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return "unreadable";
90805
91504
  settings = parsed;
90806
91505
  } catch {
90807
91506
  return "unreadable";
90808
91507
  }
90809
91508
  }
90810
- if (settings["statusLine"] !== void 0 && !isErrataStatusLine(settings["statusLine"])) return "kept-own";
91509
+ const ownMain = settings["statusLine"] !== void 0 && !isErrataStatusLine(settings["statusLine"]);
91510
+ const ownRows = settings["subagentStatusLine"] !== void 0 && !isErrataStatusLine(settings["subagentStatusLine"]);
91511
+ if (ownMain && ownRows) return "kept-own";
90811
91512
  const relay = join46(opts.relayDir, STATUSLINE_RELAY_FILE);
90812
91513
  mkdirSync10(opts.relayDir, { recursive: true });
90813
- if (!existsSync36(relay) || readFileSync39(relay, "utf8") !== STATUSLINE_RELAY_SOURCE) {
90814
- writeFileSync27(relay, STATUSLINE_RELAY_SOURCE, "utf8");
91514
+ if (!existsSync37(relay) || readFileSync40(relay, "utf8") !== STATUSLINE_RELAY_SOURCE) {
91515
+ writeFileSync28(relay, STATUSLINE_RELAY_SOURCE, "utf8");
91516
+ }
91517
+ const nodePath = opts.nodePath ?? process.execPath;
91518
+ const next = {
91519
+ ...ownMain ? {} : { statusLine: buildStatusLine(opts.port, nodePath, relay) },
91520
+ ...ownRows ? {} : { subagentStatusLine: buildSubagentStatusLine(opts.port, nodePath, relay) }
91521
+ };
91522
+ if (Object.entries(next).every(([k, v]) => JSON.stringify(settings[k]) === JSON.stringify(v))) {
91523
+ return ownMain ? "kept-own" : "unchanged";
90815
91524
  }
90816
- const next = buildStatusLine(opts.port, opts.nodePath ?? process.execPath, relay);
90817
- if (JSON.stringify(settings["statusLine"]) === JSON.stringify(next)) return "unchanged";
90818
- settings["statusLine"] = next;
91525
+ Object.assign(settings, next);
90819
91526
  mkdirSync10(dirname14(settingsPath), { recursive: true });
90820
- writeFileSync27(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf8");
91527
+ writeFileSync28(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf8");
90821
91528
  return "installed";
90822
91529
  }
90823
91530
  function describeStatusLineOutcome(outcome) {
@@ -91240,14 +91947,14 @@ async function cmdInit() {
91240
91947
  if (!skipHooks) {
91241
91948
  console.log("");
91242
91949
  console.log("installing harness hooks...");
91243
- const { existsSync: existsSync38 } = await import("node:fs");
91950
+ const { existsSync: existsSync39 } = await import("node:fs");
91244
91951
  const { join: join48 } = await import("node:path");
91245
91952
  try {
91246
91953
  await installClaudeHooks(port);
91247
91954
  } catch (err2) {
91248
91955
  console.warn(` \u26A0\uFE0F Claude hook install failed: ${err2 instanceof Error ? err2.message : err2}`);
91249
91956
  }
91250
- if (existsSync38(join48(ROOT, ".cursor"))) {
91957
+ if (existsSync39(join48(ROOT, ".cursor"))) {
91251
91958
  try {
91252
91959
  await installCursorMcpConfig();
91253
91960
  } catch (err2) {
@@ -91441,9 +92148,9 @@ async function cmdStatus() {
91441
92148
  console.log(` stack: ${profile.stack.join(", ") || "(none)"}`);
91442
92149
  console.log(` languages: ${profile.languages.join(", ") || "(none)"}`);
91443
92150
  }
91444
- console.log(` graph db: ${existsSync37(paths.castalia) ? "yes" : "no"} (${paths.castalia})`);
91445
- console.log(` event log: ${existsSync37(paths.eventLog) ? "yes" : "no"} (${paths.eventLog})`);
91446
- if (existsSync37(paths.castalia)) {
92151
+ console.log(` graph db: ${existsSync38(paths.castalia) ? "yes" : "no"} (${paths.castalia})`);
92152
+ console.log(` event log: ${existsSync38(paths.eventLog) ? "yes" : "no"} (${paths.eventLog})`);
92153
+ if (existsSync38(paths.castalia)) {
91447
92154
  try {
91448
92155
  const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src5(), src_exports2));
91449
92156
  const store = openGraphStore2({ path: paths.castalia });
@@ -92414,11 +93121,11 @@ async function cmdInstallationProfile(args2) {
92414
93121
  }
92415
93122
  async function cmdReview() {
92416
93123
  const paths = workspacePaths(ROOT);
92417
- if (!existsSync37(paths.reviewQueue)) {
93124
+ if (!existsSync38(paths.reviewQueue)) {
92418
93125
  console.log("(review queue empty)");
92419
93126
  return;
92420
93127
  }
92421
- const queue = JSON.parse(readFileSync40(paths.reviewQueue, "utf8"));
93128
+ const queue = JSON.parse(readFileSync41(paths.reviewQueue, "utf8"));
92422
93129
  if (queue.length === 0) {
92423
93130
  console.log("(review queue empty)");
92424
93131
  return;
@@ -93089,7 +93796,7 @@ async function gatherRepo(store, ws) {
93089
93796
  };
93090
93797
  }
93091
93798
  async function gatherReportData(generatedAt) {
93092
- const { existsSync: existsSync38 } = await import("node:fs");
93799
+ const { existsSync: existsSync39 } = await import("node:fs");
93093
93800
  const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src5(), src_exports2));
93094
93801
  const cfg = loadConfig();
93095
93802
  const outbound = cfg.consent.sync ? "auto" : "off";
@@ -93097,7 +93804,7 @@ async function gatherReportData(generatedAt) {
93097
93804
  for (const ws of listWorkspaces()) {
93098
93805
  if (ws.missing) continue;
93099
93806
  const dbPath = workspacePaths(ws.path).castalia;
93100
- if (!existsSync38(dbPath)) continue;
93807
+ if (!existsSync39(dbPath)) continue;
93101
93808
  let store = null;
93102
93809
  try {
93103
93810
  store = openGraphStore2({ path: dbPath });
@@ -93128,7 +93835,7 @@ async function gatherReportData(generatedAt) {
93128
93835
  };
93129
93836
  }
93130
93837
  async function cmdReport(args2) {
93131
- const { mkdirSync: mkdirSync11, writeFileSync: writeFileSync28 } = await import("node:fs");
93838
+ const { mkdirSync: mkdirSync11, writeFileSync: writeFileSync29 } = await import("node:fs");
93132
93839
  const { renderReport: renderReport2 } = await Promise.resolve().then(() => (init_report_render(), report_render_exports));
93133
93840
  const includeFutureVerbs = args2.includes("--future-verbs");
93134
93841
  const now = /* @__PURE__ */ new Date();
@@ -93141,7 +93848,7 @@ async function cmdReport(args2) {
93141
93848
  const outDir = workspacePaths(ROOT).configDir;
93142
93849
  mkdirSync11(outDir, { recursive: true });
93143
93850
  const files = renderReport2(data, { includeFutureVerbs });
93144
- for (const f of files) writeFileSync28(join47(outDir, f.name), f.html, "utf8");
93851
+ for (const f of files) writeFileSync29(join47(outDir, f.name), f.html, "utf8");
93145
93852
  const indexPath = join47(outDir, "report.html");
93146
93853
  console.log(`report \u2192 ${indexPath}`);
93147
93854
  console.log(
@@ -93255,24 +93962,24 @@ async function cmdInstallHooks(args2) {
93255
93962
  }
93256
93963
  }
93257
93964
  async function installOpencodePlugin(port) {
93258
- const { mkdirSync: mkdirSync11, existsSync: existsSync38, readFileSync: readFileSync41, writeFileSync: writeFileSync28 } = await import("node:fs");
93965
+ const { mkdirSync: mkdirSync11, existsSync: existsSync39, readFileSync: readFileSync42, writeFileSync: writeFileSync29 } = await import("node:fs");
93259
93966
  const { join: join48 } = await import("node:path");
93260
93967
  const dir = join48(ROOT, ".opencode", "plugin");
93261
- if (!existsSync38(dir)) mkdirSync11(dir, { recursive: true });
93968
+ if (!existsSync39(dir)) mkdirSync11(dir, { recursive: true });
93262
93969
  const file2 = join48(dir, "inerrata.js");
93263
- if (existsSync38(file2)) {
93264
- const head2 = readFileSync41(file2, "utf8").split("\n")[0] ?? "";
93970
+ if (existsSync39(file2)) {
93971
+ const head2 = readFileSync42(file2, "utf8").split("\n")[0] ?? "";
93265
93972
  if (head2.trim() !== OPENCODE_PLUGIN_MARKER) {
93266
93973
  console.error(`refusing to overwrite ${file2}: not an errata-managed plugin (line 1 lacks the marker)`);
93267
93974
  process.exit(2);
93268
93975
  }
93269
93976
  }
93270
- writeFileSync28(file2, buildOpencodePluginSource(port, { version: DAEMON_VERSION }), "utf8");
93977
+ writeFileSync29(file2, buildOpencodePluginSource(port, { version: DAEMON_VERSION }), "utf8");
93271
93978
  const cfgFile = join48(ROOT, "opencode.json");
93272
93979
  let cfg = { $schema: "https://opencode.ai/config.json" };
93273
- if (existsSync38(cfgFile)) {
93980
+ if (existsSync39(cfgFile)) {
93274
93981
  try {
93275
- cfg = JSON.parse(readFileSync41(cfgFile, "utf8"));
93982
+ cfg = JSON.parse(readFileSync42(cfgFile, "utf8"));
93276
93983
  } catch {
93277
93984
  console.error(`refusing to touch invalid JSON at ${cfgFile} \u2014 fix it and re-run`);
93278
93985
  process.exit(2);
@@ -93283,7 +93990,7 @@ async function installOpencodePlugin(port) {
93283
93990
  if (!hadErrata) {
93284
93991
  const inv = errataMcpInvocation();
93285
93992
  cfg.mcp["errata"] = { type: "local", command: [inv.command, ...inv.args] };
93286
- writeFileSync28(cfgFile, JSON.stringify(cfg, null, 2) + "\n", "utf8");
93993
+ writeFileSync29(cfgFile, JSON.stringify(cfg, null, 2) + "\n", "utf8");
93287
93994
  }
93288
93995
  console.log(`installed OpenCode plugin \u2192 ${file2}`);
93289
93996
  if (hadErrata) console.log(` mcp.errata already present in ${cfgFile} \u2014 left untouched`);
@@ -93310,15 +94017,15 @@ function ensureStatusLine(port) {
93310
94017
  }
93311
94018
  }
93312
94019
  async function installClaudeHooks(port) {
93313
- const { mkdirSync: mkdirSync11, existsSync: existsSync38, readFileSync: readFileSync41, writeFileSync: writeFileSync28 } = await import("node:fs");
94020
+ const { mkdirSync: mkdirSync11, existsSync: existsSync39, readFileSync: readFileSync42, writeFileSync: writeFileSync29 } = await import("node:fs");
93314
94021
  const { join: join48 } = await import("node:path");
93315
94022
  const dir = join48(ROOT, ".claude");
93316
- if (!existsSync38(dir)) mkdirSync11(dir, { recursive: true });
94023
+ if (!existsSync39(dir)) mkdirSync11(dir, { recursive: true });
93317
94024
  const file2 = join48(dir, "settings.json");
93318
94025
  let settings = {};
93319
- if (existsSync38(file2)) {
94026
+ if (existsSync39(file2)) {
93320
94027
  try {
93321
- settings = JSON.parse(readFileSync41(file2, "utf8"));
94028
+ settings = JSON.parse(readFileSync42(file2, "utf8"));
93322
94029
  } catch {
93323
94030
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
93324
94031
  process.exit(2);
@@ -93326,6 +94033,7 @@ async function installClaudeHooks(port) {
93326
94033
  }
93327
94034
  const matcher = "Read|Edit|Write|Grep|Glob|NotebookEdit|Bash";
93328
94035
  const postMatcher = `${matcher}|ToolSearch|mcp__errata__.*`;
94036
+ const preMatcher = `${matcher}|Agent|Task`;
93329
94037
  const preCmd = `${hookRelayCommand(port, "/api/hook")} ${ERRATA_TAG}`;
93330
94038
  const postCmd = `${hookRelayCommand(port, "/api/hook")} ${ERRATA_TAG}`;
93331
94039
  settings.hooks ??= {};
@@ -93335,7 +94043,7 @@ async function installClaudeHooks(port) {
93335
94043
  }
93336
94044
  };
93337
94045
  for (const [event, command, eventMatcher] of [
93338
- ["PreToolUse", preCmd, matcher],
94046
+ ["PreToolUse", preCmd, preMatcher],
93339
94047
  ["PostToolUse", postCmd, postMatcher],
93340
94048
  ["PostToolUseFailure", postCmd, postMatcher]
93341
94049
  ]) {
@@ -93360,13 +94068,13 @@ async function installClaudeHooks(port) {
93360
94068
  dropErrata(endList);
93361
94069
  endList.push({ hooks: [{ type: "command", command: endCmd }] });
93362
94070
  const injectCmd = `${hookRelayCommand(port, "/api/context-inject")} ${ERRATA_TAG}`;
93363
- for (const event of ["SessionStart", "UserPromptSubmit"]) {
94071
+ for (const event of ["SessionStart", "UserPromptSubmit", "SubagentStart"]) {
93364
94072
  const list = settings.hooks[event] ??= [];
93365
94073
  dropErrata(list);
93366
94074
  list.push({ hooks: [{ type: "command", command: injectCmd }] });
93367
94075
  }
93368
94076
  removeProjectStatusLine(settings);
93369
- writeFileSync28(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
94077
+ writeFileSync29(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
93370
94078
  console.log(`installed Claude Code hooks \u2192 ${file2}`);
93371
94079
  console.log(` ${ensureStatusLine(port)}`);
93372
94080
  await installClaudeMcpConfig();
@@ -93382,15 +94090,15 @@ async function installClaudeHooks(port) {
93382
94090
  console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
93383
94091
  }
93384
94092
  async function installClaudeMcpConfig() {
93385
- const { mkdirSync: mkdirSync11, existsSync: existsSync38, readFileSync: readFileSync41, writeFileSync: writeFileSync28 } = await import("node:fs");
94093
+ const { mkdirSync: mkdirSync11, existsSync: existsSync39, readFileSync: readFileSync42, writeFileSync: writeFileSync29 } = await import("node:fs");
93386
94094
  const { join: join48, dirname: dirname15 } = await import("node:path");
93387
94095
  const file2 = join48(ROOT, ".mcp.json");
93388
94096
  const dir = dirname15(file2);
93389
- if (!existsSync38(dir)) mkdirSync11(dir, { recursive: true });
94097
+ if (!existsSync39(dir)) mkdirSync11(dir, { recursive: true });
93390
94098
  let cfg = {};
93391
- if (existsSync38(file2)) {
94099
+ if (existsSync39(file2)) {
93392
94100
  try {
93393
- cfg = JSON.parse(readFileSync41(file2, "utf8"));
94101
+ cfg = JSON.parse(readFileSync42(file2, "utf8"));
93394
94102
  } catch {
93395
94103
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
93396
94104
  process.exit(2);
@@ -93398,21 +94106,21 @@ async function installClaudeMcpConfig() {
93398
94106
  }
93399
94107
  cfg.mcpServers ??= {};
93400
94108
  cfg.mcpServers["errata"] = errataMcpInvocation();
93401
- writeFileSync28(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
94109
+ writeFileSync29(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
93402
94110
  console.log(`installed Claude Code MCP server config \u2192 ${file2}`);
93403
94111
  console.log(` Claude Code will spawn \`errata mcp\` on workspace open.`);
93404
94112
  console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses / show / similar`);
93405
94113
  }
93406
94114
  async function installCursorMcpConfig() {
93407
- const { mkdirSync: mkdirSync11, existsSync: existsSync38, readFileSync: readFileSync41, writeFileSync: writeFileSync28 } = await import("node:fs");
94115
+ const { mkdirSync: mkdirSync11, existsSync: existsSync39, readFileSync: readFileSync42, writeFileSync: writeFileSync29 } = await import("node:fs");
93408
94116
  const { join: join48 } = await import("node:path");
93409
94117
  const dir = join48(ROOT, ".cursor");
93410
- if (!existsSync38(dir)) mkdirSync11(dir, { recursive: true });
94118
+ if (!existsSync39(dir)) mkdirSync11(dir, { recursive: true });
93411
94119
  const file2 = join48(dir, "mcp.json");
93412
94120
  let cfg = {};
93413
- if (existsSync38(file2)) {
94121
+ if (existsSync39(file2)) {
93414
94122
  try {
93415
- cfg = JSON.parse(readFileSync41(file2, "utf8"));
94123
+ cfg = JSON.parse(readFileSync42(file2, "utf8"));
93416
94124
  } catch {
93417
94125
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
93418
94126
  process.exit(2);
@@ -93420,7 +94128,7 @@ async function installCursorMcpConfig() {
93420
94128
  }
93421
94129
  cfg.mcpServers ??= {};
93422
94130
  cfg.mcpServers["errata"] = errataMcpInvocation();
93423
- writeFileSync28(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
94131
+ writeFileSync29(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
93424
94132
  console.log(`installed Cursor MCP server config \u2192 ${file2}`);
93425
94133
  console.log(` Cursor will spawn \`errata mcp\` on workspace open.`);
93426
94134
  console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses`);
@@ -93773,7 +94481,7 @@ async function cmdDash(args2) {
93773
94481
  const hotspotScanMark = /* @__PURE__ */ new Map();
93774
94482
  const HOTSPOT_FANIN = 20;
93775
94483
  const runNightlyPass = async (dueIds) => {
93776
- const yieldToLoop2 = () => new Promise((resolve8) => setImmediate(resolve8));
94484
+ const yieldToLoop2 = () => new Promise((resolve9) => setImmediate(resolve9));
93777
94485
  const fullReclusterPass = nightlyCount++ % FULL_RECLUSTER_EVERY === 0;
93778
94486
  const m = dueIds ? await handle2.nightlyFor(dueIds) : await handle2.nightlyAll();
93779
94487
  let skillsLearned = 0;