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
@@ -8,24 +8,29 @@ import {
8
8
  import {
9
9
  BLOCK_START,
10
10
  agentSpecs,
11
+ hasLurqHooks,
12
+ hookAgentFor,
13
+ hooksLabel,
14
+ hooksPath,
11
15
  readJsonObject,
12
16
  removeMarkedBlock,
13
17
  resolveAgents,
14
18
  stripTomlBlock,
19
+ withoutLurqHooks,
15
20
  writeFileAtomic,
16
21
  writeJson
17
- } from "./chunk-UDVNA7EA.js";
22
+ } from "./chunk-DM37MTOO.js";
18
23
  import "./chunk-LUAKDHLZ.js";
19
24
  import "./chunk-MYGSLK44.js";
20
25
  import {
21
26
  clearUserConfig,
22
27
  lurqHome,
23
28
  userConfigPath
24
- } from "./chunk-Y5GI7RL3.js";
29
+ } from "./chunk-J6XQ7OPZ.js";
25
30
  import {
26
31
  KEYS_URL,
27
32
  PACKAGE_NAME
28
- } from "./chunk-GPTKSNR6.js";
33
+ } from "./chunk-72Y2FDVS.js";
29
34
  import {
30
35
  init_esm_shims
31
36
  } from "./chunk-I3M2KJXB.js";
@@ -72,6 +77,15 @@ function mcpEntryRemoval(spec) {
72
77
  }
73
78
  };
74
79
  }
80
+ function hooksRemoval(agent) {
81
+ const path = hooksPath(agent);
82
+ if (!existsSync(path) || !hasLurqHooks(readJsonObject(path))) return null;
83
+ return {
84
+ label: hooksLabel(agent),
85
+ path,
86
+ apply: () => writeJson(path, withoutLurqHooks(readJsonObject(path)))
87
+ };
88
+ }
75
89
  function instructionsRemoval(spec) {
76
90
  const target = spec.instructions;
77
91
  if (!target || !existsSync(target.path)) return null;
@@ -108,6 +122,16 @@ function planUninstall(specs, opts) {
108
122
  problems.push(`${spec.label}: ${err instanceof Error ? err.message : String(err)}`);
109
123
  }
110
124
  add(instructionsRemoval(spec));
125
+ const hookAgent = hookAgentFor(spec.id);
126
+ if (hookAgent) {
127
+ try {
128
+ add(hooksRemoval(hookAgent));
129
+ } catch (err) {
130
+ problems.push(
131
+ `${hooksLabel(hookAgent)}: ${err instanceof Error ? err.message : String(err)}`
132
+ );
133
+ }
134
+ }
111
135
  }
112
136
  if (opts.global) {
113
137
  const guide = join(lurqHome(), "skill-instructions.md");
@@ -134,7 +158,9 @@ async function runUninstall(opts) {
134
158
  const short = (p) => p.startsWith(homedir()) ? `~${p.slice(homedir().length)}` : p;
135
159
  for (const p of problems) console.log(`${yellow("!")} ${p}`);
136
160
  if (removals.length === 0) {
137
- console.log(`Nothing to remove: lurq is not set up ${global ? "on this machine" : `for ${specs[0].label}`}.`);
161
+ console.log(
162
+ `Nothing to remove: lurq is not set up ${global ? "on this machine" : `for ${specs[0].label}`}.`
163
+ );
138
164
  if (problems.length) process.exitCode = 1;
139
165
  return;
140
166
  }
@@ -1,7 +1,4 @@
1
1
  import { createRequire as __lurqCreateRequire } from 'node:module'; const require = __lurqCreateRequire(import.meta.url);
2
- import {
3
- SURFACE_CLAIM_KINDS
4
- } from "./chunk-ST2X2GYN.js";
5
2
  import {
6
3
  diffSurfaces,
7
4
  runtimeSymbols,
@@ -17,17 +14,20 @@ import {
17
14
  extractUnpacked,
18
15
  fetchManifest,
19
16
  unpackPackage
20
- } from "./chunk-BV32UNLL.js";
17
+ } from "./chunk-FVYFV5HA.js";
21
18
  import {
22
19
  resolveRuntimeEngineConflicts
23
20
  } from "./chunk-BUALU27S.js";
24
- import "./chunk-AHBP533R.js";
25
- import "./chunk-SJOVFF7B.js";
21
+ import "./chunk-D3VTZS7V.js";
22
+ import "./chunk-KYKSZ3XZ.js";
26
23
  import {
27
24
  require_semver
28
25
  } from "./chunk-3GHJR7XR.js";
29
26
  import "./chunk-MYGSLK44.js";
30
- import "./chunk-GPTKSNR6.js";
27
+ import "./chunk-72Y2FDVS.js";
28
+ import {
29
+ SURFACE_CLAIM_KINDS
30
+ } from "./chunk-SHZFOSXC.js";
31
31
  import {
32
32
  __toESM,
33
33
  init_esm_shims
@@ -81,23 +81,41 @@ function judgeRequires(from, to, refs, ctx) {
81
81
  if (!broken.has(`${file}:${line}`)) broken.set(`${file}:${line}`, { file, line, why });
82
82
  };
83
83
  if (to === "unexported") {
84
- for (const r of requireSites) add(r.file, r.line, "the exports map no longer offers anything to require()");
84
+ for (const r of requireSites)
85
+ add(r.file, r.line, "the exports map no longer offers anything to require()");
85
86
  } else if (ctx.asyncModule) {
86
87
  for (const r of requireSites) {
87
- add(r.file, r.line, "the ES module uses top-level await, so require() throws ERR_REQUIRE_ASYNC_MODULE on every Node");
88
+ add(
89
+ r.file,
90
+ r.line,
91
+ "the ES module uses top-level await, so require() throws ERR_REQUIRE_ASYNC_MODULE on every Node"
92
+ );
88
93
  }
89
94
  } else {
90
95
  for (const r of required) {
91
96
  if (r.via === "default") {
92
97
  for (const c of r.calls ?? []) {
93
- if (c.args !== null) add(r.file, c.line, "require() now returns the module namespace, which cannot be called");
98
+ if (c.args !== null)
99
+ add(
100
+ r.file,
101
+ c.line,
102
+ "require() now returns the module namespace, which cannot be called"
103
+ );
94
104
  }
95
105
  } else if ((r.via === "namespace" || r.via === "destructured") && ctx.fromExports && ctx.toExports && !ctx.fromExports.has(r.symbol) && !ctx.toExports.has(r.symbol)) {
96
- add(r.file, r.line, `\`${r.symbol}\` is not an export of the ES module, so it reads as undefined`);
106
+ add(
107
+ r.file,
108
+ r.line,
109
+ `\`${r.symbol}\` is not an export of the ES module, so it reads as undefined`
110
+ );
97
111
  }
98
112
  }
99
113
  }
100
- const olderNode = to === "esm" && !ctx.asyncModule && !requireEsmGuaranteed(ctx.runtime) ? [...new Map(requireSites.map((r) => [`${r.file}:${r.line}`, { file: r.file, line: r.line }])).values()] : [];
114
+ const olderNode = to === "esm" && !ctx.asyncModule && !requireEsmGuaranteed(ctx.runtime) ? [
115
+ ...new Map(
116
+ requireSites.map((r) => [`${r.file}:${r.line}`, { file: r.file, line: r.line }])
117
+ ).values()
118
+ ] : [];
101
119
  if (!broken.size && !olderNode.length) return null;
102
120
  return { from, to, broken: [...broken.values()], olderNode };
103
121
  }
@@ -120,12 +138,21 @@ function engineRequirements(from, to, runtime) {
120
138
  const declared = runtime.engines;
121
139
  if (declared && import_semver.default.validRange(declared) && subsetOf(declared, needs) === false) {
122
140
  const alreadyOut = before && import_semver.default.validRange(before) && subsetOf(declared, before) === false;
123
- if (!alreadyOut) out.push({ kind: "engines", name: "node", needs, has: `${declared} (package.json engines)` });
141
+ if (!alreadyOut)
142
+ out.push({ kind: "engines", name: "node", needs, has: `${declared} (package.json engines)` });
124
143
  }
125
144
  const pinned = runtime.nodeVersionFile;
126
145
  if (pinned) {
127
146
  const conflicts = (range) => Boolean(range) && resolveRuntimeEngineConflicts(
128
- [{ name: to.name ?? "package", version: null, peerDependencies: null, peerDependenciesMeta: null, engines: { node: range } }],
147
+ [
148
+ {
149
+ name: to.name ?? "package",
150
+ version: null,
151
+ peerDependencies: null,
152
+ peerDependenciesMeta: null,
153
+ engines: { node: range }
154
+ }
155
+ ],
129
156
  pinned.value
130
157
  ).length > 0;
131
158
  if (conflicts(needs) && !conflicts(before)) {
@@ -159,7 +186,9 @@ function peerRequirements(from, to, runtime) {
159
186
  function projectVersionOf(root, name) {
160
187
  for (let dir = resolve(root); ; dir = dirname(dir)) {
161
188
  try {
162
- const { version } = JSON.parse(readFileSync(join(dir, "node_modules", name, "package.json"), "utf8"));
189
+ const { version } = JSON.parse(
190
+ readFileSync(join(dir, "node_modules", name, "package.json"), "utf8")
191
+ );
163
192
  if (version && import_semver.default.valid(version)) return { version, exact: true, source: "installed" };
164
193
  } catch {
165
194
  }
@@ -168,7 +197,8 @@ function projectVersionOf(root, name) {
168
197
  try {
169
198
  const manifest = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
170
199
  const declared = manifest.dependencies?.[name] ?? manifest.devDependencies?.[name];
171
- if (declared && import_semver.default.validRange(declared)) return { version: declared, exact: false, source: "package.json" };
200
+ if (declared && import_semver.default.validRange(declared))
201
+ return { version: declared, exact: false, source: "package.json" };
172
202
  } catch {
173
203
  }
174
204
  return null;
@@ -241,7 +271,12 @@ function compareEntry(from, to, symbols, specifier, isRoot) {
241
271
  const renames = new Map(diff.renamed.map((r) => [r.path, r.to]));
242
272
  const symbolsRemoved = diff.removed.filter((s) => referenced.has(s.path) && !toSurface.has(s.path)).map((s) => {
243
273
  const renamedTo = renames.get(s.path);
244
- return { symbol: s.path, ...tag, ...renamedTo ? { renamedTo } : {}, refs: symbols.get(s.path) ?? [] };
274
+ return {
275
+ symbol: s.path,
276
+ ...tag,
277
+ ...renamedTo ? { renamedTo } : {},
278
+ refs: symbols.get(s.path) ?? []
279
+ };
245
280
  });
246
281
  const stars = starReExports(to);
247
282
  if (symbolsRemoved.length && stars.length) {
@@ -277,9 +312,13 @@ async function checkUpgradeOne(target, refs, opts = {}) {
277
312
  if (!refs || refs.symbols.size === 0) return requirementsOnly(target, opts.runtime);
278
313
  const byEntry = groupByEntry(refs, target.package);
279
314
  if (byEntry.size === 0) return requirementsOnly(target, opts.runtime);
280
- const loose = [target.fromVersion, target.toVersion].filter((v) => import_semver2.default.validRange(v) && !import_semver2.default.valid(v));
315
+ const loose = [target.fromVersion, target.toVersion].filter(
316
+ (v) => import_semver2.default.validRange(v) && !import_semver2.default.valid(v)
317
+ );
281
318
  if (loose.length) {
282
- return { unverified: `expected exact versions, got ${target.fromVersion}..${target.toVersion}` };
319
+ return {
320
+ unverified: `expected exact versions, got ${target.fromVersion}..${target.toVersion}`
321
+ };
283
322
  }
284
323
  const settled = await Promise.allSettled([
285
324
  unpackPackage(target.package, target.fromVersion),
@@ -288,10 +327,16 @@ async function checkUpgradeOne(target, refs, opts = {}) {
288
327
  try {
289
328
  const failure = settled.find((s) => s.status === "rejected");
290
329
  if (failure) throw failure.reason;
291
- const [fromPkg, toPkg] = settled.map((s) => s.value);
330
+ const [fromPkg, toPkg] = settled.map(
331
+ (s) => s.value
332
+ );
292
333
  if (!fromPkg || !toPkg) {
293
- const missing = [fromPkg ? null : target.fromVersion, toPkg ? null : target.toVersion].filter(Boolean);
294
- return { unverified: `not published on npm: ${missing.map((v) => `${target.package}@${v}`).join(", ")}` };
334
+ const missing = [fromPkg ? null : target.fromVersion, toPkg ? null : target.toVersion].filter(
335
+ Boolean
336
+ );
337
+ return {
338
+ unverified: `not published on npm: ${missing.map((v) => `${target.package}@${v}`).join(", ")}`
339
+ };
295
340
  }
296
341
  return await compareVersions(target, refs, byEntry, fromPkg, toPkg, opts);
297
342
  } finally {
@@ -395,7 +440,7 @@ async function compareVersions(target, refs, byEntry, fromPkg, toPkg, opts) {
395
440
  const exportNames = (s) => s.undeclaredReason || starReExports(s).length ? null : new Set(s.symbols.filter((x) => x.kind !== "type_only").map((x) => x.path));
396
441
  const fromTarget = requireTarget(fromPkg.pkgDir);
397
442
  const toTarget = requireTarget(toPkg.pkgDir);
398
- const asyncModule = fromTarget?.format === "cjs" && toTarget?.format === "esm" && toTarget.file ? (await import("./extract-NKGKLIVT.js")).usesTopLevelAwait(toPkg.pkgDir, toTarget.file) : false;
443
+ const asyncModule = fromTarget?.format === "cjs" && toTarget?.format === "esm" && toTarget.file ? (await import("./extract-6WG265BL.js")).usesTopLevelAwait(toPkg.pkgDir, toTarget.file) : false;
399
444
  const moduleFormat = judgeRequires(
400
445
  fromTarget?.format ?? null,
401
446
  toTarget?.format ?? null,
@@ -449,7 +494,10 @@ async function checkUpgrade(targets, references, opts = {}) {
449
494
  const runtime = opts.rootDir ? readRepoRuntime(opts.rootDir) : {};
450
495
  for (const t of targets) {
451
496
  try {
452
- const res = await checkUpgradeOne(t, byPkg.get(t.package), { typeCheck: opts.typeCheck, runtime });
497
+ const res = await checkUpgradeOne(t, byPkg.get(t.package), {
498
+ typeCheck: opts.typeCheck,
499
+ runtime
500
+ });
453
501
  if (res.types) {
454
502
  types.push(
455
503
  res.types.checked ? { package: t.package, checked: true, files: res.types.files } : { package: t.package, checked: false, reason: res.types.reason }
@@ -478,7 +526,10 @@ function capped(items, cap = REPORT_LOCATION_CAP) {
478
526
  return items.length > cap ? `${shown} (+${items.length - cap} more)` : shown;
479
527
  }
480
528
  function locations(refs) {
481
- const all = refs.flatMap((r) => [`${r.file}:${r.line}`, ...(r.calls ?? []).map((c) => `${r.file}:${c.line}`)]);
529
+ const all = refs.flatMap((r) => [
530
+ `${r.file}:${r.line}`,
531
+ ...(r.calls ?? []).map((c) => `${r.file}:${c.line}`)
532
+ ]);
482
533
  return capped([...new Set(all)]) || "(no location)";
483
534
  }
484
535
  function params(required, max) {
@@ -510,8 +561,10 @@ function formatUpgradeReport(report, title = "upgrade check") {
510
561
  out.push(
511
562
  m.to === "esm" ? ` require('${b.package}') now loads an ES module (was CommonJS)` : ` require('${b.package}') no longer resolves: its exports map offers require() nothing`
512
563
  );
513
- for (const x of m.broken.slice(0, REPORT_LOCATION_CAP)) out.push(` \xB7 ${x.file}:${x.line} ${x.why}`);
514
- if (m.broken.length > REPORT_LOCATION_CAP) out.push(` \xB7 (+${m.broken.length - REPORT_LOCATION_CAP} more)`);
564
+ for (const x of m.broken.slice(0, REPORT_LOCATION_CAP))
565
+ out.push(` \xB7 ${x.file}:${x.line} ${x.why}`);
566
+ if (m.broken.length > REPORT_LOCATION_CAP)
567
+ out.push(` \xB7 (+${m.broken.length - REPORT_LOCATION_CAP} more)`);
515
568
  if (m.olderNode.length) {
516
569
  out.push(
517
570
  ` \xB7 throws ERR_REQUIRE_ESM on Node before 20.19 / 22.12: ${capped(m.olderNode.map((s) => `${s.file}:${s.line}`))}`
@@ -566,16 +619,17 @@ function formatUpgradeReport(report, title = "upgrade check") {
566
619
  out.push("");
567
620
  }
568
621
  const typed = report.types ?? [];
569
- const unchecked = typed.filter(
570
- (t) => !t.checked
571
- );
622
+ const unchecked = typed.filter((t) => !t.checked);
572
623
  if (typed.length > unchecked.length) {
573
- out.push(`TYPES checked ${typed.length - unchecked.length} package(s) in the files that import them`);
624
+ out.push(
625
+ `TYPES checked ${typed.length - unchecked.length} package(s) in the files that import them`
626
+ );
574
627
  }
575
628
  if (unchecked.length) {
576
629
  out.push(`TYPES not checked for ${unchecked.length} package(s):`);
577
630
  const byReason = /* @__PURE__ */ new Map();
578
- for (const t of unchecked) byReason.set(t.reason, [...byReason.get(t.reason) ?? [], t.package]);
631
+ for (const t of unchecked)
632
+ byReason.set(t.reason, [...byReason.get(t.reason) ?? [], t.package]);
579
633
  for (const [reason, names] of byReason) out.push(` \xB7 ${names.join(", ")}: ${reason}`);
580
634
  }
581
635
  if (typed.length) out.push("");
@@ -1,18 +1,19 @@
1
1
  import { createRequire as __lurqCreateRequire } from 'node:module'; const require = __lurqCreateRequire(import.meta.url);
2
2
  import {
3
3
  parseManifest
4
- } from "./chunk-DWAGCNEL.js";
5
- import "./chunk-B43LCXBM.js";
6
- import "./chunk-BCANRN5B.js";
7
- import "./chunk-SJOVFF7B.js";
4
+ } from "./chunk-TDTYV6QI.js";
5
+ import "./chunk-GM5Y555O.js";
6
+ import "./chunk-2GAYNIHG.js";
7
+ import "./chunk-KYKSZ3XZ.js";
8
+ import "./chunk-A3TYI2TF.js";
8
9
  import "./chunk-GRJXQBQZ.js";
9
10
  import "./chunk-WHX2ZFCG.js";
11
+ import "./chunk-MYGSLK44.js";
10
12
  import {
11
13
  fetchUpgradePlan
12
- } from "./chunk-4ZYCIMY4.js";
13
- import "./chunk-MYGSLK44.js";
14
- import "./chunk-Y5GI7RL3.js";
15
- import "./chunk-GPTKSNR6.js";
14
+ } from "./chunk-OTJFHESY.js";
15
+ import "./chunk-J6XQ7OPZ.js";
16
+ import "./chunk-72Y2FDVS.js";
16
17
  import {
17
18
  init_esm_shims
18
19
  } from "./chunk-I3M2KJXB.js";
@@ -111,13 +112,17 @@ function formatUpgradePlan(plan) {
111
112
  if (upgrade.removed.length) {
112
113
  const renamed = new Map((upgrade.renamed ?? []).map((r) => [r.path, r.to]));
113
114
  const label = (path) => renamed.has(path) ? `${path} \u2192 ${renamed.get(path).join(" | ")}` : path;
114
- out.push(` removes ${upgrade.removed.length}: ${upgrade.removed.slice(0, 8).map(label).join(", ")}`);
115
+ out.push(
116
+ ` removes ${upgrade.removed.length}: ${upgrade.removed.slice(0, 8).map(label).join(", ")}`
117
+ );
115
118
  }
116
119
  for (const change of upgrade.arityChanged.slice(0, 5)) {
117
120
  out.push(` arity ${change.path}: ${change.from ?? "?"} \u2192 ${change.to ?? "?"}`);
118
121
  }
119
122
  if (upgrade.hops?.length) {
120
- out.push(` via ${[upgrade.fromVersion, ...upgrade.hops.map((h) => h.toVersion)].join(" \u2192 ")}`);
123
+ out.push(
124
+ ` via ${[upgrade.fromVersion, ...upgrade.hops.map((h) => h.toVersion)].join(" \u2192 ")}`
125
+ );
121
126
  for (const hop of upgrade.hops) {
122
127
  const detail = hop.removed.length ? `removes ${hop.removed.slice(0, 5).join(", ")}` : hop.verdict === "unknown" ? "not yet analysed" : "no removals";
123
128
  out.push(` ${hop.fromVersion} \u2192 ${hop.toVersion}: ${detail}`);
@@ -136,11 +141,41 @@ function formatUpgradePlan(plan) {
136
141
  if (caveats.length) out.push("", `NOT COVERED: ${caveats.join("; ")}.`);
137
142
  return out.join("\n");
138
143
  }
144
+ function planHeadline(plan, source = []) {
145
+ const behind = plan.upgrades.length + plan.omitted;
146
+ const dead = source.filter((f) => f.severity === "blocking");
147
+ const parts = [];
148
+ if (dead.length) {
149
+ parts.push(`${dead.length} model id(s) the provider has retired \u2014 every call using them fails`);
150
+ }
151
+ if (behind === 0 && parts.length === 0) return null;
152
+ if (behind > 0) {
153
+ const advisories = plan.upgrades.filter((u) => u.advisories > 0).length;
154
+ const removes = plan.upgrades.filter((u) => u.verdict === "removes-exports").length;
155
+ parts.push(`${behind} of ${plan.deps} dependencies behind`);
156
+ if (advisories) parts.push(`${advisories} with a security advisory`);
157
+ if (removes) parts.push(`${removes} removing public exports`);
158
+ }
159
+ const unassessed = plan.omitted + plan.pending + plan.untracked;
160
+ return `${parts.join(", ")}.` + (unassessed ? ` ${unassessed} not assessed for breakage.` : "");
161
+ }
162
+ var HEADLINE_SCAN_LIMIT = 1500;
163
+ async function scanSourceDrift(dir, limit = HEADLINE_SCAN_LIMIT) {
164
+ try {
165
+ const { modelFindings } = await import("./model-ASMZWLM7.js");
166
+ return modelFindings(dir, { limit }).findings;
167
+ } catch {
168
+ return [];
169
+ }
170
+ }
139
171
  export {
172
+ HEADLINE_SCAN_LIMIT,
140
173
  buildUpgradePlan,
141
174
  detectRepoFullName,
142
175
  findManifests,
143
176
  formatUpgradePlan,
144
177
  mergedDeps,
145
- readManifests
178
+ planHeadline,
179
+ readManifests,
180
+ scanSourceDrift
146
181
  };
@@ -0,0 +1,13 @@
1
+ import { createRequire as __lurqCreateRequire } from 'node:module'; const require = __lurqCreateRequire(import.meta.url);
2
+ import {
3
+ runDomains
4
+ } from "./chunk-XBQA4I36.js";
5
+ import {
6
+ init_esm_shims
7
+ } from "./chunk-I3M2KJXB.js";
8
+
9
+ // src/mcp/upkeepHandler.ts
10
+ init_esm_shims();
11
+ export {
12
+ runDomains as handleUpkeep
13
+ };
@@ -7,7 +7,7 @@ import {
7
7
  resolveEndpoint,
8
8
  userConfigPath,
9
9
  writeUserConfig
10
- } from "./chunk-Y5GI7RL3.js";
10
+ } from "./chunk-J6XQ7OPZ.js";
11
11
  import "./chunk-I3M2KJXB.js";
12
12
  export {
13
13
  clearUserConfig,
@@ -1,29 +1,32 @@
1
1
  import { createRequire as __lurqCreateRequire } from 'node:module'; const require = __lurqCreateRequire(import.meta.url);
2
2
  import {
3
- enqueueSurface,
4
- getMcpServerNames
5
- } from "./chunk-LO35HLQZ.js";
6
- import {
3
+ enqueueCandidates,
4
+ getQueuedNames,
7
5
  syncOnePackage
8
- } from "./chunk-FW6BD2NO.js";
6
+ } from "./chunk-TUXQ32WE.js";
9
7
  import "./chunk-BUALU27S.js";
10
- import "./chunk-LRD4GBYE.js";
11
- import "./chunk-BCANRN5B.js";
12
- import "./chunk-2VMOWSRY.js";
8
+ import "./chunk-QUIMQ7YL.js";
9
+ import "./chunk-6DM6UQFD.js";
10
+ import "./chunk-EYAKM6YN.js";
11
+ import "./chunk-D3VTZS7V.js";
13
12
  import "./chunk-4ESO33J6.js";
14
- import "./chunk-CW5HJ3LX.js";
15
- import "./chunk-AHBP533R.js";
16
- import "./chunk-SJOVFF7B.js";
17
- import "./chunk-HWBBVLOT.js";
18
13
  import {
19
14
  getAllPackageNames
20
- } from "./chunk-NH5I4KHH.js";
15
+ } from "./chunk-NPVN2THM.js";
21
16
  import "./chunk-VLRHFMGJ.js";
22
- import "./chunk-WQ23REYT.js";
17
+ import "./chunk-VGCDRK3S.js";
18
+ import {
19
+ enqueueSurface,
20
+ getMcpServerNames
21
+ } from "./chunk-ONDVTXUO.js";
23
22
  import {
24
- discoveryQueue,
25
23
  watchState
26
- } from "./chunk-LYMPYETA.js";
24
+ } from "./chunk-4JHDSVIN.js";
25
+ import "./chunk-GM5Y555O.js";
26
+ import "./chunk-2GAYNIHG.js";
27
+ import "./chunk-KYKSZ3XZ.js";
28
+ import "./chunk-A3TYI2TF.js";
29
+ import "./chunk-6L67QMCP.js";
27
30
  import "./chunk-3GHJR7XR.js";
28
31
  import "./chunk-GRJXQBQZ.js";
29
32
  import "./chunk-WHX2ZFCG.js";
@@ -31,7 +34,7 @@ import "./chunk-LUAKDHLZ.js";
31
34
  import {
32
35
  logger
33
36
  } from "./chunk-MYGSLK44.js";
34
- import "./chunk-GPTKSNR6.js";
37
+ import "./chunk-72Y2FDVS.js";
35
38
  import {
36
39
  init_esm_shims
37
40
  } from "./chunk-I3M2KJXB.js";
@@ -39,25 +42,11 @@ import {
39
42
  // src/pipeline/watch.ts
40
43
  init_esm_shims();
41
44
 
42
- // src/db/discovery.ts
43
- init_esm_shims();
44
- import { eq, sql } from "drizzle-orm";
45
- async function getQueuedNames(db) {
46
- const rows = await db.select({ name: discoveryQueue.name }).from(discoveryQueue);
47
- return new Set(rows.map((r) => r.name));
48
- }
49
- async function enqueueCandidates(db, candidates) {
50
- if (candidates.length === 0) return 0;
51
- const rows = candidates.map((c) => ({ name: c.name, discoveredVia: c.via }));
52
- const inserted = await db.insert(discoveryQueue).values(rows).onConflictDoNothing({ target: discoveryQueue.name }).returning({ id: discoveryQueue.id });
53
- return inserted.length;
54
- }
55
-
56
45
  // src/db/watch.ts
57
46
  init_esm_shims();
58
- import { eq as eq2 } from "drizzle-orm";
47
+ import { eq } from "drizzle-orm";
59
48
  async function getWatchCursor(db, id) {
60
- const rows = await db.select({ seq: watchState.seq }).from(watchState).where(eq2(watchState.id, id)).limit(1);
49
+ const rows = await db.select({ seq: watchState.seq }).from(watchState).where(eq(watchState.id, id)).limit(1);
61
50
  return rows[0]?.seq ?? null;
62
51
  }
63
52
  async function setWatchCursor(db, id, seq) {
@@ -153,7 +142,7 @@ async function watchNpmChanges(db, opts = {}) {
153
142
  if (signal?.aborted) break;
154
143
  const route = routeChange(change, tracked, queued);
155
144
  if (route === "resync") {
156
- await syncOnePackage(db, change.id).catch(
145
+ await syncOnePackage(db, change.id, { fresh: true }).catch(
157
146
  (err) => logger.warn(`watch: re-sync failed for ${change.id}: ${String(err)}`)
158
147
  );
159
148
  resynced++;
@@ -193,6 +182,7 @@ async function watchNpmChanges(db, opts = {}) {
193
182
  logger.info("watch: stopped.");
194
183
  }
195
184
  function sleep(ms, signal) {
185
+ if (signal?.aborted) return Promise.resolve();
196
186
  return new Promise((resolve) => {
197
187
  const timer = setTimeout(resolve, ms);
198
188
  signal?.addEventListener(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lurqrun",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "Verify npm packages before your AI coding agent installs them: hallucinated and typosquatted names, advisories, API drift and version conflicts. MCP server, CLI and agent skill for Claude Code, Cursor and VS Code.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -93,7 +93,8 @@
93
93
  "content:releases": "tsx scripts/gen-releases.ts"
94
94
  },
95
95
  "dependencies": {
96
- "typescript": "^5.5.4"
96
+ "typescript": "^5.5.4",
97
+ "undici": "^7.29.1"
97
98
  },
98
99
  "devDependencies": {
99
100
  "@eslint/js": "^9.9.0",
@@ -20,7 +20,7 @@ reads like a guess.
20
20
  `verify` the one you choose. lurq checks candidates against evidence; it does not
21
21
  search for them, so the list is yours to bring. The same applies before hand-rolling
22
22
  something a well-maintained package may already do.
23
- - **Install a specific package** → `verify` with the exact name *before* adding it.
23
+ - **Install a specific package** → `verify` with the exact name _before_ adding it.
24
24
  This catches hallucinated, deprecated, and typosquatted names (e.g. `lodahs` vs
25
25
  `lodash`) and packages with known advisories. Cheap, and the highest-value call here.
26
26
  - **Choose between options** → `compare` with 2–5 package names for a ranked,
@@ -46,14 +46,24 @@ reads like a guess.
46
46
  shape, e.g. lodash); read its type declarations or use `resolve_surface`.
47
47
  - **Check whether a symbol actually exists at runtime** → `resolve_surface` with the
48
48
  package (and version, if you have one). `usage` reads the shipped `.d.ts`; this reads
49
- the shipped JavaScript, and the difference matters: a removed *type* breaks `tsc`, a
50
- removed *runtime* export breaks the running program. `UNKNOWN` means the surface has
49
+ the shipped JavaScript, and the difference matters: a removed _type_ breaks `tsc`, a
50
+ removed _runtime_ export breaks the running program. `UNKNOWN` means the surface has
51
51
  not been extracted yet and queues extraction — it never means the symbol is absent, so
52
52
  do not treat it as a negative answer.
53
53
  - **Explain a break, or plan an upgrade** → `diff_surface` with the package and the two
54
54
  versions. Returns what was removed, added, and what changed arity between them, with
55
55
  type-only removals listed separately because those break the build rather than the
56
56
  program. Static comparison of both published versions — no install, no test run.
57
+ - **Start work in a project you have just opened, or see what an upgrade broke** →
58
+ `upkeep` with its directory. It reads the project itself and returns what needs
59
+ fixing: environment variables the code reads that no `.env` file declares, and —
60
+ when you pass the versions you are moving between — the call sites an upgrade
61
+ breaks, the replacement the package itself proves, and the manifest ranges left
62
+ stale. Findings carry either exact edits you can apply or the facts you cannot
63
+ look up, such as the exports the target version actually ships with their
64
+ arities. A domain it could not run says so: an empty result is not a clean
65
+ project. Offered only when lurq runs beside your files (`lurq serve`) — the
66
+ hosted server cannot see them, so the tool is absent there rather than empty.
57
67
  - **Take stock of a whole project** → `audit` with the inventory you read from its
58
68
  `package.json` + lockfile and its MCP configs (names and versions only — never source).
59
69
  One call returns every outdated, deprecated and vulnerable dependency plus every MCP
@@ -84,6 +94,15 @@ reads like a guess.
84
94
  can catch it, and the symptom is a malformed call that looks like a model mistake.
85
95
  **Privilege widening** is a tool that stopped being read-only or started being
86
96
  destructive; nothing breaks, which is what makes it worse than a break.
97
+ - **Add an MCP server to a client, or a remote server will not connect** → `connect_check`
98
+ with the endpoint URL, registry name or npm package, and the `client` you are wiring it
99
+ into (`claude-code`, `cursor`, `vscode`, `chatgpt`, `claude-ai`, `codex`, `gemini-cli`, …).
100
+ Returns `works`, `needs_setup` with the exact steps (a key header, an OAuth client to
101
+ pre-register and its redirect URIs), `blocked` with the reason, or `unknown`, plus config
102
+ in that client's own format. Built from a credential-free probe of the server and the
103
+ client's documented constraints. Use the returned config instead of writing one from
104
+ memory, put any setup step in front of the user, and never invent a key: header values
105
+ are placeholders. `unknown` is not "will not work".
87
106
  - **Visualize a stack you have already chosen** → `diagram` with the package names. A
88
107
  labeled starting point by layer — not a validated architecture.
89
108
  - **Unsure whether lurq covers the situation** → `capabilities` with what you are trying