@inerrata-corporation/errata 2.0.0-dev.70 → 2.0.0-dev.72

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.
@@ -14,7 +14,7 @@ var __export = (target, all) => {
14
14
  function isCausalProtected(type) {
15
15
  return CAUSAL_PROTECT_EDGES.includes(type);
16
16
  }
17
- var SEMANTIC_NODE_LABELS, CONTEXT_NODE_LABELS, CODE_NODE_LABELS, ALL_NODE_LABELS, STRUCTURAL_EDGES, CAUSAL_EDGES, RESOLUTION_EDGES, CONCEPTUAL_EDGES, EVIDENCE_EDGES, CODE_EDGES, BRIDGE_EDGES, IDENTITY_EDGES, JUSTIFICATION_EDGES, BELIEF_EDGES, ABSTRACTION_EDGES, DECOMPOSITION_EDGES, TRANSFER_EDGES, SOLUTION_STRUCTURE_EDGES, TAXONOMY_EDGES, TRIAGE_EDGES, GIT_EDGES, ALL_EDGE_TYPES, EDGE_WEIGHT, CAUSAL_PROTECT_EDGES, VALIDATION_SOURCES, ABSTRACTION_LEVEL, PROBLEM_RESOLUTION, DRIFT_KIND;
17
+ var SEMANTIC_NODE_LABELS, CONTEXT_NODE_LABELS, CODE_NODE_LABELS, ALL_NODE_LABELS, STRUCTURAL_EDGES, CAUSAL_EDGES, RESOLUTION_EDGES, CONCEPTUAL_EDGES, EVIDENCE_EDGES, CODE_EDGES, BRIDGE_EDGES, IDENTITY_EDGES, JUSTIFICATION_EDGES, BELIEF_EDGES, ABSTRACTION_EDGES, DECOMPOSITION_EDGES, TRANSFER_EDGES, SOLUTION_STRUCTURE_EDGES, SUSPICION_EDGES, TAXONOMY_EDGES, TRIAGE_EDGES, GIT_EDGES, ALL_EDGE_TYPES, EDGE_WEIGHT, CAUSAL_PROTECT_EDGES, VALIDATION_SOURCES, ABSTRACTION_LEVEL, PROBLEM_RESOLUTION, DRIFT_KIND;
18
18
  var init_castalia = __esm({
19
19
  "../../packages/shared/src/castalia.ts"() {
20
20
  "use strict";
@@ -173,6 +173,7 @@ var init_castalia = __esm({
173
173
  DECOMPOSITION_EDGES = ["SPLIT_INTO"];
174
174
  TRANSFER_EDGES = ["MAY_RESOLVE"];
175
175
  SOLUTION_STRUCTURE_EDGES = ["BUILDS_ON", "SUPERSEDES", "ALTERNATIVE_TO"];
176
+ SUSPICION_EDGES = ["SUSPECTED_LINK"];
176
177
  TAXONOMY_EDGES = ["IS_A"];
177
178
  TRIAGE_EDGES = ["TRIAGED_BY", "CONFIRMS", "INDICATES", "ROUTES_TO"];
178
179
  GIT_EDGES = ["POINTS_AT", "PARENT", "AUTHORED_BY"];
@@ -181,6 +182,7 @@ var init_castalia = __esm({
181
182
  ...CAUSAL_EDGES,
182
183
  ...RESOLUTION_EDGES,
183
184
  ...SOLUTION_STRUCTURE_EDGES,
185
+ ...SUSPICION_EDGES,
184
186
  ...CONCEPTUAL_EDGES,
185
187
  ...EVIDENCE_EDGES,
186
188
  ...CODE_EDGES,
@@ -297,6 +299,8 @@ var init_castalia = __esm({
297
299
  BUILDS_ON: 0.4,
298
300
  SUPERSEDES: 0,
299
301
  ALTERNATIVE_TO: 0,
302
+ // Suspicion — a hypothesis, weightless + PageRank-excluded (never flows rank / EIG).
303
+ SUSPECTED_LINK: 0,
300
304
  // Git — topology/authorship, weightless (not domain signal-flow)
301
305
  POINTS_AT: 0,
302
306
  PARENT: 0,
package/errata.mjs CHANGED
@@ -64,7 +64,7 @@ function toCloudAttrs(attrs) {
64
64
  }
65
65
  return rest2;
66
66
  }
67
- var SEMANTIC_NODE_LABELS, CONTEXT_NODE_LABELS, CODE_NODE_LABELS, ALL_NODE_LABELS, STRUCTURAL_EDGES, CAUSAL_EDGES, RESOLUTION_EDGES, CONCEPTUAL_EDGES, EVIDENCE_EDGES, CODE_EDGES, BRIDGE_EDGES, IDENTITY_EDGES, JUSTIFICATION_EDGES, BELIEF_EDGES, ABSTRACTION_EDGES, DECOMPOSITION_EDGES, TRANSFER_EDGES, SOLUTION_STRUCTURE_EDGES, TAXONOMY_EDGES, TRIAGE_EDGES, GIT_EDGES, ALL_EDGE_TYPES, PAGERANK_EXCLUSIONS, EDGE_WEIGHT, EDGE_CONDUCTANCE_OVERRIDES, CAUSAL_PROTECT_EDGES, VALIDATION_SOURCES, TRUTH_KIND, ABSTRACTION_LEVEL, PROBLEM_RESOLUTION, DRIFT_KIND, TEST_PATH_RE, TEST_SCOPE_RE;
67
+ var SEMANTIC_NODE_LABELS, CONTEXT_NODE_LABELS, CODE_NODE_LABELS, ALL_NODE_LABELS, STRUCTURAL_EDGES, CAUSAL_EDGES, RESOLUTION_EDGES, CONCEPTUAL_EDGES, EVIDENCE_EDGES, CODE_EDGES, BRIDGE_EDGES, IDENTITY_EDGES, JUSTIFICATION_EDGES, BELIEF_EDGES, ABSTRACTION_EDGES, DECOMPOSITION_EDGES, TRANSFER_EDGES, SOLUTION_STRUCTURE_EDGES, SUSPICION_EDGES, TAXONOMY_EDGES, TRIAGE_EDGES, GIT_EDGES, ALL_EDGE_TYPES, PAGERANK_EXCLUSIONS, EDGE_WEIGHT, EDGE_CONDUCTANCE_OVERRIDES, CAUSAL_PROTECT_EDGES, VALIDATION_SOURCES, TRUTH_KIND, ABSTRACTION_LEVEL, PROBLEM_RESOLUTION, DRIFT_KIND, TEST_PATH_RE, TEST_SCOPE_RE;
68
68
  var init_castalia = __esm({
69
69
  "../../packages/shared/src/castalia.ts"() {
70
70
  "use strict";
@@ -223,6 +223,7 @@ var init_castalia = __esm({
223
223
  DECOMPOSITION_EDGES = ["SPLIT_INTO"];
224
224
  TRANSFER_EDGES = ["MAY_RESOLVE"];
225
225
  SOLUTION_STRUCTURE_EDGES = ["BUILDS_ON", "SUPERSEDES", "ALTERNATIVE_TO"];
226
+ SUSPICION_EDGES = ["SUSPECTED_LINK"];
226
227
  TAXONOMY_EDGES = ["IS_A"];
227
228
  TRIAGE_EDGES = ["TRIAGED_BY", "CONFIRMS", "INDICATES", "ROUTES_TO"];
228
229
  GIT_EDGES = ["POINTS_AT", "PARENT", "AUTHORED_BY"];
@@ -231,6 +232,7 @@ var init_castalia = __esm({
231
232
  ...CAUSAL_EDGES,
232
233
  ...RESOLUTION_EDGES,
233
234
  ...SOLUTION_STRUCTURE_EDGES,
235
+ ...SUSPICION_EDGES,
234
236
  ...CONCEPTUAL_EDGES,
235
237
  ...EVIDENCE_EDGES,
236
238
  ...CODE_EDGES,
@@ -279,9 +281,11 @@ var init_castalia = __esm({
279
281
  // agent attribution (Agent → knowledge), not signal-flow
280
282
  "SUPERSEDES",
281
283
  // "prefer newer" gradient between solutions, not signal-flow
282
- "ALTERNATIVE_TO"
284
+ "ALTERNATIVE_TO",
283
285
  // symmetric peer marker — weight would let alternatives inflate each other
284
286
  // NB: BUILDS_ON is NOT excluded — it flows extension→base so foundational solutions rank up.
287
+ "SUSPECTED_LINK"
288
+ // Somnus hypothesis (PLAN_SOMNUS_V2 §4) — never flows rank; navigation-invisible.
285
289
  ]);
286
290
  EDGE_WEIGHT = {
287
291
  // Causal — high signal
@@ -385,6 +389,8 @@ var init_castalia = __esm({
385
389
  BUILDS_ON: 0.4,
386
390
  SUPERSEDES: 0,
387
391
  ALTERNATIVE_TO: 0,
392
+ // Suspicion — a hypothesis, weightless + PageRank-excluded (never flows rank / EIG).
393
+ SUSPECTED_LINK: 0,
388
394
  // Git — topology/authorship, weightless (not domain signal-flow)
389
395
  POINTS_AT: 0,
390
396
  PARENT: 0,
@@ -15644,6 +15650,7 @@ __export(src_exports, {
15644
15650
  SEMANTIC_NODE_LABELS: () => SEMANTIC_NODE_LABELS,
15645
15651
  SOLUTION_STRUCTURE_EDGES: () => SOLUTION_STRUCTURE_EDGES,
15646
15652
  STRUCTURAL_EDGES: () => STRUCTURAL_EDGES,
15653
+ SUSPICION_EDGES: () => SUSPICION_EDGES,
15647
15654
  SYMBOL_SUMMARY_KINDS: () => SYMBOL_SUMMARY_KINDS,
15648
15655
  SymbolSummarySidecarSchema: () => SymbolSummarySidecarSchema,
15649
15656
  TAXONOMY_EDGES: () => TAXONOMY_EDGES,
@@ -20355,13 +20362,8 @@ function renderSnapshot(s) {
20355
20362
  if (s.skills.length > 0) {
20356
20363
  lines.push("### Skills available");
20357
20364
  lines.push(
20358
- `${s.skills.length} induced skill${s.skills.length === 1 ? "" : "s"} for this workspace. Read the body before applying; full manifest at \`.errata/skills.json\`.`
20365
+ `${s.skills.length} induced skill${s.skills.length === 1 ? "" : "s"} for this workspace, installed as \`SKILL.md\` under \`.agents/skills/\` (and your harness's skills dir) \u2014 invoke natively. No auto-discovery (e.g. Aider)? \`/read-only\` the relevant \`.agents/skills/errata-*/SKILL.md\`.`
20359
20366
  );
20360
- for (const sk of [...s.skills].sort((a, b) => b.confidence - a.confidence).slice(0, 10)) {
20361
- lines.push(
20362
- `- **${sk.title}** (${sk.layer}, ${(sk.confidence * 100).toFixed(0)}%) \u2192 \`.errata/${sk.file}\``
20363
- );
20364
- }
20365
20367
  lines.push("");
20366
20368
  }
20367
20369
  lines.push("### Prior knowledge sampled from the shared graph");
@@ -38547,12 +38549,12 @@ var init_report_render = __esm({
38547
38549
 
38548
38550
  // src/cli.ts
38549
38551
  init_src5();
38550
- import { closeSync as closeSync2, existsSync as existsSync22, openSync as openSync2, readFileSync as readFileSync20, renameSync as renameSync3, statSync as statSync6 } from "node:fs";
38551
- import { join as join25 } from "node:path";
38552
+ import { closeSync as closeSync2, existsSync as existsSync23, openSync as openSync2, readFileSync as readFileSync21, renameSync as renameSync3, statSync as statSync6 } from "node:fs";
38553
+ import { join as join26 } from "node:path";
38552
38554
  import { spawn as spawn3 } from "node:child_process";
38553
38555
 
38554
38556
  // src/daemon.ts
38555
- import { existsSync as existsSync17, writeFileSync as writeFileSync13 } from "node:fs";
38557
+ import { existsSync as existsSync18, writeFileSync as writeFileSync14 } from "node:fs";
38556
38558
 
38557
38559
  // ../../node_modules/.pnpm/@hono+node-server@1.19.11_hono@4.12.8/node_modules/@hono/node-server/dist/index.mjs
38558
38560
  import { createServer as createServerHTTP } from "http";
@@ -39132,8 +39134,8 @@ init_config();
39132
39134
 
39133
39135
  // src/engine.ts
39134
39136
  import { execFileSync as execFileSync3 } from "node:child_process";
39135
- import { existsSync as existsSync16, statSync as statSync5, appendFileSync as appendFileSync2, readdirSync as readdirSync7, renameSync as renameSync2, readFileSync as readFileSync15, writeFileSync as writeFileSync12 } from "node:fs";
39136
- import { join as join21, relative as relative6, sep as sep4 } from "node:path";
39137
+ import { existsSync as existsSync17, statSync as statSync5, appendFileSync as appendFileSync2, readdirSync as readdirSync8, renameSync as renameSync2, readFileSync as readFileSync16, writeFileSync as writeFileSync13 } from "node:fs";
39138
+ import { join as join22, relative as relative6, sep as sep4 } from "node:path";
39137
39139
 
39138
39140
  // ../../node_modules/.pnpm/chokidar@4.0.3/node_modules/chokidar/esm/index.js
39139
39141
  import { stat as statcb } from "fs";
@@ -42620,6 +42622,164 @@ async function syncSkills(paths, client, seed, pins = []) {
42620
42622
  return { written: rows.length, pruned, ...staleDaemon ? { staleDaemon } : {} };
42621
42623
  }
42622
42624
 
42625
+ // src/agent-skills.ts
42626
+ import {
42627
+ cpSync,
42628
+ existsSync as existsSync14,
42629
+ lstatSync,
42630
+ mkdirSync as mkdirSync6,
42631
+ readFileSync as readFileSync13,
42632
+ readdirSync as readdirSync7,
42633
+ rmSync as rmSync2,
42634
+ symlinkSync,
42635
+ writeFileSync as writeFileSync11
42636
+ } from "node:fs";
42637
+ import { join as join19 } from "node:path";
42638
+ var SKILL_NS = "errata-";
42639
+ var HARNESS_SKILL_DIRS = [
42640
+ { configDir: ".claude", skillsDir: join19(".claude", "skills") },
42641
+ // Cursor adopted the standard; its exact project dir is still moving — kept
42642
+ // best-effort and gated on `.cursor/` presence so we never create it blind.
42643
+ { configDir: ".cursor", skillsDir: join19(".cursor", "skills") }
42644
+ ];
42645
+ function skillSlug(title, id) {
42646
+ const base = title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || id.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "skill";
42647
+ return `${SKILL_NS}${base}`.slice(0, 64).replace(/-+$/, "");
42648
+ }
42649
+ function yamlScalar(s) {
42650
+ return `"${s.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\s+/g, " ").trim()}"`;
42651
+ }
42652
+ function deriveDescription(title, layer, body2) {
42653
+ const firstProse = body2.split(/\r?\n/).map((l) => l.trim()).find((l) => l.length > 0 && !l.startsWith("#") && !l.startsWith("---"));
42654
+ const lead = firstProse && firstProse.length >= 24 ? firstProse : title;
42655
+ const when = ` Apply when working on ${layer === "antipattern" ? "code that risks this pitfall" : "problems in this area"}.`;
42656
+ return `${lead}${lead.endsWith(".") ? "" : "."}${when}`.slice(0, 1024);
42657
+ }
42658
+ function renderSkillMd(name2, description, body2) {
42659
+ return `---
42660
+ name: ${name2}
42661
+ description: ${yamlScalar(description)}
42662
+ ---
42663
+
42664
+ ${body2.trimEnd()}
42665
+ `;
42666
+ }
42667
+ function reconcileNamespaced(dir, keep) {
42668
+ if (!existsSync14(dir)) return 0;
42669
+ let pruned = 0;
42670
+ for (const name2 of readdirSync7(dir)) {
42671
+ if (!name2.startsWith(SKILL_NS) || keep.has(name2)) continue;
42672
+ try {
42673
+ rmSync2(join19(dir, name2), { recursive: true, force: true });
42674
+ pruned++;
42675
+ } catch {
42676
+ }
42677
+ }
42678
+ return pruned;
42679
+ }
42680
+ function linkOrCopy(linkPath, target) {
42681
+ try {
42682
+ if (existsSync14(linkPath) || safeLstat(linkPath)) rmSync2(linkPath, { recursive: true, force: true });
42683
+ } catch {
42684
+ }
42685
+ try {
42686
+ symlinkSync(target, linkPath, "junction");
42687
+ } catch {
42688
+ try {
42689
+ cpSync(target, linkPath, { recursive: true });
42690
+ } catch {
42691
+ }
42692
+ }
42693
+ }
42694
+ function safeLstat(p) {
42695
+ try {
42696
+ lstatSync(p);
42697
+ return true;
42698
+ } catch {
42699
+ return false;
42700
+ }
42701
+ }
42702
+ function emitAndProjectSkills(root, skills) {
42703
+ const agentsSkillsDir = join19(root, ".agents", "skills");
42704
+ mkdirSync6(agentsSkillsDir, { recursive: true });
42705
+ const slugs = [];
42706
+ const keep = /* @__PURE__ */ new Set();
42707
+ let emitted = 0;
42708
+ for (const s of skills) {
42709
+ let body2;
42710
+ try {
42711
+ body2 = readFileSync13(s.bodyPath, "utf8");
42712
+ } catch {
42713
+ continue;
42714
+ }
42715
+ const slug2 = skillSlug(s.title, s.id);
42716
+ if (keep.has(slug2)) continue;
42717
+ keep.add(slug2);
42718
+ slugs.push(slug2);
42719
+ const description = deriveDescription(s.title, s.layer, body2);
42720
+ mkdirSync6(join19(agentsSkillsDir, slug2), { recursive: true });
42721
+ writeFileSync11(
42722
+ join19(agentsSkillsDir, slug2, "SKILL.md"),
42723
+ renderSkillMd(slug2, description, body2),
42724
+ "utf8"
42725
+ );
42726
+ emitted++;
42727
+ }
42728
+ reconcileNamespaced(agentsSkillsDir, keep);
42729
+ let projected = 0;
42730
+ for (const h of HARNESS_SKILL_DIRS) {
42731
+ if (!existsSync14(join19(root, h.configDir))) continue;
42732
+ const dir = join19(root, h.skillsDir);
42733
+ mkdirSync6(dir, { recursive: true });
42734
+ for (const slug2 of slugs) {
42735
+ linkOrCopy(join19(dir, slug2), join19(agentsSkillsDir, slug2));
42736
+ projected++;
42737
+ }
42738
+ reconcileNamespaced(dir, keep);
42739
+ }
42740
+ ensureSkillGitignore(root);
42741
+ return { slugs, emitted, projected };
42742
+ }
42743
+ function emitInputsFromManifest(erretaDir, manifestPath) {
42744
+ if (!existsSync14(manifestPath)) return [];
42745
+ try {
42746
+ const parsed = JSON.parse(readFileSync13(manifestPath, "utf8"));
42747
+ return (parsed.skills ?? []).filter((s) => Boolean(s.id && s.file)).map((s) => ({
42748
+ id: s.id,
42749
+ title: s.title ?? s.id,
42750
+ layer: s.layer ?? "technique",
42751
+ confidence: s.confidence ?? 0,
42752
+ bodyPath: join19(erretaDir, s.file)
42753
+ }));
42754
+ } catch {
42755
+ return [];
42756
+ }
42757
+ }
42758
+ var GITIGNORE_MARK = "# errata-managed agent skills (daemon-synced; namespaced)";
42759
+ var GITIGNORE_LINES = [
42760
+ GITIGNORE_MARK,
42761
+ ".agents/skills/errata-*/",
42762
+ ".claude/skills/errata-*/",
42763
+ ".cursor/skills/errata-*/"
42764
+ ];
42765
+ function ensureSkillGitignore(root) {
42766
+ const path2 = join19(root, ".gitignore");
42767
+ let current = "";
42768
+ try {
42769
+ current = existsSync14(path2) ? readFileSync13(path2, "utf8") : "";
42770
+ } catch {
42771
+ return;
42772
+ }
42773
+ if (current.includes(GITIGNORE_MARK)) return;
42774
+ const prefix = current.length > 0 && !current.endsWith("\n") ? "\n" : "";
42775
+ try {
42776
+ writeFileSync11(path2, `${current}${prefix}
42777
+ ${GITIGNORE_LINES.join("\n")}
42778
+ `, "utf8");
42779
+ } catch {
42780
+ }
42781
+ }
42782
+
42623
42783
  // src/working-file-state.ts
42624
42784
  function createWorkingFileState() {
42625
42785
  const bySession = /* @__PURE__ */ new Map();
@@ -42749,20 +42909,20 @@ var CausalBuffer = class {
42749
42909
  // src/profile.ts
42750
42910
  init_src2();
42751
42911
  init_paths();
42752
- import { existsSync as existsSync15, readFileSync as readFileSync14, writeFileSync as writeFileSync11 } from "node:fs";
42912
+ import { existsSync as existsSync16, readFileSync as readFileSync15, writeFileSync as writeFileSync12 } from "node:fs";
42753
42913
  import { createHash as createHash12 } from "node:crypto";
42754
- import { join as join20 } from "node:path";
42914
+ import { join as join21 } from "node:path";
42755
42915
 
42756
42916
  // src/git-remote.ts
42757
42917
  init_src();
42758
- import { existsSync as existsSync14, readFileSync as readFileSync13, statSync as statSync4 } from "node:fs";
42759
- import { isAbsolute as isAbsolute3, join as join19, resolve as resolve5 } from "node:path";
42918
+ import { existsSync as existsSync15, readFileSync as readFileSync14, statSync as statSync4 } from "node:fs";
42919
+ import { isAbsolute as isAbsolute3, join as join20, resolve as resolve5 } from "node:path";
42760
42920
  function resolveGitDir(root) {
42761
- const dotGit = join19(root, ".git");
42921
+ const dotGit = join20(root, ".git");
42762
42922
  try {
42763
42923
  const st = statSync4(dotGit);
42764
42924
  if (st.isDirectory()) return dotGit;
42765
- const m = /^gitdir:\s*(.+?)\s*$/m.exec(readFileSync13(dotGit, "utf8"));
42925
+ const m = /^gitdir:\s*(.+?)\s*$/m.exec(readFileSync14(dotGit, "utf8"));
42766
42926
  if (!m) return null;
42767
42927
  const dir = m[1];
42768
42928
  return isAbsolute3(dir) ? dir : resolve5(root, dir);
@@ -42771,22 +42931,22 @@ function resolveGitDir(root) {
42771
42931
  }
42772
42932
  }
42773
42933
  function gitConfigPath(gitDir) {
42774
- const commondirFile = join19(gitDir, "commondir");
42775
- if (existsSync14(commondirFile)) {
42776
- const common = readFileSync13(commondirFile, "utf8").trim();
42934
+ const commondirFile = join20(gitDir, "commondir");
42935
+ if (existsSync15(commondirFile)) {
42936
+ const common = readFileSync14(commondirFile, "utf8").trim();
42777
42937
  const commonDir = isAbsolute3(common) ? common : resolve5(gitDir, common);
42778
- return join19(commonDir, "config");
42938
+ return join20(commonDir, "config");
42779
42939
  }
42780
- return join19(gitDir, "config");
42940
+ return join20(gitDir, "config");
42781
42941
  }
42782
42942
  function readRemotes(root) {
42783
42943
  const gitDir = resolveGitDir(root);
42784
42944
  if (!gitDir) return [];
42785
42945
  const cfgPath = gitConfigPath(gitDir);
42786
- if (!existsSync14(cfgPath)) return [];
42946
+ if (!existsSync15(cfgPath)) return [];
42787
42947
  let txt;
42788
42948
  try {
42789
- txt = readFileSync13(cfgPath, "utf8");
42949
+ txt = readFileSync14(cfgPath, "utf8");
42790
42950
  } catch {
42791
42951
  return [];
42792
42952
  }
@@ -42818,13 +42978,13 @@ function refreshRepoLocator(root, profile) {
42818
42978
  }
42819
42979
  function loadProfile(root) {
42820
42980
  const p = workspacePaths(root);
42821
- if (!existsSync15(p.workspaceJson)) return null;
42822
- return JSON.parse(readFileSync14(p.workspaceJson, "utf8"));
42981
+ if (!existsSync16(p.workspaceJson)) return null;
42982
+ return JSON.parse(readFileSync15(p.workspaceJson, "utf8"));
42823
42983
  }
42824
42984
  function saveProfile(root, profile) {
42825
42985
  const p = workspacePaths(root);
42826
42986
  ensureDir(p.configDir);
42827
- writeFileSync11(p.workspaceJson, JSON.stringify(profile, null, 2), "utf8");
42987
+ writeFileSync12(p.workspaceJson, JSON.stringify(profile, null, 2), "utf8");
42828
42988
  }
42829
42989
  function autodetectProfile(root) {
42830
42990
  const id = workspaceId(root);
@@ -42832,10 +42992,10 @@ function autodetectProfile(root) {
42832
42992
  const p = emptyProfile(id, name2);
42833
42993
  const locator = detectRepoLocator(root);
42834
42994
  if (locator) p.repoLocator = locator;
42835
- const pkgPath = join20(root, "package.json");
42836
- if (existsSync15(pkgPath)) {
42995
+ const pkgPath = join21(root, "package.json");
42996
+ if (existsSync16(pkgPath)) {
42837
42997
  try {
42838
- const pkg = JSON.parse(readFileSync14(pkgPath, "utf8"));
42998
+ const pkg = JSON.parse(readFileSync15(pkgPath, "utf8"));
42839
42999
  p.languages.push("typescript", "javascript");
42840
43000
  const nodeVer = pkg.engines?.node ?? "node";
42841
43001
  p.stack.push(`node@${nodeVer}`);
@@ -42856,10 +43016,10 @@ function autodetectProfile(root) {
42856
43016
  } catch {
42857
43017
  }
42858
43018
  }
42859
- const pyproject = join20(root, "pyproject.toml");
42860
- if (existsSync15(pyproject)) {
43019
+ const pyproject = join21(root, "pyproject.toml");
43020
+ if (existsSync16(pyproject)) {
42861
43021
  try {
42862
- const txt = readFileSync14(pyproject, "utf8");
43022
+ const txt = readFileSync15(pyproject, "utf8");
42863
43023
  const py = /python\s*=\s*"([^"]+)"/.exec(txt)?.[1];
42864
43024
  p.languages.push("python");
42865
43025
  p.stack.push(`python@${py ?? "3"}`);
@@ -42870,16 +43030,16 @@ function autodetectProfile(root) {
42870
43030
  } catch {
42871
43031
  }
42872
43032
  }
42873
- const reqs = join20(root, "requirements.txt");
42874
- if (existsSync15(reqs)) {
43033
+ const reqs = join21(root, "requirements.txt");
43034
+ if (existsSync16(reqs)) {
42875
43035
  if (!p.languages.includes("python")) p.languages.push("python");
42876
43036
  if (!p.stack.includes("python@3")) p.stack.push("python@3");
42877
43037
  }
42878
- if (existsSync15(join20(root, "go.mod"))) {
43038
+ if (existsSync16(join21(root, "go.mod"))) {
42879
43039
  p.languages.push("go");
42880
43040
  p.stack.push("go");
42881
43041
  }
42882
- if (existsSync15(join20(root, "Cargo.toml"))) {
43042
+ if (existsSync16(join21(root, "Cargo.toml"))) {
42883
43043
  p.languages.push("rust");
42884
43044
  p.stack.push("rust");
42885
43045
  }
@@ -43037,7 +43197,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
43037
43197
  }
43038
43198
 
43039
43199
  // src/engine.ts
43040
- var DAEMON_VERSION = true ? "2.0.0-dev.70" : "2.0.0-alpha.0";
43200
+ var DAEMON_VERSION = true ? "2.0.0-dev.72" : "2.0.0-alpha.0";
43041
43201
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
43042
43202
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
43043
43203
  var GIT_OP_MUTE_MS = 4e3;
@@ -43047,7 +43207,7 @@ var TURN_REPLAY_LOOKBACK_MS = 7 * 24 * 60 * 6e4;
43047
43207
  function appendIdentityAudit(path2, record2, line) {
43048
43208
  if (!record2.accepted && record2.score <= 0) return;
43049
43209
  try {
43050
- if (existsSync16(path2) && statSync5(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
43210
+ if (existsSync17(path2) && statSync5(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
43051
43211
  renameSync2(path2, `${path2}.1`);
43052
43212
  }
43053
43213
  appendFileSync2(path2, line);
@@ -43057,14 +43217,14 @@ function appendIdentityAudit(path2, record2, line) {
43057
43217
  var yieldToLoop = () => new Promise((r) => setImmediate(r));
43058
43218
  function loadTurnCursors(path2) {
43059
43219
  try {
43060
- return new Map(Object.entries(JSON.parse(readFileSync15(path2, "utf8"))));
43220
+ return new Map(Object.entries(JSON.parse(readFileSync16(path2, "utf8"))));
43061
43221
  } catch {
43062
43222
  return /* @__PURE__ */ new Map();
43063
43223
  }
43064
43224
  }
43065
43225
  function saveTurnCursors(path2, cursors) {
43066
43226
  try {
43067
- writeFileSync12(path2, JSON.stringify(Object.fromEntries(cursors)), "utf8");
43227
+ writeFileSync13(path2, JSON.stringify(Object.fromEntries(cursors)), "utf8");
43068
43228
  } catch {
43069
43229
  }
43070
43230
  }
@@ -43086,7 +43246,7 @@ function gitSourceWatchTargets(root) {
43086
43246
  ["-C", root, "ls-files", "--others", "--ignored", "--exclude-standard", "--directory", "-z"],
43087
43247
  { encoding: "utf8", maxBuffer: 256 * 1024 * 1024, windowsHide: true, stdio: ["ignore", "pipe", "ignore"] }
43088
43248
  );
43089
- ignoredDirs = igOut.split("\0").filter(Boolean).map((d) => d.replace(/\/+$/, "")).filter((d) => !IGNORED_PATH.test(join21(root, d) + sep4));
43249
+ ignoredDirs = igOut.split("\0").filter(Boolean).map((d) => d.replace(/\/+$/, "")).filter((d) => !IGNORED_PATH.test(join22(root, d) + sep4));
43090
43250
  } catch {
43091
43251
  }
43092
43252
  const hasIgnoredChild = (dir) => ignoredDirs.some((ig) => ig.startsWith(dir + "/"));
@@ -43098,19 +43258,19 @@ function gitSourceWatchTargets(root) {
43098
43258
  if (!f.startsWith(prefix)) continue;
43099
43259
  const rest2 = f.slice(prefix.length);
43100
43260
  if (rest2.includes("/")) children.add(dir === "" ? rest2.slice(0, rest2.indexOf("/")) : dir + "/" + rest2.slice(0, rest2.indexOf("/")));
43101
- else targets.add(join21(root, f));
43261
+ else targets.add(join22(root, f));
43102
43262
  }
43103
43263
  for (const c of children) {
43104
- if (IGNORED_PATH.test(join21(root, c) + sep4)) continue;
43264
+ if (IGNORED_PATH.test(join22(root, c) + sep4)) continue;
43105
43265
  if (hasIgnoredChild(c)) addUnder(c);
43106
- else targets.add(join21(root, c));
43266
+ else targets.add(join22(root, c));
43107
43267
  }
43108
43268
  };
43109
43269
  addUnder("");
43110
43270
  if (targets.size > 0) return [...targets];
43111
43271
  } catch {
43112
43272
  }
43113
- return readdirSync7(root, { withFileTypes: true }).filter((e) => e.isDirectory() && !IGNORED_PATH.test(join21(root, String(e.name)) + sep4)).map((e) => join21(root, String(e.name)));
43273
+ return readdirSync8(root, { withFileTypes: true }).filter((e) => e.isDirectory() && !IGNORED_PATH.test(join22(root, String(e.name)) + sep4)).map((e) => join22(root, String(e.name)));
43114
43274
  }
43115
43275
  function createWorkspaceEngine(opts) {
43116
43276
  const paths = workspacePaths(opts.workspaceRoot);
@@ -43264,7 +43424,7 @@ function createWorkspaceEngine(opts) {
43264
43424
  const srcPaths = diff.changedPaths.filter((p) => /\.(ts|tsx|js|jsx|mjs|cjs|py)$/i.test(p));
43265
43425
  let episodeId2;
43266
43426
  if (srcPaths.length > 0) {
43267
- const abs = srcPaths.map((p) => join21(opts.workspaceRoot, p));
43427
+ const abs = srcPaths.map((p) => join22(opts.workspaceRoot, p));
43268
43428
  try {
43269
43429
  const r = await runReindexPass(
43270
43430
  `git-reindex:${profile.name} (${abs.length} files)`,
@@ -43300,8 +43460,8 @@ function createWorkspaceEngine(opts) {
43300
43460
  `[errata] git: ${ev.kind} ${ev.newSha.slice(0, 7)} by ${meta3.authorName} \u2014 ${diff.changedPaths.length} file(s), ${diff.renames.length} rename(s)`
43301
43461
  );
43302
43462
  };
43303
- const gitDir = join21(opts.workspaceRoot, ".git");
43304
- if (existsSync16(gitDir)) {
43463
+ const gitDir = join22(opts.workspaceRoot, ".git");
43464
+ if (existsSync17(gitDir)) {
43305
43465
  stopGit = startGitSensor(gitDir, (ev) => {
43306
43466
  void handleGitEvent(ev).catch((err2) => {
43307
43467
  console.warn("[errata] git event handler failed:", err2);
@@ -43369,10 +43529,10 @@ function createWorkspaceEngine(opts) {
43369
43529
  ...pendingUpdate ? { pendingUpdate } : {}
43370
43530
  });
43371
43531
  doneRender?.();
43372
- const target = join21(opts.workspaceRoot, "AGENTS.md");
43532
+ const target = join22(opts.workspaceRoot, "AGENTS.md");
43373
43533
  writeManagedBlock(target, { body: body2 });
43374
43534
  if (elicit) {
43375
- writePrimingHandles(join21(paths.configDir, "priming-handles.json"), [
43535
+ writePrimingHandles(join22(paths.configDir, "priming-handles.json"), [
43376
43536
  ...snapshot.recentProblems.map((r) => r.node),
43377
43537
  // Resolved-band handles: the ✓ problem AND its Solution are citable
43378
43538
  // (a fix tag on an already-resolved problem no-ops idempotently; the
@@ -43542,7 +43702,7 @@ function createWorkspaceEngine(opts) {
43542
43702
  resultSummary: { exitCode: e.exitCode ?? 1, errorTokens: e.errorTokens }
43543
43703
  });
43544
43704
  };
43545
- const turnCursorPath = join21(paths.configDir, "turn-cursors.json");
43705
+ const turnCursorPath = join22(paths.configDir, "turn-cursors.json");
43546
43706
  const lastTurnUuid = loadTurnCursors(turnCursorPath);
43547
43707
  const sessionLastProblem = /* @__PURE__ */ new Map();
43548
43708
  const sessionThreads = /* @__PURE__ */ new Map();
@@ -43565,7 +43725,7 @@ function createWorkspaceEngine(opts) {
43565
43725
  const t = Date.now();
43566
43726
  let processedTurns = 0;
43567
43727
  const elicit = isEdgeElicitationEnabled();
43568
- const handleMap = elicit ? readPrimingHandles(join21(paths.configDir, "priming-handles.json")) : {};
43728
+ const handleMap = elicit ? readPrimingHandles(join22(paths.configDir, "priming-handles.json")) : {};
43569
43729
  const wsRoot = (opts.workspaceRoot ?? "").replace(/\\/g, "/");
43570
43730
  const toRel = (abs) => {
43571
43731
  const p = abs.replace(/\\/g, "/");
@@ -44042,7 +44202,13 @@ function createWorkspaceEngine(opts) {
44042
44202
  return typeof cloudId === "string" && cloudId !== p.id ? [p.id, cloudId] : [p.id];
44043
44203
  });
44044
44204
  const pins = profile?.projectId ? await cloud.getSkillPins(profile.projectId).then((r) => r.pins).catch(() => []) : [];
44045
- return syncSkills(paths, cloud, skillSeed, pins);
44205
+ const result = await syncSkills(paths, cloud, skillSeed, pins);
44206
+ try {
44207
+ emitAndProjectSkills(opts.workspaceRoot, emitInputsFromManifest(paths.configDir, paths.skillsManifest));
44208
+ } catch (err2) {
44209
+ console.warn("[skills] agent-skills projection failed (non-fatal):", err2 instanceof Error ? err2.message : err2);
44210
+ }
44211
+ return result;
44046
44212
  };
44047
44213
  return {
44048
44214
  profile,
@@ -44224,7 +44390,7 @@ function createWorkspaceEngine(opts) {
44224
44390
  console.log(
44225
44391
  "[errata] sync skipped \u2014 cloud sync consent is off (enable with `errata consent sync on`)"
44226
44392
  );
44227
- const pending = existsSync16(paths.outbox) ? readdirSync7(paths.outbox).filter((f) => f.endsWith(".json")).length : 0;
44393
+ const pending = existsSync17(paths.outbox) ? readdirSync8(paths.outbox).filter((f) => f.endsWith(".json")).length : 0;
44228
44394
  return { uploaded: 0, failed: 0, remaining: pending };
44229
44395
  }
44230
44396
  try {
@@ -44311,7 +44477,7 @@ async function startDaemon(opts) {
44311
44477
  reviewUrl: () => webUiUrl + "/review"
44312
44478
  });
44313
44479
  const writeLockFile = (url2) => {
44314
- writeFileSync13(
44480
+ writeFileSync14(
44315
44481
  engine.paths.daemonLock,
44316
44482
  JSON.stringify({ pid: process.pid, webUiUrl: url2, startedAt: Date.now() }),
44317
44483
  "utf8"
@@ -44354,7 +44520,7 @@ async function startDaemon(opts) {
44354
44520
  );
44355
44521
  await engine.stop();
44356
44522
  try {
44357
- if (existsSync17(engine.paths.daemonLock)) {
44523
+ if (existsSync18(engine.paths.daemonLock)) {
44358
44524
  }
44359
44525
  } catch {
44360
44526
  }
@@ -44371,16 +44537,16 @@ async function listenServer(fetchFn, port) {
44371
44537
 
44372
44538
  // src/registry.ts
44373
44539
  init_paths();
44374
- import { existsSync as existsSync18, readFileSync as readFileSync16, writeFileSync as writeFileSync14 } from "node:fs";
44375
- import { join as join22 } from "node:path";
44540
+ import { existsSync as existsSync19, readFileSync as readFileSync17, writeFileSync as writeFileSync15 } from "node:fs";
44541
+ import { join as join23 } from "node:path";
44376
44542
  function registryPath() {
44377
- return process.env["ERRATA_REGISTRY_PATH"] ?? join22(globalDir(), "workspaces.json");
44543
+ return process.env["ERRATA_REGISTRY_PATH"] ?? join23(globalDir(), "workspaces.json");
44378
44544
  }
44379
44545
  function read() {
44380
44546
  const p = registryPath();
44381
- if (!existsSync18(p)) return { version: 1, workspaces: {} };
44547
+ if (!existsSync19(p)) return { version: 1, workspaces: {} };
44382
44548
  try {
44383
- const parsed = JSON.parse(readFileSync16(p, "utf8"));
44549
+ const parsed = JSON.parse(readFileSync17(p, "utf8"));
44384
44550
  return { version: 1, workspaces: parsed.workspaces ?? {} };
44385
44551
  } catch {
44386
44552
  return { version: 1, workspaces: {} };
@@ -44388,7 +44554,7 @@ function read() {
44388
44554
  }
44389
44555
  function write(reg) {
44390
44556
  ensureDir(globalDir());
44391
- writeFileSync14(registryPath(), JSON.stringify(reg, null, 2), "utf8");
44557
+ writeFileSync15(registryPath(), JSON.stringify(reg, null, 2), "utf8");
44392
44558
  }
44393
44559
  function registerWorkspace(profile, root, now = Date.now()) {
44394
44560
  const reg = read();
@@ -44405,7 +44571,7 @@ function pruneMissingWorkspaces() {
44405
44571
  const reg = read();
44406
44572
  const removed = [];
44407
44573
  for (const [id, entry] of Object.entries(reg.workspaces)) {
44408
- if (!existsSync18(entry.path)) {
44574
+ if (!existsSync19(entry.path)) {
44409
44575
  removed.push(entry);
44410
44576
  delete reg.workspaces[id];
44411
44577
  }
@@ -44414,13 +44580,13 @@ function pruneMissingWorkspaces() {
44414
44580
  return removed;
44415
44581
  }
44416
44582
  function workspaceStatus(entry) {
44417
- const missing = !existsSync18(entry.path);
44583
+ const missing = !existsSync19(entry.path);
44418
44584
  const lockPath = workspacePaths(entry.path).daemonLock;
44419
44585
  let running = false;
44420
44586
  let webUiUrl = null;
44421
- if (existsSync18(lockPath)) {
44587
+ if (existsSync19(lockPath)) {
44422
44588
  try {
44423
- const lock = JSON.parse(readFileSync16(lockPath, "utf8"));
44589
+ const lock = JSON.parse(readFileSync17(lockPath, "utf8"));
44424
44590
  if (lock.pid && lock.webUiUrl && pidAlive(lock.pid)) {
44425
44591
  running = true;
44426
44592
  webUiUrl = lock.webUiUrl;
@@ -44448,7 +44614,7 @@ function pidAlive(pid) {
44448
44614
  // src/multi.ts
44449
44615
  init_dist();
44450
44616
  init_src4();
44451
- import { readFileSync as readFileSync19, unlinkSync as unlinkSync3, writeFileSync as writeFileSync15 } from "node:fs";
44617
+ import { readFileSync as readFileSync20, unlinkSync as unlinkSync3, writeFileSync as writeFileSync16 } from "node:fs";
44452
44618
 
44453
44619
  // src/principle-sync.ts
44454
44620
  init_src4();
@@ -44475,8 +44641,8 @@ async function syncPrinciples(store, cloud, opts) {
44475
44641
  init_reconcile();
44476
44642
 
44477
44643
  // src/lockfile-auto.ts
44478
- import { existsSync as existsSync19, readFileSync as readFileSync17 } from "node:fs";
44479
- import { join as join23 } from "node:path";
44644
+ import { existsSync as existsSync20, readFileSync as readFileSync18 } from "node:fs";
44645
+ import { join as join24 } from "node:path";
44480
44646
 
44481
44647
  // src/package-index.ts
44482
44648
  init_src();
@@ -44740,11 +44906,11 @@ function runLockfilePass(opts) {
44740
44906
  { file: "package-lock.json", parse: parsePackageLockJson }
44741
44907
  ];
44742
44908
  for (const c of candidates) {
44743
- const p = join23(opts.root, c.file);
44744
- if (!existsSync19(p)) continue;
44909
+ const p = join24(opts.root, c.file);
44910
+ if (!existsSync20(p)) continue;
44745
44911
  let sbom;
44746
44912
  try {
44747
- sbom = c.parse(readFileSync17(p, "utf8"));
44913
+ sbom = c.parse(readFileSync18(p, "utf8"));
44748
44914
  } catch {
44749
44915
  continue;
44750
44916
  }
@@ -45020,7 +45186,7 @@ var ConsolidateWorker = class {
45020
45186
  init_paths();
45021
45187
 
45022
45188
  // src/lock.ts
45023
- import { existsSync as existsSync20, readFileSync as readFileSync18 } from "node:fs";
45189
+ import { existsSync as existsSync21, readFileSync as readFileSync19 } from "node:fs";
45024
45190
  function isProcessAlive(pid) {
45025
45191
  if (!pid || pid <= 0) return false;
45026
45192
  try {
@@ -45031,9 +45197,9 @@ function isProcessAlive(pid) {
45031
45197
  }
45032
45198
  }
45033
45199
  function readDaemonLock(lockPath) {
45034
- if (!existsSync20(lockPath)) return null;
45200
+ if (!existsSync21(lockPath)) return null;
45035
45201
  try {
45036
- const lock = JSON.parse(readFileSync18(lockPath, "utf8"));
45202
+ const lock = JSON.parse(readFileSync19(lockPath, "utf8"));
45037
45203
  return typeof lock.pid === "number" ? lock : null;
45038
45204
  } catch {
45039
45205
  return null;
@@ -45157,12 +45323,12 @@ async function ensureProjectLink(root, profile, client) {
45157
45323
  }
45158
45324
 
45159
45325
  // src/adopt.ts
45160
- import { existsSync as existsSync21 } from "node:fs";
45161
- import { dirname as dirname8, join as join24 } from "node:path";
45326
+ import { existsSync as existsSync22 } from "node:fs";
45327
+ import { dirname as dirname8, join as join25 } from "node:path";
45162
45328
  function findGitRoot(absPath) {
45163
45329
  let dir = absPath;
45164
45330
  for (let depth = 0; depth < 64; depth++) {
45165
- if (existsSync21(join24(dir, ".git"))) return dir;
45331
+ if (existsSync22(join25(dir, ".git"))) return dir;
45166
45332
  const parent = dirname8(dir);
45167
45333
  if (parent === dir) return null;
45168
45334
  dir = parent;
@@ -45350,7 +45516,7 @@ async function startMultiDaemon(opts = {}) {
45350
45516
  void ambientLinkAll();
45351
45517
  app.route(`/ws/${rec.id}`, rec.webApp);
45352
45518
  try {
45353
- writeFileSync15(
45519
+ writeFileSync16(
45354
45520
  rec.engine.paths.daemonLock,
45355
45521
  JSON.stringify({ pid: process.pid, webUiUrl: `${baseUrl}/ws/${rec.id}`, startedAt: Date.now() }),
45356
45522
  "utf8"
@@ -45536,7 +45702,7 @@ async function startMultiDaemon(opts = {}) {
45536
45702
  baseUrl = `http://127.0.0.1:${port}`;
45537
45703
  try {
45538
45704
  ensureDir(globalDir());
45539
- writeFileSync15(
45705
+ writeFileSync16(
45540
45706
  lockPath,
45541
45707
  JSON.stringify({ pid: process.pid, webUiUrl: baseUrl, startedAt: Date.now() }),
45542
45708
  "utf8"
@@ -45545,7 +45711,7 @@ async function startMultiDaemon(opts = {}) {
45545
45711
  }
45546
45712
  for (const r of records) {
45547
45713
  try {
45548
- writeFileSync15(
45714
+ writeFileSync16(
45549
45715
  r.engine.paths.daemonLock,
45550
45716
  JSON.stringify({ pid: process.pid, webUiUrl: `${baseUrl}/ws/${r.id}`, startedAt: Date.now() }),
45551
45717
  "utf8"
@@ -45899,7 +46065,7 @@ async function startMultiDaemon(opts = {}) {
45899
46065
  },
45900
46066
  async stop() {
45901
46067
  try {
45902
- const cur = readFileSync19(lockPath, "utf8");
46068
+ const cur = readFileSync20(lockPath, "utf8");
45903
46069
  if (JSON.parse(cur).pid === process.pid) unlinkSync3(lockPath);
45904
46070
  } catch {
45905
46071
  }
@@ -46494,21 +46660,21 @@ async function cmdInit() {
46494
46660
  if (!skipHooks) {
46495
46661
  console.log("");
46496
46662
  console.log("installing harness hooks...");
46497
- const { existsSync: existsSync23 } = await import("node:fs");
46498
- const { join: join26 } = await import("node:path");
46663
+ const { existsSync: existsSync24 } = await import("node:fs");
46664
+ const { join: join27 } = await import("node:path");
46499
46665
  try {
46500
46666
  await installClaudeHooks(port);
46501
46667
  } catch (err2) {
46502
46668
  console.warn(` \u26A0\uFE0F Claude hook install failed: ${err2 instanceof Error ? err2.message : err2}`);
46503
46669
  }
46504
- if (existsSync23(join26(ROOT, ".cursor"))) {
46670
+ if (existsSync24(join27(ROOT, ".cursor"))) {
46505
46671
  try {
46506
46672
  await installCursorMcpConfig();
46507
46673
  } catch (err2) {
46508
46674
  console.warn(` \u26A0\uFE0F Cursor MCP config failed: ${err2 instanceof Error ? err2.message : err2}`);
46509
46675
  }
46510
46676
  }
46511
- if (existsSync23(join26(ROOT, ".codex"))) {
46677
+ if (existsSync24(join27(ROOT, ".codex"))) {
46512
46678
  try {
46513
46679
  await installCodexHooks(port);
46514
46680
  } catch (err2) {
@@ -46665,8 +46831,8 @@ async function cmdStatus() {
46665
46831
  console.log(` stack: ${profile.stack.join(", ") || "(none)"}`);
46666
46832
  console.log(` languages: ${profile.languages.join(", ") || "(none)"}`);
46667
46833
  }
46668
- console.log(` graph db: ${existsSync22(paths.castalia) ? "yes" : "no"} (${paths.castalia})`);
46669
- console.log(` event log: ${existsSync22(paths.eventLog) ? "yes" : "no"} (${paths.eventLog})`);
46834
+ console.log(` graph db: ${existsSync23(paths.castalia) ? "yes" : "no"} (${paths.castalia})`);
46835
+ console.log(` event log: ${existsSync23(paths.eventLog) ? "yes" : "no"} (${paths.eventLog})`);
46670
46836
  const lockPath = globalDaemonLock();
46671
46837
  const running = isDaemonAlive(lockPath) ? readDaemonLock(lockPath) : null;
46672
46838
  console.log(
@@ -47118,11 +47284,11 @@ async function cmdUse(args2) {
47118
47284
  }
47119
47285
  async function cmdReview() {
47120
47286
  const paths = workspacePaths(ROOT);
47121
- if (!existsSync22(paths.reviewQueue)) {
47287
+ if (!existsSync23(paths.reviewQueue)) {
47122
47288
  console.log("(review queue empty)");
47123
47289
  return;
47124
47290
  }
47125
- const queue = JSON.parse(readFileSync20(paths.reviewQueue, "utf8"));
47291
+ const queue = JSON.parse(readFileSync21(paths.reviewQueue, "utf8"));
47126
47292
  if (queue.length === 0) {
47127
47293
  console.log("(review queue empty)");
47128
47294
  return;
@@ -47776,7 +47942,7 @@ async function gatherRepo(store, ws) {
47776
47942
  };
47777
47943
  }
47778
47944
  async function gatherReportData(generatedAt) {
47779
- const { existsSync: existsSync23 } = await import("node:fs");
47945
+ const { existsSync: existsSync24 } = await import("node:fs");
47780
47946
  const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src4(), src_exports2));
47781
47947
  const cfg = loadConfig();
47782
47948
  const outbound = cfg.consent.sync ? "auto" : "off";
@@ -47784,7 +47950,7 @@ async function gatherReportData(generatedAt) {
47784
47950
  for (const ws of listWorkspaces()) {
47785
47951
  if (ws.missing) continue;
47786
47952
  const dbPath = workspacePaths(ws.path).castalia;
47787
- if (!existsSync23(dbPath)) continue;
47953
+ if (!existsSync24(dbPath)) continue;
47788
47954
  let store = null;
47789
47955
  try {
47790
47956
  store = openGraphStore2({ path: dbPath });
@@ -47815,7 +47981,7 @@ async function gatherReportData(generatedAt) {
47815
47981
  };
47816
47982
  }
47817
47983
  async function cmdReport(args2) {
47818
- const { mkdirSync: mkdirSync6, writeFileSync: writeFileSync16 } = await import("node:fs");
47984
+ const { mkdirSync: mkdirSync7, writeFileSync: writeFileSync17 } = await import("node:fs");
47819
47985
  const { renderReport: renderReport2 } = await Promise.resolve().then(() => (init_report_render(), report_render_exports));
47820
47986
  const includeFutureVerbs = args2.includes("--future-verbs");
47821
47987
  const now = /* @__PURE__ */ new Date();
@@ -47826,10 +47992,10 @@ async function cmdReport(args2) {
47826
47992
  process.exit(2);
47827
47993
  }
47828
47994
  const outDir = workspacePaths(ROOT).configDir;
47829
- mkdirSync6(outDir, { recursive: true });
47995
+ mkdirSync7(outDir, { recursive: true });
47830
47996
  const files = renderReport2(data, { includeFutureVerbs });
47831
- for (const f of files) writeFileSync16(join25(outDir, f.name), f.html, "utf8");
47832
- const indexPath = join25(outDir, "report.html");
47997
+ for (const f of files) writeFileSync17(join26(outDir, f.name), f.html, "utf8");
47998
+ const indexPath = join26(outDir, "report.html");
47833
47999
  console.log(`report \u2192 ${indexPath}`);
47834
48000
  console.log(` ${data.repos.length} repo(s) \xB7 ${files.length} file(s) \xB7 ${data.rollup.nodes.toLocaleString("en-US")} nodes`);
47835
48001
  console.log(` open: file://${indexPath.replace(/\\/g, "/")}`);
@@ -47949,15 +48115,15 @@ function hookRelayCommand(port, path2) {
47949
48115
  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 '{}'`;
47950
48116
  }
47951
48117
  async function installClaudeHooks(port) {
47952
- const { mkdirSync: mkdirSync6, existsSync: existsSync23, readFileSync: readFileSync21, writeFileSync: writeFileSync16 } = await import("node:fs");
47953
- const { join: join26 } = await import("node:path");
47954
- const dir = join26(ROOT, ".claude");
47955
- if (!existsSync23(dir)) mkdirSync6(dir, { recursive: true });
47956
- const file2 = join26(dir, "settings.json");
48118
+ const { mkdirSync: mkdirSync7, existsSync: existsSync24, readFileSync: readFileSync22, writeFileSync: writeFileSync17 } = await import("node:fs");
48119
+ const { join: join27 } = await import("node:path");
48120
+ const dir = join27(ROOT, ".claude");
48121
+ if (!existsSync24(dir)) mkdirSync7(dir, { recursive: true });
48122
+ const file2 = join27(dir, "settings.json");
47957
48123
  let settings = {};
47958
- if (existsSync23(file2)) {
48124
+ if (existsSync24(file2)) {
47959
48125
  try {
47960
- settings = JSON.parse(readFileSync21(file2, "utf8"));
48126
+ settings = JSON.parse(readFileSync22(file2, "utf8"));
47961
48127
  } catch {
47962
48128
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
47963
48129
  process.exit(2);
@@ -48003,10 +48169,10 @@ async function installClaudeHooks(port) {
48003
48169
  dropErrata(list);
48004
48170
  list.push({ hooks: [{ type: "command", command: injectCmd }] });
48005
48171
  }
48006
- writeFileSync16(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
48172
+ writeFileSync17(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
48007
48173
  console.log(`installed Claude Code hooks \u2192 ${file2}`);
48008
48174
  await installClaudeMcpConfig();
48009
- const claudeMd = join26(ROOT, "CLAUDE.md");
48175
+ const claudeMd = join27(ROOT, "CLAUDE.md");
48010
48176
  const recall = writeManagedBlock(claudeMd, { body: RECALL_FIRST_BLOCK });
48011
48177
  if (recall.kind === "collision") {
48012
48178
  console.warn(
@@ -48018,15 +48184,15 @@ async function installClaudeHooks(port) {
48018
48184
  console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
48019
48185
  }
48020
48186
  async function installClaudeMcpConfig() {
48021
- const { mkdirSync: mkdirSync6, existsSync: existsSync23, readFileSync: readFileSync21, writeFileSync: writeFileSync16 } = await import("node:fs");
48022
- const { join: join26, dirname: dirname9 } = await import("node:path");
48023
- const file2 = join26(ROOT, ".mcp.json");
48187
+ const { mkdirSync: mkdirSync7, existsSync: existsSync24, readFileSync: readFileSync22, writeFileSync: writeFileSync17 } = await import("node:fs");
48188
+ const { join: join27, dirname: dirname9 } = await import("node:path");
48189
+ const file2 = join27(ROOT, ".mcp.json");
48024
48190
  const dir = dirname9(file2);
48025
- if (!existsSync23(dir)) mkdirSync6(dir, { recursive: true });
48191
+ if (!existsSync24(dir)) mkdirSync7(dir, { recursive: true });
48026
48192
  let cfg = {};
48027
- if (existsSync23(file2)) {
48193
+ if (existsSync24(file2)) {
48028
48194
  try {
48029
- cfg = JSON.parse(readFileSync21(file2, "utf8"));
48195
+ cfg = JSON.parse(readFileSync22(file2, "utf8"));
48030
48196
  } catch {
48031
48197
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
48032
48198
  process.exit(2);
@@ -48034,21 +48200,21 @@ async function installClaudeMcpConfig() {
48034
48200
  }
48035
48201
  cfg.mcpServers ??= {};
48036
48202
  cfg.mcpServers["errata"] = errataMcpInvocation();
48037
- writeFileSync16(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
48203
+ writeFileSync17(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
48038
48204
  console.log(`installed Claude Code MCP server config \u2192 ${file2}`);
48039
48205
  console.log(` Claude Code will spawn \`errata mcp\` on workspace open.`);
48040
48206
  console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses / show / similar`);
48041
48207
  }
48042
48208
  async function installCursorMcpConfig() {
48043
- const { mkdirSync: mkdirSync6, existsSync: existsSync23, readFileSync: readFileSync21, writeFileSync: writeFileSync16 } = await import("node:fs");
48044
- const { join: join26 } = await import("node:path");
48045
- const dir = join26(ROOT, ".cursor");
48046
- if (!existsSync23(dir)) mkdirSync6(dir, { recursive: true });
48047
- const file2 = join26(dir, "mcp.json");
48209
+ const { mkdirSync: mkdirSync7, existsSync: existsSync24, readFileSync: readFileSync22, writeFileSync: writeFileSync17 } = await import("node:fs");
48210
+ const { join: join27 } = await import("node:path");
48211
+ const dir = join27(ROOT, ".cursor");
48212
+ if (!existsSync24(dir)) mkdirSync7(dir, { recursive: true });
48213
+ const file2 = join27(dir, "mcp.json");
48048
48214
  let cfg = {};
48049
- if (existsSync23(file2)) {
48215
+ if (existsSync24(file2)) {
48050
48216
  try {
48051
- cfg = JSON.parse(readFileSync21(file2, "utf8"));
48217
+ cfg = JSON.parse(readFileSync22(file2, "utf8"));
48052
48218
  } catch {
48053
48219
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
48054
48220
  process.exit(2);
@@ -48056,7 +48222,7 @@ async function installCursorMcpConfig() {
48056
48222
  }
48057
48223
  cfg.mcpServers ??= {};
48058
48224
  cfg.mcpServers["errata"] = errataMcpInvocation();
48059
- writeFileSync16(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
48225
+ writeFileSync17(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
48060
48226
  console.log(`installed Cursor MCP server config \u2192 ${file2}`);
48061
48227
  console.log(` Cursor will spawn \`errata mcp\` on workspace open.`);
48062
48228
  console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses`);
@@ -48064,16 +48230,16 @@ async function installCursorMcpConfig() {
48064
48230
  console.log(` \u26A0\uFE0F reload Cursor (Cmd/Ctrl-Shift-P \u2192 "Reload Window") to pick it up.`);
48065
48231
  }
48066
48232
  async function installCodexHooks(port) {
48067
- const { mkdirSync: mkdirSync6, existsSync: existsSync23, readFileSync: readFileSync21, writeFileSync: writeFileSync16 } = await import("node:fs");
48068
- const { join: join26 } = await import("node:path");
48069
- const dir = join26(ROOT, ".codex");
48070
- if (!existsSync23(dir)) mkdirSync6(dir, { recursive: true });
48071
- const file2 = join26(dir, "config.toml");
48233
+ const { mkdirSync: mkdirSync7, existsSync: existsSync24, readFileSync: readFileSync22, writeFileSync: writeFileSync17 } = await import("node:fs");
48234
+ const { join: join27 } = await import("node:path");
48235
+ const dir = join27(ROOT, ".codex");
48236
+ if (!existsSync24(dir)) mkdirSync7(dir, { recursive: true });
48237
+ const file2 = join27(dir, "config.toml");
48072
48238
  const BEGIN = `# >>> errata hooks (errata-managed)`;
48073
48239
  const END = `# <<< errata hooks`;
48074
48240
  let existing = "";
48075
- if (existsSync23(file2)) {
48076
- existing = readFileSync21(file2, "utf8");
48241
+ if (existsSync24(file2)) {
48242
+ existing = readFileSync22(file2, "utf8");
48077
48243
  const beginIdx = existing.indexOf(BEGIN);
48078
48244
  const endIdx = existing.indexOf(END);
48079
48245
  if (beginIdx >= 0 && endIdx > beginIdx) {
@@ -48102,7 +48268,7 @@ ${END}
48102
48268
  const final = existing.length > 0 && !existing.endsWith("\n") ? `${existing}
48103
48269
 
48104
48270
  ${block}` : existing + (existing.endsWith("\n\n") ? "" : "\n") + block;
48105
- writeFileSync16(file2, final, "utf8");
48271
+ writeFileSync17(file2, final, "utf8");
48106
48272
  console.log(`installed Codex hooks \u2192 ${file2}`);
48107
48273
  console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
48108
48274
  console.log("");
@@ -48365,7 +48531,7 @@ async function cmdDash(args2) {
48365
48531
  await yieldToLoop2();
48366
48532
  try {
48367
48533
  const items = selectDurableMemory(handle2.sharedStore, r.engine.profile);
48368
- const res = bleedRules(join25(r.root, ".claude", "rules"), items);
48534
+ const res = bleedRules(join26(r.root, ".claude", "rules"), items);
48369
48535
  if (res.written || res.pruned) {
48370
48536
  console.log(
48371
48537
  `[rules:${r.entry.name}] ${res.written} collective principle(s) \u2192 .claude/rules` + (res.pruned ? `, ${res.pruned} pruned` : "")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.0-dev.70",
3
+ "version": "2.0.0-dev.72",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
package/pass-worker.mjs CHANGED
@@ -25,7 +25,7 @@ function isTestRelPath(relPath) {
25
25
  function isTestScopeQname(qname) {
26
26
  return TEST_SCOPE_RE.test(qname);
27
27
  }
28
- var SEMANTIC_NODE_LABELS, CONTEXT_NODE_LABELS, CODE_NODE_LABELS, ALL_NODE_LABELS, STRUCTURAL_EDGES, CAUSAL_EDGES, RESOLUTION_EDGES, CONCEPTUAL_EDGES, EVIDENCE_EDGES, CODE_EDGES, BRIDGE_EDGES, IDENTITY_EDGES, JUSTIFICATION_EDGES, BELIEF_EDGES, ABSTRACTION_EDGES, DECOMPOSITION_EDGES, TRANSFER_EDGES, SOLUTION_STRUCTURE_EDGES, TAXONOMY_EDGES, TRIAGE_EDGES, GIT_EDGES, ALL_EDGE_TYPES, PAGERANK_EXCLUSIONS, EDGE_WEIGHT, CAUSAL_PROTECT_EDGES, VALIDATION_SOURCES, PROBLEM_RESOLUTION, DRIFT_KIND, TEST_PATH_RE, TEST_SCOPE_RE;
28
+ var SEMANTIC_NODE_LABELS, CONTEXT_NODE_LABELS, CODE_NODE_LABELS, ALL_NODE_LABELS, STRUCTURAL_EDGES, CAUSAL_EDGES, RESOLUTION_EDGES, CONCEPTUAL_EDGES, EVIDENCE_EDGES, CODE_EDGES, BRIDGE_EDGES, IDENTITY_EDGES, JUSTIFICATION_EDGES, BELIEF_EDGES, ABSTRACTION_EDGES, DECOMPOSITION_EDGES, TRANSFER_EDGES, SOLUTION_STRUCTURE_EDGES, SUSPICION_EDGES, TAXONOMY_EDGES, TRIAGE_EDGES, GIT_EDGES, ALL_EDGE_TYPES, PAGERANK_EXCLUSIONS, EDGE_WEIGHT, CAUSAL_PROTECT_EDGES, VALIDATION_SOURCES, PROBLEM_RESOLUTION, DRIFT_KIND, TEST_PATH_RE, TEST_SCOPE_RE;
29
29
  var init_castalia = __esm({
30
30
  "../../packages/shared/src/castalia.ts"() {
31
31
  "use strict";
@@ -184,6 +184,7 @@ var init_castalia = __esm({
184
184
  DECOMPOSITION_EDGES = ["SPLIT_INTO"];
185
185
  TRANSFER_EDGES = ["MAY_RESOLVE"];
186
186
  SOLUTION_STRUCTURE_EDGES = ["BUILDS_ON", "SUPERSEDES", "ALTERNATIVE_TO"];
187
+ SUSPICION_EDGES = ["SUSPECTED_LINK"];
187
188
  TAXONOMY_EDGES = ["IS_A"];
188
189
  TRIAGE_EDGES = ["TRIAGED_BY", "CONFIRMS", "INDICATES", "ROUTES_TO"];
189
190
  GIT_EDGES = ["POINTS_AT", "PARENT", "AUTHORED_BY"];
@@ -192,6 +193,7 @@ var init_castalia = __esm({
192
193
  ...CAUSAL_EDGES,
193
194
  ...RESOLUTION_EDGES,
194
195
  ...SOLUTION_STRUCTURE_EDGES,
196
+ ...SUSPICION_EDGES,
195
197
  ...CONCEPTUAL_EDGES,
196
198
  ...EVIDENCE_EDGES,
197
199
  ...CODE_EDGES,
@@ -240,9 +242,11 @@ var init_castalia = __esm({
240
242
  // agent attribution (Agent → knowledge), not signal-flow
241
243
  "SUPERSEDES",
242
244
  // "prefer newer" gradient between solutions, not signal-flow
243
- "ALTERNATIVE_TO"
245
+ "ALTERNATIVE_TO",
244
246
  // symmetric peer marker — weight would let alternatives inflate each other
245
247
  // NB: BUILDS_ON is NOT excluded — it flows extension→base so foundational solutions rank up.
248
+ "SUSPECTED_LINK"
249
+ // Somnus hypothesis (PLAN_SOMNUS_V2 §4) — never flows rank; navigation-invisible.
246
250
  ]);
247
251
  EDGE_WEIGHT = {
248
252
  // Causal — high signal
@@ -346,6 +350,8 @@ var init_castalia = __esm({
346
350
  BUILDS_ON: 0.4,
347
351
  SUPERSEDES: 0,
348
352
  ALTERNATIVE_TO: 0,
353
+ // Suspicion — a hypothesis, weightless + PageRank-excluded (never flows rank / EIG).
354
+ SUSPECTED_LINK: 0,
349
355
  // Git — topology/authorship, weightless (not domain signal-flow)
350
356
  POINTS_AT: 0,
351
357
  PARENT: 0,