lurqrun 0.1.7 → 0.1.8

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 (122) hide show
  1. package/README.md +312 -148
  2. package/dist/{auditHandler-JCOJSUYW.js → auditHandler-VWCXSDVO.js} +12 -11
  3. package/dist/autopilotInit-Q62MX5M6.js +178 -0
  4. package/dist/bin/lurq.js +235 -83
  5. package/dist/{browserAuth-B6G27USY.js → browserAuth-J7APSD4P.js} +4 -3
  6. package/dist/{cache-DKI34SVS.js → cache-AEAKCV4I.js} +2 -2
  7. package/dist/check-2JTQDQA6.js +2613 -0
  8. package/dist/{check-2FDGUOV7.js → check-PQSQ2MMA.js} +1 -1
  9. package/dist/checkUpgrade-5YW77OBL.js +24 -0
  10. package/dist/{chunk-BCANRN5B.js → chunk-2GAYNIHG.js} +8 -1
  11. package/dist/{chunk-EA3DP5HG.js → chunk-2O6Z37IT.js} +155 -25
  12. package/dist/{chunk-J5FZYN4A.js → chunk-2WD4QAH4.js} +1 -1
  13. package/dist/{chunk-CUP36ND3.js → chunk-3676XOBU.js} +145 -36
  14. package/dist/chunk-3D2MPGOQ.js +181 -0
  15. package/dist/{chunk-LYMPYETA.js → chunk-4JHDSVIN.js} +270 -6
  16. package/dist/chunk-53SG6XWA.js +141 -0
  17. package/dist/chunk-5ABNDB3I.js +37 -0
  18. package/dist/chunk-5ALIJFDA.js +114 -0
  19. package/dist/{chunk-BULZAX2U.js → chunk-64ZF7KO4.js} +55 -38
  20. package/dist/{chunk-2VMOWSRY.js → chunk-6DM6UQFD.js} +19 -1
  21. package/dist/{chunk-HWBBVLOT.js → chunk-6L67QMCP.js} +1 -1
  22. package/dist/{chunk-GPTKSNR6.js → chunk-72Y2FDVS.js} +2 -1
  23. package/dist/{chunk-B43LCXBM.js → chunk-A3TYI2TF.js} +81 -16
  24. package/dist/{chunk-IQ4SDKKY.js → chunk-B2UUYRBX.js} +31 -228
  25. package/dist/{chunk-DB2VF5UD.js → chunk-BJT2LHAR.js} +16 -11
  26. package/dist/chunk-BM3LF5T6.js +132 -0
  27. package/dist/{chunk-3N3Q3DSW.js → chunk-BN3NM47Q.js} +8 -8
  28. package/dist/chunk-D3K6IZVR.js +12845 -0
  29. package/dist/{chunk-AHBP533R.js → chunk-D3VTZS7V.js} +7 -5
  30. package/dist/{chunk-UDVNA7EA.js → chunk-DM37MTOO.js} +161 -8
  31. package/dist/chunk-DONTW3NE.js +171 -0
  32. package/dist/{chunk-M6NYEXCW.js → chunk-DSROTZ3Z.js} +1 -1
  33. package/dist/{chunk-4F7ZESPO.js → chunk-EQCXENKZ.js} +3 -5
  34. package/dist/{chunk-CW5HJ3LX.js → chunk-EYAKM6YN.js} +1 -1
  35. package/dist/{chunk-VL2E5T2A.js → chunk-FDFPMBCA.js} +6 -3
  36. package/dist/{chunk-BV32UNLL.js → chunk-FVYFV5HA.js} +2 -2
  37. package/dist/{chunk-DWAGCNEL.js → chunk-GM5Y555O.js} +36 -103
  38. package/dist/{chunk-PSX3GIAN.js → chunk-HWFX4BC4.js} +2 -1
  39. package/dist/chunk-IFNONGRQ.js +603 -0
  40. package/dist/chunk-J3U2CPSK.js +136 -0
  41. package/dist/{chunk-Y5GI7RL3.js → chunk-J6XQ7OPZ.js} +9 -1
  42. package/dist/{chunk-LBFGSSF2.js → chunk-KMV4Y6R3.js} +2 -1
  43. package/dist/{chunk-L6N4JFW2.js → chunk-KP5ZDDPE.js} +81 -4
  44. package/dist/{chunk-SJOVFF7B.js → chunk-KYKSZ3XZ.js} +3 -2
  45. package/dist/chunk-NEZNAPPN.js +41 -0
  46. package/dist/{chunk-NH5I4KHH.js → chunk-NPVN2THM.js} +1 -5
  47. package/dist/{chunk-6L3U7DZ5.js → chunk-NYZU5NCW.js} +1 -1
  48. package/dist/chunk-O4KHCV6I.js +320 -0
  49. package/dist/{chunk-LO35HLQZ.js → chunk-ONDVTXUO.js} +25 -4
  50. package/dist/{chunk-4ZYCIMY4.js → chunk-OTJFHESY.js} +25 -4
  51. package/dist/chunk-P6MIKSPY.js +243 -0
  52. package/dist/{checkUpgrade-F2WESBPM.js → chunk-QCRBX3LV.js} +72 -10
  53. package/dist/{chunk-LRD4GBYE.js → chunk-QUIMQ7YL.js} +1 -1
  54. package/dist/chunk-RG3YLU6E.js +49 -0
  55. package/dist/{chunk-ST2X2GYN.js → chunk-SHZFOSXC.js} +109 -20
  56. package/dist/{chunk-CIDWNUAP.js → chunk-SOXFMMXC.js} +8 -2
  57. package/dist/chunk-TDTYV6QI.js +119 -0
  58. package/dist/{chunk-FW6BD2NO.js → chunk-TUXQ32WE.js} +457 -121
  59. package/dist/{chunk-WQ23REYT.js → chunk-VGCDRK3S.js} +1 -1
  60. package/dist/{chunk-U5AT3TD4.js → chunk-X4W64MHU.js} +1735 -1858
  61. package/dist/chunk-XBQA4I36.js +92 -0
  62. package/dist/chunk-XGOV6KV4.js +413 -0
  63. package/dist/{chunk-OQS4GUSI.js → chunk-XIFQIFSZ.js} +210 -661
  64. package/dist/{chunk-XBIDMHSK.js → chunk-XLXPVN3Y.js} +2 -34
  65. package/dist/chunk-ZJMLQ37G.js +90 -0
  66. package/dist/{client-IRKAMDYZ.js → client-MU4EUDZV.js} +3 -3
  67. package/dist/{commands-FIL5ET6P.js → commands-UOOTMBKA.js} +145 -33
  68. package/dist/{compat-R3UTFQ5Q.js → compat-Q5DVPITN.js} +6 -6
  69. package/dist/constants-DJFOFZ44.js +24 -0
  70. package/dist/{dashboardIssue-WYYMBFIB.js → dashboardIssue-KBKLQMGC.js} +105 -23
  71. package/dist/{diff-GZA2774U.js → diff-I4SNUHU3.js} +1 -1
  72. package/dist/domains-VRT4BRVZ.js +14 -0
  73. package/dist/env-UN6KGZ7S.js +15 -0
  74. package/dist/envCheck-KUPTORFQ.js +71 -0
  75. package/dist/{extract-NKGKLIVT.js → extract-6WG265BL.js} +14 -3
  76. package/dist/{fetch-QYTUJVG2.js → fetch-PJ3SC32M.js} +4 -4
  77. package/dist/{firstTouch-QQTJH4QX.js → firstTouch-COJCMOB3.js} +1 -1
  78. package/dist/fix-3EDWNKW3.js +220 -0
  79. package/dist/{handlers-GEJAVZDK.js → handlers-4Q37WIFT.js} +19 -17
  80. package/dist/hook-NA66XJLC.js +412 -0
  81. package/dist/{http-ETPYMBGD.js → http-25GJ6SKK.js} +2078 -510
  82. package/dist/{ingestQueue-VKN4KBIF.js → ingestQueue-FSVJC3AA.js} +14 -12
  83. package/dist/{install-EK3W2COX.js → install-G2HHXYJ2.js} +6 -6
  84. package/dist/{installSkill-VQJWJVCL.js → installSkill-5TIMYIJZ.js} +21 -3
  85. package/dist/manifest-ENMIC54B.js +13 -0
  86. package/dist/{mcp-3JHD5SUZ.js → mcp-PENLL2PK.js} +60 -32
  87. package/dist/mcpConfig-3LYPRY5Q.js +80 -0
  88. package/dist/{mcpHandlers-QFN4MCFL.js → mcpHandlers-PO7GENA7.js} +7 -7
  89. package/dist/{mcpScan-QZHWENIP.js → mcpScan-ULP626TQ.js} +306 -442
  90. package/dist/{mcpScanWorkflow-JPYCBGC4.js → mcpScanWorkflow-27O44FOE.js} +29 -12
  91. package/dist/{mcpStack-BYJCZNIV.js → mcpStack-ZNYIFXZ5.js} +1 -1
  92. package/dist/model-ASMZWLM7.js +214 -0
  93. package/dist/{packages-THVFMWFP.js → packages-RWF2LXST.js} +3 -5
  94. package/dist/{plan-V4OEI3J4.js → plan-SDILIDZT.js} +23 -21
  95. package/dist/{planView-JRXGCG2N.js → planView-ZAKRTGVS.js} +4 -1
  96. package/dist/{policy-3P6BGRDN.js → policy-JAGNMQJI.js} +5 -5
  97. package/dist/probe-3IK646WN.js +610 -0
  98. package/dist/publicUpgrades-WTBGLDIK.js +42 -0
  99. package/dist/{references-6N7VEPHT.js → references-I6Y4BSRR.js} +3 -1
  100. package/dist/{release-4U4ABNSJ.js → release-7IU2R4YG.js} +5 -5
  101. package/dist/{remote-YGCXYI4V.js → remote-FN6225AH.js} +13 -3
  102. package/dist/rename-OS6JYBZQ.js +204 -0
  103. package/dist/{reportRuns-CKQQYLY4.js → reportRuns-O4X7ZFTX.js} +15 -2
  104. package/dist/safeFetch-COERXGFN.js +19 -0
  105. package/dist/{sandbox-MEZLAODF.js → sandbox-SAPSRKEI.js} +4 -4
  106. package/dist/sarif-WLVJFJ7U.js +125 -0
  107. package/dist/server-OLTY3NYT.js +59 -0
  108. package/dist/{surface-V62GE554.js → surface-7MHE3RL7.js} +18 -16
  109. package/dist/{surface-YL6O67W3.js → surface-JS2XU3U3.js} +5 -3
  110. package/dist/{surfaceHandlers-X2IZKA3E.js → surfaceHandlers-4B6TMZ34.js} +5 -5
  111. package/dist/{typecheck-X7U5ELMR.js → typecheck-NGOKNAJY.js} +23 -9
  112. package/dist/{uninstall-P7RGBX6G.js → uninstall-I2IJP5JZ.js} +30 -4
  113. package/dist/{upgrade-NQ5IWFZB.js → upgrade-FS26DJGG.js} +86 -32
  114. package/dist/{upgradePlan-A4LRKLEG.js → upgradePlan-ZS5IOVMZ.js} +46 -11
  115. package/dist/upkeepHandler-VFGYXJKB.js +13 -0
  116. package/dist/{userConfig-Z3GQE776.js → userConfig-ICASHI47.js} +1 -1
  117. package/dist/{watch-DGFMWUDL.js → watch-OCNEUXG6.js} +24 -34
  118. package/package.json +3 -2
  119. package/templates/skill-instructions.md +22 -3
  120. package/dist/chunk-6AAEVQ7I.js +0 -6336
  121. package/dist/chunk-I2JUKN6Z.js +0 -24
  122. package/dist/server-KFUD5X57.js +0 -55
@@ -21,8 +21,12 @@ var code = (s) => `\`${s.replace(/[`\r\n]/g, "").slice(0, 120)}\``;
21
21
  var RANK = { critical: 0, high: 1, moderate: 2, low: 3, info: 4 };
22
22
  function mcpSection(scan, urgent) {
23
23
  const lines = ["### MCP servers", ""];
24
- if (!scan.servers.length) return [...lines, "No MCP servers are committed to this repository.", ""];
25
- lines.push("| Server | Status | Tools | Can modify | Findings |", "| --- | --- | --- | --- | --- |");
24
+ if (!scan.servers.length)
25
+ return [...lines, "No MCP servers are committed to this repository.", ""];
26
+ lines.push(
27
+ "| Server | Status | Tools | Can modify | Findings |",
28
+ "| --- | --- | --- | --- | --- |"
29
+ );
26
30
  for (const s of scan.servers.slice(0, MAX_ROWS)) {
27
31
  const f = s.analysis?.findings.filter((x) => RANK[x.severity] <= RANK.moderate) ?? [];
28
32
  const worst = f.sort((a, b) => RANK[a.severity] - RANK[b.severity])[0]?.severity;
@@ -31,36 +35,74 @@ function mcpSection(scan, urgent) {
31
35
  );
32
36
  }
33
37
  lines.push("");
34
- const account = new Map((scan.account?.results ?? []).filter((r) => r.since).map((r) => [r.alias, r.since]));
38
+ const account = new Map(
39
+ (scan.account?.results ?? []).filter((r) => r.since).map((r) => [r.alias, r.since])
40
+ );
35
41
  const changes = scan.servers.flatMap((s) => {
36
42
  const acc = account.get(s.alias);
37
- if (acc) return [{ alias: s.alias, key: s.serverKey, severity: acc.severity, summary: acc.summary, rug: acc.rugPull.length > 0 }];
43
+ if (acc)
44
+ return [
45
+ {
46
+ alias: s.alias,
47
+ key: s.serverKey,
48
+ severity: acc.severity,
49
+ summary: acc.summary,
50
+ rug: acc.rugPull.length > 0
51
+ }
52
+ ];
38
53
  const d = s.sinceLastScan;
39
- return d && !d.unchanged ? [{ alias: s.alias, key: s.serverKey, severity: d.severity, summary: d.summary, rug: d.rugPull.length > 0 || d.contract.annotationFlips.some((x) => x.widensPrivilege) }] : [];
54
+ return d && !d.unchanged ? [
55
+ {
56
+ alias: s.alias,
57
+ key: s.serverKey,
58
+ severity: d.severity,
59
+ summary: d.summary,
60
+ rug: d.rugPull.length > 0 || d.contract.annotationFlips.some((x) => x.widensPrivilege)
61
+ }
62
+ ] : [];
40
63
  });
41
64
  if (changes.length) {
42
65
  lines.push("**Changed since the last scan**", "");
43
66
  for (const c of changes.sort((a, b) => RANK[a.severity] - RANK[b.severity])) {
44
67
  const line = `- **${c.severity}** ${code(c.alias)}: ${md(c.summary, 300)}`;
45
68
  lines.push(line);
46
- if (c.rug || c.severity === "critical") urgent.push({ key: sha(`change|${c.key}|${c.summary}`).slice(0, 16), line });
69
+ if (c.rug || c.severity === "critical")
70
+ urgent.push({ key: sha(`change|${c.key}|${c.summary}`).slice(0, 16), line });
47
71
  }
48
72
  lines.push("");
49
73
  }
50
- const findings = scan.servers.flatMap((s) => (s.analysis?.findings ?? []).map((f) => ({ ...f, alias: s.alias, serverKey: s.serverKey }))).concat(scan.findings.map((f) => ({ ...f, alias: f.server ?? "stack", serverKey: `stack:${f.server ?? ""}` }))).filter((f) => RANK[f.severity] <= RANK.high).sort((a, b) => RANK[a.severity] - RANK[b.severity]);
74
+ const findings = scan.servers.flatMap(
75
+ (s) => (s.analysis?.findings ?? []).map((f) => ({ ...f, alias: s.alias, serverKey: s.serverKey }))
76
+ ).concat(
77
+ scan.findings.map((f) => ({
78
+ ...f,
79
+ alias: f.server ?? "stack",
80
+ serverKey: `stack:${f.server ?? ""}`
81
+ }))
82
+ ).filter((f) => RANK[f.severity] <= RANK.high).sort((a, b) => RANK[a.severity] - RANK[b.severity]);
51
83
  if (findings.length) {
52
84
  lines.push("**Needs attention**", "");
53
85
  for (const f of findings.slice(0, MAX_ROWS)) {
54
86
  const line = `- **${f.severity}** ${code(f.alias)}${f.tool ? ` \u203A ${code(f.tool)}` : ""}: ${md(f.detail, 240)}`;
55
87
  lines.push(line);
56
- if (f.severity === "critical") urgent.push({ key: sha(`finding|${f.serverKey}|${f.kind}|${f.tool}|${f.where}|${f.evidence}`).slice(0, 16), line });
88
+ if (f.severity === "critical")
89
+ urgent.push({
90
+ key: sha(`finding|${f.serverKey}|${f.kind}|${f.tool}|${f.where}|${f.evidence}`).slice(
91
+ 0,
92
+ 16
93
+ ),
94
+ line
95
+ });
57
96
  }
58
97
  lines.push("");
59
98
  }
60
99
  const unread = scan.servers.filter((s) => !s.snapshot);
61
100
  if (unread.length) {
62
101
  lines.push(`<details><summary>${unread.length} server(s) could not be read</summary>`, "");
63
- for (const s of unread.slice(0, MAX_ROWS)) lines.push(`- ${code(s.alias)}: ${s.status.replace(/_/g, " ")}${s.error ? `, ${md(s.error, 160)}` : ""}`);
102
+ for (const s of unread.slice(0, MAX_ROWS))
103
+ lines.push(
104
+ `- ${code(s.alias)}: ${s.status.replace(/_/g, " ")}${s.error ? `, ${md(s.error, 160)}` : ""}`
105
+ );
64
106
  lines.push("", "</details>", "");
65
107
  }
66
108
  return lines;
@@ -69,16 +111,27 @@ function dependencySection(plan, note) {
69
111
  const lines = ["### Dependencies", ""];
70
112
  if (!plan) return [...lines, note ?? "Not checked on this run.", ""];
71
113
  if (!plan.upgrades.length) {
72
- return [...lines, `Everything lurq tracks is on its latest release${plan.untracked ? ` (${plan.untracked} not yet indexed)` : ""}.`, ""];
114
+ return [
115
+ ...lines,
116
+ `Everything lurq tracks is on its latest release${plan.untracked ? ` (${plan.untracked} not yet indexed)` : ""}.`,
117
+ ""
118
+ ];
73
119
  }
74
120
  lines.push("| Package | Upgrade | What it removes | Advisories |", "| --- | --- | --- | --- |");
75
121
  const order = { "removes-exports": 0, "arity-changed": 1, unknown: 2, clean: 3 };
76
122
  for (const u of [...plan.upgrades].sort((a, b) => order[a.verdict] - order[b.verdict] || b.advisories - a.advisories).slice(0, MAX_ROWS)) {
77
123
  const removes = u.verdict === "removes-exports" ? `${u.removed.length} export(s)` : u.verdict === "arity-changed" ? "changed signatures" : u.verdict === "clean" ? "nothing" : "unknown";
78
- lines.push(`| ${code(u.package)} | ${md(u.fromVersion, 40)} \u2192 ${md(u.toVersion, 40)}${u.majorsBehind ? ` (${u.majorsBehind} major)` : ""} | ${removes} | ${u.advisories || "\u2014"} |`);
124
+ lines.push(
125
+ `| ${code(u.package)} | ${md(u.fromVersion, 40)} \u2192 ${md(u.toVersion, 40)}${u.majorsBehind ? ` (${u.majorsBehind} major)` : ""} | ${removes} | ${u.advisories || "\u2014"} |`
126
+ );
79
127
  }
80
- if (plan.upgrades.length > MAX_ROWS) lines.push("", `and ${plan.upgrades.length - MAX_ROWS} more.`);
81
- if (plan.untracked) lines.push("", `${plan.untracked} dependencies are not indexed yet, so they are not covered here.`);
128
+ if (plan.upgrades.length > MAX_ROWS)
129
+ lines.push("", `and ${plan.upgrades.length - MAX_ROWS} more.`);
130
+ if (plan.untracked)
131
+ lines.push(
132
+ "",
133
+ `${plan.untracked} dependencies are not indexed yet, so they are not covered here.`
134
+ );
82
135
  lines.push("");
83
136
  return lines;
84
137
  }
@@ -110,9 +163,12 @@ function readMarkers(body) {
110
163
  }
111
164
  function withMarkers(body, hash, alerted) {
112
165
  const keys = alerted.slice(-MAX_ALERTED_KEYS).join(",");
113
- return body.replace(DASHBOARD_MARKER, `${DASHBOARD_MARKER}
166
+ return body.replace(
167
+ DASHBOARD_MARKER,
168
+ `${DASHBOARD_MARKER}
114
169
  <!-- lurq:hash:${hash} -->
115
- <!-- lurq:alerted:${keys} -->`);
170
+ <!-- lurq:alerted:${keys} -->`
171
+ );
116
172
  }
117
173
  var GithubIssueError = class extends Error {
118
174
  constructor(message, status) {
@@ -126,7 +182,11 @@ function githubEnvFrom(env) {
126
182
  const token = env.GITHUB_TOKEN;
127
183
  const repo = env.GITHUB_REPOSITORY;
128
184
  if (!token || !repo || !/^[\w.-]+\/[\w.-]+$/.test(repo)) return null;
129
- return { token, repo, apiUrl: (env.GITHUB_API_URL ?? "https://api.github.com").replace(/\/$/, "") };
185
+ return {
186
+ token,
187
+ repo,
188
+ apiUrl: (env.GITHUB_API_URL ?? "https://api.github.com").replace(/\/$/, "")
189
+ };
130
190
  }
131
191
  async function gh(env, method, path, body) {
132
192
  const res = await (env.fetchImpl ?? fetch)(`${env.apiUrl}${path}`, {
@@ -151,28 +211,50 @@ async function gh(env, method, path, body) {
151
211
  return { status: res.status, data };
152
212
  }
153
213
  async function upsertDashboardIssue(env, rendered) {
154
- const { data: issues } = await gh(env, "GET", `/repos/${env.repo}/issues?labels=${DASHBOARD_LABEL}&state=all&per_page=100`);
155
- const mine = (issues ?? []).filter((i) => !i.pull_request && (i.body ?? "").includes(DASHBOARD_MARKER));
214
+ const { data: issues } = await gh(
215
+ env,
216
+ "GET",
217
+ `/repos/${env.repo}/issues?labels=${DASHBOARD_LABEL}&state=all&per_page=100`
218
+ );
219
+ const mine = (issues ?? []).filter(
220
+ (i) => !i.pull_request && (i.body ?? "").includes(DASHBOARD_MARKER)
221
+ );
156
222
  const open = mine.find((i) => i.state === "open");
157
223
  if (!open) {
158
224
  if (mine.length) return { action: "closed", url: mine[0].html_url, commented: 0 };
159
- await gh(env, "POST", `/repos/${env.repo}/labels`, { name: DASHBOARD_LABEL, color: "6e40c9", description: "lurq dependency and MCP dashboard" });
225
+ await gh(env, "POST", `/repos/${env.repo}/labels`, {
226
+ name: DASHBOARD_LABEL,
227
+ color: "6e40c9",
228
+ description: "lurq dependency and MCP dashboard"
229
+ });
160
230
  const { data } = await gh(env, "POST", `/repos/${env.repo}/issues`, {
161
231
  title: rendered.title,
162
- body: withMarkers(rendered.body, rendered.hash, rendered.urgent.map((u) => u.key)),
232
+ body: withMarkers(
233
+ rendered.body,
234
+ rendered.hash,
235
+ rendered.urgent.map((u) => u.key)
236
+ ),
163
237
  labels: [DASHBOARD_LABEL]
164
238
  });
165
239
  return { action: "created", url: data.html_url, commented: 0 };
166
240
  }
167
241
  const markers = readMarkers(open.body ?? "");
168
242
  const fresh = rendered.urgent.filter((u) => !markers.alerted.includes(u.key));
169
- if (markers.hash === rendered.hash && !fresh.length) return { action: "unchanged", url: open.html_url, commented: 0 };
243
+ if (markers.hash === rendered.hash && !fresh.length)
244
+ return { action: "unchanged", url: open.html_url, commented: 0 };
170
245
  await gh(env, "PATCH", `/repos/${env.repo}/issues/${open.number}`, {
171
- body: withMarkers(rendered.body, rendered.hash, [...markers.alerted, ...fresh.map((u) => u.key)])
246
+ body: withMarkers(rendered.body, rendered.hash, [
247
+ ...markers.alerted,
248
+ ...fresh.map((u) => u.key)
249
+ ])
172
250
  });
173
251
  if (fresh.length) {
174
252
  await gh(env, "POST", `/repos/${env.repo}/issues/${open.number}/comments`, {
175
- body: [`lurq found ${fresh.length === 1 ? "something" : `${fresh.length} things`} that need a look today:`, "", ...fresh.map((u) => u.line)].join("\n")
253
+ body: [
254
+ `lurq found ${fresh.length === 1 ? "something" : `${fresh.length} things`} that need a look today:`,
255
+ "",
256
+ ...fresh.map((u) => u.line)
257
+ ].join("\n")
176
258
  });
177
259
  }
178
260
  return { action: "updated", url: open.html_url, commented: fresh.length ? 1 : 0 };
@@ -3,7 +3,7 @@ import {
3
3
  checkApi,
4
4
  diffApiSurfaces,
5
5
  formatApiCheck
6
- } from "./chunk-CIDWNUAP.js";
6
+ } from "./chunk-SOXFMMXC.js";
7
7
  import "./chunk-3GHJR7XR.js";
8
8
  import "./chunk-I3M2KJXB.js";
9
9
  export {
@@ -0,0 +1,14 @@
1
+ import { createRequire as __lurqCreateRequire } from 'node:module'; const require = __lurqCreateRequire(import.meta.url);
2
+ import {
3
+ AVAILABLE,
4
+ DOMAIN_SCAN_LIMIT,
5
+ SOURCE_DOMAINS,
6
+ runDomains
7
+ } from "./chunk-XBQA4I36.js";
8
+ import "./chunk-I3M2KJXB.js";
9
+ export {
10
+ AVAILABLE,
11
+ DOMAIN_SCAN_LIMIT,
12
+ SOURCE_DOMAINS,
13
+ runDomains
14
+ };
@@ -0,0 +1,15 @@
1
+ import { createRequire as __lurqCreateRequire } from 'node:module'; const require = __lurqCreateRequire(import.meta.url);
2
+ import {
3
+ HARNESS_FILE,
4
+ declaredNames,
5
+ envFindings,
6
+ envReadsIn
7
+ } from "./chunk-DONTW3NE.js";
8
+ import "./chunk-SHZFOSXC.js";
9
+ import "./chunk-I3M2KJXB.js";
10
+ export {
11
+ HARNESS_FILE,
12
+ declaredNames,
13
+ envFindings,
14
+ envReadsIn
15
+ };
@@ -0,0 +1,71 @@
1
+ import { createRequire as __lurqCreateRequire } from 'node:module'; const require = __lurqCreateRequire(import.meta.url);
2
+ import {
3
+ envFindings
4
+ } from "./chunk-DONTW3NE.js";
5
+ import {
6
+ bold,
7
+ dim,
8
+ yellow
9
+ } from "./chunk-4KCPOMG6.js";
10
+ import "./chunk-SHZFOSXC.js";
11
+ import {
12
+ init_esm_shims
13
+ } from "./chunk-I3M2KJXB.js";
14
+
15
+ // src/cli/envCheck.ts
16
+ init_esm_shims();
17
+ import { writeFileSync } from "fs";
18
+ import { resolve } from "path";
19
+ async function runEnvCheck(dir, opts) {
20
+ const root = resolve(dir ?? process.cwd());
21
+ const limit = opts.limit ? Number(opts.limit) : void 0;
22
+ if (limit !== void 0 && (!Number.isFinite(limit) || limit <= 0)) {
23
+ throw new Error(`--limit must be a positive number; got "${opts.limit}"`);
24
+ }
25
+ const plan = envFindings(root, { limit });
26
+ const distinct = new Set(plan.reads.map((r) => r.name)).size;
27
+ if (opts.sarif) {
28
+ const { toSarif } = await import("./sarif-WLVJFJ7U.js");
29
+ const { VERSION } = await import("./constants-DJFOFZ44.js");
30
+ const doc = toSarif(plan.findings, { version: VERSION, read: () => null });
31
+ writeFileSync(opts.sarif, `${JSON.stringify(doc, null, 2)}
32
+ `, "utf8");
33
+ console.error(`wrote ${opts.sarif}`);
34
+ }
35
+ if (opts.json) {
36
+ console.log(JSON.stringify({ root, ...plan, distinct }, null, 2));
37
+ } else {
38
+ console.log(formatEnvCheck(root, plan, distinct));
39
+ }
40
+ if (opts.exitCode && (plan.findings.length > 0 || plan.truncated)) process.exitCode = 1;
41
+ }
42
+ function formatEnvCheck(root, plan, distinct) {
43
+ const out = [];
44
+ const scanned = `${plan.reads.length} read(s) of ${distinct} variable(s) in ${root}`;
45
+ if (plan.findings.length === 0) {
46
+ out.push(`Every variable this project reads is declared or supplied by the platform.`);
47
+ out.push(dim(scanned));
48
+ } else {
49
+ out.push(`${plan.findings.length} variable(s) read here and declared nowhere:`);
50
+ for (const f of plan.findings) {
51
+ out.push(` ${yellow(f.code.replace("env-undeclared:", ""))} ${dim(f.evidence ?? "")}`);
52
+ }
53
+ out.push("");
54
+ out.push(
55
+ dim(
56
+ "add each to .env.example so the next clone knows it exists; ask the user for any real value"
57
+ )
58
+ );
59
+ out.push(dim(scanned));
60
+ }
61
+ if (plan.truncated) {
62
+ out.push(
63
+ bold("the scan stopped at its file limit, so this is not a complete answer (--limit)")
64
+ );
65
+ }
66
+ return out.join("\n");
67
+ }
68
+ export {
69
+ formatEnvCheck,
70
+ runEnvCheck
71
+ };
@@ -20,7 +20,8 @@ function classify(node) {
20
20
  if (ts.isFunctionExpression(node) || ts.isArrowFunction(node) || ts.isFunctionDeclaration(node)) {
21
21
  return { kind: "function", arity: arityOf(node), maxArity: maxArityOf(node) };
22
22
  }
23
- if (ts.isClassExpression(node) || ts.isClassDeclaration(node)) return { kind: "class", arity: null };
23
+ if (ts.isClassExpression(node) || ts.isClassDeclaration(node))
24
+ return { kind: "class", arity: null };
24
25
  if (ts.isObjectLiteralExpression(node)) return { kind: "object", arity: null };
25
26
  if (ts.isStringLiteral(node) || ts.isNumericLiteral(node) || node.kind === ts.SyntaxKind.TrueKeyword || node.kind === ts.SyntaxKind.FalseKeyword || node.kind === ts.SyntaxKind.NullKeyword) {
26
27
  return { kind: "primitive", arity: null };
@@ -147,7 +148,16 @@ function walk(file, ctx, out) {
147
148
  for (const pick of picks) {
148
149
  const found = sub.get(pick.from);
149
150
  if (found) put(out, { ...found, path: pick.as });
150
- else put(out, { path: pick.as, kind: "object", arity: null, origin: "local", deprecated: false, tier: TIER, sourceRef: { file: rel, line: 1 } });
151
+ else
152
+ put(out, {
153
+ path: pick.as,
154
+ kind: "object",
155
+ arity: null,
156
+ origin: "local",
157
+ deprecated: false,
158
+ tier: TIER,
159
+ sourceRef: { file: rel, line: 1 }
160
+ });
151
161
  }
152
162
  return;
153
163
  }
@@ -340,7 +350,8 @@ function walk(file, ctx, out) {
340
350
  }
341
351
  }
342
352
  function throughGetter(sf, value) {
343
- if (!(ts.isArrowFunction(value) || ts.isFunctionExpression(value)) || value.parameters.length) return value;
353
+ if (!(ts.isArrowFunction(value) || ts.isFunctionExpression(value)) || value.parameters.length)
354
+ return value;
344
355
  let returned;
345
356
  if (!ts.isBlock(value.body)) returned = value.body;
346
357
  else if (value.body.statements.length === 1 && ts.isReturnStatement(value.body.statements[0])) {
@@ -6,11 +6,11 @@ import {
6
6
  resolveTarball,
7
7
  unpackPackage,
8
8
  verifyIntegrity
9
- } from "./chunk-BV32UNLL.js";
10
- import "./chunk-AHBP533R.js";
11
- import "./chunk-SJOVFF7B.js";
9
+ } from "./chunk-FVYFV5HA.js";
10
+ import "./chunk-D3VTZS7V.js";
11
+ import "./chunk-KYKSZ3XZ.js";
12
12
  import "./chunk-MYGSLK44.js";
13
- import "./chunk-GPTKSNR6.js";
13
+ import "./chunk-72Y2FDVS.js";
14
14
  import "./chunk-I3M2KJXB.js";
15
15
  export {
16
16
  extractUnpacked,
@@ -20,7 +20,7 @@ function extractOnce(db, pkg, version) {
20
20
  if (existing) return existing;
21
21
  if (inFlight.size >= MAX_INFLIGHT) return Promise.resolve(null);
22
22
  const task = (async () => {
23
- const { extractAndStore } = await import("./surface-V62GE554.js");
23
+ const { extractAndStore } = await import("./surface-7MHE3RL7.js");
24
24
  const { outcome, version: resolved } = await extractAndStore(db, pkg, version);
25
25
  return outcome === "stored" || outcome === "cached" ? resolved : null;
26
26
  })().catch((err) => {
@@ -0,0 +1,220 @@
1
+ import { createRequire as __lurqCreateRequire } from 'node:module'; const require = __lurqCreateRequire(import.meta.url);
2
+ import {
3
+ SCAN_LIMIT,
4
+ fixableTargets,
5
+ parseUpgradeSpec,
6
+ planUpgrades
7
+ } from "./chunk-QCRBX3LV.js";
8
+ import {
9
+ manifestFindings
10
+ } from "./chunk-5ALIJFDA.js";
11
+ import {
12
+ applyEdits,
13
+ deterministic,
14
+ editsByFile,
15
+ unifiedDiff
16
+ } from "./chunk-BM3LF5T6.js";
17
+ import "./chunk-3GHJR7XR.js";
18
+ import {
19
+ init_esm_shims
20
+ } from "./chunk-I3M2KJXB.js";
21
+
22
+ // src/cli/fix.ts
23
+ init_esm_shims();
24
+ import { readFileSync, writeFileSync } from "fs";
25
+ import { join, relative } from "path";
26
+ async function derivePlanTargets(dir, opts) {
27
+ const { buildUpgradePlan } = await import("./upgradePlan-ZS5IOVMZ.js");
28
+ try {
29
+ const plan = await buildUpgradePlan(dir, {
30
+ url: opts.url,
31
+ apiKey: opts.apiKey,
32
+ repo: opts.repo
33
+ });
34
+ return fixableTargets(plan.upgrades, opts.max);
35
+ } catch (err) {
36
+ if (err instanceof Error && err.name === "MissingKeyError") {
37
+ throw new Error(
38
+ `${err.message}
39
+
40
+ Or skip the lookup: \`lurq fix --upgrade pkg@from..to\` reads both versions straight from npm and needs no key.`
41
+ );
42
+ }
43
+ throw err;
44
+ }
45
+ }
46
+ function stage(root, findings) {
47
+ const writes = /* @__PURE__ */ new Map();
48
+ let diff = "";
49
+ for (const [file, edits] of editsByFile(findings.filter(deterministic))) {
50
+ const before = readFileSync(join(root, file), "utf8");
51
+ diff += unifiedDiff(file, before, edits);
52
+ writes.set(file, applyEdits(before, edits));
53
+ }
54
+ return { writes, diff };
55
+ }
56
+ async function runFix(dir, opts) {
57
+ const { scanReferences } = await import("./references-I6Y4BSRR.js");
58
+ const { checkUpgrade } = await import("./upgrade-FS26DJGG.js");
59
+ const { renamePlan } = await import("./rename-OS6JYBZQ.js");
60
+ const asked = Boolean(opts.plan) || (opts.upgrade?.length ?? 0) > 0;
61
+ const split = asked ? {
62
+ ...fixableTargets(opts.plan ? planUpgrades(opts.plan) : [], opts.max),
63
+ named: (opts.upgrade ?? []).map(parseUpgradeSpec)
64
+ } : { ...await derivePlanTargets(dir, opts), named: [] };
65
+ const targets = [...split.targets, ...split.named];
66
+ const skipped = split.skipped;
67
+ const { runDomains, SOURCE_DOMAINS } = await import("./domains-VRT4BRVZ.js");
68
+ const source = await runDomains({ dir, domains: SOURCE_DOMAINS });
69
+ const unchecked = source.skipped.map((d) => ({ domain: d.domain, reason: d.reason }));
70
+ if (targets.length === 0 && source.findings.length === 0) {
71
+ const empty = {
72
+ root: dir,
73
+ files: [],
74
+ applied: [],
75
+ remaining: [],
76
+ refused: [],
77
+ skipped,
78
+ unchecked
79
+ };
80
+ const lines = skipped.length ? [
81
+ `Nothing attempted in ${dir}. ${skipped.length} upgrade(s) deliberately not tried:`,
82
+ ...skippedLines(skipped)
83
+ ] : [
84
+ `Nothing to fix in ${dir}: ${asked ? "no upgrade named here needs a change" : "every dependency is current or held by the repo policy"}, ${// Never "the source is clean" when no detector survived to look.
85
+ // `ran` is empty only when every source domain threw, and that is
86
+ // the one case where the reassuring sentence would be false.
87
+ source.ran.length ? "and nothing in the source needs changing" : "and the source could not be scanned"}.`
88
+ ];
89
+ lines.push(...uncheckedLines(unchecked));
90
+ console.log(opts.json ? JSON.stringify(empty, null, 2) : lines.join("\n"));
91
+ return;
92
+ }
93
+ let findings = [];
94
+ const refused = [];
95
+ if (targets.length > 0) {
96
+ const refs = scanReferences(dir, { limit: SCAN_LIMIT });
97
+ const report = await checkUpgrade(targets, refs, { rootDir: dir });
98
+ const renames = renamePlan(report);
99
+ const { findManifests } = await import("./upgradePlan-ZS5IOVMZ.js");
100
+ const manifests = manifestFindings(dir, targets, {
101
+ files: findManifests(dir).map((abs) => relative(dir, abs) || "package.json")
102
+ });
103
+ findings = [...renames.findings, ...manifests.findings];
104
+ refused.push(
105
+ ...renames.refused,
106
+ ...manifests.refused.map((r) => ({ symbol: r.package, file: r.file, reason: r.reason }))
107
+ );
108
+ }
109
+ findings = [...findings, ...source.findings];
110
+ const result = {
111
+ root: dir,
112
+ files: [],
113
+ applied: [],
114
+ remaining: [],
115
+ refused: refused.map((r) => ({ symbol: r.symbol, file: r.file, reason: r.reason })),
116
+ skipped,
117
+ unchecked
118
+ };
119
+ const { writes, diff } = stage(dir, findings);
120
+ result.files = [...writes.keys()];
121
+ for (const f of findings) {
122
+ if (deterministic(f)) {
123
+ result.applied.push({
124
+ code: f.code,
125
+ summary: f.fix.summary,
126
+ files: [...new Set(f.fix.edits.map((e) => e.file))]
127
+ });
128
+ } else {
129
+ result.remaining.push({
130
+ code: f.code,
131
+ detail: f.detail,
132
+ instruction: f.fix?.task?.instruction,
133
+ files: f.fix?.task?.files,
134
+ evidence: f.fix?.task?.evidence
135
+ });
136
+ }
137
+ }
138
+ if (opts.apply && writes.size > 0) {
139
+ const { writeFileAtomic } = await import("./installSkill-5TIMYIJZ.js");
140
+ for (const [file, contents] of writes) writeFileAtomic(join(dir, file), contents);
141
+ }
142
+ if (opts.sarif) {
143
+ const { toSarif } = await import("./sarif-WLVJFJ7U.js");
144
+ const { VERSION } = await import("./constants-DJFOFZ44.js");
145
+ const sarif = toSarif(findings, {
146
+ version: VERSION,
147
+ // Read from disk rather than reusing the staged text: regions must
148
+ // describe the file as it is, not as it would be after the fix.
149
+ read: (file) => {
150
+ try {
151
+ return readFileSync(join(dir, file), "utf8");
152
+ } catch {
153
+ return null;
154
+ }
155
+ }
156
+ });
157
+ writeFileSync(opts.sarif, `${JSON.stringify(sarif, null, 2)}
158
+ `, "utf8");
159
+ console.error(`wrote ${opts.sarif}`);
160
+ }
161
+ if (opts.json) {
162
+ console.log(JSON.stringify({ ...result, applied_to_disk: Boolean(opts.apply) }, null, 2));
163
+ } else {
164
+ console.log(formatFix(result, diff, Boolean(opts.apply)));
165
+ }
166
+ if (opts.exitCode && result.remaining.length > 0) process.exitCode = 1;
167
+ }
168
+ function uncheckedLines(unchecked) {
169
+ if (unchecked.length === 0) return [];
170
+ return [
171
+ "",
172
+ `${unchecked.length} domain(s) could not be checked:`,
173
+ ...unchecked.map((u) => ` ${u.domain}: ${u.reason}`)
174
+ ];
175
+ }
176
+ function skippedLines(skipped) {
177
+ return skipped.map((s) => ` ${s.package}: ${s.reason}`);
178
+ }
179
+ function formatFix(result, diff, applied) {
180
+ const out = [];
181
+ if (result.applied.length === 0 && result.remaining.length === 0) {
182
+ return [
183
+ `Nothing to fix in ${result.root}: no upgrade in this plan renames a symbol this code references,`,
184
+ "every declared range already admits its target, and nothing in the source names a retired model",
185
+ "or reads an undeclared variable."
186
+ ].join(" ");
187
+ }
188
+ if (result.applied.length > 0) {
189
+ out.push(
190
+ applied ? `Wrote ${result.files.length} file(s) in ${result.root}:` : `Would write ${result.files.length} file(s) in ${result.root} (pass --apply):`
191
+ );
192
+ for (const a of result.applied) out.push(` ${a.summary} \u2014 ${a.files.join(", ")}`);
193
+ if (!applied && diff) out.push("", diff.trimEnd());
194
+ }
195
+ if (result.remaining.length > 0) {
196
+ out.push("", `${result.remaining.length} change(s) lurq will not make for you:`);
197
+ for (const r of result.remaining) {
198
+ out.push(` ${r.detail}`);
199
+ if (r.instruction) out.push(` do: ${r.instruction}`);
200
+ if (r.files?.length) out.push(` in: ${r.files.join(", ")}`);
201
+ for (const e of r.evidence ?? []) out.push(` use: ${e}`);
202
+ }
203
+ }
204
+ if (result.skipped.length > 0) {
205
+ out.push("", `${result.skipped.length} upgrade(s) deliberately not attempted:`);
206
+ out.push(...skippedLines(result.skipped));
207
+ }
208
+ out.push(...uncheckedLines(result.unchecked));
209
+ if (result.refused.length > 0) {
210
+ out.push("", "Proven renames left alone:");
211
+ for (const r of result.refused) out.push(` ${r.file ?? r.symbol}: ${r.reason}`);
212
+ }
213
+ return out.join("\n");
214
+ }
215
+ export {
216
+ formatFix,
217
+ runFix,
218
+ stage,
219
+ uncheckedLines
220
+ };
@@ -11,32 +11,34 @@ import {
11
11
  handleVerify,
12
12
  latestDataAsOf,
13
13
  rowToEvaluate
14
- } from "./chunk-BULZAX2U.js";
14
+ } from "./chunk-64ZF7KO4.js";
15
15
  import "./chunk-QSL6QN5X.js";
16
- import "./chunk-M6NYEXCW.js";
17
- import "./chunk-6L3U7DZ5.js";
18
- import "./chunk-J5FZYN4A.js";
19
- import "./chunk-PSX3GIAN.js";
20
- import "./chunk-FW6BD2NO.js";
16
+ import "./chunk-NYZU5NCW.js";
17
+ import "./chunk-2WD4QAH4.js";
18
+ import "./chunk-DSROTZ3Z.js";
19
+ import "./chunk-TUXQ32WE.js";
21
20
  import "./chunk-BUALU27S.js";
22
- import "./chunk-LRD4GBYE.js";
23
- import "./chunk-BCANRN5B.js";
24
- import "./chunk-2VMOWSRY.js";
21
+ import "./chunk-QUIMQ7YL.js";
22
+ import "./chunk-6DM6UQFD.js";
23
+ import "./chunk-EYAKM6YN.js";
24
+ import "./chunk-D3VTZS7V.js";
25
25
  import "./chunk-4ESO33J6.js";
26
- import "./chunk-CW5HJ3LX.js";
27
- import "./chunk-AHBP533R.js";
28
- import "./chunk-SJOVFF7B.js";
29
- import "./chunk-HWBBVLOT.js";
30
- import "./chunk-NH5I4KHH.js";
26
+ import "./chunk-NPVN2THM.js";
31
27
  import "./chunk-VLRHFMGJ.js";
32
- import "./chunk-WQ23REYT.js";
33
- import "./chunk-LYMPYETA.js";
28
+ import "./chunk-VGCDRK3S.js";
29
+ import "./chunk-4JHDSVIN.js";
30
+ import "./chunk-GM5Y555O.js";
31
+ import "./chunk-2GAYNIHG.js";
32
+ import "./chunk-KYKSZ3XZ.js";
33
+ import "./chunk-A3TYI2TF.js";
34
+ import "./chunk-HWFX4BC4.js";
35
+ import "./chunk-6L67QMCP.js";
34
36
  import "./chunk-3GHJR7XR.js";
35
37
  import "./chunk-GRJXQBQZ.js";
36
38
  import "./chunk-WHX2ZFCG.js";
37
39
  import "./chunk-LUAKDHLZ.js";
38
40
  import "./chunk-MYGSLK44.js";
39
- import "./chunk-GPTKSNR6.js";
41
+ import "./chunk-72Y2FDVS.js";
40
42
  import "./chunk-I3M2KJXB.js";
41
43
  export {
42
44
  USAGE_PAGE_SIZE,