lurqrun 0.1.6 → 0.1.7

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 (206) hide show
  1. package/README.md +18 -10
  2. package/dist/auditHandler-JCOJSUYW.js +23 -0
  3. package/dist/bin/lurq.js +3090 -23306
  4. package/dist/browserAuth-B6G27USY.js +95 -0
  5. package/dist/cache-DKI34SVS.js +12 -0
  6. package/dist/check-2FDGUOV7.js +192 -0
  7. package/dist/checkUpgrade-F2WESBPM.js +103 -0
  8. package/dist/chunk-2VMOWSRY.js +300 -0
  9. package/dist/chunk-3GHJR7XR.js +2049 -0
  10. package/dist/chunk-3N3Q3DSW.js +214 -0
  11. package/dist/chunk-4ESO33J6.js +34 -0
  12. package/dist/chunk-4F7ZESPO.js +132 -0
  13. package/dist/chunk-4KCPOMG6.js +68 -0
  14. package/dist/chunk-4ZYCIMY4.js +155 -0
  15. package/dist/chunk-63MUJNZL.js +318 -0
  16. package/dist/chunk-6AAEVQ7I.js +6336 -0
  17. package/dist/chunk-6EQ3ARXA.js +304 -0
  18. package/dist/chunk-6L3U7DZ5.js +23 -0
  19. package/dist/chunk-AHBP533R.js +220 -0
  20. package/dist/chunk-B43LCXBM.js +223 -0
  21. package/dist/chunk-BCANRN5B.js +33 -0
  22. package/dist/chunk-BUALU27S.js +123 -0
  23. package/dist/chunk-BULZAX2U.js +1554 -0
  24. package/dist/chunk-BV32UNLL.js +154 -0
  25. package/dist/chunk-C6GLE626.js +160 -0
  26. package/dist/chunk-CIDWNUAP.js +145 -0
  27. package/dist/chunk-CUP36ND3.js +2126 -0
  28. package/dist/chunk-CW5HJ3LX.js +96 -0
  29. package/dist/chunk-DB2VF5UD.js +315 -0
  30. package/dist/chunk-DWAGCNEL.js +210 -0
  31. package/dist/chunk-EA3DP5HG.js +293 -0
  32. package/dist/chunk-ELGCAM7P.js +184 -0
  33. package/dist/chunk-FW6BD2NO.js +1915 -0
  34. package/dist/chunk-GE37NVLN.js +15 -0
  35. package/dist/chunk-GPTKSNR6.js +171 -0
  36. package/dist/chunk-GRJXQBQZ.js +793 -0
  37. package/dist/chunk-HWBBVLOT.js +92 -0
  38. package/dist/chunk-I2JUKN6Z.js +24 -0
  39. package/dist/chunk-I3M2KJXB.js +56 -0
  40. package/dist/chunk-IQ4SDKKY.js +733 -0
  41. package/dist/chunk-J5FZYN4A.js +116 -0
  42. package/dist/chunk-L6N4JFW2.js +263 -0
  43. package/dist/chunk-LBFGSSF2.js +126 -0
  44. package/dist/chunk-LEGPB7DO.js +81 -0
  45. package/dist/chunk-LO35HLQZ.js +219 -0
  46. package/dist/chunk-LRD4GBYE.js +73 -0
  47. package/dist/chunk-LUAKDHLZ.js +40 -0
  48. package/dist/chunk-LYMPYETA.js +965 -0
  49. package/dist/chunk-M6NYEXCW.js +38 -0
  50. package/dist/chunk-MHUEVBVO.js +35 -0
  51. package/dist/chunk-MYGSLK44.js +37 -0
  52. package/dist/chunk-NH5I4KHH.js +201 -0
  53. package/dist/chunk-OQS4GUSI.js +1391 -0
  54. package/dist/chunk-PSX3GIAN.js +176 -0
  55. package/dist/chunk-Q5VPF4WI.js +26 -0
  56. package/dist/chunk-QKGYDMWB.js +7409 -0
  57. package/dist/chunk-QSL6QN5X.js +115 -0
  58. package/dist/chunk-SHCEBP3J.js +107 -0
  59. package/dist/chunk-SJOVFF7B.js +201 -0
  60. package/dist/chunk-ST2X2GYN.js +373 -0
  61. package/dist/chunk-TNTXWSYA.js +19 -0
  62. package/dist/chunk-U5AT3TD4.js +2128 -0
  63. package/dist/chunk-UDVNA7EA.js +483 -0
  64. package/dist/chunk-VL2E5T2A.js +109 -0
  65. package/dist/chunk-VLRHFMGJ.js +58 -0
  66. package/dist/chunk-WHX2ZFCG.js +4048 -0
  67. package/dist/chunk-WQ23REYT.js +37 -0
  68. package/dist/chunk-XBIDMHSK.js +15425 -0
  69. package/dist/chunk-Y5GI7RL3.js +66 -0
  70. package/dist/client-IRKAMDYZ.js +15 -0
  71. package/dist/commands-FIL5ET6P.js +911 -0
  72. package/dist/compat-R3UTFQ5Q.js +201 -0
  73. package/dist/dashboardIssue-WYYMBFIB.js +192 -0
  74. package/dist/diff-GZA2774U.js +13 -0
  75. package/dist/dist-4XXIXHHZ.js +12945 -0
  76. package/dist/e2b-FVPHDULZ.js +172 -0
  77. package/dist/extract-NKGKLIVT.js +444 -0
  78. package/dist/fetch-QYTUJVG2.js +22 -0
  79. package/dist/firstTouch-QQTJH4QX.js +55 -0
  80. package/dist/handlers-GEJAVZDK.js +53 -0
  81. package/dist/http-ETPYMBGD.js +5360 -0
  82. package/dist/ingestQueue-VKN4KBIF.js +35 -0
  83. package/dist/install-EK3W2COX.js +20 -0
  84. package/dist/installSkill-VQJWJVCL.js +52 -0
  85. package/dist/inventory-5AWSLJYU.js +31 -0
  86. package/dist/local-XPZMRH5R.js +13 -0
  87. package/dist/mcp-3JHD5SUZ.js +472 -0
  88. package/dist/mcpHandlers-QFN4MCFL.js +22 -0
  89. package/dist/mcpScan-QZHWENIP.js +1871 -0
  90. package/dist/mcpScanWorkflow-JPYCBGC4.js +81 -0
  91. package/dist/mcpStack-BYJCZNIV.js +20 -0
  92. package/dist/packages-THVFMWFP.js +42 -0
  93. package/dist/plan-V4OEI3J4.js +463 -0
  94. package/dist/planView-JRXGCG2N.js +79 -0
  95. package/dist/policy-3P6BGRDN.js +115 -0
  96. package/dist/references-6N7VEPHT.js +14 -0
  97. package/dist/release-4U4ABNSJ.js +128 -0
  98. package/dist/remote-YGCXYI4V.js +32 -0
  99. package/dist/reportRuns-CKQQYLY4.js +64 -0
  100. package/dist/sandbox-MEZLAODF.js +39 -0
  101. package/dist/server-KFUD5X57.js +55 -0
  102. package/dist/surface-V62GE554.js +141 -0
  103. package/dist/surface-YL6O67W3.js +36 -0
  104. package/dist/surfaceHandlers-X2IZKA3E.js +20 -0
  105. package/dist/typecheck-X7U5ELMR.js +268 -0
  106. package/dist/types-M5JP2W3D.js +10 -0
  107. package/dist/uninstall-P7RGBX6G.js +174 -0
  108. package/dist/upgrade-NQ5IWFZB.js +596 -0
  109. package/dist/upgradePlan-A4LRKLEG.js +146 -0
  110. package/dist/userConfig-Z3GQE776.js +20 -0
  111. package/dist/watch-DGFMWUDL.js +214 -0
  112. package/package.json +26 -21
  113. package/templates/agent-rules.md +4 -4
  114. package/templates/skill-instructions.md +13 -14
  115. package/dist/bin/lurq.js.map +0 -1
  116. package/dist/index.d.ts +0 -805
  117. package/dist/index.js +0 -23570
  118. package/dist/index.js.map +0 -1
  119. package/drizzle/0000_confused_fabian_cortez.sql +0 -54
  120. package/drizzle/0001_aspiring_timeslip.sql +0 -15
  121. package/drizzle/0002_lyrical_lila_cheney.sql +0 -14
  122. package/drizzle/0003_violet_giant_girl.sql +0 -14
  123. package/drizzle/0004_slim_valeria_richards.sql +0 -15
  124. package/drizzle/0005_petite_luke_cage.sql +0 -12
  125. package/drizzle/0006_calm_nighthawk.sql +0 -3
  126. package/drizzle/0007_slimy_naoko.sql +0 -1
  127. package/drizzle/0008_peaceful_tigra.sql +0 -1
  128. package/drizzle/0009_smooth_harrier.sql +0 -10
  129. package/drizzle/0010_curved_amphibian.sql +0 -2
  130. package/drizzle/0011_compat_provenance_closures.sql +0 -11
  131. package/drizzle/0012_api_surfaces.sql +0 -9
  132. package/drizzle/0013_nice_thanos.sql +0 -1
  133. package/drizzle/0014_luxuriant_malcolm_colcord.sql +0 -10
  134. package/drizzle/0015_past_fat_cobra.sql +0 -11
  135. package/drizzle/0016_futuristic_junta.sql +0 -50
  136. package/drizzle/0017_absent_grandmaster.sql +0 -20
  137. package/drizzle/0018_rainy_proemial_gods.sql +0 -1
  138. package/drizzle/0019_dashing_korvac.sql +0 -11
  139. package/drizzle/0020_normal_vulture.sql +0 -3
  140. package/drizzle/0021_dazzling_blue_shield.sql +0 -17
  141. package/drizzle/0022_massive_ghost_rider.sql +0 -24
  142. package/drizzle/0023_next_shatterstar.sql +0 -1
  143. package/drizzle/0024_dusty_maelstrom.sql +0 -15
  144. package/drizzle/0025_gifted_harpoon.sql +0 -5
  145. package/drizzle/0026_awesome_mordo.sql +0 -1
  146. package/drizzle/0027_charming_ulik.sql +0 -2
  147. package/drizzle/0028_romantic_loners.sql +0 -2
  148. package/drizzle/0029_busy_korvac.sql +0 -16
  149. package/drizzle/0030_steady_mathemanic.sql +0 -6
  150. package/drizzle/0031_redundant_maginty.sql +0 -2
  151. package/drizzle/0032_stack_resolutions.sql +0 -14
  152. package/drizzle/0033_graceful_tyger_tiger.sql +0 -3
  153. package/drizzle/0034_uneven_thunderbird.sql +0 -1
  154. package/drizzle/0035_api_key_scopes.sql +0 -1
  155. package/drizzle/0036_policy_audit.sql +0 -21
  156. package/drizzle/0037_subscription_seats.sql +0 -1
  157. package/drizzle/0038_symbol_offsets.sql +0 -2
  158. package/drizzle/0039_mcp_runtime_scans.sql +0 -80
  159. package/drizzle/0040_subscription_overage_and_interval.sql +0 -4
  160. package/drizzle/0041_account_email.sql +0 -38
  161. package/drizzle/0042_alert_channels.sql +0 -21
  162. package/drizzle/meta/0000_snapshot.json +0 -370
  163. package/drizzle/meta/0001_snapshot.json +0 -482
  164. package/drizzle/meta/0002_snapshot.json +0 -575
  165. package/drizzle/meta/0003_snapshot.json +0 -667
  166. package/drizzle/meta/0004_snapshot.json +0 -769
  167. package/drizzle/meta/0005_snapshot.json +0 -864
  168. package/drizzle/meta/0006_snapshot.json +0 -882
  169. package/drizzle/meta/0007_snapshot.json +0 -876
  170. package/drizzle/meta/0008_snapshot.json +0 -882
  171. package/drizzle/meta/0009_snapshot.json +0 -948
  172. package/drizzle/meta/0010_snapshot.json +0 -969
  173. package/drizzle/meta/0011_snapshot.json +0 -1049
  174. package/drizzle/meta/0012_snapshot.json +0 -1115
  175. package/drizzle/meta/0013_snapshot.json +0 -1121
  176. package/drizzle/meta/0014_snapshot.json +0 -1190
  177. package/drizzle/meta/0015_snapshot.json +0 -1280
  178. package/drizzle/meta/0016_snapshot.json +0 -1683
  179. package/drizzle/meta/0017_snapshot.json +0 -1834
  180. package/drizzle/meta/0018_snapshot.json +0 -1834
  181. package/drizzle/meta/0019_snapshot.json +0 -1909
  182. package/drizzle/meta/0020_snapshot.json +0 -1921
  183. package/drizzle/meta/0021_snapshot.json +0 -2045
  184. package/drizzle/meta/0022_snapshot.json +0 -2246
  185. package/drizzle/meta/0023_snapshot.json +0 -2252
  186. package/drizzle/meta/0024_snapshot.json +0 -2375
  187. package/drizzle/meta/0025_snapshot.json +0 -2407
  188. package/drizzle/meta/0026_snapshot.json +0 -2413
  189. package/drizzle/meta/0027_snapshot.json +0 -2425
  190. package/drizzle/meta/0028_snapshot.json +0 -2438
  191. package/drizzle/meta/0029_snapshot.json +0 -2546
  192. package/drizzle/meta/0030_snapshot.json +0 -2586
  193. package/drizzle/meta/0031_snapshot.json +0 -2598
  194. package/drizzle/meta/0032_snapshot.json +0 -2699
  195. package/drizzle/meta/0033_snapshot.json +0 -2712
  196. package/drizzle/meta/0034_snapshot.json +0 -2719
  197. package/drizzle/meta/0035_snapshot.json +0 -2726
  198. package/drizzle/meta/0036_snapshot.json +0 -2876
  199. package/drizzle/meta/0037_snapshot.json +0 -2883
  200. package/drizzle/meta/0038_snapshot.json +0 -2895
  201. package/drizzle/meta/0039_snapshot.json +0 -3501
  202. package/drizzle/meta/0040_snapshot.json +0 -3527
  203. package/drizzle/meta/0041_snapshot.json +0 -3824
  204. package/drizzle/meta/0042_snapshot.json +0 -3960
  205. package/drizzle/meta/_journal.json +0 -307
  206. package/src/data/seed.json +0 -253
@@ -0,0 +1,304 @@
1
+ import { createRequire as __lurqCreateRequire } from 'node:module'; const require = __lurqCreateRequire(import.meta.url);
2
+ import {
3
+ diffSurfaces
4
+ } from "./chunk-SHCEBP3J.js";
5
+ import {
6
+ init_esm_shims
7
+ } from "./chunk-I3M2KJXB.js";
8
+
9
+ // src/surface/mcp.ts
10
+ init_esm_shims();
11
+ import { createHash } from "crypto";
12
+ var MCP_TIER = "mcp_tools_list";
13
+ var PROSE_KEYS = /* @__PURE__ */ new Set(["description", "title", "$comment", "examples", "$schema"]);
14
+ function canonicalize(value) {
15
+ if (Array.isArray(value)) return value.map(canonicalize);
16
+ if (value === null || typeof value !== "object") return value;
17
+ const src = value;
18
+ const out = {};
19
+ for (const k of Object.keys(src).sort()) {
20
+ if (PROSE_KEYS.has(k)) continue;
21
+ const v = canonicalize(src[k]);
22
+ if (v === void 0) continue;
23
+ out[k] = v;
24
+ }
25
+ if (Array.isArray(out.type) && out.type.every((t) => typeof t === "string")) {
26
+ const t = [...new Set(out.type)].sort();
27
+ out.type = t.length === 1 ? t[0] : t;
28
+ }
29
+ if (Array.isArray(out.required) && out.required.every((r) => typeof r === "string")) {
30
+ const r = [...new Set(out.required)].sort();
31
+ if (r.length === 0) delete out.required;
32
+ else out.required = r;
33
+ }
34
+ return out;
35
+ }
36
+ var ANNOTATION_DEFAULTS = {
37
+ readOnlyHint: false,
38
+ destructiveHint: true,
39
+ idempotentHint: false,
40
+ openWorldHint: true
41
+ };
42
+ function resolveAnnotations(a) {
43
+ const out = {};
44
+ for (const k of Object.keys(ANNOTATION_DEFAULTS)) {
45
+ const v = a?.[k];
46
+ out[k] = typeof v === "boolean" ? v : ANNOTATION_DEFAULTS[k];
47
+ }
48
+ return out;
49
+ }
50
+ var WIDENS_WHEN_FALSE = {
51
+ readOnlyHint: true,
52
+ // true → false: the tool started writing
53
+ destructiveHint: false,
54
+ // false → true: the tool started destroying
55
+ idempotentHint: true,
56
+ // true → false: retries are no longer safe
57
+ openWorldHint: false
58
+ // false → true: the tool started reaching outside
59
+ };
60
+ var sha = (s) => createHash("sha256").update(s).digest("hex");
61
+ function toolContract(t) {
62
+ return {
63
+ input: canonicalize(t.inputSchema ?? null),
64
+ output: canonicalize(t.outputSchema ?? null),
65
+ annotations: resolveAnnotations(t.annotations),
66
+ prose: sha(`${t.title ?? ""}\0${t.description ?? ""}`).slice(0, 16)
67
+ };
68
+ }
69
+ function properties(c) {
70
+ const input = c?.input;
71
+ if (!input || typeof input !== "object") return {};
72
+ const props = input.properties;
73
+ return props && typeof props === "object" ? props : {};
74
+ }
75
+ function requiredSet(c) {
76
+ const input = c?.input;
77
+ if (!input || typeof input !== "object") return /* @__PURE__ */ new Set();
78
+ const req = input.required;
79
+ return new Set(Array.isArray(req) ? req.filter((r) => typeof r === "string") : []);
80
+ }
81
+ function requiredParams(t) {
82
+ return [...requiredSet(toolContract(t))].sort();
83
+ }
84
+ var DEPRECATED_RE = /^\s*[[(]?\s*(?:@)?deprecated\b/i;
85
+ function looksDeprecated(t) {
86
+ return DEPRECATED_RE.test(t.description ?? "") || DEPRECATED_RE.test(t.title ?? "");
87
+ }
88
+ function toolToSymbol(t) {
89
+ return {
90
+ path: t.name,
91
+ kind: "function",
92
+ arity: requiredParams(t).length,
93
+ // MCP has no re-export mechanism: every tool a server lists is its own.
94
+ origin: "local",
95
+ deprecated: looksDeprecated(t),
96
+ tier: MCP_TIER,
97
+ signature: JSON.stringify(toolContract(t))
98
+ };
99
+ }
100
+ function mcpSurface(server, version, tools) {
101
+ return {
102
+ package: server,
103
+ version,
104
+ tier: MCP_TIER,
105
+ entry: null,
106
+ symbols: tools.map(toolToSymbol),
107
+ filesWalked: 0,
108
+ externalReExports: [],
109
+ ...tools.length === 0 ? { undeclaredReason: "server listed no tools" } : {}
110
+ };
111
+ }
112
+ function surfaceHash(tools) {
113
+ const canon = [...tools].sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0).map((t) => [t.name, toolContract(t)]);
114
+ return sha(JSON.stringify(canon));
115
+ }
116
+ function contractOf(s) {
117
+ if (!s.signature) return null;
118
+ try {
119
+ return JSON.parse(s.signature);
120
+ } catch {
121
+ return null;
122
+ }
123
+ }
124
+ var emptyDrift = (from, to, reason) => ({
125
+ server: from.package,
126
+ fromVersion: from.version,
127
+ toVersion: to.version,
128
+ tier: MCP_TIER,
129
+ removedTools: [],
130
+ addedTools: [],
131
+ requiredAdded: [],
132
+ requiredRelaxed: [],
133
+ paramsRemoved: [],
134
+ paramsAdded: [],
135
+ typeChanged: [],
136
+ outputChanged: [],
137
+ annotationFlips: [],
138
+ silentDrift: [],
139
+ prosePolished: [],
140
+ deprecated: [],
141
+ breaking: false,
142
+ inconclusive: reason
143
+ });
144
+ function typeSet(p) {
145
+ const t = p.type;
146
+ if (typeof t === "string") return /* @__PURE__ */ new Set([t]);
147
+ if (Array.isArray(t)) return new Set(t.filter((x) => typeof x === "string"));
148
+ return null;
149
+ }
150
+ function enumSet(p) {
151
+ return Array.isArray(p.enum) ? new Set(p.enum.map((v) => JSON.stringify(v))) : null;
152
+ }
153
+ function accepts(a, b) {
154
+ if (b === null) return true;
155
+ if (a === null) return false;
156
+ return [...a].every((v) => b.has(v));
157
+ }
158
+ var RELAXABLE = /* @__PURE__ */ new Set([
159
+ "type",
160
+ "enum",
161
+ "additionalProperties",
162
+ "required",
163
+ "properties",
164
+ "items"
165
+ ]);
166
+ function isWidening(a, b) {
167
+ if (JSON.stringify(a) === JSON.stringify(b)) return true;
168
+ if (!a || typeof a !== "object" || !b || typeof b !== "object") return false;
169
+ if (Array.isArray(a) || Array.isArray(b)) return false;
170
+ const pa = a;
171
+ const pb = b;
172
+ for (const k of /* @__PURE__ */ new Set([...Object.keys(pa), ...Object.keys(pb)])) {
173
+ if (RELAXABLE.has(k)) continue;
174
+ if (JSON.stringify(pa[k]) !== JSON.stringify(pb[k])) return false;
175
+ }
176
+ if (!accepts(typeSet(pa), typeSet(pb))) return false;
177
+ if (!accepts(enumSet(pa), enumSet(pb))) return false;
178
+ if (JSON.stringify(pa.additionalProperties) !== JSON.stringify(pb.additionalProperties)) {
179
+ if (pa.additionalProperties !== false) return false;
180
+ }
181
+ const ra = new Set(Array.isArray(pa.required) ? pa.required : []);
182
+ const rb = new Set(Array.isArray(pb.required) ? pb.required : []);
183
+ for (const k of rb) if (!ra.has(k)) return false;
184
+ const propsA = pa.properties ?? {};
185
+ const propsB = pb.properties ?? {};
186
+ for (const k of Object.keys(propsA)) {
187
+ if (!(k in propsB)) {
188
+ if (pb.additionalProperties === false) return false;
189
+ continue;
190
+ }
191
+ if (!isWidening(propsA[k], propsB[k])) return false;
192
+ }
193
+ if ("items" in pa || "items" in pb) {
194
+ if (!isWidening(pa.items ?? {}, pb.items ?? {})) return false;
195
+ }
196
+ return true;
197
+ }
198
+ function diffMcpSurfaces(from, to) {
199
+ const base = diffSurfaces(from, to);
200
+ if (base.inconclusive) return emptyDrift(from, to, base.inconclusive);
201
+ const drift = emptyDrift(from, to, "");
202
+ delete drift.inconclusive;
203
+ drift.removedTools = base.removed.map((s) => s.path).sort();
204
+ drift.addedTools = base.added.map((s) => s.path).sort();
205
+ drift.deprecated = base.deprecated.map((s) => s.path).sort();
206
+ const fromByName = new Map(from.symbols.map((s) => [s.path, s]));
207
+ for (const toSym of to.symbols) {
208
+ const fromSym = fromByName.get(toSym.path);
209
+ if (!fromSym) continue;
210
+ const a = contractOf(fromSym);
211
+ const b = contractOf(toSym);
212
+ if (!a || !b) continue;
213
+ const tool = toSym.path;
214
+ const pa = properties(a);
215
+ const pb = properties(b);
216
+ const ra = requiredSet(a);
217
+ const rb = requiredSet(b);
218
+ const gone = Object.keys(pa).filter((k) => !(k in pb)).sort();
219
+ const fresh = Object.keys(pb).filter((k) => !(k in pa)).sort();
220
+ if (gone.length) drift.paramsRemoved.push({ tool, params: gone });
221
+ if (fresh.length) drift.paramsAdded.push({ tool, params: fresh });
222
+ const nowRequired = [...rb].filter((k) => !ra.has(k)).sort();
223
+ const nowOptional = [...ra].filter((k) => !rb.has(k) && k in pb).sort();
224
+ if (nowRequired.length) drift.requiredAdded.push({ tool, params: nowRequired });
225
+ if (nowOptional.length) drift.requiredRelaxed.push({ tool, params: nowOptional });
226
+ for (const param of Object.keys(pb)) {
227
+ if (!(param in pa)) continue;
228
+ const before = JSON.stringify(pa[param]);
229
+ const after = JSON.stringify(pb[param]);
230
+ if (before === after) continue;
231
+ drift.typeChanged.push({
232
+ tool,
233
+ param,
234
+ from: before,
235
+ to: after,
236
+ widened: isWidening(pa[param], pb[param])
237
+ });
238
+ }
239
+ if (JSON.stringify(a.output) !== JSON.stringify(b.output)) drift.outputChanged.push(tool);
240
+ for (const hint of Object.keys(ANNOTATION_DEFAULTS)) {
241
+ if (a.annotations[hint] === b.annotations[hint]) continue;
242
+ drift.annotationFlips.push({
243
+ tool,
244
+ hint,
245
+ from: a.annotations[hint],
246
+ to: b.annotations[hint],
247
+ widensPrivilege: b.annotations[hint] === !WIDENS_WHEN_FALSE[hint]
248
+ });
249
+ }
250
+ const contractMoved = JSON.stringify(a.input) !== JSON.stringify(b.input) || JSON.stringify(a.output) !== JSON.stringify(b.output) || JSON.stringify(a.annotations) !== JSON.stringify(b.annotations);
251
+ const proseMoved = a.prose !== b.prose;
252
+ if (contractMoved && !proseMoved) drift.silentDrift.push(tool);
253
+ if (proseMoved && !contractMoved) drift.prosePolished.push(tool);
254
+ }
255
+ drift.breaking = drift.removedTools.length > 0 || drift.requiredAdded.length > 0 || drift.paramsRemoved.length > 0 || drift.typeChanged.some((c) => !c.widened);
256
+ return drift;
257
+ }
258
+ function summarizeDrift(d) {
259
+ const alarming = [];
260
+ const benign = [];
261
+ const widened = d.annotationFlips.filter((f) => f.widensPrivilege);
262
+ if (widened.length) {
263
+ alarming.push(
264
+ `${widened.length} privilege widening(s): ` + widened.map((f) => `${f.tool}.${f.hint} ${f.from}\u2192${f.to}`).join(", ")
265
+ );
266
+ }
267
+ if (d.removedTools.length) alarming.push(`${d.removedTools.length} tool(s) removed`);
268
+ if (d.requiredAdded.length) {
269
+ alarming.push(`${d.requiredAdded.length} tool(s) gained required params`);
270
+ }
271
+ if (d.paramsRemoved.length) alarming.push(`${d.paramsRemoved.length} tool(s) dropped params`);
272
+ const narrowed = d.typeChanged.filter((c) => !c.widened);
273
+ if (narrowed.length) alarming.push(`${narrowed.length} param type(s) narrowed`);
274
+ if (d.silentDrift.length) {
275
+ alarming.push(
276
+ `${d.silentDrift.length} SILENT change(s) (contract moved, description unchanged): ${d.silentDrift.join(", ")}`
277
+ );
278
+ }
279
+ if (d.addedTools.length) benign.push(`${d.addedTools.length} tool(s) added`);
280
+ const relaxed = d.typeChanged.length - narrowed.length;
281
+ if (relaxed) benign.push(`${relaxed} param type(s) relaxed`);
282
+ if (d.requiredRelaxed.length) {
283
+ benign.push(`${d.requiredRelaxed.length} tool(s) made params optional`);
284
+ }
285
+ if (d.paramsAdded.length) benign.push(`${d.paramsAdded.length} tool(s) gained optional params`);
286
+ if (d.outputChanged.length) benign.push(`${d.outputChanged.length} output schema(s) changed`);
287
+ const safeFlips = d.annotationFlips.length - widened.length;
288
+ if (safeFlips) benign.push(`${safeFlips} annotation(s) narrowed`);
289
+ if (d.deprecated.length) benign.push(`${d.deprecated.length} tool(s) newly deprecated`);
290
+ if (d.prosePolished.length) benign.push(`${d.prosePolished.length} description(s) edited`);
291
+ if (alarming.length) return alarming.join("; ");
292
+ if (benign.length) return `compatible: ${benign.join(", ")}`;
293
+ return "no contract change";
294
+ }
295
+
296
+ export {
297
+ MCP_TIER,
298
+ resolveAnnotations,
299
+ mcpSurface,
300
+ surfaceHash,
301
+ contractOf,
302
+ diffMcpSurfaces,
303
+ summarizeDrift
304
+ };
@@ -0,0 +1,23 @@
1
+ import { createRequire as __lurqCreateRequire } from 'node:module'; const require = __lurqCreateRequire(import.meta.url);
2
+ import {
3
+ verificationRuns
4
+ } from "./chunk-LYMPYETA.js";
5
+ import {
6
+ init_esm_shims
7
+ } from "./chunk-I3M2KJXB.js";
8
+
9
+ // src/db/verification.ts
10
+ init_esm_shims();
11
+ import { desc, eq } from "drizzle-orm";
12
+ async function storeVerificationRun(db, run) {
13
+ await db.insert(verificationRuns).values(run);
14
+ }
15
+ async function getLatestVerificationByName(db, packageName) {
16
+ const rows = await db.select().from(verificationRuns).where(eq(verificationRuns.packageName, packageName)).orderBy(desc(verificationRuns.ranAt)).limit(1);
17
+ return rows[0] ?? null;
18
+ }
19
+
20
+ export {
21
+ storeVerificationRun,
22
+ getLatestVerificationByName
23
+ };
@@ -0,0 +1,220 @@
1
+ import { createRequire as __lurqCreateRequire } from 'node:module'; const require = __lurqCreateRequire(import.meta.url);
2
+ import {
3
+ httpGetJson
4
+ } from "./chunk-SJOVFF7B.js";
5
+ import {
6
+ CACHE_TTL
7
+ } from "./chunk-GPTKSNR6.js";
8
+ import {
9
+ init_esm_shims
10
+ } from "./chunk-I3M2KJXB.js";
11
+
12
+ // src/ingestion/sources/npmRegistry.ts
13
+ init_esm_shims();
14
+ var HOST = "registry.npmjs.org";
15
+ function encodeNpmName(name) {
16
+ return name.startsWith("@") ? name.replace("/", "%2F") : name;
17
+ }
18
+ function parseGithubRepo(url) {
19
+ if (!url) return null;
20
+ const match = url.match(/github\.com[/:]([^/]+)\/([^/#?]+?)(?:\.git)?(?:[/#?].*)?$/i);
21
+ if (!match) return null;
22
+ const owner = match[1];
23
+ const repo = match[2];
24
+ if (!owner || !repo) return null;
25
+ return { owner, repo };
26
+ }
27
+ function normalizeRepoUrl(repository, homepage) {
28
+ let raw = null;
29
+ if (typeof repository === "string") raw = repository;
30
+ else if (repository && typeof repository === "object" && "url" in repository) {
31
+ raw = String(repository.url);
32
+ }
33
+ const repo = parseGithubRepo(raw) ?? parseGithubRepo(homepage);
34
+ const repoUrl = repo ? `https://github.com/${repo.owner}/${repo.repo}` : cleanUrl(raw) ?? null;
35
+ return { repoUrl, repo };
36
+ }
37
+ function cleanUrl(url) {
38
+ if (!url) return null;
39
+ return url.replace(/^git\+/, "").replace(/^git:\/\//, "https://").replace(/\.git$/, "");
40
+ }
41
+ function pickLicense(value) {
42
+ if (!value) return null;
43
+ if (typeof value === "string") return value;
44
+ if (typeof value === "object" && "type" in value) return String(value.type);
45
+ return null;
46
+ }
47
+ function toDate(value) {
48
+ if (typeof value !== "string") return null;
49
+ const ms = Date.parse(value);
50
+ return Number.isNaN(ms) ? null : new Date(ms);
51
+ }
52
+ function parseNpmRegistry(json) {
53
+ const latest = json?.["dist-tags"]?.latest ?? null;
54
+ const latestManifest = latest ? json?.versions?.[latest] ?? {} : {};
55
+ const time = json?.time ?? {};
56
+ const repository = json?.repository ?? latestManifest?.repository;
57
+ const homepage = json?.homepage ?? latestManifest?.homepage ?? null;
58
+ const { repoUrl, repo } = normalizeRepoUrl(repository, homepage);
59
+ const deprecated = Boolean(latestManifest?.deprecated ?? json?.deprecated);
60
+ const maintainers = Array.isArray(json?.maintainers) ? json.maintainers.length : null;
61
+ const name = json?.name ?? "";
62
+ return {
63
+ name,
64
+ description: json?.description ?? latestManifest?.description ?? null,
65
+ latestVersion: latest,
66
+ license: pickLicense(json?.license ?? latestManifest?.license),
67
+ homepage,
68
+ repo,
69
+ repoUrl,
70
+ firstPublishedAt: toDate(time?.created),
71
+ lastReleaseAt: toDate(latest ? time?.[latest] : null) ?? toDate(time?.modified),
72
+ deprecated,
73
+ maintainersCount: maintainers,
74
+ readme: typeof json?.readme === "string" ? json.readme : null,
75
+ keywords: parseKeywords(json?.keywords ?? latestManifest?.keywords),
76
+ hasTypes: detectTypes(name, latestManifest),
77
+ hasTestScript: detectTestScript(latestManifest),
78
+ directDependenciesCount: countDeps(latestManifest?.dependencies),
79
+ hasProvenance: detectProvenance(latestManifest),
80
+ hasInstallScripts: detectInstallScripts(latestManifest),
81
+ hasBrowserField: latestManifest?.browser != null,
82
+ peerDependencies: parseDepMap(latestManifest?.peerDependencies),
83
+ peerDependenciesMeta: parsePeerMeta(latestManifest?.peerDependenciesMeta),
84
+ engines: parseDepMap(latestManifest?.engines),
85
+ versionTimeline: parseVersionTimeline(json)
86
+ };
87
+ }
88
+ function parseDepMap(value) {
89
+ if (!value || typeof value !== "object") return null;
90
+ const out = {};
91
+ for (const [name, range] of Object.entries(value)) {
92
+ if (typeof range === "string" && range.trim() !== "") out[name] = range;
93
+ }
94
+ return Object.keys(out).length ? out : null;
95
+ }
96
+ function parsePeerMeta(value) {
97
+ if (!value || typeof value !== "object") return null;
98
+ const out = {};
99
+ for (const [name, meta] of Object.entries(value)) {
100
+ if (meta && typeof meta === "object" && "optional" in meta) {
101
+ out[name] = { optional: Boolean(meta.optional) };
102
+ }
103
+ }
104
+ return Object.keys(out).length ? out : null;
105
+ }
106
+ function detectInstallScripts(manifest) {
107
+ const scripts = manifest?.scripts;
108
+ if (!scripts || typeof scripts !== "object") return false;
109
+ return ["preinstall", "install", "postinstall"].some(
110
+ (hook) => typeof scripts[hook] === "string" && scripts[hook].trim() !== ""
111
+ );
112
+ }
113
+ function parseVersionTimeline(json) {
114
+ const versions = json?.versions;
115
+ if (!versions || typeof versions !== "object") return [];
116
+ const time = json?.time ?? {};
117
+ return Object.keys(versions).map((version) => ({
118
+ version,
119
+ publishedAt: toDate(time?.[version]),
120
+ // Already in this document — no second fetch, no per-version round trip.
121
+ peerDependencies: parseDepMap(versions[version]?.peerDependencies),
122
+ engines: parseDepMap(versions[version]?.engines)
123
+ })).sort((a, b) => (b.publishedAt?.getTime() ?? 0) - (a.publishedAt?.getTime() ?? 0));
124
+ }
125
+ function parseKeywords(value) {
126
+ if (!Array.isArray(value)) return [];
127
+ return value.filter((k) => typeof k === "string");
128
+ }
129
+ function detectTypes(name, manifest) {
130
+ if (typeof manifest?.types === "string" || typeof manifest?.typings === "string") return true;
131
+ if (name.startsWith("@types/")) return true;
132
+ const exportsField = manifest?.exports;
133
+ if (exportsField && typeof exportsField === "object") {
134
+ const serialized = JSON.stringify(exportsField);
135
+ if (serialized.includes('"types"')) return true;
136
+ }
137
+ return false;
138
+ }
139
+ function detectTestScript(manifest) {
140
+ const test = manifest?.scripts?.test;
141
+ if (typeof test !== "string" || test.trim() === "") return false;
142
+ return !/no test specified/i.test(test);
143
+ }
144
+ function countDeps(deps) {
145
+ if (!deps || typeof deps !== "object") return 0;
146
+ return Object.keys(deps).length;
147
+ }
148
+ function detectProvenance(manifest) {
149
+ return Boolean(manifest?.dist?.attestations);
150
+ }
151
+ async function fetchNpmRegistry(name, fetchImpl) {
152
+ const url = `https://${HOST}/${encodeNpmName(name)}`;
153
+ const { data } = await httpGetJson(url, {
154
+ host: HOST,
155
+ ttlMs: CACHE_TTL.npmRegistry,
156
+ fetchImpl
157
+ });
158
+ return parseNpmRegistry(data);
159
+ }
160
+ async function fetchNpmCompatAtVersion(name, version, fetchImpl) {
161
+ const url = `https://${HOST}/${encodeNpmName(name)}`;
162
+ try {
163
+ const { data } = await httpGetJson(url, {
164
+ host: HOST,
165
+ ttlMs: CACHE_TTL.npmRegistry,
166
+ fetchImpl
167
+ });
168
+ const latest = data?.["dist-tags"]?.latest ?? null;
169
+ const wanted = version ? data?.versions?.[version] ? version : null : latest && data?.versions?.[latest] ? latest : null;
170
+ if (!wanted) return null;
171
+ const manifest = data.versions[wanted] ?? {};
172
+ return {
173
+ version: wanted,
174
+ peerDependencies: parseDepMap(manifest.peerDependencies),
175
+ peerDependenciesMeta: parsePeerMeta(manifest.peerDependenciesMeta),
176
+ engines: parseDepMap(manifest.engines)
177
+ };
178
+ } catch {
179
+ return null;
180
+ }
181
+ }
182
+ async function npmVersionExists(name, version, fetchImpl) {
183
+ const url = `https://${HOST}/${encodeNpmName(name)}`;
184
+ try {
185
+ const { data } = await httpGetJson(url, {
186
+ host: HOST,
187
+ ttlMs: CACHE_TTL.npmRegistry,
188
+ fetchImpl
189
+ });
190
+ if (!data?.versions || typeof data.versions !== "object") return null;
191
+ return Object.prototype.hasOwnProperty.call(data.versions, version);
192
+ } catch {
193
+ return null;
194
+ }
195
+ }
196
+ async function npmPackageExists(name, fetchImpl) {
197
+ const url = `https://${HOST}/${encodeNpmName(name)}`;
198
+ try {
199
+ const { status } = await httpGetJson(url, {
200
+ host: HOST,
201
+ ttlMs: 0,
202
+ retries: 1,
203
+ fetchImpl
204
+ });
205
+ return status === 200;
206
+ } catch (err) {
207
+ if (err && typeof err === "object" && "status" in err && err.status === 404) {
208
+ return false;
209
+ }
210
+ throw err;
211
+ }
212
+ }
213
+
214
+ export {
215
+ encodeNpmName,
216
+ fetchNpmRegistry,
217
+ fetchNpmCompatAtVersion,
218
+ npmVersionExists,
219
+ npmPackageExists
220
+ };