@inerrata-corporation/errata 2.0.2-dev.517 → 2.0.2-dev.532
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 +686 -235
- package/package.json +1 -1
- package/pass-worker.mjs +104 -27
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 && n.validTo == 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
|
});
|
|
@@ -30357,7 +30596,7 @@ async function scan(root, current, ignores, providers, out2) {
|
|
|
30357
30596
|
}
|
|
30358
30597
|
}
|
|
30359
30598
|
}
|
|
30360
|
-
function
|
|
30599
|
+
function gitListRelPaths(root, ignores) {
|
|
30361
30600
|
let stdout;
|
|
30362
30601
|
try {
|
|
30363
30602
|
stdout = execFileSync(
|
|
@@ -30380,6 +30619,15 @@ function gitListFiles(root, ignores, providers) {
|
|
|
30380
30619
|
if (segs.some((s) => ignores.has(s) || s.startsWith(".") && s.length > 1)) {
|
|
30381
30620
|
continue;
|
|
30382
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) {
|
|
30383
30631
|
const abs = join8(root, rel);
|
|
30384
30632
|
let size;
|
|
30385
30633
|
try {
|
|
@@ -37719,6 +37967,7 @@ var init_csharp_treesitter = __esm({
|
|
|
37719
37967
|
// ../../packages/indexer/src/index.ts
|
|
37720
37968
|
var src_exports5 = {};
|
|
37721
37969
|
__export(src_exports5, {
|
|
37970
|
+
DEFAULT_IGNORES: () => DEFAULT_IGNORES,
|
|
37722
37971
|
DRIFT_FORK_RATIO: () => DRIFT_FORK_RATIO,
|
|
37723
37972
|
TreeSitterCSharpProvider: () => TreeSitterCSharpProvider,
|
|
37724
37973
|
TreeSitterCppProvider: () => TreeSitterCppProvider,
|
|
@@ -37735,6 +37984,7 @@ __export(src_exports5, {
|
|
|
37735
37984
|
findInnermostScope: () => findInnermostScope,
|
|
37736
37985
|
folderNodeId: () => folderNodeId,
|
|
37737
37986
|
fromHex: () => fromHex,
|
|
37987
|
+
gitListRelPaths: () => gitListRelPaths,
|
|
37738
37988
|
hammingDistance: () => hammingDistance,
|
|
37739
37989
|
hasForkedDrift: () => hasForkedDrift,
|
|
37740
37990
|
incrementalReindex: () => incrementalReindex,
|
|
@@ -37847,6 +38097,8 @@ async function findStaleFiles(store, rootPath, workspaceId2) {
|
|
|
37847
38097
|
const fnode = store.getNode(fileNodeId(workspaceId2, rel));
|
|
37848
38098
|
if (!fnode) {
|
|
37849
38099
|
stale.push(abs);
|
|
38100
|
+
} else if ((fnode.validTo ?? null) !== null) {
|
|
38101
|
+
stale.push(abs);
|
|
37850
38102
|
} else if (fnode.lastUpdatedAt < mtimeMs) {
|
|
37851
38103
|
stale.push(abs);
|
|
37852
38104
|
} else {
|
|
@@ -37882,19 +38134,67 @@ function findStrandedSymbols(store) {
|
|
|
37882
38134
|
}
|
|
37883
38135
|
return stranded;
|
|
37884
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
|
+
}
|
|
37885
38174
|
async function reconcileStaleFiles(store, rootPath, workspaceId2) {
|
|
37886
38175
|
const stale = await findStaleFiles(store, rootPath, workspaceId2);
|
|
37887
38176
|
if (stale.length === 0) return 0;
|
|
37888
38177
|
let total = 0;
|
|
38178
|
+
let failedBatches = 0;
|
|
37889
38179
|
const BATCH = 20;
|
|
37890
38180
|
for (let i2 = 0; i2 < stale.length; i2 += BATCH) {
|
|
37891
|
-
|
|
37892
|
-
|
|
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
|
+
}
|
|
37893
38190
|
if (i2 + BATCH < stale.length) await new Promise((res) => setImmediate(res));
|
|
37894
38191
|
}
|
|
38192
|
+
if (failedBatches > 0) {
|
|
38193
|
+
console.warn(`[errata] reconcile: ${failedBatches} batch(es) failed; ${total} file(s) reindexed`);
|
|
38194
|
+
}
|
|
37895
38195
|
return total;
|
|
37896
38196
|
}
|
|
37897
|
-
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;
|
|
37898
38198
|
var init_reconcile = __esm({
|
|
37899
38199
|
"src/reconcile.ts"() {
|
|
37900
38200
|
"use strict";
|
|
@@ -37903,6 +38203,8 @@ var init_reconcile = __esm({
|
|
|
37903
38203
|
SOURCE_RE = /\.(ts|tsx|js|jsx|mjs|cjs|py)$/i;
|
|
37904
38204
|
SCAN_YIELD_EVERY = 100;
|
|
37905
38205
|
LIVENESS_CHUNK = 4e3;
|
|
38206
|
+
ORPHAN_REAP_MAX_FRACTION = 0.25;
|
|
38207
|
+
ORPHAN_REAP_MIN_ALLOWANCE = 50;
|
|
37906
38208
|
}
|
|
37907
38209
|
});
|
|
37908
38210
|
|
|
@@ -48066,27 +48368,27 @@ __export(witness_ledger_exports, {
|
|
|
48066
48368
|
summarizeWitnessLedger: () => summarizeWitnessLedger,
|
|
48067
48369
|
witnessLedgerPath: () => witnessLedgerPath
|
|
48068
48370
|
});
|
|
48069
|
-
import { appendFileSync as
|
|
48070
|
-
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";
|
|
48071
48373
|
function witnessLedgerPath(configDir) {
|
|
48072
|
-
return
|
|
48374
|
+
return join26(configDir, "witness-ledger.jsonl");
|
|
48073
48375
|
}
|
|
48074
48376
|
function appendWitnessLedger(configDir, entry) {
|
|
48075
48377
|
const path2 = witnessLedgerPath(configDir);
|
|
48076
48378
|
try {
|
|
48077
|
-
|
|
48078
|
-
const lines =
|
|
48379
|
+
appendFileSync3(path2, JSON.stringify(entry) + "\n");
|
|
48380
|
+
const lines = readFileSync21(path2, "utf8").split("\n").filter(Boolean);
|
|
48079
48381
|
if (lines.length > LEDGER_MAX_LINES) {
|
|
48080
|
-
|
|
48382
|
+
writeFileSync18(path2, lines.slice(-Math.floor(LEDGER_MAX_LINES / 2)).join("\n") + "\n");
|
|
48081
48383
|
}
|
|
48082
48384
|
} catch {
|
|
48083
48385
|
}
|
|
48084
48386
|
}
|
|
48085
48387
|
function readWitnessLedger(configDir) {
|
|
48086
48388
|
const path2 = witnessLedgerPath(configDir);
|
|
48087
|
-
if (!
|
|
48389
|
+
if (!existsSync21(path2)) return [];
|
|
48088
48390
|
try {
|
|
48089
|
-
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");
|
|
48090
48392
|
} catch {
|
|
48091
48393
|
return [];
|
|
48092
48394
|
}
|
|
@@ -48512,12 +48814,12 @@ var init_report_render = __esm({
|
|
|
48512
48814
|
|
|
48513
48815
|
// src/cli.ts
|
|
48514
48816
|
init_src6();
|
|
48515
|
-
import { closeSync as closeSync2, existsSync as
|
|
48516
|
-
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";
|
|
48517
48819
|
import { spawn as spawn3 } from "node:child_process";
|
|
48518
48820
|
|
|
48519
48821
|
// src/daemon.ts
|
|
48520
|
-
import { existsSync as
|
|
48822
|
+
import { existsSync as existsSync23, writeFileSync as writeFileSync20 } from "node:fs";
|
|
48521
48823
|
|
|
48522
48824
|
// ../../node_modules/.pnpm/@hono+node-server@1.19.11_hono@4.12.8/node_modules/@hono/node-server/dist/index.mjs
|
|
48523
48825
|
import { createServer as createServerHTTP } from "http";
|
|
@@ -49097,8 +49399,8 @@ init_config();
|
|
|
49097
49399
|
|
|
49098
49400
|
// src/engine.ts
|
|
49099
49401
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
49100
|
-
import { existsSync as
|
|
49101
|
-
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";
|
|
49102
49404
|
|
|
49103
49405
|
// ../../node_modules/.pnpm/chokidar@4.0.3/node_modules/chokidar/esm/index.js
|
|
49104
49406
|
import { stat as statcb } from "fs";
|
|
@@ -52197,6 +52499,48 @@ function repairInvalidEdges(store, opts) {
|
|
|
52197
52499
|
init_symbol_summaries();
|
|
52198
52500
|
init_reconcile();
|
|
52199
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
|
+
|
|
52200
52544
|
// src/episode.ts
|
|
52201
52545
|
init_src();
|
|
52202
52546
|
function deltaIsEmpty(d) {
|
|
@@ -52391,11 +52735,11 @@ init_outbox();
|
|
|
52391
52735
|
init_src9();
|
|
52392
52736
|
init_src();
|
|
52393
52737
|
init_src2();
|
|
52394
|
-
import { readFileSync as
|
|
52395
|
-
import { join as
|
|
52738
|
+
import { readFileSync as readFileSync14 } from "node:fs";
|
|
52739
|
+
import { join as join19 } from "node:path";
|
|
52396
52740
|
function loadClaimIgnorePatterns(workspaceRoot) {
|
|
52397
52741
|
try {
|
|
52398
|
-
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());
|
|
52399
52743
|
} catch {
|
|
52400
52744
|
return [];
|
|
52401
52745
|
}
|
|
@@ -52756,22 +53100,22 @@ async function pullCloudTriage(shared, cloud, profile, limit = 50) {
|
|
|
52756
53100
|
}
|
|
52757
53101
|
|
|
52758
53102
|
// src/git-sensor.ts
|
|
52759
|
-
import { existsSync as
|
|
52760
|
-
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";
|
|
52761
53105
|
function readFirstLine(path2) {
|
|
52762
53106
|
try {
|
|
52763
|
-
return
|
|
53107
|
+
return readFileSync15(path2, "utf8").split(/\r?\n/, 1)[0].trim();
|
|
52764
53108
|
} catch {
|
|
52765
53109
|
return null;
|
|
52766
53110
|
}
|
|
52767
53111
|
}
|
|
52768
53112
|
function readGitRefState(gitDir) {
|
|
52769
|
-
const head2 = readFirstLine(
|
|
53113
|
+
const head2 = readFirstLine(join20(gitDir, "HEAD"));
|
|
52770
53114
|
const m = head2 ? /^ref:\s*refs\/heads\/(.+)$/.exec(head2) : null;
|
|
52771
53115
|
const branch = m ? m[1] : null;
|
|
52772
53116
|
let sha2 = null;
|
|
52773
53117
|
if (branch) {
|
|
52774
|
-
sha2 = readFirstLine(
|
|
53118
|
+
sha2 = readFirstLine(join20(gitDir, "refs", "heads", branch));
|
|
52775
53119
|
if (!sha2) sha2 = shaFromPackedRefs(gitDir, `refs/heads/${branch}`);
|
|
52776
53120
|
} else if (head2 && /^[0-9a-f]{7,40}$/i.test(head2)) {
|
|
52777
53121
|
sha2 = head2;
|
|
@@ -52779,13 +53123,13 @@ function readGitRefState(gitDir) {
|
|
|
52779
53123
|
return {
|
|
52780
53124
|
branch,
|
|
52781
53125
|
sha: sha2,
|
|
52782
|
-
mergeHeadExists:
|
|
52783
|
-
origHeadExists:
|
|
53126
|
+
mergeHeadExists: existsSync16(join20(gitDir, "MERGE_HEAD")),
|
|
53127
|
+
origHeadExists: existsSync16(join20(gitDir, "ORIG_HEAD"))
|
|
52784
53128
|
};
|
|
52785
53129
|
}
|
|
52786
53130
|
function shaFromPackedRefs(gitDir, ref) {
|
|
52787
53131
|
try {
|
|
52788
|
-
for (const line of
|
|
53132
|
+
for (const line of readFileSync15(join20(gitDir, "packed-refs"), "utf8").split(/\r?\n/)) {
|
|
52789
53133
|
const [sha2, name2] = line.split(/\s+/);
|
|
52790
53134
|
if (name2 === ref && sha2) return sha2;
|
|
52791
53135
|
}
|
|
@@ -52819,7 +53163,7 @@ function startGitSensor(gitDir, onEvent, opts = {}) {
|
|
|
52819
53163
|
const settle = () => {
|
|
52820
53164
|
if (timer) clearTimeout(timer);
|
|
52821
53165
|
timer = setTimeout(() => {
|
|
52822
|
-
if (
|
|
53166
|
+
if (existsSync16(join20(gitDir, "index.lock"))) {
|
|
52823
53167
|
settle();
|
|
52824
53168
|
return;
|
|
52825
53169
|
}
|
|
@@ -52830,7 +53174,7 @@ function startGitSensor(gitDir, onEvent, opts = {}) {
|
|
|
52830
53174
|
}, debounceMs);
|
|
52831
53175
|
};
|
|
52832
53176
|
for (const sub of ["HEAD", "logs/HEAD", "MERGE_HEAD", "ORIG_HEAD"]) {
|
|
52833
|
-
const p =
|
|
53177
|
+
const p = join20(gitDir, sub);
|
|
52834
53178
|
try {
|
|
52835
53179
|
watchers.push(fsWatch(p, settle));
|
|
52836
53180
|
} catch {
|
|
@@ -53055,21 +53399,21 @@ var TelemetryRecorder = class {
|
|
|
53055
53399
|
|
|
53056
53400
|
// src/skills.ts
|
|
53057
53401
|
import {
|
|
53058
|
-
existsSync as
|
|
53402
|
+
existsSync as existsSync17,
|
|
53059
53403
|
mkdirSync as mkdirSync6,
|
|
53060
|
-
readFileSync as
|
|
53404
|
+
readFileSync as readFileSync16,
|
|
53061
53405
|
readdirSync as readdirSync7,
|
|
53062
53406
|
unlinkSync as unlinkSync2,
|
|
53063
|
-
writeFileSync as
|
|
53407
|
+
writeFileSync as writeFileSync14
|
|
53064
53408
|
} from "node:fs";
|
|
53065
|
-
import { basename as basename4, join as
|
|
53409
|
+
import { basename as basename4, join as join21 } from "node:path";
|
|
53066
53410
|
function skillFileName(id) {
|
|
53067
53411
|
return `${id.replace(/[^A-Za-z0-9_.-]/g, "_")}.md`;
|
|
53068
53412
|
}
|
|
53069
53413
|
function readSkillManifest(manifestPath) {
|
|
53070
|
-
if (!
|
|
53414
|
+
if (!existsSync17(manifestPath)) return [];
|
|
53071
53415
|
try {
|
|
53072
|
-
const parsed = JSON.parse(
|
|
53416
|
+
const parsed = JSON.parse(readFileSync16(manifestPath, "utf8"));
|
|
53073
53417
|
return (parsed.skills ?? []).map((s) => ({
|
|
53074
53418
|
title: s.title ?? "",
|
|
53075
53419
|
layer: s.layer ?? "technique",
|
|
@@ -53093,7 +53437,7 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
|
|
|
53093
53437
|
for (const s of res.skills) {
|
|
53094
53438
|
const fileName = skillFileName(s.id);
|
|
53095
53439
|
keep.add(fileName);
|
|
53096
|
-
|
|
53440
|
+
writeFileSync14(join21(paths.skillsDir, fileName), s.markdown, "utf8");
|
|
53097
53441
|
rows.push({
|
|
53098
53442
|
id: s.id,
|
|
53099
53443
|
title: s.title,
|
|
@@ -53106,7 +53450,7 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
|
|
|
53106
53450
|
const fileName = skillFileName(p.id);
|
|
53107
53451
|
if (keep.has(fileName)) continue;
|
|
53108
53452
|
keep.add(fileName);
|
|
53109
|
-
|
|
53453
|
+
writeFileSync14(join21(paths.skillsDir, fileName), p.markdown, "utf8");
|
|
53110
53454
|
rows.push({
|
|
53111
53455
|
id: p.id,
|
|
53112
53456
|
title: p.title,
|
|
@@ -53120,13 +53464,13 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
|
|
|
53120
53464
|
if (!f.endsWith(".md")) continue;
|
|
53121
53465
|
if (keep.has(basename4(f))) continue;
|
|
53122
53466
|
try {
|
|
53123
|
-
unlinkSync2(
|
|
53467
|
+
unlinkSync2(join21(paths.skillsDir, f));
|
|
53124
53468
|
pruned++;
|
|
53125
53469
|
} catch {
|
|
53126
53470
|
}
|
|
53127
53471
|
}
|
|
53128
53472
|
rows.sort((a, b) => a.id.localeCompare(b.id));
|
|
53129
|
-
|
|
53473
|
+
writeFileSync14(
|
|
53130
53474
|
paths.skillsManifest,
|
|
53131
53475
|
JSON.stringify({ generatedAt: Date.now(), skills: rows }, null, 2),
|
|
53132
53476
|
"utf8"
|
|
@@ -53138,22 +53482,22 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
|
|
|
53138
53482
|
init_src2();
|
|
53139
53483
|
import {
|
|
53140
53484
|
cpSync,
|
|
53141
|
-
existsSync as
|
|
53485
|
+
existsSync as existsSync18,
|
|
53142
53486
|
lstatSync,
|
|
53143
53487
|
mkdirSync as mkdirSync7,
|
|
53144
|
-
readFileSync as
|
|
53488
|
+
readFileSync as readFileSync17,
|
|
53145
53489
|
readdirSync as readdirSync8,
|
|
53146
53490
|
rmSync as rmSync2,
|
|
53147
53491
|
symlinkSync,
|
|
53148
|
-
writeFileSync as
|
|
53492
|
+
writeFileSync as writeFileSync15
|
|
53149
53493
|
} from "node:fs";
|
|
53150
|
-
import { join as
|
|
53494
|
+
import { join as join22 } from "node:path";
|
|
53151
53495
|
var SKILL_NS = "errata-";
|
|
53152
53496
|
var HARNESS_SKILL_DIRS = [
|
|
53153
|
-
{ configDir: ".claude", skillsDir:
|
|
53497
|
+
{ configDir: ".claude", skillsDir: join22(".claude", "skills") },
|
|
53154
53498
|
// Cursor adopted the standard; its exact project dir is still moving — kept
|
|
53155
53499
|
// best-effort and gated on `.cursor/` presence so we never create it blind.
|
|
53156
|
-
{ configDir: ".cursor", skillsDir:
|
|
53500
|
+
{ configDir: ".cursor", skillsDir: join22(".cursor", "skills") }
|
|
53157
53501
|
];
|
|
53158
53502
|
function skillSlug(title, id) {
|
|
53159
53503
|
const base = title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || id.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "skill";
|
|
@@ -53198,12 +53542,12 @@ function skillCiteHandle(s) {
|
|
|
53198
53542
|
return priorHandle({ id: s.id, description: s.title });
|
|
53199
53543
|
}
|
|
53200
53544
|
function reconcileNamespaced(dir, keep) {
|
|
53201
|
-
if (!
|
|
53545
|
+
if (!existsSync18(dir)) return 0;
|
|
53202
53546
|
let pruned = 0;
|
|
53203
53547
|
for (const name2 of readdirSync8(dir)) {
|
|
53204
53548
|
if (!name2.startsWith(SKILL_NS) || keep.has(name2)) continue;
|
|
53205
53549
|
try {
|
|
53206
|
-
rmSync2(
|
|
53550
|
+
rmSync2(join22(dir, name2), { recursive: true, force: true });
|
|
53207
53551
|
pruned++;
|
|
53208
53552
|
} catch {
|
|
53209
53553
|
}
|
|
@@ -53212,7 +53556,7 @@ function reconcileNamespaced(dir, keep) {
|
|
|
53212
53556
|
}
|
|
53213
53557
|
function linkOrCopy(linkPath, target) {
|
|
53214
53558
|
try {
|
|
53215
|
-
if (
|
|
53559
|
+
if (existsSync18(linkPath) || safeLstat(linkPath)) rmSync2(linkPath, { recursive: true, force: true });
|
|
53216
53560
|
} catch {
|
|
53217
53561
|
}
|
|
53218
53562
|
try {
|
|
@@ -53233,7 +53577,7 @@ function safeLstat(p) {
|
|
|
53233
53577
|
}
|
|
53234
53578
|
}
|
|
53235
53579
|
function emitAndProjectSkills(root, skills) {
|
|
53236
|
-
const agentsSkillsDir =
|
|
53580
|
+
const agentsSkillsDir = join22(root, ".agents", "skills");
|
|
53237
53581
|
mkdirSync7(agentsSkillsDir, { recursive: true });
|
|
53238
53582
|
const slugs = [];
|
|
53239
53583
|
const keep = /* @__PURE__ */ new Set();
|
|
@@ -53241,7 +53585,7 @@ function emitAndProjectSkills(root, skills) {
|
|
|
53241
53585
|
for (const s of skills) {
|
|
53242
53586
|
let body2;
|
|
53243
53587
|
try {
|
|
53244
|
-
body2 =
|
|
53588
|
+
body2 = readFileSync17(s.bodyPath, "utf8");
|
|
53245
53589
|
} catch {
|
|
53246
53590
|
continue;
|
|
53247
53591
|
}
|
|
@@ -53250,9 +53594,9 @@ function emitAndProjectSkills(root, skills) {
|
|
|
53250
53594
|
keep.add(slug2);
|
|
53251
53595
|
slugs.push(slug2);
|
|
53252
53596
|
const description = deriveDescription(s.title, s.layer, body2);
|
|
53253
|
-
mkdirSync7(
|
|
53254
|
-
|
|
53255
|
-
|
|
53597
|
+
mkdirSync7(join22(agentsSkillsDir, slug2), { recursive: true });
|
|
53598
|
+
writeFileSync15(
|
|
53599
|
+
join22(agentsSkillsDir, slug2, "SKILL.md"),
|
|
53256
53600
|
renderSkillMd(slug2, description, body2, skillCiteHandle(s)),
|
|
53257
53601
|
"utf8"
|
|
53258
53602
|
);
|
|
@@ -53261,11 +53605,11 @@ function emitAndProjectSkills(root, skills) {
|
|
|
53261
53605
|
reconcileNamespaced(agentsSkillsDir, keep);
|
|
53262
53606
|
let projected = 0;
|
|
53263
53607
|
for (const h of HARNESS_SKILL_DIRS) {
|
|
53264
|
-
if (!
|
|
53265
|
-
const dir =
|
|
53608
|
+
if (!existsSync18(join22(root, h.configDir))) continue;
|
|
53609
|
+
const dir = join22(root, h.skillsDir);
|
|
53266
53610
|
mkdirSync7(dir, { recursive: true });
|
|
53267
53611
|
for (const slug2 of slugs) {
|
|
53268
|
-
linkOrCopy(
|
|
53612
|
+
linkOrCopy(join22(dir, slug2), join22(agentsSkillsDir, slug2));
|
|
53269
53613
|
projected++;
|
|
53270
53614
|
}
|
|
53271
53615
|
reconcileNamespaced(dir, keep);
|
|
@@ -53274,15 +53618,15 @@ function emitAndProjectSkills(root, skills) {
|
|
|
53274
53618
|
return { slugs, emitted, projected };
|
|
53275
53619
|
}
|
|
53276
53620
|
function emitInputsFromManifest(erretaDir, manifestPath) {
|
|
53277
|
-
if (!
|
|
53621
|
+
if (!existsSync18(manifestPath)) return [];
|
|
53278
53622
|
try {
|
|
53279
|
-
const parsed = JSON.parse(
|
|
53623
|
+
const parsed = JSON.parse(readFileSync17(manifestPath, "utf8"));
|
|
53280
53624
|
return (parsed.skills ?? []).filter((s) => Boolean(s.id && s.file)).map((s) => ({
|
|
53281
53625
|
id: s.id,
|
|
53282
53626
|
title: s.title ?? s.id,
|
|
53283
53627
|
layer: s.layer ?? "technique",
|
|
53284
53628
|
confidence: s.confidence ?? 0,
|
|
53285
|
-
bodyPath:
|
|
53629
|
+
bodyPath: join22(erretaDir, s.file)
|
|
53286
53630
|
}));
|
|
53287
53631
|
} catch {
|
|
53288
53632
|
return [];
|
|
@@ -53296,17 +53640,17 @@ var GITIGNORE_LINES = [
|
|
|
53296
53640
|
".cursor/skills/errata-*/"
|
|
53297
53641
|
];
|
|
53298
53642
|
function ensureSkillGitignore(root) {
|
|
53299
|
-
const path2 =
|
|
53643
|
+
const path2 = join22(root, ".gitignore");
|
|
53300
53644
|
let current = "";
|
|
53301
53645
|
try {
|
|
53302
|
-
current =
|
|
53646
|
+
current = existsSync18(path2) ? readFileSync17(path2, "utf8") : "";
|
|
53303
53647
|
} catch {
|
|
53304
53648
|
return;
|
|
53305
53649
|
}
|
|
53306
53650
|
if (current.includes(GITIGNORE_MARK)) return;
|
|
53307
53651
|
const prefix = current.length > 0 && !current.endsWith("\n") ? "\n" : "";
|
|
53308
53652
|
try {
|
|
53309
|
-
|
|
53653
|
+
writeFileSync15(path2, `${current}${prefix}
|
|
53310
53654
|
${GITIGNORE_LINES.join("\n")}
|
|
53311
53655
|
`, "utf8");
|
|
53312
53656
|
} catch {
|
|
@@ -53399,20 +53743,20 @@ init_paths();
|
|
|
53399
53743
|
// src/profile.ts
|
|
53400
53744
|
init_src2();
|
|
53401
53745
|
init_paths();
|
|
53402
|
-
import { existsSync as
|
|
53746
|
+
import { existsSync as existsSync20, readFileSync as readFileSync19, writeFileSync as writeFileSync16 } from "node:fs";
|
|
53403
53747
|
import { createHash as createHash12 } from "node:crypto";
|
|
53404
|
-
import { join as
|
|
53748
|
+
import { join as join24 } from "node:path";
|
|
53405
53749
|
|
|
53406
53750
|
// src/git-remote.ts
|
|
53407
53751
|
init_src();
|
|
53408
|
-
import { existsSync as
|
|
53409
|
-
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";
|
|
53410
53754
|
function resolveGitDir(root) {
|
|
53411
|
-
const dotGit =
|
|
53755
|
+
const dotGit = join23(root, ".git");
|
|
53412
53756
|
try {
|
|
53413
53757
|
const st = statSync4(dotGit);
|
|
53414
53758
|
if (st.isDirectory()) return dotGit;
|
|
53415
|
-
const m = /^gitdir:\s*(.+?)\s*$/m.exec(
|
|
53759
|
+
const m = /^gitdir:\s*(.+?)\s*$/m.exec(readFileSync18(dotGit, "utf8"));
|
|
53416
53760
|
if (!m) return null;
|
|
53417
53761
|
const dir = m[1];
|
|
53418
53762
|
return isAbsolute3(dir) ? dir : resolve5(root, dir);
|
|
@@ -53421,22 +53765,22 @@ function resolveGitDir(root) {
|
|
|
53421
53765
|
}
|
|
53422
53766
|
}
|
|
53423
53767
|
function gitConfigPath(gitDir) {
|
|
53424
|
-
const commondirFile =
|
|
53425
|
-
if (
|
|
53426
|
-
const common =
|
|
53768
|
+
const commondirFile = join23(gitDir, "commondir");
|
|
53769
|
+
if (existsSync19(commondirFile)) {
|
|
53770
|
+
const common = readFileSync18(commondirFile, "utf8").trim();
|
|
53427
53771
|
const commonDir = isAbsolute3(common) ? common : resolve5(gitDir, common);
|
|
53428
|
-
return
|
|
53772
|
+
return join23(commonDir, "config");
|
|
53429
53773
|
}
|
|
53430
|
-
return
|
|
53774
|
+
return join23(gitDir, "config");
|
|
53431
53775
|
}
|
|
53432
53776
|
function readRemotes(root) {
|
|
53433
53777
|
const gitDir = resolveGitDir(root);
|
|
53434
53778
|
if (!gitDir) return [];
|
|
53435
53779
|
const cfgPath = gitConfigPath(gitDir);
|
|
53436
|
-
if (!
|
|
53780
|
+
if (!existsSync19(cfgPath)) return [];
|
|
53437
53781
|
let txt;
|
|
53438
53782
|
try {
|
|
53439
|
-
txt =
|
|
53783
|
+
txt = readFileSync18(cfgPath, "utf8");
|
|
53440
53784
|
} catch {
|
|
53441
53785
|
return [];
|
|
53442
53786
|
}
|
|
@@ -53478,13 +53822,13 @@ function refreshRepoLocator(root, profile) {
|
|
|
53478
53822
|
}
|
|
53479
53823
|
function loadProfile(root) {
|
|
53480
53824
|
const p = workspacePaths(root);
|
|
53481
|
-
if (!
|
|
53482
|
-
return JSON.parse(
|
|
53825
|
+
if (!existsSync20(p.workspaceJson)) return null;
|
|
53826
|
+
return JSON.parse(readFileSync19(p.workspaceJson, "utf8"));
|
|
53483
53827
|
}
|
|
53484
53828
|
function saveProfile(root, profile) {
|
|
53485
53829
|
const p = workspacePaths(root);
|
|
53486
53830
|
ensureDir(p.configDir);
|
|
53487
|
-
|
|
53831
|
+
writeFileSync16(p.workspaceJson, JSON.stringify(profile, null, 2), "utf8");
|
|
53488
53832
|
}
|
|
53489
53833
|
function autodetectProfile(root) {
|
|
53490
53834
|
const id = workspaceId(root);
|
|
@@ -53492,10 +53836,10 @@ function autodetectProfile(root) {
|
|
|
53492
53836
|
const p = emptyProfile(id, name2);
|
|
53493
53837
|
const locator = detectRepoLocator(root);
|
|
53494
53838
|
if (locator) p.repoLocator = locator;
|
|
53495
|
-
const pkgPath =
|
|
53496
|
-
if (
|
|
53839
|
+
const pkgPath = join24(root, "package.json");
|
|
53840
|
+
if (existsSync20(pkgPath)) {
|
|
53497
53841
|
try {
|
|
53498
|
-
const pkg = JSON.parse(
|
|
53842
|
+
const pkg = JSON.parse(readFileSync19(pkgPath, "utf8"));
|
|
53499
53843
|
p.languages.push("typescript", "javascript");
|
|
53500
53844
|
const nodeVer = pkg.engines?.node ?? "node";
|
|
53501
53845
|
p.stack.push(`node@${nodeVer}`);
|
|
@@ -53516,10 +53860,10 @@ function autodetectProfile(root) {
|
|
|
53516
53860
|
} catch {
|
|
53517
53861
|
}
|
|
53518
53862
|
}
|
|
53519
|
-
const pyproject =
|
|
53520
|
-
if (
|
|
53863
|
+
const pyproject = join24(root, "pyproject.toml");
|
|
53864
|
+
if (existsSync20(pyproject)) {
|
|
53521
53865
|
try {
|
|
53522
|
-
const txt =
|
|
53866
|
+
const txt = readFileSync19(pyproject, "utf8");
|
|
53523
53867
|
const py = /python\s*=\s*"([^"]+)"/.exec(txt)?.[1];
|
|
53524
53868
|
p.languages.push("python");
|
|
53525
53869
|
p.stack.push(`python@${py ?? "3"}`);
|
|
@@ -53530,16 +53874,16 @@ function autodetectProfile(root) {
|
|
|
53530
53874
|
} catch {
|
|
53531
53875
|
}
|
|
53532
53876
|
}
|
|
53533
|
-
const reqs =
|
|
53534
|
-
if (
|
|
53877
|
+
const reqs = join24(root, "requirements.txt");
|
|
53878
|
+
if (existsSync20(reqs)) {
|
|
53535
53879
|
if (!p.languages.includes("python")) p.languages.push("python");
|
|
53536
53880
|
if (!p.stack.includes("python@3")) p.stack.push("python@3");
|
|
53537
53881
|
}
|
|
53538
|
-
if (
|
|
53882
|
+
if (existsSync20(join24(root, "go.mod"))) {
|
|
53539
53883
|
p.languages.push("go");
|
|
53540
53884
|
p.stack.push("go");
|
|
53541
53885
|
}
|
|
53542
|
-
if (
|
|
53886
|
+
if (existsSync20(join24(root, "Cargo.toml"))) {
|
|
53543
53887
|
p.languages.push("rust");
|
|
53544
53888
|
p.stack.push("rust");
|
|
53545
53889
|
}
|
|
@@ -53549,17 +53893,17 @@ function autodetectProfile(root) {
|
|
|
53549
53893
|
}
|
|
53550
53894
|
|
|
53551
53895
|
// src/witness-queue.ts
|
|
53552
|
-
import { readFileSync as
|
|
53553
|
-
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";
|
|
53554
53898
|
var WITNESS_QUEUE_CAP = 500;
|
|
53555
53899
|
var WITNESS_TTL_MS = 14 * 24 * 60 * 60 * 1e3;
|
|
53556
53900
|
var WITNESS_MAX_ATTEMPTS = 5;
|
|
53557
53901
|
function witnessQueuePath(workspaceConfigDir) {
|
|
53558
|
-
return
|
|
53902
|
+
return join25(workspaceConfigDir, "witness-queue.json");
|
|
53559
53903
|
}
|
|
53560
53904
|
function loadWitnessQueue(path2) {
|
|
53561
53905
|
try {
|
|
53562
|
-
const raw2 = JSON.parse(
|
|
53906
|
+
const raw2 = JSON.parse(readFileSync20(path2, "utf8"));
|
|
53563
53907
|
if (!Array.isArray(raw2)) return [];
|
|
53564
53908
|
return raw2.filter(
|
|
53565
53909
|
(w) => !!w && typeof w === "object" && typeof w.nodeId === "string" && typeof w.witnessKey === "string"
|
|
@@ -53570,8 +53914,8 @@ function loadWitnessQueue(path2) {
|
|
|
53570
53914
|
}
|
|
53571
53915
|
function saveWitnessQueue(path2, queue) {
|
|
53572
53916
|
try {
|
|
53573
|
-
const tmp =
|
|
53574
|
-
|
|
53917
|
+
const tmp = join25(dirname9(path2), `.${Date.now()}.witness-queue.tmp`);
|
|
53918
|
+
writeFileSync17(tmp, JSON.stringify(queue), "utf8");
|
|
53575
53919
|
renameSync2(tmp, path2);
|
|
53576
53920
|
} catch {
|
|
53577
53921
|
}
|
|
@@ -53862,7 +54206,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
|
|
|
53862
54206
|
}
|
|
53863
54207
|
|
|
53864
54208
|
// src/engine.ts
|
|
53865
|
-
var DAEMON_VERSION = true ? "2.0.2-dev.
|
|
54209
|
+
var DAEMON_VERSION = true ? "2.0.2-dev.532" : "2.0.0-alpha.0";
|
|
53866
54210
|
var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
|
|
53867
54211
|
var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
|
|
53868
54212
|
var GIT_OP_MUTE_MS = 4e3;
|
|
@@ -53872,17 +54216,17 @@ var TURN_REPLAY_LOOKBACK_MS = 7 * 24 * 60 * 6e4;
|
|
|
53872
54216
|
function appendIdentityAudit(path2, record2, line) {
|
|
53873
54217
|
if (!record2.accepted && record2.score <= 0) return;
|
|
53874
54218
|
try {
|
|
53875
|
-
if (
|
|
54219
|
+
if (existsSync22(path2) && statSync5(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
|
|
53876
54220
|
renameSync3(path2, `${path2}.1`);
|
|
53877
54221
|
}
|
|
53878
|
-
|
|
54222
|
+
appendFileSync4(path2, line);
|
|
53879
54223
|
} catch {
|
|
53880
54224
|
}
|
|
53881
54225
|
}
|
|
53882
54226
|
var yieldToLoop = () => new Promise((r) => setImmediate(r));
|
|
53883
54227
|
function loadTurnCursors(path2) {
|
|
53884
54228
|
try {
|
|
53885
|
-
const raw2 = JSON.parse(
|
|
54229
|
+
const raw2 = JSON.parse(readFileSync22(path2, "utf8"));
|
|
53886
54230
|
return new Map(
|
|
53887
54231
|
Object.entries(raw2).map(([k, v]) => [k, typeof v === "string" ? v : String(v?.uuid ?? "")])
|
|
53888
54232
|
);
|
|
@@ -53892,7 +54236,7 @@ function loadTurnCursors(path2) {
|
|
|
53892
54236
|
}
|
|
53893
54237
|
function loadTurnOffsets(path2) {
|
|
53894
54238
|
try {
|
|
53895
|
-
const raw2 = JSON.parse(
|
|
54239
|
+
const raw2 = JSON.parse(readFileSync22(path2, "utf8"));
|
|
53896
54240
|
const out2 = /* @__PURE__ */ new Map();
|
|
53897
54241
|
for (const [k, v] of Object.entries(raw2)) {
|
|
53898
54242
|
const off = typeof v === "object" && v !== null ? v.offset : void 0;
|
|
@@ -53908,7 +54252,7 @@ function saveTurnCursors(path2, cursors, offsets) {
|
|
|
53908
54252
|
const merged = {};
|
|
53909
54253
|
for (const [k, uuid3] of cursors) merged[k] = { uuid: uuid3, offset: offsets.get(k) ?? 0 };
|
|
53910
54254
|
for (const [k, offset] of offsets) if (!merged[k]) merged[k] = { uuid: "", offset };
|
|
53911
|
-
|
|
54255
|
+
writeFileSync19(path2, JSON.stringify(merged), "utf8");
|
|
53912
54256
|
} catch {
|
|
53913
54257
|
}
|
|
53914
54258
|
}
|
|
@@ -53930,7 +54274,7 @@ function gitSourceWatchTargets(root) {
|
|
|
53930
54274
|
["-C", root, "ls-files", "--others", "--ignored", "--exclude-standard", "--directory", "-z"],
|
|
53931
54275
|
{ encoding: "utf8", maxBuffer: 256 * 1024 * 1024, windowsHide: true, stdio: ["ignore", "pipe", "ignore"] }
|
|
53932
54276
|
);
|
|
53933
|
-
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));
|
|
53934
54278
|
} catch {
|
|
53935
54279
|
}
|
|
53936
54280
|
const hasIgnoredChild = (dir) => ignoredDirs.some((ig) => ig.startsWith(dir + "/"));
|
|
@@ -53942,19 +54286,19 @@ function gitSourceWatchTargets(root) {
|
|
|
53942
54286
|
if (!f.startsWith(prefix)) continue;
|
|
53943
54287
|
const rest2 = f.slice(prefix.length);
|
|
53944
54288
|
if (rest2.includes("/")) children.add(dir === "" ? rest2.slice(0, rest2.indexOf("/")) : dir + "/" + rest2.slice(0, rest2.indexOf("/")));
|
|
53945
|
-
else targets.add(
|
|
54289
|
+
else targets.add(join27(root, f));
|
|
53946
54290
|
}
|
|
53947
54291
|
for (const c of children) {
|
|
53948
|
-
if (IGNORED_PATH.test(
|
|
54292
|
+
if (IGNORED_PATH.test(join27(root, c) + sep4)) continue;
|
|
53949
54293
|
if (hasIgnoredChild(c)) addUnder(c);
|
|
53950
|
-
else targets.add(
|
|
54294
|
+
else targets.add(join27(root, c));
|
|
53951
54295
|
}
|
|
53952
54296
|
};
|
|
53953
54297
|
addUnder("");
|
|
53954
54298
|
if (targets.size > 0) return [...targets];
|
|
53955
54299
|
} catch {
|
|
53956
54300
|
}
|
|
53957
|
-
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)));
|
|
53958
54302
|
}
|
|
53959
54303
|
function createWorkspaceEngine(opts) {
|
|
53960
54304
|
const paths = workspacePaths(opts.workspaceRoot);
|
|
@@ -54112,7 +54456,7 @@ function createWorkspaceEngine(opts) {
|
|
|
54112
54456
|
const srcPaths = diff.changedPaths.filter((p) => /\.(ts|tsx|js|jsx|mjs|cjs|py)$/i.test(p));
|
|
54113
54457
|
let episodeId2;
|
|
54114
54458
|
if (srcPaths.length > 0) {
|
|
54115
|
-
const abs = srcPaths.map((p) =>
|
|
54459
|
+
const abs = srcPaths.map((p) => join27(opts.workspaceRoot, p));
|
|
54116
54460
|
try {
|
|
54117
54461
|
const r = await runReindexPass(
|
|
54118
54462
|
`git-reindex:${profile.name} (${abs.length} files)`,
|
|
@@ -54148,8 +54492,8 @@ function createWorkspaceEngine(opts) {
|
|
|
54148
54492
|
`[errata] git: ${ev.kind} ${ev.newSha.slice(0, 7)} by ${meta3.authorName} \u2014 ${diff.changedPaths.length} file(s), ${diff.renames.length} rename(s)`
|
|
54149
54493
|
);
|
|
54150
54494
|
};
|
|
54151
|
-
const gitDir =
|
|
54152
|
-
if (
|
|
54495
|
+
const gitDir = join27(opts.workspaceRoot, ".git");
|
|
54496
|
+
if (existsSync22(gitDir)) {
|
|
54153
54497
|
stopGit = startGitSensor(gitDir, (ev) => {
|
|
54154
54498
|
void handleGitEvent(ev).catch((err2) => {
|
|
54155
54499
|
console.warn("[errata] git event handler failed:", err2);
|
|
@@ -54162,7 +54506,26 @@ function createWorkspaceEngine(opts) {
|
|
|
54162
54506
|
if (n > 0) {
|
|
54163
54507
|
console.log(`[errata] reconcile: re-indexed ${n} stale file(s) on startup`);
|
|
54164
54508
|
}
|
|
54165
|
-
}).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
|
+
});
|
|
54166
54529
|
});
|
|
54167
54530
|
}
|
|
54168
54531
|
const workingFiles = createWorkingFileState();
|
|
@@ -54254,15 +54617,19 @@ function createWorkspaceEngine(opts) {
|
|
|
54254
54617
|
doneRender?.();
|
|
54255
54618
|
try {
|
|
54256
54619
|
const seq = store.currentIngestSeq();
|
|
54257
|
-
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
|
+
});
|
|
54258
54625
|
} catch (err2) {
|
|
54259
54626
|
console.warn("[errata] render ledger failed:", err2.message?.slice(0, 120));
|
|
54260
54627
|
}
|
|
54261
54628
|
writeContextFile(opts.workspaceRoot, body2);
|
|
54262
|
-
const target =
|
|
54629
|
+
const target = join27(opts.workspaceRoot, "AGENTS.md");
|
|
54263
54630
|
writeManagedBlock(target, { body: AGENTS_POINTER_BODY, stable: true, force: true });
|
|
54264
54631
|
if (elicit) {
|
|
54265
|
-
writePrimingHandles(
|
|
54632
|
+
writePrimingHandles(join27(paths.configDir, "priming-handles.json"), [
|
|
54266
54633
|
...snapshot.recentProblems.map((r) => r.node),
|
|
54267
54634
|
// Resolved-band handles: the ✓ problem AND its Solution are citable
|
|
54268
54635
|
// (a fix tag on an already-resolved problem no-ops idempotently; the
|
|
@@ -54484,7 +54851,7 @@ function createWorkspaceEngine(opts) {
|
|
|
54484
54851
|
resultSummary: { exitCode: e.exitCode ?? 1, errorTokens: e.errorTokens }
|
|
54485
54852
|
});
|
|
54486
54853
|
};
|
|
54487
|
-
const turnCursorPath =
|
|
54854
|
+
const turnCursorPath = join27(paths.configDir, "turn-cursors.json");
|
|
54488
54855
|
const lastTurnUuid = loadTurnCursors(turnCursorPath);
|
|
54489
54856
|
const turnOffset = loadTurnOffsets(turnCursorPath);
|
|
54490
54857
|
const sessionLastProblem = /* @__PURE__ */ new Map();
|
|
@@ -54507,8 +54874,9 @@ function createWorkspaceEngine(opts) {
|
|
|
54507
54874
|
let linked = 0;
|
|
54508
54875
|
const t = Date.now();
|
|
54509
54876
|
let processedTurns = 0;
|
|
54877
|
+
const seqAtStart = store.currentIngestSeq();
|
|
54510
54878
|
const elicit = isEdgeElicitationEnabled();
|
|
54511
|
-
const handleMap = elicit ? readPrimingHandles(
|
|
54879
|
+
const handleMap = elicit ? readPrimingHandles(join27(paths.configDir, "priming-handles.json")) : {};
|
|
54512
54880
|
const wsRoot = (opts.workspaceRoot ?? "").replace(/\\/g, "/");
|
|
54513
54881
|
const toRel = (abs) => {
|
|
54514
54882
|
const p = abs.replace(/\\/g, "/");
|
|
@@ -55015,6 +55383,16 @@ function createWorkspaceEngine(opts) {
|
|
|
55015
55383
|
if (triaged > 0) {
|
|
55016
55384
|
console.log(`[errata] triage: ${triaged} wrong-door(s) captured from the conversation`);
|
|
55017
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
|
+
}
|
|
55018
55396
|
};
|
|
55019
55397
|
const harvestTurns = async (sessionId, transcriptPath) => {
|
|
55020
55398
|
const known = turnOffset.get(sessionId);
|
|
@@ -55181,7 +55559,7 @@ function createWorkspaceEngine(opts) {
|
|
|
55181
55559
|
try {
|
|
55182
55560
|
const inputs = emitInputsFromManifest(paths.configDir, paths.skillsManifest);
|
|
55183
55561
|
emitAndProjectSkills(opts.workspaceRoot, inputs);
|
|
55184
|
-
writePrimingHandles(
|
|
55562
|
+
writePrimingHandles(join27(paths.configDir, "priming-handles.json"), skillHandleNodes(inputs));
|
|
55185
55563
|
} catch (err2) {
|
|
55186
55564
|
console.warn("[skills] agent-skills projection failed (non-fatal):", err2 instanceof Error ? err2.message : err2);
|
|
55187
55565
|
}
|
|
@@ -55265,6 +55643,26 @@ function createWorkspaceEngine(opts) {
|
|
|
55265
55643
|
}
|
|
55266
55644
|
return report;
|
|
55267
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
|
+
},
|
|
55268
55666
|
async nightly() {
|
|
55269
55667
|
const report = (await runNightly()).report;
|
|
55270
55668
|
const summarizer = opts.intentSummarizer ?? envIntentSummarizer();
|
|
@@ -55280,6 +55678,18 @@ function createWorkspaceEngine(opts) {
|
|
|
55280
55678
|
console.warn("[errata] symbol summary sweep failed:", err2 instanceof Error ? err2.message : err2);
|
|
55281
55679
|
}
|
|
55282
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
|
+
});
|
|
55283
55693
|
return report;
|
|
55284
55694
|
},
|
|
55285
55695
|
async embedSettled() {
|
|
@@ -55368,7 +55778,7 @@ function createWorkspaceEngine(opts) {
|
|
|
55368
55778
|
console.log(
|
|
55369
55779
|
"[errata] sync skipped \u2014 cloud sync consent is off (enable with `errata consent sync on`)"
|
|
55370
55780
|
);
|
|
55371
|
-
const pending =
|
|
55781
|
+
const pending = existsSync22(paths.outbox) ? readdirSync9(paths.outbox).filter((f) => f.endsWith(".json")).length : 0;
|
|
55372
55782
|
return { uploaded: 0, failed: 0, remaining: pending };
|
|
55373
55783
|
}
|
|
55374
55784
|
try {
|
|
@@ -55455,7 +55865,7 @@ async function startDaemon(opts) {
|
|
|
55455
55865
|
reviewUrl: () => webUiUrl + "/review"
|
|
55456
55866
|
});
|
|
55457
55867
|
const writeLockFile = (url2) => {
|
|
55458
|
-
|
|
55868
|
+
writeFileSync20(
|
|
55459
55869
|
engine.paths.daemonLock,
|
|
55460
55870
|
JSON.stringify({ pid: process.pid, webUiUrl: url2, startedAt: Date.now() }),
|
|
55461
55871
|
"utf8"
|
|
@@ -55498,7 +55908,7 @@ async function startDaemon(opts) {
|
|
|
55498
55908
|
);
|
|
55499
55909
|
await engine.stop();
|
|
55500
55910
|
try {
|
|
55501
|
-
if (
|
|
55911
|
+
if (existsSync23(engine.paths.daemonLock)) {
|
|
55502
55912
|
}
|
|
55503
55913
|
} catch {
|
|
55504
55914
|
}
|
|
@@ -55515,16 +55925,16 @@ async function listenServer(fetchFn, port) {
|
|
|
55515
55925
|
|
|
55516
55926
|
// src/registry.ts
|
|
55517
55927
|
init_paths();
|
|
55518
|
-
import { existsSync as
|
|
55519
|
-
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";
|
|
55520
55930
|
function registryPath() {
|
|
55521
|
-
return process.env["ERRATA_REGISTRY_PATH"] ??
|
|
55931
|
+
return process.env["ERRATA_REGISTRY_PATH"] ?? join28(globalDir(), "workspaces.json");
|
|
55522
55932
|
}
|
|
55523
55933
|
function read() {
|
|
55524
55934
|
const p = registryPath();
|
|
55525
|
-
if (!
|
|
55935
|
+
if (!existsSync24(p)) return { version: 1, workspaces: {} };
|
|
55526
55936
|
try {
|
|
55527
|
-
const parsed = JSON.parse(
|
|
55937
|
+
const parsed = JSON.parse(readFileSync23(p, "utf8"));
|
|
55528
55938
|
return { version: 1, workspaces: parsed.workspaces ?? {} };
|
|
55529
55939
|
} catch {
|
|
55530
55940
|
return { version: 1, workspaces: {} };
|
|
@@ -55532,7 +55942,7 @@ function read() {
|
|
|
55532
55942
|
}
|
|
55533
55943
|
function write(reg) {
|
|
55534
55944
|
ensureDir(globalDir());
|
|
55535
|
-
|
|
55945
|
+
writeFileSync21(registryPath(), JSON.stringify(reg, null, 2), "utf8");
|
|
55536
55946
|
}
|
|
55537
55947
|
function registerWorkspace(profile, root, now = Date.now()) {
|
|
55538
55948
|
const reg = read();
|
|
@@ -55549,7 +55959,7 @@ function pruneMissingWorkspaces() {
|
|
|
55549
55959
|
const reg = read();
|
|
55550
55960
|
const removed = [];
|
|
55551
55961
|
for (const [id, entry] of Object.entries(reg.workspaces)) {
|
|
55552
|
-
if (!
|
|
55962
|
+
if (!existsSync24(entry.path)) {
|
|
55553
55963
|
removed.push(entry);
|
|
55554
55964
|
delete reg.workspaces[id];
|
|
55555
55965
|
}
|
|
@@ -55558,13 +55968,13 @@ function pruneMissingWorkspaces() {
|
|
|
55558
55968
|
return removed;
|
|
55559
55969
|
}
|
|
55560
55970
|
function workspaceStatus(entry) {
|
|
55561
|
-
const missing = !
|
|
55971
|
+
const missing = !existsSync24(entry.path);
|
|
55562
55972
|
const lockPath = workspacePaths(entry.path).daemonLock;
|
|
55563
55973
|
let running = false;
|
|
55564
55974
|
let webUiUrl = null;
|
|
55565
|
-
if (
|
|
55975
|
+
if (existsSync24(lockPath)) {
|
|
55566
55976
|
try {
|
|
55567
|
-
const lock = JSON.parse(
|
|
55977
|
+
const lock = JSON.parse(readFileSync23(lockPath, "utf8"));
|
|
55568
55978
|
if (lock.pid && lock.webUiUrl && pidAlive(lock.pid)) {
|
|
55569
55979
|
running = true;
|
|
55570
55980
|
webUiUrl = lock.webUiUrl;
|
|
@@ -55592,7 +56002,7 @@ function pidAlive(pid) {
|
|
|
55592
56002
|
// src/multi.ts
|
|
55593
56003
|
init_dist();
|
|
55594
56004
|
init_src5();
|
|
55595
|
-
import { readFileSync as
|
|
56005
|
+
import { readFileSync as readFileSync26, unlinkSync as unlinkSync3, writeFileSync as writeFileSync22 } from "node:fs";
|
|
55596
56006
|
|
|
55597
56007
|
// src/principle-sync.ts
|
|
55598
56008
|
init_src5();
|
|
@@ -55620,8 +56030,8 @@ init_reconcile();
|
|
|
55620
56030
|
|
|
55621
56031
|
// src/lockfile-auto.ts
|
|
55622
56032
|
init_src();
|
|
55623
|
-
import { existsSync as
|
|
55624
|
-
import { join as
|
|
56033
|
+
import { existsSync as existsSync25, readFileSync as readFileSync24 } from "node:fs";
|
|
56034
|
+
import { join as join29 } from "node:path";
|
|
55625
56035
|
|
|
55626
56036
|
// src/package-index.ts
|
|
55627
56037
|
init_src();
|
|
@@ -55770,11 +56180,11 @@ function runLockfilePass(opts) {
|
|
|
55770
56180
|
{ file: "package-lock.json", parse: parsePackageLockJson }
|
|
55771
56181
|
];
|
|
55772
56182
|
for (const c of candidates) {
|
|
55773
|
-
const p =
|
|
55774
|
-
if (!
|
|
56183
|
+
const p = join29(opts.root, c.file);
|
|
56184
|
+
if (!existsSync25(p)) continue;
|
|
55775
56185
|
let sbom;
|
|
55776
56186
|
try {
|
|
55777
|
-
sbom = c.parse(
|
|
56187
|
+
sbom = c.parse(readFileSync24(p, "utf8"));
|
|
55778
56188
|
} catch {
|
|
55779
56189
|
continue;
|
|
55780
56190
|
}
|
|
@@ -56222,7 +56632,7 @@ var ConsolidateWorker = class {
|
|
|
56222
56632
|
init_paths();
|
|
56223
56633
|
|
|
56224
56634
|
// src/lock.ts
|
|
56225
|
-
import { existsSync as
|
|
56635
|
+
import { existsSync as existsSync26, readFileSync as readFileSync25 } from "node:fs";
|
|
56226
56636
|
function isProcessAlive(pid) {
|
|
56227
56637
|
if (!pid || pid <= 0) return false;
|
|
56228
56638
|
try {
|
|
@@ -56233,9 +56643,9 @@ function isProcessAlive(pid) {
|
|
|
56233
56643
|
}
|
|
56234
56644
|
}
|
|
56235
56645
|
function readDaemonLock(lockPath) {
|
|
56236
|
-
if (!
|
|
56646
|
+
if (!existsSync26(lockPath)) return null;
|
|
56237
56647
|
try {
|
|
56238
|
-
const lock = JSON.parse(
|
|
56648
|
+
const lock = JSON.parse(readFileSync25(lockPath, "utf8"));
|
|
56239
56649
|
return typeof lock.pid === "number" ? lock : null;
|
|
56240
56650
|
} catch {
|
|
56241
56651
|
return null;
|
|
@@ -56519,12 +56929,12 @@ async function reanchorProject(opts) {
|
|
|
56519
56929
|
}
|
|
56520
56930
|
|
|
56521
56931
|
// src/adopt.ts
|
|
56522
|
-
import { existsSync as
|
|
56523
|
-
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";
|
|
56524
56934
|
function findGitRoot(absPath) {
|
|
56525
56935
|
let dir = absPath;
|
|
56526
56936
|
for (let depth = 0; depth < 64; depth++) {
|
|
56527
|
-
if (
|
|
56937
|
+
if (existsSync27(join30(dir, ".git"))) return dir;
|
|
56528
56938
|
const parent = dirname10(dir);
|
|
56529
56939
|
if (parent === dir) return null;
|
|
56530
56940
|
dir = parent;
|
|
@@ -56773,7 +57183,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
56773
57183
|
void ambientLinkAll();
|
|
56774
57184
|
app.route(`/ws/${rec.id}`, rec.webApp);
|
|
56775
57185
|
try {
|
|
56776
|
-
|
|
57186
|
+
writeFileSync22(
|
|
56777
57187
|
rec.engine.paths.daemonLock,
|
|
56778
57188
|
JSON.stringify({ pid: process.pid, webUiUrl: `${baseUrl}/ws/${rec.id}`, startedAt: Date.now() }),
|
|
56779
57189
|
"utf8"
|
|
@@ -56962,7 +57372,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
56962
57372
|
baseUrl = `http://127.0.0.1:${port}`;
|
|
56963
57373
|
try {
|
|
56964
57374
|
ensureDir(globalDir());
|
|
56965
|
-
|
|
57375
|
+
writeFileSync22(
|
|
56966
57376
|
lockPath,
|
|
56967
57377
|
JSON.stringify({ pid: process.pid, webUiUrl: baseUrl, startedAt: Date.now() }),
|
|
56968
57378
|
"utf8"
|
|
@@ -56971,7 +57381,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
56971
57381
|
}
|
|
56972
57382
|
for (const r of records) {
|
|
56973
57383
|
try {
|
|
56974
|
-
|
|
57384
|
+
writeFileSync22(
|
|
56975
57385
|
r.engine.paths.daemonLock,
|
|
56976
57386
|
JSON.stringify({ pid: process.pid, webUiUrl: `${baseUrl}/ws/${r.id}`, startedAt: Date.now() }),
|
|
56977
57387
|
"utf8"
|
|
@@ -57098,6 +57508,22 @@ async function startMultiDaemon(opts = {}) {
|
|
|
57098
57508
|
}
|
|
57099
57509
|
return out2;
|
|
57100
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
|
+
},
|
|
57101
57527
|
async nightlyAll() {
|
|
57102
57528
|
const out2 = /* @__PURE__ */ new Map();
|
|
57103
57529
|
for (const r of records) {
|
|
@@ -57503,7 +57929,7 @@ async function startMultiDaemon(opts = {}) {
|
|
|
57503
57929
|
},
|
|
57504
57930
|
async stop() {
|
|
57505
57931
|
try {
|
|
57506
|
-
const cur =
|
|
57932
|
+
const cur = readFileSync26(lockPath, "utf8");
|
|
57507
57933
|
if (JSON.parse(cur).pid === process.pid) unlinkSync3(lockPath);
|
|
57508
57934
|
} catch {
|
|
57509
57935
|
}
|
|
@@ -58520,21 +58946,21 @@ async function cmdInit() {
|
|
|
58520
58946
|
if (!skipHooks) {
|
|
58521
58947
|
console.log("");
|
|
58522
58948
|
console.log("installing harness hooks...");
|
|
58523
|
-
const { existsSync:
|
|
58524
|
-
const { join:
|
|
58949
|
+
const { existsSync: existsSync29 } = await import("node:fs");
|
|
58950
|
+
const { join: join32 } = await import("node:path");
|
|
58525
58951
|
try {
|
|
58526
58952
|
await installClaudeHooks(port);
|
|
58527
58953
|
} catch (err2) {
|
|
58528
58954
|
console.warn(` \u26A0\uFE0F Claude hook install failed: ${err2 instanceof Error ? err2.message : err2}`);
|
|
58529
58955
|
}
|
|
58530
|
-
if (
|
|
58956
|
+
if (existsSync29(join32(ROOT, ".cursor"))) {
|
|
58531
58957
|
try {
|
|
58532
58958
|
await installCursorMcpConfig();
|
|
58533
58959
|
} catch (err2) {
|
|
58534
58960
|
console.warn(` \u26A0\uFE0F Cursor MCP config failed: ${err2 instanceof Error ? err2.message : err2}`);
|
|
58535
58961
|
}
|
|
58536
58962
|
}
|
|
58537
|
-
if (
|
|
58963
|
+
if (existsSync29(join32(ROOT, ".codex"))) {
|
|
58538
58964
|
try {
|
|
58539
58965
|
await installCodexHooks(port);
|
|
58540
58966
|
} catch (err2) {
|
|
@@ -58691,9 +59117,9 @@ async function cmdStatus() {
|
|
|
58691
59117
|
console.log(` stack: ${profile.stack.join(", ") || "(none)"}`);
|
|
58692
59118
|
console.log(` languages: ${profile.languages.join(", ") || "(none)"}`);
|
|
58693
59119
|
}
|
|
58694
|
-
console.log(` graph db: ${
|
|
58695
|
-
console.log(` event log: ${
|
|
58696
|
-
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)) {
|
|
58697
59123
|
try {
|
|
58698
59124
|
const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src5(), src_exports2));
|
|
58699
59125
|
const store = openGraphStore2({ path: paths.castalia });
|
|
@@ -59374,11 +59800,11 @@ function cmdInstallationProfile(args2) {
|
|
|
59374
59800
|
}
|
|
59375
59801
|
async function cmdReview() {
|
|
59376
59802
|
const paths = workspacePaths(ROOT);
|
|
59377
|
-
if (!
|
|
59803
|
+
if (!existsSync28(paths.reviewQueue)) {
|
|
59378
59804
|
console.log("(review queue empty)");
|
|
59379
59805
|
return;
|
|
59380
59806
|
}
|
|
59381
|
-
const queue = JSON.parse(
|
|
59807
|
+
const queue = JSON.parse(readFileSync27(paths.reviewQueue, "utf8"));
|
|
59382
59808
|
if (queue.length === 0) {
|
|
59383
59809
|
console.log("(review queue empty)");
|
|
59384
59810
|
return;
|
|
@@ -60049,7 +60475,7 @@ async function gatherRepo(store, ws) {
|
|
|
60049
60475
|
};
|
|
60050
60476
|
}
|
|
60051
60477
|
async function gatherReportData(generatedAt) {
|
|
60052
|
-
const { existsSync:
|
|
60478
|
+
const { existsSync: existsSync29 } = await import("node:fs");
|
|
60053
60479
|
const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src5(), src_exports2));
|
|
60054
60480
|
const cfg = loadConfig();
|
|
60055
60481
|
const outbound = cfg.consent.sync ? "auto" : "off";
|
|
@@ -60057,7 +60483,7 @@ async function gatherReportData(generatedAt) {
|
|
|
60057
60483
|
for (const ws of listWorkspaces()) {
|
|
60058
60484
|
if (ws.missing) continue;
|
|
60059
60485
|
const dbPath = workspacePaths(ws.path).castalia;
|
|
60060
|
-
if (!
|
|
60486
|
+
if (!existsSync29(dbPath)) continue;
|
|
60061
60487
|
let store = null;
|
|
60062
60488
|
try {
|
|
60063
60489
|
store = openGraphStore2({ path: dbPath });
|
|
@@ -60088,7 +60514,7 @@ async function gatherReportData(generatedAt) {
|
|
|
60088
60514
|
};
|
|
60089
60515
|
}
|
|
60090
60516
|
async function cmdReport(args2) {
|
|
60091
|
-
const { mkdirSync: mkdirSync8, writeFileSync:
|
|
60517
|
+
const { mkdirSync: mkdirSync8, writeFileSync: writeFileSync23 } = await import("node:fs");
|
|
60092
60518
|
const { renderReport: renderReport2 } = await Promise.resolve().then(() => (init_report_render(), report_render_exports));
|
|
60093
60519
|
const includeFutureVerbs = args2.includes("--future-verbs");
|
|
60094
60520
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -60101,8 +60527,8 @@ async function cmdReport(args2) {
|
|
|
60101
60527
|
const outDir = workspacePaths(ROOT).configDir;
|
|
60102
60528
|
mkdirSync8(outDir, { recursive: true });
|
|
60103
60529
|
const files = renderReport2(data, { includeFutureVerbs });
|
|
60104
|
-
for (const f of files)
|
|
60105
|
-
const indexPath =
|
|
60530
|
+
for (const f of files) writeFileSync23(join31(outDir, f.name), f.html, "utf8");
|
|
60531
|
+
const indexPath = join31(outDir, "report.html");
|
|
60106
60532
|
console.log(`report \u2192 ${indexPath}`);
|
|
60107
60533
|
console.log(
|
|
60108
60534
|
` ${data.repos.length} repo(s) \xB7 ${files.length} file(s) \xB7 ${data.rollup.nodes.toLocaleString("en-US")} nodes`
|
|
@@ -60220,15 +60646,15 @@ function hookRelayCommand(port, path2) {
|
|
|
60220
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 '{}'`;
|
|
60221
60647
|
}
|
|
60222
60648
|
async function installClaudeHooks(port) {
|
|
60223
|
-
const { mkdirSync: mkdirSync8, existsSync:
|
|
60224
|
-
const { join:
|
|
60225
|
-
const dir =
|
|
60226
|
-
if (!
|
|
60227
|
-
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");
|
|
60228
60654
|
let settings = {};
|
|
60229
|
-
if (
|
|
60655
|
+
if (existsSync29(file2)) {
|
|
60230
60656
|
try {
|
|
60231
|
-
settings = JSON.parse(
|
|
60657
|
+
settings = JSON.parse(readFileSync28(file2, "utf8"));
|
|
60232
60658
|
} catch {
|
|
60233
60659
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
60234
60660
|
process.exit(2);
|
|
@@ -60274,10 +60700,10 @@ async function installClaudeHooks(port) {
|
|
|
60274
60700
|
dropErrata(list);
|
|
60275
60701
|
list.push({ hooks: [{ type: "command", command: injectCmd }] });
|
|
60276
60702
|
}
|
|
60277
|
-
|
|
60703
|
+
writeFileSync23(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
|
|
60278
60704
|
console.log(`installed Claude Code hooks \u2192 ${file2}`);
|
|
60279
60705
|
await installClaudeMcpConfig();
|
|
60280
|
-
const claudeMd =
|
|
60706
|
+
const claudeMd = join32(ROOT, "CLAUDE.md");
|
|
60281
60707
|
const recall = writeManagedBlock(claudeMd, { body: RECALL_FIRST_BLOCK });
|
|
60282
60708
|
if (recall.kind === "collision") {
|
|
60283
60709
|
console.warn(
|
|
@@ -60289,15 +60715,15 @@ async function installClaudeHooks(port) {
|
|
|
60289
60715
|
console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
|
|
60290
60716
|
}
|
|
60291
60717
|
async function installClaudeMcpConfig() {
|
|
60292
|
-
const { mkdirSync: mkdirSync8, existsSync:
|
|
60293
|
-
const { join:
|
|
60294
|
-
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");
|
|
60295
60721
|
const dir = dirname11(file2);
|
|
60296
|
-
if (!
|
|
60722
|
+
if (!existsSync29(dir)) mkdirSync8(dir, { recursive: true });
|
|
60297
60723
|
let cfg = {};
|
|
60298
|
-
if (
|
|
60724
|
+
if (existsSync29(file2)) {
|
|
60299
60725
|
try {
|
|
60300
|
-
cfg = JSON.parse(
|
|
60726
|
+
cfg = JSON.parse(readFileSync28(file2, "utf8"));
|
|
60301
60727
|
} catch {
|
|
60302
60728
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
60303
60729
|
process.exit(2);
|
|
@@ -60305,21 +60731,21 @@ async function installClaudeMcpConfig() {
|
|
|
60305
60731
|
}
|
|
60306
60732
|
cfg.mcpServers ??= {};
|
|
60307
60733
|
cfg.mcpServers["errata"] = errataMcpInvocation();
|
|
60308
|
-
|
|
60734
|
+
writeFileSync23(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
|
|
60309
60735
|
console.log(`installed Claude Code MCP server config \u2192 ${file2}`);
|
|
60310
60736
|
console.log(` Claude Code will spawn \`errata mcp\` on workspace open.`);
|
|
60311
60737
|
console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses / show / similar`);
|
|
60312
60738
|
}
|
|
60313
60739
|
async function installCursorMcpConfig() {
|
|
60314
|
-
const { mkdirSync: mkdirSync8, existsSync:
|
|
60315
|
-
const { join:
|
|
60316
|
-
const dir =
|
|
60317
|
-
if (!
|
|
60318
|
-
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");
|
|
60319
60745
|
let cfg = {};
|
|
60320
|
-
if (
|
|
60746
|
+
if (existsSync29(file2)) {
|
|
60321
60747
|
try {
|
|
60322
|
-
cfg = JSON.parse(
|
|
60748
|
+
cfg = JSON.parse(readFileSync28(file2, "utf8"));
|
|
60323
60749
|
} catch {
|
|
60324
60750
|
console.error(`refusing to overwrite invalid JSON at ${file2}`);
|
|
60325
60751
|
process.exit(2);
|
|
@@ -60327,7 +60753,7 @@ async function installCursorMcpConfig() {
|
|
|
60327
60753
|
}
|
|
60328
60754
|
cfg.mcpServers ??= {};
|
|
60329
60755
|
cfg.mcpServers["errata"] = errataMcpInvocation();
|
|
60330
|
-
|
|
60756
|
+
writeFileSync23(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
|
|
60331
60757
|
console.log(`installed Cursor MCP server config \u2192 ${file2}`);
|
|
60332
60758
|
console.log(` Cursor will spawn \`errata mcp\` on workspace open.`);
|
|
60333
60759
|
console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses`);
|
|
@@ -60335,16 +60761,16 @@ async function installCursorMcpConfig() {
|
|
|
60335
60761
|
console.log(` \u26A0\uFE0F reload Cursor (Cmd/Ctrl-Shift-P \u2192 "Reload Window") to pick it up.`);
|
|
60336
60762
|
}
|
|
60337
60763
|
async function installCodexHooks(port) {
|
|
60338
|
-
const { mkdirSync: mkdirSync8, existsSync:
|
|
60339
|
-
const { join:
|
|
60340
|
-
const dir =
|
|
60341
|
-
if (!
|
|
60342
|
-
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");
|
|
60343
60769
|
const BEGIN = `# >>> errata hooks (errata-managed)`;
|
|
60344
60770
|
const END = `# <<< errata hooks`;
|
|
60345
60771
|
let existing = "";
|
|
60346
|
-
if (
|
|
60347
|
-
existing =
|
|
60772
|
+
if (existsSync29(file2)) {
|
|
60773
|
+
existing = readFileSync28(file2, "utf8");
|
|
60348
60774
|
const beginIdx = existing.indexOf(BEGIN);
|
|
60349
60775
|
const endIdx = existing.indexOf(END);
|
|
60350
60776
|
if (beginIdx >= 0 && endIdx > beginIdx) {
|
|
@@ -60373,7 +60799,7 @@ ${END}
|
|
|
60373
60799
|
const final = existing.length > 0 && !existing.endsWith("\n") ? `${existing}
|
|
60374
60800
|
|
|
60375
60801
|
${block}` : existing + (existing.endsWith("\n\n") ? "" : "\n") + block;
|
|
60376
|
-
|
|
60802
|
+
writeFileSync23(file2, final, "utf8");
|
|
60377
60803
|
console.log(`installed Codex hooks \u2192 ${file2}`);
|
|
60378
60804
|
console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
|
|
60379
60805
|
console.log("");
|
|
@@ -60566,16 +60992,38 @@ async function cmdDash(args2) {
|
|
|
60566
60992
|
}).catch(() => {
|
|
60567
60993
|
});
|
|
60568
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
|
+
};
|
|
60569
61015
|
const scheduleQuiescenceFlush = () => {
|
|
60570
61016
|
if (quiesceTimer) clearTimeout(quiesceTimer);
|
|
60571
61017
|
quiesceTimer = setTimeout(() => {
|
|
60572
61018
|
quiesceTimer = null;
|
|
60573
61019
|
runBoundaryFlush("quiescent");
|
|
61020
|
+
runSemanticPass("quiescent");
|
|
60574
61021
|
triggerConsolidation(false);
|
|
60575
61022
|
}, QUIESCENCE_MS);
|
|
60576
61023
|
};
|
|
60577
61024
|
handle2.onSessionBoundary(() => {
|
|
60578
61025
|
runBoundaryFlush("session-end");
|
|
61026
|
+
runSemanticPass("session-end");
|
|
60579
61027
|
triggerConsolidation(true);
|
|
60580
61028
|
});
|
|
60581
61029
|
let ticking = false;
|
|
@@ -60687,7 +61135,7 @@ async function cmdDash(args2) {
|
|
|
60687
61135
|
await yieldToLoop2();
|
|
60688
61136
|
try {
|
|
60689
61137
|
const items = selectDurableMemory(handle2.sharedStore, r.engine.profile);
|
|
60690
|
-
const res = bleedRules(
|
|
61138
|
+
const res = bleedRules(join31(r.root, ".claude", "rules"), items);
|
|
60691
61139
|
if (res.written || res.pruned) {
|
|
60692
61140
|
console.log(
|
|
60693
61141
|
`[rules:${r.entry.name}] ${res.written} collective principle(s) \u2192 .claude/rules` + (res.pruned ? `, ${res.pruned} pruned` : "")
|
|
@@ -60789,7 +61237,10 @@ async function cmdDash(args2) {
|
|
|
60789
61237
|
}
|
|
60790
61238
|
};
|
|
60791
61239
|
triggerConsolidation = (force) => void maybeConsolidate(force);
|
|
60792
|
-
const nightlyInterval = setInterval(() =>
|
|
61240
|
+
const nightlyInterval = setInterval(() => {
|
|
61241
|
+
runSemanticPass("periodic");
|
|
61242
|
+
triggerConsolidation(false);
|
|
61243
|
+
}, NIGHTLY_INTERVAL_MS);
|
|
60793
61244
|
const shutdown = async (signal) => {
|
|
60794
61245
|
console.log(`
|
|
60795
61246
|
shutting down\u2026 (${signal})`);
|