@neat.is/core 0.4.4 → 0.4.5
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/dist/{chunk-YJOA7BBF.js → chunk-3QCRUEQD.js} +2 -2
- package/dist/{chunk-J4YBTD24.js → chunk-6GXBAR3M.js} +3 -3
- package/dist/{chunk-ZVNP3ZDH.js → chunk-HVF4S7J3.js} +6 -3
- package/dist/chunk-HVF4S7J3.js.map +1 -0
- package/dist/{chunk-G3YGPWJL.js → chunk-RBWL4HRB.js} +13 -2
- package/dist/chunk-RBWL4HRB.js.map +1 -0
- package/dist/cli.cjs +161 -32
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +149 -34
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +15 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +4 -4
- package/dist/neatd.cjs +15 -1
- package/dist/neatd.cjs.map +1 -1
- package/dist/neatd.js +3 -3
- package/dist/{otel-grpc-FIERFRGD.js → otel-grpc-VSPMP3OS.js} +3 -3
- package/dist/server.cjs +15 -1
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +3 -3
- package/package.json +2 -2
- package/dist/chunk-G3YGPWJL.js.map +0 -1
- package/dist/chunk-ZVNP3ZDH.js.map +0 -1
- /package/dist/{chunk-YJOA7BBF.js.map → chunk-3QCRUEQD.js.map} +0 -0
- /package/dist/{chunk-J4YBTD24.js.map → chunk-6GXBAR3M.js.map} +0 -0
- /package/dist/{otel-grpc-FIERFRGD.js.map → otel-grpc-VSPMP3OS.js.map} +0 -0
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/gitignore.ts","../src/summary.ts","../src/watch.ts","../src/deploy/detect.ts","../src/installers/javascript.ts","../src/installers/templates.ts","../src/installers/python.ts","../src/installers/shared.ts","../src/installers/index.ts","../src/orchestrator.ts","../src/cli-verbs.ts","../src/cli-client.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport path from 'node:path'\nimport { promises as fs, readFileSync } from 'node:fs'\nimport { fileURLToPath } from 'node:url'\nimport { DEFAULT_PROJECT, getGraph, resetGraph } from './graph.js'\nimport { extractFromDirectory } from './extract.js'\nimport {\n formatExtractionBanner,\n formatPrecisionFloorBanner,\n isStrictExtractionEnabled,\n} from './extract/errors.js'\nimport { discoverServices } from './extract/services.js'\nimport type { DiscoveredService } from './extract/shared.js'\nimport { computeDivergences } from './divergences.js'\nimport { saveGraphToDisk } from './persist.js'\nimport { ensureNeatOutIgnored } from './gitignore.js'\nimport { renderValueForwardSummary } from './summary.js'\nimport { startWatch, type WatchHandle } from './watch.js'\nimport { runDeploy, renderOtelEnvBlock } from './deploy/detect.js'\nimport { pathsForProject } from './projects.js'\nimport {\n addProject,\n listProjects,\n ProjectNameCollisionError,\n removeProject,\n setStatus,\n} from './registry.js'\nimport {\n INSTALLERS,\n isEmptyPlan,\n pickInstaller,\n renderPatch,\n type InstallPlan,\n type PatchSection,\n} from './installers/index.js'\nimport { runOrchestrator } from './orchestrator.js'\nimport { runSync } from './cli-verbs.js'\nimport { DivergenceTypeSchema, type DivergenceType } from '@neat.is/types'\nimport {\n createHttpClient,\n exitCodeForError,\n formatHuman,\n formatJson,\n HttpError,\n runBlastRadius,\n runDependencies,\n runDiff,\n runDivergences,\n runIncidents,\n runObservedDependencies,\n runPolicies,\n runRootCause,\n runSearch,\n runStaleEdges,\n TransportError,\n type VerbResult,\n} from './cli-client.js'\n\nexport interface InitOptions {\n scanPath: string\n outPath: string\n // The project's registry name. Defaults to the basename of the scan path\n // when the user didn't pass `--project` (ADR-046 — project naming).\n project: string\n // Whether `project` was set explicitly via `--project`. The flag affects\n // which in-memory graph slot we use: explicit names get isolated slots\n // per ADR-026, the default basename keeps using DEFAULT_PROJECT for\n // back-compat with `neat watch`.\n projectExplicit: boolean\n apply: boolean\n dryRun: boolean\n noInstall: boolean\n // ADR-073 §5 — when true, append the per-type node/edge breakdown after\n // the value-forward findings block. Default false.\n verbose: boolean\n}\n\nexport interface InitResult {\n // Process exit code. 0 on success, 1 on collision / runtime failure,\n // 2 on misuse (handled before we get here, but documented for completeness).\n exitCode: number\n // Paths the run actually wrote to. Empty in `--dry-run` except for\n // `neat.patch`. Useful for tests asserting \"init only wrote X\".\n writtenFiles: string[]\n}\n\nfunction usage(): void {\n console.log('usage: neat <command> [args] [--project <name>]')\n console.log('')\n console.log('lifecycle commands:')\n console.log(' init <path> One-time install: discover, extract, register, plan SDK install.')\n console.log(' Snapshot lands in <path>/neat-out/graph.json by default')\n console.log(' (or <path>/neat-out/<project>.json for non-default).')\n console.log(' Flags:')\n console.log(' --apply run the SDK install patch in place')\n console.log(' --dry-run write only neat.patch; do not register or snapshot')\n console.log(' --no-install skip SDK install planning entirely')\n console.log(' watch <path> Start neat-core, watch <path>, re-extract on changes.')\n console.log(' PORT (default 8080), OTEL_PORT (4318), HOST (0.0.0.0)')\n console.log(' control listeners. NEAT_OTLP_GRPC=true also opens 4317.')\n console.log(' list List every project registered in the machine-level registry.')\n console.log(' pause <name> Mark a project paused — daemon stops watching until resumed.')\n console.log(' resume <name> Mark a project active again.')\n console.log(' uninstall <name>')\n console.log(' Remove a project from the registry. Does not touch')\n console.log(' neat-out/, policy.json, or any user file.')\n console.log(' version Print the installed @neat.is/core version and exit.')\n console.log(' Aliases: --version, -v.')\n console.log(' skill Install or print the Claude Code MCP drop-in.')\n console.log(' Flags:')\n console.log(' --print-config print the JSON snippet to stdout')\n console.log(' --apply merge mcpServers.neat into ~/.claude.json')\n console.log(' deploy Detect the deploy substrate, generate NEAT_AUTH_TOKEN,')\n console.log(' emit a docker-compose / systemd / docker run artifact, and')\n console.log(' print the OTel env-vars block to paste into your platform.')\n console.log(' sync Re-run discovery, extraction, and SDK apply against the')\n console.log(' registered project, then notify the running daemon.')\n console.log(' Flags:')\n console.log(' --project <name> target a registered project by name')\n console.log(' --to <url> push the snapshot to a remote daemon')\n console.log(' --token <token> bearer token for --to (or $NEAT_REMOTE_TOKEN)')\n console.log(' --dry-run run extraction in-memory; do not write')\n console.log(' --no-instrument skip the SDK install apply step')\n console.log(' --json emit the delta summary as JSON')\n console.log('')\n console.log('query commands (mirror the MCP tools, ADR-050):')\n console.log(' root-cause <node-id> Walk inbound edges to find what broke first.')\n console.log(' example: neat root-cause service:<name>')\n console.log(' blast-radius <node-id> BFS outbound — what would break if this dies.')\n console.log(' example: neat blast-radius database:<host>')\n console.log(' dependencies <node-id> Transitive outbound dependencies.')\n console.log(' Flags: --depth N (default 3, max 10)')\n console.log(' example: neat dependencies service:<name> --depth 2')\n console.log(' observed-dependencies <node-id> OBSERVED-only outbound edges (runtime traffic).')\n console.log(' example: neat observed-dependencies service:<name>')\n console.log(' incidents [<node-id>] Recent error events; per-node when an id is given.')\n console.log(' Flags: --limit N (default 20)')\n console.log(' example: neat incidents service:<name> --limit 5')\n console.log(' search <query> Semantic (or substring) match on node names/ids.')\n console.log(' example: neat search \"checkout\"')\n console.log(' diff --against <snapshot> Compare the live graph to a saved snapshot.')\n console.log(' example: neat diff --against ./snapshots/baseline.json')\n console.log(' stale-edges Recent OBSERVED → STALE transitions.')\n console.log(' Flags: --limit N, --edge-type CALLS|CONNECTS_TO|...')\n console.log(' example: neat stale-edges --edge-type CALLS')\n console.log(' policies Current policy violations.')\n console.log(' Flags: --node <id>, --hypothetical-action <json>')\n console.log(' example: neat policies --node service:<name> --json')\n console.log(' divergences Where code (EXTRACTED) and production (OBSERVED) disagree.')\n console.log(' Flags: --type <list>, --min-confidence <0..1>, --node <id>')\n console.log(' example: neat divergences --min-confidence 0.7')\n console.log('')\n console.log('flags:')\n console.log(' --project <name> Name the project this command targets. Default: \"default\".')\n console.log(' --json Emit machine-readable JSON instead of human text. Query verbs only.')\n console.log('')\n console.log('exit codes:')\n console.log(' 0 success')\n console.log(' 1 server error (4xx/5xx body printed to stderr)')\n console.log(' 2 misuse (missing args, bad flags) — handled before any network call')\n console.log(' 3 daemon not reachable (connection refused / timeout)')\n console.log('')\n console.log('environment:')\n console.log(' NEAT_API_URL base URL for the core REST API (default http://localhost:8080)')\n console.log(' NEAT_PROJECT project name when --project isn\\'t passed')\n}\n\n// Tiny argv parser — pulls `--project <name>`, the v0.2.5 init flags, and\n// the v0.2.8 verb flags out of `rest`. Boolean / value flags are surfaced\n// unconditionally; per-command validation lives in `main`.\ninterface ParsedArgs {\n project: string | null\n apply: boolean\n dryRun: boolean\n noInstall: boolean\n noInstrument: boolean\n noOpen: boolean\n yes: boolean\n verbose: boolean\n printConfig: boolean\n json: boolean\n depth: number | null\n limit: number | null\n edgeType: string | null\n node: string | null\n since: string | null\n against: string | null\n errorId: string | null\n hypotheticalAction: string | null\n type: string | null\n minConfidence: number | null\n // `neat sync` (ADR-074 §1) — remote daemon URL + bearer token.\n to: string | null\n token: string | null\n positional: string[]\n}\n\n// String-valued flags supported across the verb surface. Each entry maps the\n// canonical `--flag` name (and its `--flag=` equivalent) to the parsed-args\n// field that receives it. Centralising the table keeps misuse diagnostics\n// (exit code 2) consistent across verbs.\nconst STRING_FLAGS = [\n ['--project', 'project'],\n ['--depth', 'depth'],\n ['--limit', 'limit'],\n ['--edge-type', 'edgeType'],\n ['--node', 'node'],\n ['--since', 'since'],\n ['--against', 'against'],\n ['--error-id', 'errorId'],\n ['--hypothetical-action', 'hypotheticalAction'],\n ['--type', 'type'],\n ['--min-confidence', 'minConfidence'],\n ['--to', 'to'],\n ['--token', 'token'],\n] as const\n\nfunction parseArgs(rest: string[]): ParsedArgs {\n const positional: string[] = []\n const out: ParsedArgs = {\n project: null,\n apply: false,\n dryRun: false,\n noInstall: false,\n noInstrument: false,\n noOpen: false,\n yes: false,\n verbose: false,\n printConfig: false,\n json: false,\n depth: null,\n limit: null,\n edgeType: null,\n node: null,\n since: null,\n against: null,\n errorId: null,\n hypotheticalAction: null,\n type: null,\n minConfidence: null,\n to: null,\n token: null,\n positional: [],\n }\n for (let i = 0; i < rest.length; i++) {\n const arg = rest[i] as string\n\n // Boolean flags first.\n if (arg === '--apply') { out.apply = true; continue }\n if (arg === '--dry-run') { out.dryRun = true; continue }\n if (arg === '--no-install') { out.noInstall = true; continue }\n if (arg === '--no-instrument') { out.noInstrument = true; continue }\n if (arg === '--no-open') { out.noOpen = true; continue }\n if (arg === '--yes' || arg === '-y') { out.yes = true; continue }\n if (arg === '--verbose') { out.verbose = true; continue }\n if (arg === '--print-config') { out.printConfig = true; continue }\n if (arg === '--json') { out.json = true; continue }\n\n // String/number flags via the shared table.\n let matched = false\n for (const [flag, field] of STRING_FLAGS) {\n if (arg === flag) {\n const next = rest[i + 1]\n if (next === undefined) {\n console.error(`neat: ${flag} requires a value`)\n process.exit(2)\n }\n assignFlag(out, field, next)\n i++\n matched = true\n break\n }\n if (arg.startsWith(`${flag}=`)) {\n assignFlag(out, field, arg.slice(flag.length + 1))\n matched = true\n break\n }\n }\n if (matched) continue\n positional.push(arg)\n }\n out.positional = positional\n return out\n}\n\nexport { parseArgs }\n\n// Number flags get parsed at assignment time so misuse (`--depth foo`)\n// surfaces with exit code 2 before any network call.\nfunction assignFlag(out: ParsedArgs, field: (typeof STRING_FLAGS)[number][1], value: string): void {\n if (field === 'depth' || field === 'limit') {\n const n = Number(value)\n if (!Number.isFinite(n) || !Number.isInteger(n) || n < 1) {\n console.error(`neat: --${field === 'depth' ? 'depth' : 'limit'} must be a positive integer`)\n process.exit(2)\n }\n out[field] = n\n return\n }\n if (field === 'minConfidence') {\n const n = Number(value)\n if (!Number.isFinite(n) || n < 0 || n > 1) {\n console.error('neat: --min-confidence must be a number in [0, 1]')\n process.exit(2)\n }\n out.minConfidence = n\n return\n }\n // String fields.\n ;(out as unknown as Record<string, unknown>)[field] = value\n}\n\n// Per-type node/edge counts + compat formatting moved into summary.ts as\n// part of the value-forward findings block (issue #305 / ADR-073 §5).\n\n// The `neat --version` family reads its answer from the bundled package's\n// own package.json. Reading at run time keeps the published bin in lockstep\n// with whatever version `tsup` shipped without a build-time substitution.\n// `dist/cli.cjs` sits one level below the package root.\nexport function readPackageVersion(): string {\n const here =\n typeof __dirname !== 'undefined'\n ? __dirname\n : path.dirname(fileURLToPath(import.meta.url))\n // dist/ → package root. tsup writes both cjs and mjs to dist/, so the\n // parent-of-parent walk is the same in either format.\n const candidates = [\n path.resolve(here, '../package.json'),\n path.resolve(here, '../../package.json'),\n ]\n for (const candidate of candidates) {\n try {\n const raw = readFileSync(candidate, 'utf8')\n const parsed = JSON.parse(raw) as { name?: string; version?: string }\n if (parsed.name === '@neat.is/core' && typeof parsed.version === 'string') {\n return parsed.version\n }\n } catch {\n // try the next candidate\n }\n }\n return 'unknown'\n}\n\nfunction printVersion(): void {\n process.stdout.write(`${readPackageVersion()}\\n`)\n}\n\nfunction printBanner(): void {\n console.log('███╗ ██╗███████╗ █████╗ ████████╗')\n console.log('████╗ ██║██╔════╝██╔══██╗╚══██╔══╝')\n console.log('██╔██╗ ██║█████╗ ███████║ ██║ ')\n console.log('██║╚██╗██║██╔══╝ ██╔══██║ ██║ ')\n console.log('██║ ╚████║███████╗██║ ██║ ██║ ')\n console.log('╚═╝ ╚═══╝╚══════╝╚═╝ ╚═╝ ╚═╝ ')\n console.log('')\n console.log(' Network Expressive Architecting Tool')\n console.log(' neat.is · v0.4.0 · Apache 2.0')\n console.log('')\n}\n\nfunction printDiscoveryReport(opts: InitOptions, services: DiscoveredService[]): void {\n const languages = [...new Set(services.map((s) => s.node.language))].sort()\n const mode = opts.dryRun ? 'dry-run' : opts.apply ? 'apply' : 'patch-only'\n printBanner()\n console.log('=== neat init: discovery ===')\n console.log(`scan path: ${opts.scanPath}`)\n console.log(`project: ${opts.project}`)\n console.log(`mode: ${mode}`)\n console.log(`services: ${services.length}`)\n for (const s of services) {\n const where = s.node.repoPath && s.node.repoPath.length > 0 ? s.node.repoPath : '.'\n console.log(` - ${s.node.name} (${s.node.language}) — ${where}`)\n }\n console.log(`languages: ${languages.length > 0 ? languages.join(', ') : '(none)'}`)\n if (opts.noInstall) {\n console.log('install: skipped (--no-install)')\n } else if (opts.dryRun) {\n console.log('install: patch will be written to neat.patch; nothing else.')\n } else if (opts.apply) {\n console.log('install: patch will be applied in place. Run `npm install` afterwards.')\n } else {\n console.log('install: patch will be written to neat.patch for review.')\n }\n console.log('')\n}\n\nasync function buildPatchSections(\n services: DiscoveredService[],\n project: string,\n): Promise<PatchSection[]> {\n const sections: PatchSection[] = []\n for (const svc of services) {\n const installer = await pickInstaller(svc.dir)\n if (!installer) continue\n // v0.4.1 / refs #339 — pass the registered project name so the per-\n // package `.env.neat` carries `OTEL_SERVICE_NAME=<project>`. The daemon\n // routes spans by registered project name; matching keys end-to-end\n // is what keeps OBSERVED edges landing.\n const plan: InstallPlan = await installer.plan(svc.dir, { project })\n // Lib-only + runtime-kind-skipped packages keep a section so the dry-run\n // patch documents the skip and the apply summary counts them (ADR-069 §2,\n // v0.4.4 / #370). Empty plans without either flag are already-instrumented\n // end-to-end and drop out.\n if (isEmptyPlan(plan) && !plan.libOnly && plan.runtimeKind === undefined) continue\n sections.push({ installer: installer.name, plan })\n }\n return sections\n}\n\nexport async function runInit(opts: InitOptions): Promise<InitResult> {\n const written: string[] = []\n\n // ── Step 1: validate path ────────────────────────────────────────────\n const stat = await fs.stat(opts.scanPath).catch(() => null)\n if (!stat || !stat.isDirectory()) {\n console.error(`neat init: ${opts.scanPath} is not a directory`)\n return { exitCode: 2, writtenFiles: written }\n }\n\n // ── Step 2: discovery (ADR-046 #2 — before any mutation) ─────────────\n const services = await discoverServices(opts.scanPath)\n printDiscoveryReport(opts, services)\n\n // ── Step 3: plan SDK install (pure data, no fs writes) ───────────────\n const sections = opts.noInstall ? [] : await buildPatchSections(services, opts.project)\n const patch = renderPatch(sections)\n const patchPath = path.join(opts.scanPath, 'neat.patch')\n\n // ── Step 4: dry-run shortcut — only neat.patch is allowed to land ────\n if (opts.dryRun) {\n await fs.writeFile(patchPath, patch, 'utf8')\n written.push(patchPath)\n console.log(`dry-run: patch written to ${patchPath}`)\n // ADR-073 §6 — list the planned `.gitignore` write alongside the other\n // planned writes. No file mutation in dry-run; only the announcement.\n const gitignorePath = path.join(opts.scanPath, '.gitignore')\n const gitignoreExists = await fs.stat(gitignorePath).then(() => true).catch(() => false)\n const verb = gitignoreExists ? 'append' : 'create'\n console.log(`dry-run: would ${verb} ${gitignorePath} (add neat-out/)`)\n console.log('rerun without --dry-run to register and snapshot.')\n return { exitCode: 0, writtenFiles: written }\n }\n\n // ── Step 5: extraction + snapshot ────────────────────────────────────\n // Use DEFAULT_PROJECT for the in-memory graph slot when --project wasn't\n // explicitly passed; named projects get isolated slots per ADR-026.\n const graphKey = opts.projectExplicit ? opts.project : DEFAULT_PROJECT\n resetGraph(graphKey)\n const graph = getGraph(graphKey)\n // ADR-065 — per-file extraction failures land alongside the snapshot in\n // <projectDir>/neat-out/errors.ndjson. Same file as OTel error events\n // (ADR-033) with a `source: 'extract'` discriminator.\n const projectPaths = pathsForProject(\n graphKey,\n path.join(opts.scanPath, 'neat-out'),\n )\n const errorsPath = path.join(path.dirname(opts.outPath), path.basename(projectPaths.errorsPath))\n const result = await extractFromDirectory(graph, opts.scanPath, { errorsPath })\n await saveGraphToDisk(graph, opts.outPath)\n written.push(opts.outPath)\n\n // ADR-073 §6 — ensure `neat-out/` is git-ignored. Snapshot just landed on\n // disk; an un-ignored neat-out/ would leak into git history on the next\n // commit. Idempotent: the helper no-ops when the line is already present.\n const gitignoreResult = await ensureNeatOutIgnored(opts.scanPath)\n if (gitignoreResult.action !== 'unchanged') {\n written.push(gitignoreResult.file)\n }\n\n // ── Step 6: register in the machine-level registry ───────────────────\n // Idempotent re-init of the same path under the same name refreshes the\n // entry; collision against a different path exits non-zero (ADR-046 #7).\n const languages = [...new Set(services.map((s) => s.node.language))].sort()\n let currentProjectName = opts.project\n try {\n const entry = await addProject({\n name: opts.project,\n path: opts.scanPath,\n languages,\n status: 'active',\n })\n currentProjectName = entry.name\n } catch (err) {\n if (err instanceof ProjectNameCollisionError) {\n console.error(`neat init: ${err.message}`)\n console.error('pass --project <other-name> to register under a different name.')\n return { exitCode: 1, writtenFiles: written }\n }\n throw err\n }\n\n // Narrow the active-project surface to the project the operator just\n // registered. Mirrors the bare-orchestrator behaviour so `neat init` and\n // `neat <path>` agree on the activation contract.\n const siblings = await listProjects()\n const paused: string[] = []\n for (const p of siblings) {\n if (p.name !== currentProjectName && p.status === 'active') {\n await setStatus(p.name, 'paused')\n paused.push(p.name)\n }\n }\n if (paused.length > 0) {\n const plural = paused.length === 1 ? '' : 's'\n console.log(\n `neat: paused ${paused.length} sibling project${plural}; run \\`neat resume <name>\\` to bring one back active.`,\n )\n }\n\n // ── Step 7: write or apply patch ─────────────────────────────────────\n if (!opts.noInstall) {\n if (opts.apply) {\n let instrumented = 0\n let alreadyInstrumented = 0\n let libOnly = 0\n let browserBundle = 0\n let reactNative = 0\n for (const section of sections) {\n const installer = INSTALLERS.find((i) => i.name === section.installer)\n if (!installer) continue\n const outcome = await installer.apply(section.plan)\n if (outcome.outcome === 'instrumented') {\n instrumented++\n for (const f of outcome.writtenFiles) written.push(f)\n } else if (outcome.outcome === 'already-instrumented') {\n alreadyInstrumented++\n } else if (outcome.outcome === 'lib-only') {\n libOnly++\n } else if (outcome.outcome === 'browser-bundle') {\n browserBundle++\n console.log(`skipping ${section.plan.serviceDir}: browser bundle; browser-OTel support lands in a future release.`)\n } else if (outcome.outcome === 'react-native') {\n reactNative++\n console.log(`skipping ${section.plan.serviceDir}: React Native target; browser-OTel support lands in a future release.`)\n }\n }\n if (sections.length > 0) {\n console.log('')\n const parts = [\n `instrumented ${instrumented}`,\n `already-instrumented ${alreadyInstrumented}`,\n `lib-only ${libOnly}`,\n ]\n if (browserBundle > 0) parts.push(`browser-bundle ${browserBundle}`)\n if (reactNative > 0) parts.push(`react-native ${reactNative}`)\n console.log(`apply: ${parts.join(', ')}`)\n console.log('Run `npm install` (or your language equivalent) to refresh lockfiles.')\n }\n } else {\n await fs.writeFile(patchPath, patch, 'utf8')\n written.push(patchPath)\n }\n }\n\n // ── Step 8: summary + incompatibilities ──────────────────────────────\n // ADR-073 §5 / issue #305 — findings-first: compat violations, top\n // divergences, services without OBSERVED coverage, then the OTel env-vars\n // block. Per-type counts ride behind `--verbose`.\n console.log('')\n console.log(`snapshot: ${opts.outPath}`)\n console.log(`added: ${result.nodesAdded} nodes, ${result.edgesAdded} edges`)\n console.log('')\n const divergenceResult = computeDivergences(graph)\n console.log(\n renderValueForwardSummary({\n graph,\n divergences: divergenceResult.divergences,\n verbose: opts.verbose,\n }),\n )\n // ADR-065 — loud failure mode banner. Unconditional; 0 is a positive\n // signal. When errors > 0, also surface the sidecar path so the operator\n // can read per-file detail.\n console.log(formatExtractionBanner(result.extractionErrors))\n if (result.extractionErrors > 0) {\n console.log(`errors: ${errorsPath}`)\n }\n // ADR-066 — precision-floor drop banner. Always emitted; 0 is observable\n // as a positive signal that no cross-service heuristic edges grew the\n // graph this pass.\n console.log(formatPrecisionFloorBanner(result.extractedDropped))\n\n // ADR-065 — NEAT_STRICT_EXTRACTION=1 makes any per-file failure exit\n // non-zero. Default is forgiving (banner only). Exit code 4 keeps\n // misuse (2) and daemon-down (3) distinguishable per the CLI contract.\n if (result.extractionErrors > 0 && isStrictExtractionEnabled()) {\n return { exitCode: 4, writtenFiles: written }\n }\n\n return { exitCode: 0, writtenFiles: written }\n}\n\n// ── Claude Code skill (ADR-049 / v0.2.5 step 6) ────────────────────────\n//\n// The skill is a one-shot MCP-config drop-in. Source of truth for the\n// snippet lives here (the @neat.is/claude-skill package's\n// claude_code_config.json holds an identical copy for documentation; a\n// contract test keeps the two byte-aligned).\nexport const CLAUDE_SKILL_CONFIG = {\n mcpServers: {\n neat: {\n type: 'stdio' as const,\n command: 'npx',\n args: ['-y', '@neat.is/mcp'],\n env: {\n NEAT_API_URL: 'http://localhost:8080',\n },\n },\n },\n}\n\nfunction claudeConfigPath(): string {\n // ~/.claude.json is Claude Code's user-level MCP config. Tests override\n // via NEAT_CLAUDE_CONFIG so they don't touch the real file.\n const override = process.env.NEAT_CLAUDE_CONFIG\n if (override && override.length > 0) return path.resolve(override)\n const home = process.env.HOME ?? process.env.USERPROFILE ?? ''\n return path.join(home, '.claude.json')\n}\n\nexport interface SkillOptions {\n apply: boolean\n printConfig: boolean\n}\n\nexport async function runSkill(opts: SkillOptions): Promise<{ exitCode: number }> {\n const snippet = JSON.stringify(CLAUDE_SKILL_CONFIG, null, 2) + '\\n'\n\n if (opts.printConfig) {\n process.stdout.write(snippet)\n return { exitCode: 0 }\n }\n\n if (opts.apply) {\n const target = claudeConfigPath()\n let existing: Record<string, unknown> = {}\n try {\n existing = JSON.parse(await fs.readFile(target, 'utf8'))\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {\n console.error(`neat skill: failed to read ${target} — ${(err as Error).message}`)\n return { exitCode: 1 }\n }\n }\n // Merge mcpServers.neat without disturbing other entries the user\n // might have wired up by hand.\n const mcp =\n (existing as { mcpServers?: Record<string, unknown> }).mcpServers ?? {}\n const merged = {\n ...existing,\n mcpServers: { ...mcp, neat: CLAUDE_SKILL_CONFIG.mcpServers.neat },\n }\n await fs.mkdir(path.dirname(target), { recursive: true })\n await fs.writeFile(target, JSON.stringify(merged, null, 2) + '\\n', 'utf8')\n console.log(`neat skill: wrote mcpServers.neat to ${target}`)\n console.log('restart Claude Code to pick up the new MCP server.')\n return { exitCode: 0 }\n }\n\n console.log('neat skill — Claude Code MCP drop-in for NEAT')\n console.log('')\n console.log(' --print-config print the JSON snippet to stdout')\n console.log(' --apply merge mcpServers.neat into ~/.claude.json')\n console.log('')\n console.log('Manual install: copy mcpServers.neat from --print-config into ~/.claude.json,')\n console.log('then restart Claude Code. See packages/claude-skill/SKILL.md for the tool list.')\n return { exitCode: 0 }\n}\n\nasync function main(): Promise<void> {\n const [, , cmd, ...rest] = process.argv\n\n if (!cmd || cmd === '-h' || cmd === '--help') {\n usage()\n process.exit(0)\n }\n\n if (cmd === '--version' || cmd === '-v' || cmd === 'version') {\n printVersion()\n process.exit(0)\n }\n\n const parsed = parseArgs(rest)\n const { positional, apply, dryRun, noInstall } = parsed\n const project = parsed.project ?? DEFAULT_PROJECT\n\n if (cmd === 'init') {\n const target = positional[0]\n if (!target) {\n console.error('neat init: missing <path>')\n usage()\n process.exit(2)\n }\n if (apply && dryRun) {\n console.error('neat init: --apply and --dry-run are mutually exclusive')\n process.exit(2)\n }\n const scanPath = path.resolve(target)\n // ADR-046 — when --project isn't passed, the registry name defaults to\n // the basename of the scan path. The in-memory graph slot stays on\n // DEFAULT_PROJECT (back-compat with existing `neat watch` invocations).\n const projectExplicit = parsed.project !== null\n const projectName = projectExplicit ? project : path.basename(scanPath)\n // Default project keeps writing to graph.json (ADR-026 back-compat);\n // named projects use <project>.json under the same neat-out directory.\n const projectKey = projectExplicit ? project : DEFAULT_PROJECT\n const fallback = pathsForProject(projectKey, path.join(scanPath, 'neat-out')).snapshotPath\n const outPath = path.resolve(process.env.NEAT_OUT_PATH ?? fallback)\n const result = await runInit({\n scanPath,\n outPath,\n project: projectName,\n projectExplicit,\n apply,\n dryRun,\n noInstall,\n verbose: parsed.verbose,\n })\n if (result.exitCode !== 0) process.exit(result.exitCode)\n return\n }\n\n if (cmd === 'watch') {\n const target = positional[0]\n if (!target) {\n console.error('neat watch: missing <path>')\n usage()\n process.exit(2)\n }\n const scanPath = path.resolve(target)\n const stat = await fs.stat(scanPath).catch(() => null)\n if (!stat || !stat.isDirectory()) {\n console.error(`neat watch: ${scanPath} is not a directory`)\n process.exit(2)\n }\n const projectPaths = pathsForProject(project, path.join(scanPath, 'neat-out'))\n const outPath = path.resolve(process.env.NEAT_OUT_PATH ?? projectPaths.snapshotPath)\n const errorsPath = path.resolve(\n process.env.NEAT_ERRORS_PATH ??\n path.join(path.dirname(outPath), path.basename(projectPaths.errorsPath)),\n )\n const staleEventsPath = path.resolve(\n process.env.NEAT_STALE_EVENTS_PATH ??\n path.join(path.dirname(outPath), path.basename(projectPaths.staleEventsPath)),\n )\n\n const embeddingsCachePath = process.env.NEAT_EMBEDDINGS_CACHE_PATH\n ? path.resolve(process.env.NEAT_EMBEDDINGS_CACHE_PATH)\n : undefined\n\n const handle: WatchHandle = await startWatch(getGraph(project), {\n scanPath,\n outPath,\n errorsPath,\n staleEventsPath,\n project,\n ...(embeddingsCachePath ? { embeddingsCachePath } : {}),\n host: process.env.HOST ?? '0.0.0.0',\n port: Number(process.env.PORT ?? 8080),\n otelPort: Number(process.env.OTEL_PORT ?? 4318),\n otelGrpc: process.env.NEAT_OTLP_GRPC === 'true',\n otelGrpcPort: process.env.NEAT_OTLP_GRPC_PORT\n ? Number(process.env.NEAT_OTLP_GRPC_PORT)\n : undefined,\n })\n\n // startPersistLoop already wires SIGTERM/SIGINT to flush + exit. Hook in\n // ahead of it so the watcher closes cleanly first; the persist handler's\n // `process.exit(0)` will still run after our stop() resolves.\n let shuttingDown = false\n const shutdown = (signal: NodeJS.Signals): void => {\n if (shuttingDown) return\n shuttingDown = true\n console.log(`neat watch: ${signal} received, stopping…`)\n void handle.stop().catch((err) => {\n console.error('neat watch: shutdown error', err)\n })\n }\n process.on('SIGTERM', shutdown)\n process.on('SIGINT', shutdown)\n return\n }\n\n if (cmd === 'list') {\n const projects = await listProjects()\n if (projects.length === 0) {\n console.log('no projects registered. run `neat init <path>` to register one.')\n return\n }\n for (const p of projects) {\n const seen = p.lastSeenAt ? p.lastSeenAt : 'never'\n const langs = p.languages.length > 0 ? p.languages.join(',') : '-'\n console.log(`${p.name}\\t${p.status}\\t${langs}\\t${p.path}\\tlast-seen=${seen}`)\n }\n return\n }\n\n if (cmd === 'pause') {\n const name = positional[0]\n if (!name) {\n console.error('neat pause: missing <name>')\n usage()\n process.exit(2)\n }\n try {\n const entry = await setStatus(name, 'paused')\n console.log(`paused: ${entry.name} (${entry.path})`)\n } catch (err) {\n console.error((err as Error).message)\n process.exit(1)\n }\n return\n }\n\n if (cmd === 'resume') {\n const name = positional[0]\n if (!name) {\n console.error('neat resume: missing <name>')\n usage()\n process.exit(2)\n }\n try {\n const entry = await setStatus(name, 'active')\n console.log(`resumed: ${entry.name} (${entry.path})`)\n } catch (err) {\n console.error((err as Error).message)\n process.exit(1)\n }\n return\n }\n\n if (cmd === 'skill') {\n const result = await runSkill({ apply: parsed.apply, printConfig: parsed.printConfig })\n if (result.exitCode !== 0) process.exit(result.exitCode)\n return\n }\n\n if (cmd === 'uninstall') {\n const name = positional[0]\n if (!name) {\n console.error('neat uninstall: missing <name>')\n usage()\n process.exit(2)\n }\n const removed = await removeProject(name)\n if (!removed) {\n console.error(`neat uninstall: no project named \"${name}\"`)\n process.exit(1)\n }\n console.log(`unregistered: ${removed.name} (${removed.path})`)\n console.log('note: neat-out/, policy.json, and other files at the project path were left in place.')\n return\n }\n\n if (cmd === 'deploy') {\n // ADR-073 §2 — detect substrate, generate token, emit artifact, print\n // the OTel env-vars block. Token is the only secret printed to stdout;\n // the artifact written to disk names the env-var by reference only.\n const artifact = await runDeploy()\n const block = renderOtelEnvBlock(artifact.token)\n\n console.log()\n console.log(`Substrate detected: ${artifact.substrate}`)\n if (artifact.artifactPath) {\n console.log(`Artifact written: ${artifact.artifactPath}`)\n } else {\n console.log('No on-disk artifact — copy the snippet below into your substrate.')\n console.log()\n console.log(artifact.contents)\n }\n console.log()\n console.log('NEAT_AUTH_TOKEN (store this — it will not be printed again):')\n console.log(` ${artifact.token}`)\n console.log()\n console.log(\"For your application's deploy platform, set these env vars:\")\n console.log(block.split('\\n').map((l) => ` ${l}`).join('\\n'))\n console.log()\n console.log('Once NEAT is running, your dashboard will be at:')\n console.log(' https://<host>:6328')\n console.log()\n console.log('To start NEAT, run:')\n console.log(` ${artifact.startCommand}`)\n return\n }\n\n if (cmd === 'sync') {\n // ADR-074 §1 — re-runs discovery + extract + SDK apply + daemon notify\n // against the registered project. Skips registry registration, browser\n // open, daemon spawn, and the first-run summary block.\n const result = await runSync({\n ...(parsed.project ? { project: parsed.project } : {}),\n ...(parsed.to ? { to: parsed.to } : {}),\n ...(parsed.token ? { token: parsed.token } : {}),\n dryRun: parsed.dryRun,\n noInstrument: parsed.noInstrument,\n json: parsed.json,\n })\n if (result.exitCode !== 0) process.exit(result.exitCode)\n return\n }\n\n // ── Query verbs (ADR-050) ────────────────────────────────────────────\n // The nine verbs mirror the MCP tool allowlist. Same multi-project\n // routing, same three-part response shape (summary + block + footer),\n // exit codes branch on misuse vs server error vs daemon-down.\n if (QUERY_VERBS.has(cmd)) {\n const code = await runQueryVerb(cmd, parsed)\n if (code !== 0) process.exit(code)\n return\n }\n\n // ── Bare-path orchestrator (ADR-073 §1) ──────────────────────────────\n // `neat <path>` — when the first positional doesn't match any verb but\n // resolves to a directory, hand the run off to the orchestrator. This is\n // the `npx neat.is <path>` shape from ADR-073: one command, end-to-end.\n const orchestratorCode = await tryOrchestrator(cmd, parsed)\n if (orchestratorCode !== null) {\n if (orchestratorCode !== 0) process.exit(orchestratorCode)\n return\n }\n\n console.error(`neat: unknown command \"${cmd}\"`)\n usage()\n process.exit(1)\n}\n\n// Returns null when the first positional doesn't resolve to a directory\n// (so the caller can fall through to the unknown-command error). Returns\n// an exit code when the orchestrator ran.\nasync function tryOrchestrator(cmd: string, parsed: ParsedArgs): Promise<number | null> {\n const scanPath = path.resolve(cmd)\n const stat = await fs.stat(scanPath).catch(() => null)\n if (!stat || !stat.isDirectory()) return null\n\n const projectExplicit = parsed.project !== null\n const projectName = projectExplicit ? (parsed.project as string) : path.basename(scanPath)\n const result = await runOrchestrator({\n scanPath,\n project: projectName,\n projectExplicit,\n noInstrument: parsed.noInstrument,\n noOpen: parsed.noOpen,\n yes: parsed.yes,\n })\n return result.exitCode\n}\n\n// ── Query verb dispatcher ──────────────────────────────────────────────\n\nexport const QUERY_VERBS: Set<string> = new Set([\n 'root-cause',\n 'blast-radius',\n 'dependencies',\n 'observed-dependencies',\n 'incidents',\n 'search',\n 'diff',\n 'stale-edges',\n 'policies',\n // Tenth verb (ADR-060) — amends ADR-050's locked allowlist of nine.\n 'divergences',\n])\n\n// ADR-050 #2: --project flag → NEAT_PROJECT env → undefined (server's\n// `default` slot). undefined keeps legacy unprefixed routes; explicit names\n// route through /projects/:project/...\nfunction resolveProjectFlag(parsed: ParsedArgs): string | undefined {\n if (parsed.project) return parsed.project\n const env = process.env.NEAT_PROJECT\n if (env && env.length > 0 && env !== DEFAULT_PROJECT) return env\n return undefined\n}\n\nexport async function runQueryVerb(cmd: string, parsed: ParsedArgs): Promise<number> {\n const baseUrl = process.env.NEAT_API_URL ?? 'http://localhost:8080'\n const client = createHttpClient(baseUrl)\n const project = resolveProjectFlag(parsed)\n const positional = parsed.positional\n\n // Per-verb arg/flag validation. Misuse exits 2 before any network call.\n let work: Promise<VerbResult>\n switch (cmd) {\n case 'root-cause': {\n const node = positional[0]\n if (!node) {\n console.error('neat root-cause: missing <node-id>')\n return 2\n }\n work = runRootCause(client, {\n errorNode: node,\n ...(parsed.errorId ? { errorId: parsed.errorId } : {}),\n ...(project ? { project } : {}),\n })\n break\n }\n case 'blast-radius': {\n const node = positional[0]\n if (!node) {\n console.error('neat blast-radius: missing <node-id>')\n return 2\n }\n work = runBlastRadius(client, {\n nodeId: node,\n ...(parsed.depth !== null ? { depth: parsed.depth } : {}),\n ...(project ? { project } : {}),\n })\n break\n }\n case 'dependencies': {\n const node = positional[0]\n if (!node) {\n console.error('neat dependencies: missing <node-id>')\n return 2\n }\n work = runDependencies(client, {\n nodeId: node,\n ...(parsed.depth !== null ? { depth: parsed.depth } : {}),\n ...(project ? { project } : {}),\n })\n break\n }\n case 'observed-dependencies': {\n const node = positional[0]\n if (!node) {\n console.error('neat observed-dependencies: missing <node-id>')\n return 2\n }\n work = runObservedDependencies(client, {\n nodeId: node,\n ...(project ? { project } : {}),\n })\n break\n }\n case 'incidents': {\n // node-id is optional — bare `neat incidents` returns the global log.\n work = runIncidents(client, {\n ...(positional[0] ? { nodeId: positional[0] } : {}),\n ...(parsed.limit !== null ? { limit: parsed.limit } : {}),\n ...(project ? { project } : {}),\n })\n break\n }\n case 'search': {\n const q = positional.join(' ').trim()\n if (!q) {\n console.error('neat search: missing <query>')\n return 2\n }\n work = runSearch(client, { query: q, ...(project ? { project } : {}) })\n break\n }\n case 'diff': {\n // --against names a snapshot file the core can resolve via\n // loadSnapshotForDiff. --since is reserved for a future date-range\n // mode (the contract lists it as `[--since <date>]`); for MVP, the\n // diff verb requires --against.\n const against = parsed.against ?? parsed.since\n if (!against) {\n console.error('neat diff: --against <snapshot-path> is required')\n return 2\n }\n work = runDiff(client, {\n againstSnapshot: against,\n ...(project ? { project } : {}),\n })\n break\n }\n case 'stale-edges': {\n work = runStaleEdges(client, {\n ...(parsed.limit !== null ? { limit: parsed.limit } : {}),\n ...(parsed.edgeType ? { edgeType: parsed.edgeType } : {}),\n ...(project ? { project } : {}),\n })\n break\n }\n case 'policies': {\n let hypothetical: ReturnType<typeof JSON.parse> | undefined\n if (parsed.hypotheticalAction) {\n try {\n hypothetical = JSON.parse(parsed.hypotheticalAction)\n } catch (err) {\n console.error(\n `neat policies: --hypothetical-action must be valid JSON: ${(err as Error).message}`,\n )\n return 2\n }\n }\n work = runPolicies(client, {\n ...(parsed.node ? { nodeId: parsed.node } : {}),\n ...(hypothetical ? { hypotheticalAction: hypothetical } : {}),\n ...(project ? { project } : {}),\n })\n break\n }\n case 'divergences': {\n let typeFilter: DivergenceType[] | undefined\n if (parsed.type) {\n const parts = parsed.type\n .split(',')\n .map((s) => s.trim())\n .filter((s) => s.length > 0)\n const out: DivergenceType[] = []\n for (const p of parts) {\n const r = DivergenceTypeSchema.safeParse(p)\n if (!r.success) {\n console.error(\n `neat divergences: unknown --type \"${p}\". allowed: ${DivergenceTypeSchema.options.join(', ')}`,\n )\n return 2\n }\n out.push(r.data)\n }\n typeFilter = out\n }\n work = runDivergences(client, {\n ...(typeFilter ? { type: typeFilter } : {}),\n ...(parsed.minConfidence !== null ? { minConfidence: parsed.minConfidence } : {}),\n ...(parsed.node ? { node: parsed.node } : {}),\n ...(project ? { project } : {}),\n })\n break\n }\n default:\n // Unreachable — QUERY_VERBS gates the dispatch.\n console.error(`neat: unknown query verb \"${cmd}\"`)\n return 2\n }\n\n try {\n const result = await work\n if (parsed.json) process.stdout.write(formatJson(result) + '\\n')\n else process.stdout.write(formatHuman(result) + '\\n')\n return 0\n } catch (err) {\n // Server / transport errors land on stderr per ADR-050 #3 (stderr for\n // diagnostics, stdout for results — never mix). Exit code branches per\n // ADR-050 #4: 1 for HttpError, 3 for TransportError.\n if (err instanceof HttpError) {\n const detail = err.responseBody.length > 0 ? err.responseBody : err.message\n console.error(`neat ${cmd}: ${detail.trim()}`)\n } else if (err instanceof TransportError) {\n console.error(`neat ${cmd}: ${err.message}. Is the daemon running? (NEAT_API_URL=${process.env.NEAT_API_URL ?? 'http://localhost:8080'})`)\n } else {\n console.error(`neat ${cmd}: ${(err as Error).message}`)\n }\n return exitCodeForError(err)\n }\n}\n\n// Only auto-run when invoked as the CLI entry point. Importing this module\n// from tests must not start the parser; otherwise vitest sees a stray\n// `process.exit` from `main()` running with no argv.\nconst entry = process.argv[1] ?? ''\nif (/[\\\\/]cli\\.(?:cjs|js)$/.test(entry) || entry.endsWith('/cli') || entry.endsWith('/neat') || entry.endsWith('/neat.is')) {\n main().catch((err) => {\n console.error(err)\n process.exit(1)\n })\n}\n","/**\n * `.gitignore` automation for the init flow (ADR-073 §6).\n *\n * Init writes a snapshot under `<projectDir>/neat-out/`. Un-ignored, that\n * directory leaks the snapshot into git history within one commit. The\n * helper here ensures `neat-out/` is present in `<projectDir>/.gitignore` —\n * appending to an existing file with a NEAT comment header, creating the\n * file when absent, no-oping when the line is already there.\n *\n * Idempotency rule: an exact-match line (`neat-out/` or `neat-out`, with\n * any surrounding whitespace) counts as already-present. No duplicate\n * line is written on a re-run.\n */\n\nimport { promises as fs } from 'node:fs'\nimport path from 'node:path'\n\nexport const NEAT_OUT_LINE = 'neat-out/'\nconst NEAT_HEADER = '# NEAT — machine-local snapshots and events'\n\nexport interface EnsureNeatOutResult {\n // 'added' when the line was appended to an existing .gitignore.\n // 'created' when the file did not exist and was created with a single line.\n // 'unchanged' when the line was already present.\n action: 'added' | 'created' | 'unchanged'\n // Absolute path to the .gitignore file, regardless of action.\n file: string\n}\n\nfunction isNeatOutLine(line: string): boolean {\n const trimmed = line.trim()\n return trimmed === 'neat-out/' || trimmed === 'neat-out'\n}\n\nexport async function ensureNeatOutIgnored(projectDir: string): Promise<EnsureNeatOutResult> {\n const file = path.join(projectDir, '.gitignore')\n let existing: string | null = null\n try {\n existing = await fs.readFile(file, 'utf8')\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') throw err\n }\n\n if (existing === null) {\n await fs.writeFile(file, `${NEAT_HEADER}\\n${NEAT_OUT_LINE}\\n`, 'utf8')\n return { action: 'created', file }\n }\n\n for (const line of existing.split(/\\r?\\n/)) {\n if (isNeatOutLine(line)) return { action: 'unchanged', file }\n }\n\n // Append with a leading newline if the file doesn't already end in one,\n // so the comment header sits on its own line.\n const needsLeadingNewline = existing.length > 0 && !existing.endsWith('\\n')\n const appended = `${needsLeadingNewline ? '\\n' : ''}\\n${NEAT_HEADER}\\n${NEAT_OUT_LINE}\\n`\n await fs.writeFile(file, existing + appended, 'utf8')\n return { action: 'added', file }\n}\n","/**\n * Value-forward CLI summary (issue #305, ADR-073 §5).\n *\n * Replaces the per-type node/edge counts that ended `neat init` with a\n * findings-first block — compat violations, top divergences, services\n * that never produced an OBSERVED edge, and the OTel env-vars block the\n * operator pastes into their deploy platform. Per-type counts move behind\n * `--verbose`.\n *\n * The renderer is a pure string builder so tests can assert against its\n * output without spawning the CLI.\n */\n\nimport type { Divergence, GraphEdge, GraphNode, ServiceNode } from '@neat.is/types'\nimport { NodeType, Provenance } from '@neat.is/types'\nimport type { NeatGraph } from './graph.js'\n\nexport interface SummaryInput {\n graph: NeatGraph\n divergences: Divergence[]\n // True → render the per-type counts after the value-forward block.\n verbose: boolean\n}\n\n// Static placeholder. The orchestrator and `neat deploy` print the same\n// block; `neat deploy` substitutes the actual token + host. This shape\n// lives in one place so the wire format stays in step.\nexport function renderOtelEnvBlock(): string {\n return [\n 'for prod OTel routing, set these in your deploy platform\\'s env:',\n ' OTEL_EXPORTER_OTLP_ENDPOINT=https://<your-neat-host>:4318',\n ' OTEL_EXPORTER_OTLP_HEADERS=Authorization=Bearer <NEAT_AUTH_TOKEN>',\n ].join('\\n')\n}\n\nfunction findIncompatServices(nodes: GraphNode[]): ServiceNode[] {\n return nodes.filter(\n (n): n is ServiceNode =>\n n.type === NodeType.ServiceNode &&\n Array.isArray((n as ServiceNode).incompatibilities) &&\n ((n as ServiceNode).incompatibilities ?? []).length > 0,\n )\n}\n\n// Services that show up in the EXTRACTED graph but have no OBSERVED edge\n// pointing at or out of them. The thesis says: when the OBSERVED layer is\n// silent on a service, the gap is a load-bearing signal for the operator.\nfunction servicesWithoutObserved(nodes: GraphNode[], edges: GraphEdge[]): ServiceNode[] {\n const seen = new Set<string>()\n for (const e of edges) {\n if (e.provenance === Provenance.OBSERVED) {\n seen.add(e.source)\n seen.add(e.target)\n }\n }\n return nodes.filter(\n (n): n is ServiceNode => n.type === NodeType.ServiceNode && !seen.has(n.id),\n )\n}\n\nfunction formatDivergence(d: Divergence): string {\n // Short, scannable, one-line-per-finding. The reason field already carries\n // the load-bearing detail; the recommendation rides on a second indent.\n const conf = d.confidence.toFixed(2)\n return ` [${conf}] ${d.type} ${d.source} → ${d.target} — ${d.reason}`\n}\n\nexport function renderValueForwardSummary(input: SummaryInput): string {\n const { graph, divergences, verbose } = input\n const nodes: GraphNode[] = []\n graph.forEachNode((_id, attrs) => nodes.push(attrs))\n const edges: GraphEdge[] = []\n graph.forEachEdge((_id, attrs) => edges.push(attrs))\n\n const lines: string[] = []\n lines.push('=== neat: findings ===')\n lines.push('')\n\n // ── Compat violations (driver/engine mismatches) ───────────────────────\n const incompatServices = findIncompatServices(nodes)\n const totalIncompats = incompatServices.reduce(\n (acc, s) => acc + (s.incompatibilities?.length ?? 0),\n 0,\n )\n lines.push(`compat violations: ${totalIncompats}`)\n for (const svc of incompatServices) {\n for (const inc of svc.incompatibilities ?? []) {\n const detail = formatIncompat(inc)\n lines.push(` ${svc.name}: ${detail}`)\n }\n }\n lines.push('')\n\n // ── Top divergences (top 3 by confidence desc) ─────────────────────────\n const top = [...divergences].sort((a, b) => b.confidence - a.confidence).slice(0, 3)\n lines.push(`top divergences: ${divergences.length} total${top.length > 0 ? ', top 3:' : ''}`)\n for (const d of top) lines.push(formatDivergence(d))\n lines.push('')\n\n // ── Services missing OBSERVED coverage ─────────────────────────────────\n const noObserved = servicesWithoutObserved(nodes, edges)\n if (noObserved.length > 0) {\n lines.push(`services without OBSERVED coverage: ${noObserved.length}`)\n for (const svc of noObserved) lines.push(` ${svc.name}`)\n lines.push(' → run your services with the generated otel-init to populate OBSERVED edges.')\n lines.push('')\n }\n\n // ── OTel env-vars block (static; `neat deploy` substitutes real values)\n lines.push(renderOtelEnvBlock())\n lines.push('')\n\n // ── --verbose: per-type node/edge counts ──────────────────────────────\n if (verbose) {\n const byNode = new Map<string, number>()\n for (const n of nodes) byNode.set(n.type, (byNode.get(n.type) ?? 0) + 1)\n const byEdge = new Map<string, number>()\n for (const e of edges) byEdge.set(e.type, (byEdge.get(e.type) ?? 0) + 1)\n lines.push('=== graph (verbose) ===')\n lines.push(`total: ${graph.order} nodes, ${graph.size} edges`)\n lines.push('nodes:')\n for (const [t, c] of [...byNode.entries()].sort()) lines.push(` ${t}: ${c}`)\n lines.push('edges:')\n for (const [t, c] of [...byEdge.entries()].sort()) lines.push(` ${t}: ${c}`)\n lines.push('')\n }\n\n return lines.join('\\n')\n}\n\nfunction formatIncompat(inc: NonNullable<ServiceNode['incompatibilities']>[number]): string {\n if (inc.kind === 'node-engine') {\n const range = inc.declaredNodeEngine ? ` (engines.node=\"${inc.declaredNodeEngine}\")` : ''\n return `${inc.package}@${inc.packageVersion ?? '?'} requires Node ${inc.requiredNodeVersion}${range} — ${inc.reason}`\n }\n if (inc.kind === 'package-conflict') {\n const found = inc.foundVersion ? `@${inc.foundVersion}` : ' (missing)'\n return `${inc.package}@${inc.packageVersion ?? '?'} requires ${inc.requires.name}>=${inc.requires.minVersion}; found ${inc.requires.name}${found} — ${inc.reason}`\n }\n if (inc.kind === 'deprecated-api') {\n return `${inc.package}@${inc.packageVersion ?? '?'} is deprecated — ${inc.reason}`\n }\n return `${inc.driver}@${inc.driverVersion} vs ${inc.engine} ${inc.engineVersion} — ${inc.reason}`\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport chokidar, { type FSWatcher } from 'chokidar'\nimport type { FastifyInstance } from 'fastify'\nimport type { NeatGraph } from './graph.js'\nimport { buildApi } from './api.js'\nimport { ensureCompatLoaded } from './compat.js'\nimport { discoverServices, addServiceNodes } from './extract/services.js'\nimport { addServiceAliases } from './extract/aliases.js'\nimport { addDatabasesAndCompat } from './extract/databases/index.js'\nimport { addConfigNodes } from './extract/configs.js'\nimport { addCallEdges } from './extract/calls/index.js'\nimport { addInfra } from './extract/infra/index.js'\nimport { retireEdgesByFile } from './extract/retire.js'\nimport {\n makeErrorSpanWriter,\n makeSpanHandler,\n promoteFrontierNodes,\n startStalenessLoop,\n} from './ingest.js'\nimport {\n evaluateAllPolicies,\n loadPolicyFile,\n PolicyViolationsLog,\n} from './policy.js'\nimport type { Policy } from '@neat.is/types'\nimport { buildOtelReceiver } from './otel.js'\nimport { startOtelGrpcReceiver } from './otel-grpc.js'\nimport { loadGraphFromDisk, startPersistLoop } from './persist.js'\nimport { buildSearchIndex, type SearchIndex } from './search.js'\nimport { DEFAULT_PROJECT } from './graph.js'\nimport { Projects, pathsForProject } from './projects.js'\nimport { attachGraphToEventBus, emitNeatEvent } from './events.js'\n\nexport type ExtractPhase =\n | 'services'\n | 'aliases'\n | 'databases'\n | 'configs'\n | 'calls'\n | 'infra'\n\nconst ALL_PHASES: ExtractPhase[] = [\n 'services',\n 'aliases',\n 'databases',\n 'configs',\n 'calls',\n 'infra',\n]\n\n// Map a changed path to the phases that need re-running. Anything not matched\n// here falls back to a full re-extract — better an extra ~50ms of work than a\n// missed update because the path didn't fit a regex.\n//\n// Mapping:\n// package.json / requirements.txt / pyproject.toml → services + aliases + databases\n// (deps drive compat; aliases pull from manifest fields)\n// .env / *.env.* / prisma / knex / ormconfig → databases + configs\n// docker-compose / Dockerfile / *.tf / k8s yaml → infra + aliases\n// (compose labels and Dockerfile labels feed alias discovery)\n// *.js / *.ts / *.tsx / *.py / *.jsx / *.mjs / *.cjs → calls\n// *.yaml / *.yml that isn't compose → databases + configs (ORM yaml fallbacks)\nexport function classifyChange(relPath: string): Set<ExtractPhase> {\n const phases = new Set<ExtractPhase>()\n const base = path.basename(relPath).toLowerCase()\n const segments = relPath.split(path.sep).map((s) => s.toLowerCase())\n\n if (\n base === 'package.json' ||\n base === 'requirements.txt' ||\n base === 'pyproject.toml' ||\n base === 'setup.py'\n ) {\n phases.add('services')\n phases.add('aliases')\n phases.add('databases')\n }\n\n if (\n base === '.env' ||\n base.startsWith('.env.') ||\n base === 'schema.prisma' ||\n /^knexfile\\.(?:js|ts|cjs|mjs)$/.test(base) ||\n /^ormconfig\\.(?:js|ts|json|ya?ml)$/.test(base)\n ) {\n phases.add('databases')\n phases.add('configs')\n }\n\n if (\n base === 'dockerfile' ||\n /^docker-compose.*\\.ya?ml$/.test(base) ||\n base.endsWith('.tf') ||\n segments.includes('k8s') ||\n segments.includes('kustomize') ||\n segments.includes('manifests')\n ) {\n phases.add('infra')\n phases.add('aliases')\n }\n\n if (/\\.(?:js|jsx|mjs|cjs|ts|tsx|py)$/.test(base)) {\n phases.add('calls')\n }\n\n if (/\\.ya?ml$/.test(base) && !/^docker-compose.*\\.ya?ml$/.test(base)) {\n // Generic yaml — could be an ORM file, k8s manifest, or random config.\n // Cheap to run databases + configs; if it was infra, the dir-name check\n // above already added that phase.\n phases.add('databases')\n phases.add('configs')\n }\n\n return phases\n}\n\ninterface RunPhasesResult {\n phases: ExtractPhase[]\n nodesAdded: number\n edgesAdded: number\n frontiersPromoted: number\n durationMs: number\n}\n\nexport async function runExtractPhases(\n graph: NeatGraph,\n scanPath: string,\n phases: Set<ExtractPhase>,\n // Project tag passed through for the runtime event bus (ADR-051) — not\n // required for extraction logic itself but threaded for parity with\n // extractFromDirectory's project option.\n project: string = DEFAULT_PROJECT,\n): Promise<RunPhasesResult> {\n void project\n const started = Date.now()\n await ensureCompatLoaded()\n // Discovery is cheap and every phase needs the same DiscoveredService list,\n // so we always re-walk. If the user moved a service directory, this is also\n // the path that picks it up.\n const services = await discoverServices(scanPath)\n\n let nodesAdded = 0\n let edgesAdded = 0\n\n if (phases.has('services')) {\n nodesAdded += addServiceNodes(graph, services)\n }\n if (phases.has('aliases')) {\n await addServiceAliases(graph, scanPath, services)\n }\n if (phases.has('databases')) {\n const r = await addDatabasesAndCompat(graph, services, scanPath)\n nodesAdded += r.nodesAdded\n edgesAdded += r.edgesAdded\n }\n if (phases.has('configs')) {\n const r = await addConfigNodes(graph, services, scanPath)\n nodesAdded += r.nodesAdded\n edgesAdded += r.edgesAdded\n }\n if (phases.has('calls')) {\n const r = await addCallEdges(graph, services)\n nodesAdded += r.nodesAdded\n edgesAdded += r.edgesAdded\n }\n if (phases.has('infra')) {\n const r = await addInfra(graph, scanPath, services)\n nodesAdded += r.nodesAdded\n edgesAdded += r.edgesAdded\n }\n const frontiersPromoted = promoteFrontierNodes(graph)\n\n return {\n phases: ALL_PHASES.filter((p) => phases.has(p)),\n nodesAdded,\n edgesAdded,\n frontiersPromoted,\n durationMs: Date.now() - started,\n }\n}\n\nexport interface WatchOptions {\n scanPath: string\n outPath: string\n errorsPath: string\n staleEventsPath: string\n embeddingsCachePath?: string\n // Project name this watch instance owns. Defaults to `default` for the\n // single-project workflow that's been the only one until #83.\n project?: string\n host?: string\n port?: number\n otelPort?: number\n otelGrpc?: boolean\n otelGrpcPort?: number\n debounceMs?: number\n}\n\nexport interface WatchHandle {\n api: FastifyInstance\n stop: () => Promise<void>\n}\n\n// Anymatch-compatible ignore set passed to chokidar (#233). The earlier\n// implementation passed a function alone, which forced chokidar to descend\n// into every subdirectory before testing the path. On macOS with kqueue\n// (chokidar 4 dropped fsevents in favour of kqueue), each subdir under the\n// scan root opens a watch handle; nested `node_modules` blew through the\n// per-process kqueue cap with EMFILE before the function-based ignore ever\n// fired. Globs let chokidar prune at descent time — the dirs are never\n// opened in the first place.\nconst IGNORED_WATCH_GLOBS = [\n '**/node_modules/**',\n '**/.git/**',\n '**/dist/**',\n '**/build/**',\n '**/.turbo/**',\n '**/.next/**',\n '**/neat-out/**',\n // Python venv shapes (issue #344). chokidar opens one watch handle per\n // descended dir; a CPython venv carries 20k+ files and trivially blows\n // through the macOS kqueue cap before extraction even runs.\n '**/.venv/**',\n '**/venv/**',\n '**/__pypackages__/**',\n '**/.tox/**',\n '**/site-packages/**',\n '**/.DS_Store',\n]\n\n// Backstop regex set — covers anything chokidar surfaces post-descent that\n// the globs missed (e.g. a path containing one of these segments at an\n// unexpected depth). Same shape as before; the globs are the load-bearing\n// pruning, this is defence in depth.\nconst IGNORED_WATCH_PATHS = [\n /(?:^|[\\\\/])node_modules[\\\\/]/,\n /(?:^|[\\\\/])\\.git[\\\\/]/,\n /(?:^|[\\\\/])dist[\\\\/]/,\n /(?:^|[\\\\/])build[\\\\/]/,\n /(?:^|[\\\\/])\\.turbo[\\\\/]/,\n /(?:^|[\\\\/])\\.next[\\\\/]/,\n /(?:^|[\\\\/])neat-out[\\\\/]/,\n /(?:^|[\\\\/])\\.venv[\\\\/]/,\n /(?:^|[\\\\/])venv[\\\\/]/,\n /(?:^|[\\\\/])__pypackages__[\\\\/]/,\n /(?:^|[\\\\/])\\.tox[\\\\/]/,\n /(?:^|[\\\\/])site-packages[\\\\/]/,\n /[\\\\/]?\\.DS_Store$/,\n]\n\nfunction shouldIgnore(absPath: string): boolean {\n return IGNORED_WATCH_PATHS.some((re) => re.test(absPath))\n}\n\n// Roughly the number of immediate, non-ignored subdirectories in the scan\n// root above which `neat watch` should fall back to polling on darwin. kqueue\n// opens one handle per watched dir; macOS's per-process file-descriptor cap\n// is typically 256 (soft) / unlimited (hard) but raising the hard cap doesn't\n// help with the kqueue-specific limits. Empirically anything north of ~500\n// non-ignored dirs starts to flirt with EMFILE. Threshold sits comfortably\n// under that.\nconst DARWIN_POLLING_DIR_THRESHOLD = 400\n\n// Fast non-recursive count: walk top-level entries only, descending one\n// level into non-ignored subdirs to capture the medusa-shaped case where\n// `packages/*` itself looks small but each contains a heavy `node_modules`.\n// Returns early once it crosses the threshold so we don't waste time on huge\n// repos.\nfunction countWatchableDirs(scanPath: string, limit: number): number {\n let count = 0\n const visit = (dir: string, depth: number): void => {\n if (count >= limit) return\n let entries: fs.Dirent[]\n try {\n entries = fs.readdirSync(dir, { withFileTypes: true })\n } catch {\n return\n }\n for (const e of entries) {\n if (count >= limit) return\n if (!e.isDirectory()) continue\n if (IGNORED_WATCH_PATHS.some((re) => re.test(path.join(dir, e.name) + path.sep))) continue\n count++\n // One level deeper — enough to surface nested `node_modules` shapes\n // without traversing the whole tree.\n if (depth < 2) visit(path.join(dir, e.name), depth + 1)\n }\n }\n visit(scanPath, 0)\n return count\n}\n\n// Darwin heuristic (#233). Forces chokidar onto polling when the scan root\n// is large enough that kqueue would EMFILE. Override via NEAT_WATCH_POLLING:\n// - \"1\" / \"true\" → force polling regardless of platform/threshold\n// - \"0\" / \"false\" → never poll (matches pre-#233 behaviour)\n// - unset → auto-detect on darwin\nfunction shouldUsePolling(scanPath: string): boolean {\n const env = process.env.NEAT_WATCH_POLLING\n if (env === '1' || env === 'true') return true\n if (env === '0' || env === 'false') return false\n if (process.platform !== 'darwin') return false\n return countWatchableDirs(scanPath, DARWIN_POLLING_DIR_THRESHOLD) >= DARWIN_POLLING_DIR_THRESHOLD\n}\n\nexport async function startWatch(\n graph: NeatGraph,\n opts: WatchOptions,\n): Promise<WatchHandle> {\n const debounceMs = opts.debounceMs ?? 1000\n const projectName = opts.project ?? DEFAULT_PROJECT\n\n await loadGraphFromDisk(graph, opts.outPath)\n\n // Wire graph mutations into the event bus (ADR-051) before extract begins\n // so the initial pass also produces node/edge events. Detached on stop().\n const detachEventBus = attachGraphToEventBus(graph, { project: projectName })\n\n // Load policies + open the violations log once at startup. policy.json\n // lives at the project root per ADR-042 §File location; absent file is\n // a perfectly fine state (loadPolicyFile returns []). Reload-on-change\n // is queued for v0.2.5 — the kickoff doc tracks it.\n const policyFilePath = path.join(opts.scanPath, 'policy.json')\n const policyViolationsPath = path.join(path.dirname(opts.outPath), 'policy-violations.ndjson')\n let policies: Policy[] = []\n try {\n policies = await loadPolicyFile(policyFilePath)\n if (policies.length > 0) {\n console.log(`policies: loaded ${policies.length} from ${policyFilePath}`)\n }\n } catch (err) {\n console.warn(`policies: failed to load ${policyFilePath} — ${(err as Error).message}`)\n }\n const policyLog = new PolicyViolationsLog(policyViolationsPath, projectName)\n\n // Single shared trigger callback wired into post-ingest, post-extract, and\n // post-stale per ADR-043. Failures append to console.warn but don't kill\n // the daemon — a malformed evaluator shouldn't take down ingest.\n const onPolicyTrigger = async (g: NeatGraph): Promise<void> => {\n if (policies.length === 0) return\n try {\n const violations = evaluateAllPolicies(g, policies, { now: () => Date.now() })\n for (const v of violations) await policyLog.append(v)\n } catch (err) {\n console.warn(`policies: evaluation failed — ${(err as Error).message}`)\n }\n }\n\n // The post-extract trigger fires from extractFromDirectory via opts.\n // For the initial extract here we run it inline so violations land on\n // startup before the receiver opens. Subsequent watch-driven re-extract\n // passes go through runExtractPhases which doesn't take the hook directly\n // — we run it after each flush() instead.\n const initial = await runExtractPhases(\n graph,\n opts.scanPath,\n new Set(ALL_PHASES),\n projectName,\n )\n console.log(\n `extract: ${initial.nodesAdded} new nodes, ${initial.edgesAdded} new edges (graph total ${graph.order}/${graph.size})`,\n )\n // extraction-complete for the initial pass (ADR-051). runExtractPhases\n // doesn't emit on its own — the event lives at the watch / orchestrator\n // boundary so the daemon can swap in its own emission shape.\n emitNeatEvent({\n type: 'extraction-complete',\n project: projectName,\n payload: {\n project: projectName,\n fileCount: 0,\n nodesAdded: initial.nodesAdded,\n edgesAdded: initial.edgesAdded,\n },\n })\n await onPolicyTrigger(graph)\n\n const stopPersist = startPersistLoop(graph, opts.outPath)\n const stopStaleness = startStalenessLoop(graph, {\n staleEventsPath: opts.staleEventsPath,\n project: projectName,\n onPolicyTrigger,\n })\n\n const host = opts.host ?? '0.0.0.0'\n const port = opts.port ?? 8080\n const otelPort = opts.otelPort ?? 4318\n\n const cachePath =\n opts.embeddingsCachePath ?? path.join(path.dirname(opts.outPath), 'embeddings.json')\n let searchIndex: SearchIndex | undefined\n try {\n searchIndex = await buildSearchIndex(graph, { cachePath })\n console.log(`semantic_search: ${searchIndex.provider} provider`)\n } catch (err) {\n console.warn(\n `semantic_search: index build failed (${(err as Error).message}); falling back to inline substring`,\n )\n }\n\n const registry = new Projects()\n registry.set(projectName, {\n graph,\n scanPath: opts.scanPath,\n paths: {\n // Paths are derived from the explicit options the watch caller passes\n // — pathsForProject is only used to fill in the embeddings/snapshot\n // fields so the registry shape is complete.\n ...pathsForProject(projectName, path.dirname(opts.outPath)),\n snapshotPath: opts.outPath,\n errorsPath: opts.errorsPath,\n staleEventsPath: opts.staleEventsPath,\n },\n searchIndex,\n })\n\n const api = await buildApi({ projects: registry })\n await api.listen({ port, host })\n console.log(`neat-core listening on http://${host}:${port}`)\n console.log(` scan path: ${opts.scanPath} (watching for changes)`)\n console.log(` snapshot path: ${opts.outPath}`)\n console.log(` errors log: ${opts.errorsPath}`)\n\n // The receiver writes ErrorEvents synchronously before reply (durability).\n // makeSpanHandler runs on the async queue and skips the inline write\n // because the receiver already handled it. Ad-hoc callers that bypass the\n // receiver (CLI tests, fixtures) leave writeErrorEventInline at its default\n // and get the in-handleSpan write. ADR-033 §Error events.\n const onSpan = makeSpanHandler({\n graph,\n errorsPath: opts.errorsPath,\n project: projectName,\n writeErrorEventInline: false,\n onPolicyTrigger,\n })\n const onErrorSpanSync = makeErrorSpanWriter(opts.errorsPath)\n const otelHttp = await buildOtelReceiver({ onSpan, onErrorSpanSync })\n await otelHttp.listen({ port: otelPort, host })\n console.log(`neat-core OTLP receiver on http://${host}:${otelPort}/v1/traces`)\n\n let grpcReceiver: { stop: () => Promise<void> } | null = null\n if (opts.otelGrpc) {\n const grpcPort = opts.otelGrpcPort ?? 4317\n // gRPC handler keeps the inline ErrorEvent write — the gRPC receiver\n // awaits onSpan synchronously (otel-grpc.ts), so the same durability\n // guarantee is met without a separate sync hook. Non-blocking gRPC\n // ingest is out of scope for the v0.2.2 batch.\n const onSpanGrpc = makeSpanHandler({\n graph,\n errorsPath: opts.errorsPath,\n project: projectName,\n onPolicyTrigger,\n })\n const r = await startOtelGrpcReceiver({ onSpan: onSpanGrpc, host, port: grpcPort })\n console.log(`neat-core OTLP/gRPC receiver on ${r.address}`)\n grpcReceiver = r\n }\n\n // Coalesce bursts of changes into a single re-extract. chokidar fires one\n // event per affected path; an editor save can produce 3+ events on the same\n // file in <50ms.\n const pending = new Set<ExtractPhase>()\n const pendingPaths = new Set<string>()\n let timer: NodeJS.Timeout | null = null\n let inflight: Promise<void> | null = null\n\n const flush = async (): Promise<void> => {\n if (pending.size === 0) return\n const phases = new Set(pending)\n const paths = new Set(pendingPaths)\n pending.clear()\n pendingPaths.clear()\n try {\n // Drop EXTRACTED edges keyed to changed paths first, so the producer's\n // idempotent re-extract recreates only the edges that still apply.\n // Without this, edges from deleted code would survive forever\n // (docs/contracts/static-extraction.md §Ghost-edge cleanup).\n let retired = 0\n for (const p of paths) retired += retireEdgesByFile(graph, p)\n const result = await runExtractPhases(graph, opts.scanPath, phases, projectName)\n console.log(\n `[watch] re-extract phases=${result.phases.join(',')} retired=${retired} +${result.nodesAdded}n/+${result.edgesAdded}e in ${result.durationMs}ms`,\n )\n // extraction-complete after every re-extract pass (ADR-051). fileCount\n // is the number of paths that drove the pass — closest signal we have\n // for \"how much source moved\" without per-phase accounting.\n emitNeatEvent({\n type: 'extraction-complete',\n project: projectName,\n payload: {\n project: projectName,\n fileCount: paths.size,\n nodesAdded: result.nodesAdded,\n edgesAdded: result.edgesAdded,\n },\n })\n if (searchIndex) {\n try {\n await searchIndex.refresh(graph)\n } catch (err) {\n console.warn('[watch] semantic_search refresh failed', err)\n }\n }\n // Post-extract policy trigger (ADR-043). The runExtractPhases call\n // doesn't take the hook directly — it runs through promoteFrontierNodes\n // for FRONTIER → OBSERVED upgrades but doesn't load policies itself.\n // Firing the evaluator here keeps the trigger surface symmetric across\n // ingest / extract / stale paths.\n await onPolicyTrigger(graph)\n } catch (err) {\n console.error('[watch] re-extract failed', err)\n }\n }\n\n const schedule = (): void => {\n if (timer) clearTimeout(timer)\n timer = setTimeout(() => {\n timer = null\n // Serialise re-extracts so two flushes can't interleave on the graph.\n inflight = (inflight ?? Promise.resolve()).then(flush)\n }, debounceMs)\n }\n\n const onPath = (absPath: string): void => {\n if (shouldIgnore(absPath)) return\n const rel = path.relative(opts.scanPath, absPath)\n if (!rel || rel.startsWith('..')) return\n pendingPaths.add(rel.split(path.sep).join('/'))\n const phases = classifyChange(rel)\n if (phases.size === 0) {\n // Unknown file kind — fall back to full re-extract rather than silently\n // miss it. Cheaper than the user wondering why their change didn't show.\n for (const p of ALL_PHASES) pending.add(p)\n } else {\n for (const p of phases) pending.add(p)\n }\n schedule()\n }\n\n const usePolling = shouldUsePolling(opts.scanPath)\n if (usePolling) {\n const reason =\n process.env.NEAT_WATCH_POLLING === '1' || process.env.NEAT_WATCH_POLLING === 'true'\n ? 'NEAT_WATCH_POLLING env override'\n : 'darwin heuristic — large scan root, kqueue cap risk'\n console.log(`[${projectName}] watch: usePolling=true (${reason})`)\n }\n const watcher: FSWatcher = chokidar.watch(opts.scanPath, {\n ignoreInitial: true,\n // Glob array prunes at descent time (#233) so chokidar never opens a\n // kqueue handle for `node_modules` and friends. The function backstop\n // catches any path that slipped through and matches the regex set.\n ignored: [...IGNORED_WATCH_GLOBS, (p: string) => shouldIgnore(p)],\n persistent: true,\n usePolling,\n awaitWriteFinish: { stabilityThreshold: 200, pollInterval: 50 },\n })\n watcher.on('add', onPath)\n watcher.on('change', onPath)\n watcher.on('unlink', onPath)\n watcher.on('addDir', onPath)\n watcher.on('unlinkDir', onPath)\n\n let stopped = false\n const stop = async (): Promise<void> => {\n if (stopped) return\n stopped = true\n if (timer) clearTimeout(timer)\n timer = null\n if (inflight) {\n try {\n await inflight\n } catch {\n // surfaced already in flush()\n }\n }\n await watcher.close()\n stopStaleness()\n stopPersist()\n detachEventBus()\n await api.close()\n await otelHttp.close()\n if (grpcReceiver) await grpcReceiver.stop()\n }\n\n return { api, stop }\n}\n","/**\n * `neat deploy` substrate detection + artifact generation (ADR-073 §2).\n *\n * Three substrates, detected in order:\n *\n * 1. Docker + `docker compose` present → emit `docker-compose.neat.yml`.\n * 2. Bare machine with `systemctl` available → emit `neat.service`.\n * 3. Fallback → print a `docker run` snippet to stdout.\n *\n * Every branch generates a fresh `NEAT_AUTH_TOKEN` (32 bytes, base64url),\n * prints it once, and never embeds it in the on-disk artifact — the file\n * names the env-var, the operator stores the value out of band.\n *\n * Every branch also prints the OTel env-vars block the operator pastes into\n * their application services' deploy platform.\n */\n\nimport { promises as fs } from 'node:fs'\nimport path from 'node:path'\nimport { spawn } from 'node:child_process'\nimport { randomBytes } from 'node:crypto'\n\nexport type Substrate = 'docker-compose' | 'systemd' | 'docker-run'\n\nexport interface DetectOptions {\n cwd?: string\n // Detection is shellable-out by injected probes; tests pass these to avoid\n // depending on the local docker / systemctl installation.\n hasDocker?: () => Promise<boolean>\n hasSystemd?: () => Promise<boolean>\n}\n\nexport interface DeployArtifact {\n substrate: Substrate\n // Path written to disk; undefined for the docker-run fallback (stdout-only).\n artifactPath?: string\n // The newly generated bearer token. Printed once by the caller, never\n // re-read from disk.\n token: string\n // The body of the artifact. Always returned so callers (and tests) can\n // inspect what was written without re-reading the file.\n contents: string\n // The shell command the operator runs to bring NEAT up on this substrate.\n startCommand: string\n}\n\nexport function generateToken(): string {\n // 32 bytes → 43-byte base64url (no padding). Plenty of entropy; URL-safe\n // so the operator can paste it into env-var dashboards that escape `=`.\n return randomBytes(32).toString('base64url')\n}\n\nasync function probeBinary(binary: string, arg: string): Promise<boolean> {\n return new Promise((resolve) => {\n const child = spawn(binary, [arg], { stdio: 'ignore' })\n const timer = setTimeout(() => {\n child.kill('SIGKILL')\n resolve(false)\n }, 2000)\n child.once('error', () => {\n clearTimeout(timer)\n resolve(false)\n })\n child.once('exit', (code) => {\n clearTimeout(timer)\n resolve(code === 0)\n })\n })\n}\n\nexport async function detectSubstrate(opts: DetectOptions = {}): Promise<Substrate> {\n const hasDocker = opts.hasDocker ?? (() => probeBinary('docker', 'version'))\n const hasSystemd = opts.hasSystemd ?? (() => probeBinary('systemctl', '--version'))\n if (await hasDocker()) return 'docker-compose'\n if (await hasSystemd()) return 'systemd'\n return 'docker-run'\n}\n\nconst IMAGE = 'ghcr.io/neat-technologies/neat:latest'\n\nexport function emitDockerCompose(cwd: string): string {\n // Compose v3 — declares the three documented ports + a data volume. The\n // operator's deploy platform supplies `NEAT_AUTH_TOKEN`; the file names\n // the var with no default, so a missing env stops the container from\n // coming up rather than running unauthenticated.\n return [\n 'services:',\n ' neat:',\n ` image: ${IMAGE}`,\n ' restart: unless-stopped',\n ' environment:',\n ' NEAT_AUTH_TOKEN: ${NEAT_AUTH_TOKEN:?NEAT_AUTH_TOKEN must be set}',\n ' ports:',\n ' - \"8080:8080\"',\n ' - \"4318:4318\"',\n ' - \"6328:6328\"',\n ' volumes:',\n ` - ${cwd}:/workspace`,\n ' - ./neat-data:/neat-out',\n '',\n ].join('\\n')\n}\n\nexport function emitSystemdUnit(cwd: string): string {\n // Token lives in /etc/neat/neatd.env (NEAT_AUTH_TOKEN=...) so it's readable\n // only by root and the service user. The unit itself stays version-\n // controllable without leaking the secret.\n return [\n '# NEAT_AUTH_TOKEN is read from /etc/neat/neatd.env at startup.',\n '# Put `NEAT_AUTH_TOKEN=<value>` in that file with mode 0640 root:root.',\n '[Unit]',\n 'Description=NEAT daemon',\n 'After=network-online.target',\n 'Wants=network-online.target',\n '',\n '[Service]',\n 'Type=simple',\n 'ExecStart=/usr/local/bin/neatd start --foreground',\n `WorkingDirectory=${cwd}`,\n 'EnvironmentFile=/etc/neat/neatd.env',\n 'Restart=always',\n 'RestartSec=5',\n '',\n '[Install]',\n 'WantedBy=multi-user.target',\n '',\n ].join('\\n')\n}\n\nexport function emitDockerRunSnippet(): string {\n // Single-line `docker run` for substrates we can't detect. Operator pastes\n // their own token in; the variable name keeps the bearer-token-must-be-set\n // shape consistent across all three branches.\n return [\n '#!/usr/bin/env bash',\n 'set -euo pipefail',\n '',\n '# Generate a fresh token once, then store it where your secrets live.',\n ': \"${NEAT_AUTH_TOKEN:?NEAT_AUTH_TOKEN must be set}\"',\n '',\n `docker run -d --name neat \\\\`,\n ' -e NEAT_AUTH_TOKEN=\"$NEAT_AUTH_TOKEN\" \\\\',\n ' -p 8080:8080 -p 4318:4318 -p 6328:6328 \\\\',\n ' -v \"$PWD\":/workspace -v /var/lib/neat:/neat-out \\\\',\n ` ${IMAGE}`,\n '',\n ].join('\\n')\n}\n\nexport interface RenderDeployBlockOptions {\n substrate: Substrate\n // Host the operator's services will reach NEAT at. Defaults to a\n // placeholder so the operator notices and fills it in.\n host?: string\n}\n\n// The OTel env-vars block the operator pastes into their deploy platform.\n// Format matches the orchestrator summary so the two never drift.\nexport function renderOtelEnvBlock(token: string, host: string = '<host>'): string {\n return [\n `OTEL_EXPORTER_OTLP_ENDPOINT=https://${host}:4318`,\n `OTEL_EXPORTER_OTLP_HEADERS=Authorization=Bearer ${token}`,\n 'OTEL_SERVICE_NAME=<service>',\n ].join('\\n')\n}\n\nexport async function runDeploy(opts: DetectOptions = {}): Promise<DeployArtifact> {\n const cwd = opts.cwd ?? process.cwd()\n const substrate = await detectSubstrate(opts)\n const token = generateToken()\n\n switch (substrate) {\n case 'docker-compose': {\n const artifactPath = path.join(cwd, 'docker-compose.neat.yml')\n const contents = emitDockerCompose(cwd)\n await fs.writeFile(artifactPath, contents, 'utf8')\n return {\n substrate,\n artifactPath,\n token,\n contents,\n startCommand: `NEAT_AUTH_TOKEN=${token} docker compose -f ${path.basename(artifactPath)} up -d`,\n }\n }\n case 'systemd': {\n const artifactPath = path.join(cwd, 'neat.service')\n const contents = emitSystemdUnit(cwd)\n await fs.writeFile(artifactPath, contents, 'utf8')\n return {\n substrate,\n artifactPath,\n token,\n contents,\n startCommand: [\n `sudo install -m 0640 -o root -g root <(echo NEAT_AUTH_TOKEN=${token}) /etc/neat/neatd.env`,\n `sudo install -m 0644 neat.service /etc/systemd/system/neat.service`,\n 'sudo systemctl daemon-reload && sudo systemctl enable --now neat',\n ].join(' && '),\n }\n }\n case 'docker-run':\n default: {\n const contents = emitDockerRunSnippet()\n // No on-disk artifact for the fallback — operator copies the snippet.\n return {\n substrate: 'docker-run',\n token,\n contents,\n startCommand: `NEAT_AUTH_TOKEN=${token} bash <(cat <<'EOF'\\n${contents}EOF\\n)`,\n }\n }\n }\n}\n","/**\n * Node / TypeScript SDK installer (ADR-047 + ADR-069).\n *\n * Detects services by the presence of a `package.json` carrying a `name`\n * field — same shape `extract/services.ts` uses to decide what counts as a\n * Node service. The plan adds four OTel-adjacent packages to `dependencies`\n * (api, sdk-node, auto-instrumentations-node, dotenv), writes a generated\n * `otel-init.{js,ts}` adjacent to the resolved entry, and injects the\n * require/import as the first non-shebang line of that entry. Per-package\n * `.env.neat` carries `OTEL_SERVICE_NAME` (scope-preserved) so dashboards\n * joining OBSERVED spans against the EXTRACTED graph use the same key.\n *\n * Lockfiles are never touched (ADR-047 §4). The apply phase writes only to\n * package.json, otel-init.{js,ts}, and .env.neat (ADR-069 §7). After\n * `--apply`, init prints \"run npm install\" so the user owns the lockfile\n * commit.\n *\n * Idempotency (ADR-069 §6): the generated otel-init's presence is the\n * primary signal that a package is instrumented end-to-end — when it\n * exists, the apply phase logs `already instrumented` and skips the file\n * write and the entry-point injection together. Existing `.env.neat` files\n * are preserved (never overwritten).\n */\n\nimport { promises as fs } from 'node:fs'\nimport path from 'node:path'\nimport type {\n ApplyResult,\n DependencyEdit,\n EntrypointEdit,\n EnvEdit,\n GeneratedFile,\n Installer,\n InstallPlan,\n PlanOptions,\n} from './shared.js'\nimport {\n ASTRO_MIDDLEWARE_JS,\n ASTRO_MIDDLEWARE_TS,\n ASTRO_OTEL_INIT_JS,\n ASTRO_OTEL_INIT_TS,\n NEXT_INSTRUMENTATION_HEADER,\n NEXT_INSTRUMENTATION_JS,\n NEXT_INSTRUMENTATION_NODE_JS,\n NEXT_INSTRUMENTATION_NODE_TS,\n NEXT_INSTRUMENTATION_TS,\n NUXT_OTEL_INIT_JS,\n NUXT_OTEL_INIT_TS,\n NUXT_OTEL_PLUGIN_JS,\n NUXT_OTEL_PLUGIN_TS,\n OTEL_INIT_CJS,\n OTEL_INIT_ESM,\n OTEL_INIT_HEADER,\n OTEL_INIT_TS,\n REMIX_OTEL_SERVER_JS,\n REMIX_OTEL_SERVER_TS,\n SVELTEKIT_HOOKS_SERVER_JS,\n SVELTEKIT_HOOKS_SERVER_TS,\n SVELTEKIT_OTEL_INIT_JS,\n SVELTEKIT_OTEL_INIT_TS,\n renderEnvNeat,\n renderFrameworkOtelInit,\n renderNextInstrumentationNode,\n renderNodeOtelInit,\n} from './templates.js'\n\n// ADR-069 §5 — three OTel packages land in `dependencies`. `dotenv` was a\n// fourth from v0.3.6 through v0.4.3; the generated `otel-init` templates\n// no longer load `.env.neat` from disk (issue #369), so it's gone from the\n// dep set.\nconst SDK_PACKAGES = [\n { name: '@opentelemetry/api', version: '^1.9.0' },\n { name: '@opentelemetry/sdk-node', version: '^0.57.0' },\n { name: '@opentelemetry/auto-instrumentations-node', version: '^0.55.0' },\n] as const\n\nconst OTEL_ENV: EnvEdit = {\n // ADR-069 §4 — endpoint moves into the per-package .env.neat (written\n // by the apply phase). The envEdits surface stays for the dry-run\n // patch render: it documents the key/value the user can inspect in the\n // generated .env.neat.\n file: null,\n key: 'OTEL_EXPORTER_OTLP_TRACES_ENDPOINT',\n value: 'http://localhost:4318/projects/<project>/v1/traces',\n}\n\ninterface PackageJsonShape {\n name?: string\n type?: string\n main?: string\n bin?: string | Record<string, string>\n scripts?: Record<string, string>\n dependencies?: Record<string, string>\n devDependencies?: Record<string, string>\n}\n\n// v0.4.4 — `OTEL_SERVICE_NAME` regains its proper semantic role: the\n// ServiceNode id inside the project's graph, not the project name. v0.4.1\n// papered over the missing routing key by writing the project basename here;\n// the project-scoped OTLP URL (issue #367) means the URL carries the routing\n// key and the env var goes back to naming the ServiceNode.\nfunction serviceNodeName(pkg: PackageJsonShape, serviceDir: string): string {\n return pkg.name ?? path.basename(serviceDir)\n}\n\n// The URL routing key. When the orchestrator threads a project through we use\n// it verbatim; ad-hoc / test usage falls back to the package's own name so\n// the generated file is still well-formed.\nfunction projectToken(\n pkg: PackageJsonShape,\n serviceDir: string,\n project: string | undefined,\n): string {\n if (project && project.length > 0) return project\n return pkg.name ?? path.basename(serviceDir)\n}\n\n// Issue #370 — runtime-kind detection. The installer historically treated\n// every JavaScript package as a Node service; Brief's frontend workspace\n// showed that wrong assumption write `instrumentation-node/register` into a\n// Vite browser bundle and an Expo React Native entry, where the Node SDK\n// can't execute. Detection runs after framework dispatch (Next / Remix /\n// SvelteKit / Nuxt / Astro all render server-side, so they classify as\n// `node`); only the framework-less packages reach the bucket here.\ntype RuntimeKind = 'node' | 'browser-bundle' | 'react-native'\n\nasync function readJsonFile(p: string): Promise<unknown> {\n try {\n const raw = await fs.readFile(p, 'utf8')\n return JSON.parse(raw) as unknown\n } catch {\n return null\n }\n}\n\nasync function detectRuntimeKind(\n pkgRoot: string,\n pkg: PackageJsonShape,\n): Promise<RuntimeKind> {\n const deps = allDeps(pkg)\n if ('react-native' in deps || 'expo' in deps) return 'react-native'\n // Expo apps sometimes carry the SDK only as a transitive dep but always\n // ship an `app.json` carrying an `expo` block — that's the canonical Expo\n // signal.\n const appJson = await readJsonFile(path.join(pkgRoot, 'app.json'))\n if (appJson && typeof appJson === 'object' && 'expo' in (appJson as Record<string, unknown>)) {\n return 'react-native'\n }\n if (\n (await exists(path.join(pkgRoot, 'vite.config.js'))) ||\n (await exists(path.join(pkgRoot, 'vite.config.ts'))) ||\n (await exists(path.join(pkgRoot, 'vite.config.mjs'))) ||\n 'vite' in deps\n ) {\n return 'browser-bundle'\n }\n return 'node'\n}\n\n// Issue #368 — `OTel deps in package.json` is no longer the signal for\n// `already-instrumented`. The hook file is. Each `plan<Framework>` reads its\n// canonical hook path off disk via `await exists(...)` before queueing the\n// generated-file write, so deps-present-but-hook-absent correctly buckets\n// the package as `instrumented` (the installer writes the hook), not\n// `already-instrumented`. The next-deps-no-hook fixture in the contract\n// suite locks this against regression.\n\nasync function readPackageJson(serviceDir: string): Promise<PackageJsonShape | null> {\n try {\n const raw = await fs.readFile(path.join(serviceDir, 'package.json'), 'utf8')\n return JSON.parse(raw) as PackageJsonShape\n } catch {\n return null\n }\n}\n\nasync function exists(p: string): Promise<boolean> {\n try {\n await fs.stat(p)\n return true\n } catch {\n return false\n }\n}\n\nasync function detect(serviceDir: string): Promise<boolean> {\n const pkg = await readPackageJson(serviceDir)\n return pkg !== null && typeof pkg.name === 'string'\n}\n\n// ADR-073 §1 — Next.js detection. A package is Next-flavored when it\n// declares `next` as a (dev)dependency AND ships a `next.config.{js,ts,mjs}`\n// at the package root. Both are required: a stray `next` import without the\n// config file isn't a Next app, and a config file without the dep is dead\n// configuration.\nconst NEXT_CONFIG_CANDIDATES = ['next.config.js', 'next.config.ts', 'next.config.mjs']\n\nasync function findNextConfig(serviceDir: string): Promise<string | null> {\n for (const name of NEXT_CONFIG_CANDIDATES) {\n const candidate = path.join(serviceDir, name)\n if (await exists(candidate)) return candidate\n }\n return null\n}\n\nfunction hasNextDependency(pkg: PackageJsonShape): boolean {\n return (\n (pkg.dependencies?.next !== undefined) ||\n (pkg.devDependencies?.next !== undefined)\n )\n}\n\n// Read the merged dep + devDep map once per detection step. Framework checks\n// only care about presence, not version.\nfunction allDeps(pkg: PackageJsonShape): Record<string, string> {\n return { ...(pkg.dependencies ?? {}), ...(pkg.devDependencies ?? {}) }\n}\n\n// ADR-074 §3 — Remix detection. A package is Remix-flavored when it declares\n// `remix` or any `@remix-run/*` package AND ships an entry-server file at one\n// of the canonical paths (`app/entry.server.{ts,tsx,js,jsx}`).\nconst REMIX_ENTRY_CANDIDATES = [\n 'app/entry.server.ts',\n 'app/entry.server.tsx',\n 'app/entry.server.js',\n 'app/entry.server.jsx',\n]\n\nfunction hasRemixDependency(pkg: PackageJsonShape): boolean {\n const deps = allDeps(pkg)\n if ('remix' in deps) return true\n for (const name of Object.keys(deps)) {\n if (name.startsWith('@remix-run/')) return true\n }\n return false\n}\n\nasync function findRemixEntry(serviceDir: string): Promise<string | null> {\n for (const rel of REMIX_ENTRY_CANDIDATES) {\n const candidate = path.join(serviceDir, rel)\n if (await exists(candidate)) return candidate\n }\n return null\n}\n\n// ADR-074 §3 — SvelteKit detection. `@sveltejs/kit` dep, plus either an\n// existing `src/hooks.server.{ts,js}` or a top-level `svelte.config.{js,ts}`\n// (the absent-hooks case where the installer creates the hook file).\nconst SVELTEKIT_HOOKS_CANDIDATES = ['src/hooks.server.ts', 'src/hooks.server.js']\nconst SVELTEKIT_CONFIG_CANDIDATES = ['svelte.config.js', 'svelte.config.ts']\n\nfunction hasSvelteKitDependency(pkg: PackageJsonShape): boolean {\n return '@sveltejs/kit' in allDeps(pkg)\n}\n\nasync function findSvelteKitHooks(serviceDir: string): Promise<string | null> {\n for (const rel of SVELTEKIT_HOOKS_CANDIDATES) {\n const candidate = path.join(serviceDir, rel)\n if (await exists(candidate)) return candidate\n }\n return null\n}\n\nasync function findSvelteKitConfig(serviceDir: string): Promise<string | null> {\n for (const rel of SVELTEKIT_CONFIG_CANDIDATES) {\n const candidate = path.join(serviceDir, rel)\n if (await exists(candidate)) return candidate\n }\n return null\n}\n\n// ADR-074 §3 — Nuxt detection. `nuxt` dep + `nuxt.config.{ts,js,mjs}`.\nconst NUXT_CONFIG_CANDIDATES = ['nuxt.config.ts', 'nuxt.config.js', 'nuxt.config.mjs']\n\nfunction hasNuxtDependency(pkg: PackageJsonShape): boolean {\n return 'nuxt' in allDeps(pkg)\n}\n\nasync function findNuxtConfig(serviceDir: string): Promise<string | null> {\n for (const name of NUXT_CONFIG_CANDIDATES) {\n const candidate = path.join(serviceDir, name)\n if (await exists(candidate)) return candidate\n }\n return null\n}\n\n// ADR-074 §3 — Astro detection. `astro` dep + `astro.config.{mjs,ts,js}`.\nconst ASTRO_CONFIG_CANDIDATES = ['astro.config.mjs', 'astro.config.ts', 'astro.config.js']\n\nfunction hasAstroDependency(pkg: PackageJsonShape): boolean {\n return 'astro' in allDeps(pkg)\n}\n\nasync function findAstroConfig(serviceDir: string): Promise<string | null> {\n for (const name of ASTRO_CONFIG_CANDIDATES) {\n const candidate = path.join(serviceDir, name)\n if (await exists(candidate)) return candidate\n }\n return null\n}\n\n// Parse the leading major version out of a semver range like \"^14.0.3\" or\n// \"~15.0\" or \"15.0.0\". Returns null when the range can't be read (workspace\n// links, git refs, \"*\", etc.).\nexport function parseNextMajor(range: string | undefined): number | null {\n if (!range) return null\n const cleaned = range.trim().replace(/^[\\^~>=<\\s]+/, '')\n const match = cleaned.match(/^(\\d+)/)\n if (!match) return null\n const n = Number(match[1])\n return Number.isFinite(n) ? n : null\n}\n\nasync function isTypeScriptProject(serviceDir: string): Promise<boolean> {\n return exists(path.join(serviceDir, 'tsconfig.json'))\n}\n\n// ADR-069 §2 + ADR-070 — entry resolution: pkg.main → pkg.bin → scripts.start\n// → scripts.dev → src/index.* → src/{server,main,app}.* → root index.*.\n// Returns the absolute path to the resolved entry, or null when the package\n// is lib-only (no resolvable entry).\nconst INDEX_EXTENSIONS = ['.ts', '.tsx', '.js', '.mjs', '.cjs']\nconst INDEX_CANDIDATES = INDEX_EXTENSIONS.map((ext) => `index${ext}`)\nconst SRC_INDEX_CANDIDATES = INDEX_EXTENSIONS.map((ext) => `src/index${ext}`)\nconst SRC_NAMED_CANDIDATES = ['server', 'main', 'app'].flatMap((name) =>\n INDEX_EXTENSIONS.map((ext) => `src/${name}${ext}`),\n)\n\n// ADR-070 — script-entry tokeniser. Launchers and similar wrappers we strip\n// before reading the first file-shaped argument. Anything not in this set is\n// treated as a candidate entry if it looks like a relative file path.\nconst SCRIPT_LAUNCHERS = new Set([\n 'node',\n 'ts-node',\n 'tsx',\n 'ts-node-dev',\n 'nodemon',\n 'npx',\n 'pnpm',\n 'yarn',\n 'npm',\n 'cross-env',\n 'dotenv',\n '--',\n])\n\n// True when the token resembles a path inside the package — contains a `/` or\n// ends in one of the JS/TS extensions we instrument.\nfunction looksLikeEntryPath(token: string): boolean {\n if (token.length === 0) return false\n if (token.startsWith('-')) return false\n if (token.includes('=')) return false // env-var assignments\n if (token.includes('/')) return true\n return /\\.(?:m?[jt]sx?|c[jt]s)$/.test(token)\n}\n\n// Bail when the script chains commands or pipes — those scripts mean an\n// orchestrator runs multiple things and our heuristic can't pick safely.\nfunction scriptHasShellChain(script: string): boolean {\n return /(?:&&|\\|\\||;|\\|(?!\\|))/.test(script)\n}\n\n// Pull the first file-shaped argument out of a script invocation, after\n// stripping recognised launchers and inline env-var assignments. Returns\n// undefined when no candidate surfaces (or when shell chaining bails us out).\nexport function entryFromScript(script: string | undefined): string | undefined {\n if (!script) return undefined\n if (scriptHasShellChain(script)) return undefined\n const tokens = script.split(/\\s+/).filter((t) => t.length > 0)\n for (const token of tokens) {\n const lower = token.toLowerCase()\n if (SCRIPT_LAUNCHERS.has(lower)) continue\n // Strip a leading `./` so the existence check resolves cleanly.\n const cleaned = token.startsWith('./') ? token.slice(2) : token\n if (looksLikeEntryPath(cleaned)) return cleaned\n }\n return undefined\n}\n\nexport async function resolveEntry(\n serviceDir: string,\n pkg: PackageJsonShape,\n): Promise<string | null> {\n // 1) pkg.main — but only when it actually exists on disk (ADR-070).\n if (typeof pkg.main === 'string' && pkg.main.length > 0) {\n const candidate = path.resolve(serviceDir, pkg.main)\n if (await exists(candidate)) return candidate\n // Manifest points main at a missing build output (e.g. dist/index.js\n // pre-build). Fall through to bin/scripts/src heuristics rather than\n // marking lib-only.\n }\n // 2) pkg.bin (string or pkg.name-keyed map).\n if (pkg.bin) {\n let binEntry: string | undefined\n if (typeof pkg.bin === 'string') {\n binEntry = pkg.bin\n } else if (pkg.name && typeof pkg.bin[pkg.name] === 'string') {\n binEntry = pkg.bin[pkg.name]\n } else {\n const first = Object.values(pkg.bin)[0]\n if (typeof first === 'string') binEntry = first\n }\n if (binEntry) {\n const candidate = path.resolve(serviceDir, binEntry)\n if (await exists(candidate)) return candidate\n }\n }\n // 3) scripts.start — ADR-070.\n const startEntry = entryFromScript(pkg.scripts?.start)\n if (startEntry) {\n const candidate = path.resolve(serviceDir, startEntry)\n if (await exists(candidate)) return candidate\n }\n // 4) scripts.dev — ADR-070.\n const devEntry = entryFromScript(pkg.scripts?.dev)\n if (devEntry) {\n const candidate = path.resolve(serviceDir, devEntry)\n if (await exists(candidate)) return candidate\n }\n // 5) src/index.* — ADR-070.\n for (const rel of SRC_INDEX_CANDIDATES) {\n const candidate = path.join(serviceDir, rel)\n if (await exists(candidate)) return candidate\n }\n // 6) src/server.*, src/main.*, src/app.* — ADR-070.\n for (const rel of SRC_NAMED_CANDIDATES) {\n const candidate = path.join(serviceDir, rel)\n if (await exists(candidate)) return candidate\n }\n // 7) root index.* — original ADR-069 §3 fallback.\n for (const name of INDEX_CANDIDATES) {\n const candidate = path.join(serviceDir, name)\n if (await exists(candidate)) return candidate\n }\n return null\n}\n\n// ADR-069 §1, §3 — dispatch by entry extension + pkg.type.\ntype EntryFlavor = 'cjs' | 'esm' | 'ts'\n\nexport function dispatchEntry(entryFile: string, pkg: PackageJsonShape): EntryFlavor {\n const ext = path.extname(entryFile).toLowerCase()\n if (ext === '.ts' || ext === '.tsx') return 'ts'\n if (ext === '.mjs') return 'esm'\n if (ext === '.cjs') return 'cjs'\n // .js — disambiguate on pkg.type. \"module\" → ESM, anything else → CJS.\n return pkg.type === 'module' ? 'esm' : 'cjs'\n}\n\n// Generated-file basename per flavor.\nfunction otelInitFilename(flavor: EntryFlavor): string {\n if (flavor === 'ts') return 'otel-init.ts'\n if (flavor === 'esm') return 'otel-init.mjs'\n return 'otel-init.cjs'\n}\n\nfunction otelInitContents(flavor: EntryFlavor): string {\n if (flavor === 'ts') return OTEL_INIT_TS\n if (flavor === 'esm') return OTEL_INIT_ESM\n return OTEL_INIT_CJS\n}\n\n// Build the injection line per flavor. The relative path is computed against\n// the entry's directory so the injection works regardless of the entry's\n// depth inside the package.\nexport function injectionLine(\n flavor: EntryFlavor,\n entryFile: string,\n otelInitFile: string,\n): string {\n let rel = path.relative(path.dirname(entryFile), otelInitFile)\n if (!rel.startsWith('.')) rel = `./${rel}`\n // Normalize to forward slashes for cross-platform module specifiers.\n rel = rel.split(path.sep).join('/')\n if (flavor === 'cjs') return `require('${rel}')`\n if (flavor === 'esm') return `import '${rel}'`\n // TS: drop the .ts extension so the resolver doesn't choke on it under\n // either tsc-output or runtime-loader pipelines.\n const tsRel = rel.replace(/\\.ts$/, '')\n return `import '${tsRel}'`\n}\n\n// Detect whether a given line already matches an injection of our otel-init.\n// Used for the entry-point idempotency check (ADR-069 §6).\nfunction lineIsOtelInjection(line: string): boolean {\n const trimmed = line.trim()\n if (trimmed.length === 0) return false\n // Match require('./otel-init…') and import './otel-init…' shapes.\n return /(?:require\\(|import\\s+)['\"]\\.\\/otel-init[^'\"]*['\"]/.test(trimmed)\n}\n\n// `create-next-app --src-dir` puts source under `src/` and Next then resolves\n// the instrumentation hook from `src/instrumentation.ts`. Routing the\n// generated files to root in that case means the hook never loads. We detect\n// src-layout by the presence of `src/app/` or `src/pages/` AND the absence of\n// the same at the package root — a project with both is treated as flat, the\n// safer default for monorepos that vendor a `src/` subpackage.\nasync function detectsSrcLayout(serviceDir: string): Promise<boolean> {\n const [hasSrcApp, hasSrcPages, hasRootApp, hasRootPages] = await Promise.all([\n exists(path.join(serviceDir, 'src', 'app')),\n exists(path.join(serviceDir, 'src', 'pages')),\n exists(path.join(serviceDir, 'app')),\n exists(path.join(serviceDir, 'pages')),\n ])\n return (hasSrcApp || hasSrcPages) && !hasRootApp && !hasRootPages\n}\n\n// ADR-073 §1 — Next.js apply path. Emits `instrumentation.{ts,js}` and\n// `instrumentation.node.{ts,js}` at the package root (or under `src/` for\n// `--src-dir` layouts), plus `.env.neat` co-located with them. Skips\n// entry-point injection entirely — Next loads the instrumentation file\n// through its own runtime hook. Queues a next.config edit only when the\n// declared major is < 15 (the flag is on-by-default from Next 15 on).\nasync function planNext(\n serviceDir: string,\n pkg: PackageJsonShape,\n manifestPath: string,\n nextConfigPath: string,\n project: string | undefined,\n): Promise<InstallPlan> {\n const useTs = await isTypeScriptProject(serviceDir)\n const srcLayout = await detectsSrcLayout(serviceDir)\n // Co-locate the generated files with where Next looks for the hook. When\n // src-layout is detected the framework resolves `src/instrumentation.{ts,js}`\n // and we route the .env.neat alongside so an operator reading the codebase\n // finds the wiring in one place. The flat layout keeps the existing root\n // placement.\n const baseDir = srcLayout ? path.join(serviceDir, 'src') : serviceDir\n const instrumentationFile = path.join(baseDir, useTs ? 'instrumentation.ts' : 'instrumentation.js')\n const instrumentationNodeFile = path.join(\n baseDir,\n useTs ? 'instrumentation.node.ts' : 'instrumentation.node.js',\n )\n const envNeatFile = path.join(baseDir, '.env.neat')\n\n // Dependency edits — `dotenv` is gone repo-wide from v0.4.4 (issue #369),\n // so SDK_PACKAGES has the three OTel packages the apply phase adds and the\n // Next branch shares the same loop as every other framework.\n const existingDeps = { ...(pkg.dependencies ?? {}), ...(pkg.devDependencies ?? {}) }\n const dependencyEdits: DependencyEdit[] = []\n for (const sdk of SDK_PACKAGES) {\n if (sdk.name in existingDeps) continue\n dependencyEdits.push({\n file: manifestPath,\n kind: 'add',\n name: sdk.name,\n version: sdk.version,\n })\n }\n\n // Generated files — instrumentation pair + .env.neat. Existing files are\n // preserved (skipIfExists honours user customisations and keeps the apply\n // phase idempotent per ADR-069 §6). The instrumentation.node template\n // carries `__SERVICE_NAME__` (the ServiceNode id) and `__PROJECT__` (the\n // registered project basename — the URL routing key) placeholders we\n // substitute here so the bundler-survivable `process.env.X ||=` lines land\n // with both values verbatim.\n const svcName = serviceNodeName(pkg, serviceDir)\n const projectName = projectToken(pkg, serviceDir, project)\n const generatedFiles: GeneratedFile[] = []\n if (!(await exists(instrumentationFile))) {\n generatedFiles.push({\n file: instrumentationFile,\n contents: useTs ? NEXT_INSTRUMENTATION_TS : NEXT_INSTRUMENTATION_JS,\n skipIfExists: true,\n })\n }\n if (!(await exists(instrumentationNodeFile))) {\n generatedFiles.push({\n file: instrumentationNodeFile,\n contents: renderNextInstrumentationNode(\n useTs ? NEXT_INSTRUMENTATION_NODE_TS : NEXT_INSTRUMENTATION_NODE_JS,\n svcName,\n projectName,\n ),\n skipIfExists: true,\n })\n }\n if (!(await exists(envNeatFile))) {\n generatedFiles.push({\n file: envNeatFile,\n contents: renderEnvNeat(svcName, projectName),\n skipIfExists: true,\n })\n }\n\n // ADR-073 §1 — `experimental.instrumentationHook: true` is required for\n // Next 13 / 14 and a no-op on Next 15+. Plan the edit only when the\n // declared major is < 15 and the flag isn't already present.\n let nextConfigEdit: InstallPlan['nextConfigEdit']\n const nextRange = pkg.dependencies?.next ?? pkg.devDependencies?.next\n const nextMajor = parseNextMajor(nextRange)\n if (nextMajor !== null && nextMajor < 15) {\n try {\n const raw = await fs.readFile(nextConfigPath, 'utf8')\n if (!raw.includes('instrumentationHook')) {\n nextConfigEdit = {\n file: nextConfigPath,\n reason: `enable experimental.instrumentationHook (Next ${nextMajor} requires the opt-in flag)`,\n }\n }\n } catch {\n // Config disappeared between detect and plan. Skip the edit.\n }\n }\n\n const empty =\n dependencyEdits.length === 0 &&\n generatedFiles.length === 0 &&\n nextConfigEdit === undefined\n\n if (empty) {\n return {\n language: 'javascript',\n serviceDir,\n dependencyEdits: [],\n entrypointEdits: [],\n envEdits: [],\n generatedFiles: [],\n framework: 'next',\n }\n }\n\n return {\n language: 'javascript',\n serviceDir,\n dependencyEdits,\n entrypointEdits: [],\n envEdits: [OTEL_ENV],\n generatedFiles,\n framework: 'next',\n ...(nextConfigEdit ? { nextConfigEdit } : {}),\n }\n}\n\n// ── Meta-framework planners (ADR-074 §3). ───────────────────────────────\n//\n// Each planner mirrors planNext's shape: build dep edits via the same\n// SDK_PACKAGES + existing-deps filter, queue generated files for the\n// framework-canonical hook surface, record `framework: '<name>'`, never\n// inject into pkg.main. Idempotency rides on `skipIfExists` for generated\n// files and on a re-read header-grep for the inject-into-existing case.\n\nfunction buildDependencyEdits(\n pkg: PackageJsonShape,\n manifestPath: string,\n): DependencyEdit[] {\n const existingDeps = allDeps(pkg)\n const edits: DependencyEdit[] = []\n for (const sdk of SDK_PACKAGES) {\n if (sdk.name in existingDeps) continue\n edits.push({\n file: manifestPath,\n kind: 'add',\n name: sdk.name,\n version: sdk.version,\n })\n }\n return edits\n}\n\nasync function queueEnvNeat(\n serviceDir: string,\n pkg: PackageJsonShape,\n project: string | undefined,\n generatedFiles: GeneratedFile[],\n): Promise<void> {\n const envNeatFile = path.join(serviceDir, '.env.neat')\n if (!(await exists(envNeatFile))) {\n generatedFiles.push({\n file: envNeatFile,\n contents: renderEnvNeat(\n serviceNodeName(pkg, serviceDir),\n projectToken(pkg, serviceDir, project),\n ),\n skipIfExists: true,\n })\n }\n}\n\nfunction renderFrameworkOtelInitForPkg(\n template: string,\n pkg: PackageJsonShape,\n serviceDir: string,\n project: string | undefined,\n): string {\n return renderFrameworkOtelInit(\n template,\n serviceNodeName(pkg, serviceDir),\n projectToken(pkg, serviceDir, project),\n )\n}\n\nfunction fileImportsOtelHook(raw: string, specifiers: readonly string[]): boolean {\n const lines = raw.split(/\\r?\\n/)\n for (const line of lines) {\n const trimmed = line.trim()\n for (const spec of specifiers) {\n const escaped = spec.replace(/\\./g, '\\\\.')\n const pattern = new RegExp(\n `(?:import\\\\s+['\"]${escaped}['\"]|require\\\\(['\"]${escaped}['\"]\\\\))`,\n )\n if (pattern.test(trimmed)) return true\n }\n }\n return false\n}\n\nasync function planRemix(\n serviceDir: string,\n pkg: PackageJsonShape,\n manifestPath: string,\n entryFile: string,\n project: string | undefined,\n): Promise<InstallPlan> {\n const useTs = await isTypeScriptProject(serviceDir)\n const otelServerFile = path.join(\n serviceDir,\n useTs ? 'app/otel.server.ts' : 'app/otel.server.js',\n )\n\n const dependencyEdits = buildDependencyEdits(pkg, manifestPath)\n const generatedFiles: GeneratedFile[] = []\n\n if (!(await exists(otelServerFile))) {\n generatedFiles.push({\n file: otelServerFile,\n contents: renderFrameworkOtelInitForPkg(\n useTs ? REMIX_OTEL_SERVER_TS : REMIX_OTEL_SERVER_JS,\n pkg,\n serviceDir,\n project,\n ),\n skipIfExists: true,\n })\n }\n await queueEnvNeat(serviceDir, pkg, project, generatedFiles)\n\n const entrypointEdits: EntrypointEdit[] = []\n try {\n const raw = await fs.readFile(entryFile, 'utf8')\n if (!fileImportsOtelHook(raw, ['./otel.server'])) {\n const lines = raw.split(/\\r?\\n/)\n const firstReal = lines[0]?.startsWith('#!') ? lines[1] ?? '' : lines[0] ?? ''\n entrypointEdits.push({\n file: entryFile,\n before: firstReal,\n after: \"import './otel.server'\",\n })\n }\n } catch {\n // Entry file disappeared between detect and plan; fall through.\n }\n\n const empty =\n dependencyEdits.length === 0 &&\n generatedFiles.length === 0 &&\n entrypointEdits.length === 0\n\n if (empty) {\n return {\n language: 'javascript',\n serviceDir,\n dependencyEdits: [],\n entrypointEdits: [],\n envEdits: [],\n generatedFiles: [],\n framework: 'remix',\n }\n }\n\n return {\n language: 'javascript',\n serviceDir,\n dependencyEdits,\n entrypointEdits,\n envEdits: [OTEL_ENV],\n generatedFiles,\n framework: 'remix',\n }\n}\n\nasync function planSvelteKit(\n serviceDir: string,\n pkg: PackageJsonShape,\n manifestPath: string,\n hooksFile: string | null,\n project: string | undefined,\n): Promise<InstallPlan> {\n const useTs = await isTypeScriptProject(serviceDir)\n const otelInitFile = path.join(\n serviceDir,\n useTs ? 'src/otel-init.ts' : 'src/otel-init.js',\n )\n const resolvedHooksFile =\n hooksFile ??\n path.join(serviceDir, useTs ? 'src/hooks.server.ts' : 'src/hooks.server.js')\n\n const dependencyEdits = buildDependencyEdits(pkg, manifestPath)\n const generatedFiles: GeneratedFile[] = []\n const entrypointEdits: EntrypointEdit[] = []\n\n if (!(await exists(otelInitFile))) {\n generatedFiles.push({\n file: otelInitFile,\n contents: renderFrameworkOtelInitForPkg(\n useTs ? SVELTEKIT_OTEL_INIT_TS : SVELTEKIT_OTEL_INIT_JS,\n pkg,\n serviceDir,\n project,\n ),\n skipIfExists: true,\n })\n }\n await queueEnvNeat(serviceDir, pkg, project, generatedFiles)\n\n if (hooksFile === null) {\n generatedFiles.push({\n file: resolvedHooksFile,\n contents: useTs ? SVELTEKIT_HOOKS_SERVER_TS : SVELTEKIT_HOOKS_SERVER_JS,\n skipIfExists: true,\n })\n } else {\n try {\n const raw = await fs.readFile(hooksFile, 'utf8')\n if (!fileImportsOtelHook(raw, ['./otel-init'])) {\n const lines = raw.split(/\\r?\\n/)\n const firstReal = lines[0]?.startsWith('#!') ? lines[1] ?? '' : lines[0] ?? ''\n entrypointEdits.push({\n file: hooksFile,\n before: firstReal,\n after: \"import './otel-init'\",\n })\n }\n } catch {\n // Disappeared between detect and plan; fall through.\n }\n }\n\n const empty =\n dependencyEdits.length === 0 &&\n generatedFiles.length === 0 &&\n entrypointEdits.length === 0\n\n if (empty) {\n return {\n language: 'javascript',\n serviceDir,\n dependencyEdits: [],\n entrypointEdits: [],\n envEdits: [],\n generatedFiles: [],\n framework: 'sveltekit',\n }\n }\n\n return {\n language: 'javascript',\n serviceDir,\n dependencyEdits,\n entrypointEdits,\n envEdits: [OTEL_ENV],\n generatedFiles,\n framework: 'sveltekit',\n }\n}\n\nasync function planNuxt(\n serviceDir: string,\n pkg: PackageJsonShape,\n manifestPath: string,\n project: string | undefined,\n): Promise<InstallPlan> {\n const useTs = await isTypeScriptProject(serviceDir)\n const otelPluginFile = path.join(\n serviceDir,\n useTs ? 'server/plugins/otel.ts' : 'server/plugins/otel.js',\n )\n const otelInitFile = path.join(\n serviceDir,\n useTs ? 'server/plugins/otel-init.ts' : 'server/plugins/otel-init.js',\n )\n\n const dependencyEdits = buildDependencyEdits(pkg, manifestPath)\n const generatedFiles: GeneratedFile[] = []\n\n if (!(await exists(otelInitFile))) {\n generatedFiles.push({\n file: otelInitFile,\n contents: renderFrameworkOtelInitForPkg(\n useTs ? NUXT_OTEL_INIT_TS : NUXT_OTEL_INIT_JS,\n pkg,\n serviceDir,\n project,\n ),\n skipIfExists: true,\n })\n }\n if (!(await exists(otelPluginFile))) {\n generatedFiles.push({\n file: otelPluginFile,\n contents: useTs ? NUXT_OTEL_PLUGIN_TS : NUXT_OTEL_PLUGIN_JS,\n skipIfExists: true,\n })\n }\n await queueEnvNeat(serviceDir, pkg, project, generatedFiles)\n\n const empty = dependencyEdits.length === 0 && generatedFiles.length === 0\n\n if (empty) {\n return {\n language: 'javascript',\n serviceDir,\n dependencyEdits: [],\n entrypointEdits: [],\n envEdits: [],\n generatedFiles: [],\n framework: 'nuxt',\n }\n }\n\n return {\n language: 'javascript',\n serviceDir,\n dependencyEdits,\n entrypointEdits: [],\n envEdits: [OTEL_ENV],\n generatedFiles,\n framework: 'nuxt',\n }\n}\n\nconst ASTRO_MIDDLEWARE_CANDIDATES = ['src/middleware.ts', 'src/middleware.js']\n\nasync function findAstroMiddleware(serviceDir: string): Promise<string | null> {\n for (const rel of ASTRO_MIDDLEWARE_CANDIDATES) {\n const candidate = path.join(serviceDir, rel)\n if (await exists(candidate)) return candidate\n }\n return null\n}\n\nasync function planAstro(\n serviceDir: string,\n pkg: PackageJsonShape,\n manifestPath: string,\n project: string | undefined,\n): Promise<InstallPlan> {\n const useTs = await isTypeScriptProject(serviceDir)\n const otelInitFile = path.join(\n serviceDir,\n useTs ? 'src/otel-init.ts' : 'src/otel-init.js',\n )\n const existingMiddleware = await findAstroMiddleware(serviceDir)\n const middlewareFile =\n existingMiddleware ??\n path.join(serviceDir, useTs ? 'src/middleware.ts' : 'src/middleware.js')\n\n const dependencyEdits = buildDependencyEdits(pkg, manifestPath)\n const generatedFiles: GeneratedFile[] = []\n const entrypointEdits: EntrypointEdit[] = []\n\n if (!(await exists(otelInitFile))) {\n generatedFiles.push({\n file: otelInitFile,\n contents: renderFrameworkOtelInitForPkg(\n useTs ? ASTRO_OTEL_INIT_TS : ASTRO_OTEL_INIT_JS,\n pkg,\n serviceDir,\n project,\n ),\n skipIfExists: true,\n })\n }\n await queueEnvNeat(serviceDir, pkg, project, generatedFiles)\n\n if (existingMiddleware === null) {\n generatedFiles.push({\n file: middlewareFile,\n contents: useTs ? ASTRO_MIDDLEWARE_TS : ASTRO_MIDDLEWARE_JS,\n skipIfExists: true,\n })\n } else {\n try {\n const raw = await fs.readFile(existingMiddleware, 'utf8')\n if (!fileImportsOtelHook(raw, ['./otel-init'])) {\n const lines = raw.split(/\\r?\\n/)\n const firstReal = lines[0]?.startsWith('#!') ? lines[1] ?? '' : lines[0] ?? ''\n entrypointEdits.push({\n file: existingMiddleware,\n before: firstReal,\n after: \"import './otel-init'\",\n })\n }\n } catch {\n // Disappeared between detect and plan; fall through.\n }\n }\n\n const empty =\n dependencyEdits.length === 0 &&\n generatedFiles.length === 0 &&\n entrypointEdits.length === 0\n\n if (empty) {\n return {\n language: 'javascript',\n serviceDir,\n dependencyEdits: [],\n entrypointEdits: [],\n envEdits: [],\n generatedFiles: [],\n framework: 'astro',\n }\n }\n\n return {\n language: 'javascript',\n serviceDir,\n dependencyEdits,\n entrypointEdits,\n envEdits: [OTEL_ENV],\n generatedFiles,\n framework: 'astro',\n }\n}\n\nasync function plan(serviceDir: string, opts?: PlanOptions): Promise<InstallPlan> {\n const pkg = await readPackageJson(serviceDir)\n const manifestPath = path.join(serviceDir, 'package.json')\n const project = opts?.project\n const empty: InstallPlan = {\n language: 'javascript',\n serviceDir,\n dependencyEdits: [],\n entrypointEdits: [],\n envEdits: [],\n generatedFiles: [],\n }\n if (!pkg) return empty\n\n // ADR-073 §1 + ADR-074 §3 — framework dispatch runs before entry\n // resolution. When a meta-framework owns the boot path, `pkg.main` isn't\n // load-bearing and the require/import injection would be ignored. Each\n // framework-flavored plan emits the framework's canonical hook surface\n // instead. Detection precedence is Next → Remix → SvelteKit → Nuxt →\n // Astro → vanilla Node; the chain bails on the first match.\n if (hasNextDependency(pkg)) {\n const nextConfig = await findNextConfig(serviceDir)\n if (nextConfig) {\n return planNext(serviceDir, pkg, manifestPath, nextConfig, project)\n }\n }\n if (hasRemixDependency(pkg)) {\n const remixEntry = await findRemixEntry(serviceDir)\n if (remixEntry) {\n return planRemix(serviceDir, pkg, manifestPath, remixEntry, project)\n }\n }\n if (hasSvelteKitDependency(pkg)) {\n const hooks = await findSvelteKitHooks(serviceDir)\n const config = await findSvelteKitConfig(serviceDir)\n if (hooks || config) {\n return planSvelteKit(serviceDir, pkg, manifestPath, hooks, project)\n }\n }\n if (hasNuxtDependency(pkg)) {\n const nuxtConfig = await findNuxtConfig(serviceDir)\n if (nuxtConfig) {\n return planNuxt(serviceDir, pkg, manifestPath, project)\n }\n }\n if (hasAstroDependency(pkg)) {\n const astroConfig = await findAstroConfig(serviceDir)\n if (astroConfig) {\n return planAstro(serviceDir, pkg, manifestPath, project)\n }\n }\n\n // Issue #370 — runtime-kind detection sits between the framework dispatch\n // chain and vanilla Node template emission. Browser bundles (Vite) and\n // React Native / Expo packages bucket here so the apply phase skips every\n // write and surfaces the package in the summary instead of injecting a\n // Node SDK hook into code that can't run it.\n const runtimeKind = await detectRuntimeKind(serviceDir, pkg)\n if (runtimeKind !== 'node') {\n return { ...empty, runtimeKind }\n }\n\n // ADR-069 §2 — entry resolution before anything else. No entry → lib-only.\n const entryFile = await resolveEntry(serviceDir, pkg)\n if (!entryFile) {\n return { ...empty, libOnly: true }\n }\n const flavor = dispatchEntry(entryFile, pkg)\n const otelInitFile = path.join(path.dirname(entryFile), otelInitFilename(flavor))\n const envNeatFile = path.join(serviceDir, '.env.neat')\n\n // ── Dependency edits (four-deps invariant; ADR-069 §5). ────────────────\n const existingDeps = { ...(pkg.dependencies ?? {}), ...(pkg.devDependencies ?? {}) }\n const dependencyEdits: DependencyEdit[] = []\n for (const sdk of SDK_PACKAGES) {\n if (sdk.name in existingDeps) continue\n dependencyEdits.push({\n file: manifestPath,\n kind: 'add',\n name: sdk.name,\n version: sdk.version,\n })\n }\n\n // ── Entry-point injection edit (ADR-069 §3). ───────────────────────────\n const entrypointEdits: EntrypointEdit[] = []\n try {\n const raw = await fs.readFile(entryFile, 'utf8')\n const lines = raw.split(/\\r?\\n/)\n // Preserve a shebang on line 1 and check line 2 (the first non-shebang\n // line) for an existing injection.\n const firstReal = lines[0]?.startsWith('#!') ? lines[1] ?? '' : lines[0] ?? ''\n if (!lineIsOtelInjection(firstReal)) {\n const inject = injectionLine(flavor, entryFile, otelInitFile)\n // Use the existing first-real line as the `before` marker so the apply\n // phase can splice the injection cleanly even if the file shifts.\n entrypointEdits.push({\n file: entryFile,\n before: firstReal,\n after: inject,\n })\n }\n } catch {\n // Entry file disappeared between resolve and plan (rare). Treat as\n // lib-only.\n return { ...empty, libOnly: true }\n }\n\n // ── Generated files (ADR-069 §1, §4). ──────────────────────────────────\n // v0.4.4 — the otel-init template carries `__SERVICE_NAME__` (the\n // ServiceNode id) and `__PROJECT__` (the URL routing key) placeholders we\n // substitute here. The .env.neat shape lands with the same pair so an\n // operator can grep for both fields in one place.\n const svcName = serviceNodeName(pkg, serviceDir)\n const projectName = projectToken(pkg, serviceDir, project)\n const generatedFiles: GeneratedFile[] = []\n if (!(await exists(otelInitFile))) {\n generatedFiles.push({\n file: otelInitFile,\n contents: renderNodeOtelInit(otelInitContents(flavor), svcName, projectName),\n skipIfExists: true,\n })\n }\n if (!(await exists(envNeatFile))) {\n generatedFiles.push({\n file: envNeatFile,\n contents: renderEnvNeat(svcName, projectName),\n skipIfExists: true,\n })\n }\n\n // ── Idempotency check (ADR-069 §6). ────────────────────────────────────\n // If the package is already instrumented end-to-end — deps present, entry\n // already injected, generated files already there — return an empty plan.\n if (\n dependencyEdits.length === 0 &&\n entrypointEdits.length === 0 &&\n generatedFiles.length === 0\n ) {\n return empty\n }\n\n return {\n language: 'javascript',\n serviceDir,\n dependencyEdits,\n entrypointEdits,\n envEdits: [OTEL_ENV],\n generatedFiles,\n entryFile,\n libOnly: false,\n }\n}\n\n// ADR-069 §7 + ADR-073 §1 + ADR-074 §3 — allowed write paths. Anything\n// outside this set inside an installer's apply phase is a contract violation.\nfunction isAllowedWritePath(serviceDir: string, target: string): boolean {\n const rel = path.relative(serviceDir, target)\n if (rel.startsWith('..')) return false\n const base = path.basename(target)\n if (base === 'package.json') return true\n if (base === '.env.neat') return true\n if (/^otel-init\\.(?:js|cjs|mjs|ts)$/.test(base)) return true\n // ADR-073 §1 — Next framework files at the package root, or under src/\n // when create-next-app's --src-dir layout is in use. The instrumentation\n // hook resolves from `src/` in that layout; routing files there is the\n // load-bearing fix for the src-dir shape.\n const relPosix = rel.split(path.sep).join('/')\n if (/^instrumentation(?:\\.node)?\\.(?:js|cjs|mjs|ts)$/.test(base)) {\n if (relPosix === base) return true\n if (relPosix === `src/${base}`) return true\n return false\n }\n if (/^next\\.config\\.(?:js|mjs|ts)$/.test(base)) return true\n // ADR-074 §3 — meta-framework hook surfaces.\n if (relPosix === 'app/otel.server.ts' || relPosix === 'app/otel.server.js') return true\n if (/^app\\/entry\\.server\\.(?:tsx?|jsx?)$/.test(relPosix)) return true\n if (relPosix === 'src/otel-init.ts' || relPosix === 'src/otel-init.js') return true\n if (relPosix === 'src/hooks.server.ts' || relPosix === 'src/hooks.server.js') return true\n if (relPosix === 'server/plugins/otel.ts' || relPosix === 'server/plugins/otel.js') return true\n if (relPosix === 'server/plugins/otel-init.ts' || relPosix === 'server/plugins/otel-init.js') return true\n if (relPosix === 'src/middleware.ts' || relPosix === 'src/middleware.js') return true\n return false\n}\n\nasync function writeAtomic(file: string, contents: string): Promise<void> {\n // Meta-framework branches write to convention-driven subdirs that the user\n // may not have scaffolded yet (`server/plugins/`, `src/`, `app/`). Ensure\n // the parent directory exists before the atomic write; existing parents\n // are a no-op under `recursive: true`.\n await fs.mkdir(path.dirname(file), { recursive: true })\n const tmp = `${file}.${process.pid}.${Date.now()}.tmp`\n await fs.writeFile(tmp, contents, 'utf8')\n await fs.rename(tmp, file)\n}\n\nasync function apply(installPlan: InstallPlan): Promise<ApplyResult> {\n const { serviceDir } = installPlan\n if (installPlan.libOnly) {\n return {\n serviceDir,\n outcome: 'lib-only',\n reason: 'no resolvable entry point',\n writtenFiles: [],\n }\n }\n\n // Issue #370 — non-Node runtimes write nothing. The CLI surfaces the\n // outcome in the summary so the operator can see which packages were\n // skipped and why.\n if (installPlan.runtimeKind === 'browser-bundle') {\n return {\n serviceDir,\n outcome: 'browser-bundle',\n reason: 'browser bundle; Node OTel SDK cannot run here',\n writtenFiles: [],\n }\n }\n if (installPlan.runtimeKind === 'react-native') {\n return {\n serviceDir,\n outcome: 'react-native',\n reason: 'React Native / Expo target; Node OTel SDK cannot run here',\n writtenFiles: [],\n }\n }\n\n // Already-instrumented check: an empty plan means there's nothing to do.\n if (\n installPlan.dependencyEdits.length === 0 &&\n installPlan.entrypointEdits.length === 0 &&\n (installPlan.generatedFiles?.length ?? 0) === 0 &&\n installPlan.nextConfigEdit === undefined\n ) {\n return {\n serviceDir,\n outcome: 'already-instrumented',\n writtenFiles: [],\n }\n }\n\n // Validate every target we plan to touch against the allowed-path set.\n // Bail out before any write if a violation slipped through.\n const allTargets = new Set<string>()\n for (const d of installPlan.dependencyEdits) allTargets.add(d.file)\n for (const e of installPlan.entrypointEdits) allTargets.add(e.file)\n for (const g of installPlan.generatedFiles ?? []) allTargets.add(g.file)\n if (installPlan.nextConfigEdit) allTargets.add(installPlan.nextConfigEdit.file)\n for (const target of allTargets) {\n // Entry-point edits land in user source files, not the allowed set —\n // they're explicitly carved out below.\n const isEntryEdit = installPlan.entrypointEdits.some((e) => e.file === target)\n if (isEntryEdit) continue\n if (!isAllowedWritePath(serviceDir, target)) {\n throw new Error(\n `javascript installer: refusing to write outside the allowed path set (ADR-069 §7): ${target}`,\n )\n }\n }\n\n // Snapshot every file we may touch so a partial failure can roll back the\n // batch (ADR-047 §7). Newly-generated files have no prior contents — they\n // get tracked separately so rollback unlinks them instead of restoring.\n const originals = new Map<string, string>()\n const createdFiles: string[] = []\n for (const target of allTargets) {\n if (await exists(target)) {\n try {\n originals.set(target, await fs.readFile(target, 'utf8'))\n } catch {\n // Best-effort. The mutation loop below will throw if this matters.\n }\n }\n }\n\n const writtenFiles: string[] = []\n try {\n // ── 1. Manifest edits (package.json) ─────────────────────────────────\n const manifestTargets = installPlan.dependencyEdits\n .reduce<Set<string>>((acc, e) => {\n acc.add(e.file)\n return acc\n }, new Set())\n for (const file of manifestTargets) {\n const raw = originals.get(file)\n if (raw === undefined) {\n throw new Error(`javascript installer: cannot read ${file} during apply`)\n }\n const pkg = JSON.parse(raw) as PackageJsonShape\n pkg.dependencies = pkg.dependencies ?? {}\n for (const dep of installPlan.dependencyEdits) {\n if (dep.file !== file) continue\n if (dep.kind === 'add') {\n if (!(dep.name in (pkg.dependencies ?? {}))) {\n pkg.dependencies[dep.name] = dep.version\n }\n // No version bump on existing entries (ADR-069 §6).\n } else {\n delete pkg.dependencies[dep.name]\n }\n }\n const newRaw = JSON.stringify(pkg, null, 2) + '\\n'\n await writeAtomic(file, newRaw)\n writtenFiles.push(file)\n }\n\n // ── 2. Generated files (otel-init, .env.neat) ────────────────────────\n for (const gen of installPlan.generatedFiles ?? []) {\n if (gen.skipIfExists && (await exists(gen.file))) {\n // Skip silently; the contract treats this as part of the\n // already-instrumented path.\n continue\n }\n await writeAtomic(gen.file, gen.contents)\n if (!originals.has(gen.file)) createdFiles.push(gen.file)\n writtenFiles.push(gen.file)\n }\n\n // ── 3. Entry-point injection (require/import on first non-shebang line)\n for (const ep of installPlan.entrypointEdits) {\n const raw = originals.get(ep.file)\n if (raw === undefined) {\n throw new Error(`javascript installer: cannot read entry ${ep.file} during apply`)\n }\n const lines = raw.split(/\\r?\\n/)\n const hasShebang = lines[0]?.startsWith('#!') ?? false\n const insertAt = hasShebang ? 1 : 0\n // Idempotency: if the first non-shebang line already matches our\n // injection pattern, skip — never double-inject.\n const firstReal = lines[insertAt] ?? ''\n if (lineIsOtelInjection(firstReal)) continue\n lines.splice(insertAt, 0, ep.after)\n const newRaw = lines.join('\\n')\n await writeAtomic(ep.file, newRaw)\n writtenFiles.push(ep.file)\n }\n\n // ── 4. Next.js config flag (ADR-073 §1) — only present on the Next\n // path when the declared major is < 15 and the flag isn't already\n // mentioned in the file. Best-effort regex insertion into the first\n // config object literal; bails silently when the shape isn't\n // recognisable so we never corrupt a user-customised config.\n if (installPlan.nextConfigEdit) {\n const target = installPlan.nextConfigEdit.file\n const raw = originals.get(target)\n if (raw !== undefined && !raw.includes('instrumentationHook')) {\n const updated = injectInstrumentationHook(raw)\n if (updated !== null) {\n await writeAtomic(target, updated)\n writtenFiles.push(target)\n }\n }\n }\n } catch (err) {\n await rollback(installPlan, originals, createdFiles)\n throw err\n }\n\n return {\n serviceDir,\n outcome: 'instrumented',\n writtenFiles,\n }\n}\n\nasync function rollback(\n installPlan: InstallPlan,\n originals: Map<string, string>,\n createdFiles: string[],\n): Promise<void> {\n const restored: string[] = []\n const removed: string[] = []\n for (const [file, raw] of originals.entries()) {\n try {\n await fs.writeFile(file, raw, 'utf8')\n restored.push(file)\n } catch {\n // Best-effort: keep going so we restore as much as we can.\n }\n }\n for (const file of createdFiles) {\n try {\n await fs.unlink(file)\n removed.push(file)\n } catch {\n // Best-effort.\n }\n }\n const lines = [\n '# neat-rollback.patch',\n '',\n `# Generated after a partial apply failure in the ${installPlan.language} installer.`,\n '# Files listed below were restored to their pre-apply contents.',\n '',\n ...restored.map((f) => `restored: ${f}`),\n ...removed.map((f) => `removed: ${f}`),\n '',\n ]\n const rollbackPath = path.join(installPlan.serviceDir, 'neat-rollback.patch')\n await fs.writeFile(rollbackPath, lines.join('\\n'), 'utf8')\n}\n\n// ADR-073 §1 — best-effort injection of `experimental.instrumentationHook:\n// true` into a next.config.{js,ts,mjs}. Returns the rewritten contents on\n// success, or null when the config shape isn't recognisable (in which case\n// the apply phase leaves the file alone — partial Next coverage is fine,\n// silent corruption of a user's config is not).\n//\n// Recognised shapes:\n// - `module.exports = { ... }` (CJS)\n// - `module.exports = { ... } satisfies NextConfig` (TS-via-CJS)\n// - `export default { ... }` (ESM / TS)\n// - `const nextConfig = { ... }; module.exports = nextConfig` (named CJS)\n// - `const nextConfig: NextConfig = { ... }; export default nextConfig` (TS)\nexport function injectInstrumentationHook(raw: string): string | null {\n if (raw.includes('instrumentationHook')) return raw\n\n // Strategy: find the first config object literal whose contents we can\n // edit, then either merge into an existing `experimental: { ... }` block\n // or insert a fresh `experimental: { instrumentationHook: true }` entry.\n //\n // We look for one of four anchors near a top-level `{` and splice from\n // there. The regexes capture the `{` so we can splice right after it.\n const anchors: Array<{ pattern: RegExp; label: string }> = [\n { pattern: /(module\\.exports\\s*=\\s*\\{)/, label: 'cjs-default' },\n { pattern: /(export\\s+default\\s*\\{)/, label: 'esm-default' },\n { pattern: /(?:const|let|var)\\s+\\w+(?:\\s*:\\s*[^=]+)?\\s*=\\s*(\\{)/, label: 'named-config' },\n ]\n\n for (const { pattern } of anchors) {\n const match = pattern.exec(raw)\n if (!match) continue\n const insertAfter = match.index + match[0].length\n const before = raw.slice(0, insertAfter)\n const after = raw.slice(insertAfter)\n // Insert a leading newline so the injection sits on its own line and\n // doesn't fight any existing trailing-comma style. Two-space indent\n // covers most code-styled configs.\n const injection = '\\n experimental: { instrumentationHook: true },'\n return `${before}${injection}${after}`\n }\n\n return null\n}\n\nexport const javascriptInstaller: Installer = {\n name: 'javascript',\n detect,\n plan,\n apply,\n}\n\n// Re-exports used by the contract test surface.\nexport { NEXT_INSTRUMENTATION_HEADER, OTEL_INIT_HEADER }\n","/**\n * Generated-file templates for the Node SDK installer (ADR-069 §1).\n *\n * Three flavors so the inserted file matches the host package's module\n * system: CJS for `require`-based packages, ESM for `import`-based, TS for\n * TypeScript entries. Env vars are inlined as `process.env.X ||=` defaults\n * rather than loaded from `.env.neat` at runtime — `__dirname` /\n * `import.meta.url` resolve unpredictably once a bundler rewrites the\n * generated file (Brief-smoke evidence, issue #369), so we let the OTel SDK\n * read its config from the same `process.env` either way. Platform env\n * (Vercel / Railway / Fly / etc.) stays authoritative at deploy time;\n * `||=` keeps the local default for laptop dev only.\n */\n\n// Header comment that ships at the top of every generated otel-init. Stable\n// across flavors so a grep for the header line finds every generated file in\n// a target codebase. Used by the idempotency check too (ADR-069 §6).\nexport const OTEL_INIT_HEADER = '// Generated by `neat init --apply` (ADR-069). OpenTelemetry auto-instrumentation hook.'\n\n// __SERVICE_NAME__ → the ServiceNode id (the package's `pkg.name`, or the\n// directory basename for nameless packages); __PROJECT__ → the registered\n// project basename. Both are substituted at apply time via\n// renderNodeOtelInit().\nexport const OTEL_INIT_CJS = `${OTEL_INIT_HEADER}\nprocess.env.OTEL_SERVICE_NAME ||= '__SERVICE_NAME__'\nprocess.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ||= 'http://localhost:4318/projects/__PROJECT__/v1/traces'\n\nrequire('@opentelemetry/auto-instrumentations-node/register')\n`\n\nexport const OTEL_INIT_ESM = `${OTEL_INIT_HEADER}\nprocess.env.OTEL_SERVICE_NAME ||= '__SERVICE_NAME__'\nprocess.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ||= 'http://localhost:4318/projects/__PROJECT__/v1/traces'\n\nawait import('@opentelemetry/auto-instrumentations-node/register')\n`\n\nexport const OTEL_INIT_TS = `${OTEL_INIT_HEADER}\nprocess.env.OTEL_SERVICE_NAME ||= '__SERVICE_NAME__'\nprocess.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ||= 'http://localhost:4318/projects/__PROJECT__/v1/traces'\n\nawait import('@opentelemetry/auto-instrumentations-node/register')\n`\n\n// Substitute __SERVICE_NAME__ and __PROJECT__ at apply time. Falls back to\n// the package's own name when the orchestrator hasn't threaded a project\n// through (ad-hoc / test usage); the same fallback the .env.neat renderer\n// uses, kept aligned so dev-time fixtures don't have to fabricate a registry.\nexport function renderNodeOtelInit(\n template: string,\n serviceName: string,\n projectName: string,\n): string {\n return template\n .replace(/__SERVICE_NAME__/g, serviceName)\n .replace(/__PROJECT__/g, projectName)\n}\n\n// .env.neat shape (ADR-069 §4, amended v0.4.1 — refs #339, v0.4.4 — refs\n// #367 + #369). Two keys: OTEL_SERVICE_NAME (the ServiceNode id — the\n// package's own name, scope-preserved, so spans land on per-service nodes\n// inside the project's graph) and OTEL_EXPORTER_OTLP_TRACES_ENDPOINT (the\n// project-scoped URL the daemon mounts at /projects/<project>/v1/traces).\n// Both env vars are advisory only — the generated `otel-init` inlines them\n// via `process.env.X ||=` so bundlers can't lose them; the file is kept so\n// operators can grep for service.name → project mapping in one place.\nexport function renderEnvNeat(serviceName: string, projectName: string): string {\n return [\n '# Generated by `neat init --apply` (ADR-069).',\n `OTEL_SERVICE_NAME=${serviceName}`,\n `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://localhost:4318/projects/${projectName}/v1/traces`,\n '',\n ].join('\\n')\n}\n\n// ── Next.js framework-aware templates (ADR-073 §1, ADR-069 §3). ─────────\n//\n// Next.js owns its own boot — `pkg.main` is unused, and the auto-instrumentation\n// register hook can't run before user code. Next 13+ ships an `instrumentation`\n// file at the project root with an async `register()` export the framework\n// invokes during server start (Node runtime only). For Edge / browser runtimes\n// the file is ignored.\n//\n// Two-file shape: `instrumentation.{ts,js}` keeps the runtime gate so the\n// Node SDK doesn't load on the Edge runtime; `instrumentation.node.{ts,js}`\n// carries the SDK init itself. Both files sit at the project root.\n\nexport const NEXT_INSTRUMENTATION_HEADER =\n '// Generated by `neat init --apply` (ADR-073). Next.js instrumentation hook.'\n\nexport const NEXT_INSTRUMENTATION_TS = `${NEXT_INSTRUMENTATION_HEADER}\nexport async function register() {\n if (process.env.NEXT_RUNTIME === 'nodejs') {\n await import('./instrumentation.node')\n }\n}\n`\n\nexport const NEXT_INSTRUMENTATION_JS = `${NEXT_INSTRUMENTATION_HEADER}\nexport async function register() {\n if (process.env.NEXT_RUNTIME === 'nodejs') {\n await import('./instrumentation.node')\n }\n}\n`\n\n// Env vars are inlined as process.env defaults so they survive Turbopack /\n// Webpack bundling — `import.meta.url` resolves to a path under .next/dev/\n// server/chunks/ once Next compiles this file, which would miss .env.neat.\n// `process.env.X ||=` keeps platform env (Vercel / Railway / Fly / etc.)\n// authoritative at deploy time while the local default carries the routing\n// key the daemon needs to map spans back to this project. The endpoint uses\n// the project-scoped URL form so the daemon never has to guess which project\n// owns the span (issue #367); the OTel SDK reads the env vars from\n// process.env directly, so no file-system lookup is required at runtime.\nexport const NEXT_INSTRUMENTATION_NODE_TS = `${NEXT_INSTRUMENTATION_HEADER}\nprocess.env.OTEL_SERVICE_NAME ||= '__SERVICE_NAME__'\nprocess.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ||= 'http://localhost:4318/projects/__PROJECT__/v1/traces'\n\nimport { NodeSDK } from '@opentelemetry/sdk-node'\nimport { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node'\n\nnew NodeSDK({ instrumentations: [getNodeAutoInstrumentations()] }).start()\n`\n\nexport const NEXT_INSTRUMENTATION_NODE_JS = `${NEXT_INSTRUMENTATION_HEADER}\nprocess.env.OTEL_SERVICE_NAME ||= '__SERVICE_NAME__'\nprocess.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ||= 'http://localhost:4318/projects/__PROJECT__/v1/traces'\n\nconst { NodeSDK } = require('@opentelemetry/sdk-node')\nconst { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node')\n\nnew NodeSDK({ instrumentations: [getNodeAutoInstrumentations()] }).start()\n`\n\n// Substitute the placeholders at apply time so the generated file carries the\n// ServiceNode id (`__SERVICE_NAME__`) and the registered project name\n// (`__PROJECT__`) verbatim. The two roles diverged in v0.4.4: the service name\n// names the ServiceNode inside one project's graph, the project basename is\n// the URL routing key.\nexport function renderNextInstrumentationNode(\n template: string,\n serviceName: string,\n projectName: string,\n): string {\n return template\n .replace(/__SERVICE_NAME__/g, serviceName)\n .replace(/__PROJECT__/g, projectName)\n}\n\n// ── Meta-framework templates (ADR-074 §3). ──────────────────────────────\n//\n// Remix, SvelteKit, Nuxt, and Astro each own their boot path. The installer\n// emits one OTel-init module that loads `.env.neat` and starts the Node SDK,\n// then either creates or injects an import into the framework's canonical\n// hook file. Templates mirror the Next.js pair in shape — one generated init\n// module, one optional framework-hook stub for the absent-file case.\n\nexport const FRAMEWORK_OTEL_INIT_HEADER =\n '// Generated by `neat init --apply` (ADR-074). OpenTelemetry SDK hook.'\n\n// Same inline-defaults pattern as the plain-Node + Next templates: env vars\n// arrive on `process.env` via the apply-time substitution below so bundler\n// path mangling (issue #369) can't lose them. `__SERVICE_NAME__` /\n// `__PROJECT__` are substituted via renderFrameworkOtelInit().\nconst FRAMEWORK_OTEL_INIT_TS_BODY = `${FRAMEWORK_OTEL_INIT_HEADER}\nprocess.env.OTEL_SERVICE_NAME ||= '__SERVICE_NAME__'\nprocess.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ||= 'http://localhost:4318/projects/__PROJECT__/v1/traces'\n\nimport { NodeSDK } from '@opentelemetry/sdk-node'\nimport { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node'\n\nconst sdk = new NodeSDK({\n serviceName: process.env.OTEL_SERVICE_NAME,\n instrumentations: [getNodeAutoInstrumentations()],\n})\nsdk.start()\n`\n\nconst FRAMEWORK_OTEL_INIT_JS_BODY = `${FRAMEWORK_OTEL_INIT_HEADER}\nprocess.env.OTEL_SERVICE_NAME ||= '__SERVICE_NAME__'\nprocess.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ||= 'http://localhost:4318/projects/__PROJECT__/v1/traces'\n\nconst { NodeSDK } = require('@opentelemetry/sdk-node')\nconst { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node')\n\nconst sdk = new NodeSDK({\n serviceName: process.env.OTEL_SERVICE_NAME,\n instrumentations: [getNodeAutoInstrumentations()],\n})\nsdk.start()\n`\n\nexport function renderFrameworkOtelInit(\n template: string,\n serviceName: string,\n projectName: string,\n): string {\n return template\n .replace(/__SERVICE_NAME__/g, serviceName)\n .replace(/__PROJECT__/g, projectName)\n}\n\n// Remix — `app/otel.server.{ts,js}` carries the SDK bootstrap. The framework\n// loads `entry.server.*` at server-process start, and a top-of-module import\n// of `./otel.server` runs the bootstrap before any request handler imports.\nexport const REMIX_OTEL_SERVER_TS = FRAMEWORK_OTEL_INIT_TS_BODY\nexport const REMIX_OTEL_SERVER_JS = FRAMEWORK_OTEL_INIT_JS_BODY\n\n// SvelteKit — `src/otel-init.{ts,js}` carries the SDK bootstrap; the\n// framework's `src/hooks.server.{ts,js}` imports it. When hooks.server is\n// absent, the installer writes the stub below alongside the import.\nexport const SVELTEKIT_OTEL_INIT_TS = FRAMEWORK_OTEL_INIT_TS_BODY\nexport const SVELTEKIT_OTEL_INIT_JS = FRAMEWORK_OTEL_INIT_JS_BODY\n\nexport const SVELTEKIT_HOOKS_SERVER_TS = `${FRAMEWORK_OTEL_INIT_HEADER}\nimport './otel-init'\n\nimport type { Handle } from '@sveltejs/kit'\n\nexport const handle: Handle = async ({ event, resolve }) => {\n return resolve(event)\n}\n`\n\nexport const SVELTEKIT_HOOKS_SERVER_JS = `${FRAMEWORK_OTEL_INIT_HEADER}\nimport './otel-init'\n\n/** @type {import('@sveltejs/kit').Handle} */\nexport const handle = async ({ event, resolve }) => {\n return resolve(event)\n}\n`\n\n// Nuxt — `server/plugins/otel.{ts,js}` is the convention-loaded plugin file;\n// it imports the sibling `otel-init.{ts,js}` which carries the SDK bootstrap.\nexport const NUXT_OTEL_INIT_TS = FRAMEWORK_OTEL_INIT_TS_BODY\nexport const NUXT_OTEL_INIT_JS = FRAMEWORK_OTEL_INIT_JS_BODY\n\nexport const NUXT_OTEL_PLUGIN_TS = `${FRAMEWORK_OTEL_INIT_HEADER}\nimport './otel-init'\n\nexport default defineNitroPlugin(() => {\n // OTel SDK is initialised at module-load via the side-effect import above.\n})\n`\n\nexport const NUXT_OTEL_PLUGIN_JS = `${FRAMEWORK_OTEL_INIT_HEADER}\nrequire('./otel-init')\n\nmodule.exports = defineNitroPlugin(() => {\n // OTel SDK is initialised at module-load via the side-effect import above.\n})\n`\n\n// Astro — `src/middleware.{ts,js}` runs once at module-load (and then per\n// request via onRequest). The top-of-module import of `./otel-init` boots\n// the SDK before the first request lands.\nexport const ASTRO_OTEL_INIT_TS = FRAMEWORK_OTEL_INIT_TS_BODY\nexport const ASTRO_OTEL_INIT_JS = FRAMEWORK_OTEL_INIT_JS_BODY\n\nexport const ASTRO_MIDDLEWARE_TS = `${FRAMEWORK_OTEL_INIT_HEADER}\nimport './otel-init'\n\nimport { defineMiddleware } from 'astro:middleware'\n\nexport const onRequest = defineMiddleware(async (context, next) => {\n return next()\n})\n`\n\nexport const ASTRO_MIDDLEWARE_JS = `${FRAMEWORK_OTEL_INIT_HEADER}\nimport './otel-init'\n\nimport { defineMiddleware } from 'astro:middleware'\n\nexport const onRequest = defineMiddleware(async (context, next) => {\n return next()\n})\n`\n","/**\n * Python SDK installer (ADR-047).\n *\n * `detect` matches on the canonical Python project markers — requirements.txt,\n * pyproject.toml, setup.py. `plan` produces dependency edits against the\n * primary manifest and entrypoint edits against a Procfile when one exists.\n *\n * MVP scope:\n * - requirements.txt is the full-fidelity manifest (read / append).\n * - pyproject.toml dependencies live inside a TOML `dependencies = [...]`\n * block; we line-insert into that block when found, otherwise hold off\n * on rewriting until a successor ADR addresses TOML editing properly.\n * - Procfile lines starting with `python` get prefixed with\n * `opentelemetry-instrument`.\n *\n * Lockfiles (poetry.lock, Pipfile.lock) are never touched. After `--apply`,\n * init's summary tells the user to run `pip install -r requirements.txt`\n * (or `poetry lock && poetry install`) so they own the lockfile commit.\n */\n\nimport { promises as fs } from 'node:fs'\nimport path from 'node:path'\nimport type {\n ApplyResult,\n DependencyEdit,\n EntrypointEdit,\n EnvEdit,\n Installer,\n InstallPlan,\n} from './shared.js'\n\nconst SDK_PACKAGES = [\n { name: 'opentelemetry-distro', version: '>=0.49b0' },\n { name: 'opentelemetry-exporter-otlp', version: '>=1.28.0' },\n] as const\n\nconst OTEL_ENV: EnvEdit = {\n file: null,\n key: 'OTEL_EXPORTER_OTLP_ENDPOINT',\n value: 'http://localhost:4318',\n}\n\nasync function exists(p: string): Promise<boolean> {\n try {\n await fs.stat(p)\n return true\n } catch {\n return false\n }\n}\n\nasync function detect(serviceDir: string): Promise<boolean> {\n const markers = ['requirements.txt', 'pyproject.toml', 'setup.py']\n for (const m of markers) {\n if (await exists(path.join(serviceDir, m))) return true\n }\n return false\n}\n\n// Strip a requirements.txt line down to its lower-cased package name.\n// `flask==3.0.0` → `flask`, `Flask>=2 ; python_version>\"3.6\"` → `flask`.\nfunction reqPackageName(line: string): string {\n const stripped = line.split('#')[0]?.trim() ?? ''\n const head = stripped.split(/[\\s;]/)[0] ?? ''\n return head.replace(/[<>=!~].*$/, '').toLowerCase()\n}\n\nasync function planRequirementsTxtEdits(\n serviceDir: string,\n): Promise<{ manifest: string; missing: typeof SDK_PACKAGES[number][] } | null> {\n const file = path.join(serviceDir, 'requirements.txt')\n if (!(await exists(file))) return null\n const raw = await fs.readFile(file, 'utf8')\n const presentNames = new Set(\n raw\n .split(/\\r?\\n/)\n .map(reqPackageName)\n .filter((n) => n.length > 0),\n )\n const missing = SDK_PACKAGES.filter((p) => !presentNames.has(p.name.toLowerCase()))\n return { manifest: file, missing: [...missing] }\n}\n\nasync function planProcfileEdits(serviceDir: string): Promise<EntrypointEdit[]> {\n const procfile = path.join(serviceDir, 'Procfile')\n if (!(await exists(procfile))) return []\n const raw = await fs.readFile(procfile, 'utf8')\n const edits: EntrypointEdit[] = []\n for (const line of raw.split(/\\r?\\n/)) {\n if (line.length === 0) continue\n // Procfile lines look like `<process>: <cmd>`. Prefix the cmd when it\n // starts with python and isn't already wrapped.\n const m = line.match(/^([a-zA-Z0-9_-]+):\\s*(.+)$/)\n if (!m) continue\n const cmd = m[2]!\n if (!/^python\\b/.test(cmd)) continue\n if (cmd.startsWith('opentelemetry-instrument ')) continue\n const after = `${m[1]}: opentelemetry-instrument ${cmd}`\n edits.push({ file: procfile, before: line, after })\n }\n return edits\n}\n\nasync function plan(serviceDir: string): Promise<InstallPlan> {\n const empty: InstallPlan = {\n language: 'python',\n serviceDir,\n dependencyEdits: [],\n entrypointEdits: [],\n envEdits: [],\n }\n\n const dependencyEdits: DependencyEdit[] = []\n const reqs = await planRequirementsTxtEdits(serviceDir)\n if (reqs) {\n for (const sdk of reqs.missing) {\n dependencyEdits.push({\n file: reqs.manifest,\n kind: 'add',\n name: sdk.name,\n version: sdk.version,\n })\n }\n }\n // pyproject.toml / setup.py without requirements.txt: deferred to a\n // successor ADR. The patch will note it; apply is a no-op for those\n // manifests in the MVP.\n\n const entrypointEdits = await planProcfileEdits(serviceDir)\n\n if (dependencyEdits.length === 0 && entrypointEdits.length === 0) {\n return empty\n }\n return {\n language: 'python',\n serviceDir,\n dependencyEdits,\n entrypointEdits,\n envEdits: [OTEL_ENV],\n }\n}\n\nasync function applyRequirementsTxt(\n manifest: string,\n edits: DependencyEdit[],\n original: string,\n): Promise<void> {\n // Append missing packages on their own lines. Preserve a trailing newline.\n const newlines = edits\n .filter((e) => e.kind === 'add')\n .map((e) => `${e.name}${e.version}`)\n const trailing = original.endsWith('\\n') ? '' : '\\n'\n const next = `${original}${trailing}${newlines.join('\\n')}\\n`\n const tmp = `${manifest}.${process.pid}.${Date.now()}.tmp`\n await fs.writeFile(tmp, next, 'utf8')\n await fs.rename(tmp, manifest)\n}\n\nasync function applyProcfile(\n procfile: string,\n edits: EntrypointEdit[],\n original: string,\n): Promise<void> {\n let next = original\n for (const e of edits) {\n if (!next.includes(e.before)) continue\n next = next.replace(e.before, e.after)\n }\n const tmp = `${procfile}.${process.pid}.${Date.now()}.tmp`\n await fs.writeFile(tmp, next, 'utf8')\n await fs.rename(tmp, procfile)\n}\n\nasync function apply(installPlan: InstallPlan): Promise<ApplyResult> {\n const { serviceDir } = installPlan\n const touched = new Set<string>()\n for (const e of installPlan.dependencyEdits) touched.add(e.file)\n for (const e of installPlan.entrypointEdits) touched.add(e.file)\n if (touched.size === 0) {\n return { serviceDir, outcome: 'already-instrumented', writtenFiles: [] }\n }\n\n const originals = new Map<string, string>()\n for (const file of touched) {\n try {\n originals.set(file, await fs.readFile(file, 'utf8'))\n } catch {\n // Mutation will fail loudly below; rollback covers what did land.\n }\n }\n\n const writtenFiles: string[] = []\n try {\n for (const file of touched) {\n const raw = originals.get(file)\n if (raw === undefined) {\n throw new Error(`python installer: cannot read ${file} during apply`)\n }\n const base = path.basename(file)\n if (base === 'requirements.txt') {\n const edits = installPlan.dependencyEdits.filter((e) => e.file === file)\n if (edits.length > 0) {\n await applyRequirementsTxt(file, edits, raw)\n writtenFiles.push(file)\n }\n } else if (base === 'Procfile') {\n const edits = installPlan.entrypointEdits.filter((e) => e.file === file)\n if (edits.length > 0) {\n await applyProcfile(file, edits, raw)\n writtenFiles.push(file)\n }\n }\n // pyproject.toml / setup.py: MVP no-op as planned above.\n }\n } catch (err) {\n await rollback(installPlan, originals)\n throw err\n }\n\n return { serviceDir, outcome: 'instrumented', writtenFiles }\n}\n\nasync function rollback(\n installPlan: InstallPlan,\n originals: Map<string, string>,\n): Promise<void> {\n const restored: string[] = []\n for (const [file, raw] of originals.entries()) {\n try {\n await fs.writeFile(file, raw, 'utf8')\n restored.push(file)\n } catch {\n // Best-effort.\n }\n }\n const lines = [\n '# neat-rollback.patch',\n '',\n `# Generated after a partial apply failure in the ${installPlan.language} installer.`,\n '# Files listed below were restored to their pre-apply contents.',\n '',\n ...restored.map((f) => `restored: ${f}`),\n '',\n ]\n const rollbackPath = path.join(installPlan.serviceDir, 'neat-rollback.patch')\n await fs.writeFile(rollbackPath, lines.join('\\n'), 'utf8')\n}\n\nexport const pythonInstaller: Installer = {\n name: 'python',\n detect,\n plan,\n apply,\n}\n","/**\n * Shared types for SDK installer modules (ADR-047).\n *\n * Each language has its own installer at `installers/<language>.ts` exporting\n * a `detect / plan / apply` triple. Plans are pure data — no fs side effects\n * during planning — so `init --dry-run` can render a patch without ever\n * touching the project. `apply` runs the codemod in place.\n *\n * Step 2 (this PR) ships the interface and an empty registry. Step 3 (Node\n * installer) and step 4 (Python installer) populate it.\n */\n\n// Field names match ADR-047's documented patch shape exactly: `file`, `kind`,\n// `name`, `version`. Patches will be reviewed by humans and matched in tests\n// by name; renaming for clarity would have cost more than it bought.\n\nexport interface DependencyEdit {\n file: string\n kind: 'add' | 'remove'\n name: string\n version: string\n}\n\nexport interface EntrypointEdit {\n file: string\n before: string\n after: string\n}\n\nexport interface EnvEdit {\n // `null` denotes a recommendation only — the user will set the env var in\n // their orchestration layer, NEAT does not write a `.env` file.\n file: string | null\n key: string\n value: string\n}\n\n// Files the installer generates from scratch (ADR-069 §1). The generated\n// `otel-init.{js,ts}` for the Node installer rides here, along with the\n// per-package `.env.neat` (ADR-069 §4). Treated as additive writes — the\n// apply phase skips any file already present (ADR-069 §6).\nexport interface GeneratedFile {\n file: string\n contents: string\n // When true, write only if the file does not already exist. The apply\n // phase logs an `already instrumented` / `already present` notice instead\n // of overwriting (ADR-069 §6).\n skipIfExists?: boolean\n}\n\nexport interface InstallPlan {\n // Free-form language tag matching the service node's language: `'javascript'`,\n // `'python'`, …\n language: string\n // Service directory the plan targets. Absolute path.\n serviceDir: string\n dependencyEdits: DependencyEdit[]\n entrypointEdits: EntrypointEdit[]\n envEdits: EnvEdit[]\n // ADR-069 §1, §4 — generated files (otel-init, .env.neat). Optional so\n // installers that don't generate files (the Python installer at MVP) can\n // omit it.\n generatedFiles?: GeneratedFile[]\n // ADR-069 §2 — flagged when entry-point resolution found nothing.\n // The apply phase records this in the summary and skips all file writes\n // for the package.\n libOnly?: boolean\n // ADR-069 §2 — resolved entry-point path (absolute). Present when the\n // installer is going to inject the require/import. Absent for libOnly\n // packages and for the Python installer.\n entryFile?: string\n // ADR-073 §1 + ADR-074 §3 — when a framework owns its own boot, the\n // installer skips `pkg.main` injection and emits framework-native\n // instrumentation files instead. Five values today: Next.js from v0.3.8,\n // then Remix / SvelteKit / Nuxt / Astro from v0.3.9.\n framework?: 'next' | 'remix' | 'sveltekit' | 'nuxt' | 'astro'\n // v0.4.4 / issue #370 — when a JavaScript package isn't a Node service\n // (browser bundle, React Native), the installer records the runtime here\n // and writes nothing. Absent → vanilla Node default (the existing apply\n // path). Browser-side OTel support (`@opentelemetry/sdk-trace-web`) lands\n // in a future release.\n runtimeKind?: 'browser-bundle' | 'react-native'\n // ADR-073 §1 — Next.js' `next.config.{js,ts,mjs}` may need the\n // `experimental.instrumentationHook: true` flag set when the major\n // version is < 15. The apply phase mutates the file in place when this\n // field is set. Absent → no config mutation planned.\n nextConfigEdit?: {\n file: string\n // Reason this edit is queued — surfaces in the dry-run patch and the\n // apply summary so the operator knows why their next.config moved.\n reason: string\n }\n}\n\n// ADR-069 §9 — apply outcome per service. The CLI surfaces these counts\n// at the end of `neat init --apply`. v0.4.4 / issue #370 — two new buckets\n// for non-Node JavaScript runtimes: `browser-bundle` (Vite, esbuild-shipped\n// SPAs) and `react-native` (Expo / RN bare). The Node SDK can't run in\n// either; both buckets skip every write and surface the package in the\n// summary so the operator knows the frontend wasn't instrumented.\nexport type ApplyOutcome =\n | 'instrumented'\n | 'already-instrumented'\n | 'lib-only'\n | 'failed'\n | 'browser-bundle'\n | 'react-native'\n\nexport interface ApplyResult {\n serviceDir: string\n outcome: ApplyOutcome\n // Free-form reason string for `lib-only` / `failed` outcomes. Surfaced\n // in the CLI summary so the user knows why a package was skipped.\n reason?: string\n // Absolute paths the apply phase actually wrote to. Used by the contract\n // test that asserts the allowed-path-set restriction (ADR-069 §7).\n writtenFiles: string[]\n}\n\n// Plan-time inputs the orchestrator threads through (v0.4.1 — refs #339).\n// `project` is the registered project name — the routing key the daemon\n// owns. When present the installer writes it as `OTEL_SERVICE_NAME` so the\n// OTLP wire and the registry agree end-to-end. Absent → installers fall\n// back to a package-local default for ad-hoc / test usage.\nexport interface PlanOptions {\n project?: string\n}\n\nexport interface Installer {\n // Free-form module name. Used for the patch header and for diagnostics.\n name: string\n // Returns true if the installer thinks `serviceDir` is shaped like a project\n // it can instrument. Cheap; no fs writes.\n detect(serviceDir: string): boolean | Promise<boolean>\n // Builds an `InstallPlan` describing the edits the installer would make.\n // Pure data; no fs writes. An empty plan (every edits array empty) means\n // the SDK is already installed and there is nothing to do.\n plan(serviceDir: string, opts?: PlanOptions): InstallPlan | Promise<InstallPlan>\n // Apply a previously-produced plan. Mutates files in place. On failure,\n // produces `<serviceDir>/neat-rollback.patch` per ADR-047 #7. Returns a\n // structured outcome so the CLI can surface coverage (ADR-069 §9).\n apply(plan: InstallPlan): Promise<ApplyResult>\n}\n\nexport function isEmptyPlan(plan: InstallPlan): boolean {\n return (\n plan.dependencyEdits.length === 0 &&\n plan.entrypointEdits.length === 0 &&\n plan.envEdits.length === 0 &&\n (plan.generatedFiles?.length ?? 0) === 0 &&\n plan.nextConfigEdit === undefined\n )\n}\n","/**\n * Installer registry. v0.2.5 step 2 ships the scaffolding; the JavaScript\n * installer (step 3) and Python installer (step 4) populate `INSTALLERS`.\n */\n\nimport type { Installer, InstallPlan } from './shared.js'\nimport { javascriptInstaller } from './javascript.js'\nimport { pythonInstaller } from './python.js'\nexport { isEmptyPlan } from './shared.js'\nexport { javascriptInstaller } from './javascript.js'\nexport { pythonInstaller } from './python.js'\nexport type {\n ApplyOutcome,\n ApplyResult,\n DependencyEdit,\n EntrypointEdit,\n EnvEdit,\n GeneratedFile,\n Installer,\n InstallPlan,\n} from './shared.js'\n\n// Lockfile basenames installers must never write to (ADR-047 — \"lockfiles\n// never touched\"). Used by the patch renderer's safety check below.\nexport const FORBIDDEN_LOCKFILES: ReadonlySet<string> = new Set([\n 'package-lock.json',\n 'pnpm-lock.yaml',\n 'yarn.lock',\n 'poetry.lock',\n 'Pipfile.lock',\n 'Gemfile.lock',\n 'Cargo.lock',\n 'go.sum',\n])\n\n// Order is priority — first match wins per service. JavaScript leads because\n// it's the most common shape in the projects NEAT targets; Python follows.\nexport const INSTALLERS: Installer[] = [javascriptInstaller, pythonInstaller]\n\n/**\n * Resolve the first installer that claims a given service directory. Returns\n * `null` if none match.\n *\n * Per language, the first matching installer wins. Order in `INSTALLERS`\n * defines that priority — declarations are explicit, not alphabetical.\n */\nexport async function pickInstaller(serviceDir: string): Promise<Installer | null> {\n for (const inst of INSTALLERS) {\n if (await inst.detect(serviceDir)) return inst\n }\n return null\n}\n\nexport interface PatchSection {\n installer: string\n plan: InstallPlan\n}\n\n/**\n * Render install plans into a single review-friendly text patch. The format\n * is intentionally human-shaped, not unified-diff: agents and humans both\n * read this. Determinism — same input, byte-identical output — is the\n * load-bearing property (ADR-047 #6).\n */\nexport function renderPatch(sections: PatchSection[]): string {\n if (sections.length === 0) {\n return [\n '# neat install plan',\n '',\n 'No SDK installers matched the discovered services. Two reasons this',\n 'normally happens:',\n ' - the project uses a language NEAT does not yet instrument',\n ' (Java / Ruby / .NET / Go / Rust are out of MVP scope per ADR-047);',\n ' - the SDK is already installed, so the installer returned an empty',\n ' plan.',\n '',\n 'You can re-run `neat init --apply` later to pick up new services.',\n '',\n ].join('\\n')\n }\n\n const lines: string[] = ['# neat install plan', '']\n for (const section of sections) {\n const { installer, plan } = section\n lines.push(`## ${installer} (${plan.language}) — ${plan.serviceDir}`)\n lines.push('')\n\n if (plan.libOnly) {\n lines.push('### skipped — no resolvable entry point (lib-only)')\n lines.push('')\n continue\n }\n\n if (plan.entryFile) {\n lines.push(`entry: ${plan.entryFile}`)\n lines.push('')\n }\n\n if (plan.dependencyEdits.length > 0) {\n lines.push('### dependencies')\n // Group by manifest file so each section names the path the apply phase\n // will write, satisfying the dry-run/apply path-parity contract\n // (ADR-069 §8).\n const byFile = new Map<string, typeof plan.dependencyEdits>()\n for (const dep of plan.dependencyEdits) {\n // Hard-fail rather than render a patch that could mislead the user\n // into thinking NEAT touches lockfiles.\n const base = dep.file.split(/[\\\\/]/).pop() ?? dep.file\n if (FORBIDDEN_LOCKFILES.has(base)) {\n throw new Error(\n `installer \"${installer}\" produced a dependency edit against a lockfile (${dep.file}); ` +\n `lockfiles must never be touched (ADR-047).`,\n )\n }\n const existing = byFile.get(dep.file) ?? []\n existing.push(dep)\n byFile.set(dep.file, existing)\n }\n for (const [file, deps] of byFile) {\n lines.push(`--- ${file}`)\n for (const dep of deps) {\n lines.push(`+ \"${dep.name}\": \"${dep.version}\"`)\n }\n }\n lines.push('')\n }\n\n if (plan.generatedFiles && plan.generatedFiles.length > 0) {\n lines.push('### generated files')\n for (const gen of plan.generatedFiles) {\n lines.push(`--- (new file) ${gen.file}`)\n for (const ln of gen.contents.split(/\\r?\\n/)) {\n lines.push(`+ ${ln}`)\n }\n }\n lines.push('')\n }\n\n if (plan.entrypointEdits.length > 0) {\n lines.push('### entry-point injection')\n for (const e of plan.entrypointEdits) {\n lines.push(`--- ${e.file}`)\n lines.push(`+ ${e.after}`)\n lines.push(` ${e.before}`)\n }\n lines.push('')\n }\n\n if (plan.envEdits.length > 0) {\n lines.push('### env (written to <package-dir>/.env.neat)')\n for (const env of plan.envEdits) {\n lines.push(`- ${env.key}=${env.value}`)\n }\n lines.push('')\n }\n\n // ADR-073 §1 — surface the next.config edit in the dry-run patch so the\n // operator can review the framework-flag change before it lands.\n if (plan.nextConfigEdit) {\n lines.push('### next.config (framework flag)')\n lines.push(`--- ${plan.nextConfigEdit.file}`)\n lines.push(`+ experimental: { instrumentationHook: true }, // ${plan.nextConfigEdit.reason}`)\n lines.push('')\n }\n }\n return lines.join('\\n')\n}\n","/**\n * One-command orchestrator (ADR-073 §1).\n *\n * Bare `neat <path>` dispatches here when the first positional argument\n * resolves to a directory and doesn't match a registered verb. Six steps,\n * in order:\n *\n * 1. Discovery + extraction (per static-extraction contract).\n * 2. `.gitignore` automation (ADR-073 §6) + project registration.\n * 3. SDK install apply — patches manifests + writes otel-init + writes\n * `.env.neat`. Default yes; `--no-instrument` opts out.\n * 4. Daemon spawn — `neatd start --detach` if no daemon is running.\n * Polls `/health` up to 15s for readiness.\n * 5. Browser open against the web UI on port 6328 (T9 NEAT).\n * Default yes; `--no-open` and headless runs skip the launch.\n * 6. Summary block — value-forward findings + OTel env-vars block.\n *\n * `neat init` retains its patch-by-default contract (ADR-046 §5). The\n * orchestrator runs apply unconditionally because the bare-`<path>` shape's\n * user intent is \"make this work end-to-end.\"\n */\n\nimport { promises as fs } from 'node:fs'\nimport http from 'node:http'\nimport path from 'node:path'\nimport { spawn } from 'node:child_process'\nimport readline from 'node:readline'\nimport type { GraphEdge, GraphNode } from '@neat.is/types'\nimport { DEFAULT_PROJECT, getGraph, resetGraph } from './graph.js'\nimport { extractFromDirectory } from './extract.js'\nimport { discoverServices } from './extract/services.js'\nimport { ensureNeatOutIgnored } from './gitignore.js'\nimport { saveGraphToDisk } from './persist.js'\nimport { pathsForProject } from './projects.js'\nimport { addProject, listProjects, ProjectNameCollisionError, setStatus } from './registry.js'\nimport {\n isEmptyPlan,\n pickInstaller,\n type InstallPlan,\n} from './installers/index.js'\n\nexport interface OrchestratorOptions {\n scanPath: string\n // Project name resolution mirrors `neat init` — basename of the scan\n // path unless overridden via --project.\n project: string\n projectExplicit: boolean\n // Skip step 3 (SDK install apply).\n noInstrument: boolean\n // Skip step 5 (browser open).\n noOpen: boolean\n // Skip the interactive prompt (CI invocation flag — implied when\n // stdin/stdout aren't a TTY).\n yes: boolean\n // Dashboard URL — defaults to http://localhost:6328 (T9 NEAT, ADR-059).\n dashboardUrl?: string\n // Health-check timeout in ms. Default 15s.\n daemonReadyTimeoutMs?: number\n}\n\nexport interface OrchestratorResult {\n exitCode: number\n // High-level step-by-step status for the test surface.\n steps: {\n discovery: { services: number; languages: string[] }\n extraction: { nodesAdded: number; edgesAdded: number }\n gitignore: 'added' | 'created' | 'unchanged'\n apply: { instrumented: number; alreadyInstrumented: number; libOnly: number; skipped: boolean }\n daemon: 'spawned' | 'already-running' | 'timed-out' | 'skipped'\n browser: 'opened' | 'skipped' | 'failed'\n }\n}\n\n// Shared sub-pipeline `neat sync` re-uses (ADR-074 §1). Discovery + extract\n// + snapshot write. Distinct from the first-run-only steps (registry add,\n// daemon spawn, browser open, summary block) that the orchestrator owns\n// directly.\nexport interface ExtractAndPersistOptions {\n scanPath: string\n project: string\n projectExplicit: boolean\n // When true, skip persisting to disk — for `neat sync --dry-run`.\n dryRun?: boolean\n}\n\nexport interface ExtractAndPersistResult {\n graph: ReturnType<typeof getGraph>\n graphKey: string\n services: Awaited<ReturnType<typeof discoverServices>>\n languages: string[]\n nodesAdded: number\n edgesAdded: number\n snapshotPath: string\n errorsPath: string\n}\n\nexport async function extractAndPersist(\n opts: ExtractAndPersistOptions,\n): Promise<ExtractAndPersistResult> {\n const services = await discoverServices(opts.scanPath)\n const languages = [...new Set(services.map((s) => s.node.language))].sort()\n\n const graphKey = opts.projectExplicit ? opts.project : DEFAULT_PROJECT\n resetGraph(graphKey)\n const graph = getGraph(graphKey)\n const projectPaths = pathsForProject(graphKey, path.join(opts.scanPath, 'neat-out'))\n const extraction = await extractFromDirectory(graph, opts.scanPath, {\n errorsPath: projectPaths.errorsPath,\n })\n if (!opts.dryRun) {\n await saveGraphToDisk(graph, projectPaths.snapshotPath)\n }\n return {\n graph,\n graphKey,\n services,\n languages,\n nodesAdded: extraction.nodesAdded,\n edgesAdded: extraction.edgesAdded,\n snapshotPath: projectPaths.snapshotPath,\n errorsPath: projectPaths.errorsPath,\n }\n}\n\n// SDK-install apply over a discovered service list. Returns the same shape\n// the orchestrator's result.steps.apply uses so callers (orchestrator + sync)\n// share the rollup logic. v0.4.1 / refs #339 — `project` is threaded through\n// to the installer so the per-package `.env.neat` carries\n// `OTEL_SERVICE_NAME=<project>`, matching the daemon's routing key.\nexport async function applyInstallersOver(\n services: Awaited<ReturnType<typeof discoverServices>>,\n project: string,\n): Promise<{\n instrumented: number\n alreadyInstrumented: number\n libOnly: number\n browserBundle: number\n reactNative: number\n}> {\n let instrumented = 0\n let already = 0\n let libOnly = 0\n let browserBundle = 0\n let reactNative = 0\n for (const svc of services) {\n const installer = await pickInstaller(svc.dir)\n if (!installer) continue\n const plan: InstallPlan = await installer.plan(svc.dir, { project })\n if (isEmptyPlan(plan) && !plan.libOnly && plan.runtimeKind === undefined) {\n already++\n continue\n }\n const outcome = await installer.apply(plan)\n if (outcome.outcome === 'instrumented') instrumented++\n else if (outcome.outcome === 'already-instrumented') already++\n else if (outcome.outcome === 'lib-only') libOnly++\n else if (outcome.outcome === 'browser-bundle') {\n browserBundle++\n console.log(`skipping ${svc.dir}: browser bundle; browser-OTel support lands in a future release.`)\n } else if (outcome.outcome === 'react-native') {\n reactNative++\n console.log(`skipping ${svc.dir}: React Native target; browser-OTel support lands in a future release.`)\n }\n }\n return { instrumented, alreadyInstrumented: already, libOnly, browserBundle, reactNative }\n}\n\nasync function promptYesNo(question: string): Promise<boolean> {\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout })\n return new Promise((resolve) => {\n rl.question(`${question} [Y/n] `, (answer) => {\n rl.close()\n const trimmed = answer.trim().toLowerCase()\n resolve(trimmed === '' || trimmed === 'y' || trimmed === 'yes')\n })\n })\n}\n\n// 60s covers boot + per-project graph load across a registry with several\n// sibling projects. Issue #340 — `app.listen()` now returns the moment the\n// socket binds, so the steady-state happy path lands well inside the first\n// second; the longer ceiling is the cold-clone window where multi-project\n// bootstraps run in the background after listen.\nconst DEFAULT_DAEMON_READY_TIMEOUT_MS = 60_000\n\n// 500ms poll cadence — responsive enough that the operator sees a fresh\n// status line on every transition without spamming the daemon.\nconst PROBE_INTERVAL_MS = 500\n\ninterface DaemonHealthResponse {\n ok?: boolean\n uptimeMs?: number\n projects?: Array<{\n name: string\n status?: 'bootstrapping' | 'active' | 'broken'\n elapsedMs?: number\n }>\n}\n\nasync function fetchDaemonHealth(restPort: number): Promise<DaemonHealthResponse | null> {\n return new Promise((resolve) => {\n const req = http.get(`http://127.0.0.1:${restPort}/health`, (res) => {\n const ok = res.statusCode !== undefined && res.statusCode >= 200 && res.statusCode < 300\n if (!ok) {\n res.resume()\n resolve(null)\n return\n }\n let body = ''\n res.setEncoding('utf8')\n res.on('data', (chunk: string) => { body += chunk })\n res.on('end', () => {\n try {\n resolve(JSON.parse(body) as DaemonHealthResponse)\n } catch {\n resolve({ ok: true })\n }\n })\n })\n req.on('error', () => resolve(null))\n req.setTimeout(1000, () => {\n req.destroy()\n resolve(null)\n })\n })\n}\n\nasync function checkDaemonHealth(restPort: number): Promise<boolean> {\n const body = await fetchDaemonHealth(restPort)\n return body !== null\n}\n\nasync function probeProjectHealth(\n restPort: number,\n name: string,\n): Promise<'bootstrapping' | 'active' | 'broken'> {\n return new Promise((resolve) => {\n const req = http.get(\n `http://127.0.0.1:${restPort}/projects/${encodeURIComponent(name)}/health`,\n (res) => {\n const code = res.statusCode ?? 0\n res.resume()\n if (code >= 200 && code < 300) resolve('active')\n else resolve('bootstrapping')\n },\n )\n req.on('error', () => resolve('bootstrapping'))\n req.setTimeout(1000, () => {\n req.destroy()\n resolve('bootstrapping')\n })\n })\n}\n\n// Resolve the project-status set the wait loop branches on. Prefers the\n// daemon-wide /health response when it carries the list; otherwise reads\n// the registry directly and probes each project's per-project /health.\n// The fallback handles the case where the daemon-wide /health hasn't\n// landed in this branch's main yet.\nasync function snapshotProjectStatus(\n restPort: number,\n body: DaemonHealthResponse,\n): Promise<Array<{ name: string; status: 'bootstrapping' | 'active' | 'broken' }>> {\n if (body.projects && body.projects.length > 0) {\n return body.projects.map((p) => ({\n name: p.name,\n status: p.status ?? 'active',\n }))\n }\n const entries = await listProjects().catch(() => [])\n if (entries.length === 0) return []\n return Promise.all(\n entries.map(async (entry) => ({\n name: entry.name,\n status: await probeProjectHealth(restPort, entry.name),\n })),\n )\n}\n\ninterface DaemonReadyResult {\n ready: boolean\n brokenProjects: string[]\n stillBootstrapping: string[]\n}\n\nasync function waitForDaemonReady(restPort: number, timeoutMs: number): Promise<DaemonReadyResult> {\n const deadline = Date.now() + timeoutMs\n let lastBootstrapping: string[] = []\n while (Date.now() < deadline) {\n const body = await fetchDaemonHealth(restPort)\n if (body !== null) {\n const projects = await snapshotProjectStatus(restPort, body)\n const bootstrapping = projects\n .filter((p) => p.status === 'bootstrapping')\n .map((p) => p.name)\n const broken = projects.filter((p) => p.status === 'broken').map((p) => p.name)\n if (bootstrapping.length === 0) {\n return { ready: true, brokenProjects: broken, stillBootstrapping: [] }\n }\n const key = bootstrapping.slice().sort().join(',')\n const prevKey = lastBootstrapping.slice().sort().join(',')\n if (key !== prevKey) {\n const plural = bootstrapping.length === 1 ? '' : 's'\n console.log(\n `neat: waiting on ${bootstrapping.length} project${plural}: ${bootstrapping.join(', ')}`,\n )\n lastBootstrapping = bootstrapping\n }\n }\n await new Promise((r) => setTimeout(r, PROBE_INTERVAL_MS))\n }\n const final = await fetchDaemonHealth(restPort)\n const projects = final ? await snapshotProjectStatus(restPort, final) : []\n return {\n ready: false,\n brokenProjects: projects.filter((p) => p.status === 'broken').map((p) => p.name),\n stillBootstrapping: projects\n .filter((p) => p.status === 'bootstrapping')\n .map((p) => p.name),\n }\n}\n\n// Spawn the daemon as a child process the orchestrator drives. Returns the\n// child handle so the caller can read its stderr verbatim when the bind\n// gate (or any other startup failure) reports back through that pipe\n// (issue #341). The `detached: true` + `unref()` pair survives the\n// orchestrator exiting cleanly; the inherited stderr keeps the operator\n// informed when something does fail.\nfunction spawnDaemonDetached(): import('node:child_process').ChildProcess {\n // Resolve the neatd entry inside the @neat.is/core dist next to this\n // file. `import.meta.url` is post-bundling — at runtime, this resolves\n // to `<core>/dist/neatd.{js,cjs}`. We pick the .cjs because tsup ships\n // it in both forms and node tolerates either.\n const here = path.dirname(new URL(import.meta.url).pathname)\n const candidates = [\n path.join(here, 'neatd.cjs'),\n path.join(here, 'neatd.js'),\n ]\n let entry: string | null = null\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const fsSync = require('node:fs') as typeof import('node:fs')\n for (const c of candidates) {\n try {\n fsSync.accessSync(c)\n entry = c\n break\n } catch {\n // try next\n }\n }\n if (!entry) {\n throw new Error(`orchestrator: cannot locate neatd entry in ${here}`)\n }\n\n // ADR-073 §3 + issue #341 — first-touch path is loopback-only. When the\n // operator hasn't set `NEAT_AUTH_TOKEN` the orchestrator hard-pins\n // HOST=127.0.0.1 in the child env so `assertBindAuthority` lets the bind\n // through. Public-bind is opt-in via the token (and an explicit\n // `HOST=0.0.0.0` if the operator wants the literal). The parent's HOST is\n // preserved untouched when the token is set — that's the deploy path,\n // where the platform owns the bind decision.\n const env = { ...process.env }\n const hasToken = typeof env.NEAT_AUTH_TOKEN === 'string' && env.NEAT_AUTH_TOKEN.length > 0\n if (!hasToken && (!env.HOST || env.HOST.length === 0)) {\n env.HOST = '127.0.0.1'\n }\n\n const child = spawn(process.execPath, [entry, 'start'], {\n detached: true,\n // stderr inherits the orchestrator's fd so the daemon's\n // `BindAuthorityError` message lands in front of the operator instead\n // of being swallowed (issue #341).\n stdio: ['ignore', 'ignore', 'inherit'],\n env,\n })\n child.unref()\n return child\n}\n\nfunction openBrowser(url: string): 'opened' | 'failed' {\n // Skip when running headlessly; we don't want CI invocations to fail\n // because xdg-open isn't installed.\n if (!process.stdout.isTTY) return 'failed'\n const platform = process.platform\n const cmd =\n platform === 'darwin' ? 'open' :\n platform === 'win32' ? 'cmd' :\n 'xdg-open'\n const args = platform === 'win32' ? ['/c', 'start', '', url] : [url]\n try {\n const child = spawn(cmd, args, { detached: true, stdio: 'ignore' })\n child.on('error', () => {})\n child.unref()\n return 'opened'\n } catch {\n return 'failed'\n }\n}\n\nexport async function runOrchestrator(opts: OrchestratorOptions): Promise<OrchestratorResult> {\n const result: OrchestratorResult = {\n exitCode: 0,\n steps: {\n discovery: { services: 0, languages: [] },\n extraction: { nodesAdded: 0, edgesAdded: 0 },\n gitignore: 'unchanged',\n apply: { instrumented: 0, alreadyInstrumented: 0, libOnly: 0, skipped: false },\n daemon: 'skipped',\n browser: 'skipped',\n },\n }\n\n // ── Path validation ───────────────────────────────────────────────────\n const stat = await fs.stat(opts.scanPath).catch(() => null)\n if (!stat || !stat.isDirectory()) {\n console.error(`neat: ${opts.scanPath} is not a directory`)\n result.exitCode = 2\n return result\n }\n\n console.log(`neat: ${opts.scanPath}`)\n console.log('')\n\n // ── Step 1: discovery, Step 2: extraction + snapshot ─────────────────\n // Shared with `neat sync` (ADR-074 §1) via extractAndPersist.\n const persisted = await extractAndPersist({\n scanPath: opts.scanPath,\n project: opts.project,\n projectExplicit: opts.projectExplicit,\n })\n const { graph, services, languages } = persisted\n result.steps.discovery = { services: services.length, languages }\n console.log(`discovered ${services.length} service(s) across ${languages.length} language(s)`)\n\n // ── Confirmation prompt (default yes; --no-instrument or no-TTY skip)\n let runApply = !opts.noInstrument\n if (runApply && !opts.yes && process.stdout.isTTY && process.stdin.isTTY) {\n runApply = await promptYesNo('instrument your services and open the dashboard?')\n }\n\n result.steps.extraction = {\n nodesAdded: persisted.nodesAdded,\n edgesAdded: persisted.edgesAdded,\n }\n\n const gi = await ensureNeatOutIgnored(opts.scanPath)\n result.steps.gitignore = gi.action\n if (gi.action !== 'unchanged') {\n console.log(`${gi.action} .gitignore (neat-out/)`)\n }\n\n let currentProjectName = opts.project\n try {\n const entry = await addProject({\n name: opts.project,\n path: opts.scanPath,\n languages,\n status: 'active',\n })\n currentProjectName = entry.name\n } catch (err) {\n if (!(err instanceof ProjectNameCollisionError)) throw err\n // Same path, same name → re-init. Different path → bail with a clear\n // message so the operator can pass --project <other-name>.\n console.error(`neat: ${err.message}`)\n console.error('pass --project <other-name> to register under a different name.')\n result.exitCode = 1\n return result\n }\n\n // Narrow the active-project surface to what the operator is currently in.\n // Every other `active` entry transitions to `paused`; `broken` is left alone\n // so the daemon's broken-path handling still surfaces. `neat resume <name>`\n // brings any of them back when cross-project work is the explicit intent.\n const siblings = await listProjects()\n const paused: string[] = []\n for (const p of siblings) {\n if (p.name !== currentProjectName && p.status === 'active') {\n await setStatus(p.name, 'paused')\n paused.push(p.name)\n }\n }\n if (paused.length > 0) {\n const plural = paused.length === 1 ? '' : 's'\n console.log(\n `neat: paused ${paused.length} sibling project${plural}; run \\`neat resume <name>\\` to bring one back active.`,\n )\n }\n\n // ── Step 3: SDK install apply (default yes; --no-instrument skips) ───\n if (!runApply) {\n result.steps.apply.skipped = true\n console.log('skipped instrumentation (--no-instrument)')\n } else {\n const tally = await applyInstallersOver(services, opts.project)\n result.steps.apply = { ...tally, skipped: false }\n console.log(\n `instrumented ${tally.instrumented}, already ${tally.alreadyInstrumented}, lib-only ${tally.libOnly}`,\n )\n }\n\n // ── Step 4: daemon spawn + health poll ───────────────────────────────\n const restPort = Number(process.env.PORT ?? 8080)\n const timeoutMs = opts.daemonReadyTimeoutMs ?? DEFAULT_DAEMON_READY_TIMEOUT_MS\n if (await checkDaemonHealth(restPort)) {\n result.steps.daemon = 'already-running'\n } else {\n try {\n spawnDaemonDetached()\n } catch (err) {\n console.error(`neat: daemon spawn failed — ${(err as Error).message}`)\n result.exitCode = 1\n return result\n }\n const ready = await waitForDaemonReady(restPort, timeoutMs)\n result.steps.daemon = ready.ready ? 'spawned' : 'timed-out'\n if (!ready.ready) {\n console.error(`neat: daemon did not become ready within ${timeoutMs}ms`)\n if (ready.stillBootstrapping.length > 0) {\n console.error(\n `neat: still bootstrapping: ${ready.stillBootstrapping.join(', ')}`,\n )\n }\n if (ready.brokenProjects.length > 0) {\n console.error(`neat: broken projects: ${ready.brokenProjects.join(', ')}`)\n }\n result.exitCode = 1\n return result\n }\n if (ready.brokenProjects.length > 0) {\n console.warn(\n `neat: ${ready.brokenProjects.length} project(s) reported broken: ${ready.brokenProjects.join(', ')}`,\n )\n }\n }\n\n // ── Step 5: browser open ─────────────────────────────────────────────\n const dashboardUrl = opts.dashboardUrl ?? 'http://localhost:6328'\n if (opts.noOpen || !process.stdout.isTTY) {\n result.steps.browser = 'skipped'\n } else {\n result.steps.browser = openBrowser(dashboardUrl)\n }\n\n // ── Step 6: summary (stub — PR 4 replaces with the value-forward shape)\n printSummary(result, graph, dashboardUrl)\n\n return result\n}\n\nfunction printSummary(\n result: OrchestratorResult,\n graph: ReturnType<typeof getGraph>,\n dashboardUrl: string,\n): void {\n const nodes: GraphNode[] = []\n graph.forEachNode((_id, attrs) => nodes.push(attrs))\n const edges: GraphEdge[] = []\n graph.forEachEdge((_id, attrs) => edges.push(attrs))\n\n const byNode = new Map<string, number>()\n for (const n of nodes) byNode.set(n.type, (byNode.get(n.type) ?? 0) + 1)\n const byEdge = new Map<string, number>()\n for (const e of edges) byEdge.set(e.type, (byEdge.get(e.type) ?? 0) + 1)\n\n console.log('')\n console.log('=== summary ===')\n console.log(`graph: ${graph.order} nodes, ${graph.size} edges`)\n for (const [t, c] of [...byNode.entries()].sort()) console.log(` ${t}: ${c}`)\n for (const [t, c] of [...byEdge.entries()].sort()) console.log(` ${t}: ${c}`)\n console.log('')\n console.log(`dashboard: ${dashboardUrl}`)\n}\n","/**\n * Lifecycle-verb implementations for the CLI. Query verbs live in\n * `cli-client.ts` next to the REST client; lifecycle verbs (currently\n * `neat sync`) live here because they orchestrate filesystem work and\n * daemon-state probes rather than wrapping a single REST endpoint.\n */\n\nimport path from 'node:path'\nimport type { RegistryEntry } from '@neat.is/types'\nimport {\n applyInstallersOver,\n extractAndPersist,\n type ExtractAndPersistResult,\n} from './orchestrator.js'\nimport { listProjects, normalizeProjectPath } from './registry.js'\nimport { saveGraphToDisk, type PersistedGraph } from './persist.js'\nimport {\n HttpError,\n pushSnapshotToRemote,\n TransportError,\n} from './cli-client.js'\n\nexport interface SyncOptions {\n // Project name from `--project <name>`. When absent, sync resolves the\n // project by matching the cwd against the registered project paths.\n project?: string\n // Push the snapshot to a remote daemon URL. When absent, sync runs against\n // the local daemon on http://localhost:8080.\n to?: string\n // Bearer token for the remote daemon. Falls back to NEAT_REMOTE_TOKEN env.\n token?: string\n // Skip writing the snapshot or notifying the daemon. Mirrors `neat <path>\n // --dry-run`.\n dryRun: boolean\n // Skip the SDK install apply step.\n noInstrument: boolean\n // Emit a structured JSON payload on stdout instead of human text.\n json: boolean\n // Override the local daemon URL. Defaults to NEAT_API_URL or\n // http://localhost:8080. Useful for tests.\n daemonUrl?: string\n // Working directory the verb resolves against when `--project` isn't\n // passed. Defaults to process.cwd(); tests override.\n cwd?: string\n}\n\nexport interface SyncResult {\n exitCode: number\n // Stable shape across human / json output paths. cli.ts decides which\n // formatter to invoke based on `--json`.\n project: string\n scanPath: string\n nodesAdded: number\n edgesAdded: number\n snapshotPath: string | null\n // Tracks which branch the run took for `--json` consumers.\n mode: 'dry-run' | 'local' | 'remote'\n daemon: 'reloaded' | 'down' | 'remote-ok' | 'skipped'\n apply: {\n instrumented: number\n alreadyInstrumented: number\n libOnly: number\n skipped: boolean\n }\n // Soft warning lines surfaced to stderr in the human path. Empty when the\n // run was fully clean.\n warnings: string[]\n}\n\nasync function resolveProjectEntry(opts: SyncOptions): Promise<RegistryEntry | null> {\n const entries = await listProjects()\n if (opts.project) {\n const match = entries.find((e) => e.name === opts.project)\n return match ?? null\n }\n const cwd = opts.cwd ?? process.cwd()\n const resolvedCwd = await normalizeProjectPath(cwd)\n // Match by path: the cwd must be inside (or equal to) the registered path.\n for (const entry of entries) {\n if (\n resolvedCwd === entry.path ||\n resolvedCwd.startsWith(`${entry.path}${path.sep}`)\n ) {\n return entry\n }\n }\n return null\n}\n\nasync function checkDaemonHealth(baseUrl: string): Promise<boolean> {\n try {\n const res = await fetch(`${baseUrl.replace(/\\/$/, '')}/health`, {\n signal: AbortSignal.timeout(1500),\n })\n return res.ok\n } catch {\n return false\n }\n}\n\nfunction snapshotForGraph(persisted: ExtractAndPersistResult): PersistedGraph {\n return {\n schemaVersion: 3,\n exportedAt: new Date().toISOString(),\n graph: persisted.graph.export(),\n }\n}\n\nfunction emitResult(result: SyncResult, json: boolean): void {\n if (json) {\n process.stdout.write(JSON.stringify(result, null, 2) + '\\n')\n return\n }\n const verb =\n result.mode === 'dry-run'\n ? 'dry-run'\n : result.mode === 'remote'\n ? 'pushed'\n : 'synced'\n console.log(\n `${verb}: ${result.project} — ${result.nodesAdded} node(s) and ${result.edgesAdded} edge(s) added` +\n (result.snapshotPath ? `; snapshot at ${result.snapshotPath}` : ''),\n )\n if (!result.apply.skipped) {\n const { instrumented, alreadyInstrumented, libOnly } = result.apply\n console.log(\n `instrumented ${instrumented}, already ${alreadyInstrumented}, lib-only ${libOnly}`,\n )\n } else {\n console.log('skipped instrumentation (--no-instrument)')\n }\n for (const warn of result.warnings) console.error(warn)\n}\n\nexport async function runSync(opts: SyncOptions): Promise<SyncResult> {\n const entry = await resolveProjectEntry(opts)\n if (!entry) {\n const target = opts.project ?? opts.cwd ?? process.cwd()\n console.error(\n `neat sync: no registered project ${\n opts.project ? `named \"${opts.project}\"` : `covers ${target}`\n }. Run \\`neat <path>\\` or \\`neat init <path>\\` first.`,\n )\n return {\n exitCode: 1,\n project: opts.project ?? '',\n scanPath: target,\n nodesAdded: 0,\n edgesAdded: 0,\n snapshotPath: null,\n mode: opts.to ? 'remote' : 'local',\n daemon: 'skipped',\n apply: { instrumented: 0, alreadyInstrumented: 0, libOnly: 0, skipped: true },\n warnings: [],\n }\n }\n\n // ── Step 1 + 2: discovery + extraction (no snapshot in dry-run) ─────\n const persisted = await extractAndPersist({\n scanPath: entry.path,\n project: entry.name,\n projectExplicit: true,\n dryRun: true,\n })\n\n let snapshotPath: string | null = null\n if (!opts.dryRun) {\n const target = persisted.snapshotPath\n await saveGraphToDisk(persisted.graph, target)\n snapshotPath = target\n }\n\n // ── Step 3: SDK install apply (default yes; --dry-run + --no-instrument skip)\n const skipApply = opts.dryRun || opts.noInstrument\n const applyTally = skipApply\n ? { instrumented: 0, alreadyInstrumented: 0, libOnly: 0, browserBundle: 0, reactNative: 0 }\n : await applyInstallersOver(persisted.services, entry.name)\n\n // ── Step 4: daemon notify ────────────────────────────────────────────\n const warnings: string[] = []\n let daemonState: SyncResult['daemon'] = 'skipped'\n let exitCode = 0\n const mode: SyncResult['mode'] = opts.dryRun ? 'dry-run' : opts.to ? 'remote' : 'local'\n\n if (!opts.dryRun) {\n const snapshot = snapshotForGraph(persisted)\n if (opts.to) {\n const token = opts.token ?? process.env.NEAT_REMOTE_TOKEN\n try {\n await pushSnapshotToRemote({\n baseUrl: opts.to,\n token,\n project: entry.name,\n snapshot,\n })\n daemonState = 'remote-ok'\n } catch (err) {\n if (err instanceof HttpError) {\n console.error(`neat sync: ${err.message}`)\n exitCode = 1\n } else if (err instanceof TransportError) {\n console.error(`neat sync: ${err.message}`)\n exitCode = 3\n } else {\n console.error(`neat sync: ${(err as Error).message}`)\n exitCode = 1\n }\n daemonState = 'skipped'\n }\n } else {\n const daemonUrl =\n opts.daemonUrl ?? process.env.NEAT_API_URL ?? 'http://localhost:8080'\n const healthy = await checkDaemonHealth(daemonUrl)\n if (healthy) {\n try {\n await pushSnapshotToRemote({\n baseUrl: daemonUrl,\n token: process.env.NEAT_AUTH_TOKEN,\n project: entry.name,\n snapshot,\n })\n daemonState = 'reloaded'\n } catch (err) {\n warnings.push(\n `neat sync: daemon merge failed — ${(err as Error).message}. Snapshot is on disk at ${snapshotPath}.`,\n )\n daemonState = 'down'\n exitCode = 2\n }\n } else {\n warnings.push(\n 'neat sync: daemon not running; snapshot updated, run `neatd start` to serve it',\n )\n daemonState = 'down'\n exitCode = 2\n }\n }\n }\n\n const result: SyncResult = {\n exitCode,\n project: entry.name,\n scanPath: entry.path,\n nodesAdded: persisted.nodesAdded,\n edgesAdded: persisted.edgesAdded,\n snapshotPath,\n mode,\n daemon: daemonState,\n apply: { ...applyTally, skipped: skipApply },\n warnings,\n }\n\n emitResult(result, opts.json)\n return result\n}\n","// REST helper + CLI verb implementations for `neat <verb>` (ADR-050).\n//\n// The HttpClient and its createHttpClient factory are the \"shared REST helper\n// module\" the contract calls for — one endpoint surface, two consumers\n// (`packages/mcp/src/client.ts` re-exports from here, the CLI dispatcher\n// imports it directly).\n//\n// Verb handlers live alongside the client because they're tightly coupled:\n// each verb maps 1:1 to an MCP tool from ADR-039, but produces the structured\n// `{ summary, block, confidence, provenance }` shape (ADR-050 #3) in pure\n// data form. cli.ts formats that shape into either human-readable text or\n// `--json` output.\n\nimport type {\n BlastRadiusAffectedNode,\n BlastRadiusResult,\n Divergence,\n DivergenceResult,\n DivergenceType,\n ErrorEvent,\n GraphEdge,\n GraphNode,\n HypotheticalAction,\n PolicyViolation,\n RootCauseResult,\n TransitiveDependenciesResult,\n} from '@neat.is/types'\nimport { Provenance } from '@neat.is/types'\n\n// ──────────────────────────────────────────────────────────────────────────\n// REST client\n// ──────────────────────────────────────────────────────────────────────────\n\nexport interface HttpClient {\n get<T>(path: string): Promise<T>\n post?<T>(path: string, body: unknown): Promise<T>\n}\n\nexport class HttpError extends Error {\n constructor(\n public readonly status: number,\n message: string,\n public readonly responseBody: string = '',\n ) {\n super(message)\n this.name = 'HttpError'\n }\n}\n\n// Network-level failures (ECONNREFUSED, ETIMEDOUT, DNS) — distinct from\n// HttpError so the CLI can map them to exit code 3 (daemon-down) without\n// parsing error strings.\nexport class TransportError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'TransportError'\n }\n}\n\nexport function createHttpClient(baseUrl: string, bearerToken?: string): HttpClient {\n const root = baseUrl.replace(/\\/$/, '')\n const authHeader = bearerToken && bearerToken.length > 0\n ? { authorization: `Bearer ${bearerToken}` }\n : {}\n return {\n async get<T>(path: string): Promise<T> {\n let res: Response\n try {\n res = await fetch(`${root}${path}`, {\n headers: { ...authHeader },\n })\n } catch (err) {\n throw new TransportError(\n `cannot reach neat-core at ${root}: ${(err as Error).message}`,\n )\n }\n if (!res.ok) {\n const body = await res.text().catch(() => '')\n throw new HttpError(\n res.status,\n `${res.status} ${res.statusText} on GET ${path}: ${body}`,\n body,\n )\n }\n return (await res.json()) as T\n },\n async post<T>(path: string, body: unknown): Promise<T> {\n let res: Response\n try {\n res = await fetch(`${root}${path}`, {\n method: 'POST',\n headers: { 'content-type': 'application/json', ...authHeader },\n body: JSON.stringify(body),\n })\n } catch (err) {\n throw new TransportError(\n `cannot reach neat-core at ${root}: ${(err as Error).message}`,\n )\n }\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new HttpError(\n res.status,\n `${res.status} ${res.statusText} on POST ${path}: ${text}`,\n text,\n )\n }\n return (await res.json()) as T\n },\n }\n}\n\n// Project routing per ADR-050 #2: `--project <name>` (handled in cli.ts) →\n// `NEAT_PROJECT` env → `default`. The default routes hit the legacy\n// unprefixed URLs which the core resolves to project=`default`.\nfunction projectPath(project: string | undefined, suffix: string): string {\n if (!project) return suffix\n return `/projects/${encodeURIComponent(project)}${suffix}`\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Verb result shape (ADR-050 #3)\n// ──────────────────────────────────────────────────────────────────────────\n\nexport interface VerbResult {\n // NL paragraph. What was found and why it matters.\n summary: string\n // Structured payload — usually a bulleted list. Empty when the summary\n // already conveys everything.\n block?: string\n // Per-result confidence in [0, 1]. Undefined → footer reads \"n/a\".\n confidence?: number\n // Per-result provenance. String, array (mixed paths), or undefined.\n provenance?: string | string[]\n}\n\n// Common shape the nine verbs produce. cli.ts renders this to text or JSON.\n\n// ──────────────────────────────────────────────────────────────────────────\n// Verbs\n// ──────────────────────────────────────────────────────────────────────────\n\nexport interface RootCauseInput {\n errorNode: string\n errorId?: string\n project?: string\n}\n\nexport async function runRootCause(\n client: HttpClient,\n input: RootCauseInput,\n): Promise<VerbResult> {\n const qs = input.errorId ? `?errorId=${encodeURIComponent(input.errorId)}` : ''\n const path = projectPath(\n input.project,\n `/graph/root-cause/${encodeURIComponent(input.errorNode)}${qs}`,\n )\n try {\n const result = await client.get<RootCauseResult>(path)\n const arrowPath = result.traversalPath.join(' ← ')\n const provenances = result.edgeProvenances.length\n ? result.edgeProvenances.join(', ')\n : '(direct, no edges traversed)'\n const summary =\n `Root cause for ${input.errorNode} is ${result.rootCauseNode}. ` +\n result.rootCauseReason +\n (result.fixRecommendation ? ` Recommended fix: ${result.fixRecommendation}.` : '')\n const blockLines = [\n `Traversal path: ${arrowPath}`,\n `Edge provenances: ${provenances}`,\n ]\n if (result.fixRecommendation) blockLines.push(`Recommended fix: ${result.fixRecommendation}`)\n return {\n summary,\n block: blockLines.join('\\n'),\n confidence: result.confidence,\n provenance: result.edgeProvenances.length ? result.edgeProvenances : undefined,\n }\n } catch (err) {\n if (err instanceof HttpError && err.status === 404) {\n return {\n summary: `No root cause found for ${input.errorNode}. The node may be healthy, or it may not exist in the graph.`,\n }\n }\n throw err\n }\n}\n\nexport interface BlastRadiusInput {\n nodeId: string\n depth?: number\n project?: string\n}\n\nexport async function runBlastRadius(\n client: HttpClient,\n input: BlastRadiusInput,\n): Promise<VerbResult> {\n const qs = input.depth !== undefined ? `?depth=${input.depth}` : ''\n const path = projectPath(\n input.project,\n `/graph/blast-radius/${encodeURIComponent(input.nodeId)}${qs}`,\n )\n try {\n const result = await client.get<BlastRadiusResult>(path)\n if (result.totalAffected === 0) {\n return {\n summary: `${result.origin} has no downstream dependencies. Nothing else would break if it failed.`,\n }\n }\n const sorted = [...result.affectedNodes].sort(\n (a, b) => a.distance - b.distance || a.nodeId.localeCompare(b.nodeId),\n )\n const blockLines = sorted.map(formatBlastEntry)\n const minConfidence = sorted.reduce(\n (m, n) => Math.min(m, n.confidence),\n Number.POSITIVE_INFINITY,\n )\n const provenances = [...new Set(sorted.map((n) => n.edgeProvenance))]\n return {\n summary: `Blast radius for ${result.origin}: ${result.totalAffected} affected node${result.totalAffected === 1 ? '' : 's'} reachable downstream.`,\n block: blockLines.join('\\n'),\n confidence: Number.isFinite(minConfidence) ? minConfidence : undefined,\n provenance: provenances.length ? provenances : undefined,\n }\n } catch (err) {\n if (err instanceof HttpError && err.status === 404) {\n return { summary: `Node ${input.nodeId} not found in the graph.` }\n }\n throw err\n }\n}\n\nfunction formatBlastEntry(n: BlastRadiusAffectedNode): string {\n const tag = n.edgeProvenance === Provenance.STALE ? ' [STALE — last seen too long ago]' : ''\n return ` • ${n.nodeId} (distance ${n.distance}, ${n.edgeProvenance})${tag}`\n}\n\nexport interface DependenciesInput {\n nodeId: string\n depth?: number\n project?: string\n}\n\nexport async function runDependencies(\n client: HttpClient,\n input: DependenciesInput,\n): Promise<VerbResult> {\n const depth = input.depth ?? 3\n const path = projectPath(\n input.project,\n `/graph/dependencies/${encodeURIComponent(input.nodeId)}?depth=${depth}`,\n )\n try {\n const result = await client.get<TransitiveDependenciesResult>(path)\n if (result.total === 0) {\n return {\n summary:\n depth === 1\n ? `${input.nodeId} has no direct dependencies in the graph.`\n : `${input.nodeId} has no dependencies (BFS to depth ${depth}).`,\n }\n }\n const byDistance = new Map<number, typeof result.dependencies>()\n for (const dep of result.dependencies) {\n const ring = byDistance.get(dep.distance) ?? []\n ring.push(dep)\n byDistance.set(dep.distance, ring)\n }\n const blockLines: string[] = []\n for (const distance of [...byDistance.keys()].sort((a, b) => a - b)) {\n const label = distance === 1 ? 'Direct (distance 1)' : `Distance ${distance}`\n blockLines.push(`${label}:`)\n for (const dep of byDistance.get(distance)!) {\n blockLines.push(` • ${dep.nodeId} — ${dep.edgeType} (${dep.provenance})`)\n }\n }\n const provenances = [...new Set(result.dependencies.map((d) => d.provenance))]\n const directCount = byDistance.get(1)?.length ?? 0\n const summary =\n depth === 1\n ? `${input.nodeId} has ${directCount} direct dependenc${directCount === 1 ? 'y' : 'ies'}.`\n : `${input.nodeId} has ${result.total} dependenc${result.total === 1 ? 'y' : 'ies'} reachable to depth ${depth} (${directCount} direct).`\n return { summary, block: blockLines.join('\\n'), provenance: provenances }\n } catch (err) {\n if (err instanceof HttpError && err.status === 404) {\n return { summary: `Node ${input.nodeId} not found in the graph.` }\n }\n throw err\n }\n}\n\ninterface EdgesResponse {\n inbound: GraphEdge[]\n outbound: GraphEdge[]\n}\n\nexport async function runObservedDependencies(\n client: HttpClient,\n input: DependenciesInput,\n): Promise<VerbResult> {\n try {\n const edges = await client.get<EdgesResponse>(\n projectPath(input.project, `/graph/edges/${encodeURIComponent(input.nodeId)}`),\n )\n const observed = edges.outbound.filter((e) => e.provenance === Provenance.OBSERVED)\n if (observed.length === 0) {\n const hasExtracted = edges.outbound.some((e) => e.provenance === Provenance.EXTRACTED)\n const note = hasExtracted\n ? ' Static (EXTRACTED) dependencies exist but no runtime traffic has been seen — is OTel running?'\n : ''\n return { summary: `No OBSERVED dependencies for ${input.nodeId}.${note}` }\n }\n const blockLines = observed.map((e) => ` • ${e.target} — ${e.type}${edgeMeta(e)}`)\n return {\n summary: `${input.nodeId} has ${observed.length} runtime dependenc${observed.length === 1 ? 'y' : 'ies'} confirmed by OTel.`,\n block: blockLines.join('\\n'),\n provenance: Provenance.OBSERVED,\n }\n } catch (err) {\n if (err instanceof HttpError && err.status === 404) {\n return { summary: `Node ${input.nodeId} not found in the graph.` }\n }\n throw err\n }\n}\n\nfunction edgeMeta(e: GraphEdge): string {\n const bits: string[] = []\n if (e.signal) {\n bits.push(`spans=${e.signal.spanCount}`)\n if (e.signal.errorCount > 0) bits.push(`errors=${e.signal.errorCount}`)\n if (e.signal.lastObservedAgeMs !== undefined) {\n bits.push(`age=${formatDuration(e.signal.lastObservedAgeMs)}`)\n }\n } else if (e.callCount !== undefined) {\n bits.push(`callCount=${e.callCount}`)\n }\n if (e.lastObserved) bits.push(`lastObserved=${e.lastObserved}`)\n if (e.confidence !== undefined) bits.push(`confidence=${e.confidence}`)\n return bits.length ? ` [${bits.join(', ')}]` : ''\n}\n\nfunction formatDuration(ms: number): string {\n if (ms < 1000) return `${Math.round(ms)}ms`\n const s = Math.round(ms / 1000)\n if (s < 60) return `${s}s`\n const m = Math.round(s / 60)\n if (m < 60) return `${m}m`\n const h = Math.round(m / 60)\n if (h < 48) return `${h}h`\n return `${Math.round(h / 24)}d`\n}\n\nexport interface IncidentsInput {\n nodeId?: string\n limit?: number\n project?: string\n}\n\n// `neat incidents` shape: with a node id, returns that node's incidents.\n// Without one, returns the global recent log.\nexport async function runIncidents(\n client: HttpClient,\n input: IncidentsInput,\n): Promise<VerbResult> {\n const path = input.nodeId\n ? projectPath(input.project, `/incidents/${encodeURIComponent(input.nodeId)}`)\n : projectPath(input.project, '/incidents')\n try {\n const body = await client.get<{ count: number; total: number; events: ErrorEvent[] }>(path)\n const events = body.events\n if (events.length === 0) {\n return {\n summary: input.nodeId\n ? `No incidents recorded against ${input.nodeId}.`\n : 'No incidents recorded.',\n }\n }\n const ordered = [...events].reverse().slice(0, input.limit ?? 20)\n const blockLines: string[] = []\n for (const ev of ordered) {\n blockLines.push(` ${ev.timestamp} — ${ev.service}: ${ev.errorMessage}`)\n blockLines.push(` trace=${ev.traceId} span=${ev.spanId}`)\n }\n const target = input.nodeId ?? 'the project'\n return {\n summary: `${target} has ${body.total} recorded incident${body.total === 1 ? '' : 's'}; showing the ${ordered.length} most recent.`,\n block: blockLines.join('\\n'),\n provenance: Provenance.OBSERVED,\n }\n } catch (err) {\n if (err instanceof HttpError && err.status === 404) {\n return { summary: `Node ${input.nodeId ?? ''} not found in the graph.` }\n }\n throw err\n }\n}\n\nexport interface SearchInput {\n query: string\n project?: string\n}\n\ninterface SearchResponse {\n query: string\n provider?: 'ollama' | 'transformers' | 'substring'\n matches: (GraphNode & { score?: number })[]\n}\n\nexport async function runSearch(\n client: HttpClient,\n input: SearchInput,\n): Promise<VerbResult> {\n const result = await client.get<SearchResponse>(\n projectPath(input.project, `/search?q=${encodeURIComponent(input.query)}`),\n )\n if (result.matches.length === 0) {\n return { summary: `No matches for \"${input.query}\".` }\n }\n const provider = result.provider ?? 'substring'\n const blockLines: string[] = []\n let topScore: number | undefined\n for (const n of result.matches) {\n const score = provider !== 'substring' && typeof n.score === 'number' ? n.score : undefined\n const scoreBit = score !== undefined ? ` [score=${score.toFixed(2)}]` : ''\n if (score !== undefined && (topScore === undefined || score > topScore)) topScore = score\n blockLines.push(\n ` • ${n.id} (${n.type}) — ${(n as { name?: string }).name ?? n.id}${scoreBit}`,\n )\n }\n return {\n summary: `Found ${result.matches.length} match${result.matches.length === 1 ? '' : 'es'} for \"${input.query}\" via ${provider} provider.`,\n block: blockLines.join('\\n'),\n confidence: topScore,\n }\n}\n\nexport interface DiffInput {\n againstSnapshot: string\n project?: string\n}\n\ninterface GraphDiffResponse {\n base: { exportedAt?: string }\n current: { exportedAt: string }\n added: { nodes: GraphNode[]; edges: GraphEdge[] }\n removed: { nodes: GraphNode[]; edges: GraphEdge[] }\n changed: {\n nodes: { id: string; before: GraphNode; after: GraphNode }[]\n edges: { id: string; before: GraphEdge; after: GraphEdge }[]\n }\n}\n\nexport async function runDiff(client: HttpClient, input: DiffInput): Promise<VerbResult> {\n const result = await client.get<GraphDiffResponse>(\n projectPath(\n input.project,\n `/graph/diff?against=${encodeURIComponent(input.againstSnapshot)}`,\n ),\n )\n const total =\n result.added.nodes.length +\n result.added.edges.length +\n result.removed.nodes.length +\n result.removed.edges.length +\n result.changed.nodes.length +\n result.changed.edges.length\n const baseLabel = result.base.exportedAt ?? 'unknown'\n if (total === 0) {\n return {\n summary: `No differences between the current graph and ${input.againstSnapshot} (base exportedAt=${baseLabel}).`,\n }\n }\n const blockLines: string[] = [\n ` base exportedAt: ${baseLabel}`,\n ` current exportedAt: ${result.current.exportedAt}`,\n '',\n ]\n if (result.added.nodes.length || result.added.edges.length) {\n blockLines.push('Added:')\n for (const n of result.added.nodes) blockLines.push(` + node ${n.id} (${n.type})`)\n for (const e of result.added.edges)\n blockLines.push(` + edge ${e.id} — ${e.source} -> ${e.target} (${e.type}, ${e.provenance})`)\n blockLines.push('')\n }\n if (result.removed.nodes.length || result.removed.edges.length) {\n blockLines.push('Removed:')\n for (const n of result.removed.nodes) blockLines.push(` - node ${n.id} (${n.type})`)\n for (const e of result.removed.edges)\n blockLines.push(` - edge ${e.id} — ${e.source} -> ${e.target} (${e.type}, ${e.provenance})`)\n blockLines.push('')\n }\n if (result.changed.nodes.length || result.changed.edges.length) {\n blockLines.push('Changed:')\n for (const c of result.changed.nodes) {\n blockLines.push(` ~ node ${c.id} — ${summariseAttrDiff(c.before, c.after)}`)\n }\n for (const c of result.changed.edges) {\n const provBit =\n c.before.provenance !== c.after.provenance\n ? `provenance ${c.before.provenance} → ${c.after.provenance}`\n : summariseAttrDiff(c.before, c.after)\n blockLines.push(` ~ edge ${c.id} — ${provBit}`)\n }\n }\n return {\n summary: `Diff against ${input.againstSnapshot}: ${total} change${total === 1 ? '' : 's'} between the snapshot and the live graph.`,\n block: blockLines.join('\\n').trimEnd(),\n }\n}\n\nfunction summariseAttrDiff(\n before: Record<string, unknown>,\n after: Record<string, unknown>,\n): string {\n const keys = new Set([...Object.keys(before), ...Object.keys(after)])\n const changed: string[] = []\n for (const k of keys) {\n if (JSON.stringify(before[k]) !== JSON.stringify(after[k])) changed.push(k)\n }\n return changed.length === 0 ? 'attributes differ' : `fields changed: ${changed.sort().join(', ')}`\n}\n\nexport interface StaleEdgesInput {\n limit?: number\n edgeType?: string\n project?: string\n}\n\ninterface StaleEventResponse {\n edgeId: string\n source: string\n target: string\n edgeType: string\n thresholdMs: number\n ageMs: number\n lastObserved: string\n transitionedAt: string\n}\n\nexport async function runStaleEdges(\n client: HttpClient,\n input: StaleEdgesInput,\n): Promise<VerbResult> {\n const params = new URLSearchParams()\n if (input.limit !== undefined) params.set('limit', String(input.limit))\n if (input.edgeType) params.set('edgeType', input.edgeType)\n const qs = params.size > 0 ? `?${params.toString()}` : ''\n const body = await client.get<{ count: number; total: number; events: StaleEventResponse[] }>(\n projectPath(input.project, `/stale-events${qs}`),\n )\n const events = body.events\n if (events.length === 0) {\n return {\n summary: input.edgeType\n ? `No stale ${input.edgeType} edges recorded.`\n : 'No stale-edge transitions recorded yet.',\n }\n }\n const blockLines = events.map(\n (e) =>\n ` ${e.transitionedAt} — ${e.source} -[${e.edgeType}]-> ${e.target}` +\n ` (last seen ${e.lastObserved}, threshold ${formatDuration(e.thresholdMs)})`,\n )\n return {\n summary: `${events.length} stale-edge transition${events.length === 1 ? '' : 's'} recorded${input.edgeType ? ` for ${input.edgeType}` : ''}.`,\n block: blockLines.join('\\n'),\n provenance: Provenance.STALE,\n }\n}\n\nexport interface PoliciesInput {\n nodeId?: string\n policyId?: string\n hypotheticalAction?: HypotheticalAction\n project?: string\n}\n\ninterface PoliciesCheckResponse {\n allowed: boolean\n hypotheticalAction?: HypotheticalAction\n violations: PolicyViolation[]\n}\n\nexport async function runPolicies(\n client: HttpClient,\n input: PoliciesInput,\n): Promise<VerbResult> {\n let violations: PolicyViolation[]\n let allowed = true\n let hypothetical: HypotheticalAction | undefined\n\n if (input.hypotheticalAction) {\n if (typeof client.post !== 'function') {\n throw new Error('HttpClient does not support POST — required for policies dry-run')\n }\n const body = await client.post<PoliciesCheckResponse>(\n projectPath(input.project, '/policies/check'),\n { hypotheticalAction: input.hypotheticalAction },\n )\n violations = body.violations\n allowed = body.allowed\n hypothetical = body.hypotheticalAction\n } else {\n const params = new URLSearchParams()\n if (input.policyId) params.set('policyId', input.policyId)\n const qs = params.size > 0 ? `?${params.toString()}` : ''\n const body = await client.get<{ violations: PolicyViolation[] }>(\n projectPath(input.project, `/policies/violations${qs}`),\n )\n violations = body.violations\n allowed = violations.every((v) => v.onViolation !== 'block')\n }\n\n // Optional --node filter is applied here against the returned set; the\n // server-side endpoint doesn't take a node-id query yet.\n if (input.nodeId) {\n violations = violations.filter(\n (v) => v.subject.nodeId === input.nodeId || v.subject.path?.includes(input.nodeId!),\n )\n }\n\n if (violations.length === 0) {\n return {\n summary: hypothetical\n ? `No violations would result from the hypothetical action (${hypothetical.kind}).`\n : 'No policy violations recorded.',\n }\n }\n\n const blockCount = violations.filter((v) => v.onViolation === 'block').length\n const summaryParts: string[] = []\n if (hypothetical) {\n summaryParts.push(\n `Hypothetical ${hypothetical.kind} would surface ${violations.length} violation${violations.length === 1 ? '' : 's'}`,\n )\n } else {\n summaryParts.push(\n `${violations.length} policy violation${violations.length === 1 ? '' : 's'} currently recorded`,\n )\n }\n if (blockCount > 0) summaryParts.push(`${blockCount} of which block`)\n if (!allowed && hypothetical) summaryParts.push('action denied')\n const summary = summaryParts.join('; ') + '.'\n\n const blockLines = violations.map((v) => {\n const subject = v.subject.nodeId ?? v.subject.edgeId ?? v.subject.path?.[0] ?? '(global)'\n return ` • [${v.severity}/${v.onViolation}] ${v.policyName}: ${v.message} — ${subject}`\n })\n const severities = [...new Set(violations.map((v) => v.severity))]\n return {\n summary,\n block: blockLines.join('\\n'),\n confidence: hypothetical ? 0.7 : 1,\n provenance: severities.join(' '),\n }\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// divergences (ADR-060) — the tenth verb. Amends ADR-050's nine-verb\n// allowlist; the verb mirrors the get_divergences MCP tool.\n// ──────────────────────────────────────────────────────────────────────────\n\nexport interface DivergencesInput {\n type?: ReadonlyArray<DivergenceType>\n minConfidence?: number\n node?: string\n project?: string\n}\n\nfunction formatDivergenceLine(d: Divergence): string {\n switch (d.type) {\n case 'missing-observed':\n case 'missing-extracted':\n return ` • [${d.type}] ${d.source} → ${d.target} (${d.edgeType}) — confidence ${d.confidence.toFixed(2)}`\n case 'version-mismatch':\n return ` • [${d.type}] ${d.source} → ${d.target} — declared ${d.extractedVersion}, observed engine ${d.observedVersion} (${d.compatibility})`\n case 'host-mismatch':\n return ` • [${d.type}] ${d.source} → ${d.target} — declared host ${d.extractedHost}, observed host ${d.observedHost}`\n case 'compat-violation':\n return ` • [${d.type}] ${d.source} → ${d.target} — ${d.rule.kind}${d.rule.package ? ` (${d.rule.package})` : ''}`\n }\n}\n\nexport async function runDivergences(\n client: HttpClient,\n input: DivergencesInput,\n): Promise<VerbResult> {\n const params = new URLSearchParams()\n if (input.type && input.type.length > 0) params.set('type', input.type.join(','))\n if (input.minConfidence !== undefined) {\n params.set('minConfidence', String(input.minConfidence))\n }\n if (input.node) params.set('node', input.node)\n const qs = params.size > 0 ? `?${params.toString()}` : ''\n const result = await client.get<DivergenceResult>(\n projectPath(input.project, `/graph/divergences${qs}`),\n )\n if (result.totalAffected === 0) {\n return {\n summary:\n 'No divergences found between the declared (EXTRACTED) and observed (OBSERVED) views of the graph.',\n }\n }\n const headline = result.divergences[0]!\n const summary =\n `Found ${result.totalAffected} divergence${result.totalAffected === 1 ? '' : 's'} between code and production. ` +\n `Highest-confidence: ${headline.type} on ${headline.source} → ${headline.target}. ${headline.reason}`\n const blockLines: string[] = []\n for (const d of result.divergences) {\n blockLines.push(formatDivergenceLine(d))\n blockLines.push(` reason: ${d.reason}`)\n blockLines.push(` recommendation: ${d.recommendation}`)\n }\n const maxConfidence = result.divergences.reduce(\n (m, d) => Math.max(m, d.confidence),\n 0,\n )\n return {\n summary,\n block: blockLines.join('\\n'),\n confidence: maxConfidence,\n provenance: 'composite (EXTRACTED + OBSERVED)',\n }\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Output formatting (ADR-050 #3)\n// ──────────────────────────────────────────────────────────────────────────\n\nfunction formatFooter(\n confidence: number | undefined,\n provenance: string | string[] | undefined,\n): string {\n const c = confidence === undefined ? 'n/a' : confidence.toFixed(2)\n const p =\n provenance === undefined\n ? 'n/a'\n : Array.isArray(provenance)\n ? [...new Set(provenance)].join(', ')\n : provenance\n return `confidence: ${c} · provenance: ${p}`\n}\n\n// Default human output (NL summary + table-shaped block + footer). Mirrors\n// the three-part MCP response from ADR-039 in plain text.\nexport function formatHuman(result: VerbResult): string {\n const sections: string[] = [result.summary.trim()]\n if (result.block && result.block.trim().length > 0) sections.push(result.block.trimEnd())\n sections.push(formatFooter(result.confidence, result.provenance))\n return sections.join('\\n\\n')\n}\n\n// `--json` output. Same three sections as named fields per ADR-050 #3.\nexport function formatJson(result: VerbResult): string {\n return JSON.stringify(\n {\n summary: result.summary,\n block: result.block ?? '',\n confidence: result.confidence ?? null,\n provenance: result.provenance ?? null,\n },\n null,\n 2,\n )\n}\n\n// Exit-code mapping for thrown errors (ADR-050 #4):\n// 0 — success (handled at the call site, never via throw)\n// 1 — server error (HttpError)\n// 2 — misuse (handled in cli.ts before any network call)\n// 3 — daemon unreachable (TransportError)\nexport function exitCodeForError(err: unknown): number {\n if (err instanceof TransportError) return 3\n if (err instanceof HttpError) return 1\n return 1\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Snapshot push (ADR-074 §1)\n//\n// `neat sync` (local + --to <url>) feeds the freshly extracted snapshot into\n// either the local daemon or a remote one. The endpoint is dual-mounted via\n// registerRoutes — default project lands at /snapshot, named projects at\n// /projects/:project/snapshot. The helper goes through the shared\n// HttpClient so the verb stays on the same network path as every query verb.\n// ──────────────────────────────────────────────────────────────────────────\n\nexport interface PushSnapshotInput {\n baseUrl: string\n token: string | undefined\n project: string\n snapshot: unknown\n}\n\nexport interface PushSnapshotResult {\n project: string\n nodesAdded: number\n edgesAdded: number\n nodeCount: number\n edgeCount: number\n}\n\nexport function createSnapshotPushClient(\n baseUrl: string,\n token: string | undefined,\n): HttpClient {\n return createHttpClient(baseUrl, token && token.length > 0 ? token : undefined)\n}\n\nexport async function pushSnapshotToRemote(\n input: PushSnapshotInput,\n): Promise<PushSnapshotResult> {\n const client = createSnapshotPushClient(input.baseUrl, input.token)\n if (typeof client.post !== 'function') {\n throw new Error('HttpClient does not support POST — required for snapshot push')\n }\n return client.post<PushSnapshotResult>(\n `/projects/${encodeURIComponent(input.project)}/snapshot`,\n { snapshot: input.snapshot },\n )\n}\n"],"mappings":"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","names":["path","fs","fs","path","path","fs","fs","path","renderOtelEnvBlock","fs","path","path","fs","fs","path","SDK_PACKAGES","OTEL_ENV","exists","detect","plan","apply","rollback","plan","plan","fs","path","spawn","path","plan","entry","projects","spawn","fs","path","Provenance","path","entry","path","checkDaemonHealth","path","plan","fs","entry","apply","renderOtelEnvBlock"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/gitignore.ts","../src/summary.ts","../src/watch.ts","../src/deploy/detect.ts","../src/installers/javascript.ts","../src/installers/templates.ts","../src/installers/python.ts","../src/installers/shared.ts","../src/installers/index.ts","../src/orchestrator.ts","../src/cli-verbs.ts","../src/cli-client.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport path from 'node:path'\nimport { promises as fs, readFileSync } from 'node:fs'\nimport { fileURLToPath } from 'node:url'\nimport { DEFAULT_PROJECT, getGraph, resetGraph } from './graph.js'\nimport { extractFromDirectory } from './extract.js'\nimport {\n formatExtractionBanner,\n formatPrecisionFloorBanner,\n isStrictExtractionEnabled,\n} from './extract/errors.js'\nimport { discoverServices } from './extract/services.js'\nimport type { DiscoveredService } from './extract/shared.js'\nimport { computeDivergences } from './divergences.js'\nimport { saveGraphToDisk } from './persist.js'\nimport { ensureNeatOutIgnored } from './gitignore.js'\nimport { renderValueForwardSummary } from './summary.js'\nimport { startWatch, type WatchHandle } from './watch.js'\nimport { runDeploy, renderOtelEnvBlock } from './deploy/detect.js'\nimport { pathsForProject } from './projects.js'\nimport {\n addProject,\n listProjects,\n ProjectNameCollisionError,\n removeProject,\n setStatus,\n} from './registry.js'\nimport {\n INSTALLERS,\n isEmptyPlan,\n pickInstaller,\n renderPatch,\n type InstallPlan,\n type PatchSection,\n} from './installers/index.js'\nimport { runOrchestrator } from './orchestrator.js'\nimport { runSync } from './cli-verbs.js'\nimport { DivergenceTypeSchema, type DivergenceType } from '@neat.is/types'\nimport {\n createHttpClient,\n exitCodeForError,\n formatHuman,\n formatJson,\n HttpError,\n runBlastRadius,\n runDependencies,\n runDiff,\n runDivergences,\n runIncidents,\n runObservedDependencies,\n runPolicies,\n runRootCause,\n runSearch,\n runStaleEdges,\n TransportError,\n type VerbResult,\n} from './cli-client.js'\n\nexport interface InitOptions {\n scanPath: string\n outPath: string\n // The project's registry name. Defaults to the basename of the scan path\n // when the user didn't pass `--project` (ADR-046 — project naming).\n project: string\n // Whether `project` was set explicitly via `--project`. The flag affects\n // which in-memory graph slot we use: explicit names get isolated slots\n // per ADR-026, the default basename keeps using DEFAULT_PROJECT for\n // back-compat with `neat watch`.\n projectExplicit: boolean\n apply: boolean\n dryRun: boolean\n noInstall: boolean\n // ADR-073 §5 — when true, append the per-type node/edge breakdown after\n // the value-forward findings block. Default false.\n verbose: boolean\n}\n\nexport interface InitResult {\n // Process exit code. 0 on success, 1 on collision / runtime failure,\n // 2 on misuse (handled before we get here, but documented for completeness).\n exitCode: number\n // Paths the run actually wrote to. Empty in `--dry-run` except for\n // `neat.patch`. Useful for tests asserting \"init only wrote X\".\n writtenFiles: string[]\n}\n\nfunction usage(): void {\n console.log('usage: neat <command> [args] [--project <name>]')\n console.log('')\n console.log('lifecycle commands:')\n console.log(' init <path> One-time install: discover, extract, register, plan SDK install.')\n console.log(' Snapshot lands in <path>/neat-out/graph.json by default')\n console.log(' (or <path>/neat-out/<project>.json for non-default).')\n console.log(' Flags:')\n console.log(' --apply run the SDK install patch in place')\n console.log(' --dry-run write only neat.patch; do not register or snapshot')\n console.log(' --no-install skip SDK install planning entirely')\n console.log(' watch <path> Start neat-core, watch <path>, re-extract on changes.')\n console.log(' PORT (default 8080), OTEL_PORT (4318), HOST (0.0.0.0)')\n console.log(' control listeners. NEAT_OTLP_GRPC=true also opens 4317.')\n console.log(' list List every project registered in the machine-level registry.')\n console.log(' pause <name> Mark a project paused — daemon stops watching until resumed.')\n console.log(' resume <name> Mark a project active again.')\n console.log(' uninstall <name>')\n console.log(' Remove a project from the registry. Does not touch')\n console.log(' neat-out/, policy.json, or any user file.')\n console.log(' version Print the installed @neat.is/core version and exit.')\n console.log(' Aliases: --version, -v.')\n console.log(' skill Install or print the Claude Code MCP drop-in.')\n console.log(' Flags:')\n console.log(' --print-config print the JSON snippet to stdout')\n console.log(' --apply merge mcpServers.neat into ~/.claude.json')\n console.log(' deploy Detect the deploy substrate, generate NEAT_AUTH_TOKEN,')\n console.log(' emit a docker-compose / systemd / docker run artifact, and')\n console.log(' print the OTel env-vars block to paste into your platform.')\n console.log(' sync Re-run discovery, extraction, and SDK apply against the')\n console.log(' registered project, then notify the running daemon.')\n console.log(' Flags:')\n console.log(' --project <name> target a registered project by name')\n console.log(' --to <url> push the snapshot to a remote daemon')\n console.log(' --token <token> bearer token for --to (or $NEAT_REMOTE_TOKEN)')\n console.log(' --dry-run run extraction in-memory; do not write')\n console.log(' --no-instrument skip the SDK install apply step')\n console.log(' --json emit the delta summary as JSON')\n console.log('')\n console.log('query commands (mirror the MCP tools, ADR-050):')\n console.log(' root-cause <node-id> Walk inbound edges to find what broke first.')\n console.log(' example: neat root-cause service:<name>')\n console.log(' blast-radius <node-id> BFS outbound — what would break if this dies.')\n console.log(' example: neat blast-radius database:<host>')\n console.log(' dependencies <node-id> Transitive outbound dependencies.')\n console.log(' Flags: --depth N (default 3, max 10)')\n console.log(' example: neat dependencies service:<name> --depth 2')\n console.log(' observed-dependencies <node-id> OBSERVED-only outbound edges (runtime traffic).')\n console.log(' example: neat observed-dependencies service:<name>')\n console.log(' incidents [<node-id>] Recent error events; per-node when an id is given.')\n console.log(' Flags: --limit N (default 20)')\n console.log(' example: neat incidents service:<name> --limit 5')\n console.log(' search <query> Semantic (or substring) match on node names/ids.')\n console.log(' example: neat search \"checkout\"')\n console.log(' diff --against <snapshot> Compare the live graph to a saved snapshot.')\n console.log(' example: neat diff --against ./snapshots/baseline.json')\n console.log(' stale-edges Recent OBSERVED → STALE transitions.')\n console.log(' Flags: --limit N, --edge-type CALLS|CONNECTS_TO|...')\n console.log(' example: neat stale-edges --edge-type CALLS')\n console.log(' policies Current policy violations.')\n console.log(' Flags: --node <id>, --hypothetical-action <json>')\n console.log(' example: neat policies --node service:<name> --json')\n console.log(' divergences Where code (EXTRACTED) and production (OBSERVED) disagree.')\n console.log(' Flags: --type <list>, --min-confidence <0..1>, --node <id>')\n console.log(' example: neat divergences --min-confidence 0.7')\n console.log('')\n console.log('flags:')\n console.log(' --project <name> Name the project this command targets. Default: \"default\".')\n console.log(' --json Emit machine-readable JSON instead of human text. Query verbs only.')\n console.log('')\n console.log('exit codes:')\n console.log(' 0 success')\n console.log(' 1 server error (4xx/5xx body printed to stderr)')\n console.log(' 2 misuse (missing args, bad flags) — handled before any network call')\n console.log(' 3 environmental — daemon unreachable, or one of ports 8080 / 4318 / 6328')\n console.log(' is held by another process when `neat <path>` tries to spawn the daemon')\n console.log('')\n console.log('environment:')\n console.log(' NEAT_API_URL base URL for the core REST API (default http://localhost:8080)')\n console.log(' NEAT_PROJECT project name when --project isn\\'t passed')\n}\n\n// Tiny argv parser — pulls `--project <name>`, the v0.2.5 init flags, and\n// the v0.2.8 verb flags out of `rest`. Boolean / value flags are surfaced\n// unconditionally; per-command validation lives in `main`.\ninterface ParsedArgs {\n project: string | null\n apply: boolean\n dryRun: boolean\n noInstall: boolean\n noInstrument: boolean\n noOpen: boolean\n yes: boolean\n verbose: boolean\n printConfig: boolean\n json: boolean\n depth: number | null\n limit: number | null\n edgeType: string | null\n node: string | null\n since: string | null\n against: string | null\n errorId: string | null\n hypotheticalAction: string | null\n type: string | null\n minConfidence: number | null\n // `neat sync` (ADR-074 §1) — remote daemon URL + bearer token.\n to: string | null\n token: string | null\n positional: string[]\n}\n\n// String-valued flags supported across the verb surface. Each entry maps the\n// canonical `--flag` name (and its `--flag=` equivalent) to the parsed-args\n// field that receives it. Centralising the table keeps misuse diagnostics\n// (exit code 2) consistent across verbs.\nconst STRING_FLAGS = [\n ['--project', 'project'],\n ['--depth', 'depth'],\n ['--limit', 'limit'],\n ['--edge-type', 'edgeType'],\n ['--node', 'node'],\n ['--since', 'since'],\n ['--against', 'against'],\n ['--error-id', 'errorId'],\n ['--hypothetical-action', 'hypotheticalAction'],\n ['--type', 'type'],\n ['--min-confidence', 'minConfidence'],\n ['--to', 'to'],\n ['--token', 'token'],\n] as const\n\nfunction parseArgs(rest: string[]): ParsedArgs {\n const positional: string[] = []\n const out: ParsedArgs = {\n project: null,\n apply: false,\n dryRun: false,\n noInstall: false,\n noInstrument: false,\n noOpen: false,\n yes: false,\n verbose: false,\n printConfig: false,\n json: false,\n depth: null,\n limit: null,\n edgeType: null,\n node: null,\n since: null,\n against: null,\n errorId: null,\n hypotheticalAction: null,\n type: null,\n minConfidence: null,\n to: null,\n token: null,\n positional: [],\n }\n for (let i = 0; i < rest.length; i++) {\n const arg = rest[i] as string\n\n // Boolean flags first.\n if (arg === '--apply') { out.apply = true; continue }\n if (arg === '--dry-run') { out.dryRun = true; continue }\n if (arg === '--no-install') { out.noInstall = true; continue }\n if (arg === '--no-instrument') { out.noInstrument = true; continue }\n if (arg === '--no-open') { out.noOpen = true; continue }\n if (arg === '--yes' || arg === '-y') { out.yes = true; continue }\n if (arg === '--verbose') { out.verbose = true; continue }\n if (arg === '--print-config') { out.printConfig = true; continue }\n if (arg === '--json') { out.json = true; continue }\n\n // String/number flags via the shared table.\n let matched = false\n for (const [flag, field] of STRING_FLAGS) {\n if (arg === flag) {\n const next = rest[i + 1]\n if (next === undefined) {\n console.error(`neat: ${flag} requires a value`)\n process.exit(2)\n }\n assignFlag(out, field, next)\n i++\n matched = true\n break\n }\n if (arg.startsWith(`${flag}=`)) {\n assignFlag(out, field, arg.slice(flag.length + 1))\n matched = true\n break\n }\n }\n if (matched) continue\n positional.push(arg)\n }\n out.positional = positional\n return out\n}\n\nexport { parseArgs }\n\n// Number flags get parsed at assignment time so misuse (`--depth foo`)\n// surfaces with exit code 2 before any network call.\nfunction assignFlag(out: ParsedArgs, field: (typeof STRING_FLAGS)[number][1], value: string): void {\n if (field === 'depth' || field === 'limit') {\n const n = Number(value)\n if (!Number.isFinite(n) || !Number.isInteger(n) || n < 1) {\n console.error(`neat: --${field === 'depth' ? 'depth' : 'limit'} must be a positive integer`)\n process.exit(2)\n }\n out[field] = n\n return\n }\n if (field === 'minConfidence') {\n const n = Number(value)\n if (!Number.isFinite(n) || n < 0 || n > 1) {\n console.error('neat: --min-confidence must be a number in [0, 1]')\n process.exit(2)\n }\n out.minConfidence = n\n return\n }\n // String fields.\n ;(out as unknown as Record<string, unknown>)[field] = value\n}\n\n// Per-type node/edge counts + compat formatting moved into summary.ts as\n// part of the value-forward findings block (issue #305 / ADR-073 §5).\n\n// The `neat --version` family reads its answer from the bundled package's\n// own package.json. Reading at run time keeps the published bin in lockstep\n// with whatever version `tsup` shipped without a build-time substitution.\n// `dist/cli.cjs` sits one level below the package root.\nexport function readPackageVersion(): string {\n const here =\n typeof __dirname !== 'undefined'\n ? __dirname\n : path.dirname(fileURLToPath(import.meta.url))\n // dist/ → package root. tsup writes both cjs and mjs to dist/, so the\n // parent-of-parent walk is the same in either format.\n const candidates = [\n path.resolve(here, '../package.json'),\n path.resolve(here, '../../package.json'),\n ]\n for (const candidate of candidates) {\n try {\n const raw = readFileSync(candidate, 'utf8')\n const parsed = JSON.parse(raw) as { name?: string; version?: string }\n if (parsed.name === '@neat.is/core' && typeof parsed.version === 'string') {\n return parsed.version\n }\n } catch {\n // try the next candidate\n }\n }\n return 'unknown'\n}\n\nfunction printVersion(): void {\n process.stdout.write(`${readPackageVersion()}\\n`)\n}\n\nfunction printBanner(): void {\n console.log('███╗ ██╗███████╗ █████╗ ████████╗')\n console.log('████╗ ██║██╔════╝██╔══██╗╚══██╔══╝')\n console.log('██╔██╗ ██║█████╗ ███████║ ██║ ')\n console.log('██║╚██╗██║██╔══╝ ██╔══██║ ██║ ')\n console.log('██║ ╚████║███████╗██║ ██║ ██║ ')\n console.log('╚═╝ ╚═══╝╚══════╝╚═╝ ╚═╝ ╚═╝ ')\n console.log('')\n console.log(' Network Expressive Architecting Tool')\n console.log(' neat.is · v0.4.0 · Apache 2.0')\n console.log('')\n}\n\nfunction printDiscoveryReport(opts: InitOptions, services: DiscoveredService[]): void {\n const languages = [...new Set(services.map((s) => s.node.language))].sort()\n const mode = opts.dryRun ? 'dry-run' : opts.apply ? 'apply' : 'patch-only'\n printBanner()\n console.log('=== neat init: discovery ===')\n console.log(`scan path: ${opts.scanPath}`)\n console.log(`project: ${opts.project}`)\n console.log(`mode: ${mode}`)\n console.log(`services: ${services.length}`)\n for (const s of services) {\n const where = s.node.repoPath && s.node.repoPath.length > 0 ? s.node.repoPath : '.'\n console.log(` - ${s.node.name} (${s.node.language}) — ${where}`)\n }\n console.log(`languages: ${languages.length > 0 ? languages.join(', ') : '(none)'}`)\n if (opts.noInstall) {\n console.log('install: skipped (--no-install)')\n } else if (opts.dryRun) {\n console.log('install: patch will be written to neat.patch; nothing else.')\n } else if (opts.apply) {\n console.log('install: patch will be applied in place. Run `npm install` afterwards.')\n } else {\n console.log('install: patch will be written to neat.patch for review.')\n }\n console.log('')\n}\n\nasync function buildPatchSections(\n services: DiscoveredService[],\n project: string,\n): Promise<PatchSection[]> {\n const sections: PatchSection[] = []\n for (const svc of services) {\n const installer = await pickInstaller(svc.dir)\n if (!installer) continue\n // v0.4.1 / refs #339 — pass the registered project name so the per-\n // package `.env.neat` carries `OTEL_SERVICE_NAME=<project>`. The daemon\n // routes spans by registered project name; matching keys end-to-end\n // is what keeps OBSERVED edges landing.\n const plan: InstallPlan = await installer.plan(svc.dir, { project })\n // Lib-only + runtime-kind-skipped packages keep a section so the dry-run\n // patch documents the skip and the apply summary counts them (ADR-069 §2,\n // v0.4.4 / #370). Empty plans without either flag are already-instrumented\n // end-to-end and drop out.\n if (isEmptyPlan(plan) && !plan.libOnly && plan.runtimeKind === undefined) continue\n sections.push({ installer: installer.name, plan })\n }\n return sections\n}\n\nexport async function runInit(opts: InitOptions): Promise<InitResult> {\n const written: string[] = []\n\n // ── Step 1: validate path ────────────────────────────────────────────\n const stat = await fs.stat(opts.scanPath).catch(() => null)\n if (!stat || !stat.isDirectory()) {\n console.error(`neat init: ${opts.scanPath} is not a directory`)\n return { exitCode: 2, writtenFiles: written }\n }\n\n // ── Step 2: discovery (ADR-046 #2 — before any mutation) ─────────────\n const services = await discoverServices(opts.scanPath)\n printDiscoveryReport(opts, services)\n\n // ── Step 3: plan SDK install (pure data, no fs writes) ───────────────\n const sections = opts.noInstall ? [] : await buildPatchSections(services, opts.project)\n const patch = renderPatch(sections)\n const patchPath = path.join(opts.scanPath, 'neat.patch')\n\n // ── Step 4: dry-run shortcut — only neat.patch is allowed to land ────\n if (opts.dryRun) {\n await fs.writeFile(patchPath, patch, 'utf8')\n written.push(patchPath)\n console.log(`dry-run: patch written to ${patchPath}`)\n // ADR-073 §6 — list the planned `.gitignore` write alongside the other\n // planned writes. No file mutation in dry-run; only the announcement.\n const gitignorePath = path.join(opts.scanPath, '.gitignore')\n const gitignoreExists = await fs.stat(gitignorePath).then(() => true).catch(() => false)\n const verb = gitignoreExists ? 'append' : 'create'\n console.log(`dry-run: would ${verb} ${gitignorePath} (add neat-out/)`)\n console.log('rerun without --dry-run to register and snapshot.')\n return { exitCode: 0, writtenFiles: written }\n }\n\n // ── Step 5: extraction + snapshot ────────────────────────────────────\n // Use DEFAULT_PROJECT for the in-memory graph slot when --project wasn't\n // explicitly passed; named projects get isolated slots per ADR-026.\n const graphKey = opts.projectExplicit ? opts.project : DEFAULT_PROJECT\n resetGraph(graphKey)\n const graph = getGraph(graphKey)\n // ADR-065 — per-file extraction failures land alongside the snapshot in\n // <projectDir>/neat-out/errors.ndjson. Same file as OTel error events\n // (ADR-033) with a `source: 'extract'` discriminator.\n const projectPaths = pathsForProject(\n graphKey,\n path.join(opts.scanPath, 'neat-out'),\n )\n const errorsPath = path.join(path.dirname(opts.outPath), path.basename(projectPaths.errorsPath))\n const result = await extractFromDirectory(graph, opts.scanPath, { errorsPath })\n await saveGraphToDisk(graph, opts.outPath)\n written.push(opts.outPath)\n\n // ADR-073 §6 — ensure `neat-out/` is git-ignored. Snapshot just landed on\n // disk; an un-ignored neat-out/ would leak into git history on the next\n // commit. Idempotent: the helper no-ops when the line is already present.\n const gitignoreResult = await ensureNeatOutIgnored(opts.scanPath)\n if (gitignoreResult.action !== 'unchanged') {\n written.push(gitignoreResult.file)\n }\n\n // ── Step 6: register in the machine-level registry ───────────────────\n // Idempotent re-init of the same path under the same name refreshes the\n // entry; collision against a different path exits non-zero (ADR-046 #7).\n const languages = [...new Set(services.map((s) => s.node.language))].sort()\n let currentProjectName = opts.project\n try {\n const entry = await addProject({\n name: opts.project,\n path: opts.scanPath,\n languages,\n status: 'active',\n })\n currentProjectName = entry.name\n } catch (err) {\n if (err instanceof ProjectNameCollisionError) {\n console.error(`neat init: ${err.message}`)\n console.error('pass --project <other-name> to register under a different name.')\n return { exitCode: 1, writtenFiles: written }\n }\n throw err\n }\n\n // Narrow the active-project surface to the project the operator just\n // registered. Mirrors the bare-orchestrator behaviour so `neat init` and\n // `neat <path>` agree on the activation contract.\n const siblings = await listProjects()\n const paused: string[] = []\n for (const p of siblings) {\n if (p.name !== currentProjectName && p.status === 'active') {\n await setStatus(p.name, 'paused')\n paused.push(p.name)\n }\n }\n if (paused.length > 0) {\n const plural = paused.length === 1 ? '' : 's'\n console.log(\n `neat: paused ${paused.length} sibling project${plural}; run \\`neat resume <name>\\` to bring one back active.`,\n )\n }\n\n // ── Step 7: write or apply patch ─────────────────────────────────────\n if (!opts.noInstall) {\n if (opts.apply) {\n let instrumented = 0\n let alreadyInstrumented = 0\n let libOnly = 0\n let browserBundle = 0\n let reactNative = 0\n for (const section of sections) {\n const installer = INSTALLERS.find((i) => i.name === section.installer)\n if (!installer) continue\n const outcome = await installer.apply(section.plan)\n if (outcome.outcome === 'instrumented') {\n instrumented++\n for (const f of outcome.writtenFiles) written.push(f)\n } else if (outcome.outcome === 'already-instrumented') {\n alreadyInstrumented++\n } else if (outcome.outcome === 'lib-only') {\n libOnly++\n } else if (outcome.outcome === 'browser-bundle') {\n browserBundle++\n console.log(`skipping ${section.plan.serviceDir}: browser bundle; browser-OTel support lands in a future release.`)\n } else if (outcome.outcome === 'react-native') {\n reactNative++\n console.log(`skipping ${section.plan.serviceDir}: React Native target; browser-OTel support lands in a future release.`)\n }\n }\n if (sections.length > 0) {\n console.log('')\n const parts = [\n `instrumented ${instrumented}`,\n `already-instrumented ${alreadyInstrumented}`,\n `lib-only ${libOnly}`,\n ]\n if (browserBundle > 0) parts.push(`browser-bundle ${browserBundle}`)\n if (reactNative > 0) parts.push(`react-native ${reactNative}`)\n console.log(`apply: ${parts.join(', ')}`)\n console.log('Run `npm install` (or your language equivalent) to refresh lockfiles.')\n }\n } else {\n await fs.writeFile(patchPath, patch, 'utf8')\n written.push(patchPath)\n }\n }\n\n // ── Step 8: summary + incompatibilities ──────────────────────────────\n // ADR-073 §5 / issue #305 — findings-first: compat violations, top\n // divergences, services without OBSERVED coverage, then the OTel env-vars\n // block. Per-type counts ride behind `--verbose`.\n console.log('')\n console.log(`snapshot: ${opts.outPath}`)\n console.log(`added: ${result.nodesAdded} nodes, ${result.edgesAdded} edges`)\n console.log('')\n const divergenceResult = computeDivergences(graph)\n console.log(\n renderValueForwardSummary({\n graph,\n divergences: divergenceResult.divergences,\n verbose: opts.verbose,\n }),\n )\n // ADR-065 — loud failure mode banner. Unconditional; 0 is a positive\n // signal. When errors > 0, also surface the sidecar path so the operator\n // can read per-file detail.\n console.log(formatExtractionBanner(result.extractionErrors))\n if (result.extractionErrors > 0) {\n console.log(`errors: ${errorsPath}`)\n }\n // ADR-066 — precision-floor drop banner. Always emitted; 0 is observable\n // as a positive signal that no cross-service heuristic edges grew the\n // graph this pass.\n console.log(formatPrecisionFloorBanner(result.extractedDropped))\n\n // ADR-065 — NEAT_STRICT_EXTRACTION=1 makes any per-file failure exit\n // non-zero. Default is forgiving (banner only). Exit code 4 keeps\n // misuse (2) and daemon-down (3) distinguishable per the CLI contract.\n if (result.extractionErrors > 0 && isStrictExtractionEnabled()) {\n return { exitCode: 4, writtenFiles: written }\n }\n\n return { exitCode: 0, writtenFiles: written }\n}\n\n// ── Claude Code skill (ADR-049 / v0.2.5 step 6) ────────────────────────\n//\n// The skill is a one-shot MCP-config drop-in. Source of truth for the\n// snippet lives here (the @neat.is/claude-skill package's\n// claude_code_config.json holds an identical copy for documentation; a\n// contract test keeps the two byte-aligned).\nexport const CLAUDE_SKILL_CONFIG = {\n mcpServers: {\n neat: {\n type: 'stdio' as const,\n command: 'npx',\n args: ['-y', '@neat.is/mcp'],\n env: {\n NEAT_API_URL: 'http://localhost:8080',\n },\n },\n },\n}\n\nfunction claudeConfigPath(): string {\n // ~/.claude.json is Claude Code's user-level MCP config. Tests override\n // via NEAT_CLAUDE_CONFIG so they don't touch the real file.\n const override = process.env.NEAT_CLAUDE_CONFIG\n if (override && override.length > 0) return path.resolve(override)\n const home = process.env.HOME ?? process.env.USERPROFILE ?? ''\n return path.join(home, '.claude.json')\n}\n\nexport interface SkillOptions {\n apply: boolean\n printConfig: boolean\n}\n\nexport async function runSkill(opts: SkillOptions): Promise<{ exitCode: number }> {\n const snippet = JSON.stringify(CLAUDE_SKILL_CONFIG, null, 2) + '\\n'\n\n if (opts.printConfig) {\n process.stdout.write(snippet)\n return { exitCode: 0 }\n }\n\n if (opts.apply) {\n const target = claudeConfigPath()\n let existing: Record<string, unknown> = {}\n try {\n existing = JSON.parse(await fs.readFile(target, 'utf8'))\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {\n console.error(`neat skill: failed to read ${target} — ${(err as Error).message}`)\n return { exitCode: 1 }\n }\n }\n // Merge mcpServers.neat without disturbing other entries the user\n // might have wired up by hand.\n const mcp =\n (existing as { mcpServers?: Record<string, unknown> }).mcpServers ?? {}\n const merged = {\n ...existing,\n mcpServers: { ...mcp, neat: CLAUDE_SKILL_CONFIG.mcpServers.neat },\n }\n await fs.mkdir(path.dirname(target), { recursive: true })\n await fs.writeFile(target, JSON.stringify(merged, null, 2) + '\\n', 'utf8')\n console.log(`neat skill: wrote mcpServers.neat to ${target}`)\n console.log('restart Claude Code to pick up the new MCP server.')\n return { exitCode: 0 }\n }\n\n console.log('neat skill — Claude Code MCP drop-in for NEAT')\n console.log('')\n console.log(' --print-config print the JSON snippet to stdout')\n console.log(' --apply merge mcpServers.neat into ~/.claude.json')\n console.log('')\n console.log('Manual install: copy mcpServers.neat from --print-config into ~/.claude.json,')\n console.log('then restart Claude Code. See packages/claude-skill/SKILL.md for the tool list.')\n return { exitCode: 0 }\n}\n\nasync function main(): Promise<void> {\n const [, , cmd, ...rest] = process.argv\n\n if (!cmd || cmd === '-h' || cmd === '--help') {\n usage()\n process.exit(0)\n }\n\n if (cmd === '--version' || cmd === '-v' || cmd === 'version') {\n printVersion()\n process.exit(0)\n }\n\n const parsed = parseArgs(rest)\n const { positional, apply, dryRun, noInstall } = parsed\n const project = parsed.project ?? DEFAULT_PROJECT\n\n if (cmd === 'init') {\n const target = positional[0]\n if (!target) {\n console.error('neat init: missing <path>')\n usage()\n process.exit(2)\n }\n if (apply && dryRun) {\n console.error('neat init: --apply and --dry-run are mutually exclusive')\n process.exit(2)\n }\n const scanPath = path.resolve(target)\n // ADR-046 — when --project isn't passed, the registry name defaults to\n // the basename of the scan path. The in-memory graph slot stays on\n // DEFAULT_PROJECT (back-compat with existing `neat watch` invocations).\n const projectExplicit = parsed.project !== null\n const projectName = projectExplicit ? project : path.basename(scanPath)\n // Default project keeps writing to graph.json (ADR-026 back-compat);\n // named projects use <project>.json under the same neat-out directory.\n const projectKey = projectExplicit ? project : DEFAULT_PROJECT\n const fallback = pathsForProject(projectKey, path.join(scanPath, 'neat-out')).snapshotPath\n const outPath = path.resolve(process.env.NEAT_OUT_PATH ?? fallback)\n const result = await runInit({\n scanPath,\n outPath,\n project: projectName,\n projectExplicit,\n apply,\n dryRun,\n noInstall,\n verbose: parsed.verbose,\n })\n if (result.exitCode !== 0) process.exit(result.exitCode)\n return\n }\n\n if (cmd === 'watch') {\n const target = positional[0]\n if (!target) {\n console.error('neat watch: missing <path>')\n usage()\n process.exit(2)\n }\n const scanPath = path.resolve(target)\n const stat = await fs.stat(scanPath).catch(() => null)\n if (!stat || !stat.isDirectory()) {\n console.error(`neat watch: ${scanPath} is not a directory`)\n process.exit(2)\n }\n const projectPaths = pathsForProject(project, path.join(scanPath, 'neat-out'))\n const outPath = path.resolve(process.env.NEAT_OUT_PATH ?? projectPaths.snapshotPath)\n const errorsPath = path.resolve(\n process.env.NEAT_ERRORS_PATH ??\n path.join(path.dirname(outPath), path.basename(projectPaths.errorsPath)),\n )\n const staleEventsPath = path.resolve(\n process.env.NEAT_STALE_EVENTS_PATH ??\n path.join(path.dirname(outPath), path.basename(projectPaths.staleEventsPath)),\n )\n\n const embeddingsCachePath = process.env.NEAT_EMBEDDINGS_CACHE_PATH\n ? path.resolve(process.env.NEAT_EMBEDDINGS_CACHE_PATH)\n : undefined\n\n const handle: WatchHandle = await startWatch(getGraph(project), {\n scanPath,\n outPath,\n errorsPath,\n staleEventsPath,\n project,\n ...(embeddingsCachePath ? { embeddingsCachePath } : {}),\n host: process.env.HOST ?? '0.0.0.0',\n port: Number(process.env.PORT ?? 8080),\n otelPort: Number(process.env.OTEL_PORT ?? 4318),\n otelGrpc: process.env.NEAT_OTLP_GRPC === 'true',\n otelGrpcPort: process.env.NEAT_OTLP_GRPC_PORT\n ? Number(process.env.NEAT_OTLP_GRPC_PORT)\n : undefined,\n })\n\n // startPersistLoop already wires SIGTERM/SIGINT to flush + exit. Hook in\n // ahead of it so the watcher closes cleanly first; the persist handler's\n // `process.exit(0)` will still run after our stop() resolves.\n let shuttingDown = false\n const shutdown = (signal: NodeJS.Signals): void => {\n if (shuttingDown) return\n shuttingDown = true\n console.log(`neat watch: ${signal} received, stopping…`)\n void handle.stop().catch((err) => {\n console.error('neat watch: shutdown error', err)\n })\n }\n process.on('SIGTERM', shutdown)\n process.on('SIGINT', shutdown)\n return\n }\n\n if (cmd === 'list') {\n const projects = await listProjects()\n if (projects.length === 0) {\n console.log('no projects registered. run `neat init <path>` to register one.')\n return\n }\n for (const p of projects) {\n const seen = p.lastSeenAt ? p.lastSeenAt : 'never'\n const langs = p.languages.length > 0 ? p.languages.join(',') : '-'\n console.log(`${p.name}\\t${p.status}\\t${langs}\\t${p.path}\\tlast-seen=${seen}`)\n }\n return\n }\n\n if (cmd === 'pause') {\n const name = positional[0]\n if (!name) {\n console.error('neat pause: missing <name>')\n usage()\n process.exit(2)\n }\n try {\n const entry = await setStatus(name, 'paused')\n console.log(`paused: ${entry.name} (${entry.path})`)\n } catch (err) {\n console.error((err as Error).message)\n process.exit(1)\n }\n return\n }\n\n if (cmd === 'resume') {\n const name = positional[0]\n if (!name) {\n console.error('neat resume: missing <name>')\n usage()\n process.exit(2)\n }\n try {\n const entry = await setStatus(name, 'active')\n console.log(`resumed: ${entry.name} (${entry.path})`)\n } catch (err) {\n console.error((err as Error).message)\n process.exit(1)\n }\n return\n }\n\n if (cmd === 'skill') {\n const result = await runSkill({ apply: parsed.apply, printConfig: parsed.printConfig })\n if (result.exitCode !== 0) process.exit(result.exitCode)\n return\n }\n\n if (cmd === 'uninstall') {\n const name = positional[0]\n if (!name) {\n console.error('neat uninstall: missing <name>')\n usage()\n process.exit(2)\n }\n const removed = await removeProject(name)\n if (!removed) {\n console.error(`neat uninstall: no project named \"${name}\"`)\n process.exit(1)\n }\n console.log(`unregistered: ${removed.name} (${removed.path})`)\n console.log('note: neat-out/, policy.json, and other files at the project path were left in place.')\n return\n }\n\n if (cmd === 'deploy') {\n // ADR-073 §2 — detect substrate, generate token, emit artifact, print\n // the OTel env-vars block. Token is the only secret printed to stdout;\n // the artifact written to disk names the env-var by reference only.\n const artifact = await runDeploy()\n const block = renderOtelEnvBlock(artifact.token)\n\n console.log()\n console.log(`Substrate detected: ${artifact.substrate}`)\n if (artifact.artifactPath) {\n console.log(`Artifact written: ${artifact.artifactPath}`)\n } else {\n console.log('No on-disk artifact — copy the snippet below into your substrate.')\n console.log()\n console.log(artifact.contents)\n }\n console.log()\n console.log('NEAT_AUTH_TOKEN (store this — it will not be printed again):')\n console.log(` ${artifact.token}`)\n console.log()\n console.log(\"For your application's deploy platform, set these env vars:\")\n console.log(block.split('\\n').map((l) => ` ${l}`).join('\\n'))\n console.log()\n console.log('Once NEAT is running, your dashboard will be at:')\n console.log(' https://<host>:6328')\n console.log()\n console.log('To start NEAT, run:')\n console.log(` ${artifact.startCommand}`)\n return\n }\n\n if (cmd === 'sync') {\n // ADR-074 §1 — re-runs discovery + extract + SDK apply + daemon notify\n // against the registered project. Skips registry registration, browser\n // open, daemon spawn, and the first-run summary block.\n const result = await runSync({\n ...(parsed.project ? { project: parsed.project } : {}),\n ...(parsed.to ? { to: parsed.to } : {}),\n ...(parsed.token ? { token: parsed.token } : {}),\n dryRun: parsed.dryRun,\n noInstrument: parsed.noInstrument,\n json: parsed.json,\n })\n if (result.exitCode !== 0) process.exit(result.exitCode)\n return\n }\n\n // ── Query verbs (ADR-050) ────────────────────────────────────────────\n // The nine verbs mirror the MCP tool allowlist. Same multi-project\n // routing, same three-part response shape (summary + block + footer),\n // exit codes branch on misuse vs server error vs daemon-down.\n if (QUERY_VERBS.has(cmd)) {\n const code = await runQueryVerb(cmd, parsed)\n if (code !== 0) process.exit(code)\n return\n }\n\n // ── Bare-path orchestrator (ADR-073 §1) ──────────────────────────────\n // `neat <path>` — when the first positional doesn't match any verb but\n // resolves to a directory, hand the run off to the orchestrator. This is\n // the `npx neat.is <path>` shape from ADR-073: one command, end-to-end.\n const orchestratorCode = await tryOrchestrator(cmd, parsed)\n if (orchestratorCode !== null) {\n if (orchestratorCode !== 0) process.exit(orchestratorCode)\n return\n }\n\n console.error(`neat: unknown command \"${cmd}\"`)\n usage()\n process.exit(1)\n}\n\n// Returns null when the first positional doesn't resolve to a directory\n// (so the caller can fall through to the unknown-command error). Returns\n// an exit code when the orchestrator ran.\nasync function tryOrchestrator(cmd: string, parsed: ParsedArgs): Promise<number | null> {\n const scanPath = path.resolve(cmd)\n const stat = await fs.stat(scanPath).catch(() => null)\n if (!stat || !stat.isDirectory()) return null\n\n const projectExplicit = parsed.project !== null\n const projectName = projectExplicit ? (parsed.project as string) : path.basename(scanPath)\n const result = await runOrchestrator({\n scanPath,\n project: projectName,\n projectExplicit,\n noInstrument: parsed.noInstrument,\n noOpen: parsed.noOpen,\n yes: parsed.yes,\n })\n return result.exitCode\n}\n\n// ── Query verb dispatcher ──────────────────────────────────────────────\n\nexport const QUERY_VERBS: Set<string> = new Set([\n 'root-cause',\n 'blast-radius',\n 'dependencies',\n 'observed-dependencies',\n 'incidents',\n 'search',\n 'diff',\n 'stale-edges',\n 'policies',\n // Tenth verb (ADR-060) — amends ADR-050's locked allowlist of nine.\n 'divergences',\n])\n\n// ADR-050 #2: --project flag → NEAT_PROJECT env → undefined (server's\n// `default` slot). undefined keeps legacy unprefixed routes; explicit names\n// route through /projects/:project/...\nfunction resolveProjectFlag(parsed: ParsedArgs): string | undefined {\n if (parsed.project) return parsed.project\n const env = process.env.NEAT_PROJECT\n if (env && env.length > 0 && env !== DEFAULT_PROJECT) return env\n return undefined\n}\n\nexport async function runQueryVerb(cmd: string, parsed: ParsedArgs): Promise<number> {\n const baseUrl = process.env.NEAT_API_URL ?? 'http://localhost:8080'\n const client = createHttpClient(baseUrl)\n const project = resolveProjectFlag(parsed)\n const positional = parsed.positional\n\n // Per-verb arg/flag validation. Misuse exits 2 before any network call.\n let work: Promise<VerbResult>\n switch (cmd) {\n case 'root-cause': {\n const node = positional[0]\n if (!node) {\n console.error('neat root-cause: missing <node-id>')\n return 2\n }\n work = runRootCause(client, {\n errorNode: node,\n ...(parsed.errorId ? { errorId: parsed.errorId } : {}),\n ...(project ? { project } : {}),\n })\n break\n }\n case 'blast-radius': {\n const node = positional[0]\n if (!node) {\n console.error('neat blast-radius: missing <node-id>')\n return 2\n }\n work = runBlastRadius(client, {\n nodeId: node,\n ...(parsed.depth !== null ? { depth: parsed.depth } : {}),\n ...(project ? { project } : {}),\n })\n break\n }\n case 'dependencies': {\n const node = positional[0]\n if (!node) {\n console.error('neat dependencies: missing <node-id>')\n return 2\n }\n work = runDependencies(client, {\n nodeId: node,\n ...(parsed.depth !== null ? { depth: parsed.depth } : {}),\n ...(project ? { project } : {}),\n })\n break\n }\n case 'observed-dependencies': {\n const node = positional[0]\n if (!node) {\n console.error('neat observed-dependencies: missing <node-id>')\n return 2\n }\n work = runObservedDependencies(client, {\n nodeId: node,\n ...(project ? { project } : {}),\n })\n break\n }\n case 'incidents': {\n // node-id is optional — bare `neat incidents` returns the global log.\n work = runIncidents(client, {\n ...(positional[0] ? { nodeId: positional[0] } : {}),\n ...(parsed.limit !== null ? { limit: parsed.limit } : {}),\n ...(project ? { project } : {}),\n })\n break\n }\n case 'search': {\n const q = positional.join(' ').trim()\n if (!q) {\n console.error('neat search: missing <query>')\n return 2\n }\n work = runSearch(client, { query: q, ...(project ? { project } : {}) })\n break\n }\n case 'diff': {\n // --against names a snapshot file the core can resolve via\n // loadSnapshotForDiff. --since is reserved for a future date-range\n // mode (the contract lists it as `[--since <date>]`); for MVP, the\n // diff verb requires --against.\n const against = parsed.against ?? parsed.since\n if (!against) {\n console.error('neat diff: --against <snapshot-path> is required')\n return 2\n }\n work = runDiff(client, {\n againstSnapshot: against,\n ...(project ? { project } : {}),\n })\n break\n }\n case 'stale-edges': {\n work = runStaleEdges(client, {\n ...(parsed.limit !== null ? { limit: parsed.limit } : {}),\n ...(parsed.edgeType ? { edgeType: parsed.edgeType } : {}),\n ...(project ? { project } : {}),\n })\n break\n }\n case 'policies': {\n let hypothetical: ReturnType<typeof JSON.parse> | undefined\n if (parsed.hypotheticalAction) {\n try {\n hypothetical = JSON.parse(parsed.hypotheticalAction)\n } catch (err) {\n console.error(\n `neat policies: --hypothetical-action must be valid JSON: ${(err as Error).message}`,\n )\n return 2\n }\n }\n work = runPolicies(client, {\n ...(parsed.node ? { nodeId: parsed.node } : {}),\n ...(hypothetical ? { hypotheticalAction: hypothetical } : {}),\n ...(project ? { project } : {}),\n })\n break\n }\n case 'divergences': {\n let typeFilter: DivergenceType[] | undefined\n if (parsed.type) {\n const parts = parsed.type\n .split(',')\n .map((s) => s.trim())\n .filter((s) => s.length > 0)\n const out: DivergenceType[] = []\n for (const p of parts) {\n const r = DivergenceTypeSchema.safeParse(p)\n if (!r.success) {\n console.error(\n `neat divergences: unknown --type \"${p}\". allowed: ${DivergenceTypeSchema.options.join(', ')}`,\n )\n return 2\n }\n out.push(r.data)\n }\n typeFilter = out\n }\n work = runDivergences(client, {\n ...(typeFilter ? { type: typeFilter } : {}),\n ...(parsed.minConfidence !== null ? { minConfidence: parsed.minConfidence } : {}),\n ...(parsed.node ? { node: parsed.node } : {}),\n ...(project ? { project } : {}),\n })\n break\n }\n default:\n // Unreachable — QUERY_VERBS gates the dispatch.\n console.error(`neat: unknown query verb \"${cmd}\"`)\n return 2\n }\n\n try {\n const result = await work\n if (parsed.json) process.stdout.write(formatJson(result) + '\\n')\n else process.stdout.write(formatHuman(result) + '\\n')\n return 0\n } catch (err) {\n // Server / transport errors land on stderr per ADR-050 #3 (stderr for\n // diagnostics, stdout for results — never mix). Exit code branches per\n // ADR-050 #4: 1 for HttpError, 3 for TransportError.\n if (err instanceof HttpError) {\n const detail = err.responseBody.length > 0 ? err.responseBody : err.message\n console.error(`neat ${cmd}: ${detail.trim()}`)\n } else if (err instanceof TransportError) {\n console.error(`neat ${cmd}: ${err.message}. Is the daemon running? (NEAT_API_URL=${process.env.NEAT_API_URL ?? 'http://localhost:8080'})`)\n } else {\n console.error(`neat ${cmd}: ${(err as Error).message}`)\n }\n return exitCodeForError(err)\n }\n}\n\n// Only auto-run when invoked as the CLI entry point. Importing this module\n// from tests must not start the parser; otherwise vitest sees a stray\n// `process.exit` from `main()` running with no argv.\nconst entry = process.argv[1] ?? ''\nif (/[\\\\/]cli\\.(?:cjs|js)$/.test(entry) || entry.endsWith('/cli') || entry.endsWith('/neat') || entry.endsWith('/neat.is')) {\n main().catch((err) => {\n console.error(err)\n process.exit(1)\n })\n}\n","/**\n * `.gitignore` automation for the init flow (ADR-073 §6).\n *\n * Init writes a snapshot under `<projectDir>/neat-out/`. Un-ignored, that\n * directory leaks the snapshot into git history within one commit. The\n * helper here ensures `neat-out/` is present in `<projectDir>/.gitignore` —\n * appending to an existing file with a NEAT comment header, creating the\n * file when absent, no-oping when the line is already there.\n *\n * Idempotency rule: an exact-match line (`neat-out/` or `neat-out`, with\n * any surrounding whitespace) counts as already-present. No duplicate\n * line is written on a re-run.\n */\n\nimport { promises as fs } from 'node:fs'\nimport path from 'node:path'\n\nexport const NEAT_OUT_LINE = 'neat-out/'\nconst NEAT_HEADER = '# NEAT — machine-local snapshots and events'\n\nexport interface EnsureNeatOutResult {\n // 'added' when the line was appended to an existing .gitignore.\n // 'created' when the file did not exist and was created with a single line.\n // 'unchanged' when the line was already present.\n action: 'added' | 'created' | 'unchanged'\n // Absolute path to the .gitignore file, regardless of action.\n file: string\n}\n\nfunction isNeatOutLine(line: string): boolean {\n const trimmed = line.trim()\n return trimmed === 'neat-out/' || trimmed === 'neat-out'\n}\n\nexport async function ensureNeatOutIgnored(projectDir: string): Promise<EnsureNeatOutResult> {\n const file = path.join(projectDir, '.gitignore')\n let existing: string | null = null\n try {\n existing = await fs.readFile(file, 'utf8')\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') throw err\n }\n\n if (existing === null) {\n await fs.writeFile(file, `${NEAT_HEADER}\\n${NEAT_OUT_LINE}\\n`, 'utf8')\n return { action: 'created', file }\n }\n\n for (const line of existing.split(/\\r?\\n/)) {\n if (isNeatOutLine(line)) return { action: 'unchanged', file }\n }\n\n // Append with a leading newline if the file doesn't already end in one,\n // so the comment header sits on its own line.\n const needsLeadingNewline = existing.length > 0 && !existing.endsWith('\\n')\n const appended = `${needsLeadingNewline ? '\\n' : ''}\\n${NEAT_HEADER}\\n${NEAT_OUT_LINE}\\n`\n await fs.writeFile(file, existing + appended, 'utf8')\n return { action: 'added', file }\n}\n","/**\n * Value-forward CLI summary (issue #305, ADR-073 §5).\n *\n * Replaces the per-type node/edge counts that ended `neat init` with a\n * findings-first block — compat violations, top divergences, services\n * that never produced an OBSERVED edge, and the OTel env-vars block the\n * operator pastes into their deploy platform. Per-type counts move behind\n * `--verbose`.\n *\n * The renderer is a pure string builder so tests can assert against its\n * output without spawning the CLI.\n */\n\nimport type { Divergence, GraphEdge, GraphNode, ServiceNode } from '@neat.is/types'\nimport { NodeType, Provenance } from '@neat.is/types'\nimport type { NeatGraph } from './graph.js'\n\nexport interface SummaryInput {\n graph: NeatGraph\n divergences: Divergence[]\n // True → render the per-type counts after the value-forward block.\n verbose: boolean\n}\n\n// Static placeholder. The orchestrator and `neat deploy` print the same\n// block; `neat deploy` substitutes the actual token + host. This shape\n// lives in one place so the wire format stays in step.\nexport function renderOtelEnvBlock(): string {\n return [\n 'for prod OTel routing, set these in your deploy platform\\'s env:',\n ' OTEL_EXPORTER_OTLP_ENDPOINT=https://<your-neat-host>:4318',\n ' OTEL_EXPORTER_OTLP_HEADERS=Authorization=Bearer <NEAT_AUTH_TOKEN>',\n ].join('\\n')\n}\n\nfunction findIncompatServices(nodes: GraphNode[]): ServiceNode[] {\n return nodes.filter(\n (n): n is ServiceNode =>\n n.type === NodeType.ServiceNode &&\n Array.isArray((n as ServiceNode).incompatibilities) &&\n ((n as ServiceNode).incompatibilities ?? []).length > 0,\n )\n}\n\n// Services that show up in the EXTRACTED graph but have no OBSERVED edge\n// pointing at or out of them. The thesis says: when the OBSERVED layer is\n// silent on a service, the gap is a load-bearing signal for the operator.\nfunction servicesWithoutObserved(nodes: GraphNode[], edges: GraphEdge[]): ServiceNode[] {\n const seen = new Set<string>()\n for (const e of edges) {\n if (e.provenance === Provenance.OBSERVED) {\n seen.add(e.source)\n seen.add(e.target)\n }\n }\n return nodes.filter(\n (n): n is ServiceNode => n.type === NodeType.ServiceNode && !seen.has(n.id),\n )\n}\n\nfunction formatDivergence(d: Divergence): string {\n // Short, scannable, one-line-per-finding. The reason field already carries\n // the load-bearing detail; the recommendation rides on a second indent.\n const conf = d.confidence.toFixed(2)\n return ` [${conf}] ${d.type} ${d.source} → ${d.target} — ${d.reason}`\n}\n\nexport function renderValueForwardSummary(input: SummaryInput): string {\n const { graph, divergences, verbose } = input\n const nodes: GraphNode[] = []\n graph.forEachNode((_id, attrs) => nodes.push(attrs))\n const edges: GraphEdge[] = []\n graph.forEachEdge((_id, attrs) => edges.push(attrs))\n\n const lines: string[] = []\n lines.push('=== neat: findings ===')\n lines.push('')\n\n // ── Compat violations (driver/engine mismatches) ───────────────────────\n const incompatServices = findIncompatServices(nodes)\n const totalIncompats = incompatServices.reduce(\n (acc, s) => acc + (s.incompatibilities?.length ?? 0),\n 0,\n )\n lines.push(`compat violations: ${totalIncompats}`)\n for (const svc of incompatServices) {\n for (const inc of svc.incompatibilities ?? []) {\n const detail = formatIncompat(inc)\n lines.push(` ${svc.name}: ${detail}`)\n }\n }\n lines.push('')\n\n // ── Top divergences (top 3 by confidence desc) ─────────────────────────\n const top = [...divergences].sort((a, b) => b.confidence - a.confidence).slice(0, 3)\n lines.push(`top divergences: ${divergences.length} total${top.length > 0 ? ', top 3:' : ''}`)\n for (const d of top) lines.push(formatDivergence(d))\n lines.push('')\n\n // ── Services missing OBSERVED coverage ─────────────────────────────────\n const noObserved = servicesWithoutObserved(nodes, edges)\n if (noObserved.length > 0) {\n lines.push(`services without OBSERVED coverage: ${noObserved.length}`)\n for (const svc of noObserved) lines.push(` ${svc.name}`)\n lines.push(' → run your services with the generated otel-init to populate OBSERVED edges.')\n lines.push('')\n }\n\n // ── OTel env-vars block (static; `neat deploy` substitutes real values)\n lines.push(renderOtelEnvBlock())\n lines.push('')\n\n // ── --verbose: per-type node/edge counts ──────────────────────────────\n if (verbose) {\n const byNode = new Map<string, number>()\n for (const n of nodes) byNode.set(n.type, (byNode.get(n.type) ?? 0) + 1)\n const byEdge = new Map<string, number>()\n for (const e of edges) byEdge.set(e.type, (byEdge.get(e.type) ?? 0) + 1)\n lines.push('=== graph (verbose) ===')\n lines.push(`total: ${graph.order} nodes, ${graph.size} edges`)\n lines.push('nodes:')\n for (const [t, c] of [...byNode.entries()].sort()) lines.push(` ${t}: ${c}`)\n lines.push('edges:')\n for (const [t, c] of [...byEdge.entries()].sort()) lines.push(` ${t}: ${c}`)\n lines.push('')\n }\n\n return lines.join('\\n')\n}\n\nfunction formatIncompat(inc: NonNullable<ServiceNode['incompatibilities']>[number]): string {\n if (inc.kind === 'node-engine') {\n const range = inc.declaredNodeEngine ? ` (engines.node=\"${inc.declaredNodeEngine}\")` : ''\n return `${inc.package}@${inc.packageVersion ?? '?'} requires Node ${inc.requiredNodeVersion}${range} — ${inc.reason}`\n }\n if (inc.kind === 'package-conflict') {\n const found = inc.foundVersion ? `@${inc.foundVersion}` : ' (missing)'\n return `${inc.package}@${inc.packageVersion ?? '?'} requires ${inc.requires.name}>=${inc.requires.minVersion}; found ${inc.requires.name}${found} — ${inc.reason}`\n }\n if (inc.kind === 'deprecated-api') {\n return `${inc.package}@${inc.packageVersion ?? '?'} is deprecated — ${inc.reason}`\n }\n return `${inc.driver}@${inc.driverVersion} vs ${inc.engine} ${inc.engineVersion} — ${inc.reason}`\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport chokidar, { type FSWatcher } from 'chokidar'\nimport type { FastifyInstance } from 'fastify'\nimport type { NeatGraph } from './graph.js'\nimport { buildApi } from './api.js'\nimport { ensureCompatLoaded } from './compat.js'\nimport { discoverServices, addServiceNodes } from './extract/services.js'\nimport { addServiceAliases } from './extract/aliases.js'\nimport { addDatabasesAndCompat } from './extract/databases/index.js'\nimport { addConfigNodes } from './extract/configs.js'\nimport { addCallEdges } from './extract/calls/index.js'\nimport { addInfra } from './extract/infra/index.js'\nimport { retireEdgesByFile } from './extract/retire.js'\nimport {\n makeErrorSpanWriter,\n makeSpanHandler,\n promoteFrontierNodes,\n startStalenessLoop,\n} from './ingest.js'\nimport {\n evaluateAllPolicies,\n loadPolicyFile,\n PolicyViolationsLog,\n} from './policy.js'\nimport type { Policy } from '@neat.is/types'\nimport { buildOtelReceiver } from './otel.js'\nimport { startOtelGrpcReceiver } from './otel-grpc.js'\nimport { loadGraphFromDisk, startPersistLoop } from './persist.js'\nimport { buildSearchIndex, type SearchIndex } from './search.js'\nimport { DEFAULT_PROJECT } from './graph.js'\nimport { Projects, pathsForProject } from './projects.js'\nimport { attachGraphToEventBus, emitNeatEvent } from './events.js'\n\nexport type ExtractPhase =\n | 'services'\n | 'aliases'\n | 'databases'\n | 'configs'\n | 'calls'\n | 'infra'\n\nconst ALL_PHASES: ExtractPhase[] = [\n 'services',\n 'aliases',\n 'databases',\n 'configs',\n 'calls',\n 'infra',\n]\n\n// Map a changed path to the phases that need re-running. Anything not matched\n// here falls back to a full re-extract — better an extra ~50ms of work than a\n// missed update because the path didn't fit a regex.\n//\n// Mapping:\n// package.json / requirements.txt / pyproject.toml → services + aliases + databases\n// (deps drive compat; aliases pull from manifest fields)\n// .env / *.env.* / prisma / knex / ormconfig → databases + configs\n// docker-compose / Dockerfile / *.tf / k8s yaml → infra + aliases\n// (compose labels and Dockerfile labels feed alias discovery)\n// *.js / *.ts / *.tsx / *.py / *.jsx / *.mjs / *.cjs → calls\n// *.yaml / *.yml that isn't compose → databases + configs (ORM yaml fallbacks)\nexport function classifyChange(relPath: string): Set<ExtractPhase> {\n const phases = new Set<ExtractPhase>()\n const base = path.basename(relPath).toLowerCase()\n const segments = relPath.split(path.sep).map((s) => s.toLowerCase())\n\n if (\n base === 'package.json' ||\n base === 'requirements.txt' ||\n base === 'pyproject.toml' ||\n base === 'setup.py'\n ) {\n phases.add('services')\n phases.add('aliases')\n phases.add('databases')\n }\n\n if (\n base === '.env' ||\n base.startsWith('.env.') ||\n base === 'schema.prisma' ||\n /^knexfile\\.(?:js|ts|cjs|mjs)$/.test(base) ||\n /^ormconfig\\.(?:js|ts|json|ya?ml)$/.test(base)\n ) {\n phases.add('databases')\n phases.add('configs')\n }\n\n if (\n base === 'dockerfile' ||\n /^docker-compose.*\\.ya?ml$/.test(base) ||\n base.endsWith('.tf') ||\n segments.includes('k8s') ||\n segments.includes('kustomize') ||\n segments.includes('manifests')\n ) {\n phases.add('infra')\n phases.add('aliases')\n }\n\n if (/\\.(?:js|jsx|mjs|cjs|ts|tsx|py)$/.test(base)) {\n phases.add('calls')\n }\n\n if (/\\.ya?ml$/.test(base) && !/^docker-compose.*\\.ya?ml$/.test(base)) {\n // Generic yaml — could be an ORM file, k8s manifest, or random config.\n // Cheap to run databases + configs; if it was infra, the dir-name check\n // above already added that phase.\n phases.add('databases')\n phases.add('configs')\n }\n\n return phases\n}\n\ninterface RunPhasesResult {\n phases: ExtractPhase[]\n nodesAdded: number\n edgesAdded: number\n frontiersPromoted: number\n durationMs: number\n}\n\nexport async function runExtractPhases(\n graph: NeatGraph,\n scanPath: string,\n phases: Set<ExtractPhase>,\n // Project tag passed through for the runtime event bus (ADR-051) — not\n // required for extraction logic itself but threaded for parity with\n // extractFromDirectory's project option.\n project: string = DEFAULT_PROJECT,\n): Promise<RunPhasesResult> {\n void project\n const started = Date.now()\n await ensureCompatLoaded()\n // Discovery is cheap and every phase needs the same DiscoveredService list,\n // so we always re-walk. If the user moved a service directory, this is also\n // the path that picks it up.\n const services = await discoverServices(scanPath)\n\n let nodesAdded = 0\n let edgesAdded = 0\n\n if (phases.has('services')) {\n nodesAdded += addServiceNodes(graph, services)\n }\n if (phases.has('aliases')) {\n await addServiceAliases(graph, scanPath, services)\n }\n if (phases.has('databases')) {\n const r = await addDatabasesAndCompat(graph, services, scanPath)\n nodesAdded += r.nodesAdded\n edgesAdded += r.edgesAdded\n }\n if (phases.has('configs')) {\n const r = await addConfigNodes(graph, services, scanPath)\n nodesAdded += r.nodesAdded\n edgesAdded += r.edgesAdded\n }\n if (phases.has('calls')) {\n const r = await addCallEdges(graph, services)\n nodesAdded += r.nodesAdded\n edgesAdded += r.edgesAdded\n }\n if (phases.has('infra')) {\n const r = await addInfra(graph, scanPath, services)\n nodesAdded += r.nodesAdded\n edgesAdded += r.edgesAdded\n }\n const frontiersPromoted = promoteFrontierNodes(graph)\n\n return {\n phases: ALL_PHASES.filter((p) => phases.has(p)),\n nodesAdded,\n edgesAdded,\n frontiersPromoted,\n durationMs: Date.now() - started,\n }\n}\n\nexport interface WatchOptions {\n scanPath: string\n outPath: string\n errorsPath: string\n staleEventsPath: string\n embeddingsCachePath?: string\n // Project name this watch instance owns. Defaults to `default` for the\n // single-project workflow that's been the only one until #83.\n project?: string\n host?: string\n port?: number\n otelPort?: number\n otelGrpc?: boolean\n otelGrpcPort?: number\n debounceMs?: number\n}\n\nexport interface WatchHandle {\n api: FastifyInstance\n stop: () => Promise<void>\n}\n\n// Anymatch-compatible ignore set passed to chokidar (#233). The earlier\n// implementation passed a function alone, which forced chokidar to descend\n// into every subdirectory before testing the path. On macOS with kqueue\n// (chokidar 4 dropped fsevents in favour of kqueue), each subdir under the\n// scan root opens a watch handle; nested `node_modules` blew through the\n// per-process kqueue cap with EMFILE before the function-based ignore ever\n// fired. Globs let chokidar prune at descent time — the dirs are never\n// opened in the first place.\nconst IGNORED_WATCH_GLOBS = [\n '**/node_modules/**',\n '**/.git/**',\n '**/dist/**',\n '**/build/**',\n '**/.turbo/**',\n '**/.next/**',\n '**/neat-out/**',\n // Python venv shapes (issue #344). chokidar opens one watch handle per\n // descended dir; a CPython venv carries 20k+ files and trivially blows\n // through the macOS kqueue cap before extraction even runs.\n '**/.venv/**',\n '**/venv/**',\n '**/__pypackages__/**',\n '**/.tox/**',\n '**/site-packages/**',\n '**/.DS_Store',\n]\n\n// Backstop regex set — covers anything chokidar surfaces post-descent that\n// the globs missed (e.g. a path containing one of these segments at an\n// unexpected depth). Same shape as before; the globs are the load-bearing\n// pruning, this is defence in depth.\nconst IGNORED_WATCH_PATHS = [\n /(?:^|[\\\\/])node_modules[\\\\/]/,\n /(?:^|[\\\\/])\\.git[\\\\/]/,\n /(?:^|[\\\\/])dist[\\\\/]/,\n /(?:^|[\\\\/])build[\\\\/]/,\n /(?:^|[\\\\/])\\.turbo[\\\\/]/,\n /(?:^|[\\\\/])\\.next[\\\\/]/,\n /(?:^|[\\\\/])neat-out[\\\\/]/,\n /(?:^|[\\\\/])\\.venv[\\\\/]/,\n /(?:^|[\\\\/])venv[\\\\/]/,\n /(?:^|[\\\\/])__pypackages__[\\\\/]/,\n /(?:^|[\\\\/])\\.tox[\\\\/]/,\n /(?:^|[\\\\/])site-packages[\\\\/]/,\n /[\\\\/]?\\.DS_Store$/,\n]\n\nfunction shouldIgnore(absPath: string): boolean {\n return IGNORED_WATCH_PATHS.some((re) => re.test(absPath))\n}\n\n// Roughly the number of immediate, non-ignored subdirectories in the scan\n// root above which `neat watch` should fall back to polling on darwin. kqueue\n// opens one handle per watched dir; macOS's per-process file-descriptor cap\n// is typically 256 (soft) / unlimited (hard) but raising the hard cap doesn't\n// help with the kqueue-specific limits. Empirically anything north of ~500\n// non-ignored dirs starts to flirt with EMFILE. Threshold sits comfortably\n// under that.\nconst DARWIN_POLLING_DIR_THRESHOLD = 400\n\n// Fast non-recursive count: walk top-level entries only, descending one\n// level into non-ignored subdirs to capture the medusa-shaped case where\n// `packages/*` itself looks small but each contains a heavy `node_modules`.\n// Returns early once it crosses the threshold so we don't waste time on huge\n// repos.\nfunction countWatchableDirs(scanPath: string, limit: number): number {\n let count = 0\n const visit = (dir: string, depth: number): void => {\n if (count >= limit) return\n let entries: fs.Dirent[]\n try {\n entries = fs.readdirSync(dir, { withFileTypes: true })\n } catch {\n return\n }\n for (const e of entries) {\n if (count >= limit) return\n if (!e.isDirectory()) continue\n if (IGNORED_WATCH_PATHS.some((re) => re.test(path.join(dir, e.name) + path.sep))) continue\n count++\n // One level deeper — enough to surface nested `node_modules` shapes\n // without traversing the whole tree.\n if (depth < 2) visit(path.join(dir, e.name), depth + 1)\n }\n }\n visit(scanPath, 0)\n return count\n}\n\n// Darwin heuristic (#233). Forces chokidar onto polling when the scan root\n// is large enough that kqueue would EMFILE. Override via NEAT_WATCH_POLLING:\n// - \"1\" / \"true\" → force polling regardless of platform/threshold\n// - \"0\" / \"false\" → never poll (matches pre-#233 behaviour)\n// - unset → auto-detect on darwin\nfunction shouldUsePolling(scanPath: string): boolean {\n const env = process.env.NEAT_WATCH_POLLING\n if (env === '1' || env === 'true') return true\n if (env === '0' || env === 'false') return false\n if (process.platform !== 'darwin') return false\n return countWatchableDirs(scanPath, DARWIN_POLLING_DIR_THRESHOLD) >= DARWIN_POLLING_DIR_THRESHOLD\n}\n\nexport async function startWatch(\n graph: NeatGraph,\n opts: WatchOptions,\n): Promise<WatchHandle> {\n const debounceMs = opts.debounceMs ?? 1000\n const projectName = opts.project ?? DEFAULT_PROJECT\n\n await loadGraphFromDisk(graph, opts.outPath)\n\n // Wire graph mutations into the event bus (ADR-051) before extract begins\n // so the initial pass also produces node/edge events. Detached on stop().\n const detachEventBus = attachGraphToEventBus(graph, { project: projectName })\n\n // Load policies + open the violations log once at startup. policy.json\n // lives at the project root per ADR-042 §File location; absent file is\n // a perfectly fine state (loadPolicyFile returns []). Reload-on-change\n // is queued for v0.2.5 — the kickoff doc tracks it.\n const policyFilePath = path.join(opts.scanPath, 'policy.json')\n const policyViolationsPath = path.join(path.dirname(opts.outPath), 'policy-violations.ndjson')\n let policies: Policy[] = []\n try {\n policies = await loadPolicyFile(policyFilePath)\n if (policies.length > 0) {\n console.log(`policies: loaded ${policies.length} from ${policyFilePath}`)\n }\n } catch (err) {\n console.warn(`policies: failed to load ${policyFilePath} — ${(err as Error).message}`)\n }\n const policyLog = new PolicyViolationsLog(policyViolationsPath, projectName)\n\n // Single shared trigger callback wired into post-ingest, post-extract, and\n // post-stale per ADR-043. Failures append to console.warn but don't kill\n // the daemon — a malformed evaluator shouldn't take down ingest.\n const onPolicyTrigger = async (g: NeatGraph): Promise<void> => {\n if (policies.length === 0) return\n try {\n const violations = evaluateAllPolicies(g, policies, { now: () => Date.now() })\n for (const v of violations) await policyLog.append(v)\n } catch (err) {\n console.warn(`policies: evaluation failed — ${(err as Error).message}`)\n }\n }\n\n // The post-extract trigger fires from extractFromDirectory via opts.\n // For the initial extract here we run it inline so violations land on\n // startup before the receiver opens. Subsequent watch-driven re-extract\n // passes go through runExtractPhases which doesn't take the hook directly\n // — we run it after each flush() instead.\n const initial = await runExtractPhases(\n graph,\n opts.scanPath,\n new Set(ALL_PHASES),\n projectName,\n )\n console.log(\n `extract: ${initial.nodesAdded} new nodes, ${initial.edgesAdded} new edges (graph total ${graph.order}/${graph.size})`,\n )\n // extraction-complete for the initial pass (ADR-051). runExtractPhases\n // doesn't emit on its own — the event lives at the watch / orchestrator\n // boundary so the daemon can swap in its own emission shape.\n emitNeatEvent({\n type: 'extraction-complete',\n project: projectName,\n payload: {\n project: projectName,\n fileCount: 0,\n nodesAdded: initial.nodesAdded,\n edgesAdded: initial.edgesAdded,\n },\n })\n await onPolicyTrigger(graph)\n\n const stopPersist = startPersistLoop(graph, opts.outPath)\n const stopStaleness = startStalenessLoop(graph, {\n staleEventsPath: opts.staleEventsPath,\n project: projectName,\n onPolicyTrigger,\n })\n\n const host = opts.host ?? '0.0.0.0'\n const port = opts.port ?? 8080\n const otelPort = opts.otelPort ?? 4318\n\n const cachePath =\n opts.embeddingsCachePath ?? path.join(path.dirname(opts.outPath), 'embeddings.json')\n let searchIndex: SearchIndex | undefined\n try {\n searchIndex = await buildSearchIndex(graph, { cachePath })\n console.log(`semantic_search: ${searchIndex.provider} provider`)\n } catch (err) {\n console.warn(\n `semantic_search: index build failed (${(err as Error).message}); falling back to inline substring`,\n )\n }\n\n const registry = new Projects()\n registry.set(projectName, {\n graph,\n scanPath: opts.scanPath,\n paths: {\n // Paths are derived from the explicit options the watch caller passes\n // — pathsForProject is only used to fill in the embeddings/snapshot\n // fields so the registry shape is complete.\n ...pathsForProject(projectName, path.dirname(opts.outPath)),\n snapshotPath: opts.outPath,\n errorsPath: opts.errorsPath,\n staleEventsPath: opts.staleEventsPath,\n },\n searchIndex,\n })\n\n const api = await buildApi({ projects: registry })\n await api.listen({ port, host })\n console.log(`neat-core listening on http://${host}:${port}`)\n console.log(` scan path: ${opts.scanPath} (watching for changes)`)\n console.log(` snapshot path: ${opts.outPath}`)\n console.log(` errors log: ${opts.errorsPath}`)\n\n // The receiver writes ErrorEvents synchronously before reply (durability).\n // makeSpanHandler runs on the async queue and skips the inline write\n // because the receiver already handled it. Ad-hoc callers that bypass the\n // receiver (CLI tests, fixtures) leave writeErrorEventInline at its default\n // and get the in-handleSpan write. ADR-033 §Error events.\n const onSpan = makeSpanHandler({\n graph,\n errorsPath: opts.errorsPath,\n project: projectName,\n writeErrorEventInline: false,\n onPolicyTrigger,\n })\n const onErrorSpanSync = makeErrorSpanWriter(opts.errorsPath)\n const otelHttp = await buildOtelReceiver({ onSpan, onErrorSpanSync })\n await otelHttp.listen({ port: otelPort, host })\n console.log(`neat-core OTLP receiver on http://${host}:${otelPort}/v1/traces`)\n\n let grpcReceiver: { stop: () => Promise<void> } | null = null\n if (opts.otelGrpc) {\n const grpcPort = opts.otelGrpcPort ?? 4317\n // gRPC handler keeps the inline ErrorEvent write — the gRPC receiver\n // awaits onSpan synchronously (otel-grpc.ts), so the same durability\n // guarantee is met without a separate sync hook. Non-blocking gRPC\n // ingest is out of scope for the v0.2.2 batch.\n const onSpanGrpc = makeSpanHandler({\n graph,\n errorsPath: opts.errorsPath,\n project: projectName,\n onPolicyTrigger,\n })\n const r = await startOtelGrpcReceiver({ onSpan: onSpanGrpc, host, port: grpcPort })\n console.log(`neat-core OTLP/gRPC receiver on ${r.address}`)\n grpcReceiver = r\n }\n\n // Coalesce bursts of changes into a single re-extract. chokidar fires one\n // event per affected path; an editor save can produce 3+ events on the same\n // file in <50ms.\n const pending = new Set<ExtractPhase>()\n const pendingPaths = new Set<string>()\n let timer: NodeJS.Timeout | null = null\n let inflight: Promise<void> | null = null\n\n const flush = async (): Promise<void> => {\n if (pending.size === 0) return\n const phases = new Set(pending)\n const paths = new Set(pendingPaths)\n pending.clear()\n pendingPaths.clear()\n try {\n // Drop EXTRACTED edges keyed to changed paths first, so the producer's\n // idempotent re-extract recreates only the edges that still apply.\n // Without this, edges from deleted code would survive forever\n // (docs/contracts/static-extraction.md §Ghost-edge cleanup).\n let retired = 0\n for (const p of paths) retired += retireEdgesByFile(graph, p)\n const result = await runExtractPhases(graph, opts.scanPath, phases, projectName)\n console.log(\n `[watch] re-extract phases=${result.phases.join(',')} retired=${retired} +${result.nodesAdded}n/+${result.edgesAdded}e in ${result.durationMs}ms`,\n )\n // extraction-complete after every re-extract pass (ADR-051). fileCount\n // is the number of paths that drove the pass — closest signal we have\n // for \"how much source moved\" without per-phase accounting.\n emitNeatEvent({\n type: 'extraction-complete',\n project: projectName,\n payload: {\n project: projectName,\n fileCount: paths.size,\n nodesAdded: result.nodesAdded,\n edgesAdded: result.edgesAdded,\n },\n })\n if (searchIndex) {\n try {\n await searchIndex.refresh(graph)\n } catch (err) {\n console.warn('[watch] semantic_search refresh failed', err)\n }\n }\n // Post-extract policy trigger (ADR-043). The runExtractPhases call\n // doesn't take the hook directly — it runs through promoteFrontierNodes\n // for FRONTIER → OBSERVED upgrades but doesn't load policies itself.\n // Firing the evaluator here keeps the trigger surface symmetric across\n // ingest / extract / stale paths.\n await onPolicyTrigger(graph)\n } catch (err) {\n console.error('[watch] re-extract failed', err)\n }\n }\n\n const schedule = (): void => {\n if (timer) clearTimeout(timer)\n timer = setTimeout(() => {\n timer = null\n // Serialise re-extracts so two flushes can't interleave on the graph.\n inflight = (inflight ?? Promise.resolve()).then(flush)\n }, debounceMs)\n }\n\n const onPath = (absPath: string): void => {\n if (shouldIgnore(absPath)) return\n const rel = path.relative(opts.scanPath, absPath)\n if (!rel || rel.startsWith('..')) return\n pendingPaths.add(rel.split(path.sep).join('/'))\n const phases = classifyChange(rel)\n if (phases.size === 0) {\n // Unknown file kind — fall back to full re-extract rather than silently\n // miss it. Cheaper than the user wondering why their change didn't show.\n for (const p of ALL_PHASES) pending.add(p)\n } else {\n for (const p of phases) pending.add(p)\n }\n schedule()\n }\n\n const usePolling = shouldUsePolling(opts.scanPath)\n if (usePolling) {\n const reason =\n process.env.NEAT_WATCH_POLLING === '1' || process.env.NEAT_WATCH_POLLING === 'true'\n ? 'NEAT_WATCH_POLLING env override'\n : 'darwin heuristic — large scan root, kqueue cap risk'\n console.log(`[${projectName}] watch: usePolling=true (${reason})`)\n }\n const watcher: FSWatcher = chokidar.watch(opts.scanPath, {\n ignoreInitial: true,\n // Glob array prunes at descent time (#233) so chokidar never opens a\n // kqueue handle for `node_modules` and friends. The function backstop\n // catches any path that slipped through and matches the regex set.\n ignored: [...IGNORED_WATCH_GLOBS, (p: string) => shouldIgnore(p)],\n persistent: true,\n usePolling,\n awaitWriteFinish: { stabilityThreshold: 200, pollInterval: 50 },\n })\n watcher.on('add', onPath)\n watcher.on('change', onPath)\n watcher.on('unlink', onPath)\n watcher.on('addDir', onPath)\n watcher.on('unlinkDir', onPath)\n\n let stopped = false\n const stop = async (): Promise<void> => {\n if (stopped) return\n stopped = true\n if (timer) clearTimeout(timer)\n timer = null\n if (inflight) {\n try {\n await inflight\n } catch {\n // surfaced already in flush()\n }\n }\n await watcher.close()\n stopStaleness()\n stopPersist()\n detachEventBus()\n await api.close()\n await otelHttp.close()\n if (grpcReceiver) await grpcReceiver.stop()\n }\n\n return { api, stop }\n}\n","/**\n * `neat deploy` substrate detection + artifact generation (ADR-073 §2).\n *\n * Three substrates, detected in order:\n *\n * 1. Docker + `docker compose` present → emit `docker-compose.neat.yml`.\n * 2. Bare machine with `systemctl` available → emit `neat.service`.\n * 3. Fallback → print a `docker run` snippet to stdout.\n *\n * Every branch generates a fresh `NEAT_AUTH_TOKEN` (32 bytes, base64url),\n * prints it once, and never embeds it in the on-disk artifact — the file\n * names the env-var, the operator stores the value out of band.\n *\n * Every branch also prints the OTel env-vars block the operator pastes into\n * their application services' deploy platform.\n */\n\nimport { promises as fs } from 'node:fs'\nimport path from 'node:path'\nimport { spawn } from 'node:child_process'\nimport { randomBytes } from 'node:crypto'\n\nexport type Substrate = 'docker-compose' | 'systemd' | 'docker-run'\n\nexport interface DetectOptions {\n cwd?: string\n // Detection is shellable-out by injected probes; tests pass these to avoid\n // depending on the local docker / systemctl installation.\n hasDocker?: () => Promise<boolean>\n hasSystemd?: () => Promise<boolean>\n}\n\nexport interface DeployArtifact {\n substrate: Substrate\n // Path written to disk; undefined for the docker-run fallback (stdout-only).\n artifactPath?: string\n // The newly generated bearer token. Printed once by the caller, never\n // re-read from disk.\n token: string\n // The body of the artifact. Always returned so callers (and tests) can\n // inspect what was written without re-reading the file.\n contents: string\n // The shell command the operator runs to bring NEAT up on this substrate.\n startCommand: string\n}\n\nexport function generateToken(): string {\n // 32 bytes → 43-byte base64url (no padding). Plenty of entropy; URL-safe\n // so the operator can paste it into env-var dashboards that escape `=`.\n return randomBytes(32).toString('base64url')\n}\n\nasync function probeBinary(binary: string, arg: string): Promise<boolean> {\n return new Promise((resolve) => {\n const child = spawn(binary, [arg], { stdio: 'ignore' })\n const timer = setTimeout(() => {\n child.kill('SIGKILL')\n resolve(false)\n }, 2000)\n child.once('error', () => {\n clearTimeout(timer)\n resolve(false)\n })\n child.once('exit', (code) => {\n clearTimeout(timer)\n resolve(code === 0)\n })\n })\n}\n\nexport async function detectSubstrate(opts: DetectOptions = {}): Promise<Substrate> {\n const hasDocker = opts.hasDocker ?? (() => probeBinary('docker', 'version'))\n const hasSystemd = opts.hasSystemd ?? (() => probeBinary('systemctl', '--version'))\n if (await hasDocker()) return 'docker-compose'\n if (await hasSystemd()) return 'systemd'\n return 'docker-run'\n}\n\nconst IMAGE = 'ghcr.io/neat-technologies/neat:latest'\n\nexport function emitDockerCompose(cwd: string): string {\n // Compose v3 — declares the three documented ports + a data volume. The\n // operator's deploy platform supplies `NEAT_AUTH_TOKEN`; the file names\n // the var with no default, so a missing env stops the container from\n // coming up rather than running unauthenticated.\n return [\n 'services:',\n ' neat:',\n ` image: ${IMAGE}`,\n ' restart: unless-stopped',\n ' environment:',\n ' NEAT_AUTH_TOKEN: ${NEAT_AUTH_TOKEN:?NEAT_AUTH_TOKEN must be set}',\n ' ports:',\n ' - \"8080:8080\"',\n ' - \"4318:4318\"',\n ' - \"6328:6328\"',\n ' volumes:',\n ` - ${cwd}:/workspace`,\n ' - ./neat-data:/neat-out',\n '',\n ].join('\\n')\n}\n\nexport function emitSystemdUnit(cwd: string): string {\n // Token lives in /etc/neat/neatd.env (NEAT_AUTH_TOKEN=...) so it's readable\n // only by root and the service user. The unit itself stays version-\n // controllable without leaking the secret.\n return [\n '# NEAT_AUTH_TOKEN is read from /etc/neat/neatd.env at startup.',\n '# Put `NEAT_AUTH_TOKEN=<value>` in that file with mode 0640 root:root.',\n '[Unit]',\n 'Description=NEAT daemon',\n 'After=network-online.target',\n 'Wants=network-online.target',\n '',\n '[Service]',\n 'Type=simple',\n 'ExecStart=/usr/local/bin/neatd start --foreground',\n `WorkingDirectory=${cwd}`,\n 'EnvironmentFile=/etc/neat/neatd.env',\n 'Restart=always',\n 'RestartSec=5',\n '',\n '[Install]',\n 'WantedBy=multi-user.target',\n '',\n ].join('\\n')\n}\n\nexport function emitDockerRunSnippet(): string {\n // Single-line `docker run` for substrates we can't detect. Operator pastes\n // their own token in; the variable name keeps the bearer-token-must-be-set\n // shape consistent across all three branches.\n return [\n '#!/usr/bin/env bash',\n 'set -euo pipefail',\n '',\n '# Generate a fresh token once, then store it where your secrets live.',\n ': \"${NEAT_AUTH_TOKEN:?NEAT_AUTH_TOKEN must be set}\"',\n '',\n `docker run -d --name neat \\\\`,\n ' -e NEAT_AUTH_TOKEN=\"$NEAT_AUTH_TOKEN\" \\\\',\n ' -p 8080:8080 -p 4318:4318 -p 6328:6328 \\\\',\n ' -v \"$PWD\":/workspace -v /var/lib/neat:/neat-out \\\\',\n ` ${IMAGE}`,\n '',\n ].join('\\n')\n}\n\nexport interface RenderDeployBlockOptions {\n substrate: Substrate\n // Host the operator's services will reach NEAT at. Defaults to a\n // placeholder so the operator notices and fills it in.\n host?: string\n}\n\n// The OTel env-vars block the operator pastes into their deploy platform.\n// Format matches the orchestrator summary so the two never drift.\nexport function renderOtelEnvBlock(token: string, host: string = '<host>'): string {\n return [\n `OTEL_EXPORTER_OTLP_ENDPOINT=https://${host}:4318`,\n `OTEL_EXPORTER_OTLP_HEADERS=Authorization=Bearer ${token}`,\n 'OTEL_SERVICE_NAME=<service>',\n ].join('\\n')\n}\n\nexport async function runDeploy(opts: DetectOptions = {}): Promise<DeployArtifact> {\n const cwd = opts.cwd ?? process.cwd()\n const substrate = await detectSubstrate(opts)\n const token = generateToken()\n\n switch (substrate) {\n case 'docker-compose': {\n const artifactPath = path.join(cwd, 'docker-compose.neat.yml')\n const contents = emitDockerCompose(cwd)\n await fs.writeFile(artifactPath, contents, 'utf8')\n return {\n substrate,\n artifactPath,\n token,\n contents,\n startCommand: `NEAT_AUTH_TOKEN=${token} docker compose -f ${path.basename(artifactPath)} up -d`,\n }\n }\n case 'systemd': {\n const artifactPath = path.join(cwd, 'neat.service')\n const contents = emitSystemdUnit(cwd)\n await fs.writeFile(artifactPath, contents, 'utf8')\n return {\n substrate,\n artifactPath,\n token,\n contents,\n startCommand: [\n `sudo install -m 0640 -o root -g root <(echo NEAT_AUTH_TOKEN=${token}) /etc/neat/neatd.env`,\n `sudo install -m 0644 neat.service /etc/systemd/system/neat.service`,\n 'sudo systemctl daemon-reload && sudo systemctl enable --now neat',\n ].join(' && '),\n }\n }\n case 'docker-run':\n default: {\n const contents = emitDockerRunSnippet()\n // No on-disk artifact for the fallback — operator copies the snippet.\n return {\n substrate: 'docker-run',\n token,\n contents,\n startCommand: `NEAT_AUTH_TOKEN=${token} bash <(cat <<'EOF'\\n${contents}EOF\\n)`,\n }\n }\n }\n}\n","/**\n * Node / TypeScript SDK installer (ADR-047 + ADR-069).\n *\n * Detects services by the presence of a `package.json` carrying a `name`\n * field — same shape `extract/services.ts` uses to decide what counts as a\n * Node service. The plan adds four OTel-adjacent packages to `dependencies`\n * (api, sdk-node, auto-instrumentations-node, dotenv), writes a generated\n * `otel-init.{js,ts}` adjacent to the resolved entry, and injects the\n * require/import as the first non-shebang line of that entry. Per-package\n * `.env.neat` carries `OTEL_SERVICE_NAME` (scope-preserved) so dashboards\n * joining OBSERVED spans against the EXTRACTED graph use the same key.\n *\n * Lockfiles are never touched (ADR-047 §4). The apply phase writes only to\n * package.json, otel-init.{js,ts}, and .env.neat (ADR-069 §7). After\n * `--apply`, init prints \"run npm install\" so the user owns the lockfile\n * commit.\n *\n * Idempotency (ADR-069 §6): the generated otel-init's presence is the\n * primary signal that a package is instrumented end-to-end — when it\n * exists, the apply phase logs `already instrumented` and skips the file\n * write and the entry-point injection together. Existing `.env.neat` files\n * are preserved (never overwritten).\n */\n\nimport { promises as fs } from 'node:fs'\nimport path from 'node:path'\nimport type {\n ApplyResult,\n DependencyEdit,\n EntrypointEdit,\n EnvEdit,\n GeneratedFile,\n Installer,\n InstallPlan,\n PlanOptions,\n} from './shared.js'\nimport {\n ASTRO_MIDDLEWARE_JS,\n ASTRO_MIDDLEWARE_TS,\n ASTRO_OTEL_INIT_JS,\n ASTRO_OTEL_INIT_TS,\n NEXT_INSTRUMENTATION_HEADER,\n NEXT_INSTRUMENTATION_JS,\n NEXT_INSTRUMENTATION_NODE_JS,\n NEXT_INSTRUMENTATION_NODE_TS,\n NEXT_INSTRUMENTATION_TS,\n NUXT_OTEL_INIT_JS,\n NUXT_OTEL_INIT_TS,\n NUXT_OTEL_PLUGIN_JS,\n NUXT_OTEL_PLUGIN_TS,\n OTEL_INIT_CJS,\n OTEL_INIT_ESM,\n OTEL_INIT_HEADER,\n OTEL_INIT_TS,\n REMIX_OTEL_SERVER_JS,\n REMIX_OTEL_SERVER_TS,\n SVELTEKIT_HOOKS_SERVER_JS,\n SVELTEKIT_HOOKS_SERVER_TS,\n SVELTEKIT_OTEL_INIT_JS,\n SVELTEKIT_OTEL_INIT_TS,\n renderEnvNeat,\n renderFrameworkOtelInit,\n renderNextInstrumentationNode,\n renderNodeOtelInit,\n} from './templates.js'\n\n// ADR-069 §5 — three OTel packages land in `dependencies`. `dotenv` was a\n// fourth from v0.3.6 through v0.4.3; the generated `otel-init` templates\n// no longer load `.env.neat` from disk (issue #369), so it's gone from the\n// dep set.\nconst SDK_PACKAGES = [\n { name: '@opentelemetry/api', version: '^1.9.0' },\n { name: '@opentelemetry/sdk-node', version: '^0.57.0' },\n { name: '@opentelemetry/auto-instrumentations-node', version: '^0.55.0' },\n] as const\n\n// Issue #376 — non-bundled instrumentations. The auto-instrumentations-node\n// set covers HTTP, fetch, and the common DB drivers via the wire protocol,\n// but libraries that bypass those wires (Prisma's Rust query engine talks\n// to its own engine binary; LangChain wraps model calls in its own SDK)\n// need their own instrumentation package registered explicitly. The detected\n// entries here compose into the generated otel-init's `instrumentations`\n// array — one `instrumentations.push(...)` line per entry — and join the\n// package.json dep set so the registration line resolves at runtime.\n//\n// v0.4.5 scope is Prisma alone (first library that meaningfully widens\n// NEAT's OBSERVED coverage on real codebases). The function's interface is\n// stable so the v0.5.0 instrumentation registry (ADR-080) can return more\n// entries without revisiting the template.\ninterface NonBundledInstrumentation {\n pkg: string\n version: string\n registration: string\n}\n\nexport function detectNonBundledInstrumentations(\n pkg: PackageJsonShape,\n): NonBundledInstrumentation[] {\n const deps = allDeps(pkg)\n const out: NonBundledInstrumentation[] = []\n if ('@prisma/client' in deps) {\n out.push({\n pkg: '@prisma/instrumentation',\n version: '^5.0.0',\n registration:\n \"instrumentations.push(new (require('@prisma/instrumentation').PrismaInstrumentation)())\",\n })\n }\n return out\n}\n\nconst OTEL_ENV: EnvEdit = {\n // ADR-069 §4 — endpoint moves into the per-package .env.neat (written\n // by the apply phase). The envEdits surface stays for the dry-run\n // patch render: it documents the key/value the user can inspect in the\n // generated .env.neat.\n file: null,\n key: 'OTEL_EXPORTER_OTLP_TRACES_ENDPOINT',\n value: 'http://localhost:4318/projects/<project>/v1/traces',\n}\n\ninterface PackageJsonShape {\n name?: string\n type?: string\n main?: string\n bin?: string | Record<string, string>\n scripts?: Record<string, string>\n dependencies?: Record<string, string>\n devDependencies?: Record<string, string>\n}\n\n// v0.4.4 — `OTEL_SERVICE_NAME` regains its proper semantic role: the\n// ServiceNode id inside the project's graph, not the project name. v0.4.1\n// papered over the missing routing key by writing the project basename here;\n// the project-scoped OTLP URL (issue #367) means the URL carries the routing\n// key and the env var goes back to naming the ServiceNode.\nfunction serviceNodeName(pkg: PackageJsonShape, serviceDir: string): string {\n return pkg.name ?? path.basename(serviceDir)\n}\n\n// The URL routing key. When the orchestrator threads a project through we use\n// it verbatim; ad-hoc / test usage falls back to the package's own name so\n// the generated file is still well-formed.\nfunction projectToken(\n pkg: PackageJsonShape,\n serviceDir: string,\n project: string | undefined,\n): string {\n if (project && project.length > 0) return project\n return pkg.name ?? path.basename(serviceDir)\n}\n\n// Issue #370 — runtime-kind detection. The installer historically treated\n// every JavaScript package as a Node service; Brief's frontend workspace\n// showed that wrong assumption write `instrumentation-node/register` into a\n// Vite browser bundle and an Expo React Native entry, where the Node SDK\n// can't execute. Detection runs after framework dispatch (Next / Remix /\n// SvelteKit / Nuxt / Astro all render server-side, so they classify as\n// `node`); only the framework-less packages reach the bucket here.\ntype RuntimeKind = 'node' | 'browser-bundle' | 'react-native'\n\nasync function readJsonFile(p: string): Promise<unknown> {\n try {\n const raw = await fs.readFile(p, 'utf8')\n return JSON.parse(raw) as unknown\n } catch {\n return null\n }\n}\n\nasync function detectRuntimeKind(\n pkgRoot: string,\n pkg: PackageJsonShape,\n): Promise<RuntimeKind> {\n const deps = allDeps(pkg)\n if ('react-native' in deps || 'expo' in deps) return 'react-native'\n // Expo apps sometimes carry the SDK only as a transitive dep but always\n // ship an `app.json` carrying an `expo` block — that's the canonical Expo\n // signal.\n const appJson = await readJsonFile(path.join(pkgRoot, 'app.json'))\n if (appJson && typeof appJson === 'object' && 'expo' in (appJson as Record<string, unknown>)) {\n return 'react-native'\n }\n if (\n (await exists(path.join(pkgRoot, 'vite.config.js'))) ||\n (await exists(path.join(pkgRoot, 'vite.config.ts'))) ||\n (await exists(path.join(pkgRoot, 'vite.config.mjs'))) ||\n 'vite' in deps\n ) {\n return 'browser-bundle'\n }\n return 'node'\n}\n\n// Issue #368 — `OTel deps in package.json` is no longer the signal for\n// `already-instrumented`. The hook file is. Each `plan<Framework>` reads its\n// canonical hook path off disk via `await exists(...)` before queueing the\n// generated-file write, so deps-present-but-hook-absent correctly buckets\n// the package as `instrumented` (the installer writes the hook), not\n// `already-instrumented`. The next-deps-no-hook fixture in the contract\n// suite locks this against regression.\n\nasync function readPackageJson(serviceDir: string): Promise<PackageJsonShape | null> {\n try {\n const raw = await fs.readFile(path.join(serviceDir, 'package.json'), 'utf8')\n return JSON.parse(raw) as PackageJsonShape\n } catch {\n return null\n }\n}\n\nasync function exists(p: string): Promise<boolean> {\n try {\n await fs.stat(p)\n return true\n } catch {\n return false\n }\n}\n\nasync function detect(serviceDir: string): Promise<boolean> {\n const pkg = await readPackageJson(serviceDir)\n return pkg !== null && typeof pkg.name === 'string'\n}\n\n// ADR-073 §1 — Next.js detection. A package is Next-flavored when it\n// declares `next` as a (dev)dependency AND ships a `next.config.{js,ts,mjs}`\n// at the package root. Both are required: a stray `next` import without the\n// config file isn't a Next app, and a config file without the dep is dead\n// configuration.\nconst NEXT_CONFIG_CANDIDATES = ['next.config.js', 'next.config.ts', 'next.config.mjs']\n\nasync function findNextConfig(serviceDir: string): Promise<string | null> {\n for (const name of NEXT_CONFIG_CANDIDATES) {\n const candidate = path.join(serviceDir, name)\n if (await exists(candidate)) return candidate\n }\n return null\n}\n\nfunction hasNextDependency(pkg: PackageJsonShape): boolean {\n return (\n (pkg.dependencies?.next !== undefined) ||\n (pkg.devDependencies?.next !== undefined)\n )\n}\n\n// Read the merged dep + devDep map once per detection step. Framework checks\n// only care about presence, not version.\nfunction allDeps(pkg: PackageJsonShape): Record<string, string> {\n return { ...(pkg.dependencies ?? {}), ...(pkg.devDependencies ?? {}) }\n}\n\n// ADR-074 §3 — Remix detection. A package is Remix-flavored when it declares\n// `remix` or any `@remix-run/*` package AND ships an entry-server file at one\n// of the canonical paths (`app/entry.server.{ts,tsx,js,jsx}`).\nconst REMIX_ENTRY_CANDIDATES = [\n 'app/entry.server.ts',\n 'app/entry.server.tsx',\n 'app/entry.server.js',\n 'app/entry.server.jsx',\n]\n\nfunction hasRemixDependency(pkg: PackageJsonShape): boolean {\n const deps = allDeps(pkg)\n if ('remix' in deps) return true\n for (const name of Object.keys(deps)) {\n if (name.startsWith('@remix-run/')) return true\n }\n return false\n}\n\nasync function findRemixEntry(serviceDir: string): Promise<string | null> {\n for (const rel of REMIX_ENTRY_CANDIDATES) {\n const candidate = path.join(serviceDir, rel)\n if (await exists(candidate)) return candidate\n }\n return null\n}\n\n// ADR-074 §3 — SvelteKit detection. `@sveltejs/kit` dep, plus either an\n// existing `src/hooks.server.{ts,js}` or a top-level `svelte.config.{js,ts}`\n// (the absent-hooks case where the installer creates the hook file).\nconst SVELTEKIT_HOOKS_CANDIDATES = ['src/hooks.server.ts', 'src/hooks.server.js']\nconst SVELTEKIT_CONFIG_CANDIDATES = ['svelte.config.js', 'svelte.config.ts']\n\nfunction hasSvelteKitDependency(pkg: PackageJsonShape): boolean {\n return '@sveltejs/kit' in allDeps(pkg)\n}\n\nasync function findSvelteKitHooks(serviceDir: string): Promise<string | null> {\n for (const rel of SVELTEKIT_HOOKS_CANDIDATES) {\n const candidate = path.join(serviceDir, rel)\n if (await exists(candidate)) return candidate\n }\n return null\n}\n\nasync function findSvelteKitConfig(serviceDir: string): Promise<string | null> {\n for (const rel of SVELTEKIT_CONFIG_CANDIDATES) {\n const candidate = path.join(serviceDir, rel)\n if (await exists(candidate)) return candidate\n }\n return null\n}\n\n// ADR-074 §3 — Nuxt detection. `nuxt` dep + `nuxt.config.{ts,js,mjs}`.\nconst NUXT_CONFIG_CANDIDATES = ['nuxt.config.ts', 'nuxt.config.js', 'nuxt.config.mjs']\n\nfunction hasNuxtDependency(pkg: PackageJsonShape): boolean {\n return 'nuxt' in allDeps(pkg)\n}\n\nasync function findNuxtConfig(serviceDir: string): Promise<string | null> {\n for (const name of NUXT_CONFIG_CANDIDATES) {\n const candidate = path.join(serviceDir, name)\n if (await exists(candidate)) return candidate\n }\n return null\n}\n\n// ADR-074 §3 — Astro detection. `astro` dep + `astro.config.{mjs,ts,js}`.\nconst ASTRO_CONFIG_CANDIDATES = ['astro.config.mjs', 'astro.config.ts', 'astro.config.js']\n\nfunction hasAstroDependency(pkg: PackageJsonShape): boolean {\n return 'astro' in allDeps(pkg)\n}\n\nasync function findAstroConfig(serviceDir: string): Promise<string | null> {\n for (const name of ASTRO_CONFIG_CANDIDATES) {\n const candidate = path.join(serviceDir, name)\n if (await exists(candidate)) return candidate\n }\n return null\n}\n\n// Parse the leading major version out of a semver range like \"^14.0.3\" or\n// \"~15.0\" or \"15.0.0\". Returns null when the range can't be read (workspace\n// links, git refs, \"*\", etc.).\nexport function parseNextMajor(range: string | undefined): number | null {\n if (!range) return null\n const cleaned = range.trim().replace(/^[\\^~>=<\\s]+/, '')\n const match = cleaned.match(/^(\\d+)/)\n if (!match) return null\n const n = Number(match[1])\n return Number.isFinite(n) ? n : null\n}\n\nasync function isTypeScriptProject(serviceDir: string): Promise<boolean> {\n return exists(path.join(serviceDir, 'tsconfig.json'))\n}\n\n// ADR-069 §2 + ADR-070 — entry resolution: pkg.main → pkg.bin → scripts.start\n// → scripts.dev → src/index.* → src/{server,main,app}.* → root index.*.\n// Returns the absolute path to the resolved entry, or null when the package\n// is lib-only (no resolvable entry).\nconst INDEX_EXTENSIONS = ['.ts', '.tsx', '.js', '.mjs', '.cjs']\nconst INDEX_CANDIDATES = INDEX_EXTENSIONS.map((ext) => `index${ext}`)\nconst SRC_INDEX_CANDIDATES = INDEX_EXTENSIONS.map((ext) => `src/index${ext}`)\nconst SRC_NAMED_CANDIDATES = ['server', 'main', 'app'].flatMap((name) =>\n INDEX_EXTENSIONS.map((ext) => `src/${name}${ext}`),\n)\n\n// ADR-070 — script-entry tokeniser. Launchers and similar wrappers we strip\n// before reading the first file-shaped argument. Anything not in this set is\n// treated as a candidate entry if it looks like a relative file path.\nconst SCRIPT_LAUNCHERS = new Set([\n 'node',\n 'ts-node',\n 'tsx',\n 'ts-node-dev',\n 'nodemon',\n 'npx',\n 'pnpm',\n 'yarn',\n 'npm',\n 'cross-env',\n 'dotenv',\n '--',\n])\n\n// True when the token resembles a path inside the package — contains a `/` or\n// ends in one of the JS/TS extensions we instrument.\nfunction looksLikeEntryPath(token: string): boolean {\n if (token.length === 0) return false\n if (token.startsWith('-')) return false\n if (token.includes('=')) return false // env-var assignments\n if (token.includes('/')) return true\n return /\\.(?:m?[jt]sx?|c[jt]s)$/.test(token)\n}\n\n// Bail when the script chains commands or pipes — those scripts mean an\n// orchestrator runs multiple things and our heuristic can't pick safely.\nfunction scriptHasShellChain(script: string): boolean {\n return /(?:&&|\\|\\||;|\\|(?!\\|))/.test(script)\n}\n\n// Pull the first file-shaped argument out of a script invocation, after\n// stripping recognised launchers and inline env-var assignments. Returns\n// undefined when no candidate surfaces (or when shell chaining bails us out).\nexport function entryFromScript(script: string | undefined): string | undefined {\n if (!script) return undefined\n if (scriptHasShellChain(script)) return undefined\n const tokens = script.split(/\\s+/).filter((t) => t.length > 0)\n for (const token of tokens) {\n const lower = token.toLowerCase()\n if (SCRIPT_LAUNCHERS.has(lower)) continue\n // Strip a leading `./` so the existence check resolves cleanly.\n const cleaned = token.startsWith('./') ? token.slice(2) : token\n if (looksLikeEntryPath(cleaned)) return cleaned\n }\n return undefined\n}\n\nexport async function resolveEntry(\n serviceDir: string,\n pkg: PackageJsonShape,\n): Promise<string | null> {\n // 1) pkg.main — but only when it actually exists on disk (ADR-070).\n if (typeof pkg.main === 'string' && pkg.main.length > 0) {\n const candidate = path.resolve(serviceDir, pkg.main)\n if (await exists(candidate)) return candidate\n // Manifest points main at a missing build output (e.g. dist/index.js\n // pre-build). Fall through to bin/scripts/src heuristics rather than\n // marking lib-only.\n }\n // 2) pkg.bin (string or pkg.name-keyed map).\n if (pkg.bin) {\n let binEntry: string | undefined\n if (typeof pkg.bin === 'string') {\n binEntry = pkg.bin\n } else if (pkg.name && typeof pkg.bin[pkg.name] === 'string') {\n binEntry = pkg.bin[pkg.name]\n } else {\n const first = Object.values(pkg.bin)[0]\n if (typeof first === 'string') binEntry = first\n }\n if (binEntry) {\n const candidate = path.resolve(serviceDir, binEntry)\n if (await exists(candidate)) return candidate\n }\n }\n // 3) scripts.start — ADR-070.\n const startEntry = entryFromScript(pkg.scripts?.start)\n if (startEntry) {\n const candidate = path.resolve(serviceDir, startEntry)\n if (await exists(candidate)) return candidate\n }\n // 4) scripts.dev — ADR-070.\n const devEntry = entryFromScript(pkg.scripts?.dev)\n if (devEntry) {\n const candidate = path.resolve(serviceDir, devEntry)\n if (await exists(candidate)) return candidate\n }\n // 5) src/index.* — ADR-070.\n for (const rel of SRC_INDEX_CANDIDATES) {\n const candidate = path.join(serviceDir, rel)\n if (await exists(candidate)) return candidate\n }\n // 6) src/server.*, src/main.*, src/app.* — ADR-070.\n for (const rel of SRC_NAMED_CANDIDATES) {\n const candidate = path.join(serviceDir, rel)\n if (await exists(candidate)) return candidate\n }\n // 7) root index.* — original ADR-069 §3 fallback.\n for (const name of INDEX_CANDIDATES) {\n const candidate = path.join(serviceDir, name)\n if (await exists(candidate)) return candidate\n }\n return null\n}\n\n// ADR-069 §1, §3 — dispatch by entry extension + pkg.type.\ntype EntryFlavor = 'cjs' | 'esm' | 'ts'\n\nexport function dispatchEntry(entryFile: string, pkg: PackageJsonShape): EntryFlavor {\n const ext = path.extname(entryFile).toLowerCase()\n if (ext === '.ts' || ext === '.tsx') return 'ts'\n if (ext === '.mjs') return 'esm'\n if (ext === '.cjs') return 'cjs'\n // .js — disambiguate on pkg.type. \"module\" → ESM, anything else → CJS.\n return pkg.type === 'module' ? 'esm' : 'cjs'\n}\n\n// Generated-file basename per flavor.\nfunction otelInitFilename(flavor: EntryFlavor): string {\n if (flavor === 'ts') return 'otel-init.ts'\n if (flavor === 'esm') return 'otel-init.mjs'\n return 'otel-init.cjs'\n}\n\nfunction otelInitContents(flavor: EntryFlavor): string {\n if (flavor === 'ts') return OTEL_INIT_TS\n if (flavor === 'esm') return OTEL_INIT_ESM\n return OTEL_INIT_CJS\n}\n\n// Build the injection line per flavor. The relative path is computed against\n// the entry's directory so the injection works regardless of the entry's\n// depth inside the package.\nexport function injectionLine(\n flavor: EntryFlavor,\n entryFile: string,\n otelInitFile: string,\n): string {\n let rel = path.relative(path.dirname(entryFile), otelInitFile)\n if (!rel.startsWith('.')) rel = `./${rel}`\n // Normalize to forward slashes for cross-platform module specifiers.\n rel = rel.split(path.sep).join('/')\n if (flavor === 'cjs') return `require('${rel}')`\n if (flavor === 'esm') return `import '${rel}'`\n // TS: drop the .ts extension so the resolver doesn't choke on it under\n // either tsc-output or runtime-loader pipelines.\n const tsRel = rel.replace(/\\.ts$/, '')\n return `import '${tsRel}'`\n}\n\n// Detect whether a given line already matches an injection of our otel-init.\n// Used for the entry-point idempotency check (ADR-069 §6).\nfunction lineIsOtelInjection(line: string): boolean {\n const trimmed = line.trim()\n if (trimmed.length === 0) return false\n // Match require('./otel-init…') and import './otel-init…' shapes.\n return /(?:require\\(|import\\s+)['\"]\\.\\/otel-init[^'\"]*['\"]/.test(trimmed)\n}\n\n// `create-next-app --src-dir` puts source under `src/` and Next then resolves\n// the instrumentation hook from `src/instrumentation.ts`. Routing the\n// generated files to root in that case means the hook never loads. We detect\n// src-layout by the presence of `src/app/` or `src/pages/` AND the absence of\n// the same at the package root — a project with both is treated as flat, the\n// safer default for monorepos that vendor a `src/` subpackage.\nasync function detectsSrcLayout(serviceDir: string): Promise<boolean> {\n const [hasSrcApp, hasSrcPages, hasRootApp, hasRootPages] = await Promise.all([\n exists(path.join(serviceDir, 'src', 'app')),\n exists(path.join(serviceDir, 'src', 'pages')),\n exists(path.join(serviceDir, 'app')),\n exists(path.join(serviceDir, 'pages')),\n ])\n return (hasSrcApp || hasSrcPages) && !hasRootApp && !hasRootPages\n}\n\n// ADR-073 §1 — Next.js apply path. Emits `instrumentation.{ts,js}` and\n// `instrumentation.node.{ts,js}` at the package root (or under `src/` for\n// `--src-dir` layouts), plus `.env.neat` co-located with them. Skips\n// entry-point injection entirely — Next loads the instrumentation file\n// through its own runtime hook. Queues a next.config edit only when the\n// declared major is < 15 (the flag is on-by-default from Next 15 on).\nasync function planNext(\n serviceDir: string,\n pkg: PackageJsonShape,\n manifestPath: string,\n nextConfigPath: string,\n project: string | undefined,\n): Promise<InstallPlan> {\n const useTs = await isTypeScriptProject(serviceDir)\n const srcLayout = await detectsSrcLayout(serviceDir)\n // Co-locate the generated files with where Next looks for the hook. When\n // src-layout is detected the framework resolves `src/instrumentation.{ts,js}`\n // and we route the .env.neat alongside so an operator reading the codebase\n // finds the wiring in one place. The flat layout keeps the existing root\n // placement.\n const baseDir = srcLayout ? path.join(serviceDir, 'src') : serviceDir\n const instrumentationFile = path.join(baseDir, useTs ? 'instrumentation.ts' : 'instrumentation.js')\n const instrumentationNodeFile = path.join(\n baseDir,\n useTs ? 'instrumentation.node.ts' : 'instrumentation.node.js',\n )\n const envNeatFile = path.join(baseDir, '.env.neat')\n\n // Dependency edits — `dotenv` is gone repo-wide from v0.4.4 (issue #369),\n // so SDK_PACKAGES has the three OTel packages the apply phase adds and the\n // Next branch shares the same loop as every other framework. Issue #376\n // adds non-bundled instrumentations (Prisma in v0.4.5) — each detected\n // entry contributes one dep + one registration line into the generated\n // instrumentation.node file.\n const existingDeps = { ...(pkg.dependencies ?? {}), ...(pkg.devDependencies ?? {}) }\n const dependencyEdits: DependencyEdit[] = []\n for (const sdk of SDK_PACKAGES) {\n if (sdk.name in existingDeps) continue\n dependencyEdits.push({\n file: manifestPath,\n kind: 'add',\n name: sdk.name,\n version: sdk.version,\n })\n }\n const nonBundled = detectNonBundledInstrumentations(pkg)\n for (const inst of nonBundled) {\n if (inst.pkg in existingDeps) continue\n dependencyEdits.push({\n file: manifestPath,\n kind: 'add',\n name: inst.pkg,\n version: inst.version,\n })\n }\n\n // Generated files — instrumentation pair + .env.neat. Existing files are\n // preserved (skipIfExists honours user customisations and keeps the apply\n // phase idempotent per ADR-069 §6). The instrumentation.node template\n // carries `__SERVICE_NAME__` (the ServiceNode id) and `__PROJECT__` (the\n // registered project basename — the URL routing key) placeholders we\n // substitute here so the bundler-survivable `process.env.X ||=` lines land\n // with both values verbatim.\n const svcName = serviceNodeName(pkg, serviceDir)\n const projectName = projectToken(pkg, serviceDir, project)\n const registrations = nonBundled.map((i) => i.registration)\n const generatedFiles: GeneratedFile[] = []\n if (!(await exists(instrumentationFile))) {\n generatedFiles.push({\n file: instrumentationFile,\n contents: useTs ? NEXT_INSTRUMENTATION_TS : NEXT_INSTRUMENTATION_JS,\n skipIfExists: true,\n })\n }\n if (!(await exists(instrumentationNodeFile))) {\n generatedFiles.push({\n file: instrumentationNodeFile,\n contents: renderNextInstrumentationNode(\n useTs ? NEXT_INSTRUMENTATION_NODE_TS : NEXT_INSTRUMENTATION_NODE_JS,\n svcName,\n projectName,\n registrations,\n ),\n skipIfExists: true,\n })\n }\n if (!(await exists(envNeatFile))) {\n generatedFiles.push({\n file: envNeatFile,\n contents: renderEnvNeat(svcName, projectName),\n skipIfExists: true,\n })\n }\n\n // ADR-073 §1 — `experimental.instrumentationHook: true` is required for\n // Next 13 / 14 and a no-op on Next 15+. Plan the edit only when the\n // declared major is < 15 and the flag isn't already present.\n let nextConfigEdit: InstallPlan['nextConfigEdit']\n const nextRange = pkg.dependencies?.next ?? pkg.devDependencies?.next\n const nextMajor = parseNextMajor(nextRange)\n if (nextMajor !== null && nextMajor < 15) {\n try {\n const raw = await fs.readFile(nextConfigPath, 'utf8')\n if (!raw.includes('instrumentationHook')) {\n nextConfigEdit = {\n file: nextConfigPath,\n reason: `enable experimental.instrumentationHook (Next ${nextMajor} requires the opt-in flag)`,\n }\n }\n } catch {\n // Config disappeared between detect and plan. Skip the edit.\n }\n }\n\n const empty =\n dependencyEdits.length === 0 &&\n generatedFiles.length === 0 &&\n nextConfigEdit === undefined\n\n if (empty) {\n return {\n language: 'javascript',\n serviceDir,\n dependencyEdits: [],\n entrypointEdits: [],\n envEdits: [],\n generatedFiles: [],\n framework: 'next',\n }\n }\n\n return {\n language: 'javascript',\n serviceDir,\n dependencyEdits,\n entrypointEdits: [],\n envEdits: [OTEL_ENV],\n generatedFiles,\n framework: 'next',\n ...(nextConfigEdit ? { nextConfigEdit } : {}),\n }\n}\n\n// ── Meta-framework planners (ADR-074 §3). ───────────────────────────────\n//\n// Each planner mirrors planNext's shape: build dep edits via the same\n// SDK_PACKAGES + existing-deps filter, queue generated files for the\n// framework-canonical hook surface, record `framework: '<name>'`, never\n// inject into pkg.main. Idempotency rides on `skipIfExists` for generated\n// files and on a re-read header-grep for the inject-into-existing case.\n\nfunction buildDependencyEdits(\n pkg: PackageJsonShape,\n manifestPath: string,\n): DependencyEdit[] {\n const existingDeps = allDeps(pkg)\n const edits: DependencyEdit[] = []\n for (const sdk of SDK_PACKAGES) {\n if (sdk.name in existingDeps) continue\n edits.push({\n file: manifestPath,\n kind: 'add',\n name: sdk.name,\n version: sdk.version,\n })\n }\n return edits\n}\n\nasync function queueEnvNeat(\n serviceDir: string,\n pkg: PackageJsonShape,\n project: string | undefined,\n generatedFiles: GeneratedFile[],\n): Promise<void> {\n const envNeatFile = path.join(serviceDir, '.env.neat')\n if (!(await exists(envNeatFile))) {\n generatedFiles.push({\n file: envNeatFile,\n contents: renderEnvNeat(\n serviceNodeName(pkg, serviceDir),\n projectToken(pkg, serviceDir, project),\n ),\n skipIfExists: true,\n })\n }\n}\n\nfunction renderFrameworkOtelInitForPkg(\n template: string,\n pkg: PackageJsonShape,\n serviceDir: string,\n project: string | undefined,\n): string {\n return renderFrameworkOtelInit(\n template,\n serviceNodeName(pkg, serviceDir),\n projectToken(pkg, serviceDir, project),\n )\n}\n\nfunction fileImportsOtelHook(raw: string, specifiers: readonly string[]): boolean {\n const lines = raw.split(/\\r?\\n/)\n for (const line of lines) {\n const trimmed = line.trim()\n for (const spec of specifiers) {\n const escaped = spec.replace(/\\./g, '\\\\.')\n const pattern = new RegExp(\n `(?:import\\\\s+['\"]${escaped}['\"]|require\\\\(['\"]${escaped}['\"]\\\\))`,\n )\n if (pattern.test(trimmed)) return true\n }\n }\n return false\n}\n\nasync function planRemix(\n serviceDir: string,\n pkg: PackageJsonShape,\n manifestPath: string,\n entryFile: string,\n project: string | undefined,\n): Promise<InstallPlan> {\n const useTs = await isTypeScriptProject(serviceDir)\n const otelServerFile = path.join(\n serviceDir,\n useTs ? 'app/otel.server.ts' : 'app/otel.server.js',\n )\n\n const dependencyEdits = buildDependencyEdits(pkg, manifestPath)\n const generatedFiles: GeneratedFile[] = []\n\n if (!(await exists(otelServerFile))) {\n generatedFiles.push({\n file: otelServerFile,\n contents: renderFrameworkOtelInitForPkg(\n useTs ? REMIX_OTEL_SERVER_TS : REMIX_OTEL_SERVER_JS,\n pkg,\n serviceDir,\n project,\n ),\n skipIfExists: true,\n })\n }\n await queueEnvNeat(serviceDir, pkg, project, generatedFiles)\n\n const entrypointEdits: EntrypointEdit[] = []\n try {\n const raw = await fs.readFile(entryFile, 'utf8')\n if (!fileImportsOtelHook(raw, ['./otel.server'])) {\n const lines = raw.split(/\\r?\\n/)\n const firstReal = lines[0]?.startsWith('#!') ? lines[1] ?? '' : lines[0] ?? ''\n entrypointEdits.push({\n file: entryFile,\n before: firstReal,\n after: \"import './otel.server'\",\n })\n }\n } catch {\n // Entry file disappeared between detect and plan; fall through.\n }\n\n const empty =\n dependencyEdits.length === 0 &&\n generatedFiles.length === 0 &&\n entrypointEdits.length === 0\n\n if (empty) {\n return {\n language: 'javascript',\n serviceDir,\n dependencyEdits: [],\n entrypointEdits: [],\n envEdits: [],\n generatedFiles: [],\n framework: 'remix',\n }\n }\n\n return {\n language: 'javascript',\n serviceDir,\n dependencyEdits,\n entrypointEdits,\n envEdits: [OTEL_ENV],\n generatedFiles,\n framework: 'remix',\n }\n}\n\nasync function planSvelteKit(\n serviceDir: string,\n pkg: PackageJsonShape,\n manifestPath: string,\n hooksFile: string | null,\n project: string | undefined,\n): Promise<InstallPlan> {\n const useTs = await isTypeScriptProject(serviceDir)\n const otelInitFile = path.join(\n serviceDir,\n useTs ? 'src/otel-init.ts' : 'src/otel-init.js',\n )\n const resolvedHooksFile =\n hooksFile ??\n path.join(serviceDir, useTs ? 'src/hooks.server.ts' : 'src/hooks.server.js')\n\n const dependencyEdits = buildDependencyEdits(pkg, manifestPath)\n const generatedFiles: GeneratedFile[] = []\n const entrypointEdits: EntrypointEdit[] = []\n\n if (!(await exists(otelInitFile))) {\n generatedFiles.push({\n file: otelInitFile,\n contents: renderFrameworkOtelInitForPkg(\n useTs ? SVELTEKIT_OTEL_INIT_TS : SVELTEKIT_OTEL_INIT_JS,\n pkg,\n serviceDir,\n project,\n ),\n skipIfExists: true,\n })\n }\n await queueEnvNeat(serviceDir, pkg, project, generatedFiles)\n\n if (hooksFile === null) {\n generatedFiles.push({\n file: resolvedHooksFile,\n contents: useTs ? SVELTEKIT_HOOKS_SERVER_TS : SVELTEKIT_HOOKS_SERVER_JS,\n skipIfExists: true,\n })\n } else {\n try {\n const raw = await fs.readFile(hooksFile, 'utf8')\n if (!fileImportsOtelHook(raw, ['./otel-init'])) {\n const lines = raw.split(/\\r?\\n/)\n const firstReal = lines[0]?.startsWith('#!') ? lines[1] ?? '' : lines[0] ?? ''\n entrypointEdits.push({\n file: hooksFile,\n before: firstReal,\n after: \"import './otel-init'\",\n })\n }\n } catch {\n // Disappeared between detect and plan; fall through.\n }\n }\n\n const empty =\n dependencyEdits.length === 0 &&\n generatedFiles.length === 0 &&\n entrypointEdits.length === 0\n\n if (empty) {\n return {\n language: 'javascript',\n serviceDir,\n dependencyEdits: [],\n entrypointEdits: [],\n envEdits: [],\n generatedFiles: [],\n framework: 'sveltekit',\n }\n }\n\n return {\n language: 'javascript',\n serviceDir,\n dependencyEdits,\n entrypointEdits,\n envEdits: [OTEL_ENV],\n generatedFiles,\n framework: 'sveltekit',\n }\n}\n\nasync function planNuxt(\n serviceDir: string,\n pkg: PackageJsonShape,\n manifestPath: string,\n project: string | undefined,\n): Promise<InstallPlan> {\n const useTs = await isTypeScriptProject(serviceDir)\n const otelPluginFile = path.join(\n serviceDir,\n useTs ? 'server/plugins/otel.ts' : 'server/plugins/otel.js',\n )\n const otelInitFile = path.join(\n serviceDir,\n useTs ? 'server/plugins/otel-init.ts' : 'server/plugins/otel-init.js',\n )\n\n const dependencyEdits = buildDependencyEdits(pkg, manifestPath)\n const generatedFiles: GeneratedFile[] = []\n\n if (!(await exists(otelInitFile))) {\n generatedFiles.push({\n file: otelInitFile,\n contents: renderFrameworkOtelInitForPkg(\n useTs ? NUXT_OTEL_INIT_TS : NUXT_OTEL_INIT_JS,\n pkg,\n serviceDir,\n project,\n ),\n skipIfExists: true,\n })\n }\n if (!(await exists(otelPluginFile))) {\n generatedFiles.push({\n file: otelPluginFile,\n contents: useTs ? NUXT_OTEL_PLUGIN_TS : NUXT_OTEL_PLUGIN_JS,\n skipIfExists: true,\n })\n }\n await queueEnvNeat(serviceDir, pkg, project, generatedFiles)\n\n const empty = dependencyEdits.length === 0 && generatedFiles.length === 0\n\n if (empty) {\n return {\n language: 'javascript',\n serviceDir,\n dependencyEdits: [],\n entrypointEdits: [],\n envEdits: [],\n generatedFiles: [],\n framework: 'nuxt',\n }\n }\n\n return {\n language: 'javascript',\n serviceDir,\n dependencyEdits,\n entrypointEdits: [],\n envEdits: [OTEL_ENV],\n generatedFiles,\n framework: 'nuxt',\n }\n}\n\nconst ASTRO_MIDDLEWARE_CANDIDATES = ['src/middleware.ts', 'src/middleware.js']\n\nasync function findAstroMiddleware(serviceDir: string): Promise<string | null> {\n for (const rel of ASTRO_MIDDLEWARE_CANDIDATES) {\n const candidate = path.join(serviceDir, rel)\n if (await exists(candidate)) return candidate\n }\n return null\n}\n\nasync function planAstro(\n serviceDir: string,\n pkg: PackageJsonShape,\n manifestPath: string,\n project: string | undefined,\n): Promise<InstallPlan> {\n const useTs = await isTypeScriptProject(serviceDir)\n const otelInitFile = path.join(\n serviceDir,\n useTs ? 'src/otel-init.ts' : 'src/otel-init.js',\n )\n const existingMiddleware = await findAstroMiddleware(serviceDir)\n const middlewareFile =\n existingMiddleware ??\n path.join(serviceDir, useTs ? 'src/middleware.ts' : 'src/middleware.js')\n\n const dependencyEdits = buildDependencyEdits(pkg, manifestPath)\n const generatedFiles: GeneratedFile[] = []\n const entrypointEdits: EntrypointEdit[] = []\n\n if (!(await exists(otelInitFile))) {\n generatedFiles.push({\n file: otelInitFile,\n contents: renderFrameworkOtelInitForPkg(\n useTs ? ASTRO_OTEL_INIT_TS : ASTRO_OTEL_INIT_JS,\n pkg,\n serviceDir,\n project,\n ),\n skipIfExists: true,\n })\n }\n await queueEnvNeat(serviceDir, pkg, project, generatedFiles)\n\n if (existingMiddleware === null) {\n generatedFiles.push({\n file: middlewareFile,\n contents: useTs ? ASTRO_MIDDLEWARE_TS : ASTRO_MIDDLEWARE_JS,\n skipIfExists: true,\n })\n } else {\n try {\n const raw = await fs.readFile(existingMiddleware, 'utf8')\n if (!fileImportsOtelHook(raw, ['./otel-init'])) {\n const lines = raw.split(/\\r?\\n/)\n const firstReal = lines[0]?.startsWith('#!') ? lines[1] ?? '' : lines[0] ?? ''\n entrypointEdits.push({\n file: existingMiddleware,\n before: firstReal,\n after: \"import './otel-init'\",\n })\n }\n } catch {\n // Disappeared between detect and plan; fall through.\n }\n }\n\n const empty =\n dependencyEdits.length === 0 &&\n generatedFiles.length === 0 &&\n entrypointEdits.length === 0\n\n if (empty) {\n return {\n language: 'javascript',\n serviceDir,\n dependencyEdits: [],\n entrypointEdits: [],\n envEdits: [],\n generatedFiles: [],\n framework: 'astro',\n }\n }\n\n return {\n language: 'javascript',\n serviceDir,\n dependencyEdits,\n entrypointEdits,\n envEdits: [OTEL_ENV],\n generatedFiles,\n framework: 'astro',\n }\n}\n\ntype FrameworkDispatch = () => Promise<InstallPlan>\n\n// ADR-073 §1 + ADR-074 §3 — framework signal lookup. Returns a thunk that\n// invokes the framework-specific planner when a match lands, or null when\n// none do. Detection precedence is Next → Remix → SvelteKit → Nuxt → Astro;\n// the chain bails on the first match. Pulled out of `plan()` so issue\n// #375's lib-only check can see the framework signal upfront — a package\n// with no framework hook AND no Node entry buckets as lib-only regardless\n// of stray Vite config or Expo deps.\nasync function findFrameworkDispatch(\n serviceDir: string,\n pkg: PackageJsonShape,\n manifestPath: string,\n project: string | undefined,\n): Promise<FrameworkDispatch | null> {\n if (hasNextDependency(pkg)) {\n const nextConfig = await findNextConfig(serviceDir)\n if (nextConfig) {\n return () => planNext(serviceDir, pkg, manifestPath, nextConfig, project)\n }\n }\n if (hasRemixDependency(pkg)) {\n const remixEntry = await findRemixEntry(serviceDir)\n if (remixEntry) {\n return () => planRemix(serviceDir, pkg, manifestPath, remixEntry, project)\n }\n }\n if (hasSvelteKitDependency(pkg)) {\n const hooks = await findSvelteKitHooks(serviceDir)\n const config = await findSvelteKitConfig(serviceDir)\n if (hooks || config) {\n return () => planSvelteKit(serviceDir, pkg, manifestPath, hooks, project)\n }\n }\n if (hasNuxtDependency(pkg)) {\n const nuxtConfig = await findNuxtConfig(serviceDir)\n if (nuxtConfig) {\n return () => planNuxt(serviceDir, pkg, manifestPath, project)\n }\n }\n if (hasAstroDependency(pkg)) {\n const astroConfig = await findAstroConfig(serviceDir)\n if (astroConfig) {\n return () => planAstro(serviceDir, pkg, manifestPath, project)\n }\n }\n return null\n}\n\nasync function plan(serviceDir: string, opts?: PlanOptions): Promise<InstallPlan> {\n const pkg = await readPackageJson(serviceDir)\n const manifestPath = path.join(serviceDir, 'package.json')\n const project = opts?.project\n const empty: InstallPlan = {\n language: 'javascript',\n serviceDir,\n dependencyEdits: [],\n entrypointEdits: [],\n envEdits: [],\n generatedFiles: [],\n }\n if (!pkg) return empty\n\n // Issue #375 — classification pipeline order: lib-only → framework →\n // runtime-kind → emit. A package with no framework hook AND no resolvable\n // Node entry is lib-only regardless of stray Vite config or Expo deps. The\n // runtime-kind dispatch only fires for non-framework packages that\n // actually have an entry to instrument; without this ordering, a UI library\n // that ships a `vite.config.ts` for its build pipeline would bucket as\n // browser-bundle and surface in the operator summary as if it were a real\n // SPA the installer was choosing to skip.\n const frameworkDispatch = await findFrameworkDispatch(\n serviceDir,\n pkg,\n manifestPath,\n project,\n )\n\n // Resolve the Node entry up front so the lib-only check can read both\n // signals together. Skipped on the framework branch — frameworks own their\n // boot path and never need a `pkg.main` injection (the chain returns\n // before this line runs).\n let entryFile: string | null = null\n if (!frameworkDispatch) {\n entryFile = await resolveEntry(serviceDir, pkg)\n if (!entryFile) {\n return { ...empty, libOnly: true }\n }\n }\n\n if (frameworkDispatch) {\n return frameworkDispatch()\n }\n\n // Issue #370 — runtime-kind detection sits between the lib-only check and\n // vanilla Node template emission. Browser bundles (Vite) and React Native\n // / Expo packages bucket here so the apply phase skips every write and\n // surfaces the package in the summary instead of injecting a Node SDK hook\n // into code that can't run it.\n const runtimeKind = await detectRuntimeKind(serviceDir, pkg)\n if (runtimeKind !== 'node') {\n return { ...empty, runtimeKind }\n }\n\n // entryFile resolved above on the non-framework branch; the null path\n // already returned lib-only.\n if (!entryFile) {\n return { ...empty, libOnly: true }\n }\n const flavor = dispatchEntry(entryFile, pkg)\n const otelInitFile = path.join(path.dirname(entryFile), otelInitFilename(flavor))\n const envNeatFile = path.join(serviceDir, '.env.neat')\n\n // ── Dependency edits (four-deps invariant; ADR-069 §5). ────────────────\n // Issue #376 — non-bundled instrumentations append additional deps when\n // the host package declares libraries whose runtime traffic bypasses the\n // auto-instrumentation set (Prisma's Rust query engine for v0.4.5; the\n // v0.5.0 registry feeds the same loop with more entries).\n const existingDeps = { ...(pkg.dependencies ?? {}), ...(pkg.devDependencies ?? {}) }\n const dependencyEdits: DependencyEdit[] = []\n for (const sdk of SDK_PACKAGES) {\n if (sdk.name in existingDeps) continue\n dependencyEdits.push({\n file: manifestPath,\n kind: 'add',\n name: sdk.name,\n version: sdk.version,\n })\n }\n const nonBundled = detectNonBundledInstrumentations(pkg)\n for (const inst of nonBundled) {\n if (inst.pkg in existingDeps) continue\n dependencyEdits.push({\n file: manifestPath,\n kind: 'add',\n name: inst.pkg,\n version: inst.version,\n })\n }\n\n // ── Entry-point injection edit (ADR-069 §3). ───────────────────────────\n const entrypointEdits: EntrypointEdit[] = []\n try {\n const raw = await fs.readFile(entryFile, 'utf8')\n const lines = raw.split(/\\r?\\n/)\n // Preserve a shebang on line 1 and check line 2 (the first non-shebang\n // line) for an existing injection.\n const firstReal = lines[0]?.startsWith('#!') ? lines[1] ?? '' : lines[0] ?? ''\n if (!lineIsOtelInjection(firstReal)) {\n const inject = injectionLine(flavor, entryFile, otelInitFile)\n // Use the existing first-real line as the `before` marker so the apply\n // phase can splice the injection cleanly even if the file shifts.\n entrypointEdits.push({\n file: entryFile,\n before: firstReal,\n after: inject,\n })\n }\n } catch {\n // Entry file disappeared between resolve and plan (rare). Treat as\n // lib-only.\n return { ...empty, libOnly: true }\n }\n\n // ── Generated files (ADR-069 §1, §4). ──────────────────────────────────\n // v0.4.4 — the otel-init template carries `__SERVICE_NAME__` (the\n // ServiceNode id) and `__PROJECT__` (the URL routing key) placeholders we\n // substitute here. The .env.neat shape lands with the same pair so an\n // operator can grep for both fields in one place.\n // v0.4.5 — `__INSTRUMENTATION_BLOCK__` substitutes to the registration\n // snippets for any non-bundled instrumentations detected above (Prisma\n // for v0.4.5; the v0.5.0 registry will feed more entries through the same\n // path). Empty list collapses cleanly to nothing.\n const svcName = serviceNodeName(pkg, serviceDir)\n const projectName = projectToken(pkg, serviceDir, project)\n const registrations = nonBundled.map((i) => i.registration)\n const generatedFiles: GeneratedFile[] = []\n if (!(await exists(otelInitFile))) {\n generatedFiles.push({\n file: otelInitFile,\n contents: renderNodeOtelInit(\n otelInitContents(flavor),\n svcName,\n projectName,\n registrations,\n ),\n skipIfExists: true,\n })\n }\n if (!(await exists(envNeatFile))) {\n generatedFiles.push({\n file: envNeatFile,\n contents: renderEnvNeat(svcName, projectName),\n skipIfExists: true,\n })\n }\n\n // ── Idempotency check (ADR-069 §6). ────────────────────────────────────\n // If the package is already instrumented end-to-end — deps present, entry\n // already injected, generated files already there — return an empty plan.\n if (\n dependencyEdits.length === 0 &&\n entrypointEdits.length === 0 &&\n generatedFiles.length === 0\n ) {\n return empty\n }\n\n return {\n language: 'javascript',\n serviceDir,\n dependencyEdits,\n entrypointEdits,\n envEdits: [OTEL_ENV],\n generatedFiles,\n entryFile,\n libOnly: false,\n }\n}\n\n// ADR-069 §7 + ADR-073 §1 + ADR-074 §3 — allowed write paths. Anything\n// outside this set inside an installer's apply phase is a contract violation.\nfunction isAllowedWritePath(serviceDir: string, target: string): boolean {\n const rel = path.relative(serviceDir, target)\n if (rel.startsWith('..')) return false\n const base = path.basename(target)\n if (base === 'package.json') return true\n if (base === '.env.neat') return true\n if (/^otel-init\\.(?:js|cjs|mjs|ts)$/.test(base)) return true\n // ADR-073 §1 — Next framework files at the package root, or under src/\n // when create-next-app's --src-dir layout is in use. The instrumentation\n // hook resolves from `src/` in that layout; routing files there is the\n // load-bearing fix for the src-dir shape.\n const relPosix = rel.split(path.sep).join('/')\n if (/^instrumentation(?:\\.node)?\\.(?:js|cjs|mjs|ts)$/.test(base)) {\n if (relPosix === base) return true\n if (relPosix === `src/${base}`) return true\n return false\n }\n if (/^next\\.config\\.(?:js|mjs|ts)$/.test(base)) return true\n // ADR-074 §3 — meta-framework hook surfaces.\n if (relPosix === 'app/otel.server.ts' || relPosix === 'app/otel.server.js') return true\n if (/^app\\/entry\\.server\\.(?:tsx?|jsx?)$/.test(relPosix)) return true\n if (relPosix === 'src/otel-init.ts' || relPosix === 'src/otel-init.js') return true\n if (relPosix === 'src/hooks.server.ts' || relPosix === 'src/hooks.server.js') return true\n if (relPosix === 'server/plugins/otel.ts' || relPosix === 'server/plugins/otel.js') return true\n if (relPosix === 'server/plugins/otel-init.ts' || relPosix === 'server/plugins/otel-init.js') return true\n if (relPosix === 'src/middleware.ts' || relPosix === 'src/middleware.js') return true\n return false\n}\n\nasync function writeAtomic(file: string, contents: string): Promise<void> {\n // Meta-framework branches write to convention-driven subdirs that the user\n // may not have scaffolded yet (`server/plugins/`, `src/`, `app/`). Ensure\n // the parent directory exists before the atomic write; existing parents\n // are a no-op under `recursive: true`.\n await fs.mkdir(path.dirname(file), { recursive: true })\n const tmp = `${file}.${process.pid}.${Date.now()}.tmp`\n await fs.writeFile(tmp, contents, 'utf8')\n await fs.rename(tmp, file)\n}\n\nasync function apply(installPlan: InstallPlan): Promise<ApplyResult> {\n const { serviceDir } = installPlan\n if (installPlan.libOnly) {\n return {\n serviceDir,\n outcome: 'lib-only',\n reason: 'no resolvable entry point',\n writtenFiles: [],\n }\n }\n\n // Issue #370 — non-Node runtimes write nothing. The CLI surfaces the\n // outcome in the summary so the operator can see which packages were\n // skipped and why.\n if (installPlan.runtimeKind === 'browser-bundle') {\n return {\n serviceDir,\n outcome: 'browser-bundle',\n reason: 'browser bundle; Node OTel SDK cannot run here',\n writtenFiles: [],\n }\n }\n if (installPlan.runtimeKind === 'react-native') {\n return {\n serviceDir,\n outcome: 'react-native',\n reason: 'React Native / Expo target; Node OTel SDK cannot run here',\n writtenFiles: [],\n }\n }\n\n // Already-instrumented check: an empty plan means there's nothing to do.\n if (\n installPlan.dependencyEdits.length === 0 &&\n installPlan.entrypointEdits.length === 0 &&\n (installPlan.generatedFiles?.length ?? 0) === 0 &&\n installPlan.nextConfigEdit === undefined\n ) {\n return {\n serviceDir,\n outcome: 'already-instrumented',\n writtenFiles: [],\n }\n }\n\n // Validate every target we plan to touch against the allowed-path set.\n // Bail out before any write if a violation slipped through.\n const allTargets = new Set<string>()\n for (const d of installPlan.dependencyEdits) allTargets.add(d.file)\n for (const e of installPlan.entrypointEdits) allTargets.add(e.file)\n for (const g of installPlan.generatedFiles ?? []) allTargets.add(g.file)\n if (installPlan.nextConfigEdit) allTargets.add(installPlan.nextConfigEdit.file)\n for (const target of allTargets) {\n // Entry-point edits land in user source files, not the allowed set —\n // they're explicitly carved out below.\n const isEntryEdit = installPlan.entrypointEdits.some((e) => e.file === target)\n if (isEntryEdit) continue\n if (!isAllowedWritePath(serviceDir, target)) {\n throw new Error(\n `javascript installer: refusing to write outside the allowed path set (ADR-069 §7): ${target}`,\n )\n }\n }\n\n // Snapshot every file we may touch so a partial failure can roll back the\n // batch (ADR-047 §7). Newly-generated files have no prior contents — they\n // get tracked separately so rollback unlinks them instead of restoring.\n const originals = new Map<string, string>()\n const createdFiles: string[] = []\n for (const target of allTargets) {\n if (await exists(target)) {\n try {\n originals.set(target, await fs.readFile(target, 'utf8'))\n } catch {\n // Best-effort. The mutation loop below will throw if this matters.\n }\n }\n }\n\n const writtenFiles: string[] = []\n try {\n // ── 1. Manifest edits (package.json) ─────────────────────────────────\n const manifestTargets = installPlan.dependencyEdits\n .reduce<Set<string>>((acc, e) => {\n acc.add(e.file)\n return acc\n }, new Set())\n for (const file of manifestTargets) {\n const raw = originals.get(file)\n if (raw === undefined) {\n throw new Error(`javascript installer: cannot read ${file} during apply`)\n }\n const pkg = JSON.parse(raw) as PackageJsonShape\n pkg.dependencies = pkg.dependencies ?? {}\n for (const dep of installPlan.dependencyEdits) {\n if (dep.file !== file) continue\n if (dep.kind === 'add') {\n if (!(dep.name in (pkg.dependencies ?? {}))) {\n pkg.dependencies[dep.name] = dep.version\n }\n // No version bump on existing entries (ADR-069 §6).\n } else {\n delete pkg.dependencies[dep.name]\n }\n }\n const newRaw = JSON.stringify(pkg, null, 2) + '\\n'\n await writeAtomic(file, newRaw)\n writtenFiles.push(file)\n }\n\n // ── 2. Generated files (otel-init, .env.neat) ────────────────────────\n for (const gen of installPlan.generatedFiles ?? []) {\n if (gen.skipIfExists && (await exists(gen.file))) {\n // Skip silently; the contract treats this as part of the\n // already-instrumented path.\n continue\n }\n await writeAtomic(gen.file, gen.contents)\n if (!originals.has(gen.file)) createdFiles.push(gen.file)\n writtenFiles.push(gen.file)\n }\n\n // ── 3. Entry-point injection (require/import on first non-shebang line)\n for (const ep of installPlan.entrypointEdits) {\n const raw = originals.get(ep.file)\n if (raw === undefined) {\n throw new Error(`javascript installer: cannot read entry ${ep.file} during apply`)\n }\n const lines = raw.split(/\\r?\\n/)\n const hasShebang = lines[0]?.startsWith('#!') ?? false\n const insertAt = hasShebang ? 1 : 0\n // Idempotency: if the first non-shebang line already matches our\n // injection pattern, skip — never double-inject.\n const firstReal = lines[insertAt] ?? ''\n if (lineIsOtelInjection(firstReal)) continue\n lines.splice(insertAt, 0, ep.after)\n const newRaw = lines.join('\\n')\n await writeAtomic(ep.file, newRaw)\n writtenFiles.push(ep.file)\n }\n\n // ── 4. Next.js config flag (ADR-073 §1) — only present on the Next\n // path when the declared major is < 15 and the flag isn't already\n // mentioned in the file. Best-effort regex insertion into the first\n // config object literal; bails silently when the shape isn't\n // recognisable so we never corrupt a user-customised config.\n if (installPlan.nextConfigEdit) {\n const target = installPlan.nextConfigEdit.file\n const raw = originals.get(target)\n if (raw !== undefined && !raw.includes('instrumentationHook')) {\n const updated = injectInstrumentationHook(raw)\n if (updated !== null) {\n await writeAtomic(target, updated)\n writtenFiles.push(target)\n }\n }\n }\n } catch (err) {\n await rollback(installPlan, originals, createdFiles)\n throw err\n }\n\n return {\n serviceDir,\n outcome: 'instrumented',\n writtenFiles,\n }\n}\n\nasync function rollback(\n installPlan: InstallPlan,\n originals: Map<string, string>,\n createdFiles: string[],\n): Promise<void> {\n const restored: string[] = []\n const removed: string[] = []\n for (const [file, raw] of originals.entries()) {\n try {\n await fs.writeFile(file, raw, 'utf8')\n restored.push(file)\n } catch {\n // Best-effort: keep going so we restore as much as we can.\n }\n }\n for (const file of createdFiles) {\n try {\n await fs.unlink(file)\n removed.push(file)\n } catch {\n // Best-effort.\n }\n }\n const lines = [\n '# neat-rollback.patch',\n '',\n `# Generated after a partial apply failure in the ${installPlan.language} installer.`,\n '# Files listed below were restored to their pre-apply contents.',\n '',\n ...restored.map((f) => `restored: ${f}`),\n ...removed.map((f) => `removed: ${f}`),\n '',\n ]\n const rollbackPath = path.join(installPlan.serviceDir, 'neat-rollback.patch')\n await fs.writeFile(rollbackPath, lines.join('\\n'), 'utf8')\n}\n\n// ADR-073 §1 — best-effort injection of `experimental.instrumentationHook:\n// true` into a next.config.{js,ts,mjs}. Returns the rewritten contents on\n// success, or null when the config shape isn't recognisable (in which case\n// the apply phase leaves the file alone — partial Next coverage is fine,\n// silent corruption of a user's config is not).\n//\n// Recognised shapes:\n// - `module.exports = { ... }` (CJS)\n// - `module.exports = { ... } satisfies NextConfig` (TS-via-CJS)\n// - `export default { ... }` (ESM / TS)\n// - `const nextConfig = { ... }; module.exports = nextConfig` (named CJS)\n// - `const nextConfig: NextConfig = { ... }; export default nextConfig` (TS)\nexport function injectInstrumentationHook(raw: string): string | null {\n if (raw.includes('instrumentationHook')) return raw\n\n // Strategy: find the first config object literal whose contents we can\n // edit, then either merge into an existing `experimental: { ... }` block\n // or insert a fresh `experimental: { instrumentationHook: true }` entry.\n //\n // We look for one of four anchors near a top-level `{` and splice from\n // there. The regexes capture the `{` so we can splice right after it.\n const anchors: Array<{ pattern: RegExp; label: string }> = [\n { pattern: /(module\\.exports\\s*=\\s*\\{)/, label: 'cjs-default' },\n { pattern: /(export\\s+default\\s*\\{)/, label: 'esm-default' },\n { pattern: /(?:const|let|var)\\s+\\w+(?:\\s*:\\s*[^=]+)?\\s*=\\s*(\\{)/, label: 'named-config' },\n ]\n\n for (const { pattern } of anchors) {\n const match = pattern.exec(raw)\n if (!match) continue\n const insertAfter = match.index + match[0].length\n const before = raw.slice(0, insertAfter)\n const after = raw.slice(insertAfter)\n // Insert a leading newline so the injection sits on its own line and\n // doesn't fight any existing trailing-comma style. Two-space indent\n // covers most code-styled configs.\n const injection = '\\n experimental: { instrumentationHook: true },'\n return `${before}${injection}${after}`\n }\n\n return null\n}\n\nexport const javascriptInstaller: Installer = {\n name: 'javascript',\n detect,\n plan,\n apply,\n}\n\n// Re-exports used by the contract test surface.\nexport { NEXT_INSTRUMENTATION_HEADER, OTEL_INIT_HEADER }\n","/**\n * Generated-file templates for the Node SDK installer (ADR-069 §1).\n *\n * Three flavors so the inserted file matches the host package's module\n * system: CJS for `require`-based packages, ESM for `import`-based, TS for\n * TypeScript entries. Env vars are inlined as `process.env.X ||=` defaults\n * rather than loaded from `.env.neat` at runtime — `__dirname` /\n * `import.meta.url` resolve unpredictably once a bundler rewrites the\n * generated file (Brief-smoke evidence, issue #369), so we let the OTel SDK\n * read its config from the same `process.env` either way. Platform env\n * (Vercel / Railway / Fly / etc.) stays authoritative at deploy time;\n * `||=` keeps the local default for laptop dev only.\n */\n\n// Header comment that ships at the top of every generated otel-init. Stable\n// across flavors so a grep for the header line finds every generated file in\n// a target codebase. Used by the idempotency check too (ADR-069 §6).\nexport const OTEL_INIT_HEADER = '// Generated by `neat init --apply` (ADR-069). OpenTelemetry auto-instrumentation hook.'\n\n// __SERVICE_NAME__ → the ServiceNode id (the package's `pkg.name`, or the\n// directory basename for nameless packages); __PROJECT__ → the registered\n// project basename; __INSTRUMENTATION_BLOCK__ → a (possibly empty) sequence\n// of `instrumentations.push(...)` lines for non-bundled instrumentations\n// (Prisma for v0.4.5; more libraries via the v0.5.0 registry). All three are\n// substituted at apply time via renderNodeOtelInit().\n//\n// v0.4.5 — explicit `NodeSDK` construction replaces the\n// `auto-instrumentations-node/register` shorthand so non-bundled libraries\n// (Prisma's Rust query engine bypasses node-pg; Drizzle, BetterAuth, etc.\n// have their own packages) can compose into the same `instrumentations`\n// array without templating a different file shape per library.\nexport const OTEL_INIT_CJS = `${OTEL_INIT_HEADER}\nprocess.env.OTEL_SERVICE_NAME ||= '__SERVICE_NAME__'\nprocess.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ||= 'http://localhost:4318/projects/__PROJECT__/v1/traces'\n\nconst { NodeSDK } = require('@opentelemetry/sdk-node')\nconst { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node')\n\nconst instrumentations = [getNodeAutoInstrumentations()]\n__INSTRUMENTATION_BLOCK__\nnew NodeSDK({ instrumentations }).start()\n`\n\nexport const OTEL_INIT_ESM = `${OTEL_INIT_HEADER}\nprocess.env.OTEL_SERVICE_NAME ||= '__SERVICE_NAME__'\nprocess.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ||= 'http://localhost:4318/projects/__PROJECT__/v1/traces'\n\nimport { NodeSDK } from '@opentelemetry/sdk-node'\nimport { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node'\n\nconst instrumentations = [getNodeAutoInstrumentations()]\n__INSTRUMENTATION_BLOCK__\nnew NodeSDK({ instrumentations }).start()\n`\n\nexport const OTEL_INIT_TS = `${OTEL_INIT_HEADER}\nprocess.env.OTEL_SERVICE_NAME ||= '__SERVICE_NAME__'\nprocess.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ||= 'http://localhost:4318/projects/__PROJECT__/v1/traces'\n\nimport { NodeSDK } from '@opentelemetry/sdk-node'\nimport { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node'\n\nconst instrumentations = [getNodeAutoInstrumentations()]\n__INSTRUMENTATION_BLOCK__\nnew NodeSDK({ instrumentations }).start()\n`\n\n// Substitute __SERVICE_NAME__, __PROJECT__, and __INSTRUMENTATION_BLOCK__\n// at apply time. The third arg is a list of registration snippets — one per\n// non-bundled instrumentation the installer detected (e.g. Prisma). An empty\n// list collapses the placeholder to nothing so the generated file stays\n// readable on the common \"auto-instrumentations covers everything\" path.\nexport function renderNodeOtelInit(\n template: string,\n serviceName: string,\n projectName: string,\n registrations: readonly string[] = [],\n): string {\n const block = registrations.length === 0 ? '' : `\\n${registrations.join('\\n')}\\n`\n return template\n .replace(/__SERVICE_NAME__/g, serviceName)\n .replace(/__PROJECT__/g, projectName)\n .replace(/__INSTRUMENTATION_BLOCK__\\n?/g, block)\n}\n\n// .env.neat shape (ADR-069 §4, amended v0.4.1 — refs #339, v0.4.4 — refs\n// #367 + #369). Two keys: OTEL_SERVICE_NAME (the ServiceNode id — the\n// package's own name, scope-preserved, so spans land on per-service nodes\n// inside the project's graph) and OTEL_EXPORTER_OTLP_TRACES_ENDPOINT (the\n// project-scoped URL the daemon mounts at /projects/<project>/v1/traces).\n// Both env vars are advisory only — the generated `otel-init` inlines them\n// via `process.env.X ||=` so bundlers can't lose them; the file is kept so\n// operators can grep for service.name → project mapping in one place.\nexport function renderEnvNeat(serviceName: string, projectName: string): string {\n return [\n '# Generated by `neat init --apply` (ADR-069).',\n `OTEL_SERVICE_NAME=${serviceName}`,\n `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://localhost:4318/projects/${projectName}/v1/traces`,\n '',\n ].join('\\n')\n}\n\n// ── Next.js framework-aware templates (ADR-073 §1, ADR-069 §3). ─────────\n//\n// Next.js owns its own boot — `pkg.main` is unused, and the auto-instrumentation\n// register hook can't run before user code. Next 13+ ships an `instrumentation`\n// file at the project root with an async `register()` export the framework\n// invokes during server start (Node runtime only). For Edge / browser runtimes\n// the file is ignored.\n//\n// Two-file shape: `instrumentation.{ts,js}` keeps the runtime gate so the\n// Node SDK doesn't load on the Edge runtime; `instrumentation.node.{ts,js}`\n// carries the SDK init itself. Both files sit at the project root.\n\nexport const NEXT_INSTRUMENTATION_HEADER =\n '// Generated by `neat init --apply` (ADR-073). Next.js instrumentation hook.'\n\nexport const NEXT_INSTRUMENTATION_TS = `${NEXT_INSTRUMENTATION_HEADER}\nexport async function register() {\n if (process.env.NEXT_RUNTIME === 'nodejs') {\n await import('./instrumentation.node')\n }\n}\n`\n\nexport const NEXT_INSTRUMENTATION_JS = `${NEXT_INSTRUMENTATION_HEADER}\nexport async function register() {\n if (process.env.NEXT_RUNTIME === 'nodejs') {\n await import('./instrumentation.node')\n }\n}\n`\n\n// Env vars are inlined as process.env defaults so they survive Turbopack /\n// Webpack bundling — `import.meta.url` resolves to a path under .next/dev/\n// server/chunks/ once Next compiles this file, which would miss .env.neat.\n// `process.env.X ||=` keeps platform env (Vercel / Railway / Fly / etc.)\n// authoritative at deploy time while the local default carries the routing\n// key the daemon needs to map spans back to this project. The endpoint uses\n// the project-scoped URL form so the daemon never has to guess which project\n// owns the span (issue #367); the OTel SDK reads the env vars from\n// process.env directly, so no file-system lookup is required at runtime.\nexport const NEXT_INSTRUMENTATION_NODE_TS = `${NEXT_INSTRUMENTATION_HEADER}\nprocess.env.OTEL_SERVICE_NAME ||= '__SERVICE_NAME__'\nprocess.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ||= 'http://localhost:4318/projects/__PROJECT__/v1/traces'\n\nimport { NodeSDK } from '@opentelemetry/sdk-node'\nimport { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node'\n\nconst instrumentations = [getNodeAutoInstrumentations()]\n__INSTRUMENTATION_BLOCK__\nnew NodeSDK({ instrumentations }).start()\n`\n\nexport const NEXT_INSTRUMENTATION_NODE_JS = `${NEXT_INSTRUMENTATION_HEADER}\nprocess.env.OTEL_SERVICE_NAME ||= '__SERVICE_NAME__'\nprocess.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ||= 'http://localhost:4318/projects/__PROJECT__/v1/traces'\n\nconst { NodeSDK } = require('@opentelemetry/sdk-node')\nconst { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node')\n\nconst instrumentations = [getNodeAutoInstrumentations()]\n__INSTRUMENTATION_BLOCK__\nnew NodeSDK({ instrumentations }).start()\n`\n\n// Substitute the placeholders at apply time so the generated file carries the\n// ServiceNode id (`__SERVICE_NAME__`) and the registered project name\n// (`__PROJECT__`) verbatim. The two roles diverged in v0.4.4: the service name\n// names the ServiceNode inside one project's graph, the project basename is\n// the URL routing key. v0.4.5 adds __INSTRUMENTATION_BLOCK__ — a (possibly\n// empty) sequence of `instrumentations.push(...)` calls for non-bundled\n// libraries like Prisma whose query engines bypass the auto-instrumentation\n// set's coverage.\nexport function renderNextInstrumentationNode(\n template: string,\n serviceName: string,\n projectName: string,\n registrations: readonly string[] = [],\n): string {\n const block = registrations.length === 0 ? '' : `\\n${registrations.join('\\n')}\\n`\n return template\n .replace(/__SERVICE_NAME__/g, serviceName)\n .replace(/__PROJECT__/g, projectName)\n .replace(/__INSTRUMENTATION_BLOCK__\\n?/g, block)\n}\n\n// ── Meta-framework templates (ADR-074 §3). ──────────────────────────────\n//\n// Remix, SvelteKit, Nuxt, and Astro each own their boot path. The installer\n// emits one OTel-init module that loads `.env.neat` and starts the Node SDK,\n// then either creates or injects an import into the framework's canonical\n// hook file. Templates mirror the Next.js pair in shape — one generated init\n// module, one optional framework-hook stub for the absent-file case.\n\nexport const FRAMEWORK_OTEL_INIT_HEADER =\n '// Generated by `neat init --apply` (ADR-074). OpenTelemetry SDK hook.'\n\n// Same inline-defaults pattern as the plain-Node + Next templates: env vars\n// arrive on `process.env` via the apply-time substitution below so bundler\n// path mangling (issue #369) can't lose them. `__SERVICE_NAME__` /\n// `__PROJECT__` are substituted via renderFrameworkOtelInit().\nconst FRAMEWORK_OTEL_INIT_TS_BODY = `${FRAMEWORK_OTEL_INIT_HEADER}\nprocess.env.OTEL_SERVICE_NAME ||= '__SERVICE_NAME__'\nprocess.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ||= 'http://localhost:4318/projects/__PROJECT__/v1/traces'\n\nimport { NodeSDK } from '@opentelemetry/sdk-node'\nimport { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node'\n\nconst sdk = new NodeSDK({\n serviceName: process.env.OTEL_SERVICE_NAME,\n instrumentations: [getNodeAutoInstrumentations()],\n})\nsdk.start()\n`\n\nconst FRAMEWORK_OTEL_INIT_JS_BODY = `${FRAMEWORK_OTEL_INIT_HEADER}\nprocess.env.OTEL_SERVICE_NAME ||= '__SERVICE_NAME__'\nprocess.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ||= 'http://localhost:4318/projects/__PROJECT__/v1/traces'\n\nconst { NodeSDK } = require('@opentelemetry/sdk-node')\nconst { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node')\n\nconst sdk = new NodeSDK({\n serviceName: process.env.OTEL_SERVICE_NAME,\n instrumentations: [getNodeAutoInstrumentations()],\n})\nsdk.start()\n`\n\nexport function renderFrameworkOtelInit(\n template: string,\n serviceName: string,\n projectName: string,\n): string {\n return template\n .replace(/__SERVICE_NAME__/g, serviceName)\n .replace(/__PROJECT__/g, projectName)\n}\n\n// Remix — `app/otel.server.{ts,js}` carries the SDK bootstrap. The framework\n// loads `entry.server.*` at server-process start, and a top-of-module import\n// of `./otel.server` runs the bootstrap before any request handler imports.\nexport const REMIX_OTEL_SERVER_TS = FRAMEWORK_OTEL_INIT_TS_BODY\nexport const REMIX_OTEL_SERVER_JS = FRAMEWORK_OTEL_INIT_JS_BODY\n\n// SvelteKit — `src/otel-init.{ts,js}` carries the SDK bootstrap; the\n// framework's `src/hooks.server.{ts,js}` imports it. When hooks.server is\n// absent, the installer writes the stub below alongside the import.\nexport const SVELTEKIT_OTEL_INIT_TS = FRAMEWORK_OTEL_INIT_TS_BODY\nexport const SVELTEKIT_OTEL_INIT_JS = FRAMEWORK_OTEL_INIT_JS_BODY\n\nexport const SVELTEKIT_HOOKS_SERVER_TS = `${FRAMEWORK_OTEL_INIT_HEADER}\nimport './otel-init'\n\nimport type { Handle } from '@sveltejs/kit'\n\nexport const handle: Handle = async ({ event, resolve }) => {\n return resolve(event)\n}\n`\n\nexport const SVELTEKIT_HOOKS_SERVER_JS = `${FRAMEWORK_OTEL_INIT_HEADER}\nimport './otel-init'\n\n/** @type {import('@sveltejs/kit').Handle} */\nexport const handle = async ({ event, resolve }) => {\n return resolve(event)\n}\n`\n\n// Nuxt — `server/plugins/otel.{ts,js}` is the convention-loaded plugin file;\n// it imports the sibling `otel-init.{ts,js}` which carries the SDK bootstrap.\nexport const NUXT_OTEL_INIT_TS = FRAMEWORK_OTEL_INIT_TS_BODY\nexport const NUXT_OTEL_INIT_JS = FRAMEWORK_OTEL_INIT_JS_BODY\n\nexport const NUXT_OTEL_PLUGIN_TS = `${FRAMEWORK_OTEL_INIT_HEADER}\nimport './otel-init'\n\nexport default defineNitroPlugin(() => {\n // OTel SDK is initialised at module-load via the side-effect import above.\n})\n`\n\nexport const NUXT_OTEL_PLUGIN_JS = `${FRAMEWORK_OTEL_INIT_HEADER}\nrequire('./otel-init')\n\nmodule.exports = defineNitroPlugin(() => {\n // OTel SDK is initialised at module-load via the side-effect import above.\n})\n`\n\n// Astro — `src/middleware.{ts,js}` runs once at module-load (and then per\n// request via onRequest). The top-of-module import of `./otel-init` boots\n// the SDK before the first request lands.\nexport const ASTRO_OTEL_INIT_TS = FRAMEWORK_OTEL_INIT_TS_BODY\nexport const ASTRO_OTEL_INIT_JS = FRAMEWORK_OTEL_INIT_JS_BODY\n\nexport const ASTRO_MIDDLEWARE_TS = `${FRAMEWORK_OTEL_INIT_HEADER}\nimport './otel-init'\n\nimport { defineMiddleware } from 'astro:middleware'\n\nexport const onRequest = defineMiddleware(async (context, next) => {\n return next()\n})\n`\n\nexport const ASTRO_MIDDLEWARE_JS = `${FRAMEWORK_OTEL_INIT_HEADER}\nimport './otel-init'\n\nimport { defineMiddleware } from 'astro:middleware'\n\nexport const onRequest = defineMiddleware(async (context, next) => {\n return next()\n})\n`\n","/**\n * Python SDK installer (ADR-047).\n *\n * `detect` matches on the canonical Python project markers — requirements.txt,\n * pyproject.toml, setup.py. `plan` produces dependency edits against the\n * primary manifest and entrypoint edits against a Procfile when one exists.\n *\n * MVP scope:\n * - requirements.txt is the full-fidelity manifest (read / append).\n * - pyproject.toml dependencies live inside a TOML `dependencies = [...]`\n * block; we line-insert into that block when found, otherwise hold off\n * on rewriting until a successor ADR addresses TOML editing properly.\n * - Procfile lines starting with `python` get prefixed with\n * `opentelemetry-instrument`.\n *\n * Lockfiles (poetry.lock, Pipfile.lock) are never touched. After `--apply`,\n * init's summary tells the user to run `pip install -r requirements.txt`\n * (or `poetry lock && poetry install`) so they own the lockfile commit.\n */\n\nimport { promises as fs } from 'node:fs'\nimport path from 'node:path'\nimport type {\n ApplyResult,\n DependencyEdit,\n EntrypointEdit,\n EnvEdit,\n Installer,\n InstallPlan,\n} from './shared.js'\n\nconst SDK_PACKAGES = [\n { name: 'opentelemetry-distro', version: '>=0.49b0' },\n { name: 'opentelemetry-exporter-otlp', version: '>=1.28.0' },\n] as const\n\nconst OTEL_ENV: EnvEdit = {\n file: null,\n key: 'OTEL_EXPORTER_OTLP_ENDPOINT',\n value: 'http://localhost:4318',\n}\n\nasync function exists(p: string): Promise<boolean> {\n try {\n await fs.stat(p)\n return true\n } catch {\n return false\n }\n}\n\nasync function detect(serviceDir: string): Promise<boolean> {\n const markers = ['requirements.txt', 'pyproject.toml', 'setup.py']\n for (const m of markers) {\n if (await exists(path.join(serviceDir, m))) return true\n }\n return false\n}\n\n// Strip a requirements.txt line down to its lower-cased package name.\n// `flask==3.0.0` → `flask`, `Flask>=2 ; python_version>\"3.6\"` → `flask`.\nfunction reqPackageName(line: string): string {\n const stripped = line.split('#')[0]?.trim() ?? ''\n const head = stripped.split(/[\\s;]/)[0] ?? ''\n return head.replace(/[<>=!~].*$/, '').toLowerCase()\n}\n\nasync function planRequirementsTxtEdits(\n serviceDir: string,\n): Promise<{ manifest: string; missing: typeof SDK_PACKAGES[number][] } | null> {\n const file = path.join(serviceDir, 'requirements.txt')\n if (!(await exists(file))) return null\n const raw = await fs.readFile(file, 'utf8')\n const presentNames = new Set(\n raw\n .split(/\\r?\\n/)\n .map(reqPackageName)\n .filter((n) => n.length > 0),\n )\n const missing = SDK_PACKAGES.filter((p) => !presentNames.has(p.name.toLowerCase()))\n return { manifest: file, missing: [...missing] }\n}\n\nasync function planProcfileEdits(serviceDir: string): Promise<EntrypointEdit[]> {\n const procfile = path.join(serviceDir, 'Procfile')\n if (!(await exists(procfile))) return []\n const raw = await fs.readFile(procfile, 'utf8')\n const edits: EntrypointEdit[] = []\n for (const line of raw.split(/\\r?\\n/)) {\n if (line.length === 0) continue\n // Procfile lines look like `<process>: <cmd>`. Prefix the cmd when it\n // starts with python and isn't already wrapped.\n const m = line.match(/^([a-zA-Z0-9_-]+):\\s*(.+)$/)\n if (!m) continue\n const cmd = m[2]!\n if (!/^python\\b/.test(cmd)) continue\n if (cmd.startsWith('opentelemetry-instrument ')) continue\n const after = `${m[1]}: opentelemetry-instrument ${cmd}`\n edits.push({ file: procfile, before: line, after })\n }\n return edits\n}\n\nasync function plan(serviceDir: string): Promise<InstallPlan> {\n const empty: InstallPlan = {\n language: 'python',\n serviceDir,\n dependencyEdits: [],\n entrypointEdits: [],\n envEdits: [],\n }\n\n const dependencyEdits: DependencyEdit[] = []\n const reqs = await planRequirementsTxtEdits(serviceDir)\n if (reqs) {\n for (const sdk of reqs.missing) {\n dependencyEdits.push({\n file: reqs.manifest,\n kind: 'add',\n name: sdk.name,\n version: sdk.version,\n })\n }\n }\n // pyproject.toml / setup.py without requirements.txt: deferred to a\n // successor ADR. The patch will note it; apply is a no-op for those\n // manifests in the MVP.\n\n const entrypointEdits = await planProcfileEdits(serviceDir)\n\n if (dependencyEdits.length === 0 && entrypointEdits.length === 0) {\n return empty\n }\n return {\n language: 'python',\n serviceDir,\n dependencyEdits,\n entrypointEdits,\n envEdits: [OTEL_ENV],\n }\n}\n\nasync function applyRequirementsTxt(\n manifest: string,\n edits: DependencyEdit[],\n original: string,\n): Promise<void> {\n // Append missing packages on their own lines. Preserve a trailing newline.\n const newlines = edits\n .filter((e) => e.kind === 'add')\n .map((e) => `${e.name}${e.version}`)\n const trailing = original.endsWith('\\n') ? '' : '\\n'\n const next = `${original}${trailing}${newlines.join('\\n')}\\n`\n const tmp = `${manifest}.${process.pid}.${Date.now()}.tmp`\n await fs.writeFile(tmp, next, 'utf8')\n await fs.rename(tmp, manifest)\n}\n\nasync function applyProcfile(\n procfile: string,\n edits: EntrypointEdit[],\n original: string,\n): Promise<void> {\n let next = original\n for (const e of edits) {\n if (!next.includes(e.before)) continue\n next = next.replace(e.before, e.after)\n }\n const tmp = `${procfile}.${process.pid}.${Date.now()}.tmp`\n await fs.writeFile(tmp, next, 'utf8')\n await fs.rename(tmp, procfile)\n}\n\nasync function apply(installPlan: InstallPlan): Promise<ApplyResult> {\n const { serviceDir } = installPlan\n const touched = new Set<string>()\n for (const e of installPlan.dependencyEdits) touched.add(e.file)\n for (const e of installPlan.entrypointEdits) touched.add(e.file)\n if (touched.size === 0) {\n return { serviceDir, outcome: 'already-instrumented', writtenFiles: [] }\n }\n\n const originals = new Map<string, string>()\n for (const file of touched) {\n try {\n originals.set(file, await fs.readFile(file, 'utf8'))\n } catch {\n // Mutation will fail loudly below; rollback covers what did land.\n }\n }\n\n const writtenFiles: string[] = []\n try {\n for (const file of touched) {\n const raw = originals.get(file)\n if (raw === undefined) {\n throw new Error(`python installer: cannot read ${file} during apply`)\n }\n const base = path.basename(file)\n if (base === 'requirements.txt') {\n const edits = installPlan.dependencyEdits.filter((e) => e.file === file)\n if (edits.length > 0) {\n await applyRequirementsTxt(file, edits, raw)\n writtenFiles.push(file)\n }\n } else if (base === 'Procfile') {\n const edits = installPlan.entrypointEdits.filter((e) => e.file === file)\n if (edits.length > 0) {\n await applyProcfile(file, edits, raw)\n writtenFiles.push(file)\n }\n }\n // pyproject.toml / setup.py: MVP no-op as planned above.\n }\n } catch (err) {\n await rollback(installPlan, originals)\n throw err\n }\n\n return { serviceDir, outcome: 'instrumented', writtenFiles }\n}\n\nasync function rollback(\n installPlan: InstallPlan,\n originals: Map<string, string>,\n): Promise<void> {\n const restored: string[] = []\n for (const [file, raw] of originals.entries()) {\n try {\n await fs.writeFile(file, raw, 'utf8')\n restored.push(file)\n } catch {\n // Best-effort.\n }\n }\n const lines = [\n '# neat-rollback.patch',\n '',\n `# Generated after a partial apply failure in the ${installPlan.language} installer.`,\n '# Files listed below were restored to their pre-apply contents.',\n '',\n ...restored.map((f) => `restored: ${f}`),\n '',\n ]\n const rollbackPath = path.join(installPlan.serviceDir, 'neat-rollback.patch')\n await fs.writeFile(rollbackPath, lines.join('\\n'), 'utf8')\n}\n\nexport const pythonInstaller: Installer = {\n name: 'python',\n detect,\n plan,\n apply,\n}\n","/**\n * Shared types for SDK installer modules (ADR-047).\n *\n * Each language has its own installer at `installers/<language>.ts` exporting\n * a `detect / plan / apply` triple. Plans are pure data — no fs side effects\n * during planning — so `init --dry-run` can render a patch without ever\n * touching the project. `apply` runs the codemod in place.\n *\n * Step 2 (this PR) ships the interface and an empty registry. Step 3 (Node\n * installer) and step 4 (Python installer) populate it.\n */\n\n// Field names match ADR-047's documented patch shape exactly: `file`, `kind`,\n// `name`, `version`. Patches will be reviewed by humans and matched in tests\n// by name; renaming for clarity would have cost more than it bought.\n\nexport interface DependencyEdit {\n file: string\n kind: 'add' | 'remove'\n name: string\n version: string\n}\n\nexport interface EntrypointEdit {\n file: string\n before: string\n after: string\n}\n\nexport interface EnvEdit {\n // `null` denotes a recommendation only — the user will set the env var in\n // their orchestration layer, NEAT does not write a `.env` file.\n file: string | null\n key: string\n value: string\n}\n\n// Files the installer generates from scratch (ADR-069 §1). The generated\n// `otel-init.{js,ts}` for the Node installer rides here, along with the\n// per-package `.env.neat` (ADR-069 §4). Treated as additive writes — the\n// apply phase skips any file already present (ADR-069 §6).\nexport interface GeneratedFile {\n file: string\n contents: string\n // When true, write only if the file does not already exist. The apply\n // phase logs an `already instrumented` / `already present` notice instead\n // of overwriting (ADR-069 §6).\n skipIfExists?: boolean\n}\n\nexport interface InstallPlan {\n // Free-form language tag matching the service node's language: `'javascript'`,\n // `'python'`, …\n language: string\n // Service directory the plan targets. Absolute path.\n serviceDir: string\n dependencyEdits: DependencyEdit[]\n entrypointEdits: EntrypointEdit[]\n envEdits: EnvEdit[]\n // ADR-069 §1, §4 — generated files (otel-init, .env.neat). Optional so\n // installers that don't generate files (the Python installer at MVP) can\n // omit it.\n generatedFiles?: GeneratedFile[]\n // ADR-069 §2 — flagged when entry-point resolution found nothing.\n // The apply phase records this in the summary and skips all file writes\n // for the package.\n libOnly?: boolean\n // ADR-069 §2 — resolved entry-point path (absolute). Present when the\n // installer is going to inject the require/import. Absent for libOnly\n // packages and for the Python installer.\n entryFile?: string\n // ADR-073 §1 + ADR-074 §3 — when a framework owns its own boot, the\n // installer skips `pkg.main` injection and emits framework-native\n // instrumentation files instead. Five values today: Next.js from v0.3.8,\n // then Remix / SvelteKit / Nuxt / Astro from v0.3.9.\n framework?: 'next' | 'remix' | 'sveltekit' | 'nuxt' | 'astro'\n // v0.4.4 / issue #370 — when a JavaScript package isn't a Node service\n // (browser bundle, React Native), the installer records the runtime here\n // and writes nothing. Absent → vanilla Node default (the existing apply\n // path). Browser-side OTel support (`@opentelemetry/sdk-trace-web`) lands\n // in a future release.\n runtimeKind?: 'browser-bundle' | 'react-native'\n // ADR-073 §1 — Next.js' `next.config.{js,ts,mjs}` may need the\n // `experimental.instrumentationHook: true` flag set when the major\n // version is < 15. The apply phase mutates the file in place when this\n // field is set. Absent → no config mutation planned.\n nextConfigEdit?: {\n file: string\n // Reason this edit is queued — surfaces in the dry-run patch and the\n // apply summary so the operator knows why their next.config moved.\n reason: string\n }\n}\n\n// ADR-069 §9 — apply outcome per service. The CLI surfaces these counts\n// at the end of `neat init --apply`. v0.4.4 / issue #370 — two new buckets\n// for non-Node JavaScript runtimes: `browser-bundle` (Vite, esbuild-shipped\n// SPAs) and `react-native` (Expo / RN bare). The Node SDK can't run in\n// either; both buckets skip every write and surface the package in the\n// summary so the operator knows the frontend wasn't instrumented.\nexport type ApplyOutcome =\n | 'instrumented'\n | 'already-instrumented'\n | 'lib-only'\n | 'failed'\n | 'browser-bundle'\n | 'react-native'\n\nexport interface ApplyResult {\n serviceDir: string\n outcome: ApplyOutcome\n // Free-form reason string for `lib-only` / `failed` outcomes. Surfaced\n // in the CLI summary so the user knows why a package was skipped.\n reason?: string\n // Absolute paths the apply phase actually wrote to. Used by the contract\n // test that asserts the allowed-path-set restriction (ADR-069 §7).\n writtenFiles: string[]\n}\n\n// Plan-time inputs the orchestrator threads through (v0.4.1 — refs #339).\n// `project` is the registered project name — the routing key the daemon\n// owns. When present the installer writes it as `OTEL_SERVICE_NAME` so the\n// OTLP wire and the registry agree end-to-end. Absent → installers fall\n// back to a package-local default for ad-hoc / test usage.\nexport interface PlanOptions {\n project?: string\n}\n\nexport interface Installer {\n // Free-form module name. Used for the patch header and for diagnostics.\n name: string\n // Returns true if the installer thinks `serviceDir` is shaped like a project\n // it can instrument. Cheap; no fs writes.\n detect(serviceDir: string): boolean | Promise<boolean>\n // Builds an `InstallPlan` describing the edits the installer would make.\n // Pure data; no fs writes. An empty plan (every edits array empty) means\n // the SDK is already installed and there is nothing to do.\n plan(serviceDir: string, opts?: PlanOptions): InstallPlan | Promise<InstallPlan>\n // Apply a previously-produced plan. Mutates files in place. On failure,\n // produces `<serviceDir>/neat-rollback.patch` per ADR-047 #7. Returns a\n // structured outcome so the CLI can surface coverage (ADR-069 §9).\n apply(plan: InstallPlan): Promise<ApplyResult>\n}\n\nexport function isEmptyPlan(plan: InstallPlan): boolean {\n return (\n plan.dependencyEdits.length === 0 &&\n plan.entrypointEdits.length === 0 &&\n plan.envEdits.length === 0 &&\n (plan.generatedFiles?.length ?? 0) === 0 &&\n plan.nextConfigEdit === undefined\n )\n}\n","/**\n * Installer registry. v0.2.5 step 2 ships the scaffolding; the JavaScript\n * installer (step 3) and Python installer (step 4) populate `INSTALLERS`.\n */\n\nimport type { Installer, InstallPlan } from './shared.js'\nimport { javascriptInstaller } from './javascript.js'\nimport { pythonInstaller } from './python.js'\nexport { isEmptyPlan } from './shared.js'\nexport { javascriptInstaller } from './javascript.js'\nexport { pythonInstaller } from './python.js'\nexport type {\n ApplyOutcome,\n ApplyResult,\n DependencyEdit,\n EntrypointEdit,\n EnvEdit,\n GeneratedFile,\n Installer,\n InstallPlan,\n} from './shared.js'\n\n// Lockfile basenames installers must never write to (ADR-047 — \"lockfiles\n// never touched\"). Used by the patch renderer's safety check below.\nexport const FORBIDDEN_LOCKFILES: ReadonlySet<string> = new Set([\n 'package-lock.json',\n 'pnpm-lock.yaml',\n 'yarn.lock',\n 'poetry.lock',\n 'Pipfile.lock',\n 'Gemfile.lock',\n 'Cargo.lock',\n 'go.sum',\n])\n\n// Order is priority — first match wins per service. JavaScript leads because\n// it's the most common shape in the projects NEAT targets; Python follows.\nexport const INSTALLERS: Installer[] = [javascriptInstaller, pythonInstaller]\n\n/**\n * Resolve the first installer that claims a given service directory. Returns\n * `null` if none match.\n *\n * Per language, the first matching installer wins. Order in `INSTALLERS`\n * defines that priority — declarations are explicit, not alphabetical.\n */\nexport async function pickInstaller(serviceDir: string): Promise<Installer | null> {\n for (const inst of INSTALLERS) {\n if (await inst.detect(serviceDir)) return inst\n }\n return null\n}\n\nexport interface PatchSection {\n installer: string\n plan: InstallPlan\n}\n\n/**\n * Render install plans into a single review-friendly text patch. The format\n * is intentionally human-shaped, not unified-diff: agents and humans both\n * read this. Determinism — same input, byte-identical output — is the\n * load-bearing property (ADR-047 #6).\n */\nexport function renderPatch(sections: PatchSection[]): string {\n if (sections.length === 0) {\n return [\n '# neat install plan',\n '',\n 'No SDK installers matched the discovered services. Two reasons this',\n 'normally happens:',\n ' - the project uses a language NEAT does not yet instrument',\n ' (Java / Ruby / .NET / Go / Rust are out of MVP scope per ADR-047);',\n ' - the SDK is already installed, so the installer returned an empty',\n ' plan.',\n '',\n 'You can re-run `neat init --apply` later to pick up new services.',\n '',\n ].join('\\n')\n }\n\n const lines: string[] = ['# neat install plan', '']\n for (const section of sections) {\n const { installer, plan } = section\n lines.push(`## ${installer} (${plan.language}) — ${plan.serviceDir}`)\n lines.push('')\n\n if (plan.libOnly) {\n lines.push('### skipped — no resolvable entry point (lib-only)')\n lines.push('')\n continue\n }\n\n if (plan.entryFile) {\n lines.push(`entry: ${plan.entryFile}`)\n lines.push('')\n }\n\n if (plan.dependencyEdits.length > 0) {\n lines.push('### dependencies')\n // Group by manifest file so each section names the path the apply phase\n // will write, satisfying the dry-run/apply path-parity contract\n // (ADR-069 §8).\n const byFile = new Map<string, typeof plan.dependencyEdits>()\n for (const dep of plan.dependencyEdits) {\n // Hard-fail rather than render a patch that could mislead the user\n // into thinking NEAT touches lockfiles.\n const base = dep.file.split(/[\\\\/]/).pop() ?? dep.file\n if (FORBIDDEN_LOCKFILES.has(base)) {\n throw new Error(\n `installer \"${installer}\" produced a dependency edit against a lockfile (${dep.file}); ` +\n `lockfiles must never be touched (ADR-047).`,\n )\n }\n const existing = byFile.get(dep.file) ?? []\n existing.push(dep)\n byFile.set(dep.file, existing)\n }\n for (const [file, deps] of byFile) {\n lines.push(`--- ${file}`)\n for (const dep of deps) {\n lines.push(`+ \"${dep.name}\": \"${dep.version}\"`)\n }\n }\n lines.push('')\n }\n\n if (plan.generatedFiles && plan.generatedFiles.length > 0) {\n lines.push('### generated files')\n for (const gen of plan.generatedFiles) {\n lines.push(`--- (new file) ${gen.file}`)\n for (const ln of gen.contents.split(/\\r?\\n/)) {\n lines.push(`+ ${ln}`)\n }\n }\n lines.push('')\n }\n\n if (plan.entrypointEdits.length > 0) {\n lines.push('### entry-point injection')\n for (const e of plan.entrypointEdits) {\n lines.push(`--- ${e.file}`)\n lines.push(`+ ${e.after}`)\n lines.push(` ${e.before}`)\n }\n lines.push('')\n }\n\n if (plan.envEdits.length > 0) {\n lines.push('### env (written to <package-dir>/.env.neat)')\n for (const env of plan.envEdits) {\n lines.push(`- ${env.key}=${env.value}`)\n }\n lines.push('')\n }\n\n // ADR-073 §1 — surface the next.config edit in the dry-run patch so the\n // operator can review the framework-flag change before it lands.\n if (plan.nextConfigEdit) {\n lines.push('### next.config (framework flag)')\n lines.push(`--- ${plan.nextConfigEdit.file}`)\n lines.push(`+ experimental: { instrumentationHook: true }, // ${plan.nextConfigEdit.reason}`)\n lines.push('')\n }\n }\n return lines.join('\\n')\n}\n","/**\n * One-command orchestrator (ADR-073 §1).\n *\n * Bare `neat <path>` dispatches here when the first positional argument\n * resolves to a directory and doesn't match a registered verb. Six steps,\n * in order:\n *\n * 1. Discovery + extraction (per static-extraction contract).\n * 2. `.gitignore` automation (ADR-073 §6) + project registration.\n * 3. SDK install apply — patches manifests + writes otel-init + writes\n * `.env.neat`. Default yes; `--no-instrument` opts out.\n * 4. Daemon spawn — `neatd start --detach` if no daemon is running.\n * Polls `/health` up to 15s for readiness.\n * 5. Browser open against the web UI on port 6328 (T9 NEAT).\n * Default yes; `--no-open` and headless runs skip the launch.\n * 6. Summary block — value-forward findings + OTel env-vars block.\n *\n * `neat init` retains its patch-by-default contract (ADR-046 §5). The\n * orchestrator runs apply unconditionally because the bare-`<path>` shape's\n * user intent is \"make this work end-to-end.\"\n */\n\nimport { promises as fs } from 'node:fs'\nimport http from 'node:http'\nimport net from 'node:net'\nimport path from 'node:path'\nimport { spawn } from 'node:child_process'\nimport readline from 'node:readline'\nimport type { GraphEdge, GraphNode } from '@neat.is/types'\nimport { DEFAULT_PROJECT, getGraph, resetGraph } from './graph.js'\nimport { extractFromDirectory } from './extract.js'\nimport { discoverServices } from './extract/services.js'\nimport { ensureNeatOutIgnored } from './gitignore.js'\nimport { saveGraphToDisk } from './persist.js'\nimport { pathsForProject } from './projects.js'\nimport { addProject, listProjects, ProjectNameCollisionError, setStatus } from './registry.js'\nimport {\n isEmptyPlan,\n pickInstaller,\n type InstallPlan,\n} from './installers/index.js'\n\nexport interface OrchestratorOptions {\n scanPath: string\n // Project name resolution mirrors `neat init` — basename of the scan\n // path unless overridden via --project.\n project: string\n projectExplicit: boolean\n // Skip step 3 (SDK install apply).\n noInstrument: boolean\n // Skip step 5 (browser open).\n noOpen: boolean\n // Skip the interactive prompt (CI invocation flag — implied when\n // stdin/stdout aren't a TTY).\n yes: boolean\n // Dashboard URL — defaults to http://localhost:6328 (T9 NEAT, ADR-059).\n dashboardUrl?: string\n // Health-check timeout in ms. Default 15s.\n daemonReadyTimeoutMs?: number\n}\n\nexport interface OrchestratorResult {\n exitCode: number\n // High-level step-by-step status for the test surface.\n steps: {\n discovery: { services: number; languages: string[] }\n extraction: { nodesAdded: number; edgesAdded: number }\n gitignore: 'added' | 'created' | 'unchanged'\n apply: { instrumented: number; alreadyInstrumented: number; libOnly: number; skipped: boolean }\n daemon: 'spawned' | 'already-running' | 'timed-out' | 'skipped'\n browser: 'opened' | 'skipped' | 'failed'\n }\n}\n\n// Shared sub-pipeline `neat sync` re-uses (ADR-074 §1). Discovery + extract\n// + snapshot write. Distinct from the first-run-only steps (registry add,\n// daemon spawn, browser open, summary block) that the orchestrator owns\n// directly.\nexport interface ExtractAndPersistOptions {\n scanPath: string\n project: string\n projectExplicit: boolean\n // When true, skip persisting to disk — for `neat sync --dry-run`.\n dryRun?: boolean\n}\n\nexport interface ExtractAndPersistResult {\n graph: ReturnType<typeof getGraph>\n graphKey: string\n services: Awaited<ReturnType<typeof discoverServices>>\n languages: string[]\n nodesAdded: number\n edgesAdded: number\n snapshotPath: string\n errorsPath: string\n}\n\nexport async function extractAndPersist(\n opts: ExtractAndPersistOptions,\n): Promise<ExtractAndPersistResult> {\n const services = await discoverServices(opts.scanPath)\n const languages = [...new Set(services.map((s) => s.node.language))].sort()\n\n const graphKey = opts.projectExplicit ? opts.project : DEFAULT_PROJECT\n resetGraph(graphKey)\n const graph = getGraph(graphKey)\n const projectPaths = pathsForProject(graphKey, path.join(opts.scanPath, 'neat-out'))\n const extraction = await extractFromDirectory(graph, opts.scanPath, {\n errorsPath: projectPaths.errorsPath,\n })\n if (!opts.dryRun) {\n await saveGraphToDisk(graph, projectPaths.snapshotPath)\n }\n return {\n graph,\n graphKey,\n services,\n languages,\n nodesAdded: extraction.nodesAdded,\n edgesAdded: extraction.edgesAdded,\n snapshotPath: projectPaths.snapshotPath,\n errorsPath: projectPaths.errorsPath,\n }\n}\n\n// SDK-install apply over a discovered service list. Returns the same shape\n// the orchestrator's result.steps.apply uses so callers (orchestrator + sync)\n// share the rollup logic. v0.4.1 / refs #339 — `project` is threaded through\n// to the installer so the per-package `.env.neat` carries\n// `OTEL_SERVICE_NAME=<project>`, matching the daemon's routing key.\nexport async function applyInstallersOver(\n services: Awaited<ReturnType<typeof discoverServices>>,\n project: string,\n): Promise<{\n instrumented: number\n alreadyInstrumented: number\n libOnly: number\n browserBundle: number\n reactNative: number\n}> {\n let instrumented = 0\n let already = 0\n let libOnly = 0\n let browserBundle = 0\n let reactNative = 0\n for (const svc of services) {\n const installer = await pickInstaller(svc.dir)\n if (!installer) continue\n const plan: InstallPlan = await installer.plan(svc.dir, { project })\n if (isEmptyPlan(plan) && !plan.libOnly && plan.runtimeKind === undefined) {\n already++\n continue\n }\n const outcome = await installer.apply(plan)\n if (outcome.outcome === 'instrumented') instrumented++\n else if (outcome.outcome === 'already-instrumented') already++\n else if (outcome.outcome === 'lib-only') libOnly++\n else if (outcome.outcome === 'browser-bundle') {\n browserBundle++\n console.log(`skipping ${svc.dir}: browser bundle; browser-OTel support lands in a future release.`)\n } else if (outcome.outcome === 'react-native') {\n reactNative++\n console.log(`skipping ${svc.dir}: React Native target; browser-OTel support lands in a future release.`)\n }\n }\n return { instrumented, alreadyInstrumented: already, libOnly, browserBundle, reactNative }\n}\n\nasync function promptYesNo(question: string): Promise<boolean> {\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout })\n return new Promise((resolve) => {\n rl.question(`${question} [Y/n] `, (answer) => {\n rl.close()\n const trimmed = answer.trim().toLowerCase()\n resolve(trimmed === '' || trimmed === 'y' || trimmed === 'yes')\n })\n })\n}\n\n// 60s covers boot + per-project graph load across a registry with several\n// sibling projects. Issue #340 — `app.listen()` now returns the moment the\n// socket binds, so the steady-state happy path lands well inside the first\n// second; the longer ceiling is the cold-clone window where multi-project\n// bootstraps run in the background after listen.\nconst DEFAULT_DAEMON_READY_TIMEOUT_MS = 60_000\n\n// 500ms poll cadence — responsive enough that the operator sees a fresh\n// status line on every transition without spamming the daemon.\nconst PROBE_INTERVAL_MS = 500\n\ninterface DaemonHealthResponse {\n ok?: boolean\n uptimeMs?: number\n projects?: Array<{\n name: string\n status?: 'bootstrapping' | 'active' | 'broken'\n elapsedMs?: number\n }>\n}\n\nasync function fetchDaemonHealth(restPort: number): Promise<DaemonHealthResponse | null> {\n return new Promise((resolve) => {\n const req = http.get(`http://127.0.0.1:${restPort}/health`, (res) => {\n const ok = res.statusCode !== undefined && res.statusCode >= 200 && res.statusCode < 300\n if (!ok) {\n res.resume()\n resolve(null)\n return\n }\n let body = ''\n res.setEncoding('utf8')\n res.on('data', (chunk: string) => { body += chunk })\n res.on('end', () => {\n try {\n resolve(JSON.parse(body) as DaemonHealthResponse)\n } catch {\n resolve({ ok: true })\n }\n })\n })\n req.on('error', () => resolve(null))\n req.setTimeout(1000, () => {\n req.destroy()\n resolve(null)\n })\n })\n}\n\nasync function checkDaemonHealth(restPort: number): Promise<boolean> {\n const body = await fetchDaemonHealth(restPort)\n return body !== null\n}\n\nasync function probeProjectHealth(\n restPort: number,\n name: string,\n): Promise<'bootstrapping' | 'active' | 'broken'> {\n return new Promise((resolve) => {\n const req = http.get(\n `http://127.0.0.1:${restPort}/projects/${encodeURIComponent(name)}/health`,\n (res) => {\n const code = res.statusCode ?? 0\n res.resume()\n if (code >= 200 && code < 300) resolve('active')\n else resolve('bootstrapping')\n },\n )\n req.on('error', () => resolve('bootstrapping'))\n req.setTimeout(1000, () => {\n req.destroy()\n resolve('bootstrapping')\n })\n })\n}\n\n// Resolve the project-status set the wait loop branches on. Prefers the\n// daemon-wide /health response when it carries the list; otherwise reads\n// the registry directly and probes each project's per-project /health.\n// The fallback handles the case where the daemon-wide /health hasn't\n// landed in this branch's main yet.\nasync function snapshotProjectStatus(\n restPort: number,\n body: DaemonHealthResponse,\n): Promise<Array<{ name: string; status: 'bootstrapping' | 'active' | 'broken' }>> {\n if (body.projects && body.projects.length > 0) {\n return body.projects.map((p) => ({\n name: p.name,\n status: p.status ?? 'active',\n }))\n }\n const entries = await listProjects().catch(() => [])\n if (entries.length === 0) return []\n return Promise.all(\n entries.map(async (entry) => ({\n name: entry.name,\n status: await probeProjectHealth(restPort, entry.name),\n })),\n )\n}\n\ninterface DaemonReadyResult {\n ready: boolean\n brokenProjects: string[]\n stillBootstrapping: string[]\n}\n\nasync function waitForDaemonReady(restPort: number, timeoutMs: number): Promise<DaemonReadyResult> {\n const deadline = Date.now() + timeoutMs\n let lastBootstrapping: string[] = []\n while (Date.now() < deadline) {\n const body = await fetchDaemonHealth(restPort)\n if (body !== null) {\n const projects = await snapshotProjectStatus(restPort, body)\n const bootstrapping = projects\n .filter((p) => p.status === 'bootstrapping')\n .map((p) => p.name)\n const broken = projects.filter((p) => p.status === 'broken').map((p) => p.name)\n if (bootstrapping.length === 0) {\n return { ready: true, brokenProjects: broken, stillBootstrapping: [] }\n }\n const key = bootstrapping.slice().sort().join(',')\n const prevKey = lastBootstrapping.slice().sort().join(',')\n if (key !== prevKey) {\n const plural = bootstrapping.length === 1 ? '' : 's'\n console.log(\n `neat: waiting on ${bootstrapping.length} project${plural}: ${bootstrapping.join(', ')}`,\n )\n lastBootstrapping = bootstrapping\n }\n }\n await new Promise((r) => setTimeout(r, PROBE_INTERVAL_MS))\n }\n const final = await fetchDaemonHealth(restPort)\n const projects = final ? await snapshotProjectStatus(restPort, final) : []\n return {\n ready: false,\n brokenProjects: projects.filter((p) => p.status === 'broken').map((p) => p.name),\n stillBootstrapping: projects\n .filter((p) => p.status === 'bootstrapping')\n .map((p) => p.name),\n }\n}\n\n// Port-availability probe (#377 / ADR-079 §2).\n//\n// The orchestrator's daemon-spawn step assumes `:8080` (REST), `:4318` (OTLP\n// HTTP), and `:6328` (web UI) are free. When a sibling daemon from another\n// terminal session — or any unrelated listener — is holding one of them, the\n// spawn exits 1 with no actionable message. The probe runs before\n// `spawnDaemonDetached()` and surfaces the named port plus recovery commands\n// on collision, exiting with code 3 (environmental) per the CLI exit-code\n// surface.\nexport const NEAT_PORTS = [8080, 4318, 6328] as const\n\nexport async function isPortFree(port: number): Promise<boolean> {\n return new Promise((resolve) => {\n const server = net.createServer()\n server.once('error', () => resolve(false))\n server.once('listening', () => server.close(() => resolve(true)))\n server.listen(port, '127.0.0.1')\n })\n}\n\nexport async function probePortsFree(): Promise<\n { free: true } | { free: false; held: number }\n> {\n for (const port of NEAT_PORTS) {\n if (!(await isPortFree(port))) return { free: false, held: port }\n }\n return { free: true }\n}\n\nexport function formatPortCollisionMessage(port: number): string[] {\n return [\n `neat: port ${port} is in use; the NEAT daemon needs it.`,\n ` run \\`neatd stop\\` to release the previous daemon, or`,\n ` \\`lsof -i :${port}\\` to find the holding process.`,\n ]\n}\n\n// Spawn the daemon as a child process the orchestrator drives. Returns the\n// child handle so the caller can read its stderr verbatim when the bind\n// gate (or any other startup failure) reports back through that pipe\n// (issue #341). The `detached: true` + `unref()` pair survives the\n// orchestrator exiting cleanly; the inherited stderr keeps the operator\n// informed when something does fail.\nfunction spawnDaemonDetached(): import('node:child_process').ChildProcess {\n // Resolve the neatd entry inside the @neat.is/core dist next to this\n // file. `import.meta.url` is post-bundling — at runtime, this resolves\n // to `<core>/dist/neatd.{js,cjs}`. We pick the .cjs because tsup ships\n // it in both forms and node tolerates either.\n const here = path.dirname(new URL(import.meta.url).pathname)\n const candidates = [\n path.join(here, 'neatd.cjs'),\n path.join(here, 'neatd.js'),\n ]\n let entry: string | null = null\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const fsSync = require('node:fs') as typeof import('node:fs')\n for (const c of candidates) {\n try {\n fsSync.accessSync(c)\n entry = c\n break\n } catch {\n // try next\n }\n }\n if (!entry) {\n throw new Error(`orchestrator: cannot locate neatd entry in ${here}`)\n }\n\n // ADR-073 §3 + issue #341 — first-touch path is loopback-only. When the\n // operator hasn't set `NEAT_AUTH_TOKEN` the orchestrator hard-pins\n // HOST=127.0.0.1 in the child env so `assertBindAuthority` lets the bind\n // through. Public-bind is opt-in via the token (and an explicit\n // `HOST=0.0.0.0` if the operator wants the literal). The parent's HOST is\n // preserved untouched when the token is set — that's the deploy path,\n // where the platform owns the bind decision.\n const env = { ...process.env }\n const hasToken = typeof env.NEAT_AUTH_TOKEN === 'string' && env.NEAT_AUTH_TOKEN.length > 0\n if (!hasToken && (!env.HOST || env.HOST.length === 0)) {\n env.HOST = '127.0.0.1'\n }\n\n const child = spawn(process.execPath, [entry, 'start'], {\n detached: true,\n // stderr inherits the orchestrator's fd so the daemon's\n // `BindAuthorityError` message lands in front of the operator instead\n // of being swallowed (issue #341).\n stdio: ['ignore', 'ignore', 'inherit'],\n env,\n })\n child.unref()\n return child\n}\n\nfunction openBrowser(url: string): 'opened' | 'failed' {\n // Skip when running headlessly; we don't want CI invocations to fail\n // because xdg-open isn't installed.\n if (!process.stdout.isTTY) return 'failed'\n const platform = process.platform\n const cmd =\n platform === 'darwin' ? 'open' :\n platform === 'win32' ? 'cmd' :\n 'xdg-open'\n const args = platform === 'win32' ? ['/c', 'start', '', url] : [url]\n try {\n const child = spawn(cmd, args, { detached: true, stdio: 'ignore' })\n child.on('error', () => {})\n child.unref()\n return 'opened'\n } catch {\n return 'failed'\n }\n}\n\nexport async function runOrchestrator(opts: OrchestratorOptions): Promise<OrchestratorResult> {\n const result: OrchestratorResult = {\n exitCode: 0,\n steps: {\n discovery: { services: 0, languages: [] },\n extraction: { nodesAdded: 0, edgesAdded: 0 },\n gitignore: 'unchanged',\n apply: { instrumented: 0, alreadyInstrumented: 0, libOnly: 0, skipped: false },\n daemon: 'skipped',\n browser: 'skipped',\n },\n }\n\n // ── Path validation ───────────────────────────────────────────────────\n const stat = await fs.stat(opts.scanPath).catch(() => null)\n if (!stat || !stat.isDirectory()) {\n console.error(`neat: ${opts.scanPath} is not a directory`)\n result.exitCode = 2\n return result\n }\n\n console.log(`neat: ${opts.scanPath}`)\n console.log('')\n\n // ── Step 1: discovery, Step 2: extraction + snapshot ─────────────────\n // Shared with `neat sync` (ADR-074 §1) via extractAndPersist.\n const persisted = await extractAndPersist({\n scanPath: opts.scanPath,\n project: opts.project,\n projectExplicit: opts.projectExplicit,\n })\n const { graph, services, languages } = persisted\n result.steps.discovery = { services: services.length, languages }\n console.log(`discovered ${services.length} service(s) across ${languages.length} language(s)`)\n\n // ── Confirmation prompt (default yes; --no-instrument or no-TTY skip)\n let runApply = !opts.noInstrument\n if (runApply && !opts.yes && process.stdout.isTTY && process.stdin.isTTY) {\n runApply = await promptYesNo('instrument your services and open the dashboard?')\n }\n\n result.steps.extraction = {\n nodesAdded: persisted.nodesAdded,\n edgesAdded: persisted.edgesAdded,\n }\n\n const gi = await ensureNeatOutIgnored(opts.scanPath)\n result.steps.gitignore = gi.action\n if (gi.action !== 'unchanged') {\n console.log(`${gi.action} .gitignore (neat-out/)`)\n }\n\n let currentProjectName = opts.project\n try {\n const entry = await addProject({\n name: opts.project,\n path: opts.scanPath,\n languages,\n status: 'active',\n })\n currentProjectName = entry.name\n } catch (err) {\n if (!(err instanceof ProjectNameCollisionError)) throw err\n // Same path, same name → re-init. Different path → bail with a clear\n // message so the operator can pass --project <other-name>.\n console.error(`neat: ${err.message}`)\n console.error('pass --project <other-name> to register under a different name.')\n result.exitCode = 1\n return result\n }\n\n // Narrow the active-project surface to what the operator is currently in.\n // Every other `active` entry transitions to `paused`; `broken` is left alone\n // so the daemon's broken-path handling still surfaces. `neat resume <name>`\n // brings any of them back when cross-project work is the explicit intent.\n const siblings = await listProjects()\n const paused: string[] = []\n for (const p of siblings) {\n if (p.name !== currentProjectName && p.status === 'active') {\n await setStatus(p.name, 'paused')\n paused.push(p.name)\n }\n }\n if (paused.length > 0) {\n const plural = paused.length === 1 ? '' : 's'\n console.log(\n `neat: paused ${paused.length} sibling project${plural}; run \\`neat resume <name>\\` to bring one back active.`,\n )\n }\n\n // ── Step 3: SDK install apply (default yes; --no-instrument skips) ───\n if (!runApply) {\n result.steps.apply.skipped = true\n console.log('skipped instrumentation (--no-instrument)')\n } else {\n const tally = await applyInstallersOver(services, opts.project)\n result.steps.apply = { ...tally, skipped: false }\n console.log(\n `instrumented ${tally.instrumented}, already ${tally.alreadyInstrumented}, lib-only ${tally.libOnly}`,\n )\n }\n\n // ── Step 4: daemon spawn + health poll ───────────────────────────────\n const restPort = Number(process.env.PORT ?? 8080)\n const timeoutMs = opts.daemonReadyTimeoutMs ?? DEFAULT_DAEMON_READY_TIMEOUT_MS\n if (await checkDaemonHealth(restPort)) {\n result.steps.daemon = 'already-running'\n } else {\n const probe = await probePortsFree()\n if (!probe.free) {\n for (const line of formatPortCollisionMessage(probe.held)) {\n console.error(line)\n }\n result.exitCode = 3\n return result\n }\n try {\n spawnDaemonDetached()\n } catch (err) {\n console.error(`neat: daemon spawn failed — ${(err as Error).message}`)\n result.exitCode = 1\n return result\n }\n const ready = await waitForDaemonReady(restPort, timeoutMs)\n result.steps.daemon = ready.ready ? 'spawned' : 'timed-out'\n if (!ready.ready) {\n console.error(`neat: daemon did not become ready within ${timeoutMs}ms`)\n if (ready.stillBootstrapping.length > 0) {\n console.error(\n `neat: still bootstrapping: ${ready.stillBootstrapping.join(', ')}`,\n )\n }\n if (ready.brokenProjects.length > 0) {\n console.error(`neat: broken projects: ${ready.brokenProjects.join(', ')}`)\n }\n result.exitCode = 1\n return result\n }\n if (ready.brokenProjects.length > 0) {\n console.warn(\n `neat: ${ready.brokenProjects.length} project(s) reported broken: ${ready.brokenProjects.join(', ')}`,\n )\n }\n }\n\n // ── Step 5: browser open ─────────────────────────────────────────────\n const dashboardUrl = opts.dashboardUrl ?? 'http://localhost:6328'\n if (opts.noOpen || !process.stdout.isTTY) {\n result.steps.browser = 'skipped'\n } else {\n result.steps.browser = openBrowser(dashboardUrl)\n }\n\n // ── Step 6: summary (stub — PR 4 replaces with the value-forward shape)\n printSummary(result, graph, dashboardUrl)\n\n return result\n}\n\nfunction printSummary(\n result: OrchestratorResult,\n graph: ReturnType<typeof getGraph>,\n dashboardUrl: string,\n): void {\n const nodes: GraphNode[] = []\n graph.forEachNode((_id, attrs) => nodes.push(attrs))\n const edges: GraphEdge[] = []\n graph.forEachEdge((_id, attrs) => edges.push(attrs))\n\n const byNode = new Map<string, number>()\n for (const n of nodes) byNode.set(n.type, (byNode.get(n.type) ?? 0) + 1)\n const byEdge = new Map<string, number>()\n for (const e of edges) byEdge.set(e.type, (byEdge.get(e.type) ?? 0) + 1)\n\n console.log('')\n console.log('=== summary ===')\n console.log(`graph: ${graph.order} nodes, ${graph.size} edges`)\n for (const [t, c] of [...byNode.entries()].sort()) console.log(` ${t}: ${c}`)\n for (const [t, c] of [...byEdge.entries()].sort()) console.log(` ${t}: ${c}`)\n console.log('')\n console.log(`dashboard: ${dashboardUrl}`)\n}\n","/**\n * Lifecycle-verb implementations for the CLI. Query verbs live in\n * `cli-client.ts` next to the REST client; lifecycle verbs (currently\n * `neat sync`) live here because they orchestrate filesystem work and\n * daemon-state probes rather than wrapping a single REST endpoint.\n */\n\nimport path from 'node:path'\nimport type { RegistryEntry } from '@neat.is/types'\nimport {\n applyInstallersOver,\n extractAndPersist,\n type ExtractAndPersistResult,\n} from './orchestrator.js'\nimport { listProjects, normalizeProjectPath } from './registry.js'\nimport { saveGraphToDisk, type PersistedGraph } from './persist.js'\nimport {\n HttpError,\n pushSnapshotToRemote,\n TransportError,\n} from './cli-client.js'\n\nexport interface SyncOptions {\n // Project name from `--project <name>`. When absent, sync resolves the\n // project by matching the cwd against the registered project paths.\n project?: string\n // Push the snapshot to a remote daemon URL. When absent, sync runs against\n // the local daemon on http://localhost:8080.\n to?: string\n // Bearer token for the remote daemon. Falls back to NEAT_REMOTE_TOKEN env.\n token?: string\n // Skip writing the snapshot or notifying the daemon. Mirrors `neat <path>\n // --dry-run`.\n dryRun: boolean\n // Skip the SDK install apply step.\n noInstrument: boolean\n // Emit a structured JSON payload on stdout instead of human text.\n json: boolean\n // Override the local daemon URL. Defaults to NEAT_API_URL or\n // http://localhost:8080. Useful for tests.\n daemonUrl?: string\n // Working directory the verb resolves against when `--project` isn't\n // passed. Defaults to process.cwd(); tests override.\n cwd?: string\n}\n\nexport interface SyncResult {\n exitCode: number\n // Stable shape across human / json output paths. cli.ts decides which\n // formatter to invoke based on `--json`.\n project: string\n scanPath: string\n nodesAdded: number\n edgesAdded: number\n snapshotPath: string | null\n // Tracks which branch the run took for `--json` consumers.\n mode: 'dry-run' | 'local' | 'remote'\n daemon: 'reloaded' | 'down' | 'remote-ok' | 'skipped'\n apply: {\n instrumented: number\n alreadyInstrumented: number\n libOnly: number\n skipped: boolean\n }\n // Soft warning lines surfaced to stderr in the human path. Empty when the\n // run was fully clean.\n warnings: string[]\n}\n\nasync function resolveProjectEntry(opts: SyncOptions): Promise<RegistryEntry | null> {\n const entries = await listProjects()\n if (opts.project) {\n const match = entries.find((e) => e.name === opts.project)\n return match ?? null\n }\n const cwd = opts.cwd ?? process.cwd()\n const resolvedCwd = await normalizeProjectPath(cwd)\n // Match by path: the cwd must be inside (or equal to) the registered path.\n for (const entry of entries) {\n if (\n resolvedCwd === entry.path ||\n resolvedCwd.startsWith(`${entry.path}${path.sep}`)\n ) {\n return entry\n }\n }\n return null\n}\n\nasync function checkDaemonHealth(baseUrl: string): Promise<boolean> {\n try {\n const res = await fetch(`${baseUrl.replace(/\\/$/, '')}/health`, {\n signal: AbortSignal.timeout(1500),\n })\n return res.ok\n } catch {\n return false\n }\n}\n\nfunction snapshotForGraph(persisted: ExtractAndPersistResult): PersistedGraph {\n return {\n schemaVersion: 3,\n exportedAt: new Date().toISOString(),\n graph: persisted.graph.export(),\n }\n}\n\nfunction emitResult(result: SyncResult, json: boolean): void {\n if (json) {\n process.stdout.write(JSON.stringify(result, null, 2) + '\\n')\n return\n }\n const verb =\n result.mode === 'dry-run'\n ? 'dry-run'\n : result.mode === 'remote'\n ? 'pushed'\n : 'synced'\n console.log(\n `${verb}: ${result.project} — ${result.nodesAdded} node(s) and ${result.edgesAdded} edge(s) added` +\n (result.snapshotPath ? `; snapshot at ${result.snapshotPath}` : ''),\n )\n if (!result.apply.skipped) {\n const { instrumented, alreadyInstrumented, libOnly } = result.apply\n console.log(\n `instrumented ${instrumented}, already ${alreadyInstrumented}, lib-only ${libOnly}`,\n )\n } else {\n console.log('skipped instrumentation (--no-instrument)')\n }\n for (const warn of result.warnings) console.error(warn)\n}\n\nexport async function runSync(opts: SyncOptions): Promise<SyncResult> {\n const entry = await resolveProjectEntry(opts)\n if (!entry) {\n const target = opts.project ?? opts.cwd ?? process.cwd()\n console.error(\n `neat sync: no registered project ${\n opts.project ? `named \"${opts.project}\"` : `covers ${target}`\n }. Run \\`neat <path>\\` or \\`neat init <path>\\` first.`,\n )\n return {\n exitCode: 1,\n project: opts.project ?? '',\n scanPath: target,\n nodesAdded: 0,\n edgesAdded: 0,\n snapshotPath: null,\n mode: opts.to ? 'remote' : 'local',\n daemon: 'skipped',\n apply: { instrumented: 0, alreadyInstrumented: 0, libOnly: 0, skipped: true },\n warnings: [],\n }\n }\n\n // ── Step 1 + 2: discovery + extraction (no snapshot in dry-run) ─────\n const persisted = await extractAndPersist({\n scanPath: entry.path,\n project: entry.name,\n projectExplicit: true,\n dryRun: true,\n })\n\n let snapshotPath: string | null = null\n if (!opts.dryRun) {\n const target = persisted.snapshotPath\n await saveGraphToDisk(persisted.graph, target)\n snapshotPath = target\n }\n\n // ── Step 3: SDK install apply (default yes; --dry-run + --no-instrument skip)\n const skipApply = opts.dryRun || opts.noInstrument\n const applyTally = skipApply\n ? { instrumented: 0, alreadyInstrumented: 0, libOnly: 0, browserBundle: 0, reactNative: 0 }\n : await applyInstallersOver(persisted.services, entry.name)\n\n // ── Step 4: daemon notify ────────────────────────────────────────────\n const warnings: string[] = []\n let daemonState: SyncResult['daemon'] = 'skipped'\n let exitCode = 0\n const mode: SyncResult['mode'] = opts.dryRun ? 'dry-run' : opts.to ? 'remote' : 'local'\n\n if (!opts.dryRun) {\n const snapshot = snapshotForGraph(persisted)\n if (opts.to) {\n const token = opts.token ?? process.env.NEAT_REMOTE_TOKEN\n try {\n await pushSnapshotToRemote({\n baseUrl: opts.to,\n token,\n project: entry.name,\n snapshot,\n })\n daemonState = 'remote-ok'\n } catch (err) {\n if (err instanceof HttpError) {\n console.error(`neat sync: ${err.message}`)\n exitCode = 1\n } else if (err instanceof TransportError) {\n console.error(`neat sync: ${err.message}`)\n exitCode = 3\n } else {\n console.error(`neat sync: ${(err as Error).message}`)\n exitCode = 1\n }\n daemonState = 'skipped'\n }\n } else {\n const daemonUrl =\n opts.daemonUrl ?? process.env.NEAT_API_URL ?? 'http://localhost:8080'\n const healthy = await checkDaemonHealth(daemonUrl)\n if (healthy) {\n try {\n await pushSnapshotToRemote({\n baseUrl: daemonUrl,\n token: process.env.NEAT_AUTH_TOKEN,\n project: entry.name,\n snapshot,\n })\n daemonState = 'reloaded'\n } catch (err) {\n warnings.push(\n `neat sync: daemon merge failed — ${(err as Error).message}. Snapshot is on disk at ${snapshotPath}.`,\n )\n daemonState = 'down'\n exitCode = 2\n }\n } else {\n warnings.push(\n 'neat sync: daemon not running; snapshot updated, run `neatd start` to serve it',\n )\n daemonState = 'down'\n exitCode = 2\n }\n }\n }\n\n const result: SyncResult = {\n exitCode,\n project: entry.name,\n scanPath: entry.path,\n nodesAdded: persisted.nodesAdded,\n edgesAdded: persisted.edgesAdded,\n snapshotPath,\n mode,\n daemon: daemonState,\n apply: { ...applyTally, skipped: skipApply },\n warnings,\n }\n\n emitResult(result, opts.json)\n return result\n}\n","// REST helper + CLI verb implementations for `neat <verb>` (ADR-050).\n//\n// The HttpClient and its createHttpClient factory are the \"shared REST helper\n// module\" the contract calls for — one endpoint surface, two consumers\n// (`packages/mcp/src/client.ts` re-exports from here, the CLI dispatcher\n// imports it directly).\n//\n// Verb handlers live alongside the client because they're tightly coupled:\n// each verb maps 1:1 to an MCP tool from ADR-039, but produces the structured\n// `{ summary, block, confidence, provenance }` shape (ADR-050 #3) in pure\n// data form. cli.ts formats that shape into either human-readable text or\n// `--json` output.\n\nimport type {\n BlastRadiusAffectedNode,\n BlastRadiusResult,\n Divergence,\n DivergenceResult,\n DivergenceType,\n ErrorEvent,\n GraphEdge,\n GraphNode,\n HypotheticalAction,\n PolicyViolation,\n RootCauseResult,\n TransitiveDependenciesResult,\n} from '@neat.is/types'\nimport { Provenance } from '@neat.is/types'\n\n// ──────────────────────────────────────────────────────────────────────────\n// REST client\n// ──────────────────────────────────────────────────────────────────────────\n\nexport interface HttpClient {\n get<T>(path: string): Promise<T>\n post?<T>(path: string, body: unknown): Promise<T>\n}\n\nexport class HttpError extends Error {\n constructor(\n public readonly status: number,\n message: string,\n public readonly responseBody: string = '',\n ) {\n super(message)\n this.name = 'HttpError'\n }\n}\n\n// Network-level failures (ECONNREFUSED, ETIMEDOUT, DNS) — distinct from\n// HttpError so the CLI can map them to exit code 3 (daemon-down) without\n// parsing error strings.\nexport class TransportError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'TransportError'\n }\n}\n\nexport function createHttpClient(baseUrl: string, bearerToken?: string): HttpClient {\n const root = baseUrl.replace(/\\/$/, '')\n const authHeader = bearerToken && bearerToken.length > 0\n ? { authorization: `Bearer ${bearerToken}` }\n : {}\n return {\n async get<T>(path: string): Promise<T> {\n let res: Response\n try {\n res = await fetch(`${root}${path}`, {\n headers: { ...authHeader },\n })\n } catch (err) {\n throw new TransportError(\n `cannot reach neat-core at ${root}: ${(err as Error).message}`,\n )\n }\n if (!res.ok) {\n const body = await res.text().catch(() => '')\n throw new HttpError(\n res.status,\n `${res.status} ${res.statusText} on GET ${path}: ${body}`,\n body,\n )\n }\n return (await res.json()) as T\n },\n async post<T>(path: string, body: unknown): Promise<T> {\n let res: Response\n try {\n res = await fetch(`${root}${path}`, {\n method: 'POST',\n headers: { 'content-type': 'application/json', ...authHeader },\n body: JSON.stringify(body),\n })\n } catch (err) {\n throw new TransportError(\n `cannot reach neat-core at ${root}: ${(err as Error).message}`,\n )\n }\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new HttpError(\n res.status,\n `${res.status} ${res.statusText} on POST ${path}: ${text}`,\n text,\n )\n }\n return (await res.json()) as T\n },\n }\n}\n\n// Project routing per ADR-050 #2: `--project <name>` (handled in cli.ts) →\n// `NEAT_PROJECT` env → `default`. The default routes hit the legacy\n// unprefixed URLs which the core resolves to project=`default`.\nfunction projectPath(project: string | undefined, suffix: string): string {\n if (!project) return suffix\n return `/projects/${encodeURIComponent(project)}${suffix}`\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Verb result shape (ADR-050 #3)\n// ──────────────────────────────────────────────────────────────────────────\n\nexport interface VerbResult {\n // NL paragraph. What was found and why it matters.\n summary: string\n // Structured payload — usually a bulleted list. Empty when the summary\n // already conveys everything.\n block?: string\n // Per-result confidence in [0, 1]. Undefined → footer reads \"n/a\".\n confidence?: number\n // Per-result provenance. String, array (mixed paths), or undefined.\n provenance?: string | string[]\n}\n\n// Common shape the nine verbs produce. cli.ts renders this to text or JSON.\n\n// ──────────────────────────────────────────────────────────────────────────\n// Verbs\n// ──────────────────────────────────────────────────────────────────────────\n\nexport interface RootCauseInput {\n errorNode: string\n errorId?: string\n project?: string\n}\n\nexport async function runRootCause(\n client: HttpClient,\n input: RootCauseInput,\n): Promise<VerbResult> {\n const qs = input.errorId ? `?errorId=${encodeURIComponent(input.errorId)}` : ''\n const path = projectPath(\n input.project,\n `/graph/root-cause/${encodeURIComponent(input.errorNode)}${qs}`,\n )\n try {\n const result = await client.get<RootCauseResult>(path)\n const arrowPath = result.traversalPath.join(' ← ')\n const provenances = result.edgeProvenances.length\n ? result.edgeProvenances.join(', ')\n : '(direct, no edges traversed)'\n const summary =\n `Root cause for ${input.errorNode} is ${result.rootCauseNode}. ` +\n result.rootCauseReason +\n (result.fixRecommendation ? ` Recommended fix: ${result.fixRecommendation}.` : '')\n const blockLines = [\n `Traversal path: ${arrowPath}`,\n `Edge provenances: ${provenances}`,\n ]\n if (result.fixRecommendation) blockLines.push(`Recommended fix: ${result.fixRecommendation}`)\n return {\n summary,\n block: blockLines.join('\\n'),\n confidence: result.confidence,\n provenance: result.edgeProvenances.length ? result.edgeProvenances : undefined,\n }\n } catch (err) {\n if (err instanceof HttpError && err.status === 404) {\n return {\n summary: `No root cause found for ${input.errorNode}. The node may be healthy, or it may not exist in the graph.`,\n }\n }\n throw err\n }\n}\n\nexport interface BlastRadiusInput {\n nodeId: string\n depth?: number\n project?: string\n}\n\nexport async function runBlastRadius(\n client: HttpClient,\n input: BlastRadiusInput,\n): Promise<VerbResult> {\n const qs = input.depth !== undefined ? `?depth=${input.depth}` : ''\n const path = projectPath(\n input.project,\n `/graph/blast-radius/${encodeURIComponent(input.nodeId)}${qs}`,\n )\n try {\n const result = await client.get<BlastRadiusResult>(path)\n if (result.totalAffected === 0) {\n return {\n summary: `${result.origin} has no downstream dependencies. Nothing else would break if it failed.`,\n }\n }\n const sorted = [...result.affectedNodes].sort(\n (a, b) => a.distance - b.distance || a.nodeId.localeCompare(b.nodeId),\n )\n const blockLines = sorted.map(formatBlastEntry)\n const minConfidence = sorted.reduce(\n (m, n) => Math.min(m, n.confidence),\n Number.POSITIVE_INFINITY,\n )\n const provenances = [...new Set(sorted.map((n) => n.edgeProvenance))]\n return {\n summary: `Blast radius for ${result.origin}: ${result.totalAffected} affected node${result.totalAffected === 1 ? '' : 's'} reachable downstream.`,\n block: blockLines.join('\\n'),\n confidence: Number.isFinite(minConfidence) ? minConfidence : undefined,\n provenance: provenances.length ? provenances : undefined,\n }\n } catch (err) {\n if (err instanceof HttpError && err.status === 404) {\n return { summary: `Node ${input.nodeId} not found in the graph.` }\n }\n throw err\n }\n}\n\nfunction formatBlastEntry(n: BlastRadiusAffectedNode): string {\n const tag = n.edgeProvenance === Provenance.STALE ? ' [STALE — last seen too long ago]' : ''\n return ` • ${n.nodeId} (distance ${n.distance}, ${n.edgeProvenance})${tag}`\n}\n\nexport interface DependenciesInput {\n nodeId: string\n depth?: number\n project?: string\n}\n\nexport async function runDependencies(\n client: HttpClient,\n input: DependenciesInput,\n): Promise<VerbResult> {\n const depth = input.depth ?? 3\n const path = projectPath(\n input.project,\n `/graph/dependencies/${encodeURIComponent(input.nodeId)}?depth=${depth}`,\n )\n try {\n const result = await client.get<TransitiveDependenciesResult>(path)\n if (result.total === 0) {\n return {\n summary:\n depth === 1\n ? `${input.nodeId} has no direct dependencies in the graph.`\n : `${input.nodeId} has no dependencies (BFS to depth ${depth}).`,\n }\n }\n const byDistance = new Map<number, typeof result.dependencies>()\n for (const dep of result.dependencies) {\n const ring = byDistance.get(dep.distance) ?? []\n ring.push(dep)\n byDistance.set(dep.distance, ring)\n }\n const blockLines: string[] = []\n for (const distance of [...byDistance.keys()].sort((a, b) => a - b)) {\n const label = distance === 1 ? 'Direct (distance 1)' : `Distance ${distance}`\n blockLines.push(`${label}:`)\n for (const dep of byDistance.get(distance)!) {\n blockLines.push(` • ${dep.nodeId} — ${dep.edgeType} (${dep.provenance})`)\n }\n }\n const provenances = [...new Set(result.dependencies.map((d) => d.provenance))]\n const directCount = byDistance.get(1)?.length ?? 0\n const summary =\n depth === 1\n ? `${input.nodeId} has ${directCount} direct dependenc${directCount === 1 ? 'y' : 'ies'}.`\n : `${input.nodeId} has ${result.total} dependenc${result.total === 1 ? 'y' : 'ies'} reachable to depth ${depth} (${directCount} direct).`\n return { summary, block: blockLines.join('\\n'), provenance: provenances }\n } catch (err) {\n if (err instanceof HttpError && err.status === 404) {\n return { summary: `Node ${input.nodeId} not found in the graph.` }\n }\n throw err\n }\n}\n\ninterface EdgesResponse {\n inbound: GraphEdge[]\n outbound: GraphEdge[]\n}\n\nexport async function runObservedDependencies(\n client: HttpClient,\n input: DependenciesInput,\n): Promise<VerbResult> {\n try {\n const edges = await client.get<EdgesResponse>(\n projectPath(input.project, `/graph/edges/${encodeURIComponent(input.nodeId)}`),\n )\n const observed = edges.outbound.filter((e) => e.provenance === Provenance.OBSERVED)\n if (observed.length === 0) {\n const hasExtracted = edges.outbound.some((e) => e.provenance === Provenance.EXTRACTED)\n const note = hasExtracted\n ? ' Static (EXTRACTED) dependencies exist but no runtime traffic has been seen — is OTel running?'\n : ''\n return { summary: `No OBSERVED dependencies for ${input.nodeId}.${note}` }\n }\n const blockLines = observed.map((e) => ` • ${e.target} — ${e.type}${edgeMeta(e)}`)\n return {\n summary: `${input.nodeId} has ${observed.length} runtime dependenc${observed.length === 1 ? 'y' : 'ies'} confirmed by OTel.`,\n block: blockLines.join('\\n'),\n provenance: Provenance.OBSERVED,\n }\n } catch (err) {\n if (err instanceof HttpError && err.status === 404) {\n return { summary: `Node ${input.nodeId} not found in the graph.` }\n }\n throw err\n }\n}\n\nfunction edgeMeta(e: GraphEdge): string {\n const bits: string[] = []\n if (e.signal) {\n bits.push(`spans=${e.signal.spanCount}`)\n if (e.signal.errorCount > 0) bits.push(`errors=${e.signal.errorCount}`)\n if (e.signal.lastObservedAgeMs !== undefined) {\n bits.push(`age=${formatDuration(e.signal.lastObservedAgeMs)}`)\n }\n } else if (e.callCount !== undefined) {\n bits.push(`callCount=${e.callCount}`)\n }\n if (e.lastObserved) bits.push(`lastObserved=${e.lastObserved}`)\n if (e.confidence !== undefined) bits.push(`confidence=${e.confidence}`)\n return bits.length ? ` [${bits.join(', ')}]` : ''\n}\n\nfunction formatDuration(ms: number): string {\n if (ms < 1000) return `${Math.round(ms)}ms`\n const s = Math.round(ms / 1000)\n if (s < 60) return `${s}s`\n const m = Math.round(s / 60)\n if (m < 60) return `${m}m`\n const h = Math.round(m / 60)\n if (h < 48) return `${h}h`\n return `${Math.round(h / 24)}d`\n}\n\nexport interface IncidentsInput {\n nodeId?: string\n limit?: number\n project?: string\n}\n\n// `neat incidents` shape: with a node id, returns that node's incidents.\n// Without one, returns the global recent log.\nexport async function runIncidents(\n client: HttpClient,\n input: IncidentsInput,\n): Promise<VerbResult> {\n const path = input.nodeId\n ? projectPath(input.project, `/incidents/${encodeURIComponent(input.nodeId)}`)\n : projectPath(input.project, '/incidents')\n try {\n const body = await client.get<{ count: number; total: number; events: ErrorEvent[] }>(path)\n const events = body.events\n if (events.length === 0) {\n return {\n summary: input.nodeId\n ? `No incidents recorded against ${input.nodeId}.`\n : 'No incidents recorded.',\n }\n }\n const ordered = [...events].reverse().slice(0, input.limit ?? 20)\n const blockLines: string[] = []\n for (const ev of ordered) {\n blockLines.push(` ${ev.timestamp} — ${ev.service}: ${ev.errorMessage}`)\n blockLines.push(` trace=${ev.traceId} span=${ev.spanId}`)\n }\n const target = input.nodeId ?? 'the project'\n return {\n summary: `${target} has ${body.total} recorded incident${body.total === 1 ? '' : 's'}; showing the ${ordered.length} most recent.`,\n block: blockLines.join('\\n'),\n provenance: Provenance.OBSERVED,\n }\n } catch (err) {\n if (err instanceof HttpError && err.status === 404) {\n return { summary: `Node ${input.nodeId ?? ''} not found in the graph.` }\n }\n throw err\n }\n}\n\nexport interface SearchInput {\n query: string\n project?: string\n}\n\ninterface SearchResponse {\n query: string\n provider?: 'ollama' | 'transformers' | 'substring'\n matches: (GraphNode & { score?: number })[]\n}\n\nexport async function runSearch(\n client: HttpClient,\n input: SearchInput,\n): Promise<VerbResult> {\n const result = await client.get<SearchResponse>(\n projectPath(input.project, `/search?q=${encodeURIComponent(input.query)}`),\n )\n if (result.matches.length === 0) {\n return { summary: `No matches for \"${input.query}\".` }\n }\n const provider = result.provider ?? 'substring'\n const blockLines: string[] = []\n let topScore: number | undefined\n for (const n of result.matches) {\n const score = provider !== 'substring' && typeof n.score === 'number' ? n.score : undefined\n const scoreBit = score !== undefined ? ` [score=${score.toFixed(2)}]` : ''\n if (score !== undefined && (topScore === undefined || score > topScore)) topScore = score\n blockLines.push(\n ` • ${n.id} (${n.type}) — ${(n as { name?: string }).name ?? n.id}${scoreBit}`,\n )\n }\n return {\n summary: `Found ${result.matches.length} match${result.matches.length === 1 ? '' : 'es'} for \"${input.query}\" via ${provider} provider.`,\n block: blockLines.join('\\n'),\n confidence: topScore,\n }\n}\n\nexport interface DiffInput {\n againstSnapshot: string\n project?: string\n}\n\ninterface GraphDiffResponse {\n base: { exportedAt?: string }\n current: { exportedAt: string }\n added: { nodes: GraphNode[]; edges: GraphEdge[] }\n removed: { nodes: GraphNode[]; edges: GraphEdge[] }\n changed: {\n nodes: { id: string; before: GraphNode; after: GraphNode }[]\n edges: { id: string; before: GraphEdge; after: GraphEdge }[]\n }\n}\n\nexport async function runDiff(client: HttpClient, input: DiffInput): Promise<VerbResult> {\n const result = await client.get<GraphDiffResponse>(\n projectPath(\n input.project,\n `/graph/diff?against=${encodeURIComponent(input.againstSnapshot)}`,\n ),\n )\n const total =\n result.added.nodes.length +\n result.added.edges.length +\n result.removed.nodes.length +\n result.removed.edges.length +\n result.changed.nodes.length +\n result.changed.edges.length\n const baseLabel = result.base.exportedAt ?? 'unknown'\n if (total === 0) {\n return {\n summary: `No differences between the current graph and ${input.againstSnapshot} (base exportedAt=${baseLabel}).`,\n }\n }\n const blockLines: string[] = [\n ` base exportedAt: ${baseLabel}`,\n ` current exportedAt: ${result.current.exportedAt}`,\n '',\n ]\n if (result.added.nodes.length || result.added.edges.length) {\n blockLines.push('Added:')\n for (const n of result.added.nodes) blockLines.push(` + node ${n.id} (${n.type})`)\n for (const e of result.added.edges)\n blockLines.push(` + edge ${e.id} — ${e.source} -> ${e.target} (${e.type}, ${e.provenance})`)\n blockLines.push('')\n }\n if (result.removed.nodes.length || result.removed.edges.length) {\n blockLines.push('Removed:')\n for (const n of result.removed.nodes) blockLines.push(` - node ${n.id} (${n.type})`)\n for (const e of result.removed.edges)\n blockLines.push(` - edge ${e.id} — ${e.source} -> ${e.target} (${e.type}, ${e.provenance})`)\n blockLines.push('')\n }\n if (result.changed.nodes.length || result.changed.edges.length) {\n blockLines.push('Changed:')\n for (const c of result.changed.nodes) {\n blockLines.push(` ~ node ${c.id} — ${summariseAttrDiff(c.before, c.after)}`)\n }\n for (const c of result.changed.edges) {\n const provBit =\n c.before.provenance !== c.after.provenance\n ? `provenance ${c.before.provenance} → ${c.after.provenance}`\n : summariseAttrDiff(c.before, c.after)\n blockLines.push(` ~ edge ${c.id} — ${provBit}`)\n }\n }\n return {\n summary: `Diff against ${input.againstSnapshot}: ${total} change${total === 1 ? '' : 's'} between the snapshot and the live graph.`,\n block: blockLines.join('\\n').trimEnd(),\n }\n}\n\nfunction summariseAttrDiff(\n before: Record<string, unknown>,\n after: Record<string, unknown>,\n): string {\n const keys = new Set([...Object.keys(before), ...Object.keys(after)])\n const changed: string[] = []\n for (const k of keys) {\n if (JSON.stringify(before[k]) !== JSON.stringify(after[k])) changed.push(k)\n }\n return changed.length === 0 ? 'attributes differ' : `fields changed: ${changed.sort().join(', ')}`\n}\n\nexport interface StaleEdgesInput {\n limit?: number\n edgeType?: string\n project?: string\n}\n\ninterface StaleEventResponse {\n edgeId: string\n source: string\n target: string\n edgeType: string\n thresholdMs: number\n ageMs: number\n lastObserved: string\n transitionedAt: string\n}\n\nexport async function runStaleEdges(\n client: HttpClient,\n input: StaleEdgesInput,\n): Promise<VerbResult> {\n const params = new URLSearchParams()\n if (input.limit !== undefined) params.set('limit', String(input.limit))\n if (input.edgeType) params.set('edgeType', input.edgeType)\n const qs = params.size > 0 ? `?${params.toString()}` : ''\n const body = await client.get<{ count: number; total: number; events: StaleEventResponse[] }>(\n projectPath(input.project, `/stale-events${qs}`),\n )\n const events = body.events\n if (events.length === 0) {\n return {\n summary: input.edgeType\n ? `No stale ${input.edgeType} edges recorded.`\n : 'No stale-edge transitions recorded yet.',\n }\n }\n const blockLines = events.map(\n (e) =>\n ` ${e.transitionedAt} — ${e.source} -[${e.edgeType}]-> ${e.target}` +\n ` (last seen ${e.lastObserved}, threshold ${formatDuration(e.thresholdMs)})`,\n )\n return {\n summary: `${events.length} stale-edge transition${events.length === 1 ? '' : 's'} recorded${input.edgeType ? ` for ${input.edgeType}` : ''}.`,\n block: blockLines.join('\\n'),\n provenance: Provenance.STALE,\n }\n}\n\nexport interface PoliciesInput {\n nodeId?: string\n policyId?: string\n hypotheticalAction?: HypotheticalAction\n project?: string\n}\n\ninterface PoliciesCheckResponse {\n allowed: boolean\n hypotheticalAction?: HypotheticalAction\n violations: PolicyViolation[]\n}\n\nexport async function runPolicies(\n client: HttpClient,\n input: PoliciesInput,\n): Promise<VerbResult> {\n let violations: PolicyViolation[]\n let allowed = true\n let hypothetical: HypotheticalAction | undefined\n\n if (input.hypotheticalAction) {\n if (typeof client.post !== 'function') {\n throw new Error('HttpClient does not support POST — required for policies dry-run')\n }\n const body = await client.post<PoliciesCheckResponse>(\n projectPath(input.project, '/policies/check'),\n { hypotheticalAction: input.hypotheticalAction },\n )\n violations = body.violations\n allowed = body.allowed\n hypothetical = body.hypotheticalAction\n } else {\n const params = new URLSearchParams()\n if (input.policyId) params.set('policyId', input.policyId)\n const qs = params.size > 0 ? `?${params.toString()}` : ''\n const body = await client.get<{ violations: PolicyViolation[] }>(\n projectPath(input.project, `/policies/violations${qs}`),\n )\n violations = body.violations\n allowed = violations.every((v) => v.onViolation !== 'block')\n }\n\n // Optional --node filter is applied here against the returned set; the\n // server-side endpoint doesn't take a node-id query yet.\n if (input.nodeId) {\n violations = violations.filter(\n (v) => v.subject.nodeId === input.nodeId || v.subject.path?.includes(input.nodeId!),\n )\n }\n\n if (violations.length === 0) {\n return {\n summary: hypothetical\n ? `No violations would result from the hypothetical action (${hypothetical.kind}).`\n : 'No policy violations recorded.',\n }\n }\n\n const blockCount = violations.filter((v) => v.onViolation === 'block').length\n const summaryParts: string[] = []\n if (hypothetical) {\n summaryParts.push(\n `Hypothetical ${hypothetical.kind} would surface ${violations.length} violation${violations.length === 1 ? '' : 's'}`,\n )\n } else {\n summaryParts.push(\n `${violations.length} policy violation${violations.length === 1 ? '' : 's'} currently recorded`,\n )\n }\n if (blockCount > 0) summaryParts.push(`${blockCount} of which block`)\n if (!allowed && hypothetical) summaryParts.push('action denied')\n const summary = summaryParts.join('; ') + '.'\n\n const blockLines = violations.map((v) => {\n const subject = v.subject.nodeId ?? v.subject.edgeId ?? v.subject.path?.[0] ?? '(global)'\n return ` • [${v.severity}/${v.onViolation}] ${v.policyName}: ${v.message} — ${subject}`\n })\n const severities = [...new Set(violations.map((v) => v.severity))]\n return {\n summary,\n block: blockLines.join('\\n'),\n confidence: hypothetical ? 0.7 : 1,\n provenance: severities.join(' '),\n }\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// divergences (ADR-060) — the tenth verb. Amends ADR-050's nine-verb\n// allowlist; the verb mirrors the get_divergences MCP tool.\n// ──────────────────────────────────────────────────────────────────────────\n\nexport interface DivergencesInput {\n type?: ReadonlyArray<DivergenceType>\n minConfidence?: number\n node?: string\n project?: string\n}\n\nfunction formatDivergenceLine(d: Divergence): string {\n switch (d.type) {\n case 'missing-observed':\n case 'missing-extracted':\n return ` • [${d.type}] ${d.source} → ${d.target} (${d.edgeType}) — confidence ${d.confidence.toFixed(2)}`\n case 'version-mismatch':\n return ` • [${d.type}] ${d.source} → ${d.target} — declared ${d.extractedVersion}, observed engine ${d.observedVersion} (${d.compatibility})`\n case 'host-mismatch':\n return ` • [${d.type}] ${d.source} → ${d.target} — declared host ${d.extractedHost}, observed host ${d.observedHost}`\n case 'compat-violation':\n return ` • [${d.type}] ${d.source} → ${d.target} — ${d.rule.kind}${d.rule.package ? ` (${d.rule.package})` : ''}`\n }\n}\n\nexport async function runDivergences(\n client: HttpClient,\n input: DivergencesInput,\n): Promise<VerbResult> {\n const params = new URLSearchParams()\n if (input.type && input.type.length > 0) params.set('type', input.type.join(','))\n if (input.minConfidence !== undefined) {\n params.set('minConfidence', String(input.minConfidence))\n }\n if (input.node) params.set('node', input.node)\n const qs = params.size > 0 ? `?${params.toString()}` : ''\n const result = await client.get<DivergenceResult>(\n projectPath(input.project, `/graph/divergences${qs}`),\n )\n if (result.totalAffected === 0) {\n return {\n summary:\n 'No divergences found between the declared (EXTRACTED) and observed (OBSERVED) views of the graph.',\n }\n }\n const headline = result.divergences[0]!\n const summary =\n `Found ${result.totalAffected} divergence${result.totalAffected === 1 ? '' : 's'} between code and production. ` +\n `Highest-confidence: ${headline.type} on ${headline.source} → ${headline.target}. ${headline.reason}`\n const blockLines: string[] = []\n for (const d of result.divergences) {\n blockLines.push(formatDivergenceLine(d))\n blockLines.push(` reason: ${d.reason}`)\n blockLines.push(` recommendation: ${d.recommendation}`)\n }\n const maxConfidence = result.divergences.reduce(\n (m, d) => Math.max(m, d.confidence),\n 0,\n )\n return {\n summary,\n block: blockLines.join('\\n'),\n confidence: maxConfidence,\n provenance: 'composite (EXTRACTED + OBSERVED)',\n }\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Output formatting (ADR-050 #3)\n// ──────────────────────────────────────────────────────────────────────────\n\nfunction formatFooter(\n confidence: number | undefined,\n provenance: string | string[] | undefined,\n): string {\n const c = confidence === undefined ? 'n/a' : confidence.toFixed(2)\n const p =\n provenance === undefined\n ? 'n/a'\n : Array.isArray(provenance)\n ? [...new Set(provenance)].join(', ')\n : provenance\n return `confidence: ${c} · provenance: ${p}`\n}\n\n// Default human output (NL summary + table-shaped block + footer). Mirrors\n// the three-part MCP response from ADR-039 in plain text.\nexport function formatHuman(result: VerbResult): string {\n const sections: string[] = [result.summary.trim()]\n if (result.block && result.block.trim().length > 0) sections.push(result.block.trimEnd())\n sections.push(formatFooter(result.confidence, result.provenance))\n return sections.join('\\n\\n')\n}\n\n// `--json` output. Same three sections as named fields per ADR-050 #3.\nexport function formatJson(result: VerbResult): string {\n return JSON.stringify(\n {\n summary: result.summary,\n block: result.block ?? '',\n confidence: result.confidence ?? null,\n provenance: result.provenance ?? null,\n },\n null,\n 2,\n )\n}\n\n// Exit-code mapping for thrown errors (ADR-050 #4):\n// 0 — success (handled at the call site, never via throw)\n// 1 — server error (HttpError)\n// 2 — misuse (handled in cli.ts before any network call)\n// 3 — daemon unreachable (TransportError)\nexport function exitCodeForError(err: unknown): number {\n if (err instanceof TransportError) return 3\n if (err instanceof HttpError) return 1\n return 1\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Snapshot push (ADR-074 §1)\n//\n// `neat sync` (local + --to <url>) feeds the freshly extracted snapshot into\n// either the local daemon or a remote one. The endpoint is dual-mounted via\n// registerRoutes — default project lands at /snapshot, named projects at\n// /projects/:project/snapshot. The helper goes through the shared\n// HttpClient so the verb stays on the same network path as every query verb.\n// ──────────────────────────────────────────────────────────────────────────\n\nexport interface PushSnapshotInput {\n baseUrl: string\n token: string | undefined\n project: string\n snapshot: unknown\n}\n\nexport interface PushSnapshotResult {\n project: string\n nodesAdded: number\n edgesAdded: number\n nodeCount: number\n edgeCount: number\n}\n\nexport function createSnapshotPushClient(\n baseUrl: string,\n token: string | undefined,\n): HttpClient {\n return createHttpClient(baseUrl, token && token.length > 0 ? token : undefined)\n}\n\nexport async function pushSnapshotToRemote(\n input: PushSnapshotInput,\n): Promise<PushSnapshotResult> {\n const client = createSnapshotPushClient(input.baseUrl, input.token)\n if (typeof client.post !== 'function') {\n throw new Error('HttpClient does not support POST — required for snapshot push')\n }\n return client.post<PushSnapshotResult>(\n `/projects/${encodeURIComponent(input.project)}/snapshot`,\n { snapshot: input.snapshot },\n )\n}\n"],"mappings":"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","names":["path","fs","fs","path","path","fs","fs","path","renderOtelEnvBlock","fs","path","path","fs","fs","path","SDK_PACKAGES","OTEL_ENV","exists","detect","plan","apply","rollback","plan","plan","fs","path","spawn","path","plan","entry","projects","spawn","fs","path","Provenance","path","entry","path","checkDaemonHealth","path","plan","fs","entry","apply","renderOtelEnvBlock"]}
|