@inerrata-corporation/errata 2.0.6-dev.2333 → 2.0.6-dev.2504

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.
@@ -378,6 +378,9 @@ import { createHash } from "node:crypto";
378
378
  function sha256(input) {
379
379
  return createHash("sha256").update(input).digest("hex");
380
380
  }
381
+ function sha256Short(input, n = 8) {
382
+ return sha256(input).slice(0, n);
383
+ }
381
384
  function canonicalJSON(value) {
382
385
  if (value === null || typeof value !== "object") {
383
386
  return JSON.stringify(value);
@@ -813,6 +816,12 @@ function identityId(input) {
813
816
  );
814
817
  }
815
818
  }
819
+ function genericCanonicalId(prefix, content) {
820
+ return `${prefix}_${digest(content)}`.slice(0, 56);
821
+ }
822
+ function languageCanonicalId(name) {
823
+ return genericCanonicalId("Language", { name: name.trim().toLowerCase() });
824
+ }
816
825
  var DESIGN_PROBLEM_PREFIX, DESIGN_PROBLEM_ID_LENGTH, DIAGNOSTIC_PROBLEM_PREFIX, DIAGNOSTIC_HASH_LENGTH, TRIAGE_PREFIX, TRIAGE_ID_LENGTH;
817
826
  var init_identity = __esm({
818
827
  "../../packages/shared/src/identity.ts"() {
@@ -15250,7 +15259,49 @@ var init_edge_rules = __esm({
15250
15259
  });
15251
15260
 
15252
15261
  // ../../packages/shared/src/symbol-intent.ts
15253
- var SYMBOL_SUMMARY_KINDS, MAX_SYMBOL_SUMMARY_CHARS, MAX_SIDECAR_SYMBOLS;
15262
+ function extractIdentifierTokens(text) {
15263
+ const out = [];
15264
+ const seen = /* @__PURE__ */ new Set();
15265
+ for (const m of text.matchAll(TOKEN_RE2)) {
15266
+ if (!seen.has(m[0])) {
15267
+ seen.add(m[0]);
15268
+ out.push(m[0]);
15269
+ }
15270
+ }
15271
+ return out;
15272
+ }
15273
+ function sidecarDropBucket(reason) {
15274
+ if (reason === null) return null;
15275
+ if (reason === "empty summary") return "empty";
15276
+ if (reason === "summary too long") return "too_long";
15277
+ if (reason === "contains a path shape") return "path_shape";
15278
+ if (reason === "contains a quoted literal") return "quoted_literal";
15279
+ if (reason.startsWith("contains verbatim identifier")) return "verbatim_identifier";
15280
+ return "other";
15281
+ }
15282
+ function summaryRejectionReason(summary, isKnownToken) {
15283
+ if (!summary.trim()) return "empty summary";
15284
+ if (summary.length > MAX_SYMBOL_SUMMARY_CHARS) return "summary too long";
15285
+ if (PATH_SHAPE_RE.test(summary)) return "contains a path shape";
15286
+ if (QUOTED_LITERAL_RE.test(summary.replace(CONTRACTION_RE, "$1$2")))
15287
+ return "contains a quoted literal";
15288
+ for (const tok of extractIdentifierTokens(summary)) {
15289
+ if (isKnownToken(tok)) return `contains verbatim identifier '${tok}'`;
15290
+ if (tok.includes(".")) {
15291
+ const segs = tok.split(".");
15292
+ for (let i = 0; i < segs.length; i++) {
15293
+ let span = "";
15294
+ for (let j = i; j < segs.length; j++) {
15295
+ span = span ? `${span}.${segs[j]}` : segs[j];
15296
+ if (span !== tok && span && isKnownToken(span))
15297
+ return `contains verbatim identifier '${span}'`;
15298
+ }
15299
+ }
15300
+ }
15301
+ }
15302
+ return null;
15303
+ }
15304
+ var SYMBOL_SUMMARY_KINDS, MAX_SYMBOL_SUMMARY_CHARS, MAX_SIDECAR_SYMBOLS, TOKEN_RE2, PATH_SHAPE_RE, CONTRACTION_RE, QUOTED_LITERAL_RE;
15254
15305
  var init_symbol_intent = __esm({
15255
15306
  "../../packages/shared/src/symbol-intent.ts"() {
15256
15307
  "use strict";
@@ -15263,10 +15314,23 @@ var init_symbol_intent = __esm({
15263
15314
  ];
15264
15315
  MAX_SYMBOL_SUMMARY_CHARS = 300;
15265
15316
  MAX_SIDECAR_SYMBOLS = 200;
15317
+ TOKEN_RE2 = /[A-Za-z_$][A-Za-z0-9_$]*(?:\.[A-Za-z_$][A-Za-z0-9_$]*)*/g;
15318
+ PATH_SHAPE_RE = /[\w.~-]+[/\\][\w.$~-]+/;
15319
+ CONTRACTION_RE = /([A-Za-z])'([A-Za-z])/g;
15320
+ QUOTED_LITERAL_RE = /"[^"]+"|'[^']+'|`[^`]+`/;
15266
15321
  }
15267
15322
  });
15268
15323
 
15269
15324
  // ../../packages/shared/src/wire.ts
15325
+ function anchorVersionAttrs(attrs) {
15326
+ if (!attrs) return {};
15327
+ const commit = attrs["observedAtCommit"];
15328
+ const hash2 = attrs["symbolContentHash"];
15329
+ return {
15330
+ ...typeof commit === "string" && ANCHOR_COMMIT_SHA_RE.test(commit) ? { observedAtCommit: commit } : {},
15331
+ ...typeof hash2 === "string" && ANCHOR_BODY_HASH_RE.test(hash2) ? { symbolContentHash: hash2 } : {}
15332
+ };
15333
+ }
15270
15334
  var CLOUD_NODE_LABELS, CLOUD_WRITABLE_NODE_LABELS, PROJECT_ONLY_NODE_LABELS, PROJECT_ONLY_NODE_LABEL_SET, PROJECT_ONLY_EDGE_TYPES, PROJECT_ONLY_EDGE_TYPE_SET, CLOUD_WRITABLE_NODE_LABEL_SET, CLOUD_EDGE_TYPES, INGEST_SOURCES, INGEST_EXTRACTION_SOURCES, CastaliaIngestNodeSchema, RouteContextCountWireSchema, ANCHOR_COMMIT_SHA_RE, ANCHOR_BODY_HASH_RE, CastaliaIngestEdgeSchema, SymbolSummarySidecarSchema, CastaliaIngestPayloadSchema;
15271
15335
  var init_wire = __esm({
15272
15336
  "../../packages/shared/src/wire.ts"() {
@@ -15440,6 +15504,17 @@ var init_repo_locator = __esm({
15440
15504
  });
15441
15505
 
15442
15506
  // ../../packages/shared/src/project-symbol.ts
15507
+ import { createHmac } from "node:crypto";
15508
+ function normalizeSymbolPath(relPath) {
15509
+ return relPath.replace(/\\/g, "/").replace(/\/+/g, "/").replace(/^\.\//, "").replace(/^\//, "");
15510
+ }
15511
+ function projectSymbolId(projectSalt, projectId, relPath, qname, kind) {
15512
+ const path = normalizeSymbolPath(relPath);
15513
+ return `sym_${createHmac("sha256", projectSalt).update(`${projectId}:${path}:${qname}:${kind}`).digest("hex").slice(0, 24)}`;
15514
+ }
15515
+ function isMembraneSaltedId(id) {
15516
+ return typeof id === "string" && /^(orgn_|teamn_|projn_)/.test(id);
15517
+ }
15443
15518
  var init_project_symbol = __esm({
15444
15519
  "../../packages/shared/src/project-symbol.ts"() {
15445
15520
  "use strict";
@@ -15600,6 +15675,21 @@ var init_anchorable = __esm({
15600
15675
  });
15601
15676
 
15602
15677
  // ../../packages/local-shared/src/sqlite-adapter.ts
15678
+ function loadNodeSqlite() {
15679
+ const original = process.emitWarning;
15680
+ process.emitWarning = function(warning, ...rest) {
15681
+ const text = typeof warning === "string" ? warning : warning?.message ?? "";
15682
+ const opt = rest[0];
15683
+ const type = typeof opt === "string" ? opt : opt?.type ?? warning?.name;
15684
+ if (type === "ExperimentalWarning" && /SQLite/i.test(text)) return;
15685
+ return original.call(process, warning, ...rest);
15686
+ };
15687
+ try {
15688
+ return process.getBuiltinModule("node:sqlite");
15689
+ } finally {
15690
+ process.emitWarning = original;
15691
+ }
15692
+ }
15603
15693
  function openDatabase(path) {
15604
15694
  const db = new DatabaseSync(path);
15605
15695
  try {
@@ -15681,12 +15771,11 @@ function normalizeParam(v) {
15681
15771
  if (typeof v === "boolean") return v ? 1 : 0;
15682
15772
  return v;
15683
15773
  }
15684
- var nodeSqlite, DatabaseSync;
15774
+ var DatabaseSync;
15685
15775
  var init_sqlite_adapter = __esm({
15686
15776
  "../../packages/local-shared/src/sqlite-adapter.ts"() {
15687
15777
  "use strict";
15688
- nodeSqlite = process.getBuiltinModule("node:sqlite");
15689
- DatabaseSync = nodeSqlite.DatabaseSync;
15778
+ DatabaseSync = loadNodeSqlite().DatabaseSync;
15690
15779
  }
15691
15780
  });
15692
15781
 
@@ -16894,6 +16983,7 @@ init_src();
16894
16983
 
16895
16984
  // ../../packages/local-graph/src/design-problem.ts
16896
16985
  var RECURRENCE_DEBOUNCE_MS = 60 * 60 * 1e3;
16986
+ var AUTO_MINT_PREFIX = "addressed by an edit to ";
16897
16987
 
16898
16988
  // ../../packages/local-graph/src/intent.ts
16899
16989
  init_src();
@@ -17002,6 +17092,9 @@ function percolate(l1, l2, opts) {
17002
17092
  init_src();
17003
17093
  init_src2();
17004
17094
 
17095
+ // ../../packages/math/src/constants.ts
17096
+ var NEMORI_DEDUP_COSINE = 0.88;
17097
+
17005
17098
  // ../../packages/math/src/triage.ts
17006
17099
  var TRIAGE_GLOBAL_BUCKET = "*";
17007
17100
  function triageContextBuckets(ctx) {
@@ -17661,6 +17754,1593 @@ function findStrandedSymbols(store) {
17661
17754
  return stranded;
17662
17755
  }
17663
17756
 
17757
+ // src/package-index.ts
17758
+ init_src();
17759
+ function buildContextIngest(store, profile, daemonVersion, ignorePatterns = [], opts = {}) {
17760
+ const labels = opts.includePackages === false ? ["Language"] : ["Package", "Language"];
17761
+ const ignored = (s) => ignorePatterns.length > 0 && ignorePatterns.some((p) => s.toLowerCase().includes(p));
17762
+ const nodes = [];
17763
+ const seen = /* @__PURE__ */ new Set();
17764
+ const localIdByWireId = {};
17765
+ for (const label of labels) {
17766
+ for (const n of store.findNodesByLabel(label)) {
17767
+ if (n.attrs["source"] === "cloud") continue;
17768
+ if (ignored(n.description) || ignored(String(n.attrs["name"] ?? ""))) continue;
17769
+ if (typeof n.attrs["contributedAtSeq"] === "number") continue;
17770
+ nodes.push({
17771
+ ...n,
17772
+ // Language wire id = the shared `languageCanonicalId` (warming-spine
17773
+ // parity, EE-cloud-anchors) — the local `lang:<name>` id is internal.
17774
+ // Package ids are already the purl (= the cross-stratum canonicalId).
17775
+ id: label === "Language" ? languageCanonicalId(String(n.attrs["name"] ?? "").trim() || n.description) : n.id,
17776
+ embedding: [],
17777
+ // No `version` attr on the wire: the purl already encodes the resolved
17778
+ // version, and the door's temporal guard rejects ANY `attrs.version` as
17779
+ // bi-temporal bookkeeping (ingest-temporal-guard.ts) — shipping it 422s
17780
+ // the whole batch. `resolved` still travels (range-vs-lockfile signal).
17781
+ attrs: label === "Package" ? {
17782
+ purl: n.attrs["purl"],
17783
+ name: n.attrs["name"],
17784
+ ecosystem: n.attrs["ecosystem"],
17785
+ resolved: n.attrs["resolved"]
17786
+ } : { name: n.attrs["name"] },
17787
+ // OM-anchor-tag: context stubs are self-anchored — the wire id IS the
17788
+ // spine key (purl / languageCanonicalId). The door re-confirms on the
17789
+ // public spine; a private-registry or workspace package never confirms
17790
+ // and fails closed to org, exactly as an untagged one would.
17791
+ anchorVisibility: "public"
17792
+ });
17793
+ seen.add(n.id);
17794
+ localIdByWireId[nodes[nodes.length - 1].id] = n.id;
17795
+ }
17796
+ }
17797
+ if (nodes.length === 0) return null;
17798
+ const edges = [];
17799
+ for (const id of seen) {
17800
+ for (const e of store.outEdges(id, ["DEPENDS_ON"])) {
17801
+ if (seen.has(e.to)) edges.push({ ...e, attrs: {} });
17802
+ }
17803
+ }
17804
+ const base = {
17805
+ daemonVersion,
17806
+ // Origin key (= project, the salted `wp_…`) — the door stamps it onto created
17807
+ // nodes as `authoringProject`, arming the evidence channels' cross-origin gate
17808
+ // (EE-corrob-live: without it every node is fail-open to self-corroboration).
17809
+ ...profile.id ? { originProject: profile.id } : {},
17810
+ profile: { stack: profile.stack, languages: profile.languages, domains: profile.domains },
17811
+ nodes,
17812
+ edges
17813
+ };
17814
+ return { ...base, payloadDigest: digest(base), localIds: [...seen], localIdByWireId };
17815
+ }
17816
+
17817
+ // src/instance-ingest.ts
17818
+ init_src();
17819
+ init_src2();
17820
+
17821
+ // ../../packages/privacy-edge/src/ontology.ts
17822
+ var DEFAULT_ONTOLOGY = {
17823
+ email: { l1: "an email address", l2: "an email address" },
17824
+ ip: { l1: "an IP address", l2: "an IP address" },
17825
+ path: { l1: "a path", l2: "a path" },
17826
+ file: { l1: "a file", l2: "a path" },
17827
+ credential: "neutralize",
17828
+ uuid: { l1: "an identifier", l2: "an identifier" },
17829
+ hash: { l1: "a hash", l2: "a value" },
17830
+ date: { l1: "a date", l2: "a date" },
17831
+ // real values come from date-shapes
17832
+ person: { l1: "a contributor", l2: "someone" },
17833
+ org: { l1: "a company", l2: "an organization" }
17834
+ };
17835
+ function generalizePhrase(cls, level) {
17836
+ const rule = DEFAULT_ONTOLOGY[cls];
17837
+ if (rule === "neutralize") return "[redacted:credential]";
17838
+ return level === 1 ? rule.l1 : rule.l2;
17839
+ }
17840
+
17841
+ // ../../packages/privacy-edge/src/date-shapes.ts
17842
+ function seasonFor(month) {
17843
+ if (month <= 4) return "early";
17844
+ if (month <= 8) return "mid";
17845
+ return "late";
17846
+ }
17847
+ var MONTHS = {
17848
+ jan: 1,
17849
+ feb: 2,
17850
+ mar: 3,
17851
+ apr: 4,
17852
+ may: 5,
17853
+ jun: 6,
17854
+ jul: 7,
17855
+ aug: 8,
17856
+ sep: 9,
17857
+ oct: 10,
17858
+ nov: 11,
17859
+ dec: 12
17860
+ };
17861
+ function generalizeDates(text, level) {
17862
+ const yearOnly = level === 2;
17863
+ let out = text;
17864
+ out = out.replace(
17865
+ /\b(\d{4})-(\d{2})-(\d{2})\b/g,
17866
+ (_m, y, mo) => yearOnly ? y : `${seasonFor(Number(mo))} ${y}`
17867
+ );
17868
+ out = out.replace(/\b(\d{1,2})\/(\d{1,2})\/(\d{4})\b/g, (_m, mo, _d, y) => {
17869
+ const m = Number(mo);
17870
+ if (yearOnly || m < 1 || m > 12) return y;
17871
+ return `${seasonFor(m)} ${y}`;
17872
+ });
17873
+ out = out.replace(
17874
+ /\b(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)[a-z]*\.?\s+(\d{4})\b/gi,
17875
+ (_m, mon, y) => {
17876
+ const monNum = MONTHS[mon.slice(0, 3).toLowerCase()];
17877
+ return yearOnly || !monNum ? y : `${seasonFor(monNum)} ${y}`;
17878
+ }
17879
+ );
17880
+ return out;
17881
+ }
17882
+
17883
+ // ../../packages/canonical/src/scrub.ts
17884
+ init_src();
17885
+ var API_KEY_PATTERNS = [
17886
+ { name: "sk-ant-key", re: /\bsk-ant-[a-zA-Z0-9_\-]{30,}\b/g },
17887
+ { name: "openai-key", re: /\bsk-[a-zA-Z0-9_\-]{30,}\b/g },
17888
+ { name: "github-pat", re: /\bgh[psour]_[A-Za-z0-9]{36,}\b/g },
17889
+ { name: "aws-key", re: /\bAKIA[0-9A-Z]{16}\b/g },
17890
+ { name: "google-key", re: /\bAIza[0-9A-Za-z\-_]{35}\b/g },
17891
+ { name: "stripe-key", re: /\b(sk|pk)_(test|live)_[0-9a-zA-Z]{24,}\b/g },
17892
+ { name: "bearer", re: /\bBearer\s+[A-Za-z0-9_\-\.]{16,}\b/gi }
17893
+ ];
17894
+ var EMAIL_RE = /\b[A-Za-z0-9._%+\-]+@[A-Za-z0-9.\-]+\.[A-Za-z]{2,}\b/g;
17895
+ var IPV4_RE = /\b(?:\d{1,3}\.){3}\d{1,3}\b/g;
17896
+ var IPV6_RE = /\b(?:[A-Fa-f0-9]{1,4}:){2,7}[A-Fa-f0-9:]{1,4}\b/g;
17897
+ var WIN_PATH_RE = /\b[A-Za-z]:[\\/](?![\\/])(?:[^\\/\s"']+[\\/])*[^\\/\s"']*/g;
17898
+ var WIN_UNC_RE = /\\\\[A-Za-z0-9_\-]+\\[A-Za-z0-9_\-$]+(?:\\[^\\\s"']+)*/g;
17899
+ var POSIX_USER_PATH_RE = /\/(?:Users|home)\/[A-Za-z0-9_\-\.]+(?:\/[^"'\s)]+)*/g;
17900
+ var LONG_HASH_RE = /\b[a-fA-F0-9]{24,}\b/g;
17901
+ var UUID_RE = /\b[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\b/g;
17902
+ function scrub(input) {
17903
+ let text = input;
17904
+ const found = [];
17905
+ const bump = (kind, replaced) => {
17906
+ const ex = found.find((f) => f.kind === kind && f.replaced === replaced);
17907
+ if (ex) ex.count++;
17908
+ else found.push({ kind, replaced, count: 1 });
17909
+ };
17910
+ for (const p of API_KEY_PATTERNS) {
17911
+ text = text.replace(p.re, (m) => {
17912
+ const id = sha256Short(m, 6);
17913
+ bump("api-key", `<api-key:${id}>`);
17914
+ return `<api-key:${id}>`;
17915
+ });
17916
+ }
17917
+ text = text.replace(EMAIL_RE, (m) => {
17918
+ const id = sha256Short(m, 6);
17919
+ bump("email", `<email:${id}>`);
17920
+ return `<email:${id}>`;
17921
+ });
17922
+ text = text.replace(WIN_UNC_RE, (m) => {
17923
+ const id = sha256Short(m, 6);
17924
+ bump("windows-path", `<unc:${id}>`);
17925
+ return `<unc:${id}>`;
17926
+ });
17927
+ text = text.replace(WIN_PATH_RE, (m) => {
17928
+ const file2 = m.split(/[\\/]/).pop() ?? "";
17929
+ const id = sha256Short(m, 6);
17930
+ const repl = file2 && file2.includes(".") ? `<path:${id}>/${file2}` : `<path:${id}>`;
17931
+ bump("absolute-path", repl);
17932
+ return repl;
17933
+ });
17934
+ text = text.replace(POSIX_USER_PATH_RE, (m) => {
17935
+ const file2 = m.split("/").pop() ?? "";
17936
+ const id = sha256Short(m, 6);
17937
+ const repl = file2 && file2.includes(".") ? `<path:${id}>/${file2}` : `<path:${id}>`;
17938
+ bump("home-dir", repl);
17939
+ return repl;
17940
+ });
17941
+ text = text.replace(IPV4_RE, (m) => {
17942
+ bump("ipv4", "<ipv4>");
17943
+ return "<ipv4>";
17944
+ });
17945
+ text = text.replace(IPV6_RE, (m) => {
17946
+ bump("ipv6", "<ipv6>");
17947
+ return "<ipv6>";
17948
+ });
17949
+ text = text.replace(UUID_RE, (m) => {
17950
+ bump("uuid", "<uuid>");
17951
+ return "<uuid>";
17952
+ });
17953
+ text = text.replace(LONG_HASH_RE, (m) => {
17954
+ bump("long-hash", "<hash>");
17955
+ return "<hash>";
17956
+ });
17957
+ return { text, report: { found } };
17958
+ }
17959
+
17960
+ // ../../packages/privacy-edge/src/self-reference.ts
17961
+ var L = "(?<![A-Za-z0-9])";
17962
+ var R = "(?![A-Za-z0-9])";
17963
+ var esc2 = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
17964
+ function locatorTerms(loc, full, part) {
17965
+ if (!loc) return;
17966
+ full.add(loc);
17967
+ const segs = loc.split("/").filter(Boolean);
17968
+ if (segs.length >= 2) {
17969
+ part.add(segs[segs.length - 1]);
17970
+ part.add(segs[segs.length - 2]);
17971
+ }
17972
+ }
17973
+ function scrubSelfReferences(text, project) {
17974
+ let out = text;
17975
+ out = out.replace(
17976
+ /\b(MRs?|PRs?|merge requests?|pull requests?|issues?|tickets?)\s+#?[0-9]+\b/gi,
17977
+ (_m, kind) => {
17978
+ const k = kind.toLowerCase();
17979
+ if (k.startsWith("p")) return "a pull request";
17980
+ if (k.startsWith("i")) return "an issue";
17981
+ if (k.startsWith("t")) return "a ticket";
17982
+ return "a merge request";
17983
+ }
17984
+ ).replace(new RegExp(`${L}![0-9]{1,6}(?![0-9])`, "g"), "a merge request").replace(new RegExp(`(?<![A-Za-z0-9#])#[0-9]{2,6}(?![0-9])`, "g"), "an issue");
17985
+ const full = /* @__PURE__ */ new Set();
17986
+ const part = /* @__PURE__ */ new Set();
17987
+ locatorTerms(project.repoLocator, full, part);
17988
+ for (const a of project.aliases ?? []) locatorTerms(a, full, part);
17989
+ if (project.name) part.add(project.name);
17990
+ for (const a of project.aka ?? []) part.add(a);
17991
+ const ordered = [
17992
+ ...[...full].map((t) => ({ t, repl: "the repository" })),
17993
+ ...[...part].map((t) => ({ t, repl: "the project" }))
17994
+ ].filter((x) => x.t && x.t.length >= 2).sort((a, b) => b.t.length - a.t.length);
17995
+ for (const { t, repl } of ordered) {
17996
+ out = out.replace(new RegExp(`${L}${esc2(t)}${R}`, "gi"), repl);
17997
+ }
17998
+ out = out.replace(/\b(the|a|an|its|our|this)\s+the\s+(project|repository)\b/gi, "the $2");
17999
+ return out;
18000
+ }
18001
+
18002
+ // ../../packages/privacy-edge/src/generalize.ts
18003
+ var TOKEN_RULES = [
18004
+ { re: /<api-key:[0-9a-f]+>/gi, cls: "credential" },
18005
+ { re: /<email:[0-9a-f]+>/gi, cls: "email" },
18006
+ { re: /<unc:[0-9a-f]+>/gi, cls: "path" },
18007
+ { re: /<path:[0-9a-f]+>\/[^\s)"']+/gi, cls: "file" },
18008
+ // path + preserved filename
18009
+ { re: /<path:[0-9a-f]+>/gi, cls: "path" },
18010
+ { re: /<ipv4>|<ipv6>/gi, cls: "ip" },
18011
+ { re: /<uuid>/gi, cls: "uuid" },
18012
+ { re: /<hash>/gi, cls: "hash" }
18013
+ ];
18014
+ function generalize(text, opts = {}) {
18015
+ const level = opts.level ?? 1;
18016
+ const seen = /* @__PURE__ */ new Set();
18017
+ let out = generalizeDates(text, level);
18018
+ out = scrub(out).text;
18019
+ for (const { re, cls } of TOKEN_RULES) {
18020
+ out = out.replace(re, () => {
18021
+ seen.add(cls);
18022
+ return generalizePhrase(cls, level);
18023
+ });
18024
+ }
18025
+ if (opts.project) out = scrubSelfReferences(out, opts.project);
18026
+ return { text: out, report: { level, classes: [...seen] } };
18027
+ }
18028
+
18029
+ // src/instance-ingest.ts
18030
+ init_src();
18031
+
18032
+ // src/contribution-ready.ts
18033
+ function cosine2(a, b) {
18034
+ if (a.length === 0 || a.length !== b.length) return 0;
18035
+ let dot = 0;
18036
+ let na = 0;
18037
+ let nb = 0;
18038
+ for (let i = 0; i < a.length; i++) {
18039
+ dot += a[i] * b[i];
18040
+ na += a[i] * a[i];
18041
+ nb += b[i] * b[i];
18042
+ }
18043
+ return na === 0 || nb === 0 ? 0 : dot / (Math.sqrt(na) * Math.sqrt(nb));
18044
+ }
18045
+ function noveltyAgainst(node, neighbors, opts = {}) {
18046
+ const floor = opts.dedupCosine ?? NEMORI_DEDUP_COSINE;
18047
+ const emb = node.embedding ?? [];
18048
+ if (emb.length === 0) {
18049
+ return { ready: true, surprise: 1, topCosine: 0, reason: "no-embedding (fidelity-first)" };
18050
+ }
18051
+ let topCosine = 0;
18052
+ for (const other of neighbors) {
18053
+ if (other.id === node.id) continue;
18054
+ const oe = other.embedding ?? [];
18055
+ if (oe.length !== emb.length) continue;
18056
+ const c = cosine2(emb, oe);
18057
+ if (c > topCosine) topCosine = c;
18058
+ }
18059
+ const ready = topCosine < floor;
18060
+ return {
18061
+ ready,
18062
+ surprise: 1 - topCosine,
18063
+ topCosine,
18064
+ reason: ready ? "novel (not a near-duplicate)" : "near-duplicate of a reference node"
18065
+ };
18066
+ }
18067
+
18068
+ // src/profile.ts
18069
+ import { createHash as createHash2 } from "node:crypto";
18070
+ init_src2();
18071
+
18072
+ // ../../node_modules/.pnpm/env-paths@3.0.0/node_modules/env-paths/index.js
18073
+ import os from "node:os";
18074
+ import process3 from "node:process";
18075
+ var homedir = os.homedir();
18076
+ var tmpdir = os.tmpdir();
18077
+ var { env } = process3;
18078
+
18079
+ // src/git-remote.ts
18080
+ init_src();
18081
+
18082
+ // src/profile.ts
18083
+ function sessionOriginKey(sessionId) {
18084
+ if (!sessionId) return void 0;
18085
+ return "ws_" + createHash2("sha256").update(sessionId).digest("hex").slice(0, 12);
18086
+ }
18087
+
18088
+ // src/public-symbols.ts
18089
+ import { readFileSync, readdirSync, existsSync } from "node:fs";
18090
+ import { join } from "node:path";
18091
+ var HEAD_BYTES = 8 * 1024;
18092
+ var INDEX_TTL_MS = 10 * 60 * 1e3;
18093
+ var MIN_SYMBOL_LEN = 4;
18094
+ function isNameShapedSymbol(name) {
18095
+ return /[A-Z0-9_$]/.test(name);
18096
+ }
18097
+ var NAMED_IMPORT_RE = /import\s+(?:type\s+)?(.+?)\s+from\s+['"]([^'"]+)['"]/g;
18098
+ var REQUIRE_RE = /(?:const|let|var)\s+(.+?)\s*=\s*require\(\s*['"]([^'"]+)['"]\s*\)/g;
18099
+ function isBareExternal(spec, internalNames) {
18100
+ if (spec.startsWith(".") || spec.startsWith("/") || spec.startsWith("node:")) return false;
18101
+ const pkg = spec.startsWith("@") ? spec.split("/").slice(0, 2).join("/") : spec.split("/")[0];
18102
+ return !internalNames.has(pkg);
18103
+ }
18104
+ function bindingNames(clause) {
18105
+ const names = [];
18106
+ const braced = /\{([^}]*)\}/.exec(clause);
18107
+ if (braced) {
18108
+ for (const part of braced[1].split(",")) {
18109
+ const local = part.split(/\s+as\s+/).pop()?.trim();
18110
+ if (local && /^[A-Za-z_$][\w$]*$/.test(local)) names.push(local);
18111
+ }
18112
+ }
18113
+ const ns = /\*\s+as\s+([A-Za-z_$][\w$]*)/.exec(clause);
18114
+ if (ns) names.push(ns[1]);
18115
+ const head = clause.replace(/\{[^}]*\}/, "").replace(/\*\s+as\s+[A-Za-z_$][\w$]*/, "");
18116
+ const def = /(?:^|,)\s*([A-Za-z_$][\w$]*)\s*(?:,|$)/.exec(head.trim());
18117
+ if (def) names.push(def[1]);
18118
+ return names;
18119
+ }
18120
+ function internalPackageNames(workspaceRoot) {
18121
+ const names = /* @__PURE__ */ new Set();
18122
+ const tryRead = (dir) => {
18123
+ const pj = join(dir, "package.json");
18124
+ if (!existsSync(pj)) return;
18125
+ try {
18126
+ const name = JSON.parse(readFileSync(pj, "utf8")).name;
18127
+ if (typeof name === "string" && name.length > 0) names.add(name);
18128
+ } catch {
18129
+ }
18130
+ };
18131
+ tryRead(workspaceRoot);
18132
+ for (const group of ["packages", "apps"]) {
18133
+ const groupDir = join(workspaceRoot, group);
18134
+ if (!existsSync(groupDir)) continue;
18135
+ try {
18136
+ for (const entry of readdirSync(groupDir)) tryRead(join(groupDir, entry));
18137
+ } catch {
18138
+ }
18139
+ }
18140
+ return names;
18141
+ }
18142
+ var cache = /* @__PURE__ */ new Map();
18143
+ function publicSymbolIndex(store, workspaceRoot, deps = {}) {
18144
+ const now = deps.nowMs ?? Date.now();
18145
+ const cached2 = cache.get(workspaceRoot);
18146
+ if (cached2 && now - cached2.builtAt < INDEX_TTL_MS) return cached2;
18147
+ const readHead = deps.readHead ?? ((absPath) => {
18148
+ try {
18149
+ return readFileSync(absPath, "utf8").slice(0, HEAD_BYTES);
18150
+ } catch {
18151
+ return "";
18152
+ }
18153
+ });
18154
+ const internal = internalPackageNames(workspaceRoot);
18155
+ const bareModules = /* @__PURE__ */ new Set();
18156
+ for (const mod of store.findNodesByLabel("Module")) {
18157
+ if (isBareExternal(mod.description, internal)) bareModules.add(mod.id);
18158
+ }
18159
+ const files = /* @__PURE__ */ new Set();
18160
+ for (const modId of bareModules) {
18161
+ for (const e of store.inEdges(modId, ["IMPORTS"])) {
18162
+ const f = store.getNode(e.from);
18163
+ const rel = f?.attrs["relPath"];
18164
+ if (f && f.validTo == null && typeof rel === "string") files.add(rel);
18165
+ }
18166
+ }
18167
+ const symbols = /* @__PURE__ */ new Set();
18168
+ for (const rel of files) {
18169
+ const head = readHead(join(workspaceRoot, rel));
18170
+ if (!head) continue;
18171
+ for (const re of [NAMED_IMPORT_RE, REQUIRE_RE]) {
18172
+ re.lastIndex = 0;
18173
+ for (const m of head.matchAll(re)) {
18174
+ if (!isBareExternal(m[2], internal)) continue;
18175
+ for (const name of bindingNames(m[1])) {
18176
+ if (name.length >= MIN_SYMBOL_LEN && isNameShapedSymbol(name)) symbols.add(name);
18177
+ }
18178
+ }
18179
+ }
18180
+ }
18181
+ const index = { symbols, builtAt: now };
18182
+ cache.set(workspaceRoot, index);
18183
+ return index;
18184
+ }
18185
+ var PRESERVED_SYMBOLS_CAP = 8;
18186
+ function preservedSymbolsFor(description, index) {
18187
+ const out = [];
18188
+ const seen = /* @__PURE__ */ new Set();
18189
+ for (const m of description.matchAll(/[A-Za-z_$][\w$]{3,}/g)) {
18190
+ const tok = m[0];
18191
+ if (seen.has(tok) || !index.symbols.has(tok)) continue;
18192
+ seen.add(tok);
18193
+ out.push(tok);
18194
+ if (out.length >= PRESERVED_SYMBOLS_CAP) break;
18195
+ }
18196
+ return out;
18197
+ }
18198
+ function internalSymbolsFor(description, lexiconHas, publicIndex) {
18199
+ const out = [];
18200
+ const seen = /* @__PURE__ */ new Set();
18201
+ for (const m of description.matchAll(/[A-Za-z_$][\w$]{2,}(?:\.[A-Za-z_$][\w$]+)*/g)) {
18202
+ const tok = m[0];
18203
+ if (seen.has(tok)) continue;
18204
+ seen.add(tok);
18205
+ if (!lexiconHas(tok)) continue;
18206
+ if (publicIndex?.symbols.has(tok)) continue;
18207
+ out.push(tok);
18208
+ if (out.length >= PRESERVED_SYMBOLS_CAP) break;
18209
+ }
18210
+ return out;
18211
+ }
18212
+
18213
+ // src/generalize-graph.ts
18214
+ init_src();
18215
+
18216
+ // src/derive-summary.ts
18217
+ var NAME_DERIVED_ENABLED = true;
18218
+ var KIND_ARTICLE = {
18219
+ function: "a",
18220
+ method: "a",
18221
+ class: "a",
18222
+ interface: "an",
18223
+ constant: "a"
18224
+ };
18225
+ var lead = (kind) => `${KIND_ARTICLE[kind]} ${kind}`;
18226
+ var MAX_PAYLOAD_CHARS = 56;
18227
+ var DANGLING = /* @__PURE__ */ new Set([
18228
+ "a",
18229
+ "an",
18230
+ "the",
18231
+ "and",
18232
+ "or",
18233
+ "but",
18234
+ "of",
18235
+ "to",
18236
+ "in",
18237
+ "on",
18238
+ "at",
18239
+ "by",
18240
+ "for",
18241
+ "from",
18242
+ "with",
18243
+ "into",
18244
+ "onto",
18245
+ "over",
18246
+ "under",
18247
+ "as",
18248
+ "that",
18249
+ "which",
18250
+ "when",
18251
+ "while",
18252
+ "if",
18253
+ "so",
18254
+ "then",
18255
+ "than",
18256
+ "its",
18257
+ "their",
18258
+ "this",
18259
+ "these",
18260
+ "those",
18261
+ "is",
18262
+ "are",
18263
+ "was",
18264
+ "be",
18265
+ "been",
18266
+ "not",
18267
+ "no",
18268
+ "per",
18269
+ "via",
18270
+ "up",
18271
+ "out",
18272
+ "off",
18273
+ "about",
18274
+ "after",
18275
+ "before",
18276
+ "during",
18277
+ "without",
18278
+ "within",
18279
+ "against",
18280
+ "between",
18281
+ "through",
18282
+ "across",
18283
+ "upon"
18284
+ ]);
18285
+ var VERBS = /* @__PURE__ */ new Set([
18286
+ "accept",
18287
+ "add",
18288
+ "advance",
18289
+ "allow",
18290
+ "apply",
18291
+ "assert",
18292
+ "attach",
18293
+ "bind",
18294
+ "build",
18295
+ "bump",
18296
+ "cache",
18297
+ "call",
18298
+ "cap",
18299
+ "carry",
18300
+ "check",
18301
+ "choose",
18302
+ "clamp",
18303
+ "classify",
18304
+ "clean",
18305
+ "clear",
18306
+ "close",
18307
+ "collapse",
18308
+ "collect",
18309
+ "compare",
18310
+ "compute",
18311
+ "connect",
18312
+ "contain",
18313
+ "convert",
18314
+ "count",
18315
+ "cover",
18316
+ "create",
18317
+ "decide",
18318
+ "declare",
18319
+ "decode",
18320
+ "define",
18321
+ "delete",
18322
+ "demote",
18323
+ "derive",
18324
+ "describe",
18325
+ "detach",
18326
+ "detect",
18327
+ "determine",
18328
+ "disable",
18329
+ "drain",
18330
+ "drop",
18331
+ "emit",
18332
+ "enable",
18333
+ "encode",
18334
+ "ensure",
18335
+ "enqueue",
18336
+ "evaluate",
18337
+ "expand",
18338
+ "expose",
18339
+ "extend",
18340
+ "extract",
18341
+ "fetch",
18342
+ "fill",
18343
+ "filter",
18344
+ "find",
18345
+ "fire",
18346
+ "fix",
18347
+ "flag",
18348
+ "flatten",
18349
+ "flip",
18350
+ "flush",
18351
+ "fold",
18352
+ "format",
18353
+ "gate",
18354
+ "gather",
18355
+ "generate",
18356
+ "get",
18357
+ "give",
18358
+ "grant",
18359
+ "guard",
18360
+ "handle",
18361
+ "hash",
18362
+ "hide",
18363
+ "hold",
18364
+ "hook",
18365
+ "index",
18366
+ "infer",
18367
+ "initialize",
18368
+ "insert",
18369
+ "inspect",
18370
+ "join",
18371
+ "keep",
18372
+ "limit",
18373
+ "link",
18374
+ "list",
18375
+ "load",
18376
+ "locate",
18377
+ "log",
18378
+ "make",
18379
+ "map",
18380
+ "mark",
18381
+ "match",
18382
+ "materialize",
18383
+ "measure",
18384
+ "merge",
18385
+ "mint",
18386
+ "mount",
18387
+ "move",
18388
+ "name",
18389
+ "normalize",
18390
+ "note",
18391
+ "observe",
18392
+ "open",
18393
+ "package",
18394
+ "parse",
18395
+ "persist",
18396
+ "pick",
18397
+ "pop",
18398
+ "populate",
18399
+ "prepare",
18400
+ "produce",
18401
+ "promote",
18402
+ "prune",
18403
+ "publish",
18404
+ "pull",
18405
+ "push",
18406
+ "query",
18407
+ "queue",
18408
+ "raise",
18409
+ "rank",
18410
+ "read",
18411
+ "rebuild",
18412
+ "record",
18413
+ "recover",
18414
+ "redact",
18415
+ "reduce",
18416
+ "refresh",
18417
+ "register",
18418
+ "reject",
18419
+ "release",
18420
+ "remove",
18421
+ "rename",
18422
+ "render",
18423
+ "repair",
18424
+ "replace",
18425
+ "replay",
18426
+ "report",
18427
+ "represent",
18428
+ "require",
18429
+ "reset",
18430
+ "resolve",
18431
+ "restore",
18432
+ "retire",
18433
+ "retry",
18434
+ "return",
18435
+ "reveal",
18436
+ "revive",
18437
+ "rewrite",
18438
+ "route",
18439
+ "run",
18440
+ "sanitize",
18441
+ "save",
18442
+ "scan",
18443
+ "schedule",
18444
+ "score",
18445
+ "scrub",
18446
+ "seed",
18447
+ "select",
18448
+ "send",
18449
+ "serialize",
18450
+ "serve",
18451
+ "set",
18452
+ "show",
18453
+ "sign",
18454
+ "skip",
18455
+ "sort",
18456
+ "split",
18457
+ "stamp",
18458
+ "start",
18459
+ "stop",
18460
+ "store",
18461
+ "strip",
18462
+ "summarize",
18463
+ "supply",
18464
+ "suppress",
18465
+ "sweep",
18466
+ "switch",
18467
+ "sync",
18468
+ "tag",
18469
+ "take",
18470
+ "test",
18471
+ "throw",
18472
+ "toggle",
18473
+ "touch",
18474
+ "trace",
18475
+ "track",
18476
+ "transform",
18477
+ "translate",
18478
+ "traverse",
18479
+ "trigger",
18480
+ "trim",
18481
+ "turn",
18482
+ "unwrap",
18483
+ "update",
18484
+ "upsert",
18485
+ "validate",
18486
+ "verify",
18487
+ "walk",
18488
+ "warn",
18489
+ "watch",
18490
+ "wire",
18491
+ "wrap",
18492
+ "write",
18493
+ "yield"
18494
+ ]);
18495
+ function inflect(verb) {
18496
+ if (/(?:s|x|ch|sh|z)$/.test(verb)) return `${verb}es`;
18497
+ if (/[^aeiou]y$/.test(verb)) return `${verb.slice(0, -1)}ies`;
18498
+ return `${verb}s`;
18499
+ }
18500
+ function deinflect(word) {
18501
+ if (word.endsWith("ies") && VERBS.has(`${word.slice(0, -3)}y`)) return `${word.slice(0, -3)}y`;
18502
+ if (word.endsWith("es") && VERBS.has(word.slice(0, -2))) return word.slice(0, -2);
18503
+ if (word.endsWith("s") && VERBS.has(word.slice(0, -1))) return word.slice(0, -1);
18504
+ return null;
18505
+ }
18506
+ function verbHead(word) {
18507
+ const w = word.toLowerCase().replace(/[^a-z]/g, "");
18508
+ if (!w) return null;
18509
+ if (VERBS.has(w)) return inflect(w);
18510
+ return deinflect(w) !== null ? w : null;
18511
+ }
18512
+ var tidy = (s) => s.replace(/\s+/g, " ").replace(/\s+([,.;:])/g, "$1").replace(/[\s,;:.]+$/, "").trim();
18513
+ function identifierWords(name) {
18514
+ return name.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").replace(/[_$]+/g, " ").toLowerCase().split(/\s+/).filter(Boolean);
18515
+ }
18516
+ function clipClause(text) {
18517
+ let t = tidy(text.split(/\s+[—–-]\s+|[:;(]|,|\s+(?:and|or|plus)\s+|\s\+\s/)[0] ?? "");
18518
+ if (t.length > MAX_PAYLOAD_CHARS) {
18519
+ const cut = t.slice(0, MAX_PAYLOAD_CHARS).lastIndexOf(" ");
18520
+ if (cut <= 20) return null;
18521
+ t = tidy(t.slice(0, cut));
18522
+ }
18523
+ const words = t.split(/\s+/);
18524
+ while (words.length > 0 && DANGLING.has(words[words.length - 1].toLowerCase().replace(/[^a-z]/g, ""))) {
18525
+ words.pop();
18526
+ }
18527
+ const out = tidy(words.join(" "));
18528
+ return out.length >= 12 && out.split(/\s+/).length >= 2 ? out : null;
18529
+ }
18530
+ function firstSentence(doc) {
18531
+ const clean = doc.replace(/^[\s*/]+/gm, " ").replace(/\s+/g, " ").trim();
18532
+ const m = clean.match(/^(.{10,400}?[.!?])(\s|$)/);
18533
+ return (m ? m[1] : clean).slice(0, 280);
18534
+ }
18535
+ function stripUnshippable(sentence) {
18536
+ return sentence.replace(/`[^`]*`|"[^"]*"|'[^']{2,}'/g, " ").replace(/[\w.~-]+[/\\][\w.$~-]+/g, " ").replace(/\([^)]*\)/g, " ");
18537
+ }
18538
+ function summaryFromDoc(doc, kind) {
18539
+ const clipped = clipClause(stripUnshippable(firstSentence(doc)).replace(/^[^A-Za-z]+/, ""));
18540
+ if (clipped === null) return null;
18541
+ const words = clipped.split(/\s+/);
18542
+ const verb = verbHead(words[0]);
18543
+ if (verb !== null && words.length > 1) {
18544
+ return tidy(`${lead(kind)} that ${verb} ${words.slice(1).join(" ")}`);
18545
+ }
18546
+ if (verb !== null) return null;
18547
+ const noun = clipped.replace(/^(?:the|a|an)\s+/i, "");
18548
+ return tidy(`${lead(kind)} for ${noun.charAt(0).toLowerCase()}${noun.slice(1)}`);
18549
+ }
18550
+ var VERB_PHRASE_KINDS = /* @__PURE__ */ new Set(["function", "method"]);
18551
+ function summaryFromName(name, kind) {
18552
+ if (!NAME_DERIVED_ENABLED) return null;
18553
+ const words = identifierWords(name);
18554
+ while (words.length > 1 && DANGLING.has(words[words.length - 1])) words.pop();
18555
+ if (words.length === 0) return null;
18556
+ const verb = VERB_PHRASE_KINDS.has(kind) ? verbHead(words[0]) : null;
18557
+ const rest = words.slice(1).join(" ");
18558
+ const phrase = verb !== null && rest ? `${lead(kind)} that ${verb} the ${rest}` : verb !== null ? null : `${lead(kind)} for the ${words.join(" ")}`;
18559
+ if (phrase === null) return null;
18560
+ const trimmed = tidy(phrase);
18561
+ return trimmed.length <= MAX_PAYLOAD_CHARS + 24 ? trimmed : null;
18562
+ }
18563
+ function summaryCandidates(name, kind, doc) {
18564
+ const candidates = [];
18565
+ const fromDoc = doc ? summaryFromDoc(doc, kind) : null;
18566
+ if (fromDoc !== null) candidates.push(fromDoc);
18567
+ const fromName = summaryFromName(name, kind);
18568
+ if (fromName !== null && fromName !== fromDoc) candidates.push(fromName);
18569
+ return candidates;
18570
+ }
18571
+
18572
+ // src/generalize-graph.ts
18573
+ var SYMBOL_LABELS = [
18574
+ ["Function", "function"],
18575
+ ["Method", "method"],
18576
+ ["Class", "class"],
18577
+ ["Interface", "interface"],
18578
+ ["Const", "constant"]
18579
+ ];
18580
+ var BUILTIN_TYPE_NAMES = /* @__PURE__ */ new Set([
18581
+ "Array",
18582
+ "Boolean",
18583
+ "Buffer",
18584
+ "Date",
18585
+ "Error",
18586
+ "Function",
18587
+ "Map",
18588
+ "Math",
18589
+ "Number",
18590
+ "Object",
18591
+ "Promise",
18592
+ "Proxy",
18593
+ "RegExp",
18594
+ "Set",
18595
+ "String",
18596
+ "Symbol",
18597
+ "WeakMap",
18598
+ "WeakSet",
18599
+ "TypeError",
18600
+ "RangeError",
18601
+ "SyntaxError",
18602
+ "URL",
18603
+ "Request",
18604
+ "Response",
18605
+ "Headers"
18606
+ ]);
18607
+ function isDistinctiveIdentifier(name) {
18608
+ if (name.length < 3) return false;
18609
+ if (/[\s:]/.test(name)) return false;
18610
+ if (BUILTIN_TYPE_NAMES.has(name)) return false;
18611
+ if (name.includes(".") || name.includes("_") || /\d/.test(name)) return true;
18612
+ if (/[a-z][A-Z]/.test(name)) return true;
18613
+ if (/^[A-Z]/.test(name) && /[a-z]/.test(name) && name.length >= 4) return true;
18614
+ return false;
18615
+ }
18616
+ var DOC_COMMENT_KINDS = /* @__PURE__ */ new Set(["docstring", "explanation"]);
18617
+ var MAX_DOC_CHARS = 600;
18618
+ function buildDocIndex(store) {
18619
+ const byName = /* @__PURE__ */ new Map();
18620
+ for (const c of store.findNodesByLabel("Comment")) {
18621
+ const name = c.attrs["attachedTo"];
18622
+ const kind = c.attrs["kind"];
18623
+ if (typeof name !== "string" || !name) continue;
18624
+ if (typeof kind !== "string" || !DOC_COMMENT_KINDS.has(kind)) continue;
18625
+ const text = typeof c.attrs["text"] === "string" ? c.attrs["text"] : c.description;
18626
+ if (!text?.trim()) continue;
18627
+ if (!byName.has(name)) byName.set(name, text.trim().slice(0, MAX_DOC_CHARS));
18628
+ }
18629
+ return byName;
18630
+ }
18631
+ function buildSymbolLexicon(store) {
18632
+ const lex = /* @__PURE__ */ new Map();
18633
+ const docs = buildDocIndex(store);
18634
+ const candidates = [];
18635
+ for (const [label, kind] of SYMBOL_LABELS) {
18636
+ for (const n of store.findNodesByLabel(label)) {
18637
+ const qname = String(n.attrs["qname"] ?? "");
18638
+ const doc = (n.description ? docs.get(n.description) : void 0) ?? (qname ? docs.get(qname) : void 0);
18639
+ for (const name of [n.description, qname]) {
18640
+ if (name && isDistinctiveIdentifier(name) && !lex.has(name)) {
18641
+ lex.set(name, { kind });
18642
+ candidates.push([name, kind, doc]);
18643
+ }
18644
+ }
18645
+ }
18646
+ }
18647
+ const isKnown = (tok) => lex.has(tok);
18648
+ for (const [name, kind, doc] of candidates) {
18649
+ for (const phrase of summaryCandidates(name, kind, doc)) {
18650
+ if (summaryRejectionReason(phrase, isKnown) === null) {
18651
+ lex.get(name).summary = phrase;
18652
+ break;
18653
+ }
18654
+ }
18655
+ }
18656
+ return lex;
18657
+ }
18658
+ var RE_RESERVED = /[.*+?^${}()|[\]\\]/g;
18659
+ var escapeRe2 = (s) => s.replace(RE_RESERVED, "\\$&");
18660
+ var RE_LEADING_ARTICLE = /^(?:an?|the)\s/i;
18661
+ function replaceWithPhrase(text, before, escapedKey, after, phrase) {
18662
+ if (!RE_LEADING_ARTICLE.test(phrase)) {
18663
+ return text.replace(new RegExp(`${before}${escapedKey}${after}`, "g"), phrase);
18664
+ }
18665
+ const re = new RegExp(`${before}${String.raw`(?:(An|an|A|a|The|the)\s+)?`}${escapedKey}${after}`, "g");
18666
+ return text.replace(
18667
+ re,
18668
+ (_match, article) => article !== void 0 && /^[A-Z]/.test(article) ? phrase.charAt(0).toUpperCase() + phrase.slice(1) : phrase
18669
+ );
18670
+ }
18671
+ function isBareMatchableStem(stem) {
18672
+ return stem.length >= 5 && /^[A-Za-z0-9]+(?:[-_][A-Za-z0-9]+)+$/.test(stem);
18673
+ }
18674
+ var CONVENTION_FILENAMES = /* @__PURE__ */ new Set([
18675
+ "package.json",
18676
+ "package-lock.json",
18677
+ "pnpm-lock.yaml",
18678
+ "pnpm-workspace.yaml",
18679
+ "yarn.lock",
18680
+ "tsconfig.json",
18681
+ "tsconfig.base.json",
18682
+ "turbo.json",
18683
+ "README.md",
18684
+ "LICENSE",
18685
+ "CHANGELOG.md",
18686
+ "CONTRIBUTING.md",
18687
+ // agent-config conventions — as cross-repo universal as README.md by 2026
18688
+ "AGENTS.md",
18689
+ "CLAUDE.md",
18690
+ "Dockerfile",
18691
+ "docker-compose.yml",
18692
+ ".gitignore",
18693
+ ".env",
18694
+ ".env.example",
18695
+ "index.ts",
18696
+ "index.js",
18697
+ "index.tsx",
18698
+ "index.mjs"
18699
+ ]);
18700
+ var CONVENTION_BASENAME_MIN_FILES = 3;
18701
+ var CONVENTION_STEMS = /* @__PURE__ */ new Set([
18702
+ "well-known",
18703
+ "read-only",
18704
+ "type-safe",
18705
+ "end-to-end",
18706
+ "fail-open",
18707
+ "fail-closed",
18708
+ "up-to-date",
18709
+ "server-side",
18710
+ "client-side",
18711
+ "cross-origin",
18712
+ "same-origin",
18713
+ "well-formed",
18714
+ "first-class",
18715
+ "in-memory",
18716
+ "single-page",
18717
+ "use-case",
18718
+ "out-of-band"
18719
+ ]);
18720
+ function buildFileLexicon(store) {
18721
+ const byKey = /* @__PURE__ */ new Map();
18722
+ const byBasename = /* @__PURE__ */ new Map();
18723
+ const byStem = /* @__PURE__ */ new Map();
18724
+ const basenameCount = /* @__PURE__ */ new Map();
18725
+ const stemRelPaths = /* @__PURE__ */ new Map();
18726
+ const entries = [];
18727
+ for (const n of store.findNodesByLabel("File")) {
18728
+ const relPath = typeof n.attrs["relPath"] === "string" && n.attrs["relPath"].length > 0 ? n.attrs["relPath"] : n.description;
18729
+ if (!relPath) continue;
18730
+ const basename = relPath.split("/").pop();
18731
+ if (!basename.includes(".")) continue;
18732
+ entries.push({ relPath, basename });
18733
+ basenameCount.set(basename, (basenameCount.get(basename) ?? 0) + 1);
18734
+ const stem = basename.slice(0, basename.indexOf("."));
18735
+ if (isBareMatchableStem(stem)) {
18736
+ let s = stemRelPaths.get(stem);
18737
+ if (!s) stemRelPaths.set(stem, s = /* @__PURE__ */ new Set());
18738
+ s.add(relPath);
18739
+ }
18740
+ }
18741
+ for (const { relPath, basename } of entries) {
18742
+ const entry = { relPath };
18743
+ if (relPath !== basename) byKey.set(relPath, entry);
18744
+ const conventional = CONVENTION_FILENAMES.has(basename) || (basenameCount.get(basename) ?? 0) >= CONVENTION_BASENAME_MIN_FILES;
18745
+ if (!conventional && !byKey.has(basename)) byKey.set(basename, entry);
18746
+ const list = byBasename.get(basename);
18747
+ if (list) list.push(entry);
18748
+ else byBasename.set(basename, [entry]);
18749
+ const stem = basename.slice(0, basename.indexOf("."));
18750
+ if (isBareMatchableStem(stem) && !CONVENTION_STEMS.has(stem) && !byStem.has(stem)) {
18751
+ const dirStems = new Set(
18752
+ [...stemRelPaths.get(stem) ?? []].map((p) => {
18753
+ const bn = p.split("/").pop();
18754
+ return p.slice(0, p.length - bn.length) + bn.slice(0, bn.indexOf("."));
18755
+ })
18756
+ );
18757
+ if (dirStems.size === 1) byStem.set(stem, entry);
18758
+ }
18759
+ }
18760
+ return { byKey, byBasename, byStem };
18761
+ }
18762
+ var FILE_TOKEN_RE = /(?:[A-Za-z0-9_.-]+\/)*[A-Za-z0-9_-][A-Za-z0-9_.-]*\.[A-Za-z0-9]+/g;
18763
+ function resolveFileToken(token, lexicon) {
18764
+ const exact = lexicon.byKey.get(token);
18765
+ if (exact) return exact;
18766
+ if (!token.includes("/")) return null;
18767
+ const basename = token.split("/").pop();
18768
+ for (const entry of lexicon.byBasename.get(basename) ?? []) {
18769
+ if (entry.relPath === token || entry.relPath.endsWith(`/${token}`)) return entry;
18770
+ }
18771
+ return null;
18772
+ }
18773
+ function internalFilesFor(description, lexicon) {
18774
+ const out = [];
18775
+ const seen = /* @__PURE__ */ new Set();
18776
+ for (const m of description.matchAll(FILE_TOKEN_RE)) {
18777
+ const tok = m[0];
18778
+ if (seen.has(tok)) continue;
18779
+ seen.add(tok);
18780
+ if (resolveFileToken(tok, lexicon)) out.push(tok);
18781
+ }
18782
+ return out;
18783
+ }
18784
+ function fileRolePhrase(relPath, level = 1) {
18785
+ if (level !== 1) return "a file";
18786
+ if (/\.(test|spec)\.|__tests__\/|(?:^|\/)e2e\//.test(relPath)) return "a test file";
18787
+ if (/(?:^|\/)scripts?\//.test(relPath)) return "a script";
18788
+ if (/\.md$/i.test(relPath)) return "a documentation file";
18789
+ if (/\.(json|ya?ml|toml|env)$/i.test(relPath)) return "a config file";
18790
+ return "a source file";
18791
+ }
18792
+ var STEM_TOKEN_RE = /[A-Za-z0-9]+(?:[-_][A-Za-z0-9]+)+/g;
18793
+ var SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([
18794
+ "ts",
18795
+ "tsx",
18796
+ "js",
18797
+ "jsx",
18798
+ "mjs",
18799
+ "cjs",
18800
+ "py",
18801
+ "go",
18802
+ "rs",
18803
+ "java",
18804
+ "kt",
18805
+ "rb",
18806
+ "c",
18807
+ "h",
18808
+ "cc",
18809
+ "cpp",
18810
+ "hpp",
18811
+ "cs",
18812
+ "php",
18813
+ "swift",
18814
+ "scala",
18815
+ "sh",
18816
+ "ps1",
18817
+ "sql",
18818
+ "css",
18819
+ "scss",
18820
+ "html",
18821
+ "vue",
18822
+ "svelte",
18823
+ "md",
18824
+ "json",
18825
+ "yaml",
18826
+ "yml",
18827
+ "toml",
18828
+ "ini",
18829
+ "env",
18830
+ "cypher"
18831
+ ]);
18832
+ function isSourceFileToken(token) {
18833
+ const basename = token.split(/[/\\]/).pop() ?? token;
18834
+ if (CONVENTION_FILENAMES.has(basename)) return false;
18835
+ const ext = basename.split(".").pop();
18836
+ return ext !== void 0 && SOURCE_EXTENSIONS.has(ext.toLowerCase());
18837
+ }
18838
+ function generalizeFileRefs(text, fileLexicon, level = 1) {
18839
+ let out = text;
18840
+ let lexiconMisses = 0;
18841
+ const files = [];
18842
+ const seenFiles = /* @__PURE__ */ new Set();
18843
+ for (const m of out.matchAll(FILE_TOKEN_RE)) {
18844
+ const tok = m[0];
18845
+ if (seenFiles.has(tok)) continue;
18846
+ seenFiles.add(tok);
18847
+ const entry = resolveFileToken(tok, fileLexicon);
18848
+ if (entry) files.push([tok, entry]);
18849
+ else if (isSourceFileToken(tok)) lexiconMisses++;
18850
+ }
18851
+ files.sort((a, b) => b[0].length - a[0].length);
18852
+ for (const [tok, entry] of files) {
18853
+ out = replaceWithPhrase(
18854
+ out,
18855
+ "(?<![\\w$/\\\\.-])",
18856
+ escapeRe2(tok),
18857
+ "(?![\\w$-])",
18858
+ fileRolePhrase(entry.relPath, level)
18859
+ );
18860
+ }
18861
+ const stems = [];
18862
+ const seenStems = /* @__PURE__ */ new Set();
18863
+ for (const m of out.matchAll(STEM_TOKEN_RE)) {
18864
+ const tok = m[0];
18865
+ if (seenStems.has(tok)) continue;
18866
+ seenStems.add(tok);
18867
+ const entry = fileLexicon.byStem.get(tok);
18868
+ if (entry) stems.push([tok, entry]);
18869
+ }
18870
+ stems.sort((a, b) => b[0].length - a[0].length);
18871
+ for (const [tok, entry] of stems) {
18872
+ out = replaceWithPhrase(
18873
+ out,
18874
+ "(?<![\\w$/\\\\.-])",
18875
+ escapeRe2(tok),
18876
+ "(?![\\w$/\\\\.-])",
18877
+ fileRolePhrase(entry.relPath, level)
18878
+ );
18879
+ }
18880
+ return { text: out, substitutions: files.length + stems.length, lexiconMisses };
18881
+ }
18882
+
18883
+ // src/instance-ingest.ts
18884
+ var INSTANCE_LABELS = ["Problem", "Solution", "RootCause"];
18885
+ var INSTANCE_EDGES = ["CAUSED_BY", "SOLVED_BY"];
18886
+ var ANCHOR_EDGES = ["OCCURS_IN", "DEPENDS_ON", "PERTAIN_TO", "CONCERNS"];
18887
+ var ANCHOR_TARGET_LABELS = ["Language", "Package", "Domain", "Component"];
18888
+ function stripCodebaseScope(scope) {
18889
+ const s = { ...scope ?? {} };
18890
+ delete s["codebase"];
18891
+ return s;
18892
+ }
18893
+ function contributedWireId(n) {
18894
+ const cloudId = n.attrs["cloudNodeId"];
18895
+ return isMembraneSaltedId(cloudId) ? cloudId : n.id;
18896
+ }
18897
+ var WIRE_CANONICAL_ID_MIN = 6;
18898
+ var SHIP_TERMINAL_REFUSALS = 3;
18899
+ function refusalFingerprint(reason, description) {
18900
+ return digest(`${reason}\0${description}`);
18901
+ }
18902
+ function isRetryableRefusal(reason) {
18903
+ return /\bretry\b/i.test(reason);
18904
+ }
18905
+ function isTerminallyRefused(n) {
18906
+ const reason = String(n.attrs["shipRefusedReason"] ?? "");
18907
+ return typeof n.attrs["shipRefusedCount"] === "number" && n.attrs["shipRefusedCount"] >= SHIP_TERMINAL_REFUSALS && !isRetryableRefusal(reason) && n.attrs["shipRefusedFingerprint"] === refusalFingerprint(reason, n.description);
18908
+ }
18909
+ function unshippableReason(canonical, label) {
18910
+ void label;
18911
+ if (canonical.length < WIRE_CANONICAL_ID_MIN) {
18912
+ return `canonicalId "${canonical}" is ${canonical.length} chars; the door requires >= ${WIRE_CANONICAL_ID_MIN}`;
18913
+ }
18914
+ return null;
18915
+ }
18916
+ function wireContextId(n) {
18917
+ if (n.label === "Language" && n.attrs["source"] !== "cloud") {
18918
+ const name = String(n.attrs["name"] ?? "").trim() || n.description.trim() || n.id.replace(/^lang:/, "");
18919
+ return languageCanonicalId(name);
18920
+ }
18921
+ if (n.label === "Domain" && n.attrs["source"] !== "cloud") {
18922
+ return String(n.attrs["canonicalId"] ?? n.id);
18923
+ }
18924
+ if (n.label === "Component" && n.attrs["source"] !== "cloud") {
18925
+ return String(n.attrs["canonicalId"] ?? n.id);
18926
+ }
18927
+ return n.id;
18928
+ }
18929
+ function langAnchor(t) {
18930
+ const name = String(t.attrs["name"] ?? "").trim() || t.description.trim() || t.id.replace(/^lang:/, "").trim();
18931
+ return name ? `lang:${name.toLowerCase()}` : void 0;
18932
+ }
18933
+ function shareableContext(n, wireId) {
18934
+ const attrs = n.label === "Package" ? {
18935
+ // No `version` attr: the purl encodes it, and the door's temporal
18936
+ // guard 422s any `attrs.version` (mirrors buildContextIngest).
18937
+ purl: n.attrs["purl"],
18938
+ name: n.attrs["name"],
18939
+ ecosystem: n.attrs["ecosystem"],
18940
+ resolved: n.attrs["resolved"]
18941
+ } : n.label === "Domain" ? { name: n.description, canonicalId: n.attrs["canonicalId"] } : n.label === "Component" ? { name: n.attrs["name"], canonicalId: n.attrs["canonicalId"] } : { name: n.attrs["name"] };
18942
+ return {
18943
+ ...n,
18944
+ id: wireId,
18945
+ embedding: [],
18946
+ attrs,
18947
+ ...n.label === "Package" ? { anchorVisibility: "public" } : {},
18948
+ ...n.label === "Language" && langAnchor(n) ? { anchorVisibility: "public", anchor: langAnchor(n) } : {},
18949
+ // A Component stub claims itself by slug (OM-agent-anchors) — the door
18950
+ // confirms only against an EXISTING public Component of that slug, so an
18951
+ // org-internal component name never crosses (fails closed to org).
18952
+ ...n.label === "Component" ? { anchorVisibility: "public", anchor: `component:${wireId}` } : {}
18953
+ };
18954
+ }
18955
+ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [], opts = {}) {
18956
+ const level = opts.level ?? 1;
18957
+ const noveltyOpts = opts.dedupCosine != null ? { dedupCosine: opts.dedupCosine } : {};
18958
+ const ignored = (text) => ignorePatterns.length > 0 && ignorePatterns.some((p) => text.toLowerCase().includes(p));
18959
+ const originSessionOf = (n) => {
18960
+ const key = sessionOriginKey(n.attrs["sources"]?.[0]);
18961
+ return key ? { originSession: key } : {};
18962
+ };
18963
+ const symbolIndex = opts.workspaceRoot ? publicSymbolIndex(store, opts.workspaceRoot) : null;
18964
+ const ownLexicon = opts.lexicon ?? buildSymbolLexicon(store);
18965
+ const projectIdentity = {
18966
+ ...profile.name ? { name: profile.name } : {},
18967
+ ...profile.repoLocator ? { repoLocator: profile.repoLocator } : {},
18968
+ ...profile.repoLocatorAliases ? { aliases: profile.repoLocatorAliases } : {},
18969
+ ...profile.aka ? { aka: profile.aka } : {}
18970
+ };
18971
+ const fileLexicon = buildFileLexicon(store);
18972
+ const shareable = (n) => {
18973
+ const preserved = symbolIndex ? preservedSymbolsFor(n.description, symbolIndex) : [];
18974
+ const fileRefs = generalizeFileRefs(n.description, fileLexicon, level);
18975
+ const fileScrubbed = fileRefs.text;
18976
+ composition.fileRefsSubstituted += fileRefs.substitutions;
18977
+ composition.fileRefLexiconMisses += fileRefs.lexiconMisses;
18978
+ const generalized = generalize(fileScrubbed, { level, project: projectIdentity });
18979
+ const shippedText = generalized.text;
18980
+ if (generalized.report.classes.length > 0) composition.privacyRewritten++;
18981
+ const internalSyms = internalSymbolsFor(shippedText, (t) => ownLexicon.has(t), symbolIndex);
18982
+ const internalFiles = internalFilesFor(shippedText, fileLexicon);
18983
+ const internal = [.../* @__PURE__ */ new Set([...internalFiles, ...internalSyms])].slice(
18984
+ 0,
18985
+ PRESERVED_SYMBOLS_CAP
18986
+ );
18987
+ return {
18988
+ ...n,
18989
+ description: shippedText,
18990
+ embedding: [],
18991
+ ...originSessionOf(n),
18992
+ attrs: {
18993
+ scope: stripCodebaseScope(n.attrs["scope"]),
18994
+ ...n.attrs["kind"] ? { kind: n.attrs["kind"] } : {},
18995
+ ...n.attrs["resolvedAs"] ? { resolvedAs: n.attrs["resolvedAs"] } : {},
18996
+ ...preserved.length > 0 ? { preservedSymbols: preserved } : {},
18997
+ ...internal.length > 0 ? { internalSymbols: internal } : {}
18998
+ }
18999
+ };
19000
+ };
19001
+ const nodes = [];
19002
+ const seen = /* @__PURE__ */ new Set();
19003
+ const walked = /* @__PURE__ */ new Set();
19004
+ const shippedById = /* @__PURE__ */ new Map();
19005
+ const anchorSources = /* @__PURE__ */ new Set();
19006
+ const semanticEndpoints = /* @__PURE__ */ new Map();
19007
+ const includedByLabel = /* @__PURE__ */ new Map();
19008
+ const composition = {
19009
+ candidates: 0,
19010
+ shipped: 0,
19011
+ cloudSourced: 0,
19012
+ falsePositive: 0,
19013
+ ignored: 0,
19014
+ watermarked: 0,
19015
+ autoMint: 0,
19016
+ notNovel: 0,
19017
+ unshippable: 0,
19018
+ heldOrphans: 0,
19019
+ terminalRefused: 0,
19020
+ privacyRewritten: 0,
19021
+ sidecarDropped: 0,
19022
+ sidecarDropReasons: {},
19023
+ sidecarTruncatedAtCap: 0,
19024
+ sidecarNoLexicon: 0,
19025
+ sidecarNoSummary: 0,
19026
+ fileRefsSubstituted: 0,
19027
+ fileRefLexiconMisses: 0
19028
+ };
19029
+ for (const label of INSTANCE_LABELS) {
19030
+ const ref = [];
19031
+ includedByLabel.set(label, ref);
19032
+ const population = label === "RootCause" && opts.sharedStore ? [...store.findNodesByLabel(label), ...opts.sharedStore.findNodesByLabel(label)] : store.findNodesByLabel(label);
19033
+ for (const n of population) {
19034
+ if (seen.has(n.id)) continue;
19035
+ if (walked.has(n.id)) continue;
19036
+ walked.add(n.id);
19037
+ composition.candidates++;
19038
+ if (n.attrs["source"] === "cloud") {
19039
+ composition.cloudSourced++;
19040
+ continue;
19041
+ }
19042
+ if (label === "Problem" && n.attrs["resolvedAs"] === PROBLEM_RESOLUTION.FALSE_POSITIVE) {
19043
+ composition.falsePositive++;
19044
+ continue;
19045
+ }
19046
+ if (ignored(n.description)) {
19047
+ composition.ignored++;
19048
+ continue;
19049
+ }
19050
+ const contributedAtSeq = n.attrs["contributedAtSeq"];
19051
+ if (typeof contributedAtSeq === "number" && (n.lastReinforcedAtSeq ?? 0) <= contributedAtSeq) {
19052
+ composition.watermarked++;
19053
+ anchorSources.add(n.id);
19054
+ semanticEndpoints.set(n.id, contributedWireId(n));
19055
+ continue;
19056
+ }
19057
+ if (label === "Solution" && n.description.startsWith(AUTO_MINT_PREFIX)) {
19058
+ composition.autoMint++;
19059
+ continue;
19060
+ }
19061
+ if (isTerminallyRefused(n)) {
19062
+ composition.terminalRefused++;
19063
+ continue;
19064
+ }
19065
+ if (!noveltyAgainst(n, ref, noveltyOpts).ready) {
19066
+ composition.notNovel++;
19067
+ continue;
19068
+ }
19069
+ const reject = unshippableReason(n.id, n.label);
19070
+ if (reject) {
19071
+ console.warn(`[errata] skipping unshippable node ${n.id} (${n.label}): ${reject}`);
19072
+ composition.unshippable++;
19073
+ continue;
19074
+ }
19075
+ ref.push(n);
19076
+ const wireNode = shareable(n);
19077
+ nodes.push(wireNode);
19078
+ shippedById.set(n.id, wireNode);
19079
+ seen.add(n.id);
19080
+ anchorSources.add(n.id);
19081
+ semanticEndpoints.set(n.id, n.id);
19082
+ }
19083
+ }
19084
+ for (const n of nodes) {
19085
+ if (!INSTANCE_LABELS.includes(n.label)) {
19086
+ throw new Error(`buildInstanceIngest: refusing to ship non-instance ${n.id} (${n.label}) \u2014 C7 invariant`);
19087
+ }
19088
+ }
19089
+ const anchorEdges = [];
19090
+ const contextNodes = [];
19091
+ const contextSeen = /* @__PURE__ */ new Set();
19092
+ const anchorDigests = {};
19093
+ for (const sourceId of anchorSources) {
19094
+ const targets = [];
19095
+ for (const e of store.outEdges(sourceId, [...ANCHOR_EDGES])) {
19096
+ const t = store.getNode(e.to);
19097
+ if (!t || !ANCHOR_TARGET_LABELS.includes(t.label)) continue;
19098
+ if (e.type === "OCCURS_IN" && t.label !== "Language") continue;
19099
+ if (e.type === "DEPENDS_ON" && t.label !== "Package") continue;
19100
+ if (e.type === "PERTAIN_TO" && t.label !== "Domain") continue;
19101
+ if (e.type === "CONCERNS" && t.label !== "Component") continue;
19102
+ if ((t.label === "Package" || t.label === "Component") && opts.includePackages !== true) continue;
19103
+ if (ignored(t.description) || ignored(String(t.attrs["name"] ?? ""))) continue;
19104
+ targets.push({ e, t, wireId: wireContextId(t) });
19105
+ }
19106
+ if (targets.length === 0) continue;
19107
+ const shipped = shippedById.get(sourceId);
19108
+ if (shipped) {
19109
+ const anchors = (label) => targets.filter((x) => x.t.label === label).map(
19110
+ (x) => label === "Language" ? langAnchor(x.t) : label === "Component" ? `component:${x.wireId}` : x.wireId
19111
+ ).filter((a) => a != null).sort();
19112
+ const anchor = anchors("Package")[0] ?? anchors("Component")[0] ?? anchors("Language")[0];
19113
+ if (anchor) {
19114
+ shipped.anchorVisibility = "public";
19115
+ shipped.anchor = anchor;
19116
+ }
19117
+ }
19118
+ const dg = digest(targets.map(({ e, wireId }) => `${e.type}>${wireId}`).sort());
19119
+ const sourceNode = store.getNode(sourceId);
19120
+ if (sourceNode?.attrs["anchorsContributedDigest"] === dg) continue;
19121
+ anchorDigests[sourceId] = dg;
19122
+ const wireFrom = seen.has(sourceId) || !sourceNode ? sourceId : contributedWireId(sourceNode);
19123
+ for (const { e, t, wireId } of targets) {
19124
+ const reject = unshippableReason(wireId, t.label);
19125
+ if (reject) {
19126
+ console.warn(`[errata] skipping unshippable anchor ${wireId} (${t.label}): ${reject}`);
19127
+ continue;
19128
+ }
19129
+ anchorEdges.push({ ...e, from: wireFrom, to: wireId, attrs: {} });
19130
+ if (t.attrs["source"] === "cloud" || contextSeen.has(wireId)) continue;
19131
+ contextSeen.add(wireId);
19132
+ contextNodes.push(shareableContext(t, wireId));
19133
+ }
19134
+ }
19135
+ const primaryLang = (profile.languages ?? []).map((l) => String(l).trim().toLowerCase()).filter(Boolean)[0];
19136
+ if (primaryLang) {
19137
+ for (const shipped of shippedById.values()) {
19138
+ if (!shipped.anchorVisibility) {
19139
+ shipped.anchorVisibility = "public";
19140
+ shipped.anchor = `lang:${primaryLang}`;
19141
+ }
19142
+ }
19143
+ }
19144
+ const project = opts.project;
19145
+ const projectAnchorDigests = {};
19146
+ if (project) {
19147
+ const now = Date.now();
19148
+ for (const sourceId of anchorSources) {
19149
+ const source = store.getNode(sourceId);
19150
+ if (!source) continue;
19151
+ const wireFrom = seen.has(sourceId) ? sourceId : contributedWireId(source);
19152
+ const planned = [];
19153
+ for (const e of store.outEdges(sourceId, ["ANCHORED_AT"])) {
19154
+ const target = store.getNode(e.to);
19155
+ if (!target) continue;
19156
+ const relPath = target.attrs["relPath"];
19157
+ const qname = target.attrs["qname"];
19158
+ if (typeof relPath !== "string" || typeof qname !== "string") continue;
19159
+ if (ignored(relPath) || ignored(qname)) continue;
19160
+ planned.push({ e, target, symId: projectSymbolId(project.salt, project.projectId, relPath, qname, target.label) });
19161
+ }
19162
+ if (planned.length === 0) continue;
19163
+ const dg = digest(
19164
+ planned.map(({ e, symId }) => `ANCHORED_AT>${symId}>${JSON.stringify(anchorVersionAttrs(e.attrs))}`).sort()
19165
+ );
19166
+ if (source.attrs["projectAnchorsContributedDigest"] === dg) continue;
19167
+ projectAnchorDigests[sourceId] = dg;
19168
+ for (const { e, target, symId } of planned) {
19169
+ if (!contextSeen.has(symId)) {
19170
+ contextSeen.add(symId);
19171
+ contextNodes.push({
19172
+ id: symId,
19173
+ label: "Symbol",
19174
+ // The id IS the description: there is nothing that can be said about an
19175
+ // opaque symbol without disclosing it, and the wire requires a non-empty
19176
+ // string. It must never carry the name or the path.
19177
+ description: symId,
19178
+ // `kind` is coarse (Function/Class/…) — shape, not identity.
19179
+ attrs: { kind: target.label },
19180
+ embedding: [],
19181
+ extractionConfidence: 1,
19182
+ extractionSource: "daemon-extracted",
19183
+ cumulativeSurprise: 0,
19184
+ peakSurprise: 0,
19185
+ cumulativeHits: 0,
19186
+ lastUpdatedAt: now,
19187
+ createdAt: now,
19188
+ memoryTier: "short-term",
19189
+ pageRank: 0,
19190
+ isLandmark: false,
19191
+ community: null,
19192
+ stability: "unstable"
19193
+ });
19194
+ }
19195
+ anchorEdges.push({ ...e, from: wireFrom, to: symId, attrs: anchorVersionAttrs(e.attrs) });
19196
+ }
19197
+ }
19198
+ }
19199
+ const edges = [];
19200
+ const semanticEdgeDigests = {};
19201
+ for (const [sourceId, wireFrom] of semanticEndpoints) {
19202
+ const rawOuts = [
19203
+ ...store.outEdges(sourceId, [...INSTANCE_EDGES]),
19204
+ ...opts.sharedStore?.outEdges(sourceId, [...INSTANCE_EDGES]) ?? []
19205
+ ];
19206
+ const dedup = /* @__PURE__ */ new Map();
19207
+ for (const e of rawOuts) dedup.set(`${e.type}>${e.to}`, e);
19208
+ const outs = [...dedup.values()].map((e) => ({ e, wireTo: semanticEndpoints.get(e.to) })).filter((x) => x.wireTo != null);
19209
+ if (outs.length === 0) continue;
19210
+ const dg = digest(outs.map(({ e, wireTo }) => `${e.type}>${wireTo}`).sort());
19211
+ const owner = store.getNode(sourceId) ?? opts.sharedStore?.getNode(sourceId);
19212
+ const digestSkip = owner?.attrs["semanticEdgesContributedDigest"] === dg;
19213
+ if (!digestSkip) semanticEdgeDigests[sourceId] = dg;
19214
+ for (const { e, wireTo } of outs) {
19215
+ if (digestSkip && !shippedById.has(e.to)) continue;
19216
+ edges.push({ ...e, from: wireFrom, to: wireTo, attrs: {} });
19217
+ }
19218
+ }
19219
+ if (nodes.length === 0 && anchorEdges.length === 0 && edges.length === 0) {
19220
+ opts.onComposition?.(composition);
19221
+ return null;
19222
+ }
19223
+ let symbolSummaries;
19224
+ if (!opts.lexicon || opts.lexicon.size === 0) composition.sidecarNoLexicon = 1;
19225
+ if (opts.lexicon && opts.lexicon.size > 0 && nodes.length > 0) {
19226
+ const lexicon = opts.lexicon;
19227
+ const isKnown = (tok) => lexicon.has(tok);
19228
+ const sidecar = {};
19229
+ let count = 0;
19230
+ outer: for (const n of nodes) {
19231
+ if (!INSTANCE_LABELS.includes(n.label)) continue;
19232
+ for (const tok of extractIdentifierTokens(n.description)) {
19233
+ if (sidecar[tok]) continue;
19234
+ const entry = lexicon.get(tok);
19235
+ if (!entry) continue;
19236
+ if (!entry.summary) {
19237
+ composition.sidecarNoSummary++;
19238
+ continue;
19239
+ }
19240
+ const scrubbed = generalize(entry.summary, { level, project: projectIdentity }).text.trim();
19241
+ const dropBucket = !scrubbed ? "empty" : sidecarDropBucket(summaryRejectionReason(scrubbed, isKnown));
19242
+ if (dropBucket !== null) {
19243
+ composition.sidecarDropped++;
19244
+ composition.sidecarDropReasons[dropBucket] = (composition.sidecarDropReasons[dropBucket] ?? 0) + 1;
19245
+ continue;
19246
+ }
19247
+ if (count >= MAX_SIDECAR_SYMBOLS) {
19248
+ composition.sidecarTruncatedAtCap = 1;
19249
+ break outer;
19250
+ }
19251
+ sidecar[tok] = { kind: entry.kind, summary: scrubbed };
19252
+ count++;
19253
+ }
19254
+ }
19255
+ if (count > 0) symbolSummaries = sidecar;
19256
+ }
19257
+ edges.push(...anchorEdges);
19258
+ const bindingEndpoints = /* @__PURE__ */ new Set();
19259
+ for (const e of edges) {
19260
+ if (e.type === "CAUSED_BY" || e.type === "SOLVED_BY") {
19261
+ bindingEndpoints.add(e.from);
19262
+ bindingEndpoints.add(e.to);
19263
+ }
19264
+ }
19265
+ const heldOrphans = /* @__PURE__ */ new Set();
19266
+ for (const wn of nodes) {
19267
+ if (wn.label !== "RootCause" && wn.label !== "Solution") continue;
19268
+ const src = store.getNode(wn.id) ?? opts.sharedStore?.getNode(wn.id);
19269
+ if (typeof src?.attrs["contributedAtSeq"] === "number") continue;
19270
+ if (bindingEndpoints.has(wn.id)) continue;
19271
+ heldOrphans.add(wn.id);
19272
+ }
19273
+ const shippableNodes = heldOrphans.size === 0 ? nodes : nodes.filter((n) => !heldOrphans.has(n.id));
19274
+ const shippableEdges = heldOrphans.size === 0 ? edges : edges.filter((e) => !heldOrphans.has(e.from) && !heldOrphans.has(e.to));
19275
+ for (const id of heldOrphans) {
19276
+ delete anchorDigests[id];
19277
+ delete semanticEdgeDigests[id];
19278
+ delete projectAnchorDigests[id];
19279
+ }
19280
+ if (heldOrphans.size > 0) {
19281
+ console.warn(
19282
+ `[errata] held ${heldOrphans.size} causal-orphan node(s) \u2014 no shippable binding edge this drain (VS-orphan-gate)`
19283
+ );
19284
+ }
19285
+ composition.heldOrphans = heldOrphans.size;
19286
+ composition.shipped = shippableNodes.length;
19287
+ if (shippableNodes.length === 0 && shippableEdges.length === 0) {
19288
+ opts.onComposition?.(composition);
19289
+ return null;
19290
+ }
19291
+ const base = {
19292
+ daemonVersion,
19293
+ // Origin key (= project, the salted `wp_…`) — the door stamps it onto created
19294
+ // nodes as `authoringProject`, arming the evidence channels' cross-origin gate
19295
+ // (EE-corrob-live: this is the MAIN semantic drain; without the stamp every
19296
+ // Problem/Solution lands fail-open to self-corroboration).
19297
+ ...profile.id ? { originProject: profile.id } : {},
19298
+ profile: { stack: profile.stack, languages: profile.languages, domains: profile.domains },
19299
+ // Context nodes FIRST: a chunked drain (cloud-client, 25-node chunks) then
19300
+ // co-locates the few Language/Package stubs with the first instance chunk,
19301
+ // maximizing in-payload endpoint resolution.
19302
+ nodes: [...contextNodes, ...shippableNodes],
19303
+ edges: shippableEdges,
19304
+ // Spread-if-present: an absent sidecar keeps `base` — and therefore the
19305
+ // payloadDigest — byte-identical to the pre-sidecar batch (backward compat).
19306
+ ...symbolSummaries ? { symbolSummaries } : {}
19307
+ };
19308
+ opts.onComposition?.(composition);
19309
+ return { ...base, payloadDigest: digest(base), anchorDigests, semanticEdgeDigests, projectAnchorDigests, composition };
19310
+ }
19311
+
19312
+ // src/drain-build.ts
19313
+ function buildDrainContext(store, input) {
19314
+ return buildContextIngest(store, input.profile, input.daemonVersion, input.ignorePatterns, {
19315
+ ...input.includePackages !== void 0 ? { includePackages: input.includePackages } : {}
19316
+ });
19317
+ }
19318
+ function buildDrainInstances(store, sharedStore, input) {
19319
+ let lexicon;
19320
+ let lexiconError;
19321
+ try {
19322
+ lexicon = buildSymbolLexicon(store);
19323
+ } catch (err) {
19324
+ lexiconError = err instanceof Error ? err.message : String(err);
19325
+ }
19326
+ let composition = null;
19327
+ const batch = buildInstanceIngest(store, input.profile, input.daemonVersion, input.ignorePatterns, {
19328
+ ...input.includePackages !== void 0 ? { includePackages: input.includePackages } : {},
19329
+ workspaceRoot: input.workspaceRoot,
19330
+ sharedStore,
19331
+ onComposition: (c) => {
19332
+ composition = c;
19333
+ },
19334
+ ...lexicon ? { lexicon } : {},
19335
+ ...input.project ? { project: input.project } : {}
19336
+ });
19337
+ return {
19338
+ batch,
19339
+ composition: composition ?? batch?.composition ?? null,
19340
+ ...lexiconError ? { lexiconError } : {}
19341
+ };
19342
+ }
19343
+
17664
19344
  // src/consolidate-worker.ts
17665
19345
  var stores = /* @__PURE__ */ new Map();
17666
19346
  function storeAt(path) {
@@ -17709,6 +19389,16 @@ function runPass(msg) {
17709
19389
  if (!msg.castaliaPath) throw new Error("strandedCount: castaliaPath required");
17710
19390
  return findStrandedSymbols(storeAt(msg.castaliaPath)).length;
17711
19391
  }
19392
+ case "drainContext": {
19393
+ if (!msg.castaliaPath) throw new Error("drainContext: castaliaPath required");
19394
+ if (!msg.drain) throw new Error("drainContext: drain input required");
19395
+ return buildDrainContext(storeAt(msg.castaliaPath), msg.drain);
19396
+ }
19397
+ case "drainInstances": {
19398
+ if (!msg.castaliaPath) throw new Error("drainInstances: castaliaPath required");
19399
+ if (!msg.drain) throw new Error("drainInstances: drain input required");
19400
+ return buildDrainInstances(storeAt(msg.castaliaPath), shared, msg.drain);
19401
+ }
17712
19402
  default:
17713
19403
  throw new Error(`unknown consolidation pass: ${msg.kind}`);
17714
19404
  }