@inerrata-corporation/errata 2.0.2-dev.196 → 2.0.2-dev.204
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 +370 -187
- package/package.json +1 -1
- package/pass-worker.mjs +7 -4
package/errata.mjs
CHANGED
|
@@ -20982,10 +20982,13 @@ function buildSnapshot(opts) {
|
|
|
20982
20982
|
episodeId: episodeId2,
|
|
20983
20983
|
problems: problems2
|
|
20984
20984
|
}));
|
|
20985
|
-
const
|
|
20986
|
-
|
|
20987
|
-
|
|
20988
|
-
|
|
20985
|
+
const revisitSeen = /* @__PURE__ */ new Set();
|
|
20986
|
+
const needsRevisit = listNeedsRevisit(opts.store, (opts.now ?? /* @__PURE__ */ new Date()).getTime()).filter((r) => {
|
|
20987
|
+
const key = `${r.label}:${r.description.trim().toLowerCase()}`;
|
|
20988
|
+
if (revisitSeen.has(key)) return false;
|
|
20989
|
+
revisitSeen.add(key);
|
|
20990
|
+
return true;
|
|
20991
|
+
}).slice(0, 5);
|
|
20989
20992
|
const norm = (x) => x.toLowerCase().replace(/[^a-z0-9]+/g, "");
|
|
20990
20993
|
const pkgBase = (x) => {
|
|
20991
20994
|
const at = x.lastIndexOf("@");
|
|
@@ -21386,8 +21389,16 @@ ${RECALL_FIRST_BODY}`;
|
|
|
21386
21389
|
// A standing design tension outranks an enrichment nudge (it prevents a wrong
|
|
21387
21390
|
// decision) but yields to a live defect (which is actionable now).
|
|
21388
21391
|
"recentConstraints",
|
|
21389
|
-
|
|
21390
|
-
|
|
21392
|
+
// `needsRevisit` used to sit LAST — the most protected band in the block. That
|
|
21393
|
+
// inverted the block's whole purpose once the link-elicitation instruction (4,942
|
|
21394
|
+
// chars, 55% of the budget, non-evictable) started competing for room: the
|
|
21395
|
+
// budgeter drained all 8 Problems and all 4 Solutions and kept nine stale
|
|
21396
|
+
// auto-close notices, so the agent was handed an instruction to cite `[handles]`
|
|
21397
|
+
// with zero problem handles left to cite. A revisit flag is a maintenance nudge
|
|
21398
|
+
// about something ALREADY closed; a live prior is the substrate every link verb
|
|
21399
|
+
// needs. Problems outrank it now.
|
|
21400
|
+
"needsRevisit",
|
|
21401
|
+
"recentProblems"
|
|
21391
21402
|
];
|
|
21392
21403
|
DEFAULT_AGENT_CONTEXT_BUDGET = 9e3;
|
|
21393
21404
|
}
|
|
@@ -25259,15 +25270,15 @@ function triageBullet(ref) {
|
|
|
25259
25270
|
}
|
|
25260
25271
|
function linkBullet(ref) {
|
|
25261
25272
|
return [
|
|
25262
|
-
" \u2022
|
|
25273
|
+
" \u2022 you flagged a problem \u2014 LINK it, and do it ESPECIALLY when the finding feels novel.",
|
|
25274
|
+
" Work you just did feels specific to here; that feeling is why links go unwritten, and it is",
|
|
25275
|
+
" exactly backwards \u2014 a finding nobody can reach from anywhere else is one nobody reuses:",
|
|
25263
25276
|
` \xB7 (instance:[${ref}],[another-prior],\u2026) \u2014 the priors this problem is an instance of.`,
|
|
25264
25277
|
" Aim for ~3 DIFFERENT relevant priors; one link is weak, three triangulate it.",
|
|
25265
25278
|
` \xB7 ${TAG_EXAMPLE.pattern()} \u2014 name the general shape it instantiates (e.g. (pattern: unbounded`,
|
|
25266
25279
|
" queue growth under backpressure)) \u2014 this works with NO code anchor, and two agents naming",
|
|
25267
|
-
" the same pattern converge on one node.
|
|
25268
|
-
|
|
25269
|
-
" (domain: Community Detection)). An abstract problem with no code anchor NEEDS this or it's",
|
|
25270
|
-
" an invisible island: the Domain is the topic other problems in the area cluster on. Title Case.",
|
|
25280
|
+
" the same pattern converge on one node. Naming the shape costs your finding nothing and is",
|
|
25281
|
+
" what lets a stranger hit it. Cite a shown Pattern by handle: (pattern:[handle]).",
|
|
25271
25282
|
` \xB7 ${TAG_EXAMPLE.package()} \u2014 the PUBLIC PACKAGE the problem is about, even when this`,
|
|
25272
25283
|
" workspace doesn't depend on it (e.g. (package: chokidar), (package: pypi/requests)) \u2014 a",
|
|
25273
25284
|
" public-registry anchor lets the knowledge cross to the collective; internal names stay private.",
|
|
@@ -25291,9 +25302,9 @@ function attemptBullet() {
|
|
|
25291
25302
|
].join("\n");
|
|
25292
25303
|
}
|
|
25293
25304
|
function buildAgentInstruction(opts = {}) {
|
|
25294
|
-
const signals = opts.signals ?? ["prior", "problem", "fix", "constraint", "triage", "attempt", "link"];
|
|
25305
|
+
const signals = opts.signals ?? ["prior", "problem", "domain", "fix", "constraint", "triage", "attempt", "link"];
|
|
25295
25306
|
const ref = opts.referent ?? "its-handle";
|
|
25296
|
-
const token = (s) => s === "problem" ? TAG_EXAMPLE.problem() : s === "constraint" ? TAG_EXAMPLE.constraint() : s === "attempt" ? TAG_EXAMPLE.tried() : s === "link" ? TAG_EXAMPLE.pattern() : TAG_EXAMPLE[s](ref);
|
|
25307
|
+
const token = (s) => s === "problem" ? TAG_EXAMPLE.problem() : s === "constraint" ? TAG_EXAMPLE.constraint() : s === "attempt" ? TAG_EXAMPLE.tried() : s === "domain" ? TAG_EXAMPLE.domain() : s === "link" ? TAG_EXAMPLE.pattern() : TAG_EXAMPLE[s](ref);
|
|
25297
25308
|
const head2 = `We tag the priors we show you with a short handle like [${opts.handleExample ?? "chokidar-glob"}]. This is a capture protocol, not optional notes: what you DON'T tag is silently lost \u2014 the tag is the ONLY thing recorded. Whenever one of these is true, wrap it inline in your prose (no fences, no extra calls). Tag every one you state; we filter downstream, so don't self-censor or batch:`;
|
|
25298
25309
|
const tail = "Mid-turn text (between tool calls) can be dropped by the harness \u2014 if a tag above appeared only mid-turn, RESTATE it in your final message of the turn; the final message always survives.";
|
|
25299
25310
|
return [
|
|
@@ -25359,6 +25370,22 @@ var init_agent_signals = __esm({
|
|
|
25359
25370
|
constraint: "you made a design decision because requirements conflict or something's constrained \u2014 tag the tension, ESPECIALLY when your fix makes it 'only look' contradictory (a clean solution still hides a real trap the next agent needs)",
|
|
25360
25371
|
triage: "you diagnosed a bug \u2014 SPLIT the symptom (what breaks \u2192 [!\u2026]) from the cause (the mechanism you'd change \u2192 (cause:\u2026)); if the line says WHY it breaks, it's a cause, not a problem",
|
|
25361
25372
|
attempt: "you're attempting an approach, or an attempt didn't pan out \u2014 (tried: \u2026) / (failed: \u2026); a failed attempt rules out a path for the next agent",
|
|
25373
|
+
// DOMAIN — promoted to a FIRST-CLASS signal (was nested inside linkBullet, whose
|
|
25374
|
+
// lead-in gates on "a problem you flagged resembles prior knowledge"). Naming the
|
|
25375
|
+
// area a problem is about is unconditional and has nothing to do with recognizing
|
|
25376
|
+
// a prior, so that gate silently suppressed it: field census 2026-07-30 across 387
|
|
25377
|
+
// sessions — `domain` in 10/194 tag-emitting sessions (5%) against `problem` in
|
|
25378
|
+
// 124/194 (64%), and bimodal (the 10 that do emit average ~7 each), i.e. the
|
|
25379
|
+
// syntax is fine and the trigger was never reached.
|
|
25380
|
+
//
|
|
25381
|
+
// The gloss carries the anti-performance framing Cycles 9–11 proved is the actual
|
|
25382
|
+
// lever (the tag alone scored 0 = control; naming the bias and inverting it is
|
|
25383
|
+
// what lifted capture). The bias here is the mirror of the constraint one: an
|
|
25384
|
+
// agent that has just named a problem *precisely* feels the precision IS the
|
|
25385
|
+
// contribution, so stating the general area reads as vague restatement — exactly
|
|
25386
|
+
// when it matters most, because precise wording is what makes a problem
|
|
25387
|
+
// unfindable to anyone who doesn't already share it.
|
|
25388
|
+
domain: "you flagged a problem that isn't about one specific file \u2014 name the AREA it's about. Precision is not a substitute: the sharper your wording, the LESS anyone else will search for it, and an abstract problem with no area is an invisible island. Title Case",
|
|
25362
25389
|
link: "the problem you flagged is an instance of priors/abstractions you can name \u2014 (instance:[h1],[h2],\u2026) / (pattern: \u2026) / (aids:[h]); rendered whole via linkBullet"
|
|
25363
25390
|
};
|
|
25364
25391
|
}
|
|
@@ -47172,12 +47199,12 @@ var init_report_render = __esm({
|
|
|
47172
47199
|
|
|
47173
47200
|
// src/cli.ts
|
|
47174
47201
|
init_src5();
|
|
47175
|
-
import { closeSync as closeSync2, existsSync as
|
|
47176
|
-
import { join as
|
|
47202
|
+
import { closeSync as closeSync2, existsSync as existsSync25, openSync as openSync2, readFileSync as readFileSync23, renameSync as renameSync3, statSync as statSync6 } from "node:fs";
|
|
47203
|
+
import { join as join27 } from "node:path";
|
|
47177
47204
|
import { spawn as spawn3 } from "node:child_process";
|
|
47178
47205
|
|
|
47179
47206
|
// src/daemon.ts
|
|
47180
|
-
import { existsSync as
|
|
47207
|
+
import { existsSync as existsSync20, writeFileSync as writeFileSync16 } from "node:fs";
|
|
47181
47208
|
|
|
47182
47209
|
// ../../node_modules/.pnpm/@hono+node-server@1.19.11_hono@4.12.8/node_modules/@hono/node-server/dist/index.mjs
|
|
47183
47210
|
import { createServer as createServerHTTP } from "http";
|
|
@@ -47757,8 +47784,8 @@ init_config();
|
|
|
47757
47784
|
|
|
47758
47785
|
// src/engine.ts
|
|
47759
47786
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
47760
|
-
import { existsSync as
|
|
47761
|
-
import { join as
|
|
47787
|
+
import { existsSync as existsSync19, statSync as statSync5, appendFileSync as appendFileSync2, readdirSync as readdirSync9, renameSync as renameSync2, readFileSync as readFileSync18, writeFileSync as writeFileSync15 } from "node:fs";
|
|
47788
|
+
import { join as join23, relative as relative6, sep as sep4 } from "node:path";
|
|
47762
47789
|
|
|
47763
47790
|
// ../../node_modules/.pnpm/chokidar@4.0.3/node_modules/chokidar/esm/index.js
|
|
47764
47791
|
import { stat as statcb } from "fs";
|
|
@@ -50541,6 +50568,147 @@ ${conversation}` }]
|
|
|
50541
50568
|
};
|
|
50542
50569
|
}
|
|
50543
50570
|
|
|
50571
|
+
// src/constraint-backfill.ts
|
|
50572
|
+
init_src4();
|
|
50573
|
+
init_src2();
|
|
50574
|
+
import { existsSync as existsSync13, readFileSync as readFileSync11, readdirSync as readdirSync6, writeFileSync as writeFileSync11 } from "node:fs";
|
|
50575
|
+
import { join as join16 } from "node:path";
|
|
50576
|
+
import { homedir as homedir4 } from "node:os";
|
|
50577
|
+
var BACKFILL_VERSION = 1;
|
|
50578
|
+
var EMPTY = {
|
|
50579
|
+
skipped: true,
|
|
50580
|
+
stamped: 0,
|
|
50581
|
+
detached: 0,
|
|
50582
|
+
reopened: 0,
|
|
50583
|
+
witnessed: 0,
|
|
50584
|
+
cloudTwins: []
|
|
50585
|
+
};
|
|
50586
|
+
function markerPath(configDir) {
|
|
50587
|
+
return join16(configDir, "constraint-backfill.json");
|
|
50588
|
+
}
|
|
50589
|
+
function alreadyDone(configDir) {
|
|
50590
|
+
const p = markerPath(configDir);
|
|
50591
|
+
if (!existsSync13(p)) return false;
|
|
50592
|
+
try {
|
|
50593
|
+
const raw2 = JSON.parse(readFileSync11(p, "utf8"));
|
|
50594
|
+
return raw2?.version === BACKFILL_VERSION;
|
|
50595
|
+
} catch {
|
|
50596
|
+
return false;
|
|
50597
|
+
}
|
|
50598
|
+
}
|
|
50599
|
+
function replay(root) {
|
|
50600
|
+
const statements = /* @__PURE__ */ new Set();
|
|
50601
|
+
const citedByFix = /* @__PURE__ */ new Set();
|
|
50602
|
+
const dir = claudeProjectDir(root, homedir4());
|
|
50603
|
+
if (!existsSync13(dir)) return { statements, citedByFix };
|
|
50604
|
+
let names;
|
|
50605
|
+
try {
|
|
50606
|
+
names = readdirSync6(dir).filter((n) => n.endsWith(".jsonl"));
|
|
50607
|
+
} catch {
|
|
50608
|
+
return { statements, citedByFix };
|
|
50609
|
+
}
|
|
50610
|
+
for (const f of names) {
|
|
50611
|
+
let lines;
|
|
50612
|
+
try {
|
|
50613
|
+
lines = readFileSync11(join16(dir, f), "utf8").split("\n");
|
|
50614
|
+
} catch {
|
|
50615
|
+
continue;
|
|
50616
|
+
}
|
|
50617
|
+
for (const line of lines) {
|
|
50618
|
+
if (!line.trim()) continue;
|
|
50619
|
+
let rec;
|
|
50620
|
+
try {
|
|
50621
|
+
rec = JSON.parse(line);
|
|
50622
|
+
} catch {
|
|
50623
|
+
continue;
|
|
50624
|
+
}
|
|
50625
|
+
if (rec.type !== "assistant" || !Array.isArray(rec.message?.content)) continue;
|
|
50626
|
+
for (const b of rec.message.content) {
|
|
50627
|
+
if (b?.type !== "text" || typeof b.text !== "string") continue;
|
|
50628
|
+
for (const tag of parseInlineTags(b.text)) {
|
|
50629
|
+
if (tag.kind === "constraint" && tag.statement) statements.add(tag.statement);
|
|
50630
|
+
if (tag.kind === "fix") {
|
|
50631
|
+
const t = tag;
|
|
50632
|
+
if (t.handle) citedByFix.add(t.handle);
|
|
50633
|
+
if (t.threadId) citedByFix.add(t.threadId);
|
|
50634
|
+
}
|
|
50635
|
+
}
|
|
50636
|
+
}
|
|
50637
|
+
}
|
|
50638
|
+
}
|
|
50639
|
+
return { statements, citedByFix };
|
|
50640
|
+
}
|
|
50641
|
+
function backfillConstraintKind(store, opts) {
|
|
50642
|
+
if (!opts.force && !opts.dryRun && alreadyDone(opts.configDir)) return EMPTY;
|
|
50643
|
+
const { statements, citedByFix } = replay(opts.root);
|
|
50644
|
+
const report = {
|
|
50645
|
+
skipped: false,
|
|
50646
|
+
stamped: 0,
|
|
50647
|
+
detached: 0,
|
|
50648
|
+
reopened: 0,
|
|
50649
|
+
witnessed: 0,
|
|
50650
|
+
cloudTwins: []
|
|
50651
|
+
};
|
|
50652
|
+
const seen = /* @__PURE__ */ new Set();
|
|
50653
|
+
const work = [];
|
|
50654
|
+
for (const statement of statements) {
|
|
50655
|
+
const id = designProblemId(statement);
|
|
50656
|
+
if (seen.has(id)) continue;
|
|
50657
|
+
seen.add(id);
|
|
50658
|
+
const node2 = store.getNode(id);
|
|
50659
|
+
if (!node2 || node2.label !== "Problem") continue;
|
|
50660
|
+
const isWitnessed = citedByFix.has(priorHandle(node2)) || citedByFix.has(id) || [...citedByFix].some((c) => c && id.startsWith(c));
|
|
50661
|
+
const fabricated = [];
|
|
50662
|
+
for (const e of store.outEdges(id, ["SOLVED_BY"])) {
|
|
50663
|
+
const sol = store.getNode(e.to);
|
|
50664
|
+
if (!sol) continue;
|
|
50665
|
+
const auto = sol.description.startsWith(AUTO_MINT_PREFIX);
|
|
50666
|
+
if (!auto && isWitnessed) report.witnessed++;
|
|
50667
|
+
else fabricated.push(sol.id);
|
|
50668
|
+
}
|
|
50669
|
+
const stamp = node2.attrs["kind"] !== "constraint";
|
|
50670
|
+
if (stamp) report.stamped++;
|
|
50671
|
+
if (fabricated.length > 0) {
|
|
50672
|
+
report.detached += fabricated.length;
|
|
50673
|
+
report.reopened++;
|
|
50674
|
+
}
|
|
50675
|
+
const cloudNodeId = node2.attrs["cloudNodeId"];
|
|
50676
|
+
if (typeof cloudNodeId === "string" && (stamp || fabricated.length > 0)) {
|
|
50677
|
+
report.cloudTwins.push(cloudNodeId);
|
|
50678
|
+
}
|
|
50679
|
+
if (stamp || fabricated.length > 0) work.push({ id, fabricated, stamp });
|
|
50680
|
+
}
|
|
50681
|
+
if (opts.dryRun) return report;
|
|
50682
|
+
store.transaction(() => {
|
|
50683
|
+
for (const w of work) {
|
|
50684
|
+
const node2 = store.getNode(w.id);
|
|
50685
|
+
if (!node2) continue;
|
|
50686
|
+
const attrs = { ...node2.attrs, kind: "constraint" };
|
|
50687
|
+
if (w.fabricated.length > 0) {
|
|
50688
|
+
delete attrs["resolvedAt"];
|
|
50689
|
+
delete attrs["resolvedReason"];
|
|
50690
|
+
}
|
|
50691
|
+
store.updateNode(w.id, { attrs, lastUpdatedAt: opts.now });
|
|
50692
|
+
for (const solId of w.fabricated) {
|
|
50693
|
+
for (const e of store.outEdges(w.id, ["SOLVED_BY"])) {
|
|
50694
|
+
if (e.to === solId) store.closeEdge(e.id, opts.now);
|
|
50695
|
+
}
|
|
50696
|
+
const sol = store.getNode(solId);
|
|
50697
|
+
if (sol?.description.startsWith(AUTO_MINT_PREFIX)) store.closeNode(solId, opts.now);
|
|
50698
|
+
}
|
|
50699
|
+
}
|
|
50700
|
+
});
|
|
50701
|
+
try {
|
|
50702
|
+
writeFileSync11(
|
|
50703
|
+
markerPath(opts.configDir),
|
|
50704
|
+
JSON.stringify({ version: BACKFILL_VERSION, at: opts.now, ...report, cloudTwins: report.cloudTwins.length }, null, 2),
|
|
50705
|
+
"utf8"
|
|
50706
|
+
);
|
|
50707
|
+
} catch {
|
|
50708
|
+
}
|
|
50709
|
+
return report;
|
|
50710
|
+
}
|
|
50711
|
+
|
|
50544
50712
|
// src/engine.ts
|
|
50545
50713
|
init_symbol_summaries();
|
|
50546
50714
|
init_reconcile();
|
|
@@ -50739,11 +50907,11 @@ init_outbox();
|
|
|
50739
50907
|
init_src8();
|
|
50740
50908
|
init_src();
|
|
50741
50909
|
init_src2();
|
|
50742
|
-
import { readFileSync as
|
|
50743
|
-
import { join as
|
|
50910
|
+
import { readFileSync as readFileSync12 } from "node:fs";
|
|
50911
|
+
import { join as join17 } from "node:path";
|
|
50744
50912
|
function loadClaimIgnorePatterns(workspaceRoot) {
|
|
50745
50913
|
try {
|
|
50746
|
-
return
|
|
50914
|
+
return readFileSync12(join17(workspaceRoot, ".errataignore"), "utf8").split(/\r?\n/).map((l) => l.trim()).filter((l) => l.length > 0 && !l.startsWith("#")).map((l) => l.toLowerCase());
|
|
50747
50915
|
} catch {
|
|
50748
50916
|
return [];
|
|
50749
50917
|
}
|
|
@@ -51104,22 +51272,22 @@ async function pullCloudTriage(shared, cloud, profile, limit = 50) {
|
|
|
51104
51272
|
}
|
|
51105
51273
|
|
|
51106
51274
|
// src/git-sensor.ts
|
|
51107
|
-
import { existsSync as
|
|
51108
|
-
import { join as
|
|
51275
|
+
import { existsSync as existsSync14, readFileSync as readFileSync13, watch as fsWatch } from "node:fs";
|
|
51276
|
+
import { join as join18 } from "node:path";
|
|
51109
51277
|
function readFirstLine(path2) {
|
|
51110
51278
|
try {
|
|
51111
|
-
return
|
|
51279
|
+
return readFileSync13(path2, "utf8").split(/\r?\n/, 1)[0].trim();
|
|
51112
51280
|
} catch {
|
|
51113
51281
|
return null;
|
|
51114
51282
|
}
|
|
51115
51283
|
}
|
|
51116
51284
|
function readGitRefState(gitDir) {
|
|
51117
|
-
const head2 = readFirstLine(
|
|
51285
|
+
const head2 = readFirstLine(join18(gitDir, "HEAD"));
|
|
51118
51286
|
const m = head2 ? /^ref:\s*refs\/heads\/(.+)$/.exec(head2) : null;
|
|
51119
51287
|
const branch = m ? m[1] : null;
|
|
51120
51288
|
let sha2 = null;
|
|
51121
51289
|
if (branch) {
|
|
51122
|
-
sha2 = readFirstLine(
|
|
51290
|
+
sha2 = readFirstLine(join18(gitDir, "refs", "heads", branch));
|
|
51123
51291
|
if (!sha2) sha2 = shaFromPackedRefs(gitDir, `refs/heads/${branch}`);
|
|
51124
51292
|
} else if (head2 && /^[0-9a-f]{7,40}$/i.test(head2)) {
|
|
51125
51293
|
sha2 = head2;
|
|
@@ -51127,13 +51295,13 @@ function readGitRefState(gitDir) {
|
|
|
51127
51295
|
return {
|
|
51128
51296
|
branch,
|
|
51129
51297
|
sha: sha2,
|
|
51130
|
-
mergeHeadExists:
|
|
51131
|
-
origHeadExists:
|
|
51298
|
+
mergeHeadExists: existsSync14(join18(gitDir, "MERGE_HEAD")),
|
|
51299
|
+
origHeadExists: existsSync14(join18(gitDir, "ORIG_HEAD"))
|
|
51132
51300
|
};
|
|
51133
51301
|
}
|
|
51134
51302
|
function shaFromPackedRefs(gitDir, ref) {
|
|
51135
51303
|
try {
|
|
51136
|
-
for (const line of
|
|
51304
|
+
for (const line of readFileSync13(join18(gitDir, "packed-refs"), "utf8").split(/\r?\n/)) {
|
|
51137
51305
|
const [sha2, name2] = line.split(/\s+/);
|
|
51138
51306
|
if (name2 === ref && sha2) return sha2;
|
|
51139
51307
|
}
|
|
@@ -51167,7 +51335,7 @@ function startGitSensor(gitDir, onEvent, opts = {}) {
|
|
|
51167
51335
|
const settle = () => {
|
|
51168
51336
|
if (timer) clearTimeout(timer);
|
|
51169
51337
|
timer = setTimeout(() => {
|
|
51170
|
-
if (
|
|
51338
|
+
if (existsSync14(join18(gitDir, "index.lock"))) {
|
|
51171
51339
|
settle();
|
|
51172
51340
|
return;
|
|
51173
51341
|
}
|
|
@@ -51178,7 +51346,7 @@ function startGitSensor(gitDir, onEvent, opts = {}) {
|
|
|
51178
51346
|
}, debounceMs);
|
|
51179
51347
|
};
|
|
51180
51348
|
for (const sub of ["HEAD", "logs/HEAD", "MERGE_HEAD", "ORIG_HEAD"]) {
|
|
51181
|
-
const p =
|
|
51349
|
+
const p = join18(gitDir, sub);
|
|
51182
51350
|
try {
|
|
51183
51351
|
watchers.push(fsWatch(p, settle));
|
|
51184
51352
|
} catch {
|
|
@@ -51403,21 +51571,21 @@ var TelemetryRecorder = class {
|
|
|
51403
51571
|
|
|
51404
51572
|
// src/skills.ts
|
|
51405
51573
|
import {
|
|
51406
|
-
existsSync as
|
|
51574
|
+
existsSync as existsSync15,
|
|
51407
51575
|
mkdirSync as mkdirSync6,
|
|
51408
|
-
readFileSync as
|
|
51409
|
-
readdirSync as
|
|
51576
|
+
readFileSync as readFileSync14,
|
|
51577
|
+
readdirSync as readdirSync7,
|
|
51410
51578
|
unlinkSync as unlinkSync2,
|
|
51411
|
-
writeFileSync as
|
|
51579
|
+
writeFileSync as writeFileSync12
|
|
51412
51580
|
} from "node:fs";
|
|
51413
|
-
import { basename as basename4, join as
|
|
51581
|
+
import { basename as basename4, join as join19 } from "node:path";
|
|
51414
51582
|
function skillFileName(id) {
|
|
51415
51583
|
return `${id.replace(/[^A-Za-z0-9_.-]/g, "_")}.md`;
|
|
51416
51584
|
}
|
|
51417
51585
|
function readSkillManifest(manifestPath) {
|
|
51418
|
-
if (!
|
|
51586
|
+
if (!existsSync15(manifestPath)) return [];
|
|
51419
51587
|
try {
|
|
51420
|
-
const parsed = JSON.parse(
|
|
51588
|
+
const parsed = JSON.parse(readFileSync14(manifestPath, "utf8"));
|
|
51421
51589
|
return (parsed.skills ?? []).map((s) => ({
|
|
51422
51590
|
title: s.title ?? "",
|
|
51423
51591
|
layer: s.layer ?? "technique",
|
|
@@ -51433,7 +51601,7 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
|
|
|
51433
51601
|
const staleDaemon = res.staleDaemon && res.latestDaemonVersion ? { latest: res.latestDaemonVersion } : void 0;
|
|
51434
51602
|
mkdirSync6(paths.skillsDir, { recursive: true });
|
|
51435
51603
|
if (res.skills.length === 0 && pins.length === 0) {
|
|
51436
|
-
const existing =
|
|
51604
|
+
const existing = readdirSync7(paths.skillsDir).filter((f) => f.endsWith(".md"));
|
|
51437
51605
|
if (existing.length > 0) return { written: 0, pruned: 0, ...staleDaemon ? { staleDaemon } : {} };
|
|
51438
51606
|
}
|
|
51439
51607
|
const rows = [];
|
|
@@ -51441,7 +51609,7 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
|
|
|
51441
51609
|
for (const s of res.skills) {
|
|
51442
51610
|
const fileName = skillFileName(s.id);
|
|
51443
51611
|
keep.add(fileName);
|
|
51444
|
-
|
|
51612
|
+
writeFileSync12(join19(paths.skillsDir, fileName), s.markdown, "utf8");
|
|
51445
51613
|
rows.push({
|
|
51446
51614
|
id: s.id,
|
|
51447
51615
|
title: s.title,
|
|
@@ -51454,7 +51622,7 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
|
|
|
51454
51622
|
const fileName = skillFileName(p.id);
|
|
51455
51623
|
if (keep.has(fileName)) continue;
|
|
51456
51624
|
keep.add(fileName);
|
|
51457
|
-
|
|
51625
|
+
writeFileSync12(join19(paths.skillsDir, fileName), p.markdown, "utf8");
|
|
51458
51626
|
rows.push({
|
|
51459
51627
|
id: p.id,
|
|
51460
51628
|
title: p.title,
|
|
@@ -51464,17 +51632,17 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
|
|
|
51464
51632
|
});
|
|
51465
51633
|
}
|
|
51466
51634
|
let pruned = 0;
|
|
51467
|
-
for (const f of
|
|
51635
|
+
for (const f of readdirSync7(paths.skillsDir)) {
|
|
51468
51636
|
if (!f.endsWith(".md")) continue;
|
|
51469
51637
|
if (keep.has(basename4(f))) continue;
|
|
51470
51638
|
try {
|
|
51471
|
-
unlinkSync2(
|
|
51639
|
+
unlinkSync2(join19(paths.skillsDir, f));
|
|
51472
51640
|
pruned++;
|
|
51473
51641
|
} catch {
|
|
51474
51642
|
}
|
|
51475
51643
|
}
|
|
51476
51644
|
rows.sort((a, b) => a.id.localeCompare(b.id));
|
|
51477
|
-
|
|
51645
|
+
writeFileSync12(
|
|
51478
51646
|
paths.skillsManifest,
|
|
51479
51647
|
JSON.stringify({ generatedAt: Date.now(), skills: rows }, null, 2),
|
|
51480
51648
|
"utf8"
|
|
@@ -51486,22 +51654,22 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
|
|
|
51486
51654
|
init_src2();
|
|
51487
51655
|
import {
|
|
51488
51656
|
cpSync,
|
|
51489
|
-
existsSync as
|
|
51657
|
+
existsSync as existsSync16,
|
|
51490
51658
|
lstatSync,
|
|
51491
51659
|
mkdirSync as mkdirSync7,
|
|
51492
|
-
readFileSync as
|
|
51493
|
-
readdirSync as
|
|
51660
|
+
readFileSync as readFileSync15,
|
|
51661
|
+
readdirSync as readdirSync8,
|
|
51494
51662
|
rmSync as rmSync2,
|
|
51495
51663
|
symlinkSync,
|
|
51496
|
-
writeFileSync as
|
|
51664
|
+
writeFileSync as writeFileSync13
|
|
51497
51665
|
} from "node:fs";
|
|
51498
|
-
import { join as
|
|
51666
|
+
import { join as join20 } from "node:path";
|
|
51499
51667
|
var SKILL_NS = "errata-";
|
|
51500
51668
|
var HARNESS_SKILL_DIRS = [
|
|
51501
|
-
{ configDir: ".claude", skillsDir:
|
|
51669
|
+
{ configDir: ".claude", skillsDir: join20(".claude", "skills") },
|
|
51502
51670
|
// Cursor adopted the standard; its exact project dir is still moving — kept
|
|
51503
51671
|
// best-effort and gated on `.cursor/` presence so we never create it blind.
|
|
51504
|
-
{ configDir: ".cursor", skillsDir:
|
|
51672
|
+
{ configDir: ".cursor", skillsDir: join20(".cursor", "skills") }
|
|
51505
51673
|
];
|
|
51506
51674
|
function skillSlug(title, id) {
|
|
51507
51675
|
const base = title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || id.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "skill";
|
|
@@ -51546,12 +51714,12 @@ function skillCiteHandle(s) {
|
|
|
51546
51714
|
return priorHandle({ id: s.id, description: s.title });
|
|
51547
51715
|
}
|
|
51548
51716
|
function reconcileNamespaced(dir, keep) {
|
|
51549
|
-
if (!
|
|
51717
|
+
if (!existsSync16(dir)) return 0;
|
|
51550
51718
|
let pruned = 0;
|
|
51551
|
-
for (const name2 of
|
|
51719
|
+
for (const name2 of readdirSync8(dir)) {
|
|
51552
51720
|
if (!name2.startsWith(SKILL_NS) || keep.has(name2)) continue;
|
|
51553
51721
|
try {
|
|
51554
|
-
rmSync2(
|
|
51722
|
+
rmSync2(join20(dir, name2), { recursive: true, force: true });
|
|
51555
51723
|
pruned++;
|
|
51556
51724
|
} catch {
|
|
51557
51725
|
}
|
|
@@ -51560,7 +51728,7 @@ function reconcileNamespaced(dir, keep) {
|
|
|
51560
51728
|
}
|
|
51561
51729
|
function linkOrCopy(linkPath, target) {
|
|
51562
51730
|
try {
|
|
51563
|
-
if (
|
|
51731
|
+
if (existsSync16(linkPath) || safeLstat(linkPath)) rmSync2(linkPath, { recursive: true, force: true });
|
|
51564
51732
|
} catch {
|
|
51565
51733
|
}
|
|
51566
51734
|
try {
|
|
@@ -51581,7 +51749,7 @@ function safeLstat(p) {
|
|
|
51581
51749
|
}
|
|
51582
51750
|
}
|
|
51583
51751
|
function emitAndProjectSkills(root, skills) {
|
|
51584
|
-
const agentsSkillsDir =
|
|
51752
|
+
const agentsSkillsDir = join20(root, ".agents", "skills");
|
|
51585
51753
|
mkdirSync7(agentsSkillsDir, { recursive: true });
|
|
51586
51754
|
const slugs = [];
|
|
51587
51755
|
const keep = /* @__PURE__ */ new Set();
|
|
@@ -51589,7 +51757,7 @@ function emitAndProjectSkills(root, skills) {
|
|
|
51589
51757
|
for (const s of skills) {
|
|
51590
51758
|
let body2;
|
|
51591
51759
|
try {
|
|
51592
|
-
body2 =
|
|
51760
|
+
body2 = readFileSync15(s.bodyPath, "utf8");
|
|
51593
51761
|
} catch {
|
|
51594
51762
|
continue;
|
|
51595
51763
|
}
|
|
@@ -51598,9 +51766,9 @@ function emitAndProjectSkills(root, skills) {
|
|
|
51598
51766
|
keep.add(slug2);
|
|
51599
51767
|
slugs.push(slug2);
|
|
51600
51768
|
const description = deriveDescription(s.title, s.layer, body2);
|
|
51601
|
-
mkdirSync7(
|
|
51602
|
-
|
|
51603
|
-
|
|
51769
|
+
mkdirSync7(join20(agentsSkillsDir, slug2), { recursive: true });
|
|
51770
|
+
writeFileSync13(
|
|
51771
|
+
join20(agentsSkillsDir, slug2, "SKILL.md"),
|
|
51604
51772
|
renderSkillMd(slug2, description, body2, skillCiteHandle(s)),
|
|
51605
51773
|
"utf8"
|
|
51606
51774
|
);
|
|
@@ -51609,11 +51777,11 @@ function emitAndProjectSkills(root, skills) {
|
|
|
51609
51777
|
reconcileNamespaced(agentsSkillsDir, keep);
|
|
51610
51778
|
let projected = 0;
|
|
51611
51779
|
for (const h of HARNESS_SKILL_DIRS) {
|
|
51612
|
-
if (!
|
|
51613
|
-
const dir =
|
|
51780
|
+
if (!existsSync16(join20(root, h.configDir))) continue;
|
|
51781
|
+
const dir = join20(root, h.skillsDir);
|
|
51614
51782
|
mkdirSync7(dir, { recursive: true });
|
|
51615
51783
|
for (const slug2 of slugs) {
|
|
51616
|
-
linkOrCopy(
|
|
51784
|
+
linkOrCopy(join20(dir, slug2), join20(agentsSkillsDir, slug2));
|
|
51617
51785
|
projected++;
|
|
51618
51786
|
}
|
|
51619
51787
|
reconcileNamespaced(dir, keep);
|
|
@@ -51622,15 +51790,15 @@ function emitAndProjectSkills(root, skills) {
|
|
|
51622
51790
|
return { slugs, emitted, projected };
|
|
51623
51791
|
}
|
|
51624
51792
|
function emitInputsFromManifest(erretaDir, manifestPath) {
|
|
51625
|
-
if (!
|
|
51793
|
+
if (!existsSync16(manifestPath)) return [];
|
|
51626
51794
|
try {
|
|
51627
|
-
const parsed = JSON.parse(
|
|
51795
|
+
const parsed = JSON.parse(readFileSync15(manifestPath, "utf8"));
|
|
51628
51796
|
return (parsed.skills ?? []).filter((s) => Boolean(s.id && s.file)).map((s) => ({
|
|
51629
51797
|
id: s.id,
|
|
51630
51798
|
title: s.title ?? s.id,
|
|
51631
51799
|
layer: s.layer ?? "technique",
|
|
51632
51800
|
confidence: s.confidence ?? 0,
|
|
51633
|
-
bodyPath:
|
|
51801
|
+
bodyPath: join20(erretaDir, s.file)
|
|
51634
51802
|
}));
|
|
51635
51803
|
} catch {
|
|
51636
51804
|
return [];
|
|
@@ -51644,17 +51812,17 @@ var GITIGNORE_LINES = [
|
|
|
51644
51812
|
".cursor/skills/errata-*/"
|
|
51645
51813
|
];
|
|
51646
51814
|
function ensureSkillGitignore(root) {
|
|
51647
|
-
const path2 =
|
|
51815
|
+
const path2 = join20(root, ".gitignore");
|
|
51648
51816
|
let current = "";
|
|
51649
51817
|
try {
|
|
51650
|
-
current =
|
|
51818
|
+
current = existsSync16(path2) ? readFileSync15(path2, "utf8") : "";
|
|
51651
51819
|
} catch {
|
|
51652
51820
|
return;
|
|
51653
51821
|
}
|
|
51654
51822
|
if (current.includes(GITIGNORE_MARK)) return;
|
|
51655
51823
|
const prefix = current.length > 0 && !current.endsWith("\n") ? "\n" : "";
|
|
51656
51824
|
try {
|
|
51657
|
-
|
|
51825
|
+
writeFileSync13(path2, `${current}${prefix}
|
|
51658
51826
|
${GITIGNORE_LINES.join("\n")}
|
|
51659
51827
|
`, "utf8");
|
|
51660
51828
|
} catch {
|
|
@@ -51818,20 +51986,20 @@ var CausalBuffer = class {
|
|
|
51818
51986
|
// src/profile.ts
|
|
51819
51987
|
init_src2();
|
|
51820
51988
|
init_paths();
|
|
51821
|
-
import { existsSync as
|
|
51989
|
+
import { existsSync as existsSync18, readFileSync as readFileSync17, writeFileSync as writeFileSync14 } from "node:fs";
|
|
51822
51990
|
import { createHash as createHash12 } from "node:crypto";
|
|
51823
|
-
import { join as
|
|
51991
|
+
import { join as join22 } from "node:path";
|
|
51824
51992
|
|
|
51825
51993
|
// src/git-remote.ts
|
|
51826
51994
|
init_src();
|
|
51827
|
-
import { existsSync as
|
|
51828
|
-
import { isAbsolute as isAbsolute3, join as
|
|
51995
|
+
import { existsSync as existsSync17, readFileSync as readFileSync16, statSync as statSync4 } from "node:fs";
|
|
51996
|
+
import { isAbsolute as isAbsolute3, join as join21, resolve as resolve5 } from "node:path";
|
|
51829
51997
|
function resolveGitDir(root) {
|
|
51830
|
-
const dotGit =
|
|
51998
|
+
const dotGit = join21(root, ".git");
|
|
51831
51999
|
try {
|
|
51832
52000
|
const st = statSync4(dotGit);
|
|
51833
52001
|
if (st.isDirectory()) return dotGit;
|
|
51834
|
-
const m = /^gitdir:\s*(.+?)\s*$/m.exec(
|
|
52002
|
+
const m = /^gitdir:\s*(.+?)\s*$/m.exec(readFileSync16(dotGit, "utf8"));
|
|
51835
52003
|
if (!m) return null;
|
|
51836
52004
|
const dir = m[1];
|
|
51837
52005
|
return isAbsolute3(dir) ? dir : resolve5(root, dir);
|
|
@@ -51840,22 +52008,22 @@ function resolveGitDir(root) {
|
|
|
51840
52008
|
}
|
|
51841
52009
|
}
|
|
51842
52010
|
function gitConfigPath(gitDir) {
|
|
51843
|
-
const commondirFile =
|
|
51844
|
-
if (
|
|
51845
|
-
const common =
|
|
52011
|
+
const commondirFile = join21(gitDir, "commondir");
|
|
52012
|
+
if (existsSync17(commondirFile)) {
|
|
52013
|
+
const common = readFileSync16(commondirFile, "utf8").trim();
|
|
51846
52014
|
const commonDir = isAbsolute3(common) ? common : resolve5(gitDir, common);
|
|
51847
|
-
return
|
|
52015
|
+
return join21(commonDir, "config");
|
|
51848
52016
|
}
|
|
51849
|
-
return
|
|
52017
|
+
return join21(gitDir, "config");
|
|
51850
52018
|
}
|
|
51851
52019
|
function readRemotes(root) {
|
|
51852
52020
|
const gitDir = resolveGitDir(root);
|
|
51853
52021
|
if (!gitDir) return [];
|
|
51854
52022
|
const cfgPath = gitConfigPath(gitDir);
|
|
51855
|
-
if (!
|
|
52023
|
+
if (!existsSync17(cfgPath)) return [];
|
|
51856
52024
|
let txt;
|
|
51857
52025
|
try {
|
|
51858
|
-
txt =
|
|
52026
|
+
txt = readFileSync16(cfgPath, "utf8");
|
|
51859
52027
|
} catch {
|
|
51860
52028
|
return [];
|
|
51861
52029
|
}
|
|
@@ -51887,13 +52055,13 @@ function refreshRepoLocator(root, profile) {
|
|
|
51887
52055
|
}
|
|
51888
52056
|
function loadProfile(root) {
|
|
51889
52057
|
const p = workspacePaths(root);
|
|
51890
|
-
if (!
|
|
51891
|
-
return JSON.parse(
|
|
52058
|
+
if (!existsSync18(p.workspaceJson)) return null;
|
|
52059
|
+
return JSON.parse(readFileSync17(p.workspaceJson, "utf8"));
|
|
51892
52060
|
}
|
|
51893
52061
|
function saveProfile(root, profile) {
|
|
51894
52062
|
const p = workspacePaths(root);
|
|
51895
52063
|
ensureDir(p.configDir);
|
|
51896
|
-
|
|
52064
|
+
writeFileSync14(p.workspaceJson, JSON.stringify(profile, null, 2), "utf8");
|
|
51897
52065
|
}
|
|
51898
52066
|
function autodetectProfile(root) {
|
|
51899
52067
|
const id = workspaceId(root);
|
|
@@ -51901,10 +52069,10 @@ function autodetectProfile(root) {
|
|
|
51901
52069
|
const p = emptyProfile(id, name2);
|
|
51902
52070
|
const locator = detectRepoLocator(root);
|
|
51903
52071
|
if (locator) p.repoLocator = locator;
|
|
51904
|
-
const pkgPath =
|
|
51905
|
-
if (
|
|
52072
|
+
const pkgPath = join22(root, "package.json");
|
|
52073
|
+
if (existsSync18(pkgPath)) {
|
|
51906
52074
|
try {
|
|
51907
|
-
const pkg = JSON.parse(
|
|
52075
|
+
const pkg = JSON.parse(readFileSync17(pkgPath, "utf8"));
|
|
51908
52076
|
p.languages.push("typescript", "javascript");
|
|
51909
52077
|
const nodeVer = pkg.engines?.node ?? "node";
|
|
51910
52078
|
p.stack.push(`node@${nodeVer}`);
|
|
@@ -51925,10 +52093,10 @@ function autodetectProfile(root) {
|
|
|
51925
52093
|
} catch {
|
|
51926
52094
|
}
|
|
51927
52095
|
}
|
|
51928
|
-
const pyproject =
|
|
51929
|
-
if (
|
|
52096
|
+
const pyproject = join22(root, "pyproject.toml");
|
|
52097
|
+
if (existsSync18(pyproject)) {
|
|
51930
52098
|
try {
|
|
51931
|
-
const txt =
|
|
52099
|
+
const txt = readFileSync17(pyproject, "utf8");
|
|
51932
52100
|
const py = /python\s*=\s*"([^"]+)"/.exec(txt)?.[1];
|
|
51933
52101
|
p.languages.push("python");
|
|
51934
52102
|
p.stack.push(`python@${py ?? "3"}`);
|
|
@@ -51939,16 +52107,16 @@ function autodetectProfile(root) {
|
|
|
51939
52107
|
} catch {
|
|
51940
52108
|
}
|
|
51941
52109
|
}
|
|
51942
|
-
const reqs =
|
|
51943
|
-
if (
|
|
52110
|
+
const reqs = join22(root, "requirements.txt");
|
|
52111
|
+
if (existsSync18(reqs)) {
|
|
51944
52112
|
if (!p.languages.includes("python")) p.languages.push("python");
|
|
51945
52113
|
if (!p.stack.includes("python@3")) p.stack.push("python@3");
|
|
51946
52114
|
}
|
|
51947
|
-
if (
|
|
52115
|
+
if (existsSync18(join22(root, "go.mod"))) {
|
|
51948
52116
|
p.languages.push("go");
|
|
51949
52117
|
p.stack.push("go");
|
|
51950
52118
|
}
|
|
51951
|
-
if (
|
|
52119
|
+
if (existsSync18(join22(root, "Cargo.toml"))) {
|
|
51952
52120
|
p.languages.push("rust");
|
|
51953
52121
|
p.stack.push("rust");
|
|
51954
52122
|
}
|
|
@@ -52106,7 +52274,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
|
|
|
52106
52274
|
}
|
|
52107
52275
|
|
|
52108
52276
|
// src/engine.ts
|
|
52109
|
-
var DAEMON_VERSION = true ? "2.0.2-dev.
|
|
52277
|
+
var DAEMON_VERSION = true ? "2.0.2-dev.204" : "2.0.0-alpha.0";
|
|
52110
52278
|
var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
|
|
52111
52279
|
var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
|
|
52112
52280
|
var GIT_OP_MUTE_MS = 4e3;
|
|
@@ -52116,7 +52284,7 @@ var TURN_REPLAY_LOOKBACK_MS = 7 * 24 * 60 * 6e4;
|
|
|
52116
52284
|
function appendIdentityAudit(path2, record2, line) {
|
|
52117
52285
|
if (!record2.accepted && record2.score <= 0) return;
|
|
52118
52286
|
try {
|
|
52119
|
-
if (
|
|
52287
|
+
if (existsSync19(path2) && statSync5(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
|
|
52120
52288
|
renameSync2(path2, `${path2}.1`);
|
|
52121
52289
|
}
|
|
52122
52290
|
appendFileSync2(path2, line);
|
|
@@ -52126,14 +52294,14 @@ function appendIdentityAudit(path2, record2, line) {
|
|
|
52126
52294
|
var yieldToLoop = () => new Promise((r) => setImmediate(r));
|
|
52127
52295
|
function loadTurnCursors(path2) {
|
|
52128
52296
|
try {
|
|
52129
|
-
return new Map(Object.entries(JSON.parse(
|
|
52297
|
+
return new Map(Object.entries(JSON.parse(readFileSync18(path2, "utf8"))));
|
|
52130
52298
|
} catch {
|
|
52131
52299
|
return /* @__PURE__ */ new Map();
|
|
52132
52300
|
}
|
|
52133
52301
|
}
|
|
52134
52302
|
function saveTurnCursors(path2, cursors) {
|
|
52135
52303
|
try {
|
|
52136
|
-
|
|
52304
|
+
writeFileSync15(path2, JSON.stringify(Object.fromEntries(cursors)), "utf8");
|
|
52137
52305
|
} catch {
|
|
52138
52306
|
}
|
|
52139
52307
|
}
|
|
@@ -52155,7 +52323,7 @@ function gitSourceWatchTargets(root) {
|
|
|
52155
52323
|
["-C", root, "ls-files", "--others", "--ignored", "--exclude-standard", "--directory", "-z"],
|
|
52156
52324
|
{ encoding: "utf8", maxBuffer: 256 * 1024 * 1024, windowsHide: true, stdio: ["ignore", "pipe", "ignore"] }
|
|
52157
52325
|
);
|
|
52158
|
-
ignoredDirs = igOut.split("\0").filter(Boolean).map((d) => d.replace(/\/+$/, "")).filter((d) => !IGNORED_PATH.test(
|
|
52326
|
+
ignoredDirs = igOut.split("\0").filter(Boolean).map((d) => d.replace(/\/+$/, "")).filter((d) => !IGNORED_PATH.test(join23(root, d) + sep4));
|
|
52159
52327
|
} catch {
|
|
52160
52328
|
}
|
|
52161
52329
|
const hasIgnoredChild = (dir) => ignoredDirs.some((ig) => ig.startsWith(dir + "/"));
|
|
@@ -52167,19 +52335,19 @@ function gitSourceWatchTargets(root) {
|
|
|
52167
52335
|
if (!f.startsWith(prefix)) continue;
|
|
52168
52336
|
const rest2 = f.slice(prefix.length);
|
|
52169
52337
|
if (rest2.includes("/")) children.add(dir === "" ? rest2.slice(0, rest2.indexOf("/")) : dir + "/" + rest2.slice(0, rest2.indexOf("/")));
|
|
52170
|
-
else targets.add(
|
|
52338
|
+
else targets.add(join23(root, f));
|
|
52171
52339
|
}
|
|
52172
52340
|
for (const c of children) {
|
|
52173
|
-
if (IGNORED_PATH.test(
|
|
52341
|
+
if (IGNORED_PATH.test(join23(root, c) + sep4)) continue;
|
|
52174
52342
|
if (hasIgnoredChild(c)) addUnder(c);
|
|
52175
|
-
else targets.add(
|
|
52343
|
+
else targets.add(join23(root, c));
|
|
52176
52344
|
}
|
|
52177
52345
|
};
|
|
52178
52346
|
addUnder("");
|
|
52179
52347
|
if (targets.size > 0) return [...targets];
|
|
52180
52348
|
} catch {
|
|
52181
52349
|
}
|
|
52182
|
-
return
|
|
52350
|
+
return readdirSync9(root, { withFileTypes: true }).filter((e) => e.isDirectory() && !IGNORED_PATH.test(join23(root, String(e.name)) + sep4)).map((e) => join23(root, String(e.name)));
|
|
52183
52351
|
}
|
|
52184
52352
|
function createWorkspaceEngine(opts) {
|
|
52185
52353
|
const paths = workspacePaths(opts.workspaceRoot);
|
|
@@ -52333,7 +52501,7 @@ function createWorkspaceEngine(opts) {
|
|
|
52333
52501
|
const srcPaths = diff.changedPaths.filter((p) => /\.(ts|tsx|js|jsx|mjs|cjs|py)$/i.test(p));
|
|
52334
52502
|
let episodeId2;
|
|
52335
52503
|
if (srcPaths.length > 0) {
|
|
52336
|
-
const abs = srcPaths.map((p) =>
|
|
52504
|
+
const abs = srcPaths.map((p) => join23(opts.workspaceRoot, p));
|
|
52337
52505
|
try {
|
|
52338
52506
|
const r = await runReindexPass(
|
|
52339
52507
|
`git-reindex:${profile.name} (${abs.length} files)`,
|
|
@@ -52369,8 +52537,8 @@ function createWorkspaceEngine(opts) {
|
|
|
52369
52537
|
`[errata] git: ${ev.kind} ${ev.newSha.slice(0, 7)} by ${meta3.authorName} \u2014 ${diff.changedPaths.length} file(s), ${diff.renames.length} rename(s)`
|
|
52370
52538
|
);
|
|
52371
52539
|
};
|
|
52372
|
-
const gitDir =
|
|
52373
|
-
if (
|
|
52540
|
+
const gitDir = join23(opts.workspaceRoot, ".git");
|
|
52541
|
+
if (existsSync19(gitDir)) {
|
|
52374
52542
|
stopGit = startGitSensor(gitDir, (ev) => {
|
|
52375
52543
|
void handleGitEvent(ev).catch((err2) => {
|
|
52376
52544
|
console.warn("[errata] git event handler failed:", err2);
|
|
@@ -52440,10 +52608,10 @@ function createWorkspaceEngine(opts) {
|
|
|
52440
52608
|
});
|
|
52441
52609
|
doneRender?.();
|
|
52442
52610
|
writeContextFile(opts.workspaceRoot, body2);
|
|
52443
|
-
const target =
|
|
52611
|
+
const target = join23(opts.workspaceRoot, "AGENTS.md");
|
|
52444
52612
|
writeManagedBlock(target, { body: AGENTS_POINTER_BODY, stable: true, force: true });
|
|
52445
52613
|
if (elicit) {
|
|
52446
|
-
writePrimingHandles(
|
|
52614
|
+
writePrimingHandles(join23(paths.configDir, "priming-handles.json"), [
|
|
52447
52615
|
...snapshot.recentProblems.map((r) => r.node),
|
|
52448
52616
|
// Resolved-band handles: the ✓ problem AND its Solution are citable
|
|
52449
52617
|
// (a fix tag on an already-resolved problem no-ops idempotently; the
|
|
@@ -52534,6 +52702,21 @@ function createWorkspaceEngine(opts) {
|
|
|
52534
52702
|
} catch (err2) {
|
|
52535
52703
|
console.warn("[errata] anchor backfill failed:", err2);
|
|
52536
52704
|
}
|
|
52705
|
+
try {
|
|
52706
|
+
const c = backfillConstraintKind(store, {
|
|
52707
|
+
root: opts.workspaceRoot,
|
|
52708
|
+
configDir: paths.configDir,
|
|
52709
|
+
now: Date.now()
|
|
52710
|
+
});
|
|
52711
|
+
if (!c.skipped && (c.stamped > 0 || c.detached > 0)) {
|
|
52712
|
+
console.log(
|
|
52713
|
+
`[errata] constraint backfill: ${c.stamped} design tension(s) marked` + (c.detached > 0 ? `; ${c.detached} fabricated resolution(s) detached, ${c.reopened} reopened` : "") + (c.witnessed > 0 ? `; ${c.witnessed} cited discharge(s) kept` : "") + (c.cloudTwins.length > 0 ? ` \u2014 ${c.cloudTwins.length} already contributed; run scripts/repair-cloud-constraints.ts to repair the cloud twins` : "")
|
|
52714
|
+
);
|
|
52715
|
+
refreshContextNow();
|
|
52716
|
+
}
|
|
52717
|
+
} catch (err2) {
|
|
52718
|
+
console.warn("[errata] constraint backfill failed:", err2);
|
|
52719
|
+
}
|
|
52537
52720
|
const report = runNightlyPipeline(store);
|
|
52538
52721
|
try {
|
|
52539
52722
|
const m = mergeDuplicateProblems(store, { ts: Date.now() });
|
|
@@ -52633,7 +52816,7 @@ function createWorkspaceEngine(opts) {
|
|
|
52633
52816
|
resultSummary: { exitCode: e.exitCode ?? 1, errorTokens: e.errorTokens }
|
|
52634
52817
|
});
|
|
52635
52818
|
};
|
|
52636
|
-
const turnCursorPath =
|
|
52819
|
+
const turnCursorPath = join23(paths.configDir, "turn-cursors.json");
|
|
52637
52820
|
const lastTurnUuid = loadTurnCursors(turnCursorPath);
|
|
52638
52821
|
const sessionLastProblem = /* @__PURE__ */ new Map();
|
|
52639
52822
|
const sessionThreads = /* @__PURE__ */ new Map();
|
|
@@ -52656,7 +52839,7 @@ function createWorkspaceEngine(opts) {
|
|
|
52656
52839
|
const t = Date.now();
|
|
52657
52840
|
let processedTurns = 0;
|
|
52658
52841
|
const elicit = isEdgeElicitationEnabled();
|
|
52659
|
-
const handleMap = elicit ? readPrimingHandles(
|
|
52842
|
+
const handleMap = elicit ? readPrimingHandles(join23(paths.configDir, "priming-handles.json")) : {};
|
|
52660
52843
|
const wsRoot = (opts.workspaceRoot ?? "").replace(/\\/g, "/");
|
|
52661
52844
|
const toRel = (abs) => {
|
|
52662
52845
|
const p = abs.replace(/\\/g, "/");
|
|
@@ -53191,7 +53374,7 @@ function createWorkspaceEngine(opts) {
|
|
|
53191
53374
|
try {
|
|
53192
53375
|
const inputs = emitInputsFromManifest(paths.configDir, paths.skillsManifest);
|
|
53193
53376
|
emitAndProjectSkills(opts.workspaceRoot, inputs);
|
|
53194
|
-
writePrimingHandles(
|
|
53377
|
+
writePrimingHandles(join23(paths.configDir, "priming-handles.json"), skillHandleNodes(inputs));
|
|
53195
53378
|
} catch (err2) {
|
|
53196
53379
|
console.warn("[skills] agent-skills projection failed (non-fatal):", err2 instanceof Error ? err2.message : err2);
|
|
53197
53380
|
}
|
|
@@ -53378,7 +53561,7 @@ function createWorkspaceEngine(opts) {
|
|
|
53378
53561
|
console.log(
|
|
53379
53562
|
"[errata] sync skipped \u2014 cloud sync consent is off (enable with `errata consent sync on`)"
|
|
53380
53563
|
);
|
|
53381
|
-
const pending =
|
|
53564
|
+
const pending = existsSync19(paths.outbox) ? readdirSync9(paths.outbox).filter((f) => f.endsWith(".json")).length : 0;
|
|
53382
53565
|
return { uploaded: 0, failed: 0, remaining: pending };
|
|
53383
53566
|
}
|
|
53384
53567
|
try {
|
|
@@ -53465,7 +53648,7 @@ async function startDaemon(opts) {
|
|
|
53465
53648
|
reviewUrl: () => webUiUrl + "/review"
|
|
53466
53649
|
});
|
|
53467
53650
|
const writeLockFile = (url2) => {
|
|
53468
|
-
|
|
53651
|
+
writeFileSync16(
|
|
53469
53652
|
engine.paths.daemonLock,
|
|
53470
53653
|
JSON.stringify({ pid: process.pid, webUiUrl: url2, startedAt: Date.now() }),
|
|
53471
53654
|
"utf8"
|
|
@@ -53508,7 +53691,7 @@ async function startDaemon(opts) {
|
|
|
53508
53691
|
);
|
|
53509
53692
|
await engine.stop();
|
|
53510
53693
|
try {
|
|
53511
|
-
if (
|
|
53694
|
+
if (existsSync20(engine.paths.daemonLock)) {
|
|
53512
53695
|
}
|
|
53513
53696
|
} catch {
|
|
53514
53697
|
}
|
|
@@ -53525,16 +53708,16 @@ async function listenServer(fetchFn, port) {
|
|
|
53525
53708
|
|
|
53526
53709
|
// src/registry.ts
|
|
53527
53710
|
init_paths();
|
|
53528
|
-
import { existsSync as
|
|
53529
|
-
import { join as
|
|
53711
|
+
import { existsSync as existsSync21, readFileSync as readFileSync19, writeFileSync as writeFileSync17 } from "node:fs";
|
|
53712
|
+
import { join as join24 } from "node:path";
|
|
53530
53713
|
function registryPath() {
|
|
53531
|
-
return process.env["ERRATA_REGISTRY_PATH"] ??
|
|
53714
|
+
return process.env["ERRATA_REGISTRY_PATH"] ?? join24(globalDir(), "workspaces.json");
|
|
53532
53715
|
}
|
|
53533
53716
|
function read() {
|
|
53534
53717
|
const p = registryPath();
|
|
53535
|
-
if (!
|
|
53718
|
+
if (!existsSync21(p)) return { version: 1, workspaces: {} };
|
|
53536
53719
|
try {
|
|
53537
|
-
const parsed = JSON.parse(
|
|
53720
|
+
const parsed = JSON.parse(readFileSync19(p, "utf8"));
|
|
53538
53721
|
return { version: 1, workspaces: parsed.workspaces ?? {} };
|
|
53539
53722
|
} catch {
|
|
53540
53723
|
return { version: 1, workspaces: {} };
|
|
@@ -53542,7 +53725,7 @@ function read() {
|
|
|
53542
53725
|
}
|
|
53543
53726
|
function write(reg) {
|
|
53544
53727
|
ensureDir(globalDir());
|
|
53545
|
-
|
|
53728
|
+
writeFileSync17(registryPath(), JSON.stringify(reg, null, 2), "utf8");
|
|
53546
53729
|
}
|
|
53547
53730
|
function registerWorkspace(profile, root, now = Date.now()) {
|
|
53548
53731
|
const reg = read();
|
|
@@ -53559,7 +53742,7 @@ function pruneMissingWorkspaces() {
|
|
|
53559
53742
|
const reg = read();
|
|
53560
53743
|
const removed = [];
|
|
53561
53744
|
for (const [id, entry] of Object.entries(reg.workspaces)) {
|
|
53562
|
-
if (!
|
|
53745
|
+
if (!existsSync21(entry.path)) {
|
|
53563
53746
|
removed.push(entry);
|
|
53564
53747
|
delete reg.workspaces[id];
|
|
53565
53748
|
}
|
|
@@ -53568,13 +53751,13 @@ function pruneMissingWorkspaces() {
|
|
|
53568
53751
|
return removed;
|
|
53569
53752
|
}
|
|
53570
53753
|
function workspaceStatus(entry) {
|
|
53571
|
-
const missing = !
|
|
53754
|
+
const missing = !existsSync21(entry.path);
|
|
53572
53755
|
const lockPath = workspacePaths(entry.path).daemonLock;
|
|
53573
53756
|
let running = false;
|
|
53574
53757
|
let webUiUrl = null;
|
|
53575
|
-
if (
|
|
53758
|
+
if (existsSync21(lockPath)) {
|
|
53576
53759
|
try {
|
|
53577
|
-
const lock = JSON.parse(
|
|
53760
|
+
const lock = JSON.parse(readFileSync19(lockPath, "utf8"));
|
|
53578
53761
|
if (lock.pid && lock.webUiUrl && pidAlive(lock.pid)) {
|
|
53579
53762
|
running = true;
|
|
53580
53763
|
webUiUrl = lock.webUiUrl;
|
|
@@ -53602,7 +53785,7 @@ function pidAlive(pid) {
|
|
|
53602
53785
|
// src/multi.ts
|
|
53603
53786
|
init_dist();
|
|
53604
53787
|
init_src4();
|
|
53605
|
-
import { readFileSync as
|
|
53788
|
+
import { readFileSync as readFileSync22, unlinkSync as unlinkSync3, writeFileSync as writeFileSync18 } from "node:fs";
|
|
53606
53789
|
|
|
53607
53790
|
// src/principle-sync.ts
|
|
53608
53791
|
init_src4();
|
|
@@ -53630,8 +53813,8 @@ init_reconcile();
|
|
|
53630
53813
|
|
|
53631
53814
|
// src/lockfile-auto.ts
|
|
53632
53815
|
init_src();
|
|
53633
|
-
import { existsSync as
|
|
53634
|
-
import { join as
|
|
53816
|
+
import { existsSync as existsSync22, readFileSync as readFileSync20 } from "node:fs";
|
|
53817
|
+
import { join as join25 } from "node:path";
|
|
53635
53818
|
|
|
53636
53819
|
// src/package-index.ts
|
|
53637
53820
|
init_src();
|
|
@@ -53777,11 +53960,11 @@ function runLockfilePass(opts) {
|
|
|
53777
53960
|
{ file: "package-lock.json", parse: parsePackageLockJson }
|
|
53778
53961
|
];
|
|
53779
53962
|
for (const c of candidates) {
|
|
53780
|
-
const p =
|
|
53781
|
-
if (!
|
|
53963
|
+
const p = join25(opts.root, c.file);
|
|
53964
|
+
if (!existsSync22(p)) continue;
|
|
53782
53965
|
let sbom;
|
|
53783
53966
|
try {
|
|
53784
|
-
sbom = c.parse(
|
|
53967
|
+
sbom = c.parse(readFileSync20(p, "utf8"));
|
|
53785
53968
|
} catch {
|
|
53786
53969
|
continue;
|
|
53787
53970
|
}
|
|
@@ -54224,7 +54407,7 @@ var ConsolidateWorker = class {
|
|
|
54224
54407
|
init_paths();
|
|
54225
54408
|
|
|
54226
54409
|
// src/lock.ts
|
|
54227
|
-
import { existsSync as
|
|
54410
|
+
import { existsSync as existsSync23, readFileSync as readFileSync21 } from "node:fs";
|
|
54228
54411
|
function isProcessAlive(pid) {
|
|
54229
54412
|
if (!pid || pid <= 0) return false;
|
|
54230
54413
|
try {
|
|
@@ -54235,9 +54418,9 @@ function isProcessAlive(pid) {
|
|
|
54235
54418
|
}
|
|
54236
54419
|
}
|
|
54237
54420
|
function readDaemonLock(lockPath) {
|
|
54238
|
-
if (!
|
|
54421
|
+
if (!existsSync23(lockPath)) return null;
|
|
54239
54422
|
try {
|
|
54240
|
-
const lock = JSON.parse(
|
|
54423
|
+
const lock = JSON.parse(readFileSync21(lockPath, "utf8"));
|
|
54241
54424
|
return typeof lock.pid === "number" ? lock : null;
|
|
54242
54425
|
} catch {
|
|
54243
54426
|
return null;
|
|
@@ -54479,12 +54662,12 @@ async function reanchorProject(opts) {
|
|
|
54479
54662
|
}
|
|
54480
54663
|
|
|
54481
54664
|
// src/adopt.ts
|
|
54482
|
-
import { existsSync as
|
|
54483
|
-
import { dirname as dirname9, join as
|
|
54665
|
+
import { existsSync as existsSync24 } from "node:fs";
|
|
54666
|
+
import { dirname as dirname9, join as join26 } from "node:path";
|
|
54484
54667
|
function findGitRoot(absPath) {
|
|
54485
54668
|
let dir = absPath;
|
|
54486
54669
|
for (let depth = 0; depth < 64; depth++) {
|
|
54487
|
-
if (
|
|
54670
|
+
if (existsSync24(join26(dir, ".git"))) return dir;
|
|
54488
54671
|
const parent = dirname9(dir);
|
|
54489
54672
|
if (parent === dir) return null;
|
|
54490
54673
|
dir = parent;
|
|
@@ -54706,7 +54889,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
54706
54889
|
void ambientLinkAll();
|
|
54707
54890
|
app.route(`/ws/${rec.id}`, rec.webApp);
|
|
54708
54891
|
try {
|
|
54709
|
-
|
|
54892
|
+
writeFileSync18(
|
|
54710
54893
|
rec.engine.paths.daemonLock,
|
|
54711
54894
|
JSON.stringify({ pid: process.pid, webUiUrl: `${baseUrl}/ws/${rec.id}`, startedAt: Date.now() }),
|
|
54712
54895
|
"utf8"
|
|
@@ -54895,7 +55078,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
54895
55078
|
baseUrl = `http://127.0.0.1:${port}`;
|
|
54896
55079
|
try {
|
|
54897
55080
|
ensureDir(globalDir());
|
|
54898
|
-
|
|
55081
|
+
writeFileSync18(
|
|
54899
55082
|
lockPath,
|
|
54900
55083
|
JSON.stringify({ pid: process.pid, webUiUrl: baseUrl, startedAt: Date.now() }),
|
|
54901
55084
|
"utf8"
|
|
@@ -54904,7 +55087,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
54904
55087
|
}
|
|
54905
55088
|
for (const r of records) {
|
|
54906
55089
|
try {
|
|
54907
|
-
|
|
55090
|
+
writeFileSync18(
|
|
54908
55091
|
r.engine.paths.daemonLock,
|
|
54909
55092
|
JSON.stringify({ pid: process.pid, webUiUrl: `${baseUrl}/ws/${r.id}`, startedAt: Date.now() }),
|
|
54910
55093
|
"utf8"
|
|
@@ -55372,7 +55555,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
55372
55555
|
},
|
|
55373
55556
|
async stop() {
|
|
55374
55557
|
try {
|
|
55375
|
-
const cur =
|
|
55558
|
+
const cur = readFileSync22(lockPath, "utf8");
|
|
55376
55559
|
if (JSON.parse(cur).pid === process.pid) unlinkSync3(lockPath);
|
|
55377
55560
|
} catch {
|
|
55378
55561
|
}
|
|
@@ -56392,21 +56575,21 @@ async function cmdInit() {
|
|
|
56392
56575
|
if (!skipHooks) {
|
|
56393
56576
|
console.log("");
|
|
56394
56577
|
console.log("installing harness hooks...");
|
|
56395
|
-
const { existsSync:
|
|
56396
|
-
const { join:
|
|
56578
|
+
const { existsSync: existsSync26 } = await import("node:fs");
|
|
56579
|
+
const { join: join28 } = await import("node:path");
|
|
56397
56580
|
try {
|
|
56398
56581
|
await installClaudeHooks(port);
|
|
56399
56582
|
} catch (err2) {
|
|
56400
56583
|
console.warn(` \u26A0\uFE0F Claude hook install failed: ${err2 instanceof Error ? err2.message : err2}`);
|
|
56401
56584
|
}
|
|
56402
|
-
if (
|
|
56585
|
+
if (existsSync26(join28(ROOT, ".cursor"))) {
|
|
56403
56586
|
try {
|
|
56404
56587
|
await installCursorMcpConfig();
|
|
56405
56588
|
} catch (err2) {
|
|
56406
56589
|
console.warn(` \u26A0\uFE0F Cursor MCP config failed: ${err2 instanceof Error ? err2.message : err2}`);
|
|
56407
56590
|
}
|
|
56408
56591
|
}
|
|
56409
|
-
if (
|
|
56592
|
+
if (existsSync26(join28(ROOT, ".codex"))) {
|
|
56410
56593
|
try {
|
|
56411
56594
|
await installCodexHooks(port);
|
|
56412
56595
|
} catch (err2) {
|
|
@@ -56563,8 +56746,8 @@ async function cmdStatus() {
|
|
|
56563
56746
|
console.log(` stack: ${profile.stack.join(", ") || "(none)"}`);
|
|
56564
56747
|
console.log(` languages: ${profile.languages.join(", ") || "(none)"}`);
|
|
56565
56748
|
}
|
|
56566
|
-
console.log(` graph db: ${
|
|
56567
|
-
console.log(` event log: ${
|
|
56749
|
+
console.log(` graph db: ${existsSync25(paths.castalia) ? "yes" : "no"} (${paths.castalia})`);
|
|
56750
|
+
console.log(` event log: ${existsSync25(paths.eventLog) ? "yes" : "no"} (${paths.eventLog})`);
|
|
56568
56751
|
const lockPath = globalDaemonLock();
|
|
56569
56752
|
const running = isDaemonAlive(lockPath) ? readDaemonLock(lockPath) : null;
|
|
56570
56753
|
console.log(
|
|
@@ -57194,11 +57377,11 @@ function cmdInstallationProfile(args2) {
|
|
|
57194
57377
|
}
|
|
57195
57378
|
async function cmdReview() {
|
|
57196
57379
|
const paths = workspacePaths(ROOT);
|
|
57197
|
-
if (!
|
|
57380
|
+
if (!existsSync25(paths.reviewQueue)) {
|
|
57198
57381
|
console.log("(review queue empty)");
|
|
57199
57382
|
return;
|
|
57200
57383
|
}
|
|
57201
|
-
const queue = JSON.parse(
|
|
57384
|
+
const queue = JSON.parse(readFileSync23(paths.reviewQueue, "utf8"));
|
|
57202
57385
|
if (queue.length === 0) {
|
|
57203
57386
|
console.log("(review queue empty)");
|
|
57204
57387
|
return;
|
|
@@ -57869,7 +58052,7 @@ async function gatherRepo(store, ws) {
|
|
|
57869
58052
|
};
|
|
57870
58053
|
}
|
|
57871
58054
|
async function gatherReportData(generatedAt) {
|
|
57872
|
-
const { existsSync:
|
|
58055
|
+
const { existsSync: existsSync26 } = await import("node:fs");
|
|
57873
58056
|
const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src4(), src_exports2));
|
|
57874
58057
|
const cfg = loadConfig();
|
|
57875
58058
|
const outbound = cfg.consent.sync ? "auto" : "off";
|
|
@@ -57877,7 +58060,7 @@ async function gatherReportData(generatedAt) {
|
|
|
57877
58060
|
for (const ws of listWorkspaces()) {
|
|
57878
58061
|
if (ws.missing) continue;
|
|
57879
58062
|
const dbPath = workspacePaths(ws.path).castalia;
|
|
57880
|
-
if (!
|
|
58063
|
+
if (!existsSync26(dbPath)) continue;
|
|
57881
58064
|
let store = null;
|
|
57882
58065
|
try {
|
|
57883
58066
|
store = openGraphStore2({ path: dbPath });
|
|
@@ -57908,7 +58091,7 @@ async function gatherReportData(generatedAt) {
|
|
|
57908
58091
|
};
|
|
57909
58092
|
}
|
|
57910
58093
|
async function cmdReport(args2) {
|
|
57911
|
-
const { mkdirSync: mkdirSync8, writeFileSync:
|
|
58094
|
+
const { mkdirSync: mkdirSync8, writeFileSync: writeFileSync19 } = await import("node:fs");
|
|
57912
58095
|
const { renderReport: renderReport2 } = await Promise.resolve().then(() => (init_report_render(), report_render_exports));
|
|
57913
58096
|
const includeFutureVerbs = args2.includes("--future-verbs");
|
|
57914
58097
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -57921,8 +58104,8 @@ async function cmdReport(args2) {
|
|
|
57921
58104
|
const outDir = workspacePaths(ROOT).configDir;
|
|
57922
58105
|
mkdirSync8(outDir, { recursive: true });
|
|
57923
58106
|
const files = renderReport2(data, { includeFutureVerbs });
|
|
57924
|
-
for (const f of files)
|
|
57925
|
-
const indexPath =
|
|
58107
|
+
for (const f of files) writeFileSync19(join27(outDir, f.name), f.html, "utf8");
|
|
58108
|
+
const indexPath = join27(outDir, "report.html");
|
|
57926
58109
|
console.log(`report \u2192 ${indexPath}`);
|
|
57927
58110
|
console.log(
|
|
57928
58111
|
` ${data.repos.length} repo(s) \xB7 ${files.length} file(s) \xB7 ${data.rollup.nodes.toLocaleString("en-US")} nodes`
|
|
@@ -58040,15 +58223,15 @@ function hookRelayCommand(port, path2) {
|
|
|
58040
58223
|
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 '{}'`;
|
|
58041
58224
|
}
|
|
58042
58225
|
async function installClaudeHooks(port) {
|
|
58043
|
-
const { mkdirSync: mkdirSync8, existsSync:
|
|
58044
|
-
const { join:
|
|
58045
|
-
const dir =
|
|
58046
|
-
if (!
|
|
58047
|
-
const file2 =
|
|
58226
|
+
const { mkdirSync: mkdirSync8, existsSync: existsSync26, readFileSync: readFileSync24, writeFileSync: writeFileSync19 } = await import("node:fs");
|
|
58227
|
+
const { join: join28 } = await import("node:path");
|
|
58228
|
+
const dir = join28(ROOT, ".claude");
|
|
58229
|
+
if (!existsSync26(dir)) mkdirSync8(dir, { recursive: true });
|
|
58230
|
+
const file2 = join28(dir, "settings.json");
|
|
58048
58231
|
let settings = {};
|
|
58049
|
-
if (
|
|
58232
|
+
if (existsSync26(file2)) {
|
|
58050
58233
|
try {
|
|
58051
|
-
settings = JSON.parse(
|
|
58234
|
+
settings = JSON.parse(readFileSync24(file2, "utf8"));
|
|
58052
58235
|
} catch {
|
|
58053
58236
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
58054
58237
|
process.exit(2);
|
|
@@ -58094,10 +58277,10 @@ async function installClaudeHooks(port) {
|
|
|
58094
58277
|
dropErrata(list);
|
|
58095
58278
|
list.push({ hooks: [{ type: "command", command: injectCmd }] });
|
|
58096
58279
|
}
|
|
58097
|
-
|
|
58280
|
+
writeFileSync19(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
|
|
58098
58281
|
console.log(`installed Claude Code hooks \u2192 ${file2}`);
|
|
58099
58282
|
await installClaudeMcpConfig();
|
|
58100
|
-
const claudeMd =
|
|
58283
|
+
const claudeMd = join28(ROOT, "CLAUDE.md");
|
|
58101
58284
|
const recall = writeManagedBlock(claudeMd, { body: RECALL_FIRST_BLOCK });
|
|
58102
58285
|
if (recall.kind === "collision") {
|
|
58103
58286
|
console.warn(
|
|
@@ -58109,15 +58292,15 @@ async function installClaudeHooks(port) {
|
|
|
58109
58292
|
console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
|
|
58110
58293
|
}
|
|
58111
58294
|
async function installClaudeMcpConfig() {
|
|
58112
|
-
const { mkdirSync: mkdirSync8, existsSync:
|
|
58113
|
-
const { join:
|
|
58114
|
-
const file2 =
|
|
58295
|
+
const { mkdirSync: mkdirSync8, existsSync: existsSync26, readFileSync: readFileSync24, writeFileSync: writeFileSync19 } = await import("node:fs");
|
|
58296
|
+
const { join: join28, dirname: dirname10 } = await import("node:path");
|
|
58297
|
+
const file2 = join28(ROOT, ".mcp.json");
|
|
58115
58298
|
const dir = dirname10(file2);
|
|
58116
|
-
if (!
|
|
58299
|
+
if (!existsSync26(dir)) mkdirSync8(dir, { recursive: true });
|
|
58117
58300
|
let cfg = {};
|
|
58118
|
-
if (
|
|
58301
|
+
if (existsSync26(file2)) {
|
|
58119
58302
|
try {
|
|
58120
|
-
cfg = JSON.parse(
|
|
58303
|
+
cfg = JSON.parse(readFileSync24(file2, "utf8"));
|
|
58121
58304
|
} catch {
|
|
58122
58305
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
58123
58306
|
process.exit(2);
|
|
@@ -58125,21 +58308,21 @@ async function installClaudeMcpConfig() {
|
|
|
58125
58308
|
}
|
|
58126
58309
|
cfg.mcpServers ??= {};
|
|
58127
58310
|
cfg.mcpServers["errata"] = errataMcpInvocation();
|
|
58128
|
-
|
|
58311
|
+
writeFileSync19(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
|
|
58129
58312
|
console.log(`installed Claude Code MCP server config \u2192 ${file2}`);
|
|
58130
58313
|
console.log(` Claude Code will spawn \`errata mcp\` on workspace open.`);
|
|
58131
58314
|
console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses / show / similar`);
|
|
58132
58315
|
}
|
|
58133
58316
|
async function installCursorMcpConfig() {
|
|
58134
|
-
const { mkdirSync: mkdirSync8, existsSync:
|
|
58135
|
-
const { join:
|
|
58136
|
-
const dir =
|
|
58137
|
-
if (!
|
|
58138
|
-
const file2 =
|
|
58317
|
+
const { mkdirSync: mkdirSync8, existsSync: existsSync26, readFileSync: readFileSync24, writeFileSync: writeFileSync19 } = await import("node:fs");
|
|
58318
|
+
const { join: join28 } = await import("node:path");
|
|
58319
|
+
const dir = join28(ROOT, ".cursor");
|
|
58320
|
+
if (!existsSync26(dir)) mkdirSync8(dir, { recursive: true });
|
|
58321
|
+
const file2 = join28(dir, "mcp.json");
|
|
58139
58322
|
let cfg = {};
|
|
58140
|
-
if (
|
|
58323
|
+
if (existsSync26(file2)) {
|
|
58141
58324
|
try {
|
|
58142
|
-
cfg = JSON.parse(
|
|
58325
|
+
cfg = JSON.parse(readFileSync24(file2, "utf8"));
|
|
58143
58326
|
} catch {
|
|
58144
58327
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
58145
58328
|
process.exit(2);
|
|
@@ -58147,7 +58330,7 @@ async function installCursorMcpConfig() {
|
|
|
58147
58330
|
}
|
|
58148
58331
|
cfg.mcpServers ??= {};
|
|
58149
58332
|
cfg.mcpServers["errata"] = errataMcpInvocation();
|
|
58150
|
-
|
|
58333
|
+
writeFileSync19(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
|
|
58151
58334
|
console.log(`installed Cursor MCP server config \u2192 ${file2}`);
|
|
58152
58335
|
console.log(` Cursor will spawn \`errata mcp\` on workspace open.`);
|
|
58153
58336
|
console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses`);
|
|
@@ -58155,16 +58338,16 @@ async function installCursorMcpConfig() {
|
|
|
58155
58338
|
console.log(` \u26A0\uFE0F reload Cursor (Cmd/Ctrl-Shift-P \u2192 "Reload Window") to pick it up.`);
|
|
58156
58339
|
}
|
|
58157
58340
|
async function installCodexHooks(port) {
|
|
58158
|
-
const { mkdirSync: mkdirSync8, existsSync:
|
|
58159
|
-
const { join:
|
|
58160
|
-
const dir =
|
|
58161
|
-
if (!
|
|
58162
|
-
const file2 =
|
|
58341
|
+
const { mkdirSync: mkdirSync8, existsSync: existsSync26, readFileSync: readFileSync24, writeFileSync: writeFileSync19 } = await import("node:fs");
|
|
58342
|
+
const { join: join28 } = await import("node:path");
|
|
58343
|
+
const dir = join28(ROOT, ".codex");
|
|
58344
|
+
if (!existsSync26(dir)) mkdirSync8(dir, { recursive: true });
|
|
58345
|
+
const file2 = join28(dir, "config.toml");
|
|
58163
58346
|
const BEGIN = `# >>> errata hooks (errata-managed)`;
|
|
58164
58347
|
const END = `# <<< errata hooks`;
|
|
58165
58348
|
let existing = "";
|
|
58166
|
-
if (
|
|
58167
|
-
existing =
|
|
58349
|
+
if (existsSync26(file2)) {
|
|
58350
|
+
existing = readFileSync24(file2, "utf8");
|
|
58168
58351
|
const beginIdx = existing.indexOf(BEGIN);
|
|
58169
58352
|
const endIdx = existing.indexOf(END);
|
|
58170
58353
|
if (beginIdx >= 0 && endIdx > beginIdx) {
|
|
@@ -58193,7 +58376,7 @@ ${END}
|
|
|
58193
58376
|
const final = existing.length > 0 && !existing.endsWith("\n") ? `${existing}
|
|
58194
58377
|
|
|
58195
58378
|
${block}` : existing + (existing.endsWith("\n\n") ? "" : "\n") + block;
|
|
58196
|
-
|
|
58379
|
+
writeFileSync19(file2, final, "utf8");
|
|
58197
58380
|
console.log(`installed Codex hooks \u2192 ${file2}`);
|
|
58198
58381
|
console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
|
|
58199
58382
|
console.log("");
|
|
@@ -58483,7 +58666,7 @@ async function cmdDash(args2) {
|
|
|
58483
58666
|
await yieldToLoop2();
|
|
58484
58667
|
try {
|
|
58485
58668
|
const items = selectDurableMemory(handle2.sharedStore, r.engine.profile);
|
|
58486
|
-
const res = bleedRules(
|
|
58669
|
+
const res = bleedRules(join27(r.root, ".claude", "rules"), items);
|
|
58487
58670
|
if (res.written || res.pruned) {
|
|
58488
58671
|
console.log(
|
|
58489
58672
|
`[rules:${r.entry.name}] ${res.written} collective principle(s) \u2192 .claude/rules` + (res.pruned ? `, ${res.pruned} pruned` : "")
|
package/package.json
CHANGED
package/pass-worker.mjs
CHANGED
|
@@ -26106,10 +26106,13 @@ function buildSnapshot(opts) {
|
|
|
26106
26106
|
episodeId,
|
|
26107
26107
|
problems: problems2
|
|
26108
26108
|
}));
|
|
26109
|
-
const
|
|
26110
|
-
|
|
26111
|
-
|
|
26112
|
-
|
|
26109
|
+
const revisitSeen = /* @__PURE__ */ new Set();
|
|
26110
|
+
const needsRevisit = listNeedsRevisit(opts.store, (opts.now ?? /* @__PURE__ */ new Date()).getTime()).filter((r) => {
|
|
26111
|
+
const key = `${r.label}:${r.description.trim().toLowerCase()}`;
|
|
26112
|
+
if (revisitSeen.has(key)) return false;
|
|
26113
|
+
revisitSeen.add(key);
|
|
26114
|
+
return true;
|
|
26115
|
+
}).slice(0, 5);
|
|
26113
26116
|
const norm = (x) => x.toLowerCase().replace(/[^a-z0-9]+/g, "");
|
|
26114
26117
|
const pkgBase = (x) => {
|
|
26115
26118
|
const at = x.lastIndexOf("@");
|