@inerrata-corporation/errata 2.0.16-dev.3355 → 2.0.16
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 +10 -26
- package/errata.mjs +508 -521
- package/package.json +1 -1
- package/pass-worker.mjs +11 -12
package/errata.mjs
CHANGED
|
@@ -139,7 +139,6 @@ 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",
|
|
143
142
|
/** A signed gateway write target named the destination. */
|
|
144
143
|
"signed-target-public",
|
|
145
144
|
"signed-target-org",
|
|
@@ -960,7 +959,7 @@ function lemma(token) {
|
|
|
960
959
|
}
|
|
961
960
|
return token;
|
|
962
961
|
}
|
|
963
|
-
function tokenize(text,
|
|
962
|
+
function tokenize(text, resolve8) {
|
|
964
963
|
const matches = text.normalize("NFC").toLowerCase().match(TOKEN_RE) ?? [];
|
|
965
964
|
const out2 = /* @__PURE__ */ new Set();
|
|
966
965
|
for (const raw2 of matches) {
|
|
@@ -970,7 +969,7 @@ function tokenize(text, resolve7) {
|
|
|
970
969
|
out2.add(token);
|
|
971
970
|
continue;
|
|
972
971
|
}
|
|
973
|
-
const canonical =
|
|
972
|
+
const canonical = resolve8(token);
|
|
974
973
|
out2.add(canonical ?? lemma(token));
|
|
975
974
|
}
|
|
976
975
|
return [...out2].sort();
|
|
@@ -1081,12 +1080,6 @@ function identityId(input) {
|
|
|
1081
1080
|
}
|
|
1082
1081
|
case "Claim":
|
|
1083
1082
|
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
|
-
});
|
|
1090
1083
|
case "DesignProblem":
|
|
1091
1084
|
return `${DESIGN_PROBLEM_PREFIX}${canonicalClaimId(input.statement.trim())}`.slice(
|
|
1092
1085
|
0,
|
|
@@ -15856,7 +15849,7 @@ var init_edge_rules = __esm({
|
|
|
15856
15849
|
// anchor anything at anything, e.g. at a public `Package`, quietly re-creating
|
|
15857
15850
|
// the code↔collective bridge the membrane exists to prevent.
|
|
15858
15851
|
ANCHORED_AT: {
|
|
15859
|
-
from: ["Problem", "
|
|
15852
|
+
from: ["Problem", "Solution", "RootCause", "Claim"],
|
|
15860
15853
|
to: ["Symbol"]
|
|
15861
15854
|
},
|
|
15862
15855
|
// ── Security spine (v1 taxonomy.ts SECURITY_FORWARD_ONLY commentary) ──
|
|
@@ -15901,7 +15894,7 @@ var init_edge_rules = __esm({
|
|
|
15901
15894
|
// `Component` joined the target set with OM-agent-anchors: an agent-named
|
|
15902
15895
|
// component ("React Router") is the same knowledge→named-unit anchor shape as
|
|
15903
15896
|
// a Tool — the knowledge is ABOUT it, not dependent on it.
|
|
15904
|
-
CONCERNS: { from: ["Problem", "
|
|
15897
|
+
CONCERNS: { from: ["Problem", "Solution", "RootCause", "Claim", "Pattern"], to: ["Tool", "Component"] },
|
|
15905
15898
|
OPERATES_ON: { from: ["Algorithm"], to: ["DataStructure"] },
|
|
15906
15899
|
INVOLVES: { from: ["Problem", "Solution"], to: ["DataStructure"] },
|
|
15907
15900
|
// ── Taxonomy (Track 4 Stream C: MITRE CWE `ChildOf` → `Weakness —IS_A→ Weakness`) ──
|
|
@@ -17574,7 +17567,7 @@ var init_agents_md = __esm({
|
|
|
17574
17567
|
});
|
|
17575
17568
|
|
|
17576
17569
|
// ../../packages/context-writer/src/context-file.ts
|
|
17577
|
-
import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
17570
|
+
import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, renameSync, unlinkSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
17578
17571
|
import { dirname as dirname2, join } from "node:path";
|
|
17579
17572
|
function contextFilePath(root) {
|
|
17580
17573
|
return join(root, ".errata", "context.md");
|
|
@@ -17584,7 +17577,13 @@ function writeContextFile(root, body2) {
|
|
|
17584
17577
|
mkdirSync(dirname2(path2), { recursive: true });
|
|
17585
17578
|
const text = `${body2.trim()}
|
|
17586
17579
|
`;
|
|
17587
|
-
|
|
17580
|
+
const temp = `${path2}.${process.pid}.tmp`;
|
|
17581
|
+
try {
|
|
17582
|
+
writeFileSync2(temp, text, { encoding: "utf8", mode: 384 });
|
|
17583
|
+
renameSync(temp, path2);
|
|
17584
|
+
} finally {
|
|
17585
|
+
if (existsSync2(temp)) unlinkSync(temp);
|
|
17586
|
+
}
|
|
17588
17587
|
return contextHash(text);
|
|
17589
17588
|
}
|
|
17590
17589
|
function contextHash(body2) {
|
|
@@ -18275,8 +18274,7 @@ CREATE INDEX IF NOT EXISTS nodes_live ON nodes(label, valid_to);
|
|
|
18275
18274
|
-- its table row. Partial, so it maintains a few thousand rows instead of adding
|
|
18276
18275
|
-- a write to every node write. Its label list is FINGERPRINT_INDEXED_LABELS.
|
|
18277
18276
|
DROP INDEX IF EXISTS nodes_live_fingerprint;
|
|
18278
|
-
|
|
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');
|
|
18277
|
+
CREATE INDEX IF NOT EXISTS nodes_instance_fingerprint ON nodes(label, last_updated_at, last_reinforced_at_seq, created_at_seq) WHERE valid_to IS NULL AND label IN ('Problem','Solution','RootCause');
|
|
18280
18278
|
CREATE INDEX IF NOT EXISTS nodes_logical ON nodes(logical_id, version);
|
|
18281
18279
|
CREATE INDEX IF NOT EXISTS edges_live ON edges(valid_to);
|
|
18282
18280
|
-- Expression index on the per-node relPath (stored in attrs_json) so the
|
|
@@ -18290,7 +18288,7 @@ CREATE INDEX IF NOT EXISTS nodes_live_description ON nodes(description, label) W
|
|
|
18290
18288
|
-- every edited file of every turn, and a scan parses every Problem's attrs.
|
|
18291
18289
|
CREATE INDEX IF NOT EXISTS nodes_anchor_hint_path ON nodes(json_extract(attrs_json, '$.anchorHint.path')) WHERE valid_to IS NULL;
|
|
18292
18290
|
`;
|
|
18293
|
-
FINGERPRINT_INDEXED_LABELS = ["Problem", "
|
|
18291
|
+
FINGERPRINT_INDEXED_LABELS = ["Problem", "Solution", "RootCause"];
|
|
18294
18292
|
SqliteGraphStore = class {
|
|
18295
18293
|
db;
|
|
18296
18294
|
// Typed edge lookups build their SQL from the number of types asked for, and
|
|
@@ -18968,8 +18966,8 @@ CREATE INDEX IF NOT EXISTS nodes_anchor_hint_path ON nodes(json_extract(attrs_js
|
|
|
18968
18966
|
const r2 = this.db.prepare(
|
|
18969
18967
|
`SELECT COUNT(*) AS n, MAX(last_updated_at) AS t,
|
|
18970
18968
|
MAX(COALESCE(last_reinforced_at_seq, created_at_seq, 0)) AS s
|
|
18971
|
-
FROM nodes INDEXED BY
|
|
18972
|
-
WHERE valid_to IS NULL AND label IN ('Problem','
|
|
18969
|
+
FROM nodes INDEXED BY nodes_instance_fingerprint
|
|
18970
|
+
WHERE valid_to IS NULL AND label IN ('Problem','Solution','RootCause')`
|
|
18973
18971
|
).get();
|
|
18974
18972
|
return `${r2.n}:${r2.t ?? 0}:${r2.s ?? 0}`;
|
|
18975
18973
|
}
|
|
@@ -20265,7 +20263,7 @@ function mergeContextEdge(store, from, to, type, ts) {
|
|
|
20265
20263
|
function deriveContextFromAnchors(store, problemId, ts, pkgIndex) {
|
|
20266
20264
|
const report = { languages: [], packages: [] };
|
|
20267
20265
|
const p = store.getNode(problemId);
|
|
20268
|
-
if (!p || p.label !== "Problem"
|
|
20266
|
+
if (!p || p.label !== "Problem") return report;
|
|
20269
20267
|
const files = store.outEdges(problemId, ["ANCHORED_AT"]).map((e) => store.getNode(e.to)).filter((n) => !!n && n.label === "File");
|
|
20270
20268
|
if (files.length === 0) return report;
|
|
20271
20269
|
const idx = pkgIndex ?? buildPackageIndex(store);
|
|
@@ -20903,81 +20901,6 @@ function ingestDesignProblem(store, flag, opts) {
|
|
|
20903
20901
|
...reopenedFromRegression ? { reopenedFromRegression } : {}
|
|
20904
20902
|
};
|
|
20905
20903
|
}
|
|
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
|
-
}
|
|
20981
20904
|
function canonicalizePatternText(name2) {
|
|
20982
20905
|
const stripped = name2.replace(/^\s*pattern(?:\s*[×x]\s*\d+)?\s*(?:\(exemplar\))?\s*[:—–-]\s*/i, "").replace(/\s+/g, " ").trim();
|
|
20983
20906
|
return stripped.length > 0 ? stripped : name2.replace(/\s+/g, " ").trim();
|
|
@@ -21288,7 +21211,6 @@ function findReusableSolution(store, fixText) {
|
|
|
21288
21211
|
const key = solutionTextKey(fixText);
|
|
21289
21212
|
if (!key) return null;
|
|
21290
21213
|
for (const s of store.findNodesByLabel("Solution")) {
|
|
21291
|
-
if (s.attrs["privateFinding"]) continue;
|
|
21292
21214
|
if (s.validTo != null) continue;
|
|
21293
21215
|
if (isAutoMinted(s)) continue;
|
|
21294
21216
|
if (solutionTextKey(s.description ?? "") === key) return s;
|
|
@@ -21313,7 +21235,7 @@ function priorsForFile(store, relPath) {
|
|
|
21313
21235
|
for (const e of store.inEdges(file2.id, ["ANCHORED_AT"])) {
|
|
21314
21236
|
const n = store.getNode(e.from);
|
|
21315
21237
|
if (!n) continue;
|
|
21316
|
-
if (n.label === "Problem"
|
|
21238
|
+
if (n.label === "Problem") {
|
|
21317
21239
|
if (seenProblem.has(n.id)) continue;
|
|
21318
21240
|
seenProblem.add(n.id);
|
|
21319
21241
|
if (!n.attrs["resolvedAt"]) {
|
|
@@ -21383,8 +21305,7 @@ function solutionForProblem(store, problemId) {
|
|
|
21383
21305
|
}
|
|
21384
21306
|
function anchorProblemToWorkingFile(store, problemId, relPath, workspaceId2, ts, provenance = "edited", opts = {}) {
|
|
21385
21307
|
const p = store.getNode(problemId);
|
|
21386
|
-
if (!p || p.label !== "Problem"
|
|
21387
|
-
if (p.label === "Vulnerability" && provenance !== "witnessed") return false;
|
|
21308
|
+
if (!p || p.label !== "Problem") return false;
|
|
21388
21309
|
if (!isAnchorableCodePath(relPath)) return false;
|
|
21389
21310
|
const file2 = resolveFileNode(store, relPath, workspaceId2);
|
|
21390
21311
|
if (!file2) return false;
|
|
@@ -21563,22 +21484,18 @@ function resolveDesignProblemById(store, id, fixNote, t) {
|
|
|
21563
21484
|
}
|
|
21564
21485
|
function closeDesignProblem(store, problemId, fixNote, t) {
|
|
21565
21486
|
const p = store.getNode(problemId);
|
|
21566
|
-
if (!p || p.label !== "Problem"
|
|
21487
|
+
if (!p || p.label !== "Problem") return false;
|
|
21567
21488
|
if (p.attrs["resolvedAs"]) return false;
|
|
21568
21489
|
if (fixNote?.trim() && !isFragmentFixNote(fixNote)) {
|
|
21569
21490
|
const sols = store.outEdges(problemId, ["SOLVED_BY"]).map((e) => store.getNode(e.to)).filter((n) => n !== null);
|
|
21570
21491
|
if (sols.every((s) => isAutoMinted(s))) {
|
|
21571
|
-
const reuse =
|
|
21492
|
+
const reuse = findReusableSolution(store, fixNote);
|
|
21572
21493
|
if (reuse) {
|
|
21573
21494
|
mergeEdge(store, problemId, reuse.id, "SOLVED_BY", t);
|
|
21574
21495
|
} else {
|
|
21575
21496
|
const solId = `dfix_${digest({ problemId, fix: fixNote })}`.slice(0, 56);
|
|
21576
21497
|
store.mergeNode(
|
|
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
|
-
})
|
|
21498
|
+
buildNode(store, solId, "Solution", fixNote.trim(), t, { source: "convo", provisional: false })
|
|
21582
21499
|
);
|
|
21583
21500
|
mergeEdge(store, problemId, solId, "SOLVED_BY", t);
|
|
21584
21501
|
}
|
|
@@ -21592,7 +21509,6 @@ function closeDesignProblem(store, problemId, fixNote, t) {
|
|
|
21592
21509
|
// mints no Solution, and a legacy placeholder beside it reads as
|
|
21593
21510
|
// all-heuristic either way.
|
|
21594
21511
|
attrs: { ...p.attrs, provisional: false, resolvedAt: t, resolutionWitnessed: true },
|
|
21595
|
-
...reinforcedSeqAttrs(store, p.label),
|
|
21596
21512
|
lastUpdatedAt: t
|
|
21597
21513
|
});
|
|
21598
21514
|
return true;
|
|
@@ -23944,7 +23860,7 @@ function detectLocalCommunities(store, opts = {}) {
|
|
|
23944
23860
|
const ids = /* @__PURE__ */ new Set();
|
|
23945
23861
|
for (const label of JOINT_COMMUNITY_LABELS) {
|
|
23946
23862
|
for (const n of store.findNodesByLabel(label)) {
|
|
23947
|
-
if (n.attrs["resolvedAs"] === PROBLEM_RESOLUTION.FALSE_POSITIVE) continue;
|
|
23863
|
+
if (label === "Problem" && n.attrs["resolvedAs"] === PROBLEM_RESOLUTION.FALSE_POSITIVE) continue;
|
|
23948
23864
|
ids.add(n.id);
|
|
23949
23865
|
}
|
|
23950
23866
|
}
|
|
@@ -24081,7 +23997,6 @@ var init_community2 = __esm({
|
|
|
24081
23997
|
init_src4();
|
|
24082
23998
|
JOINT_COMMUNITY_LABELS = [
|
|
24083
23999
|
"Problem",
|
|
24084
|
-
"Vulnerability",
|
|
24085
24000
|
"Solution",
|
|
24086
24001
|
"RootCause",
|
|
24087
24002
|
"Pattern"
|
|
@@ -24943,7 +24858,6 @@ __export(src_exports2, {
|
|
|
24943
24858
|
induceAbstractions: () => induceAbstractions,
|
|
24944
24859
|
induceTriage: () => induceTriage,
|
|
24945
24860
|
ingestDesignProblem: () => ingestDesignProblem,
|
|
24946
|
-
ingestWitnessedVulnerability: () => ingestWitnessedVulnerability,
|
|
24947
24861
|
isConstraintProblem: () => isConstraintProblem,
|
|
24948
24862
|
isFragmentFixNote: () => isFragmentFixNote,
|
|
24949
24863
|
isPlaceholderStatement: () => isPlaceholderStatement,
|
|
@@ -24991,7 +24905,6 @@ __export(src_exports2, {
|
|
|
24991
24905
|
recordMisreadPrior: () => recordMisreadPrior,
|
|
24992
24906
|
recordRenderLedger: () => recordRenderLedger,
|
|
24993
24907
|
recordTriageObservation: () => recordTriageObservation,
|
|
24994
|
-
recordVulnerabilityCause: () => recordVulnerabilityCause,
|
|
24995
24908
|
reinforceSameAnchorProblem: () => reinforceSameAnchorProblem,
|
|
24996
24909
|
relateClaims: () => relateClaims,
|
|
24997
24910
|
reopenAutoClosedProblems: () => reopenAutoClosedProblems,
|
|
@@ -25061,7 +24974,7 @@ function isPassiveInjectable(node2, atCommit) {
|
|
|
25061
24974
|
return false;
|
|
25062
24975
|
}
|
|
25063
24976
|
function buildSnapshot(opts) {
|
|
25064
|
-
const problems =
|
|
24977
|
+
const problems = opts.store.findNodesByLabel("Problem").filter((p) => p.attrs["mergedInto"] === void 0 && historyReadPolicy(p, { mode: "passive", atCommit: opts.atCommit }).allow);
|
|
25065
24978
|
const stillOpen = problems.filter((p) => p.attrs["resolvedAt"] == null);
|
|
25066
24979
|
const allProblems = stillOpen.filter((p) => !isConstraintProblem(p));
|
|
25067
24980
|
allProblems.sort((a, b) => b.lastUpdatedAt - a.lastUpdatedAt);
|
|
@@ -25216,11 +25129,11 @@ function sliceForFile(store, relPath, atCommit) {
|
|
|
25216
25129
|
const priors = fp ? {
|
|
25217
25130
|
openProblems: fp.openProblems.slice(0, 3).map((p) => ({
|
|
25218
25131
|
id: p.id,
|
|
25219
|
-
description: p.
|
|
25132
|
+
description: p.description,
|
|
25220
25133
|
...typeof p.attrs["fixCandidateFile"] === "string" ? { fixCandidateFile: p.attrs["fixCandidateFile"] } : {}
|
|
25221
25134
|
})),
|
|
25222
25135
|
constraints: fp.constraints.slice(0, 2).map((c) => ({ id: c.id, description: c.description })),
|
|
25223
|
-
resolvedProblems: fp.resolvedProblems.slice(0, 3).map((p) => ({ id: p.id, description: p.
|
|
25136
|
+
resolvedProblems: fp.resolvedProblems.slice(0, 3).map((p) => ({ id: p.id, description: p.description })),
|
|
25224
25137
|
related: fp.related.slice(0, 4).map((n) => ({ id: n.id, label: n.label, description: n.description })),
|
|
25225
25138
|
solutionsByProblem: Object.fromEntries(
|
|
25226
25139
|
[...fp.openProblems.slice(0, 3), ...fp.resolvedProblems.slice(0, 3)].map((p) => [
|
|
@@ -25338,8 +25251,7 @@ function renderSnapshot(s) {
|
|
|
25338
25251
|
if (s.recentProblems.length > 0) {
|
|
25339
25252
|
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):_");
|
|
25340
25253
|
for (const r of s.recentProblems) {
|
|
25341
|
-
|
|
25342
|
-
lines.push(`- **${badge}${r.node.description}** \u2014 \`${r.node.id}\`${tagOf(r.node)}`);
|
|
25254
|
+
lines.push(`- **${r.node.description}** \u2014 \`${r.node.id}\`${tagOf(r.node)}`);
|
|
25343
25255
|
const hits = r.node.cumulativeHits ?? 0;
|
|
25344
25256
|
const surprise = (r.node.cumulativeSurprise ?? 0).toFixed(2);
|
|
25345
25257
|
lines.push(` - observed ${hits}\xD7 \xB7 cumulativeSurprise ${surprise}`);
|
|
@@ -25380,8 +25292,7 @@ function renderSnapshot(s) {
|
|
|
25380
25292
|
if (s.recentResolved.length > 0) {
|
|
25381
25293
|
lines.push("_Recently resolved \u2014 solved here; jumping-off points, not live defects:_");
|
|
25382
25294
|
for (const r of s.recentResolved) {
|
|
25383
|
-
|
|
25384
|
-
lines.push(`- \u2713 **${badge}${r.node.description}** \u2014 \`${r.node.id}\`${tagOf(r.node)}`);
|
|
25295
|
+
lines.push(`- \u2713 **${r.node.description}** \u2014 \`${r.node.id}\`${tagOf(r.node)}`);
|
|
25385
25296
|
if (r.solution) {
|
|
25386
25297
|
lines.push(` - solved: ${r.solution.description.slice(0, 160)} \u2014 \`${r.solution.id}\`${tagOf(r.solution)}`);
|
|
25387
25298
|
}
|
|
@@ -27241,8 +27152,8 @@ var init_config = __esm({
|
|
|
27241
27152
|
"use strict";
|
|
27242
27153
|
init_paths();
|
|
27243
27154
|
LEGACY_CLOUD_URL = "https://inerrata-gateway.onrender.com";
|
|
27244
|
-
DEFAULT_CLOUD_URL = true ? "https://
|
|
27245
|
-
DEFAULT_UPDATE_CHANNEL =
|
|
27155
|
+
DEFAULT_CLOUD_URL = true ? "https://inerrata.dev" : DEV_CLOUD_URL;
|
|
27156
|
+
DEFAULT_UPDATE_CHANNEL = true ? "latest" : "dev";
|
|
27246
27157
|
}
|
|
27247
27158
|
});
|
|
27248
27159
|
|
|
@@ -31802,7 +31713,7 @@ var init_src8 = __esm({
|
|
|
31802
31713
|
|
|
31803
31714
|
// src/agent-signals.ts
|
|
31804
31715
|
function buildFileRecallInstruction(referent = "\u2026") {
|
|
31805
|
-
return `Touching one? paste its token: ${TAG_EXAMPLE.fix(referent)} resolved \xB7 ${TAG_EXAMPLE.prior(referent)} leaned-on \xB7 ${TAG_EXAMPLE.problem()} new
|
|
31716
|
+
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.`;
|
|
31806
31717
|
}
|
|
31807
31718
|
function triageBullet(ref) {
|
|
31808
31719
|
return [
|
|
@@ -31838,15 +31749,15 @@ function attemptBullet() {
|
|
|
31838
31749
|
].join("\n");
|
|
31839
31750
|
}
|
|
31840
31751
|
function buildAgentInstruction(opts = {}) {
|
|
31841
|
-
const signals = opts.signals ?? ["prior", "problem", "
|
|
31752
|
+
const signals = opts.signals ?? ["prior", "problem", "domain", "fix", "constraint", "triage", "attempt", "link"];
|
|
31842
31753
|
const ref = opts.referent ?? "its-handle";
|
|
31843
31754
|
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);
|
|
31844
|
-
const head2 =
|
|
31845
|
-
const tail = "
|
|
31755
|
+
const head2 = `We tag the priors we show you with a short handle like [${opts.handleExample ?? "chokidar-glob"}]. Untagged prose is silently lost. Put each tag inline in prose (no fences or backticks). Requested errata-* answer blocks are the exception: keep their fences in your turn-final reply. Tag everything, we filter downstream:`;
|
|
31756
|
+
const tail = "Mid-turn text (between tool calls) can be dropped by the harness \u2014 RESTATE every tag in your turn-final message; the final message is what reliably survives \u2014 EXCEPT one already shown above with an id: that is captured, so cite `[its-handle]` rather than retyping it (drift mints a duplicate).";
|
|
31846
31757
|
return [
|
|
31847
31758
|
head2,
|
|
31848
31759
|
...signals.map(
|
|
31849
|
-
(s) => s === "triage" ? triageBullet(ref) : s === "
|
|
31760
|
+
(s) => s === "triage" ? triageBullet(ref) : s === "attempt" ? attemptBullet() : s === "link" ? linkBullet(ref) : s === "verdict" ? verdictBullet(ref) : ` \u2022 ${GLOSS[s]} \u2192 ${token(s)}`
|
|
31850
31761
|
),
|
|
31851
31762
|
tail
|
|
31852
31763
|
].join("\n");
|
|
@@ -31858,9 +31769,6 @@ var init_agent_signals = __esm({
|
|
|
31858
31769
|
TAG_EXAMPLE = {
|
|
31859
31770
|
prior: (ref) => `([${ref}])`,
|
|
31860
31771
|
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]`,
|
|
31864
31772
|
fix: (ref) => `(fix:[${ref}])`,
|
|
31865
31773
|
// CONSTRAINT — the native capture path for a DIFFUSE problem (a constraint/tension/
|
|
31866
31774
|
// conflict that shaped a decision). Free text, attaches to the decision sentence the
|
|
@@ -31881,7 +31789,7 @@ var init_agent_signals = __esm({
|
|
|
31881
31789
|
// tags never need one — the id is for diagnoses that unfold over distance.
|
|
31882
31790
|
problemThread: () => `[!#slug one line on what's wrong]`,
|
|
31883
31791
|
causeThread: () => `(cause:#slug the mechanism)`,
|
|
31884
|
-
fixThread: (
|
|
31792
|
+
fixThread: () => `(fix:#slug what you changed)`,
|
|
31885
31793
|
// ATTEMPT arc — what's being tried and what didn't work. A failed attempt is a
|
|
31886
31794
|
// witnessed NEGATIVE result: it saves the next agent the same dead end.
|
|
31887
31795
|
tried: () => `(tried: the approach you're attempting)`,
|
|
@@ -31923,9 +31831,8 @@ var init_agent_signals = __esm({
|
|
|
31923
31831
|
// problems, and narrated them as progress (a pick-best-before-scoring bug lost).
|
|
31924
31832
|
// Every example here was diagnosis-framed, so nothing contradicted that sorting.
|
|
31925
31833
|
// Kept to 29 chars: the instruction sits at the 2600 passive-budget ceiling.
|
|
31926
|
-
problem: "any bug or
|
|
31927
|
-
|
|
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",
|
|
31834
|
+
problem: "a problem you notice or report \u2014 any bug, finding, or thing wrong, even in code you just wrote; about specific code? name the file: [!what's wrong @ src/file.ts:42]",
|
|
31835
|
+
fix: "your edit fixed a PROBLEM we showed you; for one you flagged yourself: (fix: what you changed) \u2014 a fix resolves a stated problem, completing routine work is not a fix",
|
|
31929
31836
|
constraint: "a design decision forced by conflicting requirements or constraints \u2014 tag the tension, especially when your fix makes it 'only look' resolved",
|
|
31930
31837
|
triage: "you diagnosed a cause \u2014 fold the chain into the flag with <- (caused-by), deepest sure mechanism rightmost",
|
|
31931
31838
|
attempt: "attempting an approach / an attempt failed \u2014 a failed attempt is knowledge, it rules out a path",
|
|
@@ -31947,7 +31854,7 @@ var init_agent_signals = __esm({
|
|
|
31947
31854
|
// Sim note (2026-08-02 shrink): domain emission held 4/4 with just the trigger
|
|
31948
31855
|
// clause; the pattern convergence hook now rides here too (it fell 0/4 when it
|
|
31949
31856
|
// only appeared in the link bullet's tail).
|
|
31950
|
-
domain: "no single file
|
|
31857
|
+
domain: "a problem with no single file \u2014 name the area it's about (Title Case). Also name the general shape it instantiates: (pattern: the shape) \u2014 needs no code anchor, and two agents naming the same shape converge on one node",
|
|
31951
31858
|
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",
|
|
31952
31859
|
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"
|
|
31953
31860
|
};
|
|
@@ -32169,7 +32076,11 @@ function contextCard(store, snapshot) {
|
|
|
32169
32076
|
return deliveredCard(store, intent ? `${count} for \u201C${clipIntent(intent)}\u201D` : `${count} in context`, delivered);
|
|
32170
32077
|
}
|
|
32171
32078
|
function writeContextCard(root, hash2, card) {
|
|
32172
|
-
writeFileSync6(join7(root, ".errata", CONTEXT_CARD_FILE), JSON.stringify({
|
|
32079
|
+
writeFileSync6(join7(root, ".errata", CONTEXT_CARD_FILE), JSON.stringify({
|
|
32080
|
+
hash: hash2,
|
|
32081
|
+
card,
|
|
32082
|
+
line: card && recallCardEnabled() ? renderRecallLine(card) : null
|
|
32083
|
+
}));
|
|
32173
32084
|
}
|
|
32174
32085
|
function readContextCard(root, hash2) {
|
|
32175
32086
|
const path2 = join7(root, ".errata", CONTEXT_CARD_FILE);
|
|
@@ -32184,7 +32095,7 @@ function readContextCard(root, hash2) {
|
|
|
32184
32095
|
function openProblems(store, now = Date.now()) {
|
|
32185
32096
|
const hit = openProblemsCache.get(store);
|
|
32186
32097
|
if (hit && now - hit.at < OPEN_PROBLEMS_TTL_MS) return hit.nodes;
|
|
32187
|
-
const nodes =
|
|
32098
|
+
const nodes = store.findNodesByLabel("Problem").filter((p) => live(p) && !p.attrs["resolvedAt"] && p.attrs["mergedInto"] === void 0 && !isConstraintProblem(p));
|
|
32188
32099
|
openProblemsCache.set(store, { at: now, nodes });
|
|
32189
32100
|
return nodes;
|
|
32190
32101
|
}
|
|
@@ -32634,7 +32545,7 @@ var init_process_identity = __esm({
|
|
|
32634
32545
|
});
|
|
32635
32546
|
|
|
32636
32547
|
// src/lock.ts
|
|
32637
|
-
import { existsSync as existsSync12, readFileSync as readFileSync11, unlinkSync } from "node:fs";
|
|
32548
|
+
import { existsSync as existsSync12, readFileSync as readFileSync11, unlinkSync as unlinkSync2 } from "node:fs";
|
|
32638
32549
|
function daemonLockPayload(lock) {
|
|
32639
32550
|
return JSON.stringify({
|
|
32640
32551
|
pid: lock.pid,
|
|
@@ -32715,7 +32626,7 @@ function stopLockedDaemon(lockPath) {
|
|
|
32715
32626
|
}
|
|
32716
32627
|
if (state === "unknown") return "unknown";
|
|
32717
32628
|
if (state === "stale") {
|
|
32718
|
-
|
|
32629
|
+
unlinkSync2(lockPath);
|
|
32719
32630
|
return "stale";
|
|
32720
32631
|
}
|
|
32721
32632
|
process.kill(lock.pid, "SIGTERM");
|
|
@@ -36116,13 +36027,13 @@ async function Module2(moduleArg = {}) {
|
|
|
36116
36027
|
}
|
|
36117
36028
|
readAsync = /* @__PURE__ */ __name(async (url2) => {
|
|
36118
36029
|
if (isFileURI(url2)) {
|
|
36119
|
-
return new Promise((
|
|
36030
|
+
return new Promise((resolve8, reject) => {
|
|
36120
36031
|
var xhr = new XMLHttpRequest();
|
|
36121
36032
|
xhr.open("GET", url2, true);
|
|
36122
36033
|
xhr.responseType = "arraybuffer";
|
|
36123
36034
|
xhr.onload = () => {
|
|
36124
36035
|
if (xhr.status == 200 || xhr.status == 0 && xhr.response) {
|
|
36125
|
-
|
|
36036
|
+
resolve8(xhr.response);
|
|
36126
36037
|
return;
|
|
36127
36038
|
}
|
|
36128
36039
|
reject(xhr.status);
|
|
@@ -36318,9 +36229,9 @@ async function Module2(moduleArg = {}) {
|
|
|
36318
36229
|
__name(receiveInstantiationResult, "receiveInstantiationResult");
|
|
36319
36230
|
var info2 = getWasmImports();
|
|
36320
36231
|
if (Module["instantiateWasm"]) {
|
|
36321
|
-
return new Promise((
|
|
36232
|
+
return new Promise((resolve8, reject) => {
|
|
36322
36233
|
Module["instantiateWasm"](info2, (mod, inst) => {
|
|
36323
|
-
|
|
36234
|
+
resolve8(receiveInstance(mod, inst));
|
|
36324
36235
|
});
|
|
36325
36236
|
});
|
|
36326
36237
|
}
|
|
@@ -37651,8 +37562,8 @@ async function Module2(moduleArg = {}) {
|
|
|
37651
37562
|
if (runtimeInitialized) {
|
|
37652
37563
|
moduleRtn = Module;
|
|
37653
37564
|
} else {
|
|
37654
|
-
moduleRtn = new Promise((
|
|
37655
|
-
readyPromiseResolve =
|
|
37565
|
+
moduleRtn = new Promise((resolve8, reject) => {
|
|
37566
|
+
readyPromiseResolve = resolve8;
|
|
37656
37567
|
readyPromiseReject = reject;
|
|
37657
37568
|
});
|
|
37658
37569
|
}
|
|
@@ -43571,9 +43482,47 @@ var init_mcp = __esm({
|
|
|
43571
43482
|
init_reconcile();
|
|
43572
43483
|
init_agent_signals();
|
|
43573
43484
|
INSTRUCTIONS = [
|
|
43574
|
-
|
|
43575
|
-
|
|
43576
|
-
|
|
43485
|
+
// KEEP THIS UNDER THE CLIENT'S ~2 KB instruction-injection budget (the client
|
|
43486
|
+
// truncates `instructions` on connect, ~2008 chars observed). Capture no longer
|
|
43487
|
+
// depends on a standing emit-instruction block: the daemon derives problems/fixes
|
|
43488
|
+
// from your WORK deterministically, and the one thing it asks of the agent — a
|
|
43489
|
+
// one-line root cause at a fix — rides INLINE on the next tool response (the ⚡
|
|
43490
|
+
// errata line; see the dispatch's enrichment piggyback) instead of a fenced
|
|
43491
|
+
// protocol the agent has to remember. So this stays short: tool-routing steering
|
|
43492
|
+
// plus a single line about the inline nudge. Per-tool routing lives in each tool's
|
|
43493
|
+
// own `description` (delivered via tools/list). Don't re-add a tool table here.
|
|
43494
|
+
"errata is a LIVE, bi-temporal code graph of this workspace, kept current by a",
|
|
43495
|
+
"file watcher \u2014 a SEPARATE DIAGNOSTIC AXIS to run ALONGSIDE grep/glob/read, not",
|
|
43496
|
+
"instead of them. For STRUCTURAL questions (callers of callers, blast-radius,",
|
|
43497
|
+
"rename lineage) prefer it: faster, more complete, and it reaches relationships",
|
|
43498
|
+
"grep can't. Each tool's description says when to reach for it. Fall back to",
|
|
43499
|
+
'grep/read when a tool returns found:false (ESPECIALLY reason:"unresolved" \u2014 the',
|
|
43500
|
+
"name was not recognized, NOT an empty answer; an empty list like callers:[] is a",
|
|
43501
|
+
'confident "none" \u2014 trust it), when you need EXACT bytes before a high-stakes',
|
|
43502
|
+
"edit, or for an unindexed file/language. Always confirm exact bytes with a read",
|
|
43503
|
+
"before editing.",
|
|
43504
|
+
"",
|
|
43505
|
+
"errata is a cloud knowledge substrate \u2014 AND ALSO this workspace's code graph.",
|
|
43506
|
+
"The problems you hit and the fixes you make become shared knowledge other agents",
|
|
43507
|
+
"recall. That capture is automatic: derived from your edits/commands/commits \u2014 no",
|
|
43508
|
+
"emit needed. Just after you resolve something a tool result may carry a one-line",
|
|
43509
|
+
"\u26A1 errata note asking the ROOT CAUSE; answer via errata.annotate_resolution when",
|
|
43510
|
+
"you know it, skip it otherwise.",
|
|
43511
|
+
"",
|
|
43512
|
+
"Two things it CAN'T derive \u2014 only you witness them, and this is a CAPTURE",
|
|
43513
|
+
"PROTOCOL, not optional formatting: a problem or fix you state only in prose, a",
|
|
43514
|
+
"list, or your own numbering is SILENTLY LOST \u2014 the tag is the ONLY thing recorded.",
|
|
43515
|
+
"So the moment you state one, wrap it inline (no fence, no extra call):",
|
|
43516
|
+
// Signal tokens come from the single source (agent-signals.ts) so this always-on
|
|
43517
|
+
// block can't teach a grammar the parser rejects. Referent is "its-id" here — the
|
|
43518
|
+
// raw MCP channel has no primed handles, so the agent cites a tool-result id.
|
|
43519
|
+
` \u2022 ${TAG_EXAMPLE.problem()} \u2014 EVERY problem you notice or report ([?\u2026] = TODO)`,
|
|
43520
|
+
` \u2022 ${TAG_EXAMPLE.fix("its-id")} \u2014 your edit fixed a problem errata showed you`,
|
|
43521
|
+
"Tag every one you state \u2014 we filter downstream, so don't self-censor or batch.",
|
|
43522
|
+
"",
|
|
43523
|
+
"Graph-as-files: the graph is ALSO a virtual FS \u2014 Read (or `cat`)",
|
|
43524
|
+
".errata/g/<verb>/<seed> to run a query as a file read (e.g. .errata/g/burst/",
|
|
43525
|
+
"<symbol>, /why/<sym>, /trace/<a>..<b>). Read .errata/g/index for the vocabulary."
|
|
43577
43526
|
].join("\n");
|
|
43578
43527
|
AUDIT_RUN_THRESHOLD = 5;
|
|
43579
43528
|
AUDIT_NUDGE_COOLDOWN = 12;
|
|
@@ -44165,7 +44114,7 @@ var init_mcp = __esm({
|
|
|
44165
44114
|
},
|
|
44166
44115
|
{
|
|
44167
44116
|
name: "errata.problems",
|
|
44168
|
-
description: "List the workspace's Problem
|
|
44117
|
+
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.",
|
|
44169
44118
|
inputSchema: {
|
|
44170
44119
|
type: "object",
|
|
44171
44120
|
properties: {
|
|
@@ -44177,15 +44126,13 @@ var init_mcp = __esm({
|
|
|
44177
44126
|
const want = String(args2["status"] ?? "open");
|
|
44178
44127
|
const limit = Math.max(1, Math.min(200, Number(args2["limit"] ?? 50)));
|
|
44179
44128
|
const RETRACTIONS = /* @__PURE__ */ new Set(["false_positive", "invalid", "duplicate"]);
|
|
44180
|
-
const rows =
|
|
44129
|
+
const rows = store.findAllVersionsByLabel("Problem").map((p) => {
|
|
44181
44130
|
const ra = p.attrs["resolvedAs"];
|
|
44182
44131
|
const status = ra && RETRACTIONS.has(ra) ? ra : p.attrs["resolvedAt"] != null ? "resolved" : isConstraintProblem(p) ? "constraint" : "open";
|
|
44183
44132
|
const anchorEdge = store.outEdges(p.id, ["ANCHORED_AT"])[0];
|
|
44184
44133
|
const anchor = anchorEdge ? store.getNode(anchorEdge.to)?.description : void 0;
|
|
44185
44134
|
return {
|
|
44186
44135
|
id: p.id,
|
|
44187
|
-
label: p.label,
|
|
44188
|
-
...p.label === "Vulnerability" ? { assessment: p.attrs["assessment"] } : {},
|
|
44189
44136
|
problem: p.description,
|
|
44190
44137
|
status,
|
|
44191
44138
|
createdAt: p.createdAt,
|
|
@@ -52553,8 +52500,8 @@ import {
|
|
|
52553
52500
|
existsSync as existsSync17,
|
|
52554
52501
|
readdirSync as readdirSync5,
|
|
52555
52502
|
readFileSync as readFileSync16,
|
|
52556
|
-
renameSync,
|
|
52557
|
-
unlinkSync as
|
|
52503
|
+
renameSync as renameSync2,
|
|
52504
|
+
unlinkSync as unlinkSync3,
|
|
52558
52505
|
writeFileSync as writeFileSync12
|
|
52559
52506
|
} from "node:fs";
|
|
52560
52507
|
import { join as join17 } from "node:path";
|
|
@@ -52573,7 +52520,7 @@ async function flushOutbox(paths, client, store) {
|
|
|
52573
52520
|
let failed = 0;
|
|
52574
52521
|
const quarantine = (abs, reason) => {
|
|
52575
52522
|
try {
|
|
52576
|
-
|
|
52523
|
+
renameSync2(abs, `${abs}.bad`);
|
|
52577
52524
|
console.warn(`[errata] outbox: quarantined ${abs} (${reason})`);
|
|
52578
52525
|
} catch {
|
|
52579
52526
|
}
|
|
@@ -52617,7 +52564,7 @@ async function flushOutbox(paths, client, store) {
|
|
|
52617
52564
|
}
|
|
52618
52565
|
}
|
|
52619
52566
|
}
|
|
52620
|
-
|
|
52567
|
+
unlinkSync3(abs);
|
|
52621
52568
|
if (res.accepted === 0) uploaded++;
|
|
52622
52569
|
} catch (err2) {
|
|
52623
52570
|
failed++;
|
|
@@ -52750,8 +52697,7 @@ function errorRecallTerms(errorText) {
|
|
|
52750
52697
|
}
|
|
52751
52698
|
function recallLine(n, token) {
|
|
52752
52699
|
const desc = (n.description ?? "").replace(/\s+/g, " ").slice(0, 120);
|
|
52753
|
-
|
|
52754
|
-
return `- [${label}] ${desc} \u2192 ${token}`;
|
|
52700
|
+
return `- [${n.label}] ${desc} \u2192 ${token}`;
|
|
52755
52701
|
}
|
|
52756
52702
|
function recallForFile(store, relPath) {
|
|
52757
52703
|
return fileRecall(store, relPath)?.context ?? null;
|
|
@@ -52772,7 +52718,7 @@ function fileRecall(store, relPath) {
|
|
|
52772
52718
|
const shownRelated = priors.related.slice(0, 4);
|
|
52773
52719
|
for (const p of shownProblems) {
|
|
52774
52720
|
const hasCause = store.outEdges(p.id, ["CAUSED_BY"]).some((e) => store.getNode(e.to)?.label === "RootCause");
|
|
52775
|
-
const causeCue = hasCause ? "" : ` \xB7 ${
|
|
52721
|
+
const causeCue = hasCause ? "" : ` \xB7 ${TAG_EXAMPLE.triageMint()} to diagnose its cause`;
|
|
52776
52722
|
lines.push(
|
|
52777
52723
|
recallLine(p, `${TAG_EXAMPLE.fix(p.id)} if you resolved it \xB7 ${TAG_EXAMPLE.prior(p.id)} to cite${causeCue}`)
|
|
52778
52724
|
);
|
|
@@ -55721,9 +55667,9 @@ var require_dispatcher_base = __commonJS({
|
|
|
55721
55667
|
}
|
|
55722
55668
|
close(callback) {
|
|
55723
55669
|
if (callback === void 0) {
|
|
55724
|
-
return new Promise((
|
|
55670
|
+
return new Promise((resolve8, reject) => {
|
|
55725
55671
|
this.close((err2, data) => {
|
|
55726
|
-
return err2 ? reject(err2) :
|
|
55672
|
+
return err2 ? reject(err2) : resolve8(data);
|
|
55727
55673
|
});
|
|
55728
55674
|
});
|
|
55729
55675
|
}
|
|
@@ -55761,12 +55707,12 @@ var require_dispatcher_base = __commonJS({
|
|
|
55761
55707
|
err2 = null;
|
|
55762
55708
|
}
|
|
55763
55709
|
if (callback === void 0) {
|
|
55764
|
-
return new Promise((
|
|
55710
|
+
return new Promise((resolve8, reject) => {
|
|
55765
55711
|
this.destroy(err2, (err3, data) => {
|
|
55766
55712
|
return err3 ? (
|
|
55767
55713
|
/* istanbul ignore next: should never error */
|
|
55768
55714
|
reject(err3)
|
|
55769
|
-
) :
|
|
55715
|
+
) : resolve8(data);
|
|
55770
55716
|
});
|
|
55771
55717
|
});
|
|
55772
55718
|
}
|
|
@@ -58033,8 +57979,8 @@ var require_util2 = __commonJS({
|
|
|
58033
57979
|
function createDeferredPromise() {
|
|
58034
57980
|
let res;
|
|
58035
57981
|
let rej;
|
|
58036
|
-
const promise2 = new Promise((
|
|
58037
|
-
res =
|
|
57982
|
+
const promise2 = new Promise((resolve8, reject) => {
|
|
57983
|
+
res = resolve8;
|
|
58038
57984
|
rej = reject;
|
|
58039
57985
|
});
|
|
58040
57986
|
return { promise: promise2, resolve: res, reject: rej };
|
|
@@ -60175,12 +60121,12 @@ upgrade: ${upgrade}\r
|
|
|
60175
60121
|
cb();
|
|
60176
60122
|
}
|
|
60177
60123
|
}
|
|
60178
|
-
const waitForDrain = () => new Promise((
|
|
60124
|
+
const waitForDrain = () => new Promise((resolve8, reject) => {
|
|
60179
60125
|
assert2(callback === null);
|
|
60180
60126
|
if (socket[kError]) {
|
|
60181
60127
|
reject(socket[kError]);
|
|
60182
60128
|
} else {
|
|
60183
|
-
callback =
|
|
60129
|
+
callback = resolve8;
|
|
60184
60130
|
}
|
|
60185
60131
|
});
|
|
60186
60132
|
socket.on("close", onDrain).on("drain", onDrain);
|
|
@@ -60817,12 +60763,12 @@ var require_client_h2 = __commonJS({
|
|
|
60817
60763
|
cb();
|
|
60818
60764
|
}
|
|
60819
60765
|
}
|
|
60820
|
-
const waitForDrain = () => new Promise((
|
|
60766
|
+
const waitForDrain = () => new Promise((resolve8, reject) => {
|
|
60821
60767
|
assert2(callback === null);
|
|
60822
60768
|
if (socket[kError]) {
|
|
60823
60769
|
reject(socket[kError]);
|
|
60824
60770
|
} else {
|
|
60825
|
-
callback =
|
|
60771
|
+
callback = resolve8;
|
|
60826
60772
|
}
|
|
60827
60773
|
});
|
|
60828
60774
|
h2stream.on("close", onDrain).on("drain", onDrain);
|
|
@@ -61299,16 +61245,16 @@ var require_client = __commonJS({
|
|
|
61299
61245
|
return this[kNeedDrain] < 2;
|
|
61300
61246
|
}
|
|
61301
61247
|
async [kClose]() {
|
|
61302
|
-
return new Promise((
|
|
61248
|
+
return new Promise((resolve8) => {
|
|
61303
61249
|
if (this[kSize]) {
|
|
61304
|
-
this[kClosedResolve] =
|
|
61250
|
+
this[kClosedResolve] = resolve8;
|
|
61305
61251
|
} else {
|
|
61306
|
-
|
|
61252
|
+
resolve8(null);
|
|
61307
61253
|
}
|
|
61308
61254
|
});
|
|
61309
61255
|
}
|
|
61310
61256
|
async [kDestroy](err2) {
|
|
61311
|
-
return new Promise((
|
|
61257
|
+
return new Promise((resolve8) => {
|
|
61312
61258
|
const requests = this[kQueue].splice(this[kPendingIdx]);
|
|
61313
61259
|
for (let i2 = 0; i2 < requests.length; i2++) {
|
|
61314
61260
|
const request = requests[i2];
|
|
@@ -61319,7 +61265,7 @@ var require_client = __commonJS({
|
|
|
61319
61265
|
this[kClosedResolve]();
|
|
61320
61266
|
this[kClosedResolve] = null;
|
|
61321
61267
|
}
|
|
61322
|
-
|
|
61268
|
+
resolve8(null);
|
|
61323
61269
|
};
|
|
61324
61270
|
if (this[kHTTPContext]) {
|
|
61325
61271
|
this[kHTTPContext].destroy(err2, callback);
|
|
@@ -61370,7 +61316,7 @@ var require_client = __commonJS({
|
|
|
61370
61316
|
});
|
|
61371
61317
|
}
|
|
61372
61318
|
try {
|
|
61373
|
-
const socket = await new Promise((
|
|
61319
|
+
const socket = await new Promise((resolve8, reject) => {
|
|
61374
61320
|
client[kConnector]({
|
|
61375
61321
|
host,
|
|
61376
61322
|
hostname: hostname3,
|
|
@@ -61382,7 +61328,7 @@ var require_client = __commonJS({
|
|
|
61382
61328
|
if (err2) {
|
|
61383
61329
|
reject(err2);
|
|
61384
61330
|
} else {
|
|
61385
|
-
|
|
61331
|
+
resolve8(socket2);
|
|
61386
61332
|
}
|
|
61387
61333
|
});
|
|
61388
61334
|
});
|
|
@@ -61718,8 +61664,8 @@ var require_pool_base = __commonJS({
|
|
|
61718
61664
|
if (this[kQueue].isEmpty()) {
|
|
61719
61665
|
await Promise.all(this[kClients].map((c) => c.close()));
|
|
61720
61666
|
} else {
|
|
61721
|
-
await new Promise((
|
|
61722
|
-
this[kClosedResolve] =
|
|
61667
|
+
await new Promise((resolve8) => {
|
|
61668
|
+
this[kClosedResolve] = resolve8;
|
|
61723
61669
|
});
|
|
61724
61670
|
}
|
|
61725
61671
|
}
|
|
@@ -62934,7 +62880,7 @@ var require_readable = __commonJS({
|
|
|
62934
62880
|
if (this._readableState.closeEmitted) {
|
|
62935
62881
|
return null;
|
|
62936
62882
|
}
|
|
62937
|
-
return await new Promise((
|
|
62883
|
+
return await new Promise((resolve8, reject) => {
|
|
62938
62884
|
if (this[kContentLength] > limit) {
|
|
62939
62885
|
this.destroy(new AbortError());
|
|
62940
62886
|
}
|
|
@@ -62947,7 +62893,7 @@ var require_readable = __commonJS({
|
|
|
62947
62893
|
if (signal?.aborted) {
|
|
62948
62894
|
reject(signal.reason ?? new AbortError());
|
|
62949
62895
|
} else {
|
|
62950
|
-
|
|
62896
|
+
resolve8(null);
|
|
62951
62897
|
}
|
|
62952
62898
|
}).on("error", noop).on("data", function(chunk) {
|
|
62953
62899
|
limit -= chunk.length;
|
|
@@ -62966,7 +62912,7 @@ var require_readable = __commonJS({
|
|
|
62966
62912
|
}
|
|
62967
62913
|
async function consume(stream, type) {
|
|
62968
62914
|
assert2(!stream[kConsume]);
|
|
62969
|
-
return new Promise((
|
|
62915
|
+
return new Promise((resolve8, reject) => {
|
|
62970
62916
|
if (isUnusable(stream)) {
|
|
62971
62917
|
const rState = stream._readableState;
|
|
62972
62918
|
if (rState.destroyed && rState.closeEmitted === false) {
|
|
@@ -62983,7 +62929,7 @@ var require_readable = __commonJS({
|
|
|
62983
62929
|
stream[kConsume] = {
|
|
62984
62930
|
type,
|
|
62985
62931
|
stream,
|
|
62986
|
-
resolve:
|
|
62932
|
+
resolve: resolve8,
|
|
62987
62933
|
reject,
|
|
62988
62934
|
length: 0,
|
|
62989
62935
|
body: []
|
|
@@ -63053,18 +62999,18 @@ var require_readable = __commonJS({
|
|
|
63053
62999
|
return buffer;
|
|
63054
63000
|
}
|
|
63055
63001
|
function consumeEnd(consume2) {
|
|
63056
|
-
const { type, body: body2, resolve:
|
|
63002
|
+
const { type, body: body2, resolve: resolve8, stream, length } = consume2;
|
|
63057
63003
|
try {
|
|
63058
63004
|
if (type === "text") {
|
|
63059
|
-
|
|
63005
|
+
resolve8(chunksDecode(body2, length));
|
|
63060
63006
|
} else if (type === "json") {
|
|
63061
|
-
|
|
63007
|
+
resolve8(JSON.parse(chunksDecode(body2, length)));
|
|
63062
63008
|
} else if (type === "arrayBuffer") {
|
|
63063
|
-
|
|
63009
|
+
resolve8(chunksConcat(body2, length).buffer);
|
|
63064
63010
|
} else if (type === "blob") {
|
|
63065
|
-
|
|
63011
|
+
resolve8(new Blob(body2, { type: stream[kContentType] }));
|
|
63066
63012
|
} else if (type === "bytes") {
|
|
63067
|
-
|
|
63013
|
+
resolve8(chunksConcat(body2, length));
|
|
63068
63014
|
}
|
|
63069
63015
|
consumeFinish(consume2);
|
|
63070
63016
|
} catch (err2) {
|
|
@@ -63321,9 +63267,9 @@ var require_api_request = __commonJS({
|
|
|
63321
63267
|
};
|
|
63322
63268
|
function request(opts, callback) {
|
|
63323
63269
|
if (callback === void 0) {
|
|
63324
|
-
return new Promise((
|
|
63270
|
+
return new Promise((resolve8, reject) => {
|
|
63325
63271
|
request.call(this, opts, (err2, data) => {
|
|
63326
|
-
return err2 ? reject(err2) :
|
|
63272
|
+
return err2 ? reject(err2) : resolve8(data);
|
|
63327
63273
|
});
|
|
63328
63274
|
});
|
|
63329
63275
|
}
|
|
@@ -63546,9 +63492,9 @@ var require_api_stream = __commonJS({
|
|
|
63546
63492
|
};
|
|
63547
63493
|
function stream(opts, factory, callback) {
|
|
63548
63494
|
if (callback === void 0) {
|
|
63549
|
-
return new Promise((
|
|
63495
|
+
return new Promise((resolve8, reject) => {
|
|
63550
63496
|
stream.call(this, opts, factory, (err2, data) => {
|
|
63551
|
-
return err2 ? reject(err2) :
|
|
63497
|
+
return err2 ? reject(err2) : resolve8(data);
|
|
63552
63498
|
});
|
|
63553
63499
|
});
|
|
63554
63500
|
}
|
|
@@ -63833,9 +63779,9 @@ var require_api_upgrade = __commonJS({
|
|
|
63833
63779
|
};
|
|
63834
63780
|
function upgrade(opts, callback) {
|
|
63835
63781
|
if (callback === void 0) {
|
|
63836
|
-
return new Promise((
|
|
63782
|
+
return new Promise((resolve8, reject) => {
|
|
63837
63783
|
upgrade.call(this, opts, (err2, data) => {
|
|
63838
|
-
return err2 ? reject(err2) :
|
|
63784
|
+
return err2 ? reject(err2) : resolve8(data);
|
|
63839
63785
|
});
|
|
63840
63786
|
});
|
|
63841
63787
|
}
|
|
@@ -63927,9 +63873,9 @@ var require_api_connect = __commonJS({
|
|
|
63927
63873
|
};
|
|
63928
63874
|
function connect(opts, callback) {
|
|
63929
63875
|
if (callback === void 0) {
|
|
63930
|
-
return new Promise((
|
|
63876
|
+
return new Promise((resolve8, reject) => {
|
|
63931
63877
|
connect.call(this, opts, (err2, data) => {
|
|
63932
|
-
return err2 ? reject(err2) :
|
|
63878
|
+
return err2 ? reject(err2) : resolve8(data);
|
|
63933
63879
|
});
|
|
63934
63880
|
});
|
|
63935
63881
|
}
|
|
@@ -67791,7 +67737,7 @@ var require_fetch = __commonJS({
|
|
|
67791
67737
|
function dispatch({ body: body2 }) {
|
|
67792
67738
|
const url2 = requestCurrentURL(request);
|
|
67793
67739
|
const agent = fetchParams.controller.dispatcher;
|
|
67794
|
-
return new Promise((
|
|
67740
|
+
return new Promise((resolve8, reject) => agent.dispatch(
|
|
67795
67741
|
{
|
|
67796
67742
|
path: url2.pathname + url2.search,
|
|
67797
67743
|
origin: url2.origin,
|
|
@@ -67867,7 +67813,7 @@ var require_fetch = __commonJS({
|
|
|
67867
67813
|
}
|
|
67868
67814
|
}
|
|
67869
67815
|
const onError = this.onError.bind(this);
|
|
67870
|
-
|
|
67816
|
+
resolve8({
|
|
67871
67817
|
status,
|
|
67872
67818
|
statusText,
|
|
67873
67819
|
headersList,
|
|
@@ -67913,7 +67859,7 @@ var require_fetch = __commonJS({
|
|
|
67913
67859
|
for (let i2 = 0; i2 < rawHeaders.length; i2 += 2) {
|
|
67914
67860
|
headersList.append(bufferToLowerCasedHeaderName(rawHeaders[i2]), rawHeaders[i2 + 1].toString("latin1"), true);
|
|
67915
67861
|
}
|
|
67916
|
-
|
|
67862
|
+
resolve8({
|
|
67917
67863
|
status,
|
|
67918
67864
|
statusText: STATUS_CODES[status],
|
|
67919
67865
|
headersList,
|
|
@@ -71552,8 +71498,8 @@ var require_util8 = __commonJS({
|
|
|
71552
71498
|
return true;
|
|
71553
71499
|
}
|
|
71554
71500
|
function delay(ms) {
|
|
71555
|
-
return new Promise((
|
|
71556
|
-
setTimeout(
|
|
71501
|
+
return new Promise((resolve8) => {
|
|
71502
|
+
setTimeout(resolve8, ms).unref();
|
|
71557
71503
|
});
|
|
71558
71504
|
}
|
|
71559
71505
|
module2.exports = {
|
|
@@ -72700,8 +72646,8 @@ var init_report_render = __esm({
|
|
|
72700
72646
|
|
|
72701
72647
|
// src/cli.ts
|
|
72702
72648
|
init_src6();
|
|
72703
|
-
import { closeSync as closeSync2, existsSync as
|
|
72704
|
-
import { join as
|
|
72649
|
+
import { closeSync as closeSync2, existsSync as existsSync37, openSync as openSync2, readFileSync as readFileSync40, renameSync as renameSync6, statSync as statSync11 } from "node:fs";
|
|
72650
|
+
import { join as join47, resolve as pathResolve2 } from "node:path";
|
|
72705
72651
|
import { spawn as spawn5 } from "node:child_process";
|
|
72706
72652
|
|
|
72707
72653
|
// src/daemon.ts
|
|
@@ -73135,7 +73081,7 @@ var responseViaResponseObject = async (res, outgoing, options = {}) => {
|
|
|
73135
73081
|
});
|
|
73136
73082
|
if (!chunk) {
|
|
73137
73083
|
if (i2 === 1) {
|
|
73138
|
-
await new Promise((
|
|
73084
|
+
await new Promise((resolve8) => setTimeout(resolve8));
|
|
73139
73085
|
maxReadCount = 3;
|
|
73140
73086
|
continue;
|
|
73141
73087
|
}
|
|
@@ -73282,10 +73228,11 @@ var serve = (options, listeningListener) => {
|
|
|
73282
73228
|
init_cloud_auth();
|
|
73283
73229
|
init_webui();
|
|
73284
73230
|
init_config();
|
|
73231
|
+
init_lock();
|
|
73285
73232
|
|
|
73286
73233
|
// src/engine.ts
|
|
73287
73234
|
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
73288
|
-
import { existsSync as existsSync27, statSync as statSync8, appendFileSync as appendFileSync4, readdirSync as readdirSync10, renameSync as
|
|
73235
|
+
import { existsSync as existsSync27, statSync as statSync8, appendFileSync as appendFileSync4, readdirSync as readdirSync10, renameSync as renameSync4, readFileSync as readFileSync31, writeFileSync as writeFileSync22 } from "node:fs";
|
|
73289
73236
|
import { basename as basename7, join as join35, relative as relative6, sep as sep4 } from "node:path";
|
|
73290
73237
|
|
|
73291
73238
|
// src/source-watcher.ts
|
|
@@ -74022,9 +73969,9 @@ var NodeFsHandler = class {
|
|
|
74022
73969
|
if (this.fsw.closed) {
|
|
74023
73970
|
return;
|
|
74024
73971
|
}
|
|
74025
|
-
const
|
|
73972
|
+
const dirname15 = sysPath.dirname(file2);
|
|
74026
73973
|
const basename9 = sysPath.basename(file2);
|
|
74027
|
-
const parent = this.fsw._getWatchedDir(
|
|
73974
|
+
const parent = this.fsw._getWatchedDir(dirname15);
|
|
74028
73975
|
let prevStats = stats;
|
|
74029
73976
|
if (parent.has(basename9))
|
|
74030
73977
|
return;
|
|
@@ -74051,7 +73998,7 @@ var NodeFsHandler = class {
|
|
|
74051
73998
|
prevStats = newStats2;
|
|
74052
73999
|
}
|
|
74053
74000
|
} catch (error48) {
|
|
74054
|
-
this.fsw._remove(
|
|
74001
|
+
this.fsw._remove(dirname15, basename9);
|
|
74055
74002
|
}
|
|
74056
74003
|
} else if (parent.has(basename9)) {
|
|
74057
74004
|
const at = newStats.atimeMs;
|
|
@@ -74147,7 +74094,7 @@ var NodeFsHandler = class {
|
|
|
74147
74094
|
this._addToNodeFs(path2, initialAdd, wh, depth + 1);
|
|
74148
74095
|
}
|
|
74149
74096
|
}).on(EV.ERROR, this._boundHandleError);
|
|
74150
|
-
return new Promise((
|
|
74097
|
+
return new Promise((resolve8, reject) => {
|
|
74151
74098
|
if (!stream)
|
|
74152
74099
|
return reject();
|
|
74153
74100
|
stream.once(STR_END, () => {
|
|
@@ -74156,7 +74103,7 @@ var NodeFsHandler = class {
|
|
|
74156
74103
|
return;
|
|
74157
74104
|
}
|
|
74158
74105
|
const wasThrottled = throttler ? throttler.clear() : false;
|
|
74159
|
-
|
|
74106
|
+
resolve8(void 0);
|
|
74160
74107
|
previous.getChildren().filter((item2) => {
|
|
74161
74108
|
return item2 !== directory && !current.has(item2);
|
|
74162
74109
|
}).forEach((item2) => {
|
|
@@ -76041,7 +75988,7 @@ init_src5();
|
|
|
76041
75988
|
import { readFileSync as readFileSync17, writeFileSync as writeFileSync13 } from "node:fs";
|
|
76042
75989
|
var NEG = /n['']t|\b(?:not|never|no|none|neither|nor|unrelated|irrelevant|would|might|could|if)\b/i;
|
|
76043
75990
|
var CITE_GROUP_RE = /\(((?:[^()\n]|\([^()\n]*\)){1,200})\)/g;
|
|
76044
|
-
var HANDLE_RE = /\[([a-z0-9][\w-]{0,80})\]|((?:pat|sol|drc|dcause|dfix|dprob|
|
|
75991
|
+
var HANDLE_RE = /\[([a-z0-9][\w-]{0,80})\]|((?:pat|sol|drc|dcause|dfix|dprob|prob|claim|err)_[0-9a-f]{6,})/gi;
|
|
76045
75992
|
var PLACEHOLDER_HANDLES = /* @__PURE__ */ new Set([
|
|
76046
75993
|
"handle",
|
|
76047
75994
|
"its-handle",
|
|
@@ -76056,7 +76003,7 @@ var PLACEHOLDER_HANDLES = /* @__PURE__ */ new Set([
|
|
|
76056
76003
|
"b"
|
|
76057
76004
|
]);
|
|
76058
76005
|
var isPlaceholderHandle = (h) => PLACEHOLDER_HANDLES.has(h.toLowerCase());
|
|
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|
|
|
76006
|
+
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;
|
|
76060
76007
|
var FIX_PREFIX = /^\s*fix:(?:#([a-z][\w-]{0,63}))?\s*/i;
|
|
76061
76008
|
var CONSTRAINT_RE = /\(\s*constraint:\s*([^()\n]{8,}?)\s*\)/gi;
|
|
76062
76009
|
var CAUSE_PREFIX = /^\s*cause:(?:#([a-z][\w-]{0,63}))?\s*/i;
|
|
@@ -76081,7 +76028,7 @@ var DOMAIN_RE = /\(\s*domain:\s*([^()\n]{3,}?)\s*\)/gi;
|
|
|
76081
76028
|
var PACKAGE_RE = /\(\s*package:\s*([^()\n]{2,}?)\s*\)/gi;
|
|
76082
76029
|
var COMPONENT_RE = /\(\s*component:\s*([^()\n]{2,}?)\s*\)/gi;
|
|
76083
76030
|
var CAUSE_TEXT_MIN = 8;
|
|
76084
|
-
var FLAG_RE = /\[([!?])(?:#([a-z][\w-]{0,63})\s+)?\s*((?:\[[^\]\n]*\]|[^\]\n])
|
|
76031
|
+
var FLAG_RE = /\[([!?])(?:#([a-z][\w-]{0,63})\s+)?\s*((?:\[[^\]\n]*\]|[^\]\n]){8,}?)\s*(?:@\s*([^\s\]]+?)(?::(\d+))?\s*)?\]/g;
|
|
76085
76032
|
var CONSTRAINT_MIN = 8;
|
|
76086
76033
|
function clauseBefore(sentence, idx) {
|
|
76087
76034
|
const win = sentence.slice(Math.max(0, idx - 80), idx);
|
|
@@ -76225,7 +76172,6 @@ function cleanEmittedTags(tags) {
|
|
|
76225
76172
|
}
|
|
76226
76173
|
function emptyTagDispositions() {
|
|
76227
76174
|
return {
|
|
76228
|
-
invalidVulnerability: 0,
|
|
76229
76175
|
oversizeSegments: 0,
|
|
76230
76176
|
codeSpanNeutralized: 0,
|
|
76231
76177
|
refuteTooShort: 0,
|
|
@@ -76238,7 +76184,6 @@ function emptyTagDispositions() {
|
|
|
76238
76184
|
};
|
|
76239
76185
|
}
|
|
76240
76186
|
function addTagDispositions(a, b) {
|
|
76241
|
-
a.invalidVulnerability += b.invalidVulnerability;
|
|
76242
76187
|
a.oversizeSegments += b.oversizeSegments;
|
|
76243
76188
|
a.codeSpanNeutralized += b.codeSpanNeutralized;
|
|
76244
76189
|
a.refuteTooShort += b.refuteTooShort;
|
|
@@ -76252,31 +76197,12 @@ function addTagDispositions(a, b) {
|
|
|
76252
76197
|
function parseInlineTags(text) {
|
|
76253
76198
|
return parseInlineTagsWithDispositions(text).tags;
|
|
76254
76199
|
}
|
|
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
|
-
}
|
|
76274
76200
|
function parseInlineTagsWithDispositions(text) {
|
|
76275
76201
|
const out2 = [];
|
|
76276
76202
|
const dispositions = emptyTagDispositions();
|
|
76277
76203
|
const deFenced = text.replace(/```[\s\S]*?```/g, " ");
|
|
76278
76204
|
let seqNo = -1;
|
|
76279
|
-
for (const raw2 of
|
|
76205
|
+
for (const raw2 of deFenced.split(/(?<=[.!?])\s+(?!\(fix:)|\n+/)) {
|
|
76280
76206
|
seqNo++;
|
|
76281
76207
|
if (raw2.length > 2e4) {
|
|
76282
76208
|
dispositions.oversizeSegments++;
|
|
@@ -76502,29 +76428,6 @@ function parseInlineTagsWithDispositions(text) {
|
|
|
76502
76428
|
while ((f = FLAG_RE.exec(sentence)) !== null) {
|
|
76503
76429
|
const flagThread = f[2];
|
|
76504
76430
|
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
|
-
}
|
|
76528
76431
|
if (FLAG_BODY_HANDLE_RE.test(raw3) && !f[4]) {
|
|
76529
76432
|
dispositions.flagAsHandle++;
|
|
76530
76433
|
out2.push({ kind: "prior", handle: raw3, sentence: sfield });
|
|
@@ -76895,7 +76798,7 @@ function harvestInlineTags(store, text, opts) {
|
|
|
76895
76798
|
const parsed = parseInlineTagsWithDispositions(text);
|
|
76896
76799
|
const tags = parsed.tags;
|
|
76897
76800
|
plan.dispositions = parsed.dispositions;
|
|
76898
|
-
const symptomSeqs = tags.filter((t) => (t.kind === "problem" || t.kind === "todo"
|
|
76801
|
+
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);
|
|
76899
76802
|
const bindSymptom = (seq, threadId) => {
|
|
76900
76803
|
if (threadId) {
|
|
76901
76804
|
const hit = symptomSeqs.find((s) => s.threadId === threadId);
|
|
@@ -76908,7 +76811,6 @@ function harvestInlineTags(store, text, opts) {
|
|
|
76908
76811
|
if (seq == null) return { evidence: "inferred" };
|
|
76909
76812
|
let best;
|
|
76910
76813
|
for (const s of symptomSeqs) {
|
|
76911
|
-
if (s.kind === "vulnerability") continue;
|
|
76912
76814
|
if (s.seq <= seq) best = s;
|
|
76913
76815
|
else break;
|
|
76914
76816
|
}
|
|
@@ -76923,13 +76825,10 @@ function harvestInlineTags(store, text, opts) {
|
|
|
76923
76825
|
return id;
|
|
76924
76826
|
};
|
|
76925
76827
|
for (const tag of tags) {
|
|
76926
|
-
if (tag.kind === "problem" || tag.kind === "todo"
|
|
76828
|
+
if (tag.kind === "problem" || tag.kind === "todo") {
|
|
76927
76829
|
plan.problems.push({
|
|
76928
76830
|
statement: tag.statement,
|
|
76929
76831
|
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 } : {},
|
|
76933
76832
|
...tag.location ? { location: tag.location } : {},
|
|
76934
76833
|
...tag.threadId ? { threadId: tag.threadId } : {}
|
|
76935
76834
|
});
|
|
@@ -76952,7 +76851,7 @@ function harvestInlineTags(store, text, opts) {
|
|
|
76952
76851
|
} else if (tag.threadId && !b.statement) {
|
|
76953
76852
|
plan.fixes.push({ inScope: true, fixNote: tag.fixRationale, threadId: tag.threadId });
|
|
76954
76853
|
} else if (b.statement && b.evidence === "witnessed") {
|
|
76955
|
-
plan.fixes.push({ inScope: true, fixNote: tag.fixRationale, boundStatement: b.statement
|
|
76854
|
+
plan.fixes.push({ inScope: true, fixNote: tag.fixRationale, boundStatement: b.statement });
|
|
76956
76855
|
} else {
|
|
76957
76856
|
plan.fixes.push({ inScope: true, fixNote: tag.fixRationale, ambiguous: true });
|
|
76958
76857
|
}
|
|
@@ -77155,7 +77054,6 @@ function harvestInlineTags(store, text, opts) {
|
|
|
77155
77054
|
}
|
|
77156
77055
|
var CORROBORATABLE_LABELS = /* @__PURE__ */ new Set([
|
|
77157
77056
|
"Problem",
|
|
77158
|
-
"Vulnerability",
|
|
77159
77057
|
"Solution",
|
|
77160
77058
|
"RootCause",
|
|
77161
77059
|
"Pattern",
|
|
@@ -77875,8 +77773,8 @@ var PassWorker = class {
|
|
|
77875
77773
|
const id = this.nextId++;
|
|
77876
77774
|
try {
|
|
77877
77775
|
await this.ready;
|
|
77878
|
-
return await new Promise((
|
|
77879
|
-
this.pending.set(id, { resolve:
|
|
77776
|
+
return await new Promise((resolve8, reject) => {
|
|
77777
|
+
this.pending.set(id, { resolve: resolve8, reject });
|
|
77880
77778
|
this.worker.postMessage({ id, kind, ...payload !== void 0 ? { payload } : {} });
|
|
77881
77779
|
});
|
|
77882
77780
|
} finally {
|
|
@@ -77910,12 +77808,12 @@ var PassWorker = class {
|
|
|
77910
77808
|
});
|
|
77911
77809
|
noteIsolateSpawned();
|
|
77912
77810
|
this.worker = worker;
|
|
77913
|
-
this.ready = new Promise((
|
|
77811
|
+
this.ready = new Promise((resolve8, reject) => {
|
|
77914
77812
|
const onReady = (m) => {
|
|
77915
77813
|
if (m?.ready) {
|
|
77916
77814
|
worker.off("message", onReady);
|
|
77917
77815
|
worker.off("error", onErr);
|
|
77918
|
-
|
|
77816
|
+
resolve8();
|
|
77919
77817
|
}
|
|
77920
77818
|
};
|
|
77921
77819
|
const onErr = (err2) => reject(err2);
|
|
@@ -79071,7 +78969,7 @@ function startGitSensor(gitDir, onEvent, opts = {}) {
|
|
|
79071
78969
|
// src/git-delta.ts
|
|
79072
78970
|
import { execFile } from "node:child_process";
|
|
79073
78971
|
function git(repoDir, args2) {
|
|
79074
|
-
return new Promise((
|
|
78972
|
+
return new Promise((resolve8, reject) => {
|
|
79075
78973
|
execFile(
|
|
79076
78974
|
"git",
|
|
79077
78975
|
["-C", repoDir, ...args2],
|
|
@@ -79082,7 +78980,7 @@ function git(repoDir, args2) {
|
|
|
79082
78980
|
// git-sensor runs on every commit/checkout.
|
|
79083
78981
|
windowsHide: true
|
|
79084
78982
|
},
|
|
79085
|
-
(err2, stdout) => err2 ? reject(err2) :
|
|
78983
|
+
(err2, stdout) => err2 ? reject(err2) : resolve8(stdout)
|
|
79086
78984
|
);
|
|
79087
78985
|
});
|
|
79088
78986
|
}
|
|
@@ -80240,12 +80138,12 @@ function headerPaths(diff) {
|
|
|
80240
80138
|
return out2.filter((p) => p !== "/dev/null");
|
|
80241
80139
|
}
|
|
80242
80140
|
function git2(repoDir, args2) {
|
|
80243
|
-
return new Promise((
|
|
80141
|
+
return new Promise((resolve8, reject) => {
|
|
80244
80142
|
execFile2(
|
|
80245
80143
|
"git",
|
|
80246
80144
|
["-C", repoDir, ...args2],
|
|
80247
80145
|
{ encoding: "utf8", maxBuffer: 64 * 1024 * 1024, windowsHide: true },
|
|
80248
|
-
(err2, stdout) => err2 ? reject(err2) :
|
|
80146
|
+
(err2, stdout) => err2 ? reject(err2) : resolve8(stdout)
|
|
80249
80147
|
);
|
|
80250
80148
|
});
|
|
80251
80149
|
}
|
|
@@ -80518,7 +80416,7 @@ import {
|
|
|
80518
80416
|
mkdirSync as mkdirSync7,
|
|
80519
80417
|
readFileSync as readFileSync26,
|
|
80520
80418
|
readdirSync as readdirSync8,
|
|
80521
|
-
unlinkSync as
|
|
80419
|
+
unlinkSync as unlinkSync4,
|
|
80522
80420
|
writeFileSync as writeFileSync17
|
|
80523
80421
|
} from "node:fs";
|
|
80524
80422
|
import { basename as basename6, join as join30 } from "node:path";
|
|
@@ -80579,7 +80477,7 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
|
|
|
80579
80477
|
if (!f.endsWith(".md")) continue;
|
|
80580
80478
|
if (keep.has(basename6(f))) continue;
|
|
80581
80479
|
try {
|
|
80582
|
-
|
|
80480
|
+
unlinkSync4(join30(paths.skillsDir, f));
|
|
80583
80481
|
pruned++;
|
|
80584
80482
|
} catch {
|
|
80585
80483
|
}
|
|
@@ -80861,7 +80759,7 @@ init_paths();
|
|
|
80861
80759
|
init_profile2();
|
|
80862
80760
|
|
|
80863
80761
|
// src/witness-queue.ts
|
|
80864
|
-
import { readFileSync as readFileSync28, renameSync as
|
|
80762
|
+
import { readFileSync as readFileSync28, renameSync as renameSync3, writeFileSync as writeFileSync19 } from "node:fs";
|
|
80865
80763
|
import { dirname as dirname11, join as join32 } from "node:path";
|
|
80866
80764
|
var WITNESS_QUEUE_CAP = 500;
|
|
80867
80765
|
var WITNESS_TTL_MS = 14 * 24 * 60 * 60 * 1e3;
|
|
@@ -80887,7 +80785,7 @@ function saveWitnessQueue(path2, queue) {
|
|
|
80887
80785
|
try {
|
|
80888
80786
|
const tmp = join32(dirname11(path2), `.${Date.now()}.witness-queue.tmp`);
|
|
80889
80787
|
writeFileSync19(tmp, JSON.stringify(queue), "utf8");
|
|
80890
|
-
|
|
80788
|
+
renameSync3(tmp, path2);
|
|
80891
80789
|
} catch {
|
|
80892
80790
|
}
|
|
80893
80791
|
}
|
|
@@ -80934,9 +80832,9 @@ function partitionReplayable(queue, channel, isShipped) {
|
|
|
80934
80832
|
function retireWitnesses(queue, channel, settledKeys) {
|
|
80935
80833
|
return queue.filter((w) => !(w.channel === channel && settledKeys.has(w.witnessKey)));
|
|
80936
80834
|
}
|
|
80937
|
-
var WIRE_SHIPPED_LABELS = /* @__PURE__ */ new Set(["Problem", "
|
|
80835
|
+
var WIRE_SHIPPED_LABELS = /* @__PURE__ */ new Set(["Problem", "Solution", "RootCause"]);
|
|
80938
80836
|
var MOTIF_ID_PREFIX = "motif_community_";
|
|
80939
|
-
var CANONICAL_ID_RE = /^(?:pat|sol|drc|dcause|dfix|dprob|
|
|
80837
|
+
var CANONICAL_ID_RE = /^(?:pat|sol|drc|dcause|dfix|dprob|prob|claim|err)_[0-9a-f]{6,}$/i;
|
|
80940
80838
|
function classifyWitnessTarget(nodeId, getNode) {
|
|
80941
80839
|
if (nodeId.startsWith(MOTIF_ID_PREFIX)) {
|
|
80942
80840
|
const exemplar = nodeId.slice(MOTIF_ID_PREFIX.length);
|
|
@@ -81506,7 +81404,7 @@ function createWatchBreaker(deps) {
|
|
|
81506
81404
|
}
|
|
81507
81405
|
|
|
81508
81406
|
// src/engine.ts
|
|
81509
|
-
var DAEMON_VERSION = true ? "2.0.16
|
|
81407
|
+
var DAEMON_VERSION = true ? "2.0.16" : "2.0.0-alpha.0";
|
|
81510
81408
|
var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
|
|
81511
81409
|
var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
|
|
81512
81410
|
var GIT_OP_MUTE_MS = 4e3;
|
|
@@ -81519,7 +81417,7 @@ function appendIdentityAudit(path2, record2, line) {
|
|
|
81519
81417
|
if (!record2.accepted && record2.score <= 0) return;
|
|
81520
81418
|
try {
|
|
81521
81419
|
if (existsSync27(path2) && statSync8(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
|
|
81522
|
-
|
|
81420
|
+
renameSync4(path2, `${path2}.1`);
|
|
81523
81421
|
}
|
|
81524
81422
|
appendFileSync4(path2, line);
|
|
81525
81423
|
} catch {
|
|
@@ -82398,9 +82296,6 @@ function createWorkspaceEngine(opts) {
|
|
|
82398
82296
|
const harvestTextsInner = async (sessionId, items) => {
|
|
82399
82297
|
let minted = 0;
|
|
82400
82298
|
let tagsSeen = 0;
|
|
82401
|
-
let vulnerabilitiesSeen = 0;
|
|
82402
|
-
let vulnerabilitiesMinted = 0;
|
|
82403
|
-
let vulnerabilitiesSuspected = 0;
|
|
82404
82299
|
let tagsRejected = 0;
|
|
82405
82300
|
let tagsRestated = 0;
|
|
82406
82301
|
let resolved = 0;
|
|
@@ -82631,73 +82526,10 @@ function createWorkspaceEngine(opts) {
|
|
|
82631
82526
|
if ((toolRuns.get(sessionId)?.size ?? 0) > 0) touchedToolTurns++;
|
|
82632
82527
|
const wf = workingFiles.get(sessionId);
|
|
82633
82528
|
let inScopeProblemId;
|
|
82634
|
-
const findingIds = /* @__PURE__ */ new Map();
|
|
82635
|
-
const conflictingThreads = /* @__PURE__ */ new Set();
|
|
82636
82529
|
const threads = sessionThreads.get(sessionId) ?? /* @__PURE__ */ new Map();
|
|
82637
82530
|
sessionThreads.set(sessionId, threads);
|
|
82638
82531
|
for (const p of plan.problems) {
|
|
82639
82532
|
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
|
-
}
|
|
82701
82533
|
const anchorPath = p.location?.path ?? editedTurnFile;
|
|
82702
82534
|
const anchorProvenance = p.location?.path ? "witnessed" : "edited";
|
|
82703
82535
|
const hintPath = anchorPath ? void 0 : turnFile ?? wf;
|
|
@@ -82792,10 +82624,10 @@ function createWorkspaceEngine(opts) {
|
|
|
82792
82624
|
if (r.created || r.corroborated) {
|
|
82793
82625
|
minted++;
|
|
82794
82626
|
if (p.kind !== "constraint") {
|
|
82795
|
-
sessionLastProblem.set(sessionId,
|
|
82796
|
-
inScopeProblemId =
|
|
82627
|
+
sessionLastProblem.set(sessionId, designProblemId(p.statement));
|
|
82628
|
+
inScopeProblemId = designProblemId(p.statement);
|
|
82797
82629
|
}
|
|
82798
|
-
if (p.threadId) threads.set(p.threadId,
|
|
82630
|
+
if (p.threadId) threads.set(p.threadId, designProblemId(p.statement));
|
|
82799
82631
|
try {
|
|
82800
82632
|
if (anchorPath) {
|
|
82801
82633
|
let enclosing = {};
|
|
@@ -82832,8 +82664,7 @@ function createWorkspaceEngine(opts) {
|
|
|
82832
82664
|
);
|
|
82833
82665
|
}
|
|
82834
82666
|
for (const fx of plan.fixes) {
|
|
82835
|
-
|
|
82836
|
-
const pid = fx.problemId ?? (fx.threadId ? threads.get(fx.threadId) : void 0) ?? (fx.boundStatement ? findingIds.get(fx.boundStatement) ?? designProblemId(fx.boundStatement) : void 0);
|
|
82667
|
+
const pid = fx.problemId ?? (fx.threadId ? threads.get(fx.threadId) : void 0) ?? (fx.boundStatement ? designProblemId(fx.boundStatement) : void 0);
|
|
82837
82668
|
if (!pid) {
|
|
82838
82669
|
if (fx.inScope) {
|
|
82839
82670
|
console.warn(
|
|
@@ -82845,7 +82676,7 @@ function createWorkspaceEngine(opts) {
|
|
|
82845
82676
|
const closed = resolveDesignProblemById(store, pid, fx.fixNote, t);
|
|
82846
82677
|
if (!closed) {
|
|
82847
82678
|
const n = store.getNode(pid);
|
|
82848
|
-
if (!n || n.label !== "Problem"
|
|
82679
|
+
if (!n || n.label !== "Problem" || n.attrs["resolvedAs"] != null) {
|
|
82849
82680
|
console.warn(
|
|
82850
82681
|
`[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`
|
|
82851
82682
|
);
|
|
@@ -82864,23 +82695,10 @@ function createWorkspaceEngine(opts) {
|
|
|
82864
82695
|
}
|
|
82865
82696
|
}
|
|
82866
82697
|
}
|
|
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
|
-
}
|
|
82879
82698
|
if (opts.sharedStore && plan.triages.length > 0) {
|
|
82880
82699
|
const fallbackId = sessionLastProblem.get(sessionId);
|
|
82881
82700
|
const fallbackStatement = fallbackId ? store.getNode(fallbackId)?.description : void 0;
|
|
82882
82701
|
for (const tr of plan.triages) {
|
|
82883
|
-
if (vulnerabilityTriages.has(tr)) continue;
|
|
82884
82702
|
let presentingStatement = tr.symptomStatement;
|
|
82885
82703
|
let evidence = tr.evidence;
|
|
82886
82704
|
if (!presentingStatement && tr.threadId) {
|
|
@@ -82898,7 +82716,7 @@ function createWorkspaceEngine(opts) {
|
|
|
82898
82716
|
evidence = "inferred";
|
|
82899
82717
|
}
|
|
82900
82718
|
if (!presentingStatement) continue;
|
|
82901
|
-
const presentingId = tr.symptomProblemId ??
|
|
82719
|
+
const presentingId = tr.symptomProblemId ?? designProblemId(presentingStatement);
|
|
82902
82720
|
if (tr.causeId === presentingId) continue;
|
|
82903
82721
|
try {
|
|
82904
82722
|
recordTriageObservation(
|
|
@@ -82956,7 +82774,7 @@ function createWorkspaceEngine(opts) {
|
|
|
82956
82774
|
}
|
|
82957
82775
|
}
|
|
82958
82776
|
for (const at of plan.attempts) {
|
|
82959
|
-
const pid = at.problemId ?? (at.threadId ? threads.get(at.threadId) : void 0) ?? (at.boundStatement ?
|
|
82777
|
+
const pid = at.problemId ?? (at.threadId ? threads.get(at.threadId) : void 0) ?? (at.boundStatement ? designProblemId(at.boundStatement) : void 0);
|
|
82960
82778
|
const node2 = pid ? store.getNode(pid) : void 0;
|
|
82961
82779
|
if (!pid || !node2) continue;
|
|
82962
82780
|
try {
|
|
@@ -82972,7 +82790,7 @@ function createWorkspaceEngine(opts) {
|
|
|
82972
82790
|
}
|
|
82973
82791
|
}
|
|
82974
82792
|
const bindPid = (tag) => {
|
|
82975
|
-
const pid = tag.problemId ?? (tag.threadId ? threads.get(tag.threadId) : void 0) ?? (tag.boundStatement ?
|
|
82793
|
+
const pid = tag.problemId ?? (tag.threadId ? threads.get(tag.threadId) : void 0) ?? (tag.boundStatement ? designProblemId(tag.boundStatement) : void 0) ?? inScopeProblemId ?? sessionLastProblem.get(sessionId);
|
|
82976
82794
|
return pid && store.getNode(pid) ? pid : void 0;
|
|
82977
82795
|
};
|
|
82978
82796
|
const mintCiteEdge = (from, to, type, confidence, extraAttrs) => {
|
|
@@ -83126,12 +82944,7 @@ function createWorkspaceEngine(opts) {
|
|
|
83126
82944
|
for (const [session, items2] of groups) {
|
|
83127
82945
|
if (items2.length === 0) continue;
|
|
83128
82946
|
try {
|
|
83129
|
-
const
|
|
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);
|
|
82947
|
+
const raw2 = await send(items2, session);
|
|
83135
82948
|
const d = {
|
|
83136
82949
|
recorded: raw2?.recorded ?? 0,
|
|
83137
82950
|
unmatched: raw2?.unmatched ?? 0,
|
|
@@ -83144,8 +82957,8 @@ function createWorkspaceEngine(opts) {
|
|
|
83144
82957
|
duplicate += d.duplicate;
|
|
83145
82958
|
selfGated += d.selfGated;
|
|
83146
82959
|
const missing = new Set(d.unmatchedIds);
|
|
83147
|
-
for (const
|
|
83148
|
-
if (missing.has(
|
|
82960
|
+
for (const it of items2) {
|
|
82961
|
+
if (missing.has(it.nodeId)) stillUnmatched.push({ channel, ...it, sessionKey: session, counted: isShipped(it.nodeId) });
|
|
83149
82962
|
else settled.add(it.witnessKey);
|
|
83150
82963
|
}
|
|
83151
82964
|
} catch (err2) {
|
|
@@ -83315,10 +83128,6 @@ function createWorkspaceEngine(opts) {
|
|
|
83315
83128
|
// but nothing judgeable was cited.
|
|
83316
83129
|
tagsVerdictNoHandle: dispositions.verdictNoHandle,
|
|
83317
83130
|
tagsFlagAsHandle: dispositions.flagAsHandle,
|
|
83318
|
-
tagsInvalidVulnerability: dispositions.invalidVulnerability,
|
|
83319
|
-
vulnerabilitiesSeen,
|
|
83320
|
-
vulnerabilitiesMinted,
|
|
83321
|
-
vulnerabilitiesSuspected,
|
|
83322
83131
|
unresolvedHandles,
|
|
83323
83132
|
priorEdgesFlagOff,
|
|
83324
83133
|
priorEdgesNoSource,
|
|
@@ -83386,7 +83195,7 @@ function createWorkspaceEngine(opts) {
|
|
|
83386
83195
|
}
|
|
83387
83196
|
turns = next.turns;
|
|
83388
83197
|
nextOffset = next.nextOffset;
|
|
83389
|
-
await new Promise((
|
|
83198
|
+
await new Promise((resolve8) => setImmediate(resolve8));
|
|
83390
83199
|
}
|
|
83391
83200
|
};
|
|
83392
83201
|
const seenMessageIds = /* @__PURE__ */ new Set();
|
|
@@ -84013,6 +83822,7 @@ B: ${b}`,
|
|
|
84013
83822
|
|
|
84014
83823
|
// src/daemon.ts
|
|
84015
83824
|
async function startDaemon(opts) {
|
|
83825
|
+
const processStartedAt = Date.now();
|
|
84016
83826
|
const cfg = loadConfig();
|
|
84017
83827
|
const merged = { ...cfg, cloudUrl: opts.cloudUrl ?? cfg.cloudUrl };
|
|
84018
83828
|
if (opts.apiKey) {
|
|
@@ -84036,7 +83846,7 @@ async function startDaemon(opts) {
|
|
|
84036
83846
|
const writeLockFile = (url2) => {
|
|
84037
83847
|
writeFileSync23(
|
|
84038
83848
|
engine.paths.daemonLock,
|
|
84039
|
-
|
|
83849
|
+
daemonLockPayload({ pid: process.pid, webUiUrl: url2, processStartedAt, version: DAEMON_VERSION }),
|
|
84040
83850
|
"utf8"
|
|
84041
83851
|
);
|
|
84042
83852
|
};
|
|
@@ -84085,9 +83895,9 @@ async function startDaemon(opts) {
|
|
|
84085
83895
|
};
|
|
84086
83896
|
}
|
|
84087
83897
|
async function listenServer(fetchFn, port) {
|
|
84088
|
-
return new Promise((
|
|
83898
|
+
return new Promise((resolve8) => {
|
|
84089
83899
|
const server = serve({ fetch: fetchFn, hostname: "127.0.0.1", port }, (info2) => {
|
|
84090
|
-
|
|
83900
|
+
resolve8({ server, port: info2.port });
|
|
84091
83901
|
});
|
|
84092
83902
|
});
|
|
84093
83903
|
}
|
|
@@ -84278,7 +84088,7 @@ function instanceReceiptSequence(n) {
|
|
|
84278
84088
|
// src/multi.ts
|
|
84279
84089
|
init_dist();
|
|
84280
84090
|
init_src5();
|
|
84281
|
-
import { existsSync as existsSync33, readFileSync as readFileSync35, unlinkSync as
|
|
84091
|
+
import { existsSync as existsSync33, readFileSync as readFileSync35, unlinkSync as unlinkSync5, writeFileSync as writeFileSync25 } from "node:fs";
|
|
84282
84092
|
import { resolve as pathResolve } from "node:path";
|
|
84283
84093
|
|
|
84284
84094
|
// src/principle-sync.ts
|
|
@@ -84655,7 +84465,7 @@ function internalSymbolsFor(description, lexiconHas, publicIndex) {
|
|
|
84655
84465
|
|
|
84656
84466
|
// src/instance-ingest.ts
|
|
84657
84467
|
init_generalize_graph();
|
|
84658
|
-
var INSTANCE_LABELS = ["Problem", "
|
|
84468
|
+
var INSTANCE_LABELS = ["Problem", "Solution", "RootCause"];
|
|
84659
84469
|
var INSTANCE_EDGES = ["CAUSED_BY", "SOLVED_BY"];
|
|
84660
84470
|
var ANCHOR_EDGES = ["OCCURS_IN", "DEPENDS_ON", "PERTAIN_TO", "CONCERNS"];
|
|
84661
84471
|
var ANCHOR_TARGET_LABELS = ["Language", "Package", "Domain", "Component"];
|
|
@@ -84790,10 +84600,6 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
|
|
|
84790
84600
|
attrs: {
|
|
84791
84601
|
scope: stripCodebaseScope(n.attrs["scope"]),
|
|
84792
84602
|
...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"] } : {},
|
|
84797
84603
|
...n.attrs["resolvedAs"] ? { resolvedAs: n.attrs["resolvedAs"] } : {},
|
|
84798
84604
|
...preserved.length > 0 ? { preservedSymbols: preserved } : {},
|
|
84799
84605
|
...internal.length > 0 ? { internalSymbols: internal } : {}
|
|
@@ -84808,7 +84614,6 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
|
|
|
84808
84614
|
const semanticEndpoints = /* @__PURE__ */ new Map();
|
|
84809
84615
|
const includedByLabel = /* @__PURE__ */ new Map();
|
|
84810
84616
|
const composition = {
|
|
84811
|
-
privateTargetMissing: 0,
|
|
84812
84617
|
candidates: 0,
|
|
84813
84618
|
shipped: 0,
|
|
84814
84619
|
cloudSourced: 0,
|
|
@@ -84854,15 +84659,11 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
|
|
|
84854
84659
|
if (walked.has(n.id)) continue;
|
|
84855
84660
|
walked.add(n.id);
|
|
84856
84661
|
composition.candidates++;
|
|
84857
|
-
if ((n.attrs["privateFinding"] || n.label === "Vulnerability") && !opts.project) {
|
|
84858
|
-
composition.privateTargetMissing++;
|
|
84859
|
-
continue;
|
|
84860
|
-
}
|
|
84861
84662
|
if (n.attrs["source"] === "cloud") {
|
|
84862
84663
|
composition.cloudSourced++;
|
|
84863
84664
|
continue;
|
|
84864
84665
|
}
|
|
84865
|
-
if (n.attrs["resolvedAs"] === PROBLEM_RESOLUTION.FALSE_POSITIVE) {
|
|
84666
|
+
if (label === "Problem" && n.attrs["resolvedAs"] === PROBLEM_RESOLUTION.FALSE_POSITIVE) {
|
|
84866
84667
|
composition.falsePositive++;
|
|
84867
84668
|
continue;
|
|
84868
84669
|
}
|
|
@@ -84885,7 +84686,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
|
|
|
84885
84686
|
composition.terminalRefused++;
|
|
84886
84687
|
continue;
|
|
84887
84688
|
}
|
|
84888
|
-
if (!
|
|
84689
|
+
if (!noveltyAgainst(n, ref, noveltyOpts).ready) {
|
|
84889
84690
|
composition.notNovel++;
|
|
84890
84691
|
continue;
|
|
84891
84692
|
}
|
|
@@ -84928,7 +84729,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
|
|
|
84928
84729
|
}
|
|
84929
84730
|
if (targets.length === 0) continue;
|
|
84930
84731
|
const shipped = shippedById.get(sourceId);
|
|
84931
|
-
if (shipped
|
|
84732
|
+
if (shipped) {
|
|
84932
84733
|
const anchors = (label) => targets.filter((x) => x.t.label === label).map(
|
|
84933
84734
|
(x) => label === "Language" ? langAnchor(x.t) : label === "Component" ? `component:${x.wireId}` : x.wireId
|
|
84934
84735
|
).filter((a) => a != null).sort();
|
|
@@ -85300,8 +85101,8 @@ var ConsolidateWorker = class {
|
|
|
85300
85101
|
const id = this.nextId++;
|
|
85301
85102
|
try {
|
|
85302
85103
|
await this.ready;
|
|
85303
|
-
return await new Promise((
|
|
85304
|
-
this.pending.set(id, { resolve:
|
|
85104
|
+
return await new Promise((resolve8, reject) => {
|
|
85105
|
+
this.pending.set(id, { resolve: resolve8, reject });
|
|
85305
85106
|
this.worker.postMessage({ ...req, id });
|
|
85306
85107
|
});
|
|
85307
85108
|
} finally {
|
|
@@ -85330,12 +85131,12 @@ var ConsolidateWorker = class {
|
|
|
85330
85131
|
});
|
|
85331
85132
|
noteIsolateSpawned();
|
|
85332
85133
|
this.worker = worker;
|
|
85333
|
-
this.ready = new Promise((
|
|
85134
|
+
this.ready = new Promise((resolve8, reject) => {
|
|
85334
85135
|
const onReady = (m) => {
|
|
85335
85136
|
if (m?.ready) {
|
|
85336
85137
|
worker.off("message", onReady);
|
|
85337
85138
|
worker.off("error", onErr);
|
|
85338
|
-
|
|
85139
|
+
resolve8();
|
|
85339
85140
|
}
|
|
85340
85141
|
};
|
|
85341
85142
|
const onErr = (err2) => {
|
|
@@ -85420,6 +85221,7 @@ init_config();
|
|
|
85420
85221
|
|
|
85421
85222
|
// src/update.ts
|
|
85422
85223
|
import { spawn as spawn2 } from "node:child_process";
|
|
85224
|
+
import { isAbsolute as isAbsolute5, join as join38 } from "node:path";
|
|
85423
85225
|
var PACKAGE_NAME = "@inerrata-corporation/errata";
|
|
85424
85226
|
function parse3(v) {
|
|
85425
85227
|
const m = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z][0-9A-Za-z.-]*))?/.exec(v.trim());
|
|
@@ -85539,13 +85341,40 @@ function startUpdatePoller(opts) {
|
|
|
85539
85341
|
};
|
|
85540
85342
|
}
|
|
85541
85343
|
function runNpmInstall(channel) {
|
|
85542
|
-
return new Promise((
|
|
85344
|
+
return new Promise((resolve8) => {
|
|
85543
85345
|
const child = spawn2("npm", ["install", "-g", `${PACKAGE_NAME}@${channel}`], {
|
|
85544
85346
|
stdio: "inherit",
|
|
85545
85347
|
shell: true
|
|
85546
85348
|
});
|
|
85547
|
-
child.on("close", (code) =>
|
|
85548
|
-
child.on("error", () =>
|
|
85349
|
+
child.on("close", (code) => resolve8(code ?? 1));
|
|
85350
|
+
child.on("error", () => resolve8(1));
|
|
85351
|
+
});
|
|
85352
|
+
}
|
|
85353
|
+
async function runInstalledHookRefresh() {
|
|
85354
|
+
const root = await new Promise((resolve8) => {
|
|
85355
|
+
const child = spawn2("npm", ["root", "-g"], {
|
|
85356
|
+
shell: true,
|
|
85357
|
+
windowsHide: true,
|
|
85358
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
85359
|
+
timeout: 15e3
|
|
85360
|
+
});
|
|
85361
|
+
let output = "";
|
|
85362
|
+
child.stdout.on("data", (chunk) => {
|
|
85363
|
+
output += chunk;
|
|
85364
|
+
if (output.length > 32768) child.kill();
|
|
85365
|
+
});
|
|
85366
|
+
child.on("error", () => resolve8(""));
|
|
85367
|
+
child.on("close", (code) => resolve8(code === 0 ? output.trim() : ""));
|
|
85368
|
+
});
|
|
85369
|
+
if (!isAbsolute5(root)) return 1;
|
|
85370
|
+
return new Promise((resolve8) => {
|
|
85371
|
+
const child = spawn2(process.execPath, [join38(root, PACKAGE_NAME, "errata.mjs"), "install-hooks", "codex", "--refresh-existing"], {
|
|
85372
|
+
windowsHide: true,
|
|
85373
|
+
stdio: "inherit",
|
|
85374
|
+
timeout: 3e4
|
|
85375
|
+
});
|
|
85376
|
+
child.on("error", () => resolve8(1));
|
|
85377
|
+
child.on("close", (code) => resolve8(code ?? 1));
|
|
85549
85378
|
});
|
|
85550
85379
|
}
|
|
85551
85380
|
|
|
@@ -85560,7 +85389,7 @@ function liveCloudClient(src) {
|
|
|
85560
85389
|
let current = null;
|
|
85561
85390
|
let currentKey = "";
|
|
85562
85391
|
let checkedAt = -Infinity;
|
|
85563
|
-
const
|
|
85392
|
+
const resolve8 = () => {
|
|
85564
85393
|
const t = now();
|
|
85565
85394
|
if (current && t - checkedAt < recheckMs) return current;
|
|
85566
85395
|
checkedAt = t;
|
|
@@ -85580,7 +85409,7 @@ function liveCloudClient(src) {
|
|
|
85580
85409
|
};
|
|
85581
85410
|
return new Proxy({}, {
|
|
85582
85411
|
get(_target, prop) {
|
|
85583
|
-
const client =
|
|
85412
|
+
const client = resolve8();
|
|
85584
85413
|
const value = Reflect.get(client, prop, client);
|
|
85585
85414
|
return typeof value === "function" ? value.bind(client) : value;
|
|
85586
85415
|
}
|
|
@@ -86015,7 +85844,7 @@ async function syncHistoryRevision(opts) {
|
|
|
86015
85844
|
changed += result.changed;
|
|
86016
85845
|
remaining = result.remaining;
|
|
86017
85846
|
if (!remaining || Date.now() - started2 >= (opts.budgetMs ?? 45e3)) break;
|
|
86018
|
-
await new Promise((
|
|
85847
|
+
await new Promise((resolve8) => setImmediate(resolve8));
|
|
86019
85848
|
}
|
|
86020
85849
|
return { changed, remaining };
|
|
86021
85850
|
})();
|
|
@@ -86119,7 +85948,7 @@ init_src7();
|
|
|
86119
85948
|
init_src();
|
|
86120
85949
|
import { execFile as execFile5 } from "node:child_process";
|
|
86121
85950
|
import { readFileSync as readFileSync34 } from "node:fs";
|
|
86122
|
-
import { join as
|
|
85951
|
+
import { join as join39 } from "node:path";
|
|
86123
85952
|
import { promisify as promisify3 } from "node:util";
|
|
86124
85953
|
|
|
86125
85954
|
// src/history-walk.ts
|
|
@@ -86519,8 +86348,8 @@ var GitBlobReader = class {
|
|
|
86519
86348
|
if (this.failed) return Promise.reject(this.failed);
|
|
86520
86349
|
if (/[\r\n]/.test(spec)) return Promise.resolve(null);
|
|
86521
86350
|
const proc = this.start();
|
|
86522
|
-
return new Promise((
|
|
86523
|
-
this.queue.push({ resolve:
|
|
86351
|
+
return new Promise((resolve8, reject) => {
|
|
86352
|
+
this.queue.push({ resolve: resolve8, reject });
|
|
86524
86353
|
proc.stdin.write(`${spec}
|
|
86525
86354
|
`);
|
|
86526
86355
|
});
|
|
@@ -86534,14 +86363,14 @@ var GitBlobReader = class {
|
|
|
86534
86363
|
const proc = this.proc;
|
|
86535
86364
|
this.proc = null;
|
|
86536
86365
|
if (!proc || proc.exitCode !== null) return Promise.resolve();
|
|
86537
|
-
return new Promise((
|
|
86366
|
+
return new Promise((resolve8) => {
|
|
86538
86367
|
const timer = setTimeout(() => {
|
|
86539
86368
|
proc.kill();
|
|
86540
|
-
|
|
86369
|
+
resolve8();
|
|
86541
86370
|
}, timeoutMs);
|
|
86542
86371
|
proc.once("exit", () => {
|
|
86543
86372
|
clearTimeout(timer);
|
|
86544
|
-
|
|
86373
|
+
resolve8();
|
|
86545
86374
|
});
|
|
86546
86375
|
proc.stdin.end();
|
|
86547
86376
|
});
|
|
@@ -86666,7 +86495,7 @@ async function defaultGit(root, args2) {
|
|
|
86666
86495
|
function readIgnoreLines(root, profile) {
|
|
86667
86496
|
let lines = [];
|
|
86668
86497
|
try {
|
|
86669
|
-
lines = readFileSync34(
|
|
86498
|
+
lines = readFileSync34(join39(root, ".errataignore"), "utf8").split("\n");
|
|
86670
86499
|
} catch {
|
|
86671
86500
|
}
|
|
86672
86501
|
return [...lines, ...profile.ignoreExtra ?? []].map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
|
|
@@ -87097,7 +86926,7 @@ init_cloud_auth();
|
|
|
87097
86926
|
import { createHash as createHash19 } from "node:crypto";
|
|
87098
86927
|
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
87099
86928
|
import { existsSync as existsSync31, writeFileSync as writeFileSync24 } from "node:fs";
|
|
87100
|
-
import { join as
|
|
86929
|
+
import { join as join40 } from "node:path";
|
|
87101
86930
|
|
|
87102
86931
|
// src/device-poll.ts
|
|
87103
86932
|
var THROTTLED_POLL_MIN_WAIT_MS = 11e3;
|
|
@@ -87186,7 +87015,7 @@ async function loginOAuthDevice(opts) {
|
|
|
87186
87015
|
let deviceSession = null;
|
|
87187
87016
|
let approvedInstallation = null;
|
|
87188
87017
|
while (Date.now() < deadline) {
|
|
87189
|
-
await (opts.sleep ?? ((ms) => new Promise((
|
|
87018
|
+
await (opts.sleep ?? ((ms) => new Promise((resolve8) => setTimeout(resolve8, ms))))(waitMs);
|
|
87190
87019
|
waitMs = intervalMs;
|
|
87191
87020
|
const poll = await fetchDevicePoll(fetchFn, device.token, {
|
|
87192
87021
|
method: "POST",
|
|
@@ -87311,7 +87140,7 @@ async function loginOAuthLoopback(opts) {
|
|
|
87311
87140
|
const state = randomState();
|
|
87312
87141
|
const scope = opts.scope ?? DEFAULT_OAUTH_SCOPE;
|
|
87313
87142
|
const { code, redirectUri, clientId } = await new Promise(
|
|
87314
|
-
(
|
|
87143
|
+
(resolve8, reject) => {
|
|
87315
87144
|
const server = createServer((req, res) => {
|
|
87316
87145
|
const u = new URL(req.url ?? "/", "http://127.0.0.1");
|
|
87317
87146
|
if (u.pathname !== "/callback") {
|
|
@@ -87334,7 +87163,7 @@ async function loginOAuthLoopback(opts) {
|
|
|
87334
87163
|
res.writeHead(200, { "content-type": "text/html" });
|
|
87335
87164
|
res.end("<html><body>inErrata: you're logged in. You can close this tab.</body></html>");
|
|
87336
87165
|
server.close();
|
|
87337
|
-
|
|
87166
|
+
resolve8({ code: code2, redirectUri: `http://127.0.0.1:${port}/callback`, clientId: activeClientId });
|
|
87338
87167
|
});
|
|
87339
87168
|
let activeClientId = oauthClientId();
|
|
87340
87169
|
server.on("error", reject);
|
|
@@ -87433,7 +87262,7 @@ async function linkThroughConsole(opts) {
|
|
|
87433
87262
|
const deadline = Date.now() + Math.min(code.expires_in * 1e3, opts.timeoutMs ?? Number.POSITIVE_INFINITY);
|
|
87434
87263
|
let intervalMs = Math.max(2, code.interval ?? 5) * 1e3;
|
|
87435
87264
|
let waitMs = intervalMs;
|
|
87436
|
-
const sleep = opts.sleep ?? ((ms) => new Promise((
|
|
87265
|
+
const sleep = opts.sleep ?? ((ms) => new Promise((resolve8) => setTimeout(resolve8, ms)));
|
|
87437
87266
|
while (Date.now() < deadline) {
|
|
87438
87267
|
await sleep(waitMs);
|
|
87439
87268
|
waitMs = intervalMs;
|
|
@@ -87555,7 +87384,7 @@ function applyLinkDecision(root, profile, config2, decision, now = Date.now) {
|
|
|
87555
87384
|
delete nextProfile.projectLinkHold;
|
|
87556
87385
|
let wroteIgnore = false;
|
|
87557
87386
|
if (decision.writeIgnoreStarter !== false) {
|
|
87558
|
-
const target =
|
|
87387
|
+
const target = join40(root, ".errataignore");
|
|
87559
87388
|
if (!existsSync31(target)) {
|
|
87560
87389
|
writeFileSync24(target, IGNORE_STARTER, "utf8");
|
|
87561
87390
|
wroteIgnore = true;
|
|
@@ -87571,11 +87400,11 @@ init_registry();
|
|
|
87571
87400
|
// src/adopt.ts
|
|
87572
87401
|
init_git_remote();
|
|
87573
87402
|
import { existsSync as existsSync32 } from "node:fs";
|
|
87574
|
-
import { dirname as dirname12, join as
|
|
87403
|
+
import { dirname as dirname12, join as join41 } from "node:path";
|
|
87575
87404
|
function findGitRoot(absPath) {
|
|
87576
87405
|
let dir = absPath;
|
|
87577
87406
|
for (let depth = 0; depth < 64; depth++) {
|
|
87578
|
-
if (existsSync32(
|
|
87407
|
+
if (existsSync32(join41(dir, ".git"))) return dir;
|
|
87579
87408
|
const parent = dirname12(dir);
|
|
87580
87409
|
if (parent === dir) return null;
|
|
87581
87410
|
dir = parent;
|
|
@@ -88868,7 +88697,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
88868
88697
|
const packageAutoAll = async () => {
|
|
88869
88698
|
const out2 = /* @__PURE__ */ new Map();
|
|
88870
88699
|
for (const r of records) {
|
|
88871
|
-
await new Promise((
|
|
88700
|
+
await new Promise((resolve8) => setImmediate(resolve8));
|
|
88872
88701
|
const done = markPass(`package-index:${r.entry.name}`);
|
|
88873
88702
|
try {
|
|
88874
88703
|
out2.set(
|
|
@@ -89607,7 +89436,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
89607
89436
|
clearTimeout(codexWakeBoot);
|
|
89608
89437
|
try {
|
|
89609
89438
|
const cur = readFileSync35(lockPath, "utf8");
|
|
89610
|
-
if (JSON.parse(cur).pid === process.pid)
|
|
89439
|
+
if (JSON.parse(cur).pid === process.pid) unlinkSync5(lockPath);
|
|
89611
89440
|
} catch {
|
|
89612
89441
|
}
|
|
89613
89442
|
await new Promise(
|
|
@@ -90030,7 +89859,7 @@ import { spawnSync } from "node:child_process";
|
|
|
90030
89859
|
|
|
90031
89860
|
// src/codex-runtime.ts
|
|
90032
89861
|
import { readdirSync as readdirSync12, statSync as statSync9 } from "node:fs";
|
|
90033
|
-
import { join as
|
|
89862
|
+
import { join as join42 } from "node:path";
|
|
90034
89863
|
function resolveCodexExecutable(options = {}) {
|
|
90035
89864
|
const platform = options.platform ?? process.platform;
|
|
90036
89865
|
const env2 = options.env ?? process.env;
|
|
@@ -90045,13 +89874,13 @@ function resolveCodexExecutable(options = {}) {
|
|
|
90045
89874
|
};
|
|
90046
89875
|
for (const dir of (env2["PATH"] ?? env2["Path"] ?? "").split(";")) {
|
|
90047
89876
|
if (!dir.trim()) continue;
|
|
90048
|
-
const path2 =
|
|
89877
|
+
const path2 = join42(dir.trim().replace(/^"|"$/g, ""), "codex.exe");
|
|
90049
89878
|
if (fileTime(path2) !== null) return path2;
|
|
90050
89879
|
}
|
|
90051
89880
|
if (!env2["LOCALAPPDATA"]) return "codex";
|
|
90052
|
-
const root =
|
|
89881
|
+
const root = join42(env2["LOCALAPPDATA"], "OpenAI", "Codex", "bin");
|
|
90053
89882
|
try {
|
|
90054
|
-
const candidates = readdirSync12(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) =>
|
|
89883
|
+
const candidates = readdirSync12(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join42(root, entry.name, "codex.exe")).map((path2) => ({ path: path2, mtime: fileTime(path2) })).filter((candidate) => candidate.mtime !== null).sort((a, b) => b.mtime - a.mtime || a.path.localeCompare(b.path));
|
|
90055
89884
|
return candidates[0]?.path ?? "codex";
|
|
90056
89885
|
} catch {
|
|
90057
89886
|
return "codex";
|
|
@@ -90167,12 +89996,14 @@ async function diagnoseInstallation(cfg, dependencies) {
|
|
|
90167
89996
|
|
|
90168
89997
|
// src/codex-doctor.ts
|
|
90169
89998
|
import { spawn as spawn4 } from "node:child_process";
|
|
89999
|
+
import { readFileSync as readFileSync37, statSync as statSync10 } from "node:fs";
|
|
90000
|
+
import { join as join44 } from "node:path";
|
|
90170
90001
|
import { createInterface } from "node:readline";
|
|
90171
90002
|
|
|
90172
90003
|
// src/codex-hooks.ts
|
|
90173
|
-
import { existsSync as existsSync34, mkdirSync as mkdirSync9, readFileSync as readFileSync36, writeFileSync as writeFileSync26 } from "node:fs";
|
|
90004
|
+
import { existsSync as existsSync34, mkdirSync as mkdirSync9, readFileSync as readFileSync36, renameSync as renameSync5, unlinkSync as unlinkSync6, writeFileSync as writeFileSync26 } from "node:fs";
|
|
90174
90005
|
import { homedir as homedir7 } from "node:os";
|
|
90175
|
-
import { join as
|
|
90006
|
+
import { join as join43 } from "node:path";
|
|
90176
90007
|
|
|
90177
90008
|
// src/hook-commands.ts
|
|
90178
90009
|
function hookCurlCommand(port, path2 = "/api/hook") {
|
|
@@ -90211,9 +90042,12 @@ function buildCodexHooksToml(port, options) {
|
|
|
90211
90042
|
|
|
90212
90043
|
// src/codex-hook-relay.ts
|
|
90213
90044
|
var CODEX_RELAY_SOURCE = String.raw`// errata-managed: regenerated by errata install-hooks codex
|
|
90214
|
-
import { readFileSync, statSync } from 'node:fs';
|
|
90045
|
+
import { mkdirSync, readFileSync, renameSync, statSync, writeFileSync } from 'node:fs';
|
|
90046
|
+
import { createHash } from 'node:crypto';
|
|
90215
90047
|
import { join } from 'node:path';
|
|
90216
90048
|
const workspaceRoot = null;
|
|
90049
|
+
// Stdout closing early is not delivery. Never stamp a receipt on EPIPE.
|
|
90050
|
+
process.stdout.on('error', () => process.exit(0));
|
|
90217
90051
|
|
|
90218
90052
|
try {
|
|
90219
90053
|
const payload = JSON.parse(readFileSync(0, 'utf8') || '{}');
|
|
@@ -90225,6 +90059,19 @@ try {
|
|
|
90225
90059
|
if (!Number.isInteger(port) || port < 1 || port > 65535) process.exit(0);
|
|
90226
90060
|
const contexts = [];
|
|
90227
90061
|
const messages = [];
|
|
90062
|
+
const hash = (text) => createHash('sha256').update(text).digest('hex');
|
|
90063
|
+
const boundedRead = (path, max) => statSync(path).size <= max ? readFileSync(path, 'utf8') : '';
|
|
90064
|
+
const stateDir = workspaceRoot && join(workspaceRoot, '.errata', 'codex-hook-state');
|
|
90065
|
+
const statePath = stateDir && typeof payload.session_id === 'string' && payload.session_id
|
|
90066
|
+
? join(stateDir, hash(payload.session_id) + '.json') : null;
|
|
90067
|
+
let previous = {};
|
|
90068
|
+
try {
|
|
90069
|
+
if (statePath) {
|
|
90070
|
+
const saved = JSON.parse(boundedRead(statePath, 4096));
|
|
90071
|
+
if (saved && typeof saved === 'object') previous = saved;
|
|
90072
|
+
}
|
|
90073
|
+
} catch {}
|
|
90074
|
+
let receipt = null;
|
|
90228
90075
|
const post = async (endpoint, relay = false) => {
|
|
90229
90076
|
try {
|
|
90230
90077
|
const response = await fetch('http://127.0.0.1:' + port + '/api/' + endpoint, {
|
|
@@ -90244,33 +90091,52 @@ try {
|
|
|
90244
90091
|
if (event === 'PreToolUse' || event === 'PostToolUse') await post('hook', true);
|
|
90245
90092
|
// Stop sees the final assistant message, including turns with no tools.
|
|
90246
90093
|
if (event === 'PostToolUse' || event === 'Stop') await post('turn');
|
|
90247
|
-
if (['SessionStart', 'UserPromptSubmit'
|
|
90248
|
-
//
|
|
90249
|
-
//
|
|
90250
|
-
|
|
90251
|
-
|
|
90252
|
-
|
|
90253
|
-
|
|
90254
|
-
|
|
90255
|
-
|
|
90256
|
-
|
|
90257
|
-
|
|
90258
|
-
|
|
90259
|
-
|
|
90260
|
-
|
|
90261
|
-
|
|
90262
|
-
|
|
90263
|
-
|
|
90094
|
+
if (['SessionStart', 'UserPromptSubmit'].includes(event)) {
|
|
90095
|
+
// Wake/route the engine, bounded independently of context delivery. Older
|
|
90096
|
+
// daemons may stamp their HTTP dedup gate before a timed-out response arrives;
|
|
90097
|
+
// that gate is deliberately NOT authoritative for this file-based relay.
|
|
90098
|
+
await post('context-inject', !workspaceRoot);
|
|
90099
|
+
}
|
|
90100
|
+
if (workspaceRoot && ['SessionStart', 'UserPromptSubmit', 'PostToolUse'].includes(event)) {
|
|
90101
|
+
let body = '';
|
|
90102
|
+
try { body = boundedRead(join(workspaceRoot, '.errata', 'context.md'), 128 * 1024).trim(); } catch {}
|
|
90103
|
+
if (body) {
|
|
90104
|
+
const digest = hash(body.replace(/\r\n?/g, '\n')).slice(0, 16);
|
|
90105
|
+
// Receipt is local to this graph + session, survives daemon restarts, and
|
|
90106
|
+
// records stdout emission, not a server's intention to send a response.
|
|
90107
|
+
if (event === 'SessionStart' || previous.hash !== digest) {
|
|
90108
|
+
contexts.push('Errata loaded the maintained local workspace context. This block REPLACES any earlier errata context block in this conversation. It is the latest saved snapshot; the daemon maintains it as work proceeds.\n\n' + body);
|
|
90109
|
+
if (!/^(0|off|false|no)$/i.test((process.env.ERRATA_RECALL_CARD || '').trim())) {
|
|
90110
|
+
try {
|
|
90111
|
+
const card = JSON.parse(boundedRead(join(workspaceRoot, '.errata', 'context-card.json'), 128 * 1024));
|
|
90112
|
+
if (card.hash === digest && typeof card.line === 'string' && card.line) messages.push(card.line);
|
|
90113
|
+
} catch { /* Never show a card for a different snapshot. */ }
|
|
90264
90114
|
}
|
|
90265
|
-
|
|
90115
|
+
receipt = { hash: digest, at: Date.now() };
|
|
90116
|
+
}
|
|
90117
|
+
} else if (event === 'SessionStart' || !previous.unavailable) {
|
|
90118
|
+
messages.push('errata: workspace priors are unavailable; run errata doctor in this checkout.');
|
|
90119
|
+
receipt = { unavailable: true, at: Date.now() };
|
|
90266
90120
|
}
|
|
90121
|
+
} else if (!workspaceRoot && event === 'PostToolUse') {
|
|
90122
|
+
await post('context-inject', true);
|
|
90267
90123
|
}
|
|
90268
90124
|
if (contexts.length || messages.length) {
|
|
90269
|
-
process.stdout.write(JSON.stringify({
|
|
90125
|
+
await new Promise((resolve) => process.stdout.write(JSON.stringify({
|
|
90270
90126
|
...(messages.length ? { systemMessage: messages.join('\n\n') } : {}),
|
|
90271
90127
|
...(contexts.length ? { hookSpecificOutput: {
|
|
90272
90128
|
hookEventName: event, additionalContext: contexts.join('\n\n'),
|
|
90273
90129
|
} } : {}),
|
|
90130
|
+
}), (error) => {
|
|
90131
|
+
if (!error && receipt && statePath) {
|
|
90132
|
+
try {
|
|
90133
|
+
mkdirSync(stateDir, { recursive: true });
|
|
90134
|
+
const temp = statePath + '.' + process.pid + '.tmp';
|
|
90135
|
+
writeFileSync(temp, JSON.stringify(receipt), { mode: 0o600 });
|
|
90136
|
+
renameSync(temp, statePath);
|
|
90137
|
+
} catch { /* Read-only workspace: retry next time rather than drop context. */ }
|
|
90138
|
+
}
|
|
90139
|
+
resolve();
|
|
90274
90140
|
}));
|
|
90275
90141
|
}
|
|
90276
90142
|
} catch { /* Invalid input is also fail-open. */ }
|
|
@@ -90282,8 +90148,35 @@ function buildCodexRelaySource(workspaceRoot) {
|
|
|
90282
90148
|
// src/codex-hooks.ts
|
|
90283
90149
|
init_checkout_root();
|
|
90284
90150
|
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.";
|
|
90285
|
-
function
|
|
90286
|
-
|
|
90151
|
+
function writeRelay(file2, source) {
|
|
90152
|
+
if (existsSync34(file2) && readFileSync36(file2, "utf8") === source) return;
|
|
90153
|
+
const temp = `${file2}.${process.pid}.tmp`;
|
|
90154
|
+
try {
|
|
90155
|
+
writeFileSync26(temp, source, { encoding: "utf8", mode: 384 });
|
|
90156
|
+
renameSync5(temp, file2);
|
|
90157
|
+
} finally {
|
|
90158
|
+
if (existsSync34(temp)) unlinkSync6(temp);
|
|
90159
|
+
}
|
|
90160
|
+
}
|
|
90161
|
+
function refreshCodexRelay(root) {
|
|
90162
|
+
const config2 = join43(root, ".codex", "config.toml");
|
|
90163
|
+
if (!existsSync34(config2)) return "absent";
|
|
90164
|
+
const existing = readFileSync36(config2, "utf8");
|
|
90165
|
+
if (!existing.includes(CODEX_HOOKS_BEGIN) && !existing.includes(CODEX_HOOKS_END)) return "absent";
|
|
90166
|
+
replaceCodexHooks(existing, "");
|
|
90167
|
+
const relay = join43(root, ".codex", "hooks", "errata-relay.mjs");
|
|
90168
|
+
const prior = existsSync34(relay) ? readFileSync36(relay, "utf8") : "";
|
|
90169
|
+
if (prior && !prior.startsWith("// errata-managed: regenerated by errata install-hooks codex")) {
|
|
90170
|
+
throw new Error("Codex relay is not Errata-managed; preserved it. Run errata install-hooks codex to explicitly replace it.");
|
|
90171
|
+
}
|
|
90172
|
+
const source = buildCodexRelaySource(checkoutRootOf(root));
|
|
90173
|
+
if (prior === source) return "current";
|
|
90174
|
+
mkdirSync9(join43(root, ".codex", "hooks"), { recursive: true });
|
|
90175
|
+
writeRelay(relay, source);
|
|
90176
|
+
return "updated";
|
|
90177
|
+
}
|
|
90178
|
+
function hasCodexConfig(root, codexHome = process.env["CODEX_HOME"] || join43(homedir7(), ".codex")) {
|
|
90179
|
+
return existsSync34(join43(root, ".codex")) || existsSync34(codexHome);
|
|
90287
90180
|
}
|
|
90288
90181
|
function replaceCodexHooks(existing, block) {
|
|
90289
90182
|
const begin = existing.indexOf(CODEX_HOOKS_BEGIN);
|
|
@@ -90299,20 +90192,43 @@ function replaceCodexHooks(existing, block) {
|
|
|
90299
90192
|
return existing.trimEnd() + (existing.trim() ? "\n\n" : "") + block;
|
|
90300
90193
|
}
|
|
90301
90194
|
function writeCodexHooks(root, port, nodePath = process.execPath) {
|
|
90302
|
-
const dir =
|
|
90303
|
-
const file2 =
|
|
90304
|
-
const relay =
|
|
90195
|
+
const dir = join43(root, ".codex");
|
|
90196
|
+
const file2 = join43(dir, "config.toml");
|
|
90197
|
+
const relay = join43(dir, "hooks", "errata-relay.mjs");
|
|
90305
90198
|
const block = buildCodexHooksToml(port, { nodePath, relayPath: relay });
|
|
90306
90199
|
const final = replaceCodexHooks(existsSync34(file2) ? readFileSync36(file2, "utf8") : "", block);
|
|
90307
|
-
mkdirSync9(
|
|
90308
|
-
|
|
90309
|
-
writeFileSync26(file2, final, "utf8");
|
|
90200
|
+
mkdirSync9(join43(dir, "hooks"), { recursive: true });
|
|
90201
|
+
writeRelay(relay, buildCodexRelaySource(checkoutRootOf(root)));
|
|
90202
|
+
if (!existsSync34(file2) || readFileSync36(file2, "utf8") !== final) writeFileSync26(file2, final, "utf8");
|
|
90310
90203
|
return file2;
|
|
90311
90204
|
}
|
|
90312
90205
|
|
|
90313
90206
|
// src/codex-doctor.ts
|
|
90207
|
+
init_checkout_root();
|
|
90208
|
+
function inspectCodexRelay(cwd) {
|
|
90209
|
+
const root = nearestGitRoot(cwd) ?? cwd;
|
|
90210
|
+
try {
|
|
90211
|
+
const source = readFileSync37(join44(root, ".codex", "hooks", "errata-relay.mjs"), "utf8");
|
|
90212
|
+
if (source === buildCodexRelaySource(checkoutRootOf(root))) {
|
|
90213
|
+
return { id: "codex_relay", status: "pass", detail: "Installed Codex relay matches this Errata version" };
|
|
90214
|
+
}
|
|
90215
|
+
} catch {
|
|
90216
|
+
}
|
|
90217
|
+
return { id: "codex_relay", status: "fail", detail: "Codex relay is missing or outdated; run errata install-hooks codex --refresh-existing, or errata install-hooks codex for a new setup" };
|
|
90218
|
+
}
|
|
90219
|
+
function inspectCodexContext(cwd) {
|
|
90220
|
+
const root = checkoutRootOf(nearestGitRoot(cwd) ?? cwd);
|
|
90221
|
+
try {
|
|
90222
|
+
const file2 = join44(root, ".errata", "context.md");
|
|
90223
|
+
if (statSync10(file2).size <= 128 * 1024 && readFileSync37(file2, "utf8").trim()) {
|
|
90224
|
+
return { id: "codex_context", status: "pass", detail: "Saved workspace context is readable by the relay; this does not prove live daemon freshness" };
|
|
90225
|
+
}
|
|
90226
|
+
} catch {
|
|
90227
|
+
}
|
|
90228
|
+
return { id: "codex_context", status: "fail", detail: "No usable saved workspace context; run errata start here and check the daemon log if context.md remains unavailable" };
|
|
90229
|
+
}
|
|
90314
90230
|
function readCodexHookState(cwd, options = {}) {
|
|
90315
|
-
return new Promise((
|
|
90231
|
+
return new Promise((resolve8, reject) => {
|
|
90316
90232
|
const child = spawn4(options.bin ?? resolveCodexExecutable(), options.args ?? ["app-server", "--stdio"], {
|
|
90317
90233
|
cwd,
|
|
90318
90234
|
windowsHide: true,
|
|
@@ -90328,9 +90244,14 @@ function readCodexHookState(cwd, options = {}) {
|
|
|
90328
90244
|
settled = true;
|
|
90329
90245
|
clearTimeout(timer);
|
|
90330
90246
|
lines.close();
|
|
90247
|
+
const reap = setTimeout(() => child.kill("SIGKILL"), 1e3);
|
|
90248
|
+
reap.unref();
|
|
90249
|
+
child.once("close", () => {
|
|
90250
|
+
clearTimeout(reap);
|
|
90251
|
+
if (error48) reject(error48);
|
|
90252
|
+
else resolve8({ ...hooks, features });
|
|
90253
|
+
});
|
|
90331
90254
|
child.kill();
|
|
90332
|
-
if (error48) reject(error48);
|
|
90333
|
-
else resolve7({ ...hooks, features });
|
|
90334
90255
|
};
|
|
90335
90256
|
const timer = setTimeout(() => finish(new Error("Codex hook inspection timed out")), options.timeoutMs ?? 1e4);
|
|
90336
90257
|
const send = (id, method, params) => {
|
|
@@ -90395,10 +90316,11 @@ function assessCodexHooks(state, platform = process.platform) {
|
|
|
90395
90316
|
return checks.length ? checks : check2("pass", "Codex discovers enabled, trusted Errata hooks; verify live context and capture in a session");
|
|
90396
90317
|
}
|
|
90397
90318
|
async function diagnoseCodexHooks(cwd) {
|
|
90319
|
+
const local = [inspectCodexRelay(cwd), inspectCodexContext(cwd)];
|
|
90398
90320
|
try {
|
|
90399
|
-
return assessCodexHooks(await readCodexHookState(cwd));
|
|
90321
|
+
return [...local, ...assessCodexHooks(await readCodexHookState(cwd))];
|
|
90400
90322
|
} catch (error48) {
|
|
90401
|
-
return [{ id: "codex_hooks", status: "fail", detail: error48 instanceof Error ? error48.message : "Cannot verify Codex hooks" }];
|
|
90323
|
+
return [...local, { id: "codex_hooks", status: "fail", detail: error48 instanceof Error ? error48.message : "Cannot verify Codex hooks" }];
|
|
90402
90324
|
}
|
|
90403
90325
|
}
|
|
90404
90326
|
|
|
@@ -90472,10 +90394,51 @@ function consolidationGapMs(lastPassMs, policy) {
|
|
|
90472
90394
|
return Math.max(policy.baseFloorMs, lastPassMs * policy.dutyFactor);
|
|
90473
90395
|
}
|
|
90474
90396
|
|
|
90397
|
+
// src/codex-hook-refresh.ts
|
|
90398
|
+
init_checkout_root();
|
|
90399
|
+
import { existsSync as existsSync35, readdirSync as readdirSync13, readFileSync as readFileSync38 } from "node:fs";
|
|
90400
|
+
import { dirname as dirname13, join as join45, resolve as resolve7 } from "node:path";
|
|
90401
|
+
init_registry();
|
|
90402
|
+
function codexHookRoots(roots) {
|
|
90403
|
+
const found = new Set(roots.map((root) => resolve7(root)));
|
|
90404
|
+
for (const root of [...found]) {
|
|
90405
|
+
const main2 = mainCheckoutOfWorktree(root) ?? root;
|
|
90406
|
+
found.add(main2);
|
|
90407
|
+
const dir = join45(main2, ".git", "worktrees");
|
|
90408
|
+
if (!existsSync35(dir)) continue;
|
|
90409
|
+
let names;
|
|
90410
|
+
try {
|
|
90411
|
+
names = readdirSync13(dir);
|
|
90412
|
+
} catch {
|
|
90413
|
+
continue;
|
|
90414
|
+
}
|
|
90415
|
+
for (const name2 of names) {
|
|
90416
|
+
try {
|
|
90417
|
+
const checkout = dirname13(readFileSync38(join45(dir, name2, "gitdir"), "utf8").trim());
|
|
90418
|
+
if (mainCheckoutOfWorktree(checkout) === main2) found.add(checkout);
|
|
90419
|
+
} catch {
|
|
90420
|
+
}
|
|
90421
|
+
}
|
|
90422
|
+
}
|
|
90423
|
+
return [...found];
|
|
90424
|
+
}
|
|
90425
|
+
function refreshInstalledCodexRelays(roots = listWorkspaceEntries().map((entry) => entry.path)) {
|
|
90426
|
+
const results = [];
|
|
90427
|
+
for (const root of codexHookRoots(roots)) {
|
|
90428
|
+
try {
|
|
90429
|
+
const status = refreshCodexRelay(root);
|
|
90430
|
+
if (status !== "absent") results.push({ root, status });
|
|
90431
|
+
} catch (error48) {
|
|
90432
|
+
results.push({ root, status: "error", detail: error48 instanceof Error ? error48.message : String(error48) });
|
|
90433
|
+
}
|
|
90434
|
+
}
|
|
90435
|
+
return results;
|
|
90436
|
+
}
|
|
90437
|
+
|
|
90475
90438
|
// src/claude-statusline.ts
|
|
90476
|
-
import { existsSync as
|
|
90439
|
+
import { existsSync as existsSync36, mkdirSync as mkdirSync10, readFileSync as readFileSync39, writeFileSync as writeFileSync27 } from "node:fs";
|
|
90477
90440
|
import { homedir as homedir8 } from "node:os";
|
|
90478
|
-
import { dirname as
|
|
90441
|
+
import { dirname as dirname14, join as join46 } from "node:path";
|
|
90479
90442
|
var STATUSLINE_RELAY_SOURCE = String.raw`// errata-managed: regenerated by errata init / install-hooks claude
|
|
90480
90443
|
import { readFileSync } from 'node:fs';
|
|
90481
90444
|
|
|
@@ -90508,8 +90471,8 @@ function removeProjectStatusLine(settings) {
|
|
|
90508
90471
|
return true;
|
|
90509
90472
|
}
|
|
90510
90473
|
function userClaudeSettingsPath() {
|
|
90511
|
-
const base = process.env["CLAUDE_CONFIG_DIR"] ??
|
|
90512
|
-
return
|
|
90474
|
+
const base = process.env["CLAUDE_CONFIG_DIR"] ?? join46(homedir8(), ".claude");
|
|
90475
|
+
return join46(base, "settings.json");
|
|
90513
90476
|
}
|
|
90514
90477
|
function ensureUserStatusLine(opts) {
|
|
90515
90478
|
const env2 = opts.env ?? process.env;
|
|
@@ -90517,9 +90480,9 @@ function ensureUserStatusLine(opts) {
|
|
|
90517
90480
|
if (off === "0" || off === "off" || off === "false" || off === "no") return "disabled";
|
|
90518
90481
|
const settingsPath = opts.userSettingsPath ?? userClaudeSettingsPath();
|
|
90519
90482
|
let settings = {};
|
|
90520
|
-
if (
|
|
90483
|
+
if (existsSync36(settingsPath)) {
|
|
90521
90484
|
try {
|
|
90522
|
-
const parsed = JSON.parse(
|
|
90485
|
+
const parsed = JSON.parse(readFileSync39(settingsPath, "utf8"));
|
|
90523
90486
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return "unreadable";
|
|
90524
90487
|
settings = parsed;
|
|
90525
90488
|
} catch {
|
|
@@ -90527,15 +90490,15 @@ function ensureUserStatusLine(opts) {
|
|
|
90527
90490
|
}
|
|
90528
90491
|
}
|
|
90529
90492
|
if (settings["statusLine"] !== void 0 && !isErrataStatusLine(settings["statusLine"])) return "kept-own";
|
|
90530
|
-
const relay =
|
|
90493
|
+
const relay = join46(opts.relayDir, STATUSLINE_RELAY_FILE);
|
|
90531
90494
|
mkdirSync10(opts.relayDir, { recursive: true });
|
|
90532
|
-
if (!
|
|
90495
|
+
if (!existsSync36(relay) || readFileSync39(relay, "utf8") !== STATUSLINE_RELAY_SOURCE) {
|
|
90533
90496
|
writeFileSync27(relay, STATUSLINE_RELAY_SOURCE, "utf8");
|
|
90534
90497
|
}
|
|
90535
90498
|
const next = buildStatusLine(opts.port, opts.nodePath ?? process.execPath, relay);
|
|
90536
90499
|
if (JSON.stringify(settings["statusLine"]) === JSON.stringify(next)) return "unchanged";
|
|
90537
90500
|
settings["statusLine"] = next;
|
|
90538
|
-
mkdirSync10(
|
|
90501
|
+
mkdirSync10(dirname14(settingsPath), { recursive: true });
|
|
90539
90502
|
writeFileSync27(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf8");
|
|
90540
90503
|
return "installed";
|
|
90541
90504
|
}
|
|
@@ -90959,14 +90922,14 @@ async function cmdInit() {
|
|
|
90959
90922
|
if (!skipHooks) {
|
|
90960
90923
|
console.log("");
|
|
90961
90924
|
console.log("installing harness hooks...");
|
|
90962
|
-
const { existsSync:
|
|
90963
|
-
const { join:
|
|
90925
|
+
const { existsSync: existsSync38 } = await import("node:fs");
|
|
90926
|
+
const { join: join48 } = await import("node:path");
|
|
90964
90927
|
try {
|
|
90965
90928
|
await installClaudeHooks(port);
|
|
90966
90929
|
} catch (err2) {
|
|
90967
90930
|
console.warn(` \u26A0\uFE0F Claude hook install failed: ${err2 instanceof Error ? err2.message : err2}`);
|
|
90968
90931
|
}
|
|
90969
|
-
if (
|
|
90932
|
+
if (existsSync38(join48(ROOT, ".cursor"))) {
|
|
90970
90933
|
try {
|
|
90971
90934
|
await installCursorMcpConfig();
|
|
90972
90935
|
} catch (err2) {
|
|
@@ -91050,6 +91013,7 @@ async function cmdNotifyTest() {
|
|
|
91050
91013
|
}
|
|
91051
91014
|
}
|
|
91052
91015
|
async function cmdStart() {
|
|
91016
|
+
refreshExistingCodexHooks();
|
|
91053
91017
|
if (!loadProfile(ROOT)) {
|
|
91054
91018
|
const cfg = loadConfig();
|
|
91055
91019
|
const locator = detectRepoLocator(ROOT);
|
|
@@ -91159,9 +91123,9 @@ async function cmdStatus() {
|
|
|
91159
91123
|
console.log(` stack: ${profile.stack.join(", ") || "(none)"}`);
|
|
91160
91124
|
console.log(` languages: ${profile.languages.join(", ") || "(none)"}`);
|
|
91161
91125
|
}
|
|
91162
|
-
console.log(` graph db: ${
|
|
91163
|
-
console.log(` event log: ${
|
|
91164
|
-
if (
|
|
91126
|
+
console.log(` graph db: ${existsSync37(paths.castalia) ? "yes" : "no"} (${paths.castalia})`);
|
|
91127
|
+
console.log(` event log: ${existsSync37(paths.eventLog) ? "yes" : "no"} (${paths.eventLog})`);
|
|
91128
|
+
if (existsSync37(paths.castalia)) {
|
|
91165
91129
|
try {
|
|
91166
91130
|
const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src5(), src_exports2));
|
|
91167
91131
|
const store = openGraphStore2({ path: paths.castalia });
|
|
@@ -91497,6 +91461,9 @@ async function cmdUpdate(args2) {
|
|
|
91497
91461
|
`);
|
|
91498
91462
|
const code = await runNpmInstall(channel);
|
|
91499
91463
|
if (code === 0) {
|
|
91464
|
+
if (await runInstalledHookRefresh() !== 0) {
|
|
91465
|
+
console.warn("[!] Package updated, but some Codex relays could not be refreshed. Run `errata install-hooks codex --refresh-existing`; daemon startup also retries.");
|
|
91466
|
+
}
|
|
91500
91467
|
console.log(`
|
|
91501
91468
|
[OK] updated to ${status.latest}. Restart the daemon to run it:`);
|
|
91502
91469
|
console.log(` errata stop (autostart relaunches it at next logon, or run 'errata dash')`);
|
|
@@ -92129,11 +92096,11 @@ async function cmdInstallationProfile(args2) {
|
|
|
92129
92096
|
}
|
|
92130
92097
|
async function cmdReview() {
|
|
92131
92098
|
const paths = workspacePaths(ROOT);
|
|
92132
|
-
if (!
|
|
92099
|
+
if (!existsSync37(paths.reviewQueue)) {
|
|
92133
92100
|
console.log("(review queue empty)");
|
|
92134
92101
|
return;
|
|
92135
92102
|
}
|
|
92136
|
-
const queue = JSON.parse(
|
|
92103
|
+
const queue = JSON.parse(readFileSync40(paths.reviewQueue, "utf8"));
|
|
92137
92104
|
if (queue.length === 0) {
|
|
92138
92105
|
console.log("(review queue empty)");
|
|
92139
92106
|
return;
|
|
@@ -92804,7 +92771,7 @@ async function gatherRepo(store, ws) {
|
|
|
92804
92771
|
};
|
|
92805
92772
|
}
|
|
92806
92773
|
async function gatherReportData(generatedAt) {
|
|
92807
|
-
const { existsSync:
|
|
92774
|
+
const { existsSync: existsSync38 } = await import("node:fs");
|
|
92808
92775
|
const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src5(), src_exports2));
|
|
92809
92776
|
const cfg = loadConfig();
|
|
92810
92777
|
const outbound = cfg.consent.sync ? "auto" : "off";
|
|
@@ -92812,7 +92779,7 @@ async function gatherReportData(generatedAt) {
|
|
|
92812
92779
|
for (const ws of listWorkspaces()) {
|
|
92813
92780
|
if (ws.missing) continue;
|
|
92814
92781
|
const dbPath = workspacePaths(ws.path).castalia;
|
|
92815
|
-
if (!
|
|
92782
|
+
if (!existsSync38(dbPath)) continue;
|
|
92816
92783
|
let store = null;
|
|
92817
92784
|
try {
|
|
92818
92785
|
store = openGraphStore2({ path: dbPath });
|
|
@@ -92856,8 +92823,8 @@ async function cmdReport(args2) {
|
|
|
92856
92823
|
const outDir = workspacePaths(ROOT).configDir;
|
|
92857
92824
|
mkdirSync11(outDir, { recursive: true });
|
|
92858
92825
|
const files = renderReport2(data, { includeFutureVerbs });
|
|
92859
|
-
for (const f of files) writeFileSync28(
|
|
92860
|
-
const indexPath =
|
|
92826
|
+
for (const f of files) writeFileSync28(join47(outDir, f.name), f.html, "utf8");
|
|
92827
|
+
const indexPath = join47(outDir, "report.html");
|
|
92861
92828
|
console.log(`report \u2192 ${indexPath}`);
|
|
92862
92829
|
console.log(
|
|
92863
92830
|
` ${data.repos.length} repo(s) \xB7 ${files.length} file(s) \xB7 ${data.rollup.nodes.toLocaleString("en-US")} nodes`
|
|
@@ -92901,7 +92868,7 @@ function spawnDaemonDetached(options = {}) {
|
|
|
92901
92868
|
try {
|
|
92902
92869
|
const logPath = daemonLogPath();
|
|
92903
92870
|
try {
|
|
92904
|
-
if (
|
|
92871
|
+
if (statSync11(logPath).size > 5 * 1024 * 1024) renameSync6(logPath, `${logPath}.1`);
|
|
92905
92872
|
} catch {
|
|
92906
92873
|
}
|
|
92907
92874
|
out2 = openSync2(logPath, "a");
|
|
@@ -92951,6 +92918,10 @@ async function cmdInstallHooks(args2) {
|
|
|
92951
92918
|
await installCursorMcpConfig();
|
|
92952
92919
|
return;
|
|
92953
92920
|
case "codex":
|
|
92921
|
+
if (args2.includes("--refresh-existing")) {
|
|
92922
|
+
if (!refreshExistingCodexHooks()) process.exitCode = 1;
|
|
92923
|
+
return;
|
|
92924
|
+
}
|
|
92954
92925
|
await installCodexHooks(port);
|
|
92955
92926
|
return;
|
|
92956
92927
|
case "opencode":
|
|
@@ -92966,24 +92937,24 @@ async function cmdInstallHooks(args2) {
|
|
|
92966
92937
|
}
|
|
92967
92938
|
}
|
|
92968
92939
|
async function installOpencodePlugin(port) {
|
|
92969
|
-
const { mkdirSync: mkdirSync11, existsSync:
|
|
92970
|
-
const { join:
|
|
92971
|
-
const dir =
|
|
92972
|
-
if (!
|
|
92973
|
-
const file2 =
|
|
92974
|
-
if (
|
|
92975
|
-
const head2 =
|
|
92940
|
+
const { mkdirSync: mkdirSync11, existsSync: existsSync38, readFileSync: readFileSync41, writeFileSync: writeFileSync28 } = await import("node:fs");
|
|
92941
|
+
const { join: join48 } = await import("node:path");
|
|
92942
|
+
const dir = join48(ROOT, ".opencode", "plugin");
|
|
92943
|
+
if (!existsSync38(dir)) mkdirSync11(dir, { recursive: true });
|
|
92944
|
+
const file2 = join48(dir, "inerrata.js");
|
|
92945
|
+
if (existsSync38(file2)) {
|
|
92946
|
+
const head2 = readFileSync41(file2, "utf8").split("\n")[0] ?? "";
|
|
92976
92947
|
if (head2.trim() !== OPENCODE_PLUGIN_MARKER) {
|
|
92977
92948
|
console.error(`refusing to overwrite ${file2}: not an errata-managed plugin (line 1 lacks the marker)`);
|
|
92978
92949
|
process.exit(2);
|
|
92979
92950
|
}
|
|
92980
92951
|
}
|
|
92981
92952
|
writeFileSync28(file2, buildOpencodePluginSource(port, { version: DAEMON_VERSION }), "utf8");
|
|
92982
|
-
const cfgFile =
|
|
92953
|
+
const cfgFile = join48(ROOT, "opencode.json");
|
|
92983
92954
|
let cfg = { $schema: "https://opencode.ai/config.json" };
|
|
92984
|
-
if (
|
|
92955
|
+
if (existsSync38(cfgFile)) {
|
|
92985
92956
|
try {
|
|
92986
|
-
cfg = JSON.parse(
|
|
92957
|
+
cfg = JSON.parse(readFileSync41(cfgFile, "utf8"));
|
|
92987
92958
|
} catch {
|
|
92988
92959
|
console.error(`refusing to touch invalid JSON at ${cfgFile} \u2014 fix it and re-run`);
|
|
92989
92960
|
process.exit(2);
|
|
@@ -93021,15 +92992,15 @@ function ensureStatusLine(port) {
|
|
|
93021
92992
|
}
|
|
93022
92993
|
}
|
|
93023
92994
|
async function installClaudeHooks(port) {
|
|
93024
|
-
const { mkdirSync: mkdirSync11, existsSync:
|
|
93025
|
-
const { join:
|
|
93026
|
-
const dir =
|
|
93027
|
-
if (!
|
|
93028
|
-
const file2 =
|
|
92995
|
+
const { mkdirSync: mkdirSync11, existsSync: existsSync38, readFileSync: readFileSync41, writeFileSync: writeFileSync28 } = await import("node:fs");
|
|
92996
|
+
const { join: join48 } = await import("node:path");
|
|
92997
|
+
const dir = join48(ROOT, ".claude");
|
|
92998
|
+
if (!existsSync38(dir)) mkdirSync11(dir, { recursive: true });
|
|
92999
|
+
const file2 = join48(dir, "settings.json");
|
|
93029
93000
|
let settings = {};
|
|
93030
|
-
if (
|
|
93001
|
+
if (existsSync38(file2)) {
|
|
93031
93002
|
try {
|
|
93032
|
-
settings = JSON.parse(
|
|
93003
|
+
settings = JSON.parse(readFileSync41(file2, "utf8"));
|
|
93033
93004
|
} catch {
|
|
93034
93005
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
93035
93006
|
process.exit(2);
|
|
@@ -93081,7 +93052,7 @@ async function installClaudeHooks(port) {
|
|
|
93081
93052
|
console.log(`installed Claude Code hooks \u2192 ${file2}`);
|
|
93082
93053
|
console.log(` ${ensureStatusLine(port)}`);
|
|
93083
93054
|
await installClaudeMcpConfig();
|
|
93084
|
-
const claudeMd =
|
|
93055
|
+
const claudeMd = join48(ROOT, "CLAUDE.md");
|
|
93085
93056
|
const recall = writeManagedBlock(claudeMd, { body: RECALL_FIRST_BLOCK });
|
|
93086
93057
|
if (recall.kind === "collision") {
|
|
93087
93058
|
console.warn(
|
|
@@ -93093,15 +93064,15 @@ async function installClaudeHooks(port) {
|
|
|
93093
93064
|
console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
|
|
93094
93065
|
}
|
|
93095
93066
|
async function installClaudeMcpConfig() {
|
|
93096
|
-
const { mkdirSync: mkdirSync11, existsSync:
|
|
93097
|
-
const { join:
|
|
93098
|
-
const file2 =
|
|
93099
|
-
const dir =
|
|
93100
|
-
if (!
|
|
93067
|
+
const { mkdirSync: mkdirSync11, existsSync: existsSync38, readFileSync: readFileSync41, writeFileSync: writeFileSync28 } = await import("node:fs");
|
|
93068
|
+
const { join: join48, dirname: dirname15 } = await import("node:path");
|
|
93069
|
+
const file2 = join48(ROOT, ".mcp.json");
|
|
93070
|
+
const dir = dirname15(file2);
|
|
93071
|
+
if (!existsSync38(dir)) mkdirSync11(dir, { recursive: true });
|
|
93101
93072
|
let cfg = {};
|
|
93102
|
-
if (
|
|
93073
|
+
if (existsSync38(file2)) {
|
|
93103
93074
|
try {
|
|
93104
|
-
cfg = JSON.parse(
|
|
93075
|
+
cfg = JSON.parse(readFileSync41(file2, "utf8"));
|
|
93105
93076
|
} catch {
|
|
93106
93077
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
93107
93078
|
process.exit(2);
|
|
@@ -93115,15 +93086,15 @@ async function installClaudeMcpConfig() {
|
|
|
93115
93086
|
console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses / show / similar`);
|
|
93116
93087
|
}
|
|
93117
93088
|
async function installCursorMcpConfig() {
|
|
93118
|
-
const { mkdirSync: mkdirSync11, existsSync:
|
|
93119
|
-
const { join:
|
|
93120
|
-
const dir =
|
|
93121
|
-
if (!
|
|
93122
|
-
const file2 =
|
|
93089
|
+
const { mkdirSync: mkdirSync11, existsSync: existsSync38, readFileSync: readFileSync41, writeFileSync: writeFileSync28 } = await import("node:fs");
|
|
93090
|
+
const { join: join48 } = await import("node:path");
|
|
93091
|
+
const dir = join48(ROOT, ".cursor");
|
|
93092
|
+
if (!existsSync38(dir)) mkdirSync11(dir, { recursive: true });
|
|
93093
|
+
const file2 = join48(dir, "mcp.json");
|
|
93123
93094
|
let cfg = {};
|
|
93124
|
-
if (
|
|
93095
|
+
if (existsSync38(file2)) {
|
|
93125
93096
|
try {
|
|
93126
|
-
cfg = JSON.parse(
|
|
93097
|
+
cfg = JSON.parse(readFileSync41(file2, "utf8"));
|
|
93127
93098
|
} catch {
|
|
93128
93099
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
93129
93100
|
process.exit(2);
|
|
@@ -93142,7 +93113,7 @@ async function installCodexHooks(port) {
|
|
|
93142
93113
|
const gitRoot = nearestGitRoot(process.cwd());
|
|
93143
93114
|
const hookRoot = gitRoot && mainCheckoutOfWorktree(gitRoot) ? gitRoot : ROOT;
|
|
93144
93115
|
const file2 = writeCodexHooks(hookRoot, port);
|
|
93145
|
-
const instructions = writeManagedBlock(
|
|
93116
|
+
const instructions = writeManagedBlock(join47(hookRoot, "AGENTS.md"), {
|
|
93146
93117
|
body: AGENTS_POINTER_BODY,
|
|
93147
93118
|
stable: true
|
|
93148
93119
|
});
|
|
@@ -93160,6 +93131,21 @@ async function installCodexHooks(port) {
|
|
|
93160
93131
|
console.log(" Run `errata doctor` here to check hook discovery and trust; installation alone is not activation.");
|
|
93161
93132
|
console.log(" Respect an explicit [features] hooks = false setting (older builds use codex_hooks).");
|
|
93162
93133
|
console.log(" Older Codex versions may not support every event; update if hooks do not fire.");
|
|
93134
|
+
for (const check2 of await diagnoseCodexHooks(hookRoot)) {
|
|
93135
|
+
console.log(` ${check2.status === "pass" ? "\u2713" : "!"} ${check2.detail}`);
|
|
93136
|
+
}
|
|
93137
|
+
}
|
|
93138
|
+
function refreshExistingCodexHooks() {
|
|
93139
|
+
let ok = true;
|
|
93140
|
+
const roots = [...listWorkspaceEntries().map((entry) => entry.path), process.cwd()];
|
|
93141
|
+
for (const result of refreshInstalledCodexRelays(roots)) {
|
|
93142
|
+
if (result.status === "updated") console.log(`updated existing Codex relay \u2192 ${result.root} (hook definitions preserved)`);
|
|
93143
|
+
if (result.status === "error") {
|
|
93144
|
+
ok = false;
|
|
93145
|
+
console.warn(`Codex relay refresh needs attention in ${result.root}: ${result.detail}`);
|
|
93146
|
+
}
|
|
93147
|
+
}
|
|
93148
|
+
return ok;
|
|
93163
93149
|
}
|
|
93164
93150
|
async function refreshLinkedCodexHooks(args2) {
|
|
93165
93151
|
if (args2.includes("--skip-hooks") || !hasCodexConfig(ROOT)) return;
|
|
@@ -93314,6 +93300,7 @@ function installLogTimestamps() {
|
|
|
93314
93300
|
async function cmdDash(args2) {
|
|
93315
93301
|
process.title = "errata-daemon";
|
|
93316
93302
|
installLogTimestamps();
|
|
93303
|
+
refreshExistingCodexHooks();
|
|
93317
93304
|
const portIdx = args2.indexOf("--port");
|
|
93318
93305
|
const port = portIdx >= 0 && args2[portIdx + 1] ? Number(args2[portIdx + 1]) : 7891;
|
|
93319
93306
|
const reindexOnStart = !args2.includes("--no-reindex");
|
|
@@ -93468,7 +93455,7 @@ async function cmdDash(args2) {
|
|
|
93468
93455
|
const hotspotScanMark = /* @__PURE__ */ new Map();
|
|
93469
93456
|
const HOTSPOT_FANIN = 20;
|
|
93470
93457
|
const runNightlyPass = async (dueIds) => {
|
|
93471
|
-
const yieldToLoop2 = () => new Promise((
|
|
93458
|
+
const yieldToLoop2 = () => new Promise((resolve8) => setImmediate(resolve8));
|
|
93472
93459
|
const fullReclusterPass = nightlyCount++ % FULL_RECLUSTER_EVERY === 0;
|
|
93473
93460
|
const m = dueIds ? await handle2.nightlyFor(dueIds) : await handle2.nightlyAll();
|
|
93474
93461
|
let skillsLearned = 0;
|
|
@@ -93546,9 +93533,9 @@ async function cmdDash(args2) {
|
|
|
93546
93533
|
await yieldToLoop2();
|
|
93547
93534
|
try {
|
|
93548
93535
|
const items = selectDurableMemory(handle2.sharedStore, r.engine.profile, {
|
|
93549
|
-
atCommit: readGitRefState(
|
|
93536
|
+
atCommit: readGitRefState(join47(r.root, ".git")).sha ?? void 0
|
|
93550
93537
|
});
|
|
93551
|
-
const res = bleedRules(
|
|
93538
|
+
const res = bleedRules(join47(r.root, ".claude", "rules"), items);
|
|
93552
93539
|
if (res.written || res.pruned) {
|
|
93553
93540
|
console.log(
|
|
93554
93541
|
`[rules:${r.entry.name}] ${res.written} collective principle(s) \u2192 .claude/rules` + (res.pruned ? `, ${res.pruned} pruned` : "")
|