@inerrata-corporation/errata 2.0.16-dev.3332 → 2.0.16-dev.3355
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/consolidate-worker.mjs +26 -10
- package/errata.mjs +743 -411
- package/package.json +1 -1
- package/pass-worker.mjs +12 -11
package/errata.mjs
CHANGED
|
@@ -139,6 +139,7 @@ var init_castalia = __esm({
|
|
|
139
139
|
ROUTING_REASONS = [
|
|
140
140
|
/** Harness org (CTF lane, e2e battery, canary) — forced org-private. */
|
|
141
141
|
"harness-clamp",
|
|
142
|
+
"witnessed-vulnerability-private",
|
|
142
143
|
/** A signed gateway write target named the destination. */
|
|
143
144
|
"signed-target-public",
|
|
144
145
|
"signed-target-org",
|
|
@@ -1080,6 +1081,12 @@ function identityId(input) {
|
|
|
1080
1081
|
}
|
|
1081
1082
|
case "Claim":
|
|
1082
1083
|
return canonicalClaimId(input.text, input.scope);
|
|
1084
|
+
case "WitnessedVulnerability":
|
|
1085
|
+
return genericCanonicalId("dvuln", {
|
|
1086
|
+
workspaceId: input.workspaceId,
|
|
1087
|
+
target: input.target.replace(/\\/g, "/").replace(/^\.\//, ""),
|
|
1088
|
+
statement: canonicalClaimId(input.statement.trim())
|
|
1089
|
+
});
|
|
1083
1090
|
case "DesignProblem":
|
|
1084
1091
|
return `${DESIGN_PROBLEM_PREFIX}${canonicalClaimId(input.statement.trim())}`.slice(
|
|
1085
1092
|
0,
|
|
@@ -15849,7 +15856,7 @@ var init_edge_rules = __esm({
|
|
|
15849
15856
|
// anchor anything at anything, e.g. at a public `Package`, quietly re-creating
|
|
15850
15857
|
// the code↔collective bridge the membrane exists to prevent.
|
|
15851
15858
|
ANCHORED_AT: {
|
|
15852
|
-
from: ["Problem", "Solution", "RootCause", "Claim"],
|
|
15859
|
+
from: ["Problem", "Vulnerability", "Solution", "RootCause", "Claim"],
|
|
15853
15860
|
to: ["Symbol"]
|
|
15854
15861
|
},
|
|
15855
15862
|
// ── Security spine (v1 taxonomy.ts SECURITY_FORWARD_ONLY commentary) ──
|
|
@@ -15894,7 +15901,7 @@ var init_edge_rules = __esm({
|
|
|
15894
15901
|
// `Component` joined the target set with OM-agent-anchors: an agent-named
|
|
15895
15902
|
// component ("React Router") is the same knowledge→named-unit anchor shape as
|
|
15896
15903
|
// a Tool — the knowledge is ABOUT it, not dependent on it.
|
|
15897
|
-
CONCERNS: { from: ["Problem", "Solution", "RootCause", "Claim", "Pattern"], to: ["Tool", "Component"] },
|
|
15904
|
+
CONCERNS: { from: ["Problem", "Vulnerability", "Solution", "RootCause", "Claim", "Pattern"], to: ["Tool", "Component"] },
|
|
15898
15905
|
OPERATES_ON: { from: ["Algorithm"], to: ["DataStructure"] },
|
|
15899
15906
|
INVOLVES: { from: ["Problem", "Solution"], to: ["DataStructure"] },
|
|
15900
15907
|
// ── Taxonomy (Track 4 Stream C: MITRE CWE `ChildOf` → `Weakness —IS_A→ Weakness`) ──
|
|
@@ -16448,8 +16455,8 @@ function parsePackageLockJson(jsonText) {
|
|
|
16448
16455
|
}
|
|
16449
16456
|
const dependencies = [];
|
|
16450
16457
|
for (const [path2, meta3] of Object.entries(packages)) {
|
|
16451
|
-
const
|
|
16452
|
-
if (!
|
|
16458
|
+
const self2 = byPath.get(path2);
|
|
16459
|
+
if (!self2) continue;
|
|
16453
16460
|
const deps = meta3.dependencies;
|
|
16454
16461
|
if (!deps || typeof deps !== "object") continue;
|
|
16455
16462
|
const dependsOn = [];
|
|
@@ -16458,7 +16465,7 @@ function parsePackageLockJson(jsonText) {
|
|
|
16458
16465
|
if (target) dependsOn.push(npmPurl(depName, target.version));
|
|
16459
16466
|
}
|
|
16460
16467
|
if (dependsOn.length > 0)
|
|
16461
|
-
dependencies.push({ ref: npmPurl(
|
|
16468
|
+
dependencies.push({ ref: npmPurl(self2.name, self2.version), dependsOn });
|
|
16462
16469
|
}
|
|
16463
16470
|
const directRaw = [];
|
|
16464
16471
|
for (const [path2, meta3] of Object.entries(packages)) {
|
|
@@ -16929,9 +16936,9 @@ function pomSelf(text) {
|
|
|
16929
16936
|
const group = (/<groupId>([^<]+)<\/groupId>/.exec(own)?.[1] ?? parentGroup)?.trim();
|
|
16930
16937
|
const artifact = /<artifactId>([^<]+)<\/artifactId>/.exec(own)?.[1]?.trim();
|
|
16931
16938
|
if (!group) return [];
|
|
16932
|
-
const
|
|
16933
|
-
if (artifact)
|
|
16934
|
-
return
|
|
16939
|
+
const self2 = [{ ecosystem: "maven", kind: "namespace", value: group }];
|
|
16940
|
+
if (artifact) self2.push({ ecosystem: "maven", kind: "name", value: mavenName(group, artifact) });
|
|
16941
|
+
return self2;
|
|
16935
16942
|
}
|
|
16936
16943
|
function parseManifestSelf(path2, text) {
|
|
16937
16944
|
const file2 = basename(path2);
|
|
@@ -16944,10 +16951,10 @@ function parseManifestSelf(path2, text) {
|
|
|
16944
16951
|
}
|
|
16945
16952
|
const name2 = obj && typeof obj === "object" ? obj["name"] : null;
|
|
16946
16953
|
if (typeof name2 !== "string" || !name2.trim()) return [];
|
|
16947
|
-
const
|
|
16954
|
+
const self2 = [{ ecosystem: "npm", kind: "name", value: name2.trim() }];
|
|
16948
16955
|
const scope = /^(@[^/]+)\//.exec(name2.trim())?.[1];
|
|
16949
|
-
if (scope)
|
|
16950
|
-
return
|
|
16956
|
+
if (scope) self2.push({ ecosystem: "npm", kind: "namespace", value: scope });
|
|
16957
|
+
return self2;
|
|
16951
16958
|
}
|
|
16952
16959
|
if (file2 === "pom.xml") return pomSelf(text);
|
|
16953
16960
|
if (file2 === "build.gradle" || file2 === "build.gradle.kts") {
|
|
@@ -18268,7 +18275,8 @@ CREATE INDEX IF NOT EXISTS nodes_live ON nodes(label, valid_to);
|
|
|
18268
18275
|
-- its table row. Partial, so it maintains a few thousand rows instead of adding
|
|
18269
18276
|
-- a write to every node write. Its label list is FINGERPRINT_INDEXED_LABELS.
|
|
18270
18277
|
DROP INDEX IF EXISTS nodes_live_fingerprint;
|
|
18271
|
-
|
|
18278
|
+
DROP INDEX IF EXISTS nodes_instance_fingerprint;
|
|
18279
|
+
CREATE INDEX IF NOT EXISTS nodes_instance_fingerprint_v2 ON nodes(label, last_updated_at, last_reinforced_at_seq, created_at_seq) WHERE valid_to IS NULL AND label IN ('Problem','Vulnerability','Solution','RootCause');
|
|
18272
18280
|
CREATE INDEX IF NOT EXISTS nodes_logical ON nodes(logical_id, version);
|
|
18273
18281
|
CREATE INDEX IF NOT EXISTS edges_live ON edges(valid_to);
|
|
18274
18282
|
-- Expression index on the per-node relPath (stored in attrs_json) so the
|
|
@@ -18282,7 +18290,7 @@ CREATE INDEX IF NOT EXISTS nodes_live_description ON nodes(description, label) W
|
|
|
18282
18290
|
-- every edited file of every turn, and a scan parses every Problem's attrs.
|
|
18283
18291
|
CREATE INDEX IF NOT EXISTS nodes_anchor_hint_path ON nodes(json_extract(attrs_json, '$.anchorHint.path')) WHERE valid_to IS NULL;
|
|
18284
18292
|
`;
|
|
18285
|
-
FINGERPRINT_INDEXED_LABELS = ["Problem", "Solution", "RootCause"];
|
|
18293
|
+
FINGERPRINT_INDEXED_LABELS = ["Problem", "Vulnerability", "Solution", "RootCause"];
|
|
18286
18294
|
SqliteGraphStore = class {
|
|
18287
18295
|
db;
|
|
18288
18296
|
// Typed edge lookups build their SQL from the number of types asked for, and
|
|
@@ -18960,8 +18968,8 @@ CREATE INDEX IF NOT EXISTS nodes_anchor_hint_path ON nodes(json_extract(attrs_js
|
|
|
18960
18968
|
const r2 = this.db.prepare(
|
|
18961
18969
|
`SELECT COUNT(*) AS n, MAX(last_updated_at) AS t,
|
|
18962
18970
|
MAX(COALESCE(last_reinforced_at_seq, created_at_seq, 0)) AS s
|
|
18963
|
-
FROM nodes INDEXED BY
|
|
18964
|
-
WHERE valid_to IS NULL AND label IN ('Problem','Solution','RootCause')`
|
|
18971
|
+
FROM nodes INDEXED BY nodes_instance_fingerprint_v2
|
|
18972
|
+
WHERE valid_to IS NULL AND label IN ('Problem','Vulnerability','Solution','RootCause')`
|
|
18965
18973
|
).get();
|
|
18966
18974
|
return `${r2.n}:${r2.t ?? 0}:${r2.s ?? 0}`;
|
|
18967
18975
|
}
|
|
@@ -20257,7 +20265,7 @@ function mergeContextEdge(store, from, to, type, ts) {
|
|
|
20257
20265
|
function deriveContextFromAnchors(store, problemId, ts, pkgIndex) {
|
|
20258
20266
|
const report = { languages: [], packages: [] };
|
|
20259
20267
|
const p = store.getNode(problemId);
|
|
20260
|
-
if (!p || p.label !== "Problem") return report;
|
|
20268
|
+
if (!p || p.label !== "Problem" && p.label !== "Vulnerability") return report;
|
|
20261
20269
|
const files = store.outEdges(problemId, ["ANCHORED_AT"]).map((e) => store.getNode(e.to)).filter((n) => !!n && n.label === "File");
|
|
20262
20270
|
if (files.length === 0) return report;
|
|
20263
20271
|
const idx = pkgIndex ?? buildPackageIndex(store);
|
|
@@ -20895,6 +20903,81 @@ function ingestDesignProblem(store, flag, opts) {
|
|
|
20895
20903
|
...reopenedFromRegression ? { reopenedFromRegression } : {}
|
|
20896
20904
|
};
|
|
20897
20905
|
}
|
|
20906
|
+
function ingestWitnessedVulnerability(store, flag, opts) {
|
|
20907
|
+
const statement = flag.statement.trim();
|
|
20908
|
+
if (isPlaceholderStatement(statement)) return { id: "", created: false, corroborated: false, upgraded: false, rejected: "statement" };
|
|
20909
|
+
const target = flag.target?.trim().replace(/\\/g, "/").replace(/^\.\//, "") ?? "";
|
|
20910
|
+
const file2 = target ? resolveFileNode(store, target, opts.workspaceId) : null;
|
|
20911
|
+
const symbol2 = file2 && flag.line !== void 0 && flag.fileText !== void 0 ? resolveEnclosingSymbol(store, file2.id, flag.line, flag.fileText) : null;
|
|
20912
|
+
const identityTarget = symbol2 ? String(symbol2.attrs["logicalId"] ?? `${target}#${symbol2.attrs["qname"] ?? symbol2.description}`) : target;
|
|
20913
|
+
const compatibleTarget = (n) => !symbol2 || !n.attrs["identityTarget"] || n.attrs["identityTarget"] === target || n.attrs["identityTarget"] === identityTarget;
|
|
20914
|
+
const bound = flag.existingId ? store.getNode(flag.existingId) : null;
|
|
20915
|
+
if (flag.existingId && (!bound || bound.label !== "Vulnerability" || bound.attrs["workspaceId"] !== opts.workspaceId || target && bound.attrs["affectedTarget"] && bound.attrs["affectedTarget"] !== target || !compatibleTarget(bound))) {
|
|
20916
|
+
return { id: "", created: false, corroborated: false, upgraded: false, rejected: "binding-conflict" };
|
|
20917
|
+
}
|
|
20918
|
+
const statementKey = identityId({ kind: "DesignProblem", statement });
|
|
20919
|
+
const restated = bound ? null : store.findNodesByLabel("Vulnerability").find((n) => n.attrs["workspaceId"] === opts.workspaceId && n.attrs["affectedTarget"] === target && compatibleTarget(n) && [n.description, ...n.attrs["statementAliases"] ?? []].some((s) => identityId({ kind: "DesignProblem", statement: s }) === statementKey));
|
|
20920
|
+
const id = bound?.id ?? restated?.id ?? identityId({ kind: "WitnessedVulnerability", workspaceId: opts.workspaceId, target: identityTarget, statement });
|
|
20921
|
+
const existing = bound ?? store.getNode(id);
|
|
20922
|
+
const sources = existing?.attrs["sources"] ?? [];
|
|
20923
|
+
const corroborated = !!existing && !sources.includes(opts.source);
|
|
20924
|
+
const upgraded = !!existing && existing.attrs["assessment"] !== "asserted" && flag.assessment === "asserted";
|
|
20925
|
+
const assessment = existing?.attrs["assessment"] === "asserted" ? "asserted" : flag.assessment;
|
|
20926
|
+
if (!existing) {
|
|
20927
|
+
store.mergeNode(buildNode(store, id, "Vulnerability", statement, opts.ts, {
|
|
20928
|
+
source: "convo",
|
|
20929
|
+
sourceClass: "agent-observation",
|
|
20930
|
+
privateFinding: id,
|
|
20931
|
+
workspaceId: opts.workspaceId,
|
|
20932
|
+
affectedTarget: target,
|
|
20933
|
+
identityTarget,
|
|
20934
|
+
assessment,
|
|
20935
|
+
anchorDisposition: target ? "unresolved" : "absent",
|
|
20936
|
+
provisional: true,
|
|
20937
|
+
sources: [opts.source],
|
|
20938
|
+
corroborations: 0,
|
|
20939
|
+
...opts.hostHarness ? { hostHarness: opts.hostHarness } : {}
|
|
20940
|
+
}));
|
|
20941
|
+
} else if (corroborated || upgraded || !existing.attrs["affectedTarget"] && target || symbol2 && existing.attrs["identityTarget"] !== identityTarget) {
|
|
20942
|
+
store.updateNode(id, {
|
|
20943
|
+
attrs: {
|
|
20944
|
+
...existing.attrs,
|
|
20945
|
+
assessment,
|
|
20946
|
+
...upgraded && existing.description !== statement ? { statementAliases: [...existing.attrs["statementAliases"] ?? [], existing.description].slice(-5) } : {},
|
|
20947
|
+
affectedTarget: existing.attrs["affectedTarget"] || target,
|
|
20948
|
+
...symbol2 ? { identityTarget } : {},
|
|
20949
|
+
sources: corroborated ? [...sources, opts.source] : sources,
|
|
20950
|
+
corroborations: (Number(existing.attrs["corroborations"]) || 0) + (corroborated ? 1 : 0)
|
|
20951
|
+
},
|
|
20952
|
+
// Assessment strengthens on evidence, but does not certify exploitability.
|
|
20953
|
+
...upgraded ? { description: statement } : {},
|
|
20954
|
+
...corroborated ? { cumulativeHits: existing.cumulativeHits + 1 } : {},
|
|
20955
|
+
...reinforcedSeqAttrs(store, "Vulnerability"),
|
|
20956
|
+
lastUpdatedAt: opts.ts
|
|
20957
|
+
});
|
|
20958
|
+
}
|
|
20959
|
+
return { id, created: !existing, corroborated, upgraded };
|
|
20960
|
+
}
|
|
20961
|
+
function recordVulnerabilityCause(store, findingId, causes, ts) {
|
|
20962
|
+
const finding = store.getNode(findingId);
|
|
20963
|
+
if (finding?.label !== "Vulnerability") return 0;
|
|
20964
|
+
let from = findingId;
|
|
20965
|
+
let count = 0;
|
|
20966
|
+
for (const description of causes) {
|
|
20967
|
+
if (isPlaceholderStatement(description)) continue;
|
|
20968
|
+
const id = genericCanonicalId("dcause", { findingId, description: description.trim() });
|
|
20969
|
+
if (!store.getNode(id)) store.mergeNode(buildNode(store, id, "RootCause", description.trim(), ts, {
|
|
20970
|
+
source: "convo",
|
|
20971
|
+
privateFinding: findingId,
|
|
20972
|
+
sources: finding.attrs["sources"],
|
|
20973
|
+
assessment: finding.attrs["assessment"]
|
|
20974
|
+
}));
|
|
20975
|
+
mergeEdge(store, from, id, "CAUSED_BY", ts);
|
|
20976
|
+
from = id;
|
|
20977
|
+
count++;
|
|
20978
|
+
}
|
|
20979
|
+
return count;
|
|
20980
|
+
}
|
|
20898
20981
|
function canonicalizePatternText(name2) {
|
|
20899
20982
|
const stripped = name2.replace(/^\s*pattern(?:\s*[×x]\s*\d+)?\s*(?:\(exemplar\))?\s*[:—–-]\s*/i, "").replace(/\s+/g, " ").trim();
|
|
20900
20983
|
return stripped.length > 0 ? stripped : name2.replace(/\s+/g, " ").trim();
|
|
@@ -21205,6 +21288,7 @@ function findReusableSolution(store, fixText) {
|
|
|
21205
21288
|
const key = solutionTextKey(fixText);
|
|
21206
21289
|
if (!key) return null;
|
|
21207
21290
|
for (const s of store.findNodesByLabel("Solution")) {
|
|
21291
|
+
if (s.attrs["privateFinding"]) continue;
|
|
21208
21292
|
if (s.validTo != null) continue;
|
|
21209
21293
|
if (isAutoMinted(s)) continue;
|
|
21210
21294
|
if (solutionTextKey(s.description ?? "") === key) return s;
|
|
@@ -21229,7 +21313,7 @@ function priorsForFile(store, relPath) {
|
|
|
21229
21313
|
for (const e of store.inEdges(file2.id, ["ANCHORED_AT"])) {
|
|
21230
21314
|
const n = store.getNode(e.from);
|
|
21231
21315
|
if (!n) continue;
|
|
21232
|
-
if (n.label === "Problem") {
|
|
21316
|
+
if (n.label === "Problem" || n.label === "Vulnerability") {
|
|
21233
21317
|
if (seenProblem.has(n.id)) continue;
|
|
21234
21318
|
seenProblem.add(n.id);
|
|
21235
21319
|
if (!n.attrs["resolvedAt"]) {
|
|
@@ -21299,7 +21383,8 @@ function solutionForProblem(store, problemId) {
|
|
|
21299
21383
|
}
|
|
21300
21384
|
function anchorProblemToWorkingFile(store, problemId, relPath, workspaceId2, ts, provenance = "edited", opts = {}) {
|
|
21301
21385
|
const p = store.getNode(problemId);
|
|
21302
|
-
if (!p || p.label !== "Problem") return false;
|
|
21386
|
+
if (!p || p.label !== "Problem" && p.label !== "Vulnerability") return false;
|
|
21387
|
+
if (p.label === "Vulnerability" && provenance !== "witnessed") return false;
|
|
21303
21388
|
if (!isAnchorableCodePath(relPath)) return false;
|
|
21304
21389
|
const file2 = resolveFileNode(store, relPath, workspaceId2);
|
|
21305
21390
|
if (!file2) return false;
|
|
@@ -21478,18 +21563,22 @@ function resolveDesignProblemById(store, id, fixNote, t) {
|
|
|
21478
21563
|
}
|
|
21479
21564
|
function closeDesignProblem(store, problemId, fixNote, t) {
|
|
21480
21565
|
const p = store.getNode(problemId);
|
|
21481
|
-
if (!p || p.label !== "Problem") return false;
|
|
21566
|
+
if (!p || p.label !== "Problem" && p.label !== "Vulnerability") return false;
|
|
21482
21567
|
if (p.attrs["resolvedAs"]) return false;
|
|
21483
21568
|
if (fixNote?.trim() && !isFragmentFixNote(fixNote)) {
|
|
21484
21569
|
const sols = store.outEdges(problemId, ["SOLVED_BY"]).map((e) => store.getNode(e.to)).filter((n) => n !== null);
|
|
21485
21570
|
if (sols.every((s) => isAutoMinted(s))) {
|
|
21486
|
-
const reuse = findReusableSolution(store, fixNote);
|
|
21571
|
+
const reuse = p.label === "Vulnerability" ? null : findReusableSolution(store, fixNote);
|
|
21487
21572
|
if (reuse) {
|
|
21488
21573
|
mergeEdge(store, problemId, reuse.id, "SOLVED_BY", t);
|
|
21489
21574
|
} else {
|
|
21490
21575
|
const solId = `dfix_${digest({ problemId, fix: fixNote })}`.slice(0, 56);
|
|
21491
21576
|
store.mergeNode(
|
|
21492
|
-
buildNode(store, solId, "Solution", fixNote.trim(), t, {
|
|
21577
|
+
buildNode(store, solId, "Solution", fixNote.trim(), t, {
|
|
21578
|
+
source: "convo",
|
|
21579
|
+
provisional: false,
|
|
21580
|
+
...p.label === "Vulnerability" ? { privateFinding: problemId, sources: p.attrs["sources"] } : {}
|
|
21581
|
+
})
|
|
21493
21582
|
);
|
|
21494
21583
|
mergeEdge(store, problemId, solId, "SOLVED_BY", t);
|
|
21495
21584
|
}
|
|
@@ -21503,6 +21592,7 @@ function closeDesignProblem(store, problemId, fixNote, t) {
|
|
|
21503
21592
|
// mints no Solution, and a legacy placeholder beside it reads as
|
|
21504
21593
|
// all-heuristic either way.
|
|
21505
21594
|
attrs: { ...p.attrs, provisional: false, resolvedAt: t, resolutionWitnessed: true },
|
|
21595
|
+
...reinforcedSeqAttrs(store, p.label),
|
|
21506
21596
|
lastUpdatedAt: t
|
|
21507
21597
|
});
|
|
21508
21598
|
return true;
|
|
@@ -23854,7 +23944,7 @@ function detectLocalCommunities(store, opts = {}) {
|
|
|
23854
23944
|
const ids = /* @__PURE__ */ new Set();
|
|
23855
23945
|
for (const label of JOINT_COMMUNITY_LABELS) {
|
|
23856
23946
|
for (const n of store.findNodesByLabel(label)) {
|
|
23857
|
-
if (
|
|
23947
|
+
if (n.attrs["resolvedAs"] === PROBLEM_RESOLUTION.FALSE_POSITIVE) continue;
|
|
23858
23948
|
ids.add(n.id);
|
|
23859
23949
|
}
|
|
23860
23950
|
}
|
|
@@ -23991,6 +24081,7 @@ var init_community2 = __esm({
|
|
|
23991
24081
|
init_src4();
|
|
23992
24082
|
JOINT_COMMUNITY_LABELS = [
|
|
23993
24083
|
"Problem",
|
|
24084
|
+
"Vulnerability",
|
|
23994
24085
|
"Solution",
|
|
23995
24086
|
"RootCause",
|
|
23996
24087
|
"Pattern"
|
|
@@ -24852,6 +24943,7 @@ __export(src_exports2, {
|
|
|
24852
24943
|
induceAbstractions: () => induceAbstractions,
|
|
24853
24944
|
induceTriage: () => induceTriage,
|
|
24854
24945
|
ingestDesignProblem: () => ingestDesignProblem,
|
|
24946
|
+
ingestWitnessedVulnerability: () => ingestWitnessedVulnerability,
|
|
24855
24947
|
isConstraintProblem: () => isConstraintProblem,
|
|
24856
24948
|
isFragmentFixNote: () => isFragmentFixNote,
|
|
24857
24949
|
isPlaceholderStatement: () => isPlaceholderStatement,
|
|
@@ -24899,6 +24991,7 @@ __export(src_exports2, {
|
|
|
24899
24991
|
recordMisreadPrior: () => recordMisreadPrior,
|
|
24900
24992
|
recordRenderLedger: () => recordRenderLedger,
|
|
24901
24993
|
recordTriageObservation: () => recordTriageObservation,
|
|
24994
|
+
recordVulnerabilityCause: () => recordVulnerabilityCause,
|
|
24902
24995
|
reinforceSameAnchorProblem: () => reinforceSameAnchorProblem,
|
|
24903
24996
|
relateClaims: () => relateClaims,
|
|
24904
24997
|
reopenAutoClosedProblems: () => reopenAutoClosedProblems,
|
|
@@ -24968,11 +25061,11 @@ function isPassiveInjectable(node2, atCommit) {
|
|
|
24968
25061
|
return false;
|
|
24969
25062
|
}
|
|
24970
25063
|
function buildSnapshot(opts) {
|
|
24971
|
-
const problems = opts.store.findNodesByLabel("Problem").filter((p) => p.attrs["mergedInto"] === void 0 && historyReadPolicy(p, { mode: "passive", atCommit: opts.atCommit }).allow);
|
|
25064
|
+
const problems = [...opts.store.findNodesByLabel("Problem"), ...opts.store.findNodesByLabel("Vulnerability")].filter((p) => p.attrs["mergedInto"] === void 0 && historyReadPolicy(p, { mode: "passive", atCommit: opts.atCommit }).allow);
|
|
24972
25065
|
const stillOpen = problems.filter((p) => p.attrs["resolvedAt"] == null);
|
|
24973
25066
|
const allProblems = stillOpen.filter((p) => !isConstraintProblem(p));
|
|
24974
25067
|
allProblems.sort((a, b) => b.lastUpdatedAt - a.lastUpdatedAt);
|
|
24975
|
-
const
|
|
25068
|
+
const recent3 = allProblems.slice(0, 8).map((p) => ({
|
|
24976
25069
|
node: p,
|
|
24977
25070
|
anchors: opts.store.outEdges(p.id, ["MANIFESTED_IN", "EVIDENCED_BY"])
|
|
24978
25071
|
}));
|
|
@@ -25045,10 +25138,10 @@ function buildSnapshot(opts) {
|
|
|
25045
25138
|
packages: opts.profile.stack.map((name2) => ({ name: name2, node: matchNode(pkgNodes, pkgBase(name2)) })),
|
|
25046
25139
|
tools: toolNodes.map((node2) => ({ name: String(node2.attrs["name"] ?? node2.description), node: node2 }))
|
|
25047
25140
|
};
|
|
25048
|
-
const causalNudge =
|
|
25141
|
+
const causalNudge = recent3.length >= 2 && recent3.every(
|
|
25049
25142
|
(r) => opts.store.outEdges(r.node.id, ["CAUSED_BY"]).length === 0 && opts.store.inEdges(r.node.id, ["CAUSED_BY"]).length === 0
|
|
25050
25143
|
);
|
|
25051
|
-
const abstractUndomained =
|
|
25144
|
+
const abstractUndomained = recent3.filter((r) => {
|
|
25052
25145
|
const grounded = opts.store.outEdges(r.node.id, ["ANCHORED_AT", "OCCURS_IN", "DEPENDS_ON"]).length > 0;
|
|
25053
25146
|
const hasDomain = opts.store.outEdges(r.node.id, ["PERTAIN_TO"]).length > 0;
|
|
25054
25147
|
return !grounded && !hasDomain;
|
|
@@ -25057,7 +25150,7 @@ function buildSnapshot(opts) {
|
|
|
25057
25150
|
return {
|
|
25058
25151
|
profile: opts.profile,
|
|
25059
25152
|
profileContext,
|
|
25060
|
-
recentProblems:
|
|
25153
|
+
recentProblems: recent3,
|
|
25061
25154
|
recentResolved,
|
|
25062
25155
|
recentConstraints,
|
|
25063
25156
|
regressions,
|
|
@@ -25123,11 +25216,11 @@ function sliceForFile(store, relPath, atCommit) {
|
|
|
25123
25216
|
const priors = fp ? {
|
|
25124
25217
|
openProblems: fp.openProblems.slice(0, 3).map((p) => ({
|
|
25125
25218
|
id: p.id,
|
|
25126
|
-
description: p.description,
|
|
25219
|
+
description: p.label === "Vulnerability" ? `Vulnerability (${p.attrs["assessment"] ?? "unassessed"}): ${p.description}` : p.description,
|
|
25127
25220
|
...typeof p.attrs["fixCandidateFile"] === "string" ? { fixCandidateFile: p.attrs["fixCandidateFile"] } : {}
|
|
25128
25221
|
})),
|
|
25129
25222
|
constraints: fp.constraints.slice(0, 2).map((c) => ({ id: c.id, description: c.description })),
|
|
25130
|
-
resolvedProblems: fp.resolvedProblems.slice(0, 3).map((p) => ({ id: p.id, description: p.description })),
|
|
25223
|
+
resolvedProblems: fp.resolvedProblems.slice(0, 3).map((p) => ({ id: p.id, description: p.label === "Vulnerability" ? `Vulnerability (${p.attrs["assessment"] ?? "unassessed"}): ${p.description}` : p.description })),
|
|
25131
25224
|
related: fp.related.slice(0, 4).map((n) => ({ id: n.id, label: n.label, description: n.description })),
|
|
25132
25225
|
solutionsByProblem: Object.fromEntries(
|
|
25133
25226
|
[...fp.openProblems.slice(0, 3), ...fp.resolvedProblems.slice(0, 3)].map((p) => [
|
|
@@ -25245,7 +25338,8 @@ function renderSnapshot(s) {
|
|
|
25245
25338
|
if (s.recentProblems.length > 0) {
|
|
25246
25339
|
lines.push("_Open \u2014 recently observed here, derived from your work (a recency slice, not an inventory \u2014 burst an id for its full neighborhood):_");
|
|
25247
25340
|
for (const r of s.recentProblems) {
|
|
25248
|
-
|
|
25341
|
+
const badge = r.node.label === "Vulnerability" ? `Vulnerability (${r.node.attrs["assessment"] ?? "unassessed"}): ` : "";
|
|
25342
|
+
lines.push(`- **${badge}${r.node.description}** \u2014 \`${r.node.id}\`${tagOf(r.node)}`);
|
|
25249
25343
|
const hits = r.node.cumulativeHits ?? 0;
|
|
25250
25344
|
const surprise = (r.node.cumulativeSurprise ?? 0).toFixed(2);
|
|
25251
25345
|
lines.push(` - observed ${hits}\xD7 \xB7 cumulativeSurprise ${surprise}`);
|
|
@@ -25286,7 +25380,8 @@ function renderSnapshot(s) {
|
|
|
25286
25380
|
if (s.recentResolved.length > 0) {
|
|
25287
25381
|
lines.push("_Recently resolved \u2014 solved here; jumping-off points, not live defects:_");
|
|
25288
25382
|
for (const r of s.recentResolved) {
|
|
25289
|
-
|
|
25383
|
+
const badge = r.node.label === "Vulnerability" ? `Vulnerability (${r.node.attrs["assessment"] ?? "unassessed"}): ` : "";
|
|
25384
|
+
lines.push(`- \u2713 **${badge}${r.node.description}** \u2014 \`${r.node.id}\`${tagOf(r.node)}`);
|
|
25290
25385
|
if (r.solution) {
|
|
25291
25386
|
lines.push(` - solved: ${r.solution.description.slice(0, 160)} \u2014 \`${r.solution.id}\`${tagOf(r.solution)}`);
|
|
25292
25387
|
}
|
|
@@ -31707,7 +31802,7 @@ var init_src8 = __esm({
|
|
|
31707
31802
|
|
|
31708
31803
|
// src/agent-signals.ts
|
|
31709
31804
|
function buildFileRecallInstruction(referent = "\u2026") {
|
|
31710
|
-
return `Touching one? paste its token: ${TAG_EXAMPLE.fix(referent)} resolved \xB7 ${TAG_EXAMPLE.prior(referent)} leaned-on \xB7 ${TAG_EXAMPLE.problem()} new. We harvest it.`;
|
|
31805
|
+
return `Touching one? paste its token: ${TAG_EXAMPLE.fix(referent)} resolved \xB7 ${TAG_EXAMPLE.prior(referent)} leaned-on \xB7 ${TAG_EXAMPLE.problem()} new \xB7 ${TAG_EXAMPLE.vulnerability()} security. We harvest it.`;
|
|
31711
31806
|
}
|
|
31712
31807
|
function triageBullet(ref) {
|
|
31713
31808
|
return [
|
|
@@ -31743,15 +31838,15 @@ function attemptBullet() {
|
|
|
31743
31838
|
].join("\n");
|
|
31744
31839
|
}
|
|
31745
31840
|
function buildAgentInstruction(opts = {}) {
|
|
31746
|
-
const signals = opts.signals ?? ["prior", "problem", "domain", "fix", "constraint", "triage", "attempt", "link"];
|
|
31841
|
+
const signals = opts.signals ?? ["prior", "problem", "vulnerability", "domain", "fix", "constraint", "triage", "attempt", "link"];
|
|
31747
31842
|
const ref = opts.referent ?? "its-handle";
|
|
31748
31843
|
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() : s === "verdict" ? TAG_EXAMPLE.confirm(ref) : TAG_EXAMPLE[s](ref);
|
|
31749
|
-
const head2 =
|
|
31750
|
-
const tail = "
|
|
31844
|
+
const head2 = "Tag inline (no fences or backticks). Untagged findings are silently lost. Cite short handles; tag everything, we filter downstream. Requested errata-* answer blocks are the exception: keep their fences in your turn-final reply:";
|
|
31845
|
+
const tail = "Restate mid-turn tags in your final reply; the harness can drop mid-turn text. EXCEPT one already shown with an id: cite [its-handle] instead of retyping (drift mints a duplicate).";
|
|
31751
31846
|
return [
|
|
31752
31847
|
head2,
|
|
31753
31848
|
...signals.map(
|
|
31754
|
-
(s) => s === "triage" ? triageBullet(ref) : s === "attempt" ? attemptBullet() : s === "link" ? linkBullet(ref) : s === "verdict" ? verdictBullet(ref) : ` \u2022 ${GLOSS[s]} \u2192 ${token(s)}`
|
|
31849
|
+
(s) => s === "triage" ? triageBullet(ref) : s === "vulnerability" ? ` \u2022 ${GLOSS.vulnerability} \u2192 ${TAG_EXAMPLE.vulnerability()}. Uncertain? ${TAG_EXAMPLE.suspectedVulnerability()}. Code review counts, even if immediately fixed. No CVE/exploit needed. For fixes: ${TAG_EXAMPLE.vulnerabilityThread()} ${TAG_EXAMPLE.fixThread("v")}.` : s === "attempt" ? attemptBullet() : s === "link" ? linkBullet(ref) : s === "verdict" ? verdictBullet(ref) : ` \u2022 ${GLOSS[s]} \u2192 ${token(s)}`
|
|
31755
31850
|
),
|
|
31756
31851
|
tail
|
|
31757
31852
|
].join("\n");
|
|
@@ -31763,6 +31858,9 @@ var init_agent_signals = __esm({
|
|
|
31763
31858
|
TAG_EXAMPLE = {
|
|
31764
31859
|
prior: (ref) => `([${ref}])`,
|
|
31765
31860
|
problem: () => `[!one line on what's wrong]`,
|
|
31861
|
+
vulnerability: () => `[!vuln: who can do what; observed basis @ path:line]`,
|
|
31862
|
+
suspectedVulnerability: () => `[?vuln: consequence; missing check]`,
|
|
31863
|
+
vulnerabilityThread: () => `[!#v vuln: finding here]`,
|
|
31766
31864
|
fix: (ref) => `(fix:[${ref}])`,
|
|
31767
31865
|
// CONSTRAINT — the native capture path for a DIFFUSE problem (a constraint/tension/
|
|
31768
31866
|
// conflict that shaped a decision). Free text, attaches to the decision sentence the
|
|
@@ -31783,7 +31881,7 @@ var init_agent_signals = __esm({
|
|
|
31783
31881
|
// tags never need one — the id is for diagnoses that unfold over distance.
|
|
31784
31882
|
problemThread: () => `[!#slug one line on what's wrong]`,
|
|
31785
31883
|
causeThread: () => `(cause:#slug the mechanism)`,
|
|
31786
|
-
fixThread: () => `(fix
|
|
31884
|
+
fixThread: (thread = "slug") => `(fix:#${thread} what you changed)`,
|
|
31787
31885
|
// ATTEMPT arc — what's being tried and what didn't work. A failed attempt is a
|
|
31788
31886
|
// witnessed NEGATIVE result: it saves the next agent the same dead end.
|
|
31789
31887
|
tried: () => `(tried: the approach you're attempting)`,
|
|
@@ -31825,8 +31923,9 @@ var init_agent_signals = __esm({
|
|
|
31825
31923
|
// problems, and narrated them as progress (a pick-best-before-scoring bug lost).
|
|
31826
31924
|
// Every example here was diagnosis-framed, so nothing contradicted that sorting.
|
|
31827
31925
|
// Kept to 29 chars: the instruction sits at the 2600 passive-budget ceiling.
|
|
31828
|
-
problem: "
|
|
31829
|
-
|
|
31926
|
+
problem: "any bug or finding, even in code you just wrote; name affected code: [!what's wrong @ path:42]",
|
|
31927
|
+
vulnerability: "unauthorized actions, data exposure, or execution/disruption an attacker can trigger",
|
|
31928
|
+
fix: "you fixed a shown finding; for your own non-security finding: (fix: what changed) \u2014 a fix resolves a stated problem, completing routine work is not a fix",
|
|
31830
31929
|
constraint: "a design decision forced by conflicting requirements or constraints \u2014 tag the tension, especially when your fix makes it 'only look' resolved",
|
|
31831
31930
|
triage: "you diagnosed a cause \u2014 fold the chain into the flag with <- (caused-by), deepest sure mechanism rightmost",
|
|
31832
31931
|
attempt: "attempting an approach / an attempt failed \u2014 a failed attempt is knowledge, it rules out a path",
|
|
@@ -31848,7 +31947,7 @@ var init_agent_signals = __esm({
|
|
|
31848
31947
|
// Sim note (2026-08-02 shrink): domain emission held 4/4 with just the trigger
|
|
31849
31948
|
// clause; the pattern convergence hook now rides here too (it fell 0/4 when it
|
|
31850
31949
|
// only appeared in the link bullet's tail).
|
|
31851
|
-
domain: "
|
|
31950
|
+
domain: "no single file? name the area (Title Case), and (pattern: the shape). No code anchor needed; two agents naming the same shape converge on one node",
|
|
31852
31951
|
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",
|
|
31853
31952
|
verdict: "you can judge a prior we SHOWED you \u2014 confirm it if it held, refute it (with why) if it didn't; rendered whole via verdictBullet"
|
|
31854
31953
|
};
|
|
@@ -32085,7 +32184,7 @@ function readContextCard(root, hash2) {
|
|
|
32085
32184
|
function openProblems(store, now = Date.now()) {
|
|
32086
32185
|
const hit = openProblemsCache.get(store);
|
|
32087
32186
|
if (hit && now - hit.at < OPEN_PROBLEMS_TTL_MS) return hit.nodes;
|
|
32088
|
-
const nodes = store.findNodesByLabel("Problem").filter((p) => live(p) && !p.attrs["resolvedAt"] && p.attrs["mergedInto"] === void 0 && !isConstraintProblem(p));
|
|
32187
|
+
const nodes = [...store.findNodesByLabel("Problem"), ...store.findNodesByLabel("Vulnerability")].filter((p) => live(p) && !p.attrs["resolvedAt"] && p.attrs["mergedInto"] === void 0 && !isConstraintProblem(p));
|
|
32089
32188
|
openProblemsCache.set(store, { at: now, nodes });
|
|
32090
32189
|
return nodes;
|
|
32091
32190
|
}
|
|
@@ -32479,17 +32578,172 @@ var init_checkout_root = __esm({
|
|
|
32479
32578
|
}
|
|
32480
32579
|
});
|
|
32481
32580
|
|
|
32581
|
+
// src/process-identity.ts
|
|
32582
|
+
import { execFileSync } from "node:child_process";
|
|
32583
|
+
import { readFileSync as readFileSync10 } from "node:fs";
|
|
32584
|
+
function readProcessIdentity(pid, fresh = false) {
|
|
32585
|
+
if (!Number.isSafeInteger(pid) || pid <= 0) return null;
|
|
32586
|
+
if (pid === process.pid && self) return self;
|
|
32587
|
+
const cached2 = recent.get(pid);
|
|
32588
|
+
if (!fresh && cached2 && Date.now() - cached2.at < 1e3) return cached2.value;
|
|
32589
|
+
try {
|
|
32590
|
+
const run3 = (bin, args2) => execFileSync(bin, args2, {
|
|
32591
|
+
encoding: "utf8",
|
|
32592
|
+
windowsHide: true,
|
|
32593
|
+
timeout: 3e3,
|
|
32594
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
32595
|
+
env: { ...process.env, LC_ALL: "C", TZ: "UTC" }
|
|
32596
|
+
}).trim();
|
|
32597
|
+
let value;
|
|
32598
|
+
if (process.platform === "win32") {
|
|
32599
|
+
const ticks = run3("powershell.exe", [
|
|
32600
|
+
"-NoProfile",
|
|
32601
|
+
"-NonInteractive",
|
|
32602
|
+
"-Command",
|
|
32603
|
+
`(Get-Process -Id ${pid} -ErrorAction Stop).StartTime.ToUniversalTime().Ticks`
|
|
32604
|
+
]);
|
|
32605
|
+
if (!/^\d+$/.test(ticks)) return null;
|
|
32606
|
+
value = { key: `win32:${ticks}`, bornAt: Number((BigInt(ticks) - 621355968000000000n) / 10000n) };
|
|
32607
|
+
} else if (process.platform === "linux") {
|
|
32608
|
+
const stat4 = readFileSync10(`/proc/${pid}/stat`, "utf8");
|
|
32609
|
+
const ticks = stat4.slice(stat4.lastIndexOf(")") + 2).split(" ")[19];
|
|
32610
|
+
const bootId = readFileSync10("/proc/sys/kernel/random/boot_id", "utf8").trim();
|
|
32611
|
+
const boot = /^btime (\d+)$/m.exec(readFileSync10("/proc/stat", "utf8"))?.[1];
|
|
32612
|
+
const hz = Number(run3("getconf", ["CLK_TCK"]));
|
|
32613
|
+
if (!boot || !/^\d+$/.test(ticks) || !Number.isFinite(hz) || hz <= 0) return null;
|
|
32614
|
+
value = { key: `linux:${bootId}:${ticks}`, bornAt: Number(boot) * 1e3 + Number(ticks) * 1e3 / hz };
|
|
32615
|
+
} else if (process.platform === "darwin") {
|
|
32616
|
+
const start2 = run3("ps", ["-p", String(pid), "-o", "lstart="]);
|
|
32617
|
+
value = { key: `darwin:${start2}`, bornAt: Date.parse(`${start2} UTC`) };
|
|
32618
|
+
} else return null;
|
|
32619
|
+
if (!Number.isFinite(value.bornAt) || value.bornAt <= 0) return null;
|
|
32620
|
+
if (pid === process.pid) self = value;
|
|
32621
|
+
if (recent.size >= 64) recent.clear();
|
|
32622
|
+
recent.set(pid, { at: Date.now(), value });
|
|
32623
|
+
return value;
|
|
32624
|
+
} catch {
|
|
32625
|
+
return null;
|
|
32626
|
+
}
|
|
32627
|
+
}
|
|
32628
|
+
var recent, self;
|
|
32629
|
+
var init_process_identity = __esm({
|
|
32630
|
+
"src/process-identity.ts"() {
|
|
32631
|
+
"use strict";
|
|
32632
|
+
recent = /* @__PURE__ */ new Map();
|
|
32633
|
+
}
|
|
32634
|
+
});
|
|
32635
|
+
|
|
32636
|
+
// src/lock.ts
|
|
32637
|
+
import { existsSync as existsSync12, readFileSync as readFileSync11, unlinkSync } from "node:fs";
|
|
32638
|
+
function daemonLockPayload(lock) {
|
|
32639
|
+
return JSON.stringify({
|
|
32640
|
+
pid: lock.pid,
|
|
32641
|
+
webUiUrl: lock.webUiUrl,
|
|
32642
|
+
startedAt: lock.processStartedAt,
|
|
32643
|
+
...lock.pid === process.pid ? { processIdentity: readProcessIdentity(lock.pid)?.key } : {},
|
|
32644
|
+
...lock.wokeAt !== void 0 ? { wokeAt: lock.wokeAt } : {},
|
|
32645
|
+
...lock.entry ? { entry: lock.entry } : {},
|
|
32646
|
+
...lock.version ? { version: lock.version } : {}
|
|
32647
|
+
});
|
|
32648
|
+
}
|
|
32649
|
+
function isInstalledEntry(entry) {
|
|
32650
|
+
return /\/node_modules\/@inerrata-corporation\/errata\//.test(normEntry(entry) + "/");
|
|
32651
|
+
}
|
|
32652
|
+
function foreignDaemonNote(lock, selfEntry) {
|
|
32653
|
+
if (!lock.entry || normEntry(lock.entry) === normEntry(selfEntry)) return null;
|
|
32654
|
+
const runningInstalled = isInstalledEntry(lock.entry);
|
|
32655
|
+
const head2 = [
|
|
32656
|
+
`launched from ${runningInstalled ? "the installed package" : "a LOCAL BUILD"}, not this one${lock.version ? ` (it is ${lock.version})` : ""}:`,
|
|
32657
|
+
` running: ${lock.entry}`,
|
|
32658
|
+
` this: ${selfEntry}`
|
|
32659
|
+
];
|
|
32660
|
+
return runningInstalled ? [...head2, "this CLI is a different bundle from the daemon it is talking to \u2014 its view may not match what the daemon runs."] : [...head2, "`errata update` does not replace it. To move onto the installed package: errata stop, then errata dash."];
|
|
32661
|
+
}
|
|
32662
|
+
function isProcessAlive(pid) {
|
|
32663
|
+
if (!Number.isSafeInteger(pid) || pid <= 0) return false;
|
|
32664
|
+
try {
|
|
32665
|
+
process.kill(pid, 0);
|
|
32666
|
+
return true;
|
|
32667
|
+
} catch (err2) {
|
|
32668
|
+
return err2.code === "EPERM";
|
|
32669
|
+
}
|
|
32670
|
+
}
|
|
32671
|
+
function readDaemonLock(lockPath) {
|
|
32672
|
+
if (!existsSync12(lockPath)) return null;
|
|
32673
|
+
try {
|
|
32674
|
+
return parseDaemonLock(readFileSync11(lockPath, "utf8"));
|
|
32675
|
+
} catch {
|
|
32676
|
+
return null;
|
|
32677
|
+
}
|
|
32678
|
+
}
|
|
32679
|
+
function parseDaemonLock(raw2) {
|
|
32680
|
+
try {
|
|
32681
|
+
const lock = JSON.parse(raw2);
|
|
32682
|
+
return lock && Number.isSafeInteger(lock.pid) && lock.pid > 0 ? lock : null;
|
|
32683
|
+
} catch {
|
|
32684
|
+
return null;
|
|
32685
|
+
}
|
|
32686
|
+
}
|
|
32687
|
+
function daemonLockState(lock, fresh = false) {
|
|
32688
|
+
if (!lock || !isProcessAlive(lock.pid)) return "stale";
|
|
32689
|
+
const identity = readProcessIdentity(lock.pid, fresh);
|
|
32690
|
+
if (!identity) return "unknown";
|
|
32691
|
+
if (lock.processIdentity) return lock.processIdentity === identity.key ? "running" : "stale";
|
|
32692
|
+
if (!Number.isFinite(lock.startedAt) || lock.startedAt <= 0) return "unknown";
|
|
32693
|
+
return identity.bornAt <= lock.startedAt ? "running" : "stale";
|
|
32694
|
+
}
|
|
32695
|
+
function isDaemonAlive(lockPath) {
|
|
32696
|
+
return daemonLockState(readDaemonLock(lockPath)) === "running";
|
|
32697
|
+
}
|
|
32698
|
+
function daemonLockBlocksStartup(lockPath) {
|
|
32699
|
+
return daemonLockState(readDaemonLock(lockPath), true) !== "stale";
|
|
32700
|
+
}
|
|
32701
|
+
function stopLockedDaemon(lockPath) {
|
|
32702
|
+
let original;
|
|
32703
|
+
try {
|
|
32704
|
+
original = readFileSync11(lockPath, "utf8");
|
|
32705
|
+
} catch {
|
|
32706
|
+
return "missing";
|
|
32707
|
+
}
|
|
32708
|
+
const lock = parseDaemonLock(original);
|
|
32709
|
+
if (!lock) return "unknown";
|
|
32710
|
+
const state = daemonLockState(lock, true);
|
|
32711
|
+
try {
|
|
32712
|
+
if (readFileSync11(lockPath, "utf8") !== original) return "changed";
|
|
32713
|
+
} catch {
|
|
32714
|
+
return "changed";
|
|
32715
|
+
}
|
|
32716
|
+
if (state === "unknown") return "unknown";
|
|
32717
|
+
if (state === "stale") {
|
|
32718
|
+
unlinkSync(lockPath);
|
|
32719
|
+
return "stale";
|
|
32720
|
+
}
|
|
32721
|
+
process.kill(lock.pid, "SIGTERM");
|
|
32722
|
+
return "signaled";
|
|
32723
|
+
}
|
|
32724
|
+
var normEntry;
|
|
32725
|
+
var init_lock = __esm({
|
|
32726
|
+
"src/lock.ts"() {
|
|
32727
|
+
"use strict";
|
|
32728
|
+
init_process_identity();
|
|
32729
|
+
normEntry = (p) => {
|
|
32730
|
+
const s = p.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
32731
|
+
return /^[A-Za-z]:\//.test(s) ? s.toLowerCase() : s;
|
|
32732
|
+
};
|
|
32733
|
+
}
|
|
32734
|
+
});
|
|
32735
|
+
|
|
32482
32736
|
// src/registry.ts
|
|
32483
|
-
import { existsSync as
|
|
32737
|
+
import { existsSync as existsSync13, readFileSync as readFileSync12, writeFileSync as writeFileSync9 } from "node:fs";
|
|
32484
32738
|
import { join as join11 } from "node:path";
|
|
32485
32739
|
function registryPath() {
|
|
32486
32740
|
return process.env["ERRATA_REGISTRY_PATH"] ?? join11(globalDir(), "workspaces.json");
|
|
32487
32741
|
}
|
|
32488
32742
|
function read() {
|
|
32489
32743
|
const p = registryPath();
|
|
32490
|
-
if (!
|
|
32744
|
+
if (!existsSync13(p)) return { version: 1, workspaces: {} };
|
|
32491
32745
|
try {
|
|
32492
|
-
const parsed = JSON.parse(
|
|
32746
|
+
const parsed = JSON.parse(readFileSync12(p, "utf8"));
|
|
32493
32747
|
return { version: 1, workspaces: parsed.workspaces ?? {} };
|
|
32494
32748
|
} catch {
|
|
32495
32749
|
return { version: 1, workspaces: {} };
|
|
@@ -32497,9 +32751,9 @@ function read() {
|
|
|
32497
32751
|
}
|
|
32498
32752
|
function registryCorrupt() {
|
|
32499
32753
|
const p = registryPath();
|
|
32500
|
-
if (!
|
|
32754
|
+
if (!existsSync13(p)) return false;
|
|
32501
32755
|
try {
|
|
32502
|
-
JSON.parse(
|
|
32756
|
+
JSON.parse(readFileSync12(p, "utf8"));
|
|
32503
32757
|
return false;
|
|
32504
32758
|
} catch {
|
|
32505
32759
|
return true;
|
|
@@ -32552,7 +32806,7 @@ function pruneMissingWorkspaces() {
|
|
|
32552
32806
|
const reg = read();
|
|
32553
32807
|
const removed = [];
|
|
32554
32808
|
for (const [id, entry] of Object.entries(reg.workspaces)) {
|
|
32555
|
-
if (!
|
|
32809
|
+
if (!existsSync13(entry.path)) {
|
|
32556
32810
|
removed.push(entry);
|
|
32557
32811
|
delete reg.workspaces[id];
|
|
32558
32812
|
}
|
|
@@ -32561,19 +32815,14 @@ function pruneMissingWorkspaces() {
|
|
|
32561
32815
|
return removed;
|
|
32562
32816
|
}
|
|
32563
32817
|
function workspaceStatus(entry) {
|
|
32564
|
-
const missing = !
|
|
32818
|
+
const missing = !existsSync13(entry.path);
|
|
32565
32819
|
const lockPath = workspacePaths(entry.path).daemonLock;
|
|
32566
32820
|
let running = false;
|
|
32567
32821
|
let webUiUrl = null;
|
|
32568
|
-
|
|
32569
|
-
|
|
32570
|
-
|
|
32571
|
-
|
|
32572
|
-
running = true;
|
|
32573
|
-
webUiUrl = lock.webUiUrl;
|
|
32574
|
-
}
|
|
32575
|
-
} catch {
|
|
32576
|
-
}
|
|
32822
|
+
const lock = readDaemonLock(lockPath);
|
|
32823
|
+
if (lock?.webUiUrl && daemonLockState(lock) === "running") {
|
|
32824
|
+
running = true;
|
|
32825
|
+
webUiUrl = lock.webUiUrl;
|
|
32577
32826
|
}
|
|
32578
32827
|
return { ...entry, running, webUiUrl, missing };
|
|
32579
32828
|
}
|
|
@@ -32583,19 +32832,12 @@ function listWorkspaces() {
|
|
|
32583
32832
|
function listWorkspaceEntries() {
|
|
32584
32833
|
return Object.values(read().workspaces).sort((a, b) => b.lastSeenAt - a.lastSeenAt);
|
|
32585
32834
|
}
|
|
32586
|
-
function pidAlive(pid) {
|
|
32587
|
-
try {
|
|
32588
|
-
process.kill(pid, 0);
|
|
32589
|
-
return true;
|
|
32590
|
-
} catch (err2) {
|
|
32591
|
-
return err2.code === "EPERM";
|
|
32592
|
-
}
|
|
32593
|
-
}
|
|
32594
32835
|
var init_registry = __esm({
|
|
32595
32836
|
"src/registry.ts"() {
|
|
32596
32837
|
"use strict";
|
|
32597
32838
|
init_paths();
|
|
32598
32839
|
init_checkout_root();
|
|
32840
|
+
init_lock();
|
|
32599
32841
|
}
|
|
32600
32842
|
});
|
|
32601
32843
|
|
|
@@ -33892,7 +34134,7 @@ var init_dual_augment = __esm({
|
|
|
33892
34134
|
|
|
33893
34135
|
// ../../packages/indexer/src/parse-cache.ts
|
|
33894
34136
|
import { createHash as createHash6 } from "node:crypto";
|
|
33895
|
-
import { existsSync as
|
|
34137
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync6, readFileSync as readFileSync13, readdirSync as readdirSync2, rmSync as rmSync2, statSync as statSync2, writeFileSync as writeFileSync10 } from "node:fs";
|
|
33896
34138
|
import { homedir as homedir3 } from "node:os";
|
|
33897
34139
|
import { join as join12 } from "node:path";
|
|
33898
34140
|
function parseCacheDir() {
|
|
@@ -33907,7 +34149,7 @@ function entryPath(dir, key) {
|
|
|
33907
34149
|
function readParseCache(dir, key) {
|
|
33908
34150
|
const file2 = entryPath(dir, key);
|
|
33909
34151
|
try {
|
|
33910
|
-
const raw2 =
|
|
34152
|
+
const raw2 = readFileSync13(file2, "utf8");
|
|
33911
34153
|
const parsed = JSON.parse(raw2);
|
|
33912
34154
|
if (parsed.v !== PARSE_CACHE_VERSION || !Array.isArray(parsed.symbols)) return null;
|
|
33913
34155
|
return { symbols: parsed.symbols, reExports: parsed.reExports ?? [] };
|
|
@@ -33936,7 +34178,7 @@ function sweepParseCacheOnce(dir, now = Date.now()) {
|
|
|
33936
34178
|
sweptThisProcess = true;
|
|
33937
34179
|
let removed = 0;
|
|
33938
34180
|
try {
|
|
33939
|
-
if (!
|
|
34181
|
+
if (!existsSync14(dir)) return 0;
|
|
33940
34182
|
for (const bucket of readdirSync2(dir)) {
|
|
33941
34183
|
const bucketDir = join12(dir, bucket);
|
|
33942
34184
|
let names;
|
|
@@ -34194,11 +34436,11 @@ var init_identity3 = __esm({
|
|
|
34194
34436
|
});
|
|
34195
34437
|
|
|
34196
34438
|
// ../../packages/indexer/src/pipeline.ts
|
|
34197
|
-
import { appendFileSync, readFileSync as
|
|
34439
|
+
import { appendFileSync, readFileSync as readFileSync14, statSync as statSync3 } from "node:fs";
|
|
34198
34440
|
import { readdir } from "node:fs/promises";
|
|
34199
34441
|
import { extname, join as join13, relative as relative2, sep } from "node:path";
|
|
34200
34442
|
import { createHash as createHash7 } from "node:crypto";
|
|
34201
|
-
import { execFileSync } from "node:child_process";
|
|
34443
|
+
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
34202
34444
|
function nowTs() {
|
|
34203
34445
|
return indexNow ?? Date.now();
|
|
34204
34446
|
}
|
|
@@ -34334,7 +34576,7 @@ async function incrementalReindex(store, rootPath, workspaceId2, changedAbsPaths
|
|
|
34334
34576
|
for (const rel of [...changedRelPaths]) {
|
|
34335
34577
|
let h;
|
|
34336
34578
|
try {
|
|
34337
|
-
h = createHash7("sha256").update(
|
|
34579
|
+
h = createHash7("sha256").update(readFileSync14(join13(rootPath, rel))).digest("hex");
|
|
34338
34580
|
} catch {
|
|
34339
34581
|
continue;
|
|
34340
34582
|
}
|
|
@@ -34389,7 +34631,7 @@ async function incrementalReindex(store, rootPath, workspaceId2, changedAbsPaths
|
|
|
34389
34631
|
if (!provider) continue;
|
|
34390
34632
|
let symbols;
|
|
34391
34633
|
try {
|
|
34392
|
-
symbols = provider.extractSymbols(
|
|
34634
|
+
symbols = provider.extractSymbols(readFileSync14(abs, "utf8"), abs);
|
|
34393
34635
|
} catch {
|
|
34394
34636
|
continue;
|
|
34395
34637
|
}
|
|
@@ -34709,7 +34951,7 @@ async function runIndexer(store, opts) {
|
|
|
34709
34951
|
report.filesSkipped++;
|
|
34710
34952
|
continue;
|
|
34711
34953
|
}
|
|
34712
|
-
source =
|
|
34954
|
+
source = readFileSync14(f.absPath, "utf8");
|
|
34713
34955
|
} catch {
|
|
34714
34956
|
report.filesSkipped++;
|
|
34715
34957
|
continue;
|
|
@@ -34781,7 +35023,7 @@ async function runIndexer(store, opts) {
|
|
|
34781
35023
|
const depth = fileNode.relPath.split("/").length;
|
|
34782
35024
|
if (depth !== 3) continue;
|
|
34783
35025
|
try {
|
|
34784
|
-
const pkg = JSON.parse(
|
|
35026
|
+
const pkg = JSON.parse(readFileSync14(fileNode.absPath, "utf8"));
|
|
34785
35027
|
if (!pkg.name) continue;
|
|
34786
35028
|
const pkgDir = fileNode.relPath.replace(/\/package\.json$/, "");
|
|
34787
35029
|
const candidates = [
|
|
@@ -35199,7 +35441,7 @@ async function scan(root, current, ignores, providers, out2) {
|
|
|
35199
35441
|
function gitListRelPaths(root, ignores) {
|
|
35200
35442
|
let stdout;
|
|
35201
35443
|
try {
|
|
35202
|
-
stdout =
|
|
35444
|
+
stdout = execFileSync2(
|
|
35203
35445
|
"git",
|
|
35204
35446
|
["-C", root, "ls-files", "--cached", "--others", "--exclude-standard", "-z"],
|
|
35205
35447
|
{
|
|
@@ -35257,7 +35499,7 @@ function upsertFile(store, id, f, workspaceId2, skip) {
|
|
|
35257
35499
|
if (existing && fileUnchanged(existing.attrs, f, skip)) return;
|
|
35258
35500
|
let contentHash;
|
|
35259
35501
|
try {
|
|
35260
|
-
contentHash = createHash7("sha256").update(
|
|
35502
|
+
contentHash = createHash7("sha256").update(readFileSync14(f.absPath)).digest("hex");
|
|
35261
35503
|
} catch {
|
|
35262
35504
|
}
|
|
35263
35505
|
const carried = { ...existing?.attrs ?? {} };
|
|
@@ -39641,7 +39883,7 @@ ${JSON.stringify(symbolNames, null, 2)}`);
|
|
|
39641
39883
|
// ../../packages/indexer/src/languages/tree-sitter-loader.ts
|
|
39642
39884
|
import { fileURLToPath } from "node:url";
|
|
39643
39885
|
import { dirname as dirname7, join as join14 } from "node:path";
|
|
39644
|
-
import { existsSync as
|
|
39886
|
+
import { existsSync as existsSync15, readdirSync as readdirSync3 } from "node:fs";
|
|
39645
39887
|
import { createRequire as createRequire2 } from "node:module";
|
|
39646
39888
|
function entryDir() {
|
|
39647
39889
|
try {
|
|
@@ -39656,7 +39898,7 @@ function entryDir() {
|
|
|
39656
39898
|
function findWasmDir() {
|
|
39657
39899
|
const here = entryDir();
|
|
39658
39900
|
const seaWasm = join14(here, "resources", "wasm");
|
|
39659
|
-
if (
|
|
39901
|
+
if (existsSync15(join14(seaWasm, "tree-sitter-typescript.wasm"))) return seaWasm;
|
|
39660
39902
|
let dir = here;
|
|
39661
39903
|
for (let i2 = 0; i2 < 6; i2++) {
|
|
39662
39904
|
const flat = join14(
|
|
@@ -39666,13 +39908,13 @@ function findWasmDir() {
|
|
|
39666
39908
|
"tree-sitter-wasm",
|
|
39667
39909
|
"wasm"
|
|
39668
39910
|
);
|
|
39669
|
-
if (
|
|
39911
|
+
if (existsSync15(join14(flat, "tree-sitter-typescript.wasm"))) return flat;
|
|
39670
39912
|
dir = dirname7(dir);
|
|
39671
39913
|
}
|
|
39672
39914
|
let root = here;
|
|
39673
39915
|
for (let i2 = 0; i2 < 6; i2++) {
|
|
39674
39916
|
const pnpmDir = join14(root, "node_modules", ".pnpm");
|
|
39675
|
-
if (
|
|
39917
|
+
if (existsSync15(pnpmDir)) {
|
|
39676
39918
|
for (const entry of readdirSync3(pnpmDir)) {
|
|
39677
39919
|
if (entry.startsWith("@vscode+tree-sitter-wasm@")) {
|
|
39678
39920
|
const candidate = join14(
|
|
@@ -39683,7 +39925,7 @@ function findWasmDir() {
|
|
|
39683
39925
|
"tree-sitter-wasm",
|
|
39684
39926
|
"wasm"
|
|
39685
39927
|
);
|
|
39686
|
-
if (
|
|
39928
|
+
if (existsSync15(join14(candidate, "tree-sitter-typescript.wasm"))) {
|
|
39687
39929
|
return candidate;
|
|
39688
39930
|
}
|
|
39689
39931
|
}
|
|
@@ -39698,17 +39940,17 @@ function findWasmDir() {
|
|
|
39698
39940
|
function findRuntimeDir() {
|
|
39699
39941
|
const here = entryDir();
|
|
39700
39942
|
const seaRuntime = join14(here, "resources", "wasm");
|
|
39701
|
-
if (
|
|
39943
|
+
if (existsSync15(join14(seaRuntime, "web-tree-sitter.wasm"))) return seaRuntime;
|
|
39702
39944
|
let dir = here;
|
|
39703
39945
|
for (let i2 = 0; i2 < 6; i2++) {
|
|
39704
39946
|
const flat = join14(dir, "node_modules", "web-tree-sitter");
|
|
39705
|
-
if (
|
|
39947
|
+
if (existsSync15(join14(flat, "web-tree-sitter.wasm"))) return flat;
|
|
39706
39948
|
dir = dirname7(dir);
|
|
39707
39949
|
}
|
|
39708
39950
|
let root = here;
|
|
39709
39951
|
for (let i2 = 0; i2 < 6; i2++) {
|
|
39710
39952
|
const pnpmDir = join14(root, "node_modules", ".pnpm");
|
|
39711
|
-
if (
|
|
39953
|
+
if (existsSync15(pnpmDir)) {
|
|
39712
39954
|
for (const entry of readdirSync3(pnpmDir)) {
|
|
39713
39955
|
if (entry.startsWith("web-tree-sitter@")) {
|
|
39714
39956
|
const candidate = join14(
|
|
@@ -39717,7 +39959,7 @@ function findRuntimeDir() {
|
|
|
39717
39959
|
"node_modules",
|
|
39718
39960
|
"web-tree-sitter"
|
|
39719
39961
|
);
|
|
39720
|
-
if (
|
|
39962
|
+
if (existsSync15(join14(candidate, "web-tree-sitter.wasm"))) {
|
|
39721
39963
|
return candidate;
|
|
39722
39964
|
}
|
|
39723
39965
|
}
|
|
@@ -42666,7 +42908,7 @@ var init_src11 = __esm({
|
|
|
42666
42908
|
});
|
|
42667
42909
|
|
|
42668
42910
|
// src/reconcile.ts
|
|
42669
|
-
import { execFileSync as
|
|
42911
|
+
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
42670
42912
|
import { readdirSync as readdirSync4, statSync as statSync4 } from "node:fs";
|
|
42671
42913
|
import { join as join15, relative as relative3, sep as sep2 } from "node:path";
|
|
42672
42914
|
function indexerWouldScan(rel) {
|
|
@@ -42680,7 +42922,7 @@ function indexerWouldScan(rel) {
|
|
|
42680
42922
|
function gitSourceFiles(root) {
|
|
42681
42923
|
let stdout;
|
|
42682
42924
|
try {
|
|
42683
|
-
stdout =
|
|
42925
|
+
stdout = execFileSync3(
|
|
42684
42926
|
"git",
|
|
42685
42927
|
["-C", root, "ls-files", "--cached", "--others", "--exclude-standard", "-z"],
|
|
42686
42928
|
{ encoding: "utf8", maxBuffer: 128 * 1024 * 1024, windowsHide: true, stdio: ["ignore", "pipe", "ignore"] }
|
|
@@ -42856,7 +43098,7 @@ __export(mcp_exports, {
|
|
|
42856
43098
|
runTool: () => runTool,
|
|
42857
43099
|
searchGraph: () => searchGraph
|
|
42858
43100
|
});
|
|
42859
|
-
import { existsSync as
|
|
43101
|
+
import { existsSync as existsSync16, readFileSync as readFileSync15 } from "node:fs";
|
|
42860
43102
|
import { resolve as resolve3 } from "node:path";
|
|
42861
43103
|
function collectEnrichmentPulls(store, opts = {}) {
|
|
42862
43104
|
const pending = store.findNodesByLabel("Solution").filter((s) => s.attrs["enrichmentPending"] === true).filter((s) => !opts.onlyUnsurfaced || s.attrs["enrichmentSurfaced"] !== true);
|
|
@@ -42893,7 +43135,7 @@ function takeEnrichmentNudge(store) {
|
|
|
42893
43135
|
` + items;
|
|
42894
43136
|
}
|
|
42895
43137
|
function takeDiscriminatorNudge(path2) {
|
|
42896
|
-
if (!path2 || !
|
|
43138
|
+
if (!path2 || !existsSync16(path2)) return null;
|
|
42897
43139
|
let shared;
|
|
42898
43140
|
try {
|
|
42899
43141
|
shared = openGraphStore({ path: path2 });
|
|
@@ -43024,10 +43266,10 @@ function showNode(store, node2, maxLines) {
|
|
|
43024
43266
|
if (!relPath) return { found: false, reason: "no file owner for node" };
|
|
43025
43267
|
const workspaceRoot = process.cwd();
|
|
43026
43268
|
const absPath = resolve3(workspaceRoot, relPath);
|
|
43027
|
-
if (!
|
|
43269
|
+
if (!existsSync16(absPath)) {
|
|
43028
43270
|
return { found: false, reason: `file not found on disk: ${absPath}` };
|
|
43029
43271
|
}
|
|
43030
|
-
const source =
|
|
43272
|
+
const source = readFileSync15(absPath, "utf8");
|
|
43031
43273
|
const attrs = node2.attrs;
|
|
43032
43274
|
let startByte = attrs["bodyStartByte"] ?? attrs["startByte"];
|
|
43033
43275
|
let endByte = attrs["bodyEndByte"] ?? attrs["endByte"];
|
|
@@ -43329,47 +43571,9 @@ var init_mcp = __esm({
|
|
|
43329
43571
|
init_reconcile();
|
|
43330
43572
|
init_agent_signals();
|
|
43331
43573
|
INSTRUCTIONS = [
|
|
43332
|
-
|
|
43333
|
-
|
|
43334
|
-
|
|
43335
|
-
// from your WORK deterministically, and the one thing it asks of the agent — a
|
|
43336
|
-
// one-line root cause at a fix — rides INLINE on the next tool response (the ⚡
|
|
43337
|
-
// errata line; see the dispatch's enrichment piggyback) instead of a fenced
|
|
43338
|
-
// protocol the agent has to remember. So this stays short: tool-routing steering
|
|
43339
|
-
// plus a single line about the inline nudge. Per-tool routing lives in each tool's
|
|
43340
|
-
// own `description` (delivered via tools/list). Don't re-add a tool table here.
|
|
43341
|
-
"errata is a LIVE, bi-temporal code graph of this workspace, kept current by a",
|
|
43342
|
-
"file watcher \u2014 a SEPARATE DIAGNOSTIC AXIS to run ALONGSIDE grep/glob/read, not",
|
|
43343
|
-
"instead of them. For STRUCTURAL questions (callers of callers, blast-radius,",
|
|
43344
|
-
"rename lineage) prefer it: faster, more complete, and it reaches relationships",
|
|
43345
|
-
"grep can't. Each tool's description says when to reach for it. Fall back to",
|
|
43346
|
-
'grep/read when a tool returns found:false (ESPECIALLY reason:"unresolved" \u2014 the',
|
|
43347
|
-
"name was not recognized, NOT an empty answer; an empty list like callers:[] is a",
|
|
43348
|
-
'confident "none" \u2014 trust it), when you need EXACT bytes before a high-stakes',
|
|
43349
|
-
"edit, or for an unindexed file/language. Always confirm exact bytes with a read",
|
|
43350
|
-
"before editing.",
|
|
43351
|
-
"",
|
|
43352
|
-
"errata is a cloud knowledge substrate \u2014 AND ALSO this workspace's code graph.",
|
|
43353
|
-
"The problems you hit and the fixes you make become shared knowledge other agents",
|
|
43354
|
-
"recall. That capture is automatic: derived from your edits/commands/commits \u2014 no",
|
|
43355
|
-
"emit needed. Just after you resolve something a tool result may carry a one-line",
|
|
43356
|
-
"\u26A1 errata note asking the ROOT CAUSE; answer via errata.annotate_resolution when",
|
|
43357
|
-
"you know it, skip it otherwise.",
|
|
43358
|
-
"",
|
|
43359
|
-
"Two things it CAN'T derive \u2014 only you witness them, and this is a CAPTURE",
|
|
43360
|
-
"PROTOCOL, not optional formatting: a problem or fix you state only in prose, a",
|
|
43361
|
-
"list, or your own numbering is SILENTLY LOST \u2014 the tag is the ONLY thing recorded.",
|
|
43362
|
-
"So the moment you state one, wrap it inline (no fence, no extra call):",
|
|
43363
|
-
// Signal tokens come from the single source (agent-signals.ts) so this always-on
|
|
43364
|
-
// block can't teach a grammar the parser rejects. Referent is "its-id" here — the
|
|
43365
|
-
// raw MCP channel has no primed handles, so the agent cites a tool-result id.
|
|
43366
|
-
` \u2022 ${TAG_EXAMPLE.problem()} \u2014 EVERY problem you notice or report ([?\u2026] = TODO)`,
|
|
43367
|
-
` \u2022 ${TAG_EXAMPLE.fix("its-id")} \u2014 your edit fixed a problem errata showed you`,
|
|
43368
|
-
"Tag every one you state \u2014 we filter downstream, so don't self-censor or batch.",
|
|
43369
|
-
"",
|
|
43370
|
-
"Graph-as-files: the graph is ALSO a virtual FS \u2014 Read (or `cat`)",
|
|
43371
|
-
".errata/g/<verb>/<seed> to run a query as a file read (e.g. .errata/g/burst/",
|
|
43372
|
-
"<symbol>, /why/<sym>, /trace/<a>..<b>). Read .errata/g/index for the vocabulary."
|
|
43574
|
+
"errata is a live code and knowledge graph, a SEPARATE DIAGNOSTIC AXIS alongside grep/read for callers, blast radius, rename lineage and prior fixes. Fall back to read/search on found:false (unresolved is not an empty answer), or for unindexed code. Confirm exact bytes before editing.",
|
|
43575
|
+
buildAgentInstruction({ signals: ["prior", "problem", "vulnerability", "fix"], referent: "its-id" }),
|
|
43576
|
+
"Read .errata/g/index for graph-as-files query paths. A tool result may ask for a root cause; answer via errata.annotate_resolution when known."
|
|
43373
43577
|
].join("\n");
|
|
43374
43578
|
AUDIT_RUN_THRESHOLD = 5;
|
|
43375
43579
|
AUDIT_NUDGE_COOLDOWN = 12;
|
|
@@ -43784,7 +43988,7 @@ var init_mcp = __esm({
|
|
|
43784
43988
|
const local = causalChain(store, { seedId: id, direction: "both", maxHops, limit });
|
|
43785
43989
|
try {
|
|
43786
43990
|
const path2 = sharedStorePath();
|
|
43787
|
-
if (!
|
|
43991
|
+
if (!existsSync16(path2)) return { found: true, ...local };
|
|
43788
43992
|
const shared = openGraphStore({ path: path2 });
|
|
43789
43993
|
try {
|
|
43790
43994
|
if (!shared.getNode(id)) return { found: true, ...local };
|
|
@@ -43961,7 +44165,7 @@ var init_mcp = __esm({
|
|
|
43961
44165
|
},
|
|
43962
44166
|
{
|
|
43963
44167
|
name: "errata.problems",
|
|
43964
|
-
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.",
|
|
44168
|
+
description: "List the workspace's Problem and Vulnerability 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.",
|
|
43965
44169
|
inputSchema: {
|
|
43966
44170
|
type: "object",
|
|
43967
44171
|
properties: {
|
|
@@ -43973,13 +44177,15 @@ var init_mcp = __esm({
|
|
|
43973
44177
|
const want = String(args2["status"] ?? "open");
|
|
43974
44178
|
const limit = Math.max(1, Math.min(200, Number(args2["limit"] ?? 50)));
|
|
43975
44179
|
const RETRACTIONS = /* @__PURE__ */ new Set(["false_positive", "invalid", "duplicate"]);
|
|
43976
|
-
const rows = store.findAllVersionsByLabel("Problem").map((p) => {
|
|
44180
|
+
const rows = [...store.findAllVersionsByLabel("Problem"), ...store.findAllVersionsByLabel("Vulnerability")].map((p) => {
|
|
43977
44181
|
const ra = p.attrs["resolvedAs"];
|
|
43978
44182
|
const status = ra && RETRACTIONS.has(ra) ? ra : p.attrs["resolvedAt"] != null ? "resolved" : isConstraintProblem(p) ? "constraint" : "open";
|
|
43979
44183
|
const anchorEdge = store.outEdges(p.id, ["ANCHORED_AT"])[0];
|
|
43980
44184
|
const anchor = anchorEdge ? store.getNode(anchorEdge.to)?.description : void 0;
|
|
43981
44185
|
return {
|
|
43982
44186
|
id: p.id,
|
|
44187
|
+
label: p.label,
|
|
44188
|
+
...p.label === "Vulnerability" ? { assessment: p.attrs["assessment"] } : {},
|
|
43983
44189
|
problem: p.description,
|
|
43984
44190
|
status,
|
|
43985
44191
|
createdAt: p.createdAt,
|
|
@@ -44385,7 +44591,7 @@ var init_mcp = __esm({
|
|
|
44385
44591
|
inputSchema: { type: "object", properties: {} },
|
|
44386
44592
|
handler: () => {
|
|
44387
44593
|
const path2 = sharedStorePath();
|
|
44388
|
-
if (!
|
|
44594
|
+
if (!existsSync16(path2)) return { count: 0, pending: [] };
|
|
44389
44595
|
const shared = openGraphStore({ path: path2 });
|
|
44390
44596
|
try {
|
|
44391
44597
|
const pending = pendingAbstractions(shared);
|
|
@@ -44413,7 +44619,7 @@ var init_mcp = __esm({
|
|
|
44413
44619
|
},
|
|
44414
44620
|
handler: (args2) => {
|
|
44415
44621
|
const path2 = sharedStorePath();
|
|
44416
|
-
if (!
|
|
44622
|
+
if (!existsSync16(path2)) return { count: 0, pending: [] };
|
|
44417
44623
|
const shared = openGraphStore({ path: path2 });
|
|
44418
44624
|
try {
|
|
44419
44625
|
const pending = pendingDiscriminators(shared, {
|
|
@@ -44457,7 +44663,7 @@ var init_mcp = __esm({
|
|
|
44457
44663
|
},
|
|
44458
44664
|
handler: (args2) => {
|
|
44459
44665
|
const path2 = sharedStorePath();
|
|
44460
|
-
if (!
|
|
44666
|
+
if (!existsSync16(path2)) return { count: 0, routes: [] };
|
|
44461
44667
|
const shared = openGraphStore({ path: path2 });
|
|
44462
44668
|
try {
|
|
44463
44669
|
const result = triageOf(shared, {
|
|
@@ -52344,11 +52550,11 @@ var init_tool_index = __esm({
|
|
|
52344
52550
|
|
|
52345
52551
|
// src/outbox.ts
|
|
52346
52552
|
import {
|
|
52347
|
-
existsSync as
|
|
52553
|
+
existsSync as existsSync17,
|
|
52348
52554
|
readdirSync as readdirSync5,
|
|
52349
|
-
readFileSync as
|
|
52555
|
+
readFileSync as readFileSync16,
|
|
52350
52556
|
renameSync,
|
|
52351
|
-
unlinkSync,
|
|
52557
|
+
unlinkSync as unlinkSync2,
|
|
52352
52558
|
writeFileSync as writeFileSync12
|
|
52353
52559
|
} from "node:fs";
|
|
52354
52560
|
import { join as join17 } from "node:path";
|
|
@@ -52362,7 +52568,7 @@ function enqueueOutbox(paths, payload) {
|
|
|
52362
52568
|
}
|
|
52363
52569
|
async function flushOutbox(paths, client, store) {
|
|
52364
52570
|
ensureDir(paths.outbox);
|
|
52365
|
-
const entries =
|
|
52571
|
+
const entries = existsSync17(paths.outbox) ? readdirSync5(paths.outbox) : [];
|
|
52366
52572
|
let uploaded = 0;
|
|
52367
52573
|
let failed = 0;
|
|
52368
52574
|
const quarantine = (abs, reason) => {
|
|
@@ -52376,7 +52582,7 @@ async function flushOutbox(paths, client, store) {
|
|
|
52376
52582
|
const abs = join17(paths.outbox, f);
|
|
52377
52583
|
let payload;
|
|
52378
52584
|
try {
|
|
52379
|
-
payload = JSON.parse(
|
|
52585
|
+
payload = JSON.parse(readFileSync16(abs, "utf8"));
|
|
52380
52586
|
} catch {
|
|
52381
52587
|
failed++;
|
|
52382
52588
|
quarantine(abs, "unparseable JSON");
|
|
@@ -52411,7 +52617,7 @@ async function flushOutbox(paths, client, store) {
|
|
|
52411
52617
|
}
|
|
52412
52618
|
}
|
|
52413
52619
|
}
|
|
52414
|
-
|
|
52620
|
+
unlinkSync2(abs);
|
|
52415
52621
|
if (res.accepted === 0) uploaded++;
|
|
52416
52622
|
} catch (err2) {
|
|
52417
52623
|
failed++;
|
|
@@ -52421,7 +52627,7 @@ async function flushOutbox(paths, client, store) {
|
|
|
52421
52627
|
}
|
|
52422
52628
|
}
|
|
52423
52629
|
}
|
|
52424
|
-
const remainingFiles =
|
|
52630
|
+
const remainingFiles = existsSync17(paths.outbox) ? readdirSync5(paths.outbox).filter((e) => e.endsWith(".json")) : [];
|
|
52425
52631
|
return { uploaded, failed, remaining: remainingFiles.length };
|
|
52426
52632
|
}
|
|
52427
52633
|
var init_outbox = __esm({
|
|
@@ -52544,7 +52750,8 @@ function errorRecallTerms(errorText) {
|
|
|
52544
52750
|
}
|
|
52545
52751
|
function recallLine(n, token) {
|
|
52546
52752
|
const desc = (n.description ?? "").replace(/\s+/g, " ").slice(0, 120);
|
|
52547
|
-
|
|
52753
|
+
const label = n.label === "Vulnerability" ? `Vulnerability; ${n.attrs["assessment"] ?? "unassessed"}` : n.label;
|
|
52754
|
+
return `- [${label}] ${desc} \u2192 ${token}`;
|
|
52548
52755
|
}
|
|
52549
52756
|
function recallForFile(store, relPath) {
|
|
52550
52757
|
return fileRecall(store, relPath)?.context ?? null;
|
|
@@ -52565,7 +52772,7 @@ function fileRecall(store, relPath) {
|
|
|
52565
52772
|
const shownRelated = priors.related.slice(0, 4);
|
|
52566
52773
|
for (const p of shownProblems) {
|
|
52567
52774
|
const hasCause = store.outEdges(p.id, ["CAUSED_BY"]).some((e) => store.getNode(e.to)?.label === "RootCause");
|
|
52568
|
-
const causeCue = hasCause ? "" : ` \xB7 ${TAG_EXAMPLE.triageMint()} to diagnose its cause`;
|
|
52775
|
+
const causeCue = hasCause ? "" : ` \xB7 ${p.label === "Vulnerability" ? `(cause:#${p.id} the mechanism)` : TAG_EXAMPLE.triageMint()} to diagnose its cause`;
|
|
52569
52776
|
lines.push(
|
|
52570
52777
|
recallLine(p, `${TAG_EXAMPLE.fix(p.id)} if you resolved it \xB7 ${TAG_EXAMPLE.prior(p.id)} to cite${causeCue}`)
|
|
52571
52778
|
);
|
|
@@ -52986,12 +53193,17 @@ function buildWebUi(deps) {
|
|
|
52986
53193
|
block,
|
|
52987
53194
|
lastInjectedHash
|
|
52988
53195
|
});
|
|
53196
|
+
let systemMessage = null;
|
|
52989
53197
|
if (sid && block && recallCardEnabled() && (decision || atPrompt)) {
|
|
52990
53198
|
const card = readContextCard(deps.paths.root, block.hash);
|
|
52991
|
-
if (card)
|
|
53199
|
+
if (card) {
|
|
53200
|
+
rememberCard(sid, card);
|
|
53201
|
+
if (decision && sid.startsWith("codex:")) systemMessage = renderRecallLine(card);
|
|
53202
|
+
}
|
|
52992
53203
|
}
|
|
52993
53204
|
if (!decision) return c.json({});
|
|
52994
53205
|
return c.json({
|
|
53206
|
+
...systemMessage ? { systemMessage } : {},
|
|
52995
53207
|
hookSpecificOutput: {
|
|
52996
53208
|
hookEventName: decision.hookEventName,
|
|
52997
53209
|
additionalContext: decision.additionalContext
|
|
@@ -62746,11 +62958,11 @@ var require_readable = __commonJS({
|
|
|
62746
62958
|
});
|
|
62747
62959
|
}
|
|
62748
62960
|
};
|
|
62749
|
-
function isLocked(
|
|
62750
|
-
return
|
|
62961
|
+
function isLocked(self2) {
|
|
62962
|
+
return self2[kBody] && self2[kBody].locked === true || self2[kConsume];
|
|
62751
62963
|
}
|
|
62752
|
-
function isUnusable(
|
|
62753
|
-
return util.isDisturbed(
|
|
62964
|
+
function isUnusable(self2) {
|
|
62965
|
+
return util.isDisturbed(self2) || isLocked(self2);
|
|
62754
62966
|
}
|
|
62755
62967
|
async function consume(stream, type) {
|
|
62756
62968
|
assert2(!stream[kConsume]);
|
|
@@ -63137,42 +63349,42 @@ var require_abort_signal = __commonJS({
|
|
|
63137
63349
|
var { RequestAbortedError } = require_errors();
|
|
63138
63350
|
var kListener = Symbol("kListener");
|
|
63139
63351
|
var kSignal = Symbol("kSignal");
|
|
63140
|
-
function abort2(
|
|
63141
|
-
if (
|
|
63142
|
-
|
|
63352
|
+
function abort2(self2) {
|
|
63353
|
+
if (self2.abort) {
|
|
63354
|
+
self2.abort(self2[kSignal]?.reason);
|
|
63143
63355
|
} else {
|
|
63144
|
-
|
|
63356
|
+
self2.reason = self2[kSignal]?.reason ?? new RequestAbortedError();
|
|
63145
63357
|
}
|
|
63146
|
-
removeSignal(
|
|
63358
|
+
removeSignal(self2);
|
|
63147
63359
|
}
|
|
63148
|
-
function addSignal(
|
|
63149
|
-
|
|
63150
|
-
|
|
63151
|
-
|
|
63360
|
+
function addSignal(self2, signal) {
|
|
63361
|
+
self2.reason = null;
|
|
63362
|
+
self2[kSignal] = null;
|
|
63363
|
+
self2[kListener] = null;
|
|
63152
63364
|
if (!signal) {
|
|
63153
63365
|
return;
|
|
63154
63366
|
}
|
|
63155
63367
|
if (signal.aborted) {
|
|
63156
|
-
abort2(
|
|
63368
|
+
abort2(self2);
|
|
63157
63369
|
return;
|
|
63158
63370
|
}
|
|
63159
|
-
|
|
63160
|
-
|
|
63161
|
-
abort2(
|
|
63371
|
+
self2[kSignal] = signal;
|
|
63372
|
+
self2[kListener] = () => {
|
|
63373
|
+
abort2(self2);
|
|
63162
63374
|
};
|
|
63163
|
-
addAbortListener(
|
|
63375
|
+
addAbortListener(self2[kSignal], self2[kListener]);
|
|
63164
63376
|
}
|
|
63165
|
-
function removeSignal(
|
|
63166
|
-
if (!
|
|
63377
|
+
function removeSignal(self2) {
|
|
63378
|
+
if (!self2[kSignal]) {
|
|
63167
63379
|
return;
|
|
63168
63380
|
}
|
|
63169
|
-
if ("removeEventListener" in
|
|
63170
|
-
|
|
63381
|
+
if ("removeEventListener" in self2[kSignal]) {
|
|
63382
|
+
self2[kSignal].removeEventListener("abort", self2[kListener]);
|
|
63171
63383
|
} else {
|
|
63172
|
-
|
|
63384
|
+
self2[kSignal].removeListener("abort", self2[kListener]);
|
|
63173
63385
|
}
|
|
63174
|
-
|
|
63175
|
-
|
|
63386
|
+
self2[kSignal] = null;
|
|
63387
|
+
self2[kListener] = null;
|
|
63176
63388
|
}
|
|
63177
63389
|
module2.exports = {
|
|
63178
63390
|
addSignal,
|
|
@@ -72029,7 +72241,7 @@ __export(witness_ledger_exports, {
|
|
|
72029
72241
|
summarizeWitnessLedger: () => summarizeWitnessLedger,
|
|
72030
72242
|
witnessLedgerPath: () => witnessLedgerPath
|
|
72031
72243
|
});
|
|
72032
|
-
import { appendFileSync as appendFileSync3, existsSync as
|
|
72244
|
+
import { appendFileSync as appendFileSync3, existsSync as existsSync26, readFileSync as readFileSync29, writeFileSync as writeFileSync20 } from "node:fs";
|
|
72033
72245
|
import { join as join33 } from "node:path";
|
|
72034
72246
|
function witnessLedgerPath(configDir) {
|
|
72035
72247
|
return join33(configDir, "witness-ledger.jsonl");
|
|
@@ -72038,7 +72250,7 @@ function appendWitnessLedger(configDir, entry) {
|
|
|
72038
72250
|
const path2 = witnessLedgerPath(configDir);
|
|
72039
72251
|
try {
|
|
72040
72252
|
appendFileSync3(path2, JSON.stringify(entry) + "\n");
|
|
72041
|
-
const lines =
|
|
72253
|
+
const lines = readFileSync29(path2, "utf8").split("\n").filter(Boolean);
|
|
72042
72254
|
if (lines.length > LEDGER_MAX_LINES) {
|
|
72043
72255
|
writeFileSync20(path2, lines.slice(-Math.floor(LEDGER_MAX_LINES / 2)).join("\n") + "\n");
|
|
72044
72256
|
}
|
|
@@ -72047,9 +72259,9 @@ function appendWitnessLedger(configDir, entry) {
|
|
|
72047
72259
|
}
|
|
72048
72260
|
function readWitnessLedger(configDir) {
|
|
72049
72261
|
const path2 = witnessLedgerPath(configDir);
|
|
72050
|
-
if (!
|
|
72262
|
+
if (!existsSync26(path2)) return [];
|
|
72051
72263
|
try {
|
|
72052
|
-
return
|
|
72264
|
+
return readFileSync29(path2, "utf8").split("\n").filter(Boolean).map((l) => JSON.parse(l)).filter((e) => typeof e.ts === "number" && typeof e.channel === "string");
|
|
72053
72265
|
} catch {
|
|
72054
72266
|
return [];
|
|
72055
72267
|
}
|
|
@@ -72488,12 +72700,12 @@ var init_report_render = __esm({
|
|
|
72488
72700
|
|
|
72489
72701
|
// src/cli.ts
|
|
72490
72702
|
init_src6();
|
|
72491
|
-
import { closeSync as closeSync2, existsSync as existsSync36, openSync as openSync2, readFileSync as
|
|
72703
|
+
import { closeSync as closeSync2, existsSync as existsSync36, openSync as openSync2, readFileSync as readFileSync38, renameSync as renameSync4, statSync as statSync10 } from "node:fs";
|
|
72492
72704
|
import { join as join44, resolve as pathResolve2 } from "node:path";
|
|
72493
72705
|
import { spawn as spawn5 } from "node:child_process";
|
|
72494
72706
|
|
|
72495
72707
|
// src/daemon.ts
|
|
72496
|
-
import { existsSync as
|
|
72708
|
+
import { existsSync as existsSync28, writeFileSync as writeFileSync23 } from "node:fs";
|
|
72497
72709
|
|
|
72498
72710
|
// ../../node_modules/.pnpm/@hono+node-server@1.19.11_hono@4.12.8/node_modules/@hono/node-server/dist/index.mjs
|
|
72499
72711
|
import { createServer as createServerHTTP } from "http";
|
|
@@ -73072,8 +73284,8 @@ init_webui();
|
|
|
73072
73284
|
init_config();
|
|
73073
73285
|
|
|
73074
73286
|
// src/engine.ts
|
|
73075
|
-
import { execFileSync as
|
|
73076
|
-
import { existsSync as
|
|
73287
|
+
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
73288
|
+
import { existsSync as existsSync27, statSync as statSync8, appendFileSync as appendFileSync4, readdirSync as readdirSync10, renameSync as renameSync3, readFileSync as readFileSync31, writeFileSync as writeFileSync22 } from "node:fs";
|
|
73077
73289
|
import { basename as basename7, join as join35, relative as relative6, sep as sep4 } from "node:path";
|
|
73078
73290
|
|
|
73079
73291
|
// src/source-watcher.ts
|
|
@@ -74781,16 +74993,16 @@ function createSourceWatcher(targets, opts) {
|
|
|
74781
74993
|
}
|
|
74782
74994
|
function chokidarSourceWatcher(targets, ignored) {
|
|
74783
74995
|
const w = esm_default.watch([...targets], { ignored, ignoreInitial: true, persistent: true });
|
|
74784
|
-
const
|
|
74996
|
+
const self2 = {
|
|
74785
74997
|
on(event, listener) {
|
|
74786
74998
|
w.on(event, listener);
|
|
74787
|
-
return
|
|
74999
|
+
return self2;
|
|
74788
75000
|
},
|
|
74789
75001
|
add: (p) => void w.add(p),
|
|
74790
75002
|
unwatch: (p) => void w.unwatch(p),
|
|
74791
75003
|
close: () => w.close()
|
|
74792
75004
|
};
|
|
74793
|
-
return
|
|
75005
|
+
return self2;
|
|
74794
75006
|
}
|
|
74795
75007
|
var NativeSourceWatcher = class extends EventEmitter2 {
|
|
74796
75008
|
constructor(targets, ignored) {
|
|
@@ -75118,7 +75330,7 @@ init_review2();
|
|
|
75118
75330
|
|
|
75119
75331
|
// src/turn.ts
|
|
75120
75332
|
init_checkout_root();
|
|
75121
|
-
import { closeSync, existsSync as
|
|
75333
|
+
import { closeSync, existsSync as existsSync18, fstatSync, openSync, readdirSync as readdirSync6, readSync, realpathSync, statSync as statSync6 } from "node:fs";
|
|
75122
75334
|
import { basename as basename5, delimiter, dirname as dirname10, join as join21, normalize as normalize3 } from "node:path";
|
|
75123
75335
|
import { homedir as homedir4 } from "node:os";
|
|
75124
75336
|
import { createHash as createHash16 } from "node:crypto";
|
|
@@ -75511,7 +75723,7 @@ function claudeProjectDir(cwd, home = homedir4()) {
|
|
|
75511
75723
|
}
|
|
75512
75724
|
function recentTranscripts(cwd, opts = {}) {
|
|
75513
75725
|
const dir = claudeProjectDir(cwd, opts.home ?? homedir4());
|
|
75514
|
-
if (!
|
|
75726
|
+
if (!existsSync18(dir)) return [];
|
|
75515
75727
|
let names;
|
|
75516
75728
|
try {
|
|
75517
75729
|
names = readdirSync6(dir);
|
|
@@ -75538,7 +75750,7 @@ function recentTranscripts(cwd, opts = {}) {
|
|
|
75538
75750
|
function subagentTranscripts(mainTranscriptPath, sessionId) {
|
|
75539
75751
|
if (!mainTranscriptPath || !sessionId) return [];
|
|
75540
75752
|
const dir = join21(dirname10(mainTranscriptPath), sessionId, "subagents");
|
|
75541
|
-
if (!
|
|
75753
|
+
if (!existsSync18(dir)) return [];
|
|
75542
75754
|
let names;
|
|
75543
75755
|
try {
|
|
75544
75756
|
names = readdirSync6(dir);
|
|
@@ -75622,7 +75834,7 @@ function codexRolloutsForCwd(cwd, opts = {}) {
|
|
|
75622
75834
|
const owner = checkoutRootOf(cwd);
|
|
75623
75835
|
const owners = /* @__PURE__ */ new Map();
|
|
75624
75836
|
for (const root of codexSessionRoots(opts.env, opts.home)) {
|
|
75625
|
-
if (!
|
|
75837
|
+
if (!existsSync18(root)) {
|
|
75626
75838
|
codexRolloutActivity.delete(root);
|
|
75627
75839
|
continue;
|
|
75628
75840
|
}
|
|
@@ -75723,7 +75935,7 @@ function geminiTranscriptsForCwd(cwd, opts = {}) {
|
|
|
75723
75935
|
const hashes = geminiHashesFor(cwd);
|
|
75724
75936
|
const out2 = [];
|
|
75725
75937
|
for (const root of geminiSessionRoots(opts.env, opts.home)) {
|
|
75726
|
-
if (!
|
|
75938
|
+
if (!existsSync18(root)) continue;
|
|
75727
75939
|
let slugs;
|
|
75728
75940
|
try {
|
|
75729
75941
|
slugs = readdirSync6(root);
|
|
@@ -75794,7 +76006,7 @@ function opencodeTranscriptsForCwd(cwd, opts = {}) {
|
|
|
75794
76006
|
}
|
|
75795
76007
|
const out2 = [];
|
|
75796
76008
|
for (const root of opencodeSessionRoots(opts.env, opts.home)) {
|
|
75797
|
-
if (!
|
|
76009
|
+
if (!existsSync18(root)) continue;
|
|
75798
76010
|
let names;
|
|
75799
76011
|
try {
|
|
75800
76012
|
names = readdirSync6(root);
|
|
@@ -75826,10 +76038,10 @@ init_src2();
|
|
|
75826
76038
|
init_agent_signals();
|
|
75827
76039
|
init_tool_index();
|
|
75828
76040
|
init_src5();
|
|
75829
|
-
import { readFileSync as
|
|
76041
|
+
import { readFileSync as readFileSync17, writeFileSync as writeFileSync13 } from "node:fs";
|
|
75830
76042
|
var NEG = /n['']t|\b(?:not|never|no|none|neither|nor|unrelated|irrelevant|would|might|could|if)\b/i;
|
|
75831
76043
|
var CITE_GROUP_RE = /\(((?:[^()\n]|\([^()\n]*\)){1,200})\)/g;
|
|
75832
|
-
var HANDLE_RE = /\[([a-z0-9][\w-]{0,80})\]|((?:pat|sol|drc|dcause|dfix|dprob|prob|claim|err)_[0-9a-f]{6,})/gi;
|
|
76044
|
+
var HANDLE_RE = /\[([a-z0-9][\w-]{0,80})\]|((?:pat|sol|drc|dcause|dfix|dprob|dvuln|prob|claim|err)_[0-9a-f]{6,})/gi;
|
|
75833
76045
|
var PLACEHOLDER_HANDLES = /* @__PURE__ */ new Set([
|
|
75834
76046
|
"handle",
|
|
75835
76047
|
"its-handle",
|
|
@@ -75844,7 +76056,7 @@ var PLACEHOLDER_HANDLES = /* @__PURE__ */ new Set([
|
|
|
75844
76056
|
"b"
|
|
75845
76057
|
]);
|
|
75846
76058
|
var isPlaceholderHandle = (h) => PLACEHOLDER_HANDLES.has(h.toLowerCase());
|
|
75847
|
-
var FLAG_BODY_HANDLE_RE = /^(?:[a-z0-9]+(?:-[a-z0-9]+){2,}-(?=[0-9a-f]{0,3}\d)[0-9a-f]{4}|(?:pat|sol|drc|dcause|dfix|dprob|prob|claim|err)_[0-9a-f]{6,})$/i;
|
|
76059
|
+
var FLAG_BODY_HANDLE_RE = /^(?:[a-z0-9]+(?:-[a-z0-9]+){2,}-(?=[0-9a-f]{0,3}\d)[0-9a-f]{4}|(?:pat|sol|drc|dcause|dfix|dprob|dvuln|prob|claim|err)_[0-9a-f]{6,})$/i;
|
|
75848
76060
|
var FIX_PREFIX = /^\s*fix:(?:#([a-z][\w-]{0,63}))?\s*/i;
|
|
75849
76061
|
var CONSTRAINT_RE = /\(\s*constraint:\s*([^()\n]{8,}?)\s*\)/gi;
|
|
75850
76062
|
var CAUSE_PREFIX = /^\s*cause:(?:#([a-z][\w-]{0,63}))?\s*/i;
|
|
@@ -75869,7 +76081,7 @@ var DOMAIN_RE = /\(\s*domain:\s*([^()\n]{3,}?)\s*\)/gi;
|
|
|
75869
76081
|
var PACKAGE_RE = /\(\s*package:\s*([^()\n]{2,}?)\s*\)/gi;
|
|
75870
76082
|
var COMPONENT_RE = /\(\s*component:\s*([^()\n]{2,}?)\s*\)/gi;
|
|
75871
76083
|
var CAUSE_TEXT_MIN = 8;
|
|
75872
|
-
var FLAG_RE = /\[([!?])(?:#([a-z][\w-]{0,63})\s+)?\s*((?:\[[^\]\n]*\]|[^\]\n])
|
|
76084
|
+
var FLAG_RE = /\[([!?])(?:#([a-z][\w-]{0,63})\s+)?\s*((?:\[[^\]\n]*\]|[^\]\n])*?)\s*(?:@\s*([^\s\]]+?)(?::(\d+))?\s*)?\]/g;
|
|
75873
76085
|
var CONSTRAINT_MIN = 8;
|
|
75874
76086
|
function clauseBefore(sentence, idx) {
|
|
75875
76087
|
const win = sentence.slice(Math.max(0, idx - 80), idx);
|
|
@@ -76013,6 +76225,7 @@ function cleanEmittedTags(tags) {
|
|
|
76013
76225
|
}
|
|
76014
76226
|
function emptyTagDispositions() {
|
|
76015
76227
|
return {
|
|
76228
|
+
invalidVulnerability: 0,
|
|
76016
76229
|
oversizeSegments: 0,
|
|
76017
76230
|
codeSpanNeutralized: 0,
|
|
76018
76231
|
refuteTooShort: 0,
|
|
@@ -76025,6 +76238,7 @@ function emptyTagDispositions() {
|
|
|
76025
76238
|
};
|
|
76026
76239
|
}
|
|
76027
76240
|
function addTagDispositions(a, b) {
|
|
76241
|
+
a.invalidVulnerability += b.invalidVulnerability;
|
|
76028
76242
|
a.oversizeSegments += b.oversizeSegments;
|
|
76029
76243
|
a.codeSpanNeutralized += b.codeSpanNeutralized;
|
|
76030
76244
|
a.refuteTooShort += b.refuteTooShort;
|
|
@@ -76038,12 +76252,31 @@ function addTagDispositions(a, b) {
|
|
|
76038
76252
|
function parseInlineTags(text) {
|
|
76039
76253
|
return parseInlineTagsWithDispositions(text).tags;
|
|
76040
76254
|
}
|
|
76255
|
+
function* captureSentences(text) {
|
|
76256
|
+
for (const line of text.split(/\n+/)) {
|
|
76257
|
+
if (line.length > 2e4) {
|
|
76258
|
+
yield line;
|
|
76259
|
+
continue;
|
|
76260
|
+
}
|
|
76261
|
+
const flags2 = [...line.matchAll(new RegExp(FLAG_RE.source, FLAG_RE.flags))].map((m) => ({ start: m.index, end: m.index + m[0].length }));
|
|
76262
|
+
let flag = 0;
|
|
76263
|
+
let start2 = 0;
|
|
76264
|
+
for (const boundary of line.matchAll(/(?<=[.!?])\s+(?!\(fix:)/g)) {
|
|
76265
|
+
const index = boundary.index;
|
|
76266
|
+
while (flags2[flag] && flags2[flag].end <= index) flag++;
|
|
76267
|
+
if (flags2[flag] && flags2[flag].start < index) continue;
|
|
76268
|
+
yield line.slice(start2, index);
|
|
76269
|
+
start2 = index + boundary[0].length;
|
|
76270
|
+
}
|
|
76271
|
+
yield line.slice(start2);
|
|
76272
|
+
}
|
|
76273
|
+
}
|
|
76041
76274
|
function parseInlineTagsWithDispositions(text) {
|
|
76042
76275
|
const out2 = [];
|
|
76043
76276
|
const dispositions = emptyTagDispositions();
|
|
76044
76277
|
const deFenced = text.replace(/```[\s\S]*?```/g, " ");
|
|
76045
76278
|
let seqNo = -1;
|
|
76046
|
-
for (const raw2 of deFenced
|
|
76279
|
+
for (const raw2 of captureSentences(deFenced)) {
|
|
76047
76280
|
seqNo++;
|
|
76048
76281
|
if (raw2.length > 2e4) {
|
|
76049
76282
|
dispositions.oversizeSegments++;
|
|
@@ -76269,6 +76502,29 @@ function parseInlineTagsWithDispositions(text) {
|
|
|
76269
76502
|
while ((f = FLAG_RE.exec(sentence)) !== null) {
|
|
76270
76503
|
const flagThread = f[2];
|
|
76271
76504
|
const raw3 = f[3].trim();
|
|
76505
|
+
if (/^vuln\b/i.test(raw3)) {
|
|
76506
|
+
const typed = /^vuln:\s*([\s\S]*)$/i.exec(raw3);
|
|
76507
|
+
const body2 = typed?.[1]?.trim() ?? "";
|
|
76508
|
+
const parts2 = body2.split(CAUSE_ARROW).map((s) => s.trim());
|
|
76509
|
+
const symptom = f[1] === "!" && parts2.length > 1 && !f[4] ? new RegExp(FLAG_RE.source, "i").exec(`[!${parts2[0]}]`) : null;
|
|
76510
|
+
const statement = f[1] === "?" ? body2 : symptom?.[3]?.trim() ?? parts2[0];
|
|
76511
|
+
if (statement.length < 8 || /^<[^>]*>$/.test(statement)) {
|
|
76512
|
+
dispositions.invalidVulnerability++;
|
|
76513
|
+
continue;
|
|
76514
|
+
}
|
|
76515
|
+
const path2 = (f[4] ?? symptom?.[4])?.trim();
|
|
76516
|
+
const line = f[5] ?? symptom?.[5];
|
|
76517
|
+
out2.push({
|
|
76518
|
+
kind: "vulnerability",
|
|
76519
|
+
statement,
|
|
76520
|
+
assessment: f[1] === "!" ? "asserted" : "suspected",
|
|
76521
|
+
...f[1] === "!" && parts2.length > 1 ? { vulnerabilityCauses: parts2.slice(1).filter((s) => s.length >= CAUSE_TEXT_MIN) } : {},
|
|
76522
|
+
...path2 ? { location: { path: path2, ...line ? { line: Number(line) } : {} } } : {},
|
|
76523
|
+
...flagThread ? { threadId: flagThread } : {},
|
|
76524
|
+
sentence: sfield
|
|
76525
|
+
});
|
|
76526
|
+
continue;
|
|
76527
|
+
}
|
|
76272
76528
|
if (FLAG_BODY_HANDLE_RE.test(raw3) && !f[4]) {
|
|
76273
76529
|
dispositions.flagAsHandle++;
|
|
76274
76530
|
out2.push({ kind: "prior", handle: raw3, sentence: sfield });
|
|
@@ -76521,7 +76777,7 @@ function writePrimingHandles(path2, nodes, now = Date.now()) {
|
|
|
76521
76777
|
}
|
|
76522
76778
|
function readPrimingHandles(path2) {
|
|
76523
76779
|
try {
|
|
76524
|
-
return JSON.parse(
|
|
76780
|
+
return JSON.parse(readFileSync17(path2, "utf8"));
|
|
76525
76781
|
} catch {
|
|
76526
76782
|
return {};
|
|
76527
76783
|
}
|
|
@@ -76639,7 +76895,7 @@ function harvestInlineTags(store, text, opts) {
|
|
|
76639
76895
|
const parsed = parseInlineTagsWithDispositions(text);
|
|
76640
76896
|
const tags = parsed.tags;
|
|
76641
76897
|
plan.dispositions = parsed.dispositions;
|
|
76642
|
-
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);
|
|
76898
|
+
const symptomSeqs = tags.filter((t) => (t.kind === "problem" || t.kind === "todo" || t.kind === "vulnerability") && t.statement).map((t) => ({ seq: t.seq ?? -1, statement: t.statement, threadId: t.threadId, kind: t.kind })).sort((a, b) => a.seq - b.seq);
|
|
76643
76899
|
const bindSymptom = (seq, threadId) => {
|
|
76644
76900
|
if (threadId) {
|
|
76645
76901
|
const hit = symptomSeqs.find((s) => s.threadId === threadId);
|
|
@@ -76652,6 +76908,7 @@ function harvestInlineTags(store, text, opts) {
|
|
|
76652
76908
|
if (seq == null) return { evidence: "inferred" };
|
|
76653
76909
|
let best;
|
|
76654
76910
|
for (const s of symptomSeqs) {
|
|
76911
|
+
if (s.kind === "vulnerability") continue;
|
|
76655
76912
|
if (s.seq <= seq) best = s;
|
|
76656
76913
|
else break;
|
|
76657
76914
|
}
|
|
@@ -76666,10 +76923,13 @@ function harvestInlineTags(store, text, opts) {
|
|
|
76666
76923
|
return id;
|
|
76667
76924
|
};
|
|
76668
76925
|
for (const tag of tags) {
|
|
76669
|
-
if (tag.kind === "problem" || tag.kind === "todo") {
|
|
76926
|
+
if (tag.kind === "problem" || tag.kind === "todo" || tag.kind === "vulnerability") {
|
|
76670
76927
|
plan.problems.push({
|
|
76671
76928
|
statement: tag.statement,
|
|
76672
76929
|
kind: tag.kind,
|
|
76930
|
+
...tag.assessment ? { assessment: tag.assessment } : {},
|
|
76931
|
+
...tag.vulnerabilityCauses ? { vulnerabilityCauses: tag.vulnerabilityCauses } : {},
|
|
76932
|
+
...tag.kind === "vulnerability" && tag.seq !== void 0 ? { seq: tag.seq } : {},
|
|
76673
76933
|
...tag.location ? { location: tag.location } : {},
|
|
76674
76934
|
...tag.threadId ? { threadId: tag.threadId } : {}
|
|
76675
76935
|
});
|
|
@@ -76692,7 +76952,7 @@ function harvestInlineTags(store, text, opts) {
|
|
|
76692
76952
|
} else if (tag.threadId && !b.statement) {
|
|
76693
76953
|
plan.fixes.push({ inScope: true, fixNote: tag.fixRationale, threadId: tag.threadId });
|
|
76694
76954
|
} else if (b.statement && b.evidence === "witnessed") {
|
|
76695
|
-
plan.fixes.push({ inScope: true, fixNote: tag.fixRationale, boundStatement: b.statement });
|
|
76955
|
+
plan.fixes.push({ inScope: true, fixNote: tag.fixRationale, boundStatement: b.statement, ...tag.threadId ? { threadId: tag.threadId } : {} });
|
|
76696
76956
|
} else {
|
|
76697
76957
|
plan.fixes.push({ inScope: true, fixNote: tag.fixRationale, ambiguous: true });
|
|
76698
76958
|
}
|
|
@@ -76895,6 +77155,7 @@ function harvestInlineTags(store, text, opts) {
|
|
|
76895
77155
|
}
|
|
76896
77156
|
var CORROBORATABLE_LABELS = /* @__PURE__ */ new Set([
|
|
76897
77157
|
"Problem",
|
|
77158
|
+
"Vulnerability",
|
|
76898
77159
|
"Solution",
|
|
76899
77160
|
"RootCause",
|
|
76900
77161
|
"Pattern",
|
|
@@ -76996,7 +77257,7 @@ ${conversation}` }]
|
|
|
76996
77257
|
// src/constraint-backfill.ts
|
|
76997
77258
|
init_src5();
|
|
76998
77259
|
init_src2();
|
|
76999
|
-
import { existsSync as
|
|
77260
|
+
import { existsSync as existsSync19, readFileSync as readFileSync18, readdirSync as readdirSync7, writeFileSync as writeFileSync14 } from "node:fs";
|
|
77000
77261
|
import { join as join22 } from "node:path";
|
|
77001
77262
|
import { homedir as homedir5 } from "node:os";
|
|
77002
77263
|
var BACKFILL_VERSION = 1;
|
|
@@ -77015,9 +77276,9 @@ function markerPath(configDir) {
|
|
|
77015
77276
|
}
|
|
77016
77277
|
function alreadyDone(configDir) {
|
|
77017
77278
|
const p = markerPath(configDir);
|
|
77018
|
-
if (!
|
|
77279
|
+
if (!existsSync19(p)) return false;
|
|
77019
77280
|
try {
|
|
77020
|
-
const raw2 = JSON.parse(
|
|
77281
|
+
const raw2 = JSON.parse(readFileSync18(p, "utf8"));
|
|
77021
77282
|
return raw2?.version === BACKFILL_VERSION;
|
|
77022
77283
|
} catch {
|
|
77023
77284
|
return false;
|
|
@@ -77027,7 +77288,7 @@ function replay(root) {
|
|
|
77027
77288
|
const statements = /* @__PURE__ */ new Set();
|
|
77028
77289
|
const citedByFix = /* @__PURE__ */ new Set();
|
|
77029
77290
|
const dir = claudeProjectDir(root, homedir5());
|
|
77030
|
-
if (!
|
|
77291
|
+
if (!existsSync19(dir)) return { statements, citedByFix };
|
|
77031
77292
|
let names;
|
|
77032
77293
|
try {
|
|
77033
77294
|
names = readdirSync7(dir).filter((n) => n.endsWith(".jsonl"));
|
|
@@ -77037,7 +77298,7 @@ function replay(root) {
|
|
|
77037
77298
|
for (const f of names) {
|
|
77038
77299
|
let lines;
|
|
77039
77300
|
try {
|
|
77040
|
-
lines =
|
|
77301
|
+
lines = readFileSync18(join22(dir, f), "utf8").split("\n");
|
|
77041
77302
|
} catch {
|
|
77042
77303
|
continue;
|
|
77043
77304
|
}
|
|
@@ -77164,7 +77425,7 @@ function backfillConstraintKind(store, opts) {
|
|
|
77164
77425
|
// src/edge-repair.ts
|
|
77165
77426
|
init_src();
|
|
77166
77427
|
init_src5();
|
|
77167
|
-
import { existsSync as
|
|
77428
|
+
import { existsSync as existsSync20, readFileSync as readFileSync19, writeFileSync as writeFileSync15 } from "node:fs";
|
|
77168
77429
|
import { join as join23 } from "node:path";
|
|
77169
77430
|
function citeEdgeId(from, type, to) {
|
|
77170
77431
|
return `edge_${digest({ from, type, to })}`.slice(0, 24);
|
|
@@ -77184,9 +77445,9 @@ function markerPath2(configDir) {
|
|
|
77184
77445
|
}
|
|
77185
77446
|
function alreadyDone2(configDir) {
|
|
77186
77447
|
const p = markerPath2(configDir);
|
|
77187
|
-
if (!
|
|
77448
|
+
if (!existsSync20(p)) return false;
|
|
77188
77449
|
try {
|
|
77189
|
-
return JSON.parse(
|
|
77450
|
+
return JSON.parse(readFileSync19(p, "utf8"))?.version === EDGE_REPAIR_VERSION;
|
|
77190
77451
|
} catch {
|
|
77191
77452
|
return false;
|
|
77192
77453
|
}
|
|
@@ -77249,7 +77510,7 @@ function repairInvalidEdges(store, opts) {
|
|
|
77249
77510
|
init_reconcile();
|
|
77250
77511
|
|
|
77251
77512
|
// src/pass-ledger.ts
|
|
77252
|
-
import { appendFileSync as appendFileSync2, existsSync as
|
|
77513
|
+
import { appendFileSync as appendFileSync2, existsSync as existsSync21, readFileSync as readFileSync20, writeFileSync as writeFileSync16 } from "node:fs";
|
|
77253
77514
|
import { join as join24 } from "node:path";
|
|
77254
77515
|
|
|
77255
77516
|
// src/isolate-census.ts
|
|
@@ -77302,7 +77563,7 @@ function appendPassLedger(configDir, kind, durationMs, counts) {
|
|
|
77302
77563
|
return;
|
|
77303
77564
|
}
|
|
77304
77565
|
appendsSinceTrim.set(path2, 0);
|
|
77305
|
-
const lines =
|
|
77566
|
+
const lines = readFileSync20(path2, "utf8").split("\n").filter(Boolean);
|
|
77306
77567
|
const keptByKind = /* @__PURE__ */ new Map();
|
|
77307
77568
|
const kept = [];
|
|
77308
77569
|
for (let i2 = lines.length - 1; i2 >= 0; i2--) {
|
|
@@ -77325,9 +77586,9 @@ function appendPassLedger(configDir, kind, durationMs, counts) {
|
|
|
77325
77586
|
}
|
|
77326
77587
|
function readPassLedger(configDir) {
|
|
77327
77588
|
const path2 = passLedgerPath(configDir);
|
|
77328
|
-
if (!
|
|
77589
|
+
if (!existsSync21(path2)) return [];
|
|
77329
77590
|
try {
|
|
77330
|
-
return
|
|
77591
|
+
return readFileSync20(path2, "utf8").split("\n").filter(Boolean).map((l) => JSON.parse(l)).filter(
|
|
77331
77592
|
(e) => typeof e?.ts === "number" && typeof e?.kind === "string" && typeof e?.durationMs === "number"
|
|
77332
77593
|
).map((e) => ({ ...e, counts: e.counts ?? {} }));
|
|
77333
77594
|
} catch {
|
|
@@ -77699,11 +77960,11 @@ init_outbox();
|
|
|
77699
77960
|
init_src10();
|
|
77700
77961
|
init_src();
|
|
77701
77962
|
init_src2();
|
|
77702
|
-
import { readFileSync as
|
|
77963
|
+
import { readFileSync as readFileSync21 } from "node:fs";
|
|
77703
77964
|
import { join as join25 } from "node:path";
|
|
77704
77965
|
function loadClaimIgnorePatterns(workspaceRoot) {
|
|
77705
77966
|
try {
|
|
77706
|
-
return
|
|
77967
|
+
return readFileSync21(join25(workspaceRoot, ".errataignore"), "utf8").split(/\r?\n/).map((l) => l.trim()).filter((l) => l.length > 0 && !l.startsWith("#")).map((l) => l.toLowerCase());
|
|
77707
77968
|
} catch {
|
|
77708
77969
|
return [];
|
|
77709
77970
|
}
|
|
@@ -78080,8 +78341,8 @@ async function pullCloudTriage(shared, cloud, profile, limit = 50) {
|
|
|
78080
78341
|
|
|
78081
78342
|
// src/retrieval-stack.ts
|
|
78082
78343
|
init_src();
|
|
78083
|
-
import { execFileSync as
|
|
78084
|
-
import { existsSync as
|
|
78344
|
+
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
78345
|
+
import { existsSync as existsSync22, readFileSync as readFileSync22, statSync as statSync7 } from "node:fs";
|
|
78085
78346
|
import { homedir as homedir6 } from "node:os";
|
|
78086
78347
|
import { join as join26 } from "node:path";
|
|
78087
78348
|
var RETRIEVAL_STACK_CAP = 24;
|
|
@@ -78373,7 +78634,7 @@ function mavenGroupIsSelfDisclosing(name2, selfTokens) {
|
|
|
78373
78634
|
function loadRegistryPolicy(root, env2 = process.env, repoLocator) {
|
|
78374
78635
|
const read2 = (p) => {
|
|
78375
78636
|
try {
|
|
78376
|
-
return
|
|
78637
|
+
return readFileSync22(p, "utf8");
|
|
78377
78638
|
} catch {
|
|
78378
78639
|
return null;
|
|
78379
78640
|
}
|
|
@@ -78599,7 +78860,7 @@ function readDirectDependencies(root) {
|
|
|
78599
78860
|
for (const c of LOCKFILES) {
|
|
78600
78861
|
if (familiesSeen.has(c.family)) continue;
|
|
78601
78862
|
const p = join26(root, c.file);
|
|
78602
|
-
if (!
|
|
78863
|
+
if (!existsSync22(p)) continue;
|
|
78603
78864
|
try {
|
|
78604
78865
|
const s = statSync7(p);
|
|
78605
78866
|
stamps.push(`${c.file}:${s.mtimeMs}:${s.size}`);
|
|
@@ -78619,7 +78880,7 @@ function readDirectDependencies(root) {
|
|
|
78619
78880
|
const direct = [];
|
|
78620
78881
|
for (const { c, path: path2 } of found) {
|
|
78621
78882
|
try {
|
|
78622
|
-
direct.push(...c.parse(
|
|
78883
|
+
direct.push(...c.parse(readFileSync22(path2, "utf8")).direct ?? []);
|
|
78623
78884
|
} catch {
|
|
78624
78885
|
}
|
|
78625
78886
|
}
|
|
@@ -78628,7 +78889,7 @@ function readDirectDependencies(root) {
|
|
|
78628
78889
|
}
|
|
78629
78890
|
function manifestPaths(root) {
|
|
78630
78891
|
try {
|
|
78631
|
-
const out2 =
|
|
78892
|
+
const out2 = execFileSync4("git", ["-C", root, "ls-files", "-z"], {
|
|
78632
78893
|
encoding: "utf8",
|
|
78633
78894
|
maxBuffer: 128 * 1024 * 1024,
|
|
78634
78895
|
windowsHide: true,
|
|
@@ -78662,14 +78923,14 @@ function manifestPaths(root) {
|
|
|
78662
78923
|
"project.godot"
|
|
78663
78924
|
];
|
|
78664
78925
|
return {
|
|
78665
|
-
paths: ROOT_MANIFESTS.filter((f) =>
|
|
78926
|
+
paths: ROOT_MANIFESTS.filter((f) => existsSync22(join26(root, f))),
|
|
78666
78927
|
tracked: false,
|
|
78667
78928
|
truncated: false
|
|
78668
78929
|
};
|
|
78669
78930
|
}
|
|
78670
78931
|
var WORKSPACE_MARKERS = ["pnpm-workspace.yaml", "lerna.json", "go.work", "settings.gradle", "settings.gradle.kts"];
|
|
78671
78932
|
function rootDeclaresWorkspace(root, texts) {
|
|
78672
|
-
if (WORKSPACE_MARKERS.some((f) =>
|
|
78933
|
+
if (WORKSPACE_MARKERS.some((f) => existsSync22(join26(root, f)))) return true;
|
|
78673
78934
|
return /"workspaces"\s*:/.test(texts.get("package.json") ?? "") || /<modules>/.test(texts.get("pom.xml") ?? "") || /^\s*\[workspace\]/m.test(texts.get("Cargo.toml") ?? "");
|
|
78674
78935
|
}
|
|
78675
78936
|
var EMPTY_SCAN = { deps: [], self: [], complete: true };
|
|
@@ -78687,7 +78948,7 @@ function scanManifests(root) {
|
|
|
78687
78948
|
try {
|
|
78688
78949
|
const s = statSync7(abs);
|
|
78689
78950
|
stamps.push(`${rel}:${s.mtimeMs}:${s.size}`);
|
|
78690
|
-
texts.set(rel,
|
|
78951
|
+
texts.set(rel, readFileSync22(abs, "utf8"));
|
|
78691
78952
|
} catch {
|
|
78692
78953
|
}
|
|
78693
78954
|
}
|
|
@@ -78716,11 +78977,11 @@ function readManifestDependencies(root) {
|
|
|
78716
78977
|
}
|
|
78717
78978
|
|
|
78718
78979
|
// src/git-sensor.ts
|
|
78719
|
-
import { existsSync as
|
|
78980
|
+
import { existsSync as existsSync23, readFileSync as readFileSync23, watch as fsWatch } from "node:fs";
|
|
78720
78981
|
import { join as join27 } from "node:path";
|
|
78721
78982
|
function readFirstLine(path2) {
|
|
78722
78983
|
try {
|
|
78723
|
-
return
|
|
78984
|
+
return readFileSync23(path2, "utf8").split(/\r?\n/, 1)[0].trim();
|
|
78724
78985
|
} catch {
|
|
78725
78986
|
return null;
|
|
78726
78987
|
}
|
|
@@ -78739,13 +79000,13 @@ function readGitRefState(gitDir) {
|
|
|
78739
79000
|
return {
|
|
78740
79001
|
branch,
|
|
78741
79002
|
sha: sha2,
|
|
78742
|
-
mergeHeadExists:
|
|
78743
|
-
origHeadExists:
|
|
79003
|
+
mergeHeadExists: existsSync23(join27(gitDir, "MERGE_HEAD")),
|
|
79004
|
+
origHeadExists: existsSync23(join27(gitDir, "ORIG_HEAD"))
|
|
78744
79005
|
};
|
|
78745
79006
|
}
|
|
78746
79007
|
function shaFromPackedRefs(gitDir, ref) {
|
|
78747
79008
|
try {
|
|
78748
|
-
for (const line of
|
|
79009
|
+
for (const line of readFileSync23(join27(gitDir, "packed-refs"), "utf8").split(/\r?\n/)) {
|
|
78749
79010
|
const [sha2, name2] = line.split(/\s+/);
|
|
78750
79011
|
if (name2 === ref && sha2) return sha2;
|
|
78751
79012
|
}
|
|
@@ -78779,7 +79040,7 @@ function startGitSensor(gitDir, onEvent, opts = {}) {
|
|
|
78779
79040
|
const settle = () => {
|
|
78780
79041
|
if (timer) clearTimeout(timer);
|
|
78781
79042
|
timer = setTimeout(() => {
|
|
78782
|
-
if (
|
|
79043
|
+
if (existsSync23(join27(gitDir, "index.lock"))) {
|
|
78783
79044
|
settle();
|
|
78784
79045
|
return;
|
|
78785
79046
|
}
|
|
@@ -79014,7 +79275,7 @@ var TelemetryRecorder = class {
|
|
|
79014
79275
|
};
|
|
79015
79276
|
|
|
79016
79277
|
// src/file-activity.ts
|
|
79017
|
-
import { readFileSync as
|
|
79278
|
+
import { readFileSync as readFileSync25 } from "node:fs";
|
|
79018
79279
|
import { join as join29 } from "node:path";
|
|
79019
79280
|
import { createHash as createHash17 } from "node:crypto";
|
|
79020
79281
|
|
|
@@ -79767,7 +80028,7 @@ init_git_remote();
|
|
|
79767
80028
|
// src/history-bundle.ts
|
|
79768
80029
|
init_src();
|
|
79769
80030
|
import { execFile as execFile2 } from "node:child_process";
|
|
79770
|
-
import { readFileSync as
|
|
80031
|
+
import { readFileSync as readFileSync24 } from "node:fs";
|
|
79771
80032
|
import { join as join28 } from "node:path";
|
|
79772
80033
|
var DEFAULT_MAX_TOKENS = 6e3;
|
|
79773
80034
|
var FILE_LIST_CAP = 60;
|
|
@@ -79803,7 +80064,7 @@ function pathAllowedByFloor(path2) {
|
|
|
79803
80064
|
function loadRepoIgnore(root, extraPatterns = []) {
|
|
79804
80065
|
let source = "";
|
|
79805
80066
|
try {
|
|
79806
|
-
source =
|
|
80067
|
+
source = readFileSync24(join28(root, ".errataignore"), "utf8");
|
|
79807
80068
|
} catch {
|
|
79808
80069
|
source = "";
|
|
79809
80070
|
}
|
|
@@ -80096,7 +80357,7 @@ function readActivityBranch(root) {
|
|
|
80096
80357
|
try {
|
|
80097
80358
|
const gitDir = resolveGitDir(root);
|
|
80098
80359
|
if (!gitDir) return null;
|
|
80099
|
-
const head2 =
|
|
80360
|
+
const head2 = readFileSync25(join29(gitDir, "HEAD"), "utf8").trim();
|
|
80100
80361
|
const branch = head2.startsWith("ref: refs/heads/") ? head2.slice(16) : /^[a-f0-9]{40,64}$/i.test(head2) ? "HEAD" : null;
|
|
80101
80362
|
return branch && branch.length <= 256 && !/[\x00-\x1f\x7f]/.test(branch) ? branch : null;
|
|
80102
80363
|
} catch {
|
|
@@ -80253,11 +80514,11 @@ var FileActivityReporter = class {
|
|
|
80253
80514
|
|
|
80254
80515
|
// src/skills.ts
|
|
80255
80516
|
import {
|
|
80256
|
-
existsSync as
|
|
80517
|
+
existsSync as existsSync24,
|
|
80257
80518
|
mkdirSync as mkdirSync7,
|
|
80258
|
-
readFileSync as
|
|
80519
|
+
readFileSync as readFileSync26,
|
|
80259
80520
|
readdirSync as readdirSync8,
|
|
80260
|
-
unlinkSync as
|
|
80521
|
+
unlinkSync as unlinkSync3,
|
|
80261
80522
|
writeFileSync as writeFileSync17
|
|
80262
80523
|
} from "node:fs";
|
|
80263
80524
|
import { basename as basename6, join as join30 } from "node:path";
|
|
@@ -80265,9 +80526,9 @@ function skillFileName(id) {
|
|
|
80265
80526
|
return `${id.replace(/[^A-Za-z0-9_.-]/g, "_")}.md`;
|
|
80266
80527
|
}
|
|
80267
80528
|
function readSkillManifest(manifestPath) {
|
|
80268
|
-
if (!
|
|
80529
|
+
if (!existsSync24(manifestPath)) return [];
|
|
80269
80530
|
try {
|
|
80270
|
-
const parsed = JSON.parse(
|
|
80531
|
+
const parsed = JSON.parse(readFileSync26(manifestPath, "utf8"));
|
|
80271
80532
|
return (parsed.skills ?? []).map((s) => ({
|
|
80272
80533
|
title: s.title ?? "",
|
|
80273
80534
|
layer: s.layer ?? "technique",
|
|
@@ -80318,7 +80579,7 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
|
|
|
80318
80579
|
if (!f.endsWith(".md")) continue;
|
|
80319
80580
|
if (keep.has(basename6(f))) continue;
|
|
80320
80581
|
try {
|
|
80321
|
-
|
|
80582
|
+
unlinkSync3(join30(paths.skillsDir, f));
|
|
80322
80583
|
pruned++;
|
|
80323
80584
|
} catch {
|
|
80324
80585
|
}
|
|
@@ -80336,10 +80597,10 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
|
|
|
80336
80597
|
init_src2();
|
|
80337
80598
|
import {
|
|
80338
80599
|
cpSync,
|
|
80339
|
-
existsSync as
|
|
80600
|
+
existsSync as existsSync25,
|
|
80340
80601
|
lstatSync,
|
|
80341
80602
|
mkdirSync as mkdirSync8,
|
|
80342
|
-
readFileSync as
|
|
80603
|
+
readFileSync as readFileSync27,
|
|
80343
80604
|
readdirSync as readdirSync9,
|
|
80344
80605
|
rmSync as rmSync3,
|
|
80345
80606
|
symlinkSync,
|
|
@@ -80396,7 +80657,7 @@ function skillCiteHandle(s) {
|
|
|
80396
80657
|
return priorHandle({ id: s.id, description: s.title });
|
|
80397
80658
|
}
|
|
80398
80659
|
function reconcileNamespaced(dir, keep) {
|
|
80399
|
-
if (!
|
|
80660
|
+
if (!existsSync25(dir)) return 0;
|
|
80400
80661
|
let pruned = 0;
|
|
80401
80662
|
for (const name2 of readdirSync9(dir)) {
|
|
80402
80663
|
if (!name2.startsWith(SKILL_NS) || keep.has(name2)) continue;
|
|
@@ -80410,7 +80671,7 @@ function reconcileNamespaced(dir, keep) {
|
|
|
80410
80671
|
}
|
|
80411
80672
|
function linkOrCopy(linkPath, target) {
|
|
80412
80673
|
try {
|
|
80413
|
-
if (
|
|
80674
|
+
if (existsSync25(linkPath) || safeLstat(linkPath)) rmSync3(linkPath, { recursive: true, force: true });
|
|
80414
80675
|
} catch {
|
|
80415
80676
|
}
|
|
80416
80677
|
try {
|
|
@@ -80439,7 +80700,7 @@ function emitAndProjectSkills(root, skills) {
|
|
|
80439
80700
|
for (const s of skills) {
|
|
80440
80701
|
let body2;
|
|
80441
80702
|
try {
|
|
80442
|
-
body2 =
|
|
80703
|
+
body2 = readFileSync27(s.bodyPath, "utf8");
|
|
80443
80704
|
} catch {
|
|
80444
80705
|
continue;
|
|
80445
80706
|
}
|
|
@@ -80459,7 +80720,7 @@ function emitAndProjectSkills(root, skills) {
|
|
|
80459
80720
|
reconcileNamespaced(agentsSkillsDir, keep);
|
|
80460
80721
|
let projected = 0;
|
|
80461
80722
|
for (const h of HARNESS_SKILL_DIRS) {
|
|
80462
|
-
if (!
|
|
80723
|
+
if (!existsSync25(join31(root, h.configDir))) continue;
|
|
80463
80724
|
const dir = join31(root, h.skillsDir);
|
|
80464
80725
|
mkdirSync8(dir, { recursive: true });
|
|
80465
80726
|
for (const slug2 of slugs) {
|
|
@@ -80472,9 +80733,9 @@ function emitAndProjectSkills(root, skills) {
|
|
|
80472
80733
|
return { slugs, emitted, projected };
|
|
80473
80734
|
}
|
|
80474
80735
|
function emitInputsFromManifest(erretaDir, manifestPath) {
|
|
80475
|
-
if (!
|
|
80736
|
+
if (!existsSync25(manifestPath)) return [];
|
|
80476
80737
|
try {
|
|
80477
|
-
const parsed = JSON.parse(
|
|
80738
|
+
const parsed = JSON.parse(readFileSync27(manifestPath, "utf8"));
|
|
80478
80739
|
return (parsed.skills ?? []).filter((s) => Boolean(s.id && s.file)).map((s) => ({
|
|
80479
80740
|
id: s.id,
|
|
80480
80741
|
title: s.title ?? s.id,
|
|
@@ -80497,7 +80758,7 @@ function ensureSkillGitignore(root) {
|
|
|
80497
80758
|
const path2 = join31(root, ".gitignore");
|
|
80498
80759
|
let current = "";
|
|
80499
80760
|
try {
|
|
80500
|
-
current =
|
|
80761
|
+
current = existsSync25(path2) ? readFileSync27(path2, "utf8") : "";
|
|
80501
80762
|
} catch {
|
|
80502
80763
|
return;
|
|
80503
80764
|
}
|
|
@@ -80515,7 +80776,7 @@ ${GITIGNORE_LINES.join("\n")}
|
|
|
80515
80776
|
var INTENT_TTL_MS = 15 * 60 * 1e3;
|
|
80516
80777
|
function createIntentState(ttlMs = INTENT_TTL_MS) {
|
|
80517
80778
|
const bySession = /* @__PURE__ */ new Map();
|
|
80518
|
-
let
|
|
80779
|
+
let recent3 = null;
|
|
80519
80780
|
const live3 = (s, nowMs) => s !== void 0 && nowMs - s.atMs < ttlMs;
|
|
80520
80781
|
return {
|
|
80521
80782
|
set(sessionId, text, nowMs) {
|
|
@@ -80523,8 +80784,8 @@ function createIntentState(ttlMs = INTENT_TTL_MS) {
|
|
|
80523
80784
|
if (!trimmed) return false;
|
|
80524
80785
|
const prev = bySession.get(sessionId);
|
|
80525
80786
|
bySession.set(sessionId, { text: trimmed, atMs: nowMs });
|
|
80526
|
-
const changed = !(
|
|
80527
|
-
|
|
80787
|
+
const changed = !(recent3 && recent3.text === trimmed);
|
|
80788
|
+
recent3 = { sessionId, text: trimmed, atMs: nowMs };
|
|
80528
80789
|
if (!changed && prev && prev.text === trimmed) return false;
|
|
80529
80790
|
return changed;
|
|
80530
80791
|
},
|
|
@@ -80533,12 +80794,12 @@ function createIntentState(ttlMs = INTENT_TTL_MS) {
|
|
|
80533
80794
|
return live3(s, nowMs) ? s.text : void 0;
|
|
80534
80795
|
},
|
|
80535
80796
|
mostRecent(nowMs) {
|
|
80536
|
-
if (!
|
|
80537
|
-
return nowMs -
|
|
80797
|
+
if (!recent3) return void 0;
|
|
80798
|
+
return nowMs - recent3.atMs < ttlMs ? recent3.text : void 0;
|
|
80538
80799
|
},
|
|
80539
80800
|
clear(sessionId) {
|
|
80540
80801
|
bySession.delete(sessionId);
|
|
80541
|
-
if (
|
|
80802
|
+
if (recent3?.sessionId === sessionId) recent3 = null;
|
|
80542
80803
|
}
|
|
80543
80804
|
};
|
|
80544
80805
|
}
|
|
@@ -80546,19 +80807,19 @@ function createIntentState(ttlMs = INTENT_TTL_MS) {
|
|
|
80546
80807
|
// src/working-file-state.ts
|
|
80547
80808
|
function createWorkingFileState() {
|
|
80548
80809
|
const bySession = /* @__PURE__ */ new Map();
|
|
80549
|
-
let
|
|
80810
|
+
let recent3 = null;
|
|
80550
80811
|
return {
|
|
80551
80812
|
set(sessionId, rel) {
|
|
80552
80813
|
bySession.set(sessionId, rel);
|
|
80553
|
-
if (rel ===
|
|
80554
|
-
|
|
80814
|
+
if (rel === recent3) return false;
|
|
80815
|
+
recent3 = rel;
|
|
80555
80816
|
return true;
|
|
80556
80817
|
},
|
|
80557
80818
|
get(sessionId) {
|
|
80558
80819
|
return bySession.get(sessionId);
|
|
80559
80820
|
},
|
|
80560
80821
|
mostRecent() {
|
|
80561
|
-
return
|
|
80822
|
+
return recent3;
|
|
80562
80823
|
}
|
|
80563
80824
|
};
|
|
80564
80825
|
}
|
|
@@ -80600,7 +80861,7 @@ init_paths();
|
|
|
80600
80861
|
init_profile2();
|
|
80601
80862
|
|
|
80602
80863
|
// src/witness-queue.ts
|
|
80603
|
-
import { readFileSync as
|
|
80864
|
+
import { readFileSync as readFileSync28, renameSync as renameSync2, writeFileSync as writeFileSync19 } from "node:fs";
|
|
80604
80865
|
import { dirname as dirname11, join as join32 } from "node:path";
|
|
80605
80866
|
var WITNESS_QUEUE_CAP = 500;
|
|
80606
80867
|
var WITNESS_TTL_MS = 14 * 24 * 60 * 60 * 1e3;
|
|
@@ -80611,7 +80872,7 @@ function witnessQueuePath(workspaceConfigDir) {
|
|
|
80611
80872
|
function loadWitnessQueueWithLosses(path2) {
|
|
80612
80873
|
let raw2;
|
|
80613
80874
|
try {
|
|
80614
|
-
raw2 = JSON.parse(
|
|
80875
|
+
raw2 = JSON.parse(readFileSync28(path2, "utf8"));
|
|
80615
80876
|
} catch (err2) {
|
|
80616
80877
|
const absent = err2?.code === "ENOENT";
|
|
80617
80878
|
return { queue: [], fileUnreadable: !absent, malformedEntries: 0 };
|
|
@@ -80673,9 +80934,9 @@ function partitionReplayable(queue, channel, isShipped) {
|
|
|
80673
80934
|
function retireWitnesses(queue, channel, settledKeys) {
|
|
80674
80935
|
return queue.filter((w) => !(w.channel === channel && settledKeys.has(w.witnessKey)));
|
|
80675
80936
|
}
|
|
80676
|
-
var WIRE_SHIPPED_LABELS = /* @__PURE__ */ new Set(["Problem", "Solution", "RootCause"]);
|
|
80937
|
+
var WIRE_SHIPPED_LABELS = /* @__PURE__ */ new Set(["Problem", "Vulnerability", "Solution", "RootCause"]);
|
|
80677
80938
|
var MOTIF_ID_PREFIX = "motif_community_";
|
|
80678
|
-
var CANONICAL_ID_RE = /^(?:pat|sol|drc|dcause|dfix|dprob|prob|claim|err)_[0-9a-f]{6,}$/i;
|
|
80939
|
+
var CANONICAL_ID_RE = /^(?:pat|sol|drc|dcause|dfix|dprob|dvuln|prob|claim|err)_[0-9a-f]{6,}$/i;
|
|
80679
80940
|
function classifyWitnessTarget(nodeId, getNode) {
|
|
80680
80941
|
if (nodeId.startsWith(MOTIF_ID_PREFIX)) {
|
|
80681
80942
|
const exemplar = nodeId.slice(MOTIF_ID_PREFIX.length);
|
|
@@ -80932,7 +81193,7 @@ function maybeFlushDigests() {
|
|
|
80932
81193
|
|
|
80933
81194
|
// src/liveness-watch.ts
|
|
80934
81195
|
init_src5();
|
|
80935
|
-
import { readFileSync as
|
|
81196
|
+
import { readFileSync as readFileSync30, writeFileSync as writeFileSync21 } from "node:fs";
|
|
80936
81197
|
import { join as join34 } from "node:path";
|
|
80937
81198
|
|
|
80938
81199
|
// src/loop-lag.ts
|
|
@@ -80941,7 +81202,7 @@ var RECENT_PASS_LIMIT = 12;
|
|
|
80941
81202
|
var active = /* @__PURE__ */ new Map();
|
|
80942
81203
|
var nextPassId = 1;
|
|
80943
81204
|
var started = false;
|
|
80944
|
-
var
|
|
81205
|
+
var recent2 = [];
|
|
80945
81206
|
function markPass(name2) {
|
|
80946
81207
|
const id = nextPassId++;
|
|
80947
81208
|
const startedAt = Date.now();
|
|
@@ -80951,8 +81212,8 @@ function markPass(name2) {
|
|
|
80951
81212
|
if (ended) return;
|
|
80952
81213
|
ended = true;
|
|
80953
81214
|
active.delete(id);
|
|
80954
|
-
|
|
80955
|
-
if (
|
|
81215
|
+
recent2.unshift({ name: name2, ms: Date.now() - startedAt, endedAt: Date.now() });
|
|
81216
|
+
if (recent2.length > RECENT_PASS_LIMIT) recent2.pop();
|
|
80956
81217
|
};
|
|
80957
81218
|
}
|
|
80958
81219
|
function oldestActive() {
|
|
@@ -80966,7 +81227,7 @@ function passState() {
|
|
|
80966
81227
|
current: oldest?.name ?? "idle",
|
|
80967
81228
|
runningMs: oldest === null ? null : now - oldest.startedAt,
|
|
80968
81229
|
active: [...active.values()].map((p) => ({ name: p.name, runningMs: now - p.startedAt })),
|
|
80969
|
-
recent: [...
|
|
81230
|
+
recent: [...recent2]
|
|
80970
81231
|
};
|
|
80971
81232
|
}
|
|
80972
81233
|
function describeHolders(running, finished, windowStart, now) {
|
|
@@ -80985,7 +81246,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
|
|
|
80985
81246
|
const now = Date.now();
|
|
80986
81247
|
const lag = now - last - HEARTBEAT_MS;
|
|
80987
81248
|
if (lag > thresholdMs) {
|
|
80988
|
-
const who = describeHolders(active.values(),
|
|
81249
|
+
const who = describeHolders(active.values(), recent2, last, now);
|
|
80989
81250
|
console.warn(
|
|
80990
81251
|
`[loop-lag] ${(/* @__PURE__ */ new Date()).toISOString()} event loop held ~${(lag / 1e3).toFixed(1)}s during "${who}"`
|
|
80991
81252
|
);
|
|
@@ -81068,7 +81329,7 @@ function alarmStatePath(configDir) {
|
|
|
81068
81329
|
}
|
|
81069
81330
|
function loadAlarmState(configDir) {
|
|
81070
81331
|
try {
|
|
81071
|
-
const raw2 = JSON.parse(
|
|
81332
|
+
const raw2 = JSON.parse(readFileSync30(alarmStatePath(configDir), "utf8"));
|
|
81072
81333
|
return new Map(Object.entries(raw2).filter((e) => typeof e[1] === "number"));
|
|
81073
81334
|
} catch {
|
|
81074
81335
|
return /* @__PURE__ */ new Map();
|
|
@@ -81229,8 +81490,8 @@ function createWatchBreaker(deps) {
|
|
|
81229
81490
|
windows2.set(watchedPath, w);
|
|
81230
81491
|
}
|
|
81231
81492
|
w.dispatched++;
|
|
81232
|
-
const
|
|
81233
|
-
if (!
|
|
81493
|
+
const self2 = evPath == null || evPath === "" || typeof evPath === "string" && normalizeWatchPath(evPath) === normalizeWatchPath(watchedPath);
|
|
81494
|
+
if (!self2) return;
|
|
81234
81495
|
w.self++;
|
|
81235
81496
|
if (!w.tripped && !quarantined.has(watchedPath) && w.self >= BREAKER_TRIP_SELF_EVENTS) {
|
|
81236
81497
|
w.tripped = true;
|
|
@@ -81245,7 +81506,7 @@ function createWatchBreaker(deps) {
|
|
|
81245
81506
|
}
|
|
81246
81507
|
|
|
81247
81508
|
// src/engine.ts
|
|
81248
|
-
var DAEMON_VERSION = true ? "2.0.16-dev.
|
|
81509
|
+
var DAEMON_VERSION = true ? "2.0.16-dev.3355" : "2.0.0-alpha.0";
|
|
81249
81510
|
var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
|
|
81250
81511
|
var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
|
|
81251
81512
|
var GIT_OP_MUTE_MS = 4e3;
|
|
@@ -81257,7 +81518,7 @@ var CODEX_SWEEP_LOOKBACK_MS = 10 * 6e4;
|
|
|
81257
81518
|
function appendIdentityAudit(path2, record2, line) {
|
|
81258
81519
|
if (!record2.accepted && record2.score <= 0) return;
|
|
81259
81520
|
try {
|
|
81260
|
-
if (
|
|
81521
|
+
if (existsSync27(path2) && statSync8(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
|
|
81261
81522
|
renameSync3(path2, `${path2}.1`);
|
|
81262
81523
|
}
|
|
81263
81524
|
appendFileSync4(path2, line);
|
|
@@ -81267,7 +81528,7 @@ function appendIdentityAudit(path2, record2, line) {
|
|
|
81267
81528
|
var yieldToLoop = () => new Promise((r) => setImmediate(r));
|
|
81268
81529
|
function loadTurnCursors(path2) {
|
|
81269
81530
|
try {
|
|
81270
|
-
const raw2 = JSON.parse(
|
|
81531
|
+
const raw2 = JSON.parse(readFileSync31(path2, "utf8"));
|
|
81271
81532
|
return new Map(
|
|
81272
81533
|
Object.entries(raw2).map(([k, v]) => [k, typeof v === "string" ? v : String(v?.uuid ?? "")])
|
|
81273
81534
|
);
|
|
@@ -81277,7 +81538,7 @@ function loadTurnCursors(path2) {
|
|
|
81277
81538
|
}
|
|
81278
81539
|
function loadTurnOffsets(path2) {
|
|
81279
81540
|
try {
|
|
81280
|
-
const raw2 = JSON.parse(
|
|
81541
|
+
const raw2 = JSON.parse(readFileSync31(path2, "utf8"));
|
|
81281
81542
|
const out2 = /* @__PURE__ */ new Map();
|
|
81282
81543
|
for (const [k, v] of Object.entries(raw2)) {
|
|
81283
81544
|
const off = typeof v === "object" && v !== null ? v.offset : void 0;
|
|
@@ -81300,7 +81561,7 @@ function saveTurnCursors(path2, cursors, offsets) {
|
|
|
81300
81561
|
function gitSourceWatchTargets(root) {
|
|
81301
81562
|
const SOURCE = /\.(ts|tsx|js|jsx|mjs|cjs|py)$/i;
|
|
81302
81563
|
try {
|
|
81303
|
-
const lsOut =
|
|
81564
|
+
const lsOut = execFileSync5("git", ["-C", root, "ls-files", "-z"], {
|
|
81304
81565
|
encoding: "utf8",
|
|
81305
81566
|
maxBuffer: 128 * 1024 * 1024,
|
|
81306
81567
|
windowsHide: true,
|
|
@@ -81310,7 +81571,7 @@ function gitSourceWatchTargets(root) {
|
|
|
81310
81571
|
if (sourceFiles.length === 0) throw new Error("no tracked source");
|
|
81311
81572
|
let ignoredDirs = [];
|
|
81312
81573
|
try {
|
|
81313
|
-
const igOut =
|
|
81574
|
+
const igOut = execFileSync5(
|
|
81314
81575
|
"git",
|
|
81315
81576
|
["-C", root, "ls-files", "--others", "--ignored", "--exclude-standard", "--directory", "-z"],
|
|
81316
81577
|
{ encoding: "utf8", maxBuffer: 256 * 1024 * 1024, windowsHide: true, stdio: ["ignore", "pipe", "ignore"] }
|
|
@@ -81582,7 +81843,7 @@ function createWorkspaceEngine(opts) {
|
|
|
81582
81843
|
);
|
|
81583
81844
|
};
|
|
81584
81845
|
const gitDir = join35(opts.workspaceRoot, ".git");
|
|
81585
|
-
if (
|
|
81846
|
+
if (existsSync27(gitDir)) {
|
|
81586
81847
|
stopGit = startGitSensor(gitDir, (ev) => {
|
|
81587
81848
|
void handleGitEvent(ev).catch((err2) => {
|
|
81588
81849
|
console.warn("[errata] git event handler failed:", err2);
|
|
@@ -82137,6 +82398,9 @@ function createWorkspaceEngine(opts) {
|
|
|
82137
82398
|
const harvestTextsInner = async (sessionId, items) => {
|
|
82138
82399
|
let minted = 0;
|
|
82139
82400
|
let tagsSeen = 0;
|
|
82401
|
+
let vulnerabilitiesSeen = 0;
|
|
82402
|
+
let vulnerabilitiesMinted = 0;
|
|
82403
|
+
let vulnerabilitiesSuspected = 0;
|
|
82140
82404
|
let tagsRejected = 0;
|
|
82141
82405
|
let tagsRestated = 0;
|
|
82142
82406
|
let resolved = 0;
|
|
@@ -82367,10 +82631,73 @@ function createWorkspaceEngine(opts) {
|
|
|
82367
82631
|
if ((toolRuns.get(sessionId)?.size ?? 0) > 0) touchedToolTurns++;
|
|
82368
82632
|
const wf = workingFiles.get(sessionId);
|
|
82369
82633
|
let inScopeProblemId;
|
|
82634
|
+
const findingIds = /* @__PURE__ */ new Map();
|
|
82635
|
+
const conflictingThreads = /* @__PURE__ */ new Set();
|
|
82370
82636
|
const threads = sessionThreads.get(sessionId) ?? /* @__PURE__ */ new Map();
|
|
82371
82637
|
sessionThreads.set(sessionId, threads);
|
|
82372
82638
|
for (const p of plan.problems) {
|
|
82373
82639
|
tagsSeen++;
|
|
82640
|
+
if (p.kind === "vulnerability") {
|
|
82641
|
+
vulnerabilitiesSeen++;
|
|
82642
|
+
if (p.assessment === "suspected") vulnerabilitiesSuspected++;
|
|
82643
|
+
let fileText;
|
|
82644
|
+
let anchorReadFailed = false;
|
|
82645
|
+
if (p.location) {
|
|
82646
|
+
try {
|
|
82647
|
+
fileText = readFileSync31(join35(opts.workspaceRoot, p.location.path), "utf8");
|
|
82648
|
+
} catch {
|
|
82649
|
+
anchorReadFailed = true;
|
|
82650
|
+
}
|
|
82651
|
+
}
|
|
82652
|
+
const result = ingestWitnessedVulnerability(store, {
|
|
82653
|
+
statement: p.statement,
|
|
82654
|
+
assessment: p.assessment,
|
|
82655
|
+
target: p.location?.path,
|
|
82656
|
+
line: p.location?.line,
|
|
82657
|
+
fileText,
|
|
82658
|
+
existingId: p.threadId ? threads.get(p.threadId) ?? handleMap[p.threadId]?.id ?? store.getNode(p.threadId)?.id : void 0
|
|
82659
|
+
}, { workspaceId: profile.id, source: sessionId, ts: t, hostHarness: turn.hostHarness });
|
|
82660
|
+
let anchorDisposition = p.location ? "unresolved" : "absent";
|
|
82661
|
+
if (result.rejected) {
|
|
82662
|
+
tagsRejected++;
|
|
82663
|
+
if (p.threadId) conflictingThreads.add(p.threadId);
|
|
82664
|
+
} else {
|
|
82665
|
+
findingIds.set(p.statement, result.id);
|
|
82666
|
+
if (p.threadId) threads.set(p.threadId, result.id);
|
|
82667
|
+
if (result.created || result.corroborated || result.upgraded) minted++;
|
|
82668
|
+
else tagsRestated++;
|
|
82669
|
+
if (result.created) vulnerabilitiesMinted++;
|
|
82670
|
+
if (p.location) {
|
|
82671
|
+
try {
|
|
82672
|
+
const anchored = anchorProblemToWorkingFile(store, result.id, p.location.path, profile.id, t, "witnessed", { line: p.location.line, fileText });
|
|
82673
|
+
anchorDisposition = anchored ? "resolved" : anchorReadFailed ? "error" : "unresolved";
|
|
82674
|
+
if (anchored) deriveContextFromAnchors(store, result.id, t);
|
|
82675
|
+
} catch {
|
|
82676
|
+
anchorDisposition = "error";
|
|
82677
|
+
}
|
|
82678
|
+
}
|
|
82679
|
+
const node2 = store.getNode(result.id);
|
|
82680
|
+
store.updateNode(result.id, { attrs: { ...node2.attrs, anchorDisposition } });
|
|
82681
|
+
if (p.vulnerabilityCauses) triaged += recordVulnerabilityCause(store, result.id, p.vulnerabilityCauses, t);
|
|
82682
|
+
}
|
|
82683
|
+
log.append({
|
|
82684
|
+
kind: "vulnerability.witness",
|
|
82685
|
+
workspaceId: profile.id,
|
|
82686
|
+
ts: t,
|
|
82687
|
+
digest: digest({ kind: "vulnerability.witness", workspaceId: profile.id, sessionId, turnId: turn.uuid, statement: p.statement, assessment: p.assessment, location: p.location }),
|
|
82688
|
+
sessionId,
|
|
82689
|
+
turnId: turn.uuid,
|
|
82690
|
+
harness: turn.hostHarness,
|
|
82691
|
+
findingId: result.id,
|
|
82692
|
+
statement: p.statement,
|
|
82693
|
+
assessment: p.assessment,
|
|
82694
|
+
location: p.location,
|
|
82695
|
+
seq: p.seq,
|
|
82696
|
+
anchorDisposition,
|
|
82697
|
+
disposition: result.rejected ?? (result.created ? "created" : result.upgraded ? "upgraded" : result.corroborated ? "corroborated" : "restated")
|
|
82698
|
+
});
|
|
82699
|
+
continue;
|
|
82700
|
+
}
|
|
82374
82701
|
const anchorPath = p.location?.path ?? editedTurnFile;
|
|
82375
82702
|
const anchorProvenance = p.location?.path ? "witnessed" : "edited";
|
|
82376
82703
|
const hintPath = anchorPath ? void 0 : turnFile ?? wf;
|
|
@@ -82465,10 +82792,10 @@ function createWorkspaceEngine(opts) {
|
|
|
82465
82792
|
if (r.created || r.corroborated) {
|
|
82466
82793
|
minted++;
|
|
82467
82794
|
if (p.kind !== "constraint") {
|
|
82468
|
-
sessionLastProblem.set(sessionId,
|
|
82469
|
-
inScopeProblemId =
|
|
82795
|
+
sessionLastProblem.set(sessionId, r.problemId);
|
|
82796
|
+
inScopeProblemId = r.problemId;
|
|
82470
82797
|
}
|
|
82471
|
-
if (p.threadId) threads.set(p.threadId,
|
|
82798
|
+
if (p.threadId) threads.set(p.threadId, r.problemId);
|
|
82472
82799
|
try {
|
|
82473
82800
|
if (anchorPath) {
|
|
82474
82801
|
let enclosing = {};
|
|
@@ -82477,7 +82804,7 @@ function createWorkspaceEngine(opts) {
|
|
|
82477
82804
|
const headSha = readGitRefState(join35(opts.workspaceRoot, ".git")).sha ?? void 0;
|
|
82478
82805
|
enclosing = {
|
|
82479
82806
|
line: p.location.line,
|
|
82480
|
-
fileText:
|
|
82807
|
+
fileText: readFileSync31(join35(opts.workspaceRoot, anchorPath), "utf8"),
|
|
82481
82808
|
...headSha ? { headSha } : {}
|
|
82482
82809
|
};
|
|
82483
82810
|
} catch {
|
|
@@ -82505,7 +82832,8 @@ function createWorkspaceEngine(opts) {
|
|
|
82505
82832
|
);
|
|
82506
82833
|
}
|
|
82507
82834
|
for (const fx of plan.fixes) {
|
|
82508
|
-
|
|
82835
|
+
if (fx.threadId && conflictingThreads.has(fx.threadId)) continue;
|
|
82836
|
+
const pid = fx.problemId ?? (fx.threadId ? threads.get(fx.threadId) : void 0) ?? (fx.boundStatement ? findingIds.get(fx.boundStatement) ?? designProblemId(fx.boundStatement) : void 0);
|
|
82509
82837
|
if (!pid) {
|
|
82510
82838
|
if (fx.inScope) {
|
|
82511
82839
|
console.warn(
|
|
@@ -82517,7 +82845,7 @@ function createWorkspaceEngine(opts) {
|
|
|
82517
82845
|
const closed = resolveDesignProblemById(store, pid, fx.fixNote, t);
|
|
82518
82846
|
if (!closed) {
|
|
82519
82847
|
const n = store.getNode(pid);
|
|
82520
|
-
if (!n || n.label !== "Problem" || n.attrs["resolvedAs"] != null) {
|
|
82848
|
+
if (!n || n.label !== "Problem" && n.label !== "Vulnerability" || n.attrs["resolvedAs"] != null) {
|
|
82521
82849
|
console.warn(
|
|
82522
82850
|
`[errata] fix tag went nowhere: ${!n ? `id ${pid.slice(0, 32)} unknown` : n.label !== "Problem" ? `${pid.slice(0, 32)} is a ${n.label}, not a Problem` : "the problem was retracted \u2014 a retraction is not fixable"} \u2014 the fix was NOT recorded`
|
|
82523
82851
|
);
|
|
@@ -82536,10 +82864,23 @@ function createWorkspaceEngine(opts) {
|
|
|
82536
82864
|
}
|
|
82537
82865
|
}
|
|
82538
82866
|
}
|
|
82867
|
+
const vulnerabilityTriages = /* @__PURE__ */ new Set();
|
|
82868
|
+
for (const tr of plan.triages) {
|
|
82869
|
+
if (tr.threadId && conflictingThreads.has(tr.threadId)) {
|
|
82870
|
+
vulnerabilityTriages.add(tr);
|
|
82871
|
+
continue;
|
|
82872
|
+
}
|
|
82873
|
+
const id = tr.symptomProblemId ?? (tr.threadId ? threads.get(tr.threadId) : void 0) ?? (tr.symptomStatement ? findingIds.get(tr.symptomStatement) : void 0);
|
|
82874
|
+
if (id && store.getNode(id)?.label === "Vulnerability") {
|
|
82875
|
+
vulnerabilityTriages.add(tr);
|
|
82876
|
+
if (tr.evidence === "witnessed" && tr.causeDescription) triaged += recordVulnerabilityCause(store, id, [tr.causeDescription], t);
|
|
82877
|
+
}
|
|
82878
|
+
}
|
|
82539
82879
|
if (opts.sharedStore && plan.triages.length > 0) {
|
|
82540
82880
|
const fallbackId = sessionLastProblem.get(sessionId);
|
|
82541
82881
|
const fallbackStatement = fallbackId ? store.getNode(fallbackId)?.description : void 0;
|
|
82542
82882
|
for (const tr of plan.triages) {
|
|
82883
|
+
if (vulnerabilityTriages.has(tr)) continue;
|
|
82543
82884
|
let presentingStatement = tr.symptomStatement;
|
|
82544
82885
|
let evidence = tr.evidence;
|
|
82545
82886
|
if (!presentingStatement && tr.threadId) {
|
|
@@ -82557,7 +82898,7 @@ function createWorkspaceEngine(opts) {
|
|
|
82557
82898
|
evidence = "inferred";
|
|
82558
82899
|
}
|
|
82559
82900
|
if (!presentingStatement) continue;
|
|
82560
|
-
const presentingId = tr.symptomProblemId ?? designProblemId(presentingStatement);
|
|
82901
|
+
const presentingId = tr.symptomProblemId ?? (tr.threadId ? threads.get(tr.threadId) : void 0) ?? designProblemId(presentingStatement);
|
|
82561
82902
|
if (tr.causeId === presentingId) continue;
|
|
82562
82903
|
try {
|
|
82563
82904
|
recordTriageObservation(
|
|
@@ -82615,7 +82956,7 @@ function createWorkspaceEngine(opts) {
|
|
|
82615
82956
|
}
|
|
82616
82957
|
}
|
|
82617
82958
|
for (const at of plan.attempts) {
|
|
82618
|
-
const pid = at.problemId ?? (at.threadId ? threads.get(at.threadId) : void 0) ?? (at.boundStatement ? designProblemId(at.boundStatement) : void 0);
|
|
82959
|
+
const pid = at.problemId ?? (at.threadId ? threads.get(at.threadId) : void 0) ?? (at.boundStatement ? findingIds.get(at.boundStatement) ?? designProblemId(at.boundStatement) : void 0);
|
|
82619
82960
|
const node2 = pid ? store.getNode(pid) : void 0;
|
|
82620
82961
|
if (!pid || !node2) continue;
|
|
82621
82962
|
try {
|
|
@@ -82631,7 +82972,7 @@ function createWorkspaceEngine(opts) {
|
|
|
82631
82972
|
}
|
|
82632
82973
|
}
|
|
82633
82974
|
const bindPid = (tag) => {
|
|
82634
|
-
const pid = tag.problemId ?? (tag.threadId ? threads.get(tag.threadId) : void 0) ?? (tag.boundStatement ? designProblemId(tag.boundStatement) : void 0) ?? inScopeProblemId ?? sessionLastProblem.get(sessionId);
|
|
82975
|
+
const pid = tag.problemId ?? (tag.threadId ? threads.get(tag.threadId) : void 0) ?? (tag.boundStatement ? findingIds.get(tag.boundStatement) ?? designProblemId(tag.boundStatement) : void 0) ?? inScopeProblemId ?? sessionLastProblem.get(sessionId);
|
|
82635
82976
|
return pid && store.getNode(pid) ? pid : void 0;
|
|
82636
82977
|
};
|
|
82637
82978
|
const mintCiteEdge = (from, to, type, confidence, extraAttrs) => {
|
|
@@ -82785,7 +83126,12 @@ function createWorkspaceEngine(opts) {
|
|
|
82785
83126
|
for (const [session, items2] of groups) {
|
|
82786
83127
|
if (items2.length === 0) continue;
|
|
82787
83128
|
try {
|
|
82788
|
-
const
|
|
83129
|
+
const wireItems = items2.map(({ nodeId, witnessKey }) => {
|
|
83130
|
+
const node2 = store.getNode(nodeId);
|
|
83131
|
+
const cloudId = node2?.attrs["privateFinding"] ? node2.attrs["cloudNodeId"] : void 0;
|
|
83132
|
+
return { nodeId: typeof cloudId === "string" ? cloudId : nodeId, witnessKey };
|
|
83133
|
+
});
|
|
83134
|
+
const raw2 = await send(wireItems, session);
|
|
82789
83135
|
const d = {
|
|
82790
83136
|
recorded: raw2?.recorded ?? 0,
|
|
82791
83137
|
unmatched: raw2?.unmatched ?? 0,
|
|
@@ -82798,8 +83144,8 @@ function createWorkspaceEngine(opts) {
|
|
|
82798
83144
|
duplicate += d.duplicate;
|
|
82799
83145
|
selfGated += d.selfGated;
|
|
82800
83146
|
const missing = new Set(d.unmatchedIds);
|
|
82801
|
-
for (const it of items2) {
|
|
82802
|
-
if (missing.has(
|
|
83147
|
+
for (const [index, it] of items2.entries()) {
|
|
83148
|
+
if (missing.has(wireItems[index].nodeId)) stillUnmatched.push({ channel, ...it, sessionKey: session, counted: isShipped(it.nodeId) });
|
|
82803
83149
|
else settled.add(it.witnessKey);
|
|
82804
83150
|
}
|
|
82805
83151
|
} catch (err2) {
|
|
@@ -82969,6 +83315,10 @@ function createWorkspaceEngine(opts) {
|
|
|
82969
83315
|
// but nothing judgeable was cited.
|
|
82970
83316
|
tagsVerdictNoHandle: dispositions.verdictNoHandle,
|
|
82971
83317
|
tagsFlagAsHandle: dispositions.flagAsHandle,
|
|
83318
|
+
tagsInvalidVulnerability: dispositions.invalidVulnerability,
|
|
83319
|
+
vulnerabilitiesSeen,
|
|
83320
|
+
vulnerabilitiesMinted,
|
|
83321
|
+
vulnerabilitiesSuspected,
|
|
82972
83322
|
unresolvedHandles,
|
|
82973
83323
|
priorEdgesFlagOff,
|
|
82974
83324
|
priorEdgesNoSource,
|
|
@@ -83583,7 +83933,7 @@ B: ${b}`,
|
|
|
83583
83933
|
console.log(
|
|
83584
83934
|
"[errata] sync skipped \u2014 cloud sync consent is off (enable with `errata consent sync on`)"
|
|
83585
83935
|
);
|
|
83586
|
-
const pending =
|
|
83936
|
+
const pending = existsSync27(paths.outbox) ? readdirSync10(paths.outbox).filter((f) => f.endsWith(".json")).length : 0;
|
|
83587
83937
|
return { uploaded: 0, failed: 0, remaining: pending };
|
|
83588
83938
|
}
|
|
83589
83939
|
const onDisk = loadProfile(opts.workspaceRoot);
|
|
@@ -83591,7 +83941,7 @@ B: ${b}`,
|
|
|
83591
83941
|
console.log(
|
|
83592
83942
|
"[errata] sync held \u2014 this repo is already on errata in another workspace; run `errata link` to join it or create your own project"
|
|
83593
83943
|
);
|
|
83594
|
-
const pending =
|
|
83944
|
+
const pending = existsSync27(paths.outbox) ? readdirSync10(paths.outbox).filter((f) => f.endsWith(".json")).length : 0;
|
|
83595
83945
|
return { uploaded: 0, failed: 0, remaining: pending };
|
|
83596
83946
|
}
|
|
83597
83947
|
try {
|
|
@@ -83727,7 +84077,7 @@ async function startDaemon(opts) {
|
|
|
83727
84077
|
);
|
|
83728
84078
|
await engine.stop();
|
|
83729
84079
|
try {
|
|
83730
|
-
if (
|
|
84080
|
+
if (existsSync28(engine.paths.daemonLock)) {
|
|
83731
84081
|
}
|
|
83732
84082
|
} catch {
|
|
83733
84083
|
}
|
|
@@ -83928,7 +84278,7 @@ function instanceReceiptSequence(n) {
|
|
|
83928
84278
|
// src/multi.ts
|
|
83929
84279
|
init_dist();
|
|
83930
84280
|
init_src5();
|
|
83931
|
-
import { existsSync as existsSync33, readFileSync as
|
|
84281
|
+
import { existsSync as existsSync33, readFileSync as readFileSync35, unlinkSync as unlinkSync4, writeFileSync as writeFileSync25 } from "node:fs";
|
|
83932
84282
|
import { resolve as pathResolve } from "node:path";
|
|
83933
84283
|
|
|
83934
84284
|
// src/principle-sync.ts
|
|
@@ -83957,7 +84307,7 @@ init_reconcile();
|
|
|
83957
84307
|
|
|
83958
84308
|
// src/lockfile-auto.ts
|
|
83959
84309
|
init_src();
|
|
83960
|
-
import { existsSync as
|
|
84310
|
+
import { existsSync as existsSync29, readFileSync as readFileSync32 } from "node:fs";
|
|
83961
84311
|
import { join as join36 } from "node:path";
|
|
83962
84312
|
|
|
83963
84313
|
// src/package-index.ts
|
|
@@ -84108,10 +84458,10 @@ function runLockfilePass(opts) {
|
|
|
84108
84458
|
];
|
|
84109
84459
|
for (const c of candidates) {
|
|
84110
84460
|
const p = join36(opts.root, c.file);
|
|
84111
|
-
if (!
|
|
84461
|
+
if (!existsSync29(p)) continue;
|
|
84112
84462
|
let sbom;
|
|
84113
84463
|
try {
|
|
84114
|
-
sbom = c.parse(
|
|
84464
|
+
sbom = c.parse(readFileSync32(p, "utf8"));
|
|
84115
84465
|
} catch {
|
|
84116
84466
|
continue;
|
|
84117
84467
|
}
|
|
@@ -84171,7 +84521,7 @@ function noveltyAgainst(node2, neighbors, opts = {}) {
|
|
|
84171
84521
|
init_profile2();
|
|
84172
84522
|
|
|
84173
84523
|
// src/public-symbols.ts
|
|
84174
|
-
import { readFileSync as
|
|
84524
|
+
import { readFileSync as readFileSync33, readdirSync as readdirSync11, existsSync as existsSync30 } from "node:fs";
|
|
84175
84525
|
import { join as join37 } from "node:path";
|
|
84176
84526
|
var HEAD_BYTES = 8 * 1024;
|
|
84177
84527
|
var INDEX_TTL_MS = 10 * 60 * 1e3;
|
|
@@ -84206,9 +84556,9 @@ function internalPackageNames(workspaceRoot) {
|
|
|
84206
84556
|
const names = /* @__PURE__ */ new Set();
|
|
84207
84557
|
const tryRead = (dir) => {
|
|
84208
84558
|
const pj = join37(dir, "package.json");
|
|
84209
|
-
if (!
|
|
84559
|
+
if (!existsSync30(pj)) return;
|
|
84210
84560
|
try {
|
|
84211
|
-
const name2 = JSON.parse(
|
|
84561
|
+
const name2 = JSON.parse(readFileSync33(pj, "utf8")).name;
|
|
84212
84562
|
if (typeof name2 === "string" && name2.length > 0) names.add(name2);
|
|
84213
84563
|
} catch {
|
|
84214
84564
|
}
|
|
@@ -84216,7 +84566,7 @@ function internalPackageNames(workspaceRoot) {
|
|
|
84216
84566
|
tryRead(workspaceRoot);
|
|
84217
84567
|
for (const group of ["packages", "apps"]) {
|
|
84218
84568
|
const groupDir = join37(workspaceRoot, group);
|
|
84219
|
-
if (!
|
|
84569
|
+
if (!existsSync30(groupDir)) continue;
|
|
84220
84570
|
try {
|
|
84221
84571
|
for (const entry of readdirSync11(groupDir)) tryRead(join37(groupDir, entry));
|
|
84222
84572
|
} catch {
|
|
@@ -84237,7 +84587,7 @@ function publicSymbolIndex(store, workspaceRoot, deps = {}) {
|
|
|
84237
84587
|
}
|
|
84238
84588
|
const readHead = deps.readHead ?? ((absPath) => {
|
|
84239
84589
|
try {
|
|
84240
|
-
return
|
|
84590
|
+
return readFileSync33(absPath, "utf8").slice(0, HEAD_BYTES);
|
|
84241
84591
|
} catch {
|
|
84242
84592
|
return "";
|
|
84243
84593
|
}
|
|
@@ -84305,7 +84655,7 @@ function internalSymbolsFor(description, lexiconHas, publicIndex) {
|
|
|
84305
84655
|
|
|
84306
84656
|
// src/instance-ingest.ts
|
|
84307
84657
|
init_generalize_graph();
|
|
84308
|
-
var INSTANCE_LABELS = ["Problem", "Solution", "RootCause"];
|
|
84658
|
+
var INSTANCE_LABELS = ["Problem", "Vulnerability", "Solution", "RootCause"];
|
|
84309
84659
|
var INSTANCE_EDGES = ["CAUSED_BY", "SOLVED_BY"];
|
|
84310
84660
|
var ANCHOR_EDGES = ["OCCURS_IN", "DEPENDS_ON", "PERTAIN_TO", "CONCERNS"];
|
|
84311
84661
|
var ANCHOR_TARGET_LABELS = ["Language", "Package", "Domain", "Component"];
|
|
@@ -84440,6 +84790,10 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
|
|
|
84440
84790
|
attrs: {
|
|
84441
84791
|
scope: stripCodebaseScope(n.attrs["scope"]),
|
|
84442
84792
|
...n.attrs["kind"] ? { kind: n.attrs["kind"] } : {},
|
|
84793
|
+
...n.attrs["privateFinding"] ? { privateFinding: true } : {},
|
|
84794
|
+
...n.attrs["assessment"] ? { assessment: n.attrs["assessment"] } : {},
|
|
84795
|
+
...n.attrs["sourceClass"] ? { sourceClass: n.attrs["sourceClass"] } : {},
|
|
84796
|
+
...n.attrs["resolutionWitnessed"] ? { resolutionWitnessed: true, resolvedAt: n.attrs["resolvedAt"] } : {},
|
|
84443
84797
|
...n.attrs["resolvedAs"] ? { resolvedAs: n.attrs["resolvedAs"] } : {},
|
|
84444
84798
|
...preserved.length > 0 ? { preservedSymbols: preserved } : {},
|
|
84445
84799
|
...internal.length > 0 ? { internalSymbols: internal } : {}
|
|
@@ -84454,6 +84808,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
|
|
|
84454
84808
|
const semanticEndpoints = /* @__PURE__ */ new Map();
|
|
84455
84809
|
const includedByLabel = /* @__PURE__ */ new Map();
|
|
84456
84810
|
const composition = {
|
|
84811
|
+
privateTargetMissing: 0,
|
|
84457
84812
|
candidates: 0,
|
|
84458
84813
|
shipped: 0,
|
|
84459
84814
|
cloudSourced: 0,
|
|
@@ -84499,11 +84854,15 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
|
|
|
84499
84854
|
if (walked.has(n.id)) continue;
|
|
84500
84855
|
walked.add(n.id);
|
|
84501
84856
|
composition.candidates++;
|
|
84857
|
+
if ((n.attrs["privateFinding"] || n.label === "Vulnerability") && !opts.project) {
|
|
84858
|
+
composition.privateTargetMissing++;
|
|
84859
|
+
continue;
|
|
84860
|
+
}
|
|
84502
84861
|
if (n.attrs["source"] === "cloud") {
|
|
84503
84862
|
composition.cloudSourced++;
|
|
84504
84863
|
continue;
|
|
84505
84864
|
}
|
|
84506
|
-
if (
|
|
84865
|
+
if (n.attrs["resolvedAs"] === PROBLEM_RESOLUTION.FALSE_POSITIVE) {
|
|
84507
84866
|
composition.falsePositive++;
|
|
84508
84867
|
continue;
|
|
84509
84868
|
}
|
|
@@ -84526,7 +84885,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
|
|
|
84526
84885
|
composition.terminalRefused++;
|
|
84527
84886
|
continue;
|
|
84528
84887
|
}
|
|
84529
|
-
if (!noveltyAgainst(n, ref, noveltyOpts).ready) {
|
|
84888
|
+
if (!n.attrs["privateFinding"] && !noveltyAgainst(n, ref, noveltyOpts).ready) {
|
|
84530
84889
|
composition.notNovel++;
|
|
84531
84890
|
continue;
|
|
84532
84891
|
}
|
|
@@ -84569,7 +84928,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
|
|
|
84569
84928
|
}
|
|
84570
84929
|
if (targets.length === 0) continue;
|
|
84571
84930
|
const shipped = shippedById.get(sourceId);
|
|
84572
|
-
if (shipped) {
|
|
84931
|
+
if (shipped && !shipped.attrs["privateFinding"]) {
|
|
84573
84932
|
const anchors = (label) => targets.filter((x) => x.t.label === label).map(
|
|
84574
84933
|
(x) => label === "Language" ? langAnchor(x.t) : label === "Component" ? `component:${x.wireId}` : x.wireId
|
|
84575
84934
|
).filter((a) => a != null).sort();
|
|
@@ -85055,59 +85414,8 @@ function cloudTargetDrift(daemon, shell2) {
|
|
|
85055
85414
|
return out2;
|
|
85056
85415
|
}
|
|
85057
85416
|
|
|
85058
|
-
// src/lock.ts
|
|
85059
|
-
import { existsSync as existsSync30, readFileSync as readFileSync32 } from "node:fs";
|
|
85060
|
-
function daemonLockPayload(lock) {
|
|
85061
|
-
return JSON.stringify({
|
|
85062
|
-
pid: lock.pid,
|
|
85063
|
-
webUiUrl: lock.webUiUrl,
|
|
85064
|
-
startedAt: lock.processStartedAt,
|
|
85065
|
-
...lock.wokeAt !== void 0 ? { wokeAt: lock.wokeAt } : {},
|
|
85066
|
-
...lock.entry ? { entry: lock.entry } : {},
|
|
85067
|
-
...lock.version ? { version: lock.version } : {}
|
|
85068
|
-
});
|
|
85069
|
-
}
|
|
85070
|
-
var normEntry = (p) => {
|
|
85071
|
-
const s = p.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
85072
|
-
return /^[A-Za-z]:\//.test(s) ? s.toLowerCase() : s;
|
|
85073
|
-
};
|
|
85074
|
-
function isInstalledEntry(entry) {
|
|
85075
|
-
return /\/node_modules\/@inerrata-corporation\/errata\//.test(normEntry(entry) + "/");
|
|
85076
|
-
}
|
|
85077
|
-
function foreignDaemonNote(lock, selfEntry) {
|
|
85078
|
-
if (!lock.entry || normEntry(lock.entry) === normEntry(selfEntry)) return null;
|
|
85079
|
-
const runningInstalled = isInstalledEntry(lock.entry);
|
|
85080
|
-
const head2 = [
|
|
85081
|
-
`launched from ${runningInstalled ? "the installed package" : "a LOCAL BUILD"}, not this one${lock.version ? ` (it is ${lock.version})` : ""}:`,
|
|
85082
|
-
` running: ${lock.entry}`,
|
|
85083
|
-
` this: ${selfEntry}`
|
|
85084
|
-
];
|
|
85085
|
-
return runningInstalled ? [...head2, "this CLI is a different bundle from the daemon it is talking to \u2014 its view may not match what the daemon runs."] : [...head2, "`errata update` does not replace it. To move onto the installed package: errata stop, then errata dash."];
|
|
85086
|
-
}
|
|
85087
|
-
function isProcessAlive(pid) {
|
|
85088
|
-
if (!pid || pid <= 0) return false;
|
|
85089
|
-
try {
|
|
85090
|
-
process.kill(pid, 0);
|
|
85091
|
-
return true;
|
|
85092
|
-
} catch (err2) {
|
|
85093
|
-
return err2.code === "EPERM";
|
|
85094
|
-
}
|
|
85095
|
-
}
|
|
85096
|
-
function readDaemonLock(lockPath) {
|
|
85097
|
-
if (!existsSync30(lockPath)) return null;
|
|
85098
|
-
try {
|
|
85099
|
-
const lock = JSON.parse(readFileSync32(lockPath, "utf8"));
|
|
85100
|
-
return typeof lock.pid === "number" ? lock : null;
|
|
85101
|
-
} catch {
|
|
85102
|
-
return null;
|
|
85103
|
-
}
|
|
85104
|
-
}
|
|
85105
|
-
function isDaemonAlive(lockPath) {
|
|
85106
|
-
const lock = readDaemonLock(lockPath);
|
|
85107
|
-
return lock !== null && isProcessAlive(lock.pid);
|
|
85108
|
-
}
|
|
85109
|
-
|
|
85110
85417
|
// src/multi.ts
|
|
85418
|
+
init_lock();
|
|
85111
85419
|
init_config();
|
|
85112
85420
|
|
|
85113
85421
|
// src/update.ts
|
|
@@ -85810,7 +86118,7 @@ async function syncHistoryRevisionPage(opts) {
|
|
|
85810
86118
|
init_src7();
|
|
85811
86119
|
init_src();
|
|
85812
86120
|
import { execFile as execFile5 } from "node:child_process";
|
|
85813
|
-
import { readFileSync as
|
|
86121
|
+
import { readFileSync as readFileSync34 } from "node:fs";
|
|
85814
86122
|
import { join as join38 } from "node:path";
|
|
85815
86123
|
import { promisify as promisify3 } from "node:util";
|
|
85816
86124
|
|
|
@@ -86358,7 +86666,7 @@ async function defaultGit(root, args2) {
|
|
|
86358
86666
|
function readIgnoreLines(root, profile) {
|
|
86359
86667
|
let lines = [];
|
|
86360
86668
|
try {
|
|
86361
|
-
lines =
|
|
86669
|
+
lines = readFileSync34(join38(root, ".errataignore"), "utf8").split("\n");
|
|
86362
86670
|
} catch {
|
|
86363
86671
|
}
|
|
86364
86672
|
return [...lines, ...profile.ignoreExtra ?? []].map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
|
|
@@ -86787,7 +87095,7 @@ async function startHistoryStage(root, input, client, walk11 = {}) {
|
|
|
86787
87095
|
// src/link-flow.ts
|
|
86788
87096
|
init_cloud_auth();
|
|
86789
87097
|
import { createHash as createHash19 } from "node:crypto";
|
|
86790
|
-
import { execFileSync as
|
|
87098
|
+
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
86791
87099
|
import { existsSync as existsSync31, writeFileSync as writeFileSync24 } from "node:fs";
|
|
86792
87100
|
import { join as join39 } from "node:path";
|
|
86793
87101
|
|
|
@@ -87175,7 +87483,7 @@ async function linkThroughConsole(opts) {
|
|
|
87175
87483
|
function collectRepoFacts(root) {
|
|
87176
87484
|
const git3 = (args2) => {
|
|
87177
87485
|
try {
|
|
87178
|
-
return
|
|
87486
|
+
return execFileSync6("git", args2, { cwd: root, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
|
|
87179
87487
|
} catch {
|
|
87180
87488
|
return null;
|
|
87181
87489
|
}
|
|
@@ -87609,9 +87917,9 @@ function ownerOf(records, absPath) {
|
|
|
87609
87917
|
}
|
|
87610
87918
|
async function startMultiDaemon(opts = {}) {
|
|
87611
87919
|
const lockPath = globalDaemonLock();
|
|
87612
|
-
if (opts.enforceSingleton !== false &&
|
|
87920
|
+
if (opts.enforceSingleton !== false && daemonLockBlocksStartup(lockPath)) {
|
|
87613
87921
|
throw new Error(
|
|
87614
|
-
`
|
|
87922
|
+
`a daemon lock is live or its process ownership cannot be verified (lock: ${lockPath}). Run \`errata doctor\` to inspect it, or \`errata stop\` to stop a verified owner.`
|
|
87615
87923
|
);
|
|
87616
87924
|
}
|
|
87617
87925
|
const cfg = loadConfig();
|
|
@@ -89298,8 +89606,8 @@ async function startMultiDaemon(opts = {}) {
|
|
|
89298
89606
|
clearInterval(anchorPull);
|
|
89299
89607
|
clearTimeout(codexWakeBoot);
|
|
89300
89608
|
try {
|
|
89301
|
-
const cur =
|
|
89302
|
-
if (JSON.parse(cur).pid === process.pid)
|
|
89609
|
+
const cur = readFileSync35(lockPath, "utf8");
|
|
89610
|
+
if (JSON.parse(cur).pid === process.pid) unlinkSync4(lockPath);
|
|
89303
89611
|
} catch {
|
|
89304
89612
|
}
|
|
89305
89613
|
await new Promise(
|
|
@@ -89659,6 +89967,7 @@ function openInBrowser(url2) {
|
|
|
89659
89967
|
// src/cli.ts
|
|
89660
89968
|
init_paths();
|
|
89661
89969
|
init_checkout_root();
|
|
89970
|
+
init_lock();
|
|
89662
89971
|
|
|
89663
89972
|
// src/cli-args.ts
|
|
89664
89973
|
var BURST_VALUE_FLAGS = /* @__PURE__ */ new Set(["--limit", "--hops", "--max-hops"]);
|
|
@@ -89861,7 +90170,7 @@ import { spawn as spawn4 } from "node:child_process";
|
|
|
89861
90170
|
import { createInterface } from "node:readline";
|
|
89862
90171
|
|
|
89863
90172
|
// src/codex-hooks.ts
|
|
89864
|
-
import { existsSync as existsSync34, mkdirSync as mkdirSync9, readFileSync as
|
|
90173
|
+
import { existsSync as existsSync34, mkdirSync as mkdirSync9, readFileSync as readFileSync36, writeFileSync as writeFileSync26 } from "node:fs";
|
|
89865
90174
|
import { homedir as homedir7 } from "node:os";
|
|
89866
90175
|
import { join as join42 } from "node:path";
|
|
89867
90176
|
|
|
@@ -89887,15 +90196,24 @@ function buildCodexHooksToml(port, options) {
|
|
|
89887
90196
|
};
|
|
89888
90197
|
if (!Number.isInteger(port) || port < 1 || port > 65535) throw new Error("Invalid hook port");
|
|
89889
90198
|
const command = (platform === "win32" ? "& " : "") + quote(options.nodePath) + " " + quote(options.relayPath) + " " + port;
|
|
89890
|
-
const
|
|
89891
|
-
|
|
90199
|
+
const status = {
|
|
90200
|
+
SessionStart: "errata: loading workspace priors",
|
|
90201
|
+
UserPromptSubmit: "errata: checking workspace priors",
|
|
90202
|
+
PreToolUse: "errata: checking relevant priors",
|
|
90203
|
+
PostToolUse: "errata: capturing feedback and checking priors",
|
|
90204
|
+
Stop: "errata: capturing session feedback"
|
|
90205
|
+
};
|
|
90206
|
+
const handlers = Object.keys(status).map(
|
|
90207
|
+
(event) => "[[hooks." + event + "]]\n" + (["UserPromptSubmit", "Stop"].includes(event) ? "" : 'matcher = ".*"\n') + "\n[[hooks." + event + '.hooks]]\ntype = "command"\ncommand = ' + JSON.stringify(command) + "\nstatusMessage = " + JSON.stringify(status[event]) + "\ntimeout = 10\n" + (event === "Stop" ? "" : "additionalContextLimit = 5000\n")
|
|
89892
90208
|
);
|
|
89893
90209
|
return CODEX_HOOKS_BEGIN + "\n" + handlers.join("\n") + CODEX_HOOKS_END + "\n";
|
|
89894
90210
|
}
|
|
89895
90211
|
|
|
89896
90212
|
// src/codex-hook-relay.ts
|
|
89897
90213
|
var CODEX_RELAY_SOURCE = String.raw`// errata-managed: regenerated by errata install-hooks codex
|
|
89898
|
-
import { readFileSync } from 'node:fs';
|
|
90214
|
+
import { readFileSync, statSync } from 'node:fs';
|
|
90215
|
+
import { join } from 'node:path';
|
|
90216
|
+
const workspaceRoot = null;
|
|
89899
90217
|
|
|
89900
90218
|
try {
|
|
89901
90219
|
const payload = JSON.parse(readFileSync(0, 'utf8') || '{}');
|
|
@@ -89913,13 +90231,15 @@ try {
|
|
|
89913
90231
|
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
89914
90232
|
body: JSON.stringify(payload), signal: AbortSignal.timeout(2000),
|
|
89915
90233
|
});
|
|
89916
|
-
if (!response.ok
|
|
90234
|
+
if (!response.ok) return false;
|
|
90235
|
+
if (!relay) return true;
|
|
89917
90236
|
const result = await response.json();
|
|
89918
90237
|
const context = result.hookSpecificOutput?.additionalContext;
|
|
89919
90238
|
if (typeof context === 'string' && context.trim()) contexts.push(context);
|
|
89920
|
-
//
|
|
90239
|
+
// Codex exposes systemMessage to the UI/event stream; styling is host-owned.
|
|
89921
90240
|
if (typeof result.systemMessage === 'string' && result.systemMessage.trim()) messages.push(result.systemMessage);
|
|
89922
|
-
|
|
90241
|
+
return true;
|
|
90242
|
+
} catch { return false; /* An unavailable daemon must never block the agent. */ }
|
|
89923
90243
|
};
|
|
89924
90244
|
if (event === 'PreToolUse' || event === 'PostToolUse') await post('hook', true);
|
|
89925
90245
|
// Stop sees the final assistant message, including turns with no tools.
|
|
@@ -89927,7 +90247,23 @@ try {
|
|
|
89927
90247
|
if (['SessionStart', 'UserPromptSubmit', 'PostToolUse'].includes(event)) {
|
|
89928
90248
|
// Run after capture, so changes already rendered by the daemon arrive now.
|
|
89929
90249
|
// Background extraction finishing later arrives at the next tool boundary.
|
|
89930
|
-
await post('context-inject', true);
|
|
90250
|
+
const available = await post('context-inject', true);
|
|
90251
|
+
// Startup/resume/compaction must not depend on the daemon's busy event loop.
|
|
90252
|
+
// Read only the installer's resolved workspace, never a caller-supplied path
|
|
90253
|
+
// or tracked AGENTS.md. SessionStart already re-injects unconditionally;
|
|
90254
|
+
// prompt/tool refreshes retain daemon hash deduplication (no repeated copies).
|
|
90255
|
+
if (!available && event === 'SessionStart' && workspaceRoot) {
|
|
90256
|
+
try {
|
|
90257
|
+
const path = join(workspaceRoot, '.errata', 'context.md');
|
|
90258
|
+
if (statSync(path).size <= 128 * 1024) {
|
|
90259
|
+
const body = readFileSync(path, 'utf8').trim();
|
|
90260
|
+
if (body) {
|
|
90261
|
+
contexts.push('Errata loaded the maintained local workspace context while the daemon response was unavailable. This block REPLACES any earlier errata context block in this conversation. It is the last saved snapshot; live updates resume when the daemon responds.\n\n' + body);
|
|
90262
|
+
if (!/^(0|off|false|no)$/i.test((process.env.ERRATA_RECALL_CARD || '').trim())) messages.push('⚡ errata · saved workspace priors loaded');
|
|
90263
|
+
}
|
|
90264
|
+
}
|
|
90265
|
+
} catch { /* No saved context is honest; never substitute another project. */ }
|
|
90266
|
+
}
|
|
89931
90267
|
}
|
|
89932
90268
|
if (contexts.length || messages.length) {
|
|
89933
90269
|
process.stdout.write(JSON.stringify({
|
|
@@ -89939,8 +90275,12 @@ try {
|
|
|
89939
90275
|
}
|
|
89940
90276
|
} catch { /* Invalid input is also fail-open. */ }
|
|
89941
90277
|
`;
|
|
90278
|
+
function buildCodexRelaySource(workspaceRoot) {
|
|
90279
|
+
return CODEX_RELAY_SOURCE.replace("const workspaceRoot = null;", () => `const workspaceRoot = ${JSON.stringify(workspaceRoot)};`);
|
|
90280
|
+
}
|
|
89942
90281
|
|
|
89943
90282
|
// src/codex-hooks.ts
|
|
90283
|
+
init_checkout_root();
|
|
89944
90284
|
var CODEX_HOOK_REVIEW_HELP = "Codex desktop: Settings > Hooks, select this project, expand each event and Trust the Errata hook. CLI users can use /hooks.";
|
|
89945
90285
|
function hasCodexConfig(root, codexHome = process.env["CODEX_HOME"] || join42(homedir7(), ".codex")) {
|
|
89946
90286
|
return existsSync34(join42(root, ".codex")) || existsSync34(codexHome);
|
|
@@ -89963,9 +90303,9 @@ function writeCodexHooks(root, port, nodePath = process.execPath) {
|
|
|
89963
90303
|
const file2 = join42(dir, "config.toml");
|
|
89964
90304
|
const relay = join42(dir, "hooks", "errata-relay.mjs");
|
|
89965
90305
|
const block = buildCodexHooksToml(port, { nodePath, relayPath: relay });
|
|
89966
|
-
const final = replaceCodexHooks(existsSync34(file2) ?
|
|
90306
|
+
const final = replaceCodexHooks(existsSync34(file2) ? readFileSync36(file2, "utf8") : "", block);
|
|
89967
90307
|
mkdirSync9(join42(dir, "hooks"), { recursive: true });
|
|
89968
|
-
writeFileSync26(relay,
|
|
90308
|
+
writeFileSync26(relay, buildCodexRelaySource(checkoutRootOf(root)), "utf8");
|
|
89969
90309
|
writeFileSync26(file2, final, "utf8");
|
|
89970
90310
|
return file2;
|
|
89971
90311
|
}
|
|
@@ -90133,7 +90473,7 @@ function consolidationGapMs(lastPassMs, policy) {
|
|
|
90133
90473
|
}
|
|
90134
90474
|
|
|
90135
90475
|
// src/claude-statusline.ts
|
|
90136
|
-
import { existsSync as existsSync35, mkdirSync as mkdirSync10, readFileSync as
|
|
90476
|
+
import { existsSync as existsSync35, mkdirSync as mkdirSync10, readFileSync as readFileSync37, writeFileSync as writeFileSync27 } from "node:fs";
|
|
90137
90477
|
import { homedir as homedir8 } from "node:os";
|
|
90138
90478
|
import { dirname as dirname13, join as join43 } from "node:path";
|
|
90139
90479
|
var STATUSLINE_RELAY_SOURCE = String.raw`// errata-managed: regenerated by errata init / install-hooks claude
|
|
@@ -90179,7 +90519,7 @@ function ensureUserStatusLine(opts) {
|
|
|
90179
90519
|
let settings = {};
|
|
90180
90520
|
if (existsSync35(settingsPath)) {
|
|
90181
90521
|
try {
|
|
90182
|
-
const parsed = JSON.parse(
|
|
90522
|
+
const parsed = JSON.parse(readFileSync37(settingsPath, "utf8"));
|
|
90183
90523
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return "unreadable";
|
|
90184
90524
|
settings = parsed;
|
|
90185
90525
|
} catch {
|
|
@@ -90189,7 +90529,7 @@ function ensureUserStatusLine(opts) {
|
|
|
90189
90529
|
if (settings["statusLine"] !== void 0 && !isErrataStatusLine(settings["statusLine"])) return "kept-own";
|
|
90190
90530
|
const relay = join43(opts.relayDir, STATUSLINE_RELAY_FILE);
|
|
90191
90531
|
mkdirSync10(opts.relayDir, { recursive: true });
|
|
90192
|
-
if (!existsSync35(relay) ||
|
|
90532
|
+
if (!existsSync35(relay) || readFileSync37(relay, "utf8") !== STATUSLINE_RELAY_SOURCE) {
|
|
90193
90533
|
writeFileSync27(relay, STATUSLINE_RELAY_SOURCE, "utf8");
|
|
90194
90534
|
}
|
|
90195
90535
|
const next = buildStatusLine(opts.port, opts.nodePath ?? process.execPath, relay);
|
|
@@ -90732,6 +91072,9 @@ async function cmdStart() {
|
|
|
90732
91072
|
const lockPath = globalDaemonLock();
|
|
90733
91073
|
const running = isDaemonAlive(lockPath) ? readDaemonLock(lockPath) : null;
|
|
90734
91074
|
const where = profile ? `${profile.name} (${profile.id})` : ROOT;
|
|
91075
|
+
if (!running && daemonLockState(readDaemonLock(lockPath), true) === "unknown") {
|
|
91076
|
+
throw new Error(`Cannot verify the daemon process owning ${lockPath}; leaving it untouched. Run errata doctor to inspect it.`);
|
|
91077
|
+
}
|
|
90735
91078
|
if (running) {
|
|
90736
91079
|
console.log(`errata: workspace registered; attached to the running daemon`);
|
|
90737
91080
|
console.log(` workspace: ${where}`);
|
|
@@ -91790,7 +92133,7 @@ async function cmdReview() {
|
|
|
91790
92133
|
console.log("(review queue empty)");
|
|
91791
92134
|
return;
|
|
91792
92135
|
}
|
|
91793
|
-
const queue = JSON.parse(
|
|
92136
|
+
const queue = JSON.parse(readFileSync38(paths.reviewQueue, "utf8"));
|
|
91794
92137
|
if (queue.length === 0) {
|
|
91795
92138
|
console.log("(review queue empty)");
|
|
91796
92139
|
return;
|
|
@@ -92522,31 +92865,20 @@ async function cmdReport(args2) {
|
|
|
92522
92865
|
console.log(` open: file://${indexPath.replace(/\\/g, "/")}`);
|
|
92523
92866
|
}
|
|
92524
92867
|
async function cmdStop() {
|
|
92525
|
-
const { unlinkSync: unlinkSync4 } = await import("node:fs");
|
|
92526
92868
|
const lockPath = [globalDaemonLock(), workspacePaths(ROOT).daemonLock].find((p) => readDaemonLock(p) !== null);
|
|
92527
92869
|
if (!lockPath) {
|
|
92528
92870
|
console.log(`no daemon lock found \u2014 nothing to stop`);
|
|
92529
92871
|
return;
|
|
92530
92872
|
}
|
|
92531
|
-
const lock = readDaemonLock(lockPath);
|
|
92532
|
-
if (!isProcessAlive(lock.pid)) {
|
|
92533
|
-
try {
|
|
92534
|
-
unlinkSync4(lockPath);
|
|
92535
|
-
console.log(`removed stale lock (pid ${lock.pid} not running)`);
|
|
92536
|
-
} catch {
|
|
92537
|
-
}
|
|
92538
|
-
return;
|
|
92539
|
-
}
|
|
92540
92873
|
try {
|
|
92541
|
-
|
|
92542
|
-
console.log(`sent SIGTERM to daemon
|
|
92874
|
+
const result = stopLockedDaemon(lockPath);
|
|
92875
|
+
if (result === "signaled") console.log(`sent SIGTERM to the verified daemon process`);
|
|
92876
|
+
else if (result === "stale") console.log(`removed stale daemon lock; no process was signaled`);
|
|
92877
|
+
else if (result === "missing") console.log(`no daemon lock found \u2014 nothing to stop`);
|
|
92878
|
+
else throw new Error(`daemon lock ownership is ${result}; no process was signaled and the lock was preserved`);
|
|
92543
92879
|
} catch (err2) {
|
|
92544
|
-
console.warn(`could not
|
|
92545
|
-
|
|
92546
|
-
unlinkSync4(lockPath);
|
|
92547
|
-
console.log(`removed stale lock file`);
|
|
92548
|
-
} catch {
|
|
92549
|
-
}
|
|
92880
|
+
console.warn(`could not stop daemon: ${err2 instanceof Error ? err2.message : err2}`);
|
|
92881
|
+
process.exitCode = 1;
|
|
92550
92882
|
}
|
|
92551
92883
|
}
|
|
92552
92884
|
async function cmdMcp(args2) {
|
|
@@ -92557,9 +92889,9 @@ async function cmdMcp(args2) {
|
|
|
92557
92889
|
await runMcpServer2(ROOT, { toolNameStyle: grokCompatibility ? "bare" : "prefixed" });
|
|
92558
92890
|
}
|
|
92559
92891
|
function selfArgv(sub) {
|
|
92560
|
-
const
|
|
92561
|
-
if (/errata(\.exe)?$/i.test(
|
|
92562
|
-
return { cmd:
|
|
92892
|
+
const self2 = process.execPath;
|
|
92893
|
+
if (/errata(\.exe)?$/i.test(self2)) return { cmd: self2, args: [sub] };
|
|
92894
|
+
return { cmd: self2, args: [...process.execArgv, process.argv[1] ?? "", sub] };
|
|
92563
92895
|
}
|
|
92564
92896
|
function spawnDaemonDetached(options = {}) {
|
|
92565
92897
|
const { cmd: cmd2, args: args2 } = selfArgv("dash");
|
|
@@ -92594,11 +92926,11 @@ function spawnDaemonDetached(options = {}) {
|
|
|
92594
92926
|
}
|
|
92595
92927
|
function ensureSingletonRunning(options = {}) {
|
|
92596
92928
|
try {
|
|
92597
|
-
if (
|
|
92929
|
+
if (daemonLockBlocksStartup(globalDaemonLock())) return true;
|
|
92598
92930
|
spawnDaemonDetached(options);
|
|
92599
92931
|
void (async () => {
|
|
92600
92932
|
if (await waitForDaemon(globalDaemonLock(), 8e3)) return;
|
|
92601
|
-
if (
|
|
92933
|
+
if (daemonLockBlocksStartup(globalDaemonLock())) return;
|
|
92602
92934
|
spawnDaemonDetached(options);
|
|
92603
92935
|
await waitForDaemon(globalDaemonLock(), 8e3);
|
|
92604
92936
|
})();
|
|
@@ -92634,13 +92966,13 @@ async function cmdInstallHooks(args2) {
|
|
|
92634
92966
|
}
|
|
92635
92967
|
}
|
|
92636
92968
|
async function installOpencodePlugin(port) {
|
|
92637
|
-
const { mkdirSync: mkdirSync11, existsSync: existsSync37, readFileSync:
|
|
92969
|
+
const { mkdirSync: mkdirSync11, existsSync: existsSync37, readFileSync: readFileSync39, writeFileSync: writeFileSync28 } = await import("node:fs");
|
|
92638
92970
|
const { join: join45 } = await import("node:path");
|
|
92639
92971
|
const dir = join45(ROOT, ".opencode", "plugin");
|
|
92640
92972
|
if (!existsSync37(dir)) mkdirSync11(dir, { recursive: true });
|
|
92641
92973
|
const file2 = join45(dir, "inerrata.js");
|
|
92642
92974
|
if (existsSync37(file2)) {
|
|
92643
|
-
const head2 =
|
|
92975
|
+
const head2 = readFileSync39(file2, "utf8").split("\n")[0] ?? "";
|
|
92644
92976
|
if (head2.trim() !== OPENCODE_PLUGIN_MARKER) {
|
|
92645
92977
|
console.error(`refusing to overwrite ${file2}: not an errata-managed plugin (line 1 lacks the marker)`);
|
|
92646
92978
|
process.exit(2);
|
|
@@ -92651,7 +92983,7 @@ async function installOpencodePlugin(port) {
|
|
|
92651
92983
|
let cfg = { $schema: "https://opencode.ai/config.json" };
|
|
92652
92984
|
if (existsSync37(cfgFile)) {
|
|
92653
92985
|
try {
|
|
92654
|
-
cfg = JSON.parse(
|
|
92986
|
+
cfg = JSON.parse(readFileSync39(cfgFile, "utf8"));
|
|
92655
92987
|
} catch {
|
|
92656
92988
|
console.error(`refusing to touch invalid JSON at ${cfgFile} \u2014 fix it and re-run`);
|
|
92657
92989
|
process.exit(2);
|
|
@@ -92689,7 +93021,7 @@ function ensureStatusLine(port) {
|
|
|
92689
93021
|
}
|
|
92690
93022
|
}
|
|
92691
93023
|
async function installClaudeHooks(port) {
|
|
92692
|
-
const { mkdirSync: mkdirSync11, existsSync: existsSync37, readFileSync:
|
|
93024
|
+
const { mkdirSync: mkdirSync11, existsSync: existsSync37, readFileSync: readFileSync39, writeFileSync: writeFileSync28 } = await import("node:fs");
|
|
92693
93025
|
const { join: join45 } = await import("node:path");
|
|
92694
93026
|
const dir = join45(ROOT, ".claude");
|
|
92695
93027
|
if (!existsSync37(dir)) mkdirSync11(dir, { recursive: true });
|
|
@@ -92697,7 +93029,7 @@ async function installClaudeHooks(port) {
|
|
|
92697
93029
|
let settings = {};
|
|
92698
93030
|
if (existsSync37(file2)) {
|
|
92699
93031
|
try {
|
|
92700
|
-
settings = JSON.parse(
|
|
93032
|
+
settings = JSON.parse(readFileSync39(file2, "utf8"));
|
|
92701
93033
|
} catch {
|
|
92702
93034
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
92703
93035
|
process.exit(2);
|
|
@@ -92761,7 +93093,7 @@ async function installClaudeHooks(port) {
|
|
|
92761
93093
|
console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
|
|
92762
93094
|
}
|
|
92763
93095
|
async function installClaudeMcpConfig() {
|
|
92764
|
-
const { mkdirSync: mkdirSync11, existsSync: existsSync37, readFileSync:
|
|
93096
|
+
const { mkdirSync: mkdirSync11, existsSync: existsSync37, readFileSync: readFileSync39, writeFileSync: writeFileSync28 } = await import("node:fs");
|
|
92765
93097
|
const { join: join45, dirname: dirname14 } = await import("node:path");
|
|
92766
93098
|
const file2 = join45(ROOT, ".mcp.json");
|
|
92767
93099
|
const dir = dirname14(file2);
|
|
@@ -92769,7 +93101,7 @@ async function installClaudeMcpConfig() {
|
|
|
92769
93101
|
let cfg = {};
|
|
92770
93102
|
if (existsSync37(file2)) {
|
|
92771
93103
|
try {
|
|
92772
|
-
cfg = JSON.parse(
|
|
93104
|
+
cfg = JSON.parse(readFileSync39(file2, "utf8"));
|
|
92773
93105
|
} catch {
|
|
92774
93106
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
92775
93107
|
process.exit(2);
|
|
@@ -92783,7 +93115,7 @@ async function installClaudeMcpConfig() {
|
|
|
92783
93115
|
console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses / show / similar`);
|
|
92784
93116
|
}
|
|
92785
93117
|
async function installCursorMcpConfig() {
|
|
92786
|
-
const { mkdirSync: mkdirSync11, existsSync: existsSync37, readFileSync:
|
|
93118
|
+
const { mkdirSync: mkdirSync11, existsSync: existsSync37, readFileSync: readFileSync39, writeFileSync: writeFileSync28 } = await import("node:fs");
|
|
92787
93119
|
const { join: join45 } = await import("node:path");
|
|
92788
93120
|
const dir = join45(ROOT, ".cursor");
|
|
92789
93121
|
if (!existsSync37(dir)) mkdirSync11(dir, { recursive: true });
|
|
@@ -92791,7 +93123,7 @@ async function installCursorMcpConfig() {
|
|
|
92791
93123
|
let cfg = {};
|
|
92792
93124
|
if (existsSync37(file2)) {
|
|
92793
93125
|
try {
|
|
92794
|
-
cfg = JSON.parse(
|
|
93126
|
+
cfg = JSON.parse(readFileSync39(file2, "utf8"));
|
|
92795
93127
|
} catch {
|
|
92796
93128
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
92797
93129
|
process.exit(2);
|