lurqrun 0.1.6 → 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.
- package/README.md +311 -139
- package/dist/auditHandler-VWCXSDVO.js +24 -0
- package/dist/autopilotInit-Q62MX5M6.js +178 -0
- package/dist/bin/lurq.js +3255 -23319
- package/dist/browserAuth-J7APSD4P.js +96 -0
- package/dist/cache-AEAKCV4I.js +12 -0
- package/dist/check-2JTQDQA6.js +2613 -0
- package/dist/check-PQSQ2MMA.js +192 -0
- package/dist/checkUpgrade-5YW77OBL.js +24 -0
- package/dist/chunk-2GAYNIHG.js +40 -0
- package/dist/chunk-2O6Z37IT.js +423 -0
- package/dist/chunk-2WD4QAH4.js +116 -0
- package/dist/chunk-3676XOBU.js +2235 -0
- package/dist/chunk-3D2MPGOQ.js +181 -0
- package/dist/chunk-3GHJR7XR.js +2049 -0
- package/dist/chunk-4ESO33J6.js +34 -0
- package/dist/chunk-4JHDSVIN.js +1229 -0
- package/dist/chunk-4KCPOMG6.js +68 -0
- package/dist/chunk-53SG6XWA.js +141 -0
- package/dist/chunk-5ABNDB3I.js +37 -0
- package/dist/chunk-5ALIJFDA.js +114 -0
- package/dist/chunk-63MUJNZL.js +318 -0
- package/dist/chunk-64ZF7KO4.js +1571 -0
- package/dist/chunk-6DM6UQFD.js +318 -0
- package/dist/chunk-6EQ3ARXA.js +304 -0
- package/dist/chunk-6L67QMCP.js +92 -0
- package/dist/chunk-72Y2FDVS.js +172 -0
- package/dist/chunk-A3TYI2TF.js +288 -0
- package/dist/chunk-B2UUYRBX.js +536 -0
- package/dist/chunk-BJT2LHAR.js +320 -0
- package/dist/chunk-BM3LF5T6.js +132 -0
- package/dist/chunk-BN3NM47Q.js +214 -0
- package/dist/chunk-BUALU27S.js +123 -0
- package/dist/chunk-C6GLE626.js +160 -0
- package/dist/chunk-D3K6IZVR.js +12845 -0
- package/dist/chunk-D3VTZS7V.js +222 -0
- package/dist/chunk-DM37MTOO.js +636 -0
- package/dist/chunk-DONTW3NE.js +171 -0
- package/dist/chunk-DSROTZ3Z.js +38 -0
- package/dist/chunk-ELGCAM7P.js +184 -0
- package/dist/chunk-EQCXENKZ.js +130 -0
- package/dist/chunk-EYAKM6YN.js +96 -0
- package/dist/chunk-FDFPMBCA.js +112 -0
- package/dist/chunk-FVYFV5HA.js +154 -0
- package/dist/chunk-GE37NVLN.js +15 -0
- package/dist/chunk-GM5Y555O.js +143 -0
- package/dist/chunk-GRJXQBQZ.js +793 -0
- package/dist/chunk-HWFX4BC4.js +177 -0
- package/dist/chunk-I3M2KJXB.js +56 -0
- package/dist/chunk-IFNONGRQ.js +603 -0
- package/dist/chunk-J3U2CPSK.js +136 -0
- package/dist/chunk-J6XQ7OPZ.js +74 -0
- package/dist/chunk-KMV4Y6R3.js +127 -0
- package/dist/chunk-KP5ZDDPE.js +340 -0
- package/dist/chunk-KYKSZ3XZ.js +202 -0
- package/dist/chunk-LEGPB7DO.js +81 -0
- package/dist/chunk-LUAKDHLZ.js +40 -0
- package/dist/chunk-MHUEVBVO.js +35 -0
- package/dist/chunk-MYGSLK44.js +37 -0
- package/dist/chunk-NEZNAPPN.js +41 -0
- package/dist/chunk-NPVN2THM.js +197 -0
- package/dist/chunk-NYZU5NCW.js +23 -0
- package/dist/chunk-O4KHCV6I.js +320 -0
- package/dist/chunk-ONDVTXUO.js +240 -0
- package/dist/chunk-OTJFHESY.js +176 -0
- package/dist/chunk-P6MIKSPY.js +243 -0
- package/dist/chunk-Q5VPF4WI.js +26 -0
- package/dist/chunk-QCRBX3LV.js +165 -0
- package/dist/chunk-QKGYDMWB.js +7409 -0
- package/dist/chunk-QSL6QN5X.js +115 -0
- package/dist/chunk-QUIMQ7YL.js +73 -0
- package/dist/chunk-RG3YLU6E.js +49 -0
- package/dist/chunk-SHCEBP3J.js +107 -0
- package/dist/chunk-SHZFOSXC.js +462 -0
- package/dist/chunk-SOXFMMXC.js +151 -0
- package/dist/chunk-TDTYV6QI.js +119 -0
- package/dist/chunk-TNTXWSYA.js +19 -0
- package/dist/chunk-TUXQ32WE.js +2251 -0
- package/dist/chunk-VGCDRK3S.js +37 -0
- package/dist/chunk-VLRHFMGJ.js +58 -0
- package/dist/chunk-WHX2ZFCG.js +4048 -0
- package/dist/chunk-X4W64MHU.js +2005 -0
- package/dist/chunk-XBQA4I36.js +92 -0
- package/dist/chunk-XGOV6KV4.js +413 -0
- package/dist/chunk-XIFQIFSZ.js +940 -0
- package/dist/chunk-XLXPVN3Y.js +15393 -0
- package/dist/chunk-ZJMLQ37G.js +90 -0
- package/dist/client-MU4EUDZV.js +15 -0
- package/dist/commands-UOOTMBKA.js +1023 -0
- package/dist/compat-Q5DVPITN.js +201 -0
- package/dist/constants-DJFOFZ44.js +24 -0
- package/dist/dashboardIssue-KBKLQMGC.js +274 -0
- package/dist/diff-I4SNUHU3.js +13 -0
- package/dist/dist-4XXIXHHZ.js +12945 -0
- package/dist/domains-VRT4BRVZ.js +14 -0
- package/dist/e2b-FVPHDULZ.js +172 -0
- package/dist/env-UN6KGZ7S.js +15 -0
- package/dist/envCheck-KUPTORFQ.js +71 -0
- package/dist/extract-6WG265BL.js +455 -0
- package/dist/fetch-PJ3SC32M.js +22 -0
- package/dist/firstTouch-COJCMOB3.js +55 -0
- package/dist/fix-3EDWNKW3.js +220 -0
- package/dist/handlers-4Q37WIFT.js +55 -0
- package/dist/hook-NA66XJLC.js +412 -0
- package/dist/http-25GJ6SKK.js +6928 -0
- package/dist/ingestQueue-FSVJC3AA.js +37 -0
- package/dist/install-G2HHXYJ2.js +20 -0
- package/dist/installSkill-5TIMYIJZ.js +70 -0
- package/dist/inventory-5AWSLJYU.js +31 -0
- package/dist/local-XPZMRH5R.js +13 -0
- package/dist/manifest-ENMIC54B.js +13 -0
- package/dist/mcp-PENLL2PK.js +500 -0
- package/dist/mcpConfig-3LYPRY5Q.js +80 -0
- package/dist/mcpHandlers-PO7GENA7.js +22 -0
- package/dist/mcpScan-ULP626TQ.js +1735 -0
- package/dist/mcpScanWorkflow-27O44FOE.js +98 -0
- package/dist/mcpStack-ZNYIFXZ5.js +20 -0
- package/dist/model-ASMZWLM7.js +214 -0
- package/dist/packages-RWF2LXST.js +40 -0
- package/dist/plan-SDILIDZT.js +465 -0
- package/dist/planView-ZAKRTGVS.js +82 -0
- package/dist/policy-JAGNMQJI.js +115 -0
- package/dist/probe-3IK646WN.js +610 -0
- package/dist/publicUpgrades-WTBGLDIK.js +42 -0
- package/dist/references-I6Y4BSRR.js +16 -0
- package/dist/release-7IU2R4YG.js +128 -0
- package/dist/remote-FN6225AH.js +42 -0
- package/dist/rename-OS6JYBZQ.js +204 -0
- package/dist/reportRuns-O4X7ZFTX.js +77 -0
- package/dist/safeFetch-COERXGFN.js +19 -0
- package/dist/sandbox-SAPSRKEI.js +39 -0
- package/dist/sarif-WLVJFJ7U.js +125 -0
- package/dist/server-OLTY3NYT.js +59 -0
- package/dist/surface-7MHE3RL7.js +143 -0
- package/dist/surface-JS2XU3U3.js +38 -0
- package/dist/surfaceHandlers-4B6TMZ34.js +20 -0
- package/dist/typecheck-NGOKNAJY.js +282 -0
- package/dist/types-M5JP2W3D.js +10 -0
- package/dist/uninstall-I2IJP5JZ.js +200 -0
- package/dist/upgrade-FS26DJGG.js +650 -0
- package/dist/upgradePlan-ZS5IOVMZ.js +181 -0
- package/dist/upkeepHandler-VFGYXJKB.js +13 -0
- package/dist/userConfig-ICASHI47.js +20 -0
- package/dist/watch-OCNEUXG6.js +204 -0
- package/package.json +26 -20
- package/templates/agent-rules.md +4 -4
- package/templates/skill-instructions.md +35 -17
- package/dist/bin/lurq.js.map +0 -1
- package/dist/index.d.ts +0 -805
- package/dist/index.js +0 -23570
- package/dist/index.js.map +0 -1
- package/drizzle/0000_confused_fabian_cortez.sql +0 -54
- package/drizzle/0001_aspiring_timeslip.sql +0 -15
- package/drizzle/0002_lyrical_lila_cheney.sql +0 -14
- package/drizzle/0003_violet_giant_girl.sql +0 -14
- package/drizzle/0004_slim_valeria_richards.sql +0 -15
- package/drizzle/0005_petite_luke_cage.sql +0 -12
- package/drizzle/0006_calm_nighthawk.sql +0 -3
- package/drizzle/0007_slimy_naoko.sql +0 -1
- package/drizzle/0008_peaceful_tigra.sql +0 -1
- package/drizzle/0009_smooth_harrier.sql +0 -10
- package/drizzle/0010_curved_amphibian.sql +0 -2
- package/drizzle/0011_compat_provenance_closures.sql +0 -11
- package/drizzle/0012_api_surfaces.sql +0 -9
- package/drizzle/0013_nice_thanos.sql +0 -1
- package/drizzle/0014_luxuriant_malcolm_colcord.sql +0 -10
- package/drizzle/0015_past_fat_cobra.sql +0 -11
- package/drizzle/0016_futuristic_junta.sql +0 -50
- package/drizzle/0017_absent_grandmaster.sql +0 -20
- package/drizzle/0018_rainy_proemial_gods.sql +0 -1
- package/drizzle/0019_dashing_korvac.sql +0 -11
- package/drizzle/0020_normal_vulture.sql +0 -3
- package/drizzle/0021_dazzling_blue_shield.sql +0 -17
- package/drizzle/0022_massive_ghost_rider.sql +0 -24
- package/drizzle/0023_next_shatterstar.sql +0 -1
- package/drizzle/0024_dusty_maelstrom.sql +0 -15
- package/drizzle/0025_gifted_harpoon.sql +0 -5
- package/drizzle/0026_awesome_mordo.sql +0 -1
- package/drizzle/0027_charming_ulik.sql +0 -2
- package/drizzle/0028_romantic_loners.sql +0 -2
- package/drizzle/0029_busy_korvac.sql +0 -16
- package/drizzle/0030_steady_mathemanic.sql +0 -6
- package/drizzle/0031_redundant_maginty.sql +0 -2
- package/drizzle/0032_stack_resolutions.sql +0 -14
- package/drizzle/0033_graceful_tyger_tiger.sql +0 -3
- package/drizzle/0034_uneven_thunderbird.sql +0 -1
- package/drizzle/0035_api_key_scopes.sql +0 -1
- package/drizzle/0036_policy_audit.sql +0 -21
- package/drizzle/0037_subscription_seats.sql +0 -1
- package/drizzle/0038_symbol_offsets.sql +0 -2
- package/drizzle/0039_mcp_runtime_scans.sql +0 -80
- package/drizzle/0040_subscription_overage_and_interval.sql +0 -4
- package/drizzle/0041_account_email.sql +0 -38
- package/drizzle/0042_alert_channels.sql +0 -21
- package/drizzle/meta/0000_snapshot.json +0 -370
- package/drizzle/meta/0001_snapshot.json +0 -482
- package/drizzle/meta/0002_snapshot.json +0 -575
- package/drizzle/meta/0003_snapshot.json +0 -667
- package/drizzle/meta/0004_snapshot.json +0 -769
- package/drizzle/meta/0005_snapshot.json +0 -864
- package/drizzle/meta/0006_snapshot.json +0 -882
- package/drizzle/meta/0007_snapshot.json +0 -876
- package/drizzle/meta/0008_snapshot.json +0 -882
- package/drizzle/meta/0009_snapshot.json +0 -948
- package/drizzle/meta/0010_snapshot.json +0 -969
- package/drizzle/meta/0011_snapshot.json +0 -1049
- package/drizzle/meta/0012_snapshot.json +0 -1115
- package/drizzle/meta/0013_snapshot.json +0 -1121
- package/drizzle/meta/0014_snapshot.json +0 -1190
- package/drizzle/meta/0015_snapshot.json +0 -1280
- package/drizzle/meta/0016_snapshot.json +0 -1683
- package/drizzle/meta/0017_snapshot.json +0 -1834
- package/drizzle/meta/0018_snapshot.json +0 -1834
- package/drizzle/meta/0019_snapshot.json +0 -1909
- package/drizzle/meta/0020_snapshot.json +0 -1921
- package/drizzle/meta/0021_snapshot.json +0 -2045
- package/drizzle/meta/0022_snapshot.json +0 -2246
- package/drizzle/meta/0023_snapshot.json +0 -2252
- package/drizzle/meta/0024_snapshot.json +0 -2375
- package/drizzle/meta/0025_snapshot.json +0 -2407
- package/drizzle/meta/0026_snapshot.json +0 -2413
- package/drizzle/meta/0027_snapshot.json +0 -2425
- package/drizzle/meta/0028_snapshot.json +0 -2438
- package/drizzle/meta/0029_snapshot.json +0 -2546
- package/drizzle/meta/0030_snapshot.json +0 -2586
- package/drizzle/meta/0031_snapshot.json +0 -2598
- package/drizzle/meta/0032_snapshot.json +0 -2699
- package/drizzle/meta/0033_snapshot.json +0 -2712
- package/drizzle/meta/0034_snapshot.json +0 -2719
- package/drizzle/meta/0035_snapshot.json +0 -2726
- package/drizzle/meta/0036_snapshot.json +0 -2876
- package/drizzle/meta/0037_snapshot.json +0 -2883
- package/drizzle/meta/0038_snapshot.json +0 -2895
- package/drizzle/meta/0039_snapshot.json +0 -3501
- package/drizzle/meta/0040_snapshot.json +0 -3527
- package/drizzle/meta/0041_snapshot.json +0 -3824
- package/drizzle/meta/0042_snapshot.json +0 -3960
- package/drizzle/meta/_journal.json +0 -307
- package/src/data/seed.json +0 -253
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { createRequire as __lurqCreateRequire } from 'node:module'; const require = __lurqCreateRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
getSandbox
|
|
4
|
+
} from "./chunk-RG3YLU6E.js";
|
|
5
|
+
import "./chunk-C6GLE626.js";
|
|
6
|
+
import "./chunk-GE37NVLN.js";
|
|
7
|
+
import {
|
|
8
|
+
getStackResolution,
|
|
9
|
+
recordStackResolution,
|
|
10
|
+
resolveSet,
|
|
11
|
+
stackKey
|
|
12
|
+
} from "./chunk-2WD4QAH4.js";
|
|
13
|
+
import {
|
|
14
|
+
bumpCompatVerifyAttempt,
|
|
15
|
+
canonicalPair,
|
|
16
|
+
deleteCompatVerify,
|
|
17
|
+
getPendingCompatVerify,
|
|
18
|
+
pairKey,
|
|
19
|
+
upsertCompatEdge
|
|
20
|
+
} from "./chunk-EYAKM6YN.js";
|
|
21
|
+
import {
|
|
22
|
+
getPackageByName,
|
|
23
|
+
getTopPackageNames
|
|
24
|
+
} from "./chunk-NPVN2THM.js";
|
|
25
|
+
import "./chunk-VLRHFMGJ.js";
|
|
26
|
+
import "./chunk-4JHDSVIN.js";
|
|
27
|
+
import "./chunk-GRJXQBQZ.js";
|
|
28
|
+
import "./chunk-WHX2ZFCG.js";
|
|
29
|
+
import {
|
|
30
|
+
logger
|
|
31
|
+
} from "./chunk-MYGSLK44.js";
|
|
32
|
+
import "./chunk-72Y2FDVS.js";
|
|
33
|
+
import {
|
|
34
|
+
init_esm_shims
|
|
35
|
+
} from "./chunk-I3M2KJXB.js";
|
|
36
|
+
|
|
37
|
+
// src/pipeline/compat.ts
|
|
38
|
+
init_esm_shims();
|
|
39
|
+
function pairwiseEdges(resolved, success) {
|
|
40
|
+
const edges = [];
|
|
41
|
+
if (success) {
|
|
42
|
+
for (let i = 0; i < resolved.length; i++) {
|
|
43
|
+
for (let j = i + 1; j < resolved.length; j++) {
|
|
44
|
+
edges.push({
|
|
45
|
+
a: resolved[i].name,
|
|
46
|
+
aVersion: resolved[i].version,
|
|
47
|
+
b: resolved[j].name,
|
|
48
|
+
bVersion: resolved[j].version,
|
|
49
|
+
status: "compatible"
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
} else if (resolved.length === 2) {
|
|
54
|
+
edges.push({
|
|
55
|
+
a: resolved[0].name,
|
|
56
|
+
aVersion: resolved[0].version,
|
|
57
|
+
b: resolved[1].name,
|
|
58
|
+
bVersion: resolved[1].version,
|
|
59
|
+
status: "conflict"
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
return edges;
|
|
63
|
+
}
|
|
64
|
+
function deriveCompatEdges(resolved, result) {
|
|
65
|
+
return pairwiseEdges(resolved, result.installed && result.loaded.every((l) => l.loaded === true));
|
|
66
|
+
}
|
|
67
|
+
async function verifyCompatibility(db, packages, opts = {}) {
|
|
68
|
+
const resolved = await Promise.all(
|
|
69
|
+
packages.map(async (name) => ({
|
|
70
|
+
name,
|
|
71
|
+
version: (await getPackageByName(db, name))?.latestVersion ?? "latest"
|
|
72
|
+
}))
|
|
73
|
+
);
|
|
74
|
+
const result = await (await getSandbox()).verifySet(
|
|
75
|
+
resolved.map((r) => ({ name: r.name, version: r.version === "latest" ? null : r.version })),
|
|
76
|
+
{ allowScripts: opts.allowScripts }
|
|
77
|
+
);
|
|
78
|
+
const edges = deriveCompatEdges(resolved, result);
|
|
79
|
+
await persistCompatEdges(db, edges, "verified", result.driver);
|
|
80
|
+
const failed = !result.installed || !result.loaded.every((l) => l.loaded === true);
|
|
81
|
+
return { result, edges, unattributedConflict: failed && edges.length === 0 };
|
|
82
|
+
}
|
|
83
|
+
async function persistCompatEdges(db, edges, compatibleProvenance, driver) {
|
|
84
|
+
const now = /* @__PURE__ */ new Date();
|
|
85
|
+
for (const e of edges) {
|
|
86
|
+
const pair = canonicalPair(
|
|
87
|
+
{ name: e.a, version: e.aVersion },
|
|
88
|
+
{ name: e.b, version: e.bVersion }
|
|
89
|
+
);
|
|
90
|
+
await upsertCompatEdge(db, {
|
|
91
|
+
...pair,
|
|
92
|
+
status: e.status,
|
|
93
|
+
provenance: e.status === "conflict" ? "conflict" : compatibleProvenance,
|
|
94
|
+
// Witness accrues for co-resolution evidence (`observed`); ignored otherwise.
|
|
95
|
+
witnessCount: e.status === "compatible" && compatibleProvenance === "observed" ? 1 : 0,
|
|
96
|
+
driver,
|
|
97
|
+
ranAt: now
|
|
98
|
+
}).catch(() => {
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
async function resolveVerifyCompatibility(db, packages) {
|
|
103
|
+
const resolved = await Promise.all(
|
|
104
|
+
packages.map(async (name) => ({
|
|
105
|
+
name,
|
|
106
|
+
version: (await getPackageByName(db, name))?.latestVersion ?? "latest"
|
|
107
|
+
}))
|
|
108
|
+
);
|
|
109
|
+
const res = await resolveSet(
|
|
110
|
+
resolved.map((r) => ({ name: r.name, version: r.version === "latest" ? null : r.version }))
|
|
111
|
+
);
|
|
112
|
+
const pinned = resolved.filter((r) => r.version !== "latest");
|
|
113
|
+
if (pinned.length === resolved.length && pinned.length >= 2) {
|
|
114
|
+
await recordStackResolution(db, {
|
|
115
|
+
members: pinned.map((r) => ({ name: r.name, version: r.version })),
|
|
116
|
+
resolved: res.resolved,
|
|
117
|
+
reason: res.reason,
|
|
118
|
+
detail: res.detail ?? null
|
|
119
|
+
}).catch((err) => logger.warn(`compat: caching resolution failed: ${String(err)}`));
|
|
120
|
+
}
|
|
121
|
+
return { edges: pairwiseEdges(resolved, res.resolved), resolved: res.resolved };
|
|
122
|
+
}
|
|
123
|
+
async function alreadyResolved(db, names) {
|
|
124
|
+
const members = [];
|
|
125
|
+
for (const name of [...new Set(names)]) {
|
|
126
|
+
const version = (await getPackageByName(db, name))?.latestVersion;
|
|
127
|
+
if (!version) return false;
|
|
128
|
+
members.push({ name, version });
|
|
129
|
+
}
|
|
130
|
+
if (members.length < 2) return true;
|
|
131
|
+
return await getStackResolution(db, stackKey(members)).catch(() => null) !== null;
|
|
132
|
+
}
|
|
133
|
+
async function runBackfill(db, opts, runner, label) {
|
|
134
|
+
const topN = opts.topN ?? 50;
|
|
135
|
+
const batchSize = Math.max(2, opts.batchSize ?? 5);
|
|
136
|
+
const names = await getTopPackageNames(db, topN);
|
|
137
|
+
let verified = 0;
|
|
138
|
+
let batches = 0;
|
|
139
|
+
let skipped = 0;
|
|
140
|
+
for (let i = 0; i < names.length; i += batchSize) {
|
|
141
|
+
const batch = names.slice(i, i + batchSize);
|
|
142
|
+
if (batch.length < 2) continue;
|
|
143
|
+
if (await alreadyResolved(db, batch)) {
|
|
144
|
+
skipped++;
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
logger.info(`${label}: ${batch.join(", ")}`);
|
|
148
|
+
const { edges } = await runner(db, batch).catch((err) => {
|
|
149
|
+
logger.warn(`${label} batch failed (${batch.join(", ")}): ${String(err)}`);
|
|
150
|
+
return { edges: [] };
|
|
151
|
+
});
|
|
152
|
+
verified += edges.length;
|
|
153
|
+
batches++;
|
|
154
|
+
}
|
|
155
|
+
logger.info(`${label}: ${verified} edges across ${batches} runs, ${skipped} batches skipped`);
|
|
156
|
+
return { batches, verified, skipped };
|
|
157
|
+
}
|
|
158
|
+
async function backfillVerify(db, opts = {}) {
|
|
159
|
+
return runBackfill(db, opts, verifyCompatibility, "backfill(sandbox)");
|
|
160
|
+
}
|
|
161
|
+
async function resolveBackfill(db, opts = {}) {
|
|
162
|
+
return runBackfill(db, opts, resolveVerifyCompatibility, "backfill(resolve)");
|
|
163
|
+
}
|
|
164
|
+
var MAX_COMPAT_VERIFY_ATTEMPTS = 3;
|
|
165
|
+
async function drainCompatVerifyQueue(db, opts = {}) {
|
|
166
|
+
const limit = Math.max(1, opts.limit ?? 10);
|
|
167
|
+
const pending = await getPendingCompatVerify(db, limit);
|
|
168
|
+
let verified = 0;
|
|
169
|
+
let dropped = 0;
|
|
170
|
+
for (const req of pending) {
|
|
171
|
+
const names = req.packages;
|
|
172
|
+
if (await alreadyResolved(db, names)) {
|
|
173
|
+
await deleteCompatVerify(db, req.id);
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
try {
|
|
177
|
+
const { edges } = await verifyCompatibility(db, names, {});
|
|
178
|
+
verified += edges.length;
|
|
179
|
+
await deleteCompatVerify(db, req.id);
|
|
180
|
+
} catch (err) {
|
|
181
|
+
logger.warn(`compat-verify drain failed for ${names.join(", ")}: ${String(err)}`);
|
|
182
|
+
const attempts = await bumpCompatVerifyAttempt(db, req.id);
|
|
183
|
+
if (attempts >= MAX_COMPAT_VERIFY_ATTEMPTS) {
|
|
184
|
+
await deleteCompatVerify(db, req.id);
|
|
185
|
+
dropped++;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
logger.info(
|
|
190
|
+
`compat-verify(sandbox): ${verified} edge(s) from ${pending.length} queued set(s), ${dropped} dropped`
|
|
191
|
+
);
|
|
192
|
+
return { processed: pending.length, verified, dropped };
|
|
193
|
+
}
|
|
194
|
+
export {
|
|
195
|
+
backfillVerify,
|
|
196
|
+
deriveCompatEdges,
|
|
197
|
+
drainCompatVerifyQueue,
|
|
198
|
+
pairKey,
|
|
199
|
+
resolveBackfill,
|
|
200
|
+
verifyCompatibility
|
|
201
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { createRequire as __lurqCreateRequire } from 'node:module'; const require = __lurqCreateRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
API_KEY_PREFIX,
|
|
4
|
+
CACHE_TTL,
|
|
5
|
+
DEFAULT_ENDPOINT,
|
|
6
|
+
EMBEDDING_DIM,
|
|
7
|
+
KEYS_URL,
|
|
8
|
+
PACKAGE_NAME,
|
|
9
|
+
SERVER_NAME,
|
|
10
|
+
STALENESS_DAYS,
|
|
11
|
+
VERSION
|
|
12
|
+
} from "./chunk-72Y2FDVS.js";
|
|
13
|
+
import "./chunk-I3M2KJXB.js";
|
|
14
|
+
export {
|
|
15
|
+
API_KEY_PREFIX,
|
|
16
|
+
CACHE_TTL,
|
|
17
|
+
DEFAULT_ENDPOINT,
|
|
18
|
+
EMBEDDING_DIM,
|
|
19
|
+
KEYS_URL,
|
|
20
|
+
PACKAGE_NAME,
|
|
21
|
+
SERVER_NAME,
|
|
22
|
+
STALENESS_DAYS,
|
|
23
|
+
VERSION
|
|
24
|
+
};
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import { createRequire as __lurqCreateRequire } from 'node:module'; const require = __lurqCreateRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
init_esm_shims
|
|
4
|
+
} from "./chunk-I3M2KJXB.js";
|
|
5
|
+
|
|
6
|
+
// src/github/dashboardIssue.ts
|
|
7
|
+
init_esm_shims();
|
|
8
|
+
import { createHash } from "crypto";
|
|
9
|
+
var DASHBOARD_MARKER = "<!-- lurq:dashboard -->";
|
|
10
|
+
var DASHBOARD_LABEL = "lurq";
|
|
11
|
+
var DASHBOARD_TITLE = "lurq dashboard";
|
|
12
|
+
var MAX_ALERTED_KEYS = 200;
|
|
13
|
+
var MAX_ROWS = 25;
|
|
14
|
+
var sha = (s) => createHash("sha256").update(s).digest("hex");
|
|
15
|
+
function md(s, max = 200) {
|
|
16
|
+
const flat = s.replace(/\s+/g, " ").trim();
|
|
17
|
+
const clipped = flat.length > max ? `${flat.slice(0, max - 1)}\u2026` : flat;
|
|
18
|
+
return clipped.replace(/[\\`*_[\]<>|~]/g, (c) => `\\${c}`).replace(/@/g, "@\u200B").replace(/#(?=\d)/g, "#\u200B").replace(/:\/\//g, ":\u200B//");
|
|
19
|
+
}
|
|
20
|
+
var code = (s) => `\`${s.replace(/[`\r\n]/g, "").slice(0, 120)}\``;
|
|
21
|
+
var RANK = { critical: 0, high: 1, moderate: 2, low: 3, info: 4 };
|
|
22
|
+
function mcpSection(scan, urgent) {
|
|
23
|
+
const lines = ["### MCP servers", ""];
|
|
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
|
+
);
|
|
30
|
+
for (const s of scan.servers.slice(0, MAX_ROWS)) {
|
|
31
|
+
const f = s.analysis?.findings.filter((x) => RANK[x.severity] <= RANK.moderate) ?? [];
|
|
32
|
+
const worst = f.sort((a, b) => RANK[a.severity] - RANK[b.severity])[0]?.severity;
|
|
33
|
+
lines.push(
|
|
34
|
+
`| ${code(s.alias)} | ${s.status.replace(/_/g, " ")} | ${s.analysis?.stats.tools ?? "\u2014"} | ${s.analysis?.stats.writes ?? "\u2014"} | ${f.length ? `${f.length}${worst ? ` (worst ${worst})` : ""}` : "\u2014"} |`
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
lines.push("");
|
|
38
|
+
const account = new Map(
|
|
39
|
+
(scan.account?.results ?? []).filter((r) => r.since).map((r) => [r.alias, r.since])
|
|
40
|
+
);
|
|
41
|
+
const changes = scan.servers.flatMap((s) => {
|
|
42
|
+
const acc = account.get(s.alias);
|
|
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
|
+
];
|
|
53
|
+
const d = s.sinceLastScan;
|
|
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
|
+
] : [];
|
|
63
|
+
});
|
|
64
|
+
if (changes.length) {
|
|
65
|
+
lines.push("**Changed since the last scan**", "");
|
|
66
|
+
for (const c of changes.sort((a, b) => RANK[a.severity] - RANK[b.severity])) {
|
|
67
|
+
const line = `- **${c.severity}** ${code(c.alias)}: ${md(c.summary, 300)}`;
|
|
68
|
+
lines.push(line);
|
|
69
|
+
if (c.rug || c.severity === "critical")
|
|
70
|
+
urgent.push({ key: sha(`change|${c.key}|${c.summary}`).slice(0, 16), line });
|
|
71
|
+
}
|
|
72
|
+
lines.push("");
|
|
73
|
+
}
|
|
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]);
|
|
83
|
+
if (findings.length) {
|
|
84
|
+
lines.push("**Needs attention**", "");
|
|
85
|
+
for (const f of findings.slice(0, MAX_ROWS)) {
|
|
86
|
+
const line = `- **${f.severity}** ${code(f.alias)}${f.tool ? ` \u203A ${code(f.tool)}` : ""}: ${md(f.detail, 240)}`;
|
|
87
|
+
lines.push(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
|
+
});
|
|
96
|
+
}
|
|
97
|
+
lines.push("");
|
|
98
|
+
}
|
|
99
|
+
const unread = scan.servers.filter((s) => !s.snapshot);
|
|
100
|
+
if (unread.length) {
|
|
101
|
+
lines.push(`<details><summary>${unread.length} server(s) could not be read</summary>`, "");
|
|
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
|
+
);
|
|
106
|
+
lines.push("", "</details>", "");
|
|
107
|
+
}
|
|
108
|
+
return lines;
|
|
109
|
+
}
|
|
110
|
+
function dependencySection(plan, note) {
|
|
111
|
+
const lines = ["### Dependencies", ""];
|
|
112
|
+
if (!plan) return [...lines, note ?? "Not checked on this run.", ""];
|
|
113
|
+
if (!plan.upgrades.length) {
|
|
114
|
+
return [
|
|
115
|
+
...lines,
|
|
116
|
+
`Everything lurq tracks is on its latest release${plan.untracked ? ` (${plan.untracked} not yet indexed)` : ""}.`,
|
|
117
|
+
""
|
|
118
|
+
];
|
|
119
|
+
}
|
|
120
|
+
lines.push("| Package | Upgrade | What it removes | Advisories |", "| --- | --- | --- | --- |");
|
|
121
|
+
const order = { "removes-exports": 0, "arity-changed": 1, unknown: 2, clean: 3 };
|
|
122
|
+
for (const u of [...plan.upgrades].sort((a, b) => order[a.verdict] - order[b.verdict] || b.advisories - a.advisories).slice(0, MAX_ROWS)) {
|
|
123
|
+
const removes = u.verdict === "removes-exports" ? `${u.removed.length} export(s)` : u.verdict === "arity-changed" ? "changed signatures" : u.verdict === "clean" ? "nothing" : "unknown";
|
|
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
|
+
);
|
|
127
|
+
}
|
|
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
|
+
);
|
|
135
|
+
lines.push("");
|
|
136
|
+
return lines;
|
|
137
|
+
}
|
|
138
|
+
function renderDashboardIssue(input) {
|
|
139
|
+
const urgent = [];
|
|
140
|
+
const content = [
|
|
141
|
+
...input.scan ? mcpSection(input.scan, urgent) : ["### MCP servers", "", "Not scanned on this run.", ""],
|
|
142
|
+
...dependencySection(input.plan, input.planNote)
|
|
143
|
+
].join("\n");
|
|
144
|
+
const stamp = `Updated ${input.generatedAt.toISOString().slice(0, 16).replace("T", " ")} UTC${input.runUrl ? ` by [this run](${input.runUrl})` : ""}.`;
|
|
145
|
+
const body = [
|
|
146
|
+
DASHBOARD_MARKER,
|
|
147
|
+
`## ${DASHBOARD_TITLE}`,
|
|
148
|
+
"",
|
|
149
|
+
`${stamp} This issue is edited in place; lurq comments only when something needs a look today. [Open the dashboard](${input.dashboardUrl}).`,
|
|
150
|
+
"",
|
|
151
|
+
content,
|
|
152
|
+
"<sub>Close this issue to stop lurq updating it. Remove `--github-issue` from the workflow to stop creating it.</sub>"
|
|
153
|
+
].join("\n");
|
|
154
|
+
return { title: DASHBOARD_TITLE, body, hash: sha(content).slice(0, 24), urgent };
|
|
155
|
+
}
|
|
156
|
+
var HASH_RE = /<!-- lurq:hash:([0-9a-f]+) -->/;
|
|
157
|
+
var ALERTED_RE = /<!-- lurq:alerted:([A-Za-z0-9,]*) -->/;
|
|
158
|
+
function readMarkers(body) {
|
|
159
|
+
return {
|
|
160
|
+
hash: HASH_RE.exec(body)?.[1] ?? null,
|
|
161
|
+
alerted: (ALERTED_RE.exec(body)?.[1] ?? "").split(",").filter(Boolean)
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
function withMarkers(body, hash, alerted) {
|
|
165
|
+
const keys = alerted.slice(-MAX_ALERTED_KEYS).join(",");
|
|
166
|
+
return body.replace(
|
|
167
|
+
DASHBOARD_MARKER,
|
|
168
|
+
`${DASHBOARD_MARKER}
|
|
169
|
+
<!-- lurq:hash:${hash} -->
|
|
170
|
+
<!-- lurq:alerted:${keys} -->`
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
var GithubIssueError = class extends Error {
|
|
174
|
+
constructor(message, status) {
|
|
175
|
+
super(message);
|
|
176
|
+
this.status = status;
|
|
177
|
+
this.name = "GithubIssueError";
|
|
178
|
+
}
|
|
179
|
+
status;
|
|
180
|
+
};
|
|
181
|
+
function githubEnvFrom(env) {
|
|
182
|
+
const token = env.GITHUB_TOKEN;
|
|
183
|
+
const repo = env.GITHUB_REPOSITORY;
|
|
184
|
+
if (!token || !repo || !/^[\w.-]+\/[\w.-]+$/.test(repo)) return null;
|
|
185
|
+
return {
|
|
186
|
+
token,
|
|
187
|
+
repo,
|
|
188
|
+
apiUrl: (env.GITHUB_API_URL ?? "https://api.github.com").replace(/\/$/, "")
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
async function gh(env, method, path, body) {
|
|
192
|
+
const res = await (env.fetchImpl ?? fetch)(`${env.apiUrl}${path}`, {
|
|
193
|
+
method,
|
|
194
|
+
headers: {
|
|
195
|
+
Authorization: `Bearer ${env.token}`,
|
|
196
|
+
Accept: "application/vnd.github+json",
|
|
197
|
+
"X-GitHub-Api-Version": "2022-11-28",
|
|
198
|
+
"User-Agent": "lurq",
|
|
199
|
+
...body ? { "Content-Type": "application/json" } : {}
|
|
200
|
+
},
|
|
201
|
+
body: body ? JSON.stringify(body) : void 0
|
|
202
|
+
});
|
|
203
|
+
const data = await res.json().catch(() => null);
|
|
204
|
+
if (!res.ok && !(method === "POST" && path.endsWith("/labels") && res.status === 422)) {
|
|
205
|
+
const message = data?.message ?? `HTTP ${res.status}`;
|
|
206
|
+
throw new GithubIssueError(
|
|
207
|
+
res.status === 403 || res.status === 404 ? `GitHub refused (${message}); the workflow needs \`permissions: issues: write\`` : `GitHub ${res.status}: ${message}`,
|
|
208
|
+
res.status
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
return { status: res.status, data };
|
|
212
|
+
}
|
|
213
|
+
async function upsertDashboardIssue(env, rendered) {
|
|
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
|
+
);
|
|
222
|
+
const open = mine.find((i) => i.state === "open");
|
|
223
|
+
if (!open) {
|
|
224
|
+
if (mine.length) return { action: "closed", url: mine[0].html_url, commented: 0 };
|
|
225
|
+
await gh(env, "POST", `/repos/${env.repo}/labels`, {
|
|
226
|
+
name: DASHBOARD_LABEL,
|
|
227
|
+
color: "6e40c9",
|
|
228
|
+
description: "lurq dependency and MCP dashboard"
|
|
229
|
+
});
|
|
230
|
+
const { data } = await gh(env, "POST", `/repos/${env.repo}/issues`, {
|
|
231
|
+
title: rendered.title,
|
|
232
|
+
body: withMarkers(
|
|
233
|
+
rendered.body,
|
|
234
|
+
rendered.hash,
|
|
235
|
+
rendered.urgent.map((u) => u.key)
|
|
236
|
+
),
|
|
237
|
+
labels: [DASHBOARD_LABEL]
|
|
238
|
+
});
|
|
239
|
+
return { action: "created", url: data.html_url, commented: 0 };
|
|
240
|
+
}
|
|
241
|
+
const markers = readMarkers(open.body ?? "");
|
|
242
|
+
const fresh = rendered.urgent.filter((u) => !markers.alerted.includes(u.key));
|
|
243
|
+
if (markers.hash === rendered.hash && !fresh.length)
|
|
244
|
+
return { action: "unchanged", url: open.html_url, commented: 0 };
|
|
245
|
+
await gh(env, "PATCH", `/repos/${env.repo}/issues/${open.number}`, {
|
|
246
|
+
body: withMarkers(rendered.body, rendered.hash, [
|
|
247
|
+
...markers.alerted,
|
|
248
|
+
...fresh.map((u) => u.key)
|
|
249
|
+
])
|
|
250
|
+
});
|
|
251
|
+
if (fresh.length) {
|
|
252
|
+
await gh(env, "POST", `/repos/${env.repo}/issues/${open.number}/comments`, {
|
|
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")
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
return { action: "updated", url: open.html_url, commented: fresh.length ? 1 : 0 };
|
|
261
|
+
}
|
|
262
|
+
export {
|
|
263
|
+
DASHBOARD_LABEL,
|
|
264
|
+
DASHBOARD_MARKER,
|
|
265
|
+
DASHBOARD_TITLE,
|
|
266
|
+
GithubIssueError,
|
|
267
|
+
code,
|
|
268
|
+
githubEnvFrom,
|
|
269
|
+
md,
|
|
270
|
+
readMarkers,
|
|
271
|
+
renderDashboardIssue,
|
|
272
|
+
upsertDashboardIssue,
|
|
273
|
+
withMarkers
|
|
274
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { createRequire as __lurqCreateRequire } from 'node:module'; const require = __lurqCreateRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
checkApi,
|
|
4
|
+
diffApiSurfaces,
|
|
5
|
+
formatApiCheck
|
|
6
|
+
} from "./chunk-SOXFMMXC.js";
|
|
7
|
+
import "./chunk-3GHJR7XR.js";
|
|
8
|
+
import "./chunk-I3M2KJXB.js";
|
|
9
|
+
export {
|
|
10
|
+
checkApi,
|
|
11
|
+
diffApiSurfaces,
|
|
12
|
+
formatApiCheck
|
|
13
|
+
};
|