@noir-ai/cli 1.7.1 → 1.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/bin.js +9 -9
  2. package/dist/{chunk-DQXQQDJN.js → chunk-6BCKFJ5Z.js} +1 -8
  3. package/dist/{chunk-DQXQQDJN.js.map → chunk-6BCKFJ5Z.js.map} +1 -1
  4. package/dist/{chunk-3E7ZT5OG.js → chunk-7WMO6THL.js} +3 -3
  5. package/dist/{chunk-47ITYQ3A.js → chunk-RYY2FEIQ.js} +2 -2
  6. package/dist/{chunk-WS7K4NKA.js → chunk-YZGQDUJZ.js} +6 -5
  7. package/dist/chunk-YZGQDUJZ.js.map +1 -0
  8. package/dist/{chunk-RYE3BUGP.js → chunk-ZA2URQAP.js} +3 -3
  9. package/dist/{create-P4M52LZZ.js → create-5D5BTGQ7.js} +4 -4
  10. package/dist/index.js +3 -3
  11. package/dist/{install-XACGZ235.js → install-RB2M4VUA.js} +3 -3
  12. package/dist/{sync-35DR6DNN.js → sync-MAQAT33P.js} +3 -3
  13. package/dist/tui/{chunk-L5ZKEOQV.js → chunk-A27BSG6W.js} +1 -9
  14. package/dist/tui/{chunk-L5ZKEOQV.js.map → chunk-A27BSG6W.js.map} +1 -1
  15. package/dist/tui/{chunk-LHT7M6DO.js → chunk-AYJJCWTI.js} +3 -3
  16. package/dist/tui/{chunk-CMGOOU7L.js → chunk-EH3XT7OC.js} +3 -3
  17. package/dist/tui/{chunk-63KFZH6T.js → chunk-OCKOVYUK.js} +2 -2
  18. package/dist/tui/{chunk-BDFQ5S3K.js → chunk-X2VUST7G.js} +6 -5
  19. package/dist/tui/chunk-X2VUST7G.js.map +1 -0
  20. package/dist/tui/{create-IZSOFSO7.js → create-KNHRFLW5.js} +4 -4
  21. package/dist/tui/index.js +9 -9
  22. package/dist/tui/{install-357OEHOZ.js → install-MPHQ65JD.js} +3 -3
  23. package/dist/tui/{sync-32TP7XB6.js → sync-RUHBKBMB.js} +3 -3
  24. package/dist/tui/{update-7HWOY55V.js → update-QPRYOSQN.js} +4 -4
  25. package/dist/{update-J3TAORFX.js → update-6GUYY2OQ.js} +4 -4
  26. package/package.json +9 -9
  27. package/dist/chunk-WS7K4NKA.js.map +0 -1
  28. package/dist/tui/chunk-BDFQ5S3K.js.map +0 -1
  29. /package/dist/{chunk-3E7ZT5OG.js.map → chunk-7WMO6THL.js.map} +0 -0
  30. /package/dist/{chunk-47ITYQ3A.js.map → chunk-RYY2FEIQ.js.map} +0 -0
  31. /package/dist/{chunk-RYE3BUGP.js.map → chunk-ZA2URQAP.js.map} +0 -0
  32. /package/dist/{create-P4M52LZZ.js.map → create-5D5BTGQ7.js.map} +0 -0
  33. /package/dist/{install-XACGZ235.js.map → install-RB2M4VUA.js.map} +0 -0
  34. /package/dist/{sync-35DR6DNN.js.map → sync-MAQAT33P.js.map} +0 -0
  35. /package/dist/tui/{chunk-LHT7M6DO.js.map → chunk-AYJJCWTI.js.map} +0 -0
  36. /package/dist/tui/{chunk-CMGOOU7L.js.map → chunk-EH3XT7OC.js.map} +0 -0
  37. /package/dist/tui/{chunk-63KFZH6T.js.map → chunk-OCKOVYUK.js.map} +0 -0
  38. /package/dist/tui/{create-IZSOFSO7.js.map → create-KNHRFLW5.js.map} +0 -0
  39. /package/dist/tui/{install-357OEHOZ.js.map → install-MPHQ65JD.js.map} +0 -0
  40. /package/dist/tui/{sync-32TP7XB6.js.map → sync-RUHBKBMB.js.map} +0 -0
  41. /package/dist/tui/{update-7HWOY55V.js.map → update-QPRYOSQN.js.map} +0 -0
  42. /package/dist/{update-J3TAORFX.js.map → update-6GUYY2OQ.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/conflict.ts","../../src/dedup-write.ts","../../src/commands/doctor.ts"],"sourcesContent":["// SP-C — conflict-resolution UX seam. The engine (@noir-ai/create) is UI-free;\n// this module builds the scaffold conflict options (policy + a lazy @clack\n// resolver) per the S9 interactivity contract:\n// - TTY + interactive → @clack select menu (Replace/Rename/Duplicate/Keep/Cancel,\n// plus a 6th \"merge (with conflict markers)\" when `mergedWithMarkers` is set)\n// - non-TTY / CI / NO_COLOR → preserve (never silently clobber in a pipe)\n// - --force → overwrite (explicit re-scaffold; no prompt)\n//\n// Universal contract: this seam now drives EVERY file-producing path. The\n// engine's regenerate path consults `onConflict` (apply-to-all keyed by artifact\n// CLASS so an N-pointer `noir init --upgrade` → 1 prompt); managedBlock conflicts\n// stay PER-FILE. A unified line-diff preview (LCS-based, from\n// @noir-ai/create's `lineDiff`) renders to STDERR before the prompt (via the\n// A2 theme — `+` green / `-` red / context dim), so `--json`/piped stdout stays\n// pristine. The 6th \"merge\" option writes the engine-provided zdiff3-marked\n// bytes when a 3-way merge hit an overlap.\nimport type { ConflictContext, ConflictResolution, ConflictResolverReturn } from '@noir-ai/create';\nimport { isInteractive } from './output.js';\nimport { c } from './theme.js';\n\nexport interface ConflictOptsInput {\n /** `--force`: explicit re-scaffold — overwrite differing files, no prompt. */\n force?: boolean;\n /** B1: explicit interactivity signal. When set, wins over the env/TTY\n * heuristic. `false` ⇒ preserve (never prompt); `true` ⇒ allow the @clack\n * resolver. The CLI derives this from the `NOIR_NON_INTERACTIVE` bridge\n * bin.ts owns + the `isInteractive()` TTY/CI/NO_COLOR gate. */\n interactive?: boolean;\n}\n\nexport type ScaffoldConflictOpts = {\n conflictPolicy: 'overwrite' | 'preserve';\n onConflict?: (ctx: ConflictContext) => Promise<ConflictResolverReturn> | ConflictResolverReturn;\n};\n\n/**\n * Build the scaffold conflict options for the current invocation. The engine\n * calls `onConflict` only when a `regenerate` file exists AND differs from the\n * template, so passing this on every init/create/sync is harmless on a first\n * run (no existing files → no conflict).\n *\n * B1 + SP-G: the `interactive` flag (explicit > env bridge > TTY/CI/NO_COLOR\n * gate) drives the prompt decision so the engine never reads `process.env` for\n * interactivity. The `NOIR_NON_INTERACTIVE` bridge (--json/--no-input) and the\n * `isInteractive()` gate both reduce to `preserve` (never prompt).\n *\n * B2 apply-to-all: when the resolver returns `{resolution, applyToAll: true}`\n * the engine stores the choice in its per-run memory keyed by artifact CLASS\n * (regenerate shares one decision; managedBlock/managedBlocks stay per-file).\n */\n/** True when the bin's preAction hook flagged this invocation non-interactive\n * (`--json` / `--no-input`) so the conflict resolver never prompts under those. */\nfunction flaggedNonInteractive(): boolean {\n const v = process.env.NOIR_NON_INTERACTIVE;\n return v !== undefined && v !== '';\n}\n\nexport function buildConflictOpts(input: ConflictOptsInput = {}): ScaffoldConflictOpts {\n if (input.force === true) {\n return { conflictPolicy: 'overwrite' };\n }\n // Explicit interactive flag wins over the env/TTY heuristic.\n if (input.interactive === false) {\n return { conflictPolicy: 'preserve' };\n }\n if (input.interactive === true) {\n return { conflictPolicy: 'preserve', onConflict: clackConflictResolver };\n }\n // Fallback: NOIR_NON_INTERACTIVE bridge (--json/--no-input) OR the\n // isInteractive() TTY/CI/NO_COLOR gate — either ⇒ preserve, never prompt.\n if (flaggedNonInteractive() || !isInteractive()) {\n return { conflictPolicy: 'preserve' };\n }\n return { conflictPolicy: 'preserve', onConflict: clackConflictResolver };\n}\n\n/**\n * B2 — render a colored unified line-diff of `{existing, proposed}` to STDERR\n * before the @clack prompt. Stderr (not stdout) so `--json` / piped stdout\n * stays pristine. The A2 theme colors `+` lines green (`c.ok`), `-` lines red\n * (`c.error`), and dims context lines (`c.dim`); all color is gated through\n * `useColor()` so NO_COLOR / non-TTY / CLICOLOR_FORCE behave consistently.\n * Honored by `theme.test.ts`'s NO_COLOR gate.\n */\nfunction renderDiffPreview(ctx: ConflictContext): void {\n // Lazy-import the engine's line diff so this module stays import-side-effect\n // free for callers that never hit a conflict.\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { lineDiff: ld } = require('@noir-ai/create') as typeof import('@noir-ai/create');\n const lines = ld(ctx.existing, ctx.proposed);\n if (lines.length === 0) return;\n const out: string[] = [`noir: conflict in ${ctx.relPath}`];\n for (const dl of lines) {\n if (dl.type === 'add') out.push(c.ok(`+ ${dl.line}`));\n else if (dl.type === 'del') out.push(c.error(`- ${dl.line}`));\n else out.push(c.dim(` ${dl.line}`));\n }\n process.stderr.write(`${out.join('\\n')}\\n`);\n}\n\n/**\n * SP-C + B2 — @clack-based conflict resolver. Renders a unified diff to stderr\n * (via {@link renderDiffPreview}) BEFORE the select prompt, then offers the\n * usual Replace/Rename/Duplicate/Keep/Cancel set PLUS a 6th \"merge (with\n * conflict markers)\" option when `ctx.mergedWithMarkers` is set (a 3-way merge\n * hit an overlap and the engine has the marked bytes ready).\n *\n * Apply-to-all: when the user picks an option, @clack asks whether to reuse the\n * choice for the rest of the run; if yes, the resolver returns the rich\n * `{resolution, applyToAll: true}` shape and the engine stores it in per-class\n * memory. `managedBlock`/`managedBlocks` modes bypass apply-to-all (per-file).\n */\nasync function clackConflictResolver(ctx: ConflictContext): Promise<ConflictResolverReturn> {\n renderDiffPreview(ctx);\n const clack = await import('@clack/prompts');\n const options: Array<{ value: ConflictResolution; label: string; hint: string }> = [\n {\n value: 'replace',\n label: 'Replace',\n hint: 'overwrite with the template (discard your edits)',\n },\n { value: 'rename', label: 'Rename', hint: 'keep yours as <file>.local; write the template' },\n {\n value: 'duplicate',\n label: 'Create duplicate',\n hint: 'write template to <file>.noir; keep yours',\n },\n { value: 'preserve', label: 'Keep mine', hint: 'skip; leave your file unchanged' },\n { value: 'cancel', label: 'Cancel', hint: 'abort the scaffold' },\n ];\n // 6th \"merge\" option only when the engine has marked bytes ready.\n if (ctx.mergedWithMarkers !== undefined) {\n options.splice(4, 0, {\n value: 'merge',\n label: 'Merge (with conflict markers)',\n hint: 'write the 3-way merge with <<<<<<< / ||||||| / ======= / >>>>>>> markers',\n });\n }\n const choice = await clack.select({\n message: `${ctx.relPath} was edited and differs from the Noir template.`,\n initialValue: 'preserve',\n options,\n });\n if (clack.isCancel(choice)) return 'cancel';\n const resolution = choice as ConflictResolution;\n // Apply-to-all. Only meaningful for `regenerate` (one decision\n // shared across the run); managedBlock/managedBlocks stay per-file (the\n // engine keys memory by path::block there, not by class — so even if the\n // user picks \"all\", the engine won't reuse it across files).\n const mode = ctx.mode ?? 'regenerate';\n if (mode === 'regenerate') {\n const remember = await clack.select({\n message: `Apply \"${labelFor(resolution)}\" to all remaining conflicts this run?`,\n initialValue: 'no',\n options: [\n { value: 'yes', label: 'Yes', hint: 'reuse this choice for the rest of this run' },\n { value: 'no', label: 'No', hint: 'prompt again for each conflict' },\n ],\n });\n if (!clack.isCancel(remember) && remember === 'yes') {\n return { resolution, applyToAll: true };\n }\n }\n return resolution;\n}\n\nfunction labelFor(resolution: ConflictResolution): string {\n switch (resolution) {\n case 'replace':\n return 'Replace';\n case 'rename':\n return 'Rename';\n case 'duplicate':\n return 'Create duplicate';\n case 'preserve':\n return 'Keep mine';\n case 'merge':\n return 'Merge (with conflict markers)';\n case 'cancel':\n return 'Cancel';\n }\n}\n","// Write-path semantic dedup. After `scaffold()` writes host-context\n// files (CLAUDE.md / AGENTS.md / GEMINI.md / .noir/rules/RULES.md), embed the\n// just-written file and compare it against the OTHER existing host-context\n// files. Surface a near-duplicate as a NON-BLOCKING recommendation:\n//\n// - cosine ≥ 0.95 → ACTION prompt (interactive): Replace the existing /\n// Mirror into it / Skip (delete the new file) / Create\n// anyway. Under --json/--no-input the action tier records\n// the near-dup in ScaffoldResult.conflicts[] (mode=\n// 'artifact', similarity set) and proceeds with the\n// default (Create anyway); NEVER prompts.\n// - 0.85–0.95 → INFO-only hint to stderr, write proceeds.\n// - < 0.85 → silent.\n//\n// GRACEFUL DEGRADATION (the make-orreak constraint): the embedder (ONNX\n// Runtime + the ~22 MB all-MiniLM-L6-v2 model) is lazy-loaded with a 5s ping\n// timeout; if it is unavailable, slow, OR throws, the hook prints a one-line\n// stderr warn-skip and returns an empty result. `noir init`/`sync`/`create`\n// NEVER block on a model download or fail because the embedder is missing —\n// dedup is an ENHANCEMENT, not a gate. A fresh project with no existing\n// host-context candidates short-circuits BEFORE any embedding (fast path).\n//\n// CONTENT-HASH GATE: candidate embeddings are cached under\n// `.noir/dedup-cache.json` keyed by SHA-256(content); only changed candidates\n// re-embed. The proposed file's embedding is cached the same way, so a repeat\n// `noir sync` that re-emits byte-identical content does NOT re-embed. Cache\n// entries are scoped to the resolved model id (a model change invalidates them).\n//\n// When a near-dup is found, the conflict record (mode 'artifact'\n// — the closest generic in ConflictContext['mode']) is appended to the\n// ScaffoldResult.conflicts[] the caller returns, so `--json` consumers see the\n// near-dup with its cosine `similarity` without a prompt.\n//\n// Stream discipline: every hint / warn-skip → STDERR; the CLI's `json()` is the\n// sole stdout writer. Colors via the A2 theme (`c.warn`/`c.dim`) so NO_COLOR /\n// non-TTY strip cleanly.\n\nimport { createHash } from 'node:crypto';\nimport { mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { ProjectInfo } from '@noir-ai/core';\nimport type { ConflictRecord, ScaffoldResult } from '@noir-ai/create';\nimport { collectDedupCandidates } from './commands/doctor.js';\nimport { c } from './theme.js';\n\n/** Local embedder shape (@noir-ai/context's `EmbedFn`). */\nexport type EmbedLike = (text: string) => Promise<Float32Array>;\n\n/** Host-context files dedup scans (mirrors `collectDedupCandidates`). */\nconst HOST_CONTEXT_RELS = new Set(['CLAUDE.md', 'AGENTS.md', 'GEMINI.md', '.noir/rules/RULES.md']);\n\n/** Cosine ≥ this → ACTION prompt (interactive) or conflict record (--json). */\nexport const ACTION_THRESHOLD = 0.95;\n/** Cosine ≥ this (and < ACTION) → INFO-only hint. Below → silent. */\nexport const INFO_THRESHOLD = 0.85;\n/** The first embed() call triggers ONNX load + possibly a model download; bound\n * it so init/sync/create never block indefinitely on a cold cache. */\nexport const EMBEDDER_PING_TIMEOUT_MS = 5000;\n/** Bump on disk-format changes; an older file is discarded (no migration). */\nconst DEDUP_CACHE_VERSION = 1;\n\nexport interface DedupWriteOpts {\n /** Explicit interactivity flag (the engine + skills emit read the same). */\n interactive: boolean;\n /** Project info — read from `.noir/config.yml` by the caller. When undefined\n * OR when the resolved embedder is `kind:'none'`, the hook warn-skips. */\n project?: ProjectInfo;\n /** Testability seam (mirrors `checkSemanticDupDoctor`'s `opts.embed`): when\n * set, the hook uses this embedder directly and skips the lazy ONNX load +\n * ping-timeout. Production omits it. */\n embed?: EmbedLike;\n}\n\nexport interface DedupWriteResult {\n /** Near-duplicates found, one entry per (proposed, matched) pair. */\n found: Array<{ proposedRel: string; matchedRel: string; similarity: number }>;\n /** Conflict records to append to {@link ScaffoldResult.conflicts}. */\n conflicts: ConflictRecord[];\n}\n\n/**\n * Run the write-path semantic dedup over the host-context files in\n * `res.written`. Does NOT mutate `res`; the caller decides whether to splice\n * `result.conflicts` into `res.conflicts`. Non-blocking: any embedder failure\n * degrades to a stderr warn-skip and an empty result.\n */\nexport async function checkWritePathDedup(\n root: string,\n res: ScaffoldResult,\n opts: DedupWriteOpts,\n): Promise<DedupWriteResult> {\n const result: DedupWriteResult = { found: [], conflicts: [] };\n // Fast path: only host-context files we JUST wrote are eligible. Fresh\n // projects (first init/create) typically write ONE host pointer + RULES.md;\n // if no other host-context file exists, candidates is empty → no embedding.\n const writtenHostFiles = res.written.filter((p) => HOST_CONTEXT_RELS.has(p));\n if (writtenHostFiles.length === 0) return result;\n\n const cache = loadCache(root);\n const embed = await resolveEmbedder(opts, cache);\n if (embed === undefined) return result; // warn-skip already emitted\n\n // Wrap the embedder with the content-hash cache so unchanged candidates (and\n // a repeat-emit of byte-identical proposed bytes) skip the underlying call.\n const cachedEmbed = makeCachedEmbed(cache, embed);\n\n for (const proposedRel of writtenHostFiles) {\n const proposedAbs = join(root, proposedRel);\n let proposedText: string;\n try {\n proposedText = readFileSync(proposedAbs, 'utf8');\n } catch {\n continue;\n }\n if (proposedText.trim().length === 0) continue;\n\n // Candidates = existing host-context files MINUS this proposed path. A\n // first-run init writing CLAUDE.md while AGENTS.md already exists compares\n // the new CLAUDE.md against AGENTS.md + RULES.md (not against itself).\n const candidates = collectDedupCandidates(root).filter((c) => c.path !== proposedRel);\n if (candidates.length === 0) continue; // fresh project, nothing to compare\n\n const ctx = await import('@noir-ai/context');\n const proposed = { path: proposedRel, text: proposedText };\n // Graceful degradation INSIDE the loop too: an embedder that loads (passes\n // the ping) but throws mid-batch (transient remote failure, OOM, …) must\n // never break the write. Catch, warn-skip this proposal, keep going.\n let best: Awaited<ReturnType<typeof ctx.findNearestDuplicate>>;\n try {\n best = await ctx.findNearestDuplicate(\n proposed,\n candidates,\n async (t) => cachedEmbed(t),\n INFO_THRESHOLD,\n );\n } catch (e) {\n process.stderr.write(\n `${c.dim(`noir: semantic-dedup skipped for ${proposedRel} (${errMsg(e)}).`)}\\n`,\n );\n continue;\n }\n if (best === null) continue;\n\n const matchedRel = best.a === proposedRel ? best.b : best.a;\n const sim = best.similarity;\n result.found.push({ proposedRel, matchedRel, similarity: sim });\n\n if (sim >= ACTION_THRESHOLD) {\n if (opts.interactive) {\n await promptDedupAction(root, proposedRel, matchedRel, proposedText, sim);\n } else {\n // --json / --no-input: record + proceed with the default (Create\n // anyway). Never prompt under non-interactive.\n process.stderr.write(\n `${c.warn('noir: near-duplicate')} ${proposedRel} ≈ ${matchedRel} (cosine ${sim.toFixed(2)}); creating anyway.\\n`,\n );\n }\n } else {\n // 0.85 – 0.95: INFO-only hint. Write already succeeded; just surface.\n process.stderr.write(\n `${c.dim(`noir: hint ${proposedRel} looks similar to existing ${matchedRel} (cosine ${sim.toFixed(2)}).`)}\\n`,\n );\n }\n\n // Append a structured record so --json consumers see the\n // near-dup with its cosine similarity without a prompt. The path is the\n // file we just wrote (consistent with the \"path = the file being\n // written\" convention); existingSha is the MATCHED file's hash, proposedSha the new\n // bytes'. Resolution 'preserve' = we kept both as-is under Create-anyway.\n const matchedText = safeRead(join(root, matchedRel));\n result.conflicts.push({\n path: proposedRel,\n mode: 'artifact',\n similarity: sim,\n existingSha: sha256Hex12(matchedText ?? ''),\n proposedSha: sha256Hex12(proposedText),\n resolution: 'preserve',\n });\n }\n\n saveCache(root, cache);\n return result;\n}\n\n/**\n * Resolve the embedder: injected (test seam) > local-embedder from the user's\n * `context.embedder` config. Returns undefined (after a stderr warn-skip) when\n * kind='none', the factory throws, OR the first ping exceeds the timeout.\n *\n * Model-id tracking runs in BOTH paths so a config change invalidates the\n * on-disk cache even when the caller injected an embedder (the test seam\n * still flows through the same cache discipline as production).\n */\nasync function resolveEmbedder(\n opts: DedupWriteOpts,\n cache: DedupCache,\n): Promise<EmbedLike | undefined> {\n const ctx = await import('@noir-ai/context');\n // Resolve the model id from config when available; an injected embedder\n // without project info skips invalidation (cache stays model-scoped to '' —\n // a fresh cache, which is fine for tests that always inject).\n let modelId: string | undefined;\n if (opts.project !== undefined) {\n const cfg = ctx.resolveEmbedderConfig(opts.project.config.context);\n if (cfg.kind === 'none') {\n process.stderr.write(`${c.dim('noir: semantic-dedup skipped (embedder kind=none).')}\\n`);\n return undefined;\n }\n modelId =\n cfg.kind === 'local' ? (cfg.model ?? ctx.DEFAULT_LOCAL_MODEL) : (cfg.model ?? cfg.kind);\n // Invalidate cache on a model change BEFORE deciding the embedder source.\n if (modelId !== undefined && cache.model !== modelId) {\n cache.model = modelId;\n cache.entries = {};\n }\n }\n // Test seam: an injected embedder bypasses the lazy ONNX load + ping.\n if (opts.embed !== undefined) return opts.embed;\n if (modelId === undefined) return undefined; // no project + no inject → skip\n\n let embed: EmbedLike;\n try {\n const project = opts.project;\n if (project === undefined) return undefined;\n const cfg = ctx.resolveEmbedderConfig(project.config.context);\n embed = ctx.createEmbedFn(cfg).embed as EmbedLike;\n } catch (e) {\n process.stderr.write(\n `${c.dim(`noir: semantic-dedup skipped (embedder unavailable: ${errMsg(e)}).`)}\\n`,\n );\n return undefined;\n }\n // Pre-warm with a ping under a timeout. The first call triggers the ONNX\n // load + (on a cold ~/.noir/models/) a ~22 MB model download; bound it so\n // init/sync never block on the network. A throw OR a timeout → warn-skip.\n const ping = await withTimeout(\n embed('ping').then(() => true),\n EMBEDDER_PING_TIMEOUT_MS,\n );\n if (ping !== true) {\n process.stderr.write(\n `${c.dim('noir: semantic-dedup skipped (embedder load too slow or unavailable).')}\\n`,\n );\n return undefined;\n }\n return embed;\n}\n\n/** ACTION prompt for the ≥0.95 tier (interactive only). */\nasync function promptDedupAction(\n root: string,\n proposedRel: string,\n matchedRel: string,\n proposedText: string,\n sim: number,\n): Promise<void> {\n const clack = await import('@clack/prompts');\n type Choice = 'create' | 'skip' | 'replace' | 'mirror';\n const choice = await clack.select({\n message: `${proposedRel} is near-duplicate of existing ${matchedRel} (cosine ${sim.toFixed(2)}). Create anyway?`,\n initialValue: 'create' as Choice,\n options: [\n {\n value: 'create' as Choice,\n label: 'Create anyway',\n hint: 'keep the new file as-is (default)',\n },\n { value: 'skip' as Choice, label: 'Skip', hint: `delete ${proposedRel}; keep ${matchedRel}` },\n {\n value: 'replace' as Choice,\n label: 'Replace existing',\n hint: `overwrite ${matchedRel} with this content`,\n },\n {\n value: 'mirror' as Choice,\n label: 'Mirror into existing',\n hint: `append this content to ${matchedRel}`,\n },\n ],\n });\n if (clack.isCancel(choice)) return; // cancel = keep the default (Create anyway)\n if (choice === 'skip') {\n try {\n rmSync(join(root, proposedRel), { force: true });\n } catch {\n /* best-effort; the write already happened */\n }\n } else if (choice === 'replace') {\n try {\n writeFileSync(join(root, matchedRel), proposedText, 'utf8');\n } catch {\n /* best-effort */\n }\n } else if (choice === 'mirror') {\n try {\n const existing = readFileSync(join(root, matchedRel), 'utf8');\n writeFileSync(\n join(root, matchedRel),\n `${existing}\\n\\n<!-- mirrored from ${proposedRel} -->\\n${proposedText}\\n`,\n 'utf8',\n );\n } catch {\n /* best-effort */\n }\n }\n // 'create' → no-op (the just-written file stands).\n}\n\n// ---------------------------------------------------------------------------\n// Content-hash cache (.noir/dedup-cache.json).\n// ---------------------------------------------------------------------------\n\ninterface DedupCache {\n version: number;\n model: string;\n entries: Record<string, { v: number[] }>;\n}\n\nfunction emptyCache(): DedupCache {\n return { version: DEDUP_CACHE_VERSION, model: '', entries: {} };\n}\n\nfunction cachePath(root: string): string {\n return join(root, '.noir', 'dedup-cache.json');\n}\n\nfunction loadCache(root: string): DedupCache {\n try {\n const raw = readFileSync(cachePath(root), 'utf8');\n const parsed = JSON.parse(raw) as Partial<DedupCache>;\n if (parsed.version !== DEDUP_CACHE_VERSION) return emptyCache();\n if (typeof parsed.entries !== 'object' || parsed.entries === null) return emptyCache();\n return {\n version: DEDUP_CACHE_VERSION,\n model: typeof parsed.model === 'string' ? parsed.model : '',\n entries: parsed.entries,\n };\n } catch {\n return emptyCache();\n }\n}\n\nfunction saveCache(root: string, cache: DedupCache): void {\n try {\n mkdirSync(join(root, '.noir'), { recursive: true });\n writeFileSync(cachePath(root), JSON.stringify(cache), 'utf8');\n } catch {\n // Best-effort; cache persistence is an enhancement, never a gate.\n }\n}\n\n/** Wrap `embed` with a SHA-256 content-hash cache. Cache hits return the\n * stored vector WITHOUT calling `embed`; misses call `embed` and store. */\nfunction makeCachedEmbed(cache: DedupCache, embed: EmbedLike): EmbedLike {\n return async (text: string): Promise<Float32Array> => {\n const key = createHash('sha256').update(text, 'utf8').digest('hex');\n const cached = cache.entries[key];\n if (cached !== undefined) return Float32Array.from(cached.v);\n const v = await embed(text);\n cache.entries[key] = { v: Array.from(v) };\n return v;\n };\n}\n\n// ---------------------------------------------------------------------------\n// Small helpers.\n// ---------------------------------------------------------------------------\n\n/** SHA-256 hex of content, first 12 chars (matches the sha convention). */\nfunction sha256Hex12(text: string): string {\n return createHash('sha256').update(text, 'utf8').digest('hex').slice(0, 12);\n}\n\nfunction safeRead(abs: string): string | undefined {\n try {\n return readFileSync(abs, 'utf8');\n } catch {\n return undefined;\n }\n}\n\n/** Resolve `p` OR undefined on timeout/throw (never rejects). The underlying\n * promise keeps running in the background; we just stop awaiting it. */\nfunction withTimeout<T>(p: Promise<T>, ms: number): Promise<T | undefined> {\n return new Promise((resolve) => {\n const t = setTimeout(() => resolve(undefined), ms);\n p.then(\n (v) => {\n clearTimeout(t);\n resolve(v);\n },\n () => {\n clearTimeout(t);\n resolve(undefined);\n },\n );\n });\n}\n\nfunction errMsg(e: unknown): string {\n return e instanceof Error ? e.message : String(e);\n}\n","// S9 — `noir doctor`.\n//\n// Environment + project health. Runs a fixed set of checks and renders a\n// results table (human, stderr) or the versioned `{ok,data}` envelope (--json,\n// stdout). Exit 1 if any CRITICAL (fail) check is unhealthy, else 0.\n//\n// Severity model (S9 spec F8):\n// - ok — healthy.\n// - warn — degraded but usable (daemon down, onnx missing, provider key\n// missing, project not initialized). NEVER triggers exit 1.\n// - fail — CRITICAL: the product is broken on this host. Only `config` (parse\n// error), `native deps` (better-sqlite3 / sqlite-vec will not load),\n// and `store` (open fails) can fail. Exit 1 if any fail.\n//\n// Honesty rules: provider status uses `resolveModelConfig` — a PURE projection\n// of the user's config + env-var NAME presence; it makes NO live call (blueprint\n// D5). Native-dep probes are best-effort try/catch (the store's native\n// binaries are probed via `vecAvailability`, the single cross-package surface;\n// onnxruntime-node is the context engine's own dep and is probed separately).\n//\n// Cold-start (NF6): the @noir-ai/store import (which loads better-sqlite3) is\n// DYNAMIC, inside the action, so merely running `noir status` / `noir --help`\n// never pays the native-bindings cost. @noir-ai/model is imported eagerly — its\n// provider self-registration is light (SDKs load lazily inside `complete()`).\n//\n// Stream discipline (S9): `--json` writes `{ok:true, data:{checks,summary}}`\n// to stdout (the only stdout write). Doctor always emits `ok:true` because the\n// COMMAND succeeded in producing a diagnosis; the system-health pass/fail is\n// signaled by the EXIT CODE (0 healthy / 1 critical failure) — the same shape\n// `npm audit --json` uses (valid JSON out, non-zero exit when issues found).\n\nimport { spawnSync } from 'node:child_process';\nimport { existsSync, readdirSync, readFileSync } from 'node:fs';\nimport { dirname, join, relative } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { type HostId, resolveAdapter } from '@noir-ai/adapters';\nimport {\n detectActiveMethod,\n type InstallMethod,\n latestVersionFromCache,\n loadProjectInfo,\n NOIR_VERSION,\n type ProjectInfo,\n paths,\n readInstallRecord,\n readUpdateCache,\n} from '@noir-ai/core';\nimport { CURRENT_SCAFFOLD_VERSION, readScaffoldVersion } from '@noir-ai/create';\nimport { pidAlive, readDaemonRecord } from '@noir-ai/daemon';\nimport { resolveModelConfig } from '@noir-ai/model';\nimport {\n type CliOptions,\n EXIT,\n error as err,\n log,\n NoirCliError,\n success,\n table,\n warn,\n} from '../output.js';\nimport { type BadgeState, badge } from '../theme.js';\n\n/** Options accepted by `doctor`: the global flags + the opt-in `--dedup`. */\nexport interface DoctorOptions extends CliOptions {\n /** `--dedup`: scan host-context + `.noir/` docs for semantic near-duplicates.\n * Opt-in (loads the local embedder) so a default `noir doctor` stays fast. */\n dedup?: boolean;\n}\n\ntype Severity = 'ok' | 'warn' | 'fail';\n\n/** One row of the doctor report (table cell + `--json` element). */\nexport interface CheckResult {\n name: string;\n status: Severity;\n detail: string;\n}\n\n/** The `data` payload of `noir doctor --json`. */\nexport interface DoctorPayload {\n noir: string;\n checks: CheckResult[];\n summary: { ok: number; warn: number; fail: number };\n /** Scaffold-version drift (slice S). `onDisk` is null when the stamp is\n * absent (uninitialized or pre-Slice-S project); `drift` is true only when\n * a stamp is present AND differs from the engine's current version. */\n scaffold: { onDisk: string | null; current: string; drift: boolean };\n /** RULES.md budget measurement. `null` when the project isn't\n * initialized OR `.noir/rules/RULES.md` is absent — in either case there\n * is nothing to measure and the check row stays informational (warn skip\n * or ok \"no RULES.md\"). Never drives `fail` — over-budget is a `warn`. */\n rules: {\n onDisk: { bytes: number; lines: number };\n budget: { kb: number; maxLines: number };\n over: boolean;\n } | null;\n /** S10 host report. `null` when the project isn't initialized (no resolved\n * host); otherwise carries the active `host` + the list of repo-relative\n * primary artifact paths the doctor verified (AGENTS.md for agents-md/\n * cursor/opencode; the host's native context file when distinct from\n * AGENTS.md (claude → CLAUDE.md, gemini → GEMINI.md); the host's MCP\n * config). The check row is `ok` when\n * all present, `warn` (NEVER `fail`) when any are missing — re-running\n * `noir sync` restores them. */\n host: { active: HostId; expected: string[]; missing: string[] } | null;\n /** S11 publish-readiness report (repo-developer-facing, advisory). `null`\n * when doctor is NOT running from a monorepo checkout (a global install has\n * no workspace package.json set to validate → the row reports `ok`\n * \"skipped\"). Otherwise carries the count of workspace `package.json` files\n * validated + the list of advisory issues found (bad semver, missing\n * `files`, cli missing `bin`, …). The row severity is `warn` when any issues\n * are present, `ok` otherwise — NEVER `fail` (a missing field does not break\n * the local install). */\n publish: { checked: number; issues: string[] } | null;\n /** C1 install-method report. `method` from ~/.noir/install.json (fallback\n * unknown); `latestKnown` from the update cache (never a live call). */\n install: {\n method: InstallMethod;\n installedVersion: string | null;\n latestKnown: string | null;\n } | null;\n}\n\n// ---------------------------------------------------------------------------\n// Small helpers\n// ---------------------------------------------------------------------------\n\n/** Best-effort probe of the `onnxruntime-node` native binding. */\nasync function probeOnnx(): Promise<{ ok: boolean; reason: string }> {\n try {\n // Variable specifier (not a string literal) so tsc does NOT try to resolve\n // a module the CLI package does not directly depend on — onnxruntime-node\n // is the context engine's dep and resolves through ITS node_modules at\n // runtime. Best-effort: hosts that hoist it resolve; otherwise not-loadable.\n const spec = 'onnxruntime-node';\n await import(spec);\n return { ok: true, reason: 'loadable' };\n } catch (e) {\n return { ok: false, reason: e instanceof Error ? e.message : String(e) };\n }\n}\n\n/** Human label for the onnx probe outcome (hides confusing module-not-found noise). */\nfunction describeOnnx(o: { ok: boolean; reason: string }): string {\n if (o.ok) return 'loadable';\n if (/Cannot find (module|package)/i.test(o.reason)) {\n return 'not resolvable from CLI probe (best-effort)';\n }\n const r = o.reason.length > 60 ? `${o.reason.slice(0, 59)}…` : o.reason;\n return `probe failed: ${r}`;\n}\n\nfunction fmtUptime(sec: number): string {\n if (!Number.isFinite(sec) || sec < 0) return 'unknown';\n if (sec < 60) return `${sec}s`;\n if (sec < 3600) return `${Math.floor(sec / 60)}m ${sec % 60}s`;\n return `${Math.floor(sec / 3600)}h ${Math.floor((sec % 3600) / 60)}m`;\n}\n\nfunction msg(e: unknown): string {\n return e instanceof Error ? e.message : String(e);\n}\n\n// ---------------------------------------------------------------------------\n// Checks. Each appends to `checks`; project-dependent ones short-circuit to a\n// `warn` \"skipped\" row when the project isn't initialized (so the table still\n// accounts for them, but a pre-init `noir doctor` never exit-1s on them).\n// ---------------------------------------------------------------------------\n\nasync function checkRuntime(checks: CheckResult[]): Promise<void> {\n checks.push({\n name: 'runtime',\n status: 'ok',\n detail: `noir ${NOIR_VERSION} · node ${process.version} · ${process.platform}`,\n });\n}\n\nfunction checkConfig(root: string): { project: ProjectInfo | undefined; result: CheckResult } {\n const configPath = paths.config(root);\n if (!existsSync(configPath)) {\n return {\n project: undefined,\n result: {\n name: 'config',\n status: 'warn',\n detail: `no .noir/config.yml in ${root} — run \\`noir init\\``,\n },\n };\n }\n try {\n const project = loadProjectInfo(root);\n return {\n project,\n result: {\n name: 'config',\n status: 'ok',\n detail: `host=${project.config.host} · mode=${project.config.mode}`,\n },\n };\n } catch (e) {\n return {\n project: undefined,\n result: { name: 'config', status: 'fail', detail: `config parse error: ${msg(e)}` },\n };\n }\n}\n\nasync function checkDaemon(checks: CheckResult[]): Promise<void> {\n const rec = readDaemonRecord();\n if (!rec) {\n checks.push({\n name: 'daemon',\n status: 'warn',\n detail: 'not running (start with `noir daemon start`)',\n });\n return;\n }\n if (!pidAlive(rec.pid)) {\n checks.push({\n name: 'daemon',\n status: 'warn',\n detail: `stale record (pid ${rec.pid} not alive)`,\n });\n return;\n }\n try {\n const res = await fetch(`http://127.0.0.1:${rec.port}/health`);\n const body =\n res.status === 200 ? ((await res.json()) as { ok?: boolean; uptimeSec?: number }) : null;\n if (body && body.ok === true) {\n checks.push({\n name: 'daemon',\n status: 'ok',\n detail: `running (pid ${rec.pid}, port ${rec.port}, up ${fmtUptime(body.uptimeSec ?? 0)})`,\n });\n return;\n }\n checks.push({\n name: 'daemon',\n status: 'warn',\n detail: `record present but /health unreachable on port ${rec.port}`,\n });\n } catch {\n checks.push({\n name: 'daemon',\n status: 'warn',\n detail: `record present but /health unreachable on port ${rec.port}`,\n });\n }\n}\n\nasync function checkNativeDeps(checks: CheckResult[]): Promise<{ vecOk: boolean }> {\n // vecAvailability probes better-sqlite3 + sqlite-vec together (the store opens\n // a Database and loads sqlite-vec). Dynamic import keeps the native bindings\n // out of cold-start for every other command.\n const { vecAvailability } = await import('@noir-ai/store');\n const vec = vecAvailability();\n const onnx = await probeOnnx();\n const vecOk = vec.ok === true;\n const onnxOk = onnx.ok === true;\n // The sqlite side is CRITICAL (the store cannot open without it). onnx only\n // backs local embeddings, so its absence is a warning (search → BM25-only).\n const status: Severity = vecOk ? (onnxOk ? 'ok' : 'warn') : 'fail';\n checks.push({\n name: 'native deps',\n status,\n detail: `better-sqlite3+sqlite-vec: ${vecOk ? 'loadable' : vec.ok === false ? vec.reason : 'unknown'} · onnxruntime-node: ${describeOnnx(onnx)}`,\n });\n return { vecOk };\n}\n\nasync function checkStore(\n checks: CheckResult[],\n project: ProjectInfo | undefined,\n root: string,\n): Promise<void> {\n if (!project) {\n checks.push({ name: 'store', status: 'warn', detail: 'skipped — not initialized' });\n return;\n }\n const dbPath = paths.storeDb(root, project.id);\n if (!existsSync(dbPath)) {\n // Fresh project: the store DB is created LAZILY when the daemon first runs\n // (or when content is indexed) — `noir init`/`create` does not pre-create it.\n // Its absence on an otherwise-initialized project is EXPECTED, not a failure:\n // surfacing it as `fail` would alarm every new user on their first `noir doctor`.\n // Warn (never exit-1) with the action that materializes the store.\n checks.push({\n name: 'store',\n status: 'warn',\n detail: `not created yet — the store DB is created when the daemon first runs (\\`noir daemon start\\` or index content); expected at ${dbPath}`,\n });\n return;\n }\n const { openStore } = await import('@noir-ai/store');\n let store: { close(): Promise<void> | void } | undefined;\n try {\n store = await openStore({ projectId: project.id, root, readonly: true });\n checks.push({\n name: 'store',\n status: 'ok',\n detail: `opens readonly (db: ${paths.storeDb(root, project.id)})`,\n });\n } catch (e) {\n checks.push({ name: 'store', status: 'fail', detail: `open failed: ${msg(e)}` });\n } finally {\n if (store) {\n try {\n await Promise.resolve(store.close());\n } catch {\n /* a close error must not mask the open result */\n }\n }\n }\n}\n\nfunction checkEmbedder(\n checks: CheckResult[],\n project: ProjectInfo | undefined,\n vecOk: boolean,\n): void {\n if (!project) {\n checks.push({ name: 'embedder', status: 'warn', detail: 'skipped — not initialized' });\n return;\n }\n const emb = project.config.context.embedder;\n const kind = emb.kind;\n const model = typeof emb.model === 'string' && emb.model.length > 0 ? emb.model : '<unset>';\n if (kind === 'none') {\n checks.push({\n name: 'embedder',\n status: 'ok',\n detail: `kind=none (BM25-only) · dim=${emb.dim}`,\n });\n return;\n }\n if (!vecOk) {\n // vec native layer is the embedder's hard prereq (vecs write into vec0).\n checks.push({\n name: 'embedder',\n status: 'warn',\n detail: `${kind}/${model} (${emb.dim}-dim) configured but vec native layer unavailable — search degrades to BM25`,\n });\n return;\n }\n checks.push({\n name: 'embedder',\n status: 'ok',\n detail: `${kind}/${model} (${emb.dim}-dim) · vec backend available`,\n });\n}\n\nfunction checkProvider(checks: CheckResult[], project: ProjectInfo | undefined): void {\n if (!project) {\n checks.push({ name: 'provider', status: 'warn', detail: 'skipped — not initialized' });\n return;\n }\n // PURE projection — resolveModelConfig reads config + env-var NAMES only; it\n // NEVER makes a live call and NEVER infers a provider from env-var presence.\n const resolved = resolveModelConfig(project.config.model);\n const names = Object.keys(resolved.providers);\n if (names.length === 0) {\n checks.push({\n name: 'provider',\n status: 'ok',\n detail: 'none configured (offline mode; drafting degrades to templates)',\n });\n return;\n }\n const parts: string[] = [];\n let missing = false;\n for (const name of names) {\n const p = resolved.providers[name];\n if (!p) continue;\n const key = p.hasKey ? 'key present' : p.apiKeyEnv ? `missing ${p.apiKeyEnv}` : 'anonymous';\n if (!p.hasKey && p.apiKeyEnv) missing = true;\n parts.push(`${name}/${p.model ?? '?'} (${key})`);\n }\n // Provider readiness is never CRITICAL — the model layer degrades to `null`\n // (templates) when a key is missing, so this is an ok/warn signal only.\n checks.push({\n name: 'provider',\n status: missing ? 'warn' : 'ok',\n detail: parts.join(' · '),\n });\n}\n\n// ---------------------------------------------------------------------------\n// C1 — doctor install row (advisory; ok/warn only, never fail, cache-only).\n// ---------------------------------------------------------------------------\n\nexport interface InstallCheckOutcome {\n name: 'install';\n status: 'ok' | 'warn';\n detail: string;\n method: InstallMethod;\n installedVersion: string | null;\n latestKnown: string | null;\n}\n\n/** Pure: build the doctor `install` row. NEVER `fail` — an install method issue\n * is advisory, not a broken host. Reads the cache only; no network. */\nexport function buildInstallCheck(opts: {\n method: InstallMethod;\n version: string | null;\n latestKnown: string | null;\n}): InstallCheckOutcome {\n const { method, version, latestKnown } = opts;\n const parts: string[] = [`method=${method}`];\n if (version) parts.push(`v${version}`);\n const advisory: string[] = [];\n if (method !== 'native') advisory.push('native recommended');\n if (latestKnown && version && latestKnown !== version) advisory.push('update available');\n const status: 'ok' | 'warn' = advisory.length > 0 ? 'warn' : 'ok';\n if (advisory.length > 0) parts.push(advisory.join(' + '));\n return {\n name: 'install',\n status,\n detail: parts.join(' · '),\n method,\n installedVersion: version,\n latestKnown,\n };\n}\n\nfunction checkScaffoldVersion(\n checks: CheckResult[],\n root: string,\n): {\n onDisk: string | null;\n current: string;\n drift: boolean;\n} {\n // readScaffoldVersion never throws — it returns null on an absent/malformed\n // stamp, so doctor keeps reporting even on a partially-initialized project.\n const onDisk = readScaffoldVersion(root);\n const current = CURRENT_SCAFFOLD_VERSION;\n const drift = onDisk !== null && onDisk !== current;\n // Drift is NEVER critical: a stale scaffold still works (the manifest entries\n // are forward-compatible), it just means `noir init --upgrade` will run\n // pending migrations. Absent stamp on an uninitialized project → warn (parity\n // with the other project-dependent checks that skip-with-warn pre-init).\n const status: Severity = onDisk === null || drift ? 'warn' : 'ok';\n const detail =\n onDisk === null\n ? 'no .noir/scaffold-version stamp (run `noir init`)'\n : drift\n ? `on-disk ${onDisk} ≠ current ${current} (run \\`noir init --upgrade\\`)`\n : `${onDisk} (up to date)`;\n checks.push({ name: 'scaffold version', status, detail });\n return { onDisk, current, drift };\n}\n\n/**\n * Soft RULES.md budget cap. Mirrors the Failure-Backed Rules doctrine:\n * an over-budget RULES.md tends to accumulate stale / speculative clauses, so\n * doctor warns (NEVER fails — purely a hygiene nudge) when the file exceeds\n * the configured `lengthBudgetKb` (default 6 KB) OR a 150-line ceiling. The\n * check is honest about the three \"nothing to measure\" cases:\n *\n * • project not initialized → skip-warn (parity with store/embedder/provider)\n * • RULES.md absent → ok informational (no file = no budget problem)\n * • RULES.md unreadable → warn (treat like a malformed-stamp: surface it)\n *\n * Returns the structured measurement for the `--json` envelope's `data.rules`,\n * or `null` when there is nothing to measure (absent / skipped).\n */\nfunction checkRulesMdBudget(\n checks: CheckResult[],\n root: string,\n project: ProjectInfo | undefined,\n): {\n onDisk: { bytes: number; lines: number };\n budget: { kb: number; maxLines: number };\n over: boolean;\n} | null {\n if (!project) {\n checks.push({ name: 'rules budget', status: 'warn', detail: 'skipped — not initialized' });\n return null;\n }\n const rulesPath = paths.rulesMd(root);\n if (!existsSync(rulesPath)) {\n // No RULES.md is fine — most projects don't have one yet. Informational ok\n // so a green run stays green without forcing a file creation.\n checks.push({\n name: 'rules budget',\n status: 'ok',\n detail: 'no .noir/rules/RULES.md',\n });\n return null;\n }\n // Read + measure. A read/decode failure surfaces as a warn (parallel to the\n // malformed-stamp handling in checkScaffoldVersion): the doctor keeps\n // reporting rather than crashing, and the user sees a clear hint.\n let content: string;\n try {\n content = readFileSync(rulesPath, 'utf8');\n } catch (e) {\n checks.push({\n name: 'rules budget',\n status: 'warn',\n detail: `RULES.md unreadable: ${msg(e)}`,\n });\n return null;\n }\n // bytes = UTF-8 file size on disk (the natural unit for a KB budget). lines\n // uses wc-style counting: count of '\\n' chars, +1 if the last line has no\n // trailing newline; 0 only for an empty file.\n const bytes = Buffer.byteLength(content, 'utf8');\n const lineCount =\n content.length === 0 ? 0 : content.split('\\n').length - (content.endsWith('\\n') ? 1 : 0);\n const lengthBudgetKb = project.config.rules.lengthBudgetKb;\n const budgetBytes = lengthBudgetKb * 1024;\n const maxLines = 150;\n const overBytes = bytes > budgetBytes;\n const overLines = lineCount > maxLines;\n const over = overBytes || overLines;\n const status: Severity = over ? 'warn' : 'ok';\n const kb = (n: number): string => (n / 1024).toFixed(1);\n const detail = over\n ? `OVER: ${kb(bytes)} KB / ${lengthBudgetKb} KB · ${lineCount}/${maxLines} lines — trim RULES.md (failure-backed clauses only) or raise rules.lengthBudgetKb`\n : `${kb(bytes)} KB / ${lengthBudgetKb} KB · ${lineCount}/${maxLines} lines (within budget)`;\n checks.push({ name: 'rules budget', status, detail });\n return {\n onDisk: { bytes, lines: lineCount },\n budget: { kb: lengthBudgetKb, maxLines },\n over,\n };\n}\n\nfunction summarize(checks: CheckResult[]): DoctorPayload['summary'] {\n let ok = 0;\n let warnN = 0;\n let fail = 0;\n for (const c of checks) {\n if (c.status === 'ok') ok++;\n else if (c.status === 'warn') warnN++;\n else fail++;\n }\n return { ok, warn: warnN, fail };\n}\n\n/**\n * S10 — host-artifacts presence check. Reports the ACTIVE host (read from\n * `project.config.host`) + verifies the host's primary emission paths exist on\n * disk. The expected set mirrors `buildHostArtifacts` in @noir-ai/create:\n *\n * - AGENTS.md for the hosts that emit it (agents-md/cursor/opencode — their\n * native context surface IS AGENTS.md). claude/gemini do NOT emit AGENTS.md\n * (their CLAUDE.md/GEMINI.md @-import the canonical .noir/ sources; a root\n * AGENTS.md would double-import them — fix-wave I1 removed that delta).\n * - The host's native context file when distinct from AGENTS.md\n * (claude → CLAUDE.md; gemini → GEMINI.md; agents-md/cursor/opencode →\n * none, AGENTS.md IS the context). Cursor's working-rules ride AGENTS.md's\n * `@.noir/rules/RULES.md` import — NO separate `.cursor/rules/noir-contract.mdc`\n * host-rules pointer (it was `noir-`-prefixed and the C3 cursor flat-skill\n * prune deleted it on every sync).\n * - The host's MCP config (.mcp.json / .gemini/mcp.json / .cursor/mcp.json /\n * opencode.json).\n *\n * Severity is `ok` when every expected path exists, `warn` when any are\n * missing (NEVER `fail` — a missing host artifact is restored by `noir sync`,\n * not a critical product failure). Mirrors the policy of the other\n * presence/projection checks (scaffold-version drift, RULES.md budget): warn,\n * surface the remediation, never block.\n *\n * Returns the structured payload for the `--json` envelope's `data.host`, or\n * `null` when the project isn't initialized (no resolved host).\n */\nfunction checkHostArtifacts(\n checks: CheckResult[],\n root: string,\n project: ProjectInfo | undefined,\n): { active: HostId; expected: string[]; missing: string[] } | null {\n if (!project) {\n checks.push({ name: 'host artifacts', status: 'warn', detail: 'skipped — not initialized' });\n return null;\n }\n const host = project.config.host;\n const adapter = resolveAdapter(host);\n const ectx = { root };\n\n // Build the expected repo-relative path list. Mirrors buildHostArtifacts in\n // @noir-ai/create so a missing row maps 1:1 to a manifest entry the user can\n // restore with `noir sync`. Kept inline (not imported) so doctor stays a\n // READ-ONLY health probe with zero write-side coupling.\n const expected: string[] = [];\n // AGENTS.md — only for hosts whose emitContext IS the AGENTS.md (I1: claude/\n // gemini skip it — their native context file already covers .noir/).\n const emitsAgentsMd = host === 'agents-md' || host === 'cursor' || host === 'opencode';\n if (emitsAgentsMd) {\n expected.push(relOr(adapter.agentsMdPath?.(ectx) ?? 'AGENTS.md', root));\n }\n // Host-native context file (when distinct from AGENTS.md).\n if (host === 'claude') expected.push('CLAUDE.md');\n else if (host === 'gemini') expected.push('GEMINI.md');\n // Cursor has NO separate host-rules .mdc — the prior `noir-contract.mdc`\n // pointer was REMOVED (it was `noir-`-prefixed, so the C3 cursor flat-skill\n // prune in emitSkillsToDir deleted it on every noir init/create/sync).\n // Cursor's rules ride AGENTS.md's `@.noir/rules/RULES.md` import instead.\n // Host MCP config (fallback .mcp.json for claude/agents-md).\n expected.push(relOr(adapter.mcpConfigPath?.(ectx) ?? '.mcp.json', root));\n\n const missing = expected.filter((p) => !existsSync(joinRoot(root, p)));\n const status: Severity = missing.length === 0 ? 'ok' : 'warn';\n const detail =\n missing.length === 0\n ? `host=${host} · all ${expected.length} primary artifacts present`\n : `host=${host} · missing ${missing.join(', ')} (run \\`noir sync\\` to restore)`;\n checks.push({ name: 'host artifacts', status, detail });\n return { active: host, expected, missing };\n}\n\n// ---------------------------------------------------------------------------\n// SP-A — nested-`.noir` detection (read-only).\n// ---------------------------------------------------------------------------\n\n/**\n * Detects the fingerprint of a `noir init`/`create` run from INSIDE `.noir/`\n * (now PREVENTED by `assertSafeRoot` in @noir-ai/create, but legacy/already-\n * nested projects still carry the damage): a nested `<root>/.noir/.noir/` store\n * and/or host artifacts emitted into `.noir/` as if it were a project root\n * (`.noir/CLAUDE.md`, `.noir/.mcp.json`, `.noir/.claude/`, and the ignore files\n * `.noir/.gitignore` / `.dockerignore` / `.npmignore` / `.prettierignore`).\n * Read-only `warn` —\n * doctor never mutates; remediation is manual removal (a future follow-up\n * slice can automate it). Never `fail`: a nested store wastes space + confuses\n * tooling but does not break the outer project.\n */\nexport function checkNestedNoir(\n checks: CheckResult[],\n root: string,\n): { detected: boolean; paths: string[] } {\n const candidates = [\n '.noir/.noir',\n '.noir/CLAUDE.md',\n '.noir/.mcp.json',\n '.noir/.claude',\n '.noir/.gitignore',\n '.noir/.dockerignore',\n '.noir/.npmignore',\n '.noir/.prettierignore',\n ];\n const found = candidates.filter((rel) => existsSync(join(root, rel)));\n const detected = found.length > 0;\n checks.push({\n name: 'nested .noir',\n status: detected ? 'warn' : 'ok',\n detail: detected\n ? `nested Noir artifacts inside .noir/ (${found.join(', ')}) — likely from running \\`noir init\\` inside .noir/. Remove them; the real project is at ${root}.`\n : 'no nested .noir/ artifacts',\n });\n return { detected, paths: found };\n}\n\n// ---------------------------------------------------------------------------\n// SP-C deferred — semantic duplicate detection (`--dedup`; loads the embedder).\n// ---------------------------------------------------------------------------\n\n/** Local embedder shape (@noir-ai/context's `EmbedFn`). */\ntype EmbedLike = (text: string) => Promise<Float32Array>;\n\n/**\n * Collect dedup candidates: the host context files that exist at the root\n * (CLAUDE.md / AGENTS.md / GEMINI.md — the hand-mirrored-overlap case) plus\n * `.noir/rules/RULES.md`. `.noir/NOIR.md` is EXCLUDED because host context\n * files `@import` it by design (their similarity is intentional, not a dup).\n */\nexport function collectDedupCandidates(root: string): { path: string; text: string }[] {\n const rels = ['CLAUDE.md', 'AGENTS.md', 'GEMINI.md', '.noir/rules/RULES.md'];\n const out: { path: string; text: string }[] = [];\n for (const rel of rels) {\n const abs = join(root, rel);\n if (!existsSync(abs)) continue;\n let text: string;\n try {\n text = readFileSync(abs, 'utf8');\n } catch {\n continue;\n }\n if (text.trim().length === 0) continue;\n out.push({ path: rel, text });\n }\n return out;\n}\n\n/**\n * `noir doctor --dedup`: embed the host-context + RULES.md candidates and\n * report near-duplicate pairs (cosine ≥ 0.90). The ONLY mechanism that catches\n * cross-file SEMANTIC overlap (e.g. a hand-mirrored CLAUDE.md ≈ AGENTS.md) —\n * exact content-hash cannot. Opt-in so a default `noir doctor` never pays the\n * embedder-load cost; degrades to a `warn` skip when the embedder is\n * unavailable (kind=none / native layer missing). `opts.embed` is a testability\n * seam — tests inject a deterministic fake; production omits it and the local\n * embedder is lazy-loaded via `@noir-ai/context`.\n */\nexport async function checkSemanticDupDoctor(\n checks: CheckResult[],\n root: string,\n project: ProjectInfo | undefined,\n opts: { embed?: EmbedLike } = {},\n): Promise<void> {\n if (!project) {\n checks.push({ name: 'semantic dup', status: 'warn', detail: 'skipped — not initialized' });\n return;\n }\n const candidates = collectDedupCandidates(root);\n if (candidates.length < 2) {\n checks.push({\n name: 'semantic dup',\n status: 'ok',\n detail: `${candidates.length} candidate file(s); nothing to compare`,\n });\n return;\n }\n const ctx = await import('@noir-ai/context');\n let embed: EmbedLike | undefined = opts.embed;\n if (!embed) {\n const cfg = ctx.resolveEmbedderConfig(project.config.context);\n if (cfg.kind === 'none') {\n checks.push({\n name: 'semantic dup',\n status: 'warn',\n detail: 'embedder kind=none — set context.embedder.kind=local to enable semantic dedup',\n });\n return;\n }\n try {\n embed = ctx.createEmbedFn(cfg).embed as EmbedLike;\n } catch (e) {\n checks.push({\n name: 'semantic dup',\n status: 'warn',\n detail: `embedder unavailable — skipped (${msg(e)})`,\n });\n return;\n }\n }\n if (!embed) return;\n const pairs = await ctx.findSemanticDuplicates(candidates, embed, ctx.DEFAULT_DUP_THRESHOLD);\n checks.push({\n name: 'semantic dup',\n status: pairs.length > 0 ? 'warn' : 'ok',\n detail:\n pairs.length === 0\n ? `no near-duplicates across ${candidates.length} file(s)`\n : `${pairs.length} near-duplicate pair${pairs.length === 1 ? '' : 's'}: ${pairs\n .map((p) => `${p.a}≈${p.b} (${p.similarity.toFixed(2)})`)\n .join('; ')}`,\n });\n}\n\n// ---------------------------------------------------------------------------\n// S11 — publish-readiness check (advisory, repo-developer-facing).\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve the workspace `packages/` directory from the CLI's own location —\n * walk up from `import.meta.url` to the nearest `package.json` named\n * `@noir-ai/cli`, then return its PARENT dir (the `packages/` root) IF that\n * dir's parent carries the monorepo marker (`pnpm-workspace.yaml`). Returns\n * `null` when not running from a monorepo checkout (a global `npm install -g`\n * has no `packages/*` workspace to validate → the publish check skips).\n *\n * The walk is robust across layouts: source (`packages/cli/src/commands/`),\n * built (`packages/cli/dist/`), and bundled-chunk (`packages/cli/dist/`) all\n * walk up to `packages/cli/package.json`. In a global install the same walk\n * lands on `node_modules/@noir-ai/cli/package.json`, whose parent\n * (`node_modules/@noir-ai/`) has NO `pnpm-workspace.yaml` parent → null.\n */\nfunction resolveWorkspacePackagesDir(): string | null {\n let here = dirname(fileURLToPath(import.meta.url));\n // Bound the walk so a pathological layout never loops the filesystem.\n for (let i = 0; i < 8; i++) {\n const pkgPath = join(here, 'package.json');\n if (existsSync(pkgPath)) {\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf8')) as { name?: string };\n if (pkg.name === '@noir-ai/cli') {\n // `here` is the cli package dir; `dirname(here)` is `packages/`.\n const packagesDir = dirname(here);\n // Monorepo gate: the repo root (`dirname(packagesDir)`) carries\n // `pnpm-workspace.yaml`. A global install fails this gate.\n if (existsSync(join(dirname(packagesDir), 'pnpm-workspace.yaml'))) {\n return packagesDir;\n }\n return null;\n }\n } catch {\n // Malformed package.json — keep walking.\n }\n }\n const parent = dirname(here);\n if (parent === here) break; // filesystem root\n here = parent;\n }\n return null;\n}\n\n/**\n * Permissive semver-ish regex for the advisory check. Accepts release and\n * pre-release/build forms (`1.0.0`, `1.1.0-beta.1`, `1.2.0+build.4`). Strict\n * enough to catch the obvious foot-guns (a git SHA, a literal \"latest\", a\n * missing patch) without pulling in the `semver` package for a warn-level\n * check. `npm publish` itself enforces rigor at pack time.\n */\nconst SEMVER_ISH = /^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?(?:\\+[0-9A-Za-z.-]+)?$/;\n\n/** Best-effort `npm pack --dry-run` on the cli package — read-only (it does\n * NOT write the tarball). Returns `{ fileCount, distIncluded }` parsed from\n * npm's notice output, or `{ error }` when npm is unavailable / the pack\n * fails. Gated on npm being on PATH (the spec's expensive-but-optional leg):\n * we probe `npm --version` first and skip-with-note if it isn't resolvable. */\nfunction npmPackDryRun(\n cliPkgDir: string,\n): { fileCount: number | null; distIncluded: boolean | null } | { error: string } {\n // Probe npm availability first (cheap). shell:true so Windows finds npm.cmd.\n const probe = spawnSync('npm', ['--version'], { encoding: 'utf8', shell: true });\n if (probe.status !== 0 || probe.error) {\n return { error: probe.error ? probe.error.message : 'npm not on PATH' };\n }\n // `npm pack --dry-run` lists the tarball contents without writing the file.\n // It IS read-only (npm's own docs: \"--dry-run ... does not write anything\").\n const res = spawnSync('npm', ['pack', '--dry-run'], {\n cwd: cliPkgDir,\n encoding: 'utf8',\n shell: true,\n });\n if (res.status !== 0 || res.error) {\n return { error: res.error ? res.error.message : `npm pack exited ${res.status ?? '?'}` };\n }\n const out = `${res.stdout ?? ''}\\n${res.stderr ?? ''}`;\n // `npm notice total files: 42` — the canonical summary line.\n const totalMatch = out.match(/total files:\\s*(\\d+)/i);\n const fileCount = totalMatch?.[1] ? Number.parseInt(totalMatch[1], 10) : null;\n // `dist/` appears in the tarball contents (`npm notice <size> dist/<file>`).\n const distIncluded = /\\bdist\\//.test(out);\n return { fileCount, distIncluded };\n}\n\n/**\n * S11 publish-readiness check. For every workspace `package.json` under\n * `packagesDir`, validate publishability:\n * - `name` starts with `@noir-ai/`\n * - `version` matches {@link SEMVER_ISH}\n * - `files` is a non-empty array\n * - the cli package has a `bin` field\n *\n * Optionally runs `npm pack --dry-run` on the cli package (best-effort, gated\n * on npm being available) to report the file count + confirm `dist/` ships.\n *\n * Severity is ALWAYS `ok` or `warn` — NEVER `fail`: a missing/odd package.json\n * field does not break the local install (this is an advisory nudge to repo\n * developers, not a project-facing health check). The check runs ALWAYS (it\n * produces a row in every doctor report) but returns `null` from\n * `data.publish` when not running from a monorepo (`packagesDir === null`).\n */\nexport function checkPublish(\n checks: CheckResult[],\n packagesDir: string | null,\n opts: { skipNpmPack?: boolean } = {},\n): { checked: number; issues: string[] } | null {\n if (packagesDir === null) {\n checks.push({\n name: 'publish',\n status: 'ok',\n detail: 'skipped — not a monorepo checkout (no packages/* workspace)',\n });\n return null;\n }\n // Discover workspace package.json files (depth-1 dirs only — no glob dep).\n let entries: string[] = [];\n try {\n entries = readdirSync(packagesDir, { withFileTypes: true })\n .filter((d) => d.isDirectory())\n .map((d) => d.name);\n } catch (e) {\n checks.push({\n name: 'publish',\n status: 'warn',\n detail: `could not read ${packagesDir}: ${msg(e)}`,\n });\n return { checked: 0, issues: [`unreadable packages dir: ${msg(e)}`] };\n }\n\n const issues: string[] = [];\n let checked = 0;\n let cliDir: string | null = null;\n for (const name of entries) {\n const pkgPath = join(packagesDir, name, 'package.json');\n if (!existsSync(pkgPath)) continue;\n let pkg: Record<string, unknown>;\n try {\n pkg = JSON.parse(readFileSync(pkgPath, 'utf8')) as Record<string, unknown>;\n } catch (e) {\n issues.push(`${name}/package.json: unparseable (${msg(e)})`);\n checked++;\n continue;\n }\n checked++;\n const pkgName = typeof pkg.name === 'string' ? pkg.name : '';\n if (!pkgName.startsWith('@noir-ai/')) {\n issues.push(`${name}/package.json: name '${pkgName}' is not @noir-ai/*`);\n }\n const version = typeof pkg.version === 'string' ? pkg.version : '';\n if (!SEMVER_ISH.test(version)) {\n issues.push(`${name}/package.json: version '${version}' is not semver`);\n }\n if (!Array.isArray(pkg.files) || pkg.files.length === 0) {\n issues.push(`${name}/package.json: files missing or empty`);\n }\n if (pkgName === '@noir-ai/cli') {\n if (pkg.bin == null || (typeof pkg.bin === 'object' && Object.keys(pkg.bin).length === 0)) {\n issues.push(`${name}/package.json: bin missing (cli package must declare a bin)`);\n }\n cliDir = join(packagesDir, name);\n }\n }\n\n // Best-effort npm pack --dry-run on the cli package. Gated on npm being\n // available; a failure here is surfaced in the detail but does NOT add an\n // issue (it is environmental, not a package.json defect). `skipNpmPack` is a\n // testability seam — synthetic test fixtures have no real `dist/`, so the\n // dist-absent signal would otherwise pollute the package.json-validation\n // assertions. Production (`doctor()`) leaves it unset.\n let packNote = '';\n if (cliDir && opts.skipNpmPack !== true) {\n const pack = npmPackDryRun(cliDir);\n if ('error' in pack) {\n packNote = ` · npm pack skipped (${pack.error})`;\n } else {\n const count = pack.fileCount == null ? '?' : String(pack.fileCount);\n const dist = pack.distIncluded ? 'dist/ included' : 'dist/ NOT in tarball';\n packNote = ` · npm pack: ${count} files, ${dist}`;\n if (pack.distIncluded === false) {\n issues.push('cli npm pack --dry-run: dist/ absent from the tarball');\n }\n }\n }\n\n const status: Severity = issues.length > 0 ? 'warn' : 'ok';\n const detail =\n issues.length === 0\n ? `${checked}/${entries.length} packages publish-ready${packNote}`\n : `${issues.length} issue${issues.length === 1 ? '' : 's'} across ${checked} package${checked === 1 ? '' : 's'}${packNote}`;\n checks.push({ name: 'publish', status, detail });\n return { checked, issues };\n}\n\n/** Repo-relative POSIX form of `abs` under `root`. Defensive (N2): rejects\n * paths that escape `root` — mirrors `hostRel` in @noir-ai/create/manifest.ts.\n * A future adapter that returns a stray path fails loudly here instead of\n * producing a misleading \"missing\" row for a path doctor would never probe.\n * Relative literals (e.g. `'AGENTS.md'`, `'.mcp.json'`) pass through unchanged\n * AFTER the `..`-escape check so a buggy literal could not exfiltrate either. */\nfunction relOr(abs: string, root: string): string {\n const posix = abs.replace(/\\\\/g, '/');\n if (posix.startsWith('/')) {\n const rel = relative(root, abs).replace(/\\\\/g, '/');\n if (rel.length === 0 || rel.startsWith('..') || rel.startsWith('/')) {\n throw new Error(`doctor: host path '${abs}' is not under root '${root}'`);\n }\n return rel;\n }\n // Already-relative literal: still reject `..` segments (a `../etc/passwd`\n // literal from a buggy adapter must not silently pass through).\n if (posix.split('/').some((seg) => seg === '..')) {\n throw new Error(`doctor: host path '${abs}' escapes root '${root}'`);\n }\n return posix;\n}\n\n/** Join `root` with a repo-relative POSIX path for an existsSync probe. */\nfunction joinRoot(root: string, relPath: string): string {\n return `${root}/${relPath}`;\n}\n\nfunction severityBadge(s: Severity): string {\n // Doctor's vocabulary is ok/warn/fail; the badge palette is ok/warn/error/info.\n // `fail` is the CRITICAL state → red (`error`), so RED stays reserved for the\n // broken-host states. The TEXT label keeps doctor's own uppercase word so the\n // JSON envelope (`status: 'fail'`) and the human row agree on vocabulary.\n const state: BadgeState = s === 'fail' ? 'error' : s;\n return badge(state, s.toUpperCase());\n}\n\nfunction renderHuman(payload: DoctorPayload, opts: CliOptions): void {\n log(\n `noir doctor — ${payload.checks.length} check${payload.checks.length === 1 ? '' : 's'}`,\n opts,\n );\n table(\n payload.checks.map((c) => ({\n Check: c.name,\n Status: severityBadge(c.status),\n Detail: c.detail,\n })),\n ['Check', 'Status', 'Detail'],\n opts,\n );\n const { ok, warn: warnN, fail } = payload.summary;\n if (fail > 0) {\n err(\n `${fail} critical check${fail === 1 ? '' : 's'} failed (${warnN} warning${warnN === 1 ? '' : 's'}, ${ok} ok)`,\n opts,\n );\n } else if (warnN > 0) {\n warn(`all critical checks passed (${warnN} warning${warnN === 1 ? '' : 's'}, ${ok} ok)`, opts);\n } else {\n success(`all ${ok} check${ok === 1 ? '' : 's'} passed`, opts);\n }\n}\n\n/**\n * `noir doctor`: run all checks, render, and exit.\n *\n * Under `--json` writes `{ok:true, data: DoctorPayload}` to stdout (always —\n * the command produced a diagnosis). The exit code carries health: 0 when no\n * check failed, 1 when any CRITICAL (`fail`) check is unhealthy.\n */\nexport async function doctor(opts: DoctorOptions = {}): Promise<void> {\n const root = process.cwd();\n const checks: CheckResult[] = [];\n\n await checkRuntime(checks);\n const { project, result: configResult } = checkConfig(root);\n checks.push(configResult);\n await checkDaemon(checks);\n const { vecOk } = await checkNativeDeps(checks);\n await checkStore(checks, project, root);\n checkEmbedder(checks, project, vecOk);\n checkProvider(checks, project);\n const scaffold = checkScaffoldVersion(checks, root);\n const rules = checkRulesMdBudget(checks, root, project);\n const host = checkHostArtifacts(checks, root, project);\n checkNestedNoir(checks, root);\n if (opts.dedup === true) {\n await checkSemanticDupDoctor(checks, root, project);\n }\n const publish = checkPublish(checks, resolveWorkspacePackagesDir());\n\n // C1 — install-method check (advisory, cache-only, never fail).\n const installCheck = buildInstallCheck({\n method: detectActiveMethod(),\n version: readInstallRecord()?.version ?? null,\n latestKnown: latestVersionFromCache(readUpdateCache(), 'latest'),\n });\n checks.push(installCheck);\n\n const summary = summarize(checks);\n const payload: DoctorPayload = {\n noir: NOIR_VERSION,\n checks,\n summary,\n scaffold,\n rules,\n host,\n publish,\n install: {\n method: installCheck.method,\n installedVersion: installCheck.installedVersion,\n latestKnown: installCheck.latestKnown,\n },\n };\n\n if (opts.json === true) {\n process.stdout.write(`${JSON.stringify({ ok: true, data: payload })}\\n`);\n } else {\n renderHuman(payload, opts);\n }\n\n if (summary.fail > 0) {\n // Under --json the data envelope is already on stdout; throw with an empty\n // message so handleError sets exitCode=1 without a redundant stderr line.\n // Under human mode the summary line above already named the failures.\n throw new NoirCliError(\n EXIT.ERROR,\n opts.json === true ? '' : `noir doctor: ${summary.fail} critical check(s) failed`,\n );\n }\n}\n"],"mappings":"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","names":["readFileSync","join","c","join","readFileSync","c"]}