@launchsecure/launch-kit 0.0.39 → 0.0.40

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.
Files changed (84) hide show
  1. package/dist/chart-client/assets/index-CWJFFDPu.css +1 -0
  2. package/dist/chart-client/index.html +2 -2
  3. package/dist/client/assets/index-CTzFcfGV.css +32 -0
  4. package/dist/client/index.html +2 -2
  5. package/dist/council-client/assets/index-ArgRc5mN.css +1 -0
  6. package/dist/council-client/index.html +2 -2
  7. package/dist/deck-client/assets/{_baseUniq-DOrnEQMI.js → _baseUniq-BZP7n41F.js} +1 -1
  8. package/dist/deck-client/assets/{arc-DOWK7V3m.js → arc-31biU3Az.js} +1 -1
  9. package/dist/deck-client/assets/{architectureDiagram-Q4EWVU46-DPhzvk7q.js → architectureDiagram-Q4EWVU46-DHg6Ss--.js} +1 -1
  10. package/dist/deck-client/assets/{blockDiagram-DXYQGD6D-CwAGy9lU.js → blockDiagram-DXYQGD6D-CUdblaWk.js} +1 -1
  11. package/dist/deck-client/assets/{c4Diagram-AHTNJAMY-L_g_SS21.js → c4Diagram-AHTNJAMY-MfAO5lak.js} +1 -1
  12. package/dist/deck-client/assets/channel-BBkRLdnC.js +1 -0
  13. package/dist/deck-client/assets/{chunk-4BX2VUAB-RKm0LXpu.js → chunk-4BX2VUAB-DQ1MrGgN.js} +1 -1
  14. package/dist/deck-client/assets/{chunk-4TB4RGXK-Bk0FUbxU.js → chunk-4TB4RGXK-BUJtZ7jO.js} +1 -1
  15. package/dist/deck-client/assets/{chunk-55IACEB6-Cl3hja-M.js → chunk-55IACEB6-BdSnXB6g.js} +1 -1
  16. package/dist/deck-client/assets/{chunk-EDXVE4YY-CNIMQCV2.js → chunk-EDXVE4YY-94yZIUI8.js} +1 -1
  17. package/dist/deck-client/assets/{chunk-FMBD7UC4-DqOvWr1k.js → chunk-FMBD7UC4-PnZ9v6ey.js} +1 -1
  18. package/dist/deck-client/assets/{chunk-OYMX7WX6-1Kd7yK5u.js → chunk-OYMX7WX6-DXrWNOsV.js} +1 -1
  19. package/dist/deck-client/assets/{chunk-QZHKN3VN-6_kraYpP.js → chunk-QZHKN3VN-CsIGIDKX.js} +1 -1
  20. package/dist/deck-client/assets/{chunk-YZCP3GAM-FgAwIWlo.js → chunk-YZCP3GAM-DVkBO9tn.js} +1 -1
  21. package/dist/deck-client/assets/classDiagram-6PBFFD2Q-DFCaeF-7.js +1 -0
  22. package/dist/deck-client/assets/classDiagram-v2-HSJHXN6E-DFCaeF-7.js +1 -0
  23. package/dist/deck-client/assets/clone-GCEVRScB.js +1 -0
  24. package/dist/deck-client/assets/{cose-bilkent-S5V4N54A-CigVnnPr.js → cose-bilkent-S5V4N54A-m126Oh3b.js} +1 -1
  25. package/dist/deck-client/assets/{dagre-KV5264BT-DHZXTktX.js → dagre-KV5264BT-C2aig8U5.js} +1 -1
  26. package/dist/deck-client/assets/{diagram-5BDNPKRD-H5k0eauU.js → diagram-5BDNPKRD-CKpoRfGn.js} +1 -1
  27. package/dist/deck-client/assets/{diagram-G4DWMVQ6-Bg3dFhSY.js → diagram-G4DWMVQ6-Cjh115Ep.js} +1 -1
  28. package/dist/deck-client/assets/{diagram-MMDJMWI5-CQLC410N.js → diagram-MMDJMWI5-DKlBv_2L.js} +1 -1
  29. package/dist/deck-client/assets/{diagram-TYMM5635-DFTCHVkP.js → diagram-TYMM5635-CdBh4cEn.js} +1 -1
  30. package/dist/deck-client/assets/{erDiagram-SMLLAGMA-aiv9GZnL.js → erDiagram-SMLLAGMA-56pn_93p.js} +1 -1
  31. package/dist/deck-client/assets/{flowDiagram-DWJPFMVM-C6Fhvtsy.js → flowDiagram-DWJPFMVM-BtV3M5xJ.js} +1 -1
  32. package/dist/deck-client/assets/{ganttDiagram-T4ZO3ILL-DSaGMPM4.js → ganttDiagram-T4ZO3ILL-DTIsC6Zg.js} +1 -1
  33. package/dist/deck-client/assets/{gitGraphDiagram-UUTBAWPF-DMjL2Vix.js → gitGraphDiagram-UUTBAWPF-CJYeyCLe.js} +1 -1
  34. package/dist/deck-client/assets/{graph-B7Vn5lkK.js → graph-BDvMu1Ss.js} +1 -1
  35. package/dist/deck-client/assets/index-D4eSxcBn.css +1 -0
  36. package/dist/deck-client/assets/{index-BD36e-tD.js → index-QnGVE9PZ.js} +72 -72
  37. package/dist/deck-client/assets/{infoDiagram-42DDH7IO-mNi4iygG.js → infoDiagram-42DDH7IO-BWyKJnpW.js} +1 -1
  38. package/dist/deck-client/assets/{ishikawaDiagram-UXIWVN3A-BwCUmUVt.js → ishikawaDiagram-UXIWVN3A-DXYkdO3T.js} +1 -1
  39. package/dist/deck-client/assets/{journeyDiagram-VCZTEJTY-C6qoqJmJ.js → journeyDiagram-VCZTEJTY-C2zBr-J5.js} +1 -1
  40. package/dist/deck-client/assets/{kanban-definition-6JOO6SKY-Dz1Tt3sA.js → kanban-definition-6JOO6SKY-CdoYLS4Z.js} +1 -1
  41. package/dist/deck-client/assets/{layout-CZTyRhOG.js → layout-vOnxnCQU.js} +1 -1
  42. package/dist/deck-client/assets/{linear--7n7iEvd.js → linear-B0J0WCGz.js} +1 -1
  43. package/dist/deck-client/assets/{min-Bh130DN8.js → min-B0AXlT9L.js} +1 -1
  44. package/dist/deck-client/assets/{mindmap-definition-QFDTVHPH-CfXcK1qH.js → mindmap-definition-QFDTVHPH-oAybLedr.js} +1 -1
  45. package/dist/deck-client/assets/{pieDiagram-DEJITSTG-DjVHLAVw.js → pieDiagram-DEJITSTG-BjHyHxGk.js} +1 -1
  46. package/dist/deck-client/assets/{quadrantDiagram-34T5L4WZ-CXwvZ1i1.js → quadrantDiagram-34T5L4WZ-dtluDZXs.js} +1 -1
  47. package/dist/deck-client/assets/{requirementDiagram-MS252O5E-Cl6xm0fR.js → requirementDiagram-MS252O5E-Cq8l7bOl.js} +1 -1
  48. package/dist/deck-client/assets/{sankeyDiagram-XADWPNL6-BOH9sLyh.js → sankeyDiagram-XADWPNL6-C1Vih91z.js} +1 -1
  49. package/dist/deck-client/assets/{sequenceDiagram-FGHM5R23-BC1MYBn6.js → sequenceDiagram-FGHM5R23-CYkd7oQK.js} +1 -1
  50. package/dist/deck-client/assets/{stateDiagram-FHFEXIEX-kNp9bv8K.js → stateDiagram-FHFEXIEX-CtyG8wBK.js} +1 -1
  51. package/dist/deck-client/assets/stateDiagram-v2-QKLJ7IA2-BLyKWfcN.js +1 -0
  52. package/dist/deck-client/assets/{timeline-definition-GMOUNBTQ-DKnITsD4.js → timeline-definition-GMOUNBTQ-DZIxSyd1.js} +1 -1
  53. package/dist/deck-client/assets/{vennDiagram-DHZGUBPP-BdajXRrh.js → vennDiagram-DHZGUBPP-Ct4JVRDM.js} +1 -1
  54. package/dist/deck-client/assets/wardley-RL74JXVD-V29ycxOW.js +162 -0
  55. package/dist/deck-client/assets/{wardleyDiagram-NUSXRM2D-B2hDCDl2.js → wardleyDiagram-NUSXRM2D-D-Ua6Cmi.js} +1 -1
  56. package/dist/deck-client/assets/{xychartDiagram-5P7HB3ND-CvnYFs51.js → xychartDiagram-5P7HB3ND-BPCOuRVl.js} +1 -1
  57. package/dist/deck-client/index.html +2 -2
  58. package/dist/server/beacon-monitor-entry.js +106 -24
  59. package/dist/server/chart-serve.js +544 -247
  60. package/dist/server/cli.js +743 -324
  61. package/dist/server/council-entry.js +16 -3
  62. package/dist/server/council-serve.js +15 -2
  63. package/dist/server/deck-mcp-entry.js +267 -107
  64. package/dist/server/deck-serve.js +98 -22
  65. package/dist/server/graph-mcp-entry.js +866 -357
  66. package/dist/server/orbit-entry.js +91 -7
  67. package/dist/server/recall-entry.js +94 -12
  68. package/dist/server/rover-entry.js +1 -1
  69. package/package.json +1 -1
  70. package/scaffolds/statusline/statusline-mcp.sh +68 -19
  71. package/scaffolds/statusline/statusline-wrapper.sh +12 -9
  72. package/dist/chart-client/assets/index-ysGpLeOW.css +0 -1
  73. package/dist/client/assets/index-CMN3tlGP.css +0 -32
  74. package/dist/council-client/assets/index-ChmNX6bZ.css +0 -1
  75. package/dist/deck-client/assets/channel-DqiACUUq.js +0 -1
  76. package/dist/deck-client/assets/classDiagram-6PBFFD2Q-D23cq2C3.js +0 -1
  77. package/dist/deck-client/assets/classDiagram-v2-HSJHXN6E-D23cq2C3.js +0 -1
  78. package/dist/deck-client/assets/clone-C7jSigGq.js +0 -1
  79. package/dist/deck-client/assets/index-CGbNOpk9.css +0 -1
  80. package/dist/deck-client/assets/stateDiagram-v2-QKLJ7IA2-hRsAFc2t.js +0 -1
  81. package/dist/deck-client/assets/wardley-RL74JXVD-BL802-su.js +0 -162
  82. /package/dist/chart-client/assets/{index-BlsuXuQ1.js → index-Dzlj-oCj.js} +0 -0
  83. /package/dist/client/assets/{index-BA7BHBWT.js → index-tTg_ezUF.js} +0 -0
  84. /package/dist/council-client/assets/{index-jjBWyhry.js → index-B1v46vTE.js} +0 -0
@@ -131,8 +131,8 @@ function getQuery(name) {
131
131
  ensureInit();
132
132
  const cached = queryCache.get(name);
133
133
  if (cached) return cached;
134
- const scmPath = (0, import_node_path13.join)(queriesDir, `${name}.scm`);
135
- const scm = (0, import_node_fs11.readFileSync)(scmPath, "utf-8");
134
+ const scmPath = (0, import_node_path16.join)(queriesDir, `${name}.scm`);
135
+ const scm = (0, import_node_fs12.readFileSync)(scmPath, "utf-8");
136
136
  const query = tsxLanguage.query(scm);
137
137
  queryCache.set(name, query);
138
138
  return query;
@@ -152,13 +152,13 @@ function parseSource(absPath) {
152
152
  ensureInit();
153
153
  let content;
154
154
  try {
155
- const stat = (0, import_node_fs11.statSync)(absPath);
155
+ const stat = (0, import_node_fs12.statSync)(absPath);
156
156
  if (stat.size > MAX_PARSEABLE_BYTES) {
157
157
  process.stderr.write(`[lc-extractor] skipping ${absPath}: ${stat.size} bytes exceeds max ${MAX_PARSEABLE_BYTES}
158
158
  `);
159
159
  return null;
160
160
  }
161
- content = (0, import_node_fs11.readFileSync)(absPath, "utf-8");
161
+ content = (0, import_node_fs12.readFileSync)(absPath, "utf-8");
162
162
  } catch (e) {
163
163
  process.stderr.write(`[lc-extractor] read failed for ${absPath}: ${e instanceof Error ? e.message : String(e)}
164
164
  `);
@@ -1192,18 +1192,18 @@ function collectUiLabels(root) {
1192
1192
  visit(root);
1193
1193
  return out;
1194
1194
  }
1195
- var import_node_fs11, import_node_path13, tsxLanguage, parserInstance, TreeSitterCtor, initPromise, initialized, queriesDir, queryCache, MAX_PARSEABLE_BYTES, MAX_CONSECUTIVE_PARSE_FAILURES, consecutiveParseFailures, ParseCascadeError, PRISMA_MUTATION_METHODS_BUILTIN, SUPABASE_MUTATION_METHODS_BUILTIN, DB_IDENTIFIERS_FALLBACK, extraDbIdentifiers, extraMutationMethods, INLINE_AUTH_IMPORTS, EXEMPT_NAME_PATTERNS, PROTECT_NAME_PATTERNS, TRUST_AS_PROTECT_KEYS, TIMER_FNS, DOM_METHOD_NAMES, CLASSLIST_METHODS, STORAGE_OBJECTS, HISTORY_METHODS, LOCATION_METHODS, ASSIGN_DOM_PROPS, UI_LABEL_KEYS, UI_LABELS_MAX, NOTE_REGEX, NOTES_MAX;
1195
+ var import_node_fs12, import_node_path16, tsxLanguage, parserInstance, TreeSitterCtor, initPromise, initialized, queriesDir, queryCache, MAX_PARSEABLE_BYTES, MAX_CONSECUTIVE_PARSE_FAILURES, consecutiveParseFailures, ParseCascadeError, PRISMA_MUTATION_METHODS_BUILTIN, SUPABASE_MUTATION_METHODS_BUILTIN, DB_IDENTIFIERS_FALLBACK, extraDbIdentifiers, extraMutationMethods, INLINE_AUTH_IMPORTS, EXEMPT_NAME_PATTERNS, PROTECT_NAME_PATTERNS, TRUST_AS_PROTECT_KEYS, TIMER_FNS, DOM_METHOD_NAMES, CLASSLIST_METHODS, STORAGE_OBJECTS, HISTORY_METHODS, LOCATION_METHODS, ASSIGN_DOM_PROPS, UI_LABEL_KEYS, UI_LABELS_MAX, NOTE_REGEX, NOTES_MAX;
1196
1196
  var init_ts_extractor = __esm({
1197
1197
  "src/server/graph/core/ts-extractor.ts"() {
1198
1198
  "use strict";
1199
- import_node_fs11 = require("node:fs");
1200
- import_node_path13 = require("node:path");
1199
+ import_node_fs12 = require("node:fs");
1200
+ import_node_path16 = require("node:path");
1201
1201
  init_parse_failure_cache();
1202
1202
  initialized = false;
1203
1203
  queriesDir = (() => {
1204
- const srcPath = (0, import_node_path13.join)((0, import_node_path13.dirname)(__filename), "..", "queries");
1204
+ const srcPath = (0, import_node_path16.join)((0, import_node_path16.dirname)(__filename), "..", "queries");
1205
1205
  if (require("fs").existsSync(srcPath)) return srcPath;
1206
- return (0, import_node_path13.join)((0, import_node_path13.dirname)(__filename), "graph", "queries");
1206
+ return (0, import_node_path16.join)((0, import_node_path16.dirname)(__filename), "graph", "queries");
1207
1207
  })();
1208
1208
  queryCache = /* @__PURE__ */ new Map();
1209
1209
  MAX_PARSEABLE_BYTES = 2 * 1024 * 1024;
@@ -1343,13 +1343,13 @@ __export(chart_serve_exports, {
1343
1343
  });
1344
1344
  module.exports = __toCommonJS(chart_serve_exports);
1345
1345
  var import_node_http = __toESM(require("node:http"));
1346
- var import_node_fs21 = __toESM(require("node:fs"));
1347
- var import_node_path24 = __toESM(require("node:path"));
1346
+ var import_node_fs22 = __toESM(require("node:fs"));
1347
+ var import_node_path27 = __toESM(require("node:path"));
1348
1348
  init_launch_kit_paths();
1349
1349
 
1350
1350
  // src/server/graph/index.ts
1351
- var import_node_fs7 = require("node:fs");
1352
- var import_node_path9 = require("node:path");
1351
+ var import_node_fs8 = require("node:fs");
1352
+ var import_node_path12 = require("node:path");
1353
1353
  init_config();
1354
1354
 
1355
1355
  // src/server/graph/core/tagger-registry.ts
@@ -1813,7 +1813,7 @@ function resolveWorkerPath() {
1813
1813
  );
1814
1814
  }
1815
1815
  function runParseInWorker(req) {
1816
- return new Promise((resolve4, reject) => {
1816
+ return new Promise((resolve5, reject) => {
1817
1817
  let workerPath;
1818
1818
  try {
1819
1819
  workerPath = resolveWorkerPath();
@@ -1832,7 +1832,7 @@ function runParseInWorker(req) {
1832
1832
  };
1833
1833
  worker.on("message", (reply) => {
1834
1834
  if (reply.ok) {
1835
- finish(() => resolve4({ results: reply.results, failedFiles: reply.failedFiles }));
1835
+ finish(() => resolve5({ results: reply.results, failedFiles: reply.failedFiles }));
1836
1836
  } else {
1837
1837
  const err = new Error(reply.error.message);
1838
1838
  err.name = reply.error.name;
@@ -1910,9 +1910,297 @@ function writeEffectsIndex(rootDir, idx) {
1910
1910
  return path2;
1911
1911
  }
1912
1912
 
1913
- // src/server/graph/core/freshness.ts
1913
+ // src/server/graph/core/context-map.ts
1914
+ var import_node_path10 = require("node:path");
1915
+ init_launch_kit_paths();
1916
+ init_config();
1917
+
1918
+ // src/server/graph/core/context/registry.ts
1919
+ var import_node_path9 = require("node:path");
1920
+
1921
+ // src/server/graph/core/context/types.ts
1922
+ var CONTEXT_NODE_ACTION = "action";
1923
+ var CONTEXT_NODE_STATE = "state";
1924
+ var CONFIDENCE_RANK = { low: 0, medium: 1, high: 2 };
1925
+ function higherConfidence(a, b) {
1926
+ return CONFIDENCE_RANK[a] >= CONFIDENCE_RANK[b] ? a : b;
1927
+ }
1928
+ function stateId(token) {
1929
+ return `state:${token}`;
1930
+ }
1931
+ function actionId(key) {
1932
+ return `action:${key}`;
1933
+ }
1934
+ function stateNode(token, label) {
1935
+ return { id: stateId(token), type: CONTEXT_NODE_STATE, name: token, label };
1936
+ }
1937
+ function actionNode(key, name, meta = {}) {
1938
+ return { id: actionId(key), type: CONTEXT_NODE_ACTION, name, ...meta };
1939
+ }
1940
+ function contextEdge(fromActionId, toStateId, type, confidence, origin) {
1941
+ return { source: fromActionId, target: toStateId, type, label: `${type} (${origin})`, confidence, origin };
1942
+ }
1943
+
1944
+ // src/server/graph/core/context/providers/nextjs-prisma.ts
1945
+ var PRODUCING_METHODS = /* @__PURE__ */ new Set(["create", "createMany", "upsert"]);
1946
+ function isPublic(auth) {
1947
+ if (!auth || auth.length === 0) return true;
1948
+ return auth.every((a) => a === "public");
1949
+ }
1950
+ function notFoundEntity(consequence) {
1951
+ if (!consequence) return null;
1952
+ const m = consequence.match(/notFound\(\s*['"]([A-Za-z0-9_]+)['"]/);
1953
+ return m ? m[1] : null;
1954
+ }
1955
+ var nextjsPrismaContextProvider = {
1956
+ id: "nextjs-prisma",
1957
+ detect(layerOutputs) {
1958
+ const api = layerOutputs["api"];
1959
+ return !!api && (api.nodes ?? []).some((n) => n.type === "endpoint");
1960
+ },
1961
+ derive(layerOutputs) {
1962
+ const api = layerOutputs["api"];
1963
+ const states = /* @__PURE__ */ new Map();
1964
+ const actions = [];
1965
+ const edges = [];
1966
+ const seenEdge = /* @__PURE__ */ new Set();
1967
+ const ensureState = (token, label) => {
1968
+ const id = stateId(token);
1969
+ if (!states.has(id)) states.set(id, stateNode(token, label));
1970
+ return id;
1971
+ };
1972
+ const addEdge = (from, to, type, confidence, origin) => {
1973
+ const key = `${from}|${type}|${to}`;
1974
+ if (seenEdge.has(key)) return;
1975
+ seenEdge.add(key);
1976
+ edges.push(contextEdge(from, to, type, confidence, origin));
1977
+ };
1978
+ const endpoints = (api?.nodes ?? []).filter((n) => n.type === "endpoint");
1979
+ for (const ep of endpoints) {
1980
+ const aId = actionId(ep.id);
1981
+ actions.push(actionNode(ep.id, ep.name, { methods: ep.methods ?? [], endpoint: ep.id }));
1982
+ if (!isPublic(ep.auth)) {
1983
+ addEdge(aId, ensureState("session", "Authenticated session"), "requires", "high", "auth-wrapper");
1984
+ }
1985
+ for (const op of ep.db_operations ?? []) {
1986
+ const [model, method] = op.split(".");
1987
+ if (!model || !PRODUCING_METHODS.has(method ?? "")) continue;
1988
+ addEdge(aId, ensureState(model, `${model} record exists`), "produces", "medium", `db:${op}`);
1989
+ }
1990
+ for (const cond of ep.conditions ?? []) {
1991
+ const entity = notFoundEntity(cond.consequence);
1992
+ if (!entity) continue;
1993
+ const token = entity.toLowerCase();
1994
+ addEdge(aId, ensureState(token, `${token} record exists`), "requires", "low", "guard:notFound");
1995
+ }
1996
+ }
1997
+ return { nodes: [...actions, ...states.values()], edges };
1998
+ }
1999
+ };
2000
+
2001
+ // src/server/graph/core/context/overlay.ts
1914
2002
  var import_node_fs6 = require("node:fs");
1915
2003
  var import_node_path8 = require("node:path");
2004
+ var OVERLAY_FILE = ".launchchart.context.json";
2005
+ function overlayPath(rootDir) {
2006
+ return (0, import_node_path8.join)(rootDir, OVERLAY_FILE);
2007
+ }
2008
+ function loadOverlay(rootDir) {
2009
+ const path2 = overlayPath(rootDir);
2010
+ if (!(0, import_node_fs6.existsSync)(path2)) return null;
2011
+ try {
2012
+ return JSON.parse((0, import_node_fs6.readFileSync)(path2, "utf-8"));
2013
+ } catch (e) {
2014
+ process.stderr.write(`[launch-chart] failed to parse ${OVERLAY_FILE}: ${e.message}
2015
+ `);
2016
+ return null;
2017
+ }
2018
+ }
2019
+ var overlayProvider = {
2020
+ id: "overlay",
2021
+ detect(_layerOutputs, rootDir) {
2022
+ return (0, import_node_fs6.existsSync)(overlayPath(rootDir));
2023
+ },
2024
+ derive(_layerOutputs, rootDir) {
2025
+ const overlay = loadOverlay(rootDir);
2026
+ if (!overlay) return { nodes: [], edges: [] };
2027
+ const nodes = /* @__PURE__ */ new Map();
2028
+ const edges = [];
2029
+ const seenEdge = /* @__PURE__ */ new Set();
2030
+ const ensureState = (token, label) => {
2031
+ const id = stateId(token);
2032
+ if (!nodes.has(id)) nodes.set(id, stateNode(token, label ?? `${token} (overlay)`));
2033
+ return id;
2034
+ };
2035
+ const ensureAction = (key, name) => {
2036
+ const id = actionId(key);
2037
+ if (!nodes.has(id)) nodes.set(id, actionNode(key, name ?? key, { source: "overlay" }));
2038
+ return id;
2039
+ };
2040
+ for (const s of overlay.states ?? []) ensureState(s.token, s.label);
2041
+ for (const a of overlay.actions ?? []) ensureAction(a.id, a.name);
2042
+ for (const e of overlay.edges ?? []) {
2043
+ const aId = ensureAction(e.action);
2044
+ const link = (token, type) => {
2045
+ const sId = ensureState(token);
2046
+ const key = `${aId}|${type}|${sId}`;
2047
+ if (seenEdge.has(key)) return;
2048
+ seenEdge.add(key);
2049
+ edges.push(contextEdge(aId, sId, type, "high", "overlay"));
2050
+ };
2051
+ for (const token of e.requires ?? []) link(token, "requires");
2052
+ for (const token of e.produces ?? []) link(token, "produces");
2053
+ }
2054
+ return { nodes: [...nodes.values()], edges };
2055
+ }
2056
+ };
2057
+ function applyOverlayRejections(edges, rootDir) {
2058
+ const overlay = loadOverlay(rootDir);
2059
+ const rejects = overlay?.reject ?? [];
2060
+ if (rejects.length === 0) return edges;
2061
+ const rejectKeys = new Set(
2062
+ rejects.map((r) => `${actionId(r.action)}|${r.type}|${stateId(r.state)}`)
2063
+ );
2064
+ return edges.filter((e) => !rejectKeys.has(`${e.source}|${e.type}|${e.target}`));
2065
+ }
2066
+
2067
+ // src/server/graph/core/context/registry.ts
2068
+ var ContextProviderRegistry = class {
2069
+ constructor() {
2070
+ this.providers = [];
2071
+ this.ids = /* @__PURE__ */ new Set();
2072
+ }
2073
+ register(provider) {
2074
+ if (this.ids.has(provider.id)) {
2075
+ throw new Error(`Duplicate context provider id: ${provider.id}`);
2076
+ }
2077
+ this.ids.add(provider.id);
2078
+ this.providers.push(provider);
2079
+ }
2080
+ getAll() {
2081
+ return [...this.providers];
2082
+ }
2083
+ };
2084
+ function registerBuiltins2(registry, disabled) {
2085
+ const builtins = [nextjsPrismaContextProvider, overlayProvider];
2086
+ for (const provider of builtins) {
2087
+ if (disabled.has(provider.id)) continue;
2088
+ registry.register(provider);
2089
+ }
2090
+ }
2091
+ function loadCustomProviders(registry, config, rootDir, disabled) {
2092
+ for (const entry of config.context?.providers ?? []) {
2093
+ try {
2094
+ const absPath = (0, import_node_path9.resolve)(rootDir, entry.path);
2095
+ const mod = require(absPath);
2096
+ const provider = "default" in mod ? mod.default : mod;
2097
+ if (disabled.has(provider.id)) continue;
2098
+ registry.register(provider);
2099
+ } catch (err) {
2100
+ process.stderr.write(`[launch-chart] failed to load custom context provider from ${entry.path}: ${err}
2101
+ `);
2102
+ }
2103
+ }
2104
+ }
2105
+ function createContextProviderRegistry(config, rootDir) {
2106
+ const registry = new ContextProviderRegistry();
2107
+ const disabled = new Set(config.context?.disabled ?? []);
2108
+ registerBuiltins2(registry, disabled);
2109
+ loadCustomProviders(registry, config, rootDir, disabled);
2110
+ return registry;
2111
+ }
2112
+
2113
+ // src/server/graph/core/context-map.ts
2114
+ function buildContextMap(layerOutputs, rootDir) {
2115
+ const generated = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
2116
+ const config = loadConfig(rootDir);
2117
+ const registry = createContextProviderRegistry(config, rootDir);
2118
+ const nodesById = /* @__PURE__ */ new Map();
2119
+ const edgesByKey = /* @__PURE__ */ new Map();
2120
+ const providerStats = {};
2121
+ const usedProviders = [];
2122
+ for (const provider of registry.getAll()) {
2123
+ let detected = false;
2124
+ try {
2125
+ detected = provider.detect(layerOutputs, rootDir);
2126
+ } catch (e) {
2127
+ process.stderr.write(`[launch-chart] context provider "${provider.id}" detect failed: ${e.message}
2128
+ `);
2129
+ continue;
2130
+ }
2131
+ if (!detected) continue;
2132
+ let contribution;
2133
+ try {
2134
+ contribution = provider.derive(layerOutputs, rootDir);
2135
+ } catch (e) {
2136
+ process.stderr.write(`[launch-chart] context provider "${provider.id}" derive failed: ${e.message}
2137
+ `);
2138
+ continue;
2139
+ }
2140
+ usedProviders.push(provider.id);
2141
+ providerStats[provider.id] = { nodes: contribution.nodes.length, edges: contribution.edges.length };
2142
+ for (const node of contribution.nodes) {
2143
+ if (!nodesById.has(node.id)) nodesById.set(node.id, node);
2144
+ }
2145
+ for (const edge of contribution.edges) {
2146
+ const key = `${edge.source}|${edge.type}|${edge.target}`;
2147
+ const existing = edgesByKey.get(key);
2148
+ const edgeConf = edge.confidence ?? "low";
2149
+ if (!existing) {
2150
+ edgesByKey.set(key, { ...edge, providers: [provider.id] });
2151
+ } else {
2152
+ const existingConf = existing.confidence ?? "low";
2153
+ existing.confidence = higherConfidence(existingConf, edgeConf);
2154
+ const provs = existing.providers ?? [];
2155
+ if (!provs.includes(provider.id)) provs.push(provider.id);
2156
+ existing.providers = provs;
2157
+ }
2158
+ }
2159
+ }
2160
+ const merged = [...edgesByKey.values()];
2161
+ const edges = applyOverlayRejections(merged, rootDir);
2162
+ const rejectedCount = merged.length - edges.length;
2163
+ const flagged = edges.map((e) => ({
2164
+ source: e.source,
2165
+ target: e.target,
2166
+ type: e.type,
2167
+ label: e.label ?? `${e.type}`,
2168
+ confidence: e.confidence ?? "low"
2169
+ }));
2170
+ const nodes = [...nodesById.values()];
2171
+ const stateCount = nodes.filter((n) => n.type === CONTEXT_NODE_STATE).length;
2172
+ return {
2173
+ metadata: {
2174
+ generated,
2175
+ scope: "derived",
2176
+ layer: "context",
2177
+ source: "context-map-builder",
2178
+ derived: true,
2179
+ providers: usedProviders,
2180
+ provider_stats: providerStats,
2181
+ action_count: nodes.length - stateCount,
2182
+ state_count: stateCount,
2183
+ candidate_edge_count: edges.length,
2184
+ rejected_edge_count: rejectedCount,
2185
+ note: "Edges are candidates (see flagged_edges + confidence) from the context providers. Promote via the curation overlay."
2186
+ },
2187
+ nodes,
2188
+ edges,
2189
+ cross_refs: [],
2190
+ contradictions: [],
2191
+ warnings: [],
2192
+ flagged_edges: flagged
2193
+ };
2194
+ }
2195
+ function writeContextMap(rootDir, output) {
2196
+ const path2 = (0, import_node_path10.join)(rootDir, LAUNCHSECURE_DIR, "graphs", "context.json");
2197
+ atomicWriteFileSync(path2, JSON.stringify(output, null, 2) + "\n");
2198
+ return path2;
2199
+ }
2200
+
2201
+ // src/server/graph/core/freshness.ts
2202
+ var import_node_fs7 = require("node:fs");
2203
+ var import_node_path11 = require("node:path");
1916
2204
  init_launch_kit_paths();
1917
2205
  function exactFilenameRegex(name) {
1918
2206
  return new RegExp(`^${name.replace(/\./g, "\\.")}$`);
@@ -1934,7 +2222,7 @@ function isHardEscalation(relativePath) {
1934
2222
  var FreshnessTracker = class {
1935
2223
  constructor(rootDir) {
1936
2224
  this.dirty = false;
1937
- this.filePath = (0, import_node_path8.join)(rootDir, LAUNCHSECURE_DIR, "graphs", ".freshness.json");
2225
+ this.filePath = (0, import_node_path11.join)(rootDir, LAUNCHSECURE_DIR, "graphs", ".freshness.json");
1938
2226
  this.snapshot = this.load() ?? {
1939
2227
  state: "fresh",
1940
2228
  lastFullRegenAt: null,
@@ -2021,9 +2309,9 @@ var FreshnessTracker = class {
2021
2309
  }
2022
2310
  }
2023
2311
  load() {
2024
- if (!(0, import_node_fs6.existsSync)(this.filePath)) return null;
2312
+ if (!(0, import_node_fs7.existsSync)(this.filePath)) return null;
2025
2313
  try {
2026
- const parsed = JSON.parse((0, import_node_fs6.readFileSync)(this.filePath, "utf-8"));
2314
+ const parsed = JSON.parse((0, import_node_fs7.readFileSync)(this.filePath, "utf-8"));
2027
2315
  if (parsed.schemaVersion !== SCHEMA_VERSION) return null;
2028
2316
  return {
2029
2317
  state: parsed.state,
@@ -2053,24 +2341,24 @@ function getFreshnessTracker(rootDir) {
2053
2341
  var GRAPHS_DIR2 = ".launchsecure/graphs";
2054
2342
  var NON_LAYER_GRAPH_FILES = /* @__PURE__ */ new Set(["tags.json", "effects-index.json"]);
2055
2343
  function getAvailableLayers(rootDir) {
2056
- const dir = (0, import_node_path9.join)(rootDir, GRAPHS_DIR2);
2057
- if (!(0, import_node_fs7.existsSync)(dir)) return [];
2058
- return (0, import_node_fs7.readdirSync)(dir).filter((f) => f.endsWith(".json") && !f.startsWith(".") && !NON_LAYER_GRAPH_FILES.has(f)).map((f) => f.replace(".json", ""));
2344
+ const dir = (0, import_node_path12.join)(rootDir, GRAPHS_DIR2);
2345
+ if (!(0, import_node_fs8.existsSync)(dir)) return [];
2346
+ return (0, import_node_fs8.readdirSync)(dir).filter((f) => f.endsWith(".json") && !f.startsWith(".") && !NON_LAYER_GRAPH_FILES.has(f)).map((f) => f.replace(".json", ""));
2059
2347
  }
2060
2348
  var graphCache = /* @__PURE__ */ new Map();
2061
2349
  var taggedCache = /* @__PURE__ */ new Map();
2062
2350
  function graphsDir(rootDir) {
2063
- return (0, import_node_path9.join)(rootDir, GRAPHS_DIR2);
2351
+ return (0, import_node_path12.join)(rootDir, GRAPHS_DIR2);
2064
2352
  }
2065
2353
  function graphFilePath(rootDir, layer) {
2066
- return (0, import_node_path9.join)(graphsDir(rootDir), `${layer}.json`);
2354
+ return (0, import_node_path12.join)(graphsDir(rootDir), `${layer}.json`);
2067
2355
  }
2068
2356
  function tagsFilePath2(rootDir) {
2069
- return (0, import_node_path9.join)(graphsDir(rootDir), "tags.json");
2357
+ return (0, import_node_path12.join)(graphsDir(rootDir), "tags.json");
2070
2358
  }
2071
2359
  function getMtimeMs(filePath) {
2072
- if (!(0, import_node_fs7.existsSync)(filePath)) return 0;
2073
- return (0, import_node_fs7.statSync)(filePath).mtimeMs;
2360
+ if (!(0, import_node_fs8.existsSync)(filePath)) return 0;
2361
+ return (0, import_node_fs8.statSync)(filePath).mtimeMs;
2074
2362
  }
2075
2363
  function invalidateCache(filePath) {
2076
2364
  graphCache.delete(filePath);
@@ -2109,20 +2397,20 @@ function applyTags(graph, layer, rootDir) {
2109
2397
  }
2110
2398
  function readGraphRaw(rootDir, layer) {
2111
2399
  const filePath = graphFilePath(rootDir, layer);
2112
- if (!(0, import_node_fs7.existsSync)(filePath)) return null;
2113
- const stat = (0, import_node_fs7.statSync)(filePath);
2400
+ if (!(0, import_node_fs8.existsSync)(filePath)) return null;
2401
+ const stat = (0, import_node_fs8.statSync)(filePath);
2114
2402
  const cached = graphCache.get(filePath);
2115
2403
  if (cached && cached.mtimeMs === stat.mtimeMs) {
2116
2404
  return cached.graph;
2117
2405
  }
2118
- const content = (0, import_node_fs7.readFileSync)(filePath, "utf-8");
2406
+ const content = (0, import_node_fs8.readFileSync)(filePath, "utf-8");
2119
2407
  const graph = JSON.parse(content);
2120
2408
  graphCache.set(filePath, { mtimeMs: stat.mtimeMs, graph });
2121
2409
  return graph;
2122
2410
  }
2123
2411
  function readGraph(rootDir, layer) {
2124
2412
  const rawFilePath = graphFilePath(rootDir, layer);
2125
- if (!(0, import_node_fs7.existsSync)(rawFilePath)) return null;
2413
+ if (!(0, import_node_fs8.existsSync)(rawFilePath)) return null;
2126
2414
  const rawMtime = getMtimeMs(rawFilePath);
2127
2415
  const tagsMtime = getMtimeMs(tagsFilePath2(rootDir));
2128
2416
  const cacheKey = `${rootDir}:${layer}`;
@@ -2146,7 +2434,7 @@ function readAllGraphs(rootDir) {
2146
2434
  }
2147
2435
  async function generateGraph(rootDir, layer) {
2148
2436
  const dir = graphsDir(rootDir);
2149
- (0, import_node_fs7.mkdirSync)(dir, { recursive: true });
2437
+ (0, import_node_fs8.mkdirSync)(dir, { recursive: true });
2150
2438
  const { results, failedFiles } = await runParseInWorker({ rootDir, layer });
2151
2439
  for (const result of results) {
2152
2440
  const filePath = graphFilePath(rootDir, result.layer);
@@ -2157,13 +2445,13 @@ async function generateGraph(rootDir, layer) {
2157
2445
  if (!layer) {
2158
2446
  const producedLayers = new Set(results.map((r) => r.layer));
2159
2447
  try {
2160
- for (const f of (0, import_node_fs7.readdirSync)(dir)) {
2161
- if (!f.endsWith(".json") || f === "tags.json" || f === "effects-index.json") continue;
2448
+ for (const f of (0, import_node_fs8.readdirSync)(dir)) {
2449
+ if (!f.endsWith(".json") || f === "tags.json" || f === "effects-index.json" || f === "context.json") continue;
2162
2450
  const layerName = f.replace(/\.json$/, "");
2163
2451
  if (producedLayers.has(layerName)) continue;
2164
- const orphan = (0, import_node_path9.join)(dir, f);
2452
+ const orphan = (0, import_node_path12.join)(dir, f);
2165
2453
  try {
2166
- (0, import_node_fs7.unlinkSync)(orphan);
2454
+ (0, import_node_fs8.unlinkSync)(orphan);
2167
2455
  invalidateCache(orphan);
2168
2456
  invalidateTaggedCache(rootDir, layerName);
2169
2457
  process.stderr.write(`[launch-chart] removed orphan layer file: ${f} (no parser produced ${layerName} this run)
@@ -2174,22 +2462,31 @@ async function generateGraph(rootDir, layer) {
2174
2462
  } catch {
2175
2463
  }
2176
2464
  }
2177
- try {
2178
- const allLayers = {};
2179
- for (const r of results) allLayers[r.layer] = r.output;
2180
- if (layer) {
2181
- for (const f of (0, import_node_fs7.readdirSync)(dir)) {
2182
- if (!f.endsWith(".json") || f === "tags.json" || f === "effects-index.json") continue;
2183
- const layerName = f.replace(/\.json$/, "");
2184
- if (allLayers[layerName]) continue;
2185
- const existing = readGraphRaw(rootDir, layerName);
2186
- if (existing) allLayers[layerName] = existing;
2187
- }
2465
+ const allLayers = {};
2466
+ for (const r of results) allLayers[r.layer] = r.output;
2467
+ if (layer) {
2468
+ for (const f of (0, import_node_fs8.readdirSync)(dir)) {
2469
+ if (!f.endsWith(".json") || f.startsWith(".") || f === "tags.json" || f === "effects-index.json" || f === "context.json") continue;
2470
+ const layerName = f.replace(/\.json$/, "");
2471
+ if (allLayers[layerName]) continue;
2472
+ const existing = readGraphRaw(rootDir, layerName);
2473
+ if (existing) allLayers[layerName] = existing;
2188
2474
  }
2475
+ }
2476
+ try {
2189
2477
  const idx = buildEffectsIndex(allLayers);
2190
2478
  writeEffectsIndex(rootDir, idx);
2191
2479
  } catch (e) {
2192
2480
  process.stderr.write(`[launch-chart] effects-index build failed: ${e.message}
2481
+ `);
2482
+ }
2483
+ try {
2484
+ const ctx = buildContextMap(allLayers, rootDir);
2485
+ const ctxPath = writeContextMap(rootDir, ctx);
2486
+ invalidateCache(ctxPath);
2487
+ invalidateTaggedCache(rootDir, "context");
2488
+ } catch (e) {
2489
+ process.stderr.write(`[launch-chart] context-map build failed: ${e.message}
2193
2490
  `);
2194
2491
  }
2195
2492
  try {
@@ -2208,29 +2505,29 @@ async function generateGraph(rootDir, layer) {
2208
2505
 
2209
2506
  // src/server/lockfile.ts
2210
2507
  var import_node_child_process = require("node:child_process");
2211
- var import_node_fs8 = require("node:fs");
2508
+ var import_node_fs9 = require("node:fs");
2212
2509
  var import_node_os = require("node:os");
2213
- var import_node_path10 = require("node:path");
2510
+ var import_node_path13 = require("node:path");
2214
2511
  init_launch_kit_paths();
2215
2512
  function lockDir(projectRoot) {
2216
2513
  if (projectRoot) {
2217
- return (0, import_node_path10.join)(projectRoot, LAUNCHSECURE_DIR);
2514
+ return (0, import_node_path13.join)(projectRoot, LAUNCHSECURE_DIR);
2218
2515
  }
2219
- return (0, import_node_path10.join)((0, import_node_os.homedir)(), LAUNCHSECURE_DIR);
2516
+ return (0, import_node_path13.join)((0, import_node_os.homedir)(), LAUNCHSECURE_DIR);
2220
2517
  }
2221
2518
  function lockPath(projectRoot) {
2222
- return (0, import_node_path10.join)(lockDir(projectRoot), "launch-chart.lock");
2519
+ return (0, import_node_path13.join)(lockDir(projectRoot), "launch-chart.lock");
2223
2520
  }
2224
2521
  var _activeProjectRoot;
2225
2522
  function readLock(projectRoot) {
2226
2523
  const root = projectRoot ?? _activeProjectRoot;
2227
2524
  const p = lockPath(root);
2228
- if (!(0, import_node_fs8.existsSync)(p)) {
2525
+ if (!(0, import_node_fs9.existsSync)(p)) {
2229
2526
  if (root) {
2230
2527
  const globalP = lockPath();
2231
- if ((0, import_node_fs8.existsSync)(globalP)) {
2528
+ if ((0, import_node_fs9.existsSync)(globalP)) {
2232
2529
  try {
2233
- const data = JSON.parse((0, import_node_fs8.readFileSync)(globalP, "utf-8"));
2530
+ const data = JSON.parse((0, import_node_fs9.readFileSync)(globalP, "utf-8"));
2234
2531
  if (typeof data.pid === "number" && typeof data.port === "number" && data.cwd === root) {
2235
2532
  return data;
2236
2533
  }
@@ -2241,7 +2538,7 @@ function readLock(projectRoot) {
2241
2538
  return null;
2242
2539
  }
2243
2540
  try {
2244
- const data = JSON.parse((0, import_node_fs8.readFileSync)(p, "utf-8"));
2541
+ const data = JSON.parse((0, import_node_fs9.readFileSync)(p, "utf-8"));
2245
2542
  if (typeof data.pid !== "number" || typeof data.port !== "number") return null;
2246
2543
  return data;
2247
2544
  } catch {
@@ -2278,7 +2575,7 @@ function getLiveLock(projectRoot) {
2278
2575
  const live = listenerPid !== null ? listenerPid === lock.pid : isPidAlive(lock.pid);
2279
2576
  if (!live) {
2280
2577
  try {
2281
- (0, import_node_fs8.unlinkSync)(lockPath(root));
2578
+ (0, import_node_fs9.unlinkSync)(lockPath(root));
2282
2579
  } catch {
2283
2580
  }
2284
2581
  return null;
@@ -2287,14 +2584,14 @@ function getLiveLock(projectRoot) {
2287
2584
  }
2288
2585
  function writeLock(data, projectRoot) {
2289
2586
  const root = projectRoot ?? _activeProjectRoot;
2290
- (0, import_node_fs8.mkdirSync)(lockDir(root), { recursive: true });
2291
- (0, import_node_fs8.writeFileSync)(lockPath(root), JSON.stringify(data, null, 2) + "\n", "utf-8");
2587
+ (0, import_node_fs9.mkdirSync)(lockDir(root), { recursive: true });
2588
+ (0, import_node_fs9.writeFileSync)(lockPath(root), JSON.stringify(data, null, 2) + "\n", "utf-8");
2292
2589
  if (root) _activeProjectRoot = root;
2293
2590
  }
2294
2591
  function clearLock(projectRoot) {
2295
2592
  const root = projectRoot ?? _activeProjectRoot;
2296
2593
  try {
2297
- (0, import_node_fs8.unlinkSync)(lockPath(root));
2594
+ (0, import_node_fs9.unlinkSync)(lockPath(root));
2298
2595
  } catch {
2299
2596
  }
2300
2597
  }
@@ -2303,20 +2600,20 @@ function clearLock(projectRoot) {
2303
2600
  init_config();
2304
2601
 
2305
2602
  // src/server/graph/core/parser-registry.ts
2306
- var import_node_path21 = require("node:path");
2603
+ var import_node_path24 = require("node:path");
2307
2604
 
2308
2605
  // src/server/graph/parsers/ts/typescript-project.ts
2309
- var import_node_fs12 = require("node:fs");
2310
- var import_node_path14 = require("node:path");
2606
+ var import_node_fs13 = require("node:fs");
2607
+ var import_node_path17 = require("node:path");
2311
2608
  init_config();
2312
2609
 
2313
2610
  // src/server/graph/core/resolve-paths.ts
2314
- var import_node_fs10 = require("node:fs");
2315
- var import_node_path12 = require("node:path");
2611
+ var import_node_fs11 = require("node:fs");
2612
+ var import_node_path15 = require("node:path");
2316
2613
 
2317
2614
  // src/server/graph/core/walk.ts
2318
- var import_node_fs9 = require("node:fs");
2319
- var import_node_path11 = require("node:path");
2615
+ var import_node_fs10 = require("node:fs");
2616
+ var import_node_path14 = require("node:path");
2320
2617
  var DEFAULT_IGNORE_DIRS = /* @__PURE__ */ new Set([
2321
2618
  "node_modules",
2322
2619
  "dist",
@@ -2326,12 +2623,12 @@ var DEFAULT_IGNORE_DIRS = /* @__PURE__ */ new Set([
2326
2623
  ]);
2327
2624
  function walk(dir, exts) {
2328
2625
  const results = [];
2329
- if (!(0, import_node_fs9.existsSync)(dir)) return results;
2330
- for (const entry of (0, import_node_fs9.readdirSync)(dir, { withFileTypes: true })) {
2331
- const full = (0, import_node_path11.join)(dir, entry.name);
2626
+ if (!(0, import_node_fs10.existsSync)(dir)) return results;
2627
+ for (const entry of (0, import_node_fs10.readdirSync)(dir, { withFileTypes: true })) {
2628
+ const full = (0, import_node_path14.join)(dir, entry.name);
2332
2629
  if (entry.isDirectory()) {
2333
2630
  results.push(...walk(full, exts));
2334
- } else if (exts.includes((0, import_node_path11.extname)(entry.name))) {
2631
+ } else if (exts.includes((0, import_node_path14.extname)(entry.name))) {
2335
2632
  results.push(full);
2336
2633
  }
2337
2634
  }
@@ -2339,15 +2636,15 @@ function walk(dir, exts) {
2339
2636
  }
2340
2637
  function walkWithIgnore(dir, exts, opts = {}) {
2341
2638
  const results = [];
2342
- if (!(0, import_node_fs9.existsSync)(dir)) return results;
2639
+ if (!(0, import_node_fs10.existsSync)(dir)) return results;
2343
2640
  const skip = opts.extraIgnore ? /* @__PURE__ */ new Set([...DEFAULT_IGNORE_DIRS, ...opts.extraIgnore]) : DEFAULT_IGNORE_DIRS;
2344
- for (const entry of (0, import_node_fs9.readdirSync)(dir, { withFileTypes: true })) {
2641
+ for (const entry of (0, import_node_fs10.readdirSync)(dir, { withFileTypes: true })) {
2345
2642
  if (entry.isDirectory()) {
2346
2643
  if (entry.name.startsWith(".")) continue;
2347
2644
  if (skip.has(entry.name)) continue;
2348
- results.push(...walkWithIgnore((0, import_node_path11.join)(dir, entry.name), exts, opts));
2349
- } else if (exts.includes((0, import_node_path11.extname)(entry.name))) {
2350
- results.push((0, import_node_path11.join)(dir, entry.name));
2645
+ results.push(...walkWithIgnore((0, import_node_path14.join)(dir, entry.name), exts, opts));
2646
+ } else if (exts.includes((0, import_node_path14.extname)(entry.name))) {
2647
+ results.push((0, import_node_path14.join)(dir, entry.name));
2351
2648
  }
2352
2649
  }
2353
2650
  return results;
@@ -2355,9 +2652,9 @@ function walkWithIgnore(dir, exts, opts = {}) {
2355
2652
 
2356
2653
  // src/server/graph/core/resolve-paths.ts
2357
2654
  function hasSqlFiles(dir) {
2358
- if (!(0, import_node_fs10.existsSync)(dir)) return false;
2655
+ if (!(0, import_node_fs11.existsSync)(dir)) return false;
2359
2656
  try {
2360
- return (0, import_node_fs10.readdirSync)(dir, { withFileTypes: true }).some(
2657
+ return (0, import_node_fs11.readdirSync)(dir, { withFileTypes: true }).some(
2361
2658
  (e) => e.isFile() && e.name.endsWith(".sql")
2362
2659
  );
2363
2660
  } catch {
@@ -2365,27 +2662,27 @@ function hasSqlFiles(dir) {
2365
2662
  }
2366
2663
  }
2367
2664
  function hasNestedMigrationSql(dir) {
2368
- if (!(0, import_node_fs10.existsSync)(dir)) return false;
2665
+ if (!(0, import_node_fs11.existsSync)(dir)) return false;
2369
2666
  try {
2370
- return (0, import_node_fs10.readdirSync)(dir, { withFileTypes: true }).some(
2371
- (e) => e.isDirectory() && (0, import_node_fs10.existsSync)((0, import_node_path12.join)(dir, e.name, "migration.sql"))
2667
+ return (0, import_node_fs11.readdirSync)(dir, { withFileTypes: true }).some(
2668
+ (e) => e.isDirectory() && (0, import_node_fs11.existsSync)((0, import_node_path15.join)(dir, e.name, "migration.sql"))
2372
2669
  );
2373
2670
  } catch {
2374
2671
  return false;
2375
2672
  }
2376
2673
  }
2377
2674
  function resolveDbFromDir(dir) {
2378
- if (!(0, import_node_fs10.existsSync)(dir)) return { kind: "none", schemaPath: null, migrationsDir: null };
2379
- const schemaPath = (0, import_node_path12.join)(dir, "schema.prisma");
2380
- if ((0, import_node_fs10.existsSync)(schemaPath)) {
2381
- const migrationsDir2 = (0, import_node_path12.join)(dir, "migrations");
2675
+ if (!(0, import_node_fs11.existsSync)(dir)) return { kind: "none", schemaPath: null, migrationsDir: null };
2676
+ const schemaPath = (0, import_node_path15.join)(dir, "schema.prisma");
2677
+ if ((0, import_node_fs11.existsSync)(schemaPath)) {
2678
+ const migrationsDir2 = (0, import_node_path15.join)(dir, "migrations");
2382
2679
  return {
2383
2680
  kind: "prisma",
2384
2681
  schemaPath,
2385
- migrationsDir: (0, import_node_fs10.existsSync)(migrationsDir2) ? migrationsDir2 : null
2682
+ migrationsDir: (0, import_node_fs11.existsSync)(migrationsDir2) ? migrationsDir2 : null
2386
2683
  };
2387
2684
  }
2388
- const migrationsDir = (0, import_node_path12.join)(dir, "migrations");
2685
+ const migrationsDir = (0, import_node_path15.join)(dir, "migrations");
2389
2686
  if (hasSqlFiles(migrationsDir) || hasNestedMigrationSql(migrationsDir)) {
2390
2687
  return { kind: "sql-migrations", migrationsDir, schemaPath: null };
2391
2688
  }
@@ -2396,19 +2693,19 @@ function resolveDbFromDir(dir) {
2396
2693
  }
2397
2694
  function detectDbConfig(rootDir, config) {
2398
2695
  if (config.paths?.dbDir) {
2399
- return resolveDbFromDir((0, import_node_path12.join)(rootDir, config.paths.dbDir));
2696
+ return resolveDbFromDir((0, import_node_path15.join)(rootDir, config.paths.dbDir));
2400
2697
  }
2401
- const candidates = ["prisma", "supabase", "drizzle", (0, import_node_path12.join)("db", "migrations"), "migrations"];
2698
+ const candidates = ["prisma", "supabase", "drizzle", (0, import_node_path15.join)("db", "migrations"), "migrations"];
2402
2699
  for (const c of candidates) {
2403
- const dir = (0, import_node_path12.join)(rootDir, c);
2700
+ const dir = (0, import_node_path15.join)(rootDir, c);
2404
2701
  const resolved = resolveDbFromDir(dir);
2405
2702
  if (resolved.kind !== "none") return resolved;
2406
2703
  }
2407
2704
  return { kind: "none", schemaPath: null, migrationsDir: null };
2408
2705
  }
2409
2706
  function detectDbDir(rootDir, config, dbConfig) {
2410
- if (config.paths?.dbDir) return (0, import_node_path12.join)(rootDir, config.paths.dbDir);
2411
- if (dbConfig.kind === "prisma") return (0, import_node_path12.dirname)(dbConfig.schemaPath);
2707
+ if (config.paths?.dbDir) return (0, import_node_path15.join)(rootDir, config.paths.dbDir);
2708
+ if (dbConfig.kind === "prisma") return (0, import_node_path15.dirname)(dbConfig.schemaPath);
2412
2709
  if (dbConfig.kind === "sql-migrations") return dbConfig.migrationsDir;
2413
2710
  return null;
2414
2711
  }
@@ -2439,16 +2736,16 @@ var NON_SOURCE_DIRS = /* @__PURE__ */ new Set([
2439
2736
  "libs"
2440
2737
  ]);
2441
2738
  function dirHasTSFiles(dir) {
2442
- if (!(0, import_node_fs10.existsSync)(dir)) return false;
2739
+ if (!(0, import_node_fs11.existsSync)(dir)) return false;
2443
2740
  try {
2444
2741
  const stack = [dir];
2445
2742
  while (stack.length > 0) {
2446
2743
  const cur = stack.pop();
2447
- const entries = (0, import_node_fs10.readdirSync)(cur, { withFileTypes: true });
2744
+ const entries = (0, import_node_fs11.readdirSync)(cur, { withFileTypes: true });
2448
2745
  for (const e of entries) {
2449
2746
  if (e.isFile() && (e.name.endsWith(".ts") || e.name.endsWith(".tsx"))) return true;
2450
2747
  if (e.isDirectory() && !e.name.startsWith(".") && !DEFAULT_IGNORE_DIRS.has(e.name)) {
2451
- stack.push((0, import_node_path12.join)(cur, e.name));
2748
+ stack.push((0, import_node_path15.join)(cur, e.name));
2452
2749
  }
2453
2750
  }
2454
2751
  }
@@ -2457,15 +2754,15 @@ function dirHasTSFiles(dir) {
2457
2754
  return false;
2458
2755
  }
2459
2756
  function collectCodeBearingChildren(dir, extraSkip) {
2460
- if (!(0, import_node_fs10.existsSync)(dir)) return [];
2757
+ if (!(0, import_node_fs11.existsSync)(dir)) return [];
2461
2758
  const out = [];
2462
2759
  try {
2463
- for (const entry of (0, import_node_fs10.readdirSync)(dir, { withFileTypes: true })) {
2760
+ for (const entry of (0, import_node_fs11.readdirSync)(dir, { withFileTypes: true })) {
2464
2761
  if (!entry.isDirectory()) continue;
2465
2762
  if (entry.name.startsWith(".")) continue;
2466
2763
  if (NON_SOURCE_DIRS.has(entry.name)) continue;
2467
2764
  if (extraSkip?.has(entry.name)) continue;
2468
- const full = (0, import_node_path12.join)(dir, entry.name);
2765
+ const full = (0, import_node_path15.join)(dir, entry.name);
2469
2766
  if (dirHasTSFiles(full)) out.push(full);
2470
2767
  }
2471
2768
  } catch {
@@ -2477,7 +2774,7 @@ function detectSrcRoots(rootDir, srcDir, appDir, config) {
2477
2774
  const roots2 = /* @__PURE__ */ new Set();
2478
2775
  roots2.add(appDir);
2479
2776
  for (const r of config.paths.srcRoots) {
2480
- const abs = (0, import_node_path12.isAbsolute)(r) ? r : (0, import_node_path12.resolve)(rootDir, r);
2777
+ const abs = (0, import_node_path15.isAbsolute)(r) ? r : (0, import_node_path15.resolve)(rootDir, r);
2481
2778
  roots2.add(abs);
2482
2779
  }
2483
2780
  return [...roots2];
@@ -2486,7 +2783,7 @@ function detectSrcRoots(rootDir, srcDir, appDir, config) {
2486
2783
  roots.add(appDir);
2487
2784
  for (const c of collectCodeBearingChildren(srcDir)) roots.add(c);
2488
2785
  if (srcDir !== rootDir) {
2489
- const skipSrcWrapper = /* @__PURE__ */ new Set([(0, import_node_path12.basename)(srcDir)]);
2786
+ const skipSrcWrapper = /* @__PURE__ */ new Set([(0, import_node_path15.basename)(srcDir)]);
2490
2787
  for (const c of collectCodeBearingChildren(rootDir, skipSrcWrapper)) roots.add(c);
2491
2788
  }
2492
2789
  return [...roots];
@@ -2498,10 +2795,10 @@ function detectConventionFiles(rootDir, srcDir) {
2498
2795
  const dirs = srcDir === rootDir ? [rootDir] : [srcDir, rootDir];
2499
2796
  for (const dir of dirs) {
2500
2797
  for (const name of CONVENTION_NAMES) {
2501
- const full = (0, import_node_path12.join)(dir, name);
2502
- if (!seen.has(full) && (0, import_node_fs10.existsSync)(full)) {
2798
+ const full = (0, import_node_path15.join)(dir, name);
2799
+ if (!seen.has(full) && (0, import_node_fs11.existsSync)(full)) {
2503
2800
  try {
2504
- if ((0, import_node_fs10.statSync)(full).isFile()) {
2801
+ if ((0, import_node_fs11.statSync)(full).isFile()) {
2505
2802
  seen.add(full);
2506
2803
  out.push(full);
2507
2804
  }
@@ -2516,22 +2813,22 @@ function resolveProjectPaths(rootDir, config) {
2516
2813
  let srcDir;
2517
2814
  let appDir;
2518
2815
  if (config.paths?.appDir) {
2519
- appDir = (0, import_node_path12.join)(rootDir, config.paths.appDir);
2520
- srcDir = config.paths.srcDir ? (0, import_node_path12.join)(rootDir, config.paths.srcDir) : (0, import_node_path12.dirname)(appDir);
2816
+ appDir = (0, import_node_path15.join)(rootDir, config.paths.appDir);
2817
+ srcDir = config.paths.srcDir ? (0, import_node_path15.join)(rootDir, config.paths.srcDir) : (0, import_node_path15.dirname)(appDir);
2521
2818
  } else {
2522
- const srcApp = (0, import_node_path12.join)(rootDir, "src", "app");
2523
- const rootApp = (0, import_node_path12.join)(rootDir, "app");
2524
- if ((0, import_node_fs10.existsSync)(srcApp)) {
2525
- srcDir = (0, import_node_path12.join)(rootDir, "src");
2819
+ const srcApp = (0, import_node_path15.join)(rootDir, "src", "app");
2820
+ const rootApp = (0, import_node_path15.join)(rootDir, "app");
2821
+ if ((0, import_node_fs11.existsSync)(srcApp)) {
2822
+ srcDir = (0, import_node_path15.join)(rootDir, "src");
2526
2823
  appDir = srcApp;
2527
- } else if ((0, import_node_fs10.existsSync)(rootApp)) {
2824
+ } else if ((0, import_node_fs11.existsSync)(rootApp)) {
2528
2825
  srcDir = rootDir;
2529
2826
  appDir = rootApp;
2530
2827
  } else {
2531
2828
  return null;
2532
2829
  }
2533
2830
  }
2534
- const apiDir = (0, import_node_path12.join)(appDir, "api");
2831
+ const apiDir = (0, import_node_path15.join)(appDir, "api");
2535
2832
  const dbConfig = detectDbConfig(rootDir, config);
2536
2833
  const dbDir = detectDbDir(rootDir, config, dbConfig);
2537
2834
  const srcRoots = detectSrcRoots(rootDir, srcDir, appDir, config);
@@ -2558,25 +2855,25 @@ var CLASSIFICATION_TO_LAYER = {
2558
2855
  external: "ui"
2559
2856
  };
2560
2857
  function toNodeId(srcDir, rootDir, absPath) {
2561
- const relFromSrc = (0, import_node_path14.relative)(srcDir, absPath).replace(/\\/g, "/");
2858
+ const relFromSrc = (0, import_node_path17.relative)(srcDir, absPath).replace(/\\/g, "/");
2562
2859
  if (relFromSrc.startsWith("..")) {
2563
- return (0, import_node_path14.relative)(rootDir, absPath).replace(/\\/g, "/");
2860
+ return (0, import_node_path17.relative)(rootDir, absPath).replace(/\\/g, "/");
2564
2861
  }
2565
2862
  return relFromSrc;
2566
2863
  }
2567
2864
  function resolveImport(srcDir, specifier) {
2568
2865
  if (!specifier.startsWith("@/")) return null;
2569
2866
  const rel = specifier.slice(2);
2570
- const base = (0, import_node_path14.join)(srcDir, rel);
2571
- for (const c of [base, base + ".ts", base + ".tsx", (0, import_node_path14.join)(base, "index.ts"), (0, import_node_path14.join)(base, "index.tsx")]) {
2572
- if ((0, import_node_fs12.existsSync)(c) && (0, import_node_fs12.statSync)(c).isFile()) return c;
2867
+ const base = (0, import_node_path17.join)(srcDir, rel);
2868
+ for (const c of [base, base + ".ts", base + ".tsx", (0, import_node_path17.join)(base, "index.ts"), (0, import_node_path17.join)(base, "index.tsx")]) {
2869
+ if ((0, import_node_fs13.existsSync)(c) && (0, import_node_fs13.statSync)(c).isFile()) return c;
2573
2870
  }
2574
2871
  return null;
2575
2872
  }
2576
2873
  function resolveRelativeImport(fromFile, specifier) {
2577
- const base = (0, import_node_path14.join)((0, import_node_path14.dirname)(fromFile), specifier);
2578
- for (const c of [base, base + ".ts", base + ".tsx", (0, import_node_path14.join)(base, "index.ts"), (0, import_node_path14.join)(base, "index.tsx")]) {
2579
- if ((0, import_node_fs12.existsSync)(c) && (0, import_node_fs12.statSync)(c).isFile()) return c;
2874
+ const base = (0, import_node_path17.join)((0, import_node_path17.dirname)(fromFile), specifier);
2875
+ for (const c of [base, base + ".ts", base + ".tsx", (0, import_node_path17.join)(base, "index.ts"), (0, import_node_path17.join)(base, "index.tsx")]) {
2876
+ if ((0, import_node_fs13.existsSync)(c) && (0, import_node_fs13.statSync)(c).isFile()) return c;
2580
2877
  }
2581
2878
  return null;
2582
2879
  }
@@ -2597,7 +2894,7 @@ function resolveBarrelMap(barrelAbsPath, parsedByPath, memo, visiting) {
2597
2894
  const resolved = resolveRelativeImport(barrelAbsPath, re.from);
2598
2895
  if (!resolved) continue;
2599
2896
  if (re.isWildcard) {
2600
- const targetBn = (0, import_node_path14.basename)(resolved);
2897
+ const targetBn = (0, import_node_path17.basename)(resolved);
2601
2898
  const targetIsBarrel = targetBn === "index.ts" || targetBn === "index.tsx";
2602
2899
  if (targetIsBarrel) {
2603
2900
  const nested = resolveBarrelMap(resolved, parsedByPath, memo, visiting);
@@ -2624,12 +2921,12 @@ function buildAllBarrelMaps(srcDir, parsedByPath) {
2624
2921
  const barrels = /* @__PURE__ */ new Map();
2625
2922
  const memo = /* @__PURE__ */ new Map();
2626
2923
  for (const [absPath, parsed] of parsedByPath) {
2627
- const bn = (0, import_node_path14.basename)(absPath);
2924
+ const bn = (0, import_node_path17.basename)(absPath);
2628
2925
  if (bn !== "index.ts" && bn !== "index.tsx") continue;
2629
2926
  if (parsed.reExports.length === 0) continue;
2630
2927
  const map = resolveBarrelMap(absPath, parsedByPath, memo, /* @__PURE__ */ new Set());
2631
2928
  if (map.size > 0) {
2632
- const barrelId = (0, import_node_path14.relative)(srcDir, (0, import_node_path14.dirname)(absPath)).replace(/\\/g, "/");
2929
+ const barrelId = (0, import_node_path17.relative)(srcDir, (0, import_node_path17.dirname)(absPath)).replace(/\\/g, "/");
2633
2930
  barrels.set(barrelId, map);
2634
2931
  }
2635
2932
  }
@@ -2654,10 +2951,10 @@ function extractRoute(id) {
2654
2951
  return route || "/";
2655
2952
  }
2656
2953
  function nameFromFilename(absPath) {
2657
- return (0, import_node_path14.basename)(absPath, (0, import_node_path14.extname)(absPath)).replace(/[-_](\w)/g, (_, c) => c.toUpperCase()).replace(/^(\w)/, (_, c) => c.toUpperCase());
2954
+ return (0, import_node_path17.basename)(absPath, (0, import_node_path17.extname)(absPath)).replace(/[-_](\w)/g, (_, c) => c.toUpperCase()).replace(/^(\w)/, (_, c) => c.toUpperCase());
2658
2955
  }
2659
2956
  function filePathToAppRoute(appDir, absPath) {
2660
- let route = ("/" + (0, import_node_path14.relative)(appDir, absPath).replace(/\\/g, "/")).replace(/\/route\.tsx?$/, "");
2957
+ let route = ("/" + (0, import_node_path17.relative)(appDir, absPath).replace(/\\/g, "/")).replace(/\/route\.tsx?$/, "");
2661
2958
  route = route.replace(/\/\([^)]+\)/g, "");
2662
2959
  route = route.replace(/\[\[\.\.\.([^\]]+)\]\]/g, "*$1?");
2663
2960
  route = route.replace(/\[\.\.\.([^\]]+)\]/g, "*$1");
@@ -2905,7 +3202,7 @@ function generate(rootDir) {
2905
3202
  const apiNodes = [];
2906
3203
  const nodeIdSet = /* @__PURE__ */ new Set();
2907
3204
  const routeToNodeId = /* @__PURE__ */ new Map();
2908
- const fileSet = allDiscovered.filter((f) => !(0, import_node_path14.basename)(f).startsWith("index."));
3205
+ const fileSet = allDiscovered.filter((f) => !(0, import_node_path17.basename)(f).startsWith("index."));
2909
3206
  for (const absPath of fileSet) {
2910
3207
  const id = toNodeId(srcDir, rootDir, absPath);
2911
3208
  const type = classifyType(absPath, id);
@@ -3065,7 +3362,7 @@ function generate(rootDir) {
3065
3362
  } catch {
3066
3363
  continue;
3067
3364
  }
3068
- const externalId = (0, import_node_path14.relative)(rootDir, absPath).replace(/\\/g, "/");
3365
+ const externalId = (0, import_node_path17.relative)(rootDir, absPath).replace(/\\/g, "/");
3069
3366
  const edgesFromThis = [];
3070
3367
  const seen = /* @__PURE__ */ new Set();
3071
3368
  for (const imp of parsed.imports) {
@@ -3415,7 +3712,7 @@ var typescriptProjectParser = {
3415
3712
  };
3416
3713
 
3417
3714
  // src/server/graph/parsers/db/prisma-schema.ts
3418
- var import_node_fs13 = require("node:fs");
3715
+ var import_node_fs14 = require("node:fs");
3419
3716
  init_config();
3420
3717
  function parseModels(content) {
3421
3718
  const nodes = [];
@@ -3508,7 +3805,7 @@ function parseEnums(content) {
3508
3805
  }
3509
3806
  function detect2(rootDir) {
3510
3807
  const paths = resolveProjectPaths(rootDir, loadConfig(rootDir));
3511
- return paths?.dbConfig.kind === "prisma" && (0, import_node_fs13.existsSync)(paths.dbConfig.schemaPath);
3808
+ return paths?.dbConfig.kind === "prisma" && (0, import_node_fs14.existsSync)(paths.dbConfig.schemaPath);
3512
3809
  }
3513
3810
  function generate2(rootDir) {
3514
3811
  const paths = resolveProjectPaths(rootDir, loadConfig(rootDir));
@@ -3525,7 +3822,7 @@ function generate2(rootDir) {
3525
3822
  };
3526
3823
  }
3527
3824
  const schemaPath = paths.dbConfig.schemaPath;
3528
- const content = (0, import_node_fs13.readFileSync)(schemaPath, "utf-8");
3825
+ const content = (0, import_node_fs14.readFileSync)(schemaPath, "utf-8");
3529
3826
  const { nodes: modelNodes, relations } = parseModels(content);
3530
3827
  const enumNodes = parseEnums(content);
3531
3828
  const allNodes = [...modelNodes, ...enumNodes];
@@ -3582,8 +3879,8 @@ var prismaSchemaParser = {
3582
3879
  };
3583
3880
 
3584
3881
  // src/server/graph/parsers/db/sql-migrations.ts
3585
- var import_node_fs14 = require("node:fs");
3586
- var import_node_path15 = require("node:path");
3882
+ var import_node_fs15 = require("node:fs");
3883
+ var import_node_path18 = require("node:path");
3587
3884
  var import_pgsql_parser = require("pgsql-parser");
3588
3885
  init_config();
3589
3886
  var PG_TO_PRISMA = {
@@ -3617,15 +3914,15 @@ function pgTypeToPrisma(pgType) {
3617
3914
  return PG_TO_PRISMA[upper] ?? upper;
3618
3915
  }
3619
3916
  function discoverMigrationFiles(migrationsDir) {
3620
- if (!(0, import_node_fs14.existsSync)(migrationsDir)) return [];
3917
+ if (!(0, import_node_fs15.existsSync)(migrationsDir)) return [];
3621
3918
  const out = [];
3622
- const entries = (0, import_node_fs14.readdirSync)(migrationsDir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
3919
+ const entries = (0, import_node_fs15.readdirSync)(migrationsDir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
3623
3920
  for (const entry of entries) {
3624
3921
  if (entry.isDirectory()) {
3625
- const sqlPath = (0, import_node_path15.join)(migrationsDir, entry.name, "migration.sql");
3626
- if ((0, import_node_fs14.existsSync)(sqlPath)) out.push(sqlPath);
3922
+ const sqlPath = (0, import_node_path18.join)(migrationsDir, entry.name, "migration.sql");
3923
+ if ((0, import_node_fs15.existsSync)(sqlPath)) out.push(sqlPath);
3627
3924
  } else if (entry.isFile() && entry.name.endsWith(".sql")) {
3628
- out.push((0, import_node_path15.join)(migrationsDir, entry.name));
3925
+ out.push((0, import_node_path18.join)(migrationsDir, entry.name));
3629
3926
  }
3630
3927
  }
3631
3928
  return out;
@@ -3670,7 +3967,7 @@ function parseMigrations(migrationsDir, dialect = postgresDialect) {
3670
3967
  };
3671
3968
  if (!migrationsDir) return state;
3672
3969
  for (const sqlPath of discoverMigrationFiles(migrationsDir)) {
3673
- const sql = (0, import_node_fs14.readFileSync)(sqlPath, "utf-8");
3970
+ const sql = (0, import_node_fs15.readFileSync)(sqlPath, "utf-8");
3674
3971
  let ast;
3675
3972
  try {
3676
3973
  ast = dialect.parse(sql);
@@ -4239,8 +4536,8 @@ function indexIsPrismaUncoverable(idx) {
4239
4536
  return idx.hasPredicate || idx.hasExpressions || idx.method !== "btree";
4240
4537
  }
4241
4538
  function loadPrismaState(schemaPath) {
4242
- if (!schemaPath || !(0, import_node_fs14.existsSync)(schemaPath)) return null;
4243
- const content = (0, import_node_fs14.readFileSync)(schemaPath, "utf-8");
4539
+ if (!schemaPath || !(0, import_node_fs15.existsSync)(schemaPath)) return null;
4540
+ const content = (0, import_node_fs15.readFileSync)(schemaPath, "utf-8");
4244
4541
  const tables = /* @__PURE__ */ new Map();
4245
4542
  const enums = /* @__PURE__ */ new Map();
4246
4543
  const relations = [];
@@ -4647,7 +4944,7 @@ function generate3(rootDir) {
4647
4944
  const migrationFiles = migrationsDir ? discoverMigrationFiles(migrationsDir) : [];
4648
4945
  let migrationNodeCount = 0;
4649
4946
  for (const sqlPath of migrationFiles) {
4650
- const sql = (0, import_node_fs14.readFileSync)(sqlPath, "utf-8");
4947
+ const sql = (0, import_node_fs15.readFileSync)(sqlPath, "utf-8");
4651
4948
  const name = deriveMigrationName(sqlPath);
4652
4949
  let ast;
4653
4950
  try {
@@ -4965,14 +5262,14 @@ var fetchResolverParser = {
4965
5262
  };
4966
5263
 
4967
5264
  // src/server/graph/parsers/crosslayer/api-annotations.ts
4968
- var import_node_fs15 = require("node:fs");
4969
- var import_node_path16 = require("node:path");
5265
+ var import_node_fs16 = require("node:fs");
5266
+ var import_node_path19 = require("node:path");
4970
5267
  init_config();
4971
5268
  var API_ANNOTATION_RE = /@api\s+(GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)\s+(\/\S+)/g;
4972
5269
  function toNodeId2(srcDir, rootDir, absPath) {
4973
- const relFromSrc = (0, import_node_path16.relative)(srcDir, absPath).replace(/\\/g, "/");
5270
+ const relFromSrc = (0, import_node_path19.relative)(srcDir, absPath).replace(/\\/g, "/");
4974
5271
  if (relFromSrc.startsWith("..")) {
4975
- return (0, import_node_path16.relative)(rootDir, absPath).replace(/\\/g, "/");
5272
+ return (0, import_node_path19.relative)(rootDir, absPath).replace(/\\/g, "/");
4976
5273
  }
4977
5274
  return relFromSrc;
4978
5275
  }
@@ -5017,7 +5314,7 @@ var apiAnnotationsParser = {
5017
5314
  const flaggedEdges = [];
5018
5315
  const seenEdge = /* @__PURE__ */ new Set();
5019
5316
  for (const absPath of files) {
5020
- const content = (0, import_node_fs15.readFileSync)(absPath, "utf-8");
5317
+ const content = (0, import_node_fs16.readFileSync)(absPath, "utf-8");
5021
5318
  const sourceId = toNodeId2(srcDir, rootDir, absPath);
5022
5319
  if (!uiNodeIds.has(sourceId)) continue;
5023
5320
  let match;
@@ -5061,14 +5358,14 @@ var apiAnnotationsParser = {
5061
5358
  };
5062
5359
 
5063
5360
  // src/server/graph/parsers/crosslayer/url-literal-scanner.ts
5064
- var import_node_fs16 = require("node:fs");
5065
- var import_node_path17 = require("node:path");
5361
+ var import_node_fs17 = require("node:fs");
5362
+ var import_node_path20 = require("node:path");
5066
5363
  init_config();
5067
5364
  var URL_LITERAL_RE = /['"`](\/[a-zA-Z][^'"`\s]*?)['"`]/g;
5068
5365
  function toNodeId3(srcDir, rootDir, absPath) {
5069
- const relFromSrc = (0, import_node_path17.relative)(srcDir, absPath).replace(/\\/g, "/");
5366
+ const relFromSrc = (0, import_node_path20.relative)(srcDir, absPath).replace(/\\/g, "/");
5070
5367
  if (relFromSrc.startsWith("..")) {
5071
- return (0, import_node_path17.relative)(rootDir, absPath).replace(/\\/g, "/");
5368
+ return (0, import_node_path20.relative)(rootDir, absPath).replace(/\\/g, "/");
5072
5369
  }
5073
5370
  return relFromSrc;
5074
5371
  }
@@ -5112,7 +5409,7 @@ var urlLiteralScannerParser = {
5112
5409
  for (const absPath of files) {
5113
5410
  const sourceId = toNodeId3(srcDir, rootDir, absPath);
5114
5411
  if (!uiNodeIds.has(sourceId)) continue;
5115
- const content = (0, import_node_fs16.readFileSync)(absPath, "utf-8");
5412
+ const content = (0, import_node_fs17.readFileSync)(absPath, "utf-8");
5116
5413
  let match;
5117
5414
  URL_LITERAL_RE.lastIndex = 0;
5118
5415
  while ((match = URL_LITERAL_RE.exec(content)) !== null) {
@@ -5143,8 +5440,8 @@ var urlLiteralScannerParser = {
5143
5440
  };
5144
5441
 
5145
5442
  // src/server/graph/parsers/static/static-values.ts
5146
- var import_node_fs17 = require("node:fs");
5147
- var import_node_path18 = require("node:path");
5443
+ var import_node_fs18 = require("node:fs");
5444
+ var import_node_path21 = require("node:path");
5148
5445
  init_config();
5149
5446
  var parseCode = null;
5150
5447
  function tryLoadTreeSitter() {
@@ -5181,21 +5478,21 @@ function extractEnumValues(rootDir) {
5181
5478
  const schemaPaths = [];
5182
5479
  if (paths?.dbConfig.kind === "prisma" && paths.dbConfig.schemaPath) {
5183
5480
  schemaPaths.push(paths.dbConfig.schemaPath);
5184
- schemaPaths.push((0, import_node_path18.join)((0, import_node_path18.dirname)(paths.dbConfig.schemaPath), "schema"));
5481
+ schemaPaths.push((0, import_node_path21.join)((0, import_node_path21.dirname)(paths.dbConfig.schemaPath), "schema"));
5185
5482
  } else {
5186
- schemaPaths.push((0, import_node_path18.join)(rootDir, "prisma", "schema.prisma"));
5187
- schemaPaths.push((0, import_node_path18.join)(rootDir, "prisma", "schema"));
5483
+ schemaPaths.push((0, import_node_path21.join)(rootDir, "prisma", "schema.prisma"));
5484
+ schemaPaths.push((0, import_node_path21.join)(rootDir, "prisma", "schema"));
5188
5485
  }
5189
5486
  let content = "";
5190
5487
  for (const p of schemaPaths) {
5191
- if ((0, import_node_fs17.existsSync)(p)) {
5488
+ if ((0, import_node_fs18.existsSync)(p)) {
5192
5489
  try {
5193
- const stat = (0, import_node_fs17.statSync)(p);
5490
+ const stat = (0, import_node_fs18.statSync)(p);
5194
5491
  if (stat.isFile()) {
5195
- content = (0, import_node_fs17.readFileSync)(p, "utf-8");
5492
+ content = (0, import_node_fs18.readFileSync)(p, "utf-8");
5196
5493
  } else if (stat.isDirectory()) {
5197
- const files = (0, import_node_fs17.readdirSync)(p).filter((f) => f.endsWith(".prisma"));
5198
- content = files.map((f) => (0, import_node_fs17.readFileSync)((0, import_node_path18.join)(p, f), "utf-8")).join("\n");
5494
+ const files = (0, import_node_fs18.readdirSync)(p).filter((f) => f.endsWith(".prisma"));
5495
+ content = files.map((f) => (0, import_node_fs18.readFileSync)((0, import_node_path21.join)(p, f), "utf-8")).join("\n");
5199
5496
  }
5200
5497
  } catch {
5201
5498
  continue;
@@ -5353,27 +5650,27 @@ function extractSeedData(rootDir) {
5353
5650
  const paths = resolveProjectPaths(rootDir, loadConfig(rootDir));
5354
5651
  const candidates = [];
5355
5652
  if (paths?.dbDir) {
5356
- candidates.push((0, import_node_path18.join)(paths.dbDir, "seed.ts"));
5357
- candidates.push((0, import_node_path18.join)(paths.dbDir, "seed.js"));
5653
+ candidates.push((0, import_node_path21.join)(paths.dbDir, "seed.ts"));
5654
+ candidates.push((0, import_node_path21.join)(paths.dbDir, "seed.js"));
5358
5655
  } else {
5359
- candidates.push((0, import_node_path18.join)(rootDir, "prisma", "seed.ts"));
5360
- candidates.push((0, import_node_path18.join)(rootDir, "prisma", "seed.js"));
5656
+ candidates.push((0, import_node_path21.join)(rootDir, "prisma", "seed.ts"));
5657
+ candidates.push((0, import_node_path21.join)(rootDir, "prisma", "seed.js"));
5361
5658
  }
5362
- const baseRoots = paths?.srcRoots ?? [(0, import_node_path18.join)(rootDir, "src")];
5659
+ const baseRoots = paths?.srcRoots ?? [(0, import_node_path21.join)(rootDir, "src")];
5363
5660
  for (const root of baseRoots) {
5364
- candidates.push((0, import_node_path18.join)(root, "server", "lib", "system-tags.ts"));
5661
+ candidates.push((0, import_node_path21.join)(root, "server", "lib", "system-tags.ts"));
5365
5662
  }
5366
5663
  const seedFiles = candidates.filter((p) => {
5367
5664
  try {
5368
- return (0, import_node_fs17.existsSync)(p) && (0, import_node_fs17.statSync)(p).isFile();
5665
+ return (0, import_node_fs18.existsSync)(p) && (0, import_node_fs18.statSync)(p).isFile();
5369
5666
  } catch {
5370
5667
  return false;
5371
5668
  }
5372
5669
  });
5373
5670
  const useTreeSitter = tryLoadTreeSitter();
5374
5671
  for (const filePath of seedFiles) {
5375
- const content = (0, import_node_fs17.readFileSync)(filePath, "utf-8");
5376
- const relPath = (0, import_node_path18.relative)(rootDir, filePath);
5672
+ const content = (0, import_node_fs18.readFileSync)(filePath, "utf-8");
5673
+ const relPath = (0, import_node_path21.relative)(rootDir, filePath);
5377
5674
  const seeded = detectSeededArrays(content, relPath);
5378
5675
  let astRoot = null;
5379
5676
  if (useTreeSitter && parseCode) {
@@ -5467,11 +5764,11 @@ function extractSeedData(rootDir) {
5467
5764
  return { nodes, edges };
5468
5765
  }
5469
5766
  function walkDir(dir, exts) {
5470
- if (!(0, import_node_fs17.existsSync)(dir)) return [];
5767
+ if (!(0, import_node_fs18.existsSync)(dir)) return [];
5471
5768
  const results = [];
5472
- for (const entry of (0, import_node_fs17.readdirSync)(dir, { withFileTypes: true })) {
5769
+ for (const entry of (0, import_node_fs18.readdirSync)(dir, { withFileTypes: true })) {
5473
5770
  if (entry.name === "node_modules" || entry.name === ".next" || entry.name === "dist") continue;
5474
- const full = (0, import_node_path18.join)(dir, entry.name);
5771
+ const full = (0, import_node_path21.join)(dir, entry.name);
5475
5772
  if (entry.isDirectory()) results.push(...walkDir(full, exts));
5476
5773
  else if (exts.some((ext) => entry.name.endsWith(ext))) results.push(full);
5477
5774
  }
@@ -5480,7 +5777,7 @@ function walkDir(dir, exts) {
5480
5777
  function extractConstants(rootDir) {
5481
5778
  const nodes = [];
5482
5779
  const paths = resolveProjectPaths(rootDir, loadConfig(rootDir));
5483
- const roots = paths?.srcRoots ?? [(0, import_node_path18.join)(rootDir, "src")];
5780
+ const roots = paths?.srcRoots ?? [(0, import_node_path21.join)(rootDir, "src")];
5484
5781
  const seenFile = /* @__PURE__ */ new Set();
5485
5782
  const allFiles = [];
5486
5783
  for (const root of roots) {
@@ -5493,8 +5790,8 @@ function extractConstants(rootDir) {
5493
5790
  }
5494
5791
  if (allFiles.length === 0) return { nodes };
5495
5792
  for (const filePath of allFiles) {
5496
- const content = (0, import_node_fs17.readFileSync)(filePath, "utf-8");
5497
- const relPath = (0, import_node_path18.relative)(rootDir, filePath);
5793
+ const content = (0, import_node_fs18.readFileSync)(filePath, "utf-8");
5794
+ const relPath = (0, import_node_path21.relative)(rootDir, filePath);
5498
5795
  const constArrayRe = /export\s+const\s+([A-Z][A-Z_0-9]+)\s*(?::[^=]+)?\s*=\s*\[/g;
5499
5796
  let cm;
5500
5797
  while ((cm = constArrayRe.exec(content)) !== null) {
@@ -5528,13 +5825,13 @@ function extractConstants(rootDir) {
5528
5825
  }
5529
5826
  function detect4(rootDir) {
5530
5827
  const paths = resolveProjectPaths(rootDir, loadConfig(rootDir));
5531
- if (paths?.dbConfig.kind === "prisma" && paths.dbConfig.schemaPath && (0, import_node_fs17.existsSync)(paths.dbConfig.schemaPath)) {
5828
+ if (paths?.dbConfig.kind === "prisma" && paths.dbConfig.schemaPath && (0, import_node_fs18.existsSync)(paths.dbConfig.schemaPath)) {
5532
5829
  return true;
5533
5830
  }
5534
5831
  if (paths?.dbDir) {
5535
- if ((0, import_node_fs17.existsSync)((0, import_node_path18.join)(paths.dbDir, "seed.ts")) || (0, import_node_fs17.existsSync)((0, import_node_path18.join)(paths.dbDir, "seed.js"))) return true;
5832
+ if ((0, import_node_fs18.existsSync)((0, import_node_path21.join)(paths.dbDir, "seed.ts")) || (0, import_node_fs18.existsSync)((0, import_node_path21.join)(paths.dbDir, "seed.js"))) return true;
5536
5833
  }
5537
- return (0, import_node_fs17.existsSync)((0, import_node_path18.join)(rootDir, "prisma", "schema.prisma")) || (0, import_node_fs17.existsSync)((0, import_node_path18.join)(rootDir, "prisma", "seed.ts"));
5834
+ return (0, import_node_fs18.existsSync)((0, import_node_path21.join)(rootDir, "prisma", "schema.prisma")) || (0, import_node_fs18.existsSync)((0, import_node_path21.join)(rootDir, "prisma", "seed.ts"));
5538
5835
  }
5539
5836
  function generate4(rootDir) {
5540
5837
  const enumResult = extractEnumValues(rootDir);
@@ -5609,8 +5906,8 @@ var staticValuesParser = {
5609
5906
  };
5610
5907
 
5611
5908
  // src/server/graph/parsers/crosslayer/static-ref-scanner.ts
5612
- var import_node_fs18 = require("node:fs");
5613
- var import_node_path19 = require("node:path");
5909
+ var import_node_fs19 = require("node:fs");
5910
+ var import_node_path22 = require("node:path");
5614
5911
  init_config();
5615
5912
  var MIN_VALUE_LENGTH = 4;
5616
5913
  var SKIP_VALUES = /* @__PURE__ */ new Set([
@@ -5785,11 +6082,11 @@ var staticRefScannerParser = {
5785
6082
  const seen = /* @__PURE__ */ new Set();
5786
6083
  let filesScanned = 0;
5787
6084
  for (const absPath of files) {
5788
- const relFromSrc = (0, import_node_path19.relative)(srcDir, absPath).replace(/\\/g, "/");
5789
- const sourceId = relFromSrc.startsWith("..") ? (0, import_node_path19.relative)(rootDir, absPath).replace(/\\/g, "/") : relFromSrc;
6085
+ const relFromSrc = (0, import_node_path22.relative)(srcDir, absPath).replace(/\\/g, "/");
6086
+ const sourceId = relFromSrc.startsWith("..") ? (0, import_node_path22.relative)(rootDir, absPath).replace(/\\/g, "/") : relFromSrc;
5790
6087
  const sourceLayer = uiNodeIds.has(sourceId) ? "ui" : apiNodeIds.has(sourceId) ? "api" : null;
5791
6088
  if (!sourceLayer) continue;
5792
- const content = (0, import_node_fs18.readFileSync)(absPath, "utf-8");
6089
+ const content = (0, import_node_fs19.readFileSync)(absPath, "utf-8");
5793
6090
  filesScanned++;
5794
6091
  let fileRefs;
5795
6092
  if (parseCode2) {
@@ -5831,13 +6128,13 @@ var staticRefScannerParser = {
5831
6128
  };
5832
6129
 
5833
6130
  // src/server/graph/parsers/crosslayer/middleware-gates.ts
5834
- var import_node_path20 = require("node:path");
6131
+ var import_node_path23 = require("node:path");
5835
6132
  init_ts_extractor();
5836
6133
  init_config();
5837
6134
  function toNodeId4(srcDir, rootDir, absPath) {
5838
- const relFromSrc = (0, import_node_path20.relative)(srcDir, absPath).replace(/\\/g, "/");
6135
+ const relFromSrc = (0, import_node_path23.relative)(srcDir, absPath).replace(/\\/g, "/");
5839
6136
  if (relFromSrc.startsWith("..")) {
5840
- return (0, import_node_path20.relative)(rootDir, absPath).replace(/\\/g, "/");
6137
+ return (0, import_node_path23.relative)(rootDir, absPath).replace(/\\/g, "/");
5841
6138
  }
5842
6139
  return relFromSrc;
5843
6140
  }
@@ -6118,7 +6415,7 @@ var ParserRegistry = class {
6118
6415
  return all;
6119
6416
  }
6120
6417
  };
6121
- function registerBuiltins2(registry, disabled) {
6418
+ function registerBuiltins3(registry, disabled) {
6122
6419
  const builtins = [
6123
6420
  typescriptProjectParser,
6124
6421
  prismaSchemaParser,
@@ -6139,7 +6436,7 @@ function registerBuiltins2(registry, disabled) {
6139
6436
  function loadCustomParsers(registry, config, rootDir, disabled) {
6140
6437
  for (const entry of config.parsers?.custom ?? []) {
6141
6438
  try {
6142
- const absPath = (0, import_node_path21.resolve)(rootDir, entry.path);
6439
+ const absPath = (0, import_node_path24.resolve)(rootDir, entry.path);
6143
6440
  const mod = require(absPath);
6144
6441
  const parser = "default" in mod ? mod.default : mod;
6145
6442
  if (disabled.has(parser.id)) continue;
@@ -6162,19 +6459,19 @@ function loadCustomParsers(registry, config, rootDir, disabled) {
6162
6459
  function createRegistry(config, rootDir) {
6163
6460
  const registry = new ParserRegistry();
6164
6461
  const disabled = new Set(config.parsers?.disabled ?? []);
6165
- registerBuiltins2(registry, disabled);
6462
+ registerBuiltins3(registry, disabled);
6166
6463
  loadCustomParsers(registry, config, rootDir, disabled);
6167
6464
  return registry;
6168
6465
  }
6169
6466
 
6170
6467
  // src/server/graph/core/audit-core.ts
6171
- var import_node_fs20 = require("node:fs");
6172
- var import_node_path23 = require("node:path");
6468
+ var import_node_fs21 = require("node:fs");
6469
+ var import_node_path26 = require("node:path");
6173
6470
  init_launch_kit_paths();
6174
6471
 
6175
6472
  // src/server/graph/core/audit-security.ts
6176
- var import_node_fs19 = require("node:fs");
6177
- var import_node_path22 = require("node:path");
6473
+ var import_node_fs20 = require("node:fs");
6474
+ var import_node_path25 = require("node:path");
6178
6475
  init_ts_extractor();
6179
6476
  init_config();
6180
6477
  function collectSourceFiles(rootDir) {
@@ -6199,9 +6496,9 @@ function collectSourceFiles(rootDir) {
6199
6496
  return out;
6200
6497
  }
6201
6498
  function toNodeId5(rootDir, srcDir, absPath) {
6202
- const relFromSrc = (0, import_node_path22.relative)(srcDir, absPath).replace(/\\/g, "/");
6499
+ const relFromSrc = (0, import_node_path25.relative)(srcDir, absPath).replace(/\\/g, "/");
6203
6500
  if (relFromSrc.startsWith("..")) {
6204
- return (0, import_node_path22.relative)(rootDir, absPath).replace(/\\/g, "/");
6501
+ return (0, import_node_path25.relative)(rootDir, absPath).replace(/\\/g, "/");
6205
6502
  }
6206
6503
  return relFromSrc;
6207
6504
  }
@@ -6311,18 +6608,18 @@ function collectDeclaredEnvKeys(rootDir) {
6311
6608
  const files = [];
6312
6609
  let entries = [];
6313
6610
  try {
6314
- entries = (0, import_node_fs19.readdirSync)(rootDir);
6611
+ entries = (0, import_node_fs20.readdirSync)(rootDir);
6315
6612
  } catch {
6316
6613
  return { keys, files };
6317
6614
  }
6318
6615
  for (const name of entries) {
6319
6616
  if (!name.startsWith(".env")) continue;
6320
- const abs = (0, import_node_path22.join)(rootDir, name);
6321
- if (!(0, import_node_fs19.existsSync)(abs)) continue;
6617
+ const abs = (0, import_node_path25.join)(rootDir, name);
6618
+ if (!(0, import_node_fs20.existsSync)(abs)) continue;
6322
6619
  files.push(name);
6323
6620
  let content = "";
6324
6621
  try {
6325
- content = (0, import_node_fs19.readFileSync)(abs, "utf-8");
6622
+ content = (0, import_node_fs20.readFileSync)(abs, "utf-8");
6326
6623
  } catch {
6327
6624
  continue;
6328
6625
  }
@@ -6509,10 +6806,10 @@ function checkHardcodedUrlFallback(rootDir, core) {
6509
6806
 
6510
6807
  // src/server/graph/core/audit-core.ts
6511
6808
  function readGraphFile(rootDir, layer) {
6512
- const filePath = (0, import_node_path23.join)(rootDir, LAUNCHSECURE_DIR, "graphs", `${layer}.json`);
6513
- if (!(0, import_node_fs20.existsSync)(filePath)) return null;
6809
+ const filePath = (0, import_node_path26.join)(rootDir, LAUNCHSECURE_DIR, "graphs", `${layer}.json`);
6810
+ if (!(0, import_node_fs21.existsSync)(filePath)) return null;
6514
6811
  try {
6515
- return JSON.parse((0, import_node_fs20.readFileSync)(filePath, "utf-8"));
6812
+ return JSON.parse((0, import_node_fs21.readFileSync)(filePath, "utf-8"));
6516
6813
  } catch {
6517
6814
  return null;
6518
6815
  }
@@ -6554,15 +6851,15 @@ function checkUnprotectedRoutes(rootDir) {
6554
6851
  const findings = [];
6555
6852
  const api = readGraphFile(rootDir, "api");
6556
6853
  if (!api) return buildSkipped("api", "unprotected_routes", "no api graph");
6557
- const routePermsPath = (0, import_node_path23.join)(rootDir, "src", "config", "route-permissions.ts");
6558
- if (!(0, import_node_fs20.existsSync)(routePermsPath)) {
6854
+ const routePermsPath = (0, import_node_path26.join)(rootDir, "src", "config", "route-permissions.ts");
6855
+ if (!(0, import_node_fs21.existsSync)(routePermsPath)) {
6559
6856
  return buildSkipped(
6560
6857
  "api",
6561
6858
  "unprotected_routes",
6562
6859
  `no src/config/route-permissions.ts \u2014 this check needs a centralized ROUTE_PERMISSIONS inventory to compare endpoints against`
6563
6860
  );
6564
6861
  }
6565
- const routePermsContent = (0, import_node_fs20.readFileSync)(routePermsPath, "utf-8");
6862
+ const routePermsContent = (0, import_node_fs21.readFileSync)(routePermsPath, "utf-8");
6566
6863
  const registeredRoutes = /* @__PURE__ */ new Set();
6567
6864
  const routeEntryRe = /path:\s*'([^']+)'/g;
6568
6865
  let rm;
@@ -6647,15 +6944,15 @@ function checkUnenforcedPermissions(rootDir) {
6647
6944
  `no seed_permission nodes \u2014 this project either has no seed permissions or hasn't tagged them in seed.ts`
6648
6945
  );
6649
6946
  }
6650
- const routePermsPath = (0, import_node_path23.join)(rootDir, "src", "config", "route-permissions.ts");
6651
- if (!(0, import_node_fs20.existsSync)(routePermsPath)) {
6947
+ const routePermsPath = (0, import_node_path26.join)(rootDir, "src", "config", "route-permissions.ts");
6948
+ if (!(0, import_node_fs21.existsSync)(routePermsPath)) {
6652
6949
  return buildSkipped(
6653
6950
  "static",
6654
6951
  "unenforced_permissions",
6655
6952
  `no src/config/route-permissions.ts to compare seed permissions against`
6656
6953
  );
6657
6954
  }
6658
- const routePermsContent = (0, import_node_fs20.readFileSync)(routePermsPath, "utf-8");
6955
+ const routePermsContent = (0, import_node_fs21.readFileSync)(routePermsPath, "utf-8");
6659
6956
  for (const perm of permissions) {
6660
6957
  const regex = new RegExp(`permission:\\s*['"]${perm.key}['"]`);
6661
6958
  if (!regex.test(routePermsContent)) {
@@ -6691,9 +6988,9 @@ function checkHardcodedValues(rootDir) {
6691
6988
  const seen = /* @__PURE__ */ new Set();
6692
6989
  for (const node of api.nodes) {
6693
6990
  if (node.type !== "endpoint") continue;
6694
- const filePath = (0, import_node_path23.join)(rootDir, "src", node.id);
6695
- if (!(0, import_node_fs20.existsSync)(filePath)) continue;
6696
- const content = (0, import_node_fs20.readFileSync)(filePath, "utf-8");
6991
+ const filePath = (0, import_node_path26.join)(rootDir, "src", node.id);
6992
+ if (!(0, import_node_fs21.existsSync)(filePath)) continue;
6993
+ const content = (0, import_node_fs21.readFileSync)(filePath, "utf-8");
6697
6994
  let m;
6698
6995
  allCapsRe.lastIndex = 0;
6699
6996
  while ((m = allCapsRe.exec(content)) !== null) {
@@ -6853,16 +7150,16 @@ var MIME_TYPES = {
6853
7150
  function findProjectRoot(startDir) {
6854
7151
  let dir = startDir;
6855
7152
  for (let i = 0; i < 8; i++) {
6856
- const graphsDir2 = import_node_path24.default.join(dir, LAUNCHSECURE_DIR, "graphs");
6857
- if (import_node_fs21.default.existsSync(import_node_path24.default.join(graphsDir2, "ui.json")) || import_node_fs21.default.existsSync(import_node_path24.default.join(graphsDir2, "api.json")) || import_node_fs21.default.existsSync(import_node_path24.default.join(graphsDir2, "db.json"))) return dir;
6858
- const parent = import_node_path24.default.dirname(dir);
7153
+ const graphsDir2 = import_node_path27.default.join(dir, LAUNCHSECURE_DIR, "graphs");
7154
+ if (import_node_fs22.default.existsSync(import_node_path27.default.join(graphsDir2, "ui.json")) || import_node_fs22.default.existsSync(import_node_path27.default.join(graphsDir2, "api.json")) || import_node_fs22.default.existsSync(import_node_path27.default.join(graphsDir2, "db.json"))) return dir;
7155
+ const parent = import_node_path27.default.dirname(dir);
6859
7156
  if (parent === dir) break;
6860
7157
  dir = parent;
6861
7158
  }
6862
7159
  dir = startDir;
6863
7160
  for (let i = 0; i < 8; i++) {
6864
- if (import_node_fs21.default.existsSync(import_node_path24.default.join(dir, ".git"))) return dir;
6865
- const parent = import_node_path24.default.dirname(dir);
7161
+ if (import_node_fs22.default.existsSync(import_node_path27.default.join(dir, ".git"))) return dir;
7162
+ const parent = import_node_path27.default.dirname(dir);
6866
7163
  if (parent === dir) break;
6867
7164
  dir = parent;
6868
7165
  }
@@ -6871,7 +7168,7 @@ function findProjectRoot(startDir) {
6871
7168
  function resolveRequestRoot(url, monorepoRoot, projects) {
6872
7169
  const projectParam = url.searchParams.get("project");
6873
7170
  if (!projectParam || projects.length === 0) return monorepoRoot;
6874
- const resolved = import_node_path24.default.resolve(monorepoRoot, projectParam);
7171
+ const resolved = import_node_path27.default.resolve(monorepoRoot, projectParam);
6875
7172
  if (!resolved.startsWith(monorepoRoot)) {
6876
7173
  throw new Error("Project path outside monorepo root");
6877
7174
  }
@@ -6922,16 +7219,16 @@ async function buildMergedGraph(root) {
6922
7219
  };
6923
7220
  }
6924
7221
  function serveStatic(res, filePath) {
6925
- if (!import_node_fs21.default.existsSync(filePath) || !import_node_fs21.default.statSync(filePath).isFile()) return false;
6926
- const ext = import_node_path24.default.extname(filePath).toLowerCase();
7222
+ if (!import_node_fs22.default.existsSync(filePath) || !import_node_fs22.default.statSync(filePath).isFile()) return false;
7223
+ const ext = import_node_path27.default.extname(filePath).toLowerCase();
6927
7224
  const mime = MIME_TYPES[ext] ?? "application/octet-stream";
6928
7225
  res.writeHead(200, { "Content-Type": mime, "Cache-Control": "no-cache" });
6929
- import_node_fs21.default.createReadStream(filePath).pipe(res);
7226
+ import_node_fs22.default.createReadStream(filePath).pipe(res);
6930
7227
  return true;
6931
7228
  }
6932
7229
  function serveIndex(res, clientDir) {
6933
- const indexPath = import_node_path24.default.join(clientDir, "index.html");
6934
- if (!import_node_fs21.default.existsSync(indexPath)) {
7230
+ const indexPath = import_node_path27.default.join(clientDir, "index.html");
7231
+ if (!import_node_fs22.default.existsSync(indexPath)) {
6935
7232
  res.writeHead(500, { "Content-Type": "text/plain" });
6936
7233
  res.end(`LaunchChart client bundle not found at ${clientDir}. Run 'npm run build:chart-client'.`);
6937
7234
  return;
@@ -6939,14 +7236,14 @@ function serveIndex(res, clientDir) {
6939
7236
  serveStatic(res, indexPath);
6940
7237
  }
6941
7238
  function tryListen(server, port) {
6942
- return new Promise((resolve4, reject) => {
7239
+ return new Promise((resolve5, reject) => {
6943
7240
  const onError = (err) => {
6944
7241
  server.off("listening", onListening);
6945
7242
  reject(err);
6946
7243
  };
6947
7244
  const onListening = () => {
6948
7245
  server.off("error", onError);
6949
- resolve4(port);
7246
+ resolve5(port);
6950
7247
  };
6951
7248
  server.once("error", onError);
6952
7249
  server.once("listening", onListening);
@@ -6983,7 +7280,7 @@ async function startChartServer(opts = {}) {
6983
7280
  }
6984
7281
  return { port: existing.port, url: existing.url };
6985
7282
  }
6986
- const clientDir = opts.clientDir ?? import_node_path24.default.join(__dirname, "..", "chart-client");
7283
+ const clientDir = opts.clientDir ?? import_node_path27.default.join(__dirname, "..", "chart-client");
6987
7284
  const rootConfig = loadConfig(projectRoot);
6988
7285
  const projects = rootConfig.projects ?? [];
6989
7286
  const server = import_node_http.default.createServer((req, res) => {
@@ -6999,11 +7296,11 @@ async function startChartServer(opts = {}) {
6999
7296
  }
7000
7297
  if (req.method === "GET" && url2.pathname === "/api/projects") {
7001
7298
  const projectList = projects.length > 0 ? projects.map((p) => {
7002
- const absRoot = import_node_path24.default.resolve(projectRoot, p.root);
7003
- const hasGraphs = import_node_fs21.default.existsSync(import_node_path24.default.join(absRoot, LAUNCHSECURE_DIR, "graphs"));
7004
- const hasNextConfig = import_node_fs21.default.existsSync(import_node_path24.default.join(absRoot, "next.config.ts")) || import_node_fs21.default.existsSync(import_node_path24.default.join(absRoot, "next.config.js")) || import_node_fs21.default.existsSync(import_node_path24.default.join(absRoot, "next.config.mjs"));
7299
+ const absRoot = import_node_path27.default.resolve(projectRoot, p.root);
7300
+ const hasGraphs = import_node_fs22.default.existsSync(import_node_path27.default.join(absRoot, LAUNCHSECURE_DIR, "graphs"));
7301
+ const hasNextConfig = import_node_fs22.default.existsSync(import_node_path27.default.join(absRoot, "next.config.ts")) || import_node_fs22.default.existsSync(import_node_path27.default.join(absRoot, "next.config.js")) || import_node_fs22.default.existsSync(import_node_path27.default.join(absRoot, "next.config.mjs"));
7005
7302
  return { name: p.name, root: p.root, hasGraphs, hasNextConfig };
7006
- }) : [{ name: import_node_path24.default.basename(projectRoot), root: ".", hasGraphs: import_node_fs21.default.existsSync(import_node_path24.default.join(projectRoot, LAUNCHSECURE_DIR, "graphs")), hasNextConfig: true }];
7303
+ }) : [{ name: import_node_path27.default.basename(projectRoot), root: ".", hasGraphs: import_node_fs22.default.existsSync(import_node_path27.default.join(projectRoot, LAUNCHSECURE_DIR, "graphs")), hasNextConfig: true }];
7007
7304
  res.writeHead(200, { "Content-Type": "application/json" });
7008
7305
  res.end(JSON.stringify({ projects: projectList, monorepoRoot: projectRoot }));
7009
7306
  return;
@@ -7049,20 +7346,20 @@ async function startChartServer(opts = {}) {
7049
7346
  }
7050
7347
  if (req.method === "GET" && url2.pathname === "/api/file-content") {
7051
7348
  const relPath = url2.searchParams.get("path");
7052
- if (!relPath || relPath.includes("..") || import_node_path24.default.isAbsolute(relPath)) {
7349
+ if (!relPath || relPath.includes("..") || import_node_path27.default.isAbsolute(relPath)) {
7053
7350
  res.writeHead(400, { "Content-Type": "application/json" });
7054
7351
  res.end(JSON.stringify({ error: "Invalid path" }));
7055
7352
  return;
7056
7353
  }
7057
- const filePath = import_node_path24.default.join(reqRoot, relPath);
7058
- if (!filePath.startsWith(reqRoot) || !import_node_fs21.default.existsSync(filePath) || !import_node_fs21.default.statSync(filePath).isFile()) {
7354
+ const filePath = import_node_path27.default.join(reqRoot, relPath);
7355
+ if (!filePath.startsWith(reqRoot) || !import_node_fs22.default.existsSync(filePath) || !import_node_fs22.default.statSync(filePath).isFile()) {
7059
7356
  res.writeHead(404, { "Content-Type": "application/json" });
7060
7357
  res.end(JSON.stringify({ error: "File not found" }));
7061
7358
  return;
7062
7359
  }
7063
- const ext = import_node_path24.default.extname(filePath).toLowerCase();
7360
+ const ext = import_node_path27.default.extname(filePath).toLowerCase();
7064
7361
  const langMap = { ".ts": "typescript", ".tsx": "tsx", ".js": "javascript", ".jsx": "jsx", ".prisma": "prisma", ".json": "json", ".css": "css" };
7065
- const content = import_node_fs21.default.readFileSync(filePath, "utf-8");
7362
+ const content = import_node_fs22.default.readFileSync(filePath, "utf-8");
7066
7363
  res.writeHead(200, { "Content-Type": "application/json" });
7067
7364
  res.end(JSON.stringify({ content, language: langMap[ext] ?? "text", path: relPath }));
7068
7365
  return;
@@ -7117,8 +7414,8 @@ async function startChartServer(opts = {}) {
7117
7414
  const newConfig = JSON.parse(body);
7118
7415
  const existingConfig = loadConfig(reqRoot);
7119
7416
  const merged = { ...existingConfig, ...newConfig };
7120
- const configPath = import_node_path24.default.join(reqRoot, LAUNCHCHART_CONFIG_FILE);
7121
- import_node_fs21.default.writeFileSync(configPath, JSON.stringify(merged, null, 2) + "\n", "utf-8");
7417
+ const configPath = import_node_path27.default.join(reqRoot, LAUNCHCHART_CONFIG_FILE);
7418
+ import_node_fs22.default.writeFileSync(configPath, JSON.stringify(merged, null, 2) + "\n", "utf-8");
7122
7419
  res.writeHead(200, { "Content-Type": "application/json" });
7123
7420
  res.end(JSON.stringify({ ok: true }));
7124
7421
  } catch (err) {
@@ -7151,8 +7448,8 @@ async function startChartServer(opts = {}) {
7151
7448
  const taggerConfig = JSON.parse(body);
7152
7449
  const config2 = loadConfig(reqRoot);
7153
7450
  config2.taggers = taggerConfig;
7154
- const configPath = import_node_path24.default.join(reqRoot, LAUNCHCHART_CONFIG_FILE);
7155
- import_node_fs21.default.writeFileSync(configPath, JSON.stringify(config2, null, 2) + "\n", "utf-8");
7451
+ const configPath = import_node_path27.default.join(reqRoot, LAUNCHCHART_CONFIG_FILE);
7452
+ import_node_fs22.default.writeFileSync(configPath, JSON.stringify(config2, null, 2) + "\n", "utf-8");
7156
7453
  res.writeHead(200, { "Content-Type": "application/json" });
7157
7454
  res.end(JSON.stringify({ ok: true }));
7158
7455
  } catch (err) {
@@ -7222,7 +7519,7 @@ async function startChartServer(opts = {}) {
7222
7519
  dbDir: !!config2.paths?.dbDir,
7223
7520
  srcRoots: !!(config2.paths?.srcRoots && config2.paths.srcRoots.length > 0)
7224
7521
  };
7225
- const relFromRoot = (abs) => import_node_path24.default.relative(reqRoot, abs) || ".";
7522
+ const relFromRoot = (abs) => import_node_path27.default.relative(reqRoot, abs) || ".";
7226
7523
  res.writeHead(200, { "Content-Type": "application/json" });
7227
7524
  res.end(JSON.stringify({
7228
7525
  projectRoot: reqRoot,
@@ -7244,19 +7541,19 @@ async function startChartServer(opts = {}) {
7244
7541
  }
7245
7542
  if (req.method === "GET" && url2.pathname === "/api/browse-dir") {
7246
7543
  const browsePath = url2.searchParams.get("path") || projectRoot;
7247
- const abs = import_node_path24.default.resolve(browsePath);
7248
- const twoUp = import_node_path24.default.resolve(projectRoot, "..", "..");
7544
+ const abs = import_node_path27.default.resolve(browsePath);
7545
+ const twoUp = import_node_path27.default.resolve(projectRoot, "..", "..");
7249
7546
  if (!abs.startsWith(twoUp)) {
7250
7547
  res.writeHead(403, { "Content-Type": "application/json" });
7251
7548
  res.end(JSON.stringify({ ok: false, error: "Path outside allowed range" }));
7252
7549
  return;
7253
7550
  }
7254
7551
  try {
7255
- const entries = import_node_fs21.default.readdirSync(abs, { withFileTypes: true });
7552
+ const entries = import_node_fs22.default.readdirSync(abs, { withFileTypes: true });
7256
7553
  const dirs = entries.filter((e) => e.isDirectory() && !e.name.startsWith(".") && e.name !== "node_modules" && e.name !== "dist" && e.name !== ".next").map((e) => e.name).sort();
7257
- const parent = abs !== twoUp ? import_node_path24.default.dirname(abs) : null;
7554
+ const parent = abs !== twoUp ? import_node_path27.default.dirname(abs) : null;
7258
7555
  res.writeHead(200, { "Content-Type": "application/json" });
7259
- res.end(JSON.stringify({ current: abs, parent, dirs, relative: import_node_path24.default.relative(projectRoot, abs) || "." }));
7556
+ res.end(JSON.stringify({ current: abs, parent, dirs, relative: import_node_path27.default.relative(projectRoot, abs) || "." }));
7260
7557
  } catch (err) {
7261
7558
  res.writeHead(400, { "Content-Type": "application/json" });
7262
7559
  res.end(JSON.stringify({ ok: false, error: String(err) }));
@@ -7282,8 +7579,8 @@ async function startChartServer(opts = {}) {
7282
7579
  const { projects: newProjects } = JSON.parse(body);
7283
7580
  const config2 = loadConfig(projectRoot);
7284
7581
  config2.projects = newProjects.length > 0 ? newProjects : void 0;
7285
- const configPath = import_node_path24.default.join(projectRoot, LAUNCHCHART_CONFIG_FILE);
7286
- import_node_fs21.default.writeFileSync(configPath, JSON.stringify(config2, null, 2) + "\n", "utf-8");
7582
+ const configPath = import_node_path27.default.join(projectRoot, LAUNCHCHART_CONFIG_FILE);
7583
+ import_node_fs22.default.writeFileSync(configPath, JSON.stringify(config2, null, 2) + "\n", "utf-8");
7287
7584
  projects.length = 0;
7288
7585
  if (config2.projects) projects.push(...config2.projects);
7289
7586
  res.writeHead(200, { "Content-Type": "application/json" });
@@ -7296,7 +7593,7 @@ async function startChartServer(opts = {}) {
7296
7593
  return;
7297
7594
  }
7298
7595
  if (url2.pathname !== "/") {
7299
- const staticPath = import_node_path24.default.join(clientDir, url2.pathname);
7596
+ const staticPath = import_node_path27.default.join(clientDir, url2.pathname);
7300
7597
  if (serveStatic(res, staticPath)) return;
7301
7598
  }
7302
7599
  serveIndex(res, clientDir);