@inerrata-corporation/errata 2.0.0-dev.28 → 2.0.0-dev.29

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.
Files changed (3) hide show
  1. package/errata.mjs +71 -27
  2. package/package.json +1 -1
  3. package/pass-worker.mjs +201 -0
package/errata.mjs CHANGED
@@ -19939,7 +19939,7 @@ function budgetSnapshot(s, maxChars) {
19939
19939
  return dropped;
19940
19940
  }
19941
19941
  function assembleAgentContext(opts) {
19942
- const snapshot = buildSnapshot({
19942
+ const snapshot = opts.snapshot ?? buildSnapshot({
19943
19943
  store: opts.store,
19944
19944
  profile: opts.profile,
19945
19945
  reviewCount: opts.reviewCount,
@@ -37695,7 +37695,7 @@ init_webui();
37695
37695
  init_config();
37696
37696
 
37697
37697
  // src/engine.ts
37698
- import { execFileSync as execFileSync4 } from "node:child_process";
37698
+ import { execFileSync as execFileSync3 } from "node:child_process";
37699
37699
  import { existsSync as existsSync14, statSync as statSync4, appendFileSync as appendFileSync2, readdirSync as readdirSync7, renameSync as renameSync2, readFileSync as readFileSync13, writeFileSync as writeFileSync11 } from "node:fs";
37700
37700
  import { join as join19, relative as relative6, sep as sep4 } from "node:path";
37701
37701
 
@@ -40272,14 +40272,19 @@ var PassWorker = class {
40272
40272
  reconcile() {
40273
40273
  return this.call("reconcile");
40274
40274
  }
40275
- call(kind) {
40275
+ /** Build the AGENTS.md ContextSnapshot on the worker's own store connection —
40276
+ * the O(graph) scans stay off the main loop (HZ-boot-render-offload). */
40277
+ snapshot(opts) {
40278
+ return this.call("snapshot", opts);
40279
+ }
40280
+ call(kind, payload) {
40276
40281
  if (this.stopped) return Promise.reject(new Error("pass worker stopped"));
40277
40282
  this.ensureWorker();
40278
40283
  const id = this.nextId++;
40279
40284
  return this.ready.then(
40280
40285
  () => new Promise((resolve5, reject) => {
40281
40286
  this.pending.set(id, { resolve: resolve5, reject });
40282
- this.worker.postMessage({ id, kind });
40287
+ this.worker.postMessage({ id, kind, ...payload !== void 0 ? { payload } : {} });
40283
40288
  })
40284
40289
  );
40285
40290
  }
@@ -40725,18 +40730,25 @@ function startGitSensor(gitDir, onEvent, opts = {}) {
40725
40730
  }
40726
40731
 
40727
40732
  // src/git-delta.ts
40728
- import { execFileSync as execFileSync3 } from "node:child_process";
40733
+ import { execFile } from "node:child_process";
40729
40734
  function git(repoDir, args2) {
40730
- return execFileSync3("git", ["-C", repoDir, ...args2], {
40731
- encoding: "utf8",
40732
- maxBuffer: 64 * 1024 * 1024,
40733
- // Windows: don't flash a console window for each git subcommand the
40734
- // git-sensor runs on every commit/checkout.
40735
- windowsHide: true
40735
+ return new Promise((resolve5, reject) => {
40736
+ execFile(
40737
+ "git",
40738
+ ["-C", repoDir, ...args2],
40739
+ {
40740
+ encoding: "utf8",
40741
+ maxBuffer: 64 * 1024 * 1024,
40742
+ // Windows: don't flash a console window for each git subcommand the
40743
+ // git-sensor runs on every commit/checkout.
40744
+ windowsHide: true
40745
+ },
40746
+ (err2, stdout) => err2 ? reject(err2) : resolve5(stdout)
40747
+ );
40736
40748
  });
40737
40749
  }
40738
- function gitDiff(repoDir, oldRef, newRef) {
40739
- const out2 = git(repoDir, ["diff", "--name-status", "-M", oldRef, newRef]);
40750
+ async function gitDiff(repoDir, oldRef, newRef) {
40751
+ const out2 = await git(repoDir, ["diff", "--name-status", "-M", oldRef, newRef]);
40740
40752
  const changedPaths = [];
40741
40753
  const renames = [];
40742
40754
  const deleted = [];
@@ -40760,8 +40772,8 @@ function gitDiff(repoDir, oldRef, newRef) {
40760
40772
  return { changedPaths, renames, deleted };
40761
40773
  }
40762
40774
  var FMT = ["%H", "%an", "%ae", "%at", "%P", "%s"].join("%x1f");
40763
- function commitMeta(repoDir, sha2) {
40764
- const line = git(repoDir, ["show", "--no-patch", `--format=${FMT}`, sha2]).split(/\r?\n/, 1)[0] ?? "";
40775
+ async function commitMeta(repoDir, sha2) {
40776
+ const line = (await git(repoDir, ["show", "--no-patch", `--format=${FMT}`, sha2])).split(/\r?\n/, 1)[0] ?? "";
40765
40777
  const [h, an, ae, at, parents, subject] = line.split("");
40766
40778
  return {
40767
40779
  sha: h ?? sha2,
@@ -41316,7 +41328,7 @@ function maybeFlushDigests() {
41316
41328
  }
41317
41329
 
41318
41330
  // src/engine.ts
41319
- var DAEMON_VERSION = true ? "2.0.0-dev.28" : "2.0.0-alpha.0";
41331
+ var DAEMON_VERSION = true ? "2.0.0-dev.29" : "2.0.0-alpha.0";
41320
41332
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
41321
41333
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
41322
41334
  var GIT_OP_MUTE_MS = 4e3;
@@ -41350,7 +41362,7 @@ function saveTurnCursors(path2, cursors) {
41350
41362
  function gitSourceWatchTargets(root) {
41351
41363
  const SOURCE = /\.(ts|tsx|js|jsx|mjs|cjs|py)$/i;
41352
41364
  try {
41353
- const lsOut = execFileSync4("git", ["-C", root, "ls-files", "-z"], {
41365
+ const lsOut = execFileSync3("git", ["-C", root, "ls-files", "-z"], {
41354
41366
  encoding: "utf8",
41355
41367
  maxBuffer: 128 * 1024 * 1024,
41356
41368
  windowsHide: true,
@@ -41360,7 +41372,7 @@ function gitSourceWatchTargets(root) {
41360
41372
  if (sourceFiles.length === 0) throw new Error("no tracked source");
41361
41373
  let ignoredDirs = [];
41362
41374
  try {
41363
- const igOut = execFileSync4(
41375
+ const igOut = execFileSync3(
41364
41376
  "git",
41365
41377
  ["-C", root, "ls-files", "--others", "--ignored", "--exclude-standard", "--directory", "-z"],
41366
41378
  { encoding: "utf8", maxBuffer: 256 * 1024 * 1024, windowsHide: true, stdio: ["ignore", "pipe", "ignore"] }
@@ -41501,8 +41513,8 @@ function createWorkspaceEngine(opts) {
41501
41513
  let diff;
41502
41514
  let meta3;
41503
41515
  try {
41504
- diff = gitDiff(opts.workspaceRoot, ev.oldSha, ev.newSha);
41505
- meta3 = commitMeta(opts.workspaceRoot, ev.newSha);
41516
+ diff = await gitDiff(opts.workspaceRoot, ev.oldSha, ev.newSha);
41517
+ meta3 = await commitMeta(opts.workspaceRoot, ev.newSha);
41506
41518
  } catch (err2) {
41507
41519
  console.warn("[errata] git read failed:", err2);
41508
41520
  return;
@@ -41559,18 +41571,46 @@ function createWorkspaceEngine(opts) {
41559
41571
  let lastRemoteAt = 0;
41560
41572
  let remoteInFlight = false;
41561
41573
  const REMOTE_REFRESH_MS = 5 * 6e4;
41574
+ let ctxRefreshInFlight = false;
41575
+ let ctxRefreshQueued = false;
41562
41576
  const refreshContextNow = () => {
41577
+ void refreshContextAsync().catch((err2) => {
41578
+ console.warn("[errata] context refresh failed:", err2 instanceof Error ? err2.message : err2);
41579
+ });
41580
+ };
41581
+ const refreshContextAsync = async () => {
41563
41582
  if (opts.skipContextWriter) return;
41583
+ if (ctxRefreshInFlight) {
41584
+ ctxRefreshQueued = true;
41585
+ return;
41586
+ }
41587
+ ctxRefreshInFlight = true;
41588
+ try {
41589
+ await refreshContextOnce();
41590
+ } finally {
41591
+ ctxRefreshInFlight = false;
41592
+ if (ctxRefreshQueued) {
41593
+ ctxRefreshQueued = false;
41594
+ refreshContextNow();
41595
+ }
41596
+ }
41597
+ };
41598
+ const refreshContextOnce = async () => {
41564
41599
  const elicit = isEdgeElicitationEnabled();
41565
- const { body: body2, snapshot } = assembleAgentContext({
41566
- store,
41600
+ const snapOpts = {
41567
41601
  profile,
41568
41602
  reviewCount: pendingCount(paths),
41569
41603
  reviewUiUrl: opts.reviewUrl(),
41570
41604
  workingFile: workingFiles.mostRecent() ?? void 0,
41571
- skills: readSkillManifest(paths.skillsManifest),
41605
+ skills: readSkillManifest(paths.skillsManifest)
41606
+ };
41607
+ const prebuilt = passWorker ? await passWorker.snapshot(snapOpts).catch(() => null) : null;
41608
+ const { body: body2, snapshot } = assembleAgentContext({
41609
+ store,
41610
+ ...snapOpts,
41572
41611
  remote: remotePriors,
41573
- ...elicit ? { edgeElicitation: { instruction: PRIOR_TAG_INSTRUCTION } } : {}
41612
+ ...elicit ? { edgeElicitation: { instruction: PRIOR_TAG_INSTRUCTION } } : {},
41613
+ ...prebuilt ? { snapshot: prebuilt } : {}
41574
41614
  });
41575
41615
  const target = join19(opts.workspaceRoot, "AGENTS.md");
41576
41616
  writeManagedBlock(target, { body: body2 });
@@ -41774,7 +41814,7 @@ function createWorkspaceEngine(opts) {
41774
41814
  return hit?.id;
41775
41815
  };
41776
41816
  for (const turn of items) {
41777
- if (processedTurns++ > 0 && processedTurns % 20 === 0) await yieldToLoop();
41817
+ if (processedTurns++ > 0) await yieldToLoop();
41778
41818
  const turnFile = turn.workingFile ? toRel(turn.workingFile) : void 0;
41779
41819
  if (opts.sharedStore) {
41780
41820
  try {
@@ -41823,7 +41863,7 @@ function createWorkspaceEngine(opts) {
41823
41863
  if (!retractAs) {
41824
41864
  const pid = r.id ?? designProblemId(r.problem);
41825
41865
  try {
41826
- const d = gitDiff(opts.workspaceRoot, "HEAD~1", "HEAD");
41866
+ const d = await gitDiff(opts.workspaceRoot, "HEAD~1", "HEAD");
41827
41867
  anchorProblemToDiff(store, pid, d.changedPaths, profile.id, t);
41828
41868
  const solId = solutionForProblem(store, pid);
41829
41869
  if (solId) anchorSolutionToDiff(store, solId, d.changedPaths, profile.id, t);
@@ -42037,6 +42077,7 @@ function createWorkspaceEngine(opts) {
42037
42077
  const harvestSession = async (sessionId, transcriptPath) => {
42038
42078
  await harvestTurns(sessionId, transcriptPath);
42039
42079
  for (const sub of subagentTranscripts(transcriptPath, sessionId)) {
42080
+ await yieldToLoop();
42040
42081
  await harvestTurns(sub.sessionId, sub.path);
42041
42082
  }
42042
42083
  };
@@ -42050,7 +42091,10 @@ function createWorkspaceEngine(opts) {
42050
42091
  sinceMs: Date.now() - TURN_REPLAY_LOOKBACK_MS,
42051
42092
  limit: 25
42052
42093
  });
42053
- for (const ref of refs) await harvestSession(ref.sessionId, ref.path);
42094
+ for (const ref of refs) {
42095
+ await yieldToLoop();
42096
+ await harvestSession(ref.sessionId, ref.path);
42097
+ }
42054
42098
  } catch {
42055
42099
  }
42056
42100
  })();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.0-dev.28",
3
+ "version": "2.0.0-dev.29",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
package/pass-worker.mjs CHANGED
@@ -24451,6 +24451,14 @@ function addDependency(store2, opts) {
24451
24451
  store2.mergeEdge(edge);
24452
24452
  return edge;
24453
24453
  }
24454
+ function listNeedsRevisit(store2, asOf) {
24455
+ return store2.nodesAsOf(asOf).filter((n) => n.attrs["revisit"] === true).map((n) => ({
24456
+ id: n.id,
24457
+ label: n.label,
24458
+ description: n.description,
24459
+ reason: String(n.attrs["revisitReason"] ?? "")
24460
+ }));
24461
+ }
24454
24462
 
24455
24463
  // ../../packages/local-graph/src/credit.ts
24456
24464
  init_src2();
@@ -24798,6 +24806,48 @@ function mergeEdge(store2, from, to, type, ts) {
24798
24806
  attrs: { provisional: true }
24799
24807
  });
24800
24808
  }
24809
+ var CITABLE_PRIOR_LABELS = /* @__PURE__ */ new Set([
24810
+ "Solution",
24811
+ "RootCause",
24812
+ "Pattern",
24813
+ "Technique",
24814
+ "AntiPattern"
24815
+ ]);
24816
+ function priorsForFile(store2, relPath) {
24817
+ const want = relPath.trim().replace(/^\.?\//, "");
24818
+ let file2 = null;
24819
+ for (const n of store2.findNodesByLabel("File")) {
24820
+ if (n.description === want || n.attrs["relPath"] === want) {
24821
+ file2 = n;
24822
+ break;
24823
+ }
24824
+ }
24825
+ if (!file2) return null;
24826
+ const openProblems = [];
24827
+ const seenProblem = /* @__PURE__ */ new Set();
24828
+ const related = /* @__PURE__ */ new Map();
24829
+ for (const e of store2.inEdges(file2.id, ["ANCHORED_AT"])) {
24830
+ const n = store2.getNode(e.from);
24831
+ if (!n) continue;
24832
+ if (n.label === "Problem") {
24833
+ if (!n.attrs["resolvedAt"] && !seenProblem.has(n.id)) {
24834
+ seenProblem.add(n.id);
24835
+ openProblems.push(n);
24836
+ }
24837
+ } else if (CITABLE_PRIOR_LABELS.has(n.label)) {
24838
+ related.set(n.id, n);
24839
+ }
24840
+ }
24841
+ for (const p of openProblems) {
24842
+ for (const e of store2.outEdges(p.id, ["SOLVED_BY", "CAUSED_BY", "INSTANCE_OF"])) {
24843
+ const n = store2.getNode(e.to);
24844
+ if (n && CITABLE_PRIOR_LABELS.has(n.label)) related.set(n.id, n);
24845
+ }
24846
+ }
24847
+ if (openProblems.length === 0 && related.size === 0) return null;
24848
+ openProblems.sort((a, b) => (b.lastUpdatedAt ?? 0) - (a.lastUpdatedAt ?? 0));
24849
+ return { file: file2, openProblems, related: [...related.values()] };
24850
+ }
24801
24851
  function resolveDesignProblems(store2, t) {
24802
24852
  let resolved = 0;
24803
24853
  for (const p of store2.findNodesByLabel("Problem")) {
@@ -25517,6 +25567,146 @@ function codeAnchorProjection(store2, semanticIds, opts = {}) {
25517
25567
  return out2;
25518
25568
  }
25519
25569
 
25570
+ // ../../packages/context-writer/src/agents-md.ts
25571
+ init_src();
25572
+
25573
+ // ../../packages/context-writer/src/render.ts
25574
+ init_src2();
25575
+ function buildSnapshot(opts) {
25576
+ const problems = opts.store.findNodesByLabel("Problem").filter((p) => p.attrs["mergedInto"] === void 0);
25577
+ const allProblems = problems.filter((p) => p.attrs["resolvedAt"] == null);
25578
+ allProblems.sort((a, b) => b.lastUpdatedAt - a.lastUpdatedAt);
25579
+ const recent = allProblems.slice(0, 8).map((p) => ({
25580
+ node: p,
25581
+ anchors: opts.store.outEdges(p.id, ["MANIFESTED_IN", "EVIDENCED_BY"])
25582
+ }));
25583
+ const recentResolved = problems.filter((p) => p.attrs["resolvedAt"] != null && p.attrs["resolvedAs"] == null).sort((a, b) => Number(b.attrs["resolvedAt"] ?? 0) - Number(a.attrs["resolvedAt"] ?? 0)).slice(0, 4).map((p) => {
25584
+ const solEdge = opts.store.outEdges(p.id, ["SOLVED_BY"])[0];
25585
+ const solution = solEdge ? opts.store.getNode(solEdge.to) ?? void 0 : void 0;
25586
+ return { node: p, ...solution ? { solution } : {} };
25587
+ });
25588
+ const motifs = [
25589
+ ...opts.store.findNodesByLabel("Pattern"),
25590
+ ...opts.store.findNodesByLabel("Technique"),
25591
+ ...opts.store.findNodesByLabel("AntiPattern")
25592
+ ].sort((a, b) => b.pageRank - a.pageRank).slice(0, 10);
25593
+ const workingFile = opts.workingFile ? sliceForFile(opts.store, opts.workingFile) : void 0;
25594
+ const byEpisode = /* @__PURE__ */ new Map();
25595
+ for (const sol of opts.store.findNodesByLabel("Solution")) {
25596
+ if (sol.attrs["enrichmentPending"] !== true) continue;
25597
+ const ep = sol.attrs["episodeId"] ?? sol.id;
25598
+ const list = byEpisode.get(ep) ?? [];
25599
+ list.push({
25600
+ problemId: sol.attrs["problemId"] ?? "",
25601
+ fixed: sol.attrs["symbolName"] ?? "",
25602
+ problem: sol.attrs["problemDescription"] ?? ""
25603
+ });
25604
+ byEpisode.set(ep, list);
25605
+ }
25606
+ const pendingEnrichment = [...byEpisode.entries()].map(([episodeId, problems2]) => ({
25607
+ episodeId,
25608
+ problems: problems2
25609
+ }));
25610
+ const needsRevisit = listNeedsRevisit(
25611
+ opts.store,
25612
+ (opts.now ?? /* @__PURE__ */ new Date()).getTime()
25613
+ ).slice(0, 10);
25614
+ const norm = (x) => x.toLowerCase().replace(/[^a-z0-9]+/g, "");
25615
+ const pkgBase = (x) => {
25616
+ const at = x.lastIndexOf("@");
25617
+ return at > 0 ? x.slice(0, at) : x;
25618
+ };
25619
+ const matchNode = (cands, key) => {
25620
+ const k = norm(key);
25621
+ if (k.length < 2) return null;
25622
+ return cands.find((n) => norm(n.description ?? "") === k) ?? cands.find((n) => {
25623
+ const d = norm(n.description ?? "");
25624
+ return d.length >= 2 && (d.includes(k) || k.includes(d));
25625
+ }) ?? null;
25626
+ };
25627
+ const langNodes = opts.store.findNodesByLabel("Language");
25628
+ const pkgNodes = opts.store.findNodesByLabel("Package");
25629
+ const profileContext = {
25630
+ languages: opts.profile.languages.map((name2) => ({ name: name2, node: matchNode(langNodes, name2) })),
25631
+ packages: opts.profile.stack.map((name2) => ({ name: name2, node: matchNode(pkgNodes, pkgBase(name2)) }))
25632
+ };
25633
+ return {
25634
+ profile: opts.profile,
25635
+ profileContext,
25636
+ recentProblems: recent,
25637
+ recentResolved,
25638
+ motifs,
25639
+ reviewCount: opts.reviewCount,
25640
+ reviewUiUrl: opts.reviewUiUrl,
25641
+ ...workingFile ? { workingFile } : {},
25642
+ pendingEnrichment,
25643
+ skills: opts.skills ?? [],
25644
+ needsRevisit,
25645
+ generatedAt: (opts.now ?? /* @__PURE__ */ new Date()).toISOString()
25646
+ };
25647
+ }
25648
+ function sliceForFile(store2, relPath) {
25649
+ const candidates = store2.findNodesByLabel("File");
25650
+ const file2 = candidates.find((n) => n.description === relPath);
25651
+ if (!file2) return void 0;
25652
+ const symbols = [];
25653
+ for (const e of store2.outEdges(file2.id, ["DEFINES"])) {
25654
+ const n = store2.getNode(e.to);
25655
+ if (n) symbols.push({ label: n.label, name: n.description });
25656
+ if (symbols.length >= 25) break;
25657
+ }
25658
+ const importsFrom = [];
25659
+ for (const e of store2.outEdges(file2.id, ["IMPORTS"])) {
25660
+ const n = store2.getNode(e.to);
25661
+ if (n && n.label === "File") importsFrom.push(n.description);
25662
+ if (importsFrom.length >= 15) break;
25663
+ }
25664
+ const importedBy = [];
25665
+ for (const e of store2.inEdges(file2.id, ["IMPORTS"])) {
25666
+ const n = store2.getNode(e.from);
25667
+ if (n && n.label === "File") importedBy.push(n.description);
25668
+ if (importedBy.length >= 15) break;
25669
+ }
25670
+ const externalRefs = [];
25671
+ for (const e of store2.outEdges(file2.id, ["DEFINES"])) {
25672
+ const sym = store2.getNode(e.to);
25673
+ if (!sym) continue;
25674
+ for (const ref of store2.outEdges(sym.id, ["CALLS", "ACCESSES"])) {
25675
+ const tgt = store2.getNode(ref.to);
25676
+ if (!tgt) continue;
25677
+ const tgtFile = fileOf(store2, tgt.id);
25678
+ if (tgtFile && tgtFile !== file2.id) {
25679
+ externalRefs.push({ kind: ref.type, target: tgt.description });
25680
+ if (externalRefs.length >= 20) break;
25681
+ }
25682
+ }
25683
+ if (externalRefs.length >= 20) break;
25684
+ }
25685
+ const fp = priorsForFile(store2, relPath);
25686
+ const priors = fp ? {
25687
+ openProblems: fp.openProblems.slice(0, 3).map((p) => ({ id: p.id, description: p.description })),
25688
+ related: fp.related.slice(0, 4).map((n) => ({ id: n.id, label: n.label, description: n.description }))
25689
+ } : void 0;
25690
+ return {
25691
+ relPath,
25692
+ symbols,
25693
+ importsFrom,
25694
+ importedBy,
25695
+ externalRefs,
25696
+ ...priors ? { priors } : {}
25697
+ };
25698
+ }
25699
+ function fileOf(store2, nodeId) {
25700
+ for (const e of store2.inEdges(nodeId, ["DEFINES"])) {
25701
+ const parent = store2.getNode(e.from);
25702
+ if (parent && parent.label === "File") return parent.id;
25703
+ }
25704
+ return null;
25705
+ }
25706
+
25707
+ // ../../packages/context-writer/src/select-durable-memory.ts
25708
+ init_src2();
25709
+
25520
25710
  // ../../node_modules/.pnpm/env-paths@3.0.0/node_modules/env-paths/index.js
25521
25711
  import os from "node:os";
25522
25712
  import process3 from "node:process";
@@ -25650,6 +25840,17 @@ function runPass(msg) {
25650
25840
  return runNightly();
25651
25841
  case "reconcile":
25652
25842
  return reconcileStaleFiles(store, init2.workspaceRoot, init2.workspaceId);
25843
+ case "snapshot": {
25844
+ const p = msg.payload;
25845
+ return buildSnapshot({
25846
+ store,
25847
+ profile: p.profile,
25848
+ reviewCount: p.reviewCount,
25849
+ reviewUiUrl: p.reviewUiUrl,
25850
+ ...p.workingFile !== void 0 ? { workingFile: p.workingFile } : {},
25851
+ ...p.skills !== void 0 ? { skills: p.skills } : {}
25852
+ });
25853
+ }
25653
25854
  default:
25654
25855
  throw new Error(`pass-worker: unknown pass "${msg.kind}"`);
25655
25856
  }