lurqrun 0.0.5 → 0.0.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.
- package/README.md +71 -13
- package/dist/bin/lurq.js +8762 -4825
- package/dist/bin/lurq.js.map +1 -1
- package/dist/index.d.ts +143 -4
- package/dist/index.js +8685 -4741
- package/dist/index.js.map +1 -1
- package/drizzle/0011_compat_provenance_closures.sql +11 -0
- package/drizzle/0012_api_surfaces.sql +9 -0
- package/drizzle/0013_nice_thanos.sql +1 -0
- package/drizzle/0014_luxuriant_malcolm_colcord.sql +10 -0
- package/drizzle/0015_past_fat_cobra.sql +11 -0
- package/drizzle/0016_futuristic_junta.sql +50 -0
- package/drizzle/0017_absent_grandmaster.sql +20 -0
- package/drizzle/0018_rainy_proemial_gods.sql +1 -0
- package/drizzle/0019_dashing_korvac.sql +11 -0
- package/drizzle/0020_normal_vulture.sql +3 -0
- package/drizzle/0021_dazzling_blue_shield.sql +17 -0
- package/drizzle/0022_massive_ghost_rider.sql +24 -0
- package/drizzle/0023_next_shatterstar.sql +1 -0
- package/drizzle/meta/0011_snapshot.json +1049 -0
- package/drizzle/meta/0012_snapshot.json +1115 -0
- package/drizzle/meta/0013_snapshot.json +1121 -0
- package/drizzle/meta/0014_snapshot.json +1190 -0
- package/drizzle/meta/0015_snapshot.json +1280 -0
- package/drizzle/meta/0016_snapshot.json +1683 -0
- package/drizzle/meta/0017_snapshot.json +1834 -0
- package/drizzle/meta/0018_snapshot.json +1834 -0
- package/drizzle/meta/0019_snapshot.json +1909 -0
- package/drizzle/meta/0020_snapshot.json +1921 -0
- package/drizzle/meta/0021_snapshot.json +2045 -0
- package/drizzle/meta/0022_snapshot.json +2246 -0
- package/drizzle/meta/0023_snapshot.json +2252 -0
- package/drizzle/meta/_journal.json +91 -0
- package/package.json +14 -5
- package/templates/skill-instructions.md +38 -16
package/dist/bin/lurq.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../node_modules/tsup/assets/esm_shims.js","../../src/core/constants.ts","../../src/core/types.ts","../../src/core/config.ts","../../src/db/schema.ts","../../src/db/client.ts","../../src/core/logger.ts","../../src/core/cache.ts","../../src/db/compat.ts","../../src/core/http.ts","../../src/ingestion/sources/npmRegistry.ts","../../src/ingestion/sources/npmSearch.ts","../../src/ingestion/sources/npmDownloads.ts","../../src/ingestion/sources/github.ts","../../src/ingestion/sources/depsDev.ts","../../src/ingestion/sources/bundlephobia.ts","../../src/ingestion/sources/index.ts","../../src/compat/members.ts","../../src/compat/peerCompat.ts","../../src/compat/check.ts","../../src/db/packages.ts","../../src/db/verification.ts","../../src/db/outcomes.ts","../../src/data/successors.json","../../src/core/successors.ts","../../src/ingestion/sources/githubReadme.ts","../../src/ingestion/summarize.ts","../../src/ingestion/collect.ts","../../src/search/categoryInference.ts","../../src/core/paths.ts","../../src/scoring/weights.ts","../../src/scoring/score.ts","../../src/scoring/index.ts","../../src/search/embeddings.ts","../../src/core/concurrency.ts","../../src/pipeline/sync.ts","../../src/pipeline/ingestQueue.ts","../../src/pipeline/single.ts","../../src/search/recommend.ts","../../src/security/risk.ts","../../src/data/popular-packages.json","../../src/security/typosquat.ts","../../src/mcp/handlers.ts","../../src/mcp/diagram.ts","../../src/compat/optimize.ts","../../src/mcp/plan.ts","../../src/mcp/metrics.ts","../../src/mcp/compact.ts","../../src/mcp/server.ts","../../src/auth/apiKeys.ts","../../src/mcp/http.ts","../../src/pipeline/rescore.ts","../../src/db/discovery.ts","../../src/pipeline/discovery.ts","../../src/pipeline/index.ts","../../src/cli/format.ts","../../src/cli/planView.ts","../../src/db/watch.ts","../../src/pipeline/watch.ts","../../src/sandbox/types.ts","../../src/sandbox/local.ts","../../src/sandbox/e2b.ts","../../src/sandbox/index.ts","../../src/pipeline/sandbox.ts","../../src/pipeline/compat.ts","../../src/cli/commands.ts","../../src/cli/installSkill.ts","../../src/cli/install.ts","../../src/cli/keys.ts","../../src/db/seed.ts","../../src/db/migrate.ts","../../src/bin/lurq.ts","../../src/cli/index.ts","../../src/core/gate.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","/** Static identifiers shared across the CLI and MCP server. */\nexport const SERVER_NAME = 'lurq';\n/** Published npm package name (the CLI command and MCP nickname stay `lurq`).\n * Keep in sync with package.json \"name\". */\nexport const PACKAGE_NAME = 'lurqrun';\n/** Keep in sync with package.json \"version\". */\nexport const VERSION = '0.0.5';\n\n/** Default hosted endpoint the install wizard writes into agent configs. The\n * marketing site is `lurq.run`; the MCP service lives on the `api.` subdomain.\n * Overridable per-invocation with `lurq install --url …` or `LURQ_ENDPOINT`. */\nexport const DEFAULT_ENDPOINT = 'https://api.lurq.run/mcp';\n\n/** Prefix for issued API keys (the rest is high-entropy random). */\nexport const API_KEY_PREFIX = 'lurq_live_';\n\n/** Embedding vector dimensionality (OpenAI text-embedding-3-small). The local\n * fallback embedder produces vectors of the same length so the DB column and\n * pgvector index never need to change. */\nexport const EMBEDDING_DIM = 1536;\n\n/** A package row is flagged `stale: true` in tool responses once its data is\n * older than this (§17). */\nexport const STALENESS_DAYS = 7;\n\nconst HOUR = 60 * 60 * 1000;\nconst DAY = 24 * HOUR;\n\n/** Per-source persistent-cache TTLs (§17). */\nexport const CACHE_TTL = {\n npmRegistry: 6 * HOUR,\n npmDownloads: 12 * HOUR,\n github: 12 * HOUR,\n depsDev: 24 * HOUR,\n bundlephobia: 7 * DAY,\n} as const;\n","/**\n * Shared domain types and the v1 category taxonomy (§8.3).\n * These are the stable contracts the rest of the system builds on.\n */\n\n/** Category taxonomy for the JS/TS web stack (§8.3). `other` is the fallback. */\nexport const CATEGORIES = [\n 'framework',\n 'meta-framework',\n 'state-management',\n 'routing',\n 'orm',\n 'database-client',\n 'ui-component-library',\n 'styling',\n 'forms',\n 'validation',\n 'data-fetching',\n 'http-client',\n 'auth',\n 'testing',\n 'build-tool',\n 'bundler',\n 'linting',\n 'date-time',\n 'animation',\n 'charts',\n 'i18n',\n 'utility',\n 'other',\n] as const;\n\nexport type Category = (typeof CATEGORIES)[number];\n\nexport function isCategory(value: string): value is Category {\n return (CATEGORIES as readonly string[]).includes(value);\n}\n\n/** Provenance of a package's stored category (§2A). `curated` comes from the\n * seed file or a manual arg; `inferred` was assigned automatically at ingest\n * and is safe for a later curation pass to override. */\nexport type CategorySource = 'curated' | 'inferred';\n\n/** How a candidate entered the discovery queue (§2B). `dependency-graph` and\n * `recent` are the long-tail channels; `category-search` is keyword-seeded;\n * `reactive` is an on-demand query that wasn't tracked yet. */\nexport type DiscoverySource = 'dependency-graph' | 'category-search' | 'recent' | 'reactive';\n\n/** Lifecycle of a discovery-queue candidate (§2B). */\nexport type DiscoveryStatus = 'pending' | 'ingested' | 'rejected';\n\n/**\n * Categories for which bundle size is meaningful and Bundlephobia is consulted\n * (§9.5). Backend-only categories get a null bundle size, and their efficiency\n * weight is redistributed (§10, see scoring).\n */\nexport const FRONTEND_CATEGORIES = [\n 'ui-component-library',\n 'styling',\n 'state-management',\n 'forms',\n 'validation',\n 'data-fetching',\n 'charts',\n 'animation',\n 'date-time',\n 'utility',\n] as const;\n\nexport function isFrontendCategory(category: Category | null | undefined): boolean {\n return category != null && (FRONTEND_CATEGORIES as readonly string[]).includes(category);\n}\n\n/**\n * Evidence-trustworthiness label, independent of the numeric score (§10, §1).\n * Two-dimensional: `proven`/`emerging` are adoption ladders; `promising` is\n * adoption-independent (high intrinsic quality, new package).\n */\nexport type Confidence = 'proven' | 'emerging' | 'promising' | 'unproven';\n\nexport type Runtime = 'browser' | 'node' | 'both';\n\n/** Result of co-installing two package versions in the sandbox (compat matrix). */\nexport type CompatStatus = 'compatible' | 'conflict';\n\n/** Coarse post-install result an agent reports back via `report_outcome` — never\n * source code, just whether the recommended package installed / compiled /\n * passed tests, or failed. Feeds the recommendation→outcome flywheel (§3.1). */\nexport type BuildSignal = 'installed' | 'compiled' | 'tests_passed' | 'failed';\n\n/** Sandbox verdict surfaced to agents: did this version actually install + load? */\nexport interface BuildVerified {\n version: string;\n installed: boolean;\n loaded: boolean | null;\n driver: string;\n ranAt: string;\n}\n\n/** A map of dependency/peer/engine name → semver range (from a manifest). */\nexport type DependencyRanges = Record<string, string>;\n/** `peerDependenciesMeta`: per-peer flags, notably `{ optional: true }`. */\nexport type PeerMeta = Record<string, { optional?: boolean }>;\n\n/** One incompatibility found across a set of packages. */\nexport interface CompatConflict {\n /** Where the conflict came from. `peer-deps`/`engines` are Tier-1 (metadata,\n * instant, deterministic); `sandbox` is Tier-2 (empirical co-install). */\n source: 'peer-deps' | 'engines' | 'sandbox';\n /** The packages involved in the conflict. */\n packages: string[];\n detail: string;\n}\n\n/**\n * `compat` output: whole-architecture compatibility for a set of packages.\n * Tier-1 peer-dependency/engine analysis + any Tier-2 sandbox conflicts.\n */\nexport interface CompatOutput {\n packages: string[];\n overall: 'compatible' | 'conflict' | 'unknown';\n conflicts: CompatConflict[];\n /** Packages lurq has no compatibility metadata for (counted toward `unknown`). */\n unverified: string[];\n /** The exact members the check ran over, name + resolved version. Versions are\n * always surfaced here, and the structure is stable for later scraping. */\n checked: { name: string; version: string | null }[];\n}\n\nexport type AdvisorySeverity = 'critical' | 'high' | 'moderate' | 'low' | 'info';\n\nexport interface Advisory {\n id: string;\n severity: AdvisorySeverity;\n summary: string;\n}\n\n/** Sub-scores composing the health score (§10). `efficiency` is null when not\n * size-based (backend categories) — its weight is redistributed.\n * `quality` (§1) is a standalone, adoption-independent axis — it does NOT feed\n * the health composite; it blends with health only at ranking time. Null when\n * no manifest signals were available. */\nexport interface ScoreBreakdown {\n maintenance: number;\n adoption: number;\n reliability: number;\n efficiency: number | null;\n quality: number | null;\n}\n\n/**\n * Structured usage guide generated at ingest (product refinement: lurq explains,\n * not just ranks). Grounded in the package README/description — never fabricated.\n * Exact current API specifics are deferred to Context7 via `context7Hint`.\n */\nexport interface UsageGuide {\n whatItIs: string;\n whenToUse: string;\n whenNotToUse?: string;\n whereItFits: string;\n howToWireIn?: string;\n context7Hint?: string;\n}\n\n/** A single recommendation candidate (§12.3.1). Intentionally compact. */\nexport interface Candidate {\n name: string;\n category: Category | null;\n healthScore: number;\n qualityScore: number | null;\n confidence: Confidence;\n why: string;\n latestVersion: string | null;\n weeklyDownloads: number | null;\n lastReleaseAt: string | null;\n repoUrl: string | null;\n}\n\n/** Full evidence read for one package (§12.3.2). */\nexport interface EvaluateOutput {\n dataAsOf: string;\n stale?: boolean;\n name: string;\n category: Category | null;\n healthScore: number;\n qualityScore: number | null;\n confidence: Confidence;\n scoreBreakdown: ScoreBreakdown;\n latestVersion: string | null;\n lastReleaseAt: string | null;\n weeklyDownloads: number | null;\n downloadGrowth90d: number | null;\n scorecard: number | null;\n bundleMinGzipKb: number | null;\n deprecated: boolean;\n archived: boolean;\n advisories: Advisory[];\n summary: string | null;\n usageGuide: UsageGuide | null;\n repoUrl: string | null;\n /** If this package is superseded, the recommended migration target (§1.2). */\n replacedBy?: { name: string; reason: string } | null;\n /** Latest sandbox verdict for this package, if one has been run. */\n buildVerified?: BuildVerified | null;\n}\n\n/** `verify` output (§12.3.4). */\n/** Supply-chain risk gate: high = review before installing (see security/risk). */\nexport type RiskLevel = 'low' | 'medium' | 'high';\n\nexport interface VerifyOutput {\n exists: boolean;\n tracked: boolean;\n deprecated: boolean;\n archived: boolean;\n latestVersion: string | null;\n weeklyDownloads: number | null;\n riskFlags: string[];\n /** Overall supply-chain risk, rolled up from riskFlags. */\n risk: RiskLevel;\n /** Suspected typosquat target — a popular package this name closely mimics. */\n typosquatOf: string | null;\n confidence: Confidence | null;\n advisoryCount: number;\n}\n","/**\n * Environment configuration (§15). Validated with zod. Most vars are optional\n * so the CLI can run partially (e.g. `lurq --help`) without a full setup;\n * commands that need a specific var call `requireConfig` to fail fast with a\n * clear message.\n */\nimport { config as dotenvConfig } from 'dotenv';\nimport { z } from 'zod';\n\nlet envLoaded = false;\n\n/** Load `.env` into process.env exactly once. Safe to call repeatedly. */\nexport function loadEnv(): void {\n if (envLoaded) return;\n dotenvConfig();\n envLoaded = true;\n}\n\nconst EnvSchema = z.object({\n DATABASE_URL: z.string().min(1).optional(),\n GITHUB_TOKEN: z.string().min(1).optional(),\n\n // 'openai' here means \"OpenAI-compatible\" — any provider exposing /v1/embeddings\n // + Bearer auth (OpenAI, Together, Fireworks, HF TEI, …). Point *_BASE_URL at it.\n EMBEDDING_PROVIDER: z.enum(['openai', 'local']).default('openai'),\n EMBEDDING_API_KEY: z.string().min(1).optional(),\n EMBEDDING_MODEL: z.string().min(1).default('text-embedding-3-small'),\n EMBEDDING_BASE_URL: z.string().url().default('https://api.openai.com/v1'),\n\n // 'openai' means \"OpenAI-compatible /v1/chat/completions\": OpenAI, Groq, Together,\n // Fireworks, xAI (Grok), etc. Swap provider by setting SUMMARY_BASE_URL + key + model.\n SUMMARY_PROVIDER: z.enum(['openai', 'none']).default('openai'),\n SUMMARY_API_KEY: z.string().min(1).optional(),\n SUMMARY_MODEL: z.string().min(1).default('gpt-4o-mini'),\n SUMMARY_BASE_URL: z.string().url().default('https://api.openai.com/v1'),\n\n LURQ_SYNC_CONCURRENCY: z.coerce.number().int().positive().max(50).default(5),\n LOG_LEVEL: z.enum(['error', 'warn', 'info', 'debug']).default('info'),\n\n // Hosted HTTP service (`serve-http`). Server-side only.\n PORT: z.coerce.number().int().positive().default(8080),\n /** Per-API-key rate limit: max requests per window. */\n LURQ_RATE_LIMIT_MAX: z.coerce.number().int().positive().default(120),\n /** Coarser per-IP rate limit (blunts unauthenticated floods before auth). */\n LURQ_IP_RATE_LIMIT_MAX: z.coerce.number().int().positive().default(240),\n /** Rate-limit window, milliseconds (applies to both limiters). */\n LURQ_RATE_LIMIT_WINDOW_MS: z.coerce.number().int().positive().default(60_000),\n /** Bearer token guarding `/metrics`. Unset → the endpoint is disabled (404). */\n LURQ_METRICS_TOKEN: z.string().min(1).optional(),\n /** Shared secret for self-serve key issuance (`POST /keys`). The Clerk-\n * authenticated web app presents it to mint a key for a signed-in user. Unset\n * → the endpoint is disabled (404). Keep it server-side, never in the client. */\n LURQ_ISSUER_SECRET: z.string().min(1).optional(),\n\n // Client-side (install wizard / CLI talking to a remote endpoint).\n LURQ_ENDPOINT: z.string().url().optional(),\n LURQ_API_KEY: z.string().min(1).optional(),\n\n // Sandbox verification. With E2B_API_KEY set, package install + smoke-load\n // runs in an isolated E2B cloud sandbox (safe for UNTRUSTED packages);\n // without it, the local child-process driver is used (trusted packages only).\n E2B_API_KEY: z.string().min(1).optional(),\n // E2B template to launch. Must provide node + npm on PATH; omit for E2B's\n // default. Provision a Node-versioned template here for reproducible runs.\n E2B_TEMPLATE: z.string().min(1).optional(),\n});\n\nexport type Config = z.infer<typeof EnvSchema>;\n\nexport class ConfigError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ConfigError';\n }\n}\n\nlet cached: Config | undefined;\n\n/** Parse + validate the environment. Throws ConfigError on malformed values. */\nexport function getConfig(): Config {\n if (cached) return cached;\n loadEnv();\n const parsed = EnvSchema.safeParse(process.env);\n if (!parsed.success) {\n const issues = parsed.error.issues\n .map((i) => ` - ${i.path.join('.')}: ${i.message}`)\n .join('\\n');\n throw new ConfigError(`Invalid environment configuration:\\n${issues}`);\n }\n cached = parsed.data;\n return cached;\n}\n\n/** For tests: clear the memoized config so a fresh getConfig() re-reads\n * process.env. Does not force a `.env` reload (loadEnv stays idempotent). */\nexport function resetConfigCache(): void {\n cached = undefined;\n}\n\n/**\n * Return the config but fail fast if any of the named required keys are absent.\n * Use in command handlers that genuinely need them (e.g. sync needs DATABASE_URL).\n */\nexport function requireConfig<K extends keyof Config>(keys: K[]): Config {\n const config = getConfig();\n const missing = keys.filter((k) => config[k] === undefined || config[k] === '');\n if (missing.length > 0) {\n throw new ConfigError(\n `Missing required environment variable(s): ${missing.join(', ')}.\\n` +\n `See .env.example for setup. Tip: copy it to .env and fill in the values.`,\n );\n }\n return config;\n}\n","/**\n * Drizzle schema (§8). One denormalized `packages` table feeds all reads (§8.2),\n * plus `sync_runs` (ingestion audit) and `seed_packages` (curated bootstrap list).\n *\n * The `vector` extension must exist before these migrations apply — `db migrate`\n * runs `CREATE EXTENSION IF NOT EXISTS vector` first (pgvector is not created\n * automatically by Drizzle).\n */\nimport { sql } from 'drizzle-orm';\nimport {\n bigint,\n boolean,\n customType,\n index,\n integer,\n jsonb,\n pgTable,\n primaryKey,\n real,\n serial,\n text,\n timestamp,\n uniqueIndex,\n vector,\n} from 'drizzle-orm/pg-core';\nimport { EMBEDDING_DIM } from '../core/constants';\n\n/** Postgres full-text `tsvector` type for hybrid lexical search (§3). */\nconst tsvector = customType<{ data: string; driverData: string }>({\n dataType() {\n return 'tsvector';\n },\n});\nimport type {\n Advisory,\n BuildSignal,\n Category,\n CategorySource,\n CompatStatus,\n Confidence,\n DependencyRanges,\n DiscoverySource,\n DiscoveryStatus,\n PeerMeta,\n ScoreBreakdown,\n UsageGuide,\n} from '../core/types';\n\nconst ts = (name: string) => timestamp(name, { withTimezone: true, mode: 'date' });\n\n/** One row per tracked npm package. */\nexport const packages = pgTable(\n 'packages',\n {\n id: serial('id').primaryKey(),\n name: text('name').notNull().unique(),\n ecosystem: text('ecosystem').notNull().default('npm'),\n\n // Classification + descriptive text\n category: text('category').$type<Category>(),\n /** Whether `category` was hand-curated or inferred at ingest (§2A). */\n categorySource: text('category_source').$type<CategorySource>(),\n description: text('description'),\n summary: text('summary'),\n repoUrl: text('repo_url'),\n homepage: text('homepage'),\n latestVersion: text('latest_version'),\n license: text('license'),\n\n // Lifecycle flags\n deprecated: boolean('deprecated').notNull().default(false),\n archived: boolean('archived').notNull().default(false),\n\n // Age / maintenance signals\n firstPublishedAt: ts('first_published_at'),\n lastReleaseAt: ts('last_release_at'),\n\n // Adoption signals\n weeklyDownloads: bigint('weekly_downloads', { mode: 'number' }),\n downloadGrowth90d: real('download_growth_90d'),\n stars: integer('stars'),\n openIssues: integer('open_issues'),\n closedIssues: integer('closed_issues'),\n\n // Reliability / efficiency signals\n scorecard: real('scorecard'),\n bundleMinGzipKb: real('bundle_min_gzip_kb'),\n advisories: jsonb('advisories').$type<Advisory[]>(),\n\n // Compatibility metadata (Tier-1): declared peer-deps + engines of the\n // latest version, so a whole-stack peer-range check is one indexed query.\n peerDependencies: jsonb('peer_dependencies').$type<DependencyRanges>(),\n peerDependenciesMeta: jsonb('peer_dependencies_meta').$type<PeerMeta>(),\n engines: jsonb('engines').$type<DependencyRanges>(),\n\n // Computed outputs\n healthScore: integer('health_score'),\n /** Intrinsic-quality axis (§1), adoption-independent. Blends with health at\n * ranking time (composite); never folded into health_score itself. */\n qualityScore: integer('quality_score'),\n confidence: text('confidence').$type<Confidence>(),\n scoreBreakdown: jsonb('score_breakdown').$type<ScoreBreakdown>(),\n usageGuide: jsonb('usage_guide').$type<UsageGuide>(),\n embedding: vector('embedding', { dimensions: EMBEDDING_DIM }),\n // Identity of the vector space `embedding` was produced in (e.g.\n // `openai:text-embedding-3-small`, `local`). Vector search filters on the\n // active provider so switching models can't compare incompatible spaces.\n embeddingProvider: text('embedding_provider'),\n\n // Lexical search vector (§3): name weighted highest (A), then category (B),\n // then summary/description (C). Generated + STORED so it stays in sync with\n // the row automatically; indexed with GIN for fast `@@` matching.\n searchVector: tsvector('search_vector').generatedAlwaysAs(\n sql`setweight(to_tsvector('english', coalesce(name, '')), 'A') || setweight(to_tsvector('english', coalesce(category, '')), 'B') || setweight(to_tsvector('english', coalesce(summary, description, '')), 'C')`,\n ),\n\n // Freshness + bookkeeping\n dataAsOf: timestamp('data_as_of', { withTimezone: true, mode: 'date' }),\n createdAt: ts('created_at').notNull().defaultNow(),\n updatedAt: ts('updated_at').notNull().defaultNow(),\n },\n (table) => [\n index('packages_category_idx').on(table.category),\n index('packages_health_score_idx').on(table.healthScore),\n // pgvector HNSW index for cosine similarity search (§11).\n index('packages_embedding_idx').using('hnsw', table.embedding.op('vector_cosine_ops')),\n // GIN index for lexical full-text search (§3).\n index('packages_search_vector_idx').using('gin', table.searchVector),\n ],\n);\n\n/** Ingestion audit trail (§8.1). */\nexport const syncRuns = pgTable('sync_runs', {\n id: serial('id').primaryKey(),\n startedAt: ts('started_at').notNull().defaultNow(),\n finishedAt: ts('finished_at'),\n packagesSeen: integer('packages_seen').notNull().default(0),\n packagesUpdated: integer('packages_updated').notNull().default(0),\n errors: jsonb('errors').$type<SyncError[]>().notNull().default([]),\n status: text('status').$type<SyncStatus>().notNull().default('running'),\n});\n\n/** Curated v1 seed list (§16), loaded from seed.json. */\nexport const seedPackages = pgTable('seed_packages', {\n name: text('name').primaryKey(),\n category: text('category').$type<Category>(),\n addedAt: ts('added_at').notNull().defaultNow(),\n});\n\n/**\n * Proactive-discovery candidate queue (§2B). Operator-side: the crawler enqueues\n * adjacency-graph / category-search / recent candidates here, a merit gate\n * pre-scores them on quality signals only (downloads excluded), and survivors\n * graduate to full ingestion. Keeps cost bounded and the DB free of toy packages.\n */\nexport const discoveryQueue = pgTable(\n 'discovery_queue',\n {\n id: serial('id').primaryKey(),\n name: text('name').notNull().unique(),\n discoveredVia: text('discovered_via').$type<DiscoverySource>().notNull(),\n /** Lightweight quality-only pre-score (§2B). Null until the gate runs. */\n preScore: integer('pre_score'),\n status: text('status').$type<DiscoveryStatus>().notNull().default('pending'),\n discoveredAt: ts('discovered_at').notNull().defaultNow(),\n },\n (table) => [index('discovery_queue_status_idx').on(table.status)],\n);\n\n/**\n * API keys for the hosted HTTP service (docs/lurq-hosted-deployment.md §5). Each\n * user/org gets a key; only its sha256 hash is persisted, so a DB leak never\n * exposes a usable key — the plaintext is shown exactly once at creation.\n * `ownerId` is reserved for future self-serve issuance via the Clerk dashboard.\n */\nexport const apiKeys = pgTable(\n 'api_keys',\n {\n id: serial('id').primaryKey(),\n /** sha256 hex of the full key — the only form persisted. */\n keyHash: text('key_hash').notNull().unique(),\n /** Identifiable display prefix, e.g. `lurq_live_ab12cd` (safe to show/log). */\n prefix: text('prefix').notNull(),\n /** Free-text label (owner / org / purpose). */\n label: text('label'),\n /** Reserved for self-serve issuance: maps to a Clerk user id. */\n ownerId: text('owner_id'),\n tier: text('tier').notNull().default('free'),\n createdAt: ts('created_at').notNull().defaultNow(),\n lastUsedAt: ts('last_used_at'),\n revokedAt: ts('revoked_at'),\n },\n (table) => [index('api_keys_owner_idx').on(table.ownerId)],\n);\n\n/**\n * Per-package version timeline (versions + publish dates), ingested from the npm\n * packument on every sync. Foundation for upgrade/migration intelligence and the\n * compatibility matrix; refreshed reactively by the `_changes` follower.\n */\nexport const packageVersions = pgTable(\n 'package_versions',\n {\n packageName: text('package_name').notNull(),\n version: text('version').notNull(),\n publishedAt: ts('published_at'),\n },\n (table) => [\n primaryKey({ columns: [table.packageName, table.version] }),\n index('package_versions_name_published_idx').on(table.packageName, table.publishedAt),\n ],\n);\n\n/** One row per replication feed: the cursor the npm `_changes` follower resumes\n * from, so a restart doesn't replay the whole registry history. */\nexport const watchState = pgTable('watch_state', {\n id: text('id').primaryKey(),\n seq: text('seq').notNull(),\n updatedAt: ts('updated_at'),\n});\n\n/**\n * Sandbox verification results: did this package version actually install and\n * load? Evidence beyond static signals. The query path reads the latest run.\n */\nexport const verificationRuns = pgTable(\n 'verification_runs',\n {\n id: serial('id').primaryKey(),\n packageName: text('package_name').notNull(),\n version: text('version').notNull(),\n driver: text('driver').notNull(),\n moduleSystem: text('module_system').notNull(),\n installed: boolean('installed').notNull(),\n imported: boolean('imported'),\n ranScripts: boolean('ran_scripts').notNull().default(false),\n durationMs: integer('duration_ms'),\n error: text('error'),\n ranAt: ts('ran_at'),\n },\n (table) => [index('verification_runs_pkg_idx').on(table.packageName, table.version)],\n);\n\n/**\n * Compatibility edges from co-installing two package versions in the sandbox.\n * A successful co-install is positive proof they coexist; a 2-package failure is\n * proof they conflict. Pairs are stored canonically (packageA name < packageB).\n */\nexport const compatEdges = pgTable(\n 'compat_edges',\n {\n id: serial('id').primaryKey(),\n packageA: text('package_a').notNull(),\n versionA: text('version_a').notNull(),\n packageB: text('package_b').notNull(),\n versionB: text('version_b').notNull(),\n status: text('status').$type<CompatStatus>().notNull(),\n driver: text('driver').notNull(),\n ranAt: ts('ran_at'),\n },\n (table) => [\n uniqueIndex('compat_edges_pair_idx').on(\n table.packageA,\n table.versionA,\n table.packageB,\n table.versionB,\n ),\n ],\n);\n\n/**\n * Recommendation → outcome capture (§3.1): the flywheel asset. lurq sits inside\n * the agent loop at the choice moment, so a lightweight opt-in callback yields a\n * recommendation→outcome dataset no downstream scanner can reconstruct (they see\n * deployed deps, not the decision). Privacy: no source code — only which package,\n * accepted or not, and a coarse build signal. Cheap to capture, compounds with use.\n */\nexport const recommendationOutcomes = pgTable(\n 'recommendation_outcomes',\n {\n id: serial('id').primaryKey(),\n /** The org this outcome belongs to (api_keys.owner_id). Null for anonymous /\n * operator-issued keys. This is what turns the flywheel from a global blob\n * into a per-org asset — \"what did *this* org succeed with.\" Server-injected\n * from the authenticated key, never caller-supplied. */\n ownerId: text('owner_id'),\n packageName: text('package_name').notNull(),\n accepted: boolean('accepted').notNull(),\n buildSignal: text('build_signal').$type<BuildSignal>(),\n /** The original need text the recommendation was for — ties outcome back to\n * the ask. Optional, length-capped at the trust boundary; never source code. */\n need: text('need'),\n createdAt: ts('created_at').notNull().defaultNow(),\n },\n (table) => [\n index('recommendation_outcomes_pkg_idx').on(table.packageName),\n index('recommendation_outcomes_owner_idx').on(table.ownerId),\n ],\n);\n\nexport type SyncStatus = 'running' | 'success' | 'partial' | 'failed';\n\nexport interface SyncError {\n package: string;\n source: string;\n message: string;\n}\n\nexport type PackageRow = typeof packages.$inferSelect;\nexport type NewPackageRow = typeof packages.$inferInsert;\nexport type SeedPackageRow = typeof seedPackages.$inferSelect;\nexport type SyncRunRow = typeof syncRuns.$inferSelect;\nexport type DiscoveryQueueRow = typeof discoveryQueue.$inferSelect;\nexport type ApiKeyRow = typeof apiKeys.$inferSelect;\nexport type NewApiKeyRow = typeof apiKeys.$inferInsert;\nexport type PackageVersionRow = typeof packageVersions.$inferSelect;\nexport type NewPackageVersionRow = typeof packageVersions.$inferInsert;\nexport type VerificationRunRow = typeof verificationRuns.$inferSelect;\nexport type NewVerificationRunRow = typeof verificationRuns.$inferInsert;\nexport type CompatEdgeRow = typeof compatEdges.$inferSelect;\nexport type NewCompatEdgeRow = typeof compatEdges.$inferInsert;\nexport type RecommendationOutcomeRow = typeof recommendationOutcomes.$inferSelect;\nexport type NewRecommendationOutcomeRow = typeof recommendationOutcomes.$inferInsert;\n","/**\n * Database client factory. Uses postgres.js + Drizzle. Callers own the lifecycle:\n * create, use, then `await close()` (CLI commands are short-lived processes).\n */\nimport { drizzle, type PostgresJsDatabase } from 'drizzle-orm/postgres-js';\nimport postgres from 'postgres';\nimport { requireConfig } from '../core/config';\nimport * as schema from './schema';\n\nexport type Database = PostgresJsDatabase<typeof schema>;\n\nexport interface DbHandle {\n db: Database;\n /** Underlying postgres.js client, for raw SQL (e.g. CREATE EXTENSION). */\n sql: postgres.Sql;\n /** Close the connection pool. Always call when done. */\n close: () => Promise<void>;\n}\n\nexport function createDb(opts: { max?: number } = {}): DbHandle {\n const { DATABASE_URL } = requireConfig(['DATABASE_URL']);\n const sql = postgres(DATABASE_URL!, { max: opts.max ?? 10, onnotice: () => {} });\n const db = drizzle(sql, { schema });\n return { db, sql, close: () => sql.end() };\n}\n\nexport { schema };\n","/**\n * Minimal leveled logger.\n *\n * IMPORTANT: all output goes to **stderr**. The MCP server communicates over\n * stdio (stdout is the protocol channel), so anything written to stdout would\n * corrupt the JSON-RPC stream. Never log to stdout.\n */\n\nconst LEVELS = { error: 0, warn: 1, info: 2, debug: 3 } as const;\nexport type LogLevel = keyof typeof LEVELS;\n\nfunction currentLevel(): number {\n const raw = process.env.LOG_LEVEL as LogLevel | undefined;\n return raw && raw in LEVELS ? LEVELS[raw] : LEVELS.info;\n}\n\nfunction emit(level: LogLevel, args: unknown[]): void {\n if (LEVELS[level] > currentLevel()) return;\n const parts = args.map((a) =>\n typeof a === 'string' ? a : a instanceof Error ? (a.stack ?? a.message) : safeStringify(a),\n );\n process.stderr.write(`[lurq] ${level.toUpperCase()} ${parts.join(' ')}\\n`);\n}\n\nfunction safeStringify(value: unknown): string {\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\nexport const logger = {\n error: (...args: unknown[]) => emit('error', args),\n warn: (...args: unknown[]) => emit('warn', args),\n info: (...args: unknown[]) => emit('info', args),\n debug: (...args: unknown[]) => emit('debug', args),\n};\n","/**\n * Optional Redis response cache for the read-heavy tools (recommend / evaluate /\n * compare). The index only changes when `sync`/`rescore` run, so identical\n * queries can be served from Redis instead of re-running the hybrid search.\n *\n * Zero-config by design: with no `REDIS_URL` (the default, and every end-user's\n * machine), `cached()` is a transparent pass-through and `invalidateCache()` a\n * no-op — nothing to provision, nothing breaks. Point `REDIS_URL` at an Upstash\n * (or any) Redis on the hosted server to turn it on. Any Redis error degrades to\n * computing directly; the cache never takes the request path down.\n *\n * Invalidation is version-based: every key embeds a namespace version read from\n * `lurq:cachever`. A successful sync `INCR`s it, so all prior keys become\n * unreachable at once (and age out via TTL) — no SCAN/DEL sweep.\n */\nimport { logger } from './logger';\n\ninterface RedisLike {\n get(key: string): Promise<string | null>;\n set(key: string, value: string, mode: 'EX', ttlSeconds: number): Promise<unknown>;\n incr(key: string): Promise<number>;\n}\n\nconst VERSION_KEY = 'lurq:cachever';\nconst DEFAULT_TTL_SEC = 3600;\n/** In-process memo for the namespace version, to avoid a round-trip per call.\n * Bounded so a sync's INCR is picked up within seconds. */\nconst VERSION_MEMO_MS = 10_000;\n\nlet clientPromise: Promise<RedisLike | null> | null = null;\nlet versionMemo: { value: string; at: number } | null = null;\n\nfunction ttlSeconds(): number {\n const n = Number(process.env.LURQ_CACHE_TTL_SEC);\n return Number.isFinite(n) && n > 0 ? n : DEFAULT_TTL_SEC;\n}\n\n/** Lazily connect to Redis once. Returns null (cache disabled) when REDIS_URL is\n * unset or the client can't be created. */\nasync function getClient(): Promise<RedisLike | null> {\n if (!process.env.REDIS_URL) return null;\n if (!clientPromise) {\n clientPromise = (async () => {\n try {\n const { default: Redis } = await import('ioredis');\n const client = new Redis(process.env.REDIS_URL!, {\n maxRetriesPerRequest: 1,\n enableOfflineQueue: false,\n lazyConnect: false,\n // Railway's private network (redis.railway.internal) is IPv6-only and\n // ioredis defaults to IPv4 — family:0 lets it resolve either stack, so\n // both the private URL and a public/Upstash URL work unchanged.\n family: 0,\n });\n client.on('error', (err: Error) => logger.warn(`redis: ${err.message}`));\n logger.info('Response cache enabled (REDIS_URL set).');\n return client as unknown as RedisLike;\n } catch (err) {\n logger.warn(`redis disabled (init failed): ${(err as Error).message}`);\n return null;\n }\n })();\n }\n return clientPromise;\n}\n\nasync function namespaceVersion(client: RedisLike): Promise<string> {\n if (versionMemo && Date.now() - versionMemo.at < VERSION_MEMO_MS) return versionMemo.value;\n const value = (await client.get(VERSION_KEY).catch(() => null)) ?? '0';\n versionMemo = { value, at: Date.now() };\n return value;\n}\n\n/**\n * Get-or-compute with optional caching. When the cache is off or unreachable,\n * `compute()` runs directly. `skipCache(value)` lets the caller avoid caching\n * unhelpful results (e.g. empty recommendations or not-found lookups).\n */\nexport async function cached<T>(\n namespace: string,\n key: string,\n compute: () => Promise<T>,\n opts: { skipCache?: (value: T) => boolean } = {},\n): Promise<T> {\n const client = await getClient();\n if (!client) return compute();\n\n let fullKey: string;\n try {\n const version = await namespaceVersion(client);\n fullKey = `lurq:${namespace}:${version}:${key}`;\n const hit = await client.get(fullKey);\n if (hit != null) return JSON.parse(hit) as T;\n } catch (err) {\n logger.warn(`redis read failed, bypassing cache: ${(err as Error).message}`);\n return compute();\n }\n\n const value = await compute();\n if (!opts.skipCache?.(value)) {\n // Fire-and-forget write; a cache-write failure must never affect the response.\n client.set(fullKey, JSON.stringify(value), 'EX', ttlSeconds()).catch(() => {});\n }\n return value;\n}\n\n/** Invalidate every cached read by bumping the namespace version. Call after a\n * successful sync/rescore. No-op when the cache is off. */\nexport async function invalidateCache(): Promise<void> {\n const client = await getClient();\n if (!client) return;\n try {\n await client.incr(VERSION_KEY);\n versionMemo = null; // force the next read to pick up the new version\n } catch (err) {\n logger.warn(`redis invalidate failed: ${(err as Error).message}`);\n }\n}\n","/** Read/write helpers for the compatibility matrix (`compat_edges`). */\nimport { and, inArray } from 'drizzle-orm';\nimport type { DependencyRanges, PeerMeta } from '../core/types';\nimport type { Database } from './client';\nimport {\n compatEdges,\n packages,\n type CompatEdgeRow,\n type NewCompatEdgeRow,\n} from './schema';\n\nexport interface CompatMetadataRow {\n name: string;\n latestVersion: string | null;\n peerDependencies: DependencyRanges | null;\n peerDependenciesMeta: PeerMeta | null;\n engines: DependencyRanges | null;\n}\n\n/** Tier-1 compatibility metadata for a set of packages — one indexed query. */\nexport async function getCompatMetadata(\n db: Database,\n names: string[],\n): Promise<CompatMetadataRow[]> {\n if (names.length === 0) return [];\n return db\n .select({\n name: packages.name,\n latestVersion: packages.latestVersion,\n peerDependencies: packages.peerDependencies,\n peerDependenciesMeta: packages.peerDependenciesMeta,\n engines: packages.engines,\n })\n .from(packages)\n .where(inArray(packages.name, names));\n}\n\n/** Order a pair canonically by package name so (A,B) and (B,A) dedupe to one row. */\nexport function canonicalPair(\n a: { name: string; version: string },\n b: { name: string; version: string },\n): { packageA: string; versionA: string; packageB: string; versionB: string } {\n const [low, high] = a.name <= b.name ? [a, b] : [b, a];\n return { packageA: low.name, versionA: low.version, packageB: high.name, versionB: high.version };\n}\n\nexport async function upsertCompatEdge(db: Database, edge: NewCompatEdgeRow): Promise<void> {\n await db\n .insert(compatEdges)\n .values(edge)\n .onConflictDoUpdate({\n target: [\n compatEdges.packageA,\n compatEdges.versionA,\n compatEdges.packageB,\n compatEdges.versionB,\n ],\n set: { status: edge.status, driver: edge.driver, ranAt: edge.ranAt },\n });\n}\n\n/** All stored edges whose both endpoints are within the given package names. */\nexport async function getCompatEdges(db: Database, names: string[]): Promise<CompatEdgeRow[]> {\n if (names.length === 0) return [];\n return db\n .select()\n .from(compatEdges)\n .where(and(inArray(compatEdges.packageA, names), inArray(compatEdges.packageB, names)));\n}\n","/**\n * Shared HTTP layer (§17). One wrapper for every external call:\n * - per-host rate limiting (max concurrency + minimum gap between starts),\n * - exponential backoff on 429 / 5xx (respecting Retry-After),\n * - in-run (memory) cache + persistent on-disk cache with per-source TTLs.\n *\n * Source clients pass a `ttlMs` (the per-source TTL from §17) and a `host`\n * bucket. `ttlMs: 0` disables caching (used for liveness checks like `verify`).\n */\nimport { createHash } from 'node:crypto';\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { existsSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\nimport { logger } from './logger';\n\nexport class HttpError extends Error {\n constructor(\n message: string,\n readonly status: number,\n readonly url: string,\n ) {\n super(message);\n this.name = 'HttpError';\n }\n}\n\nexport interface HttpOptions {\n /** Rate-limit bucket key, usually the hostname. */\n host: string;\n /** Persistent cache TTL in ms. 0 disables read+write caching. */\n ttlMs: number;\n method?: 'GET' | 'POST';\n headers?: Record<string, string>;\n body?: string;\n accept?: 'json' | 'text';\n timeoutMs?: number;\n retries?: number;\n /** Override the cache key (e.g. to keep auth tokens out of the key). */\n cacheKey?: string;\n /** Injected for tests. Defaults to global fetch. */\n fetchImpl?: typeof fetch;\n}\n\nexport interface HttpResponse<T> {\n status: number;\n data: T;\n fromCache: boolean;\n}\n\n// ── Per-host rate limiting ──────────────────────────────────────────────────\n\ninterface HostConfig {\n maxConcurrent: number;\n minIntervalMs: number;\n}\n\nconst DEFAULT_HOST_CONFIG: HostConfig = { maxConcurrent: 6, minIntervalMs: 0 };\n\nconst HOST_CONFIG: Record<string, HostConfig> = {\n 'api.github.com': { maxConcurrent: 4, minIntervalMs: 50 },\n 'registry.npmjs.org': { maxConcurrent: 4, minIntervalMs: 50 },\n // The downloads API rate-limits aggressively — serialize with a steady gap.\n // Weekly downloads go through the bulk endpoint; only growth hits this often.\n 'api.npmjs.org': { maxConcurrent: 1, minIntervalMs: 250 },\n 'api.deps.dev': { maxConcurrent: 4, minIntervalMs: 40 },\n 'raw.githubusercontent.com': { maxConcurrent: 4, minIntervalMs: 30 },\n // Bundlephobia is slow/flaky — be gentle (§9.5).\n 'bundlephobia.com': { maxConcurrent: 2, minIntervalMs: 200 },\n};\n\nclass HostLimiter {\n private active = 0;\n private nextAvailable = 0;\n private queue: Array<() => void> = [];\n\n constructor(private readonly config: HostConfig) {}\n\n async acquire(): Promise<void> {\n if (this.active >= this.config.maxConcurrent) {\n await new Promise<void>((resolve) => this.queue.push(resolve));\n }\n this.active++;\n const now = Date.now();\n const wait = Math.max(0, this.nextAvailable - now);\n this.nextAvailable = Math.max(now, this.nextAvailable) + this.config.minIntervalMs;\n if (wait > 0) await delay(wait);\n }\n\n release(): void {\n this.active--;\n const next = this.queue.shift();\n if (next) next();\n }\n}\n\nconst limiters = new Map<string, HostLimiter>();\n\nfunction limiterFor(host: string): HostLimiter {\n let limiter = limiters.get(host);\n if (!limiter) {\n limiter = new HostLimiter(HOST_CONFIG[host] ?? DEFAULT_HOST_CONFIG);\n limiters.set(host, limiter);\n }\n return limiter;\n}\n\n// ── Caching ─────────────────────────────────────────────────────────────────\n\ninterface CacheEntry {\n fetchedAt: number;\n status: number;\n body: string;\n}\n\nconst memoryCache = new Map<string, CacheEntry>();\n\n/** When true, cache reads are skipped (writes still happen). Used by `sync --full`. */\nlet bypassCacheRead = false;\n\n/** Force fresh fetches (ignore cache TTLs) while still refreshing the cache. */\nexport function setCacheBypassRead(value: boolean): void {\n bypassCacheRead = value;\n}\n\nfunction cacheDir(): string {\n return process.env.LURQ_CACHE_DIR ?? join(homedir(), '.cache', 'lurq', 'http');\n}\n\nfunction cacheFile(key: string): string {\n const hash = createHash('sha256').update(key).digest('hex');\n return join(cacheDir(), `${hash}.json`);\n}\n\nasync function readCache(key: string, ttlMs: number): Promise<CacheEntry | undefined> {\n const now = Date.now();\n const mem = memoryCache.get(key);\n if (mem && now - mem.fetchedAt < ttlMs) return mem;\n\n const file = cacheFile(key);\n if (!existsSync(file)) return undefined;\n try {\n const entry = JSON.parse(await readFile(file, 'utf8')) as CacheEntry;\n if (now - entry.fetchedAt < ttlMs) {\n memoryCache.set(key, entry);\n return entry;\n }\n } catch {\n /* corrupt cache file — ignore and refetch */\n }\n return undefined;\n}\n\nasync function writeCache(key: string, entry: CacheEntry): Promise<void> {\n memoryCache.set(key, entry);\n const file = cacheFile(key);\n try {\n await mkdir(dirname(file), { recursive: true });\n await writeFile(file, JSON.stringify(entry), 'utf8');\n } catch (err) {\n logger.debug(`http cache write failed: ${(err as Error).message}`);\n }\n}\n\n// ── Core request ────────────────────────────────────────────────────────────\n\nconst RETRYABLE = new Set([429, 500, 502, 503, 504]);\n\nexport async function httpRequest<T = unknown>(\n url: string,\n opts: HttpOptions,\n): Promise<HttpResponse<T>> {\n const {\n host,\n ttlMs,\n method = 'GET',\n headers = {},\n body,\n accept = 'json',\n timeoutMs = 15_000,\n retries = 3,\n fetchImpl = fetch,\n } = opts;\n const key = opts.cacheKey ?? `${method} ${url} ${body ?? ''}`;\n\n if (ttlMs > 0 && !bypassCacheRead) {\n const cached = await readCache(key, ttlMs);\n if (cached) {\n return { status: cached.status, data: decode<T>(cached.body, accept), fromCache: true };\n }\n }\n\n const limiter = limiterFor(host);\n let lastErr: unknown;\n\n for (let attempt = 0; attempt <= retries; attempt++) {\n await limiter.acquire();\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const res = await fetchImpl(url, { method, headers, body, signal: controller.signal });\n const text = await res.text();\n\n if (res.ok) {\n if (ttlMs > 0) await writeCache(key, { fetchedAt: Date.now(), status: res.status, body: text });\n return { status: res.status, data: decode<T>(text, accept), fromCache: false };\n }\n\n // Non-2xx\n if (RETRYABLE.has(res.status) && attempt < retries) {\n const retryAfter = parseRetryAfter(res.headers.get('retry-after'));\n await delay(retryAfter ?? backoff(attempt));\n lastErr = new HttpError(`HTTP ${res.status} for ${url}`, res.status, url);\n continue;\n }\n throw new HttpError(`HTTP ${res.status} for ${url}`, res.status, url);\n } catch (err) {\n lastErr = err;\n const isAbort = err instanceof Error && err.name === 'AbortError';\n const isHttp = err instanceof HttpError;\n // Retry network/timeout errors; don't retry non-retryable HTTP statuses.\n if (isHttp && !RETRYABLE.has(err.status)) throw err;\n if (attempt < retries) {\n await delay(backoff(attempt));\n continue;\n }\n if (isAbort) throw new HttpError(`Timeout after ${timeoutMs}ms for ${url}`, 0, url);\n } finally {\n clearTimeout(timer);\n limiter.release();\n }\n }\n throw lastErr instanceof Error ? lastErr : new HttpError(`Request failed for ${url}`, 0, url);\n}\n\nexport async function httpGetJson<T = unknown>(\n url: string,\n opts: Omit<HttpOptions, 'accept' | 'method'>,\n): Promise<HttpResponse<T>> {\n return httpRequest<T>(url, { ...opts, method: 'GET', accept: 'json' });\n}\n\n// ── Helpers ─────────────────────────────────────────────────────────────────\n\nfunction decode<T>(text: string, accept: 'json' | 'text'): T {\n if (accept === 'text') return text as unknown as T;\n return (text ? JSON.parse(text) : null) as T;\n}\n\nfunction backoff(attempt: number): number {\n const base = 500 * 2 ** attempt;\n return base + Math.floor(((attempt * 137) % 100) * 3); // small deterministic jitter\n}\n\nfunction parseRetryAfter(value: string | null): number | undefined {\n if (!value) return undefined;\n const seconds = Number(value);\n if (!Number.isNaN(seconds)) return seconds * 1000;\n const date = Date.parse(value);\n return Number.isNaN(date) ? undefined : Math.max(0, date - Date.now());\n}\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/** Test helper: clear the in-memory cache and per-host limiters. */\nexport function __resetHttpStateForTests(): void {\n memoryCache.clear();\n limiters.clear();\n}\n","/**\n * npm registry client (§9.1). Base metadata: version, description, license,\n * repository, publish times, deprecation, maintainers, README.\n */\nimport { CACHE_TTL } from '../../core/constants';\nimport { httpGetJson } from '../../core/http';\nimport type { NpmRegistryData } from '../types';\n\nconst HOST = 'registry.npmjs.org';\n\n/** Encode a package name for a registry URL (scoped names need `/` → `%2F`). */\nexport function encodeNpmName(name: string): string {\n return name.startsWith('@') ? name.replace('/', '%2F') : name;\n}\n\n/** Extract `{ owner, repo }` from any GitHub repository URL form. */\nexport function parseGithubRepo(\n url: string | null | undefined,\n): { owner: string; repo: string } | null {\n if (!url) return null;\n const match = url.match(/github\\.com[/:]([^/]+)\\/([^/#?]+?)(?:\\.git)?(?:[/#?].*)?$/i);\n if (!match) return null;\n const owner = match[1];\n const repo = match[2];\n if (!owner || !repo) return null;\n return { owner, repo };\n}\n\nfunction normalizeRepoUrl(\n repository: unknown,\n homepage: string | null,\n): { repoUrl: string | null; repo: { owner: string; repo: string } | null } {\n let raw: string | null = null;\n if (typeof repository === 'string') raw = repository;\n else if (repository && typeof repository === 'object' && 'url' in repository) {\n raw = String((repository as { url: unknown }).url);\n }\n const repo = parseGithubRepo(raw) ?? parseGithubRepo(homepage);\n const repoUrl = repo ? `https://github.com/${repo.owner}/${repo.repo}` : (cleanUrl(raw) ?? null);\n return { repoUrl, repo };\n}\n\nfunction cleanUrl(url: string | null): string | null {\n if (!url) return null;\n return url\n .replace(/^git\\+/, '')\n .replace(/^git:\\/\\//, 'https://')\n .replace(/\\.git$/, '');\n}\n\nfunction pickLicense(value: unknown): string | null {\n if (!value) return null;\n if (typeof value === 'string') return value;\n if (typeof value === 'object' && 'type' in value) return String((value as { type: unknown }).type);\n return null;\n}\n\nfunction toDate(value: unknown): Date | null {\n if (typeof value !== 'string') return null;\n const ms = Date.parse(value);\n return Number.isNaN(ms) ? null : new Date(ms);\n}\n\nexport function parseNpmRegistry(json: any): NpmRegistryData {\n const latest: string | null = json?.['dist-tags']?.latest ?? null;\n const latestManifest = latest ? (json?.versions?.[latest] ?? {}) : {};\n const time = json?.time ?? {};\n\n const repository = json?.repository ?? latestManifest?.repository;\n const homepage = json?.homepage ?? latestManifest?.homepage ?? null;\n const { repoUrl, repo } = normalizeRepoUrl(repository, homepage);\n\n const deprecated = Boolean(latestManifest?.deprecated ?? json?.deprecated);\n const maintainers = Array.isArray(json?.maintainers) ? json.maintainers.length : null;\n const name: string = json?.name ?? '';\n\n return {\n name,\n description: json?.description ?? latestManifest?.description ?? null,\n latestVersion: latest,\n license: pickLicense(json?.license ?? latestManifest?.license),\n homepage,\n repo,\n repoUrl,\n firstPublishedAt: toDate(time?.created),\n lastReleaseAt: toDate(latest ? time?.[latest] : null) ?? toDate(time?.modified),\n deprecated,\n maintainersCount: maintainers,\n readme: typeof json?.readme === 'string' ? json.readme : null,\n keywords: parseKeywords(json?.keywords ?? latestManifest?.keywords),\n hasTypes: detectTypes(name, latestManifest),\n hasTestScript: detectTestScript(latestManifest),\n directDependenciesCount: countDeps(latestManifest?.dependencies),\n hasProvenance: detectProvenance(latestManifest),\n hasInstallScripts: detectInstallScripts(latestManifest),\n peerDependencies: parseDepMap(latestManifest?.peerDependencies),\n peerDependenciesMeta: parsePeerMeta(latestManifest?.peerDependenciesMeta),\n engines: parseDepMap(latestManifest?.engines),\n versionTimeline: parseVersionTimeline(json),\n };\n}\n\n/** A manifest dependency/engines map → a clean { name: range } record, or null. */\nfunction parseDepMap(value: unknown): Record<string, string> | null {\n if (!value || typeof value !== 'object') return null;\n const out: Record<string, string> = {};\n for (const [name, range] of Object.entries(value as Record<string, unknown>)) {\n if (typeof range === 'string' && range.trim() !== '') out[name] = range;\n }\n return Object.keys(out).length ? out : null;\n}\n\n/** `peerDependenciesMeta` → { name: { optional } }, or null. */\nfunction parsePeerMeta(value: unknown): Record<string, { optional?: boolean }> | null {\n if (!value || typeof value !== 'object') return null;\n const out: Record<string, { optional?: boolean }> = {};\n for (const [name, meta] of Object.entries(value as Record<string, unknown>)) {\n if (meta && typeof meta === 'object' && 'optional' in meta) {\n out[name] = { optional: Boolean((meta as { optional?: unknown }).optional) };\n }\n }\n return Object.keys(out).length ? out : null;\n}\n\n/** Lifecycle install hooks run arbitrary code at install time. We surface their\n * presence; deeper analysis belongs in the sandbox tier. */\nfunction detectInstallScripts(manifest: any): boolean {\n const scripts = manifest?.scripts;\n if (!scripts || typeof scripts !== 'object') return false;\n return ['preinstall', 'install', 'postinstall'].some(\n (hook) => typeof scripts[hook] === 'string' && scripts[hook].trim() !== '',\n );\n}\n\n/**\n * The published-version timeline from the packument: every key in `versions`\n * paired with its publish date from `time`, newest first. The `time` map also\n * holds `created`/`modified` sentinels, which we skip.\n */\nexport function parseVersionTimeline(json: any): { version: string; publishedAt: Date | null }[] {\n const versions = json?.versions;\n if (!versions || typeof versions !== 'object') return [];\n const time = json?.time ?? {};\n return Object.keys(versions)\n .map((version) => ({ version, publishedAt: toDate(time?.[version]) }))\n .sort((a, b) => (b.publishedAt?.getTime() ?? 0) - (a.publishedAt?.getTime() ?? 0));\n}\n\nfunction parseKeywords(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return value.filter((k): k is string => typeof k === 'string');\n}\n\n/** Ships types if the manifest declares `types`/`typings`, or it IS an @types pkg. */\nfunction detectTypes(name: string, manifest: any): boolean {\n if (typeof manifest?.types === 'string' || typeof manifest?.typings === 'string') return true;\n if (name.startsWith('@types/')) return true;\n // `exports` map with a `types` condition (modern dual-package layout).\n const exportsField = manifest?.exports;\n if (exportsField && typeof exportsField === 'object') {\n const serialized = JSON.stringify(exportsField);\n if (serialized.includes('\"types\"')) return true;\n }\n return false;\n}\n\n/** A real test script — npm's `init` leaves a placeholder we must not count. */\nfunction detectTestScript(manifest: any): boolean {\n const test = manifest?.scripts?.test;\n if (typeof test !== 'string' || test.trim() === '') return false;\n return !/no test specified/i.test(test);\n}\n\nfunction countDeps(deps: unknown): number | null {\n if (!deps || typeof deps !== 'object') return 0;\n return Object.keys(deps as Record<string, unknown>).length;\n}\n\n/** npm provenance leaves a signed attestation on the published dist. */\nfunction detectProvenance(manifest: any): boolean {\n return Boolean(manifest?.dist?.attestations);\n}\n\nexport async function fetchNpmRegistry(\n name: string,\n fetchImpl?: typeof fetch,\n): Promise<NpmRegistryData> {\n const url = `https://${HOST}/${encodeNpmName(name)}`;\n const { data } = await httpGetJson<any>(url, {\n host: HOST,\n ttlMs: CACHE_TTL.npmRegistry,\n fetchImpl,\n });\n return parseNpmRegistry(data);\n}\n\n/** Live existence check for `verify` (§12.3.4) — bypasses cache. */\nexport async function npmPackageExists(name: string, fetchImpl?: typeof fetch): Promise<boolean> {\n const url = `https://${HOST}/${encodeNpmName(name)}`;\n try {\n const { status } = await httpGetJson<any>(url, {\n host: HOST,\n ttlMs: 0,\n retries: 1,\n fetchImpl,\n });\n return status === 200;\n } catch (err) {\n if (err && typeof err === 'object' && 'status' in err && (err as any).status === 404) {\n return false;\n }\n throw err;\n }\n}\n","/**\n * npm registry search client (§2B). Seeds the discovery crawler's long-tail\n * channels: keyword/category search and a recently-published sweep. This is the\n * niche workhorse — the dependency graph structurally can't find niche\n * *alternatives* (a new package shares no edge with the incumbent it competes\n * with), so that job lives here.\n */\nimport { CACHE_TTL } from '../../core/constants';\nimport { httpGetJson } from '../../core/http';\n\nconst HOST = 'registry.npmjs.org';\n\nexport interface NpmSearchHit {\n name: string;\n /** ISO publish date of the matched version, if reported. */\n date: string | null;\n}\n\n/**\n * Run an npm registry search. `query` uses npm's search qualifier syntax, e.g.\n * `keywords:orm` or `orm typescript`. Returns name + publish date per hit.\n * Best-effort: returns [] on any failure.\n */\nexport async function searchNpm(\n query: string,\n size = 20,\n fetchImpl?: typeof fetch,\n): Promise<NpmSearchHit[]> {\n const url = `https://${HOST}/-/v1/search?text=${encodeURIComponent(query)}&size=${size}`;\n try {\n const { data } = await httpGetJson<any>(url, {\n host: HOST,\n ttlMs: CACHE_TTL.npmRegistry,\n fetchImpl,\n });\n const objects: any[] = Array.isArray(data?.objects) ? data.objects : [];\n return objects\n .map((o) => ({ name: o?.package?.name, date: o?.package?.date ?? null }))\n .filter((h): h is NpmSearchHit => typeof h.name === 'string');\n } catch {\n return [];\n }\n}\n","/**\n * npm downloads client (§9.2). Weekly downloads + 90-day growth.\n *\n * Weekly downloads is fetched in BULK at the pipeline level — npm's point API\n * accepts up to 128 comma-separated packages per call, which avoids the harsh\n * rate-limiting that per-package bursts trigger. The range (growth) API has no\n * bulk form, so growth is a per-package best-effort secondary signal.\n *\n * Bulk does not support scoped (@scope/name) packages; those are fetched singly.\n */\nimport { CACHE_TTL } from '../../core/constants';\nimport { httpGetJson, HttpError } from '../../core/http';\n\nconst HOST = 'api.npmjs.org';\nconst BULK_CHUNK = 128;\n\nexport function parseWeeklyDownloads(json: any): number | null {\n const value = json?.downloads;\n return typeof value === 'number' ? value : null;\n}\n\ninterface RangePoint {\n day: string;\n downloads: number;\n}\n\n/** Compute the 90d growth fraction from a daily-downloads range. */\nexport function parseDownloadGrowth(json: any): number | null {\n const points: RangePoint[] = Array.isArray(json?.downloads) ? json.downloads : [];\n if (points.length < 60) return null;\n const tail = points.slice(-60);\n const prior = tail.slice(0, 30);\n const recent = tail.slice(30);\n const sum = (arr: RangePoint[]) => arr.reduce((acc, p) => acc + (p.downloads || 0), 0);\n const priorAvg = sum(prior) / prior.length;\n const recentAvg = sum(recent) / recent.length;\n if (priorAvg <= 0) return recentAvg > 0 ? 1 : 0;\n // Round to 3 decimals: this is a best-effort secondary signal, so the float's\n // precision tail is meaningless — and it ships in every recommend/evaluate\n // response, where 19 chars of noise is tokens the calling agent pays for.\n return Math.round(((recentAvg - priorAvg) / priorAvg) * 1000) / 1000;\n}\n\n/** Format a Date as YYYY-MM-DD (UTC) for the npm range API. */\nfunction ymd(date: Date): string {\n return date.toISOString().slice(0, 10);\n}\n\n/** Build a `start:end` range string covering the last 90 days. */\nexport function last90DayRange(now: Date = new Date()): string {\n const end = now;\n const start = new Date(end.getTime() - 90 * 24 * 60 * 60 * 1000);\n return `${ymd(start)}:${ymd(end)}`;\n}\n\n/** Parse a bulk point response into a name→downloads map (handles single + multi forms). */\nexport function parseBulkWeekly(json: any, requested: string[]): Map<string, number | null> {\n const map = new Map<string, number | null>();\n // A single-package request returns the object directly, not keyed by name.\n if (json && typeof json.downloads === 'number' && typeof json.package === 'string') {\n map.set(json.package, json.downloads);\n return map;\n }\n for (const name of requested) {\n const entry = json?.[name];\n map.set(name, entry && typeof entry.downloads === 'number' ? entry.downloads : null);\n }\n return map;\n}\n\nfunction chunk<T>(items: T[], size: number): T[][] {\n const out: T[][] = [];\n for (let i = 0; i < items.length; i += size) out.push(items.slice(i, i + size));\n return out;\n}\n\n/** Single-package weekly downloads. 404 → null (no per-package data). */\nexport async function fetchWeeklyDownloads(\n name: string,\n fetchImpl?: typeof fetch,\n): Promise<number | null> {\n try {\n const { data } = await httpGetJson<any>(\n `https://${HOST}/downloads/point/last-week/${name}`,\n { host: HOST, ttlMs: CACHE_TTL.npmDownloads, retries: 5, fetchImpl },\n );\n return parseWeeklyDownloads(data);\n } catch (err) {\n if (err instanceof HttpError && err.status === 404) return null;\n throw err;\n }\n}\n\n/** Per-package 90d growth (best-effort secondary signal). */\nexport async function fetchDownloadGrowth(\n name: string,\n fetchImpl?: typeof fetch,\n): Promise<number | null> {\n try {\n const { data } = await httpGetJson<any>(\n `https://${HOST}/downloads/range/${last90DayRange()}/${name}`,\n { host: HOST, ttlMs: CACHE_TTL.npmDownloads, retries: 3, fetchImpl },\n );\n return parseDownloadGrowth(data);\n } catch {\n return null;\n }\n}\n\n/**\n * Bulk-fetch weekly downloads for many packages. Unscoped packages go through\n * the 128-at-a-time bulk endpoint; scoped packages are fetched individually.\n */\nexport async function fetchBulkWeeklyDownloads(\n names: string[],\n fetchImpl?: typeof fetch,\n): Promise<Map<string, number | null>> {\n const result = new Map<string, number | null>();\n const unscoped = names.filter((n) => !n.startsWith('@'));\n const scoped = names.filter((n) => n.startsWith('@'));\n\n for (const batch of chunk(unscoped, BULK_CHUNK)) {\n try {\n const { data } = await httpGetJson<any>(\n `https://${HOST}/downloads/point/last-week/${batch.join(',')}`,\n { host: HOST, ttlMs: CACHE_TTL.npmDownloads, retries: 5, fetchImpl },\n );\n for (const [k, v] of parseBulkWeekly(data, batch)) result.set(k, v);\n } catch {\n // Leave this batch absent; per-package fallback will retry it.\n }\n }\n\n for (const name of scoped) {\n try {\n result.set(name, await fetchWeeklyDownloads(name, fetchImpl));\n } catch {\n /* leave absent → per-package fallback */\n }\n }\n\n return result;\n}\n","/**\n * GitHub client (§9.3). One GraphQL call per repo fetches stars, issue counts,\n * archived flag, and recent releases (latest date + 12-month cadence).\n * Requires GITHUB_TOKEN; without it, the pipeline skips this source.\n */\nimport { CACHE_TTL } from '../../core/constants';\nimport { httpRequest } from '../../core/http';\nimport type { GithubRepoData } from '../types';\n\nconst HOST = 'api.github.com';\nconst ENDPOINT = `https://${HOST}/graphql`;\n\nconst QUERY = `query($owner:String!, $name:String!) {\n repository(owner:$owner, name:$name) {\n stargazerCount\n isArchived\n openIssues: issues(states:OPEN) { totalCount }\n closedIssues: issues(states:CLOSED) { totalCount }\n releases(first: 50, orderBy: {field: CREATED_AT, direction: DESC}) {\n nodes { createdAt }\n }\n }\n}`;\n\nconst ONE_YEAR_MS = 365 * 24 * 60 * 60 * 1000;\n\nexport function parseGithub(json: any, now: Date = new Date()): GithubRepoData | null {\n const repo = json?.data?.repository;\n if (!repo) return null;\n\n const releaseNodes: { createdAt: string }[] = repo.releases?.nodes ?? [];\n const releaseDates = releaseNodes\n .map((n) => Date.parse(n.createdAt))\n .filter((ms) => !Number.isNaN(ms));\n const cutoff = now.getTime() - ONE_YEAR_MS;\n\n return {\n stars: typeof repo.stargazerCount === 'number' ? repo.stargazerCount : null,\n openIssues: repo.openIssues?.totalCount ?? null,\n closedIssues: repo.closedIssues?.totalCount ?? null,\n archived: Boolean(repo.isArchived),\n lastReleaseAt: releaseDates.length ? new Date(Math.max(...releaseDates)) : null,\n releasesLast12mo: releaseDates.filter((ms) => ms >= cutoff).length,\n };\n}\n\nexport async function fetchGithubRepo(\n owner: string,\n repo: string,\n token: string,\n fetchImpl?: typeof fetch,\n): Promise<GithubRepoData | null> {\n const body = JSON.stringify({ query: QUERY, variables: { owner, name: repo } });\n const { data } = await httpRequest<any>(ENDPOINT, {\n host: HOST,\n ttlMs: CACHE_TTL.github,\n method: 'POST',\n headers: {\n Authorization: `bearer ${token}`,\n 'Content-Type': 'application/json',\n 'User-Agent': 'lurq',\n },\n body,\n // Keep the auth token out of the cache key.\n cacheKey: `POST ${ENDPOINT} ${owner}/${repo}`,\n fetchImpl,\n });\n return parseGithub(data);\n}\n","/**\n * deps.dev client (§9.4). Primary source for OpenSSF Scorecard and security\n * advisories.\n * - Scorecard comes from the project endpoint (keyed by github.com/owner/repo).\n * - Advisories: the version endpoint lists advisoryKeys; we fetch each (capped)\n * and derive a severity bucket from its CVSS score.\n */\nimport { CACHE_TTL } from '../../core/constants';\nimport { httpGetJson, type HttpResponse } from '../../core/http';\nimport type { Advisory, AdvisorySeverity } from '../../core/types';\nimport type { DepsDevData } from '../types';\n\nconst HOST = 'api.deps.dev';\nconst MAX_ADVISORIES = 10;\n\nfunction encodeName(name: string): string {\n return encodeURIComponent(name);\n}\n\nexport function severityFromCvss(score: number | null | undefined): AdvisorySeverity {\n if (score == null) return 'moderate';\n if (score >= 9) return 'critical';\n if (score >= 7) return 'high';\n if (score >= 4) return 'moderate';\n if (score > 0) return 'low';\n return 'info';\n}\n\nexport function parseScorecard(json: any): number | null {\n const score = json?.scorecard?.overallScore;\n return typeof score === 'number' ? score : null;\n}\n\nexport function parseAdvisoryKeys(versionJson: any): string[] {\n const keys = versionJson?.advisoryKeys;\n if (!Array.isArray(keys)) return [];\n return keys\n .map((k: any) => (typeof k === 'string' ? k : k?.id))\n .filter((id: unknown): id is string => typeof id === 'string');\n}\n\nexport function parseAdvisoryDetail(json: any): Advisory {\n return {\n id: json?.advisoryKey?.id ?? json?.advisoryKey ?? 'unknown',\n severity: severityFromCvss(json?.cvss3Score),\n summary: json?.title ?? '',\n };\n}\n\nexport async function fetchScorecard(\n owner: string,\n repo: string,\n fetchImpl?: typeof fetch,\n): Promise<number | null> {\n const projectKey = encodeURIComponent(`github.com/${owner}/${repo}`);\n const url = `https://${HOST}/v3/projects/${projectKey}`;\n try {\n const { data } = await httpGetJson<any>(url, {\n host: HOST,\n ttlMs: CACHE_TTL.depsDev,\n fetchImpl,\n });\n return parseScorecard(data);\n } catch {\n return null;\n }\n}\n\nexport async function fetchAdvisories(\n name: string,\n version: string,\n fetchImpl?: typeof fetch,\n): Promise<Advisory[]> {\n const versionUrl = `https://${HOST}/v3/systems/npm/packages/${encodeName(name)}/versions/${encodeURIComponent(version)}`;\n let keys: string[] = [];\n try {\n const { data } = await httpGetJson<any>(versionUrl, {\n host: HOST,\n ttlMs: CACHE_TTL.depsDev,\n fetchImpl,\n });\n keys = parseAdvisoryKeys(data).slice(0, MAX_ADVISORIES);\n } catch {\n return [];\n }\n\n const details = await Promise.allSettled(\n keys.map((key) =>\n httpGetJson<any>(`https://${HOST}/v3/advisories/${encodeURIComponent(key)}`, {\n host: HOST,\n ttlMs: CACHE_TTL.depsDev,\n fetchImpl,\n }),\n ),\n );\n return details\n .filter(\n (d): d is PromiseFulfilledResult<HttpResponse<any>> => d.status === 'fulfilled',\n )\n .map((d) => parseAdvisoryDetail(d.value.data));\n}\n\n/**\n * Direct dependency names from the deps.dev graph (§2B). These are the packages\n * a seed is *built on* — the adjacent foundations. Best-effort: returns [] on any\n * failure. We deliberately do NOT rank by dependent count (that re-introduces the\n * popularity bias §2B exists to avoid); the caller gates on quality instead.\n */\nexport async function fetchDependencyNames(\n name: string,\n version: string,\n fetchImpl?: typeof fetch,\n): Promise<string[]> {\n const url = `https://${HOST}/v3/systems/npm/packages/${encodeName(name)}/versions/${encodeURIComponent(version)}:dependencies`;\n try {\n const { data } = await httpGetJson<any>(url, {\n host: HOST,\n ttlMs: CACHE_TTL.depsDev,\n fetchImpl,\n });\n const nodes: any[] = Array.isArray(data?.nodes) ? data.nodes : [];\n const names = nodes\n .map((n) => n?.versionKey?.name)\n .filter((n: unknown): n is string => typeof n === 'string' && n !== name);\n return [...new Set(names)];\n } catch {\n return [];\n }\n}\n\nexport async function fetchDepsDev(\n name: string,\n version: string | null,\n repo: { owner: string; repo: string } | null,\n fetchImpl?: typeof fetch,\n): Promise<DepsDevData> {\n const [scorecard, advisories] = await Promise.all([\n repo ? fetchScorecard(repo.owner, repo.repo, fetchImpl) : Promise.resolve(null),\n version ? fetchAdvisories(name, version, fetchImpl) : Promise.resolve([]),\n ]);\n return { scorecard, advisories };\n}\n","/**\n * Bundlephobia client (§9.5). Minified + gzipped size for frontend packages.\n * Strictly best-effort: this API is slow and flaky, so failures degrade to null\n * and never block ingestion (per R1 build decision). Cached aggressively (7d).\n */\nimport { CACHE_TTL } from '../../core/constants';\nimport { httpGetJson } from '../../core/http';\nimport { isFrontendCategory, type Category } from '../../core/types';\nimport type { BundlephobiaData } from '../types';\n\nconst HOST = 'bundlephobia.com';\n\nexport function parseBundleSize(json: any): number | null {\n const gzipBytes = json?.gzip;\n if (typeof gzipBytes !== 'number') return null;\n return Math.round((gzipBytes / 1024) * 10) / 10; // KB, 1 decimal\n}\n\n/**\n * Fetch bundle size — only for frontend categories (§9.5); returns null for\n * backend-only packages without making a request.\n */\nexport async function fetchBundlephobia(\n name: string,\n category: Category | null,\n fetchImpl?: typeof fetch,\n): Promise<BundlephobiaData> {\n if (!isFrontendCategory(category)) return { bundleMinGzipKb: null };\n\n const url = `https://${HOST}/api/size?package=${encodeURIComponent(name)}`;\n try {\n const { data } = await httpGetJson<any>(url, {\n host: HOST,\n ttlMs: CACHE_TTL.bundlephobia,\n timeoutMs: 12_000,\n retries: 1,\n fetchImpl,\n });\n return { bundleMinGzipKb: parseBundleSize(data) };\n } catch {\n return { bundleMinGzipKb: null };\n }\n}\n","export * from './npmRegistry';\nexport * from './npmSearch';\nexport * from './npmDownloads';\nexport * from './github';\nexport * from './depsDev';\nexport * from './bundlephobia';\n","/**\n * Assemble compat members for a set of package names: the fast path reads\n * metadata straight from the DB in one query; any name not tracked is fetched\n * on-demand (the HTTP layer caches packuments) so a single untracked package\n * doesn't blind the whole-architecture check. Names that can't be resolved at\n * all are returned as `unverified` rather than guessed.\n */\nimport type { Database } from '../db/client';\nimport { getCompatMetadata } from '../db/compat';\nimport { fetchNpmRegistry } from '../ingestion/sources';\nimport type { CompatMember } from './peerCompat';\n\nexport async function assembleMembers(\n db: Database,\n names: string[],\n): Promise<{ members: CompatMember[]; unverified: string[] }> {\n const tracked = new Map((await getCompatMetadata(db, names)).map((r) => [r.name, r]));\n const members: CompatMember[] = [];\n const unverified: string[] = [];\n\n await Promise.all(\n names.map(async (name) => {\n const row = tracked.get(name);\n if (row) {\n members.push({\n name,\n version: row.latestVersion,\n peerDependencies: row.peerDependencies,\n peerDependenciesMeta: row.peerDependenciesMeta,\n engines: row.engines,\n });\n return;\n }\n const reg = await fetchNpmRegistry(name).catch(() => null);\n if (reg) {\n members.push({\n name,\n version: reg.latestVersion,\n peerDependencies: reg.peerDependencies,\n peerDependenciesMeta: reg.peerDependenciesMeta,\n engines: reg.engines,\n });\n } else {\n unverified.push(name);\n }\n }),\n );\n\n return { members, unverified };\n}\n","/**\n * Tier-1 compatibility: whole-architecture peer-dependency + engine analysis.\n *\n * Deterministic and instant — no install. Works over the *entire set* at once:\n * it collects every package's declared `peerDependencies`, groups them by peer,\n * and checks the declared semver ranges agree. Two plugins that need `eslint@8`\n * vs `eslint@9` conflict even if eslint isn't pinned in the set.\n *\n * Sparse data degrades safely: a package with no declared peers contributes no\n * constraints (which is correct — most packages declare none), so \"not fully\n * recorded\" never produces a false conflict. Genuinely-untracked packages are\n * reported as `unverified` by the caller, not guessed at.\n */\nimport semver from 'semver';\nimport type { CompatConflict, DependencyRanges, PeerMeta } from '../core/types';\n\nexport interface CompatMember {\n name: string;\n /** Pinned (latest) version, or null if unknown. */\n version: string | null;\n peerDependencies: DependencyRanges | null;\n peerDependenciesMeta: PeerMeta | null;\n engines: DependencyRanges | null;\n}\n\ninterface PeerConstraint {\n requirer: string;\n peer: string;\n range: string;\n optional: boolean;\n}\n\n/** null = can't assert (invalid version/range). */\nfunction satisfiesRange(version: string, range: string): boolean | null {\n if (!semver.validRange(range)) return null;\n const v = semver.valid(version) ? version : semver.coerce(version)?.version;\n if (!v) return null;\n return semver.satisfies(v, range, { includePrerelease: true });\n}\n\nfunction rangesIntersect(a: string, b: string): boolean | null {\n if (!semver.validRange(a) || !semver.validRange(b)) return null;\n try {\n return semver.intersects(a, b, { includePrerelease: true });\n } catch {\n return null;\n }\n}\n\n/** All peer/engine conflicts across the set (empty = no Tier-1 conflict found). */\nexport function resolveArchitectureCompat(members: CompatMember[]): CompatConflict[] {\n const conflicts: CompatConflict[] = [];\n const pinned = new Map<string, string>();\n for (const m of members) if (m.version) pinned.set(m.name, m.version);\n\n const constraints: PeerConstraint[] = [];\n for (const m of members) {\n if (!m.peerDependencies) continue;\n for (const [peer, range] of Object.entries(m.peerDependencies)) {\n constraints.push({\n requirer: m.name,\n peer,\n range,\n optional: Boolean(m.peerDependenciesMeta?.[peer]?.optional),\n });\n }\n }\n\n // (1) A peer that's pinned in the set must satisfy each declared range.\n for (const c of constraints) {\n const pv = pinned.get(c.peer);\n if (pv && satisfiesRange(pv, c.range) === false) {\n conflicts.push({\n source: 'peer-deps',\n packages: [c.requirer, c.peer],\n detail: `${c.requirer} needs peer ${c.peer}@${c.range}, but the stack uses ${c.peer}@${pv}`,\n });\n }\n }\n\n // (2) A peer required by ≥2 members but not pinned: their ranges must overlap.\n const byPeer = new Map<string, PeerConstraint[]>();\n for (const c of constraints) {\n if (pinned.has(c.peer) || c.optional) continue;\n const arr = byPeer.get(c.peer);\n if (arr) arr.push(c);\n else byPeer.set(c.peer, [c]);\n }\n for (const [peer, cs] of byPeer) {\n for (let i = 0; i < cs.length; i++) {\n for (let j = i + 1; j < cs.length; j++) {\n if (cs[i]!.range !== cs[j]!.range && rangesIntersect(cs[i]!.range, cs[j]!.range) === false) {\n conflicts.push({\n source: 'peer-deps',\n packages: [cs[i]!.requirer, cs[j]!.requirer],\n detail: `${cs[i]!.requirer} needs ${peer}@${cs[i]!.range} but ${cs[j]!.requirer} needs ${peer}@${cs[j]!.range} — no overlapping version`,\n });\n }\n }\n }\n }\n\n // (3) Node engine ranges across the set must have a common solution.\n const nodeReqs = members\n .map((m) => ({ name: m.name, range: m.engines?.node }))\n .filter((r): r is { name: string; range: string } => typeof r.range === 'string');\n for (let i = 0; i < nodeReqs.length; i++) {\n for (let j = i + 1; j < nodeReqs.length; j++) {\n if (rangesIntersect(nodeReqs[i]!.range, nodeReqs[j]!.range) === false) {\n conflicts.push({\n source: 'engines',\n packages: [nodeReqs[i]!.name, nodeReqs[j]!.name],\n detail: `${nodeReqs[i]!.name} needs node ${nodeReqs[i]!.range} but ${nodeReqs[j]!.name} needs node ${nodeReqs[j]!.range} — no overlap`,\n });\n }\n }\n }\n\n return conflicts;\n}\n","/**\n * Whole-architecture compatibility check for a set of packages, shared by the\n * `compat` tool and `plan`. Tier 1 (peer-deps/engines, instant) + any recorded\n * Tier-2 sandbox conflicts. The result lists every member as name@version so\n * versions are explicit and the evidence stays structured for later scraping.\n */\nimport type { CompatConflict, CompatOutput } from '../core/types';\nimport type { Database } from '../db/client';\nimport { getCompatEdges } from '../db/compat';\nimport { assembleMembers } from './members';\nimport { resolveArchitectureCompat } from './peerCompat';\n\nexport async function checkCompat(db: Database, packages: string[]): Promise<CompatOutput> {\n const names = [...new Set(packages)];\n const { members, unverified } = await assembleMembers(db, names);\n\n const conflicts: CompatConflict[] = resolveArchitectureCompat(members);\n for (const edge of await getCompatEdges(db, names)) {\n if (edge.status === 'conflict') {\n conflicts.push({\n source: 'sandbox',\n packages: [edge.packageA, edge.packageB],\n detail: `${edge.packageA}@${edge.versionA} and ${edge.packageB}@${edge.versionB} failed to co-install in the sandbox`,\n });\n }\n }\n\n const overall = conflicts.length ? 'conflict' : unverified.length ? 'unknown' : 'compatible';\n return {\n packages: names,\n overall,\n conflicts,\n unverified,\n checked: members.map((m) => ({ name: m.name, version: m.version })),\n };\n}\n","/**\n * Read/write helpers for the `packages` table. All recommendation/eval reads use\n * this single denormalized table (§8.2).\n */\nimport { desc, eq, isNotNull } from 'drizzle-orm';\nimport type { Category } from '../core/types';\nimport type { VersionInfo } from '../ingestion/types';\nimport type { Database } from './client';\nimport {\n packageVersions,\n packages,\n seedPackages,\n syncRuns,\n type NewPackageRow,\n type SyncError,\n} from './schema';\n\n/** How many rows to insert per statement (stays well under Postgres' param cap). */\nconst VERSION_CHUNK = 500;\n\nexport async function getSeedTargets(\n db: Database,\n): Promise<{ name: string; category: Category | null }[]> {\n const rows = await db\n .select({ name: seedPackages.name, category: seedPackages.category })\n .from(seedPackages);\n return rows.map((r) => ({ name: r.name, category: r.category ?? null }));\n}\n\nexport async function getPackageByName(db: Database, name: string) {\n const rows = await db.select().from(packages).where(eq(packages.name, name)).limit(1);\n return rows[0] ?? null;\n}\n\n/** Every tracked package name — the set the `_changes` follower filters against. */\nexport async function getAllPackageNames(db: Database): Promise<string[]> {\n const rows = await db.select({ name: packages.name }).from(packages);\n return rows.map((r) => r.name);\n}\n\n/**\n * Store a package's version timeline. Idempotent — versions are immutable on\n * npm, so existing rows are left untouched. Chunked to respect the param cap.\n */\nexport async function upsertPackageVersions(\n db: Database,\n name: string,\n versions: VersionInfo[],\n): Promise<void> {\n if (versions.length === 0) return;\n for (let i = 0; i < versions.length; i += VERSION_CHUNK) {\n const rows = versions.slice(i, i + VERSION_CHUNK).map((v) => ({\n packageName: name,\n version: v.version,\n publishedAt: v.publishedAt,\n }));\n await db.insert(packageVersions).values(rows).onConflictDoNothing();\n }\n}\n\n/** A package's stored version timeline, newest first. */\nexport async function getPackageVersions(\n db: Database,\n name: string,\n limit = 50,\n): Promise<VersionInfo[]> {\n const rows = await db\n .select({ version: packageVersions.version, publishedAt: packageVersions.publishedAt })\n .from(packageVersions)\n .where(eq(packageVersions.packageName, name))\n .orderBy(desc(packageVersions.publishedAt))\n .limit(limit);\n return rows.map((r) => ({ version: r.version, publishedAt: r.publishedAt }));\n}\n\n/**\n * The most-downloaded tracked packages — the reference set typosquat detection\n * compares a queried name against. Capped (default 1000) so the per-verify\n * distance scan stays cheap.\n */\nexport async function getTopPackageNames(db: Database, limit = 1000): Promise<string[]> {\n const rows = await db\n .select({ name: packages.name })\n .from(packages)\n .where(isNotNull(packages.weeklyDownloads))\n .orderBy(desc(packages.weeklyDownloads))\n .limit(limit);\n return rows.map((r) => r.name);\n}\n\n/**\n * Promote a package into the curated seed list so future `sync` runs keep it\n * fresh. Used by the on-demand path (§12.5) to make organically-discovered\n * packages durable. No-op if already seeded — preserves the original category\n * and `added_at` rather than overwriting a hand-curated entry.\n */\nexport async function ensureSeedEntry(\n db: Database,\n name: string,\n category: Category | null,\n): Promise<void> {\n await db\n .insert(seedPackages)\n .values({ name, category })\n .onConflictDoNothing({ target: seedPackages.name });\n}\n\n/** Upsert a fully-computed package row, refreshing every field on conflict. */\nexport async function upsertPackage(db: Database, row: NewPackageRow): Promise<void> {\n const { name: _name, createdAt: _createdAt, ...mutable } = row;\n await db\n .insert(packages)\n .values(row)\n .onConflictDoUpdate({\n target: packages.name,\n set: { ...mutable, updatedAt: new Date() },\n });\n}\n\n// ── sync_runs audit ─────────────────────────────────────────────────────────\n\nexport async function startSyncRun(db: Database): Promise<number> {\n const [row] = await db\n .insert(syncRuns)\n .values({ status: 'running' })\n .returning({ id: syncRuns.id });\n return row!.id;\n}\n\nexport async function finishSyncRun(\n db: Database,\n id: number,\n data: {\n packagesSeen: number;\n packagesUpdated: number;\n errors: SyncError[];\n status: 'success' | 'partial' | 'failed';\n },\n): Promise<void> {\n await db\n .update(syncRuns)\n .set({\n finishedAt: new Date(),\n packagesSeen: data.packagesSeen,\n packagesUpdated: data.packagesUpdated,\n errors: data.errors,\n status: data.status,\n })\n .where(eq(syncRuns.id, id));\n}\n","/** Read/write helpers for sandbox verification results (`verification_runs`). */\nimport { and, desc, eq } from 'drizzle-orm';\nimport type { Database } from './client';\nimport {\n verificationRuns,\n type NewVerificationRunRow,\n type VerificationRunRow,\n} from './schema';\n\nexport async function storeVerificationRun(\n db: Database,\n run: NewVerificationRunRow,\n): Promise<void> {\n await db.insert(verificationRuns).values(run);\n}\n\n/** Most recent run for a package (any version), if any — for the evaluate verdict. */\nexport async function getLatestVerificationByName(\n db: Database,\n packageName: string,\n): Promise<VerificationRunRow | null> {\n const rows = await db\n .select()\n .from(verificationRuns)\n .where(eq(verificationRuns.packageName, packageName))\n .orderBy(desc(verificationRuns.ranAt))\n .limit(1);\n return rows[0] ?? null;\n}\n\n/** Most recent run for a package version (any module system), if any. */\nexport async function getLatestVerification(\n db: Database,\n packageName: string,\n version: string,\n): Promise<VerificationRunRow | null> {\n const rows = await db\n .select()\n .from(verificationRuns)\n .where(\n and(eq(verificationRuns.packageName, packageName), eq(verificationRuns.version, version)),\n )\n .orderBy(desc(verificationRuns.ranAt))\n .limit(1);\n return rows[0] ?? null;\n}\n","/** Write helper for recommendation→outcome capture (`recommendation_outcomes`, §3.1). */\nimport type { Database } from './client';\nimport { recommendationOutcomes, type NewRecommendationOutcomeRow } from './schema';\n\n/** Record one opt-in outcome. Insert-only — the dataset is append-only by design. */\nexport async function recordOutcome(\n db: Database,\n outcome: NewRecommendationOutcomeRow,\n): Promise<void> {\n await db.insert(recommendationOutcomes).values(outcome);\n}\n","{\n \"moment\": {\n \"replacedBy\": \"dayjs\",\n \"reason\": \"In maintenance mode since 2020 (the maintainers recommend alternatives). dayjs is a ~2KB immutable library with a near-identical API.\"\n },\n \"request\": {\n \"replacedBy\": \"got\",\n \"reason\": \"Deprecated in 2020 and no longer maintained. Use the built-in fetch, or got for a full-featured HTTP client.\"\n },\n \"request-promise\": {\n \"replacedBy\": \"got\",\n \"reason\": \"Deprecated alongside request. got returns promises natively.\"\n },\n \"node-sass\": {\n \"replacedBy\": \"sass\",\n \"reason\": \"Deprecated; bindings break on new Node versions. sass is the Dart implementation (sass-embedded for speed).\"\n },\n \"tslint\": {\n \"replacedBy\": \"typescript-eslint\",\n \"reason\": \"Deprecated in 2019 in favor of ESLint. Use typescript-eslint to lint TypeScript.\"\n },\n \"enzyme\": {\n \"replacedBy\": \"@testing-library/react\",\n \"reason\": \"Unmaintained with no official React 17+/18 adapter. React Testing Library is the current standard.\"\n },\n \"protractor\": {\n \"replacedBy\": \"@playwright/test\",\n \"reason\": \"Reached end-of-life in 2023. Use Playwright (or Cypress) for browser E2E.\"\n },\n \"faker\": {\n \"replacedBy\": \"@faker-js/faker\",\n \"reason\": \"The original package was sabotaged and deprecated. @faker-js/faker is the community-maintained fork.\"\n },\n \"bower\": {\n \"replacedBy\": \"npm\",\n \"reason\": \"Deprecated; front-end packages ship on npm now. Use npm (or your package manager) directly.\"\n },\n \"popper.js\": {\n \"replacedBy\": \"@popperjs/core\",\n \"reason\": \"v1 is deprecated. @popperjs/core is the maintained v2 line.\"\n },\n \"create-react-app\": {\n \"replacedBy\": \"vite\",\n \"reason\": \"No longer recommended by the React team and effectively unmaintained. Vite is the current scaffolding standard.\"\n },\n \"babel-eslint\": {\n \"replacedBy\": \"@babel/eslint-parser\",\n \"reason\": \"Deprecated and renamed. Use @babel/eslint-parser.\"\n },\n \"istanbul\": {\n \"replacedBy\": \"nyc\",\n \"reason\": \"The istanbul package is legacy; nyc is its maintained CLI (or c8 for native V8 coverage).\"\n }\n}\n","/**\n * Deprecation → replacement map (§1.2). Agents confidently recommend dead\n * packages (moment, request, …) because their training data froze when those\n * were popular; lurq's freshness is exactly the corrective. This is the curated\n * seed the roadmap calls for — a small, high-confidence set of genuinely\n * superseded packages. Later this graph is learned from outcome data (§3.1);\n * for now it's hand-verified so `evaluate` never steers an agent wrong.\n */\nimport successors from '../data/successors.json';\n\nexport interface Successor {\n /** The package to migrate to. */\n name: string;\n /** Why the original is dead and this replaces it. */\n reason: string;\n}\n\nconst MAP = successors as Record<string, { replacedBy: string; reason: string }>;\n\n/** The recommended successor for a superseded package, or null if it isn't one. */\nexport function lookupSuccessor(name: string): Successor | null {\n const hit = MAP[name.toLowerCase()];\n return hit ? { name: hit.replacedBy, reason: hit.reason } : null;\n}\n","/**\n * GitHub raw README fallback (§9.6). The npm packument `readme` field is often\n * empty (e.g. zod), so we fetch the repo README directly when needed. Public\n * raw content needs no token.\n */\nimport { CACHE_TTL } from '../../core/constants';\nimport { httpRequest } from '../../core/http';\n\nconst HOST = 'raw.githubusercontent.com';\nconst CANDIDATES = ['README.md', 'readme.md', 'README.markdown', 'README'];\n\nexport async function fetchGithubReadme(\n owner: string,\n repo: string,\n fetchImpl?: typeof fetch,\n): Promise<string | null> {\n for (const file of CANDIDATES) {\n const url = `https://${HOST}/${owner}/${repo}/HEAD/${file}`;\n try {\n const { data } = await httpRequest<string>(url, {\n host: HOST,\n ttlMs: CACHE_TTL.github,\n accept: 'text',\n retries: 0,\n fetchImpl,\n });\n if (data && data.trim().length > 0) return data;\n } catch {\n /* try the next candidate */\n }\n }\n return null;\n}\n","/**\n * Summary + usage-guide generation (§9.6 + R1 explainer refinement).\n *\n * lurq generates its OWN guide grounded in the package's README/description —\n * it never depends on Context7. When a summary LLM key is configured we use it;\n * otherwise we fall back to the npm description + a category-derived guide,\n * fabricating nothing. The exact current API is deferred to Context7 via a hint.\n */\nimport { CATEGORIES, isCategory, type Category, type UsageGuide } from '../core/types';\nimport { getConfig } from '../core/config';\nimport { httpRequest } from '../core/http';\nimport { logger } from '../core/logger';\nimport { fetchGithubReadme } from './sources/githubReadme';\nimport type { RawPackageSignals } from './types';\n\nexport interface SummaryInput {\n name: string;\n description: string | null;\n category: Category | null;\n readme: string | null;\n repoUrl: string | null;\n}\n\nexport interface SummaryResult {\n summary: string | null;\n usageGuide: UsageGuide;\n /** Taxonomy category the LLM classified the package into (§2A), or null\n * (always null for the fallback provider — it does no classification). */\n inferredCategory: Category | null;\n}\n\nexport interface SummaryProvider {\n readonly kind: 'openai' | 'fallback';\n generate(input: SummaryInput): Promise<SummaryResult>;\n}\n\n/** Human-readable architectural role per category (generic — lurq has no code context). */\nconst CATEGORY_ROLE: Record<string, string> = {\n framework: 'the core application framework your app is built on',\n 'meta-framework': 'the full-stack framework wrapping routing, rendering, and build',\n 'state-management': 'the client state layer shared across components',\n routing: 'the routing layer mapping URLs to views',\n orm: 'the data-access layer between your code and the database',\n 'database-client': 'the low-level driver that talks to your database',\n 'ui-component-library': 'the prebuilt UI component layer',\n styling: 'the styling layer for your components',\n forms: 'form state and submission handling',\n validation: 'input/schema validation at your boundaries',\n 'data-fetching': 'the server-state/data-fetching layer',\n 'http-client': 'the HTTP request layer for calling APIs',\n auth: 'authentication and session handling',\n testing: 'the test tooling layer',\n 'build-tool': 'the build/dev pipeline',\n bundler: 'the module bundling step',\n linting: 'code-quality and formatting checks',\n 'date-time': 'date and time handling',\n animation: 'UI animation and motion',\n charts: 'data visualization and charts',\n i18n: 'internationalization and localization',\n utility: 'a focused helper you compose into your app',\n other: 'a supporting library in your app',\n};\n\nfunction context7Hint(name: string): string {\n return `For the exact current API of \"${name}\", resolve it via Context7 (resolve-library-id → query-docs).`;\n}\n\n/** Keep text to ~`max` sentences. */\nexport function truncateSentences(text: string, max = 3): string {\n const clean = text.replace(/\\s+/g, ' ').trim();\n if (!clean) return '';\n // Match full sentences, plus a trailing fragment with no terminal punctuation\n // (so descriptions without a period return the whole text, not just the last word).\n const sentences = clean.match(/[^.!?]+[.!?]+|[^.!?]+$/g) ?? [clean];\n return sentences\n .slice(0, max)\n .map((s) => s.trim())\n .join(' ')\n .trim();\n}\n\n// ── Fallback provider (no LLM key) ──────────────────────────────────────────\n\nexport class FallbackSummaryProvider implements SummaryProvider {\n readonly kind = 'fallback' as const;\n\n async generate(input: SummaryInput): Promise<SummaryResult> {\n const description = input.description?.trim() || null;\n const role = CATEGORY_ROLE[input.category ?? 'other'] ?? CATEGORY_ROLE.other!;\n const summary = description ? truncateSentences(description, 3) : null;\n const guide: UsageGuide = {\n whatItIs: description ? truncateSentences(description, 2) : input.name,\n whenToUse: `Reach for ${input.name} when you need ${role}.`,\n whereItFits: `Sits at ${role}.`,\n context7Hint: context7Hint(input.name),\n };\n return { summary, usageGuide: guide, inferredCategory: null };\n }\n}\n\n// ── OpenAI provider (raw fetch, no SDK dependency) ──────────────────────────\n\nconst SYSTEM_PROMPT =\n 'You summarize npm packages factually for an AI coding agent choosing dependencies. ' +\n 'Use ONLY the provided README/description. Never invent capabilities or APIs. ' +\n 'Be concise and concrete. Respond with a JSON object.';\n\nfunction buildUserPrompt(input: SummaryInput): string {\n const readme = (input.readme ?? '').slice(0, 4000);\n // Ask the model to classify only when we don't already have a curated category\n // (§2A) — otherwise the curated value wins and we save the model the choice.\n const needsCategory = input.category == null;\n return [\n `Package: ${input.name}`,\n `Category: ${input.category ?? 'unknown'}`,\n `Description: ${input.description ?? '(none)'}`,\n `README (truncated):\\n${readme || '(none)'}`,\n '',\n 'Return JSON with keys:',\n '- \"summary\": 2-3 sentences: what it is, when to use it, how it fits an app.',\n '- \"whatItIs\": one sentence.',\n '- \"whenToUse\": one sentence on the ideal use case.',\n '- \"whenNotToUse\": one sentence on when to pick something else (or \"\").',\n '- \"whereItFits\": one sentence on its architectural role.',\n '- \"howToWireIn\": one short sentence on the minimal setup (install + entry point), or \"\".',\n ...(needsCategory\n ? [`- \"category\": the single best fit from this list: ${CATEGORIES.join(', ')}.`]\n : []),\n ].join('\\n');\n}\n\nexport class OpenAISummaryProvider implements SummaryProvider {\n readonly kind = 'openai' as const;\n\n private readonly endpoint: string;\n private readonly host: string;\n\n constructor(\n private readonly apiKey: string,\n private readonly model: string,\n baseUrl: string,\n private readonly fetchImpl?: typeof fetch,\n ) {\n this.endpoint = `${baseUrl.replace(/\\/$/, '')}/chat/completions`;\n this.host = new URL(baseUrl).host;\n }\n\n async generate(input: SummaryInput): Promise<SummaryResult> {\n try {\n const body = JSON.stringify({\n model: this.model,\n messages: [\n { role: 'system', content: SYSTEM_PROMPT },\n { role: 'user', content: buildUserPrompt(input) },\n ],\n response_format: { type: 'json_object' },\n temperature: 0.2,\n });\n const { data } = await httpRequest<any>(this.endpoint, {\n host: this.host,\n method: 'POST',\n ttlMs: 30 * 24 * 60 * 60 * 1000, // cache summaries 30d to control cost\n cacheKey: `openai-summary ${this.model} ${input.name} ${(input.readme ?? '').length}`,\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n 'Content-Type': 'application/json',\n },\n body,\n fetchImpl: this.fetchImpl,\n });\n const content = data?.choices?.[0]?.message?.content;\n const parsed = content ? JSON.parse(content) : {};\n const guide: UsageGuide = {\n whatItIs: str(parsed.whatItIs) || input.name,\n whenToUse: str(parsed.whenToUse),\n whenNotToUse: str(parsed.whenNotToUse) || undefined,\n whereItFits: str(parsed.whereItFits),\n howToWireIn: str(parsed.howToWireIn) || undefined,\n context7Hint: context7Hint(input.name),\n };\n const rawCategory = str(parsed.category);\n const inferredCategory = rawCategory && isCategory(rawCategory) ? rawCategory : null;\n return {\n summary: str(parsed.summary) ? truncateSentences(parsed.summary, 3) : null,\n usageGuide: guide,\n inferredCategory,\n };\n } catch (err) {\n logger.warn(`summary LLM failed for ${input.name}, using fallback: ${(err as Error).message}`);\n return new FallbackSummaryProvider().generate(input);\n }\n }\n}\n\nfunction str(value: unknown): string {\n return typeof value === 'string' ? value.trim() : '';\n}\n\n// ── Factory + input assembly ────────────────────────────────────────────────\n\nexport function createSummaryProvider(fetchImpl?: typeof fetch): SummaryProvider {\n const config = getConfig();\n if (config.SUMMARY_PROVIDER === 'openai' && config.SUMMARY_API_KEY) {\n return new OpenAISummaryProvider(\n config.SUMMARY_API_KEY,\n config.SUMMARY_MODEL,\n config.SUMMARY_BASE_URL,\n fetchImpl,\n );\n }\n return new FallbackSummaryProvider();\n}\n\n/** Assemble the summary input, fetching the GitHub-raw README when npm's is empty. */\nexport async function buildSummaryInput(\n signals: RawPackageSignals,\n category: Category | null,\n fetchImpl?: typeof fetch,\n): Promise<SummaryInput> {\n const registry = signals.registry;\n let readme = registry?.readme?.trim() || null;\n if (!readme && registry?.repo) {\n readme = await fetchGithubReadme(registry.repo.owner, registry.repo.repo, fetchImpl).catch(\n () => null,\n );\n }\n return {\n name: signals.name,\n description: registry?.description ?? null,\n category,\n readme,\n repoUrl: registry?.repoUrl ?? null,\n };\n}\n","/**\n * Gather all source signals for one package (§9.7 steps 1–5). Fault-isolated:\n * each source is wrapped so a single failure records an error and degrades that\n * signal to null rather than failing the package (§17).\n */\nimport { logger } from '../core/logger';\nimport type { Category } from '../core/types';\nimport { fetchBundlephobia } from './sources/bundlephobia';\nimport { fetchDepsDev } from './sources/depsDev';\nimport { fetchGithubRepo } from './sources/github';\nimport { fetchDownloadGrowth, fetchWeeklyDownloads } from './sources/npmDownloads';\nimport { fetchNpmRegistry } from './sources/npmRegistry';\nimport type { NpmDownloadsData, RawPackageSignals } from './types';\n\nexport interface CollectDeps {\n githubToken?: string;\n fetchImpl?: typeof fetch;\n /**\n * Pre-fetched weekly downloads (from the bulk endpoint). When provided (even\n * as null), the per-package weekly fetch is skipped — avoiding the downloads\n * API's harsh rate limits during a full sync.\n */\n prefetchedWeekly?: number | null;\n}\n\nasync function attempt<T>(\n source: string,\n errors: { source: string; message: string }[],\n fn: () => Promise<T>,\n): Promise<T | null> {\n try {\n return await fn();\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n errors.push({ source, message });\n logger.debug(`[${source}] ${message}`);\n return null;\n }\n}\n\nexport async function collectSignals(\n name: string,\n category: Category | null,\n deps: CollectDeps = {},\n): Promise<RawPackageSignals> {\n const { githubToken, fetchImpl } = deps;\n const errors: { source: string; message: string }[] = [];\n\n // 1. Registry first — it provides the repo + version the other sources need.\n const registry = await attempt('npm-registry', errors, () => fetchNpmRegistry(name, fetchImpl));\n\n const repo = registry?.repo ?? null;\n const version = registry?.latestVersion ?? null;\n\n // 2–5. The rest run concurrently.\n const [downloads, github, depsDev, bundle] = await Promise.all([\n attempt('npm-downloads', errors, async (): Promise<NpmDownloadsData> => {\n const weeklyDownloads =\n deps.prefetchedWeekly !== undefined\n ? deps.prefetchedWeekly\n : await fetchWeeklyDownloads(name, fetchImpl);\n const downloadGrowth90d = await fetchDownloadGrowth(name, fetchImpl);\n return { weeklyDownloads, downloadGrowth90d };\n }),\n repo && githubToken\n ? attempt('github', errors, () => fetchGithubRepo(repo.owner, repo.repo, githubToken, fetchImpl))\n : Promise.resolve(null),\n attempt('deps-dev', errors, () => fetchDepsDev(name, version, repo, fetchImpl)),\n attempt('bundlephobia', errors, () => fetchBundlephobia(name, category, fetchImpl)),\n ]);\n\n return { name, registry, downloads, github, depsDev, bundle, errors };\n}\n","/**\n * Lightweight category inference (§11). Maps a natural-language need to a\n * taxonomy category via keyword matching. Returns null when uncertain, so the\n * caller searches across all categories rather than over-filtering.\n */\nimport type { Category } from '../core/types';\nimport type { RawPackageSignals } from '../ingestion/types';\n\nconst RULES: { category: Category; patterns: RegExp }[] = [\n { category: 'meta-framework', patterns: /\\b(meta-?framework|next\\.?js|nuxt|remix|astro|gatsby|sveltekit|full-?stack framework)\\b/ },\n { category: 'state-management', patterns: /\\b(state management|global state|store|redux|zustand|jotai|mobx|atoms?)\\b/ },\n { category: 'routing', patterns: /\\b(rout(e|er|ing)|navigation|url matching)\\b/ },\n { category: 'orm', patterns: /\\b(orm|object-?relational|query builder|prisma|drizzle|sequelize|typeorm)\\b/ },\n { category: 'database-client', patterns: /\\b(database (driver|client)|postgres|mysql|mongo(db)?|redis|sqlite|db driver)\\b/ },\n { category: 'ui-component-library', patterns: /\\b(component library|ui kit|ui components?|design system|buttons?|modal|dialog)\\b/ },\n { category: 'styling', patterns: /\\b(styl(e|ing)|css|tailwind|sass|scss|class ?names?|theme)\\b/ },\n { category: 'forms', patterns: /\\b(forms?|form (state|library|handling)|input handling)\\b/ },\n { category: 'validation', patterns: /\\b(validat(e|ion|or)|schema|parse input|type ?safe parsing)\\b/ },\n { category: 'data-fetching', patterns: /\\b(data fetching|server state|react query|swr|graphql client|caching queries)\\b/ },\n { category: 'http-client', patterns: /\\b(http client|fetch wrapper|rest client|make (a )?request|ajax|api calls?)\\b/ },\n { category: 'auth', patterns: /\\b(auth(entication|orization)?|login|session|jwt|oauth|password hashing)\\b/ },\n { category: 'testing', patterns: /\\b(test(ing|s)?|unit test|e2e|assertion|mocking|test runner)\\b/ },\n { category: 'bundler', patterns: /\\b(bundler|bundle (modules?|code)|webpack|rollup|esbuild|parcel)\\b/ },\n { category: 'build-tool', patterns: /\\b(build tool|dev server|monorepo|task runner|compile|transpile)\\b/ },\n // date-time precedes linting: \"date formatting\" must not be captured by linting's\n // bare \"formatting\" token before the date rule is reached (first-match-wins).\n { category: 'date-time', patterns: /\\b(dates?|date ?time|time(zone)?s?|calendar|parse dates?|format dates?)\\b/ },\n { category: 'linting', patterns: /\\b(lint(er|ing)?|formatter|formatting|code (quality|style|format)|prettier|eslint)\\b/ },\n { category: 'animation', patterns: /\\b(animat(e|ion)|motion|transition|spring|gsap|3d)\\b/ },\n { category: 'charts', patterns: /\\b(charts?|graphs?|data ?vis(ualization)?|plots?|dashboards?)\\b/ },\n { category: 'i18n', patterns: /\\b(i18n|internationali[sz]ation|localization|translat(e|ion)|locale)\\b/ },\n { category: 'framework', patterns: /\\b(framework|react|vue|svelte|angular|web server|backend framework)\\b/ },\n { category: 'utility', patterns: /\\b(debounce|throttle|deep ?clone|slugify|uuid|util(ity|ities)?|helper|lodash|retry)\\b/ },\n];\n\nexport function inferCategory(need: string): Category | null {\n const text = need.toLowerCase();\n for (const rule of RULES) {\n if (rule.patterns.test(text)) return rule.category;\n }\n return null;\n}\n\n/**\n * Categorize-on-ingest (§2A): infer a category from a package's *own* text —\n * name, keywords, description, and the README head — instead of a user query.\n * Keywords are repeated to give them extra weight (they're the most reliable\n * categorical signal). Returns null when no rule matches; the caller then falls\n * back to the LLM classifier or leaves the category null.\n */\nexport function inferCategoryFromSignals(signals: RawPackageSignals): Category | null {\n const r = signals.registry;\n const keywords = (r?.keywords ?? []).join(' ');\n const text = [\n signals.name,\n keywords,\n keywords, // weight keywords higher via repetition\n r?.description ?? '',\n (r?.readme ?? '').slice(0, 600),\n ]\n .filter(Boolean)\n .join(' ');\n return inferCategory(text);\n}\n","/**\n * Locate package-relative resources at runtime. Works in dev (tsx, source under\n * src/) and when published (bundled under dist/), by walking up from this module\n * until a directory containing package.json is found.\n */\nimport { existsSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nlet cachedRoot: string | undefined;\n\n/** Absolute path to the installed lurq package root (the dir with package.json). */\nexport function packageRoot(): string {\n if (cachedRoot) return cachedRoot;\n let dir = dirname(fileURLToPath(import.meta.url));\n // Walk up to the filesystem root looking for our package.json.\n for (;;) {\n if (existsSync(join(dir, 'package.json'))) {\n cachedRoot = dir;\n return dir;\n }\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n // Fallback: current working directory.\n cachedRoot = process.cwd();\n return cachedRoot;\n}\n\n/** Folder holding generated Drizzle migrations. */\nexport function migrationsDir(): string {\n return join(packageRoot(), 'drizzle');\n}\n\n/** The curated seed list shipped with the package. */\nexport function seedJsonPath(): string {\n return join(packageRoot(), 'src', 'data', 'seed.json');\n}\n\n/** User-level weight-override config (§4): `~/.config/lurq/weights.json`. */\nexport function userWeightsPath(): string {\n const base = process.env.XDG_CONFIG_HOME || join(homedir(), '.config');\n return join(base, 'lurq', 'weights.json');\n}\n\n/** Project-local weight-override config (§4): `.lurq/weights.json` in the cwd.\n * Takes precedence over the user-level file when present. */\nexport function projectWeightsPath(): string {\n return join(process.cwd(), '.lurq', 'weights.json');\n}\n","/**\n * All scoring weights and thresholds in one tunable file (§10).\n * Changing the model means editing this file only.\n */\n\n/** Composite health-score weights. Must sum to 1.0. */\nexport const HEALTH_WEIGHTS = {\n maintenance: 0.35,\n adoption: 0.3,\n reliability: 0.25,\n efficiency: 0.1,\n} as const;\n\n/**\n * Health↔Quality blend for the default composite sort (§1). Quality is a\n * standalone, adoption-independent axis — NOT a member of HEALTH_WEIGHTS. The\n * two only blend here, for ranking/sort: composite = (1−λ)·health + λ·quality.\n * λ is the single most impactful knob `edit-weights` exposes.\n */\nexport const COMPOSITE = {\n lambda: 0.35,\n} as const;\n\n/**\n * Quality sub-score component weights (of the *available* components — missing\n * signals are dropped, not zeroed, via weightedAverage). All inputs are\n * adoption-independent: they measure how well-built a package is, not how many\n * people use it.\n */\nexport const QUALITY_WEIGHTS = {\n types: 0.25,\n tests: 0.2,\n docs: 0.2,\n changelog: 0.1,\n deps: 0.1,\n license: 0.1,\n provenance: 0.05,\n} as const;\n\nexport const QUALITY = {\n /** README at/above this many characters scores full marks on doc length. */\n docsFullLengthChars: 1200,\n /** Direct-dependency count at/above this scores 0 on the deps component (log-scaled). */\n depsLogMax: 30,\n /** A license string present but not OSI-recognized scores this (vs 100 / 0). */\n licenseUnrecognizedScore: 60,\n} as const;\n\n/** Maintenance sub-score component weights (of the available components). */\nexport const MAINTENANCE_WEIGHTS = {\n recency: 0.5,\n cadence: 0.25,\n closeRatio: 0.25,\n} as const;\n\nexport const MAINTENANCE = {\n /** A release within this many days scores full recency. */\n freshDays: 30,\n /** Recency decays linearly to 0 by this many days (~24 months). */\n staleDays: 730,\n /** Releases/12mo at or above this cap full cadence. */\n cadenceCap: 12,\n /** deprecated/archived hard-cap maintenance at this value. */\n deadCap: 15,\n} as const;\n\nexport const ADOPTION = {\n /** log10(weekly downloads): this maps to 0. */\n downloadsLogMin: 1, // 10/wk\n /** log10(weekly downloads): this maps to 100. */\n downloadsLogMax: 7, // 10M/wk\n /** log10(stars) that maps to 100. */\n starsLogMax: 5, // 100k stars\n /** Weight of the stars component when available (downloads gets the rest). */\n starsWeight: 0.2,\n /** Growth bonus: growth fraction × this, clamped to ±cap. */\n growthMultiplier: 30,\n growthBonusCap: 20,\n} as const;\n\nexport const RELIABILITY = {\n /** Used when no Scorecard is available (unknown security posture). */\n neutralWhenUnknown: 50,\n /** Advisory penalties by severity. */\n penalty: {\n critical: 40,\n high: 20,\n moderate: 8,\n low: 3,\n info: 0,\n },\n} as const;\n\nexport const EFFICIENCY = {\n /** Bundle size at the category median maps to this score; smaller → higher. */\n medianScore: 50,\n} as const;\n\n/** Proactive-discovery crawler tuning (§2B). The gate is quality-only — downloads\n * are deliberately excluded so merit, not popularity, decides what graduates. */\nexport const DISCOVERY = {\n /** A queued candidate must clear this quality pre-score to graduate to ingest. */\n minPreScore: 45,\n /** Max candidates fully ingested per crawler run (cost bound). */\n perRunCap: 25,\n /** npm-search hits to pull per category keyword. */\n searchSizePerCategory: 10,\n /** Max dependency-graph neighbors to enqueue per tracked seed. */\n graphNeighborsPerSeed: 20,\n} as const;\n\n// ── Tunable weight model: defaults ← user-config ← env (§4) ──────────────────\n\nimport { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport { projectWeightsPath, userWeightsPath } from '../core/paths';\n\n/** The user-tunable slice of the model (§4). Sub-component weights and\n * thresholds stay fixed; these are the knobs `edit-weights` exposes. */\nexport interface WeightConfig {\n health: {\n maintenance: number;\n adoption: number;\n reliability: number;\n efficiency: number;\n };\n /** Health↔Quality blend λ for the default sort composite. */\n composite: { lambda: number };\n}\n\nexport const DEFAULT_WEIGHTS: WeightConfig = {\n health: { ...HEALTH_WEIGHTS },\n composite: { ...COMPOSITE },\n};\n\nexport type WeightSource = 'defaults' | 'user-config' | 'project-config';\n\n/** Where overrides are read from, if anywhere — for `lurq weights` to report. */\nexport function activeWeightsPath(): { path: string; source: WeightSource } | null {\n if (existsSync(projectWeightsPath())) return { path: projectWeightsPath(), source: 'project-config' };\n if (existsSync(userWeightsPath())) return { path: userWeightsPath(), source: 'user-config' };\n return null;\n}\n\nlet cachedWeights: WeightConfig | undefined;\n\n/**\n * Resolve the effective weight model: defaults, overlaid by a config file\n * (project-local wins over user-level), overlaid by env (`LURQ_COMPOSITE_LAMBDA`).\n * Always returns a validated, sum-to-1 health block. Memoized; call\n * `resetWeightsCache()` after a write or in tests.\n */\nexport function loadWeights(): WeightConfig {\n if (cachedWeights) return cachedWeights;\n\n let merged: WeightConfig = structuredClone(DEFAULT_WEIGHTS);\n const active = activeWeightsPath();\n if (active) {\n try {\n const fromFile = JSON.parse(readFileSync(active.path, 'utf8')) as Partial<WeightConfig>;\n merged = mergeWeights(merged, fromFile);\n } catch {\n // A corrupt override file must never break scoring — fall back to defaults.\n }\n }\n\n const envLambda = process.env.LURQ_COMPOSITE_LAMBDA;\n if (envLambda !== undefined && envLambda !== '') {\n const n = Number(envLambda);\n if (Number.isFinite(n)) merged.composite.lambda = n;\n }\n\n cachedWeights = validateWeights(merged).weights;\n return cachedWeights;\n}\n\nexport function resetWeightsCache(): void {\n cachedWeights = undefined;\n}\n\nfunction mergeWeights(base: WeightConfig, over: Partial<WeightConfig>): WeightConfig {\n return {\n health: { ...base.health, ...(over.health ?? {}) },\n composite: { ...base.composite, ...(over.composite ?? {}) },\n };\n}\n\nexport interface WeightValidation {\n weights: WeightConfig;\n /** True if the health block was renormalized to sum to 1.0. */\n normalized: boolean;\n}\n\n/**\n * Clamp λ to [0,1] and renormalize the health block to sum to 1.0 (§4 invariant,\n * weights.ts:6). Returns the cleaned weights and whether normalization happened\n * so the CLI can report it.\n */\nexport function validateWeights(w: WeightConfig): WeightValidation {\n const lambda = Math.max(0, Math.min(1, w.composite.lambda));\n const h = w.health;\n const sum = h.maintenance + h.adoption + h.reliability + h.efficiency;\n let normalized = false;\n let health = h;\n if (sum <= 0) {\n health = { ...DEFAULT_WEIGHTS.health };\n normalized = true;\n } else if (Math.abs(sum - 1) > 1e-6) {\n health = {\n maintenance: h.maintenance / sum,\n adoption: h.adoption / sum,\n reliability: h.reliability / sum,\n efficiency: h.efficiency / sum,\n };\n normalized = true;\n }\n return { weights: { health, composite: { lambda } }, normalized };\n}\n\n/** Keys settable via `edit-weights --set` and their slot in the config. */\nconst SETTABLE: Record<string, (w: WeightConfig, v: number) => void> = {\n 'health.maintenance': (w, v) => (w.health.maintenance = v),\n 'health.adoption': (w, v) => (w.health.adoption = v),\n 'health.reliability': (w, v) => (w.health.reliability = v),\n 'health.efficiency': (w, v) => (w.health.efficiency = v),\n 'composite.lambda': (w, v) => (w.composite.lambda = v),\n};\n\nexport function settableKeys(): string[] {\n return Object.keys(SETTABLE);\n}\n\n/** Apply `key=value` overrides to a config, returning a new config. Throws on an\n * unknown key or non-numeric value. */\nexport function applyOverrides(base: WeightConfig, sets: string[]): WeightConfig {\n const next = structuredClone(base);\n for (const entry of sets) {\n const eq = entry.indexOf('=');\n if (eq < 0) throw new Error(`Invalid --set \"${entry}\" (expected key=value).`);\n const key = entry.slice(0, eq).trim();\n const value = Number(entry.slice(eq + 1).trim());\n const apply = SETTABLE[key];\n if (!apply) {\n throw new Error(`Unknown weight key \"${key}\". Settable: ${settableKeys().join(', ')}.`);\n }\n if (!Number.isFinite(value)) throw new Error(`Value for \"${key}\" must be a number.`);\n apply(next, value);\n }\n return next;\n}\n\n/** Persist a config to the override file and bust the cache. */\nexport function saveWeights(w: WeightConfig, scope: 'user' | 'project' = 'user'): string {\n const path = scope === 'project' ? projectWeightsPath() : userWeightsPath();\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, JSON.stringify(w, null, 2) + '\\n', 'utf8');\n resetWeightsCache();\n return path;\n}\n\n/** Remove any override files, restoring defaults. Returns the paths removed. */\nexport function resetWeights(): string[] {\n const removed: string[] = [];\n for (const path of [projectWeightsPath(), userWeightsPath()]) {\n if (existsSync(path)) {\n rmSync(path);\n removed.push(path);\n }\n }\n resetWeightsCache();\n return removed;\n}\n\n/** Human-readable explanation per health component / knob (§4 `--explain`). */\nexport const WEIGHT_EXPLANATIONS: Record<string, string> = {\n maintenance: 'release recency, cadence, and issue close-ratio (weights.ts MAINTENANCE_WEIGHTS).',\n adoption: 'weekly downloads (log-scaled), stars, and 90-day growth (weights.ts ADOPTION).',\n reliability: 'OpenSSF Scorecard scaled 0–100, minus advisory penalties (weights.ts RELIABILITY).',\n efficiency: 'bundle size vs the category median; frontend categories only (weights.ts EFFICIENCY).',\n quality:\n 'intrinsic, adoption-independent: types, tests, docs, changelog, deps, license, provenance (weights.ts QUALITY_WEIGHTS). A standalone axis — it does NOT feed health.',\n lambda: 'how much the default sort composite favors quality over health: (1−λ)·health + λ·quality.',\n};\n\n/** Confidence-label thresholds (§10, §1). */\nexport const CONFIDENCE = {\n proven: {\n minWeeklyDownloads: 100_000,\n minAgeMonths: 12,\n maxLastReleaseMonths: 6,\n },\n emerging: {\n minWeeklyDownloads: 5_000,\n strongGrowth: 0.5,\n maxLastReleaseMonths: 9,\n },\n /** `promising` (§1): new but intrinsically high-quality, regardless of adoption. */\n promising: {\n minQuality: 70,\n maxLastReleaseMonths: 12,\n },\n} as const;\n","/**\n * Scoring & confidence model (§10). All functions are pure and take an explicit\n * `now` for deterministic testing.\n *\n * Two-pass design: maintenance / adoption / reliability / confidence depend only\n * on a single package, so they're computed in pass 1. Efficiency needs the\n * category median bundle size (§10), so it — and the composite health score —\n * are computed in pass 2 once all packages are collected.\n */\nimport type { Advisory, Category, Confidence, ScoreBreakdown } from '../core/types';\nimport { isFrontendCategory } from '../core/types';\nimport type { RawPackageSignals } from '../ingestion/types';\nimport {\n ADOPTION,\n COMPOSITE,\n CONFIDENCE,\n EFFICIENCY,\n HEALTH_WEIGHTS,\n MAINTENANCE,\n MAINTENANCE_WEIGHTS,\n QUALITY,\n QUALITY_WEIGHTS,\n RELIABILITY,\n} from './weights';\n\nexport interface ScoringInput {\n weeklyDownloads: number | null;\n downloadGrowth90d: number | null;\n stars: number | null;\n firstPublishedAt: Date | null;\n lastReleaseAt: Date | null;\n releasesLast12mo: number | null;\n openIssues: number | null;\n closedIssues: number | null;\n scorecard: number | null;\n advisories: Advisory[];\n deprecated: boolean;\n archived: boolean;\n bundleMinGzipKb: number | null;\n category: Category | null;\n // ── Intrinsic-quality signals (§1), adoption-independent ──\n hasTypes: boolean | null;\n hasTestScript: boolean | null;\n readmeLength: number | null;\n hasExamples: boolean | null;\n hasHomepage: boolean | null;\n hasReleaseNotes: boolean | null;\n directDependenciesCount: number | null;\n license: string | null;\n hasProvenance: boolean | null;\n}\n\nconst DAY_MS = 24 * 60 * 60 * 1000;\nconst MONTH_MS = 30 * DAY_MS;\n\nconst clamp = (n: number, lo = 0, hi = 100): number => Math.max(lo, Math.min(hi, n));\nconst daysSince = (date: Date | null, now: Date): number | null =>\n date ? (now.getTime() - date.getTime()) / DAY_MS : null;\nconst monthsSince = (date: Date | null, now: Date): number | null =>\n date ? (now.getTime() - date.getTime()) / MONTH_MS : null;\n\n/** Build a ScoringInput from collected raw signals. */\nexport function toScoringInput(signals: RawPackageSignals, category: Category | null): ScoringInput {\n const { registry, downloads, github, depsDev, bundle } = signals;\n const readme = registry?.readme ?? null;\n return {\n weeklyDownloads: downloads?.weeklyDownloads ?? null,\n downloadGrowth90d: downloads?.downloadGrowth90d ?? null,\n stars: github?.stars ?? null,\n firstPublishedAt: registry?.firstPublishedAt ?? null,\n lastReleaseAt: github?.lastReleaseAt ?? registry?.lastReleaseAt ?? null,\n releasesLast12mo: github?.releasesLast12mo ?? null,\n openIssues: github?.openIssues ?? null,\n closedIssues: github?.closedIssues ?? null,\n scorecard: depsDev?.scorecard ?? null,\n advisories: depsDev?.advisories ?? [],\n deprecated: registry?.deprecated ?? false,\n archived: github?.archived ?? false,\n bundleMinGzipKb: bundle?.bundleMinGzipKb ?? null,\n category,\n // Quality signals — null (not false) when the manifest itself is missing, so\n // weightedAverage drops the component rather than scoring it 0.\n hasTypes: registry ? registry.hasTypes : null,\n hasTestScript: registry ? registry.hasTestScript : null,\n readmeLength: readme !== null ? readme.length : null,\n hasExamples: readme !== null ? /```/.test(readme) : null,\n hasHomepage: registry ? registry.homepage !== null : null,\n hasReleaseNotes: github?.releasesLast12mo != null ? github.releasesLast12mo > 0 : null,\n directDependenciesCount: registry?.directDependenciesCount ?? null,\n license: registry?.license ?? null,\n hasProvenance: registry ? registry.hasProvenance : null,\n };\n}\n\n// ── Maintenance ─────────────────────────────────────────────────────────────\n\nexport function computeMaintenance(input: ScoringInput, now: Date): number {\n if (input.deprecated || input.archived) return MAINTENANCE.deadCap;\n\n const components: { value: number; weight: number }[] = [];\n\n const days = daysSince(input.lastReleaseAt, now);\n if (days !== null) {\n const recency =\n days <= MAINTENANCE.freshDays\n ? 100\n : clamp((100 * (MAINTENANCE.staleDays - days)) / (MAINTENANCE.staleDays - MAINTENANCE.freshDays));\n components.push({ value: recency, weight: MAINTENANCE_WEIGHTS.recency });\n }\n\n if (input.releasesLast12mo !== null) {\n const cadence = clamp((Math.min(input.releasesLast12mo, MAINTENANCE.cadenceCap) / MAINTENANCE.cadenceCap) * 100);\n components.push({ value: cadence, weight: MAINTENANCE_WEIGHTS.cadence });\n }\n\n if (input.openIssues !== null && input.closedIssues !== null) {\n const total = input.openIssues + input.closedIssues;\n if (total > 0) {\n components.push({ value: (input.closedIssues / total) * 100, weight: MAINTENANCE_WEIGHTS.closeRatio });\n }\n }\n\n return weightedAverage(components);\n}\n\n// ── Adoption ────────────────────────────────────────────────────────────────\n\nexport function computeAdoption(input: ScoringInput): number {\n const dl = input.weeklyDownloads ?? 0;\n const downloadsScore = clamp(\n ((Math.log10(Math.max(dl, 1)) - ADOPTION.downloadsLogMin) /\n (ADOPTION.downloadsLogMax - ADOPTION.downloadsLogMin)) *\n 100,\n );\n\n let base = downloadsScore;\n if (input.stars !== null) {\n const starsScore = clamp((Math.log10(Math.max(input.stars, 1)) / ADOPTION.starsLogMax) * 100);\n base = (1 - ADOPTION.starsWeight) * downloadsScore + ADOPTION.starsWeight * starsScore;\n }\n\n if (input.downloadGrowth90d !== null) {\n const bonus = clamp(\n input.downloadGrowth90d * ADOPTION.growthMultiplier,\n -ADOPTION.growthBonusCap,\n ADOPTION.growthBonusCap,\n );\n base += bonus;\n }\n\n return clamp(base);\n}\n\n// ── Reliability ─────────────────────────────────────────────────────────────\n\nexport function computeReliability(input: ScoringInput): number {\n const base = input.scorecard !== null ? input.scorecard * 10 : RELIABILITY.neutralWhenUnknown;\n const penalty = input.advisories.reduce(\n (sum, adv) => sum + (RELIABILITY.penalty[adv.severity] ?? 0),\n 0,\n );\n return clamp(base - penalty);\n}\n\n// ── Efficiency (pass 2 — needs the category median) ─────────────────────────\n\n/**\n * Efficiency for frontend categories: smaller-than-median bundle → higher score\n * (median maps to 50). Returns null for backend categories / missing data; the\n * null signals the composite to redistribute the efficiency weight (§10, R1).\n */\nexport function computeEfficiency(\n bundleMinGzipKb: number | null,\n category: Category | null,\n categoryMedian: number | null,\n): number | null {\n if (!isFrontendCategory(category) || bundleMinGzipKb === null || !categoryMedian || categoryMedian <= 0) {\n return null;\n }\n const ratio = bundleMinGzipKb / categoryMedian;\n return clamp(100 - ratio * EFFICIENCY.medianScore);\n}\n\n// ── Quality (pass 1 — intrinsic, adoption-independent §1) ────────────────────\n\n/** A small set of OSI-recognized SPDX license IDs (prefix-matched, case-insensitive). */\nconst RECOGNIZED_LICENSES = [\n 'mit',\n 'isc',\n 'apache-2.0',\n 'bsd-2-clause',\n 'bsd-3-clause',\n 'mpl-2.0',\n 'lgpl',\n 'gpl',\n 'agpl',\n 'unlicense',\n '0bsd',\n 'cc0-1.0',\n];\n\nexport function isRecognizedLicense(license: string | null): boolean {\n if (!license) return false;\n const id = license.trim().toLowerCase();\n return RECOGNIZED_LICENSES.some((l) => id === l || id.startsWith(l));\n}\n\n/**\n * Intrinsic-quality score (§1): how well-built a package is, independent of\n * adoption. A weighted average over the *available* components, so a missing\n * signal is dropped rather than penalized. Returns null only when no signal is\n * available at all (e.g. the registry manifest itself failed to load).\n */\nexport function computeQuality(input: ScoringInput): number | null {\n const components: { value: number; weight: number }[] = [];\n\n if (input.hasTypes !== null) {\n components.push({ value: input.hasTypes ? 100 : 0, weight: QUALITY_WEIGHTS.types });\n }\n if (input.hasTestScript !== null) {\n components.push({ value: input.hasTestScript ? 100 : 0, weight: QUALITY_WEIGHTS.tests });\n }\n if (input.readmeLength !== null || input.hasHomepage !== null) {\n const lenScore = Math.min((input.readmeLength ?? 0) / QUALITY.docsFullLengthChars, 1) * 60;\n const examples = input.hasExamples ? 25 : 0;\n const homepage = input.hasHomepage ? 15 : 0;\n components.push({ value: clamp(lenScore + examples + homepage), weight: QUALITY_WEIGHTS.docs });\n }\n if (input.hasReleaseNotes !== null) {\n components.push({ value: input.hasReleaseNotes ? 100 : 0, weight: QUALITY_WEIGHTS.changelog });\n }\n if (input.directDependenciesCount !== null) {\n const deps = input.directDependenciesCount;\n const depsScore = clamp(\n 100 - (Math.log10(deps + 1) / Math.log10(QUALITY.depsLogMax + 1)) * 100,\n );\n components.push({ value: depsScore, weight: QUALITY_WEIGHTS.deps });\n }\n if (input.license !== null) {\n components.push({\n value: isRecognizedLicense(input.license) ? 100 : QUALITY.licenseUnrecognizedScore,\n weight: QUALITY_WEIGHTS.license,\n });\n }\n // Provenance is a pure bonus — only counted when present, never penalizing.\n if (input.hasProvenance) {\n components.push({ value: 100, weight: QUALITY_WEIGHTS.provenance });\n }\n\n if (components.length === 0) return null;\n return weightedAverage(components);\n}\n\n// ── Composite ───────────────────────────────────────────────────────────────\n\n/** Compose the health score, redistributing efficiency's weight when null.\n * Weights default to HEALTH_WEIGHTS but can be overridden (§4 rescore). */\nexport function computeHealthScore(\n breakdown: ScoreBreakdown,\n weights: typeof HEALTH_WEIGHTS | { maintenance: number; adoption: number; reliability: number; efficiency: number } = HEALTH_WEIGHTS,\n): number {\n const { maintenance, adoption, reliability, efficiency } = breakdown;\n const w = weights;\n if (efficiency === null) {\n const denom = w.maintenance + w.adoption + w.reliability;\n return Math.round(\n (w.maintenance * maintenance + w.adoption * adoption + w.reliability * reliability) / denom,\n );\n }\n return Math.round(\n w.maintenance * maintenance +\n w.adoption * adoption +\n w.reliability * reliability +\n w.efficiency * efficiency,\n );\n}\n\n/**\n * Default sort composite (§1): blend the popularity-tilted health score with the\n * adoption-independent quality axis. `lambda` (default COMPOSITE.lambda) is the\n * tunable knob `edit-weights` exposes. Falls back to pure health when quality is\n * unavailable, so a missing manifest never drags a package down.\n */\nexport function computeComposite(\n healthScore: number,\n qualityScore: number | null,\n lambda: number = COMPOSITE.lambda,\n): number {\n if (qualityScore === null) return healthScore;\n return Math.round((1 - lambda) * healthScore + lambda * qualityScore);\n}\n\n// ── Confidence ──────────────────────────────────────────────────────────────\n\nexport function hasCriticalOrHighAdvisory(advisories: Advisory[]): boolean {\n return advisories.some((a) => a.severity === 'critical' || a.severity === 'high');\n}\n\nexport function computeConfidence(\n input: ScoringInput,\n now: Date,\n qualityScore: number | null = null,\n): Confidence {\n const dl = input.weeklyDownloads ?? 0;\n const ageMonths = monthsSince(input.firstPublishedAt, now);\n const lastReleaseMonths = monthsSince(input.lastReleaseAt, now);\n const growth = input.downloadGrowth90d ?? 0;\n\n const provenReleaseOk =\n lastReleaseMonths !== null && lastReleaseMonths <= CONFIDENCE.proven.maxLastReleaseMonths;\n const provenAgeOk = ageMonths !== null && ageMonths >= CONFIDENCE.proven.minAgeMonths;\n\n if (\n dl >= CONFIDENCE.proven.minWeeklyDownloads &&\n provenAgeOk &&\n provenReleaseOk &&\n !hasCriticalOrHighAdvisory(input.advisories) &&\n !input.deprecated &&\n !input.archived\n ) {\n return 'proven';\n }\n\n const emergingReleaseOk =\n lastReleaseMonths !== null && lastReleaseMonths <= CONFIDENCE.emerging.maxLastReleaseMonths;\n const emergingAdoptionOk =\n dl >= CONFIDENCE.emerging.minWeeklyDownloads || growth >= CONFIDENCE.emerging.strongGrowth;\n\n if (emergingAdoptionOk && emergingReleaseOk && !input.deprecated && !input.archived) {\n return 'emerging';\n }\n\n // `promising` (§1): adoption-independent — high intrinsic quality on a package\n // that hasn't yet earned adoption traction. This is how new-but-good packages\n // surface on merit instead of sinking to `unproven`.\n // A freshly published package may have no separate release date (registry and\n // GitHub both empty); fall back to first-publish recency so a new-but-good\n // package isn't locked to `unproven` — the exact case this tier targets.\n const promisingRecencyMonths = lastReleaseMonths ?? ageMonths;\n const promisingReleaseOk =\n promisingRecencyMonths !== null &&\n promisingRecencyMonths <= CONFIDENCE.promising.maxLastReleaseMonths;\n if (\n qualityScore !== null &&\n qualityScore >= CONFIDENCE.promising.minQuality &&\n promisingReleaseOk &&\n !hasCriticalOrHighAdvisory(input.advisories) &&\n !input.deprecated &&\n !input.archived\n ) {\n return 'promising';\n }\n\n return 'unproven';\n}\n\n// ── Helpers ─────────────────────────────────────────────────────────────────\n\nfunction weightedAverage(components: { value: number; weight: number }[]): number {\n if (components.length === 0) return 0;\n const totalWeight = components.reduce((s, c) => s + c.weight, 0);\n if (totalWeight === 0) return 0;\n return Math.round(components.reduce((s, c) => s + c.value * c.weight, 0) / totalWeight);\n}\n\n/** Median of a numeric list, or null if empty. */\nexport function median(values: number[]): number | null {\n if (values.length === 0) return null;\n const sorted = [...values].sort((a, b) => a - b);\n const mid = Math.floor(sorted.length / 2);\n return sorted.length % 2 === 0 ? (sorted[mid - 1]! + sorted[mid]!) / 2 : sorted[mid]!;\n}\n","export * from './score';\nexport * from './weights';\n","/**\n * Embedding providers (§11). A pluggable interface with two implementations:\n * - OpenAI (`text-embedding-3-small`, 1536-dim) — the default when a key is set.\n * - Local deterministic embedder (no key) — a hashing bag-of-words that captures\n * lexical overlap. Crude but real: it makes `recommend` and tests work with\n * zero credentials (R1 decision). Both emit EMBEDDING_DIM-length unit vectors,\n * so the DB column and pgvector index never change.\n */\nimport { createHash } from 'node:crypto';\nimport { getConfig } from '../core/config';\nimport { EMBEDDING_DIM } from '../core/constants';\nimport { httpRequest } from '../core/http';\nimport { logger } from '../core/logger';\nimport type { Category } from '../core/types';\n\nexport interface EmbeddingProvider {\n readonly kind: 'openai' | 'local';\n readonly dimensions: number;\n /**\n * Stable identity of the vector space this provider produces (e.g.\n * `openai:text-embedding-3-small`, `local`). Stored per row so vector search\n * only compares vectors from the same space — switching providers then falls\n * back to lexical retrieval until rows are re-embedded, instead of silently\n * returning garbage from a cosine distance across incompatible spaces.\n */\n readonly id: string;\n embed(texts: string[]): Promise<number[][]>;\n}\n\n/** Normalized text blob embedded per package (§8.2). */\nexport function buildEmbeddingText(input: {\n name: string;\n category: Category | null;\n summary: string | null;\n description: string | null;\n}): string {\n const body = input.summary || input.description || '';\n return `${input.name}. ${input.category ?? ''}. ${body}`.trim();\n}\n\n// ── Local deterministic embedder ────────────────────────────────────────────\n\nfunction tokenize(text: string): string[] {\n return text\n .toLowerCase()\n .split(/[^a-z0-9]+/)\n .filter((t) => t.length > 1);\n}\n\n/** FNV-1a 32-bit hash. */\nfunction fnv1a(str: string): number {\n let h = 0x811c9dc5;\n for (let i = 0; i < str.length; i++) {\n h ^= str.charCodeAt(i);\n h = Math.imul(h, 0x01000193);\n }\n return h >>> 0;\n}\n\nexport function localEmbed(text: string, dim = EMBEDDING_DIM): number[] {\n const vec = new Float64Array(dim);\n const tokens = tokenize(text);\n const add = (token: string, weight: number) => {\n const idx = fnv1a(token) % dim;\n const sign = fnv1a('s:' + token) & 1 ? 1 : -1;\n vec[idx]! += weight * sign;\n };\n for (const t of tokens) add(t, 1);\n for (let i = 0; i < tokens.length - 1; i++) add(`${tokens[i]} ${tokens[i + 1]}`, 0.5);\n\n // L2-normalize to a unit vector (cosine-friendly).\n let norm = 0;\n for (let i = 0; i < dim; i++) norm += vec[i]! * vec[i]!;\n norm = Math.sqrt(norm) || 1;\n const out = new Array<number>(dim);\n for (let i = 0; i < dim; i++) out[i] = vec[i]! / norm;\n return out;\n}\n\nexport class LocalEmbeddingProvider implements EmbeddingProvider {\n readonly kind = 'local' as const;\n readonly dimensions = EMBEDDING_DIM;\n readonly id = 'local';\n async embed(texts: string[]): Promise<number[][]> {\n return texts.map((t) => localEmbed(t));\n }\n}\n\n// ── OpenAI embedder ─────────────────────────────────────────────────────────\n\nconst OPENAI_BATCH = 96;\n\nexport class OpenAIEmbeddingProvider implements EmbeddingProvider {\n readonly kind = 'openai' as const;\n readonly dimensions = EMBEDDING_DIM;\n readonly id: string;\n\n private readonly endpoint: string;\n private readonly host: string;\n\n constructor(\n private readonly apiKey: string,\n private readonly model: string,\n baseUrl: string,\n private readonly fetchImpl?: typeof fetch,\n ) {\n this.id = `openai:${model}`;\n this.endpoint = `${baseUrl.replace(/\\/$/, '')}/embeddings`;\n this.host = new URL(baseUrl).host;\n }\n\n async embed(texts: string[]): Promise<number[][]> {\n const out: number[][] = [];\n for (let i = 0; i < texts.length; i += OPENAI_BATCH) {\n const batch = texts.slice(i, i + OPENAI_BATCH);\n // Pin the output dimension to the DB column width. Every text-embedding-3\n // model honors `dimensions`, so a larger model (e.g. -3-large, natively\n // 3072-dim) is projected to 1536 instead of overflowing the vector(1536)\n // column at insert time. ponytail: non-OpenAI providers may ignore\n // `dimensions`; the length check below fails loud if the space mismatches.\n const body = JSON.stringify({ model: this.model, input: batch, dimensions: EMBEDDING_DIM });\n const { data } = await httpRequest<any>(this.endpoint, {\n host: this.host,\n method: 'POST',\n ttlMs: 30 * 24 * 60 * 60 * 1000, // cache embeddings 30d to control cost\n cacheKey: `openai-embed ${this.model} ${createHash('sha256').update(body).digest('hex')}`,\n headers: { Authorization: `Bearer ${this.apiKey}`, 'Content-Type': 'application/json' },\n body,\n fetchImpl: this.fetchImpl,\n });\n const vectors: { embedding: number[]; index: number }[] = data?.data ?? [];\n vectors.sort((a, b) => a.index - b.index);\n for (const v of vectors) {\n // Fail loud on any dimension drift rather than silently storing vectors\n // that pgvector can't compare against the rest of the column.\n if (v.embedding.length !== EMBEDDING_DIM) {\n throw new Error(\n `OpenAI model ${this.model} returned ${v.embedding.length}-dim vectors; expected ${EMBEDDING_DIM}. Set EMBEDDING_MODEL to a text-embedding-3 model or update EMBEDDING_DIM.`,\n );\n }\n out.push(v.embedding);\n }\n }\n return out;\n }\n}\n\n// ── Factory ─────────────────────────────────────────────────────────────────\n\nexport function createEmbeddingProvider(fetchImpl?: typeof fetch): EmbeddingProvider {\n const config = getConfig();\n if (config.EMBEDDING_PROVIDER === 'openai' && config.EMBEDDING_API_KEY) {\n return new OpenAIEmbeddingProvider(\n config.EMBEDDING_API_KEY,\n config.EMBEDDING_MODEL,\n config.EMBEDDING_BASE_URL,\n fetchImpl,\n );\n }\n if (config.EMBEDDING_PROVIDER === 'openai' && !config.EMBEDDING_API_KEY) {\n logger.warn('EMBEDDING_API_KEY not set — falling back to the local embedder.');\n }\n return new LocalEmbeddingProvider();\n}\n","/** Map over items with bounded concurrency, preserving input order. */\nexport async function pMap<T, R>(\n items: readonly T[],\n mapper: (item: T, index: number) => Promise<R>,\n concurrency: number,\n): Promise<R[]> {\n const results = new Array<R>(items.length);\n let cursor = 0;\n const workerCount = Math.max(1, Math.min(concurrency, items.length));\n const workers = Array.from({ length: workerCount }, async () => {\n while (cursor < items.length) {\n const index = cursor++;\n results[index] = await mapper(items[index]!, index);\n }\n });\n await Promise.all(workers);\n return results;\n}\n","/**\n * `lurq sync` pipeline (§9.7). End-to-end ingestion for the seed list (or one\n * package): collect signals → score → summarize → upsert, recording a sync_runs\n * row. Idempotent, concurrent, and tolerant of individual source failures (§17).\n *\n * Two-pass for efficiency (§10): pass 1 collects + scores everything that's\n * per-package; then category medians are computed; pass 2 finalizes efficiency\n * and the composite health score. Embeddings are added in M4.\n */\nimport { invalidateCache } from '../core/cache';\nimport { getConfig } from '../core/config';\nimport { pMap } from '../core/concurrency';\nimport { setCacheBypassRead } from '../core/http';\nimport { logger } from '../core/logger';\nimport type { Category, CategorySource, ScoreBreakdown } from '../core/types';\nimport { collectSignals } from '../ingestion/collect';\nimport { fetchBulkWeeklyDownloads } from '../ingestion/sources/npmDownloads';\nimport { buildSummaryInput, createSummaryProvider } from '../ingestion/summarize';\nimport { inferCategoryFromSignals } from '../search/categoryInference';\nimport { buildEmbeddingText, createEmbeddingProvider } from '../search/embeddings';\nimport type { RawPackageSignals } from '../ingestion/types';\nimport {\n computeAdoption,\n computeConfidence,\n computeEfficiency,\n computeHealthScore,\n computeMaintenance,\n computeQuality,\n computeReliability,\n median,\n toScoringInput,\n type ScoringInput,\n} from '../scoring';\nimport { createDb, type Database } from '../db/client';\nimport {\n finishSyncRun,\n getSeedTargets,\n startSyncRun,\n upsertPackage,\n} from '../db/packages';\nimport { isFrontendCategory } from '../core/types';\nimport type { NewPackageRow, SyncError } from '../db/schema';\n\nexport interface SyncOptions {\n full?: boolean;\n packageName?: string;\n}\n\nexport interface SyncSummary {\n seen: number;\n updated: number;\n errors: number;\n status: 'success' | 'partial' | 'failed';\n}\n\ninterface Target {\n name: string;\n category: Category | null;\n}\n\n/** Per-package state carried from pass 1 to pass 2. */\ninterface Computed {\n target: Target;\n /** Final resolved category (curated or inferred at ingest, §2A). */\n category: Category | null;\n categorySource: CategorySource | null;\n signals: RawPackageSignals;\n input: ScoringInput;\n maintenance: number;\n adoption: number;\n reliability: number;\n quality: number | null;\n confidence: ReturnType<typeof computeConfidence>;\n summary: string | null;\n usageGuide: NewPackageRow['usageGuide'];\n}\n\nexport async function runSync(opts: SyncOptions = {}): Promise<SyncSummary> {\n const config = getConfig();\n const now = new Date();\n if (opts.full) setCacheBypassRead(true);\n\n const handle = createDb({ max: Math.max(4, config.LURQ_SYNC_CONCURRENCY) });\n const provider = createSummaryProvider();\n logger.info(`Summary provider: ${provider.kind}`);\n if (!config.GITHUB_TOKEN) {\n logger.warn(\n 'GITHUB_TOKEN not set — GitHub signals (stars, issues, release cadence) will be ' +\n 'skipped, degrading maintenance/adoption scores. Set it for accurate scoring.',\n );\n }\n\n const runId = await startSyncRun(handle.db);\n const allErrors: SyncError[] = [];\n\n try {\n const targets = await resolveTargets(handle.db, opts);\n logger.info(`Syncing ${targets.length} package(s) with concurrency ${config.LURQ_SYNC_CONCURRENCY}…`);\n\n // Bulk-fetch weekly downloads up front (one call per 128 packages) to avoid\n // the downloads API rate limit that per-package bursts trigger.\n logger.info('Fetching weekly downloads in bulk…');\n const weeklyMap = await fetchBulkWeeklyDownloads(targets.map((t) => t.name));\n\n // ── Pass 1: collect + per-package scoring + summary ──────────────────────\n let done = 0;\n const computed = await pMap(\n targets,\n async (target): Promise<Computed | null> => {\n try {\n const signals = await collectSignals(target.name, target.category, {\n githubToken: config.GITHUB_TOKEN,\n prefetchedWeekly: weeklyMap.has(target.name) ? weeklyMap.get(target.name)! : undefined,\n });\n for (const e of signals.errors) allErrors.push({ package: target.name, ...e });\n\n const summaryInput = await buildSummaryInput(signals, target.category);\n const { summary, usageGuide, inferredCategory } = await provider.generate(summaryInput);\n\n // Categorize-on-ingest (§2A): curated category wins; otherwise infer\n // from the package's own text, then fall back to the LLM classifier.\n let category = target.category;\n let categorySource: CategorySource | null = target.category ? 'curated' : null;\n if (!category) {\n category = inferCategoryFromSignals(signals) ?? inferredCategory ?? null;\n categorySource = category ? 'inferred' : null;\n }\n\n const input = toScoringInput(signals, category);\n const quality = computeQuality(input);\n if (++done % 25 === 0) logger.info(` …${done}/${targets.length}`);\n return {\n target,\n category,\n categorySource,\n signals,\n input,\n maintenance: computeMaintenance(input, now),\n adoption: computeAdoption(input),\n reliability: computeReliability(input),\n quality,\n confidence: computeConfidence(input, now, quality),\n summary,\n usageGuide,\n };\n } catch (err) {\n allErrors.push({\n package: target.name,\n source: 'pipeline',\n message: err instanceof Error ? err.message : String(err),\n });\n return null;\n }\n },\n config.LURQ_SYNC_CONCURRENCY,\n );\n\n const ok = computed.filter((c): c is Computed => c !== null);\n\n // ── Category medians for efficiency (§10) ────────────────────────────────\n const medians = computeCategoryMedians(ok);\n\n // ── Embeddings (§11): embed the normalized text blob for each package ─────\n const embProvider = createEmbeddingProvider();\n logger.info(`Embedding provider: ${embProvider.kind}`);\n const embeddings = await embProvider.embed(\n ok.map((c) =>\n buildEmbeddingText({\n name: c.target.name,\n category: c.category,\n summary: c.summary,\n description: c.signals.registry?.description ?? null,\n }),\n ),\n );\n\n // ── Pass 2: efficiency + composite + upsert ──────────────────────────────\n let updated = 0;\n for (let i = 0; i < ok.length; i++) {\n const c = ok[i]!;\n const efficiency = computeEfficiency(\n c.input.bundleMinGzipKb,\n c.category,\n c.category ? (medians.get(c.category) ?? null) : null,\n );\n const breakdown: ScoreBreakdown = {\n maintenance: c.maintenance,\n adoption: c.adoption,\n reliability: c.reliability,\n efficiency,\n quality: c.quality,\n };\n const healthScore = computeHealthScore(breakdown);\n await upsertPackage(\n handle.db,\n assemblePackageRow({\n name: c.target.name,\n category: c.category,\n categorySource: c.categorySource,\n signals: c.signals,\n input: c.input,\n summary: c.summary,\n usageGuide: c.usageGuide,\n confidence: c.confidence,\n breakdown,\n healthScore,\n qualityScore: c.quality,\n embedding: embeddings[i] ?? null,\n embeddingProvider: embProvider.id,\n now,\n }),\n );\n updated++;\n }\n\n const status: SyncSummary['status'] =\n updated === 0 ? 'failed' : allErrors.length > 0 ? 'partial' : 'success';\n await finishSyncRun(handle.db, runId, {\n packagesSeen: targets.length,\n packagesUpdated: updated,\n errors: allErrors,\n status,\n });\n\n logger.info(`Sync ${status}: ${updated}/${targets.length} updated, ${allErrors.length} source errors.`);\n // The index changed — drop cached reads so the next query sees fresh scores.\n if (updated > 0) await invalidateCache();\n return { seen: targets.length, updated, errors: allErrors.length, status };\n } catch (err) {\n await finishSyncRun(handle.db, runId, {\n packagesSeen: 0,\n packagesUpdated: 0,\n errors: [{ package: '*', source: 'pipeline', message: (err as Error).message }],\n status: 'failed',\n });\n throw err;\n } finally {\n if (opts.full) setCacheBypassRead(false);\n await handle.close();\n }\n}\n\nasync function resolveTargets(db: Database, opts: SyncOptions): Promise<Target[]> {\n if (opts.packageName) {\n const seeds = await getSeedTargets(db);\n const found = seeds.find((s) => s.name === opts.packageName);\n return [{ name: opts.packageName, category: found?.category ?? null }];\n }\n return getSeedTargets(db);\n}\n\nfunction computeCategoryMedians(computed: Computed[]): Map<Category, number> {\n const byCategory = new Map<Category, number[]>();\n for (const c of computed) {\n const cat = c.category;\n const kb = c.input.bundleMinGzipKb;\n if (cat && isFrontendCategory(cat) && kb !== null) {\n const list = byCategory.get(cat) ?? [];\n list.push(kb);\n byCategory.set(cat, list);\n }\n }\n const medians = new Map<Category, number>();\n for (const [cat, list] of byCategory) {\n const m = median(list);\n if (m !== null) medians.set(cat, m);\n }\n return medians;\n}\n\n/** Assemble a fully-scored package row. Shared by the bulk sync and the\n * on-demand single-package path (§12.5). */\nexport function assemblePackageRow(p: {\n name: string;\n category: Category | null;\n categorySource: CategorySource | null;\n signals: RawPackageSignals;\n input: ScoringInput;\n summary: string | null;\n usageGuide: NewPackageRow['usageGuide'];\n confidence: NewPackageRow['confidence'];\n breakdown: ScoreBreakdown;\n healthScore: number;\n qualityScore: number | null;\n embedding: number[] | null;\n embeddingProvider: string | null;\n now: Date;\n}): NewPackageRow {\n const r = p.signals.registry;\n return {\n name: p.name,\n ecosystem: 'npm',\n category: p.category,\n categorySource: p.categorySource,\n description: r?.description ?? null,\n summary: p.summary,\n repoUrl: r?.repoUrl ?? null,\n homepage: r?.homepage ?? null,\n latestVersion: r?.latestVersion ?? null,\n license: r?.license ?? null,\n deprecated: p.input.deprecated,\n archived: p.input.archived,\n firstPublishedAt: p.input.firstPublishedAt,\n lastReleaseAt: p.input.lastReleaseAt,\n weeklyDownloads: p.input.weeklyDownloads,\n downloadGrowth90d: p.input.downloadGrowth90d,\n stars: p.input.stars,\n openIssues: p.input.openIssues,\n closedIssues: p.input.closedIssues,\n scorecard: p.input.scorecard,\n bundleMinGzipKb: p.input.bundleMinGzipKb,\n advisories: p.input.advisories,\n peerDependencies: r?.peerDependencies ?? null,\n peerDependenciesMeta: r?.peerDependenciesMeta ?? null,\n engines: r?.engines ?? null,\n healthScore: p.healthScore,\n qualityScore: p.qualityScore,\n confidence: p.confidence,\n scoreBreakdown: p.breakdown,\n usageGuide: p.usageGuide,\n embedding: p.embedding,\n embeddingProvider: p.embedding ? p.embeddingProvider : null,\n dataAsOf: p.now,\n };\n}\n","/**\n * In-process background ingester for on-demand misses (§12.5). Keeps the heavy\n * fetch→score→embed→upsert OFF the request path: evaluate/compare/verify enqueue\n * an untracked-but-real package and return immediately (\"tracking, retry\n * shortly\"), while a bounded worker pool ingests it within seconds.\n *\n * Bounded on purpose — moving unbounded work off the request path just relocates\n * the problem. Dedup (a package already pending or in-flight is never queued\n * again) + a hard pending cap mean a flood of distinct names can't spawn\n * unbounded syncs or grow memory without limit. Process-local; each instance\n * drains its own queue. Durability is by self-heal: if the process dies with\n * work pending, the next request for that package re-enqueues it.\n */\nimport { logger } from '../core/logger';\nimport type { Database } from '../db/client';\nimport { ensureSeedEntry } from '../db/packages';\nimport { syncOnePackage } from './single';\n\nconst MAX_CONCURRENT = 3;\nconst MAX_PENDING = 500;\n\nconst pending: string[] = [];\nconst inFlight = new Set<string>();\nconst queuedNames = new Set<string>();\nlet active = 0;\n\n/** Current backlog (pending + in-flight) — exposed for tests/observability. */\nexport function ingestQueueDepth(): number {\n return pending.length + inFlight.size;\n}\n\n/** Test-only: clear all queue state. */\nexport function resetIngestQueue(): void {\n pending.length = 0;\n inFlight.clear();\n queuedNames.clear();\n active = 0;\n}\n\n/**\n * Schedule an untracked-but-real package for background ingestion. No-op if it's\n * already pending or in-flight, or if the queue is at capacity. Returns without\n * awaiting any network/DB work.\n */\nexport function enqueueIngest(db: Database, name: string): void {\n if (queuedNames.has(name) || inFlight.has(name)) return;\n if (pending.length >= MAX_PENDING) {\n logger.warn(`ingest queue full (${MAX_PENDING}); dropping on-demand request for ${name}`);\n return;\n }\n queuedNames.add(name);\n pending.push(name);\n pump(db);\n}\n\nfunction pump(db: Database): void {\n while (active < MAX_CONCURRENT && pending.length > 0) {\n const name = pending.shift()!;\n queuedNames.delete(name);\n inFlight.add(name);\n active += 1;\n void ingestOne(db, name).finally(() => {\n inFlight.delete(name);\n active -= 1;\n pump(db);\n });\n }\n}\n\nasync function ingestOne(db: Database, name: string): Promise<void> {\n try {\n const row = await syncOnePackage(db, name);\n // Same roster-promotion bar as the old inline path: only genuinely-trackable\n // discoveries join the sync roster, so the on-demand tail can't inflate cost.\n if (row.confidence && row.confidence !== 'unproven') {\n await ensureSeedEntry(db, name, row.category);\n }\n } catch (err) {\n logger.warn(`on-demand ingest failed for ${name}: ${String(err)}`);\n }\n}\n","/**\n * Single-package ingestion + the on-demand path (§12.5). When a queried package\n * isn't tracked but exists on npm, lurq fetches, scores, embeds, stores, and\n * returns it — organically growing coverage beyond the seed list.\n */\nimport { and, eq, isNotNull, sql } from 'drizzle-orm';\nimport { getConfig } from '../core/config';\nimport type { Category, CategorySource, ScoreBreakdown } from '../core/types';\nimport { collectSignals } from '../ingestion/collect';\nimport { fetchWeeklyDownloads, npmPackageExists } from '../ingestion/sources';\nimport { buildSummaryInput, createSummaryProvider } from '../ingestion/summarize';\nimport { inferCategoryFromSignals } from '../search/categoryInference';\nimport {\n computeAdoption,\n computeConfidence,\n computeEfficiency,\n computeHealthScore,\n computeMaintenance,\n computeQuality,\n computeReliability,\n toScoringInput,\n} from '../scoring';\nimport { buildEmbeddingText, createEmbeddingProvider } from '../search/embeddings';\nimport type { Database } from '../db/client';\nimport {\n getPackageByName,\n upsertPackage,\n upsertPackageVersions,\n} from '../db/packages';\nimport { packages, seedPackages, type PackageRow } from '../db/schema';\nimport { assemblePackageRow } from './sync';\n// Safe module cycle: ingestQueue imports syncOnePackage from here, but both\n// bindings are used only at call time, never at module-eval, so ESM resolves it.\nimport { enqueueIngest } from './ingestQueue';\n\nasync function getSeedCategory(db: Database, name: string): Promise<Category | null> {\n const [row] = await db\n .select({ category: seedPackages.category })\n .from(seedPackages)\n .where(eq(seedPackages.name, name))\n .limit(1);\n return row?.category ?? null;\n}\n\n/** Median bundle size across already-tracked packages in a category (for efficiency). */\nasync function getCategoryMedianBundle(db: Database, category: Category): Promise<number | null> {\n const [row] = await db\n .select({\n m: sql<number | null>`percentile_cont(0.5) within group (order by ${packages.bundleMinGzipKb})`,\n })\n .from(packages)\n .where(and(eq(packages.category, category), isNotNull(packages.bundleMinGzipKb)));\n return row?.m ?? null;\n}\n\n/** Fetch, score, embed, and upsert a single package; returns the stored row. */\nexport async function syncOnePackage(\n db: Database,\n name: string,\n opts: { category?: Category | null } = {},\n): Promise<PackageRow> {\n const config = getConfig();\n const now = new Date();\n\n const existing = await getPackageByName(db, name);\n // The curated category (from a manual arg or the seed list) wins. We resolve\n // the final category *after* ingest so a discovered package can be classified\n // from its own text rather than stored as a second-class `null` (§2A).\n const curatedCategory = opts.category ?? (await getSeedCategory(db, name)) ?? null;\n const initialCategory = curatedCategory ?? existing?.category ?? null;\n\n const prefetchedWeekly = await fetchWeeklyDownloads(name).catch(() => null);\n const signals = await collectSignals(name, initialCategory, {\n githubToken: config.GITHUB_TOKEN,\n prefetchedWeekly,\n });\n\n const summaryInput = await buildSummaryInput(signals, initialCategory);\n const { summary, usageGuide, inferredCategory } =\n await createSummaryProvider().generate(summaryInput);\n\n let category: Category | null;\n let categorySource: CategorySource | null;\n if (curatedCategory) {\n category = curatedCategory;\n categorySource = 'curated';\n } else if (existing?.category) {\n category = existing.category;\n categorySource = existing.categorySource ?? 'inferred';\n } else {\n category = inferCategoryFromSignals(signals) ?? inferredCategory ?? null;\n categorySource = category ? 'inferred' : null;\n }\n\n const input = toScoringInput(signals, category);\n\n const median = category ? await getCategoryMedianBundle(db, category) : null;\n const quality = computeQuality(input);\n const breakdown: ScoreBreakdown = {\n maintenance: computeMaintenance(input, now),\n adoption: computeAdoption(input),\n reliability: computeReliability(input),\n efficiency: computeEfficiency(input.bundleMinGzipKb, category, median),\n quality,\n };\n const healthScore = computeHealthScore(breakdown);\n const confidence = computeConfidence(input, now, quality);\n\n const embProvider = createEmbeddingProvider();\n const [embedding] = await embProvider.embed([\n buildEmbeddingText({ name, category, summary, description: signals.registry?.description ?? null }),\n ]);\n\n await upsertPackage(\n db,\n assemblePackageRow({\n name,\n category,\n categorySource,\n signals,\n input,\n summary,\n usageGuide,\n confidence,\n breakdown,\n healthScore,\n qualityScore: quality,\n embedding: embedding ?? null,\n embeddingProvider: embProvider.id,\n now,\n }),\n );\n // Record the version timeline (idempotent). Non-fatal: never block a\n // successful package upsert on the version-history write.\n await upsertPackageVersions(db, name, signals.registry?.versionTimeline ?? []).catch(\n () => {},\n );\n return (await getPackageByName(db, name))!;\n}\n\nexport interface GetOrFetchResult {\n row: PackageRow | null;\n /** True if the package was already in the index before this call. */\n wasTracked: boolean;\n existsOnNpm: boolean;\n /** True if a real-but-untracked package was scheduled for background\n * ingestion this call — the caller should tell the agent to retry shortly. */\n queued?: boolean;\n}\n\n/**\n * Return a tracked package, or — if it's a real npm package not yet in the index\n * (§12.5) — schedule it for background ingestion and return row=null so the\n * request never blocks on the heavy fetch→score→embed→upsert. The caller surfaces\n * a \"tracking, retry shortly\" hint; a few seconds later the row exists. Returns\n * existsOnNpm=false when the name isn't a real package at all.\n */\nexport async function getOrFetchPackage(db: Database, name: string): Promise<GetOrFetchResult> {\n const existing = await getPackageByName(db, name);\n if (existing) return { row: existing, wasTracked: true, existsOnNpm: true };\n\n const exists = await npmPackageExists(name);\n if (!exists) return { row: null, wasTracked: false, existsOnNpm: false };\n\n // Real but untracked: ingest off the request path. Bounded + deduped so a\n // flood of distinct names can't spawn unbounded work (the whole point of not\n // doing it inline). Roster promotion happens in the worker, same quality bar.\n enqueueIngest(db, name);\n return { row: null, wasTracked: false, existsOnNpm: true, queued: true };\n}\n","/**\n * Hybrid recommendation (§3, §11). Two retrievals run over the same candidate\n * table — vector cosine (semantic) and `tsvector` lexical (exact name/keyword) —\n * fused with Reciprocal Rank Fusion (RRF), then re-ranked by a blend of fused\n * relevance and the quality-aware composite (§1). Pure vector search misses\n * exact-name hits (especially the keyless local embedder); the lexical leg fixes\n * that, and RRF avoids having to normalize two incomparable score scales.\n */\nimport { and, cosineDistance, eq, isNotNull, lte, sql } from 'drizzle-orm';\nimport type { Candidate, Category, Confidence, Runtime } from '../core/types';\nimport type { Database } from '../db/client';\nimport { packages } from '../db/schema';\nimport { computeComposite } from '../scoring';\nimport { loadWeights } from '../scoring/weights';\nimport { inferCategory } from './categoryInference';\nimport { createEmbeddingProvider, type EmbeddingProvider } from './embeddings';\n\nexport interface RecommendConstraints {\n runtime?: Runtime;\n license?: string;\n maxBundleKb?: number;\n minConfidence?: Confidence;\n}\n\nexport interface RecommendOptions {\n need: string;\n category?: Category;\n constraints?: RecommendConstraints;\n limit?: number;\n}\n\nconst CONFIDENCE_RANK: Record<Confidence, number> = {\n unproven: 0,\n promising: 1,\n emerging: 2,\n proven: 3,\n};\n/** Fused-relevance vs composite blend (§3, §11). The second term is the\n * quality-aware composite (§1), not raw health — so a well-built package isn't\n * buried by a popularity-tilted score. */\nconst RELEVANCE_WEIGHT = 0.6;\nconst COMPOSITE_WEIGHT = 0.4;\n/** RRF damping constant — standard value from the original RRF paper (§3). */\nconst RRF_K = 60;\n\ninterface Row {\n name: string;\n category: Category | null;\n healthScore: number | null;\n qualityScore: number | null;\n confidence: Confidence | null;\n latestVersion: string | null;\n weeklyDownloads: number | null;\n lastReleaseAt: Date | null;\n repoUrl: string | null;\n}\n\nexport async function recommend(\n db: Database,\n opts: RecommendOptions,\n provider: EmbeddingProvider = createEmbeddingProvider(),\n): Promise<Candidate[]> {\n const limit = Math.min(Math.max(opts.limit ?? 3, 1), 5);\n const [queryVec] = await provider.embed([opts.need]);\n if (!queryVec) return [];\n\n const category = opts.category ?? inferCategory(opts.need);\n const pool = Math.max(limit * 5, 25);\n\n // Primary search (category-filtered when we have one).\n let fused = await hybridSearch(db, queryVec, provider.id, opts.need, opts.constraints, category, pool);\n // If a category filter starved the results, broaden to all categories.\n if (category && fused.length < limit) {\n const broad = await hybridSearch(db, queryVec, provider.id, opts.need, opts.constraints, null, pool);\n const seen = new Set(fused.map((f) => f.row.name));\n fused = fused.concat(broad.filter((f) => !seen.has(f.row.name)));\n }\n if (fused.length === 0) return [];\n\n // Re-rank: blend normalized fused relevance (RRF) with the quality-aware\n // composite (§1). RRF rank-fusion already absorbs both retrieval legs, so the\n // relevance term rewards exact lexical hits the vector leg alone would miss.\n const lambda = loadWeights().composite.lambda;\n const maxRrf = Math.max(...fused.map((f) => f.rrf));\n const ranked = fused\n .map((f) => {\n const relevance = maxRrf > 0 ? f.rrf / maxRrf : 0;\n const composite = computeComposite(f.row.healthScore ?? 0, f.row.qualityScore, lambda) / 100;\n return { row: f.row, score: RELEVANCE_WEIGHT * relevance + COMPOSITE_WEIGHT * composite };\n })\n .sort((a, b) => b.score - a.score)\n .slice(0, limit);\n\n return ranked.map(({ row }) => toCandidate(row));\n}\n\ninterface Fused {\n row: Row;\n rrf: number;\n}\n\n/**\n * Run the vector and lexical retrievals and fuse them with RRF (§3). Each leg\n * independently ranks the candidate set; a doc's fused score is the sum of\n * 1/(k+rank) across the legs it appears in — so documents both legs agree on\n * rise, and exact-name hits the vector leg ranks poorly still surface.\n */\nasync function hybridSearch(\n db: Database,\n queryVec: number[],\n providerId: string,\n need: string,\n constraints: RecommendConstraints | undefined,\n category: Category | null,\n pool: number,\n): Promise<Fused[]> {\n const [vectorRows, lexicalRows] = await Promise.all([\n runVectorQuery(db, queryVec, providerId, constraints, category, pool),\n runLexicalQuery(db, need, constraints, category, pool),\n ]);\n return rrfFuse([vectorRows, lexicalRows]);\n}\n\n/**\n * Reciprocal Rank Fusion over N ranked lists (§3). A document's fused score is\n * Σ 1/(k + rank) across the lists it appears in — using only ranks, never raw\n * scores, so two incomparable scales (cosine distance vs ts_rank) never need\n * normalizing. Generic over `{ name }` so the fusion math is unit-testable.\n */\nexport function rrfFuse<T extends { name: string }>(\n lists: T[][],\n k = RRF_K,\n): { row: T; rrf: number }[] {\n const fused = new Map<string, { row: T; rrf: number }>();\n for (const list of lists) {\n list.forEach((row, idx) => {\n const contribution = 1 / (k + idx + 1); // rank is 1-based\n const prev = fused.get(row.name);\n if (prev) prev.rrf += contribution;\n else fused.set(row.name, { row, rrf: contribution });\n });\n }\n return [...fused.values()].sort((a, b) => b.rrf - a.rrf);\n}\n\nconst ROW_COLUMNS = {\n name: packages.name,\n category: packages.category,\n healthScore: packages.healthScore,\n qualityScore: packages.qualityScore,\n confidence: packages.confidence,\n latestVersion: packages.latestVersion,\n weeklyDownloads: packages.weeklyDownloads,\n lastReleaseAt: packages.lastReleaseAt,\n repoUrl: packages.repoUrl,\n} as const;\n\n/** Shared filter conditions (category + constraints) for both retrieval legs. */\nfunction buildConditions(\n constraints: RecommendConstraints | undefined,\n category: Category | null,\n) {\n const conditions = [];\n if (category) conditions.push(eq(packages.category, category));\n if (constraints?.license) conditions.push(eq(packages.license, constraints.license));\n if (constraints?.maxBundleKb !== undefined) {\n conditions.push(lte(packages.bundleMinGzipKb, constraints.maxBundleKb));\n }\n if (constraints?.minConfidence) {\n const allowed = (['proven', 'emerging', 'promising', 'unproven'] as Confidence[]).filter(\n (c) => CONFIDENCE_RANK[c] >= CONFIDENCE_RANK[constraints.minConfidence!],\n );\n conditions.push(\n sql`${packages.confidence} in ${sql.raw(`(${allowed.map((c) => `'${c}'`).join(',')})`)}`,\n );\n }\n return conditions;\n}\n\n/** Semantic leg: pgvector cosine, ordered by ascending distance. */\nasync function runVectorQuery(\n db: Database,\n queryVec: number[],\n providerId: string,\n constraints: RecommendConstraints | undefined,\n category: Category | null,\n pool: number,\n): Promise<Row[]> {\n const distance = cosineDistance(packages.embedding, queryVec);\n // Only compare vectors produced in the same space as the query vector. Rows\n // embedded by a different provider/model are excluded (they get retrieved by\n // the lexical leg instead) rather than compared across incompatible spaces.\n const conditions = [\n isNotNull(packages.embedding),\n eq(packages.embeddingProvider, providerId),\n ...buildConditions(constraints, category),\n ];\n return db\n .select(ROW_COLUMNS)\n .from(packages)\n .where(and(...conditions))\n .orderBy(distance)\n .limit(pool);\n}\n\n/** Lexical leg: full-text `tsvector` match, ranked by `ts_rank` (§3). */\nasync function runLexicalQuery(\n db: Database,\n need: string,\n constraints: RecommendConstraints | undefined,\n category: Category | null,\n pool: number,\n): Promise<Row[]> {\n const tsquery = sql`websearch_to_tsquery('english', ${need})`;\n const rank = sql<number>`ts_rank(${packages.searchVector}, ${tsquery})`;\n const conditions = [sql`${packages.searchVector} @@ ${tsquery}`, ...buildConditions(constraints, category)];\n return db\n .select(ROW_COLUMNS)\n .from(packages)\n .where(and(...conditions))\n .orderBy(sql`${rank} desc`)\n .limit(pool);\n}\n\nfunction toCandidate(row: Row): Candidate {\n return {\n name: row.name,\n category: row.category,\n healthScore: row.healthScore ?? 0,\n qualityScore: row.qualityScore,\n confidence: row.confidence ?? 'unproven',\n why: buildWhy(row),\n latestVersion: row.latestVersion,\n weeklyDownloads: row.weeklyDownloads,\n lastReleaseAt: row.lastReleaseAt ? row.lastReleaseAt.toISOString() : null,\n repoUrl: row.repoUrl,\n };\n}\n\n/** A ≤1-sentence rationale (§12.3.1). */\nfunction buildWhy(row: Row): string {\n const parts: string[] = [];\n if (row.confidence) parts.push(row.confidence);\n if (row.weeklyDownloads) parts.push(`${formatDownloads(row.weeklyDownloads)} weekly downloads`);\n if (row.healthScore !== null) parts.push(`health ${row.healthScore}`);\n return parts.join(', ') || 'tracked package';\n}\n\nfunction formatDownloads(n: number): string {\n if (n >= 1_000_000) return `${Math.round(n / 100_000) / 10}M`;\n if (n >= 1_000) return `${Math.round(n / 1_000)}k`;\n return String(n);\n}\n","/**\n * Supply-chain risk gate.\n *\n * Rolls the individual findings from `verify` into a single level an agent can\n * act on before installing:\n * high — do not install without human review\n * medium — proceed with caution / prefer an alternative\n * low — no supply-chain red flags\n *\n * Install scripts alone are NOT escalated (esbuild, sharp, husky all use them);\n * they only matter on an otherwise low-trust package.\n */\nimport type { RiskLevel } from '../core/types';\n\nexport interface RiskInput {\n /** All collected riskFlags (used for the `single-maintainer` signal). */\n flags: string[];\n hasCriticalOrHighAdvisory: boolean;\n /** Name closely mimics a popular package. */\n typosquat: boolean;\n /** Runs preinstall/install/postinstall hooks. */\n installScripts: boolean;\n /** First published within the last 7 days. */\n brandNew: boolean;\n /** Fewer than ~1k weekly downloads (or unknown). */\n lowTrust: boolean;\n deprecatedOrArchived: boolean;\n}\n\nexport function assessRisk(i: RiskInput): RiskLevel {\n // Classic malware fingerprint: brand-new + install hooks + ~no adoption.\n const malwarePattern = i.installScripts && i.brandNew && i.lowTrust;\n if (i.typosquat || i.hasCriticalOrHighAdvisory || malwarePattern) return 'high';\n\n if (\n i.deprecatedOrArchived ||\n (i.installScripts && (i.lowTrust || i.brandNew)) ||\n (i.lowTrust && i.flags.includes('single-maintainer'))\n ) {\n return 'medium';\n }\n return 'low';\n}\n","[\n \"react\", \"react-dom\", \"react-router\", \"react-router-dom\", \"next\", \"vue\",\n \"vue-router\", \"pinia\", \"vuex\", \"svelte\", \"solid-js\", \"preact\", \"angular\",\n \"@angular/core\", \"jquery\", \"lodash\", \"underscore\", \"ramda\", \"immer\", \"rxjs\",\n \"express\", \"koa\", \"fastify\", \"@nestjs/core\", \"hapi\", \"connect\", \"body-parser\",\n \"cookie-parser\", \"cors\", \"helmet\", \"morgan\", \"compression\", \"express-session\",\n \"express-rate-limit\", \"multer\", \"passport\", \"jsonwebtoken\", \"bcrypt\",\n \"bcryptjs\", \"axios\", \"node-fetch\", \"got\", \"undici\", \"superagent\", \"request\",\n \"cheerio\", \"puppeteer\", \"playwright\", \"cypress\", \"jsdom\", \"ws\", \"socket.io\",\n \"socket.io-client\", \"graphql\", \"@apollo/client\", \"apollo-server\", \"dataloader\",\n \"mongoose\", \"mongodb\", \"pg\", \"mysql2\", \"sequelize\", \"prisma\", \"knex\",\n \"drizzle-orm\", \"typeorm\", \"redis\", \"ioredis\", \"sqlite3\", \"better-sqlite3\",\n \"typescript\", \"eslint\", \"prettier\", \"tslint\", \"webpack\", \"vite\", \"rollup\",\n \"esbuild\", \"parcel\", \"@babel/core\", \"babel-core\", \"babel-loader\", \"ts-node\",\n \"tsx\", \"tsup\", \"nodemon\", \"concurrently\", \"npm-run-all\", \"jest\", \"vitest\",\n \"mocha\", \"chai\", \"sinon\", \"ava\", \"tape\", \"supertest\", \"@testing-library/react\",\n \"enzyme\", \"chalk\", \"colors\", \"kleur\", \"picocolors\", \"ansi-colors\", \"commander\",\n \"yargs\", \"meow\", \"minimist\", \"inquirer\", \"prompts\", \"ora\", \"boxen\", \"figlet\",\n \"cli-progress\", \"debug\", \"dotenv\", \"cross-env\", \"rimraf\", \"glob\", \"fast-glob\",\n \"chokidar\", \"fs-extra\", \"execa\", \"cross-spawn\", \"shelljs\", \"which\", \"semver\",\n \"uuid\", \"nanoid\", \"ulid\", \"moment\", \"dayjs\", \"date-fns\", \"luxon\", \"zod\", \"yup\",\n \"joi\", \"ajv\", \"validator\", \"class-validator\", \"winston\", \"pino\", \"bunyan\",\n \"nodemailer\", \"node-cron\", \"bull\", \"bullmq\", \"kafkajs\", \"amqplib\", \"sharp\",\n \"jimp\", \"archiver\", \"tar\", \"adm-zip\", \"qs\", \"query-string\", \"form-data\",\n \"mime-types\", \"http-errors\", \"classnames\", \"clsx\", \"styled-components\",\n \"@emotion/react\", \"tailwindcss\", \"postcss\", \"autoprefixer\", \"sass\", \"less\",\n \"framer-motion\", \"three\", \"d3\", \"chart.js\", \"recharts\", \"gsap\", \"swiper\",\n \"leaflet\", \"mapbox-gl\", \"formik\", \"react-hook-form\", \"redux\", \"@reduxjs/toolkit\",\n \"zustand\", \"jotai\", \"mobx\", \"bootstrap\", \"@popperjs/core\", \"aws-sdk\",\n \"@aws-sdk/client-s3\", \"firebase\", \"firebase-admin\", \"stripe\", \"twilio\",\n \"openai\", \"@anthropic-ai/sdk\", \"googleapis\", \"bignumber.js\", \"decimal.js\",\n \"mathjs\", \"slugify\", \"faker\", \"@faker-js/faker\", \"puppeteer-core\"\n]\n","/**\n * Typosquat detection.\n *\n * A package whose name is a near-miss of a popular one (`crossenv` for\n * `cross-env`, `expres` for `express`) is the classic supply-chain attack: a\n * coding agent fat-fingers or hallucinates a name and installs the impostor.\n * We compare a queried name against the most-downloaded packages lurq already\n * tracks — a tiny edit distance to a popular name the package itself is NOT is\n * a strong signal.\n */\nimport popularPackages from '../data/popular-packages.json';\n\n/** Static baseline of well-known npm names. Unioned with the tracked corpus so\n * detection still works on a cold/thin index (fresh deploy, few syncs) and\n * catches squats of famous packages that aren't tracked yet. */\nconst POPULAR_BASELINE = popularPackages as string[];\n\n/** Tracked top-downloads names + the static baseline, de-duplicated. Pass the\n * result as the corpus to `detectTyposquat` so the guard is never silently off. */\nexport function typosquatCorpus(trackedTopNames: string[]): string[] {\n return [...new Set([...POPULAR_BASELINE, ...trackedTopNames])];\n}\n\n/** `@scope/name` → `name` so scope decoration doesn't dominate the distance. */\nfunction bareName(name: string): string {\n const slash = name.indexOf('/');\n return (slash >= 0 ? name.slice(slash + 1) : name).toLowerCase();\n}\n\n/**\n * Damerau-Levenshtein (optimal string alignment) edit distance — counts\n * insertions, deletions, substitutions, and adjacent transpositions.\n */\nexport function editDistance(a: string, b: string): number {\n const m = a.length;\n const n = b.length;\n if (m === 0) return n;\n if (n === 0) return m;\n\n // Rolling rows: prevPrev enables the adjacent-transposition check.\n let prevPrev = new Array<number>(n + 1).fill(0);\n let prev = Array.from({ length: n + 1 }, (_, j) => j);\n for (let i = 1; i <= m; i++) {\n const cur = new Array<number>(n + 1).fill(0);\n cur[0] = i;\n for (let j = 1; j <= n; j++) {\n const cost = a[i - 1] === b[j - 1] ? 0 : 1;\n let val = Math.min(\n (prev[j] ?? 0) + 1,\n (cur[j - 1] ?? 0) + 1,\n (prev[j - 1] ?? 0) + cost,\n );\n if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) {\n val = Math.min(val, (prevPrev[j - 2] ?? 0) + 1);\n }\n cur[j] = val;\n }\n prevPrev = prev;\n prev = cur;\n }\n return prev[n] ?? 0;\n}\n\nexport type TyposquatHit = { target: string; distance: number };\n\n/**\n * Closest popular package within `maxDistance` edits, or null. The queried name\n * being popular itself is never a hit. Names shorter than 4 chars are skipped —\n * at that length a single edit is noise, not an attack signal.\n */\nexport function detectTyposquat(\n name: string,\n popular: readonly string[],\n maxDistance = 2,\n): TyposquatHit | null {\n const target = bareName(name);\n if (target.length < 4) return null;\n if (popular.some((p) => p.toLowerCase() === name.toLowerCase())) return null;\n\n let best: TyposquatHit | null = null;\n for (const p of popular) {\n const cand = bareName(p);\n if (cand === target) continue; // same bare name (e.g. a fork under a scope)\n if (Math.abs(cand.length - target.length) > maxDistance) continue; // can't be close\n const dist = editDistance(target, cand);\n if (dist >= 1 && dist <= maxDistance && (!best || dist < best.distance)) {\n best = { target: p, distance: dist };\n if (dist === 1) break; // nothing closer is possible\n }\n }\n return best;\n}\n","/**\n * MCP tool handlers (§12.3). Pure functions over a Database — the transport\n * layer (server.ts) just wires zod schemas to these. Responses are kept compact\n * (§12.4): summaries truncated, advisories capped, no raw payloads, always a\n * `dataAsOf` and a `stale` hint when data is old (§17).\n */\nimport { createHash } from 'node:crypto';\nimport { sql } from 'drizzle-orm';\nimport { cached } from '../core/cache';\nimport { STALENESS_DAYS } from '../core/constants';\nimport type {\n Advisory,\n AdvisorySeverity,\n BuildSignal,\n BuildVerified,\n Category,\n CompatOutput,\n Confidence,\n EvaluateOutput,\n VerifyOutput,\n} from '../core/types';\nimport { checkCompat } from '../compat/check';\nimport type { Database } from '../db/client';\nimport { getTopPackageNames } from '../db/packages';\nimport { getLatestVerificationByName } from '../db/verification';\nimport { recordOutcome } from '../db/outcomes';\nimport { lookupSuccessor } from '../core/successors';\nimport type { VerificationRunRow } from '../db/schema';\nimport { packages, type PackageRow } from '../db/schema';\nimport { fetchNpmRegistry, fetchWeeklyDownloads, npmPackageExists } from '../ingestion/sources';\nimport { truncateSentences } from '../ingestion/summarize';\nimport { getOrFetchPackage } from '../pipeline/single';\nimport { hasCriticalOrHighAdvisory } from '../scoring/score';\nimport { recommend, type RecommendOptions } from '../search/recommend';\nimport { assessRisk } from '../security/risk';\nimport { detectTyposquat, typosquatCorpus } from '../security/typosquat';\n\nconst SEVERITY_RANK: Record<AdvisorySeverity, number> = {\n critical: 4,\n high: 3,\n moderate: 2,\n low: 1,\n info: 0,\n};\nconst DAY_MS = 24 * 60 * 60 * 1000;\n\nfunction isStale(dataAsOf: Date | null): boolean {\n if (!dataAsOf) return true;\n return Date.now() - dataAsOf.getTime() > STALENESS_DAYS * DAY_MS;\n}\n\n/** Re-derive the wall-clock `stale` hint (§17) on a (possibly cached) evaluate\n * row, so a cached response doesn't keep claiming fresh data after it ages past\n * the threshold between syncs. */\nfunction refreshStale(out: EvaluateOutput): EvaluateOutput {\n out.stale = isStale(out.dataAsOf ? new Date(out.dataAsOf) : null) || undefined;\n return out;\n}\n\nfunction withinDays(date: Date | null, days: number): boolean {\n return date ? Date.now() - date.getTime() <= days * DAY_MS : false;\n}\n\n/** Top advisories by severity, capped (§12.4). */\nfunction topAdvisories(advisories: Advisory[] | null, max = 5): Advisory[] {\n if (!advisories?.length) return [];\n return [...advisories]\n .sort((a, b) => SEVERITY_RANK[b.severity] - SEVERITY_RANK[a.severity])\n .slice(0, max);\n}\n\n/** Map a stored row to the compact EvaluateOutput shape (§12.3.2). */\nexport function rowToEvaluate(row: PackageRow): EvaluateOutput {\n const breakdown = row.scoreBreakdown ?? {\n maintenance: 0,\n adoption: 0,\n reliability: 0,\n efficiency: null,\n quality: null,\n };\n return {\n dataAsOf: (row.dataAsOf ?? new Date()).toISOString(),\n stale: isStale(row.dataAsOf) || undefined,\n name: row.name,\n category: row.category,\n healthScore: row.healthScore ?? 0,\n qualityScore: row.qualityScore ?? null,\n confidence: (row.confidence as Confidence) ?? 'unproven',\n scoreBreakdown: breakdown,\n latestVersion: row.latestVersion,\n lastReleaseAt: row.lastReleaseAt ? row.lastReleaseAt.toISOString() : null,\n weeklyDownloads: row.weeklyDownloads,\n downloadGrowth90d: row.downloadGrowth90d,\n scorecard: row.scorecard,\n bundleMinGzipKb: row.bundleMinGzipKb,\n deprecated: row.deprecated,\n archived: row.archived,\n advisories: topAdvisories(row.advisories),\n summary: row.summary ? truncateSentences(row.summary, 3) : null,\n usageGuide: row.usageGuide ?? null,\n repoUrl: row.repoUrl,\n replacedBy: lookupSuccessor(row.name),\n };\n}\n\nexport async function latestDataAsOf(db: Database): Promise<string> {\n const [row] = await db\n .select({ m: sql<string | null>`max(${packages.dataAsOf})` })\n .from(packages);\n return new Date(row?.m ?? Date.now()).toISOString();\n}\n\n// ── recommend ───────────────────────────────────────────────────────────────\n\nexport interface RecommendInput {\n need: string;\n category?: Category;\n constraints?: RecommendOptions['constraints'];\n}\n\n/** Short, stable cache key from arbitrary input. */\nfunction cacheKey(parts: unknown): string {\n return createHash('sha1').update(JSON.stringify(parts)).digest('hex').slice(0, 24);\n}\n\nexport async function handleRecommend(db: Database, input: RecommendInput) {\n return cached(\n 'rec',\n cacheKey([input.need, input.category ?? null, input.constraints ?? null]),\n async () => {\n const candidates = await recommend(db, {\n need: input.need,\n category: input.category,\n constraints: input.constraints,\n limit: 5,\n });\n return { dataAsOf: await latestDataAsOf(db), candidates };\n },\n // Don't cache empty results — the index may still be populating.\n { skipCache: (r) => r.candidates.length === 0 },\n );\n}\n\n// ── evaluate ────────────────────────────────────────────────────────────────\n\nexport async function handleEvaluate(\n db: Database,\n input: { package: string },\n): Promise<EvaluateOutput | { tracked: false; suggestion: string }> {\n const out = await cached(\n 'eval',\n cacheKey([input.package]),\n async () => {\n const { row, existsOnNpm } = await getOrFetchPackage(db, input.package);\n if (!row) {\n return {\n tracked: false as const,\n suggestion: existsOnNpm\n ? `🎉 Congrats — you're the first to add \"${input.package}\" to lurq's registry! It's being fetched and scored now; retry in a few seconds for the full evidence read.`\n : `\"${input.package}\" was not found on the npm registry. Check the package name.`,\n };\n }\n const evaluated = rowToEvaluate(row);\n const verification = await getLatestVerificationByName(db, row.name);\n return verification\n ? { ...evaluated, buildVerified: toBuildVerified(verification) }\n : evaluated;\n },\n // Don't cache \"not found / not scored yet\" — it may resolve on a later fetch.\n { skipCache: (r) => 'tracked' in r },\n );\n // Re-derive the time-based stale hint, which a cached row would otherwise freeze.\n return 'tracked' in out ? out : refreshStale(out);\n}\n\n// ── compare ─────────────────────────────────────────────────────────────────\n\nexport async function handleCompare(db: Database, input: { packages: string[] }) {\n // Key on the exact input — the response echoes the caller's own names/order in\n // `missing`, so a normalized key would serve another caller's casing.\n const out = await cached(\n 'cmp',\n cacheKey(input.packages),\n async () => {\n const results = await Promise.all(input.packages.map((name) => getOrFetchPackage(db, name)));\n const rows = results\n .map((r) => r.row)\n .filter((row): row is PackageRow => row !== null)\n .map(rowToEvaluate)\n .sort((a, b) => b.healthScore - a.healthScore);\n const missing = input.packages.filter((name) => !rows.some((r) => r.name === name));\n return {\n dataAsOf: await latestDataAsOf(db),\n rows,\n ...(missing.length\n ? {\n missing,\n note: \"🎉 You're the first to add these to lurq's registry! They're being scored now; retry shortly for the full comparison.\",\n }\n : {}),\n };\n },\n // Don't cache a transient miss (a package that momentarily failed to fetch).\n { skipCache: (r) => Boolean((r as { missing?: string[] }).missing?.length) },\n );\n out.rows = out.rows.map(refreshStale);\n return out;\n}\n\n// ── compat ──────────────────────────────────────────────────────────────────\n\nfunction toBuildVerified(v: VerificationRunRow): BuildVerified {\n return {\n version: v.version,\n installed: v.installed,\n loaded: v.imported,\n driver: v.driver,\n ranAt: v.ranAt ? v.ranAt.toISOString() : '',\n };\n}\n\n/**\n * Whole-architecture compatibility for a set of packages: Tier-1 peer/engine\n * analysis + recorded Tier-2 sandbox conflicts (see compat/check).\n */\nexport async function handleCompat(\n db: Database,\n input: { packages: string[] },\n): Promise<CompatOutput> {\n return checkCompat(db, input.packages);\n}\n\n// ── verify ──────────────────────────────────────────────────────────────────\n\nexport async function handleVerify(\n db: Database,\n input: { package: string },\n): Promise<VerifyOutput> {\n const name = input.package;\n const exists = await npmPackageExists(name);\n if (!exists) {\n // A name that doesn't exist but closely mimics a popular one is a squat the\n // agent was about to fall for — surface the suspected target.\n const typo = detectTyposquat(name, typosquatCorpus(await getTopPackageNames(db).catch(() => [])));\n return {\n exists: false,\n tracked: false,\n deprecated: false,\n archived: false,\n latestVersion: null,\n weeklyDownloads: null,\n riskFlags: typo\n ? ['not-found-on-registry', `possible-typosquat-of:${typo.target}`]\n : ['not-found-on-registry'],\n risk: 'high',\n typosquatOf: typo?.target ?? null,\n confidence: null,\n advisoryCount: 0,\n };\n }\n\n const [registry, { row, wasTracked }, popular] = await Promise.all([\n fetchNpmRegistry(name).catch(() => null),\n getOrFetchPackage(db, name),\n getTopPackageNames(db).catch(() => [] as string[]),\n ]);\n\n // On-demand ingestion is now async, so an untracked package has no row yet.\n // Fetch weekly downloads live (one cheap call) rather than let the risk flags\n // falsely trip 'zero-downloads' on a popular package the index hasn't caught up\n // to. Only pays the extra call on the untracked path.\n const weeklyDownloads = row?.weeklyDownloads ?? (await fetchWeeklyDownloads(name).catch(() => null));\n const advisories = row?.advisories ?? [];\n const advisoryCount = advisories.length;\n const deprecated = Boolean(row?.deprecated || registry?.deprecated);\n const archived = Boolean(row?.archived);\n const brandNew = withinDays(registry?.firstPublishedAt ?? null, 7);\n const lowTrust = weeklyDownloads === null || weeklyDownloads < 1000;\n const installScripts = registry?.hasInstallScripts ?? false;\n const typo = detectTyposquat(name, typosquatCorpus(popular));\n\n const riskFlags: string[] = [];\n if (typo) riskFlags.push(`possible-typosquat-of:${typo.target}`);\n if (weeklyDownloads === null || weeklyDownloads === 0) riskFlags.push('zero-downloads');\n else if (weeklyDownloads < 1000) riskFlags.push('low-downloads');\n if (brandNew) riskFlags.push('published-within-7-days');\n if (registry?.maintainersCount === 1) riskFlags.push('single-maintainer');\n if (installScripts) riskFlags.push('runs-install-scripts');\n if (advisoryCount > 0) riskFlags.push('has-known-advisory');\n if (deprecated) riskFlags.push('deprecated');\n if (archived) riskFlags.push('archived');\n\n const risk = assessRisk({\n flags: riskFlags,\n hasCriticalOrHighAdvisory: hasCriticalOrHighAdvisory(advisories),\n typosquat: Boolean(typo),\n installScripts,\n brandNew,\n lowTrust,\n deprecatedOrArchived: deprecated || archived,\n });\n\n return {\n exists: true,\n tracked: wasTracked,\n deprecated,\n archived,\n latestVersion: registry?.latestVersion ?? row?.latestVersion ?? null,\n weeklyDownloads,\n riskFlags,\n risk,\n typosquatOf: typo?.target ?? null,\n confidence: (row?.confidence as Confidence) ?? null,\n advisoryCount,\n };\n}\n\n// ── report_outcome ────────────────────────────────────────────────────────────\n\nexport interface ReportOutcomeInput {\n package: string;\n accepted: boolean;\n buildSignal?: BuildSignal;\n need?: string;\n}\n\n/**\n * Capture an opt-in recommendation outcome (§3.1). Append-only, no source code —\n * just which package, accepted or not, and a coarse build signal. Not cached (a\n * write), and cheap enough that the per-key rate limiter is the only guard needed.\n * `ownerId` is server-injected from the authenticated key, attributing the\n * outcome to an org so the flywheel accrues per-customer, not to a global pool.\n */\nexport async function handleReportOutcome(\n db: Database,\n input: ReportOutcomeInput,\n ownerId: string | null = null,\n): Promise<{ recorded: true }> {\n await recordOutcome(db, {\n ownerId,\n packageName: input.package,\n accepted: input.accepted,\n buildSignal: input.buildSignal ?? null,\n need: input.need ?? null,\n });\n return { recorded: true };\n}\n","/**\n * Optional `diagram` tool (§12.3.5). Emits a reference-architecture Mermaid\n * diagram for a stack the caller has *already chosen* (package names), using\n * built-in layer patterns. Input is stack-only by design: inferring an\n * architecture from a freeform description is the \"architecture oracle\" behavior\n * that the master spec (§4) and roadmap (§1) declare a non-goal. lurq labels a\n * stack you name; it does not design one. A starting point, not a validator.\n *\n * Honesty over completeness:\n * - A package we can't classify (not in the index AND no category match) is\n * placed in an explicit `Unclassified` bucket — never silently dropped into a\n * default layer. The note lists what couldn't be placed. Partial, not\n * authoritative.\n * - KNOWN LIMITATION — front/back framework ambiguity: the taxonomy has a single\n * `framework` category, so a `framework` package can't be told apart as\n * frontend vs backend from its category alone. BACKEND_FRAMEWORKS is a\n * hand-maintained band-aid that re-routes the common backend frameworks to the\n * Backend layer; it degrades as the ecosystem adds new ones (an unlisted\n * backend framework will be drawn in Presentation). The real fix is a taxonomy\n * change (a distinct backend-framework category or a runtime/target flag on\n * packages), which is out of scope for v1. Documented, not solved.\n */\nimport { inArray } from 'drizzle-orm';\nimport type { Category } from '../core/types';\nimport { inferCategory } from '../search/categoryInference';\nimport type { Database } from '../db/client';\nimport { packages } from '../db/schema';\n\n/** Bucket for packages we cannot place: unknown category, or a category with no\n * real architectural home (e.g. `other`). Rendered, but kept out of the flow. */\nconst UNCLASSIFIED = 'Unclassified';\n\n/** Which architectural layer each category sits in. Categories with no honest\n * architectural home (e.g. `other`) are intentionally absent: layerFor routes\n * anything unmapped to UNCLASSIFIED rather than faking a layer. */\nconst LAYER_OF: Partial<Record<Category, string>> = {\n framework: 'Presentation',\n 'meta-framework': 'Presentation',\n 'ui-component-library': 'Presentation',\n styling: 'Presentation',\n animation: 'Presentation',\n charts: 'Presentation',\n 'state-management': 'Client Logic',\n routing: 'Client Logic',\n forms: 'Client Logic',\n validation: 'Client Logic',\n 'data-fetching': 'Client Logic',\n 'http-client': 'Client Logic',\n i18n: 'Client Logic',\n 'date-time': 'Client Logic',\n utility: 'Client Logic',\n auth: 'Backend',\n orm: 'Data',\n 'database-client': 'Data',\n 'build-tool': 'Tooling',\n bundler: 'Tooling',\n linting: 'Tooling',\n testing: 'Tooling',\n};\n\nconst FLOW_LAYERS = ['Presentation', 'Client Logic', 'Backend', 'Data'];\n\n/** Band-aid for the front/back framework ambiguity (see file header). Category\n * `framework` alone can't distinguish frontend from backend, so these common\n * backend frameworks are re-routed to the Backend layer. Hand-maintained;\n * unlisted backend frameworks will be mis-drawn in Presentation. Not a real fix. */\nconst BACKEND_FRAMEWORKS = new Set([\n 'express',\n 'fastify',\n 'koa',\n 'hono',\n '@nestjs/core',\n '@hapi/hapi',\n]);\n\nexport interface Item {\n label: string;\n /** null = could not be classified (not in index, no category match). */\n category: Category | null;\n}\n\nexport function layerFor(item: Item): string {\n if (!item.category) return UNCLASSIFIED;\n if (item.category === 'framework' && BACKEND_FRAMEWORKS.has(item.label)) return 'Backend';\n return LAYER_OF[item.category] ?? UNCLASSIFIED;\n}\n\nfunction nodeId(label: string, i: number): string {\n return `n${i}_${label.replace(/[^a-zA-Z0-9]/g, '_')}`;\n}\n\nexport function buildMermaid(items: Item[]): string {\n const byLayer = new Map<string, Item[]>();\n for (const item of items) {\n const layer = layerFor(item);\n const list = byLayer.get(layer) ?? [];\n list.push(item);\n byLayer.set(layer, list);\n }\n\n const lines = ['flowchart TD', ' user([User])'];\n const ids = new Map<string, string>(); // label → node id\n let counter = 0;\n const repNode = new Map<string, string>(); // layer → first node id\n\n const emitLayer = (layer: string) => {\n const list = byLayer.get(layer);\n if (!list?.length) return;\n lines.push(` subgraph ${layer.replace(/\\s+/g, '_')}[\"${layer}\"]`);\n for (const item of list) {\n const id = nodeId(item.label, counter++);\n ids.set(item.label, id);\n if (!repNode.has(layer)) repNode.set(layer, id);\n // Unclassified nodes carry no category prefix — we don't claim one we lack.\n const text = layer === UNCLASSIFIED ? item.label : `${item.category}: ${item.label}`;\n lines.push(` ${id}[\"${text}\"]`);\n }\n lines.push(' end');\n };\n\n for (const layer of FLOW_LAYERS) emitLayer(layer);\n emitLayer('Tooling');\n emitLayer(UNCLASSIFIED);\n\n // Connect the flow layers that are present, top to bottom.\n const present = FLOW_LAYERS.filter((l) => byLayer.has(l));\n let prev = 'user';\n for (const layer of present) {\n lines.push(` ${prev} --> ${repNode.get(layer)}`);\n prev = repNode.get(layer)!;\n }\n if (byLayer.has('Data')) lines.push(` ${repNode.get('Data')} --> db[(Database)]`);\n\n return lines.join('\\n');\n}\n\nexport interface DiagramInput {\n stack?: string[];\n}\n\nexport async function handleDiagram(\n db: Database,\n input: DiagramInput,\n): Promise<{ mermaid: string; note: string }> {\n if (!input.stack?.length) {\n return {\n mermaid: 'flowchart TD\\n user([User]) --> app[Application]',\n note: 'Provide a `stack` of package names to diagram. lurq labels a stack you choose; it does not infer an architecture from a description.',\n };\n }\n\n const rows = await db\n .select({ name: packages.name, category: packages.category })\n .from(packages)\n .where(inArray(packages.name, input.stack));\n const known = new Map(rows.map((r) => [r.name, r.category]));\n // inferCategory is best-effort on a bare package name (it was built for NL\n // needs); a miss yields null, not a faked category. No silent 'other'.\n const items: Item[] = input.stack.map((name) => ({\n label: name,\n category: known.get(name) ?? inferCategory(name),\n }));\n\n const unclassified = items.filter((i) => layerFor(i) === UNCLASSIFIED).map((i) => i.label);\n const note = unclassified.length\n ? `Reference pattern derived from the provided stack — partial, not authoritative. Could not place ${unclassified.length} package(s): ${unclassified.join(', ')} (not in lurq's index and no category match) — shown under Unclassified, outside the flow.`\n : 'Reference pattern derived from the provided stack. A labeled starting point, not a validated architecture.';\n\n return { mermaid: buildMermaid(items), note };\n}\n","/**\n * Global stack optimizer.\n *\n * Branch-and-bound over each slot's ranked candidates to find the highest-quality\n * combination that's compatible — the globally optimal coherent stack, not the\n * greedy local one. \"Quality\" is rank-regret: each candidate's index in its slot\n * (0 = the top pick), so the objective is to deviate from the ideal ranking as\n * little as possible while staying conflict-free.\n *\n * The feasibility oracle is instant (Tier-1 peer/engine math + pre-loaded sandbox\n * conflict edges), so the search runs purely in memory. Two prunes keep the tree\n * tiny: feasibility (a partial pick that already conflicts can never un-conflict)\n * and bound (a branch whose regret already exceeds the best feasible stack can't\n * win). Both are provably safe, so within the search budget the result is\n * order-independent — the optimum.\n *\n * A node budget caps pathological search spaces (many slots × many candidates).\n * If it's hit the search returns the best stack found so far and sets\n * `bounded: true` — best-effort, no longer a proof of optimality. At realistic\n * stack sizes the budget is never approached.\n */\nimport type { CompatConflict } from '../core/types';\nimport { resolveArchitectureCompat, type CompatMember } from './peerCompat';\n\nexport interface OptimizeResult {\n /** Chosen candidate index per slot (0 = top pick; higher = more regret). */\n selection: number[];\n conflicts: CompatConflict[];\n /** Sum of chosen indices — how far the stack drifted from the ideal ranking. */\n regret: number;\n /** True if the node budget was exhausted: the result is best-effort, not a\n * proven optimum. False (the normal case) means the search completed. */\n bounded: boolean;\n}\n\n/** Conflicts for a (partial) selection: Tier-1 peer/engine + cached sandbox edges. */\nfunction conflictsFor(members: CompatMember[], sandboxConflicts: Set<string>): CompatConflict[] {\n const out = resolveArchitectureCompat(members);\n for (let i = 0; i < members.length; i++) {\n for (let j = i + 1; j < members.length; j++) {\n const a = members[i]!.name;\n const b = members[j]!.name;\n const key = a <= b ? `${a}|${b}` : `${b}|${a}`;\n if (sandboxConflicts.has(key)) {\n out.push({\n source: 'sandbox',\n packages: [a, b],\n detail: `${a} and ${b} are recorded as incompatible (sandbox)`,\n });\n }\n }\n }\n return out;\n}\n\n/**\n * Pick one candidate per slot to minimise total rank-regret subject to\n * compatibility. `slots[i]` is slot i's candidates in preference order.\n */\nexport function optimizeStack(\n slots: CompatMember[][],\n sandboxConflicts: Set<string> = new Set(),\n): OptimizeResult {\n // Every slot must offer at least one candidate — otherwise the non-null\n // indexing below (`slots[s]![idx]!`) yields undefined and crashes in\n // conflictsFor. Callers pre-filter, but keep the exported fn safe to reuse.\n if (slots.some((s) => s.length === 0)) {\n throw new Error('optimizeStack: every slot must have at least one candidate');\n }\n\n const n = slots.length;\n const budget = 50_000;\n let nodes = 0;\n let exhausted = false;\n\n // Incumbent: top pick of every slot. Only a *feasible* stack bounds the search.\n let bestSelection = new Array<number>(n).fill(0);\n let bestRegret = conflictsFor(\n slots.map((c) => c[0]).filter((m): m is CompatMember => Boolean(m)),\n sandboxConflicts,\n ).length === 0\n ? 0\n : Infinity;\n\n const chosen = new Array<number>(n).fill(0);\n const dfs = (slot: number, regret: number): void => {\n if (nodes++ > budget) {\n exhausted = true;\n return;\n }\n if (regret >= bestRegret) return; // bound prune\n if (slot === n) {\n bestSelection = chosen.slice();\n bestRegret = regret;\n return;\n }\n const candidates = slots[slot]!;\n for (let i = 0; i < candidates.length; i++) {\n chosen[slot] = i;\n // Feasibility prune: a conflict among assigned members is permanent, so a\n // partial pick that already conflicts can never become compatible.\n const assigned = chosen.slice(0, slot + 1).map((idx, s) => slots[s]![idx]!);\n if (conflictsFor(assigned, sandboxConflicts).length === 0) {\n dfs(slot + 1, regret + i);\n }\n if (nodes > budget) {\n exhausted = true;\n return;\n }\n }\n };\n dfs(0, 0);\n\n const members = bestSelection.map((idx, s) => slots[s]![idx]!);\n return {\n selection: bestSelection,\n conflicts: conflictsFor(members, sandboxConflicts),\n regret: bestRegret === Infinity ? bestSelection.reduce((a, b) => a + b, 0) : bestRegret,\n bounded: exhausted,\n };\n}\n","/**\n * `plan` tool — turn a described program into an evidence-scored build plan.\n *\n * This is NOT the \"architecture oracle\" non-goal (master-spec §4): it does not\n * invent an architecture from a one-line prompt. It takes a program the caller\n * has *already described in detail* (a spec/README) — or a pre-decomposed list\n * of needs — and runs lurq's normal `recommend` engine slot-by-slot, returning\n * real packages from the index with their scores. lurq still \"supplies building\n * blocks slot-by-slot; the agent assembles the architecture\" (§1.3). The rich\n * input is what removes the guesswork the spec warned against; the §20 roadmap\n * item (\"architecture recommendation … once data can ground it\") is honored\n * because every recommendation is grounded in the scored index.\n *\n * Decomposition (document → needs) follows Option C:\n * - a caller-supplied `needs[]` is used as-is (the agent already read the doc — the\n * fast, zero-LLM path, and the cleanest companion-model division of labor); else\n * - a raw `document` is decomposed server-side: by the summary LLM when a key is\n * configured, otherwise by a transparent heading/keyword heuristic. The heuristic\n * is honest-but-coarse, and the response note says so.\n */\nimport { createHash } from 'node:crypto';\nimport { inArray } from 'drizzle-orm';\nimport { getConfig } from '../core/config';\nimport { httpRequest } from '../core/http';\nimport { checkCompat } from '../compat/check';\nimport { assembleMembers } from '../compat/members';\nimport { optimizeStack } from '../compat/optimize';\nimport type { CompatMember } from '../compat/peerCompat';\nimport { getCompatEdges } from '../db/compat';\nimport { logger } from '../core/logger';\nimport {\n isCategory,\n type Candidate,\n type Category,\n type CompatConflict,\n type CompatOutput,\n} from '../core/types';\nimport type { Database } from '../db/client';\nimport { packages } from '../db/schema';\nimport { inferCategory } from '../search/categoryInference';\nimport { recommend } from '../search/recommend';\nimport { getOrFetchPackage } from '../pipeline/single';\nimport type { PackageRow } from '../db/schema';\nimport { buildMermaid, layerFor } from './diagram';\nimport { latestDataAsOf } from './handlers';\n\n/** A pinned package the user chose, resolved to a fixed single-candidate slot. */\nfunction packageToCandidate(row: PackageRow): Candidate {\n return {\n name: row.name,\n category: row.category,\n healthScore: row.healthScore ?? 0,\n qualityScore: row.qualityScore,\n confidence: row.confidence ?? 'unproven',\n why: 'pinned by you',\n latestVersion: row.latestVersion,\n weeklyDownloads: row.weeklyDownloads,\n lastReleaseAt: row.lastReleaseAt ? row.lastReleaseAt.toISOString() : null,\n repoUrl: row.repoUrl,\n };\n}\n\n/** Resolve user-pinned packages into fixed slots (one candidate, no alternatives)\n * so the optimizer routes the recommended slots around them. Unresolvable pins\n * (not on npm) are returned so the caller can report them. */\nexport async function resolvePins(\n db: Database,\n using: string[] | undefined,\n recommendedNames: Set<string>,\n): Promise<{ slots: PlanSlot[]; unresolved: string[] }> {\n const slots: PlanSlot[] = [];\n const unresolved: string[] = [];\n // Dedupe, and skip a pin the recommender already picked (avoid double slots).\n for (const name of new Set(using ?? [])) {\n if (recommendedNames.has(name)) continue;\n const { row } = await getOrFetchPackage(db, name);\n if (!row) {\n unresolved.push(name);\n continue;\n }\n slots.push({\n need: `using ${name}`,\n category: row.category,\n layer: layerFor({ label: name, category: row.category }),\n recommended: packageToCandidate(row),\n alternatives: [], // fixed: the user chose this, so it never gets swapped\n note: 'pinned by you',\n });\n }\n return { slots, unresolved };\n}\n\n/** A single component/slot to recommend a package for. */\nexport interface PlanNeed {\n need: string;\n category?: Category;\n}\n\nexport interface PlanInput {\n /** Detailed description of the program (spec/README). lurq decomposes it. */\n document?: string;\n /** Pre-decomposed needs (e.g. the calling agent already read the doc). */\n needs?: PlanNeed[];\n /** Packages the user has already chosen. Pinned as fixed slots; lurq\n * recommends only the remaining needs and plans the stack around these. */\n using?: string[];\n /** Ranking bias. 'speed' prefers the lightest-bundle option among the top\n * candidates for a slot; 'balanced' (default) uses the normal ranking. */\n optimize?: 'speed' | 'balanced';\n}\n\nexport interface PlanSlot {\n need: string;\n category: Category | null;\n layer: string;\n recommended: Candidate | null;\n alternatives: Candidate[];\n note?: string;\n /** Picked packages this slot's pick still conflicts with, if it couldn't be\n * auto-resolved with the available alternatives (residual conflict). */\n conflictsWith?: string[];\n /** If plan swapped this slot's pick to keep the stack compatible, the name of\n * the original (higher-ranked) pick it replaced. */\n swappedFrom?: string;\n}\n\nexport interface PlanOutput {\n dataAsOf: string;\n optimize: 'speed' | 'balanced';\n /** Where the slots came from: caller-supplied needs, lurq's LLM, or the heuristic. */\n source: 'needs' | 'llm' | 'heuristic';\n /** The framework/meta-framework that anchored the plan, if one was found. Every\n * other slot was recommended in this ecosystem's context. null = no framework\n * in the spec, so slots were recommended independently. */\n framework: string | null;\n slots: PlanSlot[];\n /** Needs for which no tracked package matched. */\n unmatched: string[];\n mermaid: string;\n note: string;\n /** Whole-stack compatibility of the picked packages (peer-deps/engines +\n * recorded sandbox conflicts). Evidence-backed, with name@version of each\n * member; null if the check couldn't run. */\n compatibility: CompatOutput | null;\n}\n\n/** Candidates to surface per slot: the pick plus a couple of alternatives. */\nconst PER_SLOT = 3;\n/** Cap on slots so a huge document can't fan out into hundreds of queries. */\nconst MAX_SLOTS = 24;\n\nexport async function handlePlan(db: Database, input: PlanInput): Promise<PlanOutput | { note: string }> {\n const optimize = input.optimize ?? 'balanced';\n\n const decomposed = input.needs?.length\n ? { needs: dedupeNeeds(input.needs), source: 'needs' as const }\n : input.document?.trim()\n ? await decompose(input.document)\n : null;\n\n const hasPins = Boolean(input.using?.length);\n if ((!decomposed || decomposed.needs.length === 0) && !hasPins) {\n return {\n note: 'Provide a `document` (a detailed description of your program), a `needs` array, or a `using` list of packages you have already chosen. lurq recommends evidence-scored packages per component — it does not invent an architecture from a bare prompt.',\n };\n }\n\n const needs = (decomposed?.needs ?? []).slice(0, MAX_SLOTS);\n const source = decomposed?.source ?? 'needs';\n\n const safeRecommend = (need: string, category: Category | undefined) =>\n recommend(db, { need, category, limit: PER_SLOT }).catch((err) => {\n logger.warn(`plan: recommend failed for \"${need}\": ${(err as Error).message}`);\n return [] as Candidate[];\n });\n // Effective category per slot — the decomposition hint, else inferred from the\n // ORIGINAL need text (before any framework context is appended, so the word we\n // inject below can never misclassify the slot).\n const effCat = (n: PlanNeed): Category | undefined => n.category ?? inferCategory(n.need) ?? undefined;\n\n // Detect the framework family from the WHOLE spec (document + need texts), so the\n // plan stays coherent even when decomposition doesn't emit a framework slot.\n // This drives the coherence re-rank below.\n const anchorFamily = familyOf(`${input.document ?? ''} ${needs.map((n) => n.need).join(' ')}`);\n\n // Phase 1: if a framework/meta-framework component exists, resolve it first to\n // name the concrete package (a meta-framework like Next wins over a bare\n // framework); otherwise the detected family is the context word.\n const metaIdx = needs.findIndex((n) => effCat(n) === 'meta-framework');\n const anchorIdx = metaIdx >= 0 ? metaIdx : needs.findIndex((n) => effCat(n) === 'framework');\n\n const recs: Candidate[][] = new Array(needs.length);\n let framework: string | null = anchorFamily;\n if (anchorIdx >= 0) {\n recs[anchorIdx] = await safeRecommend(needs[anchorIdx]!.need, effCat(needs[anchorIdx]!));\n framework = recs[anchorIdx]![0]?.name ?? anchorFamily;\n }\n\n // Phase 2: recommend the remaining slots concurrently, weaving the chosen\n // framework into each query so sibling libraries stay in-ecosystem. The slot's\n // category is passed explicitly, so the injected framework word only sways\n // relevance — never the category filter. Framework-agnostic slots (e.g.\n // date/time) are unaffected since their candidates don't mention the framework.\n const [, dataAsOf] = await Promise.all([\n Promise.all(\n needs.map(async (n, i) => {\n if (i === anchorIdx) return;\n const need = framework ? `${n.need} (for a ${framework} app)` : n.need;\n recs[i] = await safeRecommend(need, effCat(n));\n }),\n ),\n latestDataAsOf(db),\n ]);\n\n // Re-rank each slot's candidates: keep the architecture coherent (cross-\n // framework bindings last), then — for 'speed' — prefer the lightest bundle,\n // otherwise preserve recommend's relevance order. One batched lookup keeps\n // `recommend` itself untouched.\n const bundleByName = optimize === 'speed' ? await bundleSizes(db, recs.flat()) : new Map<string, number>();\n\n const recSlots: PlanSlot[] = needs.map((n, i) => {\n const candidates = orderCandidates(recs[i]!, anchorFamily, optimize, bundleByName);\n const recommended = candidates[0] ?? null;\n const category = n.category ?? recommended?.category ?? inferCategory(n.need);\n return {\n need: n.need,\n category,\n layer: layerFor({ label: recommended?.name ?? n.need, category }),\n recommended,\n alternatives: candidates.slice(1),\n note: recommended ? undefined : 'no tracked package matched this need yet',\n };\n });\n\n // Pin the user's chosen packages as fixed slots, then plan the rest around\n // them. Pins lead so they anchor the stack; the optimizer can only move the\n // recommended slots, so it routes them to stay compatible with the pins.\n const recommendedNames = new Set(\n recSlots.map((s) => s.recommended?.name).filter((n): n is string => Boolean(n)),\n );\n const { slots: pinnedSlots, unresolved: unresolvedPins } = await resolvePins(\n db,\n input.using,\n recommendedNames,\n );\n const slots = [...pinnedSlots, ...recSlots];\n\n // Auto-resolve compatibility: actually make the picked stack coherent by\n // swapping a conflicting slot's pick for an alternative that resolves it.\n // Runs before the diagram/output so everything below reflects the final stack.\n const compatibility = await resolveCompat(db, slots);\n\n const unmatched = [\n ...slots.filter((s) => !s.recommended).map((s) => s.need),\n ...unresolvedPins.map((n) => `${n} (pinned, but not found on npm)`),\n ];\n const mermaid = buildMermaid(\n slots\n .filter((s) => s.recommended)\n .map((s) => ({ label: s.recommended!.name, category: s.category })),\n );\n\n return {\n dataAsOf,\n optimize,\n source,\n framework,\n slots,\n unmatched,\n mermaid,\n note: planNote(source, unmatched.length, optimize, framework),\n compatibility,\n };\n}\n\n/** Map each slot (by need) to the other picked packages its pick conflicts with. */\nexport function flagSlotConflicts(\n picks: { need: string; name: string | null }[],\n conflicts: CompatConflict[],\n): Map<string, string[]> {\n const out = new Map<string, string[]>();\n for (const c of conflicts) {\n for (const p of picks) {\n if (p.name && c.packages.includes(p.name)) {\n const others = c.packages.filter((n) => n !== p.name);\n out.set(p.need, [...new Set([...(out.get(p.need) ?? []), ...others])]);\n }\n }\n }\n return out;\n}\n\nconst NO_META = (c: Candidate): CompatMember => ({\n name: c.name,\n version: c.latestVersion,\n peerDependencies: null,\n peerDependenciesMeta: null,\n engines: null,\n});\n\n/**\n * Make the picked stack compatible by *globally optimising* the slot choices:\n * pre-load every candidate's metadata + cached sandbox edges once, then run a\n * branch-and-bound that picks the highest-quality (lowest rank-regret) compatible\n * combination. The chosen alternative is promoted to `recommended` (original\n * demoted, recorded via `swappedFrom`); residual conflicts are flagged per slot.\n * The search is pure/in-memory; only the final report re-reads the DB.\n * Best-effort — never throws.\n */\nasync function resolveCompat(db: Database, slots: PlanSlot[]): Promise<CompatOutput | null> {\n const eligible = slots.filter((s) => s.recommended);\n if (eligible.length < 2) return null;\n\n try {\n // One pass: metadata for every candidate across all slots → pure search.\n const allNames = [\n ...new Set(eligible.flatMap((s) => [s.recommended!, ...s.alternatives].map((c) => c.name))),\n ];\n const [{ members }, edges] = await Promise.all([\n assembleMembers(db, allNames),\n getCompatEdges(db, allNames),\n ]);\n const metaByName = new Map(members.map((m) => [m.name, m]));\n const sandboxConflicts = new Set(\n edges.filter((e) => e.status === 'conflict').map((e) => `${e.packageA}|${e.packageB}`),\n );\n const slotCandidates = eligible.map((s) =>\n [s.recommended!, ...s.alternatives].map((c) => metaByName.get(c.name) ?? NO_META(c)),\n );\n\n const { selection } = optimizeStack(slotCandidates, sandboxConflicts);\n\n // Apply the optimal selection: promote the chosen candidate per slot.\n eligible.forEach((s, i) => {\n const idx = selection[i] ?? 0;\n if (idx <= 0) return;\n const all = [s.recommended!, ...s.alternatives];\n const chosen = all[idx];\n if (!chosen) return;\n s.recommended = chosen;\n s.alternatives = all.filter((c) => c.name !== chosen.name);\n s.swappedFrom = all[0]!.name;\n });\n } catch (err) {\n logger.warn(`plan: compat optimization failed: ${String(err)}`);\n }\n\n // Authoritative report on the final picks, and flag any residual conflicts.\n const compat = await checkCompat(\n db,\n eligible.map((s) => s.recommended!.name),\n ).catch(() => null);\n if (compat) {\n const flags = flagSlotConflicts(\n slots.map((s) => ({ need: s.need, name: s.recommended?.name ?? null })),\n compat.conflicts,\n );\n for (const s of slots) {\n const cw = flags.get(s.need);\n s.conflictsWith = cw?.length ? cw : undefined;\n }\n }\n return compat;\n}\n\nfunction planNote(\n source: PlanOutput['source'],\n unmatched: number,\n optimize: string,\n framework: string | null,\n): string {\n const base =\n source === 'heuristic'\n ? 'Components were extracted from your document with a keyword heuristic (no summary LLM configured) — coarse; pass a `needs` array or set SUMMARY_API_KEY for sharper decomposition.'\n : source === 'llm'\n ? 'Components were extracted from your document by the summary model.'\n : 'Components taken from the supplied needs.';\n const grounding =\n ' Each package is recommended from lurq’s scored index — a labeled, evidence-backed starting point, not a validated architecture.';\n const ctx = framework\n ? ` Anchored to the ${framework} ecosystem so sibling libraries stay coherent across the stack.`\n : '';\n const tail = unmatched ? ` ${unmatched} need(s) had no tracked match (listed in \\`unmatched\\`).` : '';\n const opt = optimize === 'speed' ? ' Ranking favored the lightest-bundle option per slot.' : '';\n return base + grounding + ctx + opt + tail;\n}\n\n/** Merge duplicate needs (same text), keeping the first category hint seen. */\nfunction dedupeNeeds(needs: PlanNeed[]): PlanNeed[] {\n const seen = new Map<string, PlanNeed>();\n for (const n of needs) {\n const key = n.need.trim().toLowerCase();\n if (!key) continue;\n if (!seen.has(key)) seen.set(key, { need: n.need.trim(), category: n.category });\n }\n return [...seen.values()];\n}\n\n/** The framework \"family\" a package name belongs to (by naming convention), or\n * null if framework-agnostic. Lets the plan stay in one ecosystem — never\n * surface a different framework's binding (e.g. vue-router in a React app). */\nconst FAMILY_TOKENS: { family: string; re: RegExp }[] = [\n { family: 'react', re: /\\breact\\b|preact/ },\n { family: 'vue', re: /\\bvue\\b|nuxt/ },\n { family: 'angular', re: /angular/ },\n { family: 'svelte', re: /svelte/ },\n { family: 'solid', re: /\\bsolid(-?js)?\\b/ },\n];\n\nexport function familyOf(name: string): string | null {\n const n = name.toLowerCase();\n for (const f of FAMILY_TOKENS) if (f.re.test(n)) return f.family;\n return null;\n}\n\n/**\n * Order a slot's candidates: in-ecosystem first and cross-framework bindings\n * last (when an anchor framework was found), then — for 'speed' — lightest\n * bundle, otherwise preserving recommend's relevance ranking (V8's sort is\n * stable, so equal-key candidates keep their incoming order).\n */\nexport function orderCandidates(\n cands: Candidate[],\n anchorFamily: string | null,\n optimize: 'speed' | 'balanced',\n bundleByName: Map<string, number>,\n): Candidate[] {\n // +1 same ecosystem, −1 a competing framework, 0 framework-agnostic.\n const coherence = (c: Candidate): number => {\n const fam = familyOf(c.name);\n if (!fam) return 0;\n return fam === anchorFamily ? 1 : -1;\n };\n return [...cands].sort((a, b) => {\n if (anchorFamily) {\n const d = coherence(b) - coherence(a);\n if (d) return d;\n }\n if (optimize === 'speed') {\n return (bundleByName.get(a.name) ?? Infinity) - (bundleByName.get(b.name) ?? Infinity);\n }\n return 0;\n });\n}\n\n/** Batched bundle-size lookup for the 'speed' re-rank. */\nasync function bundleSizes(db: Database, candidates: Candidate[]): Promise<Map<string, number>> {\n const names = [...new Set(candidates.map((c) => c.name))];\n if (names.length === 0) return new Map();\n const rows = await db\n .select({ name: packages.name, bundle: packages.bundleMinGzipKb })\n .from(packages)\n .where(inArray(packages.name, names));\n return new Map(rows.filter((r) => r.bundle != null).map((r) => [r.name, r.bundle as number]));\n}\n\n// ── Decomposition (document → needs) ─────────────────────────────────────────\n\nasync function decompose(document: string): Promise<{ needs: PlanNeed[]; source: 'llm' | 'heuristic' }> {\n const config = getConfig();\n if (config.SUMMARY_PROVIDER === 'openai' && config.SUMMARY_API_KEY) {\n const llm = await decomposeWithLlm(\n document,\n config.SUMMARY_API_KEY,\n config.SUMMARY_MODEL,\n config.SUMMARY_BASE_URL,\n ).catch((err) => {\n logger.warn(`plan: LLM decomposition failed, using heuristic: ${(err as Error).message}`);\n return null;\n });\n if (llm?.length) return { needs: dedupeNeeds(llm), source: 'llm' };\n }\n return { needs: decomposeHeuristic(document), source: 'heuristic' };\n}\n\nconst DECOMPOSE_SYSTEM =\n 'You break a software project description into the distinct technical components that each need a library. ' +\n 'Return ONLY components the project actually requires, grounded in the description. Respond with a JSON object.';\n\nasync function decomposeWithLlm(\n document: string,\n apiKey: string,\n model: string,\n baseUrl: string,\n): Promise<PlanNeed[]> {\n const prompt = [\n 'Project description:',\n document.slice(0, 8000),\n '',\n 'Return JSON: { \"needs\": [ { \"need\": \"<one phrase describing a component that needs a library>\", \"category\": \"<optional taxonomy hint or empty>\" } ] }.',\n 'One entry per distinct component (e.g. routing, validation, ORM, HTTP client). Omit anything not implied by the description.',\n ].join('\\n');\n const { data } = await httpRequest<any>(`${baseUrl.replace(/\\/$/, '')}/chat/completions`, {\n host: new URL(baseUrl).host,\n method: 'POST',\n ttlMs: 24 * 60 * 60 * 1000,\n // Hash the FULL document — length + a 64-char prefix collide for same-length\n // edits or shared templated headers, which would serve a stale decomposition.\n cacheKey: `openai-plan ${model} ${createHash('sha1').update(document).digest('hex')}`,\n headers: { Authorization: `Bearer ${apiKey}`, 'Content-Type': 'application/json' },\n body: JSON.stringify({\n model,\n messages: [\n { role: 'system', content: DECOMPOSE_SYSTEM },\n { role: 'user', content: prompt },\n ],\n response_format: { type: 'json_object' },\n temperature: 0.2,\n }),\n });\n const content = data?.choices?.[0]?.message?.content;\n const parsed = content ? JSON.parse(content) : {};\n const raw = Array.isArray(parsed?.needs) ? parsed.needs : [];\n return raw\n .map((n: any): PlanNeed | null => {\n const need = typeof n?.need === 'string' ? n.need.trim() : '';\n if (!need) return null;\n const cat = typeof n?.category === 'string' && isCategory(n.category) ? n.category : undefined;\n return { need, category: cat };\n })\n .filter(Boolean) as PlanNeed[];\n}\n\n/**\n * Heuristic fallback: scan the document line-by-line, infer a category per line,\n * and emit one need per distinct category (first matching line as the phrase).\n * Coarse by design — it only surfaces components whose category lurq can name.\n */\nexport function decomposeHeuristic(document: string): PlanNeed[] {\n const byCategory = new Map<Category, string>();\n for (const rawLine of document.split('\\n')) {\n // Strip markdown headings/blockquotes/bullets, then an ordered-list \"12. \"\n // marker — but NOT bare leading digits, so \"2FA auth\" stays intact.\n const line = rawLine.replace(/^[#>*\\-\\s]+/, '').replace(/^\\d+\\.\\s+/, '').trim();\n if (line.length < 3) continue;\n const category = inferCategory(line);\n if (category && !byCategory.has(category)) {\n byCategory.set(category, line.slice(0, 120));\n }\n }\n return [...byCategory.entries()].map(([category, need]) => ({ need, category }));\n}\n","/**\n * Minimal per-tool metrics for the hosted MCP path — Prometheus text format, no\n * dependency. Counts calls, errors, and cumulative latency per tool so an\n * operator can see usage and error rates without wiring up an APM. Process-local\n * (a module singleton): each server instance exposes its own counters at\n * `/metrics`, which is exactly what a Prometheus scrape expects.\n */\ninterface Stat {\n calls: number;\n errors: number;\n totalMs: number;\n}\n\nconst stats = new Map<string, Stat>();\n\n/** Record one tool invocation. `ok=false` marks a handler that threw. */\nexport function recordToolCall(tool: string, ok: boolean, ms: number): void {\n const s = stats.get(tool) ?? { calls: 0, errors: 0, totalMs: 0 };\n s.calls += 1;\n if (!ok) s.errors += 1;\n s.totalMs += ms;\n stats.set(tool, s);\n}\n\n/** Time a tool handler and record the outcome, re-throwing any error unchanged. */\nexport async function timed<T>(tool: string, fn: () => Promise<T>): Promise<T> {\n const start = Date.now();\n let ok = false;\n try {\n const result = await fn();\n ok = true;\n return result;\n } finally {\n recordToolCall(tool, ok, Date.now() - start);\n }\n}\n\n/** Render current counters in Prometheus exposition format. */\nexport function renderPrometheus(): string {\n const lines = [\n '# HELP lurq_tool_calls_total Total MCP tool invocations.',\n '# TYPE lurq_tool_calls_total counter',\n '# HELP lurq_tool_errors_total MCP tool invocations that threw.',\n '# TYPE lurq_tool_errors_total counter',\n '# HELP lurq_tool_duration_ms_total Cumulative tool handler time in ms.',\n '# TYPE lurq_tool_duration_ms_total counter',\n ];\n for (const [tool, s] of stats) {\n const label = `{tool=\"${tool}\"}`;\n lines.push(`lurq_tool_calls_total${label} ${s.calls}`);\n lines.push(`lurq_tool_errors_total${label} ${s.errors}`);\n lines.push(`lurq_tool_duration_ms_total${label} ${s.totalMs}`);\n }\n return lines.join('\\n') + '\\n';\n}\n\n/** Test-only: clear all counters. */\nexport function resetMetrics(): void {\n stats.clear();\n}\n","/**\n * Compact MCP responses (§12.4). Every tool response is JSON injected straight\n * into the calling agent's context window, so each `\"field\":null` or empty\n * container is tokens the user pays for on every call — and noise that dilutes\n * the agent's attention. `compact()` recursively drops null/undefined values,\n * empty arrays, and objects that become empty, keeping only signal.\n *\n * Deliberately KEEPS `false` and `0`: `deprecated:false` and `weeklyDownloads:0`\n * carry meaning an agent shouldn't have to infer from a field's absence. Only\n * genuinely-absent data (null/undefined/empty) is stripped.\n */\nfunction isEmptyObject(value: unknown): boolean {\n return (\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(value) &&\n Object.keys(value).length === 0\n );\n}\n\nexport function compact<T>(value: T): T {\n if (Array.isArray(value)) {\n return value\n .map((v) => compact(v))\n .filter((v) => v !== null && v !== undefined) as unknown as T;\n }\n if (value !== null && typeof value === 'object') {\n const out: Record<string, unknown> = {};\n for (const [key, raw] of Object.entries(value as Record<string, unknown>)) {\n if (raw === null || raw === undefined) continue;\n const cleaned = compact(raw);\n if (cleaned === null || cleaned === undefined) continue;\n if (Array.isArray(cleaned) && cleaned.length === 0) continue;\n if (isEmptyObject(cleaned)) continue;\n out[key] = cleaned;\n }\n return out as T;\n }\n return value;\n}\n","/**\n * MCP server (§12). Exposes recommend / evaluate / compare / verify over stdio.\n * Inputs are validated with zod; outputs are compact JSON text (§12.4).\n */\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { z } from 'zod';\nimport { SERVER_NAME, VERSION } from '../core/constants';\nimport { CATEGORIES, type Category } from '../core/types';\nimport { createDb } from '../db/client';\nimport { logger } from '../core/logger';\nimport {\n handleCompare,\n handleCompat,\n handleEvaluate,\n handleRecommend,\n handleReportOutcome,\n handleVerify,\n} from './handlers';\nimport { handleDiagram } from './diagram';\nimport { handlePlan } from './plan';\nimport { timed } from './metrics';\nimport { compact } from './compact';\n\nconst categoryEnum = z.enum(CATEGORIES as unknown as [Category, ...Category[]]);\nconst confidenceEnum = z.enum(['proven', 'emerging', 'promising', 'unproven']);\n\n// Validate package names at the trust boundary. A name flows straight into a\n// registry URL (`registry.npmjs.org/${name}`) and the response cache key, so\n// reject anything that isn't a legal npm name: this blocks path/query\n// injection (`/`, `?`, `#`, `%`), whitespace, and control characters. Case is\n// permitted for legacy packages; the char class is what closes the hole.\nexport const npmName = z\n .string()\n .trim()\n .min(1)\n .max(214)\n .regex(/^(?:@[a-z0-9-][a-z0-9-._]*\\/)?[a-z0-9-][a-z0-9-._]*$/i, 'Invalid npm package name');\n\nconst constraintsSchema = z\n .object({\n runtime: z.enum(['browser', 'node', 'both']).optional(),\n license: z.string().optional(),\n maxBundleKb: z.number().positive().optional(),\n minConfidence: confidenceEnum.optional(),\n })\n .optional();\n\n/** Wrap any result object as a compact MCP text response. `compact` strips\n * null/empty fields so the agent's context only carries signal (§12.4). */\nfunction json(obj: unknown) {\n return { content: [{ type: 'text' as const, text: JSON.stringify(compact(obj)) }] };\n}\n\n/**\n * Per-connection identity, resolved from the authenticated API key at the HTTP\n * boundary and threaded into the tools. This is the channel that lets lurq know\n * *who* is calling — stamped onto the data it collects (§3.1 flywheel) so it\n * accrues to an org instead of an anonymous pool. `ownerId` is null on the stdio\n * / local path and for operator-issued keys with no org.\n */\nexport interface ServerContext {\n ownerId?: string | null;\n}\n\nexport function buildMcpServer(\n db: ReturnType<typeof createDb>['db'],\n ctx: ServerContext = {},\n): McpServer {\n const server = new McpServer({ name: SERVER_NAME, version: VERSION });\n\n server.registerTool(\n 'recommend',\n {\n title: 'Recommend packages',\n description:\n 'Recommend the best current npm packages for a described need — fresh, objectively scored, with confidence labels. Call before choosing or hand-rolling a dependency.',\n inputSchema: {\n need: z.string().min(1).describe('Natural-language description of what you need'),\n category: categoryEnum.optional().describe('Optional taxonomy category to restrict to'),\n constraints: constraintsSchema,\n },\n },\n async (args) => json(await timed('recommend', () => handleRecommend(db, args))),\n );\n\n server.registerTool(\n 'evaluate',\n {\n title: 'Evaluate a package',\n description:\n 'Full evidence read for one npm package: scores, signals, advisories, summary, and a usage guide. Fetches & scores on demand if not yet tracked.',\n inputSchema: {\n package: npmName.describe('npm package name'),\n },\n },\n async (args) => json(await timed('evaluate', () => handleEvaluate(db, args))),\n );\n\n server.registerTool(\n 'compare',\n {\n title: 'Compare packages',\n description: 'Side-by-side comparison of 2–5 npm packages, ranked by health score.',\n inputSchema: {\n packages: z.array(npmName).min(2).max(5).describe('2–5 npm package names'),\n },\n },\n async (args) => json(await timed('compare', () => handleCompare(db, args))),\n );\n\n server.registerTool(\n 'compat',\n {\n title: 'Check package compatibility',\n description:\n 'Check whether a set of packages forms a coherent stack: peer-dependency and engine-range compatibility across the whole set (instant, from declared metadata), plus any recorded sandbox-verified conflicts. Returns the exact clashing constraints. Read-only — does not run installs. Call before committing to a multi-package stack.',\n inputSchema: {\n packages: z\n .array(npmName)\n .min(2)\n .max(8)\n .describe('2–8 npm package names to check together'),\n },\n },\n async (args) => json(await timed('compat', () => handleCompat(db, args))),\n );\n\n server.registerTool(\n 'verify',\n {\n title: 'Verify a package',\n description:\n 'Confirm an npm package is real, healthy, and not risky before installing — guards against hallucinated or typosquatted dependency names. Checks the live registry.',\n inputSchema: {\n package: npmName.describe('npm package name to verify'),\n },\n },\n async (args) => json(await timed('verify', () => handleVerify(db, args))),\n );\n\n server.registerTool(\n 'diagram',\n {\n title: 'Reference architecture diagram',\n description:\n 'Emit a reference-architecture Mermaid diagram for a stack you have already chosen (package names). A labeled starting point keyed by layer — not a validated architecture, and not an architecture designer.',\n inputSchema: {\n stack: z\n .array(npmName)\n .optional()\n .describe('Package names that make up the stack; omit or empty to get usage guidance'),\n },\n },\n async (args) => json(await timed('diagram', () => handleDiagram(db, args))),\n );\n\n server.registerTool(\n 'plan',\n {\n title: 'Plan a stack from a program description',\n description:\n 'Turn a detailed program description (spec/README) or a list of component needs into an evidence-scored build plan: a real, lurq-scored package recommended per component, plus a Mermaid roadmap other agents can parse. Recommends building blocks slot-by-slot from the index — it does not invent an architecture from a bare prompt.',\n inputSchema: {\n document: z\n .string()\n .optional()\n .describe('Detailed description of the program (spec/README); lurq decomposes it into components'),\n needs: z\n .array(\n z.object({\n need: z.string().min(1).describe('A component that needs a library'),\n category: categoryEnum.optional(),\n }),\n )\n .optional()\n .describe('Pre-decomposed components (skip if you pass a document)'),\n using: z\n .array(npmName)\n .max(12)\n .optional()\n .describe(\n 'Packages you have already decided on. lurq pins these as fixed slots, recommends only the remaining needs, and checks/optimizes the whole stack around your picks.',\n ),\n optimize: z\n .enum(['speed', 'balanced'])\n .optional()\n .describe(\"'speed' prefers the lightest-bundle option per slot; default 'balanced'\"),\n },\n },\n async (args) => json(await timed('plan', () => handlePlan(db, args))),\n );\n\n server.registerTool(\n 'report_outcome',\n {\n title: 'Report a recommendation outcome',\n description:\n 'Opt-in feedback after acting on a lurq recommendation: report whether you went with the package and whether it built. No source code — only the coarse decision + a build signal. Helps lurq learn which packages agents actually succeed with; safe to skip.',\n inputSchema: {\n package: npmName.describe('The package that was recommended'),\n accepted: z.boolean().describe('Did you go with this package?'),\n buildSignal: z\n .enum(['installed', 'compiled', 'tests_passed', 'failed'])\n .optional()\n .describe('Coarse post-install result, if known'),\n need: z\n .string()\n .max(500)\n .optional()\n .describe('The original need this was recommended for (no source code)'),\n },\n },\n // ownerId comes from the authenticated key (ctx), NOT the tool arguments —\n // a caller must never be able to attribute an outcome to another org.\n async (args) =>\n json(await timed('report_outcome', () => handleReportOutcome(db, args, ctx.ownerId ?? null))),\n );\n\n return server;\n}\n\nexport async function startMcpServer(): Promise<void> {\n const { db, close } = createDb();\n const server = buildMcpServer(db);\n\n const shutdown = async () => {\n try {\n await close();\n } finally {\n process.exit(0);\n }\n };\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n logger.info(`${SERVER_NAME} MCP server v${VERSION} running on stdio.`);\n}\n","/**\n * API-key generation, hashing, and lifecycle for the hosted HTTP service\n * (docs/lurq-hosted-deployment.md §5). Keys are high-entropy random strings; only\n * their sha256 hash is persisted, so a DB leak never exposes a usable key. The\n * plaintext is returned exactly once (at creation) and never stored or logged.\n */\nimport { createHash, randomBytes } from 'node:crypto';\nimport { and, desc, eq, isNull } from 'drizzle-orm';\nimport { API_KEY_PREFIX } from '../core/constants';\nimport type { Database } from '../db/client';\nimport { apiKeys, type ApiKeyRow } from '../db/schema';\nimport { logger } from '../core/logger';\n\n/** Chars of the random body kept in the display prefix (`lurq_live_<6>`). */\nconst DISPLAY_BODY = 6;\n\n/** sha256 hex of a key — the only form ever persisted or compared. */\nexport function hashKey(key: string): string {\n return createHash('sha256').update(key).digest('hex');\n}\n\nexport interface GeneratedKey {\n /** The full plaintext key — show once, never store. */\n key: string;\n /** sha256 hash to persist. */\n hash: string;\n /** Identifiable, safe-to-display prefix. */\n prefix: string;\n}\n\nexport function generateApiKey(): GeneratedKey {\n // 24 random bytes → 32-char base64url body: unbiased, URL/header-safe.\n const body = randomBytes(24).toString('base64url');\n const key = API_KEY_PREFIX + body;\n return { key, hash: hashKey(key), prefix: API_KEY_PREFIX + body.slice(0, DISPLAY_BODY) };\n}\n\nexport interface CreateKeyInput {\n label?: string;\n tier?: string;\n ownerId?: string;\n}\n\n/** Create and persist a key. Returns the plaintext ONCE plus the stored row. */\nexport async function createKey(\n db: Database,\n input: CreateKeyInput = {},\n): Promise<{ key: string; row: ApiKeyRow }> {\n const { key, hash, prefix } = generateApiKey();\n const [row] = await db\n .insert(apiKeys)\n .values({\n keyHash: hash,\n prefix,\n label: input.label,\n tier: input.tier ?? 'free',\n ownerId: input.ownerId,\n })\n .returning();\n return { key, row: row! };\n}\n\n/**\n * Short-TTL cache of resolved keys. Auth runs on every hosted request, so an\n * uncached lookup means a SELECT (plus a lastUsedAt UPDATE) per call — pure load\n * on the DB, which is the scaling bottleneck. We cache only *valid* keys (the\n * hot path); unknown tokens always hit the DB so a flood of garbage tokens can't\n * bloat the map, and the per-IP limiter blunts that anyway. Trade-off: a revoked\n * key keeps working for up to AUTH_TTL_MS. Process-local; each instance caches\n * independently, which is fine for a bearer check.\n */\ninterface AuthEntry {\n row: ApiKeyRow;\n cachedAt: number;\n lastStampAt: number;\n}\nconst authCache = new Map<string, AuthEntry>();\nconst AUTH_TTL_MS = 60_000;\n/** lastUsedAt is analytics, not correctness — stamp at most this often per key. */\nconst STAMP_INTERVAL_MS = 60_000;\n\n/** Test-only: clear the auth cache so a fresh lookup re-reads the DB. */\nexport function resetAuthCache(): void {\n authCache.clear();\n}\n\n/** Fire-and-forget usage stamp, throttled per key. Never blocks the request. */\nfunction stampLastUsed(db: Database, entry: AuthEntry, now: number): void {\n if (now - entry.lastStampAt < STAMP_INTERVAL_MS) return;\n entry.lastStampAt = now;\n db.update(apiKeys)\n .set({ lastUsedAt: new Date(now) })\n .where(eq(apiKeys.id, entry.row.id))\n .then(undefined, (err) => logger.debug(`lastUsedAt stamp failed: ${String(err)}`));\n}\n\n/**\n * Look up an active (non-revoked) key by its plaintext form. Returns null if the\n * key is unknown or revoked. Cached for AUTH_TTL_MS; stamps `lastUsedAt`\n * best-effort (throttled) without blocking.\n */\nexport async function lookupActiveKey(db: Database, key: string): Promise<ApiKeyRow | null> {\n const hash = hashKey(key);\n const now = Date.now();\n\n const cached = authCache.get(hash);\n if (cached && now - cached.cachedAt < AUTH_TTL_MS) {\n stampLastUsed(db, cached, now);\n return cached.row;\n }\n\n const [row] = await db\n .select()\n .from(apiKeys)\n .where(and(eq(apiKeys.keyHash, hash), isNull(apiKeys.revokedAt)))\n .limit(1);\n if (!row) {\n authCache.delete(hash); // e.g. a key revoked since it was last cached\n return null;\n }\n const entry: AuthEntry = { row, cachedAt: now, lastStampAt: 0 };\n authCache.set(hash, entry);\n stampLastUsed(db, entry, now);\n return row;\n}\n\nexport async function listKeys(db: Database): Promise<ApiKeyRow[]> {\n return db.select().from(apiKeys).orderBy(desc(apiKeys.createdAt));\n}\n\n/** Resolve a \"prefix or numeric id\" argument to a Drizzle equality filter. */\nfunction matchByPrefixOrId(prefixOrId: string) {\n const asId = Number(prefixOrId);\n return Number.isInteger(asId) && String(asId) === prefixOrId.trim()\n ? eq(apiKeys.id, asId)\n : eq(apiKeys.prefix, prefixOrId);\n}\n\n/**\n * Revoke a key by display prefix or numeric id. Returns how many active keys were\n * revoked (0 if none matched or it was already revoked).\n */\nexport async function revokeKey(db: Database, prefixOrId: string): Promise<number> {\n const rows = await db\n .update(apiKeys)\n .set({ revokedAt: new Date() })\n .where(and(matchByPrefixOrId(prefixOrId), isNull(apiKeys.revokedAt)))\n .returning({ id: apiKeys.id });\n return rows.length;\n}\n\n/**\n * Rotate (\"swap\") a key: issue a replacement carrying the old key's label, tier,\n * and owner, then revoke the original. Returns the new plaintext (once), the new\n * row, and the revoked row — or null if no active key matched.\n *\n * The new key is created BEFORE the old one is revoked, so a failure mid-rotation\n * leaves the caller with a working key (at worst two active keys, never zero).\n */\nexport async function rotateKey(\n db: Database,\n prefixOrId: string,\n): Promise<{ key: string; row: ApiKeyRow; previous: ApiKeyRow } | null> {\n const [previous] = await db\n .select()\n .from(apiKeys)\n .where(and(matchByPrefixOrId(prefixOrId), isNull(apiKeys.revokedAt)))\n .limit(1);\n if (!previous) return null;\n\n const { key, row } = await createKey(db, {\n label: previous.label ?? undefined,\n tier: previous.tier,\n ownerId: previous.ownerId ?? undefined,\n });\n await db.update(apiKeys).set({ revokedAt: new Date() }).where(eq(apiKeys.id, previous.id));\n return { key, row, previous };\n}\n","/**\n * Hosted HTTP transport for the MCP server (docs/lurq-hosted-deployment.md §4–5).\n *\n * Stateless Streamable HTTP: one shared DB pool created at startup, a fresh MCP\n * server+transport per request, fronted by helmet + rate limiting + API-key auth.\n * The DB credentials stay server-side; users connect with only a URL + Bearer key.\n * `buildMcpServer` is reused verbatim from the stdio path — the tools are\n * transport-agnostic.\n *\n * express/helmet/express-rate-limit are imported dynamically so the CLI and the\n * install wizard never pull server-only deps into their startup path.\n */\nimport { createHash, timingSafeEqual } from 'node:crypto';\nimport type { NextFunction, Request, Response } from 'express';\nimport type { Store } from 'express-rate-limit';\nimport { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';\nimport { getConfig } from '../core/config';\nimport { logger } from '../core/logger';\nimport { createKey, lookupActiveKey } from '../auth/apiKeys';\nimport { createDb } from '../db/client';\nimport type { ApiKeyRow } from '../db/schema';\nimport { buildMcpServer } from './server';\nimport { renderPrometheus } from './metrics';\n\ninterface AuthedRequest extends Request {\n lurqKey?: ApiKeyRow;\n}\n\n/** JSON-RPC-shaped error envelope for HTTP-level rejections. */\nfunction rpcError(code: number, message: string) {\n return { jsonrpc: '2.0' as const, error: { code, message }, id: null };\n}\n\n/** Constant-time secret comparison (hash to a fixed length first, so length\n * never leaks and mismatched lengths don't throw). */\nexport function secretEquals(a: string, b: string): boolean {\n return timingSafeEqual(\n createHash('sha256').update(a).digest(),\n createHash('sha256').update(b).digest(),\n );\n}\n\nexport async function startHttpServer(opts: { port?: number } = {}): Promise<void> {\n const config = getConfig();\n const port = opts.port ?? config.PORT;\n\n const [{ default: express }, { default: helmet }, { rateLimit, ipKeyGenerator }] =\n await Promise.all([import('express'), import('helmet'), import('express-rate-limit')]);\n\n // The DB pool is the expensive resource — created once, shared by all requests.\n const { db } = createDb({ max: 20 });\n\n // Without Redis the response cache is a pass-through, so every recommend/\n // evaluate/compare recomputes its search on the DB — fine for one box, but the\n // first thing that buckles under real traffic. Warn loudly on the hosted path.\n if (!process.env.REDIS_URL) {\n logger.warn(\n 'REDIS_URL not set — response caching is OFF; every request recomputes on the ' +\n 'database. Set REDIS_URL before serving real traffic (and it also backs the ' +\n 'rate limiter across instances).',\n );\n }\n\n // Rate-limit store: Redis-backed when REDIS_URL is set, so limits are shared\n // and correct across horizontally-scaled instances. Without it the default\n // in-memory store is per-process — fine for one box, but N instances would\n // each enforce the full quota (N× the real limit). Each limiter gets its own\n // prefix so their counters don't collide in one Redis keyspace.\n let makeStore: ((prefix: string) => Store) | null = null;\n if (process.env.REDIS_URL) {\n const [{ default: Redis }, { default: RedisStore }] = await Promise.all([\n import('ioredis'),\n import('rate-limit-redis'),\n ]);\n const rlRedis = new Redis(process.env.REDIS_URL, { maxRetriesPerRequest: 1, family: 0 });\n rlRedis.on('error', (err: Error) => logger.warn(`rate-limit redis: ${err.message}`));\n makeStore = (prefix: string) =>\n new RedisStore({\n prefix,\n sendCommand: (...args: string[]) => rlRedis.call(args[0]!, ...args.slice(1)) as Promise<never>,\n });\n }\n\n const app = express();\n app.set('trust proxy', 1); // Railway terminates TLS at the edge.\n app.use(helmet());\n app.use(express.json({ limit: '1mb' }));\n\n // Unauthenticated, no DB hit — for Railway's healthcheck. Intentionally not\n // rate-limited: it's a static response with no backend cost, and limiting it\n // risks 429'ing Railway's own frequent healthcheck poll into a restart loop.\n app.get('/healthz', (_req: Request, res: Response) => {\n res.status(200).json({ status: 'ok' });\n });\n\n // Prometheus scrape of per-tool call/error/latency counters. Disabled (404)\n // unless LURQ_METRICS_TOKEN is set; when set, require it as a Bearer token so\n // the endpoint doesn't leak usage on a public host.\n app.get('/metrics', (req: Request, res: Response) => {\n const token = config.LURQ_METRICS_TOKEN;\n if (!token) {\n res.status(404).end();\n return;\n }\n const header = req.headers.authorization;\n const presented = header?.startsWith('Bearer ') ? header.slice(7).trim() : '';\n if (presented !== token) {\n res.status(401).end();\n return;\n }\n res.type('text/plain').send(renderPrometheus());\n });\n\n // Coarse per-IP limiter to blunt unauthenticated floods before the auth lookup.\n const ipLimiter = rateLimit({\n windowMs: config.LURQ_RATE_LIMIT_WINDOW_MS,\n limit: config.LURQ_IP_RATE_LIMIT_MAX,\n standardHeaders: 'draft-7',\n legacyHeaders: false,\n ...(makeStore ? { store: makeStore('rl:ip:') } : {}),\n message: rpcError(-32029, 'Rate limit exceeded.'),\n });\n\n // Bearer API-key auth: resolve and attach the key, or 401.\n const auth = async (req: AuthedRequest, res: Response, next: NextFunction): Promise<void> => {\n const header = req.headers.authorization;\n const token = header?.startsWith('Bearer ') ? header.slice(7).trim() : '';\n if (!token) {\n res.status(401).json(rpcError(-32001, 'Missing API key. Pass Authorization: Bearer <key>.'));\n return;\n }\n try {\n const row = await lookupActiveKey(db, token);\n if (!row) {\n res.status(401).json(rpcError(-32001, 'Invalid or revoked API key.'));\n return;\n }\n req.lurqKey = row;\n next();\n } catch (err) {\n logger.error('auth lookup failed:', err instanceof Error ? err.message : String(err));\n res.status(500).json(rpcError(-32603, 'Internal error.'));\n }\n };\n\n // Per-key limiter (runs after auth so it can key on the resolved API key).\n const keyLimiter = rateLimit({\n windowMs: config.LURQ_RATE_LIMIT_WINDOW_MS,\n limit: config.LURQ_RATE_LIMIT_MAX,\n standardHeaders: 'draft-7',\n legacyHeaders: false,\n // Key on the resolved API key's unique row id (always present — auth runs\n // first). The display `prefix` is only 6 chars of body, so distinct keys\n // can collide on it and share a quota; the id cannot. The IP fallback uses\n // express-rate-limit's ipKeyGenerator so IPv6 addresses are normalized\n // correctly (v8 throws ERR_ERL_KEY_GEN_IPV6 on a raw req.ip).\n keyGenerator: (req: Request) => {\n const id = (req as AuthedRequest).lurqKey?.id;\n return id != null ? `key:${id}` : ipKeyGenerator(req.ip ?? '0.0.0.0');\n },\n ...(makeStore ? { store: makeStore('rl:key:') } : {}),\n message: rpcError(-32029, 'Rate limit exceeded.'),\n });\n\n // Self-serve key issuance for the web dashboard (§ identity). Gated by the\n // shared LURQ_ISSUER_SECRET: the Clerk-authenticated web app presents it and\n // supplies the signed-in user's resolved `ownerId`. The backend trusts the web\n // app to have authenticated the user — it just mints the key. NOT behind the\n // per-IP limiter: all web-app calls share one egress IP, so that would throttle\n // every user together; the secret + the web app's own per-user auth are the\n // gate. Disabled (404) when the secret is unset.\n app.post('/keys', async (req: Request, res: Response) => {\n const secret = config.LURQ_ISSUER_SECRET;\n if (!secret) {\n res.status(404).end();\n return;\n }\n const header = req.headers.authorization;\n const token = header?.startsWith('Bearer ') ? header.slice(7).trim() : '';\n if (!token || !secretEquals(token, secret)) {\n res.status(401).json({ error: 'Invalid issuer secret.' });\n return;\n }\n const body = (req.body ?? {}) as { ownerId?: unknown; label?: unknown };\n const ownerId = typeof body.ownerId === 'string' ? body.ownerId.trim() : '';\n if (!ownerId) {\n res.status(400).json({ error: 'ownerId is required.' });\n return;\n }\n const label = typeof body.label === 'string' ? body.label.slice(0, 200) : undefined;\n try {\n const { key, row } = await createKey(db, { ownerId, label, tier: 'free' });\n res.status(201).json({ key, prefix: row.prefix });\n } catch (err) {\n logger.error('key issuance failed:', err instanceof Error ? err.message : String(err));\n res.status(500).json({ error: 'Could not issue key.' });\n }\n });\n\n app.post('/mcp', ipLimiter, auth, keyLimiter, async (req: Request, res: Response) => {\n // Stateless: a fresh server+transport per request, sharing the one DB pool.\n // Thread the authenticated key's org identity into the tools (§3.1).\n const server = buildMcpServer(db, { ownerId: (req as AuthedRequest).lurqKey?.ownerId ?? null });\n const transport = new StreamableHTTPServerTransport({\n sessionIdGenerator: undefined,\n enableJsonResponse: true,\n });\n res.on('close', () => {\n void transport.close();\n void server.close();\n });\n try {\n await server.connect(transport);\n await transport.handleRequest(req, res, req.body);\n } catch (err) {\n logger.error('mcp request failed:', err instanceof Error ? err.message : String(err));\n if (!res.headersSent) res.status(500).json(rpcError(-32603, 'Internal error'));\n }\n });\n\n // Stateless server: no session GET/DELETE handling.\n app.all('/mcp', (_req: Request, res: Response) => {\n res.status(405).json(rpcError(-32000, 'Method not allowed.'));\n });\n\n app.listen(port, () => {\n logger.info(`lurq HTTP MCP server listening on :${port}/mcp`);\n });\n}\n","/**\n * `lurq rescore` (§4). Re-derive health scores from each package's *cached*\n * `scoreBreakdown` using the currently-loaded weight model — no re-ingestion,\n * no network. This is the payoff of storing the breakdown per package: a weight\n * edit (`edit-weights`) applies to the whole DB in one cheap pass.\n *\n * Only health weights change a stored value (`health_score`). The composite\n * (health↔quality blend) and its λ are applied at read time in `recommend`, so\n * a λ-only edit needs no rescore — but running it is harmless and idempotent.\n */\nimport { isNotNull } from 'drizzle-orm';\nimport { invalidateCache } from '../core/cache';\nimport { logger } from '../core/logger';\nimport { createDb } from '../db/client';\nimport { packages } from '../db/schema';\nimport { computeHealthScore } from '../scoring';\nimport { loadWeights } from '../scoring/weights';\nimport { eq } from 'drizzle-orm';\n\nexport interface RescoreSummary {\n seen: number;\n updated: number;\n}\n\nexport async function runRescore(): Promise<RescoreSummary> {\n const weights = loadWeights();\n const handle = createDb({ max: 4 });\n try {\n const rows = await handle.db\n .select({ id: packages.id, breakdown: packages.scoreBreakdown, healthScore: packages.healthScore })\n .from(packages)\n .where(isNotNull(packages.scoreBreakdown));\n\n let updated = 0;\n for (const row of rows) {\n if (!row.breakdown) continue;\n const health = computeHealthScore(row.breakdown, weights.health);\n if (health !== row.healthScore) {\n await handle.db\n .update(packages)\n .set({ healthScore: health, updatedAt: new Date() })\n .where(eq(packages.id, row.id));\n updated++;\n }\n }\n\n logger.info(`Rescored ${rows.length} package(s); ${updated} health score(s) changed.`);\n if (updated > 0) await invalidateCache();\n return { seen: rows.length, updated };\n } finally {\n await handle.close();\n }\n}\n","/**\n * Read/write helpers for the `discovery_queue` table (§2B). The crawler enqueues\n * candidates here; the merit gate pre-scores and graduates them.\n */\nimport { eq } from 'drizzle-orm';\nimport type { DiscoverySource, DiscoveryStatus } from '../core/types';\nimport type { Database } from './client';\nimport { discoveryQueue, packages, type DiscoveryQueueRow } from './schema';\n\nexport interface DiscoveryCandidate {\n name: string;\n via: DiscoverySource;\n}\n\n/** Names already tracked (in `packages`) or already queued — never re-enqueue. */\nexport async function getKnownNames(db: Database): Promise<Set<string>> {\n const [tracked, queued] = await Promise.all([\n db.select({ name: packages.name }).from(packages),\n db.select({ name: discoveryQueue.name }).from(discoveryQueue),\n ]);\n return new Set([...tracked.map((r) => r.name), ...queued.map((r) => r.name)]);\n}\n\n/** Insert new candidates, ignoring any that race in concurrently. Returns count inserted. */\nexport async function enqueueCandidates(\n db: Database,\n candidates: DiscoveryCandidate[],\n): Promise<number> {\n if (candidates.length === 0) return 0;\n const rows = candidates.map((c) => ({ name: c.name, discoveredVia: c.via }));\n const inserted = await db\n .insert(discoveryQueue)\n .values(rows)\n .onConflictDoNothing({ target: discoveryQueue.name })\n .returning({ id: discoveryQueue.id });\n return inserted.length;\n}\n\nexport async function getPendingCandidates(\n db: Database,\n limit: number,\n): Promise<DiscoveryQueueRow[]> {\n return db\n .select()\n .from(discoveryQueue)\n .where(eq(discoveryQueue.status, 'pending'))\n .limit(limit);\n}\n\nexport async function setDiscoveryStatus(\n db: Database,\n name: string,\n data: { status: DiscoveryStatus; preScore?: number | null },\n): Promise<void> {\n await db\n .update(discoveryQueue)\n .set({ status: data.status, ...(data.preScore !== undefined ? { preScore: data.preScore } : {}) })\n .where(eq(discoveryQueue.name, name));\n}\n","/**\n * Proactive multi-channel discovery crawler (§2B). OPERATOR-SIDE: this is a\n * scheduled job against the central index, never triggered by a user query.\n *\n * Three channels feed one queue, then a *merit* gate decides what graduates:\n * 1. Dependency-graph adjacency (deps.dev) — surfaced wholesale, NOT ranked by\n * dependent count (that re-introduces popularity bias).\n * 2. Category-keyword + recency (npm search) — the niche workhorse; the graph\n * structurally can't find niche alternatives.\n * 3. Merit gate — pre-scores candidates on QUALITY signals only. Downloads are\n * deliberately excluded so merit, not popularity, decides what's ingested.\n *\n * Cost is bounded by a per-run cap; anything dropped is logged (no silent\n * truncation), and the tail stays queued for the next run.\n */\nimport { isNotNull } from 'drizzle-orm';\nimport { logger } from '../core/logger';\nimport { CATEGORIES } from '../core/types';\nimport { createDb, type Database } from '../db/client';\nimport {\n enqueueCandidates,\n getKnownNames,\n getPendingCandidates,\n setDiscoveryStatus,\n type DiscoveryCandidate,\n} from '../db/discovery';\nimport { packages } from '../db/schema';\nimport { fetchDependencyNames } from '../ingestion/sources/depsDev';\nimport { fetchNpmRegistry } from '../ingestion/sources/npmRegistry';\nimport { searchNpm } from '../ingestion/sources/npmSearch';\nimport type { RawPackageSignals } from '../ingestion/types';\nimport { computeQuality, toScoringInput } from '../scoring';\nimport { DISCOVERY } from '../scoring/weights';\nimport { syncOnePackage } from './single';\n\nexport interface DiscoverOptions {\n /** Max candidates to fully ingest this run (defaults to DISCOVERY.perRunCap). */\n perRunCap?: number;\n /** Discover + queue + gate, but don't ingest survivors (preview). */\n dryRun?: boolean;\n}\n\nexport interface DiscoverSummary {\n enqueued: number;\n gated: number;\n passed: number;\n ingested: number;\n droppedToNextRun: number;\n}\n\n// ── Pure helpers (unit-tested) ───────────────────────────────────────────────\n\n/** Dedupe raw candidates by name (first channel wins), dropping anything already\n * known or with an invalid name. */\nexport function selectCandidates(\n raw: DiscoveryCandidate[],\n known: Set<string>,\n): DiscoveryCandidate[] {\n const seen = new Set<string>(known);\n const out: DiscoveryCandidate[] = [];\n for (const c of raw) {\n const name = c.name?.trim();\n if (!name || seen.has(name)) continue;\n seen.add(name);\n out.push({ name, via: c.via });\n }\n return out;\n}\n\n/** The merit gate: quality-only pre-score must clear the bar (§2B). */\nexport function passesGate(preScore: number | null): boolean {\n return preScore !== null && preScore >= DISCOVERY.minPreScore;\n}\n\n/**\n * Quality-only pre-score from a single cheap registry fetch (§2B). Reuses the\n * §1 quality model but with only manifest signals — no downloads, no GitHub —\n * so the gate is adoption-independent by construction.\n */\nexport async function preScorePackage(\n name: string,\n fetchImpl?: typeof fetch,\n): Promise<number | null> {\n try {\n const registry = await fetchNpmRegistry(name, fetchImpl);\n const signals: RawPackageSignals = {\n name,\n registry,\n downloads: null,\n github: null,\n depsDev: null,\n bundle: null,\n errors: [],\n };\n return computeQuality(toScoringInput(signals, null));\n } catch {\n return null;\n }\n}\n\n// ── Channels ─────────────────────────────────────────────────────────────────\n\n/** Dependency-graph neighbors of tracked packages (adjacency, not ranking). */\nasync function graphChannel(db: Database): Promise<DiscoveryCandidate[]> {\n const tracked = await db\n .select({ name: packages.name, version: packages.latestVersion })\n .from(packages)\n .where(isNotNull(packages.latestVersion));\n\n const out: DiscoveryCandidate[] = [];\n for (const t of tracked) {\n if (!t.version) continue;\n const deps = (await fetchDependencyNames(t.name, t.version)).slice(\n 0,\n DISCOVERY.graphNeighborsPerSeed,\n );\n for (const name of deps) out.push({ name, via: 'dependency-graph' });\n }\n return out;\n}\n\n/** Category-keyword + recency channel via npm search (the niche workhorse). */\nasync function searchChannel(): Promise<DiscoveryCandidate[]> {\n const out: DiscoveryCandidate[] = [];\n for (const category of CATEGORIES) {\n if (category === 'other') continue;\n const hits = await searchNpm(`keywords:${category}`, DISCOVERY.searchSizePerCategory);\n for (const hit of hits) {\n const via = isRecent(hit.date) ? 'recent' : 'category-search';\n out.push({ name: hit.name, via });\n }\n }\n return out;\n}\n\n/** Published within ~90 days counts as a \"recent\" entrant. */\nfunction isRecent(date: string | null): boolean {\n if (!date) return false;\n const ms = Date.parse(date);\n if (Number.isNaN(ms)) return false;\n return Date.now() - ms <= 90 * 24 * 60 * 60 * 1000;\n}\n\n// ── Orchestration ────────────────────────────────────────────────────────────\n\nexport async function runDiscovery(opts: DiscoverOptions = {}): Promise<DiscoverSummary> {\n const cap = opts.perRunCap ?? DISCOVERY.perRunCap;\n const handle = createDb({ max: 6 });\n try {\n logger.info('Discovery: gathering candidates from graph + search channels…');\n const [graph, search] = await Promise.all([graphChannel(handle.db), searchChannel()]);\n const known = await getKnownNames(handle.db);\n const fresh = selectCandidates([...graph, ...search], known);\n const enqueued = await enqueueCandidates(handle.db, fresh);\n logger.info(\n `Discovery: ${graph.length} graph + ${search.length} search candidates → ${enqueued} new queued.`,\n );\n\n // ── Merit gate: pre-score pending candidates on quality only ──────────────\n const pending = await getPendingCandidates(handle.db, cap * 4);\n const scored: { name: string; preScore: number }[] = [];\n for (const cand of pending) {\n // Reuse a stored pre-score: a candidate still 'pending' with a non-null\n // pre-score already cleared the gate on a prior run and was deferred past\n // the per-run cap. Re-fetching + re-scoring it every run is a wasted\n // registry round-trip — only score candidates that have never been gated.\n if (cand.preScore !== null) {\n scored.push({ name: cand.name, preScore: cand.preScore });\n continue;\n }\n const preScore = await preScorePackage(cand.name);\n await setDiscoveryStatus(handle.db, cand.name, {\n status: passesGate(preScore) ? 'pending' : 'rejected',\n preScore: preScore ?? null,\n });\n if (passesGate(preScore)) scored.push({ name: cand.name, preScore: preScore! });\n }\n logger.info(`Discovery: gated ${pending.length}; ${scored.length} cleared the quality bar.`);\n\n // ── Graduate the best, capped; log (don't silently drop) the tail ─────────\n scored.sort((a, b) => b.preScore - a.preScore);\n const toIngest = scored.slice(0, cap);\n const deferred = scored.slice(cap);\n if (deferred.length > 0) {\n logger.info(\n `Discovery: per-run cap ${cap} reached — ${deferred.length} eligible candidate(s) deferred to the next run: ${deferred.map((d) => d.name).join(', ')}`,\n );\n }\n\n let ingested = 0;\n if (!opts.dryRun) {\n for (const cand of toIngest) {\n try {\n await syncOnePackage(handle.db, cand.name);\n await setDiscoveryStatus(handle.db, cand.name, { status: 'ingested' });\n ingested++;\n } catch (err) {\n logger.warn(`Discovery: failed to ingest ${cand.name}: ${(err as Error).message}`);\n }\n }\n }\n\n logger.info(`Discovery: ingested ${ingested}/${toIngest.length} candidate(s).`);\n return {\n enqueued,\n gated: pending.length,\n passed: scored.length,\n ingested,\n droppedToNextRun: deferred.length,\n };\n } finally {\n await handle.close();\n }\n}\n","export { runSync, type SyncOptions, type SyncSummary } from './sync';\nexport { runRescore, type RescoreSummary } from './rescore';\nexport { runDiscovery, type DiscoverOptions, type DiscoverSummary } from './discovery';\n","/**\n * Dependency-free formatting helpers for human-facing CLI output. Compact tables\n * and labeled detail views; `--json` paths bypass these entirely.\n */\n\nconst ESC = '\u001b[';\nconst wrap = (code: string, s: string) => `${ESC}${code}m${s}${ESC}0m`;\n\nexport const bold = (s: string) => wrap('1', s);\nexport const dim = (s: string) => wrap('2', s);\nexport const red = (s: string) => wrap('31', s);\nexport const green = (s: string) => wrap('32', s);\nexport const yellow = (s: string) => wrap('33', s);\n\n// eslint-disable-next-line no-control-regex\nconst ANSI_RE = /\u001b\\[[0-9;]*m/g;\nconst width = (s: string) => s.replace(ANSI_RE, '').length;\n\n/** Render a simple aligned table. */\nexport function table(headers: string[], rows: string[][]): string {\n const widths = headers.map((h, i) => Math.max(width(h), ...rows.map((r) => width(r[i] ?? ''))));\n const pad = (s: string, w: number) => s + ' '.repeat(Math.max(0, w - width(s)));\n const line = (cells: string[]) => cells.map((c, i) => pad(c, widths[i]!)).join(' ');\n const out = [bold(line(headers)), dim(widths.map((w) => '─'.repeat(w)).join(' '))];\n for (const r of rows) out.push(line(r));\n return out.join('\\n');\n}\n\n/** Render a labeled key/value detail block. */\nexport function detail(pairs: [string, string][]): string {\n const labelWidth = Math.max(...pairs.map(([k]) => k.length));\n return pairs.map(([k, v]) => `${dim((k + ':').padEnd(labelWidth + 1))} ${v}`).join('\\n');\n}\n\n/** Compact number formatting: 1.2M, 34k, 950. */\nexport function formatNumber(n: number | null | undefined): string {\n if (n == null) return '—';\n if (n >= 1_000_000) return `${Math.round(n / 100_000) / 10}M`;\n if (n >= 1_000) return `${Math.round(n / 100) / 10}k`;\n return String(n);\n}\n\nexport function formatDate(iso: string | null): string {\n return iso ? iso.slice(0, 10) : '—';\n}\n\nexport function formatPercent(fraction: number | null | undefined): string {\n if (fraction == null) return '—';\n const pct = Math.round(fraction * 1000) / 10;\n return `${pct > 0 ? '+' : ''}${pct}%`;\n}\n\n/** Color a confidence label. */\nexport function confidenceLabel(c: string): string {\n if (c === 'proven') return green(c);\n if (c === 'emerging') return yellow(c);\n // `promising` (§1): high intrinsic quality, adoption-independent.\n if (c === 'promising') return green(c);\n return red(c);\n}\n","/**\n * Render a `plan` result as a self-contained HTML page: the Mermaid roadmap\n * rendered visually, plus the scored slot table. Mermaid is pulled from a CDN at\n * view time, so the file is a single portable artifact (no build step, no deps\n * added to the CLI). Used by `lurq plan --html <path>` / `--open`.\n */\nimport type { PlanOutput } from '../mcp/plan';\n\nfunction esc(s: string): string {\n return s.replace(/[&<>\"]/g, (c) => ({ '&': '&', '<': '<', '>': '>', '\"': '"' })[c]!);\n}\n\nfunction slotRows(plan: PlanOutput): string {\n return plan.slots\n .map((s) => {\n const rec = s.recommended;\n const name = rec\n ? rec.repoUrl\n ? `<a href=\"${esc(rec.repoUrl)}\" target=\"_blank\" rel=\"noreferrer\">${esc(rec.name)}</a>`\n : esc(rec.name)\n : '<span class=\"muted\">— no match —</span>';\n const alts = s.alternatives.map((a) => esc(a.name)).join(', ') || '<span class=\"muted\">—</span>';\n return `<tr>\n <td>${esc(s.need)}</td>\n <td><span class=\"layer\">${esc(s.layer)}</span></td>\n <td class=\"pkg\">${name}</td>\n <td class=\"num\">${rec ? rec.healthScore : '—'}</td>\n <td>${rec ? esc(rec.confidence) : '—'}</td>\n <td class=\"alts\">${alts}</td>\n </tr>`;\n })\n .join('\\n');\n}\n\nexport function renderPlanHtml(plan: PlanOutput): string {\n return `<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\" />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n<title>lurq plan — roadmap</title>\n<style>\n :root { color-scheme: dark; }\n * { box-sizing: border-box; }\n body { margin: 0; font: 15px/1.5 ui-sans-serif, system-ui, -apple-system, sans-serif;\n background: #0b0b0f; color: #e7e7ea; padding: 2.5rem clamp(1rem, 5vw, 4rem); }\n h1 { font-size: 1.5rem; margin: 0 0 .25rem; }\n h2 { font-size: 1rem; text-transform: uppercase; letter-spacing: .08em; color: #9a9aa6; margin: 2.5rem 0 .75rem; }\n .sub { color: #9a9aa6; margin: 0 0 1rem; max-width: 70ch; }\n .diagram { background: #141419; border: 1px solid #26262e; border-radius: 14px; padding: 1.5rem; overflow: auto; }\n table { width: 100%; border-collapse: collapse; margin-top: .5rem; }\n th, td { text-align: left; padding: .55rem .75rem; border-bottom: 1px solid #1e1e25; vertical-align: top; }\n th { font-size: .78rem; text-transform: uppercase; letter-spacing: .05em; color: #9a9aa6; }\n .pkg a { color: #d98cff; text-decoration: none; } .pkg a:hover { text-decoration: underline; }\n .num { text-align: right; font-variant-numeric: tabular-nums; }\n .muted { color: #6a6a76; } .alts { color: #b8b8c2; font-size: .92rem; }\n .layer { font-size: .8rem; color: #8ad; background: #15202b; border-radius: 6px; padding: .1rem .45rem; }\n footer { margin-top: 2.5rem; color: #6a6a76; font-size: .85rem; }\n</style>\n</head>\n<body>\n <h1>lurq plan <span class=\"muted\">· ${esc(plan.optimize)} · ${esc(plan.source)}${plan.framework ? ` · ${esc(plan.framework)} ecosystem` : ''}</span></h1>\n <p class=\"sub\">${esc(plan.note)}</p>\n\n <h2>Roadmap</h2>\n <div class=\"diagram\"><pre class=\"mermaid\">${esc(plan.mermaid)}</pre></div>\n\n <h2>Components</h2>\n <table>\n <thead><tr><th>Component</th><th>Layer</th><th>Recommended</th><th>Health</th><th>Confidence</th><th>Alternatives</th></tr></thead>\n <tbody>\n${slotRows(plan)}\n </tbody>\n </table>\n\n <footer>data as of ${esc(plan.dataAsOf)} · generated by lurq</footer>\n\n <script type=\"module\">\n import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';\n mermaid.initialize({ startOnLoad: true, theme: 'dark' });\n </script>\n</body>\n</html>\n`;\n}\n","/**\n * Cursor persistence for the npm `_changes` follower (one row per feed in\n * `watch_state`), so a restart resumes from the last processed sequence instead\n * of replaying the registry from the beginning.\n */\nimport { eq } from 'drizzle-orm';\nimport type { Database } from './client';\nimport { watchState } from './schema';\n\nexport async function getWatchCursor(db: Database, id: string): Promise<string | null> {\n const rows = await db\n .select({ seq: watchState.seq })\n .from(watchState)\n .where(eq(watchState.id, id))\n .limit(1);\n return rows[0]?.seq ?? null;\n}\n\nexport async function setWatchCursor(db: Database, id: string, seq: string): Promise<void> {\n await db\n .insert(watchState)\n .values({ id, seq, updatedAt: new Date() })\n .onConflictDoUpdate({ target: watchState.id, set: { seq, updatedAt: new Date() } });\n}\n","/**\n * npm `_changes` follower — the streaming log.\n *\n * Subscribes to the registry replication feed and, whenever a *tracked* package\n * publishes a new version, re-syncs it so scores, advisories, and the version\n * timeline stay fresh without a full crawl. Resumable via a persisted sequence\n * cursor (db/watch), so a restart picks up where it left off instead of\n * replaying the registry. Long-running: an operator runs `lurq watch` as a\n * daemon, matching lurq's external-scheduler model.\n */\nimport { logger } from '../core/logger';\nimport type { Database } from '../db/client';\nimport { getAllPackageNames } from '../db/packages';\nimport { getWatchCursor, setWatchCursor } from '../db/watch';\nimport { syncOnePackage } from './single';\n\nconst FEED_ID = 'npm-changes';\nconst FEED_URL = 'https://replicate.npmjs.com/_changes';\nconst HEARTBEAT_MS = 30_000;\nconst TRACKED_REFRESH_MS = 5 * 60_000; // re-read the tracked set this often\nconst CHECKPOINT_EVERY = 200; // advance the cursor through churn at least this often\nconst MAX_BACKOFF_MS = 30_000;\n\nexport interface ChangeRecord {\n seq: number | string;\n id: string;\n deleted: boolean;\n}\n\n/** Parse one NDJSON line from the continuous feed; null for heartbeats/garbage. */\nexport function parseChangeLine(line: string): ChangeRecord | null {\n const trimmed = line.trim();\n if (!trimmed) return null; // heartbeat\n try {\n const obj = JSON.parse(trimmed);\n if (typeof obj?.id !== 'string' || obj.seq == null) return null;\n return { seq: obj.seq, id: obj.id, deleted: Boolean(obj.deleted) };\n } catch {\n return null;\n }\n}\n\nexport interface WatchOptions {\n signal?: AbortSignal;\n /** Start point when no cursor is stored. 'now' (default) = only future changes. */\n since?: string;\n}\n\nexport async function watchNpmChanges(db: Database, opts: WatchOptions = {}): Promise<void> {\n const { signal } = opts;\n let backoff = 1000;\n\n while (!signal?.aborted) {\n let tracked = new Set(await getAllPackageNames(db));\n let trackedAt = Date.now();\n const since = (await getWatchCursor(db, FEED_ID)) ?? opts.since ?? 'now';\n const url = `${FEED_URL}?feed=continuous&since=${encodeURIComponent(since)}&heartbeat=${HEARTBEAT_MS}`;\n logger.info(`watch: connecting from seq=${since} (${tracked.size} tracked packages)`);\n\n try {\n const res = await fetch(url, { signal });\n if (!res.ok || !res.body) throw new Error(`feed responded ${res.status}`);\n backoff = 1000; // healthy connection — reset\n\n let sinceCheckpoint = 0;\n for await (const line of ndjsonLines(res.body, signal)) {\n const change = parseChangeLine(line);\n if (!change) continue;\n const seq = String(change.seq);\n sinceCheckpoint++;\n\n if (Date.now() - trackedAt > TRACKED_REFRESH_MS) {\n tracked = new Set(await getAllPackageNames(db));\n trackedAt = Date.now();\n }\n\n if (!change.deleted && tracked.has(change.id)) {\n logger.info(`watch: re-syncing ${change.id} (seq=${seq})`);\n await syncOnePackage(db, change.id).catch((err) =>\n logger.warn(`watch: re-sync failed for ${change.id}: ${String(err)}`),\n );\n await setWatchCursor(db, FEED_ID, seq);\n sinceCheckpoint = 0;\n } else if (sinceCheckpoint >= CHECKPOINT_EVERY) {\n await setWatchCursor(db, FEED_ID, seq); // advance through irrelevant churn\n sinceCheckpoint = 0;\n }\n }\n logger.info('watch: feed stream ended; reconnecting');\n } catch (err) {\n if (signal?.aborted) break;\n logger.warn(`watch: ${String(err)} — retrying in ${backoff}ms`);\n await sleep(backoff, signal);\n backoff = Math.min(backoff * 2, MAX_BACKOFF_MS);\n }\n }\n}\n\n/** Yield newline-delimited lines from a fetch ReadableStream as they arrive. */\nasync function* ndjsonLines(\n body: ReadableStream<Uint8Array>,\n signal?: AbortSignal,\n): AsyncGenerator<string> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n try {\n while (!signal?.aborted) {\n const { value, done } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n let nl: number;\n while ((nl = buffer.indexOf('\\n')) >= 0) {\n yield buffer.slice(0, nl);\n buffer = buffer.slice(nl + 1);\n }\n }\n } finally {\n reader.releaseLock();\n }\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve) => {\n const timer = setTimeout(resolve, ms);\n signal?.addEventListener(\n 'abort',\n () => {\n clearTimeout(timer);\n resolve();\n },\n { once: true },\n );\n });\n}\n","/**\n * Sandbox driver contract.\n *\n * Verification runs an install + smoke-load of a package version in an isolated\n * environment and reports whether it *actually* installs and loads — evidence no\n * static signal (downloads, stars) can provide.\n *\n * The interface is deliberately small so the runner is swappable: a local\n * child-process driver for dev/operator use, and a VM-isolated driver (E2B /\n * Firecracker / gVisor) for verifying UNTRUSTED packages at scale. Callers\n * depend only on this contract, never on a concrete driver.\n */\n\nexport type ModuleSystem = 'esm' | 'cjs';\n\nexport interface SandboxTarget {\n /** Node major the run targets. The local driver uses the host Node and just\n * records this; a VM driver provisions it. */\n node: string;\n moduleSystem: ModuleSystem;\n}\n\nexport interface SandboxVerifyOptions {\n target?: SandboxTarget;\n /** Run lifecycle install scripts (preinstall/install/postinstall). Off by\n * default: running untrusted scripts needs VM isolation, not a bare driver. */\n allowScripts?: boolean;\n timeoutMs?: number;\n signal?: AbortSignal;\n}\n\nexport interface SandboxResult {\n /** Provenance tag for the driver that produced this ('local', 'e2b', ...). */\n driver: string;\n moduleSystem: ModuleSystem;\n /** `npm install` succeeded. */\n installed: boolean;\n /** Package loaded (import/require without throwing). null = not attempted\n * because the install failed. */\n imported: boolean | null;\n /** Whether install scripts were allowed to run for this result. */\n ranScripts: boolean;\n durationMs: number;\n /** Condensed first line(s) of the failure, if any. */\n error: string | null;\n}\n\nexport interface SandboxPackage {\n name: string;\n version: string | null;\n}\n\nexport interface SandboxSetResult {\n driver: string;\n moduleSystem: ModuleSystem;\n /** Co-install of the whole set succeeded. */\n installed: boolean;\n /** Per-package smoke-load (null = not attempted because the install failed). */\n loaded: { name: string; loaded: boolean | null }[];\n durationMs: number;\n error: string | null;\n}\n\nexport interface Sandbox {\n /** Provenance tag stored with each result. */\n readonly name: string;\n verify(\n pkg: string,\n version: string | null,\n opts?: SandboxVerifyOptions,\n ): Promise<SandboxResult>;\n /** Co-install a set of packages and smoke-load each — the basis of the\n * compatibility matrix. A successful co-install proves the set coexists. */\n verifySet(\n packages: SandboxPackage[],\n opts?: SandboxVerifyOptions,\n ): Promise<SandboxSetResult>;\n}\n\nexport const DEFAULT_TARGET: SandboxTarget = {\n node: '20',\n moduleSystem: 'cjs',\n};\n","/**\n * Local child-process sandbox driver.\n *\n * Installs package(s) into a throwaway temp dir and smoke-loads them, reporting\n * whether they install and load. Fast and dependency-free (just npm + node).\n *\n * NOT an isolation boundary: loading a package executes its top-level code on\n * the host, so use this only for packages you already trust (operator/dev).\n * Verify UNTRUSTED packages with a VM driver. Install scripts stay OFF unless\n * `allowScripts` is set, since the whole point of the security tier is to not\n * execute untrusted install hooks.\n */\nimport { execFile } from 'node:child_process';\nimport { mkdtemp, rm, writeFile } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport { promisify } from 'node:util';\nimport {\n DEFAULT_TARGET,\n type ModuleSystem,\n type Sandbox,\n type SandboxPackage,\n type SandboxResult,\n type SandboxSetResult,\n type SandboxVerifyOptions,\n} from './types';\n\nconst execFileAsync = promisify(execFile);\nconst INSTALL_TIMEOUT_MS = 120_000;\nconst SMOKE_TIMEOUT_MS = 30_000;\nconst ERROR_MAX = 500;\n\n/** npm args for a throwaway install of one or more specs into the sandbox dir. */\nexport function npmInstallArgs(specs: string[], opts: { allowScripts: boolean }): string[] {\n // A spec beginning with `-` would be parsed as an npm flag (e.g.\n // `--registry=evil`), not a package. Legitimate names/specs never start with\n // one, so reject rather than smuggle it into the install command.\n const bad = specs.find((s) => s.startsWith('-'));\n if (bad) throw new Error(`Invalid package spec: ${bad}`);\n const args = ['install', ...specs, '--no-audit', '--no-fund', '--no-package-lock', '--no-save'];\n if (!opts.allowScripts) args.push('--ignore-scripts');\n return args;\n}\n\n/** A one-liner that loads the package and exits non-zero if it throws. */\nexport function smokeScript(pkg: string, moduleSystem: ModuleSystem): string[] {\n return moduleSystem === 'esm'\n ? ['--input-type=module', '-e', `await import(${JSON.stringify(pkg)})`]\n : ['-e', `require(${JSON.stringify(pkg)})`];\n}\n\nfunction condense(s: string): string {\n return s.replace(/\\s+/g, ' ').trim().slice(0, ERROR_MAX);\n}\n\nfunction stderrOf(err: unknown): string {\n if (err && typeof err === 'object') {\n const e = err as { stderr?: unknown; message?: unknown };\n if (typeof e.stderr === 'string' && e.stderr.trim()) return e.stderr;\n if (typeof e.message === 'string') return e.message;\n }\n return String(err);\n}\n\nconst toSpec = (p: SandboxPackage): string => (p.version ? `${p.name}@${p.version}` : p.name);\n\nexport class LocalSandbox implements Sandbox {\n readonly name = 'local';\n\n async verify(\n pkg: string,\n version: string | null,\n opts: SandboxVerifyOptions = {},\n ): Promise<SandboxResult> {\n const set = await this.verifySet([{ name: pkg, version }], opts);\n return {\n driver: this.name,\n moduleSystem: set.moduleSystem,\n installed: set.installed,\n imported: set.loaded[0]?.loaded ?? null,\n ranScripts: opts.allowScripts ?? false,\n durationMs: set.durationMs,\n error: set.error,\n };\n }\n\n async verifySet(\n packages: SandboxPackage[],\n opts: SandboxVerifyOptions = {},\n ): Promise<SandboxSetResult> {\n const target = opts.target ?? DEFAULT_TARGET;\n const allowScripts = opts.allowScripts ?? false;\n const specs = packages.map(toSpec);\n const dir = await mkdtemp(join(tmpdir(), 'lurq-sandbox-'));\n const started = Date.now();\n const loaded = packages.map((p) => ({ name: p.name, loaded: null as boolean | null }));\n let installed = false;\n let error: string | null = null;\n\n try {\n await writeFile(\n join(dir, 'package.json'),\n JSON.stringify({ name: 'lurq-sandbox', version: '0.0.0', private: true }),\n );\n await execFileAsync('npm', npmInstallArgs(specs, { allowScripts }), {\n cwd: dir,\n timeout: opts.timeoutMs ?? INSTALL_TIMEOUT_MS,\n signal: opts.signal,\n });\n installed = true;\n\n for (let i = 0; i < packages.length; i++) {\n try {\n await execFileAsync('node', smokeScript(packages[i]!.name, target.moduleSystem), {\n cwd: dir,\n timeout: SMOKE_TIMEOUT_MS,\n signal: opts.signal,\n });\n loaded[i]!.loaded = true;\n } catch (err) {\n loaded[i]!.loaded = false;\n if (!error) error = condense(stderrOf(err));\n }\n }\n } catch (err) {\n error = condense(stderrOf(err));\n } finally {\n await rm(dir, { recursive: true, force: true }).catch(() => {});\n }\n\n return {\n driver: this.name,\n moduleSystem: target.moduleSystem,\n installed,\n loaded,\n durationMs: Date.now() - started,\n error,\n };\n }\n}\n","/**\n * E2B cloud-sandbox driver.\n *\n * Installs package(s) and smoke-loads them inside an isolated E2B microVM, so\n * top-level package code (and, with allowScripts, install hooks) runs OFF the\n * host. This is the isolation boundary the local driver deliberately lacks —\n * use it to verify UNTRUSTED packages at scale.\n *\n * Requires E2B_API_KEY. The launched template must have node + npm on PATH\n * (see E2B_TEMPLATE). Like the local driver, target.node is recorded but not\n * provisioned — pin a Node-versioned template for reproducible majors.\n */\nimport { getConfig } from '../core/config';\nimport {\n DEFAULT_TARGET,\n type ModuleSystem,\n type Sandbox as SandboxDriver,\n type SandboxPackage,\n type SandboxResult,\n type SandboxSetResult,\n type SandboxVerifyOptions,\n} from './types';\n\nconst INSTALL_TIMEOUT_MS = 120_000;\nconst SMOKE_TIMEOUT_MS = 30_000;\nconst ERROR_MAX = 500;\nconst WORKDIR = '/home/user';\n\n/** POSIX single-quote: safe for any arg (specs may carry `^`, `>`, spaces). */\nexport function shQuote(s: string): string {\n return `'${s.replace(/'/g, `'\\\\''`)}'`;\n}\n\n/** Shell command that installs the specs into WORKDIR. */\nexport function installCommand(specs: string[], allowScripts: boolean): string {\n const bad = specs.find((s) => s.startsWith('-'));\n if (bad) throw new Error(`Invalid package spec: ${bad}`);\n const flags = ['--no-audit', '--no-fund', '--no-package-lock', '--no-save'];\n if (!allowScripts) flags.push('--ignore-scripts');\n return `npm install ${specs.map(shQuote).join(' ')} ${flags.join(' ')}`;\n}\n\n/** Shell command that loads a package and exits non-zero if it throws. */\nexport function smokeCommand(pkg: string, moduleSystem: ModuleSystem): string {\n const js =\n moduleSystem === 'esm' ? `await import(${JSON.stringify(pkg)})` : `require(${JSON.stringify(pkg)})`;\n const flags = moduleSystem === 'esm' ? '--input-type=module ' : '';\n return `node ${flags}-e ${shQuote(js)}`;\n}\n\nfunction condense(s: string): string {\n return s.replace(/\\s+/g, ' ').trim().slice(0, ERROR_MAX);\n}\n\nfunction errText(err: unknown): string {\n if (err && typeof err === 'object') {\n const e = err as { stderr?: unknown; message?: unknown };\n if (typeof e.stderr === 'string' && e.stderr.trim()) return e.stderr;\n if (typeof e.message === 'string') return e.message;\n }\n return String(err);\n}\n\nconst toSpec = (p: SandboxPackage): string => (p.version ? `${p.name}@${p.version}` : p.name);\n\nexport class E2BSandbox implements SandboxDriver {\n readonly name = 'e2b';\n\n async verify(\n pkg: string,\n version: string | null,\n opts: SandboxVerifyOptions = {},\n ): Promise<SandboxResult> {\n const set = await this.verifySet([{ name: pkg, version }], opts);\n return {\n driver: this.name,\n moduleSystem: set.moduleSystem,\n installed: set.installed,\n imported: set.loaded[0]?.loaded ?? null,\n ranScripts: opts.allowScripts ?? false,\n durationMs: set.durationMs,\n error: set.error,\n };\n }\n\n async verifySet(\n packages: SandboxPackage[],\n opts: SandboxVerifyOptions = {},\n ): Promise<SandboxSetResult> {\n const config = getConfig();\n const target = opts.target ?? DEFAULT_TARGET;\n const allowScripts = opts.allowScripts ?? false;\n const specs = packages.map(toSpec);\n const installTimeout = opts.timeoutMs ?? INSTALL_TIMEOUT_MS;\n const started = Date.now();\n const loaded = packages.map((p) => ({ name: p.name, loaded: null as boolean | null }));\n let installed = false;\n let error: string | null = null;\n\n // Build install command up front so a bad spec fails before we spend a VM.\n const install = installCommand(specs, allowScripts);\n\n // Lazy-load e2b: its CJS build does require('chalk'), and chalk@5 is\n // ESM-only, which crashes require(esm) on some Node 22.x versions. Keeping\n // it off the import graph means the crash can only ever reach `verify`,\n // never `lurq` startup. (tsup would otherwise hoist a static top-level\n // `import` even though sandbox/index.ts loads this module dynamically.)\n const { default: Sandbox } = await import('e2b');\n\n // Sandbox lifetime must outlast install + every smoke run, plus buffer.\n const createOpts = {\n apiKey: config.E2B_API_KEY,\n timeoutMs: installTimeout + SMOKE_TIMEOUT_MS * packages.length + 30_000,\n };\n const sandbox = config.E2B_TEMPLATE\n ? await Sandbox.create(config.E2B_TEMPLATE, createOpts)\n : await Sandbox.create(createOpts);\n\n try {\n await sandbox.files.write(\n `${WORKDIR}/package.json`,\n JSON.stringify({ name: 'lurq-sandbox', version: '0.0.0', private: true }),\n );\n await sandbox.commands.run(install, { cwd: WORKDIR, timeoutMs: installTimeout });\n installed = true;\n\n for (let i = 0; i < packages.length; i++) {\n try {\n await sandbox.commands.run(smokeCommand(packages[i]!.name, target.moduleSystem), {\n cwd: WORKDIR,\n timeoutMs: SMOKE_TIMEOUT_MS,\n });\n loaded[i]!.loaded = true;\n } catch (err) {\n loaded[i]!.loaded = false;\n if (!error) error = condense(errText(err));\n }\n }\n } catch (err) {\n error = condense(errText(err));\n } finally {\n await sandbox.kill().catch(() => {});\n }\n\n return {\n driver: this.name,\n moduleSystem: target.moduleSystem,\n installed,\n loaded,\n durationMs: Date.now() - started,\n error,\n };\n }\n}\n","/**\n * Sandbox driver selection. With E2B_API_KEY set, the VM-isolated E2B driver is\n * used (safe for untrusted packages); otherwise the local child-process driver\n * (trusted packages only). The E2B module is imported lazily so its heavy SDK\n * never loads on the CLI/install path when isolation isn't configured.\n */\nimport { getConfig } from '../core/config';\nimport { LocalSandbox } from './local';\nimport type { Sandbox } from './types';\n\nexport async function getSandbox(): Promise<Sandbox> {\n if (getConfig().E2B_API_KEY) {\n const { E2BSandbox } = await import('./e2b');\n return new E2BSandbox();\n }\n return new LocalSandbox();\n}\n\nexport * from './types';\nexport { LocalSandbox, npmInstallArgs, smokeScript } from './local';\n","/**\n * Run a package version through the sandbox and persist the result. Decoupled\n * from the query path: an operator/cron drives this in the background and the\n * stored verdict is read instantly at recommend/verify time.\n */\nimport type { Database } from '../db/client';\nimport { storeVerificationRun } from '../db/verification';\nimport { getSandbox } from '../sandbox';\nimport type { SandboxResult, SandboxVerifyOptions } from '../sandbox/types';\n\nexport async function verifyPackageInSandbox(\n db: Database,\n pkg: string,\n version: string | null,\n opts: SandboxVerifyOptions = {},\n): Promise<SandboxResult> {\n const result = await (await getSandbox()).verify(pkg, version, opts);\n // Persist for the query path. Non-fatal: never fail the run on a write error.\n await storeVerificationRun(db, {\n packageName: pkg,\n version: version ?? 'latest',\n driver: result.driver,\n moduleSystem: result.moduleSystem,\n installed: result.installed,\n imported: result.imported,\n ranScripts: result.ranScripts,\n durationMs: result.durationMs,\n error: result.error,\n ranAt: new Date(),\n }).catch(() => {});\n return result;\n}\n","/**\n * Compatibility verification: co-install a set of packages in the sandbox and\n * record pairwise edges. A successful co-install proves the set coexists (every\n * pair compatible); a 2-package failure proves that pair conflicts. A larger\n * failed set can't pin the culprit, so no edge is asserted (set-level report).\n */\nimport type { CompatStatus } from '../core/types';\nimport type { Database } from '../db/client';\nimport { canonicalPair, upsertCompatEdge } from '../db/compat';\nimport { getPackageByName } from '../db/packages';\nimport { getSandbox } from '../sandbox';\nimport type { SandboxSetResult } from '../sandbox/types';\n\nexport interface CompatEdge {\n a: string;\n aVersion: string;\n b: string;\n bVersion: string;\n status: CompatStatus;\n}\n\ninterface Resolved {\n name: string;\n version: string;\n}\n\n/** Derive pairwise edges from a set co-install result. Pure. */\nexport function deriveCompatEdges(resolved: Resolved[], result: SandboxSetResult): CompatEdge[] {\n const allLoaded = result.loaded.every((l) => l.loaded === true);\n const edges: CompatEdge[] = [];\n\n if (result.installed && allLoaded) {\n // Co-install proved the whole set coexists → every pair is compatible.\n for (let i = 0; i < resolved.length; i++) {\n for (let j = i + 1; j < resolved.length; j++) {\n edges.push({\n a: resolved[i]!.name,\n aVersion: resolved[i]!.version,\n b: resolved[j]!.name,\n bVersion: resolved[j]!.version,\n status: 'compatible',\n });\n }\n }\n } else if (resolved.length === 2) {\n // A failed *pair* is precise: those two conflict.\n edges.push({\n a: resolved[0]!.name,\n aVersion: resolved[0]!.version,\n b: resolved[1]!.name,\n bVersion: resolved[1]!.version,\n status: 'conflict',\n });\n }\n // else: a larger set failed — can't attribute the conflict to a single pair.\n return edges;\n}\n\nexport interface CompatRunResult {\n result: SandboxSetResult;\n edges: CompatEdge[];\n /** A set-level conflict that couldn't be pinned to a specific pair. */\n unattributedConflict: boolean;\n}\n\nexport async function verifyCompatibility(\n db: Database,\n packages: string[],\n opts: { allowScripts?: boolean } = {},\n): Promise<CompatRunResult> {\n const resolved: Resolved[] = await Promise.all(\n packages.map(async (name) => ({\n name,\n version: (await getPackageByName(db, name))?.latestVersion ?? 'latest',\n })),\n );\n\n const result = await (await getSandbox()).verifySet(\n resolved.map((r) => ({ name: r.name, version: r.version === 'latest' ? null : r.version })),\n { allowScripts: opts.allowScripts },\n );\n\n const edges = deriveCompatEdges(resolved, result);\n for (const e of edges) {\n const pair = canonicalPair(\n { name: e.a, version: e.aVersion },\n { name: e.b, version: e.bVersion },\n );\n await upsertCompatEdge(db, {\n ...pair,\n status: e.status,\n driver: result.driver,\n ranAt: new Date(),\n }).catch(() => {});\n }\n\n const failed = !result.installed || !result.loaded.every((l) => l.loaded === true);\n return { result, edges, unattributedConflict: failed && edges.length === 0 };\n}\n","/**\n * Human-facing CLI command implementations (§13). Each reuses the MCP handlers\n * against a DB connection, then renders a compact table/detail view — or raw\n * JSON with `--json`.\n */\nimport { requireConfig } from '../core/config';\nimport { isCategory, type Category, type Confidence } from '../core/types';\nimport { createDb } from '../db/client';\nimport { getPackageVersions } from '../db/packages';\nimport { handleCompare, handleEvaluate, handleRecommend, handleVerify } from '../mcp/handlers';\nimport { CONFIDENCE, QUALITY_WEIGHTS } from '../scoring/weights';\nimport {\n activeWeightsPath,\n applyOverrides,\n loadWeights,\n resetWeights,\n saveWeights,\n settableKeys,\n validateWeights,\n WEIGHT_EXPLANATIONS,\n} from '../scoring/weights';\nimport {\n bold,\n confidenceLabel,\n detail,\n dim,\n formatDate,\n formatNumber,\n formatPercent,\n green,\n red,\n table,\n yellow,\n} from './format';\n\nasync function withDb<T>(fn: (db: ReturnType<typeof createDb>['db']) => Promise<T>): Promise<T> {\n requireConfig(['DATABASE_URL']);\n const handle = createDb();\n try {\n return await fn(handle.db);\n } finally {\n await handle.close();\n }\n}\n\nexport interface RecommendCliOpts {\n category?: string;\n minConfidence?: string;\n json?: boolean;\n}\n\nexport async function runRecommend(need: string, opts: RecommendCliOpts): Promise<void> {\n if (opts.category && !isCategory(opts.category)) {\n throw new Error(`Unknown category \"${opts.category}\".`);\n }\n await withDb(async (db) => {\n const res = await handleRecommend(db, {\n need,\n category: opts.category as Category | undefined,\n constraints: opts.minConfidence\n ? { minConfidence: opts.minConfidence as Confidence }\n : undefined,\n });\n if (opts.json) return console.log(JSON.stringify(res, null, 2));\n if (res.candidates.length === 0) {\n console.log('No matching packages found.');\n return;\n }\n console.log(\n table(\n ['Package', 'Health', 'Quality', 'Confidence', 'Weekly', 'Latest', 'Category'],\n res.candidates.map((c) => [\n c.name,\n String(c.healthScore),\n c.qualityScore != null ? String(c.qualityScore) : '—',\n confidenceLabel(c.confidence),\n formatNumber(c.weeklyDownloads),\n c.latestVersion ?? '—',\n c.category ?? '—',\n ]),\n ),\n );\n console.log(dim(`\\ndata as of ${formatDate(res.dataAsOf)}`));\n });\n}\n\nexport async function runEvaluate(pkg: string, opts: { json?: boolean }): Promise<void> {\n await withDb(async (db) => {\n const res = await handleEvaluate(db, { package: pkg });\n if (opts.json) return console.log(JSON.stringify(res, null, 2));\n if ('tracked' in res) {\n console.log(res.suggestion);\n return;\n }\n console.log(bold(res.name) + (res.category ? dim(` (${res.category})`) : ''));\n const b = res.scoreBreakdown;\n console.log(\n detail([\n ['health', `${res.healthScore} ${confidenceLabel(res.confidence)}`],\n ['quality', res.qualityScore != null ? String(res.qualityScore) : '—'],\n [\n 'breakdown',\n `maint ${b.maintenance} · adopt ${b.adoption} · rel ${b.reliability} · eff ${b.efficiency ?? '—'} · qual ${b.quality ?? '—'}`,\n ],\n ['version', res.latestVersion ?? '—'],\n ['weekly dl', `${formatNumber(res.weeklyDownloads)} (${formatPercent(res.downloadGrowth90d)} 90d)`],\n ['scorecard', res.scorecard != null ? String(res.scorecard) : '—'],\n ['bundle', res.bundleMinGzipKb != null ? `${res.bundleMinGzipKb} KB gzip` : '—'],\n ['released', formatDate(res.lastReleaseAt)],\n ['flags', [res.deprecated && 'deprecated', res.archived && 'archived'].filter(Boolean).join(', ') || 'none'],\n ['advisories', res.advisories.length ? res.advisories.map((a) => `${a.severity}`).join(', ') : 'none'],\n ['repo', res.repoUrl ?? '—'],\n ]),\n );\n if (res.buildVerified) {\n const bv = res.buildVerified;\n const state = !bv.installed\n ? red('install failed')\n : bv.loaded === false\n ? yellow('installs, load failed')\n : green('installs and loads');\n console.log(`\\nsandbox: ${state} ${dim(`${bv.version} · ${bv.driver}`)}`);\n }\n if (res.summary) console.log('\\n' + res.summary);\n if (res.usageGuide) {\n const g = res.usageGuide;\n console.log(\n '\\n' +\n detail(\n [\n ['what', g.whatItIs],\n ['when', g.whenToUse],\n g.whenNotToUse ? (['when not', g.whenNotToUse] as [string, string]) : null,\n ['fits', g.whereItFits],\n g.howToWireIn ? (['wire-in', g.howToWireIn] as [string, string]) : null,\n ].filter(Boolean) as [string, string][],\n ),\n );\n }\n console.log(dim(`\\ndata as of ${formatDate(res.dataAsOf)}${res.stale ? ' (stale)' : ''}`));\n });\n}\n\nexport async function runCompare(pkgs: string[], opts: { json?: boolean }): Promise<void> {\n await withDb(async (db) => {\n const res = await handleCompare(db, { packages: pkgs });\n if (opts.json) return console.log(JSON.stringify(res, null, 2));\n console.log(\n table(\n ['Package', 'Health', 'Confidence', 'Weekly', '90d', 'Scorecard', 'Released'],\n res.rows.map((r) => [\n r.name,\n String(r.healthScore),\n confidenceLabel(r.confidence),\n formatNumber(r.weeklyDownloads),\n formatPercent(r.downloadGrowth90d),\n r.scorecard != null ? String(r.scorecard) : '—',\n formatDate(r.lastReleaseAt),\n ]),\n ),\n );\n if (res.missing?.length) console.log(dim(`\\nnot found: ${res.missing.join(', ')}`));\n console.log(dim(`data as of ${formatDate(res.dataAsOf)}`));\n });\n}\n\n// ── weights / edit-weights (§4) ──────────────────────────────────────────────\n\n/** `lurq weights` — show + explain the score model (no DB needed). */\nexport function runWeights(opts: { json?: boolean } = {}): void {\n const w = loadWeights();\n const active = activeWeightsPath();\n if (opts.json) {\n console.log(JSON.stringify({ ...w, source: active?.source ?? 'defaults' }, null, 2));\n return;\n }\n const pct = (n: number) => n.toFixed(2);\n console.log(bold('Two axes, blended for default sort:'));\n console.log(` composite = (1−λ)·health + λ·quality λ = ${pct(w.composite.lambda)}\\n`);\n console.log(bold('Health (proven-ness) — weighted sum of 4 components:'));\n console.log(\n detail([\n ['maintenance', `${pct(w.health.maintenance)} ${dim('— ' + WEIGHT_EXPLANATIONS.maintenance!)}`],\n ['adoption', `${pct(w.health.adoption)} ${dim('— ' + WEIGHT_EXPLANATIONS.adoption!)}`],\n ['reliability', `${pct(w.health.reliability)} ${dim('— ' + WEIGHT_EXPLANATIONS.reliability!)}`],\n ['efficiency', `${pct(w.health.efficiency)} ${dim('— ' + WEIGHT_EXPLANATIONS.efficiency!)}`],\n ]),\n );\n console.log('\\n' + bold('Quality (intrinsic, adoption-independent):'));\n console.log(' ' + dim(Object.keys(QUALITY_WEIGHTS).join(', ')));\n console.log('\\n' + bold('Confidence thresholds:'));\n console.log(\n detail([\n ['proven', `≥ ${formatNumber(CONFIDENCE.proven.minWeeklyDownloads)} weekly dl, ≥ ${CONFIDENCE.proven.minAgeMonths}mo old`],\n ['emerging', `≥ ${formatNumber(CONFIDENCE.emerging.minWeeklyDownloads)} weekly dl OR ≥ ${CONFIDENCE.emerging.strongGrowth * 100}% 90d growth`],\n ['promising', `≥ ${CONFIDENCE.promising.minQuality} quality score (adoption-independent)`],\n ]),\n );\n console.log(dim(`\\nSource: ${active ? `${active.source} (${active.path})` : 'defaults (no user overrides)'}`));\n}\n\nexport interface EditWeightsOpts {\n set?: string[];\n reset?: boolean;\n explain?: string;\n project?: boolean;\n json?: boolean;\n}\n\n/** `lurq edit-weights` — override / reset / explain the model (no DB needed).\n * A weight change alters ranking at read time, so invalidate the response cache\n * (no-op without REDIS_URL) when run where the index is served. */\nexport async function runEditWeights(opts: EditWeightsOpts): Promise<void> {\n const { invalidateCache } = await import('../core/cache');\n if (opts.reset) {\n const removed = resetWeights();\n console.log(removed.length ? `Removed overrides:\\n ${removed.join('\\n ')}` : 'No overrides to remove; already on defaults.');\n if (removed.length) await invalidateCache();\n return;\n }\n\n if (opts.explain) {\n const key = opts.explain;\n const text = WEIGHT_EXPLANATIONS[key];\n if (!text) {\n throw new Error(`No explanation for \"${key}\". Known: ${Object.keys(WEIGHT_EXPLANATIONS).join(', ')}.`);\n }\n console.log(`${bold(key)} — ${text}`);\n return;\n }\n\n if (opts.set && opts.set.length > 0) {\n const next = applyOverrides(loadWeights(), opts.set);\n const { weights, normalized } = validateWeights(next);\n const path = saveWeights(weights, opts.project ? 'project' : 'user');\n await invalidateCache();\n console.log(`Saved overrides to ${path}`);\n if (normalized) {\n console.log(\n yellow('Health weights did not sum to 1.0 — renormalized to: ') +\n `maint ${weights.health.maintenance.toFixed(3)}, adopt ${weights.health.adoption.toFixed(3)}, rel ${weights.health.reliability.toFixed(3)}, eff ${weights.health.efficiency.toFixed(3)}`,\n );\n }\n console.log(dim('\\nRun `lurq rescore` to apply the new health weights to the stored index.'));\n return;\n }\n\n // No action flags → behave like `lurq weights`.\n console.log(dim(`No changes. Settable keys: ${settableKeys().join(', ')}.\\n`));\n runWeights(opts);\n}\n\nexport interface PlanCliOpts {\n optimize?: string;\n json?: boolean;\n html?: string;\n open?: boolean;\n}\n\n/** Open a file/URL in the OS default app, cross-platform, best-effort. No shell\n * (avoids metacharacter injection); on Windows `cmd /c start \"\" <target>` keeps\n * spaced paths intact because Node passes each arg separately. */\nasync function openInBrowser(target: string): Promise<void> {\n const { spawn } = await import('node:child_process');\n const [cmd, args]: [string, string[]] =\n process.platform === 'darwin'\n ? ['open', [target]]\n : process.platform === 'win32'\n ? ['cmd', ['/c', 'start', '', target]]\n : ['xdg-open', [target]];\n spawn(cmd, args, { stdio: 'ignore', detached: true }).unref();\n}\n\nexport async function runPlan(file: string, opts: PlanCliOpts): Promise<void> {\n const { readFileSync } = await import('node:fs');\n let document: string;\n try {\n document = readFileSync(file, 'utf8');\n } catch {\n throw new Error(`Could not read \"${file}\".`);\n }\n if (opts.optimize && opts.optimize !== 'speed' && opts.optimize !== 'balanced') {\n throw new Error(\"--optimize must be 'speed' or 'balanced'.\");\n }\n await withDb(async (db) => {\n const { handlePlan } = await import('../mcp/plan');\n const res = await handlePlan(db, {\n document,\n optimize: opts.optimize as 'speed' | 'balanced' | undefined,\n });\n if (opts.json) return console.log(JSON.stringify(res, null, 2));\n if (!('slots' in res)) {\n console.log(res.note);\n return;\n }\n\n // Visualization: render the roadmap to a portable HTML file and optionally open it.\n if (opts.html || opts.open) {\n const { writeFileSync } = await import('node:fs');\n const { tmpdir } = await import('node:os');\n const { join } = await import('node:path');\n const { renderPlanHtml } = await import('./planView');\n const out = opts.html ?? join(tmpdir(), `lurq-plan-${Date.now()}.html`);\n writeFileSync(out, renderPlanHtml(res), 'utf8');\n console.log(`Roadmap written to ${out}`);\n if (opts.open) await openInBrowser(out);\n }\n\n console.log(\n table(\n ['Component', 'Layer', 'Recommended', 'Health', 'Confidence', 'Alternatives'],\n res.slots.map((s) => [\n s.need.length > 32 ? s.need.slice(0, 31) + '…' : s.need,\n s.layer,\n s.recommended\n ? `${s.recommended.name}@${s.recommended.latestVersion ?? '?'}`\n : dim('—'),\n s.recommended ? String(s.recommended.healthScore) : '—',\n s.recommended ? confidenceLabel(s.recommended.confidence) : '—',\n s.alternatives.map((a) => a.name).join(', ') || '—',\n ]),\n ),\n );\n if (res.unmatched.length) console.log(yellow(`\\nNo match for: ${res.unmatched.join(', ')}`));\n\n if (res.compatibility) {\n const c = res.compatibility;\n const col = c.overall === 'compatible' ? green : c.overall === 'conflict' ? red : dim;\n console.log('\\n' + bold('Compatibility: ') + col(c.overall));\n for (const s of res.slots) {\n if (s.swappedFrom && s.recommended) {\n console.log(green(` ✓ swapped ${s.swappedFrom} → ${s.recommended.name} for compatibility`));\n }\n }\n for (const cf of c.conflicts) console.log(red(` ✗ ${cf.detail} (no compatible alternative)`));\n if (c.unverified.length) console.log(dim(` unverified: ${c.unverified.join(', ')}`));\n }\n\n console.log('\\n' + bold('Roadmap (Mermaid):'));\n console.log(res.mermaid);\n console.log(dim(`\\n${res.note}`));\n console.log(dim(`data as of ${formatDate(res.dataAsOf)}`));\n });\n}\n\nexport async function runVerify(pkg: string, opts: { json?: boolean }): Promise<void> {\n await withDb(async (db) => {\n const res = await handleVerify(db, { package: pkg });\n if (opts.json) return console.log(JSON.stringify(res, null, 2));\n const riskColor = res.risk === 'high' ? red : res.risk === 'medium' ? yellow : green;\n const verdict = !res.exists\n ? red('✗ NOT FOUND on npm')\n : res.risk === 'high'\n ? red('✗ high supply-chain risk')\n : res.risk === 'medium'\n ? yellow('⚠ exists, but risky')\n : green('✓ looks safe');\n console.log(`${bold(pkg)} ${verdict}`);\n console.log(\n detail([\n ['version', res.latestVersion ?? '—'],\n ['weekly dl', formatNumber(res.weeklyDownloads)],\n ['confidence', res.confidence ? confidenceLabel(res.confidence) : '—'],\n ['advisories', String(res.advisoryCount)],\n ['risk', riskColor(res.risk)],\n ['risk flags', res.riskFlags.length ? yellow(res.riskFlags.join(', ')) : 'none'],\n ]),\n );\n });\n}\n\nexport async function runVersions(\n pkg: string,\n opts: { json?: boolean; limit?: string },\n): Promise<void> {\n const limit = opts.limit ? Math.max(1, parseInt(opts.limit, 10) || 30) : 30;\n await withDb(async (db) => {\n const versions = await getPackageVersions(db, pkg, limit);\n if (opts.json) return console.log(JSON.stringify(versions, null, 2));\n if (versions.length === 0) {\n console.log(`No stored versions for ${bold(pkg)}. Run \\`lurq sync --package ${pkg}\\` first.`);\n return;\n }\n console.log(bold(pkg));\n console.log(\n table(\n ['Version', 'Published'],\n versions.map((v) => [\n v.version,\n v.publishedAt ? v.publishedAt.toISOString().slice(0, 10) : '—',\n ]),\n ),\n );\n });\n}\n\n/** Long-running: follow the npm changes feed until interrupted (Ctrl-C). */\nexport async function runWatch(): Promise<void> {\n const { watchNpmChanges } = await import('../pipeline/watch');\n await withDb(async (db) => {\n const controller = new AbortController();\n const stop = () => controller.abort();\n process.once('SIGINT', stop);\n process.once('SIGTERM', stop);\n console.log(dim('watching npm for releases of tracked packages — Ctrl-C to stop'));\n try {\n await watchNpmChanges(db, { signal: controller.signal });\n } finally {\n process.off('SIGINT', stop);\n process.off('SIGTERM', stop);\n }\n });\n}\n\n/** Operator-side: install + smoke-load a package in the sandbox to verify it works. */\nexport async function runSandbox(\n pkg: string,\n version: string | undefined,\n opts: { esm?: boolean; allowScripts?: boolean; json?: boolean },\n): Promise<void> {\n if (opts.allowScripts) {\n console.error(\n yellow('warning: running install scripts and loading the package locally without isolation'),\n );\n }\n const { verifyPackageInSandbox } = await import('../pipeline/sandbox');\n await withDb(async (db) => {\n const result = await verifyPackageInSandbox(db, pkg, version ?? null, {\n target: { node: '20', moduleSystem: opts.esm ? 'esm' : 'cjs' },\n allowScripts: opts.allowScripts,\n });\n if (opts.json) return console.log(JSON.stringify(result, null, 2));\n const ok = result.installed && result.imported !== false;\n const label = version ? `${pkg}@${version}` : pkg;\n const verdict = ok ? green('✓ installs and loads') : red('✗ failed');\n console.log(`${bold(label)} ${verdict} ${dim(`(${result.durationMs}ms · ${result.driver})`)}`);\n console.log(\n detail([\n ['installed', result.installed ? 'yes' : 'no'],\n ['loaded', result.imported === null ? '—' : result.imported ? 'yes' : 'no'],\n ['module', result.moduleSystem],\n ['scripts', result.ranScripts ? 'ran' : 'skipped'],\n ['error', result.error ?? 'none'],\n ]),\n );\n });\n}\n\n/** Read (or, with --run, sandbox-verify then read) pairwise package compatibility. */\nexport async function runCompat(\n pkgs: string[],\n opts: { run?: boolean; json?: boolean },\n): Promise<void> {\n await withDb(async (db) => {\n if (opts.run) {\n console.error(\n yellow('co-installing in the sandbox (loads package code locally without isolation)'),\n );\n const { verifyCompatibility } = await import('../pipeline/compat');\n await verifyCompatibility(db, pkgs);\n }\n const { handleCompat } = await import('../mcp/handlers');\n const res = await handleCompat(db, { packages: pkgs });\n if (opts.json) return console.log(JSON.stringify(res, null, 2));\n const color = res.overall === 'compatible' ? green : res.overall === 'conflict' ? red : dim;\n console.log(`${bold(res.packages.join(' + '))} ${color(res.overall)}`);\n if (res.conflicts.length) {\n console.log(\n table(\n ['Source', 'Detail'],\n res.conflicts.map((c) => [c.source, c.detail]),\n ),\n );\n } else if (res.overall === 'compatible') {\n console.log(dim('no peer-dependency or engine conflicts across the set'));\n }\n if (res.unverified.length) {\n console.log(dim(`\\nunverified (no metadata): ${res.unverified.join(', ')}`));\n }\n });\n}\n","/**\n * Agent skill installer (§14). Registers lurq as an MCP server in supported\n * assistants by MERGING a single `lurq` entry into each agent's config — never\n * overwriting unrelated config — and drops the skill-instructions file.\n *\n * Two modes:\n * - **remote** (hosted, default for real users): writes a keyed HTTP entry\n * pointing at the lurq service. No DATABASE_URL ever touches a user's machine.\n * - **local** (self-host / contributors): writes the legacy stdio entry that\n * runs `lurq serve` locally against the user's own DB.\n *\n * MCP config formats move fast and differ per agent; this writes the current\n * widely-supported shapes and prints exactly what it did, so a stale path is\n * obvious rather than silent. Remote shapes verified against current agent docs\n * (2026-06): Claude Code / VS Code use `{ type:\"http\", url, headers }`; Cursor\n * uses `{ url, headers }`; Windsurf uses `{ serverUrl, headers }`; Codex (TOML)\n * uses `url` + an inline `http_headers` table.\n */\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { copyFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\nimport { DEFAULT_ENDPOINT, PACKAGE_NAME } from '../core/constants';\nimport { logger } from '../core/logger';\nimport { packageRoot } from '../core/paths';\n\nconst ENV_KEYS = [\n 'DATABASE_URL',\n 'GITHUB_TOKEN',\n 'EMBEDDING_PROVIDER',\n 'EMBEDDING_API_KEY',\n 'EMBEDDING_MODEL',\n 'SUMMARY_PROVIDER',\n 'SUMMARY_API_KEY',\n 'SUMMARY_MODEL',\n] as const;\n\nexport type ConfigFormat = 'mcpServers' | 'servers' | 'toml';\n\nexport interface AgentSpec {\n id: string;\n label: string;\n format: ConfigFormat;\n /** Absolute config file path. */\n path: string;\n /** Whether this agent appears installed (used by `--agent all` and the wizard). */\n detected: boolean;\n}\n\nfunction home(...p: string[]): string {\n return join(homedir(), ...p);\n}\n\nexport function agentSpecs(): AgentSpec[] {\n return [\n {\n id: 'claude-code',\n label: 'Claude Code',\n format: 'mcpServers',\n path: home('.claude.json'),\n detected: existsSync(home('.claude.json')) || existsSync(home('.claude')),\n },\n {\n id: 'cursor',\n label: 'Cursor',\n format: 'mcpServers',\n path: home('.cursor', 'mcp.json'),\n detected: existsSync(home('.cursor')),\n },\n {\n id: 'windsurf',\n label: 'Windsurf',\n format: 'mcpServers',\n path: home('.codeium', 'windsurf', 'mcp_config.json'),\n detected: existsSync(home('.codeium')),\n },\n {\n id: 'copilot',\n label: 'VS Code / GitHub Copilot',\n format: 'servers',\n path: home('Library', 'Application Support', 'Code', 'User', 'mcp.json'),\n detected: existsSync(home('Library', 'Application Support', 'Code', 'User')),\n },\n {\n id: 'codex',\n label: 'OpenAI Codex CLI',\n format: 'toml',\n path: home('.codex', 'config.toml'),\n detected: existsSync(home('.codex')),\n },\n ];\n}\n\nexport const SUPPORTED_AGENTS = ['claude-code', 'cursor', 'windsurf', 'copilot', 'codex'] as const;\n\n/** How to wire the lurq entry: hosted HTTP endpoint, or local stdio process. */\nexport type InstallMode =\n | { kind: 'remote'; url: string; apiKey: string }\n | { kind: 'local'; env: Record<string, string> };\n\nfunction collectEnv(): Record<string, string> {\n const env: Record<string, string> = {};\n for (const key of ENV_KEYS) {\n const value = process.env[key];\n if (value) env[key] = value;\n }\n return env;\n}\n\nexport interface InstallResult {\n agent: string;\n path: string;\n status: 'installed' | 'skipped' | 'error';\n message?: string;\n}\n\nfunction readJsonObject(path: string): Record<string, any> {\n if (!existsSync(path)) return {};\n const text = readFileSync(path, 'utf8').trim();\n if (!text) return {};\n return JSON.parse(text);\n}\n\nfunction writeJson(path: string, obj: unknown): void {\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, JSON.stringify(obj, null, 2) + '\\n', 'utf8');\n}\n\n/** Local (stdio) lurq server entry for JSON configs. */\nexport function buildServerEntry(env: Record<string, string>, withType: boolean): Record<string, any> {\n const entry: Record<string, any> = { command: 'npx', args: ['-y', PACKAGE_NAME, 'serve'] };\n if (withType) entry.type = 'stdio';\n if (Object.keys(env).length) entry.env = env;\n return entry;\n}\n\n/**\n * Remote (hosted) lurq server entry for JSON configs. Per-agent shape differs:\n * Claude Code & VS Code take `type:\"http\"`; Cursor & Windsurf infer transport\n * from the URL (Windsurf names the field `serverUrl`).\n */\nexport function buildRemoteServerEntry(\n agentId: string,\n opts: { url: string; apiKey: string },\n): Record<string, any> {\n const headers = { Authorization: `Bearer ${opts.apiKey}` };\n switch (agentId) {\n case 'cursor':\n return { url: opts.url, headers };\n case 'windsurf':\n return { serverUrl: opts.url, headers };\n case 'claude-code':\n case 'copilot':\n default:\n return { type: 'http', url: opts.url, headers };\n }\n}\n\n/** Local (stdio) TOML block for the Codex config. */\nexport function buildTomlBlock(env: Record<string, string>): string {\n const lines = ['[mcp_servers.lurq]', 'command = \"npx\"', `args = [\"-y\", \"${PACKAGE_NAME}\", \"serve\"]`];\n if (Object.keys(env).length) {\n lines.push('', '[mcp_servers.lurq.env]');\n for (const [k, v] of Object.entries(env)) lines.push(`${k} = ${JSON.stringify(v)}`);\n }\n return lines.join('\\n') + '\\n';\n}\n\n/**\n * Remote (hosted) TOML block for the Codex config. Codex parses with\n * `deny_unknown_fields`: literal headers go in an inline `http_headers` table,\n * NOT a `[mcp_servers.lurq.headers]` subtable (verified against the openai/codex\n * StreamableHttp config schema).\n */\nexport function buildRemoteTomlBlock(opts: { url: string; apiKey: string }): string {\n return (\n [\n '[mcp_servers.lurq]',\n `url = ${JSON.stringify(opts.url)}`,\n `http_headers = { Authorization = ${JSON.stringify(`Bearer ${opts.apiKey}`)} }`,\n ].join('\\n') + '\\n'\n );\n}\n\nfunction installJsonEntry(spec: AgentSpec, entry: Record<string, any>): InstallResult {\n const key = spec.format === 'servers' ? 'servers' : 'mcpServers';\n const config = readJsonObject(spec.path);\n if (typeof config[key] !== 'object' || config[key] === null) config[key] = {};\n config[key].lurq = entry;\n writeJson(spec.path, config);\n return { agent: spec.id, path: spec.path, status: 'installed' };\n}\n\nfunction installTomlBlock(spec: AgentSpec, block: string): InstallResult {\n const existing = existsSync(spec.path) ? readFileSync(spec.path, 'utf8') : '';\n if (existing.includes('[mcp_servers.lurq]')) {\n return {\n agent: spec.id,\n path: spec.path,\n status: 'skipped',\n message: 'lurq already present; edit manually to change it.',\n };\n }\n mkdirSync(dirname(spec.path), { recursive: true });\n const sep = existing && !existing.endsWith('\\n') ? '\\n\\n' : existing ? '\\n' : '';\n writeFileSync(spec.path, existing + sep + block, 'utf8');\n return { agent: spec.id, path: spec.path, status: 'installed' };\n}\n\n/** Apply the lurq entry to one agent's config, in the given mode. */\nexport function installAgent(spec: AgentSpec, mode: InstallMode): InstallResult {\n try {\n if (spec.format === 'toml') {\n const block =\n mode.kind === 'remote'\n ? buildRemoteTomlBlock(mode)\n : buildTomlBlock(mode.env);\n return installTomlBlock(spec, block);\n }\n const entry =\n mode.kind === 'remote'\n ? buildRemoteServerEntry(spec.id, mode)\n : buildServerEntry(mode.env, spec.format === 'servers');\n return installJsonEntry(spec, entry);\n } catch (err) {\n return {\n agent: spec.id,\n path: spec.path,\n status: 'error',\n message: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\n/** Copy the skill-instructions template to ~/.lurq. Returns the path, or null. */\nexport function installInstructionsFile(): string | null {\n const src = join(packageRoot(), 'templates', 'skill-instructions.md');\n if (!existsSync(src)) return null;\n const destDir = home('.lurq');\n const dest = join(destDir, 'skill-instructions.md');\n mkdirSync(destDir, { recursive: true });\n copyFileSync(src, dest);\n return dest;\n}\n\n/** Resolve `--agent <id|all>` to the set of agent specs to write. */\nexport function resolveAgents(target: string): AgentSpec[] {\n const specs = agentSpecs();\n if (target === 'all') return specs.filter((s) => s.detected);\n const spec = specs.find((s) => s.id === target);\n if (!spec) {\n throw new Error(`Unknown agent \"${target}\". Supported: ${SUPPORTED_AGENTS.join(', ')}, all.`);\n }\n return [spec];\n}\n\n/** Print the per-agent registration report + next steps. Shared by both paths. */\nexport function printInstallReport(\n results: InstallResult[],\n instructionsPath: string | null,\n mode: InstallMode,\n): void {\n const specs = agentSpecs();\n console.log('lurq MCP server registration:');\n for (const r of results) {\n const spec = specs.find((s) => s.id === r.agent)!;\n const mark = r.status === 'installed' ? '✓' : r.status === 'skipped' ? '•' : '✗';\n console.log(` ${mark} ${spec.label.padEnd(26)} ${r.path}${r.message ? ` (${r.message})` : ''}`);\n }\n if (instructionsPath) console.log(`\\nSkill instructions written to ${instructionsPath}`);\n console.log('\\nNext steps:');\n if (mode.kind === 'local') {\n console.log(' 1. Ensure DATABASE_URL (and any API keys) are set in the config env above.');\n console.log(' 2. Restart the agent so it picks up the new MCP server.');\n } else {\n console.log(' 1. Restart the agent so it picks up the new MCP server.');\n }\n console.log(' • Ask it to recommend a library — it should call lurq.');\n}\n\nexport interface InstallSkillOptions {\n agent?: string;\n /** Hosted endpoint URL (defaults to LURQ_ENDPOINT or the built-in default). */\n url?: string;\n /** API key for the hosted endpoint. Presence selects remote mode. */\n apiKey?: string;\n /** Force the legacy local/stdio entry (self-host). */\n local?: boolean;\n}\n\nexport async function runInstallSkill(opts: InstallSkillOptions): Promise<void> {\n const selected = resolveAgents(opts.agent ?? 'claude-code');\n if (selected.length === 0) {\n console.log('No supported agents detected on this machine.');\n return;\n }\n\n // Remote unless explicitly --local. Remote requires an API key.\n const remote = !opts.local;\n let mode: InstallMode;\n if (remote) {\n const apiKey = opts.apiKey ?? process.env.LURQ_API_KEY;\n if (!apiKey) {\n throw new Error(\n 'An API key is required for a hosted install. Pass --api-key <key> (or set LURQ_API_KEY), ' +\n 'or use `lurq install` for the guided setup, or --local to self-host.',\n );\n }\n const url = opts.url ?? process.env.LURQ_ENDPOINT ?? DEFAULT_ENDPOINT;\n mode = { kind: 'remote', url, apiKey };\n } else {\n const env = collectEnv();\n if (!env.DATABASE_URL) {\n logger.warn(\n 'DATABASE_URL is not set — the local server entry will have no DATABASE_URL. ' +\n 'Set it (in .env) and re-run, or edit the config.',\n );\n }\n mode = { kind: 'local', env };\n }\n\n const results = selected.map((spec) => installAgent(spec, mode));\n const instructionsPath = installInstructionsFile();\n printInstallReport(results, instructionsPath, mode);\n}\n","/**\n * Guided install wizard (`lurq install`, i.e. `npx lurqrun install`). Walks a user\n * through connecting lurq's hosted MCP service to their AI assistant(s): collects\n * the API key, optionally validates it against the endpoint, detects installed\n * agents, and writes the keyed remote config — no DATABASE_URL ever on their\n * machine. Fully non-interactive with `--yes` + flags/env for scripting.\n */\nimport { DEFAULT_ENDPOINT } from '../core/constants';\nimport {\n agentSpecs,\n installAgent,\n installInstructionsFile,\n printInstallReport,\n resolveAgents,\n type AgentSpec,\n type InstallMode,\n} from './installSkill';\n\nexport interface WizardOptions {\n apiKey?: string;\n url?: string;\n agent?: string;\n yes?: boolean;\n}\n\n/** Where users obtain a key (operator-issued for now; self-serve dashboard later). */\nconst GET_KEY_URL = 'https://lurq.run';\n\n/**\n * Lightweight MCP `tools/list` ping to confirm the key authenticates.\n * Distinguishes a rejected key (401/403) from an unreachable endpoint so the\n * wizard can tell the user which one happened instead of blaming the key on a\n * flaky network.\n */\ntype KeyCheck = 'valid' | 'invalid' | 'unreachable';\n\nasync function validateKey(url: string, apiKey: string): Promise<KeyCheck> {\n try {\n const res = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'application/json, text/event-stream',\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'tools/list' }),\n });\n if (res.ok) return 'valid';\n if (res.status === 401 || res.status === 403) return 'invalid';\n return 'unreachable';\n } catch {\n return 'unreachable';\n }\n}\n\nexport async function runInstallWizard(opts: WizardOptions): Promise<void> {\n const interactive = !opts.yes;\n const url = opts.url ?? process.env.LURQ_ENDPOINT ?? DEFAULT_ENDPOINT;\n let apiKey = (opts.apiKey ?? process.env.LURQ_API_KEY)?.trim();\n\n if (interactive) {\n const { input, checkbox, confirm, select } = await import('@inquirer/prompts');\n\n console.log('\\n lurq — connect your coding agent to the hosted package index.\\n');\n\n if (!apiKey) {\n console.log(` Need a key? Get one at ${GET_KEY_URL}\\n`);\n apiKey = (\n await input({\n message: 'Paste your lurq API key',\n validate: (v) =>\n v.trim().startsWith('lurq_') ? true : 'Keys look like lurq_live_… ',\n })\n ).trim();\n }\n\n process.stdout.write(' Validating key… ');\n const check = await validateKey(url, apiKey);\n console.log(\n check === 'valid' ? 'ok' : check === 'invalid' ? 'rejected' : 'could not reach endpoint',\n );\n if (check !== 'valid') {\n const proceed = await confirm({\n message:\n check === 'invalid'\n ? `That key was rejected (401) by ${url}. Continue anyway?`\n : `Couldn't reach ${url} to validate the key. Continue anyway?`,\n default: false,\n });\n if (!proceed) {\n console.log('Aborted. No config was changed.');\n return;\n }\n }\n\n if (opts.agent) {\n await finish(resolveAgents(opts.agent), { url, apiKey });\n return;\n }\n\n const specs = agentSpecs();\n // Natural-language quick path: if we spot likely agents, offer a one-tap\n // connect before falling back to the full multi-select. Mirrors the simplified\n // \"connect to Claude Code? (y/n/other)\" flow in docs/lurq-demo.md. \"Yes\" wires\n // up EVERY detected agent (the prior multi-select pre-checked them all), so a\n // user with two editors doesn't silently leave one unconnected.\n const detected = specs.filter((s) => s.detected);\n const primary = detected.find((s) => s.id === 'claude-code') ?? detected[0];\n if (primary) {\n const others = detected.length - 1;\n const choice = await select({\n message:\n others > 0\n ? `Looks like you have ${detected.map((s) => s.label).join(', ')}. Connect lurq to them?`\n : `Looks like you have ${primary.label}. Connect lurq to it?`,\n default: 'yes',\n choices: [\n {\n name: others > 0 ? `Yes — set up all ${detected.length} detected agents` : `Yes — set up ${primary.label} for me`,\n value: 'yes',\n },\n { name: 'No — let me choose which agent(s)', value: 'other' },\n { name: 'Cancel — change nothing', value: 'cancel' },\n ],\n });\n if (choice === 'cancel') {\n console.log('No problem — nothing was changed. Run `lurq install` again anytime.');\n return;\n }\n if (choice === 'yes') {\n await finish(detected, { url, apiKey });\n return;\n }\n // 'other' falls through to the full multi-select below.\n }\n\n const ids = await checkbox({\n message: 'Which assistant(s) should I configure?',\n choices: specs.map((s) => ({\n name: `${s.label}${s.detected ? ' (detected)' : ''}`,\n value: s.id,\n checked: s.detected,\n })),\n });\n await finish(specs.filter((s) => ids.includes(s.id)), { url, apiKey });\n return;\n }\n\n // Non-interactive (--yes): require a key, use flags/env + detected agents.\n if (!apiKey) {\n throw new Error(\n 'No API key. Pass --api-key <key> or set LURQ_API_KEY (or drop --yes to be prompted).',\n );\n }\n const selected = opts.agent\n ? resolveAgents(opts.agent)\n : agentSpecs().filter((s) => s.detected);\n await finish(selected, { url, apiKey });\n}\n\nasync function finish(\n selected: AgentSpec[],\n remote: { url: string; apiKey: string },\n): Promise<void> {\n if (selected.length === 0) {\n console.log(\n '\\nNo agents selected or detected. Re-run with --agent <id>, or install an assistant first.',\n );\n return;\n }\n const mode: InstallMode = { kind: 'remote', ...remote };\n const results = selected.map((s) => installAgent(s, mode));\n const instructionsPath = installInstructionsFile();\n console.log('');\n printInstallReport(results, instructionsPath, mode);\n}\n","/**\n * Operator-only API-key management for the hosted service (`lurq keys …`).\n * Requires DATABASE_URL — these commands run where the central DB lives, never on\n * a user's machine. New keys are printed in plaintext exactly once; only hashes\n * are stored, and list/JSON output never includes the hash.\n */\nimport { requireConfig } from '../core/config';\nimport { logger } from '../core/logger';\nimport { createKey, listKeys, revokeKey, rotateKey } from '../auth/apiKeys';\nimport type { ApiKeyRow } from '../db/schema';\nimport { createDb } from '../db/client';\nimport { bold, dim, green, table } from './format';\n\nconst isoDay = (d: Date | null) => (d ? d.toISOString().slice(0, 10) : '—');\n\n/** Block until the operator presses Enter (resolves immediately if not a TTY). */\nfunction waitForEnter(prompt: string): Promise<void> {\n return new Promise((resolve) => {\n process.stdout.write(prompt);\n process.stdin.resume();\n process.stdin.once('data', () => {\n process.stdin.pause();\n resolve();\n });\n });\n}\n\n/**\n * Present a freshly-issued plaintext key exactly once. In JSON mode it prints a\n * single line (plus any `extraJson`) for scripts. Interactively it shows the key,\n * waits for the operator to copy it, then wipes it from the terminal (screen +\n * scroll-back). Shared by `keys create` and `keys rotate`.\n */\nasync function presentNewKey(\n key: string,\n row: ApiKeyRow,\n opts: { json?: boolean; header?: string; extraJson?: Record<string, unknown> },\n): Promise<void> {\n if (opts.json) {\n console.log(\n JSON.stringify({ key, prefix: row.prefix, tier: row.tier, label: row.label, ...opts.extraJson }),\n );\n return;\n }\n\n const meta = `prefix=${row.prefix} tier=${row.tier}${row.label ? ` label=${row.label}` : ''}`;\n const block = [bold(opts.header ?? 'API key created.'), '', ` ${green(key)}`, '', dim(meta)];\n\n console.log(block.join('\\n'));\n\n if (process.stdout.isTTY && process.stdin.isTTY) {\n // Show the key, then wipe it from the terminal (screen + scrollback) once\n // the operator confirms they've copied it — so it doesn't linger on screen\n // or in scroll-back history.\n await waitForEnter(dim('Copy it now, then press Enter to erase it from the terminal… '));\n // Move to the top of the printed block (block lines + the prompt line the\n // Enter advanced past), clear to end of screen, and clear scroll-back.\n process.stdout.write(`\\x1b[${block.length + 1}F\\x1b[0J\\x1b[3J`);\n console.log(\n dim(`New key (prefix ${row.prefix}) erased from the terminal. ` +\n `It is stored only as a hash and cannot be recovered, so make sure you saved it.`),\n );\n } else {\n // Non-TTY (piped, or over a non-interactive SSH exec): can't erase, so just\n // warn. Operator is responsible for clearing their buffer.\n console.log(dim('Store it now — shown only once, stored hashed, cannot be recovered.'));\n }\n}\n\nexport async function runKeysCreate(opts: {\n label?: string;\n tier?: string;\n owner?: string;\n json?: boolean;\n}): Promise<void> {\n requireConfig(['DATABASE_URL']);\n const { db, close } = createDb({ max: 1 });\n try {\n const { key, row } = await createKey(db, {\n label: opts.label,\n tier: opts.tier,\n ownerId: opts.owner,\n });\n await presentNewKey(key, row, opts);\n } finally {\n await close();\n }\n}\n\nexport async function runKeysRotate(\n prefixOrId: string,\n opts: { json?: boolean },\n): Promise<void> {\n requireConfig(['DATABASE_URL']);\n const { db, close } = createDb({ max: 1 });\n try {\n const result = await rotateKey(db, prefixOrId);\n if (!result) {\n logger.warn(`No active key matched \"${prefixOrId}\".`);\n process.exitCode = 1;\n return;\n }\n await presentNewKey(result.key, result.row, {\n json: opts.json,\n header: `API key rotated — replaces ${result.previous.prefix} (now revoked).`,\n extraJson: { replaced: result.previous.prefix },\n });\n } finally {\n await close();\n }\n}\n\nexport async function runKeysList(opts: { json?: boolean }): Promise<void> {\n requireConfig(['DATABASE_URL']);\n const { db, close } = createDb({ max: 1 });\n try {\n const rows = await listKeys(db);\n if (opts.json) {\n // Deliberately omit keyHash from machine output.\n console.log(\n JSON.stringify(\n rows.map((r) => ({\n id: r.id,\n prefix: r.prefix,\n label: r.label,\n tier: r.tier,\n ownerId: r.ownerId,\n createdAt: r.createdAt,\n lastUsedAt: r.lastUsedAt,\n revokedAt: r.revokedAt,\n })),\n null,\n 2,\n ),\n );\n return;\n }\n if (rows.length === 0) {\n console.log('No API keys yet. Create one with `lurq keys create --label <name>`.');\n return;\n }\n console.log(\n table(\n ['prefix', 'label', 'tier', 'created', 'last used', 'status'],\n rows.map((r) => [\n r.prefix,\n r.label ?? '—',\n r.tier,\n isoDay(r.createdAt),\n isoDay(r.lastUsedAt),\n r.revokedAt ? 'revoked' : 'active',\n ]),\n ),\n );\n } finally {\n await close();\n }\n}\n\nexport async function runKeysRevoke(prefixOrId: string): Promise<void> {\n requireConfig(['DATABASE_URL']);\n const { db, close } = createDb({ max: 1 });\n try {\n const n = await revokeKey(db, prefixOrId);\n if (n === 0) {\n logger.warn(`No active key matched \"${prefixOrId}\".`);\n process.exitCode = 1;\n return;\n }\n console.log(`Revoked ${n} key(s) matching \"${prefixOrId}\".`);\n } finally {\n await close();\n }\n}\n","/**\n * Load the curated seed list (§16) into `seed_packages`. Idempotent: re-running\n * upserts category and leaves `added_at` intact for existing rows.\n */\nimport { readFileSync } from 'node:fs';\nimport { sql } from 'drizzle-orm';\nimport { z } from 'zod';\nimport { CATEGORIES, type Category } from '../core/types';\nimport { logger } from '../core/logger';\nimport { seedJsonPath } from '../core/paths';\nimport type { Database } from './client';\nimport { seedPackages } from './schema';\n\nconst SeedEntrySchema = z.object({\n name: z.string().min(1),\n category: z.enum(CATEGORIES as unknown as [Category, ...Category[]]).optional(),\n});\nconst SeedFileSchema = z.array(SeedEntrySchema);\n\nexport interface SeedEntry {\n name: string;\n category?: Category;\n}\n\nexport function loadSeedFile(path = seedJsonPath()): SeedEntry[] {\n const raw = JSON.parse(readFileSync(path, 'utf8'));\n const parsed = SeedFileSchema.parse(raw);\n // De-duplicate by name (first occurrence wins) so a package can't be seeded twice.\n const byName = new Map<string, SeedEntry>();\n for (const entry of parsed) {\n if (!byName.has(entry.name)) byName.set(entry.name, entry);\n }\n return [...byName.values()];\n}\n\nexport async function loadSeedPackages(db: Database, path?: string): Promise<number> {\n const entries = loadSeedFile(path);\n if (entries.length === 0) return 0;\n await db\n .insert(seedPackages)\n .values(entries.map((e) => ({ name: e.name, category: e.category ?? null })))\n .onConflictDoUpdate({\n target: seedPackages.name,\n // Refresh category to the incoming value on conflict (EXCLUDED.category).\n set: { category: sql`excluded.category` },\n });\n logger.info(`Loaded ${entries.length} packages into seed_packages.`);\n return entries.length;\n}\n","/**\n * Schema management for `lurq db migrate` / `lurq db reset`.\n *\n * `migrate` ensures the pgvector extension exists (Drizzle does not create it),\n * applies generated migrations, then loads the curated seed list (§18 M1).\n * `reset` drops the public schema and re-runs migrate — destructive.\n */\nimport { migrate } from 'drizzle-orm/postgres-js/migrator';\nimport { logger } from '../core/logger';\nimport { migrationsDir } from '../core/paths';\nimport { createDb, type DbHandle } from './client';\nimport { loadSeedPackages } from './seed';\n\nasync function ensureVectorExtension(handle: DbHandle): Promise<void> {\n // Non-fatal: if the extension already exists (it must, once migration 0000's\n // `vector` column is in place) this is a no-op, and a transient hiccup here\n // must NOT abort the migrator and leave later migrations (0001+) unapplied.\n try {\n await handle.sql`CREATE EXTENSION IF NOT EXISTS vector`;\n } catch (err) {\n logger.warn(\n `CREATE EXTENSION vector did not run cleanly (continuing to migrations): ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n}\n\nexport async function runMigrate(): Promise<void> {\n // A single, non-pooled connection is best for migrations.\n const handle = createDb({ max: 1 });\n try {\n logger.info('Ensuring pgvector extension…');\n await ensureVectorExtension(handle);\n\n logger.info('Applying migrations…');\n await migrate(handle.db, { migrationsFolder: migrationsDir() });\n\n logger.info('Loading seed list…');\n await loadSeedPackages(handle.db);\n\n logger.info('Migration complete.');\n } finally {\n await handle.close();\n }\n}\n\nexport async function runReset(): Promise<void> {\n const handle = createDb({ max: 1 });\n try {\n logger.warn('Dropping schema `public` (destructive)…');\n await handle.sql.unsafe('DROP SCHEMA IF EXISTS public CASCADE; CREATE SCHEMA public;');\n // Drizzle tracks applied migrations in its own schema; clear it too.\n await handle.sql`DROP SCHEMA IF EXISTS drizzle CASCADE`;\n } finally {\n await handle.close();\n }\n // Re-apply everything from scratch.\n await runMigrate();\n logger.info('Reset complete.');\n}\n","#!/usr/bin/env node\n/**\n * lurq CLI entry point. Runnable via `npx lurq <command>` (§7, §13).\n */\nimport { readFileSync } from 'node:fs';\nimport updateNotifier from 'update-notifier';\nimport { buildProgram } from '../cli/index';\nimport { loadEnv } from '../core/config';\nimport { enforceGate } from '../core/gate';\nimport { logger } from '../core/logger';\n\nloadEnv();\n\n// Private-preview gate: non-owners get a placeholder, the owner runs as usual.\n// Runs after loadEnv so LURQ_OWNER_KEY from a .env file is honored too.\nenforceGate(process.argv.slice(2));\n\nnotifyOnUpdate();\n\nbuildProgram()\n .parseAsync(process.argv)\n .catch((err) => {\n logger.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n });\n\n/**\n * Check npm (at most once a day, in a detached background process) and print a\n * one-line \"update available\" banner on exit when a newer lurqrun is published.\n * Skipped in agent/machine contexts — MCP stdio servers and `--json` output —\n * so the protocol/output stream is never touched. update-notifier additionally\n * only prints in a TTY, so piped runs stay silent regardless. Any failure here\n * must never break the CLI, hence the broad guard.\n */\nfunction notifyOnUpdate(): void {\n const argv = process.argv.slice(2);\n const quiet =\n argv[0] === 'serve' || argv[0] === 'serve-http' || argv.includes('--json');\n if (quiet) return;\n\n try {\n const pkg = JSON.parse(\n readFileSync(new URL('../../package.json', import.meta.url), 'utf8'),\n ) as { name: string; version: string };\n updateNotifier({ pkg }).notify();\n } catch {\n // Offline, no config dir, malformed metadata — never fatal for the CLI.\n }\n}\n","/**\n * CLI command wiring (§13). Built with commander. Each command mirrors an MCP\n * tool or an operational task. Handlers are filled in across milestones M1–M7;\n * the command/option surface here is the final, stable shape.\n *\n * Every command supports `--json` for machine-readable output.\n */\nimport { Command } from 'commander';\nimport { SERVER_NAME, VERSION } from '../core/constants';\n\nexport function buildProgram(): Command {\n const program = new Command();\n\n program\n .name(SERVER_NAME)\n .description(\n 'lurq - a fresh, objectively-scored index of JS/TS packages for AI coding agents.',\n )\n .version(VERSION, '-v, --version', 'output the lurq version');\n\n program\n .command('serve')\n .description('start the MCP server over stdio (for agent integration)')\n .action(async () => {\n const { startMcpServer } = await import('../mcp/server');\n await startMcpServer();\n });\n\n program\n .command('serve-http')\n .description('start the hosted MCP server over HTTP with API-key auth')\n .option('--port <n>', 'port to listen on (default: $PORT or 8080)', (v) => parseInt(v, 10))\n .action(async (opts: { port?: number }) => {\n const { startHttpServer } = await import('../mcp/http');\n await startHttpServer({ port: opts.port });\n });\n\n program\n .command('sync')\n .description('run ingestion: refresh scores for the seed list (or one package)')\n .option('--full', 'force a full re-sync, ignoring cache TTLs')\n .option('--package <name>', 'sync a single package by name')\n .option('--json', 'output the run summary as JSON')\n .action(async (opts: { full?: boolean; package?: string; json?: boolean }) => {\n const { runSync } = await import('../pipeline/index');\n const summary = await runSync({ full: opts.full, packageName: opts.package });\n if (opts.json) console.log(JSON.stringify(summary, null, 2));\n if (summary.status === 'failed') process.exitCode = 1;\n });\n\n program\n .command('recommend')\n .argument('<need>', 'natural-language description of what you need')\n .description('recommend the best current packages for a described need')\n .option('--category <category>', 'restrict to a taxonomy category')\n .option('--min-confidence <level>', 'proven | emerging | promising | unproven')\n .option('--json', 'output JSON instead of a table')\n .action(async (need: string, opts: { category?: string; minConfidence?: string; json?: boolean }) => {\n const { runRecommend } = await import('./commands');\n await runRecommend(need, opts);\n });\n\n program\n .command('evaluate')\n .argument('<package>', 'npm package name')\n .description('full evidence read for one package (scores, signals, usage guide)')\n .option('--json', 'output JSON instead of a table')\n .action(async (pkg: string, opts: { json?: boolean }) => {\n const { runEvaluate } = await import('./commands');\n await runEvaluate(pkg, opts);\n });\n\n program\n .command('compare')\n .argument('<packages...>', '2–5 npm package names')\n .description('side-by-side comparison of packages, ranked by health')\n .option('--json', 'output JSON instead of a table')\n .action(async (pkgs: string[], opts: { json?: boolean }) => {\n const { runCompare } = await import('./commands');\n await runCompare(pkgs, opts);\n });\n\n program\n .command('verify')\n .argument('<package>', 'npm package name')\n .description('safety check: is this package real, healthy, and not risky?')\n .option('--json', 'output JSON instead of a table')\n .action(async (pkg: string, opts: { json?: boolean }) => {\n const { runVerify } = await import('./commands');\n await runVerify(pkg, opts);\n });\n\n program\n .command('versions')\n .argument('<package>', 'npm package name')\n .description('show the stored version timeline for a package')\n .option('--json', 'output JSON instead of a table')\n .option('-n, --limit <n>', 'how many versions to show (default 30)')\n .action(async (pkg: string, opts: { json?: boolean; limit?: string }) => {\n const { runVersions } = await import('./commands');\n await runVersions(pkg, opts);\n });\n\n program\n .command('plan')\n .argument('<file>', 'path to a markdown file describing your program')\n .description('turn a program description into an evidence-scored package plan + roadmap')\n .option('--optimize <mode>', \"ranking bias: 'speed' (lightest bundle) or 'balanced'\")\n .option('--html <path>', 'write the roadmap as a self-contained HTML visualization')\n .option('--open', 'render the roadmap to HTML and open it in your browser')\n .option('--json', 'output the full plan as JSON')\n .action(async (file: string, opts: { optimize?: string; json?: boolean; html?: string; open?: boolean }) => {\n const { runPlan } = await import('./commands');\n await runPlan(file, opts);\n });\n\n program\n .command('weights')\n .description('show and explain the scoring weight model (health, quality, composite λ)')\n .option('--json', 'output the weight model as JSON')\n .action(async (opts: { json?: boolean }) => {\n const { runWeights } = await import('./commands');\n runWeights(opts);\n });\n\n program\n .command('edit-weights')\n .description('override, reset, or explain the scoring weights (layered over defaults)')\n .option('--set <pair>', 'override key=value, e.g. composite.lambda=0.5 (repeatable)', (v: string, acc: string[]) => acc.concat(v), [])\n .option('--reset', 'remove all overrides and restore defaults')\n .option('--explain <component>', 'explain a component (e.g. adoption, quality, lambda)')\n .option('--project', 'write to project-local .lurq/weights.json instead of the user config')\n .action(async (opts: { set?: string[]; reset?: boolean; explain?: string; project?: boolean }) => {\n const { runEditWeights } = await import('./commands');\n await runEditWeights(opts);\n });\n\n program\n .command('discover')\n .description('operator-side: proactively crawl for new packages and queue/gate them (§2B)')\n .option('--cap <n>', 'max candidates to fully ingest this run', (v) => parseInt(v, 10))\n .option('--dry-run', 'discover, queue, and gate, but do not ingest survivors')\n .option('--json', 'output the discovery summary as JSON')\n .action(async (opts: { cap?: number; dryRun?: boolean; json?: boolean }) => {\n const { requireConfig } = await import('../core/config');\n requireConfig(['DATABASE_URL']);\n const { runDiscovery } = await import('../pipeline/index');\n const summary = await runDiscovery({ perRunCap: opts.cap, dryRun: opts.dryRun });\n if (opts.json) console.log(JSON.stringify(summary, null, 2));\n });\n\n program\n .command('rescore')\n .description('re-derive health scores from cached breakdowns using current weights (no re-ingest)')\n .option('--json', 'output the rescore summary as JSON')\n .action(async (opts: { json?: boolean }) => {\n const { requireConfig } = await import('../core/config');\n requireConfig(['DATABASE_URL']);\n const { runRescore } = await import('../pipeline/index');\n const summary = await runRescore();\n if (opts.json) console.log(JSON.stringify(summary, null, 2));\n });\n\n program\n .command('watch')\n .description(\n 'operator-side: follow the npm changes feed, re-syncing tracked packages on new releases',\n )\n .action(async () => {\n const { runWatch } = await import('./commands');\n await runWatch();\n });\n\n program\n .command('sandbox')\n .argument('<package>', 'npm package name')\n .argument('[version]', 'specific version (default: latest)')\n .description(\n 'operator-side: install + smoke-load a package in a sandbox to verify it actually works',\n )\n .option('--esm', 'load via ESM import instead of CJS require')\n .option('--allow-scripts', 'run install scripts (UNSAFE without VM isolation)')\n .option('--json', 'output JSON')\n .action(\n async (\n pkg: string,\n version: string | undefined,\n opts: { esm?: boolean; allowScripts?: boolean; json?: boolean },\n ) => {\n const { runSandbox } = await import('./commands');\n await runSandbox(pkg, version, opts);\n },\n );\n\n program\n .command('compat')\n .argument('<packages...>', 'npm package names to check together')\n .description('check pairwise compatibility of packages from the sandbox matrix')\n .option('--run', 'operator-side: co-install them in the sandbox first (UNSAFE without VM isolation)')\n .option('--json', 'output JSON')\n .action(async (pkgs: string[], opts: { run?: boolean; json?: boolean }) => {\n const { runCompat } = await import('./commands');\n await runCompat(pkgs, opts);\n });\n\n program\n .command('install')\n .description('guided setup: connect lurq to your AI assistant(s)')\n .option('--api-key <key>', 'hosted API key (skips the prompt)')\n .option('--url <url>', 'hosted endpoint URL (defaults to the lurq service)')\n .option('--agent <agent>', 'claude-code | cursor | copilot | windsurf | codex | all')\n .option('--yes', 'non-interactive: use flags/env and detected agents without prompting')\n .action(async (opts: { apiKey?: string; url?: string; agent?: string; yes?: boolean }) => {\n const { runInstallWizard } = await import('./install');\n await runInstallWizard(opts);\n });\n\n program\n .command('install-skill')\n .description('register lurq as an MCP server in supported AI assistants (scriptable)')\n .option(\n '--agent <agent>',\n 'claude-code | cursor | copilot | windsurf | codex | all',\n 'claude-code',\n )\n .option('--api-key <key>', 'hosted API key (remote install; default mode)')\n .option('--url <url>', 'hosted endpoint URL (defaults to the lurq service)')\n .option('--local', 'self-host: write a local stdio entry using your own DATABASE_URL')\n .action(async (opts: { agent?: string; apiKey?: string; url?: string; local?: boolean }) => {\n const { runInstallSkill } = await import('./installSkill');\n await runInstallSkill(opts);\n });\n\n const keys = program\n .command('keys')\n .description('manage API keys for the hosted service (operator; needs DATABASE_URL)');\n keys\n .command('create')\n .description('create a new API key (shown once; erased from the terminal after you copy it)')\n .option('--label <label>', 'human label (owner / org / purpose)')\n .option('--tier <tier>', 'tier name', 'free')\n .option('--owner <id>', 'org/owner id to attribute this key to (e.g. a Clerk org id)')\n .option('--json', 'print the key as JSON and skip the interactive erase (for scripts)')\n .action(async (opts: { label?: string; tier?: string; owner?: string; json?: boolean }) => {\n const { runKeysCreate } = await import('./keys');\n await runKeysCreate(opts);\n });\n keys\n .command('list')\n .description('list issued API keys (hashes are never shown)')\n .option('--json', 'output as JSON')\n .action(async (opts: { json?: boolean }) => {\n const { runKeysList } = await import('./keys');\n await runKeysList(opts);\n });\n keys\n .command('rotate')\n .argument('<prefixOrId>', 'key prefix (e.g. lurq_live_ab12cd) or numeric id to replace')\n .description('issue a replacement key (same label/tier) and revoke the old one')\n .option('--json', 'print the new key as JSON and skip the interactive erase (for scripts)')\n .action(async (prefixOrId: string, opts: { json?: boolean }) => {\n const { runKeysRotate } = await import('./keys');\n await runKeysRotate(prefixOrId, opts);\n });\n keys\n .command('revoke')\n .argument('<prefixOrId>', 'key prefix (e.g. lurq_live_ab12cd) or numeric id')\n .description('revoke an API key')\n .action(async (prefixOrId: string) => {\n const { runKeysRevoke } = await import('./keys');\n await runKeysRevoke(prefixOrId);\n });\n\n const db = program.command('db').description('database management');\n db.command('migrate')\n .description('apply database migrations and load the seed list')\n .action(async () => {\n const { runMigrate } = await import('../db/migrate');\n await runMigrate();\n });\n db.command('reset')\n .description('drop and recreate the schema (destructive)')\n .option('--yes', 'skip the confirmation prompt')\n .action(async (opts: { yes?: boolean }) => {\n if (!opts.yes) {\n console.error(\n 'Refusing to reset without confirmation. Re-run with `--yes` to drop and recreate the schema.',\n );\n process.exitCode = 1;\n return;\n }\n const { runReset } = await import('../db/migrate');\n await runReset();\n });\n\n return program;\n}\n","/**\n * Pre-launch access gate.\n *\n * While lurq is in private preview, anyone may `npm install lurqrun`, but only\n * the owner may run commands — everyone else gets a branded placeholder. The\n * owner proves identity by exporting `LURQ_OWNER_KEY` in their shell to the\n * secret whose SHA-256 is baked into `OWNER_HASH` below. The published bundle\n * carries only the hash, never the secret, so inspecting the source reveals\n * nothing usable.\n *\n * To lift the gate at public launch, flip `PRE_LAUNCH` to false (or delete the\n * `enforceGate()` call in bin/lurq.ts). The owner bypass keeps working either\n * way, so nothing else needs to change.\n */\nimport { createHash, timingSafeEqual } from 'node:crypto';\n\nimport { PACKAGE_NAME } from './constants';\n\n/** Master switch. Set to false to open lurq to everyone at launch. */\nconst PRE_LAUNCH = false;\n\n/**\n * SHA-256 of the owner secret. Regenerate after choosing a new secret with:\n * node -e \"console.log(require('node:crypto').createHash('sha256').update(process.argv[1]).digest('hex'))\" <secret>\n * and paste the result here. Keep the plaintext only in your shell env.\n */\nconst OWNER_HASH = '9675c37e56783e747e4a89ee3919d95d1364f2e5dd0f14501b0f878f8cc3682b';\n\n/**\n * Top-level commands that bypass the gate even for non-owners:\n * - `-v/--version/-h/--help/help` — harmless, expected by npm users.\n * - `serve`/`serve-http` — the MCP transports. The gate must NEVER write to the\n * stdio JSON-RPC channel (`serve`), and the hosted server must boot without\n * depending on the owner key (`serve-http`).\n * - `sync`/`discover`/`rescore`/`db`/`keys` — operator/infra commands that all\n * require DATABASE_URL, which a public installer never has. Gating them adds no\n * protection (a keyless user can't run them anyway) while risking the owner's\n * own deploy. The gate's real job is the user-facing commands (recommend,\n * evaluate, compare, verify, plan, install, install-skill, weights).\n */\nconst ALLOWED = new Set([\n '-v', '--version', '-h', '--help', 'help',\n 'serve', 'serve-http',\n 'sync', 'discover', 'rescore', 'db', 'keys',\n]);\n\n/** True when the caller has proven they are the owner via `LURQ_OWNER_KEY`. */\nexport function isOwner(): boolean {\n const key = process.env.LURQ_OWNER_KEY;\n if (!key) return false;\n const got = createHash('sha256').update(key).digest();\n const want = Buffer.from(OWNER_HASH, 'hex');\n // Equal-length buffers (both 32 bytes); timingSafeEqual guards against a\n // timing oracle on the comparison.\n return got.length === want.length && timingSafeEqual(got, want);\n}\n\n/**\n * Enforce the gate before any command runs. Returns normally when the caller is\n * the owner, the gate is lifted, or the invocation is a top-level help/version\n * query. Otherwise prints the placeholder and exits cleanly (code 0 — installing\n * early is not an error).\n */\nexport function enforceGate(argv: string[]): void {\n if (!PRE_LAUNCH || isOwner()) return;\n if (argv[0] && ALLOWED.has(argv[0])) return;\n\n printPlaceholder();\n process.exit(0);\n}\n\nfunction printPlaceholder(): void {\n const tty = process.stdout.isTTY;\n const bold = (s: string) => (tty ? `\\x1b[1m${s}\\x1b[0m` : s);\n const dim = (s: string) => (tty ? `\\x1b[2m${s}\\x1b[0m` : s);\n const accent = (s: string) => (tty ? `\\x1b[38;5;213m${s}\\x1b[0m` : s);\n\n process.stdout.write(\n [\n '',\n ` ${bold('lurq')} ${dim('— evidence-scored package index for AI coding agents')}`,\n '',\n ` ${accent('◆ private preview')}`,\n '',\n ` lurq isn't open to the public yet — thanks for installing early.`,\n ` Join the waitlist and watch the demo at ${bold('https://lurq.run')}`,\n '',\n dim(` You'll be able to connect Claude Code, Cursor, and other agents`),\n dim(` the moment we open the gate.`),\n '',\n dim(` (${PACKAGE_NAME} is installed and ready — no further action needed.)`),\n '',\n '',\n ].join('\\n'),\n );\n}\n"],"mappings":"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","names":["table","sql","cached","cached","attempt","text","json","HOST","json","HOST","json","HOST","json","HOST","json","HOST","packages","and","desc","eq","init_successors","HOST","text","text","existsSync","homedir","dirname","join","fileURLToPath","existsSync","dirname","active","eq","path","createHash","text","str","dim","index","and","eq","isNotNull","sql","median","and","eq","isNotNull","sql","createHash","sql","DAY_MS","cached","typo","init_successors","inArray","text","createHash","inArray","z","createHash","and","desc","eq","cached","createHash","init_http","isNotNull","eq","eq","isNotNull","pending","init_discovery","init_discovery","eq","backoff","init_watch","init_types","writeFile","join","init_types","packages","condense","ERROR_MAX","INSTALL_TIMEOUT_MS","SMOKE_TIMEOUT_MS","toSpec","init_types","packages","E2BSandbox","init_types","init_sandbox","packages","init_compat","active","invalidateCache","text","path","readFileSync","handlePlan","writeFileSync","tmpdir","join","renderPlanHtml","watchNpmChanges","verifyPackageInSandbox","verifyCompatibility","handleCompat","existsSync","mkdirSync","readFileSync","writeFileSync","homedir","dirname","join","path","text","readFileSync","sql","z","path","readFileSync","startMcpServer","startHttpServer","runSync","runRecommend","runEvaluate","runCompare","runVerify","runVersions","runPlan","runWeights","runEditWeights","requireConfig","runDiscovery","runRescore","runWatch","runSandbox","runCompat","runInstallWizard","runInstallSkill","runKeysCreate","runKeysList","runKeysRotate","runKeysRevoke","runMigrate","runReset","createHash","timingSafeEqual","bold","dim","readFileSync"]}
|
|
1
|
+
{"version":3,"sources":["../../node_modules/tsup/assets/esm_shims.js","../../src/core/constants.ts","../../src/core/logger.ts","../../src/core/paths.ts","../../src/cli/installSkill.ts","../../src/core/types.ts","../../src/core/config.ts","../../src/db/schema.ts","../../src/db/client.ts","../../src/core/cache.ts","../../src/graph/types.ts","../../src/db/graph.ts","../../src/db/surface.ts","../../src/surface/types.ts","../../src/surface/diff.ts","../../src/mcp/surfaceHandlers.ts","../../src/db/compat.ts","../../src/core/http.ts","../../src/ingestion/sources/npmRegistry.ts","../../src/ingestion/sources/npmSearch.ts","../../src/ingestion/sources/npmDownloads.ts","../../src/ingestion/sources/github.ts","../../src/ingestion/sources/depsDev.ts","../../src/ingestion/sources/bundlephobia.ts","../../src/ingestion/sources/index.ts","../../src/compat/members.ts","../../src/compat/peerCompat.ts","../../src/compat/check.ts","../../src/db/packages.ts","../../src/usage/diff.ts","../../src/db/apiSurfaces.ts","../../src/usage/extract.ts","../../src/usage/service.ts","../../src/db/verification.ts","../../src/db/outcomes.ts","../../src/data/successors.json","../../src/core/successors.ts","../../src/ingestion/sources/githubReadme.ts","../../src/ingestion/summarize.ts","../../src/ingestion/collect.ts","../../src/search/categoryInference.ts","../../src/scoring/weights.ts","../../src/scoring/score.ts","../../src/scoring/index.ts","../../src/search/embeddings.ts","../../src/core/concurrency.ts","../../src/core/errors.ts","../../src/pipeline/mineEdges.ts","../../src/pipeline/sync.ts","../../src/pipeline/ingestQueue.ts","../../src/pipeline/single.ts","../../src/search/recommend.ts","../../src/security/risk.ts","../../src/data/popular-packages.json","../../src/security/typosquat.ts","../../src/mcp/handlers.ts","../../src/mcp/diagram.ts","../../src/compat/optimize.ts","../../src/mcp/plan.ts","../../src/mcp/metrics.ts","../../src/mcp/compact.ts","../../src/mcp/toolDescriptions.ts","../../src/db/usage.ts","../../src/mcp/server.ts","../../src/auth/apiKeys.ts","../../src/github/types.ts","../../src/db/repos.ts","../../src/github/app.ts","../../src/github/attribute.ts","../../src/github/drift.ts","../../src/github/hops.ts","../../src/github/brief.ts","../../src/github/runs.ts","../../src/db/upgradeRuns.ts","../../src/github/workflow.ts","../../src/github/manifests.ts","../../src/github/sbom.ts","../../src/pipeline/repoScan.ts","../../src/mcp/http.ts","../../src/cli/format.ts","../../src/cli/planView.ts","../../src/db/watch.ts","../../src/pipeline/watch.ts","../../src/sandbox/types.ts","../../src/sandbox/local.ts","../../src/sandbox/e2b.ts","../../src/sandbox/index.ts","../../src/pipeline/sandbox.ts","../../src/pipeline/resolveCheck.ts","../../src/pipeline/compat.ts","../../src/cli/commands.ts","../../src/cli/remote.ts","../../src/cli/upgradePlan.ts","../../src/surface/references.ts","../../src/surface/resolve.ts","../../src/surface/extract.ts","../../src/surface/fetch.ts","../../src/surface/upgrade.ts","../../src/cli/checkUpgrade.ts","../../src/cli/install.ts","../../src/bin/lurq.ts","../../src/cli/index.ts","../../src/core/gate.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","/** Static identifiers shared across the CLI and MCP server. */\nexport const SERVER_NAME = 'lurq';\n/** Published npm package name (the CLI command and MCP nickname stay `lurq`).\n * Keep in sync with package.json \"name\". */\nexport const PACKAGE_NAME = 'lurqrun';\n/** Keep in sync with package.json \"version\". */\nexport const VERSION = '0.0.7';\n\n/** Default hosted endpoint the install wizard writes into agent configs. The\n * marketing site is `lurq.run`; the MCP service lives on the `api.` subdomain.\n * Overridable per-invocation with `lurq install --url …` or `LURQ_ENDPOINT`. */\nexport const DEFAULT_ENDPOINT = 'https://api.lurq.run/mcp';\n\n/** Prefix for issued API keys (the rest is high-entropy random). */\nexport const API_KEY_PREFIX = 'lurq_live_';\n\n/** Embedding vector dimensionality (OpenAI text-embedding-3-small). The local\n * fallback embedder produces vectors of the same length so the DB column and\n * pgvector index never need to change. */\nexport const EMBEDDING_DIM = 1536;\n\n/** A package row is flagged `stale: true` in tool responses once its data is\n * older than this (§17). */\nexport const STALENESS_DAYS = 7;\n\nconst HOUR = 60 * 60 * 1000;\nconst DAY = 24 * HOUR;\n\n/** Per-source persistent-cache TTLs (§17). */\nexport const CACHE_TTL = {\n npmRegistry: 6 * HOUR,\n npmDownloads: 12 * HOUR,\n github: 12 * HOUR,\n depsDev: 24 * HOUR,\n bundlephobia: 7 * DAY,\n} as const;\n","/**\n * Minimal leveled logger.\n *\n * IMPORTANT: all output goes to **stderr**. The MCP server communicates over\n * stdio (stdout is the protocol channel), so anything written to stdout would\n * corrupt the JSON-RPC stream. Never log to stdout.\n */\n\nconst LEVELS = { error: 0, warn: 1, info: 2, debug: 3 } as const;\nexport type LogLevel = keyof typeof LEVELS;\n\nfunction currentLevel(): number {\n const raw = process.env.LOG_LEVEL as LogLevel | undefined;\n return raw && raw in LEVELS ? LEVELS[raw] : LEVELS.info;\n}\n\nfunction emit(level: LogLevel, args: unknown[]): void {\n if (LEVELS[level] > currentLevel()) return;\n const parts = args.map((a) =>\n typeof a === 'string' ? a : a instanceof Error ? (a.stack ?? a.message) : safeStringify(a),\n );\n process.stderr.write(`[lurq] ${level.toUpperCase()} ${parts.join(' ')}\\n`);\n}\n\nfunction safeStringify(value: unknown): string {\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\nexport const logger = {\n error: (...args: unknown[]) => emit('error', args),\n warn: (...args: unknown[]) => emit('warn', args),\n info: (...args: unknown[]) => emit('info', args),\n debug: (...args: unknown[]) => emit('debug', args),\n};\n","/**\n * Locate package-relative resources at runtime. Works in dev (tsx, source under\n * src/) and when published (bundled under dist/), by walking up from this module\n * until a directory containing package.json is found.\n */\nimport { existsSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nlet cachedRoot: string | undefined;\n\n/** Absolute path to the installed lurq package root (the dir with package.json). */\nexport function packageRoot(): string {\n if (cachedRoot) return cachedRoot;\n let dir = dirname(fileURLToPath(import.meta.url));\n // Walk up to the filesystem root looking for our package.json.\n for (;;) {\n if (existsSync(join(dir, 'package.json'))) {\n cachedRoot = dir;\n return dir;\n }\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n // Fallback: current working directory.\n cachedRoot = process.cwd();\n return cachedRoot;\n}\n\n/** Folder holding generated Drizzle migrations. */\nexport function migrationsDir(): string {\n return join(packageRoot(), 'drizzle');\n}\n\n/** The curated seed list shipped with the package. */\nexport function seedJsonPath(): string {\n return join(packageRoot(), 'src', 'data', 'seed.json');\n}\n\n/** User-level weight-override config (§4): `~/.config/lurq/weights.json`. */\nexport function userWeightsPath(): string {\n const base = process.env.XDG_CONFIG_HOME || join(homedir(), '.config');\n return join(base, 'lurq', 'weights.json');\n}\n\n/** Project-local weight-override config (§4): `.lurq/weights.json` in the cwd.\n * Takes precedence over the user-level file when present. */\nexport function projectWeightsPath(): string {\n return join(process.cwd(), '.lurq', 'weights.json');\n}\n","/**\n * Agent skill installer (§14). Registers lurq as an MCP server in supported\n * assistants by MERGING a single `lurq` entry into each agent's config — never\n * overwriting unrelated config — and drops the skill-instructions file.\n *\n * Two modes:\n * - **remote** (hosted, default for real users): writes a keyed HTTP entry\n * pointing at the lurq service. No DATABASE_URL ever touches a user's machine.\n * - **local** (self-host / contributors): writes the legacy stdio entry that\n * runs `lurq serve` locally against the user's own DB.\n *\n * MCP config formats move fast and differ per agent; this writes the current\n * widely-supported shapes and prints exactly what it did, so a stale path is\n * obvious rather than silent. Remote shapes verified against current agent docs\n * (2026-06): Claude Code / VS Code use `{ type:\"http\", url, headers }`; Cursor\n * and Kiro use `{ url, headers }`; Windsurf and Antigravity use\n * `{ serverUrl, headers }`; Gemini CLI uses `{ httpUrl, headers }` (`url` there\n * means SSE); Codex (TOML) uses `url` + an inline `http_headers` table.\n */\nimport { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs';\nimport { copyFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\nimport { DEFAULT_ENDPOINT, PACKAGE_NAME } from '../core/constants';\nimport { logger } from '../core/logger';\nimport { packageRoot } from '../core/paths';\n\nconst ENV_KEYS = [\n 'DATABASE_URL',\n 'GITHUB_TOKEN',\n 'EMBEDDING_PROVIDER',\n 'EMBEDDING_API_KEY',\n 'EMBEDDING_MODEL',\n 'SUMMARY_PROVIDER',\n 'SUMMARY_API_KEY',\n 'SUMMARY_MODEL',\n] as const;\n\nexport type ConfigFormat = 'mcpServers' | 'servers' | 'toml';\n\nexport interface AgentSpec {\n id: string;\n label: string;\n format: ConfigFormat;\n /** Absolute config file path. */\n path: string;\n /** Whether this agent appears installed (used by `--agent all` and the wizard). */\n detected: boolean;\n}\n\nfunction home(...p: string[]): string {\n return join(homedir(), ...p);\n}\n\n/**\n * VS Code's user-data directory, which is per-platform:\n * macOS ~/Library/Application Support/Code/User\n * Windows %APPDATA%\\Code\\User\n * Linux $XDG_CONFIG_HOME/Code/User (default ~/.config/Code/User)\n * Hardcoding the macOS path made detection always false elsewhere — and\n * `--agent copilot` write a config nobody reads.\n */\nfunction vscodeUserDir(): string {\n if (process.platform === 'darwin') return home('Library', 'Application Support', 'Code', 'User');\n if (process.platform === 'win32') {\n return join(process.env.APPDATA ?? home('AppData', 'Roaming'), 'Code', 'User');\n }\n return join(process.env.XDG_CONFIG_HOME || home('.config'), 'Code', 'User');\n}\n\nexport function agentSpecs(): AgentSpec[] {\n return [\n {\n id: 'claude-code',\n label: 'Claude Code',\n format: 'mcpServers',\n path: home('.claude.json'),\n detected: existsSync(home('.claude.json')) || existsSync(home('.claude')),\n },\n {\n id: 'cursor',\n label: 'Cursor',\n format: 'mcpServers',\n path: home('.cursor', 'mcp.json'),\n detected: existsSync(home('.cursor')),\n },\n {\n id: 'windsurf',\n label: 'Windsurf',\n format: 'mcpServers',\n path: home('.codeium', 'windsurf', 'mcp_config.json'),\n detected: existsSync(home('.codeium')),\n },\n {\n id: 'copilot',\n label: 'VS Code / GitHub Copilot',\n format: 'servers',\n path: join(vscodeUserDir(), 'mcp.json'),\n detected: existsSync(vscodeUserDir()),\n },\n {\n id: 'codex',\n label: 'OpenAI Codex CLI',\n format: 'toml',\n path: home('.codex', 'config.toml'),\n detected: existsSync(home('.codex')),\n },\n {\n id: 'gemini-cli',\n label: 'Gemini CLI',\n format: 'mcpServers',\n path: home('.gemini', 'settings.json'),\n detected: existsSync(home('.gemini', 'settings.json')),\n },\n {\n // Shares the ~/.gemini root with the Gemini CLI but keeps its own file, so\n // detection has to look at the file rather than at the directory.\n id: 'antigravity',\n label: 'Google Antigravity',\n format: 'mcpServers',\n path: home('.gemini', 'config', 'mcp_config.json'),\n detected: existsSync(home('.gemini', 'config')),\n },\n {\n id: 'kiro',\n label: 'Kiro',\n format: 'mcpServers',\n path: home('.kiro', 'settings', 'mcp.json'),\n detected: existsSync(home('.kiro')),\n },\n ];\n}\n\nexport const SUPPORTED_AGENTS = [\n 'claude-code',\n 'cursor',\n 'windsurf',\n 'copilot',\n 'codex',\n 'gemini-cli',\n 'antigravity',\n 'kiro',\n] as const;\n\n/** How to wire the lurq entry: hosted HTTP endpoint, or local stdio process. */\nexport type InstallMode =\n | { kind: 'remote'; url: string; apiKey: string }\n | { kind: 'local'; env: Record<string, string> };\n\nfunction collectEnv(): Record<string, string> {\n const env: Record<string, string> = {};\n for (const key of ENV_KEYS) {\n const value = process.env[key];\n if (value) env[key] = value;\n }\n return env;\n}\n\nexport interface InstallResult {\n agent: string;\n path: string;\n status: 'installed' | 'skipped' | 'error';\n message?: string;\n}\n\nfunction readJsonObject(path: string): Record<string, any> {\n if (!existsSync(path)) return {};\n const text = readFileSync(path, 'utf8').trim();\n if (!text) return {};\n return JSON.parse(text);\n}\n\n/**\n * Write via a temp file + rename, which is atomic within a directory. These are\n * the user's own agent configs — `~/.claude.json` holds Claude Code's entire\n * project state — and a crash partway through a plain write truncates the file.\n * A reader sees either the old config or the new one, never a half-written one.\n */\nfunction writeFileAtomic(path: string, contents: string): void {\n mkdirSync(dirname(path), { recursive: true });\n const tmp = `${path}.lurq-${process.pid}.tmp`;\n try {\n writeFileSync(tmp, contents, 'utf8');\n renameSync(tmp, path);\n } catch (err) {\n try {\n rmSync(tmp, { force: true });\n } catch {\n /* best-effort cleanup; report the original failure */\n }\n throw err;\n }\n}\n\nfunction writeJson(path: string, obj: unknown): void {\n writeFileAtomic(path, JSON.stringify(obj, null, 2) + '\\n');\n}\n\n/** Local (stdio) lurq server entry for JSON configs. */\nexport function buildServerEntry(env: Record<string, string>, withType: boolean): Record<string, any> {\n const entry: Record<string, any> = { command: 'npx', args: ['-y', PACKAGE_NAME, 'serve'] };\n if (withType) entry.type = 'stdio';\n if (Object.keys(env).length) entry.env = env;\n return entry;\n}\n\n/**\n * Remote (hosted) lurq server entry for JSON configs. Per-agent shape differs:\n * Claude Code & VS Code take `type:\"http\"`; the rest infer transport from which\n * URL field is set — `url` (Cursor, Kiro), `serverUrl` (Windsurf, Antigravity),\n * or `httpUrl` (Gemini CLI, where a plain `url` would be read as an SSE\n * endpoint and the streamable-HTTP handshake would never happen).\n */\nexport function buildRemoteServerEntry(\n agentId: string,\n opts: { url: string; apiKey: string },\n): Record<string, any> {\n const headers = { Authorization: `Bearer ${opts.apiKey}` };\n switch (agentId) {\n case 'cursor':\n case 'kiro':\n return { url: opts.url, headers };\n case 'windsurf':\n case 'antigravity':\n return { serverUrl: opts.url, headers };\n case 'gemini-cli':\n return { httpUrl: opts.url, headers };\n case 'claude-code':\n case 'copilot':\n default:\n return { type: 'http', url: opts.url, headers };\n }\n}\n\n/** Local (stdio) TOML block for the Codex config. */\nexport function buildTomlBlock(env: Record<string, string>): string {\n const lines = ['[mcp_servers.lurq]', 'command = \"npx\"', `args = [\"-y\", \"${PACKAGE_NAME}\", \"serve\"]`];\n if (Object.keys(env).length) {\n lines.push('', '[mcp_servers.lurq.env]');\n for (const [k, v] of Object.entries(env)) lines.push(`${k} = ${JSON.stringify(v)}`);\n }\n return lines.join('\\n') + '\\n';\n}\n\n/**\n * Remote (hosted) TOML block for the Codex config. Codex parses with\n * `deny_unknown_fields`: literal headers go in an inline `http_headers` table,\n * NOT a `[mcp_servers.lurq.headers]` subtable (verified against the openai/codex\n * StreamableHttp config schema).\n */\nexport function buildRemoteTomlBlock(opts: { url: string; apiKey: string }): string {\n return (\n [\n '[mcp_servers.lurq]',\n `url = ${JSON.stringify(opts.url)}`,\n `http_headers = { Authorization = ${JSON.stringify(`Bearer ${opts.apiKey}`)} }`,\n ].join('\\n') + '\\n'\n );\n}\n\nfunction installJsonEntry(spec: AgentSpec, entry: Record<string, any>): InstallResult {\n const key = spec.format === 'servers' ? 'servers' : 'mcpServers';\n const config = readJsonObject(spec.path);\n if (typeof config[key] !== 'object' || config[key] === null) config[key] = {};\n config[key].lurq = entry;\n writeJson(spec.path, config);\n return { agent: spec.id, path: spec.path, status: 'installed' };\n}\n\n/**\n * Drop the existing `[mcp_servers.lurq]` table (its header through the line\n * before the next top-level `[`), leaving every other table untouched. Enough\n * TOML awareness to replace our own block without taking a parser dependency:\n * we only ever need to find one section we wrote ourselves.\n */\nexport function stripTomlBlock(text: string, header = '[mcp_servers.lurq]'): string {\n const lines = text.split('\\n');\n const start = lines.findIndex((l) => l.trim() === header);\n if (start === -1) return text;\n let end = start + 1;\n // Sub-tables ([mcp_servers.lurq.env]) belong to the block; a sibling table ends it.\n while (end < lines.length) {\n const t = lines[end]!.trim();\n if (t.startsWith('[') && !t.startsWith(`${header.slice(0, -1)}.`)) break;\n end++;\n }\n return [...lines.slice(0, start), ...lines.slice(end)].join('\\n').replace(/\\n{3,}/g, '\\n\\n');\n}\n\nfunction installTomlBlock(spec: AgentSpec, block: string): InstallResult {\n const current = existsSync(spec.path) ? readFileSync(spec.path, 'utf8') : '';\n // Replace, never skip: skipping meant a re-run after a key rotation left\n // Codex pointed at the dead key while reporting success. Every other agent\n // upserts its entry, so this one does too.\n const existing = stripTomlBlock(current).replace(/\\s+$/, '');\n const sep = existing ? '\\n\\n' : '';\n writeFileAtomic(spec.path, existing + sep + block);\n return {\n agent: spec.id,\n path: spec.path,\n status: 'installed',\n message: current.includes('[mcp_servers.lurq]') ? 'replaced the existing lurq entry' : undefined,\n };\n}\n\n/** Apply the lurq entry to one agent's config, in the given mode. */\nexport function installAgent(spec: AgentSpec, mode: InstallMode): InstallResult {\n try {\n if (spec.format === 'toml') {\n const block =\n mode.kind === 'remote'\n ? buildRemoteTomlBlock(mode)\n : buildTomlBlock(mode.env);\n return installTomlBlock(spec, block);\n }\n const entry =\n mode.kind === 'remote'\n ? buildRemoteServerEntry(spec.id, mode)\n : buildServerEntry(mode.env, spec.format === 'servers');\n return installJsonEntry(spec, entry);\n } catch (err) {\n return {\n agent: spec.id,\n path: spec.path,\n status: 'error',\n message: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\n/** Copy the skill-instructions template to ~/.lurq. Returns the path, or null. */\nexport function installInstructionsFile(): string | null {\n const src = join(packageRoot(), 'templates', 'skill-instructions.md');\n if (!existsSync(src)) return null;\n const destDir = home('.lurq');\n const dest = join(destDir, 'skill-instructions.md');\n mkdirSync(destDir, { recursive: true });\n copyFileSync(src, dest);\n return dest;\n}\n\n/** Resolve `--agent <id|all>` to the set of agent specs to write. */\nexport function resolveAgents(target: string): AgentSpec[] {\n const specs = agentSpecs();\n if (target === 'all') return specs.filter((s) => s.detected);\n const spec = specs.find((s) => s.id === target);\n if (!spec) {\n throw new Error(`Unknown agent \"${target}\". Supported: ${SUPPORTED_AGENTS.join(', ')}, all.`);\n }\n return [spec];\n}\n\n/** Print the per-agent registration report + next steps. Shared by both paths. */\nexport function printInstallReport(\n results: InstallResult[],\n instructionsPath: string | null,\n mode: InstallMode,\n): void {\n const specs = agentSpecs();\n console.log('lurq MCP server registration:');\n for (const r of results) {\n const spec = specs.find((s) => s.id === r.agent)!;\n const mark = r.status === 'installed' ? '✓' : r.status === 'skipped' ? '•' : '✗';\n console.log(` ${mark} ${spec.label.padEnd(26)} ${r.path}${r.message ? ` (${r.message})` : ''}`);\n }\n if (instructionsPath) console.log(`\\nSkill instructions written to ${instructionsPath}`);\n console.log('\\nNext steps:');\n if (mode.kind === 'local') {\n console.log(' 1. Ensure DATABASE_URL (and any API keys) are set in the config env above.');\n console.log(' 2. Restart the agent so it picks up the new MCP server.');\n } else {\n console.log(' 1. Restart the agent so it picks up the new MCP server.');\n }\n console.log(' • Ask it to recommend a library — it should call lurq.');\n}\n\nexport interface InstallSkillOptions {\n agent?: string;\n /** Hosted endpoint URL (defaults to LURQ_ENDPOINT or the built-in default). */\n url?: string;\n /** API key for the hosted endpoint. Presence selects remote mode. */\n apiKey?: string;\n /** Force the legacy local/stdio entry (self-host). */\n local?: boolean;\n}\n\nexport async function runInstallSkill(opts: InstallSkillOptions): Promise<void> {\n const selected = resolveAgents(opts.agent ?? 'claude-code');\n if (selected.length === 0) {\n console.log('No supported agents detected on this machine.');\n return;\n }\n\n // Remote unless explicitly --local. Remote requires an API key.\n const remote = !opts.local;\n let mode: InstallMode;\n if (remote) {\n const apiKey = opts.apiKey ?? process.env.LURQ_API_KEY;\n if (!apiKey) {\n throw new Error(\n 'An API key is required for a hosted install. Pass --api-key <key> (or set LURQ_API_KEY), ' +\n 'or use `lurq install` for the guided setup, or --local to self-host.',\n );\n }\n const url = opts.url ?? process.env.LURQ_ENDPOINT ?? DEFAULT_ENDPOINT;\n mode = { kind: 'remote', url, apiKey };\n } else {\n const env = collectEnv();\n if (!env.DATABASE_URL) {\n logger.warn(\n 'DATABASE_URL is not set — the local server entry will have no DATABASE_URL. ' +\n 'Set it (in .env) and re-run, or edit the config.',\n );\n }\n mode = { kind: 'local', env };\n }\n\n const results = selected.map((spec) => installAgent(spec, mode));\n const instructionsPath = installInstructionsFile();\n printInstallReport(results, instructionsPath, mode);\n}\n","/**\n * Shared domain types and the v1 category taxonomy (§8.3).\n * These are the stable contracts the rest of the system builds on.\n */\n\n/** Category taxonomy for the JS/TS web stack (§8.3). `other` is the fallback. */\nexport const CATEGORIES = [\n 'framework',\n 'meta-framework',\n 'state-management',\n 'routing',\n 'orm',\n 'database-client',\n 'ui-component-library',\n 'styling',\n 'forms',\n 'validation',\n 'data-fetching',\n 'http-client',\n 'auth',\n 'testing',\n 'build-tool',\n 'bundler',\n 'linting',\n 'date-time',\n 'animation',\n 'charts',\n 'i18n',\n 'utility',\n 'other',\n] as const;\n\nexport type Category = (typeof CATEGORIES)[number];\n\nexport function isCategory(value: string): value is Category {\n return (CATEGORIES as readonly string[]).includes(value);\n}\n\n/** Provenance of a package's stored category (§2A). `curated` comes from the\n * seed file or a manual arg; `inferred` was assigned automatically at ingest\n * and is safe for a later curation pass to override. */\nexport type CategorySource = 'curated' | 'inferred';\n\n/** How a candidate entered the discovery queue (§2B). `dependency-graph` and\n * `recent` are the long-tail channels; `category-search` is keyword-seeded;\n * `reactive` is an on-demand query that wasn't tracked yet. */\nexport type DiscoverySource = 'dependency-graph' | 'category-search' | 'recent' | 'reactive';\n\n/** Lifecycle of a discovery-queue candidate (§2B). */\nexport type DiscoveryStatus = 'pending' | 'ingested' | 'rejected';\n\n/**\n * Categories for which bundle size is meaningful and Bundlephobia is consulted\n * (§9.5). Backend-only categories get a null bundle size, and their efficiency\n * weight is redistributed (§10, see scoring).\n */\nexport const FRONTEND_CATEGORIES = [\n 'ui-component-library',\n 'styling',\n 'state-management',\n 'forms',\n 'validation',\n 'data-fetching',\n 'charts',\n 'animation',\n 'date-time',\n 'utility',\n] as const;\n\nexport function isFrontendCategory(category: Category | null | undefined): boolean {\n return category != null && (FRONTEND_CATEGORIES as readonly string[]).includes(category);\n}\n\n/**\n * Evidence-trustworthiness label, independent of the numeric score (§10, §1).\n * Two-dimensional: `proven`/`emerging` are adoption ladders; `promising` is\n * adoption-independent (high intrinsic quality, new package).\n */\nexport type Confidence = 'proven' | 'emerging' | 'promising' | 'unproven';\n\nexport type Runtime = 'browser' | 'node' | 'both';\n\n/** Result of co-installing two package versions in the sandbox (compat matrix). */\nexport type CompatStatus = 'compatible' | 'conflict';\n\n/**\n * Evidence class behind a compat edge (§3, §4B). Ordered weakest→strongest for\n * upsert precedence: a mined `observed` must never overwrite a sandbox `verified`\n * or `conflict`. `declared` = Tier-0 peer/engine semver; `observed` = co-resolved\n * in N real dependency graphs; `verified` = sandbox co-install passed; `conflict`\n * = declared conflict or a sandbox co-install failed.\n */\nexport type CompatProvenance = 'declared' | 'observed' | 'verified' | 'conflict';\n\n/** Upsert precedence: higher wins, so mining can't erase a proven verdict. */\nexport const PROVENANCE_RANK: Record<CompatProvenance, number> = {\n declared: 0,\n observed: 1,\n verified: 2,\n conflict: 3,\n};\n\n/** Coarse post-install result an agent reports back via `report_outcome` — never\n * source code, just whether the recommended package installed / compiled /\n * passed tests, or failed. Feeds the recommendation→outcome flywheel (§3.1). */\nexport type BuildSignal = 'installed' | 'compiled' | 'tests_passed' | 'failed';\n\n/** Sandbox verdict surfaced to agents: did this version actually install + load? */\nexport interface BuildVerified {\n version: string;\n installed: boolean;\n loaded: boolean | null;\n driver: string;\n ranAt: string;\n}\n\n/** A map of dependency/peer/engine name → semver range (from a manifest). */\nexport type DependencyRanges = Record<string, string>;\n/** `peerDependenciesMeta`: per-peer flags, notably `{ optional: true }`. */\nexport type PeerMeta = Record<string, { optional?: boolean }>;\n\n/** One incompatibility found across a set of packages. */\nexport interface CompatConflict {\n /** Where the conflict came from. `peer-deps`/`engines` are Tier-1 (metadata,\n * instant, deterministic); `sandbox` is Tier-2 (empirical co-install). */\n source: 'peer-deps' | 'engines' | 'sandbox';\n /** The packages involved in the conflict. */\n packages: string[];\n detail: string;\n /** The same fact as `detail`, structured, so a consumer can lay it out without\n * parsing prose. Present on peer-range violations; absent for engine and\n * sandbox conflicts, which aren't about a single declared range. */\n requirement?: {\n /** The peer being asked for. */\n peer: string;\n /** The range the requirer declares. */\n range: string;\n /** What the set actually resolves that peer to, when it is in the set. */\n resolved: string | null;\n };\n}\n\n/**\n * One unordered pair among the checked members.\n *\n * A verdict belongs to a pair, not to a package: the same package can sit in a\n * held pair and a conflicting one, so grading packages would either contradict\n * itself or paint the whole set red. `held` means no declared constraint between\n * the two was violated — it does not mean the pair was executed. Nothing here\n * has been executed.\n */\nexport interface CompatPair {\n a: string;\n b: string;\n status: 'held' | 'conflict';\n /** Only on `conflict` — the conflict's own detail string. */\n detail?: string;\n /** Only on `conflict`, and only for peer-range violations. */\n requirement?: CompatConflict['requirement'];\n}\n\n/** One stored compat edge surfaced to agents, with its evidence class (§4B). */\nexport interface CompatEvidence {\n packages: [string, string];\n versions: [string, string];\n status: CompatStatus;\n provenance: CompatProvenance;\n /** Distinct resolved graphs an `observed` edge was witnessed in (0 otherwise).\n * Only a newly-fetched closure accrues one; the daily re-mine re-reads closures\n * it has already counted and deliberately does not. NOTE: rows minted before\n * that fix carry an inflated count (one per sync run, ~16× on average) and are\n * only corrected by a backfill, which has not been run. */\n witnessCount: number;\n}\n\n/**\n * `compat` output: whole-architecture compatibility for a set of packages.\n * Tier-1 peer-dependency/engine analysis + any Tier-2 sandbox conflicts.\n */\nexport interface CompatOutput {\n packages: string[];\n /** Evidence-graded verdict:\n * - `conflict` — a proven incompatibility (peer-range violation or conflict edge).\n * - `compatible` — every pair is *positively evidenced* (verified/observed edge).\n * - `likely` — no conflict found, but not proven; absence of a declared\n * conflict is not proof, so an unverified set is never `compatible`.\n * - `unknown` — a member has no metadata yet (not ingested). */\n overall: 'compatible' | 'likely' | 'conflict' | 'unknown';\n conflicts: CompatConflict[];\n /** Packages lurq has no compatibility metadata for (counted toward `unknown`). */\n unverified: string[];\n /** The exact members the check ran over, name + resolved version. Versions are\n * always surfaced here, and the structure is stable for later scraping. */\n checked: { name: string; version: string | null }[];\n /** Stored edges among these packages with their evidence strength (§4B) — lets\n * agents (and metrics) see *why* a pair is called compatible, not just that. */\n evidence: CompatEvidence[];\n /** Every unordered pair among `checked`, each with its own verdict — exactly\n * n(n−1)/2 entries. `conflicts` lists only what went wrong; this lists what\n * was compared, which is what lets a caller show coverage rather than just\n * failures. */\n pairs: CompatPair[];\n}\n\n// ── Usage axis D1: API signature drift (§4D) ─────────────────────────────────\n\n/** Kind of an exported symbol, from its `.d.ts` declaration. */\nexport type ExportKind =\n | 'function'\n | 'class'\n | 'interface'\n | 'type'\n | 'enum'\n | 'variable'\n | 'namespace'\n | 'unknown';\n\n/** One normalized exported symbol of a package version's public API surface. */\nexport interface ExportSymbol {\n name: string;\n kind: ExportKind;\n /** Single-line normalized signature (params/return for functions, etc.), or\n * null when the declaration carries no useful signature. */\n signature: string | null;\n}\n\n/** What changed between two API surfaces (§4D). Deltas are computed, not guessed. */\nexport interface SurfaceDelta {\n added: ExportSymbol[];\n removed: ExportSymbol[];\n /** A symbol that disappeared and a near-identical one that appeared — inferred\n * by signature similarity, so an agent sees a rename, not remove+add. */\n renamed: { from: ExportSymbol; to: ExportSymbol }[];\n /** Same name, changed signature. */\n changed: { name: string; before: string | null; after: string | null }[];\n}\n\n/** `usage` tool output: version-exact API surface + optional delta from a known\n * version the agent was trained/working on (§4D). */\nexport interface UsageOutput {\n package: string;\n version: string | null;\n /** Extracted export list, or null when types are unavailable (falls back to\n * the README, which is already fetched). */\n surface: ExportSymbol[] | null;\n available: boolean;\n /** Declared `engines` for this exact version (e.g. `{ node: \">=20\" }`), or null\n * when the manifest declares none. Independent of `available` — the runtime\n * floor matters even for untyped packages. */\n engines: Record<string, string> | null;\n /** Present when a `knownVersion` was supplied and both surfaces resolved. */\n delta?: SurfaceDelta & { fromVersion: string };\n note?: string;\n}\n\nexport type AdvisorySeverity = 'critical' | 'high' | 'moderate' | 'low' | 'info';\n\nexport interface Advisory {\n id: string;\n severity: AdvisorySeverity;\n summary: string;\n}\n\n/** Sub-scores composing the health score (§10). `efficiency` is null when not\n * size-based (backend categories) — its weight is redistributed.\n * `quality` (§1) is a standalone, adoption-independent axis — it does NOT feed\n * the health composite; it blends with health only at ranking time. Null when\n * no manifest signals were available. */\nexport interface ScoreBreakdown {\n maintenance: number;\n adoption: number;\n reliability: number;\n efficiency: number | null;\n quality: number | null;\n}\n\n/**\n * Structured usage guide generated at ingest (product refinement: lurq explains,\n * not just ranks). Grounded in the package README/description — never fabricated.\n * Exact current API specifics are deferred to Context7 via `context7Hint`.\n */\nexport interface UsageGuide {\n whatItIs: string;\n whenToUse: string;\n whenNotToUse?: string;\n whereItFits: string;\n howToWireIn?: string;\n context7Hint?: string;\n}\n\n/** A single recommendation candidate (§12.3.1). Intentionally compact. */\nexport interface Candidate {\n name: string;\n category: Category | null;\n healthScore: number;\n qualityScore: number | null;\n confidence: Confidence;\n why: string;\n latestVersion: string | null;\n weeklyDownloads: number | null;\n lastReleaseAt: string | null;\n repoUrl: string | null;\n}\n\n/** Full evidence read for one package (§12.3.2). */\nexport interface EvaluateOutput {\n dataAsOf: string;\n stale?: boolean;\n name: string;\n category: Category | null;\n healthScore: number;\n qualityScore: number | null;\n confidence: Confidence;\n scoreBreakdown: ScoreBreakdown;\n latestVersion: string | null;\n lastReleaseAt: string | null;\n weeklyDownloads: number | null;\n downloadGrowth90d: number | null;\n scorecard: number | null;\n bundleMinGzipKb: number | null;\n deprecated: boolean;\n archived: boolean;\n advisories: Advisory[];\n summary: string | null;\n usageGuide: UsageGuide | null;\n repoUrl: string | null;\n /** If this package is superseded, the recommended migration target (§1.2). */\n replacedBy?: { name: string; reason: string } | null;\n /** Latest sandbox verdict for this package, if one has been run. */\n buildVerified?: BuildVerified | null;\n}\n\n/** `verify` output (§12.3.4). */\n/** Supply-chain risk gate: high = review before installing (see security/risk). */\nexport type RiskLevel = 'low' | 'medium' | 'high';\n\nexport interface VerifyOutput {\n exists: boolean;\n tracked: boolean;\n deprecated: boolean;\n archived: boolean;\n latestVersion: string | null;\n weeklyDownloads: number | null;\n riskFlags: string[];\n /** Overall supply-chain risk, rolled up from riskFlags. */\n risk: RiskLevel;\n /** Suspected typosquat target — a popular package this name closely mimics. */\n typosquatOf: string | null;\n confidence: Confidence | null;\n advisoryCount: number;\n}\n","/**\n * Environment configuration (§15). Validated with zod. Most vars are optional\n * so the CLI can run partially (e.g. `lurq --help`) without a full setup;\n * commands that need a specific var call `requireConfig` to fail fast with a\n * clear message.\n */\nimport { config as dotenvConfig } from 'dotenv';\nimport { z } from 'zod';\n\nlet envLoaded = false;\n\n/**\n * Load env into process.env exactly once. Safe to call repeatedly.\n *\n * Layering: if `LURQ_ENV_FILE` is set (e.g. `.env.production`), that file loads\n * *first* so its values win, then `.env` fills in the rest (dotenv never\n * overrides an already-set key). This is how the explicit prod path works —\n * `LURQ_ENV_FILE=.env.production` supplies the prod DATABASE_URL while `.env`\n * still provides shared secrets — without prod ever being the ambient default.\n */\nexport function loadEnv(): void {\n if (envLoaded) return;\n const overrideFile = process.env.LURQ_ENV_FILE;\n if (overrideFile) dotenvConfig({ path: overrideFile });\n dotenvConfig();\n envLoaded = true;\n}\n\nconst EnvSchema = z.object({\n DATABASE_URL: z.string().min(1).optional(),\n GITHUB_TOKEN: z.string().min(1).optional(),\n\n // 'openai' here means \"OpenAI-compatible\" — any provider exposing /v1/embeddings\n // + Bearer auth (OpenAI, Together, Fireworks, HF TEI, …). Point *_BASE_URL at it.\n EMBEDDING_PROVIDER: z.enum(['openai', 'local']).default('openai'),\n EMBEDDING_API_KEY: z.string().min(1).optional(),\n EMBEDDING_MODEL: z.string().min(1).default('text-embedding-3-small'),\n EMBEDDING_BASE_URL: z.string().url().default('https://api.openai.com/v1'),\n\n // 'openai' means \"OpenAI-compatible /v1/chat/completions\": OpenAI, Groq, Together,\n // Fireworks, xAI (Grok), etc. Swap provider by setting SUMMARY_BASE_URL + key + model.\n SUMMARY_PROVIDER: z.enum(['openai', 'none']).default('openai'),\n SUMMARY_API_KEY: z.string().min(1).optional(),\n SUMMARY_MODEL: z.string().min(1).default('gpt-4o-mini'),\n SUMMARY_BASE_URL: z.string().url().default('https://api.openai.com/v1'),\n\n LURQ_SYNC_CONCURRENCY: z.coerce.number().int().positive().max(50).default(5),\n /** Stalest non-seed packages the daily sync refreshes on top of the seed list.\n * This is the rotation rate for everything discovery ingested: index size /\n * this = days to come all the way around. Raise it if the sync finishes well\n * inside the cron window; lower it if npm starts rate-limiting. 0 disables\n * the rotation (seeds only, the pre-rotation behaviour). */\n LURQ_SYNC_REFRESH_CAP: z.coerce.number().int().min(0).max(5000).default(400),\n LOG_LEVEL: z.enum(['error', 'warn', 'info', 'debug']).default('info'),\n\n // Hosted HTTP service (`serve-http`). Server-side only.\n PORT: z.coerce.number().int().positive().default(8080),\n /** Per-API-key rate limit: max requests per window. */\n LURQ_RATE_LIMIT_MAX: z.coerce.number().int().positive().default(120),\n /** Coarser per-IP rate limit (blunts unauthenticated floods before auth). */\n LURQ_IP_RATE_LIMIT_MAX: z.coerce.number().int().positive().default(240),\n /** Rate-limit window, milliseconds (applies to both limiters). */\n LURQ_RATE_LIMIT_WINDOW_MS: z.coerce.number().int().positive().default(60_000),\n /** Bearer token guarding `/metrics`. Unset → the endpoint is disabled (404). */\n LURQ_METRICS_TOKEN: z.string().min(1).optional(),\n /** Shared secret for self-serve key issuance (`POST /keys`). The Clerk-\n * authenticated web app presents it to mint a key for a signed-in user. Unset\n * → the endpoint is disabled (404). Keep it server-side, never in the client. */\n LURQ_ISSUER_SECRET: z.string().min(1).optional(),\n\n // GitHub App (repo autopilot). Only the App itself holds repo access; lurq\n // never stores a user's personal token. Either unset → /repos is disabled (404).\n // The App *slug* is deliberately not here: only the web app needs it, to build\n // the install link, and it reads process.env directly.\n /** Numeric App ID from the GitHub App settings page. */\n LURQ_GITHUB_APP_ID: z.string().min(1).optional(),\n /** PEM private key. Accepts literal newlines or `\\n` escapes (Railway/Vercel). */\n LURQ_GITHUB_APP_PRIVATE_KEY: z.string().min(1).optional(),\n\n // Client-side (install wizard / CLI talking to a remote endpoint).\n LURQ_ENDPOINT: z.string().url().optional(),\n LURQ_API_KEY: z.string().min(1).optional(),\n\n // Sandbox verification. With E2B_API_KEY set, package install + smoke-load\n // runs in an isolated E2B cloud sandbox (safe for UNTRUSTED packages);\n // without it, the local child-process driver is used (trusted packages only).\n E2B_API_KEY: z.string().min(1).optional(),\n // E2B template to launch. Must provide node + npm on PATH; omit for E2B's\n // default. Provision a Node-versioned template here for reproducible runs.\n E2B_TEMPLATE: z.string().min(1).optional(),\n\n // Lurq bakeoff testing toggle b/w local and prod DB\n USE_LIVE_API: z.string().min(1).optional(),\n});\n\nexport type Config = z.infer<typeof EnvSchema>;\n\nexport class ConfigError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ConfigError';\n }\n}\n\nlet cached: Config | undefined;\n\n/** Parse + validate the environment. Throws ConfigError on malformed values. */\nexport function getConfig(): Config {\n if (cached) return cached;\n loadEnv();\n const parsed = EnvSchema.safeParse(process.env);\n if (!parsed.success) {\n const issues = parsed.error.issues\n .map((i) => ` - ${i.path.join('.')}: ${i.message}`)\n .join('\\n');\n throw new ConfigError(`Invalid environment configuration:\\n${issues}`);\n }\n cached = parsed.data;\n return cached;\n}\n\n/** For tests: clear the memoized config so a fresh getConfig() re-reads\n * process.env. Does not force a `.env` reload (loadEnv stays idempotent). */\nexport function resetConfigCache(): void {\n cached = undefined;\n}\n\n/**\n * Return the config but fail fast if any of the named required keys are absent.\n * Use in command handlers that genuinely need them (e.g. sync needs DATABASE_URL).\n */\nexport function requireConfig<K extends keyof Config>(keys: K[]): Config {\n const config = getConfig();\n const missing = keys.filter((k) => config[k] === undefined || config[k] === '');\n if (missing.length > 0) {\n throw new ConfigError(\n `Missing required environment variable(s): ${missing.join(', ')}.\\n` +\n `See .env.example for setup. Tip: copy it to .env and fill in the values.`,\n );\n }\n return config;\n}\n","/**\n * Drizzle schema (§8). One denormalized `packages` table feeds all reads (§8.2),\n * plus `sync_runs` (ingestion audit) and `seed_packages` (curated bootstrap list).\n *\n * The `vector` extension must exist before these migrations apply — `db migrate`\n * runs `CREATE EXTENSION IF NOT EXISTS vector` first (pgvector is not created\n * automatically by Drizzle).\n */\nimport { sql } from 'drizzle-orm';\nimport {\n bigint,\n boolean,\n customType,\n date,\n index,\n integer,\n jsonb,\n pgTable,\n primaryKey,\n real,\n serial,\n text,\n timestamp,\n uniqueIndex,\n vector,\n} from 'drizzle-orm/pg-core';\nimport { EMBEDDING_DIM } from '../core/constants';\n\n/** Postgres full-text `tsvector` type for hybrid lexical search (§3). */\nconst tsvector = customType<{ data: string; driverData: string }>({\n dataType() {\n return 'tsvector';\n },\n});\nimport type {\n Advisory,\n BuildSignal,\n Category,\n CategorySource,\n CompatProvenance,\n CompatStatus,\n Confidence,\n DependencyRanges,\n DiscoverySource,\n DiscoveryStatus,\n ExportSymbol,\n PeerMeta,\n ScoreBreakdown,\n UsageGuide,\n} from '../core/types';\nimport type { EntityKind, EvidenceClass, Verdict } from '../graph/types';\nimport type {\n RepoDrift,\n RepoManifest,\n RepoPolicy,\n UpgradeRunStatus,\n UpgradeSeverity,\n} from '../github/types';\nimport type { ExtractionTier, SymbolKind } from '../surface/types';\n\nconst ts = (name: string) => timestamp(name, { withTimezone: true, mode: 'date' });\n\n/** One row per tracked npm package. */\nexport const packages = pgTable(\n 'packages',\n {\n id: serial('id').primaryKey(),\n name: text('name').notNull().unique(),\n ecosystem: text('ecosystem').notNull().default('npm'),\n\n // Classification + descriptive text\n category: text('category').$type<Category>(),\n /** Whether `category` was hand-curated or inferred at ingest (§2A). */\n categorySource: text('category_source').$type<CategorySource>(),\n description: text('description'),\n summary: text('summary'),\n repoUrl: text('repo_url'),\n homepage: text('homepage'),\n latestVersion: text('latest_version'),\n license: text('license'),\n\n // Lifecycle flags\n deprecated: boolean('deprecated').notNull().default(false),\n archived: boolean('archived').notNull().default(false),\n\n // Age / maintenance signals\n firstPublishedAt: ts('first_published_at'),\n lastReleaseAt: ts('last_release_at'),\n\n // Adoption signals\n weeklyDownloads: bigint('weekly_downloads', { mode: 'number' }),\n downloadGrowth90d: real('download_growth_90d'),\n stars: integer('stars'),\n openIssues: integer('open_issues'),\n closedIssues: integer('closed_issues'),\n\n // Reliability / efficiency signals\n scorecard: real('scorecard'),\n bundleMinGzipKb: real('bundle_min_gzip_kb'),\n advisories: jsonb('advisories').$type<Advisory[]>(),\n\n // Compatibility metadata (Tier-1): declared peer-deps + engines of the\n // latest version, so a whole-stack peer-range check is one indexed query.\n peerDependencies: jsonb('peer_dependencies').$type<DependencyRanges>(),\n peerDependenciesMeta: jsonb('peer_dependencies_meta').$type<PeerMeta>(),\n engines: jsonb('engines').$type<DependencyRanges>(),\n\n // Computed outputs\n healthScore: integer('health_score'),\n /** Intrinsic-quality axis (§1), adoption-independent. Blends with health at\n * ranking time (composite); never folded into health_score itself. */\n qualityScore: integer('quality_score'),\n confidence: text('confidence').$type<Confidence>(),\n scoreBreakdown: jsonb('score_breakdown').$type<ScoreBreakdown>(),\n usageGuide: jsonb('usage_guide').$type<UsageGuide>(),\n embedding: vector('embedding', { dimensions: EMBEDDING_DIM }),\n // Identity of the vector space `embedding` was produced in (e.g.\n // `openai:text-embedding-3-small`, `local`). Vector search filters on the\n // active provider so switching models can't compare incompatible spaces.\n embeddingProvider: text('embedding_provider'),\n\n // Lexical search vector (§3): name weighted highest (A), then category (B),\n // then summary/description (C). Generated + STORED so it stays in sync with\n // the row automatically; indexed with GIN for fast `@@` matching.\n searchVector: tsvector('search_vector').generatedAlwaysAs(\n sql`setweight(to_tsvector('english', coalesce(name, '')), 'A') || setweight(to_tsvector('english', coalesce(category, '')), 'B') || setweight(to_tsvector('english', coalesce(summary, description, '')), 'C')`,\n ),\n\n // Freshness + bookkeeping\n dataAsOf: timestamp('data_as_of', { withTimezone: true, mode: 'date' }),\n /** latest_version this package's direct deps were last expanded for by the\n * discovery graph channel (§2B). Discovery re-scans a package only when this\n * differs from latest_version — deps are version-pinned, so an unchanged\n * version has unchanged neighbors. NULL = never scanned. */\n graphScannedVersion: text('graph_scanned_version'),\n createdAt: ts('created_at').notNull().defaultNow(),\n updatedAt: ts('updated_at').notNull().defaultNow(),\n /** The individual account (api_keys.owner_id) whose on-demand query first\n * caused this package to be ingested — nobody had asked for it before them.\n * Null for crawler/_changes-created packages, or ones ingested before\n * dashboard accounts existed. Stamped once via a standalone WHERE ... IS NULL\n * update kept out of upsertPackage, so re-syncs can never clobber it. */\n firstRequestedByOwnerId: text('first_requested_by_owner_id'),\n },\n (table) => [\n index('packages_category_idx').on(table.category),\n index('packages_health_score_idx').on(table.healthScore),\n // pgvector HNSW index for cosine similarity search (§11).\n index('packages_embedding_idx').using('hnsw', table.embedding.op('vector_cosine_ops')),\n // GIN index for lexical full-text search (§3).\n index('packages_search_vector_idx').using('gin', table.searchVector),\n index('packages_first_requested_by_idx').on(table.firstRequestedByOwnerId),\n ],\n);\n\n/** Ingestion audit trail (§8.1). */\nexport const syncRuns = pgTable('sync_runs', {\n id: serial('id').primaryKey(),\n startedAt: ts('started_at').notNull().defaultNow(),\n finishedAt: ts('finished_at'),\n packagesSeen: integer('packages_seen').notNull().default(0),\n packagesUpdated: integer('packages_updated').notNull().default(0),\n errors: jsonb('errors').$type<SyncError[]>().notNull().default([]),\n status: text('status').$type<SyncStatus>().notNull().default('running'),\n /** Which deployment started this run, `<environment>/<service>`, or null when\n * the host injects neither (local runs). Diagnostic only: two rows in the\n * same minute with *different* origins is a duplicate scheduler — a second\n * environment or a second service tile running the same cron — which is\n * otherwise invisible from the data and doubles the outbound request rate\n * until npm starts answering 429. */\n origin: text('origin'),\n});\n\n/** Curated v1 seed list (§16), loaded from seed.json. */\nexport const seedPackages = pgTable('seed_packages', {\n name: text('name').primaryKey(),\n category: text('category').$type<Category>(),\n addedAt: ts('added_at').notNull().defaultNow(),\n});\n\n/**\n * Proactive-discovery candidate queue (§2B). Operator-side: the crawler enqueues\n * adjacency-graph / category-search / recent candidates here, a merit gate\n * pre-scores them on quality signals only (downloads excluded), and survivors\n * graduate to full ingestion. Keeps cost bounded and the DB free of toy packages.\n */\nexport const discoveryQueue = pgTable(\n 'discovery_queue',\n {\n id: serial('id').primaryKey(),\n name: text('name').notNull().unique(),\n discoveredVia: text('discovered_via').$type<DiscoverySource>().notNull(),\n /** Lightweight quality-only pre-score (§2B). Null until the gate runs. */\n preScore: integer('pre_score'),\n status: text('status').$type<DiscoveryStatus>().notNull().default('pending'),\n discoveredAt: ts('discovered_at').notNull().defaultNow(),\n },\n (table) => [index('discovery_queue_status_idx').on(table.status)],\n);\n\n/**\n * Demand-driven compat-verify queue (§4C). A `compat` query that finds an\n * unverified pair enqueues the set here (instant, off the query path); the worker\n * drains it and runs the sandbox co-install, so the matrix self-densifies from\n * real usage without ever blocking a user or running a VM in the HTTP process.\n */\nexport const compatVerifyQueue = pgTable(\n 'compat_verify_queue',\n {\n id: serial('id').primaryKey(),\n /** Canonical order-independent key of the package set — dedups pending requests. */\n setKey: text('set_key').notNull().unique(),\n /** The package names to co-install in the sandbox. */\n packages: jsonb('packages').$type<string[]>().notNull(),\n /** Failed drains bump this; the worker drops a set that keeps failing. */\n attempts: integer('attempts').notNull().default(0),\n requestedAt: ts('requested_at').notNull().defaultNow(),\n },\n (table) => [index('compat_verify_queue_requested_idx').on(table.requestedAt)],\n);\n\n/**\n * API keys for the hosted HTTP service (docs/lurq-hosted-deployment.md §5). Each\n * user gets a key; only its sha256 hash is persisted, so a DB leak never\n * exposes a usable key — the plaintext is shown exactly once at creation.\n * `ownerId` is the individual Clerk user id, set at self-serve issuance from\n * the web dashboard (no org/team concept — one identity per account).\n */\nexport const apiKeys = pgTable(\n 'api_keys',\n {\n id: serial('id').primaryKey(),\n /** sha256 hex of the full key — the only form persisted. */\n keyHash: text('key_hash').notNull().unique(),\n /** Identifiable display prefix, e.g. `lurq_live_ab12cd` (safe to show/log). */\n prefix: text('prefix').notNull(),\n /** Free-text label (owner / org / purpose). */\n label: text('label'),\n /** Reserved for self-serve issuance: maps to a Clerk user id. */\n ownerId: text('owner_id'),\n tier: text('tier').notNull().default('free'),\n createdAt: ts('created_at').notNull().defaultNow(),\n lastUsedAt: ts('last_used_at'),\n revokedAt: ts('revoked_at'),\n },\n (table) => [index('api_keys_owner_idx').on(table.ownerId)],\n);\n\n/**\n * Per-package version timeline (versions + publish dates), ingested from the npm\n * packument on every sync. Foundation for upgrade/migration intelligence and the\n * compatibility matrix; refreshed reactively by the `_changes` follower.\n */\nexport const packageVersions = pgTable(\n 'package_versions',\n {\n packageName: text('package_name').notNull(),\n version: text('version').notNull(),\n publishedAt: ts('published_at'),\n },\n (table) => [\n primaryKey({ columns: [table.packageName, table.version] }),\n index('package_versions_name_published_idx').on(table.packageName, table.publishedAt),\n ],\n);\n\n/** One row per replication feed: the cursor the npm `_changes` follower resumes\n * from, so a restart doesn't replay the whole registry history. */\nexport const watchState = pgTable('watch_state', {\n id: text('id').primaryKey(),\n seq: text('seq').notNull(),\n updatedAt: ts('updated_at'),\n});\n\n/**\n * Sandbox verification results: did this package version actually install and\n * load? Evidence beyond static signals. The query path reads the latest run.\n */\nexport const verificationRuns = pgTable(\n 'verification_runs',\n {\n id: serial('id').primaryKey(),\n packageName: text('package_name').notNull(),\n version: text('version').notNull(),\n driver: text('driver').notNull(),\n moduleSystem: text('module_system').notNull(),\n installed: boolean('installed').notNull(),\n imported: boolean('imported'),\n ranScripts: boolean('ran_scripts').notNull().default(false),\n durationMs: integer('duration_ms'),\n error: text('error'),\n ranAt: ts('ran_at'),\n },\n (table) => [index('verification_runs_pkg_idx').on(table.packageName, table.version)],\n);\n\n/**\n * Compatibility edges from co-installing two package versions in the sandbox.\n * A successful co-install is positive proof they coexist; a 2-package failure is\n * proof they conflict. Pairs are stored canonically (packageA name < packageB).\n */\nexport const compatEdges = pgTable(\n 'compat_edges',\n {\n id: serial('id').primaryKey(),\n packageA: text('package_a').notNull(),\n versionA: text('version_a').notNull(),\n packageB: text('package_b').notNull(),\n versionB: text('version_b').notNull(),\n status: text('status').$type<CompatStatus>().notNull(),\n /** Evidence class (§4B). Existing rows are sandbox co-installs, so the column\n * defaults to `verified` to preserve their meaning. */\n provenance: text('provenance').$type<CompatProvenance>().notNull().default('verified'),\n /** Distinct resolved graphs an `observed` edge was witnessed in (confidence).\n * Ignored for verified/conflict. Accumulates on conflict, never overwritten. */\n witnessCount: integer('witness_count').notNull().default(0),\n driver: text('driver').notNull(),\n ranAt: ts('ran_at'),\n },\n (table) => [\n uniqueIndex('compat_edges_pair_idx').on(\n table.packageA,\n table.versionA,\n table.packageB,\n table.versionB,\n ),\n ],\n);\n\n/**\n * Persisted immutable resolved dependency closures (§4B). A `package@version`\n * always resolves to the same tree, so we store it once at first ingest; the\n * daily re-mine pass reads these with NO network to mint `observed` edges for\n * nodes that became tracked after the closure was captured.\n */\nexport const resolvedClosures = pgTable(\n 'resolved_closures',\n {\n id: serial('id').primaryKey(),\n packageName: text('package_name').notNull(),\n version: text('version').notNull(),\n /** Full closure: [{ name, version }, …] — every node in node_modules. */\n nodes: jsonb('nodes').$type<{ name: string; version: string }[]>().notNull(),\n fetchedAt: ts('fetched_at').notNull().defaultNow(),\n },\n (table) => [\n uniqueIndex('resolved_closures_pkg_idx').on(table.packageName, table.version),\n ],\n);\n\n/**\n * Extracted public API surface per `package@version` (§4D — usage axis D1).\n * Ground truth = the package's shipped `.d.ts`, parsed deterministically (no\n * LLM). Versions are immutable, so a surface is extracted once and cached\n * forever; `usage` serves it and diffs across versions for API drift.\n */\nexport const apiSurfaces = pgTable(\n 'api_surfaces',\n {\n id: serial('id').primaryKey(),\n packageName: text('package_name').notNull(),\n version: text('version').notNull(),\n /** Normalized export list: [{ name, kind, signature }, …]. */\n surface: jsonb('surface').$type<ExportSymbol[]>().notNull(),\n extractedAt: ts('extracted_at').notNull().defaultNow(),\n },\n (table) => [uniqueIndex('api_surfaces_pkg_idx').on(table.packageName, table.version)],\n);\n\n/**\n * Recommendation → outcome capture (§3.1): the flywheel asset. lurq sits inside\n * the agent loop at the choice moment, so a lightweight opt-in callback yields a\n * recommendation→outcome dataset no downstream scanner can reconstruct (they see\n * deployed deps, not the decision). Privacy: no source code — only which package,\n * accepted or not, and a coarse build signal. Cheap to capture, compounds with use.\n */\nexport const recommendationOutcomes = pgTable(\n 'recommendation_outcomes',\n {\n id: serial('id').primaryKey(),\n /** The individual user this outcome belongs to (api_keys.owner_id). Null for\n * anonymous/operator-issued keys. This is what turns the flywheel from a\n * global blob into a per-user asset — \"what did *this* person succeed\n * with.\" Server-injected from the authenticated key, never caller-supplied. */\n ownerId: text('owner_id'),\n packageName: text('package_name').notNull(),\n accepted: boolean('accepted').notNull(),\n buildSignal: text('build_signal').$type<BuildSignal>(),\n /** The original need text the recommendation was for — ties outcome back to\n * the ask. Optional, length-capped at the trust boundary; never source code. */\n need: text('need'),\n createdAt: ts('created_at').notNull().defaultNow(),\n },\n (table) => [\n index('recommendation_outcomes_pkg_idx').on(table.packageName),\n index('recommendation_outcomes_owner_idx').on(table.ownerId),\n ],\n);\n\n/**\n * Per-user, per-day, per-tool call counts for the dashboard usage view. Keyed by\n * ownerId (not per-key — a user can hold multiple keys; the dashboard is\n * per-individual). Display-only, not a billing ledger: writes are fire-and-forget\n * UPSERTs, so an undercount on a DB hiccup is acceptable. Skipped entirely when a\n * request has no ownerId (operator-issued keys with no dashboard account).\n */\nexport const ownerUsageDaily = pgTable(\n 'owner_usage_daily',\n {\n ownerId: text('owner_id').notNull(),\n /** UTC day, 'YYYY-MM-DD'. */\n date: date('date').notNull(),\n /** recommend | evaluate | compare | compat | verify | usage | diagram | plan | report_outcome */\n tool: text('tool').notNull(),\n count: integer('count').notNull().default(0),\n },\n (table) => [\n primaryKey({ columns: [table.ownerId, table.date, table.tool] }),\n index('owner_usage_daily_owner_date_idx').on(table.ownerId, table.date),\n ],\n);\n\n/**\n * A GitHub repository connected through the lurq App (repo autopilot).\n *\n * What is NOT here is the point: no source, no tokens, no clone. `manifests`\n * holds only declared dependency ranges, and access is re-minted per scan from\n * the App's own installation credentials, so revoking the install revokes\n * everything instantly and there is no long-lived secret to leak.\n */\nexport const repos = pgTable(\n 'repos',\n {\n id: serial('id').primaryKey(),\n /** Clerk user id — same identity as api_keys.owner_id. */\n ownerId: text('owner_id').notNull(),\n /** GitHub App installation this repo is reachable through. */\n installationId: bigint('installation_id', { mode: 'number' }).notNull(),\n /** `owner/name`. */\n fullName: text('full_name').notNull(),\n defaultBranch: text('default_branch'),\n isPrivate: boolean('is_private').notNull().default(false),\n policy: jsonb('policy').$type<RepoPolicy>().notNull(),\n manifests: jsonb('manifests').$type<RepoManifest[]>(),\n /** Install command detected from the lockfile at scan time, so the generated\n * workflow uses the repo's actual package manager instead of assuming npm. */\n installCommand: text('install_command'),\n drift: jsonb('drift').$type<RepoDrift>(),\n lastScanAt: ts('last_scan_at'),\n /** Last scan failure, surfaced in the dashboard. Null once a scan succeeds —\n * a stale error next to fresh drift numbers reads as a current outage. */\n lastScanError: text('last_scan_error'),\n createdAt: ts('created_at').notNull().defaultNow(),\n },\n (table) => [\n uniqueIndex('repos_owner_full_name_idx').on(table.ownerId, table.fullName),\n index('repos_installation_idx').on(table.installationId),\n ],\n);\n\n/**\n * One row per upgrade the CI loop considered — the observability spine of the\n * autopilot, and what the dashboard's impact figures are computed from.\n *\n * Written by the user's own workflow through an API key, so everything here is\n * caller-supplied and validated at the boundary. Deliberately narrow: symbol\n * names and counts, never file contents. `callSites` is a count and always\n * safe to send; `callSiteFiles` carries paths and is only populated when the\n * repo's policy opts in, because a file path is information about someone's\n * codebase even though it is not source.\n */\nexport const upgradeRuns = pgTable(\n 'upgrade_runs',\n {\n id: serial('id').primaryKey(),\n /** Resolved server-side from the authenticated API key. Never caller-supplied. */\n ownerId: text('owner_id').notNull(),\n /** Links to `repos` when the repo is also connected. Null when the workflow\n * runs somewhere lurq has no GitHub App installation — the CLI works\n * standalone, and losing those runs would bias every impact figure. */\n repoId: integer('repo_id'),\n /** `owner/name` from GITHUB_REPOSITORY. */\n repoFullName: text('repo_full_name').notNull(),\n packageName: text('package_name').notNull(),\n fromVersion: text('from_version').notNull(),\n toVersion: text('to_version').notNull(),\n severity: text('severity').$type<UpgradeSeverity>().notNull(),\n status: text('status').$type<UpgradeRunStatus>().notNull(),\n /** Referenced symbols the upgrade removes or re-shapes. */\n symbolsAffected: jsonb('symbols_affected').$type<string[]>().notNull().default([]),\n /** How many references those symbols have in the repo. */\n callSites: integer('call_sites').notNull().default(0),\n /** Distinct files containing them. Opt-in per repo policy. */\n callSiteFiles: jsonb('call_site_files').$type<string[]>(),\n filesChanged: integer('files_changed'),\n /** Null when the repo has no test script — distinct from `false`, which\n * means the suite ran and failed. */\n testsPassed: boolean('tests_passed'),\n prUrl: text('pr_url'),\n /**\n * The GitHub Actions run, so a dashboard row links back to real logs.\n * NOT NULL with an empty-string default rather than nullable: it is part of\n * the dedup key below, and Postgres treats NULLs as distinct — a nullable\n * column there would silently let every re-post insert a duplicate. Empty\n * means \"posted outside Actions\" (a local CLI run), which then dedups to one\n * row per package+target and updates in place.\n */\n runUrl: text('run_url').notNull().default(''),\n createdAt: ts('created_at').notNull().defaultNow(),\n },\n (table) => [\n index('upgrade_runs_owner_created_idx').on(table.ownerId, table.createdAt),\n index('upgrade_runs_repo_idx').on(table.repoId),\n // One row per package per Actions run: a re-post of the same run must update\n // rather than duplicate, or a retried job would double every impact figure.\n uniqueIndex('upgrade_runs_dedup_idx').on(\n table.ownerId,\n table.repoFullName,\n table.packageName,\n table.toVersion,\n table.runUrl,\n ),\n ],\n);\n\nexport type SyncStatus = 'running' | 'success' | 'partial' | 'failed';\n\nexport interface SyncError {\n package: string;\n source: string;\n message: string;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// v2 graph (docs/lurq-v2-spec.md §5). Generic entity/claim/observation model,\n// running ALONGSIDE the npm-specific tables above — not replacing them yet. See\n// docs/lurq-v2-integration-plan.md §4 for why the migration is deferred.\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Demand-driven surface-extraction queue (§6.1).\n *\n * A query for a package-version not in the graph IS a discovery event, and the\n * spec ranks it the highest-priority queue input because it is revealed demand\n * rather than a guess about what matters. Enqueueing is instant and off the\n * query path: extraction never runs synchronously inside a request (§8), so a\n * miss returns UNKNOWN and the worker fills it in.\n *\n * Same shape as compat_verify_queue, deliberately — that loop already works.\n */\nexport const surfaceQueue = pgTable(\n 'surface_queue',\n {\n id: serial('id').primaryKey(),\n packageName: text('package_name').notNull(),\n /** Null means \"whatever latest resolves to at extraction time\". */\n version: text('version'),\n /** Dedup key: `name@version`. */\n specKey: text('spec_key').notNull().unique(),\n /** Failed drains bump this; the worker drops a spec that keeps failing. */\n attempts: integer('attempts').notNull().default(0),\n requestedAt: ts('requested_at').notNull().defaultNow(),\n },\n (table) => [index('surface_queue_requested_idx').on(table.requestedAt)],\n);\n\n/** A node in the graph. Anything an agent depends on that an oracle can check. */\nexport const entities = pgTable(\n 'entities',\n {\n id: serial('id').primaryKey(),\n kind: text('kind').$type<EntityKind>().notNull(),\n /** Registry or authority: npm, api.stripe.com, … */\n namespace: text('namespace').notNull(),\n name: text('name').notNull(),\n /** Null for unversioned kinds. */\n version: text('version'),\n /** `kind:namespace:name:version` */\n canonicalKey: text('canonical_key').notNull(),\n /**\n * 0 = the public graph; a real id = a private deployment's tenant. The spec\n * models public as NULL, but Postgres UNIQUE treats NULLs as distinct, so\n * (key, NULL) would insert unlimited duplicates and the dedup silently fails.\n * A non-null sentinel is the cheap fix that works on every PG version.\n */\n tenantId: bigint('tenant_id', { mode: 'number' }).notNull().default(0),\n /** Tarball digest. THE extraction cache key: unchanged digest, no re-extraction.\n * This is what keeps cost sublinear as the index grows (§5, §6.5). */\n artifactHash: text('artifact_hash'),\n /** Dependent count. Drives sampling AND refresh priority — and note priority\n * is NOT popularity: the study found drift concentrates at LOW in-degree\n * (18.7% vs 8.3%), which is exactly where models have the weakest priors. */\n inDegree: integer('in_degree'),\n firstSeen: ts('first_seen').notNull().defaultNow(),\n },\n (table) => [\n uniqueIndex('entities_canonical_idx').on(table.canonicalKey, table.tenantId),\n index('entities_kind_idx').on(table.kind, table.namespace, table.name),\n index('entities_artifact_idx').on(table.artifactHash),\n ],\n);\n\n/**\n * One row per exported symbol of a package version (§5).\n *\n * `origin` and `tier` are not decoration — each exists because of a defect that\n * silently corrupted the drift study:\n * - `origin` (§6.4.1): a symbol re-exported from another package is not this\n * package's surface. Counting them made one package appear to delete 168\n * exports when the true figure was 0.\n * - `tier` (§6.4.3): surfaces extracted at different tiers are NOT comparable,\n * so the tier has to travel with every symbol or diffs go wrong quietly.\n */\nexport const symbols = pgTable(\n 'symbols',\n {\n id: serial('id').primaryKey(),\n entityId: integer('entity_id')\n .notNull()\n .references(() => entities.id),\n /** 'default', 'foo', 'foo.bar' */\n path: text('path').notNull(),\n /** function | class | object | primitive | type_only */\n kind: text('kind').$type<SymbolKind>().notNull(),\n /** `fn.length` equivalent; null when not statically determinable. */\n arity: integer('arity'),\n /** 'local' | 'external:<pkg>' */\n origin: text('origin').notNull().default('local'),\n deprecated: boolean('deprecated').notNull().default(false),\n tier: text('tier').$type<ExtractionTier>().notNull(),\n /** Full declaration text; tier C only (§6.2). */\n signature: text('signature'),\n sourceFile: text('source_file'),\n sourceLine: integer('source_line'),\n },\n // Keyed by TIER as well as path: a package version has one surface per tier and\n // they are not interchangeable (§6.4.3). Without the tier in the key, storing a\n // tier-C surface would silently overwrite the tier-A one that answers runtime\n // existence — replacing the authoritative answer with a type-level guess.\n (table) => [uniqueIndex('symbols_entity_path_tier_idx').on(table.entityId, table.path, table.tier)],\n);\n\n/** The runtime a verdict holds in. Never a node — always a dimension (§2). */\nexport const environments = pgTable('environments', {\n id: serial('id').primaryKey(),\n os: text('os').notNull(),\n arch: text('arch').notNull(),\n runtime: text('runtime').notNull(),\n runtimeVer: text('runtime_ver').notNull(),\n resolver: text('resolver'),\n /** Hash of the above; the dedup key. */\n fingerprint: text('fingerprint').notNull().unique(),\n});\n\n/** A (subject, relation, object, environment) tuple awaiting observations. */\nexport const claims = pgTable(\n 'claims',\n {\n id: serial('id').primaryKey(),\n subjectId: integer('subject_id')\n .notNull()\n .references(() => entities.id),\n /** Null for unary claims (\"does this install at all\"). */\n objectId: integer('object_id').references(() => entities.id),\n relation: text('relation').notNull(),\n /** NULL for DECLARED claims: a shipped-JS surface reads the same on every\n * machine, so there is no environment to fingerprint. Executed claims\n * (co-install, conflict, behaviour) always carry one (§5). */\n environmentId: integer('environment_id').references(() => environments.id),\n tenantId: bigint('tenant_id', { mode: 'number' }).notNull().default(0),\n },\n (table) => [\n uniqueIndex('claims_tuple_idx').on(\n table.subjectId,\n table.objectId,\n table.relation,\n table.environmentId,\n table.tenantId,\n ),\n ],\n);\n\n/**\n * APPEND-ONLY. Verdicts are never mutated — the history is the product, and\n * `breaks_at` (the highest-value edge in the graph) is derived by scanning\n * observations across versions. `stale` is applied at READ time from the\n * oracle's TTL, never written by a background job.\n */\nexport const observations = pgTable(\n 'observations',\n {\n id: serial('id').primaryKey(),\n claimId: integer('claim_id')\n .notNull()\n .references(() => claims.id),\n verdict: text('verdict').$type<Verdict>().notNull(),\n /** What KIND of evidence backs the verdict (§4.1) — orthogonal to the verdict\n * itself. A declared surface fact must never read as behavioural proof. */\n class: text('class').$type<EvidenceClass>().notNull().default('executed'),\n /** Which extraction tier produced it; null for executed claims. */\n tier: text('tier').$type<ExtractionTier>(),\n /** Evidence that makes the verdict auditable. Null only for `unknown`. */\n evidence: text('evidence'),\n oracleId: text('oracle_id').notNull(),\n oracleVer: text('oracle_ver').notNull(),\n costMillis: integer('cost_millis'),\n observedAt: ts('observed_at').notNull().defaultNow(),\n },\n (table) => [index('observations_claim_idx').on(table.claimId, table.observedAt)],\n);\n\nexport type PackageRow = typeof packages.$inferSelect;\nexport type NewPackageRow = typeof packages.$inferInsert;\nexport type EntityRow = typeof entities.$inferSelect;\nexport type NewEntityRow = typeof entities.$inferInsert;\nexport type EnvironmentRow = typeof environments.$inferSelect;\nexport type ClaimRow = typeof claims.$inferSelect;\nexport type ObservationRow = typeof observations.$inferSelect;\nexport type SymbolRow = typeof symbols.$inferSelect;\nexport type SurfaceQueueRow = typeof surfaceQueue.$inferSelect;\nexport type NewSymbolRow = typeof symbols.$inferInsert;\nexport type NewObservationRow = typeof observations.$inferInsert;\nexport type SeedPackageRow = typeof seedPackages.$inferSelect;\nexport type SyncRunRow = typeof syncRuns.$inferSelect;\nexport type DiscoveryQueueRow = typeof discoveryQueue.$inferSelect;\nexport type CompatVerifyQueueRow = typeof compatVerifyQueue.$inferSelect;\nexport type ApiKeyRow = typeof apiKeys.$inferSelect;\nexport type NewApiKeyRow = typeof apiKeys.$inferInsert;\nexport type PackageVersionRow = typeof packageVersions.$inferSelect;\nexport type NewPackageVersionRow = typeof packageVersions.$inferInsert;\nexport type VerificationRunRow = typeof verificationRuns.$inferSelect;\nexport type NewVerificationRunRow = typeof verificationRuns.$inferInsert;\nexport type CompatEdgeRow = typeof compatEdges.$inferSelect;\nexport type NewCompatEdgeRow = typeof compatEdges.$inferInsert;\nexport type ResolvedClosureRow = typeof resolvedClosures.$inferSelect;\nexport type NewResolvedClosureRow = typeof resolvedClosures.$inferInsert;\nexport type ApiSurfaceRow = typeof apiSurfaces.$inferSelect;\nexport type NewApiSurfaceRow = typeof apiSurfaces.$inferInsert;\nexport type RecommendationOutcomeRow = typeof recommendationOutcomes.$inferSelect;\nexport type NewRecommendationOutcomeRow = typeof recommendationOutcomes.$inferInsert;\nexport type OwnerUsageDailyRow = typeof ownerUsageDaily.$inferSelect;\nexport type NewOwnerUsageDailyRow = typeof ownerUsageDaily.$inferInsert;\nexport type RepoRow = typeof repos.$inferSelect;\nexport type NewRepoRow = typeof repos.$inferInsert;\nexport type UpgradeRunRow = typeof upgradeRuns.$inferSelect;\nexport type NewUpgradeRunRow = typeof upgradeRuns.$inferInsert;\n","/**\n * Database client factory. Uses postgres.js + Drizzle. Callers own the lifecycle:\n * create, use, then `await close()` (CLI commands are short-lived processes).\n */\nimport { drizzle, type PostgresJsDatabase } from 'drizzle-orm/postgres-js';\nimport postgres from 'postgres';\nimport { requireConfig } from '../core/config';\nimport * as schema from './schema';\n\nexport type Database = PostgresJsDatabase<typeof schema>;\n\nexport interface DbHandle {\n db: Database;\n /** Underlying postgres.js client, for raw SQL (e.g. CREATE EXTENSION). */\n sql: postgres.Sql;\n /** Close the connection pool. Always call when done. */\n close: () => Promise<void>;\n}\n\nexport function createDb(opts: { max?: number } = {}): DbHandle {\n const { DATABASE_URL } = requireConfig(['DATABASE_URL']);\n const sql = postgres(DATABASE_URL!, { max: opts.max ?? 10, onnotice: () => {} });\n const db = drizzle(sql, { schema });\n return { db, sql, close: () => sql.end() };\n}\n\nexport { schema };\n","/**\n * Optional Redis response cache for the read-heavy tools (recommend / evaluate /\n * compare). The index only changes when `sync`/`rescore` run, so identical\n * queries can be served from Redis instead of re-running the hybrid search.\n *\n * Zero-config by design: with no `REDIS_URL` (the default, and every end-user's\n * machine), `cached()` is a transparent pass-through and `invalidateCache()` a\n * no-op — nothing to provision, nothing breaks. Point `REDIS_URL` at an Upstash\n * (or any) Redis on the hosted server to turn it on. Any Redis error degrades to\n * computing directly; the cache never takes the request path down.\n *\n * Invalidation is version-based: every key embeds a namespace version read from\n * `lurq:cachever`. A successful sync `INCR`s it, so all prior keys become\n * unreachable at once (and age out via TTL) — no SCAN/DEL sweep.\n */\nimport { logger } from './logger';\n\ninterface RedisLike {\n get(key: string): Promise<string | null>;\n set(key: string, value: string, mode: 'EX', ttlSeconds: number): Promise<unknown>;\n incr(key: string): Promise<number>;\n}\n\nconst VERSION_KEY = 'lurq:cachever';\nconst DEFAULT_TTL_SEC = 3600;\n/** In-process memo for the namespace version, to avoid a round-trip per call.\n * Bounded so a sync's INCR is picked up within seconds. */\nconst VERSION_MEMO_MS = 10_000;\n\nlet clientPromise: Promise<RedisLike | null> | null = null;\nlet versionMemo: { value: string; at: number } | null = null;\n\nfunction ttlSeconds(): number {\n const n = Number(process.env.LURQ_CACHE_TTL_SEC);\n return Number.isFinite(n) && n > 0 ? n : DEFAULT_TTL_SEC;\n}\n\n/** Lazily connect to Redis once. Returns null (cache disabled) when REDIS_URL is\n * unset or the client can't be created. */\nasync function getClient(): Promise<RedisLike | null> {\n if (!process.env.REDIS_URL) return null;\n if (!clientPromise) {\n clientPromise = (async () => {\n try {\n const { default: Redis } = await import('ioredis');\n const client = new Redis(process.env.REDIS_URL!, {\n maxRetriesPerRequest: 1,\n enableOfflineQueue: false,\n lazyConnect: false,\n // Railway's private network (redis.railway.internal) is IPv6-only and\n // ioredis defaults to IPv4 — family:0 lets it resolve either stack, so\n // both the private URL and a public/Upstash URL work unchanged.\n family: 0,\n });\n client.on('error', (err: Error) => logger.warn(`redis: ${err.message}`));\n logger.info('Response cache enabled (REDIS_URL set).');\n return client as unknown as RedisLike;\n } catch (err) {\n logger.warn(`redis disabled (init failed): ${(err as Error).message}`);\n return null;\n }\n })();\n }\n return clientPromise;\n}\n\nasync function namespaceVersion(client: RedisLike): Promise<string> {\n if (versionMemo && Date.now() - versionMemo.at < VERSION_MEMO_MS) return versionMemo.value;\n const value = (await client.get(VERSION_KEY).catch(() => null)) ?? '0';\n versionMemo = { value, at: Date.now() };\n return value;\n}\n\n/**\n * Get-or-compute with optional caching. When the cache is off or unreachable,\n * `compute()` runs directly. `skipCache(value)` lets the caller avoid caching\n * unhelpful results (e.g. empty recommendations or not-found lookups).\n */\nexport async function cached<T>(\n namespace: string,\n key: string,\n compute: () => Promise<T>,\n opts: { skipCache?: (value: T) => boolean } = {},\n): Promise<T> {\n const client = await getClient();\n if (!client) return compute();\n\n let fullKey: string;\n try {\n const version = await namespaceVersion(client);\n fullKey = `lurq:${namespace}:${version}:${key}`;\n const hit = await client.get(fullKey);\n if (hit != null) return JSON.parse(hit) as T;\n } catch (err) {\n logger.warn(`redis read failed, bypassing cache: ${(err as Error).message}`);\n return compute();\n }\n\n const value = await compute();\n if (!opts.skipCache?.(value)) {\n // Fire-and-forget write; a cache-write failure must never affect the response.\n client.set(fullKey, JSON.stringify(value), 'EX', ttlSeconds()).catch(() => {});\n }\n return value;\n}\n\n/** Invalidate every cached read by bumping the namespace version. Call after a\n * successful sync/rescore. No-op when the cache is off. */\nexport async function invalidateCache(): Promise<void> {\n const client = await getClient();\n if (!client) return;\n try {\n await client.incr(VERSION_KEY);\n versionMemo = null; // force the next read to pick up the new version\n } catch (err) {\n logger.warn(`redis invalidate failed: ${(err as Error).message}`);\n }\n}\n","/**\n * v2 graph primitives (docs/lurq-v2-spec.md §2–§4).\n *\n * The load-bearing idea is the Oracle Rule: a node type may enter the graph only\n * if you can name the command that verifies it and what failure looks like. That\n * is a function signature, and this file is it. Adding a node type means writing\n * an `Oracle` and registering it — nothing downstream (preflight, breaks_at,\n * private mode) needs to know which oracle produced an observation.\n *\n * This runs ALONGSIDE the v1 npm tables, deliberately. v1's package path is the\n * only thing with users; migrating it onto this model to prove the shape is the\n * highest-risk/lowest-information move available. Migrate after a second node\n * type has shown the abstraction holds.\n */\nimport type { Sandbox } from '../sandbox/types';\n\n/** Node types. Extend only when the Oracle Rule is satisfiable for the new kind. */\nexport type EntityKind =\n /** P0 */\n | 'package_version'\n /** P0 — the central node type: highest query volume, and what breaks (§2). */\n | 'package_surface'\n /** P1 */\n | 'mcp_server'\n | 'mcp_tool'\n /** P2 */\n | 'api_spec'\n | 'schema_provider';\n\n/**\n * §4.1. The distinction between `verified_false` and `unknown` is the most\n * important thing in the API: an agent must always be able to tell \"we checked\n * and it does not work\" from \"we have not checked\".\n *\n * `unverifiable` must NEVER collapse into `verified_false` — an upstream rate\n * limit or a sandbox crash is not evidence about the subject. A single false\n * `verified_false` costs more trust than a hundred `unknown`s.\n */\nexport type Verdict =\n | 'verified_true'\n | 'verified_false'\n | 'unknown'\n | 'stale'\n /** Entity ships no usable artifact for this claim. NOT the same as absence:\n * 3.0% of study extractions resolved at no tier, and reporting those as\n * \"no exports\" would be a false removal. */\n | 'undeclared'\n | 'unverifiable';\n\n/**\n * §4.1. Orthogonal to the verdict: a verdict says what we concluded, a class says\n * what kind of evidence backs it.\n *\n * The rule that matters: a DERIVED claim inherits the WEAKEST class among its\n * inputs, and a DECLARED surface fact must never be presented as behavioural\n * evidence. \"This symbol is exported\" and \"this symbol works\" are different\n * claims and conflating them is how an index starts lying.\n */\nexport type EvidenceClass = 'declared' | 'executed' | 'derived';\n\n/** Identity of a node, before it has a database id. */\nexport interface EntityRef {\n kind: EntityKind;\n /** Registry or authority: 'npm', 'api.stripe.com', … */\n namespace: string;\n name: string;\n /** Null for kinds that aren't versioned. */\n version?: string | null;\n}\n\n/** `kind:namespace:name:version` — the dedup key. */\nexport function canonicalKey(ref: EntityRef): string {\n return `${ref.kind}:${ref.namespace}:${ref.name}:${ref.version ?? ''}`;\n}\n\n/**\n * §2. `runtime_env` is deliberately not a verifiable node — it is a fingerprint\n * attached to every verdict. \"Incompatible\" is meaningless without it: the same\n * pair resolves cleanly on one runtime and fails on another.\n */\nexport interface Environment {\n os: string;\n arch: string;\n runtime: string;\n runtimeVer: string;\n /** 'npm@10', 'uv@0.5', … Null when the oracle doesn't resolve dependencies. */\n resolver?: string | null;\n}\n\n/** One fact an oracle established, plus the evidence that established it. */\nexport interface OracleObservation {\n /** Subject is implied by the oracle's target; object is set for binary claims. */\n object?: EntityRef;\n /** `resolves_with`, `provides`, `conflicts_with`, … (§3) */\n relation: string;\n verdict: Verdict;\n /** Exit code, stderr tail, schema diff — whatever makes the verdict auditable. */\n evidence?: string;\n}\n\nexport interface OracleResult {\n observations: OracleObservation[];\n /** Child nodes discovered while verifying (e.g. the tools an MCP server lists). */\n discovered?: EntityRef[];\n costMillis: number;\n}\n\n/**\n * The Oracle Rule as a type. `run` must never throw for a subject-side failure —\n * that is a `verified_false` observation with evidence. Throw only when the\n * oracle itself could not run, and the caller records `unverifiable`.\n */\nexport interface Oracle<T extends EntityRef = EntityRef> {\n /** Stable id, e.g. 'mcp_server.handshake'. */\n readonly id: string;\n /** Bump when the oracle's semantics change; invalidates prior observations. */\n readonly version: string;\n readonly kind: EntityKind;\n /** Past this age an observation reads as `stale` (§4.1, applied at read time). */\n readonly ttlHours: number;\n /** One sentence: what we run, and what failure looks like. Enforced by review. */\n readonly rule: string;\n run(target: T, env: Environment, sandbox: Sandbox): Promise<OracleResult>;\n}\n","/**\n * Read/write helpers for the v2 graph (entities / environments / claims /\n * observations). See docs/lurq-v2-spec.md §5.\n *\n * The only invariant that matters here: `observations` is APPEND-ONLY. Nothing\n * in this file updates a verdict, and nothing should ever be added that does —\n * `breaks_at` is derived by scanning the history, so overwriting destroys the\n * product. `stale` is computed at read time from the oracle's TTL.\n */\nimport { and, eq, isNull } from 'drizzle-orm';\nimport { createHash } from 'node:crypto';\nimport type { Database } from './client';\nimport { claims, entities, environments, observations } from './schema';\nimport type { ClaimRow, EntityRow, EnvironmentRow } from './schema';\nimport {\n canonicalKey,\n type Environment,\n type EntityRef,\n type EvidenceClass,\n type Verdict,\n} from '../graph/types';\nimport type { ExtractionTier } from '../surface/types';\n\n/** Stable hash of the runtime dimensions — the environment dedup key. */\nexport function fingerprint(env: Environment): string {\n const parts = [env.os, env.arch, env.runtime, env.runtimeVer, env.resolver ?? ''];\n return createHash('sha256').update(parts.join('\\0')).digest('hex').slice(0, 32);\n}\n\nexport async function upsertEnvironment(db: Database, env: Environment): Promise<EnvironmentRow> {\n const fp = fingerprint(env);\n const [row] = await db\n .insert(environments)\n .values({ ...env, resolver: env.resolver ?? null, fingerprint: fp })\n .onConflictDoUpdate({\n target: environments.fingerprint,\n // No-op update so the RETURNING clause yields the existing row.\n set: { fingerprint: fp },\n })\n .returning();\n return row!;\n}\n\nexport async function upsertEntity(\n db: Database,\n ref: EntityRef,\n tenantId = 0,\n): Promise<EntityRow> {\n const key = canonicalKey(ref);\n const [row] = await db\n .insert(entities)\n .values({\n kind: ref.kind,\n namespace: ref.namespace,\n name: ref.name,\n version: ref.version ?? null,\n canonicalKey: key,\n tenantId,\n })\n .onConflictDoUpdate({\n target: [entities.canonicalKey, entities.tenantId],\n set: { canonicalKey: key },\n })\n .returning();\n return row!;\n}\n\nexport async function upsertClaim(\n db: Database,\n args: {\n subjectId: number;\n objectId?: number | null;\n relation: string;\n /** Null for declared claims — they hold in every environment (§5). */\n environmentId?: number | null;\n tenantId?: number;\n },\n): Promise<ClaimRow> {\n const objectId = args.objectId ?? null;\n const envId = args.environmentId ?? null;\n const tenantId = args.tenantId ?? 0;\n const existing = await db\n .select()\n .from(claims)\n .where(\n and(\n eq(claims.subjectId, args.subjectId),\n objectId === null ? isNull(claims.objectId) : eq(claims.objectId, objectId),\n eq(claims.relation, args.relation),\n envId === null ? isNull(claims.environmentId) : eq(claims.environmentId, envId),\n eq(claims.tenantId, tenantId),\n ),\n )\n .limit(1);\n if (existing[0]) return existing[0];\n\n // The unique index can't dedup NULL object_id or environment_id (Postgres\n // treats NULLs as distinct), so the select above is the real guard and this\n // insert races benignly: a duplicate claim costs one redundant row, never a\n // wrong verdict. Fully-populated tuples are protected by the index.\n const [row] = await db\n .insert(claims)\n .values({ subjectId: args.subjectId, objectId, relation: args.relation, environmentId: envId, tenantId })\n .returning();\n return row!;\n}\n\nexport async function recordObservation(\n db: Database,\n args: {\n claimId: number;\n verdict: Verdict;\n /** What kind of evidence backs it (§4.1). Defaults to executed for oracles. */\n class?: EvidenceClass;\n /** Extraction tier, for declared claims; null for executed ones (§6.2). */\n tier?: ExtractionTier | null;\n evidence?: string | null;\n oracleId: string;\n oracleVer: string;\n costMillis?: number | null;\n },\n): Promise<void> {\n await db.insert(observations).values({\n claimId: args.claimId,\n verdict: args.verdict,\n class: args.class ?? 'executed',\n tier: args.tier ?? null,\n evidence: args.evidence ?? null,\n oracleId: args.oracleId,\n oracleVer: args.oracleVer,\n costMillis: args.costMillis ?? null,\n });\n}\n\n/**\n * §4.1, applied at READ time — never written by a background job.\n *\n * A verdict past its oracle's TTL reads as `stale`, never as its original value.\n * `unknown` never goes stale (there is nothing to expire), and it must stay\n * distinguishable from `verified_false`: \"we have not checked\" is a different\n * answer from \"we checked and it does not work\".\n */\nexport function applyTtl(\n verdict: Verdict,\n observedAt: Date,\n ttlHours: number,\n now = Date.now(),\n): Verdict {\n if (verdict === 'unknown' || verdict === 'unverifiable' || verdict === 'undeclared')\n return verdict;\n const ageHours = (now - observedAt.getTime()) / 3_600_000;\n return ageHours > ttlHours ? 'stale' : verdict;\n}\n","/**\n * Surface persistence (§5, §6.5).\n *\n * Two responsibilities:\n * 1. Store an extracted surface as `symbols` + an `observation` recording how\n * it was established (class + tier), never overwriting history.\n * 2. Skip re-extraction when the artifact digest is unchanged — the content-\n * addressed cache that keeps cost sublinear as the index grows.\n *\n * Nothing here executes package code; extraction upstream is static (§9.2).\n */\nimport { and, desc, eq, sql } from 'drizzle-orm';\nimport type { Database } from './client';\nimport { claims, entities, observations, surfaceQueue, symbols } from './schema';\nimport type { SurfaceQueueRow } from './schema';\nimport { recordObservation, upsertClaim, upsertEntity } from './graph';\nimport type { EntityRef } from '../graph/types';\nimport type { ExtractedSurface, ExtractionTier } from '../surface/types';\n\n/** The entity ref for a package version's surface. */\nexport function surfaceRef(pkg: string, version: string | null): EntityRef {\n return { kind: 'package_surface', namespace: 'npm', name: pkg, version };\n}\n\n/**\n * Is a stored surface still good, or does it need extracting again?\n *\n * This compared the tarball digest alone, and a published tarball never\n * changes — so once a package was extracted it was cached forever and no\n * improvement to the extractor could ever reach stored data. Two landed the\n * same day: the ESM-first entry fallback (date-fns and vitest had no readable\n * surface) and namespace member resolution (zod presented as one symbol). A\n * full re-extraction over 2,780 packages reported success and changed nothing,\n * because every call returned 'cached'.\n *\n * The extractor version was already being recorded — `storeSurface` writes it\n * as the observation's `oracleVer` — it was simply never read back. A cache key\n * has to contain everything the value depends on, and the surface depends on\n * the code that produced it as much as on the bytes it was produced from.\n */\nexport async function isExtractionCached(\n db: Database,\n ref: EntityRef,\n artifactHash: string,\n extractorVersion: string,\n tier: ExtractionTier = 'shipped_js_ast',\n tenantId = 0,\n): Promise<boolean> {\n const row = await upsertEntity(db, ref, tenantId);\n if (row.artifactHash !== artifactHash) return false;\n const existing = await db\n .select({ id: symbols.id })\n .from(symbols)\n .where(and(eq(symbols.entityId, row.id), eq(symbols.tier, tier)))\n .limit(1);\n if (existing.length === 0) return false;\n\n // Extracted by which version of the extractor? Anything but the current one\n // is stale by definition, however unchanged the tarball is.\n const seen = await db\n .select({ oracleVer: observations.oracleVer })\n .from(observations)\n .innerJoin(claims, eq(claims.id, observations.claimId))\n .where(\n and(\n eq(claims.subjectId, row.id),\n eq(claims.relation, 'exposes'),\n eq(observations.tier, tier),\n ),\n )\n .orderBy(desc(observations.observedAt))\n .limit(1);\n return seen[0]?.oracleVer === extractorVersion;\n}\n\n/**\n * Persist an extracted surface.\n *\n * An empty surface is recorded as `undeclared` with the extractor's stated\n * reason — never as \"this package exports nothing\" (§4.2, §6.4.2). That\n * distinction is the difference between a measurement gap and a false removal.\n */\nexport async function storeSurface(\n db: Database,\n surface: ExtractedSurface,\n opts: { artifactHash?: string | null; extractorVersion: string; tenantId?: number } = {\n extractorVersion: '1',\n },\n): Promise<{ entityId: number; symbolsWritten: number; verdict: string }> {\n const tenantId = opts.tenantId ?? 0;\n const ref = surfaceRef(surface.package, surface.version);\n const entity = await upsertEntity(db, ref, tenantId);\n\n if (opts.artifactHash) {\n await db\n .update(entities)\n .set({ artifactHash: opts.artifactHash })\n .where(eq(entities.id, entity.id));\n }\n\n const claim = await upsertClaim(db, {\n subjectId: entity.id,\n relation: 'exposes',\n // Declared claims are environment-independent: a shipped-JS surface reads\n // identically on every machine, so no fingerprint is attached (§5).\n environmentId: null,\n tenantId,\n });\n\n const undeclared = surface.symbols.length === 0;\n await recordObservation(db, {\n claimId: claim.id,\n verdict: undeclared ? 'undeclared' : 'verified_true',\n class: 'declared',\n tier: surface.tier,\n evidence: undeclared\n ? (surface.undeclaredReason ?? 'no symbols extracted')\n : `${surface.symbols.length} symbols from ${surface.filesWalked} file(s), entry ${surface.entry}`,\n oracleId: 'surface.tier_a',\n oracleVer: opts.extractorVersion,\n });\n\n if (undeclared) return { entityId: entity.id, symbolsWritten: 0, verdict: 'undeclared' };\n\n // Replace only THIS tier's rows: a tier-C surface must never clear the tier-A\n // one, since they answer different questions (§6.4.3). Symbols snapshot an\n // immutable artifact; the history that matters lives in `observations`.\n await db\n .delete(symbols)\n .where(and(eq(symbols.entityId, entity.id), eq(symbols.tier, surface.tier)));\n const rows = surface.symbols.map((s) => ({\n entityId: entity.id,\n path: s.path,\n kind: s.kind,\n arity: s.arity,\n origin: s.origin,\n deprecated: s.deprecated,\n tier: s.tier,\n signature: s.signature ?? null,\n sourceFile: s.sourceRef?.file ?? null,\n sourceLine: s.sourceRef?.line ?? null,\n }));\n for (let i = 0; i < rows.length; i += 500) {\n await db.insert(symbols).values(rows.slice(i, i + 500)).onConflictDoNothing();\n }\n\n return { entityId: entity.id, symbolsWritten: rows.length, verdict: 'verified_true' };\n}\n\n/** Dedup key for the extraction queue. */\nexport function specKey(pkg: string, version: string | null): string {\n return `${pkg}@${version ?? 'latest'}`;\n}\n\n/**\n * Record a query miss (§6.1). Instant, deduped, and never blocking — the query\n * path returns UNKNOWN and the worker does the work.\n */\nexport async function enqueueSurface(\n db: Database,\n pkg: string,\n version: string | null,\n): Promise<void> {\n await db\n .insert(surfaceQueue)\n .values({ packageName: pkg, version, specKey: specKey(pkg, version) })\n .onConflictDoNothing();\n}\n\n/** Oldest pending specs, for the worker drain. */\nexport async function getPendingSurfaces(db: Database, limit = 10): Promise<SurfaceQueueRow[]> {\n return db.select().from(surfaceQueue).orderBy(surfaceQueue.requestedAt).limit(limit);\n}\n\nexport async function dropSurfaceQueue(db: Database, id: number): Promise<void> {\n await db.delete(surfaceQueue).where(eq(surfaceQueue.id, id));\n}\n\nexport async function bumpSurfaceAttempt(db: Database, id: number): Promise<void> {\n await db\n .update(surfaceQueue)\n .set({ attempts: sql`${surfaceQueue.attempts} + 1` })\n .where(eq(surfaceQueue.id, id));\n}\n","/**\n * Normalized surface IR (v1 spec §6.3).\n *\n * Deliberately ecosystem-agnostic: this shape is what makes a second ecosystem\n * cheap instead of linear, so nothing npm-specific belongs here. Per-ecosystem\n * detail goes in a sidecar, never forced into the common shape.\n */\n\n/**\n * §6.2. Ordered by authority for RUNTIME-existence claims. Tier A is primary\n * (89.3% coverage in the study); C is type-level only and must never answer\n * \"does this symbol exist at runtime\" — a removed type breaks `tsc`, a removed\n * runtime symbol breaks `node`.\n */\nexport type ExtractionTier =\n | 'shipped_js_ast' // A — primary\n | 'runtime_import' // B — sandboxed require/import; the cost driver\n | 'bundled_dts' // C — secondary, signatures + deprecation only\n | 'types_package' // D — DefinitelyTyped; drifts from the real package\n | 'jsdoc_generated'; // E — rarely reached\n\nexport type SymbolKind = 'function' | 'class' | 'object' | 'primitive' | 'type_only';\n\n/**\n * `origin` exists because of defect §6.4.1: `export { X } from \"@scope/other\"`\n * re-exports a symbol this package does not own. Counting those as local surface\n * made one package look like it deleted 168 exports when the true figure was 0.\n * Anything `external:*` is excluded from removal counts.\n */\nexport type SymbolOrigin = 'local' | `external:${string}`;\n\nexport interface SurfaceSymbol {\n /** 'default', 'foo', 'foo.bar' */\n path: string;\n kind: SymbolKind;\n /** `fn.length` equivalent; null when not statically determinable. */\n arity: number | null;\n origin: SymbolOrigin;\n deprecated: boolean;\n tier: ExtractionTier;\n /** Full declaration text. Tier C only — tier A cannot see types, and an\n * overload set collapses to one symbol whose signature lists each overload. */\n signature?: string;\n sourceRef?: { file: string; line: number };\n}\n\nexport interface ExtractedSurface {\n package: string;\n version: string | null;\n tier: ExtractionTier;\n entry: string | null;\n symbols: SurfaceSymbol[];\n /** Files walked through the package-internal module graph (§6.4.5). */\n filesWalked: number;\n /** Specifiers that resolved outside the package — their names are external. */\n externalReExports: string[];\n /** Set when nothing could be extracted; the caller records UNDECLARED, not absence. */\n undeclaredReason?: string;\n}\n\n/** Runtime-existence symbols only: `type_only` never counts (§6.4.4). */\nexport function runtimeSymbols(surface: ExtractedSurface): SurfaceSymbol[] {\n return surface.symbols.filter((s) => s.kind !== 'type_only' && s.origin === 'local');\n}\n","/**\n * Surface diff (§8.1 `diff_surface`, §3 `removed_at` / `arity_changed`).\n *\n * The highest-value output in the spec and the cheapest: \"when did this stop\n * working\" falls out of a static comparison of two extracted surfaces, with no\n * oracle executed across a version matrix.\n *\n * Three guards, each for a defect that silently corrupted the study (§6.4):\n * - cross-tier diffs are refused outright (§6.4.3)\n * - `type_only` never counts as runtime breakage (§6.4.4)\n * - `external:*` re-exports are never counted as this package's removals (§6.4.1)\n *\n * The fourth guard lives here too: a diff against an EMPTY surface is refused\n * (§6.4.2). An empty extraction is a measurement failure, and treating it as\n * \"everything was removed\" is exactly the bug that reported 100% precision on a\n * harness that had loaded nothing.\n */\nimport { runtimeSymbols, type ExtractedSurface, type SurfaceSymbol } from './types';\n\nexport interface ArityChange {\n path: string;\n from: number | null;\n to: number | null;\n}\n\nexport interface SignatureChange {\n path: string;\n from: string;\n to: string;\n}\n\nexport interface SurfaceDiff {\n package: string;\n fromVersion: string | null;\n toVersion: string | null;\n tier: ExtractedSurface['tier'];\n /** Runtime symbols present in `from` and absent from `to`. Breaks `node`. */\n removed: SurfaceSymbol[];\n added: SurfaceSymbol[];\n arityChanged: ArityChange[];\n /** Signature drift. Tier C only — tier A cannot see types at all, so an empty\n * list from a tier-A diff means \"not measurable\", not \"nothing changed\". */\n signatureChanged: SignatureChange[];\n /** Type-level removals — break `tsc`, NOT `node`. Reported separately (§8.1). */\n typeOnlyRemoved: SurfaceSymbol[];\n deprecated: SurfaceSymbol[];\n /** Set when no comparison could be made; callers must not read the arrays. */\n inconclusive?: string;\n}\n\nconst empty = (\n from: ExtractedSurface,\n to: ExtractedSurface,\n reason: string,\n): SurfaceDiff => ({\n package: from.package,\n fromVersion: from.version,\n toVersion: to.version,\n tier: from.tier,\n removed: [],\n added: [],\n arityChanged: [],\n signatureChanged: [],\n typeOnlyRemoved: [],\n deprecated: [],\n inconclusive: reason,\n});\n\nexport function diffSurfaces(from: ExtractedSurface, to: ExtractedSurface): SurfaceDiff {\n // §6.4.3 — a tier-A surface and a tier-C surface are not comparable.\n if (from.tier !== to.tier) {\n return empty(from, to, `cross-tier comparison refused: ${from.tier} vs ${to.tier}`);\n }\n // §6.4.2 — never issue a verdict from an empty surface. Mandatory guard.\n if (from.symbols.length === 0) {\n return empty(from, to, 'source surface is empty — extraction failed, not a removal');\n }\n if (to.symbols.length === 0) {\n return empty(from, to, 'target surface is empty — extraction failed, not a removal');\n }\n\n const fromRuntime = new Map(runtimeSymbols(from).map((s) => [s.path, s]));\n const toRuntime = new Map(runtimeSymbols(to).map((s) => [s.path, s]));\n\n const removed = [...fromRuntime.values()].filter((s) => !toRuntime.has(s.path));\n const added = [...toRuntime.values()].filter((s) => !fromRuntime.has(s.path));\n\n const arityChanged: ArityChange[] = [];\n for (const [path, a] of fromRuntime) {\n const b = toRuntime.get(path);\n if (!b) continue;\n if (a.arity !== null && b.arity !== null && a.arity !== b.arity) {\n arityChanged.push({ path, from: a.arity, to: b.arity });\n }\n }\n\n // §6.4.4 — reported, but as a separate class so a caller can tell a `tsc`\n // break from a `node` break.\n const typeOnlyFrom = from.symbols.filter((s) => s.kind === 'type_only');\n const toPaths = new Set(to.symbols.map((s) => s.path));\n const typeOnlyRemoved = typeOnlyFrom.filter((s) => !toPaths.has(s.path));\n\n // Signatures exist only at tier C. Comparing them on a tier-A diff would\n // report \"no changes\" for something never measured.\n const signatureChanged: SignatureChange[] = [];\n if (from.tier === 'bundled_dts') {\n const fromAll = new Map(from.symbols.map((s) => [s.path, s]));\n for (const b of to.symbols) {\n const a = fromAll.get(b.path);\n if (a?.signature && b.signature && a.signature !== b.signature) {\n signatureChanged.push({ path: b.path, from: a.signature, to: b.signature });\n }\n }\n }\n\n const deprecated = [...toRuntime.values()].filter(\n (s) => s.deprecated && !fromRuntime.get(s.path)?.deprecated,\n );\n\n return {\n package: from.package,\n fromVersion: from.version,\n toVersion: to.version,\n tier: from.tier,\n removed,\n added,\n arityChanged,\n signatureChanged,\n typeOnlyRemoved,\n deprecated,\n };\n}\n","/**\n * `resolve_surface` and `diff_surface` (§8.1) — the two tools the v1 thesis\n * rests on. `diff_surface` is the demo.\n *\n * Response discipline (§8.2) is enforced here rather than left to callers: every\n * response carries `verdict`, `class`, `tier`, `observedAt`, and a coverage note.\n * A bare answer without provenance is indistinguishable from the model's own\n * guess, which is the thing these tools exist to correct.\n *\n * Extraction NEVER runs inside a query (§8). A miss returns UNKNOWN and enqueues;\n * the worker fills it in. That is what keeps the p99 target reachable, and it is\n * also why the miss path has to be honest rather than optimistic.\n */\nimport { createHash } from 'node:crypto';\nimport { and, desc, eq } from 'drizzle-orm';\nimport { cached } from '../core/cache';\nimport type { Database } from '../db/client';\nimport { claims, entities, observations, symbols } from '../db/schema';\nimport type { SymbolRow } from '../db/schema';\nimport { enqueueSurface, surfaceRef } from '../db/surface';\nimport { canonicalKey, type Verdict } from '../graph/types';\nimport { diffSurfaces } from '../surface/diff';\nimport type { ExtractedSurface, ExtractionTier, SurfaceSymbol } from '../surface/types';\n\nexport interface ResolveSurfaceInput {\n package: string;\n version?: string | null;\n}\n\nexport interface SurfaceResponse {\n package: string;\n version: string | null;\n verdict: Verdict;\n class: 'declared' | 'executed' | 'derived' | null;\n tier: ExtractionTier | null;\n symbols: { path: string; kind: string; arity: number | null; deprecated: boolean }[];\n /** Always populated: a caller must be able to tell a thin answer from a full one. */\n coverageNote: string;\n observedAt: string | null;\n}\n\n/** Stored rows → the extractor's IR, so the diff logic has exactly one implementation. */\nfunction rowsToSurface(\n pkg: string,\n version: string | null,\n rows: SymbolRow[],\n tier: ExtractionTier,\n): ExtractedSurface {\n const symbolsOut: SurfaceSymbol[] = rows.map((r) => ({\n path: r.path,\n kind: r.kind,\n arity: r.arity,\n origin: r.origin as SurfaceSymbol['origin'],\n deprecated: r.deprecated,\n tier: r.tier,\n ...(r.sourceFile ? { sourceRef: { file: r.sourceFile, line: r.sourceLine ?? 0 } } : {}),\n }));\n return {\n package: pkg,\n version,\n tier,\n entry: null,\n symbols: symbolsOut,\n filesWalked: 0,\n externalReExports: [],\n };\n}\n\ninterface StoredSurface {\n entityId: number;\n rows: SymbolRow[];\n verdict: Verdict;\n class: SurfaceResponse['class'];\n tier: ExtractionTier | null;\n observedAt: string | null;\n}\n\n/** Look up a stored surface plus the observation that established it. */\nasync function loadStored(\n db: Database,\n pkg: string,\n version: string | null,\n tenantId = 0,\n): Promise<StoredSurface | null> {\n // Surfaces are always STORED under a concrete resolved version, so a query\n // with no version can never match by canonical key. An agent asking \"what does\n // zod export?\" without pinning is the common call, so fall back to the most\n // recently observed version of that package.\n let entity;\n if (version === null) {\n const rows = await db\n .select({ e: entities, at: observations.observedAt })\n .from(entities)\n .innerJoin(claims, eq(claims.subjectId, entities.id))\n .innerJoin(observations, eq(observations.claimId, claims.id))\n .where(and(eq(entities.kind, 'package_surface'), eq(entities.name, pkg)))\n .orderBy(desc(observations.observedAt))\n .limit(1);\n entity = rows.find((r) => r.e.tenantId === tenantId)?.e;\n } else {\n const key = canonicalKey(surfaceRef(pkg, version));\n const ents = await db.select().from(entities).where(eq(entities.canonicalKey, key)).limit(2);\n entity = ents.find((e) => e.tenantId === tenantId);\n }\n if (!entity) return null;\n\n const obs = await db\n .select({ o: observations })\n .from(observations)\n .innerJoin(claims, eq(observations.claimId, claims.id))\n .where(eq(claims.subjectId, entity.id))\n .orderBy(desc(observations.observedAt))\n .limit(1);\n const latest = obs[0]?.o ?? null;\n const rows = await db.select().from(symbols).where(eq(symbols.entityId, entity.id));\n\n return {\n entityId: entity.id,\n rows,\n verdict: latest?.verdict ?? 'unknown',\n class: latest?.class ?? null,\n tier: latest?.tier ?? null,\n observedAt: latest?.observedAt ? latest.observedAt.toISOString() : null,\n };\n}\n\nconst MISS: Omit<SurfaceResponse, 'package' | 'version'> = {\n verdict: 'unknown',\n class: null,\n tier: null,\n symbols: [],\n coverageNote: 'not yet extracted — queued; retry shortly. This is NOT evidence of absence.',\n observedAt: null,\n};\n\n/** Short stable cache key. */\nfunction ckey(parts: unknown): string {\n return createHash('sha1').update(JSON.stringify(parts)).digest('hex').slice(0, 24);\n}\n\n/**\n * §8 requires p99 < 150 ms for cached reads, so the read path is cached — but a\n * MISS is never cached. The worker is about to fill it in, and a cached UNKNOWN\n * would keep answering \"not extracted\" long after it was.\n */\nexport async function handleResolveSurface(\n db: Database,\n input: ResolveSurfaceInput,\n): Promise<SurfaceResponse> {\n return cached(\n 'resolve_surface',\n ckey([input.package, input.version ?? null]),\n () => resolveSurfaceUncached(db, input),\n { skipCache: (v) => v.verdict === 'unknown' },\n );\n}\n\nasync function resolveSurfaceUncached(\n db: Database,\n input: ResolveSurfaceInput,\n): Promise<SurfaceResponse> {\n const version = input.version ?? null;\n const stored = await loadStored(db, input.package, version);\n\n if (!stored || (stored.verdict === 'unknown' && stored.rows.length === 0)) {\n // §8: never extract inside a query. Enqueue and answer honestly.\n await enqueueSurface(db, input.package, version).catch(() => {});\n return { package: input.package, version, ...MISS };\n }\n\n if (stored.verdict === 'undeclared') {\n return {\n package: input.package,\n version,\n verdict: 'undeclared',\n class: stored.class,\n tier: stored.tier,\n symbols: [],\n coverageNote:\n 'package ships no artifact this tier can read — UNDECLARED, which is a measurement gap, not an empty API',\n observedAt: stored.observedAt,\n };\n }\n\n // Runtime surface only: type-only exports break `tsc`, not `node`, and an\n // external re-export is not this package's surface (§6.4.1, §6.4.4).\n const runtime = stored.rows.filter((r) => r.kind !== 'type_only' && r.origin === 'local');\n const excluded = stored.rows.length - runtime.length;\n\n return {\n package: input.package,\n version,\n verdict: stored.verdict,\n class: stored.class,\n tier: stored.tier,\n symbols: runtime.map((r) => ({\n path: r.path,\n kind: r.kind,\n arity: r.arity,\n deprecated: r.deprecated,\n })),\n coverageNote:\n `${runtime.length} runtime symbol(s)` +\n (excluded ? `; ${excluded} excluded as type-only or re-exported from another package` : '') +\n (stored.tier === 'shipped_js_ast'\n ? '. Runtime existence only — signatures require tier C.'\n : ''),\n observedAt: stored.observedAt,\n };\n}\n\nexport interface DiffSurfaceInput {\n package: string;\n fromVersion: string;\n toVersion: string;\n}\n\nexport async function handleDiffSurface(db: Database, input: DiffSurfaceInput) {\n return cached(\n 'diff_surface',\n ckey([input.package, input.fromVersion, input.toVersion]),\n () => diffSurfaceUncached(db, input),\n { skipCache: (v) => v.verdict === 'unknown' },\n );\n}\n\nasync function diffSurfaceUncached(db: Database, input: DiffSurfaceInput) {\n const [a, b] = await Promise.all([\n loadStored(db, input.package, input.fromVersion),\n loadStored(db, input.package, input.toVersion),\n ]);\n\n const missing: string[] = [];\n if (!a || a.rows.length === 0) missing.push(input.fromVersion);\n if (!b || b.rows.length === 0) missing.push(input.toVersion);\n if (missing.length) {\n for (const v of missing) await enqueueSurface(db, input.package, v).catch(() => {});\n return {\n package: input.package,\n fromVersion: input.fromVersion,\n toVersion: input.toVersion,\n verdict: 'unknown' as const,\n inconclusive: `no extracted surface for ${missing.join(', ')} — queued; retry shortly. NOT evidence that symbols were removed.`,\n removed: [],\n added: [],\n arityChanged: [],\n typeOnlyRemoved: [],\n // Present-but-empty like every other list above, so a miss and a hit have\n // the same shape and callers never have to branch on which one they got.\n deprecated: [],\n observedAt: null,\n };\n }\n\n const diff = diffSurfaces(\n rowsToSurface(input.package, input.fromVersion, a!.rows, a!.tier ?? 'shipped_js_ast'),\n rowsToSurface(input.package, input.toVersion, b!.rows, b!.tier ?? 'shipped_js_ast'),\n );\n\n return {\n package: input.package,\n fromVersion: input.fromVersion,\n toVersion: input.toVersion,\n verdict: (diff.inconclusive ? 'unknown' : 'verified_true') as Verdict,\n class: 'derived' as const,\n tier: diff.tier,\n ...(diff.inconclusive ? { inconclusive: diff.inconclusive } : {}),\n /** Breaks `node`. */\n removed: diff.removed.map((s) => ({ path: s.path, kind: s.kind, arity: s.arity })),\n added: diff.added.map((s) => ({ path: s.path, kind: s.kind })),\n arityChanged: diff.arityChanged,\n /** Breaks `tsc`, NOT `node` — returned separately on purpose (§8.1). */\n typeOnlyRemoved: diff.typeOnlyRemoved.map((s) => s.path),\n deprecated: diff.deprecated.map((s) => s.path),\n observedAt: b!.observedAt,\n };\n}\n","/** Read/write helpers for the compatibility matrix (`compat_edges`). */\nimport { and, eq, inArray, sql, type SQLWrapper } from 'drizzle-orm';\nimport type { DependencyRanges, PeerMeta } from '../core/types';\nimport type { Database } from './client';\nimport {\n compatEdges,\n compatVerifyQueue,\n packages,\n resolvedClosures,\n type CompatEdgeRow,\n type CompatVerifyQueueRow,\n type NewCompatEdgeRow,\n type ResolvedClosureRow,\n} from './schema';\n\nexport interface CompatMetadataRow {\n name: string;\n latestVersion: string | null;\n peerDependencies: DependencyRanges | null;\n peerDependenciesMeta: PeerMeta | null;\n engines: DependencyRanges | null;\n}\n\n/** Tier-1 compatibility metadata for a set of packages — one indexed query. */\nexport async function getCompatMetadata(\n db: Database,\n names: string[],\n): Promise<CompatMetadataRow[]> {\n if (names.length === 0) return [];\n return db\n .select({\n name: packages.name,\n latestVersion: packages.latestVersion,\n peerDependencies: packages.peerDependencies,\n peerDependenciesMeta: packages.peerDependenciesMeta,\n engines: packages.engines,\n })\n .from(packages)\n .where(inArray(packages.name, names));\n}\n\n/** Order a pair canonically by package name so (A,B) and (B,A) dedupe to one row. */\nexport function canonicalPair(\n a: { name: string; version: string },\n b: { name: string; version: string },\n): { packageA: string; versionA: string; packageB: string; versionB: string } {\n const [low, high] = a.name <= b.name ? [a, b] : [b, a];\n return { packageA: low.name, versionA: low.version, packageB: high.name, versionB: high.version };\n}\n\n/** Provenance rank as SQL, mirroring PROVENANCE_RANK (§4B). Higher wins. */\nfunction provenanceRank(col: SQLWrapper) {\n return sql`case ${col} when 'conflict' then 3 when 'verified' then 2 when 'observed' then 1 else 0 end`;\n}\n\n/** The provenance-precedence conflict SET, shared by single + batch upsert (§4B).\n * witness_count accumulates; status/provenance/driver/ranAt update only when the\n * incoming edge is at least as strong, so a mined `observed` never erases a\n * sandbox `verified`/`conflict`. Encodes conflict > verified > observed > declared. */\nfunction conflictSet() {\n const incomingWins = sql`${provenanceRank(sql`excluded.provenance`)} >= ${provenanceRank(compatEdges.provenance)}`;\n return {\n status: sql`case when ${incomingWins} then excluded.status else ${compatEdges.status} end`,\n provenance: sql`case when ${incomingWins} then excluded.provenance else ${compatEdges.provenance} end`,\n driver: sql`case when ${incomingWins} then excluded.driver else ${compatEdges.driver} end`,\n ranAt: sql`case when ${incomingWins} then excluded.ran_at else ${compatEdges.ranAt} end`,\n witnessCount: sql`${compatEdges.witnessCount} + excluded.witness_count`,\n };\n}\n\nconst CONFLICT_TARGET = [\n compatEdges.packageA,\n compatEdges.versionA,\n compatEdges.packageB,\n compatEdges.versionB,\n] as const;\n\nexport async function upsertCompatEdge(db: Database, edge: NewCompatEdgeRow): Promise<void> {\n await db\n .insert(compatEdges)\n .values(edge)\n .onConflictDoUpdate({ target: [...CONFLICT_TARGET], set: conflictSet() });\n}\n\n/** Max rows per compat_edges INSERT. Fat closures (10k+ pairs) must not become\n * one mega-statement — that OOMs Node and trips Postgres param limits. Chunks\n * lose per-closure atomicity; fine for loss-tolerant `observed` mints. */\nexport const EDGE_UPSERT_CHUNK = 250;\n\n/** Split `items` into consecutive slices of at most `size`. Exported for tests. */\nexport function chunk<T>(items: T[], size: number): T[][] {\n if (size <= 0) throw new Error(`chunk size must be positive, got ${size}`);\n const out: T[][] = [];\n for (let i = 0; i < items.length; i += size) out.push(items.slice(i, i + size));\n return out;\n}\n\n/**\n * Batch-upsert edges (§4F write-behind for high-volume, loss-tolerant `observed`\n * mints). Writes in chunks of {@link EDGE_UPSERT_CHUNK} so large closures stay\n * within Postgres bind limits and Drizzle AST depth. The caller MUST pass a\n * batch with unique conflict keys (Postgres rejects the same ON CONFLICT target\n * twice per statement) — one resolved closure's canonical pairs are unique by\n * construction; each chunk inherits that. Same precedence as the single upsert;\n * verified/conflict/score writes stay individual (durable).\n */\nexport async function upsertCompatEdgesBatch(db: Database, edges: NewCompatEdgeRow[]): Promise<void> {\n if (edges.length === 0) return;\n for (const part of chunk(edges, EDGE_UPSERT_CHUNK)) {\n await db\n .insert(compatEdges)\n .values(part)\n .onConflictDoUpdate({ target: [...CONFLICT_TARGET], set: conflictSet() });\n }\n}\n\n/**\n * Upsert for the daily re-mine pass (§4B trigger 2). That pass re-reads the\n * *same* persisted closures with no network, so it has genuine news only about\n * pairs it has never seen before. An existing same-or-stronger edge is therefore\n * left completely untouched:\n *\n * - no witness bump. `witness_count` is documented as \"distinct resolved graphs\n * an edge was witnessed in\", but accruing +1 per pass made it count *cron\n * runs*: 47.1M updates against 1.31M rows, a median stored value of 29 where\n * the true count is 1, and 54% of edges advertising >5 witnesses for a single\n * resolved graph.\n * - no `ran_at` refresh. The evidence is as old as the closure it came from,\n * not as new as the pass that re-read it.\n *\n * `setWhere` is what makes skipping a *real* no-write: Postgres writes a new row\n * version for `DO UPDATE` even when every assigned value is identical, so the\n * predicate — not the SET list — is what keeps 97% of these writes off the disk.\n * Because it fires only when the incoming edge *strictly* outranks the stored\n * one, the SET can assign unconditionally: a weaker `declared` edge is still\n * upgraded to `observed`, while `verified`/`conflict` are never downgraded.\n */\nexport async function upsertObservedEdgesRemine(\n db: Database,\n edges: NewCompatEdgeRow[],\n): Promise<void> {\n if (edges.length === 0) return;\n for (const part of chunk(edges, EDGE_UPSERT_CHUNK)) {\n await db\n .insert(compatEdges)\n .values(part)\n .onConflictDoUpdate({\n target: [...CONFLICT_TARGET],\n set: {\n status: sql`excluded.status`,\n provenance: sql`excluded.provenance`,\n driver: sql`excluded.driver`,\n ranAt: sql`excluded.ran_at`,\n },\n setWhere: sql`${provenanceRank(sql`excluded.provenance`)} > ${provenanceRank(compatEdges.provenance)}`,\n });\n }\n}\n\n/** Persist a resolved closure once (§4B); refresh nodes if the version reappears\n * (a republish under the same version — rare, but keep the freshest). */\nexport async function persistClosure(\n db: Database,\n packageName: string,\n version: string,\n nodes: { name: string; version: string }[],\n): Promise<void> {\n await db\n .insert(resolvedClosures)\n .values({ packageName, version, nodes })\n .onConflictDoUpdate({\n target: [resolvedClosures.packageName, resolvedClosures.version],\n set: { nodes, fetchedAt: new Date() },\n });\n}\n\n/** All persisted closures — the daily re-mine pass reads these with no network. */\nexport async function getAllClosures(db: Database): Promise<ResolvedClosureRow[]> {\n return db.select().from(resolvedClosures);\n}\n\n/** All stored edges whose both endpoints are within the given package names. */\nexport async function getCompatEdges(db: Database, names: string[]): Promise<CompatEdgeRow[]> {\n if (names.length === 0) return [];\n return db\n .select()\n .from(compatEdges)\n .where(and(inArray(compatEdges.packageA, names), inArray(compatEdges.packageB, names)));\n}\n\n// ── Pure pair helpers (§4C) ──────────────────────────────────────────────────\n\n/** Canonical `a|b` key for a name pair, order-independent. */\nexport function pairKey(a: string, b: string): string {\n return a <= b ? `${a}|${b}` : `${b}|${a}`;\n}\n\n/** True if every C(K,2) pair in a batch already has an edge in `covered`. */\nexport function fullyCovered(batch: string[], covered: Set<string>): boolean {\n for (let i = 0; i < batch.length; i++) {\n for (let j = i + 1; j < batch.length; j++) {\n if (!covered.has(pairKey(batch[i]!, batch[j]!))) return false;\n }\n }\n return true;\n}\n\n/** Canonical order-independent key for a whole package set (queue dedup). */\nexport function compatSetKey(names: string[]): string {\n return [...new Set(names)].sort().join('|');\n}\n\n// ── Demand-driven compat-verify queue (§4C) ──────────────────────────────────\n\n/** Queue a package set for background sandbox co-install. Deduped on the set key,\n * so repeated queries for the same unverified set enqueue exactly one run.\n * Returns true if a new row was inserted. */\nexport async function enqueueCompatVerify(db: Database, names: string[]): Promise<boolean> {\n const packages = [...new Set(names)].filter(Boolean);\n if (packages.length < 2) return false;\n const inserted = await db\n .insert(compatVerifyQueue)\n .values({ setKey: compatSetKey(packages), packages })\n .onConflictDoNothing({ target: compatVerifyQueue.setKey })\n .returning({ id: compatVerifyQueue.id });\n return inserted.length > 0;\n}\n\n/** Oldest-first pending verify requests (FIFO fairness). */\nexport async function getPendingCompatVerify(\n db: Database,\n limit: number,\n): Promise<CompatVerifyQueueRow[]> {\n return db\n .select()\n .from(compatVerifyQueue)\n .orderBy(compatVerifyQueue.requestedAt)\n .limit(limit);\n}\n\nexport async function deleteCompatVerify(db: Database, id: number): Promise<void> {\n await db.delete(compatVerifyQueue).where(eq(compatVerifyQueue.id, id));\n}\n\n/** Bump attempt count; returns the new count so the caller can drop a stuck set. */\nexport async function bumpCompatVerifyAttempt(db: Database, id: number): Promise<number> {\n const [row] = await db\n .update(compatVerifyQueue)\n .set({ attempts: sql`${compatVerifyQueue.attempts} + 1` })\n .where(eq(compatVerifyQueue.id, id))\n .returning({ attempts: compatVerifyQueue.attempts });\n return row?.attempts ?? 0;\n}\n","/**\n * Shared HTTP layer (§17). One wrapper for every external call:\n * - per-host rate limiting (max concurrency + minimum gap between starts),\n * - exponential backoff on 429 / 5xx (respecting Retry-After),\n * - in-run (memory) cache + persistent on-disk cache with per-source TTLs.\n *\n * Source clients pass a `ttlMs` (the per-source TTL from §17) and a `host`\n * bucket. `ttlMs: 0` disables caching (used for liveness checks like `verify`).\n */\nimport { createHash } from 'node:crypto';\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { existsSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\nimport { logger } from './logger';\n\nexport class HttpError extends Error {\n constructor(\n message: string,\n readonly status: number,\n readonly url: string,\n ) {\n super(message);\n this.name = 'HttpError';\n }\n}\n\nexport interface HttpOptions {\n /** Rate-limit bucket key, usually the hostname. */\n host: string;\n /** Persistent cache TTL in ms. 0 disables read+write caching. */\n ttlMs: number;\n method?: 'GET' | 'POST';\n headers?: Record<string, string>;\n body?: string;\n accept?: 'json' | 'text';\n timeoutMs?: number;\n retries?: number;\n /** Override the cache key (e.g. to keep auth tokens out of the key). */\n cacheKey?: string;\n /** Injected for tests. Defaults to global fetch. */\n fetchImpl?: typeof fetch;\n}\n\nexport interface HttpResponse<T> {\n status: number;\n data: T;\n fromCache: boolean;\n}\n\n// ── Per-host rate limiting ──────────────────────────────────────────────────\n\ninterface HostConfig {\n maxConcurrent: number;\n minIntervalMs: number;\n}\n\nconst DEFAULT_HOST_CONFIG: HostConfig = { maxConcurrent: 6, minIntervalMs: 0 };\n\nconst HOST_CONFIG: Record<string, HostConfig> = {\n 'api.github.com': { maxConcurrent: 4, minIntervalMs: 50 },\n 'registry.npmjs.org': { maxConcurrent: 4, minIntervalMs: 50 },\n // The downloads API rate-limits aggressively — serialize with a steady gap.\n // Weekly downloads go through the bulk endpoint; only growth hits this often.\n 'api.npmjs.org': { maxConcurrent: 1, minIntervalMs: 250 },\n 'api.deps.dev': { maxConcurrent: 4, minIntervalMs: 40 },\n 'raw.githubusercontent.com': { maxConcurrent: 4, minIntervalMs: 30 },\n // Bundlephobia is slow/flaky — be gentle (§9.5).\n 'bundlephobia.com': { maxConcurrent: 2, minIntervalMs: 200 },\n};\n\nclass HostLimiter {\n private active = 0;\n private nextAvailable = 0;\n private queue: Array<() => void> = [];\n\n constructor(private readonly config: HostConfig) {}\n\n async acquire(): Promise<void> {\n if (this.active >= this.config.maxConcurrent) {\n await new Promise<void>((resolve) => this.queue.push(resolve));\n }\n this.active++;\n const now = Date.now();\n const wait = Math.max(0, this.nextAvailable - now);\n this.nextAvailable = Math.max(now, this.nextAvailable) + this.config.minIntervalMs;\n if (wait > 0) await delay(wait);\n }\n\n release(): void {\n this.active--;\n const next = this.queue.shift();\n if (next) next();\n }\n}\n\nconst limiters = new Map<string, HostLimiter>();\n\nfunction limiterFor(host: string): HostLimiter {\n let limiter = limiters.get(host);\n if (!limiter) {\n limiter = new HostLimiter(HOST_CONFIG[host] ?? DEFAULT_HOST_CONFIG);\n limiters.set(host, limiter);\n }\n return limiter;\n}\n\n// ── Caching ─────────────────────────────────────────────────────────────────\n\ninterface CacheEntry {\n fetchedAt: number;\n status: number;\n body: string;\n}\n\n/**\n * In-run memo in front of the disk cache. Bounded: the hosted server fetches\n * packuments for arbitrary packages over a process lifetime measured in weeks,\n * and packument bodies run to megabytes — unbounded, this is the box's OOM.\n * Map preserves insertion order, so deleting the first key evicts the oldest\n * (re-inserting on hit makes it LRU rather than FIFO).\n * ponytail: count-bounded, not byte-bounded. Swap in a byte budget only if\n * profiling shows entry size, not entry count, is what runs the heap up.\n */\nconst MEMORY_CACHE_MAX = 500;\nconst memoryCache = new Map<string, CacheEntry>();\n\nfunction memoryCacheSet(key: string, entry: CacheEntry): void {\n memoryCache.delete(key);\n memoryCache.set(key, entry);\n if (memoryCache.size > MEMORY_CACHE_MAX) {\n const oldest = memoryCache.keys().next();\n if (!oldest.done) memoryCache.delete(oldest.value);\n }\n}\n\n/** When true, cache reads are skipped (writes still happen). Used by `sync --full`. */\nlet bypassCacheRead = false;\n\n/** Force fresh fetches (ignore cache TTLs) while still refreshing the cache. */\nexport function setCacheBypassRead(value: boolean): void {\n bypassCacheRead = value;\n}\n\nfunction cacheDir(): string {\n return process.env.LURQ_CACHE_DIR ?? join(homedir(), '.cache', 'lurq', 'http');\n}\n\nfunction cacheFile(key: string): string {\n const hash = createHash('sha256').update(key).digest('hex');\n return join(cacheDir(), `${hash}.json`);\n}\n\nasync function readCache(key: string, ttlMs: number): Promise<CacheEntry | undefined> {\n const now = Date.now();\n const mem = memoryCache.get(key);\n if (mem && now - mem.fetchedAt < ttlMs) {\n memoryCacheSet(key, mem); // touch: most-recently-used moves to the back\n return mem;\n }\n\n const file = cacheFile(key);\n if (!existsSync(file)) return undefined;\n try {\n const entry = JSON.parse(await readFile(file, 'utf8')) as CacheEntry;\n if (now - entry.fetchedAt < ttlMs) {\n memoryCacheSet(key, entry);\n return entry;\n }\n } catch {\n /* corrupt cache file — ignore and refetch */\n }\n return undefined;\n}\n\nasync function writeCache(key: string, entry: CacheEntry): Promise<void> {\n memoryCacheSet(key, entry);\n const file = cacheFile(key);\n try {\n await mkdir(dirname(file), { recursive: true });\n await writeFile(file, JSON.stringify(entry), 'utf8');\n } catch (err) {\n logger.debug(`http cache write failed: ${(err as Error).message}`);\n }\n}\n\n// ── Core request ────────────────────────────────────────────────────────────\n\nconst RETRYABLE = new Set([429, 500, 502, 503, 504]);\n\nexport async function httpRequest<T = unknown>(\n url: string,\n opts: HttpOptions,\n): Promise<HttpResponse<T>> {\n const {\n host,\n ttlMs,\n method = 'GET',\n headers = {},\n body,\n accept = 'json',\n timeoutMs = 15_000,\n retries = 3,\n fetchImpl = fetch,\n } = opts;\n const key = opts.cacheKey ?? `${method} ${url} ${body ?? ''}`;\n\n if (ttlMs > 0 && !bypassCacheRead) {\n const cached = await readCache(key, ttlMs);\n if (cached) {\n return { status: cached.status, data: decode<T>(cached.body, accept), fromCache: true };\n }\n }\n\n const limiter = limiterFor(host);\n let lastErr: unknown;\n\n for (let attempt = 0; attempt <= retries; attempt++) {\n await limiter.acquire();\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const res = await fetchImpl(url, { method, headers, body, signal: controller.signal });\n const text = await res.text();\n\n if (res.ok) {\n if (ttlMs > 0) await writeCache(key, { fetchedAt: Date.now(), status: res.status, body: text });\n return { status: res.status, data: decode<T>(text, accept), fromCache: false };\n }\n\n // Non-2xx\n if (RETRYABLE.has(res.status) && attempt < retries) {\n const retryAfter = parseRetryAfter(res.headers.get('retry-after'));\n await delay(retryAfter ?? backoff(attempt));\n lastErr = new HttpError(`HTTP ${res.status} for ${url}`, res.status, url);\n continue;\n }\n throw new HttpError(`HTTP ${res.status} for ${url}`, res.status, url);\n } catch (err) {\n lastErr = err;\n const isAbort = err instanceof Error && err.name === 'AbortError';\n const isHttp = err instanceof HttpError;\n // Retry network/timeout errors; don't retry non-retryable HTTP statuses.\n if (isHttp && !RETRYABLE.has(err.status)) throw err;\n if (attempt < retries) {\n await delay(backoff(attempt));\n continue;\n }\n if (isAbort) throw new HttpError(`Timeout after ${timeoutMs}ms for ${url}`, 0, url);\n } finally {\n clearTimeout(timer);\n limiter.release();\n }\n }\n throw lastErr instanceof Error ? lastErr : new HttpError(`Request failed for ${url}`, 0, url);\n}\n\nexport async function httpGetJson<T = unknown>(\n url: string,\n opts: Omit<HttpOptions, 'accept' | 'method'>,\n): Promise<HttpResponse<T>> {\n return httpRequest<T>(url, { ...opts, method: 'GET', accept: 'json' });\n}\n\n// ── Helpers ─────────────────────────────────────────────────────────────────\n\nfunction decode<T>(text: string, accept: 'json' | 'text'): T {\n if (accept === 'text') return text as unknown as T;\n return (text ? JSON.parse(text) : null) as T;\n}\n\nfunction backoff(attempt: number): number {\n const base = 500 * 2 ** attempt;\n return base + Math.floor(((attempt * 137) % 100) * 3); // small deterministic jitter\n}\n\nfunction parseRetryAfter(value: string | null): number | undefined {\n if (!value) return undefined;\n const seconds = Number(value);\n if (!Number.isNaN(seconds)) return seconds * 1000;\n const date = Date.parse(value);\n return Number.isNaN(date) ? undefined : Math.max(0, date - Date.now());\n}\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/** Test helper: clear the in-memory cache and per-host limiters. */\nexport function __resetHttpStateForTests(): void {\n memoryCache.clear();\n limiters.clear();\n}\n","/**\n * npm registry client (§9.1). Base metadata: version, description, license,\n * repository, publish times, deprecation, maintainers, README.\n */\nimport { CACHE_TTL } from '../../core/constants';\nimport { httpGetJson } from '../../core/http';\nimport type { NpmRegistryData } from '../types';\n\nconst HOST = 'registry.npmjs.org';\n\n/** Encode a package name for a registry URL (scoped names need `/` → `%2F`). */\nexport function encodeNpmName(name: string): string {\n return name.startsWith('@') ? name.replace('/', '%2F') : name;\n}\n\n/** Extract `{ owner, repo }` from any GitHub repository URL form. */\nexport function parseGithubRepo(\n url: string | null | undefined,\n): { owner: string; repo: string } | null {\n if (!url) return null;\n const match = url.match(/github\\.com[/:]([^/]+)\\/([^/#?]+?)(?:\\.git)?(?:[/#?].*)?$/i);\n if (!match) return null;\n const owner = match[1];\n const repo = match[2];\n if (!owner || !repo) return null;\n return { owner, repo };\n}\n\nfunction normalizeRepoUrl(\n repository: unknown,\n homepage: string | null,\n): { repoUrl: string | null; repo: { owner: string; repo: string } | null } {\n let raw: string | null = null;\n if (typeof repository === 'string') raw = repository;\n else if (repository && typeof repository === 'object' && 'url' in repository) {\n raw = String((repository as { url: unknown }).url);\n }\n const repo = parseGithubRepo(raw) ?? parseGithubRepo(homepage);\n const repoUrl = repo ? `https://github.com/${repo.owner}/${repo.repo}` : (cleanUrl(raw) ?? null);\n return { repoUrl, repo };\n}\n\nfunction cleanUrl(url: string | null): string | null {\n if (!url) return null;\n return url\n .replace(/^git\\+/, '')\n .replace(/^git:\\/\\//, 'https://')\n .replace(/\\.git$/, '');\n}\n\nfunction pickLicense(value: unknown): string | null {\n if (!value) return null;\n if (typeof value === 'string') return value;\n if (typeof value === 'object' && 'type' in value) return String((value as { type: unknown }).type);\n return null;\n}\n\nfunction toDate(value: unknown): Date | null {\n if (typeof value !== 'string') return null;\n const ms = Date.parse(value);\n return Number.isNaN(ms) ? null : new Date(ms);\n}\n\nexport function parseNpmRegistry(json: any): NpmRegistryData {\n const latest: string | null = json?.['dist-tags']?.latest ?? null;\n const latestManifest = latest ? (json?.versions?.[latest] ?? {}) : {};\n const time = json?.time ?? {};\n\n const repository = json?.repository ?? latestManifest?.repository;\n const homepage = json?.homepage ?? latestManifest?.homepage ?? null;\n const { repoUrl, repo } = normalizeRepoUrl(repository, homepage);\n\n const deprecated = Boolean(latestManifest?.deprecated ?? json?.deprecated);\n const maintainers = Array.isArray(json?.maintainers) ? json.maintainers.length : null;\n const name: string = json?.name ?? '';\n\n return {\n name,\n description: json?.description ?? latestManifest?.description ?? null,\n latestVersion: latest,\n license: pickLicense(json?.license ?? latestManifest?.license),\n homepage,\n repo,\n repoUrl,\n firstPublishedAt: toDate(time?.created),\n lastReleaseAt: toDate(latest ? time?.[latest] : null) ?? toDate(time?.modified),\n deprecated,\n maintainersCount: maintainers,\n readme: typeof json?.readme === 'string' ? json.readme : null,\n keywords: parseKeywords(json?.keywords ?? latestManifest?.keywords),\n hasTypes: detectTypes(name, latestManifest),\n hasTestScript: detectTestScript(latestManifest),\n directDependenciesCount: countDeps(latestManifest?.dependencies),\n hasProvenance: detectProvenance(latestManifest),\n hasInstallScripts: detectInstallScripts(latestManifest),\n peerDependencies: parseDepMap(latestManifest?.peerDependencies),\n peerDependenciesMeta: parsePeerMeta(latestManifest?.peerDependenciesMeta),\n engines: parseDepMap(latestManifest?.engines),\n versionTimeline: parseVersionTimeline(json),\n };\n}\n\n/** A manifest dependency/engines map → a clean { name: range } record, or null. */\nfunction parseDepMap(value: unknown): Record<string, string> | null {\n if (!value || typeof value !== 'object') return null;\n const out: Record<string, string> = {};\n for (const [name, range] of Object.entries(value as Record<string, unknown>)) {\n if (typeof range === 'string' && range.trim() !== '') out[name] = range;\n }\n return Object.keys(out).length ? out : null;\n}\n\n/** `peerDependenciesMeta` → { name: { optional } }, or null. */\nfunction parsePeerMeta(value: unknown): Record<string, { optional?: boolean }> | null {\n if (!value || typeof value !== 'object') return null;\n const out: Record<string, { optional?: boolean }> = {};\n for (const [name, meta] of Object.entries(value as Record<string, unknown>)) {\n if (meta && typeof meta === 'object' && 'optional' in meta) {\n out[name] = { optional: Boolean((meta as { optional?: unknown }).optional) };\n }\n }\n return Object.keys(out).length ? out : null;\n}\n\n/** Lifecycle install hooks run arbitrary code at install time. We surface their\n * presence; deeper analysis belongs in the sandbox tier. */\nfunction detectInstallScripts(manifest: any): boolean {\n const scripts = manifest?.scripts;\n if (!scripts || typeof scripts !== 'object') return false;\n return ['preinstall', 'install', 'postinstall'].some(\n (hook) => typeof scripts[hook] === 'string' && scripts[hook].trim() !== '',\n );\n}\n\n/**\n * The published-version timeline from the packument: every key in `versions`\n * paired with its publish date from `time`, newest first. The `time` map also\n * holds `created`/`modified` sentinels, which we skip.\n */\nexport function parseVersionTimeline(json: any): { version: string; publishedAt: Date | null }[] {\n const versions = json?.versions;\n if (!versions || typeof versions !== 'object') return [];\n const time = json?.time ?? {};\n return Object.keys(versions)\n .map((version) => ({ version, publishedAt: toDate(time?.[version]) }))\n .sort((a, b) => (b.publishedAt?.getTime() ?? 0) - (a.publishedAt?.getTime() ?? 0));\n}\n\nfunction parseKeywords(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return value.filter((k): k is string => typeof k === 'string');\n}\n\n/** Ships types if the manifest declares `types`/`typings`, or it IS an @types pkg. */\nfunction detectTypes(name: string, manifest: any): boolean {\n if (typeof manifest?.types === 'string' || typeof manifest?.typings === 'string') return true;\n if (name.startsWith('@types/')) return true;\n // `exports` map with a `types` condition (modern dual-package layout).\n const exportsField = manifest?.exports;\n if (exportsField && typeof exportsField === 'object') {\n const serialized = JSON.stringify(exportsField);\n if (serialized.includes('\"types\"')) return true;\n }\n return false;\n}\n\n/** A real test script — npm's `init` leaves a placeholder we must not count. */\nfunction detectTestScript(manifest: any): boolean {\n const test = manifest?.scripts?.test;\n if (typeof test !== 'string' || test.trim() === '') return false;\n return !/no test specified/i.test(test);\n}\n\nfunction countDeps(deps: unknown): number | null {\n if (!deps || typeof deps !== 'object') return 0;\n return Object.keys(deps as Record<string, unknown>).length;\n}\n\n/** npm provenance leaves a signed attestation on the published dist. */\nfunction detectProvenance(manifest: any): boolean {\n return Boolean(manifest?.dist?.attestations);\n}\n\nexport async function fetchNpmRegistry(\n name: string,\n fetchImpl?: typeof fetch,\n): Promise<NpmRegistryData> {\n const url = `https://${HOST}/${encodeNpmName(name)}`;\n const { data } = await httpGetJson<any>(url, {\n host: HOST,\n ttlMs: CACHE_TTL.npmRegistry,\n fetchImpl,\n });\n return parseNpmRegistry(data);\n}\n\n/**\n * Compat metadata for a specific published version (peers + engines).\n *\n * `latest` is used only when no version was requested. A version that was\n * requested but isn't published returns null rather than silently answering\n * about `latest` — otherwise `compat` would grade a different stack than the\n * caller pinned, and the caller would have no way to tell.\n */\nexport async function fetchNpmCompatAtVersion(\n name: string,\n version: string | null | undefined,\n fetchImpl?: typeof fetch,\n): Promise<{\n version: string | null;\n peerDependencies: Record<string, string> | null;\n peerDependenciesMeta: Record<string, { optional?: boolean }> | null;\n engines: Record<string, string> | null;\n} | null> {\n const url = `https://${HOST}/${encodeNpmName(name)}`;\n try {\n const { data } = await httpGetJson<any>(url, {\n host: HOST,\n ttlMs: CACHE_TTL.npmRegistry,\n fetchImpl,\n });\n const latest: string | null = data?.['dist-tags']?.latest ?? null;\n const wanted = version\n ? (data?.versions?.[version] ? version : null)\n : latest && data?.versions?.[latest]\n ? latest\n : null;\n if (!wanted) return null;\n const manifest = data.versions[wanted] ?? {};\n return {\n version: wanted,\n peerDependencies: parseDepMap(manifest.peerDependencies),\n peerDependenciesMeta: parsePeerMeta(manifest.peerDependenciesMeta),\n engines: parseDepMap(manifest.engines),\n };\n } catch {\n return null;\n }\n}\n\n/** Live existence check for `verify` (§12.3.4) — bypasses cache. */\nexport async function npmPackageExists(name: string, fetchImpl?: typeof fetch): Promise<boolean> {\n const url = `https://${HOST}/${encodeNpmName(name)}`;\n try {\n const { status } = await httpGetJson<any>(url, {\n host: HOST,\n ttlMs: 0,\n retries: 1,\n fetchImpl,\n });\n return status === 200;\n } catch (err) {\n if (err && typeof err === 'object' && 'status' in err && (err as any).status === 404) {\n return false;\n }\n throw err;\n }\n}\n","/**\n * npm registry search client (§2B). Seeds the discovery crawler's long-tail\n * channels: keyword/category search and a recently-published sweep. This is the\n * niche workhorse — the dependency graph structurally can't find niche\n * *alternatives* (a new package shares no edge with the incumbent it competes\n * with), so that job lives here.\n */\nimport { CACHE_TTL } from '../../core/constants';\nimport { httpGetJson } from '../../core/http';\n\nconst HOST = 'registry.npmjs.org';\n\nexport interface NpmSearchHit {\n name: string;\n /** ISO publish date of the matched version, if reported. */\n date: string | null;\n}\n\n/**\n * Run an npm registry search. `query` uses npm's search qualifier syntax, e.g.\n * `keywords:orm` or `orm typescript`. `from` is the rank offset — the search is\n * deterministic, so a caller that always passes 0 re-reads the same head of the\n * ranking on every call. Returns name + publish date per hit. Best-effort:\n * returns [] on any failure.\n */\nexport async function searchNpm(\n query: string,\n size = 20,\n from = 0,\n fetchImpl?: typeof fetch,\n): Promise<NpmSearchHit[]> {\n const url = `https://${HOST}/-/v1/search?text=${encodeURIComponent(query)}&size=${size}&from=${from}`;\n try {\n const { data } = await httpGetJson<any>(url, {\n host: HOST,\n ttlMs: CACHE_TTL.npmRegistry,\n fetchImpl,\n });\n const objects: any[] = Array.isArray(data?.objects) ? data.objects : [];\n return objects\n .map((o) => ({ name: o?.package?.name, date: o?.package?.date ?? null }))\n .filter((h): h is NpmSearchHit => typeof h.name === 'string');\n } catch {\n return [];\n }\n}\n","/**\n * npm downloads client (§9.2). Weekly downloads + 90-day growth.\n *\n * Weekly downloads is fetched in BULK at the pipeline level — npm's point API\n * accepts up to 128 comma-separated packages per call, which avoids the harsh\n * rate-limiting that per-package bursts trigger. The range (growth) API has no\n * bulk form, so growth is a per-package best-effort secondary signal.\n *\n * Bulk does not support scoped (@scope/name) packages; those are fetched singly.\n */\nimport { CACHE_TTL } from '../../core/constants';\nimport { httpGetJson, HttpError } from '../../core/http';\n\nconst HOST = 'api.npmjs.org';\nconst BULK_CHUNK = 128;\n\nexport function parseWeeklyDownloads(json: any): number | null {\n const value = json?.downloads;\n return typeof value === 'number' ? value : null;\n}\n\ninterface RangePoint {\n day: string;\n downloads: number;\n}\n\n/** Compute the 90d growth fraction from a daily-downloads range. */\nexport function parseDownloadGrowth(json: any): number | null {\n const points: RangePoint[] = Array.isArray(json?.downloads) ? json.downloads : [];\n if (points.length < 60) return null;\n const tail = points.slice(-60);\n const prior = tail.slice(0, 30);\n const recent = tail.slice(30);\n const sum = (arr: RangePoint[]) => arr.reduce((acc, p) => acc + (p.downloads || 0), 0);\n const priorAvg = sum(prior) / prior.length;\n const recentAvg = sum(recent) / recent.length;\n if (priorAvg <= 0) return recentAvg > 0 ? 1 : 0;\n // Round to 3 decimals: this is a best-effort secondary signal, so the float's\n // precision tail is meaningless — and it ships in every recommend/evaluate\n // response, where 19 chars of noise is tokens the calling agent pays for.\n return Math.round(((recentAvg - priorAvg) / priorAvg) * 1000) / 1000;\n}\n\n/** Format a Date as YYYY-MM-DD (UTC) for the npm range API. */\nfunction ymd(date: Date): string {\n return date.toISOString().slice(0, 10);\n}\n\n/** Build a `start:end` range string covering the last 90 days. */\nexport function last90DayRange(now: Date = new Date()): string {\n const end = now;\n const start = new Date(end.getTime() - 90 * 24 * 60 * 60 * 1000);\n return `${ymd(start)}:${ymd(end)}`;\n}\n\n/** Parse a bulk point response into a name→downloads map (handles single + multi forms). */\nexport function parseBulkWeekly(json: any, requested: string[]): Map<string, number | null> {\n const map = new Map<string, number | null>();\n // A single-package request returns the object directly, not keyed by name.\n if (json && typeof json.downloads === 'number' && typeof json.package === 'string') {\n map.set(json.package, json.downloads);\n return map;\n }\n for (const name of requested) {\n const entry = json?.[name];\n map.set(name, entry && typeof entry.downloads === 'number' ? entry.downloads : null);\n }\n return map;\n}\n\nfunction chunk<T>(items: T[], size: number): T[][] {\n const out: T[][] = [];\n for (let i = 0; i < items.length; i += size) out.push(items.slice(i, i + size));\n return out;\n}\n\n/** Single-package weekly downloads. 404 → null (no per-package data). */\nexport async function fetchWeeklyDownloads(\n name: string,\n fetchImpl?: typeof fetch,\n): Promise<number | null> {\n try {\n const { data } = await httpGetJson<any>(\n `https://${HOST}/downloads/point/last-week/${name}`,\n { host: HOST, ttlMs: CACHE_TTL.npmDownloads, retries: 5, fetchImpl },\n );\n return parseWeeklyDownloads(data);\n } catch (err) {\n if (err instanceof HttpError && err.status === 404) return null;\n throw err;\n }\n}\n\n/** Per-package 90d growth (best-effort secondary signal). */\nexport async function fetchDownloadGrowth(\n name: string,\n fetchImpl?: typeof fetch,\n): Promise<number | null> {\n try {\n const { data } = await httpGetJson<any>(\n `https://${HOST}/downloads/range/${last90DayRange()}/${name}`,\n { host: HOST, ttlMs: CACHE_TTL.npmDownloads, retries: 3, fetchImpl },\n );\n return parseDownloadGrowth(data);\n } catch {\n return null;\n }\n}\n\n/**\n * Bulk-fetch weekly downloads for many packages. Unscoped packages go through\n * the 128-at-a-time bulk endpoint; scoped packages are fetched individually.\n */\nexport async function fetchBulkWeeklyDownloads(\n names: string[],\n fetchImpl?: typeof fetch,\n): Promise<Map<string, number | null>> {\n const result = new Map<string, number | null>();\n const unscoped = names.filter((n) => !n.startsWith('@'));\n const scoped = names.filter((n) => n.startsWith('@'));\n\n for (const batch of chunk(unscoped, BULK_CHUNK)) {\n try {\n const { data } = await httpGetJson<any>(\n `https://${HOST}/downloads/point/last-week/${batch.join(',')}`,\n { host: HOST, ttlMs: CACHE_TTL.npmDownloads, retries: 5, fetchImpl },\n );\n for (const [k, v] of parseBulkWeekly(data, batch)) result.set(k, v);\n } catch {\n // Leave this batch absent; per-package fallback will retry it.\n }\n }\n\n for (const name of scoped) {\n try {\n result.set(name, await fetchWeeklyDownloads(name, fetchImpl));\n } catch {\n /* leave absent → per-package fallback */\n }\n }\n\n return result;\n}\n","/**\n * GitHub client (§9.3). One GraphQL call per repo fetches stars, issue counts,\n * archived flag, and recent releases (latest date + 12-month cadence).\n * Requires GITHUB_TOKEN; without it, the pipeline skips this source.\n */\nimport { CACHE_TTL } from '../../core/constants';\nimport { httpRequest } from '../../core/http';\nimport type { GithubRepoData } from '../types';\n\nconst HOST = 'api.github.com';\nconst ENDPOINT = `https://${HOST}/graphql`;\n\nconst QUERY = `query($owner:String!, $name:String!) {\n repository(owner:$owner, name:$name) {\n stargazerCount\n isArchived\n openIssues: issues(states:OPEN) { totalCount }\n closedIssues: issues(states:CLOSED) { totalCount }\n releases(first: 50, orderBy: {field: CREATED_AT, direction: DESC}) {\n nodes { createdAt }\n }\n }\n}`;\n\nconst ONE_YEAR_MS = 365 * 24 * 60 * 60 * 1000;\n\nexport function parseGithub(json: any, now: Date = new Date()): GithubRepoData | null {\n const repo = json?.data?.repository;\n if (!repo) return null;\n\n const releaseNodes: { createdAt: string }[] = repo.releases?.nodes ?? [];\n const releaseDates = releaseNodes\n .map((n) => Date.parse(n.createdAt))\n .filter((ms) => !Number.isNaN(ms));\n const cutoff = now.getTime() - ONE_YEAR_MS;\n\n return {\n stars: typeof repo.stargazerCount === 'number' ? repo.stargazerCount : null,\n openIssues: repo.openIssues?.totalCount ?? null,\n closedIssues: repo.closedIssues?.totalCount ?? null,\n archived: Boolean(repo.isArchived),\n lastReleaseAt: releaseDates.length ? new Date(Math.max(...releaseDates)) : null,\n releasesLast12mo: releaseDates.filter((ms) => ms >= cutoff).length,\n };\n}\n\nexport async function fetchGithubRepo(\n owner: string,\n repo: string,\n token: string,\n fetchImpl?: typeof fetch,\n): Promise<GithubRepoData | null> {\n const body = JSON.stringify({ query: QUERY, variables: { owner, name: repo } });\n const { data } = await httpRequest<any>(ENDPOINT, {\n host: HOST,\n ttlMs: CACHE_TTL.github,\n method: 'POST',\n headers: {\n Authorization: `bearer ${token}`,\n 'Content-Type': 'application/json',\n 'User-Agent': 'lurq',\n },\n body,\n // Keep the auth token out of the cache key.\n cacheKey: `POST ${ENDPOINT} ${owner}/${repo}`,\n fetchImpl,\n });\n return parseGithub(data);\n}\n","/**\n * deps.dev client (§9.4). Primary source for OpenSSF Scorecard and security\n * advisories.\n * - Scorecard comes from the project endpoint (keyed by github.com/owner/repo).\n * - Advisories: the version endpoint lists advisoryKeys; we fetch each (capped)\n * and derive a severity bucket from its CVSS score.\n */\nimport { CACHE_TTL } from '../../core/constants';\nimport { httpGetJson, type HttpResponse } from '../../core/http';\nimport type { Advisory, AdvisorySeverity } from '../../core/types';\nimport type { DepsDevData } from '../types';\n\nconst HOST = 'api.deps.dev';\nconst MAX_ADVISORIES = 10;\n\nfunction encodeName(name: string): string {\n return encodeURIComponent(name);\n}\n\nexport function severityFromCvss(score: number | null | undefined): AdvisorySeverity {\n if (score == null) return 'moderate';\n if (score >= 9) return 'critical';\n if (score >= 7) return 'high';\n if (score >= 4) return 'moderate';\n if (score > 0) return 'low';\n return 'info';\n}\n\nexport function parseScorecard(json: any): number | null {\n const score = json?.scorecard?.overallScore;\n return typeof score === 'number' ? score : null;\n}\n\nexport function parseAdvisoryKeys(versionJson: any): string[] {\n const keys = versionJson?.advisoryKeys;\n if (!Array.isArray(keys)) return [];\n return keys\n .map((k: any) => (typeof k === 'string' ? k : k?.id))\n .filter((id: unknown): id is string => typeof id === 'string');\n}\n\nexport function parseAdvisoryDetail(json: any): Advisory {\n return {\n id: json?.advisoryKey?.id ?? json?.advisoryKey ?? 'unknown',\n severity: severityFromCvss(json?.cvss3Score),\n summary: json?.title ?? '',\n };\n}\n\nexport async function fetchScorecard(\n owner: string,\n repo: string,\n fetchImpl?: typeof fetch,\n): Promise<number | null> {\n const projectKey = encodeURIComponent(`github.com/${owner}/${repo}`);\n const url = `https://${HOST}/v3/projects/${projectKey}`;\n try {\n const { data } = await httpGetJson<any>(url, {\n host: HOST,\n ttlMs: CACHE_TTL.depsDev,\n fetchImpl,\n });\n return parseScorecard(data);\n } catch {\n return null;\n }\n}\n\nexport async function fetchAdvisories(\n name: string,\n version: string,\n fetchImpl?: typeof fetch,\n): Promise<Advisory[]> {\n const versionUrl = `https://${HOST}/v3/systems/npm/packages/${encodeName(name)}/versions/${encodeURIComponent(version)}`;\n let keys: string[] = [];\n try {\n const { data } = await httpGetJson<any>(versionUrl, {\n host: HOST,\n ttlMs: CACHE_TTL.depsDev,\n fetchImpl,\n });\n keys = parseAdvisoryKeys(data).slice(0, MAX_ADVISORIES);\n } catch {\n return [];\n }\n\n const details = await Promise.allSettled(\n keys.map((key) =>\n httpGetJson<any>(`https://${HOST}/v3/advisories/${encodeURIComponent(key)}`, {\n host: HOST,\n ttlMs: CACHE_TTL.depsDev,\n fetchImpl,\n }),\n ),\n );\n return details\n .filter(\n (d): d is PromiseFulfilledResult<HttpResponse<any>> => d.status === 'fulfilled',\n )\n .map((d) => parseAdvisoryDetail(d.value.data));\n}\n\n/**\n * Direct dependency names from the deps.dev graph (§2B). These are the packages\n * a seed is *built on* — the adjacent foundations. Best-effort: returns [] on any\n * failure. We deliberately do NOT rank by dependent count (that re-introduces the\n * popularity bias §2B exists to avoid); the caller gates on quality instead.\n */\nexport async function fetchDependencyNames(\n name: string,\n version: string,\n fetchImpl?: typeof fetch,\n): Promise<string[]> {\n const url = `https://${HOST}/v3/systems/npm/packages/${encodeName(name)}/versions/${encodeURIComponent(version)}:dependencies`;\n try {\n const { data } = await httpGetJson<any>(url, {\n host: HOST,\n ttlMs: CACHE_TTL.depsDev,\n fetchImpl,\n });\n const nodes: any[] = Array.isArray(data?.nodes) ? data.nodes : [];\n const names = nodes\n .map((n) => n?.versionKey?.name)\n .filter((n: unknown): n is string => typeof n === 'string' && n !== name);\n return [...new Set(names)];\n } catch {\n return [];\n }\n}\n\nexport interface ResolvedNode {\n name: string;\n version: string;\n}\n\n/**\n * The full resolved dependency closure for `name@version` (§4B) — every node npm\n * would put in node_modules, each with its exact resolved version. This is a\n * co-installation witness: the resolver found a working assignment including all\n * of them and the artifact shipped, so every pair inside provably co-resolves.\n * Best-effort: [] on any failure. Unlike `fetchDependencyNames`, keeps versions.\n */\nexport async function fetchResolvedGraph(\n name: string,\n version: string,\n fetchImpl?: typeof fetch,\n): Promise<ResolvedNode[]> {\n const url = `https://${HOST}/v3/systems/npm/packages/${encodeName(name)}/versions/${encodeURIComponent(version)}:dependencies`;\n try {\n const { data } = await httpGetJson<any>(url, {\n host: HOST,\n ttlMs: CACHE_TTL.depsDev,\n fetchImpl,\n });\n const nodes: any[] = Array.isArray(data?.nodes) ? data.nodes : [];\n const out: ResolvedNode[] = [];\n const seen = new Set<string>();\n for (const n of nodes) {\n const nm = n?.versionKey?.name;\n const ver = n?.versionKey?.version;\n if (typeof nm !== 'string' || typeof ver !== 'string') continue;\n const key = `${nm}@${ver}`;\n if (seen.has(key)) continue;\n seen.add(key);\n out.push({ name: nm, version: ver });\n }\n return out;\n } catch {\n return [];\n }\n}\n\n/**\n * Direct dependencies only (§4G BFS), with versions — the ~15 packages the author\n * deliberately chose, not the transitive plumbing. Reads the graph `edges`: a\n * node is direct iff an edge from the root (the `SELF` node) points to it. Falls\n * back to [] on failure. Enqueuing only these keeps discovery from re-introducing\n * the plumbing explosion one hop later.\n */\nexport async function fetchDirectDependencies(\n name: string,\n version: string,\n fetchImpl?: typeof fetch,\n): Promise<ResolvedNode[]> {\n const url = `https://${HOST}/v3/systems/npm/packages/${encodeName(name)}/versions/${encodeURIComponent(version)}:dependencies`;\n try {\n const { data } = await httpGetJson<any>(url, {\n host: HOST,\n ttlMs: CACHE_TTL.depsDev,\n fetchImpl,\n });\n const nodes: any[] = Array.isArray(data?.nodes) ? data.nodes : [];\n const edges: any[] = Array.isArray(data?.edges) ? data.edges : [];\n // Root is the SELF node; deps.dev conventionally places it at index 0.\n const rootIdx = nodes.findIndex((n) => n?.relation === 'SELF');\n const root = rootIdx >= 0 ? rootIdx : 0;\n const out: ResolvedNode[] = [];\n const seen = new Set<string>();\n for (const e of edges) {\n if (e?.fromNode !== root) continue;\n const target = nodes[e?.toNode];\n const nm = target?.versionKey?.name;\n const ver = target?.versionKey?.version;\n if (typeof nm !== 'string' || typeof ver !== 'string' || nm === name) continue;\n if (seen.has(nm)) continue;\n seen.add(nm);\n out.push({ name: nm, version: ver });\n }\n return out;\n } catch {\n return [];\n }\n}\n\nexport async function fetchDepsDev(\n name: string,\n version: string | null,\n repo: { owner: string; repo: string } | null,\n fetchImpl?: typeof fetch,\n): Promise<DepsDevData> {\n const [scorecard, advisories] = await Promise.all([\n repo ? fetchScorecard(repo.owner, repo.repo, fetchImpl) : Promise.resolve(null),\n version ? fetchAdvisories(name, version, fetchImpl) : Promise.resolve([]),\n ]);\n return { scorecard, advisories };\n}\n","/**\n * Bundlephobia client (§9.5). Minified + gzipped size for frontend packages.\n * Strictly best-effort: this API is slow and flaky, so failures degrade to null\n * and never block ingestion (per R1 build decision). Cached aggressively (7d).\n */\nimport { CACHE_TTL } from '../../core/constants';\nimport { httpGetJson } from '../../core/http';\nimport { isFrontendCategory, type Category } from '../../core/types';\nimport type { BundlephobiaData } from '../types';\n\nconst HOST = 'bundlephobia.com';\n\nexport function parseBundleSize(json: any): number | null {\n const gzipBytes = json?.gzip;\n if (typeof gzipBytes !== 'number') return null;\n return Math.round((gzipBytes / 1024) * 10) / 10; // KB, 1 decimal\n}\n\n/**\n * Fetch bundle size — only for frontend categories (§9.5); returns null for\n * backend-only packages without making a request.\n */\nexport async function fetchBundlephobia(\n name: string,\n category: Category | null,\n fetchImpl?: typeof fetch,\n): Promise<BundlephobiaData> {\n if (!isFrontendCategory(category)) return { bundleMinGzipKb: null };\n\n const url = `https://${HOST}/api/size?package=${encodeURIComponent(name)}`;\n try {\n const { data } = await httpGetJson<any>(url, {\n host: HOST,\n ttlMs: CACHE_TTL.bundlephobia,\n timeoutMs: 12_000,\n retries: 1,\n fetchImpl,\n });\n return { bundleMinGzipKb: parseBundleSize(data) };\n } catch {\n return { bundleMinGzipKb: null };\n }\n}\n","export * from './npmRegistry';\nexport * from './npmSearch';\nexport * from './npmDownloads';\nexport * from './github';\nexport * from './depsDev';\nexport * from './bundlephobia';\n","/**\n * Assemble compat members for a set of package names: the fast path reads\n * metadata straight from the DB in one query; any name not tracked is fetched\n * on-demand (the HTTP layer caches packuments) so a single untracked package\n * doesn't blind the whole-architecture check. Names that can't be resolved at\n * all are returned as `unverified` rather than guessed.\n *\n * When a pin differs from the indexed latest, peers/engines are loaded for that\n * exact published version so Tier-1 checks match the stack being installed.\n */\nimport type { Database } from '../db/client';\nimport { getCompatMetadata } from '../db/compat';\nimport { fetchNpmCompatAtVersion, fetchNpmRegistry } from '../ingestion/sources';\nimport type { CompatMember } from './peerCompat';\n\nexport interface CompatPackageRef {\n name: string;\n /** Exact version to check. Null/undefined → indexed latest (or registry latest). */\n version?: string | null;\n}\n\nexport async function assembleMembers(\n db: Database,\n refs: CompatPackageRef[] | string[],\n): Promise<{ members: CompatMember[]; unverified: string[] }> {\n const normalized: CompatPackageRef[] = refs.map((r) =>\n typeof r === 'string' ? { name: r, version: null } : r,\n );\n const names = [...new Set(normalized.map((r) => r.name))];\n const tracked = new Map((await getCompatMetadata(db, names)).map((r) => [r.name, r]));\n const members: CompatMember[] = [];\n const unverified: string[] = [];\n\n await Promise.all(\n normalized.map(async (ref) => {\n const row = tracked.get(ref.name);\n const pin = ref.version?.trim() || null;\n const canUseIndexed =\n row && (!pin || !row.latestVersion || pin === row.latestVersion);\n\n if (canUseIndexed && row) {\n members.push({\n name: ref.name,\n version: pin ?? row.latestVersion,\n peerDependencies: row.peerDependencies,\n peerDependenciesMeta: row.peerDependenciesMeta,\n engines: row.engines,\n });\n return;\n }\n\n // Pinned away from latest (or untracked): load that version's manifest.\n if (pin) {\n const at = await fetchNpmCompatAtVersion(ref.name, pin).catch(() => null);\n if (at) {\n members.push({\n name: ref.name,\n version: at.version,\n peerDependencies: at.peerDependencies,\n peerDependenciesMeta: at.peerDependenciesMeta,\n engines: at.engines,\n });\n return;\n }\n unverified.push(ref.name);\n return;\n }\n\n const reg = await fetchNpmRegistry(ref.name).catch(() => null);\n if (reg) {\n members.push({\n name: ref.name,\n version: reg.latestVersion,\n peerDependencies: reg.peerDependencies,\n peerDependenciesMeta: reg.peerDependenciesMeta,\n engines: reg.engines,\n });\n } else {\n unverified.push(ref.name);\n }\n }),\n );\n\n return { members, unverified };\n}\n","/**\n * Tier-1 compatibility: whole-architecture peer-dependency + engine analysis.\n *\n * Deterministic and instant — no install. Works over the *entire set* at once:\n * it collects every package's declared `peerDependencies`, groups them by peer,\n * and checks the declared semver ranges agree. Two plugins that need `eslint@8`\n * vs `eslint@9` conflict even if eslint isn't pinned in the set.\n *\n * Sparse data degrades safely: a package with no declared peers contributes no\n * constraints (which is correct — most packages declare none), so \"not fully\n * recorded\" never produces a false conflict. Genuinely-untracked packages are\n * reported as `unverified` by the caller, not guessed at.\n */\nimport semver from 'semver';\nimport type { CompatConflict, DependencyRanges, PeerMeta } from '../core/types';\n\nexport interface CompatMember {\n name: string;\n /** Pinned (latest) version, or null if unknown. */\n version: string | null;\n peerDependencies: DependencyRanges | null;\n peerDependenciesMeta: PeerMeta | null;\n engines: DependencyRanges | null;\n}\n\ninterface PeerConstraint {\n requirer: string;\n peer: string;\n range: string;\n optional: boolean;\n}\n\n/** null = can't assert (invalid version/range). */\nfunction satisfiesRange(version: string, range: string): boolean | null {\n if (!semver.validRange(range)) return null;\n const v = semver.valid(version) ? version : semver.coerce(version)?.version;\n if (!v) return null;\n return semver.satisfies(v, range, { includePrerelease: true });\n}\n\nfunction rangesIntersect(a: string, b: string): boolean | null {\n if (!semver.validRange(a) || !semver.validRange(b)) return null;\n try {\n return semver.intersects(a, b, { includePrerelease: true });\n } catch {\n return null;\n }\n}\n\n/** All peer/engine conflicts across the set (empty = no Tier-1 conflict found). */\nexport function resolveArchitectureCompat(members: CompatMember[]): CompatConflict[] {\n const conflicts: CompatConflict[] = [];\n const pinned = new Map<string, string>();\n for (const m of members) if (m.version) pinned.set(m.name, m.version);\n\n const constraints: PeerConstraint[] = [];\n for (const m of members) {\n if (!m.peerDependencies) continue;\n for (const [peer, range] of Object.entries(m.peerDependencies)) {\n constraints.push({\n requirer: m.name,\n peer,\n range,\n optional: Boolean(m.peerDependenciesMeta?.[peer]?.optional),\n });\n }\n }\n\n // (1) A peer that's pinned in the set must satisfy each declared range.\n for (const c of constraints) {\n const pv = pinned.get(c.peer);\n if (pv && satisfiesRange(pv, c.range) === false) {\n conflicts.push({\n source: 'peer-deps',\n packages: [c.requirer, c.peer],\n detail: `${c.requirer} needs peer ${c.peer}@${c.range}, but the stack uses ${c.peer}@${pv}`,\n requirement: { peer: c.peer, range: c.range, resolved: pv },\n });\n }\n }\n\n // (2) A peer required by ≥2 members but not pinned: their ranges must overlap.\n const byPeer = new Map<string, PeerConstraint[]>();\n for (const c of constraints) {\n if (pinned.has(c.peer) || c.optional) continue;\n const arr = byPeer.get(c.peer);\n if (arr) arr.push(c);\n else byPeer.set(c.peer, [c]);\n }\n for (const [peer, cs] of byPeer) {\n for (let i = 0; i < cs.length; i++) {\n for (let j = i + 1; j < cs.length; j++) {\n if (cs[i]!.range !== cs[j]!.range && rangesIntersect(cs[i]!.range, cs[j]!.range) === false) {\n conflicts.push({\n source: 'peer-deps',\n packages: [cs[i]!.requirer, cs[j]!.requirer],\n detail: `${cs[i]!.requirer} needs ${peer}@${cs[i]!.range} but ${cs[j]!.requirer} needs ${peer}@${cs[j]!.range} — no overlapping version`,\n // Two requirers disagreeing about a peer that isn't in the set: the\n // peer has no resolved version to report.\n requirement: { peer, range: cs[i]!.range, resolved: null },\n });\n }\n }\n }\n }\n\n // (3) Node engine ranges across the set must have a common solution.\n const nodeReqs = members\n .map((m) => ({ name: m.name, range: m.engines?.node }))\n .filter((r): r is { name: string; range: string } => typeof r.range === 'string');\n for (let i = 0; i < nodeReqs.length; i++) {\n for (let j = i + 1; j < nodeReqs.length; j++) {\n if (rangesIntersect(nodeReqs[i]!.range, nodeReqs[j]!.range) === false) {\n conflicts.push({\n source: 'engines',\n packages: [nodeReqs[i]!.name, nodeReqs[j]!.name],\n detail: `${nodeReqs[i]!.name} needs node ${nodeReqs[i]!.range} but ${nodeReqs[j]!.name} needs node ${nodeReqs[j]!.range} — no overlap`,\n });\n }\n }\n }\n\n return conflicts;\n}\n\n/**\n * Tier-1 check: each member's `engines.node` must satisfy the target runtime\n * (e.g. the benchmark / sandbox Node version). Sparse/missing engines are ignored.\n *\n * A bare major (`\"20\"`) means \"some Node 20\", not `20.0.0` — coercing it to the\n * .0.0 floor false-flagged every package with a modern engines floor (vite's\n * `^20.19.0 || >=22.12.0` \"conflicted\" with node 20). Partial versions are\n * therefore compared as *ranges* and only conflict when no Node in the target\n * line can satisfy the package; an exact version still gets an exact check.\n */\nexport function resolveRuntimeEngineConflicts(\n members: CompatMember[],\n nodeVersion: string,\n): CompatConflict[] {\n const runtime = normalizeNodeVersion(nodeVersion);\n if (!runtime) return [];\n\n const conflicts: CompatConflict[] = [];\n for (const m of members) {\n const range = m.engines?.node;\n if (!range) continue;\n const ok = runtime.exact\n ? satisfiesRange(runtime.value, range)\n : rangesIntersect(runtime.value, range);\n if (ok === false) {\n conflicts.push({\n source: 'engines',\n packages: [m.name],\n detail: `${m.name}@${m.version ?? '?'} needs node ${range}, but the runtime is node ${runtime.label}`,\n });\n }\n }\n return conflicts;\n}\n\n/** The target runtime as a semver *range*, plus whether the caller pinned an\n * exact version. `20` / `v20` → `20.x` (any Node 20); `20.20.2` → exact. */\ninterface TargetRuntime {\n /** Exact version, or a range covering the requested line. */\n value: string;\n exact: boolean;\n /** What the caller asked for, for the conflict message. */\n label: string;\n}\n\nfunction normalizeNodeVersion(raw: string): TargetRuntime | null {\n const trimmed = raw.trim().replace(/^v/i, '');\n if (!trimmed) return null;\n if (semver.valid(trimmed)) return { value: trimmed, exact: true, label: trimmed };\n // `20` or `20.19` — a version line, not a version. Widen to the whole line.\n if (/^\\d+(\\.\\d+)?$/.test(trimmed)) {\n return { value: `${trimmed}.x`, exact: false, label: trimmed };\n }\n const coerced = semver.coerce(trimmed);\n return coerced ? { value: coerced.version, exact: true, label: coerced.version } : null;\n}\n","/**\n * Whole-architecture compatibility check for a set of packages, shared by the\n * `compat` tool and `plan`. Tier 1 (peer-deps/engines, instant) + any recorded\n * Tier-2 sandbox conflicts. The result lists every member as name@version so\n * versions are explicit and the evidence stays structured for later scraping.\n */\nimport type { CompatConflict, CompatEvidence, CompatOutput, CompatPair } from '../core/types';\nimport type { Database } from '../db/client';\nimport { enqueueCompatVerify, fullyCovered, getCompatEdges, pairKey } from '../db/compat';\nimport { assembleMembers, type CompatPackageRef } from './members';\nimport { resolveArchitectureCompat, resolveRuntimeEngineConflicts } from './peerCompat';\n\n/**\n * Evidence-graded verdict (pure). `compatible` requires *positive* proof for every\n * pair; absence of a declared conflict is not proof, so an unverified set is\n * `likely`, never `compatible`. A single package has no pairs → trivially fine.\n */\nexport function gradeOverall(args: {\n hasConflict: boolean;\n hasUnverifiedMember: boolean;\n memberNames: string[];\n provenCompatible: Set<string>;\n}): CompatOutput['overall'] {\n if (args.hasConflict) return 'conflict';\n if (args.hasUnverifiedMember) return 'unknown';\n if (args.memberNames.length < 2 || fullyCovered(args.memberNames, args.provenCompatible))\n return 'compatible';\n return 'likely';\n}\n\nexport interface CheckCompatOptions {\n /** Exact versions to evaluate (name → version). Missing names use indexed latest. */\n versions?: Record<string, string | null | undefined>;\n /** Target Node runtime (e.g. \"20\" or \"20.20.2\"). Checks each package's engines.node. */\n node?: string | null;\n}\n\nexport async function checkCompat(\n db: Database,\n packages: string[],\n opts: CheckCompatOptions = {},\n): Promise<CompatOutput> {\n const names = [...new Set(packages)];\n const refs: CompatPackageRef[] = names.map((name) => ({\n name,\n version: opts.versions?.[name] ?? null,\n }));\n const { members, unverified } = await assembleMembers(db, refs);\n\n const conflicts: CompatConflict[] = [\n ...resolveArchitectureCompat(members),\n ...(opts.node ? resolveRuntimeEngineConflicts(members, opts.node) : []),\n ];\n const edges = await getCompatEdges(db, names);\n const evidence: CompatEvidence[] = edges.map((edge) => ({\n packages: [edge.packageA, edge.packageB],\n versions: [edge.versionA, edge.versionB],\n status: edge.status,\n provenance: edge.provenance,\n witnessCount: edge.witnessCount,\n }));\n for (const edge of edges) {\n if (edge.status === 'conflict') {\n conflicts.push({\n source: 'sandbox',\n packages: [edge.packageA, edge.packageB],\n detail: `${edge.packageA}@${edge.versionA} and ${edge.packageB}@${edge.versionB} failed to co-install in the sandbox`,\n });\n }\n }\n\n // Pairs backed by a *positive* (compatible) edge — verified or observed. A\n // `conflict` edge is not positive evidence, so it's excluded here (it already\n // pushed a conflict above). ponytail: name-level coverage; a version-matched\n // check (edge versions == members' current versions) is the stricter follow-up.\n const checkedNames = members.map((m) => m.name);\n const provenCompatible = new Set(\n edges.filter((e) => e.status === 'compatible').map((e) => pairKey(e.packageA, e.packageB)),\n );\n\n // Self-heal (§4C): if any pair among the checked members lacks a positive edge,\n // queue a background sandbox co-install so the next asker gets a real answer.\n // One deduped insert — never blocks, never runs a VM here. Skip when a conflict\n // is already known (nothing to learn) or every pair is already proven.\n if (checkedNames.length >= 2 && !conflicts.length && !fullyCovered(checkedNames, provenCompatible)) {\n await enqueueCompatVerify(db, checkedNames).catch(() => {});\n }\n\n const overall = gradeOverall({\n hasConflict: conflicts.length > 0,\n hasUnverifiedMember: unverified.length > 0,\n memberNames: checkedNames,\n provenCompatible,\n });\n\n return {\n packages: names,\n overall,\n conflicts,\n unverified,\n checked: members.map((m) => ({ name: m.name, version: m.version })),\n evidence,\n pairs: enumeratePairs(checkedNames, conflicts),\n };\n}\n\n/**\n * Every unordered pair among the checked members, in reading order (row-major\n * over the lower triangle), each graded from the conflicts already found.\n *\n * `held` is the absence of a violated declared constraint, which is a weaker\n * claim than \"these work together\" — see the note on CompatPair. It is reported\n * anyway because \"we compared these ten pairs and two failed\" is a different and\n * more useful statement than \"two things failed\", and a caller can only make the\n * first one if it knows what the denominator was.\n */\nexport function enumeratePairs(names: string[], conflicts: CompatConflict[]): CompatPair[] {\n // First conflict wins a pair; a second one for the same two packages adds no\n // verdict, and the detail of the first is the one that was found first.\n const byPair = new Map<string, CompatConflict>();\n for (const c of conflicts) {\n const [a, b] = c.packages;\n if (!a || !b) continue;\n const key = pairKey(a, b);\n if (!byPair.has(key)) byPair.set(key, c);\n }\n\n const pairs: CompatPair[] = [];\n for (let i = 0; i < names.length; i++) {\n for (let j = 0; j < i; j++) {\n const a = names[i]!;\n const b = names[j]!;\n const hit = byPair.get(pairKey(a, b));\n pairs.push(\n hit\n ? {\n // Orient the pair the way the conflict states it, so `a` is the\n // package making the demand rather than whichever came first in\n // the argument list.\n a: hit.packages[0] ?? a,\n b: hit.packages[1] ?? b,\n status: 'conflict',\n detail: hit.detail,\n ...(hit.requirement ? { requirement: hit.requirement } : {}),\n }\n : { a, b, status: 'held' },\n );\n }\n }\n return pairs;\n}\n","/**\n * Read/write helpers for the `packages` table. All recommendation/eval reads use\n * this single denormalized table (§8.2).\n */\nimport { and, desc, eq, isNotNull, isNull, lt, notExists, sql } from 'drizzle-orm';\nimport { logger } from '../core/logger';\nimport type { Category } from '../core/types';\nimport type { VersionInfo } from '../ingestion/types';\nimport type { Database } from './client';\nimport {\n packageVersions,\n packages,\n seedPackages,\n syncRuns,\n type NewPackageRow,\n type SyncError,\n} from './schema';\n\n/** How many rows to insert per statement (stays well under Postgres' param cap). */\nconst VERSION_CHUNK = 500;\n\nexport async function getSeedTargets(\n db: Database,\n): Promise<{ name: string; category: Category | null }[]> {\n const rows = await db\n .select({ name: seedPackages.name, category: seedPackages.category })\n .from(seedPackages);\n return rows.map((r) => ({ name: r.name, category: r.category ?? null }));\n}\n\n/**\n * The daily sync's rotation slice: the stalest tracked packages that aren't in\n * `seed_packages`. Discovery ingests thousands of packages `getSeedTargets`\n * never returns, so without this their scores — and their `latest_version` —\n * stay frozen at the moment they were ingested.\n *\n * A frozen `latest_version` also closes the discovery frontier: `graphChannel`\n * (§2B) only re-expands a package whose version moved, so a package that is\n * never refreshed can never re-arm, and the crawler flatlines once the initial\n * BFS converges. This rotation is what keeps it open.\n *\n * Only a `curated` category is carried through. An `inferred` one is left null\n * so the pipeline re-infers it — passing it back in would make the refresh\n * silently relabel it `curated`, and a later curation pass would then skip it.\n */\nexport async function getStaleRefreshTargets(\n db: Database,\n limit: number,\n): Promise<{ name: string; category: Category | null }[]> {\n if (limit <= 0) return [];\n const rows = await db\n .select({\n name: packages.name,\n category: sql<\n Category | null\n >`case when ${packages.categorySource} = 'curated' then ${packages.category} end`,\n })\n .from(packages)\n .where(\n notExists(\n db\n .select({ one: sql`1` })\n .from(seedPackages)\n .where(eq(seedPackages.name, packages.name)),\n ),\n )\n // Never-synced rows (null `data_as_of`) are the stalest of all, and ASC puts\n // nulls last in Postgres — so say it explicitly.\n .orderBy(sql`${packages.dataAsOf} asc nulls first`)\n .limit(limit);\n return rows.map((r) => ({ name: r.name, category: r.category ?? null }));\n}\n\nexport async function getPackageByName(db: Database, name: string) {\n const rows = await db.select().from(packages).where(eq(packages.name, name)).limit(1);\n return rows[0] ?? null;\n}\n\n/** Every tracked package name — the set the `_changes` follower filters against. */\nexport async function getAllPackageNames(db: Database): Promise<string[]> {\n const rows = await db.select({ name: packages.name }).from(packages);\n return rows.map((r) => r.name);\n}\n\n/**\n * Store a package's version timeline. Idempotent — versions are immutable on\n * npm, so existing rows are left untouched. Chunked to respect the param cap.\n */\nexport async function upsertPackageVersions(\n db: Database,\n name: string,\n versions: VersionInfo[],\n): Promise<void> {\n // An empty timeline means the registry fetch came back without one, not that\n // the package has no versions. Returning silently made that indistinguishable\n // from a successful write, so a package could sit with no history forever and\n // nothing in the logs would say why.\n if (versions.length === 0) {\n logger.debug(`no version timeline to store for ${name}: registry returned none`);\n return;\n }\n for (let i = 0; i < versions.length; i += VERSION_CHUNK) {\n const rows = versions.slice(i, i + VERSION_CHUNK).map((v) => ({\n packageName: name,\n version: v.version,\n publishedAt: v.publishedAt,\n }));\n await db.insert(packageVersions).values(rows).onConflictDoNothing();\n }\n}\n\n/** A package's stored version timeline, newest first. */\nexport async function getPackageVersions(\n db: Database,\n name: string,\n limit = 50,\n): Promise<VersionInfo[]> {\n const rows = await db\n .select({ version: packageVersions.version, publishedAt: packageVersions.publishedAt })\n .from(packageVersions)\n .where(eq(packageVersions.packageName, name))\n .orderBy(desc(packageVersions.publishedAt))\n .limit(limit);\n return rows.map((r) => ({ version: r.version, publishedAt: r.publishedAt }));\n}\n\n/**\n * The most-downloaded tracked packages — the reference set typosquat detection\n * compares a queried name against. Capped (default 1000) so the per-verify\n * distance scan stays cheap.\n */\nexport async function getTopPackageNames(db: Database, limit = 1000): Promise<string[]> {\n const rows = await db\n .select({ name: packages.name })\n .from(packages)\n .where(isNotNull(packages.weeklyDownloads))\n .orderBy(desc(packages.weeklyDownloads))\n .limit(limit);\n return rows.map((r) => r.name);\n}\n\n/**\n * Promote a package into the curated seed list so future `sync` runs keep it\n * fresh. Used by the on-demand path (§12.5) to make organically-discovered\n * packages durable. No-op if already seeded — preserves the original category\n * and `added_at` rather than overwriting a hand-curated entry.\n */\nexport async function ensureSeedEntry(\n db: Database,\n name: string,\n category: Category | null,\n): Promise<void> {\n await db\n .insert(seedPackages)\n .values({ name, category })\n .onConflictDoNothing({ target: seedPackages.name });\n}\n\n/** Upsert a fully-computed package row, refreshing every field on conflict. */\nexport async function upsertPackage(db: Database, row: NewPackageRow): Promise<void> {\n const { name: _name, createdAt: _createdAt, ...mutable } = row;\n await db\n .insert(packages)\n .values(row)\n .onConflictDoUpdate({\n target: packages.name,\n set: { ...mutable, updatedAt: new Date() },\n });\n}\n\n/**\n * Credit the individual account whose on-demand query first caused `name` to be\n * ingested. A standalone, idempotent UPDATE guarded by `IS NULL` — kept OUT of\n * upsertPackage (which refreshes every field on conflict) so re-syncs and the\n * `_changes` watcher, which never pass an owner, can never clobber the credit.\n * The `IS NULL` guard is also the cross-process race tie-breaker: whichever\n * concurrent first-ingest commits first wins; the rest match zero rows.\n */\nexport async function stampFirstRequester(\n db: Database,\n name: string,\n ownerId: string,\n): Promise<void> {\n await db\n .update(packages)\n .set({ firstRequestedByOwnerId: ownerId })\n .where(and(eq(packages.name, name), isNull(packages.firstRequestedByOwnerId)));\n}\n\nexport interface Contribution {\n name: string;\n category: Category | null;\n healthScore: number | null;\n /** = packages.createdAt (immutable since first insert). */\n firstRequestedAt: Date;\n}\n\n/**\n * Packages this account first caused to be ingested (dashboard v1 phase 2),\n * newest first, plus the total for pagination. `firstRequestedAt` is the row's\n * immutable `createdAt`, so no separate timestamp column is needed.\n */\nexport async function getContributionsByOwner(\n db: Database,\n ownerId: string,\n opts: { limit?: number; offset?: number } = {},\n): Promise<{ total: number; packages: Contribution[] }> {\n const limit = opts.limit ?? 50;\n const offset = opts.offset ?? 0;\n const [rows, [countRow]] = await Promise.all([\n db\n .select({\n name: packages.name,\n category: packages.category,\n healthScore: packages.healthScore,\n firstRequestedAt: packages.createdAt,\n })\n .from(packages)\n .where(eq(packages.firstRequestedByOwnerId, ownerId))\n .orderBy(desc(packages.createdAt))\n .limit(limit)\n .offset(offset),\n db\n .select({ count: sql<number>`count(*)::int` })\n .from(packages)\n .where(eq(packages.firstRequestedByOwnerId, ownerId)),\n ]);\n return { total: countRow?.count ?? 0, packages: rows };\n}\n\n// ── sync_runs audit ─────────────────────────────────────────────────────────\n\n/** `<environment>/<service>` from the host's injected vars, or null when it\n * injects neither. Railway sets both on every deployment; nothing to configure. */\nfunction syncOrigin(): string | null {\n const env = process.env.RAILWAY_ENVIRONMENT_NAME;\n const service = process.env.RAILWAY_SERVICE_NAME;\n if (!env && !service) return null;\n return `${env ?? '?'}/${service ?? '?'}`;\n}\n\n/** How long a run may sit in `running` before a later run declares it dead.\n * Full syncs finish in about twenty minutes, so this is an order of magnitude\n * of headroom — the point is to reap abandoned rows, never to race a live one.\n * It must also stay clear of a concurrent sibling: two schedulers firing the\n * same cron start seconds apart, nowhere near this. */\nconst SYNC_STALE_MS = 6 * 60 * 60 * 1000;\n\n/**\n * Mark runs abandoned by a process that never came back.\n *\n * `runSync` writes a terminal status on both the success and the throw path, so\n * a row left at `running` means the process died where no handler could run:\n * OOM, SIGKILL, a container timeout. Nothing else can ever close those rows, and\n * without this they accumulate forever and quietly corrupt any \"when did the\n * index last sync cleanly\" read — a stuck `running` row is indistinguishable\n * from a sync in progress.\n */\nasync function reapAbandonedSyncRuns(db: Database): Promise<void> {\n await db\n .update(syncRuns)\n .set({\n status: 'failed',\n finishedAt: new Date(),\n errors: [\n {\n package: '*',\n source: 'pipeline',\n message: 'abandoned: the process died before writing a terminal status',\n },\n ],\n })\n .where(\n and(\n eq(syncRuns.status, 'running'),\n lt(syncRuns.startedAt, new Date(Date.now() - SYNC_STALE_MS)),\n ),\n );\n}\n\nexport async function startSyncRun(db: Database): Promise<number> {\n // Cheap, and this is the only moment we know a sweep is safe: any run still\n // `running` from six hours ago cannot be the one we are about to start.\n await reapAbandonedSyncRuns(db);\n const [row] = await db\n .insert(syncRuns)\n .values({ status: 'running', origin: syncOrigin() })\n .returning({ id: syncRuns.id });\n return row!.id;\n}\n\nexport async function finishSyncRun(\n db: Database,\n id: number,\n data: {\n packagesSeen: number;\n packagesUpdated: number;\n errors: SyncError[];\n status: 'success' | 'partial' | 'failed';\n },\n): Promise<void> {\n await db\n .update(syncRuns)\n .set({\n finishedAt: new Date(),\n packagesSeen: data.packagesSeen,\n packagesUpdated: data.packagesUpdated,\n errors: data.errors,\n status: data.status,\n })\n .where(eq(syncRuns.id, id));\n}\n","/**\n * Surface delta (§4D). Pure: given two extracted API surfaces, compute what an\n * agent must change — added / removed / renamed / changed exports. Deltas are\n * computed, not guessed. `renamed` is inferred when a symbol disappears and a\n * near-identical one (same kind + signature) appears, so an agent sees a rename\n * rather than an unrelated remove + add.\n */\nimport type { ExportSymbol, SurfaceDelta } from '../core/types';\n\nfunction byName(surface: ExportSymbol[]): Map<string, ExportSymbol> {\n return new Map(surface.map((s) => [s.name, s]));\n}\n\n/** Two removed/added symbols are the \"same\" renamed export if kind + signature\n * match (signature-similarity heuristic from §4D). */\nfunction looksRenamed(a: ExportSymbol, b: ExportSymbol): boolean {\n return a.kind === b.kind && a.signature !== null && a.signature === b.signature;\n}\n\nexport function diffSurface(oldSurface: ExportSymbol[], newSurface: ExportSymbol[]): SurfaceDelta {\n const oldByName = byName(oldSurface);\n const newByName = byName(newSurface);\n\n const removed: ExportSymbol[] = oldSurface.filter((s) => !newByName.has(s.name));\n const added: ExportSymbol[] = newSurface.filter((s) => !oldByName.has(s.name));\n const changed: SurfaceDelta['changed'] = [];\n\n for (const oldSym of oldSurface) {\n const newSym = newByName.get(oldSym.name);\n if (newSym && oldSym.signature !== newSym.signature) {\n changed.push({ name: oldSym.name, before: oldSym.signature, after: newSym.signature });\n }\n }\n\n // Pair removed↔added by signature similarity → renames. Each side used once.\n const renamed: SurfaceDelta['renamed'] = [];\n const takenAdded = new Set<string>();\n const stillRemoved: ExportSymbol[] = [];\n for (const r of removed) {\n const match = added.find((a) => !takenAdded.has(a.name) && looksRenamed(r, a));\n if (match) {\n renamed.push({ from: r, to: match });\n takenAdded.add(match.name);\n } else {\n stillRemoved.push(r);\n }\n }\n\n return {\n added: added.filter((a) => !takenAdded.has(a.name)),\n removed: stillRemoved,\n renamed,\n changed,\n };\n}\n","/** Read/write helpers for the API-surface cache (`api_surfaces`, §4D). */\nimport { and, eq, isNotNull, isNull, sql } from 'drizzle-orm';\nimport type { ExportSymbol } from '../core/types';\nimport type { Database } from './client';\nimport { apiSurfaces, packages } from './schema';\n\nexport async function getStoredSurface(\n db: Database,\n packageName: string,\n version: string,\n): Promise<ExportSymbol[] | null> {\n const [row] = await db\n .select({ surface: apiSurfaces.surface })\n .from(apiSurfaces)\n .where(and(eq(apiSurfaces.packageName, packageName), eq(apiSurfaces.version, version)))\n .limit(1);\n return row?.surface ?? null;\n}\n\n/**\n * Tracked packages whose latest version has no extracted surface yet — the\n * worker's extraction backlog (§4G).\n *\n * A package that ships no types extracts to nothing and stores nothing, so it\n * stays in this result set forever. Unordered, that meant the worker pulled the\n * same head rows every cycle and never reached the tail: 96 cycles a day × 50\n * rows produced 357 surfaces against 3,316 packages.\n *\n * ponytail: `random()` guarantees the pass advances without a schema change, at\n * the cost of re-attempting permanent failures. If that retry waste starts\n * mattering, the upgrade is an `attempts`/`last_attempt_at` column on `packages`\n * (or a negative-cache row) plus exponential backoff — same shape as\n * `surface_queue.attempts` already uses on the demand-driven path.\n */\nexport async function getPackagesMissingSurface(\n db: Database,\n limit: number,\n): Promise<{ name: string; version: string }[]> {\n const rows = await db\n .select({ name: packages.name, version: packages.latestVersion })\n .from(packages)\n .leftJoin(\n apiSurfaces,\n and(\n eq(apiSurfaces.packageName, packages.name),\n eq(apiSurfaces.version, packages.latestVersion),\n ),\n )\n .where(and(isNotNull(packages.latestVersion), isNull(apiSurfaces.id)))\n .orderBy(sql`random()`)\n .limit(limit);\n return rows.filter((r): r is { name: string; version: string } => r.version !== null);\n}\n\n/** Cache a version's surface. Versions are immutable, so a stored surface is\n * authoritative; on the rare conflict we refresh rather than error. */\nexport async function upsertSurface(\n db: Database,\n packageName: string,\n version: string,\n surface: ExportSymbol[],\n): Promise<void> {\n await db\n .insert(apiSurfaces)\n .values({ packageName, version, surface })\n .onConflictDoUpdate({\n target: [apiSurfaces.packageName, apiSurfaces.version],\n set: { surface, extractedAt: new Date() },\n });\n}\n","/**\n * API surface extraction (§4D — usage axis D1). Ground truth is the package's\n * shipped `.d.ts`, parsed deterministically (no LLM) into a normalized export\n * list. Types are the code's real contract, extracted from the *exact* version —\n * no prose lag, no hallucination surface.\n *\n * We fetch the resolved types entry directly from the jsDelivr CDN rather than\n * download + untar the tarball: a single-file *syntactic* parse (createSourceFile,\n * no type-checker, no module resolution) captures top-level export presence and\n * signatures — the dominant drift class — without pulling the whole dep graph or\n * adding a `tar` dependency.\n *\n * The parse is per-file, but the walk is not: a barrel entry that only forwards\n * (`export * from './lib'`) is followed a bounded number of hops and merged, so\n * the entry's shape doesn't decide whether a package has a surface.\n *\n * Entry resolution covers `types`/`typings`, the `exports` map's root entry and\n * `index.d.ts`, then `@types/<name>` for packages that ship no types at all —\n * the whole 14-package popular-library sample in scripts/surface-coverage.mts\n * now extracts, where 5 did before. This matters more than it used to: while\n * extraction was worker-only a miss was just a gap, but now that a miss extracts\n * on the request path (usage/service) it bounds how often `usage` can answer at\n * all. Run that script after changing anything here.\n *\n * ponytail: what still degrades to null is a package whose types are reachable\n * only through a subpath (`pkg/submodule`) with no root entry, and one whose\n * barrel chain runs deeper than MAX_HOPS. Both fall back to the README.\n *\n * The compiler is loaded LAZILY and non-fatally, and that is load-bearing for the\n * plane split (§4E): `typescript` is a devDependency, present in the operator\n * runtime but never installed for consumers of the published package (which ships\n * `dist` only). A static `import ts from 'typescript'` here is hoisted by esbuild\n * into a top-level import of the public bundle, so every `lurqrun` command — not\n * just `usage` — would die at startup with ERR_MODULE_NOT_FOUND. Deferring the\n * import to the first extraction keeps it out of the bundle's static graph, and a\n * compiler that won't load degrades to null exactly like an untyped package.\n */\nimport { posix } from 'node:path';\nimport type * as TSApi from 'typescript';\nimport { HttpError, httpRequest } from '../core/http';\nimport { CACHE_TTL } from '../core/constants';\nimport type { ExportKind, ExportSymbol } from '../core/types';\n\n/** The compiler module itself, threaded through the parse helpers as a value so\n * nothing in this file references `typescript` at module scope. */\ntype Compiler = typeof TSApi;\n\nconst CDN = 'cdn.jsdelivr.net';\n\n/** HTTP tuning for the CDN fetches. The read path passes a tighter budget than\n * the worker: on the serving path a slow CDN must not hold a request open for\n * the default 15s × 4 attempts. */\nexport interface ExtractOptions {\n timeoutMs?: number;\n retries?: number;\n /** Wall-clock ceiling on one extraction, after which no further fetches start.\n * `timeoutMs` bounds a single fetch, but a barrel walk issues up to MAX_FILES\n * of them across MAX_HOPS waves, so only this bounds the whole thing. Omitted\n * → unbounded, which is what the worker wants: a cold jsDelivr edge can take\n * a minute for a wide barrel, and that extraction is the one warming the cache\n * for everyone after. */\n deadlineMs?: number;\n}\n\n/** One extraction's options with its deadline resolved to an absolute instant,\n * so every fetch in the walk measures against the same clock. */\ninterface Walk extends ExtractOptions {\n expiresAt: number;\n}\n\nfunction startWalk(opts: ExtractOptions): Walk {\n return {\n ...opts,\n expiresAt: opts.deadlineMs === undefined ? Infinity : Date.now() + opts.deadlineMs,\n };\n}\n\nlet compiler: Promise<Compiler | null> | undefined;\n\n/**\n * Load `typescript` once per process, resolving null when it isn't installed.\n * Memoized on the promise so concurrent cold misses share one module load, and\n * so a missing compiler is only probed once.\n */\nexport function loadCompiler(): Promise<Compiler | null> {\n compiler ??= import('typescript')\n .then((m) => (m as { default?: Compiler }).default ?? (m as unknown as Compiler))\n .catch(() => null);\n return compiler;\n}\n\ninterface FetchResult {\n text: string | null;\n /** True when the file's existence is unknown — a timeout, 5xx or network error\n * rather than a 404. A surface is only as trustworthy as the completeness of\n * the walk that built it, and the store is cache-forever, so this is what\n * keeps a transient CDN failure from being frozen in as a package's API. */\n unknown: boolean;\n}\n\nasync function fetchFile(\n url: string,\n opts: Walk,\n // Versions are immutable, so a long TTL is safe. Callers resolving a floating\n // range pass a shorter one.\n ttlMs: number = CACHE_TTL.depsDev,\n): Promise<FetchResult> {\n // Out of time counts as unknown, not absent: the walk is then unsound and its\n // partial result is discarded rather than cached as the package's API.\n if (Date.now() >= opts.expiresAt) return { text: null, unknown: true };\n try {\n const { data } = await httpRequest<string>(url, {\n host: CDN,\n ttlMs,\n accept: 'text',\n ...(opts.timeoutMs !== undefined ? { timeoutMs: opts.timeoutMs } : {}),\n ...(opts.retries !== undefined ? { retries: opts.retries } : {}),\n });\n return { text: typeof data === 'string' ? data : null, unknown: false };\n } catch (err) {\n // jsDelivr answers 404 for a path a package doesn't ship, which is a real\n // answer: that candidate simply isn't the file.\n const missing = err instanceof HttpError && err.status === 404;\n return { text: null, unknown: !missing };\n }\n}\n\nasync function fetchText(url: string, opts: Walk): Promise<string | null> {\n return (await fetchFile(url, opts)).text;\n}\n\nconst DTS_EXT = /\\.d\\.[cm]?ts$/;\nconst JS_EXT = /\\.(m|c)?js$/;\n\n/** The declaration file pairing with a path: itself if it already is one, else\n * the `.d.ts`/`.d.mts`/`.d.cts` sitting beside the JS. Null for anything else.\n * This is the \"types next to the JS\" rule TypeScript itself resolves by. */\nfunction declarationFor(path: string): string | null {\n if (DTS_EXT.test(path)) return path;\n const js = JS_EXT.exec(path);\n return js ? path.replace(JS_EXT, `.d.${js[1] ?? ''}ts`) : null;\n}\n\n/** Strip the leading `./` a manifest path carries; CDN paths are root-relative. */\nfunction relativeToRoot(path: string): string {\n return path.replace(/^\\.?\\//, '');\n}\n\n/** Conditions walked when reading the root entry out of an `exports` map, in\n * precedence order: an explicit types condition first (Node requires it to be\n * declared first for exactly this reason), then the runtime targets, whose\n * declaration siblings are the entry when no types condition exists at all. */\nconst EXPORT_CONDITIONS = ['types', 'typings', 'node', 'import', 'require', 'default'];\n\n/**\n * The root (`\".\"`) target of an `exports` map, as a declaration path. Packages\n * that publish through `exports` alone (execa, ora) have no `types` field to\n * read, and some (uuid) name no types condition either — there the JS target's\n * declaration sibling is what TypeScript would resolve.\n */\nexport function typesFromExports(exports: unknown, depth = 0): string | null {\n if (depth > 4) return null; // Pathological nesting isn't worth chasing.\n if (typeof exports === 'string') return declarationFor(exports);\n if (!exports || typeof exports !== 'object') return null;\n if (Array.isArray(exports)) {\n for (const alt of exports) {\n const found = typesFromExports(alt, depth + 1);\n if (found) return found;\n }\n return null;\n }\n const map = exports as Record<string, unknown>;\n // A subpath map: only the root entry describes the package's main surface.\n if ('.' in map) return typesFromExports(map['.'], depth + 1);\n if (Object.keys(map).some((k) => k.startsWith('.'))) return null;\n for (const condition of EXPORT_CONDITIONS) {\n if (!(condition in map)) continue;\n const found = typesFromExports(map[condition], depth + 1);\n if (found) return found;\n }\n return null;\n}\n\n/**\n * The `.d.ts` entry paths to try, most authoritative first: `types`/`typings`,\n * then the `exports` map's root target, then the conventional `index.d.ts`.\n * Ordered rather than singular because a `types` field can point at a file the\n * package doesn't actually ship (or ships only under `exports`), and a 404 there\n * shouldn't end the extraction.\n */\nfunction typesEntries(pkgJson: string): string[] {\n const entries: string[] = [];\n try {\n const manifest = JSON.parse(pkgJson);\n const declared: unknown = manifest.types ?? manifest.typings;\n if (typeof declared === 'string') entries.push(relativeToRoot(declared));\n const fromExports = typesFromExports(manifest.exports);\n if (fromExports) entries.push(relativeToRoot(fromExports));\n } catch {\n /* fall through to the conventional entry */\n }\n entries.push('index.d.ts');\n return [...new Set(entries)];\n}\n\nfunction kindOf(ts: Compiler, node: TSApi.Node): ExportKind {\n if (ts.isFunctionDeclaration(node)) return 'function';\n if (ts.isClassDeclaration(node)) return 'class';\n if (ts.isInterfaceDeclaration(node)) return 'interface';\n if (ts.isTypeAliasDeclaration(node)) return 'type';\n if (ts.isEnumDeclaration(node)) return 'enum';\n if (ts.isModuleDeclaration(node)) return 'namespace';\n if (ts.isVariableStatement(node)) return 'variable';\n return 'unknown';\n}\n\n/** Collapse whitespace so signatures compare cleanly across formatting changes. */\nfunction normalize(text: string): string {\n return text.replace(/\\s+/g, ' ').trim();\n}\n\n/** A function's `(params): return` signature; other kinds keep their head line. */\nfunction signatureOf(ts: Compiler, node: TSApi.Node, src: TSApi.SourceFile): string | null {\n if (ts.isFunctionDeclaration(node)) {\n const params = node.parameters.map((p) => normalize(p.getText(src))).join(', ');\n const ret = node.type ? `: ${normalize(node.type.getText(src))}` : '';\n return `(${params})${ret}`;\n }\n if (ts.isTypeAliasDeclaration(node)) return normalize(node.type.getText(src));\n // For classes/interfaces/enums the name+kind is the stable contract; a full\n // body diff is noisy. Keep null so `changed` only fires on real signature drift.\n return null;\n}\n\nfunction hasExportModifier(ts: Compiler, node: TSApi.Node): boolean {\n return (\n ts.canHaveModifiers(node) &&\n (ts.getModifiers(node)?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword) ?? false)\n );\n}\n\n/** What a statement declares, as `[localName, kind, signature]` tuples — a\n * `var`/`const` statement can declare several names, most statements one, and\n * anonymous ones none. Used both for the local index and for the exported\n * declarations themselves, so a name means the same thing either way. */\nfunction declarationsIn(\n ts: Compiler,\n node: TSApi.Node,\n src: TSApi.SourceFile,\n): Array<[string, ExportKind, string | null]> {\n if (ts.isVariableStatement(node)) {\n const out: Array<[string, ExportKind, string | null]> = [];\n for (const decl of node.declarationList.declarations) {\n if (ts.isIdentifier(decl.name)) {\n out.push([\n decl.name.text,\n 'variable',\n decl.type ? normalize(decl.type.getText(src)) : null,\n ]);\n }\n }\n return out;\n }\n const named = node as TSApi.DeclarationStatement;\n if (named.name && ts.isIdentifier(named.name)) {\n return [[named.name.text, kindOf(ts, node), signatureOf(ts, node, src)]];\n }\n return [];\n}\n\n/** One parsed `.d.ts`: what it exports itself, plus the `export * from '…'`\n * specifiers whose exports it forwards without naming (see `collectSurface`). */\nexport interface ParsedModule {\n symbols: ExportSymbol[];\n stars: string[];\n}\n\n/** Parse `.d.ts` text into a normalized, name-sorted export surface. The compiler\n * is passed in (see `loadCompiler`) rather than imported at module scope. */\nexport function parseSurface(source: string, ts: Compiler): ExportSymbol[] {\n return parseModule(source, ts).symbols;\n}\n\n/** `parseSurface`, also reporting the star re-exports it could not resolve alone. */\nexport function parseModule(source: string, ts: Compiler): ParsedModule {\n const src = ts.createSourceFile('surface.d.ts', source, ts.ScriptTarget.Latest, true);\n const out = new Map<string, ExportSymbol>();\n const stars: string[] = [];\n\n const add = (name: string, kind: ExportKind, signature: string | null) => {\n if (!out.has(name)) out.set(name, { name, kind, signature });\n };\n\n // Index every top-level declaration by local name, exported or not. A `.d.ts`\n // rolled up by rollup-plugin-dts or api-extractor (vite, helmet, and most\n // bundled types) is a wall of bare `declare`s closed by ONE `export { … }`\n // block, so the statement carrying a name's kind and signature is almost never\n // the statement that exports it. Private declarations stay private: nothing\n // reaches `out` unless an export form below names it.\n const local = new Map<string, { kind: ExportKind; signature: string | null }>();\n const namespaces = new Map<string, TSApi.ModuleDeclaration>();\n for (const node of src.statements) {\n for (const [name, kind, signature] of declarationsIn(ts, node, src)) {\n if (!local.has(name)) local.set(name, { kind, signature });\n }\n if (\n ts.isModuleDeclaration(node) &&\n ts.isIdentifier(node.name) &&\n !namespaces.has(node.name.text)\n ) {\n namespaces.set(node.name.text, node);\n }\n }\n\n /** Lift an ambient namespace's members to the top level. Members of a `declare\n * namespace` are all exported, with or without the keyword. */\n const liftNamespace = (decl: TSApi.ModuleDeclaration) => {\n if (!decl.body || !ts.isModuleBlock(decl.body)) return;\n for (const stmt of decl.body.statements) {\n for (const [name, kind, signature] of declarationsIn(ts, stmt, src))\n add(name, kind, signature);\n }\n };\n\n for (const node of src.statements) {\n // `export { … }`, `export * from …`, `export = …`: the `export` keyword is\n // part of these statements' own syntax rather than a modifier, so they carry\n // no modifiers at all and must be matched BEFORE the modifier gate below.\n if (ts.isExportDeclaration(node)) {\n const clause = node.exportClause;\n if (!clause) {\n // `export * from './lib'` — this file names nothing; the exports are in\n // the target, which only the caller can fetch.\n if (node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)) {\n stars.push(node.moduleSpecifier.text);\n }\n continue;\n }\n if (ts.isNamespaceExport(clause)) {\n // `export * as ns from './x'` binds the whole module under one name.\n add(clause.name.text, 'namespace', null);\n continue;\n }\n const reExport = node.moduleSpecifier !== undefined;\n for (const el of clause.elements) {\n // `export { Local as Public }` — the local binding holds the kind and\n // signature. A re-export from another module has neither, since a\n // single-file parse never sees that module's declarations.\n const decl = reExport ? undefined : local.get((el.propertyName ?? el.name).text);\n const typeOnly = node.isTypeOnly || el.isTypeOnly;\n add(el.name.text, decl?.kind ?? (typeOnly ? 'type' : 'unknown'), decl?.signature ?? null);\n }\n continue;\n }\n\n if (ts.isExportAssignment(node) && ts.isIdentifier(node.expression)) {\n const target = node.expression.text;\n const decl = local.get(target);\n // The exported value itself is `default`: that is the name an importing\n // agent binds it to, for both `export default x` and `export = x` under\n // esModuleInterop.\n if (decl) add('default', decl.kind, decl.signature);\n // `export = e` is the CommonJS shape (@types/express, @types/react): the\n // module's whole surface lives in a namespace merged onto `e`, so the\n // members ARE the public API, not properties of one exported symbol.\n const ns = node.isExportEquals ? namespaces.get(target) : undefined;\n if (ns) liftNamespace(ns);\n continue;\n }\n\n if (!hasExportModifier(ts, node)) continue;\n for (const [name, kind, signature] of declarationsIn(ts, node, src)) add(name, kind, signature);\n }\n\n return { symbols: [...out.values()].sort((a, b) => a.name.localeCompare(b.name)), stars };\n}\n\n/**\n * The `.d.ts` files a relative specifier could resolve to, most likely first.\n * Empty for anything this parse has no business fetching: a bare specifier names\n * another package, and a path climbing out of the version root isn't ours.\n */\nexport function dtsCandidates(fromFile: string, specifier: string): string[] {\n if (!specifier.startsWith('./') && !specifier.startsWith('../')) return [];\n const path = posix.normalize(posix.join(posix.dirname(fromFile), specifier));\n if (path.startsWith('..')) return [];\n // `export * from './table.js'` is the ESM `.d.ts` idiom (drizzle-orm).\n const paired = declarationFor(path);\n if (paired) return [paired];\n // Extensionless (zod's `export * from './lib'`): a sibling, else a directory\n // barrel. Ordered, not raced — the first almost always hits, so the second\n // costs a round-trip only for real directories.\n return [`${path}.d.ts`, `${path}/index.d.ts`];\n}\n\n/** How far a barrel chain is followed. zod needs all three hops: index.d.ts →\n * lib/index.d.ts → lib/external.d.ts → the leaves that actually declare things. */\nconst MAX_HOPS = 3;\n\n/** Ceiling on files fetched per extraction, across all hops. Bounds a wide\n * barrel (drizzle-orm forwards 14 modules from its entry, each of which\n * forwards more) so a request-path extraction can't fan out without limit. */\nconst MAX_FILES = 24;\n\n/**\n * Merge a barrel's chain into one surface: parse `source`, then follow whatever\n * `export * from` it defers to, breadth-first. Bounded on both axes — MAX_HOPS\n * deep, MAX_FILES wide — because this runs on the `usage` read path under a\n * wall-clock budget; each hop's fetches go out in parallel so the cost is hops,\n * not files. Shallowest definition wins, so a barrel's own naming of a symbol\n * beats one it forwards.\n *\n * `sound` is false if any followed file couldn't be fetched. Stopping at the\n * caps is deliberate and deterministic — the same package always yields the same\n * surface — but a timed-out hop yields an arbitrary subset, and the caller\n * caches forever, so that one must not be mistaken for a package's API.\n */\nasync function collectSurface(\n ts: Compiler,\n root: string,\n entry: string,\n source: string,\n opts: Walk,\n): Promise<{ symbols: ExportSymbol[]; sound: boolean }> {\n const merged = new Map<string, ExportSymbol>();\n const attempted = new Set<string>([entry]);\n let budget = MAX_FILES;\n let sound = true;\n\n /** Absorb one file's exports; hand back the candidate lists it defers to. */\n const absorb = (file: string, text: string): string[][] => {\n const { symbols, stars } = parseModule(text, ts);\n for (const s of symbols) if (!merged.has(s.name)) merged.set(s.name, s);\n return stars.map((spec) => dtsCandidates(file, spec)).filter((c) => c.length > 0);\n };\n\n /** Fetch the first candidate that exists. These are alternatives for ONE\n * specifier, so they're tried in order rather than raced. `attempted` doubles\n * as the cycle guard: a barrel that re-exports its own ancestor stops here. */\n const fetchFirst = async (candidates: string[]): Promise<[string, string] | null> => {\n for (const file of candidates) {\n if (attempted.has(file) || budget <= 0) continue;\n attempted.add(file);\n budget--;\n const { text, unknown } = await fetchFile(`${root}/${file}`, opts);\n if (text !== null) return [file, text];\n if (unknown) {\n sound = false;\n return null; // Don't read a 404 into the next candidate; we never got one.\n }\n }\n return null;\n };\n\n let frontier = absorb(entry, source);\n for (let hop = 0; hop < MAX_HOPS && frontier.length > 0 && budget > 0; hop++) {\n const fetched = await Promise.all(frontier.map(fetchFirst));\n frontier = fetched.flatMap((hit) => (hit ? absorb(hit[0], hit[1]) : []));\n }\n\n return { symbols: [...merged.values()].sort((a, b) => a.name.localeCompare(b.name)), sound };\n}\n\n/**\n * Walk one package version root: try its types entries in order, stopping at the\n * first that yields a surface. Tried in order and only as far as needed, so a\n * package whose `types` field resolves — the overwhelming majority — pays\n * nothing for the fallbacks behind it.\n */\nasync function surfaceFrom(\n ts: Compiler,\n root: string,\n pkgJson: string,\n opts: Walk,\n): Promise<ExportSymbol[] | null> {\n for (const entry of typesEntries(pkgJson)) {\n const dts = await fetchText(`${root}/${entry}`, opts);\n if (!dts) continue;\n const { symbols, sound } = await collectSurface(ts, root, entry, dts, opts);\n // An unsound walk degrades to null rather than to a partial surface: null\n // means \"fall back to the README\" and is retried on the next request, while\n // a stored surface is believed forever. Under the read path's tight fetch\n // ceiling that is the likely outcome for a wide barrel on a cold CDN edge —\n // the worker, with the default timeouts, extracts it in full later.\n if (sound && symbols.length > 0) return symbols;\n }\n return null;\n}\n\n/** DefinitelyTyped's package name for a library: a scoped `@scope/name` mangles\n * to `@types/scope__name`, since npm scopes don't nest. */\nexport function typesPackageName(name: string): string {\n return name.startsWith('@') ? `@types/${name.slice(1).replace('/', '__')}` : `@types/${name}`;\n}\n\n/**\n * The surface from DefinitelyTyped, for packages that ship no types of their own\n * (react, express, semver). Pinned to the MATCHING MAJOR, never to `latest`:\n * @types/react's latest types React 19, and storing that as react@18.3.1's API\n * would be a confident wrong answer rather than a missing one. Within the major\n * there is still skew — @types/semver@7.8.0 answers for semver@7.7.2 — which is\n * the approximation DefinitelyTyped's own versioning offers.\n */\nasync function typesPackageSurface(\n ts: Compiler,\n name: string,\n version: string,\n opts: Walk,\n): Promise<ExportSymbol[] | null> {\n const major = /^\\d+/.exec(version)?.[0];\n if (!major) return null;\n const dt = typesPackageName(name);\n // jsDelivr resolves the range and 404s when DefinitelyTyped has no matching\n // major. The manifest reports which version answered, and the file fetches\n // pin to it so a walk can't straddle two releases mid-flight.\n const { text: pkgJson } = await fetchFile(\n `https://${CDN}/npm/${dt}@${major}/package.json`,\n opts,\n CACHE_TTL.npmRegistry, // A floating range: don't hold it for a day.\n );\n if (!pkgJson) return null;\n let resolved: unknown;\n try {\n resolved = JSON.parse(pkgJson).version;\n } catch {\n return null;\n }\n if (typeof resolved !== 'string') return null;\n return surfaceFrom(ts, `https://${CDN}/npm/${dt}@${resolved}`, pkgJson, opts);\n}\n\n/**\n * Extract the public API surface for `name@version`, or null if types can't be\n * resolved. Deterministic and cache-forever (versions are immutable).\n *\n * The compiler is resolved *before* the CDN fetches so a runtime without\n * `typescript` costs nothing but the (memoized) failed import.\n */\nexport async function extractSurface(\n name: string,\n version: string,\n opts: ExtractOptions = {},\n): Promise<ExportSymbol[] | null> {\n const ts = await loadCompiler();\n if (!ts) return null;\n // The deadline starts after the compiler load, not before: that cost is paid\n // once per process and isn't what a per-extraction ceiling is guarding.\n const walk = startWalk(opts);\n const root = `https://${CDN}/npm/${name}@${version}`;\n const pkgJson = await fetchText(`${root}/package.json`, walk);\n // No manifest means no answer either way. Falling through to @types here would\n // turn an unreachable CDN into a surface attributed to a package we never\n // established ships none of its own.\n if (!pkgJson) return null;\n return (\n (await surfaceFrom(ts, root, pkgJson, walk)) ?? typesPackageSurface(ts, name, version, walk)\n );\n}\n","/** Usage-axis serving layer (§4D): read-through the surface cache, extracting\n * on a miss. Shared by the `usage` handler and the discovery worker (§4G). */\nimport type { ExportSymbol } from '../core/types';\nimport type { Database } from '../db/client';\nimport { getStoredSurface, upsertSurface } from '../db/apiSurfaces';\nimport { extractSurface, type ExtractOptions } from './extract';\n\n/** Block-on-first-touch budget for the `usage` read path, mirroring\n * FIRST_TOUCH_BUDGET_MS (§4A): past this the caller gets the README-fallback\n * note while the extraction finishes in the background, so the *next* request\n * for that version is a cache hit. */\nexport const USAGE_EXTRACT_BUDGET_MS = 4000;\n\n/** CDN fetch tuning for the read path. The http default (15s × 4 attempts) is\n * sized for the worker; on a request path a stuck jsDelivr must not outlive the\n * budget by minutes, since the abandoned extraction keeps holding one of the\n * 6 per-host connection slots.\n *\n * `deadlineMs` is what actually bounds that, now that resolving a package can\n * mean walking a barrel over many files rather than fetching two: `timeoutMs`\n * only bounds one fetch. It sits well past USAGE_EXTRACT_BUDGET_MS on purpose —\n * an extraction the caller has already given up waiting for is still the one\n * warming the cache for the next request, and cutting it at the budget would\n * mean a slow package never gets extracted on this path at all. */\nconst READ_PATH_FETCH: ExtractOptions = { timeoutMs: 3000, retries: 0, deadlineMs: 15_000 };\n\n/** A flood of distinct versions must not grow memory without limit (same reason\n * ingestQueue caps its backlog). Past the cap a miss degrades to the note. */\nconst MAX_INFLIGHT = 64;\n\n/** Extractions in progress, keyed `name@version`, so concurrent misses for the\n * same version share one CDN round-trip instead of N. */\nconst inFlight = new Map<string, Promise<ExportSymbol[] | null>>();\n\nexport interface SurfaceLookupOptions {\n /** Wall-clock budget for a cold-miss extraction. Omitted → wait for it (the\n * worker and the landing-content generator want the surface, not a fast no).\n * 0 → skip extraction entirely (cache-only). */\n budgetMs?: number;\n /** Override the CDN fetch timeout/retries. */\n fetch?: ExtractOptions;\n}\n\n/** Resolve with the task's value, or null once `budgetMs` elapses. The task is\n * deliberately NOT cancelled: its cache write is the point. */\nfunction raceBudget<T>(task: Promise<T>, budgetMs: number): Promise<T | null> {\n return Promise.race([task, new Promise<null>((resolve) => setTimeout(resolve, budgetMs, null))]);\n}\n\n/** Start (or join) the single extraction for `name@version`. */\nfunction extractOnce(\n db: Database,\n name: string,\n version: string,\n fetchOpts: ExtractOptions,\n): Promise<ExportSymbol[] | null> {\n const key = `${name}@${version}`;\n const existing = inFlight.get(key);\n if (existing) return existing;\n if (inFlight.size >= MAX_INFLIGHT) return Promise.resolve(null);\n\n const task = extractSurface(name, version, fetchOpts)\n .then(async (extracted) => {\n // Best-effort write: a database at its size limit must not turn a\n // successful extraction into a failed read.\n if (extracted) await upsertSurface(db, name, version, extracted).catch(() => {});\n return extracted;\n })\n .catch(() => null)\n .finally(() => inFlight.delete(key));\n\n inFlight.set(key, task);\n return task;\n}\n\n/**\n * The API surface for `name@version` from cache, or extract-and-store on a miss.\n * Returns null when types can't be resolved (caller falls back to README).\n * Cache-forever: versions are immutable.\n */\nexport async function getOrExtractSurface(\n db: Database,\n name: string,\n version: string,\n opts: SurfaceLookupOptions = {},\n): Promise<ExportSymbol[] | null> {\n const stored = await getStoredSurface(db, name, version);\n if (stored) return stored;\n if (opts.budgetMs === 0) return null;\n\n // A budget means a caller is waiting on a request path, which is also what\n // justifies the tighter fetch ceiling; the unbudgeted worker keeps the http\n // defaults so a slow-but-working CDN still yields a surface.\n const fetchOpts = opts.fetch ?? (opts.budgetMs === undefined ? {} : READ_PATH_FETCH);\n const task = extractOnce(db, name, version, fetchOpts);\n return opts.budgetMs === undefined ? task : raceBudget(task, opts.budgetMs);\n}\n\n/** Test-only: drop memoized in-flight extractions. */\nexport function resetSurfaceInflight(): void {\n inFlight.clear();\n}\n","/** Read/write helpers for sandbox verification results (`verification_runs`). */\nimport { desc, eq } from 'drizzle-orm';\nimport type { Database } from './client';\nimport {\n verificationRuns,\n type NewVerificationRunRow,\n type VerificationRunRow,\n} from './schema';\n\nexport async function storeVerificationRun(\n db: Database,\n run: NewVerificationRunRow,\n): Promise<void> {\n await db.insert(verificationRuns).values(run);\n}\n\n/** Most recent run for a package (any version), if any — for the evaluate verdict. */\nexport async function getLatestVerificationByName(\n db: Database,\n packageName: string,\n): Promise<VerificationRunRow | null> {\n const rows = await db\n .select()\n .from(verificationRuns)\n .where(eq(verificationRuns.packageName, packageName))\n .orderBy(desc(verificationRuns.ranAt))\n .limit(1);\n return rows[0] ?? null;\n}\n","/** Read/write helpers for recommendation→outcome capture (`recommendation_outcomes`, §3.1). */\nimport { desc, eq } from 'drizzle-orm';\nimport type { Database } from './client';\nimport {\n recommendationOutcomes,\n type NewRecommendationOutcomeRow,\n type RecommendationOutcomeRow,\n} from './schema';\n\n/** Record one opt-in outcome. Insert-only — the dataset is append-only by design. */\nexport async function recordOutcome(\n db: Database,\n outcome: NewRecommendationOutcomeRow,\n): Promise<void> {\n await db.insert(recommendationOutcomes).values(outcome);\n}\n\n/** One owner's outcome history, newest first — powers the dashboard activity feed. */\nexport async function getOutcomesByOwner(\n db: Database,\n ownerId: string,\n opts: { limit?: number } = {},\n): Promise<RecommendationOutcomeRow[]> {\n return db\n .select()\n .from(recommendationOutcomes)\n .where(eq(recommendationOutcomes.ownerId, ownerId))\n .orderBy(desc(recommendationOutcomes.createdAt))\n .limit(opts.limit ?? 50);\n}\n","{\n \"moment\": {\n \"replacedBy\": \"dayjs\",\n \"reason\": \"In maintenance mode since 2020 (the maintainers recommend alternatives). dayjs is a ~2KB immutable library with a near-identical API.\"\n },\n \"request\": {\n \"replacedBy\": \"got\",\n \"reason\": \"Deprecated in 2020 and no longer maintained. Use the built-in fetch, or got for a full-featured HTTP client.\"\n },\n \"request-promise\": {\n \"replacedBy\": \"got\",\n \"reason\": \"Deprecated alongside request. got returns promises natively.\"\n },\n \"node-sass\": {\n \"replacedBy\": \"sass\",\n \"reason\": \"Deprecated; bindings break on new Node versions. sass is the Dart implementation (sass-embedded for speed).\"\n },\n \"tslint\": {\n \"replacedBy\": \"typescript-eslint\",\n \"reason\": \"Deprecated in 2019 in favor of ESLint. Use typescript-eslint to lint TypeScript.\"\n },\n \"enzyme\": {\n \"replacedBy\": \"@testing-library/react\",\n \"reason\": \"Unmaintained with no official React 17+/18 adapter. React Testing Library is the current standard.\"\n },\n \"protractor\": {\n \"replacedBy\": \"@playwright/test\",\n \"reason\": \"Reached end-of-life in 2023. Use Playwright (or Cypress) for browser E2E.\"\n },\n \"faker\": {\n \"replacedBy\": \"@faker-js/faker\",\n \"reason\": \"The original package was sabotaged and deprecated. @faker-js/faker is the community-maintained fork.\"\n },\n \"bower\": {\n \"replacedBy\": \"npm\",\n \"reason\": \"Deprecated; front-end packages ship on npm now. Use npm (or your package manager) directly.\"\n },\n \"popper.js\": {\n \"replacedBy\": \"@popperjs/core\",\n \"reason\": \"v1 is deprecated. @popperjs/core is the maintained v2 line.\"\n },\n \"create-react-app\": {\n \"replacedBy\": \"vite\",\n \"reason\": \"No longer recommended by the React team and effectively unmaintained. Vite is the current scaffolding standard.\"\n },\n \"babel-eslint\": {\n \"replacedBy\": \"@babel/eslint-parser\",\n \"reason\": \"Deprecated and renamed. Use @babel/eslint-parser.\"\n },\n \"istanbul\": {\n \"replacedBy\": \"nyc\",\n \"reason\": \"The istanbul package is legacy; nyc is its maintained CLI (or c8 for native V8 coverage).\"\n }\n}\n","/**\n * Deprecation → replacement map (§1.2). Agents confidently recommend dead\n * packages (moment, request, …) because their training data froze when those\n * were popular; lurq's freshness is exactly the corrective. This is the curated\n * seed the roadmap calls for — a small, high-confidence set of genuinely\n * superseded packages. Later this graph is learned from outcome data (§3.1);\n * for now it's hand-verified so `evaluate` never steers an agent wrong.\n */\nimport successors from '../data/successors.json';\n\nexport interface Successor {\n /** The package to migrate to. */\n name: string;\n /** Why the original is dead and this replaces it. */\n reason: string;\n}\n\nconst MAP = successors as Record<string, { replacedBy: string; reason: string }>;\n\n/** The recommended successor for a superseded package, or null if it isn't one. */\nexport function lookupSuccessor(name: string): Successor | null {\n const hit = MAP[name.toLowerCase()];\n return hit ? { name: hit.replacedBy, reason: hit.reason } : null;\n}\n","/**\n * GitHub raw README fallback (§9.6). The npm packument `readme` field is often\n * empty (e.g. zod), so we fetch the repo README directly when needed. Public\n * raw content needs no token.\n */\nimport { CACHE_TTL } from '../../core/constants';\nimport { httpRequest } from '../../core/http';\n\nconst HOST = 'raw.githubusercontent.com';\nconst CANDIDATES = ['README.md', 'readme.md', 'README.markdown', 'README'];\n\nexport async function fetchGithubReadme(\n owner: string,\n repo: string,\n fetchImpl?: typeof fetch,\n): Promise<string | null> {\n for (const file of CANDIDATES) {\n const url = `https://${HOST}/${owner}/${repo}/HEAD/${file}`;\n try {\n const { data } = await httpRequest<string>(url, {\n host: HOST,\n ttlMs: CACHE_TTL.github,\n accept: 'text',\n retries: 0,\n fetchImpl,\n });\n if (data && data.trim().length > 0) return data;\n } catch {\n /* try the next candidate */\n }\n }\n return null;\n}\n","/**\n * Summary + usage-guide generation (§9.6 + R1 explainer refinement).\n *\n * lurq generates its OWN guide grounded in the package's README/description —\n * it never depends on Context7. When a summary LLM key is configured we use it;\n * otherwise we fall back to the npm description + a category-derived guide,\n * fabricating nothing. The exact current API is deferred to Context7 via a hint.\n */\nimport { CATEGORIES, isCategory, type Category, type UsageGuide } from '../core/types';\nimport { getConfig } from '../core/config';\nimport { httpRequest } from '../core/http';\nimport { logger } from '../core/logger';\nimport { fetchGithubReadme } from './sources/githubReadme';\nimport type { RawPackageSignals } from './types';\n\nexport interface SummaryInput {\n name: string;\n description: string | null;\n category: Category | null;\n readme: string | null;\n repoUrl: string | null;\n}\n\nexport interface SummaryResult {\n summary: string | null;\n usageGuide: UsageGuide;\n /** Taxonomy category the LLM classified the package into (§2A), or null\n * (always null for the fallback provider — it does no classification). */\n inferredCategory: Category | null;\n}\n\nexport interface SummaryProvider {\n readonly kind: 'openai' | 'fallback';\n generate(input: SummaryInput): Promise<SummaryResult>;\n}\n\n/** Human-readable architectural role per category (generic — lurq has no code context). */\nconst CATEGORY_ROLE: Record<string, string> = {\n framework: 'the core application framework your app is built on',\n 'meta-framework': 'the full-stack framework wrapping routing, rendering, and build',\n 'state-management': 'the client state layer shared across components',\n routing: 'the routing layer mapping URLs to views',\n orm: 'the data-access layer between your code and the database',\n 'database-client': 'the low-level driver that talks to your database',\n 'ui-component-library': 'the prebuilt UI component layer',\n styling: 'the styling layer for your components',\n forms: 'form state and submission handling',\n validation: 'input/schema validation at your boundaries',\n 'data-fetching': 'the server-state/data-fetching layer',\n 'http-client': 'the HTTP request layer for calling APIs',\n auth: 'authentication and session handling',\n testing: 'the test tooling layer',\n 'build-tool': 'the build/dev pipeline',\n bundler: 'the module bundling step',\n linting: 'code-quality and formatting checks',\n 'date-time': 'date and time handling',\n animation: 'UI animation and motion',\n charts: 'data visualization and charts',\n i18n: 'internationalization and localization',\n utility: 'a focused helper you compose into your app',\n other: 'a supporting library in your app',\n};\n\nfunction context7Hint(name: string): string {\n return `For the exact current API of \"${name}\", resolve it via Context7 (resolve-library-id → query-docs).`;\n}\n\n/** Keep text to ~`max` sentences. */\nexport function truncateSentences(text: string, max = 3): string {\n const clean = text.replace(/\\s+/g, ' ').trim();\n if (!clean) return '';\n // Match full sentences, plus a trailing fragment with no terminal punctuation\n // (so descriptions without a period return the whole text, not just the last word).\n const sentences = clean.match(/[^.!?]+[.!?]+|[^.!?]+$/g) ?? [clean];\n return sentences\n .slice(0, max)\n .map((s) => s.trim())\n .join(' ')\n .trim();\n}\n\n// ── Fallback provider (no LLM key) ──────────────────────────────────────────\n\nexport class FallbackSummaryProvider implements SummaryProvider {\n readonly kind = 'fallback' as const;\n\n async generate(input: SummaryInput): Promise<SummaryResult> {\n const description = input.description?.trim() || null;\n const role = CATEGORY_ROLE[input.category ?? 'other'] ?? CATEGORY_ROLE.other!;\n const summary = description ? truncateSentences(description, 3) : null;\n const guide: UsageGuide = {\n whatItIs: description ? truncateSentences(description, 2) : input.name,\n whenToUse: `Reach for ${input.name} when you need ${role}.`,\n whereItFits: `Sits at ${role}.`,\n context7Hint: context7Hint(input.name),\n };\n return { summary, usageGuide: guide, inferredCategory: null };\n }\n}\n\n// ── OpenAI provider (raw fetch, no SDK dependency) ──────────────────────────\n\nconst SYSTEM_PROMPT =\n 'You summarize npm packages factually for an AI coding agent choosing dependencies. ' +\n 'Use ONLY the provided README/description. Never invent capabilities or APIs. ' +\n 'Be concise and concrete. Respond with a JSON object.';\n\nfunction buildUserPrompt(input: SummaryInput): string {\n const readme = (input.readme ?? '').slice(0, 4000);\n // Ask the model to classify only when we don't already have a curated category\n // (§2A) — otherwise the curated value wins and we save the model the choice.\n const needsCategory = input.category == null;\n return [\n `Package: ${input.name}`,\n `Category: ${input.category ?? 'unknown'}`,\n `Description: ${input.description ?? '(none)'}`,\n `README (truncated):\\n${readme || '(none)'}`,\n '',\n 'Return JSON with keys:',\n '- \"summary\": 2-3 sentences: what it is, when to use it, how it fits an app.',\n '- \"whatItIs\": one sentence.',\n '- \"whenToUse\": one sentence on the ideal use case.',\n '- \"whenNotToUse\": one sentence on when to pick something else (or \"\").',\n '- \"whereItFits\": one sentence on its architectural role.',\n '- \"howToWireIn\": one short sentence on the minimal setup (install + entry point), or \"\".',\n ...(needsCategory\n ? [`- \"category\": the single best fit from this list: ${CATEGORIES.join(', ')}.`]\n : []),\n ].join('\\n');\n}\n\nexport class OpenAISummaryProvider implements SummaryProvider {\n readonly kind = 'openai' as const;\n\n private readonly endpoint: string;\n private readonly host: string;\n\n constructor(\n private readonly apiKey: string,\n private readonly model: string,\n baseUrl: string,\n private readonly fetchImpl?: typeof fetch,\n ) {\n this.endpoint = `${baseUrl.replace(/\\/$/, '')}/chat/completions`;\n this.host = new URL(baseUrl).host;\n }\n\n async generate(input: SummaryInput): Promise<SummaryResult> {\n try {\n const body = JSON.stringify({\n model: this.model,\n messages: [\n { role: 'system', content: SYSTEM_PROMPT },\n { role: 'user', content: buildUserPrompt(input) },\n ],\n response_format: { type: 'json_object' },\n temperature: 0.2,\n });\n const { data } = await httpRequest<any>(this.endpoint, {\n host: this.host,\n method: 'POST',\n ttlMs: 30 * 24 * 60 * 60 * 1000, // cache summaries 30d to control cost\n cacheKey: `openai-summary ${this.model} ${input.name} ${(input.readme ?? '').length}`,\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n 'Content-Type': 'application/json',\n },\n body,\n fetchImpl: this.fetchImpl,\n });\n const content = data?.choices?.[0]?.message?.content;\n const parsed = content ? JSON.parse(content) : {};\n const guide: UsageGuide = {\n whatItIs: str(parsed.whatItIs) || input.name,\n whenToUse: str(parsed.whenToUse),\n whenNotToUse: str(parsed.whenNotToUse) || undefined,\n whereItFits: str(parsed.whereItFits),\n howToWireIn: str(parsed.howToWireIn) || undefined,\n context7Hint: context7Hint(input.name),\n };\n const rawCategory = str(parsed.category);\n const inferredCategory = rawCategory && isCategory(rawCategory) ? rawCategory : null;\n return {\n summary: str(parsed.summary) ? truncateSentences(parsed.summary, 3) : null,\n usageGuide: guide,\n inferredCategory,\n };\n } catch (err) {\n logger.warn(`summary LLM failed for ${input.name}, using fallback: ${(err as Error).message}`);\n return new FallbackSummaryProvider().generate(input);\n }\n }\n}\n\nfunction str(value: unknown): string {\n return typeof value === 'string' ? value.trim() : '';\n}\n\n// ── Factory + input assembly ────────────────────────────────────────────────\n\nexport function createSummaryProvider(fetchImpl?: typeof fetch): SummaryProvider {\n const config = getConfig();\n if (config.SUMMARY_PROVIDER === 'openai' && config.SUMMARY_API_KEY) {\n return new OpenAISummaryProvider(\n config.SUMMARY_API_KEY,\n config.SUMMARY_MODEL,\n config.SUMMARY_BASE_URL,\n fetchImpl,\n );\n }\n return new FallbackSummaryProvider();\n}\n\n/** Assemble the summary input, fetching the GitHub-raw README when npm's is empty. */\nexport async function buildSummaryInput(\n signals: RawPackageSignals,\n category: Category | null,\n fetchImpl?: typeof fetch,\n): Promise<SummaryInput> {\n const registry = signals.registry;\n let readme = registry?.readme?.trim() || null;\n if (!readme && registry?.repo) {\n readme = await fetchGithubReadme(registry.repo.owner, registry.repo.repo, fetchImpl).catch(\n () => null,\n );\n }\n return {\n name: signals.name,\n description: registry?.description ?? null,\n category,\n readme,\n repoUrl: registry?.repoUrl ?? null,\n };\n}\n","/**\n * Gather all source signals for one package (§9.7 steps 1–5). Fault-isolated:\n * each source is wrapped so a single failure records an error and degrades that\n * signal to null rather than failing the package (§17).\n */\nimport { logger } from '../core/logger';\nimport type { Category } from '../core/types';\nimport { fetchBundlephobia } from './sources/bundlephobia';\nimport { fetchDepsDev } from './sources/depsDev';\nimport { fetchGithubRepo } from './sources/github';\nimport { fetchDownloadGrowth, fetchWeeklyDownloads } from './sources/npmDownloads';\nimport { fetchNpmRegistry } from './sources/npmRegistry';\nimport type { NpmDownloadsData, RawPackageSignals } from './types';\n\nexport interface CollectDeps {\n githubToken?: string;\n fetchImpl?: typeof fetch;\n /**\n * Pre-fetched weekly downloads (from the bulk endpoint). When provided (even\n * as null), the per-package weekly fetch is skipped — avoiding the downloads\n * API's harsh rate limits during a full sync.\n */\n prefetchedWeekly?: number | null;\n}\n\nasync function attempt<T>(\n source: string,\n errors: { source: string; message: string }[],\n fn: () => Promise<T>,\n): Promise<T | null> {\n try {\n return await fn();\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n errors.push({ source, message });\n logger.debug(`[${source}] ${message}`);\n return null;\n }\n}\n\nexport async function collectSignals(\n name: string,\n category: Category | null,\n deps: CollectDeps = {},\n): Promise<RawPackageSignals> {\n const { githubToken, fetchImpl } = deps;\n const errors: { source: string; message: string }[] = [];\n\n // 1. Registry first — it provides the repo + version the other sources need.\n const registry = await attempt('npm-registry', errors, () => fetchNpmRegistry(name, fetchImpl));\n\n const repo = registry?.repo ?? null;\n const version = registry?.latestVersion ?? null;\n\n // 2–5. The rest run concurrently.\n const [downloads, github, depsDev, bundle] = await Promise.all([\n attempt('npm-downloads', errors, async (): Promise<NpmDownloadsData> => {\n const weeklyDownloads =\n deps.prefetchedWeekly !== undefined\n ? deps.prefetchedWeekly\n : await fetchWeeklyDownloads(name, fetchImpl);\n const downloadGrowth90d = await fetchDownloadGrowth(name, fetchImpl);\n return { weeklyDownloads, downloadGrowth90d };\n }),\n repo && githubToken\n ? attempt('github', errors, () => fetchGithubRepo(repo.owner, repo.repo, githubToken, fetchImpl))\n : Promise.resolve(null),\n attempt('deps-dev', errors, () => fetchDepsDev(name, version, repo, fetchImpl)),\n attempt('bundlephobia', errors, () => fetchBundlephobia(name, category, fetchImpl)),\n ]);\n\n return { name, registry, downloads, github, depsDev, bundle, errors };\n}\n","/**\n * Lightweight category inference (§11). Maps a natural-language need to a\n * taxonomy category via keyword matching. Returns null when uncertain, so the\n * caller searches across all categories rather than over-filtering.\n */\nimport type { Category } from '../core/types';\nimport type { RawPackageSignals } from '../ingestion/types';\n\nconst RULES: { category: Category; patterns: RegExp }[] = [\n { category: 'meta-framework', patterns: /\\b(meta-?framework|next\\.?js|nuxt|remix|astro|gatsby|sveltekit|full-?stack framework)\\b/ },\n { category: 'state-management', patterns: /\\b(state management|global state|store|redux|zustand|jotai|mobx|atoms?)\\b/ },\n { category: 'routing', patterns: /\\b(rout(e|er|ing)|navigation|url matching)\\b/ },\n { category: 'orm', patterns: /\\b(orm|object-?relational|query builder|prisma|drizzle|sequelize|typeorm)\\b/ },\n { category: 'database-client', patterns: /\\b(database (driver|client)|postgres|mysql|mongo(db)?|redis|sqlite|db driver)\\b/ },\n { category: 'ui-component-library', patterns: /\\b(component library|ui kit|ui components?|design system|buttons?|modal|dialog)\\b/ },\n { category: 'styling', patterns: /\\b(styl(e|ing)|css|tailwind|sass|scss|class ?names?|theme)\\b/ },\n { category: 'forms', patterns: /\\b(forms?|form (state|library|handling)|input handling)\\b/ },\n { category: 'validation', patterns: /\\b(validat(e|ion|or)|schema|parse input|type ?safe parsing)\\b/ },\n { category: 'data-fetching', patterns: /\\b(data fetching|server state|react query|swr|graphql client|caching queries)\\b/ },\n { category: 'http-client', patterns: /\\b(http client|fetch wrapper|rest client|make (a )?request|ajax|api calls?)\\b/ },\n { category: 'auth', patterns: /\\b(auth(entication|orization)?|login|session|jwt|oauth|password hashing)\\b/ },\n { category: 'testing', patterns: /\\b(test(ing|s)?|unit test|e2e|assertion|mocking|test runner)\\b/ },\n { category: 'bundler', patterns: /\\b(bundler|bundle (modules?|code)|webpack|rollup|esbuild|parcel)\\b/ },\n { category: 'build-tool', patterns: /\\b(build tool|dev server|monorepo|task runner|compile|transpile)\\b/ },\n // date-time precedes linting: \"date formatting\" must not be captured by linting's\n // bare \"formatting\" token before the date rule is reached (first-match-wins).\n { category: 'date-time', patterns: /\\b(dates?|date ?time|time(zone)?s?|calendar|parse dates?|format dates?)\\b/ },\n { category: 'linting', patterns: /\\b(lint(er|ing)?|formatter|formatting|code (quality|style|format)|prettier|eslint)\\b/ },\n { category: 'animation', patterns: /\\b(animat(e|ion)|motion|transition|spring|gsap|3d)\\b/ },\n { category: 'charts', patterns: /\\b(charts?|graphs?|data ?vis(ualization)?|plots?|dashboards?)\\b/ },\n { category: 'i18n', patterns: /\\b(i18n|internationali[sz]ation|localization|translat(e|ion)|locale)\\b/ },\n { category: 'framework', patterns: /\\b(framework|react|vue|svelte|angular|web server|backend framework)\\b/ },\n { category: 'utility', patterns: /\\b(debounce|throttle|deep ?clone|slugify|uuid|util(ity|ities)?|helper|lodash|retry)\\b/ },\n];\n\nexport function inferCategory(need: string): Category | null {\n const text = need.toLowerCase();\n for (const rule of RULES) {\n if (rule.patterns.test(text)) return rule.category;\n }\n return null;\n}\n\n/**\n * Categorize-on-ingest (§2A): infer a category from a package's *own* text —\n * name, keywords, description, and the README head — instead of a user query.\n * Keywords are repeated to give them extra weight (they're the most reliable\n * categorical signal). Returns null when no rule matches; the caller then falls\n * back to the LLM classifier or leaves the category null.\n */\nexport function inferCategoryFromSignals(signals: RawPackageSignals): Category | null {\n const r = signals.registry;\n const keywords = (r?.keywords ?? []).join(' ');\n const text = [\n signals.name,\n keywords,\n keywords, // weight keywords higher via repetition\n r?.description ?? '',\n (r?.readme ?? '').slice(0, 600),\n ]\n .filter(Boolean)\n .join(' ');\n return inferCategory(text);\n}\n","/**\n * All scoring weights and thresholds in one tunable file (§10).\n * Changing the model means editing this file only.\n */\n\n/** Composite health-score weights. Must sum to 1.0. */\nexport const HEALTH_WEIGHTS = {\n maintenance: 0.35,\n adoption: 0.3,\n reliability: 0.25,\n efficiency: 0.1,\n} as const;\n\n/**\n * Health↔Quality blend for the default composite sort (§1). Quality is a\n * standalone, adoption-independent axis — NOT a member of HEALTH_WEIGHTS. The\n * two only blend here, for ranking/sort: composite = (1−λ)·health + λ·quality.\n * λ is the single most impactful knob `edit-weights` exposes.\n */\nexport const COMPOSITE = {\n lambda: 0.35,\n} as const;\n\n/**\n * Quality sub-score component weights (of the *available* components — missing\n * signals are dropped, not zeroed, via weightedAverage). All inputs are\n * adoption-independent: they measure how well-built a package is, not how many\n * people use it.\n */\nexport const QUALITY_WEIGHTS = {\n types: 0.25,\n tests: 0.2,\n docs: 0.2,\n changelog: 0.1,\n deps: 0.1,\n license: 0.1,\n provenance: 0.05,\n} as const;\n\nexport const QUALITY = {\n /** README at/above this many characters scores full marks on doc length. */\n docsFullLengthChars: 1200,\n /** Direct-dependency count at/above this scores 0 on the deps component (log-scaled). */\n depsLogMax: 30,\n /** A license string present but not OSI-recognized scores this (vs 100 / 0). */\n licenseUnrecognizedScore: 60,\n} as const;\n\n/** Maintenance sub-score component weights (of the available components). */\nexport const MAINTENANCE_WEIGHTS = {\n recency: 0.5,\n cadence: 0.25,\n closeRatio: 0.25,\n} as const;\n\nexport const MAINTENANCE = {\n /** A release within this many days scores full recency. */\n freshDays: 30,\n /** Recency decays linearly to 0 by this many days (~24 months). */\n staleDays: 730,\n /** Releases/12mo at or above this cap full cadence. */\n cadenceCap: 12,\n /** deprecated/archived hard-cap maintenance at this value. */\n deadCap: 15,\n} as const;\n\nexport const ADOPTION = {\n /** log10(weekly downloads): this maps to 0. */\n downloadsLogMin: 1, // 10/wk\n /** log10(weekly downloads): this maps to 100. */\n downloadsLogMax: 7, // 10M/wk\n /** log10(stars) that maps to 100. */\n starsLogMax: 5, // 100k stars\n /** Weight of the stars component when available (downloads gets the rest). */\n starsWeight: 0.2,\n /** Growth bonus: growth fraction × this, clamped to ±cap. */\n growthMultiplier: 30,\n growthBonusCap: 20,\n} as const;\n\nexport const RELIABILITY = {\n /** Used when no Scorecard is available (unknown security posture). */\n neutralWhenUnknown: 50,\n /** Advisory penalties by severity. */\n penalty: {\n critical: 40,\n high: 20,\n moderate: 8,\n low: 3,\n info: 0,\n },\n} as const;\n\nexport const EFFICIENCY = {\n /** Bundle size at the category median maps to this score; smaller → higher. */\n medianScore: 50,\n} as const;\n\n/** Proactive-discovery crawler tuning (§2B). The gate is quality-only — downloads\n * are deliberately excluded so merit, not popularity, decides what graduates. */\nexport const DISCOVERY = {\n /** A queued candidate must clear this quality pre-score to graduate to ingest. */\n minPreScore: 45,\n /** Max candidates fully ingested per crawler run (cost bound). */\n perRunCap: 25,\n /** npm-search hits to pull per category keyword. */\n searchSizePerCategory: 10,\n /** Max dependency-graph neighbors to enqueue per tracked seed. */\n graphNeighborsPerSeed: 20,\n} as const;\n\n// ── Tunable weight model: defaults ← user-config ← env (§4) ──────────────────\n\nimport { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport { projectWeightsPath, userWeightsPath } from '../core/paths';\n\n/** The user-tunable slice of the model (§4). Sub-component weights and\n * thresholds stay fixed; these are the knobs `edit-weights` exposes. */\nexport interface WeightConfig {\n health: {\n maintenance: number;\n adoption: number;\n reliability: number;\n efficiency: number;\n };\n /** Health↔Quality blend λ for the default sort composite. */\n composite: { lambda: number };\n}\n\nexport const DEFAULT_WEIGHTS: WeightConfig = {\n health: { ...HEALTH_WEIGHTS },\n composite: { ...COMPOSITE },\n};\n\nexport type WeightSource = 'defaults' | 'user-config' | 'project-config';\n\n/** Where overrides are read from, if anywhere — for `lurq weights` to report. */\nexport function activeWeightsPath(): { path: string; source: WeightSource } | null {\n if (existsSync(projectWeightsPath())) return { path: projectWeightsPath(), source: 'project-config' };\n if (existsSync(userWeightsPath())) return { path: userWeightsPath(), source: 'user-config' };\n return null;\n}\n\nlet cachedWeights: WeightConfig | undefined;\n\n/**\n * Resolve the effective weight model: defaults, overlaid by a config file\n * (project-local wins over user-level), overlaid by env (`LURQ_COMPOSITE_LAMBDA`).\n * Always returns a validated, sum-to-1 health block. Memoized; call\n * `resetWeightsCache()` after a write or in tests.\n */\nexport function loadWeights(): WeightConfig {\n if (cachedWeights) return cachedWeights;\n\n let merged: WeightConfig = structuredClone(DEFAULT_WEIGHTS);\n const active = activeWeightsPath();\n if (active) {\n try {\n const fromFile = JSON.parse(readFileSync(active.path, 'utf8')) as Partial<WeightConfig>;\n merged = mergeWeights(merged, fromFile);\n } catch {\n // A corrupt override file must never break scoring — fall back to defaults.\n }\n }\n\n const envLambda = process.env.LURQ_COMPOSITE_LAMBDA;\n if (envLambda !== undefined && envLambda !== '') {\n const n = Number(envLambda);\n if (Number.isFinite(n)) merged.composite.lambda = n;\n }\n\n cachedWeights = validateWeights(merged).weights;\n return cachedWeights;\n}\n\nexport function resetWeightsCache(): void {\n cachedWeights = undefined;\n}\n\nfunction mergeWeights(base: WeightConfig, over: Partial<WeightConfig>): WeightConfig {\n return {\n health: { ...base.health, ...(over.health ?? {}) },\n composite: { ...base.composite, ...(over.composite ?? {}) },\n };\n}\n\nexport interface WeightValidation {\n weights: WeightConfig;\n /** True if the health block was renormalized to sum to 1.0. */\n normalized: boolean;\n}\n\n/**\n * Clamp λ to [0,1] and renormalize the health block to sum to 1.0 (§4 invariant,\n * weights.ts:6). Returns the cleaned weights and whether normalization happened\n * so the CLI can report it.\n */\nexport function validateWeights(w: WeightConfig): WeightValidation {\n const lambda = Math.max(0, Math.min(1, w.composite.lambda));\n const h = w.health;\n const sum = h.maintenance + h.adoption + h.reliability + h.efficiency;\n let normalized = false;\n let health = h;\n if (sum <= 0) {\n health = { ...DEFAULT_WEIGHTS.health };\n normalized = true;\n } else if (Math.abs(sum - 1) > 1e-6) {\n health = {\n maintenance: h.maintenance / sum,\n adoption: h.adoption / sum,\n reliability: h.reliability / sum,\n efficiency: h.efficiency / sum,\n };\n normalized = true;\n }\n return { weights: { health, composite: { lambda } }, normalized };\n}\n\n/** Keys settable via `edit-weights --set` and their slot in the config. */\nconst SETTABLE: Record<string, (w: WeightConfig, v: number) => void> = {\n 'health.maintenance': (w, v) => (w.health.maintenance = v),\n 'health.adoption': (w, v) => (w.health.adoption = v),\n 'health.reliability': (w, v) => (w.health.reliability = v),\n 'health.efficiency': (w, v) => (w.health.efficiency = v),\n 'composite.lambda': (w, v) => (w.composite.lambda = v),\n};\n\nexport function settableKeys(): string[] {\n return Object.keys(SETTABLE);\n}\n\n/** Apply `key=value` overrides to a config, returning a new config. Throws on an\n * unknown key or non-numeric value. */\nexport function applyOverrides(base: WeightConfig, sets: string[]): WeightConfig {\n const next = structuredClone(base);\n for (const entry of sets) {\n const eq = entry.indexOf('=');\n if (eq < 0) throw new Error(`Invalid --set \"${entry}\" (expected key=value).`);\n const key = entry.slice(0, eq).trim();\n const value = Number(entry.slice(eq + 1).trim());\n const apply = SETTABLE[key];\n if (!apply) {\n throw new Error(`Unknown weight key \"${key}\". Settable: ${settableKeys().join(', ')}.`);\n }\n if (!Number.isFinite(value)) throw new Error(`Value for \"${key}\" must be a number.`);\n apply(next, value);\n }\n return next;\n}\n\n/** Persist a config to the override file and bust the cache. */\nexport function saveWeights(w: WeightConfig, scope: 'user' | 'project' = 'user'): string {\n const path = scope === 'project' ? projectWeightsPath() : userWeightsPath();\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, JSON.stringify(w, null, 2) + '\\n', 'utf8');\n resetWeightsCache();\n return path;\n}\n\n/** Remove any override files, restoring defaults. Returns the paths removed. */\nexport function resetWeights(): string[] {\n const removed: string[] = [];\n for (const path of [projectWeightsPath(), userWeightsPath()]) {\n if (existsSync(path)) {\n rmSync(path);\n removed.push(path);\n }\n }\n resetWeightsCache();\n return removed;\n}\n\n/** Human-readable explanation per health component / knob (§4 `--explain`). */\nexport const WEIGHT_EXPLANATIONS: Record<string, string> = {\n maintenance: 'release recency, cadence, and issue close-ratio (weights.ts MAINTENANCE_WEIGHTS).',\n adoption: 'weekly downloads (log-scaled), stars, and 90-day growth (weights.ts ADOPTION).',\n reliability: 'OpenSSF Scorecard scaled 0–100, minus advisory penalties (weights.ts RELIABILITY).',\n efficiency: 'bundle size vs the category median; frontend categories only (weights.ts EFFICIENCY).',\n quality:\n 'intrinsic, adoption-independent: types, tests, docs, changelog, deps, license, provenance (weights.ts QUALITY_WEIGHTS). A standalone axis — it does NOT feed health.',\n lambda: 'how much the default sort composite favors quality over health: (1−λ)·health + λ·quality.',\n};\n\n/** Confidence-label thresholds (§10, §1). */\nexport const CONFIDENCE = {\n proven: {\n minWeeklyDownloads: 100_000,\n minAgeMonths: 12,\n maxLastReleaseMonths: 6,\n },\n emerging: {\n minWeeklyDownloads: 5_000,\n strongGrowth: 0.5,\n maxLastReleaseMonths: 9,\n },\n /** `promising` (§1): new but intrinsically high-quality, regardless of adoption. */\n promising: {\n minQuality: 70,\n maxLastReleaseMonths: 12,\n },\n} as const;\n","/**\n * Scoring & confidence model (§10). All functions are pure and take an explicit\n * `now` for deterministic testing.\n *\n * Two-pass design: maintenance / adoption / reliability / confidence depend only\n * on a single package, so they're computed in pass 1. Efficiency needs the\n * category median bundle size (§10), so it — and the composite health score —\n * are computed in pass 2 once all packages are collected.\n */\nimport type { Advisory, Category, Confidence, ScoreBreakdown } from '../core/types';\nimport { isFrontendCategory } from '../core/types';\nimport type { RawPackageSignals } from '../ingestion/types';\nimport {\n ADOPTION,\n COMPOSITE,\n CONFIDENCE,\n EFFICIENCY,\n HEALTH_WEIGHTS,\n MAINTENANCE,\n MAINTENANCE_WEIGHTS,\n QUALITY,\n QUALITY_WEIGHTS,\n RELIABILITY,\n} from './weights';\n\nexport interface ScoringInput {\n weeklyDownloads: number | null;\n downloadGrowth90d: number | null;\n stars: number | null;\n firstPublishedAt: Date | null;\n lastReleaseAt: Date | null;\n releasesLast12mo: number | null;\n openIssues: number | null;\n closedIssues: number | null;\n scorecard: number | null;\n advisories: Advisory[];\n deprecated: boolean;\n archived: boolean;\n bundleMinGzipKb: number | null;\n category: Category | null;\n // ── Intrinsic-quality signals (§1), adoption-independent ──\n hasTypes: boolean | null;\n hasTestScript: boolean | null;\n readmeLength: number | null;\n hasExamples: boolean | null;\n hasHomepage: boolean | null;\n hasReleaseNotes: boolean | null;\n directDependenciesCount: number | null;\n license: string | null;\n hasProvenance: boolean | null;\n}\n\nconst DAY_MS = 24 * 60 * 60 * 1000;\nconst MONTH_MS = 30 * DAY_MS;\n\nconst clamp = (n: number, lo = 0, hi = 100): number => Math.max(lo, Math.min(hi, n));\nconst daysSince = (date: Date | null, now: Date): number | null =>\n date ? (now.getTime() - date.getTime()) / DAY_MS : null;\nconst monthsSince = (date: Date | null, now: Date): number | null =>\n date ? (now.getTime() - date.getTime()) / MONTH_MS : null;\n\n/** Build a ScoringInput from collected raw signals. */\nexport function toScoringInput(signals: RawPackageSignals, category: Category | null): ScoringInput {\n const { registry, downloads, github, depsDev, bundle } = signals;\n const readme = registry?.readme ?? null;\n return {\n weeklyDownloads: downloads?.weeklyDownloads ?? null,\n downloadGrowth90d: downloads?.downloadGrowth90d ?? null,\n stars: github?.stars ?? null,\n firstPublishedAt: registry?.firstPublishedAt ?? null,\n lastReleaseAt: github?.lastReleaseAt ?? registry?.lastReleaseAt ?? null,\n releasesLast12mo: github?.releasesLast12mo ?? null,\n openIssues: github?.openIssues ?? null,\n closedIssues: github?.closedIssues ?? null,\n scorecard: depsDev?.scorecard ?? null,\n advisories: depsDev?.advisories ?? [],\n deprecated: registry?.deprecated ?? false,\n archived: github?.archived ?? false,\n bundleMinGzipKb: bundle?.bundleMinGzipKb ?? null,\n category,\n // Quality signals — null (not false) when the manifest itself is missing, so\n // weightedAverage drops the component rather than scoring it 0.\n hasTypes: registry ? registry.hasTypes : null,\n hasTestScript: registry ? registry.hasTestScript : null,\n readmeLength: readme !== null ? readme.length : null,\n hasExamples: readme !== null ? /```/.test(readme) : null,\n hasHomepage: registry ? registry.homepage !== null : null,\n hasReleaseNotes: github?.releasesLast12mo != null ? github.releasesLast12mo > 0 : null,\n directDependenciesCount: registry?.directDependenciesCount ?? null,\n license: registry?.license ?? null,\n hasProvenance: registry ? registry.hasProvenance : null,\n };\n}\n\n// ── Maintenance ─────────────────────────────────────────────────────────────\n\nexport function computeMaintenance(input: ScoringInput, now: Date): number {\n if (input.deprecated || input.archived) return MAINTENANCE.deadCap;\n\n const components: { value: number; weight: number }[] = [];\n\n const days = daysSince(input.lastReleaseAt, now);\n if (days !== null) {\n const recency =\n days <= MAINTENANCE.freshDays\n ? 100\n : clamp((100 * (MAINTENANCE.staleDays - days)) / (MAINTENANCE.staleDays - MAINTENANCE.freshDays));\n components.push({ value: recency, weight: MAINTENANCE_WEIGHTS.recency });\n }\n\n if (input.releasesLast12mo !== null) {\n const cadence = clamp((Math.min(input.releasesLast12mo, MAINTENANCE.cadenceCap) / MAINTENANCE.cadenceCap) * 100);\n components.push({ value: cadence, weight: MAINTENANCE_WEIGHTS.cadence });\n }\n\n if (input.openIssues !== null && input.closedIssues !== null) {\n const total = input.openIssues + input.closedIssues;\n if (total > 0) {\n components.push({ value: (input.closedIssues / total) * 100, weight: MAINTENANCE_WEIGHTS.closeRatio });\n }\n }\n\n return weightedAverage(components);\n}\n\n// ── Adoption ────────────────────────────────────────────────────────────────\n\nexport function computeAdoption(input: ScoringInput): number {\n const dl = input.weeklyDownloads ?? 0;\n const downloadsScore = clamp(\n ((Math.log10(Math.max(dl, 1)) - ADOPTION.downloadsLogMin) /\n (ADOPTION.downloadsLogMax - ADOPTION.downloadsLogMin)) *\n 100,\n );\n\n let base = downloadsScore;\n if (input.stars !== null) {\n const starsScore = clamp((Math.log10(Math.max(input.stars, 1)) / ADOPTION.starsLogMax) * 100);\n base = (1 - ADOPTION.starsWeight) * downloadsScore + ADOPTION.starsWeight * starsScore;\n }\n\n if (input.downloadGrowth90d !== null) {\n const bonus = clamp(\n input.downloadGrowth90d * ADOPTION.growthMultiplier,\n -ADOPTION.growthBonusCap,\n ADOPTION.growthBonusCap,\n );\n base += bonus;\n }\n\n return clamp(base);\n}\n\n// ── Reliability ─────────────────────────────────────────────────────────────\n\nexport function computeReliability(input: ScoringInput): number {\n const base = input.scorecard !== null ? input.scorecard * 10 : RELIABILITY.neutralWhenUnknown;\n const penalty = input.advisories.reduce(\n (sum, adv) => sum + (RELIABILITY.penalty[adv.severity] ?? 0),\n 0,\n );\n return clamp(base - penalty);\n}\n\n// ── Efficiency (pass 2 — needs the category median) ─────────────────────────\n\n/**\n * Efficiency for frontend categories: smaller-than-median bundle → higher score\n * (median maps to 50). Returns null for backend categories / missing data; the\n * null signals the composite to redistribute the efficiency weight (§10, R1).\n */\nexport function computeEfficiency(\n bundleMinGzipKb: number | null,\n category: Category | null,\n categoryMedian: number | null,\n): number | null {\n if (!isFrontendCategory(category) || bundleMinGzipKb === null || !categoryMedian || categoryMedian <= 0) {\n return null;\n }\n const ratio = bundleMinGzipKb / categoryMedian;\n return clamp(100 - ratio * EFFICIENCY.medianScore);\n}\n\n// ── Quality (pass 1 — intrinsic, adoption-independent §1) ────────────────────\n\n/** A small set of OSI-recognized SPDX license IDs (prefix-matched, case-insensitive). */\nconst RECOGNIZED_LICENSES = [\n 'mit',\n 'isc',\n 'apache-2.0',\n 'bsd-2-clause',\n 'bsd-3-clause',\n 'mpl-2.0',\n 'lgpl',\n 'gpl',\n 'agpl',\n 'unlicense',\n '0bsd',\n 'cc0-1.0',\n];\n\nexport function isRecognizedLicense(license: string | null): boolean {\n if (!license) return false;\n const id = license.trim().toLowerCase();\n return RECOGNIZED_LICENSES.some((l) => id === l || id.startsWith(l));\n}\n\n/**\n * Intrinsic-quality score (§1): how well-built a package is, independent of\n * adoption. A weighted average over the *available* components, so a missing\n * signal is dropped rather than penalized. Returns null only when no signal is\n * available at all (e.g. the registry manifest itself failed to load).\n */\nexport function computeQuality(input: ScoringInput): number | null {\n const components: { value: number; weight: number }[] = [];\n\n if (input.hasTypes !== null) {\n components.push({ value: input.hasTypes ? 100 : 0, weight: QUALITY_WEIGHTS.types });\n }\n if (input.hasTestScript !== null) {\n components.push({ value: input.hasTestScript ? 100 : 0, weight: QUALITY_WEIGHTS.tests });\n }\n if (input.readmeLength !== null || input.hasHomepage !== null) {\n const lenScore = Math.min((input.readmeLength ?? 0) / QUALITY.docsFullLengthChars, 1) * 60;\n const examples = input.hasExamples ? 25 : 0;\n const homepage = input.hasHomepage ? 15 : 0;\n components.push({ value: clamp(lenScore + examples + homepage), weight: QUALITY_WEIGHTS.docs });\n }\n if (input.hasReleaseNotes !== null) {\n components.push({ value: input.hasReleaseNotes ? 100 : 0, weight: QUALITY_WEIGHTS.changelog });\n }\n if (input.directDependenciesCount !== null) {\n const deps = input.directDependenciesCount;\n const depsScore = clamp(\n 100 - (Math.log10(deps + 1) / Math.log10(QUALITY.depsLogMax + 1)) * 100,\n );\n components.push({ value: depsScore, weight: QUALITY_WEIGHTS.deps });\n }\n if (input.license !== null) {\n components.push({\n value: isRecognizedLicense(input.license) ? 100 : QUALITY.licenseUnrecognizedScore,\n weight: QUALITY_WEIGHTS.license,\n });\n }\n // Provenance is a pure bonus — only counted when present, never penalizing.\n if (input.hasProvenance) {\n components.push({ value: 100, weight: QUALITY_WEIGHTS.provenance });\n }\n\n if (components.length === 0) return null;\n return weightedAverage(components);\n}\n\n// ── Composite ───────────────────────────────────────────────────────────────\n\n/** Compose the health score, redistributing efficiency's weight when null.\n * Weights default to HEALTH_WEIGHTS but can be overridden (§4 rescore). */\nexport function computeHealthScore(\n breakdown: ScoreBreakdown,\n weights: typeof HEALTH_WEIGHTS | { maintenance: number; adoption: number; reliability: number; efficiency: number } = HEALTH_WEIGHTS,\n): number {\n const { maintenance, adoption, reliability, efficiency } = breakdown;\n const w = weights;\n if (efficiency === null) {\n const denom = w.maintenance + w.adoption + w.reliability;\n return Math.round(\n (w.maintenance * maintenance + w.adoption * adoption + w.reliability * reliability) / denom,\n );\n }\n return Math.round(\n w.maintenance * maintenance +\n w.adoption * adoption +\n w.reliability * reliability +\n w.efficiency * efficiency,\n );\n}\n\n/**\n * Default sort composite (§1): blend the popularity-tilted health score with the\n * adoption-independent quality axis. `lambda` (default COMPOSITE.lambda) is the\n * tunable knob `edit-weights` exposes. Falls back to pure health when quality is\n * unavailable, so a missing manifest never drags a package down.\n */\nexport function computeComposite(\n healthScore: number,\n qualityScore: number | null,\n lambda: number = COMPOSITE.lambda,\n): number {\n if (qualityScore === null) return healthScore;\n return Math.round((1 - lambda) * healthScore + lambda * qualityScore);\n}\n\n// ── Confidence ──────────────────────────────────────────────────────────────\n\nexport function hasCriticalOrHighAdvisory(advisories: Advisory[]): boolean {\n return advisories.some((a) => a.severity === 'critical' || a.severity === 'high');\n}\n\nexport function computeConfidence(\n input: ScoringInput,\n now: Date,\n qualityScore: number | null = null,\n): Confidence {\n const dl = input.weeklyDownloads ?? 0;\n const ageMonths = monthsSince(input.firstPublishedAt, now);\n const lastReleaseMonths = monthsSince(input.lastReleaseAt, now);\n const growth = input.downloadGrowth90d ?? 0;\n\n const provenReleaseOk =\n lastReleaseMonths !== null && lastReleaseMonths <= CONFIDENCE.proven.maxLastReleaseMonths;\n const provenAgeOk = ageMonths !== null && ageMonths >= CONFIDENCE.proven.minAgeMonths;\n\n if (\n dl >= CONFIDENCE.proven.minWeeklyDownloads &&\n provenAgeOk &&\n provenReleaseOk &&\n !hasCriticalOrHighAdvisory(input.advisories) &&\n !input.deprecated &&\n !input.archived\n ) {\n return 'proven';\n }\n\n const emergingReleaseOk =\n lastReleaseMonths !== null && lastReleaseMonths <= CONFIDENCE.emerging.maxLastReleaseMonths;\n const emergingAdoptionOk =\n dl >= CONFIDENCE.emerging.minWeeklyDownloads || growth >= CONFIDENCE.emerging.strongGrowth;\n\n if (emergingAdoptionOk && emergingReleaseOk && !input.deprecated && !input.archived) {\n return 'emerging';\n }\n\n // `promising` (§1): adoption-independent — high intrinsic quality on a package\n // that hasn't yet earned adoption traction. This is how new-but-good packages\n // surface on merit instead of sinking to `unproven`.\n // A freshly published package may have no separate release date (registry and\n // GitHub both empty); fall back to first-publish recency so a new-but-good\n // package isn't locked to `unproven` — the exact case this tier targets.\n const promisingRecencyMonths = lastReleaseMonths ?? ageMonths;\n const promisingReleaseOk =\n promisingRecencyMonths !== null &&\n promisingRecencyMonths <= CONFIDENCE.promising.maxLastReleaseMonths;\n if (\n qualityScore !== null &&\n qualityScore >= CONFIDENCE.promising.minQuality &&\n promisingReleaseOk &&\n !hasCriticalOrHighAdvisory(input.advisories) &&\n !input.deprecated &&\n !input.archived\n ) {\n return 'promising';\n }\n\n return 'unproven';\n}\n\n// ── Helpers ─────────────────────────────────────────────────────────────────\n\nfunction weightedAverage(components: { value: number; weight: number }[]): number {\n if (components.length === 0) return 0;\n const totalWeight = components.reduce((s, c) => s + c.weight, 0);\n if (totalWeight === 0) return 0;\n return Math.round(components.reduce((s, c) => s + c.value * c.weight, 0) / totalWeight);\n}\n\n/** Median of a numeric list, or null if empty. */\nexport function median(values: number[]): number | null {\n if (values.length === 0) return null;\n const sorted = [...values].sort((a, b) => a - b);\n const mid = Math.floor(sorted.length / 2);\n return sorted.length % 2 === 0 ? (sorted[mid - 1]! + sorted[mid]!) / 2 : sorted[mid]!;\n}\n","export * from './score';\nexport * from './weights';\n","/**\n * Embedding providers (§11). A pluggable interface with two implementations:\n * - OpenAI (`text-embedding-3-small`, 1536-dim) — the default when a key is set.\n * - Local deterministic embedder (no key) — a hashing bag-of-words that captures\n * lexical overlap. Crude but real: it makes `recommend` and tests work with\n * zero credentials (R1 decision). Both emit EMBEDDING_DIM-length unit vectors,\n * so the DB column and pgvector index never change.\n */\nimport { createHash } from 'node:crypto';\nimport { getConfig } from '../core/config';\nimport { EMBEDDING_DIM } from '../core/constants';\nimport { httpRequest } from '../core/http';\nimport { logger } from '../core/logger';\nimport type { Category } from '../core/types';\n\nexport interface EmbeddingProvider {\n readonly kind: 'openai' | 'local';\n readonly dimensions: number;\n /**\n * Stable identity of the vector space this provider produces (e.g.\n * `openai:text-embedding-3-small`, `local`). Stored per row so vector search\n * only compares vectors from the same space — switching providers then falls\n * back to lexical retrieval until rows are re-embedded, instead of silently\n * returning garbage from a cosine distance across incompatible spaces.\n */\n readonly id: string;\n embed(texts: string[]): Promise<number[][]>;\n}\n\n/** Normalized text blob embedded per package (§8.2). */\nexport function buildEmbeddingText(input: {\n name: string;\n category: Category | null;\n summary: string | null;\n description: string | null;\n}): string {\n const body = input.summary || input.description || '';\n return `${input.name}. ${input.category ?? ''}. ${body}`.trim();\n}\n\n// ── Local deterministic embedder ────────────────────────────────────────────\n\nfunction tokenize(text: string): string[] {\n return text\n .toLowerCase()\n .split(/[^a-z0-9]+/)\n .filter((t) => t.length > 1);\n}\n\n/** FNV-1a 32-bit hash. */\nfunction fnv1a(str: string): number {\n let h = 0x811c9dc5;\n for (let i = 0; i < str.length; i++) {\n h ^= str.charCodeAt(i);\n h = Math.imul(h, 0x01000193);\n }\n return h >>> 0;\n}\n\nexport function localEmbed(text: string, dim = EMBEDDING_DIM): number[] {\n const vec = new Float64Array(dim);\n const tokens = tokenize(text);\n const add = (token: string, weight: number) => {\n const idx = fnv1a(token) % dim;\n const sign = fnv1a('s:' + token) & 1 ? 1 : -1;\n vec[idx]! += weight * sign;\n };\n for (const t of tokens) add(t, 1);\n for (let i = 0; i < tokens.length - 1; i++) add(`${tokens[i]} ${tokens[i + 1]}`, 0.5);\n\n // L2-normalize to a unit vector (cosine-friendly).\n let norm = 0;\n for (let i = 0; i < dim; i++) norm += vec[i]! * vec[i]!;\n norm = Math.sqrt(norm) || 1;\n const out = new Array<number>(dim);\n for (let i = 0; i < dim; i++) out[i] = vec[i]! / norm;\n return out;\n}\n\nexport class LocalEmbeddingProvider implements EmbeddingProvider {\n readonly kind = 'local' as const;\n readonly dimensions = EMBEDDING_DIM;\n readonly id = 'local';\n async embed(texts: string[]): Promise<number[][]> {\n return texts.map((t) => localEmbed(t));\n }\n}\n\n// ── OpenAI embedder ─────────────────────────────────────────────────────────\n\nconst OPENAI_BATCH = 96;\n\nexport class OpenAIEmbeddingProvider implements EmbeddingProvider {\n readonly kind = 'openai' as const;\n readonly dimensions = EMBEDDING_DIM;\n readonly id: string;\n\n private readonly endpoint: string;\n private readonly host: string;\n\n constructor(\n private readonly apiKey: string,\n private readonly model: string,\n baseUrl: string,\n private readonly fetchImpl?: typeof fetch,\n ) {\n this.id = `openai:${model}`;\n this.endpoint = `${baseUrl.replace(/\\/$/, '')}/embeddings`;\n this.host = new URL(baseUrl).host;\n }\n\n async embed(texts: string[]): Promise<number[][]> {\n const out: number[][] = [];\n for (let i = 0; i < texts.length; i += OPENAI_BATCH) {\n const batch = texts.slice(i, i + OPENAI_BATCH);\n // Pin the output dimension to the DB column width. Every text-embedding-3\n // model honors `dimensions`, so a larger model (e.g. -3-large, natively\n // 3072-dim) is projected to 1536 instead of overflowing the vector(1536)\n // column at insert time. ponytail: non-OpenAI providers may ignore\n // `dimensions`; the length check below fails loud if the space mismatches.\n const body = JSON.stringify({ model: this.model, input: batch, dimensions: EMBEDDING_DIM });\n const { data } = await httpRequest<any>(this.endpoint, {\n host: this.host,\n method: 'POST',\n ttlMs: 30 * 24 * 60 * 60 * 1000, // cache embeddings 30d to control cost\n cacheKey: `openai-embed ${this.model} ${createHash('sha256').update(body).digest('hex')}`,\n headers: { Authorization: `Bearer ${this.apiKey}`, 'Content-Type': 'application/json' },\n body,\n fetchImpl: this.fetchImpl,\n });\n const vectors: { embedding: number[]; index: number }[] = data?.data ?? [];\n vectors.sort((a, b) => a.index - b.index);\n for (const v of vectors) {\n // Fail loud on any dimension drift rather than silently storing vectors\n // that pgvector can't compare against the rest of the column.\n if (v.embedding.length !== EMBEDDING_DIM) {\n throw new Error(\n `OpenAI model ${this.model} returned ${v.embedding.length}-dim vectors; expected ${EMBEDDING_DIM}. Set EMBEDDING_MODEL to a text-embedding-3 model or update EMBEDDING_DIM.`,\n );\n }\n out.push(v.embedding);\n }\n }\n return out;\n }\n}\n\n// ── Factory ─────────────────────────────────────────────────────────────────\n\nexport function createEmbeddingProvider(fetchImpl?: typeof fetch): EmbeddingProvider {\n const config = getConfig();\n if (config.EMBEDDING_PROVIDER === 'openai' && config.EMBEDDING_API_KEY) {\n return new OpenAIEmbeddingProvider(\n config.EMBEDDING_API_KEY,\n config.EMBEDDING_MODEL,\n config.EMBEDDING_BASE_URL,\n fetchImpl,\n );\n }\n if (config.EMBEDDING_PROVIDER === 'openai' && !config.EMBEDDING_API_KEY) {\n logger.warn('EMBEDDING_API_KEY not set — falling back to the local embedder.');\n }\n return new LocalEmbeddingProvider();\n}\n","/** Map over items with bounded concurrency, preserving input order. */\nexport async function pMap<T, R>(\n items: readonly T[],\n mapper: (item: T, index: number) => Promise<R>,\n concurrency: number,\n): Promise<R[]> {\n const results = new Array<R>(items.length);\n let cursor = 0;\n const workerCount = Math.max(1, Math.min(concurrency, items.length));\n const workers = Array.from({ length: workerCount }, async () => {\n while (cursor < items.length) {\n const index = cursor++;\n results[index] = await mapper(items[index]!, index);\n }\n });\n await Promise.all(workers);\n return results;\n}\n","/**\n * Compact error formatting for logs. Drizzle stuffs full SQL + every bind param\n * into `err.message`, which can be megabytes for a fat batch insert — and the\n * real Postgres reason lives on `err.cause`, which bare `err.message` drops.\n */\n\nconst DEFAULT_MAX = 300;\n\nfunction truncate(text: string, max: number): string {\n if (text.length <= max) return text;\n return `${text.slice(0, max)}…`;\n}\n\nfunction causeText(cause: unknown): string | null {\n if (cause == null) return null;\n if (cause instanceof Error) {\n const code =\n 'code' in cause && (typeof cause.code === 'string' || typeof cause.code === 'number')\n ? String(cause.code)\n : null;\n const msg = truncate(cause.message, DEFAULT_MAX);\n return code ? `${code}: ${msg}` : msg;\n }\n if (typeof cause === 'object' && cause !== null && 'message' in cause) {\n const msg = truncate(String((cause as { message: unknown }).message), DEFAULT_MAX);\n const code =\n 'code' in cause ? String((cause as { code: unknown }).code) : null;\n return code ? `${code}: ${msg}` : msg;\n }\n return truncate(String(cause), DEFAULT_MAX);\n}\n\n/** Truncated message + optional Postgres/Drizzle cause for safe logging. */\nexport function formatError(err: unknown, max = DEFAULT_MAX): string {\n const message =\n err instanceof Error ? truncate(err.message, max) : truncate(String(err), max);\n const cause = err instanceof Error ? causeText(err.cause) : null;\n return cause ? `${message} (cause: ${cause})` : message;\n}\n","/**\n * Compat edge miner (§4B — the moat). A resolved dependency graph is a\n * co-installation witness: npm's resolver found a working assignment including\n * every node and the artifact shipped, so every pair inside provably co-resolves.\n * We fetch these graphs anyway; the miner is pure transformation — free,\n * evidence-backed `observed` edges.\n *\n * Bounded to **tracked × tracked** pairs (§4B step 2): a resolved closure has\n * hundreds of transitive nodes (`ms`↔`bytes` plumbing nobody queries); C(N,2)\n * explodes. Mining only pairs where both endpoints are tracked keeps writes to\n * ~C(tracked-in-tree, 2) and to the universe we actually serve queries about.\n */\nimport { formatError } from '../core/errors';\nimport { logger } from '../core/logger';\nimport { getAllPackageNames } from '../db/packages';\nimport {\n canonicalPair,\n getAllClosures,\n persistClosure,\n upsertCompatEdgesBatch,\n upsertObservedEdgesRemine,\n} from '../db/compat';\nimport type { Database } from '../db/client';\nimport { fetchResolvedGraph, type ResolvedNode } from '../ingestion/sources/depsDev';\n\n/**\n * Canonical tracked×tracked pairs in a closure (§4B step 2). Pure — the bounded\n * pair set, filtered to the served universe, same-package pairs dropped. Exported\n * for the self-check; the explosion guard lives entirely here.\n */\nexport function trackedPairs(\n nodes: ResolvedNode[],\n tracked: Set<string>,\n): ReturnType<typeof canonicalPair>[] {\n const t = nodes.filter((n) => tracked.has(n.name));\n const pairs: ReturnType<typeof canonicalPair>[] = [];\n for (let i = 0; i < t.length; i++) {\n for (let j = i + 1; j < t.length; j++) {\n // Skip two versions of the same package co-resolving — not a compat claim.\n if (t[i]!.name === t[j]!.name) continue;\n pairs.push(canonicalPair(t[i]!, t[j]!));\n }\n }\n return pairs;\n}\n\n/**\n * Mint `observed` edges for every tracked-tracked pair in a resolved closure.\n * One chunked batch upsert per closure (§4F) — pairs are unique within a closure;\n * both writers split large sets so fat trees stay bounded.\n *\n * `freshWitness` distinguishes the two triggers. Trigger 1 has a closure it just\n * fetched, which is a new co-installation witness, so it accrues. Trigger 2\n * re-reads closures it has already mined and must not re-count them — see\n * {@link upsertObservedEdgesRemine}.\n */\nasync function mintObservedPairs(\n db: Database,\n nodes: ResolvedNode[],\n tracked: Set<string>,\n now: Date,\n freshWitness: boolean,\n): Promise<number> {\n const pairs = trackedPairs(nodes, tracked);\n const rows = pairs.map((pair) => ({\n ...pair,\n status: 'compatible' as const,\n provenance: 'observed' as const,\n witnessCount: 1,\n driver: 'depsdev',\n ranAt: now,\n }));\n await (freshWitness\n ? upsertCompatEdgesBatch(db, rows)\n : upsertObservedEdgesRemine(db, rows));\n return pairs.length;\n}\n\n/**\n * Trigger 1 — mint at ingest (§4B). Fetch `name@version`'s resolved closure,\n * persist it immutably (so the daily re-mine can read it with no network), and\n * mint `observed` edges among the nodes that are *already* tracked. Best-effort:\n * a mining failure never fails the ingest that called it.\n *\n * `tracked` may be preloaded once per bulk sync; omitted, it's loaded here (one\n * query) for the on-demand single-package path.\n */\nexport async function mineEdgesForPackage(\n db: Database,\n name: string,\n version: string | null,\n tracked?: Set<string>,\n now: Date = new Date(),\n): Promise<number> {\n if (!version) return 0;\n try {\n const closure = await fetchResolvedGraph(name, version);\n if (closure.length === 0) return 0;\n await persistClosure(db, name, version, closure).catch(() => {});\n const set = tracked ?? new Set(await getAllPackageNames(db));\n // Freshly fetched closure — a genuinely new witness, so it accrues.\n return await mintObservedPairs(db, closure, set, now, true);\n } catch (err) {\n logger.warn(`edge mining failed for ${name}@${version}: ${formatError(err)}`);\n return 0;\n }\n}\n\n/**\n * Trigger 2 — daily re-mine pass (§4B). Opportunistic minting alone misses a\n * stable package P that never republishes: a package tracked *later* would never\n * link to it. This local pass re-scans every persisted closure against the\n * *current* tracked set — no network — so any package is fully linked within 24h\n * of becoming tracked.\n *\n * Its only real output is edges that did not exist yet: it is re-reading closures\n * it has already mined, so an already-known pair gets no witness and no `ran_at`\n * bump ({@link upsertObservedEdgesRemine}). Pair *generation* is still\n * O(tracked-in-closure²) — ~4.5M candidate rows a pass — but all but the genuinely\n * new ones are now discarded by Postgres without a write.\n */\nexport async function remineAllClosures(db: Database): Promise<number> {\n const tracked = new Set(await getAllPackageNames(db));\n const closures = await getAllClosures(db);\n const now = new Date();\n let count = 0;\n for (const c of closures) {\n count += await mintObservedPairs(db, c.nodes, tracked, now, false);\n }\n logger.info(`re-mine: ${count} candidate pairs across ${closures.length} closures`);\n return count;\n}\n","/**\n * `lurq sync` pipeline (§9.7). End-to-end ingestion for the seed list (or one\n * package): collect signals → score → summarize → upsert, recording a sync_runs\n * row. Idempotent, concurrent, and tolerant of individual source failures (§17).\n *\n * Two-pass for efficiency (§10): pass 1 collects + scores everything that's\n * per-package; then category medians are computed; pass 2 finalizes efficiency\n * and the composite health score. Embeddings are added in M4.\n */\nimport { invalidateCache } from '../core/cache';\nimport { getConfig } from '../core/config';\nimport { pMap } from '../core/concurrency';\nimport { formatError } from '../core/errors';\nimport { setCacheBypassRead } from '../core/http';\nimport { logger } from '../core/logger';\nimport type { Category, CategorySource, ScoreBreakdown } from '../core/types';\nimport { collectSignals } from '../ingestion/collect';\nimport { fetchBulkWeeklyDownloads } from '../ingestion/sources/npmDownloads';\nimport { buildSummaryInput, createSummaryProvider } from '../ingestion/summarize';\nimport { inferCategoryFromSignals } from '../search/categoryInference';\nimport { buildEmbeddingText, createEmbeddingProvider } from '../search/embeddings';\nimport type { RawPackageSignals } from '../ingestion/types';\nimport {\n computeAdoption,\n computeConfidence,\n computeEfficiency,\n computeHealthScore,\n computeMaintenance,\n computeQuality,\n computeReliability,\n median,\n toScoringInput,\n type ScoringInput,\n} from '../scoring';\nimport { createDb, type Database } from '../db/client';\nimport {\n finishSyncRun,\n getAllPackageNames,\n getSeedTargets,\n getStaleRefreshTargets,\n startSyncRun,\n upsertPackage,\n upsertPackageVersions,\n} from '../db/packages';\nimport { mineEdgesForPackage, remineAllClosures } from './mineEdges';\nimport { isFrontendCategory } from '../core/types';\nimport type { NewPackageRow, SyncError } from '../db/schema';\n\nexport interface SyncOptions {\n full?: boolean;\n packageName?: string;\n}\n\n/** Post-sync edge mining concurrency. Kept at 1 so fat dependency trees cannot\n * spike heap the way concurrent mega-upserts did on the Railway sync cron. */\nexport const SYNC_MINE_CONCURRENCY = 1;\n\nexport interface SyncSummary {\n seen: number;\n updated: number;\n errors: number;\n status: 'success' | 'partial' | 'failed';\n}\n\ninterface Target {\n name: string;\n category: Category | null;\n}\n\n/** Per-package state carried from pass 1 to pass 2. */\ninterface Computed {\n target: Target;\n /** Final resolved category (curated or inferred at ingest, §2A). */\n category: Category | null;\n categorySource: CategorySource | null;\n signals: RawPackageSignals;\n input: ScoringInput;\n maintenance: number;\n adoption: number;\n reliability: number;\n quality: number | null;\n confidence: ReturnType<typeof computeConfidence>;\n summary: string | null;\n usageGuide: NewPackageRow['usageGuide'];\n}\n\nexport async function runSync(opts: SyncOptions = {}): Promise<SyncSummary> {\n const config = getConfig();\n const now = new Date();\n if (opts.full) setCacheBypassRead(true);\n\n const handle = createDb({ max: Math.max(4, config.LURQ_SYNC_CONCURRENCY) });\n const provider = createSummaryProvider();\n logger.info(`Summary provider: ${provider.kind}`);\n if (!config.GITHUB_TOKEN) {\n logger.warn(\n 'GITHUB_TOKEN not set — GitHub signals (stars, issues, release cadence) will be ' +\n 'skipped, degrading maintenance/adoption scores. Set it for accurate scoring.',\n );\n }\n\n const runId = await startSyncRun(handle.db);\n const allErrors: SyncError[] = [];\n\n try {\n const targets = await resolveTargets(handle.db, opts, config.LURQ_SYNC_REFRESH_CAP);\n logger.info(`Syncing ${targets.length} package(s) with concurrency ${config.LURQ_SYNC_CONCURRENCY}…`);\n\n // Bulk-fetch weekly downloads up front (one call per 128 packages) to avoid\n // the downloads API rate limit that per-package bursts trigger.\n logger.info('Fetching weekly downloads in bulk…');\n const weeklyMap = await fetchBulkWeeklyDownloads(targets.map((t) => t.name));\n\n // ── Pass 1: collect + per-package scoring + summary ──────────────────────\n let done = 0;\n const computed = await pMap(\n targets,\n async (target): Promise<Computed | null> => {\n try {\n const signals = await collectSignals(target.name, target.category, {\n githubToken: config.GITHUB_TOKEN,\n prefetchedWeekly: weeklyMap.has(target.name) ? weeklyMap.get(target.name)! : undefined,\n });\n for (const e of signals.errors) allErrors.push({ package: target.name, ...e });\n\n const summaryInput = await buildSummaryInput(signals, target.category);\n const { summary, usageGuide, inferredCategory } = await provider.generate(summaryInput);\n\n // Categorize-on-ingest (§2A): curated category wins; otherwise infer\n // from the package's own text, then fall back to the LLM classifier.\n let category = target.category;\n let categorySource: CategorySource | null = target.category ? 'curated' : null;\n if (!category) {\n category = inferCategoryFromSignals(signals) ?? inferredCategory ?? null;\n categorySource = category ? 'inferred' : null;\n }\n\n const input = toScoringInput(signals, category);\n const quality = computeQuality(input);\n if (++done % 25 === 0) logger.info(` …${done}/${targets.length}`);\n return {\n target,\n category,\n categorySource,\n signals,\n input,\n maintenance: computeMaintenance(input, now),\n adoption: computeAdoption(input),\n reliability: computeReliability(input),\n quality,\n confidence: computeConfidence(input, now, quality),\n summary,\n usageGuide,\n };\n } catch (err) {\n allErrors.push({\n package: target.name,\n source: 'pipeline',\n message: err instanceof Error ? err.message : String(err),\n });\n return null;\n }\n },\n config.LURQ_SYNC_CONCURRENCY,\n );\n\n const ok = computed.filter((c): c is Computed => c !== null);\n\n // ── Category medians for efficiency (§10) ────────────────────────────────\n const medians = computeCategoryMedians(ok);\n\n // ── Embeddings (§11): embed the normalized text blob for each package ─────\n const embProvider = createEmbeddingProvider();\n logger.info(`Embedding provider: ${embProvider.kind}`);\n const embeddings = await embProvider.embed(\n ok.map((c) =>\n buildEmbeddingText({\n name: c.target.name,\n category: c.category,\n summary: c.summary,\n description: c.signals.registry?.description ?? null,\n }),\n ),\n );\n\n // ── Pass 2: efficiency + composite + upsert ──────────────────────────────\n let updated = 0;\n for (let i = 0; i < ok.length; i++) {\n const c = ok[i]!;\n const efficiency = computeEfficiency(\n c.input.bundleMinGzipKb,\n c.category,\n c.category ? (medians.get(c.category) ?? null) : null,\n );\n const breakdown: ScoreBreakdown = {\n maintenance: c.maintenance,\n adoption: c.adoption,\n reliability: c.reliability,\n efficiency,\n quality: c.quality,\n };\n const healthScore = computeHealthScore(breakdown);\n await upsertPackage(\n handle.db,\n assemblePackageRow({\n name: c.target.name,\n category: c.category,\n categorySource: c.categorySource,\n signals: c.signals,\n input: c.input,\n summary: c.summary,\n usageGuide: c.usageGuide,\n confidence: c.confidence,\n breakdown,\n healthScore,\n qualityScore: c.quality,\n embedding: embeddings[i] ?? null,\n embeddingProvider: embProvider.id,\n now,\n }),\n );\n // Record the version timeline. The on-demand path (pipeline/single.ts)\n // has always done this; the sync pass never did, so every package whose\n // only route into the index is the nightly cron — which is the entire\n // seed list — had a package row and no history behind it. Measured on\n // production before this line existed: 220 tracked packages with zero\n // versions, including react, chalk, commander, lodash, eslint and\n // esbuild, and 15 of the 100 most-installed packages in the index.\n //\n // Everything version-shaped reads that table, so the absence was not\n // quiet: the drift board's \"N% of packages have broken\" is computed over\n // a set that could not contain them, and `compat`, `usage` and the whole\n // upgrade path have nothing to say about a package with no timeline.\n //\n // Failure is logged rather than swallowed. single.ts catches this into a\n // bare `() => {}` — right that a history write must not fail a sync,\n // wrong that it should do so in silence, which is the other half of why\n // this went unnoticed.\n await upsertPackageVersions(\n handle.db,\n c.target.name,\n c.signals.registry?.versionTimeline ?? [],\n ).catch((err: unknown) => {\n logger.warn(`version timeline write failed for ${c.target.name}: ${String(err)}`);\n });\n updated++;\n }\n\n // ── Mine observed compat edges (§4B) ─────────────────────────────────────\n // Every ingested package's resolved closure is a co-installation witness;\n // mint free `observed` edges among its tracked nodes. Tracked set loaded once\n // (§4B step 2). Best-effort; concurrency 1 caps peak memory for fat trees\n // (ingest above stays concurrent).\n const tracked = new Set(await getAllPackageNames(handle.db));\n await pMap(\n ok,\n (c) => mineEdgesForPackage(handle.db, c.target.name, c.signals.registry?.latestVersion ?? null, tracked, now),\n SYNC_MINE_CONCURRENCY,\n );\n // Trigger 2 (§4B): a full sync is the daily cron — re-mine every persisted\n // closure against the *current* tracked set (no network) so packages tracked\n // since the closure was captured get fully linked within 24h. Best-effort.\n if (!opts.packageName) {\n await remineAllClosures(handle.db).catch((err) =>\n logger.warn(`re-mine pass failed: ${formatError(err)}`),\n );\n }\n\n const status: SyncSummary['status'] =\n updated === 0 ? 'failed' : allErrors.length > 0 ? 'partial' : 'success';\n await finishSyncRun(handle.db, runId, {\n packagesSeen: targets.length,\n packagesUpdated: updated,\n errors: allErrors,\n status,\n });\n\n logger.info(`Sync ${status}: ${updated}/${targets.length} updated, ${allErrors.length} source errors.`);\n // The index changed — drop cached reads so the next query sees fresh scores.\n if (updated > 0) await invalidateCache();\n return { seen: targets.length, updated, errors: allErrors.length, status };\n } catch (err) {\n await finishSyncRun(handle.db, runId, {\n packagesSeen: 0,\n packagesUpdated: 0,\n errors: [{ package: '*', source: 'pipeline', message: (err as Error).message }],\n status: 'failed',\n });\n throw err;\n } finally {\n if (opts.full) setCacheBypassRead(false);\n await handle.close();\n }\n}\n\n/**\n * Seeds every run, plus a rotation of the stalest discovered packages. Seeds are\n * ~9% of the index; syncing only those left the other ~91% frozen at their\n * ingest date (and, via `latest_version`, stalled discovery — see\n * `getStaleRefreshTargets`).\n */\nasync function resolveTargets(\n db: Database,\n opts: SyncOptions,\n refreshCap: number,\n): Promise<Target[]> {\n const seeds = await getSeedTargets(db);\n if (opts.packageName) {\n const found = seeds.find((s) => s.name === opts.packageName);\n return [{ name: opts.packageName, category: found?.category ?? null }];\n }\n const refresh = await getStaleRefreshTargets(db, refreshCap);\n logger.info(`Targets: ${seeds.length} seed(s) + ${refresh.length} stale refresh(es).`);\n return [...seeds, ...refresh];\n}\n\nfunction computeCategoryMedians(computed: Computed[]): Map<Category, number> {\n const byCategory = new Map<Category, number[]>();\n for (const c of computed) {\n const cat = c.category;\n const kb = c.input.bundleMinGzipKb;\n if (cat && isFrontendCategory(cat) && kb !== null) {\n const list = byCategory.get(cat) ?? [];\n list.push(kb);\n byCategory.set(cat, list);\n }\n }\n const medians = new Map<Category, number>();\n for (const [cat, list] of byCategory) {\n const m = median(list);\n if (m !== null) medians.set(cat, m);\n }\n return medians;\n}\n\n/** Assemble a fully-scored package row. Shared by the bulk sync and the\n * on-demand single-package path (§12.5). */\nexport function assemblePackageRow(p: {\n name: string;\n category: Category | null;\n categorySource: CategorySource | null;\n signals: RawPackageSignals;\n input: ScoringInput;\n summary: string | null;\n usageGuide: NewPackageRow['usageGuide'];\n confidence: NewPackageRow['confidence'];\n breakdown: ScoreBreakdown;\n healthScore: number;\n qualityScore: number | null;\n embedding: number[] | null;\n embeddingProvider: string | null;\n now: Date;\n}): NewPackageRow {\n const r = p.signals.registry;\n return {\n name: p.name,\n ecosystem: 'npm',\n category: p.category,\n categorySource: p.categorySource,\n description: r?.description ?? null,\n summary: p.summary,\n repoUrl: r?.repoUrl ?? null,\n homepage: r?.homepage ?? null,\n latestVersion: r?.latestVersion ?? null,\n license: r?.license ?? null,\n deprecated: p.input.deprecated,\n archived: p.input.archived,\n firstPublishedAt: p.input.firstPublishedAt,\n lastReleaseAt: p.input.lastReleaseAt,\n weeklyDownloads: p.input.weeklyDownloads,\n downloadGrowth90d: p.input.downloadGrowth90d,\n stars: p.input.stars,\n openIssues: p.input.openIssues,\n closedIssues: p.input.closedIssues,\n scorecard: p.input.scorecard,\n bundleMinGzipKb: p.input.bundleMinGzipKb,\n advisories: p.input.advisories,\n peerDependencies: r?.peerDependencies ?? null,\n peerDependenciesMeta: r?.peerDependenciesMeta ?? null,\n engines: r?.engines ?? null,\n healthScore: p.healthScore,\n qualityScore: p.qualityScore,\n confidence: p.confidence,\n scoreBreakdown: p.breakdown,\n usageGuide: p.usageGuide,\n embedding: p.embedding,\n embeddingProvider: p.embedding ? p.embeddingProvider : null,\n dataAsOf: p.now,\n };\n}\n","/**\n * In-process background ingester for on-demand misses (§12.5). Keeps the heavy\n * fetch→score→embed→upsert OFF the request path: evaluate/compare/verify enqueue\n * an untracked-but-real package and return immediately (\"tracking, retry\n * shortly\"), while a bounded worker pool ingests it within seconds.\n *\n * Bounded on purpose — moving unbounded work off the request path just relocates\n * the problem. Dedup (a package already pending or in-flight is never queued\n * again) + a hard pending cap mean a flood of distinct names can't spawn\n * unbounded syncs or grow memory without limit. Process-local; each instance\n * drains its own queue. Durability is by self-heal: if the process dies with\n * work pending, the next request for that package re-enqueues it.\n */\nimport { logger } from '../core/logger';\nimport type { Database } from '../db/client';\nimport { ensureSeedEntry } from '../db/packages';\nimport type { PackageRow } from '../db/schema';\nimport { syncOnePackage } from './single';\n\nconst MAX_CONCURRENT = 3;\nconst MAX_PENDING = 500;\n\nconst pending: string[] = [];\nconst inFlight = new Set<string>();\nconst queuedNames = new Set<string>();\n/** First-requester ownerId per queued name (dashboard v1 phase 2 attribution).\n * Dedup stays keyed by name, so the first enqueue's owner is the one credited. */\nconst owners = new Map<string, string | null>();\nlet active = 0;\n\n/** Current backlog (pending + in-flight) — exposed for tests/observability. */\nexport function ingestQueueDepth(): number {\n return pending.length + inFlight.size;\n}\n\n/** Test-only: clear all queue state. */\nexport function resetIngestQueue(): void {\n pending.length = 0;\n inFlight.clear();\n queuedNames.clear();\n owners.clear();\n active = 0;\n}\n\n/**\n * Schedule an untracked-but-real package for background ingestion. No-op if it's\n * already pending or in-flight, or if the queue is at capacity. Returns without\n * awaiting any network/DB work.\n */\nexport function enqueueIngest(\n db: Database,\n name: string,\n requestedByOwnerId: string | null = null,\n): void {\n if (queuedNames.has(name) || inFlight.has(name)) return;\n if (pending.length >= MAX_PENDING) {\n logger.warn(`ingest queue full (${MAX_PENDING}); dropping on-demand request for ${name}`);\n return;\n }\n queuedNames.add(name);\n owners.set(name, requestedByOwnerId);\n pending.push(name);\n pump(db);\n}\n\nfunction pump(db: Database): void {\n while (active < MAX_CONCURRENT && pending.length > 0) {\n const name = pending.shift()!;\n queuedNames.delete(name);\n const owner = owners.get(name) ?? null;\n owners.delete(name);\n inFlight.add(name);\n active += 1;\n void runIngest(db, name, owner).finally(() => {\n inFlight.delete(name);\n active -= 1;\n pump(db);\n });\n }\n}\n\n/**\n * Fetch→score→embed→upsert one package and, if it clears the roster-promotion\n * bar, seed it for future syncs. Returns the stored row, or null on failure.\n * Shared by the background queue and the block-on-first-touch path (§4A) so both\n * apply the same promotion rule.\n */\nexport async function runIngest(\n db: Database,\n name: string,\n requestedByOwnerId: string | null = null,\n): Promise<PackageRow | null> {\n try {\n const row = await syncOnePackage(db, name, { requestedByOwnerId });\n // Same roster-promotion bar as the old inline path: only genuinely-trackable\n // discoveries join the sync roster, so the on-demand tail can't inflate cost.\n if (row.confidence && row.confidence !== 'unproven') {\n await ensureSeedEntry(db, name, row.category).catch(() => {});\n }\n return row;\n } catch (err) {\n logger.warn(`on-demand ingest failed for ${name}: ${String(err)}`);\n return null;\n }\n}\n","/**\n * Single-package ingestion + the on-demand path (§12.5). When a queried package\n * isn't tracked but exists on npm, lurq fetches, scores, embeds, stores, and\n * returns it — organically growing coverage beyond the seed list.\n */\nimport { and, eq, isNotNull, sql } from 'drizzle-orm';\nimport { getConfig } from '../core/config';\nimport { logger } from '../core/logger';\nimport type { Category, CategorySource, ScoreBreakdown } from '../core/types';\nimport { collectSignals } from '../ingestion/collect';\nimport { fetchWeeklyDownloads, npmPackageExists } from '../ingestion/sources';\nimport { buildSummaryInput, createSummaryProvider } from '../ingestion/summarize';\nimport { inferCategoryFromSignals } from '../search/categoryInference';\nimport {\n computeAdoption,\n computeConfidence,\n computeEfficiency,\n computeHealthScore,\n computeMaintenance,\n computeQuality,\n computeReliability,\n toScoringInput,\n} from '../scoring';\nimport { buildEmbeddingText, createEmbeddingProvider } from '../search/embeddings';\nimport type { Database } from '../db/client';\nimport {\n getPackageByName,\n stampFirstRequester,\n upsertPackage,\n upsertPackageVersions,\n} from '../db/packages';\nimport { packages, seedPackages, type PackageRow } from '../db/schema';\nimport { assemblePackageRow } from './sync';\nimport { mineEdgesForPackage } from './mineEdges';\n// Safe module cycle: ingestQueue imports syncOnePackage from here, but both\n// bindings are used only at call time, never at module-eval, so ESM resolves it.\nimport { enqueueIngest, runIngest } from './ingestQueue';\n\n/** Block-on-first-touch budget for single-package tools (§4A). Past this the\n * in-flight ingest keeps running in the background and the caller gets the\n * \"retry shortly\" hint instead of a stalled request. */\nexport const FIRST_TOUCH_BUDGET_MS = 4000;\n\nfunction raceTimeout<T>(p: Promise<T>, ms: number): Promise<T | null> {\n let timer: NodeJS.Timeout;\n // Cleared on settle: a live timer keeps Node's event loop open, so without\n // this the CLI sat idle for the rest of the budget after a fast ingest.\n return Promise.race([\n p,\n new Promise<null>((resolve) => {\n timer = setTimeout(() => resolve(null), ms);\n }),\n ]).finally(() => clearTimeout(timer));\n}\n\nasync function getSeedCategory(db: Database, name: string): Promise<Category | null> {\n const [row] = await db\n .select({ category: seedPackages.category })\n .from(seedPackages)\n .where(eq(seedPackages.name, name))\n .limit(1);\n return row?.category ?? null;\n}\n\n/** Median bundle size across already-tracked packages in a category (for efficiency). */\nasync function getCategoryMedianBundle(db: Database, category: Category): Promise<number | null> {\n const [row] = await db\n .select({\n m: sql<number | null>`percentile_cont(0.5) within group (order by ${packages.bundleMinGzipKb})`,\n })\n .from(packages)\n .where(and(eq(packages.category, category), isNotNull(packages.bundleMinGzipKb)));\n return row?.m ?? null;\n}\n\n/** Fetch, score, embed, and upsert a single package; returns the stored row. */\nexport async function syncOnePackage(\n db: Database,\n name: string,\n opts: { category?: Category | null; requestedByOwnerId?: string | null } = {},\n): Promise<PackageRow> {\n const config = getConfig();\n const now = new Date();\n\n const existing = await getPackageByName(db, name);\n // The curated category (from a manual arg or the seed list) wins. We resolve\n // the final category *after* ingest so a discovered package can be classified\n // from its own text rather than stored as a second-class `null` (§2A).\n const curatedCategory = opts.category ?? (await getSeedCategory(db, name)) ?? null;\n const initialCategory = curatedCategory ?? existing?.category ?? null;\n\n const prefetchedWeekly = await fetchWeeklyDownloads(name).catch(() => null);\n const signals = await collectSignals(name, initialCategory, {\n githubToken: config.GITHUB_TOKEN,\n prefetchedWeekly,\n });\n\n const summaryInput = await buildSummaryInput(signals, initialCategory);\n const { summary, usageGuide, inferredCategory } =\n await createSummaryProvider().generate(summaryInput);\n\n let category: Category | null;\n let categorySource: CategorySource | null;\n if (curatedCategory) {\n category = curatedCategory;\n categorySource = 'curated';\n } else if (existing?.category) {\n category = existing.category;\n categorySource = existing.categorySource ?? 'inferred';\n } else {\n category = inferCategoryFromSignals(signals) ?? inferredCategory ?? null;\n categorySource = category ? 'inferred' : null;\n }\n\n const input = toScoringInput(signals, category);\n\n const median = category ? await getCategoryMedianBundle(db, category) : null;\n const quality = computeQuality(input);\n const breakdown: ScoreBreakdown = {\n maintenance: computeMaintenance(input, now),\n adoption: computeAdoption(input),\n reliability: computeReliability(input),\n efficiency: computeEfficiency(input.bundleMinGzipKb, category, median),\n quality,\n };\n const healthScore = computeHealthScore(breakdown);\n const confidence = computeConfidence(input, now, quality);\n\n const embProvider = createEmbeddingProvider();\n const [embedding] = await embProvider.embed([\n buildEmbeddingText({ name, category, summary, description: signals.registry?.description ?? null }),\n ]);\n\n await upsertPackage(\n db,\n assemblePackageRow({\n name,\n category,\n categorySource,\n signals,\n input,\n summary,\n usageGuide,\n confidence,\n breakdown,\n healthScore,\n qualityScore: quality,\n embedding: embedding ?? null,\n embeddingProvider: embProvider.id,\n now,\n }),\n );\n // Attribution (dashboard v1 phase 2): if this call is the one that first\n // inserted the row, credit the requesting account. Standalone + IS NULL-guarded\n // (see stampFirstRequester) so re-syncs never clobber it and concurrent\n // first-touches resolve deterministically. Best-effort — never blocks the upsert.\n if (!existing && opts.requestedByOwnerId) {\n await stampFirstRequester(db, name, opts.requestedByOwnerId).catch(() => {});\n }\n // Record the version timeline (idempotent). Non-fatal: never block a\n // successful package upsert on the version-history write.\n await upsertPackageVersions(db, name, signals.registry?.versionTimeline ?? []).catch((err) =>\n // Swallowed but no longer invisible: this is the only write to\n // package_versions in the codebase, and drift reads that table, so a\n // failure here silently zeroes drift for the package.\n logger.warn(`version timeline write failed for ${name}: ${(err as Error).message}`),\n );\n // Mint observed compat edges from this package's resolved closure (§4B\n // Trigger 1). Best-effort — mineEdgesForPackage swallows its own errors.\n await mineEdgesForPackage(db, name, signals.registry?.latestVersion ?? null, undefined, now);\n return (await getPackageByName(db, name))!;\n}\n\nexport interface GetOrFetchResult {\n row: PackageRow | null;\n /** True if the package was already in the index before this call. */\n wasTracked: boolean;\n existsOnNpm: boolean;\n /** True if a real-but-untracked package was scheduled for background\n * ingestion this call — the caller should tell the agent to retry shortly. */\n queued?: boolean;\n}\n\n/**\n * Return a tracked package, or — if it's a real npm package not yet in the index\n * (§12.5) — fetch it. Two modes:\n *\n * - Default (async): schedule background ingestion and return row=null so a\n * multi-package fan-out never blocks on one slow package.\n * - `blockMs` set (§4A block-on-first-touch): await the ingest up to a budget\n * and return the real row on the *first* call. On timeout the ingest keeps\n * running in the background and the caller gets the \"retry shortly\" hint.\n *\n * Returns existsOnNpm=false when the name isn't a real package at all.\n */\nexport async function getOrFetchPackage(\n db: Database,\n name: string,\n opts: { blockMs?: number; requestedByOwnerId?: string | null } = {},\n): Promise<GetOrFetchResult> {\n const existing = await getPackageByName(db, name);\n if (existing) return { row: existing, wasTracked: true, existsOnNpm: true };\n\n const exists = await npmPackageExists(name);\n if (!exists) return { row: null, wasTracked: false, existsOnNpm: false };\n\n if (opts.blockMs && opts.blockMs > 0) {\n // Single-package tools await the ingest so the first call returns a real row\n // instead of a placeholder that reads as failure. On timeout the started\n // ingest keeps running (not cancelled) and lands within a few more seconds.\n // ponytail: inline ingest isn't queue-bounded; single-package request rate\n // is the natural cap. Route through enqueueIngest if a flood ever appears.\n const row = await raceTimeout(runIngest(db, name, opts.requestedByOwnerId ?? null), opts.blockMs);\n if (row) return { row, wasTracked: false, existsOnNpm: true };\n return { row: null, wasTracked: false, existsOnNpm: true, queued: true };\n }\n\n // Real but untracked: ingest off the request path. Bounded + deduped so a\n // flood of distinct names can't spawn unbounded work (the whole point of not\n // doing it inline). Roster promotion happens in the worker, same quality bar.\n enqueueIngest(db, name, opts.requestedByOwnerId ?? null);\n return { row: null, wasTracked: false, existsOnNpm: true, queued: true };\n}\n","/**\n * Hybrid recommendation (§3, §11). Two retrievals run over the same candidate\n * table — vector cosine (semantic) and `tsvector` lexical (exact name/keyword) —\n * fused with Reciprocal Rank Fusion (RRF), then re-ranked by a blend of fused\n * relevance and the quality-aware composite (§1). Pure vector search misses\n * exact-name hits (especially the keyless local embedder); the lexical leg fixes\n * that, and RRF avoids having to normalize two incomparable score scales.\n */\nimport { and, cosineDistance, eq, inArray, isNotNull, lte, sql } from 'drizzle-orm';\nimport type { Candidate, Category, Confidence } from '../core/types';\nimport type { Database } from '../db/client';\nimport { packages } from '../db/schema';\nimport { computeComposite } from '../scoring';\nimport { loadWeights } from '../scoring/weights';\nimport { inferCategory } from './categoryInference';\nimport { createEmbeddingProvider, type EmbeddingProvider } from './embeddings';\n\nexport interface RecommendConstraints {\n license?: string;\n maxBundleKb?: number;\n minConfidence?: Confidence;\n}\n\nexport interface RecommendOptions {\n need: string;\n category?: Category;\n constraints?: RecommendConstraints;\n limit?: number;\n}\n\nconst CONFIDENCE_RANK: Record<Confidence, number> = {\n unproven: 0,\n promising: 1,\n emerging: 2,\n proven: 3,\n};\n/** Fused-relevance vs composite blend (§3, §11). The second term is the\n * quality-aware composite (§1), not raw health — so a well-built package isn't\n * buried by a popularity-tilted score. */\nconst RELEVANCE_WEIGHT = 0.6;\nconst COMPOSITE_WEIGHT = 0.4;\n/** RRF damping constant — standard value from the original RRF paper (§3). */\nconst RRF_K = 60;\n\ninterface Row {\n name: string;\n category: Category | null;\n healthScore: number | null;\n qualityScore: number | null;\n confidence: Confidence | null;\n latestVersion: string | null;\n weeklyDownloads: number | null;\n lastReleaseAt: Date | null;\n repoUrl: string | null;\n}\n\nexport async function recommend(\n db: Database,\n opts: RecommendOptions,\n provider: EmbeddingProvider = createEmbeddingProvider(),\n): Promise<Candidate[]> {\n const limit = Math.min(Math.max(opts.limit ?? 3, 1), 5);\n const [queryVec] = await provider.embed([opts.need]);\n if (!queryVec) return [];\n\n const category = opts.category ?? inferCategory(opts.need);\n const pool = Math.max(limit * 5, 25);\n\n // Primary search (category-filtered when we have one).\n let fused = await hybridSearch(db, queryVec, provider.id, opts.need, opts.constraints, category, pool);\n // If a category filter starved the results, broaden to all categories.\n if (category && fused.length < limit) {\n const broad = await hybridSearch(db, queryVec, provider.id, opts.need, opts.constraints, null, pool);\n const seen = new Set(fused.map((f) => f.row.name));\n fused = fused.concat(broad.filter((f) => !seen.has(f.row.name)));\n }\n if (fused.length === 0) return [];\n\n // Re-rank: blend normalized fused relevance (RRF) with the quality-aware\n // composite (§1). RRF rank-fusion already absorbs both retrieval legs, so the\n // relevance term rewards exact lexical hits the vector leg alone would miss.\n const lambda = loadWeights().composite.lambda;\n const maxRrf = Math.max(...fused.map((f) => f.rrf));\n const ranked = fused\n .map((f) => {\n const relevance = maxRrf > 0 ? f.rrf / maxRrf : 0;\n const composite = computeComposite(f.row.healthScore ?? 0, f.row.qualityScore, lambda) / 100;\n return { row: f.row, score: RELEVANCE_WEIGHT * relevance + COMPOSITE_WEIGHT * composite };\n })\n .sort((a, b) => b.score - a.score)\n .slice(0, limit);\n\n return ranked.map(({ row }) => toCandidate(row));\n}\n\ninterface Fused {\n row: Row;\n rrf: number;\n}\n\n/**\n * Run the vector and lexical retrievals and fuse them with RRF (§3). Each leg\n * independently ranks the candidate set; a doc's fused score is the sum of\n * 1/(k+rank) across the legs it appears in — so documents both legs agree on\n * rise, and exact-name hits the vector leg ranks poorly still surface.\n */\nasync function hybridSearch(\n db: Database,\n queryVec: number[],\n providerId: string,\n need: string,\n constraints: RecommendConstraints | undefined,\n category: Category | null,\n pool: number,\n): Promise<Fused[]> {\n const [vectorRows, lexicalRows] = await Promise.all([\n runVectorQuery(db, queryVec, providerId, constraints, category, pool),\n runLexicalQuery(db, need, constraints, category, pool),\n ]);\n return rrfFuse([vectorRows, lexicalRows]);\n}\n\n/**\n * Reciprocal Rank Fusion over N ranked lists (§3). A document's fused score is\n * Σ 1/(k + rank) across the lists it appears in — using only ranks, never raw\n * scores, so two incomparable scales (cosine distance vs ts_rank) never need\n * normalizing. Generic over `{ name }` so the fusion math is unit-testable.\n */\nexport function rrfFuse<T extends { name: string }>(\n lists: T[][],\n k = RRF_K,\n): { row: T; rrf: number }[] {\n const fused = new Map<string, { row: T; rrf: number }>();\n for (const list of lists) {\n list.forEach((row, idx) => {\n const contribution = 1 / (k + idx + 1); // rank is 1-based\n const prev = fused.get(row.name);\n if (prev) prev.rrf += contribution;\n else fused.set(row.name, { row, rrf: contribution });\n });\n }\n return [...fused.values()].sort((a, b) => b.rrf - a.rrf);\n}\n\nconst ROW_COLUMNS = {\n name: packages.name,\n category: packages.category,\n healthScore: packages.healthScore,\n qualityScore: packages.qualityScore,\n confidence: packages.confidence,\n latestVersion: packages.latestVersion,\n weeklyDownloads: packages.weeklyDownloads,\n lastReleaseAt: packages.lastReleaseAt,\n repoUrl: packages.repoUrl,\n} as const;\n\n/** Shared filter conditions (category + constraints) for both retrieval legs. */\nfunction buildConditions(\n constraints: RecommendConstraints | undefined,\n category: Category | null,\n) {\n const conditions = [];\n if (category) conditions.push(eq(packages.category, category));\n if (constraints?.license) conditions.push(eq(packages.license, constraints.license));\n if (constraints?.maxBundleKb !== undefined) {\n conditions.push(lte(packages.bundleMinGzipKb, constraints.maxBundleKb));\n }\n if (constraints?.minConfidence) {\n const allowed = (['proven', 'emerging', 'promising', 'unproven'] as Confidence[]).filter(\n (c) => CONFIDENCE_RANK[c] >= CONFIDENCE_RANK[constraints.minConfidence!],\n );\n // Parameterized: drizzle binds each value, closing the sql.raw interpolation\n // hole (safe today — validated enum — but no reason to keep a raw string).\n conditions.push(inArray(packages.confidence, allowed));\n }\n return conditions;\n}\n\n/** Semantic leg: pgvector cosine, ordered by ascending distance. */\nasync function runVectorQuery(\n db: Database,\n queryVec: number[],\n providerId: string,\n constraints: RecommendConstraints | undefined,\n category: Category | null,\n pool: number,\n): Promise<Row[]> {\n const distance = cosineDistance(packages.embedding, queryVec);\n // Only compare vectors produced in the same space as the query vector. Rows\n // embedded by a different provider/model are excluded (they get retrieved by\n // the lexical leg instead) rather than compared across incompatible spaces.\n const conditions = [\n isNotNull(packages.embedding),\n eq(packages.embeddingProvider, providerId),\n ...buildConditions(constraints, category),\n ];\n return db\n .select(ROW_COLUMNS)\n .from(packages)\n .where(and(...conditions))\n .orderBy(distance)\n .limit(pool);\n}\n\n/** Lexical leg: full-text `tsvector` match, ranked by `ts_rank` (§3). */\nasync function runLexicalQuery(\n db: Database,\n need: string,\n constraints: RecommendConstraints | undefined,\n category: Category | null,\n pool: number,\n): Promise<Row[]> {\n const tsquery = sql`websearch_to_tsquery('english', ${need})`;\n const rank = sql<number>`ts_rank(${packages.searchVector}, ${tsquery})`;\n const conditions = [sql`${packages.searchVector} @@ ${tsquery}`, ...buildConditions(constraints, category)];\n return db\n .select(ROW_COLUMNS)\n .from(packages)\n .where(and(...conditions))\n .orderBy(sql`${rank} desc`)\n .limit(pool);\n}\n\nfunction toCandidate(row: Row): Candidate {\n return {\n name: row.name,\n category: row.category,\n healthScore: row.healthScore ?? 0,\n qualityScore: row.qualityScore,\n confidence: row.confidence ?? 'unproven',\n why: buildWhy(row),\n latestVersion: row.latestVersion,\n weeklyDownloads: row.weeklyDownloads,\n lastReleaseAt: row.lastReleaseAt ? row.lastReleaseAt.toISOString() : null,\n repoUrl: row.repoUrl,\n };\n}\n\n/** A ≤1-sentence rationale (§12.3.1). */\nfunction buildWhy(row: Row): string {\n const parts: string[] = [];\n if (row.confidence) parts.push(row.confidence);\n if (row.weeklyDownloads) parts.push(`${formatDownloads(row.weeklyDownloads)} weekly downloads`);\n if (row.healthScore !== null) parts.push(`health ${row.healthScore}`);\n return parts.join(', ') || 'tracked package';\n}\n\nfunction formatDownloads(n: number): string {\n if (n >= 1_000_000) return `${Math.round(n / 100_000) / 10}M`;\n if (n >= 1_000) return `${Math.round(n / 1_000)}k`;\n return String(n);\n}\n","/**\n * Supply-chain risk gate.\n *\n * Rolls the individual findings from `verify` into a single level an agent can\n * act on before installing:\n * high — do not install without human review\n * medium — proceed with caution / prefer an alternative\n * low — no supply-chain red flags\n *\n * Install scripts alone are NOT escalated (esbuild, sharp, husky all use them);\n * they only matter on an otherwise low-trust package.\n */\nimport type { RiskLevel } from '../core/types';\n\nexport interface RiskInput {\n /** All collected riskFlags (used for the `single-maintainer` signal). */\n flags: string[];\n hasCriticalOrHighAdvisory: boolean;\n /** Name closely mimics a popular package. */\n typosquat: boolean;\n /** Runs preinstall/install/postinstall hooks. */\n installScripts: boolean;\n /** First published within the last 7 days. */\n brandNew: boolean;\n /** Fewer than ~1k weekly downloads (or unknown). */\n lowTrust: boolean;\n deprecatedOrArchived: boolean;\n}\n\nexport function assessRisk(i: RiskInput): RiskLevel {\n // Classic malware fingerprint: brand-new + install hooks + ~no adoption.\n const malwarePattern = i.installScripts && i.brandNew && i.lowTrust;\n if (i.typosquat || i.hasCriticalOrHighAdvisory || malwarePattern) return 'high';\n\n if (\n i.deprecatedOrArchived ||\n (i.installScripts && (i.lowTrust || i.brandNew)) ||\n (i.lowTrust && i.flags.includes('single-maintainer'))\n ) {\n return 'medium';\n }\n return 'low';\n}\n","[\n \"react\", \"react-dom\", \"react-router\", \"react-router-dom\", \"next\", \"vue\",\n \"vue-router\", \"pinia\", \"vuex\", \"svelte\", \"solid-js\", \"preact\", \"angular\",\n \"@angular/core\", \"jquery\", \"lodash\", \"underscore\", \"ramda\", \"immer\", \"rxjs\",\n \"express\", \"koa\", \"fastify\", \"@nestjs/core\", \"hapi\", \"connect\", \"body-parser\",\n \"cookie-parser\", \"cors\", \"helmet\", \"morgan\", \"compression\", \"express-session\",\n \"express-rate-limit\", \"multer\", \"passport\", \"jsonwebtoken\", \"bcrypt\",\n \"bcryptjs\", \"axios\", \"node-fetch\", \"got\", \"undici\", \"superagent\", \"request\",\n \"cheerio\", \"puppeteer\", \"playwright\", \"cypress\", \"jsdom\", \"ws\", \"socket.io\",\n \"socket.io-client\", \"graphql\", \"@apollo/client\", \"apollo-server\", \"dataloader\",\n \"mongoose\", \"mongodb\", \"pg\", \"mysql2\", \"sequelize\", \"prisma\", \"knex\",\n \"drizzle-orm\", \"typeorm\", \"redis\", \"ioredis\", \"sqlite3\", \"better-sqlite3\",\n \"typescript\", \"eslint\", \"prettier\", \"tslint\", \"webpack\", \"vite\", \"rollup\",\n \"esbuild\", \"parcel\", \"@babel/core\", \"babel-core\", \"babel-loader\", \"ts-node\",\n \"tsx\", \"tsup\", \"nodemon\", \"concurrently\", \"npm-run-all\", \"jest\", \"vitest\",\n \"mocha\", \"chai\", \"sinon\", \"ava\", \"tape\", \"supertest\", \"@testing-library/react\",\n \"enzyme\", \"chalk\", \"colors\", \"kleur\", \"picocolors\", \"ansi-colors\", \"commander\",\n \"yargs\", \"meow\", \"minimist\", \"inquirer\", \"prompts\", \"ora\", \"boxen\", \"figlet\",\n \"cli-progress\", \"debug\", \"dotenv\", \"cross-env\", \"rimraf\", \"glob\", \"fast-glob\",\n \"chokidar\", \"fs-extra\", \"execa\", \"cross-spawn\", \"shelljs\", \"which\", \"semver\",\n \"uuid\", \"nanoid\", \"ulid\", \"moment\", \"dayjs\", \"date-fns\", \"luxon\", \"zod\", \"yup\",\n \"joi\", \"ajv\", \"validator\", \"class-validator\", \"winston\", \"pino\", \"bunyan\",\n \"nodemailer\", \"node-cron\", \"bull\", \"bullmq\", \"kafkajs\", \"amqplib\", \"sharp\",\n \"jimp\", \"archiver\", \"tar\", \"adm-zip\", \"qs\", \"query-string\", \"form-data\",\n \"mime-types\", \"http-errors\", \"classnames\", \"clsx\", \"styled-components\",\n \"@emotion/react\", \"tailwindcss\", \"postcss\", \"autoprefixer\", \"sass\", \"less\",\n \"framer-motion\", \"three\", \"d3\", \"chart.js\", \"recharts\", \"gsap\", \"swiper\",\n \"leaflet\", \"mapbox-gl\", \"formik\", \"react-hook-form\", \"redux\", \"@reduxjs/toolkit\",\n \"zustand\", \"jotai\", \"mobx\", \"bootstrap\", \"@popperjs/core\", \"aws-sdk\",\n \"@aws-sdk/client-s3\", \"firebase\", \"firebase-admin\", \"stripe\", \"twilio\",\n \"openai\", \"@anthropic-ai/sdk\", \"googleapis\", \"bignumber.js\", \"decimal.js\",\n \"mathjs\", \"slugify\", \"faker\", \"@faker-js/faker\", \"puppeteer-core\"\n]\n","/**\n * Typosquat detection.\n *\n * A package whose name is a near-miss of a popular one (`crossenv` for\n * `cross-env`, `expres` for `express`) is the classic supply-chain attack: a\n * coding agent fat-fingers or hallucinates a name and installs the impostor.\n * We compare a queried name against the most-downloaded packages lurq already\n * tracks — a tiny edit distance to a popular name the package itself is NOT is\n * a strong signal.\n */\nimport popularPackages from '../data/popular-packages.json';\n\n/** Static baseline of well-known npm names. Unioned with the tracked corpus so\n * detection still works on a cold/thin index (fresh deploy, few syncs) and\n * catches squats of famous packages that aren't tracked yet. */\nconst POPULAR_BASELINE = popularPackages as string[];\n\n/** Tracked top-downloads names + the static baseline, de-duplicated. Pass the\n * result as the corpus to `detectTyposquat` so the guard is never silently off. */\nexport function typosquatCorpus(trackedTopNames: string[]): string[] {\n return [...new Set([...POPULAR_BASELINE, ...trackedTopNames])];\n}\n\n/** `@scope/name` → `name` so scope decoration doesn't dominate the distance. */\nfunction bareName(name: string): string {\n const slash = name.indexOf('/');\n return (slash >= 0 ? name.slice(slash + 1) : name).toLowerCase();\n}\n\n/**\n * Damerau-Levenshtein (optimal string alignment) edit distance — counts\n * insertions, deletions, substitutions, and adjacent transpositions.\n */\nexport function editDistance(a: string, b: string): number {\n const m = a.length;\n const n = b.length;\n if (m === 0) return n;\n if (n === 0) return m;\n\n // Rolling rows: prevPrev enables the adjacent-transposition check.\n let prevPrev = new Array<number>(n + 1).fill(0);\n let prev = Array.from({ length: n + 1 }, (_, j) => j);\n for (let i = 1; i <= m; i++) {\n const cur = new Array<number>(n + 1).fill(0);\n cur[0] = i;\n for (let j = 1; j <= n; j++) {\n const cost = a[i - 1] === b[j - 1] ? 0 : 1;\n let val = Math.min(\n (prev[j] ?? 0) + 1,\n (cur[j - 1] ?? 0) + 1,\n (prev[j - 1] ?? 0) + cost,\n );\n if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) {\n val = Math.min(val, (prevPrev[j - 2] ?? 0) + 1);\n }\n cur[j] = val;\n }\n prevPrev = prev;\n prev = cur;\n }\n return prev[n] ?? 0;\n}\n\nexport type TyposquatHit = { target: string; distance: number };\n\n/**\n * Closest popular package within `maxDistance` edits, or null. The queried name\n * being popular itself is never a hit. Names shorter than 4 chars are skipped —\n * at that length a single edit is noise, not an attack signal.\n */\nexport function detectTyposquat(\n name: string,\n popular: readonly string[],\n maxDistance = 2,\n): TyposquatHit | null {\n const target = bareName(name);\n if (target.length < 4) return null;\n if (popular.some((p) => p.toLowerCase() === name.toLowerCase())) return null;\n\n let best: TyposquatHit | null = null;\n for (const p of popular) {\n const cand = bareName(p);\n if (cand === target) continue; // same bare name (e.g. a fork under a scope)\n if (Math.abs(cand.length - target.length) > maxDistance) continue; // can't be close\n const dist = editDistance(target, cand);\n if (dist >= 1 && dist <= maxDistance && (!best || dist < best.distance)) {\n best = { target: p, distance: dist };\n if (dist === 1) break; // nothing closer is possible\n }\n }\n return best;\n}\n","/**\n * MCP tool handlers (§12.3). Pure functions over a Database — the transport\n * layer (server.ts) just wires zod schemas to these. Responses are kept compact\n * (§12.4): summaries truncated, advisories capped, no raw payloads, always a\n * `dataAsOf` and a `stale` hint when data is old (§17).\n */\nimport { createHash } from 'node:crypto';\nimport { sql } from 'drizzle-orm';\nimport { cached } from '../core/cache';\nimport { STALENESS_DAYS } from '../core/constants';\nimport type {\n Advisory,\n AdvisorySeverity,\n BuildSignal,\n BuildVerified,\n Category,\n CompatOutput,\n Confidence,\n EvaluateOutput,\n UsageOutput,\n VerifyOutput,\n} from '../core/types';\nimport { checkCompat } from '../compat/check';\nimport type { Database } from '../db/client';\nimport { getPackageByName, getTopPackageNames } from '../db/packages';\nimport { diffSurface } from '../usage/diff';\nimport { getOrExtractSurface, USAGE_EXTRACT_BUDGET_MS } from '../usage/service';\nimport { getLatestVerificationByName } from '../db/verification';\nimport { recordOutcome } from '../db/outcomes';\nimport { lookupSuccessor } from '../core/successors';\nimport type { VerificationRunRow } from '../db/schema';\nimport { packages, type PackageRow } from '../db/schema';\nimport {\n fetchNpmCompatAtVersion,\n fetchNpmRegistry,\n fetchWeeklyDownloads,\n npmPackageExists,\n} from '../ingestion/sources';\nimport { truncateSentences } from '../ingestion/summarize';\nimport { FIRST_TOUCH_BUDGET_MS, getOrFetchPackage } from '../pipeline/single';\nimport { hasCriticalOrHighAdvisory } from '../scoring/score';\nimport { recommend, type RecommendOptions } from '../search/recommend';\nimport { assessRisk } from '../security/risk';\nimport { detectTyposquat, typosquatCorpus } from '../security/typosquat';\n\nconst SEVERITY_RANK: Record<AdvisorySeverity, number> = {\n critical: 4,\n high: 3,\n moderate: 2,\n low: 1,\n info: 0,\n};\nconst DAY_MS = 24 * 60 * 60 * 1000;\n\nfunction isStale(dataAsOf: Date | null): boolean {\n if (!dataAsOf) return true;\n return Date.now() - dataAsOf.getTime() > STALENESS_DAYS * DAY_MS;\n}\n\n/** Re-derive the wall-clock `stale` hint (§17) on a (possibly cached) evaluate\n * row, so a cached response doesn't keep claiming fresh data after it ages past\n * the threshold between syncs. */\nfunction refreshStale(out: EvaluateOutput): EvaluateOutput {\n out.stale = isStale(out.dataAsOf ? new Date(out.dataAsOf) : null) || undefined;\n return out;\n}\n\nfunction withinDays(date: Date | null, days: number): boolean {\n return date ? Date.now() - date.getTime() <= days * DAY_MS : false;\n}\n\n/** Top advisories by severity, capped (§12.4). */\nfunction topAdvisories(advisories: Advisory[] | null, max = 5): Advisory[] {\n if (!advisories?.length) return [];\n return [...advisories]\n .sort((a, b) => SEVERITY_RANK[b.severity] - SEVERITY_RANK[a.severity])\n .slice(0, max);\n}\n\n/** Map a stored row to the compact EvaluateOutput shape (§12.3.2). */\nexport function rowToEvaluate(row: PackageRow): EvaluateOutput {\n const breakdown = row.scoreBreakdown ?? {\n maintenance: 0,\n adoption: 0,\n reliability: 0,\n efficiency: null,\n quality: null,\n };\n return {\n dataAsOf: (row.dataAsOf ?? new Date()).toISOString(),\n stale: isStale(row.dataAsOf) || undefined,\n name: row.name,\n category: row.category,\n healthScore: row.healthScore ?? 0,\n qualityScore: row.qualityScore ?? null,\n confidence: (row.confidence as Confidence) ?? 'unproven',\n scoreBreakdown: breakdown,\n latestVersion: row.latestVersion,\n lastReleaseAt: row.lastReleaseAt ? row.lastReleaseAt.toISOString() : null,\n weeklyDownloads: row.weeklyDownloads,\n downloadGrowth90d: row.downloadGrowth90d,\n scorecard: row.scorecard,\n bundleMinGzipKb: row.bundleMinGzipKb,\n deprecated: row.deprecated,\n archived: row.archived,\n advisories: topAdvisories(row.advisories),\n summary: row.summary ? truncateSentences(row.summary, 3) : null,\n usageGuide: row.usageGuide ?? null,\n repoUrl: row.repoUrl,\n replacedBy: lookupSuccessor(row.name),\n };\n}\n\nexport async function latestDataAsOf(db: Database): Promise<string> {\n const [row] = await db\n .select({ m: sql<string | null>`max(${packages.dataAsOf})` })\n .from(packages);\n return new Date(row?.m ?? Date.now()).toISOString();\n}\n\n// ── recommend ───────────────────────────────────────────────────────────────\n\nexport interface RecommendInput {\n need: string;\n category?: Category;\n constraints?: RecommendOptions['constraints'];\n}\n\n/** Short, stable cache key from arbitrary input. */\nfunction cacheKey(parts: unknown): string {\n return createHash('sha1').update(JSON.stringify(parts)).digest('hex').slice(0, 24);\n}\n\nexport async function handleRecommend(db: Database, input: RecommendInput) {\n return cached(\n 'rec',\n cacheKey([input.need, input.category ?? null, input.constraints ?? null]),\n async () => {\n const candidates = await recommend(db, {\n need: input.need,\n category: input.category,\n constraints: input.constraints,\n limit: 5,\n });\n return { dataAsOf: await latestDataAsOf(db), candidates };\n },\n // Don't cache empty results — the index may still be populating.\n { skipCache: (r) => r.candidates.length === 0 },\n );\n}\n\n// ── evaluate ────────────────────────────────────────────────────────────────\n\nexport async function handleEvaluate(\n db: Database,\n input: { package: string },\n ownerId: string | null = null,\n): Promise<EvaluateOutput | { tracked: false; suggestion: string }> {\n const out = await cached(\n 'eval',\n cacheKey([input.package]),\n async () => {\n // Block-on-first-touch (§4A): a single-package eval awaits the ingest so\n // the first call returns real evidence, not a \"retry shortly\" placeholder.\n const { row, existsOnNpm } = await getOrFetchPackage(db, input.package, {\n blockMs: FIRST_TOUCH_BUDGET_MS,\n requestedByOwnerId: ownerId,\n });\n if (!row) {\n return {\n tracked: false as const,\n suggestion: existsOnNpm\n ? `🎉 Congrats — you're the first to add \"${input.package}\" to lurq's registry! It's being fetched and scored now; retry in a few seconds for the full evidence read.`\n : `\"${input.package}\" was not found on the npm registry. Check the package name.`,\n };\n }\n const evaluated = rowToEvaluate(row);\n const verification = await getLatestVerificationByName(db, row.name);\n return verification\n ? { ...evaluated, buildVerified: toBuildVerified(verification) }\n : evaluated;\n },\n // Don't cache \"not found / not scored yet\" — it may resolve on a later fetch.\n { skipCache: (r) => 'tracked' in r },\n );\n // Re-derive the time-based stale hint, which a cached row would otherwise freeze.\n return 'tracked' in out ? out : refreshStale(out);\n}\n\n// ── compare ─────────────────────────────────────────────────────────────────\n\nexport async function handleCompare(\n db: Database,\n input: { packages: string[] },\n ownerId: string | null = null,\n) {\n // Key on the exact input — the response echoes the caller's own names/order in\n // `missing`, so a normalized key would serve another caller's casing.\n const out = await cached(\n 'cmp',\n cacheKey(input.packages),\n async () => {\n const results = await Promise.all(\n input.packages.map((name) => getOrFetchPackage(db, name, { requestedByOwnerId: ownerId })),\n );\n const rows = results\n .map((r) => r.row)\n .filter((row): row is PackageRow => row !== null)\n .map(rowToEvaluate)\n .sort((a, b) => b.healthScore - a.healthScore);\n const missing = input.packages.filter((name) => !rows.some((r) => r.name === name));\n return {\n dataAsOf: await latestDataAsOf(db),\n rows,\n ...(missing.length\n ? {\n missing,\n note: \"🎉 You're the first to add these to lurq's registry! They're being scored now; retry shortly for the full comparison.\",\n }\n : {}),\n };\n },\n // Don't cache a transient miss (a package that momentarily failed to fetch).\n { skipCache: (r) => Boolean((r as { missing?: string[] }).missing?.length) },\n );\n out.rows = out.rows.map(refreshStale);\n return out;\n}\n\n// ── compat ──────────────────────────────────────────────────────────────────\n\nfunction toBuildVerified(v: VerificationRunRow): BuildVerified {\n return {\n version: v.version,\n installed: v.installed,\n loaded: v.imported,\n driver: v.driver,\n ranAt: v.ranAt ? v.ranAt.toISOString() : '',\n };\n}\n\n/**\n * Whole-architecture compatibility for a set of packages: Tier-1 peer/engine\n * analysis + recorded Tier-2 sandbox conflicts (see compat/check).\n *\n * Optional `versions` pins peer/engine metadata to exact publishes (not just\n * indexed latest). Optional `node` checks each package's engines.node against\n * the target runtime.\n */\nexport async function handleCompat(\n db: Database,\n input: {\n packages: string[];\n versions?: Record<string, string | null | undefined>;\n node?: string | null;\n },\n): Promise<CompatOutput> {\n return checkCompat(db, input.packages, {\n versions: input.versions,\n node: input.node,\n });\n}\n\n// ── verify ──────────────────────────────────────────────────────────────────\n\nexport async function handleVerify(\n db: Database,\n input: { package: string },\n ownerId: string | null = null,\n): Promise<VerifyOutput> {\n const name = input.package;\n const exists = await npmPackageExists(name);\n if (!exists) {\n // A name that doesn't exist but closely mimics a popular one is a squat the\n // agent was about to fall for — surface the suspected target.\n const typo = detectTyposquat(name, typosquatCorpus(await getTopPackageNames(db).catch(() => [])));\n return {\n exists: false,\n tracked: false,\n deprecated: false,\n archived: false,\n latestVersion: null,\n weeklyDownloads: null,\n riskFlags: typo\n ? ['not-found-on-registry', `possible-typosquat-of:${typo.target}`]\n : ['not-found-on-registry'],\n risk: 'high',\n typosquatOf: typo?.target ?? null,\n confidence: null,\n advisoryCount: 0,\n };\n }\n\n const [registry, { row, wasTracked }, popular] = await Promise.all([\n fetchNpmRegistry(name).catch(() => null),\n // Block-on-first-touch (§4A): verify is single-package, so await the ingest\n // for a real confidence/tracked read on the first call.\n getOrFetchPackage(db, name, { blockMs: FIRST_TOUCH_BUDGET_MS, requestedByOwnerId: ownerId }),\n getTopPackageNames(db).catch(() => [] as string[]),\n ]);\n\n // On-demand ingestion is now async, so an untracked package has no row yet.\n // Fetch weekly downloads live (one cheap call) rather than let the risk flags\n // falsely trip 'zero-downloads' on a popular package the index hasn't caught up\n // to. Only pays the extra call on the untracked path.\n const weeklyDownloads = row?.weeklyDownloads ?? (await fetchWeeklyDownloads(name).catch(() => null));\n const advisories = row?.advisories ?? [];\n const advisoryCount = advisories.length;\n const deprecated = Boolean(row?.deprecated || registry?.deprecated);\n const archived = Boolean(row?.archived);\n const brandNew = withinDays(registry?.firstPublishedAt ?? null, 7);\n const lowTrust = weeklyDownloads === null || weeklyDownloads < 1000;\n const installScripts = registry?.hasInstallScripts ?? false;\n const typo = detectTyposquat(name, typosquatCorpus(popular));\n\n const riskFlags: string[] = [];\n if (typo) riskFlags.push(`possible-typosquat-of:${typo.target}`);\n if (weeklyDownloads === null || weeklyDownloads === 0) riskFlags.push('zero-downloads');\n else if (weeklyDownloads < 1000) riskFlags.push('low-downloads');\n if (brandNew) riskFlags.push('published-within-7-days');\n if (registry?.maintainersCount === 1) riskFlags.push('single-maintainer');\n if (installScripts) riskFlags.push('runs-install-scripts');\n if (advisoryCount > 0) riskFlags.push('has-known-advisory');\n if (deprecated) riskFlags.push('deprecated');\n if (archived) riskFlags.push('archived');\n\n const risk = assessRisk({\n flags: riskFlags,\n hasCriticalOrHighAdvisory: hasCriticalOrHighAdvisory(advisories),\n typosquat: Boolean(typo),\n installScripts,\n brandNew,\n lowTrust,\n deprecatedOrArchived: deprecated || archived,\n });\n\n return {\n exists: true,\n tracked: wasTracked,\n deprecated,\n archived,\n latestVersion: registry?.latestVersion ?? row?.latestVersion ?? null,\n weeklyDownloads,\n riskFlags,\n risk,\n typosquatOf: typo?.target ?? null,\n confidence: (row?.confidence as Confidence) ?? null,\n advisoryCount,\n };\n}\n\n// ── usage (§4D — API signature drift) ─────────────────────────────────────────\n\n/** Resolve the version to serve: explicit request → tracked latest → npm latest. */\nasync function resolveVersion(\n db: Database,\n name: string,\n requested?: string,\n): Promise<string | null> {\n if (requested) return requested;\n const row = await getPackageByName(db, name);\n if (row?.latestVersion) return row.latestVersion;\n const reg = await fetchNpmRegistry(name).catch(() => null);\n return reg?.latestVersion ?? null;\n}\n\nexport interface UsageInput {\n package: string;\n version?: string;\n /** The version the agent already knows (e.g. its training-cutoff version) —\n * when given, the response includes the delta the agent must account for. */\n knownVersion?: string;\n}\n\n/**\n * Version-exact API surface + optional migration delta (§4D). The surface is the\n * package's real contract, extracted from the shipped `.d.ts` — no prose lag, no\n * hallucination.\n *\n * Read-through (§4A block-on-first-touch): a stored surface is served as-is, and\n * a miss extracts from the CDN-hosted `.d.ts` within USAGE_EXTRACT_BUDGET_MS and\n * stores it, so the first request for a package populates the cache instead of\n * turning agents away. Past the budget the extraction keeps running in the\n * background and the caller gets the README-fallback note — the same answer the\n * stored-only path gave, so a slow or unreachable CDN only ever costs latency.\n *\n * The TypeScript compiler needed to parse the `.d.ts` is loaded lazily and\n * non-fatally (see usage/extract), which is what lets the public plane call this\n * without `typescript` in its dependency tree: where it isn't installed, every\n * miss simply degrades to the note.\n *\n * `knownVersion` shares ONE deadline with the primary lookup rather than getting\n * its own, so a two-version cold miss can't double the worst-case latency.\n */\nexport async function handleUsage(db: Database, input: UsageInput): Promise<UsageOutput> {\n const version = await resolveVersion(db, input.package, input.version);\n if (!version) {\n return {\n package: input.package,\n version: null,\n surface: null,\n available: false,\n engines: null,\n note: `Could not resolve a version for \"${input.package}\" on npm.`,\n };\n }\n\n // Both halves of the answer at once. The surface comes through the\n // read-through path (a miss extracts within the budget rather than turning the\n // caller away); `engines` is a registry read that shares none of that state,\n // so serialising them would add its latency to every request for nothing.\n const deadline = Date.now() + USAGE_EXTRACT_BUDGET_MS;\n const [surface, compat] = await Promise.all([\n getOrExtractSurface(db, input.package, version, {\n budgetMs: USAGE_EXTRACT_BUDGET_MS,\n }),\n fetchNpmCompatAtVersion(input.package, version).catch(() => null),\n ]);\n const out: UsageOutput = {\n package: input.package,\n version,\n surface,\n available: surface !== null,\n engines: compat?.engines ?? null,\n note: surface\n ? undefined\n : 'No extracted API surface for this version yet; fall back to the README.',\n };\n\n if (input.knownVersion && input.knownVersion !== version && surface) {\n // Whatever the primary lookup left of the budget. Never below zero: a\n // budgetMs of 0 means cache-only, which is the right call once we're out of\n // time — the delta is an enrichment, not the answer.\n const known = await getOrExtractSurface(db, input.package, input.knownVersion, {\n budgetMs: Math.max(0, deadline - Date.now()),\n });\n if (known) out.delta = { ...diffSurface(known, surface), fromVersion: input.knownVersion };\n }\n return out;\n}\n\n// ── report_outcome ────────────────────────────────────────────────────────────\n\nexport interface ReportOutcomeInput {\n package: string;\n accepted: boolean;\n buildSignal?: BuildSignal;\n need?: string;\n}\n\n/**\n * Capture an opt-in recommendation outcome (§3.1). Append-only, no source code —\n * just which package, accepted or not, and a coarse build signal. Not cached (a\n * write), and cheap enough that the per-key rate limiter is the only guard needed.\n * `ownerId` is server-injected from the authenticated key, attributing the\n * outcome to an org so the flywheel accrues per-customer, not to a global pool.\n */\nexport async function handleReportOutcome(\n db: Database,\n input: ReportOutcomeInput,\n ownerId: string | null = null,\n): Promise<{ recorded: true }> {\n await recordOutcome(db, {\n ownerId,\n packageName: input.package,\n accepted: input.accepted,\n buildSignal: input.buildSignal ?? null,\n need: input.need ?? null,\n });\n return { recorded: true };\n}\n","/**\n * Optional `diagram` tool (§12.3.5). Emits a reference-architecture Mermaid\n * diagram for a stack the caller has *already chosen* (package names), using\n * built-in layer patterns. Input is stack-only by design: inferring an\n * architecture from a freeform description is the \"architecture oracle\" behavior\n * that the master spec (§4) and roadmap (§1) declare a non-goal. lurq labels a\n * stack you name; it does not design one. A starting point, not a validator.\n *\n * Honesty over completeness:\n * - A package we can't classify (not in the index AND no category match) is\n * placed in an explicit `Unclassified` bucket — never silently dropped into a\n * default layer. The note lists what couldn't be placed. Partial, not\n * authoritative.\n * - KNOWN LIMITATION — front/back framework ambiguity: the taxonomy has a single\n * `framework` category, so a `framework` package can't be told apart as\n * frontend vs backend from its category alone. BACKEND_FRAMEWORKS is a\n * hand-maintained band-aid that re-routes the common backend frameworks to the\n * Backend layer; it degrades as the ecosystem adds new ones (an unlisted\n * backend framework will be drawn in Presentation). The real fix is a taxonomy\n * change (a distinct backend-framework category or a runtime/target flag on\n * packages), which is out of scope for v1. Documented, not solved.\n */\nimport { inArray } from 'drizzle-orm';\nimport type { Category } from '../core/types';\nimport { inferCategory } from '../search/categoryInference';\nimport type { Database } from '../db/client';\nimport { packages } from '../db/schema';\n\n/** Bucket for packages we cannot place: unknown category, or a category with no\n * real architectural home (e.g. `other`). Rendered, but kept out of the flow. */\nconst UNCLASSIFIED = 'Unclassified';\n\n/** Which architectural layer each category sits in. Categories with no honest\n * architectural home (e.g. `other`) are intentionally absent: layerFor routes\n * anything unmapped to UNCLASSIFIED rather than faking a layer. */\nconst LAYER_OF: Partial<Record<Category, string>> = {\n framework: 'Presentation',\n 'meta-framework': 'Presentation',\n 'ui-component-library': 'Presentation',\n styling: 'Presentation',\n animation: 'Presentation',\n charts: 'Presentation',\n 'state-management': 'Client Logic',\n routing: 'Client Logic',\n forms: 'Client Logic',\n validation: 'Client Logic',\n 'data-fetching': 'Client Logic',\n 'http-client': 'Client Logic',\n i18n: 'Client Logic',\n 'date-time': 'Client Logic',\n utility: 'Client Logic',\n auth: 'Backend',\n orm: 'Data',\n 'database-client': 'Data',\n 'build-tool': 'Tooling',\n bundler: 'Tooling',\n linting: 'Tooling',\n testing: 'Tooling',\n};\n\nconst FLOW_LAYERS = ['Presentation', 'Client Logic', 'Backend', 'Data'];\n\n/** Band-aid for the front/back framework ambiguity (see file header). Category\n * `framework` alone can't distinguish frontend from backend, so these common\n * backend frameworks are re-routed to the Backend layer. Hand-maintained;\n * unlisted backend frameworks will be mis-drawn in Presentation. Not a real fix. */\nconst BACKEND_FRAMEWORKS = new Set([\n 'express',\n 'fastify',\n 'koa',\n 'hono',\n '@nestjs/core',\n '@hapi/hapi',\n]);\n\nexport interface Item {\n label: string;\n /** null = could not be classified (not in index, no category match). */\n category: Category | null;\n}\n\nexport function layerFor(item: Item): string {\n if (!item.category) return UNCLASSIFIED;\n if (item.category === 'framework' && BACKEND_FRAMEWORKS.has(item.label)) return 'Backend';\n return LAYER_OF[item.category] ?? UNCLASSIFIED;\n}\n\nfunction nodeId(label: string, i: number): string {\n return `n${i}_${label.replace(/[^a-zA-Z0-9]/g, '_')}`;\n}\n\nexport function buildMermaid(items: Item[]): string {\n const byLayer = new Map<string, Item[]>();\n for (const item of items) {\n const layer = layerFor(item);\n const list = byLayer.get(layer) ?? [];\n list.push(item);\n byLayer.set(layer, list);\n }\n\n const lines = ['flowchart TD', ' user([User])'];\n const ids = new Map<string, string>(); // label → node id\n let counter = 0;\n const repNode = new Map<string, string>(); // layer → first node id\n\n const emitLayer = (layer: string) => {\n const list = byLayer.get(layer);\n if (!list?.length) return;\n lines.push(` subgraph ${layer.replace(/\\s+/g, '_')}[\"${layer}\"]`);\n for (const item of list) {\n const id = nodeId(item.label, counter++);\n ids.set(item.label, id);\n if (!repNode.has(layer)) repNode.set(layer, id);\n // Unclassified nodes carry no category prefix — we don't claim one we lack.\n const text = layer === UNCLASSIFIED ? item.label : `${item.category}: ${item.label}`;\n lines.push(` ${id}[\"${text}\"]`);\n }\n lines.push(' end');\n };\n\n for (const layer of FLOW_LAYERS) emitLayer(layer);\n emitLayer('Tooling');\n emitLayer(UNCLASSIFIED);\n\n // Connect the flow layers that are present, top to bottom.\n const present = FLOW_LAYERS.filter((l) => byLayer.has(l));\n let prev = 'user';\n for (const layer of present) {\n lines.push(` ${prev} --> ${repNode.get(layer)}`);\n prev = repNode.get(layer)!;\n }\n if (byLayer.has('Data')) lines.push(` ${repNode.get('Data')} --> db[(Database)]`);\n\n return lines.join('\\n');\n}\n\nexport interface DiagramInput {\n stack?: string[];\n}\n\nexport async function handleDiagram(\n db: Database,\n input: DiagramInput,\n): Promise<{ mermaid: string; note: string }> {\n if (!input.stack?.length) {\n return {\n mermaid: 'flowchart TD\\n user([User]) --> app[Application]',\n note: 'Provide a `stack` of package names to diagram. lurq labels a stack you choose; it does not infer an architecture from a description.',\n };\n }\n\n const rows = await db\n .select({ name: packages.name, category: packages.category })\n .from(packages)\n .where(inArray(packages.name, input.stack));\n const known = new Map(rows.map((r) => [r.name, r.category]));\n // inferCategory is best-effort on a bare package name (it was built for NL\n // needs); a miss yields null, not a faked category. No silent 'other'.\n const items: Item[] = input.stack.map((name) => ({\n label: name,\n category: known.get(name) ?? inferCategory(name),\n }));\n\n const unclassified = items.filter((i) => layerFor(i) === UNCLASSIFIED).map((i) => i.label);\n const note = unclassified.length\n ? `Reference pattern derived from the provided stack — partial, not authoritative. Could not place ${unclassified.length} package(s): ${unclassified.join(', ')} (not in lurq's index and no category match) — shown under Unclassified, outside the flow.`\n : 'Reference pattern derived from the provided stack. A labeled starting point, not a validated architecture.';\n\n return { mermaid: buildMermaid(items), note };\n}\n","/**\n * Global stack optimizer.\n *\n * Branch-and-bound over each slot's ranked candidates to find the highest-quality\n * combination that's compatible — the globally optimal coherent stack, not the\n * greedy local one. \"Quality\" is rank-regret: each candidate's index in its slot\n * (0 = the top pick), so the objective is to deviate from the ideal ranking as\n * little as possible while staying conflict-free.\n *\n * The feasibility oracle is instant (Tier-1 peer/engine math + pre-loaded sandbox\n * conflict edges), so the search runs purely in memory. Two prunes keep the tree\n * tiny: feasibility (a partial pick that already conflicts can never un-conflict)\n * and bound (a branch whose regret already exceeds the best feasible stack can't\n * win). Both are provably safe, so within the search budget the result is\n * order-independent — the optimum.\n *\n * A node budget caps pathological search spaces (many slots × many candidates).\n * If it's hit the search returns the best stack found so far and sets\n * `bounded: true` — best-effort, no longer a proof of optimality. At realistic\n * stack sizes the budget is never approached.\n */\nimport type { CompatConflict } from '../core/types';\nimport { resolveArchitectureCompat, type CompatMember } from './peerCompat';\n\nexport interface OptimizeResult {\n /** Chosen candidate index per slot (0 = top pick; higher = more regret). */\n selection: number[];\n conflicts: CompatConflict[];\n /** Sum of chosen indices — how far the stack drifted from the ideal ranking. */\n regret: number;\n /** True if the node budget was exhausted: the result is best-effort, not a\n * proven optimum. False (the normal case) means the search completed. */\n bounded: boolean;\n}\n\n/** Conflicts for a (partial) selection: Tier-1 peer/engine + cached sandbox edges. */\nfunction conflictsFor(members: CompatMember[], sandboxConflicts: Set<string>): CompatConflict[] {\n const out = resolveArchitectureCompat(members);\n for (let i = 0; i < members.length; i++) {\n for (let j = i + 1; j < members.length; j++) {\n const a = members[i]!.name;\n const b = members[j]!.name;\n const key = a <= b ? `${a}|${b}` : `${b}|${a}`;\n if (sandboxConflicts.has(key)) {\n out.push({\n source: 'sandbox',\n packages: [a, b],\n detail: `${a} and ${b} are recorded as incompatible (sandbox)`,\n });\n }\n }\n }\n return out;\n}\n\n/**\n * Pick one candidate per slot to minimise total rank-regret subject to\n * compatibility. `slots[i]` is slot i's candidates in preference order.\n */\nexport function optimizeStack(\n slots: CompatMember[][],\n sandboxConflicts: Set<string> = new Set(),\n): OptimizeResult {\n // Every slot must offer at least one candidate — otherwise the non-null\n // indexing below (`slots[s]![idx]!`) yields undefined and crashes in\n // conflictsFor. Callers pre-filter, but keep the exported fn safe to reuse.\n if (slots.some((s) => s.length === 0)) {\n throw new Error('optimizeStack: every slot must have at least one candidate');\n }\n\n const n = slots.length;\n const budget = 50_000;\n let nodes = 0;\n let exhausted = false;\n\n // Incumbent: top pick of every slot. Only a *feasible* stack bounds the search.\n let bestSelection = new Array<number>(n).fill(0);\n let bestRegret = conflictsFor(\n slots.map((c) => c[0]).filter((m): m is CompatMember => Boolean(m)),\n sandboxConflicts,\n ).length === 0\n ? 0\n : Infinity;\n\n const chosen = new Array<number>(n).fill(0);\n const dfs = (slot: number, regret: number): void => {\n if (nodes++ > budget) {\n exhausted = true;\n return;\n }\n if (regret >= bestRegret) return; // bound prune\n if (slot === n) {\n bestSelection = chosen.slice();\n bestRegret = regret;\n return;\n }\n const candidates = slots[slot]!;\n for (let i = 0; i < candidates.length; i++) {\n chosen[slot] = i;\n // Feasibility prune: a conflict among assigned members is permanent, so a\n // partial pick that already conflicts can never become compatible.\n const assigned = chosen.slice(0, slot + 1).map((idx, s) => slots[s]![idx]!);\n if (conflictsFor(assigned, sandboxConflicts).length === 0) {\n dfs(slot + 1, regret + i);\n }\n if (nodes > budget) {\n exhausted = true;\n return;\n }\n }\n };\n dfs(0, 0);\n\n const members = bestSelection.map((idx, s) => slots[s]![idx]!);\n return {\n selection: bestSelection,\n conflicts: conflictsFor(members, sandboxConflicts),\n regret: bestRegret === Infinity ? bestSelection.reduce((a, b) => a + b, 0) : bestRegret,\n bounded: exhausted,\n };\n}\n","/**\n * `plan` tool — turn a described program into an evidence-scored build plan.\n *\n * This is NOT the \"architecture oracle\" non-goal (master-spec §4): it does not\n * invent an architecture from a one-line prompt. It takes a program the caller\n * has *already described in detail* (a spec/README) — or a pre-decomposed list\n * of needs — and runs lurq's normal `recommend` engine slot-by-slot, returning\n * real packages from the index with their scores. lurq still \"supplies building\n * blocks slot-by-slot; the agent assembles the architecture\" (§1.3). The rich\n * input is what removes the guesswork the spec warned against; the §20 roadmap\n * item (\"architecture recommendation … once data can ground it\") is honored\n * because every recommendation is grounded in the scored index.\n *\n * Decomposition (document → needs) follows Option C:\n * - a caller-supplied `needs[]` is used as-is (the agent already read the doc — the\n * fast, zero-LLM path, and the cleanest companion-model division of labor); else\n * - a raw `document` is decomposed server-side: by the summary LLM when a key is\n * configured, otherwise by a transparent heading/keyword heuristic. The heuristic\n * is honest-but-coarse, and the response note says so.\n */\nimport { createHash } from 'node:crypto';\nimport { inArray } from 'drizzle-orm';\nimport { getConfig } from '../core/config';\nimport { httpRequest } from '../core/http';\nimport { checkCompat } from '../compat/check';\nimport { assembleMembers } from '../compat/members';\nimport { optimizeStack } from '../compat/optimize';\nimport type { CompatMember } from '../compat/peerCompat';\nimport { getCompatEdges } from '../db/compat';\nimport { logger } from '../core/logger';\nimport {\n isCategory,\n type Candidate,\n type Category,\n type CompatConflict,\n type CompatOutput,\n} from '../core/types';\nimport type { Database } from '../db/client';\nimport { packages } from '../db/schema';\nimport { inferCategory } from '../search/categoryInference';\nimport { recommend } from '../search/recommend';\nimport { getOrFetchPackage } from '../pipeline/single';\nimport type { PackageRow } from '../db/schema';\nimport { buildMermaid, layerFor } from './diagram';\nimport { latestDataAsOf } from './handlers';\n\n/** A pinned package the user chose, resolved to a fixed single-candidate slot. */\nfunction packageToCandidate(row: PackageRow): Candidate {\n return {\n name: row.name,\n category: row.category,\n healthScore: row.healthScore ?? 0,\n qualityScore: row.qualityScore,\n confidence: row.confidence ?? 'unproven',\n why: 'pinned by you',\n latestVersion: row.latestVersion,\n weeklyDownloads: row.weeklyDownloads,\n lastReleaseAt: row.lastReleaseAt ? row.lastReleaseAt.toISOString() : null,\n repoUrl: row.repoUrl,\n };\n}\n\n/** Resolve user-pinned packages into fixed slots (one candidate, no alternatives)\n * so the optimizer routes the recommended slots around them. Unresolvable pins\n * (not on npm) are returned so the caller can report them. */\nexport async function resolvePins(\n db: Database,\n using: string[] | undefined,\n recommendedNames: Set<string>,\n requestedByOwnerId: string | null = null,\n): Promise<{ slots: PlanSlot[]; unresolved: string[] }> {\n const slots: PlanSlot[] = [];\n const unresolved: string[] = [];\n // Dedupe, and skip a pin the recommender already picked (avoid double slots).\n for (const name of new Set(using ?? [])) {\n if (recommendedNames.has(name)) continue;\n const { row } = await getOrFetchPackage(db, name, { requestedByOwnerId });\n if (!row) {\n unresolved.push(name);\n continue;\n }\n slots.push({\n need: `using ${name}`,\n category: row.category,\n layer: layerFor({ label: name, category: row.category }),\n recommended: packageToCandidate(row),\n alternatives: [], // fixed: the user chose this, so it never gets swapped\n note: 'pinned by you',\n });\n }\n return { slots, unresolved };\n}\n\n/** A single component/slot to recommend a package for. */\nexport interface PlanNeed {\n need: string;\n category?: Category;\n}\n\nexport interface PlanInput {\n /** Detailed description of the program (spec/README). lurq decomposes it. */\n document?: string;\n /** Pre-decomposed needs (e.g. the calling agent already read the doc). */\n needs?: PlanNeed[];\n /** Packages the user has already chosen. Pinned as fixed slots; lurq\n * recommends only the remaining needs and plans the stack around these. */\n using?: string[];\n /** Ranking bias. 'speed' prefers the lightest-bundle option among the top\n * candidates for a slot; 'balanced' (default) uses the normal ranking. */\n optimize?: 'speed' | 'balanced';\n}\n\nexport interface PlanSlot {\n need: string;\n category: Category | null;\n layer: string;\n recommended: Candidate | null;\n alternatives: Candidate[];\n note?: string;\n /** Picked packages this slot's pick still conflicts with, if it couldn't be\n * auto-resolved with the available alternatives (residual conflict). */\n conflictsWith?: string[];\n /** If plan swapped this slot's pick to keep the stack compatible, the name of\n * the original (higher-ranked) pick it replaced. */\n swappedFrom?: string;\n}\n\nexport interface PlanOutput {\n dataAsOf: string;\n optimize: 'speed' | 'balanced';\n /** Where the slots came from: caller-supplied needs, lurq's LLM, or the heuristic. */\n source: 'needs' | 'llm' | 'heuristic';\n /** The framework/meta-framework that anchored the plan, if one was found. Every\n * other slot was recommended in this ecosystem's context. null = no framework\n * in the spec, so slots were recommended independently. */\n framework: string | null;\n slots: PlanSlot[];\n /** Needs for which no tracked package matched. */\n unmatched: string[];\n mermaid: string;\n note: string;\n /** Whole-stack compatibility of the picked packages (peer-deps/engines +\n * recorded sandbox conflicts). Evidence-backed, with name@version of each\n * member; null if the check couldn't run. */\n compatibility: CompatOutput | null;\n}\n\n/** Candidates to surface per slot: the pick plus a couple of alternatives. */\nconst PER_SLOT = 3;\n/** Cap on slots so a huge document can't fan out into hundreds of queries. */\nconst MAX_SLOTS = 24;\n\nexport async function handlePlan(\n db: Database,\n input: PlanInput,\n ownerId: string | null = null,\n): Promise<PlanOutput | { note: string }> {\n const optimize = input.optimize ?? 'balanced';\n\n const decomposed = input.needs?.length\n ? { needs: dedupeNeeds(input.needs), source: 'needs' as const }\n : input.document?.trim()\n ? await decompose(input.document)\n : null;\n\n const hasPins = Boolean(input.using?.length);\n if ((!decomposed || decomposed.needs.length === 0) && !hasPins) {\n return {\n note: 'Provide a `document` (a detailed description of your program), a `needs` array, or a `using` list of packages you have already chosen. lurq recommends evidence-scored packages per component — it does not invent an architecture from a bare prompt.',\n };\n }\n\n const needs = (decomposed?.needs ?? []).slice(0, MAX_SLOTS);\n const source = decomposed?.source ?? 'needs';\n\n const safeRecommend = (need: string, category: Category | undefined) =>\n recommend(db, { need, category, limit: PER_SLOT }).catch((err) => {\n logger.warn(`plan: recommend failed for \"${need}\": ${(err as Error).message}`);\n return [] as Candidate[];\n });\n // Effective category per slot — the decomposition hint, else inferred from the\n // ORIGINAL need text (before any framework context is appended, so the word we\n // inject below can never misclassify the slot).\n const effCat = (n: PlanNeed): Category | undefined => n.category ?? inferCategory(n.need) ?? undefined;\n\n // Detect the framework family from the WHOLE spec (document + need texts), so the\n // plan stays coherent even when decomposition doesn't emit a framework slot.\n // This drives the coherence re-rank below.\n const anchorFamily = familyOf(`${input.document ?? ''} ${needs.map((n) => n.need).join(' ')}`);\n\n // Phase 1: if a framework/meta-framework component exists, resolve it first to\n // name the concrete package (a meta-framework like Next wins over a bare\n // framework); otherwise the detected family is the context word.\n const metaIdx = needs.findIndex((n) => effCat(n) === 'meta-framework');\n const anchorIdx = metaIdx >= 0 ? metaIdx : needs.findIndex((n) => effCat(n) === 'framework');\n\n const recs: Candidate[][] = new Array(needs.length);\n let framework: string | null = anchorFamily;\n if (anchorIdx >= 0) {\n recs[anchorIdx] = await safeRecommend(needs[anchorIdx]!.need, effCat(needs[anchorIdx]!));\n framework = recs[anchorIdx]![0]?.name ?? anchorFamily;\n }\n\n // Phase 2: recommend the remaining slots concurrently, weaving the chosen\n // framework into each query so sibling libraries stay in-ecosystem. The slot's\n // category is passed explicitly, so the injected framework word only sways\n // relevance — never the category filter. Framework-agnostic slots (e.g.\n // date/time) are unaffected since their candidates don't mention the framework.\n const [, dataAsOf] = await Promise.all([\n Promise.all(\n needs.map(async (n, i) => {\n if (i === anchorIdx) return;\n const need = framework ? `${n.need} (for a ${framework} app)` : n.need;\n recs[i] = await safeRecommend(need, effCat(n));\n }),\n ),\n latestDataAsOf(db),\n ]);\n\n // Re-rank each slot's candidates: keep the architecture coherent (cross-\n // framework bindings last), then — for 'speed' — prefer the lightest bundle,\n // otherwise preserve recommend's relevance order. One batched lookup keeps\n // `recommend` itself untouched.\n const bundleByName = optimize === 'speed' ? await bundleSizes(db, recs.flat()) : new Map<string, number>();\n\n // Adjacent needs often retrieve the same package (an \"auth\" slot and a\n // \"session\" slot both landing on the same library). Emitting it twice reads as\n // \"install this twice\" and double-counts it in the compat check, so a slot\n // whose top pick is already taken falls through to its best free alternative.\n const taken = new Set<string>();\n const recSlots: PlanSlot[] = needs.map((n, i) => {\n const candidates = orderCandidates(recs[i]!, anchorFamily, optimize, bundleByName);\n const free = candidates.filter((c) => !taken.has(c.name));\n const recommended = free[0] ?? null;\n if (recommended) taken.add(recommended.name);\n const category = n.category ?? recommended?.category ?? inferCategory(n.need);\n return {\n need: n.need,\n category,\n layer: layerFor({ label: recommended?.name ?? n.need, category }),\n recommended,\n alternatives: free.slice(1),\n note: recommended\n ? undefined\n : candidates.length\n ? 'every match for this need is already in the stack for another slot'\n : 'no tracked package matched this need yet',\n };\n });\n\n // Pin the user's chosen packages as fixed slots, then plan the rest around\n // them. Pins lead so they anchor the stack; the optimizer can only move the\n // recommended slots, so it routes them to stay compatible with the pins.\n const recommendedNames = new Set(\n recSlots.map((s) => s.recommended?.name).filter((n): n is string => Boolean(n)),\n );\n const { slots: pinnedSlots, unresolved: unresolvedPins } = await resolvePins(\n db,\n input.using,\n recommendedNames,\n ownerId,\n );\n const slots = [...pinnedSlots, ...recSlots];\n\n // Auto-resolve compatibility: actually make the picked stack coherent by\n // swapping a conflicting slot's pick for an alternative that resolves it.\n // Runs before the diagram/output so everything below reflects the final stack.\n const compatibility = await resolveCompat(db, slots);\n\n const unmatched = [\n ...slots.filter((s) => !s.recommended).map((s) => s.need),\n ...unresolvedPins.map((n) => `${n} (pinned, but not found on npm)`),\n ];\n const mermaid = buildMermaid(\n slots\n .filter((s) => s.recommended)\n .map((s) => ({ label: s.recommended!.name, category: s.category })),\n );\n\n return {\n dataAsOf,\n optimize,\n source,\n framework,\n slots,\n unmatched,\n mermaid,\n note: planNote(source, unmatched.length, optimize, framework),\n compatibility,\n };\n}\n\n/** Map each slot (by need) to the other picked packages its pick conflicts with. */\nexport function flagSlotConflicts(\n picks: { need: string; name: string | null }[],\n conflicts: CompatConflict[],\n): Map<string, string[]> {\n const out = new Map<string, string[]>();\n for (const c of conflicts) {\n for (const p of picks) {\n if (p.name && c.packages.includes(p.name)) {\n const others = c.packages.filter((n) => n !== p.name);\n out.set(p.need, [...new Set([...(out.get(p.need) ?? []), ...others])]);\n }\n }\n }\n return out;\n}\n\nconst NO_META = (c: Candidate): CompatMember => ({\n name: c.name,\n version: c.latestVersion,\n peerDependencies: null,\n peerDependenciesMeta: null,\n engines: null,\n});\n\n/**\n * Make the picked stack compatible by *globally optimising* the slot choices:\n * pre-load every candidate's metadata + cached sandbox edges once, then run a\n * branch-and-bound that picks the highest-quality (lowest rank-regret) compatible\n * combination. The chosen alternative is promoted to `recommended` (original\n * demoted, recorded via `swappedFrom`); residual conflicts are flagged per slot.\n * The search is pure/in-memory; only the final report re-reads the DB.\n * Best-effort — never throws.\n */\nasync function resolveCompat(db: Database, slots: PlanSlot[]): Promise<CompatOutput | null> {\n const eligible = slots.filter((s) => s.recommended);\n if (eligible.length < 2) return null;\n\n try {\n // One pass: metadata for every candidate across all slots → pure search.\n const allNames = [\n ...new Set(eligible.flatMap((s) => [s.recommended!, ...s.alternatives].map((c) => c.name))),\n ];\n const [{ members }, edges] = await Promise.all([\n assembleMembers(db, allNames),\n getCompatEdges(db, allNames),\n ]);\n const metaByName = new Map(members.map((m) => [m.name, m]));\n const sandboxConflicts = new Set(\n edges.filter((e) => e.status === 'conflict').map((e) => `${e.packageA}|${e.packageB}`),\n );\n const slotCandidates = eligible.map((s) =>\n [s.recommended!, ...s.alternatives].map((c) => metaByName.get(c.name) ?? NO_META(c)),\n );\n\n const { selection } = optimizeStack(slotCandidates, sandboxConflicts);\n\n // Apply the optimal selection: promote the chosen candidate per slot.\n eligible.forEach((s, i) => {\n const idx = selection[i] ?? 0;\n if (idx <= 0) return;\n const all = [s.recommended!, ...s.alternatives];\n const chosen = all[idx];\n if (!chosen) return;\n s.recommended = chosen;\n s.alternatives = all.filter((c) => c.name !== chosen.name);\n s.swappedFrom = all[0]!.name;\n });\n } catch (err) {\n logger.warn(`plan: compat optimization failed: ${String(err)}`);\n }\n\n // Authoritative report on the final picks, and flag any residual conflicts.\n const compat = await checkCompat(\n db,\n eligible.map((s) => s.recommended!.name),\n ).catch(() => null);\n if (compat) {\n const flags = flagSlotConflicts(\n slots.map((s) => ({ need: s.need, name: s.recommended?.name ?? null })),\n compat.conflicts,\n );\n for (const s of slots) {\n const cw = flags.get(s.need);\n s.conflictsWith = cw?.length ? cw : undefined;\n }\n }\n return compat;\n}\n\nfunction planNote(\n source: PlanOutput['source'],\n unmatched: number,\n optimize: string,\n framework: string | null,\n): string {\n const base =\n source === 'heuristic'\n ? 'Components were extracted from your document with a keyword heuristic (no summary LLM configured) — coarse; pass a `needs` array or set SUMMARY_API_KEY for sharper decomposition.'\n : source === 'llm'\n ? 'Components were extracted from your document by the summary model.'\n : 'Components taken from the supplied needs.';\n const grounding =\n ' Each package is recommended from lurq’s scored index — a labeled, evidence-backed starting point, not a validated architecture.';\n const ctx = framework\n ? ` Anchored to the ${framework} ecosystem so sibling libraries stay coherent across the stack.`\n : '';\n const tail = unmatched ? ` ${unmatched} need(s) had no tracked match (listed in \\`unmatched\\`).` : '';\n const opt = optimize === 'speed' ? ' Ranking favored the lightest-bundle option per slot.' : '';\n return base + grounding + ctx + opt + tail;\n}\n\n/** Merge duplicate needs (same text), keeping the first category hint seen. */\nfunction dedupeNeeds(needs: PlanNeed[]): PlanNeed[] {\n const seen = new Map<string, PlanNeed>();\n for (const n of needs) {\n const key = n.need.trim().toLowerCase();\n if (!key) continue;\n if (!seen.has(key)) seen.set(key, { need: n.need.trim(), category: n.category });\n }\n return [...seen.values()];\n}\n\n/** The framework \"family\" a package name belongs to (by naming convention), or\n * null if framework-agnostic. Lets the plan stay in one ecosystem — never\n * surface a different framework's binding (e.g. vue-router in a React app). */\nconst FAMILY_TOKENS: { family: string; re: RegExp }[] = [\n { family: 'react', re: /\\breact\\b|preact/ },\n { family: 'vue', re: /\\bvue\\b|nuxt/ },\n { family: 'angular', re: /angular/ },\n { family: 'svelte', re: /svelte/ },\n { family: 'solid', re: /\\bsolid(-?js)?\\b/ },\n];\n\nexport function familyOf(name: string): string | null {\n const n = name.toLowerCase();\n for (const f of FAMILY_TOKENS) if (f.re.test(n)) return f.family;\n return null;\n}\n\n/**\n * Order a slot's candidates: in-ecosystem first and cross-framework bindings\n * last (when an anchor framework was found), then — for 'speed' — lightest\n * bundle, otherwise preserving recommend's relevance ranking (V8's sort is\n * stable, so equal-key candidates keep their incoming order).\n */\nexport function orderCandidates(\n cands: Candidate[],\n anchorFamily: string | null,\n optimize: 'speed' | 'balanced',\n bundleByName: Map<string, number>,\n): Candidate[] {\n // +1 same ecosystem, −1 a competing framework, 0 framework-agnostic.\n const coherence = (c: Candidate): number => {\n const fam = familyOf(c.name);\n if (!fam) return 0;\n return fam === anchorFamily ? 1 : -1;\n };\n return [...cands].sort((a, b) => {\n if (anchorFamily) {\n const d = coherence(b) - coherence(a);\n if (d) return d;\n }\n if (optimize === 'speed') {\n return (bundleByName.get(a.name) ?? Infinity) - (bundleByName.get(b.name) ?? Infinity);\n }\n return 0;\n });\n}\n\n/** Batched bundle-size lookup for the 'speed' re-rank. */\nasync function bundleSizes(db: Database, candidates: Candidate[]): Promise<Map<string, number>> {\n const names = [...new Set(candidates.map((c) => c.name))];\n if (names.length === 0) return new Map();\n const rows = await db\n .select({ name: packages.name, bundle: packages.bundleMinGzipKb })\n .from(packages)\n .where(inArray(packages.name, names));\n return new Map(rows.filter((r) => r.bundle != null).map((r) => [r.name, r.bundle as number]));\n}\n\n// ── Decomposition (document → needs) ─────────────────────────────────────────\n\nasync function decompose(document: string): Promise<{ needs: PlanNeed[]; source: 'llm' | 'heuristic' }> {\n const config = getConfig();\n if (config.SUMMARY_PROVIDER === 'openai' && config.SUMMARY_API_KEY) {\n const llm = await decomposeWithLlm(\n document,\n config.SUMMARY_API_KEY,\n config.SUMMARY_MODEL,\n config.SUMMARY_BASE_URL,\n ).catch((err) => {\n logger.warn(`plan: LLM decomposition failed, using heuristic: ${(err as Error).message}`);\n return null;\n });\n if (llm?.length) return { needs: dedupeNeeds(llm), source: 'llm' };\n }\n return { needs: decomposeHeuristic(document), source: 'heuristic' };\n}\n\nconst DECOMPOSE_SYSTEM =\n 'You break a software project description into the distinct technical components that each need a library. ' +\n 'Return ONLY components the project actually requires, grounded in the description. Respond with a JSON object.';\n\nasync function decomposeWithLlm(\n document: string,\n apiKey: string,\n model: string,\n baseUrl: string,\n): Promise<PlanNeed[]> {\n const prompt = [\n 'Project description:',\n document.slice(0, 8000),\n '',\n 'Return JSON: { \"needs\": [ { \"need\": \"<one phrase describing a component that needs a library>\", \"category\": \"<optional taxonomy hint or empty>\" } ] }.',\n 'One entry per distinct component (e.g. routing, validation, ORM, HTTP client). Omit anything not implied by the description.',\n ].join('\\n');\n const { data } = await httpRequest<any>(`${baseUrl.replace(/\\/$/, '')}/chat/completions`, {\n host: new URL(baseUrl).host,\n method: 'POST',\n ttlMs: 24 * 60 * 60 * 1000,\n // Hash the FULL document — length + a 64-char prefix collide for same-length\n // edits or shared templated headers, which would serve a stale decomposition.\n cacheKey: `openai-plan ${model} ${createHash('sha1').update(document).digest('hex')}`,\n headers: { Authorization: `Bearer ${apiKey}`, 'Content-Type': 'application/json' },\n body: JSON.stringify({\n model,\n messages: [\n { role: 'system', content: DECOMPOSE_SYSTEM },\n { role: 'user', content: prompt },\n ],\n response_format: { type: 'json_object' },\n temperature: 0.2,\n }),\n });\n const content = data?.choices?.[0]?.message?.content;\n const parsed = content ? JSON.parse(content) : {};\n const raw = Array.isArray(parsed?.needs) ? parsed.needs : [];\n return raw\n .map((n: any): PlanNeed | null => {\n const need = typeof n?.need === 'string' ? n.need.trim() : '';\n if (!need) return null;\n const cat = typeof n?.category === 'string' && isCategory(n.category) ? n.category : undefined;\n return { need, category: cat };\n })\n .filter(Boolean) as PlanNeed[];\n}\n\n/**\n * Heuristic fallback: scan the document line-by-line, infer a category per line,\n * and emit one need per distinct category (first matching line as the phrase).\n * Coarse by design — it only surfaces components whose category lurq can name.\n */\nexport function decomposeHeuristic(document: string): PlanNeed[] {\n const byCategory = new Map<Category, string>();\n for (const rawLine of document.split('\\n')) {\n // Strip markdown headings/blockquotes/bullets, then an ordered-list \"12. \"\n // marker — but NOT bare leading digits, so \"2FA auth\" stays intact.\n const line = rawLine.replace(/^[#>*\\-\\s]+/, '').replace(/^\\d+\\.\\s+/, '').trim();\n if (line.length < 3) continue;\n const category = inferCategory(line);\n if (category && !byCategory.has(category)) {\n byCategory.set(category, line.slice(0, 120));\n }\n }\n return [...byCategory.entries()].map(([category, need]) => ({ need, category }));\n}\n","/**\n * Minimal per-tool metrics for the hosted MCP path — Prometheus text format, no\n * dependency. Counts calls, errors, and cumulative latency per tool so an\n * operator can see usage and error rates without wiring up an APM. Process-local\n * (a module singleton): each server instance exposes its own counters at\n * `/metrics`, which is exactly what a Prometheus scrape expects.\n */\ninterface Stat {\n calls: number;\n errors: number;\n totalMs: number;\n}\n\nconst stats = new Map<string, Stat>();\n\n/** Record one tool invocation. `ok=false` marks a handler that threw. */\nexport function recordToolCall(tool: string, ok: boolean, ms: number): void {\n const s = stats.get(tool) ?? { calls: 0, errors: 0, totalMs: 0 };\n s.calls += 1;\n if (!ok) s.errors += 1;\n s.totalMs += ms;\n stats.set(tool, s);\n}\n\n/** Time a tool handler and record the outcome, re-throwing any error unchanged. */\nexport async function timed<T>(tool: string, fn: () => Promise<T>): Promise<T> {\n const start = Date.now();\n let ok = false;\n try {\n const result = await fn();\n ok = true;\n return result;\n } finally {\n recordToolCall(tool, ok, Date.now() - start);\n }\n}\n\n/** Render current counters in Prometheus exposition format. */\nexport function renderPrometheus(): string {\n const lines = [\n '# HELP lurq_tool_calls_total Total MCP tool invocations.',\n '# TYPE lurq_tool_calls_total counter',\n '# HELP lurq_tool_errors_total MCP tool invocations that threw.',\n '# TYPE lurq_tool_errors_total counter',\n '# HELP lurq_tool_duration_ms_total Cumulative tool handler time in ms.',\n '# TYPE lurq_tool_duration_ms_total counter',\n ];\n for (const [tool, s] of stats) {\n const label = `{tool=\"${tool}\"}`;\n lines.push(`lurq_tool_calls_total${label} ${s.calls}`);\n lines.push(`lurq_tool_errors_total${label} ${s.errors}`);\n lines.push(`lurq_tool_duration_ms_total${label} ${s.totalMs}`);\n }\n return lines.join('\\n') + '\\n';\n}\n\n/** Test-only: clear all counters. */\nexport function resetMetrics(): void {\n stats.clear();\n}\n","/**\n * Compact MCP responses (§12.4). Every tool response is JSON injected straight\n * into the calling agent's context window, so each `\"field\":null` or empty\n * container is tokens the user pays for on every call — and noise that dilutes\n * the agent's attention. `compact()` recursively drops null/undefined values,\n * empty arrays, and objects that become empty, keeping only signal.\n *\n * Deliberately KEEPS `false` and `0`: `deprecated:false` and `weeklyDownloads:0`\n * carry meaning an agent shouldn't have to infer from a field's absence. Only\n * genuinely-absent data (null/undefined/empty) is stripped.\n */\n/** True only for a *plain* object with no keys. A Date has no own keys, so\n * without the instanceof guard every date field would be dropped as \"empty\". */\nfunction isEmptyObject(value: unknown): boolean {\n return (\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(value) &&\n !(value instanceof Date) &&\n Object.keys(value).length === 0\n );\n}\n\nexport function compact<T>(value: T): T {\n // A Date is an object with no own keys, so the generic object walk below would\n // see `{}` and drop the field entirely. Handlers stringify their dates today;\n // this keeps the first one that forgets from silently losing data.\n if (value instanceof Date) return value;\n if (Array.isArray(value)) {\n return value\n .map((v) => compact(v))\n .filter((v) => v !== null && v !== undefined) as unknown as T;\n }\n if (value !== null && typeof value === 'object') {\n const out: Record<string, unknown> = {};\n for (const [key, raw] of Object.entries(value as Record<string, unknown>)) {\n if (raw === null || raw === undefined) continue;\n const cleaned = compact(raw);\n if (cleaned === null || cleaned === undefined) continue;\n if (Array.isArray(cleaned) && cleaned.length === 0) continue;\n if (isEmptyObject(cleaned)) continue;\n out[key] = cleaned;\n }\n return out as T;\n }\n return value;\n}\n","/**\n * The canonical descriptions for the three tools the benchmark's agent arms\n * expose, in one place because they were being written twice.\n *\n * server.ts is what real agents see. The benchmark participants each hand-wrote\n * their own paraphrase of the same three tools — once per vendor schema shape —\n * and those paraphrases drifted well below the originals. `compat` is the clear\n * case: production says \"across the whole set ... call before committing to a\n * multi-package stack\", the benchmark's copy said only \"check if packages are\n * compatible\", and the measured consequence was the model calling `compat` four\n * separate times on a two-need case instead of once with the whole set. Every\n * one of those extra turns resends the entire accumulated context, so a weaker\n * sentence here was costing real tokens and real latency.\n *\n * That made the benchmark measure a worse lurq than the one that ships — the\n * arm meant to show what the tools are worth was describing them badly. Hence\n * one source: a description improved for agents is now improved for the number\n * we publish about them, and neither can quietly fall behind the other.\n *\n * Only these three are extracted, not all nine tools on the server. The other\n * six have exactly one caller and gain nothing from the indirection.\n */\n\nexport const PLAN_DESCRIPTION =\n 'Turn a detailed program description (spec/README) or a list of component needs into an evidence-scored build plan: a real, lurq-scored package recommended per component, plus a Mermaid roadmap other agents can parse. Recommends building blocks slot-by-slot from the index — it does not invent an architecture from a bare prompt.';\n\nexport const VERIFY_DESCRIPTION =\n 'Confirm an npm package is real, healthy, and not risky before installing — guards against hallucinated or typosquatted dependency names. Checks the live registry.';\n\nexport const COMPAT_DESCRIPTION =\n 'Check whether a set of packages forms a coherent stack: peer-dependency and engine-range compatibility across the whole set (instant, from declared metadata), plus any recorded sandbox-verified conflicts. Returns the exact clashing constraints. Read-only — does not run installs. Call before committing to a multi-package stack.';\n\n/**\n * The `packages` parameter carries the batching instruction, not just the\n * bound. A model told the argument is a set checks the set; a model told only\n * that it is an array checks pairs, one round trip at a time, which is what it\n * actually did before this said otherwise.\n */\nexport const COMPAT_PACKAGES_DESCRIPTION =\n 'The full candidate stack to check together, 2–8 npm package names. Pass every package in one call — checking pairs separately misses conflicts that only appear across the whole set, and costs a round trip each.';\n\nexport const COMPAT_VERSIONS_DESCRIPTION =\n 'Optional exact versions keyed by package name (use when not checking latest)';\n\nexport const COMPAT_NODE_DESCRIPTION =\n 'Optional target Node runtime (e.g. \"20\" or \"20.20.2\") for engines.node checks';\n","/**\n * Dashboard usage counters (dashboard v1 phase 2). Per-owner, per-day, per-tool\n * call counts. Display-only, not a billing ledger — the write is a fire-and-forget\n * UPSERT that swallows its own errors, so a counter hiccup can never fail a tool\n * call (same idiom as stampLastUsed). Reads power the dashboard `/usage` view.\n */\nimport { and, desc, eq, gte, sql } from 'drizzle-orm';\nimport type { Database } from './client';\nimport { ownerUsageDaily } from './schema';\n\nexport interface UsagePoint {\n /** UTC day, 'YYYY-MM-DD'. */\n date: string;\n count: number;\n}\n\n/**\n * First day of a trailing `days`-day window, inclusive of today.\n *\n * The `::int` cast is load-bearing, not decoration. postgres.js's `inferType`\n * returns 0 (unspecified) for a plain JS number, so an uncast `CURRENT_DATE - $n`\n * lets Postgres resolve the operator as `date - date -> integer`; the surrounding\n * comparison then becomes `date >= integer` and the query dies with\n * `operator does not exist`. Shared by both readers so the cast can't drift.\n */\nexport function windowStart(days: number) {\n return sql`CURRENT_DATE - (${days}::int - 1)`;\n}\n\n/**\n * Increment today's counter for (owner, tool). No-op when ownerId is null/empty\n * (operator-issued keys with no dashboard account). Fire-and-forget: an undercount\n * on a transient DB failure is acceptable for a display-only counter.\n */\nexport async function recordUsage(\n db: Database,\n ownerId: string | null | undefined,\n tool: string,\n): Promise<void> {\n if (!ownerId) return;\n try {\n await db\n .insert(ownerUsageDaily)\n .values({ ownerId, date: sql`CURRENT_DATE`, tool, count: 1 })\n .onConflictDoUpdate({\n target: [ownerUsageDaily.ownerId, ownerUsageDaily.date, ownerUsageDaily.tool],\n set: { count: sql`${ownerUsageDaily.count} + 1` },\n });\n } catch {\n // Display-only counter: never let a usage write break the request.\n }\n}\n\n/**\n * Trailing-`days`-window daily totals (summed across tools), plus today's total.\n *\n * The window is generated DB-side with `generate_series` and LEFT JOINed, so the\n * result is **gap-free**: every day in the window is present, zero-count days\n * included. Callers can therefore plot it on a uniform time axis — a series that\n * only carried days-with-traffic would render equal-width bars for unequal time\n * spans and misstate the trend.\n */\nexport async function getUsageSummary(\n db: Database,\n ownerId: string,\n days: number,\n): Promise<{ today: number; series: UsagePoint[] }> {\n const rows = (await db.execute<{ date: string; count: number }>(sql`\n select\n to_char(d, 'YYYY-MM-DD') as date,\n coalesce(sum(u.count), 0)::int as count\n from generate_series(${windowStart(days)}, CURRENT_DATE, interval '1 day') as d\n left join ${ownerUsageDaily} u\n on u.date = d::date and u.owner_id = ${ownerId}\n group by d\n order by d\n `)) as unknown as { date: string; count: number }[];\n\n const series: UsagePoint[] = rows.map((r) => ({ date: String(r.date), count: Number(r.count) }));\n // The series ends at the database's CURRENT_DATE, which is the same clock the\n // counters are written against. Deriving \"today\" from the process's UTC date\n // instead would read 0 on any server not running in UTC.\n const today = series.at(-1)?.count ?? 0;\n return { today, series };\n}\n\n/** Trailing-`days`-window totals grouped by tool, busiest first. */\nexport async function getUsageByTool(\n db: Database,\n ownerId: string,\n days: number,\n): Promise<{ tool: string; count: number }[]> {\n const rows = await db\n .select({\n tool: ownerUsageDaily.tool,\n count: sql<number>`sum(${ownerUsageDaily.count})::int`,\n })\n .from(ownerUsageDaily)\n .where(\n and(\n eq(ownerUsageDaily.ownerId, ownerId),\n gte(ownerUsageDaily.date, windowStart(days)),\n ),\n )\n .groupBy(ownerUsageDaily.tool)\n .orderBy(desc(sql`sum(${ownerUsageDaily.count})`));\n\n return rows.map((r) => ({ tool: r.tool, count: Number(r.count) }));\n}\n","/**\n * MCP server (§12). Exposes recommend / evaluate / compare / verify over stdio.\n * Inputs are validated with zod; outputs are compact JSON text (§12.4).\n */\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { z } from 'zod';\nimport { SERVER_NAME, VERSION } from '../core/constants';\nimport { CATEGORIES, type Category } from '../core/types';\nimport { createDb } from '../db/client';\nimport { logger } from '../core/logger';\nimport { handleDiffSurface, handleResolveSurface } from './surfaceHandlers';\nimport {\n handleCompare,\n handleCompat,\n handleEvaluate,\n handleRecommend,\n handleReportOutcome,\n handleUsage,\n handleVerify,\n} from './handlers';\nimport { handleDiagram } from './diagram';\nimport { handlePlan } from './plan';\nimport { timed } from './metrics';\nimport { compact } from './compact';\nimport {\n COMPAT_DESCRIPTION,\n COMPAT_NODE_DESCRIPTION,\n COMPAT_PACKAGES_DESCRIPTION,\n COMPAT_VERSIONS_DESCRIPTION,\n PLAN_DESCRIPTION,\n VERIFY_DESCRIPTION,\n} from './toolDescriptions';\nimport { recordUsage } from '../db/usage';\n\nconst categoryEnum = z.enum(CATEGORIES as unknown as [Category, ...Category[]]);\nconst confidenceEnum = z.enum(['proven', 'emerging', 'promising', 'unproven']);\n\n// Validate package names at the trust boundary. A name flows straight into a\n// registry URL (`registry.npmjs.org/${name}`) and the response cache key, so\n// reject anything that isn't a legal npm name: this blocks path/query\n// injection (`/`, `?`, `#`, `%`), whitespace, and control characters. Case is\n// permitted for legacy packages; the char class is what closes the hole.\nexport const npmName = z\n .string()\n .trim()\n .min(1)\n .max(214)\n .regex(/^(?:@[a-z0-9-][a-z0-9-._]*\\/)?[a-z0-9-][a-z0-9-._]*$/i, 'Invalid npm package name');\n\n// No `runtime` filter: lurq stores no per-package runtime signal, so the field\n// was accepted and silently ignored — an agent asking for browser-only packages\n// got the unfiltered list back. Restore it when ingestion records the manifest's\n// `browser` field / `exports` browser condition, not before.\nconst constraintsSchema = z\n .object({\n license: z.string().optional(),\n maxBundleKb: z.number().positive().optional(),\n minConfidence: confidenceEnum.optional(),\n })\n .optional();\n\n/** Wrap any result object as a compact MCP text response. `compact` strips\n * null/empty fields so the agent's context only carries signal (§12.4). */\nfunction json(obj: unknown) {\n return { content: [{ type: 'text' as const, text: JSON.stringify(compact(obj)) }] };\n}\n\n/**\n * Per-connection identity, resolved from the authenticated API key at the HTTP\n * boundary and threaded into the tools. This is the channel that lets lurq know\n * *who* is calling — stamped onto the data it collects (§3.1 flywheel) so it\n * accrues to an individual account instead of an anonymous pool. `ownerId` is\n * null on the stdio/local path and for operator-issued keys with no account.\n */\nexport interface ServerContext {\n ownerId?: string | null;\n}\n\nexport function buildMcpServer(\n db: ReturnType<typeof createDb>['db'],\n ctx: ServerContext = {},\n): McpServer {\n const server = new McpServer({ name: SERVER_NAME, version: VERSION });\n\n // Run a tool with Prometheus timing (metrics) AND a fire-and-forget per-user\n // usage counter for the dashboard (§ dashboard v1 phase 2). The counter is\n // recorded in a finally so an errored call still counts; recordUsage no-ops\n // when ctx.ownerId is null (stdio/local or operator keys with no account).\n const run = <T>(tool: string, fn: () => Promise<T>): Promise<T> =>\n (async () => {\n try {\n return await timed(tool, fn);\n } finally {\n void recordUsage(db, ctx.ownerId ?? null, tool);\n }\n })();\n\n server.registerTool(\n 'recommend',\n {\n title: 'Recommend packages',\n description:\n 'Recommend the best current npm packages for a described need — fresh, objectively scored, with confidence labels. Call before choosing or hand-rolling a dependency.',\n inputSchema: {\n need: z.string().min(1).describe('Natural-language description of what you need'),\n category: categoryEnum.optional().describe('Optional taxonomy category to restrict to'),\n constraints: constraintsSchema,\n },\n },\n async (args) => json(await run('recommend', () => handleRecommend(db, args))),\n );\n\n server.registerTool(\n 'evaluate',\n {\n title: 'Evaluate a package',\n description:\n 'Full evidence read for one npm package: scores, signals, advisories, summary, and a usage guide. Fetches & scores on demand if not yet tracked.',\n inputSchema: {\n package: npmName.describe('npm package name'),\n },\n },\n async (args) => json(await run('evaluate', () => handleEvaluate(db, args, ctx.ownerId ?? null))),\n );\n\n server.registerTool(\n 'compare',\n {\n title: 'Compare packages',\n description: 'Side-by-side comparison of 2–5 npm packages, ranked by health score.',\n inputSchema: {\n packages: z.array(npmName).min(2).max(5).describe('2–5 npm package names'),\n },\n },\n async (args) => json(await run('compare', () => handleCompare(db, args, ctx.ownerId ?? null))),\n );\n\n server.registerTool(\n 'compat',\n {\n title: 'Check package compatibility',\n description: COMPAT_DESCRIPTION,\n inputSchema: {\n packages: z.array(npmName).min(2).max(8).describe(COMPAT_PACKAGES_DESCRIPTION),\n versions: z.record(z.string()).optional().describe(COMPAT_VERSIONS_DESCRIPTION),\n node: z.string().optional().describe(COMPAT_NODE_DESCRIPTION),\n },\n },\n async (args) => json(await run('compat', () => handleCompat(db, args))),\n );\n\n server.registerTool(\n 'verify',\n {\n title: 'Verify a package',\n description: VERIFY_DESCRIPTION,\n inputSchema: {\n package: npmName.describe('npm package name to verify'),\n },\n },\n async (args) => json(await run('verify', () => handleVerify(db, args, ctx.ownerId ?? null))),\n );\n\n server.registerTool(\n 'usage',\n {\n title: 'Version-exact API surface + drift',\n description:\n \"Get a package version's real public API — the exported symbols and signatures extracted from its shipped .d.ts, exact to the version, none of it in the model's training data. Pass knownVersion (e.g. the version you were trained on) to get the precise delta: what was added, removed, renamed, or changed. Also returns the version's declared engines (Node/runtime floor) so you don't write code against a version the target runtime cannot install. Use before writing code against a package whose API may have moved. For framework file/convention changes (not exported symbols), consult the official migration guide / Context7 instead.\",\n inputSchema: {\n package: npmName.describe('npm package name'),\n version: z.string().optional().describe('Target version (defaults to latest)'),\n knownVersion: z\n .string()\n .optional()\n .describe('A version you already know; returns the API delta from it to the target'),\n },\n },\n async (args) => json(await run('usage', () => handleUsage(db, args))),\n );\n\n server.registerTool(\n 'diagram',\n {\n title: 'Reference architecture diagram',\n description:\n 'Emit a reference-architecture Mermaid diagram for a stack you have already chosen (package names). A labeled starting point keyed by layer — not a validated architecture, and not an architecture designer.',\n inputSchema: {\n stack: z\n .array(npmName)\n .optional()\n .describe('Package names that make up the stack; omit or empty to get usage guidance'),\n },\n },\n async (args) => json(await run('diagram', () => handleDiagram(db, args))),\n );\n\n server.registerTool(\n 'plan',\n {\n title: 'Plan a stack from a program description',\n description: PLAN_DESCRIPTION,\n inputSchema: {\n document: z\n .string()\n .optional()\n .describe('Detailed description of the program (spec/README); lurq decomposes it into components'),\n needs: z\n .array(\n z.object({\n need: z.string().min(1).describe('A component that needs a library'),\n category: categoryEnum.optional(),\n }),\n )\n .optional()\n .describe('Pre-decomposed components (skip if you pass a document)'),\n using: z\n .array(npmName)\n .max(12)\n .optional()\n .describe(\n 'Packages you have already decided on. lurq pins these as fixed slots, recommends only the remaining needs, and checks/optimizes the whole stack around your picks.',\n ),\n optimize: z\n .enum(['speed', 'balanced'])\n .optional()\n .describe(\"'speed' prefers the lightest-bundle option per slot; default 'balanced'\"),\n },\n },\n async (args) => json(await run('plan', () => handlePlan(db, args, ctx.ownerId ?? null))),\n );\n\n server.registerTool(\n 'resolve_surface',\n {\n title: 'Version-exact runtime surface',\n description:\n \"What a package version ACTUALLY exports at runtime, extracted from its shipped JavaScript rather than from documentation or the model's memory. Call before writing code against a package whose API may have moved. Runtime existence is what decides whether an import throws; a removed type breaks tsc, a removed runtime symbol breaks the program. A miss returns UNKNOWN and queues extraction — UNKNOWN never means the symbol is absent.\",\n inputSchema: {\n package: npmName.describe('npm package name'),\n version: z.string().optional().describe('Exact version; omit for the latest extracted'),\n },\n },\n async (args) => json(await run('resolve_surface', () => handleResolveSurface(db, args))),\n );\n\n server.registerTool(\n 'diff_surface',\n {\n title: 'Surface diff between two versions',\n description:\n 'What changed in a package\\'s runtime surface between two versions: symbols removed, added, and arity changes. Removals break `node`; type-only removals are returned separately because they break `tsc` instead. Answers \"when did this stop working\" from static comparison, with no install required. Use before an upgrade, and to explain a break after one.',\n inputSchema: {\n package: npmName.describe('npm package name'),\n fromVersion: z.string().describe('Version you are on'),\n toVersion: z.string().describe('Version you are moving to'),\n },\n },\n async (args) => json(await run('diff_surface', () => handleDiffSurface(db, args))),\n );\n\n server.registerTool(\n 'report_outcome',\n {\n title: 'Report a recommendation outcome',\n description:\n 'Opt-in feedback after acting on a lurq recommendation: report whether you went with the package and whether it built. No source code — only the coarse decision + a build signal. Helps lurq learn which packages agents actually succeed with; safe to skip.',\n inputSchema: {\n package: npmName.describe('The package that was recommended'),\n accepted: z.boolean().describe('Did you go with this package?'),\n buildSignal: z\n .enum(['installed', 'compiled', 'tests_passed', 'failed'])\n .optional()\n .describe('Coarse post-install result, if known'),\n need: z\n .string()\n .max(500)\n .optional()\n .describe('The original need this was recommended for (no source code)'),\n },\n },\n // ownerId comes from the authenticated key (ctx), NOT the tool arguments —\n // a caller must never be able to attribute an outcome to another org.\n async (args) =>\n json(await run('report_outcome', () => handleReportOutcome(db, args, ctx.ownerId ?? null))),\n );\n\n return server;\n}\n\nexport async function startMcpServer(): Promise<void> {\n const { db, close } = createDb();\n const server = buildMcpServer(db);\n\n const shutdown = async () => {\n try {\n await close();\n } finally {\n process.exit(0);\n }\n };\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n logger.info(`${SERVER_NAME} MCP server v${VERSION} running on stdio.`);\n}\n","/**\n * API-key generation, hashing, and lifecycle for the hosted HTTP service\n * (docs/lurq-hosted-deployment.md §5). Keys are high-entropy random strings; only\n * their sha256 hash is persisted, so a DB leak never exposes a usable key. The\n * plaintext is returned exactly once (at creation) and never stored or logged.\n */\nimport { createHash, randomBytes } from 'node:crypto';\nimport { and, desc, eq, isNull } from 'drizzle-orm';\nimport { API_KEY_PREFIX } from '../core/constants';\nimport type { Database } from '../db/client';\nimport { apiKeys, type ApiKeyRow } from '../db/schema';\nimport { logger } from '../core/logger';\n\n/** Chars of the random body kept in the display prefix (`lurq_live_<6>`). */\nconst DISPLAY_BODY = 6;\n\n/** sha256 hex of a key — the only form ever persisted or compared. */\nexport function hashKey(key: string): string {\n return createHash('sha256').update(key).digest('hex');\n}\n\nexport interface GeneratedKey {\n /** The full plaintext key — show once, never store. */\n key: string;\n /** sha256 hash to persist. */\n hash: string;\n /** Identifiable, safe-to-display prefix. */\n prefix: string;\n}\n\nexport function generateApiKey(): GeneratedKey {\n // 24 random bytes → 32-char base64url body: unbiased, URL/header-safe.\n const body = randomBytes(24).toString('base64url');\n const key = API_KEY_PREFIX + body;\n return { key, hash: hashKey(key), prefix: API_KEY_PREFIX + body.slice(0, DISPLAY_BODY) };\n}\n\nexport interface CreateKeyInput {\n label?: string;\n tier?: string;\n ownerId?: string;\n}\n\n/** Create and persist a key. Returns the plaintext ONCE plus the stored row. */\nexport async function createKey(\n db: Database,\n input: CreateKeyInput = {},\n): Promise<{ key: string; row: ApiKeyRow }> {\n const { key, hash, prefix } = generateApiKey();\n const [row] = await db\n .insert(apiKeys)\n .values({\n keyHash: hash,\n prefix,\n label: input.label,\n tier: input.tier ?? 'free',\n ownerId: input.ownerId,\n })\n .returning();\n return { key, row: row! };\n}\n\n/**\n * Short-TTL cache of resolved keys. Auth runs on every hosted request, so an\n * uncached lookup means a SELECT (plus a lastUsedAt UPDATE) per call — pure load\n * on the DB, which is the scaling bottleneck. We cache only *valid* keys (the\n * hot path); unknown tokens always hit the DB so a flood of garbage tokens can't\n * bloat the map, and the per-IP limiter blunts that anyway. Trade-off: a revoked\n * key keeps working for up to AUTH_TTL_MS. Process-local; each instance caches\n * independently, which is fine for a bearer check.\n */\ninterface AuthEntry {\n row: ApiKeyRow;\n cachedAt: number;\n lastStampAt: number;\n}\nconst authCache = new Map<string, AuthEntry>();\nconst AUTH_TTL_MS = 60_000;\n/** lastUsedAt is analytics, not correctness — stamp at most this often per key. */\nconst STAMP_INTERVAL_MS = 60_000;\n\n/** Test-only: clear the auth cache so a fresh lookup re-reads the DB. */\nexport function resetAuthCache(): void {\n authCache.clear();\n}\n\n/** Fire-and-forget usage stamp, throttled per key. Never blocks the request. */\nfunction stampLastUsed(db: Database, entry: AuthEntry, now: number): void {\n if (now - entry.lastStampAt < STAMP_INTERVAL_MS) return;\n entry.lastStampAt = now;\n db.update(apiKeys)\n .set({ lastUsedAt: new Date(now) })\n .where(eq(apiKeys.id, entry.row.id))\n .then(undefined, (err) => logger.debug(`lastUsedAt stamp failed: ${String(err)}`));\n}\n\n/**\n * Look up an active (non-revoked) key by its plaintext form. Returns null if the\n * key is unknown or revoked. Cached for AUTH_TTL_MS; stamps `lastUsedAt`\n * best-effort (throttled) without blocking.\n */\nexport async function lookupActiveKey(db: Database, key: string): Promise<ApiKeyRow | null> {\n const hash = hashKey(key);\n const now = Date.now();\n\n const cached = authCache.get(hash);\n if (cached && now - cached.cachedAt < AUTH_TTL_MS) {\n stampLastUsed(db, cached, now);\n return cached.row;\n }\n\n const [row] = await db\n .select()\n .from(apiKeys)\n .where(and(eq(apiKeys.keyHash, hash), isNull(apiKeys.revokedAt)))\n .limit(1);\n if (!row) {\n authCache.delete(hash); // e.g. a key revoked since it was last cached\n return null;\n }\n const entry: AuthEntry = { row, cachedAt: now, lastStampAt: 0 };\n authCache.set(hash, entry);\n stampLastUsed(db, entry, now);\n return row;\n}\n\nexport async function listKeys(db: Database): Promise<ApiKeyRow[]> {\n return db.select().from(apiKeys).orderBy(desc(apiKeys.createdAt));\n}\n\n/** Keys belonging to one dashboard account (§ hosted dashboard), newest first. */\nexport async function listKeysForOwner(db: Database, ownerId: string): Promise<ApiKeyRow[]> {\n return db\n .select()\n .from(apiKeys)\n .where(eq(apiKeys.ownerId, ownerId))\n .orderBy(desc(apiKeys.createdAt));\n}\n\n/** Resolve a \"prefix or numeric id\" argument to a Drizzle equality filter. */\nfunction matchByPrefixOrId(prefixOrId: string) {\n const asId = Number(prefixOrId);\n return Number.isInteger(asId) && String(asId) === prefixOrId.trim()\n ? eq(apiKeys.id, asId)\n : eq(apiKeys.prefix, prefixOrId);\n}\n\n/**\n * Resolve a key by display prefix, scoped to one owner — the ownership check\n * the dashboard's revoke/rotate routes use before touching the row. Returns\n * null if no active key with that prefix belongs to this owner (never reveals\n * whether a key with that prefix exists for someone else).\n */\nexport async function findKeyForOwner(\n db: Database,\n args: { prefixOrId: string; ownerId: string },\n): Promise<ApiKeyRow | null> {\n const [row] = await db\n .select()\n .from(apiKeys)\n .where(and(matchByPrefixOrId(args.prefixOrId), isNull(apiKeys.revokedAt)))\n .limit(1);\n if (!row || row.ownerId !== args.ownerId) return null;\n return row;\n}\n\n/**\n * Revoke a key by display prefix or numeric id. Returns how many active keys were\n * revoked (0 if none matched or it was already revoked).\n */\nexport async function revokeKey(db: Database, prefixOrId: string): Promise<number> {\n const rows = await db\n .update(apiKeys)\n .set({ revokedAt: new Date() })\n .where(and(matchByPrefixOrId(prefixOrId), isNull(apiKeys.revokedAt)))\n .returning({ id: apiKeys.id });\n return rows.length;\n}\n\n/**\n * Rotate (\"swap\") a key: issue a replacement carrying the old key's label, tier,\n * and owner, then revoke the original. Returns the new plaintext (once), the new\n * row, and the revoked row — or null if no active key matched.\n *\n * The new key is created BEFORE the old one is revoked, so a failure mid-rotation\n * leaves the caller with a working key (at worst two active keys, never zero).\n */\nexport async function rotateKey(\n db: Database,\n prefixOrId: string,\n): Promise<{ key: string; row: ApiKeyRow; previous: ApiKeyRow } | null> {\n const [previous] = await db\n .select()\n .from(apiKeys)\n .where(and(matchByPrefixOrId(prefixOrId), isNull(apiKeys.revokedAt)))\n .limit(1);\n if (!previous) return null;\n\n const { key, row } = await createKey(db, {\n label: previous.label ?? undefined,\n tier: previous.tier,\n ownerId: previous.ownerId ?? undefined,\n });\n await db.update(apiKeys).set({ revokedAt: new Date() }).where(eq(apiKeys.id, previous.id));\n return { key, row, previous };\n}\n","/**\n * Repo-autopilot types.\n *\n * Scope discipline: lurq reads *manifests*, never source. A `package.json`\n * dependency block is the minimum input needed to compute drift, and it is also\n * the most we can read without breaking the promise the rest of the product is\n * built on (\"lurq never sees your code\"). The agent that eventually edits code\n * runs in the user's own CI, on their runner — see docs/lurq-autopilot.md.\n */\nimport type { CompatConflict } from '../core/types';\n\n/** One `package.json` found in a repo. Monorepos yield several. */\nexport interface RepoManifest {\n /** Repo-relative path, e.g. `package.json` or `packages/api/package.json`. */\n path: string;\n /** Declared ranges, dependencies + devDependencies merged. */\n deps: Record<string, string>;\n}\n\n/** Where a dependency is declared. A monorepo declares the same package in\n * several workspaces, often at different ranges — and an agent editing the\n * upgrade needs the file list, not just the merged view. */\nexport interface DepDeclaration {\n /** Repo-relative manifest path. */\n path: string;\n range: string;\n}\n\n/** Per-dependency drift, computed against the lurq index. */\nexport interface DepDrift {\n name: string;\n /** Lowest range declared anywhere — the one that governs the repo's drift. */\n range: string;\n /** Every manifest declaring this package, with that manifest's own range. */\n declaredIn: DepDeclaration[];\n /** Highest indexed version the range admits — what a fresh install resolves to. */\n resolved: string | null;\n /** `packages.latest_version` at scan time. */\n latest: string | null;\n /** Major versions between `resolved` and `latest`. 0 = current. */\n majorsBehind: number;\n deprecated: boolean;\n /** Count of known advisories on the package. */\n advisories: number;\n}\n\n/** A resolved transitive dependency carrying a risk signal worth reporting. */\nexport interface TransitiveRisk {\n name: string;\n /** The exact installed version, from the resolved tree — no range guessing. */\n version: string;\n /** Latest known release, so \"how stale is this\" is answerable. */\n latest: string | null;\n /**\n * Advisories recorded against the PACKAGE, not proven against `version`.\n * lurq does not store affected-version ranges, so this is \"this package has\n * known advisories\", never \"this install is vulnerable\". The field name and\n * every label built from it say so.\n */\n advisories: number;\n deprecated: boolean;\n /**\n * Direct dependencies whose tree pulls this in — the actual upgrade targets.\n *\n * Empty means the resolved tree carried no usable parentage, NOT that nothing\n * depends on this. Every node in a tree got there somehow, so an absence here\n * is always a gap in our data and the UI says so.\n */\n pulledInBy: string[];\n}\n\n/**\n * The resolved dependency tree beyond what `package.json` declares.\n *\n * Kept as its own block rather than folded into the direct-dependency counts,\n * because the two are fixed differently: a direct dependency you bump, a\n * transitive one you either wait for its parent or force an override. Adding\n * them together would produce a number nobody can act on.\n */\nexport interface TransitiveDrift {\n /** Total resolved npm nodes GitHub reported. */\n resolved: number;\n /** How many of those lurq has indexed — the rest carry no signal either way. */\n tracked: number;\n /** Indexed transitives whose package has known advisories. */\n advisoryPackages: number;\n /** Indexed transitives whose package is deprecated upstream. */\n deprecated: number;\n /** The worst of them, ranked. Capped — see TRANSITIVE_DETAIL_CAP. */\n risks: TransitiveRisk[];\n /** True when the tree exceeded the node cap and is therefore incomplete. */\n truncated: boolean;\n /** True when the SBOM carried usable DEPENDS_ON edges, so `pulledInBy` is\n * meaningful. False means blame paths were unavailable for the whole repo. */\n attributed: boolean;\n}\n\n/**\n * Repo-level drift summary, recomputed on every scan and stored denormalized so\n * the dashboard reads one row per repo instead of joining the whole index.\n */\nexport interface RepoDrift {\n /** Distinct dependencies declared across all manifests. */\n depsDeclared: number;\n /** How many of those lurq has indexed. The rest are `unknown` — never\n * silently counted as current (same discipline as `unverified` in\n * src/surface/upgrade.ts: not-looked-at must never read as fine). */\n depsTracked: number;\n /** Tracked deps at least one major behind. */\n majorDrift: number;\n /** Tracked deps behind at all (any semver level). */\n anyDrift: number;\n /** Tracked deps flagged deprecated upstream. */\n deprecated: number;\n /** Total advisories across tracked deps. */\n advisories: number;\n /** Per-dep detail, worst-drift first. Capped — see REPO_DRIFT_DETAIL_CAP. */\n deps: DepDrift[];\n /**\n * The resolved tree beyond the manifest. Null when the repo has no dependency\n * graph enabled — which is \"we could not look\", not \"nothing is there\", and\n * the dashboard renders the two differently.\n */\n transitive: TransitiveDrift | null;\n /**\n * Peer-dependency and engine conflicts across the tracked dependencies **at\n * their latest versions** — i.e. what breaks if the repo takes the upgrades in\n * its own migration brief. Not the state of the current install: that needs\n * each pinned version's own manifest, which is a registry read per dependency.\n *\n * `undefined` means the repo has not been scanned since this check shipped, and\n * is rendered as \"not checked\" rather than as a clean stack — same rule as\n * `transitive: null`. An empty array is a real all-clear.\n */\n conflictsAtLatest?: CompatConflict[];\n}\n\n/** Per-repo autopilot policy. Set by the connect survey, edited in the dashboard. */\nexport interface RepoPolicy {\n /** Master switch. Connecting a repo does not arm it. */\n enabled: boolean;\n /**\n * Which upgrades the agent may attempt.\n * `security` — only deps with advisories\n * `blocking` — security, plus upgrades whose surface diff removes a symbol\n * the code references (the ones that break silently)\n * `all` — every drifted dependency\n */\n scope: 'security' | 'blocking' | 'all';\n /**\n * Merge the PR when the repo's own CI passes. Opt-in per repo, and it is the\n * only setting that lets lurq change a default branch. Default false, always.\n */\n autoMerge: boolean;\n}\n\nexport const DEFAULT_REPO_POLICY: RepoPolicy = {\n enabled: false,\n scope: 'blocking',\n autoMerge: false,\n};\n\n/**\n * What the CI check concluded about one upgrade, straight from `checkUpgrade`.\n * `unverified` is a first-class outcome and is never rolled into `ok` — a check\n * that could not run is not a check that passed.\n */\nexport type UpgradeSeverity = 'blocking' | 'warning' | 'ok' | 'unverified';\n\n/**\n * How far one upgrade got through the loop.\n * checked — analysed only (comment mode, or the agent step was not armed)\n * skipped — policy excluded it\n * edited — the agent changed code but the run stopped before a PR\n * pr_open — a pull request exists\n * merged — that PR landed\n * failed — the edit or the repo's own checks failed\n */\nexport type UpgradeRunStatus =\n | 'checked'\n | 'skipped'\n | 'edited'\n | 'pr_open'\n | 'merged'\n | 'failed';\n\nexport const UPGRADE_SEVERITIES: UpgradeSeverity[] = ['blocking', 'warning', 'ok', 'unverified'];\nexport const UPGRADE_RUN_STATUSES: UpgradeRunStatus[] = [\n 'checked',\n 'skipped',\n 'edited',\n 'pr_open',\n 'merged',\n 'failed',\n];\n\n/** Manifests scanned per repo. A monorepo with more workspaces than this reports\n * partial coverage rather than silently truncating — see scanRepo. */\nexport const REPO_MANIFEST_CAP = 25;\n\n/** Per-dep drift rows persisted. The summary counts are always exact; only the\n * detail list is capped, and the dashboard says so when it truncates. */\nexport const REPO_DRIFT_DETAIL_CAP = 200;\n\n/** Transitive risk rows persisted. Counts above the list stay exact. */\nexport const TRANSITIVE_DETAIL_CAP = 100;\n","/**\n * Read/write helpers for connected repositories.\n *\n * Every query is scoped by `ownerId`. That is the authorization boundary: the\n * HTTP layer authenticates the web app with the issuer secret and passes the\n * signed-in user's id, so a missing `ownerId` filter here would hand one user\n * another user's repos. There is deliberately no \"get by id\" without an owner.\n */\nimport { and, eq, sql } from 'drizzle-orm';\nimport type { Database } from './client';\nimport { repos, type RepoRow } from './schema';\nimport { DEFAULT_REPO_POLICY, type RepoDrift, type RepoManifest, type RepoPolicy } from '../github/types';\n\nexport interface RepoUpsert {\n ownerId: string;\n installationId: number;\n fullName: string;\n defaultBranch: string | null;\n isPrivate: boolean;\n}\n\n/**\n * Register repos discovered from an installation.\n *\n * Idempotent, and deliberately does NOT touch `policy`, `drift`, or the scan\n * bookkeeping: re-running the connect flow (or GitHub replaying an installation\n * webhook) must never silently disarm a repo the user already configured.\n */\nexport async function upsertRepos(db: Database, rows: RepoUpsert[]): Promise<number> {\n if (rows.length === 0) return 0;\n await db\n .insert(repos)\n .values(\n rows.map((row) => ({\n ownerId: row.ownerId,\n installationId: row.installationId,\n fullName: row.fullName,\n defaultBranch: row.defaultBranch,\n isPrivate: row.isPrivate,\n policy: DEFAULT_REPO_POLICY,\n })),\n )\n .onConflictDoUpdate({\n target: [repos.ownerId, repos.fullName],\n set: {\n installationId: sql`excluded.installation_id`,\n defaultBranch: sql`excluded.default_branch`,\n isPrivate: sql`excluded.is_private`,\n },\n });\n return rows.length;\n}\n\nexport async function listRepos(db: Database, ownerId: string): Promise<RepoRow[]> {\n return db\n .select()\n .from(repos)\n .where(eq(repos.ownerId, ownerId))\n .orderBy(repos.fullName);\n}\n\n/**\n * Every connected repo, all owners. The one deliberately unscoped read — it\n * backs the nightly cron, which has no user context. Never reachable from an\n * HTTP route.\n */\nexport async function listAllRepos(db: Database): Promise<RepoRow[]> {\n return db.select().from(repos).orderBy(repos.installationId, repos.fullName);\n}\n\nexport async function getRepo(\n db: Database,\n ownerId: string,\n id: number,\n): Promise<RepoRow | null> {\n const rows = await db\n .select()\n .from(repos)\n .where(and(eq(repos.ownerId, ownerId), eq(repos.id, id)))\n .limit(1);\n return rows[0] ?? null;\n}\n\n/** Persist a successful scan. Clears `lastScanError` — see the schema comment. */\nexport async function saveScan(\n db: Database,\n id: number,\n scan: { manifests: RepoManifest[]; drift: RepoDrift; installCommand: string },\n): Promise<void> {\n await db\n .update(repos)\n .set({\n manifests: scan.manifests,\n drift: scan.drift,\n installCommand: scan.installCommand,\n lastScanAt: new Date(),\n lastScanError: null,\n })\n .where(eq(repos.id, id));\n}\n\n/**\n * Record a failed scan without discarding the last good drift numbers. Stale\n * data plus a visible error beats an empty table: the user can still see what\n * their repo looked like at the last successful read.\n */\nexport async function saveScanError(\n db: Database,\n id: number,\n message: string,\n): Promise<void> {\n await db\n .update(repos)\n .set({ lastScanAt: new Date(), lastScanError: message.slice(0, 500) })\n .where(eq(repos.id, id));\n}\n\nexport async function setRepoPolicy(\n db: Database,\n ownerId: string,\n id: number,\n policy: RepoPolicy,\n): Promise<boolean> {\n const updated = await db\n .update(repos)\n .set({ policy })\n .where(and(eq(repos.ownerId, ownerId), eq(repos.id, id)))\n .returning({ id: repos.id });\n return updated.length > 0;\n}\n\n/** Forget a repo. The GitHub App install itself is revoked on GitHub, not here. */\nexport async function deleteRepo(\n db: Database,\n ownerId: string,\n id: number,\n): Promise<boolean> {\n const deleted = await db\n .delete(repos)\n .where(and(eq(repos.ownerId, ownerId), eq(repos.id, id)))\n .returning({ id: repos.id });\n return deleted.length > 0;\n}\n","/**\n * GitHub App authentication + REST access for the repo autopilot.\n *\n * Two-step, per GitHub's App auth model: sign a short-lived RS256 JWT with the\n * App's private key, exchange it for an *installation* access token, then call\n * the REST API as that installation. The JWT is the only thing derived from the\n * private key, and it lives ~9 minutes; the installation token lives an hour and\n * is scoped to exactly the repos the user selected at install time.\n *\n * No Octokit: the whole surface we need is three endpoints and an RS256 sign,\n * which `node:crypto` already does. Adding `@octokit/auth-app` + its transitive\n * tree to sign one JWT would be the expensive way to save fifteen lines.\n *\n * Token caching is in-memory and per-process only — deliberately never routed\n * through the shared on-disk `httpRequest` cache, which would write live repo\n * credentials to `~/.lurq`.\n */\nimport { createSign } from 'node:crypto';\nimport { getConfig } from '../core/config';\nimport { HttpError, httpRequest } from '../core/http';\n\nconst API_HOST = 'api.github.com';\nconst API = `https://${API_HOST}`;\n\n/** GitHub rejects a JWT with `exp` more than 10 minutes out; 9 leaves slack. */\nconst JWT_TTL_S = 9 * 60;\n/** Re-mint an installation token this long before it actually expires. */\nconst TOKEN_SKEW_MS = 60_000;\n\nexport class GithubAppError extends Error {\n constructor(\n message: string,\n readonly status: number,\n ) {\n super(message);\n this.name = 'GithubAppError';\n }\n}\n\nexport interface GithubAppCredentials {\n appId: string;\n privateKey: string;\n}\n\n/**\n * Read App credentials from config, or null when the App is not configured.\n *\n * Returning null rather than throwing is what lets `/repos` 404 cleanly on a\n * deployment that has not set the App up yet — the same shape `LURQ_ISSUER_SECRET`\n * uses for key issuance.\n */\nexport function githubAppCredentials(): GithubAppCredentials | null {\n const config = getConfig();\n const appId = config.LURQ_GITHUB_APP_ID;\n const rawKey = config.LURQ_GITHUB_APP_PRIVATE_KEY;\n if (!appId || !rawKey) return null;\n // Host env editors differ: Railway keeps real newlines, most CI secret fields\n // flatten them to a literal backslash-n. A PEM with the wrong one fails inside\n // crypto with an opaque error, so normalize here rather than debug it there.\n const privateKey = rawKey.includes('\\\\n') ? rawKey.replace(/\\\\n/g, '\\n') : rawKey;\n return { appId, privateKey };\n}\n\nfunction b64url(input: Buffer | string): string {\n return Buffer.from(input)\n .toString('base64')\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '');\n}\n\n/** Mint the App-level JWT. `iat` is backdated 60s to tolerate clock skew. */\nexport function appJwt(creds: GithubAppCredentials, now: Date = new Date()): string {\n const issued = Math.floor(now.getTime() / 1000) - 60;\n const header = b64url(JSON.stringify({ alg: 'RS256', typ: 'JWT' }));\n const payload = b64url(\n JSON.stringify({ iat: issued, exp: issued + JWT_TTL_S, iss: creds.appId }),\n );\n const signature = createSign('RSA-SHA256')\n .update(`${header}.${payload}`)\n .sign(creds.privateKey);\n return `${header}.${payload}.${b64url(signature)}`;\n}\n\ninterface CachedToken {\n token: string;\n expiresAt: number;\n}\n\nconst tokenCache = new Map<number, CachedToken>();\n\n/**\n * Exchange the App JWT for an installation access token.\n *\n * A 404 here means the installation is gone (user uninstalled the App), which is\n * a normal, expected state — callers surface it as \"reconnect\" rather than an error.\n */\nexport async function installationToken(installationId: number): Promise<string> {\n const cached = tokenCache.get(installationId);\n if (cached && cached.expiresAt - TOKEN_SKEW_MS > Date.now()) return cached.token;\n\n const creds = githubAppCredentials();\n if (!creds) throw new GithubAppError('GitHub App is not configured.', 503);\n\n let res;\n try {\n res = await httpRequest<{ token?: string; expires_at?: string }>(\n `${API}/app/installations/${installationId}/access_tokens`,\n {\n host: API_HOST,\n ttlMs: 0, // never cache credentials to disk\n method: 'POST',\n headers: {\n Authorization: `Bearer ${appJwt(creds)}`,\n Accept: 'application/vnd.github+json',\n 'X-GitHub-Api-Version': '2022-11-28',\n },\n },\n );\n } catch (err) {\n if (err instanceof HttpError && err.status === 404) {\n throw new GithubAppError('This GitHub installation no longer exists.', 404);\n }\n throw new GithubAppError(\n err instanceof Error ? err.message : 'Could not authenticate with GitHub.',\n 502,\n );\n }\n\n const token = res.data?.token;\n if (!token) throw new GithubAppError('GitHub returned no installation token.', 502);\n\n const expiresAt = res.data.expires_at ? Date.parse(res.data.expires_at) : NaN;\n tokenCache.set(installationId, {\n token,\n // A token with an unparseable expiry is still valid; treat it as short-lived\n // rather than caching it forever on a malformed timestamp.\n expiresAt: Number.isNaN(expiresAt) ? Date.now() + 5 * 60_000 : expiresAt,\n });\n return token;\n}\n\n/** Authenticated REST GET as an installation. */\nexport async function installationGet<T>(\n installationId: number,\n path: string,\n): Promise<T> {\n const token = await installationToken(installationId);\n const res = await httpRequest<T>(`${API}${path}`, {\n host: API_HOST,\n ttlMs: 0, // repo state changes under us; a cached manifest is a wrong answer\n headers: {\n Authorization: `Bearer ${token}`,\n Accept: 'application/vnd.github+json',\n 'X-GitHub-Api-Version': '2022-11-28',\n },\n });\n return res.data;\n}\n","/**\n * Blame paths: which direct dependency pulls a transitive one in.\n *\n * Without this, a transitive advisory tells you *what* but not what to do — you\n * can see `minimist@1.2.5` is flagged and have no idea which of your own\n * dependencies is responsible. Walking the DEPENDS_ON graph upward turns that\n * into \"upgrade eslint\", which is an action.\n *\n * The whole module is written around one distinction: **\"nothing pulls this in\"\n * is never a true answer.** Every node in a resolved tree got there somehow. So\n * an empty result always means the graph could not tell us, and it is reported\n * as unattributed rather than as an absence of parents.\n */\nimport type { DependencyEdge, ResolvedDep } from './sbom';\n\n/**\n * Depth bound for the upward walk. Real npm trees nest deeply and contain\n * cycles; this caps the work per node without changing the answer for anything\n * a human would act on.\n */\nconst MAX_DEPTH = 24;\n\nexport interface AttributionIndex {\n /** True when the document carried usable DEPENDS_ON edges at all. */\n available: boolean;\n /** Direct dependency names reachable *above* a given package name. */\n parentsOf: Map<string, string[]>;\n}\n\n/**\n * Build the reverse index once per scan, then answer every risk from it.\n *\n * Done as one pass rather than a walk per risky package: a tree with thousands\n * of nodes and a hundred flagged packages would otherwise re-traverse the same\n * subgraphs a hundred times.\n */\nexport function buildAttribution(\n deps: ResolvedDep[],\n edges: DependencyEdge[],\n directNames: Set<string>,\n): AttributionIndex {\n if (edges.length === 0) return { available: false, parentsOf: new Map() };\n\n // SPDX ids are the edge vocabulary; names are what anyone can act on.\n const nameOf = new Map<string, string>();\n for (const dep of deps) {\n if (dep.spdxId) nameOf.set(dep.spdxId, dep.name);\n }\n\n // child id → parent ids. The SBOM gives parent → child; attribution walks up.\n const parentIds = new Map<string, string[]>();\n for (const edge of edges) {\n const list = parentIds.get(edge.child);\n if (list) list.push(edge.parent);\n else parentIds.set(edge.child, [edge.parent]);\n }\n\n // An SBOM whose only edges come from the document root gives every package the\n // same non-informative parent. Detect that and report it as unavailable rather\n // than attributing every transitive to a repo node nobody can upgrade.\n const informative = edges.some(\n (edge) => nameOf.has(edge.parent) && nameOf.has(edge.child),\n );\n if (!informative) return { available: false, parentsOf: new Map() };\n\n const parentsOf = new Map<string, string[]>();\n\n for (const dep of deps) {\n if (!dep.spdxId || directNames.has(dep.name)) continue;\n\n const roots = new Set<string>();\n const seen = new Set<string>([dep.spdxId]);\n let frontier = [dep.spdxId];\n\n for (let depth = 0; depth < MAX_DEPTH && frontier.length > 0; depth++) {\n const next: string[] = [];\n for (const id of frontier) {\n for (const parent of parentIds.get(id) ?? []) {\n if (seen.has(parent)) continue; // npm graphs contain cycles\n seen.add(parent);\n const parentName = nameOf.get(parent);\n if (parentName && directNames.has(parentName)) {\n // A direct dependency: stop climbing this branch. Anything above it\n // is the repo itself, which is not an upgrade target.\n roots.add(parentName);\n continue;\n }\n next.push(parent);\n }\n }\n frontier = next;\n }\n\n if (roots.size > 0) {\n parentsOf.set(dep.name, [...roots].sort());\n }\n }\n\n return { available: true, parentsOf };\n}\n","/**\n * Drift computation: declared ranges → how far behind this repo actually is.\n *\n * \"Behind\" is measured against what a *fresh install today* would resolve to,\n * not against the range's floor. `^6.4.0` on a package now at 6.9.2 is current,\n * not five minors behind — reporting it as drift is how a dashboard trains its\n * user to ignore it. So `resolved` is `maxSatisfying(range)` and drift is the\n * gap from there to `latest`.\n *\n * Anything the index does not know stays out of the drift counts entirely and is\n * reported as `depsDeclared - depsTracked`. Same discipline as `unverified` in\n * src/surface/upgrade.ts: a dependency we did not look at must never be counted\n * as one we found nothing wrong with.\n */\nimport { inArray } from 'drizzle-orm';\nimport semver from 'semver';\nimport type { Database } from '../db/client';\nimport { packageVersions, packages } from '../db/schema';\nimport {\n REPO_DRIFT_DETAIL_CAP,\n TRANSITIVE_DETAIL_CAP,\n type DepDeclaration,\n type DepDrift,\n type RepoDrift,\n type RepoManifest,\n type TransitiveDrift,\n type TransitiveRisk,\n} from './types';\nimport { buildAttribution } from './attribute';\nimport { assembleMembers } from '../compat/members';\nimport { resolveArchitectureCompat } from '../compat/peerCompat';\nimport type { CompatConflict } from '../core/types';\nimport type { DependencyEdge, ResolvedDep } from './sbom';\n\n/** Postgres caps bind parameters; chunk the `IN` lists well under it. */\nconst NAME_CHUNK = 500;\n\ninterface IndexedPackage {\n latestVersion: string | null;\n deprecated: boolean;\n advisories: number;\n}\n\nexport interface DeclaredDep {\n /** Lowest range declared anywhere — see below. */\n range: string;\n /** Every manifest that declares it, in manifest order (root first). */\n declaredIn: DepDeclaration[];\n}\n\n/**\n * Distinct dependencies across every manifest, with where each is declared.\n *\n * `range` is the *lowest* declared range, because that is the one whose upgrade\n * is furthest away and therefore governs the repo's real drift. `declaredIn`\n * keeps every site, because reporting drift and *editing* it need different\n * views: the merged range answers \"how far behind is this repo\", the file list\n * answers \"which package.json does the agent bump\".\n */\nexport function declaredDeps(manifests: RepoManifest[]): Map<string, DeclaredDep> {\n const out = new Map<string, DeclaredDep>();\n for (const manifest of manifests) {\n for (const [name, range] of Object.entries(manifest.deps)) {\n const existing = out.get(name);\n if (!existing) {\n out.set(name, { range, declaredIn: [{ path: manifest.path, range }] });\n continue;\n }\n existing.declaredIn.push({ path: manifest.path, range });\n const current = semver.minVersion(existing.range);\n const candidate = semver.minVersion(range);\n if (current && candidate && semver.lt(candidate, current)) existing.range = range;\n }\n }\n return out;\n}\n\nasync function loadIndexed(\n db: Database,\n names: string[],\n): Promise<Map<string, IndexedPackage>> {\n const out = new Map<string, IndexedPackage>();\n for (let i = 0; i < names.length; i += NAME_CHUNK) {\n const rows = await db\n .select({\n name: packages.name,\n latestVersion: packages.latestVersion,\n deprecated: packages.deprecated,\n advisories: packages.advisories,\n })\n .from(packages)\n .where(inArray(packages.name, names.slice(i, i + NAME_CHUNK)));\n for (const row of rows) {\n out.set(row.name, {\n latestVersion: row.latestVersion,\n deprecated: row.deprecated,\n advisories: row.advisories?.length ?? 0,\n });\n }\n }\n return out;\n}\n\n/**\n * Versions the index knows for each name, so `maxSatisfying` answers what a real\n * install would pick rather than assuming the range's floor.\n *\n * Deliberately one query per chunk of names rather than per name: a repo with\n * 300 dependencies would otherwise open 300 round trips per scan.\n */\nexport async function loadVersions(\n db: Database,\n names: string[],\n): Promise<Map<string, string[]>> {\n const out = new Map<string, string[]>();\n for (let i = 0; i < names.length; i += NAME_CHUNK) {\n const rows = await db\n .select({ name: packageVersions.packageName, version: packageVersions.version })\n .from(packageVersions)\n .where(inArray(packageVersions.packageName, names.slice(i, i + NAME_CHUNK)));\n for (const row of rows) {\n const list = out.get(row.name);\n if (list) list.push(row.version);\n else out.set(row.name, [row.version]);\n }\n }\n return out;\n}\n\n/** Pure drift math for one dependency — the part worth testing in isolation. */\nexport function depDrift(\n name: string,\n declared: DeclaredDep,\n indexed: IndexedPackage,\n knownVersions: string[],\n): DepDrift {\n const { range } = declared;\n const latest = indexed.latestVersion;\n // `maxSatisfying` needs the candidate list; when the index has no timeline yet,\n // fall back to the range's own floor rather than reporting no drift at all.\n const resolved =\n semver.maxSatisfying(knownVersions, range, { includePrerelease: false }) ??\n semver.minVersion(range)?.version ??\n null;\n\n let majorsBehind = 0;\n if (resolved && latest && semver.valid(resolved) && semver.valid(latest)) {\n majorsBehind = Math.max(0, semver.major(latest) - semver.major(resolved));\n }\n\n return {\n name,\n range,\n declaredIn: declared.declaredIn,\n resolved,\n latest,\n majorsBehind,\n deprecated: indexed.deprecated,\n advisories: indexed.advisories,\n };\n}\n\n/** True when `resolved` is behind `latest` at any semver level. */\nfunction isBehind(dep: DepDrift): boolean {\n if (!dep.resolved || !dep.latest) return false;\n if (!semver.valid(dep.resolved) || !semver.valid(dep.latest)) return false;\n return semver.lt(dep.resolved, dep.latest);\n}\n\n/**\n * Rank worst-first so the capped detail list keeps what matters: an advisory\n * outranks a major bump, which outranks a deprecation notice, which outranks a\n * minor. The summary counts above the list are always exact regardless of the cap.\n */\nfunction severity(dep: DepDrift): number {\n return (\n dep.advisories * 1000 +\n dep.majorsBehind * 100 +\n (dep.deprecated ? 50 : 0) +\n (isBehind(dep) ? 1 : 0)\n );\n}\n\n/**\n * Risk in the resolved tree, excluding what the manifest already declares.\n *\n * Deliberately reports *presence of advisories on the package*, not \"vulnerable\n * install\": lurq stores advisories without affected-version ranges, so claiming\n * a specific resolved version is affected would be an inference we cannot back.\n * `advisoryPackages` is named for what it actually counts.\n */\nexport async function computeTransitiveDrift(\n db: Database,\n resolved: ResolvedDep[],\n directNames: Set<string>,\n truncated: boolean,\n edges: DependencyEdge[] = [],\n): Promise<TransitiveDrift> {\n const transitives = resolved.filter((dep) => !directNames.has(dep.name));\n const attribution = buildAttribution(resolved, edges, directNames);\n const empty: TransitiveDrift = {\n resolved: transitives.length,\n tracked: 0,\n advisoryPackages: 0,\n deprecated: 0,\n risks: [],\n truncated,\n attributed: attribution.available,\n };\n if (transitives.length === 0) return empty;\n\n const indexed = await loadIndexed(db, [...new Set(transitives.map((d) => d.name))]);\n\n const risks: TransitiveRisk[] = [];\n let tracked = 0;\n for (const dep of transitives) {\n const row = indexed.get(dep.name);\n if (!row) continue; // untracked — no signal either way, never counted as clean\n tracked++;\n if (row.advisories === 0 && !row.deprecated) continue;\n risks.push({\n name: dep.name,\n version: dep.version,\n latest: row.latestVersion,\n advisories: row.advisories,\n deprecated: row.deprecated,\n pulledInBy: attribution.parentsOf.get(dep.name) ?? [],\n });\n }\n\n // Advisories outrank deprecation: one is a security signal, the other is a\n // maintenance one, and a capped list should keep the former.\n risks.sort(\n (a, b) =>\n b.advisories - a.advisories ||\n Number(b.deprecated) - Number(a.deprecated) ||\n a.name.localeCompare(b.name),\n );\n\n return {\n resolved: transitives.length,\n tracked,\n advisoryPackages: risks.filter((r) => r.advisories > 0).length,\n deprecated: risks.filter((r) => r.deprecated).length,\n risks: risks.slice(0, TRANSITIVE_DETAIL_CAP),\n truncated,\n attributed: attribution.available,\n };\n}\n\n/**\n * Peer/engine conflicts across the repo's tracked dependencies, evaluated at the\n * versions the index calls latest.\n *\n * Names are passed without pins on purpose. `assembleMembers` reads peers and\n * engines straight from the index for an unpinned name, so this costs one query;\n * pinning each dependency to its *resolved* version would instead fetch that\n * exact manifest from npm, one request per dependency, on every nightly scan of\n * every repo. The unpinned question is also the more useful one here — the\n * dashboard's job is to say whether the upgrades it is recommending land on a\n * stack that holds together.\n *\n * Capped like `deps`, and for a sharper reason. `resolveArchitectureCompat` emits\n * one conflict per PAIR of requirers of the same unpinned peer, so its output is\n * quadratic in that group's size. Its other caller is `compat`, which passes 2-5\n * packages; a repo passes every tracked direct dependency, and fifty plugins\n * disagreeing about one uninstalled peer is 1,225 rows. This result is persisted\n * whole into the `drift` JSONB column and re-served on every dashboard load, so\n * an unbounded array here is unbounded storage and an unbounded response.\n *\n * ponytail: conflicts in the CURRENT install (pinned versions) are the other half\n * and are not computed. Add them when the registry read can be amortised — a\n * `package_versions`-level peer/engine column would make it another single query.\n */\nasync function conflictsAtLatest(\n db: Database,\n names: string[],\n): Promise<CompatConflict[]> {\n if (names.length === 0) return [];\n const { members } = await assembleMembers(db, names);\n return resolveArchitectureCompat(members).slice(0, REPO_DRIFT_DETAIL_CAP);\n}\n\n/** Compute a repo's full drift summary from its manifests. */\nexport async function computeDrift(\n db: Database,\n manifests: RepoManifest[],\n resolvedTree: { deps: ResolvedDep[]; edges: DependencyEdge[]; truncated: boolean } | null = null,\n): Promise<RepoDrift> {\n const declared = declaredDeps(manifests);\n const names = [...declared.keys()];\n const directNames = new Set(names);\n const transitive = resolvedTree\n ? await computeTransitiveDrift(\n db,\n resolvedTree.deps,\n directNames,\n resolvedTree.truncated,\n resolvedTree.edges,\n )\n : null;\n\n if (names.length === 0) {\n return {\n depsDeclared: 0,\n depsTracked: 0,\n majorDrift: 0,\n anyDrift: 0,\n deprecated: 0,\n advisories: 0,\n deps: [],\n transitive,\n conflictsAtLatest: [],\n };\n }\n\n const [indexed, versions] = await Promise.all([\n loadIndexed(db, names),\n loadVersions(db, names),\n ]);\n\n const deps: DepDrift[] = [];\n for (const [name, entry] of declared) {\n const row = indexed.get(name);\n if (!row) continue; // untracked — counted via depsDeclared - depsTracked\n deps.push(depDrift(name, entry, row, versions.get(name) ?? []));\n }\n\n deps.sort((a, b) => severity(b) - severity(a) || a.name.localeCompare(b.name));\n\n // Tracked names only. An untracked one would send `assembleMembers` to the npm\n // registry for its manifest, turning a one-query check into one request per\n // unindexed dependency on every scan.\n const conflicts = await conflictsAtLatest(db, deps.map((d) => d.name));\n\n return {\n depsDeclared: declared.size,\n depsTracked: deps.length,\n majorDrift: deps.filter((d) => d.majorsBehind > 0).length,\n anyDrift: deps.filter(isBehind).length,\n deprecated: deps.filter((d) => d.deprecated).length,\n advisories: deps.reduce((sum, d) => sum + d.advisories, 0),\n deps: deps.slice(0, REPO_DRIFT_DETAIL_CAP),\n transitive,\n conflictsAtLatest: conflicts,\n };\n}\n","/**\n * Migration hop planning.\n *\n * Nobody upgrades react-router 6.9.2 → 8.1.0 in one edit. They go 6 → 7, get the\n * codebase green, then 7 → 8. The brief has to say that, because the ordering is\n * most of the work and a single 6→8 diff hides which breakage belongs to which\n * step.\n *\n * The hop list is NOT how breakage is decided. The direct `from → to` diff stays\n * authoritative for \"will my code break\": a symbol removed at 7 and restored at\n * 8 is not a breakage, and unioning per-hop removals would report it as one.\n * Hops answer a different question — *in what order do I do this* — and the two\n * are kept separate on purpose (see `briefUpgrade`).\n */\nimport semver from 'semver';\n\n/** Hops past this are a rewrite, not an upgrade; the brief says so rather than\n * fanning out a dozen surface extractions nobody will read. */\nexport const MAX_HOPS = 4;\n\n/**\n * The highest non-prerelease release of each major between `from` and `to`.\n *\n * Prereleases are excluded throughout: `semver.maxSatisfying` with\n * `includePrerelease: false` is what an install resolves to, and routing a\n * migration through an alpha nobody shipped would be actively misleading.\n */\nexport function planHops(versions: string[], from: string, to: string): string[] {\n if (!semver.valid(from) || !semver.valid(to)) return [];\n if (!semver.gt(to, from)) return [];\n\n const fromMajor = semver.major(from);\n const toMajor = semver.major(to);\n // Same major, or adjacent majors: the direct diff already IS the single hop.\n if (toMajor - fromMajor < 2) return [];\n\n const stops: string[] = [];\n for (let major = fromMajor + 1; major < toMajor; major++) {\n const best = semver.maxSatisfying(versions, `${major}.x`, { includePrerelease: false });\n // A major with no known release is a gap in our version timeline, not a\n // major that does not exist. Skipping it silently would claim a shorter\n // migration than the real one, so the caller reports `truncated` instead.\n if (best) stops.push(best);\n }\n\n const path = [from, ...stops, to];\n return path.length > MAX_HOPS + 1 ? [] : path;\n}\n\n/** Consecutive pairs of a hop path — the diffs actually worth computing. */\nexport function hopPairs(path: string[]): { fromVersion: string; toVersion: string }[] {\n const pairs: { fromVersion: string; toVersion: string }[] = [];\n for (let i = 0; i < path.length - 1; i++) {\n pairs.push({ fromVersion: path[i]!, toVersion: path[i + 1]! });\n }\n return pairs;\n}\n\n/**\n * True when the majors between `from` and `to` exceed what we will plan.\n * Surfaced so the brief can say \"too far to sequence\" rather than quietly\n * presenting a one-shot diff as the whole story.\n */\nexport function tooFarToSequence(from: string, to: string): boolean {\n if (!semver.valid(from) || !semver.valid(to)) return false;\n return semver.major(to) - semver.major(from) > MAX_HOPS;\n}\n","/**\n * Migration brief: for each dependency a repo is behind on, what does the\n * upgrade actually remove from the public API?\n *\n * This is the half of the answer that can be computed without the source. It\n * says \"react-router 6.9.2 → 8.1.0 removes 14 runtime exports\", which is a fact\n * about the packages. It deliberately does NOT say \"this breaks your code\" —\n * that requires knowing which of those 14 the repo references, and the reference\n * scan runs in the user's own CI where the source already is. The CI half feeds\n * the same symbols into `checkUpgradeOne` (src/surface/upgrade.ts) to narrow\n * `removesExports` down to `symbolsRemoved`.\n *\n * Wording matters here and is load-bearing: a brief that overclaims once gets\n * the whole gate switched off (§12 M3). Every field name says what was measured.\n */\nimport type { Database } from '../db/client';\nimport { handleDiffSurface } from '../mcp/surfaceHandlers';\nimport { loadVersions } from './drift';\nimport { hopPairs, planHops, tooFarToSequence } from './hops';\nimport type { DepDeclaration, DepDrift, RepoDrift } from './types';\n\n/**\n * What the diff established about an upgrade.\n * `removes-exports` — runtime exports disappear. Whether THIS repo calls them\n * is the CI half; on its own this is a real hazard signal.\n * `arity-changed` — nothing removed, but a signature took a different count.\n * `clean` — surfaces compared, nothing removed or re-shaped.\n * `unknown` — one or both surfaces are not extracted yet. Queued by the\n * diff call itself. NEVER folded into `clean`.\n */\nexport type UpgradeVerdict = 'removes-exports' | 'arity-changed' | 'clean' | 'unknown';\n\n/** One step of a multi-major migration. */\nexport interface UpgradeHop {\n fromVersion: string;\n toVersion: string;\n verdict: UpgradeVerdict;\n removed: string[];\n arityChanged: { path: string; from: number | null; to: number | null }[];\n}\n\nexport interface UpgradeBrief {\n package: string;\n fromVersion: string;\n toVersion: string;\n /**\n * Every manifest declaring this package. A monorepo needs all of them: bumping\n * only the root leaves the workspace pinned to the old major and the upgrade\n * half-applied, which typechecks locally and breaks on install.\n */\n declaredIn: DepDeclaration[];\n majorsBehind: number;\n advisories: number;\n deprecated: boolean;\n verdict: UpgradeVerdict;\n /** Runtime exports present in `from` and gone in `to`. */\n removed: string[];\n /** Exports whose parameter count changed — silent misbehaviour, not a crash. */\n arityChanged: { path: string; from: number | null; to: number | null }[];\n /** Removed type-only exports. Breaks `tsc`, never `node` — separated on purpose. */\n typeOnlyRemoved: string[];\n /** Exports newly marked `@deprecated` at the target version. */\n newlyDeprecated: string[];\n /** Why the answer is `unknown`, when it is. */\n inconclusive?: string;\n /**\n * The migration sequence, when the upgrade crosses two or more majors. Empty\n * for a single-major bump, where the direct diff already is the only hop.\n *\n * These do NOT determine breakage — the fields above do, from the direct\n * from→to diff. A symbol dropped at 7 and restored at 8 appears in a hop and\n * correctly does not appear in `removed`.\n */\n hops: UpgradeHop[];\n /** Set when the sequence could not be planned, and why. Never left implicit:\n * an absent hop list would otherwise read as \"this is a one-step upgrade\". */\n sequenceNote?: string;\n}\n\nexport interface RepoBrief {\n upgrades: UpgradeBrief[];\n /** Drifted deps not briefed because of the cap — reported, never silent. */\n omitted: number;\n /** Upgrades whose surfaces are still being extracted. */\n pending: number;\n}\n\n/** Diffs per brief. Each is two indexed reads, but a 200-dep monorepo would\n * otherwise fan out to 200 of them on a page load. */\nexport const BRIEF_CAP = 25;\n\n/** Deps worth briefing: something changed between what they run and what's current. */\nfunction briefable(dep: DepDrift): boolean {\n return Boolean(dep.resolved && dep.latest && dep.resolved !== dep.latest);\n}\n\n/**\n * Rank by consequence, so a cap keeps what matters. Advisories first — an\n * upgrade you must do outranks one you might want to.\n */\nfunction rank(dep: DepDrift): number {\n return dep.advisories * 1000 + dep.majorsBehind * 100 + (dep.deprecated ? 50 : 0);\n}\n\nfunction verdictOf(\n removed: string[],\n arityChanged: unknown[],\n inconclusive: string | undefined,\n): UpgradeVerdict {\n if (inconclusive) return 'unknown';\n if (removed.length > 0) return 'removes-exports';\n if (arityChanged.length > 0) return 'arity-changed';\n return 'clean';\n}\n\n/** Brief one upgrade. Reuses the `diff_surface` handler so there is exactly one\n * implementation of the diff — including its enqueue-on-miss behaviour. */\nexport async function briefUpgrade(\n db: Database,\n dep: DepDrift,\n knownVersions: string[] = [],\n): Promise<UpgradeBrief> {\n const base = {\n package: dep.name,\n fromVersion: dep.resolved!,\n toVersion: dep.latest!,\n declaredIn: dep.declaredIn,\n majorsBehind: dep.majorsBehind,\n advisories: dep.advisories,\n deprecated: dep.deprecated,\n };\n\n // The direct diff is authoritative for breakage. Hops below are sequencing.\n const diff = await handleDiffSurface(db, {\n package: dep.name,\n fromVersion: base.fromVersion,\n toVersion: base.toVersion,\n });\n\n const removed = diff.removed.map((s) => s.path);\n const inconclusive = 'inconclusive' in diff ? (diff.inconclusive as string) : undefined;\n\n const { hops, sequenceNote } = await planSequence(db, dep, base, knownVersions);\n\n return {\n ...base,\n verdict: verdictOf(removed, diff.arityChanged, inconclusive),\n removed,\n arityChanged: diff.arityChanged,\n typeOnlyRemoved: diff.typeOnlyRemoved,\n newlyDeprecated: diff.deprecated ?? [],\n hops,\n ...(inconclusive ? { inconclusive } : {}),\n ...(sequenceNote ? { sequenceNote } : {}),\n };\n}\n\n/** Diff each step of a multi-major migration, so the work can be ordered. */\nasync function planSequence(\n db: Database,\n dep: DepDrift,\n base: { fromVersion: string; toVersion: string },\n knownVersions: string[],\n): Promise<{ hops: UpgradeHop[]; sequenceNote?: string }> {\n if (dep.majorsBehind < 2) return { hops: [] };\n\n if (tooFarToSequence(base.fromVersion, base.toVersion)) {\n return {\n hops: [],\n sequenceNote: `${dep.majorsBehind} majors behind — too far to sequence automatically. Treat this as a migration, not an upgrade.`,\n };\n }\n\n const path = planHops(knownVersions, base.fromVersion, base.toVersion);\n if (path.length === 0) {\n return {\n hops: [],\n sequenceNote: 'Intermediate releases are missing from the index, so the hop sequence could not be planned.',\n };\n }\n\n const hops: UpgradeHop[] = [];\n for (const pair of hopPairs(path)) {\n const hopDiff = await handleDiffSurface(db, { package: dep.name, ...pair });\n const hopRemoved = hopDiff.removed.map((s) => s.path);\n hops.push({\n ...pair,\n verdict: verdictOf(\n hopRemoved,\n hopDiff.arityChanged,\n 'inconclusive' in hopDiff ? (hopDiff.inconclusive as string) : undefined,\n ),\n removed: hopRemoved,\n arityChanged: hopDiff.arityChanged,\n });\n }\n return { hops };\n}\n\n/** Brief a repo's outstanding upgrades, worst-first. */\nexport async function briefRepo(\n db: Database,\n drift: RepoDrift | null,\n limit = BRIEF_CAP,\n): Promise<RepoBrief> {\n if (!drift) return { upgrades: [], omitted: 0, pending: 0 };\n\n const candidates = drift.deps.filter(briefable).sort((a, b) => rank(b) - rank(a));\n const selected = candidates.slice(0, Math.min(limit, BRIEF_CAP));\n\n // Sequential: each diff can enqueue an extraction, and a burst of parallel\n // misses on a fresh repo would queue the same specs from several callers at\n // once. There is no user-visible latency budget on a brief.\n // One version query for the whole brief rather than one per upgrade: hop\n // planning needs each package's release timeline, and 25 round trips on a\n // page load is the kind of cost that only shows up under real accounts.\n const versions = await loadVersions(db, selected.map((d) => d.name));\n\n const upgrades: UpgradeBrief[] = [];\n for (const dep of selected) {\n upgrades.push(await briefUpgrade(db, dep, versions.get(dep.name) ?? []));\n }\n\n // Hazards first, then unknowns — an unextracted surface should sit above a\n // clean one, because \"we haven't looked\" is a more actionable state than \"fine\".\n const order: Record<UpgradeVerdict, number> = {\n 'removes-exports': 0,\n 'arity-changed': 1,\n unknown: 2,\n clean: 3,\n };\n upgrades.sort(\n (a, b) => order[a.verdict] - order[b.verdict] || b.removed.length - a.removed.length,\n );\n\n return {\n upgrades,\n omitted: candidates.length - selected.length,\n pending: upgrades.filter((u) => u.verdict === 'unknown').length,\n };\n}\n","/**\n * Validation for CI-reported upgrade runs.\n *\n * This is a trust boundary: the payload comes from a workflow running on a\n * machine we do not control, authenticated only by an API key. Everything is\n * parsed rather than trusted, unknown fields are dropped, and every string is\n * length-capped so a malformed (or hostile) post cannot write unbounded data.\n *\n * `ownerId` and `repoId` are NOT parsed here — the caller injects them from the\n * authenticated key. A payload that could name its own owner would let any key\n * write rows against any account.\n */\nimport {\n UPGRADE_RUN_STATUSES,\n UPGRADE_SEVERITIES,\n type UpgradeRunStatus,\n type UpgradeSeverity,\n} from './types';\n\n/** Package names, versions, and repo slugs are all short; paths can be longer. */\nconst MAX_NAME = 214; // npm's own package-name limit\nconst MAX_VERSION = 64;\nconst MAX_URL = 500;\nconst MAX_SYMBOLS = 200;\nconst MAX_FILES = 100;\nconst MAX_PATH = 400;\n\nexport interface ParsedUpgradeRun {\n repoFullName: string;\n packageName: string;\n fromVersion: string;\n toVersion: string;\n severity: UpgradeSeverity;\n status: UpgradeRunStatus;\n symbolsAffected: string[];\n callSites: number;\n callSiteFiles: string[] | null;\n filesChanged: number | null;\n testsPassed: boolean | null;\n prUrl: string | null;\n runUrl: string;\n}\n\nfunction str(value: unknown, max: number): string | null {\n if (typeof value !== 'string') return null;\n const trimmed = value.trim();\n return trimmed ? trimmed.slice(0, max) : null;\n}\n\nfunction strList(value: unknown, maxItems: number, maxLen: number): string[] {\n if (!Array.isArray(value)) return [];\n const out: string[] = [];\n for (const item of value) {\n const parsed = str(item, maxLen);\n if (parsed) out.push(parsed);\n if (out.length >= maxItems) break;\n }\n return out;\n}\n\n/** Non-negative integers only; anything else becomes null rather than NaN. */\nfunction count(value: unknown): number | null {\n const n = typeof value === 'number' ? value : Number(value);\n return Number.isInteger(n) && n >= 0 && n < 1_000_000 ? n : null;\n}\n\n/** Parse one reported run, or null when it is unusable. */\nexport function parseUpgradeRun(input: unknown): ParsedUpgradeRun | null {\n if (!input || typeof input !== 'object') return null;\n const raw = input as Record<string, unknown>;\n\n const repoFullName = str(raw.repoFullName, MAX_NAME);\n const packageName = str(raw.packageName, MAX_NAME);\n const fromVersion = str(raw.fromVersion, MAX_VERSION);\n const toVersion = str(raw.toVersion, MAX_VERSION);\n if (!repoFullName || !packageName || !fromVersion || !toVersion) return null;\n\n const severity = UPGRADE_SEVERITIES.find((s) => s === raw.severity);\n const status = UPGRADE_RUN_STATUSES.find((s) => s === raw.status);\n if (!severity || !status) return null;\n\n // Absent means \"not shared\", which is different from \"no files\" — keep null so\n // the dashboard can tell a repo that opted out from one with nothing to report.\n const files = raw.callSiteFiles === undefined ? null : strList(raw.callSiteFiles, MAX_FILES, MAX_PATH);\n\n return {\n repoFullName,\n packageName,\n fromVersion,\n toVersion,\n severity,\n status,\n symbolsAffected: strList(raw.symbolsAffected, MAX_SYMBOLS, MAX_NAME),\n callSites: count(raw.callSites) ?? 0,\n callSiteFiles: files,\n filesChanged: count(raw.filesChanged),\n testsPassed: typeof raw.testsPassed === 'boolean' ? raw.testsPassed : null,\n prUrl: str(raw.prUrl, MAX_URL),\n // Empty string, not null: it is part of the dedup key (see schema).\n runUrl: str(raw.runUrl, MAX_URL) ?? '',\n };\n}\n\n/** Parse a batch, dropping unusable entries and reporting how many were dropped. */\nexport function parseUpgradeRuns(\n input: unknown,\n max: number,\n): { runs: ParsedUpgradeRun[]; rejected: number } {\n if (!Array.isArray(input)) return { runs: [], rejected: 0 };\n const runs: ParsedUpgradeRun[] = [];\n let rejected = 0;\n for (const item of input.slice(0, max)) {\n const parsed = parseUpgradeRun(item);\n if (parsed) runs.push(parsed);\n else rejected++;\n }\n return { runs, rejected };\n}\n\n/** Declared dependency ranges posted by the CLI for a plan. */\nexport function parseDepsInput(input: unknown): Record<string, string> {\n if (!input || typeof input !== 'object') return {};\n const out: Record<string, string> = {};\n for (const [name, range] of Object.entries(input as Record<string, unknown>)) {\n const key = str(name, MAX_NAME);\n const value = str(range, MAX_VERSION);\n if (key && value) out[key] = value;\n // A manifest with more entries than this is not a real project's direct\n // dependency list; stop rather than fan out unbounded index lookups.\n if (Object.keys(out).length >= 1000) break;\n }\n return out;\n}\n","/**\n * Read/write helpers for `upgrade_runs`.\n *\n * Writes come from users' CI through an API key, so `ownerId` is always resolved\n * from the authenticated key and never read off the request body. Reads are\n * owner-scoped for the same reason as `db/repos.ts`.\n */\nimport { and, desc, eq, gte, sql } from 'drizzle-orm';\nimport type { Database } from './client';\nimport { repos, upgradeRuns, type NewUpgradeRunRow, type UpgradeRunRow } from './schema';\n\n/** Cap on a single CI post. A run that proposes more than this is misconfigured,\n * not ambitious, and the limit keeps one request from writing unbounded rows. */\nexport const MAX_RUNS_PER_POST = 100;\n\n/**\n * Insert or refresh the rows for one Actions run.\n *\n * Upserts on the dedup key so a retried job updates its rows in place. Without\n * that, re-running a failed workflow would double every figure the impact view\n * reports — the most likely way for these numbers to quietly become wrong.\n */\nexport async function recordUpgradeRuns(\n db: Database,\n rows: NewUpgradeRunRow[],\n): Promise<number> {\n if (rows.length === 0) return 0;\n await db\n .insert(upgradeRuns)\n .values(rows)\n .onConflictDoUpdate({\n target: [\n upgradeRuns.ownerId,\n upgradeRuns.repoFullName,\n upgradeRuns.packageName,\n upgradeRuns.toVersion,\n upgradeRuns.runUrl,\n ],\n set: {\n severity: sql`excluded.severity`,\n status: sql`excluded.status`,\n symbolsAffected: sql`excluded.symbols_affected`,\n callSites: sql`excluded.call_sites`,\n callSiteFiles: sql`excluded.call_site_files`,\n filesChanged: sql`excluded.files_changed`,\n testsPassed: sql`excluded.tests_passed`,\n prUrl: sql`excluded.pr_url`,\n repoId: sql`excluded.repo_id`,\n },\n });\n return rows.length;\n}\n\n/** Resolve `owner/name` to a connected repo id, or null when it isn't connected. */\nexport async function findRepoIdByFullName(\n db: Database,\n ownerId: string,\n fullName: string,\n): Promise<number | null> {\n const rows = await db\n .select({ id: repos.id })\n .from(repos)\n .where(and(eq(repos.ownerId, ownerId), eq(repos.fullName, fullName)))\n .limit(1);\n return rows[0]?.id ?? null;\n}\n\nexport async function listRunsForRepo(\n db: Database,\n ownerId: string,\n repoId: number,\n limit = 50,\n): Promise<UpgradeRunRow[]> {\n return db\n .select()\n .from(upgradeRuns)\n .where(and(eq(upgradeRuns.ownerId, ownerId), eq(upgradeRuns.repoId, repoId)))\n .orderBy(desc(upgradeRuns.createdAt))\n .limit(limit);\n}\n\nexport interface UpgradeImpact {\n /** Upgrades analysed in the window. */\n analysed: number;\n /** Upgrades where a referenced symbol disappears — caught before merge. */\n blocking: number;\n /** Referenced call sites those upgrades would have broken. */\n callSites: number;\n prsOpened: number;\n merged: number;\n /** Analysed but not conclusively checked. Reported, never folded into \"clean\". */\n unverified: number;\n}\n\n/**\n * Impact totals for the dashboard.\n *\n * One aggregate query rather than pulling rows and reducing in JS: this is the\n * figure on the overview, and it should stay O(1) work for the web tier no\n * matter how many runs an account accumulates.\n */\nexport async function getUpgradeImpact(\n db: Database,\n ownerId: string,\n days = 30,\n): Promise<UpgradeImpact> {\n const since = new Date(Date.now() - days * 86_400_000);\n const rows = await db\n .select({\n analysed: sql<number>`count(*)::int`,\n blocking: sql<number>`count(*) filter (where ${upgradeRuns.severity} = 'blocking')::int`,\n callSites: sql<number>`coalesce(sum(${upgradeRuns.callSites}) filter (where ${upgradeRuns.severity} = 'blocking'), 0)::int`,\n prsOpened: sql<number>`count(*) filter (where ${upgradeRuns.status} in ('pr_open','merged'))::int`,\n merged: sql<number>`count(*) filter (where ${upgradeRuns.status} = 'merged')::int`,\n unverified: sql<number>`count(*) filter (where ${upgradeRuns.severity} = 'unverified')::int`,\n })\n .from(upgradeRuns)\n .where(and(eq(upgradeRuns.ownerId, ownerId), gte(upgradeRuns.createdAt, since)));\n\n return (\n rows[0] ?? {\n analysed: 0,\n blocking: 0,\n callSites: 0,\n prsOpened: 0,\n merged: 0,\n unverified: 0,\n }\n );\n}\n","/**\n * The workflow file a user commits to arm the autopilot.\n *\n * Note what the analysis half costs: nothing but a lurq key. Planning the\n * upgrades and checking them against the codebase are plain CLI steps, so a repo\n * gets the full drift + breakage brief without any Anthropic credential at all.\n * That is only needed once someone switches the job to `pr` mode and wants code\n * actually rewritten — and then either an API key or an existing Claude\n * Pro/Max subscription token will do.\n *\n * Read the `permissions:` block first — it is the entire trust model. lurq's own\n * GitHub App is Contents:read-only and can never write to anyone's repository.\n * Every write in this loop is done by GitHub's own `GITHUB_TOKEN`: ephemeral,\n * scoped to the one repo, and limited to exactly what this file declares. The\n * user owns the file, so revoking the autopilot is `git rm`.\n *\n * Two more guardrails are structural rather than advisory:\n * · the agent's tool allowlist has no `git` and no network tool, so the model\n * edits files and the *workflow* does version control — a prompt injection\n * in a dependency's changelog cannot push a branch;\n * · the job defaults to `comment` mode, which analyses and reports without\n * touching a line. Editing is opt-in per repository.\n */\n\nexport interface WorkflowOptions {\n /** Cron schedule. Default: Mondays 06:00 UTC. */\n cron?: string;\n /** Start in `pr` mode instead of the analyse-only default. */\n armed?: boolean;\n /** Package manager install command, detected from the lockfile. */\n installCommand?: string;\n /** Max upgrades attempted per run — the blast-radius cap. */\n maxUpgrades?: number;\n}\n\nexport const WORKFLOW_PATH = '.github/workflows/lurq-upgrade.yml';\n\nconst DEFAULT_CRON = '0 6 * * 1';\n\n/** Lockfile → install command. `npm ci` needs a lockfile, so fall back to install. */\nexport function detectInstallCommand(lockfiles: string[]): string {\n if (lockfiles.includes('pnpm-lock.yaml')) return 'pnpm install --frozen-lockfile';\n if (lockfiles.includes('yarn.lock')) return 'yarn install --frozen-lockfile';\n if (lockfiles.includes('bun.lockb') || lockfiles.includes('bun.lock')) return 'bun install';\n if (lockfiles.includes('package-lock.json')) return 'npm ci';\n return 'npm install';\n}\n\nexport function renderWorkflow(opts: WorkflowOptions = {}): string {\n const cron = opts.cron ?? DEFAULT_CRON;\n const install = opts.installCommand ?? 'npm ci';\n const max = opts.maxUpgrades ?? 3;\n const mode = opts.armed ? 'pr' : 'comment';\n\n return `# Managed by lurq — https://lurq.run\n#\n# Keeps this repository's dependencies current and rewrites the call sites an\n# upgrade breaks. lurq itself has read-only access to your code; every write\n# below is made by this workflow's own GITHUB_TOKEN, scoped by the permissions\n# block. Delete this file to turn the autopilot off.\nname: lurq upgrade\n\non:\n schedule:\n - cron: \"${cron}\"\n workflow_dispatch:\n inputs:\n mode:\n description: \"comment = analyse only · pr = open pull requests\"\n type: choice\n options: [comment, pr]\n default: ${mode}\n\n# The blast radius. \\`contents: write\\` permits pushing a BRANCH; branch\n# protection on your default branch is what stops anything landing unreviewed.\npermissions:\n contents: write\n pull-requests: write\n\nconcurrency:\n group: lurq-upgrade-\\${{ github.ref }}\n cancel-in-progress: true\n\njobs:\n upgrade:\n runs-on: ubuntu-latest\n env:\n LURQ_MODE: \\${{ inputs.mode || vars.LURQ_MODE || '${mode}' }}\n MAX_UPGRADES: \"${max}\"\n steps:\n - uses: actions/checkout@v6\n\n - uses: actions/setup-node@v4\n with:\n node-version: 22\n\n # 1. What is behind, and what does each upgrade remove from its API?\n # Sends only the dependency ranges already public in package.json.\n - name: Plan\n env:\n LURQ_API_KEY: \\${{ secrets.LURQ_API_KEY }}\n run: npx -y lurqrun upgrade-plan . --json > lurq-plan.json\n\n # 2. Narrow that to symbols THIS repo references. Runs entirely locally\n # against both versions' npm tarballs — no API key, no test suite.\n - name: Check against this codebase\n run: npx -y lurqrun check-upgrade . --plan lurq-plan.json --json > lurq-brief.json\n\n # The same report twice: once into the run summary, once as the body of\n # the pull request. Fenced, because the report is aligned plain text and\n # markdown would otherwise collapse its indentation into one paragraph.\n - name: Summarise\n run: |\n npx -y lurqrun check-upgrade . --plan lurq-plan.json > lurq-report.txt\n { echo '\\`\\`\\`'; cat lurq-report.txt; echo '\\`\\`\\`'; } > lurq-report.md\n cat lurq-report.md >> \"$\\{GITHUB_STEP_SUMMARY}\"\n\n # 3. Editing is opt-in. Until LURQ_MODE is 'pr', the job stops here having\n # changed nothing — the brief is in the run summary above, and no\n # Anthropic credential is needed to get this far.\n - name: Check agent credentials\n if: env.LURQ_MODE == 'pr'\n env:\n API_KEY: \\${{ secrets.ANTHROPIC_API_KEY }}\n OAUTH_TOKEN: \\${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}\n run: |\n if [ -z \"$API_KEY\" ] && [ -z \"$OAUTH_TOKEN\" ]; then\n echo \"::error::pr mode needs one of ANTHROPIC_API_KEY or CLAUDE_CODE_OAUTH_TOKEN in this repository's secrets. A Claude Pro/Max subscription token works for the latter. Set LURQ_MODE=comment to run analysis only.\"\n exit 1\n fi\n\n - name: Install dependencies\n if: env.LURQ_MODE == 'pr'\n run: ${install}\n\n - name: Apply upgrades\n if: env.LURQ_MODE == 'pr'\n uses: anthropics/claude-code-action@v1\n with:\n # Either credential works; set whichever you have. An API key bills\n # per token, an OAuth token uses an existing Claude Pro/Max plan.\n # Unset secrets resolve to empty and are ignored by the action.\n anthropic_api_key: \\${{ secrets.ANTHROPIC_API_KEY }}\n claude_code_oauth_token: \\${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}\n prompt: |\n REPO: \\${{ github.repository }}\n\n lurq-brief.json lists dependency upgrades this repository is behind\n on. For each entry under \"breaking\", the \"symbolsRemoved\" array names\n exports that DISAPPEAR at the target version, and each carries the\n exact file and line where this repository uses it.\n\n lurq-plan.json carries two more things per upgrade:\n · \"declaredIn\" — EVERY package.json declaring that dependency.\n Bump all of them. Bumping only the root leaves a workspace\n pinned to the old major, which typechecks and breaks on install.\n · \"hops\" — the migration sequence when the upgrade crosses two or\n more majors, with what each step removes. Work the steps in\n order; do not jump straight to the target version. When\n \"sequenceNote\" is present, the sequence could not be planned —\n treat that dependency as a migration and skip it.\n\n Take at most \\${{ env.MAX_UPGRADES }} entries, hardest first:\n\n 1. Bump the dependency's range in every manifest listed in\n \"declaredIn\".\n 2. Run \\`${install.split(' ')[0]} install\\` so node_modules holds the\n TARGET version. Until you do, the package on disk is the old one\n and anything you read from it describes the API you are leaving.\n 3. Rewrite every listed call site. \"newExports\" on each entry names\n the exports the target version ADDED, extracted from its shipped\n JavaScript — that is where the replacement for a removed symbol\n comes from. Confirm each one against the freshly installed package\n under node_modules before you call it. You have NO network access\n and no documentation: an API in neither the brief nor node_modules\n is one you cannot verify, and writing it anyway is the failure\n this whole job exists to prevent. Revert that dependency instead.\n 4. Run the repository's test script. If it fails and you cannot fix\n it from the upgrade itself, revert that dependency and move on —\n a reverted upgrade is a fine outcome, a broken build is not.\n 5. Leave the working tree with only the upgrades that pass.\n\n Do not touch unrelated files. Do not change CI configuration. Do not\n run git commands — the workflow handles version control.\n claude_args: |\n --allowedTools \"Read,Edit,Write,Bash(${install.split(' ')[0]}:*)\"\n\n # 4. The workflow does version control, never the model.\n - name: Open pull request\n if: env.LURQ_MODE == 'pr'\n uses: peter-evans/create-pull-request@v7\n with:\n branch: lurq/upgrades\n title: \"chore(deps): lurq dependency upgrades\"\n commit-message: \"chore(deps): upgrade dependencies and migrate call sites\"\n # The rendered report, not the raw JSON. A reviewer opening this PR\n # reads what was removed and where it is used; the JSON is the agent's\n # input, and pasting it here made the case for the change unreadable.\n body-path: lurq-report.md\n labels: dependencies\n delete-branch: true\n`;\n}\n\n/**\n * GitHub's prefilled new-file URL. The dashboard links here instead of lurq\n * opening the PR itself — the user sees the exact file before committing it, and\n * lurq keeps zero write scope.\n */\nexport function newFileUrl(fullName: string, branch: string, content: string): string {\n const params = new URLSearchParams({ filename: WORKFLOW_PATH, value: content });\n return `https://github.com/${fullName}/new/${encodeURIComponent(branch)}?${params.toString()}`;\n}\n","/**\n * Repo inventory + manifest reading.\n *\n * Everything here reads exactly two things from a repository: the list of repos\n * the installation covers, and the dependency blocks of its `package.json`\n * files. File *names* come along in the tree listing — that is how the package\n * manager is detected — but no lockfile, source file, or history is ever read.\n * That is not a limitation we plan to lift server-side: the code-reading half of\n * the product runs in the user's own CI.\n */\nimport { installationGet } from './app';\nimport { detectInstallCommand } from './workflow';\nimport { REPO_MANIFEST_CAP, type RepoManifest } from './types';\nimport { logger } from '../core/logger';\n\nexport interface InstallationRepo {\n fullName: string;\n defaultBranch: string;\n isPrivate: boolean;\n}\n\ninterface ReposResponse {\n repositories?: { full_name: string; default_branch: string; private: boolean }[];\n}\n\n/** GitHub caps `per_page` at 100 for this endpoint. */\nconst PAGE_SIZE = 100;\n/** Stop paginating here. 20 pages = 2000 repos; past that the connect flow needs\n * repo selection in the UI, not a bigger loop. */\nconst MAX_PAGES = 20;\n\n/** Every repo the user granted the installation access to. */\nexport async function listInstallationRepos(\n installationId: number,\n): Promise<InstallationRepo[]> {\n const out: InstallationRepo[] = [];\n for (let page = 1; page <= MAX_PAGES; page++) {\n const data = await installationGet<ReposResponse>(\n installationId,\n `/installation/repositories?per_page=${PAGE_SIZE}&page=${page}`,\n );\n const batch = data.repositories ?? [];\n for (const repo of batch) {\n out.push({\n fullName: repo.full_name,\n defaultBranch: repo.default_branch,\n isPrivate: repo.private,\n });\n }\n if (batch.length < PAGE_SIZE) break;\n }\n return out;\n}\n\ninterface TreeResponse {\n tree?: { path: string; type: string }[];\n truncated?: boolean;\n}\n\ninterface ContentsResponse {\n content?: string;\n encoding?: string;\n}\n\n/**\n * Paths of every `package.json` in the repo, root first.\n *\n * One recursive tree call instead of guessing workspace globs: it costs the same\n * as reading the root manifest alone, and it is the only way to find the real\n * layout of a monorepo without parsing `workspaces` patterns (which can be\n * globs, arrays, or a pnpm YAML file we would then also have to read).\n */\nexport function manifestPaths(tree: { path: string; type: string }[]): string[] {\n return tree\n .filter(\n (node) =>\n node.type === 'blob' &&\n (node.path === 'package.json' || node.path.endsWith('/package.json')) &&\n // A committed node_modules is rare but real, and its manifests are not\n // this project's dependencies — counting them would invent drift.\n !node.path.split('/').includes('node_modules'),\n )\n .sort((a, b) => a.path.split('/').length - b.path.split('/').length)\n .map((node) => node.path);\n}\n\n/** Merge `dependencies` + `devDependencies`, dropping non-registry specifiers. */\nexport function parseManifest(path: string, json: unknown): RepoManifest | null {\n if (!json || typeof json !== 'object') return null;\n const pkg = json as Record<string, unknown>;\n const deps: Record<string, string> = {};\n for (const block of ['dependencies', 'devDependencies']) {\n const entry = pkg[block];\n if (!entry || typeof entry !== 'object') continue;\n for (const [name, range] of Object.entries(entry as Record<string, unknown>)) {\n if (typeof range !== 'string') continue;\n // `file:`, `link:`, `workspace:`, `git+…`, and bare URLs never resolve to a\n // registry version, so they have no drift to report. Including them would\n // pad `depsDeclared` with rows that can only ever read \"unknown\".\n if (/^(file|link|workspace|git|github|https?|portal):/i.test(range)) continue;\n if (range.includes('/') && !range.startsWith('>') && !range.startsWith('<')) continue;\n deps[name] = range;\n }\n }\n return Object.keys(deps).length > 0 ? { path, deps } : null;\n}\n\nexport interface ManifestScan {\n manifests: RepoManifest[];\n /** Install command for the repo's actual package manager, from its lockfile. */\n installCommand: string;\n /** True when the repo has more manifests than we read, or GitHub truncated the\n * tree. The dashboard says \"partial\" rather than reporting a low count as\n * complete — an undercount that looks authoritative is worse than a caveat. */\n partial: boolean;\n}\n\n/** Read every dependency block in a repo. */\nexport async function fetchManifests(\n installationId: number,\n fullName: string,\n branch: string,\n): Promise<ManifestScan> {\n const tree = await installationGet<TreeResponse>(\n installationId,\n `/repos/${fullName}/git/trees/${encodeURIComponent(branch)}?recursive=1`,\n );\n const nodes = tree.tree ?? [];\n const allPaths = manifestPaths(nodes);\n // Root-level lockfiles only: a nested one belongs to a workspace, not to the\n // command that installs the whole repo.\n const lockfiles = nodes.filter((n) => !n.path.includes('/')).map((n) => n.path);\n const paths = allPaths.slice(0, REPO_MANIFEST_CAP);\n\n const manifests: RepoManifest[] = [];\n for (const path of paths) {\n try {\n const res = await installationGet<ContentsResponse>(\n installationId,\n `/repos/${fullName}/contents/${path.split('/').map(encodeURIComponent).join('/')}?ref=${encodeURIComponent(branch)}`,\n );\n if (!res.content || res.encoding !== 'base64') continue;\n const parsed = parseManifest(\n path,\n JSON.parse(Buffer.from(res.content, 'base64').toString('utf8')),\n );\n if (parsed) manifests.push(parsed);\n } catch (err) {\n // One malformed or unreadable manifest must not fail the whole repo scan —\n // the other workspaces still have real drift worth reporting.\n logger.debug(`manifest read failed for ${fullName}/${path}: ${(err as Error).message}`);\n }\n }\n\n return {\n manifests,\n installCommand: detectInstallCommand(lockfiles),\n partial: Boolean(tree.truncated) || allPaths.length > paths.length,\n };\n}\n","/**\n * Resolved dependency tree, via GitHub's dependency-graph SBOM.\n *\n * Everything else in this product reads declared ranges from `package.json`,\n * which makes the whole transitive tree invisible — and transitives are where\n * most advisories actually live. A repo can read \"0 advisories\" while shipping a\n * known-vulnerable package four levels down.\n *\n * We do NOT parse lockfiles to fix that. There are five formats across npm v1–v3,\n * yarn classic and berry, pnpm, and bun (binary), they run to megabytes, and\n * GitHub already resolves all of them into one SPDX document. One authenticated\n * call replaces a parser suite we would then own forever.\n *\n * The cost is a dependency on a repo feature: the dependency graph is on by\n * default for public repos but opt-in for private ones. A repo without it gets\n * `null`, reported as \"not available\" — never as \"no transitive risk\".\n */\nimport { HttpError } from '../core/http';\nimport { installationGet } from './app';\nimport { GithubAppError } from './app';\n\n/** One node of the resolved tree. */\nexport interface ResolvedDep {\n name: string;\n version: string;\n /** SPDX element id, the key the relationship edges are expressed in. */\n spdxId?: string;\n}\n\ninterface SpdxPackage {\n SPDXID?: string;\n name?: string;\n versionInfo?: string;\n externalRefs?: { referenceType?: string; referenceLocator?: string }[];\n}\n\ninterface SpdxRelationship {\n spdxElementId?: string;\n relationshipType?: string;\n relatedSpdxElement?: string;\n}\n\ninterface SbomResponse {\n sbom?: { packages?: SpdxPackage[]; relationships?: SpdxRelationship[] };\n}\n\n/** `parent DEPENDS_ON child`, in SPDX element ids. */\nexport interface DependencyEdge {\n parent: string;\n child: string;\n}\n\n/**\n * A real tree runs to a few thousand nodes; past this the repo is a monorepo of\n * monorepos and the summary is what matters, not the list. Reported, not silent.\n */\nexport const SBOM_NODE_CAP = 5000;\n\n/**\n * Parse an npm package identity out of a Package URL.\n *\n * Scoped names are the whole difficulty: producers emit `pkg:npm/%40babel/core`\n * (correctly percent-encoded) and `pkg:npm/@babel/core` (not) interchangeably,\n * and the version separator is the LAST `@`, which a naive split gets wrong for\n * every scoped package.\n */\nexport function parseNpmPurl(purl: string): ResolvedDep | null {\n if (!purl.startsWith('pkg:npm/')) return null;\n let body = purl.slice('pkg:npm/'.length);\n\n // Drop qualifiers and subpath: `pkg:npm/foo@1.0.0?arch=x64#sub`.\n const cut = body.search(/[?#]/);\n if (cut !== -1) body = body.slice(0, cut);\n\n const at = body.lastIndexOf('@');\n // `@` at index 0 is a scope marker, not a version separator.\n if (at <= 0) return null;\n\n const name = decodeURIComponent(body.slice(0, at));\n const version = decodeURIComponent(body.slice(at + 1));\n if (!name || !version) return null;\n return { name, version };\n}\n\n/** Extract every npm node from an SPDX document, deduped by name@version. */\nexport function parseSbom(json: unknown): ResolvedDep[] {\n const packages = (json as SbomResponse)?.sbom?.packages;\n if (!Array.isArray(packages)) return [];\n\n const seen = new Set<string>();\n const out: ResolvedDep[] = [];\n\n for (const pkg of packages) {\n const purl = pkg.externalRefs?.find((ref) => ref.referenceType === 'purl')?.referenceLocator;\n // The purl is authoritative. `name` is a display string whose format varies\n // by producer (\"npm:lodash\", \"lodash\"), so it is only a fallback — and then\n // only when `versionInfo` supplies the version the purl would have carried.\n const parsed = purl\n ? parseNpmPurl(purl)\n : pkg.name?.startsWith('npm:') && pkg.versionInfo\n ? { name: pkg.name.slice(4), version: pkg.versionInfo }\n : null;\n if (!parsed) continue;\n\n const key = `${parsed.name}@${parsed.version}`;\n if (seen.has(key)) continue;\n seen.add(key);\n out.push({ ...parsed, ...(pkg.SPDXID ? { spdxId: pkg.SPDXID } : {}) });\n if (out.length >= SBOM_NODE_CAP) break;\n }\n\n return out;\n}\n\n/**\n * `DEPENDS_ON` edges, the raw material for attributing a transitive back to the\n * direct dependency that pulls it in.\n *\n * GitHub does not guarantee a nested tree here — some documents carry only\n * `DESCRIBES` from the root, which yields no useful parentage at all. That is\n * why callers check whether any edges came back rather than assuming they did:\n * \"we could not attribute this\" and \"nothing depends on this\" are different\n * claims, and only the first one is ever true.\n */\nexport function parseRelationships(json: unknown): DependencyEdge[] {\n const relationships = (json as SbomResponse)?.sbom?.relationships;\n if (!Array.isArray(relationships)) return [];\n const out: DependencyEdge[] = [];\n for (const rel of relationships) {\n if (rel.relationshipType !== 'DEPENDS_ON') continue;\n if (!rel.spdxElementId || !rel.relatedSpdxElement) continue;\n out.push({ parent: rel.spdxElementId, child: rel.relatedSpdxElement });\n }\n return out;\n}\n\nexport interface SbomResult {\n deps: ResolvedDep[];\n edges: DependencyEdge[];\n /** True when the tree hit SBOM_NODE_CAP and is therefore incomplete. */\n truncated: boolean;\n}\n\n/**\n * Fetch the resolved tree, or null when the repo has no dependency graph.\n *\n * A 403 here means the feature is disabled for that repository, which is a\n * normal state and not an error — callers surface it as \"not available\" so the\n * dashboard never implies a clean tree it did not actually see.\n */\nexport async function fetchResolvedTree(\n installationId: number,\n fullName: string,\n): Promise<SbomResult | null> {\n try {\n const data = await installationGet<SbomResponse>(\n installationId,\n `/repos/${fullName}/dependency-graph/sbom`,\n );\n const deps = parseSbom(data);\n return {\n deps,\n edges: parseRelationships(data),\n truncated: deps.length >= SBOM_NODE_CAP,\n };\n } catch (err) {\n const status =\n err instanceof HttpError ? err.status : err instanceof GithubAppError ? err.status : 0;\n // 403: dependency graph disabled. 404: repo gone, or the endpoint is not\n // enabled for this installation. Neither is worth failing a scan over — the\n // direct-dependency drift above it is still correct and useful.\n if (status === 403 || status === 404) return null;\n throw err;\n }\n}\n","/**\n * Repo scan: read manifests from GitHub, compute drift against the index, store\n * the summary.\n *\n * Runs on connect, on demand from the dashboard, and once a day from the sync\n * cron. Scans are independent per repo and a failure is recorded rather than\n * thrown, so one archived or permission-revoked repository cannot stop the\n * nightly pass for everything else the user connected.\n *\n * Cost note: a scan is 1 tree call + N content calls per repo, no clone and no\n * npm traffic — the version data it diffs against is already in our own index.\n */\nimport { logger } from '../core/logger';\nimport type { Database } from '../db/client';\nimport { listAllRepos, listRepos, saveScan, saveScanError } from '../db/repos';\nimport type { RepoRow } from '../db/schema';\nimport { GithubAppError } from '../github/app';\nimport { computeDrift } from '../github/drift';\nimport { fetchManifests } from '../github/manifests';\nimport { fetchResolvedTree } from '../github/sbom';\n\nexport interface ScanResult {\n repoId: number;\n fullName: string;\n ok: boolean;\n depsTracked: number;\n majorDrift: number;\n partial: boolean;\n /** False when the repo has no dependency graph, so transitives were not read. */\n transitivesRead: boolean;\n error?: string;\n}\n\n/** Scan one repo. Never throws — failures land in `lastScanError`. */\nexport async function scanRepo(db: Database, repo: RepoRow): Promise<ScanResult> {\n const base = { repoId: repo.id, fullName: repo.fullName };\n try {\n const branch = repo.defaultBranch ?? 'main';\n const { manifests, installCommand, partial } = await fetchManifests(\n repo.installationId,\n repo.fullName,\n branch,\n );\n // The resolved tree is where most advisories actually live, but it depends\n // on a repo feature that may be off. A null result degrades to\n // direct-dependency-only drift rather than failing the scan.\n const resolvedTree = await fetchResolvedTree(repo.installationId, repo.fullName);\n const drift = await computeDrift(db, manifests, resolvedTree);\n await saveScan(db, repo.id, { manifests, drift, installCommand });\n return {\n ...base,\n ok: true,\n depsTracked: drift.depsTracked,\n majorDrift: drift.majorDrift,\n partial,\n transitivesRead: resolvedTree !== null,\n };\n } catch (err) {\n // A revoked installation is the common case and deserves an actionable\n // message rather than a raw HTTP status the user can do nothing with.\n const message =\n err instanceof GithubAppError && err.status === 404\n ? 'GitHub access was revoked for this repo. Reconnect the lurq app.'\n : err instanceof Error\n ? err.message\n : 'Scan failed.';\n logger.warn(`repo scan failed for ${repo.fullName}: ${message}`);\n await saveScanError(db, repo.id, message).catch(() => {\n /* the scan already failed; a bookkeeping write failure must not mask it */\n });\n return {\n ...base,\n ok: false,\n depsTracked: 0,\n majorDrift: 0,\n partial: false,\n transitivesRead: false,\n error: message,\n };\n }\n}\n\n/** Sequential on purpose: GitHub's rate limit is per installation and shared\n * across these calls, and a scan is a background job with nobody waiting on\n * latency. Parallelism here buys seconds and costs 403s. */\nasync function scanEach(db: Database, rows: RepoRow[]): Promise<ScanResult[]> {\n const results: ScanResult[] = [];\n for (const repo of rows) {\n results.push(await scanRepo(db, repo));\n }\n return results;\n}\n\n/** Scan every repo an owner has connected. */\nexport async function scanOwnerRepos(\n db: Database,\n ownerId: string,\n): Promise<ScanResult[]> {\n return scanEach(db, await listRepos(db, ownerId));\n}\n\n/** Scan every connected repo across all owners — the daily cron entry point. */\nexport async function scanAllRepos(db: Database): Promise<ScanResult[]> {\n return scanEach(db, await listAllRepos(db));\n}\n","/**\n * Hosted HTTP transport for the MCP server (docs/lurq-hosted-deployment.md §4–5).\n *\n * Stateless Streamable HTTP: one shared DB pool created at startup, a fresh MCP\n * server+transport per request, fronted by helmet + rate limiting + API-key auth.\n * The DB credentials stay server-side; users connect with only a URL + Bearer key.\n * `buildMcpServer` is reused verbatim from the stdio path — the tools are\n * transport-agnostic.\n *\n * express/helmet/express-rate-limit are imported dynamically so the CLI and the\n * install wizard never pull server-only deps into their startup path.\n */\nimport { createHash, timingSafeEqual } from 'node:crypto';\nimport type { NextFunction, Request, Response } from 'express';\nimport type { Store } from 'express-rate-limit';\nimport { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';\nimport { getConfig } from '../core/config';\nimport { logger } from '../core/logger';\nimport {\n createKey,\n findKeyForOwner,\n listKeysForOwner,\n lookupActiveKey,\n revokeKey,\n rotateKey,\n} from '../auth/apiKeys';\nimport { getOutcomesByOwner } from '../db/outcomes';\nimport { getContributionsByOwner } from '../db/packages';\nimport { deleteRepo, getRepo, listRepos, setRepoPolicy, upsertRepos } from '../db/repos';\nimport { getUsageByTool, getUsageSummary } from '../db/usage';\nimport { createDb } from '../db/client';\nimport { githubAppCredentials, GithubAppError } from '../github/app';\nimport { briefRepo } from '../github/brief';\nimport { computeDrift } from '../github/drift';\nimport { parseDepsInput, parseUpgradeRuns } from '../github/runs';\nimport {\n findRepoIdByFullName,\n getUpgradeImpact,\n listRunsForRepo,\n recordUpgradeRuns,\n MAX_RUNS_PER_POST,\n} from '../db/upgradeRuns';\nimport { listInstallationRepos } from '../github/manifests';\nimport type { RepoPolicy } from '../github/types';\nimport { newFileUrl, renderWorkflow, WORKFLOW_PATH } from '../github/workflow';\nimport { scanOwnerRepos, scanRepo } from '../pipeline/repoScan';\nimport type { ApiKeyRow, RepoRow } from '../db/schema';\nimport { buildMcpServer } from './server';\nimport { renderPrometheus } from './metrics';\n\ninterface AuthedRequest extends Request {\n lurqKey?: ApiKeyRow;\n}\n\n/** JSON-RPC-shaped error envelope for HTTP-level rejections. */\nfunction rpcError(code: number, message: string) {\n return { jsonrpc: '2.0' as const, error: { code, message }, id: null };\n}\n\n/** Constant-time secret comparison (hash to a fixed length first, so length\n * never leaks and mismatched lengths don't throw). */\nexport function secretEquals(a: string, b: string): boolean {\n return timingSafeEqual(\n createHash('sha256').update(a).digest(),\n createHash('sha256').update(b).digest(),\n );\n}\n\nexport async function startHttpServer(opts: { port?: number } = {}): Promise<void> {\n const config = getConfig();\n const port = opts.port ?? config.PORT;\n\n const [{ default: express }, { default: helmet }, { rateLimit, ipKeyGenerator }] =\n await Promise.all([import('express'), import('helmet'), import('express-rate-limit')]);\n\n // The DB pool is the expensive resource — created once, shared by all requests.\n const { db } = createDb({ max: 20 });\n\n // Without Redis the response cache is a pass-through, so every recommend/\n // evaluate/compare recomputes its search on the DB — fine for one box, but the\n // first thing that buckles under real traffic. Warn loudly on the hosted path.\n if (!process.env.REDIS_URL) {\n logger.warn(\n 'REDIS_URL not set — response caching is OFF; every request recomputes on the ' +\n 'database. Set REDIS_URL before serving real traffic (and it also backs the ' +\n 'rate limiter across instances).',\n );\n }\n\n // Rate-limit store: Redis-backed when REDIS_URL is set, so limits are shared\n // and correct across horizontally-scaled instances. Without it the default\n // in-memory store is per-process — fine for one box, but N instances would\n // each enforce the full quota (N× the real limit). Each limiter gets its own\n // prefix so their counters don't collide in one Redis keyspace.\n let makeStore: ((prefix: string) => Store) | null = null;\n if (process.env.REDIS_URL) {\n const [{ default: Redis }, { default: RedisStore }] = await Promise.all([\n import('ioredis'),\n import('rate-limit-redis'),\n ]);\n const rlRedis = new Redis(process.env.REDIS_URL, { maxRetriesPerRequest: 1, family: 0 });\n rlRedis.on('error', (err: Error) => logger.warn(`rate-limit redis: ${err.message}`));\n makeStore = (prefix: string) =>\n new RedisStore({\n prefix,\n sendCommand: (...args: string[]) => rlRedis.call(args[0]!, ...args.slice(1)) as Promise<never>,\n });\n }\n\n const app = express();\n app.set('trust proxy', 1); // Railway terminates TLS at the edge.\n app.use(helmet());\n app.use(express.json({ limit: '1mb' }));\n\n // Unauthenticated, no DB hit — for Railway's healthcheck. Intentionally not\n // rate-limited: it's a static response with no backend cost, and limiting it\n // risks 429'ing Railway's own frequent healthcheck poll into a restart loop.\n app.get('/healthz', (_req: Request, res: Response) => {\n res.status(200).json({ status: 'ok' });\n });\n\n // Prometheus scrape of per-tool call/error/latency counters. Disabled (404)\n // unless LURQ_METRICS_TOKEN is set; when set, require it as a Bearer token so\n // the endpoint doesn't leak usage on a public host.\n app.get('/metrics', (req: Request, res: Response) => {\n const token = config.LURQ_METRICS_TOKEN;\n if (!token) {\n res.status(404).end();\n return;\n }\n const header = req.headers.authorization;\n const presented = header?.startsWith('Bearer ') ? header.slice(7).trim() : '';\n if (presented !== token) {\n res.status(401).end();\n return;\n }\n res.type('text/plain').send(renderPrometheus());\n });\n\n // Coarse per-IP limiter to blunt unauthenticated floods before the auth lookup.\n const ipLimiter = rateLimit({\n windowMs: config.LURQ_RATE_LIMIT_WINDOW_MS,\n limit: config.LURQ_IP_RATE_LIMIT_MAX,\n standardHeaders: 'draft-7',\n legacyHeaders: false,\n ...(makeStore ? { store: makeStore('rl:ip:') } : {}),\n message: rpcError(-32029, 'Rate limit exceeded.'),\n });\n\n // Bearer API-key auth: resolve and attach the key, or 401.\n const auth = async (req: AuthedRequest, res: Response, next: NextFunction): Promise<void> => {\n const header = req.headers.authorization;\n const token = header?.startsWith('Bearer ') ? header.slice(7).trim() : '';\n if (!token) {\n res.status(401).json(rpcError(-32001, 'Missing API key. Pass Authorization: Bearer <key>.'));\n return;\n }\n try {\n const row = await lookupActiveKey(db, token);\n if (!row) {\n res.status(401).json(rpcError(-32001, 'Invalid or revoked API key.'));\n return;\n }\n req.lurqKey = row;\n next();\n } catch (err) {\n logger.error('auth lookup failed:', err instanceof Error ? err.message : String(err));\n res.status(500).json(rpcError(-32603, 'Internal error.'));\n }\n };\n\n // Per-key limiter (runs after auth so it can key on the resolved API key).\n const keyLimiter = rateLimit({\n windowMs: config.LURQ_RATE_LIMIT_WINDOW_MS,\n limit: config.LURQ_RATE_LIMIT_MAX,\n standardHeaders: 'draft-7',\n legacyHeaders: false,\n // Key on the resolved API key's unique row id (always present — auth runs\n // first). The display `prefix` is only 6 chars of body, so distinct keys\n // can collide on it and share a quota; the id cannot. The IP fallback uses\n // express-rate-limit's ipKeyGenerator so IPv6 addresses are normalized\n // correctly (v8 throws ERR_ERL_KEY_GEN_IPV6 on a raw req.ip).\n keyGenerator: (req: Request) => {\n const id = (req as AuthedRequest).lurqKey?.id;\n return id != null ? `key:${id}` : ipKeyGenerator(req.ip ?? '0.0.0.0');\n },\n ...(makeStore ? { store: makeStore('rl:key:') } : {}),\n message: rpcError(-32029, 'Rate limit exceeded.'),\n });\n\n // Dashboard-authenticated routes (§ identity): gated by the shared\n // LURQ_ISSUER_SECRET, never by a per-request API key. The Clerk-authenticated\n // web app presents the secret and supplies the signed-in user's `ownerId` in\n // the request body/query — the backend trusts the web app to have already\n // authenticated the user. NOT behind the per-IP limiter: all web-app calls\n // share one egress IP, so that would throttle every user together; the secret\n // + the web app's own per-user auth are the gate. Disabled (404) when the\n // secret is unset. This auth model never overlaps with the Bearer-API-key\n // `auth` middleware below: the two tokens live in disjoint namespaces (an\n // issued `lurq_live_...` key can never satisfy `secretEquals` against the\n // issuer secret, and the issuer secret is never looked up in `apiKeys`).\n const requireIssuerSecret = (req: Request, res: Response, next: NextFunction): void => {\n const secret = config.LURQ_ISSUER_SECRET;\n if (!secret) {\n res.status(404).end();\n return;\n }\n const header = req.headers.authorization;\n const token = header?.startsWith('Bearer ') ? header.slice(7).trim() : '';\n if (!token || !secretEquals(token, secret)) {\n res.status(401).json({ error: 'Invalid issuer secret.' });\n return;\n }\n next();\n };\n\n // Safe DTO for the dashboard's key list — never includes keyHash.\n const toDashboardKey = (row: ApiKeyRow) => ({\n id: row.id,\n prefix: row.prefix,\n label: row.label,\n tier: row.tier,\n createdAt: row.createdAt,\n lastUsedAt: row.lastUsedAt,\n revokedAt: row.revokedAt,\n });\n\n app.post('/keys', requireIssuerSecret, async (req: Request, res: Response) => {\n const body = (req.body ?? {}) as { ownerId?: unknown; label?: unknown };\n const ownerId = typeof body.ownerId === 'string' ? body.ownerId.trim() : '';\n if (!ownerId) {\n res.status(400).json({ error: 'ownerId is required.' });\n return;\n }\n const label = typeof body.label === 'string' ? body.label.slice(0, 200) : undefined;\n try {\n const { key, row } = await createKey(db, { ownerId, label, tier: 'free' });\n res.status(201).json({ key, prefix: row.prefix });\n } catch (err) {\n logger.error('key issuance failed:', err instanceof Error ? err.message : String(err));\n res.status(500).json({ error: 'Could not issue key.' });\n }\n });\n\n app.get('/keys', requireIssuerSecret, async (req: Request, res: Response) => {\n const ownerId = typeof req.query.ownerId === 'string' ? req.query.ownerId.trim() : '';\n if (!ownerId) {\n res.status(400).json({ error: 'ownerId is required.' });\n return;\n }\n try {\n const rows = await listKeysForOwner(db, ownerId);\n res.status(200).json({ keys: rows.map(toDashboardKey) });\n } catch (err) {\n logger.error('key listing failed:', err instanceof Error ? err.message : String(err));\n res.status(500).json({ error: 'Could not list keys.' });\n }\n });\n\n app.post('/keys/:prefix/revoke', requireIssuerSecret, async (req: Request, res: Response) => {\n const prefix = req.params.prefix;\n const body = (req.body ?? {}) as { ownerId?: unknown };\n const ownerId = typeof body.ownerId === 'string' ? body.ownerId.trim() : '';\n if (typeof prefix !== 'string' || !ownerId) {\n res.status(400).json({ error: 'ownerId is required.' });\n return;\n }\n try {\n const row = await findKeyForOwner(db, { prefixOrId: prefix, ownerId });\n if (!row) {\n res.status(404).json({ error: 'Key not found.' });\n return;\n }\n await revokeKey(db, String(row.id));\n res.status(200).json({ revoked: true });\n } catch (err) {\n logger.error('key revoke failed:', err instanceof Error ? err.message : String(err));\n res.status(500).json({ error: 'Could not revoke key.' });\n }\n });\n\n app.post('/keys/:prefix/rotate', requireIssuerSecret, async (req: Request, res: Response) => {\n const prefix = req.params.prefix;\n const body = (req.body ?? {}) as { ownerId?: unknown };\n const ownerId = typeof body.ownerId === 'string' ? body.ownerId.trim() : '';\n if (typeof prefix !== 'string' || !ownerId) {\n res.status(400).json({ error: 'ownerId is required.' });\n return;\n }\n try {\n const row = await findKeyForOwner(db, { prefixOrId: prefix, ownerId });\n if (!row) {\n res.status(404).json({ error: 'Key not found.' });\n return;\n }\n const rotated = await rotateKey(db, String(row.id));\n if (!rotated) {\n res.status(404).json({ error: 'Key not found.' });\n return;\n }\n res.status(200).json({ key: rotated.key, prefix: rotated.row.prefix });\n } catch (err) {\n logger.error('key rotate failed:', err instanceof Error ? err.message : String(err));\n res.status(500).json({ error: 'Could not rotate key.' });\n }\n });\n\n app.get('/outcomes', requireIssuerSecret, async (req: Request, res: Response) => {\n const ownerId = typeof req.query.ownerId === 'string' ? req.query.ownerId.trim() : '';\n if (!ownerId) {\n res.status(400).json({ error: 'ownerId is required.' });\n return;\n }\n const limitRaw = typeof req.query.limit === 'string' ? Number(req.query.limit) : undefined;\n const limit = limitRaw && Number.isInteger(limitRaw) && limitRaw > 0 ? Math.min(limitRaw, 200) : undefined;\n try {\n const rows = await getOutcomesByOwner(db, ownerId, { limit });\n res.status(200).json({\n outcomes: rows.map((row) => ({\n packageName: row.packageName,\n accepted: row.accepted,\n buildSignal: row.buildSignal,\n need: row.need,\n createdAt: row.createdAt,\n })),\n });\n } catch (err) {\n logger.error('outcomes read failed:', err instanceof Error ? err.message : String(err));\n res.status(500).json({ error: 'Could not read outcomes.' });\n }\n });\n\n app.get('/usage', requireIssuerSecret, async (req: Request, res: Response) => {\n const ownerId = typeof req.query.ownerId === 'string' ? req.query.ownerId.trim() : '';\n if (!ownerId) {\n res.status(400).json({ error: 'ownerId is required.' });\n return;\n }\n const daysRaw = typeof req.query.days === 'string' ? Number(req.query.days) : NaN;\n const days = Number.isInteger(daysRaw) && daysRaw > 0 ? Math.min(daysRaw, 365) : 30;\n try {\n const [summary, byTool] = await Promise.all([\n getUsageSummary(db, ownerId, days),\n getUsageByTool(db, ownerId, days),\n ]);\n res.status(200).json({ today: summary.today, series: summary.series, byTool });\n } catch (err) {\n logger.error('usage read failed:', err instanceof Error ? err.message : String(err));\n res.status(500).json({ error: 'Could not read usage.' });\n }\n });\n\n /** Autopilot impact totals for the dashboard. Not gated on the GitHub App:\n * runs can arrive from any checkout via the CLI, connected or not. */\n app.get('/impact', requireIssuerSecret, async (req: Request, res: Response) => {\n const ownerId = typeof req.query.ownerId === 'string' ? req.query.ownerId.trim() : '';\n if (!ownerId) {\n res.status(400).json({ error: 'ownerId is required.' });\n return;\n }\n const daysRaw = typeof req.query.days === 'string' ? Number(req.query.days) : NaN;\n const days = Number.isInteger(daysRaw) && daysRaw > 0 ? Math.min(daysRaw, 365) : 30;\n try {\n res.status(200).json(await getUpgradeImpact(db, ownerId, days));\n } catch (err) {\n logger.error('impact read failed:', err instanceof Error ? err.message : String(err));\n res.status(500).json({ error: 'Could not read impact.' });\n }\n });\n\n app.get('/contributions', requireIssuerSecret, async (req: Request, res: Response) => {\n const ownerId = typeof req.query.ownerId === 'string' ? req.query.ownerId.trim() : '';\n if (!ownerId) {\n res.status(400).json({ error: 'ownerId is required.' });\n return;\n }\n const limitRaw = typeof req.query.limit === 'string' ? Number(req.query.limit) : NaN;\n const limit = Number.isInteger(limitRaw) && limitRaw > 0 ? Math.min(limitRaw, 200) : 50;\n const offsetRaw = typeof req.query.offset === 'string' ? Number(req.query.offset) : NaN;\n const offset = Number.isInteger(offsetRaw) && offsetRaw > 0 ? offsetRaw : 0;\n try {\n const { total, packages: rows } = await getContributionsByOwner(db, ownerId, { limit, offset });\n res.status(200).json({ total, packages: rows });\n } catch (err) {\n logger.error('contributions read failed:', err instanceof Error ? err.message : String(err));\n res.status(500).json({ error: 'Could not read contributions.' });\n }\n });\n\n // ── Repo autopilot (dashboard-authenticated, same issuer-secret model) ──────\n\n /** 404 the whole surface when no GitHub App is configured, matching /keys. */\n const requireGithubApp = (_req: Request, res: Response, next: NextFunction): void => {\n if (!githubAppCredentials()) {\n res.status(404).end();\n return;\n }\n next();\n };\n\n /** Every repo route is owner-scoped; a missing ownerId is a 400, never a\n * wildcard read. See the header of src/db/repos.ts. */\n const ownerFrom = (req: Request): string => {\n const source = req.method === 'GET' ? req.query : (req.body ?? {});\n const raw = (source as Record<string, unknown>).ownerId;\n return typeof raw === 'string' ? raw.trim() : '';\n };\n\n /** Manifests are never sent to the browser — only the derived drift summary.\n * The dependency ranges are input to our computation, not dashboard content. */\n const toDashboardRepo = (row: RepoRow) => ({\n id: row.id,\n fullName: row.fullName,\n defaultBranch: row.defaultBranch,\n isPrivate: row.isPrivate,\n policy: row.policy,\n drift: row.drift\n ? {\n depsDeclared: row.drift.depsDeclared,\n depsTracked: row.drift.depsTracked,\n majorDrift: row.drift.majorDrift,\n anyDrift: row.drift.anyDrift,\n deprecated: row.drift.deprecated,\n advisories: row.drift.advisories,\n /** null = scanned before the check existed, so it was never run. Kept\n * distinct from 0 so the dashboard cannot render \"not checked\" as a\n * clean stack. */\n conflicts: row.drift.conflictsAtLatest?.length ?? null,\n transitive: row.drift.transitive\n ? {\n resolved: row.drift.transitive.resolved,\n tracked: row.drift.transitive.tracked,\n advisoryPackages: row.drift.transitive.advisoryPackages,\n deprecated: row.drift.transitive.deprecated,\n truncated: row.drift.transitive.truncated,\n attributed: row.drift.transitive.attributed,\n }\n : null,\n }\n : null,\n lastScanAt: row.lastScanAt,\n lastScanError: row.lastScanError,\n });\n\n /** Reject anything not matching RepoPolicy rather than merging partial input —\n * a policy is a permission grant, and a half-parsed one could arm a repo the\n * user meant to leave off. */\n function parsePolicy(input: unknown): RepoPolicy | null {\n if (!input || typeof input !== 'object') return null;\n const raw = input as Record<string, unknown>;\n if (typeof raw.enabled !== 'boolean') return null;\n if (typeof raw.autoMerge !== 'boolean') return null;\n if (raw.scope !== 'security' && raw.scope !== 'blocking' && raw.scope !== 'all') return null;\n return { enabled: raw.enabled, scope: raw.scope, autoMerge: raw.autoMerge };\n }\n\n app.post('/repos/connect', requireIssuerSecret, requireGithubApp, async (req: Request, res: Response) => {\n const ownerId = ownerFrom(req);\n const installationRaw = (req.body ?? {}).installationId;\n const installationId = Number(installationRaw);\n if (!ownerId || !Number.isInteger(installationId) || installationId <= 0) {\n res.status(400).json({ error: 'ownerId and installationId are required.' });\n return;\n }\n try {\n const found = await listInstallationRepos(installationId);\n const connected = await upsertRepos(\n db,\n found.map((repo) => ({\n ownerId,\n installationId,\n fullName: repo.fullName,\n defaultBranch: repo.defaultBranch,\n isPrivate: repo.isPrivate,\n })),\n );\n // Respond as soon as the repos are registered. A first scan of a large\n // account is minutes of GitHub calls, and holding the connect request open\n // for it would time out at the edge and look like a failed install.\n void scanOwnerRepos(db, ownerId).catch((err: unknown) => {\n logger.warn(`initial repo scan failed: ${err instanceof Error ? err.message : String(err)}`);\n });\n res.status(200).json({ connected });\n } catch (err) {\n const status = err instanceof GithubAppError ? err.status : 502;\n logger.error('repo connect failed:', err instanceof Error ? err.message : String(err));\n res.status(status).json({ error: 'Could not read the GitHub installation.' });\n }\n });\n\n app.get('/repos', requireIssuerSecret, requireGithubApp, async (req: Request, res: Response) => {\n const ownerId = ownerFrom(req);\n if (!ownerId) {\n res.status(400).json({ error: 'ownerId is required.' });\n return;\n }\n try {\n const rows = await listRepos(db, ownerId);\n res.status(200).json({ repos: rows.map(toDashboardRepo) });\n } catch (err) {\n logger.error('repo list failed:', err instanceof Error ? err.message : String(err));\n res.status(500).json({ error: 'Could not list repos.' });\n }\n });\n\n app.get('/repos/:id', requireIssuerSecret, requireGithubApp, async (req: Request, res: Response) => {\n const ownerId = ownerFrom(req);\n const id = Number(req.params.id);\n if (!ownerId || !Number.isInteger(id)) {\n res.status(400).json({ error: 'ownerId and a numeric id are required.' });\n return;\n }\n try {\n const row = await getRepo(db, ownerId, id);\n if (!row) {\n res.status(404).json({ error: 'Repo not found.' });\n return;\n }\n const runs = await listRunsForRepo(db, ownerId, row.id);\n // The setup file is rendered per repo because it carries that repo's own\n // package manager and armed state. Shipped as text so the dashboard can\n // show exactly what will be committed before anything is.\n const workflow = renderWorkflow({\n installCommand: row.installCommand ?? undefined,\n armed: row.policy.enabled,\n });\n res.status(200).json({\n repo: {\n ...toDashboardRepo(row),\n deps: row.drift?.deps ?? [],\n transitiveRisks: row.drift?.transitive?.risks ?? [],\n conflicts: row.drift?.conflictsAtLatest ?? null,\n runs,\n workflow,\n workflowPath: WORKFLOW_PATH,\n setupUrl: newFileUrl(row.fullName, row.defaultBranch ?? 'main', workflow),\n },\n });\n } catch (err) {\n logger.error('repo read failed:', err instanceof Error ? err.message : String(err));\n res.status(500).json({ error: 'Could not read repo.' });\n }\n });\n\n app.get('/repos/:id/brief', requireIssuerSecret, requireGithubApp, async (req: Request, res: Response) => {\n const ownerId = ownerFrom(req);\n const id = Number(req.params.id);\n if (!ownerId || !Number.isInteger(id)) {\n res.status(400).json({ error: 'ownerId and a numeric id are required.' });\n return;\n }\n try {\n const row = await getRepo(db, ownerId, id);\n if (!row) {\n res.status(404).json({ error: 'Repo not found.' });\n return;\n }\n res.status(200).json(await briefRepo(db, row.drift ?? null));\n } catch (err) {\n logger.error('repo brief failed:', err instanceof Error ? err.message : String(err));\n res.status(500).json({ error: 'Could not build the migration brief.' });\n }\n });\n\n app.post('/repos/:id/scan', requireIssuerSecret, requireGithubApp, async (req: Request, res: Response) => {\n const ownerId = ownerFrom(req);\n const id = Number(req.params.id);\n if (!ownerId || !Number.isInteger(id)) {\n res.status(400).json({ error: 'ownerId and a numeric id are required.' });\n return;\n }\n try {\n const row = await getRepo(db, ownerId, id);\n if (!row) {\n res.status(404).json({ error: 'Repo not found.' });\n return;\n }\n // One repo is a handful of GitHub calls — fast enough to await, so the\n // dashboard can render the new numbers instead of polling for them.\n const result = await scanRepo(db, row);\n res.status(200).json({ result });\n } catch (err) {\n logger.error('repo scan failed:', err instanceof Error ? err.message : String(err));\n res.status(500).json({ error: 'Could not scan repo.' });\n }\n });\n\n app.patch('/repos/:id', requireIssuerSecret, requireGithubApp, async (req: Request, res: Response) => {\n const ownerId = ownerFrom(req);\n const id = Number(req.params.id);\n const policy = parsePolicy((req.body ?? {}).policy);\n if (!ownerId || !Number.isInteger(id) || !policy) {\n res.status(400).json({ error: 'ownerId, a numeric id, and a complete policy are required.' });\n return;\n }\n try {\n const updated = await setRepoPolicy(db, ownerId, id, policy);\n if (!updated) {\n res.status(404).json({ error: 'Repo not found.' });\n return;\n }\n res.status(200).json({ policy });\n } catch (err) {\n logger.error('repo policy update failed:', err instanceof Error ? err.message : String(err));\n res.status(500).json({ error: 'Could not update policy.' });\n }\n });\n\n app.delete('/repos/:id', requireIssuerSecret, requireGithubApp, async (req: Request, res: Response) => {\n const ownerId = ownerFrom(req);\n const id = Number(req.params.id);\n if (!ownerId || !Number.isInteger(id)) {\n res.status(400).json({ error: 'ownerId and a numeric id are required.' });\n return;\n }\n try {\n const removed = await deleteRepo(db, ownerId, id);\n res.status(removed ? 200 : 404).json(removed ? { removed: true } : { error: 'Repo not found.' });\n } catch (err) {\n logger.error('repo delete failed:', err instanceof Error ? err.message : String(err));\n res.status(500).json({ error: 'Could not disconnect repo.' });\n }\n });\n\n // ── Autopilot CI surface (API-key authenticated, same as /mcp) ─────────────\n //\n // These two are what the user's GitHub Actions workflow calls. They are keyed\n // on the API key, NOT the issuer secret: the workflow is the user's own\n // machine, so it holds a per-user key and never the web↔backend shared secret.\n //\n // Note there is no repo id in either path. The workflow sends the manifest it\n // already has on disk, so `upgrade-plan` works in any checkout — connecting a\n // repo to the dashboard adds visibility, it is not a precondition for the loop.\n\n app.post('/upgrade-plan', ipLimiter, auth, keyLimiter, async (req: Request, res: Response) => {\n const deps = parseDepsInput((req.body ?? {}).deps);\n if (Object.keys(deps).length === 0) {\n res.status(400).json({ error: 'deps is required: { \"package\": \"range\", … }' });\n return;\n }\n try {\n const drift = await computeDrift(db, [{ path: 'package.json', deps }]);\n const brief = await briefRepo(db, drift);\n res.status(200).json({\n ...brief,\n // Surfaced so CI can log what lurq had no opinion on. An upgrade we do\n // not know about must not look like an upgrade we cleared.\n untracked: Object.keys(deps).length - drift.depsTracked,\n });\n } catch (err) {\n logger.error('upgrade plan failed:', err instanceof Error ? err.message : String(err));\n res.status(500).json({ error: 'Could not build the upgrade plan.' });\n }\n });\n\n app.post('/upgrade-runs', ipLimiter, auth, keyLimiter, async (req: Request, res: Response) => {\n const ownerId = (req as AuthedRequest).lurqKey?.ownerId ?? null;\n if (!ownerId) {\n // Operator-issued keys have no dashboard account to attribute runs to.\n res.status(403).json({ error: 'This key has no account attached.' });\n return;\n }\n const { runs, rejected } = parseUpgradeRuns((req.body ?? {}).runs, MAX_RUNS_PER_POST);\n if (runs.length === 0) {\n res.status(400).json({ error: 'runs must be a non-empty array of upgrade results.' });\n return;\n }\n try {\n // Resolve repo links once per distinct repo, not once per run.\n const repoIds = new Map<string, number | null>();\n for (const run of runs) {\n if (!repoIds.has(run.repoFullName)) {\n repoIds.set(run.repoFullName, await findRepoIdByFullName(db, ownerId, run.repoFullName));\n }\n }\n const recorded = await recordUpgradeRuns(\n db,\n runs.map((run) => ({ ...run, ownerId, repoId: repoIds.get(run.repoFullName) ?? null })),\n );\n res.status(200).json({ recorded, rejected });\n } catch (err) {\n logger.error('upgrade run record failed:', err instanceof Error ? err.message : String(err));\n res.status(500).json({ error: 'Could not record the upgrade runs.' });\n }\n });\n\n app.post('/mcp', ipLimiter, auth, keyLimiter, async (req: Request, res: Response) => {\n // Stateless: a fresh server+transport per request, sharing the one DB pool.\n // Thread the authenticated key's owner identity into the tools (§3.1).\n const server = buildMcpServer(db, { ownerId: (req as AuthedRequest).lurqKey?.ownerId ?? null });\n const transport = new StreamableHTTPServerTransport({\n sessionIdGenerator: undefined,\n enableJsonResponse: true,\n });\n res.on('close', () => {\n void transport.close();\n void server.close();\n });\n try {\n await server.connect(transport);\n await transport.handleRequest(req, res, req.body);\n } catch (err) {\n logger.error('mcp request failed:', err instanceof Error ? err.message : String(err));\n if (!res.headersSent) res.status(500).json(rpcError(-32603, 'Internal error'));\n }\n });\n\n // Stateless server: no session GET/DELETE handling.\n app.all('/mcp', (_req: Request, res: Response) => {\n res.status(405).json(rpcError(-32000, 'Method not allowed.'));\n });\n\n app.listen(port, () => {\n logger.info(`lurq HTTP MCP server listening on :${port}/mcp`);\n });\n}\n","/**\n * Dependency-free formatting helpers for human-facing CLI output. Compact tables\n * and labeled detail views; `--json` paths bypass these entirely.\n */\n\nconst ESC = '\u001b[';\nconst wrap = (code: string, s: string) => `${ESC}${code}m${s}${ESC}0m`;\n\nexport const bold = (s: string) => wrap('1', s);\nexport const dim = (s: string) => wrap('2', s);\nexport const red = (s: string) => wrap('31', s);\nexport const green = (s: string) => wrap('32', s);\nexport const yellow = (s: string) => wrap('33', s);\n\n// eslint-disable-next-line no-control-regex\nconst ANSI_RE = /\u001b\\[[0-9;]*m/g;\nconst width = (s: string) => s.replace(ANSI_RE, '').length;\n\n/** Render a simple aligned table. */\nexport function table(headers: string[], rows: string[][]): string {\n const widths = headers.map((h, i) => Math.max(width(h), ...rows.map((r) => width(r[i] ?? ''))));\n const pad = (s: string, w: number) => s + ' '.repeat(Math.max(0, w - width(s)));\n const line = (cells: string[]) => cells.map((c, i) => pad(c, widths[i]!)).join(' ');\n const out = [bold(line(headers)), dim(widths.map((w) => '─'.repeat(w)).join(' '))];\n for (const r of rows) out.push(line(r));\n return out.join('\\n');\n}\n\n/** Render a labeled key/value detail block. */\nexport function detail(pairs: [string, string][]): string {\n const labelWidth = Math.max(...pairs.map(([k]) => k.length));\n return pairs.map(([k, v]) => `${dim((k + ':').padEnd(labelWidth + 1))} ${v}`).join('\\n');\n}\n\n/** Compact number formatting: 1.2M, 34k, 950. */\nexport function formatNumber(n: number | null | undefined): string {\n if (n == null) return '—';\n if (n >= 1_000_000) return `${Math.round(n / 100_000) / 10}M`;\n if (n >= 1_000) return `${Math.round(n / 100) / 10}k`;\n return String(n);\n}\n\nexport function formatDate(iso: string | null): string {\n return iso ? iso.slice(0, 10) : '—';\n}\n\nexport function formatPercent(fraction: number | null | undefined): string {\n if (fraction == null) return '—';\n const pct = Math.round(fraction * 1000) / 10;\n return `${pct > 0 ? '+' : ''}${pct}%`;\n}\n\n/** Color a confidence label. */\nexport function confidenceLabel(c: string): string {\n if (c === 'proven') return green(c);\n if (c === 'emerging') return yellow(c);\n // `promising` (§1): high intrinsic quality, adoption-independent.\n if (c === 'promising') return green(c);\n return red(c);\n}\n","/**\n * Render a `plan` result as a self-contained HTML page: the Mermaid roadmap\n * rendered visually, plus the scored slot table. Mermaid is pulled from a CDN at\n * view time, so the file is a single portable artifact (no build step, no deps\n * added to the CLI). Used by `lurq plan --html <path>` / `--open`.\n */\nimport type { PlanOutput } from '../mcp/plan';\n\nfunction esc(s: string): string {\n return s.replace(/[&<>\"]/g, (c) => ({ '&': '&', '<': '<', '>': '>', '\"': '"' })[c]!);\n}\n\nfunction slotRows(plan: PlanOutput): string {\n return plan.slots\n .map((s) => {\n const rec = s.recommended;\n const name = rec\n ? rec.repoUrl\n ? `<a href=\"${esc(rec.repoUrl)}\" target=\"_blank\" rel=\"noreferrer\">${esc(rec.name)}</a>`\n : esc(rec.name)\n : '<span class=\"muted\">— no match —</span>';\n const alts = s.alternatives.map((a) => esc(a.name)).join(', ') || '<span class=\"muted\">—</span>';\n return `<tr>\n <td>${esc(s.need)}</td>\n <td><span class=\"layer\">${esc(s.layer)}</span></td>\n <td class=\"pkg\">${name}</td>\n <td class=\"num\">${rec ? rec.healthScore : '—'}</td>\n <td>${rec ? esc(rec.confidence) : '—'}</td>\n <td class=\"alts\">${alts}</td>\n </tr>`;\n })\n .join('\\n');\n}\n\nexport function renderPlanHtml(plan: PlanOutput): string {\n return `<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\" />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n<title>lurq plan — roadmap</title>\n<style>\n :root { color-scheme: dark; }\n * { box-sizing: border-box; }\n body { margin: 0; font: 15px/1.5 ui-sans-serif, system-ui, -apple-system, sans-serif;\n background: #0b0b0f; color: #e7e7ea; padding: 2.5rem clamp(1rem, 5vw, 4rem); }\n h1 { font-size: 1.5rem; margin: 0 0 .25rem; }\n h2 { font-size: 1rem; text-transform: uppercase; letter-spacing: .08em; color: #9a9aa6; margin: 2.5rem 0 .75rem; }\n .sub { color: #9a9aa6; margin: 0 0 1rem; max-width: 70ch; }\n .diagram { background: #141419; border: 1px solid #26262e; border-radius: 14px; padding: 1.5rem; overflow: auto; }\n table { width: 100%; border-collapse: collapse; margin-top: .5rem; }\n th, td { text-align: left; padding: .55rem .75rem; border-bottom: 1px solid #1e1e25; vertical-align: top; }\n th { font-size: .78rem; text-transform: uppercase; letter-spacing: .05em; color: #9a9aa6; }\n .pkg a { color: #d98cff; text-decoration: none; } .pkg a:hover { text-decoration: underline; }\n .num { text-align: right; font-variant-numeric: tabular-nums; }\n .muted { color: #6a6a76; } .alts { color: #b8b8c2; font-size: .92rem; }\n .layer { font-size: .8rem; color: #8ad; background: #15202b; border-radius: 6px; padding: .1rem .45rem; }\n footer { margin-top: 2.5rem; color: #6a6a76; font-size: .85rem; }\n</style>\n</head>\n<body>\n <h1>lurq plan <span class=\"muted\">· ${esc(plan.optimize)} · ${esc(plan.source)}${plan.framework ? ` · ${esc(plan.framework)} ecosystem` : ''}</span></h1>\n <p class=\"sub\">${esc(plan.note)}</p>\n\n <h2>Roadmap</h2>\n <div class=\"diagram\"><pre class=\"mermaid\">${esc(plan.mermaid)}</pre></div>\n\n <h2>Components</h2>\n <table>\n <thead><tr><th>Component</th><th>Layer</th><th>Recommended</th><th>Health</th><th>Confidence</th><th>Alternatives</th></tr></thead>\n <tbody>\n${slotRows(plan)}\n </tbody>\n </table>\n\n <footer>data as of ${esc(plan.dataAsOf)} · generated by lurq</footer>\n\n <script type=\"module\">\n import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';\n mermaid.initialize({ startOnLoad: true, theme: 'dark' });\n </script>\n</body>\n</html>\n`;\n}\n","/**\n * Cursor persistence for the npm `_changes` follower (one row per feed in\n * `watch_state`), so a restart resumes from the last processed sequence instead\n * of replaying the registry from the beginning.\n */\nimport { eq } from 'drizzle-orm';\nimport type { Database } from './client';\nimport { watchState } from './schema';\n\nexport async function getWatchCursor(db: Database, id: string): Promise<string | null> {\n const rows = await db\n .select({ seq: watchState.seq })\n .from(watchState)\n .where(eq(watchState.id, id))\n .limit(1);\n return rows[0]?.seq ?? null;\n}\n\nexport async function setWatchCursor(db: Database, id: string, seq: string): Promise<void> {\n await db\n .insert(watchState)\n .values({ id, seq, updatedAt: new Date() })\n .onConflictDoUpdate({ target: watchState.id, set: { seq, updatedAt: new Date() } });\n}\n","/**\n * npm `_changes` follower — the streaming log.\n *\n * Subscribes to the registry replication feed and, whenever a *tracked* package\n * publishes a new version, re-syncs it so scores, advisories, and the version\n * timeline stay fresh without a full crawl. Resumable via a persisted sequence\n * cursor (db/watch), so a restart picks up where it left off instead of\n * replaying the registry. Long-running: an operator runs `lurq watch` as a\n * daemon, matching lurq's external-scheduler model.\n */\nimport { logger } from '../core/logger';\nimport type { Database } from '../db/client';\nimport { getAllPackageNames } from '../db/packages';\nimport { getWatchCursor, setWatchCursor } from '../db/watch';\nimport { syncOnePackage } from './single';\n\nconst FEED_ID = 'npm-changes';\nconst FEED_URL = 'https://replicate.npmjs.com/_changes';\nconst HEARTBEAT_MS = 30_000;\nconst TRACKED_REFRESH_MS = 5 * 60_000; // re-read the tracked set this often\nconst CHECKPOINT_EVERY = 200; // advance the cursor through churn at least this often\nconst MAX_BACKOFF_MS = 30_000;\n\nexport interface ChangeRecord {\n seq: number | string;\n id: string;\n deleted: boolean;\n}\n\n/** Parse one NDJSON line from the continuous feed; null for heartbeats/garbage. */\nexport function parseChangeLine(line: string): ChangeRecord | null {\n const trimmed = line.trim();\n if (!trimmed) return null; // heartbeat\n try {\n const obj = JSON.parse(trimmed);\n if (typeof obj?.id !== 'string' || obj.seq == null) return null;\n return { seq: obj.seq, id: obj.id, deleted: Boolean(obj.deleted) };\n } catch {\n return null;\n }\n}\n\nexport interface WatchOptions {\n signal?: AbortSignal;\n /** Start point when no cursor is stored. 'now' (default) = only future changes. */\n since?: string;\n}\n\nexport async function watchNpmChanges(db: Database, opts: WatchOptions = {}): Promise<void> {\n const { signal } = opts;\n let backoff = 1000;\n\n while (!signal?.aborted) {\n let tracked = new Set(await getAllPackageNames(db));\n let trackedAt = Date.now();\n const since = (await getWatchCursor(db, FEED_ID)) ?? opts.since ?? 'now';\n const url = `${FEED_URL}?feed=continuous&since=${encodeURIComponent(since)}&heartbeat=${HEARTBEAT_MS}`;\n logger.info(`watch: connecting from seq=${since} (${tracked.size} tracked packages)`);\n\n try {\n const res = await fetch(url, { signal });\n if (!res.ok || !res.body) throw new Error(`feed responded ${res.status}`);\n backoff = 1000; // healthy connection — reset\n\n let sinceCheckpoint = 0;\n for await (const line of ndjsonLines(res.body, signal)) {\n const change = parseChangeLine(line);\n if (!change) continue;\n const seq = String(change.seq);\n sinceCheckpoint++;\n\n if (Date.now() - trackedAt > TRACKED_REFRESH_MS) {\n tracked = new Set(await getAllPackageNames(db));\n trackedAt = Date.now();\n }\n\n if (!change.deleted && tracked.has(change.id)) {\n logger.info(`watch: re-syncing ${change.id} (seq=${seq})`);\n await syncOnePackage(db, change.id).catch((err) =>\n logger.warn(`watch: re-sync failed for ${change.id}: ${String(err)}`),\n );\n await setWatchCursor(db, FEED_ID, seq);\n sinceCheckpoint = 0;\n } else if (sinceCheckpoint >= CHECKPOINT_EVERY) {\n await setWatchCursor(db, FEED_ID, seq); // advance through irrelevant churn\n sinceCheckpoint = 0;\n }\n }\n logger.info('watch: feed stream ended; reconnecting');\n } catch (err) {\n if (signal?.aborted) break;\n logger.warn(`watch: ${String(err)} — retrying in ${backoff}ms`);\n await sleep(backoff, signal);\n backoff = Math.min(backoff * 2, MAX_BACKOFF_MS);\n }\n }\n}\n\n/** Yield newline-delimited lines from a fetch ReadableStream as they arrive. */\nasync function* ndjsonLines(\n body: ReadableStream<Uint8Array>,\n signal?: AbortSignal,\n): AsyncGenerator<string> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n try {\n while (!signal?.aborted) {\n const { value, done } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n let nl: number;\n while ((nl = buffer.indexOf('\\n')) >= 0) {\n yield buffer.slice(0, nl);\n buffer = buffer.slice(nl + 1);\n }\n }\n } finally {\n reader.releaseLock();\n }\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve) => {\n const timer = setTimeout(resolve, ms);\n signal?.addEventListener(\n 'abort',\n () => {\n clearTimeout(timer);\n resolve();\n },\n { once: true },\n );\n });\n}\n","/**\n * Sandbox driver contract.\n *\n * Verification runs an install + smoke-load of a package version in an isolated\n * environment and reports whether it *actually* installs and loads — evidence no\n * static signal (downloads, stars) can provide.\n *\n * The interface is deliberately small so the runner is swappable: a local\n * child-process driver for dev/operator use, and a VM-isolated driver (E2B /\n * Firecracker / gVisor) for verifying UNTRUSTED packages at scale. Callers\n * depend only on this contract, never on a concrete driver.\n */\n\nexport type ModuleSystem = 'esm' | 'cjs';\n\nexport interface SandboxTarget {\n /** Node major the run targets. The local driver uses the host Node and just\n * records this; a VM driver provisions it. */\n node: string;\n moduleSystem: ModuleSystem;\n}\n\nexport interface SandboxVerifyOptions {\n target?: SandboxTarget;\n /** Run lifecycle install scripts (preinstall/install/postinstall). Off by\n * default: running untrusted scripts needs VM isolation, not a bare driver. */\n allowScripts?: boolean;\n timeoutMs?: number;\n signal?: AbortSignal;\n /** When set, only these packages are smoke-loaded after install. The full\n * install list is still co-installed. Defaults to the install list itself.\n * Use this to install all packages but smoke-load only runtime ones. */\n smokePackages?: SandboxPackage[];\n}\n\nexport interface SandboxResult {\n /** Provenance tag for the driver that produced this ('local', 'e2b', ...). */\n driver: string;\n moduleSystem: ModuleSystem;\n /** `npm install` succeeded. */\n installed: boolean;\n /** Package loaded (import/require without throwing). null = not attempted\n * because the install failed. */\n imported: boolean | null;\n /** Whether install scripts were allowed to run for this result. */\n ranScripts: boolean;\n durationMs: number;\n /** Condensed first line(s) of the failure, if any. */\n error: string | null;\n}\n\nexport interface SandboxPackage {\n name: string;\n version: string | null;\n}\n\nexport interface SandboxSetResult {\n driver: string;\n moduleSystem: ModuleSystem;\n /** Co-install of the whole set succeeded. */\n installed: boolean;\n /** Per-package smoke-load (null = not attempted because the install failed). */\n loaded: { name: string; loaded: boolean | null }[];\n durationMs: number;\n error: string | null;\n}\n\nexport interface ExecResult {\n exitCode: number;\n stdout: string;\n stderr: string;\n}\n\nexport interface ExecOptions {\n timeoutMs?: number;\n signal?: AbortSignal;\n /** Install these before running the command (same flags as a verify install). */\n install?: SandboxPackage[];\n allowScripts?: boolean;\n}\n\nexport interface Sandbox {\n /** Provenance tag stored with each result. */\n readonly name: string;\n /**\n * Run an arbitrary command in a throwaway sandbox, optionally after installing\n * packages. This is the generic escape hatch every non-npm oracle needs — an\n * MCP handshake, a `--help` probe, a container smoke test. A non-zero exit is\n * a RESULT, not an error: it resolves with the exit code so the oracle can\n * decide whether that means `verified_false`. Only infrastructure failures\n * (the sandbox itself dying) throw.\n */\n exec(command: string, opts?: ExecOptions): Promise<ExecResult>;\n verify(\n pkg: string,\n version: string | null,\n opts?: SandboxVerifyOptions,\n ): Promise<SandboxResult>;\n /** Co-install a set of packages and smoke-load a subset (or all).\n * `packages` are all co-installed; `opts.smokePackages` controls which are\n * smoke-loaded (defaults to `packages`). A successful co-install proves\n * the set coexists. */\n verifySet(\n packages: SandboxPackage[],\n opts?: SandboxVerifyOptions,\n ): Promise<SandboxSetResult>;\n /** Retrieve the node and npm versions running inside this sandbox. */\n getRuntimeInfo(): Promise<{ nodeVersion: string; npmVersion: string }>;\n}\n\nexport const DEFAULT_TARGET: SandboxTarget = {\n node: '20',\n moduleSystem: 'cjs',\n};\n","/**\n * Local child-process sandbox driver.\n *\n * Installs package(s) into a throwaway temp dir and smoke-loads them, reporting\n * whether they install and load. Fast and dependency-free (just npm + node).\n *\n * NOT an isolation boundary: loading a package executes its top-level code on\n * the host, so use this only for packages you already trust (operator/dev).\n * Verify UNTRUSTED packages with a VM driver. Install scripts stay OFF unless\n * `allowScripts` is set, since the whole point of the security tier is to not\n * execute untrusted install hooks.\n */\nimport { execFile } from 'node:child_process';\nimport { mkdtemp, rm, writeFile } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport { promisify } from 'node:util';\nimport {\n DEFAULT_TARGET,\n type ExecOptions,\n type ExecResult,\n type Sandbox,\n type SandboxPackage,\n type SandboxResult,\n type SandboxSetResult,\n type SandboxVerifyOptions,\n} from './types';\n\nconst execFileAsync = promisify(execFile);\nconst INSTALL_TIMEOUT_MS = 120_000;\nconst SMOKE_TIMEOUT_MS = 30_000;\nconst ERROR_MAX = 500;\nconst EXEC_MAX_BUFFER = 8 * 1024 * 1024;\n\n/** npm args for a throwaway install of one or more specs into the sandbox dir. */\nexport function npmInstallArgs(specs: string[], opts: { allowScripts: boolean }): string[] {\n // A spec beginning with `-` would be parsed as an npm flag (e.g.\n // `--registry=evil`), not a package. Legitimate names/specs never start with\n // one, so reject rather than smuggle it into the install command.\n const bad = specs.find((s) => s.startsWith('-'));\n if (bad) throw new Error(`Invalid package spec: ${bad}`);\n const args = ['install', ...specs, '--no-audit', '--no-fund', '--no-package-lock', '--no-save'];\n if (!opts.allowScripts) args.push('--ignore-scripts');\n return args;\n}\n\n/**\n * Load the package the way that works for both module systems.\n *\n * This used to branch on the target's `moduleSystem`, which nothing ever\n * derived from the package — DEFAULT_TARGET hardcodes 'cjs', so every smoke\n * load was a `require()`. An ESM-only package therefore came back\n * ERR_REQUIRE_ESM and was recorded as failing to load. Measured: nanoid@6.0.1,\n * a package that works perfectly, reported `installed: yes, loaded: no`.\n *\n * That verdict is not cosmetic — it feeds `verify` and the recommendation path,\n * so lurq was calling a large and growing share of the modern registry broken.\n * chalk, node-fetch, execa, got, ora and nanoid have all gone ESM-only.\n *\n * `import()` handles both: Node wraps a CJS module and hands back its exports\n * as `default`. So there is nothing to detect and no branch to get wrong, and\n * \"does `import` work\" is the right definition of loading in 2026 anyway.\n */\nexport function smokeScript(pkg: string): string[] {\n return ['--input-type=module', '-e', `await import(${JSON.stringify(pkg)})`];\n}\n\nfunction condense(s: string): string {\n return s.replace(/\\s+/g, ' ').trim().slice(0, ERROR_MAX);\n}\n\nfunction stderrOf(err: unknown): string {\n if (err && typeof err === 'object') {\n const e = err as { stderr?: unknown; message?: unknown };\n if (typeof e.stderr === 'string' && e.stderr.trim()) return e.stderr;\n if (typeof e.message === 'string') return e.message;\n }\n return String(err);\n}\n\nconst toSpec = (p: SandboxPackage): string => (p.version ? `${p.name}@${p.version}` : p.name);\n\nexport class LocalSandbox implements Sandbox {\n readonly name = 'local';\n\n async verify(\n pkg: string,\n version: string | null,\n opts: SandboxVerifyOptions = {},\n ): Promise<SandboxResult> {\n const set = await this.verifySet([{ name: pkg, version }], opts);\n return {\n driver: this.name,\n moduleSystem: set.moduleSystem,\n installed: set.installed,\n imported: set.loaded[0]?.loaded ?? null,\n ranScripts: opts.allowScripts ?? false,\n durationMs: set.durationMs,\n error: set.error,\n };\n }\n\n async verifySet(\n packages: SandboxPackage[],\n opts: SandboxVerifyOptions = {},\n ): Promise<SandboxSetResult> {\n const target = opts.target ?? DEFAULT_TARGET;\n const allowScripts = opts.allowScripts ?? false;\n const specs = packages.map(toSpec);\n const dir = await mkdtemp(join(tmpdir(), 'lurq-sandbox-'));\n const started = Date.now();\n const smokeTargets = opts.smokePackages ?? packages;\n const loaded = smokeTargets.map((p) => ({ name: p.name, loaded: null as boolean | null }));\n let installed = false;\n let error: string | null = null;\n\n try {\n await writeFile(\n join(dir, 'package.json'),\n JSON.stringify({ name: 'lurq-sandbox', version: '0.0.0', private: true }),\n );\n await execFileAsync('npm', npmInstallArgs(specs, { allowScripts }), {\n cwd: dir,\n timeout: opts.timeoutMs ?? INSTALL_TIMEOUT_MS,\n signal: opts.signal,\n });\n installed = true;\n\n for (let i = 0; i < smokeTargets.length; i++) {\n try {\n await execFileAsync('node', smokeScript(smokeTargets[i]!.name), {\n cwd: dir,\n timeout: SMOKE_TIMEOUT_MS,\n signal: opts.signal,\n });\n loaded[i]!.loaded = true;\n } catch (err) {\n loaded[i]!.loaded = false;\n if (!error) error = condense(stderrOf(err));\n }\n }\n } catch (err) {\n error = condense(stderrOf(err));\n } finally {\n await rm(dir, { recursive: true, force: true }).catch(() => {});\n }\n\n return {\n driver: this.name,\n moduleSystem: target.moduleSystem,\n installed,\n loaded,\n durationMs: Date.now() - started,\n error,\n };\n }\n\n async exec(command: string, opts: ExecOptions = {}): Promise<ExecResult> {\n const dir = await mkdtemp(join(tmpdir(), 'lurq-exec-'));\n try {\n await writeFile(\n join(dir, 'package.json'),\n JSON.stringify({ name: 'lurq-sandbox', version: '0.0.0', private: true }),\n );\n if (opts.install?.length) {\n await execFileAsync(\n 'npm',\n npmInstallArgs(opts.install.map(toSpec), { allowScripts: opts.allowScripts ?? false }),\n { cwd: dir, timeout: opts.timeoutMs ?? INSTALL_TIMEOUT_MS, signal: opts.signal },\n );\n }\n const { stdout, stderr } = await execFileAsync('sh', ['-c', command], {\n cwd: dir,\n timeout: opts.timeoutMs ?? SMOKE_TIMEOUT_MS,\n signal: opts.signal,\n maxBuffer: EXEC_MAX_BUFFER,\n });\n return { exitCode: 0, stdout, stderr };\n } catch (err) {\n // A non-zero exit is a result the oracle interprets, not a thrown error.\n const e = err as { code?: unknown; stdout?: unknown; stderr?: unknown };\n if (typeof e?.code === 'number') {\n return {\n exitCode: e.code,\n stdout: typeof e.stdout === 'string' ? e.stdout : '',\n stderr: typeof e.stderr === 'string' ? e.stderr : stderrOf(err),\n };\n }\n throw err; // timeout / spawn failure — infrastructure, not the subject\n } finally {\n await rm(dir, { recursive: true, force: true }).catch(() => {});\n }\n }\n\n async getRuntimeInfo(): Promise<{ nodeVersion: string; npmVersion: string }> {\n let nodeVersion = 'unknown';\n let npmVersion = 'unknown';\n try {\n const nodeOut = await execFileAsync('node', ['--version']);\n nodeVersion = nodeOut.stdout.trim() || 'unknown';\n const npmOut = await execFileAsync('npm', ['--version']);\n npmVersion = npmOut.stdout.trim() || 'unknown';\n } catch { /* ignore */ }\n return { nodeVersion, npmVersion };\n }\n}\n","/**\n * E2B cloud-sandbox driver.\n *\n * Installs package(s) and smoke-loads them inside an isolated E2B microVM, so\n * top-level package code (and, with allowScripts, install hooks) runs OFF the\n * host. This is the isolation boundary the local driver deliberately lacks —\n * use it to verify UNTRUSTED packages at scale.\n *\n * Requires E2B_API_KEY. The launched template must have node + npm on PATH\n * (see E2B_TEMPLATE). Like the local driver, target.node is recorded but not\n * provisioned — pin a Node-versioned template for reproducible majors.\n */\nimport { getConfig } from '../core/config';\nimport {\n DEFAULT_TARGET,\n type ExecOptions,\n type ExecResult,\n type Sandbox as SandboxDriver,\n type SandboxPackage,\n type SandboxResult,\n type SandboxSetResult,\n type SandboxVerifyOptions,\n} from './types';\n\nconst INSTALL_TIMEOUT_MS = 120_000;\nconst SMOKE_TIMEOUT_MS = 30_000;\nconst ERROR_MAX = 500;\nconst WORKDIR = '/home/user';\n\n/** POSIX single-quote: safe for any arg (specs may carry `^`, `>`, spaces). */\nexport function shQuote(s: string): string {\n return `'${s.replace(/'/g, `'\\\\''`)}'`;\n}\n\n/** Shell command that installs the specs into WORKDIR. */\nexport function installCommand(specs: string[], allowScripts: boolean): string {\n const bad = specs.find((s) => s.startsWith('-'));\n if (bad) throw new Error(`Invalid package spec: ${bad}`);\n const flags = ['--no-audit', '--no-fund', '--no-package-lock', '--no-save'];\n if (!allowScripts) flags.push('--ignore-scripts');\n return `npm install ${specs.map(shQuote).join(' ')} ${flags.join(' ')}`;\n}\n\n/** Shell command that loads a package and exits non-zero if it throws.\n * Always `import()` — it handles ESM and CJS alike; see smokeScript in\n * local.ts for why branching on a module system nobody derived was wrong. */\nexport function smokeCommand(pkg: string): string {\n return `node --input-type=module -e ${shQuote(`await import(${JSON.stringify(pkg)})`)}`;\n}\n\nfunction condense(s: string): string {\n return s.replace(/\\s+/g, ' ').trim().slice(0, ERROR_MAX);\n}\n\nfunction errText(err: unknown): string {\n if (err && typeof err === 'object') {\n const e = err as { stderr?: unknown; message?: unknown };\n if (typeof e.stderr === 'string' && e.stderr.trim()) return e.stderr;\n if (typeof e.message === 'string') return e.message;\n }\n return String(err);\n}\n\nconst toSpec = (p: SandboxPackage): string => (p.version ? `${p.name}@${p.version}` : p.name);\n\nexport class E2BSandbox implements SandboxDriver {\n readonly name = 'e2b';\n\n async verify(\n pkg: string,\n version: string | null,\n opts: SandboxVerifyOptions = {},\n ): Promise<SandboxResult> {\n const set = await this.verifySet([{ name: pkg, version }], opts);\n return {\n driver: this.name,\n moduleSystem: set.moduleSystem,\n installed: set.installed,\n imported: set.loaded[0]?.loaded ?? null,\n ranScripts: opts.allowScripts ?? false,\n durationMs: set.durationMs,\n error: set.error,\n };\n }\n\n async verifySet(\n packages: SandboxPackage[],\n opts: SandboxVerifyOptions = {},\n ): Promise<SandboxSetResult> {\n const config = getConfig();\n const target = opts.target ?? DEFAULT_TARGET;\n const allowScripts = opts.allowScripts ?? false;\n const specs = packages.map(toSpec);\n const installTimeout = opts.timeoutMs ?? INSTALL_TIMEOUT_MS;\n const started = Date.now();\n const smokeTargets = opts.smokePackages ?? packages;\n const loaded = smokeTargets.map((p) => ({ name: p.name, loaded: null as boolean | null }));\n let installed = false;\n let error: string | null = null;\n\n // Build install command up front so a bad spec fails before we spend a VM.\n const install = installCommand(specs, allowScripts);\n\n // Lazy-load e2b: its CJS build does require('chalk'), and chalk@5 is\n // ESM-only, which crashes require(esm) on some Node 22.x versions. Keeping\n // it off the import graph means the crash can only ever reach `verify`,\n // never `lurq` startup. (tsup would otherwise hoist a static top-level\n // `import` even though sandbox/index.ts loads this module dynamically.)\n const { default: Sandbox } = await import('e2b');\n\n // Sandbox lifetime must outlast install + every smoke run, plus buffer.\n const createOpts = {\n apiKey: config.E2B_API_KEY,\n timeoutMs: installTimeout + SMOKE_TIMEOUT_MS * packages.length + 30_000,\n };\n const sandbox = config.E2B_TEMPLATE\n ? await Sandbox.create(config.E2B_TEMPLATE, createOpts)\n : await Sandbox.create(createOpts);\n\n try {\n await sandbox.files.write(\n `${WORKDIR}/package.json`,\n JSON.stringify({ name: 'lurq-sandbox', version: '0.0.0', private: true }),\n );\n await sandbox.commands.run(install, { cwd: WORKDIR, timeoutMs: installTimeout });\n installed = true;\n\n for (let i = 0; i < smokeTargets.length; i++) {\n try {\n await sandbox.commands.run(smokeCommand(smokeTargets[i]!.name), {\n cwd: WORKDIR,\n timeoutMs: SMOKE_TIMEOUT_MS,\n });\n loaded[i]!.loaded = true;\n } catch (err) {\n loaded[i]!.loaded = false;\n if (!error) error = condense(errText(err));\n }\n }\n } catch (err) {\n error = condense(errText(err));\n } finally {\n await sandbox.kill().catch(() => {});\n }\n\n return {\n driver: this.name,\n moduleSystem: target.moduleSystem,\n installed,\n loaded,\n durationMs: Date.now() - started,\n error,\n };\n }\n\n async exec(command: string, opts: ExecOptions = {}): Promise<ExecResult> {\n const config = getConfig();\n const timeoutMs = opts.timeoutMs ?? SMOKE_TIMEOUT_MS;\n // Build the install command first so a bad spec fails before we spend a VM.\n const install = opts.install?.length\n ? installCommand(opts.install.map(toSpec), opts.allowScripts ?? false)\n : null;\n\n const { default: Sandbox } = await import('e2b');\n const createOpts = {\n apiKey: config.E2B_API_KEY,\n timeoutMs: (install ? INSTALL_TIMEOUT_MS : 0) + timeoutMs + 30_000,\n };\n const sandbox = config.E2B_TEMPLATE\n ? await Sandbox.create(config.E2B_TEMPLATE, createOpts)\n : await Sandbox.create(createOpts);\n\n try {\n await sandbox.files.write(\n `${WORKDIR}/package.json`,\n JSON.stringify({ name: 'lurq-sandbox', version: '0.0.0', private: true }),\n );\n if (install) {\n await sandbox.commands.run(install, { cwd: WORKDIR, timeoutMs: INSTALL_TIMEOUT_MS });\n }\n const out = await sandbox.commands.run(command, { cwd: WORKDIR, timeoutMs });\n return { exitCode: out.exitCode ?? 0, stdout: out.stdout ?? '', stderr: out.stderr ?? '' };\n } catch (err) {\n // A non-zero exit is a result the oracle interprets, not a thrown error.\n const e = err as { exitCode?: unknown; stdout?: unknown; stderr?: unknown };\n if (typeof e?.exitCode === 'number') {\n return {\n exitCode: e.exitCode,\n stdout: typeof e.stdout === 'string' ? e.stdout : '',\n stderr: typeof e.stderr === 'string' ? e.stderr : errText(err),\n };\n }\n throw err; // VM/timeout failure — infrastructure, not the subject\n } finally {\n await sandbox.kill().catch(() => {});\n }\n }\n\n async getRuntimeInfo(): Promise<{ nodeVersion: string; npmVersion: string }> {\n let nodeVersion = 'unknown';\n let npmVersion = 'unknown';\n const config = getConfig();\n try {\n const { default: Sandbox } = await import('e2b');\n const createOpts = { apiKey: config.E2B_API_KEY, timeoutMs: 30_000 };\n const sandbox = config.E2B_TEMPLATE\n ? await Sandbox.create(config.E2B_TEMPLATE, createOpts)\n : await Sandbox.create(createOpts);\n try {\n const nodeOut = await sandbox.commands.run('node --version');\n nodeVersion = (nodeOut.stdout ?? '').trim() || 'unknown';\n const npmOut = await sandbox.commands.run('npm --version');\n npmVersion = (npmOut.stdout ?? '').trim() || 'unknown';\n } finally {\n await sandbox.kill().catch(() => {});\n }\n } catch { /* ignore */ }\n return { nodeVersion, npmVersion };\n }\n}\n","/**\n * Sandbox driver selection. With E2B_API_KEY set, the VM-isolated E2B driver is\n * used (safe for untrusted packages); otherwise the local child-process driver\n * (trusted packages only). The E2B module is imported lazily so its heavy SDK\n * never loads on the CLI/install path when isolation isn't configured.\n */\nimport { getConfig } from '../core/config';\nimport { LocalSandbox } from './local';\nimport type { Sandbox } from './types';\n\nexport async function getSandbox(): Promise<Sandbox> {\n if (getConfig().E2B_API_KEY) {\n const { E2BSandbox } = await import('./e2b');\n return new E2BSandbox();\n }\n return new LocalSandbox();\n}\n\nexport * from './types';\nexport { LocalSandbox, npmInstallArgs, smokeScript } from './local';\n","/**\n * Run a package version through the sandbox and persist the result. Decoupled\n * from the query path: an operator/cron drives this in the background and the\n * stored verdict is read instantly at recommend/verify time.\n */\nimport type { Database } from '../db/client';\nimport { storeVerificationRun } from '../db/verification';\nimport { getSandbox } from '../sandbox';\nimport type { SandboxResult, SandboxVerifyOptions } from '../sandbox/types';\n\nexport async function verifyPackageInSandbox(\n db: Database,\n pkg: string,\n version: string | null,\n opts: SandboxVerifyOptions = {},\n): Promise<SandboxResult> {\n const result = await (await getSandbox()).verify(pkg, version, opts);\n // Persist for the query path. Non-fatal: never fail the run on a write error.\n await storeVerificationRun(db, {\n packageName: pkg,\n version: version ?? 'latest',\n driver: result.driver,\n moduleSystem: result.moduleSystem,\n installed: result.installed,\n imported: result.imported,\n ranScripts: result.ranScripts,\n durationMs: result.durationMs,\n error: result.error,\n ranAt: new Date(),\n }).catch(() => {});\n return result;\n}\n","/**\n * Tier-2 resolve-only compat check (§4C). Ask npm to *resolve* a package set\n * without installing it: `npm install --package-lock-only` builds the lockfile\n * (or fails with ERESOLVE) from registry metadata alone — no tarballs, no build,\n * no VM. This catches the version-conflict class (diamond deps, unsatisfiable\n * peer ranges) that Tier-0 declared analysis can't see, at a fraction of the\n * sandbox's cost. The sandbox (Tier-3) is reserved for runtime proof only.\n */\nimport { execFile } from 'node:child_process';\nimport { mkdtemp, rm, writeFile } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport { promisify } from 'node:util';\n\nconst execFileP = promisify(execFile);\n\nexport interface ResolveResult {\n /** True if npm produced a lockfile (the set co-resolves). */\n resolved: boolean;\n /** 'ERESOLVE' when a proven version conflict; null on success. */\n reason: 'ERESOLVE' | null;\n}\n\n/**\n * Resolve a package set without installing it. Returns resolved:false only for a\n * *proven* conflict (ERESOLVE); transient failures (network, timeout) throw so\n * the caller treats them as inconclusive and never records a false conflict.\n */\nexport async function resolveSet(\n specs: { name: string; version: string | null }[],\n opts: { timeoutMs?: number } = {},\n): Promise<ResolveResult> {\n const dir = await mkdtemp(join(tmpdir(), 'lurq-resolve-'));\n try {\n const dependencies: Record<string, string> = {};\n for (const s of specs) dependencies[s.name] = s.version ?? 'latest';\n await writeFile(\n join(dir, 'package.json'),\n JSON.stringify({ name: 'lurq-resolve', private: true, dependencies }),\n );\n // Default (non-legacy) peer resolution is exactly what we want: npm ERESOLVEs\n // on a genuine peer/version conflict instead of silently papering over it.\n await execFileP('npm', ['install', '--package-lock-only', '--no-audit', '--no-fund'], {\n cwd: dir,\n timeout: opts.timeoutMs ?? 60_000,\n });\n return { resolved: true, reason: null };\n } catch (err) {\n const msg =\n (err as { stderr?: string }).stderr ?? (err as Error).message ?? '';\n if (/ERESOLVE/i.test(msg)) return { resolved: false, reason: 'ERESOLVE' };\n throw err; // network / timeout / other — inconclusive, not a proven conflict\n } finally {\n await rm(dir, { recursive: true, force: true }).catch(() => {});\n }\n}\n","/**\n * Compatibility verification: co-install a set of packages in the sandbox and\n * record pairwise edges. A successful co-install proves the set coexists (every\n * pair compatible); a 2-package failure proves that pair conflicts. A larger\n * failed set can't pin the culprit, so no edge is asserted (set-level report).\n */\nimport type { CompatStatus } from '../core/types';\nimport { logger } from '../core/logger';\nimport type { Database } from '../db/client';\nimport {\n bumpCompatVerifyAttempt,\n canonicalPair,\n deleteCompatVerify,\n fullyCovered,\n getCompatEdges,\n getPendingCompatVerify,\n pairKey,\n upsertCompatEdge,\n} from '../db/compat';\nimport { getPackageByName, getTopPackageNames } from '../db/packages';\nimport { getSandbox } from '../sandbox';\nimport type { SandboxSetResult } from '../sandbox/types';\nimport { resolveSet } from './resolveCheck';\n\n// Re-exported: the pure pair helpers live in the light db layer (so the query\n// path can use them without pulling in the sandbox), but they were minted here.\nexport { fullyCovered, pairKey } from '../db/compat';\n\nexport interface CompatEdge {\n a: string;\n aVersion: string;\n b: string;\n bVersion: string;\n status: CompatStatus;\n}\n\ninterface Resolved {\n name: string;\n version: string;\n}\n\n/**\n * Pairwise edges from a set-level outcome. Pure, shared by every tier (sandbox\n * co-install, resolve-only): a success proves the whole set coexists → every pair\n * compatible; a failed *pair* is precise → conflict; a larger failed set can't\n * attribute the culprit → no edge.\n */\nfunction pairwiseEdges(resolved: Resolved[], success: boolean): CompatEdge[] {\n const edges: CompatEdge[] = [];\n if (success) {\n for (let i = 0; i < resolved.length; i++) {\n for (let j = i + 1; j < resolved.length; j++) {\n edges.push({\n a: resolved[i]!.name,\n aVersion: resolved[i]!.version,\n b: resolved[j]!.name,\n bVersion: resolved[j]!.version,\n status: 'compatible',\n });\n }\n }\n } else if (resolved.length === 2) {\n edges.push({\n a: resolved[0]!.name,\n aVersion: resolved[0]!.version,\n b: resolved[1]!.name,\n bVersion: resolved[1]!.version,\n status: 'conflict',\n });\n }\n return edges;\n}\n\n/** Derive pairwise edges from a sandbox set co-install result. Pure. */\nexport function deriveCompatEdges(resolved: Resolved[], result: SandboxSetResult): CompatEdge[] {\n return pairwiseEdges(resolved, result.installed && result.loaded.every((l) => l.loaded === true));\n}\n\nexport interface CompatRunResult {\n result: SandboxSetResult;\n edges: CompatEdge[];\n /** A set-level conflict that couldn't be pinned to a specific pair. */\n unattributedConflict: boolean;\n}\n\nexport async function verifyCompatibility(\n db: Database,\n packages: string[],\n opts: { allowScripts?: boolean } = {},\n): Promise<CompatRunResult> {\n const resolved: Resolved[] = await Promise.all(\n packages.map(async (name) => ({\n name,\n version: (await getPackageByName(db, name))?.latestVersion ?? 'latest',\n })),\n );\n\n const result = await (await getSandbox()).verifySet(\n resolved.map((r) => ({ name: r.name, version: r.version === 'latest' ? null : r.version })),\n { allowScripts: opts.allowScripts },\n );\n\n const edges = deriveCompatEdges(resolved, result);\n await persistCompatEdges(db, edges, 'verified', result.driver);\n\n const failed = !result.installed || !result.loaded.every((l) => l.loaded === true);\n return { result, edges, unattributedConflict: failed && edges.length === 0 };\n}\n\n/** Upsert derived edges with a given evidence class. A compatible edge carries the\n * caller's provenance (`verified` for sandbox runtime proof, `observed` for a\n * resolve-only co-resolution witness); a conflict is always the proven-negative\n * `conflict`. Provenance precedence means a weaker tier never erases a stronger. */\nasync function persistCompatEdges(\n db: Database,\n edges: CompatEdge[],\n compatibleProvenance: 'verified' | 'observed',\n driver: string,\n): Promise<void> {\n const now = new Date();\n for (const e of edges) {\n const pair = canonicalPair(\n { name: e.a, version: e.aVersion },\n { name: e.b, version: e.bVersion },\n );\n await upsertCompatEdge(db, {\n ...pair,\n status: e.status,\n provenance: e.status === 'conflict' ? 'conflict' : compatibleProvenance,\n // Witness accrues for co-resolution evidence (`observed`); ignored otherwise.\n witnessCount: e.status === 'compatible' && compatibleProvenance === 'observed' ? 1 : 0,\n driver,\n ranAt: now,\n }).catch(() => {});\n }\n}\n\nexport interface ResolveCompatResult {\n edges: CompatEdge[];\n /** True if the set co-resolves; false only on a proven ERESOLVE conflict. */\n resolved: boolean;\n}\n\n/**\n * Tier-2 resolve-only verify (§4C): resolve a package set with npm (no install,\n * no VM) and mint `observed`-class edges — a proven co-resolution, but not the\n * runtime proof a sandbox gives, so it never overrides a `verified`/`conflict`.\n * An ERESOLVE on a pair is a real `conflict`. Inconclusive resolves (network,\n * timeout) throw so the caller can retry rather than record a false result.\n */\nasync function resolveVerifyCompatibility(\n db: Database,\n packages: string[],\n): Promise<ResolveCompatResult> {\n const resolved: Resolved[] = await Promise.all(\n packages.map(async (name) => ({\n name,\n version: (await getPackageByName(db, name))?.latestVersion ?? 'latest',\n })),\n );\n const res = await resolveSet(\n resolved.map((r) => ({ name: r.name, version: r.version === 'latest' ? null : r.version })),\n );\n const edges = pairwiseEdges(resolved, res.resolved);\n await persistCompatEdges(db, edges, 'observed', 'npm-resolve');\n return { edges, resolved: res.resolved };\n}\n\n// ── Targeted backfill (§4C) ───────────────────────────────────────────────────\n\n/** Name-pair keys that already have *any* stored edge among `names` — the pairs\n * a sandbox run would waste itself on (§4C: sandbox is only for unverified). */\nasync function coveredPairs(db: Database, names: string[]): Promise<Set<string>> {\n const edges = await getCompatEdges(db, names);\n return new Set(edges.map((e) => pairKey(e.packageA, e.packageB)));\n}\n\nexport interface BackfillResult {\n batches: number;\n verified: number;\n skipped: number;\n}\n\ntype BatchRunner = (db: Database, batch: string[]) => Promise<{ edges: CompatEdge[] }>;\n\n/**\n * Batch the top-N popular tracked packages and settle each batch with `runner`,\n * minting edges for every pair that mining/Tier-0 left uncovered (§4C). One\n * K-package run yields all C(K,2) edges, so per-edge cost is sublinear; batches\n * already fully covered are skipped — no wasted run. The runner is the tier:\n * sandbox (runtime proof, expensive) or resolve-only (co-resolution, cheap).\n */\nasync function runBackfill(\n db: Database,\n opts: { topN?: number; batchSize?: number },\n runner: BatchRunner,\n label: string,\n): Promise<BackfillResult> {\n const topN = opts.topN ?? 50;\n const batchSize = Math.max(2, opts.batchSize ?? 5);\n const names = await getTopPackageNames(db, topN);\n const covered = await coveredPairs(db, names);\n\n let verified = 0;\n let batches = 0;\n let skipped = 0;\n for (let i = 0; i < names.length; i += batchSize) {\n const batch = names.slice(i, i + batchSize);\n if (batch.length < 2) continue;\n if (fullyCovered(batch, covered)) {\n skipped++;\n continue;\n }\n logger.info(`${label}: ${batch.join(', ')}`);\n const { edges } = await runner(db, batch).catch((err) => {\n logger.warn(`${label} batch failed (${batch.join(', ')}): ${String(err)}`);\n return { edges: [] as CompatEdge[] };\n });\n verified += edges.length;\n batches++;\n }\n logger.info(`${label}: ${verified} edges across ${batches} runs, ${skipped} batches skipped`);\n return { batches, verified, skipped };\n}\n\n/** Sandbox backfill (Tier-3, runtime proof) — reserve E2B for where it buys most. */\nexport async function backfillVerify(\n db: Database,\n opts: { topN?: number; batchSize?: number } = {},\n): Promise<BackfillResult> {\n return runBackfill(db, opts, verifyCompatibility, 'backfill(sandbox)');\n}\n\n/** Resolve-only backfill (Tier-2, no VM) — cheap enough to pre-warm the whole\n * corpus before launch; escalate ambiguous pairs to `backfillVerify` later. */\nexport async function resolveBackfill(\n db: Database,\n opts: { topN?: number; batchSize?: number } = {},\n): Promise<BackfillResult> {\n return runBackfill(db, opts, resolveVerifyCompatibility, 'backfill(resolve)');\n}\n\n// ── Demand-driven self-heal drain (§4C) ───────────────────────────────────────\n\nconst MAX_COMPAT_VERIFY_ATTEMPTS = 3;\n\nexport interface DrainResult {\n processed: number;\n verified: number;\n dropped: number;\n}\n\n/**\n * Drain the demand-driven compat-verify queue (§4C): pop the oldest pending sets\n * (capped) and settle each with the *resolve-only* tier (npm resolution, no VM),\n * minting observed/conflict edges so a real `compat` query that missed gets a\n * real answer on the next ask — cheaply. A set already covered by edges since it\n * was queued (backfill/remine/another drain got there first) is dropped without\n * any work; a set that keeps failing (network/timeout — never a proven conflict)\n * is dropped after MAX attempts so a bad request can't wedge the queue. Runtime\n * proof (the sandbox tier) stays with the deliberate `compat-backfill` path.\n */\nexport async function drainCompatVerifyQueue(\n db: Database,\n opts: { limit?: number } = {},\n): Promise<DrainResult> {\n const limit = Math.max(1, opts.limit ?? 10);\n const pending = await getPendingCompatVerify(db, limit);\n let verified = 0;\n let dropped = 0;\n for (const req of pending) {\n const names = req.packages;\n if (fullyCovered(names, await coveredPairs(db, names))) {\n await deleteCompatVerify(db, req.id);\n continue;\n }\n try {\n const { edges } = await resolveVerifyCompatibility(db, names);\n verified += edges.length;\n await deleteCompatVerify(db, req.id);\n } catch (err) {\n logger.warn(`compat-verify drain failed for ${names.join(', ')}: ${String(err)}`);\n const attempts = await bumpCompatVerifyAttempt(db, req.id);\n if (attempts >= MAX_COMPAT_VERIFY_ATTEMPTS) {\n await deleteCompatVerify(db, req.id);\n dropped++;\n }\n }\n }\n logger.info(\n `compat-verify: ${verified} edge(s) from ${pending.length} queued set(s), ${dropped} dropped`,\n );\n return { processed: pending.length, verified, dropped };\n}\n","/**\n * Human-facing CLI command implementations (§13). Each reuses the MCP handlers\n * against a DB connection, then renders a compact table/detail view — or raw\n * JSON with `--json`.\n */\nimport semver from 'semver';\nimport { requireConfig } from '../core/config';\nimport { isCategory, type Category, type Confidence } from '../core/types';\nimport { createDb } from '../db/client';\nimport { getPackageVersions } from '../db/packages';\nimport { handleCompare, handleEvaluate, handleRecommend, handleVerify } from '../mcp/handlers';\nimport { CONFIDENCE, QUALITY_WEIGHTS } from '../scoring/weights';\nimport {\n activeWeightsPath,\n applyOverrides,\n loadWeights,\n resetWeights,\n saveWeights,\n settableKeys,\n validateWeights,\n WEIGHT_EXPLANATIONS,\n} from '../scoring/weights';\nimport {\n bold,\n confidenceLabel,\n detail,\n dim,\n formatDate,\n formatNumber,\n formatPercent,\n green,\n red,\n table,\n yellow,\n} from './format';\n\nasync function withDb<T>(fn: (db: ReturnType<typeof createDb>['db']) => Promise<T>): Promise<T> {\n requireConfig(['DATABASE_URL']);\n const handle = createDb();\n try {\n return await fn(handle.db);\n } finally {\n await handle.close();\n }\n}\n\nexport interface RecommendCliOpts {\n category?: string;\n minConfidence?: string;\n json?: boolean;\n}\n\nexport async function runRecommend(need: string, opts: RecommendCliOpts): Promise<void> {\n if (opts.category && !isCategory(opts.category)) {\n throw new Error(`Unknown category \"${opts.category}\".`);\n }\n await withDb(async (db) => {\n const res = await handleRecommend(db, {\n need,\n category: opts.category as Category | undefined,\n constraints: opts.minConfidence\n ? { minConfidence: opts.minConfidence as Confidence }\n : undefined,\n });\n if (opts.json) return console.log(JSON.stringify(res, null, 2));\n if (res.candidates.length === 0) {\n console.log('No matching packages found.');\n return;\n }\n console.log(\n table(\n ['Package', 'Health', 'Quality', 'Confidence', 'Weekly', 'Latest', 'Category'],\n res.candidates.map((c) => [\n c.name,\n String(c.healthScore),\n c.qualityScore != null ? String(c.qualityScore) : '—',\n confidenceLabel(c.confidence),\n formatNumber(c.weeklyDownloads),\n c.latestVersion ?? '—',\n c.category ?? '—',\n ]),\n ),\n );\n console.log(dim(`\\ndata as of ${formatDate(res.dataAsOf)}`));\n });\n}\n\nexport async function runEvaluate(pkg: string, opts: { json?: boolean }): Promise<void> {\n await withDb(async (db) => {\n const res = await handleEvaluate(db, { package: pkg });\n if (opts.json) return console.log(JSON.stringify(res, null, 2));\n if ('tracked' in res) {\n console.log(res.suggestion);\n return;\n }\n console.log(bold(res.name) + (res.category ? dim(` (${res.category})`) : ''));\n const b = res.scoreBreakdown;\n console.log(\n detail([\n ['health', `${res.healthScore} ${confidenceLabel(res.confidence)}`],\n ['quality', res.qualityScore != null ? String(res.qualityScore) : '—'],\n [\n 'breakdown',\n `maint ${b.maintenance} · adopt ${b.adoption} · rel ${b.reliability} · eff ${b.efficiency ?? '—'} · qual ${b.quality ?? '—'}`,\n ],\n ['version', res.latestVersion ?? '—'],\n ['weekly dl', `${formatNumber(res.weeklyDownloads)} (${formatPercent(res.downloadGrowth90d)} 90d)`],\n ['scorecard', res.scorecard != null ? String(res.scorecard) : '—'],\n ['bundle', res.bundleMinGzipKb != null ? `${res.bundleMinGzipKb} KB gzip` : '—'],\n ['released', formatDate(res.lastReleaseAt)],\n ['flags', [res.deprecated && 'deprecated', res.archived && 'archived'].filter(Boolean).join(', ') || 'none'],\n ['advisories', res.advisories.length ? res.advisories.map((a) => `${a.severity}`).join(', ') : 'none'],\n ['repo', res.repoUrl ?? '—'],\n ]),\n );\n if (res.buildVerified) {\n const bv = res.buildVerified;\n const state = !bv.installed\n ? red('install failed')\n : bv.loaded === false\n ? yellow('installs, load failed')\n : green('installs and loads');\n console.log(`\\nsandbox: ${state} ${dim(`${bv.version} · ${bv.driver}`)}`);\n }\n if (res.summary) console.log('\\n' + res.summary);\n if (res.usageGuide) {\n const g = res.usageGuide;\n console.log(\n '\\n' +\n detail(\n [\n ['what', g.whatItIs],\n ['when', g.whenToUse],\n g.whenNotToUse ? (['when not', g.whenNotToUse] as [string, string]) : null,\n ['fits', g.whereItFits],\n g.howToWireIn ? (['wire-in', g.howToWireIn] as [string, string]) : null,\n ].filter(Boolean) as [string, string][],\n ),\n );\n }\n console.log(dim(`\\ndata as of ${formatDate(res.dataAsOf)}${res.stale ? ' (stale)' : ''}`));\n });\n}\n\nexport async function runCompare(pkgs: string[], opts: { json?: boolean }): Promise<void> {\n await withDb(async (db) => {\n const res = await handleCompare(db, { packages: pkgs });\n if (opts.json) return console.log(JSON.stringify(res, null, 2));\n console.log(\n table(\n ['Package', 'Health', 'Confidence', 'Weekly', '90d', 'Scorecard', 'Released'],\n res.rows.map((r) => [\n r.name,\n String(r.healthScore),\n confidenceLabel(r.confidence),\n formatNumber(r.weeklyDownloads),\n formatPercent(r.downloadGrowth90d),\n r.scorecard != null ? String(r.scorecard) : '—',\n formatDate(r.lastReleaseAt),\n ]),\n ),\n );\n if (res.missing?.length) console.log(dim(`\\nnot found: ${res.missing.join(', ')}`));\n console.log(dim(`data as of ${formatDate(res.dataAsOf)}`));\n });\n}\n\n// ── weights / edit-weights (§4) ──────────────────────────────────────────────\n\n/** `lurq weights` — show + explain the score model (no DB needed). */\nexport function runWeights(opts: { json?: boolean } = {}): void {\n const w = loadWeights();\n const active = activeWeightsPath();\n if (opts.json) {\n console.log(JSON.stringify({ ...w, source: active?.source ?? 'defaults' }, null, 2));\n return;\n }\n const pct = (n: number) => n.toFixed(2);\n console.log(bold('Two axes, blended for default sort:'));\n console.log(` composite = (1−λ)·health + λ·quality λ = ${pct(w.composite.lambda)}\\n`);\n console.log(bold('Health (proven-ness) — weighted sum of 4 components:'));\n console.log(\n detail([\n ['maintenance', `${pct(w.health.maintenance)} ${dim('— ' + WEIGHT_EXPLANATIONS.maintenance!)}`],\n ['adoption', `${pct(w.health.adoption)} ${dim('— ' + WEIGHT_EXPLANATIONS.adoption!)}`],\n ['reliability', `${pct(w.health.reliability)} ${dim('— ' + WEIGHT_EXPLANATIONS.reliability!)}`],\n ['efficiency', `${pct(w.health.efficiency)} ${dim('— ' + WEIGHT_EXPLANATIONS.efficiency!)}`],\n ]),\n );\n console.log('\\n' + bold('Quality (intrinsic, adoption-independent):'));\n console.log(' ' + dim(Object.keys(QUALITY_WEIGHTS).join(', ')));\n console.log('\\n' + bold('Confidence thresholds:'));\n console.log(\n detail([\n ['proven', `≥ ${formatNumber(CONFIDENCE.proven.minWeeklyDownloads)} weekly dl, ≥ ${CONFIDENCE.proven.minAgeMonths}mo old`],\n ['emerging', `≥ ${formatNumber(CONFIDENCE.emerging.minWeeklyDownloads)} weekly dl OR ≥ ${CONFIDENCE.emerging.strongGrowth * 100}% 90d growth`],\n ['promising', `≥ ${CONFIDENCE.promising.minQuality} quality score (adoption-independent)`],\n ]),\n );\n console.log(dim(`\\nSource: ${active ? `${active.source} (${active.path})` : 'defaults (no user overrides)'}`));\n}\n\nexport interface EditWeightsOpts {\n set?: string[];\n reset?: boolean;\n explain?: string;\n project?: boolean;\n json?: boolean;\n}\n\n/** `lurq edit-weights` — override / reset / explain the model (no DB needed).\n * A weight change alters ranking at read time, so invalidate the response cache\n * (no-op without REDIS_URL) when run where the index is served. */\nexport async function runEditWeights(opts: EditWeightsOpts): Promise<void> {\n const { invalidateCache } = await import('../core/cache');\n if (opts.reset) {\n const removed = resetWeights();\n console.log(removed.length ? `Removed overrides:\\n ${removed.join('\\n ')}` : 'No overrides to remove; already on defaults.');\n if (removed.length) await invalidateCache();\n return;\n }\n\n if (opts.explain) {\n const key = opts.explain;\n const text = WEIGHT_EXPLANATIONS[key];\n if (!text) {\n throw new Error(`No explanation for \"${key}\". Known: ${Object.keys(WEIGHT_EXPLANATIONS).join(', ')}.`);\n }\n console.log(`${bold(key)} — ${text}`);\n return;\n }\n\n if (opts.set && opts.set.length > 0) {\n const next = applyOverrides(loadWeights(), opts.set);\n const { weights, normalized } = validateWeights(next);\n const path = saveWeights(weights, opts.project ? 'project' : 'user');\n await invalidateCache();\n console.log(`Saved overrides to ${path}`);\n if (normalized) {\n console.log(\n yellow('Health weights did not sum to 1.0 — renormalized to: ') +\n `maint ${weights.health.maintenance.toFixed(3)}, adopt ${weights.health.adoption.toFixed(3)}, rel ${weights.health.reliability.toFixed(3)}, eff ${weights.health.efficiency.toFixed(3)}`,\n );\n }\n console.log(dim('\\nRun `lurq rescore` to apply the new health weights to the stored index.'));\n return;\n }\n\n // No action flags → behave like `lurq weights`.\n console.log(dim(`No changes. Settable keys: ${settableKeys().join(', ')}.\\n`));\n runWeights(opts);\n}\n\nexport interface PlanCliOpts {\n optimize?: string;\n json?: boolean;\n html?: string;\n open?: boolean;\n}\n\n/** Open a file/URL in the OS default app, cross-platform, best-effort. No shell\n * (avoids metacharacter injection); on Windows `cmd /c start \"\" <target>` keeps\n * spaced paths intact because Node passes each arg separately. */\nasync function openInBrowser(target: string): Promise<void> {\n const { spawn } = await import('node:child_process');\n const [cmd, args]: [string, string[]] =\n process.platform === 'darwin'\n ? ['open', [target]]\n : process.platform === 'win32'\n ? ['cmd', ['/c', 'start', '', target]]\n : ['xdg-open', [target]];\n spawn(cmd, args, { stdio: 'ignore', detached: true }).unref();\n}\n\nexport async function runPlan(file: string, opts: PlanCliOpts): Promise<void> {\n const { readFileSync } = await import('node:fs');\n let document: string;\n try {\n document = readFileSync(file, 'utf8');\n } catch {\n throw new Error(`Could not read \"${file}\".`);\n }\n if (opts.optimize && opts.optimize !== 'speed' && opts.optimize !== 'balanced') {\n throw new Error(\"--optimize must be 'speed' or 'balanced'.\");\n }\n await withDb(async (db) => {\n const { handlePlan } = await import('../mcp/plan');\n const res = await handlePlan(db, {\n document,\n optimize: opts.optimize as 'speed' | 'balanced' | undefined,\n });\n if (opts.json) return console.log(JSON.stringify(res, null, 2));\n if (!('slots' in res)) {\n console.log(res.note);\n return;\n }\n\n // Visualization: render the roadmap to a portable HTML file and optionally open it.\n if (opts.html || opts.open) {\n const { writeFileSync } = await import('node:fs');\n const { tmpdir } = await import('node:os');\n const { join } = await import('node:path');\n const { renderPlanHtml } = await import('./planView');\n const out = opts.html ?? join(tmpdir(), `lurq-plan-${Date.now()}.html`);\n writeFileSync(out, renderPlanHtml(res), 'utf8');\n console.log(`Roadmap written to ${out}`);\n if (opts.open) await openInBrowser(out);\n }\n\n console.log(\n table(\n ['Component', 'Layer', 'Recommended', 'Health', 'Confidence', 'Alternatives'],\n res.slots.map((s) => [\n s.need.length > 32 ? s.need.slice(0, 31) + '…' : s.need,\n s.layer,\n s.recommended\n ? `${s.recommended.name}@${s.recommended.latestVersion ?? '?'}`\n : dim('—'),\n s.recommended ? String(s.recommended.healthScore) : '—',\n s.recommended ? confidenceLabel(s.recommended.confidence) : '—',\n s.alternatives.map((a) => a.name).join(', ') || '—',\n ]),\n ),\n );\n if (res.unmatched.length) console.log(yellow(`\\nNo match for: ${res.unmatched.join(', ')}`));\n\n if (res.compatibility) {\n const c = res.compatibility;\n const col = c.overall === 'compatible' ? green : c.overall === 'conflict' ? red : dim;\n console.log('\\n' + bold('Compatibility: ') + col(c.overall));\n for (const s of res.slots) {\n if (s.swappedFrom && s.recommended) {\n console.log(green(` ✓ swapped ${s.swappedFrom} → ${s.recommended.name} for compatibility`));\n }\n }\n for (const cf of c.conflicts) console.log(red(` ✗ ${cf.detail} (no compatible alternative)`));\n if (c.unverified.length) console.log(dim(` unverified: ${c.unverified.join(', ')}`));\n }\n\n console.log('\\n' + bold('Roadmap (Mermaid):'));\n console.log(res.mermaid);\n console.log(dim(`\\n${res.note}`));\n console.log(dim(`data as of ${formatDate(res.dataAsOf)}`));\n });\n}\n\nexport async function runVerify(pkg: string, opts: { json?: boolean }): Promise<void> {\n await withDb(async (db) => {\n const res = await handleVerify(db, { package: pkg });\n if (opts.json) return console.log(JSON.stringify(res, null, 2));\n const riskColor = res.risk === 'high' ? red : res.risk === 'medium' ? yellow : green;\n const verdict = !res.exists\n ? red('✗ NOT FOUND on npm')\n : res.risk === 'high'\n ? red('✗ high supply-chain risk')\n : res.risk === 'medium'\n ? yellow('⚠ exists, but risky')\n : green('✓ looks safe');\n console.log(`${bold(pkg)} ${verdict}`);\n console.log(\n detail([\n ['version', res.latestVersion ?? '—'],\n ['weekly dl', formatNumber(res.weeklyDownloads)],\n ['confidence', res.confidence ? confidenceLabel(res.confidence) : '—'],\n ['advisories', String(res.advisoryCount)],\n ['risk', riskColor(res.risk)],\n ['risk flags', res.riskFlags.length ? yellow(res.riskFlags.join(', ')) : 'none'],\n ]),\n );\n });\n}\n\nexport async function runVersions(\n pkg: string,\n opts: { json?: boolean; limit?: string },\n): Promise<void> {\n const limit = opts.limit ? Math.max(1, parseInt(opts.limit, 10) || 30) : 30;\n await withDb(async (db) => {\n const versions = await getPackageVersions(db, pkg, limit);\n if (opts.json) return console.log(JSON.stringify(versions, null, 2));\n if (versions.length === 0) {\n console.log(`No stored versions for ${bold(pkg)}. Run \\`lurq sync --package ${pkg}\\` first.`);\n return;\n }\n console.log(bold(pkg));\n console.log(\n table(\n ['Version', 'Published'],\n versions.map((v) => [\n v.version,\n v.publishedAt ? v.publishedAt.toISOString().slice(0, 10) : '—',\n ]),\n ),\n );\n });\n}\n\n/** Long-running: follow the npm changes feed until interrupted (Ctrl-C). */\nexport async function runWatch(): Promise<void> {\n const { watchNpmChanges } = await import('../pipeline/watch');\n await withDb(async (db) => {\n const controller = new AbortController();\n const stop = () => controller.abort();\n process.once('SIGINT', stop);\n process.once('SIGTERM', stop);\n console.log(dim('watching npm for releases of tracked packages — Ctrl-C to stop'));\n try {\n await watchNpmChanges(db, { signal: controller.signal });\n } finally {\n process.off('SIGINT', stop);\n process.off('SIGTERM', stop);\n }\n });\n}\n\n/** Operator-side: install + smoke-load a package in the sandbox to verify it works. */\nexport async function runSandbox(\n pkg: string,\n version: string | undefined,\n opts: { esm?: boolean; allowScripts?: boolean; json?: boolean },\n): Promise<void> {\n if (opts.allowScripts) {\n console.error(\n yellow('warning: running install scripts and loading the package locally without isolation'),\n );\n }\n const { verifyPackageInSandbox } = await import('../pipeline/sandbox');\n await withDb(async (db) => {\n const result = await verifyPackageInSandbox(db, pkg, version ?? null, {\n target: { node: '20', moduleSystem: opts.esm ? 'esm' : 'cjs' },\n allowScripts: opts.allowScripts,\n });\n if (opts.json) return console.log(JSON.stringify(result, null, 2));\n const ok = result.installed && result.imported !== false;\n const label = version ? `${pkg}@${version}` : pkg;\n const verdict = ok ? green('✓ installs and loads') : red('✗ failed');\n console.log(`${bold(label)} ${verdict} ${dim(`(${result.durationMs}ms · ${result.driver})`)}`);\n console.log(\n detail([\n ['installed', result.installed ? 'yes' : 'no'],\n ['loaded', result.imported === null ? '—' : result.imported ? 'yes' : 'no'],\n ['module', result.moduleSystem],\n ['scripts', result.ranScripts ? 'ran' : 'skipped'],\n ['error', result.error ?? 'none'],\n ]),\n );\n });\n}\n\n/** Version-exact API surface + drift from a known version (§4D). */\nexport async function runUsage(\n pkg: string,\n opts: { version?: string; known?: string; json?: boolean },\n): Promise<void> {\n await withDb(async (db) => {\n const { handleUsage } = await import('../mcp/handlers');\n const res = await handleUsage(db, {\n package: pkg,\n version: opts.version,\n knownVersion: opts.known,\n });\n if (opts.json) return console.log(JSON.stringify(res, null, 2));\n\n console.log(`${bold(res.package)}${res.version ? `@${res.version}` : ''}`);\n if (res.engines) {\n const reqs = Object.entries(res.engines).map(([k, v]) => `${k} ${v}`).join(', ');\n if (reqs) console.log(dim(`requires: ${reqs}`));\n }\n if (!res.available) return console.log(dim(res.note ?? 'no API surface available'));\n\n console.log(\n table(\n ['Export', 'Kind', 'Signature'],\n (res.surface ?? []).map((s) => [s.name, s.kind, s.signature ?? '']),\n ),\n );\n\n if (res.delta) {\n const d = res.delta;\n console.log(bold(`\\nΔ from ${res.package}@${d.fromVersion}:`));\n for (const s of d.removed) console.log(red(` - ${s.name}`));\n for (const s of d.added) console.log(green(` + ${s.name}`));\n for (const r of d.renamed) console.log(yellow(` ~ ${r.from.name} → ${r.to.name}`));\n for (const c of d.changed) console.log(yellow(` ! ${c.name}: ${c.before ?? '?'} → ${c.after ?? '?'}`));\n if (!d.removed.length && !d.added.length && !d.renamed.length && !d.changed.length) {\n console.log(dim(' no API changes'));\n }\n }\n });\n}\n\n/** Operator: batched backfill of compat edges over the top-N packages (§4C).\n * `resolve` uses the cheap resolve-only tier (no VM); otherwise the sandbox. */\nexport async function runCompatBackfill(opts: {\n topN?: number;\n batchSize?: number;\n resolve?: boolean;\n}): Promise<void> {\n await withDb(async (db) => {\n const compat = await import('../pipeline/compat');\n if (opts.resolve) {\n console.error(yellow('resolve-only backfill (npm resolution, no install/VM)'));\n const res = await compat.resolveBackfill(db, opts);\n console.log(\n `${green('resolve backfill done')}: ${res.verified} edges across ${res.batches} runs, ${res.skipped} batches skipped`,\n );\n return;\n }\n console.error(\n yellow('co-installing top packages in the sandbox (loads package code locally without isolation unless E2B_API_KEY is set)'),\n );\n const res = await compat.backfillVerify(db, opts);\n console.log(\n `${green('backfill done')}: ${res.verified} edges across ${res.batches} runs, ${res.skipped} batches skipped`,\n );\n });\n}\n\n/**\n * `--pin next=15.5.4` → `{ next: '15.5.4' }`.\n *\n * Exact versions only, and that restriction is load-bearing rather than lazy.\n * `fetchNpmCompatAtVersion` resolves a pin by exact key against the packument\n * and falls back to `latest` when the key is absent (see\n * ingestion/sources/npmRegistry.ts) — so `--pin next=15` would quietly check\n * next@16 and report it as the pinned answer. Refusing a range here is the\n * difference between \"no result\" and \"a confident wrong result\".\n */\nfunction parsePins(pins: string[] | undefined): Record<string, string> | undefined {\n if (!pins?.length) return undefined;\n const out: Record<string, string> = {};\n for (const raw of pins) {\n const at = raw.indexOf('=');\n const name = at === -1 ? '' : raw.slice(0, at).trim();\n const version = at === -1 ? '' : raw.slice(at + 1).trim();\n if (!name || !version) throw new Error(`--pin expects name=version, got \"${raw}\"`);\n if (!semver.valid(version)) {\n throw new Error(\n `--pin needs an exact published version, got \"${name}=${version}\". ` +\n `A range resolves to latest instead of erroring, which would report the wrong version as pinned.`,\n );\n }\n out[name] = version;\n }\n return out;\n}\n\n/** Read (or, with --run, sandbox-verify then read) pairwise package compatibility. */\nexport async function runCompat(\n pkgs: string[],\n opts: { run?: boolean; json?: boolean; pin?: string[] },\n): Promise<void> {\n const versions = parsePins(opts.pin);\n await withDb(async (db) => {\n if (opts.run) {\n console.error(\n yellow('co-installing in the sandbox (loads package code locally without isolation)'),\n );\n const { verifyCompatibility } = await import('../pipeline/compat');\n await verifyCompatibility(db, pkgs);\n }\n const { handleCompat } = await import('../mcp/handlers');\n const res = await handleCompat(db, { packages: pkgs, versions });\n if (opts.json) return console.log(JSON.stringify(res, null, 2));\n const color = res.overall === 'compatible' ? green : res.overall === 'conflict' ? red : dim;\n console.log(`${bold(res.packages.join(' + '))} ${color(res.overall)}`);\n if (res.conflicts.length) {\n console.log(\n table(\n ['Source', 'Detail'],\n res.conflicts.map((c) => [c.source, c.detail]),\n ),\n );\n } else if (res.overall === 'compatible') {\n console.log(dim('no peer-dependency or engine conflicts across the set'));\n }\n if (res.unverified.length) {\n console.log(dim(`\\nunverified (no metadata): ${res.unverified.join(', ')}`));\n }\n // Evidence strength (§4B): show co-install witnesses behind each pair.\n //\n // A pair can be both: tier-1 says the declared peer range is violated, and a\n // co-resolution witness says something out there installed them together\n // anyway. The declared constraint wins, which is the whole point of tier 1,\n // but printing a bare \"observed, 1 witness\" row directly under a red\n // `conflict` reads as the tool contradicting itself. Say which one lost.\n const conflicted = new Set(\n res.conflicts.flatMap((c) =>\n c.packages.length >= 2 ? [[...c.packages].sort().join('\u0000')] : [],\n ),\n );\n const isOverruled = (e: { packages: [string, string] }) =>\n conflicted.has([...e.packages].sort().join('\u0000'));\n const compatEvidence = res.evidence.filter((e) => e.status === 'compatible');\n if (compatEvidence.length) {\n console.log(\n table(\n ['Pair', 'Evidence', 'Witnesses'],\n compatEvidence.map((e) => [\n `${e.packages[0]} + ${e.packages[1]}`,\n isOverruled(e) ? `${e.provenance} (overruled)` : e.provenance,\n e.provenance === 'observed' ? String(e.witnessCount) : '—',\n ]),\n ),\n );\n if (compatEvidence.some(isOverruled)) {\n console.log(\n dim('overruled: a declared peer/engine constraint above beats the co-resolution witness'),\n );\n }\n }\n });\n}\n","/**\n * Client for the hosted lurq API, used by the commands that run on a user's\n * machine or in their CI rather than against a local database.\n *\n * The rest of the CLI talks to Postgres directly (`withDb` in commands.ts); that\n * is right for the operator and wrong here — a GitHub Actions runner has an API\n * key and no database. This module is the whole client: two calls, no SDK.\n */\nimport { DEFAULT_ENDPOINT } from '../core/constants';\n\nexport class RemoteError extends Error {\n constructor(\n message: string,\n readonly status: number,\n ) {\n super(message);\n this.name = 'RemoteError';\n }\n}\n\n/** Endpoint the CLI talks to, with the same precedence `install` uses. */\nexport function endpoint(override?: string): string {\n const base = override ?? process.env.LURQ_ENDPOINT ?? DEFAULT_ENDPOINT;\n // The published endpoint is the MCP path; the REST routes sit beside it.\n return base.replace(/\\/mcp\\/?$/, '').replace(/\\/$/, '');\n}\n\nfunction apiKey(override?: string): string {\n const key = override ?? process.env.LURQ_API_KEY;\n if (!key) {\n throw new RemoteError(\n 'No API key. Set LURQ_API_KEY (create one at lurq.run/dashboard/keys).',\n 401,\n );\n }\n return key;\n}\n\n/**\n * Pull a human-readable message out of an error body.\n *\n * The server speaks two envelopes and the client has to read both: the REST\n * handlers send `{ error: \"some text\" }`, but every auth and rate-limit\n * rejection goes through the JSON-RPC shape `{ error: { code, message } }`.\n * Reading `.error` as a string worked for the first and stringified the second\n * to `[object Object]`, which is what a user saw for every 401 the hosted API\n * has ever returned, i.e. exactly the case where the message mattered most.\n */\nfunction errorText(body: unknown): string | undefined {\n const err = (body as { error?: unknown })?.error;\n if (typeof err === 'string') return err;\n const message = (err as { message?: unknown })?.message;\n return typeof message === 'string' ? message : undefined;\n}\n\nexport interface RemoteOptions {\n url?: string;\n apiKey?: string;\n timeoutMs?: number;\n}\n\nasync function post<T>(path: string, body: unknown, opts: RemoteOptions = {}): Promise<T> {\n const url = `${endpoint(opts.url)}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), opts.timeoutMs ?? 60_000);\n let res: Response;\n try {\n res = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey(opts.apiKey)}`,\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n } catch (err) {\n if (err instanceof RemoteError) throw err;\n const aborted = err instanceof Error && err.name === 'AbortError';\n throw new RemoteError(aborted ? `Timed out calling ${url}` : `Could not reach ${url}`, 0);\n } finally {\n clearTimeout(timer);\n }\n\n if (!res.ok) {\n const detail = await res\n .json()\n .then(errorText)\n .catch(() => undefined);\n throw new RemoteError(detail ?? `${path} failed with HTTP ${res.status}`, res.status);\n }\n return (await res.json()) as T;\n}\n\n/** Response shape of `POST /upgrade-plan` — mirrors github/brief.ts. */\nexport interface RemoteUpgrade {\n package: string;\n fromVersion: string;\n toVersion: string;\n /** Manifests declaring it — every one needs bumping, not just the root. */\n declaredIn: { path: string; range: string }[];\n /** Migration sequence for a multi-major upgrade; empty when one hop suffices. */\n hops: {\n fromVersion: string;\n toVersion: string;\n verdict: RemoteUpgrade['verdict'];\n removed: string[];\n arityChanged: { path: string; from: number | null; to: number | null }[];\n }[];\n sequenceNote?: string;\n majorsBehind: number;\n advisories: number;\n deprecated: boolean;\n verdict: 'removes-exports' | 'arity-changed' | 'clean' | 'unknown';\n removed: string[];\n arityChanged: { path: string; from: number | null; to: number | null }[];\n typeOnlyRemoved: string[];\n newlyDeprecated: string[];\n inconclusive?: string;\n}\n\nexport interface RemotePlan {\n upgrades: RemoteUpgrade[];\n omitted: number;\n pending: number;\n /** Declared dependencies lurq has no index entry for. */\n untracked: number;\n}\n\nexport function fetchUpgradePlan(\n deps: Record<string, string>,\n opts: RemoteOptions = {},\n): Promise<RemotePlan> {\n return post<RemotePlan>('/upgrade-plan', { deps }, opts);\n}\n\nexport interface ReportedRun {\n repoFullName: string;\n packageName: string;\n fromVersion: string;\n toVersion: string;\n severity: 'blocking' | 'warning' | 'ok' | 'unverified';\n status: 'checked' | 'skipped' | 'edited' | 'pr_open' | 'merged' | 'failed';\n symbolsAffected?: string[];\n callSites?: number;\n callSiteFiles?: string[];\n filesChanged?: number;\n testsPassed?: boolean | null;\n prUrl?: string | null;\n runUrl?: string;\n}\n","/**\n * `lurq upgrade-plan` and the plan half of `lurq check-upgrade`.\n *\n * These run where the code is — a laptop or a CI runner — so they read manifests\n * from disk and ask the hosted index only \"what changed between these versions\".\n * Nothing about the source is sent: the request body is the dependency block\n * that is already public in any published package.json.\n */\nimport { readFileSync, readdirSync, statSync } from 'node:fs';\nimport { join, relative } from 'node:path';\nimport { parseManifest } from '../github/manifests';\nimport type { RepoManifest } from '../github/types';\nimport { fetchUpgradePlan, type RemoteOptions, type RemotePlan, type RemoteUpgrade } from './remote';\n\n/** Directories never worth walking for a workspace manifest. */\nconst SKIP = new Set(['node_modules', '.git', 'dist', 'build', '.next', 'coverage', 'vendor']);\n\n/** Matches the server-side scan cap so local and CI plans agree. */\nconst MAX_MANIFESTS = 25;\nconst MAX_DEPTH = 4;\n\n/**\n * Find every `package.json` under `dir`, root first.\n *\n * Mirrors `manifestPaths` (which reads a GitHub tree) for the local filesystem.\n * The two deliberately apply the same rules — a plan computed in CI must match\n * what the dashboard reported, or the two views of one repo disagree.\n */\nexport function findManifests(dir: string, maxDepth = MAX_DEPTH): string[] {\n const found: string[] = [];\n\n const walk = (current: string, depth: number): void => {\n if (found.length >= MAX_MANIFESTS || depth > maxDepth) return;\n let entries: string[];\n try {\n entries = readdirSync(current);\n } catch {\n return; // unreadable directory: skip rather than abort the whole scan\n }\n if (entries.includes('package.json')) found.push(join(current, 'package.json'));\n for (const entry of entries) {\n if (SKIP.has(entry) || entry.startsWith('.')) continue;\n const child = join(current, entry);\n try {\n if (statSync(child).isDirectory()) walk(child, depth + 1);\n } catch {\n /* symlink loop or permission error — skip this entry */\n }\n }\n };\n\n walk(dir, 0);\n return found;\n}\n\n/** Read and parse every manifest under `dir`. */\nexport function readManifests(dir: string): RepoManifest[] {\n const out: RepoManifest[] = [];\n for (const file of findManifests(dir)) {\n try {\n const parsed = parseManifest(\n relative(dir, file) || 'package.json',\n JSON.parse(readFileSync(file, 'utf8')),\n );\n if (parsed) out.push(parsed);\n } catch {\n /* malformed manifest: the others still have real drift worth planning */\n }\n }\n return out;\n}\n\n/** Merge every manifest's ranges into one dependency map for the plan request. */\nexport function mergedDeps(manifests: RepoManifest[]): Record<string, string> {\n const out: Record<string, string> = {};\n for (const manifest of manifests) {\n for (const [name, range] of Object.entries(manifest.deps)) {\n out[name] ??= range;\n }\n }\n return out;\n}\n\nexport interface UpgradePlanResult extends RemotePlan {\n manifests: number;\n deps: number;\n}\n\nexport async function buildUpgradePlan(\n dir: string,\n opts: RemoteOptions = {},\n): Promise<UpgradePlanResult> {\n const manifests = readManifests(dir);\n const deps = mergedDeps(manifests);\n if (Object.keys(deps).length === 0) {\n throw new Error(`No package.json with dependencies found under ${dir}`);\n }\n const plan = await fetchUpgradePlan(deps, opts);\n return { ...plan, manifests: manifests.length, deps: Object.keys(deps).length };\n}\n\nconst VERDICT_LABEL: Record<RemoteUpgrade['verdict'], string> = {\n 'removes-exports': 'REMOVES ',\n 'arity-changed': 'ARITY ',\n clean: 'CLEAN ',\n unknown: 'UNKNOWN ',\n};\n\n/** One-screen summary. Same shape as formatUpgradeReport so the two read alike. */\nexport function formatUpgradePlan(plan: UpgradePlanResult): string {\n const out: string[] = [\n `lurq — upgrade plan (${plan.deps} dependencies across ${plan.manifests} manifest(s))`,\n '',\n ];\n\n if (plan.upgrades.length === 0) {\n out.push('Everything lurq tracks is already on its latest release.');\n }\n\n for (const upgrade of plan.upgrades) {\n out.push(\n `${VERDICT_LABEL[upgrade.verdict]} ${upgrade.package} ${upgrade.fromVersion} → ${upgrade.toVersion}` +\n (upgrade.advisories ? ` (${upgrade.advisories} advisory)` : ''),\n );\n if (upgrade.removed.length) {\n out.push(` removes ${upgrade.removed.length}: ${upgrade.removed.slice(0, 8).join(', ')}`);\n }\n for (const change of upgrade.arityChanged.slice(0, 5)) {\n out.push(` arity ${change.path}: ${change.from ?? '?'} → ${change.to ?? '?'}`);\n }\n // The migration sequence, when this crosses two or more majors. Ordering is\n // most of the work, and a single 6→8 line hides which step owns which break.\n if (upgrade.hops?.length) {\n out.push(` via ${[upgrade.fromVersion, ...upgrade.hops.map((h) => h.toVersion)].join(' → ')}`);\n for (const hop of upgrade.hops) {\n const detail = hop.removed.length\n ? `removes ${hop.removed.slice(0, 5).join(', ')}`\n : hop.verdict === 'unknown'\n ? 'not yet analysed'\n : 'no removals';\n out.push(` ${hop.fromVersion} → ${hop.toVersion}: ${detail}`);\n }\n }\n if (upgrade.sequenceNote) out.push(` ${upgrade.sequenceNote}`);\n // Only worth printing for a monorepo; a single root manifest is the default\n // assumption and saying so on every line would be noise.\n if (upgrade.declaredIn?.length > 1) {\n out.push(` declared in ${upgrade.declaredIn.map((d) => d.path).join(', ')}`);\n }\n if (upgrade.inconclusive) out.push(` ${upgrade.inconclusive}`);\n }\n\n // Never let a partial plan read as a complete one.\n const caveats: string[] = [];\n if (plan.untracked > 0) caveats.push(`${plan.untracked} dependency(ies) not in the lurq index`);\n if (plan.omitted > 0) caveats.push(`${plan.omitted} further upgrade(s) not shown`);\n if (plan.pending > 0) caveats.push(`${plan.pending} awaiting surface extraction`);\n if (caveats.length) out.push('', `NOT COVERED: ${caveats.join('; ')}.`);\n\n return out.join('\\n');\n}\n","/**\n * Reference scanner (§9.1) — what symbols does this codebase actually use from\n * each dependency, and at which file:line.\n *\n * This is the half of `check_upgrade` that makes the check COVERAGE-INDEPENDENT,\n * and it is the whole wedge: Renovate and Dependabot gate an upgrade on your test\n * suite, so an uncovered path merges green and breaks later. Comparing what the\n * code *references* against what the target version *exports* needs no tests at\n * all.\n *\n * Static and conservative by construction. It resolves what an import binds and\n * which properties are read off it; it does not attempt dynamic access\n * (`pkg[name]`), which is reported nowhere rather than guessed at — a false\n * \"you use this\" is a false blocking result, and a CI check that cries wolf gets\n * disabled inside two weeks (§12 M3's kill condition).\n */\nimport { execFileSync } from 'node:child_process';\nimport { readdirSync, readFileSync, statSync } from 'node:fs';\nimport { extname, join, relative } from 'node:path';\nimport ts from 'typescript';\n\nconst SOURCE_EXT = new Set(['.ts', '.tsx', '.mts', '.cts', '.js', '.jsx', '.mjs', '.cjs']);\nconst SKIP_DIRS = new Set(['node_modules', '.git', 'dist', 'build', 'out', '.next', 'coverage']);\n\n/**\n * How the symbol was reached — which decides whether it is a claim about the\n * MODULE'S EXPORT SURFACE or about a property of an exported value.\n *\n * named / destructured / namespace → a real export claim; tier A can verify\n * default → the module itself\n * default-member → a property of the default export's VALUE\n *\n * The last one is the important distinction. `chalk.bold` is correct chalk usage\n * but `bold` is not a module export, so scoring it against a tier-A surface\n * reports a miss on working code. Doing that in check_upgrade would block a PR\n * on valid code, which is how a CI gate gets switched off (§12 M3).\n */\nexport type ReferenceVia =\n | 'named'\n | 'destructured'\n | 'namespace'\n | 'default'\n | 'default-member'\n /**\n * A property read off a NAMED import: `import { z } from 'zod'` then\n * `z.string()`. Conditional, which is why it is not in SURFACE_CLAIM_KINDS.\n *\n * Some packages export a namespace-shaped object alongside the same names at\n * the top level, and zod is the canonical one: `z.string` and the top-level\n * `string` export are the same function. For those, the member IS checkable\n * against the module surface. For a named export that is merely an object\n * with its own unrelated properties, it is not, and conflating the two would\n * block a PR on correct code. The scorer decides using the parent's kind,\n * which only it can see; the scanner records the fact and the parent name.\n */\n | 'named-member'\n /** Erased by TypeScript before runtime — never a runtime-surface claim. */\n | 'type-only';\n\nexport interface SymbolReference {\n /** Exported name used from the package. 'default' for a default import. */\n symbol: string;\n via: ReferenceVia;\n /** Only on `named-member`: the named export the property was read from. */\n parent?: string;\n /**\n * The full import specifier. A subpath (`drizzle-orm/pg-core`) has its OWN\n * entry point and its own surface — scoring its symbols against the package\n * ROOT reports every one of them missing, on correct code.\n */\n specifier: string;\n file: string;\n line: number;\n}\n\n/** Kinds that assert something about the module's own export surface. */\nexport const SURFACE_CLAIM_KINDS: ReferenceVia[] = ['named', 'destructured', 'namespace'];\n\n/** True when the reference is against the package root rather than a subpath. */\nexport function isRootSpecifier(ref: SymbolReference, pkg: string): boolean {\n return ref.specifier === pkg;\n}\n\nexport interface PackageReferences {\n package: string;\n symbols: Map<string, SymbolReference[]>;\n}\n\n/** Bare specifier → package name (`@scope/pkg/sub` → `@scope/pkg`). */\nexport function packageOfSpecifier(spec: string): string | null {\n if (!spec || spec.startsWith('.') || spec.startsWith('/')) return null;\n if (spec.startsWith('node:')) return null;\n const parts = spec.split('/');\n return spec.startsWith('@') ? parts.slice(0, 2).join('/') : parts[0]!;\n}\n\n/**\n * Source files, asking git rather than guessing at directory names.\n *\n * SKIP_DIRS is a fixed list — `dist`, `build`, `out` — and a build output\n * directory called anything else gets walked as if it were source. lurq's own\n * repo is the proof: tsup writes to `dist-operator` (tsup.config.ts), which is\n * not on the list, so scanning this project reported symbols at\n * `dist-operator/chunk-OX3TLAEA.js:12` — a generated file nobody edits, and a\n * citation nobody can act on. Reading tsconfig's `outDir` would not have caught\n * it either, since the path is declared by the bundler, not the compiler.\n *\n * Widening the list is the wrong repair: `lib`, `es` and `esm` are build output\n * in some projects and hand-written source in others, so any name-based guess\n * either misses output or silently drops real code. The second failure is much\n * worse than the first — a missed call site turns a blocking upgrade into a\n * clean one.\n *\n * `git ls-files --cached --others --exclude-standard` is exactly the question\n * being asked: the files this project treats as its own, tracked or newly\n * written, excluding everything its own ignore rules call generated. One\n * subprocess, no glob parsing, and it uses the project's declaration rather\n * than our guess about it.\n *\n * The walk stays as the fallback, because a directory that is not a git\n * checkout still has to be scannable.\n */\nfunction listSourceFiles(dir: string, limit = 5000): string[] {\n const tracked = gitSourceFiles(dir, limit);\n if (tracked) return tracked;\n\n const out: string[] = [];\n const walk = (d: string) => {\n if (out.length >= limit) return;\n let entries: string[];\n try {\n entries = readdirSync(d);\n } catch {\n return;\n }\n for (const e of entries) {\n if (out.length >= limit) return;\n if (SKIP_DIRS.has(e) || e.startsWith('.')) continue;\n const full = join(d, e);\n let st;\n try {\n st = statSync(full);\n } catch {\n continue;\n }\n if (st.isDirectory()) walk(full);\n else if (SOURCE_EXT.has(extname(e)) && !e.endsWith('.d.ts')) out.push(full);\n }\n };\n walk(dir);\n return out;\n}\n\n/** Source files per git, or null when `dir` is not a usable checkout. */\nfunction gitSourceFiles(dir: string, limit: number): string[] | null {\n let stdout: string;\n try {\n stdout = execFileSync('git', ['ls-files', '--cached', '--others', '--exclude-standard'], {\n cwd: dir,\n encoding: 'utf8',\n maxBuffer: 32 * 1024 * 1024,\n stdio: ['ignore', 'pipe', 'ignore'],\n });\n } catch {\n return null; // not a repo, or git is unavailable — walk instead\n }\n\n const out: string[] = [];\n for (const rel of stdout.split('\\n')) {\n if (!rel || out.length >= limit) break;\n if (!SOURCE_EXT.has(extname(rel)) || rel.endsWith('.d.ts')) continue;\n // node_modules can be committed; it is never the project's own source.\n if (rel.split('/').includes('node_modules')) continue;\n out.push(join(dir, rel));\n }\n return out;\n}\n\n/**\n * Scan a codebase for the symbols it uses from each bare-specifier import.\n *\n * Namespace and default bindings are tracked so member reads resolve to the\n * right package: `import fg from 'fast-glob'` + `fg.escapePath` records\n * `escapePath`, which is what makes the §9.0 report able to name a line.\n */\n\n/**\n * Identifiers that appear in VALUE position.\n *\n * TypeScript erases imports used only as types, so a named import that never\n * appears in a value position asserts nothing about the runtime surface. This\n * is a syntactic approximation — no type checker — which is the right bias:\n * treating a genuine value use as type-only would UNDER-report, and a missed\n * detection is far cheaper than a false \"this symbol does not exist\".\n */\nfunction collectValueIdentifiers(sf: ts.SourceFile): Set<string> {\n const out = new Set<string>();\n const visit = (node: ts.Node, inType: boolean): void => {\n const nowInType = inType || ts.isTypeNode(node) || ts.isTypeQueryNode(node);\n if (\n !nowInType &&\n ts.isIdentifier(node) &&\n node.parent &&\n !ts.isImportSpecifier(node.parent) &&\n !ts.isImportClause(node.parent) &&\n !ts.isNamespaceImport(node.parent) &&\n !ts.isPropertyAccessExpression(node.parent)\n ) {\n out.add(node.text);\n }\n // A property access still uses its OBJECT in value position.\n if (!nowInType && ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.expression)) {\n out.add(node.expression.text);\n }\n ts.forEachChild(node, (c) => visit(c, nowInType));\n };\n visit(sf, false);\n return out;\n}\n\nexport function scanReferences(rootDir: string, opts: { limit?: number } = {}): PackageReferences[] {\n const byPackage = new Map<string, Map<string, SymbolReference[]>>();\n\n const record = (\n pkg: string,\n symbol: string,\n via: ReferenceVia,\n specifier: string,\n file: string,\n line: number,\n parent?: string,\n ) => {\n let syms = byPackage.get(pkg);\n if (!syms) byPackage.set(pkg, (syms = new Map()));\n const list = syms.get(symbol);\n const ref: SymbolReference = { symbol, via, specifier, file, line, ...(parent ? { parent } : {}) };\n if (list) {\n // Same file:line can legitimately carry two different claims (`z` as a\n // named import, `z.string` as a member read off it), so the dedupe key\n // has to include how the symbol was reached.\n if (!list.some((r) => r.file === file && r.line === line && r.via === via)) list.push(ref);\n } else {\n syms.set(symbol, [ref]);\n }\n };\n\n for (const file of listSourceFiles(rootDir, opts.limit)) {\n let text: string;\n try {\n text = readFileSync(file, 'utf8');\n } catch {\n continue;\n }\n const rel = relative(rootDir, file);\n const sf = ts.createSourceFile(file, text, ts.ScriptTarget.Latest, true);\n const lineOf = (n: ts.Node) => sf.getLineAndCharacterOfPosition(n.getStart(sf)).line + 1;\n\n // Two binding maps, because member reads mean different things:\n // a namespace/CJS binding IS the module's exports; a default binding is a\n // VALUE that happens to have properties.\n const nsBindings = new Map<string, { pkg: string; spec: string }>();\n const defaultBindings = new Map<string, { pkg: string; spec: string }>();\n // Named imports whose properties get read: `import { z } from 'zod'` then\n // `z.string()`. Tracked separately from the other two because whether the\n // member is a claim about the module surface depends on what the parent\n // export turns out to be, and only the scorer can see that.\n const namedBindings = new Map<string, { pkg: string; spec: string; exported: string }>();\n\n // Identifiers used in VALUE position. A named import used only in type\n // position (`(req: Request) => …`) is erased by TypeScript and never\n // reaches runtime, so it asserts nothing about the runtime surface.\n // `import express, { Request, Response } from 'express'` is correct code;\n // counting Request/Response as runtime symbols reports a miss on it.\n const valueUsed = collectValueIdentifiers(sf);\n\n const visit = (node: ts.Node): void => {\n // ── ESM imports ──\n if (ts.isImportDeclaration(node) && ts.isStringLiteral(node.moduleSpecifier)) {\n const pkg = packageOfSpecifier(node.moduleSpecifier.text);\n if (pkg) {\n const clause = node.importClause;\n if (clause?.name) {\n record(pkg, 'default', 'default', node.moduleSpecifier.text, rel, lineOf(clause.name));\n defaultBindings.set(clause.name.text, { pkg, spec: node.moduleSpecifier.text });\n }\n if (clause?.namedBindings) {\n if (ts.isNamespaceImport(clause.namedBindings)) {\n nsBindings.set(clause.namedBindings.name.text, { pkg, spec: node.moduleSpecifier.text });\n } else {\n for (const el of clause.namedBindings.elements) {\n const local = el.name.text;\n const exported = el.propertyName?.text ?? local;\n const typeOnly = clause.isTypeOnly || el.isTypeOnly || !valueUsed.has(local);\n record(\n pkg,\n exported,\n typeOnly ? 'type-only' : 'named',\n node.moduleSpecifier.text,\n rel,\n lineOf(el),\n );\n if (!typeOnly) {\n namedBindings.set(local, {\n pkg,\n spec: node.moduleSpecifier.text,\n exported,\n });\n }\n }\n }\n }\n }\n }\n\n // ── CJS require ──\n if (\n ts.isVariableDeclaration(node) &&\n node.initializer &&\n ts.isCallExpression(node.initializer) &&\n ts.isIdentifier(node.initializer.expression) &&\n node.initializer.expression.text === 'require' &&\n node.initializer.arguments.length === 1 &&\n ts.isStringLiteral(node.initializer.arguments[0]!)\n ) {\n const spec = (node.initializer.arguments[0] as ts.StringLiteral).text;\n const pkg = packageOfSpecifier(spec);\n if (pkg) {\n if (ts.isIdentifier(node.name)) {\n // In CJS the binding IS module.exports, so member reads are export\n // claims — unless module.exports is a bare value, which the scorer\n // detects from the surface shape rather than guessing here.\n nsBindings.set(node.name.text, { pkg, spec });\n record(pkg, 'default', 'default', spec, rel, lineOf(node.name));\n } else if (ts.isObjectBindingPattern(node.name)) {\n for (const el of node.name.elements) {\n const name = el.propertyName ?? el.name;\n if (ts.isIdentifier(name)) record(pkg, name.text, 'destructured', spec, rel, lineOf(el));\n }\n }\n }\n }\n\n // ── member reads on a bound namespace/default/named import ──\n if (ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.expression)) {\n const local = node.expression.text;\n const ns = nsBindings.get(local);\n const def = defaultBindings.get(local);\n const named = namedBindings.get(local);\n if (ns) record(ns.pkg, node.name.text, 'namespace', ns.spec, rel, lineOf(node));\n else if (def) record(def.pkg, node.name.text, 'default-member', def.spec, rel, lineOf(node));\n else if (named) {\n record(\n named.pkg,\n node.name.text,\n 'named-member',\n named.spec,\n rel,\n lineOf(node),\n named.exported,\n );\n }\n }\n\n ts.forEachChild(node, visit);\n };\n visit(sf);\n }\n\n return [...byPackage.entries()]\n .map(([pkg, symbols]) => ({ package: pkg, symbols }))\n .sort((a, b) => a.package.localeCompare(b.package));\n}\n","/**\n * Entry-point and specifier resolution for tier-A extraction (§6.2).\n *\n * Two jobs, both boring and both load-bearing:\n * 1. Find the file `require('pkg')` actually loads: exports map → main → index.js\n * 2. Decide whether a specifier stays inside the package (recurse into it) or\n * leaves it (record as external, per defect §6.4.1)\n */\nimport { existsSync, readFileSync, statSync } from 'node:fs';\nimport { dirname, join, resolve as resolvePath, sep } from 'node:path';\n\nconst EXTENSIONS = ['.js', '.cjs', '.mjs', '.json'];\n\nexport interface PackageManifest {\n name?: string;\n version?: string;\n main?: string;\n module?: string;\n types?: string;\n typings?: string;\n exports?: unknown;\n peerDependencies?: Record<string, string>;\n}\n\nexport function readManifest(pkgDir: string): PackageManifest | null {\n const p = join(pkgDir, 'package.json');\n if (!existsSync(p)) return null;\n try {\n return JSON.parse(readFileSync(p, 'utf8')) as PackageManifest;\n } catch {\n return null;\n }\n}\n\n\n/** The conditions tier A will read an entry from, best first. */\nconst CONDITIONS = ['require', 'node', 'default', 'import', 'module'] as const;\n\n/** A subpath map keys entries by path (`\".\"`, `\"./pg-core\"`); a condition map\n * keys them by condition (`\"require\"`, `\"import\"`). One dot tells them apart. */\nfunction isSubpathMap(o: Record<string, unknown>): boolean {\n return Object.keys(o).some((k) => k.startsWith('.'));\n}\n\n/**\n * Match a subpath key against an `exports` pattern containing one `*`.\n * `./pg-core` against `./*` captures `pg-core`; the capture is substituted back\n * into the target, which is how `\"./*\": \"./dist/*.js\"` resolves.\n */\nfunction matchWildcard(pattern: string, key: string): string | null {\n const star = pattern.indexOf('*');\n if (star === -1) return null;\n const pre = pattern.slice(0, star);\n const post = pattern.slice(star + 1);\n if (key.length < pre.length + post.length) return null;\n if (!key.startsWith(pre) || !key.endsWith(post)) return null;\n return key.slice(pre.length, key.length - post.length);\n}\n\n/**\n * Every entry an `exports` map offers for one subpath key, in condition order.\n *\n * Collecting rather than short-circuiting, so a caller whose first choice\n * extracted nothing has the remaining conditions to try. Duplicates are fine\n * here — resolveEntryCandidates dedupes on the resolved path, which is what\n * actually has to be distinct.\n *\n * `key` is `\".\"` for the package root and `\"./pg-core\"` for a subpath. Without\n * it this could only ever answer for the root, which is why\n * `drizzle-orm/pg-core` had no surface to compare against and every symbol\n * imported from it went unchecked.\n */\nfunction pickAllFromExports(exp: unknown, key = '.', depth = 0): string[] {\n if (depth > 8) return [];\n // A bare string `exports` declares the root entry and nothing else.\n if (typeof exp === 'string') return key === '.' ? [exp] : [];\n if (Array.isArray(exp)) return exp.flatMap((e) => pickAllFromExports(e, key, depth + 1));\n if (!exp || typeof exp !== 'object') return [];\n const o = exp as Record<string, unknown>;\n\n if (isSubpathMap(o)) {\n if (key in o) return pickAllFromExports(o[key], '.', depth + 1);\n // Longest matching pattern wins, as Node does: `./lib/*` beats `./*`.\n const patterns = Object.keys(o)\n .filter((k) => k.includes('*'))\n .sort((a, b) => b.length - a.length);\n for (const p of patterns) {\n const capture = matchWildcard(p, key);\n if (capture === null) continue;\n const targets = pickAllFromExports(o[p], '.', depth + 1);\n if (targets.length) return targets.map((t) => t.split('*').join(capture));\n }\n return [];\n }\n return CONDITIONS.filter((c) => c in o).flatMap((c) => pickAllFromExports(o[c], key, depth + 1));\n}\n\n/** Resolve a file path, trying extensions and directory index files. */\nexport function resolveFile(candidate: string): string | null {\n if (existsSync(candidate)) {\n try {\n if (statSync(candidate).isFile()) return candidate;\n // directory → index.*\n for (const ext of EXTENSIONS) {\n const idx = join(candidate, `index${ext}`);\n if (existsSync(idx) && statSync(idx).isFile()) return idx;\n }\n } catch {\n return null;\n }\n }\n for (const ext of EXTENSIONS) {\n const withExt = `${candidate}${ext}`;\n if (existsSync(withExt)) return withExt;\n }\n return null;\n}\n\n/**\n * The file `require('<pkg>')` loads, or `require('<pkg>/<subpath>')` when a\n * subpath is given. Null when the package ships no usable JS entry there.\n */\nexport function resolveEntry(\n pkgDir: string,\n manifest?: PackageManifest | null,\n subpath?: string,\n): string | null {\n return resolveEntryCandidates(pkgDir, manifest, subpath)[0] ?? null;\n}\n\n/**\n * Every entry this package could reasonably be read from, best first.\n *\n * `resolveEntry` returns only the winner, which is right until the winner turns\n * out to be unreadable. An ESM-first package ships a `require` condition that is\n * a thin CJS wrapper — it re-exports through a runtime call the AST walker\n * cannot follow, so extraction resolves an entry, walks one file, and finds zero\n * exports. date-fns and vitest both did exactly that, and the result was not an\n * error: `usage` and `diff_surface` returned an empty surface for two packages\n * with hundreds of exports between them, which reads as \"this package has no\n * API\" rather than \"we could not read it\".\n *\n * So the caller gets the whole ordered list and can move on when a candidate\n * comes back empty. The order is unchanged — `require` still wins for the CJS\n * packages it was chosen for, and nothing that already extracted cleanly takes a\n * different path. This only adds somewhere to go when the first door is shut.\n *\n * With a `subpath`, the same list for that entry point instead. A subpath entry\n * has its own export surface, unrelated to the root's: `drizzle-orm/pg-core`\n * exports `pgTable`, which `drizzle-orm` does not. Scoring one against the other\n * reports every symbol missing on correct code, so those references used to be\n * dropped instead, which reported nothing missing on broken code. Both\n * directions are wrong; resolving the real entry is the only answer, and it\n * inherits the same unreadable-candidate fallback the root gets.\n */\nexport function resolveEntryCandidates(\n pkgDir: string,\n manifest?: PackageManifest | null,\n subpath?: string,\n): string[] {\n const m = manifest ?? readManifest(pkgDir);\n if (!m) return [];\n const sub = subpath?.replace(/^\\.?\\//, '').replace(/\\/$/, '');\n const specifiers = (\n sub\n ? // An `exports` map is a hard boundary in Node: a subpath it does not\n // list cannot be imported, so guessing at a file would invent a surface\n // the runtime refuses to load. The bare path is offered only for the\n // legacy main/index layout, where any real file is genuinely reachable.\n m.exports !== undefined\n ? pickAllFromExports(m.exports, `./${sub}`)\n : [`./${sub}`]\n : [\n ...(m.exports !== undefined ? pickAllFromExports(m.exports) : []),\n m.main ?? null,\n m.module ?? null,\n './index.js',\n ]\n ).filter((c): c is string => typeof c === 'string' && c.length > 0);\n\n const out: string[] = [];\n for (const c of specifiers) {\n const hit = resolveFile(resolvePath(pkgDir, c));\n if (hit && !out.includes(hit)) out.push(hit);\n }\n return out;\n}\n\n/**\n * Does this specifier stay inside the package?\n *\n * Relative specifiers do. A bare specifier (`@smithy/types`, `lodash`) does not,\n * and its names must be recorded with `origin: external:*` rather than counted as\n * this package's runtime surface — defect §6.4.1, the one that produced a phantom\n * 168-export deletion.\n */\nexport function resolvesInsidePackage(spec: string): boolean {\n return spec.startsWith('./') || spec.startsWith('../') || spec === '.' || spec === '..';\n}\n\n/** Resolve a relative specifier from `fromFile`, refusing to escape `pkgDir`. */\nexport function resolveInternal(\n fromFile: string,\n spec: string,\n pkgDir: string,\n): string | null {\n const target = resolvePath(dirname(fromFile), spec);\n const root = resolvePath(pkgDir);\n // Escaping the package root means it isn't this package's surface.\n if (target !== root && !target.startsWith(root + sep)) return null;\n return resolveFile(target);\n}\n","/**\n * Tier A — shipped-JS surface extraction via module-graph AST (§6.2).\n *\n * Answers \"does this symbol exist at runtime\", which is what decides whether an\n * import throws. Never executes the subject's code — that property is what makes\n * enterprise extraction against a customer's private registry reviewable (§9.2).\n *\n * The single most important behaviour here is that it RECURSES through the\n * package-internal module graph. `module.exports = require('./lib/x')` is\n * ubiquitous; a single-file parse returns zero exports for express, debug, and\n * react (defect §6.4.5). Coverage on the study's 12-package smoke test went 9/12\n * with two total failures → 12/12 once the graph walk landed.\n *\n * Parser: the `typescript` package, which is already a devDependency and parses\n * plain JS fine. It stays on the operator plane — see 192ca3f for why it must\n * never enter the public bundle.\n */\nimport { readFileSync } from 'node:fs';\nimport { relative } from 'node:path';\nimport ts from 'typescript';\nimport {\n readManifest,\n resolveEntryCandidates,\n resolveInternal,\n resolvesInsidePackage,\n type PackageManifest,\n} from './resolve';\nimport type { ExtractedSurface, SurfaceSymbol, SymbolKind } from './types';\n\nconst TIER = 'shipped_js_ast' as const;\nconst MAX_FILES = 400; // cycle guard is exact; this bounds pathological graphs\n\ninterface WalkCtx {\n pkgDir: string;\n visited: Set<string>;\n filesWalked: number;\n external: Set<string>;\n truncated: boolean;\n}\n\n/** Classify an expression into the IR's kind + arity. */\nfunction classify(node: ts.Node): { kind: SymbolKind; arity: number | null } {\n if (ts.isFunctionExpression(node) || ts.isArrowFunction(node) || ts.isFunctionDeclaration(node)) {\n return { kind: 'function', arity: arityOf(node) };\n }\n if (ts.isClassExpression(node) || ts.isClassDeclaration(node)) return { kind: 'class', arity: null };\n if (ts.isObjectLiteralExpression(node)) return { kind: 'object', arity: null };\n if (\n ts.isStringLiteral(node) ||\n ts.isNumericLiteral(node) ||\n node.kind === ts.SyntaxKind.TrueKeyword ||\n node.kind === ts.SyntaxKind.FalseKeyword ||\n node.kind === ts.SyntaxKind.NullKeyword\n ) {\n return { kind: 'primitive', arity: null };\n }\n return { kind: 'object', arity: null };\n}\n\n/**\n * `fn.length` semantics: parameters before the first one with a default or rest.\n * Matching the runtime definition matters because arity drift is compared against\n * values captured at tier B, where it really is `fn.length`.\n */\nfunction arityOf(fn: ts.SignatureDeclarationBase): number {\n let n = 0;\n for (const p of fn.parameters) {\n if (p.initializer || p.dotDotDotToken) break;\n n++;\n }\n return n;\n}\n\nfunction lineOf(sf: ts.SourceFile, node: ts.Node): number {\n return sf.getLineAndCharacterOfPosition(node.getStart(sf)).line + 1;\n}\n\nfunction put(\n out: Map<string, SurfaceSymbol>,\n sym: SurfaceSymbol,\n): void {\n // First writer wins: the entry file's own binding outranks a later re-export.\n if (!out.has(sym.path)) out.set(sym.path, sym);\n}\n\n/** Resolve an identifier to its initializer within the same file, if declared there. */\nfunction localBinding(sf: ts.SourceFile, name: string): ts.Node | null {\n let found: ts.Node | null = null;\n for (const stmt of sf.statements) {\n if (ts.isVariableStatement(stmt)) {\n for (const d of stmt.declarationList.declarations) {\n if (ts.isIdentifier(d.name) && d.name.text === name && d.initializer) found = d.initializer;\n }\n } else if (ts.isFunctionDeclaration(stmt) && stmt.name?.text === name) {\n found = stmt;\n } else if (ts.isClassDeclaration(stmt) && stmt.name?.text === name) {\n found = stmt;\n }\n }\n return found;\n}\n\nfunction isModuleExports(e: ts.Expression): boolean {\n return (\n ts.isPropertyAccessExpression(e) &&\n ts.isIdentifier(e.expression) &&\n e.expression.text === 'module' &&\n e.name.text === 'exports'\n );\n}\n\n/** `module.exports.X` / `exports.X` → \"X\"; null if it isn't an exports write. */\nfunction exportTargetName(e: ts.Expression): string | null {\n if (!ts.isPropertyAccessExpression(e)) return null;\n if (ts.isIdentifier(e.expression) && e.expression.text === 'exports') return e.name.text;\n if (isModuleExports(e.expression)) return e.name.text;\n return null;\n}\n\nfunction hasDeprecatedTag(sf: ts.SourceFile, node: ts.Node): boolean {\n const full = node.getFullText(sf);\n const lead = full.slice(0, full.length - node.getText(sf).length);\n return /@deprecated/i.test(lead);\n}\n\n/**\n * Top-level statements plus those nested in control flow.\n *\n * `debug` ships `if (…) { module.exports = require('./browser.js') } else { … }`\n * — a top-level-only scan returns zero exports for it, which is defect §6.4.5.\n * Function and class bodies are deliberately NOT descended into: an assignment\n * inside a function is not the module's surface.\n */\nfunction flattenStatements(\n stmts: readonly ts.Statement[],\n depth = 0,\n): ts.Statement[] {\n if (depth > 6) return [...stmts];\n const out: ts.Statement[] = [];\n for (const s of stmts) {\n out.push(s);\n if (ts.isBlock(s)) out.push(...flattenStatements(s.statements, depth + 1));\n else if (ts.isIfStatement(s)) {\n const branches = [s.thenStatement, s.elseStatement].filter(Boolean) as ts.Statement[];\n for (const b of branches) {\n out.push(...flattenStatements(ts.isBlock(b) ? b.statements : [b], depth + 1));\n }\n } else if (ts.isTryStatement(s)) {\n out.push(...flattenStatements(s.tryBlock.statements, depth + 1));\n if (s.catchClause) out.push(...flattenStatements(s.catchClause.block.statements, depth + 1));\n if (s.finallyBlock) out.push(...flattenStatements(s.finallyBlock.statements, depth + 1));\n } else if (ts.isSwitchStatement(s)) {\n for (const c of s.caseBlock.clauses) {\n out.push(...flattenStatements(c.statements, depth + 1));\n }\n }\n }\n return out;\n}\n\nfunction walk(file: string, ctx: WalkCtx, out: Map<string, SurfaceSymbol>): void {\n if (ctx.visited.has(file)) return; // cycle guard (§6.2)\n if (ctx.filesWalked >= MAX_FILES) {\n ctx.truncated = true;\n return;\n }\n ctx.visited.add(file);\n ctx.filesWalked++;\n\n let text: string;\n try {\n text = readFileSync(file, 'utf8');\n } catch {\n return;\n }\n const sf = ts.createSourceFile(file, text, ts.ScriptTarget.Latest, true, ts.ScriptKind.JS);\n const rel = relative(ctx.pkgDir, file);\n\n const add = (path: string, node: ts.Node, over: Partial<SurfaceSymbol> = {}) => {\n const { kind, arity } = classify(node);\n put(out, {\n path,\n kind,\n arity,\n origin: 'local',\n deprecated: hasDeprecatedTag(sf, node),\n tier: TIER,\n sourceRef: { file: rel, line: lineOf(sf, node) },\n ...over,\n });\n };\n\n /**\n * A re-export specifier: recurse if internal, record as external if not\n * (§6.4.1).\n *\n * `picks` carries the named subset for `export { a, b as c } from './x'`.\n * Honouring it is not optional: `uuid` re-exports one `default` per internal\n * file (`export { default as MAX } from './max.js'`), so merging the target's\n * whole surface both INVENTS its internal helpers as package exports and LOSES\n * the renamed ones. Measured at 3/10 baseline precision before this — the\n * worst class of error we can make, since it claims symbols that do not exist.\n */\n const reExport = (\n spec: string,\n names: string[] | null,\n picks?: { from: string; as: string }[],\n ): void => {\n if (resolvesInsidePackage(spec)) {\n const target = resolveInternal(file, spec, ctx.pkgDir);\n if (!target) return;\n if (!picks) {\n walk(target, ctx, out); // `export * from` — the whole surface is correct\n return;\n }\n // Selective: resolve the target's surface separately, then take only what\n // was asked for, under the name it was asked for.\n const sub = new Map<string, SurfaceSymbol>();\n walk(target, { ...ctx, visited: new Set(ctx.visited) }, sub);\n for (const pick of picks) {\n const found = sub.get(pick.from);\n if (found) put(out, { ...found, path: pick.as });\n else put(out, { path: pick.as, kind: 'object', arity: null, origin: 'local', deprecated: false, tier: TIER, sourceRef: { file: rel, line: 1 } });\n }\n return;\n }\n ctx.external.add(spec);\n for (const n of names ?? []) {\n put(out, {\n path: n,\n kind: 'object',\n arity: null,\n origin: `external:${spec}`,\n deprecated: false,\n tier: TIER,\n sourceRef: { file: rel, line: 1 },\n });\n }\n };\n\n for (const stmt of flattenStatements(sf.statements)) {\n // ── ESM ────────────────────────────────────────────────────────────────\n if (ts.isExportDeclaration(stmt)) {\n const spec =\n stmt.moduleSpecifier && ts.isStringLiteral(stmt.moduleSpecifier)\n ? stmt.moduleSpecifier.text\n : null;\n const isTypeOnly = stmt.isTypeOnly;\n if (stmt.exportClause && ts.isNamedExports(stmt.exportClause)) {\n const names = stmt.exportClause.elements.map((el) => el.name.text);\n if (spec) {\n reExport(\n spec,\n names,\n stmt.exportClause.elements.map((el) => ({\n from: el.propertyName?.text ?? el.name.text,\n as: el.name.text,\n })),\n );\n } else {\n for (const el of stmt.exportClause.elements) {\n const local = el.propertyName?.text ?? el.name.text;\n const decl = localBinding(sf, local);\n if (isTypeOnly || el.isTypeOnly) {\n put(out, {\n path: el.name.text,\n kind: 'type_only',\n arity: null,\n origin: 'local',\n deprecated: false,\n tier: TIER,\n sourceRef: { file: rel, line: lineOf(sf, el) },\n });\n } else if (decl) {\n add(el.name.text, decl);\n } else {\n add(el.name.text, el);\n }\n }\n }\n } else if (spec) {\n // `export * from '<spec>'`\n reExport(spec, null);\n }\n continue;\n }\n\n // `export const X` / `export function X` / `export class X`\n const mods = ts.canHaveModifiers(stmt) ? ts.getModifiers(stmt) : undefined;\n const exported = mods?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword);\n if (exported) {\n if (ts.isVariableStatement(stmt)) {\n for (const d of stmt.declarationList.declarations) {\n if (ts.isIdentifier(d.name)) add(d.name.text, d.initializer ?? d);\n }\n } else if (ts.isFunctionDeclaration(stmt) && stmt.name) {\n add(stmt.name.text, stmt);\n } else if (ts.isClassDeclaration(stmt) && stmt.name) {\n add(stmt.name.text, stmt);\n } else if (ts.isInterfaceDeclaration(stmt) || ts.isTypeAliasDeclaration(stmt)) {\n // §6.4.4: type-only. Never counted in runtime-surface diffs.\n put(out, {\n path: stmt.name.text,\n kind: 'type_only',\n arity: null,\n origin: 'local',\n deprecated: false,\n tier: TIER,\n sourceRef: { file: rel, line: lineOf(sf, stmt) },\n });\n }\n continue;\n }\n\n if (ts.isExportAssignment(stmt)) {\n // `export default <expr>`\n const target = ts.isIdentifier(stmt.expression)\n ? (localBinding(sf, stmt.expression.text) ?? stmt.expression)\n : stmt.expression;\n add('default', target);\n continue;\n }\n\n // ── CommonJS ───────────────────────────────────────────────────────────\n if (ts.isExpressionStatement(stmt)) {\n const e = stmt.expression;\n\n // Object.defineProperty(exports, \"name\", { get() {…} }) — Babel's CJS\n // output, and older tsc's. Extremely common on npm: uuid@9 declares its\n // entire surface this way, and without this branch every Babel-compiled\n // package extracts as zero exports and lands as UNDECLARED.\n if (\n ts.isCallExpression(e) &&\n ts.isPropertyAccessExpression(e.expression) &&\n ts.isIdentifier(e.expression.expression) &&\n e.expression.expression.text === 'Object' &&\n e.expression.name.text === 'defineProperty' &&\n e.arguments.length >= 2\n ) {\n const targetArg = e.arguments[0]!;\n const isExportsTarget =\n (ts.isIdentifier(targetArg) && targetArg.text === 'exports') ||\n isModuleExports(targetArg as ts.Expression);\n const nameArg = e.arguments[1]!;\n if (isExportsTarget && ts.isStringLiteral(nameArg) && nameArg.text !== '__esModule') {\n // The descriptor's getter usually forwards to another module\n // (`return _nil.default`), so the VALUE is not statically known — but\n // existence is, and existence is what tier A is for.\n put(out, {\n path: nameArg.text,\n kind: 'object',\n arity: null,\n origin: 'local',\n deprecated: hasDeprecatedTag(sf, stmt),\n tier: TIER,\n sourceRef: { file: rel, line: lineOf(sf, stmt) },\n });\n continue;\n }\n }\n\n // Object.assign(module.exports, X, …) / __exportStar(require('x'), …)\n if (ts.isCallExpression(e)) {\n const callee = e.expression;\n const isObjectAssign =\n ts.isPropertyAccessExpression(callee) &&\n ts.isIdentifier(callee.expression) &&\n callee.expression.text === 'Object' &&\n callee.name.text === 'assign' &&\n e.arguments.length > 0 &&\n isModuleExports(e.arguments[0]!);\n // esbuild emits `__reExport(target, require('./x'), module.exports)`, tsc\n // emits `__exportStar(require('./x'), exports)`. Helper names and argument\n // order both vary, so match the family and scan every argument for a\n // require() rather than assuming a slot.\n const isExportStar =\n ts.isIdentifier(callee) && /^_{0,2}(exportStar|reExport|export)$/i.test(callee.text);\n\n if (isObjectAssign || isExportStar) {\n for (const arg of e.arguments.slice(isObjectAssign ? 1 : 0)) {\n const spec = requireSpecifier(arg);\n if (spec) reExport(spec, null);\n else if (ts.isObjectLiteralExpression(arg)) {\n for (const p of arg.properties) {\n if (p.name && ts.isIdentifier(p.name)) {\n add(p.name.text, ts.isPropertyAssignment(p) ? p.initializer : p);\n }\n }\n } else if (ts.isIdentifier(arg)) {\n const b = localBinding(sf, arg.text);\n if (b && ts.isObjectLiteralExpression(b)) {\n for (const p of b.properties) {\n if (p.name && ts.isIdentifier(p.name)) {\n add(p.name.text, ts.isPropertyAssignment(p) ? p.initializer : p);\n }\n }\n }\n }\n }\n continue;\n }\n }\n\n if (!ts.isBinaryExpression(e) || e.operatorToken.kind !== ts.SyntaxKind.EqualsToken) continue;\n const lhs = e.left;\n const rhs = e.right;\n\n // module.exports = <expr>\n if (isModuleExports(lhs)) {\n const spec = requireSpecifier(rhs);\n if (spec) {\n reExport(spec, null);\n continue;\n }\n if (ts.isObjectLiteralExpression(rhs)) {\n for (const p of rhs.properties) {\n if (p.name && ts.isIdentifier(p.name)) {\n add(p.name.text, ts.isPropertyAssignment(p) ? p.initializer : p);\n }\n }\n continue;\n }\n if (ts.isIdentifier(rhs)) {\n // `const N = {…}; module.exports = N` — resolve the binding (§6.2)\n const b = localBinding(sf, rhs.text);\n if (b && ts.isObjectLiteralExpression(b)) {\n for (const p of b.properties) {\n if (p.name && ts.isIdentifier(p.name)) {\n add(p.name.text, ts.isPropertyAssignment(p) ? p.initializer : p);\n }\n }\n continue;\n }\n if (b) {\n add('default', b);\n continue;\n }\n }\n add('default', rhs);\n continue;\n }\n\n // module.exports.X = <expr> / exports.X = <expr>\n const name = exportTargetName(lhs);\n if (name) {\n const spec = requireSpecifier(rhs);\n if (spec && !resolvesInsidePackage(spec)) {\n ctx.external.add(spec);\n put(out, {\n path: name,\n kind: 'object',\n arity: null,\n origin: `external:${spec}`,\n deprecated: false,\n tier: TIER,\n sourceRef: { file: rel, line: lineOf(sf, stmt) },\n });\n continue;\n }\n const target = ts.isIdentifier(rhs) ? (localBinding(sf, rhs.text) ?? rhs) : rhs;\n add(name, target, { deprecated: hasDeprecatedTag(sf, stmt) });\n }\n }\n }\n}\n\n/** `require('x')` → 'x', including `require('x').y`. Null otherwise. */\nfunction requireSpecifier(node: ts.Node): string | null {\n let n: ts.Node = node;\n if (ts.isPropertyAccessExpression(n)) n = n.expression;\n if (\n ts.isCallExpression(n) &&\n ts.isIdentifier(n.expression) &&\n n.expression.text === 'require' &&\n n.arguments.length === 1 &&\n ts.isStringLiteral(n.arguments[0]!)\n ) {\n return (n.arguments[0] as ts.StringLiteral).text;\n }\n return null;\n}\n\n/**\n * Did this entry give us anything a consumer could name?\n *\n * Empty is the obvious failure. A lone `default` is the same failure wearing a\n * result: `module.exports = require('./impl')(globalThis)` parses, produces\n * exactly one symbol, and tells you nothing about the API behind it. Both mean\n * \"try the next condition\" — and a package whose surface genuinely is one\n * default export loses nothing, because no other candidate will read better and\n * the first attempt is what gets reported.\n */\nfunction isReadable(symbols: SurfaceSymbol[]): boolean {\n if (symbols.length === 0) return false;\n return !(symbols.length === 1 && symbols[0]!.path === 'default');\n}\n\n/**\n * Extract the tier-A runtime surface of an installed package directory.\n * Never throws for a subject-side problem — a package with no resolvable entry\n * returns `undeclaredReason`, which the caller records as UNDECLARED, not as\n * absence (§4.2).\n */\nexport function extractSurface(\n pkgDir: string,\n opts: { manifest?: PackageManifest | null; subpath?: string } = {},\n): ExtractedSurface {\n const manifest = opts.manifest ?? readManifest(pkgDir);\n const candidates = resolveEntryCandidates(pkgDir, manifest, opts.subpath);\n const base: ExtractedSurface = {\n package: manifest?.name ?? pkgDir,\n version: manifest?.version ?? null,\n tier: TIER,\n entry: null,\n symbols: [],\n filesWalked: 0,\n externalReExports: [],\n };\n if (!candidates.length) {\n return {\n ...base,\n undeclaredReason: opts.subpath\n ? `no resolvable JS entry point for subpath ./${opts.subpath}`\n : 'no resolvable JS entry point',\n };\n }\n\n // Try each entry until one yields a readable surface. An ESM-first package's\n // `require` condition is often a wrapper that re-exports through a runtime\n // call, which the AST walker cannot follow: it resolves, walks one file, and\n // reports nothing usable. Reporting that as the package's surface is the\n // dangerous outcome — an empty surface reads as \"no API\" and makes every\n // later diff look like the package deleted everything.\n //\n // The first candidate that reads wins, so the require-first preference is\n // intact for the CJS packages it was chosen for. When no candidate reads, the\n // first attempt is what we report, because that is the entry a consumer would\n // actually load and \"we could not read this one\" is the honest answer.\n const attempts: { entry: string; symbols: SurfaceSymbol[]; walked: number; external: string[] }[] = [];\n for (const entry of candidates) {\n const ctx: WalkCtx = {\n pkgDir,\n visited: new Set(),\n filesWalked: 0,\n external: new Set(),\n truncated: false,\n };\n const out = new Map<string, SurfaceSymbol>();\n walk(entry, ctx, out);\n attempts.push({\n entry,\n symbols: [...out.values()].sort((a, b) => a.path.localeCompare(b.path)),\n walked: ctx.filesWalked,\n external: [...ctx.external].sort(),\n });\n if (isReadable(attempts[attempts.length - 1]!.symbols)) break;\n }\n const attempt = attempts.find((a) => isReadable(a.symbols)) ?? attempts[0]!;\n\n return {\n ...base,\n entry: relative(pkgDir, attempt.entry),\n symbols: attempt.symbols,\n filesWalked: attempt.walked,\n externalReExports: attempt.external,\n ...(attempt.symbols.length === 0\n ? { undeclaredReason: 'entry resolved but no exports found' }\n : {}),\n };\n}\n","/**\n * Fetch stage (§6.1): pull a package tarball, hash it, extract its tier-A\n * surface, and hand it back for storage.\n *\n * The digest is the cache key. An unchanged tarball must never pay for\n * extraction twice — that is what keeps cost sublinear as breadth grows (§6.5),\n * and breadth is exactly when cost starts to matter.\n *\n * Nothing here executes package code. The tarball is unpacked and parsed; no\n * install runs, no lifecycle script fires. That property is load-bearing for\n * §9.2: \"we read the shipped JS in your registry\" survives a security review\n * that \"we run your packages in our sandbox\" does not.\n */\nimport { execFile } from 'node:child_process';\nimport { createHash } from 'node:crypto';\nimport { mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport { promisify } from 'node:util';\nimport { encodeNpmName } from '../ingestion/sources/npmRegistry';\nimport type { ExtractedSurface } from './types';\n\nconst execFileP = promisify(execFile);\nconst FETCH_TIMEOUT_MS = 60_000;\nconst MAX_TARBALL_BYTES = 64 * 1024 * 1024;\n\nexport interface FetchedSurface {\n surface: ExtractedSurface;\n /**\n * Surfaces of the subpath entry points named in `opts.subpaths`, keyed by\n * subpath (`pg-core`). Extracted from the same unpacked tarball as the root,\n * because a package with four used entry points would otherwise cost four\n * downloads of the same archive.\n */\n subpathSurfaces?: Record<string, ExtractedSurface>;\n /** sha256 of the tarball — the extraction cache key. */\n artifactHash: string;\n resolvedVersion: string;\n}\n\ninterface DistInfo {\n tarball: string;\n version: string;\n}\n\n/** Resolve a version spec to a concrete tarball URL via the registry. */\nexport async function resolveTarball(\n name: string,\n version: string | null,\n fetchImpl: typeof fetch = fetch,\n): Promise<DistInfo | null> {\n const spec = version ?? 'latest';\n const url = `https://registry.npmjs.org/${encodeNpmName(name)}/${encodeURIComponent(spec)}`;\n const res = await fetchImpl(url, { headers: { accept: 'application/json' } });\n if (!res.ok) return null;\n const body = (await res.json()) as { version?: string; dist?: { tarball?: string } };\n if (!body?.dist?.tarball || !body.version) return null;\n return { tarball: body.dist.tarball, version: body.version };\n}\n\n/**\n * Download, hash, unpack, and extract. Throws only on infrastructure failure —\n * the caller records UNVERIFIABLE and requeues rather than condemning the\n * package, because a rate limit is not evidence about a package (§4.2).\n */\nexport async function fetchAndExtract(\n name: string,\n version: string | null,\n opts: { fetchImpl?: typeof fetch; subpaths?: string[] } = {},\n): Promise<FetchedSurface | null> {\n const fetchImpl = opts.fetchImpl ?? fetch;\n const dist = await resolveTarball(name, version, fetchImpl);\n if (!dist) return null;\n\n const res = await fetchImpl(dist.tarball);\n if (!res.ok) throw new Error(`tarball fetch failed: ${res.status} ${dist.tarball}`);\n const buf = Buffer.from(await res.arrayBuffer());\n if (buf.byteLength > MAX_TARBALL_BYTES) {\n throw new Error(`tarball exceeds ${MAX_TARBALL_BYTES} bytes: ${name}@${dist.version}`);\n }\n const artifactHash = createHash('sha256').update(buf).digest('hex');\n\n const dir = await mkdtemp(join(tmpdir(), 'lurq-surface-'));\n try {\n const tgz = join(dir, 'pkg.tgz');\n const pkgDir = join(dir, 'pkg');\n await mkdir(pkgDir, { recursive: true });\n await writeFile(tgz, buf);\n // `tar` only unpacks; it never executes anything from the archive.\n //\n // --strip-components=1 rather than assuming a `package/` root: npm tarballs\n // USUALLY root there, but not always — @types/* roots at the type name\n // (`node/`, not `package/`), so a hardcoded path fails extraction outright\n // for all of DefinitelyTyped. Stripping the first component normalizes any\n // root name.\n await execFileP('tar', ['xzf', tgz, '--strip-components=1', '-C', pkgDir], {\n timeout: FETCH_TIMEOUT_MS,\n });\n\n // A tarball with no readable manifest is a fact ABOUT THE PACKAGE, not an\n // infrastructure failure — it must surface as UNDECLARED rather than throw,\n // or the drain will treat a type-only package as our own outage and retry\n // it forever (§4.2).\n try {\n await readFile(join(pkgDir, 'package.json'), 'utf8');\n } catch {\n return {\n surface: {\n package: name,\n version: dist.version,\n tier: 'shipped_js_ast',\n entry: null,\n symbols: [],\n filesWalked: 0,\n externalReExports: [],\n undeclaredReason: 'tarball contains no readable package.json',\n },\n artifactHash,\n resolvedVersion: dist.version,\n };\n }\n\n // Loaded here, not at module scope: `extractSurface` pulls in the TypeScript\n // compiler, which is an operator-only dependency. A static edge put it in\n // every bundle chunk that reaches this file, so `sync` (which never\n // extracts) refused to boot without it.\n const { extractSurface } = await import('./extract');\n const surface = extractSurface(pkgDir);\n const subpathSurfaces: Record<string, ExtractedSurface> = {};\n for (const sub of new Set(opts.subpaths ?? [])) {\n subpathSurfaces[sub] = {\n ...extractSurface(pkgDir, { subpath: sub }),\n package: `${name}/${sub}`,\n version: dist.version,\n };\n }\n return {\n surface: { ...surface, package: name, version: dist.version },\n ...(opts.subpaths?.length ? { subpathSurfaces } : {}),\n artifactHash,\n resolvedVersion: dist.version,\n };\n } finally {\n await rm(dir, { recursive: true, force: true }).catch(() => {});\n }\n}\n","/**\n * `check_upgrade` (§8.1) — the team product's core call, and the first surface\n * with a plausible payer.\n *\n * The wedge, stated exactly: *Renovate and Dependabot catch what your tests\n * cover; lurq catches what your code references.* Existing tooling gates an\n * upgrade on a test suite, so if coverage misses the affected path the PR merges\n * green and breaks in production. This check needs no tests at all — it compares\n * the symbols the codebase actually references against the runtime surface of\n * the target version.\n *\n * Severity is deliberately blunt:\n * BLOCKING — a referenced symbol disappears. The code will throw.\n * WARNING — a referenced symbol changed arity. It may silently misbehave.\n * OK — nothing referenced is affected.\n *\n * Anything we could not establish is `unverified`, never folded into OK. A check\n * that reports \"safe\" when it simply did not look is worse than no check, and it\n * is how a CI gate loses its credibility in one incident.\n */\nimport { fetchAndExtract } from './fetch';\nimport { diffSurfaces } from './diff';\nimport { SURFACE_CLAIM_KINDS } from './references';\nimport type { PackageReferences, SymbolReference } from './references';\nimport { runtimeSymbols, type ExtractedSurface, type SymbolKind } from './types';\n\nexport interface UpgradeTarget {\n package: string;\n fromVersion: string;\n toVersion: string;\n}\n\nexport interface BreakingFinding {\n package: string;\n fromVersion: string;\n toVersion: string;\n severity: 'blocking' | 'warning';\n /** Referenced symbols removed at the target version. `specifier` names the\n * entry point they were imported from. Absent means the package root. */\n symbolsRemoved: { symbol: string; specifier?: string; refs: SymbolReference[] }[];\n arityChanged: {\n symbol: string;\n specifier?: string;\n from: number | null;\n to: number | null;\n refs: SymbolReference[];\n }[];\n /**\n * Runtime exports that exist at the target version and did not at the source\n * — the verified candidates for whatever replaced `symbolsRemoved`.\n *\n * This is the other half of the answer and it used to be computed and thrown\n * away. Knowing `renderToString` disappeared does not tell an agent to reach\n * for `renderToPipeableStream`; the agent that rewrites the call sites runs\n * with no network tool and no MCP access, so without this list its only source\n * for a replacement is the training data whose staleness is the entire reason\n * lurq exists. Extracted from the target's own shipped JS, so it is a fact\n * about the package rather than a recollection.\n *\n * Same-kind-as-something-removed first, then alphabetical, then capped: a\n * package can add hundreds of exports and this rides inside a brief a model\n * has to read.\n */\n newExports: { symbol: string; kind: SymbolKind; arity: number | null }[];\n}\n\n/** How many candidate replacements travel with one finding. Enough to contain\n * the real replacement, small enough to stay legible inside the brief. */\nconst NEW_EXPORT_CAP = 40;\n\nexport interface UpgradeReport {\n safe: boolean;\n breaking: BreakingFinding[];\n /** Packages checked with nothing referenced affected. */\n ok: string[];\n /** Could not be established — NEVER counted as safe. */\n unverified: { package: string; reason: string }[];\n}\n\n/**\n * Split a package's references by the entry point they were imported from.\n * The key is the subpath (`pg-core`), or `''` for the package root.\n *\n * This grouping is the whole of the subpath fix. `drizzle-orm/pg-core` is a\n * different module with a different export surface than `drizzle-orm`, and the\n * check used to keep only root-specifier references, so a repo importing\n * `pgTable` from the subpath had those symbols silently discarded, and a package\n * whose every use was a subpath import was compared against an empty reference\n * set and reported OK. In this repo that was 40% of all references.\n */\nfunction groupByEntry(\n refs: PackageReferences,\n pkg: string,\n): Map<string, Map<string, SymbolReference[]>> {\n const byEntry = new Map<string, Map<string, SymbolReference[]>>();\n for (const [sym, uses] of refs.symbols) {\n for (const use of uses) {\n if (use.specifier !== pkg && !use.specifier.startsWith(`${pkg}/`)) continue;\n const sub = use.specifier === pkg ? '' : use.specifier.slice(pkg.length + 1);\n let symbols = byEntry.get(sub);\n if (!symbols) byEntry.set(sub, (symbols = new Map()));\n const list = symbols.get(sym);\n if (list) list.push(use);\n else symbols.set(sym, [use]);\n }\n }\n return byEntry;\n}\n\n/** Runtime exports of `surface` whose value is a plain object. */\nfunction objectPaths(surface: ExtractedSurface): Set<string> {\n return new Set(\n runtimeSymbols(surface)\n .filter((s) => s.kind === 'object')\n .map((s) => s.path),\n );\n}\n\n/**\n * Does a `named-member` read assert something about the module's export surface?\n *\n * Exported and kept tiny because it is the money path: a wrong `true` here is a\n * BLOCKING result on correct code, which is the §12 M3 kill condition.\n *\n * True only for a namespace-shaped parent: an exported object that groups the\n * same names the module also exports at the top level. zod is the case that\n * drove this, and `z.string` and the top-level `string` are the same function.\n * Requiring `object` in BOTH versions keeps `vi.fn()` and `expect.any()` out,\n * since those parents are not object exports at all. The remaining guard is\n * implicit at the call site: only `diff.removed` is consulted, so a property\n * that was never a top-level export of the from-version cannot be reached.\n */\nexport function isNamespaceMemberClaim(\n ref: SymbolReference,\n fromObjects: Set<string>,\n toObjects: Set<string>,\n): boolean {\n if (ref.via !== 'named-member' || ref.parent === undefined) return false;\n return fromObjects.has(ref.parent) && toObjects.has(ref.parent);\n}\n\ninterface EntryComparison {\n symbolsRemoved: BreakingFinding['symbolsRemoved'];\n arityChanged: BreakingFinding['arityChanged'];\n candidates: BreakingFinding['newExports'];\n lostKinds: Set<SymbolKind>;\n}\n\n/** Compare one entry point's from/to surfaces against the symbols read from it. */\nfunction compareEntry(\n from: ExtractedSurface | undefined,\n to: ExtractedSurface | undefined,\n symbols: Map<string, SymbolReference[]>,\n specifier: string,\n isRoot: boolean,\n): EntryComparison | { unverified: string } {\n if (!from || !to) return { unverified: 'entry point not extracted' };\n if (from.undeclaredReason || to.undeclaredReason) {\n return { unverified: `no readable surface (${from.undeclaredReason ?? to.undeclaredReason})` };\n }\n\n const diff = diffSurfaces(from, to);\n if (diff.inconclusive) return { unverified: diff.inconclusive };\n\n // Only symbols claimed against the MODULE'S export surface can be \"removed\".\n // `chalk.bold` is a property of the default export's value — valid code that\n // tier A cannot see. Blocking a PR on that is the false positive that gets a\n // CI gate switched off inside two weeks (§12 M3 kill condition).\n const toSurface = new Set(runtimeSymbols(to).map((s) => s.path));\n const bareValue = toSurface.size <= 1 && toSurface.has('default');\n\n // ...and `z.string` can be one too, when the parent is namespace-shaped. See\n // isNamespaceMemberClaim for which parents qualify and why.\n const objectExports = objectPaths(from);\n const toObjects = objectPaths(to);\n const throughNamespaceObject = (r: SymbolReference): boolean =>\n isNamespaceMemberClaim(r, objectExports, toObjects);\n\n const referenced = new Set(\n [...symbols.entries()]\n .filter(\n ([sym, uses]) =>\n sym !== 'default' &&\n uses.some(\n (r) =>\n (SURFACE_CLAIM_KINDS.includes(r.via) && !(bareValue && r.via === 'namespace')) ||\n throughNamespaceObject(r),\n ),\n )\n .map(([sym]) => sym),\n );\n\n // `specifier` rides along only for subpaths, so root findings serialize\n // exactly as they did before this change.\n const tag = isRoot ? {} : { specifier };\n return {\n symbolsRemoved: diff.removed\n .filter((s) => referenced.has(s.path) && !toSurface.has(s.path))\n .map((s) => ({ symbol: s.path, ...tag, refs: symbols.get(s.path) ?? [] })),\n arityChanged: diff.arityChanged\n .filter((a) => referenced.has(a.path))\n .map((a) => ({\n symbol: a.path,\n ...tag,\n from: a.from,\n to: a.to,\n refs: symbols.get(a.path) ?? [],\n })),\n // The target's whole surface, not just what it added: a rename that shipped\n // the new name a major early leaves `diff.added` empty. `default` is never a\n // useful candidate, and the caller drops anything it just reported removed.\n candidates: runtimeSymbols(to)\n .filter((s) => s.path !== 'default')\n .map((s) => ({ symbol: s.path, kind: s.kind, arity: s.arity })),\n lostKinds: new Set(diff.removed.filter((s) => referenced.has(s.path)).map((s) => s.kind)),\n };\n}\n\n/**\n * Check one upgrade against what the codebase references.\n *\n * Only symbols the code actually uses are reported. A package can drop fifty\n * exports; if this codebase touches none of them, the upgrade is safe FOR THIS\n * CODEBASE, and saying otherwise trains people to ignore the check.\n *\n * Returns both channels rather than one of three, because a package can be\n * breaking on one entry point and unreadable on another: `drizzle-orm` can lose\n * a root symbol while `drizzle-orm/pg-core` fails to resolve. Collapsing that to\n * a single verdict has to discard one of the two facts, and discarding the\n * doubt is how the check ends up reporting safe when it did not look.\n */\nexport async function checkUpgradeOne(\n target: UpgradeTarget,\n refs: PackageReferences | undefined,\n): Promise<{ finding?: BreakingFinding; unverified?: string }> {\n if (!refs || refs.symbols.size === 0) return {};\n\n const byEntry = groupByEntry(refs, target.package);\n if (byEntry.size === 0) return {};\n const subpaths = [...byEntry.keys()].filter(Boolean);\n\n const [from, to] = await Promise.all([\n fetchAndExtract(target.package, target.fromVersion, { subpaths }),\n fetchAndExtract(target.package, target.toVersion, { subpaths }),\n ]);\n if (!from || !to) return { unverified: 'could not fetch one or both versions' };\n\n const symbolsRemoved: BreakingFinding['symbolsRemoved'] = [];\n const arityChanged: BreakingFinding['arityChanged'] = [];\n const candidates: BreakingFinding['newExports'] = [];\n const lostKinds = new Set<SymbolKind>();\n const blind: string[] = [];\n\n for (const [sub, symbols] of byEntry) {\n const specifier = sub ? `${target.package}/${sub}` : target.package;\n const res = compareEntry(\n sub ? from.subpathSurfaces?.[sub] : from.surface,\n sub ? to.subpathSurfaces?.[sub] : to.surface,\n symbols,\n specifier,\n !sub,\n );\n if ('unverified' in res) {\n blind.push(byEntry.size === 1 ? res.unverified : `${specifier}: ${res.unverified}`);\n continue;\n }\n symbolsRemoved.push(...res.symbolsRemoved);\n arityChanged.push(...res.arityChanged);\n candidates.push(...res.candidates);\n for (const k of res.lostKinds) lostKinds.add(k);\n }\n\n const unverified = blind.length ? blind.join('; ') : undefined;\n if (!symbolsRemoved.length && !arityChanged.length) {\n return unverified ? { unverified } : {};\n }\n\n // Candidates are what the TARGET exports, not what it added.\n //\n // This read `diff.added` — symbols present at the target and absent at the\n // source. That is right for \"the library grew a new API\" and wrong for the\n // commonest rename there is: ship the new name, let both live, remove the old\n // one a major later. cookie did exactly that. Going 1.1.1 → 2.0.1 removes\n // `parse` and `serialize`, and `parseCookie` and `stringifyCookie` — the\n // things you are supposed to call instead — had been exported since 1.x. So\n // `diff.added` was empty, and a caller holding a blocking finding got\n // `\"newExports\": []`: told what broke, told nothing about what to write.\n //\n // The model does the mapping, and does it well, given the candidates. It\n // cannot do it from an empty array. So this hands over the target's surface\n // and leaves the choice where it belongs; there is deliberately no matcher\n // here, because `parse(str, options?)` → `parseCookie(str, options?)` is not\n // a problem that needs one.\n //\n // Ranking survives as a retrieval filter rather than an answer. Surfaces run\n // to 129 exports for react-router and 240 for zod, so the cap is real and\n // what it keeps matters: symbols whose kind matches something this codebase\n // just lost come first, so a removed function is not pushed out by constants.\n //\n // Collected per entry point, so a package used through several of them offers\n // candidates from each. Deduped on the symbol name: `lostKinds` and the cap\n // both count distinct names, and two entry points can re-export one.\n const removedNames = new Set(symbolsRemoved.map((s) => s.symbol));\n const seen = new Set<string>();\n const newExports = candidates\n .filter((c) => !removedNames.has(c.symbol) && !seen.has(c.symbol) && seen.add(c.symbol))\n .sort(\n (a, b) =>\n Number(lostKinds.has(b.kind)) - Number(lostKinds.has(a.kind)) ||\n a.symbol.localeCompare(b.symbol),\n )\n .slice(0, NEW_EXPORT_CAP);\n\n return {\n finding: {\n package: target.package,\n fromVersion: target.fromVersion,\n toVersion: target.toVersion,\n severity: symbolsRemoved.length ? 'blocking' : 'warning',\n symbolsRemoved,\n arityChanged,\n newExports,\n },\n ...(unverified ? { unverified } : {}),\n };\n}\n\nexport async function checkUpgrade(\n targets: UpgradeTarget[],\n references: PackageReferences[],\n): Promise<UpgradeReport> {\n const byPkg = new Map(references.map((r) => [r.package, r]));\n const breaking: BreakingFinding[] = [];\n const ok: string[] = [];\n const unverified: UpgradeReport['unverified'] = [];\n\n for (const t of targets) {\n try {\n const res = await checkUpgradeOne(t, byPkg.get(t.package));\n if (res.finding) breaking.push(res.finding);\n if (res.unverified) unverified.push({ package: t.package, reason: res.unverified });\n if (!res.finding && !res.unverified) ok.push(t.package);\n } catch (err) {\n unverified.push({ package: t.package, reason: String(err).slice(0, 160) });\n }\n }\n\n return {\n // `safe` requires that nothing broke AND nothing was left unchecked.\n safe: breaking.length === 0 && unverified.length === 0,\n breaking,\n ok,\n unverified,\n };\n}\n\n/** Candidates listed in the text report. The full set stays in the JSON; this\n * keeps the report to the one screen §9.0 asks for. */\nconst REPORT_CANDIDATE_CAP = 8;\n\n/** The §9.0 report: fits on one screen, names files and lines. */\nexport function formatUpgradeReport(report: UpgradeReport, title = 'upgrade check'): string {\n const out: string[] = [`lurq — ${title}`, ''];\n\n for (const b of report.breaking.sort((a, z) => (a.severity === 'blocking' ? -1 : 1))) {\n const label = b.severity === 'blocking' ? 'BLOCKING' : 'WARNING ';\n out.push(`${label} ${b.package} ${b.fromVersion} → ${b.toVersion}`);\n if (b.symbolsRemoved.length) {\n out.push(` Removes ${b.symbolsRemoved.length} symbol(s) your code references:`);\n for (const s of b.symbolsRemoved) {\n const where = s.refs.map((r) => `${r.file}:${r.line}`).join(', ') || '(no location)';\n out.push(` · ${s.specifier ?? b.package}.${s.symbol} ${where}`);\n }\n }\n for (const a of b.arityChanged) {\n const where = a.refs.map((r) => `${r.file}:${r.line}`).join(', ') || '(no location)';\n out.push(` Arity change: ${a.specifier ?? b.package}.${a.symbol} ${a.from} → ${a.to} params`);\n out.push(` · ${where}`);\n }\n // The reader's next question is always \"replaced by what\", so answer it here\n // rather than making them open the JSON. Named as candidates, not as a\n // mapping: these are the exports the target version gained, and which one\n // replaces which is a judgement this diff cannot make.\n if (b.symbolsRemoved.length && b.newExports.length) {\n const shown = b.newExports.slice(0, REPORT_CANDIDATE_CAP);\n const more = b.newExports.length - shown.length;\n out.push(\n ` New at ${b.toVersion}, candidate replacements: ${shown.map((n) => n.symbol).join(', ')}${more > 0 ? ` (+${more} more)` : ''}`,\n );\n }\n out.push('');\n }\n\n if (report.unverified.length) {\n out.push(`UNVERIFIED ${report.unverified.length} package(s) — not checked, NOT declared safe:`);\n for (const u of report.unverified) out.push(` · ${u.package}: ${u.reason}`);\n out.push('');\n }\n\n if (report.ok.length) {\n out.push(`OK ${report.ok.length} package(s) — no referenced symbols removed`);\n }\n if (!report.breaking.length && !report.unverified.length) {\n out.push('', 'No referenced symbols are removed by these upgrades.');\n }\n return out.join('\\n');\n}\n","/**\n * `lurq check-upgrade` — the CI gate.\n *\n * Narrows an upgrade plan down to what this codebase actually references. The\n * plan says react-router 6→8 removes `useHistory`; this says whether *you* call\n * it, and where. That intersection is the product, and it deliberately runs\n * where the source already is: nothing read here is ever transmitted.\n *\n * It also needs no lurq API key and no test suite. Surfaces come straight from\n * the npm tarballs of both versions, so the gate keeps working when our API is\n * down, and it catches breakage in code no test covers — which is precisely the\n * gap that lets a green Dependabot PR fail in production.\n */\nimport { readFileSync } from 'node:fs';\nimport type { UpgradeTarget } from '../surface/upgrade';\n\n/** `pkg@from..to`, the repeatable `--upgrade` form. */\nexport function parseUpgradeSpec(spec: string): UpgradeTarget {\n const at = spec.lastIndexOf('@');\n const name = spec.slice(0, at);\n const [fromVersion, toVersion] = spec.slice(at + 1).split('..');\n if (!name || !fromVersion || !toVersion) {\n throw new Error(`bad --upgrade '${spec}', expected pkg@from..to`);\n }\n return { package: name, fromVersion, toVersion };\n}\n\n/** Shape of the `upgrade-plan --json` file, as far as this command cares. */\ninterface PlanFile {\n upgrades?: { package: string; fromVersion: string; toVersion: string }[];\n}\n\n/** Read targets from a plan produced by `lurq upgrade-plan --json`. */\nexport function targetsFromPlanFile(path: string): UpgradeTarget[] {\n // A plan file is written by one command and read by another, usually across\n // two CI steps. When step one fails the file is missing or empty, and the bare\n // `Unexpected end of JSON input` that fell out of JSON.parse named neither the\n // file nor the step that should have written it.\n let text: string;\n try {\n text = readFileSync(path, 'utf8');\n } catch (err) {\n const why = (err as NodeJS.ErrnoException).code === 'ENOENT' ? 'does not exist' : String(err);\n throw new Error(`plan file ${path} ${why}. Did \\`lurq upgrade-plan --json\\` run?`);\n }\n if (!text.trim()) {\n throw new Error(`plan file ${path} is empty. Did \\`lurq upgrade-plan --json\\` run?`);\n }\n let parsed: PlanFile;\n try {\n parsed = JSON.parse(text) as PlanFile;\n } catch (err) {\n throw new Error(`plan file ${path} is not valid JSON: ${(err as Error).message}`);\n }\n if (!Array.isArray(parsed.upgrades)) {\n throw new Error(`${path} is not an upgrade plan (no \"upgrades\" array)`);\n }\n return parsed.upgrades\n .filter((u) => u.package && u.fromVersion && u.toVersion)\n .map((u) => ({ package: u.package, fromVersion: u.fromVersion, toVersion: u.toVersion }));\n}\n\nexport interface CheckUpgradeOpts {\n upgrade?: string[];\n plan?: string;\n json?: boolean;\n exitCode?: boolean;\n}\n\nexport async function runCheckUpgrade(dir: string, opts: CheckUpgradeOpts): Promise<void> {\n const { scanReferences } = await import('../surface/references');\n const { checkUpgrade, formatUpgradeReport } = await import('../surface/upgrade');\n\n const targets = [\n ...(opts.plan ? targetsFromPlanFile(opts.plan) : []),\n ...(opts.upgrade ?? []).map(parseUpgradeSpec),\n ];\n if (targets.length === 0) {\n // An empty plan is a legitimate \"nothing to do\", not a usage error — CI must\n // not fail a scheduled run just because the repo is already up to date.\n if (opts.plan) {\n const empty = { safe: true, breaking: [], ok: [], unverified: [] };\n console.log(opts.json ? JSON.stringify(empty, null, 2) : 'Nothing to check.');\n return;\n }\n throw new Error('give --plan <file> or at least one --upgrade pkg@from..to');\n }\n\n const refs = scanReferences(dir);\n const report = await checkUpgrade(targets, refs);\n\n console.log(\n opts.json\n ? JSON.stringify(report, null, 2)\n : formatUpgradeReport(report, `upgrade check on ${dir}`),\n );\n if (opts.exitCode && !report.safe) process.exitCode = 1;\n}\n","/**\n * Guided install wizard (`lurq install`, i.e. `npx lurqrun install`). Walks a user\n * through connecting lurq's hosted MCP service to their AI assistant(s): collects\n * the API key, optionally validates it against the endpoint, detects installed\n * agents, and writes the keyed remote config — no DATABASE_URL ever on their\n * machine. Fully non-interactive with `--yes` + flags/env for scripting.\n */\nimport { DEFAULT_ENDPOINT } from '../core/constants';\nimport {\n agentSpecs,\n installAgent,\n installInstructionsFile,\n printInstallReport,\n resolveAgents,\n type AgentSpec,\n type InstallMode,\n} from './installSkill';\n\nexport interface WizardOptions {\n apiKey?: string;\n url?: string;\n agent?: string;\n yes?: boolean;\n}\n\n/** Where users obtain a key (operator-issued for now; self-serve dashboard later). */\nconst GET_KEY_URL = 'https://lurq.run';\n\n/**\n * Lightweight MCP `tools/list` ping to confirm the key authenticates.\n * Distinguishes a rejected key (401/403) from an unreachable endpoint so the\n * wizard can tell the user which one happened instead of blaming the key on a\n * flaky network.\n */\ntype KeyCheck = 'valid' | 'invalid' | 'unreachable';\n\nasync function validateKey(url: string, apiKey: string): Promise<KeyCheck> {\n try {\n const res = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'application/json, text/event-stream',\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'tools/list' }),\n });\n if (res.ok) return 'valid';\n if (res.status === 401 || res.status === 403) return 'invalid';\n return 'unreachable';\n } catch {\n return 'unreachable';\n }\n}\n\nexport async function runInstallWizard(opts: WizardOptions): Promise<void> {\n const interactive = !opts.yes;\n const url = opts.url ?? process.env.LURQ_ENDPOINT ?? DEFAULT_ENDPOINT;\n let apiKey = (opts.apiKey ?? process.env.LURQ_API_KEY)?.trim();\n\n if (interactive) {\n const { input, checkbox, confirm, select } = await import('@inquirer/prompts');\n\n console.log('\\n lurq — connect your coding agent to the hosted package index.\\n');\n\n if (!apiKey) {\n console.log(` Need a key? Get one at ${GET_KEY_URL}\\n`);\n apiKey = (\n await input({\n message: 'Paste your lurq API key',\n validate: (v) =>\n v.trim().startsWith('lurq_') ? true : 'Keys look like lurq_live_… ',\n })\n ).trim();\n }\n\n process.stdout.write(' Validating key… ');\n const check = await validateKey(url, apiKey);\n console.log(\n check === 'valid' ? 'ok' : check === 'invalid' ? 'rejected' : 'could not reach endpoint',\n );\n if (check !== 'valid') {\n const proceed = await confirm({\n message:\n check === 'invalid'\n ? `That key was rejected (401) by ${url}. Continue anyway?`\n : `Couldn't reach ${url} to validate the key. Continue anyway?`,\n default: false,\n });\n if (!proceed) {\n console.log('Aborted. No config was changed.');\n return;\n }\n }\n\n if (opts.agent) {\n await finish(resolveAgents(opts.agent), { url, apiKey });\n return;\n }\n\n const specs = agentSpecs();\n // Natural-language quick path: if we spot likely agents, offer a one-tap\n // connect before falling back to the full multi-select. Mirrors the simplified\n // \"connect to Claude Code? (y/n/other)\" flow in docs/lurq-demo.md. \"Yes\" wires\n // up EVERY detected agent (the prior multi-select pre-checked them all), so a\n // user with two editors doesn't silently leave one unconnected.\n const detected = specs.filter((s) => s.detected);\n const primary = detected.find((s) => s.id === 'claude-code') ?? detected[0];\n if (primary) {\n const others = detected.length - 1;\n const choice = await select({\n message:\n others > 0\n ? `Looks like you have ${detected.map((s) => s.label).join(', ')}. Connect lurq to them?`\n : `Looks like you have ${primary.label}. Connect lurq to it?`,\n default: 'yes',\n choices: [\n {\n name: others > 0 ? `Yes — set up all ${detected.length} detected agents` : `Yes — set up ${primary.label} for me`,\n value: 'yes',\n },\n { name: 'No — let me choose which agent(s)', value: 'other' },\n { name: 'Cancel — change nothing', value: 'cancel' },\n ],\n });\n if (choice === 'cancel') {\n console.log('No problem — nothing was changed. Run `lurq install` again anytime.');\n return;\n }\n if (choice === 'yes') {\n await finish(detected, { url, apiKey });\n return;\n }\n // 'other' falls through to the full multi-select below.\n }\n\n const ids = await checkbox({\n message: 'Which assistant(s) should I configure?',\n choices: specs.map((s) => ({\n name: `${s.label}${s.detected ? ' (detected)' : ''}`,\n value: s.id,\n checked: s.detected,\n })),\n });\n await finish(specs.filter((s) => ids.includes(s.id)), { url, apiKey });\n return;\n }\n\n // Non-interactive (--yes): require a key, use flags/env + detected agents.\n if (!apiKey) {\n throw new Error(\n 'No API key. Pass --api-key <key> or set LURQ_API_KEY (or drop --yes to be prompted).',\n );\n }\n const selected = opts.agent\n ? resolveAgents(opts.agent)\n : agentSpecs().filter((s) => s.detected);\n await finish(selected, { url, apiKey });\n}\n\nasync function finish(\n selected: AgentSpec[],\n remote: { url: string; apiKey: string },\n): Promise<void> {\n if (selected.length === 0) {\n console.log(\n '\\nNo agents selected or detected. Re-run with --agent <id>, or install an assistant first.',\n );\n return;\n }\n const mode: InstallMode = { kind: 'remote', ...remote };\n const results = selected.map((s) => installAgent(s, mode));\n const instructionsPath = installInstructionsFile();\n console.log('');\n printInstallReport(results, instructionsPath, mode);\n}\n","#!/usr/bin/env node\n/**\n * lurq CLI entry point. Runnable via `npx lurq <command>` (§7, §13).\n */\nimport { readFileSync } from 'node:fs';\nimport updateNotifier from 'update-notifier';\nimport { buildProgram } from '../cli/index';\nimport { loadEnv } from '../core/config';\nimport { enforceGate } from '../core/gate';\nimport { logger } from '../core/logger';\n\nloadEnv();\n\n// Private-preview gate: non-owners get a placeholder, the owner runs as usual.\n// Runs after loadEnv so LURQ_OWNER_KEY from a .env file is honored too.\nenforceGate(process.argv.slice(2));\n\nnotifyOnUpdate();\n\nbuildProgram()\n .parseAsync(process.argv)\n .catch((err) => {\n logger.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n });\n\n/**\n * Check npm (at most once a day, in a detached background process) and print a\n * one-line \"update available\" banner on exit when a newer lurqrun is published.\n * Skipped in agent/machine contexts — MCP stdio servers and `--json` output —\n * so the protocol/output stream is never touched. update-notifier additionally\n * only prints in a TTY, so piped runs stay silent regardless. Any failure here\n * must never break the CLI, hence the broad guard.\n */\nfunction notifyOnUpdate(): void {\n const argv = process.argv.slice(2);\n const quiet =\n argv[0] === 'serve' || argv[0] === 'serve-http' || argv.includes('--json');\n if (quiet) return;\n\n try {\n const pkg = JSON.parse(\n readFileSync(new URL('../../package.json', import.meta.url), 'utf8'),\n ) as { name: string; version: string };\n updateNotifier({ pkg }).notify();\n } catch {\n // Offline, no config dir, malformed metadata — never fatal for the CLI.\n }\n}\n","/**\n * CLI command wiring (§13). Built with commander. Each command mirrors an MCP\n * tool or an operational task. Handlers are filled in across milestones M1–M7;\n * the command/option surface here is the final, stable shape.\n *\n * Every command supports `--json` for machine-readable output.\n */\nimport { Command, Option } from 'commander';\nimport { SERVER_NAME, VERSION } from '../core/constants';\nimport { SUPPORTED_AGENTS } from './installSkill';\n\n/**\n * Built from the installer's own list rather than typed out, so adding an agent\n * cannot leave `--help` advertising the old set. Safe to import eagerly:\n * installSkill pulls in node builtins only (the heavy prompt deps live in\n * ./install, which stays lazy).\n */\nconst AGENT_CHOICES = [...SUPPORTED_AGENTS, 'all'].join(' | ');\n\nexport function buildProgram(): Command {\n const program = new Command();\n\n program\n .name(SERVER_NAME)\n .description(\n 'lurq - a fresh, objectively-scored index of JS/TS packages for AI coding agents.',\n )\n .version(VERSION, '-v, --version', 'output the lurq version')\n // Confine program-level flags to the slot before the subcommand name.\n // Without this, commander lets the program consume a `--version` written\n // *after* a subcommand, so `lurq usage pkg --version 24.14.0` printed the\n // lurq version and exited instead of running the command — shadowing the\n // per-command version options on `usage` and (operator plane) `oracle`.\n .enablePositionalOptions();\n\n program\n .command('serve')\n .description('start the MCP server over stdio (for agent integration)')\n .action(async () => {\n const { startMcpServer } = await import('../mcp/server');\n await startMcpServer();\n });\n\n program\n .command('serve-http')\n .description('start the hosted MCP server over HTTP with API-key auth')\n .option('--port <n>', 'port to listen on (default: $PORT or 8080)', (v) => parseInt(v, 10))\n .action(async (opts: { port?: number }) => {\n const { startHttpServer } = await import('../mcp/http');\n await startHttpServer({ port: opts.port });\n });\n\n program\n .command('recommend')\n .argument('<need>', 'natural-language description of what you need')\n .description('recommend the best current packages for a described need')\n .option('--category <category>', 'restrict to a taxonomy category')\n .option('--min-confidence <level>', 'proven | emerging | promising | unproven')\n .option('--json', 'output JSON instead of a table')\n .action(async (need: string, opts: { category?: string; minConfidence?: string; json?: boolean }) => {\n const { runRecommend } = await import('./commands');\n await runRecommend(need, opts);\n });\n\n program\n .command('evaluate')\n .argument('<package>', 'npm package name')\n .description('full evidence read for one package (scores, signals, usage guide)')\n .option('--json', 'output JSON instead of a table')\n .action(async (pkg: string, opts: { json?: boolean }) => {\n const { runEvaluate } = await import('./commands');\n await runEvaluate(pkg, opts);\n });\n\n program\n .command('compare')\n .argument('<packages...>', '2–5 npm package names')\n .description('side-by-side comparison of packages, ranked by health')\n .option('--json', 'output JSON instead of a table')\n .action(async (pkgs: string[], opts: { json?: boolean }) => {\n const { runCompare } = await import('./commands');\n await runCompare(pkgs, opts);\n });\n\n program\n .command('verify')\n .argument('<package>', 'npm package name')\n .description('safety check: is this package real, healthy, and not risky?')\n .option('--json', 'output JSON instead of a table')\n .action(async (pkg: string, opts: { json?: boolean }) => {\n const { runVerify } = await import('./commands');\n await runVerify(pkg, opts);\n });\n\n program\n .command('usage')\n .argument('<package>', 'npm package name')\n .description(\"version-exact API surface (exported symbols/signatures) + drift from a known version\")\n .option('--target <v>', 'target version (defaults to latest)')\n // Historical spelling of --target, kept working but out of the help text so\n // only one spelling is advertised.\n .addOption(new Option('--version <v>', 'alias for --target').hideHelp())\n .option('--known <v>', 'a version you know; shows the API delta to the target')\n .option('--json', 'output JSON')\n .action(\n async (\n pkg: string,\n opts: { target?: string; version?: string; known?: string; json?: boolean },\n ) => {\n const { runUsage } = await import('./commands');\n await runUsage(pkg, {\n version: opts.target ?? opts.version,\n known: opts.known,\n json: opts.json,\n });\n },\n );\n\n program\n .command('versions')\n .argument('<package>', 'npm package name')\n .description('show the stored version timeline for a package')\n .option('--json', 'output JSON instead of a table')\n .option('-n, --limit <n>', 'how many versions to show (default 30)')\n .action(async (pkg: string, opts: { json?: boolean; limit?: string }) => {\n const { runVersions } = await import('./commands');\n await runVersions(pkg, opts);\n });\n\n program\n .command('plan')\n .argument('<file>', 'path to a markdown file describing your program')\n .description('turn a program description into an evidence-scored package plan + roadmap')\n .option('--optimize <mode>', \"ranking bias: 'speed' (lightest bundle) or 'balanced'\")\n .option('--html <path>', 'write the roadmap as a self-contained HTML visualization')\n .option('--open', 'render the roadmap to HTML and open it in your browser')\n .option('--json', 'output the full plan as JSON')\n .action(async (file: string, opts: { optimize?: string; json?: boolean; html?: string; open?: boolean }) => {\n const { runPlan } = await import('./commands');\n await runPlan(file, opts);\n });\n\n program\n .command('weights')\n .description('show and explain the scoring weight model (health, quality, composite λ)')\n .option('--json', 'output the weight model as JSON')\n .action(async (opts: { json?: boolean }) => {\n const { runWeights } = await import('./commands');\n runWeights(opts);\n });\n\n program\n .command('edit-weights')\n .description('override, reset, or explain the scoring weights (layered over defaults)')\n .option('--set <pair>', 'override key=value, e.g. composite.lambda=0.5 (repeatable)', (v: string, acc: string[]) => acc.concat(v), [])\n .option('--reset', 'remove all overrides and restore defaults')\n .option('--explain <component>', 'explain a component (e.g. adoption, quality, lambda)')\n .option('--project', 'write to project-local .lurq/weights.json instead of the user config')\n .action(async (opts: { set?: string[]; reset?: boolean; explain?: string; project?: boolean }) => {\n const { runEditWeights } = await import('./commands');\n await runEditWeights(opts);\n });\n\n program\n .command('compat')\n .argument('<packages...>', 'npm package names to check together')\n .description('check whether a set of packages forms a coherent stack (peer/engine + recorded evidence)')\n // The checker has always taken exact versions (CheckCompatOptions.versions);\n // there was just no way to say so from the CLI. Arguments are bare names, so\n // `next@15` would look up a package called \"next@15\" and come back unknown.\n .option('--pin <name=version...>', 'evaluate an exact version, e.g. --pin next=15')\n .option('--json', 'output JSON')\n .action(async (pkgs: string[], opts: { json?: boolean; pin?: string[] }) => {\n const { runCompat } = await import('./commands');\n await runCompat(pkgs, opts);\n });\n\n // ── Upgrade autopilot ─────────────────────────────────────────────────────\n // These two run where the code is (a laptop or a CI runner), not against a\n // local database. `upgrade-plan` asks the index what changed between versions;\n // `check-upgrade` narrows that to what this codebase references, using nothing\n // but the two npm tarballs — no API key, no test suite, no network to us.\n\n program\n .command('upgrade-plan')\n .argument('[dir]', 'project directory (default: current)', '.')\n .description('what is behind in this project, and what each upgrade removes from its API')\n .option('--json', 'output the plan as JSON (feed to `check-upgrade --plan`)')\n .option('--url <url>', 'hosted endpoint URL (defaults to the lurq service)')\n .option('--api-key <key>', 'hosted API key (defaults to $LURQ_API_KEY)')\n .action(async (dir: string, opts: { json?: boolean; url?: string; apiKey?: string }) => {\n const { buildUpgradePlan, formatUpgradePlan } = await import('./upgradePlan');\n const plan = await buildUpgradePlan(dir, { url: opts.url, apiKey: opts.apiKey });\n console.log(opts.json ? JSON.stringify(plan, null, 2) : formatUpgradePlan(plan));\n });\n\n program\n .command('check-upgrade')\n .argument('[dir]', 'project directory to scan (default: current)', '.')\n .description('do these upgrades remove symbols your code actually references?')\n .option('--plan <file>', 'targets from `upgrade-plan --json`')\n .option('--upgrade <spec...>', 'pkg@from..to (repeatable), e.g. commander@11.1.0..12.1.0')\n .option('--json', 'output the report as JSON')\n .option('--exit-code', 'exit 1 when the report is not safe (for CI)')\n .action(\n async (\n dir: string,\n opts: { plan?: string; upgrade?: string[]; json?: boolean; exitCode?: boolean },\n ) => {\n const { runCheckUpgrade } = await import('./checkUpgrade');\n await runCheckUpgrade(dir, opts);\n },\n );\n\n program\n .command('install')\n .description('guided setup: connect lurq to your AI assistant(s)')\n .option('--api-key <key>', 'hosted API key (skips the prompt)')\n .option('--url <url>', 'hosted endpoint URL (defaults to the lurq service)')\n .option('--agent <agent>', AGENT_CHOICES)\n .option('--yes', 'non-interactive: use flags/env and detected agents without prompting')\n .action(async (opts: { apiKey?: string; url?: string; agent?: string; yes?: boolean }) => {\n const { runInstallWizard } = await import('./install');\n await runInstallWizard(opts);\n });\n\n program\n .command('install-skill')\n .description('register lurq as an MCP server in supported AI assistants (scriptable)')\n .option('--agent <agent>', AGENT_CHOICES, 'claude-code')\n .option('--api-key <key>', 'hosted API key (remote install; default mode)')\n .option('--url <url>', 'hosted endpoint URL (defaults to the lurq service)')\n .option('--local', 'self-host: write a local stdio entry using your own DATABASE_URL')\n .action(async (opts: { agent?: string; apiKey?: string; url?: string; local?: boolean }) => {\n const { runInstallSkill } = await import('./installSkill');\n await runInstallSkill(opts);\n });\n\n return program;\n}\n","/**\n * Pre-launch access gate.\n *\n * While lurq is in private preview, anyone may `npm install lurqrun`, but only\n * the owner may run commands — everyone else gets a branded placeholder. The\n * owner proves identity by exporting `LURQ_OWNER_KEY` in their shell to the\n * secret whose SHA-256 is baked into `OWNER_HASH` below. The published bundle\n * carries only the hash, never the secret, so inspecting the source reveals\n * nothing usable.\n *\n * To lift the gate at public launch, flip `PRE_LAUNCH` to false (or delete the\n * `enforceGate()` call in bin/lurq.ts). The owner bypass keeps working either\n * way, so nothing else needs to change.\n */\nimport { createHash, timingSafeEqual } from 'node:crypto';\n\nimport { PACKAGE_NAME } from './constants';\n\n/** Master switch. Set to false to open lurq to everyone at launch. */\nconst PRE_LAUNCH = false;\n\n/**\n * SHA-256 of the owner secret. Regenerate after choosing a new secret with:\n * node -e \"console.log(require('node:crypto').createHash('sha256').update(process.argv[1]).digest('hex'))\" <secret>\n * and paste the result here. Keep the plaintext only in your shell env.\n */\nconst OWNER_HASH = '9675c37e56783e747e4a89ee3919d95d1364f2e5dd0f14501b0f878f8cc3682b';\n\n/**\n * Top-level commands that bypass the gate even for non-owners:\n * - `-v/--version/-h/--help/help` — harmless, expected by npm users.\n * - `serve`/`serve-http` — the MCP transports. The gate must NEVER write to the\n * stdio JSON-RPC channel (`serve`), and the hosted server must boot without\n * depending on the owner key (`serve-http`).\n * - `sync`/`discover`/`rescore`/`db`/`keys` — operator/infra commands that all\n * require DATABASE_URL, which a public installer never has. Gating them adds no\n * protection (a keyless user can't run them anyway) while risking the owner's\n * own deploy. The gate's real job is the user-facing commands (recommend,\n * evaluate, compare, verify, plan, install, install-skill, weights).\n */\nconst ALLOWED = new Set([\n '-v', '--version', '-h', '--help', 'help',\n 'serve', 'serve-http',\n 'sync', 'discover', 'rescore', 'db', 'keys',\n]);\n\n/** True when the caller has proven they are the owner via `LURQ_OWNER_KEY`. */\nexport function isOwner(): boolean {\n const key = process.env.LURQ_OWNER_KEY;\n if (!key) return false;\n const got = createHash('sha256').update(key).digest();\n const want = Buffer.from(OWNER_HASH, 'hex');\n // Equal-length buffers (both 32 bytes); timingSafeEqual guards against a\n // timing oracle on the comparison.\n return got.length === want.length && timingSafeEqual(got, want);\n}\n\n/**\n * Enforce the gate before any command runs. Returns normally when the caller is\n * the owner, the gate is lifted, or the invocation is a top-level help/version\n * query. Otherwise prints the placeholder and exits cleanly (code 0 — installing\n * early is not an error).\n */\nexport function enforceGate(argv: string[]): void {\n if (!PRE_LAUNCH || isOwner()) return;\n if (argv[0] && ALLOWED.has(argv[0])) return;\n\n printPlaceholder();\n process.exit(0);\n}\n\nfunction printPlaceholder(): void {\n const tty = process.stdout.isTTY;\n const bold = (s: string) => (tty ? `\\x1b[1m${s}\\x1b[0m` : s);\n const dim = (s: string) => (tty ? `\\x1b[2m${s}\\x1b[0m` : s);\n const accent = (s: string) => (tty ? `\\x1b[38;5;213m${s}\\x1b[0m` : s);\n\n process.stdout.write(\n [\n '',\n ` ${bold('lurq')} ${dim('— evidence-scored package index for AI coding agents')}`,\n '',\n ` ${accent('◆ private preview')}`,\n '',\n ` lurq isn't open to the public yet — thanks for installing early.`,\n ` Join the waitlist and watch the demo at ${bold('https://lurq.run')}`,\n '',\n dim(` You'll be able to connect Claude Code, Cursor, and other agents`),\n dim(` the moment we open the gate.`),\n '',\n dim(` (${PACKAGE_NAME} is installed and ready — no further action needed.)`),\n '',\n '',\n ].join('\\n'),\n );\n}\n"],"mappings":"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","names":["fileURLToPath","existsSync","homedir","dirname","join","path","text","sep","apiKey","table","sql","cached","init_types","init_types","and","eq","sql","init_types","path","init_types","createHash","and","desc","eq","rows","cached","init_types","and","eq","sql","packages","createHash","existsSync","homedir","dirname","join","cached","attempt","text","date","json","json","date","HOST","json","HOST","json","HOST","json","HOST","packages","and","desc","eq","isNull","sql","init_diff","and","eq","isNotNull","isNull","sql","path","ts","text","symbols","walk","desc","eq","desc","eq","init_successors","HOST","text","apiKey","text","existsSync","mkdirSync","readFileSync","rmSync","writeFileSync","dirname","active","eq","path","date","createHash","text","str","dim","apiKey","text","inFlight","and","eq","isNotNull","sql","median","and","eq","inArray","isNotNull","sql","rank","createHash","sql","DAY_MS","date","cached","typo","init_diff","init_successors","inArray","text","createHash","inArray","apiKey","and","desc","eq","sql","z","createHash","and","desc","eq","isNull","cached","init_types","and","eq","sql","init_types","cached","path","inArray","semver","empty","init_types","semver","path","MAX_HOPS","path","str","severity","MAX_FILES","init_types","and","desc","eq","gte","sql","path","json","init_types","json","packages","installCommand","createHash","init_http","eq","backoff","init_watch","init_types","writeFile","join","init_types","packages","condense","ERROR_MAX","INSTALL_TIMEOUT_MS","SMOKE_TIMEOUT_MS","toSpec","init_types","packages","E2BSandbox","init_types","init_sandbox","execFile","mkdtemp","rm","writeFile","tmpdir","join","promisify","packages","pending","init_compat","semver","active","invalidateCache","text","path","readFileSync","handlePlan","writeFileSync","tmpdir","join","renderPlanHtml","watchNpmChanges","verifyPackageInSandbox","handleUsage","res","verifyCompatibility","handleCompat","path","detail","readFileSync","join","MAX_DEPTH","walk","detail","readdirSync","readFileSync","statSync","join","relative","ts","walk","text","lineOf","symbols","existsSync","readFileSync","statSync","dirname","join","post","extractSurface","readFileSync","relative","ts","MAX_FILES","text","path","symbols","attempt","init_extract","execFile","createHash","mkdir","mkdtemp","readFile","rm","writeFile","tmpdir","join","promisify","execFileP","extractSurface","symbols","z","init_types","readFileSync","path","text","scanReferences","checkUpgrade","formatUpgradeReport","empty","apiKey","readFileSync","startMcpServer","startHttpServer","runRecommend","runEvaluate","runCompare","runVerify","runUsage","runVersions","runPlan","runWeights","runEditWeights","runCompat","buildUpgradePlan","formatUpgradePlan","runCheckUpgrade","runInstallWizard","runInstallSkill","createHash","timingSafeEqual","bold","dim","readFileSync"]}
|