@inerrata-corporation/errata 2.0.2-dev.192 → 2.0.2-dev.201
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 +407 -198
- package/package.json +1 -1
- package/pass-worker.mjs +18 -6
package/errata.mjs
CHANGED
|
@@ -18183,6 +18183,9 @@ var init_problem_package_link = __esm({
|
|
|
18183
18183
|
});
|
|
18184
18184
|
|
|
18185
18185
|
// ../../packages/local-graph/src/design-problem.ts
|
|
18186
|
+
function isConstraintProblem(node2) {
|
|
18187
|
+
return node2.attrs["kind"] === "constraint";
|
|
18188
|
+
}
|
|
18186
18189
|
function isPlaceholderStatement(statement) {
|
|
18187
18190
|
const s = statement.trim();
|
|
18188
18191
|
if (s.length < 8) return true;
|
|
@@ -18432,7 +18435,7 @@ function tokenJaccard(a, b) {
|
|
|
18432
18435
|
for (const t of sa) if (sb.has(t)) inter++;
|
|
18433
18436
|
return inter / (sa.size + sb.size - inter);
|
|
18434
18437
|
}
|
|
18435
|
-
function reinforceSameAnchorProblem(store, relPath, workspaceId2, statement, source, ts) {
|
|
18438
|
+
function reinforceSameAnchorProblem(store, relPath, workspaceId2, statement, source, ts, kind = "problem") {
|
|
18436
18439
|
const stmt = statement.trim();
|
|
18437
18440
|
if (!ANCHORABLE_CODE.test(relPath)) return null;
|
|
18438
18441
|
const file2 = resolveFileNode(store, relPath, workspaceId2);
|
|
@@ -18443,6 +18446,8 @@ function reinforceSameAnchorProblem(store, relPath, workspaceId2, statement, sou
|
|
|
18443
18446
|
const cand = store.getNode(e.from);
|
|
18444
18447
|
if (!cand || cand.label !== "Problem" || cand.attrs["resolvedAt"]) continue;
|
|
18445
18448
|
if (cand.id === selfId) continue;
|
|
18449
|
+
const candKind = cand.attrs["kind"] === "constraint" ? "constraint" : "problem";
|
|
18450
|
+
if (candKind !== (kind === "constraint" ? "constraint" : "problem")) continue;
|
|
18446
18451
|
const score2 = tokenJaccard(stmt, cand.description);
|
|
18447
18452
|
if (score2 >= SAME_ANCHOR_DEDUP_JACCARD && (!best || score2 > best.score)) best = { node: cand, score: score2 };
|
|
18448
18453
|
}
|
|
@@ -18477,6 +18482,7 @@ function priorsForFile(store, relPath) {
|
|
|
18477
18482
|
}
|
|
18478
18483
|
if (!file2) return null;
|
|
18479
18484
|
const openProblems = [];
|
|
18485
|
+
const constraints = [];
|
|
18480
18486
|
const seenProblem = /* @__PURE__ */ new Set();
|
|
18481
18487
|
const related = /* @__PURE__ */ new Map();
|
|
18482
18488
|
for (const e of store.inEdges(file2.id, ["ANCHORED_AT"])) {
|
|
@@ -18485,14 +18491,14 @@ function priorsForFile(store, relPath) {
|
|
|
18485
18491
|
if (n.label === "Problem") {
|
|
18486
18492
|
if (!n.attrs["resolvedAt"] && !seenProblem.has(n.id)) {
|
|
18487
18493
|
seenProblem.add(n.id);
|
|
18488
|
-
openProblems.push(n);
|
|
18494
|
+
(isConstraintProblem(n) ? constraints : openProblems).push(n);
|
|
18489
18495
|
}
|
|
18490
18496
|
} else if (CITABLE_PRIOR_LABELS.has(n.label)) {
|
|
18491
18497
|
related.set(n.id, n);
|
|
18492
18498
|
}
|
|
18493
18499
|
}
|
|
18494
18500
|
const solutionsByProblem = /* @__PURE__ */ new Map();
|
|
18495
|
-
for (const p of openProblems) {
|
|
18501
|
+
for (const p of [...openProblems, ...constraints]) {
|
|
18496
18502
|
for (const e of store.outEdges(p.id, ["SOLVED_BY", "CAUSED_BY", "INSTANCE_OF"])) {
|
|
18497
18503
|
const n = store.getNode(e.to);
|
|
18498
18504
|
if (n && CITABLE_PRIOR_LABELS.has(n.label)) related.set(n.id, n);
|
|
@@ -18503,9 +18509,11 @@ function priorsForFile(store, relPath) {
|
|
|
18503
18509
|
}
|
|
18504
18510
|
}
|
|
18505
18511
|
}
|
|
18506
|
-
if (openProblems.length === 0 && related.size === 0) return null;
|
|
18507
|
-
|
|
18508
|
-
|
|
18512
|
+
if (openProblems.length === 0 && constraints.length === 0 && related.size === 0) return null;
|
|
18513
|
+
const recentFirst = (a, b) => (b.lastUpdatedAt ?? 0) - (a.lastUpdatedAt ?? 0);
|
|
18514
|
+
openProblems.sort(recentFirst);
|
|
18515
|
+
constraints.sort(recentFirst);
|
|
18516
|
+
return { file: file2, openProblems, constraints, related: [...related.values()], solutionsByProblem };
|
|
18509
18517
|
}
|
|
18510
18518
|
function anchorProblemToDiff(store, problemId, changedPaths, workspaceId2, t, opts = {}) {
|
|
18511
18519
|
return anchorNodeToDiff(store, problemId, "Problem", changedPaths, workspaceId2, t, opts);
|
|
@@ -18626,6 +18634,7 @@ function resolveDesignProblems(store, t) {
|
|
|
18626
18634
|
for (const p of store.findNodesByLabel("Problem")) {
|
|
18627
18635
|
if (!p.id.startsWith("dprob_")) continue;
|
|
18628
18636
|
if (p.attrs["resolvedAt"]) continue;
|
|
18637
|
+
if (isConstraintProblem(p)) continue;
|
|
18629
18638
|
let symName = "";
|
|
18630
18639
|
let symRelPath;
|
|
18631
18640
|
let edited = false;
|
|
@@ -20536,6 +20545,7 @@ function mergeDuplicateProblems(store, opts) {
|
|
|
20536
20545
|
if (consumed.has(b.id)) continue;
|
|
20537
20546
|
const tb = tokens.get(b.id);
|
|
20538
20547
|
if (Math.min(ta.size, tb.size) < minTokens) continue;
|
|
20548
|
+
if (isConstraintProblem(a) !== isConstraintProblem(b)) continue;
|
|
20539
20549
|
if (overlap(ta, tb) >= minOverlap) {
|
|
20540
20550
|
cluster.push(b);
|
|
20541
20551
|
consumed.add(b.id);
|
|
@@ -20592,6 +20602,7 @@ var init_problem_dedup = __esm({
|
|
|
20592
20602
|
"use strict";
|
|
20593
20603
|
init_src();
|
|
20594
20604
|
init_src();
|
|
20605
|
+
init_design_problem();
|
|
20595
20606
|
REDIRECT_EDGES = [
|
|
20596
20607
|
"CAUSED_BY",
|
|
20597
20608
|
"SOLVED_BY",
|
|
@@ -20850,6 +20861,7 @@ __export(src_exports2, {
|
|
|
20850
20861
|
induceAbstractions: () => induceAbstractions,
|
|
20851
20862
|
induceTriage: () => induceTriage,
|
|
20852
20863
|
ingestDesignProblem: () => ingestDesignProblem,
|
|
20864
|
+
isConstraintProblem: () => isConstraintProblem,
|
|
20853
20865
|
isPlaceholderStatement: () => isPlaceholderStatement,
|
|
20854
20866
|
linkProblemToLanguages: () => linkProblemToLanguages,
|
|
20855
20867
|
linkProblemToPackages: () => linkProblemToPackages,
|
|
@@ -20935,12 +20947,14 @@ function isPassiveInjectable(node2) {
|
|
|
20935
20947
|
}
|
|
20936
20948
|
function buildSnapshot(opts) {
|
|
20937
20949
|
const problems = opts.store.findNodesByLabel("Problem").filter((p) => p.attrs["mergedInto"] === void 0);
|
|
20938
|
-
const
|
|
20950
|
+
const stillOpen = problems.filter((p) => p.attrs["resolvedAt"] == null);
|
|
20951
|
+
const allProblems = stillOpen.filter((p) => !isConstraintProblem(p));
|
|
20939
20952
|
allProblems.sort((a, b) => b.lastUpdatedAt - a.lastUpdatedAt);
|
|
20940
20953
|
const recent = allProblems.slice(0, 8).map((p) => ({
|
|
20941
20954
|
node: p,
|
|
20942
20955
|
anchors: opts.store.outEdges(p.id, ["MANIFESTED_IN", "EVIDENCED_BY"])
|
|
20943
20956
|
}));
|
|
20957
|
+
const recentConstraints = stillOpen.filter((p) => isConstraintProblem(p)).sort((a, b) => b.lastUpdatedAt - a.lastUpdatedAt).slice(0, 3);
|
|
20944
20958
|
const recentResolved = problems.filter((p) => p.attrs["resolvedAt"] != null && p.attrs["resolvedAs"] == null).sort((a, b) => Number(b.attrs["resolvedAt"] ?? 0) - Number(a.attrs["resolvedAt"] ?? 0)).slice(0, 4).map((p) => {
|
|
20945
20959
|
const solEdge = opts.store.outEdges(p.id, ["SOLVED_BY"])[0];
|
|
20946
20960
|
const solution = solEdge ? opts.store.getNode(solEdge.to) ?? void 0 : void 0;
|
|
@@ -21007,6 +21021,7 @@ function buildSnapshot(opts) {
|
|
|
21007
21021
|
profileContext,
|
|
21008
21022
|
recentProblems: recent,
|
|
21009
21023
|
recentResolved,
|
|
21024
|
+
recentConstraints,
|
|
21010
21025
|
...causalNudge ? { causalNudge } : {},
|
|
21011
21026
|
...domainNudge ? { domainNudge } : {},
|
|
21012
21027
|
motifs,
|
|
@@ -21059,6 +21074,7 @@ function sliceForFile(store, relPath) {
|
|
|
21059
21074
|
const fp = priorsForFile(store, relPath);
|
|
21060
21075
|
const priors = fp ? {
|
|
21061
21076
|
openProblems: fp.openProblems.slice(0, 3).map((p) => ({ id: p.id, description: p.description })),
|
|
21077
|
+
constraints: fp.constraints.slice(0, 2).map((c) => ({ id: c.id, description: c.description })),
|
|
21062
21078
|
related: fp.related.slice(0, 4).map((n) => ({ id: n.id, label: n.label, description: n.description })),
|
|
21063
21079
|
solutionsByProblem: Object.fromEntries(
|
|
21064
21080
|
fp.openProblems.slice(0, 3).map((p) => [
|
|
@@ -21153,7 +21169,7 @@ function renderSnapshot(s) {
|
|
|
21153
21169
|
}
|
|
21154
21170
|
const tagOf = (n) => s.edgeElicitation ? ` \`[${priorHandle(n)}]\`` : "";
|
|
21155
21171
|
lines.push("### Recently observed problems in this workspace");
|
|
21156
|
-
if (s.recentProblems.length === 0 && s.recentResolved.length === 0) {
|
|
21172
|
+
if (s.recentProblems.length === 0 && s.recentResolved.length === 0 && s.recentConstraints.length === 0) {
|
|
21157
21173
|
lines.push("- _none yet \u2014 errata is still building its model_");
|
|
21158
21174
|
} else {
|
|
21159
21175
|
if (s.recentProblems.length > 0) {
|
|
@@ -21175,6 +21191,12 @@ function renderSnapshot(s) {
|
|
|
21175
21191
|
);
|
|
21176
21192
|
}
|
|
21177
21193
|
}
|
|
21194
|
+
if (s.recentConstraints.length > 0) {
|
|
21195
|
+
lines.push("_Design tensions \u2014 constraints this work is shaped around, not defects to fix:_");
|
|
21196
|
+
for (const c of s.recentConstraints) {
|
|
21197
|
+
lines.push(`- \u2696 **${c.description}** \u2014 \`${c.id}\`${tagOf(c)}`);
|
|
21198
|
+
}
|
|
21199
|
+
}
|
|
21178
21200
|
if (s.recentResolved.length > 0) {
|
|
21179
21201
|
lines.push("_Recently resolved \u2014 solved here; jumping-off points, not live defects:_");
|
|
21180
21202
|
for (const r of s.recentResolved) {
|
|
@@ -21242,6 +21264,14 @@ function renderSnapshot(s) {
|
|
|
21242
21264
|
}
|
|
21243
21265
|
}
|
|
21244
21266
|
}
|
|
21267
|
+
if (w.priors?.constraints.length) {
|
|
21268
|
+
lines.push(
|
|
21269
|
+
"- **Design tensions here** \u2014 standing constraints this code is shaped around. They are NOT open work and a change does not resolve one, so there is no `(fix:)` token; cite one you worked within with `([id])`:"
|
|
21270
|
+
);
|
|
21271
|
+
for (const c of w.priors.constraints) {
|
|
21272
|
+
lines.push(` - ${c.description} \u2192 \`([${c.id}])\``);
|
|
21273
|
+
}
|
|
21274
|
+
}
|
|
21245
21275
|
if (w.priors?.related.length) {
|
|
21246
21276
|
lines.push("- **Related priors** (cite with `([id])` where you lean on one):");
|
|
21247
21277
|
for (const n of w.priors.related) {
|
|
@@ -21279,6 +21309,9 @@ function dropLowestUnit(s) {
|
|
|
21279
21309
|
case "pendingEnrichment":
|
|
21280
21310
|
if (s.pendingEnrichment.length) return s.pendingEnrichment.pop(), true;
|
|
21281
21311
|
break;
|
|
21312
|
+
case "recentConstraints":
|
|
21313
|
+
if (s.recentConstraints.length) return s.recentConstraints.pop(), true;
|
|
21314
|
+
break;
|
|
21282
21315
|
case "recentProblems":
|
|
21283
21316
|
if (s.recentProblems.length) return s.recentProblems.pop(), true;
|
|
21284
21317
|
break;
|
|
@@ -21350,6 +21383,9 @@ ${RECALL_FIRST_BODY}`;
|
|
|
21350
21383
|
// budget they drop before anything open/actionable.
|
|
21351
21384
|
"recentResolved",
|
|
21352
21385
|
"pendingEnrichment",
|
|
21386
|
+
// A standing design tension outranks an enrichment nudge (it prevents a wrong
|
|
21387
|
+
// decision) but yields to a live defect (which is actionable now).
|
|
21388
|
+
"recentConstraints",
|
|
21353
21389
|
"recentProblems",
|
|
21354
21390
|
"needsRevisit"
|
|
21355
21391
|
];
|
|
@@ -26475,6 +26511,7 @@ function mergeProblemsByEmbedding(store, opts) {
|
|
|
26475
26511
|
if (b.id === a.id || consumed.has(b.id)) continue;
|
|
26476
26512
|
if (b.embedding.length !== a.embedding.length) continue;
|
|
26477
26513
|
if ((a.attrs["embeddingVersion"] ?? "") !== (b.attrs["embeddingVersion"] ?? "")) continue;
|
|
26514
|
+
if (isConstraintProblem(a) !== isConstraintProblem(b)) continue;
|
|
26478
26515
|
if (cosine(a.embedding, b.embedding) >= minCosine) {
|
|
26479
26516
|
cluster.push(b);
|
|
26480
26517
|
consumed.add(b.id);
|
|
@@ -37711,11 +37748,11 @@ var init_mcp = __esm({
|
|
|
37711
37748
|
},
|
|
37712
37749
|
{
|
|
37713
37750
|
name: "errata.problems",
|
|
37714
|
-
description: "List the workspace's Problem backlog \u2014 the triage view that search/why/impact can't give because they need a seed. status: 'open' (default) | 'resolved' (a real fix) | 'retracted' (false alarms \u2014 false_positive/dissolution) | 'all'. Also returns a `retracted` breakdown so the false-positive rate stays visible.",
|
|
37751
|
+
description: "List the workspace's Problem backlog \u2014 the triage view that search/why/impact can't give because they need a seed. status: 'open' (default) | 'resolved' (a real fix) | 'retracted' (false alarms \u2014 false_positive/dissolution) | 'constraint' (design TENSIONS captured via `(constraint: \u2026)` \u2014 standing context, not open work, so they're excluded from 'open') | 'all'. Also returns a `retracted` breakdown so the false-positive rate stays visible.",
|
|
37715
37752
|
inputSchema: {
|
|
37716
37753
|
type: "object",
|
|
37717
37754
|
properties: {
|
|
37718
|
-
status: { type: "string", description: "open | resolved | retracted | all (default open)" },
|
|
37755
|
+
status: { type: "string", description: "open | resolved | retracted | constraint | all (default open)" },
|
|
37719
37756
|
limit: { type: "number" }
|
|
37720
37757
|
}
|
|
37721
37758
|
},
|
|
@@ -37725,7 +37762,7 @@ var init_mcp = __esm({
|
|
|
37725
37762
|
const RETRACTIONS = /* @__PURE__ */ new Set(["false_positive", "invalid", "duplicate"]);
|
|
37726
37763
|
const rows = store.findAllVersionsByLabel("Problem").map((p) => {
|
|
37727
37764
|
const ra = p.attrs["resolvedAs"];
|
|
37728
|
-
const status = ra && RETRACTIONS.has(ra) ? ra : p.attrs["resolvedAt"] != null ? "resolved" : "open";
|
|
37765
|
+
const status = ra && RETRACTIONS.has(ra) ? ra : p.attrs["resolvedAt"] != null ? "resolved" : isConstraintProblem(p) ? "constraint" : "open";
|
|
37729
37766
|
const anchorEdge = store.outEdges(p.id, ["ANCHORED_AT"])[0];
|
|
37730
37767
|
const anchor = anchorEdge ? store.getNode(anchorEdge.to)?.description : void 0;
|
|
37731
37768
|
return {
|
|
@@ -37733,17 +37770,21 @@ var init_mcp = __esm({
|
|
|
37733
37770
|
problem: p.description,
|
|
37734
37771
|
status,
|
|
37735
37772
|
createdAt: p.createdAt,
|
|
37773
|
+
// Surfaced even when `status` is resolved/retracted, so a caller can tell
|
|
37774
|
+
// an explicitly-discharged TENSION from a fixed defect.
|
|
37775
|
+
...isConstraintProblem(p) ? { kind: "constraint" } : {},
|
|
37736
37776
|
...p.attrs["provisional"] ? { provisional: true } : {},
|
|
37737
37777
|
...p.attrs["resolvedReason"] ? { reason: String(p.attrs["resolvedReason"]) } : {},
|
|
37738
37778
|
...anchor ? { anchor } : {}
|
|
37739
37779
|
};
|
|
37740
37780
|
});
|
|
37741
|
-
const inScope = (s) => want === "all" ? true : want === "resolved" ? s === "resolved" : want === "retracted" ? RETRACTIONS.has(s) : s === "open";
|
|
37781
|
+
const inScope = (s) => want === "all" ? true : want === "resolved" ? s === "resolved" : want === "retracted" ? RETRACTIONS.has(s) : want === "constraint" ? s === "constraint" : s === "open";
|
|
37742
37782
|
const items = rows.filter((r) => inScope(r.status)).sort((a, b) => b.createdAt - a.createdAt).slice(0, limit);
|
|
37743
37783
|
const countBy = (s) => rows.filter((r) => r.status === s).length;
|
|
37744
37784
|
return {
|
|
37745
37785
|
open: countBy("open"),
|
|
37746
37786
|
resolved: countBy("resolved"),
|
|
37787
|
+
constraints: countBy("constraint"),
|
|
37747
37788
|
retracted: {
|
|
37748
37789
|
falsePositive: countBy("false_positive"),
|
|
37749
37790
|
dissolution: countBy("invalid"),
|
|
@@ -37832,7 +37873,8 @@ var init_mcp = __esm({
|
|
|
37832
37873
|
inputSchema: { type: "object", properties: {} },
|
|
37833
37874
|
handler: (_args, store) => {
|
|
37834
37875
|
const problems = store.findNodesByLabel("Problem");
|
|
37835
|
-
const open2 = problems.filter((p) => p.attrs["resolvedAt"] == null);
|
|
37876
|
+
const open2 = problems.filter((p) => p.attrs["resolvedAt"] == null && !isConstraintProblem(p));
|
|
37877
|
+
const constraints = problems.filter((p) => p.attrs["resolvedAt"] == null && isConstraintProblem(p));
|
|
37836
37878
|
const noFix = open2.filter((p) => store.outEdges(p.id, ["SOLVED_BY"]).length === 0);
|
|
37837
37879
|
const allProblems = store.findAllVersionsByLabel("Problem");
|
|
37838
37880
|
const ungroundedDerived = store.findNodesByLabel("Claim").filter((c) => c.attrs["crystallized"] === "derived" && Number(c.attrs["groundedSupport"] ?? 0) === 0);
|
|
@@ -37842,6 +37884,7 @@ var init_mcp = __esm({
|
|
|
37842
37884
|
strandedSymbols: findStrandedSymbols(store).length,
|
|
37843
37885
|
openProblems: open2.length,
|
|
37844
37886
|
openProblemsWithoutFix: noFix.length,
|
|
37887
|
+
designConstraints: constraints.length,
|
|
37845
37888
|
retractedFalsePositive: allProblems.filter((p) => p.attrs["resolvedAs"] === "false_positive").length,
|
|
37846
37889
|
retractedDissolution: allProblems.filter((p) => p.attrs["resolvedAs"] === "invalid").length,
|
|
37847
37890
|
ungroundedDerivedClaims: ungroundedDerived.length,
|
|
@@ -38413,7 +38456,7 @@ function formatProblemsMd(r) {
|
|
|
38413
38456
|
const lines = [head("problems")];
|
|
38414
38457
|
const ret = r.retracted ?? { falsePositive: 0, dissolution: 0, duplicate: 0 };
|
|
38415
38458
|
lines.push(
|
|
38416
|
-
`open ${r.open} \xB7 resolved ${r.resolved} \xB7 retracted: ${ret.falsePositive} fp / ${ret.dissolution} dissolution / ${ret.duplicate} dup`
|
|
38459
|
+
`open ${r.open} \xB7 resolved ${r.resolved}` + (r.constraints ? ` \xB7 constraints ${r.constraints}` : "") + ` \xB7 retracted: ${ret.falsePositive} fp / ${ret.dissolution} dissolution / ${ret.duplicate} dup`
|
|
38417
38460
|
);
|
|
38418
38461
|
lines.push(`showing ${r.count}`);
|
|
38419
38462
|
lines.push("");
|
|
@@ -46151,10 +46194,13 @@ function recallForFile(store, relPath) {
|
|
|
46151
46194
|
recallLine(p, `${TAG_EXAMPLE.fix(p.id)} if you resolved it \xB7 ${TAG_EXAMPLE.prior(p.id)} to cite${causeCue}`)
|
|
46152
46195
|
);
|
|
46153
46196
|
}
|
|
46197
|
+
for (const c of priors.constraints.slice(0, 2)) {
|
|
46198
|
+
lines.push(recallLine(c, `design tension \u2014 hold it, don't "fix" it \xB7 ${TAG_EXAMPLE.prior(c.id)} to cite`));
|
|
46199
|
+
}
|
|
46154
46200
|
for (const n of priors.related.slice(0, 4)) {
|
|
46155
46201
|
lines.push(recallLine(n, `cite with ${TAG_EXAMPLE.prior(n.id)}`));
|
|
46156
46202
|
}
|
|
46157
|
-
const total = priors.openProblems.length + priors.related.length;
|
|
46203
|
+
const total = priors.openProblems.length + priors.constraints.length + priors.related.length;
|
|
46158
46204
|
return `errata \u2014 ${total} prior(s) recorded on this file (act only if relevant):
|
|
46159
46205
|
${lines.join("\n")}
|
|
46160
46206
|
` + buildFileRecallInstruction();
|
|
@@ -47126,12 +47172,12 @@ var init_report_render = __esm({
|
|
|
47126
47172
|
|
|
47127
47173
|
// src/cli.ts
|
|
47128
47174
|
init_src5();
|
|
47129
|
-
import { closeSync as closeSync2, existsSync as
|
|
47130
|
-
import { join as
|
|
47175
|
+
import { closeSync as closeSync2, existsSync as existsSync25, openSync as openSync2, readFileSync as readFileSync23, renameSync as renameSync3, statSync as statSync6 } from "node:fs";
|
|
47176
|
+
import { join as join27 } from "node:path";
|
|
47131
47177
|
import { spawn as spawn3 } from "node:child_process";
|
|
47132
47178
|
|
|
47133
47179
|
// src/daemon.ts
|
|
47134
|
-
import { existsSync as
|
|
47180
|
+
import { existsSync as existsSync20, writeFileSync as writeFileSync16 } from "node:fs";
|
|
47135
47181
|
|
|
47136
47182
|
// ../../node_modules/.pnpm/@hono+node-server@1.19.11_hono@4.12.8/node_modules/@hono/node-server/dist/index.mjs
|
|
47137
47183
|
import { createServer as createServerHTTP } from "http";
|
|
@@ -47711,8 +47757,8 @@ init_config();
|
|
|
47711
47757
|
|
|
47712
47758
|
// src/engine.ts
|
|
47713
47759
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
47714
|
-
import { existsSync as
|
|
47715
|
-
import { join as
|
|
47760
|
+
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";
|
|
47761
|
+
import { join as join23, relative as relative6, sep as sep4 } from "node:path";
|
|
47716
47762
|
|
|
47717
47763
|
// ../../node_modules/.pnpm/chokidar@4.0.3/node_modules/chokidar/esm/index.js
|
|
47718
47764
|
import { stat as statcb } from "fs";
|
|
@@ -50204,7 +50250,7 @@ function harvestInlineTags(store, text, opts) {
|
|
|
50204
50250
|
const touched = opts.sessionTouchedIds ?? /* @__PURE__ */ new Set();
|
|
50205
50251
|
const plan = { priorEdges: 0, problems: [], fixes: [], triages: [], attempts: [], unresolvedFixes: [], transfers: [], solutionLinks: [], instances: [], patterns: [], domains: [], packages: [], components: [], refutes: [], corroborations: [] };
|
|
50206
50252
|
const tags = parseInlineTags(text);
|
|
50207
|
-
const symptomSeqs = tags.filter((t) => (t.kind === "problem" || t.kind === "todo"
|
|
50253
|
+
const symptomSeqs = tags.filter((t) => (t.kind === "problem" || t.kind === "todo") && t.statement).map((t) => ({ seq: t.seq ?? -1, statement: t.statement, threadId: t.threadId })).sort((a, b) => a.seq - b.seq);
|
|
50208
50254
|
const bindSymptom = (seq, threadId) => {
|
|
50209
50255
|
if (threadId) {
|
|
50210
50256
|
const hit = symptomSeqs.find((s) => s.threadId === threadId);
|
|
@@ -50234,7 +50280,7 @@ function harvestInlineTags(store, text, opts) {
|
|
|
50234
50280
|
...tag.threadId ? { threadId: tag.threadId } : {}
|
|
50235
50281
|
});
|
|
50236
50282
|
} else if (tag.kind === "constraint") {
|
|
50237
|
-
plan.problems.push({ statement: tag.statement, kind: "
|
|
50283
|
+
plan.problems.push({ statement: tag.statement, kind: "constraint" });
|
|
50238
50284
|
} else if (tag.kind === "fix") {
|
|
50239
50285
|
if (tag.handle) {
|
|
50240
50286
|
const problemId = resolveHandle(store, tag.handle, opts.handleMap);
|
|
@@ -50454,7 +50500,10 @@ function parseRollupJson(text) {
|
|
|
50454
50500
|
...str("cause") ? { cause: str("cause") } : {},
|
|
50455
50501
|
...str("fix") ? { fix: str("fix") } : {},
|
|
50456
50502
|
...str("anchor") ? { anchor: str("anchor") } : {},
|
|
50457
|
-
|
|
50503
|
+
// Preserve `constraint` (GH-constraint-kind) — collapsing it to `problem`
|
|
50504
|
+
// here would re-arm the auto-close and the inferred fix-binding on a design
|
|
50505
|
+
// tension that arrived through the rollup path instead of the inline tag.
|
|
50506
|
+
kind: o["kind"] === "todo" ? "todo" : o["kind"] === "constraint" ? "constraint" : "problem"
|
|
50458
50507
|
});
|
|
50459
50508
|
}
|
|
50460
50509
|
return flags2.slice(0, 12);
|
|
@@ -50492,6 +50541,147 @@ ${conversation}` }]
|
|
|
50492
50541
|
};
|
|
50493
50542
|
}
|
|
50494
50543
|
|
|
50544
|
+
// src/constraint-backfill.ts
|
|
50545
|
+
init_src4();
|
|
50546
|
+
init_src2();
|
|
50547
|
+
import { existsSync as existsSync13, readFileSync as readFileSync11, readdirSync as readdirSync6, writeFileSync as writeFileSync11 } from "node:fs";
|
|
50548
|
+
import { join as join16 } from "node:path";
|
|
50549
|
+
import { homedir as homedir4 } from "node:os";
|
|
50550
|
+
var BACKFILL_VERSION = 1;
|
|
50551
|
+
var EMPTY = {
|
|
50552
|
+
skipped: true,
|
|
50553
|
+
stamped: 0,
|
|
50554
|
+
detached: 0,
|
|
50555
|
+
reopened: 0,
|
|
50556
|
+
witnessed: 0,
|
|
50557
|
+
cloudTwins: []
|
|
50558
|
+
};
|
|
50559
|
+
function markerPath(configDir) {
|
|
50560
|
+
return join16(configDir, "constraint-backfill.json");
|
|
50561
|
+
}
|
|
50562
|
+
function alreadyDone(configDir) {
|
|
50563
|
+
const p = markerPath(configDir);
|
|
50564
|
+
if (!existsSync13(p)) return false;
|
|
50565
|
+
try {
|
|
50566
|
+
const raw2 = JSON.parse(readFileSync11(p, "utf8"));
|
|
50567
|
+
return raw2?.version === BACKFILL_VERSION;
|
|
50568
|
+
} catch {
|
|
50569
|
+
return false;
|
|
50570
|
+
}
|
|
50571
|
+
}
|
|
50572
|
+
function replay(root) {
|
|
50573
|
+
const statements = /* @__PURE__ */ new Set();
|
|
50574
|
+
const citedByFix = /* @__PURE__ */ new Set();
|
|
50575
|
+
const dir = claudeProjectDir(root, homedir4());
|
|
50576
|
+
if (!existsSync13(dir)) return { statements, citedByFix };
|
|
50577
|
+
let names;
|
|
50578
|
+
try {
|
|
50579
|
+
names = readdirSync6(dir).filter((n) => n.endsWith(".jsonl"));
|
|
50580
|
+
} catch {
|
|
50581
|
+
return { statements, citedByFix };
|
|
50582
|
+
}
|
|
50583
|
+
for (const f of names) {
|
|
50584
|
+
let lines;
|
|
50585
|
+
try {
|
|
50586
|
+
lines = readFileSync11(join16(dir, f), "utf8").split("\n");
|
|
50587
|
+
} catch {
|
|
50588
|
+
continue;
|
|
50589
|
+
}
|
|
50590
|
+
for (const line of lines) {
|
|
50591
|
+
if (!line.trim()) continue;
|
|
50592
|
+
let rec;
|
|
50593
|
+
try {
|
|
50594
|
+
rec = JSON.parse(line);
|
|
50595
|
+
} catch {
|
|
50596
|
+
continue;
|
|
50597
|
+
}
|
|
50598
|
+
if (rec.type !== "assistant" || !Array.isArray(rec.message?.content)) continue;
|
|
50599
|
+
for (const b of rec.message.content) {
|
|
50600
|
+
if (b?.type !== "text" || typeof b.text !== "string") continue;
|
|
50601
|
+
for (const tag of parseInlineTags(b.text)) {
|
|
50602
|
+
if (tag.kind === "constraint" && tag.statement) statements.add(tag.statement);
|
|
50603
|
+
if (tag.kind === "fix") {
|
|
50604
|
+
const t = tag;
|
|
50605
|
+
if (t.handle) citedByFix.add(t.handle);
|
|
50606
|
+
if (t.threadId) citedByFix.add(t.threadId);
|
|
50607
|
+
}
|
|
50608
|
+
}
|
|
50609
|
+
}
|
|
50610
|
+
}
|
|
50611
|
+
}
|
|
50612
|
+
return { statements, citedByFix };
|
|
50613
|
+
}
|
|
50614
|
+
function backfillConstraintKind(store, opts) {
|
|
50615
|
+
if (!opts.force && !opts.dryRun && alreadyDone(opts.configDir)) return EMPTY;
|
|
50616
|
+
const { statements, citedByFix } = replay(opts.root);
|
|
50617
|
+
const report = {
|
|
50618
|
+
skipped: false,
|
|
50619
|
+
stamped: 0,
|
|
50620
|
+
detached: 0,
|
|
50621
|
+
reopened: 0,
|
|
50622
|
+
witnessed: 0,
|
|
50623
|
+
cloudTwins: []
|
|
50624
|
+
};
|
|
50625
|
+
const seen = /* @__PURE__ */ new Set();
|
|
50626
|
+
const work = [];
|
|
50627
|
+
for (const statement of statements) {
|
|
50628
|
+
const id = designProblemId(statement);
|
|
50629
|
+
if (seen.has(id)) continue;
|
|
50630
|
+
seen.add(id);
|
|
50631
|
+
const node2 = store.getNode(id);
|
|
50632
|
+
if (!node2 || node2.label !== "Problem") continue;
|
|
50633
|
+
const isWitnessed = citedByFix.has(priorHandle(node2)) || citedByFix.has(id) || [...citedByFix].some((c) => c && id.startsWith(c));
|
|
50634
|
+
const fabricated = [];
|
|
50635
|
+
for (const e of store.outEdges(id, ["SOLVED_BY"])) {
|
|
50636
|
+
const sol = store.getNode(e.to);
|
|
50637
|
+
if (!sol) continue;
|
|
50638
|
+
const auto = sol.description.startsWith(AUTO_MINT_PREFIX);
|
|
50639
|
+
if (!auto && isWitnessed) report.witnessed++;
|
|
50640
|
+
else fabricated.push(sol.id);
|
|
50641
|
+
}
|
|
50642
|
+
const stamp = node2.attrs["kind"] !== "constraint";
|
|
50643
|
+
if (stamp) report.stamped++;
|
|
50644
|
+
if (fabricated.length > 0) {
|
|
50645
|
+
report.detached += fabricated.length;
|
|
50646
|
+
report.reopened++;
|
|
50647
|
+
}
|
|
50648
|
+
const cloudNodeId = node2.attrs["cloudNodeId"];
|
|
50649
|
+
if (typeof cloudNodeId === "string" && (stamp || fabricated.length > 0)) {
|
|
50650
|
+
report.cloudTwins.push(cloudNodeId);
|
|
50651
|
+
}
|
|
50652
|
+
if (stamp || fabricated.length > 0) work.push({ id, fabricated, stamp });
|
|
50653
|
+
}
|
|
50654
|
+
if (opts.dryRun) return report;
|
|
50655
|
+
store.transaction(() => {
|
|
50656
|
+
for (const w of work) {
|
|
50657
|
+
const node2 = store.getNode(w.id);
|
|
50658
|
+
if (!node2) continue;
|
|
50659
|
+
const attrs = { ...node2.attrs, kind: "constraint" };
|
|
50660
|
+
if (w.fabricated.length > 0) {
|
|
50661
|
+
delete attrs["resolvedAt"];
|
|
50662
|
+
delete attrs["resolvedReason"];
|
|
50663
|
+
}
|
|
50664
|
+
store.updateNode(w.id, { attrs, lastUpdatedAt: opts.now });
|
|
50665
|
+
for (const solId of w.fabricated) {
|
|
50666
|
+
for (const e of store.outEdges(w.id, ["SOLVED_BY"])) {
|
|
50667
|
+
if (e.to === solId) store.closeEdge(e.id, opts.now);
|
|
50668
|
+
}
|
|
50669
|
+
const sol = store.getNode(solId);
|
|
50670
|
+
if (sol?.description.startsWith(AUTO_MINT_PREFIX)) store.closeNode(solId, opts.now);
|
|
50671
|
+
}
|
|
50672
|
+
}
|
|
50673
|
+
});
|
|
50674
|
+
try {
|
|
50675
|
+
writeFileSync11(
|
|
50676
|
+
markerPath(opts.configDir),
|
|
50677
|
+
JSON.stringify({ version: BACKFILL_VERSION, at: opts.now, ...report, cloudTwins: report.cloudTwins.length }, null, 2),
|
|
50678
|
+
"utf8"
|
|
50679
|
+
);
|
|
50680
|
+
} catch {
|
|
50681
|
+
}
|
|
50682
|
+
return report;
|
|
50683
|
+
}
|
|
50684
|
+
|
|
50495
50685
|
// src/engine.ts
|
|
50496
50686
|
init_symbol_summaries();
|
|
50497
50687
|
init_reconcile();
|
|
@@ -50690,11 +50880,11 @@ init_outbox();
|
|
|
50690
50880
|
init_src8();
|
|
50691
50881
|
init_src();
|
|
50692
50882
|
init_src2();
|
|
50693
|
-
import { readFileSync as
|
|
50694
|
-
import { join as
|
|
50883
|
+
import { readFileSync as readFileSync12 } from "node:fs";
|
|
50884
|
+
import { join as join17 } from "node:path";
|
|
50695
50885
|
function loadClaimIgnorePatterns(workspaceRoot) {
|
|
50696
50886
|
try {
|
|
50697
|
-
return
|
|
50887
|
+
return readFileSync12(join17(workspaceRoot, ".errataignore"), "utf8").split(/\r?\n/).map((l) => l.trim()).filter((l) => l.length > 0 && !l.startsWith("#")).map((l) => l.toLowerCase());
|
|
50698
50888
|
} catch {
|
|
50699
50889
|
return [];
|
|
50700
50890
|
}
|
|
@@ -51055,22 +51245,22 @@ async function pullCloudTriage(shared, cloud, profile, limit = 50) {
|
|
|
51055
51245
|
}
|
|
51056
51246
|
|
|
51057
51247
|
// src/git-sensor.ts
|
|
51058
|
-
import { existsSync as
|
|
51059
|
-
import { join as
|
|
51248
|
+
import { existsSync as existsSync14, readFileSync as readFileSync13, watch as fsWatch } from "node:fs";
|
|
51249
|
+
import { join as join18 } from "node:path";
|
|
51060
51250
|
function readFirstLine(path2) {
|
|
51061
51251
|
try {
|
|
51062
|
-
return
|
|
51252
|
+
return readFileSync13(path2, "utf8").split(/\r?\n/, 1)[0].trim();
|
|
51063
51253
|
} catch {
|
|
51064
51254
|
return null;
|
|
51065
51255
|
}
|
|
51066
51256
|
}
|
|
51067
51257
|
function readGitRefState(gitDir) {
|
|
51068
|
-
const head2 = readFirstLine(
|
|
51258
|
+
const head2 = readFirstLine(join18(gitDir, "HEAD"));
|
|
51069
51259
|
const m = head2 ? /^ref:\s*refs\/heads\/(.+)$/.exec(head2) : null;
|
|
51070
51260
|
const branch = m ? m[1] : null;
|
|
51071
51261
|
let sha2 = null;
|
|
51072
51262
|
if (branch) {
|
|
51073
|
-
sha2 = readFirstLine(
|
|
51263
|
+
sha2 = readFirstLine(join18(gitDir, "refs", "heads", branch));
|
|
51074
51264
|
if (!sha2) sha2 = shaFromPackedRefs(gitDir, `refs/heads/${branch}`);
|
|
51075
51265
|
} else if (head2 && /^[0-9a-f]{7,40}$/i.test(head2)) {
|
|
51076
51266
|
sha2 = head2;
|
|
@@ -51078,13 +51268,13 @@ function readGitRefState(gitDir) {
|
|
|
51078
51268
|
return {
|
|
51079
51269
|
branch,
|
|
51080
51270
|
sha: sha2,
|
|
51081
|
-
mergeHeadExists:
|
|
51082
|
-
origHeadExists:
|
|
51271
|
+
mergeHeadExists: existsSync14(join18(gitDir, "MERGE_HEAD")),
|
|
51272
|
+
origHeadExists: existsSync14(join18(gitDir, "ORIG_HEAD"))
|
|
51083
51273
|
};
|
|
51084
51274
|
}
|
|
51085
51275
|
function shaFromPackedRefs(gitDir, ref) {
|
|
51086
51276
|
try {
|
|
51087
|
-
for (const line of
|
|
51277
|
+
for (const line of readFileSync13(join18(gitDir, "packed-refs"), "utf8").split(/\r?\n/)) {
|
|
51088
51278
|
const [sha2, name2] = line.split(/\s+/);
|
|
51089
51279
|
if (name2 === ref && sha2) return sha2;
|
|
51090
51280
|
}
|
|
@@ -51118,7 +51308,7 @@ function startGitSensor(gitDir, onEvent, opts = {}) {
|
|
|
51118
51308
|
const settle = () => {
|
|
51119
51309
|
if (timer) clearTimeout(timer);
|
|
51120
51310
|
timer = setTimeout(() => {
|
|
51121
|
-
if (
|
|
51311
|
+
if (existsSync14(join18(gitDir, "index.lock"))) {
|
|
51122
51312
|
settle();
|
|
51123
51313
|
return;
|
|
51124
51314
|
}
|
|
@@ -51129,7 +51319,7 @@ function startGitSensor(gitDir, onEvent, opts = {}) {
|
|
|
51129
51319
|
}, debounceMs);
|
|
51130
51320
|
};
|
|
51131
51321
|
for (const sub of ["HEAD", "logs/HEAD", "MERGE_HEAD", "ORIG_HEAD"]) {
|
|
51132
|
-
const p =
|
|
51322
|
+
const p = join18(gitDir, sub);
|
|
51133
51323
|
try {
|
|
51134
51324
|
watchers.push(fsWatch(p, settle));
|
|
51135
51325
|
} catch {
|
|
@@ -51354,21 +51544,21 @@ var TelemetryRecorder = class {
|
|
|
51354
51544
|
|
|
51355
51545
|
// src/skills.ts
|
|
51356
51546
|
import {
|
|
51357
|
-
existsSync as
|
|
51547
|
+
existsSync as existsSync15,
|
|
51358
51548
|
mkdirSync as mkdirSync6,
|
|
51359
|
-
readFileSync as
|
|
51360
|
-
readdirSync as
|
|
51549
|
+
readFileSync as readFileSync14,
|
|
51550
|
+
readdirSync as readdirSync7,
|
|
51361
51551
|
unlinkSync as unlinkSync2,
|
|
51362
|
-
writeFileSync as
|
|
51552
|
+
writeFileSync as writeFileSync12
|
|
51363
51553
|
} from "node:fs";
|
|
51364
|
-
import { basename as basename4, join as
|
|
51554
|
+
import { basename as basename4, join as join19 } from "node:path";
|
|
51365
51555
|
function skillFileName(id) {
|
|
51366
51556
|
return `${id.replace(/[^A-Za-z0-9_.-]/g, "_")}.md`;
|
|
51367
51557
|
}
|
|
51368
51558
|
function readSkillManifest(manifestPath) {
|
|
51369
|
-
if (!
|
|
51559
|
+
if (!existsSync15(manifestPath)) return [];
|
|
51370
51560
|
try {
|
|
51371
|
-
const parsed = JSON.parse(
|
|
51561
|
+
const parsed = JSON.parse(readFileSync14(manifestPath, "utf8"));
|
|
51372
51562
|
return (parsed.skills ?? []).map((s) => ({
|
|
51373
51563
|
title: s.title ?? "",
|
|
51374
51564
|
layer: s.layer ?? "technique",
|
|
@@ -51384,7 +51574,7 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
|
|
|
51384
51574
|
const staleDaemon = res.staleDaemon && res.latestDaemonVersion ? { latest: res.latestDaemonVersion } : void 0;
|
|
51385
51575
|
mkdirSync6(paths.skillsDir, { recursive: true });
|
|
51386
51576
|
if (res.skills.length === 0 && pins.length === 0) {
|
|
51387
|
-
const existing =
|
|
51577
|
+
const existing = readdirSync7(paths.skillsDir).filter((f) => f.endsWith(".md"));
|
|
51388
51578
|
if (existing.length > 0) return { written: 0, pruned: 0, ...staleDaemon ? { staleDaemon } : {} };
|
|
51389
51579
|
}
|
|
51390
51580
|
const rows = [];
|
|
@@ -51392,7 +51582,7 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
|
|
|
51392
51582
|
for (const s of res.skills) {
|
|
51393
51583
|
const fileName = skillFileName(s.id);
|
|
51394
51584
|
keep.add(fileName);
|
|
51395
|
-
|
|
51585
|
+
writeFileSync12(join19(paths.skillsDir, fileName), s.markdown, "utf8");
|
|
51396
51586
|
rows.push({
|
|
51397
51587
|
id: s.id,
|
|
51398
51588
|
title: s.title,
|
|
@@ -51405,7 +51595,7 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
|
|
|
51405
51595
|
const fileName = skillFileName(p.id);
|
|
51406
51596
|
if (keep.has(fileName)) continue;
|
|
51407
51597
|
keep.add(fileName);
|
|
51408
|
-
|
|
51598
|
+
writeFileSync12(join19(paths.skillsDir, fileName), p.markdown, "utf8");
|
|
51409
51599
|
rows.push({
|
|
51410
51600
|
id: p.id,
|
|
51411
51601
|
title: p.title,
|
|
@@ -51415,17 +51605,17 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
|
|
|
51415
51605
|
});
|
|
51416
51606
|
}
|
|
51417
51607
|
let pruned = 0;
|
|
51418
|
-
for (const f of
|
|
51608
|
+
for (const f of readdirSync7(paths.skillsDir)) {
|
|
51419
51609
|
if (!f.endsWith(".md")) continue;
|
|
51420
51610
|
if (keep.has(basename4(f))) continue;
|
|
51421
51611
|
try {
|
|
51422
|
-
unlinkSync2(
|
|
51612
|
+
unlinkSync2(join19(paths.skillsDir, f));
|
|
51423
51613
|
pruned++;
|
|
51424
51614
|
} catch {
|
|
51425
51615
|
}
|
|
51426
51616
|
}
|
|
51427
51617
|
rows.sort((a, b) => a.id.localeCompare(b.id));
|
|
51428
|
-
|
|
51618
|
+
writeFileSync12(
|
|
51429
51619
|
paths.skillsManifest,
|
|
51430
51620
|
JSON.stringify({ generatedAt: Date.now(), skills: rows }, null, 2),
|
|
51431
51621
|
"utf8"
|
|
@@ -51437,22 +51627,22 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
|
|
|
51437
51627
|
init_src2();
|
|
51438
51628
|
import {
|
|
51439
51629
|
cpSync,
|
|
51440
|
-
existsSync as
|
|
51630
|
+
existsSync as existsSync16,
|
|
51441
51631
|
lstatSync,
|
|
51442
51632
|
mkdirSync as mkdirSync7,
|
|
51443
|
-
readFileSync as
|
|
51444
|
-
readdirSync as
|
|
51633
|
+
readFileSync as readFileSync15,
|
|
51634
|
+
readdirSync as readdirSync8,
|
|
51445
51635
|
rmSync as rmSync2,
|
|
51446
51636
|
symlinkSync,
|
|
51447
|
-
writeFileSync as
|
|
51637
|
+
writeFileSync as writeFileSync13
|
|
51448
51638
|
} from "node:fs";
|
|
51449
|
-
import { join as
|
|
51639
|
+
import { join as join20 } from "node:path";
|
|
51450
51640
|
var SKILL_NS = "errata-";
|
|
51451
51641
|
var HARNESS_SKILL_DIRS = [
|
|
51452
|
-
{ configDir: ".claude", skillsDir:
|
|
51642
|
+
{ configDir: ".claude", skillsDir: join20(".claude", "skills") },
|
|
51453
51643
|
// Cursor adopted the standard; its exact project dir is still moving — kept
|
|
51454
51644
|
// best-effort and gated on `.cursor/` presence so we never create it blind.
|
|
51455
|
-
{ configDir: ".cursor", skillsDir:
|
|
51645
|
+
{ configDir: ".cursor", skillsDir: join20(".cursor", "skills") }
|
|
51456
51646
|
];
|
|
51457
51647
|
function skillSlug(title, id) {
|
|
51458
51648
|
const base = title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || id.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "skill";
|
|
@@ -51497,12 +51687,12 @@ function skillCiteHandle(s) {
|
|
|
51497
51687
|
return priorHandle({ id: s.id, description: s.title });
|
|
51498
51688
|
}
|
|
51499
51689
|
function reconcileNamespaced(dir, keep) {
|
|
51500
|
-
if (!
|
|
51690
|
+
if (!existsSync16(dir)) return 0;
|
|
51501
51691
|
let pruned = 0;
|
|
51502
|
-
for (const name2 of
|
|
51692
|
+
for (const name2 of readdirSync8(dir)) {
|
|
51503
51693
|
if (!name2.startsWith(SKILL_NS) || keep.has(name2)) continue;
|
|
51504
51694
|
try {
|
|
51505
|
-
rmSync2(
|
|
51695
|
+
rmSync2(join20(dir, name2), { recursive: true, force: true });
|
|
51506
51696
|
pruned++;
|
|
51507
51697
|
} catch {
|
|
51508
51698
|
}
|
|
@@ -51511,7 +51701,7 @@ function reconcileNamespaced(dir, keep) {
|
|
|
51511
51701
|
}
|
|
51512
51702
|
function linkOrCopy(linkPath, target) {
|
|
51513
51703
|
try {
|
|
51514
|
-
if (
|
|
51704
|
+
if (existsSync16(linkPath) || safeLstat(linkPath)) rmSync2(linkPath, { recursive: true, force: true });
|
|
51515
51705
|
} catch {
|
|
51516
51706
|
}
|
|
51517
51707
|
try {
|
|
@@ -51532,7 +51722,7 @@ function safeLstat(p) {
|
|
|
51532
51722
|
}
|
|
51533
51723
|
}
|
|
51534
51724
|
function emitAndProjectSkills(root, skills) {
|
|
51535
|
-
const agentsSkillsDir =
|
|
51725
|
+
const agentsSkillsDir = join20(root, ".agents", "skills");
|
|
51536
51726
|
mkdirSync7(agentsSkillsDir, { recursive: true });
|
|
51537
51727
|
const slugs = [];
|
|
51538
51728
|
const keep = /* @__PURE__ */ new Set();
|
|
@@ -51540,7 +51730,7 @@ function emitAndProjectSkills(root, skills) {
|
|
|
51540
51730
|
for (const s of skills) {
|
|
51541
51731
|
let body2;
|
|
51542
51732
|
try {
|
|
51543
|
-
body2 =
|
|
51733
|
+
body2 = readFileSync15(s.bodyPath, "utf8");
|
|
51544
51734
|
} catch {
|
|
51545
51735
|
continue;
|
|
51546
51736
|
}
|
|
@@ -51549,9 +51739,9 @@ function emitAndProjectSkills(root, skills) {
|
|
|
51549
51739
|
keep.add(slug2);
|
|
51550
51740
|
slugs.push(slug2);
|
|
51551
51741
|
const description = deriveDescription(s.title, s.layer, body2);
|
|
51552
|
-
mkdirSync7(
|
|
51553
|
-
|
|
51554
|
-
|
|
51742
|
+
mkdirSync7(join20(agentsSkillsDir, slug2), { recursive: true });
|
|
51743
|
+
writeFileSync13(
|
|
51744
|
+
join20(agentsSkillsDir, slug2, "SKILL.md"),
|
|
51555
51745
|
renderSkillMd(slug2, description, body2, skillCiteHandle(s)),
|
|
51556
51746
|
"utf8"
|
|
51557
51747
|
);
|
|
@@ -51560,11 +51750,11 @@ function emitAndProjectSkills(root, skills) {
|
|
|
51560
51750
|
reconcileNamespaced(agentsSkillsDir, keep);
|
|
51561
51751
|
let projected = 0;
|
|
51562
51752
|
for (const h of HARNESS_SKILL_DIRS) {
|
|
51563
|
-
if (!
|
|
51564
|
-
const dir =
|
|
51753
|
+
if (!existsSync16(join20(root, h.configDir))) continue;
|
|
51754
|
+
const dir = join20(root, h.skillsDir);
|
|
51565
51755
|
mkdirSync7(dir, { recursive: true });
|
|
51566
51756
|
for (const slug2 of slugs) {
|
|
51567
|
-
linkOrCopy(
|
|
51757
|
+
linkOrCopy(join20(dir, slug2), join20(agentsSkillsDir, slug2));
|
|
51568
51758
|
projected++;
|
|
51569
51759
|
}
|
|
51570
51760
|
reconcileNamespaced(dir, keep);
|
|
@@ -51573,15 +51763,15 @@ function emitAndProjectSkills(root, skills) {
|
|
|
51573
51763
|
return { slugs, emitted, projected };
|
|
51574
51764
|
}
|
|
51575
51765
|
function emitInputsFromManifest(erretaDir, manifestPath) {
|
|
51576
|
-
if (!
|
|
51766
|
+
if (!existsSync16(manifestPath)) return [];
|
|
51577
51767
|
try {
|
|
51578
|
-
const parsed = JSON.parse(
|
|
51768
|
+
const parsed = JSON.parse(readFileSync15(manifestPath, "utf8"));
|
|
51579
51769
|
return (parsed.skills ?? []).filter((s) => Boolean(s.id && s.file)).map((s) => ({
|
|
51580
51770
|
id: s.id,
|
|
51581
51771
|
title: s.title ?? s.id,
|
|
51582
51772
|
layer: s.layer ?? "technique",
|
|
51583
51773
|
confidence: s.confidence ?? 0,
|
|
51584
|
-
bodyPath:
|
|
51774
|
+
bodyPath: join20(erretaDir, s.file)
|
|
51585
51775
|
}));
|
|
51586
51776
|
} catch {
|
|
51587
51777
|
return [];
|
|
@@ -51595,17 +51785,17 @@ var GITIGNORE_LINES = [
|
|
|
51595
51785
|
".cursor/skills/errata-*/"
|
|
51596
51786
|
];
|
|
51597
51787
|
function ensureSkillGitignore(root) {
|
|
51598
|
-
const path2 =
|
|
51788
|
+
const path2 = join20(root, ".gitignore");
|
|
51599
51789
|
let current = "";
|
|
51600
51790
|
try {
|
|
51601
|
-
current =
|
|
51791
|
+
current = existsSync16(path2) ? readFileSync15(path2, "utf8") : "";
|
|
51602
51792
|
} catch {
|
|
51603
51793
|
return;
|
|
51604
51794
|
}
|
|
51605
51795
|
if (current.includes(GITIGNORE_MARK)) return;
|
|
51606
51796
|
const prefix = current.length > 0 && !current.endsWith("\n") ? "\n" : "";
|
|
51607
51797
|
try {
|
|
51608
|
-
|
|
51798
|
+
writeFileSync13(path2, `${current}${prefix}
|
|
51609
51799
|
${GITIGNORE_LINES.join("\n")}
|
|
51610
51800
|
`, "utf8");
|
|
51611
51801
|
} catch {
|
|
@@ -51769,20 +51959,20 @@ var CausalBuffer = class {
|
|
|
51769
51959
|
// src/profile.ts
|
|
51770
51960
|
init_src2();
|
|
51771
51961
|
init_paths();
|
|
51772
|
-
import { existsSync as
|
|
51962
|
+
import { existsSync as existsSync18, readFileSync as readFileSync17, writeFileSync as writeFileSync14 } from "node:fs";
|
|
51773
51963
|
import { createHash as createHash12 } from "node:crypto";
|
|
51774
|
-
import { join as
|
|
51964
|
+
import { join as join22 } from "node:path";
|
|
51775
51965
|
|
|
51776
51966
|
// src/git-remote.ts
|
|
51777
51967
|
init_src();
|
|
51778
|
-
import { existsSync as
|
|
51779
|
-
import { isAbsolute as isAbsolute3, join as
|
|
51968
|
+
import { existsSync as existsSync17, readFileSync as readFileSync16, statSync as statSync4 } from "node:fs";
|
|
51969
|
+
import { isAbsolute as isAbsolute3, join as join21, resolve as resolve5 } from "node:path";
|
|
51780
51970
|
function resolveGitDir(root) {
|
|
51781
|
-
const dotGit =
|
|
51971
|
+
const dotGit = join21(root, ".git");
|
|
51782
51972
|
try {
|
|
51783
51973
|
const st = statSync4(dotGit);
|
|
51784
51974
|
if (st.isDirectory()) return dotGit;
|
|
51785
|
-
const m = /^gitdir:\s*(.+?)\s*$/m.exec(
|
|
51975
|
+
const m = /^gitdir:\s*(.+?)\s*$/m.exec(readFileSync16(dotGit, "utf8"));
|
|
51786
51976
|
if (!m) return null;
|
|
51787
51977
|
const dir = m[1];
|
|
51788
51978
|
return isAbsolute3(dir) ? dir : resolve5(root, dir);
|
|
@@ -51791,22 +51981,22 @@ function resolveGitDir(root) {
|
|
|
51791
51981
|
}
|
|
51792
51982
|
}
|
|
51793
51983
|
function gitConfigPath(gitDir) {
|
|
51794
|
-
const commondirFile =
|
|
51795
|
-
if (
|
|
51796
|
-
const common =
|
|
51984
|
+
const commondirFile = join21(gitDir, "commondir");
|
|
51985
|
+
if (existsSync17(commondirFile)) {
|
|
51986
|
+
const common = readFileSync16(commondirFile, "utf8").trim();
|
|
51797
51987
|
const commonDir = isAbsolute3(common) ? common : resolve5(gitDir, common);
|
|
51798
|
-
return
|
|
51988
|
+
return join21(commonDir, "config");
|
|
51799
51989
|
}
|
|
51800
|
-
return
|
|
51990
|
+
return join21(gitDir, "config");
|
|
51801
51991
|
}
|
|
51802
51992
|
function readRemotes(root) {
|
|
51803
51993
|
const gitDir = resolveGitDir(root);
|
|
51804
51994
|
if (!gitDir) return [];
|
|
51805
51995
|
const cfgPath = gitConfigPath(gitDir);
|
|
51806
|
-
if (!
|
|
51996
|
+
if (!existsSync17(cfgPath)) return [];
|
|
51807
51997
|
let txt;
|
|
51808
51998
|
try {
|
|
51809
|
-
txt =
|
|
51999
|
+
txt = readFileSync16(cfgPath, "utf8");
|
|
51810
52000
|
} catch {
|
|
51811
52001
|
return [];
|
|
51812
52002
|
}
|
|
@@ -51838,13 +52028,13 @@ function refreshRepoLocator(root, profile) {
|
|
|
51838
52028
|
}
|
|
51839
52029
|
function loadProfile(root) {
|
|
51840
52030
|
const p = workspacePaths(root);
|
|
51841
|
-
if (!
|
|
51842
|
-
return JSON.parse(
|
|
52031
|
+
if (!existsSync18(p.workspaceJson)) return null;
|
|
52032
|
+
return JSON.parse(readFileSync17(p.workspaceJson, "utf8"));
|
|
51843
52033
|
}
|
|
51844
52034
|
function saveProfile(root, profile) {
|
|
51845
52035
|
const p = workspacePaths(root);
|
|
51846
52036
|
ensureDir(p.configDir);
|
|
51847
|
-
|
|
52037
|
+
writeFileSync14(p.workspaceJson, JSON.stringify(profile, null, 2), "utf8");
|
|
51848
52038
|
}
|
|
51849
52039
|
function autodetectProfile(root) {
|
|
51850
52040
|
const id = workspaceId(root);
|
|
@@ -51852,10 +52042,10 @@ function autodetectProfile(root) {
|
|
|
51852
52042
|
const p = emptyProfile(id, name2);
|
|
51853
52043
|
const locator = detectRepoLocator(root);
|
|
51854
52044
|
if (locator) p.repoLocator = locator;
|
|
51855
|
-
const pkgPath =
|
|
51856
|
-
if (
|
|
52045
|
+
const pkgPath = join22(root, "package.json");
|
|
52046
|
+
if (existsSync18(pkgPath)) {
|
|
51857
52047
|
try {
|
|
51858
|
-
const pkg = JSON.parse(
|
|
52048
|
+
const pkg = JSON.parse(readFileSync17(pkgPath, "utf8"));
|
|
51859
52049
|
p.languages.push("typescript", "javascript");
|
|
51860
52050
|
const nodeVer = pkg.engines?.node ?? "node";
|
|
51861
52051
|
p.stack.push(`node@${nodeVer}`);
|
|
@@ -51876,10 +52066,10 @@ function autodetectProfile(root) {
|
|
|
51876
52066
|
} catch {
|
|
51877
52067
|
}
|
|
51878
52068
|
}
|
|
51879
|
-
const pyproject =
|
|
51880
|
-
if (
|
|
52069
|
+
const pyproject = join22(root, "pyproject.toml");
|
|
52070
|
+
if (existsSync18(pyproject)) {
|
|
51881
52071
|
try {
|
|
51882
|
-
const txt =
|
|
52072
|
+
const txt = readFileSync17(pyproject, "utf8");
|
|
51883
52073
|
const py = /python\s*=\s*"([^"]+)"/.exec(txt)?.[1];
|
|
51884
52074
|
p.languages.push("python");
|
|
51885
52075
|
p.stack.push(`python@${py ?? "3"}`);
|
|
@@ -51890,16 +52080,16 @@ function autodetectProfile(root) {
|
|
|
51890
52080
|
} catch {
|
|
51891
52081
|
}
|
|
51892
52082
|
}
|
|
51893
|
-
const reqs =
|
|
51894
|
-
if (
|
|
52083
|
+
const reqs = join22(root, "requirements.txt");
|
|
52084
|
+
if (existsSync18(reqs)) {
|
|
51895
52085
|
if (!p.languages.includes("python")) p.languages.push("python");
|
|
51896
52086
|
if (!p.stack.includes("python@3")) p.stack.push("python@3");
|
|
51897
52087
|
}
|
|
51898
|
-
if (
|
|
52088
|
+
if (existsSync18(join22(root, "go.mod"))) {
|
|
51899
52089
|
p.languages.push("go");
|
|
51900
52090
|
p.stack.push("go");
|
|
51901
52091
|
}
|
|
51902
|
-
if (
|
|
52092
|
+
if (existsSync18(join22(root, "Cargo.toml"))) {
|
|
51903
52093
|
p.languages.push("rust");
|
|
51904
52094
|
p.stack.push("rust");
|
|
51905
52095
|
}
|
|
@@ -52057,7 +52247,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
|
|
|
52057
52247
|
}
|
|
52058
52248
|
|
|
52059
52249
|
// src/engine.ts
|
|
52060
|
-
var DAEMON_VERSION = true ? "2.0.2-dev.
|
|
52250
|
+
var DAEMON_VERSION = true ? "2.0.2-dev.201" : "2.0.0-alpha.0";
|
|
52061
52251
|
var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
|
|
52062
52252
|
var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
|
|
52063
52253
|
var GIT_OP_MUTE_MS = 4e3;
|
|
@@ -52067,7 +52257,7 @@ var TURN_REPLAY_LOOKBACK_MS = 7 * 24 * 60 * 6e4;
|
|
|
52067
52257
|
function appendIdentityAudit(path2, record2, line) {
|
|
52068
52258
|
if (!record2.accepted && record2.score <= 0) return;
|
|
52069
52259
|
try {
|
|
52070
|
-
if (
|
|
52260
|
+
if (existsSync19(path2) && statSync5(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
|
|
52071
52261
|
renameSync2(path2, `${path2}.1`);
|
|
52072
52262
|
}
|
|
52073
52263
|
appendFileSync2(path2, line);
|
|
@@ -52077,14 +52267,14 @@ function appendIdentityAudit(path2, record2, line) {
|
|
|
52077
52267
|
var yieldToLoop = () => new Promise((r) => setImmediate(r));
|
|
52078
52268
|
function loadTurnCursors(path2) {
|
|
52079
52269
|
try {
|
|
52080
|
-
return new Map(Object.entries(JSON.parse(
|
|
52270
|
+
return new Map(Object.entries(JSON.parse(readFileSync18(path2, "utf8"))));
|
|
52081
52271
|
} catch {
|
|
52082
52272
|
return /* @__PURE__ */ new Map();
|
|
52083
52273
|
}
|
|
52084
52274
|
}
|
|
52085
52275
|
function saveTurnCursors(path2, cursors) {
|
|
52086
52276
|
try {
|
|
52087
|
-
|
|
52277
|
+
writeFileSync15(path2, JSON.stringify(Object.fromEntries(cursors)), "utf8");
|
|
52088
52278
|
} catch {
|
|
52089
52279
|
}
|
|
52090
52280
|
}
|
|
@@ -52106,7 +52296,7 @@ function gitSourceWatchTargets(root) {
|
|
|
52106
52296
|
["-C", root, "ls-files", "--others", "--ignored", "--exclude-standard", "--directory", "-z"],
|
|
52107
52297
|
{ encoding: "utf8", maxBuffer: 256 * 1024 * 1024, windowsHide: true, stdio: ["ignore", "pipe", "ignore"] }
|
|
52108
52298
|
);
|
|
52109
|
-
ignoredDirs = igOut.split("\0").filter(Boolean).map((d) => d.replace(/\/+$/, "")).filter((d) => !IGNORED_PATH.test(
|
|
52299
|
+
ignoredDirs = igOut.split("\0").filter(Boolean).map((d) => d.replace(/\/+$/, "")).filter((d) => !IGNORED_PATH.test(join23(root, d) + sep4));
|
|
52110
52300
|
} catch {
|
|
52111
52301
|
}
|
|
52112
52302
|
const hasIgnoredChild = (dir) => ignoredDirs.some((ig) => ig.startsWith(dir + "/"));
|
|
@@ -52118,19 +52308,19 @@ function gitSourceWatchTargets(root) {
|
|
|
52118
52308
|
if (!f.startsWith(prefix)) continue;
|
|
52119
52309
|
const rest2 = f.slice(prefix.length);
|
|
52120
52310
|
if (rest2.includes("/")) children.add(dir === "" ? rest2.slice(0, rest2.indexOf("/")) : dir + "/" + rest2.slice(0, rest2.indexOf("/")));
|
|
52121
|
-
else targets.add(
|
|
52311
|
+
else targets.add(join23(root, f));
|
|
52122
52312
|
}
|
|
52123
52313
|
for (const c of children) {
|
|
52124
|
-
if (IGNORED_PATH.test(
|
|
52314
|
+
if (IGNORED_PATH.test(join23(root, c) + sep4)) continue;
|
|
52125
52315
|
if (hasIgnoredChild(c)) addUnder(c);
|
|
52126
|
-
else targets.add(
|
|
52316
|
+
else targets.add(join23(root, c));
|
|
52127
52317
|
}
|
|
52128
52318
|
};
|
|
52129
52319
|
addUnder("");
|
|
52130
52320
|
if (targets.size > 0) return [...targets];
|
|
52131
52321
|
} catch {
|
|
52132
52322
|
}
|
|
52133
|
-
return
|
|
52323
|
+
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)));
|
|
52134
52324
|
}
|
|
52135
52325
|
function createWorkspaceEngine(opts) {
|
|
52136
52326
|
const paths = workspacePaths(opts.workspaceRoot);
|
|
@@ -52284,7 +52474,7 @@ function createWorkspaceEngine(opts) {
|
|
|
52284
52474
|
const srcPaths = diff.changedPaths.filter((p) => /\.(ts|tsx|js|jsx|mjs|cjs|py)$/i.test(p));
|
|
52285
52475
|
let episodeId2;
|
|
52286
52476
|
if (srcPaths.length > 0) {
|
|
52287
|
-
const abs = srcPaths.map((p) =>
|
|
52477
|
+
const abs = srcPaths.map((p) => join23(opts.workspaceRoot, p));
|
|
52288
52478
|
try {
|
|
52289
52479
|
const r = await runReindexPass(
|
|
52290
52480
|
`git-reindex:${profile.name} (${abs.length} files)`,
|
|
@@ -52320,8 +52510,8 @@ function createWorkspaceEngine(opts) {
|
|
|
52320
52510
|
`[errata] git: ${ev.kind} ${ev.newSha.slice(0, 7)} by ${meta3.authorName} \u2014 ${diff.changedPaths.length} file(s), ${diff.renames.length} rename(s)`
|
|
52321
52511
|
);
|
|
52322
52512
|
};
|
|
52323
|
-
const gitDir =
|
|
52324
|
-
if (
|
|
52513
|
+
const gitDir = join23(opts.workspaceRoot, ".git");
|
|
52514
|
+
if (existsSync19(gitDir)) {
|
|
52325
52515
|
stopGit = startGitSensor(gitDir, (ev) => {
|
|
52326
52516
|
void handleGitEvent(ev).catch((err2) => {
|
|
52327
52517
|
console.warn("[errata] git event handler failed:", err2);
|
|
@@ -52391,10 +52581,10 @@ function createWorkspaceEngine(opts) {
|
|
|
52391
52581
|
});
|
|
52392
52582
|
doneRender?.();
|
|
52393
52583
|
writeContextFile(opts.workspaceRoot, body2);
|
|
52394
|
-
const target =
|
|
52584
|
+
const target = join23(opts.workspaceRoot, "AGENTS.md");
|
|
52395
52585
|
writeManagedBlock(target, { body: AGENTS_POINTER_BODY, stable: true, force: true });
|
|
52396
52586
|
if (elicit) {
|
|
52397
|
-
writePrimingHandles(
|
|
52587
|
+
writePrimingHandles(join23(paths.configDir, "priming-handles.json"), [
|
|
52398
52588
|
...snapshot.recentProblems.map((r) => r.node),
|
|
52399
52589
|
// Resolved-band handles: the ✓ problem AND its Solution are citable
|
|
52400
52590
|
// (a fix tag on an already-resolved problem no-ops idempotently; the
|
|
@@ -52485,6 +52675,21 @@ function createWorkspaceEngine(opts) {
|
|
|
52485
52675
|
} catch (err2) {
|
|
52486
52676
|
console.warn("[errata] anchor backfill failed:", err2);
|
|
52487
52677
|
}
|
|
52678
|
+
try {
|
|
52679
|
+
const c = backfillConstraintKind(store, {
|
|
52680
|
+
root: opts.workspaceRoot,
|
|
52681
|
+
configDir: paths.configDir,
|
|
52682
|
+
now: Date.now()
|
|
52683
|
+
});
|
|
52684
|
+
if (!c.skipped && (c.stamped > 0 || c.detached > 0)) {
|
|
52685
|
+
console.log(
|
|
52686
|
+
`[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` : "")
|
|
52687
|
+
);
|
|
52688
|
+
refreshContextNow();
|
|
52689
|
+
}
|
|
52690
|
+
} catch (err2) {
|
|
52691
|
+
console.warn("[errata] constraint backfill failed:", err2);
|
|
52692
|
+
}
|
|
52488
52693
|
const report = runNightlyPipeline(store);
|
|
52489
52694
|
try {
|
|
52490
52695
|
const m = mergeDuplicateProblems(store, { ts: Date.now() });
|
|
@@ -52584,7 +52789,7 @@ function createWorkspaceEngine(opts) {
|
|
|
52584
52789
|
resultSummary: { exitCode: e.exitCode ?? 1, errorTokens: e.errorTokens }
|
|
52585
52790
|
});
|
|
52586
52791
|
};
|
|
52587
|
-
const turnCursorPath =
|
|
52792
|
+
const turnCursorPath = join23(paths.configDir, "turn-cursors.json");
|
|
52588
52793
|
const lastTurnUuid = loadTurnCursors(turnCursorPath);
|
|
52589
52794
|
const sessionLastProblem = /* @__PURE__ */ new Map();
|
|
52590
52795
|
const sessionThreads = /* @__PURE__ */ new Map();
|
|
@@ -52607,7 +52812,7 @@ function createWorkspaceEngine(opts) {
|
|
|
52607
52812
|
const t = Date.now();
|
|
52608
52813
|
let processedTurns = 0;
|
|
52609
52814
|
const elicit = isEdgeElicitationEnabled();
|
|
52610
|
-
const handleMap = elicit ? readPrimingHandles(
|
|
52815
|
+
const handleMap = elicit ? readPrimingHandles(join23(paths.configDir, "priming-handles.json")) : {};
|
|
52611
52816
|
const wsRoot = (opts.workspaceRoot ?? "").replace(/\\/g, "/");
|
|
52612
52817
|
const toRel = (abs) => {
|
|
52613
52818
|
const p = abs.replace(/\\/g, "/");
|
|
@@ -52649,7 +52854,7 @@ function createWorkspaceEngine(opts) {
|
|
|
52649
52854
|
ts: t
|
|
52650
52855
|
});
|
|
52651
52856
|
if (r.created || r.corroborated) minted++;
|
|
52652
|
-
sessionLastProblem.set(sessionId, designProblemId(flag.problem));
|
|
52857
|
+
if (flag.kind !== "constraint") sessionLastProblem.set(sessionId, designProblemId(flag.problem));
|
|
52653
52858
|
if (r.created || r.corroborated) {
|
|
52654
52859
|
try {
|
|
52655
52860
|
if (editedTurnFile) {
|
|
@@ -52729,11 +52934,13 @@ function createWorkspaceEngine(opts) {
|
|
|
52729
52934
|
const dedupPath = anchorPath ?? hintPath;
|
|
52730
52935
|
if (dedupPath) {
|
|
52731
52936
|
try {
|
|
52732
|
-
const dupId = reinforceSameAnchorProblem(store, dedupPath, profile.id, p.statement, sessionId, t);
|
|
52937
|
+
const dupId = reinforceSameAnchorProblem(store, dedupPath, profile.id, p.statement, sessionId, t, p.kind);
|
|
52733
52938
|
if (dupId) {
|
|
52734
52939
|
minted++;
|
|
52735
|
-
|
|
52736
|
-
|
|
52940
|
+
if (p.kind !== "constraint") {
|
|
52941
|
+
sessionLastProblem.set(sessionId, dupId);
|
|
52942
|
+
inScopeProblemId = dupId;
|
|
52943
|
+
}
|
|
52737
52944
|
if (p.threadId) threads.set(p.threadId, dupId);
|
|
52738
52945
|
continue;
|
|
52739
52946
|
}
|
|
@@ -52747,8 +52954,10 @@ function createWorkspaceEngine(opts) {
|
|
|
52747
52954
|
});
|
|
52748
52955
|
if (r.created || r.corroborated) {
|
|
52749
52956
|
minted++;
|
|
52750
|
-
|
|
52751
|
-
|
|
52957
|
+
if (p.kind !== "constraint") {
|
|
52958
|
+
sessionLastProblem.set(sessionId, designProblemId(p.statement));
|
|
52959
|
+
inScopeProblemId = designProblemId(p.statement);
|
|
52960
|
+
}
|
|
52752
52961
|
if (p.threadId) threads.set(p.threadId, designProblemId(p.statement));
|
|
52753
52962
|
try {
|
|
52754
52963
|
if (anchorPath) {
|
|
@@ -53138,7 +53347,7 @@ function createWorkspaceEngine(opts) {
|
|
|
53138
53347
|
try {
|
|
53139
53348
|
const inputs = emitInputsFromManifest(paths.configDir, paths.skillsManifest);
|
|
53140
53349
|
emitAndProjectSkills(opts.workspaceRoot, inputs);
|
|
53141
|
-
writePrimingHandles(
|
|
53350
|
+
writePrimingHandles(join23(paths.configDir, "priming-handles.json"), skillHandleNodes(inputs));
|
|
53142
53351
|
} catch (err2) {
|
|
53143
53352
|
console.warn("[skills] agent-skills projection failed (non-fatal):", err2 instanceof Error ? err2.message : err2);
|
|
53144
53353
|
}
|
|
@@ -53325,7 +53534,7 @@ function createWorkspaceEngine(opts) {
|
|
|
53325
53534
|
console.log(
|
|
53326
53535
|
"[errata] sync skipped \u2014 cloud sync consent is off (enable with `errata consent sync on`)"
|
|
53327
53536
|
);
|
|
53328
|
-
const pending =
|
|
53537
|
+
const pending = existsSync19(paths.outbox) ? readdirSync9(paths.outbox).filter((f) => f.endsWith(".json")).length : 0;
|
|
53329
53538
|
return { uploaded: 0, failed: 0, remaining: pending };
|
|
53330
53539
|
}
|
|
53331
53540
|
try {
|
|
@@ -53412,7 +53621,7 @@ async function startDaemon(opts) {
|
|
|
53412
53621
|
reviewUrl: () => webUiUrl + "/review"
|
|
53413
53622
|
});
|
|
53414
53623
|
const writeLockFile = (url2) => {
|
|
53415
|
-
|
|
53624
|
+
writeFileSync16(
|
|
53416
53625
|
engine.paths.daemonLock,
|
|
53417
53626
|
JSON.stringify({ pid: process.pid, webUiUrl: url2, startedAt: Date.now() }),
|
|
53418
53627
|
"utf8"
|
|
@@ -53455,7 +53664,7 @@ async function startDaemon(opts) {
|
|
|
53455
53664
|
);
|
|
53456
53665
|
await engine.stop();
|
|
53457
53666
|
try {
|
|
53458
|
-
if (
|
|
53667
|
+
if (existsSync20(engine.paths.daemonLock)) {
|
|
53459
53668
|
}
|
|
53460
53669
|
} catch {
|
|
53461
53670
|
}
|
|
@@ -53472,16 +53681,16 @@ async function listenServer(fetchFn, port) {
|
|
|
53472
53681
|
|
|
53473
53682
|
// src/registry.ts
|
|
53474
53683
|
init_paths();
|
|
53475
|
-
import { existsSync as
|
|
53476
|
-
import { join as
|
|
53684
|
+
import { existsSync as existsSync21, readFileSync as readFileSync19, writeFileSync as writeFileSync17 } from "node:fs";
|
|
53685
|
+
import { join as join24 } from "node:path";
|
|
53477
53686
|
function registryPath() {
|
|
53478
|
-
return process.env["ERRATA_REGISTRY_PATH"] ??
|
|
53687
|
+
return process.env["ERRATA_REGISTRY_PATH"] ?? join24(globalDir(), "workspaces.json");
|
|
53479
53688
|
}
|
|
53480
53689
|
function read() {
|
|
53481
53690
|
const p = registryPath();
|
|
53482
|
-
if (!
|
|
53691
|
+
if (!existsSync21(p)) return { version: 1, workspaces: {} };
|
|
53483
53692
|
try {
|
|
53484
|
-
const parsed = JSON.parse(
|
|
53693
|
+
const parsed = JSON.parse(readFileSync19(p, "utf8"));
|
|
53485
53694
|
return { version: 1, workspaces: parsed.workspaces ?? {} };
|
|
53486
53695
|
} catch {
|
|
53487
53696
|
return { version: 1, workspaces: {} };
|
|
@@ -53489,7 +53698,7 @@ function read() {
|
|
|
53489
53698
|
}
|
|
53490
53699
|
function write(reg) {
|
|
53491
53700
|
ensureDir(globalDir());
|
|
53492
|
-
|
|
53701
|
+
writeFileSync17(registryPath(), JSON.stringify(reg, null, 2), "utf8");
|
|
53493
53702
|
}
|
|
53494
53703
|
function registerWorkspace(profile, root, now = Date.now()) {
|
|
53495
53704
|
const reg = read();
|
|
@@ -53506,7 +53715,7 @@ function pruneMissingWorkspaces() {
|
|
|
53506
53715
|
const reg = read();
|
|
53507
53716
|
const removed = [];
|
|
53508
53717
|
for (const [id, entry] of Object.entries(reg.workspaces)) {
|
|
53509
|
-
if (!
|
|
53718
|
+
if (!existsSync21(entry.path)) {
|
|
53510
53719
|
removed.push(entry);
|
|
53511
53720
|
delete reg.workspaces[id];
|
|
53512
53721
|
}
|
|
@@ -53515,13 +53724,13 @@ function pruneMissingWorkspaces() {
|
|
|
53515
53724
|
return removed;
|
|
53516
53725
|
}
|
|
53517
53726
|
function workspaceStatus(entry) {
|
|
53518
|
-
const missing = !
|
|
53727
|
+
const missing = !existsSync21(entry.path);
|
|
53519
53728
|
const lockPath = workspacePaths(entry.path).daemonLock;
|
|
53520
53729
|
let running = false;
|
|
53521
53730
|
let webUiUrl = null;
|
|
53522
|
-
if (
|
|
53731
|
+
if (existsSync21(lockPath)) {
|
|
53523
53732
|
try {
|
|
53524
|
-
const lock = JSON.parse(
|
|
53733
|
+
const lock = JSON.parse(readFileSync19(lockPath, "utf8"));
|
|
53525
53734
|
if (lock.pid && lock.webUiUrl && pidAlive(lock.pid)) {
|
|
53526
53735
|
running = true;
|
|
53527
53736
|
webUiUrl = lock.webUiUrl;
|
|
@@ -53549,7 +53758,7 @@ function pidAlive(pid) {
|
|
|
53549
53758
|
// src/multi.ts
|
|
53550
53759
|
init_dist();
|
|
53551
53760
|
init_src4();
|
|
53552
|
-
import { readFileSync as
|
|
53761
|
+
import { readFileSync as readFileSync22, unlinkSync as unlinkSync3, writeFileSync as writeFileSync18 } from "node:fs";
|
|
53553
53762
|
|
|
53554
53763
|
// src/principle-sync.ts
|
|
53555
53764
|
init_src4();
|
|
@@ -53577,8 +53786,8 @@ init_reconcile();
|
|
|
53577
53786
|
|
|
53578
53787
|
// src/lockfile-auto.ts
|
|
53579
53788
|
init_src();
|
|
53580
|
-
import { existsSync as
|
|
53581
|
-
import { join as
|
|
53789
|
+
import { existsSync as existsSync22, readFileSync as readFileSync20 } from "node:fs";
|
|
53790
|
+
import { join as join25 } from "node:path";
|
|
53582
53791
|
|
|
53583
53792
|
// src/package-index.ts
|
|
53584
53793
|
init_src();
|
|
@@ -53724,11 +53933,11 @@ function runLockfilePass(opts) {
|
|
|
53724
53933
|
{ file: "package-lock.json", parse: parsePackageLockJson }
|
|
53725
53934
|
];
|
|
53726
53935
|
for (const c of candidates) {
|
|
53727
|
-
const p =
|
|
53728
|
-
if (!
|
|
53936
|
+
const p = join25(opts.root, c.file);
|
|
53937
|
+
if (!existsSync22(p)) continue;
|
|
53729
53938
|
let sbom;
|
|
53730
53939
|
try {
|
|
53731
|
-
sbom = c.parse(
|
|
53940
|
+
sbom = c.parse(readFileSync20(p, "utf8"));
|
|
53732
53941
|
} catch {
|
|
53733
53942
|
continue;
|
|
53734
53943
|
}
|
|
@@ -54171,7 +54380,7 @@ var ConsolidateWorker = class {
|
|
|
54171
54380
|
init_paths();
|
|
54172
54381
|
|
|
54173
54382
|
// src/lock.ts
|
|
54174
|
-
import { existsSync as
|
|
54383
|
+
import { existsSync as existsSync23, readFileSync as readFileSync21 } from "node:fs";
|
|
54175
54384
|
function isProcessAlive(pid) {
|
|
54176
54385
|
if (!pid || pid <= 0) return false;
|
|
54177
54386
|
try {
|
|
@@ -54182,9 +54391,9 @@ function isProcessAlive(pid) {
|
|
|
54182
54391
|
}
|
|
54183
54392
|
}
|
|
54184
54393
|
function readDaemonLock(lockPath) {
|
|
54185
|
-
if (!
|
|
54394
|
+
if (!existsSync23(lockPath)) return null;
|
|
54186
54395
|
try {
|
|
54187
|
-
const lock = JSON.parse(
|
|
54396
|
+
const lock = JSON.parse(readFileSync21(lockPath, "utf8"));
|
|
54188
54397
|
return typeof lock.pid === "number" ? lock : null;
|
|
54189
54398
|
} catch {
|
|
54190
54399
|
return null;
|
|
@@ -54426,12 +54635,12 @@ async function reanchorProject(opts) {
|
|
|
54426
54635
|
}
|
|
54427
54636
|
|
|
54428
54637
|
// src/adopt.ts
|
|
54429
|
-
import { existsSync as
|
|
54430
|
-
import { dirname as dirname9, join as
|
|
54638
|
+
import { existsSync as existsSync24 } from "node:fs";
|
|
54639
|
+
import { dirname as dirname9, join as join26 } from "node:path";
|
|
54431
54640
|
function findGitRoot(absPath) {
|
|
54432
54641
|
let dir = absPath;
|
|
54433
54642
|
for (let depth = 0; depth < 64; depth++) {
|
|
54434
|
-
if (
|
|
54643
|
+
if (existsSync24(join26(dir, ".git"))) return dir;
|
|
54435
54644
|
const parent = dirname9(dir);
|
|
54436
54645
|
if (parent === dir) return null;
|
|
54437
54646
|
dir = parent;
|
|
@@ -54653,7 +54862,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
54653
54862
|
void ambientLinkAll();
|
|
54654
54863
|
app.route(`/ws/${rec.id}`, rec.webApp);
|
|
54655
54864
|
try {
|
|
54656
|
-
|
|
54865
|
+
writeFileSync18(
|
|
54657
54866
|
rec.engine.paths.daemonLock,
|
|
54658
54867
|
JSON.stringify({ pid: process.pid, webUiUrl: `${baseUrl}/ws/${rec.id}`, startedAt: Date.now() }),
|
|
54659
54868
|
"utf8"
|
|
@@ -54842,7 +55051,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
54842
55051
|
baseUrl = `http://127.0.0.1:${port}`;
|
|
54843
55052
|
try {
|
|
54844
55053
|
ensureDir(globalDir());
|
|
54845
|
-
|
|
55054
|
+
writeFileSync18(
|
|
54846
55055
|
lockPath,
|
|
54847
55056
|
JSON.stringify({ pid: process.pid, webUiUrl: baseUrl, startedAt: Date.now() }),
|
|
54848
55057
|
"utf8"
|
|
@@ -54851,7 +55060,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
54851
55060
|
}
|
|
54852
55061
|
for (const r of records) {
|
|
54853
55062
|
try {
|
|
54854
|
-
|
|
55063
|
+
writeFileSync18(
|
|
54855
55064
|
r.engine.paths.daemonLock,
|
|
54856
55065
|
JSON.stringify({ pid: process.pid, webUiUrl: `${baseUrl}/ws/${r.id}`, startedAt: Date.now() }),
|
|
54857
55066
|
"utf8"
|
|
@@ -55319,7 +55528,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
55319
55528
|
},
|
|
55320
55529
|
async stop() {
|
|
55321
55530
|
try {
|
|
55322
|
-
const cur =
|
|
55531
|
+
const cur = readFileSync22(lockPath, "utf8");
|
|
55323
55532
|
if (JSON.parse(cur).pid === process.pid) unlinkSync3(lockPath);
|
|
55324
55533
|
} catch {
|
|
55325
55534
|
}
|
|
@@ -56339,21 +56548,21 @@ async function cmdInit() {
|
|
|
56339
56548
|
if (!skipHooks) {
|
|
56340
56549
|
console.log("");
|
|
56341
56550
|
console.log("installing harness hooks...");
|
|
56342
|
-
const { existsSync:
|
|
56343
|
-
const { join:
|
|
56551
|
+
const { existsSync: existsSync26 } = await import("node:fs");
|
|
56552
|
+
const { join: join28 } = await import("node:path");
|
|
56344
56553
|
try {
|
|
56345
56554
|
await installClaudeHooks(port);
|
|
56346
56555
|
} catch (err2) {
|
|
56347
56556
|
console.warn(` \u26A0\uFE0F Claude hook install failed: ${err2 instanceof Error ? err2.message : err2}`);
|
|
56348
56557
|
}
|
|
56349
|
-
if (
|
|
56558
|
+
if (existsSync26(join28(ROOT, ".cursor"))) {
|
|
56350
56559
|
try {
|
|
56351
56560
|
await installCursorMcpConfig();
|
|
56352
56561
|
} catch (err2) {
|
|
56353
56562
|
console.warn(` \u26A0\uFE0F Cursor MCP config failed: ${err2 instanceof Error ? err2.message : err2}`);
|
|
56354
56563
|
}
|
|
56355
56564
|
}
|
|
56356
|
-
if (
|
|
56565
|
+
if (existsSync26(join28(ROOT, ".codex"))) {
|
|
56357
56566
|
try {
|
|
56358
56567
|
await installCodexHooks(port);
|
|
56359
56568
|
} catch (err2) {
|
|
@@ -56510,8 +56719,8 @@ async function cmdStatus() {
|
|
|
56510
56719
|
console.log(` stack: ${profile.stack.join(", ") || "(none)"}`);
|
|
56511
56720
|
console.log(` languages: ${profile.languages.join(", ") || "(none)"}`);
|
|
56512
56721
|
}
|
|
56513
|
-
console.log(` graph db: ${
|
|
56514
|
-
console.log(` event log: ${
|
|
56722
|
+
console.log(` graph db: ${existsSync25(paths.castalia) ? "yes" : "no"} (${paths.castalia})`);
|
|
56723
|
+
console.log(` event log: ${existsSync25(paths.eventLog) ? "yes" : "no"} (${paths.eventLog})`);
|
|
56515
56724
|
const lockPath = globalDaemonLock();
|
|
56516
56725
|
const running = isDaemonAlive(lockPath) ? readDaemonLock(lockPath) : null;
|
|
56517
56726
|
console.log(
|
|
@@ -57141,11 +57350,11 @@ function cmdInstallationProfile(args2) {
|
|
|
57141
57350
|
}
|
|
57142
57351
|
async function cmdReview() {
|
|
57143
57352
|
const paths = workspacePaths(ROOT);
|
|
57144
|
-
if (!
|
|
57353
|
+
if (!existsSync25(paths.reviewQueue)) {
|
|
57145
57354
|
console.log("(review queue empty)");
|
|
57146
57355
|
return;
|
|
57147
57356
|
}
|
|
57148
|
-
const queue = JSON.parse(
|
|
57357
|
+
const queue = JSON.parse(readFileSync23(paths.reviewQueue, "utf8"));
|
|
57149
57358
|
if (queue.length === 0) {
|
|
57150
57359
|
console.log("(review queue empty)");
|
|
57151
57360
|
return;
|
|
@@ -57816,7 +58025,7 @@ async function gatherRepo(store, ws) {
|
|
|
57816
58025
|
};
|
|
57817
58026
|
}
|
|
57818
58027
|
async function gatherReportData(generatedAt) {
|
|
57819
|
-
const { existsSync:
|
|
58028
|
+
const { existsSync: existsSync26 } = await import("node:fs");
|
|
57820
58029
|
const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src4(), src_exports2));
|
|
57821
58030
|
const cfg = loadConfig();
|
|
57822
58031
|
const outbound = cfg.consent.sync ? "auto" : "off";
|
|
@@ -57824,7 +58033,7 @@ async function gatherReportData(generatedAt) {
|
|
|
57824
58033
|
for (const ws of listWorkspaces()) {
|
|
57825
58034
|
if (ws.missing) continue;
|
|
57826
58035
|
const dbPath = workspacePaths(ws.path).castalia;
|
|
57827
|
-
if (!
|
|
58036
|
+
if (!existsSync26(dbPath)) continue;
|
|
57828
58037
|
let store = null;
|
|
57829
58038
|
try {
|
|
57830
58039
|
store = openGraphStore2({ path: dbPath });
|
|
@@ -57855,7 +58064,7 @@ async function gatherReportData(generatedAt) {
|
|
|
57855
58064
|
};
|
|
57856
58065
|
}
|
|
57857
58066
|
async function cmdReport(args2) {
|
|
57858
|
-
const { mkdirSync: mkdirSync8, writeFileSync:
|
|
58067
|
+
const { mkdirSync: mkdirSync8, writeFileSync: writeFileSync19 } = await import("node:fs");
|
|
57859
58068
|
const { renderReport: renderReport2 } = await Promise.resolve().then(() => (init_report_render(), report_render_exports));
|
|
57860
58069
|
const includeFutureVerbs = args2.includes("--future-verbs");
|
|
57861
58070
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -57868,8 +58077,8 @@ async function cmdReport(args2) {
|
|
|
57868
58077
|
const outDir = workspacePaths(ROOT).configDir;
|
|
57869
58078
|
mkdirSync8(outDir, { recursive: true });
|
|
57870
58079
|
const files = renderReport2(data, { includeFutureVerbs });
|
|
57871
|
-
for (const f of files)
|
|
57872
|
-
const indexPath =
|
|
58080
|
+
for (const f of files) writeFileSync19(join27(outDir, f.name), f.html, "utf8");
|
|
58081
|
+
const indexPath = join27(outDir, "report.html");
|
|
57873
58082
|
console.log(`report \u2192 ${indexPath}`);
|
|
57874
58083
|
console.log(
|
|
57875
58084
|
` ${data.repos.length} repo(s) \xB7 ${files.length} file(s) \xB7 ${data.rollup.nodes.toLocaleString("en-US")} nodes`
|
|
@@ -57987,15 +58196,15 @@ function hookRelayCommand(port, path2) {
|
|
|
57987
58196
|
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 '{}'`;
|
|
57988
58197
|
}
|
|
57989
58198
|
async function installClaudeHooks(port) {
|
|
57990
|
-
const { mkdirSync: mkdirSync8, existsSync:
|
|
57991
|
-
const { join:
|
|
57992
|
-
const dir =
|
|
57993
|
-
if (!
|
|
57994
|
-
const file2 =
|
|
58199
|
+
const { mkdirSync: mkdirSync8, existsSync: existsSync26, readFileSync: readFileSync24, writeFileSync: writeFileSync19 } = await import("node:fs");
|
|
58200
|
+
const { join: join28 } = await import("node:path");
|
|
58201
|
+
const dir = join28(ROOT, ".claude");
|
|
58202
|
+
if (!existsSync26(dir)) mkdirSync8(dir, { recursive: true });
|
|
58203
|
+
const file2 = join28(dir, "settings.json");
|
|
57995
58204
|
let settings = {};
|
|
57996
|
-
if (
|
|
58205
|
+
if (existsSync26(file2)) {
|
|
57997
58206
|
try {
|
|
57998
|
-
settings = JSON.parse(
|
|
58207
|
+
settings = JSON.parse(readFileSync24(file2, "utf8"));
|
|
57999
58208
|
} catch {
|
|
58000
58209
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
58001
58210
|
process.exit(2);
|
|
@@ -58041,10 +58250,10 @@ async function installClaudeHooks(port) {
|
|
|
58041
58250
|
dropErrata(list);
|
|
58042
58251
|
list.push({ hooks: [{ type: "command", command: injectCmd }] });
|
|
58043
58252
|
}
|
|
58044
|
-
|
|
58253
|
+
writeFileSync19(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
|
|
58045
58254
|
console.log(`installed Claude Code hooks \u2192 ${file2}`);
|
|
58046
58255
|
await installClaudeMcpConfig();
|
|
58047
|
-
const claudeMd =
|
|
58256
|
+
const claudeMd = join28(ROOT, "CLAUDE.md");
|
|
58048
58257
|
const recall = writeManagedBlock(claudeMd, { body: RECALL_FIRST_BLOCK });
|
|
58049
58258
|
if (recall.kind === "collision") {
|
|
58050
58259
|
console.warn(
|
|
@@ -58056,15 +58265,15 @@ async function installClaudeHooks(port) {
|
|
|
58056
58265
|
console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
|
|
58057
58266
|
}
|
|
58058
58267
|
async function installClaudeMcpConfig() {
|
|
58059
|
-
const { mkdirSync: mkdirSync8, existsSync:
|
|
58060
|
-
const { join:
|
|
58061
|
-
const file2 =
|
|
58268
|
+
const { mkdirSync: mkdirSync8, existsSync: existsSync26, readFileSync: readFileSync24, writeFileSync: writeFileSync19 } = await import("node:fs");
|
|
58269
|
+
const { join: join28, dirname: dirname10 } = await import("node:path");
|
|
58270
|
+
const file2 = join28(ROOT, ".mcp.json");
|
|
58062
58271
|
const dir = dirname10(file2);
|
|
58063
|
-
if (!
|
|
58272
|
+
if (!existsSync26(dir)) mkdirSync8(dir, { recursive: true });
|
|
58064
58273
|
let cfg = {};
|
|
58065
|
-
if (
|
|
58274
|
+
if (existsSync26(file2)) {
|
|
58066
58275
|
try {
|
|
58067
|
-
cfg = JSON.parse(
|
|
58276
|
+
cfg = JSON.parse(readFileSync24(file2, "utf8"));
|
|
58068
58277
|
} catch {
|
|
58069
58278
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
58070
58279
|
process.exit(2);
|
|
@@ -58072,21 +58281,21 @@ async function installClaudeMcpConfig() {
|
|
|
58072
58281
|
}
|
|
58073
58282
|
cfg.mcpServers ??= {};
|
|
58074
58283
|
cfg.mcpServers["errata"] = errataMcpInvocation();
|
|
58075
|
-
|
|
58284
|
+
writeFileSync19(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
|
|
58076
58285
|
console.log(`installed Claude Code MCP server config \u2192 ${file2}`);
|
|
58077
58286
|
console.log(` Claude Code will spawn \`errata mcp\` on workspace open.`);
|
|
58078
58287
|
console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses / show / similar`);
|
|
58079
58288
|
}
|
|
58080
58289
|
async function installCursorMcpConfig() {
|
|
58081
|
-
const { mkdirSync: mkdirSync8, existsSync:
|
|
58082
|
-
const { join:
|
|
58083
|
-
const dir =
|
|
58084
|
-
if (!
|
|
58085
|
-
const file2 =
|
|
58290
|
+
const { mkdirSync: mkdirSync8, existsSync: existsSync26, readFileSync: readFileSync24, writeFileSync: writeFileSync19 } = await import("node:fs");
|
|
58291
|
+
const { join: join28 } = await import("node:path");
|
|
58292
|
+
const dir = join28(ROOT, ".cursor");
|
|
58293
|
+
if (!existsSync26(dir)) mkdirSync8(dir, { recursive: true });
|
|
58294
|
+
const file2 = join28(dir, "mcp.json");
|
|
58086
58295
|
let cfg = {};
|
|
58087
|
-
if (
|
|
58296
|
+
if (existsSync26(file2)) {
|
|
58088
58297
|
try {
|
|
58089
|
-
cfg = JSON.parse(
|
|
58298
|
+
cfg = JSON.parse(readFileSync24(file2, "utf8"));
|
|
58090
58299
|
} catch {
|
|
58091
58300
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
58092
58301
|
process.exit(2);
|
|
@@ -58094,7 +58303,7 @@ async function installCursorMcpConfig() {
|
|
|
58094
58303
|
}
|
|
58095
58304
|
cfg.mcpServers ??= {};
|
|
58096
58305
|
cfg.mcpServers["errata"] = errataMcpInvocation();
|
|
58097
|
-
|
|
58306
|
+
writeFileSync19(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
|
|
58098
58307
|
console.log(`installed Cursor MCP server config \u2192 ${file2}`);
|
|
58099
58308
|
console.log(` Cursor will spawn \`errata mcp\` on workspace open.`);
|
|
58100
58309
|
console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses`);
|
|
@@ -58102,16 +58311,16 @@ async function installCursorMcpConfig() {
|
|
|
58102
58311
|
console.log(` \u26A0\uFE0F reload Cursor (Cmd/Ctrl-Shift-P \u2192 "Reload Window") to pick it up.`);
|
|
58103
58312
|
}
|
|
58104
58313
|
async function installCodexHooks(port) {
|
|
58105
|
-
const { mkdirSync: mkdirSync8, existsSync:
|
|
58106
|
-
const { join:
|
|
58107
|
-
const dir =
|
|
58108
|
-
if (!
|
|
58109
|
-
const file2 =
|
|
58314
|
+
const { mkdirSync: mkdirSync8, existsSync: existsSync26, readFileSync: readFileSync24, writeFileSync: writeFileSync19 } = await import("node:fs");
|
|
58315
|
+
const { join: join28 } = await import("node:path");
|
|
58316
|
+
const dir = join28(ROOT, ".codex");
|
|
58317
|
+
if (!existsSync26(dir)) mkdirSync8(dir, { recursive: true });
|
|
58318
|
+
const file2 = join28(dir, "config.toml");
|
|
58110
58319
|
const BEGIN = `# >>> errata hooks (errata-managed)`;
|
|
58111
58320
|
const END = `# <<< errata hooks`;
|
|
58112
58321
|
let existing = "";
|
|
58113
|
-
if (
|
|
58114
|
-
existing =
|
|
58322
|
+
if (existsSync26(file2)) {
|
|
58323
|
+
existing = readFileSync24(file2, "utf8");
|
|
58115
58324
|
const beginIdx = existing.indexOf(BEGIN);
|
|
58116
58325
|
const endIdx = existing.indexOf(END);
|
|
58117
58326
|
if (beginIdx >= 0 && endIdx > beginIdx) {
|
|
@@ -58140,7 +58349,7 @@ ${END}
|
|
|
58140
58349
|
const final = existing.length > 0 && !existing.endsWith("\n") ? `${existing}
|
|
58141
58350
|
|
|
58142
58351
|
${block}` : existing + (existing.endsWith("\n\n") ? "" : "\n") + block;
|
|
58143
|
-
|
|
58352
|
+
writeFileSync19(file2, final, "utf8");
|
|
58144
58353
|
console.log(`installed Codex hooks \u2192 ${file2}`);
|
|
58145
58354
|
console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
|
|
58146
58355
|
console.log("");
|
|
@@ -58430,7 +58639,7 @@ async function cmdDash(args2) {
|
|
|
58430
58639
|
await yieldToLoop2();
|
|
58431
58640
|
try {
|
|
58432
58641
|
const items = selectDurableMemory(handle2.sharedStore, r.engine.profile);
|
|
58433
|
-
const res = bleedRules(
|
|
58642
|
+
const res = bleedRules(join27(r.root, ".claude", "rules"), items);
|
|
58434
58643
|
if (res.written || res.pruned) {
|
|
58435
58644
|
console.log(
|
|
58436
58645
|
`[rules:${r.entry.name}] ${res.written} collective principle(s) \u2192 .claude/rules` + (res.pruned ? `, ${res.pruned} pruned` : "")
|