@inerrata-corporation/errata 2.0.17-dev.3369 → 2.0.17-dev.3416

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/pass-worker.mjs CHANGED
@@ -15430,6 +15430,308 @@ var init_project_symbol = __esm({
15430
15430
  });
15431
15431
 
15432
15432
  // ../../packages/shared/src/lockfile.ts
15433
+ function rankDirect(raw, ecosystem = "npm") {
15434
+ const byName = /* @__PURE__ */ new Map();
15435
+ for (const { name: name2, version: version2 } of raw) {
15436
+ const prev = byName.get(name2);
15437
+ if (prev) {
15438
+ prev.importers++;
15439
+ continue;
15440
+ }
15441
+ byName.set(name2, {
15442
+ purl: `pkg:${ecosystem}/${name2}@${version2}`,
15443
+ name: name2,
15444
+ version: version2,
15445
+ ecosystem,
15446
+ importers: 1
15447
+ });
15448
+ }
15449
+ return [...byName.values()].sort(
15450
+ (a, b) => b.importers - a.importers || a.name.localeCompare(b.name)
15451
+ );
15452
+ }
15453
+ function npmPurl(name2, version2) {
15454
+ return `pkg:npm/${name2}@${version2}`;
15455
+ }
15456
+ function component(name2, version2) {
15457
+ return { purl: npmPurl(name2, version2), name: name2, version: version2, ecosystem: "npm" };
15458
+ }
15459
+ function isNpmImporterPath(path) {
15460
+ return path === "" || !path.includes("node_modules/");
15461
+ }
15462
+ function parsePackageLockJson(jsonText) {
15463
+ let doc;
15464
+ try {
15465
+ doc = JSON.parse(jsonText);
15466
+ } catch {
15467
+ return { components: [], dependencies: [] };
15468
+ }
15469
+ const packages = doc.packages ?? {};
15470
+ const components = [];
15471
+ const hoisted = /* @__PURE__ */ new Map();
15472
+ const byPath = /* @__PURE__ */ new Map();
15473
+ for (const [path, meta3] of Object.entries(packages)) {
15474
+ if (path === "" || meta3.link === true) continue;
15475
+ const ix = path.lastIndexOf("node_modules/");
15476
+ if (ix === -1) continue;
15477
+ const name2 = path.slice(ix + "node_modules/".length);
15478
+ const version2 = typeof meta3.version === "string" ? meta3.version : "";
15479
+ if (!name2 || !version2) continue;
15480
+ components.push(component(name2, version2));
15481
+ byPath.set(path, { name: name2, version: version2 });
15482
+ const depth = path.split("node_modules/").length;
15483
+ const prev = hoisted.get(name2);
15484
+ if (!prev || depth < prev.depth) hoisted.set(name2, { version: version2, depth });
15485
+ }
15486
+ const dependencies = [];
15487
+ for (const [path, meta3] of Object.entries(packages)) {
15488
+ const self = byPath.get(path);
15489
+ if (!self) continue;
15490
+ const deps = meta3.dependencies;
15491
+ if (!deps || typeof deps !== "object") continue;
15492
+ const dependsOn = [];
15493
+ for (const depName of Object.keys(deps)) {
15494
+ const target = hoisted.get(depName);
15495
+ if (target) dependsOn.push(npmPurl(depName, target.version));
15496
+ }
15497
+ if (dependsOn.length > 0)
15498
+ dependencies.push({ ref: npmPurl(self.name, self.version), dependsOn });
15499
+ }
15500
+ const directRaw = [];
15501
+ for (const [path, meta3] of Object.entries(packages)) {
15502
+ if (!isNpmImporterPath(path)) continue;
15503
+ for (const section of [meta3.dependencies, meta3.devDependencies, meta3.optionalDependencies]) {
15504
+ if (!section || typeof section !== "object") continue;
15505
+ for (const name2 of Object.keys(section)) {
15506
+ const target = hoisted.get(name2);
15507
+ if (target) directRaw.push({ name: name2, version: target.version });
15508
+ }
15509
+ }
15510
+ }
15511
+ const direct = rankDirect(directRaw);
15512
+ return {
15513
+ components,
15514
+ dependencies: dedupeRefs(dependencies),
15515
+ ...direct.length > 0 ? { direct } : {}
15516
+ };
15517
+ }
15518
+ function splitPnpmKey(raw) {
15519
+ let k = raw.trim().replace(/^['"]|['"]$/g, "");
15520
+ if (k.startsWith("/")) k = k.slice(1);
15521
+ const paren = k.indexOf("(");
15522
+ if (paren !== -1) k = k.slice(0, paren);
15523
+ if (k.startsWith("link:") || k.startsWith("file:") || k.includes("://")) return null;
15524
+ const at = k.lastIndexOf("@");
15525
+ if (at <= 0) return null;
15526
+ const name2 = k.slice(0, at);
15527
+ const version2 = k.slice(at + 1);
15528
+ if (!name2 || !version2) return null;
15529
+ return { name: name2, version: version2 };
15530
+ }
15531
+ function parsePnpmImporters(lines) {
15532
+ const DEP_SECTIONS = /* @__PURE__ */ new Set(["dependencies:", "devDependencies:", "optionalDependencies:"]);
15533
+ const raw = [];
15534
+ let inImporters = false;
15535
+ let inDepSection = false;
15536
+ let depName = null;
15537
+ for (const line of lines) {
15538
+ if (!line.trim() || line.trimStart().startsWith("#")) continue;
15539
+ const indent = line.length - line.trimStart().length;
15540
+ if (indent === 0) {
15541
+ inImporters = line.trimEnd() === "importers:";
15542
+ inDepSection = false;
15543
+ depName = null;
15544
+ continue;
15545
+ }
15546
+ if (!inImporters) continue;
15547
+ if (indent === 2) {
15548
+ inDepSection = false;
15549
+ depName = null;
15550
+ continue;
15551
+ }
15552
+ if (indent === 4) {
15553
+ inDepSection = DEP_SECTIONS.has(line.trim());
15554
+ depName = null;
15555
+ continue;
15556
+ }
15557
+ if (!inDepSection) continue;
15558
+ if (indent === 6 && line.trimEnd().endsWith(":")) {
15559
+ depName = line.trim().slice(0, -1).replace(/^['"]|['"]$/g, "") || null;
15560
+ continue;
15561
+ }
15562
+ if (indent === 8 && depName) {
15563
+ const t = line.trim();
15564
+ if (!t.startsWith("version:")) continue;
15565
+ let version2 = t.slice("version:".length).trim().replace(/^['"]|['"]$/g, "");
15566
+ const paren = version2.indexOf("(");
15567
+ if (paren !== -1) version2 = version2.slice(0, paren);
15568
+ if (!version2 || version2.startsWith("link:") || version2.startsWith("file:") || version2.includes("://")) {
15569
+ depName = null;
15570
+ continue;
15571
+ }
15572
+ raw.push({ name: depName, version: version2 });
15573
+ depName = null;
15574
+ }
15575
+ }
15576
+ return rankDirect(raw);
15577
+ }
15578
+ function parsePnpmLock(text) {
15579
+ const lines = text.split(/\r?\n/);
15580
+ const components = [];
15581
+ const seen = /* @__PURE__ */ new Set();
15582
+ const dependencies = [];
15583
+ let section = null;
15584
+ let currentPkg = null;
15585
+ let inDepsBlock = false;
15586
+ let currentDeps = [];
15587
+ const flushDeps = () => {
15588
+ if (currentPkg && currentDeps.length > 0) {
15589
+ dependencies.push({
15590
+ ref: npmPurl(currentPkg.name, currentPkg.version),
15591
+ dependsOn: currentDeps.slice()
15592
+ });
15593
+ }
15594
+ currentDeps = [];
15595
+ };
15596
+ for (const line of lines) {
15597
+ if (!line.trim() || line.trimStart().startsWith("#")) continue;
15598
+ const indent = line.length - line.trimStart().length;
15599
+ if (indent === 0) {
15600
+ flushDeps();
15601
+ currentPkg = null;
15602
+ inDepsBlock = false;
15603
+ section = line === "packages:" ? "packages" : line === "snapshots:" ? "snapshots" : null;
15604
+ continue;
15605
+ }
15606
+ if (!section) continue;
15607
+ if (indent === 2 && line.trimEnd().endsWith(":")) {
15608
+ flushDeps();
15609
+ inDepsBlock = false;
15610
+ const key = line.trim().slice(0, -1);
15611
+ currentPkg = splitPnpmKey(key);
15612
+ if (currentPkg && section === "packages") {
15613
+ const purl = npmPurl(currentPkg.name, currentPkg.version);
15614
+ if (!seen.has(purl)) {
15615
+ seen.add(purl);
15616
+ components.push(component(currentPkg.name, currentPkg.version));
15617
+ }
15618
+ }
15619
+ continue;
15620
+ }
15621
+ if (!currentPkg) continue;
15622
+ if (indent === 4) {
15623
+ inDepsBlock = line.trim() === "dependencies:";
15624
+ continue;
15625
+ }
15626
+ if (inDepsBlock && indent === 6) {
15627
+ const t = line.trim();
15628
+ const at = t.indexOf(": ");
15629
+ if (at === -1) continue;
15630
+ const depName = t.slice(0, at).replace(/^['"]|['"]$/g, "");
15631
+ let depVersion = t.slice(at + 2).trim().replace(/^['"]|['"]$/g, "");
15632
+ const paren = depVersion.indexOf("(");
15633
+ if (paren !== -1) depVersion = depVersion.slice(0, paren);
15634
+ if (depName && depVersion && !depVersion.startsWith("link:"))
15635
+ currentDeps.push(npmPurl(depName, depVersion));
15636
+ }
15637
+ }
15638
+ flushDeps();
15639
+ const direct = parsePnpmImporters(lines);
15640
+ return {
15641
+ components,
15642
+ dependencies: dedupeRefs(dependencies),
15643
+ ...direct.length > 0 ? { direct } : {}
15644
+ };
15645
+ }
15646
+ function parseGemfileLock(text) {
15647
+ const lines = text.split(/\r?\n/);
15648
+ const components = [];
15649
+ const dependencies = [];
15650
+ const seen = /* @__PURE__ */ new Set();
15651
+ const registryVersions = /* @__PURE__ */ new Map();
15652
+ const nonRegistry = /* @__PURE__ */ new Set();
15653
+ const declared = [];
15654
+ let section = null;
15655
+ let inSpecs = false;
15656
+ let currentGem = null;
15657
+ const specLine = /^\s{4}([A-Za-z0-9_.-]+)\s*\(([^)]*)\)\s*$/;
15658
+ const nestedDep = /^\s{6}([A-Za-z0-9_.-]+)/;
15659
+ for (const line of lines) {
15660
+ if (!line.trim()) continue;
15661
+ if (!/^\s/.test(line)) {
15662
+ const header = line.trim();
15663
+ section = header === "GEM" ? "gem" : header === "PATH" || header === "GIT" || header === "PLUGIN SOURCE" ? "path-or-git" : header === "DEPENDENCIES" ? "dependencies" : null;
15664
+ inSpecs = false;
15665
+ currentGem = null;
15666
+ continue;
15667
+ }
15668
+ if (section === "dependencies") {
15669
+ const d = /^\s{2}([A-Za-z0-9_.-]+)(!?)/.exec(line);
15670
+ if (d?.[1] && d[2] !== "!") declared.push(d[1]);
15671
+ continue;
15672
+ }
15673
+ if (!section) continue;
15674
+ if (/^\s{2}specs:\s*$/.test(line)) {
15675
+ inSpecs = true;
15676
+ currentGem = null;
15677
+ continue;
15678
+ }
15679
+ if (/^\s{2}\S/.test(line)) {
15680
+ inSpecs = false;
15681
+ currentGem = null;
15682
+ continue;
15683
+ }
15684
+ if (!inSpecs) continue;
15685
+ const spec = specLine.exec(line);
15686
+ if (spec) {
15687
+ const name2 = spec[1];
15688
+ const version2 = (spec[2] ?? "").trim();
15689
+ if (section === "path-or-git") {
15690
+ nonRegistry.add(name2);
15691
+ currentGem = null;
15692
+ continue;
15693
+ }
15694
+ if (!version2) continue;
15695
+ currentGem = { name: name2, version: version2 };
15696
+ registryVersions.set(name2, version2);
15697
+ const purl = `pkg:gem/${name2}@${version2}`;
15698
+ if (!seen.has(purl)) {
15699
+ seen.add(purl);
15700
+ components.push({ purl, name: name2, version: version2, ecosystem: "gem" });
15701
+ }
15702
+ continue;
15703
+ }
15704
+ const nested = nestedDep.exec(line);
15705
+ if (nested?.[1] && currentGem) {
15706
+ dependencies.push({
15707
+ ref: `pkg:gem/${currentGem.name}@${currentGem.version}`,
15708
+ dependsOn: [nested[1]]
15709
+ });
15710
+ }
15711
+ }
15712
+ const resolved = dependencies.map((d) => ({
15713
+ ref: d.ref,
15714
+ dependsOn: d.dependsOn.filter((n) => !nonRegistry.has(n) && registryVersions.has(n)).map((n) => `pkg:gem/${n}@${registryVersions.get(n)}`)
15715
+ })).filter((d) => d.dependsOn.length > 0);
15716
+ const direct = rankDirect(
15717
+ declared.filter((n) => !nonRegistry.has(n) && registryVersions.has(n)).map((n) => ({ name: n, version: registryVersions.get(n) })),
15718
+ "gem"
15719
+ );
15720
+ return {
15721
+ components,
15722
+ dependencies: dedupeRefs(resolved),
15723
+ ...direct.length > 0 ? { direct } : {}
15724
+ };
15725
+ }
15726
+ function dedupeRefs(deps) {
15727
+ const byRef = /* @__PURE__ */ new Map();
15728
+ for (const d of deps) {
15729
+ const set2 = byRef.get(d.ref) ?? /* @__PURE__ */ new Set();
15730
+ for (const t of d.dependsOn) set2.add(t);
15731
+ byRef.set(d.ref, set2);
15732
+ }
15733
+ return [...byRef.entries()].map(([ref, set2]) => ({ ref, dependsOn: [...set2] }));
15734
+ }
15433
15735
  var init_lockfile = __esm({
15434
15736
  "../../packages/shared/src/lockfile.ts"() {
15435
15737
  "use strict";
@@ -15437,10 +15739,307 @@ var init_lockfile = __esm({
15437
15739
  });
15438
15740
 
15439
15741
  // ../../packages/shared/src/manifests.ts
15742
+ function isManifestPath(p) {
15743
+ return MANIFEST_PATH_RE.test(p);
15744
+ }
15745
+ function basename(p) {
15746
+ const ix = p.lastIndexOf("/");
15747
+ return ix === -1 ? p : p.slice(ix + 1);
15748
+ }
15749
+ function parseCsproj(path, text) {
15750
+ const deps = [];
15751
+ for (const m of text.matchAll(/<PackageReference\s+Include="([^"]+)"(?:\s+Version="([^"]+)")?/g)) {
15752
+ deps.push({ ecosystem: "nuget", name: m[1] ?? "", version: m[2] ?? null, kind: "package", manifest: path });
15753
+ }
15754
+ for (const m of text.matchAll(/<Project\s+Sdk="([^"/]+)(?:\/([^"]+))?"/g)) {
15755
+ const sdk = m[1] ?? "";
15756
+ if (sdk.toLowerCase() !== "microsoft.net.sdk") {
15757
+ deps.push({ ecosystem: "nuget", name: sdk, version: m[2] ?? null, kind: "sdk", manifest: path });
15758
+ }
15759
+ }
15760
+ for (const m of text.matchAll(/<TargetFramework>([^<]+)<\/TargetFramework>/g)) {
15761
+ const mm = /^net(\d+\.\d+)/.exec((m[1] ?? "").trim());
15762
+ if (mm) deps.push({ ecosystem: "dotnet", name: "dotnet", version: mm[1] ?? null, kind: "runtime", manifest: path });
15763
+ }
15764
+ return deps;
15765
+ }
15766
+ function parseGodot(path, text) {
15767
+ const m = /config\/features=PackedStringArray\(([^)]*)\)/.exec(text);
15768
+ if (!m) return [];
15769
+ const feats = (m[1] ?? "").split(",").map((f) => f.trim().replace(/^"|"$/g, "")).filter((f) => f.length > 0);
15770
+ const version2 = feats.find((f) => /^\d+\.\d+/.test(f)) ?? null;
15771
+ return [{ ecosystem: "godot", name: "godot", version: version2, kind: "engine", manifest: path }];
15772
+ }
15773
+ function parsePackageJson(path, text) {
15774
+ let obj;
15775
+ try {
15776
+ obj = JSON.parse(text);
15777
+ } catch {
15778
+ return [];
15779
+ }
15780
+ if (!obj || typeof obj !== "object") return [];
15781
+ const deps = [];
15782
+ for (const key of PACKAGE_JSON_SECTIONS) {
15783
+ const section = obj[key];
15784
+ if (!section || typeof section !== "object") continue;
15785
+ for (const [name2, ver] of Object.entries(section)) {
15786
+ const version2 = ver ? String(ver) : null;
15787
+ deps.push({ ecosystem: "npm", name: name2, version: version2, kind: "package", manifest: path });
15788
+ }
15789
+ }
15790
+ return deps;
15791
+ }
15792
+ function isPep508DirectRef(spec) {
15793
+ return /^[A-Za-z0-9][A-Za-z0-9._-]*(?:\[[^\]]*\])?\s*@\s*\S/.test(spec.trim());
15794
+ }
15795
+ function parseRequirements(path, text) {
15796
+ const deps = [];
15797
+ for (const raw of text.split(/\r?\n/)) {
15798
+ const line = (raw.split("#", 1)[0] ?? "").trim();
15799
+ if (!line || line.startsWith("-") || line.startsWith("git+") || line.startsWith("http")) continue;
15800
+ const m = /^([A-Za-z0-9][A-Za-z0-9._-]*)(?:\[[^\]]*\])?\s*(?:([=<>!~]+)\s*([^\s;]+))?/.exec(line);
15801
+ if (m) {
15802
+ deps.push({
15803
+ ecosystem: "pypi",
15804
+ name: m[1] ?? "",
15805
+ version: m[2] ? m[3] ?? null : null,
15806
+ kind: "package",
15807
+ manifest: path,
15808
+ ...isPep508DirectRef(line) ? { directRef: true } : {}
15809
+ });
15810
+ }
15811
+ }
15812
+ return deps;
15813
+ }
15814
+ function parsePyproject(path, text) {
15815
+ const deps = [];
15816
+ const m = /^\s*dependencies\s*=\s*\[([\s\S]*?)\]/m.exec(text);
15817
+ if (!m) return deps;
15818
+ for (const s of (m[1] ?? "").matchAll(/"([^"]+)"|'([^']+)'/g)) {
15819
+ const spec = s[1] || s[2] || "";
15820
+ const mm = /^([A-Za-z0-9][A-Za-z0-9._-]*)/.exec(spec);
15821
+ if (mm) {
15822
+ deps.push({
15823
+ ecosystem: "pypi",
15824
+ name: mm[1] ?? "",
15825
+ version: null,
15826
+ kind: "package",
15827
+ manifest: path,
15828
+ ...isPep508DirectRef(spec) ? { directRef: true } : {}
15829
+ });
15830
+ }
15831
+ }
15832
+ return deps;
15833
+ }
15834
+ function parseDocker(path, text) {
15835
+ const deps = [];
15836
+ for (const m of text.matchAll(/^\s*(?:image:\s*|FROM\s+(?:--platform=\S+\s+)?)["']?([^\s"']+)/gm)) {
15837
+ const ref = m[1] ?? "";
15838
+ if (ref.toLowerCase() === "scratch" || ref.includes("$") || LOCAL_IMAGE_RE.test(ref)) continue;
15839
+ const at = ref.indexOf("@");
15840
+ const undigested = at === -1 ? ref : ref.slice(0, at);
15841
+ const colon = undigested.indexOf(":");
15842
+ const name2 = colon === -1 ? undigested : undigested.slice(0, colon);
15843
+ const tag = colon === -1 ? "" : undigested.slice(colon + 1);
15844
+ deps.push({ ecosystem: "docker", name: name2, version: tag || null, kind: "image", manifest: path });
15845
+ }
15846
+ return deps;
15847
+ }
15848
+ function parseGoMod(path, text) {
15849
+ const deps = [];
15850
+ for (const m of text.matchAll(/^\s*(?:require\s+)?([a-z0-9.\-]+\.[a-z]+\/[^\s]+)\s+(v[^\s]+)/gm)) {
15851
+ const end = (m.index ?? 0) + m[0].length;
15852
+ if (text.slice(end, end + 20).includes("// indirect")) continue;
15853
+ deps.push({ ecosystem: "golang", name: m[1] ?? "", version: m[2] ?? null, kind: "package", manifest: path });
15854
+ }
15855
+ return deps;
15856
+ }
15857
+ function parseCargo(path, text) {
15858
+ const deps = [];
15859
+ const sec = /^\[dependencies\]([\s\S]*?)(?=^\[|(?![\s\S]))/m.exec(text);
15860
+ if (!sec) return deps;
15861
+ for (const m of (sec[1] ?? "").matchAll(/^\s*([A-Za-z0-9_-]+)\s*=\s*(?:"([^"]+)"|\{[^}]*version\s*=\s*"([^"]+)")/gm)) {
15862
+ deps.push({ ecosystem: "cargo", name: m[1] ?? "", version: m[2] ?? m[3] ?? null, kind: "package", manifest: path });
15863
+ }
15864
+ return deps;
15865
+ }
15866
+ function mavenName(groupId, artifactId) {
15867
+ return `${groupId.trim()}:${artifactId.trim()}`;
15868
+ }
15869
+ function parsePom(path, text) {
15870
+ const deps = [];
15871
+ const coord = (block) => {
15872
+ const g = /<groupId>([^<]+)<\/groupId>/.exec(block)?.[1];
15873
+ const a = /<artifactId>([^<]+)<\/artifactId>/.exec(block)?.[1];
15874
+ if (!g || !a) return null;
15875
+ return { g, a, v: /<version>([^<]+)<\/version>/.exec(block)?.[1]?.trim() ?? null };
15876
+ };
15877
+ for (const m of text.matchAll(/<dependency>([\s\S]*?)<\/dependency>/g)) {
15878
+ const c = coord(m[1] ?? "");
15879
+ if (c) deps.push({ ecosystem: "maven", name: mavenName(c.g, c.a), version: c.v, kind: "package", manifest: path });
15880
+ }
15881
+ for (const m of text.matchAll(/<parent>([\s\S]*?)<\/parent>/g)) {
15882
+ const c = coord(m[1] ?? "");
15883
+ if (c) deps.push({ ecosystem: "maven", name: mavenName(c.g, c.a), version: c.v, kind: "sdk", manifest: path });
15884
+ }
15885
+ return deps;
15886
+ }
15887
+ function parseGradle(path, text) {
15888
+ const deps = [];
15889
+ const re = new RegExp(`\\b(?:${GRADLE_CONFIGS})\\s*(?:\\(\\s*)?["']([^"']+)["']`, "g");
15890
+ for (const m of text.matchAll(re)) {
15891
+ const parts2 = (m[1] ?? "").split(":");
15892
+ const [group, artifact, version2] = parts2;
15893
+ if (!group || !artifact || parts2.length < 2) continue;
15894
+ deps.push({
15895
+ ecosystem: "maven",
15896
+ name: mavenName(group, artifact),
15897
+ version: version2?.trim() || null,
15898
+ kind: "package",
15899
+ manifest: path
15900
+ });
15901
+ }
15902
+ return deps;
15903
+ }
15904
+ function parseVersionCatalog(path, text) {
15905
+ const section = /^\s*\[libraries\]([\s\S]*?)(?=^\s*\[|(?![\s\S]))/m.exec(text);
15906
+ if (!section) return [];
15907
+ const deps = [];
15908
+ for (const line of (section[1] ?? "").split(/\r?\n/)) {
15909
+ if (!line.trim() || line.trimStart().startsWith("#")) continue;
15910
+ const module2 = /module\s*=\s*["']([^"']+)["']/.exec(line)?.[1];
15911
+ const version2 = /version(?:\.ref)?\s*=\s*["']([^"']+)["']/.exec(line)?.[1] ?? null;
15912
+ if (module2) {
15913
+ const [group2, artifact2] = module2.split(":");
15914
+ if (group2 && artifact2) {
15915
+ deps.push({ ecosystem: "maven", name: mavenName(group2, artifact2), version: version2, kind: "package", manifest: path });
15916
+ }
15917
+ continue;
15918
+ }
15919
+ const group = /\bgroup\s*=\s*["']([^"']+)["']/.exec(line)?.[1];
15920
+ const artifact = /\bname\s*=\s*["']([^"']+)["']/.exec(line)?.[1];
15921
+ if (group && artifact) {
15922
+ deps.push({ ecosystem: "maven", name: mavenName(group, artifact), version: version2, kind: "package", manifest: path });
15923
+ }
15924
+ }
15925
+ return deps;
15926
+ }
15927
+ function parseGemfile(path, text) {
15928
+ const deps = [];
15929
+ for (const raw of text.split(/\r?\n/)) {
15930
+ const line = (raw.split("#", 1)[0] ?? "").trim();
15931
+ const m = /^gem\s+["']([^"']+)["']\s*(?:,\s*["']([^"']+)["'])?/.exec(line);
15932
+ if (!m?.[1]) continue;
15933
+ deps.push({ ecosystem: "gem", name: m[1], version: m[2] ?? null, kind: "package", manifest: path });
15934
+ }
15935
+ return deps;
15936
+ }
15937
+ function parseGemspec(path, text) {
15938
+ const deps = [];
15939
+ for (const m of text.matchAll(
15940
+ /\.add_(?:runtime_|development_)?dependency\s*\(?\s*["']([^"']+)["']\s*(?:,\s*["']([^"']+)["'])?/g
15941
+ )) {
15942
+ if (m[1]) deps.push({ ecosystem: "gem", name: m[1], version: m[2] ?? null, kind: "package", manifest: path });
15943
+ }
15944
+ return deps;
15945
+ }
15946
+ function tomlTable(text, header) {
15947
+ const escaped = header.replace(/[.[\]]/g, "\\$&");
15948
+ return new RegExp(`^\\s*\\[${escaped}\\]([\\s\\S]*?)(?=^\\s*\\[|(?![\\s\\S]))`, "m").exec(text)?.[1] ?? null;
15949
+ }
15950
+ function tomlName(table) {
15951
+ return table && /^\s*name\s*=\s*["']([^"']+)["']/m.exec(table)?.[1]?.trim() || null;
15952
+ }
15953
+ function pomSelf(text) {
15954
+ const parentGroup = /<groupId>([^<]+)<\/groupId>/.exec(/<parent>([\s\S]*?)<\/parent>/.exec(text)?.[1] ?? "")?.[1];
15955
+ const own = text.replace(POM_FOREIGN_BLOCKS, "");
15956
+ const group = (/<groupId>([^<]+)<\/groupId>/.exec(own)?.[1] ?? parentGroup)?.trim();
15957
+ const artifact = /<artifactId>([^<]+)<\/artifactId>/.exec(own)?.[1]?.trim();
15958
+ if (!group) return [];
15959
+ const self = [{ ecosystem: "maven", kind: "namespace", value: group }];
15960
+ if (artifact) self.push({ ecosystem: "maven", kind: "name", value: mavenName(group, artifact) });
15961
+ return self;
15962
+ }
15963
+ function parseManifestSelf(path, text) {
15964
+ const file2 = basename(path);
15965
+ if (file2 === "package.json") {
15966
+ let obj;
15967
+ try {
15968
+ obj = JSON.parse(text);
15969
+ } catch {
15970
+ return [];
15971
+ }
15972
+ const name2 = obj && typeof obj === "object" ? obj["name"] : null;
15973
+ if (typeof name2 !== "string" || !name2.trim()) return [];
15974
+ const self = [{ ecosystem: "npm", kind: "name", value: name2.trim() }];
15975
+ const scope = /^(@[^/]+)\//.exec(name2.trim())?.[1];
15976
+ if (scope) self.push({ ecosystem: "npm", kind: "namespace", value: scope });
15977
+ return self;
15978
+ }
15979
+ if (file2 === "pom.xml") return pomSelf(text);
15980
+ if (file2 === "build.gradle" || file2 === "build.gradle.kts") {
15981
+ const group = /^\s*group\s*(?:=\s*)?["']([^"']+)["']/m.exec(text)?.[1]?.trim();
15982
+ return group ? [{ ecosystem: "maven", kind: "namespace", value: group }] : [];
15983
+ }
15984
+ if (file2 === "Cargo.toml") {
15985
+ const name2 = tomlName(tomlTable(text, "package"));
15986
+ return name2 ? [{ ecosystem: "cargo", kind: "name", value: name2 }] : [];
15987
+ }
15988
+ if (file2 === "pyproject.toml") {
15989
+ const name2 = tomlName(tomlTable(text, "project")) ?? tomlName(tomlTable(text, "tool.poetry"));
15990
+ return name2 ? [{ ecosystem: "pypi", kind: "name", value: name2 }] : [];
15991
+ }
15992
+ if (file2 === "go.mod") {
15993
+ const module2 = /^\s*module\s+(\S+)/m.exec(text)?.[1];
15994
+ return module2 ? [{ ecosystem: "golang", kind: "namespace", value: module2 }] : [];
15995
+ }
15996
+ if (file2.endsWith(".gemspec")) {
15997
+ const name2 = /\.name\s*=\s*["']([^"']+)["']/.exec(text)?.[1]?.trim();
15998
+ return name2 ? [{ ecosystem: "gem", kind: "name", value: name2 }] : [];
15999
+ }
16000
+ if (file2.endsWith(".csproj") || file2.endsWith(".fsproj")) {
16001
+ const id = /<PackageId>([^<]+)<\/PackageId>/.exec(text)?.[1]?.trim() ?? file2.replace(/\.(cs|fs)proj$/, "");
16002
+ return id ? [{ ecosystem: "nuget", kind: "name", value: id }] : [];
16003
+ }
16004
+ return [];
16005
+ }
16006
+ function parseManifest(path, text) {
16007
+ const name2 = basename(path);
16008
+ if (name2.endsWith(".csproj") || name2.endsWith(".fsproj")) return parseCsproj(path, text);
16009
+ if (name2 === "project.godot") return parseGodot(path, text);
16010
+ if (name2 === "package.json") return parsePackageJson(path, text);
16011
+ if (name2.startsWith("requirements") && name2.endsWith(".txt")) return parseRequirements(path, text);
16012
+ if (name2 === "pyproject.toml") return parsePyproject(path, text);
16013
+ if (name2.startsWith("docker-compose") || name2.startsWith("compose") || name2.startsWith("Dockerfile")) {
16014
+ return parseDocker(path, text);
16015
+ }
16016
+ if (name2 === "go.mod") return parseGoMod(path, text);
16017
+ if (name2 === "libs.versions.toml") return parseVersionCatalog(path, text);
16018
+ if (name2 === "Cargo.toml") return parseCargo(path, text);
16019
+ if (name2 === "pom.xml") return parsePom(path, text);
16020
+ if (name2 === "build.gradle" || name2 === "build.gradle.kts") return parseGradle(path, text);
16021
+ if (name2 === "Gemfile") return parseGemfile(path, text);
16022
+ if (name2.endsWith(".gemspec")) return parseGemspec(path, text);
16023
+ return [];
16024
+ }
16025
+ function buildSpine(sha2, manifestPaths2, readText) {
16026
+ const manifests = {};
16027
+ for (const p of manifestPaths2) {
16028
+ const deps = parseManifest(p, readText(p));
16029
+ if (deps.length > 0) manifests[p] = deps;
16030
+ }
16031
+ return { sha: sha2, manifests };
16032
+ }
16033
+ var MANIFEST_PATH_RE, LOCAL_IMAGE_RE, PACKAGE_JSON_SECTIONS, GRADLE_CONFIGS, POM_FOREIGN_BLOCKS;
15440
16034
  var init_manifests = __esm({
15441
16035
  "../../packages/shared/src/manifests.ts"() {
15442
16036
  "use strict";
15443
16037
  init_identity();
16038
+ MANIFEST_PATH_RE = /(^|\/)(?:[^/]+\.csproj|[^/]+\.fsproj|project\.godot|package\.json|requirements[^/]*\.txt|pyproject\.toml|docker-compose[^/]*\.ya?ml|compose[^/]*\.ya?ml|Dockerfile(?:\.[^/]+)?|go\.mod|Cargo\.toml|pom\.xml|build\.gradle(?:\.kts)?|libs\.versions\.toml|Gemfile|[^/]+\.gemspec)$/;
16039
+ LOCAL_IMAGE_RE = /^(openbane|local)[/-]|:local$/;
16040
+ PACKAGE_JSON_SECTIONS = ["dependencies", "devDependencies", "peerDependencies", "optionalDependencies"];
16041
+ GRADLE_CONFIGS = "implementation|api|compileOnly|compileOnlyApi|runtimeOnly|testImplementation|testCompileOnly|testRuntimeOnly|annotationProcessor|kapt|ksp|classpath|developmentOnly";
16042
+ POM_FOREIGN_BLOCKS = /<(parent|dependencies|dependencyManagement|build|profiles|reporting|distributionManagement|modules)>[\s\S]*?<\/\1>/g;
15444
16043
  }
15445
16044
  });
15446
16045
 
@@ -15620,6 +16219,10 @@ var init_review = __esm({
15620
16219
  });
15621
16220
 
15622
16221
  // ../../packages/local-shared/src/anchorable.ts
16222
+ function isAnchorableCodePath(relPath) {
16223
+ const p = relPath.toLowerCase();
16224
+ return BY_LENGTH.some((ext) => p.endsWith(ext));
16225
+ }
15623
16226
  function anchorableExtensionAlternation() {
15624
16227
  return BY_LENGTH.map((e) => e.slice(1).replace(/[+.]/g, (c) => `\\${c}`)).join("|");
15625
16228
  }
@@ -18835,7 +19438,7 @@ async function Module2(moduleArg = {}) {
18835
19438
  _fd_close.sig = "ii";
18836
19439
  var INT53_MAX = 9007199254740992;
18837
19440
  var INT53_MIN = -9007199254740992;
18838
- var bigintToI53Checked = /* @__PURE__ */ __name((num) => num < INT53_MIN || num > INT53_MAX ? NaN : Number(num), "bigintToI53Checked");
19441
+ var bigintToI53Checked = /* @__PURE__ */ __name((num2) => num2 < INT53_MIN || num2 > INT53_MAX ? NaN : Number(num2), "bigintToI53Checked");
18839
19442
  function _fd_seek(fd, offset, whence, newOffset) {
18840
19443
  offset = bigintToI53Checked(offset);
18841
19444
  return 70;
@@ -18853,7 +19456,7 @@ async function Module2(moduleArg = {}) {
18853
19456
  }
18854
19457
  }, "printChar");
18855
19458
  var _fd_write = /* @__PURE__ */ __name((fd, iov, iovcnt, pnum) => {
18856
- var num = 0;
19459
+ var num2 = 0;
18857
19460
  for (var i2 = 0; i2 < iovcnt; i2++) {
18858
19461
  var ptr = LE_HEAP_LOAD_U32((iov >> 2) * 4);
18859
19462
  var len = LE_HEAP_LOAD_U32((iov + 4 >> 2) * 4);
@@ -18861,9 +19464,9 @@ async function Module2(moduleArg = {}) {
18861
19464
  for (var j = 0; j < len; j++) {
18862
19465
  printChar(fd, HEAPU8[ptr + j]);
18863
19466
  }
18864
- num += len;
19467
+ num2 += len;
18865
19468
  }
18866
- LE_HEAP_STORE_U32((pnum >> 2) * 4, num);
19469
+ LE_HEAP_STORE_U32((pnum >> 2) * 4, num2);
18867
19470
  return 0;
18868
19471
  }, "_fd_write");
18869
19472
  _fd_write.sig = "iippp";
@@ -24627,12 +25230,13 @@ function installHistoryCacheFloor(db) {
24627
25230
  }
24628
25231
 
24629
25232
  // ../../packages/local-graph/src/session-evidence.ts
25233
+ var arrays = /* @__PURE__ */ new Set(["sources", "recurrenceSources", "contributors", "inferredContributors", "citeSessions"]);
25234
+ var scalars = /* @__PURE__ */ new Set(["discriminatorSource", "originSession", "sessionId", "sourceSession"]);
25235
+ var SESSION_EVIDENCE_FIELDS = [...arrays, ...scalars, "citeAnchorHints"];
24630
25236
  function repairSessionEvidence(input, aliases = /* @__PURE__ */ new Map()) {
24631
25237
  const mapping = new Map(aliases);
24632
25238
  const uuid3 = "[a-f0-9]{8}(?:-[a-f0-9]{4}){3}-[a-f0-9]{12}";
24633
25239
  const codex = new RegExp(`^codex:(?:rollout-.*?)?(${uuid3})$`, "i");
24634
- const arrays = /* @__PURE__ */ new Set(["sources", "recurrenceSources", "contributors", "inferredContributors", "citeSessions"]);
24635
- const scalars = /* @__PURE__ */ new Set(["discriminatorSource", "originSession", "sessionId", "sourceSession"]);
24636
25240
  const discover = (value, key = "") => {
24637
25241
  if (typeof value === "string" && (arrays.has(key) || scalars.has(key) || key === "citeAnchorHints")) {
24638
25242
  const match = value.match(codex);
@@ -24730,6 +25334,7 @@ function localEdgeViolation(fromLabel, type, toLabel) {
24730
25334
  return verdict.ok ? null : verdict.reason ?? "edge rule violation";
24731
25335
  }
24732
25336
  var SCHEMA_VERSION = 6;
25337
+ var SESSION_EVIDENCE_PREDICATE = SESSION_EVIDENCE_FIELDS.map((field) => `instr(attrs_json, '${JSON.stringify(field)}') > 0`).join(" OR ");
24733
25338
  var SCHEMA_SQL = `
24734
25339
  CREATE TABLE IF NOT EXISTS schema_version (
24735
25340
  version INTEGER PRIMARY KEY
@@ -24822,6 +25427,10 @@ CREATE UNIQUE INDEX IF NOT EXISTS edges_triple ON edges(from_id, type, to_id);
24822
25427
  `;
24823
25428
  var TEMPORAL_INDEX_SQL = `
24824
25429
  CREATE INDEX IF NOT EXISTS nodes_live ON nodes(label, valid_to);
25430
+ CREATE INDEX IF NOT EXISTS nodes_live_count ON nodes(valid_to);
25431
+ CREATE INDEX IF NOT EXISTS nodes_live_recent ON nodes(label, last_updated_at DESC) WHERE valid_to IS NULL;
25432
+ CREATE INDEX IF NOT EXISTS nodes_session_evidence ON nodes(id) WHERE ${SESSION_EVIDENCE_PREDICATE};
25433
+ CREATE INDEX IF NOT EXISTS edges_session_evidence ON edges(id) WHERE ${SESSION_EVIDENCE_PREDICATE};
24825
25434
  -- Covering + partial index for labelFingerprint over the instance labels: the
24826
25435
  -- live-push probe runs it per workspace on a timer, and each hit used to read
24827
25436
  -- its table row. Partial, so it maintains a few thousand rows instead of adding
@@ -25191,12 +25800,13 @@ var SqliteGraphStore = class {
25191
25800
  });
25192
25801
  }
25193
25802
  repairSessionAliases(canonical, aliases = []) {
25803
+ if (canonical && aliases.length === 0) return 0;
25194
25804
  const mapping = new Map(aliases.map((alias) => [alias, canonical]));
25195
25805
  let changed = 0;
25196
25806
  for (const table of ["nodes", "edges"]) {
25197
25807
  const predicates = canonical ? aliases.map(() => "instr(attrs_json, ?) > 0") : ["instr(attrs_json, 'codex:') > 0", "instr(attrs_json, 'discriminatorSource') > 0"];
25198
25808
  if (!predicates.length) continue;
25199
- const rows = this.db.prepare(`SELECT id, attrs_json FROM ${table} WHERE ${predicates.join(" OR ")}`).all(...canonical ? aliases : []);
25809
+ const rows = this.db.prepare(`SELECT id, attrs_json FROM ${table} WHERE (${SESSION_EVIDENCE_PREDICATE}) AND (${predicates.join(" OR ")})`).all(...canonical ? aliases.map((alias) => JSON.stringify(alias)) : []);
25200
25810
  const update = this.db.prepare(`UPDATE ${table} SET attrs_json = ?${table === "edges" ? ", type = CASE WHEN type = 'CONFIRMS' AND json_extract(?, '$.provisional') = 1 THEN 'INDICATES' ELSE type END" : ""} WHERE id = ?`);
25201
25811
  for (const row of rows) {
25202
25812
  const attrs = JSON.stringify(repairSessionEvidence(JSON.parse(row.attrs_json), mapping));
@@ -25422,6 +26032,25 @@ var SqliteGraphStore = class {
25422
26032
  const rows = this.db.prepare("SELECT id FROM nodes WHERE label = ? AND valid_to IS NULL ORDER BY last_updated_at DESC LIMIT ?").all(label, Math.max(0, limit));
25423
26033
  return rows.map((r) => r.id);
25424
26034
  }
26035
+ recentOpenProblemCandidates(opts) {
26036
+ if (!Number.isSafeInteger(opts.limit) || opts.limit < 0) {
26037
+ throw new RangeError("candidate limit must be a non-negative safe integer");
26038
+ }
26039
+ return this.db.prepare(`SELECT id, description FROM nodes
26040
+ WHERE label = 'Problem' AND valid_to IS NULL
26041
+ AND json_extract(attrs_json, '$.resolvedAt') IS NULL
26042
+ AND json_type(attrs_json, '$.mergedInto') IS NULL
26043
+ AND (? IS NULL OR id != ?)
26044
+ AND (json_type(attrs_json, '$.workspaceId') IS NULL OR json_extract(attrs_json, '$.workspaceId') = ?)
26045
+ AND COALESCE(json_extract(attrs_json, '$.kind') = 'constraint', 0) = ?
26046
+ ORDER BY last_updated_at DESC, rowid ASC LIMIT ?`).all(
26047
+ opts.excludeId ?? null,
26048
+ opts.excludeId ?? null,
26049
+ opts.workspaceId,
26050
+ opts.constraint ? 1 : 0,
26051
+ opts.limit
26052
+ );
26053
+ }
25425
26054
  hasLiveNodes() {
25426
26055
  const r = this.db.prepare("SELECT EXISTS(SELECT 1 FROM nodes WHERE valid_to IS NULL) AS e").get();
25427
26056
  return r.e === 1;
@@ -26359,6 +26988,14 @@ function isConstraintProblem(node) {
26359
26988
  return node.attrs["kind"] === "constraint";
26360
26989
  }
26361
26990
  var RECURRENCE_DEBOUNCE_MS = 60 * 60 * 1e3;
26991
+ function resolveFileNode(store2, path, workspaceId) {
26992
+ const want = path.trim().replace(/^\.?\//, "");
26993
+ for (const n of store2.findNodesByLabel("File")) {
26994
+ if (n.attrs["workspaceId"] && n.attrs["workspaceId"] !== workspaceId) continue;
26995
+ if (n.attrs["relPath"] === want || n.description === want) return n;
26996
+ }
26997
+ return null;
26998
+ }
26362
26999
  var CITABLE_PRIOR_LABELS = /* @__PURE__ */ new Set([
26363
27000
  "Solution",
26364
27001
  "RootCause",
@@ -26428,6 +27065,127 @@ function priorsForFile(store2, relPath) {
26428
27065
  solutionsByProblem
26429
27066
  };
26430
27067
  }
27068
+ function anchorProblemToWorkingFile(store2, problemId, relPath, workspaceId, ts, provenance = "edited", opts = {}) {
27069
+ const p = store2.getNode(problemId);
27070
+ if (!p || p.label !== "Problem" && p.label !== "Vulnerability") return false;
27071
+ if (p.label === "Vulnerability" && provenance !== "witnessed") return false;
27072
+ if (!isAnchorableCodePath(relPath)) return false;
27073
+ const file2 = resolveFileNode(store2, relPath, workspaceId);
27074
+ if (!file2) return false;
27075
+ const already = new Set(store2.outEdges(problemId, ["ANCHORED_AT"]).map((e) => e.to));
27076
+ const confidence = provenance === "witnessed" ? 0.4 : 0.3;
27077
+ if (!already.has(file2.id)) {
27078
+ store2.mergeEdge({
27079
+ id: `edge_${digest({ from: problemId, type: "ANCHORED_AT", to: file2.id })}`.slice(0, 24),
27080
+ from: problemId,
27081
+ to: file2.id,
27082
+ type: "ANCHORED_AT",
27083
+ confidence,
27084
+ extractionSource: "agent-observed",
27085
+ createdAt: ts,
27086
+ lastSeenAt: ts,
27087
+ navSuccesses: 0,
27088
+ navFailures: 0,
27089
+ attrs: { provisional: true, captureTime: true, anchorProvenance: provenance }
27090
+ });
27091
+ }
27092
+ if (opts.line !== void 0 && opts.fileText !== void 0) {
27093
+ const sym = resolveEnclosingSymbol(store2, file2.id, opts.line, opts.fileText);
27094
+ if (sym && !already.has(sym.id)) {
27095
+ store2.mergeEdge({
27096
+ id: `edge_${digest({ from: problemId, type: "ANCHORED_AT", to: sym.id })}`.slice(0, 24),
27097
+ from: problemId,
27098
+ to: sym.id,
27099
+ type: "ANCHORED_AT",
27100
+ confidence,
27101
+ extractionSource: "agent-observed",
27102
+ createdAt: ts,
27103
+ lastSeenAt: ts,
27104
+ navSuccesses: 0,
27105
+ navFailures: 0,
27106
+ attrs: {
27107
+ provisional: true,
27108
+ captureTime: true,
27109
+ anchorProvenance: provenance,
27110
+ anchorLine: opts.line,
27111
+ enclosingSymbol: true,
27112
+ // PJ-anchor-version: WHICH version of the symbol this was witnessed
27113
+ // against. `bodyHash` is the indexer's 16-hex sha256 of the body;
27114
+ // `headSha` is the checkout's HEAD at capture. Both opaque, both
27115
+ // cross the membrane on the anchor edge, and a teammate's reanchor
27116
+ // compares the hash with their own symbol to tell "current" from
27117
+ // "pre-change" — the branch hazard where a fix witnessed on feat/x
27118
+ // would otherwise read as a fact about the unchanged symbol on dev.
27119
+ ...typeof sym.attrs["bodyHash"] === "string" ? { symbolContentHash: sym.attrs["bodyHash"] } : {},
27120
+ ...opts.headSha ? { observedAtCommit: opts.headSha } : {}
27121
+ }
27122
+ });
27123
+ }
27124
+ }
27125
+ return true;
27126
+ }
27127
+ var ENCLOSING_SYMBOL_KINDS = /* @__PURE__ */ new Set([
27128
+ "Function",
27129
+ "Class",
27130
+ "Method",
27131
+ "Module",
27132
+ "Interface",
27133
+ "Const",
27134
+ "Enum",
27135
+ "TypeAlias",
27136
+ "Namespace",
27137
+ "Property"
27138
+ ]);
27139
+ var ENCLOSING_WALK_DEPTH = 8;
27140
+ function resolveEnclosingSymbol(store2, fileId, line, fileText) {
27141
+ if (!Number.isFinite(line) || line < 1) return null;
27142
+ const row = Math.floor(line) - 1;
27143
+ const lineStarts = [0];
27144
+ for (let i2 = 0; i2 < fileText.length; i2++) if (fileText.charCodeAt(i2) === 10) lineStarts.push(i2 + 1);
27145
+ const rowOf = (index) => {
27146
+ let lo = 0;
27147
+ let hi = lineStarts.length - 1;
27148
+ while (lo < hi) {
27149
+ const mid = lo + hi + 1 >> 1;
27150
+ if (lineStarts[mid] <= index) lo = mid;
27151
+ else hi = mid - 1;
27152
+ }
27153
+ return lo;
27154
+ };
27155
+ let best = null;
27156
+ let bestStart = -1;
27157
+ let bestSpan = Number.POSITIVE_INFINITY;
27158
+ const seen = /* @__PURE__ */ new Set([fileId]);
27159
+ let frontier = [fileId];
27160
+ for (let depth = 0; depth < ENCLOSING_WALK_DEPTH && frontier.length > 0; depth++) {
27161
+ const next = [];
27162
+ for (const id of frontier) {
27163
+ for (const e of store2.outEdges(id, ["DEFINES"])) {
27164
+ if (seen.has(e.to)) continue;
27165
+ seen.add(e.to);
27166
+ const n = store2.getNode(e.to);
27167
+ if (!n) continue;
27168
+ next.push(n.id);
27169
+ if (!ENCLOSING_SYMBOL_KINDS.has(n.label)) continue;
27170
+ const startRow = n.attrs["startRow"];
27171
+ const startByte = n.attrs["startByte"];
27172
+ const endByte = n.attrs["endByte"];
27173
+ if (typeof startRow !== "number" || typeof startByte !== "number" || typeof endByte !== "number") continue;
27174
+ if (startRow < 0 || endByte < startByte) continue;
27175
+ const endRow = rowOf(Math.max(startByte, Math.min(endByte, fileText.length) - 1));
27176
+ if (row < startRow || row > endRow) continue;
27177
+ const span = endByte - startByte;
27178
+ if (startRow > bestStart || startRow === bestStart && span < bestSpan) {
27179
+ best = n;
27180
+ bestStart = startRow;
27181
+ bestSpan = span;
27182
+ }
27183
+ }
27184
+ }
27185
+ frontier = next;
27186
+ }
27187
+ return best;
27188
+ }
26431
27189
  function recordAnchorHint(store2, problemId, relPath, provenance, ts) {
26432
27190
  const p = store2.getNode(problemId);
26433
27191
  if (!p || p.label !== "Problem") return false;
@@ -26437,6 +27195,49 @@ function recordAnchorHint(store2, problemId, relPath, provenance, ts) {
26437
27195
  });
26438
27196
  return true;
26439
27197
  }
27198
+ function openAnchorHint(p) {
27199
+ const h = p.attrs["anchorHint"];
27200
+ if (!h || typeof h.path !== "string" || h.upgradedAt) return null;
27201
+ return { path: h.path, ts: typeof h.ts === "number" ? h.ts : 0 };
27202
+ }
27203
+ function consumeAnchorHint(store2, p, ts) {
27204
+ const hint = p.attrs["anchorHint"];
27205
+ store2.updateNode(p.id, { attrs: { ...p.attrs, anchorHint: { ...hint, upgradedAt: ts } } });
27206
+ deriveContextFromAnchors(store2, p.id, ts);
27207
+ }
27208
+ function upgradeAnchorHints(store2, workspaceId, ts) {
27209
+ let upgraded = 0;
27210
+ let standing = 0;
27211
+ let unresolvable = 0;
27212
+ let blocked = 0;
27213
+ const filesByPath = /* @__PURE__ */ new Map();
27214
+ for (const f of store2.findNodesByLabel("File")) {
27215
+ if (f.attrs["workspaceId"] && f.attrs["workspaceId"] !== workspaceId) continue;
27216
+ const rel = typeof f.attrs["relPath"] === "string" ? f.attrs["relPath"] : f.description;
27217
+ if (rel && !filesByPath.has(rel)) filesByPath.set(rel, f);
27218
+ }
27219
+ for (const p of store2.findNodesByLabel("Problem")) {
27220
+ if (p.validTo != null || p.attrs["resolvedAt"]) continue;
27221
+ const hint = openAnchorHint(p);
27222
+ if (!hint) continue;
27223
+ const file2 = filesByPath.get(hint.path.trim().replace(/^\.?\//, ""));
27224
+ if (!file2 || !isAnchorableCodePath(hint.path)) {
27225
+ unresolvable++;
27226
+ continue;
27227
+ }
27228
+ standing++;
27229
+ const changedAt = Number(file2.attrs["contentChangedAt"] ?? 0);
27230
+ if (changedAt <= hint.ts) continue;
27231
+ if (anchorProblemToWorkingFile(store2, p.id, hint.path, workspaceId, ts, "hint-confirmed")) {
27232
+ consumeAnchorHint(store2, p, ts);
27233
+ upgraded++;
27234
+ standing--;
27235
+ } else {
27236
+ blocked++;
27237
+ }
27238
+ }
27239
+ return { upgraded, standing, unresolvable, blocked };
27240
+ }
26440
27241
  function reopenAutoClosedProblems(store2, t) {
26441
27242
  const report = { reopened: 0, alreadySuspect: 0, agentDescribed: 0 };
26442
27243
  for (const p of store2.findNodesByLabel("Problem")) {
@@ -27174,7 +27975,380 @@ function rankToolsForHandles(store2, limit = 5) {
27174
27975
  init_src2();
27175
27976
 
27176
27977
  // ../../packages/local-graph/src/mechanism-liveness.ts
27978
+ var STALL_MIN_RUNS = 3;
27177
27979
  var STALL_MIN_SPAN_MS = 60 * 60 * 1e3;
27980
+ var MECHANISMS = [
27981
+ {
27982
+ id: "refute-local-stamp",
27983
+ what: "stamps a harvested refute witness onto the LOCAL node (refutedAt/refutations/reason)",
27984
+ // Stamped at harvest, so the capture pass carries the effect counter.
27985
+ pass: "capture",
27986
+ // Refutes are rare by design (a verdict, not a lean-on) — the bar is "the
27987
+ // field is written at all", the revisitAnsweredWhen precedent. RG-mark
27988
+ // ships the producer; RG-recall is the ranking consumer — until it lands,
27989
+ // THIS descriptor is the consumer, which is exactly the condition the
27990
+ // probe exists to keep visible rather than let rot silently.
27991
+ fed: {
27992
+ labels: ["Problem", "Solution", "RootCause", "Pattern"],
27993
+ attr: "refutedAt",
27994
+ minFraction: 0
27995
+ },
27996
+ effectCounter: "refutesStamped",
27997
+ note: "RG-mark; reason text is local-only (wire ships nodeId+witnessKey)"
27998
+ },
27999
+ {
28000
+ id: "regression-recognize",
28001
+ what: "marks a resolved problem as resolutionSuspect when it recurs at the door",
28002
+ pass: "capture",
28003
+ // Regressions are rare and precious — written-at-all bar, like refutedAt.
28004
+ fed: {
28005
+ labels: ["Problem"],
28006
+ attr: "recurredAt",
28007
+ minFraction: 0
28008
+ },
28009
+ effectCounter: "recurrencesMarked",
28010
+ note: "RG-recognize tier A (exact-id door); tiers B/C add REGRESSION_OF edges; reopen is RG-reopen's"
28011
+ },
28012
+ {
28013
+ id: "regression-reopen",
28014
+ what: "flips a marked close back open once two DISTINCT sessions witnessed the recurrence",
28015
+ pass: "capture",
28016
+ // Reopens should be rarer than recurrences by construction — written-at-all.
28017
+ fed: {
28018
+ labels: ["Problem"],
28019
+ attr: "reopenedFrom",
28020
+ minFraction: 0
28021
+ },
28022
+ effectCounter: "reopenedFromRegression",
28023
+ note: "RG-reopen; the machine sweep never counts as a witness \u2014 only sessions do"
28024
+ },
28025
+ {
28026
+ id: "fix-candidate-ask",
28027
+ what: "asks an agent whether an edit to a problem's anchor fixed it",
28028
+ pass: "semantic-maintenance",
28029
+ // markFixCandidates fails CLOSED on a File anchor with no contentChangedAt —
28030
+ // correct (the alternative manufactured 92 asks out of no-op reindexes) and
28031
+ // exactly why coverage must be watched rather than assumed. Measured over
28032
+ // the recently-TOUCHED files, because the stamp is forward-only: whole-corpus
28033
+ // coverage on this store is ~0.5% and says nothing about whether the
28034
+ // producer works.
28035
+ fed: { labels: ["File"], attr: "contentChangedAt", minFraction: 0.02, recent: 200 },
28036
+ effectCounter: "fixCandidatesSettled",
28037
+ // Standing asks ARE the queue: 94 of them sat forever while the sweep
28038
+ // reported zero every run, and nothing could tell that from a clean backlog.
28039
+ backlogCounter: "fixCandidatesStanding",
28040
+ note: "stamped forward-only; measured over the 200 newest File nodes"
28041
+ },
28042
+ {
28043
+ id: "revisit-sweep",
28044
+ what: "retires a revisit ask once its recorded condition is met",
28045
+ pass: "semantic-maintenance",
28046
+ fed: {
28047
+ labels: ["Solution", "Problem", "RootCause", "Pattern"],
28048
+ attr: "revisitAnsweredWhen",
28049
+ // Only FLAGGED nodes carry it, and flags are rare by design, so the bar is
28050
+ // "the field is written at all" — it was written zero times before this.
28051
+ minFraction: 0
28052
+ },
28053
+ effectCounter: "revisitsCleared",
28054
+ backlogCounter: "revisitsStanding"
28055
+ },
28056
+ {
28057
+ id: "ingest-sequence",
28058
+ what: "orders knowledge arrivals so decay is driven by superseding info, not the clock",
28059
+ // CAPTURE, not semantic-maintenance. The sequence advances where knowledge
28060
+ // ENTERS the graph, and the maintenance pass never mints — so pointing this
28061
+ // at maintenance named a counter that is structurally always zero and the
28062
+ // mechanism read IDLE forever while stamping every new node. A descriptor
28063
+ // that cannot report an effect is the same defect it exists to detect.
28064
+ pass: "capture",
28065
+ fed: {
28066
+ labels: ["Problem", "Solution", "RootCause", "Pattern"],
28067
+ attr: "__createdAtSeq",
28068
+ // UNIVERSAL stamp: every semantic node minted after the producer went live
28069
+ // carries a sequence position, so the honest metric is "of the nodes born
28070
+ // since the first stamp, how many are stamped" — an invariant that should
28071
+ // read ~1.0 always. The 173k pre-fix nodes are deliberately never
28072
+ // backfilled (inventing a sequence position would feed the decay math
28073
+ // fabricated evidence it would read as real), and a recent-N window would
28074
+ // have to turn over 50 nodes before it could go green: it read 6% while
28075
+ // the producer was verifiably stamping every new node.
28076
+ minFraction: 0.9,
28077
+ recent: 200,
28078
+ sinceFirstStamp: true
28079
+ },
28080
+ effectCounter: "seqAdvanced",
28081
+ note: "column, not attr; measured over nodes born since the first stamp in the recent window"
28082
+ },
28083
+ {
28084
+ id: "render-ledger",
28085
+ what: "records which priors actually reached the agent, so an answer rate has a denominator",
28086
+ // RENDER, not semantic-maintenance — `shown` only moves during a render, so
28087
+ // attributing it elsewhere named an always-zero counter (same defect as
28088
+ // ingest-sequence's, found alongside it).
28089
+ pass: "render",
28090
+ fed: {
28091
+ labels: ["Problem", "Solution", "RootCause", "Pattern"],
28092
+ attr: "shownCount",
28093
+ minFraction: 5e-3
28094
+ },
28095
+ effectCounter: "shown"
28096
+ },
28097
+ {
28098
+ id: "contribution-ship",
28099
+ what: "carries local knowledge across the membrane to the cloud, and records the door's verdict",
28100
+ pass: "ship",
28101
+ // FED = nodes that have actually crossed. `contributedAtSeq` is stamped
28102
+ // only after the door accepts, so a fed reading is proof the whole chain
28103
+ // (build → generalize → drain → accept) ran, not merely that a timer fired.
28104
+ // The instance lane sat DEAD for 13 days behind a 422 nobody surfaced —
28105
+ // this row is the instrument that would have caught it on day one.
28106
+ fed: {
28107
+ labels: ["Problem", "Solution", "RootCause"],
28108
+ attr: "contributedAtSeq",
28109
+ minFraction: 0.01
28110
+ },
28111
+ effectCounter: "accepted",
28112
+ // Rising = knowledge piling up locally that never crossed. A backlog that
28113
+ // climbs while `accepted` stays flat is the shape of a silently-closed door.
28114
+ backlogCounter: "candidates"
28115
+ },
28116
+ {
28117
+ id: "orphan-reap",
28118
+ what: "closes File nodes whose path the indexer no longer covers",
28119
+ pass: "orphan-reap",
28120
+ // Stranded lineage is the CONDITION this clears, so a rising reading is bad;
28121
+ // it is declared fed-by-liveness so the row exists and the pass is watched.
28122
+ fed: { labels: ["File"], attr: "relPath", minFraction: 0.9 },
28123
+ effectCounter: "reaped"
28124
+ },
28125
+ {
28126
+ id: "prior-corroboration",
28127
+ what: "grounds a cited prior by overlap with what the session actually touched",
28128
+ // CAPTURE mints the edges and stamps the verdict; the fed metric is the
28129
+ // corroborated fraction of the newest priorTag edges. Measured 2026-08-08:
28130
+ // 1 of 139 recent despite 84 having a live grounding path — reading STARVED
28131
+ // is the honest state until the touched-set plumbing is fixed
28132
+ // (VS-corroboration-rate); an alarm on a genuinely broken channel is what
28133
+ // alarms are for.
28134
+ pass: "capture",
28135
+ fedEdges: { marker: '"priorTag":true', attr: "corroborated", minFraction: 0.02, recent: 100 },
28136
+ effectCounter: "corroboratedEdges",
28137
+ note: "expected STARVED until VS-corroboration-rate lands \u2014 the channel is genuinely starved"
28138
+ },
28139
+ {
28140
+ id: "anchor-hint-upgrade",
28141
+ what: "promotes a read-grade anchor hint once its file is edited while the problem stays open",
28142
+ // The maintenance sweep is the reliable invoker (the harvest seam also
28143
+ // counts into capture's anchorHintsUpgraded, but only on edited turns).
28144
+ pass: "semantic-maintenance",
28145
+ // Conditional stamp: only flagged-during-read Problems carry a hint. 302
28146
+ // held one at mechanism birth (census 2026-08-09) — the fed floor is
28147
+ // "the field exists at all", the revisit-sweep precedent.
28148
+ fed: { labels: ["Problem"], attr: "anchorHint", minFraction: 0 },
28149
+ effectCounter: "anchorHintsUpgraded",
28150
+ // The gauge is the work the mechanism CAN act on and didn't: hints whose file
28151
+ // changed after the hint yet never upgraded. `anchorHintsStanding` also
28152
+ // counts hints still waiting for their file to be edited — a queue that
28153
+ // drains on the user's schedule, which read STUCK over any quiet stretch
28154
+ // (2026-09-23: 71 standing, none edited, toasted daily). Standing stays in
28155
+ // the ledger as information; it just cannot declare a stall.
28156
+ backlogCounter: "anchorHintsBlocked",
28157
+ note: "a hint upgrades when its file is next edited; stuck means an edited file's hint failed to anchor"
28158
+ },
28159
+ {
28160
+ id: "fold-candidate-resolve",
28161
+ what: "resolves parked paraphrase-fold nominations (embedding-certain bands auto, ambiguous band via the equivalence judge)",
28162
+ // The settle boundary's fold-judge pass is the sole consumer of
28163
+ // attrs.foldCandidate; producers are the file/workspace scouts (capture)
28164
+ // and the settle near-miss band (mergeProblemsByEmbedding).
28165
+ pass: "fold-judge",
28166
+ // Conditional mark, rare by design (a nomination is a near-miss event) —
28167
+ // the bar is "the field is written at all", the revisit-sweep precedent.
28168
+ fed: { labels: ["Problem"], attr: "foldCandidate", minFraction: 0 },
28169
+ effectCounter: "folded",
28170
+ // Standing nominations ARE the judge-less backlog — without the gauge a
28171
+ // deployment with no judge configured reads as "nothing to fold".
28172
+ backlogCounter: "standing",
28173
+ configCounter: "judgeConfigured",
28174
+ note: "the ambiguous band needs the opt-in judge: set ERRATA_FOLD_JUDGE=1 + a configured chat provider (azure env), or leave it off and the nominations stand"
28175
+ },
28176
+ {
28177
+ id: "cite-anchor-accrual",
28178
+ what: "accrues cite-context anchor evidence on anchorless cited priors; two distinct sessions promote a cite-confirmed ANCHORED_AT",
28179
+ pass: "capture",
28180
+ // Conditional attr: only anchorless semantic priors cited from a known
28181
+ // working file carry hints — "written at all" is the honest floor.
28182
+ fed: { labels: ["Problem"], attr: "citeAnchorHints", minFraction: 0 },
28183
+ effectCounter: "citeAnchorsPromoted",
28184
+ note: "the supply-side fix for corroboration 0-for-8: promoted anchors are what the overlap gate intersects on the NEXT citation"
28185
+ },
28186
+ {
28187
+ id: "wm-reinforce-exposure",
28188
+ what: "labels each paraphrase re-derivation with the prior's exposure (shown/evicted/unshown)",
28189
+ // The producer runs inside capture's fold path (reinforceSameAnchorProblem),
28190
+ // but capture cannot count it without threading the fold verdict up through
28191
+ // ingestDesignProblem — so the WM-JOIN reading is the observable: the
28192
+ // wm-calibration pass reads the stamped counters as levels every tick.
28193
+ pass: "wm-calibration",
28194
+ // Conditional stamp, rare by design (a paraphrase fold is a few-per-day
28195
+ // event) — the bar is "the field is written at all", the revisit-sweep
28196
+ // precedent. Zero everywhere = the outcome site never fired, which was
28197
+ // this store's measured state on 2026-08-09, day one of WM-labels.
28198
+ fed: { labels: ["Problem"], attr: "lastReinforceExposure", minFraction: 0 },
28199
+ // A LEVEL, not an increment: nonzero once any node ever carried an outcome.
28200
+ // Which is precisely why it must be read as movement — measured across the
28201
+ // 103 retained rows it never left 1, and the summed reading called that
28202
+ // "effect 103, ok".
28203
+ effectCounter: "reinforcedNodes",
28204
+ effectIsLevel: true,
28205
+ note: "levels ride the wm-calibration row; expect no-effect until outcome data accrues"
28206
+ },
28207
+ {
28208
+ id: "wm-leaned-exposure",
28209
+ what: "classifies a leaned-cite's exposure at outcome time (the display-confounded cell)",
28210
+ // CAPTURE parses the cite and classifies against the render stamps — the
28211
+ // gate's input is `lastShownAtSeq`, the render ledger's seq stamp.
28212
+ pass: "capture",
28213
+ fed: {
28214
+ labels: ["Problem", "Solution", "RootCause", "Pattern"],
28215
+ attr: "lastShownAtSeq",
28216
+ minFraction: 5e-3
28217
+ },
28218
+ effectCounter: "exposureOutcomes",
28219
+ note: "0 with live render stamps = no lean-cites parsed, not a broken classifier"
28220
+ },
28221
+ {
28222
+ id: "liveness-watch",
28223
+ what: "the daemon-side schedule of this very verdict \u2014 alarms when a mechanism stops working",
28224
+ // The watcher is itself a row: a probe that only runs when a human remembers
28225
+ // is how the original six defects shipped, and a scheduled watch that
28226
+ // silently stops running is the same failure one level up. Its `invoked …
28227
+ // ago` column is the reading that matters.
28228
+ pass: "liveness-watch",
28229
+ // It reads the pass LEDGER, not a node attribute; minFraction 0 makes the
28230
+ // fed gate structurally unfailable (the same "field written at all" bar as
28231
+ // revisit-sweep) so this row can only ever alarm on invocation.
28232
+ fed: { labels: ["Problem"], attr: "revisitReason", minFraction: 0 },
28233
+ // Alarms ARE its state transitions; zero on a healthy store, so the steady
28234
+ // reading is IDLE — correct, and it declares no backlog on purpose.
28235
+ effectCounter: "alarms",
28236
+ note: "steady-state IDLE is healthy; the row exists for its invocation age"
28237
+ }
28238
+ ];
28239
+ var COLUMN_INPUTS = {
28240
+ __createdAtSeq: (n) => n.createdAtSeq !== void 0 && n.createdAtSeq !== null
28241
+ };
28242
+ function evaluateFed(store2, d) {
28243
+ if (d.fedEdges) {
28244
+ const { count: count2, total } = store2.recentEdgeAttrCoverage(
28245
+ d.fedEdges.marker,
28246
+ d.fedEdges.attr,
28247
+ d.fedEdges.recent
28248
+ );
28249
+ return { count: count2, total, fraction: total === 0 ? 0 : count2 / total };
28250
+ }
28251
+ if (!d.fed) return { count: 0, total: 0, fraction: 0 };
28252
+ const column = COLUMN_INPUTS[d.fed.attr];
28253
+ const fed = d.fed;
28254
+ const has = (n) => column ? column(n) : n.attrs[fed.attr] !== void 0;
28255
+ const nodes = fed.labels.flatMap((label) => store2.findNodeAttrsByLabel(label));
28256
+ let window2 = nodes;
28257
+ if (fed.recent !== void 0) {
28258
+ window2 = [...nodes].sort((a, b) => b.createdAt - a.createdAt).slice(0, fed.recent);
28259
+ }
28260
+ if (fed.sinceFirstStamp) {
28261
+ let anchor = Infinity;
28262
+ for (const n of window2) if (has(n) && n.createdAt < anchor) anchor = n.createdAt;
28263
+ window2 = anchor === Infinity ? [] : window2.filter((n) => n.createdAt >= anchor);
28264
+ }
28265
+ let count = 0;
28266
+ for (const n of window2) if (has(n)) count++;
28267
+ return { count, total: window2.length, fraction: window2.length === 0 ? 0 : count / window2.length };
28268
+ }
28269
+ function evaluateMechanisms(store2, invocations = /* @__PURE__ */ new Map(), mechanisms = MECHANISMS) {
28270
+ return mechanisms.map((d) => {
28271
+ const fed = evaluateFed(store2, d);
28272
+ const inv = invocations.get(d.pass);
28273
+ const effectCount = d.effectIsLevel ? Math.max(
28274
+ 0,
28275
+ (inv?.lastTotals?.[d.effectCounter] ?? 0) - (inv?.firstTotals?.[d.effectCounter] ?? 0)
28276
+ ) : inv?.totals[d.effectCounter] ?? 0;
28277
+ const backlog = d.backlogCounter ? inv?.lastTotals?.[d.backlogCounter] : void 0;
28278
+ const backlogWas = d.backlogCounter ? inv?.firstTotals?.[d.backlogCounter] : void 0;
28279
+ const span = inv?.firstTs === void 0 ? 0 : inv.lastTs - inv.firstTs;
28280
+ 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);
28281
+ let verdict;
28282
+ if (!inv || inv.runs === 0) verdict = "never-invoked";
28283
+ else if (d.configCounter && inv.lastTotals?.[d.configCounter] === 0) verdict = "unconfigured";
28284
+ else if (fed.fraction < (d.fedEdges?.minFraction ?? d.fed?.minFraction ?? 0)) verdict = "starved";
28285
+ else if (stalled) verdict = "stalled";
28286
+ else if (effectCount === 0) verdict = "no-effect";
28287
+ else verdict = "ok";
28288
+ return {
28289
+ id: d.id,
28290
+ what: d.what,
28291
+ pass: d.pass,
28292
+ fedCount: fed.count,
28293
+ fedTotal: fed.total,
28294
+ fedFraction: fed.fraction,
28295
+ minFraction: d.fedEdges?.minFraction ?? d.fed?.minFraction ?? 0,
28296
+ ...inv ? { lastInvokedMs: inv.lastTs } : {},
28297
+ runs: inv?.runs ?? 0,
28298
+ effectCount,
28299
+ ...backlog !== void 0 ? { backlog } : {},
28300
+ ...backlogWas !== void 0 ? { backlogWas } : {},
28301
+ ...inv?.firstTs !== void 0 ? { spanMs: span } : {},
28302
+ verdict,
28303
+ ...d.note ? { note: d.note } : {}
28304
+ };
28305
+ });
28306
+ }
28307
+
28308
+ // ../../packages/local-graph/src/wm-calibration.ts
28309
+ var WM_CALIBRATION_LABELS = [
28310
+ "Problem",
28311
+ "Solution",
28312
+ "RootCause",
28313
+ "Pattern",
28314
+ "Technique",
28315
+ "AntiPattern"
28316
+ ];
28317
+ var num = (v) => typeof v === "number" && Number.isFinite(v) ? v : 0;
28318
+ function wmCalibrationCells(store2) {
28319
+ const cells = {
28320
+ shownNodes: 0,
28321
+ shownImpressions: 0,
28322
+ evictedNodes: 0,
28323
+ evictedImpressions: 0,
28324
+ reinforceShown: 0,
28325
+ reinforceEvicted: 0,
28326
+ reinforceUnshown: 0,
28327
+ reinforcedNodes: 0
28328
+ };
28329
+ for (const label of WM_CALIBRATION_LABELS) {
28330
+ for (const n of store2.findNodesByLabel(label)) {
28331
+ const shown = num(n.attrs["shownCount"]);
28332
+ const evicted = num(n.attrs["evictedCount"]);
28333
+ if (shown > 0) {
28334
+ cells.shownNodes++;
28335
+ cells.shownImpressions += shown;
28336
+ }
28337
+ if (evicted > 0) {
28338
+ cells.evictedNodes++;
28339
+ cells.evictedImpressions += evicted;
28340
+ }
28341
+ const rs = num(n.attrs["reinforceShownCount"]);
28342
+ const re = num(n.attrs["reinforceEvictedCount"]);
28343
+ const ru = num(n.attrs["reinforceUnshownCount"]);
28344
+ cells.reinforceShown += rs;
28345
+ cells.reinforceEvicted += re;
28346
+ cells.reinforceUnshown += ru;
28347
+ if (rs + re + ru > 0) cells.reinforcedNodes++;
28348
+ }
28349
+ }
28350
+ return cells;
28351
+ }
27178
28352
 
27179
28353
  // ../../packages/generalizer/src/generalizer.ts
27180
28354
  init_src2();
@@ -28004,6 +29178,381 @@ async function reconcileStaleFiles(store2, rootPath, workspaceId) {
28004
29178
  return total;
28005
29179
  }
28006
29180
 
29181
+ // src/workspace-maintenance.ts
29182
+ function runWorkspaceMaintenance(store2, workspaceId) {
29183
+ const seqBefore = store2.currentIngestSeq();
29184
+ const report = runSemanticMaintenance(store2);
29185
+ let hintUpgrade = { upgraded: 0, standing: 0, unresolvable: 0, blocked: 0 };
29186
+ try {
29187
+ hintUpgrade = upgradeAnchorHints(store2, workspaceId, Date.now());
29188
+ } catch {
29189
+ }
29190
+ let calibration = null;
29191
+ const calibrationStarted = Date.now();
29192
+ try {
29193
+ calibration = wmCalibrationCells(store2);
29194
+ } catch {
29195
+ }
29196
+ return {
29197
+ report,
29198
+ hintUpgrade,
29199
+ seqAdvanced: store2.currentIngestSeq() - seqBefore,
29200
+ calibration,
29201
+ calibrationMs: Date.now() - calibrationStarted
29202
+ };
29203
+ }
29204
+
29205
+ // src/retrieval-stack.ts
29206
+ init_src();
29207
+ import { execFileSync as execFileSync3 } from "node:child_process";
29208
+ import { existsSync as existsSync3, readFileSync as readFileSync3, statSync as statSync4 } from "node:fs";
29209
+ import { homedir as homedir3 } from "node:os";
29210
+ import { join as join6 } from "node:path";
29211
+ var MANIFEST_SCAN_CAP = 400;
29212
+ var PUBLIC_NPM_HOSTS = /* @__PURE__ */ new Set(["registry.npmjs.org", "registry.yarnpkg.com"]);
29213
+ var PUBLIC_PYPI_HOSTS = /* @__PURE__ */ new Set(["pypi.org", "files.pythonhosted.org", "pypi.python.org"]);
29214
+ var PUBLIC_NUGET_HOSTS = /* @__PURE__ */ new Set(["api.nuget.org", "www.nuget.org", "nuget.org"]);
29215
+ var PUBLIC_GEM_HOSTS = /* @__PURE__ */ new Set(["rubygems.org", "index.rubygems.org"]);
29216
+ var PUBLIC_MAVEN_HOSTS = /* @__PURE__ */ new Set([
29217
+ "repo.maven.apache.org",
29218
+ "repo1.maven.org",
29219
+ "central.sonatype.com",
29220
+ "oss.sonatype.org",
29221
+ "dl.google.com",
29222
+ "maven.google.com",
29223
+ "plugins.gradle.org"
29224
+ ]);
29225
+ function ecoKey(ecosystem, name2) {
29226
+ return `${ecosystem.toLowerCase()}\0${name2.toLowerCase()}`;
29227
+ }
29228
+ function selfIdentityFrom(selves) {
29229
+ const selfNames = /* @__PURE__ */ new Set();
29230
+ const selfNamespaces = /* @__PURE__ */ new Set();
29231
+ for (const s of selves) {
29232
+ (s.kind === "name" ? selfNames : selfNamespaces).add(ecoKey(s.ecosystem, s.value));
29233
+ }
29234
+ return { selfNames, selfNamespaces };
29235
+ }
29236
+ function hostOf(value) {
29237
+ try {
29238
+ return new URL(value.trim()).hostname.toLowerCase();
29239
+ } catch {
29240
+ return null;
29241
+ }
29242
+ }
29243
+ function urlIsPublic(value, publicHosts) {
29244
+ const host = hostOf(value);
29245
+ return host !== null && publicHosts.has(host);
29246
+ }
29247
+ var unquote = (s) => s.trim().replace(/^['"]|['"]$/g, "");
29248
+ function parseNpmrcPolicy(texts) {
29249
+ let defaultPublic = null;
29250
+ const privateScopes = /* @__PURE__ */ new Set();
29251
+ const decidedScopes = /* @__PURE__ */ new Set();
29252
+ for (const text of texts) {
29253
+ for (const rawLine of text.split(/\r?\n/)) {
29254
+ const line = rawLine.trim();
29255
+ if (!line || line.startsWith("#") || line.startsWith(";")) continue;
29256
+ const eq = line.indexOf("=");
29257
+ if (eq === -1) continue;
29258
+ const key = line.slice(0, eq).trim().toLowerCase();
29259
+ const value = line.slice(eq + 1).trim();
29260
+ if (key === "registry") {
29261
+ if (defaultPublic === null) defaultPublic = urlIsPublic(value, PUBLIC_NPM_HOSTS);
29262
+ continue;
29263
+ }
29264
+ const scoped = /^(@[^:]+):registry$/.exec(key);
29265
+ if (!scoped) continue;
29266
+ const scope = (scoped[1] ?? "").toLowerCase();
29267
+ if (decidedScopes.has(scope)) continue;
29268
+ decidedScopes.add(scope);
29269
+ if (!urlIsPublic(value, PUBLIC_NPM_HOSTS)) privateScopes.add(scope);
29270
+ }
29271
+ }
29272
+ return { defaultPublic: defaultPublic ?? true, privateScopes };
29273
+ }
29274
+ function pypiIndexIsPrivate(texts) {
29275
+ for (const text of texts) {
29276
+ if (/^\s*\[\[?\s*tool\.(poetry\.source|uv\.index)\s*\]\]?/m.test(text)) {
29277
+ const urls = [...text.matchAll(/^\s*url\s*=\s*(.+)$/gm)].map((m) => unquote(m[1] ?? ""));
29278
+ if (urls.length === 0 || urls.some((u) => !urlIsPublic(u, PUBLIC_PYPI_HOSTS))) return true;
29279
+ }
29280
+ for (const m of text.matchAll(/^\s*(?:-i\b|--?(?:extra-)?index-url)\s*[=:]?\s*(\S+)/gm)) {
29281
+ if (!urlIsPublic(unquote(m[1] ?? ""), PUBLIC_PYPI_HOSTS)) return true;
29282
+ }
29283
+ for (const m of text.matchAll(/^\s*(?:extra-)?index-url\s*=\s*(\S+)/gm)) {
29284
+ if (!urlIsPublic(unquote(m[1] ?? ""), PUBLIC_PYPI_HOSTS)) return true;
29285
+ }
29286
+ }
29287
+ return false;
29288
+ }
29289
+ function cargoRegistryIsPrivate(texts) {
29290
+ return texts.some(
29291
+ (t) => /^\s*\[registries(\.|\])/m.test(t) || /^\s*replace-with\s*=/m.test(t)
29292
+ );
29293
+ }
29294
+ function nugetSourcesArePrivate(texts) {
29295
+ for (const text of texts) {
29296
+ const block = /<packageSources>([\s\S]*?)<\/packageSources>/i.exec(text);
29297
+ if (!block) continue;
29298
+ for (const m of (block[1] ?? "").matchAll(/<add\b[^>]*\bvalue\s*=\s*"([^"]+)"/gi)) {
29299
+ if (!urlIsPublic(m[1] ?? "", PUBLIC_NUGET_HOSTS)) return true;
29300
+ }
29301
+ }
29302
+ return false;
29303
+ }
29304
+ function parseGoPrivate(values) {
29305
+ return values.flatMap((v) => (v ?? "").split(",")).map((s) => s.trim()).filter(Boolean);
29306
+ }
29307
+ function mavenReposArePrivate(texts) {
29308
+ for (const text of texts) {
29309
+ if (/<servers>[\s\S]*?<server>/i.test(text)) return true;
29310
+ for (const m of text.matchAll(/<(?:repository|pluginRepository|mirror)\b[\s\S]*?<\/(?:repository|pluginRepository|mirror)>/gi)) {
29311
+ const url2 = /<url>([^<]+)<\/url>/i.exec(m[0])?.[1];
29312
+ if (!url2 || !urlIsPublic(url2, PUBLIC_MAVEN_HOSTS)) return true;
29313
+ }
29314
+ }
29315
+ return false;
29316
+ }
29317
+ function gemSourceIsPrivate(texts) {
29318
+ for (const text of texts) {
29319
+ for (const m of text.matchAll(/^\s*source\s+["']([^"']+)["']/gm)) {
29320
+ if (!urlIsPublic(m[1] ?? "", PUBLIC_GEM_HOSTS)) return true;
29321
+ }
29322
+ }
29323
+ return false;
29324
+ }
29325
+ function privateGemNamesIn(texts) {
29326
+ const names = /* @__PURE__ */ new Set();
29327
+ for (const text of texts) {
29328
+ for (const raw of text.split(/\r?\n/)) {
29329
+ const line = (raw.split("#", 1)[0] ?? "").trim();
29330
+ const m = /^gem\s+["']([^"']+)["']/.exec(line);
29331
+ if (!m?.[1]) continue;
29332
+ if (/(?::(?:git|path|github|gist|bitbucket)\s*=>|\b(?:git|path|github|gist|bitbucket):\s)/.test(line)) {
29333
+ names.add(m[1]);
29334
+ }
29335
+ }
29336
+ }
29337
+ return names;
29338
+ }
29339
+ function selfTokensFromLocator(repoLocator) {
29340
+ if (!repoLocator) return [];
29341
+ const segments = repoLocator.toLowerCase().split("/").slice(1).filter(Boolean);
29342
+ return [...new Set(segments.filter((s) => s.length >= 3))];
29343
+ }
29344
+ function loadRegistryPolicy(root, env2 = process.env, repoLocator) {
29345
+ const read = (p) => {
29346
+ try {
29347
+ return readFileSync3(p, "utf8");
29348
+ } catch {
29349
+ return null;
29350
+ }
29351
+ };
29352
+ const texts = (...paths2) => paths2.map(read).filter((t) => t !== null);
29353
+ const home = homedir3();
29354
+ const npm = parseNpmrcPolicy(texts(join6(root, ".npmrc"), join6(home, ".npmrc")));
29355
+ const blocked = /* @__PURE__ */ new Set();
29356
+ if (!npm.defaultPublic) blocked.add("npm");
29357
+ if (pypiIndexIsPrivate(
29358
+ texts(
29359
+ join6(root, "pip.conf"),
29360
+ join6(root, "pip.ini"),
29361
+ join6(root, "pyproject.toml"),
29362
+ join6(root, "requirements.txt"),
29363
+ join6(home, ".pip", "pip.conf"),
29364
+ join6(home, ".config", "pip", "pip.conf"),
29365
+ join6(env2["APPDATA"] ?? home, "pip", "pip.ini")
29366
+ )
29367
+ )) {
29368
+ blocked.add("pypi");
29369
+ }
29370
+ if (cargoRegistryIsPrivate(
29371
+ texts(
29372
+ join6(root, ".cargo", "config.toml"),
29373
+ join6(root, ".cargo", "config"),
29374
+ join6(home, ".cargo", "config.toml"),
29375
+ join6(home, ".cargo", "config")
29376
+ )
29377
+ )) {
29378
+ blocked.add("cargo");
29379
+ }
29380
+ if (nugetSourcesArePrivate(
29381
+ texts(
29382
+ join6(root, "NuGet.config"),
29383
+ join6(root, "nuget.config"),
29384
+ join6(root, "NuGet.Config"),
29385
+ join6(env2["APPDATA"] ?? home, "NuGet", "NuGet.Config"),
29386
+ join6(home, ".nuget", "NuGet", "NuGet.Config")
29387
+ )
29388
+ )) {
29389
+ blocked.add("nuget");
29390
+ }
29391
+ const goEnvFile = env2["GOENV"] ?? join6(env2["APPDATA"] ?? join6(home, ".config"), "go", "env");
29392
+ const goEnvText = read(goEnvFile) ?? "";
29393
+ const fromFile = ["GOPRIVATE", "GONOSUMDB", "GONOSUMCHECK"].map(
29394
+ (k) => new RegExp(`^${k}=(.*)$`, "m").exec(goEnvText)?.[1]
29395
+ );
29396
+ const goPrivatePatterns = parseGoPrivate([
29397
+ env2["GOPRIVATE"],
29398
+ env2["GONOSUMDB"],
29399
+ env2["GONOSUMCHECK"],
29400
+ ...fromFile
29401
+ ]);
29402
+ const gemfiles = texts(join6(root, "Gemfile"));
29403
+ if (gemSourceIsPrivate(gemfiles)) blocked.add("gem");
29404
+ if (mavenReposArePrivate(
29405
+ texts(join6(root, "pom.xml"), join6(home, ".m2", "settings.xml"))
29406
+ )) {
29407
+ blocked.add("maven");
29408
+ }
29409
+ const scan2 = scanManifests(root);
29410
+ return {
29411
+ blockedEcosystems: blocked,
29412
+ npmPrivateScopes: npm.privateScopes,
29413
+ goPrivatePatterns,
29414
+ privateGemNames: privateGemNamesIn(gemfiles),
29415
+ selfTokens: selfTokensFromLocator(repoLocator),
29416
+ ...selfIdentityFrom(scan2.self),
29417
+ selfComplete: scan2.complete
29418
+ };
29419
+ }
29420
+ var LOCKFILES = [
29421
+ { file: "pnpm-lock.yaml", family: "npm", parse: parsePnpmLock },
29422
+ { file: "package-lock.json", family: "npm", parse: parsePackageLockJson },
29423
+ { file: "Gemfile.lock", family: "gem", parse: parseGemfileLock }
29424
+ ];
29425
+ var directCache = /* @__PURE__ */ new Map();
29426
+ function readDirectDependencies(root) {
29427
+ const stamps = [];
29428
+ const found = [];
29429
+ const familiesSeen = /* @__PURE__ */ new Set();
29430
+ for (const c of LOCKFILES) {
29431
+ if (familiesSeen.has(c.family)) continue;
29432
+ const p = join6(root, c.file);
29433
+ if (!existsSync3(p)) continue;
29434
+ try {
29435
+ const s = statSync4(p);
29436
+ stamps.push(`${c.file}:${s.mtimeMs}:${s.size}`);
29437
+ } catch {
29438
+ continue;
29439
+ }
29440
+ familiesSeen.add(c.family);
29441
+ found.push({ c, path: p });
29442
+ }
29443
+ if (found.length === 0) {
29444
+ directCache.delete(root);
29445
+ return [];
29446
+ }
29447
+ const key = stamps.join("|");
29448
+ const hit = directCache.get(root);
29449
+ if (hit && hit.key === key) return hit.direct;
29450
+ const direct = [];
29451
+ for (const { c, path } of found) {
29452
+ try {
29453
+ direct.push(...c.parse(readFileSync3(path, "utf8")).direct ?? []);
29454
+ } catch {
29455
+ }
29456
+ }
29457
+ directCache.set(root, { key, direct });
29458
+ return direct;
29459
+ }
29460
+ function manifestPaths(root) {
29461
+ try {
29462
+ const out2 = execFileSync3("git", ["-C", root, "ls-files", "-z"], {
29463
+ encoding: "utf8",
29464
+ maxBuffer: 128 * 1024 * 1024,
29465
+ windowsHide: true,
29466
+ stdio: ["ignore", "pipe", "ignore"]
29467
+ });
29468
+ const paths2 = out2.split("\0").filter((f) => f && isManifestPath(f));
29469
+ if (paths2.length > 0) {
29470
+ return {
29471
+ paths: paths2.slice(0, MANIFEST_SCAN_CAP),
29472
+ tracked: true,
29473
+ truncated: paths2.length > MANIFEST_SCAN_CAP
29474
+ };
29475
+ }
29476
+ } catch {
29477
+ }
29478
+ const ROOT_MANIFESTS = [
29479
+ "package.json",
29480
+ "pyproject.toml",
29481
+ "requirements.txt",
29482
+ "go.mod",
29483
+ "Cargo.toml",
29484
+ "pom.xml",
29485
+ "build.gradle",
29486
+ "build.gradle.kts",
29487
+ "gradle/libs.versions.toml",
29488
+ "Gemfile",
29489
+ "docker-compose.yml",
29490
+ "docker-compose.yaml",
29491
+ "compose.yaml",
29492
+ "Dockerfile",
29493
+ "project.godot"
29494
+ ];
29495
+ return {
29496
+ paths: ROOT_MANIFESTS.filter((f) => existsSync3(join6(root, f))),
29497
+ tracked: false,
29498
+ truncated: false
29499
+ };
29500
+ }
29501
+ var WORKSPACE_MARKERS = ["pnpm-workspace.yaml", "lerna.json", "go.work", "settings.gradle", "settings.gradle.kts"];
29502
+ function rootDeclaresWorkspace(root, texts) {
29503
+ if (WORKSPACE_MARKERS.some((f) => existsSync3(join6(root, f)))) return true;
29504
+ return /"workspaces"\s*:/.test(texts.get("package.json") ?? "") || /<modules>/.test(texts.get("pom.xml") ?? "") || /^\s*\[workspace\]/m.test(texts.get("Cargo.toml") ?? "");
29505
+ }
29506
+ var EMPTY_SCAN = { deps: [], self: [], complete: true };
29507
+ var manifestCache = /* @__PURE__ */ new Map();
29508
+ function scanManifests(root) {
29509
+ const { paths: paths2, tracked, truncated } = manifestPaths(root);
29510
+ if (paths2.length === 0) {
29511
+ manifestCache.delete(root);
29512
+ return EMPTY_SCAN;
29513
+ }
29514
+ const texts = /* @__PURE__ */ new Map();
29515
+ const stamps = [];
29516
+ for (const rel of paths2) {
29517
+ const abs = join6(root, rel);
29518
+ try {
29519
+ const s = statSync4(abs);
29520
+ stamps.push(`${rel}:${s.mtimeMs}:${s.size}`);
29521
+ texts.set(rel, readFileSync3(abs, "utf8"));
29522
+ } catch {
29523
+ }
29524
+ }
29525
+ const key = stamps.join("|");
29526
+ const hit = manifestCache.get(root);
29527
+ if (hit && hit.key === key) return hit.scan;
29528
+ const scan2 = {
29529
+ deps: [],
29530
+ self: [],
29531
+ complete: !truncated && (tracked || !rootDeclaresWorkspace(root, texts))
29532
+ };
29533
+ try {
29534
+ const spine = buildSpine("workspace", [...texts.keys()], (p) => texts.get(p) ?? "");
29535
+ scan2.deps = Object.values(spine.manifests).flat();
29536
+ for (const [path, text] of texts) scan2.self.push(...parseManifestSelf(path, text));
29537
+ } catch {
29538
+ scan2.deps = [];
29539
+ scan2.self = [];
29540
+ scan2.complete = false;
29541
+ }
29542
+ manifestCache.set(root, { key, scan: scan2 });
29543
+ return scan2;
29544
+ }
29545
+ function readManifestDependencies(root) {
29546
+ return scanManifests(root).deps;
29547
+ }
29548
+ function readRetrievalInputs(root, repoLocator) {
29549
+ return {
29550
+ direct: readDirectDependencies(root),
29551
+ manifestDeps: readManifestDependencies(root),
29552
+ registry: loadRegistryPolicy(root, process.env, repoLocator)
29553
+ };
29554
+ }
29555
+
28007
29556
  // src/pass-worker.ts
28008
29557
  var init2 = workerData;
28009
29558
  var store = openGraphStore({ path: init2.castaliaPath });
@@ -28017,6 +29566,12 @@ port.on("message", (msg) => {
28017
29566
  });
28018
29567
  function runPass(msg) {
28019
29568
  switch (msg.kind) {
29569
+ case "semanticMaintenance":
29570
+ return runWorkspaceMaintenance(store, init2.workspaceId);
29571
+ case "liveness":
29572
+ return evaluateMechanisms(store, new Map(msg.payload));
29573
+ case "retrievalInputs":
29574
+ return readRetrievalInputs(init2.workspaceRoot, msg.payload);
28020
29575
  case "nightly":
28021
29576
  return runNightly();
28022
29577
  case "reconcile":