@inerrata-corporation/errata 2.0.2-dev.633 → 2.0.2-dev.646
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/errata.mjs +119 -35
- package/package.json +1 -1
package/errata.mjs
CHANGED
|
@@ -18962,14 +18962,19 @@ function ingestDesignProblem(store, flag, opts) {
|
|
|
18962
18962
|
}
|
|
18963
18963
|
let solutionId = null;
|
|
18964
18964
|
if (flag.fix?.trim() && !isFragmentFixNote(flag.fix)) {
|
|
18965
|
-
|
|
18966
|
-
|
|
18967
|
-
|
|
18968
|
-
|
|
18969
|
-
|
|
18970
|
-
|
|
18971
|
-
|
|
18972
|
-
|
|
18965
|
+
const reuse = findReusableSolution(store, flag.fix);
|
|
18966
|
+
if (reuse) {
|
|
18967
|
+
solutionId = reuse.id;
|
|
18968
|
+
} else {
|
|
18969
|
+
solutionId = `dfix_${digest({ problemId, fix: flag.fix })}`.slice(0, 56);
|
|
18970
|
+
store.mergeNode(
|
|
18971
|
+
buildNode(store, solutionId, "Solution", flag.fix.trim(), opts.ts, {
|
|
18972
|
+
source: "convo",
|
|
18973
|
+
provisional: true,
|
|
18974
|
+
rationale: flag.fix.trim()
|
|
18975
|
+
})
|
|
18976
|
+
);
|
|
18977
|
+
}
|
|
18973
18978
|
mergeEdge(store, problemId, solutionId, "SOLVED_BY", opts.ts);
|
|
18974
18979
|
}
|
|
18975
18980
|
let anchored = false;
|
|
@@ -19177,6 +19182,19 @@ function isFragmentFixNote(note) {
|
|
|
19177
19182
|
function isAutoMinted(n) {
|
|
19178
19183
|
return n.label === "Solution" && String(n.description ?? "").startsWith(AUTO_MINT_PREFIX);
|
|
19179
19184
|
}
|
|
19185
|
+
function solutionTextKey(text) {
|
|
19186
|
+
return text.trim().replace(/\s+/g, " ").toLowerCase();
|
|
19187
|
+
}
|
|
19188
|
+
function findReusableSolution(store, fixText) {
|
|
19189
|
+
const key = solutionTextKey(fixText);
|
|
19190
|
+
if (!key) return null;
|
|
19191
|
+
for (const s of store.findNodesByLabel("Solution")) {
|
|
19192
|
+
if (s.validTo != null) continue;
|
|
19193
|
+
if (isAutoMinted(s)) continue;
|
|
19194
|
+
if (solutionTextKey(s.description ?? "") === key) return s;
|
|
19195
|
+
}
|
|
19196
|
+
return null;
|
|
19197
|
+
}
|
|
19180
19198
|
function priorsForFile(store, relPath) {
|
|
19181
19199
|
const want = relPath.trim().replace(/^\.?\//, "");
|
|
19182
19200
|
let file2 = null;
|
|
@@ -19360,11 +19378,16 @@ function closeDesignProblem(store, problemId, fixNote, t) {
|
|
|
19360
19378
|
if (fixNote?.trim() && !isFragmentFixNote(fixNote)) {
|
|
19361
19379
|
const sols = store.outEdges(problemId, ["SOLVED_BY"]).map((e) => store.getNode(e.to)).filter((n) => n !== null);
|
|
19362
19380
|
if (sols.every((s) => isAutoMinted(s))) {
|
|
19363
|
-
const
|
|
19364
|
-
|
|
19365
|
-
|
|
19366
|
-
|
|
19367
|
-
|
|
19381
|
+
const reuse = findReusableSolution(store, fixNote);
|
|
19382
|
+
if (reuse) {
|
|
19383
|
+
mergeEdge(store, problemId, reuse.id, "SOLVED_BY", t);
|
|
19384
|
+
} else {
|
|
19385
|
+
const solId = `dfix_${digest({ problemId, fix: fixNote })}`.slice(0, 56);
|
|
19386
|
+
store.mergeNode(
|
|
19387
|
+
buildNode(store, solId, "Solution", fixNote.trim(), t, { source: "convo", provisional: false })
|
|
19388
|
+
);
|
|
19389
|
+
mergeEdge(store, problemId, solId, "SOLVED_BY", t);
|
|
19390
|
+
}
|
|
19368
19391
|
}
|
|
19369
19392
|
}
|
|
19370
19393
|
if (p.attrs["resolvedAt"]) return false;
|
|
@@ -21246,8 +21269,9 @@ function harvestTriageFences(l2, text, opts) {
|
|
|
21246
21269
|
);
|
|
21247
21270
|
if (f.fix) {
|
|
21248
21271
|
const fix = f.fix.trim();
|
|
21249
|
-
const
|
|
21250
|
-
|
|
21272
|
+
const reuse = findReusableSolution(l2, fix);
|
|
21273
|
+
const fixId = reuse ? reuse.id : `dfix_${digest({ cause: causeId, fix })}`.slice(0, 56);
|
|
21274
|
+
if (!reuse && !l2.getNode(fixId)) {
|
|
21251
21275
|
l2.mergeNode(semNode(l2, fixId, "Solution", fix, opts.ts, { scope: {} }));
|
|
21252
21276
|
}
|
|
21253
21277
|
const solEdgeId = `edge_sol_${causeId}_${fixId}`;
|
|
@@ -21264,6 +21288,7 @@ var init_triage2 = __esm({
|
|
|
21264
21288
|
"../../packages/local-graph/src/triage.ts"() {
|
|
21265
21289
|
"use strict";
|
|
21266
21290
|
init_src();
|
|
21291
|
+
init_design_problem();
|
|
21267
21292
|
init_src();
|
|
21268
21293
|
init_src();
|
|
21269
21294
|
init_src4();
|
|
@@ -22294,6 +22319,7 @@ __export(src_exports2, {
|
|
|
22294
22319
|
findMintTimeDuplicate: () => findMintTimeDuplicate,
|
|
22295
22320
|
findOrCreatePackage: () => findOrCreatePackage,
|
|
22296
22321
|
findPath: () => findPath,
|
|
22322
|
+
findReusableSolution: () => findReusableSolution,
|
|
22297
22323
|
flattenCloudCounts: () => flattenCloudCounts,
|
|
22298
22324
|
foldDuplicateProblem: () => foldDuplicateProblem,
|
|
22299
22325
|
formatMechanismStatus: () => formatMechanismStatus,
|
|
@@ -27529,10 +27555,15 @@ function buildSymbolLexicon(store, summariesByBodyHash2) {
|
|
|
27529
27555
|
}
|
|
27530
27556
|
return lex;
|
|
27531
27557
|
}
|
|
27558
|
+
function isBareMatchableStem(stem) {
|
|
27559
|
+
return stem.length >= 5 && /^[A-Za-z0-9]+(?:[-_][A-Za-z0-9]+)+$/.test(stem);
|
|
27560
|
+
}
|
|
27532
27561
|
function buildFileLexicon(store) {
|
|
27533
27562
|
const byKey = /* @__PURE__ */ new Map();
|
|
27534
27563
|
const byBasename = /* @__PURE__ */ new Map();
|
|
27564
|
+
const byStem = /* @__PURE__ */ new Map();
|
|
27535
27565
|
const basenameCount = /* @__PURE__ */ new Map();
|
|
27566
|
+
const stemRelPaths = /* @__PURE__ */ new Map();
|
|
27536
27567
|
const entries = [];
|
|
27537
27568
|
for (const n of store.findNodesByLabel("File")) {
|
|
27538
27569
|
const relPath = typeof n.attrs["relPath"] === "string" && n.attrs["relPath"].length > 0 ? n.attrs["relPath"] : n.description;
|
|
@@ -27541,6 +27572,12 @@ function buildFileLexicon(store) {
|
|
|
27541
27572
|
if (!basename5.includes(".")) continue;
|
|
27542
27573
|
entries.push({ relPath, basename: basename5 });
|
|
27543
27574
|
basenameCount.set(basename5, (basenameCount.get(basename5) ?? 0) + 1);
|
|
27575
|
+
const stem = basename5.slice(0, basename5.indexOf("."));
|
|
27576
|
+
if (isBareMatchableStem(stem)) {
|
|
27577
|
+
let s = stemRelPaths.get(stem);
|
|
27578
|
+
if (!s) stemRelPaths.set(stem, s = /* @__PURE__ */ new Set());
|
|
27579
|
+
s.add(relPath);
|
|
27580
|
+
}
|
|
27544
27581
|
}
|
|
27545
27582
|
for (const { relPath, basename: basename5 } of entries) {
|
|
27546
27583
|
const entry = { relPath };
|
|
@@ -27550,8 +27587,18 @@ function buildFileLexicon(store) {
|
|
|
27550
27587
|
const list = byBasename.get(basename5);
|
|
27551
27588
|
if (list) list.push(entry);
|
|
27552
27589
|
else byBasename.set(basename5, [entry]);
|
|
27590
|
+
const stem = basename5.slice(0, basename5.indexOf("."));
|
|
27591
|
+
if (isBareMatchableStem(stem) && !CONVENTION_STEMS.has(stem) && !byStem.has(stem)) {
|
|
27592
|
+
const dirStems = new Set(
|
|
27593
|
+
[...stemRelPaths.get(stem) ?? []].map((p) => {
|
|
27594
|
+
const bn = p.split("/").pop();
|
|
27595
|
+
return p.slice(0, p.length - bn.length) + bn.slice(0, bn.indexOf("."));
|
|
27596
|
+
})
|
|
27597
|
+
);
|
|
27598
|
+
if (dirStems.size === 1) byStem.set(stem, entry);
|
|
27599
|
+
}
|
|
27553
27600
|
}
|
|
27554
|
-
return { byKey, byBasename };
|
|
27601
|
+
return { byKey, byBasename, byStem };
|
|
27555
27602
|
}
|
|
27556
27603
|
function resolveFileToken(token, lexicon) {
|
|
27557
27604
|
const exact = lexicon.byKey.get(token);
|
|
@@ -27582,24 +27629,40 @@ function fileRolePhrase(relPath, level = 1) {
|
|
|
27582
27629
|
if (/\.(json|ya?ml|toml|env)$/i.test(relPath)) return "a config file";
|
|
27583
27630
|
return "a source file";
|
|
27584
27631
|
}
|
|
27585
|
-
function
|
|
27632
|
+
function generalizeFileRefs(text, fileLexicon, level = 1) {
|
|
27586
27633
|
let out2 = text;
|
|
27587
|
-
|
|
27588
|
-
|
|
27589
|
-
|
|
27590
|
-
|
|
27591
|
-
|
|
27592
|
-
|
|
27593
|
-
|
|
27594
|
-
|
|
27595
|
-
|
|
27596
|
-
|
|
27597
|
-
|
|
27598
|
-
|
|
27599
|
-
|
|
27600
|
-
|
|
27601
|
-
|
|
27634
|
+
const files = [];
|
|
27635
|
+
const seenFiles = /* @__PURE__ */ new Set();
|
|
27636
|
+
for (const m of out2.matchAll(FILE_TOKEN_RE)) {
|
|
27637
|
+
const tok = m[0];
|
|
27638
|
+
if (seenFiles.has(tok)) continue;
|
|
27639
|
+
seenFiles.add(tok);
|
|
27640
|
+
const entry = resolveFileToken(tok, fileLexicon);
|
|
27641
|
+
if (entry) files.push([tok, entry]);
|
|
27642
|
+
}
|
|
27643
|
+
files.sort((a, b) => b[0].length - a[0].length);
|
|
27644
|
+
for (const [tok, entry] of files) {
|
|
27645
|
+
const re = new RegExp(`(?<![\\w$/\\\\.-])${escapeRe4(tok)}(?![\\w$-])`, "g");
|
|
27646
|
+
out2 = out2.replace(re, fileRolePhrase(entry.relPath, level));
|
|
27647
|
+
}
|
|
27648
|
+
const stems = [];
|
|
27649
|
+
const seenStems = /* @__PURE__ */ new Set();
|
|
27650
|
+
for (const m of out2.matchAll(STEM_TOKEN_RE)) {
|
|
27651
|
+
const tok = m[0];
|
|
27652
|
+
if (seenStems.has(tok)) continue;
|
|
27653
|
+
seenStems.add(tok);
|
|
27654
|
+
const entry = fileLexicon.byStem.get(tok);
|
|
27655
|
+
if (entry) stems.push([tok, entry]);
|
|
27656
|
+
}
|
|
27657
|
+
stems.sort((a, b) => b[0].length - a[0].length);
|
|
27658
|
+
for (const [tok, entry] of stems) {
|
|
27659
|
+
const re = new RegExp(`(?<![\\w$/\\\\.-])${escapeRe4(tok)}(?![\\w$/\\\\.-])`, "g");
|
|
27660
|
+
out2 = out2.replace(re, fileRolePhrase(entry.relPath, level));
|
|
27602
27661
|
}
|
|
27662
|
+
return out2;
|
|
27663
|
+
}
|
|
27664
|
+
function generalizeSymbols(text, lexicon, level = 1, fileLexicon) {
|
|
27665
|
+
let out2 = fileLexicon ? generalizeFileRefs(text, fileLexicon, level) : text;
|
|
27603
27666
|
const present = [];
|
|
27604
27667
|
const seen = /* @__PURE__ */ new Set();
|
|
27605
27668
|
for (const m of out2.matchAll(TOKEN_RE3)) {
|
|
@@ -27618,7 +27681,7 @@ function generalizeSymbols(text, lexicon, level = 1, fileLexicon) {
|
|
|
27618
27681
|
}
|
|
27619
27682
|
return generalize(out2, { level }).text;
|
|
27620
27683
|
}
|
|
27621
|
-
var SYMBOL_LABELS2, KIND_PHRASE, RE_RESERVED2, escapeRe4, CONVENTION_FILENAMES, CONVENTION_BASENAME_MIN_FILES, FILE_TOKEN_RE, TOKEN_RE3;
|
|
27684
|
+
var SYMBOL_LABELS2, KIND_PHRASE, RE_RESERVED2, escapeRe4, CONVENTION_FILENAMES, CONVENTION_BASENAME_MIN_FILES, CONVENTION_STEMS, FILE_TOKEN_RE, STEM_TOKEN_RE, TOKEN_RE3;
|
|
27622
27685
|
var init_generalize_graph = __esm({
|
|
27623
27686
|
"src/generalize-graph.ts"() {
|
|
27624
27687
|
"use strict";
|
|
@@ -27667,7 +27730,27 @@ var init_generalize_graph = __esm({
|
|
|
27667
27730
|
"index.mjs"
|
|
27668
27731
|
]);
|
|
27669
27732
|
CONVENTION_BASENAME_MIN_FILES = 3;
|
|
27733
|
+
CONVENTION_STEMS = /* @__PURE__ */ new Set([
|
|
27734
|
+
"well-known",
|
|
27735
|
+
"read-only",
|
|
27736
|
+
"type-safe",
|
|
27737
|
+
"end-to-end",
|
|
27738
|
+
"fail-open",
|
|
27739
|
+
"fail-closed",
|
|
27740
|
+
"up-to-date",
|
|
27741
|
+
"server-side",
|
|
27742
|
+
"client-side",
|
|
27743
|
+
"cross-origin",
|
|
27744
|
+
"same-origin",
|
|
27745
|
+
"well-formed",
|
|
27746
|
+
"first-class",
|
|
27747
|
+
"in-memory",
|
|
27748
|
+
"single-page",
|
|
27749
|
+
"use-case",
|
|
27750
|
+
"out-of-band"
|
|
27751
|
+
]);
|
|
27670
27752
|
FILE_TOKEN_RE = /(?:[A-Za-z0-9_.-]+\/)*[A-Za-z0-9_-][A-Za-z0-9_.-]*\.[A-Za-z0-9]+/g;
|
|
27753
|
+
STEM_TOKEN_RE = /[A-Za-z0-9]+(?:[-_][A-Za-z0-9]+)+/g;
|
|
27671
27754
|
TOKEN_RE3 = /[A-Za-z_$][A-Za-z0-9_$]*(?:\.[A-Za-z_$][A-Za-z0-9_$]*)*/g;
|
|
27672
27755
|
}
|
|
27673
27756
|
});
|
|
@@ -54908,7 +54991,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
|
|
|
54908
54991
|
}
|
|
54909
54992
|
|
|
54910
54993
|
// src/engine.ts
|
|
54911
|
-
var DAEMON_VERSION = true ? "2.0.2-dev.
|
|
54994
|
+
var DAEMON_VERSION = true ? "2.0.2-dev.646" : "2.0.0-alpha.0";
|
|
54912
54995
|
var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
|
|
54913
54996
|
var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
|
|
54914
54997
|
var GIT_OP_MUTE_MS = 4e3;
|
|
@@ -57274,7 +57357,8 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
|
|
|
57274
57357
|
const fileLexicon = buildFileLexicon(store);
|
|
57275
57358
|
const shareable = (n) => {
|
|
57276
57359
|
const preserved = symbolIndex ? preservedSymbolsFor(n.description, symbolIndex) : [];
|
|
57277
|
-
const
|
|
57360
|
+
const fileScrubbed = generalizeFileRefs(n.description, fileLexicon, level);
|
|
57361
|
+
const shippedText = generalize(fileScrubbed, { level, project: projectIdentity }).text;
|
|
57278
57362
|
const internalSyms = internalSymbolsFor(shippedText, (t) => ownLexicon.has(t), symbolIndex);
|
|
57279
57363
|
const internalFiles = internalFilesFor(shippedText, fileLexicon);
|
|
57280
57364
|
const internal = [.../* @__PURE__ */ new Set([...internalFiles, ...internalSyms])].slice(
|