@inerrata-corporation/errata 2.0.2-dev.513 → 2.0.2-dev.530
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 +14 -4
- package/errata.mjs +690 -237
- package/package.json +1 -1
- package/pass-worker.mjs +108 -29
package/errata.mjs
CHANGED
|
@@ -17314,6 +17314,10 @@ CREATE INDEX IF NOT EXISTS nodes_relpath ON nodes(json_extract(attrs_json, '$.re
|
|
|
17314
17314
|
if (!live) return null;
|
|
17315
17315
|
const version2 = live.version ?? 1;
|
|
17316
17316
|
const frozenId = `${liveId}@v${version2}`;
|
|
17317
|
+
if (this.getNode(frozenId)) {
|
|
17318
|
+
this.stmts.advanceLive.run({ live_id: liveId, t });
|
|
17319
|
+
return frozenId;
|
|
17320
|
+
}
|
|
17317
17321
|
this.stmts.freezeCopy.run({ frozen_id: frozenId, live_id: liveId, t });
|
|
17318
17322
|
this.mergeEdge({
|
|
17319
17323
|
id: `edge_superseded_${frozenId}`,
|
|
@@ -17699,14 +17703,17 @@ function markRevisit(store, node2, reason, ts, answeredWhen) {
|
|
|
17699
17703
|
revisit: true,
|
|
17700
17704
|
revisitReason: reason,
|
|
17701
17705
|
revisitSinceTs: ts,
|
|
17702
|
-
|
|
17706
|
+
revisitAnsweredWhen: answeredWhen
|
|
17703
17707
|
},
|
|
17704
17708
|
lastUpdatedAt: ts
|
|
17705
17709
|
});
|
|
17706
17710
|
}
|
|
17711
|
+
function isRevisitCondition(v) {
|
|
17712
|
+
return typeof v === "string" && Object.prototype.hasOwnProperty.call(KNOWN_CONDITIONS, v);
|
|
17713
|
+
}
|
|
17707
17714
|
function conditionOf(node2) {
|
|
17708
17715
|
const explicit = node2.attrs["revisitAnsweredWhen"];
|
|
17709
|
-
if (explicit
|
|
17716
|
+
if (isRevisitCondition(explicit)) return explicit;
|
|
17710
17717
|
if (String(node2.attrs["revisitReason"] ?? "").startsWith(LEGACY_AUTO_CLOSE_ASK)) {
|
|
17711
17718
|
return "parentProblemOpen";
|
|
17712
17719
|
}
|
|
@@ -17714,23 +17721,32 @@ function conditionOf(node2) {
|
|
|
17714
17721
|
}
|
|
17715
17722
|
function clearAnsweredRevisits(store, ts) {
|
|
17716
17723
|
const report = { cleared: 0, standing: 0 };
|
|
17717
|
-
for (const
|
|
17718
|
-
|
|
17719
|
-
|
|
17720
|
-
|
|
17721
|
-
|
|
17722
|
-
|
|
17723
|
-
|
|
17724
|
-
|
|
17725
|
-
|
|
17726
|
-
report.
|
|
17727
|
-
continue;
|
|
17724
|
+
for (const label of SEMANTIC_NODE_LABELS) {
|
|
17725
|
+
for (const node2 of store.findNodesByLabel(label)) {
|
|
17726
|
+
if (node2.attrs["revisit"] !== true) continue;
|
|
17727
|
+
const condition = conditionOf(node2);
|
|
17728
|
+
if (condition === void 0 || !isRevisitAnswered(store, node2, condition)) {
|
|
17729
|
+
report.standing++;
|
|
17730
|
+
continue;
|
|
17731
|
+
}
|
|
17732
|
+
clearRevisit(store, node2.id, ts);
|
|
17733
|
+
report.cleared++;
|
|
17728
17734
|
}
|
|
17729
|
-
clearRevisit(store, node2.id, ts);
|
|
17730
|
-
report.cleared++;
|
|
17731
17735
|
}
|
|
17732
17736
|
return report;
|
|
17733
17737
|
}
|
|
17738
|
+
function isRevisitAnswered(store, node2, condition) {
|
|
17739
|
+
switch (condition) {
|
|
17740
|
+
case "parentProblemOpen": {
|
|
17741
|
+
const parents = store.inEdges(node2.id, ["SOLVED_BY"]).map((e) => store.getNode(e.from)).filter((n) => n !== null);
|
|
17742
|
+
return parents.every((p) => p.attrs["resolvedAt"] == null);
|
|
17743
|
+
}
|
|
17744
|
+
case "dependentStale": {
|
|
17745
|
+
const since = Number(node2.attrs["revisitSinceTs"] ?? 0);
|
|
17746
|
+
return since > 0 && node2.lastUpdatedAt > since;
|
|
17747
|
+
}
|
|
17748
|
+
}
|
|
17749
|
+
}
|
|
17734
17750
|
function clearRevisit(store, nodeId, ts) {
|
|
17735
17751
|
const n = store.getNode(nodeId);
|
|
17736
17752
|
if (!n) return;
|
|
@@ -17756,7 +17772,7 @@ function cascade(store, seeds, visited, flagged, ts) {
|
|
|
17756
17772
|
visited.add(id);
|
|
17757
17773
|
const node2 = store.getNode(id);
|
|
17758
17774
|
if (!node2) continue;
|
|
17759
|
-
markRevisit(store, node2, reason, ts);
|
|
17775
|
+
markRevisit(store, node2, reason, ts, "dependentStale");
|
|
17760
17776
|
flagged.push({ id, label: node2.label, description: node2.description, reason });
|
|
17761
17777
|
for (const e of store.inEdges(id, ["DEPENDS_ON"])) {
|
|
17762
17778
|
queue.push({
|
|
@@ -17803,12 +17819,17 @@ function propagateFactChange(store, opts) {
|
|
|
17803
17819
|
cascade(store, seeds, visited, flagged, opts.ts);
|
|
17804
17820
|
return flagged;
|
|
17805
17821
|
}
|
|
17806
|
-
var LEGACY_AUTO_CLOSE_ASK;
|
|
17822
|
+
var LEGACY_AUTO_CLOSE_ASK, KNOWN_CONDITIONS;
|
|
17807
17823
|
var init_justification = __esm({
|
|
17808
17824
|
"../../packages/local-graph/src/justification.ts"() {
|
|
17809
17825
|
"use strict";
|
|
17810
17826
|
init_src();
|
|
17827
|
+
init_src2();
|
|
17811
17828
|
LEGACY_AUTO_CLOSE_ASK = "auto-closed off a pre-provenance anchor";
|
|
17829
|
+
KNOWN_CONDITIONS = {
|
|
17830
|
+
parentProblemOpen: true,
|
|
17831
|
+
dependentStale: true
|
|
17832
|
+
};
|
|
17812
17833
|
}
|
|
17813
17834
|
});
|
|
17814
17835
|
|
|
@@ -18788,7 +18809,8 @@ function isPlaceholderStatement(statement) {
|
|
|
18788
18809
|
if (bracketed.length > 0 && bracketedLen >= s.length * 0.6) return true;
|
|
18789
18810
|
return false;
|
|
18790
18811
|
}
|
|
18791
|
-
function buildNode(id, label, description, ts, attrs) {
|
|
18812
|
+
function buildNode(store, id, label, description, ts, attrs) {
|
|
18813
|
+
const seq = SEMANTIC_NODE_LABELS.includes(label) ? store.nextIngestSeq() : void 0;
|
|
18792
18814
|
return {
|
|
18793
18815
|
id,
|
|
18794
18816
|
label,
|
|
@@ -18807,9 +18829,14 @@ function buildNode(id, label, description, ts, attrs) {
|
|
|
18807
18829
|
isLandmark: false,
|
|
18808
18830
|
community: null,
|
|
18809
18831
|
stability: "unstable",
|
|
18832
|
+
...seq !== void 0 ? { createdAtSeq: seq, lastReinforcedAtSeq: seq } : {},
|
|
18810
18833
|
attrs
|
|
18811
18834
|
};
|
|
18812
18835
|
}
|
|
18836
|
+
function reinforcedSeqAttrs(store, label) {
|
|
18837
|
+
if (!SEMANTIC_NODE_LABELS.includes(label)) return {};
|
|
18838
|
+
return { lastReinforcedAtSeq: store.nextIngestSeq() };
|
|
18839
|
+
}
|
|
18813
18840
|
function mergeEdge(store, from, to, type, ts) {
|
|
18814
18841
|
store.mergeEdge({
|
|
18815
18842
|
id: `edge_${digest({ from, type, to })}`.slice(0, 24),
|
|
@@ -18889,13 +18916,19 @@ function ingestDesignProblem(store, flag, opts) {
|
|
|
18889
18916
|
},
|
|
18890
18917
|
cumulativeHits: (existing.cumulativeHits ?? 0) + 1,
|
|
18891
18918
|
...promoted ? { extractionConfidence: 0.65 } : {},
|
|
18919
|
+
// A corroborating re-flag is a REINFORCE: advance the sequence and move
|
|
18920
|
+
// this node's marker with it, which resets its Δseq and makes it read
|
|
18921
|
+
// fresh again. Without this the mint path would advance the ruler while
|
|
18922
|
+
// re-observation never moved along it, so a heavily-reinforced node would
|
|
18923
|
+
// decay exactly as fast as one nobody has mentioned since.
|
|
18924
|
+
...reinforcedSeqAttrs(store, existing.label),
|
|
18892
18925
|
lastUpdatedAt: opts.ts
|
|
18893
18926
|
});
|
|
18894
18927
|
}
|
|
18895
18928
|
} else {
|
|
18896
18929
|
created = true;
|
|
18897
18930
|
store.mergeNode(
|
|
18898
|
-
buildNode(problemId, "Problem", statement, opts.ts, {
|
|
18931
|
+
buildNode(store, problemId, "Problem", statement, opts.ts, {
|
|
18899
18932
|
source: "convo",
|
|
18900
18933
|
provisional: true,
|
|
18901
18934
|
kind: flag.kind ?? "problem",
|
|
@@ -18910,7 +18943,7 @@ function ingestDesignProblem(store, flag, opts) {
|
|
|
18910
18943
|
if (flag.cause?.trim()) {
|
|
18911
18944
|
rootCauseId = `dcause_${digest({ problemId, cause: flag.cause })}`.slice(0, 56);
|
|
18912
18945
|
store.mergeNode(
|
|
18913
|
-
buildNode(rootCauseId, "RootCause", flag.cause.trim(), opts.ts, {
|
|
18946
|
+
buildNode(store, rootCauseId, "RootCause", flag.cause.trim(), opts.ts, {
|
|
18914
18947
|
source: "convo",
|
|
18915
18948
|
provisional: true
|
|
18916
18949
|
})
|
|
@@ -18921,7 +18954,7 @@ function ingestDesignProblem(store, flag, opts) {
|
|
|
18921
18954
|
if (flag.fix?.trim()) {
|
|
18922
18955
|
solutionId = `dfix_${digest({ problemId, fix: flag.fix })}`.slice(0, 56);
|
|
18923
18956
|
store.mergeNode(
|
|
18924
|
-
buildNode(solutionId, "Solution", flag.fix.trim(), opts.ts, {
|
|
18957
|
+
buildNode(store, solutionId, "Solution", flag.fix.trim(), opts.ts, {
|
|
18925
18958
|
source: "convo",
|
|
18926
18959
|
provisional: true,
|
|
18927
18960
|
rationale: flag.fix.trim()
|
|
@@ -18961,6 +18994,8 @@ function mintPatternNode(store, name2, ts) {
|
|
|
18961
18994
|
observedCount: (Number(node2.attrs["observedCount"]) || 1) + 1,
|
|
18962
18995
|
...aliases.length > 0 ? { aliasTexts: aliases } : {}
|
|
18963
18996
|
},
|
|
18997
|
+
// Re-observing a Pattern is a REINFORCE on the same ruler as minting one.
|
|
18998
|
+
...reinforcedSeqAttrs(store, node2.label),
|
|
18964
18999
|
lastUpdatedAt: ts
|
|
18965
19000
|
});
|
|
18966
19001
|
return node2.id;
|
|
@@ -18981,7 +19016,7 @@ function mintPatternNode(store, name2, ts) {
|
|
|
18981
19016
|
}
|
|
18982
19017
|
if (best && bestCos >= PATTERN_DEDUP_COSINE) return reinforce(best, display);
|
|
18983
19018
|
store.mergeNode({
|
|
18984
|
-
...buildNode(id, "Pattern", display, ts, { source: "convo", provisional: true, observedCount: 1 }),
|
|
19019
|
+
...buildNode(store, id, "Pattern", display, ts, { source: "convo", provisional: true, observedCount: 1 }),
|
|
18985
19020
|
// Embedded inline (sync hash) so the node participates in the gate
|
|
18986
19021
|
// immediately — buildNode's empty embedding would leave every new pattern
|
|
18987
19022
|
// invisible to dedup until the nightly embed pass.
|
|
@@ -18997,7 +19032,7 @@ function mintDomainNode(store, name2, ts) {
|
|
|
18997
19032
|
const id = `dom_${digest({ domain: display.toLowerCase() })}`.slice(0, 56);
|
|
18998
19033
|
if (!store.getNode(id)) {
|
|
18999
19034
|
store.mergeNode(
|
|
19000
|
-
buildNode(id, "Domain", display, ts, {
|
|
19035
|
+
buildNode(store, id, "Domain", display, ts, {
|
|
19001
19036
|
source: "convo",
|
|
19002
19037
|
provisional: true,
|
|
19003
19038
|
canonicalId: genericCanonicalId("dom", { type: "Domain", description: display })
|
|
@@ -19028,7 +19063,7 @@ function mintCitedPackageNode(store, ref, ts) {
|
|
|
19028
19063
|
const purl = `pkg:${eco}/${purlName}`;
|
|
19029
19064
|
if (!store.getNode(purl)) {
|
|
19030
19065
|
store.mergeNode(
|
|
19031
|
-
buildNode(purl, "Package", name2, ts, {
|
|
19066
|
+
buildNode(store, purl, "Package", name2, ts, {
|
|
19032
19067
|
purl,
|
|
19033
19068
|
name: name2,
|
|
19034
19069
|
ecosystem: eco,
|
|
@@ -19048,7 +19083,7 @@ function mintComponentNode(store, name2, ts) {
|
|
|
19048
19083
|
const existing = store.getNode(slug2);
|
|
19049
19084
|
if (!existing) {
|
|
19050
19085
|
store.mergeNode(
|
|
19051
|
-
buildNode(slug2, "Component", display, ts, {
|
|
19086
|
+
buildNode(store, slug2, "Component", display, ts, {
|
|
19052
19087
|
name: display,
|
|
19053
19088
|
source: "convo",
|
|
19054
19089
|
provisional: true,
|
|
@@ -19255,7 +19290,7 @@ function closeDesignProblem(store, problemId, fixNote, t) {
|
|
|
19255
19290
|
if (fixNote?.trim() && store.outEdges(problemId, ["SOLVED_BY"]).length === 0) {
|
|
19256
19291
|
const solId = `dfix_${digest({ problemId, fix: fixNote })}`.slice(0, 56);
|
|
19257
19292
|
store.mergeNode(
|
|
19258
|
-
buildNode(solId, "Solution", fixNote.trim(), t, { source: "convo", provisional: false })
|
|
19293
|
+
buildNode(store, solId, "Solution", fixNote.trim(), t, { source: "convo", provisional: false })
|
|
19259
19294
|
);
|
|
19260
19295
|
mergeEdge(store, problemId, solId, "SOLVED_BY", t);
|
|
19261
19296
|
}
|
|
@@ -20613,7 +20648,8 @@ var init_src4 = __esm({
|
|
|
20613
20648
|
});
|
|
20614
20649
|
|
|
20615
20650
|
// ../../packages/local-graph/src/triage.ts
|
|
20616
|
-
function semNode(id, label, description, ts, attrs) {
|
|
20651
|
+
function semNode(store, id, label, description, ts, attrs) {
|
|
20652
|
+
const seq = SEMANTIC_NODE_LABELS.includes(label) ? store.nextIngestSeq() : void 0;
|
|
20617
20653
|
return {
|
|
20618
20654
|
id,
|
|
20619
20655
|
label,
|
|
@@ -20631,6 +20667,7 @@ function semNode(id, label, description, ts, attrs) {
|
|
|
20631
20667
|
isLandmark: false,
|
|
20632
20668
|
community: null,
|
|
20633
20669
|
stability: "unstable",
|
|
20670
|
+
...seq !== void 0 ? { createdAtSeq: seq, lastReinforcedAtSeq: seq } : {},
|
|
20634
20671
|
attrs
|
|
20635
20672
|
};
|
|
20636
20673
|
}
|
|
@@ -20661,7 +20698,7 @@ function recordTriageObservation(l2, obs, ts) {
|
|
|
20661
20698
|
const buckets = [...triageContextBuckets(canonicalizeContext(obs.context)), TRIAGE_GLOBAL_BUCKET];
|
|
20662
20699
|
l2.transaction(() => {
|
|
20663
20700
|
if (!l2.getNode(presentingId)) {
|
|
20664
|
-
l2.mergeNode(semNode(presentingId, "Problem", statement, ts, { scope: {} }));
|
|
20701
|
+
l2.mergeNode(semNode(l2, presentingId, "Problem", statement, ts, { scope: {} }));
|
|
20665
20702
|
}
|
|
20666
20703
|
const tri = l2.getNode(triageId);
|
|
20667
20704
|
const seen = {
|
|
@@ -20675,7 +20712,7 @@ function recordTriageObservation(l2, obs, ts) {
|
|
|
20675
20712
|
});
|
|
20676
20713
|
} else {
|
|
20677
20714
|
l2.mergeNode(
|
|
20678
|
-
semNode(triageId, "Triage", `differential for: ${statement}`, ts, {
|
|
20715
|
+
semNode(l2, triageId, "Triage", `differential for: ${statement}`, ts, {
|
|
20679
20716
|
statement,
|
|
20680
20717
|
perContextSeen: seen
|
|
20681
20718
|
})
|
|
@@ -20687,7 +20724,7 @@ function recordTriageObservation(l2, obs, ts) {
|
|
|
20687
20724
|
}
|
|
20688
20725
|
if (!l2.getNode(obs.causeId)) {
|
|
20689
20726
|
l2.mergeNode(
|
|
20690
|
-
semNode(obs.causeId, obs.causeLabel ?? "RootCause", obs.causeDescription ?? "(cause)", ts, {
|
|
20727
|
+
semNode(l2, obs.causeId, obs.causeLabel ?? "RootCause", obs.causeDescription ?? "(cause)", ts, {
|
|
20691
20728
|
scope: {}
|
|
20692
20729
|
})
|
|
20693
20730
|
);
|
|
@@ -20751,7 +20788,7 @@ function recordCauseChainLink(l2, link, ts, attrs = {}) {
|
|
|
20751
20788
|
[link.fromId, link.fromDescription],
|
|
20752
20789
|
[link.toId, link.toDescription]
|
|
20753
20790
|
]) {
|
|
20754
|
-
if (!l2.getNode(id)) l2.mergeNode(semNode(id, "RootCause", description, ts, { ...attrs }));
|
|
20791
|
+
if (!l2.getNode(id)) l2.mergeNode(semNode(l2, id, "RootCause", description, ts, { ...attrs }));
|
|
20755
20792
|
}
|
|
20756
20793
|
const edgeId2 = `edge_cb_${link.fromId}_${link.toId}`;
|
|
20757
20794
|
if (!l2.getEdge(edgeId2)) {
|
|
@@ -20774,7 +20811,7 @@ function mintWorkspaceCausalFact(ws, fact, ts) {
|
|
|
20774
20811
|
ws.transaction(() => {
|
|
20775
20812
|
if (!ws.getNode(fact.causeId)) {
|
|
20776
20813
|
ws.mergeNode(
|
|
20777
|
-
semNode(fact.causeId, "RootCause", description, ts, {
|
|
20814
|
+
semNode(ws, fact.causeId, "RootCause", description, ts, {
|
|
20778
20815
|
scope: {},
|
|
20779
20816
|
...fact.sessionId ? { sources: [fact.sessionId] } : {}
|
|
20780
20817
|
})
|
|
@@ -21116,7 +21153,7 @@ function harvestTriageFences(l2, text, opts) {
|
|
|
21116
21153
|
const fix = f.fix.trim();
|
|
21117
21154
|
const fixId = `dfix_${digest({ cause: causeId, fix })}`.slice(0, 56);
|
|
21118
21155
|
if (!l2.getNode(fixId)) {
|
|
21119
|
-
l2.mergeNode(semNode(fixId, "Solution", fix, opts.ts, { scope: {} }));
|
|
21156
|
+
l2.mergeNode(semNode(l2, fixId, "Solution", fix, opts.ts, { scope: {} }));
|
|
21120
21157
|
}
|
|
21121
21158
|
const solEdgeId = `edge_sol_${causeId}_${fixId}`;
|
|
21122
21159
|
if (!l2.getEdge(solEdgeId)) {
|
|
@@ -21799,6 +21836,169 @@ var init_principle_sync = __esm({
|
|
|
21799
21836
|
}
|
|
21800
21837
|
});
|
|
21801
21838
|
|
|
21839
|
+
// ../../packages/local-graph/src/mechanism-liveness.ts
|
|
21840
|
+
function evaluateFed(store, d) {
|
|
21841
|
+
const column = COLUMN_INPUTS[d.fed.attr];
|
|
21842
|
+
const has = (n) => column ? column(n) : n.attrs[d.fed.attr] !== void 0;
|
|
21843
|
+
const nodes = d.fed.labels.flatMap((label) => store.findNodesByLabel(label));
|
|
21844
|
+
let window2 = nodes;
|
|
21845
|
+
if (d.fed.recent !== void 0) {
|
|
21846
|
+
window2 = [...nodes].sort((a, b) => b.createdAt - a.createdAt).slice(0, d.fed.recent);
|
|
21847
|
+
}
|
|
21848
|
+
if (d.fed.sinceFirstStamp) {
|
|
21849
|
+
let anchor = Infinity;
|
|
21850
|
+
for (const n of window2) if (has(n) && n.createdAt < anchor) anchor = n.createdAt;
|
|
21851
|
+
window2 = anchor === Infinity ? [] : window2.filter((n) => n.createdAt >= anchor);
|
|
21852
|
+
}
|
|
21853
|
+
let count = 0;
|
|
21854
|
+
for (const n of window2) if (has(n)) count++;
|
|
21855
|
+
return { count, total: window2.length, fraction: window2.length === 0 ? 0 : count / window2.length };
|
|
21856
|
+
}
|
|
21857
|
+
function evaluateMechanisms(store, invocations = /* @__PURE__ */ new Map(), mechanisms = MECHANISMS) {
|
|
21858
|
+
return mechanisms.map((d) => {
|
|
21859
|
+
const fed = evaluateFed(store, d);
|
|
21860
|
+
const inv = invocations.get(d.pass);
|
|
21861
|
+
const effectCount = inv?.totals[d.effectCounter] ?? 0;
|
|
21862
|
+
const backlog = d.backlogCounter ? inv?.lastTotals?.[d.backlogCounter] : void 0;
|
|
21863
|
+
const backlogWas = d.backlogCounter ? inv?.firstTotals?.[d.backlogCounter] : void 0;
|
|
21864
|
+
const span = inv?.firstTs === void 0 ? 0 : inv.lastTs - inv.firstTs;
|
|
21865
|
+
const stalled = backlog !== void 0 && backlog > 0 && effectCount === 0 && (inv?.runs ?? 0) >= STALL_MIN_RUNS && span >= STALL_MIN_SPAN_MS && (backlogWas === void 0 || backlog >= backlogWas);
|
|
21866
|
+
let verdict;
|
|
21867
|
+
if (!inv || inv.runs === 0) verdict = "never-invoked";
|
|
21868
|
+
else if (fed.fraction < d.fed.minFraction) verdict = "starved";
|
|
21869
|
+
else if (stalled) verdict = "stalled";
|
|
21870
|
+
else if (effectCount === 0) verdict = "no-effect";
|
|
21871
|
+
else verdict = "ok";
|
|
21872
|
+
return {
|
|
21873
|
+
id: d.id,
|
|
21874
|
+
what: d.what,
|
|
21875
|
+
pass: d.pass,
|
|
21876
|
+
fedCount: fed.count,
|
|
21877
|
+
fedTotal: fed.total,
|
|
21878
|
+
fedFraction: fed.fraction,
|
|
21879
|
+
minFraction: d.fed.minFraction,
|
|
21880
|
+
...inv ? { lastInvokedMs: inv.lastTs } : {},
|
|
21881
|
+
runs: inv?.runs ?? 0,
|
|
21882
|
+
effectCount,
|
|
21883
|
+
...backlog !== void 0 ? { backlog } : {},
|
|
21884
|
+
...backlogWas !== void 0 ? { backlogWas } : {},
|
|
21885
|
+
...inv?.firstTs !== void 0 ? { spanMs: span } : {},
|
|
21886
|
+
verdict,
|
|
21887
|
+
...d.note ? { note: d.note } : {}
|
|
21888
|
+
};
|
|
21889
|
+
});
|
|
21890
|
+
}
|
|
21891
|
+
function formatMechanismStatus(rows, nowMs) {
|
|
21892
|
+
return rows.map((r) => {
|
|
21893
|
+
const pct = (r.fedFraction * 100).toFixed(r.fedFraction < 0.01 ? 2 : 1);
|
|
21894
|
+
const age = r.lastInvokedMs === void 0 ? "never" : `${Math.max(0, Math.round((nowMs - r.lastInvokedMs) / 6e4))}m ago`;
|
|
21895
|
+
const mark = r.verdict === "ok" ? "ok " : r.verdict === "no-effect" ? "IDLE" : r.verdict === "stalled" ? "STUCK" : "DEAD";
|
|
21896
|
+
const hours = r.spanMs === void 0 ? 0 : Math.floor(r.spanMs / 36e5);
|
|
21897
|
+
const over = hours >= 24 ? `${Math.floor(hours / 24)}d` : `${hours}h`;
|
|
21898
|
+
const trend = r.verdict === "stalled" && r.backlog !== void 0 ? ` \u2014 ${r.backlog} waiting${r.backlogWas !== void 0 ? ` (was ${r.backlogWas})` : ""}, none cleared in ${over}` : "";
|
|
21899
|
+
return `${mark.padEnd(6)}${r.id.padEnd(20)} invoked ${age.padEnd(9)} ` + `fed ${pct}% (${r.fedCount}/${r.fedTotal})`.padEnd(28) + `effect ${r.effectCount}` + trend + (r.verdict !== "ok" && r.note ? ` \u2014 ${r.note}` : "");
|
|
21900
|
+
});
|
|
21901
|
+
}
|
|
21902
|
+
function hasStarvedMechanism(rows) {
|
|
21903
|
+
return rows.some(
|
|
21904
|
+
(r) => r.verdict === "never-invoked" || r.verdict === "starved" || r.verdict === "stalled"
|
|
21905
|
+
);
|
|
21906
|
+
}
|
|
21907
|
+
var STALL_MIN_RUNS, STALL_MIN_SPAN_MS, MECHANISMS, COLUMN_INPUTS;
|
|
21908
|
+
var init_mechanism_liveness = __esm({
|
|
21909
|
+
"../../packages/local-graph/src/mechanism-liveness.ts"() {
|
|
21910
|
+
"use strict";
|
|
21911
|
+
STALL_MIN_RUNS = 3;
|
|
21912
|
+
STALL_MIN_SPAN_MS = 60 * 60 * 1e3;
|
|
21913
|
+
MECHANISMS = [
|
|
21914
|
+
{
|
|
21915
|
+
id: "fix-candidate-ask",
|
|
21916
|
+
what: "asks an agent whether an edit to a problem's anchor fixed it",
|
|
21917
|
+
pass: "semantic-maintenance",
|
|
21918
|
+
// markFixCandidates fails CLOSED on a File anchor with no contentChangedAt —
|
|
21919
|
+
// correct (the alternative manufactured 92 asks out of no-op reindexes) and
|
|
21920
|
+
// exactly why coverage must be watched rather than assumed. Measured over
|
|
21921
|
+
// the recently-TOUCHED files, because the stamp is forward-only: whole-corpus
|
|
21922
|
+
// coverage on this store is ~0.5% and says nothing about whether the
|
|
21923
|
+
// producer works.
|
|
21924
|
+
fed: { labels: ["File"], attr: "contentChangedAt", minFraction: 0.02, recent: 200 },
|
|
21925
|
+
effectCounter: "fixCandidatesSettled",
|
|
21926
|
+
// Standing asks ARE the queue: 94 of them sat forever while the sweep
|
|
21927
|
+
// reported zero every run, and nothing could tell that from a clean backlog.
|
|
21928
|
+
backlogCounter: "fixCandidatesStanding",
|
|
21929
|
+
note: "stamped forward-only; measured over the 200 newest File nodes"
|
|
21930
|
+
},
|
|
21931
|
+
{
|
|
21932
|
+
id: "revisit-sweep",
|
|
21933
|
+
what: "retires a revisit ask once its recorded condition is met",
|
|
21934
|
+
pass: "semantic-maintenance",
|
|
21935
|
+
fed: {
|
|
21936
|
+
labels: ["Solution", "Problem", "RootCause", "Pattern"],
|
|
21937
|
+
attr: "revisitAnsweredWhen",
|
|
21938
|
+
// Only FLAGGED nodes carry it, and flags are rare by design, so the bar is
|
|
21939
|
+
// "the field is written at all" — it was written zero times before this.
|
|
21940
|
+
minFraction: 0
|
|
21941
|
+
},
|
|
21942
|
+
effectCounter: "revisitsCleared",
|
|
21943
|
+
backlogCounter: "revisitsStanding"
|
|
21944
|
+
},
|
|
21945
|
+
{
|
|
21946
|
+
id: "ingest-sequence",
|
|
21947
|
+
what: "orders knowledge arrivals so decay is driven by superseding info, not the clock",
|
|
21948
|
+
// CAPTURE, not semantic-maintenance. The sequence advances where knowledge
|
|
21949
|
+
// ENTERS the graph, and the maintenance pass never mints — so pointing this
|
|
21950
|
+
// at maintenance named a counter that is structurally always zero and the
|
|
21951
|
+
// mechanism read IDLE forever while stamping every new node. A descriptor
|
|
21952
|
+
// that cannot report an effect is the same defect it exists to detect.
|
|
21953
|
+
pass: "capture",
|
|
21954
|
+
fed: {
|
|
21955
|
+
labels: ["Problem", "Solution", "RootCause", "Pattern"],
|
|
21956
|
+
attr: "__createdAtSeq",
|
|
21957
|
+
// UNIVERSAL stamp: every semantic node minted after the producer went live
|
|
21958
|
+
// carries a sequence position, so the honest metric is "of the nodes born
|
|
21959
|
+
// since the first stamp, how many are stamped" — an invariant that should
|
|
21960
|
+
// read ~1.0 always. The 173k pre-fix nodes are deliberately never
|
|
21961
|
+
// backfilled (inventing a sequence position would feed the decay math
|
|
21962
|
+
// fabricated evidence it would read as real), and a recent-N window would
|
|
21963
|
+
// have to turn over 50 nodes before it could go green: it read 6% while
|
|
21964
|
+
// the producer was verifiably stamping every new node.
|
|
21965
|
+
minFraction: 0.9,
|
|
21966
|
+
recent: 200,
|
|
21967
|
+
sinceFirstStamp: true
|
|
21968
|
+
},
|
|
21969
|
+
effectCounter: "seqAdvanced",
|
|
21970
|
+
note: "column, not attr; measured over nodes born since the first stamp in the recent window"
|
|
21971
|
+
},
|
|
21972
|
+
{
|
|
21973
|
+
id: "render-ledger",
|
|
21974
|
+
what: "records which priors actually reached the agent, so an answer rate has a denominator",
|
|
21975
|
+
// RENDER, not semantic-maintenance — `shown` only moves during a render, so
|
|
21976
|
+
// attributing it elsewhere named an always-zero counter (same defect as
|
|
21977
|
+
// ingest-sequence's, found alongside it).
|
|
21978
|
+
pass: "render",
|
|
21979
|
+
fed: {
|
|
21980
|
+
labels: ["Problem", "Solution", "RootCause", "Pattern"],
|
|
21981
|
+
attr: "shownCount",
|
|
21982
|
+
minFraction: 5e-3
|
|
21983
|
+
},
|
|
21984
|
+
effectCounter: "shown"
|
|
21985
|
+
},
|
|
21986
|
+
{
|
|
21987
|
+
id: "orphan-reap",
|
|
21988
|
+
what: "closes File nodes whose path the indexer no longer covers",
|
|
21989
|
+
pass: "orphan-reap",
|
|
21990
|
+
// Stranded lineage is the CONDITION this clears, so a rising reading is bad;
|
|
21991
|
+
// it is declared fed-by-liveness so the row exists and the pass is watched.
|
|
21992
|
+
fed: { labels: ["File"], attr: "relPath", minFraction: 0.9 },
|
|
21993
|
+
effectCounter: "reaped"
|
|
21994
|
+
}
|
|
21995
|
+
];
|
|
21996
|
+
COLUMN_INPUTS = {
|
|
21997
|
+
__createdAtSeq: (n) => n.createdAtSeq !== void 0 && n.createdAtSeq !== null
|
|
21998
|
+
};
|
|
21999
|
+
}
|
|
22000
|
+
});
|
|
22001
|
+
|
|
21802
22002
|
// ../../packages/local-graph/src/index.ts
|
|
21803
22003
|
var src_exports2 = {};
|
|
21804
22004
|
__export(src_exports2, {
|
|
@@ -21812,12 +22012,15 @@ __export(src_exports2, {
|
|
|
21812
22012
|
JOINT_COMMUNITY_EDGES: () => JOINT_COMMUNITY_EDGES,
|
|
21813
22013
|
JOINT_COMMUNITY_LABELS: () => JOINT_COMMUNITY_LABELS,
|
|
21814
22014
|
MAX_ANCHOR_FILES: () => MAX_ANCHOR_FILES,
|
|
22015
|
+
MECHANISMS: () => MECHANISMS,
|
|
21815
22016
|
MIN_INTENT_TOKENS: () => MIN_INTENT_TOKENS,
|
|
21816
22017
|
PATTERN_DEDUP_COSINE: () => PATTERN_DEDUP_COSINE,
|
|
21817
22018
|
PERCOLATING_DRIFT_EDGES: () => PERCOLATING_DRIFT_EDGES,
|
|
21818
22019
|
PERCOLATING_EDGES: () => PERCOLATING_EDGES,
|
|
21819
22020
|
PERCOLATING_LABELS: () => PERCOLATING_LABELS,
|
|
21820
22021
|
SAME_ANCHOR_DEDUP_JACCARD: () => SAME_ANCHOR_DEDUP_JACCARD,
|
|
22022
|
+
STALL_MIN_RUNS: () => STALL_MIN_RUNS,
|
|
22023
|
+
STALL_MIN_SPAN_MS: () => STALL_MIN_SPAN_MS,
|
|
21821
22024
|
SqliteGraphStore: () => SqliteGraphStore,
|
|
21822
22025
|
addDependency: () => addDependency,
|
|
21823
22026
|
aggregateClaimConfidence: () => aggregateClaimConfidence,
|
|
@@ -21851,14 +22054,18 @@ __export(src_exports2, {
|
|
|
21851
22054
|
detectLocalCommunities: () => detectLocalCommunities,
|
|
21852
22055
|
edgeConductance: () => edgeConductance,
|
|
21853
22056
|
evaluateDependency: () => evaluateDependency,
|
|
22057
|
+
evaluateFed: () => evaluateFed,
|
|
22058
|
+
evaluateMechanisms: () => evaluateMechanisms,
|
|
21854
22059
|
findMintTimeDuplicate: () => findMintTimeDuplicate,
|
|
21855
22060
|
findOrCreatePackage: () => findOrCreatePackage,
|
|
21856
22061
|
findPath: () => findPath,
|
|
21857
22062
|
flattenCloudCounts: () => flattenCloudCounts,
|
|
21858
22063
|
foldDuplicateProblem: () => foldDuplicateProblem,
|
|
22064
|
+
formatMechanismStatus: () => formatMechanismStatus,
|
|
21859
22065
|
getClaim: () => getClaim,
|
|
21860
22066
|
harvestAbstractionFences: () => harvestAbstractionFences,
|
|
21861
22067
|
harvestTriageFences: () => harvestTriageFences,
|
|
22068
|
+
hasStarvedMechanism: () => hasStarvedMechanism,
|
|
21862
22069
|
induceAbstractions: () => induceAbstractions,
|
|
21863
22070
|
induceTriage: () => induceTriage,
|
|
21864
22071
|
ingestDesignProblem: () => ingestDesignProblem,
|
|
@@ -21948,6 +22155,7 @@ var init_src5 = __esm({
|
|
|
21948
22155
|
init_problem_package_link();
|
|
21949
22156
|
init_tools();
|
|
21950
22157
|
init_principle_sync();
|
|
22158
|
+
init_mechanism_liveness();
|
|
21951
22159
|
}
|
|
21952
22160
|
});
|
|
21953
22161
|
|
|
@@ -28477,7 +28685,7 @@ var init_motifs = __esm({
|
|
|
28477
28685
|
});
|
|
28478
28686
|
|
|
28479
28687
|
// ../../packages/generalizer/src/nightly.ts
|
|
28480
|
-
function
|
|
28688
|
+
function runGraphRescore(store) {
|
|
28481
28689
|
const started2 = Date.now();
|
|
28482
28690
|
const allowedTypes = new Set(pagerankEdgeTypes());
|
|
28483
28691
|
const nodeIds = [];
|
|
@@ -28560,11 +28768,6 @@ function runNightlyPipeline(store) {
|
|
|
28560
28768
|
for (const [id, c] of comm.community) store.updateNode(id, { community: c });
|
|
28561
28769
|
});
|
|
28562
28770
|
const motifs = promoteMotifs(store, started2);
|
|
28563
|
-
reopenAutoClosedProblems(store, started2);
|
|
28564
|
-
const revisits = clearAnsweredRevisits(store, started2);
|
|
28565
|
-
const fixCandidates = clearSettledFixCandidates(store, started2);
|
|
28566
|
-
const designResolved = markFixCandidates(store, started2);
|
|
28567
|
-
const cry = crystallize(store, { ts: started2 });
|
|
28568
28771
|
return {
|
|
28569
28772
|
scoredNodes: scored,
|
|
28570
28773
|
iterations: result.iterations,
|
|
@@ -28574,17 +28777,51 @@ function runNightlyPipeline(store) {
|
|
|
28574
28777
|
motifsPromoted: motifs.promoted,
|
|
28575
28778
|
techniques: motifs.techniques,
|
|
28576
28779
|
antipatterns: motifs.antipatterns,
|
|
28577
|
-
|
|
28578
|
-
|
|
28579
|
-
|
|
28780
|
+
durationMs: Date.now() - started2
|
|
28781
|
+
};
|
|
28782
|
+
}
|
|
28783
|
+
function runSemanticMaintenance(store) {
|
|
28784
|
+
const started2 = Date.now();
|
|
28785
|
+
reopenAutoClosedProblems(store, started2);
|
|
28786
|
+
const revisits = clearAnsweredRevisits(store, started2);
|
|
28787
|
+
const fixCandidates = clearSettledFixCandidates(store, started2);
|
|
28788
|
+
const designResolved = markFixCandidates(store, started2);
|
|
28789
|
+
const cry = crystallize(store, { ts: started2 });
|
|
28790
|
+
return {
|
|
28580
28791
|
designResolved,
|
|
28581
28792
|
revisitsCleared: revisits.cleared,
|
|
28793
|
+
revisitsStanding: revisits.standing,
|
|
28582
28794
|
fixCandidatesSettled: fixCandidates.answered + fixCandidates.ignored + fixCandidates.unsubstantiated,
|
|
28795
|
+
fixCandidates,
|
|
28583
28796
|
claimsEvaluated: cry.evaluated,
|
|
28584
28797
|
claimsDerived: cry.derived.length,
|
|
28585
28798
|
durationMs: Date.now() - started2
|
|
28586
28799
|
};
|
|
28587
28800
|
}
|
|
28801
|
+
function runNightlyPipeline(store) {
|
|
28802
|
+
const started2 = Date.now();
|
|
28803
|
+
const rescore = runGraphRescore(store);
|
|
28804
|
+
const semantic = runSemanticMaintenance(store);
|
|
28805
|
+
return {
|
|
28806
|
+
scoredNodes: rescore.scoredNodes,
|
|
28807
|
+
iterations: rescore.iterations,
|
|
28808
|
+
converged: rescore.converged,
|
|
28809
|
+
landmarks: rescore.landmarks,
|
|
28810
|
+
communities: rescore.communities,
|
|
28811
|
+
motifsPromoted: rescore.motifsPromoted,
|
|
28812
|
+
techniques: rescore.techniques,
|
|
28813
|
+
antipatterns: rescore.antipatterns,
|
|
28814
|
+
skillsInduced: 0,
|
|
28815
|
+
// skills are cloud-induced now (see above)
|
|
28816
|
+
skillsRefreshed: 0,
|
|
28817
|
+
designResolved: semantic.designResolved,
|
|
28818
|
+
revisitsCleared: semantic.revisitsCleared,
|
|
28819
|
+
fixCandidatesSettled: semantic.fixCandidatesSettled,
|
|
28820
|
+
claimsEvaluated: semantic.claimsEvaluated,
|
|
28821
|
+
claimsDerived: semantic.claimsDerived,
|
|
28822
|
+
durationMs: Date.now() - started2
|
|
28823
|
+
};
|
|
28824
|
+
}
|
|
28588
28825
|
function codeAnchorProjection(store, semanticIds, opts = {}) {
|
|
28589
28826
|
const anchorToNodes = /* @__PURE__ */ new Map();
|
|
28590
28827
|
for (const id of semanticIds) {
|
|
@@ -28874,7 +29111,9 @@ __export(src_exports4, {
|
|
|
28874
29111
|
reconcileDiagnostics: () => reconcileDiagnostics,
|
|
28875
29112
|
resolveProblem: () => resolveProblem,
|
|
28876
29113
|
runGeneralizer: () => runGeneralizer,
|
|
29114
|
+
runGraphRescore: () => runGraphRescore,
|
|
28877
29115
|
runNightlyPipeline: () => runNightlyPipeline,
|
|
29116
|
+
runSemanticMaintenance: () => runSemanticMaintenance,
|
|
28878
29117
|
scoreCandidate: () => scoreCandidate,
|
|
28879
29118
|
selectAnchorFrame: () => selectAnchorFrame
|
|
28880
29119
|
});
|
|
@@ -29521,6 +29760,7 @@ async function incrementalReindex(store, rootPath, workspaceId2, changedAbsPaths
|
|
|
29521
29760
|
};
|
|
29522
29761
|
}
|
|
29523
29762
|
const fileHashes = /* @__PURE__ */ new Map();
|
|
29763
|
+
const contentMovedPaths = /* @__PURE__ */ new Set();
|
|
29524
29764
|
for (const rel of [...changedRelPaths]) {
|
|
29525
29765
|
let h;
|
|
29526
29766
|
try {
|
|
@@ -29533,6 +29773,8 @@ async function incrementalReindex(store, rootPath, workspaceId2, changedAbsPaths
|
|
|
29533
29773
|
if (fnode && fnode.attrs["contentHash"] === h && !fileHasStrandedSymbol(store, fnode.id)) {
|
|
29534
29774
|
store.updateNode(fnode.id, { lastUpdatedAt: t });
|
|
29535
29775
|
changedRelPaths.delete(rel);
|
|
29776
|
+
} else if (!fnode || fnode.attrs["contentHash"] !== h) {
|
|
29777
|
+
contentMovedPaths.add(rel);
|
|
29536
29778
|
}
|
|
29537
29779
|
}
|
|
29538
29780
|
if (changedRelPaths.size === 0) {
|
|
@@ -29777,12 +30019,11 @@ async function incrementalReindex(store, rootPath, workspaceId2, changedAbsPaths
|
|
|
29777
30019
|
if (!h) continue;
|
|
29778
30020
|
const fnode = store.getNode(fileNodeId(workspaceId2, rel));
|
|
29779
30021
|
if (!fnode) continue;
|
|
29780
|
-
const contentMoved = fnode.attrs["contentHash"] !== h;
|
|
29781
30022
|
store.updateNode(fnode.id, {
|
|
29782
30023
|
attrs: {
|
|
29783
30024
|
...fnode.attrs,
|
|
29784
30025
|
contentHash: h,
|
|
29785
|
-
...
|
|
30026
|
+
...contentMovedPaths.has(rel) ? { contentChangedAt: t } : {}
|
|
29786
30027
|
}
|
|
29787
30028
|
});
|
|
29788
30029
|
}
|
|
@@ -30355,7 +30596,7 @@ async function scan(root, current, ignores, providers, out2) {
|
|
|
30355
30596
|
}
|
|
30356
30597
|
}
|
|
30357
30598
|
}
|
|
30358
|
-
function
|
|
30599
|
+
function gitListRelPaths(root, ignores) {
|
|
30359
30600
|
let stdout;
|
|
30360
30601
|
try {
|
|
30361
30602
|
stdout = execFileSync(
|
|
@@ -30378,6 +30619,15 @@ function gitListFiles(root, ignores, providers) {
|
|
|
30378
30619
|
if (segs.some((s) => ignores.has(s) || s.startsWith(".") && s.length > 1)) {
|
|
30379
30620
|
continue;
|
|
30380
30621
|
}
|
|
30622
|
+
out2.push(rel);
|
|
30623
|
+
}
|
|
30624
|
+
return out2;
|
|
30625
|
+
}
|
|
30626
|
+
function gitListFiles(root, ignores, providers) {
|
|
30627
|
+
const rels = gitListRelPaths(root, ignores);
|
|
30628
|
+
if (rels === null) return null;
|
|
30629
|
+
const out2 = [];
|
|
30630
|
+
for (const rel of rels) {
|
|
30381
30631
|
const abs = join8(root, rel);
|
|
30382
30632
|
let size;
|
|
30383
30633
|
try {
|
|
@@ -37717,6 +37967,7 @@ var init_csharp_treesitter = __esm({
|
|
|
37717
37967
|
// ../../packages/indexer/src/index.ts
|
|
37718
37968
|
var src_exports5 = {};
|
|
37719
37969
|
__export(src_exports5, {
|
|
37970
|
+
DEFAULT_IGNORES: () => DEFAULT_IGNORES,
|
|
37720
37971
|
DRIFT_FORK_RATIO: () => DRIFT_FORK_RATIO,
|
|
37721
37972
|
TreeSitterCSharpProvider: () => TreeSitterCSharpProvider,
|
|
37722
37973
|
TreeSitterCppProvider: () => TreeSitterCppProvider,
|
|
@@ -37733,6 +37984,7 @@ __export(src_exports5, {
|
|
|
37733
37984
|
findInnermostScope: () => findInnermostScope,
|
|
37734
37985
|
folderNodeId: () => folderNodeId,
|
|
37735
37986
|
fromHex: () => fromHex,
|
|
37987
|
+
gitListRelPaths: () => gitListRelPaths,
|
|
37736
37988
|
hammingDistance: () => hammingDistance,
|
|
37737
37989
|
hasForkedDrift: () => hasForkedDrift,
|
|
37738
37990
|
incrementalReindex: () => incrementalReindex,
|
|
@@ -37845,6 +38097,8 @@ async function findStaleFiles(store, rootPath, workspaceId2) {
|
|
|
37845
38097
|
const fnode = store.getNode(fileNodeId(workspaceId2, rel));
|
|
37846
38098
|
if (!fnode) {
|
|
37847
38099
|
stale.push(abs);
|
|
38100
|
+
} else if ((fnode.validTo ?? null) !== null) {
|
|
38101
|
+
stale.push(abs);
|
|
37848
38102
|
} else if (fnode.lastUpdatedAt < mtimeMs) {
|
|
37849
38103
|
stale.push(abs);
|
|
37850
38104
|
} else {
|
|
@@ -37880,19 +38134,67 @@ function findStrandedSymbols(store) {
|
|
|
37880
38134
|
}
|
|
37881
38135
|
return stranded;
|
|
37882
38136
|
}
|
|
38137
|
+
function reapOrphanedFiles(store, rootPath, workspaceId2, ignoreDirs = []) {
|
|
38138
|
+
const ignores = /* @__PURE__ */ new Set([...DEFAULT_IGNORES, ...ignoreDirs]);
|
|
38139
|
+
const listed = gitListRelPaths(rootPath, ignores);
|
|
38140
|
+
if (listed === null) return { reaped: 0, symbolsClosed: 0, skipped: "no-git-listing" };
|
|
38141
|
+
if (listed.length === 0) return { reaped: 0, symbolsClosed: 0, skipped: "empty-listing" };
|
|
38142
|
+
const onDisk = new Set(listed);
|
|
38143
|
+
const live = store.findNodesByLabel("File").filter((f) => f.attrs["workspaceId"] === workspaceId2);
|
|
38144
|
+
const orphans = live.filter((f) => {
|
|
38145
|
+
const rel = f.attrs["relPath"];
|
|
38146
|
+
return typeof rel === "string" && !onDisk.has(rel);
|
|
38147
|
+
});
|
|
38148
|
+
const allowance = Math.max(ORPHAN_REAP_MIN_ALLOWANCE, live.length * ORPHAN_REAP_MAX_FRACTION);
|
|
38149
|
+
if (orphans.length > allowance) {
|
|
38150
|
+
return {
|
|
38151
|
+
reaped: 0,
|
|
38152
|
+
symbolsClosed: 0,
|
|
38153
|
+
skipped: "over-fraction",
|
|
38154
|
+
candidates: orphans.length
|
|
38155
|
+
};
|
|
38156
|
+
}
|
|
38157
|
+
const t = Date.now();
|
|
38158
|
+
let symbolsClosed = 0;
|
|
38159
|
+
store.transaction(() => {
|
|
38160
|
+
for (const f of orphans) {
|
|
38161
|
+
for (const e of store.outEdges(f.id, ["DEFINES", "CONTAINS"])) {
|
|
38162
|
+
store.closeEdge(e.id, t);
|
|
38163
|
+
const sym = store.getNode(e.to);
|
|
38164
|
+
if (sym && (sym.validTo ?? null) === null) {
|
|
38165
|
+
store.closeNode(sym.id, t);
|
|
38166
|
+
symbolsClosed++;
|
|
38167
|
+
}
|
|
38168
|
+
}
|
|
38169
|
+
store.closeNode(f.id, t);
|
|
38170
|
+
}
|
|
38171
|
+
});
|
|
38172
|
+
return { reaped: orphans.length, symbolsClosed };
|
|
38173
|
+
}
|
|
37883
38174
|
async function reconcileStaleFiles(store, rootPath, workspaceId2) {
|
|
37884
38175
|
const stale = await findStaleFiles(store, rootPath, workspaceId2);
|
|
37885
38176
|
if (stale.length === 0) return 0;
|
|
37886
38177
|
let total = 0;
|
|
38178
|
+
let failedBatches = 0;
|
|
37887
38179
|
const BATCH = 20;
|
|
37888
38180
|
for (let i2 = 0; i2 < stale.length; i2 += BATCH) {
|
|
37889
|
-
|
|
37890
|
-
|
|
38181
|
+
try {
|
|
38182
|
+
const r = await incrementalReindex(store, rootPath, workspaceId2, stale.slice(i2, i2 + BATCH));
|
|
38183
|
+
total += r.filesReindexed;
|
|
38184
|
+
} catch (err2) {
|
|
38185
|
+
failedBatches++;
|
|
38186
|
+
console.warn(
|
|
38187
|
+
`[errata] reconcile: batch ${i2 / BATCH + 1} failed (${stale.slice(i2, i2 + BATCH).length} file(s) skipped): ${err2 instanceof Error ? err2.message : err2}`
|
|
38188
|
+
);
|
|
38189
|
+
}
|
|
37891
38190
|
if (i2 + BATCH < stale.length) await new Promise((res) => setImmediate(res));
|
|
37892
38191
|
}
|
|
38192
|
+
if (failedBatches > 0) {
|
|
38193
|
+
console.warn(`[errata] reconcile: ${failedBatches} batch(es) failed; ${total} file(s) reindexed`);
|
|
38194
|
+
}
|
|
37893
38195
|
return total;
|
|
37894
38196
|
}
|
|
37895
|
-
var IGNORED, SOURCE_RE, SCAN_YIELD_EVERY, LIVENESS_CHUNK;
|
|
38197
|
+
var IGNORED, SOURCE_RE, SCAN_YIELD_EVERY, LIVENESS_CHUNK, ORPHAN_REAP_MAX_FRACTION, ORPHAN_REAP_MIN_ALLOWANCE;
|
|
37896
38198
|
var init_reconcile = __esm({
|
|
37897
38199
|
"src/reconcile.ts"() {
|
|
37898
38200
|
"use strict";
|
|
@@ -37901,6 +38203,8 @@ var init_reconcile = __esm({
|
|
|
37901
38203
|
SOURCE_RE = /\.(ts|tsx|js|jsx|mjs|cjs|py)$/i;
|
|
37902
38204
|
SCAN_YIELD_EVERY = 100;
|
|
37903
38205
|
LIVENESS_CHUNK = 4e3;
|
|
38206
|
+
ORPHAN_REAP_MAX_FRACTION = 0.25;
|
|
38207
|
+
ORPHAN_REAP_MIN_ALLOWANCE = 50;
|
|
37904
38208
|
}
|
|
37905
38209
|
});
|
|
37906
38210
|
|
|
@@ -48064,27 +48368,27 @@ __export(witness_ledger_exports, {
|
|
|
48064
48368
|
summarizeWitnessLedger: () => summarizeWitnessLedger,
|
|
48065
48369
|
witnessLedgerPath: () => witnessLedgerPath
|
|
48066
48370
|
});
|
|
48067
|
-
import { appendFileSync as
|
|
48068
|
-
import { join as
|
|
48371
|
+
import { appendFileSync as appendFileSync3, existsSync as existsSync21, readFileSync as readFileSync21, writeFileSync as writeFileSync18 } from "node:fs";
|
|
48372
|
+
import { join as join26 } from "node:path";
|
|
48069
48373
|
function witnessLedgerPath(configDir) {
|
|
48070
|
-
return
|
|
48374
|
+
return join26(configDir, "witness-ledger.jsonl");
|
|
48071
48375
|
}
|
|
48072
48376
|
function appendWitnessLedger(configDir, entry) {
|
|
48073
48377
|
const path2 = witnessLedgerPath(configDir);
|
|
48074
48378
|
try {
|
|
48075
|
-
|
|
48076
|
-
const lines =
|
|
48379
|
+
appendFileSync3(path2, JSON.stringify(entry) + "\n");
|
|
48380
|
+
const lines = readFileSync21(path2, "utf8").split("\n").filter(Boolean);
|
|
48077
48381
|
if (lines.length > LEDGER_MAX_LINES) {
|
|
48078
|
-
|
|
48382
|
+
writeFileSync18(path2, lines.slice(-Math.floor(LEDGER_MAX_LINES / 2)).join("\n") + "\n");
|
|
48079
48383
|
}
|
|
48080
48384
|
} catch {
|
|
48081
48385
|
}
|
|
48082
48386
|
}
|
|
48083
48387
|
function readWitnessLedger(configDir) {
|
|
48084
48388
|
const path2 = witnessLedgerPath(configDir);
|
|
48085
|
-
if (!
|
|
48389
|
+
if (!existsSync21(path2)) return [];
|
|
48086
48390
|
try {
|
|
48087
|
-
return
|
|
48391
|
+
return readFileSync21(path2, "utf8").split("\n").filter(Boolean).map((l) => JSON.parse(l)).filter((e) => typeof e.ts === "number" && typeof e.channel === "string");
|
|
48088
48392
|
} catch {
|
|
48089
48393
|
return [];
|
|
48090
48394
|
}
|
|
@@ -48510,12 +48814,12 @@ var init_report_render = __esm({
|
|
|
48510
48814
|
|
|
48511
48815
|
// src/cli.ts
|
|
48512
48816
|
init_src6();
|
|
48513
|
-
import { closeSync as closeSync2, existsSync as
|
|
48514
|
-
import { join as
|
|
48817
|
+
import { closeSync as closeSync2, existsSync as existsSync28, openSync as openSync2, readFileSync as readFileSync27, renameSync as renameSync4, statSync as statSync6 } from "node:fs";
|
|
48818
|
+
import { join as join31 } from "node:path";
|
|
48515
48819
|
import { spawn as spawn3 } from "node:child_process";
|
|
48516
48820
|
|
|
48517
48821
|
// src/daemon.ts
|
|
48518
|
-
import { existsSync as
|
|
48822
|
+
import { existsSync as existsSync23, writeFileSync as writeFileSync20 } from "node:fs";
|
|
48519
48823
|
|
|
48520
48824
|
// ../../node_modules/.pnpm/@hono+node-server@1.19.11_hono@4.12.8/node_modules/@hono/node-server/dist/index.mjs
|
|
48521
48825
|
import { createServer as createServerHTTP } from "http";
|
|
@@ -49095,8 +49399,8 @@ init_config();
|
|
|
49095
49399
|
|
|
49096
49400
|
// src/engine.ts
|
|
49097
49401
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
49098
|
-
import { existsSync as
|
|
49099
|
-
import { join as
|
|
49402
|
+
import { existsSync as existsSync22, statSync as statSync5, appendFileSync as appendFileSync4, readdirSync as readdirSync9, renameSync as renameSync3, readFileSync as readFileSync22, writeFileSync as writeFileSync19 } from "node:fs";
|
|
49403
|
+
import { join as join27, relative as relative6, sep as sep4 } from "node:path";
|
|
49100
49404
|
|
|
49101
49405
|
// ../../node_modules/.pnpm/chokidar@4.0.3/node_modules/chokidar/esm/index.js
|
|
49102
49406
|
import { stat as statcb } from "fs";
|
|
@@ -52195,6 +52499,48 @@ function repairInvalidEdges(store, opts) {
|
|
|
52195
52499
|
init_symbol_summaries();
|
|
52196
52500
|
init_reconcile();
|
|
52197
52501
|
|
|
52502
|
+
// src/pass-ledger.ts
|
|
52503
|
+
import { appendFileSync as appendFileSync2, existsSync as existsSync15, readFileSync as readFileSync13, writeFileSync as writeFileSync13 } from "node:fs";
|
|
52504
|
+
import { join as join18 } from "node:path";
|
|
52505
|
+
var PER_KIND_MAX = 100;
|
|
52506
|
+
var TRIM_EVERY = 50;
|
|
52507
|
+
var appendsSinceTrim = /* @__PURE__ */ new Map();
|
|
52508
|
+
function passLedgerPath(configDir) {
|
|
52509
|
+
return join18(configDir, "pass-ledger.jsonl");
|
|
52510
|
+
}
|
|
52511
|
+
function appendPassLedger(configDir, kind, durationMs, counts) {
|
|
52512
|
+
const path2 = passLedgerPath(configDir);
|
|
52513
|
+
try {
|
|
52514
|
+
const entry = { ts: Date.now(), kind, durationMs, counts };
|
|
52515
|
+
appendFileSync2(path2, JSON.stringify(entry) + "\n");
|
|
52516
|
+
const n = (appendsSinceTrim.get(path2) ?? 0) + 1;
|
|
52517
|
+
if (n < TRIM_EVERY) {
|
|
52518
|
+
appendsSinceTrim.set(path2, n);
|
|
52519
|
+
return;
|
|
52520
|
+
}
|
|
52521
|
+
appendsSinceTrim.set(path2, 0);
|
|
52522
|
+
const lines = readFileSync13(path2, "utf8").split("\n").filter(Boolean);
|
|
52523
|
+
const keptByKind = /* @__PURE__ */ new Map();
|
|
52524
|
+
const kept = [];
|
|
52525
|
+
for (let i2 = lines.length - 1; i2 >= 0; i2--) {
|
|
52526
|
+
let kind2;
|
|
52527
|
+
try {
|
|
52528
|
+
kind2 = String(JSON.parse(lines[i2]).kind ?? "");
|
|
52529
|
+
} catch {
|
|
52530
|
+
continue;
|
|
52531
|
+
}
|
|
52532
|
+
const n2 = keptByKind.get(kind2) ?? 0;
|
|
52533
|
+
if (n2 >= PER_KIND_MAX) continue;
|
|
52534
|
+
keptByKind.set(kind2, n2 + 1);
|
|
52535
|
+
kept.push(lines[i2]);
|
|
52536
|
+
}
|
|
52537
|
+
if (kept.length < lines.length) {
|
|
52538
|
+
writeFileSync13(path2, kept.reverse().join("\n") + "\n");
|
|
52539
|
+
}
|
|
52540
|
+
} catch {
|
|
52541
|
+
}
|
|
52542
|
+
}
|
|
52543
|
+
|
|
52198
52544
|
// src/episode.ts
|
|
52199
52545
|
init_src();
|
|
52200
52546
|
function deltaIsEmpty(d) {
|
|
@@ -52389,11 +52735,11 @@ init_outbox();
|
|
|
52389
52735
|
init_src9();
|
|
52390
52736
|
init_src();
|
|
52391
52737
|
init_src2();
|
|
52392
|
-
import { readFileSync as
|
|
52393
|
-
import { join as
|
|
52738
|
+
import { readFileSync as readFileSync14 } from "node:fs";
|
|
52739
|
+
import { join as join19 } from "node:path";
|
|
52394
52740
|
function loadClaimIgnorePatterns(workspaceRoot) {
|
|
52395
52741
|
try {
|
|
52396
|
-
return
|
|
52742
|
+
return readFileSync14(join19(workspaceRoot, ".errataignore"), "utf8").split(/\r?\n/).map((l) => l.trim()).filter((l) => l.length > 0 && !l.startsWith("#")).map((l) => l.toLowerCase());
|
|
52397
52743
|
} catch {
|
|
52398
52744
|
return [];
|
|
52399
52745
|
}
|
|
@@ -52754,22 +53100,22 @@ async function pullCloudTriage(shared, cloud, profile, limit = 50) {
|
|
|
52754
53100
|
}
|
|
52755
53101
|
|
|
52756
53102
|
// src/git-sensor.ts
|
|
52757
|
-
import { existsSync as
|
|
52758
|
-
import { join as
|
|
53103
|
+
import { existsSync as existsSync16, readFileSync as readFileSync15, watch as fsWatch } from "node:fs";
|
|
53104
|
+
import { join as join20 } from "node:path";
|
|
52759
53105
|
function readFirstLine(path2) {
|
|
52760
53106
|
try {
|
|
52761
|
-
return
|
|
53107
|
+
return readFileSync15(path2, "utf8").split(/\r?\n/, 1)[0].trim();
|
|
52762
53108
|
} catch {
|
|
52763
53109
|
return null;
|
|
52764
53110
|
}
|
|
52765
53111
|
}
|
|
52766
53112
|
function readGitRefState(gitDir) {
|
|
52767
|
-
const head2 = readFirstLine(
|
|
53113
|
+
const head2 = readFirstLine(join20(gitDir, "HEAD"));
|
|
52768
53114
|
const m = head2 ? /^ref:\s*refs\/heads\/(.+)$/.exec(head2) : null;
|
|
52769
53115
|
const branch = m ? m[1] : null;
|
|
52770
53116
|
let sha2 = null;
|
|
52771
53117
|
if (branch) {
|
|
52772
|
-
sha2 = readFirstLine(
|
|
53118
|
+
sha2 = readFirstLine(join20(gitDir, "refs", "heads", branch));
|
|
52773
53119
|
if (!sha2) sha2 = shaFromPackedRefs(gitDir, `refs/heads/${branch}`);
|
|
52774
53120
|
} else if (head2 && /^[0-9a-f]{7,40}$/i.test(head2)) {
|
|
52775
53121
|
sha2 = head2;
|
|
@@ -52777,13 +53123,13 @@ function readGitRefState(gitDir) {
|
|
|
52777
53123
|
return {
|
|
52778
53124
|
branch,
|
|
52779
53125
|
sha: sha2,
|
|
52780
|
-
mergeHeadExists:
|
|
52781
|
-
origHeadExists:
|
|
53126
|
+
mergeHeadExists: existsSync16(join20(gitDir, "MERGE_HEAD")),
|
|
53127
|
+
origHeadExists: existsSync16(join20(gitDir, "ORIG_HEAD"))
|
|
52782
53128
|
};
|
|
52783
53129
|
}
|
|
52784
53130
|
function shaFromPackedRefs(gitDir, ref) {
|
|
52785
53131
|
try {
|
|
52786
|
-
for (const line of
|
|
53132
|
+
for (const line of readFileSync15(join20(gitDir, "packed-refs"), "utf8").split(/\r?\n/)) {
|
|
52787
53133
|
const [sha2, name2] = line.split(/\s+/);
|
|
52788
53134
|
if (name2 === ref && sha2) return sha2;
|
|
52789
53135
|
}
|
|
@@ -52817,7 +53163,7 @@ function startGitSensor(gitDir, onEvent, opts = {}) {
|
|
|
52817
53163
|
const settle = () => {
|
|
52818
53164
|
if (timer) clearTimeout(timer);
|
|
52819
53165
|
timer = setTimeout(() => {
|
|
52820
|
-
if (
|
|
53166
|
+
if (existsSync16(join20(gitDir, "index.lock"))) {
|
|
52821
53167
|
settle();
|
|
52822
53168
|
return;
|
|
52823
53169
|
}
|
|
@@ -52828,7 +53174,7 @@ function startGitSensor(gitDir, onEvent, opts = {}) {
|
|
|
52828
53174
|
}, debounceMs);
|
|
52829
53175
|
};
|
|
52830
53176
|
for (const sub of ["HEAD", "logs/HEAD", "MERGE_HEAD", "ORIG_HEAD"]) {
|
|
52831
|
-
const p =
|
|
53177
|
+
const p = join20(gitDir, sub);
|
|
52832
53178
|
try {
|
|
52833
53179
|
watchers.push(fsWatch(p, settle));
|
|
52834
53180
|
} catch {
|
|
@@ -53053,21 +53399,21 @@ var TelemetryRecorder = class {
|
|
|
53053
53399
|
|
|
53054
53400
|
// src/skills.ts
|
|
53055
53401
|
import {
|
|
53056
|
-
existsSync as
|
|
53402
|
+
existsSync as existsSync17,
|
|
53057
53403
|
mkdirSync as mkdirSync6,
|
|
53058
|
-
readFileSync as
|
|
53404
|
+
readFileSync as readFileSync16,
|
|
53059
53405
|
readdirSync as readdirSync7,
|
|
53060
53406
|
unlinkSync as unlinkSync2,
|
|
53061
|
-
writeFileSync as
|
|
53407
|
+
writeFileSync as writeFileSync14
|
|
53062
53408
|
} from "node:fs";
|
|
53063
|
-
import { basename as basename4, join as
|
|
53409
|
+
import { basename as basename4, join as join21 } from "node:path";
|
|
53064
53410
|
function skillFileName(id) {
|
|
53065
53411
|
return `${id.replace(/[^A-Za-z0-9_.-]/g, "_")}.md`;
|
|
53066
53412
|
}
|
|
53067
53413
|
function readSkillManifest(manifestPath) {
|
|
53068
|
-
if (!
|
|
53414
|
+
if (!existsSync17(manifestPath)) return [];
|
|
53069
53415
|
try {
|
|
53070
|
-
const parsed = JSON.parse(
|
|
53416
|
+
const parsed = JSON.parse(readFileSync16(manifestPath, "utf8"));
|
|
53071
53417
|
return (parsed.skills ?? []).map((s) => ({
|
|
53072
53418
|
title: s.title ?? "",
|
|
53073
53419
|
layer: s.layer ?? "technique",
|
|
@@ -53091,7 +53437,7 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
|
|
|
53091
53437
|
for (const s of res.skills) {
|
|
53092
53438
|
const fileName = skillFileName(s.id);
|
|
53093
53439
|
keep.add(fileName);
|
|
53094
|
-
|
|
53440
|
+
writeFileSync14(join21(paths.skillsDir, fileName), s.markdown, "utf8");
|
|
53095
53441
|
rows.push({
|
|
53096
53442
|
id: s.id,
|
|
53097
53443
|
title: s.title,
|
|
@@ -53104,7 +53450,7 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
|
|
|
53104
53450
|
const fileName = skillFileName(p.id);
|
|
53105
53451
|
if (keep.has(fileName)) continue;
|
|
53106
53452
|
keep.add(fileName);
|
|
53107
|
-
|
|
53453
|
+
writeFileSync14(join21(paths.skillsDir, fileName), p.markdown, "utf8");
|
|
53108
53454
|
rows.push({
|
|
53109
53455
|
id: p.id,
|
|
53110
53456
|
title: p.title,
|
|
@@ -53118,13 +53464,13 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
|
|
|
53118
53464
|
if (!f.endsWith(".md")) continue;
|
|
53119
53465
|
if (keep.has(basename4(f))) continue;
|
|
53120
53466
|
try {
|
|
53121
|
-
unlinkSync2(
|
|
53467
|
+
unlinkSync2(join21(paths.skillsDir, f));
|
|
53122
53468
|
pruned++;
|
|
53123
53469
|
} catch {
|
|
53124
53470
|
}
|
|
53125
53471
|
}
|
|
53126
53472
|
rows.sort((a, b) => a.id.localeCompare(b.id));
|
|
53127
|
-
|
|
53473
|
+
writeFileSync14(
|
|
53128
53474
|
paths.skillsManifest,
|
|
53129
53475
|
JSON.stringify({ generatedAt: Date.now(), skills: rows }, null, 2),
|
|
53130
53476
|
"utf8"
|
|
@@ -53136,22 +53482,22 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
|
|
|
53136
53482
|
init_src2();
|
|
53137
53483
|
import {
|
|
53138
53484
|
cpSync,
|
|
53139
|
-
existsSync as
|
|
53485
|
+
existsSync as existsSync18,
|
|
53140
53486
|
lstatSync,
|
|
53141
53487
|
mkdirSync as mkdirSync7,
|
|
53142
|
-
readFileSync as
|
|
53488
|
+
readFileSync as readFileSync17,
|
|
53143
53489
|
readdirSync as readdirSync8,
|
|
53144
53490
|
rmSync as rmSync2,
|
|
53145
53491
|
symlinkSync,
|
|
53146
|
-
writeFileSync as
|
|
53492
|
+
writeFileSync as writeFileSync15
|
|
53147
53493
|
} from "node:fs";
|
|
53148
|
-
import { join as
|
|
53494
|
+
import { join as join22 } from "node:path";
|
|
53149
53495
|
var SKILL_NS = "errata-";
|
|
53150
53496
|
var HARNESS_SKILL_DIRS = [
|
|
53151
|
-
{ configDir: ".claude", skillsDir:
|
|
53497
|
+
{ configDir: ".claude", skillsDir: join22(".claude", "skills") },
|
|
53152
53498
|
// Cursor adopted the standard; its exact project dir is still moving — kept
|
|
53153
53499
|
// best-effort and gated on `.cursor/` presence so we never create it blind.
|
|
53154
|
-
{ configDir: ".cursor", skillsDir:
|
|
53500
|
+
{ configDir: ".cursor", skillsDir: join22(".cursor", "skills") }
|
|
53155
53501
|
];
|
|
53156
53502
|
function skillSlug(title, id) {
|
|
53157
53503
|
const base = title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || id.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "skill";
|
|
@@ -53196,12 +53542,12 @@ function skillCiteHandle(s) {
|
|
|
53196
53542
|
return priorHandle({ id: s.id, description: s.title });
|
|
53197
53543
|
}
|
|
53198
53544
|
function reconcileNamespaced(dir, keep) {
|
|
53199
|
-
if (!
|
|
53545
|
+
if (!existsSync18(dir)) return 0;
|
|
53200
53546
|
let pruned = 0;
|
|
53201
53547
|
for (const name2 of readdirSync8(dir)) {
|
|
53202
53548
|
if (!name2.startsWith(SKILL_NS) || keep.has(name2)) continue;
|
|
53203
53549
|
try {
|
|
53204
|
-
rmSync2(
|
|
53550
|
+
rmSync2(join22(dir, name2), { recursive: true, force: true });
|
|
53205
53551
|
pruned++;
|
|
53206
53552
|
} catch {
|
|
53207
53553
|
}
|
|
@@ -53210,7 +53556,7 @@ function reconcileNamespaced(dir, keep) {
|
|
|
53210
53556
|
}
|
|
53211
53557
|
function linkOrCopy(linkPath, target) {
|
|
53212
53558
|
try {
|
|
53213
|
-
if (
|
|
53559
|
+
if (existsSync18(linkPath) || safeLstat(linkPath)) rmSync2(linkPath, { recursive: true, force: true });
|
|
53214
53560
|
} catch {
|
|
53215
53561
|
}
|
|
53216
53562
|
try {
|
|
@@ -53231,7 +53577,7 @@ function safeLstat(p) {
|
|
|
53231
53577
|
}
|
|
53232
53578
|
}
|
|
53233
53579
|
function emitAndProjectSkills(root, skills) {
|
|
53234
|
-
const agentsSkillsDir =
|
|
53580
|
+
const agentsSkillsDir = join22(root, ".agents", "skills");
|
|
53235
53581
|
mkdirSync7(agentsSkillsDir, { recursive: true });
|
|
53236
53582
|
const slugs = [];
|
|
53237
53583
|
const keep = /* @__PURE__ */ new Set();
|
|
@@ -53239,7 +53585,7 @@ function emitAndProjectSkills(root, skills) {
|
|
|
53239
53585
|
for (const s of skills) {
|
|
53240
53586
|
let body2;
|
|
53241
53587
|
try {
|
|
53242
|
-
body2 =
|
|
53588
|
+
body2 = readFileSync17(s.bodyPath, "utf8");
|
|
53243
53589
|
} catch {
|
|
53244
53590
|
continue;
|
|
53245
53591
|
}
|
|
@@ -53248,9 +53594,9 @@ function emitAndProjectSkills(root, skills) {
|
|
|
53248
53594
|
keep.add(slug2);
|
|
53249
53595
|
slugs.push(slug2);
|
|
53250
53596
|
const description = deriveDescription(s.title, s.layer, body2);
|
|
53251
|
-
mkdirSync7(
|
|
53252
|
-
|
|
53253
|
-
|
|
53597
|
+
mkdirSync7(join22(agentsSkillsDir, slug2), { recursive: true });
|
|
53598
|
+
writeFileSync15(
|
|
53599
|
+
join22(agentsSkillsDir, slug2, "SKILL.md"),
|
|
53254
53600
|
renderSkillMd(slug2, description, body2, skillCiteHandle(s)),
|
|
53255
53601
|
"utf8"
|
|
53256
53602
|
);
|
|
@@ -53259,11 +53605,11 @@ function emitAndProjectSkills(root, skills) {
|
|
|
53259
53605
|
reconcileNamespaced(agentsSkillsDir, keep);
|
|
53260
53606
|
let projected = 0;
|
|
53261
53607
|
for (const h of HARNESS_SKILL_DIRS) {
|
|
53262
|
-
if (!
|
|
53263
|
-
const dir =
|
|
53608
|
+
if (!existsSync18(join22(root, h.configDir))) continue;
|
|
53609
|
+
const dir = join22(root, h.skillsDir);
|
|
53264
53610
|
mkdirSync7(dir, { recursive: true });
|
|
53265
53611
|
for (const slug2 of slugs) {
|
|
53266
|
-
linkOrCopy(
|
|
53612
|
+
linkOrCopy(join22(dir, slug2), join22(agentsSkillsDir, slug2));
|
|
53267
53613
|
projected++;
|
|
53268
53614
|
}
|
|
53269
53615
|
reconcileNamespaced(dir, keep);
|
|
@@ -53272,15 +53618,15 @@ function emitAndProjectSkills(root, skills) {
|
|
|
53272
53618
|
return { slugs, emitted, projected };
|
|
53273
53619
|
}
|
|
53274
53620
|
function emitInputsFromManifest(erretaDir, manifestPath) {
|
|
53275
|
-
if (!
|
|
53621
|
+
if (!existsSync18(manifestPath)) return [];
|
|
53276
53622
|
try {
|
|
53277
|
-
const parsed = JSON.parse(
|
|
53623
|
+
const parsed = JSON.parse(readFileSync17(manifestPath, "utf8"));
|
|
53278
53624
|
return (parsed.skills ?? []).filter((s) => Boolean(s.id && s.file)).map((s) => ({
|
|
53279
53625
|
id: s.id,
|
|
53280
53626
|
title: s.title ?? s.id,
|
|
53281
53627
|
layer: s.layer ?? "technique",
|
|
53282
53628
|
confidence: s.confidence ?? 0,
|
|
53283
|
-
bodyPath:
|
|
53629
|
+
bodyPath: join22(erretaDir, s.file)
|
|
53284
53630
|
}));
|
|
53285
53631
|
} catch {
|
|
53286
53632
|
return [];
|
|
@@ -53294,17 +53640,17 @@ var GITIGNORE_LINES = [
|
|
|
53294
53640
|
".cursor/skills/errata-*/"
|
|
53295
53641
|
];
|
|
53296
53642
|
function ensureSkillGitignore(root) {
|
|
53297
|
-
const path2 =
|
|
53643
|
+
const path2 = join22(root, ".gitignore");
|
|
53298
53644
|
let current = "";
|
|
53299
53645
|
try {
|
|
53300
|
-
current =
|
|
53646
|
+
current = existsSync18(path2) ? readFileSync17(path2, "utf8") : "";
|
|
53301
53647
|
} catch {
|
|
53302
53648
|
return;
|
|
53303
53649
|
}
|
|
53304
53650
|
if (current.includes(GITIGNORE_MARK)) return;
|
|
53305
53651
|
const prefix = current.length > 0 && !current.endsWith("\n") ? "\n" : "";
|
|
53306
53652
|
try {
|
|
53307
|
-
|
|
53653
|
+
writeFileSync15(path2, `${current}${prefix}
|
|
53308
53654
|
${GITIGNORE_LINES.join("\n")}
|
|
53309
53655
|
`, "utf8");
|
|
53310
53656
|
} catch {
|
|
@@ -53397,20 +53743,20 @@ init_paths();
|
|
|
53397
53743
|
// src/profile.ts
|
|
53398
53744
|
init_src2();
|
|
53399
53745
|
init_paths();
|
|
53400
|
-
import { existsSync as
|
|
53746
|
+
import { existsSync as existsSync20, readFileSync as readFileSync19, writeFileSync as writeFileSync16 } from "node:fs";
|
|
53401
53747
|
import { createHash as createHash12 } from "node:crypto";
|
|
53402
|
-
import { join as
|
|
53748
|
+
import { join as join24 } from "node:path";
|
|
53403
53749
|
|
|
53404
53750
|
// src/git-remote.ts
|
|
53405
53751
|
init_src();
|
|
53406
|
-
import { existsSync as
|
|
53407
|
-
import { isAbsolute as isAbsolute3, join as
|
|
53752
|
+
import { existsSync as existsSync19, readFileSync as readFileSync18, statSync as statSync4 } from "node:fs";
|
|
53753
|
+
import { isAbsolute as isAbsolute3, join as join23, resolve as resolve5 } from "node:path";
|
|
53408
53754
|
function resolveGitDir(root) {
|
|
53409
|
-
const dotGit =
|
|
53755
|
+
const dotGit = join23(root, ".git");
|
|
53410
53756
|
try {
|
|
53411
53757
|
const st = statSync4(dotGit);
|
|
53412
53758
|
if (st.isDirectory()) return dotGit;
|
|
53413
|
-
const m = /^gitdir:\s*(.+?)\s*$/m.exec(
|
|
53759
|
+
const m = /^gitdir:\s*(.+?)\s*$/m.exec(readFileSync18(dotGit, "utf8"));
|
|
53414
53760
|
if (!m) return null;
|
|
53415
53761
|
const dir = m[1];
|
|
53416
53762
|
return isAbsolute3(dir) ? dir : resolve5(root, dir);
|
|
@@ -53419,22 +53765,22 @@ function resolveGitDir(root) {
|
|
|
53419
53765
|
}
|
|
53420
53766
|
}
|
|
53421
53767
|
function gitConfigPath(gitDir) {
|
|
53422
|
-
const commondirFile =
|
|
53423
|
-
if (
|
|
53424
|
-
const common =
|
|
53768
|
+
const commondirFile = join23(gitDir, "commondir");
|
|
53769
|
+
if (existsSync19(commondirFile)) {
|
|
53770
|
+
const common = readFileSync18(commondirFile, "utf8").trim();
|
|
53425
53771
|
const commonDir = isAbsolute3(common) ? common : resolve5(gitDir, common);
|
|
53426
|
-
return
|
|
53772
|
+
return join23(commonDir, "config");
|
|
53427
53773
|
}
|
|
53428
|
-
return
|
|
53774
|
+
return join23(gitDir, "config");
|
|
53429
53775
|
}
|
|
53430
53776
|
function readRemotes(root) {
|
|
53431
53777
|
const gitDir = resolveGitDir(root);
|
|
53432
53778
|
if (!gitDir) return [];
|
|
53433
53779
|
const cfgPath = gitConfigPath(gitDir);
|
|
53434
|
-
if (!
|
|
53780
|
+
if (!existsSync19(cfgPath)) return [];
|
|
53435
53781
|
let txt;
|
|
53436
53782
|
try {
|
|
53437
|
-
txt =
|
|
53783
|
+
txt = readFileSync18(cfgPath, "utf8");
|
|
53438
53784
|
} catch {
|
|
53439
53785
|
return [];
|
|
53440
53786
|
}
|
|
@@ -53476,13 +53822,13 @@ function refreshRepoLocator(root, profile) {
|
|
|
53476
53822
|
}
|
|
53477
53823
|
function loadProfile(root) {
|
|
53478
53824
|
const p = workspacePaths(root);
|
|
53479
|
-
if (!
|
|
53480
|
-
return JSON.parse(
|
|
53825
|
+
if (!existsSync20(p.workspaceJson)) return null;
|
|
53826
|
+
return JSON.parse(readFileSync19(p.workspaceJson, "utf8"));
|
|
53481
53827
|
}
|
|
53482
53828
|
function saveProfile(root, profile) {
|
|
53483
53829
|
const p = workspacePaths(root);
|
|
53484
53830
|
ensureDir(p.configDir);
|
|
53485
|
-
|
|
53831
|
+
writeFileSync16(p.workspaceJson, JSON.stringify(profile, null, 2), "utf8");
|
|
53486
53832
|
}
|
|
53487
53833
|
function autodetectProfile(root) {
|
|
53488
53834
|
const id = workspaceId(root);
|
|
@@ -53490,10 +53836,10 @@ function autodetectProfile(root) {
|
|
|
53490
53836
|
const p = emptyProfile(id, name2);
|
|
53491
53837
|
const locator = detectRepoLocator(root);
|
|
53492
53838
|
if (locator) p.repoLocator = locator;
|
|
53493
|
-
const pkgPath =
|
|
53494
|
-
if (
|
|
53839
|
+
const pkgPath = join24(root, "package.json");
|
|
53840
|
+
if (existsSync20(pkgPath)) {
|
|
53495
53841
|
try {
|
|
53496
|
-
const pkg = JSON.parse(
|
|
53842
|
+
const pkg = JSON.parse(readFileSync19(pkgPath, "utf8"));
|
|
53497
53843
|
p.languages.push("typescript", "javascript");
|
|
53498
53844
|
const nodeVer = pkg.engines?.node ?? "node";
|
|
53499
53845
|
p.stack.push(`node@${nodeVer}`);
|
|
@@ -53514,10 +53860,10 @@ function autodetectProfile(root) {
|
|
|
53514
53860
|
} catch {
|
|
53515
53861
|
}
|
|
53516
53862
|
}
|
|
53517
|
-
const pyproject =
|
|
53518
|
-
if (
|
|
53863
|
+
const pyproject = join24(root, "pyproject.toml");
|
|
53864
|
+
if (existsSync20(pyproject)) {
|
|
53519
53865
|
try {
|
|
53520
|
-
const txt =
|
|
53866
|
+
const txt = readFileSync19(pyproject, "utf8");
|
|
53521
53867
|
const py = /python\s*=\s*"([^"]+)"/.exec(txt)?.[1];
|
|
53522
53868
|
p.languages.push("python");
|
|
53523
53869
|
p.stack.push(`python@${py ?? "3"}`);
|
|
@@ -53528,16 +53874,16 @@ function autodetectProfile(root) {
|
|
|
53528
53874
|
} catch {
|
|
53529
53875
|
}
|
|
53530
53876
|
}
|
|
53531
|
-
const reqs =
|
|
53532
|
-
if (
|
|
53877
|
+
const reqs = join24(root, "requirements.txt");
|
|
53878
|
+
if (existsSync20(reqs)) {
|
|
53533
53879
|
if (!p.languages.includes("python")) p.languages.push("python");
|
|
53534
53880
|
if (!p.stack.includes("python@3")) p.stack.push("python@3");
|
|
53535
53881
|
}
|
|
53536
|
-
if (
|
|
53882
|
+
if (existsSync20(join24(root, "go.mod"))) {
|
|
53537
53883
|
p.languages.push("go");
|
|
53538
53884
|
p.stack.push("go");
|
|
53539
53885
|
}
|
|
53540
|
-
if (
|
|
53886
|
+
if (existsSync20(join24(root, "Cargo.toml"))) {
|
|
53541
53887
|
p.languages.push("rust");
|
|
53542
53888
|
p.stack.push("rust");
|
|
53543
53889
|
}
|
|
@@ -53547,17 +53893,17 @@ function autodetectProfile(root) {
|
|
|
53547
53893
|
}
|
|
53548
53894
|
|
|
53549
53895
|
// src/witness-queue.ts
|
|
53550
|
-
import { readFileSync as
|
|
53551
|
-
import { dirname as dirname9, join as
|
|
53896
|
+
import { readFileSync as readFileSync20, renameSync as renameSync2, writeFileSync as writeFileSync17 } from "node:fs";
|
|
53897
|
+
import { dirname as dirname9, join as join25 } from "node:path";
|
|
53552
53898
|
var WITNESS_QUEUE_CAP = 500;
|
|
53553
53899
|
var WITNESS_TTL_MS = 14 * 24 * 60 * 60 * 1e3;
|
|
53554
53900
|
var WITNESS_MAX_ATTEMPTS = 5;
|
|
53555
53901
|
function witnessQueuePath(workspaceConfigDir) {
|
|
53556
|
-
return
|
|
53902
|
+
return join25(workspaceConfigDir, "witness-queue.json");
|
|
53557
53903
|
}
|
|
53558
53904
|
function loadWitnessQueue(path2) {
|
|
53559
53905
|
try {
|
|
53560
|
-
const raw2 = JSON.parse(
|
|
53906
|
+
const raw2 = JSON.parse(readFileSync20(path2, "utf8"));
|
|
53561
53907
|
if (!Array.isArray(raw2)) return [];
|
|
53562
53908
|
return raw2.filter(
|
|
53563
53909
|
(w) => !!w && typeof w === "object" && typeof w.nodeId === "string" && typeof w.witnessKey === "string"
|
|
@@ -53568,8 +53914,8 @@ function loadWitnessQueue(path2) {
|
|
|
53568
53914
|
}
|
|
53569
53915
|
function saveWitnessQueue(path2, queue) {
|
|
53570
53916
|
try {
|
|
53571
|
-
const tmp =
|
|
53572
|
-
|
|
53917
|
+
const tmp = join25(dirname9(path2), `.${Date.now()}.witness-queue.tmp`);
|
|
53918
|
+
writeFileSync17(tmp, JSON.stringify(queue), "utf8");
|
|
53573
53919
|
renameSync2(tmp, path2);
|
|
53574
53920
|
} catch {
|
|
53575
53921
|
}
|
|
@@ -53860,7 +54206,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
|
|
|
53860
54206
|
}
|
|
53861
54207
|
|
|
53862
54208
|
// src/engine.ts
|
|
53863
|
-
var DAEMON_VERSION = true ? "2.0.2-dev.
|
|
54209
|
+
var DAEMON_VERSION = true ? "2.0.2-dev.530" : "2.0.0-alpha.0";
|
|
53864
54210
|
var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
|
|
53865
54211
|
var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
|
|
53866
54212
|
var GIT_OP_MUTE_MS = 4e3;
|
|
@@ -53870,17 +54216,17 @@ var TURN_REPLAY_LOOKBACK_MS = 7 * 24 * 60 * 6e4;
|
|
|
53870
54216
|
function appendIdentityAudit(path2, record2, line) {
|
|
53871
54217
|
if (!record2.accepted && record2.score <= 0) return;
|
|
53872
54218
|
try {
|
|
53873
|
-
if (
|
|
54219
|
+
if (existsSync22(path2) && statSync5(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
|
|
53874
54220
|
renameSync3(path2, `${path2}.1`);
|
|
53875
54221
|
}
|
|
53876
|
-
|
|
54222
|
+
appendFileSync4(path2, line);
|
|
53877
54223
|
} catch {
|
|
53878
54224
|
}
|
|
53879
54225
|
}
|
|
53880
54226
|
var yieldToLoop = () => new Promise((r) => setImmediate(r));
|
|
53881
54227
|
function loadTurnCursors(path2) {
|
|
53882
54228
|
try {
|
|
53883
|
-
const raw2 = JSON.parse(
|
|
54229
|
+
const raw2 = JSON.parse(readFileSync22(path2, "utf8"));
|
|
53884
54230
|
return new Map(
|
|
53885
54231
|
Object.entries(raw2).map(([k, v]) => [k, typeof v === "string" ? v : String(v?.uuid ?? "")])
|
|
53886
54232
|
);
|
|
@@ -53890,7 +54236,7 @@ function loadTurnCursors(path2) {
|
|
|
53890
54236
|
}
|
|
53891
54237
|
function loadTurnOffsets(path2) {
|
|
53892
54238
|
try {
|
|
53893
|
-
const raw2 = JSON.parse(
|
|
54239
|
+
const raw2 = JSON.parse(readFileSync22(path2, "utf8"));
|
|
53894
54240
|
const out2 = /* @__PURE__ */ new Map();
|
|
53895
54241
|
for (const [k, v] of Object.entries(raw2)) {
|
|
53896
54242
|
const off = typeof v === "object" && v !== null ? v.offset : void 0;
|
|
@@ -53906,7 +54252,7 @@ function saveTurnCursors(path2, cursors, offsets) {
|
|
|
53906
54252
|
const merged = {};
|
|
53907
54253
|
for (const [k, uuid3] of cursors) merged[k] = { uuid: uuid3, offset: offsets.get(k) ?? 0 };
|
|
53908
54254
|
for (const [k, offset] of offsets) if (!merged[k]) merged[k] = { uuid: "", offset };
|
|
53909
|
-
|
|
54255
|
+
writeFileSync19(path2, JSON.stringify(merged), "utf8");
|
|
53910
54256
|
} catch {
|
|
53911
54257
|
}
|
|
53912
54258
|
}
|
|
@@ -53928,7 +54274,7 @@ function gitSourceWatchTargets(root) {
|
|
|
53928
54274
|
["-C", root, "ls-files", "--others", "--ignored", "--exclude-standard", "--directory", "-z"],
|
|
53929
54275
|
{ encoding: "utf8", maxBuffer: 256 * 1024 * 1024, windowsHide: true, stdio: ["ignore", "pipe", "ignore"] }
|
|
53930
54276
|
);
|
|
53931
|
-
ignoredDirs = igOut.split("\0").filter(Boolean).map((d) => d.replace(/\/+$/, "")).filter((d) => !IGNORED_PATH.test(
|
|
54277
|
+
ignoredDirs = igOut.split("\0").filter(Boolean).map((d) => d.replace(/\/+$/, "")).filter((d) => !IGNORED_PATH.test(join27(root, d) + sep4));
|
|
53932
54278
|
} catch {
|
|
53933
54279
|
}
|
|
53934
54280
|
const hasIgnoredChild = (dir) => ignoredDirs.some((ig) => ig.startsWith(dir + "/"));
|
|
@@ -53940,19 +54286,19 @@ function gitSourceWatchTargets(root) {
|
|
|
53940
54286
|
if (!f.startsWith(prefix)) continue;
|
|
53941
54287
|
const rest2 = f.slice(prefix.length);
|
|
53942
54288
|
if (rest2.includes("/")) children.add(dir === "" ? rest2.slice(0, rest2.indexOf("/")) : dir + "/" + rest2.slice(0, rest2.indexOf("/")));
|
|
53943
|
-
else targets.add(
|
|
54289
|
+
else targets.add(join27(root, f));
|
|
53944
54290
|
}
|
|
53945
54291
|
for (const c of children) {
|
|
53946
|
-
if (IGNORED_PATH.test(
|
|
54292
|
+
if (IGNORED_PATH.test(join27(root, c) + sep4)) continue;
|
|
53947
54293
|
if (hasIgnoredChild(c)) addUnder(c);
|
|
53948
|
-
else targets.add(
|
|
54294
|
+
else targets.add(join27(root, c));
|
|
53949
54295
|
}
|
|
53950
54296
|
};
|
|
53951
54297
|
addUnder("");
|
|
53952
54298
|
if (targets.size > 0) return [...targets];
|
|
53953
54299
|
} catch {
|
|
53954
54300
|
}
|
|
53955
|
-
return readdirSync9(root, { withFileTypes: true }).filter((e) => e.isDirectory() && !IGNORED_PATH.test(
|
|
54301
|
+
return readdirSync9(root, { withFileTypes: true }).filter((e) => e.isDirectory() && !IGNORED_PATH.test(join27(root, String(e.name)) + sep4)).map((e) => join27(root, String(e.name)));
|
|
53956
54302
|
}
|
|
53957
54303
|
function createWorkspaceEngine(opts) {
|
|
53958
54304
|
const paths = workspacePaths(opts.workspaceRoot);
|
|
@@ -54110,7 +54456,7 @@ function createWorkspaceEngine(opts) {
|
|
|
54110
54456
|
const srcPaths = diff.changedPaths.filter((p) => /\.(ts|tsx|js|jsx|mjs|cjs|py)$/i.test(p));
|
|
54111
54457
|
let episodeId2;
|
|
54112
54458
|
if (srcPaths.length > 0) {
|
|
54113
|
-
const abs = srcPaths.map((p) =>
|
|
54459
|
+
const abs = srcPaths.map((p) => join27(opts.workspaceRoot, p));
|
|
54114
54460
|
try {
|
|
54115
54461
|
const r = await runReindexPass(
|
|
54116
54462
|
`git-reindex:${profile.name} (${abs.length} files)`,
|
|
@@ -54146,8 +54492,8 @@ function createWorkspaceEngine(opts) {
|
|
|
54146
54492
|
`[errata] git: ${ev.kind} ${ev.newSha.slice(0, 7)} by ${meta3.authorName} \u2014 ${diff.changedPaths.length} file(s), ${diff.renames.length} rename(s)`
|
|
54147
54493
|
);
|
|
54148
54494
|
};
|
|
54149
|
-
const gitDir =
|
|
54150
|
-
if (
|
|
54495
|
+
const gitDir = join27(opts.workspaceRoot, ".git");
|
|
54496
|
+
if (existsSync22(gitDir)) {
|
|
54151
54497
|
stopGit = startGitSensor(gitDir, (ev) => {
|
|
54152
54498
|
void handleGitEvent(ev).catch((err2) => {
|
|
54153
54499
|
console.warn("[errata] git event handler failed:", err2);
|
|
@@ -54160,7 +54506,26 @@ function createWorkspaceEngine(opts) {
|
|
|
54160
54506
|
if (n > 0) {
|
|
54161
54507
|
console.log(`[errata] reconcile: re-indexed ${n} stale file(s) on startup`);
|
|
54162
54508
|
}
|
|
54163
|
-
}).catch((err2) => console.warn("[errata] startup reconcile failed:", err2))
|
|
54509
|
+
}).catch((err2) => console.warn("[errata] startup reconcile failed:", err2)).finally(() => {
|
|
54510
|
+
try {
|
|
54511
|
+
const reap = reapOrphanedFiles(store, opts.workspaceRoot, profile.id);
|
|
54512
|
+
appendPassLedger(paths.configDir, "orphan-reap", 0, {
|
|
54513
|
+
reaped: reap.reaped,
|
|
54514
|
+
symbolsClosed: reap.symbolsClosed
|
|
54515
|
+
});
|
|
54516
|
+
if (reap.skipped) {
|
|
54517
|
+
console.warn(
|
|
54518
|
+
`[errata] orphan reap skipped (${reap.skipped}${reap.candidates !== void 0 ? `, ${reap.candidates} candidates` : ""}) \u2014 no File nodes closed`
|
|
54519
|
+
);
|
|
54520
|
+
} else if (reap.reaped > 0) {
|
|
54521
|
+
console.log(
|
|
54522
|
+
`[errata] orphan reap: closed ${reap.reaped} File node(s) no longer indexed (${reap.symbolsClosed} symbol(s) with them)`
|
|
54523
|
+
);
|
|
54524
|
+
}
|
|
54525
|
+
} catch (err2) {
|
|
54526
|
+
console.warn("[errata] orphan reap failed:", err2 instanceof Error ? err2.message : err2);
|
|
54527
|
+
}
|
|
54528
|
+
});
|
|
54164
54529
|
});
|
|
54165
54530
|
}
|
|
54166
54531
|
const workingFiles = createWorkingFileState();
|
|
@@ -54252,15 +54617,19 @@ function createWorkspaceEngine(opts) {
|
|
|
54252
54617
|
doneRender?.();
|
|
54253
54618
|
try {
|
|
54254
54619
|
const seq = store.currentIngestSeq();
|
|
54255
|
-
recordRenderLedger(store, ledger, seq, Date.now());
|
|
54620
|
+
const stamped = recordRenderLedger(store, ledger, seq, Date.now());
|
|
54621
|
+
appendPassLedger(paths.configDir, "render", 0, {
|
|
54622
|
+
shown: stamped.shown,
|
|
54623
|
+
evicted: stamped.evicted
|
|
54624
|
+
});
|
|
54256
54625
|
} catch (err2) {
|
|
54257
54626
|
console.warn("[errata] render ledger failed:", err2.message?.slice(0, 120));
|
|
54258
54627
|
}
|
|
54259
54628
|
writeContextFile(opts.workspaceRoot, body2);
|
|
54260
|
-
const target =
|
|
54629
|
+
const target = join27(opts.workspaceRoot, "AGENTS.md");
|
|
54261
54630
|
writeManagedBlock(target, { body: AGENTS_POINTER_BODY, stable: true, force: true });
|
|
54262
54631
|
if (elicit) {
|
|
54263
|
-
writePrimingHandles(
|
|
54632
|
+
writePrimingHandles(join27(paths.configDir, "priming-handles.json"), [
|
|
54264
54633
|
...snapshot.recentProblems.map((r) => r.node),
|
|
54265
54634
|
// Resolved-band handles: the ✓ problem AND its Solution are citable
|
|
54266
54635
|
// (a fix tag on an already-resolved problem no-ops idempotently; the
|
|
@@ -54482,7 +54851,7 @@ function createWorkspaceEngine(opts) {
|
|
|
54482
54851
|
resultSummary: { exitCode: e.exitCode ?? 1, errorTokens: e.errorTokens }
|
|
54483
54852
|
});
|
|
54484
54853
|
};
|
|
54485
|
-
const turnCursorPath =
|
|
54854
|
+
const turnCursorPath = join27(paths.configDir, "turn-cursors.json");
|
|
54486
54855
|
const lastTurnUuid = loadTurnCursors(turnCursorPath);
|
|
54487
54856
|
const turnOffset = loadTurnOffsets(turnCursorPath);
|
|
54488
54857
|
const sessionLastProblem = /* @__PURE__ */ new Map();
|
|
@@ -54505,8 +54874,9 @@ function createWorkspaceEngine(opts) {
|
|
|
54505
54874
|
let linked = 0;
|
|
54506
54875
|
const t = Date.now();
|
|
54507
54876
|
let processedTurns = 0;
|
|
54877
|
+
const seqAtStart = store.currentIngestSeq();
|
|
54508
54878
|
const elicit = isEdgeElicitationEnabled();
|
|
54509
|
-
const handleMap = elicit ? readPrimingHandles(
|
|
54879
|
+
const handleMap = elicit ? readPrimingHandles(join27(paths.configDir, "priming-handles.json")) : {};
|
|
54510
54880
|
const wsRoot = (opts.workspaceRoot ?? "").replace(/\\/g, "/");
|
|
54511
54881
|
const toRel = (abs) => {
|
|
54512
54882
|
const p = abs.replace(/\\/g, "/");
|
|
@@ -55013,6 +55383,16 @@ function createWorkspaceEngine(opts) {
|
|
|
55013
55383
|
if (triaged > 0) {
|
|
55014
55384
|
console.log(`[errata] triage: ${triaged} wrong-door(s) captured from the conversation`);
|
|
55015
55385
|
}
|
|
55386
|
+
if (processedTurns > 0) {
|
|
55387
|
+
appendPassLedger(paths.configDir, "capture", Date.now() - t, {
|
|
55388
|
+
turns: processedTurns,
|
|
55389
|
+
minted,
|
|
55390
|
+
resolved,
|
|
55391
|
+
triaged,
|
|
55392
|
+
priorEdges,
|
|
55393
|
+
seqAdvanced: store.currentIngestSeq() - seqAtStart
|
|
55394
|
+
});
|
|
55395
|
+
}
|
|
55016
55396
|
};
|
|
55017
55397
|
const harvestTurns = async (sessionId, transcriptPath) => {
|
|
55018
55398
|
const known = turnOffset.get(sessionId);
|
|
@@ -55179,7 +55559,7 @@ function createWorkspaceEngine(opts) {
|
|
|
55179
55559
|
try {
|
|
55180
55560
|
const inputs = emitInputsFromManifest(paths.configDir, paths.skillsManifest);
|
|
55181
55561
|
emitAndProjectSkills(opts.workspaceRoot, inputs);
|
|
55182
|
-
writePrimingHandles(
|
|
55562
|
+
writePrimingHandles(join27(paths.configDir, "priming-handles.json"), skillHandleNodes(inputs));
|
|
55183
55563
|
} catch (err2) {
|
|
55184
55564
|
console.warn("[skills] agent-skills projection failed (non-fatal):", err2 instanceof Error ? err2.message : err2);
|
|
55185
55565
|
}
|
|
@@ -55263,6 +55643,26 @@ function createWorkspaceEngine(opts) {
|
|
|
55263
55643
|
}
|
|
55264
55644
|
return report;
|
|
55265
55645
|
},
|
|
55646
|
+
semanticMaintenance() {
|
|
55647
|
+
const seqBefore = store.currentIngestSeq();
|
|
55648
|
+
const report = runSemanticMaintenance(store);
|
|
55649
|
+
appendPassLedger(paths.configDir, "semantic-maintenance", report.durationMs, {
|
|
55650
|
+
revisitsCleared: report.revisitsCleared,
|
|
55651
|
+
revisitsStanding: report.revisitsStanding,
|
|
55652
|
+
fixCandidatesSettled: report.fixCandidatesSettled,
|
|
55653
|
+
fixCandidatesAnswered: report.fixCandidates.answered,
|
|
55654
|
+
fixCandidatesIgnored: report.fixCandidates.ignored,
|
|
55655
|
+
fixCandidatesUnsubstantiated: report.fixCandidates.unsubstantiated,
|
|
55656
|
+
fixCandidatesStanding: report.fixCandidates.standing,
|
|
55657
|
+
designResolved: report.designResolved,
|
|
55658
|
+
claimsEvaluated: report.claimsEvaluated,
|
|
55659
|
+
seqAdvanced: store.currentIngestSeq() - seqBefore
|
|
55660
|
+
});
|
|
55661
|
+
if (report.revisitsCleared > 0 || report.fixCandidatesSettled > 0 || report.designResolved > 0) {
|
|
55662
|
+
refreshContextNow();
|
|
55663
|
+
}
|
|
55664
|
+
return report;
|
|
55665
|
+
},
|
|
55266
55666
|
async nightly() {
|
|
55267
55667
|
const report = (await runNightly()).report;
|
|
55268
55668
|
const summarizer = opts.intentSummarizer ?? envIntentSummarizer();
|
|
@@ -55278,6 +55678,18 @@ function createWorkspaceEngine(opts) {
|
|
|
55278
55678
|
console.warn("[errata] symbol summary sweep failed:", err2 instanceof Error ? err2.message : err2);
|
|
55279
55679
|
}
|
|
55280
55680
|
}
|
|
55681
|
+
appendPassLedger(paths.configDir, "graph-rescore", report.durationMs, {
|
|
55682
|
+
scoredNodes: report.scoredNodes,
|
|
55683
|
+
landmarks: report.landmarks,
|
|
55684
|
+
communities: report.communities,
|
|
55685
|
+
motifsPromoted: report.motifsPromoted
|
|
55686
|
+
});
|
|
55687
|
+
appendPassLedger(paths.configDir, "semantic-maintenance", report.durationMs, {
|
|
55688
|
+
revisitsCleared: report.revisitsCleared,
|
|
55689
|
+
fixCandidatesSettled: report.fixCandidatesSettled,
|
|
55690
|
+
designResolved: report.designResolved,
|
|
55691
|
+
claimsEvaluated: report.claimsEvaluated
|
|
55692
|
+
});
|
|
55281
55693
|
return report;
|
|
55282
55694
|
},
|
|
55283
55695
|
async embedSettled() {
|
|
@@ -55366,7 +55778,7 @@ function createWorkspaceEngine(opts) {
|
|
|
55366
55778
|
console.log(
|
|
55367
55779
|
"[errata] sync skipped \u2014 cloud sync consent is off (enable with `errata consent sync on`)"
|
|
55368
55780
|
);
|
|
55369
|
-
const pending =
|
|
55781
|
+
const pending = existsSync22(paths.outbox) ? readdirSync9(paths.outbox).filter((f) => f.endsWith(".json")).length : 0;
|
|
55370
55782
|
return { uploaded: 0, failed: 0, remaining: pending };
|
|
55371
55783
|
}
|
|
55372
55784
|
try {
|
|
@@ -55453,7 +55865,7 @@ async function startDaemon(opts) {
|
|
|
55453
55865
|
reviewUrl: () => webUiUrl + "/review"
|
|
55454
55866
|
});
|
|
55455
55867
|
const writeLockFile = (url2) => {
|
|
55456
|
-
|
|
55868
|
+
writeFileSync20(
|
|
55457
55869
|
engine.paths.daemonLock,
|
|
55458
55870
|
JSON.stringify({ pid: process.pid, webUiUrl: url2, startedAt: Date.now() }),
|
|
55459
55871
|
"utf8"
|
|
@@ -55496,7 +55908,7 @@ async function startDaemon(opts) {
|
|
|
55496
55908
|
);
|
|
55497
55909
|
await engine.stop();
|
|
55498
55910
|
try {
|
|
55499
|
-
if (
|
|
55911
|
+
if (existsSync23(engine.paths.daemonLock)) {
|
|
55500
55912
|
}
|
|
55501
55913
|
} catch {
|
|
55502
55914
|
}
|
|
@@ -55513,16 +55925,16 @@ async function listenServer(fetchFn, port) {
|
|
|
55513
55925
|
|
|
55514
55926
|
// src/registry.ts
|
|
55515
55927
|
init_paths();
|
|
55516
|
-
import { existsSync as
|
|
55517
|
-
import { join as
|
|
55928
|
+
import { existsSync as existsSync24, readFileSync as readFileSync23, writeFileSync as writeFileSync21 } from "node:fs";
|
|
55929
|
+
import { join as join28 } from "node:path";
|
|
55518
55930
|
function registryPath() {
|
|
55519
|
-
return process.env["ERRATA_REGISTRY_PATH"] ??
|
|
55931
|
+
return process.env["ERRATA_REGISTRY_PATH"] ?? join28(globalDir(), "workspaces.json");
|
|
55520
55932
|
}
|
|
55521
55933
|
function read() {
|
|
55522
55934
|
const p = registryPath();
|
|
55523
|
-
if (!
|
|
55935
|
+
if (!existsSync24(p)) return { version: 1, workspaces: {} };
|
|
55524
55936
|
try {
|
|
55525
|
-
const parsed = JSON.parse(
|
|
55937
|
+
const parsed = JSON.parse(readFileSync23(p, "utf8"));
|
|
55526
55938
|
return { version: 1, workspaces: parsed.workspaces ?? {} };
|
|
55527
55939
|
} catch {
|
|
55528
55940
|
return { version: 1, workspaces: {} };
|
|
@@ -55530,7 +55942,7 @@ function read() {
|
|
|
55530
55942
|
}
|
|
55531
55943
|
function write(reg) {
|
|
55532
55944
|
ensureDir(globalDir());
|
|
55533
|
-
|
|
55945
|
+
writeFileSync21(registryPath(), JSON.stringify(reg, null, 2), "utf8");
|
|
55534
55946
|
}
|
|
55535
55947
|
function registerWorkspace(profile, root, now = Date.now()) {
|
|
55536
55948
|
const reg = read();
|
|
@@ -55547,7 +55959,7 @@ function pruneMissingWorkspaces() {
|
|
|
55547
55959
|
const reg = read();
|
|
55548
55960
|
const removed = [];
|
|
55549
55961
|
for (const [id, entry] of Object.entries(reg.workspaces)) {
|
|
55550
|
-
if (!
|
|
55962
|
+
if (!existsSync24(entry.path)) {
|
|
55551
55963
|
removed.push(entry);
|
|
55552
55964
|
delete reg.workspaces[id];
|
|
55553
55965
|
}
|
|
@@ -55556,13 +55968,13 @@ function pruneMissingWorkspaces() {
|
|
|
55556
55968
|
return removed;
|
|
55557
55969
|
}
|
|
55558
55970
|
function workspaceStatus(entry) {
|
|
55559
|
-
const missing = !
|
|
55971
|
+
const missing = !existsSync24(entry.path);
|
|
55560
55972
|
const lockPath = workspacePaths(entry.path).daemonLock;
|
|
55561
55973
|
let running = false;
|
|
55562
55974
|
let webUiUrl = null;
|
|
55563
|
-
if (
|
|
55975
|
+
if (existsSync24(lockPath)) {
|
|
55564
55976
|
try {
|
|
55565
|
-
const lock = JSON.parse(
|
|
55977
|
+
const lock = JSON.parse(readFileSync23(lockPath, "utf8"));
|
|
55566
55978
|
if (lock.pid && lock.webUiUrl && pidAlive(lock.pid)) {
|
|
55567
55979
|
running = true;
|
|
55568
55980
|
webUiUrl = lock.webUiUrl;
|
|
@@ -55590,7 +56002,7 @@ function pidAlive(pid) {
|
|
|
55590
56002
|
// src/multi.ts
|
|
55591
56003
|
init_dist();
|
|
55592
56004
|
init_src5();
|
|
55593
|
-
import { readFileSync as
|
|
56005
|
+
import { readFileSync as readFileSync26, unlinkSync as unlinkSync3, writeFileSync as writeFileSync22 } from "node:fs";
|
|
55594
56006
|
|
|
55595
56007
|
// src/principle-sync.ts
|
|
55596
56008
|
init_src5();
|
|
@@ -55618,8 +56030,8 @@ init_reconcile();
|
|
|
55618
56030
|
|
|
55619
56031
|
// src/lockfile-auto.ts
|
|
55620
56032
|
init_src();
|
|
55621
|
-
import { existsSync as
|
|
55622
|
-
import { join as
|
|
56033
|
+
import { existsSync as existsSync25, readFileSync as readFileSync24 } from "node:fs";
|
|
56034
|
+
import { join as join29 } from "node:path";
|
|
55623
56035
|
|
|
55624
56036
|
// src/package-index.ts
|
|
55625
56037
|
init_src();
|
|
@@ -55768,11 +56180,11 @@ function runLockfilePass(opts) {
|
|
|
55768
56180
|
{ file: "package-lock.json", parse: parsePackageLockJson }
|
|
55769
56181
|
];
|
|
55770
56182
|
for (const c of candidates) {
|
|
55771
|
-
const p =
|
|
55772
|
-
if (!
|
|
56183
|
+
const p = join29(opts.root, c.file);
|
|
56184
|
+
if (!existsSync25(p)) continue;
|
|
55773
56185
|
let sbom;
|
|
55774
56186
|
try {
|
|
55775
|
-
sbom = c.parse(
|
|
56187
|
+
sbom = c.parse(readFileSync24(p, "utf8"));
|
|
55776
56188
|
} catch {
|
|
55777
56189
|
continue;
|
|
55778
56190
|
}
|
|
@@ -56220,7 +56632,7 @@ var ConsolidateWorker = class {
|
|
|
56220
56632
|
init_paths();
|
|
56221
56633
|
|
|
56222
56634
|
// src/lock.ts
|
|
56223
|
-
import { existsSync as
|
|
56635
|
+
import { existsSync as existsSync26, readFileSync as readFileSync25 } from "node:fs";
|
|
56224
56636
|
function isProcessAlive(pid) {
|
|
56225
56637
|
if (!pid || pid <= 0) return false;
|
|
56226
56638
|
try {
|
|
@@ -56231,9 +56643,9 @@ function isProcessAlive(pid) {
|
|
|
56231
56643
|
}
|
|
56232
56644
|
}
|
|
56233
56645
|
function readDaemonLock(lockPath) {
|
|
56234
|
-
if (!
|
|
56646
|
+
if (!existsSync26(lockPath)) return null;
|
|
56235
56647
|
try {
|
|
56236
|
-
const lock = JSON.parse(
|
|
56648
|
+
const lock = JSON.parse(readFileSync25(lockPath, "utf8"));
|
|
56237
56649
|
return typeof lock.pid === "number" ? lock : null;
|
|
56238
56650
|
} catch {
|
|
56239
56651
|
return null;
|
|
@@ -56517,12 +56929,12 @@ async function reanchorProject(opts) {
|
|
|
56517
56929
|
}
|
|
56518
56930
|
|
|
56519
56931
|
// src/adopt.ts
|
|
56520
|
-
import { existsSync as
|
|
56521
|
-
import { dirname as dirname10, join as
|
|
56932
|
+
import { existsSync as existsSync27 } from "node:fs";
|
|
56933
|
+
import { dirname as dirname10, join as join30 } from "node:path";
|
|
56522
56934
|
function findGitRoot(absPath) {
|
|
56523
56935
|
let dir = absPath;
|
|
56524
56936
|
for (let depth = 0; depth < 64; depth++) {
|
|
56525
|
-
if (
|
|
56937
|
+
if (existsSync27(join30(dir, ".git"))) return dir;
|
|
56526
56938
|
const parent = dirname10(dir);
|
|
56527
56939
|
if (parent === dir) return null;
|
|
56528
56940
|
dir = parent;
|
|
@@ -56771,7 +57183,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
56771
57183
|
void ambientLinkAll();
|
|
56772
57184
|
app.route(`/ws/${rec.id}`, rec.webApp);
|
|
56773
57185
|
try {
|
|
56774
|
-
|
|
57186
|
+
writeFileSync22(
|
|
56775
57187
|
rec.engine.paths.daemonLock,
|
|
56776
57188
|
JSON.stringify({ pid: process.pid, webUiUrl: `${baseUrl}/ws/${rec.id}`, startedAt: Date.now() }),
|
|
56777
57189
|
"utf8"
|
|
@@ -56960,7 +57372,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
56960
57372
|
baseUrl = `http://127.0.0.1:${port}`;
|
|
56961
57373
|
try {
|
|
56962
57374
|
ensureDir(globalDir());
|
|
56963
|
-
|
|
57375
|
+
writeFileSync22(
|
|
56964
57376
|
lockPath,
|
|
56965
57377
|
JSON.stringify({ pid: process.pid, webUiUrl: baseUrl, startedAt: Date.now() }),
|
|
56966
57378
|
"utf8"
|
|
@@ -56969,7 +57381,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
56969
57381
|
}
|
|
56970
57382
|
for (const r of records) {
|
|
56971
57383
|
try {
|
|
56972
|
-
|
|
57384
|
+
writeFileSync22(
|
|
56973
57385
|
r.engine.paths.daemonLock,
|
|
56974
57386
|
JSON.stringify({ pid: process.pid, webUiUrl: `${baseUrl}/ws/${r.id}`, startedAt: Date.now() }),
|
|
56975
57387
|
"utf8"
|
|
@@ -57096,6 +57508,22 @@ async function startMultiDaemon(opts = {}) {
|
|
|
57096
57508
|
}
|
|
57097
57509
|
return out2;
|
|
57098
57510
|
},
|
|
57511
|
+
semanticMaintenanceAll() {
|
|
57512
|
+
const out2 = /* @__PURE__ */ new Map();
|
|
57513
|
+
for (const r of records) {
|
|
57514
|
+
const done = markPass(`semantic:${r.entry.name}`);
|
|
57515
|
+
try {
|
|
57516
|
+
out2.set(r.id, r.engine.semanticMaintenance());
|
|
57517
|
+
} catch (err2) {
|
|
57518
|
+
console.warn(
|
|
57519
|
+
`[errata] semantic maintenance failed for ${r.entry.name}: ${err2 instanceof Error ? err2.message : err2}`
|
|
57520
|
+
);
|
|
57521
|
+
} finally {
|
|
57522
|
+
done();
|
|
57523
|
+
}
|
|
57524
|
+
}
|
|
57525
|
+
return out2;
|
|
57526
|
+
},
|
|
57099
57527
|
async nightlyAll() {
|
|
57100
57528
|
const out2 = /* @__PURE__ */ new Map();
|
|
57101
57529
|
for (const r of records) {
|
|
@@ -57501,7 +57929,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
57501
57929
|
},
|
|
57502
57930
|
async stop() {
|
|
57503
57931
|
try {
|
|
57504
|
-
const cur =
|
|
57932
|
+
const cur = readFileSync26(lockPath, "utf8");
|
|
57505
57933
|
if (JSON.parse(cur).pid === process.pid) unlinkSync3(lockPath);
|
|
57506
57934
|
} catch {
|
|
57507
57935
|
}
|
|
@@ -58518,21 +58946,21 @@ async function cmdInit() {
|
|
|
58518
58946
|
if (!skipHooks) {
|
|
58519
58947
|
console.log("");
|
|
58520
58948
|
console.log("installing harness hooks...");
|
|
58521
|
-
const { existsSync:
|
|
58522
|
-
const { join:
|
|
58949
|
+
const { existsSync: existsSync29 } = await import("node:fs");
|
|
58950
|
+
const { join: join32 } = await import("node:path");
|
|
58523
58951
|
try {
|
|
58524
58952
|
await installClaudeHooks(port);
|
|
58525
58953
|
} catch (err2) {
|
|
58526
58954
|
console.warn(` \u26A0\uFE0F Claude hook install failed: ${err2 instanceof Error ? err2.message : err2}`);
|
|
58527
58955
|
}
|
|
58528
|
-
if (
|
|
58956
|
+
if (existsSync29(join32(ROOT, ".cursor"))) {
|
|
58529
58957
|
try {
|
|
58530
58958
|
await installCursorMcpConfig();
|
|
58531
58959
|
} catch (err2) {
|
|
58532
58960
|
console.warn(` \u26A0\uFE0F Cursor MCP config failed: ${err2 instanceof Error ? err2.message : err2}`);
|
|
58533
58961
|
}
|
|
58534
58962
|
}
|
|
58535
|
-
if (
|
|
58963
|
+
if (existsSync29(join32(ROOT, ".codex"))) {
|
|
58536
58964
|
try {
|
|
58537
58965
|
await installCodexHooks(port);
|
|
58538
58966
|
} catch (err2) {
|
|
@@ -58689,9 +59117,9 @@ async function cmdStatus() {
|
|
|
58689
59117
|
console.log(` stack: ${profile.stack.join(", ") || "(none)"}`);
|
|
58690
59118
|
console.log(` languages: ${profile.languages.join(", ") || "(none)"}`);
|
|
58691
59119
|
}
|
|
58692
|
-
console.log(` graph db: ${
|
|
58693
|
-
console.log(` event log: ${
|
|
58694
|
-
if (
|
|
59120
|
+
console.log(` graph db: ${existsSync28(paths.castalia) ? "yes" : "no"} (${paths.castalia})`);
|
|
59121
|
+
console.log(` event log: ${existsSync28(paths.eventLog) ? "yes" : "no"} (${paths.eventLog})`);
|
|
59122
|
+
if (existsSync28(paths.castalia)) {
|
|
58695
59123
|
try {
|
|
58696
59124
|
const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src5(), src_exports2));
|
|
58697
59125
|
const store = openGraphStore2({ path: paths.castalia });
|
|
@@ -59372,11 +59800,11 @@ function cmdInstallationProfile(args2) {
|
|
|
59372
59800
|
}
|
|
59373
59801
|
async function cmdReview() {
|
|
59374
59802
|
const paths = workspacePaths(ROOT);
|
|
59375
|
-
if (!
|
|
59803
|
+
if (!existsSync28(paths.reviewQueue)) {
|
|
59376
59804
|
console.log("(review queue empty)");
|
|
59377
59805
|
return;
|
|
59378
59806
|
}
|
|
59379
|
-
const queue = JSON.parse(
|
|
59807
|
+
const queue = JSON.parse(readFileSync27(paths.reviewQueue, "utf8"));
|
|
59380
59808
|
if (queue.length === 0) {
|
|
59381
59809
|
console.log("(review queue empty)");
|
|
59382
59810
|
return;
|
|
@@ -60047,7 +60475,7 @@ async function gatherRepo(store, ws) {
|
|
|
60047
60475
|
};
|
|
60048
60476
|
}
|
|
60049
60477
|
async function gatherReportData(generatedAt) {
|
|
60050
|
-
const { existsSync:
|
|
60478
|
+
const { existsSync: existsSync29 } = await import("node:fs");
|
|
60051
60479
|
const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src5(), src_exports2));
|
|
60052
60480
|
const cfg = loadConfig();
|
|
60053
60481
|
const outbound = cfg.consent.sync ? "auto" : "off";
|
|
@@ -60055,7 +60483,7 @@ async function gatherReportData(generatedAt) {
|
|
|
60055
60483
|
for (const ws of listWorkspaces()) {
|
|
60056
60484
|
if (ws.missing) continue;
|
|
60057
60485
|
const dbPath = workspacePaths(ws.path).castalia;
|
|
60058
|
-
if (!
|
|
60486
|
+
if (!existsSync29(dbPath)) continue;
|
|
60059
60487
|
let store = null;
|
|
60060
60488
|
try {
|
|
60061
60489
|
store = openGraphStore2({ path: dbPath });
|
|
@@ -60086,7 +60514,7 @@ async function gatherReportData(generatedAt) {
|
|
|
60086
60514
|
};
|
|
60087
60515
|
}
|
|
60088
60516
|
async function cmdReport(args2) {
|
|
60089
|
-
const { mkdirSync: mkdirSync8, writeFileSync:
|
|
60517
|
+
const { mkdirSync: mkdirSync8, writeFileSync: writeFileSync23 } = await import("node:fs");
|
|
60090
60518
|
const { renderReport: renderReport2 } = await Promise.resolve().then(() => (init_report_render(), report_render_exports));
|
|
60091
60519
|
const includeFutureVerbs = args2.includes("--future-verbs");
|
|
60092
60520
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -60099,8 +60527,8 @@ async function cmdReport(args2) {
|
|
|
60099
60527
|
const outDir = workspacePaths(ROOT).configDir;
|
|
60100
60528
|
mkdirSync8(outDir, { recursive: true });
|
|
60101
60529
|
const files = renderReport2(data, { includeFutureVerbs });
|
|
60102
|
-
for (const f of files)
|
|
60103
|
-
const indexPath =
|
|
60530
|
+
for (const f of files) writeFileSync23(join31(outDir, f.name), f.html, "utf8");
|
|
60531
|
+
const indexPath = join31(outDir, "report.html");
|
|
60104
60532
|
console.log(`report \u2192 ${indexPath}`);
|
|
60105
60533
|
console.log(
|
|
60106
60534
|
` ${data.repos.length} repo(s) \xB7 ${files.length} file(s) \xB7 ${data.rollup.nodes.toLocaleString("en-US")} nodes`
|
|
@@ -60218,15 +60646,15 @@ function hookRelayCommand(port, path2) {
|
|
|
60218
60646
|
return process.platform === "win32" ? `cmd //c "curl -s --connect-timeout 1 --max-time 2 -X POST -H \\"Content-Type: application/json\\" --data-binary @- ${url2} 2>NUL || echo {}"` : `curl -s --connect-timeout 1 --max-time 2 -X POST -H 'Content-Type: application/json' --data-binary @- ${url2} 2>/dev/null || echo '{}'`;
|
|
60219
60647
|
}
|
|
60220
60648
|
async function installClaudeHooks(port) {
|
|
60221
|
-
const { mkdirSync: mkdirSync8, existsSync:
|
|
60222
|
-
const { join:
|
|
60223
|
-
const dir =
|
|
60224
|
-
if (!
|
|
60225
|
-
const file2 =
|
|
60649
|
+
const { mkdirSync: mkdirSync8, existsSync: existsSync29, readFileSync: readFileSync28, writeFileSync: writeFileSync23 } = await import("node:fs");
|
|
60650
|
+
const { join: join32 } = await import("node:path");
|
|
60651
|
+
const dir = join32(ROOT, ".claude");
|
|
60652
|
+
if (!existsSync29(dir)) mkdirSync8(dir, { recursive: true });
|
|
60653
|
+
const file2 = join32(dir, "settings.json");
|
|
60226
60654
|
let settings = {};
|
|
60227
|
-
if (
|
|
60655
|
+
if (existsSync29(file2)) {
|
|
60228
60656
|
try {
|
|
60229
|
-
settings = JSON.parse(
|
|
60657
|
+
settings = JSON.parse(readFileSync28(file2, "utf8"));
|
|
60230
60658
|
} catch {
|
|
60231
60659
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
60232
60660
|
process.exit(2);
|
|
@@ -60272,10 +60700,10 @@ async function installClaudeHooks(port) {
|
|
|
60272
60700
|
dropErrata(list);
|
|
60273
60701
|
list.push({ hooks: [{ type: "command", command: injectCmd }] });
|
|
60274
60702
|
}
|
|
60275
|
-
|
|
60703
|
+
writeFileSync23(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
|
|
60276
60704
|
console.log(`installed Claude Code hooks \u2192 ${file2}`);
|
|
60277
60705
|
await installClaudeMcpConfig();
|
|
60278
|
-
const claudeMd =
|
|
60706
|
+
const claudeMd = join32(ROOT, "CLAUDE.md");
|
|
60279
60707
|
const recall = writeManagedBlock(claudeMd, { body: RECALL_FIRST_BLOCK });
|
|
60280
60708
|
if (recall.kind === "collision") {
|
|
60281
60709
|
console.warn(
|
|
@@ -60287,15 +60715,15 @@ async function installClaudeHooks(port) {
|
|
|
60287
60715
|
console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
|
|
60288
60716
|
}
|
|
60289
60717
|
async function installClaudeMcpConfig() {
|
|
60290
|
-
const { mkdirSync: mkdirSync8, existsSync:
|
|
60291
|
-
const { join:
|
|
60292
|
-
const file2 =
|
|
60718
|
+
const { mkdirSync: mkdirSync8, existsSync: existsSync29, readFileSync: readFileSync28, writeFileSync: writeFileSync23 } = await import("node:fs");
|
|
60719
|
+
const { join: join32, dirname: dirname11 } = await import("node:path");
|
|
60720
|
+
const file2 = join32(ROOT, ".mcp.json");
|
|
60293
60721
|
const dir = dirname11(file2);
|
|
60294
|
-
if (!
|
|
60722
|
+
if (!existsSync29(dir)) mkdirSync8(dir, { recursive: true });
|
|
60295
60723
|
let cfg = {};
|
|
60296
|
-
if (
|
|
60724
|
+
if (existsSync29(file2)) {
|
|
60297
60725
|
try {
|
|
60298
|
-
cfg = JSON.parse(
|
|
60726
|
+
cfg = JSON.parse(readFileSync28(file2, "utf8"));
|
|
60299
60727
|
} catch {
|
|
60300
60728
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
60301
60729
|
process.exit(2);
|
|
@@ -60303,21 +60731,21 @@ async function installClaudeMcpConfig() {
|
|
|
60303
60731
|
}
|
|
60304
60732
|
cfg.mcpServers ??= {};
|
|
60305
60733
|
cfg.mcpServers["errata"] = errataMcpInvocation();
|
|
60306
|
-
|
|
60734
|
+
writeFileSync23(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
|
|
60307
60735
|
console.log(`installed Claude Code MCP server config \u2192 ${file2}`);
|
|
60308
60736
|
console.log(` Claude Code will spawn \`errata mcp\` on workspace open.`);
|
|
60309
60737
|
console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses / show / similar`);
|
|
60310
60738
|
}
|
|
60311
60739
|
async function installCursorMcpConfig() {
|
|
60312
|
-
const { mkdirSync: mkdirSync8, existsSync:
|
|
60313
|
-
const { join:
|
|
60314
|
-
const dir =
|
|
60315
|
-
if (!
|
|
60316
|
-
const file2 =
|
|
60740
|
+
const { mkdirSync: mkdirSync8, existsSync: existsSync29, readFileSync: readFileSync28, writeFileSync: writeFileSync23 } = await import("node:fs");
|
|
60741
|
+
const { join: join32 } = await import("node:path");
|
|
60742
|
+
const dir = join32(ROOT, ".cursor");
|
|
60743
|
+
if (!existsSync29(dir)) mkdirSync8(dir, { recursive: true });
|
|
60744
|
+
const file2 = join32(dir, "mcp.json");
|
|
60317
60745
|
let cfg = {};
|
|
60318
|
-
if (
|
|
60746
|
+
if (existsSync29(file2)) {
|
|
60319
60747
|
try {
|
|
60320
|
-
cfg = JSON.parse(
|
|
60748
|
+
cfg = JSON.parse(readFileSync28(file2, "utf8"));
|
|
60321
60749
|
} catch {
|
|
60322
60750
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
60323
60751
|
process.exit(2);
|
|
@@ -60325,7 +60753,7 @@ async function installCursorMcpConfig() {
|
|
|
60325
60753
|
}
|
|
60326
60754
|
cfg.mcpServers ??= {};
|
|
60327
60755
|
cfg.mcpServers["errata"] = errataMcpInvocation();
|
|
60328
|
-
|
|
60756
|
+
writeFileSync23(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
|
|
60329
60757
|
console.log(`installed Cursor MCP server config \u2192 ${file2}`);
|
|
60330
60758
|
console.log(` Cursor will spawn \`errata mcp\` on workspace open.`);
|
|
60331
60759
|
console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses`);
|
|
@@ -60333,16 +60761,16 @@ async function installCursorMcpConfig() {
|
|
|
60333
60761
|
console.log(` \u26A0\uFE0F reload Cursor (Cmd/Ctrl-Shift-P \u2192 "Reload Window") to pick it up.`);
|
|
60334
60762
|
}
|
|
60335
60763
|
async function installCodexHooks(port) {
|
|
60336
|
-
const { mkdirSync: mkdirSync8, existsSync:
|
|
60337
|
-
const { join:
|
|
60338
|
-
const dir =
|
|
60339
|
-
if (!
|
|
60340
|
-
const file2 =
|
|
60764
|
+
const { mkdirSync: mkdirSync8, existsSync: existsSync29, readFileSync: readFileSync28, writeFileSync: writeFileSync23 } = await import("node:fs");
|
|
60765
|
+
const { join: join32 } = await import("node:path");
|
|
60766
|
+
const dir = join32(ROOT, ".codex");
|
|
60767
|
+
if (!existsSync29(dir)) mkdirSync8(dir, { recursive: true });
|
|
60768
|
+
const file2 = join32(dir, "config.toml");
|
|
60341
60769
|
const BEGIN = `# >>> errata hooks (errata-managed)`;
|
|
60342
60770
|
const END = `# <<< errata hooks`;
|
|
60343
60771
|
let existing = "";
|
|
60344
|
-
if (
|
|
60345
|
-
existing =
|
|
60772
|
+
if (existsSync29(file2)) {
|
|
60773
|
+
existing = readFileSync28(file2, "utf8");
|
|
60346
60774
|
const beginIdx = existing.indexOf(BEGIN);
|
|
60347
60775
|
const endIdx = existing.indexOf(END);
|
|
60348
60776
|
if (beginIdx >= 0 && endIdx > beginIdx) {
|
|
@@ -60371,7 +60799,7 @@ ${END}
|
|
|
60371
60799
|
const final = existing.length > 0 && !existing.endsWith("\n") ? `${existing}
|
|
60372
60800
|
|
|
60373
60801
|
${block}` : existing + (existing.endsWith("\n\n") ? "" : "\n") + block;
|
|
60374
|
-
|
|
60802
|
+
writeFileSync23(file2, final, "utf8");
|
|
60375
60803
|
console.log(`installed Codex hooks \u2192 ${file2}`);
|
|
60376
60804
|
console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
|
|
60377
60805
|
console.log("");
|
|
@@ -60564,16 +60992,38 @@ async function cmdDash(args2) {
|
|
|
60564
60992
|
}).catch(() => {
|
|
60565
60993
|
});
|
|
60566
60994
|
};
|
|
60995
|
+
const runSemanticPass = (reason) => {
|
|
60996
|
+
try {
|
|
60997
|
+
const reports = handle2.semanticMaintenanceAll();
|
|
60998
|
+
let cleared = 0;
|
|
60999
|
+
let settled = 0;
|
|
61000
|
+
let raised = 0;
|
|
61001
|
+
for (const r of reports.values()) {
|
|
61002
|
+
cleared += r.revisitsCleared;
|
|
61003
|
+
settled += r.fixCandidatesSettled;
|
|
61004
|
+
raised += r.designResolved;
|
|
61005
|
+
}
|
|
61006
|
+
if (cleared > 0 || settled > 0 || raised > 0) {
|
|
61007
|
+
console.log(
|
|
61008
|
+
`[semantic:${reason}] asks settled ${settled}, revisits cleared ${cleared}, questions raised ${raised}`
|
|
61009
|
+
);
|
|
61010
|
+
}
|
|
61011
|
+
} catch (err2) {
|
|
61012
|
+
console.warn(`[semantic] pass failed: ${err2 instanceof Error ? err2.message : err2}`);
|
|
61013
|
+
}
|
|
61014
|
+
};
|
|
60567
61015
|
const scheduleQuiescenceFlush = () => {
|
|
60568
61016
|
if (quiesceTimer) clearTimeout(quiesceTimer);
|
|
60569
61017
|
quiesceTimer = setTimeout(() => {
|
|
60570
61018
|
quiesceTimer = null;
|
|
60571
61019
|
runBoundaryFlush("quiescent");
|
|
61020
|
+
runSemanticPass("quiescent");
|
|
60572
61021
|
triggerConsolidation(false);
|
|
60573
61022
|
}, QUIESCENCE_MS);
|
|
60574
61023
|
};
|
|
60575
61024
|
handle2.onSessionBoundary(() => {
|
|
60576
61025
|
runBoundaryFlush("session-end");
|
|
61026
|
+
runSemanticPass("session-end");
|
|
60577
61027
|
triggerConsolidation(true);
|
|
60578
61028
|
});
|
|
60579
61029
|
let ticking = false;
|
|
@@ -60685,7 +61135,7 @@ async function cmdDash(args2) {
|
|
|
60685
61135
|
await yieldToLoop2();
|
|
60686
61136
|
try {
|
|
60687
61137
|
const items = selectDurableMemory(handle2.sharedStore, r.engine.profile);
|
|
60688
|
-
const res = bleedRules(
|
|
61138
|
+
const res = bleedRules(join31(r.root, ".claude", "rules"), items);
|
|
60689
61139
|
if (res.written || res.pruned) {
|
|
60690
61140
|
console.log(
|
|
60691
61141
|
`[rules:${r.entry.name}] ${res.written} collective principle(s) \u2192 .claude/rules` + (res.pruned ? `, ${res.pruned} pruned` : "")
|
|
@@ -60787,7 +61237,10 @@ async function cmdDash(args2) {
|
|
|
60787
61237
|
}
|
|
60788
61238
|
};
|
|
60789
61239
|
triggerConsolidation = (force) => void maybeConsolidate(force);
|
|
60790
|
-
const nightlyInterval = setInterval(() =>
|
|
61240
|
+
const nightlyInterval = setInterval(() => {
|
|
61241
|
+
runSemanticPass("periodic");
|
|
61242
|
+
triggerConsolidation(false);
|
|
61243
|
+
}, NIGHTLY_INTERVAL_MS);
|
|
60791
61244
|
const shutdown = async (signal) => {
|
|
60792
61245
|
console.log(`
|
|
60793
61246
|
shutting down\u2026 (${signal})`);
|