@inerrata-corporation/errata 2.0.0-dev.71 → 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.
- package/errata.mjs +289 -130
- package/package.json +1 -1
package/errata.mjs
CHANGED
|
@@ -20362,13 +20362,8 @@ function renderSnapshot(s) {
|
|
|
20362
20362
|
if (s.skills.length > 0) {
|
|
20363
20363
|
lines.push("### Skills available");
|
|
20364
20364
|
lines.push(
|
|
20365
|
-
`${s.skills.length} induced skill${s.skills.length === 1 ? "" : "s"} for this workspace.
|
|
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\`.`
|
|
20366
20366
|
);
|
|
20367
|
-
for (const sk of [...s.skills].sort((a, b) => b.confidence - a.confidence).slice(0, 10)) {
|
|
20368
|
-
lines.push(
|
|
20369
|
-
`- **${sk.title}** (${sk.layer}, ${(sk.confidence * 100).toFixed(0)}%) \u2192 \`.errata/${sk.file}\``
|
|
20370
|
-
);
|
|
20371
|
-
}
|
|
20372
20367
|
lines.push("");
|
|
20373
20368
|
}
|
|
20374
20369
|
lines.push("### Prior knowledge sampled from the shared graph");
|
|
@@ -38554,12 +38549,12 @@ var init_report_render = __esm({
|
|
|
38554
38549
|
|
|
38555
38550
|
// src/cli.ts
|
|
38556
38551
|
init_src5();
|
|
38557
|
-
import { closeSync as closeSync2, existsSync as
|
|
38558
|
-
import { join as
|
|
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";
|
|
38559
38554
|
import { spawn as spawn3 } from "node:child_process";
|
|
38560
38555
|
|
|
38561
38556
|
// src/daemon.ts
|
|
38562
|
-
import { existsSync as
|
|
38557
|
+
import { existsSync as existsSync18, writeFileSync as writeFileSync14 } from "node:fs";
|
|
38563
38558
|
|
|
38564
38559
|
// ../../node_modules/.pnpm/@hono+node-server@1.19.11_hono@4.12.8/node_modules/@hono/node-server/dist/index.mjs
|
|
38565
38560
|
import { createServer as createServerHTTP } from "http";
|
|
@@ -39139,8 +39134,8 @@ init_config();
|
|
|
39139
39134
|
|
|
39140
39135
|
// src/engine.ts
|
|
39141
39136
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
39142
|
-
import { existsSync as
|
|
39143
|
-
import { join as
|
|
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";
|
|
39144
39139
|
|
|
39145
39140
|
// ../../node_modules/.pnpm/chokidar@4.0.3/node_modules/chokidar/esm/index.js
|
|
39146
39141
|
import { stat as statcb } from "fs";
|
|
@@ -42627,6 +42622,164 @@ async function syncSkills(paths, client, seed, pins = []) {
|
|
|
42627
42622
|
return { written: rows.length, pruned, ...staleDaemon ? { staleDaemon } : {} };
|
|
42628
42623
|
}
|
|
42629
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
|
+
|
|
42630
42783
|
// src/working-file-state.ts
|
|
42631
42784
|
function createWorkingFileState() {
|
|
42632
42785
|
const bySession = /* @__PURE__ */ new Map();
|
|
@@ -42756,20 +42909,20 @@ var CausalBuffer = class {
|
|
|
42756
42909
|
// src/profile.ts
|
|
42757
42910
|
init_src2();
|
|
42758
42911
|
init_paths();
|
|
42759
|
-
import { existsSync as
|
|
42912
|
+
import { existsSync as existsSync16, readFileSync as readFileSync15, writeFileSync as writeFileSync12 } from "node:fs";
|
|
42760
42913
|
import { createHash as createHash12 } from "node:crypto";
|
|
42761
|
-
import { join as
|
|
42914
|
+
import { join as join21 } from "node:path";
|
|
42762
42915
|
|
|
42763
42916
|
// src/git-remote.ts
|
|
42764
42917
|
init_src();
|
|
42765
|
-
import { existsSync as
|
|
42766
|
-
import { isAbsolute as isAbsolute3, join as
|
|
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";
|
|
42767
42920
|
function resolveGitDir(root) {
|
|
42768
|
-
const dotGit =
|
|
42921
|
+
const dotGit = join20(root, ".git");
|
|
42769
42922
|
try {
|
|
42770
42923
|
const st = statSync4(dotGit);
|
|
42771
42924
|
if (st.isDirectory()) return dotGit;
|
|
42772
|
-
const m = /^gitdir:\s*(.+?)\s*$/m.exec(
|
|
42925
|
+
const m = /^gitdir:\s*(.+?)\s*$/m.exec(readFileSync14(dotGit, "utf8"));
|
|
42773
42926
|
if (!m) return null;
|
|
42774
42927
|
const dir = m[1];
|
|
42775
42928
|
return isAbsolute3(dir) ? dir : resolve5(root, dir);
|
|
@@ -42778,22 +42931,22 @@ function resolveGitDir(root) {
|
|
|
42778
42931
|
}
|
|
42779
42932
|
}
|
|
42780
42933
|
function gitConfigPath(gitDir) {
|
|
42781
|
-
const commondirFile =
|
|
42782
|
-
if (
|
|
42783
|
-
const common =
|
|
42934
|
+
const commondirFile = join20(gitDir, "commondir");
|
|
42935
|
+
if (existsSync15(commondirFile)) {
|
|
42936
|
+
const common = readFileSync14(commondirFile, "utf8").trim();
|
|
42784
42937
|
const commonDir = isAbsolute3(common) ? common : resolve5(gitDir, common);
|
|
42785
|
-
return
|
|
42938
|
+
return join20(commonDir, "config");
|
|
42786
42939
|
}
|
|
42787
|
-
return
|
|
42940
|
+
return join20(gitDir, "config");
|
|
42788
42941
|
}
|
|
42789
42942
|
function readRemotes(root) {
|
|
42790
42943
|
const gitDir = resolveGitDir(root);
|
|
42791
42944
|
if (!gitDir) return [];
|
|
42792
42945
|
const cfgPath = gitConfigPath(gitDir);
|
|
42793
|
-
if (!
|
|
42946
|
+
if (!existsSync15(cfgPath)) return [];
|
|
42794
42947
|
let txt;
|
|
42795
42948
|
try {
|
|
42796
|
-
txt =
|
|
42949
|
+
txt = readFileSync14(cfgPath, "utf8");
|
|
42797
42950
|
} catch {
|
|
42798
42951
|
return [];
|
|
42799
42952
|
}
|
|
@@ -42825,13 +42978,13 @@ function refreshRepoLocator(root, profile) {
|
|
|
42825
42978
|
}
|
|
42826
42979
|
function loadProfile(root) {
|
|
42827
42980
|
const p = workspacePaths(root);
|
|
42828
|
-
if (!
|
|
42829
|
-
return JSON.parse(
|
|
42981
|
+
if (!existsSync16(p.workspaceJson)) return null;
|
|
42982
|
+
return JSON.parse(readFileSync15(p.workspaceJson, "utf8"));
|
|
42830
42983
|
}
|
|
42831
42984
|
function saveProfile(root, profile) {
|
|
42832
42985
|
const p = workspacePaths(root);
|
|
42833
42986
|
ensureDir(p.configDir);
|
|
42834
|
-
|
|
42987
|
+
writeFileSync12(p.workspaceJson, JSON.stringify(profile, null, 2), "utf8");
|
|
42835
42988
|
}
|
|
42836
42989
|
function autodetectProfile(root) {
|
|
42837
42990
|
const id = workspaceId(root);
|
|
@@ -42839,10 +42992,10 @@ function autodetectProfile(root) {
|
|
|
42839
42992
|
const p = emptyProfile(id, name2);
|
|
42840
42993
|
const locator = detectRepoLocator(root);
|
|
42841
42994
|
if (locator) p.repoLocator = locator;
|
|
42842
|
-
const pkgPath =
|
|
42843
|
-
if (
|
|
42995
|
+
const pkgPath = join21(root, "package.json");
|
|
42996
|
+
if (existsSync16(pkgPath)) {
|
|
42844
42997
|
try {
|
|
42845
|
-
const pkg = JSON.parse(
|
|
42998
|
+
const pkg = JSON.parse(readFileSync15(pkgPath, "utf8"));
|
|
42846
42999
|
p.languages.push("typescript", "javascript");
|
|
42847
43000
|
const nodeVer = pkg.engines?.node ?? "node";
|
|
42848
43001
|
p.stack.push(`node@${nodeVer}`);
|
|
@@ -42863,10 +43016,10 @@ function autodetectProfile(root) {
|
|
|
42863
43016
|
} catch {
|
|
42864
43017
|
}
|
|
42865
43018
|
}
|
|
42866
|
-
const pyproject =
|
|
42867
|
-
if (
|
|
43019
|
+
const pyproject = join21(root, "pyproject.toml");
|
|
43020
|
+
if (existsSync16(pyproject)) {
|
|
42868
43021
|
try {
|
|
42869
|
-
const txt =
|
|
43022
|
+
const txt = readFileSync15(pyproject, "utf8");
|
|
42870
43023
|
const py = /python\s*=\s*"([^"]+)"/.exec(txt)?.[1];
|
|
42871
43024
|
p.languages.push("python");
|
|
42872
43025
|
p.stack.push(`python@${py ?? "3"}`);
|
|
@@ -42877,16 +43030,16 @@ function autodetectProfile(root) {
|
|
|
42877
43030
|
} catch {
|
|
42878
43031
|
}
|
|
42879
43032
|
}
|
|
42880
|
-
const reqs =
|
|
42881
|
-
if (
|
|
43033
|
+
const reqs = join21(root, "requirements.txt");
|
|
43034
|
+
if (existsSync16(reqs)) {
|
|
42882
43035
|
if (!p.languages.includes("python")) p.languages.push("python");
|
|
42883
43036
|
if (!p.stack.includes("python@3")) p.stack.push("python@3");
|
|
42884
43037
|
}
|
|
42885
|
-
if (
|
|
43038
|
+
if (existsSync16(join21(root, "go.mod"))) {
|
|
42886
43039
|
p.languages.push("go");
|
|
42887
43040
|
p.stack.push("go");
|
|
42888
43041
|
}
|
|
42889
|
-
if (
|
|
43042
|
+
if (existsSync16(join21(root, "Cargo.toml"))) {
|
|
42890
43043
|
p.languages.push("rust");
|
|
42891
43044
|
p.stack.push("rust");
|
|
42892
43045
|
}
|
|
@@ -43044,7 +43197,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
|
|
|
43044
43197
|
}
|
|
43045
43198
|
|
|
43046
43199
|
// src/engine.ts
|
|
43047
|
-
var DAEMON_VERSION = true ? "2.0.0-dev.
|
|
43200
|
+
var DAEMON_VERSION = true ? "2.0.0-dev.72" : "2.0.0-alpha.0";
|
|
43048
43201
|
var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
|
|
43049
43202
|
var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
|
|
43050
43203
|
var GIT_OP_MUTE_MS = 4e3;
|
|
@@ -43054,7 +43207,7 @@ var TURN_REPLAY_LOOKBACK_MS = 7 * 24 * 60 * 6e4;
|
|
|
43054
43207
|
function appendIdentityAudit(path2, record2, line) {
|
|
43055
43208
|
if (!record2.accepted && record2.score <= 0) return;
|
|
43056
43209
|
try {
|
|
43057
|
-
if (
|
|
43210
|
+
if (existsSync17(path2) && statSync5(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
|
|
43058
43211
|
renameSync2(path2, `${path2}.1`);
|
|
43059
43212
|
}
|
|
43060
43213
|
appendFileSync2(path2, line);
|
|
@@ -43064,14 +43217,14 @@ function appendIdentityAudit(path2, record2, line) {
|
|
|
43064
43217
|
var yieldToLoop = () => new Promise((r) => setImmediate(r));
|
|
43065
43218
|
function loadTurnCursors(path2) {
|
|
43066
43219
|
try {
|
|
43067
|
-
return new Map(Object.entries(JSON.parse(
|
|
43220
|
+
return new Map(Object.entries(JSON.parse(readFileSync16(path2, "utf8"))));
|
|
43068
43221
|
} catch {
|
|
43069
43222
|
return /* @__PURE__ */ new Map();
|
|
43070
43223
|
}
|
|
43071
43224
|
}
|
|
43072
43225
|
function saveTurnCursors(path2, cursors) {
|
|
43073
43226
|
try {
|
|
43074
|
-
|
|
43227
|
+
writeFileSync13(path2, JSON.stringify(Object.fromEntries(cursors)), "utf8");
|
|
43075
43228
|
} catch {
|
|
43076
43229
|
}
|
|
43077
43230
|
}
|
|
@@ -43093,7 +43246,7 @@ function gitSourceWatchTargets(root) {
|
|
|
43093
43246
|
["-C", root, "ls-files", "--others", "--ignored", "--exclude-standard", "--directory", "-z"],
|
|
43094
43247
|
{ encoding: "utf8", maxBuffer: 256 * 1024 * 1024, windowsHide: true, stdio: ["ignore", "pipe", "ignore"] }
|
|
43095
43248
|
);
|
|
43096
|
-
ignoredDirs = igOut.split("\0").filter(Boolean).map((d) => d.replace(/\/+$/, "")).filter((d) => !IGNORED_PATH.test(
|
|
43249
|
+
ignoredDirs = igOut.split("\0").filter(Boolean).map((d) => d.replace(/\/+$/, "")).filter((d) => !IGNORED_PATH.test(join22(root, d) + sep4));
|
|
43097
43250
|
} catch {
|
|
43098
43251
|
}
|
|
43099
43252
|
const hasIgnoredChild = (dir) => ignoredDirs.some((ig) => ig.startsWith(dir + "/"));
|
|
@@ -43105,19 +43258,19 @@ function gitSourceWatchTargets(root) {
|
|
|
43105
43258
|
if (!f.startsWith(prefix)) continue;
|
|
43106
43259
|
const rest2 = f.slice(prefix.length);
|
|
43107
43260
|
if (rest2.includes("/")) children.add(dir === "" ? rest2.slice(0, rest2.indexOf("/")) : dir + "/" + rest2.slice(0, rest2.indexOf("/")));
|
|
43108
|
-
else targets.add(
|
|
43261
|
+
else targets.add(join22(root, f));
|
|
43109
43262
|
}
|
|
43110
43263
|
for (const c of children) {
|
|
43111
|
-
if (IGNORED_PATH.test(
|
|
43264
|
+
if (IGNORED_PATH.test(join22(root, c) + sep4)) continue;
|
|
43112
43265
|
if (hasIgnoredChild(c)) addUnder(c);
|
|
43113
|
-
else targets.add(
|
|
43266
|
+
else targets.add(join22(root, c));
|
|
43114
43267
|
}
|
|
43115
43268
|
};
|
|
43116
43269
|
addUnder("");
|
|
43117
43270
|
if (targets.size > 0) return [...targets];
|
|
43118
43271
|
} catch {
|
|
43119
43272
|
}
|
|
43120
|
-
return
|
|
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)));
|
|
43121
43274
|
}
|
|
43122
43275
|
function createWorkspaceEngine(opts) {
|
|
43123
43276
|
const paths = workspacePaths(opts.workspaceRoot);
|
|
@@ -43271,7 +43424,7 @@ function createWorkspaceEngine(opts) {
|
|
|
43271
43424
|
const srcPaths = diff.changedPaths.filter((p) => /\.(ts|tsx|js|jsx|mjs|cjs|py)$/i.test(p));
|
|
43272
43425
|
let episodeId2;
|
|
43273
43426
|
if (srcPaths.length > 0) {
|
|
43274
|
-
const abs = srcPaths.map((p) =>
|
|
43427
|
+
const abs = srcPaths.map((p) => join22(opts.workspaceRoot, p));
|
|
43275
43428
|
try {
|
|
43276
43429
|
const r = await runReindexPass(
|
|
43277
43430
|
`git-reindex:${profile.name} (${abs.length} files)`,
|
|
@@ -43307,8 +43460,8 @@ function createWorkspaceEngine(opts) {
|
|
|
43307
43460
|
`[errata] git: ${ev.kind} ${ev.newSha.slice(0, 7)} by ${meta3.authorName} \u2014 ${diff.changedPaths.length} file(s), ${diff.renames.length} rename(s)`
|
|
43308
43461
|
);
|
|
43309
43462
|
};
|
|
43310
|
-
const gitDir =
|
|
43311
|
-
if (
|
|
43463
|
+
const gitDir = join22(opts.workspaceRoot, ".git");
|
|
43464
|
+
if (existsSync17(gitDir)) {
|
|
43312
43465
|
stopGit = startGitSensor(gitDir, (ev) => {
|
|
43313
43466
|
void handleGitEvent(ev).catch((err2) => {
|
|
43314
43467
|
console.warn("[errata] git event handler failed:", err2);
|
|
@@ -43376,10 +43529,10 @@ function createWorkspaceEngine(opts) {
|
|
|
43376
43529
|
...pendingUpdate ? { pendingUpdate } : {}
|
|
43377
43530
|
});
|
|
43378
43531
|
doneRender?.();
|
|
43379
|
-
const target =
|
|
43532
|
+
const target = join22(opts.workspaceRoot, "AGENTS.md");
|
|
43380
43533
|
writeManagedBlock(target, { body: body2 });
|
|
43381
43534
|
if (elicit) {
|
|
43382
|
-
writePrimingHandles(
|
|
43535
|
+
writePrimingHandles(join22(paths.configDir, "priming-handles.json"), [
|
|
43383
43536
|
...snapshot.recentProblems.map((r) => r.node),
|
|
43384
43537
|
// Resolved-band handles: the ✓ problem AND its Solution are citable
|
|
43385
43538
|
// (a fix tag on an already-resolved problem no-ops idempotently; the
|
|
@@ -43549,7 +43702,7 @@ function createWorkspaceEngine(opts) {
|
|
|
43549
43702
|
resultSummary: { exitCode: e.exitCode ?? 1, errorTokens: e.errorTokens }
|
|
43550
43703
|
});
|
|
43551
43704
|
};
|
|
43552
|
-
const turnCursorPath =
|
|
43705
|
+
const turnCursorPath = join22(paths.configDir, "turn-cursors.json");
|
|
43553
43706
|
const lastTurnUuid = loadTurnCursors(turnCursorPath);
|
|
43554
43707
|
const sessionLastProblem = /* @__PURE__ */ new Map();
|
|
43555
43708
|
const sessionThreads = /* @__PURE__ */ new Map();
|
|
@@ -43572,7 +43725,7 @@ function createWorkspaceEngine(opts) {
|
|
|
43572
43725
|
const t = Date.now();
|
|
43573
43726
|
let processedTurns = 0;
|
|
43574
43727
|
const elicit = isEdgeElicitationEnabled();
|
|
43575
|
-
const handleMap = elicit ? readPrimingHandles(
|
|
43728
|
+
const handleMap = elicit ? readPrimingHandles(join22(paths.configDir, "priming-handles.json")) : {};
|
|
43576
43729
|
const wsRoot = (opts.workspaceRoot ?? "").replace(/\\/g, "/");
|
|
43577
43730
|
const toRel = (abs) => {
|
|
43578
43731
|
const p = abs.replace(/\\/g, "/");
|
|
@@ -44049,7 +44202,13 @@ function createWorkspaceEngine(opts) {
|
|
|
44049
44202
|
return typeof cloudId === "string" && cloudId !== p.id ? [p.id, cloudId] : [p.id];
|
|
44050
44203
|
});
|
|
44051
44204
|
const pins = profile?.projectId ? await cloud.getSkillPins(profile.projectId).then((r) => r.pins).catch(() => []) : [];
|
|
44052
|
-
|
|
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;
|
|
44053
44212
|
};
|
|
44054
44213
|
return {
|
|
44055
44214
|
profile,
|
|
@@ -44231,7 +44390,7 @@ function createWorkspaceEngine(opts) {
|
|
|
44231
44390
|
console.log(
|
|
44232
44391
|
"[errata] sync skipped \u2014 cloud sync consent is off (enable with `errata consent sync on`)"
|
|
44233
44392
|
);
|
|
44234
|
-
const pending =
|
|
44393
|
+
const pending = existsSync17(paths.outbox) ? readdirSync8(paths.outbox).filter((f) => f.endsWith(".json")).length : 0;
|
|
44235
44394
|
return { uploaded: 0, failed: 0, remaining: pending };
|
|
44236
44395
|
}
|
|
44237
44396
|
try {
|
|
@@ -44318,7 +44477,7 @@ async function startDaemon(opts) {
|
|
|
44318
44477
|
reviewUrl: () => webUiUrl + "/review"
|
|
44319
44478
|
});
|
|
44320
44479
|
const writeLockFile = (url2) => {
|
|
44321
|
-
|
|
44480
|
+
writeFileSync14(
|
|
44322
44481
|
engine.paths.daemonLock,
|
|
44323
44482
|
JSON.stringify({ pid: process.pid, webUiUrl: url2, startedAt: Date.now() }),
|
|
44324
44483
|
"utf8"
|
|
@@ -44361,7 +44520,7 @@ async function startDaemon(opts) {
|
|
|
44361
44520
|
);
|
|
44362
44521
|
await engine.stop();
|
|
44363
44522
|
try {
|
|
44364
|
-
if (
|
|
44523
|
+
if (existsSync18(engine.paths.daemonLock)) {
|
|
44365
44524
|
}
|
|
44366
44525
|
} catch {
|
|
44367
44526
|
}
|
|
@@ -44378,16 +44537,16 @@ async function listenServer(fetchFn, port) {
|
|
|
44378
44537
|
|
|
44379
44538
|
// src/registry.ts
|
|
44380
44539
|
init_paths();
|
|
44381
|
-
import { existsSync as
|
|
44382
|
-
import { join as
|
|
44540
|
+
import { existsSync as existsSync19, readFileSync as readFileSync17, writeFileSync as writeFileSync15 } from "node:fs";
|
|
44541
|
+
import { join as join23 } from "node:path";
|
|
44383
44542
|
function registryPath() {
|
|
44384
|
-
return process.env["ERRATA_REGISTRY_PATH"] ??
|
|
44543
|
+
return process.env["ERRATA_REGISTRY_PATH"] ?? join23(globalDir(), "workspaces.json");
|
|
44385
44544
|
}
|
|
44386
44545
|
function read() {
|
|
44387
44546
|
const p = registryPath();
|
|
44388
|
-
if (!
|
|
44547
|
+
if (!existsSync19(p)) return { version: 1, workspaces: {} };
|
|
44389
44548
|
try {
|
|
44390
|
-
const parsed = JSON.parse(
|
|
44549
|
+
const parsed = JSON.parse(readFileSync17(p, "utf8"));
|
|
44391
44550
|
return { version: 1, workspaces: parsed.workspaces ?? {} };
|
|
44392
44551
|
} catch {
|
|
44393
44552
|
return { version: 1, workspaces: {} };
|
|
@@ -44395,7 +44554,7 @@ function read() {
|
|
|
44395
44554
|
}
|
|
44396
44555
|
function write(reg) {
|
|
44397
44556
|
ensureDir(globalDir());
|
|
44398
|
-
|
|
44557
|
+
writeFileSync15(registryPath(), JSON.stringify(reg, null, 2), "utf8");
|
|
44399
44558
|
}
|
|
44400
44559
|
function registerWorkspace(profile, root, now = Date.now()) {
|
|
44401
44560
|
const reg = read();
|
|
@@ -44412,7 +44571,7 @@ function pruneMissingWorkspaces() {
|
|
|
44412
44571
|
const reg = read();
|
|
44413
44572
|
const removed = [];
|
|
44414
44573
|
for (const [id, entry] of Object.entries(reg.workspaces)) {
|
|
44415
|
-
if (!
|
|
44574
|
+
if (!existsSync19(entry.path)) {
|
|
44416
44575
|
removed.push(entry);
|
|
44417
44576
|
delete reg.workspaces[id];
|
|
44418
44577
|
}
|
|
@@ -44421,13 +44580,13 @@ function pruneMissingWorkspaces() {
|
|
|
44421
44580
|
return removed;
|
|
44422
44581
|
}
|
|
44423
44582
|
function workspaceStatus(entry) {
|
|
44424
|
-
const missing = !
|
|
44583
|
+
const missing = !existsSync19(entry.path);
|
|
44425
44584
|
const lockPath = workspacePaths(entry.path).daemonLock;
|
|
44426
44585
|
let running = false;
|
|
44427
44586
|
let webUiUrl = null;
|
|
44428
|
-
if (
|
|
44587
|
+
if (existsSync19(lockPath)) {
|
|
44429
44588
|
try {
|
|
44430
|
-
const lock = JSON.parse(
|
|
44589
|
+
const lock = JSON.parse(readFileSync17(lockPath, "utf8"));
|
|
44431
44590
|
if (lock.pid && lock.webUiUrl && pidAlive(lock.pid)) {
|
|
44432
44591
|
running = true;
|
|
44433
44592
|
webUiUrl = lock.webUiUrl;
|
|
@@ -44455,7 +44614,7 @@ function pidAlive(pid) {
|
|
|
44455
44614
|
// src/multi.ts
|
|
44456
44615
|
init_dist();
|
|
44457
44616
|
init_src4();
|
|
44458
|
-
import { readFileSync as
|
|
44617
|
+
import { readFileSync as readFileSync20, unlinkSync as unlinkSync3, writeFileSync as writeFileSync16 } from "node:fs";
|
|
44459
44618
|
|
|
44460
44619
|
// src/principle-sync.ts
|
|
44461
44620
|
init_src4();
|
|
@@ -44482,8 +44641,8 @@ async function syncPrinciples(store, cloud, opts) {
|
|
|
44482
44641
|
init_reconcile();
|
|
44483
44642
|
|
|
44484
44643
|
// src/lockfile-auto.ts
|
|
44485
|
-
import { existsSync as
|
|
44486
|
-
import { join as
|
|
44644
|
+
import { existsSync as existsSync20, readFileSync as readFileSync18 } from "node:fs";
|
|
44645
|
+
import { join as join24 } from "node:path";
|
|
44487
44646
|
|
|
44488
44647
|
// src/package-index.ts
|
|
44489
44648
|
init_src();
|
|
@@ -44747,11 +44906,11 @@ function runLockfilePass(opts) {
|
|
|
44747
44906
|
{ file: "package-lock.json", parse: parsePackageLockJson }
|
|
44748
44907
|
];
|
|
44749
44908
|
for (const c of candidates) {
|
|
44750
|
-
const p =
|
|
44751
|
-
if (!
|
|
44909
|
+
const p = join24(opts.root, c.file);
|
|
44910
|
+
if (!existsSync20(p)) continue;
|
|
44752
44911
|
let sbom;
|
|
44753
44912
|
try {
|
|
44754
|
-
sbom = c.parse(
|
|
44913
|
+
sbom = c.parse(readFileSync18(p, "utf8"));
|
|
44755
44914
|
} catch {
|
|
44756
44915
|
continue;
|
|
44757
44916
|
}
|
|
@@ -45027,7 +45186,7 @@ var ConsolidateWorker = class {
|
|
|
45027
45186
|
init_paths();
|
|
45028
45187
|
|
|
45029
45188
|
// src/lock.ts
|
|
45030
|
-
import { existsSync as
|
|
45189
|
+
import { existsSync as existsSync21, readFileSync as readFileSync19 } from "node:fs";
|
|
45031
45190
|
function isProcessAlive(pid) {
|
|
45032
45191
|
if (!pid || pid <= 0) return false;
|
|
45033
45192
|
try {
|
|
@@ -45038,9 +45197,9 @@ function isProcessAlive(pid) {
|
|
|
45038
45197
|
}
|
|
45039
45198
|
}
|
|
45040
45199
|
function readDaemonLock(lockPath) {
|
|
45041
|
-
if (!
|
|
45200
|
+
if (!existsSync21(lockPath)) return null;
|
|
45042
45201
|
try {
|
|
45043
|
-
const lock = JSON.parse(
|
|
45202
|
+
const lock = JSON.parse(readFileSync19(lockPath, "utf8"));
|
|
45044
45203
|
return typeof lock.pid === "number" ? lock : null;
|
|
45045
45204
|
} catch {
|
|
45046
45205
|
return null;
|
|
@@ -45164,12 +45323,12 @@ async function ensureProjectLink(root, profile, client) {
|
|
|
45164
45323
|
}
|
|
45165
45324
|
|
|
45166
45325
|
// src/adopt.ts
|
|
45167
|
-
import { existsSync as
|
|
45168
|
-
import { dirname as dirname8, join as
|
|
45326
|
+
import { existsSync as existsSync22 } from "node:fs";
|
|
45327
|
+
import { dirname as dirname8, join as join25 } from "node:path";
|
|
45169
45328
|
function findGitRoot(absPath) {
|
|
45170
45329
|
let dir = absPath;
|
|
45171
45330
|
for (let depth = 0; depth < 64; depth++) {
|
|
45172
|
-
if (
|
|
45331
|
+
if (existsSync22(join25(dir, ".git"))) return dir;
|
|
45173
45332
|
const parent = dirname8(dir);
|
|
45174
45333
|
if (parent === dir) return null;
|
|
45175
45334
|
dir = parent;
|
|
@@ -45357,7 +45516,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
45357
45516
|
void ambientLinkAll();
|
|
45358
45517
|
app.route(`/ws/${rec.id}`, rec.webApp);
|
|
45359
45518
|
try {
|
|
45360
|
-
|
|
45519
|
+
writeFileSync16(
|
|
45361
45520
|
rec.engine.paths.daemonLock,
|
|
45362
45521
|
JSON.stringify({ pid: process.pid, webUiUrl: `${baseUrl}/ws/${rec.id}`, startedAt: Date.now() }),
|
|
45363
45522
|
"utf8"
|
|
@@ -45543,7 +45702,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
45543
45702
|
baseUrl = `http://127.0.0.1:${port}`;
|
|
45544
45703
|
try {
|
|
45545
45704
|
ensureDir(globalDir());
|
|
45546
|
-
|
|
45705
|
+
writeFileSync16(
|
|
45547
45706
|
lockPath,
|
|
45548
45707
|
JSON.stringify({ pid: process.pid, webUiUrl: baseUrl, startedAt: Date.now() }),
|
|
45549
45708
|
"utf8"
|
|
@@ -45552,7 +45711,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
45552
45711
|
}
|
|
45553
45712
|
for (const r of records) {
|
|
45554
45713
|
try {
|
|
45555
|
-
|
|
45714
|
+
writeFileSync16(
|
|
45556
45715
|
r.engine.paths.daemonLock,
|
|
45557
45716
|
JSON.stringify({ pid: process.pid, webUiUrl: `${baseUrl}/ws/${r.id}`, startedAt: Date.now() }),
|
|
45558
45717
|
"utf8"
|
|
@@ -45906,7 +46065,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
45906
46065
|
},
|
|
45907
46066
|
async stop() {
|
|
45908
46067
|
try {
|
|
45909
|
-
const cur =
|
|
46068
|
+
const cur = readFileSync20(lockPath, "utf8");
|
|
45910
46069
|
if (JSON.parse(cur).pid === process.pid) unlinkSync3(lockPath);
|
|
45911
46070
|
} catch {
|
|
45912
46071
|
}
|
|
@@ -46501,21 +46660,21 @@ async function cmdInit() {
|
|
|
46501
46660
|
if (!skipHooks) {
|
|
46502
46661
|
console.log("");
|
|
46503
46662
|
console.log("installing harness hooks...");
|
|
46504
|
-
const { existsSync:
|
|
46505
|
-
const { join:
|
|
46663
|
+
const { existsSync: existsSync24 } = await import("node:fs");
|
|
46664
|
+
const { join: join27 } = await import("node:path");
|
|
46506
46665
|
try {
|
|
46507
46666
|
await installClaudeHooks(port);
|
|
46508
46667
|
} catch (err2) {
|
|
46509
46668
|
console.warn(` \u26A0\uFE0F Claude hook install failed: ${err2 instanceof Error ? err2.message : err2}`);
|
|
46510
46669
|
}
|
|
46511
|
-
if (
|
|
46670
|
+
if (existsSync24(join27(ROOT, ".cursor"))) {
|
|
46512
46671
|
try {
|
|
46513
46672
|
await installCursorMcpConfig();
|
|
46514
46673
|
} catch (err2) {
|
|
46515
46674
|
console.warn(` \u26A0\uFE0F Cursor MCP config failed: ${err2 instanceof Error ? err2.message : err2}`);
|
|
46516
46675
|
}
|
|
46517
46676
|
}
|
|
46518
|
-
if (
|
|
46677
|
+
if (existsSync24(join27(ROOT, ".codex"))) {
|
|
46519
46678
|
try {
|
|
46520
46679
|
await installCodexHooks(port);
|
|
46521
46680
|
} catch (err2) {
|
|
@@ -46672,8 +46831,8 @@ async function cmdStatus() {
|
|
|
46672
46831
|
console.log(` stack: ${profile.stack.join(", ") || "(none)"}`);
|
|
46673
46832
|
console.log(` languages: ${profile.languages.join(", ") || "(none)"}`);
|
|
46674
46833
|
}
|
|
46675
|
-
console.log(` graph db: ${
|
|
46676
|
-
console.log(` event log: ${
|
|
46834
|
+
console.log(` graph db: ${existsSync23(paths.castalia) ? "yes" : "no"} (${paths.castalia})`);
|
|
46835
|
+
console.log(` event log: ${existsSync23(paths.eventLog) ? "yes" : "no"} (${paths.eventLog})`);
|
|
46677
46836
|
const lockPath = globalDaemonLock();
|
|
46678
46837
|
const running = isDaemonAlive(lockPath) ? readDaemonLock(lockPath) : null;
|
|
46679
46838
|
console.log(
|
|
@@ -47125,11 +47284,11 @@ async function cmdUse(args2) {
|
|
|
47125
47284
|
}
|
|
47126
47285
|
async function cmdReview() {
|
|
47127
47286
|
const paths = workspacePaths(ROOT);
|
|
47128
|
-
if (!
|
|
47287
|
+
if (!existsSync23(paths.reviewQueue)) {
|
|
47129
47288
|
console.log("(review queue empty)");
|
|
47130
47289
|
return;
|
|
47131
47290
|
}
|
|
47132
|
-
const queue = JSON.parse(
|
|
47291
|
+
const queue = JSON.parse(readFileSync21(paths.reviewQueue, "utf8"));
|
|
47133
47292
|
if (queue.length === 0) {
|
|
47134
47293
|
console.log("(review queue empty)");
|
|
47135
47294
|
return;
|
|
@@ -47783,7 +47942,7 @@ async function gatherRepo(store, ws) {
|
|
|
47783
47942
|
};
|
|
47784
47943
|
}
|
|
47785
47944
|
async function gatherReportData(generatedAt) {
|
|
47786
|
-
const { existsSync:
|
|
47945
|
+
const { existsSync: existsSync24 } = await import("node:fs");
|
|
47787
47946
|
const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src4(), src_exports2));
|
|
47788
47947
|
const cfg = loadConfig();
|
|
47789
47948
|
const outbound = cfg.consent.sync ? "auto" : "off";
|
|
@@ -47791,7 +47950,7 @@ async function gatherReportData(generatedAt) {
|
|
|
47791
47950
|
for (const ws of listWorkspaces()) {
|
|
47792
47951
|
if (ws.missing) continue;
|
|
47793
47952
|
const dbPath = workspacePaths(ws.path).castalia;
|
|
47794
|
-
if (!
|
|
47953
|
+
if (!existsSync24(dbPath)) continue;
|
|
47795
47954
|
let store = null;
|
|
47796
47955
|
try {
|
|
47797
47956
|
store = openGraphStore2({ path: dbPath });
|
|
@@ -47822,7 +47981,7 @@ async function gatherReportData(generatedAt) {
|
|
|
47822
47981
|
};
|
|
47823
47982
|
}
|
|
47824
47983
|
async function cmdReport(args2) {
|
|
47825
|
-
const { mkdirSync:
|
|
47984
|
+
const { mkdirSync: mkdirSync7, writeFileSync: writeFileSync17 } = await import("node:fs");
|
|
47826
47985
|
const { renderReport: renderReport2 } = await Promise.resolve().then(() => (init_report_render(), report_render_exports));
|
|
47827
47986
|
const includeFutureVerbs = args2.includes("--future-verbs");
|
|
47828
47987
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -47833,10 +47992,10 @@ async function cmdReport(args2) {
|
|
|
47833
47992
|
process.exit(2);
|
|
47834
47993
|
}
|
|
47835
47994
|
const outDir = workspacePaths(ROOT).configDir;
|
|
47836
|
-
|
|
47995
|
+
mkdirSync7(outDir, { recursive: true });
|
|
47837
47996
|
const files = renderReport2(data, { includeFutureVerbs });
|
|
47838
|
-
for (const f of files)
|
|
47839
|
-
const indexPath =
|
|
47997
|
+
for (const f of files) writeFileSync17(join26(outDir, f.name), f.html, "utf8");
|
|
47998
|
+
const indexPath = join26(outDir, "report.html");
|
|
47840
47999
|
console.log(`report \u2192 ${indexPath}`);
|
|
47841
48000
|
console.log(` ${data.repos.length} repo(s) \xB7 ${files.length} file(s) \xB7 ${data.rollup.nodes.toLocaleString("en-US")} nodes`);
|
|
47842
48001
|
console.log(` open: file://${indexPath.replace(/\\/g, "/")}`);
|
|
@@ -47956,15 +48115,15 @@ function hookRelayCommand(port, path2) {
|
|
|
47956
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 '{}'`;
|
|
47957
48116
|
}
|
|
47958
48117
|
async function installClaudeHooks(port) {
|
|
47959
|
-
const { mkdirSync:
|
|
47960
|
-
const { join:
|
|
47961
|
-
const dir =
|
|
47962
|
-
if (!
|
|
47963
|
-
const file2 =
|
|
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");
|
|
47964
48123
|
let settings = {};
|
|
47965
|
-
if (
|
|
48124
|
+
if (existsSync24(file2)) {
|
|
47966
48125
|
try {
|
|
47967
|
-
settings = JSON.parse(
|
|
48126
|
+
settings = JSON.parse(readFileSync22(file2, "utf8"));
|
|
47968
48127
|
} catch {
|
|
47969
48128
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
47970
48129
|
process.exit(2);
|
|
@@ -48010,10 +48169,10 @@ async function installClaudeHooks(port) {
|
|
|
48010
48169
|
dropErrata(list);
|
|
48011
48170
|
list.push({ hooks: [{ type: "command", command: injectCmd }] });
|
|
48012
48171
|
}
|
|
48013
|
-
|
|
48172
|
+
writeFileSync17(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
|
|
48014
48173
|
console.log(`installed Claude Code hooks \u2192 ${file2}`);
|
|
48015
48174
|
await installClaudeMcpConfig();
|
|
48016
|
-
const claudeMd =
|
|
48175
|
+
const claudeMd = join27(ROOT, "CLAUDE.md");
|
|
48017
48176
|
const recall = writeManagedBlock(claudeMd, { body: RECALL_FIRST_BLOCK });
|
|
48018
48177
|
if (recall.kind === "collision") {
|
|
48019
48178
|
console.warn(
|
|
@@ -48025,15 +48184,15 @@ async function installClaudeHooks(port) {
|
|
|
48025
48184
|
console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
|
|
48026
48185
|
}
|
|
48027
48186
|
async function installClaudeMcpConfig() {
|
|
48028
|
-
const { mkdirSync:
|
|
48029
|
-
const { join:
|
|
48030
|
-
const file2 =
|
|
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");
|
|
48031
48190
|
const dir = dirname9(file2);
|
|
48032
|
-
if (!
|
|
48191
|
+
if (!existsSync24(dir)) mkdirSync7(dir, { recursive: true });
|
|
48033
48192
|
let cfg = {};
|
|
48034
|
-
if (
|
|
48193
|
+
if (existsSync24(file2)) {
|
|
48035
48194
|
try {
|
|
48036
|
-
cfg = JSON.parse(
|
|
48195
|
+
cfg = JSON.parse(readFileSync22(file2, "utf8"));
|
|
48037
48196
|
} catch {
|
|
48038
48197
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
48039
48198
|
process.exit(2);
|
|
@@ -48041,21 +48200,21 @@ async function installClaudeMcpConfig() {
|
|
|
48041
48200
|
}
|
|
48042
48201
|
cfg.mcpServers ??= {};
|
|
48043
48202
|
cfg.mcpServers["errata"] = errataMcpInvocation();
|
|
48044
|
-
|
|
48203
|
+
writeFileSync17(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
|
|
48045
48204
|
console.log(`installed Claude Code MCP server config \u2192 ${file2}`);
|
|
48046
48205
|
console.log(` Claude Code will spawn \`errata mcp\` on workspace open.`);
|
|
48047
48206
|
console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses / show / similar`);
|
|
48048
48207
|
}
|
|
48049
48208
|
async function installCursorMcpConfig() {
|
|
48050
|
-
const { mkdirSync:
|
|
48051
|
-
const { join:
|
|
48052
|
-
const dir =
|
|
48053
|
-
if (!
|
|
48054
|
-
const file2 =
|
|
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");
|
|
48055
48214
|
let cfg = {};
|
|
48056
|
-
if (
|
|
48215
|
+
if (existsSync24(file2)) {
|
|
48057
48216
|
try {
|
|
48058
|
-
cfg = JSON.parse(
|
|
48217
|
+
cfg = JSON.parse(readFileSync22(file2, "utf8"));
|
|
48059
48218
|
} catch {
|
|
48060
48219
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
48061
48220
|
process.exit(2);
|
|
@@ -48063,7 +48222,7 @@ async function installCursorMcpConfig() {
|
|
|
48063
48222
|
}
|
|
48064
48223
|
cfg.mcpServers ??= {};
|
|
48065
48224
|
cfg.mcpServers["errata"] = errataMcpInvocation();
|
|
48066
|
-
|
|
48225
|
+
writeFileSync17(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
|
|
48067
48226
|
console.log(`installed Cursor MCP server config \u2192 ${file2}`);
|
|
48068
48227
|
console.log(` Cursor will spawn \`errata mcp\` on workspace open.`);
|
|
48069
48228
|
console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses`);
|
|
@@ -48071,16 +48230,16 @@ async function installCursorMcpConfig() {
|
|
|
48071
48230
|
console.log(` \u26A0\uFE0F reload Cursor (Cmd/Ctrl-Shift-P \u2192 "Reload Window") to pick it up.`);
|
|
48072
48231
|
}
|
|
48073
48232
|
async function installCodexHooks(port) {
|
|
48074
|
-
const { mkdirSync:
|
|
48075
|
-
const { join:
|
|
48076
|
-
const dir =
|
|
48077
|
-
if (!
|
|
48078
|
-
const file2 =
|
|
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");
|
|
48079
48238
|
const BEGIN = `# >>> errata hooks (errata-managed)`;
|
|
48080
48239
|
const END = `# <<< errata hooks`;
|
|
48081
48240
|
let existing = "";
|
|
48082
|
-
if (
|
|
48083
|
-
existing =
|
|
48241
|
+
if (existsSync24(file2)) {
|
|
48242
|
+
existing = readFileSync22(file2, "utf8");
|
|
48084
48243
|
const beginIdx = existing.indexOf(BEGIN);
|
|
48085
48244
|
const endIdx = existing.indexOf(END);
|
|
48086
48245
|
if (beginIdx >= 0 && endIdx > beginIdx) {
|
|
@@ -48109,7 +48268,7 @@ ${END}
|
|
|
48109
48268
|
const final = existing.length > 0 && !existing.endsWith("\n") ? `${existing}
|
|
48110
48269
|
|
|
48111
48270
|
${block}` : existing + (existing.endsWith("\n\n") ? "" : "\n") + block;
|
|
48112
|
-
|
|
48271
|
+
writeFileSync17(file2, final, "utf8");
|
|
48113
48272
|
console.log(`installed Codex hooks \u2192 ${file2}`);
|
|
48114
48273
|
console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
|
|
48115
48274
|
console.log("");
|
|
@@ -48372,7 +48531,7 @@ async function cmdDash(args2) {
|
|
|
48372
48531
|
await yieldToLoop2();
|
|
48373
48532
|
try {
|
|
48374
48533
|
const items = selectDurableMemory(handle2.sharedStore, r.engine.profile);
|
|
48375
|
-
const res = bleedRules(
|
|
48534
|
+
const res = bleedRules(join26(r.root, ".claude", "rules"), items);
|
|
48376
48535
|
if (res.written || res.pruned) {
|
|
48377
48536
|
console.log(
|
|
48378
48537
|
`[rules:${r.entry.name}] ${res.written} collective principle(s) \u2192 .claude/rules` + (res.pruned ? `, ${res.pruned} pruned` : "")
|