@outcomeeng/spx 0.5.3 → 0.5.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/README.md +17 -2
- package/dist/cli.js +2089 -1075
- package/dist/cli.js.map +1 -1
- package/package.json +5 -6
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/domains/audit/paths.ts","../src/domains/audit/reader.ts","../src/domains/audit/semantic.ts","../src/domains/audit/structural.ts","../src/domains/audit/verify.ts","../src/commands/audit/verify.ts","../src/interfaces/cli/audit.ts","../src/commands/claude/init.ts","../src/lib/claude/permissions/discovery.ts","../src/lib/claude/permissions/parser.ts","../src/lib/file-system/normalizePath.ts","../src/lib/claude/permissions/subsumption.ts","../src/lib/claude/permissions/merger.ts","../src/lib/claude/settings/backup.ts","../src/lib/claude/settings/reporter.ts","../src/lib/claude/settings/writer.ts","../src/commands/claude/settings/consolidate.ts","../src/interfaces/cli/claude.ts","../src/config/index.ts","../src/domains/agent-environment/config.ts","../src/config/primitives/path-filter.ts","../src/domains/audit/config.ts","../src/lib/spec-tree/config.ts","../src/lib/file-inclusion/adapters/eslint.ts","../src/lib/file-inclusion/adapters/knip.ts","../src/lib/file-inclusion/adapters/madge.ts","../src/lib/file-inclusion/adapters/markdownlint.ts","../src/lib/file-inclusion/adapters/pytest.ts","../src/lib/file-inclusion/adapters/tsc.ts","../src/lib/file-inclusion/adapters/vitest.ts","../src/lib/file-inclusion/adapters/index.ts","../src/lib/file-inclusion/ignore-source.ts","../src/lib/file-inclusion/predicates/artifact-directory.ts","../src/lib/file-inclusion/predicates/hidden-prefix.ts","../src/lib/file-inclusion/config.ts","../src/lib/precommit/config.ts","../src/testing/config.ts","../src/validation/literal/config.ts","../src/validation/config/descriptor.ts","../src/config/registry.ts","../src/config/descriptor-digest.ts","../src/commands/config/defaults.ts","../src/commands/config/show.ts","../src/commands/config/validate.ts","../src/domains/config/root.ts","../src/interfaces/cli/write-warning.ts","../src/interfaces/cli/config.ts","../src/commands/session/archive.ts","../src/domains/session/archive.ts","../src/domains/session/batch.ts","../src/domains/session/handoff-base-checklist.ts","../src/domains/session/errors.ts","../src/git/root.ts","../src/config/defaults.ts","../src/git/environment.ts","../src/commands/session/resolve-config.ts","../src/commands/session/delete.ts","../src/domains/session/delete.ts","../src/domains/session/show.ts","../src/domains/session/list.ts","../src/domains/session/timestamp.ts","../src/domains/session/types.ts","../src/commands/session/handoff.ts","../src/domains/session/create.ts","../src/domains/session/handoff-base.ts","../src/domains/session/parse-handoff-input.ts","../src/commands/session/list.ts","../src/commands/session/pickup.ts","../src/domains/session/pickup.ts","../src/commands/session/prune.ts","../src/domains/session/prune.ts","../src/commands/session/release.ts","../src/domains/session/release.ts","../src/commands/session/show.ts","../src/domains/session/help.ts","../src/interfaces/cli/session.ts","../src/lib/spec-tree/index.ts","../src/commands/spec/root.ts","../src/commands/spec/next.ts","../src/commands/testing/discovery.ts","../src/domains/testing/aggregation.ts","../src/domains/testing/grouping.ts","../src/commands/testing/dispatch.ts","../src/commands/testing/run-command.ts","../src/testing/run-state.ts","../src/domains/audit/run-state.ts","../src/commands/spec/node-outcome-resolver.ts","../src/lib/node-status/classify.ts","../src/lib/node-status/provider.ts","../src/lib/node-status/read.ts","../src/lib/node-status/update.ts","../src/commands/spec/status.ts","../src/testing/languages/python.ts","../src/testing/languages/typescript.ts","../src/testing/registry.ts","../src/lib/process-lifecycle/exit-codes.ts","../src/lib/process-lifecycle/handlers.ts","../src/lib/process-lifecycle/install.ts","../src/lib/process-lifecycle/registry.ts","../src/lib/process-lifecycle/runner.ts","../src/lib/process-lifecycle/managed-subprocess.ts","../src/validation/discovery/language-finder.ts","../src/interfaces/cli/testing-runner-deps.ts","../src/interfaces/cli/spec.ts","../src/interfaces/cli/testing.ts","../src/commands/validation/markdown.ts","../src/validation/config/path-filter.ts","../src/validation/steps/markdown.ts","../src/commands/validation/messages.ts","../src/validation/languages/markdown.ts","../node_modules/.pnpm/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/impl/scanner.js","../node_modules/.pnpm/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/impl/string-intern.js","../node_modules/.pnpm/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/impl/parser.js","../node_modules/.pnpm/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/main.js","../src/validation/config/scope.ts","../src/validation/discovery/tool-finder.ts","../src/validation/discovery/constants.ts","../src/validation/steps/circular.ts","../src/commands/validation/circular.ts","../src/validation/steps/knip.ts","../src/commands/validation/knip.ts","../src/validation/steps/eslint.ts","../src/validation/lint-policy.ts","../src/validation/lint-policy-constants.ts","../src/validation/types.ts","../src/validation/steps/subprocess-output.ts","../src/commands/validation/lint.ts","../src/validation/literal/index.ts","../src/lib/file-inclusion/predicates/ignore-source.ts","../src/lib/file-inclusion/layer-sequence.ts","../src/lib/file-inclusion/pipeline.ts","../src/validation/literal/detector.ts","../src/domains/spec/fixture-writer-methods.ts","../src/validation/literal/walker.ts","../src/commands/validation/literal.ts","../src/validation/steps/typescript.ts","../src/commands/validation/typescript.ts","../src/validation/languages/typescript.ts","../src/validation/registry.ts","../src/commands/validation/format.ts","../src/commands/validation/all.ts","../src/interfaces/cli/sanitize.ts","../src/validation/literal/allowlist-existing.ts","../src/interfaces/cli/validation.ts","../src/interfaces/cli/registry.ts"],"sourcesContent":["/**\n * CLI entry point for spx\n */\nimport { Command } from \"commander\";\nimport { createRequire } from \"node:module\";\n\nimport { CLI_DOMAINS } from \"./interfaces/cli/registry\";\nimport { installLifecycle } from \"./lib/process-lifecycle\";\n\ninstallLifecycle();\n\nconst require = createRequire(import.meta.url);\nconst { version } = require(\"../package.json\") as { version: string };\n\nconst program = new Command();\n\nprogram\n .name(\"spx\")\n .description(\"Fast, deterministic CLI tool for spec workflow management\")\n .version(version);\n\nfor (const domain of CLI_DOMAINS) {\n domain.register(program);\n}\n\nprogram.parse();\n","import { existsSync } from \"node:fs\";\nimport { relative, resolve } from \"node:path\";\nimport { AuditVerdict } from \"./reader\";\n\nexport const AUDIT_PATH_DEFECT = {\n ESCAPES_ROOT: \"path escapes product directory\",\n MISSING_FILE: \"missing file\",\n} as const;\n\nexport function validatePaths(verdict: AuditVerdict, productDir: string): readonly string[] {\n const defects: string[] = [];\n const root = resolve(productDir);\n\n for (const gate of verdict.gates) {\n for (const finding of gate.findings) {\n checkPath(finding.spec_file, root, defects);\n checkPath(finding.test_file, root, defects);\n }\n }\n\n return defects;\n}\n\nfunction checkPath(filePath: string | undefined, root: string, defects: string[]): void {\n if (!filePath) return;\n\n const rel = relative(root, resolve(root, filePath));\n if (rel.startsWith(\"..\")) {\n defects.push(`${AUDIT_PATH_DEFECT.ESCAPES_ROOT}: ${filePath}`);\n return;\n }\n\n if (!existsSync(resolve(root, filePath))) {\n defects.push(`${AUDIT_PATH_DEFECT.MISSING_FILE}: ${filePath}`);\n }\n}\n","/**\n * Audit verdict reader — parses an audit verdict XML file from disk into a\n * typed in-memory representation.\n *\n * All downstream verify stages (structural, semantic, paths) import\n * AuditVerdict from this module and operate on the parsed representation\n * rather than raw XML.\n *\n * @module audit/reader\n */\n\nimport { readFile } from \"node:fs/promises\";\n\nimport { XMLParser, XMLValidator } from \"fast-xml-parser\";\n\nexport interface AuditFinding {\n readonly spec_file?: string;\n readonly test_file?: string;\n}\n\nexport const AUDIT_VERDICT_VALUE = {\n APPROVED: \"APPROVED\",\n REJECT: \"REJECT\",\n} as const;\n\nexport type AuditVerdictValue = (typeof AUDIT_VERDICT_VALUE)[keyof typeof AUDIT_VERDICT_VALUE];\n\nexport const AUDIT_GATE_STATUS = {\n FAIL: \"FAIL\",\n PASS: \"PASS\",\n SKIPPED: \"SKIPPED\",\n} as const;\n\nexport type AuditGateStatus = (typeof AUDIT_GATE_STATUS)[keyof typeof AUDIT_GATE_STATUS];\n\nexport interface AuditGate {\n readonly name?: string;\n readonly status?: string;\n readonly skipped_reason?: string;\n readonly count?: string;\n readonly findings: readonly AuditFinding[];\n}\n\nexport interface AuditVerdictHeader {\n readonly spec_node?: string;\n readonly verdict?: string;\n readonly timestamp?: string;\n}\n\nexport interface AuditVerdict {\n readonly header?: AuditVerdictHeader;\n readonly gates: readonly AuditGate[];\n}\n\nexport const AUDIT_VERDICT_XML = {\n ROOT: \"audit_verdict\",\n HEADER: \"header\",\n SPEC_NODE: \"spec_node\",\n VERDICT: \"verdict\",\n TIMESTAMP: \"timestamp\",\n GATES: \"gates\",\n GATE: \"gate\",\n NAME: \"name\",\n STATUS: \"status\",\n SKIPPED_REASON: \"skipped_reason\",\n FINDINGS: \"findings\",\n FINDING: \"finding\",\n COUNT: \"count\",\n PARSED_COUNT: \"@_count\",\n SPEC_FILE: \"spec_file\",\n TEST_FILE: \"test_file\",\n} as const;\n\nconst ARRAY_TAGS = new Set<string>([AUDIT_VERDICT_XML.GATE, AUDIT_VERDICT_XML.FINDING]);\n\nconst PARSER_OPTIONS = {\n ignoreAttributes: false,\n attributeNamePrefix: \"@_\",\n parseTagValue: false,\n parseAttributeValue: false,\n isArray: (name: string) => ARRAY_TAGS.has(name),\n} as const;\n\n/**\n * Reads and parses an audit verdict XML file from disk.\n *\n * @throws {Error} When the file does not exist — message includes filePath.\n * @throws {Error} When the file is not well-formed XML — message includes filePath.\n */\nexport async function readVerdictFile(filePath: string): Promise<AuditVerdict> {\n let xml: string;\n try {\n xml = await readFile(filePath, \"utf-8\");\n } catch (cause) {\n throw new Error(`Failed to read verdict file: ${filePath}`, { cause });\n }\n\n const validation = XMLValidator.validate(xml);\n if (validation !== true) {\n throw new Error(\n `Malformed XML in verdict file: ${filePath}: ${validation.err.msg}`,\n );\n }\n\n const parser = new XMLParser(PARSER_OPTIONS);\n const parsed = parser.parse(xml) as Record<string, unknown>;\n\n return buildVerdict(parsed);\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction asString(value: unknown): string | undefined {\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction buildVerdict(parsed: Record<string, unknown>): AuditVerdict {\n const rootUnknown = parsed[AUDIT_VERDICT_XML.ROOT];\n if (!isObject(rootUnknown)) {\n return { gates: [] };\n }\n\n const headerUnknown = rootUnknown[AUDIT_VERDICT_XML.HEADER];\n const gatesUnknown = rootUnknown[AUDIT_VERDICT_XML.GATES];\n\n return {\n header: isObject(headerUnknown) ? buildHeader(headerUnknown) : undefined,\n gates: isObject(gatesUnknown) ? buildGates(gatesUnknown) : [],\n };\n}\n\nfunction buildHeader(raw: Record<string, unknown>): AuditVerdictHeader {\n return {\n spec_node: asString(raw[AUDIT_VERDICT_XML.SPEC_NODE]),\n verdict: asString(raw[AUDIT_VERDICT_XML.VERDICT]),\n timestamp: asString(raw[AUDIT_VERDICT_XML.TIMESTAMP]),\n };\n}\n\nfunction buildGates(raw: Record<string, unknown>): readonly AuditGate[] {\n const gatesUnknown = raw[AUDIT_VERDICT_XML.GATE];\n if (!Array.isArray(gatesUnknown)) return [];\n return gatesUnknown.filter(isObject).map(buildGate);\n}\n\nfunction buildGate(raw: Record<string, unknown>): AuditGate {\n const findingsUnknown = raw[AUDIT_VERDICT_XML.FINDINGS];\n return {\n name: asString(raw[AUDIT_VERDICT_XML.NAME]),\n status: asString(raw[AUDIT_VERDICT_XML.STATUS]),\n skipped_reason: asString(raw[AUDIT_VERDICT_XML.SKIPPED_REASON]),\n count: isObject(findingsUnknown) ? asString(findingsUnknown[AUDIT_VERDICT_XML.PARSED_COUNT]) : undefined,\n findings: isObject(findingsUnknown) ? buildFindings(findingsUnknown) : [],\n };\n}\n\nfunction buildFindings(raw: Record<string, unknown>): readonly AuditFinding[] {\n const findingsUnknown = raw[AUDIT_VERDICT_XML.FINDING];\n if (!Array.isArray(findingsUnknown)) return [];\n return findingsUnknown.filter(isObject).map(buildFinding);\n}\n\nfunction buildFinding(raw: Record<string, unknown>): AuditFinding {\n return {\n spec_file: asString(raw[AUDIT_VERDICT_XML.SPEC_FILE]),\n test_file: asString(raw[AUDIT_VERDICT_XML.TEST_FILE]),\n };\n}\n","import { AUDIT_GATE_STATUS, AUDIT_VERDICT_VALUE, AuditVerdict } from \"./reader\";\n\nexport function validateSemantics(verdict: AuditVerdict): readonly string[] {\n const defects: string[] = [];\n\n const hasFail = verdict.gates.some((g) => g.status === AUDIT_GATE_STATUS.FAIL);\n const hasSkipped = verdict.gates.some((g) => g.status === AUDIT_GATE_STATUS.SKIPPED);\n\n if (verdict.header?.verdict === AUDIT_VERDICT_VALUE.APPROVED && (hasFail || hasSkipped)) {\n defects.push(\"incoherent verdict: APPROVED but at least one gate is not PASS\");\n } else if (verdict.header?.verdict === AUDIT_VERDICT_VALUE.REJECT && !hasFail && !hasSkipped) {\n defects.push(\"incoherent verdict: REJECT but all gates are PASS\");\n }\n\n for (const gate of verdict.gates) {\n const label = gate.name ? `gate \"${gate.name}\"` : \"gate\";\n\n if (gate.status === AUDIT_GATE_STATUS.FAIL && gate.findings.length === 0) {\n defects.push(`failed gate has no findings: ${label}`);\n }\n\n if (gate.status === AUDIT_GATE_STATUS.SKIPPED && !gate.skipped_reason) {\n defects.push(`skipped gate missing reason: ${label}`);\n }\n }\n\n return defects;\n}\n","import { AUDIT_GATE_STATUS, AUDIT_VERDICT_VALUE, AuditVerdict } from \"./reader\";\n\nconst VALID_VERDICTS = new Set<string>(Object.values(AUDIT_VERDICT_VALUE));\nconst VALID_GATE_STATUSES = new Set<string>(Object.values(AUDIT_GATE_STATUS));\n\nexport const STRUCTURAL_DEFECT_TEXT = {\n MISSING_REQUIRED_ELEMENT: \"missing required element\",\n INVALID_ENUM_VALUE: \"invalid enum value\",\n} as const;\n\nexport function validateStructure(verdict: AuditVerdict): readonly string[] {\n const defects: string[] = [];\n\n if (!verdict.header) {\n defects.push(`${STRUCTURAL_DEFECT_TEXT.MISSING_REQUIRED_ELEMENT}: <header>`);\n return defects;\n }\n\n if (!verdict.header.spec_node) {\n defects.push(`${STRUCTURAL_DEFECT_TEXT.MISSING_REQUIRED_ELEMENT}: <spec_node>`);\n }\n\n if (!verdict.header.verdict) {\n defects.push(`${STRUCTURAL_DEFECT_TEXT.MISSING_REQUIRED_ELEMENT}: <verdict> in <header>`);\n } else if (!VALID_VERDICTS.has(verdict.header.verdict)) {\n defects.push(\n `${STRUCTURAL_DEFECT_TEXT.INVALID_ENUM_VALUE}: verdict \"${verdict.header.verdict}\" is not one of APPROVED, REJECT`,\n );\n }\n\n if (!verdict.header.timestamp) {\n defects.push(`${STRUCTURAL_DEFECT_TEXT.MISSING_REQUIRED_ELEMENT}: <timestamp>`);\n }\n\n if (verdict.gates.length === 0) {\n defects.push(`${STRUCTURAL_DEFECT_TEXT.MISSING_REQUIRED_ELEMENT}: at least one <gate> in <gates>`);\n }\n\n for (const gate of verdict.gates) {\n const label = gate.name ? `gate \"${gate.name}\"` : \"gate\";\n\n if (gate.status !== undefined && !VALID_GATE_STATUSES.has(gate.status)) {\n defects.push(\n `${STRUCTURAL_DEFECT_TEXT.INVALID_ENUM_VALUE}: ${label} status \"${gate.status}\" is not one of PASS, FAIL, SKIPPED`,\n );\n }\n\n if (gate.count !== undefined) {\n const declared = parseInt(gate.count, 10);\n const actual = gate.findings.length;\n if (isNaN(declared) || declared !== actual) {\n defects.push(\n `count mismatch: ${label} declares count=\"${gate.count}\" but has ${actual} finding(s)`,\n );\n }\n }\n }\n\n return defects;\n}\n","import { validatePaths } from \"./paths\";\nimport { readVerdictFile } from \"./reader\";\nimport { validateSemantics } from \"./semantic\";\nimport { validateStructure } from \"./structural\";\n\nexport interface VerifyOutput {\n readonly lines: readonly string[];\n readonly exitCode: 0 | 1;\n readonly verdict?: string;\n}\n\nexport async function runVerifyPipeline(\n filePath: string,\n productDir: string,\n): Promise<VerifyOutput> {\n let verdict;\n try {\n verdict = await readVerdictFile(filePath);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return { lines: [`reader: ${message}`], exitCode: 1 };\n }\n\n const structuralDefects = validateStructure(verdict);\n if (structuralDefects.length > 0) {\n return { lines: structuralDefects.map((d) => `structural: ${d}`), exitCode: 1 };\n }\n\n const semanticDefects = validateSemantics(verdict);\n if (semanticDefects.length > 0) {\n return { lines: semanticDefects.map((d) => `semantic: ${d}`), exitCode: 1 };\n }\n\n const pathDefects = validatePaths(verdict, productDir);\n if (pathDefects.length > 0) {\n return { lines: pathDefects.map((d) => `paths: ${d}`), exitCode: 1 };\n }\n\n return { lines: [], exitCode: 0, verdict: verdict.header?.verdict };\n}\n","import { runVerifyPipeline } from \"@/domains/audit/verify\";\n\nexport async function runVerifyCommand(\n filePath: string,\n productDir: string,\n writeLine: (line: string) => void,\n): Promise<0 | 1> {\n const result = await runVerifyPipeline(filePath, productDir);\n if (result.exitCode === 0) {\n writeLine(result.verdict ?? \"\");\n } else {\n for (const line of result.lines) {\n writeLine(line);\n }\n }\n return result.exitCode;\n}\n","import type { Command } from \"commander\";\n\nimport { runVerifyCommand } from \"@/commands/audit/verify\";\nimport type { Domain } from \"@/domains/types\";\n\nexport const auditDomain: Domain = {\n name: \"audit\",\n description: \"Audit verdict verification\",\n register: (program: Command) => {\n const auditCmd = program.command(\"audit\").description(\"Audit verdict verification\");\n\n auditCmd\n .command(\"verify <file>\")\n .description(\"Verify an audit verdict XML file\")\n .action(async (file: string) => {\n const exitCode = await runVerifyCommand(file, process.cwd(), console.log);\n process.exit(exitCode);\n });\n },\n};\n","/**\n * Init command implementation\n *\n * Wrapper around `claude plugin marketplace` to install/update outcomeeng marketplace\n */\nimport { execa } from \"execa\";\n\n/**\n * Options for init command\n */\nexport interface InitOptions {\n /** Working directory (for testing) */\n cwd?: string;\n}\n\n/**\n * Execute claude init command\n *\n * Wraps the Claude CLI's `plugin marketplace` commands to manage\n * the outcomeeng marketplace installation.\n *\n * Behavior:\n * 1. Check if outcomeeng marketplace exists via `claude plugin marketplace list`\n * 2. If missing: shell `claude plugin marketplace add outcomeeng/plugins`\n * 3. If exists: shell `claude plugin marketplace update outcomeeng`\n * (the marketplace registers under the org name \"outcomeeng\", so the\n * update command stays the same even if the source repo is renamed\n * within the org)\n * 4. Parse output and return status message\n *\n * @param options - Command options\n * @returns Status message\n * @throws Error if claude CLI not available or commands fail\n *\n * @example\n * ```typescript\n * const output = await initCommand();\n * console.log(output);\n * // Output: \"✓ outcomeeng marketplace installed successfully\"\n * // or: \"✓ outcomeeng marketplace updated successfully\"\n * ```\n */\nexport async function initCommand(\n options: InitOptions = {},\n): Promise<string> {\n const cwd = options.cwd || process.cwd();\n\n try {\n // Step 1: Check if outcomeeng marketplace exists\n const { stdout: listOutput } = await execa(\n \"claude\",\n [\"plugin\", \"marketplace\", \"list\"],\n { cwd },\n );\n\n const exists = listOutput.includes(\"outcomeeng\");\n\n // Step 2: Add or update based on existence\n if (!exists) {\n // Add marketplace\n await execa(\n \"claude\",\n [\"plugin\", \"marketplace\", \"add\", \"outcomeeng/plugins\"],\n { cwd },\n );\n\n return \"✓ outcomeeng marketplace installed successfully\\n\\nRun 'claude plugin marketplace list' to view all marketplaces.\";\n } else {\n // Update marketplace\n await execa(\"claude\", [\"plugin\", \"marketplace\", \"update\", \"outcomeeng\"], {\n cwd,\n });\n\n return \"✓ outcomeeng marketplace updated successfully\\n\\nThe marketplace is now up to date.\";\n }\n } catch (error) {\n if (error instanceof Error) {\n // Check for specific error conditions\n if (\n error.message.includes(\"ENOENT\")\n || error.message.includes(\"command not found\")\n ) {\n throw new Error(\n \"Claude CLI not found. Please install Claude Code first.\\n\\nVisit: https://docs.anthropic.com/claude-code\",\n );\n }\n\n throw new Error(`Failed to initialize marketplace: ${error.message}`);\n }\n throw error;\n }\n}\n","/**\n * Discovery of Claude Code settings files across project directories\n */\nimport fs from \"fs/promises\";\nimport path from \"path\";\n\n/**\n * Recursively find all .claude/settings.local.json files under a root directory\n *\n * Walks the directory tree looking for files matching the pattern:\n * `**\\/.claude/settings.local.json`\n *\n * @param root - Root directory path to start searching from\n * @param visited - Set of visited paths to avoid symlink loops (internal use)\n * @returns Promise resolving to array of absolute paths to settings.local.json files\n * @throws Error if root directory doesn't exist or permission denied\n *\n * @example\n * ```typescript\n * const files = await findSettingsFiles(\"~/Code\");\n * // Returns: [\n * // \"/Users/user/Code/project-a/.claude/settings.local.json\",\n * // \"/Users/user/Code/project-b/.claude/settings.local.json\"\n * // ]\n * ```\n */\nexport async function findSettingsFiles(\n root: string,\n visited: Set<string> = new Set(),\n): Promise<string[]> {\n // Normalize and resolve path to handle symlinks and ~ expansion\n const normalizedRoot = path.resolve(root.replace(/^~/, process.env.HOME || \"~\"));\n\n // Check for symlink loops\n if (visited.has(normalizedRoot)) {\n return []; // Skip already visited directories\n }\n visited.add(normalizedRoot);\n\n try {\n // Stat the root to verify it exists and is a directory\n const stats = await fs.stat(normalizedRoot);\n if (!stats.isDirectory()) {\n throw new Error(`Path is not a directory: ${normalizedRoot}`);\n }\n\n // Read directory contents\n const entries = await fs.readdir(normalizedRoot, { withFileTypes: true });\n const results: string[] = [];\n\n for (const entry of entries) {\n const fullPath = path.join(normalizedRoot, entry.name);\n\n // If this is a .claude directory, check for settings.local.json\n if (entry.isDirectory() && entry.name === \".claude\") {\n const settingsPath = path.join(fullPath, \"settings.local.json\");\n if (await isValidSettingsFile(settingsPath)) {\n results.push(settingsPath);\n }\n }\n\n // Recursively search subdirectories (skip .claude to avoid double-checking)\n if (entry.isDirectory() && entry.name !== \".claude\") {\n const subFiles = await findSettingsFiles(fullPath, visited);\n results.push(...subFiles);\n }\n }\n\n return results;\n } catch (error) {\n // Re-throw with more context\n if (error instanceof Error) {\n if (error.message.includes(\"ENOENT\")) {\n throw new Error(`Directory not found: ${normalizedRoot}`);\n }\n if (error.message.includes(\"EACCES\")) {\n throw new Error(`Permission denied: ${normalizedRoot}`);\n }\n throw new Error(`Failed to search directory \"${normalizedRoot}\": ${error.message}`);\n }\n throw error;\n }\n}\n\n/**\n * Check if a given path is a valid settings.local.json file\n *\n * Validates that:\n * - File exists\n * - File is readable\n * - File has .json extension\n *\n * @param filePath - Absolute path to check\n * @returns Promise resolving to true if valid settings file, false otherwise\n *\n * @example\n * ```typescript\n * const isValid = await isValidSettingsFile(\"/path/to/.claude/settings.local.json\");\n * // Returns: true or false\n * ```\n */\nexport async function isValidSettingsFile(filePath: string): Promise<boolean> {\n try {\n // Check if file exists and is readable\n await fs.access(filePath, fs.constants.R_OK);\n\n // Check if it's actually a file (not a directory)\n const stats = await fs.stat(filePath);\n if (!stats.isFile()) {\n return false;\n }\n\n // Validate it has .json extension\n return path.extname(filePath) === \".json\";\n } catch {\n // File doesn't exist or isn't readable\n return false;\n }\n}\n","/**\n * Parser for Claude Code settings files and permissions\n */\nimport fs from \"fs/promises\";\nimport type { ClaudeSettings, Permission, PermissionCategory, Permissions } from \"./types\";\n\n/**\n * Parse a settings.json file and extract permissions\n *\n * Handles:\n * - Malformed JSON (returns null)\n * - Missing permissions object (returns empty permissions)\n * - Validates basic structure\n *\n * @param filePath - Absolute path to settings.json file\n * @returns Promise resolving to ClaudeSettings object, or null if malformed\n *\n * @example\n * ```typescript\n * const settings = await parseSettingsFile(\"/path/to/.claude/settings.json\");\n * if (settings) {\n * console.log(settings.permissions?.allow);\n * }\n * ```\n */\nexport async function parseSettingsFile(filePath: string): Promise<ClaudeSettings | null> {\n try {\n // Read file contents\n const content = await fs.readFile(filePath, \"utf-8\");\n\n // Parse JSON\n const parsed = JSON.parse(content);\n\n // Basic validation: should be an object\n if (typeof parsed !== \"object\" || parsed === null) {\n return null;\n }\n\n return parsed as ClaudeSettings;\n } catch {\n // JSON parse error or file read error\n return null;\n }\n}\n\n/**\n * Parse a permission string into structured components\n *\n * Permission format: \"Type(scope)\"\n * Examples:\n * - \"Bash(git:*)\" => { type: \"Bash\", scope: \"git:*\" }\n * - \"Read(file_path:/Users/user/Code/**)\" => { type: \"Read\", scope: \"file_path:/Users/user/Code/**\" }\n * - \"WebFetch(domain:github.com)\" => { type: \"WebFetch\", scope: \"domain:github.com\" }\n *\n * @param raw - Raw permission string\n * @param category - Permission category (allow/deny/ask)\n * @returns Parsed Permission object\n * @throws Error if permission string is malformed\n *\n * @example\n * ```typescript\n * const perm = parsePermission(\"Bash(git:*)\", \"allow\");\n * // Returns: { raw: \"Bash(git:*)\", type: \"Bash\", scope: \"git:*\", category: \"allow\" }\n * ```\n */\nexport function parsePermission(raw: string, category: PermissionCategory): Permission {\n // Match pattern: Type(scope)\n const match = raw.match(/^([^(]+)\\((.+)\\)$/);\n\n if (!match) {\n throw new Error(`Malformed permission string: \"${raw}\"`);\n }\n\n const [, type, scope] = match;\n\n return {\n raw,\n type: type.trim(),\n scope: scope.trim(),\n category,\n };\n}\n\n/**\n * Parse all permissions from a Permissions object\n *\n * Converts permission strings to structured Permission objects,\n * grouped by category (allow/deny/ask).\n *\n * @param permissions - Permissions object from settings.json\n * @returns Array of parsed Permission objects\n *\n * @example\n * ```typescript\n * const permissions = {\n * allow: [\"Bash(git:*)\", \"Bash(npm:*)\"],\n * deny: [\"Bash(rm -rf:*)\"]\n * };\n * const parsed = parseAllPermissions(permissions);\n * // Returns array of Permission objects with category set\n * ```\n */\nexport function parseAllPermissions(permissions: Permissions): Permission[] {\n const result: Permission[] = [];\n\n // Parse allow permissions\n if (permissions.allow) {\n for (const perm of permissions.allow) {\n try {\n result.push(parsePermission(perm, \"allow\"));\n } catch {\n // Skip malformed permissions\n continue;\n }\n }\n }\n\n // Parse deny permissions\n if (permissions.deny) {\n for (const perm of permissions.deny) {\n try {\n result.push(parsePermission(perm, \"deny\"));\n } catch {\n // Skip malformed permissions\n continue;\n }\n }\n }\n\n // Parse ask permissions\n if (permissions.ask) {\n for (const perm of permissions.ask) {\n try {\n result.push(parsePermission(perm, \"ask\"));\n } catch {\n // Skip malformed permissions\n continue;\n }\n }\n }\n\n return result;\n}\n\n/**\n * Read and parse multiple settings files\n *\n * Processes an array of file paths, reading and parsing each one.\n * Skips files that can't be read or parsed.\n *\n * @param filePaths - Array of absolute paths to settings files\n * @returns Promise resolving to array of Permissions objects (one per valid file)\n *\n * @example\n * ```typescript\n * const files = [\n * \"/Users/user/Code/project-a/.claude/settings.local.json\",\n * \"/Users/user/Code/project-b/.claude/settings.local.json\"\n * ];\n * const allPermissions = await parseAllSettings(files);\n * // Returns: [{ allow: [...], deny: [...] }, { allow: [...] }]\n * ```\n */\nexport async function parseAllSettings(filePaths: string[]): Promise<Permissions[]> {\n const results: Permissions[] = [];\n\n for (const filePath of filePaths) {\n const settings = await parseSettingsFile(filePath);\n if (settings?.permissions) {\n results.push(settings.permissions);\n }\n }\n\n return results;\n}\n","/**\n * Normalize path separators for cross-platform consistency\n *\n * Converts Windows backslashes to forward slashes for consistent path handling\n * across different operating systems.\n *\n * @param filepath - Path to normalize\n * @returns Normalized path with forward slashes\n *\n * @example\n * ```typescript\n * normalizePath(\"C:\\\\Users\\\\test\\\\specs\"); // Returns: \"C:/Users/test/specs\"\n * normalizePath(\"/home/user/specs\"); // Returns: \"/home/user/specs\"\n * ```\n */\n\nexport function normalizePath(filepath: string): string {\n // Replace all backslashes with forward slashes for cross-platform consistency\n return filepath.replace(/\\\\/g, \"/\");\n}\n","/**\n * Permission subsumption detection\n *\n * Detects when broader permissions subsume narrower ones:\n * - Bash(git:*) subsumes Bash(git log:*), Bash(git worktree:*), etc.\n * - Read(file_path:/Users/user/Code/**) subsumes Read(file_path:/Users/user/Code/project-a/**)\n */\nimport { normalizePath } from \"@/lib/file-system/normalizePath\";\nimport { parsePermission } from \"./parser\";\nimport type { Permission, PermissionCategory, ScopePattern, SubsumptionResult } from \"./types\";\n\n/**\n * Parse a scope string to extract pattern type and value\n *\n * Determines whether the scope is a command pattern (e.g., \"git:*\")\n * or a path pattern (e.g., \"file_path:/Users/user/Code/**\").\n *\n * @param scope - Scope string from permission\n * @returns ScopePattern with type and pattern\n *\n * @example\n * ```typescript\n * parseScopePattern(\"git:*\")\n * // Returns: { type: \"command\", pattern: \"git:*\" }\n *\n * parseScopePattern(\"file_path:/Users/user/Code/**\")\n * // Returns: { type: \"path\", pattern: \"/Users/user/Code/**\" }\n * ```\n */\nexport function parseScopePattern(scope: string): ScopePattern {\n // Check if scope contains path indicators\n if (\n scope.includes(\"file_path:\")\n || scope.includes(\"directory_path:\")\n || scope.includes(\"path:\")\n ) {\n // Extract path after the colon\n const colonIndex = scope.indexOf(\":\");\n const pattern = colonIndex >= 0 ? scope.substring(colonIndex + 1) : scope;\n return { type: \"path\", pattern };\n }\n\n // Default to command pattern (e.g., \"git:*\", \"npm:*\")\n return { type: \"command\", pattern: scope };\n}\n\n/**\n * Check if permission A subsumes permission B\n *\n * Subsumption rules:\n * 1. Same type required (Bash subsumes Bash, not Read)\n * 2. Identical scopes = not subsumption (exact match)\n * 3. Broader scope subsumes narrower scope:\n * - Command: \"git:*\" subsumes \"git log:*\", \"git worktree:*\"\n * - Path: \"/Users/user/Code/**\" subsumes \"/Users/user/Code/project-a/**\"\n *\n * @param broader - Permission that might subsume the other\n * @param narrower - Permission that might be subsumed\n * @returns true if broader subsumes narrower, false otherwise\n *\n * @example\n * ```typescript\n * subsumes(\n * parsePermission(\"Bash(git:*)\", \"allow\"),\n * parsePermission(\"Bash(git log:*)\", \"allow\")\n * )\n * // Returns: true\n *\n * subsumes(\n * parsePermission(\"Read(file_path:/Users/user/Code/**)\", \"allow\"),\n * parsePermission(\"Read(file_path:/Users/user/Code/project-a/**)\", \"allow\")\n * )\n * // Returns: true\n *\n * subsumes(\n * parsePermission(\"Bash(git:*)\", \"allow\"),\n * parsePermission(\"Read(file_path:/Users/user/Code/**)\", \"allow\")\n * )\n * // Returns: false (different types)\n * ```\n */\nexport function subsumes(broader: Permission, narrower: Permission): boolean {\n // 1. Type must match\n if (broader.type !== narrower.type) {\n return false;\n }\n\n // 2. Identical = not subsumption (this is just a duplicate)\n if (broader.scope === narrower.scope) {\n return false;\n }\n\n // 3. Parse scope patterns\n const broaderScope = parseScopePattern(broader.scope);\n const narrowerScope = parseScopePattern(narrower.scope);\n\n // 4. Handle command patterns (e.g., \"git:*\")\n if (broaderScope.type === \"command\" && narrowerScope.type === \"command\") {\n // Extract base command by removing :* suffix\n const broaderBase = broaderScope.pattern.replace(/:?\\*+$/, \"\");\n const narrowerFull = narrowerScope.pattern.replace(/:?\\*+$/, \"\");\n\n // Check if narrower starts with broader prefix\n // \"git:*\" subsumes \"git log:*\" if:\n // - narrowerFull starts with broaderBase\n // - narrowerFull is longer (more specific)\n if (narrowerFull.startsWith(broaderBase)) {\n // Additional specificity check: narrower must add more detail\n // e.g., \"git\" subsumes \"git log\", but not \"git\" subsumes \"git\"\n return narrowerFull.length > broaderBase.length;\n }\n }\n\n // 5. Handle path patterns (e.g., \"/Users/user/Code/**\")\n if (broaderScope.type === \"path\" && narrowerScope.type === \"path\") {\n // Normalize paths for comparison\n const broaderPath = normalizePath(broaderScope.pattern.replace(/\\/?\\*+$/, \"\"));\n const narrowerPath = normalizePath(narrowerScope.pattern.replace(/\\/?\\*+$/, \"\"));\n\n // Check if narrower is a sub-path of broader\n // \"/Users/user/Code\" subsumes \"/Users/user/Code/project-a\" if:\n // - narrowerPath starts with broaderPath + \"/\"\n return narrowerPath.startsWith(broaderPath + \"/\");\n }\n\n // 6. Mixed pattern types don't subsume each other\n return false;\n}\n\n/**\n * Find all subsumption relationships in a permission list\n *\n * Returns a map of broader permissions to the narrower permissions\n * they subsume. This allows identifying which permissions can be\n * removed from the list.\n *\n * @param permissions - Array of permissions to analyze\n * @returns Array of subsumption results\n *\n * @example\n * ```typescript\n * const permissions = [\n * parsePermission(\"Bash(git:*)\", \"allow\"),\n * parsePermission(\"Bash(git log:*)\", \"allow\"),\n * parsePermission(\"Bash(git worktree:*)\", \"allow\"),\n * parsePermission(\"Bash(npm:*)\", \"allow\"),\n * ];\n *\n * const results = detectSubsumptions(permissions);\n * // Returns: [\n * // {\n * // broader: { raw: \"Bash(git:*)\", ... },\n * // narrower: [\n * // { raw: \"Bash(git log:*)\", ... },\n * // { raw: \"Bash(git worktree:*)\", ... }\n * // ]\n * // }\n * // ]\n * ```\n */\nexport function detectSubsumptions(permissions: Permission[]): SubsumptionResult[] {\n const results: SubsumptionResult[] = [];\n const processedBroader = new Set<string>();\n\n for (let i = 0; i < permissions.length; i++) {\n const broader = permissions[i];\n\n // Skip if already processed as a broader permission\n if (processedBroader.has(broader.raw)) {\n continue;\n }\n\n const narrowerPerms: Permission[] = [];\n\n // Check all other permissions to see if this one subsumes them\n for (let j = 0; j < permissions.length; j++) {\n if (i === j) continue; // Skip comparing with self\n\n const narrower = permissions[j];\n\n if (subsumes(broader, narrower)) {\n narrowerPerms.push(narrower);\n }\n }\n\n // If this permission subsumes others, record it\n if (narrowerPerms.length > 0) {\n results.push({\n broader,\n narrower: narrowerPerms,\n });\n processedBroader.add(broader.raw);\n }\n }\n\n return results;\n}\n\n/**\n * Remove subsumed permissions from a list, keeping only the broadest ones\n *\n * This is the main function for consolidating permissions.\n * It finds all subsumption relationships and removes narrower\n * permissions, leaving only the broadest ones.\n *\n * @param permissionStrings - Array of raw permission strings\n * @param category - Permission category (for parsing)\n * @returns Array of permission strings with subsumed ones removed\n *\n * @example\n * ```typescript\n * const permissions = [\n * \"Bash(git:*)\",\n * \"Bash(git log:*)\",\n * \"Bash(git worktree:*)\",\n * \"Bash(npm:*)\",\n * ];\n *\n * const result = removeSubsumed(permissions, \"allow\");\n * // Returns: [\"Bash(git:*)\", \"Bash(npm:*)\"]\n * ```\n */\nexport function removeSubsumed(\n permissionStrings: string[],\n category: PermissionCategory,\n): string[] {\n // Parse all permission strings\n const permissions = permissionStrings\n .map((raw) => {\n try {\n return parsePermission(raw, category);\n } catch {\n // Keep malformed permissions as-is (don't filter them out)\n return null;\n }\n })\n .filter((p): p is Permission => p !== null);\n\n // Detect subsumptions\n const subsumptions = detectSubsumptions(permissions);\n\n // Build set of narrower permissions to remove\n const toRemove = new Set<string>();\n for (const result of subsumptions) {\n for (const narrower of result.narrower) {\n toRemove.add(narrower.raw);\n }\n }\n\n // Filter out subsumed permissions\n return permissionStrings.filter((perm) => !toRemove.has(perm));\n}\n","/**\n * Permission merging with subsumption and conflict resolution\n */\nimport { parsePermission } from \"./parser\";\nimport { removeSubsumed, subsumes } from \"./subsumption\";\nimport type { ConsolidationResult, Permissions, PermissionsAdded } from \"./types\";\n\n/**\n * Merge permissions from global settings and multiple local settings files\n *\n * Process:\n * 1. Combine all permissions by category (allow/deny/ask)\n * 2. Apply subsumption to remove narrower permissions\n * 3. Resolve conflicts (deny wins over allow)\n * 4. Deduplicate using Sets\n * 5. Sort alphabetically\n *\n * @param global - Global settings permissions (baseline)\n * @param local - Array of local settings permissions to merge in\n * @returns Merged permissions and consolidation statistics\n *\n * @example\n * ```typescript\n * const global = { allow: [\"Bash(ls:*)\"] };\n * const local = [\n * { allow: [\"Bash(git:*)\", \"Bash(git log:*)\"] },\n * { deny: [\"Bash(rm:*)\"] }\n * ];\n *\n * const { merged, result } = mergePermissions(global, local);\n * // merged.allow: [\"Bash(git:*)\", \"Bash(ls:*)\"] // git log:* removed by subsumption\n * // merged.deny: [\"Bash(rm:*)\"]\n * // result.subsumed: [\"Bash(git log:*)\"]\n * ```\n */\nexport function mergePermissions(\n global: Permissions,\n local: Permissions[],\n): { merged: Permissions; result: ConsolidationResult } {\n // Track original global permissions for computing added\n const originalGlobal = {\n allow: new Set(global.allow || []),\n deny: new Set(global.deny || []),\n ask: new Set(global.ask || []),\n };\n\n // Step 1: Combine all permissions by category\n const combined: Permissions = {\n allow: [...(global.allow || [])],\n deny: [...(global.deny || [])],\n ask: [...(global.ask || [])],\n };\n\n let filesProcessed = 0;\n let filesSkipped = 0;\n\n for (const localPerms of local) {\n let hasPerms = false;\n\n if (localPerms.allow && localPerms.allow.length > 0) {\n combined.allow?.push(...localPerms.allow);\n hasPerms = true;\n }\n if (localPerms.deny && localPerms.deny.length > 0) {\n combined.deny?.push(...localPerms.deny);\n hasPerms = true;\n }\n if (localPerms.ask && localPerms.ask.length > 0) {\n combined.ask?.push(...localPerms.ask);\n hasPerms = true;\n }\n\n if (hasPerms) {\n filesProcessed++;\n } else {\n filesSkipped++;\n }\n }\n\n // Step 2: Apply subsumption to each category\n const allSubsumed: string[] = [];\n\n const afterSubsumption: Permissions = {};\n\n if (combined.allow && combined.allow.length > 0) {\n const before = new Set(combined.allow);\n combined.allow = removeSubsumed(combined.allow, \"allow\");\n const after = new Set(combined.allow);\n\n // Track what was removed\n for (const perm of before) {\n if (!after.has(perm)) {\n allSubsumed.push(perm);\n }\n }\n }\n\n if (combined.deny && combined.deny.length > 0) {\n const before = new Set(combined.deny);\n combined.deny = removeSubsumed(combined.deny, \"deny\");\n const after = new Set(combined.deny);\n\n // Track what was removed\n for (const perm of before) {\n if (!after.has(perm)) {\n allSubsumed.push(perm);\n }\n }\n }\n\n if (combined.ask && combined.ask.length > 0) {\n const before = new Set(combined.ask);\n combined.ask = removeSubsumed(combined.ask, \"ask\");\n const after = new Set(combined.ask);\n\n // Track what was removed\n for (const perm of before) {\n if (!after.has(perm)) {\n allSubsumed.push(perm);\n }\n }\n }\n\n afterSubsumption.allow = combined.allow;\n afterSubsumption.deny = combined.deny;\n afterSubsumption.ask = combined.ask;\n\n // Step 3: Resolve conflicts (deny wins over allow)\n const {\n resolved,\n conflictCount,\n subsumed: conflictSubsumed,\n } = resolveConflicts(afterSubsumption);\n\n // Combine subsumptions from step 2 and step 3\n const subsumed = [...allSubsumed, ...conflictSubsumed];\n\n // Step 4: Deduplicate using Sets and sort\n const merged: Permissions = {};\n\n if (resolved.allow && resolved.allow.length > 0) {\n merged.allow = Array.from(new Set(resolved.allow)).sort();\n }\n\n if (resolved.deny && resolved.deny.length > 0) {\n merged.deny = Array.from(new Set(resolved.deny)).sort();\n }\n\n if (resolved.ask && resolved.ask.length > 0) {\n merged.ask = Array.from(new Set(resolved.ask)).sort();\n }\n\n // Step 5: Compute what was added\n const added: PermissionsAdded = {\n allow: [],\n deny: [],\n ask: [],\n };\n\n for (const perm of merged.allow || []) {\n if (!originalGlobal.allow.has(perm)) {\n added.allow.push(perm);\n }\n }\n\n for (const perm of merged.deny || []) {\n if (!originalGlobal.deny.has(perm)) {\n added.deny.push(perm);\n }\n }\n\n for (const perm of merged.ask || []) {\n if (!originalGlobal.ask.has(perm)) {\n added.ask.push(perm);\n }\n }\n\n // Build result\n const result: ConsolidationResult = {\n filesScanned: local.length,\n filesProcessed,\n filesSkipped,\n added,\n subsumed,\n conflictsResolved: conflictCount,\n };\n\n return { merged, result };\n}\n\n/**\n * Resolve conflicts between allow and deny permissions\n *\n * Rules:\n * - If exact match in both allow and deny: keep in deny, remove from allow\n * - If deny has broader permission that subsumes allow: remove from allow\n *\n * This implements a security-first approach: deny always wins.\n *\n * @param permissions - Permissions with potential conflicts\n * @returns Resolved permissions with conflicts removed, count of conflicts, and list of subsumed permissions\n *\n * @example\n * ```typescript\n * const permissions = {\n * allow: [\"Bash(git log:*)\", \"Bash(npm:*)\"],\n * deny: [\"Bash(git:*)\"]\n * };\n *\n * const { resolved, conflictCount } = resolveConflicts(permissions);\n * // resolved.allow: [\"Bash(npm:*)\"] // git log:* removed (subsumed by deny git:*)\n * // resolved.deny: [\"Bash(git:*)\"]\n * // conflictCount: 1\n * ```\n */\nexport function resolveConflicts(permissions: Permissions): {\n resolved: Permissions;\n conflictCount: number;\n subsumed: string[];\n} {\n const allow = permissions.allow || [];\n const deny = permissions.deny || [];\n const ask = permissions.ask || [];\n\n const denySet = new Set(deny);\n const subsumed: string[] = [];\n let conflictCount = 0;\n\n // Check each allow permission against deny permissions\n const allowToRemove = new Set<string>();\n\n for (const allowPerm of allow) {\n // Exact match: move to deny\n if (denySet.has(allowPerm)) {\n allowToRemove.add(allowPerm);\n conflictCount++;\n continue;\n }\n\n // Check if any deny permission subsumes this allow permission\n for (const denyPerm of deny) {\n try {\n const allowParsed = parsePermission(allowPerm, \"allow\");\n const denyParsed = parsePermission(denyPerm, \"deny\");\n\n if (subsumes(denyParsed, allowParsed)) {\n // Deny subsumes allow - remove from allow\n allowToRemove.add(allowPerm);\n subsumed.push(allowPerm);\n conflictCount++;\n break;\n }\n } catch {\n // Skip malformed permissions\n continue;\n }\n }\n }\n\n // Build resolved permissions\n const resolved: Permissions = {\n allow: allow.filter((p) => !allowToRemove.has(p)),\n deny,\n ask,\n };\n\n return { resolved, conflictCount, subsumed };\n}\n","/**\n * Backup management for Claude Code settings files\n */\nimport fs from \"fs/promises\";\n\n/**\n * Create a timestamped backup of a settings file\n *\n * Backup format: `<original-path>.backup.YYYY-MM-DD-HHmmss`\n *\n * Example: `settings.json.backup.2026-01-08-143022`\n *\n * @param settingsPath - Absolute path to settings file to back up\n * @returns Promise resolving to backup file path\n * @throws Error if source file doesn't exist or backup fails\n *\n * @example\n * ```typescript\n * const backupPath = await createBackup(\"/Users/shz/.claude/settings.json\");\n * // Returns: \"/Users/shz/.claude/settings.json.backup.2026-01-08-143022\"\n * ```\n */\nexport async function createBackup(settingsPath: string): Promise<string> {\n try {\n // Verify source file exists\n await fs.access(settingsPath, fs.constants.R_OK);\n\n // Generate timestamp: YYYY-MM-DD-HHmmss\n const now = new Date();\n const timestamp = [\n now.getFullYear(),\n String(now.getMonth() + 1).padStart(2, \"0\"),\n String(now.getDate()).padStart(2, \"0\"),\n ].join(\"-\") + \"-\" + [\n String(now.getHours()).padStart(2, \"0\"),\n String(now.getMinutes()).padStart(2, \"0\"),\n String(now.getSeconds()).padStart(2, \"0\"),\n ].join(\"\");\n\n // Build backup path\n const backupPath = `${settingsPath}.backup.${timestamp}`;\n\n // Copy file to backup location\n await fs.copyFile(settingsPath, backupPath);\n\n return backupPath;\n } catch (error) {\n if (error instanceof Error) {\n if (error.message.includes(\"ENOENT\")) {\n throw new Error(`Settings file not found: ${settingsPath}`);\n }\n if (error.message.includes(\"EACCES\")) {\n throw new Error(`Permission denied: ${settingsPath}`);\n }\n throw new Error(`Failed to create backup: ${error.message}`);\n }\n throw error;\n }\n}\n","/**\n * Formatting and reporting of consolidation results\n */\nimport type { ConsolidationResult } from \"../permissions/types\";\n\n/**\n * Format consolidation result as user-friendly text report\n *\n * Shows:\n * - Files scanned/processed/skipped\n * - Permissions added by category (allow/deny/ask)\n * - Conflicts resolved\n * - Subsumed permissions removed\n * - Backup path (if created)\n * - Instructions (if preview mode) or confirmation (if written)\n *\n * @param result - Consolidation result data\n * @param previewOnly - Whether this is preview-only mode (default behavior)\n * @param globalSettingsPath - Path to global settings file\n * @param outputFile - Optional output file path\n * @returns Formatted report string\n *\n * @example\n * ```typescript\n * const result = {\n * filesScanned: 12,\n * filesProcessed: 10,\n * filesSkipped: 2,\n * added: {\n * allow: [\"Bash(git:*)\", \"Bash(npm:*)\"],\n * deny: [\"Bash(rm:*)\"],\n * ask: []\n * },\n * subsumed: [\"Bash(git log:*)\", \"Bash(git worktree:*)\"],\n * conflictsResolved: 1,\n * backupPath: \"/Users/shz/.claude/settings.json.backup.2026-01-08-143022\"\n * };\n *\n * console.log(formatReport(result, true, \"/Users/shz/.claude/settings.json\"));\n * // Outputs formatted report with instructions\n * ```\n */\nexport function formatReport(\n result: ConsolidationResult,\n previewOnly: boolean,\n globalSettingsPath?: string,\n outputFile?: string,\n): string {\n const lines: string[] = [];\n\n // Header\n lines.push(\"Scanning for Claude Code settings files...\");\n lines.push(\"\");\n\n // Files summary\n lines.push(`Found ${result.filesScanned} settings files`);\n lines.push(` Processed: ${result.filesProcessed}`);\n if (result.filesSkipped > 0) {\n lines.push(` Skipped: ${result.filesSkipped} (no permissions)`);\n }\n lines.push(\"\");\n\n // Permissions added\n const totalAdded = result.added.allow.length\n + result.added.deny.length\n + result.added.ask.length;\n\n if (totalAdded > 0) {\n lines.push(`Permissions to add: ${totalAdded}`);\n\n if (result.added.allow.length > 0) {\n lines.push(\"\");\n lines.push(\" allow:\");\n for (const perm of result.added.allow) {\n lines.push(` + ${perm}`);\n }\n }\n\n if (result.added.deny.length > 0) {\n lines.push(\"\");\n lines.push(\" deny:\");\n for (const perm of result.added.deny) {\n lines.push(` + ${perm}`);\n }\n }\n\n if (result.added.ask.length > 0) {\n lines.push(\"\");\n lines.push(\" ask:\");\n for (const perm of result.added.ask) {\n lines.push(` + ${perm}`);\n }\n }\n } else {\n lines.push(\"No new permissions to add (all permissions already in global settings)\");\n }\n\n lines.push(\"\");\n\n // Subsumption results\n if (result.subsumed.length > 0) {\n lines.push(`Subsumed permissions removed: ${result.subsumed.length}`);\n lines.push(\" (narrower permissions replaced by broader ones)\");\n for (const perm of result.subsumed) {\n lines.push(` - ${perm}`);\n }\n lines.push(\"\");\n }\n\n // Conflicts\n if (result.conflictsResolved > 0) {\n lines.push(`Conflicts resolved: ${result.conflictsResolved}`);\n lines.push(\" (permissions moved from allow to deny)\");\n lines.push(\"\");\n }\n\n // Backup\n if (result.backupPath) {\n lines.push(`Backup created: ${result.backupPath}`);\n lines.push(\"\");\n }\n\n // Summary\n lines.push(\"Summary:\");\n lines.push(` Files scanned: ${result.filesScanned}`);\n lines.push(\n ` Permissions added: ${result.added.allow.length} allow, ${result.added.deny.length} deny, ${result.added.ask.length} ask`,\n );\n if (result.subsumed.length > 0) {\n lines.push(` Subsumed removed: ${result.subsumed.length}`);\n }\n if (result.conflictsResolved > 0) {\n lines.push(` Conflicts resolved: ${result.conflictsResolved}`);\n }\n\n // Final status message\n lines.push(\"\");\n if (previewOnly) {\n lines.push(\"ℹ️ Preview mode: No changes written\");\n lines.push(\"\");\n lines.push(\"To apply changes:\");\n lines.push(` • Modify global settings: spx claude settings consolidate --write`);\n lines.push(` • Write to file: spx claude settings consolidate --output-file /path/to/file`);\n } else if (outputFile) {\n lines.push(`✓ Settings written to: ${result.outputPath || outputFile}`);\n lines.push(\"\");\n lines.push(\"To apply to your global settings:\");\n lines.push(` • Review the file, then copy to: ${globalSettingsPath || \"~/.claude/settings.json\"}`);\n lines.push(` • Or run: spx claude settings consolidate --write`);\n } else {\n lines.push(`✓ Global settings updated: ${globalSettingsPath || \"~/.claude/settings.json\"}`);\n }\n\n return lines.join(\"\\n\");\n}\n","/**\n * Atomic file writing for Claude Code settings\n */\nimport fs from \"fs/promises\";\nimport os from \"os\";\nimport path from \"path\";\nimport type { ClaudeSettings } from \"../permissions/types\";\n\n/**\n * Filesystem abstraction for dependency injection\n *\n * Enables testing error paths without mocking.\n */\nexport interface FileSystem {\n writeFile(path: string, content: string): Promise<void>;\n rename(oldPath: string, newPath: string): Promise<void>;\n unlink(path: string): Promise<void>;\n mkdir(path: string, options?: { recursive?: boolean }): Promise<void>;\n}\n\n/**\n * Production filesystem implementation\n */\nconst realFs: FileSystem = {\n writeFile: (path, content) => fs.writeFile(path, content, \"utf-8\"),\n rename: fs.rename,\n unlink: fs.unlink,\n mkdir: async (path, options) => {\n await fs.mkdir(path, options);\n },\n};\n\n/**\n * Atomically write settings to a file\n *\n * Uses temp file + rename pattern for atomicity:\n * 1. Write to temporary file\n * 2. Rename to target (atomic operation on most filesystems)\n *\n * Preserves JSON formatting with 2-space indentation.\n *\n * @param filePath - Absolute path to settings file\n * @param settings - Settings object to write\n * @param deps - Dependencies (for testing)\n * @throws Error if write fails\n *\n * @example\n * ```typescript\n * const settings = {\n * permissions: {\n * allow: [\"Bash(git:*)\", \"Bash(npm:*)\"]\n * }\n * };\n * await writeSettings(\"/Users/shz/.claude/settings.json\", settings);\n * ```\n */\nexport async function writeSettings(\n filePath: string,\n settings: ClaudeSettings,\n deps: { fs: FileSystem } = { fs: realFs },\n): Promise<void> {\n // Ensure directory exists\n const dir = path.dirname(filePath);\n await deps.fs.mkdir(dir, { recursive: true });\n\n // Generate temporary file path\n const tempPath = path.join(\n os.tmpdir(),\n `settings-${Date.now()}-${Math.random().toString(36).substring(7)}.json`,\n );\n\n try {\n // Format JSON with 2-space indentation and trailing newline\n const content = JSON.stringify(settings, null, 2) + \"\\n\";\n\n // Write to temp file\n await deps.fs.writeFile(tempPath, content);\n\n // Atomic rename\n await deps.fs.rename(tempPath, filePath);\n } catch (error) {\n // Cleanup temp file on failure\n try {\n await deps.fs.unlink(tempPath);\n } catch {\n // Ignore cleanup errors\n }\n\n // Re-throw original error\n if (error instanceof Error) {\n throw new Error(`Failed to write settings: ${error.message}`);\n }\n throw error;\n }\n}\n","/**\n * Consolidate command implementation\n *\n * Orchestrates the full consolidation pipeline:\n * 1. Discovery - Find all settings.local.json files\n * 2. Parsing - Extract permissions from each file\n * 3. Merging - Combine with subsumption and conflict resolution\n * 4. Backup - Create timestamped backup (if not dry-run)\n * 5. Writing - Atomically write merged settings (if not dry-run)\n * 6. Reporting - Format and return result summary\n */\nimport { findSettingsFiles } from \"@/lib/claude/permissions/discovery\";\nimport { mergePermissions } from \"@/lib/claude/permissions/merger\";\nimport { parseAllSettings, parseSettingsFile } from \"@/lib/claude/permissions/parser\";\nimport { createBackup } from \"@/lib/claude/settings/backup\";\nimport { formatReport } from \"@/lib/claude/settings/reporter\";\nimport { writeSettings } from \"@/lib/claude/settings/writer\";\nimport os from \"os\";\nimport path from \"path\";\n\n/**\n * Options for consolidate command\n */\nexport interface ConsolidateOptions {\n /** Root directory to scan for settings files (default: ~/Code) */\n root?: string;\n /** Write changes to global settings file (default: false = preview only) */\n write?: boolean;\n /** Write merged settings to specified file instead of global settings */\n outputFile?: string;\n /** Path to global settings file (for testing; default: ~/.claude/settings.json) */\n globalSettings?: string;\n}\n\n/**\n * Execute settings consolidate command\n *\n * Consolidates permissions from project-local settings files into\n * the global Claude Code settings file.\n *\n * Behavior:\n * - Discovers all `.claude/settings.local.json` files recursively\n * - Applies subsumption to remove narrower permissions\n * - Resolves conflicts (deny wins over allow)\n * - Deduplicates and sorts permissions\n * - Creates backup before modifications\n * - Supports dry-run mode for preview\n *\n * @param options - Command options\n * @returns Formatted report string\n * @throws Error if discovery, parsing, or writing fails\n *\n * @example\n * ```typescript\n * // Normal consolidation\n * const output = await consolidateCommand({ root: \"~/Code\" });\n * console.log(output);\n *\n * // Dry-run preview\n * const preview = await consolidateCommand({ root: \"~/Code\", dryRun: true });\n * console.log(preview);\n * ```\n */\nexport async function consolidateCommand(\n options: ConsolidateOptions = {},\n): Promise<string> {\n // Resolve paths\n const root = options.root\n ? path.resolve(options.root.replace(/^~/, os.homedir()))\n : path.join(os.homedir(), \"Code\");\n\n const globalSettingsPath = options.globalSettings\n || path.join(os.homedir(), \".claude\", \"settings.json\");\n\n const shouldWrite = options.write || false;\n const outputFile = options.outputFile;\n const previewOnly = !shouldWrite && !outputFile;\n\n // Step 1: Discovery - find all settings.local.json files\n const settingsFiles = await findSettingsFiles(root);\n\n if (settingsFiles.length === 0) {\n return `No settings files found in ${root}\\n\\nSearched for: **/.claude/settings.local.json`;\n }\n\n // Step 2: Parsing - extract permissions from each file\n const localPermissions = await parseAllSettings(settingsFiles);\n\n // Step 3: Read global settings\n let globalSettings = await parseSettingsFile(globalSettingsPath);\n\n // If global settings doesn't exist, create empty structure\n if (!globalSettings) {\n globalSettings = {\n permissions: {\n allow: [],\n deny: [],\n ask: [],\n },\n };\n }\n\n // Ensure permissions object exists\n if (!globalSettings.permissions) {\n globalSettings.permissions = {\n allow: [],\n deny: [],\n ask: [],\n };\n }\n\n // Step 4: Merge with subsumption and conflict resolution\n const { merged, result } = mergePermissions(\n globalSettings.permissions,\n localPermissions,\n );\n\n // Step 5: Backup (only when writing to global settings)\n if (shouldWrite) {\n try {\n result.backupPath = await createBackup(globalSettingsPath);\n } catch (error) {\n // If backup fails because file doesn't exist, that's okay (first time)\n if (error instanceof Error && !error.message.includes(\"not found\")) {\n throw error;\n }\n }\n }\n\n // Step 6: Write (if --write or --output-file specified)\n if (shouldWrite) {\n const updatedSettings = {\n ...globalSettings,\n permissions: merged,\n };\n await writeSettings(globalSettingsPath, updatedSettings);\n } else if (outputFile) {\n const updatedSettings = {\n ...globalSettings,\n permissions: merged,\n };\n const resolvedOutputPath = path.resolve(outputFile.replace(/^~/, os.homedir()));\n await writeSettings(resolvedOutputPath, updatedSettings);\n result.outputPath = resolvedOutputPath;\n }\n\n // Step 7: Report\n return formatReport(result, previewOnly, globalSettingsPath, outputFile);\n}\n","/**\n * Claude domain - Manage Claude Code settings and plugins\n */\nimport { initCommand } from \"@/commands/claude/init\";\nimport { consolidateCommand } from \"@/commands/claude/settings/consolidate\";\nimport type { Domain } from \"@/domains/types\";\nimport type { Command } from \"commander\";\n\n/**\n * Register claude domain commands\n *\n * @param claudeCmd - Commander.js claude domain command\n */\nfunction registerClaudeCommands(claudeCmd: Command): void {\n // init command\n claudeCmd\n .command(\"init\")\n .description(\"Initialize or update outcomeeng marketplace plugin\")\n .action(async () => {\n try {\n const output = await initCommand({ cwd: process.cwd() });\n console.log(output);\n } catch (error) {\n console.error(\n \"Error:\",\n error instanceof Error ? error.message : String(error),\n );\n process.exit(1);\n }\n });\n\n // settings subcommand group\n const settingsCmd = claudeCmd\n .command(\"settings\")\n .description(\"Manage Claude Code settings\");\n\n // settings consolidate command\n settingsCmd\n .command(\"consolidate\")\n .description(\n \"Consolidate permissions from project-specific settings into global settings\",\n )\n .option(\"--write\", \"Write changes to global settings file (default: preview only)\")\n .option(\n \"--output-file <path>\",\n \"Write merged settings to specified file instead of global settings\",\n )\n .option(\n \"--root <path>\",\n \"Root directory to scan for settings files (default: ~/Code)\",\n )\n .option(\n \"--global-settings <path>\",\n \"Path to global settings file (default: ~/.claude/settings.json)\",\n )\n .action(\n async (options: {\n write?: boolean;\n outputFile?: string;\n root?: string;\n globalSettings?: string;\n }) => {\n try {\n // Validate mutually exclusive options\n if (options.write && options.outputFile) {\n console.error(\n \"Error: --write and --output-file are mutually exclusive\\n\"\n + \"Use --write to modify global settings, or --output-file to write to a different location\",\n );\n process.exit(1);\n }\n\n const output = await consolidateCommand({\n write: options.write,\n outputFile: options.outputFile,\n root: options.root,\n globalSettings: options.globalSettings,\n });\n console.log(output);\n } catch (error) {\n console.error(\n \"Error:\",\n error instanceof Error ? error.message : String(error),\n );\n process.exit(1);\n }\n },\n );\n}\n\n/**\n * Claude domain - Manage Claude Code settings and plugins\n */\nexport const claudeDomain: Domain = {\n name: \"claude\",\n description: \"Manage Claude Code settings and plugins\",\n register: (program: Command) => {\n const claudeCmd = program\n .command(\"claude\")\n .description(\"Manage Claude Code settings and plugins\");\n\n registerClaudeCommands(claudeCmd);\n },\n};\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { parse as parseToml, stringify as stringifyToml } from \"smol-toml\";\nimport { parse as parseYaml, parseDocument as parseYamlDocument, stringify as stringifyYaml } from \"yaml\";\n\nimport { productionRegistry } from \"./registry\";\nimport type { Config, ConfigDescriptor, Result } from \"./types\";\n\nexport const CONFIG_FILE_FORMAT = {\n JSON: \"json\",\n YAML: \"yaml\",\n TOML: \"toml\",\n} as const;\n\nexport type ConfigFileFormat = (typeof CONFIG_FILE_FORMAT)[keyof typeof CONFIG_FILE_FORMAT];\n\nexport const CONFIG_FILE_DEFINITIONS = {\n [CONFIG_FILE_FORMAT.JSON]: {\n format: CONFIG_FILE_FORMAT.JSON,\n filename: \"spx.config.json\",\n },\n [CONFIG_FILE_FORMAT.YAML]: {\n format: CONFIG_FILE_FORMAT.YAML,\n filename: \"spx.config.yaml\",\n },\n [CONFIG_FILE_FORMAT.TOML]: {\n format: CONFIG_FILE_FORMAT.TOML,\n filename: \"spx.config.toml\",\n },\n} as const;\n\nexport const CONFIG_FILE_FORMAT_ORDER = [\n CONFIG_FILE_FORMAT.JSON,\n CONFIG_FILE_FORMAT.YAML,\n CONFIG_FILE_FORMAT.TOML,\n] as const;\n\nexport const DEFAULT_CONFIG_FILE_FORMAT = CONFIG_FILE_FORMAT.YAML;\n\nexport const CONFIG_FILENAMES = {\n json: CONFIG_FILE_DEFINITIONS[CONFIG_FILE_FORMAT.JSON].filename,\n yaml: CONFIG_FILE_DEFINITIONS[CONFIG_FILE_FORMAT.YAML].filename,\n toml: CONFIG_FILE_DEFINITIONS[CONFIG_FILE_FORMAT.TOML].filename,\n} as const;\n\nexport type ConfigFilename = (typeof CONFIG_FILENAMES)[keyof typeof CONFIG_FILENAMES];\n\nexport const DEFAULT_CONFIG_FILENAME = CONFIG_FILE_DEFINITIONS[DEFAULT_CONFIG_FILE_FORMAT].filename;\n\nexport type ConfigFile = {\n readonly filename: ConfigFilename;\n readonly format: ConfigFileFormat;\n readonly path: string;\n readonly raw: string;\n};\n\nexport type ConfigFileReadResult =\n | { readonly kind: \"ok\"; readonly file: ConfigFile }\n | { readonly kind: \"ambiguous\"; readonly detected: readonly ConfigFilename[] }\n | { readonly kind: \"absent\" };\n\nconst JSON_INDENT = 2;\n\nexport async function resolveConfig(\n productDir: string,\n descriptors: readonly ConfigDescriptor<unknown>[] = productionRegistry,\n): Promise<Result<Config>> {\n const detectedResult = await readProductConfigFile(productDir);\n if (!detectedResult.ok) return detectedResult;\n\n return resolveConfigFromReadResult(detectedResult.value, descriptors);\n}\n\nexport function resolveConfigFromReadResult(\n detected: ConfigFileReadResult,\n descriptors: readonly ConfigDescriptor<unknown>[] = productionRegistry,\n): Result<Config> {\n if (detected.kind === \"ambiguous\") {\n return { ok: false, error: formatConfigFileAmbiguityError(detected.detected) };\n }\n\n const sectionsResult = detected.kind === \"absent\"\n ? ({ ok: true as const, value: {} as Record<string, unknown> })\n : parseConfigFileSections(detected.file);\n if (!sectionsResult.ok) {\n return sectionsResult;\n }\n const sections = sectionsResult.value;\n\n const resolved: Record<string, unknown> = {};\n for (const descriptor of descriptors) {\n const sectionValue = sections[descriptor.section];\n if (sectionValue === undefined) {\n resolved[descriptor.section] = descriptor.defaults;\n continue;\n }\n const validated = descriptor.validate(sectionValue);\n if (!validated.ok) {\n return { ok: false, error: `${descriptor.section}: ${validated.error}` };\n }\n resolved[descriptor.section] = validated.value;\n }\n\n return { ok: true, value: resolved };\n}\n\nexport async function readProductConfigFile(productDir: string): Promise<Result<ConfigFileReadResult>> {\n const detected: ConfigFile[] = [];\n for (const format of CONFIG_FILE_FORMAT_ORDER) {\n const filename = CONFIG_FILE_DEFINITIONS[format].filename;\n const path = join(productDir, filename);\n let raw: string;\n try {\n raw = await readFile(path, \"utf8\");\n } catch (error) {\n if (isFileNotFound(error)) continue;\n return { ok: false, error: `failed to read ${filename}: ${toMessage(error)}` };\n }\n detected.push({ filename, format, path, raw });\n }\n if (detected.length === 0) return { ok: true, value: { kind: \"absent\" } };\n if (detected.length > 1) {\n return {\n ok: true,\n value: {\n kind: \"ambiguous\",\n detected: detected.map((file) => file.filename),\n },\n };\n }\n return { ok: true, value: { kind: \"ok\", file: detected[0] } };\n}\n\nexport function configFileForFormat(\n productDir: string,\n format: ConfigFileFormat = DEFAULT_CONFIG_FILE_FORMAT,\n raw = \"\",\n): ConfigFile {\n const filename = CONFIG_FILE_DEFINITIONS[format].filename;\n return {\n filename,\n format,\n path: join(productDir, filename),\n raw,\n };\n}\n\nexport function formatConfigFileAmbiguityError(detected: readonly ConfigFilename[]): string {\n return `multiple config files found: ${detected.join(\", \")}`;\n}\n\nexport function parseConfigFileSections(file: ConfigFile): Result<Record<string, unknown>> {\n if (file.raw.trim() === \"\") return { ok: true, value: {} };\n switch (file.format) {\n case CONFIG_FILE_FORMAT.JSON:\n return parseJsonSections(file.filename, file.raw);\n case CONFIG_FILE_FORMAT.YAML:\n return parseYamlSections(file.filename, file.raw);\n case CONFIG_FILE_FORMAT.TOML:\n return parseTomlSections(file.filename, file.raw);\n }\n}\n\nexport function serializeConfigFileSections(\n format: ConfigFileFormat,\n sections: Record<string, unknown>,\n): Result<string> {\n switch (format) {\n case CONFIG_FILE_FORMAT.JSON:\n return { ok: true, value: JSON.stringify(sections, null, JSON_INDENT) + \"\\n\" };\n case CONFIG_FILE_FORMAT.YAML:\n return { ok: true, value: stringifyYaml(sections) };\n case CONFIG_FILE_FORMAT.TOML:\n return serializeTomlSections(sections);\n }\n}\n\nexport function serializeConfigFileSectionsWithSetIn(\n file: ConfigFile,\n path: readonly string[],\n value: unknown,\n): Result<string> {\n if (path.length === 0) {\n return { ok: false, error: \"config mutation path must not be empty\" };\n }\n switch (file.format) {\n case CONFIG_FILE_FORMAT.YAML:\n return serializeYamlSectionsWithSetIn(file, path, value);\n case CONFIG_FILE_FORMAT.JSON:\n case CONFIG_FILE_FORMAT.TOML: {\n const sections = parseConfigFileSections(file);\n if (!sections.ok) return sections;\n setNested(sections.value, path, value);\n return serializeConfigFileSections(file.format, sections.value);\n }\n }\n}\n\nfunction parseJsonSections(filename: string, raw: string): Result<Record<string, unknown>> {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw) as unknown;\n } catch (error) {\n return { ok: false, error: `${filename} is not valid ${CONFIG_FILE_FORMAT.JSON}: ${toMessage(error)}` };\n }\n return validateParsedSections(filename, parsed);\n}\n\nfunction parseYamlSections(filename: string, raw: string): Result<Record<string, unknown>> {\n let parsed: unknown;\n try {\n parsed = parseYaml(raw) as unknown;\n } catch (error) {\n return { ok: false, error: `${filename} is not valid ${CONFIG_FILE_FORMAT.YAML}: ${toMessage(error)}` };\n }\n if (parsed === null || parsed === undefined) {\n return { ok: true, value: {} };\n }\n return validateParsedSections(filename, parsed);\n}\n\nfunction parseTomlSections(filename: string, raw: string): Result<Record<string, unknown>> {\n let parsed: unknown;\n try {\n parsed = parseToml(raw) as unknown;\n } catch (error) {\n return { ok: false, error: `${filename} is not valid ${CONFIG_FILE_FORMAT.TOML}: ${toMessage(error)}` };\n }\n return validateParsedSections(filename, parsed);\n}\n\nfunction serializeTomlSections(sections: Record<string, unknown>): Result<string> {\n try {\n return { ok: true, value: stringifyToml(sections) };\n } catch (error) {\n return {\n ok: false,\n error: `config is not serializable as ${CONFIG_FILE_FORMAT.TOML}: ${toMessage(error)}`,\n };\n }\n}\n\nfunction serializeYamlSectionsWithSetIn(\n file: ConfigFile,\n path: readonly string[],\n value: unknown,\n): Result<string> {\n try {\n const doc = parseYamlDocument(file.raw.trim() === \"\" ? \"{}\\n\" : file.raw);\n if (doc.errors.length > 0) {\n return {\n ok: false,\n error: `${file.filename} is not valid ${CONFIG_FILE_FORMAT.YAML}: ${doc.errors[0].message}`,\n };\n }\n doc.setIn([...path], value);\n return { ok: true, value: String(doc) };\n } catch (error) {\n return { ok: false, error: `${file.filename} is not valid ${CONFIG_FILE_FORMAT.YAML}: ${toMessage(error)}` };\n }\n}\n\nfunction setNested(target: Record<string, unknown>, path: readonly string[], value: unknown): void {\n let cursor: Record<string, unknown> = target;\n for (let i = 0; i < path.length - 1; i += 1) {\n const key = path[i];\n const existing = cursor[key];\n if (typeof existing === \"object\" && existing !== null && !Array.isArray(existing)) {\n cursor = existing as Record<string, unknown>;\n } else {\n const fresh: Record<string, unknown> = {};\n cursor[key] = fresh;\n cursor = fresh;\n }\n }\n cursor[path[path.length - 1]] = value;\n}\n\nfunction validateParsedSections(filename: string, parsed: unknown): Result<Record<string, unknown>> {\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n return { ok: false, error: `${filename} must parse to a mapping of descriptor sections` };\n }\n return { ok: true, value: parsed as Record<string, unknown> };\n}\n\nfunction isFileNotFound(error: unknown): boolean {\n return error instanceof Error && \"code\" in error && (error as NodeJS.ErrnoException).code === \"ENOENT\";\n}\n\nfunction toMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nexport {\n canonicalDescriptorJson,\n type DescriptorJsonValue,\n type DescriptorSectionDigest,\n digestDescriptorSection,\n} from \"./descriptor-digest\";\n","import type { ConfigDescriptor, Result } from \"@/config/types\";\n\nexport const AGENT_ENVIRONMENT_SECTION = \"agentEnvironment\";\n\nexport const AGENT_RUNTIME = {\n CODEX: \"codex\",\n CLAUDE_CODE: \"claudeCode\",\n} as const;\n\nexport type AgentRuntime = (typeof AGENT_RUNTIME)[keyof typeof AGENT_RUNTIME];\n\nexport const AGENT_ENVIRONMENT_CONFIG_FIELDS = {\n INSTRUCTIONS: \"instructions\",\n RUNTIMES: \"runtimes\",\n PLUGIN_BOOTSTRAP: \"pluginBootstrap\",\n FILES: \"files\",\n PATH: \"path\",\n TARGET_RUNTIMES: \"targetRuntimes\",\n ENABLED: \"enabled\",\n MARKETPLACES: \"marketplaces\",\n PLUGINS: \"plugins\",\n SKILLS: \"skills\",\n RUNTIME: \"runtime\",\n NAME: \"name\",\n SOURCE: \"source\",\n VERSION: \"version\",\n MARKETPLACE: \"marketplace\",\n} as const;\n\nexport interface AgentInstructionFileConfig {\n readonly path: string;\n readonly targetRuntimes: readonly AgentRuntime[];\n}\n\nexport interface AgentRuntimeConfig {\n readonly enabled: boolean;\n}\n\nexport interface AgentMarketplaceConfig {\n readonly runtime: AgentRuntime;\n readonly name: string;\n readonly source: string;\n}\n\nexport interface AgentPluginConfig {\n readonly runtime: AgentRuntime;\n readonly name: string;\n readonly marketplace?: string;\n readonly version?: string;\n}\n\nexport interface AgentSkillConfig {\n readonly runtime: AgentRuntime;\n readonly name: string;\n readonly source?: string;\n readonly version?: string;\n}\n\nexport interface AgentEnvironmentConfig {\n readonly instructions: {\n readonly files: readonly AgentInstructionFileConfig[];\n };\n readonly runtimes: { readonly [K in AgentRuntime]: AgentRuntimeConfig };\n readonly pluginBootstrap: {\n readonly marketplaces: readonly AgentMarketplaceConfig[];\n readonly plugins: readonly AgentPluginConfig[];\n readonly skills: readonly AgentSkillConfig[];\n };\n}\n\nconst AGENT_RUNTIME_SET: ReadonlySet<string> = new Set(Object.values(AGENT_RUNTIME));\nconst DEFAULT_AGENT_INSTRUCTION_TARGET_RUNTIMES = [\n AGENT_RUNTIME.CODEX,\n AGENT_RUNTIME.CLAUDE_CODE,\n] as const satisfies readonly AgentRuntime[];\n\nexport const DEFAULT_AGENT_INSTRUCTION_FILE_PATH = \"AGENTS.md\";\n\nexport const DEFAULT_AGENT_ENVIRONMENT_CONFIG: AgentEnvironmentConfig = {\n instructions: {\n files: [\n {\n path: DEFAULT_AGENT_INSTRUCTION_FILE_PATH,\n targetRuntimes: DEFAULT_AGENT_INSTRUCTION_TARGET_RUNTIMES,\n },\n ],\n },\n runtimes: {\n [AGENT_RUNTIME.CODEX]: { enabled: true },\n [AGENT_RUNTIME.CLAUDE_CODE]: { enabled: true },\n },\n pluginBootstrap: {\n marketplaces: [],\n plugins: [],\n skills: [],\n },\n};\n\nconst AGENT_ENVIRONMENT_ALLOWED_FIELDS = new Set([\n AGENT_ENVIRONMENT_CONFIG_FIELDS.INSTRUCTIONS,\n AGENT_ENVIRONMENT_CONFIG_FIELDS.RUNTIMES,\n AGENT_ENVIRONMENT_CONFIG_FIELDS.PLUGIN_BOOTSTRAP,\n]);\n\nconst AGENT_ENVIRONMENT_INSTRUCTIONS_ALLOWED_FIELDS = new Set([\n AGENT_ENVIRONMENT_CONFIG_FIELDS.FILES,\n]);\n\nconst AGENT_ENVIRONMENT_INSTRUCTION_FILE_ALLOWED_FIELDS = new Set([\n AGENT_ENVIRONMENT_CONFIG_FIELDS.PATH,\n AGENT_ENVIRONMENT_CONFIG_FIELDS.TARGET_RUNTIMES,\n]);\n\nconst AGENT_ENVIRONMENT_RUNTIME_CONFIG_ALLOWED_FIELDS = new Set([\n AGENT_ENVIRONMENT_CONFIG_FIELDS.ENABLED,\n]);\n\nconst AGENT_ENVIRONMENT_PLUGIN_BOOTSTRAP_ALLOWED_FIELDS = new Set([\n AGENT_ENVIRONMENT_CONFIG_FIELDS.MARKETPLACES,\n AGENT_ENVIRONMENT_CONFIG_FIELDS.PLUGINS,\n AGENT_ENVIRONMENT_CONFIG_FIELDS.SKILLS,\n]);\n\nconst AGENT_ENVIRONMENT_MARKETPLACE_ALLOWED_FIELDS = new Set([\n AGENT_ENVIRONMENT_CONFIG_FIELDS.RUNTIME,\n AGENT_ENVIRONMENT_CONFIG_FIELDS.NAME,\n AGENT_ENVIRONMENT_CONFIG_FIELDS.SOURCE,\n]);\n\nconst AGENT_ENVIRONMENT_PLUGIN_ALLOWED_FIELDS = new Set([\n AGENT_ENVIRONMENT_CONFIG_FIELDS.RUNTIME,\n AGENT_ENVIRONMENT_CONFIG_FIELDS.NAME,\n AGENT_ENVIRONMENT_CONFIG_FIELDS.MARKETPLACE,\n AGENT_ENVIRONMENT_CONFIG_FIELDS.VERSION,\n]);\n\nconst AGENT_ENVIRONMENT_SKILL_ALLOWED_FIELDS = new Set([\n AGENT_ENVIRONMENT_CONFIG_FIELDS.RUNTIME,\n AGENT_ENVIRONMENT_CONFIG_FIELDS.NAME,\n AGENT_ENVIRONMENT_CONFIG_FIELDS.SOURCE,\n AGENT_ENVIRONMENT_CONFIG_FIELDS.VERSION,\n]);\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction rejectUnknownFields(\n path: string,\n value: Record<string, unknown>,\n allowed: ReadonlySet<string>,\n): Result<undefined> {\n const unknownFields = Object.keys(value).filter((field) => !allowed.has(field));\n if (unknownFields.length === 1) {\n return { ok: false, error: `${path}.${unknownFields[0]} is not a recognized config field` };\n }\n if (unknownFields.length > 1) {\n return { ok: false, error: `${path} has unrecognized config fields: ${unknownFields.join(\", \")}` };\n }\n return { ok: true, value: undefined };\n}\n\nfunction validateNonEmptyString(path: string, value: unknown): Result<string> {\n if (typeof value !== \"string\" || value.length === 0) {\n return { ok: false, error: `${path} must be a non-empty string` };\n }\n return { ok: true, value };\n}\n\nfunction validateBoolean(path: string, value: unknown): Result<boolean> {\n if (typeof value !== \"boolean\") {\n return { ok: false, error: `${path} must be a boolean` };\n }\n return { ok: true, value };\n}\n\nfunction validateRuntime(path: string, value: unknown): Result<AgentRuntime> {\n if (typeof value !== \"string\" || !isAgentRuntime(value)) {\n return { ok: false, error: `${path} must be a registered agent runtime` };\n }\n return { ok: true, value };\n}\n\nfunction isAgentRuntime(value: string): value is AgentRuntime {\n return AGENT_RUNTIME_SET.has(value);\n}\n\nfunction validateRuntimeArray(path: string, value: unknown): Result<readonly AgentRuntime[]> {\n if (!Array.isArray(value) || value.length === 0) {\n return { ok: false, error: `${path} must be a non-empty array of registered agent runtimes` };\n }\n\n const runtimes: AgentRuntime[] = [];\n const seen = new Set<AgentRuntime>();\n for (const [index, entry] of value.entries()) {\n const runtime = validateRuntime(`${path}.${index}`, entry);\n if (!runtime.ok) return runtime;\n if (seen.has(runtime.value)) {\n return { ok: false, error: `${path}.${index} repeats registered agent runtime ${runtime.value}` };\n }\n seen.add(runtime.value);\n runtimes.push(runtime.value);\n }\n return { ok: true, value: runtimes };\n}\n\nfunction validateInstructions(raw: unknown): Result<AgentEnvironmentConfig[\"instructions\"]> {\n const sectionPath = `${AGENT_ENVIRONMENT_SECTION}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.INSTRUCTIONS}`;\n if (!isRecord(raw)) {\n return { ok: false, error: `${sectionPath} must be an object` };\n }\n\n const unknown = rejectUnknownFields(sectionPath, raw, AGENT_ENVIRONMENT_INSTRUCTIONS_ALLOWED_FIELDS);\n if (!unknown.ok) return unknown;\n\n const filesRaw = raw[AGENT_ENVIRONMENT_CONFIG_FIELDS.FILES];\n if (filesRaw === undefined) return { ok: true, value: DEFAULT_AGENT_ENVIRONMENT_CONFIG.instructions };\n if (!Array.isArray(filesRaw)) {\n return { ok: false, error: `${sectionPath}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.FILES} must be an array` };\n }\n\n const files: AgentInstructionFileConfig[] = [];\n for (const [index, entry] of filesRaw.entries()) {\n const file = validateInstructionFile(`${sectionPath}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.FILES}.${index}`, entry);\n if (!file.ok) return file;\n files.push(file.value);\n }\n const filePathUniqueness = validateInstructionFilePathUniqueness(\n `${sectionPath}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.FILES}`,\n files,\n );\n if (!filePathUniqueness.ok) return filePathUniqueness;\n return { ok: true, value: { files } };\n}\n\nfunction validateInstructionFile(path: string, raw: unknown): Result<AgentInstructionFileConfig> {\n if (!isRecord(raw)) return { ok: false, error: `${path} must be an object` };\n const unknown = rejectUnknownFields(\n path,\n raw,\n AGENT_ENVIRONMENT_INSTRUCTION_FILE_ALLOWED_FIELDS,\n );\n if (!unknown.ok) return unknown;\n\n const filePath = validateNonEmptyString(\n `${path}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.PATH}`,\n raw[AGENT_ENVIRONMENT_CONFIG_FIELDS.PATH],\n );\n if (!filePath.ok) return filePath;\n\n const targetRuntimes = validateRuntimeArray(\n `${path}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.TARGET_RUNTIMES}`,\n raw[AGENT_ENVIRONMENT_CONFIG_FIELDS.TARGET_RUNTIMES],\n );\n if (!targetRuntimes.ok) return targetRuntimes;\n\n return { ok: true, value: { path: filePath.value, targetRuntimes: targetRuntimes.value } };\n}\n\nfunction validateRuntimes(raw: unknown): Result<AgentEnvironmentConfig[\"runtimes\"]> {\n const sectionPath = `${AGENT_ENVIRONMENT_SECTION}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.RUNTIMES}`;\n if (!isRecord(raw)) {\n return { ok: false, error: `${sectionPath} must be an object` };\n }\n\n const runtimes: Record<AgentRuntime, AgentRuntimeConfig> = { ...DEFAULT_AGENT_ENVIRONMENT_CONFIG.runtimes };\n for (const [runtimeName, runtimeRaw] of Object.entries(raw)) {\n // Runtime ids are the field names, so unknown-field rejection is the runtime-id validation below.\n const runtime = validateRuntime(`${sectionPath}.${runtimeName}`, runtimeName);\n if (!runtime.ok) return runtime;\n const config = validateRuntimeConfig(`${sectionPath}.${runtimeName}`, runtimeRaw, runtimes[runtime.value]);\n if (!config.ok) return config;\n runtimes[runtime.value] = config.value;\n }\n\n return { ok: true, value: runtimes };\n}\n\nfunction validateRuntimeConfig(\n path: string,\n raw: unknown,\n defaults: AgentRuntimeConfig,\n): Result<AgentRuntimeConfig> {\n if (!isRecord(raw)) return { ok: false, error: `${path} must be an object` };\n const unknown = rejectUnknownFields(path, raw, AGENT_ENVIRONMENT_RUNTIME_CONFIG_ALLOWED_FIELDS);\n if (!unknown.ok) return unknown;\n\n const enabledRaw = raw[AGENT_ENVIRONMENT_CONFIG_FIELDS.ENABLED];\n if (enabledRaw === undefined) return { ok: true, value: defaults };\n const enabled = validateBoolean(`${path}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.ENABLED}`, enabledRaw);\n if (!enabled.ok) return enabled;\n return { ok: true, value: { ...defaults, enabled: enabled.value } };\n}\n\nfunction validatePluginBootstrap(raw: unknown): Result<AgentEnvironmentConfig[\"pluginBootstrap\"]> {\n const sectionPath = `${AGENT_ENVIRONMENT_SECTION}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.PLUGIN_BOOTSTRAP}`;\n if (!isRecord(raw)) {\n return { ok: false, error: `${sectionPath} must be an object` };\n }\n\n const unknown = rejectUnknownFields(\n sectionPath,\n raw,\n AGENT_ENVIRONMENT_PLUGIN_BOOTSTRAP_ALLOWED_FIELDS,\n );\n if (!unknown.ok) return unknown;\n\n const marketplaces = validateEntryArray(\n `${sectionPath}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.MARKETPLACES}`,\n raw[AGENT_ENVIRONMENT_CONFIG_FIELDS.MARKETPLACES],\n validateMarketplace,\n DEFAULT_AGENT_ENVIRONMENT_CONFIG.pluginBootstrap.marketplaces,\n );\n if (!marketplaces.ok) return marketplaces;\n\n const marketplaceUniqueness = validateNamedRuntimeEntryUniqueness(\n `${sectionPath}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.MARKETPLACES}`,\n marketplaces.value,\n );\n if (!marketplaceUniqueness.ok) return marketplaceUniqueness;\n\n const plugins = validateEntryArray(\n `${sectionPath}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.PLUGINS}`,\n raw[AGENT_ENVIRONMENT_CONFIG_FIELDS.PLUGINS],\n validatePlugin,\n DEFAULT_AGENT_ENVIRONMENT_CONFIG.pluginBootstrap.plugins,\n );\n if (!plugins.ok) return plugins;\n\n const pluginUniqueness = validateNamedRuntimeEntryUniqueness(\n `${sectionPath}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.PLUGINS}`,\n plugins.value,\n );\n if (!pluginUniqueness.ok) return pluginUniqueness;\n\n const pluginMarketplaceReferences = validatePluginMarketplaceReferences(\n sectionPath,\n marketplaces.value,\n plugins.value,\n );\n if (!pluginMarketplaceReferences.ok) return pluginMarketplaceReferences;\n\n const skills = validateEntryArray(\n `${sectionPath}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.SKILLS}`,\n raw[AGENT_ENVIRONMENT_CONFIG_FIELDS.SKILLS],\n validateSkill,\n DEFAULT_AGENT_ENVIRONMENT_CONFIG.pluginBootstrap.skills,\n );\n if (!skills.ok) return skills;\n\n const skillUniqueness = validateNamedRuntimeEntryUniqueness(\n `${sectionPath}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.SKILLS}`,\n skills.value,\n );\n if (!skillUniqueness.ok) return skillUniqueness;\n\n return {\n ok: true,\n value: {\n marketplaces: marketplaces.value,\n plugins: plugins.value,\n skills: skills.value,\n },\n };\n}\n\nfunction validateEntryArray<T>(\n path: string,\n raw: unknown,\n validateEntry: (path: string, raw: unknown) => Result<T>,\n defaults: readonly T[],\n): Result<readonly T[]> {\n if (raw === undefined) return { ok: true, value: defaults };\n if (!Array.isArray(raw)) return { ok: false, error: `${path} must be an array` };\n\n const entries: T[] = [];\n for (const [index, entry] of raw.entries()) {\n const result = validateEntry(`${path}.${index}`, entry);\n if (!result.ok) return result;\n entries.push(result.value);\n }\n return { ok: true, value: entries };\n}\n\nfunction validateInstructionFilePathUniqueness(\n path: string,\n files: readonly AgentInstructionFileConfig[],\n): Result<undefined> {\n const paths = new Set<string>();\n for (const [index, file] of files.entries()) {\n if (paths.has(file.path)) {\n return {\n ok: false,\n error: `${path}.${index}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.PATH} ${\n JSON.stringify(file.path)\n } is already used by another instruction file entry`,\n };\n }\n paths.add(file.path);\n }\n return { ok: true, value: undefined };\n}\n\nfunction validateNamedRuntimeEntryUniqueness(\n path: string,\n entries: readonly { readonly runtime: AgentRuntime; readonly name: string }[],\n): Result<undefined> {\n const namesByRuntime = new Map<AgentRuntime, Set<string>>();\n for (const [index, entry] of entries.entries()) {\n const runtimeNames = namesByRuntime.get(entry.runtime) ?? new Set<string>();\n if (runtimeNames.has(entry.name)) {\n return {\n ok: false,\n error: `${path}.${index}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.NAME} ${\n JSON.stringify(entry.name)\n } is already used by another ${entry.runtime} entry`,\n };\n }\n runtimeNames.add(entry.name);\n namesByRuntime.set(entry.runtime, runtimeNames);\n }\n return { ok: true, value: undefined };\n}\n\nfunction validatePluginMarketplaceReferences(\n path: string,\n marketplaces: readonly AgentMarketplaceConfig[],\n plugins: readonly AgentPluginConfig[],\n): Result<undefined> {\n const marketplacesByRuntime = new Map<AgentRuntime, Set<string>>();\n for (const marketplace of marketplaces) {\n const runtimeMarketplaces = marketplacesByRuntime.get(marketplace.runtime) ?? new Set<string>();\n runtimeMarketplaces.add(marketplace.name);\n marketplacesByRuntime.set(marketplace.runtime, runtimeMarketplaces);\n }\n\n for (const [index, plugin] of plugins.entries()) {\n if (plugin.marketplace === undefined) continue;\n const runtimeMarketplaces = marketplacesByRuntime.get(plugin.runtime);\n if (!runtimeMarketplaces?.has(plugin.marketplace)) {\n return {\n ok: false,\n error:\n `${path}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.PLUGINS}.${index}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.MARKETPLACE} must reference a configured marketplace for the same runtime`,\n };\n }\n }\n\n return { ok: true, value: undefined };\n}\n\nfunction validateMarketplace(path: string, raw: unknown): Result<AgentMarketplaceConfig> {\n if (!isRecord(raw)) return { ok: false, error: `${path} must be an object` };\n const unknown = rejectUnknownFields(\n path,\n raw,\n AGENT_ENVIRONMENT_MARKETPLACE_ALLOWED_FIELDS,\n );\n if (!unknown.ok) return unknown;\n\n const base = validateNamedRuntimeEntry(path, raw);\n if (!base.ok) return base;\n const source = validateNonEmptyString(\n `${path}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.SOURCE}`,\n raw[AGENT_ENVIRONMENT_CONFIG_FIELDS.SOURCE],\n );\n if (!source.ok) return source;\n return { ok: true, value: { ...base.value, source: source.value } };\n}\n\nfunction validatePlugin(path: string, raw: unknown): Result<AgentPluginConfig> {\n if (!isRecord(raw)) return { ok: false, error: `${path} must be an object` };\n const unknown = rejectUnknownFields(\n path,\n raw,\n AGENT_ENVIRONMENT_PLUGIN_ALLOWED_FIELDS,\n );\n if (!unknown.ok) return unknown;\n\n const base = validateNamedRuntimeEntry(path, raw);\n if (!base.ok) return base;\n const marketplace = validateOptionalString(\n `${path}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.MARKETPLACE}`,\n raw[AGENT_ENVIRONMENT_CONFIG_FIELDS.MARKETPLACE],\n );\n if (!marketplace.ok) return marketplace;\n const version = validateOptionalString(\n `${path}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.VERSION}`,\n raw[AGENT_ENVIRONMENT_CONFIG_FIELDS.VERSION],\n );\n if (!version.ok) return version;\n return {\n ok: true,\n value: {\n ...base.value,\n ...(marketplace.value === undefined ? {} : { marketplace: marketplace.value }),\n ...(version.value === undefined ? {} : { version: version.value }),\n },\n };\n}\n\nfunction validateSkill(path: string, raw: unknown): Result<AgentSkillConfig> {\n if (!isRecord(raw)) return { ok: false, error: `${path} must be an object` };\n const unknown = rejectUnknownFields(\n path,\n raw,\n AGENT_ENVIRONMENT_SKILL_ALLOWED_FIELDS,\n );\n if (!unknown.ok) return unknown;\n\n const base = validateNamedRuntimeEntry(path, raw);\n if (!base.ok) return base;\n const source = validateOptionalString(\n `${path}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.SOURCE}`,\n raw[AGENT_ENVIRONMENT_CONFIG_FIELDS.SOURCE],\n );\n if (!source.ok) return source;\n const version = validateOptionalString(\n `${path}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.VERSION}`,\n raw[AGENT_ENVIRONMENT_CONFIG_FIELDS.VERSION],\n );\n if (!version.ok) return version;\n return {\n ok: true,\n value: {\n ...base.value,\n ...(source.value === undefined ? {} : { source: source.value }),\n ...(version.value === undefined ? {} : { version: version.value }),\n },\n };\n}\n\nfunction validateNamedRuntimeEntry(\n path: string,\n raw: Record<string, unknown>,\n): Result<{ readonly runtime: AgentRuntime; readonly name: string }> {\n const runtime = validateRuntime(\n `${path}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.RUNTIME}`,\n raw[AGENT_ENVIRONMENT_CONFIG_FIELDS.RUNTIME],\n );\n if (!runtime.ok) return runtime;\n const name = validateNonEmptyString(\n `${path}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.NAME}`,\n raw[AGENT_ENVIRONMENT_CONFIG_FIELDS.NAME],\n );\n if (!name.ok) return name;\n return { ok: true, value: { runtime: runtime.value, name: name.value } };\n}\n\nfunction validateOptionalString(path: string, value: unknown): Result<string | undefined> {\n if (value === undefined) return { ok: true, value: undefined };\n return validateNonEmptyString(path, value);\n}\n\nfunction validate(value: unknown): Result<AgentEnvironmentConfig> {\n if (!isRecord(value)) {\n return { ok: false, error: `${AGENT_ENVIRONMENT_SECTION} section must be an object` };\n }\n\n const unknown = rejectUnknownFields(\n AGENT_ENVIRONMENT_SECTION,\n value,\n AGENT_ENVIRONMENT_ALLOWED_FIELDS,\n );\n if (!unknown.ok) return unknown;\n\n const instructionsRaw = value[AGENT_ENVIRONMENT_CONFIG_FIELDS.INSTRUCTIONS];\n const instructions = instructionsRaw === undefined\n ? { ok: true as const, value: DEFAULT_AGENT_ENVIRONMENT_CONFIG.instructions }\n : validateInstructions(instructionsRaw);\n if (!instructions.ok) return instructions;\n\n const runtimesRaw = value[AGENT_ENVIRONMENT_CONFIG_FIELDS.RUNTIMES];\n const runtimes = runtimesRaw === undefined\n ? { ok: true as const, value: DEFAULT_AGENT_ENVIRONMENT_CONFIG.runtimes }\n : validateRuntimes(runtimesRaw);\n if (!runtimes.ok) return runtimes;\n\n const pluginBootstrapRaw = value[AGENT_ENVIRONMENT_CONFIG_FIELDS.PLUGIN_BOOTSTRAP];\n const pluginBootstrap = pluginBootstrapRaw === undefined\n ? { ok: true as const, value: DEFAULT_AGENT_ENVIRONMENT_CONFIG.pluginBootstrap }\n : validatePluginBootstrap(pluginBootstrapRaw);\n if (!pluginBootstrap.ok) return pluginBootstrap;\n\n return {\n ok: true,\n value: {\n instructions: instructions.value,\n runtimes: runtimes.value,\n pluginBootstrap: pluginBootstrap.value,\n },\n };\n}\n\nexport const agentEnvironmentConfigDescriptor: ConfigDescriptor<AgentEnvironmentConfig> = {\n section: AGENT_ENVIRONMENT_SECTION,\n defaults: DEFAULT_AGENT_ENVIRONMENT_CONFIG,\n validate,\n};\n","import type { Result } from \"@/config/types\";\n\nexport const PATH_FILTER_CONFIG_FIELDS = {\n INCLUDE: \"include\",\n EXCLUDE: \"exclude\",\n} as const;\n\nexport interface PathFilterConfig {\n readonly include?: readonly string[];\n readonly exclude?: readonly string[];\n}\n\nexport function validatePathFilterConfig(raw: unknown, path: string): Result<PathFilterConfig> {\n if (typeof raw !== \"object\" || raw === null || Array.isArray(raw)) {\n return {\n ok: false,\n error: `${path} must be an object`,\n };\n }\n const candidate = raw as Record<string, unknown>;\n\n const include = candidate[PATH_FILTER_CONFIG_FIELDS.INCLUDE];\n if (\n include !== undefined\n && (!Array.isArray(include) || !include.every((value) => typeof value === \"string\"))\n ) {\n return {\n ok: false,\n error: `${path}.${PATH_FILTER_CONFIG_FIELDS.INCLUDE} must be an array of strings`,\n };\n }\n\n const exclude = candidate[PATH_FILTER_CONFIG_FIELDS.EXCLUDE];\n if (\n exclude !== undefined\n && (!Array.isArray(exclude) || !exclude.every((value) => typeof value === \"string\"))\n ) {\n return {\n ok: false,\n error: `${path}.${PATH_FILTER_CONFIG_FIELDS.EXCLUDE} must be an array of strings`,\n };\n }\n\n const value: {\n include?: readonly string[];\n exclude?: readonly string[];\n } = {};\n if (include !== undefined) value.include = include as readonly string[];\n if (exclude !== undefined) value.exclude = exclude as readonly string[];\n\n return { ok: true, value };\n}\n\nconst PATH_SEGMENT_SEPARATOR = \"/\";\n\nfunction normalizePathPrefix(value: string): string {\n return value.replace(/\\/+$/, \"\");\n}\n\nfunction pathMatchesPrefix(path: string, prefix: string): boolean {\n const normalizedPath = normalizePathPrefix(path);\n const normalizedPrefix = normalizePathPrefix(prefix);\n return normalizedPath === normalizedPrefix\n || normalizedPath.startsWith(`${normalizedPrefix}${PATH_SEGMENT_SEPARATOR}`);\n}\n\n/**\n * Keeps the paths a filter admits: a path survives when the include set is empty\n * or some include prefix matches it, and no exclude prefix matches it. A prefix\n * matches a path by exact equality or at a path-segment boundary, never by shared\n * leading text alone.\n */\nexport function applyPathFilter(\n paths: readonly string[],\n config: PathFilterConfig,\n): readonly string[] {\n const includePrefixes = config.include ?? [];\n const excludePrefixes = config.exclude ?? [];\n return paths.filter((path) => {\n if (includePrefixes.length > 0 && !includePrefixes.some((prefix) => pathMatchesPrefix(path, prefix))) {\n return false;\n }\n return !excludePrefixes.some((prefix) => pathMatchesPrefix(path, prefix));\n });\n}\n","import { type PathFilterConfig, validatePathFilterConfig } from \"@/config/primitives/path-filter\";\nimport type { ConfigDescriptor, Result } from \"@/config/types\";\n\nexport const AUDIT_SECTION = \"audit\";\n\nexport const AUDIT_CONFIG_FIELDS = {\n STORAGE: \"storage\",\n SPX_DIR: \"spxDir\",\n NODES_DIR: \"nodesDir\",\n AUDIT_DIR: \"auditDir\",\n RUNS_DIR: \"runsDir\",\n VERDICT_FILE: \"verdictFile\",\n VERDICT_FILE_SUFFIX: \"verdictFileSuffix\",\n STATE_FILE: \"stateFile\",\n BASE_REF: \"baseRef\",\n BRANCH_SLUG: \"branchSlug\",\n MAX_BYTES: \"maxBytes\",\n AUDITORS: \"auditors\",\n TARGETS: \"targets\",\n} as const;\n\nexport const AUDIT_BRANCH_SLUG_MIN_MAX_BYTES = 10;\n\nexport interface AuditStorageConfig {\n readonly spxDir: string;\n readonly nodesDir: string;\n readonly auditDir: string;\n readonly runsDir: string;\n readonly verdictFile: string;\n readonly verdictFileSuffix: string;\n readonly stateFile: string;\n}\n\ntype MutableAuditStorageConfig = {\n -readonly [Field in keyof AuditStorageConfig]: string;\n};\n\nexport interface AuditBranchSlugConfig {\n readonly maxBytes: number;\n}\n\nexport interface AuditConfig {\n readonly storage: AuditStorageConfig;\n readonly baseRef: string;\n readonly branchSlug: AuditBranchSlugConfig;\n readonly auditors: readonly string[];\n readonly targets: PathFilterConfig;\n}\n\nexport const DEFAULT_AUDIT_CONFIG: AuditConfig = {\n storage: {\n spxDir: \".spx\",\n nodesDir: \"nodes\",\n auditDir: \"audit\",\n runsDir: \"runs\",\n verdictFile: \"verdict.audit.xml\",\n verdictFileSuffix: \".audit.xml\",\n stateFile: \"state.json\",\n },\n baseRef: \"main\",\n branchSlug: {\n maxBytes: 120,\n },\n auditors: [],\n targets: resolveDefaultTargets(),\n};\n\nconst AUDIT_ALLOWED_FIELDS = new Set<string>([\n AUDIT_CONFIG_FIELDS.STORAGE,\n AUDIT_CONFIG_FIELDS.BASE_REF,\n AUDIT_CONFIG_FIELDS.BRANCH_SLUG,\n AUDIT_CONFIG_FIELDS.AUDITORS,\n AUDIT_CONFIG_FIELDS.TARGETS,\n]);\n\nconst AUDIT_STORAGE_ALLOWED_FIELDS = new Set<string>([\n AUDIT_CONFIG_FIELDS.SPX_DIR,\n AUDIT_CONFIG_FIELDS.NODES_DIR,\n AUDIT_CONFIG_FIELDS.AUDIT_DIR,\n AUDIT_CONFIG_FIELDS.RUNS_DIR,\n AUDIT_CONFIG_FIELDS.VERDICT_FILE,\n AUDIT_CONFIG_FIELDS.VERDICT_FILE_SUFFIX,\n AUDIT_CONFIG_FIELDS.STATE_FILE,\n]);\n\nconst AUDIT_BRANCH_SLUG_ALLOWED_FIELDS = new Set<string>([\n AUDIT_CONFIG_FIELDS.MAX_BYTES,\n]);\n\nconst PATH_SEPARATOR = \"/\";\nconst ENCODED_SEPARATOR = \"-\";\n\nexport const auditConfigDescriptor: ConfigDescriptor<AuditConfig> = {\n section: AUDIT_SECTION,\n defaults: DEFAULT_AUDIT_CONFIG,\n validate: validateAuditConfig,\n};\n\nexport function encodeNodePath(nodePath: string): string {\n return nodePath.replaceAll(PATH_SEPARATOR, ENCODED_SEPARATOR);\n}\n\nexport function formatAuditTimestamp(now?: () => Date): string {\n const date = (now ?? (() => new Date()))();\n\n const year = date.getUTCFullYear();\n const month = String(date.getUTCMonth() + 1).padStart(2, \"0\");\n const day = String(date.getUTCDate()).padStart(2, \"0\");\n const hours = String(date.getUTCHours()).padStart(2, \"0\");\n const minutes = String(date.getUTCMinutes()).padStart(2, \"0\");\n const seconds = String(date.getUTCSeconds()).padStart(2, \"0\");\n\n return `${year}-${month}-${day}_${hours}-${minutes}-${seconds}`;\n}\n\nfunction resolveDefaultTargets(): PathFilterConfig {\n const result = validatePathFilterConfig(\n {},\n `${AUDIT_SECTION}.${AUDIT_CONFIG_FIELDS.TARGETS}`,\n );\n if (!result.ok) throw new Error(result.error);\n return result.value;\n}\n\nfunction validateAuditConfig(raw: unknown): Result<AuditConfig> {\n if (!isRecord(raw)) {\n return { ok: false, error: `${AUDIT_SECTION} section must be an object` };\n }\n\n const unknown = rejectUnknownFields(AUDIT_SECTION, raw, AUDIT_ALLOWED_FIELDS);\n if (!unknown.ok) return unknown;\n\n const storage = raw[AUDIT_CONFIG_FIELDS.STORAGE] === undefined\n ? { ok: true as const, value: DEFAULT_AUDIT_CONFIG.storage }\n : validateStorage(raw[AUDIT_CONFIG_FIELDS.STORAGE]);\n if (!storage.ok) return storage;\n\n const baseRef = raw[AUDIT_CONFIG_FIELDS.BASE_REF] === undefined\n ? { ok: true as const, value: DEFAULT_AUDIT_CONFIG.baseRef }\n : validateNonEmptyString(\n `${AUDIT_SECTION}.${AUDIT_CONFIG_FIELDS.BASE_REF}`,\n raw[AUDIT_CONFIG_FIELDS.BASE_REF],\n );\n if (!baseRef.ok) return baseRef;\n\n const branchSlug = raw[AUDIT_CONFIG_FIELDS.BRANCH_SLUG] === undefined\n ? { ok: true as const, value: DEFAULT_AUDIT_CONFIG.branchSlug }\n : validateBranchSlug(raw[AUDIT_CONFIG_FIELDS.BRANCH_SLUG]);\n if (!branchSlug.ok) return branchSlug;\n\n const auditors = raw[AUDIT_CONFIG_FIELDS.AUDITORS] === undefined\n ? { ok: true as const, value: DEFAULT_AUDIT_CONFIG.auditors }\n : validateArrayOfNonEmptyStrings(\n `${AUDIT_SECTION}.${AUDIT_CONFIG_FIELDS.AUDITORS}`,\n raw[AUDIT_CONFIG_FIELDS.AUDITORS],\n );\n if (!auditors.ok) return auditors;\n\n const targets = raw[AUDIT_CONFIG_FIELDS.TARGETS] === undefined\n ? { ok: true as const, value: DEFAULT_AUDIT_CONFIG.targets }\n : validatePathFilterConfig(\n raw[AUDIT_CONFIG_FIELDS.TARGETS],\n `${AUDIT_SECTION}.${AUDIT_CONFIG_FIELDS.TARGETS}`,\n );\n if (!targets.ok) return targets;\n\n return {\n ok: true,\n value: {\n storage: storage.value,\n baseRef: baseRef.value,\n branchSlug: branchSlug.value,\n auditors: auditors.value,\n targets: targets.value,\n },\n };\n}\n\nfunction validateStorage(raw: unknown): Result<AuditStorageConfig> {\n if (!isRecord(raw)) {\n return { ok: false, error: `${AUDIT_SECTION}.${AUDIT_CONFIG_FIELDS.STORAGE} must be an object` };\n }\n const unknown = rejectUnknownFields(\n `${AUDIT_SECTION}.${AUDIT_CONFIG_FIELDS.STORAGE}`,\n raw,\n AUDIT_STORAGE_ALLOWED_FIELDS,\n );\n if (!unknown.ok) return unknown;\n\n return validateStringRecord(\n `${AUDIT_SECTION}.${AUDIT_CONFIG_FIELDS.STORAGE}`,\n DEFAULT_AUDIT_CONFIG.storage,\n raw,\n );\n}\n\nfunction validateBranchSlug(raw: unknown): Result<AuditBranchSlugConfig> {\n if (!isRecord(raw)) {\n return { ok: false, error: `${AUDIT_SECTION}.${AUDIT_CONFIG_FIELDS.BRANCH_SLUG} must be an object` };\n }\n const unknown = rejectUnknownFields(\n `${AUDIT_SECTION}.${AUDIT_CONFIG_FIELDS.BRANCH_SLUG}`,\n raw,\n AUDIT_BRANCH_SLUG_ALLOWED_FIELDS,\n );\n if (!unknown.ok) return unknown;\n\n const maxBytesRaw = raw[AUDIT_CONFIG_FIELDS.MAX_BYTES];\n if (maxBytesRaw === undefined) return { ok: true, value: DEFAULT_AUDIT_CONFIG.branchSlug };\n if (\n typeof maxBytesRaw !== \"number\"\n || !Number.isInteger(maxBytesRaw)\n || maxBytesRaw < AUDIT_BRANCH_SLUG_MIN_MAX_BYTES\n ) {\n return {\n ok: false,\n error:\n `${AUDIT_SECTION}.${AUDIT_CONFIG_FIELDS.BRANCH_SLUG}.${AUDIT_CONFIG_FIELDS.MAX_BYTES} must be an integer greater than or equal to ${AUDIT_BRANCH_SLUG_MIN_MAX_BYTES}`,\n };\n }\n return { ok: true, value: { maxBytes: maxBytesRaw } };\n}\n\nfunction validateStringRecord(\n path: string,\n defaults: AuditStorageConfig,\n raw: Record<string, unknown>,\n): Result<AuditStorageConfig> {\n const next: MutableAuditStorageConfig = { ...defaults };\n // Unknown fields are rejected before this default merge.\n for (const field of Object.keys(defaults)) {\n const value = raw[field];\n if (value === undefined) continue;\n const validated = validateNonEmptyString(`${path}.${field}`, value);\n if (!validated.ok) return validated;\n next[field as keyof AuditStorageConfig] = validated.value;\n }\n return { ok: true, value: next };\n}\n\nfunction validateNonEmptyString(path: string, value: unknown): Result<string> {\n if (typeof value !== \"string\" || value.length === 0) {\n return { ok: false, error: `${path} must be a non-empty string` };\n }\n return { ok: true, value };\n}\n\nfunction validateArrayOfNonEmptyStrings(path: string, value: unknown): Result<readonly string[]> {\n if (!Array.isArray(value)) {\n return { ok: false, error: `${path} must be an array of non-empty strings` };\n }\n const entries: string[] = [];\n for (const [index, entry] of value.entries()) {\n const validated = validateNonEmptyString(`${path}.${index}`, entry);\n if (!validated.ok) return validated;\n entries.push(validated.value);\n }\n return { ok: true, value: entries };\n}\n\nfunction rejectUnknownFields(\n path: string,\n value: Record<string, unknown>,\n allowed: ReadonlySet<string>,\n): Result<undefined> {\n const unknownField = Object.keys(value).find((field) => !allowed.has(field));\n if (unknownField !== undefined) {\n return { ok: false, error: `${path}.${unknownField} is not a recognized config field` };\n }\n return { ok: true, value: undefined };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import type { ConfigDescriptor, Result } from \"@/config/types\";\n\nconst SPEC_TREE_KIND_CATEGORY_VALUES = {\n NODE: \"node\",\n DECISION: \"decision\",\n} as const;\n\nconst SPEC_TREE_EMPTY_ALIASES = [] as const;\n\nexport const SPEC_TREE_CONFIG = {\n SECTION: \"specTree\",\n ROOT_DIRECTORY: \"spx\",\n PRODUCT: {\n LABEL: \"Product\",\n SUFFIX: \".product.md\",\n },\n CATEGORY: SPEC_TREE_KIND_CATEGORY_VALUES,\n KINDS: {\n enabler: {\n category: SPEC_TREE_KIND_CATEGORY_VALUES.NODE,\n label: \"Enabler\",\n suffix: \".enabler\",\n aliases: SPEC_TREE_EMPTY_ALIASES,\n },\n outcome: {\n category: SPEC_TREE_KIND_CATEGORY_VALUES.NODE,\n label: \"Outcome\",\n suffix: \".outcome\",\n aliases: SPEC_TREE_EMPTY_ALIASES,\n },\n adr: {\n category: SPEC_TREE_KIND_CATEGORY_VALUES.DECISION,\n label: \"ADR\",\n suffix: \".adr.md\",\n aliases: SPEC_TREE_EMPTY_ALIASES,\n },\n pdr: {\n category: SPEC_TREE_KIND_CATEGORY_VALUES.DECISION,\n label: \"PDR\",\n suffix: \".pdr.md\",\n aliases: SPEC_TREE_EMPTY_ALIASES,\n },\n },\n} as const;\n\nexport const SPEC_TREE_CONFIG_FIELDS = {\n KINDS: \"kinds\",\n} as const;\n\nexport const SPEC_TREE_KIND_CATEGORY = SPEC_TREE_CONFIG.CATEGORY;\n\nexport type SpecTreeKindCategory = (typeof SPEC_TREE_KIND_CATEGORY)[keyof typeof SPEC_TREE_KIND_CATEGORY];\n\nexport const KIND_REGISTRY = SPEC_TREE_CONFIG.KINDS;\n\nexport type Kind = keyof typeof KIND_REGISTRY;\nexport type KindDefinition<K extends Kind> = (typeof KIND_REGISTRY)[K];\n\nexport type NodeKind = {\n [K in Kind]: (typeof KIND_REGISTRY)[K][\"category\"] extends typeof SPEC_TREE_KIND_CATEGORY.NODE ? K : never;\n}[Kind];\n\nexport type DecisionKind = {\n [K in Kind]: (typeof KIND_REGISTRY)[K][\"category\"] extends typeof SPEC_TREE_KIND_CATEGORY.DECISION ? K : never;\n}[Kind];\n\nexport const SPEC_TREE_ADR_KIND: DecisionKind = \"adr\";\n\nexport const NODE_KINDS: readonly NodeKind[] = (Object.keys(KIND_REGISTRY) as Kind[]).filter(\n (k): k is NodeKind => KIND_REGISTRY[k].category === SPEC_TREE_KIND_CATEGORY.NODE,\n);\n\nexport const DECISION_KINDS: readonly DecisionKind[] = (Object.keys(KIND_REGISTRY) as Kind[]).filter(\n (k): k is DecisionKind => KIND_REGISTRY[k].category === SPEC_TREE_KIND_CATEGORY.DECISION,\n);\n\nexport const NODE_SUFFIXES: readonly string[] = NODE_KINDS.map((k) => KIND_REGISTRY[k].suffix);\nexport const DECISION_SUFFIXES: readonly string[] = DECISION_KINDS.map((k) => KIND_REGISTRY[k].suffix);\n\nexport const SPEC_TREE_NODE_STATE = {\n DECLARED: \"declared\",\n SPECIFIED: \"specified\",\n FAILING: \"failing\",\n PASSING: \"passing\",\n} as const;\n\nexport type SpecTreeNodeState = (typeof SPEC_TREE_NODE_STATE)[keyof typeof SPEC_TREE_NODE_STATE];\n\nexport type SpecTreeConfig = {\n readonly [SPEC_TREE_CONFIG_FIELDS.KINDS]: { readonly [K in Kind]?: KindDefinition<K> };\n};\n\nexport const SPEC_TREE_SECTION = SPEC_TREE_CONFIG.SECTION;\n\nfunction isKind(value: string): value is Kind {\n return Object.prototype.hasOwnProperty.call(KIND_REGISTRY, value);\n}\n\nfunction buildDefaults(): SpecTreeConfig {\n return { kinds: { ...KIND_REGISTRY } };\n}\n\nfunction buildConfigFromKindNames(kindNames: readonly Kind[]): SpecTreeConfig {\n const entries = kindNames.map((kind) => [kind, KIND_REGISTRY[kind]] as const);\n return { kinds: Object.fromEntries(entries) as SpecTreeConfig[\"kinds\"] };\n}\n\nfunction validate(value: unknown): Result<SpecTreeConfig> {\n if (typeof value !== \"object\" || value === null) {\n return { ok: false, error: `${SPEC_TREE_SECTION} section must be an object` };\n }\n const candidate = value as { [SPEC_TREE_CONFIG_FIELDS.KINDS]?: unknown };\n const kindValue = candidate[SPEC_TREE_CONFIG_FIELDS.KINDS];\n if (Array.isArray(kindValue)) {\n return validateKindList(kindValue);\n }\n if (\n typeof kindValue !== \"object\"\n || kindValue === null\n ) {\n return {\n ok: false,\n error:\n `${SPEC_TREE_SECTION}.${SPEC_TREE_CONFIG_FIELDS.KINDS} must be an array of registry kind names or an object with registry metadata`,\n };\n }\n\n return validateKindDefinitionMap(kindValue as Record<string, unknown>);\n}\n\nfunction validateKindList(kinds: readonly unknown[]): Result<SpecTreeConfig> {\n const kindNames: Kind[] = [];\n for (const entry of kinds) {\n if (typeof entry !== \"string\") {\n return {\n ok: false,\n error: `${SPEC_TREE_SECTION}.${SPEC_TREE_CONFIG_FIELDS.KINDS} entries must be registry kind names`,\n };\n }\n if (!isKind(entry)) {\n return {\n ok: false,\n error: `${SPEC_TREE_SECTION}.${SPEC_TREE_CONFIG_FIELDS.KINDS} contains unknown kind \"${entry}\"`,\n };\n }\n kindNames.push(entry);\n }\n\n const duplicateKinds = kindNames.filter((kind, index) => kindNames.indexOf(kind) !== index);\n if (duplicateKinds.length > 0) {\n return {\n ok: false,\n error: `${SPEC_TREE_SECTION}.${SPEC_TREE_CONFIG_FIELDS.KINDS} contains duplicate kind \"${duplicateKinds[0]}\"`,\n };\n }\n\n return { ok: true, value: buildConfigFromKindNames(kindNames) };\n}\n\nfunction validateKindDefinitionMap(kindEntries: Record<string, unknown>): Result<SpecTreeConfig> {\n const entries: Array<[Kind, KindDefinition<Kind>]> = [];\n for (const [key, entry] of Object.entries(kindEntries)) {\n if (!isKind(key)) {\n return {\n ok: false,\n error: `${SPEC_TREE_SECTION}.${SPEC_TREE_CONFIG_FIELDS.KINDS} contains unknown kind \"${key}\"`,\n };\n }\n if (typeof entry !== \"object\" || entry === null) {\n return {\n ok: false,\n error: `${SPEC_TREE_SECTION}.${SPEC_TREE_CONFIG_FIELDS.KINDS}.${key} must be an object with registry metadata`,\n };\n }\n const def = entry as { category?: unknown; suffix?: unknown };\n const expected = KIND_REGISTRY[key];\n if (def.category !== expected.category) {\n return {\n ok: false,\n error: `${SPEC_TREE_SECTION}.${SPEC_TREE_CONFIG_FIELDS.KINDS}.${key}.category must be \"${expected.category}\"`,\n };\n }\n if ((entry as { label?: unknown }).label !== expected.label) {\n return {\n ok: false,\n error: `${SPEC_TREE_SECTION}.${SPEC_TREE_CONFIG_FIELDS.KINDS}.${key}.label must be \"${expected.label}\"`,\n };\n }\n if (def.suffix !== expected.suffix) {\n return {\n ok: false,\n error: `${SPEC_TREE_SECTION}.${SPEC_TREE_CONFIG_FIELDS.KINDS}.${key}.suffix must be \"${expected.suffix}\"`,\n };\n }\n const aliases = (entry as { aliases?: unknown }).aliases;\n if (!Array.isArray(aliases) || aliases.some((alias) => typeof alias !== \"string\")) {\n return {\n ok: false,\n error: `${SPEC_TREE_SECTION}.${SPEC_TREE_CONFIG_FIELDS.KINDS}.${key}.aliases must be an array of strings`,\n };\n }\n if (\n aliases.length !== expected.aliases.length || aliases.some((alias, index) => alias !== expected.aliases[index])\n ) {\n return {\n ok: false,\n error:\n `${SPEC_TREE_SECTION}.${SPEC_TREE_CONFIG_FIELDS.KINDS}.${key}.aliases must match the registry definition`,\n };\n }\n entries.push([key, expected]);\n }\n\n const kinds = Object.fromEntries(entries) as SpecTreeConfig[\"kinds\"];\n return { ok: true, value: { kinds } };\n}\n\nexport const specTreeConfigDescriptor: ConfigDescriptor<SpecTreeConfig> = {\n section: SPEC_TREE_SECTION,\n defaults: buildDefaults(),\n validate,\n};\n","import type { AdapterConfig, ScopeResult } from \"../types\";\n\nexport function eslintAdapter(scope: ScopeResult, config: AdapterConfig): readonly string[] {\n return scope.excluded.flatMap((entry) => [config.ignoreFlag, entry.path]);\n}\n","import type { AdapterConfig, ScopeResult } from \"../types\";\n\nexport function knipAdapter(scope: ScopeResult, config: AdapterConfig): readonly string[] {\n return scope.excluded.flatMap((entry) => [config.ignoreFlag, entry.path]);\n}\n","import type { AdapterConfig, ScopeResult } from \"../types\";\n\nexport function madgeAdapter(scope: ScopeResult, config: AdapterConfig): readonly string[] {\n return scope.excluded.flatMap((entry) => [config.ignoreFlag, entry.path]);\n}\n","import type { AdapterConfig, ScopeResult } from \"../types\";\n\nexport function markdownlintAdapter(scope: ScopeResult, config: AdapterConfig): readonly string[] {\n return scope.excluded.flatMap((entry) => [config.ignoreFlag, entry.path]);\n}\n","import type { AdapterConfig, ScopeResult } from \"../types\";\n\nexport function pytestAdapter(scope: ScopeResult, config: AdapterConfig): readonly string[] {\n return scope.excluded.flatMap((entry) => [config.ignoreFlag, entry.path]);\n}\n","import type { AdapterConfig, ScopeResult } from \"../types\";\n\nexport function tscAdapter(scope: ScopeResult, config: AdapterConfig): readonly string[] {\n return scope.excluded.flatMap((entry) => [config.ignoreFlag, entry.path]);\n}\n","import type { AdapterConfig, ScopeResult } from \"../types\";\n\nexport function vitestAdapter(scope: ScopeResult, config: AdapterConfig): readonly string[] {\n return scope.excluded.flatMap((entry) => [config.ignoreFlag, entry.path]);\n}\n","import type { ScopeResult } from \"../types\";\nimport type { AdapterConfig, ToolAdapterFn, ToolAdaptersConfig } from \"../types\";\n\nimport { eslintAdapter } from \"./eslint\";\nimport { knipAdapter } from \"./knip\";\nimport { madgeAdapter } from \"./madge\";\nimport { markdownlintAdapter } from \"./markdownlint\";\nimport { pytestAdapter } from \"./pytest\";\nimport { tscAdapter } from \"./tsc\";\nimport { vitestAdapter } from \"./vitest\";\n\nexport type { AdapterConfig, ToolAdapterFn, ToolAdaptersConfig };\n\nexport const TOOL_DEFAULT_FLAGS: Readonly<Record<string, string>> = {\n eslint: \"--ignore-pattern\",\n tsc: \"--exclude\",\n madge: \"--exclude\",\n knip: \"--exclude\",\n markdownlint: \"--ignore\",\n pytest: \"--ignore\",\n vitest: \"--exclude\",\n};\n\nconst ADAPTER_MAP: Readonly<Record<string, ToolAdapterFn>> = {\n eslint: eslintAdapter,\n tsc: tscAdapter,\n madge: madgeAdapter,\n knip: knipAdapter,\n markdownlint: markdownlintAdapter,\n pytest: pytestAdapter,\n vitest: vitestAdapter,\n};\n\nexport const REGISTERED_TOOL_NAMES: readonly string[] = Object.keys(ADAPTER_MAP);\n\nexport function toToolArguments(\n scope: ScopeResult,\n toolName: string,\n config: ToolAdaptersConfig,\n): readonly string[] {\n const adapter = ADAPTER_MAP[toolName];\n if (adapter === undefined) {\n throw new Error(\n `Unknown tool \"${toolName}\". Registered tools: ${REGISTERED_TOOL_NAMES.join(\", \")}`,\n );\n }\n const adapterConfig = config[toolName];\n if (adapterConfig === undefined) {\n throw new Error(\n `No adapter config for tool \"${toolName}\". Registered tools: ${REGISTERED_TOOL_NAMES.join(\", \")}`,\n );\n }\n return adapter(scope, adapterConfig);\n}\n","import { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport const IGNORE_SOURCE_FILENAME_DEFAULT = \"EXCLUDE\";\n\nexport type IgnoreSourceReaderConfig = {\n readonly ignoreSourceFilename: string;\n readonly specTreeRootSegment: string;\n};\n\nexport type IgnoreSourceEntry = {\n readonly segment: string;\n readonly lineNumber: number;\n};\n\nexport type IgnoreSourceReader = {\n isUnderIgnoreSource(relativePath: string): boolean;\n entries(): readonly IgnoreSourceEntry[];\n matchedEntry(relativePath: string): IgnoreSourceEntry | undefined;\n};\n\nexport const EMPTY_IGNORE_READER: IgnoreSourceReader = {\n isUnderIgnoreSource(): boolean {\n return false;\n },\n entries(): readonly IgnoreSourceEntry[] {\n return [];\n },\n matchedEntry(): IgnoreSourceEntry | undefined {\n return undefined;\n },\n};\n\nconst COMMENT_PREFIX = \"#\";\n\nfunction isNodeError(err: unknown): err is NodeJS.ErrnoException {\n return err instanceof Error && \"code\" in err;\n}\n\nfunction validateEntry(entry: string, lineNumber: number): void {\n if (entry.startsWith(\"/\")) {\n throw new Error(\n `Invalid ignore-source entry \"${entry}\" at line ${lineNumber}: absolute paths are not allowed`,\n );\n }\n const parts = entry.split(\"/\");\n for (const part of parts) {\n if (part === \"..\" || part === \".\" || part === \"\") {\n throw new Error(\n `Invalid ignore-source entry \"${entry}\" at line ${lineNumber}: empty segments, traversal sequences, and dot-relative prefixes are not allowed`,\n );\n }\n }\n}\n\nexport function createIgnoreSourceReader(\n projectRoot: string,\n config: IgnoreSourceReaderConfig,\n): IgnoreSourceReader {\n const { ignoreSourceFilename, specTreeRootSegment } = config;\n const filePath = join(projectRoot, specTreeRootSegment, ignoreSourceFilename);\n\n let content: string;\n try {\n content = readFileSync(filePath, \"utf8\");\n } catch (err) {\n if (isNodeError(err) && err.code === \"ENOENT\") {\n content = \"\";\n } else {\n throw err;\n }\n }\n\n const parsedEntries: IgnoreSourceEntry[] = [];\n const lines = content.split(\"\\n\");\n for (let i = 0; i < lines.length; i++) {\n const trimmed = lines[i]!.trim();\n if (trimmed.length === 0 || trimmed.startsWith(COMMENT_PREFIX)) continue;\n const lineNumber = i + 1;\n validateEntry(trimmed, lineNumber);\n parsedEntries.push({ segment: trimmed, lineNumber });\n }\n\n const prefixes = parsedEntries.map((e) => `${specTreeRootSegment}/${e.segment}/`);\n\n return {\n isUnderIgnoreSource(relativePath: string): boolean {\n return prefixes.some((prefix) => relativePath.startsWith(prefix));\n },\n entries(): readonly IgnoreSourceEntry[] {\n return parsedEntries;\n },\n matchedEntry(relativePath: string): IgnoreSourceEntry | undefined {\n return parsedEntries.find((entry) => relativePath.startsWith(`${specTreeRootSegment}/${entry.segment}/`));\n },\n };\n}\n","import type { ArtifactDirectoryConfig, LayerDecision } from \"../types\";\n\nexport const ARTIFACT_DIRECTORIES_DEFAULT = [\n \"node_modules\",\n \"dist\",\n \"build\",\n \".next\",\n \".source\",\n \".git\",\n \"out\",\n \"coverage\",\n] as const satisfies readonly string[];\n\nexport const ARTIFACT_DIRECTORY_LAYER = \"artifact-directory\";\nconst LAYER = ARTIFACT_DIRECTORY_LAYER;\n\nexport function artifactDirectoryPredicate(\n path: string,\n config: ArtifactDirectoryConfig,\n): LayerDecision {\n const segments = path.split(\"/\");\n for (const segment of segments) {\n if (config.artifactDirectories.includes(segment)) {\n return { matched: true, layer: LAYER, detail: segment };\n }\n }\n return { matched: false, layer: LAYER };\n}\n","import type { HiddenPrefixConfig, LayerDecision } from \"../types\";\n\nexport const HIDDEN_PREFIX_DEFAULT = \".\";\n\nexport const HIDDEN_PREFIX_LAYER = \"hidden-prefix\";\nconst LAYER = HIDDEN_PREFIX_LAYER;\n\nexport function hiddenPrefixPredicate(path: string, config: HiddenPrefixConfig): LayerDecision {\n const segments = path.split(\"/\");\n const basename = segments[segments.length - 1] ?? \"\";\n const matched = basename.startsWith(config.hiddenPrefix);\n return { matched, layer: LAYER };\n}\n","import type { ConfigDescriptor, Result } from \"@/config/types\";\nimport { SPEC_TREE_CONFIG } from \"@/lib/spec-tree/config\";\n\nimport { TOOL_DEFAULT_FLAGS } from \"./adapters\";\nimport { IGNORE_SOURCE_FILENAME_DEFAULT } from \"./ignore-source\";\nimport { ARTIFACT_DIRECTORIES_DEFAULT } from \"./predicates/artifact-directory\";\nimport { HIDDEN_PREFIX_DEFAULT } from \"./predicates/hidden-prefix\";\nimport type { ScopeResolverConfig, ToolAdaptersConfig } from \"./types\";\n\nexport const FILE_INCLUSION_SECTION = \"fileInclusion\";\n\nexport const FILE_INCLUSION_CONFIG_FIELDS = {\n SCOPE: \"scope\",\n TOOLS: \"tools\",\n ARTIFACT_DIRECTORIES: \"artifactDirectories\",\n HIDDEN_PREFIX: \"hiddenPrefix\",\n IGNORE_SOURCE_FILENAME: \"ignoreSourceFilename\",\n SPEC_TREE_ROOT_SEGMENT: \"specTreeRootSegment\",\n IGNORE_FLAG: \"ignoreFlag\",\n} as const;\n\nexport type FileInclusionConfig = {\n readonly scope: ScopeResolverConfig;\n readonly tools: ToolAdaptersConfig;\n};\n\nexport const DEFAULT_SCOPE_CONFIG: ScopeResolverConfig = {\n artifactDirectories: ARTIFACT_DIRECTORIES_DEFAULT,\n hiddenPrefix: HIDDEN_PREFIX_DEFAULT,\n ignoreSourceFilename: IGNORE_SOURCE_FILENAME_DEFAULT,\n specTreeRootSegment: SPEC_TREE_CONFIG.ROOT_DIRECTORY,\n};\n\nexport const DEFAULT_TOOLS_CONFIG: ToolAdaptersConfig = Object.fromEntries(\n Object.entries(TOOL_DEFAULT_FLAGS).map(([name, flag]) => [name, { ignoreFlag: flag }]),\n);\n\nconst defaults: FileInclusionConfig = {\n scope: DEFAULT_SCOPE_CONFIG,\n tools: DEFAULT_TOOLS_CONFIG,\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction validateStringField(\n section: string,\n field: string,\n value: unknown,\n): Result<string> {\n if (typeof value !== \"string\" || value.length === 0) {\n return { ok: false, error: `${section}.${field} must be a non-empty string` };\n }\n return { ok: true, value };\n}\n\nfunction validateStringArrayField(\n section: string,\n field: string,\n value: unknown,\n): Result<readonly string[]> {\n if (!Array.isArray(value) || value.some((entry) => typeof entry !== \"string\" || entry.length === 0)) {\n return { ok: false, error: `${section}.${field} must be an array of non-empty strings` };\n }\n return { ok: true, value };\n}\n\nfunction rejectUnknownFields(\n section: string,\n value: Record<string, unknown>,\n allowed: ReadonlySet<string>,\n): Result<undefined> {\n const unknownField = Object.keys(value).find((field) => !allowed.has(field));\n if (unknownField !== undefined) {\n return { ok: false, error: `${section}.${unknownField} is not a recognized config field` };\n }\n return { ok: true, value: undefined };\n}\n\nfunction validateScope(raw: unknown): Result<ScopeResolverConfig> {\n if (!isRecord(raw)) {\n return {\n ok: false,\n error: `${FILE_INCLUSION_SECTION}.${FILE_INCLUSION_CONFIG_FIELDS.SCOPE} must be an object`,\n };\n }\n\n const allowed = new Set<string>([\n FILE_INCLUSION_CONFIG_FIELDS.ARTIFACT_DIRECTORIES,\n FILE_INCLUSION_CONFIG_FIELDS.HIDDEN_PREFIX,\n FILE_INCLUSION_CONFIG_FIELDS.IGNORE_SOURCE_FILENAME,\n FILE_INCLUSION_CONFIG_FIELDS.SPEC_TREE_ROOT_SEGMENT,\n ]);\n const scopeUnknownFieldResult = rejectUnknownFields(\n `${FILE_INCLUSION_SECTION}.${FILE_INCLUSION_CONFIG_FIELDS.SCOPE}`,\n raw,\n allowed,\n );\n if (!scopeUnknownFieldResult.ok) return scopeUnknownFieldResult;\n\n const artifactDirectoriesRaw = raw[FILE_INCLUSION_CONFIG_FIELDS.ARTIFACT_DIRECTORIES];\n const artifactDirectories = artifactDirectoriesRaw === undefined\n ? { ok: true as const, value: DEFAULT_SCOPE_CONFIG.artifactDirectories }\n : validateStringArrayField(\n `${FILE_INCLUSION_SECTION}.${FILE_INCLUSION_CONFIG_FIELDS.SCOPE}`,\n FILE_INCLUSION_CONFIG_FIELDS.ARTIFACT_DIRECTORIES,\n artifactDirectoriesRaw,\n );\n if (!artifactDirectories.ok) return artifactDirectories;\n\n const hiddenPrefixRaw = raw[FILE_INCLUSION_CONFIG_FIELDS.HIDDEN_PREFIX];\n const hiddenPrefix = hiddenPrefixRaw === undefined\n ? { ok: true as const, value: DEFAULT_SCOPE_CONFIG.hiddenPrefix }\n : validateStringField(\n `${FILE_INCLUSION_SECTION}.${FILE_INCLUSION_CONFIG_FIELDS.SCOPE}`,\n FILE_INCLUSION_CONFIG_FIELDS.HIDDEN_PREFIX,\n hiddenPrefixRaw,\n );\n if (!hiddenPrefix.ok) return hiddenPrefix;\n\n const ignoreSourceFilenameRaw = raw[FILE_INCLUSION_CONFIG_FIELDS.IGNORE_SOURCE_FILENAME];\n const ignoreSourceFilename = ignoreSourceFilenameRaw === undefined\n ? { ok: true as const, value: DEFAULT_SCOPE_CONFIG.ignoreSourceFilename }\n : validateStringField(\n `${FILE_INCLUSION_SECTION}.${FILE_INCLUSION_CONFIG_FIELDS.SCOPE}`,\n FILE_INCLUSION_CONFIG_FIELDS.IGNORE_SOURCE_FILENAME,\n ignoreSourceFilenameRaw,\n );\n if (!ignoreSourceFilename.ok) return ignoreSourceFilename;\n\n const specTreeRootSegmentRaw = raw[FILE_INCLUSION_CONFIG_FIELDS.SPEC_TREE_ROOT_SEGMENT];\n const specTreeRootSegment = specTreeRootSegmentRaw === undefined\n ? { ok: true as const, value: DEFAULT_SCOPE_CONFIG.specTreeRootSegment }\n : validateStringField(\n `${FILE_INCLUSION_SECTION}.${FILE_INCLUSION_CONFIG_FIELDS.SCOPE}`,\n FILE_INCLUSION_CONFIG_FIELDS.SPEC_TREE_ROOT_SEGMENT,\n specTreeRootSegmentRaw,\n );\n if (!specTreeRootSegment.ok) return specTreeRootSegment;\n\n return {\n ok: true,\n value: {\n artifactDirectories: artifactDirectories.value,\n hiddenPrefix: hiddenPrefix.value,\n ignoreSourceFilename: ignoreSourceFilename.value,\n specTreeRootSegment: specTreeRootSegment.value,\n },\n };\n}\n\nfunction validateTools(raw: unknown): Result<ToolAdaptersConfig> {\n if (!isRecord(raw)) {\n return {\n ok: false,\n error: `${FILE_INCLUSION_SECTION}.${FILE_INCLUSION_CONFIG_FIELDS.TOOLS} must be an object`,\n };\n }\n\n const tools: Record<string, { readonly ignoreFlag: string }> = { ...DEFAULT_TOOLS_CONFIG };\n for (const [toolName, adapterRaw] of Object.entries(raw)) {\n const defaultToolConfig = DEFAULT_TOOLS_CONFIG[toolName];\n if (defaultToolConfig === undefined) {\n return {\n ok: false,\n error: `${FILE_INCLUSION_SECTION}.${FILE_INCLUSION_CONFIG_FIELDS.TOOLS}.${toolName} is not a recognized tool`,\n };\n }\n if (!isRecord(adapterRaw)) {\n return {\n ok: false,\n error: `${FILE_INCLUSION_SECTION}.${FILE_INCLUSION_CONFIG_FIELDS.TOOLS}.${toolName} must be an object`,\n };\n }\n const toolPath = `${FILE_INCLUSION_SECTION}.${FILE_INCLUSION_CONFIG_FIELDS.TOOLS}.${toolName}`;\n const adapterUnknownFieldResult = rejectUnknownFields(\n toolPath,\n adapterRaw,\n new Set<string>([FILE_INCLUSION_CONFIG_FIELDS.IGNORE_FLAG]),\n );\n if (!adapterUnknownFieldResult.ok) return adapterUnknownFieldResult;\n const ignoreFlagRaw = adapterRaw[FILE_INCLUSION_CONFIG_FIELDS.IGNORE_FLAG];\n const ignoreFlag = ignoreFlagRaw === undefined\n ? { ok: true as const, value: defaultToolConfig.ignoreFlag }\n : validateStringField(toolPath, FILE_INCLUSION_CONFIG_FIELDS.IGNORE_FLAG, ignoreFlagRaw);\n if (!ignoreFlag.ok) return ignoreFlag;\n tools[toolName] = { ignoreFlag: ignoreFlag.value };\n }\n\n return { ok: true, value: tools };\n}\n\nfunction validate(value: unknown): Result<FileInclusionConfig> {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return { ok: false, error: `${FILE_INCLUSION_SECTION} section must be an object` };\n }\n const candidate = value as Record<string, unknown>;\n const sectionUnknownFieldResult = rejectUnknownFields(\n FILE_INCLUSION_SECTION,\n candidate,\n new Set<string>([FILE_INCLUSION_CONFIG_FIELDS.SCOPE, FILE_INCLUSION_CONFIG_FIELDS.TOOLS]),\n );\n if (!sectionUnknownFieldResult.ok) return sectionUnknownFieldResult;\n\n const scopeRaw = candidate[FILE_INCLUSION_CONFIG_FIELDS.SCOPE];\n const scope = scopeRaw === undefined\n ? { ok: true as const, value: DEFAULT_SCOPE_CONFIG }\n : validateScope(scopeRaw);\n if (!scope.ok) return scope;\n\n const toolsRaw = candidate[FILE_INCLUSION_CONFIG_FIELDS.TOOLS];\n const tools = toolsRaw === undefined\n ? { ok: true as const, value: DEFAULT_TOOLS_CONFIG }\n : validateTools(toolsRaw);\n if (!tools.ok) return tools;\n\n return {\n ok: true,\n value: {\n [FILE_INCLUSION_CONFIG_FIELDS.SCOPE]: scope.value,\n [FILE_INCLUSION_CONFIG_FIELDS.TOOLS]: tools.value,\n },\n };\n}\n\nexport const fileInclusionConfigDescriptor: ConfigDescriptor<FileInclusionConfig> = {\n section: FILE_INCLUSION_SECTION,\n defaults,\n validate,\n};\n","import type { ConfigDescriptor, Result } from \"@/config/types\";\n\nexport const PRECOMMIT_SECTION = \"precommit\";\n\nexport interface PrecommitConfig {\n readonly sourceDirs: readonly string[];\n readonly testPattern: string;\n}\n\nexport const PRECOMMIT_DEFAULTS: PrecommitConfig = {\n sourceDirs: [\"src/\"],\n testPattern: \".test.ts\",\n};\n\nfunction validate(value: unknown): Result<PrecommitConfig> {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return { ok: false, error: `${PRECOMMIT_SECTION} section must be an object` };\n }\n const candidate = value as Record<string, unknown>;\n\n const sourceDirs = candidate[\"sourceDirs\"] ?? PRECOMMIT_DEFAULTS.sourceDirs;\n if (!Array.isArray(sourceDirs) || !sourceDirs.every((x) => typeof x === \"string\" && x.length > 0)) {\n return {\n ok: false,\n error: `${PRECOMMIT_SECTION}.sourceDirs must be a non-empty array of non-empty strings`,\n };\n }\n\n const testPattern = candidate[\"testPattern\"] ?? PRECOMMIT_DEFAULTS.testPattern;\n if (typeof testPattern !== \"string\" || testPattern.length === 0) {\n return {\n ok: false,\n error: `${PRECOMMIT_SECTION}.testPattern must be a non-empty string`,\n };\n }\n\n return {\n ok: true,\n value: {\n sourceDirs: sourceDirs as readonly string[],\n testPattern: testPattern as string,\n },\n };\n}\n\nexport const precommitConfigDescriptor: ConfigDescriptor<PrecommitConfig> = {\n section: PRECOMMIT_SECTION,\n defaults: PRECOMMIT_DEFAULTS,\n validate,\n};\n","import { type PathFilterConfig, validatePathFilterConfig } from \"@/config/primitives/path-filter\";\nimport type { ConfigDescriptor, Result } from \"@/config/types\";\n\nexport const TESTING_SECTION = \"testing\";\n\nexport const TESTING_CONFIG_FIELDS = {\n PASSING_SCOPE: \"passingScope\",\n} as const;\n\nexport interface TestingConfig {\n readonly passingScope: PathFilterConfig;\n}\n\nconst DEFAULT_PASSING_SCOPE = resolveDefaultPassingScope();\n\nconst defaults: TestingConfig = {\n passingScope: DEFAULT_PASSING_SCOPE,\n};\n\nfunction resolveDefaultPassingScope(): PathFilterConfig {\n const result = validatePathFilterConfig(\n {},\n `${TESTING_SECTION}.${TESTING_CONFIG_FIELDS.PASSING_SCOPE}`,\n );\n if (!result.ok) {\n throw new Error(result.error);\n }\n return result.value;\n}\n\nfunction validate(value: unknown): Result<TestingConfig> {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return { ok: false, error: `${TESTING_SECTION} section must be an object` };\n }\n\n const candidate = value as Record<string, unknown>;\n const passingScopeRaw = candidate[TESTING_CONFIG_FIELDS.PASSING_SCOPE];\n // Null is an explicit invalid value; only an omitted field receives defaults.\n if (passingScopeRaw === undefined) {\n return { ok: true, value: defaults };\n }\n\n const passingScopeResult = validatePathFilterConfig(\n passingScopeRaw,\n `${TESTING_SECTION}.${TESTING_CONFIG_FIELDS.PASSING_SCOPE}`,\n );\n if (!passingScopeResult.ok) return passingScopeResult;\n\n return {\n ok: true,\n value: {\n passingScope: passingScopeResult.value,\n },\n };\n}\n\nexport const testingConfigDescriptor: ConfigDescriptor<TestingConfig> = {\n section: TESTING_SECTION,\n defaults,\n validate,\n};\n","import type { ConfigDescriptor, Result } from \"@/config/types\";\n\nexport const LITERAL_SECTION = \"literal\";\nexport const DEFAULT_MIN_STRING_LENGTH = 4;\nexport const DEFAULT_MIN_NUMBER_DIGITS = 4;\nexport const LEGACY_LITERAL_ALLOWLIST_FIELD = \"allowlist\";\nexport const LEGACY_LITERAL_ALLOWLIST_ERROR =\n \"validation.literal.values.allowlist is no longer valid; move its contents up one level to validation.literal.values.{presets,include,exclude}\";\n\nexport interface LiteralValueAllowlistConfig {\n readonly presets?: readonly string[];\n readonly include?: readonly string[];\n readonly exclude?: readonly string[];\n}\n\nexport interface LiteralConfig extends LiteralValueAllowlistConfig {\n readonly minStringLength: number;\n readonly minNumberDigits: number;\n}\n\nexport const PRESET_NAMES = {\n WEB: \"web\",\n} as const;\n\nexport type PresetName = (typeof PRESET_NAMES)[keyof typeof PRESET_NAMES];\n\nexport const WEB_PRESET_TOKENS = [\n \"GET\",\n \"POST\",\n \"PUT\",\n \"DELETE\",\n \"PATCH\",\n \"Content-Type\",\n \"Authorization\",\n \"Accept\",\n \"status\",\n \"message\",\n \"error\",\n \"data\",\n \"class\",\n \"id\",\n \"href\",\n \"src\",\n \"type\",\n \"name\",\n \"value\",\n] as const;\n\nexport type WebPresetToken = (typeof WEB_PRESET_TOKENS)[number];\n\nconst WEB_PRESET: ReadonlySet<WebPresetToken> = new Set(WEB_PRESET_TOKENS);\n\nconst PRESET_REGISTRY: ReadonlyMap<PresetName, ReadonlySet<string>> = new Map([\n [PRESET_NAMES.WEB, WEB_PRESET],\n]);\n\nexport function resolveAllowlist(config: LiteralValueAllowlistConfig): ReadonlySet<string> {\n const effective = new Set<string>();\n\n for (const presetId of config.presets ?? []) {\n const preset = PRESET_REGISTRY.get(presetId as PresetName);\n if (preset !== undefined) {\n for (const v of preset) effective.add(v);\n }\n }\n\n for (const v of config.include ?? []) {\n effective.add(v);\n }\n\n for (const v of config.exclude ?? []) {\n effective.delete(v);\n }\n\n return effective;\n}\n\nexport const LITERAL_DEFAULTS: LiteralConfig = {\n minStringLength: DEFAULT_MIN_STRING_LENGTH,\n minNumberDigits: DEFAULT_MIN_NUMBER_DIGITS,\n};\n\nfunction validate(value: unknown): Result<LiteralConfig> {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return { ok: false, error: `${LITERAL_SECTION} section must be an object` };\n }\n const candidate = value as Record<string, unknown>;\n\n if (candidate[LEGACY_LITERAL_ALLOWLIST_FIELD] !== undefined) {\n return { ok: false, error: LEGACY_LITERAL_ALLOWLIST_ERROR };\n }\n\n const presets = candidate[\"presets\"];\n if (presets !== undefined) {\n if (!Array.isArray(presets) || !presets.every((x) => typeof x === \"string\")) {\n return { ok: false, error: `${LITERAL_SECTION}.presets must be an array of strings` };\n }\n for (const id of presets as string[]) {\n if (!PRESET_REGISTRY.has(id as PresetName)) {\n return { ok: false, error: `${LITERAL_SECTION}.presets: unrecognized preset \"${id}\"` };\n }\n }\n }\n\n const include = candidate[\"include\"];\n if (include !== undefined && (!Array.isArray(include) || !include.every((x) => typeof x === \"string\"))) {\n return { ok: false, error: `${LITERAL_SECTION}.include must be an array of strings` };\n }\n\n const exclude = candidate[\"exclude\"];\n if (exclude !== undefined && (!Array.isArray(exclude) || !exclude.every((x) => typeof x === \"string\"))) {\n return { ok: false, error: `${LITERAL_SECTION}.exclude must be an array of strings` };\n }\n\n const minStringLength = candidate[\"minStringLength\"] ?? LITERAL_DEFAULTS.minStringLength;\n if (typeof minStringLength !== \"number\" || !Number.isInteger(minStringLength) || minStringLength < 0) {\n return {\n ok: false,\n error: `${LITERAL_SECTION}.minStringLength must be a non-negative integer`,\n };\n }\n\n const minNumberDigits = candidate[\"minNumberDigits\"] ?? LITERAL_DEFAULTS.minNumberDigits;\n if (typeof minNumberDigits !== \"number\" || !Number.isInteger(minNumberDigits) || minNumberDigits < 0) {\n return {\n ok: false,\n error: `${LITERAL_SECTION}.minNumberDigits must be a non-negative integer`,\n };\n }\n\n return {\n ok: true,\n value: {\n presets: presets as readonly string[] | undefined,\n include: include as readonly string[] | undefined,\n exclude: exclude as readonly string[] | undefined,\n minStringLength,\n minNumberDigits,\n },\n };\n}\n\nexport const literalConfigDescriptor: ConfigDescriptor<LiteralConfig> = {\n section: LITERAL_SECTION,\n defaults: LITERAL_DEFAULTS,\n validate,\n};\n","import { type PathFilterConfig, validatePathFilterConfig } from \"@/config/primitives/path-filter\";\nimport type { ConfigDescriptor, Result } from \"@/config/types\";\nimport {\n DEFAULT_MIN_NUMBER_DIGITS,\n DEFAULT_MIN_STRING_LENGTH,\n type LiteralConfig,\n literalConfigDescriptor,\n} from \"@/validation/literal/config\";\n\nexport const VALIDATION_SECTION = \"validation\";\nexport const VALIDATION_LITERAL_SUBSECTION = \"literal\";\nexport const VALIDATION_LITERAL_VALUES_SUBSECTION = \"values\";\nexport const VALIDATION_PATHS_SUBSECTION = \"paths\";\nexport const VALIDATION_KNIP_SUBSECTION = \"knip\";\nexport const VALIDATION_ENABLED_FIELD = \"enabled\";\nexport const VALIDATION_PATH_TOOL_SUBSECTIONS = {\n ESLINT: \"eslint\",\n TYPESCRIPT: \"typescript\",\n CIRCULAR: \"circular\",\n KNIP: \"knip\",\n MARKDOWN: \"markdown\",\n LITERAL: \"literal\",\n} as const;\n\nexport type ValidationPathToolSubsection =\n (typeof VALIDATION_PATH_TOOL_SUBSECTIONS)[keyof typeof VALIDATION_PATH_TOOL_SUBSECTIONS];\n\nexport type ValidationPathFilterConfig = PathFilterConfig;\n\nexport type ValidationToolPathConfig = Partial<Record<ValidationPathToolSubsection, ValidationPathFilterConfig>>;\n\nexport type ValidationPathConfig = ValidationPathFilterConfig & ValidationToolPathConfig;\n\nexport interface ValidationLiteralConfig {\n readonly enabled: boolean;\n readonly values: LiteralConfig;\n}\n\nexport interface ValidationKnipConfig {\n readonly enabled: boolean;\n}\n\nexport interface ValidationConfig {\n readonly paths: ValidationPathConfig;\n readonly literal: ValidationLiteralConfig;\n readonly knip: ValidationKnipConfig;\n}\n\nconst defaults: ValidationConfig = {\n paths: {},\n literal: {\n enabled: true,\n values: {\n minStringLength: DEFAULT_MIN_STRING_LENGTH,\n minNumberDigits: DEFAULT_MIN_NUMBER_DIGITS,\n },\n },\n knip: {\n enabled: false,\n },\n};\n\nfunction validatePaths(raw: unknown): Result<ValidationPathConfig> {\n const basePath = `${VALIDATION_SECTION}.${VALIDATION_PATHS_SUBSECTION}`;\n const baseResult = validatePathFilterConfig(raw, basePath);\n if (!baseResult.ok) return baseResult;\n const candidate = raw as Record<string, unknown>;\n const toolEntries = Object.values(VALIDATION_PATH_TOOL_SUBSECTIONS).map((tool) => {\n const toolRaw = candidate[tool];\n if (toolRaw === undefined) return [tool, undefined] as const;\n const toolResult = validatePathFilterConfig(toolRaw, `${basePath}.${tool}`);\n return [tool, toolResult] as const;\n });\n const toolConfig: ValidationToolPathConfig = {};\n for (const [tool, toolResult] of toolEntries) {\n if (toolResult === undefined) continue;\n if (!toolResult.ok) return toolResult;\n toolConfig[tool] = toolResult.value;\n }\n return { ok: true, value: { ...baseResult.value, ...toolConfig } };\n}\n\nfunction validateLiteral(raw: unknown): Result<ValidationLiteralConfig> {\n if (typeof raw !== \"object\" || raw === null || Array.isArray(raw)) {\n return {\n ok: false,\n error: `${VALIDATION_SECTION}.${VALIDATION_LITERAL_SUBSECTION} must be an object`,\n };\n }\n const candidate = raw as Record<string, unknown>;\n const enabledRaw = candidate[VALIDATION_ENABLED_FIELD] ?? defaults.literal.enabled;\n if (typeof enabledRaw !== \"boolean\") {\n return {\n ok: false,\n error: `${VALIDATION_SECTION}.${VALIDATION_LITERAL_SUBSECTION}.${VALIDATION_ENABLED_FIELD} must be a boolean`,\n };\n }\n const valuesRaw = candidate[VALIDATION_LITERAL_VALUES_SUBSECTION] ?? {};\n const valuesResult = literalConfigDescriptor.validate(valuesRaw);\n if (!valuesResult.ok) {\n return {\n ok: false,\n error:\n `${VALIDATION_SECTION}.${VALIDATION_LITERAL_SUBSECTION}.${VALIDATION_LITERAL_VALUES_SUBSECTION}: ${valuesResult.error}`,\n };\n }\n return { ok: true, value: { enabled: enabledRaw, values: valuesResult.value } };\n}\n\nfunction validateKnip(raw: unknown): Result<ValidationKnipConfig> {\n if (typeof raw !== \"object\" || raw === null || Array.isArray(raw)) {\n return {\n ok: false,\n error: `${VALIDATION_SECTION}.${VALIDATION_KNIP_SUBSECTION} must be an object`,\n };\n }\n const candidate = raw as Record<string, unknown>;\n const enabledRaw = candidate[VALIDATION_ENABLED_FIELD] ?? defaults.knip.enabled;\n if (typeof enabledRaw !== \"boolean\") {\n return {\n ok: false,\n error: `${VALIDATION_SECTION}.${VALIDATION_KNIP_SUBSECTION}.${VALIDATION_ENABLED_FIELD} must be a boolean`,\n };\n }\n return { ok: true, value: { enabled: enabledRaw } };\n}\n\nfunction validate(value: unknown): Result<ValidationConfig> {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return { ok: false, error: `${VALIDATION_SECTION} section must be an object` };\n }\n const candidate = value as Record<string, unknown>;\n\n const pathsRaw = candidate[VALIDATION_PATHS_SUBSECTION] ?? {};\n const pathsResult = validatePaths(pathsRaw);\n if (!pathsResult.ok) return pathsResult;\n\n const literalRaw = candidate[VALIDATION_LITERAL_SUBSECTION] ?? {};\n const literalResult = validateLiteral(literalRaw);\n if (!literalResult.ok) return literalResult;\n\n const knipRaw = candidate[VALIDATION_KNIP_SUBSECTION] ?? {};\n const knipResult = validateKnip(knipRaw);\n if (!knipResult.ok) return knipResult;\n\n return { ok: true, value: { paths: pathsResult.value, literal: literalResult.value, knip: knipResult.value } };\n}\n\nexport const validationConfigDescriptor: ConfigDescriptor<ValidationConfig> = {\n section: VALIDATION_SECTION,\n defaults,\n validate,\n};\n","import { agentEnvironmentConfigDescriptor } from \"@/domains/agent-environment/config\";\nimport { auditConfigDescriptor } from \"@/domains/audit/config\";\nimport { fileInclusionConfigDescriptor } from \"@/lib/file-inclusion/config\";\nimport { precommitConfigDescriptor } from \"@/lib/precommit/config\";\nimport { specTreeConfigDescriptor } from \"@/lib/spec-tree/config\";\nimport { testingConfigDescriptor } from \"@/testing/config\";\nimport { validationConfigDescriptor } from \"@/validation/config/descriptor\";\n\nimport type { ConfigDescriptor } from \"./types\";\n\nexport const productionRegistry: readonly ConfigDescriptor<unknown>[] = [\n specTreeConfigDescriptor,\n validationConfigDescriptor,\n testingConfigDescriptor,\n fileInclusionConfigDescriptor,\n precommitConfigDescriptor,\n agentEnvironmentConfigDescriptor,\n auditConfigDescriptor,\n] as const;\n","import { createHash } from \"node:crypto\";\n\nimport type { Result } from \"./types\";\n\nexport type DescriptorJsonValue =\n | string\n | number\n | boolean\n | null\n | readonly DescriptorJsonValue[]\n | { readonly [key: string]: DescriptorJsonValue };\n\nexport type DescriptorSectionDigest = {\n readonly canonicalJson: string;\n readonly sha256: string;\n};\n\nconst DEFAULT_DESCRIPTOR_PATH = \"descriptor section\";\nconst SHA256_ALGORITHM = \"sha256\";\nconst UTF8_ENCODING = \"utf8\";\nconst HEX_ENCODING = \"hex\";\n\ntype JsonRecord = { readonly [key: string]: DescriptorJsonValue };\n\nexport function canonicalDescriptorJson(\n value: unknown,\n path = DEFAULT_DESCRIPTOR_PATH,\n): Result<string> {\n const normalized = normalizeDescriptorJsonValue(value, path, new WeakSet<object>());\n if (!normalized.ok) return normalized;\n\n return { ok: true, value: JSON.stringify(normalized.value) };\n}\n\nexport function digestDescriptorSection(\n value: unknown,\n path = DEFAULT_DESCRIPTOR_PATH,\n): Result<DescriptorSectionDigest> {\n const canonical = canonicalDescriptorJson(value, path);\n if (!canonical.ok) return canonical;\n\n const sha256 = createHash(SHA256_ALGORITHM)\n .update(Buffer.from(canonical.value, UTF8_ENCODING))\n .digest(HEX_ENCODING);\n\n return {\n ok: true,\n value: {\n canonicalJson: canonical.value,\n sha256,\n },\n };\n}\n\nfunction normalizeDescriptorJsonValue(\n value: unknown,\n path: string,\n seen: WeakSet<object>,\n): Result<DescriptorJsonValue> {\n switch (typeof value) {\n case \"string\":\n case \"boolean\":\n return { ok: true, value };\n case \"number\":\n return Number.isFinite(value)\n ? { ok: true, value }\n : { ok: false, error: `${path} must be a finite number` };\n case \"object\":\n if (value === null) return { ok: true, value };\n return normalizeObject(value, path, seen);\n case \"undefined\":\n case \"bigint\":\n case \"function\":\n case \"symbol\":\n return { ok: false, error: `${path} must be JSON-representable` };\n }\n}\n\nfunction normalizeObject(\n value: object,\n path: string,\n seen: WeakSet<object>,\n): Result<DescriptorJsonValue> {\n if (seen.has(value)) {\n return { ok: false, error: `${path} must not contain circular references` };\n }\n seen.add(value);\n\n const result = Array.isArray(value)\n ? normalizeArray(value, path, seen)\n : normalizeRecord(value, path, seen);\n\n // Keep `seen` as the current DFS path so sibling branches may share objects.\n seen.delete(value);\n return result;\n}\n\nfunction normalizeArray(\n value: readonly unknown[],\n path: string,\n seen: WeakSet<object>,\n): Result<readonly DescriptorJsonValue[]> {\n const normalized: DescriptorJsonValue[] = [];\n for (const [index, item] of value.entries()) {\n const itemResult = normalizeDescriptorJsonValue(item, `${path}[${index}]`, seen);\n if (!itemResult.ok) return itemResult;\n normalized.push(itemResult.value);\n }\n return { ok: true, value: normalized };\n}\n\nfunction normalizeRecord(\n value: object,\n path: string,\n seen: WeakSet<object>,\n): Result<JsonRecord> {\n if (!isPlainRecord(value)) {\n return { ok: false, error: `${path} must be a plain object` };\n }\n\n const keys = Reflect.ownKeys(value);\n if (keys.some((key) => typeof key === \"symbol\")) {\n return { ok: false, error: `${path} must not contain symbol keys` };\n }\n\n const record = value as Record<string, unknown>;\n const normalized: Record<string, DescriptorJsonValue> = {};\n for (const key of (keys as string[]).sort(compareUnicodeCodePointStrings)) {\n const child = normalizeDescriptorJsonValue(record[key], `${path}.${key}`, seen);\n if (!child.ok) return child;\n normalized[key] = child.value;\n }\n\n return { ok: true, value: normalized };\n}\n\nfunction isPlainRecord(value: object): boolean {\n const prototype = Object.getPrototypeOf(value);\n return prototype === null || prototype === Object.prototype;\n}\n\nfunction compareUnicodeCodePointStrings(left: string, right: string): number {\n const leftCodePoints = Array.from(left, (value) => value.codePointAt(0) ?? 0);\n const rightCodePoints = Array.from(right, (value) => value.codePointAt(0) ?? 0);\n const length = Math.min(leftCodePoints.length, rightCodePoints.length);\n\n for (let index = 0; index < length; index += 1) {\n const delta = leftCodePoints[index] - rightCodePoints[index];\n if (delta !== 0) return delta;\n }\n\n return leftCodePoints.length - rightCodePoints.length;\n}\n","import { CONFIG_FILE_FORMAT, DEFAULT_CONFIG_FILE_FORMAT, serializeConfigFileSections } from \"@/config/index\";\nimport type { Config } from \"@/config/types\";\n\nimport type { CliDeps, CliResult, DefaultsOptions } from \"./types\";\n\nexport function defaultsCommand(options: DefaultsOptions, deps: CliDeps): Promise<CliResult> {\n const config: Record<string, unknown> = {};\n for (const descriptor of deps.descriptors) {\n config[descriptor.section] = descriptor.defaults;\n }\n\n return Promise.resolve({\n stdout: formatConfig(config as Config, options.json === true),\n stderr: \"\",\n exitCode: 0,\n });\n}\n\nfunction formatConfig(config: Config, asJson: boolean): string {\n const format = asJson ? CONFIG_FILE_FORMAT.JSON : DEFAULT_CONFIG_FILE_FORMAT;\n const serialized = serializeConfigFileSections(format, config as Record<string, unknown>);\n if (!serialized.ok) {\n throw new Error(serialized.error);\n }\n return serialized.value;\n}\n","import { CONFIG_FILE_FORMAT, DEFAULT_CONFIG_FILE_FORMAT, serializeConfigFileSections } from \"@/config/index\";\nimport type { Config } from \"@/config/types\";\n\nimport type { CliDeps, CliResult, ShowOptions } from \"./types\";\n\nconst EXIT_CODE_ERROR = 1;\n\nexport async function showCommand(options: ShowOptions, deps: CliDeps): Promise<CliResult> {\n const productDir = deps.resolveProductDir();\n const result = await deps.resolveConfig(productDir);\n\n if (!result.ok) {\n return {\n stdout: \"\",\n stderr: `${result.error}\\n`,\n exitCode: EXIT_CODE_ERROR,\n };\n }\n\n return {\n stdout: formatConfig(result.value, options.json === true),\n stderr: \"\",\n exitCode: 0,\n };\n}\n\nfunction formatConfig(config: Config, asJson: boolean): string {\n const format = asJson ? CONFIG_FILE_FORMAT.JSON : DEFAULT_CONFIG_FILE_FORMAT;\n const serialized = serializeConfigFileSections(format, config as Record<string, unknown>);\n if (!serialized.ok) {\n throw new Error(serialized.error);\n }\n return serialized.value;\n}\n","import type { CliDeps, CliResult, ValidateOptions } from \"./types\";\n\nconst EXIT_CODE_INVALID = 1;\n\nexport const VALIDATE_SUCCESS_TOKENS = {\n PASSES_SUFFIX: \"passes every registered descriptor's validator.\",\n ABSENT_PREFIX: \"No config file\",\n ABSENT_SUBJECT: \"descriptor defaults\",\n} as const;\n\nfunction buildPresentSuccessLine(filename: string, productDir: string): string {\n return `${filename} at ${productDir} ${VALIDATE_SUCCESS_TOKENS.PASSES_SUFFIX}\\n`;\n}\n\nfunction buildAbsentSuccessLine(productDir: string): string {\n return `${VALIDATE_SUCCESS_TOKENS.ABSENT_PREFIX} at ${productDir}; `\n + `${VALIDATE_SUCCESS_TOKENS.ABSENT_SUBJECT} ${VALIDATE_SUCCESS_TOKENS.PASSES_SUFFIX}\\n`;\n}\n\nexport async function validateCommand(_options: ValidateOptions, deps: CliDeps): Promise<CliResult> {\n const productDir = deps.resolveProductDir();\n\n const fileResult = await deps.readProductConfigFile(productDir);\n if (!fileResult.ok) {\n return {\n stdout: \"\",\n stderr: `${fileResult.error}\\n`,\n exitCode: EXIT_CODE_INVALID,\n };\n }\n\n const result = deps.resolveConfigFromReadResult(fileResult.value, deps.descriptors);\n if (!result.ok) {\n return {\n stdout: \"\",\n stderr: `${result.error}\\n`,\n exitCode: EXIT_CODE_INVALID,\n };\n }\n\n const file = fileResult.value;\n const stdout = file.kind === \"ok\"\n ? buildPresentSuccessLine(file.file.filename, productDir)\n : buildAbsentSuccessLine(productDir);\n\n return { stdout, stderr: \"\", exitCode: 0 };\n}\n","import { execSync } from \"node:child_process\";\nimport { resolve } from \"node:path\";\n\nconst GIT_TOPLEVEL_CMD = \"git rev-parse --show-toplevel\";\nconst GIT_NOT_REPO_MARKER = \"not a git repository\";\n\nexport type ResolvedProductDir = {\n readonly productDir: string;\n readonly warning?: string;\n};\n\nexport function resolveProductDir(cwd: string = process.cwd()): ResolvedProductDir {\n const resolvedCwd = resolve(cwd);\n try {\n const stdout = execSync(GIT_TOPLEVEL_CMD, {\n cwd: resolvedCwd,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n encoding: \"utf8\",\n });\n const toplevel = stdout.trim();\n if (toplevel.length > 0) {\n return { productDir: resolve(toplevel) };\n }\n } catch {\n // fall through to cwd fallback\n }\n\n return {\n productDir: resolvedCwd,\n warning:\n `warning: ${resolvedCwd} is not inside a git worktree — falling back to the current working directory. ${GIT_NOT_REPO_MARKER}.`,\n };\n}\n","/**\n * Writes a CLI diagnostic warning to standard error.\n *\n * Short-circuits when no warning is present, so a descriptor passes an optional\n * warning straight through without a local guard. Appends a trailing newline so\n * the warning occupies its own terminal line.\n *\n * @param warning - The warning text, or `undefined` when there is nothing to emit.\n */\nexport function writeWarning(warning: string | undefined): void {\n if (warning === undefined) {\n return;\n }\n process.stderr.write(`${warning}\\n`);\n}\n","import type { Command } from \"commander\";\n\nimport { defaultsCommand } from \"@/commands/config/defaults\";\nimport { showCommand } from \"@/commands/config/show\";\nimport type { CliDeps, CliResult, ShowOptions, ValidateOptions } from \"@/commands/config/types\";\nimport { validateCommand } from \"@/commands/config/validate\";\nimport {\n CONFIG_FILE_FORMAT,\n DEFAULT_CONFIG_FILE_FORMAT,\n DEFAULT_CONFIG_FILENAME,\n readProductConfigFile,\n resolveConfig,\n resolveConfigFromReadResult,\n} from \"@/config/index\";\nimport { productionRegistry } from \"@/config/registry\";\n\nimport { resolveProductDir } from \"@/domains/config/root\";\nimport type { Domain } from \"@/domains/types\";\n\nimport { writeWarning } from \"./write-warning\";\n\nfunction buildDefaultDeps(): CliDeps {\n return {\n resolveConfig,\n readProductConfigFile,\n resolveConfigFromReadResult,\n resolveProductDir: (): string => {\n const resolved = resolveProductDir();\n writeWarning(resolved.warning);\n return resolved.productDir;\n },\n descriptors: productionRegistry,\n };\n}\n\nasync function emit(result: CliResult): Promise<never> {\n if (result.stdout.length > 0) {\n process.stdout.write(result.stdout);\n }\n if (result.stderr.length > 0) {\n process.stderr.write(result.stderr);\n }\n return process.exit(result.exitCode);\n}\n\nfunction registerConfigCommands(configCmd: Command): void {\n configCmd\n .command(\"show\")\n .description(\n `Print the resolved configuration as ${DEFAULT_CONFIG_FILE_FORMAT.toUpperCase()} `\n + `(or ${CONFIG_FILE_FORMAT.JSON.toUpperCase()} with --json)`,\n )\n .option(\"--json\", `Output as ${CONFIG_FILE_FORMAT.JSON.toUpperCase()}`)\n .action(async (options: ShowOptions) => {\n await emit(await showCommand(options, buildDefaultDeps()));\n });\n\n configCmd\n .command(\"validate\")\n .description(`Verify that ${DEFAULT_CONFIG_FILENAME} passes every registered descriptor's validator`)\n .action(async (options: ValidateOptions) => {\n await emit(await validateCommand(options, buildDefaultDeps()));\n });\n\n configCmd\n .command(\"defaults\")\n .description(`Print each registered descriptor's defaults; ignores ${DEFAULT_CONFIG_FILENAME}`)\n .option(\"--json\", `Output as ${CONFIG_FILE_FORMAT.JSON.toUpperCase()}`)\n .action(async (options: ShowOptions) => {\n await emit(await defaultsCommand(options, buildDefaultDeps()));\n });\n}\n\nexport const configDomain: Domain = {\n name: \"config\",\n description: \"Inspect and validate the resolved spx configuration\",\n register: (program: Command) => {\n const configCmd = program\n .command(\"config\")\n .description(\"Inspect and validate the resolved spx configuration\");\n registerConfigCommands(configCmd);\n },\n};\n","/**\n * Session archive CLI command handler.\n *\n * @module commands/session/archive\n */\n\nimport { mkdir, rename, stat } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\n\nimport {\n buildArchivePaths,\n ExistingPathsMap,\n findSessionForArchive,\n SESSION_FILE_EXTENSION,\n} from \"@/domains/session/archive\";\nimport { processBatch } from \"@/domains/session/batch\";\nimport { SessionNotFoundError } from \"@/domains/session/errors\";\nimport { SessionDirectoryConfig } from \"@/domains/session/show\";\nimport { resolveSessionConfigSurfacingWarning, type SessionWarningHandler } from \"./resolve-config\";\n\nexport const SESSION_ARCHIVE_OUTPUT = {\n ARCHIVED: \"Archived session\",\n ARCHIVE_LOCATION: \"Archive location\",\n} as const;\n\n/**\n * Options for the archive command.\n */\nexport interface ArchiveOptions {\n /** Session ID(s) to archive */\n sessionIds: string[];\n /** Custom sessions directory */\n sessionsDir?: string;\n /** Receives the non-git-repo diagnostic for the descriptor to surface. */\n onWarning?: SessionWarningHandler;\n}\n\n/**\n * Error thrown when a session is already archived.\n */\nexport class SessionAlreadyArchivedError extends Error {\n /** The session ID that is already archived */\n readonly sessionId: string;\n\n constructor(sessionId: string) {\n super(`Session already archived: ${sessionId}.`);\n this.name = \"SessionAlreadyArchivedError\";\n this.sessionId = sessionId;\n }\n}\n\n/**\n * Checks whether a path exists as a file.\n */\nasync function fileExists(path: string): Promise<boolean> {\n try {\n const stats = await stat(path);\n return stats.isFile();\n } catch {\n return false;\n }\n}\n\n/**\n * Builds an ExistingPathsMap by probing the filesystem for a session ID\n * across all status directories.\n *\n * @param sessionId - Session ID to locate\n * @param config - Directory configuration\n * @returns Map of existing paths (null for directories where file is absent)\n */\nasync function probeSessionPaths(\n sessionId: string,\n config: SessionDirectoryConfig,\n): Promise<ExistingPathsMap> {\n const filename = `${sessionId}${SESSION_FILE_EXTENSION}`;\n const todoPath = join(config.todoDir, filename);\n const doingPath = join(config.doingDir, filename);\n const archivePath = join(config.archiveDir, filename);\n\n return {\n todo: await fileExists(todoPath) ? todoPath : null,\n doing: await fileExists(doingPath) ? doingPath : null,\n archive: await fileExists(archivePath) ? archivePath : null,\n };\n}\n\n/**\n * Resolves source and target paths for archiving a session.\n *\n * @param sessionId - Session ID to archive\n * @param config - Directory configuration\n * @returns Source and target paths for the archive rename\n * @throws {SessionNotFoundError} When session is not found in todo or doing\n * @throws {SessionAlreadyArchivedError} When session is already in archive\n */\nexport async function resolveArchivePaths(\n sessionId: string,\n config: SessionDirectoryConfig,\n): Promise<{ source: string; target: string }> {\n const existingPaths = await probeSessionPaths(sessionId, config);\n\n if (existingPaths.archive !== null) {\n throw new SessionAlreadyArchivedError(sessionId);\n }\n\n const location = findSessionForArchive(existingPaths);\n\n if (!location) {\n throw new SessionNotFoundError(sessionId);\n }\n\n const paths = buildArchivePaths(sessionId, location.status, config);\n return paths;\n}\n\n/**\n * Archives a single session by ID. Any session in todo or doing is moved to\n * archive regardless of its frontmatter shape.\n */\nasync function archiveSingle(\n sessionId: string,\n config: SessionDirectoryConfig,\n): Promise<string> {\n const { source, target } = await resolveArchivePaths(sessionId, config);\n\n await mkdir(dirname(target), { recursive: true });\n await rename(source, target);\n return `${SESSION_ARCHIVE_OUTPUT.ARCHIVED}: ${sessionId}\\n${SESSION_ARCHIVE_OUTPUT.ARCHIVE_LOCATION}: ${target}`;\n}\n\n/**\n * Executes the archive command for one or more session IDs.\n *\n * @param options - Command options with one or more session IDs\n * @returns Formatted output for display\n * @throws {BatchError} When one or more IDs fail\n * @throws {SessionNotFoundError} When session not found (single ID)\n * @throws {SessionAlreadyArchivedError} When session already archived (single ID)\n */\nexport async function archiveCommand(options: ArchiveOptions): Promise<string> {\n const config = await resolveSessionConfigSurfacingWarning(options.sessionsDir, options.onWarning);\n\n return processBatch(options.sessionIds, (id) => archiveSingle(id, config));\n}\n","/**\n * Session archiving utilities with pure functions for path resolution.\n *\n * This module provides pure functions for archive path building and session\n * location finding. Actual filesystem operations are handled by the CLI\n * command handler in commands/session/archive.ts.\n *\n * @module session/archive\n */\n\nimport type { SessionStatus } from \"./types\";\n\n/**\n * File extension for session files.\n */\nexport const SESSION_FILE_EXTENSION = \".md\";\n\n/**\n * Configuration for archive path building.\n */\nexport interface ArchivePathConfig {\n /** Directory for todo sessions */\n todoDir: string;\n /** Directory for doing (claimed) sessions */\n doingDir: string;\n /** Directory for archived sessions */\n archiveDir: string;\n}\n\n/**\n * Result of building archive paths.\n */\nexport interface ArchivePaths {\n /** Source path where session currently exists */\n source: string;\n /** Target path in archive directory */\n target: string;\n}\n\n/**\n * Map of existing paths for session lookup.\n * Each key maps to the full path if file exists, or null if not found.\n */\nexport interface ExistingPathsMap {\n /** Path in todo directory, or null if not found */\n todo: string | null;\n /** Path in doing directory, or null if not found */\n doing: string | null;\n /** Path in archive directory, or null if not found */\n archive: string | null;\n}\n\n/**\n * Archivable statuses — sessions can only be archived from todo or doing.\n */\nexport type ArchivableStatus = Exclude<SessionStatus, \"archive\">;\n\nconst ARCHIVABLE_DIR_KEYS = {\n TODO: \"todoDir\",\n DOING: \"doingDir\",\n} as const;\n\ntype ArchivableDirKey = (typeof ARCHIVABLE_DIR_KEYS)[keyof typeof ARCHIVABLE_DIR_KEYS];\n\n/**\n * Result of finding a session for archiving.\n */\nexport interface SessionLocation {\n /** Status/directory where session was found */\n status: ArchivableStatus;\n /** Full path to the session file */\n path: string;\n}\n\n/**\n * Builds source and target paths for archiving a session.\n *\n * This is a pure function that computes paths based on session ID,\n * current status, and directory configuration.\n *\n * @param sessionId - Session ID (timestamp format)\n * @param currentStatus - Current status/directory of the session\n * @param config - Directory configuration\n * @returns Source and target paths for the archive operation\n *\n * @example\n * ```typescript\n * const paths = buildArchivePaths(\"2026-01-13_08-01-05\", \"todo\", {\n * todoDir: \".spx/sessions/todo\",\n * archiveDir: \".spx/sessions/archive\",\n * });\n * // paths.source === \".spx/sessions/todo/2026-01-13_08-01-05.md\"\n * // paths.target === \".spx/sessions/archive/2026-01-13_08-01-05.md\"\n * ```\n */\n/**\n * Maps archivable status to the corresponding config directory key.\n */\nconst ARCHIVABLE_DIR_KEY: Record<ArchivableStatus, ArchivableDirKey> = {\n todo: ARCHIVABLE_DIR_KEYS.TODO,\n doing: ARCHIVABLE_DIR_KEYS.DOING,\n};\n\nexport function buildArchivePaths(\n sessionId: string,\n currentStatus: ArchivableStatus,\n config: ArchivePathConfig,\n): ArchivePaths {\n const filename = `${sessionId}${SESSION_FILE_EXTENSION}`;\n const dirKey = ARCHIVABLE_DIR_KEY[currentStatus];\n const sourceDir = config[dirKey];\n\n return {\n source: `${sourceDir}/${filename}`,\n target: `${config.archiveDir}/${filename}`,\n };\n}\n\n/**\n * Finds a session's location for archiving.\n *\n * This is a pure function that determines the session's location based\n * on a map of existing paths. Returns null if the session is already\n * archived or not found.\n *\n * @param existingPaths - Map of paths where session might exist\n * @returns Session location if found in todo or doing, null otherwise\n *\n * @example\n * ```typescript\n * // Session in todo\n * const location = findSessionForArchive({\n * todo: \".spx/sessions/todo/test.md\",\n * doing: null,\n * archive: null,\n * });\n * // location === { status: \"todo\", path: \".spx/sessions/todo/test.md\" }\n *\n * // Session already archived\n * const location = findSessionForArchive({\n * todo: null,\n * doing: null,\n * archive: \".spx/sessions/archive/test.md\",\n * });\n * // location === null\n * ```\n */\n/**\n * Statuses to check when looking for a session to archive, in priority order.\n */\nconst ARCHIVE_SEARCH_ORDER: readonly ArchivableStatus[] = [\"todo\", \"doing\"] as const;\n\nexport function findSessionForArchive(\n existingPaths: ExistingPathsMap,\n): SessionLocation | null {\n // If session is already in archive, return null\n if (existingPaths.archive !== null) {\n return null;\n }\n\n // Check archivable directories in priority order\n for (const status of ARCHIVE_SEARCH_ORDER) {\n if (existingPaths[status] !== null) {\n return { status, path: existingPaths[status] };\n }\n }\n\n // Session not found anywhere\n return null;\n}\n","/**\n * Batch processing utilities for session commands.\n *\n * Provides a shared pattern for processing multiple session IDs:\n * run a handler per ID, collect results, report per-ID outcomes,\n * throw if any failed.\n *\n * @module session/batch\n */\n\n/**\n * Result of processing a single session ID within a batch.\n */\nexport interface BatchItemResult {\n /** The session ID that was processed. */\n id: string;\n /** Whether the operation succeeded. */\n ok: boolean;\n /** Output message on success, error message on failure. */\n message: string;\n}\n\n/**\n * Error thrown when a batch operation has partial or total failures.\n * Contains per-ID results so the caller knows which succeeded and which failed.\n */\nexport class BatchError extends Error {\n readonly results: readonly BatchItemResult[];\n\n constructor(results: readonly BatchItemResult[]) {\n const failures = results.filter((r) => !r.ok);\n const successes = results.filter((r) => r.ok);\n super(\n `${failures.length} of ${results.length} operations failed. `\n + `${successes.length} succeeded.`,\n );\n this.name = \"BatchError\";\n this.results = results;\n }\n}\n\n/**\n * Processes multiple session IDs through a handler function.\n *\n * IDs are processed sequentially in argument order (left-to-right).\n * All IDs are processed regardless of individual failures.\n * Throws BatchError if any ID fails.\n *\n * @param ids - Session IDs to process\n * @param handler - Async function that processes a single ID and returns output\n * @returns Combined output string with per-ID results\n * @throws {BatchError} When one or more IDs fail\n */\nexport async function processBatch(\n ids: readonly string[],\n handler: (id: string) => Promise<string>,\n): Promise<string> {\n const results: BatchItemResult[] = [];\n\n for (const id of ids) {\n try {\n const output = await handler(id);\n results.push({ id, ok: true, message: output });\n } catch (error) {\n const message = error instanceof Error ? `${error.name}: ${error.message}` : String(error);\n results.push({ id, ok: false, message });\n }\n }\n\n const output = results\n .map((r) => r.ok ? r.message : `Error (${r.id}): ${r.message}`)\n .join(\"\\n\\n\");\n\n const hasFailures = results.some((r) => !r.ok);\n if (hasFailures) {\n const err = new BatchError(results);\n err.message = `${err.message}\\n\\n${output}`;\n throw err;\n }\n\n return output;\n}\n","/**\n * The handoff-base refusal checklist: the resolved git facts and per-prerequisite\n * evaluation a linked-worktree refusal carries, plus the source-owned vocabulary\n * the descriptor renders. Pure over the carried facts — the handler resolves the\n * facts, the resolver attaches them to {@link SessionHandoffBaseError}, and the\n * descriptor writes the rendered text to standard error.\n *\n * @module domains/session/handoff-base-checklist\n */\n\n/** The error name a handoff-base refusal carries and the checklist names. */\nexport const SESSION_HANDOFF_BASE_ERROR_NAME = \"SessionHandoffBaseError\";\n\n/** Markers a checklist line carries for a met or unmet base prerequisite. */\nexport const HANDOFF_BASE_MARK = {\n MET: \"✓\",\n UNMET: \"✗\",\n} as const;\n\n/** The base prerequisites a linked-worktree handoff must satisfy. */\nexport const HANDOFF_BASE_PREREQUISITE_LABEL = {\n CLEAN_WORKING_TREE: \"working tree is clean\",\n DETACHED_AT_DEFAULT_TIP: \"HEAD is detached at the default-branch tip\",\n} as const;\n\n/** The non-stashing remedy each unmet prerequisite states. */\nexport const HANDOFF_BASE_REMEDY = {\n /** Unclean working tree: commit, or hand off from the root worktree. */\n COMMIT_OR_ROOT: \"commit the changes, or run handoff from the root worktree\",\n /** Off the default-branch tip: detach to it, or hand off from the root worktree. */\n DETACH_TO_TIP_OR_ROOT: \"detach HEAD to the default-branch tip, or run handoff from the root worktree\",\n /** Default branch unresolved: only the root worktree can anchor the base. */\n ROOT_ONLY: \"run handoff from the root worktree\",\n} as const;\n\n/**\n * Labels on the resolved-git-fact lines the checklist carries. `DEFAULT_TIP`\n * reads `origin tip` rather than `default-branch tip` so a fact-line lookup by\n * label never collides with the `DETACHED_AT_DEFAULT_TIP` prerequisite label.\n */\nexport const HANDOFF_BASE_FACT_LABEL = {\n DEFAULT_BRANCH: \"default branch\",\n DEFAULT_TIP: \"origin tip\",\n HEAD: \"HEAD\",\n CURRENT_WORKTREE: \"current worktree\",\n ROOT_WORKTREE: \"root worktree\",\n} as const;\n\n/** Stated in place of a default branch or tip that does not resolve (`origin/HEAD` unset). */\nexport const HANDOFF_BASE_UNRESOLVED = \"unresolved\";\n\n/**\n * A single base prerequisite a linked-worktree refusal evaluates. Every\n * prerequisite is represented regardless of which are met, so the rendered\n * checklist omits none.\n */\nexport interface HandoffBasePrerequisite {\n /** The prerequisite, from {@link HANDOFF_BASE_PREREQUISITE_LABEL}. */\n readonly label: string;\n /** Whether the working context satisfies the prerequisite. */\n readonly met: boolean;\n /** When unmet, the non-stashing remedy from {@link HANDOFF_BASE_REMEDY}; empty when met. */\n readonly remedy: string;\n}\n\n/**\n * The resolved git facts and per-prerequisite evaluation a linked-worktree\n * handoff refusal carries. `null` for `defaultBranch` or `defaultTipSha` marks\n * the value unresolved — `origin/HEAD` is unset — never a fabricated branch or\n * SHA and never the literal placeholder `origin/<default>`.\n */\nexport interface HandoffBaseChecklist {\n /** The resolved default branch name, or `null` when `origin/HEAD` is unset. */\n readonly defaultBranch: string | null;\n /** The `origin/<default>` tip commit SHA, or `null` when unresolved. */\n readonly defaultTipSha: string | null;\n /** The observed HEAD commit SHA, or `null` when unavailable. */\n readonly headSha: string | null;\n /** The absolute path of the worktree handoff ran from. */\n readonly currentWorktreePath: string;\n /** The absolute path of the repository's root worktree. */\n readonly rootWorktreePath: string;\n /** Every base prerequisite, each marked met or unmet. */\n readonly prerequisites: readonly HandoffBasePrerequisite[];\n}\n\n/** Leading indent on every checklist body line. */\nconst CHECKLIST_INDENT = \" \";\n/** Separator between an unmet prerequisite and its remedy. */\nconst REMEDY_SEPARATOR = \" — \";\n/** Opening line introducing the refusal and naming the error. */\nconst CHECKLIST_HEADER =\n `${SESSION_HANDOFF_BASE_ERROR_NAME}: cannot create a handoff session from this linked worktree.`;\n\n/** Renders one resolved-fact line, stating `unresolved` for an absent value. */\nfunction renderFactLine(label: string, value: string | null): string {\n return `${CHECKLIST_INDENT}${label}: ${value ?? HANDOFF_BASE_UNRESOLVED}`;\n}\n\n/** Renders one prerequisite line — a mark, the label, and (when unmet) its remedy. */\nfunction renderPrerequisiteLine(prerequisite: HandoffBasePrerequisite): string {\n const mark = prerequisite.met ? HANDOFF_BASE_MARK.MET : HANDOFF_BASE_MARK.UNMET;\n const base = `${CHECKLIST_INDENT}${mark} ${prerequisite.label}`;\n return prerequisite.met ? base : `${base}${REMEDY_SEPARATOR}${prerequisite.remedy}`;\n}\n\n/**\n * Renders a linked-worktree handoff refusal as the prerequisite checklist the\n * descriptor writes to standard error: the error name, the resolved git values\n * (default branch, origin tip SHA, observed HEAD SHA, current and root worktree\n * paths — each stated `unresolved` when absent), and every base prerequisite on\n * its own line marked met or unmet with a non-stashing remedy when unmet.\n *\n * @param checklist - The resolved facts and per-prerequisite evaluation the\n * refusal carries.\n * @returns The multi-line diagnostic, without a trailing newline.\n */\nexport function renderHandoffBaseChecklist(checklist: HandoffBaseChecklist): string {\n return [\n CHECKLIST_HEADER,\n renderFactLine(HANDOFF_BASE_FACT_LABEL.DEFAULT_BRANCH, checklist.defaultBranch),\n renderFactLine(HANDOFF_BASE_FACT_LABEL.DEFAULT_TIP, checklist.defaultTipSha),\n renderFactLine(HANDOFF_BASE_FACT_LABEL.HEAD, checklist.headSha),\n renderFactLine(HANDOFF_BASE_FACT_LABEL.CURRENT_WORKTREE, checklist.currentWorktreePath),\n renderFactLine(HANDOFF_BASE_FACT_LABEL.ROOT_WORKTREE, checklist.rootWorktreePath),\n ...checklist.prerequisites.map(renderPrerequisiteLine),\n ].join(\"\\n\");\n}\n","/**\n * Session-specific error types.\n *\n * @module session/errors\n */\n\nimport { type HandoffBaseChecklist, SESSION_HANDOFF_BASE_ERROR_NAME } from \"./handoff-base-checklist\";\n\n/**\n * Base class for session errors.\n */\nexport class SessionError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"SessionError\";\n }\n}\n\n/**\n * Error thrown when a session cannot be found.\n */\nexport class SessionNotFoundError extends SessionError {\n /** The session ID that was not found */\n readonly sessionId: string;\n\n constructor(sessionId: string) {\n super(`Session not found: ${sessionId}. Check the session ID and try again.`);\n this.name = \"SessionNotFoundError\";\n this.sessionId = sessionId;\n }\n}\n\n/**\n * Error thrown when a session is not available for claiming (already claimed).\n */\nexport class SessionNotAvailableError extends SessionError {\n /** The session ID that is not available */\n readonly sessionId: string;\n\n constructor(sessionId: string) {\n super(`Session not available: ${sessionId}. It may have been claimed by another agent.`);\n this.name = \"SessionNotAvailableError\";\n this.sessionId = sessionId;\n }\n}\n\n/**\n * Error thrown when session content is invalid.\n */\nexport class SessionInvalidContentError extends SessionError {\n constructor(reason: string) {\n super(`Invalid session content: ${reason}`);\n this.name = \"SessionInvalidContentError\";\n }\n}\n\n/**\n * Error thrown when handoff content has no usable goal.\n */\nexport class SessionInvalidGoalError extends SessionError {\n constructor() {\n super(\"Invalid session goal: goal must be a non-empty string.\");\n this.name = \"SessionInvalidGoalError\";\n }\n}\n\n/**\n * Error thrown when handoff content has no usable next step.\n */\nexport class SessionInvalidNextStepError extends SessionError {\n constructor() {\n super(\"Invalid session next_step: next_step must be a non-empty string.\");\n this.name = \"SessionInvalidNextStepError\";\n }\n}\n\n/**\n * Error thrown when `spx session handoff` runs from a git work context that\n * cannot anchor a session to a base another agent can reach.\n *\n * Handoff is permitted from the root worktree (any reachable HEAD) or from a\n * linked worktree that is clean and detached at the tip of `origin/<default\n * branch>`. A refusal renders one of three ways, distinguished by the carried\n * fields:\n *\n * - **Linked-worktree refusal** carries a {@link HandoffBaseChecklist} the\n * descriptor renders to standard error.\n * - **Non-git base** is `silent` — the descriptor writes nothing, only the\n * non-zero exit.\n * - **Any other git refusal** (e.g. a root worktree with no reachable HEAD)\n * carries no checklist and is not silent, so the descriptor writes the message\n * as a plain diagnostic — only the non-git refusal is silent.\n */\nexport class SessionHandoffBaseError extends SessionError {\n /** The prerequisite checklist to render, or `null` for a non-checklist refusal. */\n readonly checklist: HandoffBaseChecklist | null;\n /** Whether the refusal surfaces no diagnostic — true only for a non-git base. */\n readonly silent: boolean;\n\n constructor(options: { checklist?: HandoffBaseChecklist | null; silent?: boolean } = {}) {\n super(\n \"Cannot create a handoff session from this git work context. Run handoff \"\n + \"from the root worktree, or from a linked worktree with a clean working \"\n + \"tree detached at the tip of the default branch.\",\n );\n this.name = SESSION_HANDOFF_BASE_ERROR_NAME;\n this.checklist = options.checklist ?? null;\n this.silent = options.silent ?? false;\n }\n}\n\n/**\n * Error thrown when trying to release a session that is not currently claimed.\n */\nexport class SessionNotClaimedError extends SessionError {\n /** The session ID that is not claimed */\n readonly sessionId: string;\n\n constructor(sessionId: string) {\n super(`Session not claimed: ${sessionId}. The session is not in the doing directory.`);\n this.name = \"SessionNotClaimedError\";\n this.sessionId = sessionId;\n }\n}\n\n/**\n * Error thrown when no sessions are available for auto-pickup.\n */\nexport class NoSessionsAvailableError extends SessionError {\n constructor() {\n super(\"No sessions available. The todo directory is empty.\");\n this.name = \"NoSessionsAvailableError\";\n }\n}\n\n/**\n * Error thrown when handoff stdin opens with the legacy YAML-frontmatter\n * delimiter.\n *\n * `spx session handoff` accepts caller-supplied structured fields as a JSON\n * object at the start of stdin.\n * Input opening with `---\\n` is the legacy wire format that destroys caller\n * content for any string containing YAML-significant characters (`#`, `:` after\n * a space, leading whitespace) and is rejected with this error.\n */\nexport class SessionLegacyFrontmatterInputError extends SessionError {\n constructor() {\n super(\n \"Invalid handoff input: stdin opens with the YAML-frontmatter delimiter `---`. \"\n + \"Use the JSON-prefix wire format: a single JSON object holding caller-supplied \"\n + \"fields followed by the body bytes verbatim. Example:\\n\\n\"\n + \" printf '%s\\\\n' '{\\\"priority\\\":\\\"high\\\",\\\"goal\\\":\\\"...\\\",\\\"next_step\\\":\\\"...\\\"}' '# Body' \"\n + \"| spx session handoff\",\n );\n this.name = \"SessionLegacyFrontmatterInputError\";\n }\n}\n\n/**\n * Error thrown when the JSON header at the start of handoff stdin is malformed\n * or fails schema validation.\n *\n * Raised by `parseHandoffInput` when stdin does not open with `{`, the opening\n * brace has no matching close, `JSON.parse` fails, or the parsed object does\n * not satisfy the caller-field schema.\n */\nexport class SessionInvalidJsonHeaderError extends SessionError {\n constructor(reason: string) {\n super(`Invalid JSON header for handoff: ${reason}`);\n this.name = \"SessionInvalidJsonHeaderError\";\n }\n}\n","import { execa } from \"execa\";\nimport { dirname, isAbsolute, join, relative, resolve } from \"node:path\";\n\nimport { SessionDirectoryConfig } from \"@/domains/session/show\";\nimport { DEFAULT_CONFIG } from \"../config/defaults\";\nimport { withoutGitEnvironment } from \"./environment\";\n\n// Result from product-directory detection.\nexport interface GitProductDirResult {\n /** Absolute path to product directory (or cwd if not in git repo) */\n productDir: string;\n /** Whether the directory is inside a git repository */\n isGitRepo: boolean;\n /** Warning message when not in a git repo (undefined if in repo) */\n warning?: string;\n}\n\n/**\n * Result from Git common-dir product-root detection. Carries the local worktree\n * root (`git rev-parse --show-toplevel`, or `cwd` outside a git repository) as a\n * required field alongside the Git common-dir `productDir`, so a caller that\n * needs both roots reads `--show-toplevel` once.\n */\nexport interface GitCommonDirProductDirResult extends GitProductDirResult {\n /** The local worktree root — the `--show-toplevel` value, or `cwd` outside a git repository. */\n worktreeRoot: string;\n}\n\n// Minimal command result shape used by product-directory detection.\nexport interface ExecResult {\n /** Process exit code */\n exitCode: number;\n /** Standard output */\n stdout: string;\n /** Standard error */\n stderr: string;\n}\n\n// Dependencies for git operations.\nexport interface GitDependencies {\n // Execute a command.\n execa: (\n command: string,\n args: string[],\n options?: { cwd?: string; reject?: boolean },\n ) => Promise<ExecResult>;\n}\n\n// Default dependencies using real execa.\nconst defaultDeps: GitDependencies = {\n execa: async (command, args, options) => {\n const result = await execa(command, args, {\n ...options,\n env: withoutGitEnvironment(process.env),\n extendEnv: false,\n });\n return {\n exitCode: result.exitCode ?? 0,\n stdout: typeof result.stdout === \"string\" ? result.stdout : String(result.stdout),\n stderr: typeof result.stderr === \"string\" ? result.stderr : String(result.stderr),\n };\n },\n};\n\nexport const NOT_GIT_REPO_WARNING =\n \"Warning: Not in a git repository; resolving session storage relative to the current directory.\";\n\nexport const GIT_ROOT_COMMAND = {\n EXECUTABLE: \"git\",\n REV_PARSE: \"rev-parse\",\n ABBREV_REF: \"--abbrev-ref\",\n GIT_COMMON_DIR: \"--git-common-dir\",\n HEAD: \"HEAD\",\n SHOW_TOPLEVEL: \"--show-toplevel\",\n SYMBOLIC_REF: \"symbolic-ref\",\n SHORT: \"--short\",\n ORIGIN_HEAD_REF: \"refs/remotes/origin/HEAD\",\n STATUS: \"status\",\n PORCELAIN: \"--porcelain\",\n PATH_FORMAT_ABSOLUTE: \"--path-format=absolute\",\n} as const;\n\n/** Prefix on the remote-tracking ref returned by `symbolic-ref refs/remotes/origin/HEAD`. */\nexport const ORIGIN_REF_PREFIX = \"origin/\";\n\nexport const GIT_SHOW_TOPLEVEL_ARGS = [\n GIT_ROOT_COMMAND.REV_PARSE,\n GIT_ROOT_COMMAND.SHOW_TOPLEVEL,\n] as const;\n\n// `--path-format=absolute` makes git emit an absolute common dir regardless of\n// the working directory; without it `--git-common-dir` is relative to git's cwd\n// (e.g. `../../.git` from a subdirectory), which misresolves against the toplevel.\nexport const GIT_COMMON_DIR_ARGS = [\n GIT_ROOT_COMMAND.REV_PARSE,\n GIT_ROOT_COMMAND.PATH_FORMAT_ABSOLUTE,\n GIT_ROOT_COMMAND.GIT_COMMON_DIR,\n] as const;\n\nexport const GIT_CURRENT_BRANCH_ARGS = [\n GIT_ROOT_COMMAND.REV_PARSE,\n GIT_ROOT_COMMAND.ABBREV_REF,\n GIT_ROOT_COMMAND.HEAD,\n] as const;\n\nexport const GIT_HEAD_SHA_ARGS = [\n GIT_ROOT_COMMAND.REV_PARSE,\n GIT_ROOT_COMMAND.HEAD,\n] as const;\n\nexport const GIT_ORIGIN_HEAD_REF_ARGS = [\n GIT_ROOT_COMMAND.SYMBOLIC_REF,\n GIT_ROOT_COMMAND.SHORT,\n GIT_ROOT_COMMAND.ORIGIN_HEAD_REF,\n] as const;\n\nexport const GIT_STATUS_PORCELAIN_ARGS = [\n GIT_ROOT_COMMAND.STATUS,\n GIT_ROOT_COMMAND.PORCELAIN,\n] as const;\n\n// Detects the local worktree product directory.\nexport async function detectWorktreeProductRoot(\n cwd: string = process.cwd(),\n deps: GitDependencies = defaultDeps,\n): Promise<GitProductDirResult> {\n try {\n const result = await deps.execa(\n GIT_ROOT_COMMAND.EXECUTABLE,\n [...GIT_SHOW_TOPLEVEL_ARGS],\n { cwd, reject: false },\n );\n\n // Git command succeeded - we're in a repo\n if (result.exitCode === 0 && result.stdout) {\n return {\n productDir: extractStdout(result.stdout),\n isGitRepo: true,\n };\n }\n\n // Git command failed - not in a repo\n return {\n productDir: cwd,\n isGitRepo: false,\n warning: NOT_GIT_REPO_WARNING,\n };\n } catch {\n // Command execution failed (git not installed, permission error, etc.)\n return {\n productDir: cwd,\n isGitRepo: false,\n warning: NOT_GIT_REPO_WARNING,\n };\n }\n}\n\n// Extracts a trimmed string from execa stdout.\nfunction extractStdout(stdout: unknown): string {\n if (!stdout) return \"\";\n const str = typeof stdout === \"string\" ? stdout : String(stdout);\n return str.trim().replace(/\\/+$/, \"\");\n}\n\n// Detects the Git common-dir product root, resolving through git worktrees.\nexport async function detectGitCommonDirProductRoot(\n cwd: string = process.cwd(),\n deps: GitDependencies = defaultDeps,\n): Promise<GitCommonDirProductDirResult> {\n try {\n // Step 1: Get the local worktree product directory via --show-toplevel\n const toplevelResult = await deps.execa(\n GIT_ROOT_COMMAND.EXECUTABLE,\n [...GIT_SHOW_TOPLEVEL_ARGS],\n { cwd, reject: false },\n );\n\n if (toplevelResult.exitCode !== 0 || !toplevelResult.stdout) {\n return {\n productDir: cwd,\n isGitRepo: false,\n warning: NOT_GIT_REPO_WARNING,\n worktreeRoot: cwd,\n };\n }\n\n const toplevel = extractStdout(toplevelResult.stdout);\n\n // Step 2: Get the common git directory via --git-common-dir\n const commonDirResult = await deps.execa(\n GIT_ROOT_COMMAND.EXECUTABLE,\n [...GIT_COMMON_DIR_ARGS],\n { cwd, reject: false },\n );\n\n if (commonDirResult.exitCode !== 0 || !commonDirResult.stdout) {\n // Fallback: if --git-common-dir fails, use toplevel\n return {\n productDir: toplevel,\n isGitRepo: true,\n worktreeRoot: toplevel,\n };\n }\n\n const commonDir = extractStdout(commonDirResult.stdout);\n\n // Step 3: Resolve the common dir to an absolute path. GIT_COMMON_DIR_ARGS\n // requests --path-format=absolute, so git emits an absolute path; the\n // relative branch is a defensive fallback for git builds that ignore it.\n const absoluteCommonDir = isAbsolute(commonDir)\n ? commonDir\n : resolve(toplevel, commonDir);\n\n // Step 4: The Git common-dir product root is the parent of the common .git directory\n const gitCommonDirProductRoot = dirname(absoluteCommonDir);\n\n return {\n productDir: gitCommonDirProductRoot,\n isGitRepo: true,\n worktreeRoot: toplevel,\n };\n } catch {\n return {\n productDir: cwd,\n isGitRepo: false,\n warning: NOT_GIT_REPO_WARNING,\n worktreeRoot: cwd,\n };\n }\n}\n\nexport function computeRelativeWorktreePath(commonDir: string, toplevel: string): string {\n const absoluteCommonDir = isAbsolute(commonDir)\n ? commonDir\n : resolve(toplevel, commonDir);\n const commonDirProductRoot = dirname(absoluteCommonDir);\n const worktreePath = relative(commonDirProductRoot, toplevel);\n return worktreePath === \"\" ? \"\" : worktreePath;\n}\n\n/**\n * Resolves the repository's default branch name from `origin/HEAD`\n * (e.g. `\"main\"`). Returns null when `origin/HEAD` is unset or unresolvable.\n */\nexport async function resolveDefaultBranch(\n cwd: string = process.cwd(),\n deps: GitDependencies = defaultDeps,\n): Promise<string | null> {\n const result = await deps.execa(\n GIT_ROOT_COMMAND.EXECUTABLE,\n [...GIT_ORIGIN_HEAD_REF_ARGS],\n { cwd, reject: false },\n );\n if (result.exitCode !== 0) return null;\n const ref = extractStdout(result.stdout);\n if (!ref.startsWith(ORIGIN_REF_PREFIX)) return null;\n const branch = ref.slice(ORIGIN_REF_PREFIX.length);\n return branch.length === 0 ? null : branch;\n}\n\n/**\n * Returns the checked-out branch name, or null when HEAD is detached or the\n * branch name is unavailable.\n */\nexport async function getCurrentBranch(\n cwd: string = process.cwd(),\n deps: GitDependencies = defaultDeps,\n): Promise<string | null> {\n const result = await deps.execa(\n GIT_ROOT_COMMAND.EXECUTABLE,\n [...GIT_CURRENT_BRANCH_ARGS],\n { cwd, reject: false },\n );\n if (result.exitCode !== 0) return null;\n const branch = extractStdout(result.stdout);\n if (branch.length === 0 || branch === GIT_ROOT_COMMAND.HEAD) return null;\n return branch;\n}\n\n/** Returns the HEAD commit SHA, or null when unavailable. */\nexport async function getHeadSha(\n cwd: string = process.cwd(),\n deps: GitDependencies = defaultDeps,\n): Promise<string | null> {\n const result = await deps.execa(\n GIT_ROOT_COMMAND.EXECUTABLE,\n [...GIT_HEAD_SHA_ARGS],\n { cwd, reject: false },\n );\n if (result.exitCode !== 0) return null;\n const sha = extractStdout(result.stdout);\n return sha.length === 0 ? null : sha;\n}\n\n/**\n * Returns the commit SHA at the tip of the given ref (e.g. `\"origin/main\"`),\n * or null when the ref cannot be resolved.\n */\nexport async function resolveRefSha(\n ref: string,\n cwd: string = process.cwd(),\n deps: GitDependencies = defaultDeps,\n): Promise<string | null> {\n const result = await deps.execa(\n GIT_ROOT_COMMAND.EXECUTABLE,\n [GIT_ROOT_COMMAND.REV_PARSE, ref],\n { cwd, reject: false },\n );\n if (result.exitCode !== 0) return null;\n const sha = extractStdout(result.stdout);\n return sha.length === 0 ? null : sha;\n}\n\n/**\n * Whether the working tree at `cwd` is clean — `git status --porcelain` emits\n * nothing. A non-zero git exit is treated as not clean.\n */\nexport async function isWorkingTreeClean(\n cwd: string = process.cwd(),\n deps: GitDependencies = defaultDeps,\n): Promise<boolean> {\n const result = await deps.execa(\n GIT_ROOT_COMMAND.EXECUTABLE,\n [...GIT_STATUS_PORCELAIN_ARGS],\n { cwd, reject: false },\n );\n if (result.exitCode !== 0) return false;\n return extractStdout(result.stdout).length === 0;\n}\n\n/**\n * Whether `cwd` resolves to the repository's root worktree — the working tree\n * rooted at the Git common-dir product root (empty relative worktree path). A\n * linked worktree resolves to a non-empty relative path.\n */\nexport async function isRootWorktree(\n cwd: string = process.cwd(),\n deps: GitDependencies = defaultDeps,\n): Promise<boolean> {\n const [toplevelResult, commonDirResult] = await Promise.all([\n deps.execa(GIT_ROOT_COMMAND.EXECUTABLE, [...GIT_SHOW_TOPLEVEL_ARGS], { cwd, reject: false }),\n deps.execa(GIT_ROOT_COMMAND.EXECUTABLE, [...GIT_COMMON_DIR_ARGS], { cwd, reject: false }),\n ]);\n if (toplevelResult.exitCode !== 0) return false;\n // Mirror detectGitCommonDirProductRoot's fallback: when --git-common-dir is\n // unavailable but --show-toplevel succeeded, treat the working tree as the\n // root worktree rather than misclassifying it as linked.\n if (commonDirResult.exitCode !== 0) return true;\n const toplevel = extractStdout(toplevelResult.stdout);\n const commonDir = extractStdout(commonDirResult.stdout);\n return computeRelativeWorktreePath(commonDir, toplevel) === \"\";\n}\n\n// Options for resolving session directory configuration.\nexport interface ResolveSessionConfigOptions {\n /** Explicit sessions directory (overrides auto-detection) */\n sessionsDir?: string;\n /** Current working directory for git detection */\n cwd?: string;\n /** Injectable dependencies for testing */\n deps?: GitDependencies;\n}\n\n// Result of session config resolution.\nexport interface ResolveSessionConfigResult {\n /** Resolved session directory configuration with absolute paths */\n config: SessionDirectoryConfig;\n /** Warning message if not in a git repository */\n warning?: string;\n}\n\n// Resolves session directory configuration with worktree-aware root detection.\nexport async function resolveSessionConfig(\n options: ResolveSessionConfigOptions = {},\n): Promise<ResolveSessionConfigResult> {\n const { sessionsDir, cwd, deps } = options;\n const { statusDirs } = DEFAULT_CONFIG.sessions;\n\n // Explicit directory provided — use as-is\n if (sessionsDir) {\n return {\n config: {\n todoDir: join(sessionsDir, statusDirs.todo),\n doingDir: join(sessionsDir, statusDirs.doing),\n archiveDir: join(sessionsDir, statusDirs.archive),\n },\n };\n }\n\n // Auto-detect Git common-dir product root for .spx/ operations\n const gitResult = await detectGitCommonDirProductRoot(cwd, deps);\n const baseDir = join(gitResult.productDir, DEFAULT_CONFIG.sessions.dir);\n\n return {\n config: {\n todoDir: join(baseDir, statusDirs.todo),\n doingDir: join(baseDir, statusDirs.doing),\n archiveDir: join(baseDir, statusDirs.archive),\n },\n warning: gitResult.warning,\n };\n}\n","/**\n * Default configuration for spx CLI\n *\n * This module defines the default directory structure and configuration\n * constants used throughout the spx CLI. All directory paths should reference\n * this configuration instead of using hardcoded strings.\n *\n * @module config/defaults\n */\n\n/**\n * Configuration schema for spx CLI directory structure\n */\nexport interface SpxConfig {\n /**\n * Session handoff files configuration\n */\n sessions: {\n /**\n * Directory for session handoff files\n * @default \".spx/sessions\"\n */\n dir: string;\n\n /**\n * Status-based subdirectories for sessions\n */\n statusDirs: {\n /**\n * Available sessions directory\n * @default \"todo\"\n */\n todo: string;\n\n /**\n * Claimed sessions directory\n * @default \"doing\"\n */\n doing: string;\n\n /**\n * Archived sessions directory\n * @default \"archive\"\n */\n archive: string;\n };\n };\n}\n\n/**\n * Default configuration constant\n *\n * This is the embedded default configuration that spx uses when no\n * .spx/config.json file exists in the product.\n *\n * DO NOT modify this constant at runtime - it should remain immutable.\n */\nexport const DEFAULT_CONFIG = {\n sessions: {\n dir: \".spx/sessions\",\n statusDirs: {\n todo: \"todo\",\n doing: \"doing\",\n archive: \"archive\",\n },\n },\n} as const satisfies SpxConfig;\n","/**\n * Removes Git context and identity variables for read-only commands that must\n * resolve from their own cwd instead of an inherited hook/worktree context.\n * Commit and tag callers need an identity-preserving environment instead.\n */\nexport function withoutGitEnvironment(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\n const cleaned = { ...env };\n for (const key of Object.keys(cleaned)) {\n if (key.startsWith(\"GIT_\")) {\n delete cleaned[key];\n }\n }\n return cleaned;\n}\n","/**\n * Shared session-config resolution that surfaces the non-git-repo diagnostic.\n *\n * @module commands/session/resolve-config\n */\n\nimport { SessionDirectoryConfig } from \"@/domains/session/show\";\nimport { resolveSessionConfig } from \"@/git/root\";\n\n/** Receives the non-git-repo diagnostic for a descriptor to write to stderr. */\nexport type SessionWarningHandler = (warning: string) => void;\n\n/**\n * Resolves the session directory configuration, forwarding the non-git-repo\n * diagnostic that `resolveSessionConfig` emits — when the working directory is\n * outside a git repository and session storage falls back to it — to\n * `onWarning` so the descriptor can surface it. Mirrors the spec commands'\n * `onWarning` contract.\n *\n * @param sessionsDir - Explicit sessions directory, or undefined to auto-detect.\n * @param onWarning - Receives the diagnostic when config falls back outside a git repository.\n * @returns The resolved session directory configuration.\n */\nexport async function resolveSessionConfigSurfacingWarning(\n sessionsDir: string | undefined,\n onWarning?: SessionWarningHandler,\n): Promise<SessionDirectoryConfig> {\n const { config, warning } = await resolveSessionConfig({ sessionsDir });\n if (warning !== undefined) {\n onWarning?.(warning);\n }\n return config;\n}\n","/**\n * Session delete CLI command handler.\n *\n * @module commands/session/delete\n */\n\nimport { stat, unlink } from \"node:fs/promises\";\n\nimport { processBatch } from \"@/domains/session/batch\";\nimport { resolveDeletePath } from \"@/domains/session/delete\";\nimport { resolveSessionPaths, SessionDirectoryConfig } from \"@/domains/session/show\";\nimport { resolveSessionConfigSurfacingWarning, type SessionWarningHandler } from \"./resolve-config\";\n\nexport const SESSION_DELETE_OUTPUT = {\n DELETED: \"Deleted session\",\n} as const;\n\n/**\n * Options for the delete command.\n */\nexport interface DeleteOptions {\n /** Session ID(s) to delete */\n sessionIds: string[];\n /** Custom sessions directory */\n sessionsDir?: string;\n /** Receives the non-git-repo diagnostic for the descriptor to surface. */\n onWarning?: SessionWarningHandler;\n}\n\n/**\n * Checks which paths exist.\n */\nasync function findExistingPaths(paths: string[]): Promise<string[]> {\n const existing: string[] = [];\n\n for (const path of paths) {\n try {\n const stats = await stat(path);\n if (stats.isFile()) {\n existing.push(path);\n }\n } catch {\n // File doesn't exist, skip\n }\n }\n\n return existing;\n}\n\n/**\n * Executes the delete command.\n *\n * @param options - Command options\n * @returns Formatted output for display\n * @throws {SessionNotFoundError} When session not found\n */\n/**\n * Deletes a single session by ID.\n */\nasync function deleteSingle(\n sessionId: string,\n config: SessionDirectoryConfig,\n): Promise<string> {\n const paths = resolveSessionPaths(sessionId, config);\n const existingPaths = await findExistingPaths(paths);\n const pathToDelete = resolveDeletePath(sessionId, existingPaths);\n await unlink(pathToDelete);\n return `${SESSION_DELETE_OUTPUT.DELETED}: ${sessionId}`;\n}\n\n/**\n * Executes the delete command for one or more session IDs.\n *\n * @param options - Command options with one or more session IDs\n * @returns Formatted output for display\n * @throws {BatchError} When one or more IDs fail\n * @throws {SessionNotFoundError} When session not found (single ID)\n */\nexport async function deleteCommand(options: DeleteOptions): Promise<string> {\n const config = await resolveSessionConfigSurfacingWarning(options.sessionsDir, options.onWarning);\n\n return processBatch(options.sessionIds, (id) => deleteSingle(id, config));\n}\n","/**\n * Session deletion utilities.\n *\n * @module session/delete\n */\n\nimport { SessionNotFoundError } from \"./errors\";\n\n/**\n * Resolves the path to delete for a session ID.\n *\n * Given a session ID and a list of existing paths (checked by caller),\n * returns the first path that contains the session ID.\n *\n * @param sessionId - Session ID to find\n * @param existingPaths - Paths that were found to exist\n * @returns The path to the session file\n * @throws {SessionNotFoundError} When session is not found in any directory\n *\n * @example\n * ```typescript\n * // Caller checks which paths exist, passes only existing ones\n * const existingPaths = ['.spx/sessions/doing/2026-01-13_08-01-05.md'];\n * const path = resolveDeletePath('2026-01-13_08-01-05', existingPaths);\n * // => '.spx/sessions/doing/2026-01-13_08-01-05.md'\n * ```\n */\nexport function resolveDeletePath(\n sessionId: string,\n existingPaths: string[],\n): string {\n // Find the first existing path that matches the session ID\n const matchingPath = existingPaths.find((path) => path.includes(sessionId));\n\n if (!matchingPath) {\n throw new SessionNotFoundError(sessionId);\n }\n\n return matchingPath;\n}\n","/**\n * Session display utilities for showing session content without claiming.\n *\n * @module session/show\n */\n\nimport { join } from \"node:path\";\n\nimport { DEFAULT_CONFIG } from \"@/config/defaults\";\nimport { parseSessionMetadata } from \"./list\";\nimport { SESSION_STATUSES, type SessionStatus } from \"./types\";\n\nexport const SESSION_SHOW_LABEL = {\n STATUS: \"Status\",\n PRIORITY: \"Priority\",\n GIT_REF: \"Git ref\",\n GOAL: \"Goal\",\n NEXT_STEP: \"Next step\",\n CREATED: \"Created\",\n AGENT_SESSION: \"Agent session\",\n} as const;\n\nexport const SESSION_SHOW_SEPARATOR_CHAR = \"─\";\nexport const SESSION_SHOW_SEPARATOR_WIDTH = 40;\n\n/**\n * Configuration for session directory paths.\n */\nexport interface SessionDirectoryConfig {\n /** Path to todo directory */\n todoDir: string;\n /** Path to doing directory */\n doingDir: string;\n /** Path to archive directory */\n archiveDir: string;\n}\n\n/**\n * Default session directory configuration.\n *\n * Derived from DEFAULT_CONFIG to ensure single source of truth for all path components.\n * NEVER hardcode path strings like \".spx\", \"sessions\", \"todo\" - always derive from config.\n */\nconst { dir: sessionsBaseDir, statusDirs } = DEFAULT_CONFIG.sessions;\n\nexport const DEFAULT_SESSION_CONFIG: SessionDirectoryConfig = {\n todoDir: join(sessionsBaseDir, statusDirs.todo),\n doingDir: join(sessionsBaseDir, statusDirs.doing),\n archiveDir: join(sessionsBaseDir, statusDirs.archive),\n};\n\n/**\n * Order to search directories (matches priority: todo first, then doing, then archive).\n * Derived from SESSION_STATUSES to maintain a single source of truth.\n */\nexport const SEARCH_ORDER: SessionStatus[] = [...SESSION_STATUSES];\n\n/**\n * Options for formatting show output.\n */\nexport interface ShowOutputOptions {\n /** Current status of the session */\n status: SessionStatus;\n}\n\n/**\n * Resolves possible file paths for a session ID across all status directories.\n *\n * @param id - Session ID (timestamp format)\n * @param config - Directory configuration\n * @returns Array of possible file paths in search order\n *\n * @example\n * ```typescript\n * const paths = resolveSessionPaths('2026-01-13_08-01-05', {\n * todoDir: '.spx/sessions/todo',\n * doingDir: '.spx/sessions/doing',\n * archiveDir: '.spx/sessions/archive',\n * });\n * // => [\n * // '.spx/sessions/todo/2026-01-13_08-01-05.md',\n * // '.spx/sessions/doing/2026-01-13_08-01-05.md',\n * // '.spx/sessions/archive/2026-01-13_08-01-05.md',\n * // ]\n * ```\n */\nexport function resolveSessionPaths(\n id: string,\n config: SessionDirectoryConfig = DEFAULT_SESSION_CONFIG,\n): string[] {\n const filename = `${id}.md`;\n\n return [\n `${config.todoDir}/${filename}`,\n `${config.doingDir}/${filename}`,\n `${config.archiveDir}/${filename}`,\n ];\n}\n\n/**\n * Formats session content for display with metadata header.\n *\n * @param content - Raw session file content\n * @param options - Display options including status\n * @returns Formatted output string with metadata header\n *\n * @example\n * ```typescript\n * const output = formatShowOutput(sessionContent, { status: 'todo' });\n * // => \"Status: todo\\nPriority: high\\n---\\n# Session Content...\"\n * ```\n */\nexport function formatShowOutput(\n content: string,\n options: ShowOutputOptions,\n): string {\n const metadata = parseSessionMetadata(content);\n\n // Build header with extracted metadata\n const headerLines: string[] = [\n `${SESSION_SHOW_LABEL.STATUS}: ${options.status}`,\n `${SESSION_SHOW_LABEL.PRIORITY}: ${metadata.priority}`,\n `${SESSION_SHOW_LABEL.GIT_REF}: ${metadata.git_ref}`,\n `${SESSION_SHOW_LABEL.GOAL}: ${metadata.goal}`,\n `${SESSION_SHOW_LABEL.NEXT_STEP}: ${metadata.next_step}`,\n `${SESSION_SHOW_LABEL.CREATED}: ${metadata.created_at ?? \"\"}`,\n `${SESSION_SHOW_LABEL.AGENT_SESSION}: ${metadata.agent_session_id ?? \"\"}`,\n ];\n\n // Combine header with separator and original content\n const header = headerLines.join(\"\\n\");\n const separator = \"\\n\" + SESSION_SHOW_SEPARATOR_CHAR.repeat(SESSION_SHOW_SEPARATOR_WIDTH) + \"\\n\\n\";\n\n return header + separator + content;\n}\n","/**\n * Session listing and sorting utilities.\n *\n * @module session/list\n */\n\nimport { parse as parseYaml } from \"yaml\";\n\nimport { parseSessionId } from \"./timestamp\";\nimport {\n DEFAULT_PRIORITY,\n PRIORITY_ORDER,\n type Session,\n SESSION_FRONT_MATTER,\n SESSION_PRIORITY,\n type SessionMetadata,\n type SessionPriority,\n} from \"./types\";\n\n/**\n * Regular expression to match YAML front matter.\n * Matches content between opening `---` and closing `---` or `...`\n */\nconst FRONT_MATTER_PATTERN = /^---\\r?\\n([\\s\\S]*?)\\r?\\n(?:---|\\.\\.\\.)\\r?\\n?/;\nconst SESSION_PRIORITY_VALUES = Object.values(SESSION_PRIORITY);\n\nexport const DEFAULT_SESSION_METADATA: SessionMetadata = {\n priority: DEFAULT_PRIORITY,\n git_ref: \"\",\n goal: \"\",\n next_step: \"\",\n specs: [],\n files: [],\n} as const;\n\nfunction defaultSessionMetadata(): SessionMetadata {\n return {\n ...DEFAULT_SESSION_METADATA,\n specs: [],\n files: [],\n };\n}\n\n/**\n * Validates if a value is a valid priority.\n */\nfunction isValidPriority(value: unknown): value is SessionPriority {\n return typeof value === \"string\" && SESSION_PRIORITY_VALUES.some((priority) => priority === value);\n}\n\n/**\n * Parses YAML front matter from session content to extract metadata.\n *\n * @param content - Full session file content\n * @returns Extracted metadata with defaults for missing fields\n *\n * @example\n * ```typescript\n * const metadata = parseSessionMetadata(`---\n * priority: high\n * goal: Fix failing checks\n * next_step: Run validation\n * ---\n * # Session content`);\n * // => { priority: 'high', goal: 'Fix failing checks', next_step: 'Run validation', ... }\n * ```\n */\nexport function parseSessionMetadata(content: string): SessionMetadata {\n const match = FRONT_MATTER_PATTERN.exec(content);\n\n if (!match) {\n return defaultSessionMetadata();\n }\n\n try {\n const parsed = parseYaml(match[1]) as Record<string, unknown>;\n\n if (!parsed || typeof parsed !== \"object\") {\n return defaultSessionMetadata();\n }\n\n const rawPriority = parsed[SESSION_FRONT_MATTER.PRIORITY];\n const priority = isValidPriority(rawPriority) ? rawPriority : DEFAULT_PRIORITY;\n\n const metadata: SessionMetadata = {\n ...defaultSessionMetadata(),\n priority,\n };\n\n const gitRef = parsed[SESSION_FRONT_MATTER.GIT_REF];\n metadata.git_ref = typeof gitRef === \"string\" ? gitRef : DEFAULT_SESSION_METADATA.git_ref;\n\n const goal = parsed[SESSION_FRONT_MATTER.GOAL];\n metadata.goal = typeof goal === \"string\" ? goal : DEFAULT_SESSION_METADATA.goal;\n\n const nextStep = parsed[SESSION_FRONT_MATTER.NEXT_STEP];\n metadata.next_step = typeof nextStep === \"string\" ? nextStep : DEFAULT_SESSION_METADATA.next_step;\n\n const createdAt = parsed[SESSION_FRONT_MATTER.CREATED_AT];\n if (typeof createdAt === \"string\") metadata.created_at = createdAt;\n\n const agentSessionId = parsed[SESSION_FRONT_MATTER.AGENT_SESSION_ID];\n if (typeof agentSessionId === \"string\") metadata.agent_session_id = agentSessionId;\n\n const specs = parsed[SESSION_FRONT_MATTER.SPECS];\n if (Array.isArray(specs)) {\n metadata.specs = specs.filter((s): s is string => typeof s === \"string\");\n }\n\n const files = parsed[SESSION_FRONT_MATTER.FILES];\n if (Array.isArray(files)) {\n metadata.files = files.filter((f): f is string => typeof f === \"string\");\n }\n\n return metadata;\n } catch {\n // Malformed YAML, return defaults\n return defaultSessionMetadata();\n }\n}\n\n/**\n * Sorts sessions by priority (high first) then by timestamp (newest first).\n *\n * @param sessions - Array of sessions to sort\n * @returns New sorted array (does not mutate input)\n *\n * @example\n * ```typescript\n * const sorted = sortSessions([\n * { id: 'a', metadata: { priority: 'low' } },\n * { id: 'b', metadata: { priority: 'high' } },\n * ]);\n * // => [{ id: 'b', ... }, { id: 'a', ... }]\n * ```\n */\nexport function sortSessions(sessions: Session[]): Session[] {\n return [...sessions].sort((a, b) => {\n // First: sort by priority (high = 0, medium = 1, low = 2)\n const priorityA = PRIORITY_ORDER[a.metadata.priority];\n const priorityB = PRIORITY_ORDER[b.metadata.priority];\n\n if (priorityA !== priorityB) {\n return priorityA - priorityB;\n }\n\n // Second: sort by timestamp (newest first = descending)\n const dateA = parseSessionId(a.id);\n const dateB = parseSessionId(b.id);\n\n // Handle invalid session IDs by treating them as oldest\n if (!dateA && !dateB) return 0;\n if (!dateA) return 1; // a goes after b\n if (!dateB) return -1; // b goes after a\n\n return dateB.getTime() - dateA.getTime();\n });\n}\n","/**\n * Session timestamp utilities for generating and parsing session IDs.\n *\n * Session IDs use the format YYYY-MM-DD_HH-mm-ss.\n *\n * @module session/timestamp\n */\n\n/**\n * Regular expression pattern for validating session IDs.\n * Format: YYYY-MM-DD_HH-mm-ss (all components zero-padded)\n *\n * Exported for use in validation and testing.\n */\nexport const SESSION_ID_PATTERN = /^(\\d{4})-(\\d{2})-(\\d{2})_(\\d{2})-(\\d{2})-(\\d{2})$/;\n\n/**\n * Separator between date and time components in session IDs.\n */\nexport const SESSION_ID_SEPARATOR = \"_\";\n\n/**\n * Options for generating session IDs.\n */\nexport interface GenerateSessionIdOptions {\n /**\n * Function that returns the current time.\n * Defaults to `() => new Date()` for production use.\n * Injectable for deterministic testing.\n */\n now?: () => Date;\n}\n\n/**\n * Generates a session ID from the current (or injected) time.\n *\n * @param options - Optional configuration including time source\n * @returns Session ID in format YYYY-MM-DD_HH-mm-ss\n *\n * @example\n * ```typescript\n * // Production usage\n * const id = generateSessionId();\n * // => \"2026-01-13_08-01-05\"\n *\n * // Testing with injected time\n * const id = generateSessionId({ now: () => new Date('2026-01-13T08:01:05') });\n * // => \"2026-01-13_08-01-05\"\n * ```\n */\nexport function generateSessionId(options: GenerateSessionIdOptions = {}): string {\n const now = options.now ?? (() => new Date());\n const date = now();\n\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, \"0\");\n const day = String(date.getDate()).padStart(2, \"0\");\n const hours = String(date.getHours()).padStart(2, \"0\");\n const minutes = String(date.getMinutes()).padStart(2, \"0\");\n const seconds = String(date.getSeconds()).padStart(2, \"0\");\n\n return `${year}-${month}-${day}${SESSION_ID_SEPARATOR}${hours}-${minutes}-${seconds}`;\n}\n\n/**\n * Parses a session ID string back into a Date object.\n *\n * @param id - Session ID string to parse\n * @returns Date object if valid, null if invalid format\n *\n * @example\n * ```typescript\n * const date = parseSessionId('2026-01-13_08-01-05');\n * // => Date representing 2026-01-13T08:01:05 (local time)\n *\n * const invalid = parseSessionId('invalid-format');\n * // => null\n * ```\n */\nexport function parseSessionId(id: string): Date | null {\n const match = SESSION_ID_PATTERN.exec(id);\n\n if (!match) {\n return null;\n }\n\n const [, yearStr, monthStr, dayStr, hoursStr, minutesStr, secondsStr] = match;\n\n const year = parseInt(yearStr, 10);\n const month = parseInt(monthStr, 10) - 1; // Date months are 0-indexed\n const day = parseInt(dayStr, 10);\n const hours = parseInt(hoursStr, 10);\n const minutes = parseInt(minutesStr, 10);\n const seconds = parseInt(secondsStr, 10);\n\n // Validate component ranges\n if (month < 0 || month > 11) return null;\n if (day < 1 || day > 31) return null;\n if (hours < 0 || hours > 23) return null;\n if (minutes < 0 || minutes > 59) return null;\n if (seconds < 0 || seconds > 59) return null;\n\n return new Date(year, month, day, hours, minutes, seconds);\n}\n","/**\n * Session type definitions for the session management domain.\n *\n * @module session/types\n */\n\n/**\n * Priority levels for session ordering.\n * Sessions are sorted: high → medium → low\n */\nexport const SESSION_PRIORITY = {\n HIGH: \"high\",\n MEDIUM: \"medium\",\n LOW: \"low\",\n} as const;\n\nexport type SessionPriority = (typeof SESSION_PRIORITY)[keyof typeof SESSION_PRIORITY];\n\n/**\n * All valid session statuses, derived from directory structure.\n * This is the single source of truth — SessionStatus type derives from it.\n */\nexport const SESSION_STATUSES = [\"todo\", \"doing\", \"archive\"] as const;\n\n/**\n * Status derived from directory location.\n */\nexport type SessionStatus = (typeof SESSION_STATUSES)[number];\n\n/**\n * Default statuses shown by `spx session list` when no --status filter is provided.\n * Excludes archive — use `--status archive` to see archived sessions.\n */\nexport const DEFAULT_LIST_STATUSES: readonly SessionStatus[] = [\"doing\", \"todo\"] as const;\n\n/**\n * Priority sort order (lower number = higher priority).\n */\nexport const PRIORITY_ORDER: Record<SessionPriority, number> = {\n [SESSION_PRIORITY.HIGH]: 0,\n [SESSION_PRIORITY.MEDIUM]: 1,\n [SESSION_PRIORITY.LOW]: 2,\n} as const;\n\n/**\n * Default priority when not specified in YAML front matter.\n */\nexport const DEFAULT_PRIORITY: SessionPriority = SESSION_PRIORITY.MEDIUM;\n\n/**\n * YAML front matter keys for session files.\n * Single source of truth for the serialized session schema.\n */\nexport const SESSION_FRONT_MATTER = {\n PRIORITY: \"priority\",\n GIT_REF: \"git_ref\",\n GOAL: \"goal\",\n NEXT_STEP: \"next_step\",\n CREATED_AT: \"created_at\",\n AGENT_SESSION_ID: \"agent_session_id\",\n SPECS: \"specs\",\n FILES: \"files\",\n} as const;\n\n/**\n * Metadata extracted from session YAML front matter.\n */\nexport interface SessionMetadata {\n /** Priority level for sorting */\n priority: SessionPriority;\n /** Git ref the session was cut from — a branch name (root worktree on a branch) or a commit SHA (detached) */\n git_ref: string;\n /** Handoff goal */\n goal: string;\n /** First action for the next agent */\n next_step: string;\n /** Spec files to auto-inject on pickup */\n specs: string[];\n /** Code files to auto-inject on pickup */\n files: string[];\n /** ISO 8601 timestamp when session was created */\n created_at?: string;\n /** Agent session ID from CLAUDE_SESSION_ID or CODEX_THREAD_ID at handoff time */\n agent_session_id?: string;\n}\n\n/**\n * Complete session information including status and metadata.\n */\nexport interface Session {\n /** Session ID (timestamp format: YYYY-MM-DD_HH-mm-ss) */\n id: string;\n /** Status derived from directory location */\n status: SessionStatus;\n /** Metadata from YAML front matter */\n metadata: SessionMetadata;\n /** Full path to session file */\n path: string;\n}\n","/**\n * Session handoff CLI command handler.\n *\n * Creates a new session for handoff to another agent context. Caller-supplied\n * structured fields come from a JSON object at the start of stdin; the body is\n * the remaining bytes verbatim. The on-disk file format remains YAML\n * frontmatter + markdown body, written through the `yaml` package's\n * `stringify`.\n *\n * @module commands/session/handoff\n */\n\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport { join, resolve } from \"node:path\";\n\nimport { stringify as stringifyYaml } from \"yaml\";\n\nimport { SESSION_FRONT_MATTER_CLOSE, SESSION_FRONT_MATTER_OPEN } from \"@/domains/session/create\";\nimport {\n SessionInvalidContentError,\n SessionInvalidGoalError,\n SessionInvalidNextStepError,\n} from \"@/domains/session/errors\";\nimport { resolveHandoffGitRef } from \"@/domains/session/handoff-base\";\nimport { parseHandoffInput } from \"@/domains/session/parse-handoff-input\";\nimport { generateSessionId } from \"@/domains/session/timestamp\";\nimport { SESSION_FRONT_MATTER } from \"@/domains/session/types\";\nimport {\n detectGitCommonDirProductRoot,\n getCurrentBranch,\n getHeadSha,\n type GitDependencies,\n isWorkingTreeClean,\n ORIGIN_REF_PREFIX,\n resolveDefaultBranch,\n resolveRefSha,\n resolveSessionConfig,\n} from \"@/git/root\";\n\n/**\n * Options for the handoff command.\n */\nexport interface HandoffOptions {\n /** Session content from stdin. */\n content?: string;\n /** Custom sessions directory */\n sessionsDir?: string;\n /** Current working directory for Git context detection */\n cwd?: string;\n /** Injectable Git command dependencies for tests */\n deps?: GitDependencies;\n}\n\n/**\n * Result of the handoff command. The descriptor writes `output` to stdout. The\n * handler does not touch process streams.\n */\nexport interface HandoffResult {\n /** Stdout text including `<HANDOFF_ID>` and `<SESSION_FILE>` tags. */\n output: string;\n}\n\n/**\n * Gathers every git fact the handoff-base gate evaluates (I/O), then resolves\n * the git ref to record. Every fact a linked-worktree refusal checklist renders\n * is gathered regardless of branch state, so the resolver evaluates every base\n * prerequisite and surfaces it — never short-circuiting on an earlier fact.\n */\nasync function resolveSessionGitRef(\n cwd: string | undefined,\n deps: GitDependencies | undefined,\n): Promise<string> {\n const [branch, headSha, gitRoots] = await Promise.all([\n getCurrentBranch(cwd, deps),\n getHeadSha(cwd, deps),\n detectGitCommonDirProductRoot(cwd, deps),\n ]);\n\n // `detectGitCommonDirProductRoot` reads `--show-toplevel` once and returns both\n // the worktree root and the Git common-dir product root, so no second\n // `--show-toplevel` is needed for the current-worktree path.\n const currentWorktreePath = gitRoots.worktreeRoot;\n const rootWorktreePath = gitRoots.productDir;\n // The root worktree is the one whose toplevel is the Git common-dir product\n // root; a linked worktree resolves to a path beneath it.\n const isRoot = currentWorktreePath === rootWorktreePath;\n\n // The clean-tree and origin facts feed only the linked-worktree refusal\n // checklist; a root-worktree base (permitted regardless of HEAD state) and a\n // non-git base never consult them, so gather them only for a linked worktree\n // in a git repository. Every linked worktree — detached or on a branch — still\n // gathers all of them, so the resolver evaluates every prerequisite.\n let isClean = false;\n let defaultBranch: string | null = null;\n let defaultTipSha: string | null = null;\n if (gitRoots.isGitRepo && !isRoot) {\n [isClean, defaultBranch] = await Promise.all([\n isWorkingTreeClean(cwd, deps),\n resolveDefaultBranch(cwd, deps),\n ]);\n defaultTipSha = defaultBranch === null\n ? null\n : await resolveRefSha(`${ORIGIN_REF_PREFIX}${defaultBranch}`, cwd, deps);\n }\n\n return resolveHandoffGitRef({\n isGitRepo: gitRoots.isGitRepo,\n isRootWorktree: isRoot,\n branch,\n headSha,\n isClean,\n defaultBranch,\n defaultTipSha,\n currentWorktreePath,\n rootWorktreePath,\n });\n}\n\n/**\n * Executes the handoff command.\n *\n * Creates a new session in the todo directory for pickup by another context.\n * Output includes `<HANDOFF_ID>` and `<SESSION_FILE>` tags for parsing by\n * automation tools.\n *\n * Caller-supplied structured fields come from a JSON object at the start of\n * stdin; bytes after the JSON object form the markdown body verbatim. The\n * CLI prefills `created_at` from the system clock, `git_ref` from the\n * handoff-base gate (branch name in the root worktree on a branch, HEAD SHA\n * when detached, or the `origin/<default>` tip SHA in a clean detached linked\n * worktree), and `agent_session_id` from `$CLAUDE_SESSION_ID` (falling back to\n * `$CODEX_THREAD_ID`).\n *\n * Canonical invocation:\n *\n * printf '%s\\n' '{\"priority\":\"high\",\"goal\":\"...\",\"next_step\":\"...\"}' '# Body' | spx session handoff\n *\n * @param options - Command options\n * @returns A `HandoffResult` whose `output` carries the `<HANDOFF_ID>` and\n * `<SESSION_FILE>` tags for the descriptor to write to stdout.\n * @throws {SessionInvalidContentError} When stdin is empty or whitespace-only\n * @throws {SessionLegacyFrontmatterInputError} When stdin opens with `---\\n`\n * @throws {SessionInvalidJsonHeaderError} When the JSON header is malformed\n * or fails caller-field schema validation\n * @throws {SessionInvalidGoalError} When the parsed `goal` is empty\n * @throws {SessionInvalidNextStepError} When the parsed `next_step` is empty\n * @throws {SessionHandoffBaseError} When the git work context cannot anchor a base\n */\nexport async function handoffCommand(options: HandoffOptions): Promise<HandoffResult> {\n const { config } = await resolveSessionConfig({\n sessionsDir: options.sessionsDir,\n cwd: options.cwd,\n deps: options.deps,\n });\n\n const content = options.content;\n if (content === undefined || content.trim().length === 0) {\n throw new SessionInvalidContentError(\"Session content cannot be empty\");\n }\n\n const { header, body } = parseHandoffInput(content);\n\n if (header.goal.length === 0) {\n throw new SessionInvalidGoalError();\n }\n if (header.next_step.length === 0) {\n throw new SessionInvalidNextStepError();\n }\n\n const gitRef = await resolveSessionGitRef(options.cwd, options.deps);\n\n const sessionId = generateSessionId();\n const agentSessionId = process.env.CLAUDE_SESSION_ID ?? process.env.CODEX_THREAD_ID;\n const createdAt = new Date().toISOString();\n\n const frontMatterObject: Record<string, unknown> = {\n [SESSION_FRONT_MATTER.PRIORITY]: header.priority,\n [SESSION_FRONT_MATTER.CREATED_AT]: createdAt,\n [SESSION_FRONT_MATTER.GIT_REF]: gitRef,\n [SESSION_FRONT_MATTER.GOAL]: header.goal,\n [SESSION_FRONT_MATTER.NEXT_STEP]: header.next_step,\n [SESSION_FRONT_MATTER.SPECS]: [...header.specs],\n [SESSION_FRONT_MATTER.FILES]: [...header.files],\n };\n if (agentSessionId !== undefined) {\n frontMatterObject[SESSION_FRONT_MATTER.AGENT_SESSION_ID] = agentSessionId;\n }\n\n const yaml = stringifyYaml(frontMatterObject, { defaultStringType: \"QUOTE_DOUBLE\" }).trimEnd();\n const fullContent = `${SESSION_FRONT_MATTER_OPEN}${yaml}${SESSION_FRONT_MATTER_CLOSE}${body}`;\n\n const filename = `${sessionId}.md`;\n const sessionPath = join(config.todoDir, filename);\n const absolutePath = resolve(sessionPath);\n\n await mkdir(config.todoDir, { recursive: true });\n await writeFile(sessionPath, fullContent, \"utf-8\");\n\n const output =\n `Created handoff session <HANDOFF_ID>${sessionId}</HANDOFF_ID>\\n<SESSION_FILE>${absolutePath}</SESSION_FILE>`;\n return { output };\n}\n","/**\n * Session creation utilities — YAML frontmatter delimiters and the\n * `stringifySessionFrontMatter` writer used by `spx session handoff` and the\n * session test harness.\n *\n * The JSON-prefix input wire format is parsed by\n * `src/domains/session/parse-handoff-input.ts`; this module is responsible\n * only for emitting the on-disk YAML frontmatter shape.\n *\n * @module session/create\n */\n\nimport { stringify as stringifyYaml } from \"yaml\";\n\nimport { SESSION_FRONT_MATTER, type SessionPriority } from \"./types\";\n\nexport const SESSION_FRONT_MATTER_DELIMITER = \"---\";\nexport const SESSION_FRONT_MATTER_OPEN = `${SESSION_FRONT_MATTER_DELIMITER}\\n`;\nexport const SESSION_FRONT_MATTER_CLOSE = `\\n${SESSION_FRONT_MATTER_DELIMITER}\\n`;\n\nexport interface SessionFrontMatterInput {\n readonly priority: SessionPriority;\n readonly git_ref?: string;\n readonly goal: string;\n readonly next_step: string;\n readonly specs?: readonly string[];\n readonly files?: readonly string[];\n}\n\nexport function stringifySessionFrontMatter(input: SessionFrontMatterInput): string {\n return stringifyYaml({\n [SESSION_FRONT_MATTER.PRIORITY]: input.priority,\n ...(input.git_ref === undefined ? {} : { [SESSION_FRONT_MATTER.GIT_REF]: input.git_ref }),\n [SESSION_FRONT_MATTER.GOAL]: input.goal,\n [SESSION_FRONT_MATTER.NEXT_STEP]: input.next_step,\n [SESSION_FRONT_MATTER.SPECS]: input.specs ?? [],\n [SESSION_FRONT_MATTER.FILES]: input.files ?? [],\n }, { defaultStringType: \"QUOTE_DOUBLE\" }).trimEnd();\n}\n\nexport function buildSessionFrontMatterContent(\n frontMatterLines: readonly string[],\n body: string,\n closeDelimiter: string = SESSION_FRONT_MATTER_DELIMITER,\n): string {\n return `${SESSION_FRONT_MATTER_OPEN}${frontMatterLines.join(\"\\n\")}\\n${closeDelimiter}\\n${body}`;\n}\n","/**\n * The handoff-base gate: resolves the git ref a handoff session records and\n * refuses a work context from which the recorded base would not be reachable\n * by a resuming agent.\n *\n * Pure over the supplied git facts — the handler gathers the facts via the\n * git primitives in `@/git/root` and the descriptor owns process I/O. A refused\n * linked-worktree handoff throws {@link SessionHandoffBaseError} carrying the\n * resolved facts and the per-prerequisite evaluation; a non-git base throws it\n * marked `silent`, so the descriptor writes nothing; any other git refusal\n * (e.g. a root worktree with no reachable HEAD) carries no checklist and is not\n * silent, so the descriptor writes a plain diagnostic.\n *\n * @module domains/session/handoff-base\n */\n\nimport { SessionHandoffBaseError } from \"./errors\";\nimport {\n HANDOFF_BASE_PREREQUISITE_LABEL,\n HANDOFF_BASE_REMEDY,\n type HandoffBaseChecklist,\n type HandoffBasePrerequisite,\n} from \"./handoff-base-checklist\";\n\n/**\n * Git facts the handoff-base gate evaluates. The handler gathers these via the\n * git primitives before calling {@link resolveHandoffGitRef}. Every fact a\n * linked-worktree refusal checklist renders is present, so the resolver\n * evaluates every prerequisite without re-reading git.\n */\nexport interface HandoffGitFacts {\n /** Whether `cwd` is inside a git repository at all. `false` → silent refusal. */\n readonly isGitRepo: boolean;\n /** Whether `cwd` is the repository's root worktree (Git common-dir product root). */\n readonly isRootWorktree: boolean;\n /** The checked-out branch name, or null when HEAD is detached. */\n readonly branch: string | null;\n /** The HEAD commit SHA, or null when unavailable. */\n readonly headSha: string | null;\n /** Whether the working tree is clean. */\n readonly isClean: boolean;\n /** The resolved default branch name, or null when `origin/HEAD` is unset. */\n readonly defaultBranch: string | null;\n /** The commit SHA at the tip of `origin/<default>`, or null when unresolved. */\n readonly defaultTipSha: string | null;\n /** The absolute path of the worktree handoff runs from. */\n readonly currentWorktreePath: string;\n /** The absolute path of the repository's root worktree. */\n readonly rootWorktreePath: string;\n}\n\n/**\n * The detached HEAD commit SHA when HEAD sits exactly at the resolved\n * `origin/<default>` tip, or null otherwise. Returning the SHA rather than a\n * boolean lets the caller record the permitted base without re-narrowing\n * `headSha`.\n */\nfunction detachedDefaultTipSha(facts: HandoffGitFacts): string | null {\n const atTip = facts.branch === null\n && facts.headSha !== null\n && facts.defaultTipSha !== null\n && facts.headSha === facts.defaultTipSha;\n return atTip ? facts.headSha : null;\n}\n\n/** The clean-working-tree prerequisite, with its commit-or-root remedy when unmet. */\nfunction cleanPrerequisite(facts: HandoffGitFacts): HandoffBasePrerequisite {\n return {\n label: HANDOFF_BASE_PREREQUISITE_LABEL.CLEAN_WORKING_TREE,\n met: facts.isClean,\n remedy: facts.isClean ? \"\" : HANDOFF_BASE_REMEDY.COMMIT_OR_ROOT,\n };\n}\n\n/**\n * The detached-at-default-tip prerequisite. When unmet, the remedy is to detach\n * to the tip — but only when a tip SHA resolves; when `origin/<default>` resolves\n * to no commit the only remedy is to hand off from the root worktree, matching\n * the unresolved tip the fact line renders.\n */\nfunction detachedAtTipPrerequisite(facts: HandoffGitFacts, met: boolean): HandoffBasePrerequisite {\n const remedy = facts.defaultTipSha === null\n ? HANDOFF_BASE_REMEDY.ROOT_ONLY\n : HANDOFF_BASE_REMEDY.DETACH_TO_TIP_OR_ROOT;\n return {\n label: HANDOFF_BASE_PREREQUISITE_LABEL.DETACHED_AT_DEFAULT_TIP,\n met,\n remedy: met ? \"\" : remedy,\n };\n}\n\n/** Assembles the refusal checklist from the resolved facts and prerequisites. */\nfunction buildChecklist(\n facts: HandoffGitFacts,\n prerequisites: readonly HandoffBasePrerequisite[],\n): HandoffBaseChecklist {\n return {\n defaultBranch: facts.defaultBranch,\n defaultTipSha: facts.defaultTipSha,\n headSha: facts.headSha,\n currentWorktreePath: facts.currentWorktreePath,\n rootWorktreePath: facts.rootWorktreePath,\n prerequisites,\n };\n}\n\n/**\n * Resolves the git ref a handoff session records, enforcing the handoff-base\n * gate.\n *\n * - **Non-git base**: throws a silent {@link SessionHandoffBaseError} (no checklist).\n * - **Root worktree** (any HEAD): records the branch name when HEAD is on a\n * branch, otherwise the HEAD commit SHA; a root worktree with no reachable\n * HEAD throws a non-silent diagnostic refusal (no checklist, `silent: false`),\n * since only the non-git base refuses silently.\n * - **Linked worktree**: every base prerequisite — a clean working tree and a\n * HEAD detached at the `origin/<default>` tip — is evaluated regardless of the\n * others. When all are met, records the tip SHA; otherwise throws a\n * {@link SessionHandoffBaseError} carrying the checklist.\n *\n * @param facts - The git facts gathered by the handler.\n * @returns The git ref to record in the session frontmatter.\n * @throws {SessionHandoffBaseError} When the work context cannot anchor a base.\n */\nexport function resolveHandoffGitRef(facts: HandoffGitFacts): string {\n // A non-git base resolves no reachable commit and refuses silently.\n if (!facts.isGitRepo) {\n throw new SessionHandoffBaseError({ silent: true });\n }\n\n if (facts.isRootWorktree) {\n if (facts.branch !== null) return facts.branch;\n if (facts.headSha !== null) return facts.headSha;\n // A root worktree with no reachable HEAD is a git refusal, not the non-git\n // case — it carries a plain diagnostic rather than refusing silently.\n throw new SessionHandoffBaseError();\n }\n\n // Linked worktree: evaluate every prerequisite so the checklist omits none.\n const tipSha = detachedDefaultTipSha(facts);\n const prerequisites: readonly HandoffBasePrerequisite[] = [\n cleanPrerequisite(facts),\n detachedAtTipPrerequisite(facts, tipSha !== null),\n ];\n\n if (facts.isClean && tipSha !== null) {\n return tipSha;\n }\n\n throw new SessionHandoffBaseError({ checklist: buildChecklist(facts, prerequisites) });\n}\n","/**\n * Pure parser for the `spx session handoff` JSON-prefix wire format.\n *\n * The wire format is a single JSON object at the start of stdin holding\n * caller-supplied structured fields, immediately followed by the body bytes\n * verbatim. An optional single LF or CRLF between the closing `}` and the\n * body is consumed as a separator.\n *\n * @module domains/session/parse-handoff-input\n */\n\nimport { SessionInvalidJsonHeaderError, SessionLegacyFrontmatterInputError } from \"@/domains/session/errors\";\nimport {\n DEFAULT_PRIORITY,\n SESSION_FRONT_MATTER,\n SESSION_PRIORITY,\n type SessionPriority,\n} from \"@/domains/session/types\";\n\nconst LEGACY_FRONTMATTER_PREFIX = /^---\\r?\\n/;\nconst JSON_OBJECT_OPEN_CHAR = \"{\";\nconst CARRIAGE_RETURN_CHAR_CODE = \"\\r\".charCodeAt(0);\nconst NEWLINE_CHAR_CODE = \"\\n\".charCodeAt(0);\nconst BACKSLASH_CHAR_CODE = \"\\\\\".charCodeAt(0);\nconst DOUBLE_QUOTE_CHAR_CODE = \"\\\"\".charCodeAt(0);\nconst OPEN_BRACE_CHAR_CODE = \"{\".charCodeAt(0);\nconst CLOSE_BRACE_CHAR_CODE = \"}\".charCodeAt(0);\nconst UNBALANCED_HEADER_END = -1;\nconst LF_SEPARATOR_LENGTH = 1;\nconst CRLF_SEPARATOR_LENGTH = 2;\n\nconst SESSION_PRIORITY_VALUES = new Set<string>(Object.values(SESSION_PRIORITY));\n\n/**\n * Caller-supplied structured fields recognized by `parseHandoffInput`.\n *\n * CLI-prefilled fields (`branch`, `worktree`, `created_at`, `agent_session_id`)\n * are not part of this shape and are silently ignored if the caller includes\n * them in the JSON object — the handoff command sources them from the git\n * context and process environment instead.\n */\nexport interface HandoffHeader {\n readonly priority: SessionPriority;\n readonly goal: string;\n readonly next_step: string;\n readonly specs: readonly string[];\n readonly files: readonly string[];\n}\n\n/**\n * Result of parsing `spx session handoff` stdin.\n */\nexport interface ParsedHandoffInput {\n readonly header: HandoffHeader;\n readonly body: string;\n}\n\n/**\n * Parses `spx session handoff` stdin per the JSON-prefix wire format.\n *\n * Algorithm:\n *\n * 1. Reject input opening with the YAML-frontmatter delimiter `---\\n` or\n * `---\\r\\n` with `SessionLegacyFrontmatterInputError`.\n * 2. Reject input that does not open with `{` with\n * `SessionInvalidJsonHeaderError`.\n * 3. Scan from the opening `{` to find the matching closing `}` while\n * respecting JSON string state — characters inside double-quoted strings\n * do not affect brace depth, and a backslash escapes the next character\n * inside a string. Unbalanced braces raise `SessionInvalidJsonHeaderError`.\n * 4. `JSON.parse` the header substring; parse failures raise\n * `SessionInvalidJsonHeaderError`.\n * 5. Validate the parsed object against the caller-field schema. Schema\n * failures raise `SessionInvalidJsonHeaderError`.\n * 6. Return the parsed header and the body bytes after the closing `}` (with\n * a single optional `LF` or `CRLF` separator consumed).\n *\n * @param stdin - Raw stdin bytes\n * @returns Parsed header and body\n * @throws {SessionLegacyFrontmatterInputError} When stdin opens with `---\\n`\n * @throws {SessionInvalidJsonHeaderError} When the header is malformed or\n * fails schema validation\n */\nexport function parseHandoffInput(stdin: string): ParsedHandoffInput {\n if (LEGACY_FRONTMATTER_PREFIX.test(stdin)) {\n throw new SessionLegacyFrontmatterInputError();\n }\n\n if (!stdin.startsWith(JSON_OBJECT_OPEN_CHAR)) {\n throw new SessionInvalidJsonHeaderError(\n \"stdin must begin with a JSON object opening with '{'\",\n );\n }\n\n const headerEnd = findJsonObjectEnd(stdin);\n if (headerEnd === UNBALANCED_HEADER_END) {\n throw new SessionInvalidJsonHeaderError(\n \"unbalanced JSON object — opening brace has no matching close\",\n );\n }\n\n const headerText = stdin.slice(0, headerEnd + 1);\n let parsed: unknown;\n try {\n parsed = JSON.parse(headerText);\n } catch (err) {\n const detail = err instanceof Error ? err.message : \"JSON.parse failed\";\n throw new SessionInvalidJsonHeaderError(detail);\n }\n\n const header = validateHandoffHeader(parsed);\n\n const bodyStart = consumeOptionalBodySeparator(stdin, headerEnd + 1);\n\n return { header, body: stdin.slice(bodyStart) };\n}\n\nfunction consumeOptionalBodySeparator(stdin: string, bodyStart: number): number {\n if (\n stdin.charCodeAt(bodyStart) === CARRIAGE_RETURN_CHAR_CODE\n && stdin.charCodeAt(bodyStart + LF_SEPARATOR_LENGTH) === NEWLINE_CHAR_CODE\n ) {\n return bodyStart + CRLF_SEPARATOR_LENGTH;\n }\n\n if (stdin.charCodeAt(bodyStart) === NEWLINE_CHAR_CODE) {\n return bodyStart + LF_SEPARATOR_LENGTH;\n }\n\n return bodyStart;\n}\n\n/**\n * Scans `stdin` from index `0` (assumed to start with `{`) and returns the\n * index of the closing `}` that balances the opening brace.\n *\n * JSON string-state aware: characters inside a double-quoted string don't\n * affect brace depth, and a backslash inside a string escapes the next\n * character (so `\"\\\\\"\"` and `\"\\\"\"` are valid strings).\n *\n * @returns Index of the matching closing brace, or `UNBALANCED_HEADER_END`\n * when the opening brace has no matching close in `stdin`.\n */\nfunction findJsonObjectEnd(stdin: string): number {\n let depth = 0;\n let inString = false;\n for (let i = 0; i < stdin.length; i++) {\n const code = stdin.charCodeAt(i);\n if (inString) {\n if (code === BACKSLASH_CHAR_CODE) {\n // Skip the next character (an escape sequence is one logical unit).\n i += 1;\n continue;\n }\n if (code === DOUBLE_QUOTE_CHAR_CODE) {\n inString = false;\n }\n continue;\n }\n if (code === DOUBLE_QUOTE_CHAR_CODE) {\n inString = true;\n continue;\n }\n if (code === OPEN_BRACE_CHAR_CODE) {\n depth += 1;\n continue;\n }\n if (code === CLOSE_BRACE_CHAR_CODE) {\n depth -= 1;\n if (depth === 0) return i;\n }\n }\n return UNBALANCED_HEADER_END;\n}\n\n/**\n * Validates `parsed` against the JSON-prefix header schema and narrows the\n * result to `HandoffHeader`.\n *\n * Extra fields are silently dropped — callers who include CLI-prefilled\n * fields like `branch` or `worktree` in the JSON have those fields ignored,\n * preserving the \"caller-supplied branch and worktree are ignored\" invariant\n * by construction.\n */\nfunction validateHandoffHeader(parsed: unknown): HandoffHeader {\n if (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n throw new SessionInvalidJsonHeaderError(\"header must be a JSON object\");\n }\n const obj = parsed as Record<string, unknown>;\n\n const priority = ensurePriorityOrDefault(obj[SESSION_FRONT_MATTER.PRIORITY]);\n const goal = ensureStringOrEmpty(obj[SESSION_FRONT_MATTER.GOAL], SESSION_FRONT_MATTER.GOAL);\n const nextStep = ensureStringOrEmpty(obj[SESSION_FRONT_MATTER.NEXT_STEP], SESSION_FRONT_MATTER.NEXT_STEP);\n const specs = ensureStringArrayOrDefault(obj[SESSION_FRONT_MATTER.SPECS], SESSION_FRONT_MATTER.SPECS);\n const files = ensureStringArrayOrDefault(obj[SESSION_FRONT_MATTER.FILES], SESSION_FRONT_MATTER.FILES);\n\n return {\n priority,\n goal,\n next_step: nextStep,\n specs,\n files,\n };\n}\n\n/**\n * Coerces an optional JSON value to a recognized `SessionPriority`.\n *\n * Returns the default priority when the field is missing (`undefined`). Throws\n * `SessionInvalidJsonHeaderError` when the value is present but is not a\n * string matching one of the registered priority values.\n */\nfunction ensurePriorityOrDefault(value: unknown): SessionPriority {\n if (value === undefined) return DEFAULT_PRIORITY;\n if (typeof value !== \"string\" || !SESSION_PRIORITY_VALUES.has(value)) {\n throw new SessionInvalidJsonHeaderError(\n `${SESSION_FRONT_MATTER.PRIORITY} must be one of ${[...SESSION_PRIORITY_VALUES].join(\", \")}`,\n );\n }\n return value as SessionPriority;\n}\n\n/**\n * Coerces an optional JSON value to a string.\n *\n * Returns an empty string when the field is missing (`undefined`) so the\n * downstream non-empty validation in `handoffCommand` surfaces the\n * semantic-content error (`SessionInvalidGoalError` / `SessionInvalidNextStepError`)\n * rather than a structural `SessionInvalidJsonHeaderError`. Throws\n * `SessionInvalidJsonHeaderError` only when the value is present but is not\n * a string.\n */\nfunction ensureStringOrEmpty(value: unknown, fieldName: string): string {\n if (value === undefined) return \"\";\n if (typeof value !== \"string\") {\n throw new SessionInvalidJsonHeaderError(`${fieldName} must be a string`);\n }\n return value;\n}\n\n/**\n * Coerces an optional JSON value to a readonly string array.\n *\n * Returns an empty array when the field is missing (`undefined`). Throws\n * `SessionInvalidJsonHeaderError` when the value is present but not an array\n * of strings.\n */\nfunction ensureStringArrayOrDefault(value: unknown, fieldName: string): readonly string[] {\n if (value === undefined) return [];\n if (!Array.isArray(value)) {\n throw new SessionInvalidJsonHeaderError(`${fieldName} must be an array of strings`);\n }\n for (const item of value) {\n if (typeof item !== \"string\") {\n throw new SessionInvalidJsonHeaderError(`${fieldName} must be an array of strings`);\n }\n }\n return value as readonly string[];\n}\n","/**\n * Session list CLI command handler.\n *\n * @module commands/session/list\n */\n\nimport { readdir, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { parseSessionMetadata, sortSessions } from \"@/domains/session/list\";\nimport { SessionDirectoryConfig } from \"@/domains/session/show\";\nimport {\n DEFAULT_LIST_STATUSES,\n DEFAULT_PRIORITY,\n Session,\n SESSION_STATUSES,\n SessionStatus,\n} from \"@/domains/session/types\";\nimport { resolveSessionConfigSurfacingWarning, type SessionWarningHandler } from \"./resolve-config\";\n\nexport const SESSION_LIST_FORMAT = {\n TEXT: \"text\",\n JSON: \"json\",\n} as const;\n\nexport type SessionListFormat = (typeof SESSION_LIST_FORMAT)[keyof typeof SESSION_LIST_FORMAT];\n\nexport const SESSION_LIST_EMPTY_TEXT = \"(no sessions)\";\nconst SESSION_LIST_SUMMARY_SEPARATOR = \" -> \";\n\n/**\n * Options for the list command.\n * Note: status is string (not SessionStatus) because it comes from user input via Commander.js.\n * Validation happens inside listCommand before status is used.\n */\nexport interface ListOptions {\n /** Filter by status (validated against SESSION_STATUSES) */\n status?: string;\n /** Custom sessions directory */\n sessionsDir?: string;\n /** Receives the non-git-repo diagnostic for the descriptor to surface. */\n onWarning?: SessionWarningHandler;\n /** Output format */\n format?: SessionListFormat;\n}\n\n/**\n * Loads sessions from a specific directory.\n */\nasync function loadSessionsFromDir(\n dir: string,\n status: SessionStatus,\n): Promise<Session[]> {\n try {\n const files = await readdir(dir);\n const sessions: Session[] = [];\n\n for (const file of files) {\n if (!file.endsWith(\".md\")) continue;\n\n const id = file.replace(\".md\", \"\");\n const filePath = join(dir, file);\n const content = await readFile(filePath, \"utf-8\");\n const metadata = parseSessionMetadata(content);\n\n sessions.push({\n id,\n status,\n path: filePath,\n metadata,\n });\n }\n\n return sessions;\n } catch (error) {\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") {\n return [];\n }\n throw error;\n }\n}\n\n/**\n * Maps a session status to its directory path in the config.\n */\nconst STATUS_DIR_KEY: Record<SessionStatus, keyof SessionDirectoryConfig> = {\n todo: \"todoDir\",\n doing: \"doingDir\",\n archive: \"archiveDir\",\n};\n\n/**\n * Formats sessions for text output.\n */\nfunction formatTextOutput(sessions: Session[]): string {\n if (sessions.length === 0) {\n return ` ${SESSION_LIST_EMPTY_TEXT}`;\n }\n\n return sessions\n .map((s) => {\n const priority = s.metadata.priority !== DEFAULT_PRIORITY ? ` [${s.metadata.priority}]` : \"\";\n const summary = s.metadata.goal.length > 0 && s.metadata.next_step.length > 0\n ? ` ${s.metadata.goal}${SESSION_LIST_SUMMARY_SEPARATOR}${s.metadata.next_step}`\n : \"\";\n return ` ${s.id}${priority}${summary}`;\n })\n .join(\"\\n\");\n}\n\n/**\n * Executes the list command.\n *\n * @param options - Command options\n * @returns Formatted output for display\n */\n/**\n * Validates a user-supplied status string against SESSION_STATUSES.\n * Returns the validated SessionStatus or throws with valid values listed.\n */\nfunction validateStatus(input: string): SessionStatus {\n if (SESSION_STATUSES.includes(input as SessionStatus)) {\n return input as SessionStatus;\n }\n throw new Error(\n `Invalid status: \"${input}\". Valid values: ${SESSION_STATUSES.join(\", \")}`,\n );\n}\n\nexport async function listCommand(options: ListOptions): Promise<string> {\n const config = await resolveSessionConfigSurfacingWarning(options.sessionsDir, options.onWarning);\n\n // Validate and resolve statuses before use.\n const statuses: readonly SessionStatus[] = options.status !== undefined\n ? [validateStatus(options.status)]\n : DEFAULT_LIST_STATUSES;\n\n const sessionsByStatus: Partial<Record<SessionStatus, Session[]>> = {};\n\n for (const status of statuses) {\n const dirKey = STATUS_DIR_KEY[status];\n const sessions = await loadSessionsFromDir(config[dirKey], status);\n sessionsByStatus[status] = sortSessions(sessions);\n }\n\n // Format output\n if (options.format === SESSION_LIST_FORMAT.JSON) {\n return JSON.stringify(sessionsByStatus, null, 2);\n }\n\n // Text format\n const lines: string[] = [];\n\n for (const status of statuses) {\n lines.push(`${status.toUpperCase()}:`);\n lines.push(formatTextOutput(sessionsByStatus[status] ?? []));\n lines.push(\"\");\n }\n\n return lines.join(\"\\n\").trim();\n}\n","/**\n * Session pickup CLI command handler.\n *\n * @module commands/session/pickup\n */\n\nimport { mkdir, readdir, readFile, rename } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { processBatch } from \"@/domains/session/batch\";\nimport { NoSessionsAvailableError } from \"@/domains/session/errors\";\nimport { parseSessionMetadata } from \"@/domains/session/list\";\nimport { buildClaimPaths, classifyClaimError, selectBestSession } from \"@/domains/session/pickup\";\nimport { formatShowOutput, SessionDirectoryConfig } from \"@/domains/session/show\";\nimport { Session, SESSION_STATUSES, SessionStatus } from \"@/domains/session/types\";\nimport { resolveSessionConfigSurfacingWarning, type SessionWarningHandler } from \"./resolve-config\";\n\n/** Status of sessions available for pickup. */\nconst PICKUP_SOURCE_STATUS: SessionStatus = SESSION_STATUSES[0]; // todo\n/** Status of sessions after being claimed. */\nconst PICKUP_TARGET_STATUS: SessionStatus = SESSION_STATUSES[1]; // doing\n\n/**\n * Options for the pickup command.\n */\nexport interface PickupOptions {\n /** Session IDs to pickup. Empty array is valid only with auto. */\n sessionIds: readonly string[];\n /** Auto-select highest priority session */\n auto?: boolean;\n /** Custom sessions directory */\n sessionsDir?: string;\n /** Receives the non-git-repo diagnostic for the descriptor to surface. */\n onWarning?: SessionWarningHandler;\n}\n\n/**\n * Loads sessions from the todo directory.\n */\nasync function loadTodoSessions(config: SessionDirectoryConfig): Promise<Session[]> {\n try {\n const files = await readdir(config.todoDir);\n const sessions: Session[] = [];\n\n for (const file of files) {\n if (!file.endsWith(\".md\")) continue;\n\n const id = file.replace(\".md\", \"\");\n const filePath = join(config.todoDir, file);\n const content = await readFile(filePath, \"utf-8\");\n const metadata = parseSessionMetadata(content);\n\n sessions.push({\n id,\n status: PICKUP_SOURCE_STATUS,\n path: filePath,\n metadata,\n });\n }\n\n return sessions;\n } catch (error) {\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") {\n return [];\n }\n throw error;\n }\n}\n\n/**\n * Claims one session from the todo queue and moves it to doing.\n */\nasync function pickupSingle(sessionId: string, config: SessionDirectoryConfig): Promise<string> {\n const paths = buildClaimPaths(sessionId, config);\n await mkdir(config.doingDir, { recursive: true });\n\n try {\n await rename(paths.source, paths.target);\n } catch (error) {\n throw classifyClaimError(error, sessionId);\n }\n\n const content = await readFile(paths.target, \"utf-8\");\n const output = formatShowOutput(content, { status: PICKUP_TARGET_STATUS });\n\n return `Claimed session <PICKUP_ID>${sessionId}</PICKUP_ID>\\n\\n${output}`;\n}\n\n/**\n * Executes the pickup command.\n *\n * Claims one or more sessions from the todo queue and moves them to doing.\n * Output includes one `<PICKUP_ID>` tag per claimed session for automation.\n *\n * @param options - Command options\n * @returns Formatted output for display with parseable session IDs\n * @throws {NoSessionsAvailableError} When no sessions in todo for auto mode\n * @throws {SessionNotAvailableError} When one or more sessions cannot be claimed\n * @throws {BatchError} When one or more explicit IDs fail\n */\nexport async function pickupCommand(options: PickupOptions): Promise<string> {\n const config = await resolveSessionConfigSurfacingWarning(options.sessionsDir, options.onWarning);\n\n if (options.auto) {\n if (options.sessionIds.length > 0) {\n throw new Error(\"Session IDs cannot be combined with --auto\");\n }\n\n const sessions = await loadTodoSessions(config);\n const selected = selectBestSession(sessions);\n\n if (!selected) {\n throw new NoSessionsAvailableError();\n }\n\n return pickupSingle(selected.id, config);\n }\n\n if (options.sessionIds.length === 0) {\n throw new Error(\"Either session ID or --auto flag is required\");\n }\n\n if (options.sessionIds.length === 1) {\n return pickupSingle(options.sessionIds[0], config);\n }\n\n return processBatch(options.sessionIds, (id) => pickupSingle(id, config));\n}\n","/**\n * Session pickup/claiming utilities.\n *\n * This module provides pure functions for atomic session claiming:\n * - Path construction for claim operations\n * - Error classification for claim failures\n * - Session selection for auto-pickup\n *\n * @module session/pickup\n */\n\nimport { SessionNotAvailableError } from \"./errors\";\nimport { parseSessionId } from \"./timestamp\";\nimport { PRIORITY_ORDER, type Session } from \"./types\";\n\n/**\n * Configuration for session claim paths.\n */\nexport interface ClaimPathConfig {\n /** Directory containing sessions to be claimed */\n todoDir: string;\n /** Directory for claimed sessions */\n doingDir: string;\n}\n\n/**\n * Result of building claim paths.\n */\nexport interface ClaimPaths {\n /** Source path (session in todo) */\n source: string;\n /** Target path (session in doing) */\n target: string;\n}\n\n/**\n * Builds source and target paths for claiming a session.\n *\n * @param sessionId - The session ID (timestamp format)\n * @param config - Directory configuration\n * @returns Source and target paths for the claim operation\n *\n * @example\n * ```typescript\n * const paths = buildClaimPaths(\"2026-01-13_08-01-05\", {\n * todoDir: \".spx/sessions/todo\",\n * doingDir: \".spx/sessions/doing\",\n * });\n * // => { source: \".spx/sessions/todo/2026-01-13_08-01-05.md\", target: \".spx/sessions/doing/2026-01-13_08-01-05.md\" }\n * ```\n */\nexport function buildClaimPaths(sessionId: string, config: ClaimPathConfig): ClaimPaths {\n return {\n source: `${config.todoDir}/${sessionId}.md`,\n target: `${config.doingDir}/${sessionId}.md`,\n };\n}\n\n/**\n * Classifies a filesystem error that occurred during claiming.\n *\n * When a claim operation fails, this function maps the raw filesystem\n * error to an appropriate domain error:\n * - ENOENT: Session was claimed by another agent (SessionNotAvailable)\n * - Other errors: Rethrown as-is\n *\n * @param error - The error from the claim operation\n * @param sessionId - The session ID being claimed\n * @returns A SessionNotAvailableError if ENOENT\n * @throws The original error if not ENOENT\n *\n * @example\n * ```typescript\n * const err = Object.assign(new Error(\"ENOENT\"), { code: \"ENOENT\" });\n * const classified = classifyClaimError(err, \"test-id\");\n * // => SessionNotAvailableError\n * ```\n */\nexport function classifyClaimError(error: unknown, sessionId: string): SessionNotAvailableError {\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") {\n return new SessionNotAvailableError(sessionId);\n }\n throw error;\n}\n\n/**\n * Selects the best session for auto-pickup based on priority and timestamp.\n *\n * Selection criteria:\n * 1. Highest priority (high > medium > low)\n * 2. Oldest timestamp (FIFO) for sessions with equal priority\n *\n * @param sessions - Available sessions to choose from\n * @returns The best session to claim, or null if no sessions available\n *\n * @example\n * ```typescript\n * const sessions = [\n * { id: \"low-1\", metadata: { priority: \"low\" } },\n * { id: \"high-1\", metadata: { priority: \"high\" } },\n * ];\n * const best = selectBestSession(sessions);\n * // => { id: \"high-1\", ... }\n * ```\n */\nexport function selectBestSession(sessions: Session[]): Session | null {\n if (sessions.length === 0) {\n return null;\n }\n\n // Sort by priority (high first) then by timestamp (oldest first for FIFO)\n const sorted = [...sessions].sort((a, b) => {\n // First: sort by priority (high = 0, medium = 1, low = 2)\n const priorityA = PRIORITY_ORDER[a.metadata.priority];\n const priorityB = PRIORITY_ORDER[b.metadata.priority];\n\n if (priorityA !== priorityB) {\n return priorityA - priorityB;\n }\n\n // Second: sort by timestamp (oldest first = FIFO = ascending)\n const dateA = parseSessionId(a.id);\n const dateB = parseSessionId(b.id);\n\n // Handle invalid session IDs by treating them as newest (go last)\n if (!dateA && !dateB) return 0;\n if (!dateA) return 1; // a goes after b\n if (!dateB) return -1; // b goes after a\n\n return dateA.getTime() - dateB.getTime();\n });\n\n return sorted[0];\n}\n","/**\n * Session prune CLI command handler.\n *\n * @module commands/session/prune\n */\n\nimport { readdir, readFile, unlink } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { parseSessionMetadata } from \"@/domains/session/list\";\nimport { DEFAULT_KEEP_COUNT, selectSessionsToDelete } from \"@/domains/session/prune\";\nimport { SessionDirectoryConfig } from \"@/domains/session/show\";\nimport { Session, SESSION_STATUSES, SessionStatus } from \"@/domains/session/types\";\nimport { resolveSessionConfigSurfacingWarning, type SessionWarningHandler } from \"./resolve-config\";\n\nexport { DEFAULT_KEEP_COUNT };\n\n/** Prune operates only on archived sessions. */\nconst PRUNE_STATUS: SessionStatus = SESSION_STATUSES[2]; // archive\n\nexport const SESSION_PRUNE_OUTPUT = {\n DELETED: \"Deleted\",\n WOULD_DELETE: \"Would delete\",\n} as const;\n\n/**\n * Options for the prune command.\n */\nexport interface PruneOptions {\n /** Number of sessions to keep (default: 5) */\n keep?: number;\n /** Show what would be deleted without actually deleting */\n dryRun?: boolean;\n /** Custom sessions directory */\n sessionsDir?: string;\n /** Receives the non-git-repo diagnostic for the descriptor to surface. */\n onWarning?: SessionWarningHandler;\n}\n\n/**\n * Error thrown when prune options are invalid.\n */\nexport class PruneValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"PruneValidationError\";\n }\n}\n\n/**\n * Validates prune options.\n *\n * @param options - Options to validate\n * @throws {PruneValidationError} When options are invalid\n */\nexport function validatePruneOptions(options: PruneOptions): void {\n if (options.keep !== undefined) {\n if (!Number.isInteger(options.keep) || options.keep < 1) {\n throw new PruneValidationError(\n `Invalid --keep value: ${options.keep}. Must be a positive integer.`,\n );\n }\n }\n}\n\n/**\n * Loads sessions from the archive directory.\n */\nasync function loadArchiveSessions(config: SessionDirectoryConfig): Promise<Session[]> {\n try {\n const files = await readdir(config.archiveDir);\n const sessions: Session[] = [];\n\n for (const file of files) {\n if (!file.endsWith(\".md\")) continue;\n\n const id = file.replace(\".md\", \"\");\n const filePath = join(config.archiveDir, file);\n const content = await readFile(filePath, \"utf-8\");\n const metadata = parseSessionMetadata(content);\n\n sessions.push({\n id,\n status: PRUNE_STATUS,\n path: filePath,\n metadata,\n });\n }\n\n return sessions;\n } catch (error) {\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") {\n return [];\n }\n throw error;\n }\n}\n\n/**\n * Executes the prune command.\n *\n * @param options - Command options\n * @returns Formatted output for display\n * @throws {PruneValidationError} When options are invalid\n */\nexport async function pruneCommand(options: PruneOptions): Promise<string> {\n // Validate options\n validatePruneOptions(options);\n\n const keep = options.keep ?? DEFAULT_KEEP_COUNT;\n const dryRun = options.dryRun ?? false;\n\n const config = await resolveSessionConfigSurfacingWarning(options.sessionsDir, options.onWarning);\n\n // Load and sort sessions\n const sessions = await loadArchiveSessions(config);\n const toPrune = selectSessionsToDelete(sessions, { keep });\n\n if (toPrune.length === 0) {\n return `No sessions to prune. ${sessions.length} sessions kept.`;\n }\n\n // Dry run mode\n if (dryRun) {\n const lines = [\n `${SESSION_PRUNE_OUTPUT.WOULD_DELETE} ${toPrune.length} sessions:`,\n ...toPrune.map((s) => ` - ${s.id}`),\n \"\",\n `${sessions.length - toPrune.length} sessions would be kept.`,\n ];\n return lines.join(\"\\n\");\n }\n\n // Delete sessions\n for (const session of toPrune) {\n await unlink(session.path);\n }\n\n const lines = [\n `${SESSION_PRUNE_OUTPUT.DELETED} ${toPrune.length} sessions:`,\n ...toPrune.map((s) => ` - ${s.id}`),\n \"\",\n `${sessions.length - toPrune.length} sessions kept.`,\n ];\n return lines.join(\"\\n\");\n}\n","/**\n * Session pruning utilities for cleaning up old sessions.\n *\n * @module session/prune\n */\n\nimport { parseSessionId } from \"./timestamp\";\nimport type { Session } from \"./types\";\n\n/**\n * Default number of sessions to keep when pruning.\n */\nexport const DEFAULT_KEEP_COUNT = 5;\n\n/**\n * Options for selecting sessions to delete.\n */\nexport interface SelectSessionsOptions {\n /**\n * Number of most recent sessions to keep.\n * Defaults to DEFAULT_KEEP_COUNT (5).\n */\n keep?: number;\n}\n\n/**\n * Selects sessions to delete based on keep count.\n *\n * Sessions are sorted by timestamp (oldest first), and the oldest sessions\n * beyond the keep count are selected for deletion.\n *\n * @param sessions - Array of sessions to consider\n * @param options - Selection options including keep count\n * @returns Array of sessions to delete (oldest sessions beyond keep count)\n *\n * @example\n * ```typescript\n * // Given 10 sessions, keep 5 newest\n * const toDelete = selectSessionsToDelete(sessions, { keep: 5 });\n * // Returns the 5 oldest sessions\n *\n * // Using default keep count (5)\n * const toDelete = selectSessionsToDelete(sessions);\n * ```\n */\nexport function selectSessionsToDelete(\n sessions: Session[],\n options: SelectSessionsOptions = {},\n): Session[] {\n const keep = options.keep ?? DEFAULT_KEEP_COUNT;\n\n // If we have fewer sessions than the keep count, delete nothing\n if (sessions.length <= keep) {\n return [];\n }\n\n // Sort sessions by timestamp (oldest first for deletion selection)\n const sorted = [...sessions].sort((a, b) => {\n const dateA = parseSessionId(a.id);\n const dateB = parseSessionId(b.id);\n\n // Handle invalid session IDs by treating them as oldest (delete first)\n if (!dateA && !dateB) return 0;\n if (!dateA) return -1; // a (invalid) goes before b (to be deleted first)\n if (!dateB) return 1; // b (invalid) goes before a\n\n return dateA.getTime() - dateB.getTime();\n });\n\n // Return the oldest sessions (those beyond the keep count)\n const deleteCount = sessions.length - keep;\n return sorted.slice(0, deleteCount);\n}\n","/**\n * Session release CLI command handler.\n *\n * @module commands/session/release\n */\n\nimport { readdir, rename } from \"node:fs/promises\";\n\nimport { processBatch } from \"@/domains/session/batch\";\nimport { SessionNotClaimedError } from \"@/domains/session/errors\";\nimport { buildReleasePaths, findCurrentSession } from \"@/domains/session/release\";\nimport { SessionDirectoryConfig } from \"@/domains/session/show\";\nimport { resolveSessionConfigSurfacingWarning, type SessionWarningHandler } from \"./resolve-config\";\n\nexport const SESSION_RELEASE_OUTPUT = {\n RELEASED: \"Released session\",\n RETURNED_TO_TODO: \"Session returned to todo directory.\",\n} as const;\n\n/**\n * Options for the release command.\n */\nexport interface ReleaseOptions {\n /** Session IDs to release. Empty array defaults to most recent in doing. */\n sessionIds: string[];\n /** Custom sessions directory */\n sessionsDir?: string;\n /** Receives the non-git-repo diagnostic for the descriptor to surface. */\n onWarning?: SessionWarningHandler;\n}\n\n/**\n * Loads session refs from the doing directory.\n */\nasync function loadDoingSessions(config: SessionDirectoryConfig): Promise<Array<{ id: string }>> {\n try {\n const files = await readdir(config.doingDir);\n return files\n .filter((file) => file.endsWith(\".md\"))\n .map((file) => ({ id: file.replace(\".md\", \"\") }));\n } catch (error) {\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") {\n return [];\n }\n throw error;\n }\n}\n\n/**\n * Releases a single claimed session by ID.\n */\nasync function releaseSingle(sessionId: string, config: SessionDirectoryConfig): Promise<string> {\n const paths = buildReleasePaths(sessionId, config);\n\n try {\n await rename(paths.source, paths.target);\n } catch (error) {\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") {\n throw new SessionNotClaimedError(sessionId);\n }\n throw error;\n }\n\n return `${SESSION_RELEASE_OUTPUT.RELEASED}: ${sessionId}\\n${SESSION_RELEASE_OUTPUT.RETURNED_TO_TODO}`;\n}\n\n/**\n * Executes the release command for zero or more session IDs.\n *\n * When `sessionIds` is empty, the most recently claimed session in doing is released.\n * When one or more IDs are provided, all are processed in argument order.\n *\n * @param options - Command options\n * @returns Formatted output for display\n * @throws {BatchError} When one or more IDs fail\n * @throws {SessionNotClaimedError} When no session is claimed (empty IDs) or session not in doing (single ID)\n */\nexport async function releaseCommand(options: ReleaseOptions): Promise<string> {\n const config = await resolveSessionConfigSurfacingWarning(options.sessionsDir, options.onWarning);\n\n let ids = options.sessionIds;\n\n if (ids.length === 0) {\n const sessions = await loadDoingSessions(config);\n const current = findCurrentSession(sessions);\n\n if (!current) {\n throw new SessionNotClaimedError(\"(none)\");\n }\n\n ids = [current.id];\n }\n\n return processBatch(ids, (id) => releaseSingle(id, config));\n}\n","/**\n * Session release utilities.\n *\n * This module provides pure functions for releasing claimed sessions:\n * - Path construction for release operations\n * - Finding the current session in doing directory\n *\n * @module session/release\n */\n\nimport { parseSessionId } from \"./timestamp\";\n\n/**\n * Configuration for session release paths.\n */\nexport interface ReleasePathConfig {\n /** Directory containing claimed sessions */\n doingDir: string;\n /** Directory for released sessions */\n todoDir: string;\n}\n\n/**\n * Result of building release paths.\n */\nexport interface ReleasePaths {\n /** Source path (session in doing) */\n source: string;\n /** Target path (session in todo) */\n target: string;\n}\n\n/**\n * Session reference with minimal required fields.\n */\nexport interface SessionRef {\n id: string;\n}\n\n/**\n * Builds source and target paths for releasing a session.\n *\n * @param sessionId - The session ID (timestamp format)\n * @param config - Directory configuration\n * @returns Source and target paths for the release operation\n *\n * @example\n * ```typescript\n * const paths = buildReleasePaths(\"2026-01-13_08-01-05\", {\n * doingDir: \".spx/sessions/doing\",\n * todoDir: \".spx/sessions/todo\",\n * });\n * // => { source: \".spx/sessions/doing/2026-01-13_08-01-05.md\", target: \".spx/sessions/todo/2026-01-13_08-01-05.md\" }\n * ```\n */\nexport function buildReleasePaths(sessionId: string, config: ReleasePathConfig): ReleasePaths {\n return {\n source: `${config.doingDir}/${sessionId}.md`,\n target: `${config.todoDir}/${sessionId}.md`,\n };\n}\n\n/**\n * Finds the most recent session in the doing directory.\n *\n * When no session ID is provided to release, this function\n * selects the most recently claimed session (newest timestamp).\n *\n * @param doingSessions - Sessions currently in doing directory\n * @returns The most recent session, or null if empty\n *\n * @example\n * ```typescript\n * const sessions = [\n * { id: \"2026-01-10_08-00-00\" },\n * { id: \"2026-01-13_08-00-00\" },\n * ];\n * const current = findCurrentSession(sessions);\n * // => { id: \"2026-01-13_08-00-00\" }\n * ```\n */\nexport function findCurrentSession(doingSessions: SessionRef[]): SessionRef | null {\n if (doingSessions.length === 0) {\n return null;\n }\n\n // Sort by timestamp descending (newest first)\n const sorted = [...doingSessions].sort((a, b) => {\n const dateA = parseSessionId(a.id);\n const dateB = parseSessionId(b.id);\n\n // Handle invalid session IDs by treating them as oldest\n if (!dateA && !dateB) return 0;\n if (!dateA) return 1; // a goes after b\n if (!dateB) return -1; // b goes after a\n\n return dateB.getTime() - dateA.getTime();\n });\n\n return sorted[0];\n}\n","/**\n * Session show CLI command handler.\n *\n * @module commands/session/show\n */\n\nimport { readFile, stat } from \"node:fs/promises\";\n\nimport { processBatch } from \"@/domains/session/batch\";\nimport { SessionNotFoundError } from \"@/domains/session/errors\";\nimport { formatShowOutput, resolveSessionPaths, SEARCH_ORDER, SessionDirectoryConfig } from \"@/domains/session/show\";\nimport { SessionStatus } from \"@/domains/session/types\";\nimport { resolveSessionConfigSurfacingWarning, type SessionWarningHandler } from \"./resolve-config\";\n\n/**\n * Options for the show command.\n */\nexport interface ShowOptions {\n /** Session ID(s) to show */\n sessionIds: string[];\n /** Custom sessions directory */\n sessionsDir?: string;\n /** Receives the non-git-repo diagnostic for the descriptor to surface. */\n onWarning?: SessionWarningHandler;\n}\n\n/**\n * Finds the first existing path and its status.\n */\nasync function findExistingPath(\n paths: string[],\n _config: SessionDirectoryConfig,\n): Promise<{ path: string; status: SessionStatus } | null> {\n for (let i = 0; i < paths.length; i++) {\n const filePath = paths[i];\n try {\n const stats = await stat(filePath);\n if (stats.isFile()) {\n return { path: filePath, status: SEARCH_ORDER[i] };\n }\n } catch {\n // File doesn't exist, continue\n }\n }\n return null;\n}\n\n/**\n * Executes the show command.\n *\n * @param options - Command options\n * @returns Formatted output for display\n * @throws {SessionNotFoundError} When session not found\n */\n/**\n * Shows a single session by ID.\n */\nasync function showSingle(\n sessionId: string,\n config: SessionDirectoryConfig,\n): Promise<string> {\n const paths = resolveSessionPaths(sessionId, config);\n const found = await findExistingPath(paths, config);\n\n if (!found) {\n throw new SessionNotFoundError(sessionId);\n }\n\n const content = await readFile(found.path, \"utf-8\");\n return formatShowOutput(content, { status: found.status });\n}\n\n/**\n * Executes the show command for one or more session IDs.\n *\n * @param options - Command options with one or more session IDs\n * @returns Formatted output for display\n * @throws {BatchError} When one or more IDs fail\n * @throws {SessionNotFoundError} When session not found (single ID)\n */\nexport async function showCommand(options: ShowOptions): Promise<string> {\n const config = await resolveSessionConfigSurfacingWarning(options.sessionsDir, options.onWarning);\n\n return processBatch(options.sessionIds, (id) => showSingle(id, config));\n}\n","/**\n * Shared help text for session commands.\n *\n * Centralizes help text to ensure consistency across subcommands.\n *\n * @module domains/session/help\n */\n\n/**\n * Session file format description for the main session help.\n */\nexport const SESSION_FORMAT_HELP = `\nSession File Format:\n Sessions are markdown files with YAML frontmatter for metadata.\n\n ---\n priority: high\n git_ref: main\n goal: Fix the failing release check\n next_step: Run the focused session tests\n specs: []\n files: []\n ---\n # Session Title\n\n Session content...\n\nWorkflow:\n 1. handoff - Create session (todo) — JSON header + body on stdin\n 2. pickup - Claim session (todo -> doing)\n 3. release - Return session (doing -> todo)\n 4. archive - Move session to archive\n 5. delete - Remove session permanently\n`;\n\n/**\n * Input contract for the handoff command.\n */\nexport const HANDOFF_FRONTMATTER_HELP = `\nUsage:\n Pipe a JSON header followed by the body bytes to stdin.\n\n The header is a single JSON object holding caller-supplied structured fields.\n A single LF or CRLF after the header is consumed as a separator. The body\n is the remaining bytes verbatim — no YAML, no escape rules, no ambiguity\n from leading characters like '#' or '---'.\n\nJSON Header Fields:\n priority \"high\" | \"medium\" | \"low\" (default: medium)\n goal required, non-empty string\n next_step required, non-empty string\n specs optional string[], for pickup auto-injection\n files optional string[], for pickup auto-injection\n\nPrefilled by the CLI:\n created_at, git_ref, and agent_session_id when an agent session ID is\n available.\n\n git_ref records the branch name (root worktree on a branch), the HEAD SHA\n (detached), or the origin/<default> tip SHA (clean detached linked worktree).\n Handoff is refused from any other linked-worktree state.\n\nOutput Tags (for automation):\n <HANDOFF_ID>session-id</HANDOFF_ID> Session identifier\n <SESSION_FILE>/path/to/file</SESSION_FILE> Absolute path to created file\n\nCanonical Invocation:\n printf '%s\\\\n' \\\\\n '{\"priority\":\"high\",\"goal\":\"Fix login\",\"next_step\":\"Run validation\",\"specs\":[],\"files\":[]}' \\\\\n '# Fix login' \\\\\n '' \\\\\n 'Body text — # symbols, --- delimiters, and code fences are literal.' \\\\\n | spx session handoff\n`;\n\n/**\n * Selection logic for pickup command.\n */\nexport const PICKUP_SELECTION_HELP = `\nSelection Logic (--auto):\n Sessions are selected by priority, then age (FIFO):\n 1. high priority first\n 2. medium priority second\n 3. low priority last\n 4. Within same priority: oldest session first\n\nOutput:\n <PICKUP_ID>session-id</PICKUP_ID> tag for each claimed session\n`;\n","/**\n * Session CLI — Commander registration descriptor for the session subcommands.\n */\nimport type { Command } from \"commander\";\n\nimport {\n archiveCommand,\n deleteCommand,\n handoffCommand,\n listCommand,\n pickupCommand,\n pruneCommand,\n PruneValidationError,\n releaseCommand,\n SessionAlreadyArchivedError,\n showCommand,\n} from \"@/commands/session/index\";\nimport { SessionHandoffBaseError } from \"@/domains/session/errors\";\nimport { renderHandoffBaseChecklist } from \"@/domains/session/handoff-base-checklist\";\nimport { HANDOFF_FRONTMATTER_HELP, PICKUP_SELECTION_HELP, SESSION_FORMAT_HELP } from \"@/domains/session/help\";\nimport { SESSION_STATUSES } from \"@/domains/session/types\";\nimport type { Domain } from \"@/domains/types\";\n\nimport { writeWarning } from \"./write-warning\";\n\n/**\n * Reads content from stdin if available (piped input).\n * Returns undefined if stdin is a TTY (interactive terminal).\n */\nasync function readStdin(): Promise<string | undefined> {\n // Check if stdin is a TTY (interactive) - if so, don't wait for input\n if (process.stdin.isTTY) {\n return undefined;\n }\n\n return new Promise((resolve) => {\n let data = \"\";\n process.stdin.setEncoding(\"utf-8\");\n process.stdin.on(\"data\", (chunk) => {\n data += chunk;\n });\n process.stdin.on(\"end\", () => {\n resolve(data.length === 0 ? undefined : data);\n });\n // Handle case where stdin closes without data\n process.stdin.on(\"error\", () => {\n resolve(undefined);\n });\n });\n}\n\n/**\n * Handles command errors with consistent formatting.\n */\nfunction handleError(error: unknown): never {\n console.error(\"Error:\", error instanceof Error ? `${error.name}: ${error.message}` : String(error));\n process.exit(1);\n}\n\n/**\n * Register session domain commands\n *\n * @param sessionCmd - Commander.js session domain command\n */\nfunction registerSessionCommands(sessionCmd: Command): void {\n // list command\n sessionCmd\n .command(\"list\")\n .description(\"List active sessions (doing + todo by default)\")\n .option(\"--status <status>\", \"Filter by status (todo|doing|archive); defaults to doing + todo\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--sessions-dir <path>\", \"Custom sessions directory\")\n .action(async (options: { status?: string; json?: boolean; sessionsDir?: string }) => {\n try {\n const output = await listCommand({\n status: options.status,\n format: options.json ? \"json\" : \"text\",\n sessionsDir: options.sessionsDir,\n onWarning: writeWarning,\n });\n console.log(output);\n } catch (error) {\n handleError(error);\n }\n });\n\n // todo command (convenience alias for list --status todo)\n sessionCmd\n .command(\"todo\")\n .description(\"List todo sessions\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--sessions-dir <path>\", \"Custom sessions directory\")\n .action(async (options: { json?: boolean; sessionsDir?: string }) => {\n try {\n const output = await listCommand({\n status: SESSION_STATUSES[0],\n format: options.json ? \"json\" : \"text\",\n sessionsDir: options.sessionsDir,\n onWarning: writeWarning,\n });\n console.log(output);\n } catch (error) {\n handleError(error);\n }\n });\n\n // show command\n sessionCmd\n .command(\"show <id...>\")\n .description(\"Show session content\")\n .option(\"--sessions-dir <path>\", \"Custom sessions directory\")\n .action(async (ids: string[], options: { sessionsDir?: string }) => {\n try {\n const output = await showCommand({\n sessionIds: ids,\n sessionsDir: options.sessionsDir,\n onWarning: writeWarning,\n });\n console.log(output);\n } catch (error) {\n handleError(error);\n }\n });\n\n // pickup command\n sessionCmd\n .command(\"pickup [ids...]\")\n .description(\"Claim one or more sessions (move from todo to doing)\")\n .option(\"--auto\", \"Auto-select highest priority session\")\n .option(\"--sessions-dir <path>\", \"Custom sessions directory\")\n .addHelpText(\"after\", PICKUP_SELECTION_HELP)\n .action(async (ids: string[], options: { auto?: boolean; sessionsDir?: string }) => {\n try {\n if (ids.length === 0 && !options.auto) {\n console.error(\"Error: Either session ID or --auto flag is required\");\n process.exit(1);\n }\n const output = await pickupCommand({\n sessionIds: ids,\n auto: options.auto,\n sessionsDir: options.sessionsDir,\n onWarning: writeWarning,\n });\n console.log(output);\n } catch (error) {\n handleError(error);\n }\n });\n\n // release command\n sessionCmd\n .command(\"release [ids...]\")\n .description(\"Release one or more sessions (move from doing to todo)\")\n .option(\"--sessions-dir <path>\", \"Custom sessions directory\")\n .action(async (ids: string[], options: { sessionsDir?: string }) => {\n try {\n const output = await releaseCommand({\n sessionIds: ids,\n sessionsDir: options.sessionsDir,\n onWarning: writeWarning,\n });\n console.log(output);\n } catch (error) {\n handleError(error);\n }\n });\n\n // handoff command\n // Caller-supplied fields come from a JSON header at the start of stdin;\n // bytes after the header form the markdown body verbatim.\n sessionCmd\n .command(\"handoff\")\n .description(\"Create a handoff session (reads JSON header + body from stdin)\")\n .option(\"--sessions-dir <path>\", \"Custom sessions directory\")\n .addHelpText(\"after\", HANDOFF_FRONTMATTER_HELP)\n .action(async (options: { sessionsDir?: string }) => {\n try {\n // Read content from stdin if available\n const content = await readStdin();\n\n const result = await handoffCommand({\n content,\n sessionsDir: options.sessionsDir,\n });\n console.log(result.output);\n } catch (error) {\n if (error instanceof SessionHandoffBaseError) {\n // A linked-worktree refusal renders the prerequisite checklist; a\n // non-git base refuses silently; any other git refusal writes the\n // message as a plain diagnostic.\n if (error.checklist !== null) {\n console.error(renderHandoffBaseChecklist(error.checklist));\n } else if (!error.silent) {\n console.error(\"Error:\", `${error.name}: ${error.message}`);\n }\n process.exit(1);\n }\n handleError(error);\n }\n });\n\n // delete command\n sessionCmd\n .command(\"delete <id...>\")\n .description(\"Delete one or more sessions\")\n .option(\"--sessions-dir <path>\", \"Custom sessions directory\")\n .action(async (ids: string[], options: { sessionsDir?: string }) => {\n try {\n const output = await deleteCommand({\n sessionIds: ids,\n sessionsDir: options.sessionsDir,\n onWarning: writeWarning,\n });\n console.log(output);\n } catch (error) {\n handleError(error);\n }\n });\n\n // prune command\n sessionCmd\n .command(\"prune\")\n .description(\"Remove old todo sessions, keeping the most recent N\")\n .option(\"--keep <count>\", \"Number of sessions to keep (default: 5)\", \"5\")\n .option(\"--dry-run\", \"Show what would be deleted without deleting\")\n .option(\"--sessions-dir <path>\", \"Custom sessions directory\")\n .action(async (options: { keep?: string; dryRun?: boolean; sessionsDir?: string }) => {\n try {\n const keep = options.keep ? Number.parseInt(options.keep, 10) : undefined;\n const output = await pruneCommand({\n keep,\n dryRun: options.dryRun,\n sessionsDir: options.sessionsDir,\n onWarning: writeWarning,\n });\n console.log(output);\n } catch (error) {\n if (error instanceof PruneValidationError) {\n console.error(\"Error:\", error.message);\n process.exit(1);\n }\n handleError(error);\n }\n });\n\n // archive command\n sessionCmd\n .command(\"archive <id...>\")\n .description(\"Move one or more sessions to the archive directory\")\n .option(\"--sessions-dir <path>\", \"Custom sessions directory\")\n .action(async (ids: string[], options: { sessionsDir?: string }) => {\n try {\n const output = await archiveCommand({\n sessionIds: ids,\n sessionsDir: options.sessionsDir,\n onWarning: writeWarning,\n });\n console.log(output);\n } catch (error) {\n if (error instanceof SessionAlreadyArchivedError) {\n console.error(\"Error:\", error.message);\n process.exit(1);\n }\n handleError(error);\n }\n });\n}\n\n/**\n * Session CLI — Commander registration descriptor for the session subcommands.\n */\nexport const sessionDomain: Domain = {\n name: \"session\",\n description: \"Manage session workflow\",\n register: (program: Command) => {\n const sessionCmd = program\n .command(\"session\")\n .description(\"Manage session workflow\")\n .addHelpText(\"after\", SESSION_FORMAT_HELP);\n\n registerSessionCommands(sessionCmd);\n },\n};\n","import { readdir, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport type { DecisionKind, Kind, KindDefinition, NodeKind, SpecTreeKindCategory, SpecTreeNodeState } from \"./config\";\nimport { KIND_REGISTRY, SPEC_TREE_CONFIG, SPEC_TREE_KIND_CATEGORY, SPEC_TREE_NODE_STATE } from \"./config\";\nexport { SPEC_TREE_NODE_STATE } from \"./config\";\nexport type { SpecTreeNodeState } from \"./config\";\n\nconst SPEC_TREE_FIELD_KEY = {\n VERSION: \"version\",\n PRODUCT: \"product\",\n NODES: \"nodes\",\n DECISIONS: \"decisions\",\n TYPE: \"type\",\n KIND: \"kind\",\n CHILDREN: \"children\",\n ID: \"id\",\n ORDER: \"order\",\n SLUG: \"slug\",\n STATE: \"state\",\n} as const;\n\nexport const SPEC_TREE_ENTRY_TYPE = {\n PRODUCT: SPEC_TREE_FIELD_KEY.PRODUCT,\n NODE: SPEC_TREE_KIND_CATEGORY.NODE,\n DECISION: SPEC_TREE_KIND_CATEGORY.DECISION,\n EVIDENCE: \"evidence\",\n} as const;\n\nexport type SpecTreeEntryType = (typeof SPEC_TREE_ENTRY_TYPE)[keyof typeof SPEC_TREE_ENTRY_TYPE];\n\nexport const SPEC_TREE_FILESYSTEM_RECORD_TYPE = {\n DIRECTORY: \"directory\",\n FILE: \"file\",\n} as const;\n\nexport type SpecTreeFilesystemRecordType =\n (typeof SPEC_TREE_FILESYSTEM_RECORD_TYPE)[keyof typeof SPEC_TREE_FILESYSTEM_RECORD_TYPE];\n\nexport const SPEC_TREE_EVIDENCE_STATUS = {\n LINKED: \"linked\",\n FAILING: SPEC_TREE_NODE_STATE.FAILING,\n PASSING: SPEC_TREE_NODE_STATE.PASSING,\n} as const;\n\nexport type SpecTreeEvidenceStatus = (typeof SPEC_TREE_EVIDENCE_STATUS)[keyof typeof SPEC_TREE_EVIDENCE_STATUS];\n\nexport const SPEC_TREE_EVIDENCE_FILE = {\n DIRECTORY_NAME: \"tests\",\n MODES: [\"scenario\", \"mapping\", \"conformance\", \"property\", \"compliance\"],\n LEVELS: [\"l1\", \"l2\", \"l3\"],\n TAILS: {\n TYPESCRIPT: [\"test\", \"ts\"],\n PYTHON: [\"py\"],\n RUST: [\"rs\"],\n },\n SEGMENT_SEPARATOR: \".\",\n} as const;\n\nconst SPEC_TREE_EVIDENCE_FILE_TAILS = Object.values(SPEC_TREE_EVIDENCE_FILE.TAILS);\n\nexport const SPEC_TREE_PROJECTION = {\n VERSION: 1,\n KEYS: {\n VERSION: SPEC_TREE_FIELD_KEY.VERSION,\n PRODUCT: SPEC_TREE_FIELD_KEY.PRODUCT,\n NODES: SPEC_TREE_FIELD_KEY.NODES,\n DECISIONS: SPEC_TREE_FIELD_KEY.DECISIONS,\n },\n NODE_KEYS: {\n ID: SPEC_TREE_FIELD_KEY.ID,\n KIND: SPEC_TREE_FIELD_KEY.KIND,\n ORDER: SPEC_TREE_FIELD_KEY.ORDER,\n SLUG: SPEC_TREE_FIELD_KEY.SLUG,\n STATE: SPEC_TREE_FIELD_KEY.STATE,\n CHILDREN: SPEC_TREE_FIELD_KEY.CHILDREN,\n },\n DECISION_KEYS: {\n ID: SPEC_TREE_FIELD_KEY.ID,\n KIND: SPEC_TREE_FIELD_KEY.KIND,\n ORDER: SPEC_TREE_FIELD_KEY.ORDER,\n SLUG: SPEC_TREE_FIELD_KEY.SLUG,\n },\n} as const;\n\nexport const SPEC_TREE_SOURCE_ENTRY_KEYS = {\n TYPE: SPEC_TREE_FIELD_KEY.TYPE,\n KIND: SPEC_TREE_FIELD_KEY.KIND,\n} as const;\n\nexport type SpecTreeSourceEntryKey = (typeof SPEC_TREE_SOURCE_ENTRY_KEYS)[keyof typeof SPEC_TREE_SOURCE_ENTRY_KEYS];\n\nexport const SPEC_TREE_NODE_RELATION_KEYS = {\n CHILDREN: SPEC_TREE_FIELD_KEY.CHILDREN,\n DECISIONS: SPEC_TREE_FIELD_KEY.DECISIONS,\n} as const;\n\ntype SpecTreeNodeRelationKey = (typeof SPEC_TREE_NODE_RELATION_KEYS)[keyof typeof SPEC_TREE_NODE_RELATION_KEYS];\n\nexport type SpecTreeRegistry = typeof KIND_REGISTRY;\n\nexport type SpecTreeSourceRef = {\n readonly id: string;\n readonly path?: string;\n readonly url?: string;\n};\n\ntype SpecTreeSourceEntryBase = {\n readonly id: string;\n readonly ref?: SpecTreeSourceRef;\n};\n\nexport type SpecTreeProductSourceEntry = SpecTreeSourceEntryBase & {\n readonly type: typeof SPEC_TREE_ENTRY_TYPE.PRODUCT;\n readonly title: string;\n};\n\nexport type SpecTreeNodeSourceEntry = SpecTreeSourceEntryBase & {\n readonly type: typeof SPEC_TREE_ENTRY_TYPE.NODE;\n readonly kind: NodeKind;\n readonly order: number;\n readonly slug: string;\n readonly parentId?: string;\n readonly title?: string;\n};\n\nexport type SpecTreeDecisionSourceEntry = SpecTreeSourceEntryBase & {\n readonly type: typeof SPEC_TREE_ENTRY_TYPE.DECISION;\n readonly kind: DecisionKind;\n readonly order: number;\n readonly slug: string;\n readonly parentId?: string;\n readonly title?: string;\n};\n\nexport type SpecTreeEvidenceSourceEntry = SpecTreeSourceEntryBase & {\n readonly type: typeof SPEC_TREE_ENTRY_TYPE.EVIDENCE;\n readonly parentId: string;\n readonly status: SpecTreeEvidenceStatus;\n};\n\nexport type SpecTreeSourceEntry =\n | SpecTreeProductSourceEntry\n | SpecTreeNodeSourceEntry\n | SpecTreeDecisionSourceEntry\n | SpecTreeEvidenceSourceEntry;\n\nexport type SpecTreeSource = {\n entries(): AsyncIterable<SpecTreeSourceEntry>;\n readText?(ref: SpecTreeSourceRef): Promise<string>;\n};\n\nexport type SpecTreeFilesystemRecord = {\n readonly type: SpecTreeFilesystemRecordType;\n readonly relativePath: string;\n readonly parentId?: string;\n};\n\nexport type SpecTreePathInclusionPredicate = (path: string) => boolean | Promise<boolean>;\n\nexport type FilesystemSpecTreeSourceOptions = {\n readonly productDir: string;\n readonly registry?: SpecTreeRegistry;\n readonly includePath?: SpecTreePathInclusionPredicate;\n};\n\nexport type SpecTreeEvidenceProvider = {\n stateForNode?(\n node: SpecTreeNodeSourceEntry,\n evidence: readonly SpecTreeEvidenceSourceEntry[],\n ): SpecTreeNodeState | undefined;\n};\n\nexport type SpecTreeOptions = {\n readonly source: SpecTreeSource;\n readonly registry?: SpecTreeRegistry;\n readonly evidence?: SpecTreeEvidenceProvider;\n};\n\nexport type SpecTreeProduct = {\n readonly id: string;\n readonly title: string;\n readonly ref?: SpecTreeSourceRef;\n};\n\nexport type SpecTreeDecision = {\n readonly id: string;\n readonly kind: DecisionKind;\n readonly order: number;\n readonly slug: string;\n readonly parentId?: string;\n readonly title?: string;\n readonly ref?: SpecTreeSourceRef;\n};\n\nexport type SpecTreeNode = {\n readonly id: string;\n readonly kind: NodeKind;\n readonly order: number;\n readonly slug: string;\n readonly parentId?: string;\n readonly title?: string;\n readonly ref?: SpecTreeSourceRef;\n readonly state: SpecTreeNodeState;\n readonly decisions: readonly SpecTreeDecision[];\n readonly children: readonly SpecTreeNode[];\n};\n\nexport type SpecTreeSnapshot = {\n readonly product: SpecTreeProduct | null;\n readonly nodes: readonly SpecTreeNode[];\n readonly allNodes: readonly SpecTreeNode[];\n readonly decisions: readonly SpecTreeDecision[];\n readonly entries: readonly SpecTreeSourceEntry[];\n};\n\nexport type SpecTreeProjectedNode = {\n readonly id: string;\n readonly kind: NodeKind;\n readonly order: number;\n readonly slug: string;\n readonly state: SpecTreeNodeState;\n readonly children: readonly SpecTreeProjectedNode[];\n};\n\nexport type SpecTreeProjectedDecision = {\n readonly id: string;\n readonly kind: DecisionKind;\n readonly order: number;\n readonly slug: string;\n};\n\nexport type SpecTreeProjectedProduct = {\n readonly id: string;\n readonly title: string;\n};\n\nexport type SpecTreeProjection = {\n readonly version: typeof SPEC_TREE_PROJECTION.VERSION;\n readonly product: SpecTreeProjectedProduct | null;\n readonly nodes: readonly SpecTreeProjectedNode[];\n readonly decisions: readonly SpecTreeProjectedDecision[];\n};\n\ntype MutableSpecTreeNode = Omit<SpecTreeNode, SpecTreeNodeRelationKey> & {\n readonly children: MutableSpecTreeNode[];\n readonly decisions: SpecTreeDecision[];\n};\n\ntype OrderedEntry = {\n readonly id: string;\n readonly order: number;\n};\n\nconst ORDER_COMPARISON_EQUAL = 0;\nconst SPEC_TREE_PATH_SEPARATOR = \"/\";\nconst SPEC_TREE_ORDER_SEPARATOR = \"-\";\nconst SPEC_TREE_ORDER_RADIX = 10;\nconst SPEC_TREE_TEXT_ENCODING = \"utf8\";\nconst SPEC_TREE_EMPTY_RELATIVE_PATH = \"\";\nconst SPEC_TREE_ORDER_PATTERN = /^\\d+$/;\nconst SPEC_TREE_MIN_EVIDENCE_PATH_SEGMENTS = 2;\nconst SPEC_TREE_PARENT_SEGMENT_OFFSET = 2;\nconst SPEC_TREE_FIRST_EVIDENCE_MARKER_INDEX = 1;\nconst SPEC_TREE_EXACTLY_ONE_EVIDENCE_MARKER = 1;\n\nexport function getKindDefinition<K extends keyof SpecTreeRegistry>(\n kind: K,\n registry: SpecTreeRegistry = KIND_REGISTRY,\n): KindDefinition<K> {\n return registry[kind];\n}\n\nexport function createFilesystemSpecTreeSource(options: FilesystemSpecTreeSourceOptions): SpecTreeSource {\n const registry = options.registry ?? KIND_REGISTRY;\n const includePath = options.includePath ?? includeEverySpecTreePath;\n\n return {\n entries: () => readFilesystemSourceEntries(options.productDir, registry, includePath),\n async readText(ref: SpecTreeSourceRef): Promise<string> {\n if (ref.path === undefined) {\n throw new Error(\"Filesystem source refs require a path\");\n }\n return readFile(join(options.productDir, ref.path), SPEC_TREE_TEXT_ENCODING);\n },\n };\n}\n\nexport function recognizeSpecTreeFilesystemEntry(\n record: SpecTreeFilesystemRecord,\n registry: SpecTreeRegistry = KIND_REGISTRY,\n): SpecTreeSourceEntry | null {\n const name = readLastPathSegment(record.relativePath);\n\n if (record.type === SPEC_TREE_FILESYSTEM_RECORD_TYPE.FILE && isProductFile(record.relativePath)) {\n return {\n type: SPEC_TREE_ENTRY_TYPE.PRODUCT,\n id: record.relativePath,\n title: stripSuffix(name, SPEC_TREE_CONFIG.PRODUCT.SUFFIX),\n ref: sourceRefForRelativePath(record.relativePath),\n };\n }\n\n if (record.type === SPEC_TREE_FILESYSTEM_RECORD_TYPE.DIRECTORY) {\n const nodeMatch = matchKindSuffix(name, registry, SPEC_TREE_KIND_CATEGORY.NODE);\n if (nodeMatch === null) return null;\n const parsed = parseOrderedSlug(stripSuffix(name, nodeMatch.definition.suffix));\n if (parsed === null) return null;\n return {\n type: SPEC_TREE_ENTRY_TYPE.NODE,\n kind: nodeMatch.kind as NodeKind,\n id: record.relativePath,\n order: parsed.order,\n slug: parsed.slug,\n parentId: record.parentId,\n ref: sourceRefForNode(record.relativePath, parsed.slug),\n };\n }\n\n if (\n record.type === SPEC_TREE_FILESYSTEM_RECORD_TYPE.FILE\n && record.parentId !== undefined\n && isEvidenceFile(record.relativePath)\n ) {\n return {\n type: SPEC_TREE_ENTRY_TYPE.EVIDENCE,\n id: record.relativePath,\n parentId: record.parentId,\n status: SPEC_TREE_EVIDENCE_STATUS.LINKED,\n ref: sourceRefForRelativePath(record.relativePath),\n };\n }\n\n if (record.type === SPEC_TREE_FILESYSTEM_RECORD_TYPE.FILE) {\n const decisionMatch = matchKindSuffix(name, registry, SPEC_TREE_KIND_CATEGORY.DECISION);\n if (decisionMatch === null) return null;\n const parsed = parseOrderedSlug(stripSuffix(name, decisionMatch.definition.suffix));\n if (parsed === null) return null;\n return {\n type: SPEC_TREE_ENTRY_TYPE.DECISION,\n kind: decisionMatch.kind as DecisionKind,\n id: record.relativePath,\n order: parsed.order,\n slug: parsed.slug,\n parentId: record.parentId,\n ref: sourceRefForRelativePath(record.relativePath),\n };\n }\n\n return null;\n}\n\nexport async function readSpecTree(options: SpecTreeOptions): Promise<SpecTreeSnapshot> {\n const entries = await collectSourceEntries(options.source);\n const product = entries.find(isProductEntry) ?? null;\n const evidenceByParent = groupEvidence(entries.filter(isEvidenceEntry));\n const decisions = entries.filter(isDecisionEntry).map(toDecision).sort(compareOrderedEntries);\n const decisionsByParent = groupDecisions(decisions);\n const nodesById = new Map<string, MutableSpecTreeNode>();\n\n for (const entry of entries.filter(isNodeEntry)) {\n const state = deriveState(entry, evidenceByParent.get(entry.id) ?? [], options.evidence);\n nodesById.set(entry.id, {\n id: entry.id,\n kind: entry.kind,\n order: entry.order,\n slug: entry.slug,\n parentId: entry.parentId,\n title: entry.title,\n ref: entry.ref,\n state,\n decisions: decisionsByParent.get(entry.id) ?? [],\n children: [],\n });\n }\n\n const roots: MutableSpecTreeNode[] = [];\n for (const node of nodesById.values()) {\n const parent = node.parentId === undefined ? undefined : nodesById.get(node.parentId);\n if (parent === undefined) {\n roots.push(node);\n } else {\n parent.children.push(node);\n }\n }\n\n sortNodes(roots);\n const allNodes = flattenNodes(roots);\n\n return {\n product: product === null\n ? null\n : {\n id: product.id,\n title: product.title,\n ref: product.ref,\n },\n nodes: roots,\n allNodes,\n decisions,\n entries,\n };\n}\n\nexport function projectSpecTree(snapshot: SpecTreeSnapshot): SpecTreeProjection {\n return {\n version: SPEC_TREE_PROJECTION.VERSION,\n product: snapshot.product === null\n ? null\n : {\n id: snapshot.product.id,\n title: snapshot.product.title,\n },\n nodes: snapshot.nodes.map(projectNode),\n decisions: snapshot.decisions.map((decision) => ({\n id: decision.id,\n kind: decision.kind,\n order: decision.order,\n slug: decision.slug,\n })),\n };\n}\n\nexport function findNextSpecTreeNode(snapshot: SpecTreeSnapshot): SpecTreeNode | null {\n return findFirstNonPassing(snapshot.nodes);\n}\n\nasync function collectSourceEntries(source: SpecTreeSource): Promise<SpecTreeSourceEntry[]> {\n const entries: SpecTreeSourceEntry[] = [];\n for await (const entry of source.entries()) {\n entries.push(entry);\n }\n return entries;\n}\n\nfunction isProductEntry(entry: SpecTreeSourceEntry): entry is SpecTreeProductSourceEntry {\n return entry.type === SPEC_TREE_ENTRY_TYPE.PRODUCT;\n}\n\nfunction isNodeEntry(entry: SpecTreeSourceEntry): entry is SpecTreeNodeSourceEntry {\n return entry.type === SPEC_TREE_ENTRY_TYPE.NODE;\n}\n\nfunction isDecisionEntry(entry: SpecTreeSourceEntry): entry is SpecTreeDecisionSourceEntry {\n return entry.type === SPEC_TREE_ENTRY_TYPE.DECISION;\n}\n\nfunction isEvidenceEntry(entry: SpecTreeSourceEntry): entry is SpecTreeEvidenceSourceEntry {\n return entry.type === SPEC_TREE_ENTRY_TYPE.EVIDENCE;\n}\n\nfunction toDecision(entry: SpecTreeDecisionSourceEntry): SpecTreeDecision {\n return {\n id: entry.id,\n kind: entry.kind,\n order: entry.order,\n slug: entry.slug,\n parentId: entry.parentId,\n title: entry.title,\n ref: entry.ref,\n };\n}\n\nfunction groupEvidence(\n entries: readonly SpecTreeEvidenceSourceEntry[],\n): Map<string, SpecTreeEvidenceSourceEntry[]> {\n const grouped = new Map<string, SpecTreeEvidenceSourceEntry[]>();\n for (const entry of entries) {\n const group = grouped.get(entry.parentId) ?? [];\n group.push(entry);\n grouped.set(entry.parentId, group);\n }\n return grouped;\n}\n\nfunction groupDecisions(entries: readonly SpecTreeDecision[]): Map<string, SpecTreeDecision[]> {\n const grouped = new Map<string, SpecTreeDecision[]>();\n for (const entry of entries) {\n if (entry.parentId === undefined) continue;\n const group = grouped.get(entry.parentId) ?? [];\n group.push(entry);\n grouped.set(entry.parentId, group.sort(compareOrderedEntries));\n }\n return grouped;\n}\n\nfunction deriveState(\n node: SpecTreeNodeSourceEntry,\n evidence: readonly SpecTreeEvidenceSourceEntry[],\n provider?: SpecTreeEvidenceProvider,\n): SpecTreeNodeState {\n const provided = provider?.stateForNode?.(node, evidence);\n if (provided !== undefined) return provided;\n if (evidence.length === 0) return SPEC_TREE_NODE_STATE.DECLARED;\n if (evidence.some((entry) => entry.status === SPEC_TREE_EVIDENCE_STATUS.FAILING)) {\n return SPEC_TREE_NODE_STATE.FAILING;\n }\n if (evidence.every((entry) => entry.status === SPEC_TREE_EVIDENCE_STATUS.PASSING)) {\n return SPEC_TREE_NODE_STATE.PASSING;\n }\n return SPEC_TREE_NODE_STATE.SPECIFIED;\n}\n\nfunction sortNodes(nodes: MutableSpecTreeNode[]): void {\n nodes.sort(compareOrderedEntries);\n for (const node of nodes) {\n sortNodes(node.children);\n }\n}\n\nfunction flattenNodes(nodes: readonly MutableSpecTreeNode[]): readonly SpecTreeNode[] {\n return nodes.flatMap((node) => [node, ...flattenNodes(node.children)]);\n}\n\nfunction projectNode(node: SpecTreeNode): SpecTreeProjectedNode {\n return {\n id: node.id,\n kind: node.kind,\n order: node.order,\n slug: node.slug,\n state: node.state,\n children: node.children.map(projectNode),\n };\n}\n\nfunction findFirstNonPassing(nodes: readonly SpecTreeNode[]): SpecTreeNode | null {\n for (const node of nodes) {\n if (node.state !== SPEC_TREE_NODE_STATE.PASSING) return node;\n const child = findFirstNonPassing(node.children);\n if (child !== null) return child;\n }\n return null;\n}\n\nfunction compareOrderedEntries(left: OrderedEntry, right: OrderedEntry): number {\n const orderComparison = left.order - right.order;\n if (orderComparison !== ORDER_COMPARISON_EQUAL) return orderComparison;\n return left.id.localeCompare(right.id);\n}\n\nasync function* readFilesystemSourceEntries(\n productDir: string,\n registry: SpecTreeRegistry,\n includePath: SpecTreePathInclusionPredicate,\n): AsyncIterable<SpecTreeSourceEntry> {\n yield* walkFilesystemDirectory({\n absolutePath: join(productDir, SPEC_TREE_CONFIG.ROOT_DIRECTORY),\n relativePath: SPEC_TREE_EMPTY_RELATIVE_PATH,\n registry,\n includePath,\n });\n}\n\ntype FilesystemWalkContext = {\n readonly absolutePath: string;\n readonly relativePath: string;\n readonly registry: SpecTreeRegistry;\n readonly includePath: SpecTreePathInclusionPredicate;\n readonly parentId?: string;\n};\n\nasync function* walkFilesystemDirectory(context: FilesystemWalkContext): AsyncIterable<SpecTreeSourceEntry> {\n let entries;\n try {\n entries = await readdir(context.absolutePath, { withFileTypes: true });\n } catch (error) {\n if (isFileNotFound(error)) return;\n throw error;\n }\n\n const sortedEntries = [...entries].sort((left, right) => left.name.localeCompare(right.name));\n for (const entry of sortedEntries) {\n const relativePath = joinSpecTreePath(context.relativePath, entry.name);\n const refPath = joinSpecTreePath(SPEC_TREE_CONFIG.ROOT_DIRECTORY, relativePath);\n if (!await context.includePath(refPath)) continue;\n\n const recordType = entry.isDirectory()\n ? SPEC_TREE_FILESYSTEM_RECORD_TYPE.DIRECTORY\n : entry.isFile()\n ? SPEC_TREE_FILESYSTEM_RECORD_TYPE.FILE\n : undefined;\n if (recordType === undefined) continue;\n\n const sourceEntry = recognizeSpecTreeFilesystemEntry(\n { type: recordType, relativePath, parentId: context.parentId },\n context.registry,\n );\n if (sourceEntry !== null) yield sourceEntry;\n\n if (entry.isDirectory() && shouldDescendIntoDirectory(entry.name, sourceEntry, context.registry)) {\n yield* walkFilesystemDirectory({\n absolutePath: join(context.absolutePath, entry.name),\n relativePath,\n registry: context.registry,\n includePath: context.includePath,\n parentId: sourceEntry?.type === SPEC_TREE_ENTRY_TYPE.NODE ? sourceEntry.id : context.parentId,\n });\n }\n }\n}\n\ntype KindSuffixMatch = {\n readonly kind: string;\n readonly definition: KindDefinition<Kind>;\n};\n\nfunction matchKindSuffix(\n name: string,\n registry: SpecTreeRegistry,\n category: SpecTreeKindCategory,\n): KindSuffixMatch | null {\n for (const [kind, definition] of Object.entries(registry) as Array<[Kind, KindDefinition<Kind>]>) {\n if (definition.category === category && name.endsWith(definition.suffix)) {\n return { kind, definition };\n }\n }\n return null;\n}\n\ntype OrderedSlug = {\n readonly order: number;\n readonly slug: string;\n};\n\nfunction parseOrderedSlug(value: string): OrderedSlug | null {\n const separatorIndex = value.indexOf(SPEC_TREE_ORDER_SEPARATOR);\n if (separatorIndex <= ORDER_COMPARISON_EQUAL) return null;\n const orderText = value.slice(0, separatorIndex);\n if (!SPEC_TREE_ORDER_PATTERN.test(orderText)) return null;\n const slug = value.slice(separatorIndex + SPEC_TREE_ORDER_SEPARATOR.length);\n if (slug.length === 0) return null;\n return {\n order: Number.parseInt(orderText, SPEC_TREE_ORDER_RADIX),\n slug,\n };\n}\n\nfunction isProductFile(relativePath: string): boolean {\n return !relativePath.includes(SPEC_TREE_PATH_SEPARATOR) && relativePath.endsWith(SPEC_TREE_CONFIG.PRODUCT.SUFFIX);\n}\n\nfunction isEvidenceFile(relativePath: string): boolean {\n const segments = relativePath.split(SPEC_TREE_PATH_SEPARATOR);\n if (segments.length < SPEC_TREE_MIN_EVIDENCE_PATH_SEGMENTS) return false;\n\n const filename = segments[segments.length - 1] ?? \"\";\n const directoryName = segments[segments.length - SPEC_TREE_PARENT_SEGMENT_OFFSET];\n const filenameSegments = filename.split(SPEC_TREE_EVIDENCE_FILE.SEGMENT_SEPARATOR);\n\n return directoryName === SPEC_TREE_EVIDENCE_FILE.DIRECTORY_NAME\n && SPEC_TREE_EVIDENCE_FILE_TAILS.some((tail) =>\n SPEC_TREE_EVIDENCE_FILE.MODES.some((mode) =>\n SPEC_TREE_EVIDENCE_FILE.LEVELS.some((level) => filenameHasEvidenceSuffix(filenameSegments, mode, level, tail))\n )\n );\n}\n\nfunction filenameHasEvidenceSuffix(\n filenameSegments: readonly string[],\n mode: string,\n level: string,\n tail: readonly string[],\n): boolean {\n if (!segmentsEndWith(filenameSegments, tail)) return false;\n const tailStart = filenameSegments.length - tail.length;\n let evidenceMarkerCount = 0;\n\n // Exactly one mode/level pair prevents ambiguous filenames from being treated as evidence.\n for (let index = SPEC_TREE_FIRST_EVIDENCE_MARKER_INDEX; index < tailStart - 1; index += 1) {\n if (filenameSegments[index] === mode && filenameSegments[index + 1] === level) {\n evidenceMarkerCount += 1;\n }\n }\n\n return evidenceMarkerCount === SPEC_TREE_EXACTLY_ONE_EVIDENCE_MARKER;\n}\n\nfunction segmentsEndWith(segments: readonly string[], suffix: readonly string[]): boolean {\n if (segments.length <= suffix.length) return false;\n const start = segments.length - suffix.length;\n return suffix.every((value, index) => segments[start + index] === value);\n}\n\nfunction shouldDescendIntoDirectory(\n name: string,\n sourceEntry: SpecTreeSourceEntry | null,\n registry: SpecTreeRegistry,\n): boolean {\n if (sourceEntry !== null) return true;\n if (name === SPEC_TREE_EVIDENCE_FILE.DIRECTORY_NAME) return true;\n return !isUnregisteredOrderedDirectory(name, registry);\n}\n\nfunction isUnregisteredOrderedDirectory(name: string, registry: SpecTreeRegistry): boolean {\n if (matchKindSuffix(name, registry, SPEC_TREE_KIND_CATEGORY.NODE) !== null) return false;\n return parseOrderedSlug(name) !== null;\n}\n\nfunction sourceRefForRelativePath(relativePath: string): SpecTreeSourceRef {\n const path = joinSpecTreePath(SPEC_TREE_CONFIG.ROOT_DIRECTORY, relativePath);\n return { id: path, path };\n}\n\nfunction sourceRefForNode(relativePath: string, slug: string): SpecTreeSourceRef {\n return sourceRefForRelativePath(joinSpecTreePath(relativePath, `${slug}.md`));\n}\n\nfunction stripSuffix(value: string, suffix: string): string {\n return value.slice(0, value.length - suffix.length);\n}\n\nfunction readLastPathSegment(relativePath: string): string {\n const segments = relativePath.split(SPEC_TREE_PATH_SEPARATOR);\n return segments[segments.length - 1] ?? relativePath;\n}\n\nfunction joinSpecTreePath(...segments: readonly string[]): string {\n return segments.filter((segment) => segment.length > 0).join(SPEC_TREE_PATH_SEPARATOR);\n}\n\nfunction includeEverySpecTreePath(): boolean {\n return true;\n}\n\nfunction isFileNotFound(error: unknown): boolean {\n return error instanceof Error && \"code\" in error && (error as NodeJS.ErrnoException).code === \"ENOENT\";\n}\n","import { detectWorktreeProductRoot, type GitDependencies } from \"@/git/root\";\nimport { SPEC_TREE_CONFIG } from \"@/lib/spec-tree/config\";\n\nexport const SPEC_PRODUCT_DIR_WARNING = {\n NOT_GIT_REPOSITORY:\n `Warning: Not in a git repository. Reading ${SPEC_TREE_CONFIG.ROOT_DIRECTORY} relative to the current working directory.`,\n} as const;\n\nexport type SpecProductDirWarningHandler = (warning: string) => void;\n\nexport async function resolveSpecProductDir(\n cwd: string,\n gitDependencies?: GitDependencies,\n onWarning?: SpecProductDirWarningHandler,\n): Promise<string> {\n const result = await detectWorktreeProductRoot(cwd, gitDependencies);\n if (!result.isGitRepo) {\n // Spec commands read tracked spx/ files, so the fallback warning names that domain.\n onWarning?.(SPEC_PRODUCT_DIR_WARNING.NOT_GIT_REPOSITORY);\n }\n return result.productDir;\n}\n","import type { GitDependencies } from \"@/git/root\";\nimport {\n createFilesystemSpecTreeSource,\n findNextSpecTreeNode,\n readSpecTree,\n type SpecTreeNode,\n type SpecTreeSnapshot,\n type SpecTreeSource,\n} from \"@/lib/spec-tree\";\nimport { KIND_REGISTRY, SPEC_TREE_CONFIG } from \"@/lib/spec-tree/config\";\nimport { resolveSpecProductDir, type SpecProductDirWarningHandler } from \"./root\";\n\nexport const SPEC_NEXT_MESSAGE = {\n EMPTY: `No spec-tree nodes found in ${SPEC_TREE_CONFIG.ROOT_DIRECTORY}`,\n COMPLETE: \"All spec-tree nodes are passing\",\n HEADING: \"Next spec-tree node:\",\n KIND_LABEL: \"Kind\",\n PATH_LABEL: \"Path\",\n STATE_LABEL: \"State\",\n} as const;\n\nconst INDENT = \" \";\n\nexport interface NextOptions {\n cwd?: string;\n gitDependencies?: GitDependencies;\n onWarning?: SpecProductDirWarningHandler;\n source?: SpecTreeSource;\n}\n\nexport async function nextCommand(options: NextOptions = {}): Promise<string> {\n if (options.source !== undefined) {\n // Injected sources bypass filesystem and git resolution.\n const snapshot = await readSpecTree({ source: options.source });\n return formatNextSpecTreeNode(snapshot);\n }\n\n const productDir = await resolveSpecProductDir(\n options.cwd ?? process.cwd(),\n options.gitDependencies,\n options.onWarning,\n );\n const source = createFilesystemSpecTreeSource({ productDir });\n const snapshot = await readSpecTree({ source });\n\n return formatNextSpecTreeNode(snapshot);\n}\n\nfunction formatNextSpecTreeNode(snapshot: SpecTreeSnapshot): string {\n if (snapshot.allNodes.length === 0) {\n return SPEC_NEXT_MESSAGE.EMPTY;\n }\n\n const next = findNextSpecTreeNode(snapshot);\n\n if (next === null) {\n return SPEC_NEXT_MESSAGE.COMPLETE;\n }\n\n return formatNextNode(next);\n}\n\nfunction formatNextNode(node: SpecTreeNode): string {\n return [\n SPEC_NEXT_MESSAGE.HEADING,\n \"\",\n `${INDENT}${SPEC_NEXT_MESSAGE.PATH_LABEL}: ${node.id}`,\n `${INDENT}${SPEC_NEXT_MESSAGE.KIND_LABEL}: ${KIND_REGISTRY[node.kind].label}`,\n `${INDENT}${SPEC_NEXT_MESSAGE.STATE_LABEL}: ${node.state}`,\n ].join(\"\\n\");\n}\n","import type { Dirent } from \"node:fs\";\nimport { readdir } from \"node:fs/promises\";\nimport { join, relative, sep } from \"node:path\";\n\nimport { SPEC_TREE_EVIDENCE_FILE } from \"@/lib/spec-tree\";\nimport { SPEC_TREE_CONFIG } from \"@/lib/spec-tree/config\";\n\nconst TESTS_DIRECTORY_NAME = SPEC_TREE_EVIDENCE_FILE.DIRECTORY_NAME;\nconst SPEC_ROOT_DIRECTORY = SPEC_TREE_CONFIG.ROOT_DIRECTORY;\nconst POSIX_SEPARATOR = \"/\";\nconst ERROR_CODE_NOT_FOUND = \"ENOENT\";\n\n/**\n * Walks the tracked spec tree under `productDir` and returns every file inside a\n * `tests/` directory, as POSIX paths relative to `productDir`, in deterministic\n * ascending order. Partitioning the files by language is a separate, pure concern.\n */\nexport async function discoverTestFiles(productDir: string): Promise<readonly string[]> {\n const found: string[] = [];\n await collectTestFiles(join(productDir, SPEC_ROOT_DIRECTORY), false, found);\n return found.map((absolute) => toPosixRelative(productDir, absolute)).sort(compareAscii);\n}\n\nasync function collectTestFiles(directory: string, insideTestsDir: boolean, found: string[]): Promise<void> {\n let entries: readonly Dirent[];\n try {\n entries = await readdir(directory, { withFileTypes: true });\n } catch (error) {\n if (hasErrorCode(error, ERROR_CODE_NOT_FOUND)) return;\n throw error;\n }\n\n for (const entry of entries) {\n const childPath = join(directory, entry.name);\n if (entry.isDirectory()) {\n await collectTestFiles(childPath, insideTestsDir || entry.name === TESTS_DIRECTORY_NAME, found);\n } else if (insideTestsDir && entry.isFile()) {\n found.push(childPath);\n }\n }\n}\n\nfunction toPosixRelative(productDir: string, absolute: string): string {\n return relative(productDir, absolute).split(sep).join(POSIX_SEPARATOR);\n}\n\nfunction compareAscii(left: string, right: string): number {\n if (left < right) return -1;\n if (left > right) return 1;\n return 0;\n}\n\nfunction hasErrorCode(error: unknown, code: string): boolean {\n return typeof error === \"object\" && error !== null && (error as { code?: unknown }).code === code;\n}\n","import type { TestRunInvocation } from \"@/testing/languages/types\";\n\nexport const SUCCESS_EXIT_CODE = 0;\n\n/**\n * Aggregates per-language runner invocations into a single command exit code:\n * the first invoked runner's non-zero exit code, or success when every invoked\n * runner exited zero. Runners that detection gated out do not contribute.\n */\nexport function aggregateTestExitCode(invocations: readonly TestRunInvocation[]): number {\n for (const invocation of invocations) {\n if (invocation.invoked && invocation.exitCode !== undefined && invocation.exitCode !== SUCCESS_EXIT_CODE) {\n return invocation.exitCode;\n }\n }\n return SUCCESS_EXIT_CODE;\n}\n","import type { TestingLanguageDescriptor } from \"@/testing/languages/types\";\n\n/** A registered language paired with the discovered test files it owns. */\nexport interface LanguageTestGroup {\n readonly language: TestingLanguageDescriptor;\n readonly testPaths: readonly string[];\n}\n\n/** Discovered test files partitioned by owning language, plus the files no language claims. */\nexport interface TestFileGrouping {\n readonly groups: readonly LanguageTestGroup[];\n readonly unmatched: readonly string[];\n}\n\n/**\n * Partitions discovered test files by the first registered language whose\n * `matchesTestFile` claims each file; files no language claims become\n * `unmatched`. Group order follows registry order, and only languages with at\n * least one matching file produce a group.\n */\nexport function groupTestFiles(\n testFiles: readonly string[],\n languages: readonly TestingLanguageDescriptor[],\n): TestFileGrouping {\n const pathsByLanguage = new Map<TestingLanguageDescriptor, string[]>();\n const unmatched: string[] = [];\n\n for (const testFile of testFiles) {\n const language = languages.find((candidate) => candidate.matchesTestFile(testFile));\n if (language === undefined) {\n unmatched.push(testFile);\n continue;\n }\n const existing = pathsByLanguage.get(language);\n if (existing === undefined) {\n pathsByLanguage.set(language, [testFile]);\n } else {\n existing.push(testFile);\n }\n }\n\n const groups: LanguageTestGroup[] = languages\n .filter((language) => pathsByLanguage.has(language))\n .map((language) => ({ language, testPaths: pathsByLanguage.get(language) ?? [] }));\n\n return { groups, unmatched };\n}\n","import { applyPathFilter, type PathFilterConfig } from \"@/config/primitives\";\nimport { aggregateTestExitCode, groupTestFiles, type LanguageTestGroup, SUCCESS_EXIT_CODE } from \"@/domains/testing\";\nimport type { TestingLanguageDescriptor, TestRunInvocation, TestRunnerDependencies } from \"@/testing/languages/types\";\nimport type { TestingRegistry } from \"@/testing/registry\";\nimport type { TestRunnerOutcome } from \"@/testing/run-state\";\n\nimport { discoverTestFiles } from \"./discovery\";\n\n/**\n * Outcome of a `spx test` dispatch: aggregate exit code, the dispatched groups,\n * the skipped files, and the per-runner outcomes the recording path consumes. The\n * outcomes' test paths are the set this run covered.\n */\nexport interface TestDispatchResult {\n readonly exitCode: number;\n readonly groups: readonly LanguageTestGroup[];\n readonly unmatched: readonly string[];\n readonly outcomes: readonly TestRunnerOutcome[];\n}\n\nexport interface TestDispatchOptions {\n readonly productDir: string;\n readonly registry: TestingRegistry;\n /** When present, discovered files are filtered by this scope before dispatch (`spx test passing`). */\n readonly passingScope?: PathFilterConfig;\n}\n\nexport interface TestDispatchDependencies {\n /** Supplies the detection and command-runner dependencies for a given language. */\n readonly runnerDepsFor: (language: TestingLanguageDescriptor) => TestRunnerDependencies;\n}\n\n// Passing-scope filtering removes files before grouping; the dispatch passes no\n// runner-level node exclusions, so each runner receives exactly the kept files.\nconst NO_EXCLUDED_NODE_PATHS: readonly string[] = [];\n\n/**\n * Discovers the spec tree's test files, partitions them by registered language,\n * dispatches each group to its language runner through the injected runner\n * dependencies, and aggregates the runners' exit codes into one command result.\n */\nexport async function runTests(\n options: TestDispatchOptions,\n deps: TestDispatchDependencies,\n): Promise<TestDispatchResult> {\n const discovered = await discoverTestFiles(options.productDir);\n const testFiles = options.passingScope === undefined\n ? discovered\n : applyPathFilter(discovered, options.passingScope);\n const { groups, unmatched } = groupTestFiles(testFiles, options.registry.languages);\n\n const invocations: TestRunInvocation[] = [];\n const outcomes: TestRunnerOutcome[] = [];\n for (const group of groups) {\n const invocation = await group.language.runTests(\n {\n projectRoot: options.productDir,\n testPaths: group.testPaths,\n excludedNodePaths: NO_EXCLUDED_NODE_PATHS,\n },\n deps.runnerDepsFor(group.language),\n );\n invocations.push(invocation);\n // A gated-out runner (not invoked) produces no observed outcome to record.\n if (invocation.invoked) {\n outcomes.push({\n runnerId: group.language.name,\n testPaths: group.testPaths,\n exitCode: invocation.exitCode ?? SUCCESS_EXIT_CODE,\n });\n }\n }\n\n return { exitCode: aggregateTestExitCode(invocations), groups, unmatched, outcomes };\n}\n","import { join } from \"node:path\";\n\nimport { digestDescriptorSection } from \"@/config/descriptor-digest\";\nimport { resolveConfig } from \"@/config/index\";\nimport { SUCCESS_EXIT_CODE } from \"@/domains/testing\";\nimport { getCurrentBranch, getHeadSha, type GitDependencies } from \"@/git/root\";\nimport { TESTING_SECTION, type TestingConfig, testingConfigDescriptor } from \"@/testing/config\";\nimport type { TestingLanguageDescriptor, TestRunnerDependencies } from \"@/testing/languages/types\";\nimport type { TestingRegistry } from \"@/testing/registry\";\nimport {\n createTestRunDirectory,\n defaultTestRunStateFileSystem,\n digestTestContents,\n digestTestPaths,\n formatTestRunTimestamp,\n type ProductInputDigest,\n type StalenessInputs,\n TEST_RUN_STATE_STATUS,\n type TestContentEntry,\n type TestRunDirectory,\n type TestRunnerOutcome,\n type TestRunState,\n type TestRunStateFileSystem,\n type TestRunStateStatus,\n writeTerminalTestRunState,\n} from \"@/testing/run-state\";\n\nimport { runTests, type TestDispatchResult } from \"./dispatch\";\n\n// Non-empty sentinel for branch/head-SHA when git resolution returns null (no\n// repo, detached HEAD, or no commits) — the recorded state's identity fields must\n// satisfy the non-empty-string contract `readTestingRuns` enforces on read.\nexport const NO_GIT_IDENTITY = \"(unknown)\";\nconst TEXT_ENCODING = \"utf8\";\n// Descriptor-declared product inputs are not declared by any testing descriptor\n// yet, so no product-input digest participates in recorded staleness; the field is\n// populated once the domain-execution descriptor surface lands.\nconst NO_PRODUCT_INPUT_DIGESTS: readonly ProductInputDigest[] = [];\n\n/** Shared command dependencies; filesystem, clock, and git default to real access. */\nexport interface TestCommandDependencies {\n readonly registry: TestingRegistry;\n readonly runnerDepsFor: (language: TestingLanguageDescriptor) => TestRunnerDependencies;\n /** Git access for branch and head-SHA identity; defaults to real git resolution. */\n readonly git?: GitDependencies;\n /** State filesystem for recording and discovered-content reads; defaults to real fs. */\n readonly fs?: TestRunStateFileSystem;\n /** Clock for run timestamps; defaults to the system clock. */\n readonly now?: () => Date;\n}\n\nexport interface RunTestsCommandOptions {\n readonly productDir: string;\n /** True for `spx test passing` — apply the configured passing scope before dispatch. */\n readonly passing: boolean;\n}\n\nexport interface RecordedTestRun {\n readonly dispatch: TestDispatchResult;\n readonly recorded: TestRunState;\n}\n\nexport interface RunNodeCommandOptions {\n readonly productDir: string;\n /** Full product-root path of the node whose tests run, e.g. `spx/41-testing.enabler`. */\n readonly nodePath: string;\n}\n\n// Recording dependencies with real-access defaults applied; the seams the ADR\n// requires injectable (filesystem, clock, git) resolve here once per command.\ninterface RecordingDependencies {\n readonly fs: TestRunStateFileSystem;\n readonly now: () => Date;\n readonly git?: GitDependencies;\n}\n\nfunction resolveRecordingDependencies(deps: TestCommandDependencies): RecordingDependencies {\n return {\n fs: deps.fs ?? defaultTestRunStateFileSystem,\n now: deps.now ?? (() => new Date()),\n git: deps.git,\n };\n}\n\n// Resolves the testing config and its canonical digest, the staleness input that\n// detects testing-policy changes. Throws with context on a malformed config.\nasync function resolveTestingConfig(productDir: string): Promise<{ config: TestingConfig; digest: string }> {\n const loaded = await resolveConfig(productDir, [testingConfigDescriptor]);\n if (!loaded.ok) {\n throw new Error(`failed to resolve testing config: ${loaded.error}`);\n }\n const config = loaded.value[TESTING_SECTION] as TestingConfig;\n const digest = digestDescriptorSection(config);\n if (!digest.ok) {\n throw new Error(`failed to digest testing config: ${digest.error}`);\n }\n return { config, digest: digest.value.sha256 };\n}\n\n// The files this run covered — the union of the dispatched runners' test paths.\n// Recording digests this set, so a per-node run covers only its node's files and a\n// full run covers every dispatched file.\nfunction coveredTestPaths(dispatch: TestDispatchResult): readonly string[] {\n return dispatch.outcomes.flatMap((outcome) => outcome.testPaths);\n}\n\nasync function readCoveredContents(\n productDir: string,\n paths: readonly string[],\n fs: TestRunStateFileSystem,\n): Promise<readonly TestContentEntry[]> {\n const entries: TestContentEntry[] = [];\n for (const path of paths) {\n entries.push({ path, content: await fs.readFile(join(productDir, path), TEXT_ENCODING) });\n }\n return entries;\n}\n\nfunction deriveStatus(outcomes: readonly TestRunnerOutcome[]): TestRunStateStatus {\n const allPassed = outcomes.every((outcome) => outcome.exitCode === SUCCESS_EXIT_CODE);\n return allPassed ? TEST_RUN_STATE_STATUS.PASSED : TEST_RUN_STATE_STATUS.FAILED;\n}\n\n/**\n * Computes the four current staleness inputs (testing config digest, discovered\n * path-set digest, discovered content digest, product-input digests) over a\n * covered set of test paths. The recording path and the status resolver's\n * freshness check share this one recipe, so a node's recorded staleness inputs\n * and the current inputs later compared against them never diverge.\n */\nexport async function currentStalenessInputs(\n productDir: string,\n coveredPaths: readonly string[],\n deps: { readonly fs?: TestRunStateFileSystem; readonly testingConfigDigest?: string } = {},\n): Promise<StalenessInputs> {\n const fs = deps.fs ?? defaultTestRunStateFileSystem;\n // A caller that already resolved the testing config (e.g. runTestsCommand reading\n // passingScope) passes its digest so the config is read once per command; callers\n // holding no config (the per-node run, the status resolver) resolve it here.\n const testingConfigDigest = deps.testingConfigDigest ?? (await resolveTestingConfig(productDir)).digest;\n const contents = await readCoveredContents(productDir, coveredPaths, fs);\n return {\n testingConfigDigest,\n discoveredTestPathsDigest: digestTestPaths(coveredPaths),\n discoveredTestContentDigest: digestTestContents(contents),\n productInputDigests: NO_PRODUCT_INPUT_DIGESTS,\n };\n}\n\n// The single recording path both the full run and the per-node run pass through:\n// assemble a TestRunState from the run's outcomes, the staleness digests over the\n// covered set, and the git identity, then persist it into the reserved directory.\nasync function recordRun(\n directory: TestRunDirectory,\n productDir: string,\n dispatch: TestDispatchResult,\n recording: RecordingDependencies,\n testingConfigDigest?: string,\n): Promise<TestRunState> {\n const staleness = await currentStalenessInputs(productDir, coveredTestPaths(dispatch), {\n fs: recording.fs,\n testingConfigDigest,\n });\n const branchName = (await getCurrentBranch(productDir, recording.git)) ?? NO_GIT_IDENTITY;\n const headSha = (await getHeadSha(productDir, recording.git)) ?? NO_GIT_IDENTITY;\n\n const state: TestRunState = {\n branchName,\n headSha,\n testingConfigDigest: staleness.testingConfigDigest,\n runnerOutcomes: dispatch.outcomes,\n discoveredTestPathsDigest: staleness.discoveredTestPathsDigest,\n discoveredTestContentDigest: staleness.discoveredTestContentDigest,\n productInputDigests: staleness.productInputDigests,\n startedAt: directory.startedAt,\n completedAt: formatTestRunTimestamp(recording.now()),\n status: deriveStatus(dispatch.outcomes),\n };\n\n const written = await writeTerminalTestRunState(directory.runDir, state, { fs: recording.fs });\n if (!written.ok) {\n throw new Error(`failed to record test run: ${written.error}`);\n }\n return state;\n}\n\nasync function reserveRunDirectory(\n productDir: string,\n recording: RecordingDependencies,\n): Promise<TestRunDirectory> {\n const directory = await createTestRunDirectory(productDir, { fs: recording.fs, now: recording.now });\n if (!directory.ok) {\n throw new Error(`failed to create test run directory: ${directory.error}`);\n }\n return directory.value;\n}\n\n/**\n * Runs the spec tree's tests — every discovered file, or only the configured\n * passing scope under `passing` — through the registry, then records last-run\n * evidence for the run. Reads the passing scope from the resolved testing config.\n */\nexport async function runTestsCommand(\n options: RunTestsCommandOptions,\n deps: TestCommandDependencies,\n): Promise<RecordedTestRun> {\n const { config, digest } = await resolveTestingConfig(options.productDir);\n const passingScope = options.passing ? config.passingScope : undefined;\n const recording = resolveRecordingDependencies(deps);\n const directory = await reserveRunDirectory(options.productDir, recording);\n const dispatch = await runTests(\n { productDir: options.productDir, registry: deps.registry, passingScope },\n { runnerDepsFor: deps.runnerDepsFor },\n );\n const recorded = await recordRun(directory, options.productDir, dispatch, recording, digest);\n return { dispatch, recorded };\n}\n\n/**\n * Runs a single node's tests through the registry and records fresh last-run\n * evidence covering that node, returning the recorded state for a status\n * consumer to read its outcome.\n */\nexport async function runNodeCommand(\n options: RunNodeCommandOptions,\n deps: TestCommandDependencies,\n): Promise<RecordedTestRun> {\n const recording = resolveRecordingDependencies(deps);\n const directory = await reserveRunDirectory(options.productDir, recording);\n const dispatch = await runTests(\n { productDir: options.productDir, registry: deps.registry, passingScope: { include: [options.nodePath] } },\n { runnerDepsFor: deps.runnerDepsFor },\n );\n const recorded = await recordRun(directory, options.productDir, dispatch, recording);\n return { dispatch, recorded };\n}\n","import { createHash, randomBytes as nodeRandomBytes } from \"node:crypto\";\nimport {\n mkdir as nodeMkdir,\n readdir as nodeReaddir,\n readFile as nodeReadFile,\n rename as nodeRename,\n writeFile as nodeWriteFile,\n} from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport type { Result } from \"@/config/types\";\nimport { formatAuditRunTimestamp } from \"@/domains/audit/run-state\";\n\nexport const TEST_RUN_STATE_STATUS = {\n PASSED: \"passed\",\n FAILED: \"failed\",\n INTERRUPTED: \"interrupted\",\n} as const;\n\nexport type TestRunStateStatus = (typeof TEST_RUN_STATE_STATUS)[keyof typeof TEST_RUN_STATE_STATUS];\n\nexport const TESTING_RUN_STATE_INCOMPLETE_REASON = {\n MISSING_STATE: \"missing-state\",\n IO_ERROR: \"io-error\",\n PARSE_INVALID_STATE: \"parse-invalid-state\",\n SHAPE_INVALID_STATE: \"shape-invalid-state\",\n} as const;\n\nexport type TestingRunStateIncompleteReason =\n (typeof TESTING_RUN_STATE_INCOMPLETE_REASON)[keyof typeof TESTING_RUN_STATE_INCOMPLETE_REASON];\n\nexport const TESTING_RUN_STATE_ERROR = {\n RUN_DIRECTORY_COLLISION_LIMIT: \"testing run directory collision limit exhausted\",\n RUN_DIRECTORY_CREATE_FAILED: \"testing run directory create failed\",\n STATE_ALREADY_EXISTS: \"testing run state already exists\",\n STATE_WRITE_FAILED: \"testing run state write failed\",\n} as const;\n\nexport const TEST_RUN_STATE_FIELDS = {\n BRANCH_NAME: \"branchName\",\n HEAD_SHA: \"headSha\",\n TESTING_CONFIG_DIGEST: \"testingConfigDigest\",\n RUNNER_OUTCOMES: \"runnerOutcomes\",\n DISCOVERED_TEST_PATHS_DIGEST: \"discoveredTestPathsDigest\",\n DISCOVERED_TEST_CONTENT_DIGEST: \"discoveredTestContentDigest\",\n PRODUCT_INPUT_DIGESTS: \"productInputDigests\",\n STARTED_AT: \"startedAt\",\n COMPLETED_AT: \"completedAt\",\n STATUS: \"status\",\n} as const;\n\nconst TEST_RUNNER_OUTCOME_FIELDS = {\n RUNNER_ID: \"runnerId\",\n TEST_PATHS: \"testPaths\",\n EXIT_CODE: \"exitCode\",\n} as const;\n\nconst PRODUCT_INPUT_DIGEST_FIELDS = {\n DESCRIPTOR_ID: \"descriptorId\",\n DIGEST: \"digest\",\n} as const;\n\nexport interface TestRunnerOutcome {\n readonly runnerId: string;\n readonly testPaths: readonly string[];\n readonly exitCode: number;\n}\n\nexport interface ProductInputDigest {\n readonly descriptorId: string;\n readonly digest: string;\n}\n\nexport interface TestRunState {\n readonly branchName: string;\n readonly headSha: string;\n readonly testingConfigDigest: string;\n readonly runnerOutcomes: readonly TestRunnerOutcome[];\n readonly discoveredTestPathsDigest: string;\n readonly discoveredTestContentDigest: string;\n readonly productInputDigests: readonly ProductInputDigest[];\n readonly startedAt: string;\n readonly completedAt: string;\n readonly status: TestRunStateStatus;\n}\n\nexport interface StalenessInputs {\n readonly testingConfigDigest: string;\n readonly discoveredTestPathsDigest: string;\n readonly discoveredTestContentDigest: string;\n readonly productInputDigests: readonly ProductInputDigest[];\n}\n\nexport interface TestContentEntry {\n readonly path: string;\n readonly content: string;\n}\n\nexport interface TestingStorageConfig {\n readonly spxDir: string;\n readonly localDir: string;\n readonly testingDir: string;\n readonly runsDir: string;\n readonly stateFile: string;\n}\n\nexport const DEFAULT_TESTING_STORAGE: TestingStorageConfig = {\n spxDir: \".spx\",\n localDir: \"local\",\n testingDir: \"testing\",\n runsDir: \"runs\",\n stateFile: \"state.json\",\n};\n\nexport interface TestRunDirectory {\n readonly runsDir: string;\n readonly runDir: string;\n readonly runDirectoryName: string;\n readonly runId: string;\n readonly startedAt: string;\n}\n\nexport interface TestTerminalRun {\n readonly runDirectoryName: string;\n readonly runDir: string;\n readonly statePath: string;\n readonly state: TestRunState;\n}\n\nexport interface TestIncompleteRun {\n readonly runDirectoryName: string;\n readonly runDir: string;\n readonly statePath: string;\n readonly reason: TestingRunStateIncompleteReason;\n readonly error?: string;\n}\n\nexport interface TestingRuns {\n readonly terminalRuns: readonly TestTerminalRun[];\n readonly incompleteRuns: readonly TestIncompleteRun[];\n}\n\nexport interface TestRunDirectoryEntry {\n readonly name: string;\n isDirectory(): boolean;\n}\n\nexport interface TestRunStateFileSystem {\n mkdir(path: string, options?: { readonly recursive?: boolean }): Promise<void>;\n writeFile(path: string, data: string, options?: { readonly flag?: string }): Promise<void>;\n rename(source: string, target: string): Promise<void>;\n readFile(path: string, encoding: \"utf8\"): Promise<string>;\n readdir(path: string, options: { readonly withFileTypes: true }): Promise<readonly TestRunDirectoryEntry[]>;\n}\n\nexport interface CreateTestRunDirectoryOptions {\n readonly now?: () => Date;\n readonly randomBytes?: (size: number) => Buffer;\n readonly fs?: TestRunStateFileSystem;\n readonly storage?: TestingStorageConfig;\n readonly maxAttempts?: number;\n}\n\nexport interface WriteTestRunStateOptions {\n readonly randomBytes?: (size: number) => Buffer;\n readonly fs?: TestRunStateFileSystem;\n readonly storage?: TestingStorageConfig;\n}\n\nexport interface ReadTestRunStateOptions {\n readonly fs?: TestRunStateFileSystem;\n readonly storage?: TestingStorageConfig;\n}\n\nconst SHA256_ALGORITHM = \"sha256\";\nconst HEX_ENCODING = \"hex\";\nconst UTF8_ENCODING = \"utf8\";\nconst RUN_ID_BYTES = 6;\nconst TEMP_STATE_ID_BYTES = 6;\nconst RUN_DIRECTORY_CREATE_ATTEMPTS = 10;\nconst TEMP_STATE_FILE_PREFIX = \".state\";\nconst TEMP_STATE_FILE_SUFFIX = \".tmp\";\nconst JSON_INDENT_SPACES = 2;\nconst SEGMENT_SEPARATOR = \"-\";\nconst EXCLUSIVE_CREATE_FLAG = \"wx\";\nconst ERROR_CODE_FILE_EXISTS = \"EEXIST\";\nconst ERROR_CODE_NOT_FOUND = \"ENOENT\";\nconst RUN_DIRECTORY_NAME_PATTERN = /^\\d{4}-\\d{2}-\\d{2}_\\d{2}-\\d{2}-\\d{2}-\\d{3}-[a-f0-9]{12}$/;\n\nconst defaultFileSystem: TestRunStateFileSystem = {\n mkdir: async (path, options) => {\n // Normalize nodeMkdir's recursive overload to the injected fs contract.\n await nodeMkdir(path, options);\n },\n writeFile: nodeWriteFile,\n rename: nodeRename,\n readFile: nodeReadFile,\n readdir: nodeReaddir,\n};\n\nexport { defaultFileSystem as defaultTestRunStateFileSystem };\n\n// Run-directory timestamps reuse the audit formatter so testing state and audit\n// state share one run-directory naming convention.\nexport function formatTestRunTimestamp(date: Date): string {\n return formatAuditRunTimestamp(date);\n}\n\n// Per-worktree testing runs live under `.spx/local/testing/runs/` at the local\n// worktree root (`productDir`); no branch partition participates in the path.\nexport function testingRunsDir(\n productDir: string,\n storage: TestingStorageConfig = DEFAULT_TESTING_STORAGE,\n): string {\n return join(productDir, storage.spxDir, storage.localDir, storage.testingDir, storage.runsDir);\n}\n\nexport async function createTestRunDirectory(\n productDir: string,\n options: CreateTestRunDirectoryOptions = {},\n): Promise<Result<TestRunDirectory>> {\n const fs = options.fs ?? defaultFileSystem;\n const storage = options.storage ?? DEFAULT_TESTING_STORAGE;\n const maxAttempts = options.maxAttempts ?? RUN_DIRECTORY_CREATE_ATTEMPTS;\n const startedDate = (options.now ?? (() => new Date()))();\n const startedAt = formatTestRunTimestamp(startedDate);\n const runsDir = testingRunsDir(productDir, storage);\n const randomBytes = options.randomBytes ?? nodeRandomBytes;\n\n try {\n await fs.mkdir(runsDir, { recursive: true });\n } catch (error) {\n return { ok: false, error: `${TESTING_RUN_STATE_ERROR.RUN_DIRECTORY_CREATE_FAILED}: ${toErrorMessage(error)}` };\n }\n\n for (let attempt = 0; attempt < maxAttempts; attempt += 1) {\n const runId = generateHexId(RUN_ID_BYTES, randomBytes);\n const runDirectoryName = `${startedAt}${SEGMENT_SEPARATOR}${runId}`;\n const runDir = join(runsDir, runDirectoryName);\n try {\n await fs.mkdir(runDir);\n return { ok: true, value: { runsDir, runDir, runDirectoryName, runId, startedAt } };\n } catch (error) {\n if (hasErrorCode(error, ERROR_CODE_FILE_EXISTS)) continue;\n return { ok: false, error: `${TESTING_RUN_STATE_ERROR.RUN_DIRECTORY_CREATE_FAILED}: ${toErrorMessage(error)}` };\n }\n }\n\n return { ok: false, error: TESTING_RUN_STATE_ERROR.RUN_DIRECTORY_COLLISION_LIMIT };\n}\n\nexport async function writeTerminalTestRunState(\n runDir: string,\n state: TestRunState,\n options: WriteTestRunStateOptions = {},\n): Promise<Result<string>> {\n const fs = options.fs ?? defaultFileSystem;\n const storage = options.storage ?? DEFAULT_TESTING_STORAGE;\n const statePath = join(runDir, storage.stateFile);\n\n try {\n await fs.readFile(statePath, UTF8_ENCODING);\n return { ok: false, error: TESTING_RUN_STATE_ERROR.STATE_ALREADY_EXISTS };\n } catch (error) {\n if (!hasErrorCode(error, ERROR_CODE_NOT_FOUND)) {\n return { ok: false, error: `${TESTING_RUN_STATE_ERROR.STATE_WRITE_FAILED}: ${toErrorMessage(error)}` };\n }\n }\n\n const tempId = generateHexId(TEMP_STATE_ID_BYTES, options.randomBytes ?? nodeRandomBytes);\n const tempPath = join(runDir, `${TEMP_STATE_FILE_PREFIX}-${tempId}${TEMP_STATE_FILE_SUFFIX}`);\n const serialized = `${JSON.stringify(state, null, JSON_INDENT_SPACES)}\\n`;\n\n try {\n await fs.writeFile(tempPath, serialized, { flag: EXCLUSIVE_CREATE_FLAG });\n await fs.rename(tempPath, statePath);\n return { ok: true, value: statePath };\n } catch (error) {\n return { ok: false, error: `${TESTING_RUN_STATE_ERROR.STATE_WRITE_FAILED}: ${toErrorMessage(error)}` };\n }\n}\n\nexport async function readTestingRuns(\n productDir: string,\n options: ReadTestRunStateOptions = {},\n): Promise<Result<TestingRuns>> {\n const fs = options.fs ?? defaultFileSystem;\n const storage = options.storage ?? DEFAULT_TESTING_STORAGE;\n const runsDir = testingRunsDir(productDir, storage);\n\n let entries: readonly TestRunDirectoryEntry[];\n try {\n entries = await fs.readdir(runsDir, { withFileTypes: true });\n } catch (error) {\n if (hasErrorCode(error, ERROR_CODE_NOT_FOUND)) {\n return { ok: true, value: { terminalRuns: [], incompleteRuns: [] } };\n }\n return { ok: false, error: toErrorMessage(error) };\n }\n\n const terminalRuns: TestTerminalRun[] = [];\n const incompleteRuns: TestIncompleteRun[] = [];\n for (const entry of entries.filter(isTestRunDirectoryEntry)) {\n const runDir = join(runsDir, entry.name);\n const statePath = join(runDir, storage.stateFile);\n const stateResult = await readTestRunStatePath(statePath, fs);\n if (stateResult.ok) {\n terminalRuns.push({ runDirectoryName: entry.name, runDir, statePath, state: stateResult.value });\n } else {\n incompleteRuns.push({\n runDirectoryName: entry.name,\n runDir,\n statePath,\n reason: stateResult.reason,\n ...(stateResult.error === undefined ? {} : { error: stateResult.error }),\n });\n }\n }\n\n return { ok: true, value: { terminalRuns, incompleteRuns } };\n}\n\n// Selects the latest terminal run that covers a node — one whose recorded runner\n// outcomes executed all of the node's test paths — so a later run that exercised\n// other nodes never hides an earlier node's evidence. Returns undefined when no\n// run covers the node (including a node with no test paths).\nexport function selectLatestTerminalTestRunForNode(\n runs: readonly TestTerminalRun[],\n nodeTestPaths: readonly string[],\n): TestTerminalRun | undefined {\n return runs\n .filter((run) => runCoversNode(run, nodeTestPaths))\n .reduce<TestTerminalRun | undefined>((latest, candidate) => {\n if (latest === undefined) return candidate;\n return compareTerminalRuns(latest, candidate) < 0 ? candidate : latest;\n }, undefined);\n}\n\nfunction runCoversNode(run: TestTerminalRun, nodeTestPaths: readonly string[]): boolean {\n return outcomesCoverPaths(run.state.runnerOutcomes, nodeTestPaths);\n}\n\n/**\n * True when the runner outcomes executed every one of the node's test paths. The\n * recorded-evidence selection and a fresh per-node run's outcome both judge node\n * coverage by this one predicate, so a run that left any node test path unexecuted —\n * a gated-out or unmatched language — never counts as covering the node.\n */\nexport function outcomesCoverPaths(\n outcomes: readonly TestRunnerOutcome[],\n nodeTestPaths: readonly string[],\n): boolean {\n if (nodeTestPaths.length === 0) return false;\n const executed = new Set(outcomes.flatMap((outcome) => outcome.testPaths));\n return nodeTestPaths.every((path) => executed.has(path));\n}\n\nexport function digestTestPaths(paths: readonly string[]): string {\n const normalized = [...new Set(paths)].sort(compareAsciiStrings);\n return sha256Hex(JSON.stringify(normalized));\n}\n\nexport function digestTestContents(entries: readonly TestContentEntry[]): string {\n const normalized = [...entries]\n .sort((left, right) => compareAsciiStrings(left.path, right.path))\n .map((entry) => [entry.path, entry.content]);\n return sha256Hex(JSON.stringify(normalized));\n}\n\nexport function isStalenessMatch(recorded: StalenessInputs, current: StalenessInputs): boolean {\n return recorded.testingConfigDigest === current.testingConfigDigest\n && recorded.discoveredTestPathsDigest === current.discoveredTestPathsDigest\n && recorded.discoveredTestContentDigest === current.discoveredTestContentDigest\n && productInputDigestsEqual(recorded.productInputDigests, current.productInputDigests);\n}\n\nexport function extractStalenessInputs(state: TestRunState): StalenessInputs {\n return {\n testingConfigDigest: state.testingConfigDigest,\n discoveredTestPathsDigest: state.discoveredTestPathsDigest,\n discoveredTestContentDigest: state.discoveredTestContentDigest,\n productInputDigests: state.productInputDigests,\n };\n}\n\ntype ReadStateResult =\n | { readonly ok: true; readonly value: TestRunState }\n | { readonly ok: false; readonly reason: TestingRunStateIncompleteReason; readonly error?: string };\n\nasync function readTestRunStatePath(statePath: string, fs: TestRunStateFileSystem): Promise<ReadStateResult> {\n let raw: string;\n try {\n raw = await fs.readFile(statePath, UTF8_ENCODING);\n } catch (error) {\n if (hasErrorCode(error, ERROR_CODE_NOT_FOUND)) {\n return { ok: false, reason: TESTING_RUN_STATE_INCOMPLETE_REASON.MISSING_STATE };\n }\n return { ok: false, reason: TESTING_RUN_STATE_INCOMPLETE_REASON.IO_ERROR, error: toErrorMessage(error) };\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw) as unknown;\n } catch (error) {\n return { ok: false, reason: TESTING_RUN_STATE_INCOMPLETE_REASON.PARSE_INVALID_STATE, error: toErrorMessage(error) };\n }\n\n const validated = validateTestRunState(parsed);\n if (!validated.ok) {\n return { ok: false, reason: TESTING_RUN_STATE_INCOMPLETE_REASON.SHAPE_INVALID_STATE, error: validated.error };\n }\n return { ok: true, value: validated.value };\n}\n\nfunction validateTestRunState(value: unknown): Result<TestRunState> {\n if (!isRecord(value)) return { ok: false, error: \"testing run state must be an object\" };\n\n const branchName = readString(value, TEST_RUN_STATE_FIELDS.BRANCH_NAME);\n if (!branchName.ok) return branchName;\n const headSha = readString(value, TEST_RUN_STATE_FIELDS.HEAD_SHA);\n if (!headSha.ok) return headSha;\n const testingConfigDigest = readString(value, TEST_RUN_STATE_FIELDS.TESTING_CONFIG_DIGEST);\n if (!testingConfigDigest.ok) return testingConfigDigest;\n const runnerOutcomes = readRunnerOutcomes(value[TEST_RUN_STATE_FIELDS.RUNNER_OUTCOMES]);\n if (!runnerOutcomes.ok) return runnerOutcomes;\n const discoveredTestPathsDigest = readString(value, TEST_RUN_STATE_FIELDS.DISCOVERED_TEST_PATHS_DIGEST);\n if (!discoveredTestPathsDigest.ok) return discoveredTestPathsDigest;\n const discoveredTestContentDigest = readString(value, TEST_RUN_STATE_FIELDS.DISCOVERED_TEST_CONTENT_DIGEST);\n if (!discoveredTestContentDigest.ok) return discoveredTestContentDigest;\n const productInputDigests = readProductInputDigests(value[TEST_RUN_STATE_FIELDS.PRODUCT_INPUT_DIGESTS]);\n if (!productInputDigests.ok) return productInputDigests;\n const startedAt = readString(value, TEST_RUN_STATE_FIELDS.STARTED_AT);\n if (!startedAt.ok) return startedAt;\n const completedAt = readString(value, TEST_RUN_STATE_FIELDS.COMPLETED_AT);\n if (!completedAt.ok) return completedAt;\n const status = readStatus(value[TEST_RUN_STATE_FIELDS.STATUS]);\n if (!status.ok) return status;\n\n return {\n ok: true,\n value: {\n branchName: branchName.value,\n headSha: headSha.value,\n testingConfigDigest: testingConfigDigest.value,\n runnerOutcomes: runnerOutcomes.value,\n discoveredTestPathsDigest: discoveredTestPathsDigest.value,\n discoveredTestContentDigest: discoveredTestContentDigest.value,\n productInputDigests: productInputDigests.value,\n startedAt: startedAt.value,\n completedAt: completedAt.value,\n status: status.value,\n },\n };\n}\n\nfunction readRunnerOutcomes(raw: unknown): Result<readonly TestRunnerOutcome[]> {\n if (!Array.isArray(raw)) {\n return { ok: false, error: `${TEST_RUN_STATE_FIELDS.RUNNER_OUTCOMES} must be an array` };\n }\n const outcomes: TestRunnerOutcome[] = [];\n for (const entry of raw) {\n if (!isRecord(entry)) {\n return { ok: false, error: `${TEST_RUN_STATE_FIELDS.RUNNER_OUTCOMES} entries must be objects` };\n }\n const runnerId = readString(entry, TEST_RUNNER_OUTCOME_FIELDS.RUNNER_ID);\n if (!runnerId.ok) return runnerId;\n const testPaths = readStringArray(entry, TEST_RUNNER_OUTCOME_FIELDS.TEST_PATHS);\n if (!testPaths.ok) return testPaths;\n const exitCodeRaw = entry[TEST_RUNNER_OUTCOME_FIELDS.EXIT_CODE];\n if (typeof exitCodeRaw !== \"number\" || !Number.isInteger(exitCodeRaw)) {\n return { ok: false, error: `${TEST_RUNNER_OUTCOME_FIELDS.EXIT_CODE} must be an integer` };\n }\n outcomes.push({ runnerId: runnerId.value, testPaths: testPaths.value, exitCode: exitCodeRaw });\n }\n return { ok: true, value: outcomes };\n}\n\nfunction readProductInputDigests(raw: unknown): Result<readonly ProductInputDigest[]> {\n if (!Array.isArray(raw)) {\n return { ok: false, error: `${TEST_RUN_STATE_FIELDS.PRODUCT_INPUT_DIGESTS} must be an array` };\n }\n const digests: ProductInputDigest[] = [];\n for (const entry of raw) {\n if (!isRecord(entry)) {\n return { ok: false, error: `${TEST_RUN_STATE_FIELDS.PRODUCT_INPUT_DIGESTS} entries must be objects` };\n }\n const descriptorId = readString(entry, PRODUCT_INPUT_DIGEST_FIELDS.DESCRIPTOR_ID);\n if (!descriptorId.ok) return descriptorId;\n const digest = readString(entry, PRODUCT_INPUT_DIGEST_FIELDS.DIGEST);\n if (!digest.ok) return digest;\n digests.push({ descriptorId: descriptorId.value, digest: digest.value });\n }\n return { ok: true, value: digests };\n}\n\nfunction readString(value: Record<string, unknown>, field: string): Result<string> {\n const raw = value[field];\n return typeof raw === \"string\" && raw.length > 0\n ? { ok: true, value: raw }\n : { ok: false, error: `${field} must be a non-empty string` };\n}\n\nfunction readStringArray(value: Record<string, unknown>, field: string): Result<readonly string[]> {\n const raw = value[field];\n return Array.isArray(raw) && raw.every((entry) => typeof entry === \"string\" && entry.length > 0)\n ? { ok: true, value: raw }\n : { ok: false, error: `${field} must be an array of non-empty strings` };\n}\n\nfunction readStatus(raw: unknown): Result<TestRunStateStatus> {\n return isTestRunStateStatus(raw)\n ? { ok: true, value: raw }\n : { ok: false, error: `${TEST_RUN_STATE_FIELDS.STATUS} must be a terminal testing status` };\n}\n\nfunction isTestRunStateStatus(value: unknown): value is TestRunStateStatus {\n return typeof value === \"string\" && Object.values(TEST_RUN_STATE_STATUS).includes(value as TestRunStateStatus);\n}\n\nfunction compareTerminalRuns(left: TestTerminalRun, right: TestTerminalRun): number {\n const completed = compareAsciiStrings(left.state.completedAt, right.state.completedAt);\n if (completed !== 0) return completed;\n const started = compareAsciiStrings(left.state.startedAt, right.state.startedAt);\n if (started !== 0) return started;\n return compareAsciiStrings(left.runDirectoryName, right.runDirectoryName);\n}\n\nfunction productInputDigestsEqual(\n left: readonly ProductInputDigest[],\n right: readonly ProductInputDigest[],\n): boolean {\n return canonicalProductInputDigests(left) === canonicalProductInputDigests(right);\n}\n\nfunction canonicalProductInputDigests(digests: readonly ProductInputDigest[]): string {\n const normalized = [...digests]\n .map((digest) => [digest.descriptorId, digest.digest])\n .sort((left, right) => compareAsciiStrings(left.join(SEGMENT_SEPARATOR), right.join(SEGMENT_SEPARATOR)));\n return JSON.stringify(normalized);\n}\n\nfunction compareAsciiStrings(left: string, right: string): number {\n if (left < right) return -1;\n if (left > right) return 1;\n return 0;\n}\n\nfunction isTestRunDirectoryEntry(entry: TestRunDirectoryEntry): boolean {\n return entry.isDirectory() && RUN_DIRECTORY_NAME_PATTERN.test(entry.name);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction sha256Hex(value: string): string {\n return createHash(SHA256_ALGORITHM).update(value).digest(HEX_ENCODING);\n}\n\nfunction generateHexId(size: number, randomBytes: (size: number) => Buffer): string {\n return randomBytes(size).toString(HEX_ENCODING);\n}\n\nfunction hasErrorCode(error: unknown, code: string): boolean {\n return isRecord(error) && error.code === code;\n}\n\nfunction toErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n","import { createHash, randomBytes as nodeRandomBytes } from \"node:crypto\";\nimport {\n mkdir as nodeMkdir,\n readdir as nodeReaddir,\n readFile as nodeReadFile,\n rename as nodeRename,\n writeFile as nodeWriteFile,\n} from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport type { Result } from \"@/config/types\";\n\nimport { type AuditStorageConfig, DEFAULT_AUDIT_CONFIG } from \"./config\";\nimport { AUDIT_VERDICT_VALUE } from \"./reader\";\n\nexport const AUDIT_RUN_STATE_STATUS = {\n APPROVED: \"approved\",\n REJECTED: \"rejected\",\n FAILED: \"failed\",\n INTERRUPTED: \"interrupted\",\n} as const;\n\nexport const AUDIT_RUN_STATE_DISPLAY = {\n [AUDIT_RUN_STATE_STATUS.APPROVED]: \"APPROVED\",\n [AUDIT_RUN_STATE_STATUS.REJECTED]: AUDIT_VERDICT_VALUE.REJECT,\n [AUDIT_RUN_STATE_STATUS.FAILED]: \"FAILED\",\n [AUDIT_RUN_STATE_STATUS.INTERRUPTED]: \"INTERRUPTED\",\n} as const;\n\nexport const AUDIT_RUN_STATE_FIELDS = {\n BRANCH_NAME: \"branchName\",\n BRANCH_SLUG: \"branchSlug\",\n HEAD_SHA: \"headSha\",\n BASE_REF: \"baseRef\",\n AUDIT_CONFIG_DIGEST: \"auditConfigDigest\",\n AUDITORS: \"auditors\",\n TARGETS: \"targets\",\n STARTED_AT: \"startedAt\",\n COMPLETED_AT: \"completedAt\",\n VERDICT_PATH: \"verdictPath\",\n STATUS: \"status\",\n} as const;\n\nexport const AUDIT_RUN_STATE_INCOMPLETE_REASON = {\n MISSING_STATE: \"missing-state\",\n IO_ERROR: \"io-error\",\n PARSE_INVALID_STATE: \"parse-invalid-state\",\n SHAPE_INVALID_STATE: \"shape-invalid-state\",\n} as const;\n\nexport const AUDIT_RUN_STATE_ERROR = {\n RUN_DIRECTORY_COLLISION_LIMIT: \"audit run directory collision limit exhausted\",\n RUN_DIRECTORY_CREATE_FAILED: \"audit run directory create failed\",\n INVALID_BRANCH_SLUG: \"audit branch slug must be normalized before storage\",\n STATE_ALREADY_EXISTS: \"audit run state already exists\",\n STATE_WRITE_FAILED: \"audit run state write failed\",\n INVALID_TERMINAL_STATE: \"audit run state must be terminal\",\n} as const;\n\nexport type AuditRunStateStatus = (typeof AUDIT_RUN_STATE_STATUS)[keyof typeof AUDIT_RUN_STATE_STATUS];\nexport type AuditRunStateIncompleteReason =\n (typeof AUDIT_RUN_STATE_INCOMPLETE_REASON)[keyof typeof AUDIT_RUN_STATE_INCOMPLETE_REASON];\n\nexport interface AuditRunState {\n readonly branchName: string;\n readonly branchSlug: string;\n readonly headSha: string;\n readonly baseRef: string;\n readonly auditConfigDigest: string;\n readonly auditors: readonly string[];\n readonly targets: readonly string[];\n readonly startedAt: string;\n readonly completedAt: string;\n readonly verdictPath?: string;\n readonly status: AuditRunStateStatus;\n}\n\nexport interface AuditRunDirectory {\n readonly branchDir: string;\n readonly runsDir: string;\n readonly runDir: string;\n readonly runDirectoryName: string;\n readonly runId: string;\n readonly startedAt: string;\n}\n\nexport interface AuditTerminalRun {\n readonly runDirectoryName: string;\n readonly runDir: string;\n readonly statePath: string;\n readonly state: AuditRunState;\n}\n\nexport interface AuditIncompleteRun {\n readonly runDirectoryName: string;\n readonly runDir: string;\n readonly statePath: string;\n readonly reason: AuditRunStateIncompleteReason;\n readonly error?: string;\n}\n\nexport interface AuditBranchRuns {\n readonly terminalRuns: readonly AuditTerminalRun[];\n readonly incompleteRuns: readonly AuditIncompleteRun[];\n}\n\nexport interface AuditRunDirectoryEntry {\n readonly name: string;\n isDirectory(): boolean;\n}\n\nexport interface AuditRunStateFileSystem {\n mkdir(path: string, options?: { readonly recursive?: boolean }): Promise<void>;\n writeFile(path: string, data: string, options?: { readonly flag?: string }): Promise<void>;\n rename(source: string, target: string): Promise<void>;\n readFile(path: string, encoding: \"utf8\"): Promise<string>;\n readdir(path: string, options: { readonly withFileTypes: true }): Promise<readonly AuditRunDirectoryEntry[]>;\n}\n\nexport interface CreateAuditRunDirectoryOptions {\n readonly now?: () => Date;\n readonly randomBytes?: (size: number) => Buffer;\n readonly fs?: AuditRunStateFileSystem;\n readonly storage?: AuditStorageConfig;\n readonly maxAttempts?: number;\n}\n\nexport interface WriteAuditRunStateOptions {\n readonly randomBytes?: (size: number) => Buffer;\n readonly fs?: AuditRunStateFileSystem;\n readonly storage?: AuditStorageConfig;\n}\n\nexport interface ReadAuditRunStateOptions {\n readonly fs?: AuditRunStateFileSystem;\n readonly storage?: AuditStorageConfig;\n}\n\nconst SHA256_ALGORITHM = \"sha256\";\nconst HEX_ENCODING = \"hex\";\nconst HASH_PREFIX_HEX_LENGTH = 8;\nconst DETACHED_HEAD_PREFIX = \"detached\";\nconst DETACHED_HEAD_SHA_HEX_LENGTH = 12;\nconst RUN_ID_BYTES = 6;\nconst RUN_DIRECTORY_CREATE_ATTEMPTS = 10;\nconst TEMP_STATE_ID_BYTES = 6;\nconst TEMP_STATE_FILE_PREFIX = \".state\";\nconst TEMP_STATE_FILE_SUFFIX = \".tmp\";\nconst JSON_INDENT_SPACES = 2;\nconst AUDIT_RUN_TIMESTAMP_SEPARATOR = \"_\";\nconst AUDIT_RUN_TIMESTAMP_MILLISECOND_DIGITS = 3;\nconst EXCLUSIVE_CREATE_FLAG = \"wx\";\nconst ERROR_CODE_FILE_EXISTS = \"EEXIST\";\nconst ERROR_CODE_NOT_FOUND = \"ENOENT\";\nconst PATH_SEPARATOR_PATTERN = /[^a-z0-9]+/g;\nconst EDGE_SEPARATOR_PATTERN = /^-|-$/g;\nconst TRAILING_SEPARATOR_PATTERN = /-+$/;\nconst BRANCH_SLUG_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\nconst RUN_DIRECTORY_NAME_PATTERN = /^\\d{4}-\\d{2}-\\d{2}_\\d{2}-\\d{2}-\\d{2}-\\d{3}-[a-f0-9]{12}$/;\nconst SLUG_SEPARATOR = \"-\";\nconst EMPTY_STRING = \"\";\n\nconst defaultFileSystem: AuditRunStateFileSystem = {\n mkdir: async (path, options) => {\n // Normalize nodeMkdir's recursive overload to the injected fs contract.\n await nodeMkdir(path, options);\n },\n writeFile: nodeWriteFile,\n rename: nodeRename,\n readFile: nodeReadFile,\n readdir: nodeReaddir,\n};\n\nexport function resolveAuditBranchIdentity(input: {\n readonly branchName?: string;\n readonly headSha: string;\n}): string {\n if (input.branchName !== undefined && input.branchName.length > 0) return input.branchName;\n return `${DETACHED_HEAD_PREFIX}${SLUG_SEPARATOR}${\n input.headSha.slice(0, DETACHED_HEAD_SHA_HEX_LENGTH).toLowerCase()\n }`;\n}\n\nexport function slugAuditBranchIdentity(\n branchIdentity: string,\n maxBytes: number = DEFAULT_AUDIT_CONFIG.branchSlug.maxBytes,\n): string {\n const hashPrefix = sha256Hex(branchIdentity).slice(0, HASH_PREFIX_HEX_LENGTH);\n const boundedHashPrefix = hashPrefix.slice(0, Math.max(0, maxBytes));\n const normalizedPrefix = branchIdentity\n .toLowerCase()\n .replace(PATH_SEPARATOR_PATTERN, SLUG_SEPARATOR)\n .replace(EDGE_SEPARATOR_PATTERN, EMPTY_STRING);\n\n if (normalizedPrefix.length === 0) return boundedHashPrefix;\n\n const availablePrefixBytes = maxBytes - HASH_PREFIX_HEX_LENGTH - SLUG_SEPARATOR.length;\n if (availablePrefixBytes <= 0) return boundedHashPrefix;\n\n const prefix = truncateNormalizedSlugPrefix(normalizedPrefix, availablePrefixBytes);\n return prefix.length === 0 ? boundedHashPrefix : `${prefix}${SLUG_SEPARATOR}${hashPrefix}`;\n}\n\nexport function formatAuditRunTimestamp(date: Date): string {\n const year = date.getUTCFullYear();\n const month = String(date.getUTCMonth() + 1).padStart(2, \"0\");\n const day = String(date.getUTCDate()).padStart(2, \"0\");\n const hours = String(date.getUTCHours()).padStart(2, \"0\");\n const minutes = String(date.getUTCMinutes()).padStart(2, \"0\");\n const seconds = String(date.getUTCSeconds()).padStart(2, \"0\");\n const milliseconds = String(date.getUTCMilliseconds()).padStart(AUDIT_RUN_TIMESTAMP_MILLISECOND_DIGITS, \"0\");\n\n return `${year}-${month}-${day}${AUDIT_RUN_TIMESTAMP_SEPARATOR}${hours}-${minutes}-${seconds}-${milliseconds}`;\n}\n\nexport function generateAuditRunId(randomBytes: (size: number) => Buffer = nodeRandomBytes): string {\n return randomBytes(RUN_ID_BYTES).toString(HEX_ENCODING);\n}\n\nfunction auditBranchDir(\n gitCommonDirProductDir: string,\n validatedBranchSlug: string,\n storage: AuditStorageConfig = DEFAULT_AUDIT_CONFIG.storage,\n): string {\n return join(gitCommonDirProductDir, storage.spxDir, storage.auditDir, validatedBranchSlug);\n}\n\nfunction auditRunsDir(\n gitCommonDirProductDir: string,\n branchSlug: string,\n storage: AuditStorageConfig = DEFAULT_AUDIT_CONFIG.storage,\n): string {\n return join(auditBranchDir(gitCommonDirProductDir, branchSlug, storage), storage.runsDir);\n}\n\nexport async function createAuditRunDirectory(\n gitCommonDirProductDir: string,\n branchSlug: string,\n options: CreateAuditRunDirectoryOptions = {},\n): Promise<Result<AuditRunDirectory>> {\n const fs = options.fs ?? defaultFileSystem;\n const storage = options.storage ?? DEFAULT_AUDIT_CONFIG.storage;\n const validatedBranchSlug = validateAuditBranchSlug(branchSlug);\n if (!validatedBranchSlug.ok) return validatedBranchSlug;\n const maxAttempts = options.maxAttempts ?? RUN_DIRECTORY_CREATE_ATTEMPTS;\n const startedDate = (options.now ?? (() => new Date()))();\n const startedAt = formatAuditRunTimestamp(startedDate);\n const branchDir = auditBranchDir(gitCommonDirProductDir, validatedBranchSlug.value, storage);\n const runsDir = auditRunsDir(gitCommonDirProductDir, validatedBranchSlug.value, storage);\n const randomBytes = options.randomBytes ?? nodeRandomBytes;\n\n try {\n await fs.mkdir(runsDir, { recursive: true });\n } catch (error) {\n return { ok: false, error: `${AUDIT_RUN_STATE_ERROR.RUN_DIRECTORY_CREATE_FAILED}: ${toErrorMessage(error)}` };\n }\n\n for (let attempt = 0; attempt < maxAttempts; attempt += 1) {\n const runId = generateAuditRunId(randomBytes);\n const runDirectoryName = `${startedAt}${SLUG_SEPARATOR}${runId}`;\n const runDir = join(runsDir, runDirectoryName);\n try {\n await fs.mkdir(runDir);\n return {\n ok: true,\n value: {\n branchDir,\n runsDir,\n runDir,\n runDirectoryName,\n runId,\n startedAt,\n },\n };\n } catch (error) {\n if (hasErrorCode(error, ERROR_CODE_FILE_EXISTS)) continue;\n return { ok: false, error: `${AUDIT_RUN_STATE_ERROR.RUN_DIRECTORY_CREATE_FAILED}: ${toErrorMessage(error)}` };\n }\n }\n\n return { ok: false, error: AUDIT_RUN_STATE_ERROR.RUN_DIRECTORY_COLLISION_LIMIT };\n}\n\nexport async function writeTerminalAuditRunState(\n runDir: string,\n state: AuditRunState,\n options: WriteAuditRunStateOptions = {},\n): Promise<Result<string>> {\n if (!isAuditRunStateStatus(state.status)) {\n return { ok: false, error: AUDIT_RUN_STATE_ERROR.INVALID_TERMINAL_STATE };\n }\n\n const fs = options.fs ?? defaultFileSystem;\n const storage = options.storage ?? DEFAULT_AUDIT_CONFIG.storage;\n const statePath = join(runDir, storage.stateFile);\n try {\n await fs.readFile(statePath, \"utf8\");\n return { ok: false, error: AUDIT_RUN_STATE_ERROR.STATE_ALREADY_EXISTS };\n } catch (error) {\n if (!hasErrorCode(error, ERROR_CODE_NOT_FOUND)) {\n return { ok: false, error: `${AUDIT_RUN_STATE_ERROR.STATE_WRITE_FAILED}: ${toErrorMessage(error)}` };\n }\n }\n\n const tempId = generateHexId(TEMP_STATE_ID_BYTES, options.randomBytes ?? nodeRandomBytes);\n const tempPath = join(runDir, `${TEMP_STATE_FILE_PREFIX}-${tempId}${TEMP_STATE_FILE_SUFFIX}`);\n const serialized = `${JSON.stringify(state, null, JSON_INDENT_SPACES)}\\n`;\n\n try {\n await fs.writeFile(tempPath, serialized, { flag: EXCLUSIVE_CREATE_FLAG });\n await fs.rename(tempPath, statePath);\n return { ok: true, value: statePath };\n } catch (error) {\n return { ok: false, error: `${AUDIT_RUN_STATE_ERROR.STATE_WRITE_FAILED}: ${toErrorMessage(error)}` };\n }\n}\n\nexport async function readAuditBranchRuns(\n gitCommonDirProductDir: string,\n branchSlug: string,\n options: ReadAuditRunStateOptions = {},\n): Promise<Result<AuditBranchRuns>> {\n const fs = options.fs ?? defaultFileSystem;\n const storage = options.storage ?? DEFAULT_AUDIT_CONFIG.storage;\n const validatedBranchSlug = validateAuditBranchSlug(branchSlug);\n if (!validatedBranchSlug.ok) return validatedBranchSlug;\n const runsDir = auditRunsDir(gitCommonDirProductDir, validatedBranchSlug.value, storage);\n let entries: readonly AuditRunDirectoryEntry[];\n try {\n entries = await fs.readdir(runsDir, { withFileTypes: true });\n } catch (error) {\n if (hasErrorCode(error, ERROR_CODE_NOT_FOUND)) {\n return { ok: true, value: { terminalRuns: [], incompleteRuns: [] } };\n }\n return { ok: false, error: toErrorMessage(error) };\n }\n\n const terminalRuns: AuditTerminalRun[] = [];\n const incompleteRuns: AuditIncompleteRun[] = [];\n for (const entry of entries.filter(isAuditRunDirectoryEntry)) {\n const runDir = join(runsDir, entry.name);\n const statePath = join(runDir, storage.stateFile);\n const stateResult = await readAuditRunStatePath(statePath, fs);\n if (stateResult.ok) {\n terminalRuns.push({\n runDirectoryName: entry.name,\n runDir,\n statePath,\n state: stateResult.value,\n });\n } else {\n incompleteRuns.push({\n runDirectoryName: entry.name,\n runDir,\n statePath,\n reason: stateResult.reason,\n error: stateResult.error,\n });\n }\n }\n\n return { ok: true, value: { terminalRuns, incompleteRuns } };\n}\n\nexport function selectLatestTerminalAuditRun(\n runs: readonly AuditTerminalRun[],\n): AuditTerminalRun | undefined {\n return runs.reduce<AuditTerminalRun | undefined>((latest, candidate) => {\n if (latest === undefined) return candidate;\n return compareTerminalRuns(latest, candidate) < 0 ? candidate : latest;\n }, undefined);\n}\n\nfunction compareTerminalRuns(left: AuditTerminalRun, right: AuditTerminalRun): number {\n const completed = compareAsciiStrings(left.state.completedAt, right.state.completedAt);\n if (completed !== 0) return completed;\n const started = compareAsciiStrings(left.state.startedAt, right.state.startedAt);\n if (started !== 0) return started;\n return compareAsciiStrings(left.runDirectoryName, right.runDirectoryName);\n}\n\nfunction compareAsciiStrings(left: string, right: string): number {\n if (left < right) return -1;\n if (left > right) return 1;\n return 0;\n}\n\nasync function readAuditRunStatePath(\n statePath: string,\n fs: AuditRunStateFileSystem,\n): Promise<\n | { readonly ok: true; readonly value: AuditRunState }\n | { readonly ok: false; readonly reason: AuditRunStateIncompleteReason; readonly error?: string }\n> {\n let raw: string;\n try {\n raw = await fs.readFile(statePath, \"utf8\");\n } catch (error) {\n if (hasErrorCode(error, ERROR_CODE_NOT_FOUND)) {\n return { ok: false, reason: AUDIT_RUN_STATE_INCOMPLETE_REASON.MISSING_STATE };\n }\n return {\n ok: false,\n reason: AUDIT_RUN_STATE_INCOMPLETE_REASON.IO_ERROR,\n error: toErrorMessage(error),\n };\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw) as unknown;\n } catch (error) {\n return {\n ok: false,\n reason: AUDIT_RUN_STATE_INCOMPLETE_REASON.PARSE_INVALID_STATE,\n error: toErrorMessage(error),\n };\n }\n\n const validated = validateAuditRunState(parsed);\n if (!validated.ok) {\n return {\n ok: false,\n reason: AUDIT_RUN_STATE_INCOMPLETE_REASON.SHAPE_INVALID_STATE,\n error: validated.error,\n };\n }\n return validated;\n}\n\nfunction validateAuditRunState(value: unknown): Result<AuditRunState> {\n if (!isRecord(value)) return { ok: false, error: \"audit run state must be an object\" };\n const branchName = readString(value, AUDIT_RUN_STATE_FIELDS.BRANCH_NAME);\n if (!branchName.ok) return branchName;\n const branchSlug = readString(value, AUDIT_RUN_STATE_FIELDS.BRANCH_SLUG);\n if (!branchSlug.ok) return branchSlug;\n const headSha = readString(value, AUDIT_RUN_STATE_FIELDS.HEAD_SHA);\n if (!headSha.ok) return headSha;\n const baseRef = readString(value, AUDIT_RUN_STATE_FIELDS.BASE_REF);\n if (!baseRef.ok) return baseRef;\n const auditConfigDigest = readString(value, AUDIT_RUN_STATE_FIELDS.AUDIT_CONFIG_DIGEST);\n if (!auditConfigDigest.ok) return auditConfigDigest;\n const auditors = readStringArray(value, AUDIT_RUN_STATE_FIELDS.AUDITORS);\n if (!auditors.ok) return auditors;\n const targets = readStringArray(value, AUDIT_RUN_STATE_FIELDS.TARGETS);\n if (!targets.ok) return targets;\n const startedAt = readString(value, AUDIT_RUN_STATE_FIELDS.STARTED_AT);\n if (!startedAt.ok) return startedAt;\n const completedAt = readString(value, AUDIT_RUN_STATE_FIELDS.COMPLETED_AT);\n if (!completedAt.ok) return completedAt;\n const status = readStatus(value, AUDIT_RUN_STATE_FIELDS.STATUS);\n if (!status.ok) return status;\n const verdictPathRaw = value[AUDIT_RUN_STATE_FIELDS.VERDICT_PATH];\n if (verdictPathRaw !== undefined && typeof verdictPathRaw !== \"string\") {\n return { ok: false, error: `${AUDIT_RUN_STATE_FIELDS.VERDICT_PATH} must be a string` };\n }\n\n return {\n ok: true,\n value: {\n branchName: branchName.value,\n branchSlug: branchSlug.value,\n headSha: headSha.value,\n baseRef: baseRef.value,\n auditConfigDigest: auditConfigDigest.value,\n auditors: auditors.value,\n targets: targets.value,\n startedAt: startedAt.value,\n completedAt: completedAt.value,\n ...(verdictPathRaw === undefined ? {} : { verdictPath: verdictPathRaw }),\n status: status.value,\n },\n };\n}\n\nfunction readString(value: Record<string, unknown>, field: string): Result<string> {\n const raw = value[field];\n return typeof raw === \"string\" && raw.length > 0\n ? { ok: true, value: raw }\n : { ok: false, error: `${field} must be a non-empty string` };\n}\n\nfunction readStringArray(value: Record<string, unknown>, field: string): Result<readonly string[]> {\n const raw = value[field];\n return Array.isArray(raw) && raw.every((entry) => typeof entry === \"string\" && entry.length > 0)\n ? { ok: true, value: raw }\n : { ok: false, error: `${field} must be an array of non-empty strings` };\n}\n\nfunction readStatus(value: Record<string, unknown>, field: string): Result<AuditRunStateStatus> {\n const raw = value[field];\n return isAuditRunStateStatus(raw)\n ? { ok: true, value: raw }\n : { ok: false, error: `${field} must be a terminal audit status` };\n}\n\nfunction isAuditRunStateStatus(value: unknown): value is AuditRunStateStatus {\n return typeof value === \"string\" && Object.values(AUDIT_RUN_STATE_STATUS).includes(value as AuditRunStateStatus);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction sha256Hex(value: string): string {\n return createHash(SHA256_ALGORITHM).update(value).digest(HEX_ENCODING);\n}\n\nfunction generateHexId(size: number, randomBytes: (size: number) => Buffer): string {\n return randomBytes(size).toString(HEX_ENCODING);\n}\n\nfunction truncateNormalizedSlugPrefix(value: string, maxBytes: number): string {\n return value.slice(0, maxBytes).replace(TRAILING_SEPARATOR_PATTERN, EMPTY_STRING);\n}\n\nfunction validateAuditBranchSlug(branchSlug: string): Result<string> {\n return BRANCH_SLUG_PATTERN.test(branchSlug)\n ? { ok: true, value: branchSlug }\n : { ok: false, error: AUDIT_RUN_STATE_ERROR.INVALID_BRANCH_SLUG };\n}\n\nfunction isAuditRunDirectoryEntry(entry: AuditRunDirectoryEntry): boolean {\n return entry.isDirectory() && RUN_DIRECTORY_NAME_PATTERN.test(entry.name);\n}\n\nfunction hasErrorCode(error: unknown, code: string): boolean {\n return isRecord(error) && error.code === code;\n}\n\nfunction toErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n","import { currentStalenessInputs, discoverTestFiles, runNodeCommand } from \"@/commands/testing\";\nimport type { GitDependencies } from \"@/git/root\";\nimport type { NodeOutcomeResolver } from \"@/lib/node-status\";\nimport { SPEC_TREE_CONFIG } from \"@/lib/spec-tree/config\";\nimport type { TestingLanguageDescriptor, TestRunnerDependencies } from \"@/testing/languages/types\";\nimport type { TestingRegistry } from \"@/testing/registry\";\nimport {\n extractStalenessInputs,\n isStalenessMatch,\n outcomesCoverPaths,\n readTestingRuns,\n selectLatestTerminalTestRunForNode,\n TEST_RUN_STATE_STATUS,\n type TestRunStateFileSystem,\n type TestTerminalRun,\n} from \"@/testing/run-state\";\n\nconst PATH_SEPARATOR = \"/\";\n\n/** Dependencies the production resolver composes over the testing domain. */\nexport interface NodeOutcomeResolverDependencies {\n readonly productDir: string;\n readonly registry: TestingRegistry;\n readonly runnerDepsFor: (language: TestingLanguageDescriptor) => TestRunnerDependencies;\n readonly git?: GitDependencies;\n readonly fs?: TestRunStateFileSystem;\n readonly now?: () => Date;\n}\n\n// The product-wide inputs the per-node freshness check reads, gathered once per\n// resolver rather than per node: the discovered test files and the recorded\n// terminal runs.\ninterface ResolverEvidence {\n readonly discoveredTestPaths: readonly string[];\n readonly terminalRuns: readonly TestTerminalRun[];\n}\n\n/**\n * Builds the node-outcome resolver `spx spec status --update` injects into the\n * node-status orchestration: for a node it reports the latest usable recorded\n * testing evidence (fresh and passed) and runs the testing domain's registry-based\n * per-node run only when that evidence is stale, failing, or absent. Composed at\n * the command layer over the testing domain so the pure node-status library and\n * the testing library stay independent. The discovered test files and recorded\n * runs are read once and memoized across nodes, so resolving N nodes performs one\n * tree walk and one run-directory read rather than N of each.\n */\nexport function createNodeOutcomeResolver(deps: NodeOutcomeResolverDependencies): NodeOutcomeResolver {\n let evidence: Promise<ResolverEvidence> | undefined;\n const sharedEvidence = (): Promise<ResolverEvidence> => (evidence ??= loadResolverEvidence(deps));\n\n return async (nodeId: string): Promise<boolean> => {\n const { discoveredTestPaths, terminalRuns } = await sharedEvidence();\n const nodePath = `${SPEC_TREE_CONFIG.ROOT_DIRECTORY}${PATH_SEPARATOR}${nodeId}`;\n const nodeTestPaths = filterNodeTestPaths(discoveredTestPaths, nodePath);\n const usable = await usableRecordedOutcome(deps, discoveredTestPaths, terminalRuns, nodeTestPaths);\n if (usable !== undefined) {\n return usable;\n }\n const { dispatch, recorded } = await runNodeCommand({ productDir: deps.productDir, nodePath }, deps);\n // Report the node passing only when the run executed every one of its test paths\n // and passed; a gated-out or unmatched language leaves some path unexecuted, and\n // a zero-outcome run covers nothing, so neither vacuously passes.\n return outcomesCoverPaths(dispatch.outcomes, nodeTestPaths) && recorded.status === TEST_RUN_STATE_STATUS.PASSED;\n };\n}\n\n// Reads the discovered test files and recorded terminal runs once for the whole\n// --update pass. A failed run-state read yields no terminal runs, so every node\n// reads as absent and re-runs — the conservative-correct fallback.\nasync function loadResolverEvidence(deps: NodeOutcomeResolverDependencies): Promise<ResolverEvidence> {\n const discoveredTestPaths = await discoverTestFiles(deps.productDir);\n const runs = await readTestingRuns(deps.productDir, deps);\n return { discoveredTestPaths, terminalRuns: runs.ok ? runs.value.terminalRuns : [] };\n}\n\n// A node's test paths are the discovered test files under its subtree — the same\n// set the per-node run records against, so coverage-gated evidence selection and\n// the per-node run agree on path identity.\nfunction filterNodeTestPaths(discoveredTestPaths: readonly string[], nodePath: string): readonly string[] {\n const prefix = `${nodePath}${PATH_SEPARATOR}`;\n return discoveredTestPaths.filter((path) => path.startsWith(prefix));\n}\n\n// Resolves a recorded outcome (true) only when the latest covering run is fresh —\n// every staleness digest matches the node's current inputs by the same recipe the\n// run recorded with — and passed. Returns undefined for stale, failing, or absent\n// evidence, signalling that a fresh per-node run is required.\nasync function usableRecordedOutcome(\n deps: NodeOutcomeResolverDependencies,\n discoveredTestPaths: readonly string[],\n terminalRuns: readonly TestTerminalRun[],\n nodeTestPaths: readonly string[],\n): Promise<boolean | undefined> {\n const latest = selectLatestTerminalTestRunForNode(terminalRuns, nodeTestPaths);\n if (latest === undefined) {\n return undefined;\n }\n // Compare freshness over the run's own covered paths — the set its recorded\n // digests were derived from — so a covering run reads as fresh when its executed\n // files are unchanged. Comparing over only the node's paths would judge a fresh\n // full-product run stale for any node smaller than the whole product.\n const runCoveredPaths = latest.state.runnerOutcomes.flatMap((outcome) => outcome.testPaths);\n // A covered test file deleted or renamed since the run makes the recorded\n // evidence stale; re-run rather than reading a path that no longer exists.\n const presentTestPaths = new Set(discoveredTestPaths);\n if (!runCoveredPaths.every((path) => presentTestPaths.has(path))) {\n return undefined;\n }\n const current = await currentStalenessInputs(deps.productDir, runCoveredPaths, deps);\n const fresh = isStalenessMatch(extractStalenessInputs(latest.state), current);\n return fresh && latest.state.status === TEST_RUN_STATE_STATUS.PASSED ? true : undefined;\n}\n","import { SPEC_TREE_NODE_STATE, type SpecTreeNodeState } from \"@/lib/spec-tree/config\";\n\n/**\n * The three observable facts that determine a spec-tree node's lifecycle state.\n *\n * - `hasTests` — the node directory contains co-located evidence files.\n * - `isExcluded` — the node path is listed in `spx/EXCLUDE`.\n * - `testsPass` — the node's tests all pass when executed.\n */\nexport interface NodeClassificationFacts {\n readonly hasTests: boolean;\n readonly isExcluded: boolean;\n readonly testsPass: boolean;\n}\n\n/** JSON key under which the lifecycle state is recorded in `spx.status.json`. */\nexport const NODE_STATUS_STATUS_KEY = \"status\";\n\nconst NODE_STATUS_JSON_INDENT = 2;\n\n/**\n * Resolve a node's lifecycle state from its classification facts.\n *\n * Precedence (declared in `node-status.md`): a node with no co-located tests is\n * `declared`; otherwise a node listed in `spx/EXCLUDE` is `specified`; otherwise\n * a node whose tests pass is `passing`; otherwise the node is `failing`.\n */\nexport function classifyNodeStatus(facts: NodeClassificationFacts): SpecTreeNodeState {\n if (!facts.hasTests) return SPEC_TREE_NODE_STATE.DECLARED;\n if (facts.isExcluded) return SPEC_TREE_NODE_STATE.SPECIFIED;\n if (facts.testsPass) return SPEC_TREE_NODE_STATE.PASSING;\n return SPEC_TREE_NODE_STATE.FAILING;\n}\n\n/** Serialize a lifecycle state to the canonical `spx.status.json` document. */\nexport function serializeNodeStatus(state: SpecTreeNodeState): string {\n return `${JSON.stringify({ [NODE_STATUS_STATUS_KEY]: state }, null, NODE_STATUS_JSON_INDENT)}\\n`;\n}\n","import { join } from \"node:path\";\n\nimport type { SpecTreeEvidenceProvider, SpecTreeNodeSourceEntry } from \"@/lib/spec-tree\";\nimport { SPEC_TREE_CONFIG, type SpecTreeNodeState } from \"@/lib/spec-tree/config\";\nimport { readNodeStatus } from \"./read\";\n\n/**\n * Resolve the absolute directory of a spec-tree node under `productDir`.\n *\n * A node source entry's `id` is its directory path relative to the spec-tree\n * root, so the node directory is `productDir/<root>/<id>`.\n */\nfunction nodeDirectory(productDir: string, node: SpecTreeNodeSourceEntry): string {\n return join(productDir, SPEC_TREE_CONFIG.ROOT_DIRECTORY, node.id);\n}\n\n/**\n * Build a spec-tree evidence provider that overrides each node's live-derived\n * state with the state persisted in its co-located `spx.status.json`.\n *\n * The provider closes over `productDir` because `stateForNode` receives only the\n * node source entry and in-memory evidence — no filesystem path. A node with no\n * persisted file yields `undefined`, which routes the spec-tree library back to\n * live derivation.\n *\n * @param productDir - Absolute path to the product directory.\n */\nexport function createNodeStatusProvider(productDir: string): SpecTreeEvidenceProvider {\n return {\n stateForNode(node: SpecTreeNodeSourceEntry): SpecTreeNodeState | undefined {\n return readNodeStatus(nodeDirectory(productDir, node));\n },\n };\n}\n","import { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nimport { SPEC_TREE_NODE_STATE, type SpecTreeNodeState } from \"@/lib/spec-tree/config\";\nimport { NODE_STATUS_STATUS_KEY } from \"./classify\";\n\n/** Filename of the co-located per-node lifecycle-state record. */\nexport const NODE_STATUS_FILENAME = \"spx.status.json\";\n\nconst NODE_STATUS_VALUES: ReadonlySet<string> = new Set(Object.values(SPEC_TREE_NODE_STATE));\n\nfunction isNodeError(error: unknown): error is NodeJS.ErrnoException {\n return error instanceof Error && \"code\" in error;\n}\n\nfunction isSpecTreeNodeState(value: unknown): value is SpecTreeNodeState {\n return typeof value === \"string\" && NODE_STATUS_VALUES.has(value);\n}\n\n/**\n * Read a node's recorded lifecycle state from its co-located `spx.status.json`.\n *\n * Returns `undefined` when the file is absent — absence means \"no recorded\n * state\", which routes consumers to live derivation. A present file whose\n * content is not a valid status record is a corruption error, not absence.\n *\n * @param nodeDir - Absolute path to the node directory.\n */\nexport function readNodeStatus(nodeDir: string): SpecTreeNodeState | undefined {\n const filePath = join(nodeDir, NODE_STATUS_FILENAME);\n\n let content: string;\n try {\n content = readFileSync(filePath, \"utf8\");\n } catch (error) {\n if (isNodeError(error) && error.code === \"ENOENT\") {\n return undefined;\n }\n throw error;\n }\n\n const parsed = JSON.parse(content) as Record<string, unknown>;\n const status = parsed[NODE_STATUS_STATUS_KEY];\n if (!isSpecTreeNodeState(status)) {\n throw new Error(\n `Invalid ${NODE_STATUS_FILENAME} at ${filePath}: status \"${String(status)}\" is not a lifecycle state`,\n );\n }\n return status;\n}\n","import { mkdir, writeFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\n\nimport { createIgnoreSourceReader, IGNORE_SOURCE_FILENAME_DEFAULT } from \"@/lib/file-inclusion/ignore-source\";\nimport {\n createFilesystemSpecTreeSource,\n readSpecTree,\n SPEC_TREE_ENTRY_TYPE,\n type SpecTreeNode,\n type SpecTreeSnapshot,\n} from \"@/lib/spec-tree\";\nimport { SPEC_TREE_CONFIG } from \"@/lib/spec-tree/config\";\nimport { classifyNodeStatus, type NodeClassificationFacts, serializeNodeStatus } from \"./classify\";\nimport { NODE_STATUS_FILENAME } from \"./read\";\n\n/**\n * Resolves a node's pass/fail outcome — from recorded testing evidence when it is\n * usable, otherwise by running the node's tests. Injected at the command edge so\n * the classifier's precedence logic is verifiable without executing a real suite.\n */\nexport type NodeOutcomeResolver = (nodeId: string) => Promise<boolean>;\n\nexport interface UpdateNodeStatusOptions {\n readonly productDir: string;\n readonly resolveOutcome: NodeOutcomeResolver;\n}\n\nconst NODE_STATUS_TEXT_ENCODING = \"utf8\";\n\n/**\n * Classify every spec-tree node under `productDir` and write its lifecycle state\n * to a co-located `spx.status.json`. This is the only path that writes the file.\n */\nexport async function updateNodeStatus(options: UpdateNodeStatusOptions): Promise<void> {\n const { productDir, resolveOutcome } = options;\n const snapshot = await readSpecTree({ source: createFilesystemSpecTreeSource({ productDir }) });\n const ignoreReader = createIgnoreSourceReader(productDir, {\n ignoreSourceFilename: IGNORE_SOURCE_FILENAME_DEFAULT,\n specTreeRootSegment: SPEC_TREE_CONFIG.ROOT_DIRECTORY,\n });\n const nodesWithTests = collectNodesWithTests(snapshot);\n\n for (const node of snapshot.allNodes) {\n const facts = await classifyFacts(node, {\n hasTests: nodesWithTests.has(node.id),\n isExcluded: isNodeExcluded(ignoreReader, node),\n resolveOutcome,\n });\n await writeNodeStatus(productDir, node.id, classifyNodeStatus(facts));\n }\n}\n\ntype ClassifyFactsInput = {\n readonly hasTests: boolean;\n readonly isExcluded: boolean;\n readonly resolveOutcome: NodeOutcomeResolver;\n};\n\nasync function classifyFacts(node: SpecTreeNode, input: ClassifyFactsInput): Promise<NodeClassificationFacts> {\n // The resolver is consulted only when its outcome can change the classification\n // — a node with no tests is declared, and an excluded node is specified, before\n // any outcome is resolved.\n const testsPass = input.hasTests && !input.isExcluded ? await input.resolveOutcome(node.id) : false;\n return { hasTests: input.hasTests, isExcluded: input.isExcluded, testsPass };\n}\n\nfunction collectNodesWithTests(snapshot: SpecTreeSnapshot): ReadonlySet<string> {\n const parents = new Set<string>();\n for (const entry of snapshot.entries) {\n if (entry.type === SPEC_TREE_ENTRY_TYPE.EVIDENCE) {\n parents.add(entry.parentId);\n }\n }\n return parents;\n}\n\nfunction isNodeExcluded(ignoreReader: ReturnType<typeof createIgnoreSourceReader>, node: SpecTreeNode): boolean {\n const reference = node.ref?.path;\n if (reference === undefined) return false;\n return ignoreReader.isUnderIgnoreSource(reference);\n}\n\nasync function writeNodeStatus(\n productDir: string,\n nodeId: string,\n state: ReturnType<typeof classifyNodeStatus>,\n): Promise<void> {\n const filePath = join(productDir, SPEC_TREE_CONFIG.ROOT_DIRECTORY, nodeId, NODE_STATUS_FILENAME);\n await mkdir(dirname(filePath), { recursive: true });\n await writeFile(filePath, serializeNodeStatus(state), NODE_STATUS_TEXT_ENCODING);\n}\n","import type { GitDependencies } from \"@/git/root\";\nimport { createNodeStatusProvider, type NodeOutcomeResolver, updateNodeStatus } from \"@/lib/node-status\";\nimport {\n createFilesystemSpecTreeSource,\n projectSpecTree,\n readSpecTree,\n type SpecTreeProjectedNode,\n type SpecTreeProjection,\n type SpecTreeSource,\n} from \"@/lib/spec-tree\";\nimport { KIND_REGISTRY, SPEC_TREE_CONFIG } from \"@/lib/spec-tree/config\";\nimport { resolveSpecProductDir, type SpecProductDirWarningHandler } from \"./root\";\n\nexport const OUTPUT_FORMAT = {\n TEXT: \"text\",\n JSON: \"json\",\n MARKDOWN: \"markdown\",\n TABLE: \"table\",\n} as const;\n\nexport const SPEC_STATUS_MESSAGE = {\n EMPTY: `No spec-tree nodes found in ${SPEC_TREE_CONFIG.ROOT_DIRECTORY}`,\n} as const;\n\nconst DEFAULT_FORMAT: OutputFormat = OUTPUT_FORMAT.TEXT;\nconst JSON_INDENTATION = 2;\nconst STATUS_SEPARATOR = \" \";\nconst NODE_INDENT = \" \";\nconst MARKDOWN_NODE_PREFIX = \"- \";\nconst TABLE_SEPARATOR = \"|\";\nconst TABLE_HEADER_SEPARATOR = \"---\";\nconst TABLE_HEADER = {\n KIND: \"Kind\",\n PATH: \"Path\",\n STATE: \"State\",\n} as const;\nexport const SPEC_STATUS_TABLE_HEADER = formatTableRow([\n TABLE_HEADER.KIND,\n TABLE_HEADER.PATH,\n TABLE_HEADER.STATE,\n]);\n\nexport type OutputFormat = (typeof OUTPUT_FORMAT)[keyof typeof OUTPUT_FORMAT];\n\ninterface StatusBaseOptions {\n cwd?: string;\n format?: OutputFormat;\n gitDependencies?: GitDependencies;\n onWarning?: SpecProductDirWarningHandler;\n source?: SpecTreeSource;\n}\n\n// The read path takes no resolver; the --update path requires one. Modeling the\n// co-dependency as a discriminated union makes `update: true` without a resolver a\n// compile-time error rather than a runtime throw.\ninterface StatusReadOptions extends StatusBaseOptions {\n update?: false;\n resolveOutcomeFor?: undefined;\n}\n\ninterface StatusUpdateOptions extends StatusBaseOptions {\n /** Refresh each node's spx.status.json before reporting the rollup. */\n update: true;\n /** Builds the per-node outcome resolver --update injects. */\n resolveOutcomeFor: (productDir: string) => NodeOutcomeResolver;\n}\n\nexport type StatusOptions = StatusReadOptions | StatusUpdateOptions;\n\nexport async function statusCommand(\n options: StatusOptions = {},\n): Promise<string> {\n if (options.source !== undefined) {\n // Injected sources are in-memory and carry no productDir, so the node-status\n // read-back provider — which resolves each spx.status.json under productDir —\n // cannot apply here; this path bypasses filesystem and git resolution and\n // derives state live.\n return renderSpecStatus(projectSpecTree(await readSpecTree({ source: options.source })), options.format);\n }\n\n const productDir = await resolveSpecProductDir(\n options.cwd ?? process.cwd(),\n options.gitDependencies,\n options.onWarning,\n );\n if (options.update === true) {\n // --update refreshes each node's spx.status.json before the read-back below, so\n // the reported rollup reflects the just-written state. The resolver is injected\n // at the command edge; this handler composes no language runner.\n await updateNodeStatus({ productDir, resolveOutcome: options.resolveOutcomeFor(productDir) });\n }\n // Read-back: a node's committed spx.status.json overrides live derivation; a node\n // with no status file yields undefined, routing the spec-tree library back to live\n // derivation.\n const snapshot = await readSpecTree({\n source: createFilesystemSpecTreeSource({ productDir }),\n evidence: createNodeStatusProvider(productDir),\n });\n return renderSpecStatus(projectSpecTree(snapshot), options.format);\n}\n\nexport function renderSpecStatus(\n projection: SpecTreeProjection,\n format: OutputFormat = DEFAULT_FORMAT,\n): string {\n if (projection.nodes.length === 0 && format !== OUTPUT_FORMAT.JSON) {\n return SPEC_STATUS_MESSAGE.EMPTY;\n }\n\n switch (format) {\n case OUTPUT_FORMAT.JSON:\n return formatJSON(projection);\n case OUTPUT_FORMAT.MARKDOWN:\n return formatMarkdown(projection);\n case OUTPUT_FORMAT.TABLE:\n return formatTable(projection);\n case OUTPUT_FORMAT.TEXT:\n return formatText(projection);\n default: {\n const unsupportedFormat: never = format;\n throw new RangeError(`Unsupported spec status output format: ${unsupportedFormat}`);\n }\n }\n}\n\nfunction formatJSON(projection: SpecTreeProjection): string {\n return JSON.stringify(projection, null, JSON_INDENTATION);\n}\n\nfunction formatText(projection: SpecTreeProjection): string {\n return projection.nodes.map((node) => formatTextNode(node)).join(\"\\n\");\n}\n\nfunction formatTextNode(node: SpecTreeProjectedNode, depth = 0): string {\n const current = `${NODE_INDENT.repeat(depth)}${formatNodeLabel(node)}`;\n const children = node.children.map((child) => formatTextNode(child, depth + 1));\n return [current, ...children].join(\"\\n\");\n}\n\nfunction formatMarkdown(projection: SpecTreeProjection): string {\n return projection.nodes.map((node) => formatMarkdownNode(node)).join(\"\\n\");\n}\n\nfunction formatMarkdownNode(node: SpecTreeProjectedNode, depth = 0): string {\n const current = `${NODE_INDENT.repeat(depth)}${MARKDOWN_NODE_PREFIX}${formatNodeLabel(node)}`;\n const children = node.children.map((child) => formatMarkdownNode(child, depth + 1));\n return [current, ...children].join(\"\\n\");\n}\n\nfunction formatTable(projection: SpecTreeProjection): string {\n const rows = flattenProjectionNodes(projection.nodes).map((node) => [\n KIND_REGISTRY[node.kind].label,\n node.id,\n node.state,\n ]);\n return [\n SPEC_STATUS_TABLE_HEADER,\n formatTableRow([TABLE_HEADER_SEPARATOR, TABLE_HEADER_SEPARATOR, TABLE_HEADER_SEPARATOR]),\n ...rows.map(formatTableRow),\n ].join(\"\\n\");\n}\n\nfunction flattenProjectionNodes(nodes: readonly SpecTreeProjectedNode[]): readonly SpecTreeProjectedNode[] {\n return nodes.flatMap((node) => [node, ...flattenProjectionNodes(node.children)]);\n}\n\nfunction formatTableRow(values: readonly string[]): string {\n return `${TABLE_SEPARATOR} ${values.join(` ${TABLE_SEPARATOR} `)} ${TABLE_SEPARATOR}`;\n}\n\nfunction formatNodeLabel(node: SpecTreeProjectedNode): string {\n return [\n KIND_REGISTRY[node.kind].label,\n node.id,\n `[${node.state}]`,\n ].join(STATUS_SEPARATOR);\n}\n","/**\n * Python test-runner descriptor.\n *\n * Declares pytest as the Python test runner: detection gating, the pytest\n * test-file pattern, pure exclusion-flag generation, and invocation through an\n * injected command runner. Composing descriptors into a registry and dispatching\n * the `spx test` command are separate, higher-level concerns.\n */\nimport { basename } from \"node:path\";\n\nimport type {\n TestingLanguageDescriptor,\n TestRunInvocation,\n TestRunnerDependencies,\n TestRunRequest,\n} from \"@/testing/languages/types\";\n\nconst PYTHON_TESTING_LANGUAGE_NAME = \"python\";\n\n/** pytest test-file basename shape: a `test_` prefix and a `.py` extension. */\nexport const PYTHON_TEST_FILE_PREFIX = \"test_\";\nconst PYTHON_TEST_FILE_EXTENSION = \".py\";\nconst PYTHON_TEST_FILE_PATTERNS = [`${PYTHON_TEST_FILE_PREFIX}*${PYTHON_TEST_FILE_EXTENSION}`] as const;\n\n/** pytest exclusion-flag format: an excluded node path maps to `--ignore=spx/{nodePath}/`. */\nexport const PYTHON_PYTEST_IGNORE_FLAG_PREFIX = \"--ignore=spx/\";\nexport const PYTHON_PYTEST_IGNORE_FLAG_SUFFIX = \"/\";\n\n// pytest runs through `uv run` so the project's managed Python environment provides the tool;\n// pytest takes its rootdir, configuration, and environment from the command runner's working directory.\nconst UV_COMMAND = \"uv\";\n// Exported so a provisioning harness can locate the `pytest` command token structurally rather than\n// hardcoding its position when it splices an ephemeral `--with pytest`.\nexport const PYTEST_INVOKE_ARGS = [\"run\", \"pytest\"] as const;\n\nfunction matchesTestFile(filePath: string): boolean {\n return basename(filePath).startsWith(PYTHON_TEST_FILE_PREFIX) && filePath.endsWith(PYTHON_TEST_FILE_EXTENSION);\n}\n\nfunction excludeFlag(nodePath: string): string {\n return `${PYTHON_PYTEST_IGNORE_FLAG_PREFIX}${nodePath}${PYTHON_PYTEST_IGNORE_FLAG_SUFFIX}`;\n}\n\nfunction detect(projectRoot: string, deps: Pick<TestRunnerDependencies, \"isLanguagePresent\">): boolean {\n return deps.isLanguagePresent(projectRoot);\n}\n\nasync function runTests(request: TestRunRequest, deps: TestRunnerDependencies): Promise<TestRunInvocation> {\n if (!deps.isLanguagePresent(request.projectRoot)) {\n return { invoked: false };\n }\n\n const args = [\n ...PYTEST_INVOKE_ARGS,\n ...request.testPaths,\n ...request.excludedNodePaths.map(excludeFlag),\n ];\n\n const result = await deps.runCommand(UV_COMMAND, args);\n return { invoked: true, exitCode: result.exitCode };\n}\n\nexport const pythonTestingLanguage: TestingLanguageDescriptor = {\n name: PYTHON_TESTING_LANGUAGE_NAME,\n testFilePatterns: PYTHON_TEST_FILE_PATTERNS,\n matchesTestFile,\n excludeFlag,\n detect,\n runTests,\n};\n","/**\n * TypeScript test-runner descriptor.\n *\n * Declares vitest as the TypeScript test runner: detection gating, the vitest\n * test-file patterns, pure exclusion-flag generation, and invocation through an\n * injected command runner. Composing descriptors into a registry and dispatching\n * the `spx test` command are separate, higher-level concerns.\n */\nimport type {\n TestingLanguageDescriptor,\n TestRunInvocation,\n TestRunnerDependencies,\n TestRunRequest,\n} from \"@/testing/languages/types\";\n\nconst TYPESCRIPT_TESTING_LANGUAGE_NAME = \"typescript\";\nconst TYPESCRIPT_TEST_FILE_PATTERNS = [\"*.test.ts\", \"*.test.tsx\"] as const;\nconst TYPESCRIPT_TEST_FILE_SUFFIXES = [\".test.ts\", \".test.tsx\"] as const;\n\n/** vitest exclusion-flag format: an excluded node path maps to `--exclude=spx/{nodePath}/**`. */\nexport const TYPESCRIPT_VITEST_EXCLUDE_FLAG_PREFIX = \"--exclude=spx/\";\nexport const TYPESCRIPT_VITEST_EXCLUDE_FLAG_SUFFIX = \"/**\";\n\n// vitest runs through the project's package manager so the project's node_modules\n// provides the binary; `--root` makes the project under test explicit.\nconst PACKAGE_MANAGER_COMMAND = \"pnpm\";\nconst VITEST_INVOKE_ARGS = [\"exec\", \"vitest\", \"run\"] as const;\nconst VITEST_ROOT_FLAG = \"--root\";\n\nfunction matchesTestFile(filePath: string): boolean {\n return TYPESCRIPT_TEST_FILE_SUFFIXES.some((suffix) => filePath.endsWith(suffix));\n}\n\nfunction excludeFlag(nodePath: string): string {\n return `${TYPESCRIPT_VITEST_EXCLUDE_FLAG_PREFIX}${nodePath}${TYPESCRIPT_VITEST_EXCLUDE_FLAG_SUFFIX}`;\n}\n\nfunction detect(projectRoot: string, deps: Pick<TestRunnerDependencies, \"isLanguagePresent\">): boolean {\n return deps.isLanguagePresent(projectRoot);\n}\n\nasync function runTests(request: TestRunRequest, deps: TestRunnerDependencies): Promise<TestRunInvocation> {\n if (!deps.isLanguagePresent(request.projectRoot)) {\n return { invoked: false };\n }\n\n const args = [\n ...VITEST_INVOKE_ARGS,\n VITEST_ROOT_FLAG,\n request.projectRoot,\n ...request.testPaths,\n ...request.excludedNodePaths.map(excludeFlag),\n ];\n\n const result = await deps.runCommand(PACKAGE_MANAGER_COMMAND, args);\n return { invoked: true, exitCode: result.exitCode };\n}\n\nexport const typescriptTestingLanguage: TestingLanguageDescriptor = {\n name: TYPESCRIPT_TESTING_LANGUAGE_NAME,\n testFilePatterns: TYPESCRIPT_TEST_FILE_PATTERNS,\n matchesTestFile,\n excludeFlag,\n detect,\n runTests,\n};\n","/**\n * Testing language registry.\n *\n * Composes the `spx test` dispatch from explicitly imported language testing\n * descriptors. Orchestration iterates `testingRegistry.languages`; it never\n * references a language by name and never discovers descriptors through\n * filesystem scanning. Adding a language is one descriptor module plus one entry\n * here.\n */\nimport { pythonTestingLanguage } from \"@/testing/languages/python\";\nimport type { TestingLanguageDescriptor } from \"@/testing/languages/types\";\nimport { typescriptTestingLanguage } from \"@/testing/languages/typescript\";\n\nexport interface TestingRegistry {\n readonly languages: readonly TestingLanguageDescriptor[];\n}\n\nexport const testingRegistry: TestingRegistry = {\n languages: [typescriptTestingLanguage, pythonTestingLanguage],\n};\n","/**\n * Conventional exit codes for CLI termination paths.\n *\n * The mapping follows POSIX convention: 128 + signal number for\n * signal-terminated processes, 0 for downstream-closed pipes (matches\n * `head`/`tee` behavior under `SIGPIPE`), 1 for genuine internal failures.\n *\n * @module lib/process-lifecycle/exit-codes\n */\n\nexport const SIGINT_EXIT_CODE = 130;\nexport const SIGTERM_EXIT_CODE = 143;\nexport const EPIPE_EXIT_CODE = 0;\nexport const UNCAUGHT_EXIT_CODE = 1;\n","/**\n * Lifecycle handler factory. Produces the four handler entry points that\n * fire on SIGINT, SIGTERM, EPIPE, and uncaught exceptions.\n *\n * Each handler is idempotent: a `cleanupOnce` flag plus per-child\n * `child.killed` checks ensure that repeated invocations kill each\n * registered child exactly once. This handles the race in which SIGINT\n * arrives mid-write to a closed pipe.\n *\n * @module lib/process-lifecycle/handlers\n */\n\nimport { EPIPE_EXIT_CODE, SIGINT_EXIT_CODE, SIGTERM_EXIT_CODE, UNCAUGHT_EXIT_CODE } from \"./exit-codes\";\nimport type { ChildHandle, LifecycleHandlerDeps, LifecycleHandlers } from \"./types\";\n\nexport const SIGINT_NAME: NodeJS.Signals = \"SIGINT\";\nexport const SIGTERM_NAME: NodeJS.Signals = \"SIGTERM\";\n\nexport function createHandlers(deps: LifecycleHandlerDeps): LifecycleHandlers {\n let cleanupOnce = false;\n\n function killEachChild(signal: NodeJS.Signals): void {\n deps.registry.forEach((child: ChildHandle) => {\n if (!child.killed) child.kill(signal);\n });\n }\n\n function exitOnce(code: number, killSignal?: NodeJS.Signals): void {\n if (cleanupOnce) {\n deps.exitController.exit(code);\n return;\n }\n cleanupOnce = true;\n if (killSignal !== undefined) killEachChild(killSignal);\n deps.exitController.exit(code);\n }\n\n return {\n onSigint(): void {\n exitOnce(SIGINT_EXIT_CODE, SIGINT_NAME);\n },\n onSigterm(): void {\n exitOnce(SIGTERM_EXIT_CODE, SIGTERM_NAME);\n },\n onEpipe(): void {\n exitOnce(EPIPE_EXIT_CODE, SIGTERM_NAME);\n },\n onUncaught(_error: unknown): void {\n exitOnce(UNCAUGHT_EXIT_CODE, SIGTERM_NAME);\n },\n };\n}\n","/**\n * CLI process-lifecycle installation. Wires real Node process events to the\n * lifecycle handlers and exposes the production `lifecycleProcessRunner`\n * that the validation steps consume.\n *\n * The module-scoped registry holds child handles; `installLifecycle()`\n * attaches handlers once. Calling `installLifecycle()` more than once is a\n * no-op so re-entry from accidental imports does not double-install.\n *\n * @module lib/process-lifecycle/install\n */\n\nimport { spawn } from \"node:child_process\";\n\nimport { createHandlers } from \"./handlers\";\nimport { createRegistry } from \"./registry\";\nimport { createLifecycleRunner } from \"./runner\";\nimport type { ChildRegistry, ExitController, LifecycleHandlers } from \"./types\";\n\nconst moduleRegistry: ChildRegistry = createRegistry();\nconst moduleExitController: ExitController = {\n exit(code: number): void {\n process.exit(code);\n },\n};\n\nlet installed = false;\n\nexport const lifecycleProcessRunner = createLifecycleRunner({\n registry: moduleRegistry,\n spawn,\n});\n\nexport const EPIPE_CODE = \"EPIPE\";\nexport const UNCAUGHT_EVENT_NAME = \"uncaughtException\";\nconst UNCAUGHT_PREFIX = \"Uncaught: \";\nconst NEWLINE = \"\\n\";\n\nfunction formatUncaught(error: unknown): string {\n if (error instanceof Error && error.stack !== undefined) {\n return UNCAUGHT_PREFIX + error.stack + NEWLINE;\n }\n return UNCAUGHT_PREFIX + String(error) + NEWLINE;\n}\n\nfunction logUncaughtToStderr(error: unknown): void {\n // Best-effort diagnostic write before the process exits. If stderr is\n // already closed, the write throws synchronously and we swallow it; the\n // exit path runs regardless so the operator at minimum sees a non-zero\n // exit code.\n try {\n process.stderr.write(formatUncaught(error));\n } catch {\n /* stderr unavailable; rely on exit code */\n }\n}\n\nexport function installLifecycle(): void {\n if (installed) return;\n installed = true;\n\n const handlers: LifecycleHandlers = createHandlers({\n registry: moduleRegistry,\n exitController: moduleExitController,\n });\n\n process.on(\"uncaughtException\", (error: unknown) => {\n logUncaughtToStderr(error);\n handlers.onUncaught(error);\n });\n process.on(\"unhandledRejection\", (reason: unknown) => {\n logUncaughtToStderr(reason);\n handlers.onUncaught(reason);\n });\n process.on(\"SIGTERM\", () => handlers.onSigterm());\n process.on(\"SIGINT\", () => handlers.onSigint());\n\n process.stdout.on(\"error\", (error: NodeJS.ErrnoException) => {\n if (error.code === EPIPE_CODE) {\n handlers.onEpipe();\n return;\n }\n handlers.onUncaught(error);\n });\n process.stderr.on(\"error\", (error: NodeJS.ErrnoException) => {\n if (error.code === EPIPE_CODE) {\n handlers.onEpipe();\n return;\n }\n handlers.onUncaught(error);\n });\n}\n","/**\n * Child-process registry. Tracks asynchronously spawned children so that\n * lifecycle handlers can reach them when the parent receives a termination\n * signal.\n *\n * The registry is identity-based: callers pass the `ChildHandle` reference\n * returned by `spawn` to both `add` and `remove`.\n *\n * @module lib/process-lifecycle/registry\n */\n\nimport type { ChildHandle, ChildRegistry } from \"./types\";\n\nexport function createRegistry(): ChildRegistry {\n const tracked = new Set<ChildHandle>();\n\n return {\n add(child: ChildHandle): void {\n tracked.add(child);\n },\n remove(child: ChildHandle): void {\n tracked.delete(child);\n },\n forEach(fn: (child: ChildHandle) => void): void {\n for (const child of tracked) fn(child);\n },\n get size(): number {\n return tracked.size;\n },\n };\n}\n","/**\n * Lifecycle-aware process runner. Wraps a real `spawn` function so that\n * every child handle returned by `runner.spawn(...)` is registered in the\n * lifecycle registry and removed when the child exits.\n *\n * @module lib/process-lifecycle/runner\n */\n\nimport type { ChildRegistry, ProcessRunner } from \"./types\";\n\nexport interface LifecycleRunnerDeps {\n readonly registry: ChildRegistry;\n readonly spawn: ProcessRunner[\"spawn\"];\n}\n\nexport type LifecycleSpawn = LifecycleRunnerDeps[\"spawn\"];\n\nexport function createLifecycleRunner(deps: LifecycleRunnerDeps): ProcessRunner {\n return {\n spawn(command, args, options) {\n const child = deps.spawn(command, args, options);\n deps.registry.add(child);\n child.on(\"exit\", () => deps.registry.remove(child));\n return child;\n },\n };\n}\n","import type { ChildProcess, SpawnOptions } from \"node:child_process\";\n\nimport type { ProcessRunner } from \"./types\";\n\nexport const MANAGED_SUBPROCESS_STDIO = \"pipe\";\n\nexport type ManagedSubprocessSpawnOptions = Omit<SpawnOptions, \"stdio\"> & {\n readonly stdio?: never;\n};\n\nexport function spawnManagedSubprocess(\n runner: ProcessRunner,\n command: string,\n args: readonly string[],\n options: ManagedSubprocessSpawnOptions,\n): ChildProcess {\n return runner.spawn(command, args, {\n ...options,\n stdio: MANAGED_SUBPROCESS_STDIO,\n });\n}\n","/**\n * Language detection for validation infrastructure.\n *\n * Detects which programming languages a project uses based on configuration\n * file presence. Language-specific validation tools (ESLint, tsc, mypy) consult\n * detection results to determine whether to run.\n *\n * @module validation/discovery/language-finder\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\n// =============================================================================\n// CONSTANTS\n// =============================================================================\n\n/**\n * Marker file for TypeScript projects, checked in the project root.\n */\nexport const TYPESCRIPT_MARKER = \"tsconfig.json\";\n\n/**\n * Marker file for Python projects, checked in the project root.\n */\nexport const PYTHON_MARKER = \"pyproject.toml\";\n\n/**\n * ESLint flat config file names, in priority order.\n *\n * ESLint 9+ uses flat config exclusively. When multiple config files exist in\n * the same directory, the highest-priority one wins.\n */\nexport const ESLINT_CONFIG_FILES = [\n \"eslint.config.ts\",\n \"eslint.config.js\",\n \"eslint.config.mjs\",\n \"eslint.config.cjs\",\n] as const;\nexport const ESLINT_PRODUCTION_CONFIG_FILES = [\n \"eslint.config.production.ts\",\n \"eslint.config.production.js\",\n \"eslint.config.production.mjs\",\n \"eslint.config.production.cjs\",\n] as const;\n\n/**\n * Type of an ESLint config file name.\n */\nexport type EslintConfigFile = (typeof ESLINT_CONFIG_FILES)[number];\nexport type EslintProductionConfigFile = (typeof ESLINT_PRODUCTION_CONFIG_FILES)[number];\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\n/**\n * Result of TypeScript language detection.\n */\nexport interface TypeScriptDetection {\n /** Whether TypeScript is present in the project. */\n present: boolean;\n /** The ESLint flat config file name found, if any. Only set when `present` is true. */\n eslintConfigFile?: EslintConfigFile;\n /** Production-scope ESLint flat config file name found, if any. Only set when `present` is true. */\n productionEslintConfigFile?: EslintProductionConfigFile;\n}\n\n/**\n * Result of Python language detection.\n */\nexport interface PythonDetection {\n /** Whether Python is present in the project. */\n present: boolean;\n}\n\n/**\n * Result of full language detection.\n */\nexport interface LanguageDetection {\n typescript: TypeScriptDetection;\n python: PythonDetection;\n}\n\n/**\n * Dependencies for language detection.\n *\n * Enables type-safe dependency injection for testing without mocking.\n */\nexport interface LanguageDetectionDeps {\n /**\n * Check whether a file exists at the given absolute path.\n * @param filePath - Absolute path to check.\n */\n existsSync: (filePath: string) => boolean;\n}\n\n/**\n * Default production dependencies.\n */\nexport const defaultLanguageDetectionDeps: LanguageDetectionDeps = {\n existsSync: fs.existsSync,\n};\n\n// =============================================================================\n// DETECTION FUNCTIONS\n// =============================================================================\n\n/**\n * Detect whether a project uses TypeScript.\n *\n * TypeScript is present when `tsconfig.json` exists in the project root. When\n * present, the function also searches for an ESLint flat config file and\n * returns its name in priority order.\n *\n * @param projectRoot - Absolute path to the project root.\n * @param deps - Injectable filesystem dependencies.\n * @returns Detection result with presence flag and optional ESLint config path.\n */\nexport function detectTypeScript(\n projectRoot: string,\n deps: LanguageDetectionDeps = defaultLanguageDetectionDeps,\n): TypeScriptDetection {\n const present = deps.existsSync(path.join(projectRoot, TYPESCRIPT_MARKER));\n\n if (!present) {\n return { present: false };\n }\n\n const eslintConfigFile = ESLINT_CONFIG_FILES.find((configFile) =>\n deps.existsSync(path.join(projectRoot, configFile))\n );\n const productionEslintConfigFile = ESLINT_PRODUCTION_CONFIG_FILES.find((configFile) =>\n deps.existsSync(path.join(projectRoot, configFile))\n );\n\n return { present: true, eslintConfigFile, productionEslintConfigFile };\n}\n\n/**\n * Detect whether a project uses Python.\n *\n * Python is present when `pyproject.toml` exists in the project root.\n *\n * @param projectRoot - Absolute path to the project root.\n * @param deps - Injectable filesystem dependencies.\n * @returns Detection result with presence flag.\n */\nexport function detectPython(\n projectRoot: string,\n deps: LanguageDetectionDeps = defaultLanguageDetectionDeps,\n): PythonDetection {\n const present = deps.existsSync(path.join(projectRoot, PYTHON_MARKER));\n return { present };\n}\n\n/**\n * Detect all supported languages in a project.\n *\n * @param projectRoot - Absolute path to the project root.\n * @param deps - Injectable filesystem dependencies.\n * @returns Detection result for every supported language.\n */\nexport function detectLanguages(\n projectRoot: string,\n deps: LanguageDetectionDeps = defaultLanguageDetectionDeps,\n): LanguageDetection {\n return {\n typescript: detectTypeScript(projectRoot, deps),\n python: detectPython(projectRoot, deps),\n };\n}\n","import type { ChildProcess } from \"node:child_process\";\n\nimport { lifecycleProcessRunner, spawnManagedSubprocess } from \"@/lib/process-lifecycle\";\nimport { pythonTestingLanguage } from \"@/testing/languages/python\";\nimport type {\n TestingLanguageDescriptor,\n TestRunCommandResult,\n TestRunnerDependencies,\n} from \"@/testing/languages/types\";\nimport { typescriptTestingLanguage } from \"@/testing/languages/typescript\";\nimport { detectPython, detectTypeScript } from \"@/validation/discovery/language-finder\";\n\nexport const PROCESS_FAILURE_EXIT_CODE = 1;\nconst NO_PRESENCE_DETECTOR_ERROR = \"no presence detector configured for testing language\";\n\n// Each registered language's presence check, keyed by descriptor name. The\n// descriptor delegates detection to an agnostic `isLanguagePresent`, so the\n// composition root supplies the concrete per-language check here.\nconst PRESENCE_BY_LANGUAGE_NAME: Record<string, (productDir: string) => boolean> = {\n [typescriptTestingLanguage.name]: (productDir) => detectTypeScript(productDir).present,\n [pythonTestingLanguage.name]: (productDir) => detectPython(productDir).present,\n};\n\n// Spawns a managed child through the lifecycle runner, forwards its stdout to the\n// caller-chosen stream and its stderr to the CLI's error stream, and resolves with\n// the child's terminal exit code. The stdout stream is a parameter because `spx test`\n// wants the run's output on stdout while `spx spec status --update` must keep stdout\n// for the status rollup and route per-node output to stderr.\nfunction createCommandRunner(\n productDir: string,\n outStream: NodeJS.WritableStream,\n): TestRunnerDependencies[\"runCommand\"] {\n return (command, args) =>\n new Promise<TestRunCommandResult>((resolveResult) => {\n const child: ChildProcess = spawnManagedSubprocess(lifecycleProcessRunner, command, args, {\n cwd: productDir,\n });\n child.stdout?.pipe(outStream);\n child.stderr?.pipe(process.stderr);\n child.on(\"close\", (code) => resolveResult({ exitCode: code ?? PROCESS_FAILURE_EXIT_CODE }));\n child.on(\"error\", () => resolveResult({ exitCode: PROCESS_FAILURE_EXIT_CODE }));\n });\n}\n\n/**\n * Builds the per-language runner dependencies the `spx test` run and the\n * `spx spec status --update` outcome resolver both compose: presence detection\n * keyed by descriptor name plus a command runner scoped to the product directory.\n * Both CLI descriptors share this one composition so the presence map never drifts.\n * `outStream` receives each child's stdout — `spx test` keeps the default\n * `process.stdout`, while `spx spec status --update` passes `process.stderr` so the\n * status rollup (text or `--json`) is the only thing written to stdout.\n */\nexport function createRunnerDepsFor(\n productDir: string,\n outStream: NodeJS.WritableStream = process.stdout,\n): (language: TestingLanguageDescriptor) => TestRunnerDependencies {\n const runCommand = createCommandRunner(productDir, outStream);\n return (language) => {\n const isLanguagePresent = PRESENCE_BY_LANGUAGE_NAME[language.name];\n if (isLanguagePresent === undefined) {\n throw new Error(`${NO_PRESENCE_DETECTOR_ERROR}: ${language.name}`);\n }\n return { isLanguagePresent, runCommand };\n };\n}\n","import type { Command } from \"commander\";\n\nimport { nextCommand } from \"@/commands/spec/next\";\nimport { createNodeOutcomeResolver } from \"@/commands/spec/node-outcome-resolver\";\nimport { OUTPUT_FORMAT, type OutputFormat, statusCommand } from \"@/commands/spec/status\";\nimport type { Domain } from \"@/domains/types\";\nimport { testingRegistry } from \"@/testing/registry\";\n\nimport { createRunnerDepsFor } from \"./testing-runner-deps\";\nimport { writeWarning } from \"./write-warning\";\n\nexport const SPEC_DOMAIN_CLI = {\n COMMAND: \"spec\",\n STATUS_COMMAND: \"status\",\n NEXT_COMMAND: \"next\",\n JSON_OPTION: \"--json\",\n FORMAT_OPTION_FLAG: \"--format\",\n FORMAT_OPTION_DEFINITION: \"--format <format>\",\n UPDATE_OPTION: \"--update\",\n} as const;\n\nexport const SPEC_STATUS_FORMAT_MESSAGE = {\n INVALID_PREFIX: \"Invalid format\",\n} as const;\n\nconst VALID_STATUS_FORMATS: readonly OutputFormat[] = [\n OUTPUT_FORMAT.TEXT,\n OUTPUT_FORMAT.JSON,\n OUTPUT_FORMAT.MARKDOWN,\n OUTPUT_FORMAT.TABLE,\n];\n\nfunction handleCommandError(error: unknown): never {\n console.error(\"Error:\", error instanceof Error ? error.message : String(error));\n process.exit(1);\n}\n\nfunction resolveStatusFormat(options: { json?: boolean; format?: string }): OutputFormat {\n if (options.json === true) {\n return \"json\";\n }\n\n if (options.format === undefined) {\n return \"text\";\n }\n\n if (VALID_STATUS_FORMATS.includes(options.format as OutputFormat)) {\n return options.format as OutputFormat;\n }\n\n throw new Error(\n `${SPEC_STATUS_FORMAT_MESSAGE.INVALID_PREFIX} \"${options.format}\". Must be one of: ${\n VALID_STATUS_FORMATS.join(\", \")\n }`,\n );\n}\n\nfunction registerSpecCommands(specCmd: Command): void {\n specCmd\n .command(SPEC_DOMAIN_CLI.STATUS_COMMAND)\n .description(\"Get product status\")\n .option(SPEC_DOMAIN_CLI.JSON_OPTION, \"Output as JSON\")\n .option(SPEC_DOMAIN_CLI.FORMAT_OPTION_DEFINITION, \"Output format (text|json|markdown|table)\")\n .option(SPEC_DOMAIN_CLI.UPDATE_OPTION, \"Refresh each node's spx.status.json before reporting\")\n .action(async (options: { json?: boolean; format?: string; update?: boolean }) => {\n try {\n const format = resolveStatusFormat(options);\n // The per-node runner pipes child stdout to process.stderr here so stdout\n // carries only the status rollup; a --json rollup therefore stays parseable\n // even when --update runs a node's tests for stale, failing, or absent evidence.\n const output = options.update === true\n ? await statusCommand({\n cwd: process.cwd(),\n format,\n onWarning: writeWarning,\n update: true,\n resolveOutcomeFor: (productDir) =>\n createNodeOutcomeResolver({\n productDir,\n registry: testingRegistry,\n runnerDepsFor: createRunnerDepsFor(productDir, process.stderr),\n }),\n })\n : await statusCommand({ cwd: process.cwd(), format, onWarning: writeWarning });\n console.log(output);\n } catch (error) {\n handleCommandError(error);\n }\n });\n\n specCmd\n .command(SPEC_DOMAIN_CLI.NEXT_COMMAND)\n .description(\"Find next spec-tree node to work on\")\n .action(async () => {\n try {\n const output = await nextCommand({ cwd: process.cwd(), onWarning: writeWarning });\n console.log(output);\n } catch (error) {\n handleCommandError(error);\n }\n });\n}\n\nexport const specDomain: Domain = {\n name: \"spec\",\n description: \"Manage spec workflow\",\n register: (program: Command) => {\n const specCmd = program\n .command(SPEC_DOMAIN_CLI.COMMAND)\n .description(\"Manage spec workflow\");\n\n registerSpecCommands(specCmd);\n },\n};\n","import type { Command } from \"commander\";\n\nimport { runTestsCommand, type TestDispatchResult } from \"@/commands/testing\";\nimport type { Domain } from \"@/domains/types\";\nimport { detectWorktreeProductRoot } from \"@/git/root\";\nimport { writeWarning } from \"@/interfaces/cli/write-warning\";\nimport { SPEC_TREE_CONFIG } from \"@/lib/spec-tree/config\";\nimport { testingRegistry } from \"@/testing/registry\";\n\nimport { createRunnerDepsFor, PROCESS_FAILURE_EXIT_CODE } from \"./testing-runner-deps\";\n\nconst TESTING_CLI = {\n commandName: \"test\",\n description: \"Run spec-tree tests across product languages\",\n passingSubcommand: \"passing\",\n passingDescription: \"Run only the tests within the configured passing scope\",\n} as const;\n\nconst UNMATCHED_TEST_FILES_WARNING = \"Skipped test files with no registered runner\";\n\nconst TESTING_PRODUCT_DIR_WARNING = {\n NOT_GIT_REPOSITORY:\n `Warning: Not in a git repository. Reading ${SPEC_TREE_CONFIG.ROOT_DIRECTORY} tests relative to the current working directory.`,\n} as const;\n\nasync function resolveTestProductDir(): Promise<string> {\n const { productDir, isGitRepo } = await detectWorktreeProductRoot(process.cwd());\n writeWarning(isGitRepo ? undefined : TESTING_PRODUCT_DIR_WARNING.NOT_GIT_REPOSITORY);\n return productDir;\n}\n\n// Runs the testing command, surfacing its dispatch result; a config or recording\n// failure exits here, where the descriptor owns the process boundary.\nasync function runTestsThroughCommand(productDir: string, passing: boolean): Promise<TestDispatchResult> {\n try {\n const result = await runTestsCommand(\n { productDir, passing },\n { registry: testingRegistry, runnerDepsFor: createRunnerDepsFor(productDir) },\n );\n return result.dispatch;\n } catch (error) {\n process.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n`);\n process.exit(PROCESS_FAILURE_EXIT_CODE);\n }\n}\n\nfunction reportAndExit(result: TestDispatchResult): never {\n if (result.unmatched.length > 0) {\n writeWarning(`${UNMATCHED_TEST_FILES_WARNING}:\\n${result.unmatched.join(\"\\n\")}`);\n }\n process.exit(result.exitCode);\n}\n\nexport const testingDomain: Domain = {\n name: TESTING_CLI.commandName,\n description: TESTING_CLI.description,\n register: (program: Command) => {\n const testCmd = program.command(TESTING_CLI.commandName).description(TESTING_CLI.description);\n\n testCmd.action(async () => {\n const productDir = await resolveTestProductDir();\n reportAndExit(await runTestsThroughCommand(productDir, false));\n });\n\n testCmd\n .command(TESTING_CLI.passingSubcommand)\n .description(TESTING_CLI.passingDescription)\n .action(async () => {\n const productDir = await resolveTestProductDir();\n reportAndExit(await runTestsThroughCommand(productDir, true));\n });\n },\n};\n","/**\n * Markdown validation command.\n *\n * Runs markdownlint-cli2 for markdown link integrity and structural quality.\n * Unlike other validation commands, this does not use discoverTool() --\n * markdownlint-cli2 is a production dependency, always available.\n */\n\nimport { relative } from \"node:path\";\n\nimport { resolveConfig } from \"@/config/index\";\nimport {\n VALIDATION_PATH_TOOL_SUBSECTIONS,\n type ValidationConfig,\n validationConfigDescriptor,\n} from \"@/validation/config/descriptor\";\nimport { pathPassesValidationFilter, validationPathFilterForTool } from \"@/validation/config/path-filter\";\nimport {\n getDefaultDirectories,\n MARKDOWN_VALIDATION_TARGET_KIND,\n type MarkdownSkippedValidationTarget,\n type MarkdownValidationTarget,\n resolveMarkdownValidationTarget,\n validateMarkdown,\n} from \"@/validation/steps/markdown\";\nimport { VALIDATION_COMMAND_OUTPUT, VALIDATION_SKIP_LABELS, VALIDATION_STAGE_DISPLAY_NAMES } from \"./messages\";\nimport type { MarkdownCommandOptions, ValidationCommandResult } from \"./types\";\n\n/**\n * Run markdown validation.\n *\n * Validates markdown files in the specified directories (or defaults to\n * spx/ and docs/). Returns structured results with exit code and output.\n *\n * @param options - Command options including cwd and optional file scoping\n * @returns Command result with exit code and output\n *\n * @example\n * ```typescript\n * // Validate default directories\n * const result = await markdownCommand({ cwd: process.cwd() });\n *\n * // Validate specific directories\n * const result = await markdownCommand({\n * cwd: process.cwd(),\n * files: [\"/path/to/spx\"],\n * });\n * ```\n */\nexport const MARKDOWN_COMMAND_OUTPUT = {\n ERROR_SUMMARY_SUFFIX: VALIDATION_COMMAND_OUTPUT.MARKDOWN_ERROR_SUMMARY_SUFFIX,\n NO_ISSUES: VALIDATION_COMMAND_OUTPUT.MARKDOWN_NO_ISSUES,\n SKIPPED_FILE_SCOPE_PREFIX: \"Markdown skipped file scope\",\n} as const;\nconst MARKDOWN_CONFIG_ERROR_MESSAGE = `${VALIDATION_STAGE_DISPLAY_NAMES.MARKDOWN}: ✗ config error`;\n\nexport async function markdownCommand(options: MarkdownCommandOptions): Promise<ValidationCommandResult> {\n const { cwd, files, quiet } = options;\n const startTime = Date.now();\n const loaded = await resolveConfig(cwd, [validationConfigDescriptor]);\n if (!loaded.ok) {\n return {\n exitCode: 1,\n output: `${MARKDOWN_CONFIG_ERROR_MESSAGE} — ${loaded.error}`,\n durationMs: Date.now() - startTime,\n };\n }\n const validationConfig = loaded.value[validationConfigDescriptor.section] as ValidationConfig;\n const pathFilter = validationPathFilterForTool(\n validationConfig.paths,\n VALIDATION_PATH_TOOL_SUBSECTIONS.MARKDOWN,\n );\n\n const targetResolutions = files && files.length > 0\n ? files.map((filePath) => resolveMarkdownValidationTarget(filePath))\n : undefined;\n const unfilteredTargets = targetResolutions !== undefined\n ? targetResolutions\n .map((resolution) => resolution.target)\n .filter((target): target is MarkdownValidationTarget => target !== undefined)\n : getDefaultDirectories(cwd).map((path) => ({\n kind: MARKDOWN_VALIDATION_TARGET_KIND.DIRECTORY,\n path,\n }));\n const targets = unfilteredTargets.filter((target) =>\n pathPassesValidationFilter(relative(cwd, target.path), pathFilter)\n );\n const skippedTargets = targetResolutions === undefined\n ? []\n : targetResolutions\n .map((resolution) => resolution.skipped)\n .filter((skipped): skipped is MarkdownSkippedValidationTarget => skipped !== undefined);\n const skippedOutput = quiet ? [] : skippedTargets.map(formatSkippedFileScope);\n\n if (targets.length === 0) {\n const reason = files && files.length > 0\n ? VALIDATION_SKIP_LABELS.MARKDOWN_NO_SCOPE_REASON\n : VALIDATION_SKIP_LABELS.MARKDOWN_NO_DEFAULT_DIRECTORIES_REASON;\n const output = quiet ? \"\" : [\n ...skippedOutput,\n `${VALIDATION_STAGE_DISPLAY_NAMES.MARKDOWN}: skipped (${reason})`,\n ].join(\"\\n\");\n return { exitCode: 0, output, durationMs: Date.now() - startTime };\n }\n\n // Run markdown validation\n const result = await validateMarkdown({\n targets,\n projectRoot: cwd,\n });\n const durationMs = Date.now() - startTime;\n\n // Map result to command output\n if (result.success) {\n const output = quiet ? \"\" : [...skippedOutput, MARKDOWN_COMMAND_OUTPUT.NO_ISSUES].join(\"\\n\");\n return { exitCode: 0, output, durationMs };\n } else {\n const errorLines = result.errors.map(\n (error) => ` ${error.file}:${error.line} ${error.detail}`,\n );\n const output = [\n ...skippedOutput,\n `Markdown: ${result.errors.length} ${MARKDOWN_COMMAND_OUTPUT.ERROR_SUMMARY_SUFFIX}`,\n ...errorLines,\n ]\n .join(\"\\n\");\n return { exitCode: 1, output, durationMs };\n }\n}\n\nfunction formatSkippedFileScope(target: MarkdownSkippedValidationTarget): string {\n return `${MARKDOWN_COMMAND_OUTPUT.SKIPPED_FILE_SCOPE_PREFIX}: ${target.path} (${target.reason})`;\n}\n","import { isAbsolute, relative } from \"node:path\";\n\nimport {\n type ValidationPathConfig,\n type ValidationPathFilterConfig,\n type ValidationPathToolSubsection,\n} from \"@/validation/config/descriptor\";\nimport type { ScopeConfig } from \"@/validation/types\";\n\nconst PATH_PREFIX_SEPARATOR = \"/\";\n\ninterface ValidationPathIncludeIntersection {\n readonly include?: readonly string[];\n readonly hasIncludeFilter: boolean;\n readonly noMatches: boolean;\n}\n\ntype EffectiveValidationPathFilterConfig = ValidationPathFilterConfig & {\n readonly hasIncludeFilter: boolean;\n readonly noMatchingIncludes: boolean;\n};\n\nfunction hasEffectiveValidationPathMetadata(\n filter: ValidationPathFilterConfig,\n): filter is EffectiveValidationPathFilterConfig {\n return \"hasIncludeFilter\" in filter\n && typeof filter.hasIncludeFilter === \"boolean\"\n && \"noMatchingIncludes\" in filter\n && typeof filter.noMatchingIncludes === \"boolean\";\n}\n\nfunction normalizePathPrefix(prefix: string): string {\n return prefix\n .split(/[\\\\/]/g)\n .join(PATH_PREFIX_SEPARATOR)\n .replace(/^\\.\\//, \"\")\n .replace(/\\/+$/, \"\");\n}\n\nfunction pathMatchesPrefix(path: string, prefix: string): boolean {\n const normalizedPath = normalizePathPrefix(path);\n const normalizedPrefix = normalizePathPrefix(prefix);\n return normalizedPath === normalizedPrefix\n || normalizedPath.startsWith(`${normalizedPrefix}${PATH_PREFIX_SEPARATOR}`);\n}\n\nfunction unique(values: readonly string[]): string[] {\n return [...new Set(values)];\n}\n\nfunction nonEmpty(values: readonly string[] | undefined): readonly string[] {\n return values?.filter((value) => value.length > 0) ?? [];\n}\n\nexport function toProjectRelativeValidationPath(projectRoot: string, path: string): string {\n return isAbsolute(path) ? relative(projectRoot, path) : path;\n}\n\nfunction intersectIncludes(\n baseInclude: readonly string[] | undefined,\n toolInclude: readonly string[] | undefined,\n): ValidationPathIncludeIntersection {\n const base = nonEmpty(baseInclude);\n const tool = nonEmpty(toolInclude);\n if (base.length === 0 && tool.length === 0) {\n return { hasIncludeFilter: false, noMatches: false };\n }\n if (base.length === 0) return { include: tool, hasIncludeFilter: true, noMatches: false };\n if (tool.length === 0) return { include: base, hasIncludeFilter: true, noMatches: false };\n\n const intersections = base.flatMap((basePrefix) =>\n tool.flatMap((toolPrefix) => {\n if (pathMatchesPrefix(basePrefix, toolPrefix)) return [basePrefix];\n if (pathMatchesPrefix(toolPrefix, basePrefix)) return [toolPrefix];\n return [];\n })\n );\n\n if (intersections.length === 0) {\n return { include: [], hasIncludeFilter: true, noMatches: true };\n }\n\n return { include: unique(intersections), hasIncludeFilter: true, noMatches: false };\n}\n\nexport function validationPathFilterForTool(\n paths: ValidationPathConfig,\n tool: ValidationPathToolSubsection,\n): EffectiveValidationPathFilterConfig {\n const toolConfig = paths[tool];\n const includeIntersection = intersectIncludes(paths.include, toolConfig?.include);\n return {\n include: includeIntersection.include,\n exclude: unique([...nonEmpty(paths.exclude), ...nonEmpty(toolConfig?.exclude)]),\n hasIncludeFilter: includeIntersection.hasIncludeFilter,\n noMatchingIncludes: includeIntersection.noMatches,\n };\n}\n\nexport function hasValidationPathFilter(filter: ValidationPathFilterConfig): boolean {\n return hasEffectiveValidationPathMetadata(filter) && filter.noMatchingIncludes\n || nonEmpty(filter.include).length > 0\n || nonEmpty(filter.exclude).length > 0;\n}\n\nexport function pathPassesValidationFilter(path: string, filter: ValidationPathFilterConfig): boolean {\n if (hasEffectiveValidationPathMetadata(filter) && filter.noMatchingIncludes) {\n return false;\n }\n const include = nonEmpty(filter.include);\n const exclude = nonEmpty(filter.exclude);\n if (include.length > 0 && !include.some((prefix) => pathMatchesPrefix(path, prefix))) {\n return false;\n }\n return !exclude.some((prefix) => pathMatchesPrefix(path, prefix));\n}\n\nexport function applyValidationPathFilterToScope(\n scopeConfig: ScopeConfig,\n filter: ValidationPathFilterConfig,\n): ScopeConfig {\n if (!hasValidationPathFilter(filter)) {\n return scopeConfig;\n }\n\n const includeFallbacks = nonEmpty(filter.include);\n const hasEffectiveMetadata = hasEffectiveValidationPathMetadata(filter);\n const hasIncludeFilter = hasEffectiveMetadata ? filter.hasIncludeFilter : includeFallbacks.length > 0;\n const scopedDirectories = scopeConfig.directories.filter((directory) =>\n pathPassesValidationFilter(directory, filter)\n );\n const scopedFilePatterns = scopeConfig.filePatterns.filter((pattern) => pathPassesValidationFilter(pattern, filter));\n const includeFallbacksWithinScope = includeFallbacks.filter((include) =>\n scopeConfig.directories.some((directory) => pathMatchesPrefix(include, directory))\n );\n const noMatchingIncludes = (hasEffectiveMetadata && filter.noMatchingIncludes)\n || (hasIncludeFilter && scopedDirectories.length === 0 && scopedFilePatterns.length === 0\n && includeFallbacksWithinScope.length === 0);\n const directories = noMatchingIncludes\n ? []\n : scopedDirectories.length > 0\n ? scopedDirectories\n : includeFallbacksWithinScope;\n const filePatterns = scopedFilePatterns.length > 0 ? scopedFilePatterns : [...directories];\n\n return {\n ...scopeConfig,\n directories,\n filePatterns,\n excludePatterns: unique([...scopeConfig.excludePatterns, ...nonEmpty(filter.exclude)]),\n filteredByValidationPaths: true,\n filteredByValidationPathIncludes: hasIncludeFilter,\n filteredByValidationPathNoMatches: noMatchingIncludes,\n };\n}\n","/**\n * Markdown validation step.\n *\n * Validates markdown files using markdownlint-cli2's programmatic API.\n * Configuration is built in code and passed via optionsOverride --\n * no config files are written to validated directories.\n *\n * @module validation/steps/markdown\n */\n\nimport { existsSync, statSync } from \"node:fs\";\nimport { basename, dirname, join, relative as pathRelative } from \"node:path\";\n\nimport { createIgnoreSourceReader, IGNORE_SOURCE_FILENAME_DEFAULT } from \"@/lib/file-inclusion/ignore-source\";\nimport { SPEC_TREE_CONFIG } from \"@/lib/spec-tree/config\";\n\n// @ts-expect-error markdownlint-cli2 has no TypeScript type declarations\nimport { main as markdownlintMain } from \"markdownlint-cli2\";\nimport relativeLinksRule from \"markdownlint-rule-relative-links\";\n\n// =============================================================================\n// CONSTANTS\n// =============================================================================\n\n/** Default directories to validate when no --files are specified. */\nexport const MARKDOWN_DEFAULT_DIRECTORY_NAMES = [\"spx\", \"docs\"] as const;\nexport const MARKDOWN_PRIMARY_FILE_EXTENSION = \".md\";\nconst MARKDOWN_FILE_EXTENSIONS: ReadonlySet<string> = new Set([\".md\", \".markdown\"]);\nexport const MARKDOWN_DIRECTORY_GLOB = \"**/*.md\";\n\n/** Built-in markdownlint rules enabled for validation (MD024 excluded — configured per directory). */\nconst ENABLED_RULES = {\n MD001: true,\n MD003: true,\n MD009: true,\n MD010: true,\n MD025: true,\n MD047: true,\n} as const;\n\n/** Directories where MD024 is disabled entirely (generated/repetitive headings are normal). */\nconst MD024_DISABLED_DIRECTORIES = [\"docs\"] as const;\n\nexport const MARKDOWN_CUSTOM_RULE_NAMES = relativeLinksRule.names;\nexport const MARKDOWN_VALIDATION_TARGET_KIND = {\n DIRECTORY: \"directory\",\n FILE: \"file\",\n} as const;\n\nexport const MARKDOWN_VALIDATION_TARGET_DIAGNOSTICS = {\n MISSING_OR_UNRELATED_SCOPE: \"not an existing directory or markdown file\",\n} as const;\n\n/**\n * Pattern for parsing markdownlint-cli2 default formatter output.\n * Format: filename:line[:column] [severity] ruleName/ruleAlias description [detail] [context]\n */\nconst ERROR_LINE_PATTERN = /^(.+?):(\\d+)(?::\\d+)?\\s+(.+)$/;\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\n/** A structured error from markdown validation. */\nexport interface MarkdownError {\n /** Absolute path to the file containing the error. */\n file: string;\n /** Line number where the error occurs (1-based). */\n line: number;\n /** Description of the error including rule name and detail. */\n detail: string;\n}\n\n/** Result of markdown validation. */\nexport interface MarkdownValidationResult {\n /** Whether all files passed validation. */\n success: boolean;\n /** Structured errors found during validation. */\n errors: MarkdownError[];\n}\n\n/** A markdownlint custom rule object. */\ninterface MarkdownlintRule {\n names: string[];\n description: string;\n tags: string[];\n}\n\n/** Options for the validateMarkdown function. */\nexport interface ValidateMarkdownOptions {\n /** Files or directories to validate. */\n targets: MarkdownValidationTarget[];\n /** Project root for resolving project-absolute links. */\n projectRoot?: string;\n}\n\nexport interface MarkdownValidationTarget {\n readonly kind: MarkdownValidationTargetKind;\n readonly path: string;\n}\n\nexport type MarkdownValidationTargetKind =\n (typeof MARKDOWN_VALIDATION_TARGET_KIND)[keyof typeof MARKDOWN_VALIDATION_TARGET_KIND];\n\nexport interface MarkdownSkippedValidationTarget {\n readonly path: string;\n readonly reason: string;\n}\n\nexport interface MarkdownValidationTargetResolution {\n readonly skipped?: MarkdownSkippedValidationTarget;\n readonly target?: MarkdownValidationTarget;\n}\n\nexport interface MarkdownValidationTargetDeps {\n readonly statSync: typeof statSync;\n}\n\nconst defaultMarkdownValidationTargetDeps: MarkdownValidationTargetDeps = {\n statSync,\n};\n\n// =============================================================================\n// CONFIGURATION\n// =============================================================================\n\n/**\n * Build the markdownlint configuration object.\n *\n * MD024 (no duplicate headings) is configured per directory:\n * - `spx/` and other spec directories: `siblings_only` — allows same heading\n * under different parents, flags true sibling duplicates\n * - `docs/`: disabled — generated/repetitive docs commonly reuse headings\n *\n * @param directoryName - Basename of the directory being validated (e.g. \"spx\", \"docs\")\n * @returns Configuration object for markdownlint-cli2's optionsOverride\n */\nexport function buildMarkdownlintConfig(directoryName: string): {\n default: boolean;\n MD001: boolean;\n MD003: boolean;\n MD009: boolean;\n MD010: boolean;\n MD024: boolean | { siblings_only: boolean };\n MD025: boolean;\n MD047: boolean;\n customRules: MarkdownlintRule[];\n} {\n const md024Disabled = MD024_DISABLED_DIRECTORIES.includes(\n directoryName as (typeof MD024_DISABLED_DIRECTORIES)[number],\n );\n\n return {\n default: false,\n ...ENABLED_RULES,\n MD024: md024Disabled ? false : { siblings_only: true },\n customRules: [relativeLinksRule],\n };\n}\n\n// =============================================================================\n// DEFAULT DIRECTORIES\n// =============================================================================\n\n/**\n * Get the default directories to validate.\n *\n * Returns absolute paths for spx/ and docs/ directories that exist\n * within the given project root. This is a pure function for testability.\n *\n * @param projectRoot - Absolute path to the project root\n * @returns Array of absolute paths to existing default directories\n */\nexport function getDefaultDirectories(projectRoot: string): string[] {\n return MARKDOWN_DEFAULT_DIRECTORY_NAMES\n .map((name) => join(projectRoot, name))\n .filter((dir) => existsSync(dir));\n}\n\nexport function classifyMarkdownValidationTarget(\n path: string,\n deps: MarkdownValidationTargetDeps = defaultMarkdownValidationTargetDeps,\n): MarkdownValidationTarget | undefined {\n return resolveMarkdownValidationTarget(path, deps).target;\n}\n\nexport function resolveMarkdownValidationTarget(\n path: string,\n deps: MarkdownValidationTargetDeps = defaultMarkdownValidationTargetDeps,\n): MarkdownValidationTargetResolution {\n if (isExistingDirectory(path, deps)) {\n return { target: { kind: MARKDOWN_VALIDATION_TARGET_KIND.DIRECTORY, path } };\n }\n if (hasMarkdownExtension(path) && isExistingFile(path, deps)) {\n return { target: { kind: MARKDOWN_VALIDATION_TARGET_KIND.FILE, path } };\n }\n return {\n skipped: {\n path,\n reason: MARKDOWN_VALIDATION_TARGET_DIAGNOSTICS.MISSING_OR_UNRELATED_SCOPE,\n },\n };\n}\n\n// =============================================================================\n// EXCLUDE SUPPORT\n// =============================================================================\n\n/**\n * Read node paths from spx/EXCLUDE and return them as ignore globs.\n *\n * Declared-state nodes have [test] links pointing to files that do not\n * exist yet. Listing them in spx/EXCLUDE tells markdown validation to\n * skip those directories so broken [test] links are not flagged.\n *\n * @param projectRoot - Absolute path to the project root\n * @returns Array of glob patterns to ignore (relative to the validated directory)\n */\nexport function getExcludeGlobs(projectRoot: string | undefined): string[] {\n if (projectRoot === undefined) return [];\n const reader = createIgnoreSourceReader(projectRoot, {\n ignoreSourceFilename: IGNORE_SOURCE_FILENAME_DEFAULT,\n specTreeRootSegment: SPEC_TREE_CONFIG.ROOT_DIRECTORY,\n });\n return reader.entries().map((entry) => `${entry.segment}/**`);\n}\n\n// =============================================================================\n// ERROR PARSING\n// =============================================================================\n\n/**\n * Pattern matching data URIs (data:image/..., data:text/..., etc.).\n * markdownlint-rule-relative-links does not handle data URIs natively\n * and reports them as broken relative links. Filter them out.\n */\nconst DATA_URI_PATTERN = /\\bdata:/;\n\n/**\n * Parse a line of markdownlint-cli2 default formatter output into a structured error.\n *\n * Filters out false positives from data URIs.\n *\n * @param line - A single line of error output\n * @returns Parsed MarkdownError, or null if the line is not a real error\n */\nfunction parseErrorLine(line: string): MarkdownError | null {\n if (DATA_URI_PATTERN.test(line)) {\n return null;\n }\n const match = ERROR_LINE_PATTERN.exec(line);\n if (!match) {\n return null;\n }\n const [, file, lineStr, detail] = match;\n return {\n file,\n line: parseInt(lineStr, 10),\n detail,\n };\n}\n\n// =============================================================================\n// VALIDATION FUNCTION\n// =============================================================================\n\n/**\n * Validate markdown files in the specified targets.\n *\n * Uses markdownlint-cli2's programmatic API with in-code configuration.\n * No config files are written to validated directories.\n *\n * @param options - Validation options including targets and project root\n * @returns Validation result with success status and structured errors\n *\n * @example\n * ```typescript\n * const result = await validateMarkdown({\n * targets: [{ kind: MARKDOWN_VALIDATION_TARGET_KIND.DIRECTORY, path: \"/path/to/spx\" }],\n * projectRoot: \"/path/to/project\",\n * });\n * if (!result.success) {\n * for (const error of result.errors) {\n * console.error(`${error.file}:${error.line} ${error.detail}`);\n * }\n * }\n * ```\n */\nexport async function validateMarkdown(\n options: ValidateMarkdownOptions,\n): Promise<MarkdownValidationResult> {\n const { targets, projectRoot } = options;\n const errors: MarkdownError[] = [];\n const excludeGlobs = getExcludeGlobs(projectRoot);\n\n for (const target of targets) {\n const directory = targetDirectory(target);\n const dirName = markdownlintConfigDirectoryName(directory, projectRoot);\n const config = buildMarkdownlintConfig(dirName);\n const dirErrors = await validateTarget(target, config, projectRoot, excludeGlobs);\n errors.push(...dirErrors);\n }\n\n return {\n success: errors.length === 0,\n errors,\n };\n}\n\n/**\n * Validate a single target using markdownlint-cli2's programmatic API.\n *\n * @param target - Absolute path target to validate\n * @param config - Markdownlint configuration object\n * @param projectRoot - Optional project root for resolving project-absolute links\n * @returns Array of structured errors found in the directory\n */\nasync function validateTarget(\n target: MarkdownValidationTarget,\n config: ReturnType<typeof buildMarkdownlintConfig>,\n projectRoot?: string,\n ignoreGlobs: string[] = [],\n): Promise<MarkdownError[]> {\n const errors: MarkdownError[] = [];\n const directory = targetDirectory(target);\n const argv = target.kind === MARKDOWN_VALIDATION_TARGET_KIND.FILE\n ? [basename(target.path)]\n : [MARKDOWN_DIRECTORY_GLOB];\n\n const { customRules, ...markdownlintConfig } = config;\n\n const optionsOverride: Record<string, unknown> = {\n config: {\n ...markdownlintConfig,\n \"relative-links\": projectRoot ? { root_path: projectRoot } : true,\n },\n customRules,\n noProgress: true,\n noBanner: true,\n ...(ignoreGlobs.length > 0 ? { ignores: ignoreGlobs } : {}),\n };\n\n await markdownlintMain({\n directory,\n argv,\n optionsOverride,\n noImport: true,\n logMessage: () => {},\n logError: (message: string) => {\n const parsed = parseErrorLine(message);\n if (parsed) {\n errors.push({\n ...parsed,\n file: join(directory, parsed.file),\n });\n }\n },\n });\n\n return errors;\n}\n\nfunction targetDirectory(target: MarkdownValidationTarget): string {\n return target.kind === MARKDOWN_VALIDATION_TARGET_KIND.FILE ? dirname(target.path) : target.path;\n}\n\nfunction hasMarkdownExtension(path: string): boolean {\n const lastDot = path.lastIndexOf(\".\");\n if (lastDot < 0) return false;\n return MARKDOWN_FILE_EXTENSIONS.has(path.slice(lastDot).toLowerCase());\n}\n\nfunction isExistingDirectory(path: string, deps: MarkdownValidationTargetDeps): boolean {\n try {\n return deps.statSync(path).isDirectory();\n } catch {\n return false;\n }\n}\n\nfunction isExistingFile(path: string, deps: MarkdownValidationTargetDeps): boolean {\n try {\n return deps.statSync(path).isFile();\n } catch {\n return false;\n }\n}\n\nfunction markdownlintConfigDirectoryName(directory: string, projectRoot: string | undefined): string {\n if (projectRoot !== undefined) {\n const [rootSegment] = pathRelative(projectRoot, directory).split(/[\\\\/]/);\n if (MD024_DISABLED_DIRECTORIES.includes(rootSegment as (typeof MD024_DISABLED_DIRECTORIES)[number])) {\n return rootSegment;\n }\n }\n return basename(directory);\n}\n","export const VALIDATION_EXIT_CODES = {\n SUCCESS: 0,\n FAILURE: 1,\n} as const;\n\nexport const VALIDATION_STAGE_DISPLAY_NAMES = {\n CIRCULAR: \"Circular dependencies\",\n KNIP: \"Knip\",\n ESLINT: \"ESLint\",\n TYPESCRIPT: \"TypeScript\",\n MARKDOWN: \"Markdown\",\n LITERAL: \"Literal\",\n} as const;\n\nexport const VALIDATION_SKIP_LABELS = {\n VERB: \"Skipping\",\n LITERAL_REASON: \"skip-literal\",\n TYPESCRIPT_ABSENT_REASON: \"TypeScript not detected in project\",\n VALIDATION_PATHS_NO_TARGETS_REASON: \"validation paths matched no files\",\n MARKDOWN_NO_SCOPE_REASON: \"no markdown files in --files scope\",\n MARKDOWN_NO_DEFAULT_DIRECTORIES_REASON: \"no spx/ or docs/ directories found\",\n} as const;\n\nexport const VALIDATION_COMMAND_OUTPUT = {\n CIRCULAR_FOUND: `${VALIDATION_STAGE_DISPLAY_NAMES.CIRCULAR} found`,\n CIRCULAR_NONE_FOUND: `${VALIDATION_STAGE_DISPLAY_NAMES.CIRCULAR}: ✓ None found`,\n KNIP_CONFIG_ERROR: `${VALIDATION_STAGE_DISPLAY_NAMES.KNIP}: ✗ config error`,\n KNIP_DISABLED: `${VALIDATION_STAGE_DISPLAY_NAMES.KNIP}: skipped (disabled by validation.knip.enabled)`,\n KNIP_SUCCESS: `${VALIDATION_STAGE_DISPLAY_NAMES.KNIP}: ✓ No unused code found`,\n KNIP_FAILURE: \"Unused code found\",\n ESLINT_SUCCESS: `${VALIDATION_STAGE_DISPLAY_NAMES.ESLINT}: ✓ No errors found`,\n ESLINT_FAILURE: `${VALIDATION_STAGE_DISPLAY_NAMES.ESLINT} validation failed`,\n ESLINT_MISSING_CONFIG: \"ESLint config not found: project has tsconfig.json but no eslint.config.{ts,js,mjs,cjs}\",\n TYPESCRIPT_SUCCESS: `${VALIDATION_STAGE_DISPLAY_NAMES.TYPESCRIPT}: ✓ No type errors`,\n TYPESCRIPT_FAILURE: `${VALIDATION_STAGE_DISPLAY_NAMES.TYPESCRIPT} validation failed`,\n MARKDOWN_NO_ISSUES: `${VALIDATION_STAGE_DISPLAY_NAMES.MARKDOWN}: No issues found`,\n MARKDOWN_ERROR_SUMMARY_SUFFIX: \"error(s) found\",\n} as const;\n\nexport const LITERAL_SKIP_OUTPUT =\n `${VALIDATION_STAGE_DISPLAY_NAMES.LITERAL}: skipped (--${VALIDATION_SKIP_LABELS.LITERAL_REASON})`;\n\nexport const LITERAL_SKIP_JSON_OUTPUT = JSON.stringify({\n skipped: true,\n reason: VALIDATION_SKIP_LABELS.LITERAL_REASON,\n});\n\n// Matches a pipeline step line `[N/M]`; the step count derives from the registry,\n// so the denominator is matched generically rather than pinned to a constant.\nexport const VALIDATION_STEP_LINE_PATTERN = /^\\[(\\d+)\\/(\\d+)\\]/gm;\nexport const VALIDATION_STEP_DURATION_PATTERN = /\\((\\d+(?:\\.\\d+)?)(ms|s)\\)\\s*$/;\n\nexport function formatTypeScriptAbsentSkipMessage(stageName: string): string {\n return `⏭ ${VALIDATION_SKIP_LABELS.VERB} ${stageName} (${VALIDATION_SKIP_LABELS.TYPESCRIPT_ABSENT_REASON})`;\n}\n\nexport function formatValidationPathsNoTargetsSkipMessage(stageName: string): string {\n return `⏭ ${VALIDATION_SKIP_LABELS.VERB} ${stageName} (${VALIDATION_SKIP_LABELS.VALIDATION_PATHS_NO_TARGETS_REASON})`;\n}\n","/**\n * Markdown validation language descriptor.\n *\n * Declares the single markdown-quality stage. Splitting markdown into its own\n * descriptor keeps it independent of the TypeScript language so future\n * descriptors compose without inheriting markdown validation.\n */\nimport { markdownCommand } from \"@/commands/validation/markdown\";\nimport { VALIDATION_STAGE_DISPLAY_NAMES } from \"@/commands/validation/messages\";\nimport type { ValidationLanguageDescriptor } from \"@/validation/languages/types\";\n\nconst MARKDOWN_LANGUAGE_NAME = \"markdown\";\n\nexport const markdownValidationLanguage: ValidationLanguageDescriptor = {\n name: MARKDOWN_LANGUAGE_NAME,\n stages: [\n {\n name: VALIDATION_STAGE_DISPLAY_NAMES.MARKDOWN,\n failsPipeline: true,\n run: (context) => markdownCommand({ cwd: context.cwd, files: context.files, quiet: context.quiet }),\n },\n ],\n};\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n'use strict';\n/**\n * Creates a JSON scanner on the given text.\n * If ignoreTrivia is set, whitespaces or comments are ignored.\n */\nexport function createScanner(text, ignoreTrivia = false) {\n const len = text.length;\n let pos = 0, value = '', tokenOffset = 0, token = 16 /* SyntaxKind.Unknown */, lineNumber = 0, lineStartOffset = 0, tokenLineStartOffset = 0, prevTokenLineStartOffset = 0, scanError = 0 /* ScanError.None */;\n function scanHexDigits(count, exact) {\n let digits = 0;\n let value = 0;\n while (digits < count || !exact) {\n let ch = text.charCodeAt(pos);\n if (ch >= 48 /* CharacterCodes._0 */ && ch <= 57 /* CharacterCodes._9 */) {\n value = value * 16 + ch - 48 /* CharacterCodes._0 */;\n }\n else if (ch >= 65 /* CharacterCodes.A */ && ch <= 70 /* CharacterCodes.F */) {\n value = value * 16 + ch - 65 /* CharacterCodes.A */ + 10;\n }\n else if (ch >= 97 /* CharacterCodes.a */ && ch <= 102 /* CharacterCodes.f */) {\n value = value * 16 + ch - 97 /* CharacterCodes.a */ + 10;\n }\n else {\n break;\n }\n pos++;\n digits++;\n }\n if (digits < count) {\n value = -1;\n }\n return value;\n }\n function setPosition(newPosition) {\n pos = newPosition;\n value = '';\n tokenOffset = 0;\n token = 16 /* SyntaxKind.Unknown */;\n scanError = 0 /* ScanError.None */;\n }\n function scanNumber() {\n let start = pos;\n if (text.charCodeAt(pos) === 48 /* CharacterCodes._0 */) {\n pos++;\n }\n else {\n pos++;\n while (pos < text.length && isDigit(text.charCodeAt(pos))) {\n pos++;\n }\n }\n if (pos < text.length && text.charCodeAt(pos) === 46 /* CharacterCodes.dot */) {\n pos++;\n if (pos < text.length && isDigit(text.charCodeAt(pos))) {\n pos++;\n while (pos < text.length && isDigit(text.charCodeAt(pos))) {\n pos++;\n }\n }\n else {\n scanError = 3 /* ScanError.UnexpectedEndOfNumber */;\n return text.substring(start, pos);\n }\n }\n let end = pos;\n if (pos < text.length && (text.charCodeAt(pos) === 69 /* CharacterCodes.E */ || text.charCodeAt(pos) === 101 /* CharacterCodes.e */)) {\n pos++;\n if (pos < text.length && text.charCodeAt(pos) === 43 /* CharacterCodes.plus */ || text.charCodeAt(pos) === 45 /* CharacterCodes.minus */) {\n pos++;\n }\n if (pos < text.length && isDigit(text.charCodeAt(pos))) {\n pos++;\n while (pos < text.length && isDigit(text.charCodeAt(pos))) {\n pos++;\n }\n end = pos;\n }\n else {\n scanError = 3 /* ScanError.UnexpectedEndOfNumber */;\n }\n }\n return text.substring(start, end);\n }\n function scanString() {\n let result = '', start = pos;\n while (true) {\n if (pos >= len) {\n result += text.substring(start, pos);\n scanError = 2 /* ScanError.UnexpectedEndOfString */;\n break;\n }\n const ch = text.charCodeAt(pos);\n if (ch === 34 /* CharacterCodes.doubleQuote */) {\n result += text.substring(start, pos);\n pos++;\n break;\n }\n if (ch === 92 /* CharacterCodes.backslash */) {\n result += text.substring(start, pos);\n pos++;\n if (pos >= len) {\n scanError = 2 /* ScanError.UnexpectedEndOfString */;\n break;\n }\n const ch2 = text.charCodeAt(pos++);\n switch (ch2) {\n case 34 /* CharacterCodes.doubleQuote */:\n result += '\\\"';\n break;\n case 92 /* CharacterCodes.backslash */:\n result += '\\\\';\n break;\n case 47 /* CharacterCodes.slash */:\n result += '/';\n break;\n case 98 /* CharacterCodes.b */:\n result += '\\b';\n break;\n case 102 /* CharacterCodes.f */:\n result += '\\f';\n break;\n case 110 /* CharacterCodes.n */:\n result += '\\n';\n break;\n case 114 /* CharacterCodes.r */:\n result += '\\r';\n break;\n case 116 /* CharacterCodes.t */:\n result += '\\t';\n break;\n case 117 /* CharacterCodes.u */:\n const ch3 = scanHexDigits(4, true);\n if (ch3 >= 0) {\n result += String.fromCharCode(ch3);\n }\n else {\n scanError = 4 /* ScanError.InvalidUnicode */;\n }\n break;\n default:\n scanError = 5 /* ScanError.InvalidEscapeCharacter */;\n }\n start = pos;\n continue;\n }\n if (ch >= 0 && ch <= 0x1f) {\n if (isLineBreak(ch)) {\n result += text.substring(start, pos);\n scanError = 2 /* ScanError.UnexpectedEndOfString */;\n break;\n }\n else {\n scanError = 6 /* ScanError.InvalidCharacter */;\n // mark as error but continue with string\n }\n }\n pos++;\n }\n return result;\n }\n function scanNext() {\n value = '';\n scanError = 0 /* ScanError.None */;\n tokenOffset = pos;\n lineStartOffset = lineNumber;\n prevTokenLineStartOffset = tokenLineStartOffset;\n if (pos >= len) {\n // at the end\n tokenOffset = len;\n return token = 17 /* SyntaxKind.EOF */;\n }\n let code = text.charCodeAt(pos);\n // trivia: whitespace\n if (isWhiteSpace(code)) {\n do {\n pos++;\n value += String.fromCharCode(code);\n code = text.charCodeAt(pos);\n } while (isWhiteSpace(code));\n return token = 15 /* SyntaxKind.Trivia */;\n }\n // trivia: newlines\n if (isLineBreak(code)) {\n pos++;\n value += String.fromCharCode(code);\n if (code === 13 /* CharacterCodes.carriageReturn */ && text.charCodeAt(pos) === 10 /* CharacterCodes.lineFeed */) {\n pos++;\n value += '\\n';\n }\n lineNumber++;\n tokenLineStartOffset = pos;\n return token = 14 /* SyntaxKind.LineBreakTrivia */;\n }\n switch (code) {\n // tokens: []{}:,\n case 123 /* CharacterCodes.openBrace */:\n pos++;\n return token = 1 /* SyntaxKind.OpenBraceToken */;\n case 125 /* CharacterCodes.closeBrace */:\n pos++;\n return token = 2 /* SyntaxKind.CloseBraceToken */;\n case 91 /* CharacterCodes.openBracket */:\n pos++;\n return token = 3 /* SyntaxKind.OpenBracketToken */;\n case 93 /* CharacterCodes.closeBracket */:\n pos++;\n return token = 4 /* SyntaxKind.CloseBracketToken */;\n case 58 /* CharacterCodes.colon */:\n pos++;\n return token = 6 /* SyntaxKind.ColonToken */;\n case 44 /* CharacterCodes.comma */:\n pos++;\n return token = 5 /* SyntaxKind.CommaToken */;\n // strings\n case 34 /* CharacterCodes.doubleQuote */:\n pos++;\n value = scanString();\n return token = 10 /* SyntaxKind.StringLiteral */;\n // comments\n case 47 /* CharacterCodes.slash */:\n const start = pos - 1;\n // Single-line comment\n if (text.charCodeAt(pos + 1) === 47 /* CharacterCodes.slash */) {\n pos += 2;\n while (pos < len) {\n if (isLineBreak(text.charCodeAt(pos))) {\n break;\n }\n pos++;\n }\n value = text.substring(start, pos);\n return token = 12 /* SyntaxKind.LineCommentTrivia */;\n }\n // Multi-line comment\n if (text.charCodeAt(pos + 1) === 42 /* CharacterCodes.asterisk */) {\n pos += 2;\n const safeLength = len - 1; // For lookahead.\n let commentClosed = false;\n while (pos < safeLength) {\n const ch = text.charCodeAt(pos);\n if (ch === 42 /* CharacterCodes.asterisk */ && text.charCodeAt(pos + 1) === 47 /* CharacterCodes.slash */) {\n pos += 2;\n commentClosed = true;\n break;\n }\n pos++;\n if (isLineBreak(ch)) {\n if (ch === 13 /* CharacterCodes.carriageReturn */ && text.charCodeAt(pos) === 10 /* CharacterCodes.lineFeed */) {\n pos++;\n }\n lineNumber++;\n tokenLineStartOffset = pos;\n }\n }\n if (!commentClosed) {\n pos++;\n scanError = 1 /* ScanError.UnexpectedEndOfComment */;\n }\n value = text.substring(start, pos);\n return token = 13 /* SyntaxKind.BlockCommentTrivia */;\n }\n // just a single slash\n value += String.fromCharCode(code);\n pos++;\n return token = 16 /* SyntaxKind.Unknown */;\n // numbers\n case 45 /* CharacterCodes.minus */:\n value += String.fromCharCode(code);\n pos++;\n if (pos === len || !isDigit(text.charCodeAt(pos))) {\n return token = 16 /* SyntaxKind.Unknown */;\n }\n // found a minus, followed by a number so\n // we fall through to proceed with scanning\n // numbers\n case 48 /* CharacterCodes._0 */:\n case 49 /* CharacterCodes._1 */:\n case 50 /* CharacterCodes._2 */:\n case 51 /* CharacterCodes._3 */:\n case 52 /* CharacterCodes._4 */:\n case 53 /* CharacterCodes._5 */:\n case 54 /* CharacterCodes._6 */:\n case 55 /* CharacterCodes._7 */:\n case 56 /* CharacterCodes._8 */:\n case 57 /* CharacterCodes._9 */:\n value += scanNumber();\n return token = 11 /* SyntaxKind.NumericLiteral */;\n // literals and unknown symbols\n default:\n // is a literal? Read the full word.\n while (pos < len && isUnknownContentCharacter(code)) {\n pos++;\n code = text.charCodeAt(pos);\n }\n if (tokenOffset !== pos) {\n value = text.substring(tokenOffset, pos);\n // keywords: true, false, null\n switch (value) {\n case 'true': return token = 8 /* SyntaxKind.TrueKeyword */;\n case 'false': return token = 9 /* SyntaxKind.FalseKeyword */;\n case 'null': return token = 7 /* SyntaxKind.NullKeyword */;\n }\n return token = 16 /* SyntaxKind.Unknown */;\n }\n // some\n value += String.fromCharCode(code);\n pos++;\n return token = 16 /* SyntaxKind.Unknown */;\n }\n }\n function isUnknownContentCharacter(code) {\n if (isWhiteSpace(code) || isLineBreak(code)) {\n return false;\n }\n switch (code) {\n case 125 /* CharacterCodes.closeBrace */:\n case 93 /* CharacterCodes.closeBracket */:\n case 123 /* CharacterCodes.openBrace */:\n case 91 /* CharacterCodes.openBracket */:\n case 34 /* CharacterCodes.doubleQuote */:\n case 58 /* CharacterCodes.colon */:\n case 44 /* CharacterCodes.comma */:\n case 47 /* CharacterCodes.slash */:\n return false;\n }\n return true;\n }\n function scanNextNonTrivia() {\n let result;\n do {\n result = scanNext();\n } while (result >= 12 /* SyntaxKind.LineCommentTrivia */ && result <= 15 /* SyntaxKind.Trivia */);\n return result;\n }\n return {\n setPosition: setPosition,\n getPosition: () => pos,\n scan: ignoreTrivia ? scanNextNonTrivia : scanNext,\n getToken: () => token,\n getTokenValue: () => value,\n getTokenOffset: () => tokenOffset,\n getTokenLength: () => pos - tokenOffset,\n getTokenStartLine: () => lineStartOffset,\n getTokenStartCharacter: () => tokenOffset - prevTokenLineStartOffset,\n getTokenError: () => scanError,\n };\n}\nfunction isWhiteSpace(ch) {\n return ch === 32 /* CharacterCodes.space */ || ch === 9 /* CharacterCodes.tab */;\n}\nfunction isLineBreak(ch) {\n return ch === 10 /* CharacterCodes.lineFeed */ || ch === 13 /* CharacterCodes.carriageReturn */;\n}\nfunction isDigit(ch) {\n return ch >= 48 /* CharacterCodes._0 */ && ch <= 57 /* CharacterCodes._9 */;\n}\nvar CharacterCodes;\n(function (CharacterCodes) {\n CharacterCodes[CharacterCodes[\"lineFeed\"] = 10] = \"lineFeed\";\n CharacterCodes[CharacterCodes[\"carriageReturn\"] = 13] = \"carriageReturn\";\n CharacterCodes[CharacterCodes[\"space\"] = 32] = \"space\";\n CharacterCodes[CharacterCodes[\"_0\"] = 48] = \"_0\";\n CharacterCodes[CharacterCodes[\"_1\"] = 49] = \"_1\";\n CharacterCodes[CharacterCodes[\"_2\"] = 50] = \"_2\";\n CharacterCodes[CharacterCodes[\"_3\"] = 51] = \"_3\";\n CharacterCodes[CharacterCodes[\"_4\"] = 52] = \"_4\";\n CharacterCodes[CharacterCodes[\"_5\"] = 53] = \"_5\";\n CharacterCodes[CharacterCodes[\"_6\"] = 54] = \"_6\";\n CharacterCodes[CharacterCodes[\"_7\"] = 55] = \"_7\";\n CharacterCodes[CharacterCodes[\"_8\"] = 56] = \"_8\";\n CharacterCodes[CharacterCodes[\"_9\"] = 57] = \"_9\";\n CharacterCodes[CharacterCodes[\"a\"] = 97] = \"a\";\n CharacterCodes[CharacterCodes[\"b\"] = 98] = \"b\";\n CharacterCodes[CharacterCodes[\"c\"] = 99] = \"c\";\n CharacterCodes[CharacterCodes[\"d\"] = 100] = \"d\";\n CharacterCodes[CharacterCodes[\"e\"] = 101] = \"e\";\n CharacterCodes[CharacterCodes[\"f\"] = 102] = \"f\";\n CharacterCodes[CharacterCodes[\"g\"] = 103] = \"g\";\n CharacterCodes[CharacterCodes[\"h\"] = 104] = \"h\";\n CharacterCodes[CharacterCodes[\"i\"] = 105] = \"i\";\n CharacterCodes[CharacterCodes[\"j\"] = 106] = \"j\";\n CharacterCodes[CharacterCodes[\"k\"] = 107] = \"k\";\n CharacterCodes[CharacterCodes[\"l\"] = 108] = \"l\";\n CharacterCodes[CharacterCodes[\"m\"] = 109] = \"m\";\n CharacterCodes[CharacterCodes[\"n\"] = 110] = \"n\";\n CharacterCodes[CharacterCodes[\"o\"] = 111] = \"o\";\n CharacterCodes[CharacterCodes[\"p\"] = 112] = \"p\";\n CharacterCodes[CharacterCodes[\"q\"] = 113] = \"q\";\n CharacterCodes[CharacterCodes[\"r\"] = 114] = \"r\";\n CharacterCodes[CharacterCodes[\"s\"] = 115] = \"s\";\n CharacterCodes[CharacterCodes[\"t\"] = 116] = \"t\";\n CharacterCodes[CharacterCodes[\"u\"] = 117] = \"u\";\n CharacterCodes[CharacterCodes[\"v\"] = 118] = \"v\";\n CharacterCodes[CharacterCodes[\"w\"] = 119] = \"w\";\n CharacterCodes[CharacterCodes[\"x\"] = 120] = \"x\";\n CharacterCodes[CharacterCodes[\"y\"] = 121] = \"y\";\n CharacterCodes[CharacterCodes[\"z\"] = 122] = \"z\";\n CharacterCodes[CharacterCodes[\"A\"] = 65] = \"A\";\n CharacterCodes[CharacterCodes[\"B\"] = 66] = \"B\";\n CharacterCodes[CharacterCodes[\"C\"] = 67] = \"C\";\n CharacterCodes[CharacterCodes[\"D\"] = 68] = \"D\";\n CharacterCodes[CharacterCodes[\"E\"] = 69] = \"E\";\n CharacterCodes[CharacterCodes[\"F\"] = 70] = \"F\";\n CharacterCodes[CharacterCodes[\"G\"] = 71] = \"G\";\n CharacterCodes[CharacterCodes[\"H\"] = 72] = \"H\";\n CharacterCodes[CharacterCodes[\"I\"] = 73] = \"I\";\n CharacterCodes[CharacterCodes[\"J\"] = 74] = \"J\";\n CharacterCodes[CharacterCodes[\"K\"] = 75] = \"K\";\n CharacterCodes[CharacterCodes[\"L\"] = 76] = \"L\";\n CharacterCodes[CharacterCodes[\"M\"] = 77] = \"M\";\n CharacterCodes[CharacterCodes[\"N\"] = 78] = \"N\";\n CharacterCodes[CharacterCodes[\"O\"] = 79] = \"O\";\n CharacterCodes[CharacterCodes[\"P\"] = 80] = \"P\";\n CharacterCodes[CharacterCodes[\"Q\"] = 81] = \"Q\";\n CharacterCodes[CharacterCodes[\"R\"] = 82] = \"R\";\n CharacterCodes[CharacterCodes[\"S\"] = 83] = \"S\";\n CharacterCodes[CharacterCodes[\"T\"] = 84] = \"T\";\n CharacterCodes[CharacterCodes[\"U\"] = 85] = \"U\";\n CharacterCodes[CharacterCodes[\"V\"] = 86] = \"V\";\n CharacterCodes[CharacterCodes[\"W\"] = 87] = \"W\";\n CharacterCodes[CharacterCodes[\"X\"] = 88] = \"X\";\n CharacterCodes[CharacterCodes[\"Y\"] = 89] = \"Y\";\n CharacterCodes[CharacterCodes[\"Z\"] = 90] = \"Z\";\n CharacterCodes[CharacterCodes[\"asterisk\"] = 42] = \"asterisk\";\n CharacterCodes[CharacterCodes[\"backslash\"] = 92] = \"backslash\";\n CharacterCodes[CharacterCodes[\"closeBrace\"] = 125] = \"closeBrace\";\n CharacterCodes[CharacterCodes[\"closeBracket\"] = 93] = \"closeBracket\";\n CharacterCodes[CharacterCodes[\"colon\"] = 58] = \"colon\";\n CharacterCodes[CharacterCodes[\"comma\"] = 44] = \"comma\";\n CharacterCodes[CharacterCodes[\"dot\"] = 46] = \"dot\";\n CharacterCodes[CharacterCodes[\"doubleQuote\"] = 34] = \"doubleQuote\";\n CharacterCodes[CharacterCodes[\"minus\"] = 45] = \"minus\";\n CharacterCodes[CharacterCodes[\"openBrace\"] = 123] = \"openBrace\";\n CharacterCodes[CharacterCodes[\"openBracket\"] = 91] = \"openBracket\";\n CharacterCodes[CharacterCodes[\"plus\"] = 43] = \"plus\";\n CharacterCodes[CharacterCodes[\"slash\"] = 47] = \"slash\";\n CharacterCodes[CharacterCodes[\"formFeed\"] = 12] = \"formFeed\";\n CharacterCodes[CharacterCodes[\"tab\"] = 9] = \"tab\";\n})(CharacterCodes || (CharacterCodes = {}));\n","export const cachedSpaces = new Array(20).fill(0).map((_, index) => {\n return ' '.repeat(index);\n});\nconst maxCachedValues = 200;\nexport const cachedBreakLinesWithSpaces = {\n ' ': {\n '\\n': new Array(maxCachedValues).fill(0).map((_, index) => {\n return '\\n' + ' '.repeat(index);\n }),\n '\\r': new Array(maxCachedValues).fill(0).map((_, index) => {\n return '\\r' + ' '.repeat(index);\n }),\n '\\r\\n': new Array(maxCachedValues).fill(0).map((_, index) => {\n return '\\r\\n' + ' '.repeat(index);\n }),\n },\n '\\t': {\n '\\n': new Array(maxCachedValues).fill(0).map((_, index) => {\n return '\\n' + '\\t'.repeat(index);\n }),\n '\\r': new Array(maxCachedValues).fill(0).map((_, index) => {\n return '\\r' + '\\t'.repeat(index);\n }),\n '\\r\\n': new Array(maxCachedValues).fill(0).map((_, index) => {\n return '\\r\\n' + '\\t'.repeat(index);\n }),\n }\n};\nexport const supportedEols = ['\\n', '\\r', '\\r\\n'];\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n'use strict';\nimport { createScanner } from './scanner';\nvar ParseOptions;\n(function (ParseOptions) {\n ParseOptions.DEFAULT = {\n allowTrailingComma: false\n };\n})(ParseOptions || (ParseOptions = {}));\n/**\n * For a given offset, evaluate the location in the JSON document. Each segment in the location path is either a property name or an array index.\n */\nexport function getLocation(text, position) {\n const segments = []; // strings or numbers\n const earlyReturnException = new Object();\n let previousNode = undefined;\n const previousNodeInst = {\n value: {},\n offset: 0,\n length: 0,\n type: 'object',\n parent: undefined\n };\n let isAtPropertyKey = false;\n function setPreviousNode(value, offset, length, type) {\n previousNodeInst.value = value;\n previousNodeInst.offset = offset;\n previousNodeInst.length = length;\n previousNodeInst.type = type;\n previousNodeInst.colonOffset = undefined;\n previousNode = previousNodeInst;\n }\n try {\n visit(text, {\n onObjectBegin: (offset, length) => {\n if (position <= offset) {\n throw earlyReturnException;\n }\n previousNode = undefined;\n isAtPropertyKey = position > offset;\n segments.push(''); // push a placeholder (will be replaced)\n },\n onObjectProperty: (name, offset, length) => {\n if (position < offset) {\n throw earlyReturnException;\n }\n setPreviousNode(name, offset, length, 'property');\n segments[segments.length - 1] = name;\n if (position <= offset + length) {\n throw earlyReturnException;\n }\n },\n onObjectEnd: (offset, length) => {\n if (position <= offset) {\n throw earlyReturnException;\n }\n previousNode = undefined;\n segments.pop();\n },\n onArrayBegin: (offset, length) => {\n if (position <= offset) {\n throw earlyReturnException;\n }\n previousNode = undefined;\n segments.push(0);\n },\n onArrayEnd: (offset, length) => {\n if (position <= offset) {\n throw earlyReturnException;\n }\n previousNode = undefined;\n segments.pop();\n },\n onLiteralValue: (value, offset, length) => {\n if (position < offset) {\n throw earlyReturnException;\n }\n setPreviousNode(value, offset, length, getNodeType(value));\n if (position <= offset + length) {\n throw earlyReturnException;\n }\n },\n onSeparator: (sep, offset, length) => {\n if (position <= offset) {\n throw earlyReturnException;\n }\n if (sep === ':' && previousNode && previousNode.type === 'property') {\n previousNode.colonOffset = offset;\n isAtPropertyKey = false;\n previousNode = undefined;\n }\n else if (sep === ',') {\n const last = segments[segments.length - 1];\n if (typeof last === 'number') {\n segments[segments.length - 1] = last + 1;\n }\n else {\n isAtPropertyKey = true;\n segments[segments.length - 1] = '';\n }\n previousNode = undefined;\n }\n }\n });\n }\n catch (e) {\n if (e !== earlyReturnException) {\n throw e;\n }\n }\n return {\n path: segments,\n previousNode,\n isAtPropertyKey,\n matches: (pattern) => {\n let k = 0;\n for (let i = 0; k < pattern.length && i < segments.length; i++) {\n if (pattern[k] === segments[i] || pattern[k] === '*') {\n k++;\n }\n else if (pattern[k] !== '**') {\n return false;\n }\n }\n return k === pattern.length;\n }\n };\n}\n/**\n * Parses the given text and returns the object the JSON content represents. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result.\n * Therefore always check the errors list to find out if the input was valid.\n */\nexport function parse(text, errors = [], options = ParseOptions.DEFAULT) {\n let currentProperty = null;\n let currentParent = [];\n const previousParents = [];\n function onValue(value) {\n if (Array.isArray(currentParent)) {\n currentParent.push(value);\n }\n else if (currentProperty !== null) {\n currentParent[currentProperty] = value;\n }\n }\n const visitor = {\n onObjectBegin: () => {\n const object = {};\n onValue(object);\n previousParents.push(currentParent);\n currentParent = object;\n currentProperty = null;\n },\n onObjectProperty: (name) => {\n currentProperty = name;\n },\n onObjectEnd: () => {\n currentParent = previousParents.pop();\n },\n onArrayBegin: () => {\n const array = [];\n onValue(array);\n previousParents.push(currentParent);\n currentParent = array;\n currentProperty = null;\n },\n onArrayEnd: () => {\n currentParent = previousParents.pop();\n },\n onLiteralValue: onValue,\n onError: (error, offset, length) => {\n errors.push({ error, offset, length });\n }\n };\n visit(text, visitor, options);\n return currentParent[0];\n}\n/**\n * Parses the given text and returns a tree representation the JSON content. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result.\n */\nexport function parseTree(text, errors = [], options = ParseOptions.DEFAULT) {\n let currentParent = { type: 'array', offset: -1, length: -1, children: [], parent: undefined }; // artificial root\n function ensurePropertyComplete(endOffset) {\n if (currentParent.type === 'property') {\n currentParent.length = endOffset - currentParent.offset;\n currentParent = currentParent.parent;\n }\n }\n function onValue(valueNode) {\n currentParent.children.push(valueNode);\n return valueNode;\n }\n const visitor = {\n onObjectBegin: (offset) => {\n currentParent = onValue({ type: 'object', offset, length: -1, parent: currentParent, children: [] });\n },\n onObjectProperty: (name, offset, length) => {\n currentParent = onValue({ type: 'property', offset, length: -1, parent: currentParent, children: [] });\n currentParent.children.push({ type: 'string', value: name, offset, length, parent: currentParent });\n },\n onObjectEnd: (offset, length) => {\n ensurePropertyComplete(offset + length); // in case of a missing value for a property: make sure property is complete\n currentParent.length = offset + length - currentParent.offset;\n currentParent = currentParent.parent;\n ensurePropertyComplete(offset + length);\n },\n onArrayBegin: (offset, length) => {\n currentParent = onValue({ type: 'array', offset, length: -1, parent: currentParent, children: [] });\n },\n onArrayEnd: (offset, length) => {\n currentParent.length = offset + length - currentParent.offset;\n currentParent = currentParent.parent;\n ensurePropertyComplete(offset + length);\n },\n onLiteralValue: (value, offset, length) => {\n onValue({ type: getNodeType(value), offset, length, parent: currentParent, value });\n ensurePropertyComplete(offset + length);\n },\n onSeparator: (sep, offset, length) => {\n if (currentParent.type === 'property') {\n if (sep === ':') {\n currentParent.colonOffset = offset;\n }\n else if (sep === ',') {\n ensurePropertyComplete(offset);\n }\n }\n },\n onError: (error, offset, length) => {\n errors.push({ error, offset, length });\n }\n };\n visit(text, visitor, options);\n const result = currentParent.children[0];\n if (result) {\n delete result.parent;\n }\n return result;\n}\n/**\n * Finds the node at the given path in a JSON DOM.\n */\nexport function findNodeAtLocation(root, path) {\n if (!root) {\n return undefined;\n }\n let node = root;\n for (let segment of path) {\n if (typeof segment === 'string') {\n if (node.type !== 'object' || !Array.isArray(node.children)) {\n return undefined;\n }\n let found = false;\n for (const propertyNode of node.children) {\n if (Array.isArray(propertyNode.children) && propertyNode.children[0].value === segment && propertyNode.children.length === 2) {\n node = propertyNode.children[1];\n found = true;\n break;\n }\n }\n if (!found) {\n return undefined;\n }\n }\n else {\n const index = segment;\n if (node.type !== 'array' || index < 0 || !Array.isArray(node.children) || index >= node.children.length) {\n return undefined;\n }\n node = node.children[index];\n }\n }\n return node;\n}\n/**\n * Gets the JSON path of the given JSON DOM node\n */\nexport function getNodePath(node) {\n if (!node.parent || !node.parent.children) {\n return [];\n }\n const path = getNodePath(node.parent);\n if (node.parent.type === 'property') {\n const key = node.parent.children[0].value;\n path.push(key);\n }\n else if (node.parent.type === 'array') {\n const index = node.parent.children.indexOf(node);\n if (index !== -1) {\n path.push(index);\n }\n }\n return path;\n}\n/**\n * Evaluates the JavaScript object of the given JSON DOM node\n */\nexport function getNodeValue(node) {\n switch (node.type) {\n case 'array':\n return node.children.map(getNodeValue);\n case 'object':\n const obj = Object.create(null);\n for (let prop of node.children) {\n const valueNode = prop.children[1];\n if (valueNode) {\n obj[prop.children[0].value] = getNodeValue(valueNode);\n }\n }\n return obj;\n case 'null':\n case 'string':\n case 'number':\n case 'boolean':\n return node.value;\n default:\n return undefined;\n }\n}\nexport function contains(node, offset, includeRightBound = false) {\n return (offset >= node.offset && offset < (node.offset + node.length)) || includeRightBound && (offset === (node.offset + node.length));\n}\n/**\n * Finds the most inner node at the given offset. If includeRightBound is set, also finds nodes that end at the given offset.\n */\nexport function findNodeAtOffset(node, offset, includeRightBound = false) {\n if (contains(node, offset, includeRightBound)) {\n const children = node.children;\n if (Array.isArray(children)) {\n for (let i = 0; i < children.length && children[i].offset <= offset; i++) {\n const item = findNodeAtOffset(children[i], offset, includeRightBound);\n if (item) {\n return item;\n }\n }\n }\n return node;\n }\n return undefined;\n}\n/**\n * Parses the given text and invokes the visitor functions for each object, array and literal reached.\n */\nexport function visit(text, visitor, options = ParseOptions.DEFAULT) {\n const _scanner = createScanner(text, false);\n // Important: Only pass copies of this to visitor functions to prevent accidental modification, and\n // to not affect visitor functions which stored a reference to a previous JSONPath\n const _jsonPath = [];\n // Depth of onXXXBegin() callbacks suppressed. onXXXEnd() decrements this if it isn't 0 already.\n // Callbacks are only called when this value is 0.\n let suppressedCallbacks = 0;\n function toNoArgVisit(visitFunction) {\n return visitFunction ? () => suppressedCallbacks === 0 && visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter()) : () => true;\n }\n function toOneArgVisit(visitFunction) {\n return visitFunction ? (arg) => suppressedCallbacks === 0 && visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter()) : () => true;\n }\n function toOneArgVisitWithPath(visitFunction) {\n return visitFunction ? (arg) => suppressedCallbacks === 0 && visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter(), () => _jsonPath.slice()) : () => true;\n }\n function toBeginVisit(visitFunction) {\n return visitFunction ?\n () => {\n if (suppressedCallbacks > 0) {\n suppressedCallbacks++;\n }\n else {\n let cbReturn = visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter(), () => _jsonPath.slice());\n if (cbReturn === false) {\n suppressedCallbacks = 1;\n }\n }\n }\n : () => true;\n }\n function toEndVisit(visitFunction) {\n return visitFunction ?\n () => {\n if (suppressedCallbacks > 0) {\n suppressedCallbacks--;\n }\n if (suppressedCallbacks === 0) {\n visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter());\n }\n }\n : () => true;\n }\n const onObjectBegin = toBeginVisit(visitor.onObjectBegin), onObjectProperty = toOneArgVisitWithPath(visitor.onObjectProperty), onObjectEnd = toEndVisit(visitor.onObjectEnd), onArrayBegin = toBeginVisit(visitor.onArrayBegin), onArrayEnd = toEndVisit(visitor.onArrayEnd), onLiteralValue = toOneArgVisitWithPath(visitor.onLiteralValue), onSeparator = toOneArgVisit(visitor.onSeparator), onComment = toNoArgVisit(visitor.onComment), onError = toOneArgVisit(visitor.onError);\n const disallowComments = options && options.disallowComments;\n const allowTrailingComma = options && options.allowTrailingComma;\n function scanNext() {\n while (true) {\n const token = _scanner.scan();\n switch (_scanner.getTokenError()) {\n case 4 /* ScanError.InvalidUnicode */:\n handleError(14 /* ParseErrorCode.InvalidUnicode */);\n break;\n case 5 /* ScanError.InvalidEscapeCharacter */:\n handleError(15 /* ParseErrorCode.InvalidEscapeCharacter */);\n break;\n case 3 /* ScanError.UnexpectedEndOfNumber */:\n handleError(13 /* ParseErrorCode.UnexpectedEndOfNumber */);\n break;\n case 1 /* ScanError.UnexpectedEndOfComment */:\n if (!disallowComments) {\n handleError(11 /* ParseErrorCode.UnexpectedEndOfComment */);\n }\n break;\n case 2 /* ScanError.UnexpectedEndOfString */:\n handleError(12 /* ParseErrorCode.UnexpectedEndOfString */);\n break;\n case 6 /* ScanError.InvalidCharacter */:\n handleError(16 /* ParseErrorCode.InvalidCharacter */);\n break;\n }\n switch (token) {\n case 12 /* SyntaxKind.LineCommentTrivia */:\n case 13 /* SyntaxKind.BlockCommentTrivia */:\n if (disallowComments) {\n handleError(10 /* ParseErrorCode.InvalidCommentToken */);\n }\n else {\n onComment();\n }\n break;\n case 16 /* SyntaxKind.Unknown */:\n handleError(1 /* ParseErrorCode.InvalidSymbol */);\n break;\n case 15 /* SyntaxKind.Trivia */:\n case 14 /* SyntaxKind.LineBreakTrivia */:\n break;\n default:\n return token;\n }\n }\n }\n function handleError(error, skipUntilAfter = [], skipUntil = []) {\n onError(error);\n if (skipUntilAfter.length + skipUntil.length > 0) {\n let token = _scanner.getToken();\n while (token !== 17 /* SyntaxKind.EOF */) {\n if (skipUntilAfter.indexOf(token) !== -1) {\n scanNext();\n break;\n }\n else if (skipUntil.indexOf(token) !== -1) {\n break;\n }\n token = scanNext();\n }\n }\n }\n function parseString(isValue) {\n const value = _scanner.getTokenValue();\n if (isValue) {\n onLiteralValue(value);\n }\n else {\n onObjectProperty(value);\n // add property name afterwards\n _jsonPath.push(value);\n }\n scanNext();\n return true;\n }\n function parseLiteral() {\n switch (_scanner.getToken()) {\n case 11 /* SyntaxKind.NumericLiteral */:\n const tokenValue = _scanner.getTokenValue();\n let value = Number(tokenValue);\n if (isNaN(value)) {\n handleError(2 /* ParseErrorCode.InvalidNumberFormat */);\n value = 0;\n }\n onLiteralValue(value);\n break;\n case 7 /* SyntaxKind.NullKeyword */:\n onLiteralValue(null);\n break;\n case 8 /* SyntaxKind.TrueKeyword */:\n onLiteralValue(true);\n break;\n case 9 /* SyntaxKind.FalseKeyword */:\n onLiteralValue(false);\n break;\n default:\n return false;\n }\n scanNext();\n return true;\n }\n function parseProperty() {\n if (_scanner.getToken() !== 10 /* SyntaxKind.StringLiteral */) {\n handleError(3 /* ParseErrorCode.PropertyNameExpected */, [], [2 /* SyntaxKind.CloseBraceToken */, 5 /* SyntaxKind.CommaToken */]);\n return false;\n }\n parseString(false);\n if (_scanner.getToken() === 6 /* SyntaxKind.ColonToken */) {\n onSeparator(':');\n scanNext(); // consume colon\n if (!parseValue()) {\n handleError(4 /* ParseErrorCode.ValueExpected */, [], [2 /* SyntaxKind.CloseBraceToken */, 5 /* SyntaxKind.CommaToken */]);\n }\n }\n else {\n handleError(5 /* ParseErrorCode.ColonExpected */, [], [2 /* SyntaxKind.CloseBraceToken */, 5 /* SyntaxKind.CommaToken */]);\n }\n _jsonPath.pop(); // remove processed property name\n return true;\n }\n function parseObject() {\n onObjectBegin();\n scanNext(); // consume open brace\n let needsComma = false;\n while (_scanner.getToken() !== 2 /* SyntaxKind.CloseBraceToken */ && _scanner.getToken() !== 17 /* SyntaxKind.EOF */) {\n if (_scanner.getToken() === 5 /* SyntaxKind.CommaToken */) {\n if (!needsComma) {\n handleError(4 /* ParseErrorCode.ValueExpected */, [], []);\n }\n onSeparator(',');\n scanNext(); // consume comma\n if (_scanner.getToken() === 2 /* SyntaxKind.CloseBraceToken */ && allowTrailingComma) {\n break;\n }\n }\n else if (needsComma) {\n handleError(6 /* ParseErrorCode.CommaExpected */, [], []);\n }\n if (!parseProperty()) {\n handleError(4 /* ParseErrorCode.ValueExpected */, [], [2 /* SyntaxKind.CloseBraceToken */, 5 /* SyntaxKind.CommaToken */]);\n }\n needsComma = true;\n }\n onObjectEnd();\n if (_scanner.getToken() !== 2 /* SyntaxKind.CloseBraceToken */) {\n handleError(7 /* ParseErrorCode.CloseBraceExpected */, [2 /* SyntaxKind.CloseBraceToken */], []);\n }\n else {\n scanNext(); // consume close brace\n }\n return true;\n }\n function parseArray() {\n onArrayBegin();\n scanNext(); // consume open bracket\n let isFirstElement = true;\n let needsComma = false;\n while (_scanner.getToken() !== 4 /* SyntaxKind.CloseBracketToken */ && _scanner.getToken() !== 17 /* SyntaxKind.EOF */) {\n if (_scanner.getToken() === 5 /* SyntaxKind.CommaToken */) {\n if (!needsComma) {\n handleError(4 /* ParseErrorCode.ValueExpected */, [], []);\n }\n onSeparator(',');\n scanNext(); // consume comma\n if (_scanner.getToken() === 4 /* SyntaxKind.CloseBracketToken */ && allowTrailingComma) {\n break;\n }\n }\n else if (needsComma) {\n handleError(6 /* ParseErrorCode.CommaExpected */, [], []);\n }\n if (isFirstElement) {\n _jsonPath.push(0);\n isFirstElement = false;\n }\n else {\n _jsonPath[_jsonPath.length - 1]++;\n }\n if (!parseValue()) {\n handleError(4 /* ParseErrorCode.ValueExpected */, [], [4 /* SyntaxKind.CloseBracketToken */, 5 /* SyntaxKind.CommaToken */]);\n }\n needsComma = true;\n }\n onArrayEnd();\n if (!isFirstElement) {\n _jsonPath.pop(); // remove array index\n }\n if (_scanner.getToken() !== 4 /* SyntaxKind.CloseBracketToken */) {\n handleError(8 /* ParseErrorCode.CloseBracketExpected */, [4 /* SyntaxKind.CloseBracketToken */], []);\n }\n else {\n scanNext(); // consume close bracket\n }\n return true;\n }\n function parseValue() {\n switch (_scanner.getToken()) {\n case 3 /* SyntaxKind.OpenBracketToken */:\n return parseArray();\n case 1 /* SyntaxKind.OpenBraceToken */:\n return parseObject();\n case 10 /* SyntaxKind.StringLiteral */:\n return parseString(true);\n default:\n return parseLiteral();\n }\n }\n scanNext();\n if (_scanner.getToken() === 17 /* SyntaxKind.EOF */) {\n if (options.allowEmptyContent) {\n return true;\n }\n handleError(4 /* ParseErrorCode.ValueExpected */, [], []);\n return false;\n }\n if (!parseValue()) {\n handleError(4 /* ParseErrorCode.ValueExpected */, [], []);\n return false;\n }\n if (_scanner.getToken() !== 17 /* SyntaxKind.EOF */) {\n handleError(9 /* ParseErrorCode.EndOfFileExpected */, [], []);\n }\n return true;\n}\n/**\n * Takes JSON with JavaScript-style comments and remove\n * them. Optionally replaces every none-newline character\n * of comments with a replaceCharacter\n */\nexport function stripComments(text, replaceCh) {\n let _scanner = createScanner(text), parts = [], kind, offset = 0, pos;\n do {\n pos = _scanner.getPosition();\n kind = _scanner.scan();\n switch (kind) {\n case 12 /* SyntaxKind.LineCommentTrivia */:\n case 13 /* SyntaxKind.BlockCommentTrivia */:\n case 17 /* SyntaxKind.EOF */:\n if (offset !== pos) {\n parts.push(text.substring(offset, pos));\n }\n if (replaceCh !== undefined) {\n parts.push(_scanner.getTokenValue().replace(/[^\\r\\n]/g, replaceCh));\n }\n offset = _scanner.getPosition();\n break;\n }\n } while (kind !== 17 /* SyntaxKind.EOF */);\n return parts.join('');\n}\nexport function getNodeType(value) {\n switch (typeof value) {\n case 'boolean': return 'boolean';\n case 'number': return 'number';\n case 'string': return 'string';\n case 'object': {\n if (!value) {\n return 'null';\n }\n else if (Array.isArray(value)) {\n return 'array';\n }\n return 'object';\n }\n default: return 'null';\n }\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n'use strict';\nimport * as formatter from './impl/format';\nimport * as edit from './impl/edit';\nimport * as scanner from './impl/scanner';\nimport * as parser from './impl/parser';\n/**\n * Creates a JSON scanner on the given text.\n * If ignoreTrivia is set, whitespaces or comments are ignored.\n */\nexport const createScanner = scanner.createScanner;\nexport var ScanError;\n(function (ScanError) {\n ScanError[ScanError[\"None\"] = 0] = \"None\";\n ScanError[ScanError[\"UnexpectedEndOfComment\"] = 1] = \"UnexpectedEndOfComment\";\n ScanError[ScanError[\"UnexpectedEndOfString\"] = 2] = \"UnexpectedEndOfString\";\n ScanError[ScanError[\"UnexpectedEndOfNumber\"] = 3] = \"UnexpectedEndOfNumber\";\n ScanError[ScanError[\"InvalidUnicode\"] = 4] = \"InvalidUnicode\";\n ScanError[ScanError[\"InvalidEscapeCharacter\"] = 5] = \"InvalidEscapeCharacter\";\n ScanError[ScanError[\"InvalidCharacter\"] = 6] = \"InvalidCharacter\";\n})(ScanError || (ScanError = {}));\nexport var SyntaxKind;\n(function (SyntaxKind) {\n SyntaxKind[SyntaxKind[\"OpenBraceToken\"] = 1] = \"OpenBraceToken\";\n SyntaxKind[SyntaxKind[\"CloseBraceToken\"] = 2] = \"CloseBraceToken\";\n SyntaxKind[SyntaxKind[\"OpenBracketToken\"] = 3] = \"OpenBracketToken\";\n SyntaxKind[SyntaxKind[\"CloseBracketToken\"] = 4] = \"CloseBracketToken\";\n SyntaxKind[SyntaxKind[\"CommaToken\"] = 5] = \"CommaToken\";\n SyntaxKind[SyntaxKind[\"ColonToken\"] = 6] = \"ColonToken\";\n SyntaxKind[SyntaxKind[\"NullKeyword\"] = 7] = \"NullKeyword\";\n SyntaxKind[SyntaxKind[\"TrueKeyword\"] = 8] = \"TrueKeyword\";\n SyntaxKind[SyntaxKind[\"FalseKeyword\"] = 9] = \"FalseKeyword\";\n SyntaxKind[SyntaxKind[\"StringLiteral\"] = 10] = \"StringLiteral\";\n SyntaxKind[SyntaxKind[\"NumericLiteral\"] = 11] = \"NumericLiteral\";\n SyntaxKind[SyntaxKind[\"LineCommentTrivia\"] = 12] = \"LineCommentTrivia\";\n SyntaxKind[SyntaxKind[\"BlockCommentTrivia\"] = 13] = \"BlockCommentTrivia\";\n SyntaxKind[SyntaxKind[\"LineBreakTrivia\"] = 14] = \"LineBreakTrivia\";\n SyntaxKind[SyntaxKind[\"Trivia\"] = 15] = \"Trivia\";\n SyntaxKind[SyntaxKind[\"Unknown\"] = 16] = \"Unknown\";\n SyntaxKind[SyntaxKind[\"EOF\"] = 17] = \"EOF\";\n})(SyntaxKind || (SyntaxKind = {}));\n/**\n * For a given offset, evaluate the location in the JSON document. Each segment in the location path is either a property name or an array index.\n */\nexport const getLocation = parser.getLocation;\n/**\n * Parses the given text and returns the object the JSON content represents. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result.\n * Therefore, always check the errors list to find out if the input was valid.\n */\nexport const parse = parser.parse;\n/**\n * Parses the given text and returns a tree representation the JSON content. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result.\n */\nexport const parseTree = parser.parseTree;\n/**\n * Finds the node at the given path in a JSON DOM.\n */\nexport const findNodeAtLocation = parser.findNodeAtLocation;\n/**\n * Finds the innermost node at the given offset. If includeRightBound is set, also finds nodes that end at the given offset.\n */\nexport const findNodeAtOffset = parser.findNodeAtOffset;\n/**\n * Gets the JSON path of the given JSON DOM node\n */\nexport const getNodePath = parser.getNodePath;\n/**\n * Evaluates the JavaScript object of the given JSON DOM node\n */\nexport const getNodeValue = parser.getNodeValue;\n/**\n * Parses the given text and invokes the visitor functions for each object, array and literal reached.\n */\nexport const visit = parser.visit;\n/**\n * Takes JSON with JavaScript-style comments and remove\n * them. Optionally replaces every none-newline character\n * of comments with a replaceCharacter\n */\nexport const stripComments = parser.stripComments;\nexport var ParseErrorCode;\n(function (ParseErrorCode) {\n ParseErrorCode[ParseErrorCode[\"InvalidSymbol\"] = 1] = \"InvalidSymbol\";\n ParseErrorCode[ParseErrorCode[\"InvalidNumberFormat\"] = 2] = \"InvalidNumberFormat\";\n ParseErrorCode[ParseErrorCode[\"PropertyNameExpected\"] = 3] = \"PropertyNameExpected\";\n ParseErrorCode[ParseErrorCode[\"ValueExpected\"] = 4] = \"ValueExpected\";\n ParseErrorCode[ParseErrorCode[\"ColonExpected\"] = 5] = \"ColonExpected\";\n ParseErrorCode[ParseErrorCode[\"CommaExpected\"] = 6] = \"CommaExpected\";\n ParseErrorCode[ParseErrorCode[\"CloseBraceExpected\"] = 7] = \"CloseBraceExpected\";\n ParseErrorCode[ParseErrorCode[\"CloseBracketExpected\"] = 8] = \"CloseBracketExpected\";\n ParseErrorCode[ParseErrorCode[\"EndOfFileExpected\"] = 9] = \"EndOfFileExpected\";\n ParseErrorCode[ParseErrorCode[\"InvalidCommentToken\"] = 10] = \"InvalidCommentToken\";\n ParseErrorCode[ParseErrorCode[\"UnexpectedEndOfComment\"] = 11] = \"UnexpectedEndOfComment\";\n ParseErrorCode[ParseErrorCode[\"UnexpectedEndOfString\"] = 12] = \"UnexpectedEndOfString\";\n ParseErrorCode[ParseErrorCode[\"UnexpectedEndOfNumber\"] = 13] = \"UnexpectedEndOfNumber\";\n ParseErrorCode[ParseErrorCode[\"InvalidUnicode\"] = 14] = \"InvalidUnicode\";\n ParseErrorCode[ParseErrorCode[\"InvalidEscapeCharacter\"] = 15] = \"InvalidEscapeCharacter\";\n ParseErrorCode[ParseErrorCode[\"InvalidCharacter\"] = 16] = \"InvalidCharacter\";\n})(ParseErrorCode || (ParseErrorCode = {}));\nexport function printParseErrorCode(code) {\n switch (code) {\n case 1 /* ParseErrorCode.InvalidSymbol */: return 'InvalidSymbol';\n case 2 /* ParseErrorCode.InvalidNumberFormat */: return 'InvalidNumberFormat';\n case 3 /* ParseErrorCode.PropertyNameExpected */: return 'PropertyNameExpected';\n case 4 /* ParseErrorCode.ValueExpected */: return 'ValueExpected';\n case 5 /* ParseErrorCode.ColonExpected */: return 'ColonExpected';\n case 6 /* ParseErrorCode.CommaExpected */: return 'CommaExpected';\n case 7 /* ParseErrorCode.CloseBraceExpected */: return 'CloseBraceExpected';\n case 8 /* ParseErrorCode.CloseBracketExpected */: return 'CloseBracketExpected';\n case 9 /* ParseErrorCode.EndOfFileExpected */: return 'EndOfFileExpected';\n case 10 /* ParseErrorCode.InvalidCommentToken */: return 'InvalidCommentToken';\n case 11 /* ParseErrorCode.UnexpectedEndOfComment */: return 'UnexpectedEndOfComment';\n case 12 /* ParseErrorCode.UnexpectedEndOfString */: return 'UnexpectedEndOfString';\n case 13 /* ParseErrorCode.UnexpectedEndOfNumber */: return 'UnexpectedEndOfNumber';\n case 14 /* ParseErrorCode.InvalidUnicode */: return 'InvalidUnicode';\n case 15 /* ParseErrorCode.InvalidEscapeCharacter */: return 'InvalidEscapeCharacter';\n case 16 /* ParseErrorCode.InvalidCharacter */: return 'InvalidCharacter';\n }\n return '<unknown ParseErrorCode>';\n}\n/**\n * Computes the edit operations needed to format a JSON document.\n *\n * @param documentText The input text\n * @param range The range to format or `undefined` to format the full content\n * @param options The formatting options\n * @returns The edit operations describing the formatting changes to the original document following the format described in {@linkcode EditResult}.\n * To apply the edit operations to the input, use {@linkcode applyEdits}.\n */\nexport function format(documentText, range, options) {\n return formatter.format(documentText, range, options);\n}\n/**\n * Computes the edit operations needed to modify a value in the JSON document.\n *\n * @param documentText The input text\n * @param path The path of the value to change. The path represents either to the document root, a property or an array item.\n * If the path points to an non-existing property or item, it will be created.\n * @param value The new value for the specified property or item. If the value is undefined,\n * the property or item will be removed.\n * @param options Options\n * @returns The edit operations describing the changes to the original document, following the format described in {@linkcode EditResult}.\n * To apply the edit operations to the input, use {@linkcode applyEdits}.\n */\nexport function modify(text, path, value, options) {\n return edit.setProperty(text, path, value, options);\n}\n/**\n * Applies edits to an input string.\n * @param text The input text\n * @param edits Edit operations following the format described in {@linkcode EditResult}.\n * @returns The text with the applied edits.\n * @throws An error if the edit operations are not well-formed as described in {@linkcode EditResult}.\n */\nexport function applyEdits(text, edits) {\n let sortedEdits = edits.slice(0).sort((a, b) => {\n const diff = a.offset - b.offset;\n if (diff === 0) {\n return a.length - b.length;\n }\n return diff;\n });\n let lastModifiedOffset = text.length;\n for (let i = sortedEdits.length - 1; i >= 0; i--) {\n let e = sortedEdits[i];\n if (e.offset + e.length <= lastModifiedOffset) {\n text = edit.applyEdit(text, e);\n }\n else {\n throw new Error('Overlapping edit');\n }\n lastModifiedOffset = e.offset;\n }\n return text;\n}\n","/**\n * TypeScript scope resolution for validation.\n *\n * Provides functions to determine which directories should be validated\n * based on tsconfig.json settings, ensuring alignment between TypeScript\n * and ESLint validation.\n *\n * @module validation/config/scope\n */\n\nimport * as JSONC from \"jsonc-parser\";\nimport { existsSync, readdirSync, readFileSync } from \"node:fs\";\nimport { isAbsolute, join } from \"node:path\";\n\nimport type { ScopeConfig, ValidationScope } from \"../types\";\nimport { pathPassesValidationFilter } from \"./path-filter\";\n\n// =============================================================================\n// CONSTANTS\n// =============================================================================\n\n/**\n * TSConfig file paths for each validation scope.\n */\nexport const TSCONFIG_FILES = {\n full: \"tsconfig.json\",\n production: \"tsconfig.production.json\",\n} as const;\nconst PATH_SEGMENT_SEPARATOR = \"/\";\nconst GLOB_MARKER = \"*\";\nconst HIDDEN_PATH_PREFIX = \".\";\n\n// =============================================================================\n// DEPENDENCY INJECTION INTERFACES\n// =============================================================================\n\n/**\n * Dependencies for scope resolution.\n *\n * Enables dependency injection for testing without mocking.\n */\nexport interface ScopeDeps {\n readFileSync: typeof readFileSync;\n existsSync: typeof existsSync;\n readdirSync: typeof readdirSync;\n}\n\n/**\n * Default production dependencies.\n */\nexport const defaultScopeDeps: ScopeDeps = {\n readFileSync,\n existsSync,\n readdirSync,\n};\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\ninterface TypeScriptConfig {\n include?: string[];\n exclude?: string[];\n extends?: string | string[];\n}\n\nfunction resolveProjectPath(projectRoot: string, path: string): string {\n return isAbsolute(path) ? path : join(projectRoot, path);\n}\n\n// =============================================================================\n// INTERNAL FUNCTIONS\n// =============================================================================\n\n/**\n * Parse TypeScript configuration using proper JSONC parser.\n *\n * @param configPath - Path to tsconfig file\n * @param deps - Injectable dependencies\n * @returns Parsed TypeScript configuration\n */\nexport function parseTypeScriptConfig(\n configPath: string,\n deps: ScopeDeps = defaultScopeDeps,\n): TypeScriptConfig {\n try {\n const configContent = deps.readFileSync(configPath, \"utf-8\");\n const parsed = JSONC.parse(configContent) as TypeScriptConfig;\n return parsed;\n } catch {\n // Fallback: return minimal config and let directory detection work\n return {\n include: [\"**/*.ts\", \"**/*.tsx\"],\n exclude: [\"node_modules/**\", \".pnpm-store/**\", \"dist/**\"],\n };\n }\n}\n\n/**\n * Resolve complete TypeScript configuration including extends.\n *\n * @param scope - Validation scope\n * @param deps - Injectable dependencies\n * @returns Resolved TypeScript configuration\n */\nexport function resolveTypeScriptConfig(\n scope: ValidationScope,\n projectRoot: string,\n deps: ScopeDeps = defaultScopeDeps,\n): TypeScriptConfig {\n const configFile = TSCONFIG_FILES[scope];\n const config = parseTypeScriptConfig(resolveProjectPath(projectRoot, configFile), deps);\n\n if (config.extends) {\n const baseConfigs = normalizeExtends(config.extends)\n .map((extendedConfig) => parseTypeScriptConfig(resolveProjectPath(projectRoot, extendedConfig), deps));\n // TypeScript applies later extended configs after earlier ones; include\n // and exclude arrays replace instead of merge, so the last inherited\n // field wins.\n const inheritedInclude = [...baseConfigs].reverse().find((baseConfig) => baseConfig.include !== undefined)?.include\n ?? [];\n const inheritedExclude = [...baseConfigs].reverse().find((baseConfig) => baseConfig.exclude !== undefined)?.exclude\n ?? [];\n return {\n include: config.include ?? inheritedInclude,\n exclude: config.exclude ?? inheritedExclude,\n };\n }\n\n return {\n include: config.include ?? [],\n exclude: config.exclude ?? [],\n };\n}\n\nfunction normalizeExtends(extendsConfig: string | string[]): readonly string[] {\n return Array.isArray(extendsConfig) ? extendsConfig : [extendsConfig];\n}\n\n/**\n * Check if a directory contains TypeScript files recursively.\n *\n * @param dirPath - Directory to check\n * @param maxDepth - Maximum recursion depth\n * @param deps - Injectable dependencies\n * @returns True if directory contains TypeScript files\n */\nexport function hasTypeScriptFilesRecursive(\n dirPath: string,\n maxDepth: number = 2,\n deps: ScopeDeps = defaultScopeDeps,\n): boolean {\n if (maxDepth <= 0) return false;\n\n try {\n const items = deps.readdirSync(dirPath, { withFileTypes: true });\n\n // Check for TypeScript files in current directory\n const hasDirectTsFiles = items.some(\n (item) => item.isFile() && (item.name.endsWith(\".ts\") || item.name.endsWith(\".tsx\")),\n );\n\n if (hasDirectTsFiles) return true;\n\n // Check subdirectories (limited depth to avoid performance issues)\n const subdirs = items.filter((item) => item.isDirectory() && !item.name.startsWith(\".\"));\n for (const subdir of subdirs.slice(0, 5)) {\n // Limit to first 5 subdirs\n if (hasTypeScriptFilesRecursive(join(dirPath, subdir.name), maxDepth - 1, deps)) {\n return true;\n }\n }\n\n return false;\n } catch {\n return false;\n }\n}\n\n/**\n * Get top-level directories containing TypeScript files.\n *\n * @param config - TypeScript configuration\n * @param deps - Injectable dependencies\n * @returns Array of directory names\n */\nexport function getTopLevelDirectoriesWithTypeScript(\n config: TypeScriptConfig,\n projectRoot: string,\n deps: ScopeDeps = defaultScopeDeps,\n): string[] {\n const allTopLevelItems = deps.readdirSync(projectRoot, { withFileTypes: true });\n const directories = new Set<string>();\n\n // Find all top-level directories\n const topLevelDirs = allTopLevelItems\n .filter((item) => item.isDirectory())\n .map((item) => item.name)\n .filter((name) => !name.startsWith(\".\"));\n\n // Check if each directory should be included based on tsconfig include/exclude patterns\n for (const dir of topLevelDirs) {\n // Check if directory is explicitly excluded\n const isExcluded = config.exclude?.some((pattern) => {\n // Handle directory-recursive patterns like \"docs/**/*\"\n if (pattern.includes(\"/**\")) {\n const dirPattern = pattern.split(\"/**\")[0];\n return dirPattern === dir;\n }\n // Handle exact matches and directory patterns\n return pattern === dir || pattern.startsWith(dir + \"/\") || pattern === dir + \"/**\";\n });\n\n if (!isExcluded) {\n // Check if directory has TypeScript files\n try {\n const hasTypeScriptFiles = hasTypeScriptFilesRecursive(join(projectRoot, dir), 2, deps);\n if (hasTypeScriptFiles) {\n directories.add(dir);\n }\n } catch {\n // Directory access error, skip\n continue;\n }\n }\n }\n\n // Also add explicitly mentioned directories from include patterns\n if (config.include) {\n for (const pattern of config.include) {\n // Extract directory from patterns like \"scripts/**/*.ts\", \"tests/**/*.tsx\"\n if (pattern.includes(PATH_SEGMENT_SEPARATOR)) {\n const topLevelDir = getLiteralTopLevelPatternDirectory(pattern);\n if (topLevelDir) {\n directories.add(topLevelDir);\n }\n }\n }\n }\n\n return Array.from(directories).sort();\n}\n\nfunction getLiteralTopLevelPatternDirectory(pattern: string): string | null {\n const topLevelDir = pattern.split(PATH_SEGMENT_SEPARATOR)[0];\n if (!topLevelDir || topLevelDir.includes(GLOB_MARKER) || topLevelDir.startsWith(HIDDEN_PATH_PREFIX)) {\n return null;\n }\n return topLevelDir;\n}\n\nfunction filterActiveIncludePatterns(\n patterns: readonly string[],\n excludePatterns: readonly string[],\n projectRoot: string,\n deps: ScopeDeps,\n): string[] {\n return patterns\n .filter((pattern) => {\n const topLevelDir = getLiteralTopLevelPatternDirectory(pattern);\n return topLevelDir === null || deps.existsSync(join(projectRoot, topLevelDir));\n })\n .filter((pattern) => pathPassesValidationFilter(pattern, { exclude: excludePatterns }));\n}\n\n/**\n * Get validation directories based on tsconfig files.\n *\n * @param scope - Validation scope\n * @param deps - Injectable dependencies\n * @returns Array of directory names to validate\n */\nexport function getValidationDirectories(\n scope: ValidationScope,\n projectRoot: string,\n deps: ScopeDeps = defaultScopeDeps,\n): string[] {\n // Get TypeScript configuration for the specified mode\n const config = resolveTypeScriptConfig(scope, projectRoot, deps);\n\n // Get directories that contain TypeScript files and respect tsconfig exclude patterns\n const configDirectories = getTopLevelDirectoriesWithTypeScript(config, projectRoot, deps);\n\n // Only include directories that actually exist\n const existingDirectories = configDirectories.filter((dir) => deps.existsSync(join(projectRoot, dir)));\n\n return existingDirectories;\n}\n\n/**\n * Get authoritative validation scope configuration.\n *\n * This is the main entry point for scope resolution. Returns a ScopeConfig\n * object that can be used to configure validation tools.\n *\n * @param scope - Validation scope\n * @param deps - Injectable dependencies\n * @returns Scope configuration\n *\n * @example\n * ```typescript\n * const scopeConfig = getTypeScriptScope(\"full\", projectRoot);\n * console.log(scopeConfig.directories); // [\"src\", \"tests\", \"scripts\"]\n * ```\n */\nexport function getTypeScriptScope(\n scope: ValidationScope,\n projectRoot: string,\n deps: ScopeDeps = defaultScopeDeps,\n): ScopeConfig {\n // Use validation-focused directory selection\n const directories = getValidationDirectories(scope, projectRoot, deps);\n\n // Read TypeScript config for patterns\n const config = resolveTypeScriptConfig(scope, projectRoot, deps);\n\n return {\n directories,\n filePatterns: filterActiveIncludePatterns(config.include ?? [], config.exclude ?? [], projectRoot, deps),\n excludePatterns: config.exclude ?? [],\n };\n}\n","/**\n * Tool discovery for validation infrastructure.\n *\n * Discovers validation tools (eslint, tsc, madge, etc.) using a three-tier\n * priority system: bundled → project → global.\n *\n * @module validation/discovery/tool-finder\n */\n\nimport { execSync } from \"node:child_process\";\nimport fs from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport path from \"node:path\";\n\nimport { TOOL_DISCOVERY, type ToolSource } from \"./constants\";\n\n/**\n * Information about a found tool.\n */\nexport interface ToolLocation {\n /** The tool name */\n tool: string;\n /** Absolute path to the tool executable or package */\n path: string;\n /** Where the tool was found */\n source: ToolSource;\n}\n\n/**\n * Information about a tool that was not found.\n */\nexport interface ToolNotFound {\n /** The tool name that was searched for */\n tool: string;\n /** Human-readable reason why the tool was not found */\n reason: string;\n}\n\n/**\n * Result of tool discovery - either found with location or not found with reason.\n */\nexport type ToolDiscoveryResult =\n | { found: true; location: ToolLocation }\n | { found: false; notFound: ToolNotFound };\n\n/**\n * Dependencies for tool discovery.\n * Enables testing without mocking by accepting controlled implementations.\n */\nexport interface ToolDiscoveryDeps {\n /**\n * Resolve a module path, returns the resolved path or null if not found.\n * @param modulePath - The module path to resolve (e.g., \"eslint/package.json\")\n */\n resolveModule: (modulePath: string) => string | null;\n\n /**\n * Check if a file exists at the given path.\n * @param filePath - The path to check\n */\n existsSync: (filePath: string) => boolean;\n\n /**\n * Find an executable in the system PATH.\n * @param tool - The tool name to find\n * @returns The absolute path to the tool, or null if not found\n */\n whichSync: (tool: string) => string | null;\n}\n\n/**\n * Create a require function for resolving modules.\n * Uses import.meta.url to create a require that resolves from this package.\n */\nconst require = createRequire(import.meta.url);\n\n/**\n * Default production dependencies for tool discovery.\n */\nexport const defaultToolDiscoveryDeps: ToolDiscoveryDeps = {\n resolveModule: (modulePath: string): string | null => {\n try {\n return require.resolve(modulePath);\n } catch {\n return null;\n }\n },\n\n existsSync: fs.existsSync,\n\n whichSync: (tool: string): string | null => {\n try {\n const result = execSync(`which ${tool}`, {\n encoding: \"utf-8\",\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n return result.trim() || null;\n } catch {\n return null;\n }\n },\n};\n\n/**\n * Options for tool discovery.\n */\nexport interface DiscoverToolOptions {\n /**\n * Project root directory for checking project-local node_modules.\n * Defaults to current working directory.\n */\n projectRoot?: string;\n\n /**\n * Dependencies for tool discovery.\n * Defaults to production dependencies.\n */\n deps?: ToolDiscoveryDeps;\n}\n\n/**\n * Discover a validation tool using three-tier priority.\n *\n * Discovery order:\n * 1. **Bundled**: Check if the tool is bundled with spx-cli via require.resolve\n * 2. **Project**: Check project's node_modules/.bin directory\n * 3. **Global**: Check system PATH via `which` command\n *\n * @param tool - The tool name to discover (e.g., \"eslint\", \"typescript\", \"madge\")\n * @param options - Discovery options including projectRoot and dependencies\n * @returns Discovery result with found location or not found reason\n *\n * @example\n * ```typescript\n * const result = await discoverTool(\"eslint\");\n * if (result.found) {\n * console.log(`Found ${result.location.tool} at ${result.location.path}`);\n * console.log(`Source: ${result.location.source}`);\n * } else {\n * console.log(`Not found: ${result.notFound.reason}`);\n * }\n * ```\n */\nexport async function discoverTool(\n tool: string,\n options: DiscoverToolOptions = {},\n): Promise<ToolDiscoveryResult> {\n const { projectRoot = process.cwd(), deps = defaultToolDiscoveryDeps } = options;\n\n // Tier 1: Check if bundled with spx-cli\n const bundledPath = deps.resolveModule(`${tool}/package.json`);\n if (bundledPath) {\n return {\n found: true,\n location: {\n tool,\n path: path.dirname(bundledPath),\n source: TOOL_DISCOVERY.SOURCES.BUNDLED,\n },\n };\n }\n\n // Tier 2: Check project's node_modules/.bin\n const projectBinPath = path.join(projectRoot, \"node_modules\", \".bin\", tool);\n if (deps.existsSync(projectBinPath)) {\n return {\n found: true,\n location: {\n tool,\n path: projectBinPath,\n source: TOOL_DISCOVERY.SOURCES.PROJECT,\n },\n };\n }\n\n // Tier 3: Check system PATH\n const globalPath = deps.whichSync(tool);\n if (globalPath) {\n return {\n found: true,\n location: {\n tool,\n path: globalPath,\n source: TOOL_DISCOVERY.SOURCES.GLOBAL,\n },\n };\n }\n\n // Not found anywhere\n return {\n found: false,\n notFound: {\n tool,\n reason: TOOL_DISCOVERY.MESSAGES.NOT_FOUND_REASON(tool),\n },\n };\n}\n\n/**\n * Format a graceful skip message for when a tool is not found.\n *\n * @param stepName - The name of the validation step being skipped\n * @param result - The tool discovery result\n * @returns Formatted skip message, or empty string if tool was found\n *\n * @example\n * ```typescript\n * const result = await discoverTool(\"madge\");\n * const message = formatSkipMessage(\"Circular dependency check\", result);\n * // \"⏭ Skipping Circular dependency check (madge not available)\"\n * ```\n */\nexport function formatSkipMessage(\n stepName: string,\n result: ToolDiscoveryResult,\n): string {\n if (result.found) {\n return \"\";\n }\n return TOOL_DISCOVERY.MESSAGES.SKIP_FORMAT(stepName, result.notFound.tool);\n}\n","/**\n * Constants for tool discovery.\n * @module validation/discovery/constants\n */\n\n/**\n * Tool discovery constants.\n * Using constants ensures DRY principle and makes tests verify behavior via constants.\n */\nexport const TOOL_DISCOVERY = {\n /** Tool source identifiers */\n SOURCES: {\n /** Tool bundled with spx-cli */\n BUNDLED: \"bundled\",\n /** Tool in project's node_modules */\n PROJECT: \"project\",\n /** Tool in system PATH */\n GLOBAL: \"global\",\n } as const,\n\n /** Message templates */\n MESSAGES: {\n /** Prefix for skip messages */\n SKIP_PREFIX: \"\\u23ED\", // ⏭ emoji\n /**\n * Format not found reason message.\n * @param tool - The tool name that was not found\n */\n NOT_FOUND_REASON: (tool: string): string =>\n `${tool} not found in bundled deps, project node_modules, or system PATH`,\n /**\n * Format skip message for graceful degradation.\n * @param step - The validation step name\n * @param tool - The tool that was not found\n */\n SKIP_FORMAT: (step: string, tool: string): string =>\n `${TOOL_DISCOVERY.MESSAGES.SKIP_PREFIX} Skipping ${step} (${tool} not available)`,\n },\n} as const;\n\n/** Type for tool source */\nexport type ToolSource = (typeof TOOL_DISCOVERY.SOURCES)[keyof typeof TOOL_DISCOVERY.SOURCES];\n","/**\n * Circular dependency validation step.\n *\n * Uses madge to detect circular imports in the codebase.\n *\n * @module validation/steps/circular\n */\n\nimport madge from \"madge\";\nimport { join } from \"node:path\";\n\nimport { TSCONFIG_FILES } from \"../config/scope\";\nimport type { CircularDependencyResult, ScopeConfig, ValidationScope } from \"../types\";\n\n// =============================================================================\n// DEPENDENCY INJECTION INTERFACES\n// =============================================================================\n\n/**\n * Dependencies for circular dependency validation.\n *\n * Enables dependency injection for testing.\n */\nexport interface CircularDeps {\n madge: typeof madge;\n}\n\nexport const CIRCULAR_DEPS_KEYS = {\n MADGE: \"madge\",\n} as const;\n\nexport type CircularDependencyGraphRunner = CircularDeps[typeof CIRCULAR_DEPS_KEYS.MADGE];\n\n/**\n * Default production dependencies.\n */\nexport const defaultCircularDeps: CircularDeps = {\n [CIRCULAR_DEPS_KEYS.MADGE]: madge,\n};\n\n// =============================================================================\n// VALIDATION FUNCTION\n// =============================================================================\n\n/**\n * Validate circular dependencies using TypeScript-derived scope.\n *\n * @param scope - Validation scope\n * @param typescriptScope - Scope configuration from tsconfig\n * @param projectRoot - Project root for Madge input and tsconfig resolution\n * @param deps - Injectable dependencies\n * @returns Result with success status and any circular dependencies found\n *\n * @example\n * ```typescript\n * const result = await validateCircularDependencies(\"full\", scopeConfig);\n * if (!result.success) {\n * console.error(\"Found circular dependencies:\", result.circularDependencies);\n * }\n * ```\n */\nexport async function validateCircularDependencies(\n scope: ValidationScope,\n typescriptScope: ScopeConfig,\n projectRoot: string,\n deps: CircularDeps = defaultCircularDeps,\n): Promise<CircularDependencyResult> {\n try {\n // Use TypeScript-derived directories for perfect scope alignment\n const analyzeDirectories = typescriptScope.directories.map((directory) => join(projectRoot, directory));\n\n if (analyzeDirectories.length === 0) {\n return { success: true };\n }\n\n // Use the appropriate TypeScript config based on scope\n const tsConfigFile = join(projectRoot, TSCONFIG_FILES[scope]);\n\n // Convert tsconfig exclude patterns to madge excludeRegExp\n const excludeRegExps = typescriptScope.excludePatterns.map((pattern) => {\n // Remove trailing /**/* or /* for cleaner matching\n const cleanPattern = pattern.replace(/\\/\\*\\*?\\/\\*$/, \"\");\n // Escape regex special chars and create regex\n const escaped = cleanPattern.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n return new RegExp(escaped);\n });\n\n const result = await deps.madge(analyzeDirectories, {\n baseDir: projectRoot,\n fileExtensions: [\"ts\", \"tsx\"],\n tsConfig: tsConfigFile,\n excludeRegExp: excludeRegExps,\n });\n\n const circular = result.circular();\n\n if (circular.length === 0) {\n return { success: true };\n } else {\n return {\n success: false,\n error: `Found ${circular.length} circular dependency cycle(s)`,\n circularDependencies: circular,\n };\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n return { success: false, error: errorMessage };\n }\n}\n","/**\n * Circular dependency check command.\n *\n * Runs madge to detect circular dependencies.\n */\nimport { resolveConfig } from \"@/config/index\";\nimport {\n VALIDATION_PATH_TOOL_SUBSECTIONS,\n type ValidationConfig,\n validationConfigDescriptor,\n} from \"@/validation/config/descriptor\";\nimport { applyValidationPathFilterToScope, validationPathFilterForTool } from \"@/validation/config/path-filter\";\nimport { getTypeScriptScope } from \"@/validation/config/scope\";\nimport { detectTypeScript, discoverTool, formatSkipMessage } from \"@/validation/discovery/index\";\nimport { validateCircularDependencies } from \"@/validation/steps/circular\";\nimport {\n formatTypeScriptAbsentSkipMessage,\n VALIDATION_COMMAND_OUTPUT,\n VALIDATION_STAGE_DISPLAY_NAMES,\n} from \"./messages\";\nimport type { CircularCommandOptions, ValidationCommandResult } from \"./types\";\n\nconst TYPESCRIPT_ABSENT_MESSAGE = formatTypeScriptAbsentSkipMessage(VALIDATION_STAGE_DISPLAY_NAMES.CIRCULAR);\nconst CIRCULAR_CONFIG_ERROR_MESSAGE = `${VALIDATION_STAGE_DISPLAY_NAMES.CIRCULAR}: ✗ config error`;\nexport const CIRCULAR_DEPENDENCY_OUTPUT = {\n FOUND: VALIDATION_COMMAND_OUTPUT.CIRCULAR_FOUND,\n} as const;\n\n/**\n * Check for circular dependencies.\n *\n * Gates madge execution on TypeScript language detection: madge walks the\n * TypeScript import graph and has nothing to examine in non-TypeScript\n * projects.\n *\n * @param options - Command options\n * @returns Command result with exit code and output\n */\nexport async function circularCommand(options: CircularCommandOptions): Promise<ValidationCommandResult> {\n const { cwd, quiet } = options;\n const startTime = Date.now();\n\n // Gate 1: language detection. No TypeScript = skip cleanly.\n const tsDetection = detectTypeScript(cwd);\n if (!tsDetection.present) {\n return {\n exitCode: 0,\n output: quiet ? \"\" : TYPESCRIPT_ABSENT_MESSAGE,\n durationMs: Date.now() - startTime,\n };\n }\n\n // Gate 2: tool discovery.\n const toolResult = await discoverTool(\"madge\", { projectRoot: cwd });\n if (!toolResult.found) {\n const skipMessage = formatSkipMessage(\"circular dependency check\", toolResult);\n return { exitCode: 0, output: skipMessage, durationMs: Date.now() - startTime };\n }\n\n const loaded = await resolveConfig(cwd, [validationConfigDescriptor]);\n if (!loaded.ok) {\n return {\n exitCode: 1,\n output: `${CIRCULAR_CONFIG_ERROR_MESSAGE} — ${loaded.error}`,\n durationMs: Date.now() - startTime,\n };\n }\n const validationConfig = loaded.value[validationConfigDescriptor.section] as ValidationConfig;\n const scopeConfig = applyValidationPathFilterToScope(\n getTypeScriptScope(\"full\", cwd),\n validationPathFilterForTool(validationConfig.paths, VALIDATION_PATH_TOOL_SUBSECTIONS.CIRCULAR),\n );\n\n // Run circular dependency validation\n const result = await validateCircularDependencies(\"full\", scopeConfig, cwd);\n const durationMs = Date.now() - startTime;\n\n // Map result to command output\n if (result.success) {\n const output = quiet ? \"\" : VALIDATION_COMMAND_OUTPUT.CIRCULAR_NONE_FOUND;\n return { exitCode: 0, output, durationMs };\n } else {\n // Format circular dependency output\n let output = result.error ?? CIRCULAR_DEPENDENCY_OUTPUT.FOUND;\n if (result.circularDependencies && result.circularDependencies.length > 0) {\n const cycles = result.circularDependencies\n .map((cycle) => ` ${cycle.join(\" → \")}`)\n .join(\"\\n\");\n output = `${CIRCULAR_DEPENDENCY_OUTPUT.FOUND}:\\n${cycles}`;\n }\n return { exitCode: 1, output, durationMs };\n }\n}\n","/**\n * Knip validation step.\n *\n * Detects unused exports, dependencies, and files using knip.\n *\n * @module validation/steps/knip\n */\n\nimport { existsSync } from \"node:fs\";\nimport { mkdtemp, rm, writeFile } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { isAbsolute, join } from \"node:path\";\n\nimport { lifecycleProcessRunner, type ProcessRunner, spawnManagedSubprocess } from \"@/lib/process-lifecycle\";\nimport { TSCONFIG_FILES } from \"@/validation/config/scope\";\nimport type { ScopeConfig } from \"../types\";\n\n// =============================================================================\n// DEFAULT DEPENDENCIES\n// =============================================================================\n\n/**\n * Default production process runner for Knip.\n */\nexport const defaultKnipProcessRunner: ProcessRunner = lifecycleProcessRunner;\nexport const KNIP_COMMAND_TOKENS = {\n COMMAND: \"knip\",\n TSCONFIG_FLAG: \"--tsConfig\",\n USE_TSCONFIG_FILES_FLAG: \"--use-tsconfig-files\",\n} as const;\n\nexport interface KnipDeps {\n readonly existsSync: typeof existsSync;\n readonly mkdtemp: typeof mkdtemp;\n readonly rm: typeof rm;\n readonly writeFile: typeof writeFile;\n}\n\nconst defaultKnipDeps: KnipDeps = {\n existsSync,\n mkdtemp,\n rm,\n writeFile,\n};\n\nexport interface KnipValidationContext {\n readonly projectRoot: string;\n readonly typescriptScope: ScopeConfig;\n}\n\n// =============================================================================\n// VALIDATION FUNCTION\n// =============================================================================\n\n/**\n * Validate unused code using knip with TypeScript-derived scope.\n *\n * @param context - Knip validation context\n * @param runner - Injectable process runner\n * @returns Promise resolving to validation result\n *\n * @example\n * ```typescript\n * const result = await validateKnip({ projectRoot, typescriptScope: scopeConfig });\n * if (!result.success) {\n * console.error(\"Knip found issues:\", result.error);\n * }\n * ```\n */\nexport async function validateKnip(\n context: KnipValidationContext,\n runner: ProcessRunner = defaultKnipProcessRunner,\n deps: KnipDeps = defaultKnipDeps,\n): Promise<{\n success: boolean;\n error?: string;\n}> {\n try {\n const { projectRoot, typescriptScope } = context;\n // Use TypeScript-derived directories for perfect scope alignment\n const analyzeDirectories = typescriptScope.directories;\n\n if (analyzeDirectories.length === 0) {\n return { success: true };\n }\n\n return await runKnipSubprocess(projectRoot, typescriptScope, runner, deps);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n return { success: false, error: errorMessage };\n }\n}\n\nasync function runKnipSubprocess(\n projectRoot: string,\n typescriptScope: ScopeConfig,\n runner: ProcessRunner,\n deps: KnipDeps,\n): Promise<{ success: boolean; error?: string }> {\n const scopedTsconfig = typescriptScope.filteredByValidationPaths\n ? await createScopedKnipTsconfig(projectRoot, typescriptScope, deps)\n : undefined;\n const localBin = join(projectRoot, \"node_modules\", \".bin\", \"knip\");\n const binary = deps.existsSync(localBin) ? localBin : \"npx\";\n const baseArgs = scopedTsconfig === undefined\n ? []\n : [\n KNIP_COMMAND_TOKENS.USE_TSCONFIG_FILES_FLAG,\n KNIP_COMMAND_TOKENS.TSCONFIG_FLAG,\n scopedTsconfig.configPath,\n ];\n const args = binary === \"npx\" ? [KNIP_COMMAND_TOKENS.COMMAND, ...baseArgs] : baseArgs;\n const knipProcess = spawnManagedSubprocess(runner, binary, args, {\n cwd: projectRoot,\n });\n const cleanup = scopedTsconfig?.cleanup ?? (async () => {});\n let cleanupStarted = false;\n let resultResolved = false;\n\n const cleanupOnce = async () => {\n if (cleanupStarted) {\n return;\n }\n cleanupStarted = true;\n await cleanup();\n };\n\n let knipOutput = \"\";\n let knipError = \"\";\n\n knipProcess.stdout?.on(\"data\", (data: Buffer) => {\n knipOutput += data.toString();\n });\n\n knipProcess.stderr?.on(\"data\", (data: Buffer) => {\n knipError += data.toString();\n });\n\n return new Promise((resolve) => {\n const resolveAfterCleanup = (result: { success: boolean; error?: string }) => {\n if (resultResolved) {\n return;\n }\n resultResolved = true;\n void cleanupOnce().finally(() => resolve(result));\n };\n\n knipProcess.on(\"close\", (code) => {\n if (code === 0) {\n resolveAfterCleanup({ success: true });\n } else {\n const errorOutput = knipOutput || knipError || \"Unused code detected\";\n resolveAfterCleanup({\n success: false,\n error: errorOutput,\n });\n }\n });\n\n knipProcess.on(\"error\", (error) => {\n resolveAfterCleanup({ success: false, error: error.message });\n });\n });\n}\n\nasync function createScopedKnipTsconfig(\n projectRoot: string,\n typescriptScope: ScopeConfig,\n deps: KnipDeps,\n): Promise<{ configPath: string; cleanup: () => Promise<void> }> {\n const tempDir = await deps.mkdtemp(join(tmpdir(), \"validate-knip-\"));\n const configPath = join(tempDir, TSCONFIG_FILES.full);\n const toProjectPathPattern = (pattern: string) => isAbsolute(pattern) ? pattern : join(projectRoot, pattern);\n const project = typescriptScope.filePatterns.length > 0\n ? typescriptScope.filePatterns\n : typescriptScope.directories.map((directory) => `${directory}/**/*.{js,ts,tsx}`);\n const config = {\n extends: join(projectRoot, TSCONFIG_FILES.full),\n include: project.map(toProjectPathPattern),\n exclude: typescriptScope.excludePatterns.map(toProjectPathPattern),\n };\n await deps.writeFile(configPath, JSON.stringify(config, null, 2));\n return {\n configPath,\n cleanup: () => deps.rm(tempDir, { recursive: true, force: true }),\n };\n}\n","/**\n * Knip command for detecting unused code.\n *\n * Runs knip to find unused exports, dependencies, and files.\n */\nimport { resolveConfig } from \"@/config/index\";\nimport {\n VALIDATION_PATH_TOOL_SUBSECTIONS,\n type ValidationConfig,\n validationConfigDescriptor,\n} from \"@/validation/config/descriptor\";\nimport { applyValidationPathFilterToScope, validationPathFilterForTool } from \"@/validation/config/path-filter\";\nimport { getTypeScriptScope } from \"@/validation/config/scope\";\nimport { discoverTool, formatSkipMessage } from \"@/validation/discovery/index\";\nimport { validateKnip } from \"@/validation/steps/knip\";\nimport { VALIDATION_COMMAND_OUTPUT } from \"./messages\";\nimport type { KnipCommandOptions, ValidationCommandResult } from \"./types\";\n\n/**\n * Detect unused code with knip.\n *\n * @param options - Command options\n * @returns Command result with exit code and output\n */\nexport async function knipCommand(options: KnipCommandOptions): Promise<ValidationCommandResult> {\n const { cwd, quiet } = options;\n const startTime = Date.now();\n\n const loaded = await resolveConfig(cwd, [validationConfigDescriptor]);\n if (!loaded.ok) {\n return {\n exitCode: 1,\n output: `${VALIDATION_COMMAND_OUTPUT.KNIP_CONFIG_ERROR} — ${loaded.error}`,\n durationMs: Date.now() - startTime,\n };\n }\n const validationConfig = loaded.value[validationConfigDescriptor.section] as ValidationConfig;\n\n if (!validationConfig.knip.enabled) {\n const output = quiet ? \"\" : VALIDATION_COMMAND_OUTPUT.KNIP_DISABLED;\n return { exitCode: 0, output, durationMs: Date.now() - startTime };\n }\n\n // Discover knip\n const toolResult = await discoverTool(\"knip\", { projectRoot: cwd });\n if (!toolResult.found) {\n const skipMessage = formatSkipMessage(\"unused code detection\", toolResult);\n return { exitCode: 0, output: skipMessage, durationMs: Date.now() - startTime };\n }\n\n const scopeConfig = applyValidationPathFilterToScope(\n getTypeScriptScope(\"full\", cwd),\n validationPathFilterForTool(validationConfig.paths, VALIDATION_PATH_TOOL_SUBSECTIONS.KNIP),\n );\n\n // Run knip validation\n const result = await validateKnip({ projectRoot: cwd, typescriptScope: scopeConfig });\n const durationMs = Date.now() - startTime;\n\n // Map result to command output\n if (result.success) {\n const output = quiet ? \"\" : VALIDATION_COMMAND_OUTPUT.KNIP_SUCCESS;\n return { exitCode: 0, output, durationMs };\n } else {\n const output = result.error ?? VALIDATION_COMMAND_OUTPUT.KNIP_FAILURE;\n return { exitCode: 1, output, durationMs };\n }\n}\n","/**\n * ESLint validation step.\n *\n * Validates code against ESLint rules with automatic TypeScript scope alignment.\n *\n * @module validation/steps/eslint\n */\n\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nimport { lifecycleProcessRunner, type ProcessRunner, spawnManagedSubprocess } from \"@/lib/process-lifecycle\";\nimport { validateLintPolicy } from \"@/validation/lint-policy\";\nimport type { ExecutionMode, ScopeConfig, ValidationContext, ValidationScope } from \"../types\";\nimport { EXECUTION_MODES, VALIDATION_SCOPES } from \"../types\";\nimport {\n defaultValidationSubprocessOutputStreams,\n forwardValidationSubprocessOutput,\n VALIDATION_SUBPROCESS_EVENTS,\n type ValidationSubprocessOutputStreams,\n} from \"./subprocess-output\";\n\n// =============================================================================\n// DEFAULT DEPENDENCIES\n// =============================================================================\n\n/**\n * Default production process runner for ESLint.\n */\nexport const defaultEslintProcessRunner: ProcessRunner = lifecycleProcessRunner;\n\n// =============================================================================\n// PURE ARGUMENT BUILDER\n// =============================================================================\n\n/**\n * Default ESLint flat config file name, used when the caller does not supply\n * one. Callers should prefer passing the config file reported by language\n * detection.\n */\nexport const DEFAULT_ESLINT_CONFIG_FILE = \"eslint.config.ts\";\nexport const ESLINT_COMMAND_TOKENS = {\n COMMAND: \"eslint\",\n CONFIG_FLAG: \"--config\",\n CURRENT_DIRECTORY: \".\",\n FILE_SEPARATOR: \"--\",\n FIX_FLAG: \"--fix\",\n IGNORE_PATTERN_FLAG: \"--ignore-pattern\",\n} as const;\nexport const ESLINT_LOCAL_BIN_SEGMENTS = [\"node_modules\", \".bin\", ESLINT_COMMAND_TOKENS.COMMAND] as const;\n\n/**\n * Build ESLint CLI arguments based on validation context.\n *\n * Pure function for testability - can be verified at Level 1.\n *\n * @param context - Context for building arguments\n * @returns Array of ESLint CLI arguments\n *\n * @example\n * ```typescript\n * const args = buildEslintArgs({\n * validatedFiles: [\"src/index.ts\"],\n * mode: \"write\",\n * configFile: \"eslint.config.ts\",\n * });\n * // Returns: [\"eslint\", \"--config\", \"eslint.config.ts\", \"--\", \"src/index.ts\"]\n * ```\n */\nexport function buildEslintArgs(context: {\n validatedFiles?: string[];\n mode?: ExecutionMode;\n configFile?: string;\n scope: ValidationScope;\n scopeConfig?: ScopeConfig;\n}): string[] {\n const { validatedFiles, mode, configFile = DEFAULT_ESLINT_CONFIG_FILE, scope, scopeConfig } = context;\n const fixArg = mode === EXECUTION_MODES.WRITE ? [ESLINT_COMMAND_TOKENS.FIX_FLAG] : [];\n\n if (validatedFiles && validatedFiles.length > 0) {\n // Explicit file scope is already the caller's narrowed target and takes\n // precedence over broad validation scope selection.\n return [\n ESLINT_COMMAND_TOKENS.COMMAND,\n ESLINT_COMMAND_TOKENS.CONFIG_FLAG,\n configFile,\n ...fixArg,\n ESLINT_COMMAND_TOKENS.FILE_SEPARATOR,\n ...validatedFiles,\n ];\n }\n const targetArgs = scope === VALIDATION_SCOPES.PRODUCTION || scopeConfig?.filteredByValidationPathIncludes\n ? buildProductionTargetArgs(scopeConfig)\n : buildCurrentDirectoryTargetArgs(scopeConfig);\n return [\n ESLINT_COMMAND_TOKENS.COMMAND,\n ...targetArgs,\n ESLINT_COMMAND_TOKENS.CONFIG_FLAG,\n configFile,\n ...fixArg,\n ];\n}\n\nfunction buildCurrentDirectoryTargetArgs(scopeConfig: ScopeConfig | undefined): string[] {\n return [\n ESLINT_COMMAND_TOKENS.CURRENT_DIRECTORY,\n ...(scopeConfig?.filteredByValidationPaths ? buildIgnorePatternArgs(scopeConfig.excludePatterns) : []),\n ];\n}\n\nfunction buildProductionTargetArgs(scopeConfig: ScopeConfig | undefined): string[] {\n const targetPatterns = scopeConfig?.filePatterns.length\n ? scopeConfig.filePatterns\n : [ESLINT_COMMAND_TOKENS.CURRENT_DIRECTORY];\n return [\n ...targetPatterns,\n ...buildIgnorePatternArgs(scopeConfig?.excludePatterns ?? []),\n ];\n}\n\nfunction buildIgnorePatternArgs(patterns: readonly string[]): string[] {\n return patterns.flatMap((pattern) => [ESLINT_COMMAND_TOKENS.IGNORE_PATTERN_FLAG, pattern]);\n}\n\n// =============================================================================\n// VALIDATION FUNCTION\n// =============================================================================\n\n/**\n * Validate ESLint compliance using automatic TypeScript scope alignment.\n *\n * @param context - Validation context\n * @param runner - Injectable process runner\n * @returns Promise resolving to validation result\n *\n * @example\n * ```typescript\n * const result = await validateESLint(context);\n * if (!result.success) {\n * console.error(\"ESLint failed:\", result.error);\n * }\n * ```\n */\nexport async function validateESLint(\n context: ValidationContext,\n runner: ProcessRunner = defaultEslintProcessRunner,\n outputStreams: ValidationSubprocessOutputStreams = defaultValidationSubprocessOutputStreams,\n): Promise<{\n success: boolean;\n error?: string;\n skipped?: boolean;\n}> {\n const { projectRoot, scope, validatedFiles, mode, eslintConfigFile } = context;\n const lintPolicy = validateLintPolicy(projectRoot);\n\n if (!lintPolicy.ok) {\n return { success: false, error: lintPolicy.error };\n }\n\n if (context.scopeConfig.filteredByValidationPathNoMatches) {\n return { success: true, skipped: true };\n }\n\n const eslintArgs = buildEslintArgs({\n validatedFiles,\n mode,\n configFile: eslintConfigFile,\n scope,\n scopeConfig: context.scopeConfig,\n });\n\n return new Promise((resolve) => {\n const localBin = join(projectRoot, ...ESLINT_LOCAL_BIN_SEGMENTS);\n const binary = existsSync(localBin) ? localBin : \"npx\";\n const spawnArgs = binary === \"npx\" ? eslintArgs : eslintArgs.slice(1);\n const eslintProcess = spawnManagedSubprocess(runner, binary, spawnArgs, {\n cwd: projectRoot,\n });\n forwardValidationSubprocessOutput(eslintProcess, outputStreams);\n\n eslintProcess.on(VALIDATION_SUBPROCESS_EVENTS.CLOSE, (code) => {\n if (code === 0) {\n resolve({ success: true });\n } else {\n resolve({ success: false, error: `ESLint exited with code ${code}` });\n }\n });\n\n eslintProcess.on(VALIDATION_SUBPROCESS_EVENTS.ERROR, (error) => {\n resolve({ success: false, error: error.message });\n });\n });\n}\n","import { execFileSync } from \"node:child_process\";\nimport { existsSync, readdirSync, readFileSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nimport { withoutGitEnvironment } from \"@/git/environment\";\nimport { LINT_POLICY_BASE_REFS, LINT_POLICY_MANIFESTS, parseLintPolicyManifest } from \"./lint-policy-constants\";\n\nconst TEST_LINT_DEBT_NODE_MANIFEST_FILE = LINT_POLICY_MANIFESTS.TEST_LINT_DEBT_NODES.file;\nconst TEST_LINT_DEBT_NODE_MANIFEST_KEY = LINT_POLICY_MANIFESTS.TEST_LINT_DEBT_NODES.key;\nconst TEST_OWNED_CONSTANT_DEBT_NODE_MANIFEST_FILE = LINT_POLICY_MANIFESTS.TEST_OWNED_CONSTANT_DEBT_NODES.file;\nconst TEST_OWNED_CONSTANT_DEBT_NODE_MANIFEST_KEY = LINT_POLICY_MANIFESTS.TEST_OWNED_CONSTANT_DEBT_NODES.key;\nconst SPEC_TREE_ROOT = \"spx\";\nconst SPEC_TREE_NODE_SUFFIX_PATTERN = /\\.(enabler|outcome)$/;\nconst DEPRECATED_SPEC_NODE_SUFFIX_PATTERN = /\\.(capability|feature|story)$/;\nconst BASE_BRANCH_REFS = [LINT_POLICY_BASE_REFS.REMOTE_MAIN, LINT_POLICY_BASE_REFS.LOCAL_MAIN] as const;\n\nexport type LintPolicyResult =\n | { readonly ok: true }\n | { readonly ok: false; readonly error: string };\n\nfunction readManifest(productDir: string, file: string, key: string): string[] {\n return parseLintPolicyManifest(\n readFileSync(join(productDir, file), \"utf-8\"),\n file,\n key,\n );\n}\n\nfunction manifestExists(productDir: string, file: string): boolean {\n return existsSync(join(productDir, file));\n}\n\nfunction findDeprecatedSpecNodePath(productDir: string): string | undefined {\n function visit(relativeDirectory: string): string | undefined {\n const absoluteDirectory = join(productDir, relativeDirectory);\n for (const entry of readdirSync(absoluteDirectory, { withFileTypes: true })) {\n if (!entry.isDirectory()) {\n continue;\n }\n\n const childPath = `${relativeDirectory}/${entry.name}`;\n\n if (DEPRECATED_SPEC_NODE_SUFFIX_PATTERN.test(entry.name)) {\n return childPath;\n }\n\n const nestedDeprecatedPath = visit(childPath);\n if (nestedDeprecatedPath !== undefined) {\n return nestedDeprecatedPath;\n }\n }\n\n return undefined;\n }\n\n const specTreeRootPath = join(productDir, SPEC_TREE_ROOT);\n if (!existsSync(specTreeRootPath)) {\n return undefined;\n }\n\n return visit(SPEC_TREE_ROOT);\n}\n\nfunction assertManifestEntries(\n productDir: string,\n file: string,\n entries: string[],\n suffixPattern: RegExp,\n suffixDescription: string,\n): void {\n const duplicates = entries.filter((entry, index) => entries.indexOf(entry) !== index);\n\n if (duplicates.length > 0) {\n throw new Error(\n `${file} contains duplicate entries: ${duplicates.join(\", \")}`,\n );\n }\n\n for (const entry of entries) {\n if (entry !== entry.trim()) {\n throw new Error(`${file} entry has surrounding whitespace: ${entry}`);\n }\n\n if (!entry.startsWith(`${SPEC_TREE_ROOT}/`)) {\n throw new Error(`${file} entry must be under ${SPEC_TREE_ROOT}/: ${entry}`);\n }\n\n if (entry.includes(\"..\")) {\n throw new Error(`${file} entry must not contain '..': ${entry}`);\n }\n\n if (!suffixPattern.test(entry)) {\n throw new Error(`${file} entry must ${suffixDescription}: ${entry}`);\n }\n\n const absoluteEntry = join(productDir, entry);\n if (!existsSync(absoluteEntry) || !statSync(absoluteEntry).isDirectory()) {\n throw new Error(`${file} entry does not exist as a directory: ${entry}`);\n }\n }\n}\n\nfunction readBaselineManifest(productDir: string, file: string, key: string): string[] | undefined {\n const baselineRef = readBaselineRef(productDir);\n if (baselineRef === undefined) {\n return undefined;\n }\n\n let content: string;\n try {\n content = execFileSync(\"git\", [\"show\", `${baselineRef}:${file}`], {\n cwd: productDir,\n encoding: \"utf-8\",\n env: withoutGitEnvironment(process.env),\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n });\n } catch {\n return undefined;\n }\n\n return parseLintPolicyManifest(\n content,\n `${baselineRef}:${file}`,\n key,\n );\n}\n\nfunction readBaselineRef(productDir: string): string | undefined {\n const mergeCommitFirstParent = readMergeCommitFirstParent(productDir);\n if (mergeCommitFirstParent !== undefined) {\n return mergeCommitFirstParent;\n }\n\n for (const baseBranchRef of BASE_BRANCH_REFS) {\n const mergeBase = readMergeBase(productDir, baseBranchRef);\n if (mergeBase !== undefined) {\n return mergeBase;\n }\n }\n\n return undefined;\n}\n\nfunction readMergeCommitFirstParent(productDir: string): string | undefined {\n const secondParent = readGitRef(productDir, [\"rev-parse\", \"--verify\", \"HEAD^2\"]);\n if (secondParent === undefined) {\n return undefined;\n }\n return readGitRef(productDir, [\"rev-parse\", \"--verify\", \"HEAD^1\"]);\n}\n\nfunction readMergeBase(productDir: string, baseBranchRef: string): string | undefined {\n return readGitRef(productDir, [\"merge-base\", \"HEAD\", baseBranchRef]);\n}\n\nfunction readGitRef(productDir: string, args: readonly string[]): string | undefined {\n try {\n const output = execFileSync(\"git\", [...args], {\n cwd: productDir,\n encoding: \"utf-8\",\n env: withoutGitEnvironment(process.env),\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n });\n return output.trim() || undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction assertManifestDoesNotGrow(\n productDir: string,\n file: string,\n key: string,\n entries: string[],\n): void {\n const baselineEntries = readBaselineManifest(productDir, file, key);\n\n if (baselineEntries === undefined) {\n return;\n }\n\n const baselineEntrySet = new Set(baselineEntries);\n const additions = entries.filter((entry) => !baselineEntrySet.has(entry));\n\n if (additions.length > 0) {\n throw new Error(\n `${file} is shrink-only. Remove the listed debt instead of adding entries: ${additions.join(\", \")}`,\n );\n }\n}\n\nfunction rejectDeprecatedSpecNodeSuffixes(productDir: string): void {\n const deprecatedSpecNodePath = findDeprecatedSpecNodePath(productDir);\n if (deprecatedSpecNodePath !== undefined) {\n throw new Error(\n `Spec Tree nodes must use current suffixes only: ${deprecatedSpecNodePath}`,\n );\n }\n}\n\nfunction validateTestLintDebtNodeManifest(productDir: string, entries: string[]): void {\n assertManifestEntries(\n productDir,\n TEST_LINT_DEBT_NODE_MANIFEST_FILE,\n entries,\n SPEC_TREE_NODE_SUFFIX_PATTERN,\n \"be a Spec Tree node path\",\n );\n assertManifestDoesNotGrow(\n productDir,\n TEST_LINT_DEBT_NODE_MANIFEST_FILE,\n TEST_LINT_DEBT_NODE_MANIFEST_KEY,\n entries,\n );\n}\n\nfunction validateTestOwnedConstantDebtNodeManifest(productDir: string, entries: string[]): void {\n assertManifestEntries(\n productDir,\n TEST_OWNED_CONSTANT_DEBT_NODE_MANIFEST_FILE,\n entries,\n SPEC_TREE_NODE_SUFFIX_PATTERN,\n \"be a Spec Tree node path\",\n );\n assertManifestDoesNotGrow(\n productDir,\n TEST_OWNED_CONSTANT_DEBT_NODE_MANIFEST_FILE,\n TEST_OWNED_CONSTANT_DEBT_NODE_MANIFEST_KEY,\n entries,\n );\n}\n\nexport function validateLintPolicy(productDir: string): LintPolicyResult {\n try {\n rejectDeprecatedSpecNodeSuffixes(productDir);\n\n const manifestExistence = [\n manifestExists(productDir, TEST_LINT_DEBT_NODE_MANIFEST_FILE),\n manifestExists(productDir, TEST_OWNED_CONSTANT_DEBT_NODE_MANIFEST_FILE),\n ];\n if (manifestExistence.every((exists) => !exists)) {\n return { ok: true };\n }\n if (!manifestExistence.every(Boolean)) {\n return {\n ok: false,\n error: \"lint policy manifests must be present together\",\n };\n }\n\n validateTestLintDebtNodeManifest(\n productDir,\n readManifest(productDir, TEST_LINT_DEBT_NODE_MANIFEST_FILE, TEST_LINT_DEBT_NODE_MANIFEST_KEY),\n );\n validateTestOwnedConstantDebtNodeManifest(\n productDir,\n readManifest(\n productDir,\n TEST_OWNED_CONSTANT_DEBT_NODE_MANIFEST_FILE,\n TEST_OWNED_CONSTANT_DEBT_NODE_MANIFEST_KEY,\n ),\n );\n return { ok: true };\n } catch (error) {\n return { ok: false, error: error instanceof Error ? error.message : String(error) };\n }\n}\n","import * as JSONC from \"jsonc-parser\";\n\nexport const LINT_POLICY_MANIFESTS = {\n TEST_LINT_DEBT_NODES: {\n file: \"eslint.test-lint-debt-nodes.json\",\n key: \"testLintDebtNodes\",\n },\n TEST_OWNED_CONSTANT_DEBT_NODES: {\n file: \"eslint.test-owned-constant-debt-nodes.json\",\n key: \"testOwnedConstantDebtNodes\",\n },\n} as const;\n\nexport const LINT_POLICY_BASE_REFS = {\n REMOTE_MAIN: \"origin/main\",\n LOCAL_MAIN: \"main\",\n} as const;\n\ntype JsonObject = Record<string, unknown>;\n\nfunction isJsonObject(value: unknown): value is JsonObject {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nexport function parseLintPolicyManifest(content: string, source: string, key: string): string[] {\n const parsed = JSONC.parse(content) as unknown;\n\n if (!isJsonObject(parsed)) {\n throw new Error(`${source} must contain a JSON object`);\n }\n\n const entries = parsed[key];\n\n if (!Array.isArray(entries)) {\n throw new Error(`${source} must contain a ${key} array`);\n }\n\n const invalidEntries = entries.filter((entry) => typeof entry !== \"string\");\n\n if (invalidEntries.length > 0) {\n throw new Error(`${source} ${key} entries must be strings`);\n }\n\n return entries as string[];\n}\n","/**\n * Shared types for the validation module.\n *\n * These types define the contracts for validation steps and their dependencies,\n * enabling dependency injection for testability.\n *\n * @module validation/types\n */\n\n// =============================================================================\n// DEPENDENCY INJECTION INTERFACES\n// =============================================================================\n\n/**\n * Validation scope constants.\n *\n * @example\n * ```typescript\n * import { VALIDATION_SCOPES } from \"./types.js\";\n * const scope = VALIDATION_SCOPES.FULL; // \"full\"\n * ```\n */\nexport const VALIDATION_SCOPES = {\n /** Validate entire codebase including tests and scripts */\n FULL: \"full\",\n /** Validate production files only */\n PRODUCTION: \"production\",\n} as const;\n\n/** Type for validation scope values */\nexport type ValidationScope = (typeof VALIDATION_SCOPES)[keyof typeof VALIDATION_SCOPES];\n\n/**\n * Configuration for validation scope.\n *\n * Derived from tsconfig.json settings to ensure alignment between\n * TypeScript and ESLint validation.\n */\nexport interface ScopeConfig {\n /** Project-root-relative top-level directories to include in validation */\n directories: string[];\n /** File patterns to match (from tsconfig include) */\n filePatterns: string[];\n /** Patterns to exclude from validation */\n excludePatterns: string[];\n /** Whether spx.config validation path filters narrowed this scope */\n filteredByValidationPaths?: boolean;\n /** Whether the narrowed scope came from an include path, not only excludes */\n filteredByValidationPathIncludes?: boolean;\n /** Whether include filters were declared but did not match the configured tool scope */\n filteredByValidationPathNoMatches?: boolean;\n}\n\n// =============================================================================\n// EXECUTION MODE\n// =============================================================================\n\n/**\n * Execution mode constants.\n */\nexport const EXECUTION_MODES = {\n /** Read-only mode - report errors without fixing */\n READ: \"read\",\n /** Write mode - fix errors when possible (e.g., eslint --fix) */\n WRITE: \"write\",\n} as const;\n\n/** Type for execution mode values */\nexport type ExecutionMode = (typeof EXECUTION_MODES)[keyof typeof EXECUTION_MODES];\n\n// =============================================================================\n// VALIDATION CONTEXT\n// =============================================================================\n\n/**\n * Context object passed to validation steps.\n *\n * Contains all information needed to execute a validation step,\n * enabling pure functions that don't rely on global state.\n */\nexport interface ValidationContext {\n /** Root directory of the project being validated */\n projectRoot: string;\n /** Execution mode (read-only or write/fix) */\n mode?: ExecutionMode;\n /** Validation scope (full or production) */\n scope: ValidationScope;\n /** Scope configuration derived from tsconfig */\n scopeConfig: ScopeConfig;\n /** Which validations are enabled */\n enabledValidations: Partial<Record<string, boolean>>;\n /** Specific files to validate (if file-specific mode) */\n validatedFiles?: string[];\n /** Whether running in file-specific mode */\n isFileSpecificMode: boolean;\n /** ESLint flat config file name, determined by language detection */\n eslintConfigFile?: string;\n}\n\n// =============================================================================\n// VALIDATION RESULTS\n// =============================================================================\n\n/**\n * Result from a validation step.\n *\n * All validation steps return this structure to enable consistent\n * result handling and progress reporting.\n */\nexport interface ValidationStepResult {\n /** Whether the validation passed */\n success: boolean;\n /** Error message if validation failed */\n error?: string;\n /** Duration of the validation step in milliseconds */\n duration: number;\n /** Whether the step was skipped (e.g., tool not available) */\n skipped?: boolean;\n}\n\n/**\n * Result from circular dependency validation.\n *\n * Extends ValidationStepResult with circular dependency details.\n */\nexport interface CircularDependencyResult {\n /** Whether no circular dependencies were found */\n success: boolean;\n /** Error message if circular dependencies found */\n error?: string;\n /** The circular dependency cycles found */\n circularDependencies?: string[][];\n}\n\n// =============================================================================\n// VALIDATION STEP INTERFACE\n// =============================================================================\n\n/**\n * Definition of a validation step.\n *\n * Validation steps are pluggable units that can be enabled/disabled\n * and executed in sequence.\n */\nexport interface ValidationStep {\n /** Unique identifier for the step */\n id: string;\n /** Human-readable name for progress reporting */\n name: string;\n /** Description shown during execution */\n description: string;\n /** Function to determine if step should run */\n enabled: (context: ValidationContext) => boolean;\n /** Function to execute the validation */\n execute: (context: ValidationContext) => Promise<ValidationStepResult>;\n}\n","/**\n * Output forwarding for validation subprocesses.\n *\n * Validation tools write through the parent process so CLI lifecycle handlers\n * can observe broken pipes and terminate tracked children.\n *\n * @module validation/steps/subprocess-output\n */\n\nimport type { Readable } from \"node:stream\";\n\nexport const VALIDATION_SUBPROCESS_EVENTS = {\n CLOSE: \"close\",\n DATA: \"data\",\n DRAIN: \"drain\",\n ERROR: \"error\",\n} as const;\n\nexport interface ValidationSubprocessOutputStreams {\n readonly stdout: ValidationWritableStream;\n readonly stderr: ValidationWritableStream;\n}\n\nexport interface ValidationWritableStream {\n write(chunk: string | Uint8Array): boolean;\n once?(event: typeof VALIDATION_SUBPROCESS_EVENTS.DRAIN, listener: () => void): unknown;\n}\n\nexport interface ValidationSubprocessWithOutput {\n readonly stdout?: Readable | null;\n readonly stderr?: Readable | null;\n}\n\nexport const defaultValidationSubprocessOutputStreams: ValidationSubprocessOutputStreams = {\n stdout: process.stdout,\n stderr: process.stderr,\n};\n\nexport function forwardValidationSubprocessOutput(\n child: ValidationSubprocessWithOutput,\n streams: ValidationSubprocessOutputStreams = defaultValidationSubprocessOutputStreams,\n): void {\n child.stdout?.on(VALIDATION_SUBPROCESS_EVENTS.DATA, (chunk: string | Uint8Array) => {\n forwardChunkWithBackpressure(child.stdout, streams.stdout, chunk);\n });\n\n child.stderr?.on(VALIDATION_SUBPROCESS_EVENTS.DATA, (chunk: string | Uint8Array) => {\n forwardChunkWithBackpressure(child.stderr, streams.stderr, chunk);\n });\n}\n\nfunction forwardChunkWithBackpressure(\n source: Readable | null | undefined,\n stream: ValidationWritableStream,\n chunk: string | Uint8Array,\n): void {\n const ready = stream.write(chunk);\n if (ready || stream.once === undefined || source === null || source === undefined) {\n return;\n }\n\n source.pause();\n stream.once(VALIDATION_SUBPROCESS_EVENTS.DRAIN, () => {\n source.resume();\n });\n}\n","/**\n * ESLint validation command.\n *\n * Runs ESLint for code quality checks.\n */\nimport { resolveConfig } from \"@/config/index\";\nimport {\n VALIDATION_PATH_TOOL_SUBSECTIONS,\n type ValidationConfig,\n validationConfigDescriptor,\n} from \"@/validation/config/descriptor\";\nimport {\n applyValidationPathFilterToScope,\n pathPassesValidationFilter,\n toProjectRelativeValidationPath,\n validationPathFilterForTool,\n} from \"@/validation/config/path-filter\";\nimport { getTypeScriptScope } from \"@/validation/config/scope\";\nimport { detectTypeScript, discoverTool, formatSkipMessage } from \"@/validation/discovery/index\";\nimport { validateESLint } from \"@/validation/steps/eslint\";\nimport { VALIDATION_SCOPES, type ValidationContext } from \"@/validation/types\";\nimport {\n formatTypeScriptAbsentSkipMessage,\n formatValidationPathsNoTargetsSkipMessage,\n VALIDATION_COMMAND_OUTPUT,\n VALIDATION_STAGE_DISPLAY_NAMES,\n} from \"./messages\";\nimport type { LintCommandOptions, ValidationCommandResult } from \"./types\";\n\nconst TYPESCRIPT_ABSENT_MESSAGE = formatTypeScriptAbsentSkipMessage(VALIDATION_STAGE_DISPLAY_NAMES.ESLINT);\nconst MISSING_CONFIG_MESSAGE = VALIDATION_COMMAND_OUTPUT.ESLINT_MISSING_CONFIG;\nconst ESLINT_CONFIG_ERROR_MESSAGE = `${VALIDATION_STAGE_DISPLAY_NAMES.ESLINT}: ✗ config error`;\nconst VALIDATION_PATHS_NO_TARGETS_MESSAGE = formatValidationPathsNoTargetsSkipMessage(\n VALIDATION_STAGE_DISPLAY_NAMES.ESLINT,\n);\n\n/**\n * Run ESLint validation.\n *\n * Gates ESLint execution on TypeScript language detection. ESLint runs only\n * when `tsconfig.json` is present AND an ESLint flat config file exists. A\n * project with `tsconfig.json` but no ESLint config produces a non-zero exit\n * with a descriptive error; a project without `tsconfig.json` skips cleanly.\n *\n * @param options - Command options\n * @returns Command result with exit code and output\n */\nexport async function lintCommand(options: LintCommandOptions): Promise<ValidationCommandResult> {\n const { cwd, scope = \"full\", files, fix, outputStreams, quiet } = options;\n const startTime = Date.now();\n\n // Gate 1: language detection. No TypeScript = skip cleanly.\n const tsDetection = detectTypeScript(cwd);\n if (!tsDetection.present) {\n return {\n exitCode: 0,\n output: quiet ? \"\" : TYPESCRIPT_ABSENT_MESSAGE,\n durationMs: Date.now() - startTime,\n };\n }\n\n const eslintConfigFile = scope === VALIDATION_SCOPES.PRODUCTION\n ? tsDetection.productionEslintConfigFile ?? tsDetection.eslintConfigFile\n : tsDetection.eslintConfigFile;\n\n // Gate 2: ESLint flat config must exist when TypeScript is present.\n if (eslintConfigFile === undefined) {\n return {\n exitCode: 1,\n output: MISSING_CONFIG_MESSAGE,\n durationMs: Date.now() - startTime,\n };\n }\n\n const loaded = await resolveConfig(cwd, [validationConfigDescriptor]);\n if (!loaded.ok) {\n return {\n exitCode: 1,\n output: `${ESLINT_CONFIG_ERROR_MESSAGE} — ${loaded.error}`,\n durationMs: Date.now() - startTime,\n };\n }\n const validationConfig = loaded.value[validationConfigDescriptor.section] as ValidationConfig;\n const validationPathFilter = validationPathFilterForTool(\n validationConfig.paths,\n VALIDATION_PATH_TOOL_SUBSECTIONS.ESLINT,\n );\n const scopeConfig = applyValidationPathFilterToScope(\n getTypeScriptScope(scope, cwd),\n validationPathFilter,\n );\n const validatedFiles = files\n ?.map((file) => toProjectRelativeValidationPath(cwd, file))\n .filter((file) => pathPassesValidationFilter(file, validationPathFilter));\n\n if (\n scopeConfig.filteredByValidationPathNoMatches\n || (files !== undefined && files.length > 0 && validatedFiles?.length === 0)\n ) {\n return {\n exitCode: 0,\n output: quiet ? \"\" : VALIDATION_PATHS_NO_TARGETS_MESSAGE,\n durationMs: Date.now() - startTime,\n };\n }\n\n // Gate 3: tool discovery — ensure ESLint itself is available somewhere.\n const toolResult = await discoverTool(\"eslint\", { projectRoot: cwd });\n if (!toolResult.found) {\n const skipMessage = formatSkipMessage(VALIDATION_STAGE_DISPLAY_NAMES.ESLINT, toolResult);\n return { exitCode: 0, output: skipMessage, durationMs: Date.now() - startTime };\n }\n\n // Build validation context\n const context: ValidationContext = {\n projectRoot: cwd,\n scope,\n scopeConfig,\n mode: fix ? \"write\" : \"read\",\n enabledValidations: { ESLINT: true },\n validatedFiles,\n isFileSpecificMode: Boolean(validatedFiles && validatedFiles.length > 0),\n eslintConfigFile,\n };\n\n // Run ESLint validation\n const result = await validateESLint(context, undefined, outputStreams);\n const durationMs = Date.now() - startTime;\n\n // Map result to command output\n if (result.skipped) {\n const output = quiet ? \"\" : VALIDATION_PATHS_NO_TARGETS_MESSAGE;\n return { exitCode: 0, output, durationMs };\n } else if (result.success) {\n const output = quiet ? \"\" : VALIDATION_COMMAND_OUTPUT.ESLINT_SUCCESS;\n return { exitCode: 0, output, durationMs };\n } else {\n const output = result.error ?? VALIDATION_COMMAND_OUTPUT.ESLINT_FAILURE;\n return { exitCode: 1, output, durationMs };\n }\n}\n","import { readFile } from \"node:fs/promises\";\nimport { isAbsolute, relative, resolve } from \"node:path\";\n\nimport { DEFAULT_SCOPE_CONFIG } from \"@/lib/file-inclusion/config\";\nimport { EMPTY_IGNORE_READER } from \"@/lib/file-inclusion/ignore-source\";\nimport { artifactDirectoryLayer, hiddenPrefixLayer } from \"@/lib/file-inclusion/layer-sequence\";\nimport { runPipeline } from \"@/lib/file-inclusion/pipeline\";\nimport type { ScopeEntry } from \"@/lib/file-inclusion/types\";\nimport { type ValidationPathConfig } from \"@/validation/config/descriptor\";\n\nimport { type LiteralConfig, literalConfigDescriptor, resolveAllowlist } from \"./config\";\nimport {\n buildIndex,\n collectLiterals,\n defaultVisitorKeys,\n type DetectionResult,\n detectReuse,\n type LiteralOccurrence,\n} from \"./detector\";\nimport { isTestFile, isTypescriptSource } from \"./walker\";\n\nexport { literalConfigDescriptor, resolveAllowlist } from \"./config\";\nexport type { LiteralConfig } from \"./config\";\nexport {\n buildIndex,\n collectLiterals,\n defaultVisitorKeys,\n detectReuse,\n FIXTURE_WRITER_CALLS,\n LITERAL_KIND,\n MODULE_NAMING_SKIP,\n parseLiteralReuseResult,\n REMEDIATION,\n} from \"./detector\";\nexport type {\n DetectionResult,\n DupeFinding,\n LiteralIndex,\n LiteralKind,\n LiteralLocation,\n LiteralOccurrence,\n Remediation,\n ReuseFinding,\n VisitorKeysMap,\n} from \"./detector\";\n\nexport interface ValidateLiteralReuseInput {\n readonly productDir: string;\n readonly files?: readonly string[];\n readonly config?: LiteralConfig;\n readonly pathConfig?: ValidationPathConfig;\n}\n\nexport interface ValidateLiteralReuseResult {\n readonly findings: DetectionResult;\n readonly indexedOccurrencesByFile: ReadonlyMap<string, readonly LiteralOccurrence[]>;\n}\n\nconst PATH_PREFIX_SEPARATOR = \"/\";\n\nexport const DEFAULT_LITERAL_COLLECT_OPTIONS = {\n visitorKeys: defaultVisitorKeys,\n minStringLength: literalConfigDescriptor.defaults.minStringLength,\n minNumberDigits: literalConfigDescriptor.defaults.minNumberDigits,\n} as const;\n\nexport function createEmptyLiteralAllowlist(): ReadonlySet<string> {\n return new Set();\n}\n\nfunction normalizePathPrefix(prefix: string): string {\n const posix = prefix.split(/[\\\\/]/g).join(PATH_PREFIX_SEPARATOR);\n return posix.endsWith(PATH_PREFIX_SEPARATOR) ? posix : `${posix}${PATH_PREFIX_SEPARATOR}`;\n}\n\nfunction applyPathFilter(\n entries: readonly ScopeEntry[],\n pathConfig: ValidationPathConfig | undefined,\n): readonly ScopeEntry[] {\n if (pathConfig === undefined) {\n return entries;\n }\n const includePrefixes = (pathConfig.include ?? []).map(normalizePathPrefix);\n const excludePrefixes = (pathConfig.exclude ?? []).map(normalizePathPrefix);\n return entries.filter((entry) => {\n if (\n includePrefixes.length > 0\n && !includePrefixes.some((p) => entry.path.startsWith(p))\n ) {\n return false;\n }\n if (excludePrefixes.some((p) => entry.path.startsWith(p))) {\n return false;\n }\n return true;\n });\n}\n\nexport async function validateLiteralReuse(\n input: ValidateLiteralReuseInput,\n): Promise<ValidateLiteralReuseResult> {\n const config = input.config ?? literalConfigDescriptor.defaults;\n\n const request = input.files\n ? {\n explicit: input.files.map((f) => {\n const abs = isAbsolute(f) ? f : resolve(input.productDir, f);\n return relative(input.productDir, abs).split(/[\\\\/]/g).join(\"/\");\n }),\n }\n : { walkRoot: input.productDir };\n\n const scope = await runPipeline(\n [artifactDirectoryLayer, hiddenPrefixLayer],\n input.productDir,\n request,\n DEFAULT_SCOPE_CONFIG,\n EMPTY_IGNORE_READER,\n );\n\n const filtered = applyPathFilter(scope.included, input.pathConfig);\n\n const candidateFiles = filtered\n .filter((entry) => isTypescriptSource(entry.path))\n .map((entry) => resolve(input.productDir, entry.path));\n\n const collectOptions = {\n visitorKeys: defaultVisitorKeys,\n minStringLength: config.minStringLength,\n minNumberDigits: config.minNumberDigits,\n };\n\n const srcOccurrences: LiteralOccurrence[] = [];\n const testOccurrencesByFile = new Map<string, readonly LiteralOccurrence[]>();\n const indexedOccurrencesByFile = new Map<string, readonly LiteralOccurrence[]>();\n\n for (const abs of candidateFiles) {\n const rel = relative(input.productDir, abs).split(/[\\\\/]/g).join(\"/\");\n\n const content = await readSafe(abs);\n if (content === null) continue;\n\n const occurrences = collectLiterals(content, rel, collectOptions);\n indexedOccurrencesByFile.set(rel, occurrences);\n if (isTestFile(rel)) {\n testOccurrencesByFile.set(rel, occurrences);\n } else {\n srcOccurrences.push(...occurrences);\n }\n }\n\n const srcIndex = buildIndex(srcOccurrences);\n const findings = detectReuse({\n srcIndex,\n testOccurrencesByFile,\n allowlist: resolveAllowlist(config),\n });\n\n return { findings, indexedOccurrencesByFile };\n}\n\nasync function readSafe(path: string): Promise<string | null> {\n try {\n return await readFile(path, \"utf8\");\n } catch (err: unknown) {\n if (typeof err === \"object\" && err !== null && \"code\" in err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === \"ENOENT\" || code === \"EISDIR\") return null;\n }\n throw err;\n }\n}\n","import type { IgnoreSourcePredicateConfig, LayerDecision } from \"../types\";\n\nexport const IGNORE_SOURCE_LAYER = \"ignore-source\";\nconst LAYER = IGNORE_SOURCE_LAYER;\n\nexport function ignoreSourcePredicate(\n path: string,\n config: IgnoreSourcePredicateConfig,\n): LayerDecision {\n const entry = config.reader.matchedEntry(path);\n if (entry === undefined) {\n return { matched: false, layer: LAYER };\n }\n return { matched: true, layer: LAYER, detail: entry.segment };\n}\n","import { artifactDirectoryPredicate } from \"./predicates/artifact-directory\";\nimport { hiddenPrefixPredicate } from \"./predicates/hidden-prefix\";\nimport { ignoreSourcePredicate } from \"./predicates/ignore-source\";\nimport type { ArtifactDirectoryConfig, HiddenPrefixConfig, IgnoreSourcePredicateConfig } from \"./types\";\nimport type { LayerContext, LayerDecision, LayerEntry } from \"./types\";\n\nfunction makeLayer<C>(\n extractConfig: (ctx: LayerContext) => C,\n predicate: (path: string, config: C) => LayerDecision,\n): LayerEntry {\n return {\n extractConfig,\n predicate: (path, config) => predicate(path, config as C),\n };\n}\n\nexport const artifactDirectoryLayer: LayerEntry = makeLayer(\n (ctx): ArtifactDirectoryConfig => ({ artifactDirectories: ctx.config.artifactDirectories }),\n artifactDirectoryPredicate,\n);\n\nexport const hiddenPrefixLayer: LayerEntry = makeLayer(\n (ctx): HiddenPrefixConfig => ({ hiddenPrefix: ctx.config.hiddenPrefix }),\n hiddenPrefixPredicate,\n);\n\nexport const ignoreSourceLayer: LayerEntry = makeLayer(\n (ctx): IgnoreSourcePredicateConfig => ({ reader: ctx.ignoreReader }),\n ignoreSourcePredicate,\n);\n\nexport const LAYER_SEQUENCE: readonly LayerEntry[] = [\n artifactDirectoryLayer,\n hiddenPrefixLayer,\n ignoreSourceLayer,\n];\n","import type { Dirent } from \"node:fs\";\nimport { readdir } from \"node:fs/promises\";\nimport { join, relative, sep } from \"node:path\";\n\nimport { createIgnoreSourceReader } from \"./ignore-source\";\nimport type { IgnoreSourceReader } from \"./ignore-source\";\nimport { LAYER_SEQUENCE } from \"./layer-sequence\";\nimport type {\n LayerContext,\n LayerDecision,\n LayerEntry,\n ScopeEntry,\n ScopeRequest,\n ScopeResolverConfig,\n ScopeResult,\n} from \"./types\";\n\nexport { LayerEntry, ScopeEntry, ScopeRequest, ScopeResolverConfig, ScopeResult };\nexport type { LayerContext, LayerDecision };\n\nexport const EXPLICIT_OVERRIDE_LAYER = \"explicit-override\" as const;\n\nfunction isNodeError(err: unknown): err is NodeJS.ErrnoException {\n return err instanceof Error && \"code\" in err;\n}\n\nasync function collectPaths(\n absoluteDir: string,\n projectRoot: string,\n result: string[],\n artifactDirs: ReadonlySet<string>,\n): Promise<void> {\n let dirEntries: Dirent<string>[];\n try {\n dirEntries = await readdir(absoluteDir, { withFileTypes: true });\n } catch (err) {\n if (isNodeError(err) && (err.code === \"ENOENT\" || err.code === \"ENOTDIR\")) {\n return;\n }\n throw err;\n }\n for (const entry of dirEntries) {\n if (entry.isDirectory()) {\n if (artifactDirs.has(entry.name)) continue;\n const absolutePath = join(absoluteDir, entry.name);\n await collectPaths(absolutePath, projectRoot, result, artifactDirs);\n } else if (entry.isFile()) {\n const absolutePath = join(absoluteDir, entry.name);\n const rel = relative(projectRoot, absolutePath);\n result.push(sep === \"/\" ? rel : rel.split(sep).join(\"/\"));\n }\n }\n}\n\nexport async function resolveScope(\n projectRoot: string,\n request: ScopeRequest,\n config: ScopeResolverConfig,\n): Promise<ScopeResult> {\n const ignoreReader = createIgnoreSourceReader(projectRoot, {\n ignoreSourceFilename: config.ignoreSourceFilename,\n specTreeRootSegment: config.specTreeRootSegment,\n });\n return runPipeline(LAYER_SEQUENCE, projectRoot, request, config, ignoreReader);\n}\n\nexport async function runPipeline(\n sequence: readonly LayerEntry[],\n projectRoot: string,\n request: ScopeRequest,\n config: ScopeResolverConfig,\n ignoreReader: IgnoreSourceReader,\n): Promise<ScopeResult> {\n const layerCtx: LayerContext = { config, ignoreReader };\n const layerPairs = sequence.map((entry) => ({\n entry,\n layerConfig: entry.extractConfig(layerCtx),\n }));\n\n const included: ScopeEntry[] = [];\n const excluded: ScopeEntry[] = [];\n\n const explicitPaths = request.explicit ?? [];\n const explicitPathSet = new Set<string>(explicitPaths);\n\n for (const path of explicitPaths) {\n included.push({\n path,\n decisionTrail: [{ matched: true, layer: EXPLICIT_OVERRIDE_LAYER }],\n });\n }\n\n if (request.walkRoot !== undefined) {\n const artifactDirs = new Set(config.artifactDirectories);\n const allPaths: string[] = [];\n await collectPaths(request.walkRoot, projectRoot, allPaths, artifactDirs);\n\n for (const path of allPaths) {\n if (explicitPathSet.has(path)) continue;\n\n const trail: LayerDecision[] = [];\n for (const { entry, layerConfig } of layerPairs) {\n const decision = entry.predicate(path, layerConfig);\n if (decision.matched) {\n trail.push(decision);\n }\n }\n\n if (trail.length > 0) {\n excluded.push({ path, decisionTrail: trail });\n } else {\n included.push({ path, decisionTrail: [] });\n }\n }\n }\n\n return { included, excluded };\n}\n","import { parse as parseTypeScript } from \"@typescript-eslint/parser\";\nimport { visitorKeys as typescriptVisitorKeys } from \"@typescript-eslint/visitor-keys\";\n\nimport { SPEC_TREE_ENV_FIXTURE_WRITER_METHODS } from \"@/domains/spec/fixture-writer-methods\";\n\nexport const LITERAL_KIND = {\n STRING: \"string\",\n NUMBER: \"number\",\n} as const;\n\nexport type LiteralKind = (typeof LITERAL_KIND)[keyof typeof LITERAL_KIND];\n\nexport interface LiteralLocation {\n readonly file: string;\n readonly line: number;\n}\n\nexport interface LiteralOccurrence {\n readonly kind: LiteralKind;\n readonly value: string;\n readonly loc: LiteralLocation;\n}\n\nexport type LiteralIndex = ReadonlyMap<string, readonly LiteralLocation[]>;\n\nexport type VisitorKeysMap = Record<string, readonly string[] | undefined>;\n\nexport const REMEDIATION = {\n IMPORT_FROM_SOURCE: \"import-from-source\",\n REFACTOR_TO_SOURCE_OR_GENERATOR: \"refactor-to-source-or-generator\",\n} as const;\n\nexport type Remediation = (typeof REMEDIATION)[keyof typeof REMEDIATION];\n\nexport interface ReuseFinding {\n readonly test: LiteralLocation;\n readonly kind: LiteralKind;\n readonly value: string;\n readonly src: readonly LiteralLocation[];\n readonly remediation: typeof REMEDIATION.IMPORT_FROM_SOURCE;\n}\n\nexport interface DupeFinding {\n readonly test: LiteralLocation;\n readonly kind: LiteralKind;\n readonly value: string;\n readonly otherTests: readonly LiteralLocation[];\n readonly remediation: typeof REMEDIATION.REFACTOR_TO_SOURCE_OR_GENERATOR;\n}\n\nexport interface DetectionResult {\n readonly srcReuse: readonly ReuseFinding[];\n readonly testDupe: readonly DupeFinding[];\n}\n\nexport interface CollectLiteralsOptions {\n readonly visitorKeys: VisitorKeysMap;\n readonly minStringLength: number;\n readonly minNumberDigits: number;\n}\n\nexport interface DetectReuseInput {\n readonly srcIndex: LiteralIndex;\n readonly testOccurrencesByFile: ReadonlyMap<string, readonly LiteralOccurrence[]>;\n readonly allowlist: ReadonlySet<string>;\n}\n\nexport const defaultVisitorKeys: VisitorKeysMap = typescriptVisitorKeys;\n\nexport const MODULE_NAMING_SKIP: Record<string, ReadonlySet<string>> = {\n ImportDeclaration: new Set([\"source\"]),\n ExportNamedDeclaration: new Set([\"source\"]),\n ExportAllDeclaration: new Set([\"source\"]),\n ImportExpression: new Set([\"source\"]),\n TSImportType: new Set([\"source\", \"argument\"]),\n TSExternalModuleReference: new Set([\"expression\"]),\n};\n\nconst EMPTY_SKIP: ReadonlySet<string> = new Set();\nconst TEST_PATH_SEGMENT = \"/tests/\";\nconst WINDOWS_TEST_PATH_SEGMENT = \"\\\\tests\\\\\";\nconst TEST_FILE_MARKER = \".test.\";\nconst CALL_EXPRESSION_TYPE = \"CallExpression\";\nconst VARIABLE_DECLARATOR_TYPE = \"VariableDeclarator\";\nconst IDENTIFIER_TYPE = \"Identifier\";\nconst LITERAL_TYPE = \"Literal\";\nconst MEMBER_EXPRESSION_TYPE = \"MemberExpression\";\nconst TEMPLATE_ELEMENT_TYPE = \"TemplateElement\";\nconst FUNCTION_NODE_TYPES: ReadonlySet<string> = new Set([\n \"ArrowFunctionExpression\",\n \"FunctionDeclaration\",\n \"FunctionExpression\",\n]);\nexport const FIXTURE_WRITER_CALLS: ReadonlySet<string> = new Set(\n SPEC_TREE_ENV_FIXTURE_WRITER_METHODS,\n);\nconst FIXTURE_DATA_DIRECT_SEGMENTS: ReadonlySet<string> = new Set([\"fixture\", \"payload\"]);\nconst FIXTURE_DATA_ROLE_SEGMENTS: ReadonlySet<string> = new Set([\n \"verdict\",\n \"session\",\n \"frontmatter\",\n \"xml\",\n \"yaml\",\n \"json\",\n \"source\",\n]);\nconst FIXTURE_DATA_CONTEXT_SEGMENTS: ReadonlySet<string> = new Set([\"path\", \"tree\"]);\n// Used through String#match; match resets global regex state instead of reading lastIndex.\nconst IDENTIFIER_SEGMENT_PATTERN = /[A-Z]+(?=[A-Z][a-z]|$)|[A-Z]?[a-z]+|[0-9]+/g;\n\ninterface Node {\n readonly type: string;\n readonly loc?: { readonly start?: { readonly line?: number } };\n readonly value?: unknown;\n readonly raw?: unknown;\n readonly [key: string]: unknown;\n}\n\ninterface WalkAncestor {\n readonly node: Node;\n}\n\ninterface WalkContext {\n readonly filename: string;\n readonly isTestFixtureFile: boolean;\n}\n\nexport function collectLiterals(\n source: string,\n filename: string,\n options: CollectLiteralsOptions,\n): LiteralOccurrence[] {\n const ast = parseTypeScript(source, {\n loc: true,\n range: true,\n comment: false,\n jsx: true,\n ecmaVersion: \"latest\",\n sourceType: \"module\",\n }) as unknown as Node;\n const out: LiteralOccurrence[] = [];\n const ancestors: WalkAncestor[] = [];\n walk(ast, { filename, isTestFixtureFile: isTestLikeFile(filename) }, ancestors, options, out);\n return out;\n}\n\nfunction walk(\n node: Node,\n context: WalkContext,\n ancestors: WalkAncestor[],\n options: CollectLiteralsOptions,\n out: LiteralOccurrence[],\n): void {\n emitLiteral(node, context, ancestors, options, out);\n\n const keys = options.visitorKeys[node.type];\n if (!keys) {\n return;\n }\n const skip = MODULE_NAMING_SKIP[node.type] ?? EMPTY_SKIP;\n for (const key of keys) {\n if (skip.has(key)) continue;\n const child = node[key];\n if (Array.isArray(child)) {\n for (const item of child) {\n if (isNode(item)) walkChild(item, node, context, ancestors, options, out);\n }\n } else if (isNode(child)) {\n walkChild(child, node, context, ancestors, options, out);\n }\n }\n}\n\nfunction walkChild(\n node: Node,\n parent: Node,\n context: WalkContext,\n ancestors: WalkAncestor[],\n options: CollectLiteralsOptions,\n out: LiteralOccurrence[],\n): void {\n // Shared stack mutation relies on synchronous traversal.\n ancestors.push({ node: parent });\n try {\n walk(node, context, ancestors, options, out);\n } finally {\n ancestors.pop();\n }\n}\n\nfunction isNode(value: unknown): value is Node {\n return typeof value === \"object\" && value !== null && typeof (value as Node).type === \"string\";\n}\n\nfunction emitLiteral(\n node: Node,\n context: WalkContext,\n ancestors: readonly WalkAncestor[],\n options: CollectLiteralsOptions,\n out: LiteralOccurrence[],\n): void {\n if (node.type !== LITERAL_TYPE && node.type !== TEMPLATE_ELEMENT_TYPE) {\n return;\n }\n if (isFixtureDataLiteral(context, ancestors)) {\n return;\n }\n const line = node.loc?.start?.line ?? 0;\n\n if (node.type === LITERAL_TYPE) {\n if (typeof node.value === \"string\") {\n if (node.value.length >= options.minStringLength) {\n out.push({ kind: \"string\", value: node.value, loc: { file: context.filename, line } });\n }\n } else if (typeof node.value === \"number\") {\n const raw = typeof node.raw === \"string\" ? node.raw : String(node.value);\n if (isMeaningfulNumber(raw, options.minNumberDigits)) {\n out.push({ kind: \"number\", value: String(node.value), loc: { file: context.filename, line } });\n }\n }\n return;\n }\n\n if (node.type === TEMPLATE_ELEMENT_TYPE) {\n const value = node.value as { readonly cooked?: string } | undefined;\n const cooked = value?.cooked ?? \"\";\n if (cooked.length >= options.minStringLength) {\n out.push({ kind: \"string\", value: cooked, loc: { file: context.filename, line } });\n }\n }\n}\n\nfunction isTestLikeFile(filename: string): boolean {\n return filename.includes(TEST_PATH_SEGMENT)\n || filename.includes(WINDOWS_TEST_PATH_SEGMENT)\n || filename.includes(TEST_FILE_MARKER);\n}\n\nfunction isFixtureDataLiteral(\n context: WalkContext,\n ancestors: readonly WalkAncestor[],\n): boolean {\n if (!context.isTestFixtureFile) {\n return false;\n }\n return isInsideFixtureWriterArgument(ancestors) || isInsideFixtureDataVariable(ancestors);\n}\n\nfunction isInsideFixtureWriterArgument(ancestors: readonly WalkAncestor[]): boolean {\n // Scan every call ancestor so wrappers around fixture-writer calls do not hide direct writer arguments.\n // Payload helpers inside a fixture writer remain setup data unless a nested function boundary intervenes.\n for (let index = ancestors.length - 1; index >= 0; index -= 1) {\n const ancestor = ancestors[index];\n if (ancestor.node.type !== CALL_EXPRESSION_TYPE) {\n continue;\n }\n const callName = getCallName(ancestor.node);\n if (callName === undefined || !isFixtureWriterCall(callName)) {\n continue;\n }\n if (hasNestedFunctionBetween(ancestors, index)) {\n continue;\n }\n return true;\n }\n return false;\n}\n\nfunction isFixtureWriterCall(callName: string): boolean {\n return FIXTURE_WRITER_CALLS.has(callName);\n}\n\nfunction isInsideFixtureDataVariable(ancestors: readonly WalkAncestor[]): boolean {\n for (let index = ancestors.length - 1; index >= 0; index -= 1) {\n const ancestor = ancestors[index];\n if (ancestor.node.type !== VARIABLE_DECLARATOR_TYPE) {\n continue;\n }\n if (hasNestedFunctionBetween(ancestors, index)) {\n continue;\n }\n const variableName = getFixtureDataDeclaratorName(ancestor.node);\n if (variableName !== undefined && isFixtureDataVariableName(variableName)) {\n return true;\n }\n }\n return false;\n}\n\nfunction hasNestedFunctionBetween(\n ancestors: readonly WalkAncestor[],\n ancestorIndex: number,\n): boolean {\n // The current literal node is passed separately, so this range checks only ancestors between call and literal.\n for (let index = ancestorIndex + 1; index < ancestors.length; index += 1) {\n if (FUNCTION_NODE_TYPES.has(ancestors[index].node.type)) {\n return true;\n }\n }\n return false;\n}\n\nfunction getFixtureDataDeclaratorName(node: Node): string | undefined {\n const bindingName = getIdentifierName(node.id);\n if (bindingName !== undefined) {\n return bindingName;\n }\n // Destructuring defaults are classified by the fixture object they read from.\n // Opaque initializer expressions keep their literals in the occurrence index.\n return getIdentifierName(node.init);\n}\n\nfunction isFixtureDataVariableName(variableName: string): boolean {\n const segments = splitIdentifierName(variableName);\n if (segments.length === 0) {\n return false;\n }\n // Tier 1: explicit fixture markers always denote test-authored data.\n if (segments.some((segment) => FIXTURE_DATA_DIRECT_SEGMENTS.has(segment))) {\n return true;\n }\n // Tier 2 and Tier 3 require at least one fixture role word.\n if (!segments.some((segment) => FIXTURE_DATA_ROLE_SEGMENTS.has(segment))) {\n return false;\n }\n // Tier 2: single-role and compound-role names describe fixture payloads.\n if (segments.every((segment) => FIXTURE_DATA_ROLE_SEGMENTS.has(segment))) {\n return true;\n }\n // Tier 3: role/context compounds are fixtures only when the context word is final.\n const finalSegment = segments[segments.length - 1];\n return finalSegment !== undefined && FIXTURE_DATA_CONTEXT_SEGMENTS.has(finalSegment);\n}\n\nfunction splitIdentifierName(variableName: string): readonly string[] {\n return variableName\n .split(\"_\")\n .flatMap((part) => part.match(IDENTIFIER_SEGMENT_PATTERN) ?? [])\n .map((segment) => segment.toLowerCase());\n}\n\nfunction getCallName(node: Node): string | undefined {\n const callee = node.callee;\n if (!isNode(callee)) {\n return undefined;\n }\n if (callee.type === IDENTIFIER_TYPE) {\n return getIdentifierName(callee);\n }\n if (callee.type !== MEMBER_EXPRESSION_TYPE) {\n return undefined;\n }\n const property = callee.property;\n if (isNode(property)) {\n return property.type === IDENTIFIER_TYPE ? getIdentifierName(property) : getLiteralString(property);\n }\n return undefined;\n}\n\nfunction getIdentifierName(value: unknown): string | undefined {\n if (!isNode(value) || value.type !== IDENTIFIER_TYPE) {\n return undefined;\n }\n return typeof value.name === \"string\" ? value.name : undefined;\n}\n\nfunction getLiteralString(value: unknown): string | undefined {\n if (!isNode(value) || value.type !== LITERAL_TYPE) {\n return undefined;\n }\n return typeof value.value === \"string\" ? value.value : undefined;\n}\n\nfunction isMeaningfulNumber(raw: string, minDigits: number): boolean {\n const digits = raw.replace(/[^0-9]/g, \"\");\n return digits.length >= minDigits;\n}\n\nexport function buildIndex(\n occurrences: Iterable<LiteralOccurrence>,\n): LiteralIndex {\n const map = new Map<string, LiteralLocation[]>();\n for (const occ of occurrences) {\n const key = makeKey(occ.kind, occ.value);\n const existing = map.get(key);\n if (existing) {\n existing.push(occ.loc);\n } else {\n map.set(key, [occ.loc]);\n }\n }\n return map;\n}\n\nfunction makeKey(kind: LiteralKind, value: string): string {\n return `${kind}\\0${value}`;\n}\n\nfunction splitKey(key: string): { kind: LiteralKind; value: string } {\n const idx = key.indexOf(\"\\0\");\n return { kind: key.slice(0, idx) as LiteralKind, value: key.slice(idx + 1) };\n}\n\nexport function detectReuse(input: DetectReuseInput): DetectionResult {\n const srcReuse: ReuseFinding[] = [];\n const testDupe: DupeFinding[] = [];\n\n const testIndex = new Map<string, Map<string, LiteralLocation[]>>();\n for (const [file, occurrences] of input.testOccurrencesByFile) {\n for (const occ of occurrences) {\n if (input.allowlist.has(occ.value)) continue;\n const key = makeKey(occ.kind, occ.value);\n let byFile = testIndex.get(key);\n if (!byFile) {\n byFile = new Map<string, LiteralLocation[]>();\n testIndex.set(key, byFile);\n }\n const locsInFile = byFile.get(file);\n if (locsInFile) locsInFile.push(occ.loc);\n else byFile.set(file, [occ.loc]);\n }\n }\n\n for (const [key, byFile] of testIndex) {\n const { kind, value } = splitKey(key);\n const srcLocs = input.srcIndex.get(key);\n const allTestLocs: LiteralLocation[] = [];\n for (const locs of byFile.values()) allTestLocs.push(...locs);\n\n if (srcLocs && srcLocs.length > 0) {\n for (const testLoc of allTestLocs) {\n srcReuse.push({\n test: testLoc,\n kind,\n value,\n src: srcLocs,\n remediation: REMEDIATION.IMPORT_FROM_SOURCE,\n });\n }\n } else if (byFile.size >= 2) {\n for (let i = 0; i < allTestLocs.length; i += 1) {\n const otherTests = [...allTestLocs.slice(0, i), ...allTestLocs.slice(i + 1)];\n testDupe.push({\n test: allTestLocs[i],\n kind,\n value,\n otherTests,\n remediation: REMEDIATION.REFACTOR_TO_SOURCE_OR_GENERATOR,\n });\n }\n }\n }\n\n return { srcReuse, testDupe };\n}\n\nexport function parseLiteralReuseResult(value: unknown): DetectionResult {\n if (!isPlainObject(value)) {\n throw new Error(\"literal-reuse result must be an object\");\n }\n const obj = value as { srcReuse?: unknown; testDupe?: unknown };\n if (!Array.isArray(obj.srcReuse)) {\n throw new Error(\"literal-reuse result is missing srcReuse array\");\n }\n if (!Array.isArray(obj.testDupe)) {\n throw new Error(\"literal-reuse result is missing testDupe array\");\n }\n for (const f of obj.srcReuse) validateReuseFinding(f);\n for (const f of obj.testDupe) validateDupeFinding(f);\n return { srcReuse: obj.srcReuse as readonly ReuseFinding[], testDupe: obj.testDupe as readonly DupeFinding[] };\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction validateLiteralLocation(value: unknown, context: string): void {\n if (!isPlainObject(value)) throw new Error(`${context} must be an object`);\n if (typeof value[\"file\"] !== \"string\") throw new Error(`${context}.file must be a string`);\n if (typeof value[\"line\"] !== \"number\") throw new Error(`${context}.line must be a number`);\n}\n\nfunction validateKindValue(value: unknown, context: string): void {\n if (!isPlainObject(value)) throw new Error(`${context} must be an object`);\n if (value[\"kind\"] !== \"string\" && value[\"kind\"] !== \"number\") {\n throw new Error(`${context}.kind must be \"string\" or \"number\"`);\n }\n if (typeof value[\"value\"] !== \"string\") {\n throw new Error(`${context}.value must be a string`);\n }\n}\n\nfunction validateReuseFinding(value: unknown): void {\n validateKindValue(value, \"srcReuse finding\");\n const obj = value as Record<string, unknown>;\n validateLiteralLocation(obj[\"test\"], \"srcReuse finding.test\");\n if (!Array.isArray(obj[\"src\"])) throw new Error(\"srcReuse finding.src must be an array\");\n for (const loc of obj[\"src\"]) validateLiteralLocation(loc, \"srcReuse finding.src[i]\");\n if (obj[\"remediation\"] !== REMEDIATION.IMPORT_FROM_SOURCE) {\n throw new Error(`srcReuse finding.remediation must be \"${REMEDIATION.IMPORT_FROM_SOURCE}\"`);\n }\n}\n\nfunction validateDupeFinding(value: unknown): void {\n validateKindValue(value, \"testDupe finding\");\n const obj = value as Record<string, unknown>;\n validateLiteralLocation(obj[\"test\"], \"testDupe finding.test\");\n if (!Array.isArray(obj[\"otherTests\"])) {\n throw new Error(\"testDupe finding.otherTests must be an array\");\n }\n for (const loc of obj[\"otherTests\"]) validateLiteralLocation(loc, \"testDupe finding.otherTests[i]\");\n if (obj[\"remediation\"] !== REMEDIATION.REFACTOR_TO_SOURCE_OR_GENERATOR) {\n throw new Error(\n `testDupe finding.remediation must be \"${REMEDIATION.REFACTOR_TO_SOURCE_OR_GENERATOR}\"`,\n );\n }\n}\n","// Shared production metadata for spec-tree fixture writer methods.\n// Literal validation imports this registry to classify test-authored setup data.\nexport const SPEC_TREE_ENV_FIXTURE_WRITER_METHOD = {\n DECISION: \"writeDecision\",\n NODE: \"writeNode\",\n RAW: \"writeRaw\",\n} as const;\n\nexport type SpecTreeEnvFixtureWriterMethod =\n (typeof SPEC_TREE_ENV_FIXTURE_WRITER_METHOD)[keyof typeof SPEC_TREE_ENV_FIXTURE_WRITER_METHOD];\n\nexport const SPEC_TREE_ENV_FIXTURE_WRITER_METHODS = [\n SPEC_TREE_ENV_FIXTURE_WRITER_METHOD.DECISION,\n SPEC_TREE_ENV_FIXTURE_WRITER_METHOD.NODE,\n SPEC_TREE_ENV_FIXTURE_WRITER_METHOD.RAW,\n] as const satisfies readonly SpecTreeEnvFixtureWriterMethod[];\n","const TYPESCRIPT_EXTENSIONS: ReadonlySet<string> = new Set([\".ts\", \".tsx\"]);\nconst DECLARATION_SUFFIX = \".d.ts\";\n\nexport function isTypescriptSource(path: string): boolean {\n if (path.endsWith(DECLARATION_SUFFIX)) return false;\n const ext = extensionOf(path);\n return TYPESCRIPT_EXTENSIONS.has(ext);\n}\n\nfunction extensionOf(name: string): string {\n const idx = name.lastIndexOf(\".\");\n return idx === -1 ? \"\" : name.slice(idx);\n}\n\nexport function isTestFile(relPath: string): boolean {\n return /\\.test\\.tsx?$/.test(relPath);\n}\n","import { resolveConfig } from \"@/config/index\";\nimport {\n VALIDATION_PATH_TOOL_SUBSECTIONS,\n type ValidationConfig,\n validationConfigDescriptor,\n type ValidationPathConfig,\n} from \"@/validation/config/descriptor\";\nimport { validationPathFilterForTool } from \"@/validation/config/path-filter\";\nimport { detectTypeScript } from \"@/validation/discovery/index\";\nimport { type LiteralConfig } from \"@/validation/literal/config\";\nimport {\n type DetectionResult,\n type DupeFinding,\n type LiteralKind,\n type LiteralLocation,\n type ReuseFinding,\n validateLiteralReuse,\n} from \"@/validation/literal/index\";\n\nexport const LITERAL_PROBLEM_KIND = {\n REUSE: \"reuse\",\n DUPE: \"dupe\",\n} as const;\n\nexport type LiteralProblemKind = (typeof LITERAL_PROBLEM_KIND)[keyof typeof LITERAL_PROBLEM_KIND];\n\nexport const OUTPUT_MODE_NAME = {\n TEXT: \"text\",\n VERBOSE: \"verbose\",\n FILES_WITH_PROBLEMS: \"filesWithProblems\",\n LITERALS: \"literals\",\n JSON: \"json\",\n} as const;\n\nexport const OUTPUT_MODE_NAMES = Object.values(OUTPUT_MODE_NAME);\nexport type OutputModeName = (typeof OUTPUT_MODE_NAMES)[number];\n\nexport const VERBOSE_PROBLEM_LINE_PREFIX = \"line \";\n\nexport interface LiteralCommandOptions {\n readonly cwd: string;\n readonly files?: readonly string[];\n readonly kind?: LiteralProblemKind;\n readonly filesWithProblems?: boolean;\n readonly literals?: boolean;\n readonly verbose?: boolean;\n readonly json?: boolean;\n readonly quiet?: boolean;\n readonly enabled?: boolean;\n readonly config?: LiteralConfig;\n readonly pathConfig?: ValidationPathConfig;\n}\n\nexport interface ValidationCommandResult {\n readonly exitCode: number;\n readonly output: string;\n readonly durationMs: number;\n}\n\nexport const LITERAL_EXIT_CODES = {\n OK: 0,\n FINDINGS: 1,\n CONFIG_ERROR: 2,\n} as const;\nconst TYPESCRIPT_ABSENT_MESSAGE = \"⏭ Skipping Literal (TypeScript not detected in project)\";\nexport const LITERAL_DISABLED_MESSAGE = \"⏭ Skipping Literal (disabled by validation.literal.enabled)\";\nexport const NO_PROBLEMS_MESSAGE = \"Literal: ✓ No problems\";\n\nexport function formatNoProblemsOfKind(kind: LiteralProblemKind): string {\n return `Literal: No problems of type ${kind}`;\n}\n\ninterface LiteralProblem {\n readonly problemKind: LiteralProblemKind;\n readonly literalKind: LiteralKind;\n readonly value: string;\n readonly test: LiteralLocation;\n readonly related: readonly LiteralLocation[];\n}\n\nexport async function literalCommand(\n options: LiteralCommandOptions,\n): Promise<ValidationCommandResult> {\n const start = Date.now();\n\n const tsDetection = detectTypeScript(options.cwd);\n if (!tsDetection.present) {\n return {\n exitCode: LITERAL_EXIT_CODES.OK,\n output: options.quiet ? \"\" : TYPESCRIPT_ABSENT_MESSAGE,\n durationMs: Date.now() - start,\n };\n }\n\n let resolvedEnabled: boolean;\n let resolvedLiteralConfig: LiteralConfig;\n let resolvedPathConfig: ValidationPathConfig;\n if (options.config !== undefined) {\n resolvedEnabled = options.enabled ?? validationConfigDescriptor.defaults.literal.enabled;\n resolvedLiteralConfig = options.config;\n resolvedPathConfig = options.pathConfig ?? validationConfigDescriptor.defaults.paths;\n } else {\n const loaded = await resolveConfig(options.cwd, [validationConfigDescriptor]);\n if (!loaded.ok) {\n return {\n exitCode: LITERAL_EXIT_CODES.CONFIG_ERROR,\n output: `Literal: ✗ config error — ${loaded.error}`,\n durationMs: Date.now() - start,\n };\n }\n const validationConfig = loaded.value[validationConfigDescriptor.section] as ValidationConfig;\n resolvedEnabled = validationConfig.literal.enabled;\n resolvedLiteralConfig = validationConfig.literal.values;\n resolvedPathConfig = validationPathFilterForTool(\n validationConfig.paths,\n VALIDATION_PATH_TOOL_SUBSECTIONS.LITERAL,\n );\n }\n\n if (!resolvedEnabled) {\n return {\n exitCode: LITERAL_EXIT_CODES.OK,\n output: options.quiet ? \"\" : LITERAL_DISABLED_MESSAGE,\n durationMs: Date.now() - start,\n };\n }\n\n const result = await validateLiteralReuse({\n productDir: options.cwd,\n files: options.files,\n config: resolvedLiteralConfig,\n pathConfig: resolvedPathConfig,\n });\n\n const filteredFindings = filterLiteralFindings(result.findings, options.kind);\n const totalProblems = countLiteralProblems(filteredFindings);\n const exitCode = totalProblems === 0 ? LITERAL_EXIT_CODES.OK : LITERAL_EXIT_CODES.FINDINGS;\n\n const output = options.json\n ? JSON.stringify(filteredFindings)\n : options.quiet\n ? \"\"\n : formatLiteralCommandOutput(filteredFindings, options);\n\n return { exitCode, output, durationMs: Date.now() - start };\n}\n\nexport function filterLiteralFindings(\n findings: DetectionResult,\n kind: LiteralProblemKind | undefined,\n): DetectionResult {\n return {\n srcReuse: kind === LITERAL_PROBLEM_KIND.DUPE ? [] : sortReuseFindings(findings.srcReuse),\n testDupe: kind === LITERAL_PROBLEM_KIND.REUSE ? [] : sortDupeFindings(findings.testDupe),\n };\n}\n\nexport function countLiteralProblems(findings: DetectionResult): number {\n return findings.srcReuse.length + findings.testDupe.length;\n}\n\nexport function formatDefaultLiteralProblems(findings: DetectionResult): string {\n return toLiteralProblems(findings)\n .map((problem) =>\n `[${problem.problemKind}] ${formatLiteralValue(problem.literalKind, problem.value)} ${formatLoc(problem.test)}`\n )\n .join(\"\\n\");\n}\n\nexport function formatVerboseLiteralProblems(findings: DetectionResult): string {\n const lines = [\n `Literal: ${\n countLiteralProblems(findings)\n } problems (reuse: ${findings.srcReuse.length}, dupe: ${findings.testDupe.length})`,\n ];\n\n appendVerboseSection(\n lines,\n \"REUSE\",\n findings.srcReuse.map((finding): LiteralProblem => ({\n problemKind: LITERAL_PROBLEM_KIND.REUSE,\n literalKind: finding.kind,\n value: finding.value,\n test: finding.test,\n related: finding.src,\n })),\n );\n appendVerboseSection(\n lines,\n \"DUPE\",\n findings.testDupe.map((finding): LiteralProblem => ({\n problemKind: LITERAL_PROBLEM_KIND.DUPE,\n literalKind: finding.kind,\n value: finding.value,\n test: finding.test,\n related: finding.otherTests,\n })),\n );\n\n return lines.join(\"\\n\");\n}\n\nexport function formatFilesWithProblems(findings: DetectionResult): string {\n return [...new Set(toLiteralProblems(findings).map((problem) => problem.test.file))]\n .sort()\n .join(\"\\n\");\n}\n\nexport function formatLiteralValues(findings: DetectionResult): string {\n const values = new Map<string, { readonly kind: LiteralKind; readonly value: string }>();\n for (const problem of toLiteralProblems(findings)) {\n values.set(`${problem.literalKind}\\0${problem.value}`, {\n kind: problem.literalKind,\n value: problem.value,\n });\n }\n return [...values.values()]\n .sort((left, right) => left.value.localeCompare(right.value) || left.kind.localeCompare(right.kind))\n .map((entry) => formatLiteralValue(entry.kind, entry.value))\n .join(\"\\n\");\n}\n\nfunction formatLiteralCommandOutput(\n findings: DetectionResult,\n options: LiteralCommandOptions,\n): string {\n const totalProblems = countLiteralProblems(findings);\n\n if (totalProblems === 0 && options.kind !== undefined) {\n return formatNoProblemsOfKind(options.kind);\n }\n\n if (totalProblems === 0) {\n return options.filesWithProblems || options.literals || options.verbose ? \"\" : NO_PROBLEMS_MESSAGE;\n }\n\n if (options.filesWithProblems) return formatFilesWithProblems(findings);\n if (options.literals) return formatLiteralValues(findings);\n if (options.verbose) return formatVerboseLiteralProblems(findings);\n return formatDefaultLiteralProblems(findings);\n}\n\nfunction toLiteralProblems(findings: DetectionResult): readonly LiteralProblem[] {\n return [\n ...sortReuseFindings(findings.srcReuse).map((finding): LiteralProblem => ({\n problemKind: LITERAL_PROBLEM_KIND.REUSE,\n literalKind: finding.kind,\n value: finding.value,\n test: finding.test,\n related: finding.src,\n })),\n ...sortDupeFindings(findings.testDupe).map((finding): LiteralProblem => ({\n problemKind: LITERAL_PROBLEM_KIND.DUPE,\n literalKind: finding.kind,\n value: finding.value,\n test: finding.test,\n related: finding.otherTests,\n })),\n ];\n}\n\nfunction appendVerboseSection(\n lines: string[],\n heading: string,\n problems: readonly LiteralProblem[],\n): void {\n const sortedProblems = [...problems].sort(compareLiteralProblems);\n if (sortedProblems.length === 0) return;\n\n lines.push(heading);\n let currentFile: string | undefined;\n for (const problem of sortedProblems) {\n if (problem.test.file !== currentFile) {\n lines.push(problem.test.file);\n currentFile = problem.test.file;\n }\n lines.push(\n ` line ${problem.test.line}: ${formatLiteralValue(problem.literalKind, problem.value)} also in ${\n problem.related.map(formatLoc).join(\", \")\n }`,\n );\n }\n}\n\nfunction sortReuseFindings(findings: readonly ReuseFinding[]): readonly ReuseFinding[] {\n return [...findings].sort(compareFindings);\n}\n\nfunction sortDupeFindings(findings: readonly DupeFinding[]): readonly DupeFinding[] {\n return [...findings].sort(compareFindings);\n}\n\nfunction compareFindings(\n left: { readonly kind: LiteralKind; readonly value: string; readonly test: LiteralLocation },\n right: { readonly kind: LiteralKind; readonly value: string; readonly test: LiteralLocation },\n): number {\n return (\n left.test.file.localeCompare(right.test.file)\n || left.test.line - right.test.line\n || left.kind.localeCompare(right.kind)\n || left.value.localeCompare(right.value)\n );\n}\n\nfunction compareLiteralProblems(left: LiteralProblem, right: LiteralProblem): number {\n return (\n left.test.file.localeCompare(right.test.file)\n || left.test.line - right.test.line\n || left.literalKind.localeCompare(right.literalKind)\n || left.value.localeCompare(right.value)\n );\n}\n\nfunction formatLiteralValue(kind: LiteralKind, value: string): string {\n return kind === \"string\" ? `\"${value}\"` : value;\n}\n\nfunction formatLoc(loc: LiteralLocation): string {\n return `${loc.file}:${loc.line}`;\n}\n","/**\n * TypeScript validation step.\n *\n * Validates TypeScript code using the tsc compiler.\n *\n * @module validation/steps/typescript\n */\n\nimport { existsSync, mkdirSync, rmSync, writeFileSync } from \"node:fs\";\nimport { mkdtemp } from \"node:fs/promises\";\nimport { isAbsolute, join } from \"node:path\";\n\nimport { lifecycleProcessRunner, type ProcessRunner, spawnManagedSubprocess } from \"@/lib/process-lifecycle\";\nimport { TSCONFIG_FILES } from \"../config/scope\";\nimport type { ScopeConfig, ValidationScope } from \"../types\";\nimport { VALIDATION_SCOPES } from \"../types\";\nimport {\n defaultValidationSubprocessOutputStreams,\n forwardValidationSubprocessOutput,\n VALIDATION_SUBPROCESS_EVENTS,\n type ValidationSubprocessOutputStreams,\n} from \"./subprocess-output\";\n\n// =============================================================================\n// DEFAULT DEPENDENCIES\n// =============================================================================\n\n/**\n * Default production process runner for TypeScript.\n */\nexport const defaultTypeScriptProcessRunner: ProcessRunner = lifecycleProcessRunner;\n\n/**\n * Dependencies for file-specific TypeScript validation.\n */\nexport interface TypeScriptDeps {\n mkdtemp: typeof mkdtemp;\n mkdirSync: typeof mkdirSync;\n writeFileSync: typeof writeFileSync;\n rmSync: typeof rmSync;\n existsSync: typeof existsSync;\n}\n\n/**\n * Default production dependencies.\n */\nexport const defaultTypeScriptDeps: TypeScriptDeps = {\n mkdtemp,\n mkdirSync,\n writeFileSync,\n rmSync,\n existsSync,\n};\n\nexport interface TypeScriptValidationContext {\n readonly scope: ValidationScope;\n readonly projectRoot: string;\n readonly files?: readonly string[];\n readonly scopeConfig?: ScopeConfig;\n}\n\nexport interface TypeScriptValidationOptions {\n readonly runner?: ProcessRunner;\n readonly deps?: TypeScriptDeps;\n readonly outputStreams?: ValidationSubprocessOutputStreams;\n}\n\n/**\n * Compiler options for a temporary `tsconfig.json`; all else is inherited via `extends`.\n */\nconst TEMPORARY_TSCONFIG_COMPILER_OPTIONS = { noEmit: true } as const;\n\n/**\n * Parent directory segments for temporary validation configs — kept under the project's `node_modules` so the temporary file never appears in the project's tracked working tree.\n */\nexport const TEMPORARY_TSCONFIG_PARENT_SEGMENTS = [\"node_modules\", \".cache\", \"spx\"] as const;\n\n/**\n * Directory-name prefix for temporary validation configs.\n */\nconst TEMPORARY_TSCONFIG_DIR_PREFIX = \"validate-ts-\";\n\n/**\n * Create the temporary directory that holds one validation `tsconfig.json`.\n */\nasync function createTemporaryTsconfigDir(projectRoot: string, deps: TypeScriptDeps): Promise<string> {\n const parent = join(projectRoot, ...TEMPORARY_TSCONFIG_PARENT_SEGMENTS);\n deps.mkdirSync(parent, { recursive: true });\n return deps.mkdtemp(join(parent, TEMPORARY_TSCONFIG_DIR_PREFIX));\n}\n\n// =============================================================================\n// PURE ARGUMENT BUILDER\n// =============================================================================\n\n/**\n * Build TypeScript CLI arguments based on validation scope.\n *\n * Pure function for testability - can be verified at Level 1.\n *\n * @param context - Context for building arguments\n * @returns Array of tsc CLI arguments\n *\n * @example\n * ```typescript\n * const args = buildTypeScriptArgs({ scope: \"full\", configFile: \"tsconfig.json\" });\n * // Returns: [\"tsc\", \"--noEmit\"]\n * ```\n */\nexport function buildTypeScriptArgs(context: { scope: ValidationScope; configFile: string }): string[] {\n const { scope, configFile } = context;\n return scope === VALIDATION_SCOPES.FULL ? [\"tsc\", \"--noEmit\"] : [\"tsc\", \"--project\", configFile];\n}\n\n// =============================================================================\n// FILE-SPECIFIC VALIDATION SUPPORT\n// =============================================================================\n\n/**\n * Create a temporary TypeScript configuration file for file-specific validation.\n *\n * @param scope - Validation scope\n * @param files - Files to validate\n * @param deps - Injectable dependencies\n * @returns Config path and cleanup function\n */\nexport async function createFileSpecificTsconfig(\n scope: ValidationScope,\n files: readonly string[],\n projectRoot: string,\n deps: TypeScriptDeps = defaultTypeScriptDeps,\n): Promise<{ configPath: string; tempDir: string; cleanup: () => void }> {\n // Create temporary directory\n const tempDir = await createTemporaryTsconfigDir(projectRoot, deps);\n const configPath = join(tempDir, \"tsconfig.json\");\n\n // Get base config file\n const baseConfigFile = TSCONFIG_FILES[scope];\n\n // Ensure all file paths are absolute\n const absoluteFiles = files.map((file) => (isAbsolute(file) ? file : join(projectRoot, file)));\n\n // Create temporary tsconfig that extends the base config\n const tempConfig = {\n extends: join(projectRoot, baseConfigFile),\n files: absoluteFiles,\n include: [],\n exclude: [],\n compilerOptions: TEMPORARY_TSCONFIG_COMPILER_OPTIONS,\n };\n\n // Write temporary config\n deps.writeFileSync(configPath, JSON.stringify(tempConfig, null, 2));\n\n // Return config path and cleanup function\n const cleanup = () => {\n try {\n deps.rmSync(tempDir, { recursive: true, force: true });\n } catch {\n // Cleanup error - don't fail validation\n }\n };\n\n return { configPath, tempDir, cleanup };\n}\n\nasync function createScopeFilteredTsconfig(\n scope: ValidationScope,\n projectRoot: string,\n scopeConfig: ScopeConfig,\n deps: TypeScriptDeps = defaultTypeScriptDeps,\n): Promise<{ configPath: string; tempDir: string; cleanup: () => void }> {\n const tempDir = await createTemporaryTsconfigDir(projectRoot, deps);\n const configPath = join(tempDir, \"tsconfig.json\");\n const baseConfigFile = TSCONFIG_FILES[scope];\n const toProjectPathPattern = (pattern: string) => isAbsolute(pattern) ? pattern : join(projectRoot, pattern);\n const tempConfig = {\n extends: join(projectRoot, baseConfigFile),\n include: scopeConfig.filePatterns.map(toProjectPathPattern),\n exclude: scopeConfig.excludePatterns.map(toProjectPathPattern),\n compilerOptions: TEMPORARY_TSCONFIG_COMPILER_OPTIONS,\n };\n\n deps.writeFileSync(configPath, JSON.stringify(tempConfig, null, 2));\n\n const cleanup = () => {\n try {\n deps.rmSync(tempDir, { recursive: true, force: true });\n } catch {\n // Cleanup error - don't fail validation\n }\n };\n\n return { configPath, tempDir, cleanup };\n}\n\n// =============================================================================\n// VALIDATION FUNCTION\n// =============================================================================\n\n/**\n * Validate TypeScript using authoritative configuration.\n *\n * @param context - Validation scope, project root, files, and optional path-filtered scope\n * @param options - Injectable process runner, filesystem dependencies, and output streams\n * @returns Promise resolving to validation result\n *\n * @example\n * ```typescript\n * const result = await validateTypeScript({ scope: \"full\", projectRoot });\n * if (!result.success) {\n * console.error(\"TypeScript failed:\", result.error);\n * }\n * ```\n */\nexport async function validateTypeScript(\n context: TypeScriptValidationContext,\n options: TypeScriptValidationOptions = {},\n): Promise<{\n success: boolean;\n error?: string;\n skipped?: boolean;\n}> {\n const { scope, projectRoot, files, scopeConfig } = context;\n const {\n runner = defaultTypeScriptProcessRunner,\n deps = defaultTypeScriptDeps,\n outputStreams = defaultValidationSubprocessOutputStreams,\n } = options;\n const configFile = TSCONFIG_FILES[scope];\n\n // Determine tool and arguments based on whether specific files are provided\n let tool: string;\n let tscArgs: string[];\n\n if (files && files.length > 0) {\n // File-specific validation using custom temporary tsconfig\n const { configPath, cleanup } = await createFileSpecificTsconfig(scope, files, projectRoot, deps);\n\n try {\n return await new Promise((resolve) => {\n const tscBin = join(projectRoot, \"node_modules\", \".bin\", \"tsc\");\n const tscBinary = deps.existsSync(tscBin) ? tscBin : \"npx\";\n const tscArgs = tscBinary === \"npx\" ? [\"tsc\", \"--project\", configPath] : [\"--project\", configPath];\n const tscProcess = spawnManagedSubprocess(runner, tscBinary, tscArgs, {\n cwd: projectRoot,\n });\n forwardValidationSubprocessOutput(tscProcess, outputStreams);\n\n tscProcess.on(VALIDATION_SUBPROCESS_EVENTS.CLOSE, (code) => {\n cleanup();\n if (code === 0) {\n resolve({ success: true, skipped: false });\n } else {\n resolve({ success: false, error: `TypeScript exited with code ${code}` });\n }\n });\n\n tscProcess.on(VALIDATION_SUBPROCESS_EVENTS.ERROR, (error) => {\n cleanup();\n resolve({ success: false, error: error.message });\n });\n });\n } catch (error) {\n cleanup();\n const errorMessage = error instanceof Error ? error.message : String(error);\n return { success: false, error: `Failed to create temporary config: ${errorMessage}` };\n }\n } else if (scopeConfig?.filteredByValidationPaths) {\n if (scopeConfig.filteredByValidationPathNoMatches) {\n return { success: true, skipped: true };\n }\n if (scopeConfig.filePatterns.length === 0 && scopeConfig.directories.length === 0) {\n return { success: true, skipped: true };\n }\n const { configPath, cleanup } = await createScopeFilteredTsconfig(scope, projectRoot, scopeConfig, deps);\n const tscBin = join(projectRoot, \"node_modules\", \".bin\", \"tsc\");\n tool = deps.existsSync(tscBin) ? tscBin : \"npx\";\n tscArgs = tool === \"npx\" ? [\"tsc\", \"--project\", configPath] : [\"--project\", configPath];\n return new Promise((resolve) => {\n const tscProcess = spawnManagedSubprocess(runner, tool, tscArgs, {\n cwd: projectRoot,\n });\n forwardValidationSubprocessOutput(tscProcess, outputStreams);\n\n tscProcess.on(VALIDATION_SUBPROCESS_EVENTS.CLOSE, (code) => {\n cleanup();\n if (code === 0) {\n resolve({ success: true, skipped: false });\n } else {\n resolve({ success: false, error: `TypeScript exited with code ${code}` });\n }\n });\n\n tscProcess.on(VALIDATION_SUBPROCESS_EVENTS.ERROR, (error) => {\n cleanup();\n resolve({ success: false, error: error.message });\n });\n });\n } else {\n // Full validation using tsc\n const tscBin = join(projectRoot, \"node_modules\", \".bin\", \"tsc\");\n tool = deps.existsSync(tscBin) ? tscBin : \"npx\";\n const rawArgs = buildTypeScriptArgs({ scope, configFile });\n tscArgs = tool === \"npx\" ? rawArgs : rawArgs.slice(1);\n }\n\n return new Promise((resolve) => {\n const tscProcess = spawnManagedSubprocess(runner, tool, tscArgs, {\n cwd: projectRoot,\n });\n forwardValidationSubprocessOutput(tscProcess, outputStreams);\n\n tscProcess.on(VALIDATION_SUBPROCESS_EVENTS.CLOSE, (code) => {\n if (code === 0) {\n resolve({ success: true, skipped: false });\n } else {\n resolve({ success: false, error: `TypeScript exited with code ${code}` });\n }\n });\n\n tscProcess.on(VALIDATION_SUBPROCESS_EVENTS.ERROR, (error) => {\n resolve({ success: false, error: error.message });\n });\n });\n}\n","/**\n * TypeScript validation command.\n *\n * Runs TypeScript type checking using tsc.\n */\nimport { resolveConfig } from \"@/config/index\";\nimport {\n VALIDATION_PATH_TOOL_SUBSECTIONS,\n type ValidationConfig,\n validationConfigDescriptor,\n} from \"@/validation/config/descriptor\";\nimport {\n applyValidationPathFilterToScope,\n pathPassesValidationFilter,\n toProjectRelativeValidationPath,\n validationPathFilterForTool,\n} from \"@/validation/config/path-filter\";\nimport { getTypeScriptScope } from \"@/validation/config/scope\";\nimport { detectTypeScript, discoverTool, formatSkipMessage } from \"@/validation/discovery/index\";\nimport { validateTypeScript } from \"@/validation/steps/typescript\";\nimport {\n formatTypeScriptAbsentSkipMessage,\n formatValidationPathsNoTargetsSkipMessage,\n VALIDATION_COMMAND_OUTPUT,\n VALIDATION_STAGE_DISPLAY_NAMES,\n} from \"./messages\";\nimport type { TypeScriptCommandOptions, ValidationCommandResult } from \"./types\";\n\nexport const TYPESCRIPT_VALIDATION_MESSAGES = {\n ABSENT: formatTypeScriptAbsentSkipMessage(VALIDATION_STAGE_DISPLAY_NAMES.TYPESCRIPT),\n CONFIG_ERROR: `${VALIDATION_STAGE_DISPLAY_NAMES.TYPESCRIPT}: ✗ config error`,\n NO_VALIDATION_PATH_TARGETS: formatValidationPathsNoTargetsSkipMessage(VALIDATION_STAGE_DISPLAY_NAMES.TYPESCRIPT),\n SUCCESS: VALIDATION_COMMAND_OUTPUT.TYPESCRIPT_SUCCESS,\n TOOL_LABEL: VALIDATION_STAGE_DISPLAY_NAMES.TYPESCRIPT,\n} as const;\n\n/**\n * Run TypeScript type checking.\n *\n * Gates tsc execution on language detection: without a `tsconfig.json` in the\n * project root there is nothing to type-check, and invoking tsc regardless\n * causes it to walk up and compile an ancestor project instead.\n *\n * @param options - Command options\n * @returns Command result with exit code and output\n */\nexport async function typescriptCommand(options: TypeScriptCommandOptions): Promise<ValidationCommandResult> {\n const { cwd, scope = \"full\", files, quiet } = options;\n const startTime = Date.now();\n\n // Gate 1: language detection. No TypeScript = skip cleanly.\n const tsDetection = detectTypeScript(cwd);\n if (!tsDetection.present) {\n return {\n exitCode: 0,\n output: quiet ? \"\" : TYPESCRIPT_VALIDATION_MESSAGES.ABSENT,\n durationMs: Date.now() - startTime,\n };\n }\n\n const loaded = await resolveConfig(cwd, [validationConfigDescriptor]);\n if (!loaded.ok) {\n return {\n exitCode: 1,\n output: `${TYPESCRIPT_VALIDATION_MESSAGES.CONFIG_ERROR} — ${loaded.error}`,\n durationMs: Date.now() - startTime,\n };\n }\n const validationConfig = loaded.value[validationConfigDescriptor.section] as ValidationConfig;\n const validationPathFilter = validationPathFilterForTool(\n validationConfig.paths,\n VALIDATION_PATH_TOOL_SUBSECTIONS.TYPESCRIPT,\n );\n const scopeConfig = applyValidationPathFilterToScope(\n getTypeScriptScope(scope, cwd),\n validationPathFilter,\n );\n const filteredFiles = files\n ?.map((file) => toProjectRelativeValidationPath(cwd, file))\n .filter((file) => pathPassesValidationFilter(file, validationPathFilter));\n\n if (\n scopeConfig.filteredByValidationPathNoMatches\n || (files !== undefined && files.length > 0 && filteredFiles?.length === 0)\n ) {\n return {\n exitCode: 0,\n output: quiet ? \"\" : TYPESCRIPT_VALIDATION_MESSAGES.NO_VALIDATION_PATH_TARGETS,\n durationMs: Date.now() - startTime,\n };\n }\n\n // Gate 2: tool discovery — ensure tsc itself is available somewhere.\n const toolResult = await discoverTool(\"typescript\", { projectRoot: cwd });\n if (!toolResult.found) {\n const skipMessage = formatSkipMessage(VALIDATION_STAGE_DISPLAY_NAMES.TYPESCRIPT, toolResult);\n return { exitCode: 0, output: skipMessage, durationMs: Date.now() - startTime };\n }\n\n const result = await validateTypeScript({\n scope,\n projectRoot: cwd,\n files: filteredFiles,\n scopeConfig,\n });\n const durationMs = Date.now() - startTime;\n\n // Map result to command output\n if (result.skipped) {\n const output = quiet ? \"\" : TYPESCRIPT_VALIDATION_MESSAGES.NO_VALIDATION_PATH_TARGETS;\n return { exitCode: 0, output, durationMs };\n } else if (result.success) {\n const output = quiet ? \"\" : TYPESCRIPT_VALIDATION_MESSAGES.SUCCESS;\n return { exitCode: 0, output, durationMs };\n } else {\n const output = result.error ?? VALIDATION_COMMAND_OUTPUT.TYPESCRIPT_FAILURE;\n return { exitCode: 1, output, durationMs };\n }\n}\n","/**\n * TypeScript validation language descriptor.\n *\n * Declares the validation stages a TypeScript project contributes to the\n * pipeline: circular-dependency detection, unused-code detection, ESLint,\n * type checking, and literal-reuse detection. The registry imports this\n * descriptor with an explicit import statement; orchestration never names\n * these stages directly.\n */\nimport { circularCommand } from \"@/commands/validation/circular\";\nimport { knipCommand } from \"@/commands/validation/knip\";\nimport { lintCommand } from \"@/commands/validation/lint\";\nimport { literalCommand } from \"@/commands/validation/literal\";\nimport {\n LITERAL_SKIP_JSON_OUTPUT,\n LITERAL_SKIP_OUTPUT,\n VALIDATION_STAGE_DISPLAY_NAMES,\n} from \"@/commands/validation/messages\";\nimport type { ValidationCommandResult } from \"@/commands/validation/types\";\nimport { typescriptCommand } from \"@/commands/validation/typescript\";\nimport type { ValidationLanguageDescriptor, ValidationStageContext } from \"@/validation/languages/types\";\n\nconst TYPESCRIPT_LANGUAGE_NAME = \"typescript\";\n\n/**\n * Literal-reuse stage runner.\n *\n * A full-pipeline run may skip literal detection; the skip emits the canonical\n * skip notice (text or JSON) and reports success without invoking the detector.\n */\nasync function runLiteralStage(context: ValidationStageContext): Promise<ValidationCommandResult> {\n if (context.skipLiteral) {\n const skipOutput = context.json ? LITERAL_SKIP_JSON_OUTPUT : LITERAL_SKIP_OUTPUT;\n return { exitCode: 0, output: context.quiet ? \"\" : skipOutput };\n }\n return literalCommand({\n cwd: context.cwd,\n files: context.files,\n quiet: context.quiet,\n json: context.json,\n });\n}\n\nexport const typescriptValidationLanguage: ValidationLanguageDescriptor = {\n name: TYPESCRIPT_LANGUAGE_NAME,\n stages: [\n {\n name: VALIDATION_STAGE_DISPLAY_NAMES.CIRCULAR,\n failsPipeline: true,\n run: (context) => circularCommand({ cwd: context.cwd, quiet: context.quiet, json: context.json }),\n },\n {\n name: VALIDATION_STAGE_DISPLAY_NAMES.KNIP,\n // Knip is informational: unused-code findings never fail the pipeline.\n failsPipeline: false,\n run: (context) => knipCommand({ cwd: context.cwd, quiet: context.quiet, json: context.json }),\n },\n {\n name: VALIDATION_STAGE_DISPLAY_NAMES.ESLINT,\n failsPipeline: true,\n run: (context) =>\n lintCommand({\n cwd: context.cwd,\n scope: context.scope,\n files: context.files,\n fix: context.fix,\n quiet: context.quiet,\n json: context.json,\n }),\n },\n {\n name: VALIDATION_STAGE_DISPLAY_NAMES.TYPESCRIPT,\n failsPipeline: true,\n run: (context) =>\n typescriptCommand({\n cwd: context.cwd,\n scope: context.scope,\n files: context.files,\n quiet: context.quiet,\n json: context.json,\n }),\n },\n {\n name: VALIDATION_STAGE_DISPLAY_NAMES.LITERAL,\n failsPipeline: true,\n run: runLiteralStage,\n },\n ],\n};\n","/**\n * Validation language registry.\n *\n * Composes the validation pipeline from explicitly imported language\n * descriptors. Orchestration code iterates `validationPipelineStages`; it never\n * references a language or stage by name and never discovers descriptors through\n * filesystem scanning. Adding a language is one descriptor module plus one entry\n * here.\n */\nimport { markdownValidationLanguage } from \"@/validation/languages/markdown\";\nimport type { ValidationRegistry } from \"@/validation/languages/types\";\nimport { typescriptValidationLanguage } from \"@/validation/languages/typescript\";\n\nexport const validationRegistry: ValidationRegistry = {\n languages: [typescriptValidationLanguage, markdownValidationLanguage],\n};\n\n/** Flattened, ordered pipeline stages composed from every registered language. */\nexport const validationPipelineStages = validationRegistry.languages.flatMap(\n (language) => language.stages,\n);\n\n/** Total pipeline step count, derived from the registry rather than a constant. */\nexport const VALIDATION_PIPELINE_TOTAL_STEPS = validationPipelineStages.length;\n","/**\n * Output formatting functions for validation commands.\n *\n * Pure functions that format validation results for CLI display.\n * These functions have no side effects and are fully testable.\n */\n\n/** Threshold in milliseconds for switching from ms to seconds display */\nexport const DURATION_THRESHOLD_MS = 1000;\n\n/** Symbols used in validation output */\nexport const VALIDATION_SYMBOLS = {\n SUCCESS: \"✓\",\n FAILURE: \"✗\",\n} as const;\n\nexport const VALIDATION_SUMMARY_STATUS = {\n PASSED: \"passed\",\n FAILED: \"failed\",\n} as const;\n\n/**\n * Format a duration in milliseconds for display.\n *\n * @param ms - Duration in milliseconds\n * @returns Formatted string (e.g., \"500ms\" or \"1.5s\")\n */\nexport function formatDuration(ms: number): string {\n if (ms < DURATION_THRESHOLD_MS) {\n return `${ms}ms`;\n }\n const seconds = ms / 1000;\n return `${seconds.toFixed(1)}s`;\n}\n\n/** Options for formatting a validation step output */\nexport interface FormatStepOptions {\n /** Current step number (1-indexed) */\n stepNumber: number;\n /** Total number of steps */\n totalSteps: number;\n /** Name of the validation step */\n name: string;\n /** Result message (e.g., \"✓ No errors found\") */\n result: string;\n /** Duration in milliseconds */\n durationMs: number;\n}\n\n/**\n * Format a validation step result for display.\n *\n * @param options - Step formatting options\n * @returns Formatted string (e.g., \"[1/4] ESLint: ✓ No errors found (0.8s)\")\n */\nexport function formatStepOutput(options: FormatStepOptions): string {\n const { stepNumber, totalSteps, name, result, durationMs } = options;\n const duration = formatDuration(durationMs);\n return `[${stepNumber}/${totalSteps}] ${name}: ${result} (${duration})`;\n}\n\n/** Options for formatting the validation summary */\nexport interface FormatSummaryOptions {\n /** Whether all required validations passed */\n success: boolean;\n /** Total duration in milliseconds */\n totalDurationMs: number;\n}\n\n/**\n * Format the final validation summary.\n *\n * @param options - Summary formatting options\n * @returns Formatted string (e.g., \"✓ Validation passed (2.7s total)\")\n */\nexport function formatSummary(options: FormatSummaryOptions): string {\n const { success, totalDurationMs } = options;\n const symbol = success ? VALIDATION_SYMBOLS.SUCCESS : VALIDATION_SYMBOLS.FAILURE;\n const status = success ? VALIDATION_SUMMARY_STATUS.PASSED : VALIDATION_SUMMARY_STATUS.FAILED;\n const duration = formatDuration(totalDurationMs);\n return `${symbol} Validation ${status} (${duration} total)`;\n}\n","/**\n * Run all validations command.\n *\n * Iterates the language registry, executing each composed validation stage in\n * registry order and reporting every stage's result. Stage participation and\n * step count derive entirely from the registry — no stage is dispatched by name.\n */\nimport { VALIDATION_PIPELINE_TOTAL_STEPS, validationPipelineStages } from \"@/validation/registry\";\nimport { formatDuration, formatSummary } from \"./format\";\nimport type { AllCommandOptions, ValidationCommandResult } from \"./types\";\n\n/**\n * Format step output with step number and timing.\n *\n * @param stepNumber - Current step number (1-indexed)\n * @param result - Validation result\n * @param quiet - Whether to suppress output\n * @returns Formatted output string\n */\nfunction formatStepWithTiming(\n stepNumber: number,\n result: ValidationCommandResult,\n quiet: boolean,\n): string {\n if (quiet || !result.output) return \"\";\n\n const timing = result.durationMs === undefined ? \"\" : ` (${formatDuration(result.durationMs)})`;\n return `[${stepNumber}/${VALIDATION_PIPELINE_TOTAL_STEPS}] ${result.output}${timing}`;\n}\n\n/**\n * Run all validation steps.\n *\n * @param options - Command options\n * @returns Command result with exit code and output\n */\nexport async function allCommand(options: AllCommandOptions): Promise<ValidationCommandResult> {\n const { cwd, scope, files, fix, quiet = false, json, skipLiteral = false } = options;\n const startTime = Date.now();\n const outputs: string[] = [];\n let hasFailure = false;\n\n const context = { cwd, scope, files, fix, quiet, json, skipLiteral };\n\n let stepNumber = 0;\n for (const stage of validationPipelineStages) {\n stepNumber += 1;\n const result = await stage.run(context);\n const stepOutput = formatStepWithTiming(stepNumber, result, quiet);\n if (stepOutput) outputs.push(stepOutput);\n if (stage.failsPipeline && result.exitCode !== 0) hasFailure = true;\n }\n\n // Calculate total duration\n const totalDurationMs = Date.now() - startTime;\n\n // Add summary line\n if (!quiet) {\n const summary = formatSummary({ success: !hasFailure, totalDurationMs });\n outputs.push(\"\", summary); // Empty line before summary\n }\n\n return {\n exitCode: hasFailure ? 1 : 0,\n output: outputs.join(\"\\n\"),\n durationMs: totalDurationMs,\n };\n}\n","export const MAX_CLI_ARGUMENT_DISPLAY_LENGTH = 120;\nexport const ELLIPSIS_TOKEN = \"...\";\n\nexport const SENTINEL_UNDEFINED = \"<undefined>\";\nexport const SENTINEL_NULL = \"<null>\";\nexport const SENTINEL_EMPTY = \"<empty>\";\n\nexport const CONTROL_CHAR_UPPER_BOUND = 0x1f;\nexport const DEL_CHAR_CODE = 0x7f;\nexport const FIRST_PRINTABLE_CHAR_CODE = 0x20;\n\nexport const HEX_RADIX = 16;\nexport const HEX_PAD = 2;\n\nexport function formatHexEscape(code: number): string {\n return `\\\\x${code.toString(HEX_RADIX).padStart(HEX_PAD, \"0\")}`;\n}\n\nexport function nonStringSentinel(type: string): string {\n return `<non-string:${type}>`;\n}\n\nexport function sanitizeCliArgument(input: unknown): string {\n if (input === undefined) return SENTINEL_UNDEFINED;\n if (input === null) return SENTINEL_NULL;\n if (typeof input !== \"string\") return nonStringSentinel(typeof input);\n if (input.length === 0) return SENTINEL_EMPTY;\n\n const escaped = escapeControlCharacters(input);\n return truncate(escaped);\n}\n\nfunction escapeControlCharacters(value: string): string {\n let out = \"\";\n for (const char of value) {\n const code = char.codePointAt(0);\n if (code === undefined) continue;\n if (code <= CONTROL_CHAR_UPPER_BOUND || code === DEL_CHAR_CODE) {\n out += formatHexEscape(code);\n } else {\n out += char;\n }\n }\n return out;\n}\n\nfunction truncate(value: string): string {\n if (value.length <= MAX_CLI_ARGUMENT_DISPLAY_LENGTH) return value;\n return value.slice(0, MAX_CLI_ARGUMENT_DISPLAY_LENGTH - ELLIPSIS_TOKEN.length) + ELLIPSIS_TOKEN;\n}\n","import { rename, writeFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\n\nimport {\n type ConfigFile,\n configFileForFormat,\n type ConfigFileReadResult,\n DEFAULT_CONFIG_FILE_FORMAT,\n formatConfigFileAmbiguityError,\n parseConfigFileSections,\n readProductConfigFile,\n serializeConfigFileSectionsWithSetIn,\n} from \"@/config/index\";\nimport type { Result } from \"@/config/types\";\nimport {\n VALIDATION_LITERAL_SUBSECTION,\n VALIDATION_LITERAL_VALUES_SUBSECTION,\n VALIDATION_SECTION,\n} from \"@/validation/config/descriptor\";\n\nimport { type LiteralConfig, literalConfigDescriptor } from \"./config\";\nimport { validateLiteralReuse } from \"./index\";\n\nexport interface ConfigReader {\n read(productDir: string): Promise<Result<ConfigFileReadResult>>;\n}\n\nexport interface ConfigWriter {\n write(filePath: string, content: string): Promise<void>;\n}\n\nexport interface AllowlistExistingOptions {\n readonly productDir: string;\n readonly reader?: ConfigReader;\n readonly writer?: ConfigWriter;\n}\n\nexport interface AllowlistExistingResult {\n readonly exitCode: number;\n readonly output: string;\n}\n\nconst EXIT_OK = 0;\nconst EXIT_ERROR = 1;\nconst INCLUDE_FIELD = \"include\";\nconst ALLOWLIST_INCLUDE_PATH = [\n VALIDATION_SECTION,\n VALIDATION_LITERAL_SUBSECTION,\n VALIDATION_LITERAL_VALUES_SUBSECTION,\n INCLUDE_FIELD,\n] as const;\nconst TEMP_FILE_PREFIX = \".spx-allowlist-existing-\";\nconst TEMP_FILE_SUFFIX = \".tmp\";\nconst RANDOM_BASE = 36;\nconst RANDOM_PREFIX_SLICE = 2;\nconst RANDOM_TOKEN_LENGTH = 10;\n\nexport const productionReader: ConfigReader = {\n read: readProductConfigFile,\n};\n\nexport const productionWriter: ConfigWriter = {\n async write(filePath: string, content: string): Promise<void> {\n const dir = dirname(filePath);\n const random = Math.random()\n .toString(RANDOM_BASE)\n .slice(RANDOM_PREFIX_SLICE, RANDOM_PREFIX_SLICE + RANDOM_TOKEN_LENGTH);\n const tmpPath = join(dir, `${TEMP_FILE_PREFIX}${random}${TEMP_FILE_SUFFIX}`);\n await writeFile(tmpPath, content, \"utf8\");\n await rename(tmpPath, filePath);\n },\n};\n\nexport async function allowlistExisting(\n options: AllowlistExistingOptions,\n): Promise<AllowlistExistingResult> {\n const reader = options.reader ?? productionReader;\n const writer = options.writer ?? productionWriter;\n\n const readResult = await reader.read(options.productDir);\n if (!readResult.ok) {\n return { exitCode: EXIT_ERROR, output: readResult.error };\n }\n\n const configRead = readResult.value;\n if (configRead.kind === \"ambiguous\") {\n return { exitCode: EXIT_ERROR, output: formatConfigFileAmbiguityError(configRead.detected) };\n }\n\n const currentLiteralConfig = readCurrentLiteralConfig(configRead);\n if (!currentLiteralConfig.ok) {\n return { exitCode: EXIT_ERROR, output: currentLiteralConfig.error };\n }\n\n const detection = await validateLiteralReuse({\n productDir: options.productDir,\n config: currentLiteralConfig.value,\n });\n\n const findingValues = collectFindingValues(detection.findings);\n const updatedInclude = computeUpdatedInclude(\n currentLiteralConfig.value.include,\n findingValues,\n );\n\n const target: ConfigFile = configRead.kind === \"ok\"\n ? configRead.file\n : configFileForFormat(options.productDir, DEFAULT_CONFIG_FILE_FORMAT);\n\n const serialized = serializeWithUpdatedInclude(target, updatedInclude);\n if (!serialized.ok) {\n return { exitCode: EXIT_ERROR, output: serialized.error };\n }\n await writer.write(target.path, serialized.value);\n\n return { exitCode: EXIT_OK, output: \"\" };\n}\n\nfunction readCurrentLiteralConfig(read: ConfigFileReadResult): Result<LiteralConfig> {\n if (read.kind !== \"ok\") return { ok: true, value: literalConfigDescriptor.defaults };\n const sections = parseConfigFileSections(read.file);\n if (!sections.ok) return sections;\n const validationRaw = sections.value[VALIDATION_SECTION];\n if (typeof validationRaw !== \"object\" || validationRaw === null) {\n return { ok: true, value: literalConfigDescriptor.defaults };\n }\n const literalRaw = (validationRaw as Record<string, unknown>)[VALIDATION_LITERAL_SUBSECTION];\n if (typeof literalRaw !== \"object\" || literalRaw === null) {\n return { ok: true, value: literalConfigDescriptor.defaults };\n }\n const valuesRaw = (literalRaw as Record<string, unknown>)[VALIDATION_LITERAL_VALUES_SUBSECTION];\n if (valuesRaw === undefined) {\n return { ok: true, value: literalConfigDescriptor.defaults };\n }\n const validated = literalConfigDescriptor.validate(valuesRaw);\n return validated.ok ? validated : { ok: true, value: literalConfigDescriptor.defaults };\n}\n\nfunction collectFindingValues(\n findings: {\n readonly srcReuse: readonly { readonly value: string }[];\n readonly testDupe: readonly { readonly value: string }[];\n },\n): readonly string[] {\n const values = new Set<string>();\n for (const finding of findings.srcReuse) values.add(finding.value);\n for (const finding of findings.testDupe) values.add(finding.value);\n return [...values];\n}\n\nfunction computeUpdatedInclude(\n existing: readonly string[] | undefined,\n findingValues: readonly string[],\n): readonly string[] {\n const existingArr = existing ?? [];\n const existingSet = new Set(existingArr);\n const additions = findingValues.filter((value) => !existingSet.has(value)).sort();\n return [...existingArr, ...additions];\n}\n\nfunction serializeWithUpdatedInclude(target: ConfigFile, include: readonly string[]): Result<string> {\n return serializeConfigFileSectionsWithSetIn(target, ALLOWLIST_INCLUDE_PATH, [...include]);\n}\n","import type { Command } from \"commander\";\n\nimport {\n allCommand,\n circularCommand,\n knipCommand,\n lintCommand,\n LITERAL_PROBLEM_KIND,\n literalCommand,\n type LiteralProblemKind,\n markdownCommand,\n typescriptCommand,\n} from \"@/commands/validation\";\nimport type { Domain } from \"@/domains/types\";\nimport { sanitizeCliArgument } from \"@/interfaces/cli/sanitize\";\nimport { allowlistExisting } from \"@/validation/literal/allowlist-existing\";\nimport type { ValidationScope } from \"@/validation/types\";\n\ninterface ValidationDomainCommandDefinition {\n readonly commandName: string;\n readonly alias: string;\n readonly description: string;\n}\n\ninterface ValidationSubcommandDefinition {\n readonly commandName: string;\n readonly alias?: string;\n readonly description: string;\n}\n\ninterface ValidationCliDefinition {\n readonly domain: ValidationDomainCommandDefinition;\n readonly subcommands: {\n readonly typescript: ValidationSubcommandDefinition;\n readonly lint: ValidationSubcommandDefinition;\n readonly circular: ValidationSubcommandDefinition;\n readonly knip: ValidationSubcommandDefinition;\n readonly literal: ValidationSubcommandDefinition;\n readonly markdown: ValidationSubcommandDefinition;\n readonly all: ValidationSubcommandDefinition;\n };\n readonly commanderHelpOperands: {\n readonly subcommand: string;\n readonly longFlag: string;\n readonly shortFlag: string;\n };\n readonly diagnostics: {\n readonly unknownSubcommand: {\n readonly messageLabel: string;\n readonly exitCode: number;\n };\n readonly unknownLiteralProblemKind: {\n readonly messageLabel: string;\n readonly exitCode: number;\n };\n };\n}\n\nexport const validationCliDefinition: ValidationCliDefinition = {\n domain: {\n commandName: \"validation\",\n alias: \"v\",\n description: \"Run code validation tools\",\n },\n subcommands: {\n typescript: {\n commandName: \"typescript\",\n alias: \"ts\",\n description: \"Run TypeScript type checking\",\n },\n lint: {\n commandName: \"lint\",\n description: \"Run ESLint\",\n },\n circular: {\n commandName: \"circular\",\n description: \"Check for circular dependencies\",\n },\n knip: {\n commandName: \"knip\",\n description: \"Detect unused code\",\n },\n literal: {\n commandName: \"literal\",\n description: \"Detect cross-file literal reuse between source and tests\",\n },\n markdown: {\n commandName: \"markdown\",\n alias: \"md\",\n description: \"Validate markdown link integrity and structure\",\n },\n all: {\n commandName: \"all\",\n description: \"Run all validations\",\n },\n },\n commanderHelpOperands: {\n subcommand: \"help\",\n longFlag: \"--help\",\n shortFlag: \"-h\",\n },\n diagnostics: {\n unknownSubcommand: {\n messageLabel: \"unknown subcommand\",\n exitCode: 1,\n },\n unknownLiteralProblemKind: {\n messageLabel: \"unknown problem kind\",\n exitCode: 1,\n },\n },\n} as const;\n\nexport const literalValidationCliOptions = {\n allowlistExisting: {\n flag: \"--allowlist-existing\",\n description: \"Append every current problem's value to validation.literal.values.include and exit\",\n },\n kind: {\n flag: \"--kind <kind>\",\n description: \"Only report one problem kind (reuse|dupe)\",\n },\n filesWithProblems: {\n flag: \"--files-with-problems\",\n description: \"Print each affected file path once\",\n },\n literals: {\n flag: \"--literals\",\n description: \"Print each affected literal value once\",\n },\n verbose: {\n flag: \"--verbose\",\n description: \"Print grouped problem details\",\n },\n} as const;\n\nexport const allValidationCliOptions = {\n skipLiteral: {\n flag: \"--skip-literal\",\n description: \"Skip literal reuse detection for this validation all run\",\n },\n} as const;\n\nconst validationSubcommandOperands = Object.values(validationCliDefinition.subcommands).flatMap(\n (subcommand) => {\n const operands = [subcommand.commandName];\n if (subcommand.alias !== undefined) operands.push(subcommand.alias);\n return operands;\n },\n);\n\nexport const validationKnownOperands: ReadonlySet<string> = new Set([\n ...validationSubcommandOperands,\n ...Object.values(validationCliDefinition.commanderHelpOperands),\n]);\nexport const validationOptionPrefix = validationCliDefinition.commanderHelpOperands.longFlag.slice(0, 1);\n\n/** Common options for all validation commands */\ninterface CommonOptions {\n scope?: ValidationScope;\n files?: string[];\n quiet?: boolean;\n json?: boolean;\n}\n\n/** Options for lint command */\ninterface LintOptions extends CommonOptions {\n fix?: boolean;\n}\n\ninterface LiteralOptions extends CommonOptions {\n allowlistExisting?: boolean;\n kind?: string;\n filesWithProblems?: boolean;\n literals?: boolean;\n verbose?: boolean;\n}\n\ninterface AllOptions extends CommonOptions {\n fix?: boolean;\n skipLiteral?: boolean;\n}\n\n/**\n * Add common options to a command\n */\nfunction addCommonOptions(cmd: Command): Command {\n return cmd\n .option(\"--scope <scope>\", \"Validation scope (full|production)\", \"full\")\n .option(\"--files <paths...>\", \"Specific files/directories to validate\")\n .option(\"--quiet\", \"Suppress progress output\")\n .option(\"--json\", \"Output results as JSON\");\n}\n\nfunction addValidationSubcommand(\n validationCmd: Command,\n definition: ValidationSubcommandDefinition,\n): Command {\n let subcommand = validationCmd\n .command(definition.commandName)\n .description(definition.description);\n\n if (definition.alias !== undefined) {\n subcommand = subcommand.alias(definition.alias);\n }\n\n return subcommand;\n}\n\n/**\n * Register validation domain commands\n */\nfunction registerValidationCommands(validationCmd: Command): void {\n const { subcommands } = validationCliDefinition;\n\n // typescript command\n const tsCmd = addValidationSubcommand(validationCmd, subcommands.typescript)\n .action(async (options: CommonOptions) => {\n const result = await typescriptCommand({\n cwd: process.cwd(),\n scope: options.scope,\n files: options.files,\n quiet: options.quiet,\n json: options.json,\n });\n if (result.output) console.log(result.output);\n process.exit(result.exitCode);\n });\n addCommonOptions(tsCmd);\n\n // lint command\n const lintCmd = addValidationSubcommand(validationCmd, subcommands.lint)\n .option(\"--fix\", \"Auto-fix issues\")\n .action(async (options: LintOptions) => {\n const result = await lintCommand({\n cwd: process.cwd(),\n scope: options.scope,\n files: options.files,\n fix: options.fix,\n quiet: options.quiet,\n json: options.json,\n });\n if (result.output) console.log(result.output);\n process.exit(result.exitCode);\n });\n addCommonOptions(lintCmd);\n\n // circular command\n const circularCmd = addValidationSubcommand(validationCmd, subcommands.circular)\n .action(async (options: CommonOptions) => {\n const result = await circularCommand({\n cwd: process.cwd(),\n quiet: options.quiet,\n json: options.json,\n });\n if (result.output) console.log(result.output);\n process.exit(result.exitCode);\n });\n addCommonOptions(circularCmd);\n\n // knip command\n const knipCmd = addValidationSubcommand(validationCmd, subcommands.knip)\n .action(async (options: CommonOptions) => {\n const result = await knipCommand({\n cwd: process.cwd(),\n quiet: options.quiet,\n json: options.json,\n });\n if (result.output) console.log(result.output);\n process.exit(result.exitCode);\n });\n addCommonOptions(knipCmd);\n\n // literal command (cross-file literal-reuse detector)\n const literalCmd = addValidationSubcommand(validationCmd, subcommands.literal)\n .option(\n literalValidationCliOptions.allowlistExisting.flag,\n literalValidationCliOptions.allowlistExisting.description,\n )\n .option(literalValidationCliOptions.kind.flag, literalValidationCliOptions.kind.description)\n .option(\n literalValidationCliOptions.filesWithProblems.flag,\n literalValidationCliOptions.filesWithProblems.description,\n )\n .option(literalValidationCliOptions.literals.flag, literalValidationCliOptions.literals.description)\n .option(literalValidationCliOptions.verbose.flag, literalValidationCliOptions.verbose.description)\n .addHelpText(\n \"after\",\n \"\\nEnabled for TypeScript projects by default. Set validation.literal.enabled=false\\n\"\n + \"in spx.config.* to skip during migration.\",\n )\n .action(async (options: LiteralOptions) => {\n if (options.allowlistExisting) {\n const result = await allowlistExisting({ productDir: process.cwd() });\n if (result.output) console.log(result.output);\n process.exit(result.exitCode);\n }\n let kind: LiteralProblemKind | undefined;\n if (options.kind !== undefined) {\n kind = parseLiteralProblemKind(options.kind);\n if (kind === undefined) {\n const { unknownLiteralProblemKind } = validationCliDefinition.diagnostics;\n process.stderr.write(\n `spx validation literal: ${unknownLiteralProblemKind.messageLabel}: ${sanitizeCliArgument(options.kind)}\\n`,\n );\n process.exit(unknownLiteralProblemKind.exitCode);\n }\n }\n const result = await literalCommand({\n cwd: process.cwd(),\n files: options.files,\n kind,\n filesWithProblems: options.filesWithProblems,\n literals: options.literals,\n verbose: options.verbose,\n quiet: options.quiet,\n json: options.json,\n });\n if (result.output) console.log(result.output);\n process.exit(result.exitCode);\n });\n addCommonOptions(literalCmd);\n\n // markdown command\n const markdownCmd = addValidationSubcommand(validationCmd, subcommands.markdown)\n .addHelpText(\n \"after\",\n \"\\nValidates spx/ and docs/ by default. Nodes listed in spx/EXCLUDE are\\n\"\n + \"skipped — use this for declared-state nodes whose [test] links point\\n\"\n + \"to files that do not exist yet.\",\n )\n .action(async (options: CommonOptions) => {\n const result = await markdownCommand({\n cwd: process.cwd(),\n files: options.files,\n quiet: options.quiet,\n });\n if (result.output) console.log(result.output);\n process.exit(result.exitCode);\n });\n addCommonOptions(markdownCmd);\n\n // all command\n const allCmd = addValidationSubcommand(validationCmd, subcommands.all)\n .option(\"--fix\", \"Auto-fix ESLint issues\")\n .option(allValidationCliOptions.skipLiteral.flag, allValidationCliOptions.skipLiteral.description)\n .action(async (options: AllOptions) => {\n const result = await allCommand({\n cwd: process.cwd(),\n scope: options.scope,\n files: options.files,\n fix: options.fix,\n skipLiteral: options.skipLiteral,\n quiet: options.quiet,\n json: options.json,\n });\n if (result.output) console.log(result.output);\n process.exit(result.exitCode);\n });\n addCommonOptions(allCmd);\n}\n\nfunction parseLiteralProblemKind(value: string): LiteralProblemKind | undefined {\n if (value === LITERAL_PROBLEM_KIND.REUSE || value === LITERAL_PROBLEM_KIND.DUPE) {\n return value;\n }\n return undefined;\n}\n\nfunction handleUnknownSubcommand(operands: readonly string[]): never {\n const [first] = operands;\n const sanitized = sanitizeCliArgument(first);\n const { domain, diagnostics } = validationCliDefinition;\n const { unknownSubcommand } = diagnostics;\n process.stderr.write(`spx ${domain.commandName}: ${unknownSubcommand.messageLabel}: ${sanitized}\\n`);\n process.exit(unknownSubcommand.exitCode);\n}\n\nexport const validationDomain: Domain = {\n name: validationCliDefinition.domain.commandName,\n description: validationCliDefinition.domain.description,\n register: (program: Command) => {\n const { domain } = validationCliDefinition;\n const validationCmd = program\n .command(domain.commandName)\n .alias(domain.alias)\n .description(domain.description);\n\n validationCmd.on(\"command:*\", (operands: readonly string[]) => {\n handleUnknownSubcommand(operands);\n });\n\n registerValidationCommands(validationCmd);\n },\n};\n","import type { Domain } from \"@/domains/types\";\n\nimport { auditDomain } from \"./audit\";\nimport { claudeDomain } from \"./claude\";\nimport { configDomain } from \"./config\";\nimport { sessionDomain } from \"./session\";\nimport { specDomain } from \"./spec\";\nimport { testingDomain } from \"./testing\";\nimport { validationDomain } from \"./validation\";\n\nexport const CLI_DOMAINS: readonly Domain[] = [\n auditDomain,\n claudeDomain,\n configDomain,\n sessionDomain,\n specDomain,\n testingDomain,\n validationDomain,\n];\n"],"mappings":"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A,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,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","names":["createRequire","program","fs","fs","fs","path","os","path","program","readFile","join","path","defaults","validateEntry","version","path","value","isRecord","rejectUnknownFields","validateNonEmptyString","path","defaults","validate","path","LAYER","path","basename","isRecord","rejectUnknownFields","validate","validate","defaults","validate","validate","defaults","validatePaths","validate","path","format","path","join","readFile","format","formatConfig","format","resolve","program","dirname","join","output","execa","join","relative","resolve","execa","resolve","statusDirs","join","path","join","dirname","stat","path","join","parseYaml","parseYaml","join","path","stat","mkdir","join","resolve","stringifyYaml","stringifyYaml","SESSION_PRIORITY_VALUES","stringifyYaml","join","resolve","mkdir","readFile","join","join","readFile","mkdir","readdir","readFile","rename","join","readdir","join","readFile","mkdir","rename","readdir","readFile","unlink","join","readdir","join","readFile","lines","unlink","readdir","rename","readdir","rename","readFile","stat","stat","readFile","showCommand","resolve","showCommand","program","readdir","readFile","join","readFile","join","readdir","isFileNotFound","path","snapshot","readdir","join","relative","join","readdir","relative","join","createHash","nodeRandomBytes","nodeMkdir","nodeReaddir","nodeReadFile","nodeRename","nodeWriteFile","join","createHash","join","SHA256_ALGORITHM","HEX_ENCODING","UTF8_ENCODING","ERROR_CODE_NOT_FOUND","path","nodeMkdir","nodeWriteFile","nodeRename","nodeReadFile","nodeReaddir","join","fs","nodeRandomBytes","hasErrorCode","UTF8_ENCODING","ERROR_CODE_NOT_FOUND","path","isRecord","createHash","SHA256_ALGORITHM","HEX_ENCODING","fs","path","join","path","join","readFileSync","join","isNodeError","join","readFileSync","join","mkdir","writeFile","dirname","join","join","mkdir","dirname","writeFile","format","runTests","matchesTestFile","excludeFlag","detect","runTests","fs","path","format","program","program","relative","isAbsolute","relative","normalizePathPrefix","pathMatchesPrefix","path","existsSync","basename","dirname","join","join","existsSync","path","basename","join","dirname","path","relative","value","CharacterCodes","ParseOptions","handleError","ScanError","SyntaxKind","parse","ParseErrorCode","existsSync","readFileSync","isAbsolute","join","PATH_SEGMENT_SEPARATOR","readFileSync","existsSync","path","isAbsolute","join","parse","execSync","fs","path","require","fs","execSync","path","join","join","existsSync","writeFile","isAbsolute","join","existsSync","writeFile","validateKnip","join","resolve","isAbsolute","validateKnip","existsSync","join","existsSync","readdirSync","readFileSync","statSync","join","parse","readFileSync","join","existsSync","visit","readdirSync","statSync","resolve","join","existsSync","TYPESCRIPT_ABSENT_MESSAGE","readFile","isAbsolute","relative","resolve","LAYER","path","path","readdir","join","relative","sep","isNodeError","readdir","join","relative","sep","path","path","PATH_PREFIX_SEPARATOR","normalizePathPrefix","PATH_PREFIX_SEPARATOR","applyPathFilter","isAbsolute","resolve","relative","path","readFile","TYPESCRIPT_ABSENT_MESSAGE","existsSync","mkdtemp","isAbsolute","join","mkdtemp","existsSync","join","isAbsolute","resolve","tscArgs","rename","writeFile","dirname","join","dirname","join","writeFile","rename","result","program","require","createRequire"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/commands/claude/init.ts","../src/lib/claude/permissions/discovery.ts","../src/lib/claude/permissions/parser.ts","../src/lib/file-system/normalizePath.ts","../src/lib/claude/permissions/subsumption.ts","../src/lib/claude/permissions/merger.ts","../src/lib/claude/settings/backup.ts","../src/lib/claude/settings/reporter.ts","../src/lib/claude/settings/writer.ts","../src/commands/claude/settings/consolidate.ts","../src/interfaces/cli/claude.ts","../src/domains/compact/index.ts","../src/domains/session/agent-session.ts","../src/lib/state-store/index.ts","../src/git/root.ts","../src/git/environment.ts","../src/commands/compact/retrieve.ts","../src/commands/compact/store.ts","../src/interfaces/cli/compact.ts","../src/config/index.ts","../src/domains/agent-environment/config.ts","../src/config/primitives/path-filter.ts","../src/domains/audit/config.ts","../src/lib/spec-tree/config.ts","../src/lib/file-inclusion/adapters/eslint.ts","../src/lib/file-inclusion/adapters/knip.ts","../src/lib/file-inclusion/adapters/madge.ts","../src/lib/file-inclusion/adapters/markdownlint.ts","../src/lib/file-inclusion/adapters/pytest.ts","../src/lib/file-inclusion/adapters/tsc.ts","../src/lib/file-inclusion/adapters/vitest.ts","../src/lib/file-inclusion/adapters/index.ts","../src/lib/file-inclusion/ignore-source.ts","../src/lib/file-inclusion/predicates/artifact-directory.ts","../src/lib/file-inclusion/predicates/hidden-prefix.ts","../src/lib/file-inclusion/config.ts","../src/lib/precommit/config.ts","../src/testing/config.ts","../src/validation/literal/config.ts","../src/validation/config/descriptor.ts","../src/config/registry.ts","../src/config/descriptor-digest.ts","../src/commands/config/defaults.ts","../src/commands/config/show.ts","../src/commands/config/validate.ts","../src/domains/config/root.ts","../src/interfaces/cli/write-warning.ts","../src/interfaces/cli/config.ts","../src/commands/session/archive.ts","../src/domains/session/archive.ts","../src/domains/session/batch.ts","../src/domains/session/handoff-base-checklist.ts","../src/domains/session/errors.ts","../src/commands/session/resolve-config.ts","../src/config/defaults.ts","../src/commands/session/delete.ts","../src/domains/session/delete.ts","../src/domains/session/show.ts","../src/domains/session/list.ts","../src/domains/session/timestamp.ts","../src/domains/session/types.ts","../src/commands/session/handoff.ts","../src/domains/session/create.ts","../src/domains/session/handoff-base.ts","../src/domains/session/parse-handoff-input.ts","../src/commands/session/list.ts","../src/commands/session/pickup.ts","../src/domains/session/pickup.ts","../src/commands/session/prune.ts","../src/domains/session/prune.ts","../src/commands/session/release.ts","../src/domains/session/release.ts","../src/commands/session/show.ts","../src/domains/session/help.ts","../src/interfaces/cli/session.ts","../src/lib/spec-tree/index.ts","../src/commands/spec/root.ts","../src/commands/spec/next.ts","../src/commands/testing/discovery.ts","../src/domains/testing/aggregation.ts","../src/domains/testing/grouping.ts","../src/commands/testing/dispatch.ts","../src/commands/testing/run-command.ts","../src/testing/run-state.ts","../src/commands/spec/node-outcome-resolver.ts","../src/lib/node-status/classify.ts","../src/lib/node-status/provider.ts","../src/lib/node-status/read.ts","../src/lib/node-status/update.ts","../src/commands/spec/status.ts","../src/testing/languages/python.ts","../src/validation/discovery/language-finder.ts","../src/testing/languages/python-pytest-contract.ts","../src/testing/languages/typescript.ts","../src/testing/registry.ts","../src/lib/process-lifecycle/exit-codes.ts","../src/lib/process-lifecycle/handlers.ts","../src/lib/process-lifecycle/install.ts","../src/lib/process-lifecycle/registry.ts","../src/lib/process-lifecycle/runner.ts","../src/lib/process-lifecycle/managed-subprocess.ts","../src/interfaces/cli/testing-runner-deps.ts","../src/interfaces/cli/spec.ts","../src/interfaces/cli/testing.ts","../src/commands/validation/markdown.ts","../src/validation/config/path-filter.ts","../src/validation/steps/markdown.ts","../src/commands/validation/messages.ts","../src/validation/languages/markdown.ts","../node_modules/.pnpm/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/impl/scanner.js","../node_modules/.pnpm/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/impl/string-intern.js","../node_modules/.pnpm/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/impl/parser.js","../node_modules/.pnpm/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/main.js","../src/validation/config/scope.ts","../src/validation/discovery/tool-finder.ts","../src/validation/discovery/constants.ts","../src/validation/steps/circular.ts","../src/commands/validation/circular.ts","../src/validation/steps/knip.ts","../src/commands/validation/knip.ts","../src/validation/steps/eslint.ts","../src/validation/lint-policy.ts","../src/validation/lint-policy-constants.ts","../src/validation/types.ts","../src/validation/steps/subprocess-output.ts","../src/commands/validation/lint.ts","../src/validation/literal/index.ts","../src/lib/file-inclusion/predicates/ignore-source.ts","../src/lib/file-inclusion/layer-sequence.ts","../src/lib/file-inclusion/pipeline.ts","../src/validation/literal/detector.ts","../src/domains/spec/fixture-writer-methods.ts","../src/validation/literal/walker.ts","../src/commands/validation/literal.ts","../src/validation/steps/typescript.ts","../src/commands/validation/typescript.ts","../src/validation/languages/typescript.ts","../src/validation/registry.ts","../src/commands/validation/format.ts","../src/commands/validation/all.ts","../src/interfaces/cli/sanitize.ts","../src/validation/literal/allowlist-existing.ts","../src/interfaces/cli/validation.ts","../src/domains/worktree/controlling-process.ts","../src/domains/worktree/occupancy-store.ts","../src/domains/worktree/process-table.ts","../src/commands/worktree/resolve.ts","../src/domains/worktree/worktree-name.ts","../src/commands/worktree/claim.ts","../src/commands/worktree/release.ts","../src/commands/worktree/status.ts","../src/interfaces/cli/worktree.ts","../src/interfaces/cli/registry.ts"],"sourcesContent":["/**\n * CLI entry point for spx\n */\nimport { Command } from \"commander\";\nimport { createRequire } from \"node:module\";\n\nimport { CLI_DOMAINS } from \"./interfaces/cli/registry\";\nimport { installLifecycle } from \"./lib/process-lifecycle\";\n\ninstallLifecycle();\n\nconst require = createRequire(import.meta.url);\nconst { version } = require(\"../package.json\") as { version: string };\n\nconst program = new Command();\n\nprogram\n .name(\"spx\")\n .description(\"Fast, deterministic CLI tool for spec workflow management\")\n .version(version);\n\nfor (const domain of CLI_DOMAINS) {\n domain.register(program);\n}\n\nprogram.parse();\n","/**\n * Init command implementation\n *\n * Wrapper around `claude plugin marketplace` to install/update outcomeeng marketplace\n */\nimport { execa } from \"execa\";\n\n/**\n * Options for init command\n */\nexport interface InitOptions {\n /** Working directory (for testing) */\n cwd?: string;\n}\n\n/**\n * Execute claude init command\n *\n * Wraps the Claude CLI's `plugin marketplace` commands to manage\n * the outcomeeng marketplace installation.\n *\n * Behavior:\n * 1. Check if outcomeeng marketplace exists via `claude plugin marketplace list`\n * 2. If missing: shell `claude plugin marketplace add outcomeeng/plugins`\n * 3. If exists: shell `claude plugin marketplace update outcomeeng`\n * (the marketplace registers under the org name \"outcomeeng\", so the\n * update command stays the same even if the source repo is renamed\n * within the org)\n * 4. Parse output and return status message\n *\n * @param options - Command options\n * @returns Status message\n * @throws Error if claude CLI not available or commands fail\n *\n * @example\n * ```typescript\n * const output = await initCommand();\n * console.log(output);\n * // Output: \"✓ outcomeeng marketplace installed successfully\"\n * // or: \"✓ outcomeeng marketplace updated successfully\"\n * ```\n */\nexport async function initCommand(\n options: InitOptions = {},\n): Promise<string> {\n const cwd = options.cwd || process.cwd();\n\n try {\n // Step 1: Check if outcomeeng marketplace exists\n const { stdout: listOutput } = await execa(\n \"claude\",\n [\"plugin\", \"marketplace\", \"list\"],\n { cwd },\n );\n\n const exists = listOutput.includes(\"outcomeeng\");\n\n // Step 2: Add or update based on existence\n if (!exists) {\n // Add marketplace\n await execa(\n \"claude\",\n [\"plugin\", \"marketplace\", \"add\", \"outcomeeng/plugins\"],\n { cwd },\n );\n\n return \"✓ outcomeeng marketplace installed successfully\\n\\nRun 'claude plugin marketplace list' to view all marketplaces.\";\n } else {\n // Update marketplace\n await execa(\"claude\", [\"plugin\", \"marketplace\", \"update\", \"outcomeeng\"], {\n cwd,\n });\n\n return \"✓ outcomeeng marketplace updated successfully\\n\\nThe marketplace is now up to date.\";\n }\n } catch (error) {\n if (error instanceof Error) {\n // Check for specific error conditions\n if (\n error.message.includes(\"ENOENT\")\n || error.message.includes(\"command not found\")\n ) {\n throw new Error(\n \"Claude CLI not found. Please install Claude Code first.\\n\\nVisit: https://docs.anthropic.com/claude-code\",\n );\n }\n\n throw new Error(`Failed to initialize marketplace: ${error.message}`);\n }\n throw error;\n }\n}\n","/**\n * Discovery of Claude Code settings files across project directories\n */\nimport fs from \"fs/promises\";\nimport path from \"path\";\n\n/**\n * Recursively find all .claude/settings.local.json files under a root directory\n *\n * Walks the directory tree looking for files matching the pattern:\n * `**\\/.claude/settings.local.json`\n *\n * @param root - Root directory path to start searching from\n * @param visited - Set of visited paths to avoid symlink loops (internal use)\n * @returns Promise resolving to array of absolute paths to settings.local.json files\n * @throws Error if root directory doesn't exist or permission denied\n *\n * @example\n * ```typescript\n * const files = await findSettingsFiles(\"~/Code\");\n * // Returns: [\n * // \"/Users/user/Code/project-a/.claude/settings.local.json\",\n * // \"/Users/user/Code/project-b/.claude/settings.local.json\"\n * // ]\n * ```\n */\nexport async function findSettingsFiles(\n root: string,\n visited: Set<string> = new Set(),\n): Promise<string[]> {\n // Normalize and resolve path to handle symlinks and ~ expansion\n const normalizedRoot = path.resolve(root.replace(/^~/, process.env.HOME || \"~\"));\n\n // Check for symlink loops\n if (visited.has(normalizedRoot)) {\n return []; // Skip already visited directories\n }\n visited.add(normalizedRoot);\n\n try {\n // Stat the root to verify it exists and is a directory\n const stats = await fs.stat(normalizedRoot);\n if (!stats.isDirectory()) {\n throw new Error(`Path is not a directory: ${normalizedRoot}`);\n }\n\n // Read directory contents\n const entries = await fs.readdir(normalizedRoot, { withFileTypes: true });\n const results: string[] = [];\n\n for (const entry of entries) {\n const fullPath = path.join(normalizedRoot, entry.name);\n\n // If this is a .claude directory, check for settings.local.json\n if (entry.isDirectory() && entry.name === \".claude\") {\n const settingsPath = path.join(fullPath, \"settings.local.json\");\n if (await isValidSettingsFile(settingsPath)) {\n results.push(settingsPath);\n }\n }\n\n // Recursively search subdirectories (skip .claude to avoid double-checking)\n if (entry.isDirectory() && entry.name !== \".claude\") {\n const subFiles = await findSettingsFiles(fullPath, visited);\n results.push(...subFiles);\n }\n }\n\n return results;\n } catch (error) {\n // Re-throw with more context\n if (error instanceof Error) {\n if (error.message.includes(\"ENOENT\")) {\n throw new Error(`Directory not found: ${normalizedRoot}`);\n }\n if (error.message.includes(\"EACCES\")) {\n throw new Error(`Permission denied: ${normalizedRoot}`);\n }\n throw new Error(`Failed to search directory \"${normalizedRoot}\": ${error.message}`);\n }\n throw error;\n }\n}\n\n/**\n * Check if a given path is a valid settings.local.json file\n *\n * Validates that:\n * - File exists\n * - File is readable\n * - File has .json extension\n *\n * @param filePath - Absolute path to check\n * @returns Promise resolving to true if valid settings file, false otherwise\n *\n * @example\n * ```typescript\n * const isValid = await isValidSettingsFile(\"/path/to/.claude/settings.local.json\");\n * // Returns: true or false\n * ```\n */\nexport async function isValidSettingsFile(filePath: string): Promise<boolean> {\n try {\n // Check if file exists and is readable\n await fs.access(filePath, fs.constants.R_OK);\n\n // Check if it's actually a file (not a directory)\n const stats = await fs.stat(filePath);\n if (!stats.isFile()) {\n return false;\n }\n\n // Validate it has .json extension\n return path.extname(filePath) === \".json\";\n } catch {\n // File doesn't exist or isn't readable\n return false;\n }\n}\n","/**\n * Parser for Claude Code settings files and permissions\n */\nimport fs from \"fs/promises\";\nimport type { ClaudeSettings, Permission, PermissionCategory, Permissions } from \"./types\";\n\n/**\n * Parse a settings.json file and extract permissions\n *\n * Handles:\n * - Malformed JSON (returns null)\n * - Missing permissions object (returns empty permissions)\n * - Validates basic structure\n *\n * @param filePath - Absolute path to settings.json file\n * @returns Promise resolving to ClaudeSettings object, or null if malformed\n *\n * @example\n * ```typescript\n * const settings = await parseSettingsFile(\"/path/to/.claude/settings.json\");\n * if (settings) {\n * console.log(settings.permissions?.allow);\n * }\n * ```\n */\nexport async function parseSettingsFile(filePath: string): Promise<ClaudeSettings | null> {\n try {\n // Read file contents\n const content = await fs.readFile(filePath, \"utf-8\");\n\n // Parse JSON\n const parsed = JSON.parse(content);\n\n // Basic validation: should be an object\n if (typeof parsed !== \"object\" || parsed === null) {\n return null;\n }\n\n return parsed as ClaudeSettings;\n } catch {\n // JSON parse error or file read error\n return null;\n }\n}\n\n/**\n * Parse a permission string into structured components\n *\n * Permission format: \"Type(scope)\"\n * Examples:\n * - \"Bash(git:*)\" => { type: \"Bash\", scope: \"git:*\" }\n * - \"Read(file_path:/Users/user/Code/**)\" => { type: \"Read\", scope: \"file_path:/Users/user/Code/**\" }\n * - \"WebFetch(domain:github.com)\" => { type: \"WebFetch\", scope: \"domain:github.com\" }\n *\n * @param raw - Raw permission string\n * @param category - Permission category (allow/deny/ask)\n * @returns Parsed Permission object\n * @throws Error if permission string is malformed\n *\n * @example\n * ```typescript\n * const perm = parsePermission(\"Bash(git:*)\", \"allow\");\n * // Returns: { raw: \"Bash(git:*)\", type: \"Bash\", scope: \"git:*\", category: \"allow\" }\n * ```\n */\nexport function parsePermission(raw: string, category: PermissionCategory): Permission {\n // Match pattern: Type(scope)\n const match = raw.match(/^([^(]+)\\((.+)\\)$/);\n\n if (!match) {\n throw new Error(`Malformed permission string: \"${raw}\"`);\n }\n\n const [, type, scope] = match;\n\n return {\n raw,\n type: type.trim(),\n scope: scope.trim(),\n category,\n };\n}\n\n/**\n * Parse all permissions from a Permissions object\n *\n * Converts permission strings to structured Permission objects,\n * grouped by category (allow/deny/ask).\n *\n * @param permissions - Permissions object from settings.json\n * @returns Array of parsed Permission objects\n *\n * @example\n * ```typescript\n * const permissions = {\n * allow: [\"Bash(git:*)\", \"Bash(npm:*)\"],\n * deny: [\"Bash(rm -rf:*)\"]\n * };\n * const parsed = parseAllPermissions(permissions);\n * // Returns array of Permission objects with category set\n * ```\n */\nexport function parseAllPermissions(permissions: Permissions): Permission[] {\n const result: Permission[] = [];\n\n // Parse allow permissions\n if (permissions.allow) {\n for (const perm of permissions.allow) {\n try {\n result.push(parsePermission(perm, \"allow\"));\n } catch {\n // Skip malformed permissions\n continue;\n }\n }\n }\n\n // Parse deny permissions\n if (permissions.deny) {\n for (const perm of permissions.deny) {\n try {\n result.push(parsePermission(perm, \"deny\"));\n } catch {\n // Skip malformed permissions\n continue;\n }\n }\n }\n\n // Parse ask permissions\n if (permissions.ask) {\n for (const perm of permissions.ask) {\n try {\n result.push(parsePermission(perm, \"ask\"));\n } catch {\n // Skip malformed permissions\n continue;\n }\n }\n }\n\n return result;\n}\n\n/**\n * Read and parse multiple settings files\n *\n * Processes an array of file paths, reading and parsing each one.\n * Skips files that can't be read or parsed.\n *\n * @param filePaths - Array of absolute paths to settings files\n * @returns Promise resolving to array of Permissions objects (one per valid file)\n *\n * @example\n * ```typescript\n * const files = [\n * \"/Users/user/Code/project-a/.claude/settings.local.json\",\n * \"/Users/user/Code/project-b/.claude/settings.local.json\"\n * ];\n * const allPermissions = await parseAllSettings(files);\n * // Returns: [{ allow: [...], deny: [...] }, { allow: [...] }]\n * ```\n */\nexport async function parseAllSettings(filePaths: string[]): Promise<Permissions[]> {\n const results: Permissions[] = [];\n\n for (const filePath of filePaths) {\n const settings = await parseSettingsFile(filePath);\n if (settings?.permissions) {\n results.push(settings.permissions);\n }\n }\n\n return results;\n}\n","/**\n * Normalize path separators for cross-platform consistency\n *\n * Converts Windows backslashes to forward slashes for consistent path handling\n * across different operating systems.\n *\n * @param filepath - Path to normalize\n * @returns Normalized path with forward slashes\n *\n * @example\n * ```typescript\n * normalizePath(\"C:\\\\Users\\\\test\\\\specs\"); // Returns: \"C:/Users/test/specs\"\n * normalizePath(\"/home/user/specs\"); // Returns: \"/home/user/specs\"\n * ```\n */\n\nexport function normalizePath(filepath: string): string {\n // Replace all backslashes with forward slashes for cross-platform consistency\n return filepath.replace(/\\\\/g, \"/\");\n}\n","/**\n * Permission subsumption detection\n *\n * Detects when broader permissions subsume narrower ones:\n * - Bash(git:*) subsumes Bash(git log:*), Bash(git worktree:*), etc.\n * - Read(file_path:/Users/user/Code/**) subsumes Read(file_path:/Users/user/Code/project-a/**)\n */\nimport { normalizePath } from \"@/lib/file-system/normalizePath\";\nimport { parsePermission } from \"./parser\";\nimport type { Permission, PermissionCategory, ScopePattern, SubsumptionResult } from \"./types\";\n\n/**\n * Parse a scope string to extract pattern type and value\n *\n * Determines whether the scope is a command pattern (e.g., \"git:*\")\n * or a path pattern (e.g., \"file_path:/Users/user/Code/**\").\n *\n * @param scope - Scope string from permission\n * @returns ScopePattern with type and pattern\n *\n * @example\n * ```typescript\n * parseScopePattern(\"git:*\")\n * // Returns: { type: \"command\", pattern: \"git:*\" }\n *\n * parseScopePattern(\"file_path:/Users/user/Code/**\")\n * // Returns: { type: \"path\", pattern: \"/Users/user/Code/**\" }\n * ```\n */\nexport function parseScopePattern(scope: string): ScopePattern {\n // Check if scope contains path indicators\n if (\n scope.includes(\"file_path:\")\n || scope.includes(\"directory_path:\")\n || scope.includes(\"path:\")\n ) {\n // Extract path after the colon\n const colonIndex = scope.indexOf(\":\");\n const pattern = colonIndex >= 0 ? scope.substring(colonIndex + 1) : scope;\n return { type: \"path\", pattern };\n }\n\n // Default to command pattern (e.g., \"git:*\", \"npm:*\")\n return { type: \"command\", pattern: scope };\n}\n\n/**\n * Check if permission A subsumes permission B\n *\n * Subsumption rules:\n * 1. Same type required (Bash subsumes Bash, not Read)\n * 2. Identical scopes = not subsumption (exact match)\n * 3. Broader scope subsumes narrower scope:\n * - Command: \"git:*\" subsumes \"git log:*\", \"git worktree:*\"\n * - Path: \"/Users/user/Code/**\" subsumes \"/Users/user/Code/project-a/**\"\n *\n * @param broader - Permission that might subsume the other\n * @param narrower - Permission that might be subsumed\n * @returns true if broader subsumes narrower, false otherwise\n *\n * @example\n * ```typescript\n * subsumes(\n * parsePermission(\"Bash(git:*)\", \"allow\"),\n * parsePermission(\"Bash(git log:*)\", \"allow\")\n * )\n * // Returns: true\n *\n * subsumes(\n * parsePermission(\"Read(file_path:/Users/user/Code/**)\", \"allow\"),\n * parsePermission(\"Read(file_path:/Users/user/Code/project-a/**)\", \"allow\")\n * )\n * // Returns: true\n *\n * subsumes(\n * parsePermission(\"Bash(git:*)\", \"allow\"),\n * parsePermission(\"Read(file_path:/Users/user/Code/**)\", \"allow\")\n * )\n * // Returns: false (different types)\n * ```\n */\nexport function subsumes(broader: Permission, narrower: Permission): boolean {\n // 1. Type must match\n if (broader.type !== narrower.type) {\n return false;\n }\n\n // 2. Identical = not subsumption (this is just a duplicate)\n if (broader.scope === narrower.scope) {\n return false;\n }\n\n // 3. Parse scope patterns\n const broaderScope = parseScopePattern(broader.scope);\n const narrowerScope = parseScopePattern(narrower.scope);\n\n // 4. Handle command patterns (e.g., \"git:*\")\n if (broaderScope.type === \"command\" && narrowerScope.type === \"command\") {\n // Extract base command by removing :* suffix\n const broaderBase = broaderScope.pattern.replace(/:?\\*+$/, \"\");\n const narrowerFull = narrowerScope.pattern.replace(/:?\\*+$/, \"\");\n\n // Check if narrower starts with broader prefix\n // \"git:*\" subsumes \"git log:*\" if:\n // - narrowerFull starts with broaderBase\n // - narrowerFull is longer (more specific)\n if (narrowerFull.startsWith(broaderBase)) {\n // Additional specificity check: narrower must add more detail\n // e.g., \"git\" subsumes \"git log\", but not \"git\" subsumes \"git\"\n return narrowerFull.length > broaderBase.length;\n }\n }\n\n // 5. Handle path patterns (e.g., \"/Users/user/Code/**\")\n if (broaderScope.type === \"path\" && narrowerScope.type === \"path\") {\n // Normalize paths for comparison\n const broaderPath = normalizePath(broaderScope.pattern.replace(/\\/?\\*+$/, \"\"));\n const narrowerPath = normalizePath(narrowerScope.pattern.replace(/\\/?\\*+$/, \"\"));\n\n // Check if narrower is a sub-path of broader\n // \"/Users/user/Code\" subsumes \"/Users/user/Code/project-a\" if:\n // - narrowerPath starts with broaderPath + \"/\"\n return narrowerPath.startsWith(broaderPath + \"/\");\n }\n\n // 6. Mixed pattern types don't subsume each other\n return false;\n}\n\n/**\n * Find all subsumption relationships in a permission list\n *\n * Returns a map of broader permissions to the narrower permissions\n * they subsume. This allows identifying which permissions can be\n * removed from the list.\n *\n * @param permissions - Array of permissions to analyze\n * @returns Array of subsumption results\n *\n * @example\n * ```typescript\n * const permissions = [\n * parsePermission(\"Bash(git:*)\", \"allow\"),\n * parsePermission(\"Bash(git log:*)\", \"allow\"),\n * parsePermission(\"Bash(git worktree:*)\", \"allow\"),\n * parsePermission(\"Bash(npm:*)\", \"allow\"),\n * ];\n *\n * const results = detectSubsumptions(permissions);\n * // Returns: [\n * // {\n * // broader: { raw: \"Bash(git:*)\", ... },\n * // narrower: [\n * // { raw: \"Bash(git log:*)\", ... },\n * // { raw: \"Bash(git worktree:*)\", ... }\n * // ]\n * // }\n * // ]\n * ```\n */\nexport function detectSubsumptions(permissions: Permission[]): SubsumptionResult[] {\n const results: SubsumptionResult[] = [];\n const processedBroader = new Set<string>();\n\n for (let i = 0; i < permissions.length; i++) {\n const broader = permissions[i];\n\n // Skip if already processed as a broader permission\n if (processedBroader.has(broader.raw)) {\n continue;\n }\n\n const narrowerPerms: Permission[] = [];\n\n // Check all other permissions to see if this one subsumes them\n for (let j = 0; j < permissions.length; j++) {\n if (i === j) continue; // Skip comparing with self\n\n const narrower = permissions[j];\n\n if (subsumes(broader, narrower)) {\n narrowerPerms.push(narrower);\n }\n }\n\n // If this permission subsumes others, record it\n if (narrowerPerms.length > 0) {\n results.push({\n broader,\n narrower: narrowerPerms,\n });\n processedBroader.add(broader.raw);\n }\n }\n\n return results;\n}\n\n/**\n * Remove subsumed permissions from a list, keeping only the broadest ones\n *\n * This is the main function for consolidating permissions.\n * It finds all subsumption relationships and removes narrower\n * permissions, leaving only the broadest ones.\n *\n * @param permissionStrings - Array of raw permission strings\n * @param category - Permission category (for parsing)\n * @returns Array of permission strings with subsumed ones removed\n *\n * @example\n * ```typescript\n * const permissions = [\n * \"Bash(git:*)\",\n * \"Bash(git log:*)\",\n * \"Bash(git worktree:*)\",\n * \"Bash(npm:*)\",\n * ];\n *\n * const result = removeSubsumed(permissions, \"allow\");\n * // Returns: [\"Bash(git:*)\", \"Bash(npm:*)\"]\n * ```\n */\nexport function removeSubsumed(\n permissionStrings: string[],\n category: PermissionCategory,\n): string[] {\n // Parse all permission strings\n const permissions = permissionStrings\n .map((raw) => {\n try {\n return parsePermission(raw, category);\n } catch {\n // Keep malformed permissions as-is (don't filter them out)\n return null;\n }\n })\n .filter((p): p is Permission => p !== null);\n\n // Detect subsumptions\n const subsumptions = detectSubsumptions(permissions);\n\n // Build set of narrower permissions to remove\n const toRemove = new Set<string>();\n for (const result of subsumptions) {\n for (const narrower of result.narrower) {\n toRemove.add(narrower.raw);\n }\n }\n\n // Filter out subsumed permissions\n return permissionStrings.filter((perm) => !toRemove.has(perm));\n}\n","/**\n * Permission merging with subsumption and conflict resolution\n */\nimport { parsePermission } from \"./parser\";\nimport { removeSubsumed, subsumes } from \"./subsumption\";\nimport type { ConsolidationResult, Permissions, PermissionsAdded } from \"./types\";\n\n/**\n * Merge permissions from global settings and multiple local settings files\n *\n * Process:\n * 1. Combine all permissions by category (allow/deny/ask)\n * 2. Apply subsumption to remove narrower permissions\n * 3. Resolve conflicts (deny wins over allow)\n * 4. Deduplicate using Sets\n * 5. Sort alphabetically\n *\n * @param global - Global settings permissions (baseline)\n * @param local - Array of local settings permissions to merge in\n * @returns Merged permissions and consolidation statistics\n *\n * @example\n * ```typescript\n * const global = { allow: [\"Bash(ls:*)\"] };\n * const local = [\n * { allow: [\"Bash(git:*)\", \"Bash(git log:*)\"] },\n * { deny: [\"Bash(rm:*)\"] }\n * ];\n *\n * const { merged, result } = mergePermissions(global, local);\n * // merged.allow: [\"Bash(git:*)\", \"Bash(ls:*)\"] // git log:* removed by subsumption\n * // merged.deny: [\"Bash(rm:*)\"]\n * // result.subsumed: [\"Bash(git log:*)\"]\n * ```\n */\nexport function mergePermissions(\n global: Permissions,\n local: Permissions[],\n): { merged: Permissions; result: ConsolidationResult } {\n // Track original global permissions for computing added\n const originalGlobal = {\n allow: new Set(global.allow || []),\n deny: new Set(global.deny || []),\n ask: new Set(global.ask || []),\n };\n\n // Step 1: Combine all permissions by category\n const combined: Permissions = {\n allow: [...(global.allow || [])],\n deny: [...(global.deny || [])],\n ask: [...(global.ask || [])],\n };\n\n let filesProcessed = 0;\n let filesSkipped = 0;\n\n for (const localPerms of local) {\n let hasPerms = false;\n\n if (localPerms.allow && localPerms.allow.length > 0) {\n combined.allow?.push(...localPerms.allow);\n hasPerms = true;\n }\n if (localPerms.deny && localPerms.deny.length > 0) {\n combined.deny?.push(...localPerms.deny);\n hasPerms = true;\n }\n if (localPerms.ask && localPerms.ask.length > 0) {\n combined.ask?.push(...localPerms.ask);\n hasPerms = true;\n }\n\n if (hasPerms) {\n filesProcessed++;\n } else {\n filesSkipped++;\n }\n }\n\n // Step 2: Apply subsumption to each category\n const allSubsumed: string[] = [];\n\n const afterSubsumption: Permissions = {};\n\n if (combined.allow && combined.allow.length > 0) {\n const before = new Set(combined.allow);\n combined.allow = removeSubsumed(combined.allow, \"allow\");\n const after = new Set(combined.allow);\n\n // Track what was removed\n for (const perm of before) {\n if (!after.has(perm)) {\n allSubsumed.push(perm);\n }\n }\n }\n\n if (combined.deny && combined.deny.length > 0) {\n const before = new Set(combined.deny);\n combined.deny = removeSubsumed(combined.deny, \"deny\");\n const after = new Set(combined.deny);\n\n // Track what was removed\n for (const perm of before) {\n if (!after.has(perm)) {\n allSubsumed.push(perm);\n }\n }\n }\n\n if (combined.ask && combined.ask.length > 0) {\n const before = new Set(combined.ask);\n combined.ask = removeSubsumed(combined.ask, \"ask\");\n const after = new Set(combined.ask);\n\n // Track what was removed\n for (const perm of before) {\n if (!after.has(perm)) {\n allSubsumed.push(perm);\n }\n }\n }\n\n afterSubsumption.allow = combined.allow;\n afterSubsumption.deny = combined.deny;\n afterSubsumption.ask = combined.ask;\n\n // Step 3: Resolve conflicts (deny wins over allow)\n const {\n resolved,\n conflictCount,\n subsumed: conflictSubsumed,\n } = resolveConflicts(afterSubsumption);\n\n // Combine subsumptions from step 2 and step 3\n const subsumed = [...allSubsumed, ...conflictSubsumed];\n\n // Step 4: Deduplicate using Sets and sort\n const merged: Permissions = {};\n\n if (resolved.allow && resolved.allow.length > 0) {\n merged.allow = Array.from(new Set(resolved.allow)).sort();\n }\n\n if (resolved.deny && resolved.deny.length > 0) {\n merged.deny = Array.from(new Set(resolved.deny)).sort();\n }\n\n if (resolved.ask && resolved.ask.length > 0) {\n merged.ask = Array.from(new Set(resolved.ask)).sort();\n }\n\n // Step 5: Compute what was added\n const added: PermissionsAdded = {\n allow: [],\n deny: [],\n ask: [],\n };\n\n for (const perm of merged.allow || []) {\n if (!originalGlobal.allow.has(perm)) {\n added.allow.push(perm);\n }\n }\n\n for (const perm of merged.deny || []) {\n if (!originalGlobal.deny.has(perm)) {\n added.deny.push(perm);\n }\n }\n\n for (const perm of merged.ask || []) {\n if (!originalGlobal.ask.has(perm)) {\n added.ask.push(perm);\n }\n }\n\n // Build result\n const result: ConsolidationResult = {\n filesScanned: local.length,\n filesProcessed,\n filesSkipped,\n added,\n subsumed,\n conflictsResolved: conflictCount,\n };\n\n return { merged, result };\n}\n\n/**\n * Resolve conflicts between allow and deny permissions\n *\n * Rules:\n * - If exact match in both allow and deny: keep in deny, remove from allow\n * - If deny has broader permission that subsumes allow: remove from allow\n *\n * This implements a security-first approach: deny always wins.\n *\n * @param permissions - Permissions with potential conflicts\n * @returns Resolved permissions with conflicts removed, count of conflicts, and list of subsumed permissions\n *\n * @example\n * ```typescript\n * const permissions = {\n * allow: [\"Bash(git log:*)\", \"Bash(npm:*)\"],\n * deny: [\"Bash(git:*)\"]\n * };\n *\n * const { resolved, conflictCount } = resolveConflicts(permissions);\n * // resolved.allow: [\"Bash(npm:*)\"] // git log:* removed (subsumed by deny git:*)\n * // resolved.deny: [\"Bash(git:*)\"]\n * // conflictCount: 1\n * ```\n */\nexport function resolveConflicts(permissions: Permissions): {\n resolved: Permissions;\n conflictCount: number;\n subsumed: string[];\n} {\n const allow = permissions.allow || [];\n const deny = permissions.deny || [];\n const ask = permissions.ask || [];\n\n const denySet = new Set(deny);\n const subsumed: string[] = [];\n let conflictCount = 0;\n\n // Check each allow permission against deny permissions\n const allowToRemove = new Set<string>();\n\n for (const allowPerm of allow) {\n // Exact match: move to deny\n if (denySet.has(allowPerm)) {\n allowToRemove.add(allowPerm);\n conflictCount++;\n continue;\n }\n\n // Check if any deny permission subsumes this allow permission\n for (const denyPerm of deny) {\n try {\n const allowParsed = parsePermission(allowPerm, \"allow\");\n const denyParsed = parsePermission(denyPerm, \"deny\");\n\n if (subsumes(denyParsed, allowParsed)) {\n // Deny subsumes allow - remove from allow\n allowToRemove.add(allowPerm);\n subsumed.push(allowPerm);\n conflictCount++;\n break;\n }\n } catch {\n // Skip malformed permissions\n continue;\n }\n }\n }\n\n // Build resolved permissions\n const resolved: Permissions = {\n allow: allow.filter((p) => !allowToRemove.has(p)),\n deny,\n ask,\n };\n\n return { resolved, conflictCount, subsumed };\n}\n","/**\n * Backup management for Claude Code settings files\n */\nimport fs from \"fs/promises\";\n\n/**\n * Create a timestamped backup of a settings file\n *\n * Backup format: `<original-path>.backup.YYYY-MM-DD-HHmmss`\n *\n * Example: `settings.json.backup.2026-01-08-143022`\n *\n * @param settingsPath - Absolute path to settings file to back up\n * @returns Promise resolving to backup file path\n * @throws Error if source file doesn't exist or backup fails\n *\n * @example\n * ```typescript\n * const backupPath = await createBackup(\"/Users/shz/.claude/settings.json\");\n * // Returns: \"/Users/shz/.claude/settings.json.backup.2026-01-08-143022\"\n * ```\n */\nexport async function createBackup(settingsPath: string): Promise<string> {\n try {\n // Verify source file exists\n await fs.access(settingsPath, fs.constants.R_OK);\n\n // Generate timestamp: YYYY-MM-DD-HHmmss\n const now = new Date();\n const timestamp = [\n now.getFullYear(),\n String(now.getMonth() + 1).padStart(2, \"0\"),\n String(now.getDate()).padStart(2, \"0\"),\n ].join(\"-\") + \"-\" + [\n String(now.getHours()).padStart(2, \"0\"),\n String(now.getMinutes()).padStart(2, \"0\"),\n String(now.getSeconds()).padStart(2, \"0\"),\n ].join(\"\");\n\n // Build backup path\n const backupPath = `${settingsPath}.backup.${timestamp}`;\n\n // Copy file to backup location\n await fs.copyFile(settingsPath, backupPath);\n\n return backupPath;\n } catch (error) {\n if (error instanceof Error) {\n if (error.message.includes(\"ENOENT\")) {\n throw new Error(`Settings file not found: ${settingsPath}`);\n }\n if (error.message.includes(\"EACCES\")) {\n throw new Error(`Permission denied: ${settingsPath}`);\n }\n throw new Error(`Failed to create backup: ${error.message}`);\n }\n throw error;\n }\n}\n","/**\n * Formatting and reporting of consolidation results\n */\nimport type { ConsolidationResult } from \"../permissions/types\";\n\n/**\n * Format consolidation result as user-friendly text report\n *\n * Shows:\n * - Files scanned/processed/skipped\n * - Permissions added by category (allow/deny/ask)\n * - Conflicts resolved\n * - Subsumed permissions removed\n * - Backup path (if created)\n * - Instructions (if preview mode) or confirmation (if written)\n *\n * @param result - Consolidation result data\n * @param previewOnly - Whether this is preview-only mode (default behavior)\n * @param globalSettingsPath - Path to global settings file\n * @param outputFile - Optional output file path\n * @returns Formatted report string\n *\n * @example\n * ```typescript\n * const result = {\n * filesScanned: 12,\n * filesProcessed: 10,\n * filesSkipped: 2,\n * added: {\n * allow: [\"Bash(git:*)\", \"Bash(npm:*)\"],\n * deny: [\"Bash(rm:*)\"],\n * ask: []\n * },\n * subsumed: [\"Bash(git log:*)\", \"Bash(git worktree:*)\"],\n * conflictsResolved: 1,\n * backupPath: \"/Users/shz/.claude/settings.json.backup.2026-01-08-143022\"\n * };\n *\n * console.log(formatReport(result, true, \"/Users/shz/.claude/settings.json\"));\n * // Outputs formatted report with instructions\n * ```\n */\nexport function formatReport(\n result: ConsolidationResult,\n previewOnly: boolean,\n globalSettingsPath?: string,\n outputFile?: string,\n): string {\n const lines: string[] = [];\n\n // Header\n lines.push(\"Scanning for Claude Code settings files...\");\n lines.push(\"\");\n\n // Files summary\n lines.push(`Found ${result.filesScanned} settings files`);\n lines.push(` Processed: ${result.filesProcessed}`);\n if (result.filesSkipped > 0) {\n lines.push(` Skipped: ${result.filesSkipped} (no permissions)`);\n }\n lines.push(\"\");\n\n // Permissions added\n const totalAdded = result.added.allow.length\n + result.added.deny.length\n + result.added.ask.length;\n\n if (totalAdded > 0) {\n lines.push(`Permissions to add: ${totalAdded}`);\n\n if (result.added.allow.length > 0) {\n lines.push(\"\");\n lines.push(\" allow:\");\n for (const perm of result.added.allow) {\n lines.push(` + ${perm}`);\n }\n }\n\n if (result.added.deny.length > 0) {\n lines.push(\"\");\n lines.push(\" deny:\");\n for (const perm of result.added.deny) {\n lines.push(` + ${perm}`);\n }\n }\n\n if (result.added.ask.length > 0) {\n lines.push(\"\");\n lines.push(\" ask:\");\n for (const perm of result.added.ask) {\n lines.push(` + ${perm}`);\n }\n }\n } else {\n lines.push(\"No new permissions to add (all permissions already in global settings)\");\n }\n\n lines.push(\"\");\n\n // Subsumption results\n if (result.subsumed.length > 0) {\n lines.push(`Subsumed permissions removed: ${result.subsumed.length}`);\n lines.push(\" (narrower permissions replaced by broader ones)\");\n for (const perm of result.subsumed) {\n lines.push(` - ${perm}`);\n }\n lines.push(\"\");\n }\n\n // Conflicts\n if (result.conflictsResolved > 0) {\n lines.push(`Conflicts resolved: ${result.conflictsResolved}`);\n lines.push(\" (permissions moved from allow to deny)\");\n lines.push(\"\");\n }\n\n // Backup\n if (result.backupPath) {\n lines.push(`Backup created: ${result.backupPath}`);\n lines.push(\"\");\n }\n\n // Summary\n lines.push(\"Summary:\");\n lines.push(` Files scanned: ${result.filesScanned}`);\n lines.push(\n ` Permissions added: ${result.added.allow.length} allow, ${result.added.deny.length} deny, ${result.added.ask.length} ask`,\n );\n if (result.subsumed.length > 0) {\n lines.push(` Subsumed removed: ${result.subsumed.length}`);\n }\n if (result.conflictsResolved > 0) {\n lines.push(` Conflicts resolved: ${result.conflictsResolved}`);\n }\n\n // Final status message\n lines.push(\"\");\n if (previewOnly) {\n lines.push(\"ℹ️ Preview mode: No changes written\");\n lines.push(\"\");\n lines.push(\"To apply changes:\");\n lines.push(` • Modify global settings: spx claude settings consolidate --write`);\n lines.push(` • Write to file: spx claude settings consolidate --output-file /path/to/file`);\n } else if (outputFile) {\n lines.push(`✓ Settings written to: ${result.outputPath || outputFile}`);\n lines.push(\"\");\n lines.push(\"To apply to your global settings:\");\n lines.push(` • Review the file, then copy to: ${globalSettingsPath || \"~/.claude/settings.json\"}`);\n lines.push(` • Or run: spx claude settings consolidate --write`);\n } else {\n lines.push(`✓ Global settings updated: ${globalSettingsPath || \"~/.claude/settings.json\"}`);\n }\n\n return lines.join(\"\\n\");\n}\n","/**\n * Atomic file writing for Claude Code settings\n */\nimport fs from \"fs/promises\";\nimport os from \"os\";\nimport path from \"path\";\nimport type { ClaudeSettings } from \"../permissions/types\";\n\n/**\n * Filesystem abstraction for dependency injection\n *\n * Enables testing error paths without mocking.\n */\nexport interface FileSystem {\n writeFile(path: string, content: string): Promise<void>;\n rename(oldPath: string, newPath: string): Promise<void>;\n unlink(path: string): Promise<void>;\n mkdir(path: string, options?: { recursive?: boolean }): Promise<void>;\n}\n\n/**\n * Production filesystem implementation\n */\nconst realFs: FileSystem = {\n writeFile: (path, content) => fs.writeFile(path, content, \"utf-8\"),\n rename: fs.rename,\n unlink: fs.unlink,\n mkdir: async (path, options) => {\n await fs.mkdir(path, options);\n },\n};\n\n/**\n * Atomically write settings to a file\n *\n * Uses temp file + rename pattern for atomicity:\n * 1. Write to temporary file\n * 2. Rename to target (atomic operation on most filesystems)\n *\n * Preserves JSON formatting with 2-space indentation.\n *\n * @param filePath - Absolute path to settings file\n * @param settings - Settings object to write\n * @param deps - Dependencies (for testing)\n * @throws Error if write fails\n *\n * @example\n * ```typescript\n * const settings = {\n * permissions: {\n * allow: [\"Bash(git:*)\", \"Bash(npm:*)\"]\n * }\n * };\n * await writeSettings(\"/Users/shz/.claude/settings.json\", settings);\n * ```\n */\nexport async function writeSettings(\n filePath: string,\n settings: ClaudeSettings,\n deps: { fs: FileSystem } = { fs: realFs },\n): Promise<void> {\n // Ensure directory exists\n const dir = path.dirname(filePath);\n await deps.fs.mkdir(dir, { recursive: true });\n\n // Generate temporary file path\n const tempPath = path.join(\n os.tmpdir(),\n `settings-${Date.now()}-${Math.random().toString(36).substring(7)}.json`,\n );\n\n try {\n // Format JSON with 2-space indentation and trailing newline\n const content = JSON.stringify(settings, null, 2) + \"\\n\";\n\n // Write to temp file\n await deps.fs.writeFile(tempPath, content);\n\n // Atomic rename\n await deps.fs.rename(tempPath, filePath);\n } catch (error) {\n // Cleanup temp file on failure\n try {\n await deps.fs.unlink(tempPath);\n } catch {\n // Ignore cleanup errors\n }\n\n // Re-throw original error\n if (error instanceof Error) {\n throw new Error(`Failed to write settings: ${error.message}`);\n }\n throw error;\n }\n}\n","/**\n * Consolidate command implementation\n *\n * Orchestrates the full consolidation pipeline:\n * 1. Discovery - Find all settings.local.json files\n * 2. Parsing - Extract permissions from each file\n * 3. Merging - Combine with subsumption and conflict resolution\n * 4. Backup - Create timestamped backup (if not dry-run)\n * 5. Writing - Atomically write merged settings (if not dry-run)\n * 6. Reporting - Format and return result summary\n */\nimport { findSettingsFiles } from \"@/lib/claude/permissions/discovery\";\nimport { mergePermissions } from \"@/lib/claude/permissions/merger\";\nimport { parseAllSettings, parseSettingsFile } from \"@/lib/claude/permissions/parser\";\nimport { createBackup } from \"@/lib/claude/settings/backup\";\nimport { formatReport } from \"@/lib/claude/settings/reporter\";\nimport { writeSettings } from \"@/lib/claude/settings/writer\";\nimport os from \"os\";\nimport path from \"path\";\n\n/**\n * Options for consolidate command\n */\nexport interface ConsolidateOptions {\n /** Root directory to scan for settings files (default: ~/Code) */\n root?: string;\n /** Write changes to global settings file (default: false = preview only) */\n write?: boolean;\n /** Write merged settings to specified file instead of global settings */\n outputFile?: string;\n /** Path to global settings file (for testing; default: ~/.claude/settings.json) */\n globalSettings?: string;\n}\n\n/**\n * Execute settings consolidate command\n *\n * Consolidates permissions from project-local settings files into\n * the global Claude Code settings file.\n *\n * Behavior:\n * - Discovers all `.claude/settings.local.json` files recursively\n * - Applies subsumption to remove narrower permissions\n * - Resolves conflicts (deny wins over allow)\n * - Deduplicates and sorts permissions\n * - Creates backup before modifications\n * - Supports dry-run mode for preview\n *\n * @param options - Command options\n * @returns Formatted report string\n * @throws Error if discovery, parsing, or writing fails\n *\n * @example\n * ```typescript\n * // Normal consolidation\n * const output = await consolidateCommand({ root: \"~/Code\" });\n * console.log(output);\n *\n * // Dry-run preview\n * const preview = await consolidateCommand({ root: \"~/Code\", dryRun: true });\n * console.log(preview);\n * ```\n */\nexport async function consolidateCommand(\n options: ConsolidateOptions = {},\n): Promise<string> {\n // Resolve paths\n const root = options.root\n ? path.resolve(options.root.replace(/^~/, os.homedir()))\n : path.join(os.homedir(), \"Code\");\n\n const globalSettingsPath = options.globalSettings\n || path.join(os.homedir(), \".claude\", \"settings.json\");\n\n const shouldWrite = options.write || false;\n const outputFile = options.outputFile;\n const previewOnly = !shouldWrite && !outputFile;\n\n // Step 1: Discovery - find all settings.local.json files\n const settingsFiles = await findSettingsFiles(root);\n\n if (settingsFiles.length === 0) {\n return `No settings files found in ${root}\\n\\nSearched for: **/.claude/settings.local.json`;\n }\n\n // Step 2: Parsing - extract permissions from each file\n const localPermissions = await parseAllSettings(settingsFiles);\n\n // Step 3: Read global settings\n let globalSettings = await parseSettingsFile(globalSettingsPath);\n\n // If global settings doesn't exist, create empty structure\n if (!globalSettings) {\n globalSettings = {\n permissions: {\n allow: [],\n deny: [],\n ask: [],\n },\n };\n }\n\n // Ensure permissions object exists\n if (!globalSettings.permissions) {\n globalSettings.permissions = {\n allow: [],\n deny: [],\n ask: [],\n };\n }\n\n // Step 4: Merge with subsumption and conflict resolution\n const { merged, result } = mergePermissions(\n globalSettings.permissions,\n localPermissions,\n );\n\n // Step 5: Backup (only when writing to global settings)\n if (shouldWrite) {\n try {\n result.backupPath = await createBackup(globalSettingsPath);\n } catch (error) {\n // If backup fails because file doesn't exist, that's okay (first time)\n if (error instanceof Error && !error.message.includes(\"not found\")) {\n throw error;\n }\n }\n }\n\n // Step 6: Write (if --write or --output-file specified)\n if (shouldWrite) {\n const updatedSettings = {\n ...globalSettings,\n permissions: merged,\n };\n await writeSettings(globalSettingsPath, updatedSettings);\n } else if (outputFile) {\n const updatedSettings = {\n ...globalSettings,\n permissions: merged,\n };\n const resolvedOutputPath = path.resolve(outputFile.replace(/^~/, os.homedir()));\n await writeSettings(resolvedOutputPath, updatedSettings);\n result.outputPath = resolvedOutputPath;\n }\n\n // Step 7: Report\n return formatReport(result, previewOnly, globalSettingsPath, outputFile);\n}\n","/**\n * Claude domain - Manage Claude Code settings and plugins\n */\nimport { initCommand } from \"@/commands/claude/init\";\nimport { consolidateCommand } from \"@/commands/claude/settings/consolidate\";\nimport type { Domain } from \"@/domains/types\";\nimport type { Command } from \"commander\";\n\n/**\n * Register claude domain commands\n *\n * @param claudeCmd - Commander.js claude domain command\n */\nfunction registerClaudeCommands(claudeCmd: Command): void {\n // init command\n claudeCmd\n .command(\"init\")\n .description(\"Initialize or update outcomeeng marketplace plugin\")\n .action(async () => {\n try {\n const output = await initCommand({ cwd: process.cwd() });\n console.log(output);\n } catch (error) {\n console.error(\n \"Error:\",\n error instanceof Error ? error.message : String(error),\n );\n process.exit(1);\n }\n });\n\n // settings subcommand group\n const settingsCmd = claudeCmd\n .command(\"settings\")\n .description(\"Manage Claude Code settings\");\n\n // settings consolidate command\n settingsCmd\n .command(\"consolidate\")\n .description(\n \"Consolidate permissions from project-specific settings into global settings\",\n )\n .option(\"--write\", \"Write changes to global settings file (default: preview only)\")\n .option(\n \"--output-file <path>\",\n \"Write merged settings to specified file instead of global settings\",\n )\n .option(\n \"--root <path>\",\n \"Root directory to scan for settings files (default: ~/Code)\",\n )\n .option(\n \"--global-settings <path>\",\n \"Path to global settings file (default: ~/.claude/settings.json)\",\n )\n .action(\n async (options: {\n write?: boolean;\n outputFile?: string;\n root?: string;\n globalSettings?: string;\n }) => {\n try {\n // Validate mutually exclusive options\n if (options.write && options.outputFile) {\n console.error(\n \"Error: --write and --output-file are mutually exclusive\\n\"\n + \"Use --write to modify global settings, or --output-file to write to a different location\",\n );\n process.exit(1);\n }\n\n const output = await consolidateCommand({\n write: options.write,\n outputFile: options.outputFile,\n root: options.root,\n globalSettings: options.globalSettings,\n });\n console.log(output);\n } catch (error) {\n console.error(\n \"Error:\",\n error instanceof Error ? error.message : String(error),\n );\n process.exit(1);\n }\n },\n );\n}\n\n/**\n * Claude domain - Manage Claude Code settings and plugins\n */\nexport const claudeDomain: Domain = {\n name: \"claude\",\n description: \"Manage Claude Code settings and plugins\",\n register: (program: Command) => {\n const claudeCmd = program\n .command(\"claude\")\n .description(\"Manage Claude Code settings and plugins\");\n\n registerClaudeCommands(claudeCmd);\n },\n};\n","import { join } from \"node:path\";\n\nimport type { Result } from \"@/config/types\";\nimport {\n type AgentSessionEnvironment,\n normalizeAgentSessionToken,\n resolveAgentSessionId,\n} from \"@/domains/session/agent-session\";\nimport { composeScopeDir, type JsonRecord, STATE_STORE_DOMAIN } from \"@/lib/state-store\";\n\nexport const COMPACT_STORE_PATH = {\n STASH_FILE: \"stash.jsonl\",\n} as const;\n\nexport const COMPACT_RECORD_FIELDS = {\n ACTIVE_NODE: \"active_node\",\n HAS_FOUNDATION: \"has_foundation\",\n} as const;\n\nexport const COMPACT_MARKER = {\n FOUNDATION: \"SPEC_TREE_FOUNDATION\",\n CONTEXT: \"SPEC_TREE_CONTEXT\",\n TARGET_ATTRIBUTE: \"target\",\n ESCAPED_TARGET_QUOTE: \"\\\\\\\"\",\n UNESCAPED_TARGET_QUOTE: \"\\\"\",\n} as const;\n\nexport const COMPACT_ERROR = {\n RECORD_SHAPE_INVALID: \"compact record shape invalid\",\n} as const;\n\nexport interface CompactRecord extends JsonRecord {\n readonly active_node: string;\n readonly has_foundation: true;\n}\n\nconst EMPTY_ACTIVE_NODE = \"\";\nconst JSONL_LINE_SEPARATOR = \"\\n\";\nconst ATTRIBUTE_ASSIGNMENT = \"=\";\nconst ESCAPE_CHARACTER = \"\\\\\";\nconst CONTEXT_TARGET_PREFIX = `${COMPACT_MARKER.TARGET_ATTRIBUTE}${ATTRIBUTE_ASSIGNMENT}`;\nconst NODE_PATH_PREFIX = \"spx/\";\n\n/** Normalized `--session-id` when supplied non-empty; otherwise the agent-session environment resolver. */\nexport function resolveCompactSessionToken(\n sessionId: string | undefined,\n env: AgentSessionEnvironment,\n): string | undefined {\n if (sessionId !== undefined && sessionId.length > 0) {\n return normalizeAgentSessionToken(sessionId);\n }\n return resolveAgentSessionId(env);\n}\n\nexport function extractCompactRecord(transcript: string): CompactRecord | undefined {\n let hasFoundation = false;\n let activeNode = EMPTY_ACTIVE_NODE;\n for (const value of transcriptStringValues(transcript)) {\n if (value.includes(COMPACT_MARKER.FOUNDATION)) hasFoundation = true;\n activeNode = extractLastContextTarget(value) ?? activeNode;\n }\n\n if (!hasFoundation) return undefined;\n return {\n [COMPACT_RECORD_FIELDS.ACTIVE_NODE]: activeNode,\n [COMPACT_RECORD_FIELDS.HAS_FOUNDATION]: true,\n };\n}\n\nexport function compactStashPath(worktreeScopeDir: string, sessionToken: string): Result<string> {\n const compactScope = composeScopeDir(worktreeScopeDir, sessionToken, STATE_STORE_DOMAIN.COMPACT);\n if (!compactScope.ok) return compactScope;\n return { ok: true, value: join(compactScope.value, COMPACT_STORE_PATH.STASH_FILE) };\n}\n\nexport function parseCompactRecord(value: unknown): Result<CompactRecord> {\n if (\n typeof value === \"object\"\n && value !== null\n && COMPACT_RECORD_FIELDS.ACTIVE_NODE in value\n && COMPACT_RECORD_FIELDS.HAS_FOUNDATION in value\n && typeof (value as Record<string, unknown>)[COMPACT_RECORD_FIELDS.ACTIVE_NODE] === \"string\"\n && (value as Record<string, unknown>)[COMPACT_RECORD_FIELDS.HAS_FOUNDATION] === true\n ) {\n return {\n ok: true,\n value: {\n active_node: (value as Record<string, string>)[COMPACT_RECORD_FIELDS.ACTIVE_NODE] ?? EMPTY_ACTIVE_NODE,\n has_foundation: true,\n },\n };\n }\n return { ok: false, error: COMPACT_ERROR.RECORD_SHAPE_INVALID };\n}\n\nfunction transcriptStringValues(transcript: string): readonly string[] {\n const values: string[] = [];\n for (const rawLine of transcript.split(JSONL_LINE_SEPARATOR)) {\n const line = rawLine.trim();\n if (line.length === 0) continue;\n try {\n collectStringValues(JSON.parse(line) as unknown, values);\n } catch {\n continue;\n }\n }\n return values;\n}\n\nfunction collectStringValues(value: unknown, values: string[]): void {\n if (typeof value === \"string\") {\n values.push(value);\n return;\n }\n if (Array.isArray(value)) {\n for (const entry of value) collectStringValues(entry, values);\n return;\n }\n if (typeof value === \"object\" && value !== null) {\n for (const entry of Object.values(value)) collectStringValues(entry, values);\n }\n}\n\nfunction extractLastContextTarget(value: string): string | undefined {\n let activeNode: string | undefined;\n let searchFrom = 0;\n while (searchFrom < value.length) {\n const contextIndex = value.indexOf(COMPACT_MARKER.CONTEXT, searchFrom);\n if (contextIndex < 0) return activeNode;\n const target = extractContextTargetAt(value, contextIndex + COMPACT_MARKER.CONTEXT.length);\n if (target !== undefined) activeNode = target;\n searchFrom = contextIndex + COMPACT_MARKER.CONTEXT.length;\n }\n return activeNode;\n}\n\nfunction extractContextTargetAt(value: string, searchFrom: number): string | undefined {\n const targetIndex = value.indexOf(CONTEXT_TARGET_PREFIX, searchFrom);\n if (targetIndex < 0) return undefined;\n const quoteIndex = findOpeningTargetQuote(value, targetIndex + CONTEXT_TARGET_PREFIX.length);\n if (quoteIndex === undefined) return undefined;\n const target = readTargetPath(value, quoteIndex + COMPACT_MARKER.UNESCAPED_TARGET_QUOTE.length);\n return target.startsWith(NODE_PATH_PREFIX) ? target : undefined;\n}\n\nfunction findOpeningTargetQuote(value: string, startIndex: number): number | undefined {\n let index = startIndex;\n while (value[index] === ESCAPE_CHARACTER) index += 1;\n return value[index] === COMPACT_MARKER.UNESCAPED_TARGET_QUOTE ? index : undefined;\n}\n\nfunction readTargetPath(value: string, startIndex: number): string {\n let endIndex = startIndex;\n while (endIndex < value.length && isTargetPathCharacter(value[endIndex] ?? EMPTY_ACTIVE_NODE)) {\n endIndex += 1;\n }\n return value.slice(startIndex, endIndex);\n}\n\nfunction isTargetPathCharacter(character: string): boolean {\n const code = character.charCodeAt(0);\n return (code >= 48 && code <= 57)\n || (code >= 65 && code <= 90)\n || (code >= 97 && code <= 122)\n || character === \".\"\n || character === \"_\"\n || character === \"-\"\n || character === \"/\";\n}\n","import { createHash } from \"node:crypto\";\n\nexport const AGENT_SESSION_ENV = {\n CLAUDE_SESSION_ID: \"CLAUDE_SESSION_ID\",\n CODEX_THREAD_ID: \"CODEX_THREAD_ID\",\n} as const;\n\nexport type AgentSessionEnvironment = Readonly<Record<string, string | undefined>>;\n\nexport const AGENT_SESSION_TOKEN_PATTERN = /^[A-Za-z0-9_-]+$/;\n\nconst AGENT_SESSION_TOKEN_UNSAFE_PATTERN = /[^A-Za-z0-9_-]+/g;\nconst AGENT_SESSION_TOKEN_EDGE_SEPARATOR_PATTERN = /^-+|-+$/g;\nconst AGENT_SESSION_TOKEN_SEPARATOR = \"-\";\nconst AGENT_SESSION_TOKEN_HASH_ALGORITHM = \"sha256\";\nconst AGENT_SESSION_TOKEN_HASH_ENCODING = \"hex\";\nconst AGENT_SESSION_TOKEN_HASH_LENGTH = 12;\nconst EMPTY_TOKEN = \"\";\n\nfunction nonEmptyEnvValue(value: string | undefined): string | undefined {\n return value === undefined || value.length === 0 ? undefined : value;\n}\n\nfunction hashAgentSessionToken(value: string): string {\n return createHash(AGENT_SESSION_TOKEN_HASH_ALGORITHM)\n .update(value)\n .digest(AGENT_SESSION_TOKEN_HASH_ENCODING)\n .slice(0, AGENT_SESSION_TOKEN_HASH_LENGTH);\n}\n\nexport function normalizeAgentSessionToken(value: string): string {\n if (AGENT_SESSION_TOKEN_PATTERN.test(value)) return value;\n\n const normalized = value\n .replace(AGENT_SESSION_TOKEN_UNSAFE_PATTERN, AGENT_SESSION_TOKEN_SEPARATOR)\n .replace(AGENT_SESSION_TOKEN_EDGE_SEPARATOR_PATTERN, EMPTY_TOKEN);\n const hash = hashAgentSessionToken(value);\n return normalized.length === 0 ? hash : `${normalized}${AGENT_SESSION_TOKEN_SEPARATOR}${hash}`;\n}\n\nexport function resolveAgentSessionId(env: AgentSessionEnvironment): string | undefined {\n const raw = nonEmptyEnvValue(env[AGENT_SESSION_ENV.CLAUDE_SESSION_ID])\n ?? nonEmptyEnvValue(env[AGENT_SESSION_ENV.CODEX_THREAD_ID]);\n return raw === undefined ? undefined : normalizeAgentSessionToken(raw);\n}\n","import { createHash, randomBytes as nodeRandomBytes } from \"node:crypto\";\nimport {\n appendFile as nodeAppendFile,\n mkdir as nodeMkdir,\n readdir as nodeReaddir,\n readFile as nodeReadFile,\n writeFile as nodeWriteFile,\n} from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\n\nimport type { Result } from \"@/config/types\";\nimport { detectGitCommonDirProductRoot, detectWorktreeProductRoot, type GitDependencies } from \"@/git/root\";\n\nexport const STATE_STORE_PATH = {\n SPX_DIR: \".spx\",\n BRANCH_SCOPE: \"branch\",\n WORKTREE_SCOPE: \"worktree\",\n SESSIONS_SCOPE: \"sessions\",\n WORKTREES_SCOPE: \"worktrees\",\n RUNS_DIR: \"runs\",\n RUN_FILE_PREFIX: \"run-\",\n JSONL_EXTENSION: \".jsonl\",\n} as const;\n\nexport const STATE_STORE_DOMAIN = {\n AUDIT: \"audit\",\n COMPACT: \"compact\",\n REVIEW: \"review\",\n TEST: \"test\",\n} as const;\n\nexport const STATE_STORE_ERROR = {\n INVALID_TOKEN: \"state-store token must be a safe path segment\",\n INVALID_BRANCH_SLUG: \"state-store branch slug must be normalized before storage\",\n RUN_FILE_CREATE_FAILED: \"state-store run file create failed\",\n RUN_FILE_COLLISION_LIMIT: \"state-store run file collision limit exhausted\",\n RECORD_ALREADY_EXISTS: \"state-store record already exists\",\n RECORD_WRITE_FAILED: \"state-store record write failed\",\n RECORD_READ_FAILED: \"state-store record read failed\",\n} as const;\n\nexport type StateStoreErrorCode = (typeof STATE_STORE_ERROR)[keyof typeof STATE_STORE_ERROR];\n\nexport interface StateStoreErrorInfo {\n readonly code: StateStoreErrorCode;\n readonly detail?: string;\n}\n\nexport const STATE_STORE_BRANCH_IDENTITY = {\n DETACHED_HEAD_PREFIX: \"detached\",\n DETACHED_HEAD_SHA_HEX_LENGTH: 12,\n} as const;\n\nexport const STATE_STORE_BRANCH_SLUG = {\n DEFAULT_MAX_BYTES: 120,\n HASH_PREFIX_HEX_LENGTH: 8,\n} as const;\n\nexport const STATE_STORE_FILE_SYSTEM_METHOD = {\n READ_FILE: \"readFile\",\n READDIR: \"readdir\",\n} as const;\n\nexport interface StateStoreFileEntry {\n readonly name: string;\n isFile(): boolean;\n}\n\nexport interface StateStoreFileSystem {\n mkdir(path: string, options?: { readonly recursive?: boolean }): Promise<void>;\n writeFile(path: string, data: string, options?: { readonly flag?: string }): Promise<void>;\n appendFile(path: string, data: string): Promise<void>;\n readFile(path: string, encoding: \"utf8\"): Promise<string>;\n readdir(path: string, options: { readonly withFileTypes: true }): Promise<readonly StateStoreFileEntry[]>;\n}\n\nexport interface ResolveScopeOptions {\n readonly cwd?: string;\n readonly deps?: GitDependencies;\n}\n\nexport interface CreateRunFileOptions {\n readonly now?: () => Date;\n readonly randomBytes?: (size: number) => Buffer;\n readonly fs?: StateStoreFileSystem;\n readonly maxAttempts?: number;\n}\n\nexport interface JsonlWriteOptions {\n readonly fs?: StateStoreFileSystem;\n}\n\nexport interface JsonlReadOptions {\n readonly fs?: StateStoreJsonlReaderFileSystem;\n}\n\nexport interface StateStoreRunFile {\n readonly runsDir: string;\n readonly runFilePath: string;\n readonly runFileName: string;\n readonly runToken: string;\n readonly runId: string;\n readonly startedAt: string;\n}\n\nexport type JsonValue =\n | string\n | number\n | boolean\n | null\n | readonly JsonValue[]\n | { readonly [key: string]: JsonValue };\n\nexport type JsonRecord = { readonly [key: string]: JsonValue };\nexport type StateStoreJsonlReaderFileSystem = Pick<\n StateStoreFileSystem,\n typeof STATE_STORE_FILE_SYSTEM_METHOD.READ_FILE\n>;\nexport type StateStoreRunReaderFileSystem = Pick<\n StateStoreFileSystem,\n typeof STATE_STORE_FILE_SYSTEM_METHOD.READ_FILE | typeof STATE_STORE_FILE_SYSTEM_METHOD.READDIR\n>;\n\nconst SHA256_ALGORITHM = \"sha256\";\nconst HEX_ENCODING = \"hex\";\nconst RUN_ID_BYTES = 6;\nconst RUN_FILE_CREATE_ATTEMPTS = 10;\nconst RUN_TIMESTAMP_SEPARATOR = \"_\";\nconst RUN_TIMESTAMP_MILLISECOND_DIGITS = 3;\nconst SLUG_SEPARATOR = \"-\";\nconst EMPTY_STRING = \"\";\nconst PATH_SEPARATOR_PATTERN = /[^a-z0-9]+/g;\nconst EDGE_SEPARATOR_PATTERN = /^-|-$/g;\nconst TRAILING_SEPARATOR_PATTERN = /-+$/;\nconst BRANCH_SLUG_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\nconst RUN_TOKEN_PATTERN = /^\\d{4}-\\d{2}-\\d{2}_\\d{2}-\\d{2}-\\d{2}-\\d{3}-[a-f0-9]{12}$/;\nconst TOKEN_PATTERN = /^[A-Za-z0-9_-]+$/;\nexport const EXCLUSIVE_CREATE_FLAG = \"wx\";\nconst WRITE_EXISTING_FLAG = \"r+\";\nexport const ERROR_CODE_FILE_EXISTS = \"EEXIST\";\nexport const ERROR_CODE_NOT_FOUND = \"ENOENT\";\nconst JSONL_LINE_SEPARATOR = \"\\n\";\nconst ERROR_DETAIL_SEPARATOR = \": \";\n\nconst defaultFileSystem: StateStoreFileSystem = {\n mkdir: async (path, options) => {\n await nodeMkdir(path, options);\n },\n writeFile: nodeWriteFile,\n appendFile: nodeAppendFile,\n readFile: nodeReadFile,\n readdir: nodeReaddir,\n};\n\nexport { defaultFileSystem as defaultStateStoreFileSystem };\n\nexport function resolveBranchIdentity(input: {\n readonly branchName?: string;\n readonly headSha: string;\n}): string {\n if (input.branchName !== undefined && input.branchName.length > 0) return input.branchName;\n return `${STATE_STORE_BRANCH_IDENTITY.DETACHED_HEAD_PREFIX}${SLUG_SEPARATOR}${\n input.headSha.slice(0, STATE_STORE_BRANCH_IDENTITY.DETACHED_HEAD_SHA_HEX_LENGTH).toLowerCase()\n }`;\n}\n\nexport function slugBranchIdentity(\n branchIdentity: string,\n maxBytes: number = STATE_STORE_BRANCH_SLUG.DEFAULT_MAX_BYTES,\n): string {\n const hashPrefix = sha256Hex(branchIdentity).slice(0, STATE_STORE_BRANCH_SLUG.HASH_PREFIX_HEX_LENGTH);\n const boundedHashPrefix = hashPrefix.slice(0, Math.max(0, maxBytes));\n const normalizedPrefix = branchIdentity\n .toLowerCase()\n .replace(PATH_SEPARATOR_PATTERN, SLUG_SEPARATOR)\n .replace(EDGE_SEPARATOR_PATTERN, EMPTY_STRING);\n\n if (normalizedPrefix.length === 0) return boundedHashPrefix;\n\n const availablePrefixBytes = maxBytes - STATE_STORE_BRANCH_SLUG.HASH_PREFIX_HEX_LENGTH - SLUG_SEPARATOR.length;\n if (availablePrefixBytes <= 0) return boundedHashPrefix;\n\n const prefix = truncateNormalizedSlugPrefix(normalizedPrefix, availablePrefixBytes);\n return prefix.length === 0 ? boundedHashPrefix : `${prefix}${SLUG_SEPARATOR}${hashPrefix}`;\n}\n\nexport function validateBranchSlug(branchSlug: string): Result<string> {\n return BRANCH_SLUG_PATTERN.test(branchSlug)\n ? { ok: true, value: branchSlug }\n : { ok: false, error: STATE_STORE_ERROR.INVALID_BRANCH_SLUG };\n}\n\nexport function validateScopeToken(token: string): Result<string> {\n return TOKEN_PATTERN.test(token)\n ? { ok: true, value: token }\n : { ok: false, error: STATE_STORE_ERROR.INVALID_TOKEN };\n}\n\nexport async function resolveBranchScopeDir(\n branchSlug: string,\n options: ResolveScopeOptions = {},\n): Promise<Result<string>> {\n const gitResult = await detectGitCommonDirProductRoot(options.cwd, options.deps);\n return branchScopeDir(gitResult.productDir, branchSlug);\n}\n\nexport async function resolveWorktreeScopeDir(options: ResolveScopeOptions = {}): Promise<Result<string>> {\n const gitResult = await detectWorktreeProductRoot(options.cwd, options.deps);\n return worktreeScopeDir(gitResult.productDir);\n}\n\n/** The shared `.spx/sessions` scope dir plus the non-git-repo diagnostic, if any. */\nexport interface ResolveSessionsScopeResult {\n readonly sessionsDir: string;\n readonly warning?: string;\n}\n\n/** The shared `.spx/worktrees` scope dir plus the non-git-repo diagnostic, if any. */\nexport interface ResolveWorktreesScopeResult {\n readonly worktreesDir: string;\n readonly warning?: string;\n}\n\n/**\n * Resolves the shared `.spx/sessions` scope directory from the Git common-dir\n * product root so every worktree addresses the same sessions store. The result\n * is the scope directory only — its consumer composes the status subdirectories\n * on top. Surfaces the non-git-repo diagnostic when resolution falls back to cwd.\n */\nexport async function resolveSessionsScopeDir(\n options: ResolveScopeOptions = {},\n): Promise<ResolveSessionsScopeResult> {\n const gitResult = await detectGitCommonDirProductRoot(options.cwd, options.deps);\n return {\n sessionsDir: sessionsScopeDir(gitResult.productDir),\n warning: gitResult.warning,\n };\n}\n\nexport function branchScopeDir(productDir: string, branchSlug: string): Result<string> {\n const validated = validateBranchSlug(branchSlug);\n if (!validated.ok) return validated;\n return {\n ok: true,\n value: join(productDir, STATE_STORE_PATH.SPX_DIR, STATE_STORE_PATH.BRANCH_SCOPE, validated.value),\n };\n}\n\nexport function worktreeScopeDir(productDir: string): Result<string> {\n return { ok: true, value: join(productDir, STATE_STORE_PATH.SPX_DIR, STATE_STORE_PATH.WORKTREE_SCOPE) };\n}\n\nexport function sessionsScopeDir(productDir: string): string {\n return join(productDir, STATE_STORE_PATH.SPX_DIR, STATE_STORE_PATH.SESSIONS_SCOPE);\n}\n\n/**\n * Resolves the shared `.spx/worktrees` scope directory from the Git common-dir\n * product root so every worktree of the repository addresses the same\n * worktree-occupancy claim store. Surfaces the non-git-repo diagnostic when\n * resolution falls back to cwd.\n */\nexport async function resolveWorktreesScopeDir(\n options: ResolveScopeOptions = {},\n): Promise<ResolveWorktreesScopeResult> {\n const gitResult = await detectGitCommonDirProductRoot(options.cwd, options.deps);\n return {\n worktreesDir: worktreesScopeDir(gitResult.productDir),\n warning: gitResult.warning,\n };\n}\n\nexport function worktreesScopeDir(productDir: string): string {\n return join(productDir, STATE_STORE_PATH.SPX_DIR, STATE_STORE_PATH.WORKTREES_SCOPE);\n}\n\nexport function composeScopeDir(baseScopeDir: string, ...tokens: readonly string[]): Result<string> {\n const segments: string[] = [];\n for (const token of tokens) {\n const validated = validateScopeToken(token);\n if (!validated.ok) return validated;\n segments.push(validated.value);\n }\n return { ok: true, value: join(baseScopeDir, ...segments) };\n}\n\nexport function domainDir(scopeDir: string, domainName: string): Result<string> {\n return composeScopeDir(scopeDir, domainName);\n}\n\nexport function runsDir(scopeDir: string, domainName: string): Result<string> {\n const domain = domainDir(scopeDir, domainName);\n if (!domain.ok) return domain;\n return { ok: true, value: join(domain.value, STATE_STORE_PATH.RUNS_DIR) };\n}\n\nexport function formatRunTimestamp(date: Date): string {\n const year = date.getUTCFullYear();\n const month = String(date.getUTCMonth() + 1).padStart(2, \"0\");\n const day = String(date.getUTCDate()).padStart(2, \"0\");\n const hours = String(date.getUTCHours()).padStart(2, \"0\");\n const minutes = String(date.getUTCMinutes()).padStart(2, \"0\");\n const seconds = String(date.getUTCSeconds()).padStart(2, \"0\");\n const milliseconds = String(date.getUTCMilliseconds()).padStart(RUN_TIMESTAMP_MILLISECOND_DIGITS, \"0\");\n\n return `${year}-${month}-${day}${RUN_TIMESTAMP_SEPARATOR}${hours}-${minutes}-${seconds}-${milliseconds}`;\n}\n\nexport function generateRunId(randomBytes: (size: number) => Buffer = nodeRandomBytes): string {\n return randomBytes(RUN_ID_BYTES).toString(HEX_ENCODING);\n}\n\nexport function runFileName(runToken: string): string {\n return `${STATE_STORE_PATH.RUN_FILE_PREFIX}${runToken}${STATE_STORE_PATH.JSONL_EXTENSION}`;\n}\n\nexport function isRunFileName(name: string): boolean {\n return name.startsWith(STATE_STORE_PATH.RUN_FILE_PREFIX)\n && name.endsWith(STATE_STORE_PATH.JSONL_EXTENSION)\n && RUN_TOKEN_PATTERN.test(name.slice(\n STATE_STORE_PATH.RUN_FILE_PREFIX.length,\n -STATE_STORE_PATH.JSONL_EXTENSION.length,\n ));\n}\n\nexport async function createJsonlRunFile(\n scopeDir: string,\n domainName: string,\n options: CreateRunFileOptions = {},\n): Promise<Result<StateStoreRunFile>> {\n const fs = options.fs ?? defaultFileSystem;\n const domainRunsDir = runsDir(scopeDir, domainName);\n if (!domainRunsDir.ok) return domainRunsDir;\n const maxAttempts = options.maxAttempts ?? RUN_FILE_CREATE_ATTEMPTS;\n const startedDate = (options.now ?? (() => new Date()))();\n const startedAt = formatRunTimestamp(startedDate);\n const randomBytes = options.randomBytes ?? nodeRandomBytes;\n\n try {\n await fs.mkdir(domainRunsDir.value, { recursive: true });\n } catch (error) {\n return {\n ok: false,\n error: formatStateStoreError(STATE_STORE_ERROR.RUN_FILE_CREATE_FAILED, toErrorMessage(error)),\n };\n }\n\n for (let attempt = 0; attempt < maxAttempts; attempt += 1) {\n const runId = generateRunId(randomBytes);\n const runToken = `${startedAt}${SLUG_SEPARATOR}${runId}`;\n const name = runFileName(runToken);\n const path = join(domainRunsDir.value, name);\n try {\n await fs.writeFile(path, EMPTY_STRING, { flag: EXCLUSIVE_CREATE_FLAG });\n return {\n ok: true,\n value: { runsDir: domainRunsDir.value, runFilePath: path, runFileName: name, runToken, runId, startedAt },\n };\n } catch (error) {\n if (hasErrorCode(error, ERROR_CODE_FILE_EXISTS)) continue;\n return {\n ok: false,\n error: formatStateStoreError(STATE_STORE_ERROR.RUN_FILE_CREATE_FAILED, toErrorMessage(error)),\n };\n }\n }\n\n return { ok: false, error: STATE_STORE_ERROR.RUN_FILE_COLLISION_LIMIT };\n}\n\nexport async function writeJsonlRunRecord(\n runFilePath: string,\n record: JsonRecord,\n options: JsonlWriteOptions = {},\n): Promise<Result<string>> {\n const fs = options.fs ?? defaultFileSystem;\n try {\n const existing = await fs.readFile(runFilePath, \"utf8\");\n if (existing.trim().length > 0) return { ok: false, error: STATE_STORE_ERROR.RECORD_ALREADY_EXISTS };\n } catch (error) {\n if (!hasErrorCode(error, ERROR_CODE_NOT_FOUND)) {\n return {\n ok: false,\n error: formatStateStoreError(STATE_STORE_ERROR.RECORD_WRITE_FAILED, toErrorMessage(error)),\n };\n }\n }\n\n try {\n await fs.writeFile(runFilePath, serializeJsonlRecord(record), { flag: WRITE_EXISTING_FLAG });\n return { ok: true, value: runFilePath };\n } catch (error) {\n return {\n ok: false,\n error: formatStateStoreError(STATE_STORE_ERROR.RECORD_WRITE_FAILED, toErrorMessage(error)),\n };\n }\n}\n\nexport async function appendJsonlRecord(\n filePath: string,\n record: JsonRecord,\n options: JsonlWriteOptions = {},\n): Promise<Result<string>> {\n const fs = options.fs ?? defaultFileSystem;\n try {\n await fs.mkdir(dirname(filePath), { recursive: true });\n await fs.appendFile(filePath, serializeJsonlRecord(record));\n return { ok: true, value: filePath };\n } catch (error) {\n return {\n ok: false,\n error: formatStateStoreError(STATE_STORE_ERROR.RECORD_WRITE_FAILED, toErrorMessage(error)),\n };\n }\n}\n\nexport async function readLatestJsonlRecord(\n filePath: string,\n options: JsonlReadOptions = {},\n): Promise<Result<unknown | undefined>> {\n const fs = options.fs ?? defaultFileSystem;\n let content: string;\n try {\n content = await fs.readFile(filePath, \"utf8\");\n } catch (error) {\n if (hasErrorCode(error, ERROR_CODE_NOT_FOUND)) return { ok: true, value: undefined };\n return {\n ok: false,\n error: formatStateStoreError(STATE_STORE_ERROR.RECORD_READ_FAILED, toErrorMessage(error)),\n };\n }\n\n for (const line of nonEmptyJsonlLinesNewestFirst(content)) {\n try {\n return { ok: true, value: JSON.parse(line) as unknown };\n } catch {\n continue;\n }\n }\n\n return { ok: true, value: undefined };\n}\n\nexport function latestNonEmptyJsonlLine(content: string): string | undefined {\n return nonEmptyJsonlLinesNewestFirst(content)[0];\n}\n\nexport function compareAsciiStrings(left: string, right: string): number {\n if (left < right) return -1;\n if (left > right) return 1;\n return 0;\n}\n\nexport function formatStateStoreError(code: StateStoreErrorCode, detail?: string): string {\n return detail === undefined ? code : `${code}${ERROR_DETAIL_SEPARATOR}${detail}`;\n}\n\nexport function parseStateStoreError(error: string): StateStoreErrorInfo | undefined {\n for (const code of Object.values(STATE_STORE_ERROR)) {\n if (error === code) return { code };\n const prefix = `${code}${ERROR_DETAIL_SEPARATOR}`;\n if (error.startsWith(prefix)) return { code, detail: error.slice(prefix.length) };\n }\n return undefined;\n}\n\nexport function serializeJsonlRecord(record: JsonRecord): string {\n return `${JSON.stringify(record)}${JSONL_LINE_SEPARATOR}`;\n}\n\nexport function sha256Hex(value: string): string {\n return createHash(SHA256_ALGORITHM).update(value).digest(HEX_ENCODING);\n}\n\nfunction truncateNormalizedSlugPrefix(normalizedPrefix: string, maxBytes: number): string {\n let prefix = normalizedPrefix.slice(0, maxBytes).replace(TRAILING_SEPARATOR_PATTERN, EMPTY_STRING);\n while (Buffer.byteLength(prefix) > maxBytes) {\n prefix = prefix.slice(0, -1).replace(TRAILING_SEPARATOR_PATTERN, EMPTY_STRING);\n }\n return prefix;\n}\n\nfunction nonEmptyJsonlLinesNewestFirst(content: string): string[] {\n const lines = content.split(JSONL_LINE_SEPARATOR);\n const latestLines: string[] = [];\n for (let index = lines.length - 1; index >= 0; index -= 1) {\n const line = lines[index]?.trim() ?? EMPTY_STRING;\n if (line.length > 0) latestLines.push(line);\n }\n return latestLines;\n}\n\nexport function hasErrorCode(error: unknown, code: string): boolean {\n return (\n typeof error === \"object\"\n && error !== null\n && !Array.isArray(error)\n && \"code\" in error\n && (error as { readonly code?: unknown }).code === code\n );\n}\n\nfunction toErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n","import { execa } from \"execa\";\nimport { basename, dirname, isAbsolute, join, resolve } from \"node:path\";\n\nimport { withoutGitEnvironment } from \"./environment\";\n\n// Result from product-directory detection.\nexport interface GitProductDirResult {\n /** Absolute path to product directory (or cwd if not in git repo) */\n productDir: string;\n /** Whether the directory is inside a git repository */\n isGitRepo: boolean;\n /** Warning message when not in a git repo (undefined if in repo) */\n warning?: string;\n}\n\n/**\n * Result from Git common-dir product-root detection. Carries the local worktree\n * root (`git rev-parse --show-toplevel`, or `cwd` outside a git repository) as a\n * required field alongside the Git common-dir `productDir`, so a caller that\n * needs both roots reads `--show-toplevel` once.\n */\nexport interface GitCommonDirProductDirResult extends GitProductDirResult {\n /** The local worktree root — the `--show-toplevel` value, or `cwd` outside a git repository. */\n worktreeRoot: string;\n}\n\n/**\n * Git-plumbing observations describing one checkout, gathered by the probe and\n * classified by {@link isMainCheckout}. Every field is a git-plumbing\n * observation normalized at the boundary; no main-checkout classification is\n * performed during gathering.\n */\nexport interface GitFacts {\n /** The local worktree root — `git rev-parse --show-toplevel`. */\n worktreeRoot: string;\n /** Active non-bare, non-prunable roots observed from `git worktree list --porcelain`. */\n worktreeRoots: readonly string[];\n /** Whether `git worktree list --porcelain` completed successfully. */\n worktreeListRead: boolean;\n /** The absolute common directory — `git rev-parse --git-common-dir`. */\n commonDir: string;\n /** Whether the common directory is a bare repository — `git config --get core.bare` is `true`. */\n commonDirIsBare: boolean;\n /** The `origin` remote URL — `git remote get-url origin` — or null when `origin` is unset. */\n originUrl: string | null;\n}\n\n// Minimal command result shape used by product-directory detection.\nexport interface ExecResult {\n /** Process exit code */\n exitCode: number;\n /** Standard output */\n stdout: string;\n /** Standard error */\n stderr: string;\n}\n\n// Dependencies for git operations.\nexport interface GitDependencies {\n // Execute a command.\n execa: (\n command: string,\n args: string[],\n options?: { cwd?: string; reject?: boolean },\n ) => Promise<ExecResult>;\n}\n\n// Default dependencies using real execa.\nexport const defaultGitDependencies: GitDependencies = {\n execa: async (command, args, options) => {\n const result = await execa(command, args, {\n ...options,\n env: withoutGitEnvironment(process.env),\n extendEnv: false,\n });\n return {\n exitCode: result.exitCode ?? 0,\n stdout: typeof result.stdout === \"string\" ? result.stdout : String(result.stdout),\n stderr: typeof result.stderr === \"string\" ? result.stderr : String(result.stderr),\n };\n },\n};\n\nexport const NOT_GIT_REPO_WARNING =\n \"Warning: Not in a git repository; resolving session storage relative to the current directory.\";\n\nexport const GIT_ROOT_COMMAND = {\n EXECUTABLE: \"git\",\n REV_PARSE: \"rev-parse\",\n ABBREV_REF: \"--abbrev-ref\",\n GIT_COMMON_DIR: \"--git-common-dir\",\n HEAD: \"HEAD\",\n SHOW_TOPLEVEL: \"--show-toplevel\",\n SYMBOLIC_REF: \"symbolic-ref\",\n SHOW_REF: \"show-ref\",\n VERIFY: \"--verify\",\n QUIET: \"--quiet\",\n SHORT: \"--short\",\n ORIGIN_HEAD_REF: \"refs/remotes/origin/HEAD\",\n STATUS: \"status\",\n WORKTREE: \"worktree\",\n LIST: \"list\",\n PORCELAIN: \"--porcelain\",\n PATH_FORMAT_ABSOLUTE: \"--path-format=absolute\",\n CONFIG: \"config\",\n CONFIG_GET: \"--get\",\n CONFIG_TYPE_BOOL: \"--type=bool\",\n CORE_BARE_KEY: \"core.bare\",\n REMOTE: \"remote\",\n GET_URL: \"get-url\",\n ORIGIN: \"origin\",\n} as const;\n\n/** The `.git` suffix a repository URL or bare directory carries; stripped to recover the repository name. */\nexport const GIT_URL_SUFFIX = \".git\";\n\n/** The basename of a non-bare worktree's local git directory — the common-dir fallback when `--git-common-dir` is unavailable. */\nexport const GIT_DIR_BASENAME = \".git\";\n\n/** Prefix on the remote-tracking ref returned by `symbolic-ref refs/remotes/origin/HEAD`. */\nexport const ORIGIN_REF_PREFIX = \"origin/\";\n\n/** The full remote-tracking ref prefix for `origin` branches — the namespace `show-ref --verify` checks for exact existence. */\nexport const REMOTE_ORIGIN_REF_PREFIX = \"refs/remotes/origin/\";\n\n/** The `core.bare` config value a bare repository carries; every other value (including unset) is non-bare. */\nexport const GIT_CORE_BARE_TRUE = \"true\";\n\nexport const GIT_SHOW_TOPLEVEL_ARGS = [\n GIT_ROOT_COMMAND.REV_PARSE,\n GIT_ROOT_COMMAND.SHOW_TOPLEVEL,\n] as const;\n\n// `--path-format=absolute` makes git emit an absolute common dir regardless of\n// the working directory; without it `--git-common-dir` is relative to git's cwd\n// (e.g. `../../.git` from a subdirectory), which misresolves against the toplevel.\nexport const GIT_COMMON_DIR_ARGS = [\n GIT_ROOT_COMMAND.REV_PARSE,\n GIT_ROOT_COMMAND.PATH_FORMAT_ABSOLUTE,\n GIT_ROOT_COMMAND.GIT_COMMON_DIR,\n] as const;\n\n// `git config --get --type=bool core.bare` reads the shared config the worktrees\n// of a bare pool inherit, normalizing every Git boolean spelling (`True`, `yes`,\n// `on`, `1`) to `true`/`false` so a non-canonical value is not misread as\n// non-bare: it returns `true` from every pool worktree even though\n// `--is-bare-repository` returns `false` there, and `false` from a non-bare\n// repository's main and linked worktrees alike. It is the signal that separates\n// a bare pool (main checkout is the repository-named worktree) from a non-bare\n// repository (main checkout is the main working tree).\nexport const GIT_CORE_BARE_ARGS = [\n GIT_ROOT_COMMAND.CONFIG,\n GIT_ROOT_COMMAND.CONFIG_GET,\n GIT_ROOT_COMMAND.CONFIG_TYPE_BOOL,\n GIT_ROOT_COMMAND.CORE_BARE_KEY,\n] as const;\n\n// `git remote get-url origin` reads the `origin` remote URL the worktrees of a\n// bare pool share, from which the repository name — the final path segment minus\n// a `.git` suffix — is the directory name the pool's main checkout carries.\nexport const GIT_REMOTE_GET_URL_ORIGIN_ARGS = [\n GIT_ROOT_COMMAND.REMOTE,\n GIT_ROOT_COMMAND.GET_URL,\n GIT_ROOT_COMMAND.ORIGIN,\n] as const;\n\nexport const GIT_CURRENT_BRANCH_ARGS = [\n GIT_ROOT_COMMAND.REV_PARSE,\n GIT_ROOT_COMMAND.ABBREV_REF,\n GIT_ROOT_COMMAND.HEAD,\n] as const;\n\nexport const GIT_HEAD_SHA_ARGS = [\n GIT_ROOT_COMMAND.REV_PARSE,\n GIT_ROOT_COMMAND.HEAD,\n] as const;\n\nexport const GIT_ORIGIN_HEAD_REF_ARGS = [\n GIT_ROOT_COMMAND.SYMBOLIC_REF,\n GIT_ROOT_COMMAND.SHORT,\n GIT_ROOT_COMMAND.ORIGIN_HEAD_REF,\n] as const;\n\nexport const GIT_STATUS_PORCELAIN_ARGS = [\n GIT_ROOT_COMMAND.STATUS,\n GIT_ROOT_COMMAND.PORCELAIN,\n] as const;\n\nexport const GIT_WORKTREE_LIST_PORCELAIN_ARGS = [\n GIT_ROOT_COMMAND.WORKTREE,\n GIT_ROOT_COMMAND.LIST,\n GIT_ROOT_COMMAND.PORCELAIN,\n] as const;\n\nexport const GIT_WORKTREE_PORCELAIN_ROOT_PREFIX = \"worktree \";\nexport const GIT_WORKTREE_PORCELAIN_BARE_LINE = \"bare\";\nexport const GIT_WORKTREE_PORCELAIN_PRUNABLE_LINE = \"prunable\";\nexport const GIT_WORKTREE_PORCELAIN_PRUNABLE_PREFIX = `${GIT_WORKTREE_PORCELAIN_PRUNABLE_LINE} `;\nconst TRAILING_PATH_SEPARATORS_PATTERN = /[\\\\/]+$/;\n\n// Detects the local worktree product directory.\nexport async function detectWorktreeProductRoot(\n cwd: string = process.cwd(),\n deps: GitDependencies = defaultGitDependencies,\n): Promise<GitProductDirResult> {\n try {\n const result = await deps.execa(\n GIT_ROOT_COMMAND.EXECUTABLE,\n [...GIT_SHOW_TOPLEVEL_ARGS],\n { cwd, reject: false },\n );\n\n // Git command succeeded - we're in a repo\n if (result.exitCode === 0 && result.stdout) {\n return {\n productDir: extractStdout(result.stdout),\n isGitRepo: true,\n };\n }\n\n // Git command failed - not in a repo\n return {\n productDir: cwd,\n isGitRepo: false,\n warning: NOT_GIT_REPO_WARNING,\n };\n } catch {\n // Command execution failed (git not installed, permission error, etc.)\n return {\n productDir: cwd,\n isGitRepo: false,\n warning: NOT_GIT_REPO_WARNING,\n };\n }\n}\n\n// Extracts a trimmed string from execa stdout.\nfunction extractStdout(stdout: unknown): string {\n if (!stdout) return \"\";\n const str = typeof stdout === \"string\" ? stdout : String(stdout);\n return str.trim().replace(TRAILING_PATH_SEPARATORS_PATTERN, \"\");\n}\n\nfunction trimStdout(stdout: unknown): string {\n if (!stdout) return \"\";\n const str = typeof stdout === \"string\" ? stdout : String(stdout);\n return str.trim();\n}\n\n// Detects the Git common-dir product root, resolving through git worktrees.\nexport async function detectGitCommonDirProductRoot(\n cwd: string = process.cwd(),\n deps: GitDependencies = defaultGitDependencies,\n): Promise<GitCommonDirProductDirResult> {\n try {\n // Step 1: Get the local worktree product directory via --show-toplevel\n const toplevelResult = await deps.execa(\n GIT_ROOT_COMMAND.EXECUTABLE,\n [...GIT_SHOW_TOPLEVEL_ARGS],\n { cwd, reject: false },\n );\n\n if (toplevelResult.exitCode !== 0 || !toplevelResult.stdout) {\n return {\n productDir: cwd,\n isGitRepo: false,\n warning: NOT_GIT_REPO_WARNING,\n worktreeRoot: cwd,\n };\n }\n\n const toplevel = extractStdout(toplevelResult.stdout);\n\n // Step 2: Get the common git directory via --git-common-dir\n const commonDirResult = await deps.execa(\n GIT_ROOT_COMMAND.EXECUTABLE,\n [...GIT_COMMON_DIR_ARGS],\n { cwd, reject: false },\n );\n\n if (commonDirResult.exitCode !== 0 || !commonDirResult.stdout) {\n // Fallback: if --git-common-dir fails, use toplevel\n return {\n productDir: toplevel,\n isGitRepo: true,\n worktreeRoot: toplevel,\n };\n }\n\n const commonDir = extractStdout(commonDirResult.stdout);\n\n // Step 3: Resolve the common dir to an absolute path. GIT_COMMON_DIR_ARGS\n // requests --path-format=absolute, so git emits an absolute path; the\n // relative branch is a defensive fallback for git builds that ignore it.\n const absoluteCommonDir = isAbsolute(commonDir)\n ? commonDir\n : resolve(toplevel, commonDir);\n\n // Step 4: The Git common-dir product root is the parent of the common .git directory\n const gitCommonDirProductRoot = dirname(absoluteCommonDir);\n\n return {\n productDir: gitCommonDirProductRoot,\n isGitRepo: true,\n worktreeRoot: toplevel,\n };\n } catch {\n return {\n productDir: cwd,\n isGitRepo: false,\n warning: NOT_GIT_REPO_WARNING,\n worktreeRoot: cwd,\n };\n }\n}\n\n/**\n * Resolves the repository's default branch name from `origin/HEAD`\n * (e.g. `\"main\"`). Returns null when `origin/HEAD` is unset or unresolvable.\n */\nexport async function resolveDefaultBranch(\n cwd: string = process.cwd(),\n deps: GitDependencies = defaultGitDependencies,\n): Promise<string | null> {\n const result = await deps.execa(\n GIT_ROOT_COMMAND.EXECUTABLE,\n [...GIT_ORIGIN_HEAD_REF_ARGS],\n { cwd, reject: false },\n );\n if (result.exitCode !== 0) return null;\n const ref = extractStdout(result.stdout);\n if (!ref.startsWith(ORIGIN_REF_PREFIX)) return null;\n const branch = ref.slice(ORIGIN_REF_PREFIX.length);\n return branch.length === 0 ? null : branch;\n}\n\n/**\n * Returns the checked-out branch name, or null when HEAD is detached or the\n * branch name is unavailable.\n */\nexport async function getCurrentBranch(\n cwd: string = process.cwd(),\n deps: GitDependencies = defaultGitDependencies,\n): Promise<string | null> {\n const result = await deps.execa(\n GIT_ROOT_COMMAND.EXECUTABLE,\n [...GIT_CURRENT_BRANCH_ARGS],\n { cwd, reject: false },\n );\n if (result.exitCode !== 0) return null;\n const branch = extractStdout(result.stdout);\n if (branch.length === 0 || branch === GIT_ROOT_COMMAND.HEAD) return null;\n return branch;\n}\n\n/** Returns the HEAD commit SHA, or null when unavailable. */\nexport async function getHeadSha(\n cwd: string = process.cwd(),\n deps: GitDependencies = defaultGitDependencies,\n): Promise<string | null> {\n const result = await deps.execa(\n GIT_ROOT_COMMAND.EXECUTABLE,\n [...GIT_HEAD_SHA_ARGS],\n { cwd, reject: false },\n );\n if (result.exitCode !== 0) return null;\n const sha = extractStdout(result.stdout);\n return sha.length === 0 ? null : sha;\n}\n\n/**\n * Returns the commit SHA at the tip of the given ref (e.g. `\"origin/main\"`),\n * or null when the ref cannot be resolved.\n */\nexport async function resolveRefSha(\n ref: string,\n cwd: string = process.cwd(),\n deps: GitDependencies = defaultGitDependencies,\n): Promise<string | null> {\n const result = await deps.execa(\n GIT_ROOT_COMMAND.EXECUTABLE,\n [GIT_ROOT_COMMAND.REV_PARSE, ref],\n { cwd, reject: false },\n );\n if (result.exitCode !== 0) return null;\n const sha = extractStdout(result.stdout);\n return sha.length === 0 ? null : sha;\n}\n\n/**\n * Whether `branch` names an exact remote-tracking branch on `origin` —\n * `git show-ref --verify --quiet refs/remotes/origin/<branch>` exits zero.\n *\n * `show-ref --verify` matches the full ref path literally and applies no\n * revision-expression syntax, so a revision expression like `main~1` or\n * `main^{commit}`, or a bare SHA, never matches an existing remote branch —\n * the check verifies a branch, not a resolvable revision.\n *\n * `HEAD` is excluded explicitly: `refs/remotes/origin/HEAD` is the symbolic\n * default-branch pointer, the one non-branch entry in the `refs/remotes/origin/`\n * namespace, so a literal `HEAD` (which a detached worktree's\n * `rev-parse --abbrev-ref HEAD` yields) is not a work branch.\n */\nexport async function originBranchExists(\n branch: string,\n cwd: string = process.cwd(),\n deps: GitDependencies = defaultGitDependencies,\n): Promise<boolean> {\n if (branch === GIT_ROOT_COMMAND.HEAD) return false;\n const result = await deps.execa(\n GIT_ROOT_COMMAND.EXECUTABLE,\n [\n GIT_ROOT_COMMAND.SHOW_REF,\n GIT_ROOT_COMMAND.VERIFY,\n GIT_ROOT_COMMAND.QUIET,\n `${REMOTE_ORIGIN_REF_PREFIX}${branch}`,\n ],\n { cwd, reject: false },\n );\n return result.exitCode === 0;\n}\n\n/**\n * Whether the working tree at `cwd` is clean — `git status --porcelain` emits\n * nothing. A non-zero git exit is treated as not clean.\n */\nexport async function isWorkingTreeClean(\n cwd: string = process.cwd(),\n deps: GitDependencies = defaultGitDependencies,\n): Promise<boolean> {\n const result = await deps.execa(\n GIT_ROOT_COMMAND.EXECUTABLE,\n [...GIT_STATUS_PORCELAIN_ARGS],\n { cwd, reject: false },\n );\n if (result.exitCode !== 0) return false;\n return extractStdout(result.stdout).length === 0;\n}\n\n/**\n * The repository name an `origin` URL carries — its final path segment with a\n * trailing `.git` removed — or null when the URL is absent or carries no name.\n *\n * Pure and total: parses every URL form git accepts (`https://host/owner/repo.git`,\n * `git@host:owner/repo.git`, a local path, with or without the `.git` suffix or a\n * trailing slash) by taking the segment after the last `/`, `\\`, or `:` separator.\n */\nexport function repositoryName(originUrl: string | null): string | null {\n if (originUrl === null) return null;\n const trimmed = originUrl.trim().replace(TRAILING_PATH_SEPARATORS_PATTERN, \"\");\n const lastSeparator = Math.max(\n trimmed.lastIndexOf(\"/\"),\n trimmed.lastIndexOf(\"\\\\\"),\n trimmed.lastIndexOf(\":\"),\n );\n const segment = trimmed.slice(lastSeparator + 1);\n const name = segment.endsWith(GIT_URL_SUFFIX)\n ? segment.slice(0, -GIT_URL_SUFFIX.length)\n : segment;\n return name.length === 0 ? null : name;\n}\n\nfunction normalizeGitPath(path: string): string {\n return path.trim().replace(TRAILING_PATH_SEPARATORS_PATTERN, \"\");\n}\n\nfunction normalizedGitPathKey(path: string): string {\n return normalizeGitPath(path).replace(/\\\\/g, \"/\");\n}\n\nfunction isObservedWorktreeRoot(worktreeRoots: readonly string[], candidate: string): boolean {\n const candidateKey = normalizedGitPathKey(candidate);\n return worktreeRoots.some((root) => normalizedGitPathKey(root) === candidateKey);\n}\n\nfunction isPrunableWorktreeRecordLine(line: string): boolean {\n return line === GIT_WORKTREE_PORCELAIN_PRUNABLE_LINE\n || line.startsWith(GIT_WORKTREE_PORCELAIN_PRUNABLE_PREFIX);\n}\n\nfunction parseWorktreeRoots(stdout: string): string[] {\n const roots: string[] = [];\n for (const record of stdout.split(/\\n\\n+/)) {\n const lines = record.split(\"\\n\");\n if (\n lines.includes(GIT_WORKTREE_PORCELAIN_BARE_LINE)\n || lines.some(isPrunableWorktreeRecordLine)\n ) continue;\n const rootLine = lines.find((line) => line.startsWith(GIT_WORKTREE_PORCELAIN_ROOT_PREFIX));\n if (rootLine === undefined) continue;\n const root = normalizeGitPath(rootLine.slice(GIT_WORKTREE_PORCELAIN_ROOT_PREFIX.length));\n if (root.length > 0) roots.push(root);\n }\n return roots;\n}\n\nfunction observedWorktreeRoots(worktreeListResult: ExecResult): string[] {\n if (worktreeListResult.exitCode !== 0) return [];\n return [...new Set(parseWorktreeRoots(worktreeListResult.stdout))];\n}\n\n/**\n * Whether the observed {@link GitFacts} identify the repository's main checkout.\n *\n * Pure and total: a non-bare repository's main working tree — the parent of its\n * common directory — is the main checkout whatever branch it holds and whether\n * or not it has linked worktrees; a bare-repository pool worktree is the main\n * checkout exactly when its common directory sits beside the worktree, its\n * directory basename equals the `origin` repository name, and git reports the\n * worktree root in the observed worktree list. The verdict reads no branch.\n */\nexport function isMainCheckout(facts: GitFacts): boolean {\n const commonDirParent = dirname(facts.commonDir);\n // Non-bare repository: only the main working tree — the parent of the common\n // directory — is the main checkout, whatever branch it holds and whether or\n // not the repository has linked worktrees.\n if (!facts.commonDirIsBare) return commonDirParent === facts.worktreeRoot;\n // Bare-repository pool: the common directory is a sibling of the worktree, and\n // the worktree directory is named after the `origin` repository.\n if (commonDirParent !== dirname(facts.worktreeRoot)) return false;\n const name = repositoryName(facts.originUrl);\n return name !== null\n && basename(facts.worktreeRoot) === name\n && facts.worktreeListRead\n && isObservedWorktreeRoot(facts.worktreeRoots, facts.worktreeRoot);\n}\n\n/**\n * The absolute path of the repository's main checkout designated by the observed\n * {@link GitFacts}, or null when no main checkout is designable.\n *\n * Pure and total: a non-bare repository designates its main working tree — the\n * parent of the common directory — from any of its worktrees; a bare-repository\n * pool designates the `origin`-repository-named worktree beside the bare\n * repository (the parent of the common directory joined with the repository name)\n * only when that worktree is observed, and designates no path when the pool\n * resolves no repository name or the repository-named worktree does not exist.\n */\nexport function mainCheckoutPath(facts: GitFacts): string | null {\n const commonDirParent = dirname(facts.commonDir);\n // Non-bare repository: the main checkout is the main working tree — the parent\n // of the common directory — reachable from any of its worktrees.\n if (!facts.commonDirIsBare) return commonDirParent;\n // Bare-repository pool: invert the name-and-placement rule to construct the path.\n const name = repositoryName(facts.originUrl);\n if (name === null) return null;\n if (!facts.worktreeListRead) return null;\n const candidate = join(commonDirParent, name);\n return isObservedWorktreeRoot(facts.worktreeRoots, candidate) ? candidate : null;\n}\n\n/**\n * Reads the {@link GitFacts} for `cwd` through the injected git runner. Returns\n * null only when `cwd` is outside a git repository — `git rev-parse\n * --show-toplevel` fails. When `--show-toplevel` succeeds but `--git-common-dir`\n * does not, it falls back to a non-bare single-tree shape (common dir\n * `<worktreeRoot>/.git`) so detection agrees with `detectGitCommonDirProductRoot`,\n * which falls back to the toplevel on the same failure.\n */\nexport async function gatherGitFacts(\n cwd: string = process.cwd(),\n deps: GitDependencies = defaultGitDependencies,\n): Promise<GitFacts | null> {\n try {\n // The toplevel, common-dir, and origin reads are independent, so they run in\n // one round-trip; only the bareness check depends on common-dir succeeding.\n const [toplevelResult, commonDirResult, originResult, worktreeListResult] = await Promise.all([\n deps.execa(GIT_ROOT_COMMAND.EXECUTABLE, [...GIT_SHOW_TOPLEVEL_ARGS], { cwd, reject: false }),\n deps.execa(GIT_ROOT_COMMAND.EXECUTABLE, [...GIT_COMMON_DIR_ARGS], { cwd, reject: false }),\n deps.execa(GIT_ROOT_COMMAND.EXECUTABLE, [...GIT_REMOTE_GET_URL_ORIGIN_ARGS], { cwd, reject: false }),\n deps.execa(GIT_ROOT_COMMAND.EXECUTABLE, [...GIT_WORKTREE_LIST_PORCELAIN_ARGS], { cwd, reject: false }),\n ]);\n if (toplevelResult.exitCode !== 0 || !toplevelResult.stdout) return null;\n\n const worktreeRoot = extractStdout(toplevelResult.stdout);\n const worktreeListRead = worktreeListResult.exitCode === 0;\n const worktreeRoots = observedWorktreeRoots(worktreeListResult);\n const originUrl = originResult.exitCode === 0 && originResult.stdout\n ? trimStdout(originResult.stdout)\n : null;\n\n // Mirror the `--git-common-dir` fallback of detectGitCommonDirProductRoot: a\n // worktree whose common dir cannot be read is treated as a non-bare single\n // tree rooted at the worktree, so both resolvers agree rather than this one\n // alone reporting \"not a checkout\".\n if (commonDirResult.exitCode !== 0 || !commonDirResult.stdout) {\n return {\n worktreeRoot,\n worktreeRoots,\n worktreeListRead,\n commonDir: join(worktreeRoot, GIT_DIR_BASENAME),\n commonDirIsBare: false,\n originUrl,\n };\n }\n\n const rawCommonDir = extractStdout(commonDirResult.stdout);\n const commonDir = isAbsolute(rawCommonDir) ? rawCommonDir : resolve(worktreeRoot, rawCommonDir);\n const bareResult = await deps.execa(\n GIT_ROOT_COMMAND.EXECUTABLE,\n [...GIT_CORE_BARE_ARGS],\n { cwd, reject: false },\n );\n const commonDirIsBare = bareResult.exitCode === 0\n && extractStdout(bareResult.stdout) === GIT_CORE_BARE_TRUE;\n return { worktreeRoot, worktreeRoots, worktreeListRead, commonDir, commonDirIsBare, originUrl };\n } catch {\n // Command execution failed (git not installed, permission error, etc.) —\n // the checkout cannot be classified, so it is not the main checkout.\n return null;\n }\n}\n\n/**\n * Whether the checkout at `cwd` is the repository's main checkout, composing the\n * probe with {@link isMainCheckout}. A `cwd` outside a git repository is not the\n * main checkout.\n */\nexport async function detectMainCheckout(\n cwd: string = process.cwd(),\n deps: GitDependencies = defaultGitDependencies,\n): Promise<boolean> {\n const facts = await gatherGitFacts(cwd, deps);\n if (facts === null) return false;\n return isMainCheckout(facts);\n}\n","/**\n * Removes Git context and identity variables for read-only commands that must\n * resolve from their own cwd instead of an inherited hook/worktree context.\n * Commit and tag callers need an identity-preserving environment instead.\n */\nexport function withoutGitEnvironment(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\n const cleaned = { ...env };\n for (const key of Object.keys(cleaned)) {\n if (key.startsWith(\"GIT_\")) {\n delete cleaned[key];\n }\n }\n return cleaned;\n}\n","import { compactStashPath, parseCompactRecord, resolveCompactSessionToken } from \"@/domains/compact\";\nimport type { AgentSessionEnvironment } from \"@/domains/session/agent-session\";\nimport { readLatestJsonlRecord, resolveWorktreeScopeDir } from \"@/lib/state-store\";\n\nexport interface CompactRetrieveOptions {\n readonly sessionId?: string;\n readonly cwd?: string;\n readonly env?: AgentSessionEnvironment;\n}\n\nexport interface CompactRetrieveResult {\n readonly exitCode: 0 | 1;\n readonly output: string;\n}\n\nconst EMPTY_OUTPUT = \"\";\n\nexport async function compactRetrieveCommand(options: CompactRetrieveOptions): Promise<CompactRetrieveResult> {\n const sessionToken = resolveCompactSessionToken(options.sessionId, options.env ?? process.env);\n if (sessionToken === undefined) return { exitCode: 1, output: EMPTY_OUTPUT };\n\n const worktreeScope = await resolveWorktreeScopeDir({ cwd: options.cwd });\n if (!worktreeScope.ok) return { exitCode: 1, output: EMPTY_OUTPUT };\n const stashPath = compactStashPath(worktreeScope.value, sessionToken);\n if (!stashPath.ok) return { exitCode: 1, output: EMPTY_OUTPUT };\n const latest = await readLatestJsonlRecord(stashPath.value);\n if (!latest.ok || latest.value === undefined) return { exitCode: 1, output: EMPTY_OUTPUT };\n const record = parseCompactRecord(latest.value);\n if (!record.ok) return { exitCode: 1, output: EMPTY_OUTPUT };\n return { exitCode: 0, output: `${JSON.stringify(record.value)}\\n` };\n}\n","import { readFile } from \"node:fs/promises\";\n\nimport { compactStashPath, extractCompactRecord, resolveCompactSessionToken } from \"@/domains/compact\";\nimport type { AgentSessionEnvironment } from \"@/domains/session/agent-session\";\nimport { appendJsonlRecord, resolveWorktreeScopeDir } from \"@/lib/state-store\";\n\nexport interface CompactStoreOptions {\n readonly transcript: string;\n readonly sessionId?: string;\n readonly cwd?: string;\n readonly env?: AgentSessionEnvironment;\n}\n\nconst UTF8_ENCODING = \"utf8\";\n\nexport async function compactStoreCommand(options: CompactStoreOptions): Promise<0 | 1> {\n const sessionToken = resolveCompactSessionToken(options.sessionId, options.env ?? process.env);\n if (sessionToken === undefined) return 1;\n\n let transcript: string;\n try {\n transcript = await readFile(options.transcript, UTF8_ENCODING);\n } catch {\n return 1;\n }\n\n const record = extractCompactRecord(transcript);\n if (record === undefined) return 0;\n\n const worktreeScope = await resolveWorktreeScopeDir({ cwd: options.cwd });\n if (!worktreeScope.ok) return 1;\n const stashPath = compactStashPath(worktreeScope.value, sessionToken);\n if (!stashPath.ok) return 1;\n const written = await appendJsonlRecord(stashPath.value, record);\n return written.ok ? 0 : 1;\n}\n","import type { Command } from \"commander\";\n\nimport { compactRetrieveCommand, compactStoreCommand } from \"@/commands/compact\";\nimport type { Domain } from \"@/domains/types\";\n\nexport const COMPACT_CLI = {\n commandName: \"compact\",\n storeCommandName: \"store\",\n retrieveCommandName: \"retrieve\",\n description: \"Store and retrieve compact resume state\",\n transcriptFlag: \"--transcript\",\n transcriptOption: \"--transcript <path>\",\n sessionIdFlag: \"--session-id\",\n sessionIdOption: \"--session-id <id>\",\n sessionIdDescription: \"Agent session identity (overrides the agent-session environment)\",\n} as const;\n\ninterface CompactStoreCliOptions {\n readonly transcript: string;\n readonly sessionId?: string;\n}\n\ninterface CompactRetrieveCliOptions {\n readonly sessionId?: string;\n}\n\nexport const compactDomain: Domain = {\n name: COMPACT_CLI.commandName,\n description: COMPACT_CLI.description,\n register: (program: Command) => {\n const compactCmd = program.command(COMPACT_CLI.commandName).description(COMPACT_CLI.description);\n\n compactCmd\n .command(COMPACT_CLI.storeCommandName)\n .description(\"Store compact resume state\")\n .requiredOption(COMPACT_CLI.transcriptOption, \"Transcript JSONL path\")\n .option(COMPACT_CLI.sessionIdOption, COMPACT_CLI.sessionIdDescription)\n .action(async (options: CompactStoreCliOptions) => {\n process.exit(\n await compactStoreCommand({\n transcript: options.transcript,\n sessionId: options.sessionId,\n cwd: process.cwd(),\n env: process.env,\n }),\n );\n });\n\n compactCmd\n .command(COMPACT_CLI.retrieveCommandName)\n .description(\"Retrieve compact resume state\")\n .option(COMPACT_CLI.sessionIdOption, COMPACT_CLI.sessionIdDescription)\n .action(async (options: CompactRetrieveCliOptions) => {\n const result = await compactRetrieveCommand({\n sessionId: options.sessionId,\n cwd: process.cwd(),\n env: process.env,\n });\n if (result.output.length > 0) {\n process.stdout.write(result.output);\n }\n process.exitCode = result.exitCode;\n });\n },\n};\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { parse as parseToml, stringify as stringifyToml } from \"smol-toml\";\nimport { parse as parseYaml, parseDocument as parseYamlDocument, stringify as stringifyYaml } from \"yaml\";\n\nimport { productionRegistry } from \"./registry\";\nimport type { Config, ConfigDescriptor, Result } from \"./types\";\n\nexport const CONFIG_FILE_FORMAT = {\n JSON: \"json\",\n YAML: \"yaml\",\n TOML: \"toml\",\n} as const;\n\nexport type ConfigFileFormat = (typeof CONFIG_FILE_FORMAT)[keyof typeof CONFIG_FILE_FORMAT];\n\nexport const CONFIG_FILE_DEFINITIONS = {\n [CONFIG_FILE_FORMAT.JSON]: {\n format: CONFIG_FILE_FORMAT.JSON,\n filename: \"spx.config.json\",\n },\n [CONFIG_FILE_FORMAT.YAML]: {\n format: CONFIG_FILE_FORMAT.YAML,\n filename: \"spx.config.yaml\",\n },\n [CONFIG_FILE_FORMAT.TOML]: {\n format: CONFIG_FILE_FORMAT.TOML,\n filename: \"spx.config.toml\",\n },\n} as const;\n\nexport const CONFIG_FILE_FORMAT_ORDER = [\n CONFIG_FILE_FORMAT.JSON,\n CONFIG_FILE_FORMAT.YAML,\n CONFIG_FILE_FORMAT.TOML,\n] as const;\n\nexport const DEFAULT_CONFIG_FILE_FORMAT = CONFIG_FILE_FORMAT.YAML;\n\nexport const CONFIG_FILENAMES = {\n json: CONFIG_FILE_DEFINITIONS[CONFIG_FILE_FORMAT.JSON].filename,\n yaml: CONFIG_FILE_DEFINITIONS[CONFIG_FILE_FORMAT.YAML].filename,\n toml: CONFIG_FILE_DEFINITIONS[CONFIG_FILE_FORMAT.TOML].filename,\n} as const;\n\nexport type ConfigFilename = (typeof CONFIG_FILENAMES)[keyof typeof CONFIG_FILENAMES];\n\nexport const DEFAULT_CONFIG_FILENAME = CONFIG_FILE_DEFINITIONS[DEFAULT_CONFIG_FILE_FORMAT].filename;\n\nexport type ConfigFile = {\n readonly filename: ConfigFilename;\n readonly format: ConfigFileFormat;\n readonly path: string;\n readonly raw: string;\n};\n\nexport type ConfigFileReadResult =\n | { readonly kind: \"ok\"; readonly file: ConfigFile }\n | { readonly kind: \"ambiguous\"; readonly detected: readonly ConfigFilename[] }\n | { readonly kind: \"absent\" };\n\nconst JSON_INDENT = 2;\n\nexport async function resolveConfig(\n productDir: string,\n descriptors: readonly ConfigDescriptor<unknown>[] = productionRegistry,\n): Promise<Result<Config>> {\n const detectedResult = await readProductConfigFile(productDir);\n if (!detectedResult.ok) return detectedResult;\n\n return resolveConfigFromReadResult(detectedResult.value, descriptors);\n}\n\nexport function resolveConfigFromReadResult(\n detected: ConfigFileReadResult,\n descriptors: readonly ConfigDescriptor<unknown>[] = productionRegistry,\n): Result<Config> {\n if (detected.kind === \"ambiguous\") {\n return { ok: false, error: formatConfigFileAmbiguityError(detected.detected) };\n }\n\n const sectionsResult = detected.kind === \"absent\"\n ? ({ ok: true as const, value: {} as Record<string, unknown> })\n : parseConfigFileSections(detected.file);\n if (!sectionsResult.ok) {\n return sectionsResult;\n }\n const sections = sectionsResult.value;\n\n const resolved: Record<string, unknown> = {};\n for (const descriptor of descriptors) {\n const sectionValue = sections[descriptor.section];\n if (sectionValue === undefined) {\n resolved[descriptor.section] = descriptor.defaults;\n continue;\n }\n const validated = descriptor.validate(sectionValue);\n if (!validated.ok) {\n return { ok: false, error: `${descriptor.section}: ${validated.error}` };\n }\n resolved[descriptor.section] = validated.value;\n }\n\n return { ok: true, value: resolved };\n}\n\nexport async function readProductConfigFile(productDir: string): Promise<Result<ConfigFileReadResult>> {\n const detected: ConfigFile[] = [];\n for (const format of CONFIG_FILE_FORMAT_ORDER) {\n const filename = CONFIG_FILE_DEFINITIONS[format].filename;\n const path = join(productDir, filename);\n let raw: string;\n try {\n raw = await readFile(path, \"utf8\");\n } catch (error) {\n if (isFileNotFound(error)) continue;\n return { ok: false, error: `failed to read ${filename}: ${toMessage(error)}` };\n }\n detected.push({ filename, format, path, raw });\n }\n if (detected.length === 0) return { ok: true, value: { kind: \"absent\" } };\n if (detected.length > 1) {\n return {\n ok: true,\n value: {\n kind: \"ambiguous\",\n detected: detected.map((file) => file.filename),\n },\n };\n }\n return { ok: true, value: { kind: \"ok\", file: detected[0] } };\n}\n\nexport function configFileForFormat(\n productDir: string,\n format: ConfigFileFormat = DEFAULT_CONFIG_FILE_FORMAT,\n raw = \"\",\n): ConfigFile {\n const filename = CONFIG_FILE_DEFINITIONS[format].filename;\n return {\n filename,\n format,\n path: join(productDir, filename),\n raw,\n };\n}\n\nexport function formatConfigFileAmbiguityError(detected: readonly ConfigFilename[]): string {\n return `multiple config files found: ${detected.join(\", \")}`;\n}\n\nexport function parseConfigFileSections(file: ConfigFile): Result<Record<string, unknown>> {\n if (file.raw.trim() === \"\") return { ok: true, value: {} };\n switch (file.format) {\n case CONFIG_FILE_FORMAT.JSON:\n return parseJsonSections(file.filename, file.raw);\n case CONFIG_FILE_FORMAT.YAML:\n return parseYamlSections(file.filename, file.raw);\n case CONFIG_FILE_FORMAT.TOML:\n return parseTomlSections(file.filename, file.raw);\n }\n}\n\nexport function serializeConfigFileSections(\n format: ConfigFileFormat,\n sections: Record<string, unknown>,\n): Result<string> {\n switch (format) {\n case CONFIG_FILE_FORMAT.JSON:\n return { ok: true, value: JSON.stringify(sections, null, JSON_INDENT) + \"\\n\" };\n case CONFIG_FILE_FORMAT.YAML:\n return { ok: true, value: stringifyYaml(sections) };\n case CONFIG_FILE_FORMAT.TOML:\n return serializeTomlSections(sections);\n }\n}\n\nexport function serializeConfigFileSectionsWithSetIn(\n file: ConfigFile,\n path: readonly string[],\n value: unknown,\n): Result<string> {\n if (path.length === 0) {\n return { ok: false, error: \"config mutation path must not be empty\" };\n }\n switch (file.format) {\n case CONFIG_FILE_FORMAT.YAML:\n return serializeYamlSectionsWithSetIn(file, path, value);\n case CONFIG_FILE_FORMAT.JSON:\n case CONFIG_FILE_FORMAT.TOML: {\n const sections = parseConfigFileSections(file);\n if (!sections.ok) return sections;\n setNested(sections.value, path, value);\n return serializeConfigFileSections(file.format, sections.value);\n }\n }\n}\n\nfunction parseJsonSections(filename: string, raw: string): Result<Record<string, unknown>> {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw) as unknown;\n } catch (error) {\n return { ok: false, error: `${filename} is not valid ${CONFIG_FILE_FORMAT.JSON}: ${toMessage(error)}` };\n }\n return validateParsedSections(filename, parsed);\n}\n\nfunction parseYamlSections(filename: string, raw: string): Result<Record<string, unknown>> {\n let parsed: unknown;\n try {\n parsed = parseYaml(raw) as unknown;\n } catch (error) {\n return { ok: false, error: `${filename} is not valid ${CONFIG_FILE_FORMAT.YAML}: ${toMessage(error)}` };\n }\n if (parsed === null || parsed === undefined) {\n return { ok: true, value: {} };\n }\n return validateParsedSections(filename, parsed);\n}\n\nfunction parseTomlSections(filename: string, raw: string): Result<Record<string, unknown>> {\n let parsed: unknown;\n try {\n parsed = parseToml(raw) as unknown;\n } catch (error) {\n return { ok: false, error: `${filename} is not valid ${CONFIG_FILE_FORMAT.TOML}: ${toMessage(error)}` };\n }\n return validateParsedSections(filename, parsed);\n}\n\nfunction serializeTomlSections(sections: Record<string, unknown>): Result<string> {\n try {\n return { ok: true, value: stringifyToml(sections) };\n } catch (error) {\n return {\n ok: false,\n error: `config is not serializable as ${CONFIG_FILE_FORMAT.TOML}: ${toMessage(error)}`,\n };\n }\n}\n\nfunction serializeYamlSectionsWithSetIn(\n file: ConfigFile,\n path: readonly string[],\n value: unknown,\n): Result<string> {\n try {\n const doc = parseYamlDocument(file.raw.trim() === \"\" ? \"{}\\n\" : file.raw);\n if (doc.errors.length > 0) {\n return {\n ok: false,\n error: `${file.filename} is not valid ${CONFIG_FILE_FORMAT.YAML}: ${doc.errors[0].message}`,\n };\n }\n doc.setIn([...path], value);\n return { ok: true, value: String(doc) };\n } catch (error) {\n return { ok: false, error: `${file.filename} is not valid ${CONFIG_FILE_FORMAT.YAML}: ${toMessage(error)}` };\n }\n}\n\nfunction setNested(target: Record<string, unknown>, path: readonly string[], value: unknown): void {\n let cursor: Record<string, unknown> = target;\n for (let i = 0; i < path.length - 1; i += 1) {\n const key = path[i];\n const existing = cursor[key];\n if (typeof existing === \"object\" && existing !== null && !Array.isArray(existing)) {\n cursor = existing as Record<string, unknown>;\n } else {\n const fresh: Record<string, unknown> = {};\n cursor[key] = fresh;\n cursor = fresh;\n }\n }\n cursor[path[path.length - 1]] = value;\n}\n\nfunction validateParsedSections(filename: string, parsed: unknown): Result<Record<string, unknown>> {\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n return { ok: false, error: `${filename} must parse to a mapping of descriptor sections` };\n }\n return { ok: true, value: parsed as Record<string, unknown> };\n}\n\nfunction isFileNotFound(error: unknown): boolean {\n return error instanceof Error && \"code\" in error && (error as NodeJS.ErrnoException).code === \"ENOENT\";\n}\n\nfunction toMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nexport {\n canonicalDescriptorJson,\n type DescriptorJsonValue,\n type DescriptorSectionDigest,\n digestDescriptorSection,\n} from \"./descriptor-digest\";\n","import type { ConfigDescriptor, Result } from \"@/config/types\";\n\nexport const AGENT_ENVIRONMENT_SECTION = \"agentEnvironment\";\n\nexport const AGENT_RUNTIME = {\n CODEX: \"codex\",\n CLAUDE_CODE: \"claudeCode\",\n} as const;\n\nexport type AgentRuntime = (typeof AGENT_RUNTIME)[keyof typeof AGENT_RUNTIME];\n\nexport const AGENT_ENVIRONMENT_CONFIG_FIELDS = {\n INSTRUCTIONS: \"instructions\",\n RUNTIMES: \"runtimes\",\n PLUGIN_BOOTSTRAP: \"pluginBootstrap\",\n FILES: \"files\",\n PATH: \"path\",\n TARGET_RUNTIMES: \"targetRuntimes\",\n ENABLED: \"enabled\",\n MARKETPLACES: \"marketplaces\",\n PLUGINS: \"plugins\",\n SKILLS: \"skills\",\n RUNTIME: \"runtime\",\n NAME: \"name\",\n SOURCE: \"source\",\n VERSION: \"version\",\n MARKETPLACE: \"marketplace\",\n} as const;\n\nexport interface AgentInstructionFileConfig {\n readonly path: string;\n readonly targetRuntimes: readonly AgentRuntime[];\n}\n\nexport interface AgentRuntimeConfig {\n readonly enabled: boolean;\n}\n\nexport interface AgentMarketplaceConfig {\n readonly runtime: AgentRuntime;\n readonly name: string;\n readonly source: string;\n}\n\nexport interface AgentPluginConfig {\n readonly runtime: AgentRuntime;\n readonly name: string;\n readonly marketplace?: string;\n readonly version?: string;\n}\n\nexport interface AgentSkillConfig {\n readonly runtime: AgentRuntime;\n readonly name: string;\n readonly source?: string;\n readonly version?: string;\n}\n\nexport interface AgentEnvironmentConfig {\n readonly instructions: {\n readonly files: readonly AgentInstructionFileConfig[];\n };\n readonly runtimes: { readonly [K in AgentRuntime]: AgentRuntimeConfig };\n readonly pluginBootstrap: {\n readonly marketplaces: readonly AgentMarketplaceConfig[];\n readonly plugins: readonly AgentPluginConfig[];\n readonly skills: readonly AgentSkillConfig[];\n };\n}\n\nconst AGENT_RUNTIME_SET: ReadonlySet<string> = new Set(Object.values(AGENT_RUNTIME));\nconst DEFAULT_AGENT_INSTRUCTION_TARGET_RUNTIMES = [\n AGENT_RUNTIME.CODEX,\n AGENT_RUNTIME.CLAUDE_CODE,\n] as const satisfies readonly AgentRuntime[];\n\nexport const DEFAULT_AGENT_INSTRUCTION_FILE_PATH = \"AGENTS.md\";\n\nexport const DEFAULT_AGENT_ENVIRONMENT_CONFIG: AgentEnvironmentConfig = {\n instructions: {\n files: [\n {\n path: DEFAULT_AGENT_INSTRUCTION_FILE_PATH,\n targetRuntimes: DEFAULT_AGENT_INSTRUCTION_TARGET_RUNTIMES,\n },\n ],\n },\n runtimes: {\n [AGENT_RUNTIME.CODEX]: { enabled: true },\n [AGENT_RUNTIME.CLAUDE_CODE]: { enabled: true },\n },\n pluginBootstrap: {\n marketplaces: [],\n plugins: [],\n skills: [],\n },\n};\n\nconst AGENT_ENVIRONMENT_ALLOWED_FIELDS = new Set([\n AGENT_ENVIRONMENT_CONFIG_FIELDS.INSTRUCTIONS,\n AGENT_ENVIRONMENT_CONFIG_FIELDS.RUNTIMES,\n AGENT_ENVIRONMENT_CONFIG_FIELDS.PLUGIN_BOOTSTRAP,\n]);\n\nconst AGENT_ENVIRONMENT_INSTRUCTIONS_ALLOWED_FIELDS = new Set([\n AGENT_ENVIRONMENT_CONFIG_FIELDS.FILES,\n]);\n\nconst AGENT_ENVIRONMENT_INSTRUCTION_FILE_ALLOWED_FIELDS = new Set([\n AGENT_ENVIRONMENT_CONFIG_FIELDS.PATH,\n AGENT_ENVIRONMENT_CONFIG_FIELDS.TARGET_RUNTIMES,\n]);\n\nconst AGENT_ENVIRONMENT_RUNTIME_CONFIG_ALLOWED_FIELDS = new Set([\n AGENT_ENVIRONMENT_CONFIG_FIELDS.ENABLED,\n]);\n\nconst AGENT_ENVIRONMENT_PLUGIN_BOOTSTRAP_ALLOWED_FIELDS = new Set([\n AGENT_ENVIRONMENT_CONFIG_FIELDS.MARKETPLACES,\n AGENT_ENVIRONMENT_CONFIG_FIELDS.PLUGINS,\n AGENT_ENVIRONMENT_CONFIG_FIELDS.SKILLS,\n]);\n\nconst AGENT_ENVIRONMENT_MARKETPLACE_ALLOWED_FIELDS = new Set([\n AGENT_ENVIRONMENT_CONFIG_FIELDS.RUNTIME,\n AGENT_ENVIRONMENT_CONFIG_FIELDS.NAME,\n AGENT_ENVIRONMENT_CONFIG_FIELDS.SOURCE,\n]);\n\nconst AGENT_ENVIRONMENT_PLUGIN_ALLOWED_FIELDS = new Set([\n AGENT_ENVIRONMENT_CONFIG_FIELDS.RUNTIME,\n AGENT_ENVIRONMENT_CONFIG_FIELDS.NAME,\n AGENT_ENVIRONMENT_CONFIG_FIELDS.MARKETPLACE,\n AGENT_ENVIRONMENT_CONFIG_FIELDS.VERSION,\n]);\n\nconst AGENT_ENVIRONMENT_SKILL_ALLOWED_FIELDS = new Set([\n AGENT_ENVIRONMENT_CONFIG_FIELDS.RUNTIME,\n AGENT_ENVIRONMENT_CONFIG_FIELDS.NAME,\n AGENT_ENVIRONMENT_CONFIG_FIELDS.SOURCE,\n AGENT_ENVIRONMENT_CONFIG_FIELDS.VERSION,\n]);\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction rejectUnknownFields(\n path: string,\n value: Record<string, unknown>,\n allowed: ReadonlySet<string>,\n): Result<undefined> {\n const unknownFields = Object.keys(value).filter((field) => !allowed.has(field));\n if (unknownFields.length === 1) {\n return { ok: false, error: `${path}.${unknownFields[0]} is not a recognized config field` };\n }\n if (unknownFields.length > 1) {\n return { ok: false, error: `${path} has unrecognized config fields: ${unknownFields.join(\", \")}` };\n }\n return { ok: true, value: undefined };\n}\n\nfunction validateNonEmptyString(path: string, value: unknown): Result<string> {\n if (typeof value !== \"string\" || value.length === 0) {\n return { ok: false, error: `${path} must be a non-empty string` };\n }\n return { ok: true, value };\n}\n\nfunction validateBoolean(path: string, value: unknown): Result<boolean> {\n if (typeof value !== \"boolean\") {\n return { ok: false, error: `${path} must be a boolean` };\n }\n return { ok: true, value };\n}\n\nfunction validateRuntime(path: string, value: unknown): Result<AgentRuntime> {\n if (typeof value !== \"string\" || !isAgentRuntime(value)) {\n return { ok: false, error: `${path} must be a registered agent runtime` };\n }\n return { ok: true, value };\n}\n\nfunction isAgentRuntime(value: string): value is AgentRuntime {\n return AGENT_RUNTIME_SET.has(value);\n}\n\nfunction validateRuntimeArray(path: string, value: unknown): Result<readonly AgentRuntime[]> {\n if (!Array.isArray(value) || value.length === 0) {\n return { ok: false, error: `${path} must be a non-empty array of registered agent runtimes` };\n }\n\n const runtimes: AgentRuntime[] = [];\n const seen = new Set<AgentRuntime>();\n for (const [index, entry] of value.entries()) {\n const runtime = validateRuntime(`${path}.${index}`, entry);\n if (!runtime.ok) return runtime;\n if (seen.has(runtime.value)) {\n return { ok: false, error: `${path}.${index} repeats registered agent runtime ${runtime.value}` };\n }\n seen.add(runtime.value);\n runtimes.push(runtime.value);\n }\n return { ok: true, value: runtimes };\n}\n\nfunction validateInstructions(raw: unknown): Result<AgentEnvironmentConfig[\"instructions\"]> {\n const sectionPath = `${AGENT_ENVIRONMENT_SECTION}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.INSTRUCTIONS}`;\n if (!isRecord(raw)) {\n return { ok: false, error: `${sectionPath} must be an object` };\n }\n\n const unknown = rejectUnknownFields(sectionPath, raw, AGENT_ENVIRONMENT_INSTRUCTIONS_ALLOWED_FIELDS);\n if (!unknown.ok) return unknown;\n\n const filesRaw = raw[AGENT_ENVIRONMENT_CONFIG_FIELDS.FILES];\n if (filesRaw === undefined) return { ok: true, value: DEFAULT_AGENT_ENVIRONMENT_CONFIG.instructions };\n if (!Array.isArray(filesRaw)) {\n return { ok: false, error: `${sectionPath}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.FILES} must be an array` };\n }\n\n const files: AgentInstructionFileConfig[] = [];\n for (const [index, entry] of filesRaw.entries()) {\n const file = validateInstructionFile(`${sectionPath}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.FILES}.${index}`, entry);\n if (!file.ok) return file;\n files.push(file.value);\n }\n const filePathUniqueness = validateInstructionFilePathUniqueness(\n `${sectionPath}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.FILES}`,\n files,\n );\n if (!filePathUniqueness.ok) return filePathUniqueness;\n return { ok: true, value: { files } };\n}\n\nfunction validateInstructionFile(path: string, raw: unknown): Result<AgentInstructionFileConfig> {\n if (!isRecord(raw)) return { ok: false, error: `${path} must be an object` };\n const unknown = rejectUnknownFields(\n path,\n raw,\n AGENT_ENVIRONMENT_INSTRUCTION_FILE_ALLOWED_FIELDS,\n );\n if (!unknown.ok) return unknown;\n\n const filePath = validateNonEmptyString(\n `${path}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.PATH}`,\n raw[AGENT_ENVIRONMENT_CONFIG_FIELDS.PATH],\n );\n if (!filePath.ok) return filePath;\n\n const targetRuntimes = validateRuntimeArray(\n `${path}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.TARGET_RUNTIMES}`,\n raw[AGENT_ENVIRONMENT_CONFIG_FIELDS.TARGET_RUNTIMES],\n );\n if (!targetRuntimes.ok) return targetRuntimes;\n\n return { ok: true, value: { path: filePath.value, targetRuntimes: targetRuntimes.value } };\n}\n\nfunction validateRuntimes(raw: unknown): Result<AgentEnvironmentConfig[\"runtimes\"]> {\n const sectionPath = `${AGENT_ENVIRONMENT_SECTION}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.RUNTIMES}`;\n if (!isRecord(raw)) {\n return { ok: false, error: `${sectionPath} must be an object` };\n }\n\n const runtimes: Record<AgentRuntime, AgentRuntimeConfig> = { ...DEFAULT_AGENT_ENVIRONMENT_CONFIG.runtimes };\n for (const [runtimeName, runtimeRaw] of Object.entries(raw)) {\n // Runtime ids are the field names, so unknown-field rejection is the runtime-id validation below.\n const runtime = validateRuntime(`${sectionPath}.${runtimeName}`, runtimeName);\n if (!runtime.ok) return runtime;\n const config = validateRuntimeConfig(`${sectionPath}.${runtimeName}`, runtimeRaw, runtimes[runtime.value]);\n if (!config.ok) return config;\n runtimes[runtime.value] = config.value;\n }\n\n return { ok: true, value: runtimes };\n}\n\nfunction validateRuntimeConfig(\n path: string,\n raw: unknown,\n defaults: AgentRuntimeConfig,\n): Result<AgentRuntimeConfig> {\n if (!isRecord(raw)) return { ok: false, error: `${path} must be an object` };\n const unknown = rejectUnknownFields(path, raw, AGENT_ENVIRONMENT_RUNTIME_CONFIG_ALLOWED_FIELDS);\n if (!unknown.ok) return unknown;\n\n const enabledRaw = raw[AGENT_ENVIRONMENT_CONFIG_FIELDS.ENABLED];\n if (enabledRaw === undefined) return { ok: true, value: defaults };\n const enabled = validateBoolean(`${path}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.ENABLED}`, enabledRaw);\n if (!enabled.ok) return enabled;\n return { ok: true, value: { ...defaults, enabled: enabled.value } };\n}\n\nfunction validatePluginBootstrap(raw: unknown): Result<AgentEnvironmentConfig[\"pluginBootstrap\"]> {\n const sectionPath = `${AGENT_ENVIRONMENT_SECTION}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.PLUGIN_BOOTSTRAP}`;\n if (!isRecord(raw)) {\n return { ok: false, error: `${sectionPath} must be an object` };\n }\n\n const unknown = rejectUnknownFields(\n sectionPath,\n raw,\n AGENT_ENVIRONMENT_PLUGIN_BOOTSTRAP_ALLOWED_FIELDS,\n );\n if (!unknown.ok) return unknown;\n\n const marketplaces = validateEntryArray(\n `${sectionPath}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.MARKETPLACES}`,\n raw[AGENT_ENVIRONMENT_CONFIG_FIELDS.MARKETPLACES],\n validateMarketplace,\n DEFAULT_AGENT_ENVIRONMENT_CONFIG.pluginBootstrap.marketplaces,\n );\n if (!marketplaces.ok) return marketplaces;\n\n const marketplaceUniqueness = validateNamedRuntimeEntryUniqueness(\n `${sectionPath}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.MARKETPLACES}`,\n marketplaces.value,\n );\n if (!marketplaceUniqueness.ok) return marketplaceUniqueness;\n\n const plugins = validateEntryArray(\n `${sectionPath}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.PLUGINS}`,\n raw[AGENT_ENVIRONMENT_CONFIG_FIELDS.PLUGINS],\n validatePlugin,\n DEFAULT_AGENT_ENVIRONMENT_CONFIG.pluginBootstrap.plugins,\n );\n if (!plugins.ok) return plugins;\n\n const pluginUniqueness = validateNamedRuntimeEntryUniqueness(\n `${sectionPath}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.PLUGINS}`,\n plugins.value,\n );\n if (!pluginUniqueness.ok) return pluginUniqueness;\n\n const pluginMarketplaceReferences = validatePluginMarketplaceReferences(\n sectionPath,\n marketplaces.value,\n plugins.value,\n );\n if (!pluginMarketplaceReferences.ok) return pluginMarketplaceReferences;\n\n const skills = validateEntryArray(\n `${sectionPath}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.SKILLS}`,\n raw[AGENT_ENVIRONMENT_CONFIG_FIELDS.SKILLS],\n validateSkill,\n DEFAULT_AGENT_ENVIRONMENT_CONFIG.pluginBootstrap.skills,\n );\n if (!skills.ok) return skills;\n\n const skillUniqueness = validateNamedRuntimeEntryUniqueness(\n `${sectionPath}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.SKILLS}`,\n skills.value,\n );\n if (!skillUniqueness.ok) return skillUniqueness;\n\n return {\n ok: true,\n value: {\n marketplaces: marketplaces.value,\n plugins: plugins.value,\n skills: skills.value,\n },\n };\n}\n\nfunction validateEntryArray<T>(\n path: string,\n raw: unknown,\n validateEntry: (path: string, raw: unknown) => Result<T>,\n defaults: readonly T[],\n): Result<readonly T[]> {\n if (raw === undefined) return { ok: true, value: defaults };\n if (!Array.isArray(raw)) return { ok: false, error: `${path} must be an array` };\n\n const entries: T[] = [];\n for (const [index, entry] of raw.entries()) {\n const result = validateEntry(`${path}.${index}`, entry);\n if (!result.ok) return result;\n entries.push(result.value);\n }\n return { ok: true, value: entries };\n}\n\nfunction validateInstructionFilePathUniqueness(\n path: string,\n files: readonly AgentInstructionFileConfig[],\n): Result<undefined> {\n const paths = new Set<string>();\n for (const [index, file] of files.entries()) {\n if (paths.has(file.path)) {\n return {\n ok: false,\n error: `${path}.${index}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.PATH} ${\n JSON.stringify(file.path)\n } is already used by another instruction file entry`,\n };\n }\n paths.add(file.path);\n }\n return { ok: true, value: undefined };\n}\n\nfunction validateNamedRuntimeEntryUniqueness(\n path: string,\n entries: readonly { readonly runtime: AgentRuntime; readonly name: string }[],\n): Result<undefined> {\n const namesByRuntime = new Map<AgentRuntime, Set<string>>();\n for (const [index, entry] of entries.entries()) {\n const runtimeNames = namesByRuntime.get(entry.runtime) ?? new Set<string>();\n if (runtimeNames.has(entry.name)) {\n return {\n ok: false,\n error: `${path}.${index}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.NAME} ${\n JSON.stringify(entry.name)\n } is already used by another ${entry.runtime} entry`,\n };\n }\n runtimeNames.add(entry.name);\n namesByRuntime.set(entry.runtime, runtimeNames);\n }\n return { ok: true, value: undefined };\n}\n\nfunction validatePluginMarketplaceReferences(\n path: string,\n marketplaces: readonly AgentMarketplaceConfig[],\n plugins: readonly AgentPluginConfig[],\n): Result<undefined> {\n const marketplacesByRuntime = new Map<AgentRuntime, Set<string>>();\n for (const marketplace of marketplaces) {\n const runtimeMarketplaces = marketplacesByRuntime.get(marketplace.runtime) ?? new Set<string>();\n runtimeMarketplaces.add(marketplace.name);\n marketplacesByRuntime.set(marketplace.runtime, runtimeMarketplaces);\n }\n\n for (const [index, plugin] of plugins.entries()) {\n if (plugin.marketplace === undefined) continue;\n const runtimeMarketplaces = marketplacesByRuntime.get(plugin.runtime);\n if (!runtimeMarketplaces?.has(plugin.marketplace)) {\n return {\n ok: false,\n error:\n `${path}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.PLUGINS}.${index}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.MARKETPLACE} must reference a configured marketplace for the same runtime`,\n };\n }\n }\n\n return { ok: true, value: undefined };\n}\n\nfunction validateMarketplace(path: string, raw: unknown): Result<AgentMarketplaceConfig> {\n if (!isRecord(raw)) return { ok: false, error: `${path} must be an object` };\n const unknown = rejectUnknownFields(\n path,\n raw,\n AGENT_ENVIRONMENT_MARKETPLACE_ALLOWED_FIELDS,\n );\n if (!unknown.ok) return unknown;\n\n const base = validateNamedRuntimeEntry(path, raw);\n if (!base.ok) return base;\n const source = validateNonEmptyString(\n `${path}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.SOURCE}`,\n raw[AGENT_ENVIRONMENT_CONFIG_FIELDS.SOURCE],\n );\n if (!source.ok) return source;\n return { ok: true, value: { ...base.value, source: source.value } };\n}\n\nfunction validatePlugin(path: string, raw: unknown): Result<AgentPluginConfig> {\n if (!isRecord(raw)) return { ok: false, error: `${path} must be an object` };\n const unknown = rejectUnknownFields(\n path,\n raw,\n AGENT_ENVIRONMENT_PLUGIN_ALLOWED_FIELDS,\n );\n if (!unknown.ok) return unknown;\n\n const base = validateNamedRuntimeEntry(path, raw);\n if (!base.ok) return base;\n const marketplace = validateOptionalString(\n `${path}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.MARKETPLACE}`,\n raw[AGENT_ENVIRONMENT_CONFIG_FIELDS.MARKETPLACE],\n );\n if (!marketplace.ok) return marketplace;\n const version = validateOptionalString(\n `${path}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.VERSION}`,\n raw[AGENT_ENVIRONMENT_CONFIG_FIELDS.VERSION],\n );\n if (!version.ok) return version;\n return {\n ok: true,\n value: {\n ...base.value,\n ...(marketplace.value === undefined ? {} : { marketplace: marketplace.value }),\n ...(version.value === undefined ? {} : { version: version.value }),\n },\n };\n}\n\nfunction validateSkill(path: string, raw: unknown): Result<AgentSkillConfig> {\n if (!isRecord(raw)) return { ok: false, error: `${path} must be an object` };\n const unknown = rejectUnknownFields(\n path,\n raw,\n AGENT_ENVIRONMENT_SKILL_ALLOWED_FIELDS,\n );\n if (!unknown.ok) return unknown;\n\n const base = validateNamedRuntimeEntry(path, raw);\n if (!base.ok) return base;\n const source = validateOptionalString(\n `${path}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.SOURCE}`,\n raw[AGENT_ENVIRONMENT_CONFIG_FIELDS.SOURCE],\n );\n if (!source.ok) return source;\n const version = validateOptionalString(\n `${path}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.VERSION}`,\n raw[AGENT_ENVIRONMENT_CONFIG_FIELDS.VERSION],\n );\n if (!version.ok) return version;\n return {\n ok: true,\n value: {\n ...base.value,\n ...(source.value === undefined ? {} : { source: source.value }),\n ...(version.value === undefined ? {} : { version: version.value }),\n },\n };\n}\n\nfunction validateNamedRuntimeEntry(\n path: string,\n raw: Record<string, unknown>,\n): Result<{ readonly runtime: AgentRuntime; readonly name: string }> {\n const runtime = validateRuntime(\n `${path}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.RUNTIME}`,\n raw[AGENT_ENVIRONMENT_CONFIG_FIELDS.RUNTIME],\n );\n if (!runtime.ok) return runtime;\n const name = validateNonEmptyString(\n `${path}.${AGENT_ENVIRONMENT_CONFIG_FIELDS.NAME}`,\n raw[AGENT_ENVIRONMENT_CONFIG_FIELDS.NAME],\n );\n if (!name.ok) return name;\n return { ok: true, value: { runtime: runtime.value, name: name.value } };\n}\n\nfunction validateOptionalString(path: string, value: unknown): Result<string | undefined> {\n if (value === undefined) return { ok: true, value: undefined };\n return validateNonEmptyString(path, value);\n}\n\nfunction validate(value: unknown): Result<AgentEnvironmentConfig> {\n if (!isRecord(value)) {\n return { ok: false, error: `${AGENT_ENVIRONMENT_SECTION} section must be an object` };\n }\n\n const unknown = rejectUnknownFields(\n AGENT_ENVIRONMENT_SECTION,\n value,\n AGENT_ENVIRONMENT_ALLOWED_FIELDS,\n );\n if (!unknown.ok) return unknown;\n\n const instructionsRaw = value[AGENT_ENVIRONMENT_CONFIG_FIELDS.INSTRUCTIONS];\n const instructions = instructionsRaw === undefined\n ? { ok: true as const, value: DEFAULT_AGENT_ENVIRONMENT_CONFIG.instructions }\n : validateInstructions(instructionsRaw);\n if (!instructions.ok) return instructions;\n\n const runtimesRaw = value[AGENT_ENVIRONMENT_CONFIG_FIELDS.RUNTIMES];\n const runtimes = runtimesRaw === undefined\n ? { ok: true as const, value: DEFAULT_AGENT_ENVIRONMENT_CONFIG.runtimes }\n : validateRuntimes(runtimesRaw);\n if (!runtimes.ok) return runtimes;\n\n const pluginBootstrapRaw = value[AGENT_ENVIRONMENT_CONFIG_FIELDS.PLUGIN_BOOTSTRAP];\n const pluginBootstrap = pluginBootstrapRaw === undefined\n ? { ok: true as const, value: DEFAULT_AGENT_ENVIRONMENT_CONFIG.pluginBootstrap }\n : validatePluginBootstrap(pluginBootstrapRaw);\n if (!pluginBootstrap.ok) return pluginBootstrap;\n\n return {\n ok: true,\n value: {\n instructions: instructions.value,\n runtimes: runtimes.value,\n pluginBootstrap: pluginBootstrap.value,\n },\n };\n}\n\nexport const agentEnvironmentConfigDescriptor: ConfigDescriptor<AgentEnvironmentConfig> = {\n section: AGENT_ENVIRONMENT_SECTION,\n defaults: DEFAULT_AGENT_ENVIRONMENT_CONFIG,\n validate,\n};\n","import type { Result } from \"@/config/types\";\n\nexport const PATH_FILTER_CONFIG_FIELDS = {\n INCLUDE: \"include\",\n EXCLUDE: \"exclude\",\n} as const;\n\nexport interface PathFilterConfig {\n readonly include?: readonly string[];\n readonly exclude?: readonly string[];\n}\n\nexport function validatePathFilterConfig(raw: unknown, path: string): Result<PathFilterConfig> {\n if (typeof raw !== \"object\" || raw === null || Array.isArray(raw)) {\n return {\n ok: false,\n error: `${path} must be an object`,\n };\n }\n const candidate = raw as Record<string, unknown>;\n\n const include = candidate[PATH_FILTER_CONFIG_FIELDS.INCLUDE];\n if (\n include !== undefined\n && (!Array.isArray(include) || !include.every((value) => typeof value === \"string\"))\n ) {\n return {\n ok: false,\n error: `${path}.${PATH_FILTER_CONFIG_FIELDS.INCLUDE} must be an array of strings`,\n };\n }\n\n const exclude = candidate[PATH_FILTER_CONFIG_FIELDS.EXCLUDE];\n if (\n exclude !== undefined\n && (!Array.isArray(exclude) || !exclude.every((value) => typeof value === \"string\"))\n ) {\n return {\n ok: false,\n error: `${path}.${PATH_FILTER_CONFIG_FIELDS.EXCLUDE} must be an array of strings`,\n };\n }\n\n const value: {\n include?: readonly string[];\n exclude?: readonly string[];\n } = {};\n if (include !== undefined) value.include = include as readonly string[];\n if (exclude !== undefined) value.exclude = exclude as readonly string[];\n\n return { ok: true, value };\n}\n\nconst PATH_SEGMENT_SEPARATOR = \"/\";\n\nfunction normalizePathPrefix(value: string): string {\n return value.replace(/\\/+$/, \"\");\n}\n\nfunction pathMatchesPrefix(path: string, prefix: string): boolean {\n const normalizedPath = normalizePathPrefix(path);\n const normalizedPrefix = normalizePathPrefix(prefix);\n return normalizedPath === normalizedPrefix\n || normalizedPath.startsWith(`${normalizedPrefix}${PATH_SEGMENT_SEPARATOR}`);\n}\n\n/**\n * Keeps the paths a filter admits: a path survives when the include set is empty\n * or some include prefix matches it, and no exclude prefix matches it. A prefix\n * matches a path by exact equality or at a path-segment boundary, never by shared\n * leading text alone.\n */\nexport function applyPathFilter(\n paths: readonly string[],\n config: PathFilterConfig,\n): readonly string[] {\n const includePrefixes = config.include ?? [];\n const excludePrefixes = config.exclude ?? [];\n return paths.filter((path) => {\n if (includePrefixes.length > 0 && !includePrefixes.some((prefix) => pathMatchesPrefix(path, prefix))) {\n return false;\n }\n return !excludePrefixes.some((prefix) => pathMatchesPrefix(path, prefix));\n });\n}\n","import { type PathFilterConfig, validatePathFilterConfig } from \"@/config/primitives/path-filter\";\nimport type { ConfigDescriptor, Result } from \"@/config/types\";\n\nexport const AUDIT_SECTION = \"audit\";\n\nexport const AUDIT_CONFIG_FIELDS = {\n BASE_REF: \"baseRef\",\n AUDITORS: \"auditors\",\n TARGETS: \"targets\",\n} as const;\n\nexport interface AuditConfig {\n readonly baseRef: string;\n readonly auditors: readonly string[];\n readonly targets: PathFilterConfig;\n}\n\nexport const DEFAULT_AUDIT_CONFIG: AuditConfig = {\n baseRef: \"main\",\n auditors: [],\n targets: resolveDefaultTargets(),\n};\n\nconst AUDIT_ALLOWED_FIELDS = new Set<string>([\n AUDIT_CONFIG_FIELDS.BASE_REF,\n AUDIT_CONFIG_FIELDS.AUDITORS,\n AUDIT_CONFIG_FIELDS.TARGETS,\n]);\n\nexport const auditConfigDescriptor: ConfigDescriptor<AuditConfig> = {\n section: AUDIT_SECTION,\n defaults: DEFAULT_AUDIT_CONFIG,\n validate: validateAuditConfig,\n};\n\nfunction resolveDefaultTargets(): PathFilterConfig {\n const result = validatePathFilterConfig(\n {},\n `${AUDIT_SECTION}.${AUDIT_CONFIG_FIELDS.TARGETS}`,\n );\n if (!result.ok) throw new Error(result.error);\n return result.value;\n}\n\nfunction validateAuditConfig(raw: unknown): Result<AuditConfig> {\n if (!isRecord(raw)) {\n return { ok: false, error: `${AUDIT_SECTION} section must be an object` };\n }\n\n const unknown = rejectUnknownFields(AUDIT_SECTION, raw, AUDIT_ALLOWED_FIELDS);\n if (!unknown.ok) return unknown;\n\n const baseRef = raw[AUDIT_CONFIG_FIELDS.BASE_REF] === undefined\n ? { ok: true as const, value: DEFAULT_AUDIT_CONFIG.baseRef }\n : validateNonEmptyString(\n `${AUDIT_SECTION}.${AUDIT_CONFIG_FIELDS.BASE_REF}`,\n raw[AUDIT_CONFIG_FIELDS.BASE_REF],\n );\n if (!baseRef.ok) return baseRef;\n\n const auditors = raw[AUDIT_CONFIG_FIELDS.AUDITORS] === undefined\n ? { ok: true as const, value: DEFAULT_AUDIT_CONFIG.auditors }\n : validateArrayOfNonEmptyStrings(\n `${AUDIT_SECTION}.${AUDIT_CONFIG_FIELDS.AUDITORS}`,\n raw[AUDIT_CONFIG_FIELDS.AUDITORS],\n );\n if (!auditors.ok) return auditors;\n\n const targets = raw[AUDIT_CONFIG_FIELDS.TARGETS] === undefined\n ? { ok: true as const, value: DEFAULT_AUDIT_CONFIG.targets }\n : validatePathFilterConfig(\n raw[AUDIT_CONFIG_FIELDS.TARGETS],\n `${AUDIT_SECTION}.${AUDIT_CONFIG_FIELDS.TARGETS}`,\n );\n if (!targets.ok) return targets;\n\n return {\n ok: true,\n value: {\n baseRef: baseRef.value,\n auditors: auditors.value,\n targets: targets.value,\n },\n };\n}\n\nfunction validateNonEmptyString(path: string, value: unknown): Result<string> {\n if (typeof value !== \"string\" || value.length === 0) {\n return { ok: false, error: `${path} must be a non-empty string` };\n }\n return { ok: true, value };\n}\n\nfunction validateArrayOfNonEmptyStrings(path: string, value: unknown): Result<readonly string[]> {\n if (!Array.isArray(value)) {\n return { ok: false, error: `${path} must be an array of non-empty strings` };\n }\n const entries: string[] = [];\n for (const [index, entry] of value.entries()) {\n const validated = validateNonEmptyString(`${path}.${index}`, entry);\n if (!validated.ok) return validated;\n entries.push(validated.value);\n }\n return { ok: true, value: entries };\n}\n\nfunction rejectUnknownFields(\n path: string,\n value: Record<string, unknown>,\n allowed: ReadonlySet<string>,\n): Result<undefined> {\n const unknownField = Object.keys(value).find((field) => !allowed.has(field));\n if (unknownField !== undefined) {\n return { ok: false, error: `${path}.${unknownField} is not a recognized config field` };\n }\n return { ok: true, value: undefined };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import type { ConfigDescriptor, Result } from \"@/config/types\";\n\nconst SPEC_TREE_KIND_CATEGORY_VALUES = {\n NODE: \"node\",\n DECISION: \"decision\",\n} as const;\n\nconst SPEC_TREE_EMPTY_ALIASES = [] as const;\n\nexport const SPEC_TREE_CONFIG = {\n SECTION: \"specTree\",\n ROOT_DIRECTORY: \"spx\",\n PRODUCT: {\n LABEL: \"Product\",\n SUFFIX: \".product.md\",\n },\n CATEGORY: SPEC_TREE_KIND_CATEGORY_VALUES,\n KINDS: {\n enabler: {\n category: SPEC_TREE_KIND_CATEGORY_VALUES.NODE,\n label: \"Enabler\",\n suffix: \".enabler\",\n aliases: SPEC_TREE_EMPTY_ALIASES,\n },\n outcome: {\n category: SPEC_TREE_KIND_CATEGORY_VALUES.NODE,\n label: \"Outcome\",\n suffix: \".outcome\",\n aliases: SPEC_TREE_EMPTY_ALIASES,\n },\n adr: {\n category: SPEC_TREE_KIND_CATEGORY_VALUES.DECISION,\n label: \"ADR\",\n suffix: \".adr.md\",\n aliases: SPEC_TREE_EMPTY_ALIASES,\n },\n pdr: {\n category: SPEC_TREE_KIND_CATEGORY_VALUES.DECISION,\n label: \"PDR\",\n suffix: \".pdr.md\",\n aliases: SPEC_TREE_EMPTY_ALIASES,\n },\n },\n} as const;\n\nexport const SPEC_TREE_CONFIG_FIELDS = {\n KINDS: \"kinds\",\n} as const;\n\nexport const SPEC_TREE_KIND_CATEGORY = SPEC_TREE_CONFIG.CATEGORY;\n\nexport type SpecTreeKindCategory = (typeof SPEC_TREE_KIND_CATEGORY)[keyof typeof SPEC_TREE_KIND_CATEGORY];\n\nexport const KIND_REGISTRY = SPEC_TREE_CONFIG.KINDS;\n\nexport type Kind = keyof typeof KIND_REGISTRY;\nexport type KindDefinition<K extends Kind> = (typeof KIND_REGISTRY)[K];\n\nexport type NodeKind = {\n [K in Kind]: (typeof KIND_REGISTRY)[K][\"category\"] extends typeof SPEC_TREE_KIND_CATEGORY.NODE ? K : never;\n}[Kind];\n\nexport type DecisionKind = {\n [K in Kind]: (typeof KIND_REGISTRY)[K][\"category\"] extends typeof SPEC_TREE_KIND_CATEGORY.DECISION ? K : never;\n}[Kind];\n\nexport const SPEC_TREE_ADR_KIND: DecisionKind = \"adr\";\n\nexport const NODE_KINDS: readonly NodeKind[] = (Object.keys(KIND_REGISTRY) as Kind[]).filter(\n (k): k is NodeKind => KIND_REGISTRY[k].category === SPEC_TREE_KIND_CATEGORY.NODE,\n);\n\nexport const DECISION_KINDS: readonly DecisionKind[] = (Object.keys(KIND_REGISTRY) as Kind[]).filter(\n (k): k is DecisionKind => KIND_REGISTRY[k].category === SPEC_TREE_KIND_CATEGORY.DECISION,\n);\n\nexport const NODE_SUFFIXES: readonly string[] = NODE_KINDS.map((k) => KIND_REGISTRY[k].suffix);\nexport const DECISION_SUFFIXES: readonly string[] = DECISION_KINDS.map((k) => KIND_REGISTRY[k].suffix);\n\nexport const SPEC_TREE_GRAMMAR = {\n PRODUCT_SUFFIX: SPEC_TREE_CONFIG.PRODUCT.SUFFIX,\n EVIDENCE: {\n DIRECTORY_NAME: \"tests\",\n MODES: [\"scenario\", \"mapping\", \"conformance\", \"property\", \"compliance\"],\n LEVELS: [\"l1\", \"l2\", \"l3\"],\n TAILS: {\n TYPESCRIPT: [\"test\", \"ts\"],\n PYTHON: [\"py\"],\n RUST: [\"rs\"],\n },\n SEGMENT_SEPARATOR: \".\",\n },\n RUNNERS: [\"vitest\", \"playwright\", \"subprocess\"],\n ORDER: {\n SEPARATOR: \"-\",\n PATTERN: /^\\d+$/,\n },\n PATH_SEPARATOR: \"/\",\n COORDINATION_NOTES: [\"PLAN.md\", \"ISSUES.md\"],\n EVAL_LANE: [\"eval.toml\", \"cases.jsonl\", \"prompt.md\", \"history.jsonl\", \"runs\"],\n PRIOR_NODE_SUFFIXES: [\".capability\", \".feature\", \".story\"],\n} as const;\n\nexport const SPEC_TREE_EVIDENCE_FILE = SPEC_TREE_GRAMMAR.EVIDENCE;\n\nexport type SpecTreeEvidenceGrammar = typeof SPEC_TREE_GRAMMAR.EVIDENCE;\nexport type SpecTreeOrderGrammar = typeof SPEC_TREE_GRAMMAR.ORDER;\n\nexport type NamingSchemaVersion = {\n readonly version: string;\n readonly nodeSuffixes: readonly string[];\n readonly decisionSuffixes: readonly string[];\n readonly productSuffix: string;\n readonly evidence: SpecTreeEvidenceGrammar;\n readonly runners: readonly string[];\n readonly order: SpecTreeOrderGrammar;\n readonly pathSeparator: string;\n readonly coordinationNotes: readonly string[];\n readonly evalLane: readonly string[];\n};\n\nconst NAMING_SCHEMA_VERSION_ID = {\n PRIOR: \"1.0.0\",\n CANONICAL: \"2.0.0\",\n} as const;\n\nfunction namingSchemaVersionFromNodeSuffixes(version: string, nodeSuffixes: readonly string[]): NamingSchemaVersion {\n return {\n version,\n nodeSuffixes,\n decisionSuffixes: DECISION_SUFFIXES,\n productSuffix: SPEC_TREE_GRAMMAR.PRODUCT_SUFFIX,\n evidence: SPEC_TREE_GRAMMAR.EVIDENCE,\n runners: SPEC_TREE_GRAMMAR.RUNNERS,\n order: SPEC_TREE_GRAMMAR.ORDER,\n pathSeparator: SPEC_TREE_GRAMMAR.PATH_SEPARATOR,\n coordinationNotes: SPEC_TREE_GRAMMAR.COORDINATION_NOTES,\n evalLane: SPEC_TREE_GRAMMAR.EVAL_LANE,\n };\n}\n\nexport const SPEC_TREE_NAMING_SCHEMA_VERSIONS: readonly NamingSchemaVersion[] = [\n namingSchemaVersionFromNodeSuffixes(NAMING_SCHEMA_VERSION_ID.PRIOR, SPEC_TREE_GRAMMAR.PRIOR_NODE_SUFFIXES),\n namingSchemaVersionFromNodeSuffixes(NAMING_SCHEMA_VERSION_ID.CANONICAL, NODE_SUFFIXES),\n];\n\nconst VERSION_COMPONENT_SEPARATOR = \".\";\nconst VERSION_COMPONENT_RADIX = 10;\nconst VERSION_MISSING_COMPONENT = 0;\nconst VERSION_ORDER_EQUAL = 0;\nconst VERSION_NUMERIC_COMPONENT = /^\\d+$/;\n\nfunction parseVersionComponents(version: string): number[] {\n return version.split(VERSION_COMPONENT_SEPARATOR).map((part) => {\n if (!VERSION_NUMERIC_COMPONENT.test(part)) {\n throw new Error(\n `Naming-schema version \"${version}\" must use numeric dotted components; \"${part}\" is not numeric`,\n );\n }\n return Number.parseInt(part, VERSION_COMPONENT_RADIX);\n });\n}\n\nfunction compareNumericVersionIdentifiers(left: string, right: string): number {\n const leftComponents = parseVersionComponents(left);\n const rightComponents = parseVersionComponents(right);\n const length = Math.max(leftComponents.length, rightComponents.length);\n for (let index = 0; index < length; index += 1) {\n const difference = (leftComponents[index] ?? VERSION_MISSING_COMPONENT)\n - (rightComponents[index] ?? VERSION_MISSING_COMPONENT);\n if (difference !== VERSION_ORDER_EQUAL) {\n return difference;\n }\n }\n return VERSION_ORDER_EQUAL;\n}\n\nexport function compareNamingSchemaVersions(left: NamingSchemaVersion, right: NamingSchemaVersion): number {\n return compareNumericVersionIdentifiers(left.version, right.version);\n}\n\nexport function canonicalNamingSchemaVersion(versions: readonly NamingSchemaVersion[]): NamingSchemaVersion {\n const [first, ...rest] = versions;\n if (first === undefined) {\n throw new Error(\"Naming-schema version tuple must declare at least one version\");\n }\n return rest.reduce(\n (max, version) => (compareNamingSchemaVersions(version, max) > VERSION_ORDER_EQUAL ? version : max),\n first,\n );\n}\n\nexport function supersededNodeSuffixes(versions: readonly NamingSchemaVersion[]): readonly string[] {\n const canonical = canonicalNamingSchemaVersion(versions);\n const canonicalSuffixes = new Set(canonical.nodeSuffixes);\n const superseded = new Set<string>();\n for (const version of versions) {\n if (version === canonical) {\n continue;\n }\n for (const suffix of version.nodeSuffixes) {\n if (!canonicalSuffixes.has(suffix)) {\n superseded.add(suffix);\n }\n }\n }\n return [...superseded];\n}\n\nexport const SPEC_TREE_NAMING_VERSION: string = canonicalNamingSchemaVersion(SPEC_TREE_NAMING_SCHEMA_VERSIONS).version;\nexport const SPEC_TREE_SUPERSEDED_NODE_SUFFIXES: readonly string[] = supersededNodeSuffixes(\n SPEC_TREE_NAMING_SCHEMA_VERSIONS,\n);\n\nexport const SPEC_TREE_NODE_STATE = {\n DECLARED: \"declared\",\n SPECIFIED: \"specified\",\n FAILING: \"failing\",\n PASSING: \"passing\",\n} as const;\n\nexport type SpecTreeNodeState = (typeof SPEC_TREE_NODE_STATE)[keyof typeof SPEC_TREE_NODE_STATE];\n\nexport type SpecTreeConfig = {\n readonly [SPEC_TREE_CONFIG_FIELDS.KINDS]: { readonly [K in Kind]?: KindDefinition<K> };\n};\n\nexport const SPEC_TREE_SECTION = SPEC_TREE_CONFIG.SECTION;\n\nfunction isKind(value: string): value is Kind {\n return Object.prototype.hasOwnProperty.call(KIND_REGISTRY, value);\n}\n\nfunction buildDefaults(): SpecTreeConfig {\n return { kinds: { ...KIND_REGISTRY } };\n}\n\nfunction buildConfigFromKindNames(kindNames: readonly Kind[]): SpecTreeConfig {\n const entries = kindNames.map((kind) => [kind, KIND_REGISTRY[kind]] as const);\n return { kinds: Object.fromEntries(entries) as SpecTreeConfig[\"kinds\"] };\n}\n\nfunction validate(value: unknown): Result<SpecTreeConfig> {\n if (typeof value !== \"object\" || value === null) {\n return { ok: false, error: `${SPEC_TREE_SECTION} section must be an object` };\n }\n const candidate = value as { [SPEC_TREE_CONFIG_FIELDS.KINDS]?: unknown };\n const kindValue = candidate[SPEC_TREE_CONFIG_FIELDS.KINDS];\n if (Array.isArray(kindValue)) {\n return validateKindList(kindValue);\n }\n if (\n typeof kindValue !== \"object\"\n || kindValue === null\n ) {\n return {\n ok: false,\n error:\n `${SPEC_TREE_SECTION}.${SPEC_TREE_CONFIG_FIELDS.KINDS} must be an array of registry kind names or an object with registry metadata`,\n };\n }\n\n return validateKindDefinitionMap(kindValue as Record<string, unknown>);\n}\n\nfunction validateKindList(kinds: readonly unknown[]): Result<SpecTreeConfig> {\n const kindNames: Kind[] = [];\n for (const entry of kinds) {\n if (typeof entry !== \"string\") {\n return {\n ok: false,\n error: `${SPEC_TREE_SECTION}.${SPEC_TREE_CONFIG_FIELDS.KINDS} entries must be registry kind names`,\n };\n }\n if (!isKind(entry)) {\n return {\n ok: false,\n error: `${SPEC_TREE_SECTION}.${SPEC_TREE_CONFIG_FIELDS.KINDS} contains unknown kind \"${entry}\"`,\n };\n }\n kindNames.push(entry);\n }\n\n const duplicateKinds = kindNames.filter((kind, index) => kindNames.indexOf(kind) !== index);\n if (duplicateKinds.length > 0) {\n return {\n ok: false,\n error: `${SPEC_TREE_SECTION}.${SPEC_TREE_CONFIG_FIELDS.KINDS} contains duplicate kind \"${duplicateKinds[0]}\"`,\n };\n }\n\n return { ok: true, value: buildConfigFromKindNames(kindNames) };\n}\n\nfunction validateKindDefinitionMap(kindEntries: Record<string, unknown>): Result<SpecTreeConfig> {\n const entries: Array<[Kind, KindDefinition<Kind>]> = [];\n for (const [key, entry] of Object.entries(kindEntries)) {\n if (!isKind(key)) {\n return {\n ok: false,\n error: `${SPEC_TREE_SECTION}.${SPEC_TREE_CONFIG_FIELDS.KINDS} contains unknown kind \"${key}\"`,\n };\n }\n if (typeof entry !== \"object\" || entry === null) {\n return {\n ok: false,\n error: `${SPEC_TREE_SECTION}.${SPEC_TREE_CONFIG_FIELDS.KINDS}.${key} must be an object with registry metadata`,\n };\n }\n const def = entry as { category?: unknown; suffix?: unknown };\n const expected = KIND_REGISTRY[key];\n if (def.category !== expected.category) {\n return {\n ok: false,\n error: `${SPEC_TREE_SECTION}.${SPEC_TREE_CONFIG_FIELDS.KINDS}.${key}.category must be \"${expected.category}\"`,\n };\n }\n if ((entry as { label?: unknown }).label !== expected.label) {\n return {\n ok: false,\n error: `${SPEC_TREE_SECTION}.${SPEC_TREE_CONFIG_FIELDS.KINDS}.${key}.label must be \"${expected.label}\"`,\n };\n }\n if (def.suffix !== expected.suffix) {\n return {\n ok: false,\n error: `${SPEC_TREE_SECTION}.${SPEC_TREE_CONFIG_FIELDS.KINDS}.${key}.suffix must be \"${expected.suffix}\"`,\n };\n }\n const aliases = (entry as { aliases?: unknown }).aliases;\n if (!Array.isArray(aliases) || aliases.some((alias) => typeof alias !== \"string\")) {\n return {\n ok: false,\n error: `${SPEC_TREE_SECTION}.${SPEC_TREE_CONFIG_FIELDS.KINDS}.${key}.aliases must be an array of strings`,\n };\n }\n if (\n aliases.length !== expected.aliases.length || aliases.some((alias, index) => alias !== expected.aliases[index])\n ) {\n return {\n ok: false,\n error:\n `${SPEC_TREE_SECTION}.${SPEC_TREE_CONFIG_FIELDS.KINDS}.${key}.aliases must match the registry definition`,\n };\n }\n entries.push([key, expected]);\n }\n\n const kinds = Object.fromEntries(entries) as SpecTreeConfig[\"kinds\"];\n return { ok: true, value: { kinds } };\n}\n\nexport const specTreeConfigDescriptor: ConfigDescriptor<SpecTreeConfig> = {\n section: SPEC_TREE_SECTION,\n defaults: buildDefaults(),\n validate,\n};\n","import type { AdapterConfig, ScopeResult } from \"../types\";\n\nexport function eslintAdapter(scope: ScopeResult, config: AdapterConfig): readonly string[] {\n return scope.excluded.flatMap((entry) => [config.ignoreFlag, entry.path]);\n}\n","import type { AdapterConfig, ScopeResult } from \"../types\";\n\nexport function knipAdapter(scope: ScopeResult, config: AdapterConfig): readonly string[] {\n return scope.excluded.flatMap((entry) => [config.ignoreFlag, entry.path]);\n}\n","import type { AdapterConfig, ScopeResult } from \"../types\";\n\nexport function madgeAdapter(scope: ScopeResult, config: AdapterConfig): readonly string[] {\n return scope.excluded.flatMap((entry) => [config.ignoreFlag, entry.path]);\n}\n","import type { AdapterConfig, ScopeResult } from \"../types\";\n\nexport function markdownlintAdapter(scope: ScopeResult, config: AdapterConfig): readonly string[] {\n return scope.excluded.flatMap((entry) => [config.ignoreFlag, entry.path]);\n}\n","import type { AdapterConfig, ScopeResult } from \"../types\";\n\nexport function pytestAdapter(scope: ScopeResult, config: AdapterConfig): readonly string[] {\n return scope.excluded.flatMap((entry) => [config.ignoreFlag, entry.path]);\n}\n","import type { AdapterConfig, ScopeResult } from \"../types\";\n\nexport function tscAdapter(scope: ScopeResult, config: AdapterConfig): readonly string[] {\n return scope.excluded.flatMap((entry) => [config.ignoreFlag, entry.path]);\n}\n","import type { AdapterConfig, ScopeResult } from \"../types\";\n\nexport function vitestAdapter(scope: ScopeResult, config: AdapterConfig): readonly string[] {\n return scope.excluded.flatMap((entry) => [config.ignoreFlag, entry.path]);\n}\n","import type { ScopeResult } from \"../types\";\nimport type { AdapterConfig, ToolAdapterFn, ToolAdaptersConfig } from \"../types\";\n\nimport { eslintAdapter } from \"./eslint\";\nimport { knipAdapter } from \"./knip\";\nimport { madgeAdapter } from \"./madge\";\nimport { markdownlintAdapter } from \"./markdownlint\";\nimport { pytestAdapter } from \"./pytest\";\nimport { tscAdapter } from \"./tsc\";\nimport { vitestAdapter } from \"./vitest\";\n\nexport type { AdapterConfig, ToolAdapterFn, ToolAdaptersConfig };\n\nexport const TOOL_DEFAULT_FLAGS: Readonly<Record<string, string>> = {\n eslint: \"--ignore-pattern\",\n tsc: \"--exclude\",\n madge: \"--exclude\",\n knip: \"--exclude\",\n markdownlint: \"--ignore\",\n pytest: \"--ignore\",\n vitest: \"--exclude\",\n};\n\nconst ADAPTER_MAP: Readonly<Record<string, ToolAdapterFn>> = {\n eslint: eslintAdapter,\n tsc: tscAdapter,\n madge: madgeAdapter,\n knip: knipAdapter,\n markdownlint: markdownlintAdapter,\n pytest: pytestAdapter,\n vitest: vitestAdapter,\n};\n\nexport const REGISTERED_TOOL_NAMES: readonly string[] = Object.keys(ADAPTER_MAP);\n\nexport function toToolArguments(\n scope: ScopeResult,\n toolName: string,\n config: ToolAdaptersConfig,\n): readonly string[] {\n const adapter = ADAPTER_MAP[toolName];\n if (adapter === undefined) {\n throw new Error(\n `Unknown tool \"${toolName}\". Registered tools: ${REGISTERED_TOOL_NAMES.join(\", \")}`,\n );\n }\n const adapterConfig = config[toolName];\n if (adapterConfig === undefined) {\n throw new Error(\n `No adapter config for tool \"${toolName}\". Registered tools: ${REGISTERED_TOOL_NAMES.join(\", \")}`,\n );\n }\n return adapter(scope, adapterConfig);\n}\n","import { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport const IGNORE_SOURCE_FILENAME_DEFAULT = \"EXCLUDE\";\n\nexport type IgnoreSourceReaderConfig = {\n readonly ignoreSourceFilename: string;\n readonly specTreeRootSegment: string;\n};\n\nexport type IgnoreSourceEntry = {\n readonly segment: string;\n readonly lineNumber: number;\n};\n\nexport type IgnoreSourceReader = {\n isUnderIgnoreSource(relativePath: string): boolean;\n entries(): readonly IgnoreSourceEntry[];\n matchedEntry(relativePath: string): IgnoreSourceEntry | undefined;\n};\n\nexport const EMPTY_IGNORE_READER: IgnoreSourceReader = {\n isUnderIgnoreSource(): boolean {\n return false;\n },\n entries(): readonly IgnoreSourceEntry[] {\n return [];\n },\n matchedEntry(): IgnoreSourceEntry | undefined {\n return undefined;\n },\n};\n\nconst COMMENT_PREFIX = \"#\";\n\nfunction isNodeError(err: unknown): err is NodeJS.ErrnoException {\n return err instanceof Error && \"code\" in err;\n}\n\nfunction validateEntry(entry: string, lineNumber: number): void {\n if (entry.startsWith(\"/\")) {\n throw new Error(\n `Invalid ignore-source entry \"${entry}\" at line ${lineNumber}: absolute paths are not allowed`,\n );\n }\n const parts = entry.split(\"/\");\n for (const part of parts) {\n if (part === \"..\" || part === \".\" || part === \"\") {\n throw new Error(\n `Invalid ignore-source entry \"${entry}\" at line ${lineNumber}: empty segments, traversal sequences, and dot-relative prefixes are not allowed`,\n );\n }\n }\n}\n\nexport function createIgnoreSourceReader(\n projectRoot: string,\n config: IgnoreSourceReaderConfig,\n): IgnoreSourceReader {\n const { ignoreSourceFilename, specTreeRootSegment } = config;\n const filePath = join(projectRoot, specTreeRootSegment, ignoreSourceFilename);\n\n let content: string;\n try {\n content = readFileSync(filePath, \"utf8\");\n } catch (err) {\n if (isNodeError(err) && err.code === \"ENOENT\") {\n content = \"\";\n } else {\n throw err;\n }\n }\n\n const parsedEntries: IgnoreSourceEntry[] = [];\n const lines = content.split(\"\\n\");\n for (let i = 0; i < lines.length; i++) {\n const trimmed = lines[i]!.trim();\n if (trimmed.length === 0 || trimmed.startsWith(COMMENT_PREFIX)) continue;\n const lineNumber = i + 1;\n validateEntry(trimmed, lineNumber);\n parsedEntries.push({ segment: trimmed, lineNumber });\n }\n\n const prefixes = parsedEntries.map((e) => `${specTreeRootSegment}/${e.segment}/`);\n\n return {\n isUnderIgnoreSource(relativePath: string): boolean {\n return prefixes.some((prefix) => relativePath.startsWith(prefix));\n },\n entries(): readonly IgnoreSourceEntry[] {\n return parsedEntries;\n },\n matchedEntry(relativePath: string): IgnoreSourceEntry | undefined {\n return parsedEntries.find((entry) => relativePath.startsWith(`${specTreeRootSegment}/${entry.segment}/`));\n },\n };\n}\n","import type { ArtifactDirectoryConfig, LayerDecision } from \"../types\";\n\nexport const ARTIFACT_DIRECTORIES_DEFAULT = [\n \"node_modules\",\n \"dist\",\n \"build\",\n \".next\",\n \".source\",\n \".git\",\n \"out\",\n \"coverage\",\n] as const satisfies readonly string[];\n\nexport const ARTIFACT_DIRECTORY_LAYER = \"artifact-directory\";\nconst LAYER = ARTIFACT_DIRECTORY_LAYER;\n\nexport function artifactDirectoryPredicate(\n path: string,\n config: ArtifactDirectoryConfig,\n): LayerDecision {\n const segments = path.split(\"/\");\n for (const segment of segments) {\n if (config.artifactDirectories.includes(segment)) {\n return { matched: true, layer: LAYER, detail: segment };\n }\n }\n return { matched: false, layer: LAYER };\n}\n","import type { HiddenPrefixConfig, LayerDecision } from \"../types\";\n\nexport const HIDDEN_PREFIX_DEFAULT = \".\";\n\nexport const HIDDEN_PREFIX_LAYER = \"hidden-prefix\";\nconst LAYER = HIDDEN_PREFIX_LAYER;\n\nexport function hiddenPrefixPredicate(path: string, config: HiddenPrefixConfig): LayerDecision {\n const segments = path.split(\"/\");\n const basename = segments[segments.length - 1] ?? \"\";\n const matched = basename.startsWith(config.hiddenPrefix);\n return { matched, layer: LAYER };\n}\n","import type { ConfigDescriptor, Result } from \"@/config/types\";\nimport { SPEC_TREE_CONFIG } from \"@/lib/spec-tree/config\";\n\nimport { TOOL_DEFAULT_FLAGS } from \"./adapters\";\nimport { IGNORE_SOURCE_FILENAME_DEFAULT } from \"./ignore-source\";\nimport { ARTIFACT_DIRECTORIES_DEFAULT } from \"./predicates/artifact-directory\";\nimport { HIDDEN_PREFIX_DEFAULT } from \"./predicates/hidden-prefix\";\nimport type { ScopeResolverConfig, ToolAdaptersConfig } from \"./types\";\n\nexport const FILE_INCLUSION_SECTION = \"fileInclusion\";\n\nexport const FILE_INCLUSION_CONFIG_FIELDS = {\n SCOPE: \"scope\",\n TOOLS: \"tools\",\n ARTIFACT_DIRECTORIES: \"artifactDirectories\",\n HIDDEN_PREFIX: \"hiddenPrefix\",\n IGNORE_SOURCE_FILENAME: \"ignoreSourceFilename\",\n SPEC_TREE_ROOT_SEGMENT: \"specTreeRootSegment\",\n IGNORE_FLAG: \"ignoreFlag\",\n} as const;\n\nexport type FileInclusionConfig = {\n readonly scope: ScopeResolverConfig;\n readonly tools: ToolAdaptersConfig;\n};\n\nexport const DEFAULT_SCOPE_CONFIG: ScopeResolverConfig = {\n artifactDirectories: ARTIFACT_DIRECTORIES_DEFAULT,\n hiddenPrefix: HIDDEN_PREFIX_DEFAULT,\n ignoreSourceFilename: IGNORE_SOURCE_FILENAME_DEFAULT,\n specTreeRootSegment: SPEC_TREE_CONFIG.ROOT_DIRECTORY,\n};\n\nexport const DEFAULT_TOOLS_CONFIG: ToolAdaptersConfig = Object.fromEntries(\n Object.entries(TOOL_DEFAULT_FLAGS).map(([name, flag]) => [name, { ignoreFlag: flag }]),\n);\n\nconst defaults: FileInclusionConfig = {\n scope: DEFAULT_SCOPE_CONFIG,\n tools: DEFAULT_TOOLS_CONFIG,\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction validateStringField(\n section: string,\n field: string,\n value: unknown,\n): Result<string> {\n if (typeof value !== \"string\" || value.length === 0) {\n return { ok: false, error: `${section}.${field} must be a non-empty string` };\n }\n return { ok: true, value };\n}\n\nfunction validateStringArrayField(\n section: string,\n field: string,\n value: unknown,\n): Result<readonly string[]> {\n if (!Array.isArray(value) || value.some((entry) => typeof entry !== \"string\" || entry.length === 0)) {\n return { ok: false, error: `${section}.${field} must be an array of non-empty strings` };\n }\n return { ok: true, value };\n}\n\nfunction rejectUnknownFields(\n section: string,\n value: Record<string, unknown>,\n allowed: ReadonlySet<string>,\n): Result<undefined> {\n const unknownField = Object.keys(value).find((field) => !allowed.has(field));\n if (unknownField !== undefined) {\n return { ok: false, error: `${section}.${unknownField} is not a recognized config field` };\n }\n return { ok: true, value: undefined };\n}\n\nfunction validateScope(raw: unknown): Result<ScopeResolverConfig> {\n if (!isRecord(raw)) {\n return {\n ok: false,\n error: `${FILE_INCLUSION_SECTION}.${FILE_INCLUSION_CONFIG_FIELDS.SCOPE} must be an object`,\n };\n }\n\n const allowed = new Set<string>([\n FILE_INCLUSION_CONFIG_FIELDS.ARTIFACT_DIRECTORIES,\n FILE_INCLUSION_CONFIG_FIELDS.HIDDEN_PREFIX,\n FILE_INCLUSION_CONFIG_FIELDS.IGNORE_SOURCE_FILENAME,\n FILE_INCLUSION_CONFIG_FIELDS.SPEC_TREE_ROOT_SEGMENT,\n ]);\n const scopeUnknownFieldResult = rejectUnknownFields(\n `${FILE_INCLUSION_SECTION}.${FILE_INCLUSION_CONFIG_FIELDS.SCOPE}`,\n raw,\n allowed,\n );\n if (!scopeUnknownFieldResult.ok) return scopeUnknownFieldResult;\n\n const artifactDirectoriesRaw = raw[FILE_INCLUSION_CONFIG_FIELDS.ARTIFACT_DIRECTORIES];\n const artifactDirectories = artifactDirectoriesRaw === undefined\n ? { ok: true as const, value: DEFAULT_SCOPE_CONFIG.artifactDirectories }\n : validateStringArrayField(\n `${FILE_INCLUSION_SECTION}.${FILE_INCLUSION_CONFIG_FIELDS.SCOPE}`,\n FILE_INCLUSION_CONFIG_FIELDS.ARTIFACT_DIRECTORIES,\n artifactDirectoriesRaw,\n );\n if (!artifactDirectories.ok) return artifactDirectories;\n\n const hiddenPrefixRaw = raw[FILE_INCLUSION_CONFIG_FIELDS.HIDDEN_PREFIX];\n const hiddenPrefix = hiddenPrefixRaw === undefined\n ? { ok: true as const, value: DEFAULT_SCOPE_CONFIG.hiddenPrefix }\n : validateStringField(\n `${FILE_INCLUSION_SECTION}.${FILE_INCLUSION_CONFIG_FIELDS.SCOPE}`,\n FILE_INCLUSION_CONFIG_FIELDS.HIDDEN_PREFIX,\n hiddenPrefixRaw,\n );\n if (!hiddenPrefix.ok) return hiddenPrefix;\n\n const ignoreSourceFilenameRaw = raw[FILE_INCLUSION_CONFIG_FIELDS.IGNORE_SOURCE_FILENAME];\n const ignoreSourceFilename = ignoreSourceFilenameRaw === undefined\n ? { ok: true as const, value: DEFAULT_SCOPE_CONFIG.ignoreSourceFilename }\n : validateStringField(\n `${FILE_INCLUSION_SECTION}.${FILE_INCLUSION_CONFIG_FIELDS.SCOPE}`,\n FILE_INCLUSION_CONFIG_FIELDS.IGNORE_SOURCE_FILENAME,\n ignoreSourceFilenameRaw,\n );\n if (!ignoreSourceFilename.ok) return ignoreSourceFilename;\n\n const specTreeRootSegmentRaw = raw[FILE_INCLUSION_CONFIG_FIELDS.SPEC_TREE_ROOT_SEGMENT];\n const specTreeRootSegment = specTreeRootSegmentRaw === undefined\n ? { ok: true as const, value: DEFAULT_SCOPE_CONFIG.specTreeRootSegment }\n : validateStringField(\n `${FILE_INCLUSION_SECTION}.${FILE_INCLUSION_CONFIG_FIELDS.SCOPE}`,\n FILE_INCLUSION_CONFIG_FIELDS.SPEC_TREE_ROOT_SEGMENT,\n specTreeRootSegmentRaw,\n );\n if (!specTreeRootSegment.ok) return specTreeRootSegment;\n\n return {\n ok: true,\n value: {\n artifactDirectories: artifactDirectories.value,\n hiddenPrefix: hiddenPrefix.value,\n ignoreSourceFilename: ignoreSourceFilename.value,\n specTreeRootSegment: specTreeRootSegment.value,\n },\n };\n}\n\nfunction validateTools(raw: unknown): Result<ToolAdaptersConfig> {\n if (!isRecord(raw)) {\n return {\n ok: false,\n error: `${FILE_INCLUSION_SECTION}.${FILE_INCLUSION_CONFIG_FIELDS.TOOLS} must be an object`,\n };\n }\n\n const tools: Record<string, { readonly ignoreFlag: string }> = { ...DEFAULT_TOOLS_CONFIG };\n for (const [toolName, adapterRaw] of Object.entries(raw)) {\n const defaultToolConfig = DEFAULT_TOOLS_CONFIG[toolName];\n if (defaultToolConfig === undefined) {\n return {\n ok: false,\n error: `${FILE_INCLUSION_SECTION}.${FILE_INCLUSION_CONFIG_FIELDS.TOOLS}.${toolName} is not a recognized tool`,\n };\n }\n if (!isRecord(adapterRaw)) {\n return {\n ok: false,\n error: `${FILE_INCLUSION_SECTION}.${FILE_INCLUSION_CONFIG_FIELDS.TOOLS}.${toolName} must be an object`,\n };\n }\n const toolPath = `${FILE_INCLUSION_SECTION}.${FILE_INCLUSION_CONFIG_FIELDS.TOOLS}.${toolName}`;\n const adapterUnknownFieldResult = rejectUnknownFields(\n toolPath,\n adapterRaw,\n new Set<string>([FILE_INCLUSION_CONFIG_FIELDS.IGNORE_FLAG]),\n );\n if (!adapterUnknownFieldResult.ok) return adapterUnknownFieldResult;\n const ignoreFlagRaw = adapterRaw[FILE_INCLUSION_CONFIG_FIELDS.IGNORE_FLAG];\n const ignoreFlag = ignoreFlagRaw === undefined\n ? { ok: true as const, value: defaultToolConfig.ignoreFlag }\n : validateStringField(toolPath, FILE_INCLUSION_CONFIG_FIELDS.IGNORE_FLAG, ignoreFlagRaw);\n if (!ignoreFlag.ok) return ignoreFlag;\n tools[toolName] = { ignoreFlag: ignoreFlag.value };\n }\n\n return { ok: true, value: tools };\n}\n\nfunction validate(value: unknown): Result<FileInclusionConfig> {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return { ok: false, error: `${FILE_INCLUSION_SECTION} section must be an object` };\n }\n const candidate = value as Record<string, unknown>;\n const sectionUnknownFieldResult = rejectUnknownFields(\n FILE_INCLUSION_SECTION,\n candidate,\n new Set<string>([FILE_INCLUSION_CONFIG_FIELDS.SCOPE, FILE_INCLUSION_CONFIG_FIELDS.TOOLS]),\n );\n if (!sectionUnknownFieldResult.ok) return sectionUnknownFieldResult;\n\n const scopeRaw = candidate[FILE_INCLUSION_CONFIG_FIELDS.SCOPE];\n const scope = scopeRaw === undefined\n ? { ok: true as const, value: DEFAULT_SCOPE_CONFIG }\n : validateScope(scopeRaw);\n if (!scope.ok) return scope;\n\n const toolsRaw = candidate[FILE_INCLUSION_CONFIG_FIELDS.TOOLS];\n const tools = toolsRaw === undefined\n ? { ok: true as const, value: DEFAULT_TOOLS_CONFIG }\n : validateTools(toolsRaw);\n if (!tools.ok) return tools;\n\n return {\n ok: true,\n value: {\n [FILE_INCLUSION_CONFIG_FIELDS.SCOPE]: scope.value,\n [FILE_INCLUSION_CONFIG_FIELDS.TOOLS]: tools.value,\n },\n };\n}\n\nexport const fileInclusionConfigDescriptor: ConfigDescriptor<FileInclusionConfig> = {\n section: FILE_INCLUSION_SECTION,\n defaults,\n validate,\n};\n","import type { ConfigDescriptor, Result } from \"@/config/types\";\n\nexport const PRECOMMIT_SECTION = \"precommit\";\n\nexport interface PrecommitConfig {\n readonly sourceDirs: readonly string[];\n readonly testPattern: string;\n}\n\nexport const PRECOMMIT_DEFAULTS: PrecommitConfig = {\n sourceDirs: [\"src/\"],\n testPattern: \".test.ts\",\n};\n\nfunction validate(value: unknown): Result<PrecommitConfig> {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return { ok: false, error: `${PRECOMMIT_SECTION} section must be an object` };\n }\n const candidate = value as Record<string, unknown>;\n\n const sourceDirs = candidate[\"sourceDirs\"] ?? PRECOMMIT_DEFAULTS.sourceDirs;\n if (!Array.isArray(sourceDirs) || !sourceDirs.every((x) => typeof x === \"string\" && x.length > 0)) {\n return {\n ok: false,\n error: `${PRECOMMIT_SECTION}.sourceDirs must be a non-empty array of non-empty strings`,\n };\n }\n\n const testPattern = candidate[\"testPattern\"] ?? PRECOMMIT_DEFAULTS.testPattern;\n if (typeof testPattern !== \"string\" || testPattern.length === 0) {\n return {\n ok: false,\n error: `${PRECOMMIT_SECTION}.testPattern must be a non-empty string`,\n };\n }\n\n return {\n ok: true,\n value: {\n sourceDirs: sourceDirs as readonly string[],\n testPattern: testPattern as string,\n },\n };\n}\n\nexport const precommitConfigDescriptor: ConfigDescriptor<PrecommitConfig> = {\n section: PRECOMMIT_SECTION,\n defaults: PRECOMMIT_DEFAULTS,\n validate,\n};\n","import { type PathFilterConfig, validatePathFilterConfig } from \"@/config/primitives/path-filter\";\nimport type { ConfigDescriptor, Result } from \"@/config/types\";\n\nexport const TESTING_SECTION = \"testing\";\n\nexport const TESTING_CONFIG_FIELDS = {\n PASSING_SCOPE: \"passingScope\",\n} as const;\n\nexport interface TestingConfig {\n readonly passingScope: PathFilterConfig;\n}\n\nconst DEFAULT_PASSING_SCOPE = resolveDefaultPassingScope();\n\nconst defaults: TestingConfig = {\n passingScope: DEFAULT_PASSING_SCOPE,\n};\n\nfunction resolveDefaultPassingScope(): PathFilterConfig {\n const result = validatePathFilterConfig(\n {},\n `${TESTING_SECTION}.${TESTING_CONFIG_FIELDS.PASSING_SCOPE}`,\n );\n if (!result.ok) {\n throw new Error(result.error);\n }\n return result.value;\n}\n\nfunction validate(value: unknown): Result<TestingConfig> {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return { ok: false, error: `${TESTING_SECTION} section must be an object` };\n }\n\n const candidate = value as Record<string, unknown>;\n const passingScopeRaw = candidate[TESTING_CONFIG_FIELDS.PASSING_SCOPE];\n // Null is an explicit invalid value; only an omitted field receives defaults.\n if (passingScopeRaw === undefined) {\n return { ok: true, value: defaults };\n }\n\n const passingScopeResult = validatePathFilterConfig(\n passingScopeRaw,\n `${TESTING_SECTION}.${TESTING_CONFIG_FIELDS.PASSING_SCOPE}`,\n );\n if (!passingScopeResult.ok) return passingScopeResult;\n\n return {\n ok: true,\n value: {\n passingScope: passingScopeResult.value,\n },\n };\n}\n\nexport const testingConfigDescriptor: ConfigDescriptor<TestingConfig> = {\n section: TESTING_SECTION,\n defaults,\n validate,\n};\n","import type { ConfigDescriptor, Result } from \"@/config/types\";\n\nexport const LITERAL_SECTION = \"literal\";\nexport const DEFAULT_MIN_STRING_LENGTH = 4;\nexport const DEFAULT_MIN_NUMBER_DIGITS = 4;\nexport const LEGACY_LITERAL_ALLOWLIST_FIELD = \"allowlist\";\nexport const LEGACY_LITERAL_ALLOWLIST_ERROR =\n \"validation.literal.values.allowlist is no longer valid; move its contents up one level to validation.literal.values.{presets,include,exclude}\";\n\nexport interface LiteralValueAllowlistConfig {\n readonly presets?: readonly string[];\n readonly include?: readonly string[];\n readonly exclude?: readonly string[];\n}\n\nexport interface LiteralConfig extends LiteralValueAllowlistConfig {\n readonly minStringLength: number;\n readonly minNumberDigits: number;\n}\n\nexport const PRESET_NAMES = {\n WEB: \"web\",\n} as const;\n\nexport type PresetName = (typeof PRESET_NAMES)[keyof typeof PRESET_NAMES];\n\nexport const WEB_PRESET_TOKENS = [\n \"GET\",\n \"POST\",\n \"PUT\",\n \"DELETE\",\n \"PATCH\",\n \"Content-Type\",\n \"Authorization\",\n \"Accept\",\n \"status\",\n \"message\",\n \"error\",\n \"data\",\n \"class\",\n \"id\",\n \"href\",\n \"src\",\n \"type\",\n \"name\",\n \"value\",\n] as const;\n\nexport type WebPresetToken = (typeof WEB_PRESET_TOKENS)[number];\n\nconst WEB_PRESET: ReadonlySet<WebPresetToken> = new Set(WEB_PRESET_TOKENS);\n\nconst PRESET_REGISTRY: ReadonlyMap<PresetName, ReadonlySet<string>> = new Map([\n [PRESET_NAMES.WEB, WEB_PRESET],\n]);\n\nexport function resolveAllowlist(config: LiteralValueAllowlistConfig): ReadonlySet<string> {\n const effective = new Set<string>();\n\n for (const presetId of config.presets ?? []) {\n const preset = PRESET_REGISTRY.get(presetId as PresetName);\n if (preset !== undefined) {\n for (const v of preset) effective.add(v);\n }\n }\n\n for (const v of config.include ?? []) {\n effective.add(v);\n }\n\n for (const v of config.exclude ?? []) {\n effective.delete(v);\n }\n\n return effective;\n}\n\nexport const LITERAL_DEFAULTS: LiteralConfig = {\n minStringLength: DEFAULT_MIN_STRING_LENGTH,\n minNumberDigits: DEFAULT_MIN_NUMBER_DIGITS,\n};\n\nfunction validate(value: unknown): Result<LiteralConfig> {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return { ok: false, error: `${LITERAL_SECTION} section must be an object` };\n }\n const candidate = value as Record<string, unknown>;\n\n if (candidate[LEGACY_LITERAL_ALLOWLIST_FIELD] !== undefined) {\n return { ok: false, error: LEGACY_LITERAL_ALLOWLIST_ERROR };\n }\n\n const presets = candidate[\"presets\"];\n if (presets !== undefined) {\n if (!Array.isArray(presets) || !presets.every((x) => typeof x === \"string\")) {\n return { ok: false, error: `${LITERAL_SECTION}.presets must be an array of strings` };\n }\n for (const id of presets as string[]) {\n if (!PRESET_REGISTRY.has(id as PresetName)) {\n return { ok: false, error: `${LITERAL_SECTION}.presets: unrecognized preset \"${id}\"` };\n }\n }\n }\n\n const include = candidate[\"include\"];\n if (include !== undefined && (!Array.isArray(include) || !include.every((x) => typeof x === \"string\"))) {\n return { ok: false, error: `${LITERAL_SECTION}.include must be an array of strings` };\n }\n\n const exclude = candidate[\"exclude\"];\n if (exclude !== undefined && (!Array.isArray(exclude) || !exclude.every((x) => typeof x === \"string\"))) {\n return { ok: false, error: `${LITERAL_SECTION}.exclude must be an array of strings` };\n }\n\n const minStringLength = candidate[\"minStringLength\"] ?? LITERAL_DEFAULTS.minStringLength;\n if (typeof minStringLength !== \"number\" || !Number.isInteger(minStringLength) || minStringLength < 0) {\n return {\n ok: false,\n error: `${LITERAL_SECTION}.minStringLength must be a non-negative integer`,\n };\n }\n\n const minNumberDigits = candidate[\"minNumberDigits\"] ?? LITERAL_DEFAULTS.minNumberDigits;\n if (typeof minNumberDigits !== \"number\" || !Number.isInteger(minNumberDigits) || minNumberDigits < 0) {\n return {\n ok: false,\n error: `${LITERAL_SECTION}.minNumberDigits must be a non-negative integer`,\n };\n }\n\n return {\n ok: true,\n value: {\n presets: presets as readonly string[] | undefined,\n include: include as readonly string[] | undefined,\n exclude: exclude as readonly string[] | undefined,\n minStringLength,\n minNumberDigits,\n },\n };\n}\n\nexport const literalConfigDescriptor: ConfigDescriptor<LiteralConfig> = {\n section: LITERAL_SECTION,\n defaults: LITERAL_DEFAULTS,\n validate,\n};\n","import { type PathFilterConfig, validatePathFilterConfig } from \"@/config/primitives/path-filter\";\nimport type { ConfigDescriptor, Result } from \"@/config/types\";\nimport {\n DEFAULT_MIN_NUMBER_DIGITS,\n DEFAULT_MIN_STRING_LENGTH,\n type LiteralConfig,\n literalConfigDescriptor,\n} from \"@/validation/literal/config\";\n\nexport const VALIDATION_SECTION = \"validation\";\nexport const VALIDATION_LITERAL_SUBSECTION = \"literal\";\nexport const VALIDATION_LITERAL_VALUES_SUBSECTION = \"values\";\nexport const VALIDATION_PATHS_SUBSECTION = \"paths\";\nexport const VALIDATION_KNIP_SUBSECTION = \"knip\";\nexport const VALIDATION_ENABLED_FIELD = \"enabled\";\nexport const VALIDATION_PATH_TOOL_SUBSECTIONS = {\n ESLINT: \"eslint\",\n TYPESCRIPT: \"typescript\",\n CIRCULAR: \"circular\",\n KNIP: \"knip\",\n MARKDOWN: \"markdown\",\n LITERAL: \"literal\",\n} as const;\n\nexport type ValidationPathToolSubsection =\n (typeof VALIDATION_PATH_TOOL_SUBSECTIONS)[keyof typeof VALIDATION_PATH_TOOL_SUBSECTIONS];\n\nexport type ValidationPathFilterConfig = PathFilterConfig;\n\nexport type ValidationToolPathConfig = Partial<Record<ValidationPathToolSubsection, ValidationPathFilterConfig>>;\n\nexport type ValidationPathConfig = ValidationPathFilterConfig & ValidationToolPathConfig;\n\nexport interface ValidationLiteralConfig {\n readonly enabled: boolean;\n readonly values: LiteralConfig;\n}\n\nexport interface ValidationKnipConfig {\n readonly enabled: boolean;\n}\n\nexport interface ValidationConfig {\n readonly paths: ValidationPathConfig;\n readonly literal: ValidationLiteralConfig;\n readonly knip: ValidationKnipConfig;\n}\n\nconst defaults: ValidationConfig = {\n paths: {},\n literal: {\n enabled: true,\n values: {\n minStringLength: DEFAULT_MIN_STRING_LENGTH,\n minNumberDigits: DEFAULT_MIN_NUMBER_DIGITS,\n },\n },\n knip: {\n enabled: false,\n },\n};\n\nfunction validatePaths(raw: unknown): Result<ValidationPathConfig> {\n const basePath = `${VALIDATION_SECTION}.${VALIDATION_PATHS_SUBSECTION}`;\n const baseResult = validatePathFilterConfig(raw, basePath);\n if (!baseResult.ok) return baseResult;\n const candidate = raw as Record<string, unknown>;\n const toolEntries = Object.values(VALIDATION_PATH_TOOL_SUBSECTIONS).map((tool) => {\n const toolRaw = candidate[tool];\n if (toolRaw === undefined) return [tool, undefined] as const;\n const toolResult = validatePathFilterConfig(toolRaw, `${basePath}.${tool}`);\n return [tool, toolResult] as const;\n });\n const toolConfig: ValidationToolPathConfig = {};\n for (const [tool, toolResult] of toolEntries) {\n if (toolResult === undefined) continue;\n if (!toolResult.ok) return toolResult;\n toolConfig[tool] = toolResult.value;\n }\n return { ok: true, value: { ...baseResult.value, ...toolConfig } };\n}\n\nfunction validateLiteral(raw: unknown): Result<ValidationLiteralConfig> {\n if (typeof raw !== \"object\" || raw === null || Array.isArray(raw)) {\n return {\n ok: false,\n error: `${VALIDATION_SECTION}.${VALIDATION_LITERAL_SUBSECTION} must be an object`,\n };\n }\n const candidate = raw as Record<string, unknown>;\n const enabledRaw = candidate[VALIDATION_ENABLED_FIELD] ?? defaults.literal.enabled;\n if (typeof enabledRaw !== \"boolean\") {\n return {\n ok: false,\n error: `${VALIDATION_SECTION}.${VALIDATION_LITERAL_SUBSECTION}.${VALIDATION_ENABLED_FIELD} must be a boolean`,\n };\n }\n const valuesRaw = candidate[VALIDATION_LITERAL_VALUES_SUBSECTION] ?? {};\n const valuesResult = literalConfigDescriptor.validate(valuesRaw);\n if (!valuesResult.ok) {\n return {\n ok: false,\n error:\n `${VALIDATION_SECTION}.${VALIDATION_LITERAL_SUBSECTION}.${VALIDATION_LITERAL_VALUES_SUBSECTION}: ${valuesResult.error}`,\n };\n }\n return { ok: true, value: { enabled: enabledRaw, values: valuesResult.value } };\n}\n\nfunction validateKnip(raw: unknown): Result<ValidationKnipConfig> {\n if (typeof raw !== \"object\" || raw === null || Array.isArray(raw)) {\n return {\n ok: false,\n error: `${VALIDATION_SECTION}.${VALIDATION_KNIP_SUBSECTION} must be an object`,\n };\n }\n const candidate = raw as Record<string, unknown>;\n const enabledRaw = candidate[VALIDATION_ENABLED_FIELD] ?? defaults.knip.enabled;\n if (typeof enabledRaw !== \"boolean\") {\n return {\n ok: false,\n error: `${VALIDATION_SECTION}.${VALIDATION_KNIP_SUBSECTION}.${VALIDATION_ENABLED_FIELD} must be a boolean`,\n };\n }\n return { ok: true, value: { enabled: enabledRaw } };\n}\n\nfunction validate(value: unknown): Result<ValidationConfig> {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return { ok: false, error: `${VALIDATION_SECTION} section must be an object` };\n }\n const candidate = value as Record<string, unknown>;\n\n const pathsRaw = candidate[VALIDATION_PATHS_SUBSECTION] ?? {};\n const pathsResult = validatePaths(pathsRaw);\n if (!pathsResult.ok) return pathsResult;\n\n const literalRaw = candidate[VALIDATION_LITERAL_SUBSECTION] ?? {};\n const literalResult = validateLiteral(literalRaw);\n if (!literalResult.ok) return literalResult;\n\n const knipRaw = candidate[VALIDATION_KNIP_SUBSECTION] ?? {};\n const knipResult = validateKnip(knipRaw);\n if (!knipResult.ok) return knipResult;\n\n return { ok: true, value: { paths: pathsResult.value, literal: literalResult.value, knip: knipResult.value } };\n}\n\nexport const validationConfigDescriptor: ConfigDescriptor<ValidationConfig> = {\n section: VALIDATION_SECTION,\n defaults,\n validate,\n};\n","import { agentEnvironmentConfigDescriptor } from \"@/domains/agent-environment/config\";\nimport { auditConfigDescriptor } from \"@/domains/audit/config\";\nimport { fileInclusionConfigDescriptor } from \"@/lib/file-inclusion/config\";\nimport { precommitConfigDescriptor } from \"@/lib/precommit/config\";\nimport { specTreeConfigDescriptor } from \"@/lib/spec-tree/config\";\nimport { testingConfigDescriptor } from \"@/testing/config\";\nimport { validationConfigDescriptor } from \"@/validation/config/descriptor\";\n\nimport type { ConfigDescriptor } from \"./types\";\n\nexport const productionRegistry: readonly ConfigDescriptor<unknown>[] = [\n specTreeConfigDescriptor,\n validationConfigDescriptor,\n testingConfigDescriptor,\n fileInclusionConfigDescriptor,\n precommitConfigDescriptor,\n agentEnvironmentConfigDescriptor,\n auditConfigDescriptor,\n] as const;\n","import { createHash } from \"node:crypto\";\n\nimport type { Result } from \"./types\";\n\nexport type DescriptorJsonValue =\n | string\n | number\n | boolean\n | null\n | readonly DescriptorJsonValue[]\n | { readonly [key: string]: DescriptorJsonValue };\n\nexport type DescriptorSectionDigest = {\n readonly canonicalJson: string;\n readonly sha256: string;\n};\n\nconst DEFAULT_DESCRIPTOR_PATH = \"descriptor section\";\nconst SHA256_ALGORITHM = \"sha256\";\nconst UTF8_ENCODING = \"utf8\";\nconst HEX_ENCODING = \"hex\";\n\ntype JsonRecord = { readonly [key: string]: DescriptorJsonValue };\n\nexport function canonicalDescriptorJson(\n value: unknown,\n path = DEFAULT_DESCRIPTOR_PATH,\n): Result<string> {\n const normalized = normalizeDescriptorJsonValue(value, path, new WeakSet<object>());\n if (!normalized.ok) return normalized;\n\n return { ok: true, value: JSON.stringify(normalized.value) };\n}\n\nexport function digestDescriptorSection(\n value: unknown,\n path = DEFAULT_DESCRIPTOR_PATH,\n): Result<DescriptorSectionDigest> {\n const canonical = canonicalDescriptorJson(value, path);\n if (!canonical.ok) return canonical;\n\n const sha256 = createHash(SHA256_ALGORITHM)\n .update(Buffer.from(canonical.value, UTF8_ENCODING))\n .digest(HEX_ENCODING);\n\n return {\n ok: true,\n value: {\n canonicalJson: canonical.value,\n sha256,\n },\n };\n}\n\nfunction normalizeDescriptorJsonValue(\n value: unknown,\n path: string,\n seen: WeakSet<object>,\n): Result<DescriptorJsonValue> {\n switch (typeof value) {\n case \"string\":\n case \"boolean\":\n return { ok: true, value };\n case \"number\":\n return Number.isFinite(value)\n ? { ok: true, value }\n : { ok: false, error: `${path} must be a finite number` };\n case \"object\":\n if (value === null) return { ok: true, value };\n return normalizeObject(value, path, seen);\n case \"undefined\":\n case \"bigint\":\n case \"function\":\n case \"symbol\":\n return { ok: false, error: `${path} must be JSON-representable` };\n }\n}\n\nfunction normalizeObject(\n value: object,\n path: string,\n seen: WeakSet<object>,\n): Result<DescriptorJsonValue> {\n if (seen.has(value)) {\n return { ok: false, error: `${path} must not contain circular references` };\n }\n seen.add(value);\n\n const result = Array.isArray(value)\n ? normalizeArray(value, path, seen)\n : normalizeRecord(value, path, seen);\n\n // Keep `seen` as the current DFS path so sibling branches may share objects.\n seen.delete(value);\n return result;\n}\n\nfunction normalizeArray(\n value: readonly unknown[],\n path: string,\n seen: WeakSet<object>,\n): Result<readonly DescriptorJsonValue[]> {\n const normalized: DescriptorJsonValue[] = [];\n for (const [index, item] of value.entries()) {\n const itemResult = normalizeDescriptorJsonValue(item, `${path}[${index}]`, seen);\n if (!itemResult.ok) return itemResult;\n normalized.push(itemResult.value);\n }\n return { ok: true, value: normalized };\n}\n\nfunction normalizeRecord(\n value: object,\n path: string,\n seen: WeakSet<object>,\n): Result<JsonRecord> {\n if (!isPlainRecord(value)) {\n return { ok: false, error: `${path} must be a plain object` };\n }\n\n const keys = Reflect.ownKeys(value);\n if (keys.some((key) => typeof key === \"symbol\")) {\n return { ok: false, error: `${path} must not contain symbol keys` };\n }\n\n const record = value as Record<string, unknown>;\n const normalized: Record<string, DescriptorJsonValue> = {};\n for (const key of (keys as string[]).sort(compareUnicodeCodePointStrings)) {\n const child = normalizeDescriptorJsonValue(record[key], `${path}.${key}`, seen);\n if (!child.ok) return child;\n normalized[key] = child.value;\n }\n\n return { ok: true, value: normalized };\n}\n\nfunction isPlainRecord(value: object): boolean {\n const prototype = Object.getPrototypeOf(value);\n return prototype === null || prototype === Object.prototype;\n}\n\nfunction compareUnicodeCodePointStrings(left: string, right: string): number {\n const leftCodePoints = Array.from(left, (value) => value.codePointAt(0) ?? 0);\n const rightCodePoints = Array.from(right, (value) => value.codePointAt(0) ?? 0);\n const length = Math.min(leftCodePoints.length, rightCodePoints.length);\n\n for (let index = 0; index < length; index += 1) {\n const delta = leftCodePoints[index] - rightCodePoints[index];\n if (delta !== 0) return delta;\n }\n\n return leftCodePoints.length - rightCodePoints.length;\n}\n","import { CONFIG_FILE_FORMAT, DEFAULT_CONFIG_FILE_FORMAT, serializeConfigFileSections } from \"@/config/index\";\nimport type { Config } from \"@/config/types\";\n\nimport type { CliDeps, CliResult, DefaultsOptions } from \"./types\";\n\nexport function defaultsCommand(options: DefaultsOptions, deps: CliDeps): Promise<CliResult> {\n const config: Record<string, unknown> = {};\n for (const descriptor of deps.descriptors) {\n config[descriptor.section] = descriptor.defaults;\n }\n\n return Promise.resolve({\n stdout: formatConfig(config as Config, options.json === true),\n stderr: \"\",\n exitCode: 0,\n });\n}\n\nfunction formatConfig(config: Config, asJson: boolean): string {\n const format = asJson ? CONFIG_FILE_FORMAT.JSON : DEFAULT_CONFIG_FILE_FORMAT;\n const serialized = serializeConfigFileSections(format, config as Record<string, unknown>);\n if (!serialized.ok) {\n throw new Error(serialized.error);\n }\n return serialized.value;\n}\n","import { CONFIG_FILE_FORMAT, DEFAULT_CONFIG_FILE_FORMAT, serializeConfigFileSections } from \"@/config/index\";\nimport type { Config } from \"@/config/types\";\n\nimport type { CliDeps, CliResult, ShowOptions } from \"./types\";\n\nconst EXIT_CODE_ERROR = 1;\n\nexport async function showCommand(options: ShowOptions, deps: CliDeps): Promise<CliResult> {\n const productDir = deps.resolveProductDir();\n const result = await deps.resolveConfig(productDir);\n\n if (!result.ok) {\n return {\n stdout: \"\",\n stderr: `${result.error}\\n`,\n exitCode: EXIT_CODE_ERROR,\n };\n }\n\n return {\n stdout: formatConfig(result.value, options.json === true),\n stderr: \"\",\n exitCode: 0,\n };\n}\n\nfunction formatConfig(config: Config, asJson: boolean): string {\n const format = asJson ? CONFIG_FILE_FORMAT.JSON : DEFAULT_CONFIG_FILE_FORMAT;\n const serialized = serializeConfigFileSections(format, config as Record<string, unknown>);\n if (!serialized.ok) {\n throw new Error(serialized.error);\n }\n return serialized.value;\n}\n","import type { CliDeps, CliResult, ValidateOptions } from \"./types\";\n\nconst EXIT_CODE_INVALID = 1;\n\nexport const VALIDATE_SUCCESS_TOKENS = {\n PASSES_SUFFIX: \"passes every registered descriptor's validator.\",\n ABSENT_PREFIX: \"No config file\",\n ABSENT_SUBJECT: \"descriptor defaults\",\n} as const;\n\nfunction buildPresentSuccessLine(filename: string, productDir: string): string {\n return `${filename} at ${productDir} ${VALIDATE_SUCCESS_TOKENS.PASSES_SUFFIX}\\n`;\n}\n\nfunction buildAbsentSuccessLine(productDir: string): string {\n return `${VALIDATE_SUCCESS_TOKENS.ABSENT_PREFIX} at ${productDir}; `\n + `${VALIDATE_SUCCESS_TOKENS.ABSENT_SUBJECT} ${VALIDATE_SUCCESS_TOKENS.PASSES_SUFFIX}\\n`;\n}\n\nexport async function validateCommand(_options: ValidateOptions, deps: CliDeps): Promise<CliResult> {\n const productDir = deps.resolveProductDir();\n\n const fileResult = await deps.readProductConfigFile(productDir);\n if (!fileResult.ok) {\n return {\n stdout: \"\",\n stderr: `${fileResult.error}\\n`,\n exitCode: EXIT_CODE_INVALID,\n };\n }\n\n const result = deps.resolveConfigFromReadResult(fileResult.value, deps.descriptors);\n if (!result.ok) {\n return {\n stdout: \"\",\n stderr: `${result.error}\\n`,\n exitCode: EXIT_CODE_INVALID,\n };\n }\n\n const file = fileResult.value;\n const stdout = file.kind === \"ok\"\n ? buildPresentSuccessLine(file.file.filename, productDir)\n : buildAbsentSuccessLine(productDir);\n\n return { stdout, stderr: \"\", exitCode: 0 };\n}\n","import { execSync } from \"node:child_process\";\nimport { resolve } from \"node:path\";\n\nconst GIT_TOPLEVEL_CMD = \"git rev-parse --show-toplevel\";\nconst GIT_NOT_REPO_MARKER = \"not a git repository\";\n\nexport type ResolvedProductDir = {\n readonly productDir: string;\n readonly warning?: string;\n};\n\nexport function resolveProductDir(cwd: string = process.cwd()): ResolvedProductDir {\n const resolvedCwd = resolve(cwd);\n try {\n const stdout = execSync(GIT_TOPLEVEL_CMD, {\n cwd: resolvedCwd,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n encoding: \"utf8\",\n });\n const toplevel = stdout.trim();\n if (toplevel.length > 0) {\n return { productDir: resolve(toplevel) };\n }\n } catch {\n // fall through to cwd fallback\n }\n\n return {\n productDir: resolvedCwd,\n warning:\n `warning: ${resolvedCwd} is not inside a git worktree — falling back to the current working directory. ${GIT_NOT_REPO_MARKER}.`,\n };\n}\n","/**\n * Writes a CLI diagnostic warning to standard error.\n *\n * Short-circuits when no warning is present, so a descriptor passes an optional\n * warning straight through without a local guard. Appends a trailing newline so\n * the warning occupies its own terminal line.\n *\n * @param warning - The warning text, or `undefined` when there is nothing to emit.\n */\nexport function writeWarning(warning: string | undefined): void {\n if (warning === undefined) {\n return;\n }\n process.stderr.write(`${warning}\\n`);\n}\n","import type { Command } from \"commander\";\n\nimport { defaultsCommand } from \"@/commands/config/defaults\";\nimport { showCommand } from \"@/commands/config/show\";\nimport type { CliDeps, CliResult, ShowOptions, ValidateOptions } from \"@/commands/config/types\";\nimport { validateCommand } from \"@/commands/config/validate\";\nimport {\n CONFIG_FILE_FORMAT,\n DEFAULT_CONFIG_FILE_FORMAT,\n DEFAULT_CONFIG_FILENAME,\n readProductConfigFile,\n resolveConfig,\n resolveConfigFromReadResult,\n} from \"@/config/index\";\nimport { productionRegistry } from \"@/config/registry\";\n\nimport { resolveProductDir } from \"@/domains/config/root\";\nimport type { Domain } from \"@/domains/types\";\n\nimport { writeWarning } from \"./write-warning\";\n\nfunction buildDefaultDeps(): CliDeps {\n return {\n resolveConfig,\n readProductConfigFile,\n resolveConfigFromReadResult,\n resolveProductDir: (): string => {\n const resolved = resolveProductDir();\n writeWarning(resolved.warning);\n return resolved.productDir;\n },\n descriptors: productionRegistry,\n };\n}\n\nasync function emit(result: CliResult): Promise<never> {\n if (result.stdout.length > 0) {\n process.stdout.write(result.stdout);\n }\n if (result.stderr.length > 0) {\n process.stderr.write(result.stderr);\n }\n return process.exit(result.exitCode);\n}\n\nfunction registerConfigCommands(configCmd: Command): void {\n configCmd\n .command(\"show\")\n .description(\n `Print the resolved configuration as ${DEFAULT_CONFIG_FILE_FORMAT.toUpperCase()} `\n + `(or ${CONFIG_FILE_FORMAT.JSON.toUpperCase()} with --json)`,\n )\n .option(\"--json\", `Output as ${CONFIG_FILE_FORMAT.JSON.toUpperCase()}`)\n .action(async (options: ShowOptions) => {\n await emit(await showCommand(options, buildDefaultDeps()));\n });\n\n configCmd\n .command(\"validate\")\n .description(`Verify that ${DEFAULT_CONFIG_FILENAME} passes every registered descriptor's validator`)\n .action(async (options: ValidateOptions) => {\n await emit(await validateCommand(options, buildDefaultDeps()));\n });\n\n configCmd\n .command(\"defaults\")\n .description(`Print each registered descriptor's defaults; ignores ${DEFAULT_CONFIG_FILENAME}`)\n .option(\"--json\", `Output as ${CONFIG_FILE_FORMAT.JSON.toUpperCase()}`)\n .action(async (options: ShowOptions) => {\n await emit(await defaultsCommand(options, buildDefaultDeps()));\n });\n}\n\nexport const configDomain: Domain = {\n name: \"config\",\n description: \"Inspect and validate the resolved spx configuration\",\n register: (program: Command) => {\n const configCmd = program\n .command(\"config\")\n .description(\"Inspect and validate the resolved spx configuration\");\n registerConfigCommands(configCmd);\n },\n};\n","/**\n * Session archive CLI command handler.\n *\n * @module commands/session/archive\n */\n\nimport { mkdir, rename, stat } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\n\nimport {\n buildArchivePaths,\n ExistingPathsMap,\n findSessionForArchive,\n SESSION_FILE_EXTENSION,\n} from \"@/domains/session/archive\";\nimport { processBatch } from \"@/domains/session/batch\";\nimport { SessionNotFoundError } from \"@/domains/session/errors\";\nimport { SessionDirectoryConfig } from \"@/domains/session/show\";\nimport { resolveSessionConfigSurfacingWarning, type SessionWarningHandler } from \"./resolve-config\";\n\nexport const SESSION_ARCHIVE_OUTPUT = {\n ARCHIVED: \"Archived session\",\n ARCHIVE_LOCATION: \"Archive location\",\n} as const;\n\n/**\n * Options for the archive command.\n */\nexport interface ArchiveOptions {\n /** Session ID(s) to archive */\n sessionIds: string[];\n /** Custom sessions directory */\n sessionsDir?: string;\n /** Receives the non-git-repo diagnostic for the descriptor to surface. */\n onWarning?: SessionWarningHandler;\n}\n\n/**\n * Error thrown when a session is already archived.\n */\nexport class SessionAlreadyArchivedError extends Error {\n /** The session ID that is already archived */\n readonly sessionId: string;\n\n constructor(sessionId: string) {\n super(`Session already archived: ${sessionId}.`);\n this.name = \"SessionAlreadyArchivedError\";\n this.sessionId = sessionId;\n }\n}\n\n/**\n * Checks whether a path exists as a file.\n */\nasync function fileExists(path: string): Promise<boolean> {\n try {\n const stats = await stat(path);\n return stats.isFile();\n } catch {\n return false;\n }\n}\n\n/**\n * Builds an ExistingPathsMap by probing the filesystem for a session ID\n * across all status directories.\n *\n * @param sessionId - Session ID to locate\n * @param config - Directory configuration\n * @returns Map of existing paths (null for directories where file is absent)\n */\nasync function probeSessionPaths(\n sessionId: string,\n config: SessionDirectoryConfig,\n): Promise<ExistingPathsMap> {\n const filename = `${sessionId}${SESSION_FILE_EXTENSION}`;\n const todoPath = join(config.todoDir, filename);\n const doingPath = join(config.doingDir, filename);\n const archivePath = join(config.archiveDir, filename);\n\n return {\n todo: await fileExists(todoPath) ? todoPath : null,\n doing: await fileExists(doingPath) ? doingPath : null,\n archive: await fileExists(archivePath) ? archivePath : null,\n };\n}\n\n/**\n * Resolves source and target paths for archiving a session.\n *\n * @param sessionId - Session ID to archive\n * @param config - Directory configuration\n * @returns Source and target paths for the archive rename\n * @throws {SessionNotFoundError} When session is not found in todo or doing\n * @throws {SessionAlreadyArchivedError} When session is already in archive\n */\nexport async function resolveArchivePaths(\n sessionId: string,\n config: SessionDirectoryConfig,\n): Promise<{ source: string; target: string }> {\n const existingPaths = await probeSessionPaths(sessionId, config);\n\n if (existingPaths.archive !== null) {\n throw new SessionAlreadyArchivedError(sessionId);\n }\n\n const location = findSessionForArchive(existingPaths);\n\n if (!location) {\n throw new SessionNotFoundError(sessionId);\n }\n\n const paths = buildArchivePaths(sessionId, location.status, config);\n return paths;\n}\n\n/**\n * Archives a single session by ID. Any session in todo or doing is moved to\n * archive regardless of its frontmatter shape.\n */\nasync function archiveSingle(\n sessionId: string,\n config: SessionDirectoryConfig,\n): Promise<string> {\n const { source, target } = await resolveArchivePaths(sessionId, config);\n\n await mkdir(dirname(target), { recursive: true });\n await rename(source, target);\n return `${SESSION_ARCHIVE_OUTPUT.ARCHIVED}: ${sessionId}\\n${SESSION_ARCHIVE_OUTPUT.ARCHIVE_LOCATION}: ${target}`;\n}\n\n/**\n * Executes the archive command for one or more session IDs.\n *\n * @param options - Command options with one or more session IDs\n * @returns Formatted output for display\n * @throws {BatchError} When one or more IDs fail\n * @throws {SessionNotFoundError} When session not found (single ID)\n * @throws {SessionAlreadyArchivedError} When session already archived (single ID)\n */\nexport async function archiveCommand(options: ArchiveOptions): Promise<string> {\n const config = await resolveSessionConfigSurfacingWarning(options.sessionsDir, options.onWarning);\n\n return processBatch(options.sessionIds, (id) => archiveSingle(id, config));\n}\n","/**\n * Session archiving utilities with pure functions for path resolution.\n *\n * This module provides pure functions for archive path building and session\n * location finding. Actual filesystem operations are handled by the CLI\n * command handler in commands/session/archive.ts.\n *\n * @module session/archive\n */\n\nimport type { SessionStatus } from \"./types\";\n\n/**\n * File extension for session files.\n */\nexport const SESSION_FILE_EXTENSION = \".md\";\n\n/**\n * Configuration for archive path building.\n */\nexport interface ArchivePathConfig {\n /** Directory for todo sessions */\n todoDir: string;\n /** Directory for doing (claimed) sessions */\n doingDir: string;\n /** Directory for archived sessions */\n archiveDir: string;\n}\n\n/**\n * Result of building archive paths.\n */\nexport interface ArchivePaths {\n /** Source path where session currently exists */\n source: string;\n /** Target path in archive directory */\n target: string;\n}\n\n/**\n * Map of existing paths for session lookup.\n * Each key maps to the full path if file exists, or null if not found.\n */\nexport interface ExistingPathsMap {\n /** Path in todo directory, or null if not found */\n todo: string | null;\n /** Path in doing directory, or null if not found */\n doing: string | null;\n /** Path in archive directory, or null if not found */\n archive: string | null;\n}\n\n/**\n * Archivable statuses — sessions can only be archived from todo or doing.\n */\nexport type ArchivableStatus = Exclude<SessionStatus, \"archive\">;\n\nconst ARCHIVABLE_DIR_KEYS = {\n TODO: \"todoDir\",\n DOING: \"doingDir\",\n} as const;\n\ntype ArchivableDirKey = (typeof ARCHIVABLE_DIR_KEYS)[keyof typeof ARCHIVABLE_DIR_KEYS];\n\n/**\n * Result of finding a session for archiving.\n */\nexport interface SessionLocation {\n /** Status/directory where session was found */\n status: ArchivableStatus;\n /** Full path to the session file */\n path: string;\n}\n\n/**\n * Builds source and target paths for archiving a session.\n *\n * This is a pure function that computes paths based on session ID,\n * current status, and directory configuration.\n *\n * @param sessionId - Session ID (timestamp format)\n * @param currentStatus - Current status/directory of the session\n * @param config - Directory configuration\n * @returns Source and target paths for the archive operation\n *\n * @example\n * ```typescript\n * const paths = buildArchivePaths(\"2026-01-13_08-01-05\", \"todo\", {\n * todoDir: \".spx/sessions/todo\",\n * archiveDir: \".spx/sessions/archive\",\n * });\n * // paths.source === \".spx/sessions/todo/2026-01-13_08-01-05.md\"\n * // paths.target === \".spx/sessions/archive/2026-01-13_08-01-05.md\"\n * ```\n */\n/**\n * Maps archivable status to the corresponding config directory key.\n */\nconst ARCHIVABLE_DIR_KEY: Record<ArchivableStatus, ArchivableDirKey> = {\n todo: ARCHIVABLE_DIR_KEYS.TODO,\n doing: ARCHIVABLE_DIR_KEYS.DOING,\n};\n\nexport function buildArchivePaths(\n sessionId: string,\n currentStatus: ArchivableStatus,\n config: ArchivePathConfig,\n): ArchivePaths {\n const filename = `${sessionId}${SESSION_FILE_EXTENSION}`;\n const dirKey = ARCHIVABLE_DIR_KEY[currentStatus];\n const sourceDir = config[dirKey];\n\n return {\n source: `${sourceDir}/${filename}`,\n target: `${config.archiveDir}/${filename}`,\n };\n}\n\n/**\n * Finds a session's location for archiving.\n *\n * This is a pure function that determines the session's location based\n * on a map of existing paths. Returns null if the session is already\n * archived or not found.\n *\n * @param existingPaths - Map of paths where session might exist\n * @returns Session location if found in todo or doing, null otherwise\n *\n * @example\n * ```typescript\n * // Session in todo\n * const location = findSessionForArchive({\n * todo: \".spx/sessions/todo/test.md\",\n * doing: null,\n * archive: null,\n * });\n * // location === { status: \"todo\", path: \".spx/sessions/todo/test.md\" }\n *\n * // Session already archived\n * const location = findSessionForArchive({\n * todo: null,\n * doing: null,\n * archive: \".spx/sessions/archive/test.md\",\n * });\n * // location === null\n * ```\n */\n/**\n * Statuses to check when looking for a session to archive, in priority order.\n */\nconst ARCHIVE_SEARCH_ORDER: readonly ArchivableStatus[] = [\"todo\", \"doing\"] as const;\n\nexport function findSessionForArchive(\n existingPaths: ExistingPathsMap,\n): SessionLocation | null {\n // If session is already in archive, return null\n if (existingPaths.archive !== null) {\n return null;\n }\n\n // Check archivable directories in priority order\n for (const status of ARCHIVE_SEARCH_ORDER) {\n if (existingPaths[status] !== null) {\n return { status, path: existingPaths[status] };\n }\n }\n\n // Session not found anywhere\n return null;\n}\n","/**\n * Batch processing utilities for session commands.\n *\n * Provides a shared pattern for processing multiple session IDs:\n * run a handler per ID, collect results, report per-ID outcomes,\n * throw if any failed.\n *\n * @module session/batch\n */\n\n/**\n * Result of processing a single session ID within a batch.\n */\nexport interface BatchItemResult {\n /** The session ID that was processed. */\n id: string;\n /** Whether the operation succeeded. */\n ok: boolean;\n /** Output message on success, error message on failure. */\n message: string;\n}\n\n/**\n * Error thrown when a batch operation has partial or total failures.\n * Contains per-ID results so the caller knows which succeeded and which failed.\n */\nexport class BatchError extends Error {\n readonly results: readonly BatchItemResult[];\n\n constructor(results: readonly BatchItemResult[]) {\n const failures = results.filter((r) => !r.ok);\n const successes = results.filter((r) => r.ok);\n super(\n `${failures.length} of ${results.length} operations failed. `\n + `${successes.length} succeeded.`,\n );\n this.name = \"BatchError\";\n this.results = results;\n }\n}\n\n/**\n * Processes multiple session IDs through a handler function.\n *\n * IDs are processed sequentially in argument order (left-to-right).\n * All IDs are processed regardless of individual failures.\n * Throws BatchError if any ID fails.\n *\n * @param ids - Session IDs to process\n * @param handler - Async function that processes a single ID and returns output\n * @returns Combined output string with per-ID results\n * @throws {BatchError} When one or more IDs fail\n */\nexport async function processBatch(\n ids: readonly string[],\n handler: (id: string) => Promise<string>,\n): Promise<string> {\n const results: BatchItemResult[] = [];\n\n for (const id of ids) {\n try {\n const output = await handler(id);\n results.push({ id, ok: true, message: output });\n } catch (error) {\n const message = error instanceof Error ? `${error.name}: ${error.message}` : String(error);\n results.push({ id, ok: false, message });\n }\n }\n\n const output = results\n .map((r) => r.ok ? r.message : `Error (${r.id}): ${r.message}`)\n .join(\"\\n\\n\");\n\n const hasFailures = results.some((r) => !r.ok);\n if (hasFailures) {\n const err = new BatchError(results);\n err.message = `${err.message}\\n\\n${output}`;\n throw err;\n }\n\n return output;\n}\n","/**\n * The handoff-base refusal checklist: the resolved git facts and per-prerequisite\n * evaluation a non-main-checkout refusal carries, plus the source-owned vocabulary\n * the descriptor renders. Pure over the carried facts — the handler resolves the\n * facts, the resolver attaches them to {@link SessionHandoffBaseError}, and the\n * descriptor writes the rendered text to standard error.\n *\n * @module domains/session/handoff-base-checklist\n */\n\n/** The error name a handoff-base refusal carries and the checklist names. */\nexport const SESSION_HANDOFF_BASE_ERROR_NAME = \"SessionHandoffBaseError\";\n\n/** Markers a checklist line carries for a met or unmet base prerequisite. */\nexport const HANDOFF_BASE_MARK = {\n MET: \"✓\",\n UNMET: \"✗\",\n} as const;\n\n/** The base prerequisites a non-main-checkout handoff must satisfy. */\nexport const HANDOFF_BASE_PREREQUISITE_LABEL = {\n CLEAN_WORKING_TREE: \"working tree is clean\",\n DETACHED_AT_DEFAULT_TIP: \"HEAD is detached at the default-branch tip\",\n} as const;\n\n/** The non-stashing remedy each unmet prerequisite states. */\nexport const HANDOFF_BASE_REMEDY = {\n /** Unclean working tree: commit, or hand off from the main checkout. */\n COMMIT_OR_MAIN_CHECKOUT: \"commit the changes, or run handoff from the main checkout\",\n /** Off the default-branch tip: detach to it, or hand off from the main checkout. */\n DETACH_TO_TIP_OR_MAIN_CHECKOUT: \"detach HEAD to the default-branch tip, or run handoff from the main checkout\",\n /** Default branch unresolved: only the main checkout can anchor the base. */\n MAIN_CHECKOUT_ONLY: \"run handoff from the main checkout\",\n} as const;\n\n/**\n * Labels on the resolved-git-fact lines the checklist carries. `DEFAULT_TIP`\n * reads `origin tip` rather than `default-branch tip` so a fact-line lookup by\n * label never collides with the `DETACHED_AT_DEFAULT_TIP` prerequisite label.\n */\nexport const HANDOFF_BASE_FACT_LABEL = {\n DEFAULT_BRANCH: \"default branch\",\n DEFAULT_TIP: \"origin tip\",\n HEAD: \"HEAD\",\n CURRENT_WORKTREE: \"current worktree\",\n MAIN_CHECKOUT: \"main checkout\",\n} as const;\n\n/** Stated in place of a default branch or tip that does not resolve (`origin/HEAD` unset). */\nexport const HANDOFF_BASE_UNRESOLVED = \"unresolved\";\n\n/**\n * A single base prerequisite a non-main-checkout refusal evaluates. Every\n * prerequisite is represented regardless of which are met, so the rendered\n * checklist omits none.\n */\nexport interface HandoffBasePrerequisite {\n /** The prerequisite, from {@link HANDOFF_BASE_PREREQUISITE_LABEL}. */\n readonly label: string;\n /** Whether the working context satisfies the prerequisite. */\n readonly met: boolean;\n /** When unmet, the non-stashing remedy from {@link HANDOFF_BASE_REMEDY}; empty when met. */\n readonly remedy: string;\n}\n\n/**\n * The resolved git facts and per-prerequisite evaluation a non-main-checkout\n * handoff refusal carries. `null` for `defaultBranch` or `defaultTipSha` marks\n * the value unresolved — `origin/HEAD` is unset — never a fabricated branch or\n * SHA and never the literal placeholder `origin/<default>`.\n */\nexport interface HandoffBaseChecklist {\n /** The resolved default branch name, or `null` when `origin/HEAD` is unset. */\n readonly defaultBranch: string | null;\n /** The `origin/<default>` tip commit SHA, or `null` when unresolved. */\n readonly defaultTipSha: string | null;\n /** The observed HEAD commit SHA, or `null` when unavailable. */\n readonly headSha: string | null;\n /** The absolute path of the worktree handoff ran from. */\n readonly currentWorktreePath: string;\n /** The absolute path of the repository's main checkout, or null when none is designable (rendered \"unresolved\"). */\n readonly mainCheckoutPath: string | null;\n /** Every base prerequisite, each marked met or unmet. */\n readonly prerequisites: readonly HandoffBasePrerequisite[];\n}\n\n/** Leading indent on every checklist body line. */\nconst CHECKLIST_INDENT = \" \";\n/** Separator between an unmet prerequisite and its remedy. */\nconst REMEDY_SEPARATOR = \" — \";\n/** Opening line introducing the refusal and naming the error. */\nconst CHECKLIST_HEADER =\n `${SESSION_HANDOFF_BASE_ERROR_NAME}: cannot create a handoff session from this worktree — it is not the main checkout.`;\n\n/** Renders one resolved-fact line, stating `unresolved` for an absent value. */\nfunction renderFactLine(label: string, value: string | null): string {\n return `${CHECKLIST_INDENT}${label}: ${value ?? HANDOFF_BASE_UNRESOLVED}`;\n}\n\n/** Renders one prerequisite line — a mark, the label, and (when unmet) its remedy. */\nfunction renderPrerequisiteLine(prerequisite: HandoffBasePrerequisite): string {\n const mark = prerequisite.met ? HANDOFF_BASE_MARK.MET : HANDOFF_BASE_MARK.UNMET;\n const base = `${CHECKLIST_INDENT}${mark} ${prerequisite.label}`;\n return prerequisite.met ? base : `${base}${REMEDY_SEPARATOR}${prerequisite.remedy}`;\n}\n\n/**\n * Renders a non-main-checkout handoff refusal as the prerequisite checklist the\n * descriptor writes to standard error: the error name, the resolved git values\n * (default branch, origin tip SHA, observed HEAD SHA, current and main checkout\n * paths — each stated `unresolved` when absent), and every base prerequisite on\n * its own line marked met or unmet with a non-stashing remedy when unmet.\n *\n * @param checklist - The resolved facts and per-prerequisite evaluation the\n * refusal carries.\n * @returns The multi-line diagnostic, without a trailing newline.\n */\nexport function renderHandoffBaseChecklist(checklist: HandoffBaseChecklist): string {\n return [\n CHECKLIST_HEADER,\n renderFactLine(HANDOFF_BASE_FACT_LABEL.DEFAULT_BRANCH, checklist.defaultBranch),\n renderFactLine(HANDOFF_BASE_FACT_LABEL.DEFAULT_TIP, checklist.defaultTipSha),\n renderFactLine(HANDOFF_BASE_FACT_LABEL.HEAD, checklist.headSha),\n renderFactLine(HANDOFF_BASE_FACT_LABEL.CURRENT_WORKTREE, checklist.currentWorktreePath),\n renderFactLine(HANDOFF_BASE_FACT_LABEL.MAIN_CHECKOUT, checklist.mainCheckoutPath),\n ...checklist.prerequisites.map(renderPrerequisiteLine),\n ].join(\"\\n\");\n}\n","/**\n * Session-specific error types.\n *\n * @module session/errors\n */\n\nimport { type HandoffBaseChecklist, SESSION_HANDOFF_BASE_ERROR_NAME } from \"./handoff-base-checklist\";\n\n/**\n * Base class for session errors.\n */\nexport class SessionError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"SessionError\";\n }\n}\n\n/**\n * Error thrown when a session cannot be found.\n */\nexport class SessionNotFoundError extends SessionError {\n /** The session ID that was not found */\n readonly sessionId: string;\n\n constructor(sessionId: string) {\n super(`Session not found: ${sessionId}. Check the session ID and try again.`);\n this.name = \"SessionNotFoundError\";\n this.sessionId = sessionId;\n }\n}\n\n/**\n * Error thrown when a session is not available for claiming (already claimed).\n */\nexport class SessionNotAvailableError extends SessionError {\n /** The session ID that is not available */\n readonly sessionId: string;\n\n constructor(sessionId: string) {\n super(`Session not available: ${sessionId}. It may have been claimed by another agent.`);\n this.name = \"SessionNotAvailableError\";\n this.sessionId = sessionId;\n }\n}\n\n/**\n * Error thrown when session content is invalid.\n */\nexport class SessionInvalidContentError extends SessionError {\n constructor(reason: string) {\n super(`Invalid session content: ${reason}`);\n this.name = \"SessionInvalidContentError\";\n }\n}\n\n/**\n * Error thrown when handoff content has no usable goal.\n */\nexport class SessionInvalidGoalError extends SessionError {\n constructor() {\n super(\"Invalid session goal: goal must be a non-empty string.\");\n this.name = \"SessionInvalidGoalError\";\n }\n}\n\n/**\n * Error thrown when a `--fields` selection names a token outside the session\n * record field set. Carries the offending token and the valid field set so the\n * descriptor can render an actionable diagnostic.\n */\nexport class SessionInvalidFieldError extends SessionError {\n /** The unknown field token the caller supplied. */\n readonly field: string;\n /** The full set of valid field names. */\n readonly validFields: readonly string[];\n\n constructor(field: string, validFields: readonly string[]) {\n super(`Invalid field: \"${field}\". Valid fields: ${validFields.join(\", \")}`);\n this.name = \"SessionInvalidFieldError\";\n this.field = field;\n this.validFields = validFields;\n }\n}\n\n/**\n * Error thrown when handoff content has no usable next step.\n */\nexport class SessionInvalidNextStepError extends SessionError {\n constructor() {\n super(\"Invalid session next_step: next_step must be a non-empty string.\");\n this.name = \"SessionInvalidNextStepError\";\n }\n}\n\n/**\n * Error thrown when `spx session handoff` runs from a git work context that\n * cannot anchor a session to a base another agent can reach.\n *\n * Handoff is permitted from the main checkout (any reachable HEAD) or from a\n * non-main checkout that is clean and detached at the tip of `origin/<default\n * branch>`. A refusal renders one of three ways, distinguished by the carried\n * fields:\n *\n * - **Non-main-checkout refusal** carries a {@link HandoffBaseChecklist} the\n * descriptor renders to standard error.\n * - **Non-git base** is `silent` — the descriptor writes nothing, only the\n * non-zero exit.\n * - **Any other git refusal** (e.g. a main checkout with no reachable HEAD)\n * carries no checklist and is not silent, so the descriptor writes the message\n * as a plain diagnostic — only the non-git refusal is silent.\n */\nexport class SessionHandoffBaseError extends SessionError {\n /** The prerequisite checklist to render, or `null` for a non-checklist refusal. */\n readonly checklist: HandoffBaseChecklist | null;\n /** Whether the refusal surfaces no diagnostic — true only for a non-git base. */\n readonly silent: boolean;\n\n constructor(options: { checklist?: HandoffBaseChecklist | null; silent?: boolean } = {}) {\n super(\n \"Cannot create a handoff session from this git work context. Run handoff \"\n + \"from the main checkout, or from a non-main checkout with a clean working \"\n + \"tree detached at the tip of the default branch.\",\n );\n this.name = SESSION_HANDOFF_BASE_ERROR_NAME;\n this.checklist = options.checklist ?? null;\n this.silent = options.silent ?? false;\n }\n}\n\n/**\n * Error thrown when trying to release a session that is not currently claimed.\n */\nexport class SessionNotClaimedError extends SessionError {\n /** The session ID that is not claimed */\n readonly sessionId: string;\n\n constructor(sessionId: string) {\n super(`Session not claimed: ${sessionId}. The session is not in the doing directory.`);\n this.name = \"SessionNotClaimedError\";\n this.sessionId = sessionId;\n }\n}\n\n/**\n * Error thrown when no sessions are available for auto-pickup.\n */\nexport class NoSessionsAvailableError extends SessionError {\n constructor() {\n super(\"No sessions available. The todo directory is empty.\");\n this.name = \"NoSessionsAvailableError\";\n }\n}\n\n/**\n * Error thrown when handoff stdin opens with the legacy YAML-frontmatter\n * delimiter.\n *\n * `spx session handoff` accepts caller-supplied structured fields as a JSON\n * object at the start of stdin.\n * Input opening with `---\\n` is the legacy wire format that destroys caller\n * content for any string containing YAML-significant characters (`#`, `:` after\n * a space, leading whitespace) and is rejected with this error.\n */\nexport class SessionLegacyFrontmatterInputError extends SessionError {\n constructor() {\n super(\n \"Invalid handoff input: stdin opens with the YAML-frontmatter delimiter `---`. \"\n + \"Use the JSON-prefix wire format: a single JSON object holding caller-supplied \"\n + \"fields followed by the body bytes verbatim. Example:\\n\\n\"\n + \" printf '%s\\\\n' '{\\\"priority\\\":\\\"high\\\",\\\"goal\\\":\\\"...\\\",\\\"next_step\\\":\\\"...\\\"}' '# Body' \"\n + \"| spx session handoff\",\n );\n this.name = \"SessionLegacyFrontmatterInputError\";\n }\n}\n\n/**\n * Error thrown when `spx session handoff` is given an explicit work-branch ref\n * in its stdin JSON header but that branch does not exist on `origin`.\n *\n * The recorded `git_ref` must name a base a resuming agent can reach from the\n * shared queue; an origin branch satisfies that, an unpushed local name does\n * not. Push the branch to `origin`, or omit `git_ref` to record the git\n * context instead.\n */\nexport class SessionWorkBranchNotOnOriginError extends SessionError {\n /** The work-branch ref the caller supplied that does not resolve on `origin`. */\n readonly workBranch: string;\n\n constructor(workBranch: string) {\n super(\n `Work-branch ref not found on origin: ${workBranch}. Push the branch to origin `\n + \"before recording it as the handoff base, or omit git_ref to record the git context.\",\n );\n this.name = \"SessionWorkBranchNotOnOriginError\";\n this.workBranch = workBranch;\n }\n}\n\n/**\n * Error thrown when the JSON header at the start of handoff stdin is malformed\n * or fails schema validation.\n *\n * Raised by `parseHandoffInput` when stdin does not open with `{`, the opening\n * brace has no matching close, `JSON.parse` fails, or the parsed object does\n * not satisfy the caller-field schema.\n */\nexport class SessionInvalidJsonHeaderError extends SessionError {\n constructor(reason: string) {\n super(`Invalid JSON header for handoff: ${reason}`);\n this.name = \"SessionInvalidJsonHeaderError\";\n }\n}\n","/**\n * Session directory configuration resolution.\n *\n * Resolves session paths from the shared `.spx/sessions` scope the state module\n * provides, composing the status subdirectories from config, and surfaces the\n * non-git-repo diagnostic for a descriptor to write to stderr.\n *\n * @module commands/session/resolve-config\n */\n\nimport { join } from \"node:path\";\n\nimport { DEFAULT_CONFIG } from \"@/config/defaults\";\nimport { SessionDirectoryConfig } from \"@/domains/session/show\";\nimport { type GitDependencies } from \"@/git/root\";\nimport { resolveSessionsScopeDir } from \"@/lib/state-store\";\n\n/** Options for resolving session directory configuration. */\nexport interface ResolveSessionConfigOptions {\n /** Explicit sessions directory (overrides auto-detection). */\n sessionsDir?: string;\n /** Current working directory for git detection. */\n cwd?: string;\n /** Injectable git dependencies for testing. */\n deps?: GitDependencies;\n}\n\n/** Result of session config resolution. */\nexport interface ResolveSessionConfigResult {\n /** Resolved session directory configuration with absolute paths. */\n config: SessionDirectoryConfig;\n /** Warning message if not in a git repository. */\n warning?: string;\n}\n\n/**\n * Resolves session directory configuration. With an explicit `sessionsDir` the\n * provided directory is used and git detection is skipped; otherwise the shared\n * `.spx/sessions` scope is resolved through the state module's\n * {@link resolveSessionsScopeDir}. The status subdirectories are composed from\n * `DEFAULT_CONFIG.sessions.statusDirs`.\n */\nexport async function resolveSessionConfig(\n options: ResolveSessionConfigOptions = {},\n): Promise<ResolveSessionConfigResult> {\n const { sessionsDir, cwd, deps } = options;\n const { statusDirs } = DEFAULT_CONFIG.sessions;\n\n if (sessionsDir) {\n return {\n config: {\n todoDir: join(sessionsDir, statusDirs.todo),\n doingDir: join(sessionsDir, statusDirs.doing),\n archiveDir: join(sessionsDir, statusDirs.archive),\n },\n };\n }\n\n const { sessionsDir: baseDir, warning } = await resolveSessionsScopeDir({ cwd, deps });\n return {\n config: {\n todoDir: join(baseDir, statusDirs.todo),\n doingDir: join(baseDir, statusDirs.doing),\n archiveDir: join(baseDir, statusDirs.archive),\n },\n warning,\n };\n}\n\n/** Receives the non-git-repo diagnostic for a descriptor to write to stderr. */\nexport type SessionWarningHandler = (warning: string) => void;\n\n/**\n * Resolves the session directory configuration, forwarding the non-git-repo\n * diagnostic that resolution emits — when the working directory is outside a git\n * repository and session storage falls back to it — to `onWarning` so the\n * descriptor can surface it. Mirrors the spec commands' `onWarning` contract.\n *\n * @param sessionsDir - Explicit sessions directory, or undefined to auto-detect.\n * @param onWarning - Receives the diagnostic when config falls back outside a git repository.\n * @returns The resolved session directory configuration.\n */\nexport async function resolveSessionConfigSurfacingWarning(\n sessionsDir: string | undefined,\n onWarning?: SessionWarningHandler,\n): Promise<SessionDirectoryConfig> {\n const { config, warning } = await resolveSessionConfig({ sessionsDir });\n if (warning !== undefined) {\n onWarning?.(warning);\n }\n return config;\n}\n","/**\n * Default configuration for spx CLI\n *\n * This module defines the default directory structure and configuration\n * constants used throughout the spx CLI. All directory paths should reference\n * this configuration instead of using hardcoded strings.\n *\n * @module config/defaults\n */\n\n/**\n * Configuration schema for spx CLI directory structure\n */\nexport interface SpxConfig {\n /**\n * Session handoff files configuration\n */\n sessions: {\n /**\n * Status-based subdirectories for sessions\n */\n statusDirs: {\n /**\n * Available sessions directory\n * @default \"todo\"\n */\n todo: string;\n\n /**\n * Claimed sessions directory\n * @default \"doing\"\n */\n doing: string;\n\n /**\n * Archived sessions directory\n * @default \"archive\"\n */\n archive: string;\n };\n };\n}\n\n/**\n * Default configuration constant\n *\n * This is the embedded default configuration that spx uses when no\n * .spx/config.json file exists in the product.\n *\n * DO NOT modify this constant at runtime - it should remain immutable.\n */\nexport const DEFAULT_CONFIG = {\n sessions: {\n statusDirs: {\n todo: \"todo\",\n doing: \"doing\",\n archive: \"archive\",\n },\n },\n} as const satisfies SpxConfig;\n","/**\n * Session delete CLI command handler.\n *\n * @module commands/session/delete\n */\n\nimport { stat, unlink } from \"node:fs/promises\";\n\nimport { processBatch } from \"@/domains/session/batch\";\nimport { resolveDeletePath } from \"@/domains/session/delete\";\nimport { resolveSessionPaths, SessionDirectoryConfig } from \"@/domains/session/show\";\nimport { resolveSessionConfigSurfacingWarning, type SessionWarningHandler } from \"./resolve-config\";\n\nexport const SESSION_DELETE_OUTPUT = {\n DELETED: \"Deleted session\",\n} as const;\n\n/**\n * Options for the delete command.\n */\nexport interface DeleteOptions {\n /** Session ID(s) to delete */\n sessionIds: string[];\n /** Custom sessions directory */\n sessionsDir?: string;\n /** Receives the non-git-repo diagnostic for the descriptor to surface. */\n onWarning?: SessionWarningHandler;\n}\n\n/**\n * Checks which paths exist.\n */\nasync function findExistingPaths(paths: string[]): Promise<string[]> {\n const existing: string[] = [];\n\n for (const path of paths) {\n try {\n const stats = await stat(path);\n if (stats.isFile()) {\n existing.push(path);\n }\n } catch {\n // File doesn't exist, skip\n }\n }\n\n return existing;\n}\n\n/**\n * Executes the delete command.\n *\n * @param options - Command options\n * @returns Formatted output for display\n * @throws {SessionNotFoundError} When session not found\n */\n/**\n * Deletes a single session by ID.\n */\nasync function deleteSingle(\n sessionId: string,\n config: SessionDirectoryConfig,\n): Promise<string> {\n const paths = resolveSessionPaths(sessionId, config);\n const existingPaths = await findExistingPaths(paths);\n const pathToDelete = resolveDeletePath(sessionId, existingPaths);\n await unlink(pathToDelete);\n return `${SESSION_DELETE_OUTPUT.DELETED}: ${sessionId}`;\n}\n\n/**\n * Executes the delete command for one or more session IDs.\n *\n * @param options - Command options with one or more session IDs\n * @returns Formatted output for display\n * @throws {BatchError} When one or more IDs fail\n * @throws {SessionNotFoundError} When session not found (single ID)\n */\nexport async function deleteCommand(options: DeleteOptions): Promise<string> {\n const config = await resolveSessionConfigSurfacingWarning(options.sessionsDir, options.onWarning);\n\n return processBatch(options.sessionIds, (id) => deleteSingle(id, config));\n}\n","/**\n * Session deletion utilities.\n *\n * @module session/delete\n */\n\nimport { SessionNotFoundError } from \"./errors\";\n\n/**\n * Resolves the path to delete for a session ID.\n *\n * Given a session ID and a list of existing paths (checked by caller),\n * returns the first path that contains the session ID.\n *\n * @param sessionId - Session ID to find\n * @param existingPaths - Paths that were found to exist\n * @returns The path to the session file\n * @throws {SessionNotFoundError} When session is not found in any directory\n *\n * @example\n * ```typescript\n * // Caller checks which paths exist, passes only existing ones\n * const existingPaths = ['.spx/sessions/doing/2026-01-13_08-01-05.md'];\n * const path = resolveDeletePath('2026-01-13_08-01-05', existingPaths);\n * // => '.spx/sessions/doing/2026-01-13_08-01-05.md'\n * ```\n */\nexport function resolveDeletePath(\n sessionId: string,\n existingPaths: string[],\n): string {\n // Find the first existing path that matches the session ID\n const matchingPath = existingPaths.find((path) => path.includes(sessionId));\n\n if (!matchingPath) {\n throw new SessionNotFoundError(sessionId);\n }\n\n return matchingPath;\n}\n","/**\n * Session display utilities for showing session content without claiming.\n *\n * @module session/show\n */\n\nimport { join } from \"node:path\";\n\nimport { DEFAULT_CONFIG } from \"@/config/defaults\";\nimport { STATE_STORE_PATH } from \"@/lib/state-store\";\nimport { parseSessionMetadata } from \"./list\";\nimport { SESSION_STATUSES, type SessionStatus } from \"./types\";\n\nexport const SESSION_SHOW_LABEL = {\n STATUS: \"Status\",\n PRIORITY: \"Priority\",\n GIT_REF: \"Git ref\",\n GOAL: \"Goal\",\n NEXT_STEP: \"Next step\",\n CREATED: \"Created\",\n AGENT_SESSION: \"Agent session\",\n} as const;\n\nexport const SESSION_SHOW_SEPARATOR_CHAR = \"─\";\nexport const SESSION_SHOW_SEPARATOR_WIDTH = 40;\n\n/**\n * Configuration for session directory paths.\n */\nexport interface SessionDirectoryConfig {\n /** Path to todo directory */\n todoDir: string;\n /** Path to doing directory */\n doingDir: string;\n /** Path to archive directory */\n archiveDir: string;\n}\n\n/**\n * Default session directory configuration.\n *\n * The `.spx/sessions` base derives from the state module's path tokens, which own\n * the `.spx/` layout; the status-directory names derive from DEFAULT_CONFIG. NEVER\n * hardcode these path components - always derive them from their owning source.\n */\nconst sessionsBaseDir = join(STATE_STORE_PATH.SPX_DIR, STATE_STORE_PATH.SESSIONS_SCOPE);\nconst { statusDirs } = DEFAULT_CONFIG.sessions;\n\nexport const DEFAULT_SESSION_CONFIG: SessionDirectoryConfig = {\n todoDir: join(sessionsBaseDir, statusDirs.todo),\n doingDir: join(sessionsBaseDir, statusDirs.doing),\n archiveDir: join(sessionsBaseDir, statusDirs.archive),\n};\n\n/**\n * Order to search directories (matches priority: todo first, then doing, then archive).\n * Derived from SESSION_STATUSES to maintain a single source of truth.\n */\nexport const SEARCH_ORDER: SessionStatus[] = [...SESSION_STATUSES];\n\n/**\n * Options for formatting show output.\n */\nexport interface ShowOutputOptions {\n /** Current status of the session */\n status: SessionStatus;\n}\n\n/**\n * Resolves possible file paths for a session ID across all status directories.\n *\n * @param id - Session ID (timestamp format)\n * @param config - Directory configuration\n * @returns Array of possible file paths in search order\n *\n * @example\n * ```typescript\n * const paths = resolveSessionPaths('2026-01-13_08-01-05', {\n * todoDir: '.spx/sessions/todo',\n * doingDir: '.spx/sessions/doing',\n * archiveDir: '.spx/sessions/archive',\n * });\n * // => [\n * // '.spx/sessions/todo/2026-01-13_08-01-05.md',\n * // '.spx/sessions/doing/2026-01-13_08-01-05.md',\n * // '.spx/sessions/archive/2026-01-13_08-01-05.md',\n * // ]\n * ```\n */\nexport function resolveSessionPaths(\n id: string,\n config: SessionDirectoryConfig = DEFAULT_SESSION_CONFIG,\n): string[] {\n const filename = `${id}.md`;\n\n return [\n `${config.todoDir}/${filename}`,\n `${config.doingDir}/${filename}`,\n `${config.archiveDir}/${filename}`,\n ];\n}\n\n/**\n * Formats session content for display with metadata header.\n *\n * @param content - Raw session file content\n * @param options - Display options including status\n * @returns Formatted output string with metadata header\n *\n * @example\n * ```typescript\n * const output = formatShowOutput(sessionContent, { status: 'todo' });\n * // => \"Status: todo\\nPriority: high\\n---\\n# Session Content...\"\n * ```\n */\nexport function formatShowOutput(\n content: string,\n options: ShowOutputOptions,\n): string {\n const metadata = parseSessionMetadata(content);\n\n // Build header with extracted metadata\n const headerLines: string[] = [\n `${SESSION_SHOW_LABEL.STATUS}: ${options.status}`,\n `${SESSION_SHOW_LABEL.PRIORITY}: ${metadata.priority}`,\n `${SESSION_SHOW_LABEL.GIT_REF}: ${metadata.git_ref}`,\n `${SESSION_SHOW_LABEL.GOAL}: ${metadata.goal}`,\n `${SESSION_SHOW_LABEL.NEXT_STEP}: ${metadata.next_step}`,\n `${SESSION_SHOW_LABEL.CREATED}: ${metadata.created_at ?? \"\"}`,\n `${SESSION_SHOW_LABEL.AGENT_SESSION}: ${metadata.agent_session_id ?? \"\"}`,\n ];\n\n // Combine header with separator and original content\n const header = headerLines.join(\"\\n\");\n const separator = \"\\n\" + SESSION_SHOW_SEPARATOR_CHAR.repeat(SESSION_SHOW_SEPARATOR_WIDTH) + \"\\n\\n\";\n\n return header + separator + content;\n}\n","/**\n * Session listing and sorting utilities.\n *\n * @module session/list\n */\n\nimport { parse as parseYaml } from \"yaml\";\n\nimport { SessionInvalidFieldError } from \"./errors\";\nimport { parseSessionId } from \"./timestamp\";\nimport {\n DEFAULT_PRIORITY,\n PRIORITY_ORDER,\n type Session,\n SESSION_FRONT_MATTER,\n SESSION_PRIORITY,\n type SessionMetadata,\n type SessionPriority,\n type SessionStatus,\n} from \"./types\";\n\n/**\n * Regular expression to match YAML front matter.\n * Matches content between opening `---` and closing `---` or `...`\n */\nconst FRONT_MATTER_PATTERN = /^---\\r?\\n([\\s\\S]*?)\\r?\\n(?:---|\\.\\.\\.)\\r?\\n?/;\nconst SESSION_PRIORITY_VALUES = Object.values(SESSION_PRIORITY);\n\nexport const DEFAULT_SESSION_METADATA: SessionMetadata = {\n priority: DEFAULT_PRIORITY,\n git_ref: \"\",\n goal: \"\",\n next_step: \"\",\n specs: [],\n files: [],\n} as const;\n\nfunction defaultSessionMetadata(): SessionMetadata {\n return {\n ...DEFAULT_SESSION_METADATA,\n specs: [],\n files: [],\n };\n}\n\n/**\n * Validates if a value is a valid priority.\n */\nfunction isValidPriority(value: unknown): value is SessionPriority {\n return typeof value === \"string\" && SESSION_PRIORITY_VALUES.some((priority) => priority === value);\n}\n\n/**\n * Parses YAML front matter from session content to extract metadata.\n *\n * @param content - Full session file content\n * @returns Extracted metadata with defaults for missing fields\n *\n * @example\n * ```typescript\n * const metadata = parseSessionMetadata(`---\n * priority: high\n * goal: Fix failing checks\n * next_step: Run validation\n * ---\n * # Session content`);\n * // => { priority: 'high', goal: 'Fix failing checks', next_step: 'Run validation', ... }\n * ```\n */\nexport function parseSessionMetadata(content: string): SessionMetadata {\n const match = FRONT_MATTER_PATTERN.exec(content);\n\n if (!match) {\n return defaultSessionMetadata();\n }\n\n try {\n const parsed = parseYaml(match[1]) as Record<string, unknown>;\n\n if (!parsed || typeof parsed !== \"object\") {\n return defaultSessionMetadata();\n }\n\n const rawPriority = parsed[SESSION_FRONT_MATTER.PRIORITY];\n const priority = isValidPriority(rawPriority) ? rawPriority : DEFAULT_PRIORITY;\n\n const metadata: SessionMetadata = {\n ...defaultSessionMetadata(),\n priority,\n };\n\n const gitRef = parsed[SESSION_FRONT_MATTER.GIT_REF];\n metadata.git_ref = typeof gitRef === \"string\" ? gitRef : DEFAULT_SESSION_METADATA.git_ref;\n\n const goal = parsed[SESSION_FRONT_MATTER.GOAL];\n metadata.goal = typeof goal === \"string\" ? goal : DEFAULT_SESSION_METADATA.goal;\n\n const nextStep = parsed[SESSION_FRONT_MATTER.NEXT_STEP];\n metadata.next_step = typeof nextStep === \"string\" ? nextStep : DEFAULT_SESSION_METADATA.next_step;\n\n const createdAt = parsed[SESSION_FRONT_MATTER.CREATED_AT];\n if (typeof createdAt === \"string\") metadata.created_at = createdAt;\n\n const agentSessionId = parsed[SESSION_FRONT_MATTER.AGENT_SESSION_ID];\n if (typeof agentSessionId === \"string\") metadata.agent_session_id = agentSessionId;\n\n const specs = parsed[SESSION_FRONT_MATTER.SPECS];\n if (Array.isArray(specs)) {\n metadata.specs = specs.filter((s): s is string => typeof s === \"string\");\n }\n\n const files = parsed[SESSION_FRONT_MATTER.FILES];\n if (Array.isArray(files)) {\n metadata.files = files.filter((f): f is string => typeof f === \"string\");\n }\n\n return metadata;\n } catch {\n // Malformed YAML, return defaults\n return defaultSessionMetadata();\n }\n}\n\n/**\n * Sorts sessions by priority (high first) then by timestamp (newest first).\n *\n * @param sessions - Array of sessions to sort\n * @returns New sorted array (does not mutate input)\n *\n * @example\n * ```typescript\n * const sorted = sortSessions([\n * { id: 'a', metadata: { priority: 'low' } },\n * { id: 'b', metadata: { priority: 'high' } },\n * ]);\n * // => [{ id: 'b', ... }, { id: 'a', ... }]\n * ```\n */\nexport function sortSessions(sessions: Session[]): Session[] {\n return [...sessions].sort((a, b) => {\n // First: sort by priority (high = 0, medium = 1, low = 2)\n const priorityA = PRIORITY_ORDER[a.metadata.priority];\n const priorityB = PRIORITY_ORDER[b.metadata.priority];\n\n if (priorityA !== priorityB) {\n return priorityA - priorityB;\n }\n\n // Second: sort by timestamp (newest first = descending)\n const dateA = parseSessionId(a.id);\n const dateB = parseSessionId(b.id);\n\n // Handle invalid session IDs by treating them as oldest\n if (!dateA && !dateB) return 0;\n if (!dateA) return 1; // a goes after b\n if (!dateB) return -1; // b goes after a\n\n return dateB.getTime() - dateA.getTime();\n });\n}\n\n/** Separator between field names in a `--fields` selection string. */\nexport const FIELD_SELECTION_SEPARATOR = \",\";\n\n/**\n * The projectable fields of a session record: `id` and `status` (the record-only\n * keys) plus every frontmatter key of `SESSION_FRONT_MATTER`. Each frontmatter\n * key is referenced from the registry so the selectable namespace stays tied to\n * one runtime source of truth. The order matches `toSessionRecord`'s key order\n * — required fields first, the two optional fields last — so selecting every\n * field reproduces the full record's key order exactly.\n */\nexport const SESSION_RECORD_FIELD = {\n ID: \"id\",\n STATUS: \"status\",\n PRIORITY: SESSION_FRONT_MATTER.PRIORITY,\n GIT_REF: SESSION_FRONT_MATTER.GIT_REF,\n GOAL: SESSION_FRONT_MATTER.GOAL,\n NEXT_STEP: SESSION_FRONT_MATTER.NEXT_STEP,\n SPECS: SESSION_FRONT_MATTER.SPECS,\n FILES: SESSION_FRONT_MATTER.FILES,\n CREATED_AT: SESSION_FRONT_MATTER.CREATED_AT,\n AGENT_SESSION_ID: SESSION_FRONT_MATTER.AGENT_SESSION_ID,\n} as const satisfies Record<string, keyof SessionRecord>;\n\nexport type SessionRecordField = (typeof SESSION_RECORD_FIELD)[keyof typeof SESSION_RECORD_FIELD];\n\n/** Every valid session-record field name, in registry order. */\nexport const SESSION_RECORD_FIELDS: readonly SessionRecordField[] = Object.values(SESSION_RECORD_FIELD);\n\n/**\n * Flat per-session record emitted by the JSON list output: `id` and `status`\n * alongside the frontmatter fields, with no absolute file path. Optional fields\n * are present only when the session carries them.\n */\nexport interface SessionRecord {\n id: string;\n status: SessionStatus;\n priority: SessionPriority;\n git_ref: string;\n goal: string;\n next_step: string;\n specs: string[];\n files: string[];\n created_at?: string;\n agent_session_id?: string;\n}\n\n/**\n * Flattens a session into its JSON record — `id` and `status` hoisted alongside\n * the metadata fields, with the absolute path dropped. Optional fields appear\n * only when the session's metadata carries them.\n *\n * @param session - The session to flatten\n * @returns The flat session record\n */\nexport function toSessionRecord(session: Session): SessionRecord {\n const { id, status, metadata } = session;\n const record: SessionRecord = {\n id,\n status,\n priority: metadata.priority,\n git_ref: metadata.git_ref,\n goal: metadata.goal,\n next_step: metadata.next_step,\n specs: metadata.specs,\n files: metadata.files,\n };\n if (metadata.created_at !== undefined) {\n record.created_at = metadata.created_at;\n }\n if (metadata.agent_session_id !== undefined) {\n record.agent_session_id = metadata.agent_session_id;\n }\n return record;\n}\n\n/**\n * Projects a session record to only the named fields, in the order named. A\n * named field whose value is absent on the record is omitted.\n *\n * @param record - The session record to project\n * @param fields - The fields to retain, in output order\n * @returns A record carrying only the selected, present fields\n */\nexport function projectSessionRecord(\n record: SessionRecord,\n fields: readonly SessionRecordField[],\n): Record<string, unknown> {\n const projected: Record<string, unknown> = {};\n for (const field of fields) {\n const value = record[field];\n if (value !== undefined) {\n projected[field] = value;\n }\n }\n return projected;\n}\n\n/**\n * Type guard: whether a string is a valid session-record field name.\n */\nfunction isSessionRecordField(value: string): value is SessionRecordField {\n return (SESSION_RECORD_FIELDS as readonly string[]).includes(value);\n}\n\n/**\n * Parses a comma-separated `--fields` selection into validated field names,\n * preserving order. Throws `SessionInvalidFieldError` for any token outside the\n * session-record field set, and for a selection that names no field at all (an\n * empty value or one of only separators) — an empty selection would otherwise\n * silently emit fieldless records.\n *\n * @param input - The raw `--fields` value\n * @returns The validated field selection, in the order named\n * @throws SessionInvalidFieldError when a token is not a valid field name, or when the selection names no field\n */\nexport function parseFieldSelection(input: string): SessionRecordField[] {\n const tokens = input\n .split(FIELD_SELECTION_SEPARATOR)\n .map((token) => token.trim())\n .filter((token) => token.length > 0);\n\n if (tokens.length === 0) {\n throw new SessionInvalidFieldError(input, SESSION_RECORD_FIELDS);\n }\n\n const selection: SessionRecordField[] = [];\n for (const token of tokens) {\n if (!isSessionRecordField(token)) {\n throw new SessionInvalidFieldError(token, SESSION_RECORD_FIELDS);\n }\n selection.push(token);\n }\n return selection;\n}\n","/**\n * Session timestamp utilities for generating and parsing session IDs.\n *\n * Session IDs use the format YYYY-MM-DD_HH-mm-ss.\n *\n * @module session/timestamp\n */\n\n/**\n * Regular expression pattern for validating session IDs.\n * Format: YYYY-MM-DD_HH-mm-ss (all components zero-padded)\n *\n * Exported for use in validation and testing.\n */\nexport const SESSION_ID_PATTERN = /^(\\d{4})-(\\d{2})-(\\d{2})_(\\d{2})-(\\d{2})-(\\d{2})$/;\n\n/**\n * Separator between date and time components in session IDs.\n */\nexport const SESSION_ID_SEPARATOR = \"_\";\n\n/**\n * Options for generating session IDs.\n */\nexport interface GenerateSessionIdOptions {\n /**\n * Function that returns the current time.\n * Defaults to `() => new Date()` for production use.\n * Injectable for deterministic testing.\n */\n now?: () => Date;\n}\n\n/**\n * Generates a session ID from the current (or injected) time.\n *\n * @param options - Optional configuration including time source\n * @returns Session ID in format YYYY-MM-DD_HH-mm-ss\n *\n * @example\n * ```typescript\n * // Production usage\n * const id = generateSessionId();\n * // => \"2026-01-13_08-01-05\"\n *\n * // Testing with injected time\n * const id = generateSessionId({ now: () => new Date('2026-01-13T08:01:05Z') });\n * // => \"2026-01-13_08-01-05\"\n * ```\n */\nexport function generateSessionId(options: GenerateSessionIdOptions = {}): string {\n const now = options.now ?? (() => new Date());\n const date = now();\n\n const year = date.getUTCFullYear();\n const month = String(date.getUTCMonth() + 1).padStart(2, \"0\");\n const day = String(date.getUTCDate()).padStart(2, \"0\");\n const hours = String(date.getUTCHours()).padStart(2, \"0\");\n const minutes = String(date.getUTCMinutes()).padStart(2, \"0\");\n const seconds = String(date.getUTCSeconds()).padStart(2, \"0\");\n\n return `${year}-${month}-${day}${SESSION_ID_SEPARATOR}${hours}-${minutes}-${seconds}`;\n}\n\n/**\n * Parses a session ID string back into a Date object.\n *\n * @param id - Session ID string to parse\n * @returns Date object if valid, null if invalid format\n *\n * @example\n * ```typescript\n * const date = parseSessionId('2026-01-13_08-01-05');\n * // => Date representing 2026-01-13T08:01:05Z\n *\n * const invalid = parseSessionId('invalid-format');\n * // => null\n * ```\n */\nexport function parseSessionId(id: string): Date | null {\n const match = SESSION_ID_PATTERN.exec(id);\n\n if (!match) {\n return null;\n }\n\n const [, yearStr, monthStr, dayStr, hoursStr, minutesStr, secondsStr] = match;\n\n const year = parseInt(yearStr, 10);\n const month = parseInt(monthStr, 10) - 1; // Date months are 0-indexed\n const day = parseInt(dayStr, 10);\n const hours = parseInt(hoursStr, 10);\n const minutes = parseInt(minutesStr, 10);\n const seconds = parseInt(secondsStr, 10);\n\n // Validate component ranges\n if (month < 0 || month > 11) return null;\n if (day < 1 || day > 31) return null;\n if (hours < 0 || hours > 23) return null;\n if (minutes < 0 || minutes > 59) return null;\n if (seconds < 0 || seconds > 59) return null;\n\n const date = new Date(Date.UTC(year, month, day, hours, minutes, seconds));\n if (\n date.getUTCFullYear() !== year\n || date.getUTCMonth() !== month\n || date.getUTCDate() !== day\n || date.getUTCHours() !== hours\n || date.getUTCMinutes() !== minutes\n || date.getUTCSeconds() !== seconds\n ) {\n return null;\n }\n\n return date;\n}\n","/**\n * Session type definitions for the session management domain.\n *\n * @module session/types\n */\n\n/**\n * Priority levels for session ordering.\n * Sessions are sorted: high → medium → low\n */\nexport const SESSION_PRIORITY = {\n HIGH: \"high\",\n MEDIUM: \"medium\",\n LOW: \"low\",\n} as const;\n\nexport type SessionPriority = (typeof SESSION_PRIORITY)[keyof typeof SESSION_PRIORITY];\n\n/**\n * All valid session statuses, derived from directory structure.\n * This is the single source of truth — SessionStatus type derives from it.\n */\nexport const SESSION_STATUSES = [\"todo\", \"doing\", \"archive\"] as const;\n\n/**\n * Status derived from directory location.\n */\nexport type SessionStatus = (typeof SESSION_STATUSES)[number];\n\n/**\n * Default statuses shown by `spx session list` when no --status filter is provided.\n * Excludes archive — use `--status archive` to see archived sessions.\n */\nexport const DEFAULT_LIST_STATUSES: readonly SessionStatus[] = [\"doing\", \"todo\"] as const;\n\n/**\n * Priority sort order (lower number = higher priority).\n */\nexport const PRIORITY_ORDER: Record<SessionPriority, number> = {\n [SESSION_PRIORITY.HIGH]: 0,\n [SESSION_PRIORITY.MEDIUM]: 1,\n [SESSION_PRIORITY.LOW]: 2,\n} as const;\n\n/**\n * Default priority when not specified in YAML front matter.\n */\nexport const DEFAULT_PRIORITY: SessionPriority = SESSION_PRIORITY.MEDIUM;\n\n/**\n * YAML front matter keys for session files.\n * Single source of truth for the serialized session schema.\n */\nexport const SESSION_FRONT_MATTER = {\n PRIORITY: \"priority\",\n GIT_REF: \"git_ref\",\n GOAL: \"goal\",\n NEXT_STEP: \"next_step\",\n CREATED_AT: \"created_at\",\n AGENT_SESSION_ID: \"agent_session_id\",\n SPECS: \"specs\",\n FILES: \"files\",\n} as const;\n\n/**\n * Metadata extracted from session YAML front matter.\n */\nexport interface SessionMetadata {\n /** Priority level for sorting */\n priority: SessionPriority;\n /** Git ref the session was cut from — a branch name (main checkout on a branch) or a commit SHA (detached) */\n git_ref: string;\n /** Handoff goal */\n goal: string;\n /** First action for the next agent */\n next_step: string;\n /** Spec files to auto-inject on pickup */\n specs: string[];\n /** Code files to auto-inject on pickup */\n files: string[];\n /** ISO 8601 timestamp when session was created */\n created_at?: string;\n /** Agent session ID from CLAUDE_SESSION_ID or CODEX_THREAD_ID at handoff time */\n agent_session_id?: string;\n}\n\n/**\n * Complete session information including status and metadata.\n */\nexport interface Session {\n /** Session ID (timestamp format: YYYY-MM-DD_HH-mm-ss) */\n id: string;\n /** Status derived from directory location */\n status: SessionStatus;\n /** Metadata from YAML front matter */\n metadata: SessionMetadata;\n /** Full path to session file */\n path: string;\n}\n","/**\n * Session handoff CLI command handler.\n *\n * Creates a new session for handoff to another agent context. Caller-supplied\n * structured fields come from a JSON object at the start of stdin; the body is\n * the remaining bytes verbatim. The on-disk file format remains YAML\n * frontmatter + markdown body, written through the `yaml` package's\n * `stringify`.\n *\n * @module commands/session/handoff\n */\n\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport { join, resolve } from \"node:path\";\n\nimport { stringify as stringifyYaml } from \"yaml\";\n\nimport { type AgentSessionEnvironment, resolveAgentSessionId } from \"@/domains/session/agent-session\";\nimport { SESSION_FRONT_MATTER_CLOSE, SESSION_FRONT_MATTER_OPEN } from \"@/domains/session/create\";\nimport {\n SessionInvalidContentError,\n SessionInvalidGoalError,\n SessionInvalidNextStepError,\n} from \"@/domains/session/errors\";\nimport { resolveHandoffGitRef, resolveWorkBranchGitRef } from \"@/domains/session/handoff-base\";\nimport { parseHandoffInput } from \"@/domains/session/parse-handoff-input\";\nimport { generateSessionId } from \"@/domains/session/timestamp\";\nimport { SESSION_FRONT_MATTER } from \"@/domains/session/types\";\nimport {\n gatherGitFacts,\n getCurrentBranch,\n getHeadSha,\n type GitDependencies,\n isMainCheckout,\n isWorkingTreeClean,\n mainCheckoutPath,\n ORIGIN_REF_PREFIX,\n originBranchExists,\n resolveDefaultBranch,\n resolveRefSha,\n} from \"@/git/root\";\nimport { resolveSessionConfig } from \"./resolve-config\";\n\n/**\n * Options for the handoff command.\n */\nexport interface HandoffOptions {\n /** Session content from stdin. */\n content?: string;\n /** Custom sessions directory */\n sessionsDir?: string;\n /** Current working directory for Git context detection */\n cwd?: string;\n /** Injectable Git command dependencies for tests */\n deps?: GitDependencies;\n /** Environment values used to prefill agent identity */\n env?: AgentSessionEnvironment;\n}\n\n/**\n * Result of the handoff command. The descriptor writes `output` to stdout. The\n * handler does not touch process streams.\n */\nexport interface HandoffResult {\n /** Stdout text including `<HANDOFF_ID>` and `<SESSION_FILE>` tags. */\n output: string;\n}\n\n/**\n * Gathers every git fact the handoff-base gate evaluates (I/O), then resolves\n * the git ref to record. Every fact a non-main-checkout refusal checklist renders\n * is gathered regardless of branch state, so the resolver evaluates every base\n * prerequisite and surfaces it — never short-circuiting on an earlier fact.\n */\nasync function resolveSessionGitRef(\n cwd: string | undefined,\n deps: GitDependencies | undefined,\n): Promise<string> {\n const [branch, headSha, facts] = await Promise.all([\n getCurrentBranch(cwd, deps),\n getHeadSha(cwd, deps),\n gatherGitFacts(cwd, deps),\n ]);\n\n // The probe reads the worktree root once and returns the facts the main-checkout\n // classifier needs, so the worktree path and the main-checkout verdict and path\n // compose from one read.\n const isGitRepo = facts !== null;\n const currentWorktreePath = facts?.worktreeRoot ?? cwd ?? process.cwd();\n const isMain = facts !== null && isMainCheckout(facts);\n // The main checkout is where a resuming agent reaches the base; null when none is\n // designable (e.g. a pool whose origin resolves no repository name), which the\n // refusal checklist renders as \"unresolved\" rather than echoing the current worktree.\n const designatedMainCheckout = facts !== null ? mainCheckoutPath(facts) : null;\n\n // The clean-tree and origin facts feed only the non-main-checkout refusal\n // checklist; the main checkout (permitted regardless of HEAD state) and a non-git\n // base never consult them, so gather them only for a non-main worktree in a git\n // repository. Every non-main worktree — detached or on a branch — still gathers\n // all of them, so the resolver evaluates every prerequisite.\n let isClean = false;\n let defaultBranch: string | null = null;\n let defaultTipSha: string | null = null;\n if (isGitRepo && !isMain) {\n [isClean, defaultBranch] = await Promise.all([\n isWorkingTreeClean(cwd, deps),\n resolveDefaultBranch(cwd, deps),\n ]);\n defaultTipSha = defaultBranch === null\n ? null\n : await resolveRefSha(`${ORIGIN_REF_PREFIX}${defaultBranch}`, cwd, deps);\n }\n\n return resolveHandoffGitRef({\n isGitRepo,\n isMainCheckout: isMain,\n branch,\n headSha,\n isClean,\n defaultBranch,\n defaultTipSha,\n currentWorktreePath,\n mainCheckoutPath: designatedMainCheckout,\n });\n}\n\n/**\n * Resolves the `git_ref` to record. When the caller supplies an explicit\n * work-branch ref, probes `origin/<ref>` and records the ref once the branch is\n * confirmed on `origin` (throwing {@link SessionWorkBranchNotOnOriginError}\n * otherwise); when no ref is supplied, records the gate-derived base unchanged.\n *\n * An absent or empty ref is \"no ref supplied\" — the gate-derived base is\n * recorded and no origin probe runs, so the common handoff issues no extra git\n * call. The handoff-base gate has already validated the running worktree before\n * this point, so an explicit ref changes only what is recorded, never whether\n * the handoff is permitted.\n */\nasync function resolveRecordedGitRef(\n suppliedRef: string | undefined,\n gateRef: string,\n cwd: string | undefined,\n deps: GitDependencies | undefined,\n): Promise<string> {\n if (suppliedRef === undefined || suppliedRef.length === 0) return gateRef;\n const existsOnOrigin = await originBranchExists(suppliedRef, cwd, deps);\n return resolveWorkBranchGitRef(suppliedRef, existsOnOrigin);\n}\n\n/**\n * Executes the handoff command.\n *\n * Creates a new session in the todo directory for pickup by another context.\n * Output includes `<HANDOFF_ID>` and `<SESSION_FILE>` tags for parsing by\n * automation tools.\n *\n * Caller-supplied structured fields come from a JSON object at the start of\n * stdin; bytes after the JSON object form the markdown body verbatim. The\n * CLI prefills `created_at` from the system clock and `agent_session_id` from\n * `$CLAUDE_SESSION_ID` (falling back to `$CODEX_THREAD_ID`). `git_ref` is the\n * gate-derived base (branch name in the main checkout on a branch, HEAD SHA\n * when detached, or the `origin/<default>` tip SHA in a clean detached non-main\n * checkout), overridden by an explicit work-branch ref the caller supplies in\n * the header once the command confirms that branch exists on `origin`. The\n * handoff-base gate is enforced first regardless, so an explicit ref changes\n * only what is recorded, never whether the handoff is permitted.\n *\n * Canonical invocation:\n *\n * printf '%s\\n' '{\"priority\":\"high\",\"goal\":\"...\",\"next_step\":\"...\"}' '# Body' | spx session handoff\n *\n * @param options - Command options\n * @returns A `HandoffResult` whose `output` carries the `<HANDOFF_ID>` and\n * `<SESSION_FILE>` tags for the descriptor to write to stdout.\n * @throws {SessionInvalidContentError} When stdin is empty or whitespace-only\n * @throws {SessionLegacyFrontmatterInputError} When stdin opens with `---\\n`\n * @throws {SessionInvalidJsonHeaderError} When the JSON header is malformed\n * or fails caller-field schema validation\n * @throws {SessionInvalidGoalError} When the parsed `goal` is empty\n * @throws {SessionInvalidNextStepError} When the parsed `next_step` is empty\n * @throws {SessionHandoffBaseError} When the git work context cannot anchor a base\n * @throws {SessionWorkBranchNotOnOriginError} When the caller-supplied\n * work-branch ref does not exist on `origin`\n */\nexport async function handoffCommand(options: HandoffOptions): Promise<HandoffResult> {\n const { config } = await resolveSessionConfig({\n sessionsDir: options.sessionsDir,\n cwd: options.cwd,\n deps: options.deps,\n });\n\n const content = options.content;\n if (content === undefined || content.trim().length === 0) {\n throw new SessionInvalidContentError(\"Session content cannot be empty\");\n }\n\n const { header, body } = parseHandoffInput(content);\n\n if (header.goal.length === 0) {\n throw new SessionInvalidGoalError();\n }\n if (header.next_step.length === 0) {\n throw new SessionInvalidNextStepError();\n }\n\n const gateRef = await resolveSessionGitRef(options.cwd, options.deps);\n const gitRef = await resolveRecordedGitRef(header.git_ref, gateRef, options.cwd, options.deps);\n\n const sessionId = generateSessionId();\n const agentSessionId = resolveAgentSessionId(options.env ?? process.env);\n const createdAt = new Date().toISOString();\n\n const frontMatterObject: Record<string, unknown> = {\n [SESSION_FRONT_MATTER.PRIORITY]: header.priority,\n [SESSION_FRONT_MATTER.CREATED_AT]: createdAt,\n [SESSION_FRONT_MATTER.GIT_REF]: gitRef,\n [SESSION_FRONT_MATTER.GOAL]: header.goal,\n [SESSION_FRONT_MATTER.NEXT_STEP]: header.next_step,\n [SESSION_FRONT_MATTER.SPECS]: [...header.specs],\n [SESSION_FRONT_MATTER.FILES]: [...header.files],\n };\n if (agentSessionId !== undefined) {\n frontMatterObject[SESSION_FRONT_MATTER.AGENT_SESSION_ID] = agentSessionId;\n }\n\n const yaml = stringifyYaml(frontMatterObject, { defaultStringType: \"QUOTE_DOUBLE\" }).trimEnd();\n const fullContent = `${SESSION_FRONT_MATTER_OPEN}${yaml}${SESSION_FRONT_MATTER_CLOSE}${body}`;\n\n const filename = `${sessionId}.md`;\n const sessionPath = join(config.todoDir, filename);\n const absolutePath = resolve(sessionPath);\n\n await mkdir(config.todoDir, { recursive: true });\n await writeFile(sessionPath, fullContent, \"utf-8\");\n\n const output =\n `Created handoff session <HANDOFF_ID>${sessionId}</HANDOFF_ID>\\n<SESSION_FILE>${absolutePath}</SESSION_FILE>`;\n return { output };\n}\n","/**\n * Session creation utilities — YAML frontmatter delimiters and the\n * `stringifySessionFrontMatter` writer used by `spx session handoff` and the\n * session test harness.\n *\n * The JSON-prefix input wire format is parsed by\n * `src/domains/session/parse-handoff-input.ts`; this module is responsible\n * only for emitting the on-disk YAML frontmatter shape.\n *\n * @module session/create\n */\n\nimport { stringify as stringifyYaml } from \"yaml\";\n\nimport { SESSION_FRONT_MATTER, type SessionPriority } from \"./types\";\n\nexport const SESSION_FRONT_MATTER_DELIMITER = \"---\";\nexport const SESSION_FRONT_MATTER_OPEN = `${SESSION_FRONT_MATTER_DELIMITER}\\n`;\nexport const SESSION_FRONT_MATTER_CLOSE = `\\n${SESSION_FRONT_MATTER_DELIMITER}\\n`;\n\nexport interface SessionFrontMatterInput {\n readonly priority: SessionPriority;\n readonly git_ref?: string;\n readonly goal: string;\n readonly next_step: string;\n readonly specs?: readonly string[];\n readonly files?: readonly string[];\n}\n\nexport function stringifySessionFrontMatter(input: SessionFrontMatterInput): string {\n return stringifyYaml({\n [SESSION_FRONT_MATTER.PRIORITY]: input.priority,\n ...(input.git_ref === undefined ? {} : { [SESSION_FRONT_MATTER.GIT_REF]: input.git_ref }),\n [SESSION_FRONT_MATTER.GOAL]: input.goal,\n [SESSION_FRONT_MATTER.NEXT_STEP]: input.next_step,\n [SESSION_FRONT_MATTER.SPECS]: input.specs ?? [],\n [SESSION_FRONT_MATTER.FILES]: input.files ?? [],\n }, { defaultStringType: \"QUOTE_DOUBLE\" }).trimEnd();\n}\n\nexport function buildSessionFrontMatterContent(\n frontMatterLines: readonly string[],\n body: string,\n closeDelimiter: string = SESSION_FRONT_MATTER_DELIMITER,\n): string {\n return `${SESSION_FRONT_MATTER_OPEN}${frontMatterLines.join(\"\\n\")}\\n${closeDelimiter}\\n${body}`;\n}\n","/**\n * The handoff-base gate: resolves the git ref a handoff session records and\n * refuses a work context from which the recorded base would not be reachable\n * by a resuming agent.\n *\n * Pure over the supplied git facts — the handler gathers the facts via the\n * git primitives in `@/git/root` and the descriptor owns process I/O. A refused\n * non-main-checkout handoff throws {@link SessionHandoffBaseError} carrying the\n * resolved facts and the per-prerequisite evaluation; a non-git base throws it\n * marked `silent`, so the descriptor writes nothing; any other git refusal\n * (e.g. a main checkout with no reachable HEAD) carries no checklist and is not\n * silent, so the descriptor writes a plain diagnostic.\n *\n * @module domains/session/handoff-base\n */\n\nimport { SessionHandoffBaseError, SessionWorkBranchNotOnOriginError } from \"./errors\";\nimport {\n HANDOFF_BASE_PREREQUISITE_LABEL,\n HANDOFF_BASE_REMEDY,\n type HandoffBaseChecklist,\n type HandoffBasePrerequisite,\n} from \"./handoff-base-checklist\";\n\n/**\n * Git facts the handoff-base gate evaluates. The handler gathers these via the\n * git primitives before calling {@link resolveHandoffGitRef}. Every fact a\n * non-main-checkout refusal checklist renders is present, so the resolver\n * evaluates every prerequisite without re-reading git.\n */\nexport interface HandoffGitFacts {\n /** Whether `cwd` is inside a git repository at all. `false` → silent refusal. */\n readonly isGitRepo: boolean;\n /** Whether `cwd` is the repository's main checkout — the canonical working copy. */\n readonly isMainCheckout: boolean;\n /** The checked-out branch name, or null when HEAD is detached. */\n readonly branch: string | null;\n /** The HEAD commit SHA, or null when unavailable. */\n readonly headSha: string | null;\n /** Whether the working tree is clean. */\n readonly isClean: boolean;\n /** The resolved default branch name, or null when `origin/HEAD` is unset. */\n readonly defaultBranch: string | null;\n /** The commit SHA at the tip of `origin/<default>`, or null when unresolved. */\n readonly defaultTipSha: string | null;\n /** The absolute path of the worktree handoff runs from. */\n readonly currentWorktreePath: string;\n /** The absolute path of the repository's main checkout, or null when none is designable. */\n readonly mainCheckoutPath: string | null;\n}\n\n/**\n * The detached HEAD commit SHA when HEAD sits exactly at the resolved\n * `origin/<default>` tip, or null otherwise. Returning the SHA rather than a\n * boolean lets the caller record the permitted base without re-narrowing\n * `headSha`.\n */\nfunction detachedDefaultTipSha(facts: HandoffGitFacts): string | null {\n const atTip = facts.branch === null\n && facts.headSha !== null\n && facts.defaultTipSha !== null\n && facts.headSha === facts.defaultTipSha;\n return atTip ? facts.headSha : null;\n}\n\n/** The clean-working-tree prerequisite, with its commit-or-main-checkout remedy when unmet. */\nfunction cleanPrerequisite(facts: HandoffGitFacts): HandoffBasePrerequisite {\n return {\n label: HANDOFF_BASE_PREREQUISITE_LABEL.CLEAN_WORKING_TREE,\n met: facts.isClean,\n remedy: facts.isClean ? \"\" : HANDOFF_BASE_REMEDY.COMMIT_OR_MAIN_CHECKOUT,\n };\n}\n\n/**\n * The detached-at-default-tip prerequisite. When unmet, the remedy is to detach\n * to the tip — but only when a tip SHA resolves; when `origin/<default>` resolves\n * to no commit the only remedy is to hand off from the main checkout, matching\n * the unresolved tip the fact line renders.\n */\nfunction detachedAtTipPrerequisite(facts: HandoffGitFacts, met: boolean): HandoffBasePrerequisite {\n const remedy = facts.defaultTipSha === null\n ? HANDOFF_BASE_REMEDY.MAIN_CHECKOUT_ONLY\n : HANDOFF_BASE_REMEDY.DETACH_TO_TIP_OR_MAIN_CHECKOUT;\n return {\n label: HANDOFF_BASE_PREREQUISITE_LABEL.DETACHED_AT_DEFAULT_TIP,\n met,\n remedy: met ? \"\" : remedy,\n };\n}\n\n/** Assembles the refusal checklist from the resolved facts and prerequisites. */\nfunction buildChecklist(\n facts: HandoffGitFacts,\n prerequisites: readonly HandoffBasePrerequisite[],\n): HandoffBaseChecklist {\n return {\n defaultBranch: facts.defaultBranch,\n defaultTipSha: facts.defaultTipSha,\n headSha: facts.headSha,\n currentWorktreePath: facts.currentWorktreePath,\n mainCheckoutPath: facts.mainCheckoutPath,\n prerequisites,\n };\n}\n\n/**\n * Resolves the git ref a handoff session records, enforcing the handoff-base\n * gate.\n *\n * - **Non-git base**: throws a silent {@link SessionHandoffBaseError} (no checklist).\n * - **Main checkout** (any HEAD): records the branch name when HEAD is on a\n * branch, otherwise the HEAD commit SHA; a main checkout with no reachable\n * HEAD throws a non-silent diagnostic refusal (no checklist, `silent: false`),\n * since only the non-git base refuses silently.\n * - **Non-main checkout**: every base prerequisite — a clean working tree and a\n * HEAD detached at the `origin/<default>` tip — is evaluated regardless of the\n * others. When all are met, records the tip SHA; otherwise throws a\n * {@link SessionHandoffBaseError} carrying the checklist.\n *\n * @param facts - The git facts gathered by the handler.\n * @returns The git ref to record in the session frontmatter.\n * @throws {SessionHandoffBaseError} When the work context cannot anchor a base.\n */\nexport function resolveHandoffGitRef(facts: HandoffGitFacts): string {\n // A non-git base resolves no reachable commit and refuses silently.\n if (!facts.isGitRepo) {\n throw new SessionHandoffBaseError({ silent: true });\n }\n\n if (facts.isMainCheckout) {\n if (facts.branch !== null) return facts.branch;\n if (facts.headSha !== null) return facts.headSha;\n // A main checkout with no reachable HEAD is a git refusal, not the non-git\n // case — it carries a plain diagnostic rather than refusing silently.\n throw new SessionHandoffBaseError();\n }\n\n // Non-main checkout: evaluate every prerequisite so the checklist omits none.\n const tipSha = detachedDefaultTipSha(facts);\n const prerequisites: readonly HandoffBasePrerequisite[] = [\n cleanPrerequisite(facts),\n detachedAtTipPrerequisite(facts, tipSha !== null),\n ];\n\n if (facts.isClean && tipSha !== null) {\n return tipSha;\n }\n\n throw new SessionHandoffBaseError({ checklist: buildChecklist(facts, prerequisites) });\n}\n\n/**\n * Resolves the `git_ref` to record when the caller supplies an explicit\n * work-branch ref, enforcing that the branch exists on `origin`.\n *\n * Pure over the supplied facts — the handler performs the origin probe (via\n * `originBranchExists`) and passes its existence verdict here. The recorded ref\n * overrides the git-context base only after this verification; the handoff-base\n * gate that validates the running worktree is enforced separately by\n * {@link resolveHandoffGitRef} and is never bypassed by an explicit ref.\n *\n * @param workBranch - The caller-supplied work-branch ref.\n * @param existsOnOrigin - Whether `origin/<workBranch>` exists as an exact\n * remote-tracking ref (from `git show-ref --verify --quiet`), which a revision\n * expression like `<branch>~1` or the `HEAD` symref does not satisfy.\n * @returns The work-branch ref to record as `git_ref`.\n * @throws {SessionWorkBranchNotOnOriginError} When the branch is absent from `origin`.\n */\nexport function resolveWorkBranchGitRef(workBranch: string, existsOnOrigin: boolean): string {\n if (!existsOnOrigin) {\n throw new SessionWorkBranchNotOnOriginError(workBranch);\n }\n return workBranch;\n}\n","/**\n * Pure parser for the `spx session handoff` JSON-prefix wire format.\n *\n * The wire format is a single JSON object at the start of stdin holding\n * caller-supplied structured fields, immediately followed by the body bytes\n * verbatim. An optional single LF or CRLF between the closing `}` and the\n * body is consumed as a separator.\n *\n * @module domains/session/parse-handoff-input\n */\n\nimport { SessionInvalidJsonHeaderError, SessionLegacyFrontmatterInputError } from \"@/domains/session/errors\";\nimport {\n DEFAULT_PRIORITY,\n SESSION_FRONT_MATTER,\n SESSION_PRIORITY,\n type SessionPriority,\n} from \"@/domains/session/types\";\n\nconst LEGACY_FRONTMATTER_PREFIX = /^---\\r?\\n/;\nconst JSON_OBJECT_OPEN_CHAR = \"{\";\nconst CARRIAGE_RETURN_CHAR_CODE = \"\\r\".charCodeAt(0);\nconst NEWLINE_CHAR_CODE = \"\\n\".charCodeAt(0);\nconst BACKSLASH_CHAR_CODE = \"\\\\\".charCodeAt(0);\nconst DOUBLE_QUOTE_CHAR_CODE = \"\\\"\".charCodeAt(0);\nconst OPEN_BRACE_CHAR_CODE = \"{\".charCodeAt(0);\nconst CLOSE_BRACE_CHAR_CODE = \"}\".charCodeAt(0);\nconst UNBALANCED_HEADER_END = -1;\nconst LF_SEPARATOR_LENGTH = 1;\nconst CRLF_SEPARATOR_LENGTH = 2;\n\nconst SESSION_PRIORITY_VALUES = new Set<string>(Object.values(SESSION_PRIORITY));\n\n/**\n * Caller-supplied structured fields recognized by `parseHandoffInput`.\n *\n * `git_ref` is optional: when present it names a work-branch ref the handoff\n * command records as the session base after confirming the branch exists on\n * `origin`; when absent the command derives the base from the git context.\n * `created_at` and `agent_session_id` are never caller-supplied — they are\n * silently ignored if included and sourced from the system clock and process\n * environment instead.\n */\nexport interface HandoffHeader {\n readonly priority: SessionPriority;\n readonly goal: string;\n readonly next_step: string;\n readonly specs: readonly string[];\n readonly files: readonly string[];\n readonly git_ref?: string;\n}\n\n/**\n * Result of parsing `spx session handoff` stdin.\n */\nexport interface ParsedHandoffInput {\n readonly header: HandoffHeader;\n readonly body: string;\n}\n\n/**\n * Parses `spx session handoff` stdin per the JSON-prefix wire format.\n *\n * Algorithm:\n *\n * 1. Reject input opening with the YAML-frontmatter delimiter `---\\n` or\n * `---\\r\\n` with `SessionLegacyFrontmatterInputError`.\n * 2. Reject input that does not open with `{` with\n * `SessionInvalidJsonHeaderError`.\n * 3. Scan from the opening `{` to find the matching closing `}` while\n * respecting JSON string state — characters inside double-quoted strings\n * do not affect brace depth, and a backslash escapes the next character\n * inside a string. Unbalanced braces raise `SessionInvalidJsonHeaderError`.\n * 4. `JSON.parse` the header substring; parse failures raise\n * `SessionInvalidJsonHeaderError`.\n * 5. Validate the parsed object against the caller-field schema. Schema\n * failures raise `SessionInvalidJsonHeaderError`.\n * 6. Return the parsed header and the body bytes after the closing `}` (with\n * a single optional `LF` or `CRLF` separator consumed).\n *\n * @param stdin - Raw stdin bytes\n * @returns Parsed header and body\n * @throws {SessionLegacyFrontmatterInputError} When stdin opens with `---\\n`\n * @throws {SessionInvalidJsonHeaderError} When the header is malformed or\n * fails schema validation\n */\nexport function parseHandoffInput(stdin: string): ParsedHandoffInput {\n if (LEGACY_FRONTMATTER_PREFIX.test(stdin)) {\n throw new SessionLegacyFrontmatterInputError();\n }\n\n if (!stdin.startsWith(JSON_OBJECT_OPEN_CHAR)) {\n throw new SessionInvalidJsonHeaderError(\n \"stdin must begin with a JSON object opening with '{'\",\n );\n }\n\n const headerEnd = findJsonObjectEnd(stdin);\n if (headerEnd === UNBALANCED_HEADER_END) {\n throw new SessionInvalidJsonHeaderError(\n \"unbalanced JSON object — opening brace has no matching close\",\n );\n }\n\n const headerText = stdin.slice(0, headerEnd + 1);\n let parsed: unknown;\n try {\n parsed = JSON.parse(headerText);\n } catch (err) {\n const detail = err instanceof Error ? err.message : \"JSON.parse failed\";\n throw new SessionInvalidJsonHeaderError(detail);\n }\n\n const header = validateHandoffHeader(parsed);\n\n const bodyStart = consumeOptionalBodySeparator(stdin, headerEnd + 1);\n\n return { header, body: stdin.slice(bodyStart) };\n}\n\nfunction consumeOptionalBodySeparator(stdin: string, bodyStart: number): number {\n if (\n stdin.charCodeAt(bodyStart) === CARRIAGE_RETURN_CHAR_CODE\n && stdin.charCodeAt(bodyStart + LF_SEPARATOR_LENGTH) === NEWLINE_CHAR_CODE\n ) {\n return bodyStart + CRLF_SEPARATOR_LENGTH;\n }\n\n if (stdin.charCodeAt(bodyStart) === NEWLINE_CHAR_CODE) {\n return bodyStart + LF_SEPARATOR_LENGTH;\n }\n\n return bodyStart;\n}\n\n/**\n * Scans `stdin` from index `0` (assumed to start with `{`) and returns the\n * index of the closing `}` that balances the opening brace.\n *\n * JSON string-state aware: characters inside a double-quoted string don't\n * affect brace depth, and a backslash inside a string escapes the next\n * character (so `\"\\\\\"\"` and `\"\\\"\"` are valid strings).\n *\n * @returns Index of the matching closing brace, or `UNBALANCED_HEADER_END`\n * when the opening brace has no matching close in `stdin`.\n */\nfunction findJsonObjectEnd(stdin: string): number {\n let depth = 0;\n let inString = false;\n for (let i = 0; i < stdin.length; i++) {\n const code = stdin.charCodeAt(i);\n if (inString) {\n if (code === BACKSLASH_CHAR_CODE) {\n // Skip the next character (an escape sequence is one logical unit).\n i += 1;\n continue;\n }\n if (code === DOUBLE_QUOTE_CHAR_CODE) {\n inString = false;\n }\n continue;\n }\n if (code === DOUBLE_QUOTE_CHAR_CODE) {\n inString = true;\n continue;\n }\n if (code === OPEN_BRACE_CHAR_CODE) {\n depth += 1;\n continue;\n }\n if (code === CLOSE_BRACE_CHAR_CODE) {\n depth -= 1;\n if (depth === 0) return i;\n }\n }\n return UNBALANCED_HEADER_END;\n}\n\n/**\n * Validates `parsed` against the JSON-prefix header schema and narrows the\n * result to `HandoffHeader`.\n *\n * The optional `git_ref` field is carried through when present; `created_at`\n * and `agent_session_id` are silently dropped — callers who include those\n * prefilled fields in the JSON have them ignored, preserving the\n * \"agent identity and timestamp are sourced by the command\" invariant by\n * construction.\n */\nfunction validateHandoffHeader(parsed: unknown): HandoffHeader {\n if (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n throw new SessionInvalidJsonHeaderError(\"header must be a JSON object\");\n }\n const obj = parsed as Record<string, unknown>;\n\n const priority = ensurePriorityOrDefault(obj[SESSION_FRONT_MATTER.PRIORITY]);\n const goal = ensureStringOrEmpty(obj[SESSION_FRONT_MATTER.GOAL], SESSION_FRONT_MATTER.GOAL);\n const nextStep = ensureStringOrEmpty(obj[SESSION_FRONT_MATTER.NEXT_STEP], SESSION_FRONT_MATTER.NEXT_STEP);\n const specs = ensureStringArrayOrDefault(obj[SESSION_FRONT_MATTER.SPECS], SESSION_FRONT_MATTER.SPECS);\n const files = ensureStringArrayOrDefault(obj[SESSION_FRONT_MATTER.FILES], SESSION_FRONT_MATTER.FILES);\n const gitRef = ensureOptionalString(obj[SESSION_FRONT_MATTER.GIT_REF], SESSION_FRONT_MATTER.GIT_REF);\n\n return {\n priority,\n goal,\n next_step: nextStep,\n specs,\n files,\n ...(gitRef === undefined ? {} : { git_ref: gitRef }),\n };\n}\n\n/**\n * Coerces an optional JSON value to a recognized `SessionPriority`.\n *\n * Returns the default priority when the field is missing (`undefined`). Throws\n * `SessionInvalidJsonHeaderError` when the value is present but is not a\n * string matching one of the registered priority values.\n */\nfunction ensurePriorityOrDefault(value: unknown): SessionPriority {\n if (value === undefined) return DEFAULT_PRIORITY;\n if (typeof value !== \"string\" || !SESSION_PRIORITY_VALUES.has(value)) {\n throw new SessionInvalidJsonHeaderError(\n `${SESSION_FRONT_MATTER.PRIORITY} must be one of ${[...SESSION_PRIORITY_VALUES].join(\", \")}`,\n );\n }\n return value as SessionPriority;\n}\n\n/**\n * Coerces an optional JSON value to a string.\n *\n * Returns an empty string when the field is missing (`undefined`) so the\n * downstream non-empty validation in `handoffCommand` surfaces the\n * semantic-content error (`SessionInvalidGoalError` / `SessionInvalidNextStepError`)\n * rather than a structural `SessionInvalidJsonHeaderError`. Throws\n * `SessionInvalidJsonHeaderError` only when the value is present but is not\n * a string.\n */\nfunction ensureStringOrEmpty(value: unknown, fieldName: string): string {\n if (value === undefined) return \"\";\n if (typeof value !== \"string\") {\n throw new SessionInvalidJsonHeaderError(`${fieldName} must be a string`);\n }\n return value;\n}\n\n/**\n * Coerces an optional JSON value to a string or `undefined`.\n *\n * Returns `undefined` when the field is missing so the caller can distinguish\n * \"no value supplied\" from an empty string. Throws\n * `SessionInvalidJsonHeaderError` when the value is present but is not a string.\n */\nfunction ensureOptionalString(value: unknown, fieldName: string): string | undefined {\n if (value === undefined) return undefined;\n if (typeof value !== \"string\") {\n throw new SessionInvalidJsonHeaderError(`${fieldName} must be a string`);\n }\n return value;\n}\n\n/**\n * Coerces an optional JSON value to a readonly string array.\n *\n * Returns an empty array when the field is missing (`undefined`). Throws\n * `SessionInvalidJsonHeaderError` when the value is present but not an array\n * of strings.\n */\nfunction ensureStringArrayOrDefault(value: unknown, fieldName: string): readonly string[] {\n if (value === undefined) return [];\n if (!Array.isArray(value)) {\n throw new SessionInvalidJsonHeaderError(`${fieldName} must be an array of strings`);\n }\n for (const item of value) {\n if (typeof item !== \"string\") {\n throw new SessionInvalidJsonHeaderError(`${fieldName} must be an array of strings`);\n }\n }\n return value as readonly string[];\n}\n","/**\n * Session list CLI command handler.\n *\n * @module commands/session/list\n */\n\nimport { readdir, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport {\n parseFieldSelection,\n parseSessionMetadata,\n projectSessionRecord,\n type SessionRecordField,\n sortSessions,\n toSessionRecord,\n} from \"@/domains/session/list\";\nimport { SessionDirectoryConfig } from \"@/domains/session/show\";\nimport {\n DEFAULT_LIST_STATUSES,\n DEFAULT_PRIORITY,\n Session,\n SESSION_STATUSES,\n SessionStatus,\n} from \"@/domains/session/types\";\nimport { resolveSessionConfigSurfacingWarning, type SessionWarningHandler } from \"./resolve-config\";\n\nexport const SESSION_LIST_FORMAT = {\n TEXT: \"text\",\n JSON: \"json\",\n} as const;\n\nexport type SessionListFormat = (typeof SESSION_LIST_FORMAT)[keyof typeof SESSION_LIST_FORMAT];\n\nexport const SESSION_LIST_EMPTY_TEXT = \"(no sessions)\";\nconst SESSION_LIST_SUMMARY_SEPARATOR = \" -> \";\n\n/**\n * Options for the list command.\n * Note: status is string (not SessionStatus) because it comes from user input via Commander.js.\n * Validation happens inside listCommand before status is used.\n */\nexport interface ListOptions {\n /** Filter by status (validated against SESSION_STATUSES) */\n status?: string;\n /** Custom sessions directory */\n sessionsDir?: string;\n /** Receives the non-git-repo diagnostic for the descriptor to surface. */\n onWarning?: SessionWarningHandler;\n /** Output format */\n format?: SessionListFormat;\n /** Comma-separated field selection; implies JSON output. */\n fields?: string;\n}\n\n/**\n * Loads sessions from a specific directory.\n */\nasync function loadSessionsFromDir(\n dir: string,\n status: SessionStatus,\n): Promise<Session[]> {\n try {\n const files = await readdir(dir);\n const sessions: Session[] = [];\n\n for (const file of files) {\n if (!file.endsWith(\".md\")) continue;\n\n const id = file.replace(\".md\", \"\");\n const filePath = join(dir, file);\n const content = await readFile(filePath, \"utf-8\");\n const metadata = parseSessionMetadata(content);\n\n sessions.push({\n id,\n status,\n path: filePath,\n metadata,\n });\n }\n\n return sessions;\n } catch (error) {\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") {\n return [];\n }\n throw error;\n }\n}\n\n/**\n * Maps a session status to its directory path in the config.\n */\nconst STATUS_DIR_KEY: Record<SessionStatus, keyof SessionDirectoryConfig> = {\n todo: \"todoDir\",\n doing: \"doingDir\",\n archive: \"archiveDir\",\n};\n\n/**\n * Formats sessions for text output.\n */\nfunction formatTextOutput(sessions: Session[]): string {\n if (sessions.length === 0) {\n return ` ${SESSION_LIST_EMPTY_TEXT}`;\n }\n\n return sessions\n .map((s) => {\n const priority = s.metadata.priority !== DEFAULT_PRIORITY ? ` [${s.metadata.priority}]` : \"\";\n const summary = s.metadata.goal.length > 0 && s.metadata.next_step.length > 0\n ? ` ${s.metadata.goal}${SESSION_LIST_SUMMARY_SEPARATOR}${s.metadata.next_step}`\n : \"\";\n return ` ${s.id}${priority}${summary}`;\n })\n .join(\"\\n\");\n}\n\n/**\n * Executes the list command.\n *\n * @param options - Command options\n * @returns Formatted output for display\n */\n/**\n * Validates a user-supplied status string against SESSION_STATUSES.\n * Returns the validated SessionStatus or throws with valid values listed.\n */\nfunction validateStatus(input: string): SessionStatus {\n if (SESSION_STATUSES.includes(input as SessionStatus)) {\n return input as SessionStatus;\n }\n throw new Error(\n `Invalid status: \"${input}\". Valid values: ${SESSION_STATUSES.join(\", \")}`,\n );\n}\n\nexport async function listCommand(options: ListOptions): Promise<string> {\n // Parse the field selection first so an unknown field fails fast, before any\n // filesystem work. A field selection implies JSON output.\n const fieldSelection: SessionRecordField[] | undefined = options.fields !== undefined\n ? parseFieldSelection(options.fields)\n : undefined;\n\n const config = await resolveSessionConfigSurfacingWarning(options.sessionsDir, options.onWarning);\n\n // Validate and resolve statuses before use.\n const statuses: readonly SessionStatus[] = options.status !== undefined\n ? [validateStatus(options.status)]\n : DEFAULT_LIST_STATUSES;\n\n const sessionsByStatus: Partial<Record<SessionStatus, Session[]>> = {};\n\n for (const status of statuses) {\n const dirKey = STATUS_DIR_KEY[status];\n const sessions = await loadSessionsFromDir(config[dirKey], status);\n sessionsByStatus[status] = sortSessions(sessions);\n }\n\n // Format output. A JSON format flag or a field selection emits JSON; each\n // session becomes a flat record (projected to the selected fields when given).\n const emitJson = fieldSelection !== undefined || options.format === SESSION_LIST_FORMAT.JSON;\n if (emitJson) {\n const recordsByStatus: Partial<Record<SessionStatus, unknown[]>> = {};\n for (const status of statuses) {\n recordsByStatus[status] = (sessionsByStatus[status] ?? []).map((session) => {\n const record = toSessionRecord(session);\n return fieldSelection !== undefined ? projectSessionRecord(record, fieldSelection) : record;\n });\n }\n return JSON.stringify(recordsByStatus, null, 2);\n }\n\n // Text format\n const lines: string[] = [];\n\n for (const status of statuses) {\n lines.push(`${status.toUpperCase()}:`);\n lines.push(formatTextOutput(sessionsByStatus[status] ?? []));\n lines.push(\"\");\n }\n\n return lines.join(\"\\n\").trim();\n}\n","/**\n * Session pickup CLI command handler.\n *\n * @module commands/session/pickup\n */\n\nimport { mkdir, readdir, readFile, rename } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { processBatch } from \"@/domains/session/batch\";\nimport { NoSessionsAvailableError } from \"@/domains/session/errors\";\nimport { parseSessionMetadata } from \"@/domains/session/list\";\nimport { buildClaimPaths, classifyClaimError, selectBestSession } from \"@/domains/session/pickup\";\nimport { formatShowOutput, SessionDirectoryConfig } from \"@/domains/session/show\";\nimport { Session, SESSION_STATUSES, SessionStatus } from \"@/domains/session/types\";\nimport { resolveSessionConfigSurfacingWarning, type SessionWarningHandler } from \"./resolve-config\";\n\n/** Status of sessions available for pickup. */\nconst PICKUP_SOURCE_STATUS: SessionStatus = SESSION_STATUSES[0]; // todo\n/** Status of sessions after being claimed. */\nconst PICKUP_TARGET_STATUS: SessionStatus = SESSION_STATUSES[1]; // doing\n\n/**\n * Options for the pickup command.\n */\nexport interface PickupOptions {\n /** Session IDs to pickup. Empty array is valid only with auto. */\n sessionIds: readonly string[];\n /** Auto-select highest priority session */\n auto?: boolean;\n /** Custom sessions directory */\n sessionsDir?: string;\n /** Receives the non-git-repo diagnostic for the descriptor to surface. */\n onWarning?: SessionWarningHandler;\n}\n\n/**\n * Loads sessions from the todo directory.\n */\nasync function loadTodoSessions(config: SessionDirectoryConfig): Promise<Session[]> {\n try {\n const files = await readdir(config.todoDir);\n const sessions: Session[] = [];\n\n for (const file of files) {\n if (!file.endsWith(\".md\")) continue;\n\n const id = file.replace(\".md\", \"\");\n const filePath = join(config.todoDir, file);\n const content = await readFile(filePath, \"utf-8\");\n const metadata = parseSessionMetadata(content);\n\n sessions.push({\n id,\n status: PICKUP_SOURCE_STATUS,\n path: filePath,\n metadata,\n });\n }\n\n return sessions;\n } catch (error) {\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") {\n return [];\n }\n throw error;\n }\n}\n\n/**\n * Claims one session from the todo queue and moves it to doing.\n */\nasync function pickupSingle(sessionId: string, config: SessionDirectoryConfig): Promise<string> {\n const paths = buildClaimPaths(sessionId, config);\n await mkdir(config.doingDir, { recursive: true });\n\n try {\n await rename(paths.source, paths.target);\n } catch (error) {\n throw classifyClaimError(error, sessionId);\n }\n\n const content = await readFile(paths.target, \"utf-8\");\n const output = formatShowOutput(content, { status: PICKUP_TARGET_STATUS });\n\n return `Claimed session <PICKUP_ID>${sessionId}</PICKUP_ID>\\n\\n${output}`;\n}\n\n/**\n * Executes the pickup command.\n *\n * Claims one or more sessions from the todo queue and moves them to doing.\n * Output includes one `<PICKUP_ID>` tag per claimed session for automation.\n *\n * @param options - Command options\n * @returns Formatted output for display with parseable session IDs\n * @throws {NoSessionsAvailableError} When no sessions in todo for auto mode\n * @throws {SessionNotAvailableError} When one or more sessions cannot be claimed\n * @throws {BatchError} When one or more explicit IDs fail\n */\nexport async function pickupCommand(options: PickupOptions): Promise<string> {\n const config = await resolveSessionConfigSurfacingWarning(options.sessionsDir, options.onWarning);\n\n if (options.auto) {\n if (options.sessionIds.length > 0) {\n throw new Error(\"Session IDs cannot be combined with --auto\");\n }\n\n const sessions = await loadTodoSessions(config);\n const selected = selectBestSession(sessions);\n\n if (!selected) {\n throw new NoSessionsAvailableError();\n }\n\n return pickupSingle(selected.id, config);\n }\n\n if (options.sessionIds.length === 0) {\n throw new Error(\"Either session ID or --auto flag is required\");\n }\n\n if (options.sessionIds.length === 1) {\n return pickupSingle(options.sessionIds[0], config);\n }\n\n return processBatch(options.sessionIds, (id) => pickupSingle(id, config));\n}\n","/**\n * Session pickup/claiming utilities.\n *\n * This module provides pure functions for atomic session claiming:\n * - Path construction for claim operations\n * - Error classification for claim failures\n * - Session selection for auto-pickup\n *\n * @module session/pickup\n */\n\nimport { SessionNotAvailableError } from \"./errors\";\nimport { parseSessionId } from \"./timestamp\";\nimport { PRIORITY_ORDER, type Session } from \"./types\";\n\n/**\n * Configuration for session claim paths.\n */\nexport interface ClaimPathConfig {\n /** Directory containing sessions to be claimed */\n todoDir: string;\n /** Directory for claimed sessions */\n doingDir: string;\n}\n\n/**\n * Result of building claim paths.\n */\nexport interface ClaimPaths {\n /** Source path (session in todo) */\n source: string;\n /** Target path (session in doing) */\n target: string;\n}\n\n/**\n * Builds source and target paths for claiming a session.\n *\n * @param sessionId - The session ID (timestamp format)\n * @param config - Directory configuration\n * @returns Source and target paths for the claim operation\n *\n * @example\n * ```typescript\n * const paths = buildClaimPaths(\"2026-01-13_08-01-05\", {\n * todoDir: \".spx/sessions/todo\",\n * doingDir: \".spx/sessions/doing\",\n * });\n * // => { source: \".spx/sessions/todo/2026-01-13_08-01-05.md\", target: \".spx/sessions/doing/2026-01-13_08-01-05.md\" }\n * ```\n */\nexport function buildClaimPaths(sessionId: string, config: ClaimPathConfig): ClaimPaths {\n return {\n source: `${config.todoDir}/${sessionId}.md`,\n target: `${config.doingDir}/${sessionId}.md`,\n };\n}\n\n/**\n * Classifies a filesystem error that occurred during claiming.\n *\n * When a claim operation fails, this function maps the raw filesystem\n * error to an appropriate domain error:\n * - ENOENT: Session was claimed by another agent (SessionNotAvailable)\n * - Other errors: Rethrown as-is\n *\n * @param error - The error from the claim operation\n * @param sessionId - The session ID being claimed\n * @returns A SessionNotAvailableError if ENOENT\n * @throws The original error if not ENOENT\n *\n * @example\n * ```typescript\n * const err = Object.assign(new Error(\"ENOENT\"), { code: \"ENOENT\" });\n * const classified = classifyClaimError(err, \"test-id\");\n * // => SessionNotAvailableError\n * ```\n */\nexport function classifyClaimError(error: unknown, sessionId: string): SessionNotAvailableError {\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") {\n return new SessionNotAvailableError(sessionId);\n }\n throw error;\n}\n\n/**\n * Selects the best session for auto-pickup based on priority and timestamp.\n *\n * Selection criteria:\n * 1. Highest priority (high > medium > low)\n * 2. Oldest timestamp (FIFO) for sessions with equal priority\n *\n * @param sessions - Available sessions to choose from\n * @returns The best session to claim, or null if no sessions available\n *\n * @example\n * ```typescript\n * const sessions = [\n * { id: \"low-1\", metadata: { priority: \"low\" } },\n * { id: \"high-1\", metadata: { priority: \"high\" } },\n * ];\n * const best = selectBestSession(sessions);\n * // => { id: \"high-1\", ... }\n * ```\n */\nexport function selectBestSession(sessions: Session[]): Session | null {\n if (sessions.length === 0) {\n return null;\n }\n\n // Sort by priority (high first) then by timestamp (oldest first for FIFO)\n const sorted = [...sessions].sort((a, b) => {\n // First: sort by priority (high = 0, medium = 1, low = 2)\n const priorityA = PRIORITY_ORDER[a.metadata.priority];\n const priorityB = PRIORITY_ORDER[b.metadata.priority];\n\n if (priorityA !== priorityB) {\n return priorityA - priorityB;\n }\n\n // Second: sort by timestamp (oldest first = FIFO = ascending)\n const dateA = parseSessionId(a.id);\n const dateB = parseSessionId(b.id);\n\n // Handle invalid session IDs by treating them as newest (go last)\n if (!dateA && !dateB) return 0;\n if (!dateA) return 1; // a goes after b\n if (!dateB) return -1; // b goes after a\n\n return dateA.getTime() - dateB.getTime();\n });\n\n return sorted[0];\n}\n","/**\n * Session prune CLI command handler.\n *\n * @module commands/session/prune\n */\n\nimport { readdir, readFile, unlink } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { parseSessionMetadata } from \"@/domains/session/list\";\nimport { DEFAULT_KEEP_COUNT, selectSessionsToDelete } from \"@/domains/session/prune\";\nimport { SessionDirectoryConfig } from \"@/domains/session/show\";\nimport { Session, SESSION_STATUSES, SessionStatus } from \"@/domains/session/types\";\nimport { resolveSessionConfigSurfacingWarning, type SessionWarningHandler } from \"./resolve-config\";\n\nexport { DEFAULT_KEEP_COUNT };\n\n/** Prune operates only on archived sessions. */\nconst PRUNE_STATUS: SessionStatus = SESSION_STATUSES[2]; // archive\n\nexport const SESSION_PRUNE_OUTPUT = {\n DELETED: \"Deleted\",\n WOULD_DELETE: \"Would delete\",\n} as const;\n\n/**\n * Options for the prune command.\n */\nexport interface PruneOptions {\n /** Number of sessions to keep (default: 5) */\n keep?: number;\n /** Show what would be deleted without actually deleting */\n dryRun?: boolean;\n /** Custom sessions directory */\n sessionsDir?: string;\n /** Receives the non-git-repo diagnostic for the descriptor to surface. */\n onWarning?: SessionWarningHandler;\n}\n\n/**\n * Error thrown when prune options are invalid.\n */\nexport class PruneValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"PruneValidationError\";\n }\n}\n\n/**\n * Validates prune options.\n *\n * @param options - Options to validate\n * @throws {PruneValidationError} When options are invalid\n */\nexport function validatePruneOptions(options: PruneOptions): void {\n if (options.keep !== undefined) {\n if (!Number.isInteger(options.keep) || options.keep < 1) {\n throw new PruneValidationError(\n `Invalid --keep value: ${options.keep}. Must be a positive integer.`,\n );\n }\n }\n}\n\n/**\n * Loads sessions from the archive directory.\n */\nasync function loadArchiveSessions(config: SessionDirectoryConfig): Promise<Session[]> {\n try {\n const files = await readdir(config.archiveDir);\n const sessions: Session[] = [];\n\n for (const file of files) {\n if (!file.endsWith(\".md\")) continue;\n\n const id = file.replace(\".md\", \"\");\n const filePath = join(config.archiveDir, file);\n const content = await readFile(filePath, \"utf-8\");\n const metadata = parseSessionMetadata(content);\n\n sessions.push({\n id,\n status: PRUNE_STATUS,\n path: filePath,\n metadata,\n });\n }\n\n return sessions;\n } catch (error) {\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") {\n return [];\n }\n throw error;\n }\n}\n\n/**\n * Executes the prune command.\n *\n * @param options - Command options\n * @returns Formatted output for display\n * @throws {PruneValidationError} When options are invalid\n */\nexport async function pruneCommand(options: PruneOptions): Promise<string> {\n // Validate options\n validatePruneOptions(options);\n\n const keep = options.keep ?? DEFAULT_KEEP_COUNT;\n const dryRun = options.dryRun ?? false;\n\n const config = await resolveSessionConfigSurfacingWarning(options.sessionsDir, options.onWarning);\n\n // Load and sort sessions\n const sessions = await loadArchiveSessions(config);\n const toPrune = selectSessionsToDelete(sessions, { keep });\n\n if (toPrune.length === 0) {\n return `No sessions to prune. ${sessions.length} sessions kept.`;\n }\n\n // Dry run mode\n if (dryRun) {\n const lines = [\n `${SESSION_PRUNE_OUTPUT.WOULD_DELETE} ${toPrune.length} sessions:`,\n ...toPrune.map((s) => ` - ${s.id}`),\n \"\",\n `${sessions.length - toPrune.length} sessions would be kept.`,\n ];\n return lines.join(\"\\n\");\n }\n\n // Delete sessions\n for (const session of toPrune) {\n await unlink(session.path);\n }\n\n const lines = [\n `${SESSION_PRUNE_OUTPUT.DELETED} ${toPrune.length} sessions:`,\n ...toPrune.map((s) => ` - ${s.id}`),\n \"\",\n `${sessions.length - toPrune.length} sessions kept.`,\n ];\n return lines.join(\"\\n\");\n}\n","/**\n * Session pruning utilities for cleaning up old sessions.\n *\n * @module session/prune\n */\n\nimport { parseSessionId } from \"./timestamp\";\nimport type { Session } from \"./types\";\n\n/**\n * Default number of sessions to keep when pruning.\n */\nexport const DEFAULT_KEEP_COUNT = 5;\n\n/**\n * Options for selecting sessions to delete.\n */\nexport interface SelectSessionsOptions {\n /**\n * Number of most recent sessions to keep.\n * Defaults to DEFAULT_KEEP_COUNT (5).\n */\n keep?: number;\n}\n\n/**\n * Selects sessions to delete based on keep count.\n *\n * Sessions are sorted by timestamp (oldest first), and the oldest sessions\n * beyond the keep count are selected for deletion.\n *\n * @param sessions - Array of sessions to consider\n * @param options - Selection options including keep count\n * @returns Array of sessions to delete (oldest sessions beyond keep count)\n *\n * @example\n * ```typescript\n * // Given 10 sessions, keep 5 newest\n * const toDelete = selectSessionsToDelete(sessions, { keep: 5 });\n * // Returns the 5 oldest sessions\n *\n * // Using default keep count (5)\n * const toDelete = selectSessionsToDelete(sessions);\n * ```\n */\nexport function selectSessionsToDelete(\n sessions: Session[],\n options: SelectSessionsOptions = {},\n): Session[] {\n const keep = options.keep ?? DEFAULT_KEEP_COUNT;\n\n // If we have fewer sessions than the keep count, delete nothing\n if (sessions.length <= keep) {\n return [];\n }\n\n // Sort sessions by timestamp (oldest first for deletion selection)\n const sorted = [...sessions].sort((a, b) => {\n const dateA = parseSessionId(a.id);\n const dateB = parseSessionId(b.id);\n\n // Handle invalid session IDs by treating them as oldest (delete first)\n if (!dateA && !dateB) return 0;\n if (!dateA) return -1; // a (invalid) goes before b (to be deleted first)\n if (!dateB) return 1; // b (invalid) goes before a\n\n return dateA.getTime() - dateB.getTime();\n });\n\n // Return the oldest sessions (those beyond the keep count)\n const deleteCount = sessions.length - keep;\n return sorted.slice(0, deleteCount);\n}\n","/**\n * Session release CLI command handler.\n *\n * @module commands/session/release\n */\n\nimport { readdir, rename } from \"node:fs/promises\";\n\nimport { processBatch } from \"@/domains/session/batch\";\nimport { SessionNotClaimedError } from \"@/domains/session/errors\";\nimport { buildReleasePaths, findCurrentSession } from \"@/domains/session/release\";\nimport { SessionDirectoryConfig } from \"@/domains/session/show\";\nimport { resolveSessionConfigSurfacingWarning, type SessionWarningHandler } from \"./resolve-config\";\n\nexport const SESSION_RELEASE_OUTPUT = {\n RELEASED: \"Released session\",\n RETURNED_TO_TODO: \"Session returned to todo directory.\",\n} as const;\n\n/**\n * Options for the release command.\n */\nexport interface ReleaseOptions {\n /** Session IDs to release. Empty array defaults to most recent in doing. */\n sessionIds: string[];\n /** Custom sessions directory */\n sessionsDir?: string;\n /** Receives the non-git-repo diagnostic for the descriptor to surface. */\n onWarning?: SessionWarningHandler;\n}\n\n/**\n * Loads session refs from the doing directory.\n */\nasync function loadDoingSessions(config: SessionDirectoryConfig): Promise<Array<{ id: string }>> {\n try {\n const files = await readdir(config.doingDir);\n return files\n .filter((file) => file.endsWith(\".md\"))\n .map((file) => ({ id: file.replace(\".md\", \"\") }));\n } catch (error) {\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") {\n return [];\n }\n throw error;\n }\n}\n\n/**\n * Releases a single claimed session by ID.\n */\nasync function releaseSingle(sessionId: string, config: SessionDirectoryConfig): Promise<string> {\n const paths = buildReleasePaths(sessionId, config);\n\n try {\n await rename(paths.source, paths.target);\n } catch (error) {\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") {\n throw new SessionNotClaimedError(sessionId);\n }\n throw error;\n }\n\n return `${SESSION_RELEASE_OUTPUT.RELEASED}: ${sessionId}\\n${SESSION_RELEASE_OUTPUT.RETURNED_TO_TODO}`;\n}\n\n/**\n * Executes the release command for zero or more session IDs.\n *\n * When `sessionIds` is empty, the most recently claimed session in doing is released.\n * When one or more IDs are provided, all are processed in argument order.\n *\n * @param options - Command options\n * @returns Formatted output for display\n * @throws {BatchError} When one or more IDs fail\n * @throws {SessionNotClaimedError} When no session is claimed (empty IDs) or session not in doing (single ID)\n */\nexport async function releaseCommand(options: ReleaseOptions): Promise<string> {\n const config = await resolveSessionConfigSurfacingWarning(options.sessionsDir, options.onWarning);\n\n let ids = options.sessionIds;\n\n if (ids.length === 0) {\n const sessions = await loadDoingSessions(config);\n const current = findCurrentSession(sessions);\n\n if (!current) {\n throw new SessionNotClaimedError(\"(none)\");\n }\n\n ids = [current.id];\n }\n\n return processBatch(ids, (id) => releaseSingle(id, config));\n}\n","/**\n * Session release utilities.\n *\n * This module provides pure functions for releasing claimed sessions:\n * - Path construction for release operations\n * - Finding the current session in doing directory\n *\n * @module session/release\n */\n\nimport { parseSessionId } from \"./timestamp\";\n\n/**\n * Configuration for session release paths.\n */\nexport interface ReleasePathConfig {\n /** Directory containing claimed sessions */\n doingDir: string;\n /** Directory for released sessions */\n todoDir: string;\n}\n\n/**\n * Result of building release paths.\n */\nexport interface ReleasePaths {\n /** Source path (session in doing) */\n source: string;\n /** Target path (session in todo) */\n target: string;\n}\n\n/**\n * Session reference with minimal required fields.\n */\nexport interface SessionRef {\n id: string;\n}\n\n/**\n * Builds source and target paths for releasing a session.\n *\n * @param sessionId - The session ID (timestamp format)\n * @param config - Directory configuration\n * @returns Source and target paths for the release operation\n *\n * @example\n * ```typescript\n * const paths = buildReleasePaths(\"2026-01-13_08-01-05\", {\n * doingDir: \".spx/sessions/doing\",\n * todoDir: \".spx/sessions/todo\",\n * });\n * // => { source: \".spx/sessions/doing/2026-01-13_08-01-05.md\", target: \".spx/sessions/todo/2026-01-13_08-01-05.md\" }\n * ```\n */\nexport function buildReleasePaths(sessionId: string, config: ReleasePathConfig): ReleasePaths {\n return {\n source: `${config.doingDir}/${sessionId}.md`,\n target: `${config.todoDir}/${sessionId}.md`,\n };\n}\n\n/**\n * Finds the most recent session in the doing directory.\n *\n * When no session ID is provided to release, this function\n * selects the most recently claimed session (newest timestamp).\n *\n * @param doingSessions - Sessions currently in doing directory\n * @returns The most recent session, or null if empty\n *\n * @example\n * ```typescript\n * const sessions = [\n * { id: \"2026-01-10_08-00-00\" },\n * { id: \"2026-01-13_08-00-00\" },\n * ];\n * const current = findCurrentSession(sessions);\n * // => { id: \"2026-01-13_08-00-00\" }\n * ```\n */\nexport function findCurrentSession(doingSessions: SessionRef[]): SessionRef | null {\n if (doingSessions.length === 0) {\n return null;\n }\n\n // Sort by timestamp descending (newest first)\n const sorted = [...doingSessions].sort((a, b) => {\n const dateA = parseSessionId(a.id);\n const dateB = parseSessionId(b.id);\n\n // Handle invalid session IDs by treating them as oldest\n if (!dateA && !dateB) return 0;\n if (!dateA) return 1; // a goes after b\n if (!dateB) return -1; // b goes after a\n\n return dateB.getTime() - dateA.getTime();\n });\n\n return sorted[0];\n}\n","/**\n * Session show CLI command handler.\n *\n * @module commands/session/show\n */\n\nimport { readFile, stat } from \"node:fs/promises\";\n\nimport { processBatch } from \"@/domains/session/batch\";\nimport { SessionNotFoundError } from \"@/domains/session/errors\";\nimport { formatShowOutput, resolveSessionPaths, SEARCH_ORDER, SessionDirectoryConfig } from \"@/domains/session/show\";\nimport { SessionStatus } from \"@/domains/session/types\";\nimport { resolveSessionConfigSurfacingWarning, type SessionWarningHandler } from \"./resolve-config\";\n\n/**\n * Options for the show command.\n */\nexport interface ShowOptions {\n /** Session ID(s) to show */\n sessionIds: string[];\n /** Custom sessions directory */\n sessionsDir?: string;\n /** Receives the non-git-repo diagnostic for the descriptor to surface. */\n onWarning?: SessionWarningHandler;\n}\n\n/**\n * Finds the first existing path and its status.\n */\nasync function findExistingPath(\n paths: string[],\n _config: SessionDirectoryConfig,\n): Promise<{ path: string; status: SessionStatus } | null> {\n for (let i = 0; i < paths.length; i++) {\n const filePath = paths[i];\n try {\n const stats = await stat(filePath);\n if (stats.isFile()) {\n return { path: filePath, status: SEARCH_ORDER[i] };\n }\n } catch {\n // File doesn't exist, continue\n }\n }\n return null;\n}\n\n/**\n * Executes the show command.\n *\n * @param options - Command options\n * @returns Formatted output for display\n * @throws {SessionNotFoundError} When session not found\n */\n/**\n * Shows a single session by ID.\n */\nasync function showSingle(\n sessionId: string,\n config: SessionDirectoryConfig,\n): Promise<string> {\n const paths = resolveSessionPaths(sessionId, config);\n const found = await findExistingPath(paths, config);\n\n if (!found) {\n throw new SessionNotFoundError(sessionId);\n }\n\n const content = await readFile(found.path, \"utf-8\");\n return formatShowOutput(content, { status: found.status });\n}\n\n/**\n * Executes the show command for one or more session IDs.\n *\n * @param options - Command options with one or more session IDs\n * @returns Formatted output for display\n * @throws {BatchError} When one or more IDs fail\n * @throws {SessionNotFoundError} When session not found (single ID)\n */\nexport async function showCommand(options: ShowOptions): Promise<string> {\n const config = await resolveSessionConfigSurfacingWarning(options.sessionsDir, options.onWarning);\n\n return processBatch(options.sessionIds, (id) => showSingle(id, config));\n}\n","/**\n * Shared help text for session commands.\n *\n * Centralizes help text to ensure consistency across subcommands.\n *\n * @module domains/session/help\n */\n\n/**\n * Session file format description for the main session help.\n */\nexport const SESSION_FORMAT_HELP = `\nSession File Format:\n Sessions are markdown files with YAML frontmatter for metadata.\n\n ---\n priority: high\n git_ref: main\n goal: Fix the failing release check\n next_step: Run the focused session tests\n specs: []\n files: []\n ---\n # Session Title\n\n Session content...\n\nWorkflow:\n 1. handoff - Create session (todo) — JSON header + body on stdin\n 2. pickup - Claim session (todo -> doing)\n 3. release - Return session (doing -> todo)\n 4. archive - Move session to archive\n 5. delete - Remove session permanently\n`;\n\n/**\n * Input contract for the handoff command.\n */\nexport const HANDOFF_FRONTMATTER_HELP = `\nUsage:\n Pipe a JSON header followed by the body bytes to stdin.\n\n The header is a single JSON object holding caller-supplied structured fields.\n A single LF or CRLF after the header is consumed as a separator. The body\n is the remaining bytes verbatim — no YAML, no escape rules, no ambiguity\n from leading characters like '#' or '---'.\n\nJSON Header Fields:\n priority \"high\" | \"medium\" | \"low\" (default: medium)\n goal required, non-empty string\n next_step required, non-empty string\n specs optional string[], for pickup auto-injection\n files optional string[], for pickup auto-injection\n\nPrefilled by the CLI:\n created_at, git_ref, and agent_session_id when an agent session ID is\n available.\n\n git_ref records the branch name (main checkout on a branch), the HEAD SHA\n (detached), or the origin/<default> tip SHA (clean detached non-main checkout).\n Handoff is refused from any other non-main checkout state.\n\nOutput Tags (for automation):\n <HANDOFF_ID>session-id</HANDOFF_ID> Session identifier\n <SESSION_FILE>/path/to/file</SESSION_FILE> Absolute path to created file\n\nCanonical Invocation:\n printf '%s\\\\n' \\\\\n '{\"priority\":\"high\",\"goal\":\"Fix login\",\"next_step\":\"Run validation\",\"specs\":[],\"files\":[]}' \\\\\n '# Fix login' \\\\\n '' \\\\\n 'Body text — # symbols, --- delimiters, and code fences are literal.' \\\\\n | spx session handoff\n`;\n\n/**\n * Selection logic for pickup command.\n */\nexport const PICKUP_SELECTION_HELP = `\nSelection Logic (--auto):\n Sessions are selected by priority, then age (FIFO):\n 1. high priority first\n 2. medium priority second\n 3. low priority last\n 4. Within same priority: oldest session first\n\nOutput:\n <PICKUP_ID>session-id</PICKUP_ID> tag for each claimed session\n`;\n","/**\n * Session CLI — Commander registration descriptor for the session subcommands.\n */\nimport type { Command } from \"commander\";\n\nimport {\n archiveCommand,\n deleteCommand,\n handoffCommand,\n listCommand,\n pickupCommand,\n pruneCommand,\n PruneValidationError,\n releaseCommand,\n SessionAlreadyArchivedError,\n showCommand,\n} from \"@/commands/session/index\";\nimport { SESSION_LIST_FORMAT } from \"@/commands/session/list\";\nimport { SessionHandoffBaseError } from \"@/domains/session/errors\";\nimport { renderHandoffBaseChecklist } from \"@/domains/session/handoff-base-checklist\";\nimport { HANDOFF_FRONTMATTER_HELP, PICKUP_SELECTION_HELP, SESSION_FORMAT_HELP } from \"@/domains/session/help\";\nimport { SESSION_STATUSES } from \"@/domains/session/types\";\nimport type { Domain } from \"@/domains/types\";\n\nimport { writeWarning } from \"./write-warning\";\n\n/**\n * Reads content from stdin if available (piped input).\n * Returns undefined if stdin is a TTY (interactive terminal).\n */\nasync function readStdin(): Promise<string | undefined> {\n // Check if stdin is a TTY (interactive) - if so, don't wait for input\n if (process.stdin.isTTY) {\n return undefined;\n }\n\n return new Promise((resolve) => {\n let data = \"\";\n process.stdin.setEncoding(\"utf-8\");\n process.stdin.on(\"data\", (chunk) => {\n data += chunk;\n });\n process.stdin.on(\"end\", () => {\n resolve(data.length === 0 ? undefined : data);\n });\n // Handle case where stdin closes without data\n process.stdin.on(\"error\", () => {\n resolve(undefined);\n });\n });\n}\n\n/**\n * Handles command errors with consistent formatting.\n */\nfunction handleError(error: unknown): never {\n console.error(\"Error:\", error instanceof Error ? `${error.name}: ${error.message}` : String(error));\n process.exit(1);\n}\n\n/**\n * Register session domain commands\n *\n * @param sessionCmd - Commander.js session domain command\n */\nfunction registerSessionCommands(sessionCmd: Command): void {\n // list command\n sessionCmd\n .command(\"list\")\n .description(\"List active sessions (doing + todo by default)\")\n .option(\"--status <status>\", \"Filter by status (todo|doing|archive); defaults to doing + todo\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--fields <fields>\", \"Comma-separated fields to emit as JSON (implies --json)\")\n .option(\"--sessions-dir <path>\", \"Custom sessions directory\")\n .action(async (options: { status?: string; json?: boolean; fields?: string; sessionsDir?: string }) => {\n try {\n const output = await listCommand({\n status: options.status,\n format: options.json ? SESSION_LIST_FORMAT.JSON : SESSION_LIST_FORMAT.TEXT,\n fields: options.fields,\n sessionsDir: options.sessionsDir,\n onWarning: writeWarning,\n });\n console.log(output);\n } catch (error) {\n handleError(error);\n }\n });\n\n // todo command (convenience alias for list --status todo)\n sessionCmd\n .command(\"todo\")\n .description(\"List todo sessions\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--fields <fields>\", \"Comma-separated fields to emit as JSON (implies --json)\")\n .option(\"--sessions-dir <path>\", \"Custom sessions directory\")\n .action(async (options: { json?: boolean; fields?: string; sessionsDir?: string }) => {\n try {\n const output = await listCommand({\n status: SESSION_STATUSES[0],\n format: options.json ? SESSION_LIST_FORMAT.JSON : SESSION_LIST_FORMAT.TEXT,\n fields: options.fields,\n sessionsDir: options.sessionsDir,\n onWarning: writeWarning,\n });\n console.log(output);\n } catch (error) {\n handleError(error);\n }\n });\n\n // show command\n sessionCmd\n .command(\"show <id...>\")\n .description(\"Show session content\")\n .option(\"--sessions-dir <path>\", \"Custom sessions directory\")\n .action(async (ids: string[], options: { sessionsDir?: string }) => {\n try {\n const output = await showCommand({\n sessionIds: ids,\n sessionsDir: options.sessionsDir,\n onWarning: writeWarning,\n });\n console.log(output);\n } catch (error) {\n handleError(error);\n }\n });\n\n // pickup command\n sessionCmd\n .command(\"pickup [ids...]\")\n .description(\"Claim one or more sessions (move from todo to doing)\")\n .option(\"--auto\", \"Auto-select highest priority session\")\n .option(\"--sessions-dir <path>\", \"Custom sessions directory\")\n .addHelpText(\"after\", PICKUP_SELECTION_HELP)\n .action(async (ids: string[], options: { auto?: boolean; sessionsDir?: string }) => {\n try {\n if (ids.length === 0 && !options.auto) {\n console.error(\"Error: Either session ID or --auto flag is required\");\n process.exit(1);\n }\n const output = await pickupCommand({\n sessionIds: ids,\n auto: options.auto,\n sessionsDir: options.sessionsDir,\n onWarning: writeWarning,\n });\n console.log(output);\n } catch (error) {\n handleError(error);\n }\n });\n\n // release command\n sessionCmd\n .command(\"release [ids...]\")\n .description(\"Release one or more sessions (move from doing to todo)\")\n .option(\"--sessions-dir <path>\", \"Custom sessions directory\")\n .action(async (ids: string[], options: { sessionsDir?: string }) => {\n try {\n const output = await releaseCommand({\n sessionIds: ids,\n sessionsDir: options.sessionsDir,\n onWarning: writeWarning,\n });\n console.log(output);\n } catch (error) {\n handleError(error);\n }\n });\n\n // handoff command\n // Caller-supplied fields come from a JSON header at the start of stdin;\n // bytes after the header form the markdown body verbatim.\n sessionCmd\n .command(\"handoff\")\n .description(\"Create a handoff session (reads JSON header + body from stdin)\")\n .option(\"--sessions-dir <path>\", \"Custom sessions directory\")\n .addHelpText(\"after\", HANDOFF_FRONTMATTER_HELP)\n .action(async (options: { sessionsDir?: string }) => {\n try {\n // Read content from stdin if available\n const content = await readStdin();\n\n const result = await handoffCommand({\n content,\n sessionsDir: options.sessionsDir,\n env: process.env,\n });\n console.log(result.output);\n } catch (error) {\n if (error instanceof SessionHandoffBaseError) {\n // A non-main-checkout refusal renders the prerequisite checklist; a\n // non-git base refuses silently; any other git refusal writes the\n // message as a plain diagnostic.\n if (error.checklist !== null) {\n console.error(renderHandoffBaseChecklist(error.checklist));\n } else if (!error.silent) {\n console.error(\"Error:\", `${error.name}: ${error.message}`);\n }\n process.exit(1);\n }\n handleError(error);\n }\n });\n\n // delete command\n sessionCmd\n .command(\"delete <id...>\")\n .description(\"Delete one or more sessions\")\n .option(\"--sessions-dir <path>\", \"Custom sessions directory\")\n .action(async (ids: string[], options: { sessionsDir?: string }) => {\n try {\n const output = await deleteCommand({\n sessionIds: ids,\n sessionsDir: options.sessionsDir,\n onWarning: writeWarning,\n });\n console.log(output);\n } catch (error) {\n handleError(error);\n }\n });\n\n // prune command\n sessionCmd\n .command(\"prune\")\n .description(\"Remove old todo sessions, keeping the most recent N\")\n .option(\"--keep <count>\", \"Number of sessions to keep (default: 5)\", \"5\")\n .option(\"--dry-run\", \"Show what would be deleted without deleting\")\n .option(\"--sessions-dir <path>\", \"Custom sessions directory\")\n .action(async (options: { keep?: string; dryRun?: boolean; sessionsDir?: string }) => {\n try {\n const keep = options.keep ? Number.parseInt(options.keep, 10) : undefined;\n const output = await pruneCommand({\n keep,\n dryRun: options.dryRun,\n sessionsDir: options.sessionsDir,\n onWarning: writeWarning,\n });\n console.log(output);\n } catch (error) {\n if (error instanceof PruneValidationError) {\n console.error(\"Error:\", error.message);\n process.exit(1);\n }\n handleError(error);\n }\n });\n\n // archive command\n sessionCmd\n .command(\"archive <id...>\")\n .description(\"Move one or more sessions to the archive directory\")\n .option(\"--sessions-dir <path>\", \"Custom sessions directory\")\n .action(async (ids: string[], options: { sessionsDir?: string }) => {\n try {\n const output = await archiveCommand({\n sessionIds: ids,\n sessionsDir: options.sessionsDir,\n onWarning: writeWarning,\n });\n console.log(output);\n } catch (error) {\n if (error instanceof SessionAlreadyArchivedError) {\n console.error(\"Error:\", error.message);\n process.exit(1);\n }\n handleError(error);\n }\n });\n}\n\n/**\n * Session CLI — Commander registration descriptor for the session subcommands.\n */\nexport const sessionDomain: Domain = {\n name: \"session\",\n description: \"Manage session workflow\",\n register: (program: Command) => {\n const sessionCmd = program\n .command(\"session\")\n .description(\"Manage session workflow\")\n .addHelpText(\"after\", SESSION_FORMAT_HELP);\n\n registerSessionCommands(sessionCmd);\n },\n};\n","import { readdir, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport type {\n DecisionKind,\n Kind,\n KindDefinition,\n NamingSchemaVersion,\n NodeKind,\n SpecTreeKindCategory,\n SpecTreeNodeState,\n} from \"./config\";\nimport {\n canonicalNamingSchemaVersion,\n compareNamingSchemaVersions,\n KIND_REGISTRY,\n SPEC_TREE_CONFIG,\n SPEC_TREE_EVIDENCE_FILE,\n SPEC_TREE_GRAMMAR,\n SPEC_TREE_KIND_CATEGORY,\n SPEC_TREE_NAMING_SCHEMA_VERSIONS,\n SPEC_TREE_NODE_STATE,\n} from \"./config\";\nexport {\n canonicalNamingSchemaVersion,\n compareNamingSchemaVersions,\n SPEC_TREE_NAMING_SCHEMA_VERSIONS,\n SPEC_TREE_NAMING_VERSION,\n SPEC_TREE_SUPERSEDED_NODE_SUFFIXES,\n supersededNodeSuffixes,\n} from \"./config\";\nexport { SPEC_TREE_EVIDENCE_FILE, SPEC_TREE_GRAMMAR, SPEC_TREE_NODE_STATE } from \"./config\";\nexport type { NamingSchemaVersion, SpecTreeNodeState } from \"./config\";\n\nconst SPEC_TREE_FIELD_KEY = {\n VERSION: \"version\",\n PRODUCT: \"product\",\n NODES: \"nodes\",\n DECISIONS: \"decisions\",\n TYPE: \"type\",\n KIND: \"kind\",\n CHILDREN: \"children\",\n ID: \"id\",\n ORDER: \"order\",\n SLUG: \"slug\",\n STATE: \"state\",\n} as const;\n\nexport const SPEC_TREE_ENTRY_TYPE = {\n PRODUCT: SPEC_TREE_FIELD_KEY.PRODUCT,\n NODE: SPEC_TREE_KIND_CATEGORY.NODE,\n DECISION: SPEC_TREE_KIND_CATEGORY.DECISION,\n EVIDENCE: \"evidence\",\n SUPERSEDED: \"superseded\",\n INVALID: \"invalid\",\n} as const;\n\nexport type SpecTreeEntryType = (typeof SPEC_TREE_ENTRY_TYPE)[keyof typeof SPEC_TREE_ENTRY_TYPE];\n\nexport const SPEC_TREE_FILESYSTEM_RECORD_TYPE = {\n DIRECTORY: \"directory\",\n FILE: \"file\",\n} as const;\n\nexport type SpecTreeFilesystemRecordType =\n (typeof SPEC_TREE_FILESYSTEM_RECORD_TYPE)[keyof typeof SPEC_TREE_FILESYSTEM_RECORD_TYPE];\n\nexport const SPEC_TREE_EVIDENCE_STATUS = {\n LINKED: \"linked\",\n FAILING: SPEC_TREE_NODE_STATE.FAILING,\n PASSING: SPEC_TREE_NODE_STATE.PASSING,\n} as const;\n\nexport type SpecTreeEvidenceStatus = (typeof SPEC_TREE_EVIDENCE_STATUS)[keyof typeof SPEC_TREE_EVIDENCE_STATUS];\n\nconst SPEC_TREE_EVIDENCE_FILE_TAILS = Object.values(SPEC_TREE_EVIDENCE_FILE.TAILS);\n\nexport const SPEC_TREE_PROJECTION = {\n VERSION: 1,\n KEYS: {\n VERSION: SPEC_TREE_FIELD_KEY.VERSION,\n PRODUCT: SPEC_TREE_FIELD_KEY.PRODUCT,\n NODES: SPEC_TREE_FIELD_KEY.NODES,\n DECISIONS: SPEC_TREE_FIELD_KEY.DECISIONS,\n },\n NODE_KEYS: {\n ID: SPEC_TREE_FIELD_KEY.ID,\n KIND: SPEC_TREE_FIELD_KEY.KIND,\n ORDER: SPEC_TREE_FIELD_KEY.ORDER,\n SLUG: SPEC_TREE_FIELD_KEY.SLUG,\n STATE: SPEC_TREE_FIELD_KEY.STATE,\n CHILDREN: SPEC_TREE_FIELD_KEY.CHILDREN,\n },\n DECISION_KEYS: {\n ID: SPEC_TREE_FIELD_KEY.ID,\n KIND: SPEC_TREE_FIELD_KEY.KIND,\n ORDER: SPEC_TREE_FIELD_KEY.ORDER,\n SLUG: SPEC_TREE_FIELD_KEY.SLUG,\n },\n} as const;\n\nexport const SPEC_TREE_SOURCE_ENTRY_KEYS = {\n TYPE: SPEC_TREE_FIELD_KEY.TYPE,\n KIND: SPEC_TREE_FIELD_KEY.KIND,\n} as const;\n\nexport type SpecTreeSourceEntryKey = (typeof SPEC_TREE_SOURCE_ENTRY_KEYS)[keyof typeof SPEC_TREE_SOURCE_ENTRY_KEYS];\n\nexport const SPEC_TREE_NODE_RELATION_KEYS = {\n CHILDREN: SPEC_TREE_FIELD_KEY.CHILDREN,\n DECISIONS: SPEC_TREE_FIELD_KEY.DECISIONS,\n} as const;\n\ntype SpecTreeNodeRelationKey = (typeof SPEC_TREE_NODE_RELATION_KEYS)[keyof typeof SPEC_TREE_NODE_RELATION_KEYS];\n\nexport type SpecTreeRegistry = typeof KIND_REGISTRY;\n\nexport type SpecTreeSourceRef = {\n readonly id: string;\n readonly path?: string;\n readonly url?: string;\n};\n\ntype SpecTreeSourceEntryBase = {\n readonly id: string;\n readonly ref?: SpecTreeSourceRef;\n};\n\nexport type SpecTreeProductSourceEntry = SpecTreeSourceEntryBase & {\n readonly type: typeof SPEC_TREE_ENTRY_TYPE.PRODUCT;\n readonly title: string;\n};\n\nexport type SpecTreeNodeSourceEntry = SpecTreeSourceEntryBase & {\n readonly type: typeof SPEC_TREE_ENTRY_TYPE.NODE;\n readonly kind: NodeKind;\n readonly order: number;\n readonly slug: string;\n readonly parentId?: string;\n readonly title?: string;\n};\n\nexport type SpecTreeDecisionSourceEntry = SpecTreeSourceEntryBase & {\n readonly type: typeof SPEC_TREE_ENTRY_TYPE.DECISION;\n readonly kind: DecisionKind;\n readonly order: number;\n readonly slug: string;\n readonly parentId?: string;\n readonly title?: string;\n};\n\nexport type SpecTreeEvidenceSourceEntry = SpecTreeSourceEntryBase & {\n readonly type: typeof SPEC_TREE_ENTRY_TYPE.EVIDENCE;\n readonly parentId: string;\n readonly status: SpecTreeEvidenceStatus;\n};\n\nexport type SpecTreeSupersededSourceEntry = SpecTreeSourceEntryBase & {\n readonly type: typeof SPEC_TREE_ENTRY_TYPE.SUPERSEDED;\n readonly version: string;\n readonly parentId?: string;\n};\n\nexport type SpecTreeInvalidSourceEntry = SpecTreeSourceEntryBase & {\n readonly type: typeof SPEC_TREE_ENTRY_TYPE.INVALID;\n readonly parentId?: string;\n};\n\nexport type SpecTreeSourceEntry =\n | SpecTreeProductSourceEntry\n | SpecTreeNodeSourceEntry\n | SpecTreeDecisionSourceEntry\n | SpecTreeEvidenceSourceEntry\n | SpecTreeSupersededSourceEntry\n | SpecTreeInvalidSourceEntry;\n\nexport type SpecTreeSource = {\n entries(): AsyncIterable<SpecTreeSourceEntry>;\n readText?(ref: SpecTreeSourceRef): Promise<string>;\n};\n\nexport type SpecTreeFilesystemRecord = {\n readonly type: SpecTreeFilesystemRecordType;\n readonly relativePath: string;\n readonly parentId?: string;\n};\n\nexport type SpecTreePathInclusionPredicate = (path: string) => boolean | Promise<boolean>;\n\nexport type FilesystemSpecTreeSourceOptions = {\n readonly productDir: string;\n readonly registry?: SpecTreeRegistry;\n readonly schemaVersions?: readonly NamingSchemaVersion[];\n readonly includePath?: SpecTreePathInclusionPredicate;\n};\n\nexport type SpecTreeRecognitionOptions = {\n readonly registry?: SpecTreeRegistry;\n readonly schemaVersions?: readonly NamingSchemaVersion[];\n};\n\nexport type SpecTreeEvidenceProvider = {\n stateForNode?(\n node: SpecTreeNodeSourceEntry,\n evidence: readonly SpecTreeEvidenceSourceEntry[],\n ): SpecTreeNodeState | undefined;\n};\n\nexport type SpecTreeOptions = {\n readonly source: SpecTreeSource;\n readonly registry?: SpecTreeRegistry;\n readonly evidence?: SpecTreeEvidenceProvider;\n};\n\nexport type SpecTreeProduct = {\n readonly id: string;\n readonly title: string;\n readonly ref?: SpecTreeSourceRef;\n};\n\nexport type SpecTreeDecision = {\n readonly id: string;\n readonly kind: DecisionKind;\n readonly order: number;\n readonly slug: string;\n readonly parentId?: string;\n readonly title?: string;\n readonly ref?: SpecTreeSourceRef;\n};\n\nexport type SpecTreeNode = {\n readonly id: string;\n readonly kind: NodeKind;\n readonly order: number;\n readonly slug: string;\n readonly parentId?: string;\n readonly title?: string;\n readonly ref?: SpecTreeSourceRef;\n readonly state: SpecTreeNodeState;\n readonly decisions: readonly SpecTreeDecision[];\n readonly children: readonly SpecTreeNode[];\n};\n\nexport type SpecTreeSnapshot = {\n readonly product: SpecTreeProduct | null;\n readonly nodes: readonly SpecTreeNode[];\n readonly allNodes: readonly SpecTreeNode[];\n readonly decisions: readonly SpecTreeDecision[];\n readonly superseded: readonly SpecTreeSupersededSourceEntry[];\n readonly residual: readonly SpecTreeInvalidSourceEntry[];\n readonly entries: readonly SpecTreeSourceEntry[];\n};\n\nexport type SpecTreeProjectedNode = {\n readonly id: string;\n readonly kind: NodeKind;\n readonly order: number;\n readonly slug: string;\n readonly state: SpecTreeNodeState;\n readonly children: readonly SpecTreeProjectedNode[];\n};\n\nexport type SpecTreeProjectedDecision = {\n readonly id: string;\n readonly kind: DecisionKind;\n readonly order: number;\n readonly slug: string;\n};\n\nexport type SpecTreeProjectedProduct = {\n readonly id: string;\n readonly title: string;\n};\n\nexport type SpecTreeProjection = {\n readonly version: typeof SPEC_TREE_PROJECTION.VERSION;\n readonly product: SpecTreeProjectedProduct | null;\n readonly nodes: readonly SpecTreeProjectedNode[];\n readonly decisions: readonly SpecTreeProjectedDecision[];\n};\n\ntype MutableSpecTreeNode = Omit<SpecTreeNode, SpecTreeNodeRelationKey> & {\n readonly children: MutableSpecTreeNode[];\n readonly decisions: SpecTreeDecision[];\n};\n\ntype OrderedEntry = {\n readonly id: string;\n readonly order: number;\n};\n\nconst ORDER_COMPARISON_EQUAL = 0;\nconst SPEC_TREE_PATH_SEPARATOR = SPEC_TREE_GRAMMAR.PATH_SEPARATOR;\nconst SPEC_TREE_ORDER_SEPARATOR = SPEC_TREE_GRAMMAR.ORDER.SEPARATOR;\nconst SPEC_TREE_ORDER_RADIX = 10;\nconst SPEC_TREE_TEXT_ENCODING = \"utf8\";\nconst SPEC_TREE_EMPTY_RELATIVE_PATH = \"\";\nconst SPEC_TREE_ORDER_PATTERN = SPEC_TREE_GRAMMAR.ORDER.PATTERN;\nconst SPEC_TREE_MIN_EVIDENCE_PATH_SEGMENTS = 2;\nconst SPEC_TREE_PARENT_SEGMENT_OFFSET = 2;\nconst SPEC_TREE_FIRST_EVIDENCE_MARKER_INDEX = 1;\nconst SPEC_TREE_EXACTLY_ONE_EVIDENCE_MARKER = 1;\n\nexport function getKindDefinition<K extends keyof SpecTreeRegistry>(\n kind: K,\n registry: SpecTreeRegistry = KIND_REGISTRY,\n): KindDefinition<K> {\n return registry[kind];\n}\n\nexport function createFilesystemSpecTreeSource(options: FilesystemSpecTreeSourceOptions): SpecTreeSource {\n const registry = options.registry ?? KIND_REGISTRY;\n const schemaVersions = options.schemaVersions ?? SPEC_TREE_NAMING_SCHEMA_VERSIONS;\n const includePath = options.includePath ?? includeEverySpecTreePath;\n\n return {\n entries: () => readFilesystemSourceEntries(options.productDir, registry, schemaVersions, includePath),\n async readText(ref: SpecTreeSourceRef): Promise<string> {\n if (ref.path === undefined) {\n throw new Error(\"Filesystem source refs require a path\");\n }\n return readFile(join(options.productDir, ref.path), SPEC_TREE_TEXT_ENCODING);\n },\n };\n}\n\nexport function recognizeSpecTreeFilesystemEntry(\n record: SpecTreeFilesystemRecord,\n options: SpecTreeRecognitionOptions = {},\n): SpecTreeSourceEntry | null {\n const registry = options.registry ?? KIND_REGISTRY;\n const schemaVersions = options.schemaVersions ?? SPEC_TREE_NAMING_SCHEMA_VERSIONS;\n const name = readLastPathSegment(record.relativePath);\n\n if (record.type === SPEC_TREE_FILESYSTEM_RECORD_TYPE.FILE && isProductFile(record.relativePath)) {\n return {\n type: SPEC_TREE_ENTRY_TYPE.PRODUCT,\n id: record.relativePath,\n title: stripSuffix(name, SPEC_TREE_CONFIG.PRODUCT.SUFFIX),\n ref: sourceRefForRelativePath(record.relativePath),\n };\n }\n\n if (record.type === SPEC_TREE_FILESYSTEM_RECORD_TYPE.DIRECTORY) {\n return recognizeDirectoryRecord(record, name, registry, schemaVersions);\n }\n\n if (\n record.type === SPEC_TREE_FILESYSTEM_RECORD_TYPE.FILE\n && record.parentId !== undefined\n && isEvidenceFile(record.relativePath)\n ) {\n return {\n type: SPEC_TREE_ENTRY_TYPE.EVIDENCE,\n id: record.relativePath,\n parentId: record.parentId,\n status: SPEC_TREE_EVIDENCE_STATUS.LINKED,\n ref: sourceRefForRelativePath(record.relativePath),\n };\n }\n\n if (record.type === SPEC_TREE_FILESYSTEM_RECORD_TYPE.FILE) {\n const decisionMatch = matchKindSuffix(name, registry, SPEC_TREE_KIND_CATEGORY.DECISION);\n if (decisionMatch === null) return null;\n const parsed = parseOrderedSlug(stripSuffix(name, decisionMatch.definition.suffix));\n if (parsed === null) return null;\n return {\n type: SPEC_TREE_ENTRY_TYPE.DECISION,\n kind: decisionMatch.kind as DecisionKind,\n id: record.relativePath,\n order: parsed.order,\n slug: parsed.slug,\n parentId: record.parentId,\n ref: sourceRefForRelativePath(record.relativePath),\n };\n }\n\n return null;\n}\n\nfunction recognizeDirectoryRecord(\n record: SpecTreeFilesystemRecord,\n name: string,\n registry: SpecTreeRegistry,\n schemaVersions: readonly NamingSchemaVersion[],\n): SpecTreeSourceEntry | null {\n const canonical = canonicalNamingSchemaVersion(schemaVersions);\n const canonicalMatch = matchNodeSuffixFromVersion(name, canonical);\n if (canonicalMatch !== null) {\n const kind = nodeKindForSuffix(canonicalMatch.suffix, registry);\n if (kind !== null) {\n return {\n type: SPEC_TREE_ENTRY_TYPE.NODE,\n kind,\n id: record.relativePath,\n order: canonicalMatch.parsed.order,\n slug: canonicalMatch.parsed.slug,\n parentId: record.parentId,\n ref: sourceRefForNode(record.relativePath, canonicalMatch.parsed.slug),\n };\n }\n }\n\n const supersededVersion = matchSupersededNodeVersion(name, schemaVersions, canonical);\n if (supersededVersion !== null) {\n return {\n type: SPEC_TREE_ENTRY_TYPE.SUPERSEDED,\n id: record.relativePath,\n version: supersededVersion,\n parentId: record.parentId,\n ref: sourceRefForRelativePath(record.relativePath),\n };\n }\n\n // An ordered-form attempt: parseOrderedSlug folds the unrecognized suffix into the\n // slug component (it splits on the first separator and accepts any non-empty slug),\n // so a `{NN}-{slug}{unknown-suffix}` directory parses here and is retained as invalid\n // rather than dropped.\n if (parseOrderedSlug(name) !== null) {\n return {\n type: SPEC_TREE_ENTRY_TYPE.INVALID,\n id: record.relativePath,\n parentId: record.parentId,\n ref: sourceRefForRelativePath(record.relativePath),\n };\n }\n\n return null;\n}\n\ntype NodeSuffixMatch = {\n readonly suffix: string;\n readonly parsed: OrderedSlug;\n};\n\nfunction matchNodeSuffixFromVersion(name: string, version: NamingSchemaVersion): NodeSuffixMatch | null {\n for (const suffix of version.nodeSuffixes) {\n if (!name.endsWith(suffix)) continue;\n const parsed = parseOrderedSlug(stripSuffix(name, suffix));\n if (parsed !== null) {\n return { suffix, parsed };\n }\n }\n return null;\n}\n\nfunction nodeKindForSuffix(suffix: string, registry: SpecTreeRegistry): NodeKind | null {\n for (const [kind, definition] of Object.entries(registry) as Array<[Kind, KindDefinition<Kind>]>) {\n if (definition.category === SPEC_TREE_KIND_CATEGORY.NODE && definition.suffix === suffix) {\n return kind as NodeKind;\n }\n }\n return null;\n}\n\nfunction matchSupersededNodeVersion(\n name: string,\n schemaVersions: readonly NamingSchemaVersion[],\n canonical: NamingSchemaVersion,\n): string | null {\n const canonicalSuffixes = new Set(canonical.nodeSuffixes);\n const priorVersions = schemaVersions\n .filter((version) => version !== canonical)\n .sort((left, right) => compareNamingSchemaVersions(right, left));\n\n for (const version of priorVersions) {\n for (const suffix of version.nodeSuffixes) {\n if (canonicalSuffixes.has(suffix)) continue;\n if (name.endsWith(suffix) && parseOrderedSlug(stripSuffix(name, suffix)) !== null) {\n return version.version;\n }\n }\n }\n return null;\n}\n\nexport async function readSpecTree(options: SpecTreeOptions): Promise<SpecTreeSnapshot> {\n const entries = await collectSourceEntries(options.source);\n const product = entries.find(isProductEntry) ?? null;\n const superseded = entries.filter(isSupersededEntry);\n const residual = entries.filter(isInvalidEntry);\n const evidenceByParent = groupEvidence(entries.filter(isEvidenceEntry));\n const decisions = entries.filter(isDecisionEntry).map(toDecision).sort(compareOrderedEntries);\n const decisionsByParent = groupDecisions(decisions);\n const nodesById = new Map<string, MutableSpecTreeNode>();\n\n for (const entry of entries.filter(isNodeEntry)) {\n const state = deriveState(entry, evidenceByParent.get(entry.id) ?? [], options.evidence);\n nodesById.set(entry.id, {\n id: entry.id,\n kind: entry.kind,\n order: entry.order,\n slug: entry.slug,\n parentId: entry.parentId,\n title: entry.title,\n ref: entry.ref,\n state,\n decisions: decisionsByParent.get(entry.id) ?? [],\n children: [],\n });\n }\n\n const roots: MutableSpecTreeNode[] = [];\n for (const node of nodesById.values()) {\n const parent = node.parentId === undefined ? undefined : nodesById.get(node.parentId);\n if (parent === undefined) {\n roots.push(node);\n } else {\n parent.children.push(node);\n }\n }\n\n sortNodes(roots);\n const allNodes = flattenNodes(roots);\n\n return {\n product: product === null\n ? null\n : {\n id: product.id,\n title: product.title,\n ref: product.ref,\n },\n nodes: roots,\n allNodes,\n decisions,\n superseded,\n residual,\n entries,\n };\n}\n\nexport function projectSpecTree(snapshot: SpecTreeSnapshot): SpecTreeProjection {\n return {\n version: SPEC_TREE_PROJECTION.VERSION,\n product: snapshot.product === null\n ? null\n : {\n id: snapshot.product.id,\n title: snapshot.product.title,\n },\n nodes: snapshot.nodes.map(projectNode),\n decisions: snapshot.decisions.map((decision) => ({\n id: decision.id,\n kind: decision.kind,\n order: decision.order,\n slug: decision.slug,\n })),\n };\n}\n\nexport function findNextSpecTreeNode(snapshot: SpecTreeSnapshot): SpecTreeNode | null {\n return findFirstNonPassing(snapshot.nodes);\n}\n\nasync function collectSourceEntries(source: SpecTreeSource): Promise<SpecTreeSourceEntry[]> {\n const entries: SpecTreeSourceEntry[] = [];\n for await (const entry of source.entries()) {\n entries.push(entry);\n }\n return entries;\n}\n\nfunction isProductEntry(entry: SpecTreeSourceEntry): entry is SpecTreeProductSourceEntry {\n return entry.type === SPEC_TREE_ENTRY_TYPE.PRODUCT;\n}\n\nfunction isNodeEntry(entry: SpecTreeSourceEntry): entry is SpecTreeNodeSourceEntry {\n return entry.type === SPEC_TREE_ENTRY_TYPE.NODE;\n}\n\nfunction isDecisionEntry(entry: SpecTreeSourceEntry): entry is SpecTreeDecisionSourceEntry {\n return entry.type === SPEC_TREE_ENTRY_TYPE.DECISION;\n}\n\nfunction isEvidenceEntry(entry: SpecTreeSourceEntry): entry is SpecTreeEvidenceSourceEntry {\n return entry.type === SPEC_TREE_ENTRY_TYPE.EVIDENCE;\n}\n\nfunction isSupersededEntry(entry: SpecTreeSourceEntry): entry is SpecTreeSupersededSourceEntry {\n return entry.type === SPEC_TREE_ENTRY_TYPE.SUPERSEDED;\n}\n\nfunction isInvalidEntry(entry: SpecTreeSourceEntry): entry is SpecTreeInvalidSourceEntry {\n return entry.type === SPEC_TREE_ENTRY_TYPE.INVALID;\n}\n\nfunction toDecision(entry: SpecTreeDecisionSourceEntry): SpecTreeDecision {\n return {\n id: entry.id,\n kind: entry.kind,\n order: entry.order,\n slug: entry.slug,\n parentId: entry.parentId,\n title: entry.title,\n ref: entry.ref,\n };\n}\n\nfunction groupEvidence(\n entries: readonly SpecTreeEvidenceSourceEntry[],\n): Map<string, SpecTreeEvidenceSourceEntry[]> {\n const grouped = new Map<string, SpecTreeEvidenceSourceEntry[]>();\n for (const entry of entries) {\n const group = grouped.get(entry.parentId) ?? [];\n group.push(entry);\n grouped.set(entry.parentId, group);\n }\n return grouped;\n}\n\nfunction groupDecisions(entries: readonly SpecTreeDecision[]): Map<string, SpecTreeDecision[]> {\n const grouped = new Map<string, SpecTreeDecision[]>();\n for (const entry of entries) {\n if (entry.parentId === undefined) continue;\n const group = grouped.get(entry.parentId) ?? [];\n group.push(entry);\n grouped.set(entry.parentId, group.sort(compareOrderedEntries));\n }\n return grouped;\n}\n\nfunction deriveState(\n node: SpecTreeNodeSourceEntry,\n evidence: readonly SpecTreeEvidenceSourceEntry[],\n provider?: SpecTreeEvidenceProvider,\n): SpecTreeNodeState {\n const provided = provider?.stateForNode?.(node, evidence);\n if (provided !== undefined) return provided;\n if (evidence.length === 0) return SPEC_TREE_NODE_STATE.DECLARED;\n if (evidence.some((entry) => entry.status === SPEC_TREE_EVIDENCE_STATUS.FAILING)) {\n return SPEC_TREE_NODE_STATE.FAILING;\n }\n if (evidence.every((entry) => entry.status === SPEC_TREE_EVIDENCE_STATUS.PASSING)) {\n return SPEC_TREE_NODE_STATE.PASSING;\n }\n return SPEC_TREE_NODE_STATE.SPECIFIED;\n}\n\nfunction sortNodes(nodes: MutableSpecTreeNode[]): void {\n nodes.sort(compareOrderedEntries);\n for (const node of nodes) {\n sortNodes(node.children);\n }\n}\n\nfunction flattenNodes(nodes: readonly MutableSpecTreeNode[]): readonly SpecTreeNode[] {\n return nodes.flatMap((node) => [node, ...flattenNodes(node.children)]);\n}\n\nfunction projectNode(node: SpecTreeNode): SpecTreeProjectedNode {\n return {\n id: node.id,\n kind: node.kind,\n order: node.order,\n slug: node.slug,\n state: node.state,\n children: node.children.map(projectNode),\n };\n}\n\nfunction findFirstNonPassing(nodes: readonly SpecTreeNode[]): SpecTreeNode | null {\n for (const node of nodes) {\n if (node.state !== SPEC_TREE_NODE_STATE.PASSING) return node;\n const child = findFirstNonPassing(node.children);\n if (child !== null) return child;\n }\n return null;\n}\n\nfunction compareOrderedEntries(left: OrderedEntry, right: OrderedEntry): number {\n const orderComparison = left.order - right.order;\n if (orderComparison !== ORDER_COMPARISON_EQUAL) return orderComparison;\n return left.id.localeCompare(right.id);\n}\n\nasync function* readFilesystemSourceEntries(\n productDir: string,\n registry: SpecTreeRegistry,\n schemaVersions: readonly NamingSchemaVersion[],\n includePath: SpecTreePathInclusionPredicate,\n): AsyncIterable<SpecTreeSourceEntry> {\n yield* walkFilesystemDirectory({\n absolutePath: join(productDir, SPEC_TREE_CONFIG.ROOT_DIRECTORY),\n relativePath: SPEC_TREE_EMPTY_RELATIVE_PATH,\n registry,\n schemaVersions,\n includePath,\n });\n}\n\ntype FilesystemWalkContext = {\n readonly absolutePath: string;\n readonly relativePath: string;\n readonly registry: SpecTreeRegistry;\n readonly schemaVersions: readonly NamingSchemaVersion[];\n readonly includePath: SpecTreePathInclusionPredicate;\n readonly parentId?: string;\n};\n\nasync function* walkFilesystemDirectory(context: FilesystemWalkContext): AsyncIterable<SpecTreeSourceEntry> {\n let entries;\n try {\n entries = await readdir(context.absolutePath, { withFileTypes: true });\n } catch (error) {\n if (isFileNotFound(error)) return;\n throw error;\n }\n\n const sortedEntries = [...entries].sort((left, right) => left.name.localeCompare(right.name));\n for (const entry of sortedEntries) {\n const relativePath = joinSpecTreePath(context.relativePath, entry.name);\n const refPath = joinSpecTreePath(SPEC_TREE_CONFIG.ROOT_DIRECTORY, relativePath);\n if (!await context.includePath(refPath)) continue;\n\n const recordType = entry.isDirectory()\n ? SPEC_TREE_FILESYSTEM_RECORD_TYPE.DIRECTORY\n : entry.isFile()\n ? SPEC_TREE_FILESYSTEM_RECORD_TYPE.FILE\n : undefined;\n if (recordType === undefined) continue;\n\n const sourceEntry = recognizeSpecTreeFilesystemEntry(\n { type: recordType, relativePath, parentId: context.parentId },\n { registry: context.registry, schemaVersions: context.schemaVersions },\n );\n if (sourceEntry !== null) yield sourceEntry;\n\n if (entry.isDirectory() && shouldDescendIntoDirectory(sourceEntry)) {\n yield* walkFilesystemDirectory({\n absolutePath: join(context.absolutePath, entry.name),\n relativePath,\n registry: context.registry,\n schemaVersions: context.schemaVersions,\n includePath: context.includePath,\n parentId: sourceEntry?.type === SPEC_TREE_ENTRY_TYPE.NODE ? sourceEntry.id : context.parentId,\n });\n }\n }\n}\n\ntype KindSuffixMatch = {\n readonly kind: string;\n readonly definition: KindDefinition<Kind>;\n};\n\nfunction matchKindSuffix(\n name: string,\n registry: SpecTreeRegistry,\n category: SpecTreeKindCategory,\n): KindSuffixMatch | null {\n for (const [kind, definition] of Object.entries(registry) as Array<[Kind, KindDefinition<Kind>]>) {\n if (definition.category === category && name.endsWith(definition.suffix)) {\n return { kind, definition };\n }\n }\n return null;\n}\n\ntype OrderedSlug = {\n readonly order: number;\n readonly slug: string;\n};\n\nfunction parseOrderedSlug(value: string): OrderedSlug | null {\n const separatorIndex = value.indexOf(SPEC_TREE_ORDER_SEPARATOR);\n if (separatorIndex <= ORDER_COMPARISON_EQUAL) return null;\n const orderText = value.slice(0, separatorIndex);\n if (!SPEC_TREE_ORDER_PATTERN.test(orderText)) return null;\n const slug = value.slice(separatorIndex + SPEC_TREE_ORDER_SEPARATOR.length);\n if (slug.length === 0) return null;\n return {\n order: Number.parseInt(orderText, SPEC_TREE_ORDER_RADIX),\n slug,\n };\n}\n\nfunction isProductFile(relativePath: string): boolean {\n return !relativePath.includes(SPEC_TREE_PATH_SEPARATOR) && relativePath.endsWith(SPEC_TREE_CONFIG.PRODUCT.SUFFIX);\n}\n\nfunction isEvidenceFile(relativePath: string): boolean {\n const segments = relativePath.split(SPEC_TREE_PATH_SEPARATOR);\n if (segments.length < SPEC_TREE_MIN_EVIDENCE_PATH_SEGMENTS) return false;\n\n const filename = segments[segments.length - 1] ?? \"\";\n const directoryName = segments[segments.length - SPEC_TREE_PARENT_SEGMENT_OFFSET];\n const filenameSegments = filename.split(SPEC_TREE_EVIDENCE_FILE.SEGMENT_SEPARATOR);\n\n return directoryName === SPEC_TREE_EVIDENCE_FILE.DIRECTORY_NAME\n && SPEC_TREE_EVIDENCE_FILE_TAILS.some((tail) =>\n SPEC_TREE_EVIDENCE_FILE.MODES.some((mode) =>\n SPEC_TREE_EVIDENCE_FILE.LEVELS.some((level) => filenameHasEvidenceSuffix(filenameSegments, mode, level, tail))\n )\n );\n}\n\nfunction filenameHasEvidenceSuffix(\n filenameSegments: readonly string[],\n mode: string,\n level: string,\n tail: readonly string[],\n): boolean {\n if (!segmentsEndWith(filenameSegments, tail)) return false;\n const tailStart = filenameSegments.length - tail.length;\n let evidenceMarkerCount = 0;\n\n // Exactly one mode/level pair prevents ambiguous filenames from being treated as evidence.\n for (let index = SPEC_TREE_FIRST_EVIDENCE_MARKER_INDEX; index < tailStart - 1; index += 1) {\n if (filenameSegments[index] === mode && filenameSegments[index + 1] === level) {\n evidenceMarkerCount += 1;\n }\n }\n\n return evidenceMarkerCount === SPEC_TREE_EXACTLY_ONE_EVIDENCE_MARKER;\n}\n\nfunction segmentsEndWith(segments: readonly string[], suffix: readonly string[]): boolean {\n if (segments.length <= suffix.length) return false;\n const start = segments.length - suffix.length;\n return suffix.every((value, index) => segments[start + index] === value);\n}\n\nfunction shouldDescendIntoDirectory(sourceEntry: SpecTreeSourceEntry | null): boolean {\n return sourceEntry === null || sourceEntry.type === SPEC_TREE_ENTRY_TYPE.NODE;\n}\n\nfunction sourceRefForRelativePath(relativePath: string): SpecTreeSourceRef {\n const path = joinSpecTreePath(SPEC_TREE_CONFIG.ROOT_DIRECTORY, relativePath);\n return { id: path, path };\n}\n\nfunction sourceRefForNode(relativePath: string, slug: string): SpecTreeSourceRef {\n return sourceRefForRelativePath(joinSpecTreePath(relativePath, `${slug}.md`));\n}\n\nfunction stripSuffix(value: string, suffix: string): string {\n return value.slice(0, value.length - suffix.length);\n}\n\nfunction readLastPathSegment(relativePath: string): string {\n const segments = relativePath.split(SPEC_TREE_PATH_SEPARATOR);\n return segments[segments.length - 1] ?? relativePath;\n}\n\nfunction joinSpecTreePath(...segments: readonly string[]): string {\n return segments.filter((segment) => segment.length > 0).join(SPEC_TREE_PATH_SEPARATOR);\n}\n\nfunction includeEverySpecTreePath(): boolean {\n return true;\n}\n\nfunction isFileNotFound(error: unknown): boolean {\n return error instanceof Error && \"code\" in error && (error as NodeJS.ErrnoException).code === \"ENOENT\";\n}\n","import { detectWorktreeProductRoot, type GitDependencies } from \"@/git/root\";\nimport { SPEC_TREE_CONFIG } from \"@/lib/spec-tree/config\";\n\nexport const SPEC_PRODUCT_DIR_WARNING = {\n NOT_GIT_REPOSITORY:\n `Warning: Not in a git repository. Reading ${SPEC_TREE_CONFIG.ROOT_DIRECTORY} relative to the current working directory.`,\n} as const;\n\nexport type SpecProductDirWarningHandler = (warning: string) => void;\n\nexport async function resolveSpecProductDir(\n cwd: string,\n gitDependencies?: GitDependencies,\n onWarning?: SpecProductDirWarningHandler,\n): Promise<string> {\n const result = await detectWorktreeProductRoot(cwd, gitDependencies);\n if (!result.isGitRepo) {\n // Spec commands read tracked spx/ files, so the fallback warning names that domain.\n onWarning?.(SPEC_PRODUCT_DIR_WARNING.NOT_GIT_REPOSITORY);\n }\n return result.productDir;\n}\n","import type { GitDependencies } from \"@/git/root\";\nimport {\n createFilesystemSpecTreeSource,\n findNextSpecTreeNode,\n readSpecTree,\n type SpecTreeNode,\n type SpecTreeSnapshot,\n type SpecTreeSource,\n} from \"@/lib/spec-tree\";\nimport { KIND_REGISTRY, SPEC_TREE_CONFIG } from \"@/lib/spec-tree/config\";\nimport { resolveSpecProductDir, type SpecProductDirWarningHandler } from \"./root\";\n\nexport const SPEC_NEXT_MESSAGE = {\n EMPTY: `No spec-tree nodes found in ${SPEC_TREE_CONFIG.ROOT_DIRECTORY}`,\n COMPLETE: \"All spec-tree nodes are passing\",\n HEADING: \"Next spec-tree node:\",\n KIND_LABEL: \"Kind\",\n PATH_LABEL: \"Path\",\n STATE_LABEL: \"State\",\n} as const;\n\nconst INDENT = \" \";\n\nexport interface NextOptions {\n cwd?: string;\n gitDependencies?: GitDependencies;\n onWarning?: SpecProductDirWarningHandler;\n source?: SpecTreeSource;\n}\n\nexport async function nextCommand(options: NextOptions = {}): Promise<string> {\n if (options.source !== undefined) {\n // Injected sources bypass filesystem and git resolution.\n const snapshot = await readSpecTree({ source: options.source });\n return formatNextSpecTreeNode(snapshot);\n }\n\n const productDir = await resolveSpecProductDir(\n options.cwd ?? process.cwd(),\n options.gitDependencies,\n options.onWarning,\n );\n const source = createFilesystemSpecTreeSource({ productDir });\n const snapshot = await readSpecTree({ source });\n\n return formatNextSpecTreeNode(snapshot);\n}\n\nfunction formatNextSpecTreeNode(snapshot: SpecTreeSnapshot): string {\n if (snapshot.allNodes.length === 0) {\n return SPEC_NEXT_MESSAGE.EMPTY;\n }\n\n const next = findNextSpecTreeNode(snapshot);\n\n if (next === null) {\n return SPEC_NEXT_MESSAGE.COMPLETE;\n }\n\n return formatNextNode(next);\n}\n\nfunction formatNextNode(node: SpecTreeNode): string {\n return [\n SPEC_NEXT_MESSAGE.HEADING,\n \"\",\n `${INDENT}${SPEC_NEXT_MESSAGE.PATH_LABEL}: ${node.id}`,\n `${INDENT}${SPEC_NEXT_MESSAGE.KIND_LABEL}: ${KIND_REGISTRY[node.kind].label}`,\n `${INDENT}${SPEC_NEXT_MESSAGE.STATE_LABEL}: ${node.state}`,\n ].join(\"\\n\");\n}\n","import type { Dirent } from \"node:fs\";\nimport { readdir } from \"node:fs/promises\";\nimport { join, relative, sep } from \"node:path\";\n\nimport { SPEC_TREE_EVIDENCE_FILE } from \"@/lib/spec-tree\";\nimport { SPEC_TREE_CONFIG } from \"@/lib/spec-tree/config\";\n\nconst TESTS_DIRECTORY_NAME = SPEC_TREE_EVIDENCE_FILE.DIRECTORY_NAME;\nconst SPEC_ROOT_DIRECTORY = SPEC_TREE_CONFIG.ROOT_DIRECTORY;\nconst POSIX_SEPARATOR = \"/\";\nconst ERROR_CODE_NOT_FOUND = \"ENOENT\";\n\n/**\n * Walks the tracked spec tree under `productDir` and returns every file inside a\n * `tests/` directory, as POSIX paths relative to `productDir`, in deterministic\n * ascending order. Partitioning the files by language is a separate, pure concern.\n */\nexport async function discoverTestFiles(productDir: string): Promise<readonly string[]> {\n const found: string[] = [];\n await collectTestFiles(join(productDir, SPEC_ROOT_DIRECTORY), false, found);\n return found.map((absolute) => toPosixRelative(productDir, absolute)).sort(compareAscii);\n}\n\nasync function collectTestFiles(directory: string, insideTestsDir: boolean, found: string[]): Promise<void> {\n let entries: readonly Dirent[];\n try {\n entries = await readdir(directory, { withFileTypes: true });\n } catch (error) {\n if (hasErrorCode(error, ERROR_CODE_NOT_FOUND)) return;\n throw error;\n }\n\n for (const entry of entries) {\n const childPath = join(directory, entry.name);\n if (entry.isDirectory()) {\n await collectTestFiles(childPath, insideTestsDir || entry.name === TESTS_DIRECTORY_NAME, found);\n } else if (insideTestsDir && entry.isFile()) {\n found.push(childPath);\n }\n }\n}\n\nfunction toPosixRelative(productDir: string, absolute: string): string {\n return relative(productDir, absolute).split(sep).join(POSIX_SEPARATOR);\n}\n\nfunction compareAscii(left: string, right: string): number {\n if (left < right) return -1;\n if (left > right) return 1;\n return 0;\n}\n\nfunction hasErrorCode(error: unknown, code: string): boolean {\n return typeof error === \"object\" && error !== null && (error as { code?: unknown }).code === code;\n}\n","import type { TestRunInvocation } from \"@/testing/languages/types\";\n\nexport const SUCCESS_EXIT_CODE = 0;\n\n/**\n * Aggregates per-language runner invocations into a single command exit code:\n * the first invoked runner's non-zero exit code, or success when every invoked\n * runner exited zero. Runners that detection gated out do not contribute.\n */\nexport function aggregateTestExitCode(invocations: readonly TestRunInvocation[]): number {\n for (const invocation of invocations) {\n if (invocation.invoked && invocation.exitCode !== SUCCESS_EXIT_CODE) {\n return invocation.exitCode;\n }\n }\n return SUCCESS_EXIT_CODE;\n}\n","import type { TestingLanguageDescriptor } from \"@/testing/languages/types\";\n\n/** A registered language paired with the discovered test files it owns. */\nexport interface LanguageTestGroup {\n readonly language: TestingLanguageDescriptor;\n readonly testPaths: readonly string[];\n}\n\n/** Discovered test files partitioned by owning language, plus the files no language claims. */\nexport interface TestFileGrouping {\n readonly groups: readonly LanguageTestGroup[];\n readonly unmatched: readonly string[];\n}\n\n/**\n * Partitions discovered test files by the first registered language whose\n * `matchesTestFile` claims each file; files no language claims become\n * `unmatched`. Group order follows registry order, and only languages with at\n * least one matching file produce a group.\n */\nexport function groupTestFiles(\n testFiles: readonly string[],\n languages: readonly TestingLanguageDescriptor[],\n): TestFileGrouping {\n const pathsByLanguage = new Map<TestingLanguageDescriptor, string[]>();\n const unmatched: string[] = [];\n\n for (const testFile of testFiles) {\n const language = languages.find((candidate) => candidate.matchesTestFile(testFile));\n if (language === undefined) {\n unmatched.push(testFile);\n continue;\n }\n const existing = pathsByLanguage.get(language);\n if (existing === undefined) {\n pathsByLanguage.set(language, [testFile]);\n } else {\n existing.push(testFile);\n }\n }\n\n const groups: LanguageTestGroup[] = languages\n .filter((language) => pathsByLanguage.has(language))\n .map((language) => ({ language, testPaths: pathsByLanguage.get(language) ?? [] }));\n\n return { groups, unmatched };\n}\n","import { applyPathFilter, type PathFilterConfig } from \"@/config/primitives\";\nimport { aggregateTestExitCode, groupTestFiles, type LanguageTestGroup } from \"@/domains/testing\";\nimport type { TestingLanguageDescriptor, TestRunInvocation, TestRunnerDependencies } from \"@/testing/languages/types\";\nimport type { TestingRegistry } from \"@/testing/registry\";\nimport type { TestRunnerOutcome } from \"@/testing/run-state\";\n\nimport { discoverTestFiles } from \"./discovery\";\n\n/**\n * Outcome of a `spx test` dispatch: aggregate exit code, the dispatched groups,\n * the skipped files, and the per-runner outcomes the recording path consumes. The\n * outcomes' test paths are the set this run covered.\n */\nexport interface TestDispatchResult {\n readonly exitCode: number;\n readonly groups: readonly LanguageTestGroup[];\n readonly unmatched: readonly string[];\n readonly outcomes: readonly TestRunnerOutcome[];\n}\n\nexport interface TestDispatchOptions {\n readonly productDir: string;\n readonly registry: TestingRegistry;\n /** When present, discovered files are filtered by this scope before dispatch (`spx test passing`). */\n readonly passingScope?: PathFilterConfig;\n}\n\nexport interface TestDispatchDependencies {\n /** Supplies the detection and command-runner dependencies for a given language. */\n readonly runnerDepsFor: (language: TestingLanguageDescriptor) => TestRunnerDependencies;\n}\n\n// Passing-scope filtering removes files before grouping; the dispatch passes no\n// runner-level node exclusions, so each runner receives exactly the kept files.\nconst NO_EXCLUDED_NODE_PATHS: readonly string[] = [];\n\n/**\n * Discovers the spec tree's test files, partitions them by registered language,\n * dispatches each group to its language runner through the injected runner\n * dependencies, and aggregates the runners' exit codes into one command result.\n */\nexport async function runTests(\n options: TestDispatchOptions,\n deps: TestDispatchDependencies,\n): Promise<TestDispatchResult> {\n const discovered = await discoverTestFiles(options.productDir);\n const testFiles = options.passingScope === undefined\n ? discovered\n : applyPathFilter(discovered, options.passingScope);\n const { groups, unmatched } = groupTestFiles(testFiles, options.registry.languages);\n\n const invocations: TestRunInvocation[] = [];\n const outcomes: TestRunnerOutcome[] = [];\n for (const group of groups) {\n const invocation = await group.language.runTests(\n {\n projectRoot: options.productDir,\n testPaths: group.testPaths,\n excludedNodePaths: NO_EXCLUDED_NODE_PATHS,\n },\n deps.runnerDepsFor(group.language),\n );\n invocations.push(invocation);\n // A gated-out runner (not invoked) produces no observed outcome to record.\n if (invocation.invoked) {\n outcomes.push({\n runnerId: group.language.name,\n testPaths: group.testPaths,\n exitCode: invocation.exitCode,\n });\n }\n }\n\n return { exitCode: aggregateTestExitCode(invocations), groups, unmatched, outcomes };\n}\n","import { join } from \"node:path\";\n\nimport { digestDescriptorSection } from \"@/config/descriptor-digest\";\nimport { resolveConfig } from \"@/config/index\";\nimport { SUCCESS_EXIT_CODE } from \"@/domains/testing\";\nimport { getCurrentBranch, getHeadSha, type GitDependencies } from \"@/git/root\";\nimport { compareAsciiStrings, hasErrorCode } from \"@/lib/state-store\";\nimport { TESTING_SECTION, type TestingConfig, testingConfigDescriptor } from \"@/testing/config\";\nimport type { TestingLanguageDescriptor, TestRunnerDependencies } from \"@/testing/languages/types\";\nimport type { TestingRegistry } from \"@/testing/registry\";\nimport {\n createTestRunFile,\n defaultTestRunStateFileSystem,\n digestTestContents,\n digestTestPaths,\n formatTestRunTimestamp,\n type ProductInputDigest,\n type StalenessInputs,\n TESTING_RUN_STATE_ERROR_CODE,\n TEST_RUN_STATE_STATUS,\n type TestContentEntry,\n type TestRunFile,\n type TestRunnerOutcome,\n type TestRunState,\n type TestRunStateFileSystem,\n type TestRunStateStatus,\n writeTerminalTestRunState,\n} from \"@/testing/run-state\";\n\nimport { runTests, type TestDispatchResult } from \"./dispatch\";\n\n// Non-empty sentinel for branch/head-SHA when git resolution returns null (no\n// repo, detached HEAD, or no commits) — the recorded state's identity fields must\n// satisfy the non-empty-string contract `readTestingRuns` enforces on read.\nexport const NO_GIT_IDENTITY = \"(unknown)\";\nconst TEXT_ENCODING = \"utf8\";\nconst PRODUCT_INPUT_FIELDS = {\n PATH: \"path\",\n PRESENT: \"present\",\n CONTENT: \"content\",\n} as const;\n\n/** Shared command dependencies; filesystem, clock, and git default to real access. */\nexport interface TestCommandDependencies {\n readonly registry: TestingRegistry;\n readonly runnerDepsFor: (language: TestingLanguageDescriptor) => TestRunnerDependencies;\n /** Git access for branch and head-SHA identity; defaults to real git resolution. */\n readonly git?: GitDependencies;\n /** State filesystem for recording and discovered-content reads; defaults to real fs. */\n readonly fs?: TestRunStateFileSystem;\n /** Clock for run timestamps; defaults to the system clock. */\n readonly now?: () => Date;\n}\n\nexport interface RunTestsCommandOptions {\n readonly productDir: string;\n /** True for `spx test passing` — apply the configured passing scope before dispatch. */\n readonly passing: boolean;\n}\n\nexport interface RecordedTestRun {\n readonly dispatch: TestDispatchResult;\n readonly recorded: TestRunState;\n}\n\nexport interface RunNodeCommandOptions {\n readonly productDir: string;\n /** Full product-root path of the node whose tests run, e.g. `spx/41-testing.enabler`. */\n readonly nodePath: string;\n}\n\n// Recording dependencies with real-access defaults applied; the injectable\n// filesystem, clock, and git access resolve here once per command.\ninterface RecordingDependencies {\n readonly fs: TestRunStateFileSystem;\n readonly now: () => Date;\n readonly git?: GitDependencies;\n}\n\nfunction resolveRecordingDependencies(deps: TestCommandDependencies): RecordingDependencies {\n return {\n fs: deps.fs ?? defaultTestRunStateFileSystem,\n now: deps.now ?? (() => new Date()),\n git: deps.git,\n };\n}\n\n// Resolves the testing config and its canonical digest, the staleness input that\n// detects testing-policy changes. Throws with context on a malformed config.\nasync function resolveTestingConfig(productDir: string): Promise<{ config: TestingConfig; digest: string }> {\n const loaded = await resolveConfig(productDir, [testingConfigDescriptor]);\n if (!loaded.ok) {\n throw new Error(`failed to resolve testing config: ${loaded.error}`);\n }\n const config = loaded.value[TESTING_SECTION] as TestingConfig;\n const digest = digestDescriptorSection(config);\n if (!digest.ok) {\n throw new Error(`failed to digest testing config: ${digest.error}`);\n }\n return { config, digest: digest.value.sha256 };\n}\n\n// The files this run covered — the union of the dispatched runners' test paths.\n// Recording digests this set, so a per-node run covers only its node's files and a\n// full run covers every dispatched file.\nfunction coveredTestPaths(dispatch: TestDispatchResult): readonly string[] {\n return dispatch.outcomes.flatMap((outcome) => outcome.testPaths);\n}\n\nasync function readCoveredContents(\n productDir: string,\n paths: readonly string[],\n fs: TestRunStateFileSystem,\n): Promise<readonly TestContentEntry[]> {\n const entries: TestContentEntry[] = [];\n for (const path of paths) {\n entries.push({ path, content: await fs.readFile(join(productDir, path), TEXT_ENCODING) });\n }\n return entries;\n}\n\nasync function readProductInputEntries(\n productDir: string,\n paths: readonly string[],\n fs: TestRunStateFileSystem,\n): Promise<readonly Record<string, string | boolean>[]> {\n const entries: Array<Record<string, string | boolean>> = [];\n for (const path of [...paths].sort(compareAsciiStrings)) {\n try {\n entries.push({\n [PRODUCT_INPUT_FIELDS.PATH]: path,\n [PRODUCT_INPUT_FIELDS.PRESENT]: true,\n [PRODUCT_INPUT_FIELDS.CONTENT]: await fs.readFile(join(productDir, path), TEXT_ENCODING),\n });\n } catch (error) {\n if (!hasErrorCode(error, TESTING_RUN_STATE_ERROR_CODE.NOT_FOUND)) throw error;\n entries.push({\n [PRODUCT_INPUT_FIELDS.PATH]: path,\n [PRODUCT_INPUT_FIELDS.PRESENT]: false,\n });\n }\n }\n return entries;\n}\n\nasync function digestLanguageProductInputs(\n productDir: string,\n language: TestingLanguageDescriptor,\n coveredPaths: readonly string[],\n fs: TestRunStateFileSystem,\n): Promise<string> {\n const entries = await readProductInputEntries(productDir, languageProductInputPaths(language, coveredPaths), fs);\n const digest = digestDescriptorSection(entries, `${language.name} product inputs`);\n if (!digest.ok) {\n throw new Error(`failed to digest ${language.name} product inputs: ${digest.error}`);\n }\n return digest.value.sha256;\n}\n\nasync function productInputDigests(\n productDir: string,\n registry: TestingRegistry,\n coveredPaths: readonly string[],\n fs: TestRunStateFileSystem,\n): Promise<readonly ProductInputDigest[]> {\n const digests: ProductInputDigest[] = [];\n for (const language of registry.languages) {\n digests.push({\n descriptorId: language.name,\n digest: await digestLanguageProductInputs(productDir, language, coveredPaths, fs),\n });\n }\n return digests;\n}\n\nfunction deriveStatus(outcomes: readonly TestRunnerOutcome[]): TestRunStateStatus {\n const allPassed = outcomes.every((outcome) => outcome.exitCode === SUCCESS_EXIT_CODE);\n return allPassed ? TEST_RUN_STATE_STATUS.PASSED : TEST_RUN_STATE_STATUS.FAILED;\n}\n\n/**\n * Computes the four current staleness inputs (testing config digest, discovered\n * path-set digest, discovered content digest, product-input digests) over a\n * covered set of test paths. The recording path and the status resolver's\n * freshness check share this one recipe, so a node's recorded staleness inputs\n * and the current inputs later compared against them never diverge.\n */\nexport async function currentStalenessInputs(\n productDir: string,\n coveredPaths: readonly string[],\n deps: {\n readonly fs?: TestRunStateFileSystem;\n readonly registry: TestingRegistry;\n readonly testingConfigDigest?: string;\n },\n): Promise<StalenessInputs> {\n const fs = deps.fs ?? defaultTestRunStateFileSystem;\n // A caller that already resolved the testing config (e.g. runTestsCommand reading\n // passingScope) passes its digest so the config is read once per command; callers\n // holding no config (the per-node run, the status resolver) resolve it here.\n const testingConfigDigest = deps.testingConfigDigest ?? (await resolveTestingConfig(productDir)).digest;\n const contents = await readCoveredContents(productDir, coveredPaths, fs);\n return {\n testingConfigDigest,\n discoveredTestPathsDigest: digestTestPaths(coveredPaths),\n discoveredTestContentDigest: digestTestContents(contents),\n productInputDigests: await productInputDigests(productDir, deps.registry, coveredPaths, fs),\n };\n}\n\nfunction languageProductInputPaths(\n language: TestingLanguageDescriptor,\n coveredPaths: readonly string[],\n): readonly string[] {\n return [\n ...new Set([\n ...language.productInputPaths,\n ...(language.coveredProductInputPaths?.(coveredPaths) ?? []),\n ]),\n ].sort(compareAsciiStrings);\n}\n\n// The single recording path both the full run and the per-node run pass through:\n// assemble a TestRunState from the run's outcomes, the staleness digests over the\n// covered set, and the git identity, then persist it into the reserved directory.\nasync function recordRun(\n runFile: TestRunFile,\n productDir: string,\n dispatch: TestDispatchResult,\n recording: RecordingDependencies,\n registry: TestingRegistry,\n testingConfigDigest?: string,\n): Promise<TestRunState> {\n const staleness = await currentStalenessInputs(productDir, coveredTestPaths(dispatch), {\n fs: recording.fs,\n registry,\n testingConfigDigest,\n });\n const branchName = (await getCurrentBranch(productDir, recording.git)) ?? NO_GIT_IDENTITY;\n const headSha = (await getHeadSha(productDir, recording.git)) ?? NO_GIT_IDENTITY;\n\n const state: TestRunState = {\n branchName,\n headSha,\n testingConfigDigest: staleness.testingConfigDigest,\n runnerOutcomes: dispatch.outcomes,\n discoveredTestPathsDigest: staleness.discoveredTestPathsDigest,\n discoveredTestContentDigest: staleness.discoveredTestContentDigest,\n productInputDigests: staleness.productInputDigests,\n startedAt: runFile.startedAt,\n completedAt: formatTestRunTimestamp(recording.now()),\n status: deriveStatus(dispatch.outcomes),\n };\n\n const written = await writeTerminalTestRunState(runFile.runFilePath, state, { fs: recording.fs });\n if (!written.ok) {\n throw new Error(`failed to record test run: ${written.error}`);\n }\n return state;\n}\n\nasync function reserveRunFile(\n productDir: string,\n recording: RecordingDependencies,\n): Promise<TestRunFile> {\n const runFile = await createTestRunFile(productDir, { fs: recording.fs, now: recording.now });\n if (!runFile.ok) {\n throw new Error(`failed to create test run file: ${runFile.error}`);\n }\n return runFile.value;\n}\n\n/**\n * Runs the spec tree's tests — every discovered file, or only the configured\n * passing scope under `passing` — through the registry, then records last-run\n * evidence for the run. Reads the passing scope from the resolved testing config.\n */\nexport async function runTestsCommand(\n options: RunTestsCommandOptions,\n deps: TestCommandDependencies,\n): Promise<RecordedTestRun> {\n const { config, digest } = await resolveTestingConfig(options.productDir);\n const passingScope = options.passing ? config.passingScope : undefined;\n const recording = resolveRecordingDependencies(deps);\n const runFile = await reserveRunFile(options.productDir, recording);\n const dispatch = await runTests(\n { productDir: options.productDir, registry: deps.registry, passingScope },\n { runnerDepsFor: deps.runnerDepsFor },\n );\n const recorded = await recordRun(runFile, options.productDir, dispatch, recording, deps.registry, digest);\n return { dispatch, recorded };\n}\n\n/**\n * Runs a single node's tests through the registry and records fresh last-run\n * evidence covering that node, returning the recorded state for a status\n * consumer to read its outcome.\n */\nexport async function runNodeCommand(\n options: RunNodeCommandOptions,\n deps: TestCommandDependencies,\n): Promise<RecordedTestRun> {\n const recording = resolveRecordingDependencies(deps);\n const runFile = await reserveRunFile(options.productDir, recording);\n const dispatch = await runTests(\n { productDir: options.productDir, registry: deps.registry, passingScope: { include: [options.nodePath] } },\n { runnerDepsFor: deps.runnerDepsFor },\n );\n const recorded = await recordRun(runFile, options.productDir, dispatch, recording, deps.registry);\n return { dispatch, recorded };\n}\n","import { createHash } from \"node:crypto\";\nimport { join } from \"node:path\";\n\nimport type { Result } from \"@/config/types\";\nimport {\n compareAsciiStrings,\n createJsonlRunFile,\n defaultStateStoreFileSystem,\n formatRunTimestamp,\n hasErrorCode,\n isRunFileName,\n latestNonEmptyJsonlLine,\n parseStateStoreError,\n runFileName,\n runsDir as stateStoreRunsDir,\n STATE_STORE_ERROR,\n STATE_STORE_DOMAIN,\n type CreateRunFileOptions,\n type JsonRecord,\n type StateStoreFileEntry,\n type StateStoreFileSystem,\n type StateStoreJsonlReaderFileSystem,\n type StateStoreRunReaderFileSystem,\n worktreeScopeDir,\n writeJsonlRunRecord,\n} from \"@/lib/state-store\";\n\nexport const TEST_RUN_STATE_STATUS = {\n PASSED: \"passed\",\n FAILED: \"failed\",\n INTERRUPTED: \"interrupted\",\n} as const;\n\nexport type TestRunStateStatus = (typeof TEST_RUN_STATE_STATUS)[keyof typeof TEST_RUN_STATE_STATUS];\n\nexport const TESTING_RUN_STATE_INCOMPLETE_REASON = {\n MISSING_STATE: \"missing-state\",\n IO_ERROR: \"io-error\",\n PARSE_INVALID_STATE: \"parse-invalid-state\",\n SHAPE_INVALID_STATE: \"shape-invalid-state\",\n} as const;\n\nexport type TestingRunStateIncompleteReason =\n (typeof TESTING_RUN_STATE_INCOMPLETE_REASON)[keyof typeof TESTING_RUN_STATE_INCOMPLETE_REASON];\n\nexport const TESTING_RUN_STATE_ERROR = {\n RUN_FILE_COLLISION_LIMIT: \"testing run file collision limit exhausted\",\n RUN_FILE_CREATE_FAILED: \"testing run file create failed\",\n STATE_ALREADY_EXISTS: \"testing run state already exists\",\n STATE_WRITE_FAILED: \"testing run state write failed\",\n} as const;\n\nexport const TESTING_RUN_STATE_ERROR_CODE = {\n NOT_FOUND: \"ENOENT\",\n} as const;\n\nexport const TEST_RUN_STATE_FIELDS = {\n BRANCH_NAME: \"branchName\",\n HEAD_SHA: \"headSha\",\n TESTING_CONFIG_DIGEST: \"testingConfigDigest\",\n RUNNER_OUTCOMES: \"runnerOutcomes\",\n DISCOVERED_TEST_PATHS_DIGEST: \"discoveredTestPathsDigest\",\n DISCOVERED_TEST_CONTENT_DIGEST: \"discoveredTestContentDigest\",\n PRODUCT_INPUT_DIGESTS: \"productInputDigests\",\n STARTED_AT: \"startedAt\",\n COMPLETED_AT: \"completedAt\",\n STATUS: \"status\",\n} as const;\n\nconst TEST_RUNNER_OUTCOME_FIELDS = {\n RUNNER_ID: \"runnerId\",\n TEST_PATHS: \"testPaths\",\n EXIT_CODE: \"exitCode\",\n} as const;\n\nconst PRODUCT_INPUT_DIGEST_FIELDS = {\n DESCRIPTOR_ID: \"descriptorId\",\n DIGEST: \"digest\",\n} as const;\n\nexport interface TestRunnerOutcome {\n readonly runnerId: string;\n readonly testPaths: readonly string[];\n readonly exitCode: number;\n}\n\nexport interface ProductInputDigest {\n readonly descriptorId: string;\n readonly digest: string;\n}\n\nexport interface TestRunState {\n readonly branchName: string;\n readonly headSha: string;\n readonly testingConfigDigest: string;\n readonly runnerOutcomes: readonly TestRunnerOutcome[];\n readonly discoveredTestPathsDigest: string;\n readonly discoveredTestContentDigest: string;\n readonly productInputDigests: readonly ProductInputDigest[];\n readonly startedAt: string;\n readonly completedAt: string;\n readonly status: TestRunStateStatus;\n}\n\nexport interface StalenessInputs {\n readonly testingConfigDigest: string;\n readonly discoveredTestPathsDigest: string;\n readonly discoveredTestContentDigest: string;\n readonly productInputDigests: readonly ProductInputDigest[];\n}\n\nexport interface TestContentEntry {\n readonly path: string;\n readonly content: string;\n}\n\nexport interface TestRunFile {\n readonly runsDir: string;\n readonly runFilePath: string;\n readonly runFileName: string;\n readonly runToken: string;\n readonly runId: string;\n readonly startedAt: string;\n}\n\nexport interface TestTerminalRun {\n readonly runFileName: string;\n readonly runFilePath: string;\n readonly state: TestRunState;\n}\n\nexport interface TestIncompleteRun {\n readonly runFileName: string;\n readonly runFilePath: string;\n readonly reason: TestingRunStateIncompleteReason;\n readonly error?: string;\n}\n\nexport interface TestingRuns {\n readonly terminalRuns: readonly TestTerminalRun[];\n readonly incompleteRuns: readonly TestIncompleteRun[];\n}\n\nexport type TestRunFileEntry = StateStoreFileEntry;\nexport type TestRunStateFileSystem = StateStoreFileSystem;\nexport type CreateTestRunFileOptions = CreateRunFileOptions;\n\nexport interface WriteTestRunStateOptions {\n readonly fs?: StateStoreFileSystem;\n}\n\nexport interface ReadTestRunStateOptions {\n readonly fs?: StateStoreRunReaderFileSystem;\n}\n\nconst SHA256_ALGORITHM = \"sha256\";\nconst HEX_ENCODING = \"hex\";\nconst SEGMENT_SEPARATOR = \"-\";\n\nconst defaultFileSystem: StateStoreFileSystem = defaultStateStoreFileSystem;\n\nexport { defaultFileSystem as defaultTestRunStateFileSystem };\n\nexport function formatTestRunTimestamp(date: Date): string {\n return formatRunTimestamp(date);\n}\n\nexport function testingRunsDir(productDir: string): string {\n const worktreeScope = worktreeScopeDir(productDir);\n if (!worktreeScope.ok) throw new Error(worktreeScope.error);\n const result = stateStoreRunsDir(worktreeScope.value, STATE_STORE_DOMAIN.TEST);\n if (!result.ok) throw new Error(result.error);\n return result.value;\n}\n\nexport async function createTestRunFile(\n productDir: string,\n options: CreateTestRunFileOptions = {},\n): Promise<Result<TestRunFile>> {\n const worktreeScope = worktreeScopeDir(productDir);\n if (!worktreeScope.ok) return worktreeScope;\n const created = await createJsonlRunFile(worktreeScope.value, STATE_STORE_DOMAIN.TEST, options);\n if (!created.ok) return {\n ok: false,\n error: testingRunFileError(created.error),\n };\n return { ok: true, value: created.value };\n}\n\nexport async function writeTerminalTestRunState(\n runFilePath: string,\n state: TestRunState,\n options: WriteTestRunStateOptions = {},\n): Promise<Result<string>> {\n const written = await writeJsonlRunRecord(runFilePath, testRunStateRecord(state), options);\n if (written.ok) return written;\n if (written.error === STATE_STORE_ERROR.RECORD_ALREADY_EXISTS) {\n return { ok: false, error: TESTING_RUN_STATE_ERROR.STATE_ALREADY_EXISTS };\n }\n return {\n ok: false,\n error: testingWriteError(written.error),\n };\n}\n\nexport async function readTestingRuns(\n productDir: string,\n options: ReadTestRunStateOptions = {},\n): Promise<Result<TestingRuns>> {\n const fs = options.fs ?? defaultFileSystem;\n const runsDir = testingRunsDir(productDir);\n\n let entries: readonly TestRunFileEntry[];\n try {\n entries = await fs.readdir(runsDir, { withFileTypes: true });\n } catch (error) {\n if (hasErrorCode(error, TESTING_RUN_STATE_ERROR_CODE.NOT_FOUND)) {\n return { ok: true, value: { terminalRuns: [], incompleteRuns: [] } };\n }\n return { ok: false, error: toErrorMessage(error) };\n }\n\n const terminalRuns: TestTerminalRun[] = [];\n const incompleteRuns: TestIncompleteRun[] = [];\n for (const entry of entries.filter(isTestRunFileEntry)) {\n const runFilePath = join(runsDir, entry.name);\n const stateResult = await readTestRunStatePath(runFilePath, fs);\n if (stateResult.ok) {\n terminalRuns.push({ runFileName: entry.name, runFilePath, state: stateResult.value });\n } else {\n incompleteRuns.push({\n runFileName: entry.name,\n runFilePath,\n reason: stateResult.reason,\n ...(stateResult.error === undefined ? {} : { error: stateResult.error }),\n });\n }\n }\n\n return { ok: true, value: { terminalRuns, incompleteRuns } };\n}\n\nexport function selectLatestTerminalTestRunForNode(\n runs: readonly TestTerminalRun[],\n nodeTestPaths: readonly string[],\n): TestTerminalRun | undefined {\n return runs\n .filter((run) => runCoversNode(run, nodeTestPaths))\n .reduce<TestTerminalRun | undefined>((latest, candidate) => {\n if (latest === undefined) return candidate;\n return compareTerminalRuns(latest, candidate) < 0 ? candidate : latest;\n }, undefined);\n}\n\nfunction runCoversNode(run: TestTerminalRun, nodeTestPaths: readonly string[]): boolean {\n return outcomesCoverPaths(run.state.runnerOutcomes, nodeTestPaths);\n}\n\nexport function outcomesCoverPaths(\n outcomes: readonly TestRunnerOutcome[],\n nodeTestPaths: readonly string[],\n): boolean {\n if (nodeTestPaths.length === 0) return false;\n const executed = new Set(outcomes.flatMap((outcome) => outcome.testPaths));\n return nodeTestPaths.every((path) => executed.has(path));\n}\n\nexport function digestTestPaths(paths: readonly string[]): string {\n const normalized = [...new Set(paths)].sort(compareAsciiStrings);\n return sha256Hex(JSON.stringify(normalized));\n}\n\nexport function digestTestContents(entries: readonly TestContentEntry[]): string {\n const normalized = [...entries]\n .sort((left, right) => compareAsciiStrings(left.path, right.path))\n .map((entry) => [entry.path, entry.content]);\n return sha256Hex(JSON.stringify(normalized));\n}\n\nexport function isStalenessMatch(recorded: StalenessInputs, current: StalenessInputs): boolean {\n return recorded.testingConfigDigest === current.testingConfigDigest\n && recorded.discoveredTestPathsDigest === current.discoveredTestPathsDigest\n && recorded.discoveredTestContentDigest === current.discoveredTestContentDigest\n && productInputDigestsEqual(recorded.productInputDigests, current.productInputDigests);\n}\n\nexport function extractStalenessInputs(state: TestRunState): StalenessInputs {\n return {\n testingConfigDigest: state.testingConfigDigest,\n discoveredTestPathsDigest: state.discoveredTestPathsDigest,\n discoveredTestContentDigest: state.discoveredTestContentDigest,\n productInputDigests: state.productInputDigests,\n };\n}\n\nexport function testRunFileName(runToken: string): string {\n return runFileName(runToken);\n}\n\nfunction testRunStateRecord(state: TestRunState): JsonRecord {\n return {\n branchName: state.branchName,\n headSha: state.headSha,\n testingConfigDigest: state.testingConfigDigest,\n runnerOutcomes: state.runnerOutcomes.map((outcome) => ({\n runnerId: outcome.runnerId,\n testPaths: outcome.testPaths,\n exitCode: outcome.exitCode,\n })),\n discoveredTestPathsDigest: state.discoveredTestPathsDigest,\n discoveredTestContentDigest: state.discoveredTestContentDigest,\n productInputDigests: state.productInputDigests.map((digest) => ({\n descriptorId: digest.descriptorId,\n digest: digest.digest,\n })),\n startedAt: state.startedAt,\n completedAt: state.completedAt,\n status: state.status,\n };\n}\n\ntype ReadStateResult =\n | { readonly ok: true; readonly value: TestRunState }\n | { readonly ok: false; readonly reason: TestingRunStateIncompleteReason; readonly error?: string };\n\nasync function readTestRunStatePath(\n runFilePath: string,\n fs: StateStoreJsonlReaderFileSystem,\n): Promise<ReadStateResult> {\n let content: string;\n try {\n content = await fs.readFile(runFilePath, \"utf8\");\n } catch (error) {\n return {\n ok: false,\n reason: hasErrorCode(error, TESTING_RUN_STATE_ERROR_CODE.NOT_FOUND)\n ? TESTING_RUN_STATE_INCOMPLETE_REASON.MISSING_STATE\n : TESTING_RUN_STATE_INCOMPLETE_REASON.IO_ERROR,\n error: toErrorMessage(error),\n };\n }\n\n const latest = latestNonEmptyJsonlLine(content);\n if (latest === undefined) {\n return { ok: false, reason: TESTING_RUN_STATE_INCOMPLETE_REASON.PARSE_INVALID_STATE };\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(latest) as unknown;\n } catch {\n return { ok: false, reason: TESTING_RUN_STATE_INCOMPLETE_REASON.PARSE_INVALID_STATE };\n }\n\n const validated = validateTestRunState(parsed);\n if (!validated.ok) {\n return { ok: false, reason: TESTING_RUN_STATE_INCOMPLETE_REASON.SHAPE_INVALID_STATE, error: validated.error };\n }\n return { ok: true, value: validated.value };\n}\n\nfunction validateTestRunState(value: unknown): Result<TestRunState> {\n if (!isRecord(value)) return { ok: false, error: \"testing run state must be an object\" };\n\n const branchName = readString(value, TEST_RUN_STATE_FIELDS.BRANCH_NAME);\n if (!branchName.ok) return branchName;\n const headSha = readString(value, TEST_RUN_STATE_FIELDS.HEAD_SHA);\n if (!headSha.ok) return headSha;\n const testingConfigDigest = readString(value, TEST_RUN_STATE_FIELDS.TESTING_CONFIG_DIGEST);\n if (!testingConfigDigest.ok) return testingConfigDigest;\n const runnerOutcomes = readRunnerOutcomes(value[TEST_RUN_STATE_FIELDS.RUNNER_OUTCOMES]);\n if (!runnerOutcomes.ok) return runnerOutcomes;\n const discoveredTestPathsDigest = readString(value, TEST_RUN_STATE_FIELDS.DISCOVERED_TEST_PATHS_DIGEST);\n if (!discoveredTestPathsDigest.ok) return discoveredTestPathsDigest;\n const discoveredTestContentDigest = readString(value, TEST_RUN_STATE_FIELDS.DISCOVERED_TEST_CONTENT_DIGEST);\n if (!discoveredTestContentDigest.ok) return discoveredTestContentDigest;\n const productInputDigests = readProductInputDigests(value[TEST_RUN_STATE_FIELDS.PRODUCT_INPUT_DIGESTS]);\n if (!productInputDigests.ok) return productInputDigests;\n const startedAt = readString(value, TEST_RUN_STATE_FIELDS.STARTED_AT);\n if (!startedAt.ok) return startedAt;\n const completedAt = readString(value, TEST_RUN_STATE_FIELDS.COMPLETED_AT);\n if (!completedAt.ok) return completedAt;\n const status = readStatus(value[TEST_RUN_STATE_FIELDS.STATUS]);\n if (!status.ok) return status;\n\n return {\n ok: true,\n value: {\n branchName: branchName.value,\n headSha: headSha.value,\n testingConfigDigest: testingConfigDigest.value,\n runnerOutcomes: runnerOutcomes.value,\n discoveredTestPathsDigest: discoveredTestPathsDigest.value,\n discoveredTestContentDigest: discoveredTestContentDigest.value,\n productInputDigests: productInputDigests.value,\n startedAt: startedAt.value,\n completedAt: completedAt.value,\n status: status.value,\n },\n };\n}\n\nfunction readRunnerOutcomes(raw: unknown): Result<readonly TestRunnerOutcome[]> {\n if (!Array.isArray(raw)) {\n return { ok: false, error: `${TEST_RUN_STATE_FIELDS.RUNNER_OUTCOMES} must be an array` };\n }\n const outcomes: TestRunnerOutcome[] = [];\n for (const entry of raw) {\n if (!isRecord(entry)) {\n return { ok: false, error: `${TEST_RUN_STATE_FIELDS.RUNNER_OUTCOMES} entries must be objects` };\n }\n const runnerId = readString(entry, TEST_RUNNER_OUTCOME_FIELDS.RUNNER_ID);\n if (!runnerId.ok) return runnerId;\n const testPaths = readStringArray(entry, TEST_RUNNER_OUTCOME_FIELDS.TEST_PATHS);\n if (!testPaths.ok) return testPaths;\n const exitCodeRaw = entry[TEST_RUNNER_OUTCOME_FIELDS.EXIT_CODE];\n if (typeof exitCodeRaw !== \"number\" || !Number.isInteger(exitCodeRaw)) {\n return { ok: false, error: `${TEST_RUNNER_OUTCOME_FIELDS.EXIT_CODE} must be an integer` };\n }\n outcomes.push({ runnerId: runnerId.value, testPaths: testPaths.value, exitCode: exitCodeRaw });\n }\n return { ok: true, value: outcomes };\n}\n\nfunction readProductInputDigests(raw: unknown): Result<readonly ProductInputDigest[]> {\n if (!Array.isArray(raw)) {\n return { ok: false, error: `${TEST_RUN_STATE_FIELDS.PRODUCT_INPUT_DIGESTS} must be an array` };\n }\n const digests: ProductInputDigest[] = [];\n for (const entry of raw) {\n if (!isRecord(entry)) {\n return { ok: false, error: `${TEST_RUN_STATE_FIELDS.PRODUCT_INPUT_DIGESTS} entries must be objects` };\n }\n const descriptorId = readString(entry, PRODUCT_INPUT_DIGEST_FIELDS.DESCRIPTOR_ID);\n if (!descriptorId.ok) return descriptorId;\n const digest = readString(entry, PRODUCT_INPUT_DIGEST_FIELDS.DIGEST);\n if (!digest.ok) return digest;\n digests.push({ descriptorId: descriptorId.value, digest: digest.value });\n }\n return { ok: true, value: digests };\n}\n\nfunction readString(value: Record<string, unknown>, field: string): Result<string> {\n const raw = value[field];\n return typeof raw === \"string\" && raw.length > 0\n ? { ok: true, value: raw }\n : { ok: false, error: `${field} must be a non-empty string` };\n}\n\nfunction readStringArray(value: Record<string, unknown>, field: string): Result<readonly string[]> {\n const raw = value[field];\n return Array.isArray(raw) && raw.every((entry) => typeof entry === \"string\" && entry.length > 0)\n ? { ok: true, value: raw }\n : { ok: false, error: `${field} must be an array of non-empty strings` };\n}\n\nfunction readStatus(raw: unknown): Result<TestRunStateStatus> {\n return isTestRunStateStatus(raw)\n ? { ok: true, value: raw }\n : { ok: false, error: `${TEST_RUN_STATE_FIELDS.STATUS} must be a terminal testing status` };\n}\n\nfunction isTestRunStateStatus(value: unknown): value is TestRunStateStatus {\n return typeof value === \"string\" && Object.values(TEST_RUN_STATE_STATUS).includes(value as TestRunStateStatus);\n}\n\nfunction compareTerminalRuns(left: TestTerminalRun, right: TestTerminalRun): number {\n const completed = compareAsciiStrings(left.state.completedAt, right.state.completedAt);\n if (completed !== 0) return completed;\n const started = compareAsciiStrings(left.state.startedAt, right.state.startedAt);\n if (started !== 0) return started;\n return compareAsciiStrings(left.runFileName, right.runFileName);\n}\n\nfunction productInputDigestsEqual(\n left: readonly ProductInputDigest[],\n right: readonly ProductInputDigest[],\n): boolean {\n return canonicalProductInputDigests(left) === canonicalProductInputDigests(right);\n}\n\nfunction canonicalProductInputDigests(digests: readonly ProductInputDigest[]): string {\n const normalized = [...digests]\n .map((digest) => [digest.descriptorId, digest.digest])\n .sort((left, right) => compareAsciiStrings(left.join(SEGMENT_SEPARATOR), right.join(SEGMENT_SEPARATOR)));\n return JSON.stringify(normalized);\n}\n\nfunction isTestRunFileEntry(entry: TestRunFileEntry): boolean {\n return entry.isFile() && isRunFileName(entry.name);\n}\n\nfunction testingRunFileError(error: string): string {\n const stateStoreError = parseStateStoreError(error);\n if (stateStoreError?.code === STATE_STORE_ERROR.RUN_FILE_COLLISION_LIMIT) {\n return TESTING_RUN_STATE_ERROR.RUN_FILE_COLLISION_LIMIT;\n }\n if (stateStoreError?.code === STATE_STORE_ERROR.RUN_FILE_CREATE_FAILED) {\n return withDomainErrorDetail(TESTING_RUN_STATE_ERROR.RUN_FILE_CREATE_FAILED, stateStoreError.detail);\n }\n return withDomainErrorDetail(TESTING_RUN_STATE_ERROR.RUN_FILE_CREATE_FAILED, error);\n}\n\nfunction testingWriteError(error: string): string {\n const stateStoreError = parseStateStoreError(error);\n if (stateStoreError?.code === STATE_STORE_ERROR.RECORD_WRITE_FAILED) {\n return withDomainErrorDetail(TESTING_RUN_STATE_ERROR.STATE_WRITE_FAILED, stateStoreError.detail);\n }\n return withDomainErrorDetail(TESTING_RUN_STATE_ERROR.STATE_WRITE_FAILED, error);\n}\n\nfunction withDomainErrorDetail(domainError: string, detail: string | undefined): string {\n return detail === undefined ? domainError : `${domainError}: ${detail}`;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction sha256Hex(value: string): string {\n return createHash(SHA256_ALGORITHM).update(value).digest(HEX_ENCODING);\n}\n\nfunction toErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n","import { currentStalenessInputs, discoverTestFiles, runNodeCommand } from \"@/commands/testing\";\nimport type { GitDependencies } from \"@/git/root\";\nimport type { NodeOutcomeResolver } from \"@/lib/node-status\";\nimport { SPEC_TREE_CONFIG } from \"@/lib/spec-tree/config\";\nimport type { TestingLanguageDescriptor, TestRunnerDependencies } from \"@/testing/languages/types\";\nimport type { TestingRegistry } from \"@/testing/registry\";\nimport {\n extractStalenessInputs,\n isStalenessMatch,\n outcomesCoverPaths,\n readTestingRuns,\n selectLatestTerminalTestRunForNode,\n type StalenessInputs,\n TEST_RUN_STATE_STATUS,\n type TestRunStateFileSystem,\n type TestTerminalRun,\n} from \"@/testing/run-state\";\n\nconst PATH_SEPARATOR = \"/\";\n\n/** Dependencies the production resolver composes over the testing domain. */\nexport interface NodeOutcomeResolverDependencies {\n readonly productDir: string;\n readonly registry: TestingRegistry;\n readonly runnerDepsFor: (language: TestingLanguageDescriptor) => TestRunnerDependencies;\n readonly git?: GitDependencies;\n readonly fs?: TestRunStateFileSystem;\n readonly now?: () => Date;\n}\n\n// The product-wide inputs the per-node freshness check reads, gathered once per\n// resolver rather than per node: the discovered test files and the recorded\n// terminal runs.\ninterface ResolverEvidence {\n readonly discoveredTestPaths: readonly string[];\n readonly terminalRuns: readonly TestTerminalRun[];\n}\n\ntype CurrentStalenessInputsFor = (coveredPaths: readonly string[]) => Promise<StalenessInputs>;\n\n/**\n * Builds the node-outcome resolver `spx spec status --update` injects into the\n * node-status orchestration: for a node it reports the latest usable recorded\n * testing evidence (fresh and passed) and runs the testing domain's registry-based\n * per-node run only when that evidence is stale, failing, or absent. Composed at\n * the command layer over the testing domain so the pure node-status library and\n * the testing library stay independent. The discovered test files and recorded\n * runs are read once and memoized across nodes, so resolving N nodes performs one\n * tree walk and one run-file read rather than N of each.\n */\nexport function createNodeOutcomeResolver(deps: NodeOutcomeResolverDependencies): NodeOutcomeResolver {\n let evidence: Promise<ResolverEvidence> | undefined;\n const currentInputsByCoveredPaths = new Map<string, Promise<StalenessInputs>>();\n const sharedEvidence = (): Promise<ResolverEvidence> => (evidence ??= loadResolverEvidence(deps));\n const refreshEvidence = (): void => {\n evidence = loadResolverEvidence(deps);\n };\n const currentInputsFor: CurrentStalenessInputsFor = (coveredPaths) => {\n const cacheKey = coveredPathCollectionKey(coveredPaths);\n const cached = currentInputsByCoveredPaths.get(cacheKey);\n if (cached !== undefined) {\n return cached;\n }\n const current = currentStalenessInputs(deps.productDir, coveredPaths, deps);\n currentInputsByCoveredPaths.set(cacheKey, current);\n return current;\n };\n\n return async (nodeId: string): Promise<boolean> => {\n const { discoveredTestPaths, terminalRuns } = await sharedEvidence();\n const nodePath = `${SPEC_TREE_CONFIG.ROOT_DIRECTORY}${PATH_SEPARATOR}${nodeId}`;\n const nodeTestPaths = filterNodeTestPaths(discoveredTestPaths, nodePath);\n const usable = await usableRecordedOutcome(discoveredTestPaths, terminalRuns, nodeTestPaths, currentInputsFor);\n if (usable !== undefined) {\n return usable;\n }\n const { dispatch, recorded } = await runNodeCommand({ productDir: deps.productDir, nodePath }, deps);\n refreshEvidence();\n // Report the node passing only when the run executed every one of its test paths\n // and passed; a gated-out or unmatched language leaves some path unexecuted, and\n // a zero-outcome run covers nothing, so neither vacuously passes.\n return outcomesCoverPaths(dispatch.outcomes, nodeTestPaths) && recorded.status === TEST_RUN_STATE_STATUS.PASSED;\n };\n}\n\nfunction coveredPathCollectionKey(coveredPaths: readonly string[]): string {\n return JSON.stringify([...coveredPaths].sort());\n}\n\n// Reads the discovered test files and recorded terminal runs once for the whole\n// --update pass. A failed run-state read yields no terminal runs, so every node\n// reads as absent and re-runs — the conservative-correct fallback.\nasync function loadResolverEvidence(deps: NodeOutcomeResolverDependencies): Promise<ResolverEvidence> {\n const discoveredTestPaths = await discoverTestFiles(deps.productDir);\n const runs = await readTestingRuns(deps.productDir, deps);\n return { discoveredTestPaths, terminalRuns: runs.ok ? runs.value.terminalRuns : [] };\n}\n\n// A node's test paths are the discovered test files under its subtree — the same\n// set the per-node run records against, so coverage-gated evidence selection and\n// the per-node run agree on path identity.\nfunction filterNodeTestPaths(discoveredTestPaths: readonly string[], nodePath: string): readonly string[] {\n const prefix = `${nodePath}${PATH_SEPARATOR}`;\n return discoveredTestPaths.filter((path) => path.startsWith(prefix));\n}\n\n// Resolves a recorded outcome (true) only when the latest covering run is fresh —\n// every staleness digest matches the node's current inputs by the same recipe the\n// run recorded with — and passed. Returns undefined for stale, failing, or absent\n// evidence, signalling that a fresh per-node run is required.\nasync function usableRecordedOutcome(\n discoveredTestPaths: readonly string[],\n terminalRuns: readonly TestTerminalRun[],\n nodeTestPaths: readonly string[],\n currentInputsFor: CurrentStalenessInputsFor,\n): Promise<boolean | undefined> {\n const latest = selectLatestTerminalTestRunForNode(terminalRuns, nodeTestPaths);\n if (latest === undefined) {\n return undefined;\n }\n // Compare freshness over the run's own covered paths — the set its recorded\n // digests were derived from — so a covering run reads as fresh when its executed\n // files are unchanged. Comparing over only the node's paths would judge a fresh\n // full-product run stale for any node smaller than the whole product.\n const runCoveredPaths = latest.state.runnerOutcomes.flatMap((outcome) => outcome.testPaths);\n // A covered test file deleted or renamed since the run makes the recorded\n // evidence stale; re-run rather than reading a path that no longer exists.\n const presentTestPaths = new Set(discoveredTestPaths);\n if (!runCoveredPaths.every((path) => presentTestPaths.has(path))) {\n return undefined;\n }\n const current = await currentInputsFor(runCoveredPaths);\n const fresh = isStalenessMatch(extractStalenessInputs(latest.state), current);\n return fresh && latest.state.status === TEST_RUN_STATE_STATUS.PASSED ? true : undefined;\n}\n","import { SPEC_TREE_NODE_STATE, type SpecTreeNodeState } from \"@/lib/spec-tree/config\";\n\n/**\n * The three observable facts that determine a spec-tree node's lifecycle state.\n *\n * - `hasTests` — the node directory contains co-located evidence files.\n * - `isExcluded` — the node path is listed in `spx/EXCLUDE`.\n * - `testsPass` — the node's tests all pass when executed.\n */\nexport interface NodeClassificationFacts {\n readonly hasTests: boolean;\n readonly isExcluded: boolean;\n readonly testsPass: boolean;\n}\n\n/** JSON key under which the lifecycle state is recorded in `spx.status.json`. */\nexport const NODE_STATUS_STATUS_KEY = \"status\";\n\nconst NODE_STATUS_JSON_INDENT = 2;\n\n/**\n * Resolve a node's lifecycle state from its classification facts.\n *\n * Precedence (declared in `node-status.md`): a node with no co-located tests is\n * `declared`; otherwise a node listed in `spx/EXCLUDE` is `specified`; otherwise\n * a node whose tests pass is `passing`; otherwise the node is `failing`.\n */\nexport function classifyNodeStatus(facts: NodeClassificationFacts): SpecTreeNodeState {\n if (!facts.hasTests) return SPEC_TREE_NODE_STATE.DECLARED;\n if (facts.isExcluded) return SPEC_TREE_NODE_STATE.SPECIFIED;\n if (facts.testsPass) return SPEC_TREE_NODE_STATE.PASSING;\n return SPEC_TREE_NODE_STATE.FAILING;\n}\n\n/** Serialize a lifecycle state to the canonical `spx.status.json` document. */\nexport function serializeNodeStatus(state: SpecTreeNodeState): string {\n return `${JSON.stringify({ [NODE_STATUS_STATUS_KEY]: state }, null, NODE_STATUS_JSON_INDENT)}\\n`;\n}\n","import { join } from \"node:path\";\n\nimport type { SpecTreeEvidenceProvider, SpecTreeNodeSourceEntry } from \"@/lib/spec-tree\";\nimport { SPEC_TREE_CONFIG, type SpecTreeNodeState } from \"@/lib/spec-tree/config\";\nimport { readNodeStatus } from \"./read\";\n\n/**\n * Resolve the absolute directory of a spec-tree node under `productDir`.\n *\n * A node source entry's `id` is its directory path relative to the spec-tree\n * root, so the node directory is `productDir/<root>/<id>`.\n */\nfunction nodeDirectory(productDir: string, node: SpecTreeNodeSourceEntry): string {\n return join(productDir, SPEC_TREE_CONFIG.ROOT_DIRECTORY, node.id);\n}\n\n/**\n * Build a spec-tree evidence provider that overrides each node's live-derived\n * state with the state persisted in its co-located `spx.status.json`.\n *\n * The provider closes over `productDir` because `stateForNode` receives only the\n * node source entry and in-memory evidence — no filesystem path. A node with no\n * persisted file yields `undefined`, which routes the spec-tree library back to\n * live derivation.\n *\n * @param productDir - Absolute path to the product directory.\n */\nexport function createNodeStatusProvider(productDir: string): SpecTreeEvidenceProvider {\n return {\n stateForNode(node: SpecTreeNodeSourceEntry): SpecTreeNodeState | undefined {\n return readNodeStatus(nodeDirectory(productDir, node));\n },\n };\n}\n","import { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nimport { SPEC_TREE_NODE_STATE, type SpecTreeNodeState } from \"@/lib/spec-tree/config\";\nimport { NODE_STATUS_STATUS_KEY } from \"./classify\";\n\n/** Filename of the co-located per-node lifecycle-state record. */\nexport const NODE_STATUS_FILENAME = \"spx.status.json\";\n\nconst NODE_STATUS_VALUES: ReadonlySet<string> = new Set(Object.values(SPEC_TREE_NODE_STATE));\n\nfunction isNodeError(error: unknown): error is NodeJS.ErrnoException {\n return error instanceof Error && \"code\" in error;\n}\n\nfunction isSpecTreeNodeState(value: unknown): value is SpecTreeNodeState {\n return typeof value === \"string\" && NODE_STATUS_VALUES.has(value);\n}\n\n/**\n * Read a node's recorded lifecycle state from its co-located `spx.status.json`.\n *\n * Returns `undefined` when the file is absent — absence means \"no recorded\n * state\", which routes consumers to live derivation. A present file whose\n * content is not a valid status record is a corruption error, not absence.\n *\n * @param nodeDir - Absolute path to the node directory.\n */\nexport function readNodeStatus(nodeDir: string): SpecTreeNodeState | undefined {\n const filePath = join(nodeDir, NODE_STATUS_FILENAME);\n\n let content: string;\n try {\n content = readFileSync(filePath, \"utf8\");\n } catch (error) {\n if (isNodeError(error) && error.code === \"ENOENT\") {\n return undefined;\n }\n throw error;\n }\n\n const parsed = JSON.parse(content) as Record<string, unknown>;\n const status = parsed[NODE_STATUS_STATUS_KEY];\n if (!isSpecTreeNodeState(status)) {\n throw new Error(\n `Invalid ${NODE_STATUS_FILENAME} at ${filePath}: status \"${String(status)}\" is not a lifecycle state`,\n );\n }\n return status;\n}\n","import { mkdir, writeFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\n\nimport { createIgnoreSourceReader, IGNORE_SOURCE_FILENAME_DEFAULT } from \"@/lib/file-inclusion/ignore-source\";\nimport {\n createFilesystemSpecTreeSource,\n readSpecTree,\n SPEC_TREE_ENTRY_TYPE,\n type SpecTreeNode,\n type SpecTreeSnapshot,\n} from \"@/lib/spec-tree\";\nimport { SPEC_TREE_CONFIG } from \"@/lib/spec-tree/config\";\nimport { classifyNodeStatus, type NodeClassificationFacts, serializeNodeStatus } from \"./classify\";\nimport { NODE_STATUS_FILENAME } from \"./read\";\n\n/**\n * Resolves a node's pass/fail outcome — from recorded testing evidence when it is\n * usable, otherwise by running the node's tests. Injected at the command edge so\n * the classifier's precedence logic is verifiable without executing a real suite.\n */\nexport type NodeOutcomeResolver = (nodeId: string) => Promise<boolean>;\n\nexport interface UpdateNodeStatusOptions {\n readonly productDir: string;\n readonly resolveOutcome: NodeOutcomeResolver;\n}\n\nconst NODE_STATUS_TEXT_ENCODING = \"utf8\";\n\n/**\n * Classify every spec-tree node under `productDir` and write its lifecycle state\n * to a co-located `spx.status.json`. This is the only path that writes the file.\n */\nexport async function updateNodeStatus(options: UpdateNodeStatusOptions): Promise<void> {\n const { productDir, resolveOutcome } = options;\n const snapshot = await readSpecTree({ source: createFilesystemSpecTreeSource({ productDir }) });\n const ignoreReader = createIgnoreSourceReader(productDir, {\n ignoreSourceFilename: IGNORE_SOURCE_FILENAME_DEFAULT,\n specTreeRootSegment: SPEC_TREE_CONFIG.ROOT_DIRECTORY,\n });\n const nodesWithTests = collectNodesWithTests(snapshot);\n\n for (const node of snapshot.allNodes) {\n const facts = await classifyFacts(node, {\n hasTests: nodesWithTests.has(node.id),\n isExcluded: isNodeExcluded(ignoreReader, node),\n resolveOutcome,\n });\n await writeNodeStatus(productDir, node.id, classifyNodeStatus(facts));\n }\n}\n\ntype ClassifyFactsInput = {\n readonly hasTests: boolean;\n readonly isExcluded: boolean;\n readonly resolveOutcome: NodeOutcomeResolver;\n};\n\nasync function classifyFacts(node: SpecTreeNode, input: ClassifyFactsInput): Promise<NodeClassificationFacts> {\n // The resolver is consulted only when its outcome can change the classification\n // — a node with no tests is declared, and an excluded node is specified, before\n // any outcome is resolved.\n const testsPass = input.hasTests && !input.isExcluded ? await input.resolveOutcome(node.id) : false;\n return { hasTests: input.hasTests, isExcluded: input.isExcluded, testsPass };\n}\n\nfunction collectNodesWithTests(snapshot: SpecTreeSnapshot): ReadonlySet<string> {\n const parents = new Set<string>();\n for (const entry of snapshot.entries) {\n if (entry.type === SPEC_TREE_ENTRY_TYPE.EVIDENCE) {\n parents.add(entry.parentId);\n }\n }\n return parents;\n}\n\nfunction isNodeExcluded(ignoreReader: ReturnType<typeof createIgnoreSourceReader>, node: SpecTreeNode): boolean {\n const reference = node.ref?.path;\n if (reference === undefined) return false;\n return ignoreReader.isUnderIgnoreSource(reference);\n}\n\nasync function writeNodeStatus(\n productDir: string,\n nodeId: string,\n state: ReturnType<typeof classifyNodeStatus>,\n): Promise<void> {\n const filePath = join(productDir, SPEC_TREE_CONFIG.ROOT_DIRECTORY, nodeId, NODE_STATUS_FILENAME);\n await mkdir(dirname(filePath), { recursive: true });\n await writeFile(filePath, serializeNodeStatus(state), NODE_STATUS_TEXT_ENCODING);\n}\n","import type { GitDependencies } from \"@/git/root\";\nimport { createNodeStatusProvider, type NodeOutcomeResolver, updateNodeStatus } from \"@/lib/node-status\";\nimport {\n createFilesystemSpecTreeSource,\n projectSpecTree,\n readSpecTree,\n type SpecTreeProjectedNode,\n type SpecTreeProjection,\n type SpecTreeSource,\n} from \"@/lib/spec-tree\";\nimport { KIND_REGISTRY, SPEC_TREE_CONFIG } from \"@/lib/spec-tree/config\";\nimport { resolveSpecProductDir, type SpecProductDirWarningHandler } from \"./root\";\n\nexport const OUTPUT_FORMAT = {\n TEXT: \"text\",\n JSON: \"json\",\n MARKDOWN: \"markdown\",\n TABLE: \"table\",\n} as const;\n\nexport const SPEC_STATUS_MESSAGE = {\n EMPTY: `No spec-tree nodes found in ${SPEC_TREE_CONFIG.ROOT_DIRECTORY}`,\n} as const;\n\nconst DEFAULT_FORMAT: OutputFormat = OUTPUT_FORMAT.TEXT;\nconst JSON_INDENTATION = 2;\nconst STATUS_SEPARATOR = \" \";\nconst NODE_INDENT = \" \";\nconst MARKDOWN_NODE_PREFIX = \"- \";\nconst TABLE_SEPARATOR = \"|\";\nconst TABLE_HEADER_SEPARATOR = \"---\";\nconst TABLE_HEADER = {\n KIND: \"Kind\",\n PATH: \"Path\",\n STATE: \"State\",\n} as const;\nexport const SPEC_STATUS_TABLE_HEADER = formatTableRow([\n TABLE_HEADER.KIND,\n TABLE_HEADER.PATH,\n TABLE_HEADER.STATE,\n]);\n\nexport type OutputFormat = (typeof OUTPUT_FORMAT)[keyof typeof OUTPUT_FORMAT];\n\ninterface StatusBaseOptions {\n cwd?: string;\n format?: OutputFormat;\n gitDependencies?: GitDependencies;\n onWarning?: SpecProductDirWarningHandler;\n source?: SpecTreeSource;\n}\n\n// The read path takes no resolver; the --update path requires one. Modeling the\n// co-dependency as a discriminated union makes `update: true` without a resolver a\n// compile-time error rather than a runtime throw.\ninterface StatusReadOptions extends StatusBaseOptions {\n update?: false;\n resolveOutcomeFor?: undefined;\n}\n\ninterface StatusUpdateOptions extends StatusBaseOptions {\n /** Refresh each node's spx.status.json before reporting the rollup. */\n update: true;\n /** Builds the per-node outcome resolver --update injects. */\n resolveOutcomeFor: (productDir: string) => NodeOutcomeResolver;\n}\n\nexport type StatusOptions = StatusReadOptions | StatusUpdateOptions;\n\nexport async function statusCommand(\n options: StatusOptions = {},\n): Promise<string> {\n if (options.source !== undefined) {\n // Injected sources are in-memory and carry no productDir, so the node-status\n // read-back provider — which resolves each spx.status.json under productDir —\n // cannot apply here; this path bypasses filesystem and git resolution and\n // derives state live.\n return renderSpecStatus(projectSpecTree(await readSpecTree({ source: options.source })), options.format);\n }\n\n const productDir = await resolveSpecProductDir(\n options.cwd ?? process.cwd(),\n options.gitDependencies,\n options.onWarning,\n );\n if (options.update === true) {\n // --update refreshes each node's spx.status.json before the read-back below, so\n // the reported rollup reflects the just-written state. The resolver is injected\n // at the command edge; this handler composes no language runner.\n await updateNodeStatus({ productDir, resolveOutcome: options.resolveOutcomeFor(productDir) });\n }\n // Read-back: a node's committed spx.status.json overrides live derivation; a node\n // with no status file yields undefined, routing the spec-tree library back to live\n // derivation.\n const snapshot = await readSpecTree({\n source: createFilesystemSpecTreeSource({ productDir }),\n evidence: createNodeStatusProvider(productDir),\n });\n return renderSpecStatus(projectSpecTree(snapshot), options.format);\n}\n\nexport function renderSpecStatus(\n projection: SpecTreeProjection,\n format: OutputFormat = DEFAULT_FORMAT,\n): string {\n if (projection.nodes.length === 0 && format !== OUTPUT_FORMAT.JSON) {\n return SPEC_STATUS_MESSAGE.EMPTY;\n }\n\n switch (format) {\n case OUTPUT_FORMAT.JSON:\n return formatJSON(projection);\n case OUTPUT_FORMAT.MARKDOWN:\n return formatMarkdown(projection);\n case OUTPUT_FORMAT.TABLE:\n return formatTable(projection);\n case OUTPUT_FORMAT.TEXT:\n return formatText(projection);\n default: {\n const unsupportedFormat: never = format;\n throw new RangeError(`Unsupported spec status output format: ${unsupportedFormat}`);\n }\n }\n}\n\nfunction formatJSON(projection: SpecTreeProjection): string {\n return JSON.stringify(projection, null, JSON_INDENTATION);\n}\n\nfunction formatText(projection: SpecTreeProjection): string {\n return projection.nodes.map((node) => formatTextNode(node)).join(\"\\n\");\n}\n\nfunction formatTextNode(node: SpecTreeProjectedNode, depth = 0): string {\n const current = `${NODE_INDENT.repeat(depth)}${formatNodeLabel(node)}`;\n const children = node.children.map((child) => formatTextNode(child, depth + 1));\n return [current, ...children].join(\"\\n\");\n}\n\nfunction formatMarkdown(projection: SpecTreeProjection): string {\n return projection.nodes.map((node) => formatMarkdownNode(node)).join(\"\\n\");\n}\n\nfunction formatMarkdownNode(node: SpecTreeProjectedNode, depth = 0): string {\n const current = `${NODE_INDENT.repeat(depth)}${MARKDOWN_NODE_PREFIX}${formatNodeLabel(node)}`;\n const children = node.children.map((child) => formatMarkdownNode(child, depth + 1));\n return [current, ...children].join(\"\\n\");\n}\n\nfunction formatTable(projection: SpecTreeProjection): string {\n const rows = flattenProjectionNodes(projection.nodes).map((node) => [\n KIND_REGISTRY[node.kind].label,\n node.id,\n node.state,\n ]);\n return [\n SPEC_STATUS_TABLE_HEADER,\n formatTableRow([TABLE_HEADER_SEPARATOR, TABLE_HEADER_SEPARATOR, TABLE_HEADER_SEPARATOR]),\n ...rows.map(formatTableRow),\n ].join(\"\\n\");\n}\n\nfunction flattenProjectionNodes(nodes: readonly SpecTreeProjectedNode[]): readonly SpecTreeProjectedNode[] {\n return nodes.flatMap((node) => [node, ...flattenProjectionNodes(node.children)]);\n}\n\nfunction formatTableRow(values: readonly string[]): string {\n return `${TABLE_SEPARATOR} ${values.join(` ${TABLE_SEPARATOR} `)} ${TABLE_SEPARATOR}`;\n}\n\nfunction formatNodeLabel(node: SpecTreeProjectedNode): string {\n return [\n KIND_REGISTRY[node.kind].label,\n node.id,\n `[${node.state}]`,\n ].join(STATUS_SEPARATOR);\n}\n","/**\n * Python test-runner descriptor.\n *\n * Declares pytest as the Python test runner: detection gating, the pytest\n * test-file pattern, pure exclusion-flag generation, and invocation through an\n * injected command runner. Composing descriptors into a registry and dispatching\n * the `spx test` command are separate, higher-level concerns.\n */\nimport { basename, dirname, join } from \"node:path/posix\";\n\nimport type {\n TestingLanguageDescriptor,\n TestRunInvocation,\n TestRunnerDependencies,\n TestRunRequest,\n} from \"@/testing/languages/types\";\nimport { compareAsciiStrings } from \"@/lib/state-store\";\nimport { detectPython } from \"@/validation/discovery/language-finder\";\nimport {\n PYTEST_INVOKE_ARGS,\n PYTHON_PYTEST_IGNORE_FLAG_PREFIX,\n PYTHON_PYTEST_IGNORE_FLAG_SUFFIX,\n UV_COMMAND,\n} from \"./python-pytest-contract\";\n\nconst PYTHON_TESTING_LANGUAGE_NAME = \"python\";\nexport const PYTHON_PRODUCT_INPUT_PATH = {\n CONFTEST: \"conftest.py\",\n HIDDEN_PYTEST_INI: \".pytest.ini\",\n HIDDEN_PYTEST_TOML: \".pytest.toml\",\n PYPROJECT: \"pyproject.toml\",\n PYTEST_TOML: \"pytest.toml\",\n PYTEST_INI: \"pytest.ini\",\n SETUP_CFG: \"setup.cfg\",\n SETUP_PY: \"setup.py\",\n TOX_INI: \"tox.ini\",\n UV_LOCK: \"uv.lock\",\n} as const;\nconst PYTHON_PRODUCT_INPUT_PATHS = Object.values(PYTHON_PRODUCT_INPUT_PATH);\n\n/** pytest test-file basename shape: a `test_` prefix and a `.py` extension. */\nexport const PYTHON_TEST_FILE_PREFIX = \"test_\";\nconst PYTHON_TEST_FILE_EXTENSION = \".py\";\nconst PYTHON_TEST_FILE_PATTERNS = [`${PYTHON_TEST_FILE_PREFIX}*${PYTHON_TEST_FILE_EXTENSION}`] as const;\n\nfunction matchesTestFile(filePath: string): boolean {\n return basename(filePath).startsWith(PYTHON_TEST_FILE_PREFIX) && filePath.endsWith(PYTHON_TEST_FILE_EXTENSION);\n}\n\nfunction coveredProductInputPaths(coveredTestPaths: readonly string[]): readonly string[] {\n const paths = new Set<string>();\n for (const testPath of coveredTestPaths) {\n if (!matchesTestFile(testPath)) continue;\n let directory = dirname(testPath);\n while (directory !== \".\" && directory.length > 0) {\n paths.add(join(directory, PYTHON_PRODUCT_INPUT_PATH.CONFTEST));\n const parent = dirname(directory);\n if (parent === directory) break;\n directory = parent;\n }\n }\n return [...paths].sort(compareAsciiStrings);\n}\n\nfunction excludeFlag(nodePath: string): string {\n return `${PYTHON_PYTEST_IGNORE_FLAG_PREFIX}${nodePath}${PYTHON_PYTEST_IGNORE_FLAG_SUFFIX}`;\n}\n\nfunction detect(projectRoot: string, deps?: Pick<TestRunnerDependencies, \"isLanguagePresent\">): boolean {\n return deps?.isLanguagePresent?.(projectRoot) ?? detectPython(projectRoot).present;\n}\n\nasync function runTests(request: TestRunRequest, deps: TestRunnerDependencies): Promise<TestRunInvocation> {\n if (!detect(request.projectRoot, deps)) {\n return { invoked: false };\n }\n\n const args = [\n ...PYTEST_INVOKE_ARGS,\n ...request.testPaths,\n ...request.excludedNodePaths.map(excludeFlag),\n ];\n\n const result = await deps.runCommand(UV_COMMAND, args);\n return { invoked: true, exitCode: result.exitCode };\n}\n\nexport const pythonTestingLanguage: TestingLanguageDescriptor = {\n name: PYTHON_TESTING_LANGUAGE_NAME,\n testFilePatterns: PYTHON_TEST_FILE_PATTERNS,\n productInputPaths: PYTHON_PRODUCT_INPUT_PATHS,\n coveredProductInputPaths,\n matchesTestFile,\n excludeFlag,\n detect,\n runTests,\n};\n","/**\n * Language detection for validation infrastructure.\n *\n * Detects which programming languages a project uses based on configuration\n * file presence. Language-specific validation tools (ESLint, tsc, mypy) consult\n * detection results to determine whether to run.\n *\n * @module validation/discovery/language-finder\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\n// =============================================================================\n// CONSTANTS\n// =============================================================================\n\n/**\n * Marker file for TypeScript projects, checked in the project root.\n */\nexport const TYPESCRIPT_MARKER = \"tsconfig.json\";\n\n/**\n * Marker file for Python projects, checked in the project root.\n */\nexport const PYTHON_MARKER = \"pyproject.toml\";\n\n/**\n * ESLint flat config file names, in priority order.\n *\n * ESLint 9+ uses flat config exclusively. When multiple config files exist in\n * the same directory, the highest-priority one wins.\n */\nexport const ESLINT_CONFIG_FILES = [\n \"eslint.config.ts\",\n \"eslint.config.js\",\n \"eslint.config.mjs\",\n \"eslint.config.cjs\",\n] as const;\nexport const ESLINT_PRODUCTION_CONFIG_FILES = [\n \"eslint.config.production.ts\",\n \"eslint.config.production.js\",\n \"eslint.config.production.mjs\",\n \"eslint.config.production.cjs\",\n] as const;\n\n/**\n * Type of an ESLint config file name.\n */\nexport type EslintConfigFile = (typeof ESLINT_CONFIG_FILES)[number];\nexport type EslintProductionConfigFile = (typeof ESLINT_PRODUCTION_CONFIG_FILES)[number];\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\n/**\n * Result of TypeScript language detection.\n */\nexport interface TypeScriptDetection {\n /** Whether TypeScript is present in the project. */\n present: boolean;\n /** The ESLint flat config file name found, if any. Only set when `present` is true. */\n eslintConfigFile?: EslintConfigFile;\n /** Production-scope ESLint flat config file name found, if any. Only set when `present` is true. */\n productionEslintConfigFile?: EslintProductionConfigFile;\n}\n\n/**\n * Result of Python language detection.\n */\nexport interface PythonDetection {\n /** Whether Python is present in the project. */\n present: boolean;\n}\n\n/**\n * Result of full language detection.\n */\nexport interface LanguageDetection {\n typescript: TypeScriptDetection;\n python: PythonDetection;\n}\n\n/**\n * Dependencies for language detection.\n *\n * Enables type-safe dependency injection for testing without mocking.\n */\nexport interface LanguageDetectionDeps {\n /**\n * Check whether a file exists at the given absolute path.\n * @param filePath - Absolute path to check.\n */\n existsSync: (filePath: string) => boolean;\n}\n\n/**\n * Default production dependencies.\n */\nexport const defaultLanguageDetectionDeps: LanguageDetectionDeps = {\n existsSync: fs.existsSync,\n};\n\n// =============================================================================\n// DETECTION FUNCTIONS\n// =============================================================================\n\n/**\n * Detect whether a project uses TypeScript.\n *\n * TypeScript is present when `tsconfig.json` exists in the project root. When\n * present, the function also searches for an ESLint flat config file and\n * returns its name in priority order.\n *\n * @param projectRoot - Absolute path to the project root.\n * @param deps - Injectable filesystem dependencies.\n * @returns Detection result with presence flag and optional ESLint config path.\n */\nexport function detectTypeScript(\n projectRoot: string,\n deps: LanguageDetectionDeps = defaultLanguageDetectionDeps,\n): TypeScriptDetection {\n const present = deps.existsSync(path.join(projectRoot, TYPESCRIPT_MARKER));\n\n if (!present) {\n return { present: false };\n }\n\n const eslintConfigFile = ESLINT_CONFIG_FILES.find((configFile) =>\n deps.existsSync(path.join(projectRoot, configFile))\n );\n const productionEslintConfigFile = ESLINT_PRODUCTION_CONFIG_FILES.find((configFile) =>\n deps.existsSync(path.join(projectRoot, configFile))\n );\n\n return { present: true, eslintConfigFile, productionEslintConfigFile };\n}\n\n/**\n * Detect whether a project uses Python.\n *\n * Python is present when `pyproject.toml` exists in the project root.\n *\n * @param projectRoot - Absolute path to the project root.\n * @param deps - Injectable filesystem dependencies.\n * @returns Detection result with presence flag.\n */\nexport function detectPython(\n projectRoot: string,\n deps: LanguageDetectionDeps = defaultLanguageDetectionDeps,\n): PythonDetection {\n const present = deps.existsSync(path.join(projectRoot, PYTHON_MARKER));\n return { present };\n}\n\n/**\n * Detect all supported languages in a project.\n *\n * @param projectRoot - Absolute path to the project root.\n * @param deps - Injectable filesystem dependencies.\n * @returns Detection result for every supported language.\n */\nexport function detectLanguages(\n projectRoot: string,\n deps: LanguageDetectionDeps = defaultLanguageDetectionDeps,\n): LanguageDetection {\n return {\n typescript: detectTypeScript(projectRoot, deps),\n python: detectPython(projectRoot, deps),\n };\n}\n","/** pytest exclusion-flag format: an excluded node path maps to `--ignore=spx/{nodePath}/`. */\nexport const PYTHON_PYTEST_IGNORE_FLAG_PREFIX = \"--ignore=spx/\";\nexport const PYTHON_PYTEST_IGNORE_FLAG_SUFFIX = \"/\";\n\n// pytest runs through `uv run --active` so the provisioned active Python environment provides the tool;\n// pytest takes its rootdir, configuration, and environment from the command runner's working directory.\nexport const UV_COMMAND = \"uv\";\nexport const PYTEST_INVOKE_ARGS = [\"run\", \"--active\", \"pytest\"] as const;\n","/**\n * TypeScript test-runner descriptor.\n *\n * Declares vitest as the TypeScript test runner: detection gating, the vitest\n * test-file patterns, pure exclusion-flag generation, and invocation through an\n * injected command runner. Composing descriptors into a registry and dispatching\n * the `spx test` command are separate, higher-level concerns.\n */\nimport type {\n TestingLanguageDescriptor,\n TestRunInvocation,\n TestRunnerDependencies,\n TestRunRequest,\n} from \"@/testing/languages/types\";\nimport { detectTypeScript } from \"@/validation/discovery/language-finder\";\n\nconst TYPESCRIPT_TESTING_LANGUAGE_NAME = \"typescript\";\nconst TYPESCRIPT_TEST_FILE_PATTERNS = [\"*.test.ts\", \"*.test.tsx\"] as const;\nconst TYPESCRIPT_TEST_FILE_SUFFIXES = [\".test.ts\", \".test.tsx\"] as const;\nconst TYPESCRIPT_PRODUCT_INPUT_PATHS = [\n \"package.json\",\n \"pnpm-lock.yaml\",\n \"tsconfig.json\",\n \"vitest.config.js\",\n \"vitest.config.mjs\",\n \"vitest.config.ts\",\n \"vitest.config.mts\",\n] as const;\n\n/** vitest exclusion-flag format: an excluded node path maps to `--exclude=spx/{nodePath}/**`. */\nexport const TYPESCRIPT_VITEST_EXCLUDE_FLAG_PREFIX = \"--exclude=spx/\";\nexport const TYPESCRIPT_VITEST_EXCLUDE_FLAG_SUFFIX = \"/**\";\n\n// vitest runs through the project's package manager so the project's node_modules\n// provides the binary; `--root` makes the project under test explicit.\nconst PACKAGE_MANAGER_COMMAND = \"pnpm\";\nconst VITEST_INVOKE_ARGS = [\"exec\", \"vitest\", \"run\"] as const;\nconst VITEST_ROOT_FLAG = \"--root\";\n\nfunction matchesTestFile(filePath: string): boolean {\n return TYPESCRIPT_TEST_FILE_SUFFIXES.some((suffix) => filePath.endsWith(suffix));\n}\n\nfunction excludeFlag(nodePath: string): string {\n return `${TYPESCRIPT_VITEST_EXCLUDE_FLAG_PREFIX}${nodePath}${TYPESCRIPT_VITEST_EXCLUDE_FLAG_SUFFIX}`;\n}\n\nfunction detect(projectRoot: string, deps?: Pick<TestRunnerDependencies, \"isLanguagePresent\">): boolean {\n return deps?.isLanguagePresent?.(projectRoot) ?? detectTypeScript(projectRoot).present;\n}\n\nasync function runTests(request: TestRunRequest, deps: TestRunnerDependencies): Promise<TestRunInvocation> {\n if (!detect(request.projectRoot, deps)) {\n return { invoked: false };\n }\n\n const args = [\n ...VITEST_INVOKE_ARGS,\n VITEST_ROOT_FLAG,\n request.projectRoot,\n ...request.testPaths,\n ...request.excludedNodePaths.map(excludeFlag),\n ];\n\n const result = await deps.runCommand(PACKAGE_MANAGER_COMMAND, args);\n return { invoked: true, exitCode: result.exitCode };\n}\n\nexport const typescriptTestingLanguage: TestingLanguageDescriptor = {\n name: TYPESCRIPT_TESTING_LANGUAGE_NAME,\n testFilePatterns: TYPESCRIPT_TEST_FILE_PATTERNS,\n productInputPaths: TYPESCRIPT_PRODUCT_INPUT_PATHS,\n matchesTestFile,\n excludeFlag,\n detect,\n runTests,\n};\n","/**\n * Testing language registry.\n *\n * Composes the `spx test` dispatch from explicitly imported language testing\n * descriptors. Orchestration iterates `testingRegistry.languages`; it never\n * references a language by name and never discovers descriptors through\n * filesystem scanning. Adding a language is one descriptor module plus one entry\n * here.\n */\nimport { pythonTestingLanguage } from \"@/testing/languages/python\";\nimport type { TestingLanguageDescriptor } from \"@/testing/languages/types\";\nimport { typescriptTestingLanguage } from \"@/testing/languages/typescript\";\n\nexport interface TestingRegistry {\n readonly languages: readonly TestingLanguageDescriptor[];\n}\n\nexport const testingRegistry: TestingRegistry = {\n languages: [typescriptTestingLanguage, pythonTestingLanguage],\n};\n","/**\n * Conventional exit codes for CLI termination paths.\n *\n * The mapping follows POSIX convention: 128 + signal number for\n * signal-terminated processes, 0 for downstream-closed pipes (matches\n * `head`/`tee` behavior under `SIGPIPE`), 1 for genuine internal failures.\n *\n * @module lib/process-lifecycle/exit-codes\n */\n\nexport const SIGINT_EXIT_CODE = 130;\nexport const SIGTERM_EXIT_CODE = 143;\nexport const EPIPE_EXIT_CODE = 0;\nexport const UNCAUGHT_EXIT_CODE = 1;\n","/**\n * Lifecycle handler factory. Produces the four handler entry points that\n * fire on SIGINT, SIGTERM, EPIPE, and uncaught exceptions.\n *\n * Each handler is idempotent: a `cleanupOnce` flag plus per-child\n * `child.killed` checks ensure that repeated invocations kill each\n * registered child exactly once. This handles the race in which SIGINT\n * arrives mid-write to a closed pipe.\n *\n * @module lib/process-lifecycle/handlers\n */\n\nimport { EPIPE_EXIT_CODE, SIGINT_EXIT_CODE, SIGTERM_EXIT_CODE, UNCAUGHT_EXIT_CODE } from \"./exit-codes\";\nimport type { ChildHandle, LifecycleHandlerDeps, LifecycleHandlers } from \"./types\";\n\nexport const SIGINT_NAME: NodeJS.Signals = \"SIGINT\";\nexport const SIGTERM_NAME: NodeJS.Signals = \"SIGTERM\";\n\nexport function createHandlers(deps: LifecycleHandlerDeps): LifecycleHandlers {\n let cleanupOnce = false;\n\n function killEachChild(signal: NodeJS.Signals): void {\n deps.registry.forEach((child: ChildHandle) => {\n if (!child.killed) child.kill(signal);\n });\n }\n\n function exitOnce(code: number, killSignal?: NodeJS.Signals): void {\n if (cleanupOnce) {\n deps.exitController.exit(code);\n return;\n }\n cleanupOnce = true;\n if (killSignal !== undefined) killEachChild(killSignal);\n deps.exitController.exit(code);\n }\n\n return {\n onSigint(): void {\n exitOnce(SIGINT_EXIT_CODE, SIGINT_NAME);\n },\n onSigterm(): void {\n exitOnce(SIGTERM_EXIT_CODE, SIGTERM_NAME);\n },\n onEpipe(): void {\n exitOnce(EPIPE_EXIT_CODE, SIGTERM_NAME);\n },\n onUncaught(_error: unknown): void {\n exitOnce(UNCAUGHT_EXIT_CODE, SIGTERM_NAME);\n },\n };\n}\n","/**\n * CLI process-lifecycle installation. Wires real Node process events to the\n * lifecycle handlers and exposes the production `lifecycleProcessRunner`\n * that the validation steps consume.\n *\n * The module-scoped registry holds child handles; `installLifecycle()`\n * attaches handlers once. Calling `installLifecycle()` more than once is a\n * no-op so re-entry from accidental imports does not double-install.\n *\n * @module lib/process-lifecycle/install\n */\n\nimport { spawn } from \"node:child_process\";\n\nimport { createHandlers } from \"./handlers\";\nimport { createRegistry } from \"./registry\";\nimport { createLifecycleRunner } from \"./runner\";\nimport type { ChildRegistry, ExitController, LifecycleHandlers } from \"./types\";\n\nconst moduleRegistry: ChildRegistry = createRegistry();\nconst moduleExitController: ExitController = {\n exit(code: number): void {\n process.exit(code);\n },\n};\n\nlet installed = false;\n\nexport const lifecycleProcessRunner = createLifecycleRunner({\n registry: moduleRegistry,\n spawn,\n});\n\nexport const EPIPE_CODE = \"EPIPE\";\nexport const UNCAUGHT_EVENT_NAME = \"uncaughtException\";\nconst UNCAUGHT_PREFIX = \"Uncaught: \";\nconst NEWLINE = \"\\n\";\n\nfunction formatUncaught(error: unknown): string {\n if (error instanceof Error && error.stack !== undefined) {\n return UNCAUGHT_PREFIX + error.stack + NEWLINE;\n }\n return UNCAUGHT_PREFIX + String(error) + NEWLINE;\n}\n\nfunction logUncaughtToStderr(error: unknown): void {\n // Best-effort diagnostic write before the process exits. If stderr is\n // already closed, the write throws synchronously and we swallow it; the\n // exit path runs regardless so the operator at minimum sees a non-zero\n // exit code.\n try {\n process.stderr.write(formatUncaught(error));\n } catch {\n /* stderr unavailable; rely on exit code */\n }\n}\n\nexport function installLifecycle(): void {\n if (installed) return;\n installed = true;\n\n const handlers: LifecycleHandlers = createHandlers({\n registry: moduleRegistry,\n exitController: moduleExitController,\n });\n\n process.on(\"uncaughtException\", (error: unknown) => {\n logUncaughtToStderr(error);\n handlers.onUncaught(error);\n });\n process.on(\"unhandledRejection\", (reason: unknown) => {\n logUncaughtToStderr(reason);\n handlers.onUncaught(reason);\n });\n process.on(\"SIGTERM\", () => handlers.onSigterm());\n process.on(\"SIGINT\", () => handlers.onSigint());\n\n process.stdout.on(\"error\", (error: NodeJS.ErrnoException) => {\n if (error.code === EPIPE_CODE) {\n handlers.onEpipe();\n return;\n }\n handlers.onUncaught(error);\n });\n process.stderr.on(\"error\", (error: NodeJS.ErrnoException) => {\n if (error.code === EPIPE_CODE) {\n handlers.onEpipe();\n return;\n }\n handlers.onUncaught(error);\n });\n}\n","/**\n * Child-process registry. Tracks asynchronously spawned children so that\n * lifecycle handlers can reach them when the parent receives a termination\n * signal.\n *\n * The registry is identity-based: callers pass the `ChildHandle` reference\n * returned by `spawn` to both `add` and `remove`.\n *\n * @module lib/process-lifecycle/registry\n */\n\nimport type { ChildHandle, ChildRegistry } from \"./types\";\n\nexport function createRegistry(): ChildRegistry {\n const tracked = new Set<ChildHandle>();\n\n return {\n add(child: ChildHandle): void {\n tracked.add(child);\n },\n remove(child: ChildHandle): void {\n tracked.delete(child);\n },\n forEach(fn: (child: ChildHandle) => void): void {\n for (const child of tracked) fn(child);\n },\n get size(): number {\n return tracked.size;\n },\n };\n}\n","/**\n * Lifecycle-aware process runner. Wraps a real `spawn` function so that\n * every child handle returned by `runner.spawn(...)` is registered in the\n * lifecycle registry and removed when the child exits.\n *\n * @module lib/process-lifecycle/runner\n */\n\nimport type { ChildRegistry, ProcessRunner } from \"./types\";\n\nexport interface LifecycleRunnerDeps {\n readonly registry: ChildRegistry;\n readonly spawn: ProcessRunner[\"spawn\"];\n}\n\nexport type LifecycleSpawn = LifecycleRunnerDeps[\"spawn\"];\n\nexport function createLifecycleRunner(deps: LifecycleRunnerDeps): ProcessRunner {\n return {\n spawn(command, args, options) {\n const child = deps.spawn(command, args, options);\n deps.registry.add(child);\n child.on(\"exit\", () => deps.registry.remove(child));\n return child;\n },\n };\n}\n","import type { ChildProcess, SpawnOptions } from \"node:child_process\";\n\nimport type { ProcessRunner } from \"./types\";\n\nexport const MANAGED_SUBPROCESS_STDIO = \"pipe\";\n\nexport type ManagedSubprocessSpawnOptions = Omit<SpawnOptions, \"stdio\"> & {\n readonly stdio?: never;\n};\n\nexport function spawnManagedSubprocess(\n runner: ProcessRunner,\n command: string,\n args: readonly string[],\n options: ManagedSubprocessSpawnOptions,\n): ChildProcess {\n return runner.spawn(command, args, {\n ...options,\n stdio: MANAGED_SUBPROCESS_STDIO,\n });\n}\n","import type { ChildProcess } from \"node:child_process\";\n\nimport { lifecycleProcessRunner, spawnManagedSubprocess } from \"@/lib/process-lifecycle\";\nimport type {\n TestingLanguageDescriptor,\n TestRunCommandResult,\n TestRunnerDependencies,\n} from \"@/testing/languages/types\";\n\nexport const PROCESS_FAILURE_EXIT_CODE = 1;\n\n// Spawns a managed child through the lifecycle runner, forwards its stdout to the\n// caller-chosen stream and its stderr to the CLI's error stream, and resolves with\n// the child's terminal exit code. The stdout stream is a parameter because `spx test`\n// wants the run's output on stdout while `spx spec status --update` must keep stdout\n// for the status rollup and route per-node output to stderr.\nfunction createCommandRunner(\n productDir: string,\n outStream: NodeJS.WritableStream,\n): TestRunnerDependencies[\"runCommand\"] {\n return (command, args) =>\n new Promise<TestRunCommandResult>((resolveResult) => {\n const child: ChildProcess = spawnManagedSubprocess(lifecycleProcessRunner, command, args, {\n cwd: productDir,\n });\n child.stdout?.pipe(outStream);\n child.stderr?.pipe(process.stderr);\n child.on(\"close\", (code) => resolveResult({ exitCode: code ?? PROCESS_FAILURE_EXIT_CODE }));\n child.on(\"error\", () => resolveResult({ exitCode: PROCESS_FAILURE_EXIT_CODE }));\n });\n}\n\n/**\n * Builds the runner dependencies the `spx test` run and the\n * `spx spec status --update` outcome resolver both compose: a command runner\n * scoped to the product directory. Language presence belongs to each descriptor.\n * `outStream` receives each child's stdout — `spx test` keeps the default\n * `process.stdout`, while `spx spec status --update` passes `process.stderr` so the\n * status rollup (text or `--json`) is the only thing written to stdout.\n */\nexport function createRunnerDepsFor(\n productDir: string,\n outStream: NodeJS.WritableStream = process.stdout,\n): (language: TestingLanguageDescriptor) => TestRunnerDependencies {\n const runCommand = createCommandRunner(productDir, outStream);\n return () => ({ runCommand });\n}\n","import type { Command } from \"commander\";\n\nimport { nextCommand } from \"@/commands/spec/next\";\nimport { createNodeOutcomeResolver } from \"@/commands/spec/node-outcome-resolver\";\nimport { OUTPUT_FORMAT, type OutputFormat, statusCommand } from \"@/commands/spec/status\";\nimport type { Domain } from \"@/domains/types\";\nimport { testingRegistry } from \"@/testing/registry\";\n\nimport { createRunnerDepsFor } from \"./testing-runner-deps\";\nimport { writeWarning } from \"./write-warning\";\n\nexport const SPEC_DOMAIN_CLI = {\n COMMAND: \"spec\",\n STATUS_COMMAND: \"status\",\n NEXT_COMMAND: \"next\",\n JSON_OPTION: \"--json\",\n FORMAT_OPTION_FLAG: \"--format\",\n FORMAT_OPTION_DEFINITION: \"--format <format>\",\n UPDATE_OPTION: \"--update\",\n} as const;\n\nexport const SPEC_STATUS_FORMAT_MESSAGE = {\n INVALID_PREFIX: \"Invalid format\",\n} as const;\n\nconst VALID_STATUS_FORMATS: readonly OutputFormat[] = [\n OUTPUT_FORMAT.TEXT,\n OUTPUT_FORMAT.JSON,\n OUTPUT_FORMAT.MARKDOWN,\n OUTPUT_FORMAT.TABLE,\n];\n\nfunction handleCommandError(error: unknown): never {\n console.error(\"Error:\", error instanceof Error ? error.message : String(error));\n process.exit(1);\n}\n\nfunction resolveStatusFormat(options: { json?: boolean; format?: string }): OutputFormat {\n if (options.json === true) {\n return \"json\";\n }\n\n if (options.format === undefined) {\n return \"text\";\n }\n\n if (VALID_STATUS_FORMATS.includes(options.format as OutputFormat)) {\n return options.format as OutputFormat;\n }\n\n throw new Error(\n `${SPEC_STATUS_FORMAT_MESSAGE.INVALID_PREFIX} \"${options.format}\". Must be one of: ${\n VALID_STATUS_FORMATS.join(\", \")\n }`,\n );\n}\n\nfunction registerSpecCommands(specCmd: Command): void {\n specCmd\n .command(SPEC_DOMAIN_CLI.STATUS_COMMAND)\n .description(\"Get product status\")\n .option(SPEC_DOMAIN_CLI.JSON_OPTION, \"Output as JSON\")\n .option(SPEC_DOMAIN_CLI.FORMAT_OPTION_DEFINITION, \"Output format (text|json|markdown|table)\")\n .option(SPEC_DOMAIN_CLI.UPDATE_OPTION, \"Refresh each node's spx.status.json before reporting\")\n .action(async (options: { json?: boolean; format?: string; update?: boolean }) => {\n try {\n const format = resolveStatusFormat(options);\n // The per-node runner pipes child stdout to process.stderr here so stdout\n // carries only the status rollup; a --json rollup therefore stays parseable\n // even when --update runs a node's tests for stale, failing, or absent evidence.\n const output = options.update === true\n ? await statusCommand({\n cwd: process.cwd(),\n format,\n onWarning: writeWarning,\n update: true,\n resolveOutcomeFor: (productDir) =>\n createNodeOutcomeResolver({\n productDir,\n registry: testingRegistry,\n runnerDepsFor: createRunnerDepsFor(productDir, process.stderr),\n }),\n })\n : await statusCommand({ cwd: process.cwd(), format, onWarning: writeWarning });\n console.log(output);\n } catch (error) {\n handleCommandError(error);\n }\n });\n\n specCmd\n .command(SPEC_DOMAIN_CLI.NEXT_COMMAND)\n .description(\"Find next spec-tree node to work on\")\n .action(async () => {\n try {\n const output = await nextCommand({ cwd: process.cwd(), onWarning: writeWarning });\n console.log(output);\n } catch (error) {\n handleCommandError(error);\n }\n });\n}\n\nexport const specDomain: Domain = {\n name: \"spec\",\n description: \"Manage spec workflow\",\n register: (program: Command) => {\n const specCmd = program\n .command(SPEC_DOMAIN_CLI.COMMAND)\n .description(\"Manage spec workflow\");\n\n registerSpecCommands(specCmd);\n },\n};\n","import type { Command } from \"commander\";\n\nimport { runTestsCommand, type TestDispatchResult } from \"@/commands/testing\";\nimport type { Domain } from \"@/domains/types\";\nimport { detectWorktreeProductRoot } from \"@/git/root\";\nimport { writeWarning } from \"@/interfaces/cli/write-warning\";\nimport { SPEC_TREE_CONFIG } from \"@/lib/spec-tree/config\";\nimport { testingRegistry } from \"@/testing/registry\";\n\nimport { createRunnerDepsFor, PROCESS_FAILURE_EXIT_CODE } from \"./testing-runner-deps\";\n\nconst TESTING_CLI = {\n commandName: \"test\",\n description: \"Run spec-tree tests across product languages\",\n passingSubcommand: \"passing\",\n passingDescription: \"Run only the tests within the configured passing scope\",\n} as const;\n\nconst UNMATCHED_TEST_FILES_WARNING = \"Skipped test files with no registered runner\";\n\nconst TESTING_PRODUCT_DIR_WARNING = {\n NOT_GIT_REPOSITORY:\n `Warning: Not in a git repository. Reading ${SPEC_TREE_CONFIG.ROOT_DIRECTORY} tests relative to the current working directory.`,\n} as const;\n\nasync function resolveTestProductDir(): Promise<string> {\n const { productDir, isGitRepo } = await detectWorktreeProductRoot(process.cwd());\n writeWarning(isGitRepo ? undefined : TESTING_PRODUCT_DIR_WARNING.NOT_GIT_REPOSITORY);\n return productDir;\n}\n\n// Runs the testing command, surfacing its dispatch result; a config or recording\n// failure exits here, where the descriptor owns the process boundary.\nasync function runTestsThroughCommand(productDir: string, passing: boolean): Promise<TestDispatchResult> {\n try {\n const result = await runTestsCommand(\n { productDir, passing },\n { registry: testingRegistry, runnerDepsFor: createRunnerDepsFor(productDir) },\n );\n return result.dispatch;\n } catch (error) {\n process.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n`);\n process.exit(PROCESS_FAILURE_EXIT_CODE);\n }\n}\n\nfunction reportAndExit(result: TestDispatchResult): never {\n if (result.unmatched.length > 0) {\n writeWarning(`${UNMATCHED_TEST_FILES_WARNING}:\\n${result.unmatched.join(\"\\n\")}`);\n }\n process.exit(result.exitCode);\n}\n\nexport const testingDomain: Domain = {\n name: TESTING_CLI.commandName,\n description: TESTING_CLI.description,\n register: (program: Command) => {\n const testCmd = program.command(TESTING_CLI.commandName).description(TESTING_CLI.description);\n\n testCmd.action(async () => {\n const productDir = await resolveTestProductDir();\n reportAndExit(await runTestsThroughCommand(productDir, false));\n });\n\n testCmd\n .command(TESTING_CLI.passingSubcommand)\n .description(TESTING_CLI.passingDescription)\n .action(async () => {\n const productDir = await resolveTestProductDir();\n reportAndExit(await runTestsThroughCommand(productDir, true));\n });\n },\n};\n","/**\n * Markdown validation command.\n *\n * Runs markdownlint-cli2 for markdown link integrity and structural quality.\n * Unlike other validation commands, this does not use discoverTool() --\n * markdownlint-cli2 is a production dependency, always available.\n */\n\nimport { relative } from \"node:path\";\n\nimport { resolveConfig } from \"@/config/index\";\nimport {\n VALIDATION_PATH_TOOL_SUBSECTIONS,\n type ValidationConfig,\n validationConfigDescriptor,\n} from \"@/validation/config/descriptor\";\nimport { pathPassesValidationFilter, validationPathFilterForTool } from \"@/validation/config/path-filter\";\nimport {\n getDefaultDirectories,\n MARKDOWN_VALIDATION_TARGET_KIND,\n type MarkdownSkippedValidationTarget,\n type MarkdownValidationTarget,\n resolveMarkdownValidationTarget,\n validateMarkdown,\n} from \"@/validation/steps/markdown\";\nimport { VALIDATION_COMMAND_OUTPUT, VALIDATION_SKIP_LABELS, VALIDATION_STAGE_DISPLAY_NAMES } from \"./messages\";\nimport type { MarkdownCommandOptions, ValidationCommandResult } from \"./types\";\n\n/**\n * Run markdown validation.\n *\n * Validates markdown files in the specified directories (or defaults to\n * spx/ and docs/). Returns structured results with exit code and output.\n *\n * @param options - Command options including cwd and optional file scoping\n * @returns Command result with exit code and output\n *\n * @example\n * ```typescript\n * // Validate default directories\n * const result = await markdownCommand({ cwd: process.cwd() });\n *\n * // Validate specific directories\n * const result = await markdownCommand({\n * cwd: process.cwd(),\n * files: [\"/path/to/spx\"],\n * });\n * ```\n */\nexport const MARKDOWN_COMMAND_OUTPUT = {\n ERROR_SUMMARY_SUFFIX: VALIDATION_COMMAND_OUTPUT.MARKDOWN_ERROR_SUMMARY_SUFFIX,\n NO_ISSUES: VALIDATION_COMMAND_OUTPUT.MARKDOWN_NO_ISSUES,\n SKIPPED_FILE_SCOPE_PREFIX: \"Markdown skipped file scope\",\n} as const;\nconst MARKDOWN_CONFIG_ERROR_MESSAGE = `${VALIDATION_STAGE_DISPLAY_NAMES.MARKDOWN}: ✗ config error`;\n\nexport async function markdownCommand(options: MarkdownCommandOptions): Promise<ValidationCommandResult> {\n const { cwd, files, quiet } = options;\n const startTime = Date.now();\n const loaded = await resolveConfig(cwd, [validationConfigDescriptor]);\n if (!loaded.ok) {\n return {\n exitCode: 1,\n output: `${MARKDOWN_CONFIG_ERROR_MESSAGE} — ${loaded.error}`,\n durationMs: Date.now() - startTime,\n };\n }\n const validationConfig = loaded.value[validationConfigDescriptor.section] as ValidationConfig;\n const pathFilter = validationPathFilterForTool(\n validationConfig.paths,\n VALIDATION_PATH_TOOL_SUBSECTIONS.MARKDOWN,\n );\n\n const targetResolutions = files && files.length > 0\n ? files.map((filePath) => resolveMarkdownValidationTarget(filePath))\n : undefined;\n const unfilteredTargets = targetResolutions !== undefined\n ? targetResolutions\n .map((resolution) => resolution.target)\n .filter((target): target is MarkdownValidationTarget => target !== undefined)\n : getDefaultDirectories(cwd).map((path) => ({\n kind: MARKDOWN_VALIDATION_TARGET_KIND.DIRECTORY,\n path,\n }));\n const targets = unfilteredTargets.filter((target) =>\n pathPassesValidationFilter(relative(cwd, target.path), pathFilter)\n );\n const skippedTargets = targetResolutions === undefined\n ? []\n : targetResolutions\n .map((resolution) => resolution.skipped)\n .filter((skipped): skipped is MarkdownSkippedValidationTarget => skipped !== undefined);\n const skippedOutput = quiet ? [] : skippedTargets.map(formatSkippedFileScope);\n\n if (targets.length === 0) {\n const reason = files && files.length > 0\n ? VALIDATION_SKIP_LABELS.MARKDOWN_NO_SCOPE_REASON\n : VALIDATION_SKIP_LABELS.MARKDOWN_NO_DEFAULT_DIRECTORIES_REASON;\n const output = quiet ? \"\" : [\n ...skippedOutput,\n `${VALIDATION_STAGE_DISPLAY_NAMES.MARKDOWN}: skipped (${reason})`,\n ].join(\"\\n\");\n return { exitCode: 0, output, durationMs: Date.now() - startTime };\n }\n\n // Run markdown validation\n const result = await validateMarkdown({\n targets,\n projectRoot: cwd,\n });\n const durationMs = Date.now() - startTime;\n\n // Map result to command output\n if (result.success) {\n const output = quiet ? \"\" : [...skippedOutput, MARKDOWN_COMMAND_OUTPUT.NO_ISSUES].join(\"\\n\");\n return { exitCode: 0, output, durationMs };\n } else {\n const errorLines = result.errors.map(\n (error) => ` ${error.file}:${error.line} ${error.detail}`,\n );\n const output = [\n ...skippedOutput,\n `Markdown: ${result.errors.length} ${MARKDOWN_COMMAND_OUTPUT.ERROR_SUMMARY_SUFFIX}`,\n ...errorLines,\n ]\n .join(\"\\n\");\n return { exitCode: 1, output, durationMs };\n }\n}\n\nfunction formatSkippedFileScope(target: MarkdownSkippedValidationTarget): string {\n return `${MARKDOWN_COMMAND_OUTPUT.SKIPPED_FILE_SCOPE_PREFIX}: ${target.path} (${target.reason})`;\n}\n","import { isAbsolute, relative } from \"node:path\";\n\nimport {\n type ValidationPathConfig,\n type ValidationPathFilterConfig,\n type ValidationPathToolSubsection,\n} from \"@/validation/config/descriptor\";\nimport type { ScopeConfig } from \"@/validation/types\";\n\nconst PATH_PREFIX_SEPARATOR = \"/\";\n\ninterface ValidationPathIncludeIntersection {\n readonly include?: readonly string[];\n readonly hasIncludeFilter: boolean;\n readonly noMatches: boolean;\n}\n\ntype EffectiveValidationPathFilterConfig = ValidationPathFilterConfig & {\n readonly hasIncludeFilter: boolean;\n readonly noMatchingIncludes: boolean;\n};\n\nfunction hasEffectiveValidationPathMetadata(\n filter: ValidationPathFilterConfig,\n): filter is EffectiveValidationPathFilterConfig {\n return \"hasIncludeFilter\" in filter\n && typeof filter.hasIncludeFilter === \"boolean\"\n && \"noMatchingIncludes\" in filter\n && typeof filter.noMatchingIncludes === \"boolean\";\n}\n\nfunction normalizePathPrefix(prefix: string): string {\n return prefix\n .split(/[\\\\/]/g)\n .join(PATH_PREFIX_SEPARATOR)\n .replace(/^\\.\\//, \"\")\n .replace(/\\/+$/, \"\");\n}\n\nfunction pathMatchesPrefix(path: string, prefix: string): boolean {\n const normalizedPath = normalizePathPrefix(path);\n const normalizedPrefix = normalizePathPrefix(prefix);\n return normalizedPath === normalizedPrefix\n || normalizedPath.startsWith(`${normalizedPrefix}${PATH_PREFIX_SEPARATOR}`);\n}\n\nfunction unique(values: readonly string[]): string[] {\n return [...new Set(values)];\n}\n\nfunction nonEmpty(values: readonly string[] | undefined): readonly string[] {\n return values?.filter((value) => value.length > 0) ?? [];\n}\n\nexport function toProjectRelativeValidationPath(projectRoot: string, path: string): string {\n return isAbsolute(path) ? relative(projectRoot, path) : path;\n}\n\nfunction intersectIncludes(\n baseInclude: readonly string[] | undefined,\n toolInclude: readonly string[] | undefined,\n): ValidationPathIncludeIntersection {\n const base = nonEmpty(baseInclude);\n const tool = nonEmpty(toolInclude);\n if (base.length === 0 && tool.length === 0) {\n return { hasIncludeFilter: false, noMatches: false };\n }\n if (base.length === 0) return { include: tool, hasIncludeFilter: true, noMatches: false };\n if (tool.length === 0) return { include: base, hasIncludeFilter: true, noMatches: false };\n\n const intersections = base.flatMap((basePrefix) =>\n tool.flatMap((toolPrefix) => {\n if (pathMatchesPrefix(basePrefix, toolPrefix)) return [basePrefix];\n if (pathMatchesPrefix(toolPrefix, basePrefix)) return [toolPrefix];\n return [];\n })\n );\n\n if (intersections.length === 0) {\n return { include: [], hasIncludeFilter: true, noMatches: true };\n }\n\n return { include: unique(intersections), hasIncludeFilter: true, noMatches: false };\n}\n\nexport function validationPathFilterForTool(\n paths: ValidationPathConfig,\n tool: ValidationPathToolSubsection,\n): EffectiveValidationPathFilterConfig {\n const toolConfig = paths[tool];\n const includeIntersection = intersectIncludes(paths.include, toolConfig?.include);\n return {\n include: includeIntersection.include,\n exclude: unique([...nonEmpty(paths.exclude), ...nonEmpty(toolConfig?.exclude)]),\n hasIncludeFilter: includeIntersection.hasIncludeFilter,\n noMatchingIncludes: includeIntersection.noMatches,\n };\n}\n\nexport function hasValidationPathFilter(filter: ValidationPathFilterConfig): boolean {\n return hasEffectiveValidationPathMetadata(filter) && filter.noMatchingIncludes\n || nonEmpty(filter.include).length > 0\n || nonEmpty(filter.exclude).length > 0;\n}\n\nexport function pathPassesValidationFilter(path: string, filter: ValidationPathFilterConfig): boolean {\n if (hasEffectiveValidationPathMetadata(filter) && filter.noMatchingIncludes) {\n return false;\n }\n const include = nonEmpty(filter.include);\n const exclude = nonEmpty(filter.exclude);\n if (include.length > 0 && !include.some((prefix) => pathMatchesPrefix(path, prefix))) {\n return false;\n }\n return !exclude.some((prefix) => pathMatchesPrefix(path, prefix));\n}\n\nexport function applyValidationPathFilterToScope(\n scopeConfig: ScopeConfig,\n filter: ValidationPathFilterConfig,\n): ScopeConfig {\n if (!hasValidationPathFilter(filter)) {\n return scopeConfig;\n }\n\n const includeFallbacks = nonEmpty(filter.include);\n const hasEffectiveMetadata = hasEffectiveValidationPathMetadata(filter);\n const hasIncludeFilter = hasEffectiveMetadata ? filter.hasIncludeFilter : includeFallbacks.length > 0;\n const scopedDirectories = scopeConfig.directories.filter((directory) =>\n pathPassesValidationFilter(directory, filter)\n );\n const scopedFilePatterns = scopeConfig.filePatterns.filter((pattern) => pathPassesValidationFilter(pattern, filter));\n const includeFallbacksWithinScope = includeFallbacks.filter((include) =>\n scopeConfig.directories.some((directory) => pathMatchesPrefix(include, directory))\n );\n const noMatchingIncludes = (hasEffectiveMetadata && filter.noMatchingIncludes)\n || (hasIncludeFilter && scopedDirectories.length === 0 && scopedFilePatterns.length === 0\n && includeFallbacksWithinScope.length === 0);\n const directories = noMatchingIncludes\n ? []\n : scopedDirectories.length > 0\n ? scopedDirectories\n : includeFallbacksWithinScope;\n const filePatterns = scopedFilePatterns.length > 0 ? scopedFilePatterns : [...directories];\n\n return {\n ...scopeConfig,\n directories,\n filePatterns,\n excludePatterns: unique([...scopeConfig.excludePatterns, ...nonEmpty(filter.exclude)]),\n filteredByValidationPaths: true,\n filteredByValidationPathIncludes: hasIncludeFilter,\n filteredByValidationPathNoMatches: noMatchingIncludes,\n };\n}\n","/**\n * Markdown validation step.\n *\n * Validates markdown files using markdownlint-cli2's programmatic API.\n * Configuration is built in code and passed via optionsOverride --\n * no config files are written to validated directories.\n *\n * @module validation/steps/markdown\n */\n\nimport { existsSync, statSync } from \"node:fs\";\nimport { basename, dirname, join, relative as pathRelative } from \"node:path\";\n\nimport { createIgnoreSourceReader, IGNORE_SOURCE_FILENAME_DEFAULT } from \"@/lib/file-inclusion/ignore-source\";\nimport { SPEC_TREE_CONFIG } from \"@/lib/spec-tree/config\";\n\n// @ts-expect-error markdownlint-cli2 has no TypeScript type declarations\nimport { main as markdownlintMain } from \"markdownlint-cli2\";\nimport relativeLinksRule from \"markdownlint-rule-relative-links\";\n\n// =============================================================================\n// CONSTANTS\n// =============================================================================\n\n/** Default directories to validate when no --files are specified. */\nexport const MARKDOWN_DEFAULT_DIRECTORY_NAMES = [\"spx\", \"docs\"] as const;\nexport const MARKDOWN_PRIMARY_FILE_EXTENSION = \".md\";\nconst MARKDOWN_FILE_EXTENSIONS: ReadonlySet<string> = new Set([\".md\", \".markdown\"]);\nexport const MARKDOWN_DIRECTORY_GLOB = \"**/*.md\";\n\n/** Built-in markdownlint rules enabled for validation (MD024 excluded — configured per directory). */\nconst ENABLED_RULES = {\n MD001: true,\n MD003: true,\n MD009: true,\n MD010: true,\n MD025: true,\n MD047: true,\n} as const;\n\n/** Directories where MD024 is disabled entirely (generated/repetitive headings are normal). */\nconst MD024_DISABLED_DIRECTORIES = [\"docs\"] as const;\n\nexport const MARKDOWN_CUSTOM_RULE_NAMES = relativeLinksRule.names;\nexport const MARKDOWN_VALIDATION_TARGET_KIND = {\n DIRECTORY: \"directory\",\n FILE: \"file\",\n} as const;\n\nexport const MARKDOWN_VALIDATION_TARGET_DIAGNOSTICS = {\n MISSING_OR_UNRELATED_SCOPE: \"not an existing directory or markdown file\",\n} as const;\n\n/**\n * Pattern for parsing markdownlint-cli2 default formatter output.\n * Format: filename:line[:column] [severity] ruleName/ruleAlias description [detail] [context]\n */\nconst ERROR_LINE_PATTERN = /^(.+?):(\\d+)(?::\\d+)?\\s+(.+)$/;\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\n/** A structured error from markdown validation. */\nexport interface MarkdownError {\n /** Absolute path to the file containing the error. */\n file: string;\n /** Line number where the error occurs (1-based). */\n line: number;\n /** Description of the error including rule name and detail. */\n detail: string;\n}\n\n/** Result of markdown validation. */\nexport interface MarkdownValidationResult {\n /** Whether all files passed validation. */\n success: boolean;\n /** Structured errors found during validation. */\n errors: MarkdownError[];\n}\n\n/** A markdownlint custom rule object. */\ninterface MarkdownlintRule {\n names: string[];\n description: string;\n tags: string[];\n}\n\n/** Options for the validateMarkdown function. */\nexport interface ValidateMarkdownOptions {\n /** Files or directories to validate. */\n targets: MarkdownValidationTarget[];\n /** Project root for resolving project-absolute links. */\n projectRoot?: string;\n}\n\nexport interface MarkdownValidationTarget {\n readonly kind: MarkdownValidationTargetKind;\n readonly path: string;\n}\n\nexport type MarkdownValidationTargetKind =\n (typeof MARKDOWN_VALIDATION_TARGET_KIND)[keyof typeof MARKDOWN_VALIDATION_TARGET_KIND];\n\nexport interface MarkdownSkippedValidationTarget {\n readonly path: string;\n readonly reason: string;\n}\n\nexport interface MarkdownValidationTargetResolution {\n readonly skipped?: MarkdownSkippedValidationTarget;\n readonly target?: MarkdownValidationTarget;\n}\n\nexport interface MarkdownValidationTargetDeps {\n readonly statSync: typeof statSync;\n}\n\nconst defaultMarkdownValidationTargetDeps: MarkdownValidationTargetDeps = {\n statSync,\n};\n\n// =============================================================================\n// CONFIGURATION\n// =============================================================================\n\n/**\n * Build the markdownlint configuration object.\n *\n * MD024 (no duplicate headings) is configured per directory:\n * - `spx/` and other spec directories: `siblings_only` — allows same heading\n * under different parents, flags true sibling duplicates\n * - `docs/`: disabled — generated/repetitive docs commonly reuse headings\n *\n * @param directoryName - Basename of the directory being validated (e.g. \"spx\", \"docs\")\n * @returns Configuration object for markdownlint-cli2's optionsOverride\n */\nexport function buildMarkdownlintConfig(directoryName: string): {\n default: boolean;\n MD001: boolean;\n MD003: boolean;\n MD009: boolean;\n MD010: boolean;\n MD024: boolean | { siblings_only: boolean };\n MD025: boolean;\n MD047: boolean;\n customRules: MarkdownlintRule[];\n} {\n const md024Disabled = MD024_DISABLED_DIRECTORIES.includes(\n directoryName as (typeof MD024_DISABLED_DIRECTORIES)[number],\n );\n\n return {\n default: false,\n ...ENABLED_RULES,\n MD024: md024Disabled ? false : { siblings_only: true },\n customRules: [relativeLinksRule],\n };\n}\n\n// =============================================================================\n// DEFAULT DIRECTORIES\n// =============================================================================\n\n/**\n * Get the default directories to validate.\n *\n * Returns absolute paths for spx/ and docs/ directories that exist\n * within the given project root.\n *\n * @param projectRoot - Absolute path to the project root\n * @returns Array of absolute paths to existing default directories\n */\nexport function getDefaultDirectories(projectRoot: string): string[] {\n return MARKDOWN_DEFAULT_DIRECTORY_NAMES\n .map((name) => join(projectRoot, name))\n .filter((dir) => existsSync(dir));\n}\n\nexport function classifyMarkdownValidationTarget(\n path: string,\n deps: MarkdownValidationTargetDeps = defaultMarkdownValidationTargetDeps,\n): MarkdownValidationTarget | undefined {\n return resolveMarkdownValidationTarget(path, deps).target;\n}\n\nexport function resolveMarkdownValidationTarget(\n path: string,\n deps: MarkdownValidationTargetDeps = defaultMarkdownValidationTargetDeps,\n): MarkdownValidationTargetResolution {\n if (isExistingDirectory(path, deps)) {\n return { target: { kind: MARKDOWN_VALIDATION_TARGET_KIND.DIRECTORY, path } };\n }\n if (hasMarkdownExtension(path) && isExistingFile(path, deps)) {\n return { target: { kind: MARKDOWN_VALIDATION_TARGET_KIND.FILE, path } };\n }\n return {\n skipped: {\n path,\n reason: MARKDOWN_VALIDATION_TARGET_DIAGNOSTICS.MISSING_OR_UNRELATED_SCOPE,\n },\n };\n}\n\n// =============================================================================\n// EXCLUDE SUPPORT\n// =============================================================================\n\n/**\n * Read node paths from spx/EXCLUDE and return them as ignore globs.\n *\n * Declared-state nodes have [test] links pointing to files that do not\n * exist yet. Listing them in spx/EXCLUDE tells markdown validation to\n * skip those directories so broken [test] links are not flagged.\n *\n * @param projectRoot - Absolute path to the project root\n * @returns Array of glob patterns to ignore (relative to the validated directory)\n */\nexport function getExcludeGlobs(projectRoot: string | undefined): string[] {\n if (projectRoot === undefined) return [];\n const reader = createIgnoreSourceReader(projectRoot, {\n ignoreSourceFilename: IGNORE_SOURCE_FILENAME_DEFAULT,\n specTreeRootSegment: SPEC_TREE_CONFIG.ROOT_DIRECTORY,\n });\n return reader.entries().map((entry) => `${entry.segment}/**`);\n}\n\n// =============================================================================\n// ERROR PARSING\n// =============================================================================\n\n/**\n * Pattern matching data URIs (data:image/..., data:text/..., etc.).\n * markdownlint-rule-relative-links does not handle data URIs natively\n * and reports them as broken relative links. Filter them out.\n */\nconst DATA_URI_PATTERN = /\\bdata:/;\n\n/**\n * Parse a line of markdownlint-cli2 default formatter output into a structured error.\n *\n * Filters out false positives from data URIs.\n *\n * @param line - A single line of error output\n * @returns Parsed MarkdownError, or null if the line is not a real error\n */\nfunction parseErrorLine(line: string): MarkdownError | null {\n if (DATA_URI_PATTERN.test(line)) {\n return null;\n }\n const match = ERROR_LINE_PATTERN.exec(line);\n if (!match) {\n return null;\n }\n const [, file, lineStr, detail] = match;\n return {\n file,\n line: parseInt(lineStr, 10),\n detail,\n };\n}\n\n// =============================================================================\n// VALIDATION FUNCTION\n// =============================================================================\n\n/**\n * Validate markdown files in the specified targets.\n *\n * Uses markdownlint-cli2's programmatic API with in-code configuration.\n * No config files are written to validated directories.\n *\n * @param options - Validation options including targets and project root\n * @returns Validation result with success status and structured errors\n *\n * @example\n * ```typescript\n * const result = await validateMarkdown({\n * targets: [{ kind: MARKDOWN_VALIDATION_TARGET_KIND.DIRECTORY, path: \"/path/to/spx\" }],\n * projectRoot: \"/path/to/project\",\n * });\n * if (!result.success) {\n * for (const error of result.errors) {\n * console.error(`${error.file}:${error.line} ${error.detail}`);\n * }\n * }\n * ```\n */\nexport async function validateMarkdown(\n options: ValidateMarkdownOptions,\n): Promise<MarkdownValidationResult> {\n const { targets, projectRoot } = options;\n const errors: MarkdownError[] = [];\n const excludeGlobs = getExcludeGlobs(projectRoot);\n\n for (const target of targets) {\n const directory = targetDirectory(target);\n const dirName = markdownlintConfigDirectoryName(directory, projectRoot);\n const config = buildMarkdownlintConfig(dirName);\n const dirErrors = await validateTarget(target, config, projectRoot, excludeGlobs);\n errors.push(...dirErrors);\n }\n\n return {\n success: errors.length === 0,\n errors,\n };\n}\n\n/**\n * Validate a single target using markdownlint-cli2's programmatic API.\n *\n * @param target - Absolute path target to validate\n * @param config - Markdownlint configuration object\n * @param projectRoot - Optional project root for resolving project-absolute links\n * @returns Array of structured errors found in the directory\n */\nasync function validateTarget(\n target: MarkdownValidationTarget,\n config: ReturnType<typeof buildMarkdownlintConfig>,\n projectRoot?: string,\n ignoreGlobs: string[] = [],\n): Promise<MarkdownError[]> {\n const errors: MarkdownError[] = [];\n const directory = targetDirectory(target);\n const argv = target.kind === MARKDOWN_VALIDATION_TARGET_KIND.FILE\n ? [basename(target.path)]\n : [MARKDOWN_DIRECTORY_GLOB];\n\n const { customRules, ...markdownlintConfig } = config;\n\n const optionsOverride: Record<string, unknown> = {\n config: {\n ...markdownlintConfig,\n \"relative-links\": projectRoot ? { root_path: projectRoot } : true,\n },\n customRules,\n noProgress: true,\n noBanner: true,\n ...(ignoreGlobs.length > 0 ? { ignores: ignoreGlobs } : {}),\n };\n\n await markdownlintMain({\n directory,\n argv,\n optionsOverride,\n noImport: true,\n logMessage: () => {},\n logError: (message: string) => {\n const parsed = parseErrorLine(message);\n if (parsed) {\n errors.push({\n ...parsed,\n file: join(directory, parsed.file),\n });\n }\n },\n });\n\n return errors;\n}\n\nfunction targetDirectory(target: MarkdownValidationTarget): string {\n return target.kind === MARKDOWN_VALIDATION_TARGET_KIND.FILE ? dirname(target.path) : target.path;\n}\n\nfunction hasMarkdownExtension(path: string): boolean {\n const lastDot = path.lastIndexOf(\".\");\n if (lastDot < 0) return false;\n return MARKDOWN_FILE_EXTENSIONS.has(path.slice(lastDot).toLowerCase());\n}\n\nfunction isExistingDirectory(path: string, deps: MarkdownValidationTargetDeps): boolean {\n try {\n return deps.statSync(path).isDirectory();\n } catch {\n return false;\n }\n}\n\nfunction isExistingFile(path: string, deps: MarkdownValidationTargetDeps): boolean {\n try {\n return deps.statSync(path).isFile();\n } catch {\n return false;\n }\n}\n\nfunction markdownlintConfigDirectoryName(directory: string, projectRoot: string | undefined): string {\n if (projectRoot !== undefined) {\n const [rootSegment] = pathRelative(projectRoot, directory).split(/[\\\\/]/);\n if (MD024_DISABLED_DIRECTORIES.includes(rootSegment as (typeof MD024_DISABLED_DIRECTORIES)[number])) {\n return rootSegment;\n }\n }\n return basename(directory);\n}\n","export const VALIDATION_EXIT_CODES = {\n SUCCESS: 0,\n FAILURE: 1,\n} as const;\n\nexport const VALIDATION_STAGE_DISPLAY_NAMES = {\n CIRCULAR: \"Circular dependencies\",\n KNIP: \"Knip\",\n ESLINT: \"ESLint\",\n TYPESCRIPT: \"TypeScript\",\n MARKDOWN: \"Markdown\",\n LITERAL: \"Literal\",\n} as const;\n\nexport const VALIDATION_SKIP_LABELS = {\n VERB: \"Skipping\",\n LITERAL_REASON: \"skip-literal\",\n TYPESCRIPT_ABSENT_REASON: \"TypeScript not detected in project\",\n VALIDATION_PATHS_NO_TARGETS_REASON: \"validation paths matched no files\",\n MARKDOWN_NO_SCOPE_REASON: \"no markdown files in --files scope\",\n MARKDOWN_NO_DEFAULT_DIRECTORIES_REASON: \"no spx/ or docs/ directories found\",\n} as const;\n\nexport const VALIDATION_COMMAND_OUTPUT = {\n CIRCULAR_FOUND: `${VALIDATION_STAGE_DISPLAY_NAMES.CIRCULAR} found`,\n CIRCULAR_NONE_FOUND: `${VALIDATION_STAGE_DISPLAY_NAMES.CIRCULAR}: ✓ None found`,\n KNIP_CONFIG_ERROR: `${VALIDATION_STAGE_DISPLAY_NAMES.KNIP}: ✗ config error`,\n KNIP_DISABLED: `${VALIDATION_STAGE_DISPLAY_NAMES.KNIP}: skipped (disabled by validation.knip.enabled)`,\n KNIP_SUCCESS: `${VALIDATION_STAGE_DISPLAY_NAMES.KNIP}: ✓ No unused code found`,\n KNIP_FAILURE: \"Unused code found\",\n ESLINT_SUCCESS: `${VALIDATION_STAGE_DISPLAY_NAMES.ESLINT}: ✓ No errors found`,\n ESLINT_FAILURE: `${VALIDATION_STAGE_DISPLAY_NAMES.ESLINT} validation failed`,\n ESLINT_MISSING_CONFIG: \"ESLint config not found: project has tsconfig.json but no eslint.config.{ts,js,mjs,cjs}\",\n TYPESCRIPT_SUCCESS: `${VALIDATION_STAGE_DISPLAY_NAMES.TYPESCRIPT}: ✓ No type errors`,\n TYPESCRIPT_FAILURE: `${VALIDATION_STAGE_DISPLAY_NAMES.TYPESCRIPT} validation failed`,\n MARKDOWN_NO_ISSUES: `${VALIDATION_STAGE_DISPLAY_NAMES.MARKDOWN}: No issues found`,\n MARKDOWN_ERROR_SUMMARY_SUFFIX: \"error(s) found\",\n} as const;\n\nexport const LITERAL_SKIP_OUTPUT =\n `${VALIDATION_STAGE_DISPLAY_NAMES.LITERAL}: skipped (--${VALIDATION_SKIP_LABELS.LITERAL_REASON})`;\n\nexport const LITERAL_SKIP_JSON_OUTPUT = JSON.stringify({\n skipped: true,\n reason: VALIDATION_SKIP_LABELS.LITERAL_REASON,\n});\n\n// Matches a pipeline step line `[N/M]`; the step count derives from the registry,\n// so the denominator is matched generically rather than pinned to a constant.\nexport const VALIDATION_STEP_LINE_PATTERN = /^\\[(\\d+)\\/(\\d+)\\]/gm;\nexport const VALIDATION_STEP_DURATION_PATTERN = /\\((\\d+(?:\\.\\d+)?)(ms|s)\\)\\s*$/;\n\nexport function formatTypeScriptAbsentSkipMessage(stageName: string): string {\n return `⏭ ${VALIDATION_SKIP_LABELS.VERB} ${stageName} (${VALIDATION_SKIP_LABELS.TYPESCRIPT_ABSENT_REASON})`;\n}\n\nexport function formatValidationPathsNoTargetsSkipMessage(stageName: string): string {\n return `⏭ ${VALIDATION_SKIP_LABELS.VERB} ${stageName} (${VALIDATION_SKIP_LABELS.VALIDATION_PATHS_NO_TARGETS_REASON})`;\n}\n","/**\n * Markdown validation language descriptor.\n *\n * Declares the single markdown-quality stage. Splitting markdown into its own\n * descriptor keeps it independent of the TypeScript language so future\n * descriptors compose without inheriting markdown validation.\n */\nimport { markdownCommand } from \"@/commands/validation/markdown\";\nimport { VALIDATION_STAGE_DISPLAY_NAMES } from \"@/commands/validation/messages\";\nimport type { ValidationLanguageDescriptor } from \"@/validation/languages/types\";\n\nconst MARKDOWN_LANGUAGE_NAME = \"markdown\";\n\nexport const markdownValidationLanguage: ValidationLanguageDescriptor = {\n name: MARKDOWN_LANGUAGE_NAME,\n stages: [\n {\n name: VALIDATION_STAGE_DISPLAY_NAMES.MARKDOWN,\n failsPipeline: true,\n run: (context) => markdownCommand({ cwd: context.cwd, files: context.files, quiet: context.quiet }),\n },\n ],\n};\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n'use strict';\n/**\n * Creates a JSON scanner on the given text.\n * If ignoreTrivia is set, whitespaces or comments are ignored.\n */\nexport function createScanner(text, ignoreTrivia = false) {\n const len = text.length;\n let pos = 0, value = '', tokenOffset = 0, token = 16 /* SyntaxKind.Unknown */, lineNumber = 0, lineStartOffset = 0, tokenLineStartOffset = 0, prevTokenLineStartOffset = 0, scanError = 0 /* ScanError.None */;\n function scanHexDigits(count, exact) {\n let digits = 0;\n let value = 0;\n while (digits < count || !exact) {\n let ch = text.charCodeAt(pos);\n if (ch >= 48 /* CharacterCodes._0 */ && ch <= 57 /* CharacterCodes._9 */) {\n value = value * 16 + ch - 48 /* CharacterCodes._0 */;\n }\n else if (ch >= 65 /* CharacterCodes.A */ && ch <= 70 /* CharacterCodes.F */) {\n value = value * 16 + ch - 65 /* CharacterCodes.A */ + 10;\n }\n else if (ch >= 97 /* CharacterCodes.a */ && ch <= 102 /* CharacterCodes.f */) {\n value = value * 16 + ch - 97 /* CharacterCodes.a */ + 10;\n }\n else {\n break;\n }\n pos++;\n digits++;\n }\n if (digits < count) {\n value = -1;\n }\n return value;\n }\n function setPosition(newPosition) {\n pos = newPosition;\n value = '';\n tokenOffset = 0;\n token = 16 /* SyntaxKind.Unknown */;\n scanError = 0 /* ScanError.None */;\n }\n function scanNumber() {\n let start = pos;\n if (text.charCodeAt(pos) === 48 /* CharacterCodes._0 */) {\n pos++;\n }\n else {\n pos++;\n while (pos < text.length && isDigit(text.charCodeAt(pos))) {\n pos++;\n }\n }\n if (pos < text.length && text.charCodeAt(pos) === 46 /* CharacterCodes.dot */) {\n pos++;\n if (pos < text.length && isDigit(text.charCodeAt(pos))) {\n pos++;\n while (pos < text.length && isDigit(text.charCodeAt(pos))) {\n pos++;\n }\n }\n else {\n scanError = 3 /* ScanError.UnexpectedEndOfNumber */;\n return text.substring(start, pos);\n }\n }\n let end = pos;\n if (pos < text.length && (text.charCodeAt(pos) === 69 /* CharacterCodes.E */ || text.charCodeAt(pos) === 101 /* CharacterCodes.e */)) {\n pos++;\n if (pos < text.length && text.charCodeAt(pos) === 43 /* CharacterCodes.plus */ || text.charCodeAt(pos) === 45 /* CharacterCodes.minus */) {\n pos++;\n }\n if (pos < text.length && isDigit(text.charCodeAt(pos))) {\n pos++;\n while (pos < text.length && isDigit(text.charCodeAt(pos))) {\n pos++;\n }\n end = pos;\n }\n else {\n scanError = 3 /* ScanError.UnexpectedEndOfNumber */;\n }\n }\n return text.substring(start, end);\n }\n function scanString() {\n let result = '', start = pos;\n while (true) {\n if (pos >= len) {\n result += text.substring(start, pos);\n scanError = 2 /* ScanError.UnexpectedEndOfString */;\n break;\n }\n const ch = text.charCodeAt(pos);\n if (ch === 34 /* CharacterCodes.doubleQuote */) {\n result += text.substring(start, pos);\n pos++;\n break;\n }\n if (ch === 92 /* CharacterCodes.backslash */) {\n result += text.substring(start, pos);\n pos++;\n if (pos >= len) {\n scanError = 2 /* ScanError.UnexpectedEndOfString */;\n break;\n }\n const ch2 = text.charCodeAt(pos++);\n switch (ch2) {\n case 34 /* CharacterCodes.doubleQuote */:\n result += '\\\"';\n break;\n case 92 /* CharacterCodes.backslash */:\n result += '\\\\';\n break;\n case 47 /* CharacterCodes.slash */:\n result += '/';\n break;\n case 98 /* CharacterCodes.b */:\n result += '\\b';\n break;\n case 102 /* CharacterCodes.f */:\n result += '\\f';\n break;\n case 110 /* CharacterCodes.n */:\n result += '\\n';\n break;\n case 114 /* CharacterCodes.r */:\n result += '\\r';\n break;\n case 116 /* CharacterCodes.t */:\n result += '\\t';\n break;\n case 117 /* CharacterCodes.u */:\n const ch3 = scanHexDigits(4, true);\n if (ch3 >= 0) {\n result += String.fromCharCode(ch3);\n }\n else {\n scanError = 4 /* ScanError.InvalidUnicode */;\n }\n break;\n default:\n scanError = 5 /* ScanError.InvalidEscapeCharacter */;\n }\n start = pos;\n continue;\n }\n if (ch >= 0 && ch <= 0x1f) {\n if (isLineBreak(ch)) {\n result += text.substring(start, pos);\n scanError = 2 /* ScanError.UnexpectedEndOfString */;\n break;\n }\n else {\n scanError = 6 /* ScanError.InvalidCharacter */;\n // mark as error but continue with string\n }\n }\n pos++;\n }\n return result;\n }\n function scanNext() {\n value = '';\n scanError = 0 /* ScanError.None */;\n tokenOffset = pos;\n lineStartOffset = lineNumber;\n prevTokenLineStartOffset = tokenLineStartOffset;\n if (pos >= len) {\n // at the end\n tokenOffset = len;\n return token = 17 /* SyntaxKind.EOF */;\n }\n let code = text.charCodeAt(pos);\n // trivia: whitespace\n if (isWhiteSpace(code)) {\n do {\n pos++;\n value += String.fromCharCode(code);\n code = text.charCodeAt(pos);\n } while (isWhiteSpace(code));\n return token = 15 /* SyntaxKind.Trivia */;\n }\n // trivia: newlines\n if (isLineBreak(code)) {\n pos++;\n value += String.fromCharCode(code);\n if (code === 13 /* CharacterCodes.carriageReturn */ && text.charCodeAt(pos) === 10 /* CharacterCodes.lineFeed */) {\n pos++;\n value += '\\n';\n }\n lineNumber++;\n tokenLineStartOffset = pos;\n return token = 14 /* SyntaxKind.LineBreakTrivia */;\n }\n switch (code) {\n // tokens: []{}:,\n case 123 /* CharacterCodes.openBrace */:\n pos++;\n return token = 1 /* SyntaxKind.OpenBraceToken */;\n case 125 /* CharacterCodes.closeBrace */:\n pos++;\n return token = 2 /* SyntaxKind.CloseBraceToken */;\n case 91 /* CharacterCodes.openBracket */:\n pos++;\n return token = 3 /* SyntaxKind.OpenBracketToken */;\n case 93 /* CharacterCodes.closeBracket */:\n pos++;\n return token = 4 /* SyntaxKind.CloseBracketToken */;\n case 58 /* CharacterCodes.colon */:\n pos++;\n return token = 6 /* SyntaxKind.ColonToken */;\n case 44 /* CharacterCodes.comma */:\n pos++;\n return token = 5 /* SyntaxKind.CommaToken */;\n // strings\n case 34 /* CharacterCodes.doubleQuote */:\n pos++;\n value = scanString();\n return token = 10 /* SyntaxKind.StringLiteral */;\n // comments\n case 47 /* CharacterCodes.slash */:\n const start = pos - 1;\n // Single-line comment\n if (text.charCodeAt(pos + 1) === 47 /* CharacterCodes.slash */) {\n pos += 2;\n while (pos < len) {\n if (isLineBreak(text.charCodeAt(pos))) {\n break;\n }\n pos++;\n }\n value = text.substring(start, pos);\n return token = 12 /* SyntaxKind.LineCommentTrivia */;\n }\n // Multi-line comment\n if (text.charCodeAt(pos + 1) === 42 /* CharacterCodes.asterisk */) {\n pos += 2;\n const safeLength = len - 1; // For lookahead.\n let commentClosed = false;\n while (pos < safeLength) {\n const ch = text.charCodeAt(pos);\n if (ch === 42 /* CharacterCodes.asterisk */ && text.charCodeAt(pos + 1) === 47 /* CharacterCodes.slash */) {\n pos += 2;\n commentClosed = true;\n break;\n }\n pos++;\n if (isLineBreak(ch)) {\n if (ch === 13 /* CharacterCodes.carriageReturn */ && text.charCodeAt(pos) === 10 /* CharacterCodes.lineFeed */) {\n pos++;\n }\n lineNumber++;\n tokenLineStartOffset = pos;\n }\n }\n if (!commentClosed) {\n pos++;\n scanError = 1 /* ScanError.UnexpectedEndOfComment */;\n }\n value = text.substring(start, pos);\n return token = 13 /* SyntaxKind.BlockCommentTrivia */;\n }\n // just a single slash\n value += String.fromCharCode(code);\n pos++;\n return token = 16 /* SyntaxKind.Unknown */;\n // numbers\n case 45 /* CharacterCodes.minus */:\n value += String.fromCharCode(code);\n pos++;\n if (pos === len || !isDigit(text.charCodeAt(pos))) {\n return token = 16 /* SyntaxKind.Unknown */;\n }\n // found a minus, followed by a number so\n // we fall through to proceed with scanning\n // numbers\n case 48 /* CharacterCodes._0 */:\n case 49 /* CharacterCodes._1 */:\n case 50 /* CharacterCodes._2 */:\n case 51 /* CharacterCodes._3 */:\n case 52 /* CharacterCodes._4 */:\n case 53 /* CharacterCodes._5 */:\n case 54 /* CharacterCodes._6 */:\n case 55 /* CharacterCodes._7 */:\n case 56 /* CharacterCodes._8 */:\n case 57 /* CharacterCodes._9 */:\n value += scanNumber();\n return token = 11 /* SyntaxKind.NumericLiteral */;\n // literals and unknown symbols\n default:\n // is a literal? Read the full word.\n while (pos < len && isUnknownContentCharacter(code)) {\n pos++;\n code = text.charCodeAt(pos);\n }\n if (tokenOffset !== pos) {\n value = text.substring(tokenOffset, pos);\n // keywords: true, false, null\n switch (value) {\n case 'true': return token = 8 /* SyntaxKind.TrueKeyword */;\n case 'false': return token = 9 /* SyntaxKind.FalseKeyword */;\n case 'null': return token = 7 /* SyntaxKind.NullKeyword */;\n }\n return token = 16 /* SyntaxKind.Unknown */;\n }\n // some\n value += String.fromCharCode(code);\n pos++;\n return token = 16 /* SyntaxKind.Unknown */;\n }\n }\n function isUnknownContentCharacter(code) {\n if (isWhiteSpace(code) || isLineBreak(code)) {\n return false;\n }\n switch (code) {\n case 125 /* CharacterCodes.closeBrace */:\n case 93 /* CharacterCodes.closeBracket */:\n case 123 /* CharacterCodes.openBrace */:\n case 91 /* CharacterCodes.openBracket */:\n case 34 /* CharacterCodes.doubleQuote */:\n case 58 /* CharacterCodes.colon */:\n case 44 /* CharacterCodes.comma */:\n case 47 /* CharacterCodes.slash */:\n return false;\n }\n return true;\n }\n function scanNextNonTrivia() {\n let result;\n do {\n result = scanNext();\n } while (result >= 12 /* SyntaxKind.LineCommentTrivia */ && result <= 15 /* SyntaxKind.Trivia */);\n return result;\n }\n return {\n setPosition: setPosition,\n getPosition: () => pos,\n scan: ignoreTrivia ? scanNextNonTrivia : scanNext,\n getToken: () => token,\n getTokenValue: () => value,\n getTokenOffset: () => tokenOffset,\n getTokenLength: () => pos - tokenOffset,\n getTokenStartLine: () => lineStartOffset,\n getTokenStartCharacter: () => tokenOffset - prevTokenLineStartOffset,\n getTokenError: () => scanError,\n };\n}\nfunction isWhiteSpace(ch) {\n return ch === 32 /* CharacterCodes.space */ || ch === 9 /* CharacterCodes.tab */;\n}\nfunction isLineBreak(ch) {\n return ch === 10 /* CharacterCodes.lineFeed */ || ch === 13 /* CharacterCodes.carriageReturn */;\n}\nfunction isDigit(ch) {\n return ch >= 48 /* CharacterCodes._0 */ && ch <= 57 /* CharacterCodes._9 */;\n}\nvar CharacterCodes;\n(function (CharacterCodes) {\n CharacterCodes[CharacterCodes[\"lineFeed\"] = 10] = \"lineFeed\";\n CharacterCodes[CharacterCodes[\"carriageReturn\"] = 13] = \"carriageReturn\";\n CharacterCodes[CharacterCodes[\"space\"] = 32] = \"space\";\n CharacterCodes[CharacterCodes[\"_0\"] = 48] = \"_0\";\n CharacterCodes[CharacterCodes[\"_1\"] = 49] = \"_1\";\n CharacterCodes[CharacterCodes[\"_2\"] = 50] = \"_2\";\n CharacterCodes[CharacterCodes[\"_3\"] = 51] = \"_3\";\n CharacterCodes[CharacterCodes[\"_4\"] = 52] = \"_4\";\n CharacterCodes[CharacterCodes[\"_5\"] = 53] = \"_5\";\n CharacterCodes[CharacterCodes[\"_6\"] = 54] = \"_6\";\n CharacterCodes[CharacterCodes[\"_7\"] = 55] = \"_7\";\n CharacterCodes[CharacterCodes[\"_8\"] = 56] = \"_8\";\n CharacterCodes[CharacterCodes[\"_9\"] = 57] = \"_9\";\n CharacterCodes[CharacterCodes[\"a\"] = 97] = \"a\";\n CharacterCodes[CharacterCodes[\"b\"] = 98] = \"b\";\n CharacterCodes[CharacterCodes[\"c\"] = 99] = \"c\";\n CharacterCodes[CharacterCodes[\"d\"] = 100] = \"d\";\n CharacterCodes[CharacterCodes[\"e\"] = 101] = \"e\";\n CharacterCodes[CharacterCodes[\"f\"] = 102] = \"f\";\n CharacterCodes[CharacterCodes[\"g\"] = 103] = \"g\";\n CharacterCodes[CharacterCodes[\"h\"] = 104] = \"h\";\n CharacterCodes[CharacterCodes[\"i\"] = 105] = \"i\";\n CharacterCodes[CharacterCodes[\"j\"] = 106] = \"j\";\n CharacterCodes[CharacterCodes[\"k\"] = 107] = \"k\";\n CharacterCodes[CharacterCodes[\"l\"] = 108] = \"l\";\n CharacterCodes[CharacterCodes[\"m\"] = 109] = \"m\";\n CharacterCodes[CharacterCodes[\"n\"] = 110] = \"n\";\n CharacterCodes[CharacterCodes[\"o\"] = 111] = \"o\";\n CharacterCodes[CharacterCodes[\"p\"] = 112] = \"p\";\n CharacterCodes[CharacterCodes[\"q\"] = 113] = \"q\";\n CharacterCodes[CharacterCodes[\"r\"] = 114] = \"r\";\n CharacterCodes[CharacterCodes[\"s\"] = 115] = \"s\";\n CharacterCodes[CharacterCodes[\"t\"] = 116] = \"t\";\n CharacterCodes[CharacterCodes[\"u\"] = 117] = \"u\";\n CharacterCodes[CharacterCodes[\"v\"] = 118] = \"v\";\n CharacterCodes[CharacterCodes[\"w\"] = 119] = \"w\";\n CharacterCodes[CharacterCodes[\"x\"] = 120] = \"x\";\n CharacterCodes[CharacterCodes[\"y\"] = 121] = \"y\";\n CharacterCodes[CharacterCodes[\"z\"] = 122] = \"z\";\n CharacterCodes[CharacterCodes[\"A\"] = 65] = \"A\";\n CharacterCodes[CharacterCodes[\"B\"] = 66] = \"B\";\n CharacterCodes[CharacterCodes[\"C\"] = 67] = \"C\";\n CharacterCodes[CharacterCodes[\"D\"] = 68] = \"D\";\n CharacterCodes[CharacterCodes[\"E\"] = 69] = \"E\";\n CharacterCodes[CharacterCodes[\"F\"] = 70] = \"F\";\n CharacterCodes[CharacterCodes[\"G\"] = 71] = \"G\";\n CharacterCodes[CharacterCodes[\"H\"] = 72] = \"H\";\n CharacterCodes[CharacterCodes[\"I\"] = 73] = \"I\";\n CharacterCodes[CharacterCodes[\"J\"] = 74] = \"J\";\n CharacterCodes[CharacterCodes[\"K\"] = 75] = \"K\";\n CharacterCodes[CharacterCodes[\"L\"] = 76] = \"L\";\n CharacterCodes[CharacterCodes[\"M\"] = 77] = \"M\";\n CharacterCodes[CharacterCodes[\"N\"] = 78] = \"N\";\n CharacterCodes[CharacterCodes[\"O\"] = 79] = \"O\";\n CharacterCodes[CharacterCodes[\"P\"] = 80] = \"P\";\n CharacterCodes[CharacterCodes[\"Q\"] = 81] = \"Q\";\n CharacterCodes[CharacterCodes[\"R\"] = 82] = \"R\";\n CharacterCodes[CharacterCodes[\"S\"] = 83] = \"S\";\n CharacterCodes[CharacterCodes[\"T\"] = 84] = \"T\";\n CharacterCodes[CharacterCodes[\"U\"] = 85] = \"U\";\n CharacterCodes[CharacterCodes[\"V\"] = 86] = \"V\";\n CharacterCodes[CharacterCodes[\"W\"] = 87] = \"W\";\n CharacterCodes[CharacterCodes[\"X\"] = 88] = \"X\";\n CharacterCodes[CharacterCodes[\"Y\"] = 89] = \"Y\";\n CharacterCodes[CharacterCodes[\"Z\"] = 90] = \"Z\";\n CharacterCodes[CharacterCodes[\"asterisk\"] = 42] = \"asterisk\";\n CharacterCodes[CharacterCodes[\"backslash\"] = 92] = \"backslash\";\n CharacterCodes[CharacterCodes[\"closeBrace\"] = 125] = \"closeBrace\";\n CharacterCodes[CharacterCodes[\"closeBracket\"] = 93] = \"closeBracket\";\n CharacterCodes[CharacterCodes[\"colon\"] = 58] = \"colon\";\n CharacterCodes[CharacterCodes[\"comma\"] = 44] = \"comma\";\n CharacterCodes[CharacterCodes[\"dot\"] = 46] = \"dot\";\n CharacterCodes[CharacterCodes[\"doubleQuote\"] = 34] = \"doubleQuote\";\n CharacterCodes[CharacterCodes[\"minus\"] = 45] = \"minus\";\n CharacterCodes[CharacterCodes[\"openBrace\"] = 123] = \"openBrace\";\n CharacterCodes[CharacterCodes[\"openBracket\"] = 91] = \"openBracket\";\n CharacterCodes[CharacterCodes[\"plus\"] = 43] = \"plus\";\n CharacterCodes[CharacterCodes[\"slash\"] = 47] = \"slash\";\n CharacterCodes[CharacterCodes[\"formFeed\"] = 12] = \"formFeed\";\n CharacterCodes[CharacterCodes[\"tab\"] = 9] = \"tab\";\n})(CharacterCodes || (CharacterCodes = {}));\n","export const cachedSpaces = new Array(20).fill(0).map((_, index) => {\n return ' '.repeat(index);\n});\nconst maxCachedValues = 200;\nexport const cachedBreakLinesWithSpaces = {\n ' ': {\n '\\n': new Array(maxCachedValues).fill(0).map((_, index) => {\n return '\\n' + ' '.repeat(index);\n }),\n '\\r': new Array(maxCachedValues).fill(0).map((_, index) => {\n return '\\r' + ' '.repeat(index);\n }),\n '\\r\\n': new Array(maxCachedValues).fill(0).map((_, index) => {\n return '\\r\\n' + ' '.repeat(index);\n }),\n },\n '\\t': {\n '\\n': new Array(maxCachedValues).fill(0).map((_, index) => {\n return '\\n' + '\\t'.repeat(index);\n }),\n '\\r': new Array(maxCachedValues).fill(0).map((_, index) => {\n return '\\r' + '\\t'.repeat(index);\n }),\n '\\r\\n': new Array(maxCachedValues).fill(0).map((_, index) => {\n return '\\r\\n' + '\\t'.repeat(index);\n }),\n }\n};\nexport const supportedEols = ['\\n', '\\r', '\\r\\n'];\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n'use strict';\nimport { createScanner } from './scanner';\nvar ParseOptions;\n(function (ParseOptions) {\n ParseOptions.DEFAULT = {\n allowTrailingComma: false\n };\n})(ParseOptions || (ParseOptions = {}));\n/**\n * For a given offset, evaluate the location in the JSON document. Each segment in the location path is either a property name or an array index.\n */\nexport function getLocation(text, position) {\n const segments = []; // strings or numbers\n const earlyReturnException = new Object();\n let previousNode = undefined;\n const previousNodeInst = {\n value: {},\n offset: 0,\n length: 0,\n type: 'object',\n parent: undefined\n };\n let isAtPropertyKey = false;\n function setPreviousNode(value, offset, length, type) {\n previousNodeInst.value = value;\n previousNodeInst.offset = offset;\n previousNodeInst.length = length;\n previousNodeInst.type = type;\n previousNodeInst.colonOffset = undefined;\n previousNode = previousNodeInst;\n }\n try {\n visit(text, {\n onObjectBegin: (offset, length) => {\n if (position <= offset) {\n throw earlyReturnException;\n }\n previousNode = undefined;\n isAtPropertyKey = position > offset;\n segments.push(''); // push a placeholder (will be replaced)\n },\n onObjectProperty: (name, offset, length) => {\n if (position < offset) {\n throw earlyReturnException;\n }\n setPreviousNode(name, offset, length, 'property');\n segments[segments.length - 1] = name;\n if (position <= offset + length) {\n throw earlyReturnException;\n }\n },\n onObjectEnd: (offset, length) => {\n if (position <= offset) {\n throw earlyReturnException;\n }\n previousNode = undefined;\n segments.pop();\n },\n onArrayBegin: (offset, length) => {\n if (position <= offset) {\n throw earlyReturnException;\n }\n previousNode = undefined;\n segments.push(0);\n },\n onArrayEnd: (offset, length) => {\n if (position <= offset) {\n throw earlyReturnException;\n }\n previousNode = undefined;\n segments.pop();\n },\n onLiteralValue: (value, offset, length) => {\n if (position < offset) {\n throw earlyReturnException;\n }\n setPreviousNode(value, offset, length, getNodeType(value));\n if (position <= offset + length) {\n throw earlyReturnException;\n }\n },\n onSeparator: (sep, offset, length) => {\n if (position <= offset) {\n throw earlyReturnException;\n }\n if (sep === ':' && previousNode && previousNode.type === 'property') {\n previousNode.colonOffset = offset;\n isAtPropertyKey = false;\n previousNode = undefined;\n }\n else if (sep === ',') {\n const last = segments[segments.length - 1];\n if (typeof last === 'number') {\n segments[segments.length - 1] = last + 1;\n }\n else {\n isAtPropertyKey = true;\n segments[segments.length - 1] = '';\n }\n previousNode = undefined;\n }\n }\n });\n }\n catch (e) {\n if (e !== earlyReturnException) {\n throw e;\n }\n }\n return {\n path: segments,\n previousNode,\n isAtPropertyKey,\n matches: (pattern) => {\n let k = 0;\n for (let i = 0; k < pattern.length && i < segments.length; i++) {\n if (pattern[k] === segments[i] || pattern[k] === '*') {\n k++;\n }\n else if (pattern[k] !== '**') {\n return false;\n }\n }\n return k === pattern.length;\n }\n };\n}\n/**\n * Parses the given text and returns the object the JSON content represents. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result.\n * Therefore always check the errors list to find out if the input was valid.\n */\nexport function parse(text, errors = [], options = ParseOptions.DEFAULT) {\n let currentProperty = null;\n let currentParent = [];\n const previousParents = [];\n function onValue(value) {\n if (Array.isArray(currentParent)) {\n currentParent.push(value);\n }\n else if (currentProperty !== null) {\n currentParent[currentProperty] = value;\n }\n }\n const visitor = {\n onObjectBegin: () => {\n const object = {};\n onValue(object);\n previousParents.push(currentParent);\n currentParent = object;\n currentProperty = null;\n },\n onObjectProperty: (name) => {\n currentProperty = name;\n },\n onObjectEnd: () => {\n currentParent = previousParents.pop();\n },\n onArrayBegin: () => {\n const array = [];\n onValue(array);\n previousParents.push(currentParent);\n currentParent = array;\n currentProperty = null;\n },\n onArrayEnd: () => {\n currentParent = previousParents.pop();\n },\n onLiteralValue: onValue,\n onError: (error, offset, length) => {\n errors.push({ error, offset, length });\n }\n };\n visit(text, visitor, options);\n return currentParent[0];\n}\n/**\n * Parses the given text and returns a tree representation the JSON content. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result.\n */\nexport function parseTree(text, errors = [], options = ParseOptions.DEFAULT) {\n let currentParent = { type: 'array', offset: -1, length: -1, children: [], parent: undefined }; // artificial root\n function ensurePropertyComplete(endOffset) {\n if (currentParent.type === 'property') {\n currentParent.length = endOffset - currentParent.offset;\n currentParent = currentParent.parent;\n }\n }\n function onValue(valueNode) {\n currentParent.children.push(valueNode);\n return valueNode;\n }\n const visitor = {\n onObjectBegin: (offset) => {\n currentParent = onValue({ type: 'object', offset, length: -1, parent: currentParent, children: [] });\n },\n onObjectProperty: (name, offset, length) => {\n currentParent = onValue({ type: 'property', offset, length: -1, parent: currentParent, children: [] });\n currentParent.children.push({ type: 'string', value: name, offset, length, parent: currentParent });\n },\n onObjectEnd: (offset, length) => {\n ensurePropertyComplete(offset + length); // in case of a missing value for a property: make sure property is complete\n currentParent.length = offset + length - currentParent.offset;\n currentParent = currentParent.parent;\n ensurePropertyComplete(offset + length);\n },\n onArrayBegin: (offset, length) => {\n currentParent = onValue({ type: 'array', offset, length: -1, parent: currentParent, children: [] });\n },\n onArrayEnd: (offset, length) => {\n currentParent.length = offset + length - currentParent.offset;\n currentParent = currentParent.parent;\n ensurePropertyComplete(offset + length);\n },\n onLiteralValue: (value, offset, length) => {\n onValue({ type: getNodeType(value), offset, length, parent: currentParent, value });\n ensurePropertyComplete(offset + length);\n },\n onSeparator: (sep, offset, length) => {\n if (currentParent.type === 'property') {\n if (sep === ':') {\n currentParent.colonOffset = offset;\n }\n else if (sep === ',') {\n ensurePropertyComplete(offset);\n }\n }\n },\n onError: (error, offset, length) => {\n errors.push({ error, offset, length });\n }\n };\n visit(text, visitor, options);\n const result = currentParent.children[0];\n if (result) {\n delete result.parent;\n }\n return result;\n}\n/**\n * Finds the node at the given path in a JSON DOM.\n */\nexport function findNodeAtLocation(root, path) {\n if (!root) {\n return undefined;\n }\n let node = root;\n for (let segment of path) {\n if (typeof segment === 'string') {\n if (node.type !== 'object' || !Array.isArray(node.children)) {\n return undefined;\n }\n let found = false;\n for (const propertyNode of node.children) {\n if (Array.isArray(propertyNode.children) && propertyNode.children[0].value === segment && propertyNode.children.length === 2) {\n node = propertyNode.children[1];\n found = true;\n break;\n }\n }\n if (!found) {\n return undefined;\n }\n }\n else {\n const index = segment;\n if (node.type !== 'array' || index < 0 || !Array.isArray(node.children) || index >= node.children.length) {\n return undefined;\n }\n node = node.children[index];\n }\n }\n return node;\n}\n/**\n * Gets the JSON path of the given JSON DOM node\n */\nexport function getNodePath(node) {\n if (!node.parent || !node.parent.children) {\n return [];\n }\n const path = getNodePath(node.parent);\n if (node.parent.type === 'property') {\n const key = node.parent.children[0].value;\n path.push(key);\n }\n else if (node.parent.type === 'array') {\n const index = node.parent.children.indexOf(node);\n if (index !== -1) {\n path.push(index);\n }\n }\n return path;\n}\n/**\n * Evaluates the JavaScript object of the given JSON DOM node\n */\nexport function getNodeValue(node) {\n switch (node.type) {\n case 'array':\n return node.children.map(getNodeValue);\n case 'object':\n const obj = Object.create(null);\n for (let prop of node.children) {\n const valueNode = prop.children[1];\n if (valueNode) {\n obj[prop.children[0].value] = getNodeValue(valueNode);\n }\n }\n return obj;\n case 'null':\n case 'string':\n case 'number':\n case 'boolean':\n return node.value;\n default:\n return undefined;\n }\n}\nexport function contains(node, offset, includeRightBound = false) {\n return (offset >= node.offset && offset < (node.offset + node.length)) || includeRightBound && (offset === (node.offset + node.length));\n}\n/**\n * Finds the most inner node at the given offset. If includeRightBound is set, also finds nodes that end at the given offset.\n */\nexport function findNodeAtOffset(node, offset, includeRightBound = false) {\n if (contains(node, offset, includeRightBound)) {\n const children = node.children;\n if (Array.isArray(children)) {\n for (let i = 0; i < children.length && children[i].offset <= offset; i++) {\n const item = findNodeAtOffset(children[i], offset, includeRightBound);\n if (item) {\n return item;\n }\n }\n }\n return node;\n }\n return undefined;\n}\n/**\n * Parses the given text and invokes the visitor functions for each object, array and literal reached.\n */\nexport function visit(text, visitor, options = ParseOptions.DEFAULT) {\n const _scanner = createScanner(text, false);\n // Important: Only pass copies of this to visitor functions to prevent accidental modification, and\n // to not affect visitor functions which stored a reference to a previous JSONPath\n const _jsonPath = [];\n // Depth of onXXXBegin() callbacks suppressed. onXXXEnd() decrements this if it isn't 0 already.\n // Callbacks are only called when this value is 0.\n let suppressedCallbacks = 0;\n function toNoArgVisit(visitFunction) {\n return visitFunction ? () => suppressedCallbacks === 0 && visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter()) : () => true;\n }\n function toOneArgVisit(visitFunction) {\n return visitFunction ? (arg) => suppressedCallbacks === 0 && visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter()) : () => true;\n }\n function toOneArgVisitWithPath(visitFunction) {\n return visitFunction ? (arg) => suppressedCallbacks === 0 && visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter(), () => _jsonPath.slice()) : () => true;\n }\n function toBeginVisit(visitFunction) {\n return visitFunction ?\n () => {\n if (suppressedCallbacks > 0) {\n suppressedCallbacks++;\n }\n else {\n let cbReturn = visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter(), () => _jsonPath.slice());\n if (cbReturn === false) {\n suppressedCallbacks = 1;\n }\n }\n }\n : () => true;\n }\n function toEndVisit(visitFunction) {\n return visitFunction ?\n () => {\n if (suppressedCallbacks > 0) {\n suppressedCallbacks--;\n }\n if (suppressedCallbacks === 0) {\n visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter());\n }\n }\n : () => true;\n }\n const onObjectBegin = toBeginVisit(visitor.onObjectBegin), onObjectProperty = toOneArgVisitWithPath(visitor.onObjectProperty), onObjectEnd = toEndVisit(visitor.onObjectEnd), onArrayBegin = toBeginVisit(visitor.onArrayBegin), onArrayEnd = toEndVisit(visitor.onArrayEnd), onLiteralValue = toOneArgVisitWithPath(visitor.onLiteralValue), onSeparator = toOneArgVisit(visitor.onSeparator), onComment = toNoArgVisit(visitor.onComment), onError = toOneArgVisit(visitor.onError);\n const disallowComments = options && options.disallowComments;\n const allowTrailingComma = options && options.allowTrailingComma;\n function scanNext() {\n while (true) {\n const token = _scanner.scan();\n switch (_scanner.getTokenError()) {\n case 4 /* ScanError.InvalidUnicode */:\n handleError(14 /* ParseErrorCode.InvalidUnicode */);\n break;\n case 5 /* ScanError.InvalidEscapeCharacter */:\n handleError(15 /* ParseErrorCode.InvalidEscapeCharacter */);\n break;\n case 3 /* ScanError.UnexpectedEndOfNumber */:\n handleError(13 /* ParseErrorCode.UnexpectedEndOfNumber */);\n break;\n case 1 /* ScanError.UnexpectedEndOfComment */:\n if (!disallowComments) {\n handleError(11 /* ParseErrorCode.UnexpectedEndOfComment */);\n }\n break;\n case 2 /* ScanError.UnexpectedEndOfString */:\n handleError(12 /* ParseErrorCode.UnexpectedEndOfString */);\n break;\n case 6 /* ScanError.InvalidCharacter */:\n handleError(16 /* ParseErrorCode.InvalidCharacter */);\n break;\n }\n switch (token) {\n case 12 /* SyntaxKind.LineCommentTrivia */:\n case 13 /* SyntaxKind.BlockCommentTrivia */:\n if (disallowComments) {\n handleError(10 /* ParseErrorCode.InvalidCommentToken */);\n }\n else {\n onComment();\n }\n break;\n case 16 /* SyntaxKind.Unknown */:\n handleError(1 /* ParseErrorCode.InvalidSymbol */);\n break;\n case 15 /* SyntaxKind.Trivia */:\n case 14 /* SyntaxKind.LineBreakTrivia */:\n break;\n default:\n return token;\n }\n }\n }\n function handleError(error, skipUntilAfter = [], skipUntil = []) {\n onError(error);\n if (skipUntilAfter.length + skipUntil.length > 0) {\n let token = _scanner.getToken();\n while (token !== 17 /* SyntaxKind.EOF */) {\n if (skipUntilAfter.indexOf(token) !== -1) {\n scanNext();\n break;\n }\n else if (skipUntil.indexOf(token) !== -1) {\n break;\n }\n token = scanNext();\n }\n }\n }\n function parseString(isValue) {\n const value = _scanner.getTokenValue();\n if (isValue) {\n onLiteralValue(value);\n }\n else {\n onObjectProperty(value);\n // add property name afterwards\n _jsonPath.push(value);\n }\n scanNext();\n return true;\n }\n function parseLiteral() {\n switch (_scanner.getToken()) {\n case 11 /* SyntaxKind.NumericLiteral */:\n const tokenValue = _scanner.getTokenValue();\n let value = Number(tokenValue);\n if (isNaN(value)) {\n handleError(2 /* ParseErrorCode.InvalidNumberFormat */);\n value = 0;\n }\n onLiteralValue(value);\n break;\n case 7 /* SyntaxKind.NullKeyword */:\n onLiteralValue(null);\n break;\n case 8 /* SyntaxKind.TrueKeyword */:\n onLiteralValue(true);\n break;\n case 9 /* SyntaxKind.FalseKeyword */:\n onLiteralValue(false);\n break;\n default:\n return false;\n }\n scanNext();\n return true;\n }\n function parseProperty() {\n if (_scanner.getToken() !== 10 /* SyntaxKind.StringLiteral */) {\n handleError(3 /* ParseErrorCode.PropertyNameExpected */, [], [2 /* SyntaxKind.CloseBraceToken */, 5 /* SyntaxKind.CommaToken */]);\n return false;\n }\n parseString(false);\n if (_scanner.getToken() === 6 /* SyntaxKind.ColonToken */) {\n onSeparator(':');\n scanNext(); // consume colon\n if (!parseValue()) {\n handleError(4 /* ParseErrorCode.ValueExpected */, [], [2 /* SyntaxKind.CloseBraceToken */, 5 /* SyntaxKind.CommaToken */]);\n }\n }\n else {\n handleError(5 /* ParseErrorCode.ColonExpected */, [], [2 /* SyntaxKind.CloseBraceToken */, 5 /* SyntaxKind.CommaToken */]);\n }\n _jsonPath.pop(); // remove processed property name\n return true;\n }\n function parseObject() {\n onObjectBegin();\n scanNext(); // consume open brace\n let needsComma = false;\n while (_scanner.getToken() !== 2 /* SyntaxKind.CloseBraceToken */ && _scanner.getToken() !== 17 /* SyntaxKind.EOF */) {\n if (_scanner.getToken() === 5 /* SyntaxKind.CommaToken */) {\n if (!needsComma) {\n handleError(4 /* ParseErrorCode.ValueExpected */, [], []);\n }\n onSeparator(',');\n scanNext(); // consume comma\n if (_scanner.getToken() === 2 /* SyntaxKind.CloseBraceToken */ && allowTrailingComma) {\n break;\n }\n }\n else if (needsComma) {\n handleError(6 /* ParseErrorCode.CommaExpected */, [], []);\n }\n if (!parseProperty()) {\n handleError(4 /* ParseErrorCode.ValueExpected */, [], [2 /* SyntaxKind.CloseBraceToken */, 5 /* SyntaxKind.CommaToken */]);\n }\n needsComma = true;\n }\n onObjectEnd();\n if (_scanner.getToken() !== 2 /* SyntaxKind.CloseBraceToken */) {\n handleError(7 /* ParseErrorCode.CloseBraceExpected */, [2 /* SyntaxKind.CloseBraceToken */], []);\n }\n else {\n scanNext(); // consume close brace\n }\n return true;\n }\n function parseArray() {\n onArrayBegin();\n scanNext(); // consume open bracket\n let isFirstElement = true;\n let needsComma = false;\n while (_scanner.getToken() !== 4 /* SyntaxKind.CloseBracketToken */ && _scanner.getToken() !== 17 /* SyntaxKind.EOF */) {\n if (_scanner.getToken() === 5 /* SyntaxKind.CommaToken */) {\n if (!needsComma) {\n handleError(4 /* ParseErrorCode.ValueExpected */, [], []);\n }\n onSeparator(',');\n scanNext(); // consume comma\n if (_scanner.getToken() === 4 /* SyntaxKind.CloseBracketToken */ && allowTrailingComma) {\n break;\n }\n }\n else if (needsComma) {\n handleError(6 /* ParseErrorCode.CommaExpected */, [], []);\n }\n if (isFirstElement) {\n _jsonPath.push(0);\n isFirstElement = false;\n }\n else {\n _jsonPath[_jsonPath.length - 1]++;\n }\n if (!parseValue()) {\n handleError(4 /* ParseErrorCode.ValueExpected */, [], [4 /* SyntaxKind.CloseBracketToken */, 5 /* SyntaxKind.CommaToken */]);\n }\n needsComma = true;\n }\n onArrayEnd();\n if (!isFirstElement) {\n _jsonPath.pop(); // remove array index\n }\n if (_scanner.getToken() !== 4 /* SyntaxKind.CloseBracketToken */) {\n handleError(8 /* ParseErrorCode.CloseBracketExpected */, [4 /* SyntaxKind.CloseBracketToken */], []);\n }\n else {\n scanNext(); // consume close bracket\n }\n return true;\n }\n function parseValue() {\n switch (_scanner.getToken()) {\n case 3 /* SyntaxKind.OpenBracketToken */:\n return parseArray();\n case 1 /* SyntaxKind.OpenBraceToken */:\n return parseObject();\n case 10 /* SyntaxKind.StringLiteral */:\n return parseString(true);\n default:\n return parseLiteral();\n }\n }\n scanNext();\n if (_scanner.getToken() === 17 /* SyntaxKind.EOF */) {\n if (options.allowEmptyContent) {\n return true;\n }\n handleError(4 /* ParseErrorCode.ValueExpected */, [], []);\n return false;\n }\n if (!parseValue()) {\n handleError(4 /* ParseErrorCode.ValueExpected */, [], []);\n return false;\n }\n if (_scanner.getToken() !== 17 /* SyntaxKind.EOF */) {\n handleError(9 /* ParseErrorCode.EndOfFileExpected */, [], []);\n }\n return true;\n}\n/**\n * Takes JSON with JavaScript-style comments and remove\n * them. Optionally replaces every none-newline character\n * of comments with a replaceCharacter\n */\nexport function stripComments(text, replaceCh) {\n let _scanner = createScanner(text), parts = [], kind, offset = 0, pos;\n do {\n pos = _scanner.getPosition();\n kind = _scanner.scan();\n switch (kind) {\n case 12 /* SyntaxKind.LineCommentTrivia */:\n case 13 /* SyntaxKind.BlockCommentTrivia */:\n case 17 /* SyntaxKind.EOF */:\n if (offset !== pos) {\n parts.push(text.substring(offset, pos));\n }\n if (replaceCh !== undefined) {\n parts.push(_scanner.getTokenValue().replace(/[^\\r\\n]/g, replaceCh));\n }\n offset = _scanner.getPosition();\n break;\n }\n } while (kind !== 17 /* SyntaxKind.EOF */);\n return parts.join('');\n}\nexport function getNodeType(value) {\n switch (typeof value) {\n case 'boolean': return 'boolean';\n case 'number': return 'number';\n case 'string': return 'string';\n case 'object': {\n if (!value) {\n return 'null';\n }\n else if (Array.isArray(value)) {\n return 'array';\n }\n return 'object';\n }\n default: return 'null';\n }\n}\n","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n'use strict';\nimport * as formatter from './impl/format';\nimport * as edit from './impl/edit';\nimport * as scanner from './impl/scanner';\nimport * as parser from './impl/parser';\n/**\n * Creates a JSON scanner on the given text.\n * If ignoreTrivia is set, whitespaces or comments are ignored.\n */\nexport const createScanner = scanner.createScanner;\nexport var ScanError;\n(function (ScanError) {\n ScanError[ScanError[\"None\"] = 0] = \"None\";\n ScanError[ScanError[\"UnexpectedEndOfComment\"] = 1] = \"UnexpectedEndOfComment\";\n ScanError[ScanError[\"UnexpectedEndOfString\"] = 2] = \"UnexpectedEndOfString\";\n ScanError[ScanError[\"UnexpectedEndOfNumber\"] = 3] = \"UnexpectedEndOfNumber\";\n ScanError[ScanError[\"InvalidUnicode\"] = 4] = \"InvalidUnicode\";\n ScanError[ScanError[\"InvalidEscapeCharacter\"] = 5] = \"InvalidEscapeCharacter\";\n ScanError[ScanError[\"InvalidCharacter\"] = 6] = \"InvalidCharacter\";\n})(ScanError || (ScanError = {}));\nexport var SyntaxKind;\n(function (SyntaxKind) {\n SyntaxKind[SyntaxKind[\"OpenBraceToken\"] = 1] = \"OpenBraceToken\";\n SyntaxKind[SyntaxKind[\"CloseBraceToken\"] = 2] = \"CloseBraceToken\";\n SyntaxKind[SyntaxKind[\"OpenBracketToken\"] = 3] = \"OpenBracketToken\";\n SyntaxKind[SyntaxKind[\"CloseBracketToken\"] = 4] = \"CloseBracketToken\";\n SyntaxKind[SyntaxKind[\"CommaToken\"] = 5] = \"CommaToken\";\n SyntaxKind[SyntaxKind[\"ColonToken\"] = 6] = \"ColonToken\";\n SyntaxKind[SyntaxKind[\"NullKeyword\"] = 7] = \"NullKeyword\";\n SyntaxKind[SyntaxKind[\"TrueKeyword\"] = 8] = \"TrueKeyword\";\n SyntaxKind[SyntaxKind[\"FalseKeyword\"] = 9] = \"FalseKeyword\";\n SyntaxKind[SyntaxKind[\"StringLiteral\"] = 10] = \"StringLiteral\";\n SyntaxKind[SyntaxKind[\"NumericLiteral\"] = 11] = \"NumericLiteral\";\n SyntaxKind[SyntaxKind[\"LineCommentTrivia\"] = 12] = \"LineCommentTrivia\";\n SyntaxKind[SyntaxKind[\"BlockCommentTrivia\"] = 13] = \"BlockCommentTrivia\";\n SyntaxKind[SyntaxKind[\"LineBreakTrivia\"] = 14] = \"LineBreakTrivia\";\n SyntaxKind[SyntaxKind[\"Trivia\"] = 15] = \"Trivia\";\n SyntaxKind[SyntaxKind[\"Unknown\"] = 16] = \"Unknown\";\n SyntaxKind[SyntaxKind[\"EOF\"] = 17] = \"EOF\";\n})(SyntaxKind || (SyntaxKind = {}));\n/**\n * For a given offset, evaluate the location in the JSON document. Each segment in the location path is either a property name or an array index.\n */\nexport const getLocation = parser.getLocation;\n/**\n * Parses the given text and returns the object the JSON content represents. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result.\n * Therefore, always check the errors list to find out if the input was valid.\n */\nexport const parse = parser.parse;\n/**\n * Parses the given text and returns a tree representation the JSON content. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result.\n */\nexport const parseTree = parser.parseTree;\n/**\n * Finds the node at the given path in a JSON DOM.\n */\nexport const findNodeAtLocation = parser.findNodeAtLocation;\n/**\n * Finds the innermost node at the given offset. If includeRightBound is set, also finds nodes that end at the given offset.\n */\nexport const findNodeAtOffset = parser.findNodeAtOffset;\n/**\n * Gets the JSON path of the given JSON DOM node\n */\nexport const getNodePath = parser.getNodePath;\n/**\n * Evaluates the JavaScript object of the given JSON DOM node\n */\nexport const getNodeValue = parser.getNodeValue;\n/**\n * Parses the given text and invokes the visitor functions for each object, array and literal reached.\n */\nexport const visit = parser.visit;\n/**\n * Takes JSON with JavaScript-style comments and remove\n * them. Optionally replaces every none-newline character\n * of comments with a replaceCharacter\n */\nexport const stripComments = parser.stripComments;\nexport var ParseErrorCode;\n(function (ParseErrorCode) {\n ParseErrorCode[ParseErrorCode[\"InvalidSymbol\"] = 1] = \"InvalidSymbol\";\n ParseErrorCode[ParseErrorCode[\"InvalidNumberFormat\"] = 2] = \"InvalidNumberFormat\";\n ParseErrorCode[ParseErrorCode[\"PropertyNameExpected\"] = 3] = \"PropertyNameExpected\";\n ParseErrorCode[ParseErrorCode[\"ValueExpected\"] = 4] = \"ValueExpected\";\n ParseErrorCode[ParseErrorCode[\"ColonExpected\"] = 5] = \"ColonExpected\";\n ParseErrorCode[ParseErrorCode[\"CommaExpected\"] = 6] = \"CommaExpected\";\n ParseErrorCode[ParseErrorCode[\"CloseBraceExpected\"] = 7] = \"CloseBraceExpected\";\n ParseErrorCode[ParseErrorCode[\"CloseBracketExpected\"] = 8] = \"CloseBracketExpected\";\n ParseErrorCode[ParseErrorCode[\"EndOfFileExpected\"] = 9] = \"EndOfFileExpected\";\n ParseErrorCode[ParseErrorCode[\"InvalidCommentToken\"] = 10] = \"InvalidCommentToken\";\n ParseErrorCode[ParseErrorCode[\"UnexpectedEndOfComment\"] = 11] = \"UnexpectedEndOfComment\";\n ParseErrorCode[ParseErrorCode[\"UnexpectedEndOfString\"] = 12] = \"UnexpectedEndOfString\";\n ParseErrorCode[ParseErrorCode[\"UnexpectedEndOfNumber\"] = 13] = \"UnexpectedEndOfNumber\";\n ParseErrorCode[ParseErrorCode[\"InvalidUnicode\"] = 14] = \"InvalidUnicode\";\n ParseErrorCode[ParseErrorCode[\"InvalidEscapeCharacter\"] = 15] = \"InvalidEscapeCharacter\";\n ParseErrorCode[ParseErrorCode[\"InvalidCharacter\"] = 16] = \"InvalidCharacter\";\n})(ParseErrorCode || (ParseErrorCode = {}));\nexport function printParseErrorCode(code) {\n switch (code) {\n case 1 /* ParseErrorCode.InvalidSymbol */: return 'InvalidSymbol';\n case 2 /* ParseErrorCode.InvalidNumberFormat */: return 'InvalidNumberFormat';\n case 3 /* ParseErrorCode.PropertyNameExpected */: return 'PropertyNameExpected';\n case 4 /* ParseErrorCode.ValueExpected */: return 'ValueExpected';\n case 5 /* ParseErrorCode.ColonExpected */: return 'ColonExpected';\n case 6 /* ParseErrorCode.CommaExpected */: return 'CommaExpected';\n case 7 /* ParseErrorCode.CloseBraceExpected */: return 'CloseBraceExpected';\n case 8 /* ParseErrorCode.CloseBracketExpected */: return 'CloseBracketExpected';\n case 9 /* ParseErrorCode.EndOfFileExpected */: return 'EndOfFileExpected';\n case 10 /* ParseErrorCode.InvalidCommentToken */: return 'InvalidCommentToken';\n case 11 /* ParseErrorCode.UnexpectedEndOfComment */: return 'UnexpectedEndOfComment';\n case 12 /* ParseErrorCode.UnexpectedEndOfString */: return 'UnexpectedEndOfString';\n case 13 /* ParseErrorCode.UnexpectedEndOfNumber */: return 'UnexpectedEndOfNumber';\n case 14 /* ParseErrorCode.InvalidUnicode */: return 'InvalidUnicode';\n case 15 /* ParseErrorCode.InvalidEscapeCharacter */: return 'InvalidEscapeCharacter';\n case 16 /* ParseErrorCode.InvalidCharacter */: return 'InvalidCharacter';\n }\n return '<unknown ParseErrorCode>';\n}\n/**\n * Computes the edit operations needed to format a JSON document.\n *\n * @param documentText The input text\n * @param range The range to format or `undefined` to format the full content\n * @param options The formatting options\n * @returns The edit operations describing the formatting changes to the original document following the format described in {@linkcode EditResult}.\n * To apply the edit operations to the input, use {@linkcode applyEdits}.\n */\nexport function format(documentText, range, options) {\n return formatter.format(documentText, range, options);\n}\n/**\n * Computes the edit operations needed to modify a value in the JSON document.\n *\n * @param documentText The input text\n * @param path The path of the value to change. The path represents either to the document root, a property or an array item.\n * If the path points to an non-existing property or item, it will be created.\n * @param value The new value for the specified property or item. If the value is undefined,\n * the property or item will be removed.\n * @param options Options\n * @returns The edit operations describing the changes to the original document, following the format described in {@linkcode EditResult}.\n * To apply the edit operations to the input, use {@linkcode applyEdits}.\n */\nexport function modify(text, path, value, options) {\n return edit.setProperty(text, path, value, options);\n}\n/**\n * Applies edits to an input string.\n * @param text The input text\n * @param edits Edit operations following the format described in {@linkcode EditResult}.\n * @returns The text with the applied edits.\n * @throws An error if the edit operations are not well-formed as described in {@linkcode EditResult}.\n */\nexport function applyEdits(text, edits) {\n let sortedEdits = edits.slice(0).sort((a, b) => {\n const diff = a.offset - b.offset;\n if (diff === 0) {\n return a.length - b.length;\n }\n return diff;\n });\n let lastModifiedOffset = text.length;\n for (let i = sortedEdits.length - 1; i >= 0; i--) {\n let e = sortedEdits[i];\n if (e.offset + e.length <= lastModifiedOffset) {\n text = edit.applyEdit(text, e);\n }\n else {\n throw new Error('Overlapping edit');\n }\n lastModifiedOffset = e.offset;\n }\n return text;\n}\n","/**\n * TypeScript scope resolution for validation.\n *\n * Provides functions to determine which directories should be validated\n * based on tsconfig.json settings, ensuring alignment between TypeScript\n * and ESLint validation.\n *\n * @module validation/config/scope\n */\n\nimport * as JSONC from \"jsonc-parser\";\nimport { existsSync, readdirSync, readFileSync } from \"node:fs\";\nimport { isAbsolute, join } from \"node:path\";\n\nimport type { ScopeConfig, ValidationScope } from \"../types\";\nimport { pathPassesValidationFilter } from \"./path-filter\";\n\n// =============================================================================\n// CONSTANTS\n// =============================================================================\n\n/**\n * TSConfig file paths for each validation scope.\n */\nexport const TSCONFIG_FILES = {\n full: \"tsconfig.json\",\n production: \"tsconfig.production.json\",\n} as const;\nconst PATH_SEGMENT_SEPARATOR = \"/\";\nconst GLOB_MARKER = \"*\";\nconst HIDDEN_PATH_PREFIX = \".\";\n\n// =============================================================================\n// DEPENDENCY INJECTION INTERFACES\n// =============================================================================\n\n/**\n * Dependencies for scope resolution.\n *\n * Enables dependency injection for testing without mocking.\n */\nexport interface ScopeDeps {\n readFileSync: typeof readFileSync;\n existsSync: typeof existsSync;\n readdirSync: typeof readdirSync;\n}\n\n/**\n * Default production dependencies.\n */\nexport const defaultScopeDeps: ScopeDeps = {\n readFileSync,\n existsSync,\n readdirSync,\n};\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\ninterface TypeScriptConfig {\n include?: string[];\n exclude?: string[];\n extends?: string | string[];\n}\n\nfunction resolveProjectPath(projectRoot: string, path: string): string {\n return isAbsolute(path) ? path : join(projectRoot, path);\n}\n\n// =============================================================================\n// INTERNAL FUNCTIONS\n// =============================================================================\n\n/**\n * Parse TypeScript configuration using proper JSONC parser.\n *\n * @param configPath - Path to tsconfig file\n * @param deps - Injectable dependencies\n * @returns Parsed TypeScript configuration\n */\nexport function parseTypeScriptConfig(\n configPath: string,\n deps: ScopeDeps = defaultScopeDeps,\n): TypeScriptConfig {\n try {\n const configContent = deps.readFileSync(configPath, \"utf-8\");\n const parsed = JSONC.parse(configContent) as TypeScriptConfig;\n return parsed;\n } catch {\n // Fallback: return minimal config and let directory detection work\n return {\n include: [\"**/*.ts\", \"**/*.tsx\"],\n exclude: [\"node_modules/**\", \".pnpm-store/**\", \"dist/**\"],\n };\n }\n}\n\n/**\n * Resolve complete TypeScript configuration including extends.\n *\n * @param scope - Validation scope\n * @param deps - Injectable dependencies\n * @returns Resolved TypeScript configuration\n */\nexport function resolveTypeScriptConfig(\n scope: ValidationScope,\n projectRoot: string,\n deps: ScopeDeps = defaultScopeDeps,\n): TypeScriptConfig {\n const configFile = TSCONFIG_FILES[scope];\n const config = parseTypeScriptConfig(resolveProjectPath(projectRoot, configFile), deps);\n\n if (config.extends) {\n const baseConfigs = normalizeExtends(config.extends)\n .map((extendedConfig) => parseTypeScriptConfig(resolveProjectPath(projectRoot, extendedConfig), deps));\n // TypeScript applies later extended configs after earlier ones; include\n // and exclude arrays replace instead of merge, so the last inherited\n // field wins.\n const inheritedInclude = [...baseConfigs].reverse().find((baseConfig) => baseConfig.include !== undefined)?.include\n ?? [];\n const inheritedExclude = [...baseConfigs].reverse().find((baseConfig) => baseConfig.exclude !== undefined)?.exclude\n ?? [];\n return {\n include: config.include ?? inheritedInclude,\n exclude: config.exclude ?? inheritedExclude,\n };\n }\n\n return {\n include: config.include ?? [],\n exclude: config.exclude ?? [],\n };\n}\n\nfunction normalizeExtends(extendsConfig: string | string[]): readonly string[] {\n return Array.isArray(extendsConfig) ? extendsConfig : [extendsConfig];\n}\n\n/**\n * Check if a directory contains TypeScript files recursively.\n *\n * @param dirPath - Directory to check\n * @param maxDepth - Maximum recursion depth\n * @param deps - Injectable dependencies\n * @returns True if directory contains TypeScript files\n */\nexport function hasTypeScriptFilesRecursive(\n dirPath: string,\n maxDepth: number = 2,\n deps: ScopeDeps = defaultScopeDeps,\n): boolean {\n if (maxDepth <= 0) return false;\n\n try {\n const items = deps.readdirSync(dirPath, { withFileTypes: true });\n\n // Check for TypeScript files in current directory\n const hasDirectTsFiles = items.some(\n (item) => item.isFile() && (item.name.endsWith(\".ts\") || item.name.endsWith(\".tsx\")),\n );\n\n if (hasDirectTsFiles) return true;\n\n // Check subdirectories (limited depth to avoid performance issues)\n const subdirs = items.filter((item) => item.isDirectory() && !item.name.startsWith(\".\"));\n for (const subdir of subdirs.slice(0, 5)) {\n // Limit to first 5 subdirs\n if (hasTypeScriptFilesRecursive(join(dirPath, subdir.name), maxDepth - 1, deps)) {\n return true;\n }\n }\n\n return false;\n } catch {\n return false;\n }\n}\n\n/**\n * Get top-level directories containing TypeScript files.\n *\n * @param config - TypeScript configuration\n * @param deps - Injectable dependencies\n * @returns Array of directory names\n */\nexport function getTopLevelDirectoriesWithTypeScript(\n config: TypeScriptConfig,\n projectRoot: string,\n deps: ScopeDeps = defaultScopeDeps,\n): string[] {\n const allTopLevelItems = deps.readdirSync(projectRoot, { withFileTypes: true });\n const directories = new Set<string>();\n\n // Find all top-level directories\n const topLevelDirs = allTopLevelItems\n .filter((item) => item.isDirectory())\n .map((item) => item.name)\n .filter((name) => !name.startsWith(\".\"));\n\n // Check if each directory should be included based on tsconfig include/exclude patterns\n for (const dir of topLevelDirs) {\n // Check if directory is explicitly excluded\n const isExcluded = config.exclude?.some((pattern) => {\n // Handle directory-recursive patterns like \"docs/**/*\"\n if (pattern.includes(\"/**\")) {\n const dirPattern = pattern.split(\"/**\")[0];\n return dirPattern === dir;\n }\n // Handle exact matches and directory patterns\n return pattern === dir || pattern.startsWith(dir + \"/\") || pattern === dir + \"/**\";\n });\n\n if (!isExcluded) {\n // Check if directory has TypeScript files\n try {\n const hasTypeScriptFiles = hasTypeScriptFilesRecursive(join(projectRoot, dir), 2, deps);\n if (hasTypeScriptFiles) {\n directories.add(dir);\n }\n } catch {\n // Directory access error, skip\n continue;\n }\n }\n }\n\n // Also add explicitly mentioned directories from include patterns\n if (config.include) {\n for (const pattern of config.include) {\n // Extract directory from patterns like \"scripts/**/*.ts\", \"tests/**/*.tsx\"\n if (pattern.includes(PATH_SEGMENT_SEPARATOR)) {\n const topLevelDir = getLiteralTopLevelPatternDirectory(pattern);\n if (topLevelDir) {\n directories.add(topLevelDir);\n }\n }\n }\n }\n\n return Array.from(directories).sort();\n}\n\nfunction getLiteralTopLevelPatternDirectory(pattern: string): string | null {\n const topLevelDir = pattern.split(PATH_SEGMENT_SEPARATOR)[0];\n if (!topLevelDir || topLevelDir.includes(GLOB_MARKER) || topLevelDir.startsWith(HIDDEN_PATH_PREFIX)) {\n return null;\n }\n return topLevelDir;\n}\n\nfunction filterActiveIncludePatterns(\n patterns: readonly string[],\n excludePatterns: readonly string[],\n projectRoot: string,\n deps: ScopeDeps,\n): string[] {\n return patterns\n .filter((pattern) => {\n const topLevelDir = getLiteralTopLevelPatternDirectory(pattern);\n return topLevelDir === null || deps.existsSync(join(projectRoot, topLevelDir));\n })\n .filter((pattern) => pathPassesValidationFilter(pattern, { exclude: excludePatterns }));\n}\n\n/**\n * Get validation directories based on tsconfig files.\n *\n * @param scope - Validation scope\n * @param deps - Injectable dependencies\n * @returns Array of directory names to validate\n */\nexport function getValidationDirectories(\n scope: ValidationScope,\n projectRoot: string,\n deps: ScopeDeps = defaultScopeDeps,\n): string[] {\n // Get TypeScript configuration for the specified mode\n const config = resolveTypeScriptConfig(scope, projectRoot, deps);\n\n // Get directories that contain TypeScript files and respect tsconfig exclude patterns\n const configDirectories = getTopLevelDirectoriesWithTypeScript(config, projectRoot, deps);\n\n // Only include directories that actually exist\n const existingDirectories = configDirectories.filter((dir) => deps.existsSync(join(projectRoot, dir)));\n\n return existingDirectories;\n}\n\n/**\n * Get authoritative validation scope configuration.\n *\n * This is the main entry point for scope resolution. Returns a ScopeConfig\n * object that can be used to configure validation tools.\n *\n * @param scope - Validation scope\n * @param deps - Injectable dependencies\n * @returns Scope configuration\n *\n * @example\n * ```typescript\n * const scopeConfig = getTypeScriptScope(\"full\", projectRoot);\n * console.log(scopeConfig.directories); // [\"src\", \"tests\", \"scripts\"]\n * ```\n */\nexport function getTypeScriptScope(\n scope: ValidationScope,\n projectRoot: string,\n deps: ScopeDeps = defaultScopeDeps,\n): ScopeConfig {\n // Use validation-focused directory selection\n const directories = getValidationDirectories(scope, projectRoot, deps);\n\n // Read TypeScript config for patterns\n const config = resolveTypeScriptConfig(scope, projectRoot, deps);\n\n return {\n directories,\n filePatterns: filterActiveIncludePatterns(config.include ?? [], config.exclude ?? [], projectRoot, deps),\n excludePatterns: config.exclude ?? [],\n };\n}\n","/**\n * Tool discovery for validation infrastructure.\n *\n * Discovers validation tools (eslint, tsc, madge, etc.) using a three-tier\n * priority system: bundled → project → global.\n *\n * @module validation/discovery/tool-finder\n */\n\nimport { execSync } from \"node:child_process\";\nimport fs from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport path from \"node:path\";\n\nimport { TOOL_DISCOVERY, type ToolSource } from \"./constants\";\n\n/**\n * Information about a found tool.\n */\nexport interface ToolLocation {\n /** The tool name */\n tool: string;\n /** Absolute path to the tool executable or package */\n path: string;\n /** Where the tool was found */\n source: ToolSource;\n}\n\n/**\n * Information about a tool that was not found.\n */\nexport interface ToolNotFound {\n /** The tool name that was searched for */\n tool: string;\n /** Human-readable reason why the tool was not found */\n reason: string;\n}\n\n/**\n * Result of tool discovery - either found with location or not found with reason.\n */\nexport type ToolDiscoveryResult =\n | { found: true; location: ToolLocation }\n | { found: false; notFound: ToolNotFound };\n\n/**\n * Dependencies for tool discovery.\n * Enables testing without mocking by accepting controlled implementations.\n */\nexport interface ToolDiscoveryDeps {\n /**\n * Resolve a module path, returns the resolved path or null if not found.\n * @param modulePath - The module path to resolve (e.g., \"eslint/package.json\")\n */\n resolveModule: (modulePath: string) => string | null;\n\n /**\n * Check if a file exists at the given path.\n * @param filePath - The path to check\n */\n existsSync: (filePath: string) => boolean;\n\n /**\n * Find an executable in the system PATH.\n * @param tool - The tool name to find\n * @returns The absolute path to the tool, or null if not found\n */\n whichSync: (tool: string) => string | null;\n}\n\n/**\n * Create a require function for resolving modules.\n * Uses import.meta.url to create a require that resolves from this package.\n */\nconst require = createRequire(import.meta.url);\n\n/**\n * Default production dependencies for tool discovery.\n */\nexport const defaultToolDiscoveryDeps: ToolDiscoveryDeps = {\n resolveModule: (modulePath: string): string | null => {\n try {\n return require.resolve(modulePath);\n } catch {\n return null;\n }\n },\n\n existsSync: fs.existsSync,\n\n whichSync: (tool: string): string | null => {\n try {\n const result = execSync(`which ${tool}`, {\n encoding: \"utf-8\",\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n return result.trim() || null;\n } catch {\n return null;\n }\n },\n};\n\n/**\n * Options for tool discovery.\n */\nexport interface DiscoverToolOptions {\n /**\n * Project root directory for checking project-local node_modules.\n * Defaults to current working directory.\n */\n projectRoot?: string;\n\n /**\n * Dependencies for tool discovery.\n * Defaults to production dependencies.\n */\n deps?: ToolDiscoveryDeps;\n}\n\n/**\n * Discover a validation tool using three-tier priority.\n *\n * Discovery order:\n * 1. **Bundled**: Check if the tool is bundled with spx-cli via require.resolve\n * 2. **Project**: Check project's node_modules/.bin directory\n * 3. **Global**: Check system PATH via `which` command\n *\n * @param tool - The tool name to discover (e.g., \"eslint\", \"typescript\", \"madge\")\n * @param options - Discovery options including projectRoot and dependencies\n * @returns Discovery result with found location or not found reason\n *\n * @example\n * ```typescript\n * const result = await discoverTool(\"eslint\");\n * if (result.found) {\n * console.log(`Found ${result.location.tool} at ${result.location.path}`);\n * console.log(`Source: ${result.location.source}`);\n * } else {\n * console.log(`Not found: ${result.notFound.reason}`);\n * }\n * ```\n */\nexport async function discoverTool(\n tool: string,\n options: DiscoverToolOptions = {},\n): Promise<ToolDiscoveryResult> {\n const { projectRoot = process.cwd(), deps = defaultToolDiscoveryDeps } = options;\n\n // Tier 1: Check if bundled with spx-cli\n const bundledPath = deps.resolveModule(`${tool}/package.json`);\n if (bundledPath) {\n return {\n found: true,\n location: {\n tool,\n path: path.dirname(bundledPath),\n source: TOOL_DISCOVERY.SOURCES.BUNDLED,\n },\n };\n }\n\n // Tier 2: Check project's node_modules/.bin\n const projectBinPath = path.join(projectRoot, \"node_modules\", \".bin\", tool);\n if (deps.existsSync(projectBinPath)) {\n return {\n found: true,\n location: {\n tool,\n path: projectBinPath,\n source: TOOL_DISCOVERY.SOURCES.PROJECT,\n },\n };\n }\n\n // Tier 3: Check system PATH\n const globalPath = deps.whichSync(tool);\n if (globalPath) {\n return {\n found: true,\n location: {\n tool,\n path: globalPath,\n source: TOOL_DISCOVERY.SOURCES.GLOBAL,\n },\n };\n }\n\n // Not found anywhere\n return {\n found: false,\n notFound: {\n tool,\n reason: TOOL_DISCOVERY.MESSAGES.NOT_FOUND_REASON(tool),\n },\n };\n}\n\n/**\n * Format a graceful skip message for when a tool is not found.\n *\n * @param stepName - The name of the validation step being skipped\n * @param result - The tool discovery result\n * @returns Formatted skip message, or empty string if tool was found\n *\n * @example\n * ```typescript\n * const result = await discoverTool(\"madge\");\n * const message = formatSkipMessage(\"Circular dependency check\", result);\n * // \"⏭ Skipping Circular dependency check (madge not available)\"\n * ```\n */\nexport function formatSkipMessage(\n stepName: string,\n result: ToolDiscoveryResult,\n): string {\n if (result.found) {\n return \"\";\n }\n return TOOL_DISCOVERY.MESSAGES.SKIP_FORMAT(stepName, result.notFound.tool);\n}\n","/**\n * Constants for tool discovery.\n * @module validation/discovery/constants\n */\n\n/**\n * Tool discovery constants.\n * Using constants ensures DRY principle and makes tests verify behavior via constants.\n */\nexport const TOOL_DISCOVERY = {\n /** Tool source identifiers */\n SOURCES: {\n /** Tool bundled with spx-cli */\n BUNDLED: \"bundled\",\n /** Tool in project's node_modules */\n PROJECT: \"project\",\n /** Tool in system PATH */\n GLOBAL: \"global\",\n } as const,\n\n /** Message templates */\n MESSAGES: {\n /** Prefix for skip messages */\n SKIP_PREFIX: \"\\u23ED\", // ⏭ emoji\n /**\n * Format not found reason message.\n * @param tool - The tool name that was not found\n */\n NOT_FOUND_REASON: (tool: string): string =>\n `${tool} not found in bundled deps, project node_modules, or system PATH`,\n /**\n * Format skip message for graceful degradation.\n * @param step - The validation step name\n * @param tool - The tool that was not found\n */\n SKIP_FORMAT: (step: string, tool: string): string =>\n `${TOOL_DISCOVERY.MESSAGES.SKIP_PREFIX} Skipping ${step} (${tool} not available)`,\n },\n} as const;\n\n/** Type for tool source */\nexport type ToolSource = (typeof TOOL_DISCOVERY.SOURCES)[keyof typeof TOOL_DISCOVERY.SOURCES];\n","/**\n * Circular dependency validation step.\n *\n * Uses madge to detect circular imports in the codebase.\n *\n * @module validation/steps/circular\n */\n\nimport madge from \"madge\";\nimport { join } from \"node:path\";\n\nimport { TSCONFIG_FILES } from \"../config/scope\";\nimport type { CircularDependencyResult, ScopeConfig, ValidationScope } from \"../types\";\n\n// =============================================================================\n// DEPENDENCY INJECTION INTERFACES\n// =============================================================================\n\n/**\n * Dependencies for circular dependency validation.\n *\n * Enables dependency injection for testing.\n */\nexport interface CircularDeps {\n madge: typeof madge;\n}\n\nexport const CIRCULAR_DEPS_KEYS = {\n MADGE: \"madge\",\n} as const;\n\nexport type CircularDependencyGraphRunner = CircularDeps[typeof CIRCULAR_DEPS_KEYS.MADGE];\n\n/**\n * Default production dependencies.\n */\nexport const defaultCircularDeps: CircularDeps = {\n [CIRCULAR_DEPS_KEYS.MADGE]: madge,\n};\n\n// =============================================================================\n// VALIDATION FUNCTION\n// =============================================================================\n\n/**\n * Validate circular dependencies using TypeScript-derived scope.\n *\n * @param scope - Validation scope\n * @param typescriptScope - Scope configuration from tsconfig\n * @param projectRoot - Project root for Madge input and tsconfig resolution\n * @param deps - Injectable dependencies\n * @returns Result with success status and any circular dependencies found\n *\n * @example\n * ```typescript\n * const result = await validateCircularDependencies(\"full\", scopeConfig);\n * if (!result.success) {\n * console.error(\"Found circular dependencies:\", result.circularDependencies);\n * }\n * ```\n */\nexport async function validateCircularDependencies(\n scope: ValidationScope,\n typescriptScope: ScopeConfig,\n projectRoot: string,\n deps: CircularDeps = defaultCircularDeps,\n): Promise<CircularDependencyResult> {\n try {\n // Use TypeScript-derived directories for perfect scope alignment\n const analyzeDirectories = typescriptScope.directories.map((directory) => join(projectRoot, directory));\n\n if (analyzeDirectories.length === 0) {\n return { success: true };\n }\n\n // Use the appropriate TypeScript config based on scope\n const tsConfigFile = join(projectRoot, TSCONFIG_FILES[scope]);\n\n // Convert tsconfig exclude patterns to madge excludeRegExp\n const excludeRegExps = typescriptScope.excludePatterns.map((pattern) => {\n // Remove trailing /**/* or /* for cleaner matching\n const cleanPattern = pattern.replace(/\\/\\*\\*?\\/\\*$/, \"\");\n // Escape regex special chars and create regex\n const escaped = cleanPattern.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n return new RegExp(escaped);\n });\n\n const result = await deps.madge(analyzeDirectories, {\n baseDir: projectRoot,\n fileExtensions: [\"ts\", \"tsx\"],\n tsConfig: tsConfigFile,\n excludeRegExp: excludeRegExps,\n });\n\n const circular = result.circular();\n\n if (circular.length === 0) {\n return { success: true };\n } else {\n return {\n success: false,\n error: `Found ${circular.length} circular dependency cycle(s)`,\n circularDependencies: circular,\n };\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n return { success: false, error: errorMessage };\n }\n}\n","/**\n * Circular dependency check command.\n *\n * Runs madge to detect circular dependencies.\n */\nimport { resolveConfig } from \"@/config/index\";\nimport {\n VALIDATION_PATH_TOOL_SUBSECTIONS,\n type ValidationConfig,\n validationConfigDescriptor,\n} from \"@/validation/config/descriptor\";\nimport { applyValidationPathFilterToScope, validationPathFilterForTool } from \"@/validation/config/path-filter\";\nimport { getTypeScriptScope } from \"@/validation/config/scope\";\nimport { detectTypeScript, discoverTool, formatSkipMessage } from \"@/validation/discovery/index\";\nimport { validateCircularDependencies } from \"@/validation/steps/circular\";\nimport {\n formatTypeScriptAbsentSkipMessage,\n VALIDATION_COMMAND_OUTPUT,\n VALIDATION_STAGE_DISPLAY_NAMES,\n} from \"./messages\";\nimport type { CircularCommandOptions, ValidationCommandResult } from \"./types\";\n\nconst TYPESCRIPT_ABSENT_MESSAGE = formatTypeScriptAbsentSkipMessage(VALIDATION_STAGE_DISPLAY_NAMES.CIRCULAR);\nconst CIRCULAR_CONFIG_ERROR_MESSAGE = `${VALIDATION_STAGE_DISPLAY_NAMES.CIRCULAR}: ✗ config error`;\nexport const CIRCULAR_DEPENDENCY_OUTPUT = {\n FOUND: VALIDATION_COMMAND_OUTPUT.CIRCULAR_FOUND,\n} as const;\n\n/**\n * Check for circular dependencies.\n *\n * Gates madge execution on TypeScript language detection: madge walks the\n * TypeScript import graph and has nothing to examine in non-TypeScript\n * projects.\n *\n * @param options - Command options\n * @returns Command result with exit code and output\n */\nexport async function circularCommand(options: CircularCommandOptions): Promise<ValidationCommandResult> {\n const { cwd, quiet } = options;\n const startTime = Date.now();\n\n // Gate 1: language detection. No TypeScript = skip cleanly.\n const tsDetection = detectTypeScript(cwd);\n if (!tsDetection.present) {\n return {\n exitCode: 0,\n output: quiet ? \"\" : TYPESCRIPT_ABSENT_MESSAGE,\n durationMs: Date.now() - startTime,\n };\n }\n\n // Gate 2: tool discovery.\n const toolResult = await discoverTool(\"madge\", { projectRoot: cwd });\n if (!toolResult.found) {\n const skipMessage = formatSkipMessage(\"circular dependency check\", toolResult);\n return { exitCode: 0, output: skipMessage, durationMs: Date.now() - startTime };\n }\n\n const loaded = await resolveConfig(cwd, [validationConfigDescriptor]);\n if (!loaded.ok) {\n return {\n exitCode: 1,\n output: `${CIRCULAR_CONFIG_ERROR_MESSAGE} — ${loaded.error}`,\n durationMs: Date.now() - startTime,\n };\n }\n const validationConfig = loaded.value[validationConfigDescriptor.section] as ValidationConfig;\n const scopeConfig = applyValidationPathFilterToScope(\n getTypeScriptScope(\"full\", cwd),\n validationPathFilterForTool(validationConfig.paths, VALIDATION_PATH_TOOL_SUBSECTIONS.CIRCULAR),\n );\n\n // Run circular dependency validation\n const result = await validateCircularDependencies(\"full\", scopeConfig, cwd);\n const durationMs = Date.now() - startTime;\n\n // Map result to command output\n if (result.success) {\n const output = quiet ? \"\" : VALIDATION_COMMAND_OUTPUT.CIRCULAR_NONE_FOUND;\n return { exitCode: 0, output, durationMs };\n } else {\n // Format circular dependency output\n let output = result.error ?? CIRCULAR_DEPENDENCY_OUTPUT.FOUND;\n if (result.circularDependencies && result.circularDependencies.length > 0) {\n const cycles = result.circularDependencies\n .map((cycle) => ` ${cycle.join(\" → \")}`)\n .join(\"\\n\");\n output = `${CIRCULAR_DEPENDENCY_OUTPUT.FOUND}:\\n${cycles}`;\n }\n return { exitCode: 1, output, durationMs };\n }\n}\n","/**\n * Knip validation step.\n *\n * Detects unused exports, dependencies, and files using knip.\n *\n * @module validation/steps/knip\n */\n\nimport { existsSync } from \"node:fs\";\nimport { mkdtemp, rm, writeFile } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { isAbsolute, join } from \"node:path\";\n\nimport { lifecycleProcessRunner, type ProcessRunner, spawnManagedSubprocess } from \"@/lib/process-lifecycle\";\nimport { TSCONFIG_FILES } from \"@/validation/config/scope\";\nimport type { ScopeConfig } from \"../types\";\n\n// =============================================================================\n// DEFAULT DEPENDENCIES\n// =============================================================================\n\n/**\n * Default production process runner for Knip.\n */\nexport const defaultKnipProcessRunner: ProcessRunner = lifecycleProcessRunner;\nexport const KNIP_COMMAND_TOKENS = {\n COMMAND: \"knip\",\n TSCONFIG_FLAG: \"--tsConfig\",\n USE_TSCONFIG_FILES_FLAG: \"--use-tsconfig-files\",\n} as const;\n\nexport interface KnipDeps {\n readonly existsSync: typeof existsSync;\n readonly mkdtemp: typeof mkdtemp;\n readonly rm: typeof rm;\n readonly writeFile: typeof writeFile;\n}\n\nconst defaultKnipDeps: KnipDeps = {\n existsSync,\n mkdtemp,\n rm,\n writeFile,\n};\n\nexport interface KnipValidationContext {\n readonly projectRoot: string;\n readonly typescriptScope: ScopeConfig;\n}\n\n// =============================================================================\n// VALIDATION FUNCTION\n// =============================================================================\n\n/**\n * Validate unused code using knip with TypeScript-derived scope.\n *\n * @param context - Knip validation context\n * @param runner - Injectable process runner\n * @returns Promise resolving to validation result\n *\n * @example\n * ```typescript\n * const result = await validateKnip({ projectRoot, typescriptScope: scopeConfig });\n * if (!result.success) {\n * console.error(\"Knip found issues:\", result.error);\n * }\n * ```\n */\nexport async function validateKnip(\n context: KnipValidationContext,\n runner: ProcessRunner = defaultKnipProcessRunner,\n deps: KnipDeps = defaultKnipDeps,\n): Promise<{\n success: boolean;\n error?: string;\n}> {\n try {\n const { projectRoot, typescriptScope } = context;\n // Use TypeScript-derived directories for perfect scope alignment\n const analyzeDirectories = typescriptScope.directories;\n\n if (analyzeDirectories.length === 0) {\n return { success: true };\n }\n\n return await runKnipSubprocess(projectRoot, typescriptScope, runner, deps);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n return { success: false, error: errorMessage };\n }\n}\n\nasync function runKnipSubprocess(\n projectRoot: string,\n typescriptScope: ScopeConfig,\n runner: ProcessRunner,\n deps: KnipDeps,\n): Promise<{ success: boolean; error?: string }> {\n const scopedTsconfig = typescriptScope.filteredByValidationPaths\n ? await createScopedKnipTsconfig(projectRoot, typescriptScope, deps)\n : undefined;\n const localBin = join(projectRoot, \"node_modules\", \".bin\", \"knip\");\n const binary = deps.existsSync(localBin) ? localBin : \"npx\";\n const baseArgs = scopedTsconfig === undefined\n ? []\n : [\n KNIP_COMMAND_TOKENS.USE_TSCONFIG_FILES_FLAG,\n KNIP_COMMAND_TOKENS.TSCONFIG_FLAG,\n scopedTsconfig.configPath,\n ];\n const args = binary === \"npx\" ? [KNIP_COMMAND_TOKENS.COMMAND, ...baseArgs] : baseArgs;\n const knipProcess = spawnManagedSubprocess(runner, binary, args, {\n cwd: projectRoot,\n });\n const cleanup = scopedTsconfig?.cleanup ?? (async () => {});\n let cleanupStarted = false;\n let resultResolved = false;\n\n const cleanupOnce = async () => {\n if (cleanupStarted) {\n return;\n }\n cleanupStarted = true;\n await cleanup();\n };\n\n let knipOutput = \"\";\n let knipError = \"\";\n\n knipProcess.stdout?.on(\"data\", (data: Buffer) => {\n knipOutput += data.toString();\n });\n\n knipProcess.stderr?.on(\"data\", (data: Buffer) => {\n knipError += data.toString();\n });\n\n return new Promise((resolve) => {\n const resolveAfterCleanup = (result: { success: boolean; error?: string }) => {\n if (resultResolved) {\n return;\n }\n resultResolved = true;\n void cleanupOnce().finally(() => resolve(result));\n };\n\n knipProcess.on(\"close\", (code) => {\n if (code === 0) {\n resolveAfterCleanup({ success: true });\n } else {\n const errorOutput = knipOutput || knipError || \"Unused code detected\";\n resolveAfterCleanup({\n success: false,\n error: errorOutput,\n });\n }\n });\n\n knipProcess.on(\"error\", (error) => {\n resolveAfterCleanup({ success: false, error: error.message });\n });\n });\n}\n\nasync function createScopedKnipTsconfig(\n projectRoot: string,\n typescriptScope: ScopeConfig,\n deps: KnipDeps,\n): Promise<{ configPath: string; cleanup: () => Promise<void> }> {\n const tempDir = await deps.mkdtemp(join(tmpdir(), \"validate-knip-\"));\n const configPath = join(tempDir, TSCONFIG_FILES.full);\n const toProjectPathPattern = (pattern: string) => isAbsolute(pattern) ? pattern : join(projectRoot, pattern);\n const project = typescriptScope.filePatterns.length > 0\n ? typescriptScope.filePatterns\n : typescriptScope.directories.map((directory) => `${directory}/**/*.{js,ts,tsx}`);\n const config = {\n extends: join(projectRoot, TSCONFIG_FILES.full),\n include: project.map(toProjectPathPattern),\n exclude: typescriptScope.excludePatterns.map(toProjectPathPattern),\n };\n await deps.writeFile(configPath, JSON.stringify(config, null, 2));\n return {\n configPath,\n cleanup: () => deps.rm(tempDir, { recursive: true, force: true }),\n };\n}\n","/**\n * Knip command for detecting unused code.\n *\n * Runs knip to find unused exports, dependencies, and files.\n */\nimport { resolveConfig } from \"@/config/index\";\nimport {\n VALIDATION_PATH_TOOL_SUBSECTIONS,\n type ValidationConfig,\n validationConfigDescriptor,\n} from \"@/validation/config/descriptor\";\nimport { applyValidationPathFilterToScope, validationPathFilterForTool } from \"@/validation/config/path-filter\";\nimport { getTypeScriptScope } from \"@/validation/config/scope\";\nimport { discoverTool, formatSkipMessage } from \"@/validation/discovery/index\";\nimport { validateKnip } from \"@/validation/steps/knip\";\nimport { VALIDATION_COMMAND_OUTPUT } from \"./messages\";\nimport type { KnipCommandOptions, ValidationCommandResult } from \"./types\";\n\n/**\n * Detect unused code with knip.\n *\n * @param options - Command options\n * @returns Command result with exit code and output\n */\nexport async function knipCommand(options: KnipCommandOptions): Promise<ValidationCommandResult> {\n const { cwd, quiet } = options;\n const startTime = Date.now();\n\n const loaded = await resolveConfig(cwd, [validationConfigDescriptor]);\n if (!loaded.ok) {\n return {\n exitCode: 1,\n output: `${VALIDATION_COMMAND_OUTPUT.KNIP_CONFIG_ERROR} — ${loaded.error}`,\n durationMs: Date.now() - startTime,\n };\n }\n const validationConfig = loaded.value[validationConfigDescriptor.section] as ValidationConfig;\n\n if (!validationConfig.knip.enabled) {\n const output = quiet ? \"\" : VALIDATION_COMMAND_OUTPUT.KNIP_DISABLED;\n return { exitCode: 0, output, durationMs: Date.now() - startTime };\n }\n\n // Discover knip\n const toolResult = await discoverTool(\"knip\", { projectRoot: cwd });\n if (!toolResult.found) {\n const skipMessage = formatSkipMessage(\"unused code detection\", toolResult);\n return { exitCode: 0, output: skipMessage, durationMs: Date.now() - startTime };\n }\n\n const scopeConfig = applyValidationPathFilterToScope(\n getTypeScriptScope(\"full\", cwd),\n validationPathFilterForTool(validationConfig.paths, VALIDATION_PATH_TOOL_SUBSECTIONS.KNIP),\n );\n\n // Run knip validation\n const result = await validateKnip({ projectRoot: cwd, typescriptScope: scopeConfig });\n const durationMs = Date.now() - startTime;\n\n // Map result to command output\n if (result.success) {\n const output = quiet ? \"\" : VALIDATION_COMMAND_OUTPUT.KNIP_SUCCESS;\n return { exitCode: 0, output, durationMs };\n } else {\n const output = result.error ?? VALIDATION_COMMAND_OUTPUT.KNIP_FAILURE;\n return { exitCode: 1, output, durationMs };\n }\n}\n","/**\n * ESLint validation step.\n *\n * Validates code against ESLint rules with automatic TypeScript scope alignment.\n *\n * @module validation/steps/eslint\n */\n\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nimport { lifecycleProcessRunner, type ProcessRunner, spawnManagedSubprocess } from \"@/lib/process-lifecycle\";\nimport { validateLintPolicy } from \"@/validation/lint-policy\";\nimport type { ExecutionMode, ScopeConfig, ValidationContext, ValidationScope } from \"../types\";\nimport { EXECUTION_MODES, VALIDATION_SCOPES } from \"../types\";\nimport {\n defaultValidationSubprocessOutputStreams,\n forwardValidationSubprocessOutput,\n VALIDATION_SUBPROCESS_EVENTS,\n type ValidationSubprocessOutputStreams,\n} from \"./subprocess-output\";\n\n// =============================================================================\n// DEFAULT DEPENDENCIES\n// =============================================================================\n\n/**\n * Default production process runner for ESLint.\n */\nexport const defaultEslintProcessRunner: ProcessRunner = lifecycleProcessRunner;\n\n// =============================================================================\n// PURE ARGUMENT BUILDER\n// =============================================================================\n\n/**\n * Default ESLint flat config file name, used when the caller does not supply\n * one. Callers should prefer passing the config file reported by language\n * detection.\n */\nexport const DEFAULT_ESLINT_CONFIG_FILE = \"eslint.config.ts\";\nexport const ESLINT_COMMAND_TOKENS = {\n COMMAND: \"eslint\",\n CONFIG_FLAG: \"--config\",\n CURRENT_DIRECTORY: \".\",\n FILE_SEPARATOR: \"--\",\n FIX_FLAG: \"--fix\",\n IGNORE_PATTERN_FLAG: \"--ignore-pattern\",\n} as const;\nexport const ESLINT_LOCAL_BIN_SEGMENTS = [\"node_modules\", \".bin\", ESLINT_COMMAND_TOKENS.COMMAND] as const;\n\n/**\n * Build ESLint CLI arguments based on validation context.\n *\n * Pure function for testability - can be verified at Level 1.\n *\n * @param context - Context for building arguments\n * @returns Array of ESLint CLI arguments\n *\n * @example\n * ```typescript\n * const args = buildEslintArgs({\n * validatedFiles: [\"src/index.ts\"],\n * mode: \"write\",\n * configFile: \"eslint.config.ts\",\n * });\n * // Returns: [\"eslint\", \"--config\", \"eslint.config.ts\", \"--\", \"src/index.ts\"]\n * ```\n */\nexport function buildEslintArgs(context: {\n validatedFiles?: string[];\n mode?: ExecutionMode;\n configFile?: string;\n scope: ValidationScope;\n scopeConfig?: ScopeConfig;\n}): string[] {\n const { validatedFiles, mode, configFile = DEFAULT_ESLINT_CONFIG_FILE, scope, scopeConfig } = context;\n const fixArg = mode === EXECUTION_MODES.WRITE ? [ESLINT_COMMAND_TOKENS.FIX_FLAG] : [];\n\n if (validatedFiles && validatedFiles.length > 0) {\n // Explicit file scope is already the caller's narrowed target and takes\n // precedence over broad validation scope selection.\n return [\n ESLINT_COMMAND_TOKENS.COMMAND,\n ESLINT_COMMAND_TOKENS.CONFIG_FLAG,\n configFile,\n ...fixArg,\n ESLINT_COMMAND_TOKENS.FILE_SEPARATOR,\n ...validatedFiles,\n ];\n }\n const targetArgs = scope === VALIDATION_SCOPES.PRODUCTION || scopeConfig?.filteredByValidationPathIncludes\n ? buildProductionTargetArgs(scopeConfig)\n : buildCurrentDirectoryTargetArgs(scopeConfig);\n return [\n ESLINT_COMMAND_TOKENS.COMMAND,\n ...targetArgs,\n ESLINT_COMMAND_TOKENS.CONFIG_FLAG,\n configFile,\n ...fixArg,\n ];\n}\n\nfunction buildCurrentDirectoryTargetArgs(scopeConfig: ScopeConfig | undefined): string[] {\n return [\n ESLINT_COMMAND_TOKENS.CURRENT_DIRECTORY,\n ...(scopeConfig?.filteredByValidationPaths ? buildIgnorePatternArgs(scopeConfig.excludePatterns) : []),\n ];\n}\n\nfunction buildProductionTargetArgs(scopeConfig: ScopeConfig | undefined): string[] {\n const targetPatterns = scopeConfig?.filePatterns.length\n ? scopeConfig.filePatterns\n : [ESLINT_COMMAND_TOKENS.CURRENT_DIRECTORY];\n return [\n ...targetPatterns,\n ...buildIgnorePatternArgs(scopeConfig?.excludePatterns ?? []),\n ];\n}\n\nfunction buildIgnorePatternArgs(patterns: readonly string[]): string[] {\n return patterns.flatMap((pattern) => [ESLINT_COMMAND_TOKENS.IGNORE_PATTERN_FLAG, pattern]);\n}\n\n// =============================================================================\n// VALIDATION FUNCTION\n// =============================================================================\n\n/**\n * Validate ESLint compliance using automatic TypeScript scope alignment.\n *\n * @param context - Validation context\n * @param runner - Injectable process runner\n * @returns Promise resolving to validation result\n *\n * @example\n * ```typescript\n * const result = await validateESLint(context);\n * if (!result.success) {\n * console.error(\"ESLint failed:\", result.error);\n * }\n * ```\n */\nexport async function validateESLint(\n context: ValidationContext,\n runner: ProcessRunner = defaultEslintProcessRunner,\n outputStreams: ValidationSubprocessOutputStreams = defaultValidationSubprocessOutputStreams,\n): Promise<{\n success: boolean;\n error?: string;\n skipped?: boolean;\n}> {\n const { projectRoot, scope, validatedFiles, mode, eslintConfigFile } = context;\n const lintPolicy = validateLintPolicy(projectRoot);\n\n if (!lintPolicy.ok) {\n return { success: false, error: lintPolicy.error };\n }\n\n if (context.scopeConfig.filteredByValidationPathNoMatches) {\n return { success: true, skipped: true };\n }\n\n const eslintArgs = buildEslintArgs({\n validatedFiles,\n mode,\n configFile: eslintConfigFile,\n scope,\n scopeConfig: context.scopeConfig,\n });\n\n return new Promise((resolve) => {\n const localBin = join(projectRoot, ...ESLINT_LOCAL_BIN_SEGMENTS);\n const binary = existsSync(localBin) ? localBin : \"npx\";\n const spawnArgs = binary === \"npx\" ? eslintArgs : eslintArgs.slice(1);\n const eslintProcess = spawnManagedSubprocess(runner, binary, spawnArgs, {\n cwd: projectRoot,\n });\n forwardValidationSubprocessOutput(eslintProcess, outputStreams);\n\n eslintProcess.on(VALIDATION_SUBPROCESS_EVENTS.CLOSE, (code) => {\n if (code === 0) {\n resolve({ success: true });\n } else {\n resolve({ success: false, error: `ESLint exited with code ${code}` });\n }\n });\n\n eslintProcess.on(VALIDATION_SUBPROCESS_EVENTS.ERROR, (error) => {\n resolve({ success: false, error: error.message });\n });\n });\n}\n","import { execFileSync } from \"node:child_process\";\nimport { existsSync, readdirSync, readFileSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nimport { withoutGitEnvironment } from \"@/git/environment\";\nimport { SPEC_TREE_SUPERSEDED_NODE_SUFFIXES } from \"@/lib/spec-tree\";\nimport { NODE_SUFFIXES, SPEC_TREE_CONFIG } from \"@/lib/spec-tree/config\";\nimport { LINT_POLICY_BASE_REFS, LINT_POLICY_MANIFESTS, parseLintPolicyManifest } from \"./lint-policy-constants\";\n\nconst TEST_LINT_DEBT_NODE_MANIFEST_FILE = LINT_POLICY_MANIFESTS.TEST_LINT_DEBT_NODES.file;\nconst TEST_LINT_DEBT_NODE_MANIFEST_KEY = LINT_POLICY_MANIFESTS.TEST_LINT_DEBT_NODES.key;\nconst TEST_OWNED_CONSTANT_DEBT_NODE_MANIFEST_FILE = LINT_POLICY_MANIFESTS.TEST_OWNED_CONSTANT_DEBT_NODES.file;\nconst TEST_OWNED_CONSTANT_DEBT_NODE_MANIFEST_KEY = LINT_POLICY_MANIFESTS.TEST_OWNED_CONSTANT_DEBT_NODES.key;\nconst SPEC_TREE_ROOT = SPEC_TREE_CONFIG.ROOT_DIRECTORY;\nconst BASE_BRANCH_REFS = [LINT_POLICY_BASE_REFS.REMOTE_MAIN, LINT_POLICY_BASE_REFS.LOCAL_MAIN] as const;\n\nfunction isSpecTreeNodePath(entry: string): boolean {\n return NODE_SUFFIXES.some((suffix) => entry.endsWith(suffix));\n}\n\nexport type LintPolicyResult =\n | { readonly ok: true }\n | { readonly ok: false; readonly error: string };\n\nfunction readManifest(productDir: string, file: string, key: string): string[] {\n return parseLintPolicyManifest(\n readFileSync(join(productDir, file), \"utf-8\"),\n file,\n key,\n );\n}\n\nfunction manifestExists(productDir: string, file: string): boolean {\n return existsSync(join(productDir, file));\n}\n\nfunction findDeprecatedSpecNodePath(productDir: string): string | undefined {\n function visit(relativeDirectory: string): string | undefined {\n const absoluteDirectory = join(productDir, relativeDirectory);\n for (const entry of readdirSync(absoluteDirectory, { withFileTypes: true })) {\n if (!entry.isDirectory()) {\n continue;\n }\n\n const childPath = `${relativeDirectory}/${entry.name}`;\n\n if (SPEC_TREE_SUPERSEDED_NODE_SUFFIXES.some((suffix) => entry.name.endsWith(suffix))) {\n return childPath;\n }\n\n const nestedDeprecatedPath = visit(childPath);\n if (nestedDeprecatedPath !== undefined) {\n return nestedDeprecatedPath;\n }\n }\n\n return undefined;\n }\n\n const specTreeRootPath = join(productDir, SPEC_TREE_ROOT);\n if (!existsSync(specTreeRootPath)) {\n return undefined;\n }\n\n return visit(SPEC_TREE_ROOT);\n}\n\nfunction assertManifestEntries(\n productDir: string,\n file: string,\n entries: string[],\n suffixPredicate: (entry: string) => boolean,\n suffixDescription: string,\n): void {\n const duplicates = entries.filter((entry, index) => entries.indexOf(entry) !== index);\n\n if (duplicates.length > 0) {\n throw new Error(\n `${file} contains duplicate entries: ${duplicates.join(\", \")}`,\n );\n }\n\n for (const entry of entries) {\n if (entry !== entry.trim()) {\n throw new Error(`${file} entry has surrounding whitespace: ${entry}`);\n }\n\n if (!entry.startsWith(`${SPEC_TREE_ROOT}/`)) {\n throw new Error(`${file} entry must be under ${SPEC_TREE_ROOT}/: ${entry}`);\n }\n\n if (entry.includes(\"..\")) {\n throw new Error(`${file} entry must not contain '..': ${entry}`);\n }\n\n if (!suffixPredicate(entry)) {\n throw new Error(`${file} entry must ${suffixDescription}: ${entry}`);\n }\n\n const absoluteEntry = join(productDir, entry);\n if (!existsSync(absoluteEntry) || !statSync(absoluteEntry).isDirectory()) {\n throw new Error(`${file} entry does not exist as a directory: ${entry}`);\n }\n }\n}\n\nfunction readBaselineManifest(productDir: string, file: string, key: string): string[] | undefined {\n const baselineRef = readBaselineRef(productDir);\n if (baselineRef === undefined) {\n return undefined;\n }\n\n let content: string;\n try {\n content = execFileSync(\"git\", [\"show\", `${baselineRef}:${file}`], {\n cwd: productDir,\n encoding: \"utf-8\",\n env: withoutGitEnvironment(process.env),\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n });\n } catch {\n return undefined;\n }\n\n return parseLintPolicyManifest(\n content,\n `${baselineRef}:${file}`,\n key,\n );\n}\n\nfunction readBaselineRef(productDir: string): string | undefined {\n const mergeCommitFirstParent = readMergeCommitFirstParent(productDir);\n if (mergeCommitFirstParent !== undefined) {\n return mergeCommitFirstParent;\n }\n\n for (const baseBranchRef of BASE_BRANCH_REFS) {\n const mergeBase = readMergeBase(productDir, baseBranchRef);\n if (mergeBase !== undefined) {\n return mergeBase;\n }\n }\n\n return undefined;\n}\n\nfunction readMergeCommitFirstParent(productDir: string): string | undefined {\n const secondParent = readGitRef(productDir, [\"rev-parse\", \"--verify\", \"HEAD^2\"]);\n if (secondParent === undefined) {\n return undefined;\n }\n return readGitRef(productDir, [\"rev-parse\", \"--verify\", \"HEAD^1\"]);\n}\n\nfunction readMergeBase(productDir: string, baseBranchRef: string): string | undefined {\n return readGitRef(productDir, [\"merge-base\", \"HEAD\", baseBranchRef]);\n}\n\nfunction readGitRef(productDir: string, args: readonly string[]): string | undefined {\n try {\n const output = execFileSync(\"git\", [...args], {\n cwd: productDir,\n encoding: \"utf-8\",\n env: withoutGitEnvironment(process.env),\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n });\n return output.trim() || undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction assertManifestDoesNotGrow(\n productDir: string,\n file: string,\n key: string,\n entries: string[],\n): void {\n const baselineEntries = readBaselineManifest(productDir, file, key);\n\n if (baselineEntries === undefined) {\n return;\n }\n\n const baselineEntrySet = new Set(baselineEntries);\n const additions = entries.filter((entry) => !baselineEntrySet.has(entry));\n\n if (additions.length > 0) {\n throw new Error(\n `${file} is shrink-only. Remove the listed debt instead of adding entries: ${additions.join(\", \")}`,\n );\n }\n}\n\nfunction rejectDeprecatedSpecNodeSuffixes(productDir: string): void {\n const deprecatedSpecNodePath = findDeprecatedSpecNodePath(productDir);\n if (deprecatedSpecNodePath !== undefined) {\n throw new Error(\n `Spec Tree nodes must use current suffixes only: ${deprecatedSpecNodePath}`,\n );\n }\n}\n\nfunction validateTestLintDebtNodeManifest(productDir: string, entries: string[]): void {\n assertManifestEntries(\n productDir,\n TEST_LINT_DEBT_NODE_MANIFEST_FILE,\n entries,\n isSpecTreeNodePath,\n \"be a Spec Tree node path\",\n );\n assertManifestDoesNotGrow(\n productDir,\n TEST_LINT_DEBT_NODE_MANIFEST_FILE,\n TEST_LINT_DEBT_NODE_MANIFEST_KEY,\n entries,\n );\n}\n\nfunction validateTestOwnedConstantDebtNodeManifest(productDir: string, entries: string[]): void {\n assertManifestEntries(\n productDir,\n TEST_OWNED_CONSTANT_DEBT_NODE_MANIFEST_FILE,\n entries,\n isSpecTreeNodePath,\n \"be a Spec Tree node path\",\n );\n assertManifestDoesNotGrow(\n productDir,\n TEST_OWNED_CONSTANT_DEBT_NODE_MANIFEST_FILE,\n TEST_OWNED_CONSTANT_DEBT_NODE_MANIFEST_KEY,\n entries,\n );\n}\n\nexport function validateLintPolicy(productDir: string): LintPolicyResult {\n try {\n rejectDeprecatedSpecNodeSuffixes(productDir);\n\n const manifestExistence = [\n manifestExists(productDir, TEST_LINT_DEBT_NODE_MANIFEST_FILE),\n manifestExists(productDir, TEST_OWNED_CONSTANT_DEBT_NODE_MANIFEST_FILE),\n ];\n if (manifestExistence.every((exists) => !exists)) {\n return { ok: true };\n }\n if (!manifestExistence.every(Boolean)) {\n return {\n ok: false,\n error: \"lint policy manifests must be present together\",\n };\n }\n\n validateTestLintDebtNodeManifest(\n productDir,\n readManifest(productDir, TEST_LINT_DEBT_NODE_MANIFEST_FILE, TEST_LINT_DEBT_NODE_MANIFEST_KEY),\n );\n validateTestOwnedConstantDebtNodeManifest(\n productDir,\n readManifest(\n productDir,\n TEST_OWNED_CONSTANT_DEBT_NODE_MANIFEST_FILE,\n TEST_OWNED_CONSTANT_DEBT_NODE_MANIFEST_KEY,\n ),\n );\n return { ok: true };\n } catch (error) {\n return { ok: false, error: error instanceof Error ? error.message : String(error) };\n }\n}\n","import * as JSONC from \"jsonc-parser\";\n\nexport const LINT_POLICY_MANIFESTS = {\n TEST_LINT_DEBT_NODES: {\n file: \"eslint.test-lint-debt-nodes.json\",\n key: \"testLintDebtNodes\",\n },\n TEST_OWNED_CONSTANT_DEBT_NODES: {\n file: \"eslint.test-owned-constant-debt-nodes.json\",\n key: \"testOwnedConstantDebtNodes\",\n },\n} as const;\n\nexport const LINT_POLICY_BASE_REFS = {\n REMOTE_MAIN: \"origin/main\",\n LOCAL_MAIN: \"main\",\n} as const;\n\ntype JsonObject = Record<string, unknown>;\n\nfunction isJsonObject(value: unknown): value is JsonObject {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nexport function parseLintPolicyManifest(content: string, source: string, key: string): string[] {\n const parsed = JSONC.parse(content) as unknown;\n\n if (!isJsonObject(parsed)) {\n throw new Error(`${source} must contain a JSON object`);\n }\n\n const entries = parsed[key];\n\n if (!Array.isArray(entries)) {\n throw new Error(`${source} must contain a ${key} array`);\n }\n\n const invalidEntries = entries.filter((entry) => typeof entry !== \"string\");\n\n if (invalidEntries.length > 0) {\n throw new Error(`${source} ${key} entries must be strings`);\n }\n\n return entries as string[];\n}\n","/**\n * Shared types for the validation module.\n *\n * These types define the contracts for validation steps and their dependencies,\n * enabling dependency injection for testability.\n *\n * @module validation/types\n */\n\n// =============================================================================\n// DEPENDENCY INJECTION INTERFACES\n// =============================================================================\n\n/**\n * Validation scope constants.\n *\n * @example\n * ```typescript\n * import { VALIDATION_SCOPES } from \"./types.js\";\n * const scope = VALIDATION_SCOPES.FULL; // \"full\"\n * ```\n */\nexport const VALIDATION_SCOPES = {\n /** Validate entire codebase including tests and scripts */\n FULL: \"full\",\n /** Validate production files only */\n PRODUCTION: \"production\",\n} as const;\n\n/** Type for validation scope values */\nexport type ValidationScope = (typeof VALIDATION_SCOPES)[keyof typeof VALIDATION_SCOPES];\n\n/**\n * Configuration for validation scope.\n *\n * Derived from tsconfig.json settings to ensure alignment between\n * TypeScript and ESLint validation.\n */\nexport interface ScopeConfig {\n /** Project-root-relative top-level directories to include in validation */\n directories: string[];\n /** File patterns to match (from tsconfig include) */\n filePatterns: string[];\n /** Patterns to exclude from validation */\n excludePatterns: string[];\n /** Whether spx.config validation path filters narrowed this scope */\n filteredByValidationPaths?: boolean;\n /** Whether the narrowed scope came from an include path, not only excludes */\n filteredByValidationPathIncludes?: boolean;\n /** Whether include filters were declared but did not match the configured tool scope */\n filteredByValidationPathNoMatches?: boolean;\n}\n\n// =============================================================================\n// EXECUTION MODE\n// =============================================================================\n\n/**\n * Execution mode constants.\n */\nexport const EXECUTION_MODES = {\n /** Read-only mode - report errors without fixing */\n READ: \"read\",\n /** Write mode - fix errors when possible (e.g., eslint --fix) */\n WRITE: \"write\",\n} as const;\n\n/** Type for execution mode values */\nexport type ExecutionMode = (typeof EXECUTION_MODES)[keyof typeof EXECUTION_MODES];\n\n// =============================================================================\n// VALIDATION CONTEXT\n// =============================================================================\n\n/**\n * Context object passed to validation steps.\n *\n * Contains all information needed to execute a validation step,\n * enabling pure functions that don't rely on global state.\n */\nexport interface ValidationContext {\n /** Root directory of the project being validated */\n projectRoot: string;\n /** Execution mode (read-only or write/fix) */\n mode?: ExecutionMode;\n /** Validation scope (full or production) */\n scope: ValidationScope;\n /** Scope configuration derived from tsconfig */\n scopeConfig: ScopeConfig;\n /** Which validations are enabled */\n enabledValidations: Partial<Record<string, boolean>>;\n /** Specific files to validate (if file-specific mode) */\n validatedFiles?: string[];\n /** Whether running in file-specific mode */\n isFileSpecificMode: boolean;\n /** ESLint flat config file name, determined by language detection */\n eslintConfigFile?: string;\n}\n\n// =============================================================================\n// VALIDATION RESULTS\n// =============================================================================\n\n/**\n * Result from a validation step.\n *\n * All validation steps return this structure to enable consistent\n * result handling and progress reporting.\n */\nexport interface ValidationStepResult {\n /** Whether the validation passed */\n success: boolean;\n /** Error message if validation failed */\n error?: string;\n /** Duration of the validation step in milliseconds */\n duration: number;\n /** Whether the step was skipped (e.g., tool not available) */\n skipped?: boolean;\n}\n\n/**\n * Result from circular dependency validation.\n *\n * Extends ValidationStepResult with circular dependency details.\n */\nexport interface CircularDependencyResult {\n /** Whether no circular dependencies were found */\n success: boolean;\n /** Error message if circular dependencies found */\n error?: string;\n /** The circular dependency cycles found */\n circularDependencies?: string[][];\n}\n\n// =============================================================================\n// VALIDATION STEP INTERFACE\n// =============================================================================\n\n/**\n * Definition of a validation step.\n *\n * Validation steps are pluggable units that can be enabled/disabled\n * and executed in sequence.\n */\nexport interface ValidationStep {\n /** Unique identifier for the step */\n id: string;\n /** Human-readable name for progress reporting */\n name: string;\n /** Description shown during execution */\n description: string;\n /** Function to determine if step should run */\n enabled: (context: ValidationContext) => boolean;\n /** Function to execute the validation */\n execute: (context: ValidationContext) => Promise<ValidationStepResult>;\n}\n","/**\n * Output forwarding for validation subprocesses.\n *\n * Validation tools write through the parent process so CLI lifecycle handlers\n * can observe broken pipes and terminate tracked children.\n *\n * @module validation/steps/subprocess-output\n */\n\nimport type { Readable } from \"node:stream\";\n\nexport const VALIDATION_SUBPROCESS_EVENTS = {\n CLOSE: \"close\",\n DATA: \"data\",\n DRAIN: \"drain\",\n ERROR: \"error\",\n} as const;\n\nexport interface ValidationSubprocessOutputStreams {\n readonly stdout: ValidationWritableStream;\n readonly stderr: ValidationWritableStream;\n}\n\nexport interface ValidationWritableStream {\n write(chunk: string | Uint8Array): boolean;\n once?(event: typeof VALIDATION_SUBPROCESS_EVENTS.DRAIN, listener: () => void): unknown;\n}\n\nexport interface ValidationSubprocessWithOutput {\n readonly stdout?: Readable | null;\n readonly stderr?: Readable | null;\n}\n\nexport const defaultValidationSubprocessOutputStreams: ValidationSubprocessOutputStreams = {\n stdout: process.stdout,\n stderr: process.stderr,\n};\n\nexport function forwardValidationSubprocessOutput(\n child: ValidationSubprocessWithOutput,\n streams: ValidationSubprocessOutputStreams = defaultValidationSubprocessOutputStreams,\n): void {\n child.stdout?.on(VALIDATION_SUBPROCESS_EVENTS.DATA, (chunk: string | Uint8Array) => {\n forwardChunkWithBackpressure(child.stdout, streams.stdout, chunk);\n });\n\n child.stderr?.on(VALIDATION_SUBPROCESS_EVENTS.DATA, (chunk: string | Uint8Array) => {\n forwardChunkWithBackpressure(child.stderr, streams.stderr, chunk);\n });\n}\n\nfunction forwardChunkWithBackpressure(\n source: Readable | null | undefined,\n stream: ValidationWritableStream,\n chunk: string | Uint8Array,\n): void {\n const ready = stream.write(chunk);\n if (ready || stream.once === undefined || source === null || source === undefined) {\n return;\n }\n\n source.pause();\n stream.once(VALIDATION_SUBPROCESS_EVENTS.DRAIN, () => {\n source.resume();\n });\n}\n","/**\n * ESLint validation command.\n *\n * Runs ESLint for code quality checks.\n */\nimport { resolveConfig } from \"@/config/index\";\nimport {\n VALIDATION_PATH_TOOL_SUBSECTIONS,\n type ValidationConfig,\n validationConfigDescriptor,\n} from \"@/validation/config/descriptor\";\nimport {\n applyValidationPathFilterToScope,\n pathPassesValidationFilter,\n toProjectRelativeValidationPath,\n validationPathFilterForTool,\n} from \"@/validation/config/path-filter\";\nimport { getTypeScriptScope } from \"@/validation/config/scope\";\nimport { detectTypeScript, discoverTool, formatSkipMessage } from \"@/validation/discovery/index\";\nimport { validateESLint } from \"@/validation/steps/eslint\";\nimport { VALIDATION_SCOPES, type ValidationContext } from \"@/validation/types\";\nimport {\n formatTypeScriptAbsentSkipMessage,\n formatValidationPathsNoTargetsSkipMessage,\n VALIDATION_COMMAND_OUTPUT,\n VALIDATION_STAGE_DISPLAY_NAMES,\n} from \"./messages\";\nimport type { LintCommandOptions, ValidationCommandResult } from \"./types\";\n\nconst TYPESCRIPT_ABSENT_MESSAGE = formatTypeScriptAbsentSkipMessage(VALIDATION_STAGE_DISPLAY_NAMES.ESLINT);\nconst MISSING_CONFIG_MESSAGE = VALIDATION_COMMAND_OUTPUT.ESLINT_MISSING_CONFIG;\nconst ESLINT_CONFIG_ERROR_MESSAGE = `${VALIDATION_STAGE_DISPLAY_NAMES.ESLINT}: ✗ config error`;\nconst VALIDATION_PATHS_NO_TARGETS_MESSAGE = formatValidationPathsNoTargetsSkipMessage(\n VALIDATION_STAGE_DISPLAY_NAMES.ESLINT,\n);\n\n/**\n * Run ESLint validation.\n *\n * Gates ESLint execution on TypeScript language detection. ESLint runs only\n * when `tsconfig.json` is present AND an ESLint flat config file exists. A\n * project with `tsconfig.json` but no ESLint config produces a non-zero exit\n * with a descriptive error; a project without `tsconfig.json` skips cleanly.\n *\n * @param options - Command options\n * @returns Command result with exit code and output\n */\nexport async function lintCommand(options: LintCommandOptions): Promise<ValidationCommandResult> {\n const { cwd, scope = \"full\", files, fix, outputStreams, quiet } = options;\n const startTime = Date.now();\n\n // Gate 1: language detection. No TypeScript = skip cleanly.\n const tsDetection = detectTypeScript(cwd);\n if (!tsDetection.present) {\n return {\n exitCode: 0,\n output: quiet ? \"\" : TYPESCRIPT_ABSENT_MESSAGE,\n durationMs: Date.now() - startTime,\n };\n }\n\n const eslintConfigFile = scope === VALIDATION_SCOPES.PRODUCTION\n ? tsDetection.productionEslintConfigFile ?? tsDetection.eslintConfigFile\n : tsDetection.eslintConfigFile;\n\n // Gate 2: ESLint flat config must exist when TypeScript is present.\n if (eslintConfigFile === undefined) {\n return {\n exitCode: 1,\n output: MISSING_CONFIG_MESSAGE,\n durationMs: Date.now() - startTime,\n };\n }\n\n const loaded = await resolveConfig(cwd, [validationConfigDescriptor]);\n if (!loaded.ok) {\n return {\n exitCode: 1,\n output: `${ESLINT_CONFIG_ERROR_MESSAGE} — ${loaded.error}`,\n durationMs: Date.now() - startTime,\n };\n }\n const validationConfig = loaded.value[validationConfigDescriptor.section] as ValidationConfig;\n const validationPathFilter = validationPathFilterForTool(\n validationConfig.paths,\n VALIDATION_PATH_TOOL_SUBSECTIONS.ESLINT,\n );\n const scopeConfig = applyValidationPathFilterToScope(\n getTypeScriptScope(scope, cwd),\n validationPathFilter,\n );\n const validatedFiles = files\n ?.map((file) => toProjectRelativeValidationPath(cwd, file))\n .filter((file) => pathPassesValidationFilter(file, validationPathFilter));\n\n if (\n scopeConfig.filteredByValidationPathNoMatches\n || (files !== undefined && files.length > 0 && validatedFiles?.length === 0)\n ) {\n return {\n exitCode: 0,\n output: quiet ? \"\" : VALIDATION_PATHS_NO_TARGETS_MESSAGE,\n durationMs: Date.now() - startTime,\n };\n }\n\n // Gate 3: tool discovery — ensure ESLint itself is available somewhere.\n const toolResult = await discoverTool(\"eslint\", { projectRoot: cwd });\n if (!toolResult.found) {\n const skipMessage = formatSkipMessage(VALIDATION_STAGE_DISPLAY_NAMES.ESLINT, toolResult);\n return { exitCode: 0, output: skipMessage, durationMs: Date.now() - startTime };\n }\n\n // Build validation context\n const context: ValidationContext = {\n projectRoot: cwd,\n scope,\n scopeConfig,\n mode: fix ? \"write\" : \"read\",\n enabledValidations: { ESLINT: true },\n validatedFiles,\n isFileSpecificMode: Boolean(validatedFiles && validatedFiles.length > 0),\n eslintConfigFile,\n };\n\n // Run ESLint validation\n const result = await validateESLint(context, undefined, outputStreams);\n const durationMs = Date.now() - startTime;\n\n // Map result to command output\n if (result.skipped) {\n const output = quiet ? \"\" : VALIDATION_PATHS_NO_TARGETS_MESSAGE;\n return { exitCode: 0, output, durationMs };\n } else if (result.success) {\n const output = quiet ? \"\" : VALIDATION_COMMAND_OUTPUT.ESLINT_SUCCESS;\n return { exitCode: 0, output, durationMs };\n } else {\n const output = result.error ?? VALIDATION_COMMAND_OUTPUT.ESLINT_FAILURE;\n return { exitCode: 1, output, durationMs };\n }\n}\n","import { readFile } from \"node:fs/promises\";\nimport { isAbsolute, relative, resolve } from \"node:path\";\n\nimport { DEFAULT_SCOPE_CONFIG } from \"@/lib/file-inclusion/config\";\nimport { EMPTY_IGNORE_READER } from \"@/lib/file-inclusion/ignore-source\";\nimport { artifactDirectoryLayer, hiddenPrefixLayer } from \"@/lib/file-inclusion/layer-sequence\";\nimport { runPipeline } from \"@/lib/file-inclusion/pipeline\";\nimport type { ScopeEntry } from \"@/lib/file-inclusion/types\";\nimport { type ValidationPathConfig } from \"@/validation/config/descriptor\";\n\nimport { type LiteralConfig, literalConfigDescriptor, resolveAllowlist } from \"./config\";\nimport {\n buildIndex,\n collectLiterals,\n defaultVisitorKeys,\n type DetectionResult,\n detectReuse,\n type LiteralOccurrence,\n} from \"./detector\";\nimport { isTestFile, isTypescriptSource } from \"./walker\";\n\nexport { literalConfigDescriptor, resolveAllowlist } from \"./config\";\nexport type { LiteralConfig } from \"./config\";\nexport {\n buildIndex,\n collectLiterals,\n defaultVisitorKeys,\n detectReuse,\n FIXTURE_WRITER_CALLS,\n LITERAL_KIND,\n MODULE_NAMING_SKIP,\n parseLiteralReuseResult,\n REMEDIATION,\n} from \"./detector\";\nexport type {\n DetectionResult,\n DupeFinding,\n LiteralIndex,\n LiteralKind,\n LiteralLocation,\n LiteralOccurrence,\n Remediation,\n ReuseFinding,\n VisitorKeysMap,\n} from \"./detector\";\n\nexport interface ValidateLiteralReuseInput {\n readonly productDir: string;\n readonly files?: readonly string[];\n readonly config?: LiteralConfig;\n readonly pathConfig?: ValidationPathConfig;\n}\n\nexport interface ValidateLiteralReuseResult {\n readonly findings: DetectionResult;\n readonly indexedOccurrencesByFile: ReadonlyMap<string, readonly LiteralOccurrence[]>;\n}\n\nconst PATH_PREFIX_SEPARATOR = \"/\";\n\nexport const DEFAULT_LITERAL_COLLECT_OPTIONS = {\n visitorKeys: defaultVisitorKeys,\n minStringLength: literalConfigDescriptor.defaults.minStringLength,\n minNumberDigits: literalConfigDescriptor.defaults.minNumberDigits,\n} as const;\n\nexport function createEmptyLiteralAllowlist(): ReadonlySet<string> {\n return new Set();\n}\n\nfunction normalizePathPrefix(prefix: string): string {\n const posix = prefix.split(/[\\\\/]/g).join(PATH_PREFIX_SEPARATOR);\n return posix.endsWith(PATH_PREFIX_SEPARATOR) ? posix : `${posix}${PATH_PREFIX_SEPARATOR}`;\n}\n\nfunction applyPathFilter(\n entries: readonly ScopeEntry[],\n pathConfig: ValidationPathConfig | undefined,\n): readonly ScopeEntry[] {\n if (pathConfig === undefined) {\n return entries;\n }\n const includePrefixes = (pathConfig.include ?? []).map(normalizePathPrefix);\n const excludePrefixes = (pathConfig.exclude ?? []).map(normalizePathPrefix);\n return entries.filter((entry) => {\n if (\n includePrefixes.length > 0\n && !includePrefixes.some((p) => entry.path.startsWith(p))\n ) {\n return false;\n }\n if (excludePrefixes.some((p) => entry.path.startsWith(p))) {\n return false;\n }\n return true;\n });\n}\n\nexport async function validateLiteralReuse(\n input: ValidateLiteralReuseInput,\n): Promise<ValidateLiteralReuseResult> {\n const config = input.config ?? literalConfigDescriptor.defaults;\n\n const request = input.files\n ? {\n explicit: input.files.map((f) => {\n const abs = isAbsolute(f) ? f : resolve(input.productDir, f);\n return relative(input.productDir, abs).split(/[\\\\/]/g).join(\"/\");\n }),\n }\n : { walkRoot: input.productDir };\n\n const scope = await runPipeline(\n [artifactDirectoryLayer, hiddenPrefixLayer],\n input.productDir,\n request,\n DEFAULT_SCOPE_CONFIG,\n EMPTY_IGNORE_READER,\n );\n\n const filtered = applyPathFilter(scope.included, input.pathConfig);\n\n const candidateFiles = filtered\n .filter((entry) => isTypescriptSource(entry.path))\n .map((entry) => resolve(input.productDir, entry.path));\n\n const collectOptions = {\n visitorKeys: defaultVisitorKeys,\n minStringLength: config.minStringLength,\n minNumberDigits: config.minNumberDigits,\n };\n\n const srcOccurrences: LiteralOccurrence[] = [];\n const testOccurrencesByFile = new Map<string, readonly LiteralOccurrence[]>();\n const indexedOccurrencesByFile = new Map<string, readonly LiteralOccurrence[]>();\n\n for (const abs of candidateFiles) {\n const rel = relative(input.productDir, abs).split(/[\\\\/]/g).join(\"/\");\n\n const content = await readSafe(abs);\n if (content === null) continue;\n\n const occurrences = collectLiterals(content, rel, collectOptions);\n indexedOccurrencesByFile.set(rel, occurrences);\n if (isTestFile(rel)) {\n testOccurrencesByFile.set(rel, occurrences);\n } else {\n srcOccurrences.push(...occurrences);\n }\n }\n\n const srcIndex = buildIndex(srcOccurrences);\n const findings = detectReuse({\n srcIndex,\n testOccurrencesByFile,\n allowlist: resolveAllowlist(config),\n });\n\n return { findings, indexedOccurrencesByFile };\n}\n\nasync function readSafe(path: string): Promise<string | null> {\n try {\n return await readFile(path, \"utf8\");\n } catch (err: unknown) {\n if (typeof err === \"object\" && err !== null && \"code\" in err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === \"ENOENT\" || code === \"EISDIR\") return null;\n }\n throw err;\n }\n}\n","import type { IgnoreSourcePredicateConfig, LayerDecision } from \"../types\";\n\nexport const IGNORE_SOURCE_LAYER = \"ignore-source\";\nconst LAYER = IGNORE_SOURCE_LAYER;\n\nexport function ignoreSourcePredicate(\n path: string,\n config: IgnoreSourcePredicateConfig,\n): LayerDecision {\n const entry = config.reader.matchedEntry(path);\n if (entry === undefined) {\n return { matched: false, layer: LAYER };\n }\n return { matched: true, layer: LAYER, detail: entry.segment };\n}\n","import { artifactDirectoryPredicate } from \"./predicates/artifact-directory\";\nimport { hiddenPrefixPredicate } from \"./predicates/hidden-prefix\";\nimport { ignoreSourcePredicate } from \"./predicates/ignore-source\";\nimport type { ArtifactDirectoryConfig, HiddenPrefixConfig, IgnoreSourcePredicateConfig } from \"./types\";\nimport type { LayerContext, LayerDecision, LayerEntry } from \"./types\";\n\nfunction makeLayer<C>(\n extractConfig: (ctx: LayerContext) => C,\n predicate: (path: string, config: C) => LayerDecision,\n): LayerEntry {\n return {\n extractConfig,\n predicate: (path, config) => predicate(path, config as C),\n };\n}\n\nexport const artifactDirectoryLayer: LayerEntry = makeLayer(\n (ctx): ArtifactDirectoryConfig => ({ artifactDirectories: ctx.config.artifactDirectories }),\n artifactDirectoryPredicate,\n);\n\nexport const hiddenPrefixLayer: LayerEntry = makeLayer(\n (ctx): HiddenPrefixConfig => ({ hiddenPrefix: ctx.config.hiddenPrefix }),\n hiddenPrefixPredicate,\n);\n\nexport const ignoreSourceLayer: LayerEntry = makeLayer(\n (ctx): IgnoreSourcePredicateConfig => ({ reader: ctx.ignoreReader }),\n ignoreSourcePredicate,\n);\n\nexport const LAYER_SEQUENCE: readonly LayerEntry[] = [\n artifactDirectoryLayer,\n hiddenPrefixLayer,\n ignoreSourceLayer,\n];\n","import type { Dirent } from \"node:fs\";\nimport { readdir } from \"node:fs/promises\";\nimport { join, relative, sep } from \"node:path\";\n\nimport { createIgnoreSourceReader } from \"./ignore-source\";\nimport type { IgnoreSourceReader } from \"./ignore-source\";\nimport { LAYER_SEQUENCE } from \"./layer-sequence\";\nimport type {\n LayerContext,\n LayerDecision,\n LayerEntry,\n ScopeEntry,\n ScopeRequest,\n ScopeResolverConfig,\n ScopeResult,\n} from \"./types\";\n\nexport { LayerEntry, ScopeEntry, ScopeRequest, ScopeResolverConfig, ScopeResult };\nexport type { LayerContext, LayerDecision };\n\nexport const EXPLICIT_OVERRIDE_LAYER = \"explicit-override\" as const;\n\nfunction isNodeError(err: unknown): err is NodeJS.ErrnoException {\n return err instanceof Error && \"code\" in err;\n}\n\nasync function collectPaths(\n absoluteDir: string,\n projectRoot: string,\n result: string[],\n artifactDirs: ReadonlySet<string>,\n): Promise<void> {\n let dirEntries: Dirent<string>[];\n try {\n dirEntries = await readdir(absoluteDir, { withFileTypes: true });\n } catch (err) {\n if (isNodeError(err) && (err.code === \"ENOENT\" || err.code === \"ENOTDIR\")) {\n return;\n }\n throw err;\n }\n for (const entry of dirEntries) {\n if (entry.isDirectory()) {\n if (artifactDirs.has(entry.name)) continue;\n const absolutePath = join(absoluteDir, entry.name);\n await collectPaths(absolutePath, projectRoot, result, artifactDirs);\n } else if (entry.isFile()) {\n const absolutePath = join(absoluteDir, entry.name);\n const rel = relative(projectRoot, absolutePath);\n result.push(sep === \"/\" ? rel : rel.split(sep).join(\"/\"));\n }\n }\n}\n\nexport async function resolveScope(\n projectRoot: string,\n request: ScopeRequest,\n config: ScopeResolverConfig,\n): Promise<ScopeResult> {\n const ignoreReader = createIgnoreSourceReader(projectRoot, {\n ignoreSourceFilename: config.ignoreSourceFilename,\n specTreeRootSegment: config.specTreeRootSegment,\n });\n return runPipeline(LAYER_SEQUENCE, projectRoot, request, config, ignoreReader);\n}\n\nexport async function runPipeline(\n sequence: readonly LayerEntry[],\n projectRoot: string,\n request: ScopeRequest,\n config: ScopeResolverConfig,\n ignoreReader: IgnoreSourceReader,\n): Promise<ScopeResult> {\n const layerCtx: LayerContext = { config, ignoreReader };\n const layerPairs = sequence.map((entry) => ({\n entry,\n layerConfig: entry.extractConfig(layerCtx),\n }));\n\n const included: ScopeEntry[] = [];\n const excluded: ScopeEntry[] = [];\n\n const explicitPaths = request.explicit ?? [];\n const explicitPathSet = new Set<string>(explicitPaths);\n\n for (const path of explicitPaths) {\n included.push({\n path,\n decisionTrail: [{ matched: true, layer: EXPLICIT_OVERRIDE_LAYER }],\n });\n }\n\n if (request.walkRoot !== undefined) {\n const artifactDirs = new Set(config.artifactDirectories);\n const allPaths: string[] = [];\n await collectPaths(request.walkRoot, projectRoot, allPaths, artifactDirs);\n\n for (const path of allPaths) {\n if (explicitPathSet.has(path)) continue;\n\n const trail: LayerDecision[] = [];\n for (const { entry, layerConfig } of layerPairs) {\n const decision = entry.predicate(path, layerConfig);\n if (decision.matched) {\n trail.push(decision);\n }\n }\n\n if (trail.length > 0) {\n excluded.push({ path, decisionTrail: trail });\n } else {\n included.push({ path, decisionTrail: [] });\n }\n }\n }\n\n return { included, excluded };\n}\n","import { parse as parseTypeScript } from \"@typescript-eslint/parser\";\nimport { visitorKeys as typescriptVisitorKeys } from \"@typescript-eslint/visitor-keys\";\n\nimport { SPEC_TREE_ENV_FIXTURE_WRITER_METHODS } from \"@/domains/spec/fixture-writer-methods\";\n\nexport const LITERAL_KIND = {\n STRING: \"string\",\n NUMBER: \"number\",\n} as const;\n\nexport type LiteralKind = (typeof LITERAL_KIND)[keyof typeof LITERAL_KIND];\n\nexport interface LiteralLocation {\n readonly file: string;\n readonly line: number;\n}\n\nexport interface LiteralOccurrence {\n readonly kind: LiteralKind;\n readonly value: string;\n readonly loc: LiteralLocation;\n}\n\nexport type LiteralIndex = ReadonlyMap<string, readonly LiteralLocation[]>;\n\nexport type VisitorKeysMap = Record<string, readonly string[] | undefined>;\n\nexport const REMEDIATION = {\n IMPORT_FROM_SOURCE: \"import-from-source\",\n REFACTOR_TO_SOURCE_OR_GENERATOR: \"refactor-to-source-or-generator\",\n} as const;\n\nexport type Remediation = (typeof REMEDIATION)[keyof typeof REMEDIATION];\n\nexport interface ReuseFinding {\n readonly test: LiteralLocation;\n readonly kind: LiteralKind;\n readonly value: string;\n readonly src: readonly LiteralLocation[];\n readonly remediation: typeof REMEDIATION.IMPORT_FROM_SOURCE;\n}\n\nexport interface DupeFinding {\n readonly test: LiteralLocation;\n readonly kind: LiteralKind;\n readonly value: string;\n readonly otherTests: readonly LiteralLocation[];\n readonly remediation: typeof REMEDIATION.REFACTOR_TO_SOURCE_OR_GENERATOR;\n}\n\nexport interface DetectionResult {\n readonly srcReuse: readonly ReuseFinding[];\n readonly testDupe: readonly DupeFinding[];\n}\n\nexport interface CollectLiteralsOptions {\n readonly visitorKeys: VisitorKeysMap;\n readonly minStringLength: number;\n readonly minNumberDigits: number;\n}\n\nexport interface DetectReuseInput {\n readonly srcIndex: LiteralIndex;\n readonly testOccurrencesByFile: ReadonlyMap<string, readonly LiteralOccurrence[]>;\n readonly allowlist: ReadonlySet<string>;\n}\n\nexport const defaultVisitorKeys: VisitorKeysMap = typescriptVisitorKeys;\n\nexport const MODULE_NAMING_SKIP: Record<string, ReadonlySet<string>> = {\n ImportDeclaration: new Set([\"source\"]),\n ExportNamedDeclaration: new Set([\"source\"]),\n ExportAllDeclaration: new Set([\"source\"]),\n ImportExpression: new Set([\"source\"]),\n TSImportType: new Set([\"source\", \"argument\"]),\n TSExternalModuleReference: new Set([\"expression\"]),\n};\n\nconst EMPTY_SKIP: ReadonlySet<string> = new Set();\nconst TEST_PATH_SEGMENT = \"/tests/\";\nconst WINDOWS_TEST_PATH_SEGMENT = \"\\\\tests\\\\\";\nconst TEST_FILE_MARKER = \".test.\";\nconst CALL_EXPRESSION_TYPE = \"CallExpression\";\nconst VARIABLE_DECLARATOR_TYPE = \"VariableDeclarator\";\nconst IDENTIFIER_TYPE = \"Identifier\";\nconst LITERAL_TYPE = \"Literal\";\nconst MEMBER_EXPRESSION_TYPE = \"MemberExpression\";\nconst TEMPLATE_ELEMENT_TYPE = \"TemplateElement\";\nconst FUNCTION_NODE_TYPES: ReadonlySet<string> = new Set([\n \"ArrowFunctionExpression\",\n \"FunctionDeclaration\",\n \"FunctionExpression\",\n]);\nexport const FIXTURE_WRITER_CALLS: ReadonlySet<string> = new Set(\n SPEC_TREE_ENV_FIXTURE_WRITER_METHODS,\n);\nconst FIXTURE_DATA_DIRECT_SEGMENTS: ReadonlySet<string> = new Set([\"fixture\", \"payload\"]);\nconst FIXTURE_DATA_ROLE_SEGMENTS: ReadonlySet<string> = new Set([\n \"verdict\",\n \"session\",\n \"frontmatter\",\n \"xml\",\n \"yaml\",\n \"json\",\n \"source\",\n]);\nconst FIXTURE_DATA_CONTEXT_SEGMENTS: ReadonlySet<string> = new Set([\"path\", \"tree\"]);\n// Used through String#match; match resets global regex state instead of reading lastIndex.\nconst IDENTIFIER_SEGMENT_PATTERN = /[A-Z]+(?=[A-Z][a-z]|$)|[A-Z]?[a-z]+|[0-9]+/g;\n\ninterface Node {\n readonly type: string;\n readonly loc?: { readonly start?: { readonly line?: number } };\n readonly value?: unknown;\n readonly raw?: unknown;\n readonly [key: string]: unknown;\n}\n\ninterface WalkAncestor {\n readonly node: Node;\n}\n\ninterface WalkContext {\n readonly filename: string;\n readonly isTestFixtureFile: boolean;\n}\n\nexport function collectLiterals(\n source: string,\n filename: string,\n options: CollectLiteralsOptions,\n): LiteralOccurrence[] {\n const ast = parseTypeScript(source, {\n loc: true,\n range: true,\n comment: false,\n jsx: true,\n ecmaVersion: \"latest\",\n sourceType: \"module\",\n }) as unknown as Node;\n const out: LiteralOccurrence[] = [];\n const ancestors: WalkAncestor[] = [];\n walk(ast, { filename, isTestFixtureFile: isTestLikeFile(filename) }, ancestors, options, out);\n return out;\n}\n\nfunction walk(\n node: Node,\n context: WalkContext,\n ancestors: WalkAncestor[],\n options: CollectLiteralsOptions,\n out: LiteralOccurrence[],\n): void {\n emitLiteral(node, context, ancestors, options, out);\n\n const keys = options.visitorKeys[node.type];\n if (!keys) {\n return;\n }\n const skip = MODULE_NAMING_SKIP[node.type] ?? EMPTY_SKIP;\n for (const key of keys) {\n if (skip.has(key)) continue;\n const child = node[key];\n if (Array.isArray(child)) {\n for (const item of child) {\n if (isNode(item)) walkChild(item, node, context, ancestors, options, out);\n }\n } else if (isNode(child)) {\n walkChild(child, node, context, ancestors, options, out);\n }\n }\n}\n\nfunction walkChild(\n node: Node,\n parent: Node,\n context: WalkContext,\n ancestors: WalkAncestor[],\n options: CollectLiteralsOptions,\n out: LiteralOccurrence[],\n): void {\n // Shared stack mutation relies on synchronous traversal.\n ancestors.push({ node: parent });\n try {\n walk(node, context, ancestors, options, out);\n } finally {\n ancestors.pop();\n }\n}\n\nfunction isNode(value: unknown): value is Node {\n return typeof value === \"object\" && value !== null && typeof (value as Node).type === \"string\";\n}\n\nfunction emitLiteral(\n node: Node,\n context: WalkContext,\n ancestors: readonly WalkAncestor[],\n options: CollectLiteralsOptions,\n out: LiteralOccurrence[],\n): void {\n if (node.type !== LITERAL_TYPE && node.type !== TEMPLATE_ELEMENT_TYPE) {\n return;\n }\n if (isFixtureDataLiteral(context, ancestors)) {\n return;\n }\n const line = node.loc?.start?.line ?? 0;\n\n if (node.type === LITERAL_TYPE) {\n if (typeof node.value === \"string\") {\n if (node.value.length >= options.minStringLength) {\n out.push({ kind: \"string\", value: node.value, loc: { file: context.filename, line } });\n }\n } else if (typeof node.value === \"number\") {\n const raw = typeof node.raw === \"string\" ? node.raw : String(node.value);\n if (isMeaningfulNumber(raw, options.minNumberDigits)) {\n out.push({ kind: \"number\", value: String(node.value), loc: { file: context.filename, line } });\n }\n }\n return;\n }\n\n if (node.type === TEMPLATE_ELEMENT_TYPE) {\n const value = node.value as { readonly cooked?: string } | undefined;\n const cooked = value?.cooked ?? \"\";\n if (cooked.length >= options.minStringLength) {\n out.push({ kind: \"string\", value: cooked, loc: { file: context.filename, line } });\n }\n }\n}\n\nfunction isTestLikeFile(filename: string): boolean {\n return filename.includes(TEST_PATH_SEGMENT)\n || filename.includes(WINDOWS_TEST_PATH_SEGMENT)\n || filename.includes(TEST_FILE_MARKER);\n}\n\nfunction isFixtureDataLiteral(\n context: WalkContext,\n ancestors: readonly WalkAncestor[],\n): boolean {\n if (!context.isTestFixtureFile) {\n return false;\n }\n return isInsideFixtureWriterArgument(ancestors) || isInsideFixtureDataVariable(ancestors);\n}\n\nfunction isInsideFixtureWriterArgument(ancestors: readonly WalkAncestor[]): boolean {\n // Scan every call ancestor so wrappers around fixture-writer calls do not hide direct writer arguments.\n // Payload helpers inside a fixture writer remain setup data unless a nested function boundary intervenes.\n for (let index = ancestors.length - 1; index >= 0; index -= 1) {\n const ancestor = ancestors[index];\n if (ancestor.node.type !== CALL_EXPRESSION_TYPE) {\n continue;\n }\n const callName = getCallName(ancestor.node);\n if (callName === undefined || !isFixtureWriterCall(callName)) {\n continue;\n }\n if (hasNestedFunctionBetween(ancestors, index)) {\n continue;\n }\n return true;\n }\n return false;\n}\n\nfunction isFixtureWriterCall(callName: string): boolean {\n return FIXTURE_WRITER_CALLS.has(callName);\n}\n\nfunction isInsideFixtureDataVariable(ancestors: readonly WalkAncestor[]): boolean {\n for (let index = ancestors.length - 1; index >= 0; index -= 1) {\n const ancestor = ancestors[index];\n if (ancestor.node.type !== VARIABLE_DECLARATOR_TYPE) {\n continue;\n }\n if (hasNestedFunctionBetween(ancestors, index)) {\n continue;\n }\n const variableName = getFixtureDataDeclaratorName(ancestor.node);\n if (variableName !== undefined && isFixtureDataVariableName(variableName)) {\n return true;\n }\n }\n return false;\n}\n\nfunction hasNestedFunctionBetween(\n ancestors: readonly WalkAncestor[],\n ancestorIndex: number,\n): boolean {\n // The current literal node is passed separately, so this range checks only ancestors between call and literal.\n for (let index = ancestorIndex + 1; index < ancestors.length; index += 1) {\n if (FUNCTION_NODE_TYPES.has(ancestors[index].node.type)) {\n return true;\n }\n }\n return false;\n}\n\nfunction getFixtureDataDeclaratorName(node: Node): string | undefined {\n const bindingName = getIdentifierName(node.id);\n if (bindingName !== undefined) {\n return bindingName;\n }\n // Destructuring defaults are classified by the fixture object they read from.\n // Opaque initializer expressions keep their literals in the occurrence index.\n return getIdentifierName(node.init);\n}\n\nfunction isFixtureDataVariableName(variableName: string): boolean {\n const segments = splitIdentifierName(variableName);\n if (segments.length === 0) {\n return false;\n }\n // Tier 1: explicit fixture markers always denote test-authored data.\n if (segments.some((segment) => FIXTURE_DATA_DIRECT_SEGMENTS.has(segment))) {\n return true;\n }\n // Tier 2 and Tier 3 require at least one fixture role word.\n if (!segments.some((segment) => FIXTURE_DATA_ROLE_SEGMENTS.has(segment))) {\n return false;\n }\n // Tier 2: single-role and compound-role names describe fixture payloads.\n if (segments.every((segment) => FIXTURE_DATA_ROLE_SEGMENTS.has(segment))) {\n return true;\n }\n // Tier 3: role/context compounds are fixtures only when the context word is final.\n const finalSegment = segments[segments.length - 1];\n return finalSegment !== undefined && FIXTURE_DATA_CONTEXT_SEGMENTS.has(finalSegment);\n}\n\nfunction splitIdentifierName(variableName: string): readonly string[] {\n return variableName\n .split(\"_\")\n .flatMap((part) => part.match(IDENTIFIER_SEGMENT_PATTERN) ?? [])\n .map((segment) => segment.toLowerCase());\n}\n\nfunction getCallName(node: Node): string | undefined {\n const callee = node.callee;\n if (!isNode(callee)) {\n return undefined;\n }\n if (callee.type === IDENTIFIER_TYPE) {\n return getIdentifierName(callee);\n }\n if (callee.type !== MEMBER_EXPRESSION_TYPE) {\n return undefined;\n }\n const property = callee.property;\n if (isNode(property)) {\n return property.type === IDENTIFIER_TYPE ? getIdentifierName(property) : getLiteralString(property);\n }\n return undefined;\n}\n\nfunction getIdentifierName(value: unknown): string | undefined {\n if (!isNode(value) || value.type !== IDENTIFIER_TYPE) {\n return undefined;\n }\n return typeof value.name === \"string\" ? value.name : undefined;\n}\n\nfunction getLiteralString(value: unknown): string | undefined {\n if (!isNode(value) || value.type !== LITERAL_TYPE) {\n return undefined;\n }\n return typeof value.value === \"string\" ? value.value : undefined;\n}\n\nfunction isMeaningfulNumber(raw: string, minDigits: number): boolean {\n const digits = raw.replace(/[^0-9]/g, \"\");\n return digits.length >= minDigits;\n}\n\nexport function buildIndex(\n occurrences: Iterable<LiteralOccurrence>,\n): LiteralIndex {\n const map = new Map<string, LiteralLocation[]>();\n for (const occ of occurrences) {\n const key = makeKey(occ.kind, occ.value);\n const existing = map.get(key);\n if (existing) {\n existing.push(occ.loc);\n } else {\n map.set(key, [occ.loc]);\n }\n }\n return map;\n}\n\nfunction makeKey(kind: LiteralKind, value: string): string {\n return `${kind}\\0${value}`;\n}\n\nfunction splitKey(key: string): { kind: LiteralKind; value: string } {\n const idx = key.indexOf(\"\\0\");\n return { kind: key.slice(0, idx) as LiteralKind, value: key.slice(idx + 1) };\n}\n\nexport function detectReuse(input: DetectReuseInput): DetectionResult {\n const srcReuse: ReuseFinding[] = [];\n const testDupe: DupeFinding[] = [];\n\n const testIndex = new Map<string, Map<string, LiteralLocation[]>>();\n for (const [file, occurrences] of input.testOccurrencesByFile) {\n for (const occ of occurrences) {\n if (input.allowlist.has(occ.value)) continue;\n const key = makeKey(occ.kind, occ.value);\n let byFile = testIndex.get(key);\n if (!byFile) {\n byFile = new Map<string, LiteralLocation[]>();\n testIndex.set(key, byFile);\n }\n const locsInFile = byFile.get(file);\n if (locsInFile) locsInFile.push(occ.loc);\n else byFile.set(file, [occ.loc]);\n }\n }\n\n for (const [key, byFile] of testIndex) {\n const { kind, value } = splitKey(key);\n const srcLocs = input.srcIndex.get(key);\n const allTestLocs: LiteralLocation[] = [];\n for (const locs of byFile.values()) allTestLocs.push(...locs);\n\n if (srcLocs && srcLocs.length > 0) {\n for (const testLoc of allTestLocs) {\n srcReuse.push({\n test: testLoc,\n kind,\n value,\n src: srcLocs,\n remediation: REMEDIATION.IMPORT_FROM_SOURCE,\n });\n }\n } else if (byFile.size >= 2) {\n for (let i = 0; i < allTestLocs.length; i += 1) {\n const otherTests = [...allTestLocs.slice(0, i), ...allTestLocs.slice(i + 1)];\n testDupe.push({\n test: allTestLocs[i],\n kind,\n value,\n otherTests,\n remediation: REMEDIATION.REFACTOR_TO_SOURCE_OR_GENERATOR,\n });\n }\n }\n }\n\n return { srcReuse, testDupe };\n}\n\nexport function parseLiteralReuseResult(value: unknown): DetectionResult {\n if (!isPlainObject(value)) {\n throw new Error(\"literal-reuse result must be an object\");\n }\n const obj = value as { srcReuse?: unknown; testDupe?: unknown };\n if (!Array.isArray(obj.srcReuse)) {\n throw new Error(\"literal-reuse result is missing srcReuse array\");\n }\n if (!Array.isArray(obj.testDupe)) {\n throw new Error(\"literal-reuse result is missing testDupe array\");\n }\n for (const f of obj.srcReuse) validateReuseFinding(f);\n for (const f of obj.testDupe) validateDupeFinding(f);\n return { srcReuse: obj.srcReuse as readonly ReuseFinding[], testDupe: obj.testDupe as readonly DupeFinding[] };\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction validateLiteralLocation(value: unknown, context: string): void {\n if (!isPlainObject(value)) throw new Error(`${context} must be an object`);\n if (typeof value[\"file\"] !== \"string\") throw new Error(`${context}.file must be a string`);\n if (typeof value[\"line\"] !== \"number\") throw new Error(`${context}.line must be a number`);\n}\n\nfunction validateKindValue(value: unknown, context: string): void {\n if (!isPlainObject(value)) throw new Error(`${context} must be an object`);\n if (value[\"kind\"] !== \"string\" && value[\"kind\"] !== \"number\") {\n throw new Error(`${context}.kind must be \"string\" or \"number\"`);\n }\n if (typeof value[\"value\"] !== \"string\") {\n throw new Error(`${context}.value must be a string`);\n }\n}\n\nfunction validateReuseFinding(value: unknown): void {\n validateKindValue(value, \"srcReuse finding\");\n const obj = value as Record<string, unknown>;\n validateLiteralLocation(obj[\"test\"], \"srcReuse finding.test\");\n if (!Array.isArray(obj[\"src\"])) throw new Error(\"srcReuse finding.src must be an array\");\n for (const loc of obj[\"src\"]) validateLiteralLocation(loc, \"srcReuse finding.src[i]\");\n if (obj[\"remediation\"] !== REMEDIATION.IMPORT_FROM_SOURCE) {\n throw new Error(`srcReuse finding.remediation must be \"${REMEDIATION.IMPORT_FROM_SOURCE}\"`);\n }\n}\n\nfunction validateDupeFinding(value: unknown): void {\n validateKindValue(value, \"testDupe finding\");\n const obj = value as Record<string, unknown>;\n validateLiteralLocation(obj[\"test\"], \"testDupe finding.test\");\n if (!Array.isArray(obj[\"otherTests\"])) {\n throw new Error(\"testDupe finding.otherTests must be an array\");\n }\n for (const loc of obj[\"otherTests\"]) validateLiteralLocation(loc, \"testDupe finding.otherTests[i]\");\n if (obj[\"remediation\"] !== REMEDIATION.REFACTOR_TO_SOURCE_OR_GENERATOR) {\n throw new Error(\n `testDupe finding.remediation must be \"${REMEDIATION.REFACTOR_TO_SOURCE_OR_GENERATOR}\"`,\n );\n }\n}\n","// Shared production metadata for spec-tree fixture writer methods.\n// Literal validation imports this registry to classify test-authored setup data.\nexport const SPEC_TREE_ENV_FIXTURE_WRITER_METHOD = {\n DECISION: \"writeDecision\",\n NODE: \"writeNode\",\n RAW: \"writeRaw\",\n} as const;\n\nexport type SpecTreeEnvFixtureWriterMethod =\n (typeof SPEC_TREE_ENV_FIXTURE_WRITER_METHOD)[keyof typeof SPEC_TREE_ENV_FIXTURE_WRITER_METHOD];\n\nexport const SPEC_TREE_ENV_FIXTURE_WRITER_METHODS = [\n SPEC_TREE_ENV_FIXTURE_WRITER_METHOD.DECISION,\n SPEC_TREE_ENV_FIXTURE_WRITER_METHOD.NODE,\n SPEC_TREE_ENV_FIXTURE_WRITER_METHOD.RAW,\n] as const satisfies readonly SpecTreeEnvFixtureWriterMethod[];\n","const TYPESCRIPT_EXTENSIONS: ReadonlySet<string> = new Set([\".ts\", \".tsx\"]);\nconst DECLARATION_SUFFIX = \".d.ts\";\n\nexport function isTypescriptSource(path: string): boolean {\n if (path.endsWith(DECLARATION_SUFFIX)) return false;\n const ext = extensionOf(path);\n return TYPESCRIPT_EXTENSIONS.has(ext);\n}\n\nfunction extensionOf(name: string): string {\n const idx = name.lastIndexOf(\".\");\n return idx === -1 ? \"\" : name.slice(idx);\n}\n\nexport function isTestFile(relPath: string): boolean {\n return /\\.test\\.tsx?$/.test(relPath);\n}\n","import { resolveConfig } from \"@/config/index\";\nimport {\n VALIDATION_PATH_TOOL_SUBSECTIONS,\n type ValidationConfig,\n validationConfigDescriptor,\n type ValidationPathConfig,\n} from \"@/validation/config/descriptor\";\nimport { validationPathFilterForTool } from \"@/validation/config/path-filter\";\nimport { detectTypeScript } from \"@/validation/discovery/index\";\nimport { type LiteralConfig } from \"@/validation/literal/config\";\nimport {\n type DetectionResult,\n type DupeFinding,\n type LiteralKind,\n type LiteralLocation,\n type ReuseFinding,\n validateLiteralReuse,\n} from \"@/validation/literal/index\";\n\nexport const LITERAL_PROBLEM_KIND = {\n REUSE: \"reuse\",\n DUPE: \"dupe\",\n} as const;\n\nexport type LiteralProblemKind = (typeof LITERAL_PROBLEM_KIND)[keyof typeof LITERAL_PROBLEM_KIND];\n\nexport const OUTPUT_MODE_NAME = {\n TEXT: \"text\",\n VERBOSE: \"verbose\",\n FILES_WITH_PROBLEMS: \"filesWithProblems\",\n LITERALS: \"literals\",\n JSON: \"json\",\n} as const;\n\nexport const OUTPUT_MODE_NAMES = Object.values(OUTPUT_MODE_NAME);\nexport type OutputModeName = (typeof OUTPUT_MODE_NAMES)[number];\n\nexport const VERBOSE_PROBLEM_LINE_PREFIX = \"line \";\n\nexport interface LiteralCommandOptions {\n readonly cwd: string;\n readonly files?: readonly string[];\n readonly kind?: LiteralProblemKind;\n readonly filesWithProblems?: boolean;\n readonly literals?: boolean;\n readonly verbose?: boolean;\n readonly json?: boolean;\n readonly quiet?: boolean;\n readonly enabled?: boolean;\n readonly config?: LiteralConfig;\n readonly pathConfig?: ValidationPathConfig;\n}\n\nexport interface ValidationCommandResult {\n readonly exitCode: number;\n readonly output: string;\n readonly durationMs: number;\n}\n\nexport const LITERAL_EXIT_CODES = {\n OK: 0,\n FINDINGS: 1,\n CONFIG_ERROR: 2,\n} as const;\nconst TYPESCRIPT_ABSENT_MESSAGE = \"⏭ Skipping Literal (TypeScript not detected in project)\";\nexport const LITERAL_DISABLED_MESSAGE = \"⏭ Skipping Literal (disabled by validation.literal.enabled)\";\nexport const NO_PROBLEMS_MESSAGE = \"Literal: ✓ No problems\";\n\nexport function formatNoProblemsOfKind(kind: LiteralProblemKind): string {\n return `Literal: No problems of type ${kind}`;\n}\n\ninterface LiteralProblem {\n readonly problemKind: LiteralProblemKind;\n readonly literalKind: LiteralKind;\n readonly value: string;\n readonly test: LiteralLocation;\n readonly related: readonly LiteralLocation[];\n}\n\nexport async function literalCommand(\n options: LiteralCommandOptions,\n): Promise<ValidationCommandResult> {\n const start = Date.now();\n\n const tsDetection = detectTypeScript(options.cwd);\n if (!tsDetection.present) {\n return {\n exitCode: LITERAL_EXIT_CODES.OK,\n output: options.quiet ? \"\" : TYPESCRIPT_ABSENT_MESSAGE,\n durationMs: Date.now() - start,\n };\n }\n\n let resolvedEnabled: boolean;\n let resolvedLiteralConfig: LiteralConfig;\n let resolvedPathConfig: ValidationPathConfig;\n if (options.config !== undefined) {\n resolvedEnabled = options.enabled ?? validationConfigDescriptor.defaults.literal.enabled;\n resolvedLiteralConfig = options.config;\n resolvedPathConfig = options.pathConfig ?? validationConfigDescriptor.defaults.paths;\n } else {\n const loaded = await resolveConfig(options.cwd, [validationConfigDescriptor]);\n if (!loaded.ok) {\n return {\n exitCode: LITERAL_EXIT_CODES.CONFIG_ERROR,\n output: `Literal: ✗ config error — ${loaded.error}`,\n durationMs: Date.now() - start,\n };\n }\n const validationConfig = loaded.value[validationConfigDescriptor.section] as ValidationConfig;\n resolvedEnabled = validationConfig.literal.enabled;\n resolvedLiteralConfig = validationConfig.literal.values;\n resolvedPathConfig = validationPathFilterForTool(\n validationConfig.paths,\n VALIDATION_PATH_TOOL_SUBSECTIONS.LITERAL,\n );\n }\n\n if (!resolvedEnabled) {\n return {\n exitCode: LITERAL_EXIT_CODES.OK,\n output: options.quiet ? \"\" : LITERAL_DISABLED_MESSAGE,\n durationMs: Date.now() - start,\n };\n }\n\n const result = await validateLiteralReuse({\n productDir: options.cwd,\n files: options.files,\n config: resolvedLiteralConfig,\n pathConfig: resolvedPathConfig,\n });\n\n const filteredFindings = filterLiteralFindings(result.findings, options.kind);\n const totalProblems = countLiteralProblems(filteredFindings);\n const exitCode = totalProblems === 0 ? LITERAL_EXIT_CODES.OK : LITERAL_EXIT_CODES.FINDINGS;\n\n const output = options.json\n ? JSON.stringify(filteredFindings)\n : options.quiet\n ? \"\"\n : formatLiteralCommandOutput(filteredFindings, options);\n\n return { exitCode, output, durationMs: Date.now() - start };\n}\n\nexport function filterLiteralFindings(\n findings: DetectionResult,\n kind: LiteralProblemKind | undefined,\n): DetectionResult {\n return {\n srcReuse: kind === LITERAL_PROBLEM_KIND.DUPE ? [] : sortReuseFindings(findings.srcReuse),\n testDupe: kind === LITERAL_PROBLEM_KIND.REUSE ? [] : sortDupeFindings(findings.testDupe),\n };\n}\n\nexport function countLiteralProblems(findings: DetectionResult): number {\n return findings.srcReuse.length + findings.testDupe.length;\n}\n\nexport function formatDefaultLiteralProblems(findings: DetectionResult): string {\n return toLiteralProblems(findings)\n .map((problem) =>\n `[${problem.problemKind}] ${formatLiteralValue(problem.literalKind, problem.value)} ${formatLoc(problem.test)}`\n )\n .join(\"\\n\");\n}\n\nexport function formatVerboseLiteralProblems(findings: DetectionResult): string {\n const lines = [\n `Literal: ${\n countLiteralProblems(findings)\n } problems (reuse: ${findings.srcReuse.length}, dupe: ${findings.testDupe.length})`,\n ];\n\n appendVerboseSection(\n lines,\n \"REUSE\",\n findings.srcReuse.map((finding): LiteralProblem => ({\n problemKind: LITERAL_PROBLEM_KIND.REUSE,\n literalKind: finding.kind,\n value: finding.value,\n test: finding.test,\n related: finding.src,\n })),\n );\n appendVerboseSection(\n lines,\n \"DUPE\",\n findings.testDupe.map((finding): LiteralProblem => ({\n problemKind: LITERAL_PROBLEM_KIND.DUPE,\n literalKind: finding.kind,\n value: finding.value,\n test: finding.test,\n related: finding.otherTests,\n })),\n );\n\n return lines.join(\"\\n\");\n}\n\nexport function formatFilesWithProblems(findings: DetectionResult): string {\n return [...new Set(toLiteralProblems(findings).map((problem) => problem.test.file))]\n .sort()\n .join(\"\\n\");\n}\n\nexport function formatLiteralValues(findings: DetectionResult): string {\n const values = new Map<string, { readonly kind: LiteralKind; readonly value: string }>();\n for (const problem of toLiteralProblems(findings)) {\n values.set(`${problem.literalKind}\\0${problem.value}`, {\n kind: problem.literalKind,\n value: problem.value,\n });\n }\n return [...values.values()]\n .sort((left, right) => left.value.localeCompare(right.value) || left.kind.localeCompare(right.kind))\n .map((entry) => formatLiteralValue(entry.kind, entry.value))\n .join(\"\\n\");\n}\n\nfunction formatLiteralCommandOutput(\n findings: DetectionResult,\n options: LiteralCommandOptions,\n): string {\n const totalProblems = countLiteralProblems(findings);\n\n if (totalProblems === 0 && options.kind !== undefined) {\n return formatNoProblemsOfKind(options.kind);\n }\n\n if (totalProblems === 0) {\n return options.filesWithProblems || options.literals || options.verbose ? \"\" : NO_PROBLEMS_MESSAGE;\n }\n\n if (options.filesWithProblems) return formatFilesWithProblems(findings);\n if (options.literals) return formatLiteralValues(findings);\n if (options.verbose) return formatVerboseLiteralProblems(findings);\n return formatDefaultLiteralProblems(findings);\n}\n\nfunction toLiteralProblems(findings: DetectionResult): readonly LiteralProblem[] {\n return [\n ...sortReuseFindings(findings.srcReuse).map((finding): LiteralProblem => ({\n problemKind: LITERAL_PROBLEM_KIND.REUSE,\n literalKind: finding.kind,\n value: finding.value,\n test: finding.test,\n related: finding.src,\n })),\n ...sortDupeFindings(findings.testDupe).map((finding): LiteralProblem => ({\n problemKind: LITERAL_PROBLEM_KIND.DUPE,\n literalKind: finding.kind,\n value: finding.value,\n test: finding.test,\n related: finding.otherTests,\n })),\n ];\n}\n\nfunction appendVerboseSection(\n lines: string[],\n heading: string,\n problems: readonly LiteralProblem[],\n): void {\n const sortedProblems = [...problems].sort(compareLiteralProblems);\n if (sortedProblems.length === 0) return;\n\n lines.push(heading);\n let currentFile: string | undefined;\n for (const problem of sortedProblems) {\n if (problem.test.file !== currentFile) {\n lines.push(problem.test.file);\n currentFile = problem.test.file;\n }\n lines.push(\n ` line ${problem.test.line}: ${formatLiteralValue(problem.literalKind, problem.value)} also in ${\n problem.related.map(formatLoc).join(\", \")\n }`,\n );\n }\n}\n\nfunction sortReuseFindings(findings: readonly ReuseFinding[]): readonly ReuseFinding[] {\n return [...findings].sort(compareFindings);\n}\n\nfunction sortDupeFindings(findings: readonly DupeFinding[]): readonly DupeFinding[] {\n return [...findings].sort(compareFindings);\n}\n\nfunction compareFindings(\n left: { readonly kind: LiteralKind; readonly value: string; readonly test: LiteralLocation },\n right: { readonly kind: LiteralKind; readonly value: string; readonly test: LiteralLocation },\n): number {\n return (\n left.test.file.localeCompare(right.test.file)\n || left.test.line - right.test.line\n || left.kind.localeCompare(right.kind)\n || left.value.localeCompare(right.value)\n );\n}\n\nfunction compareLiteralProblems(left: LiteralProblem, right: LiteralProblem): number {\n return (\n left.test.file.localeCompare(right.test.file)\n || left.test.line - right.test.line\n || left.literalKind.localeCompare(right.literalKind)\n || left.value.localeCompare(right.value)\n );\n}\n\nfunction formatLiteralValue(kind: LiteralKind, value: string): string {\n return kind === \"string\" ? `\"${value}\"` : value;\n}\n\nfunction formatLoc(loc: LiteralLocation): string {\n return `${loc.file}:${loc.line}`;\n}\n","/**\n * TypeScript validation step.\n *\n * Validates TypeScript code using the tsc compiler.\n *\n * @module validation/steps/typescript\n */\n\nimport { existsSync, mkdirSync, rmSync, writeFileSync } from \"node:fs\";\nimport { mkdtemp } from \"node:fs/promises\";\nimport { isAbsolute, join } from \"node:path\";\n\nimport { lifecycleProcessRunner, type ProcessRunner, spawnManagedSubprocess } from \"@/lib/process-lifecycle\";\nimport { TSCONFIG_FILES } from \"../config/scope\";\nimport type { ScopeConfig, ValidationScope } from \"../types\";\nimport { VALIDATION_SCOPES } from \"../types\";\nimport {\n defaultValidationSubprocessOutputStreams,\n forwardValidationSubprocessOutput,\n VALIDATION_SUBPROCESS_EVENTS,\n type ValidationSubprocessOutputStreams,\n} from \"./subprocess-output\";\n\n// =============================================================================\n// DEFAULT DEPENDENCIES\n// =============================================================================\n\n/**\n * Default production process runner for TypeScript.\n */\nexport const defaultTypeScriptProcessRunner: ProcessRunner = lifecycleProcessRunner;\n\n/**\n * Dependencies for file-specific TypeScript validation.\n */\nexport interface TypeScriptDeps {\n mkdtemp: typeof mkdtemp;\n mkdirSync: typeof mkdirSync;\n writeFileSync: typeof writeFileSync;\n rmSync: typeof rmSync;\n existsSync: typeof existsSync;\n}\n\n/**\n * Default production dependencies.\n */\nexport const defaultTypeScriptDeps: TypeScriptDeps = {\n mkdtemp,\n mkdirSync,\n writeFileSync,\n rmSync,\n existsSync,\n};\n\nexport interface TypeScriptValidationContext {\n readonly scope: ValidationScope;\n readonly projectRoot: string;\n readonly files?: readonly string[];\n readonly scopeConfig?: ScopeConfig;\n}\n\nexport interface TypeScriptValidationOptions {\n readonly runner?: ProcessRunner;\n readonly deps?: TypeScriptDeps;\n readonly outputStreams?: ValidationSubprocessOutputStreams;\n}\n\n/**\n * Compiler options for a temporary `tsconfig.json`; all else is inherited via `extends`.\n */\nconst TEMPORARY_TSCONFIG_COMPILER_OPTIONS = { noEmit: true } as const;\n\n/**\n * Parent directory segments for temporary validation configs — kept under the project's `node_modules` so the temporary file never appears in the project's tracked working tree.\n */\nexport const TEMPORARY_TSCONFIG_PARENT_SEGMENTS = [\"node_modules\", \".cache\", \"spx\"] as const;\n\n/**\n * Directory-name prefix for temporary validation configs.\n */\nconst TEMPORARY_TSCONFIG_DIR_PREFIX = \"validate-ts-\";\n\n/**\n * Create the temporary directory that holds one validation `tsconfig.json`.\n */\nasync function createTemporaryTsconfigDir(projectRoot: string, deps: TypeScriptDeps): Promise<string> {\n const parent = join(projectRoot, ...TEMPORARY_TSCONFIG_PARENT_SEGMENTS);\n deps.mkdirSync(parent, { recursive: true });\n return deps.mkdtemp(join(parent, TEMPORARY_TSCONFIG_DIR_PREFIX));\n}\n\n// =============================================================================\n// PURE ARGUMENT BUILDER\n// =============================================================================\n\n/**\n * Build TypeScript CLI arguments based on validation scope.\n *\n * Pure function for testability - can be verified at Level 1.\n *\n * @param context - Context for building arguments\n * @returns Array of tsc CLI arguments\n *\n * @example\n * ```typescript\n * const args = buildTypeScriptArgs({ scope: \"full\", configFile: \"tsconfig.json\" });\n * // Returns: [\"tsc\", \"--noEmit\"]\n * ```\n */\nexport function buildTypeScriptArgs(context: { scope: ValidationScope; configFile: string }): string[] {\n const { scope, configFile } = context;\n return scope === VALIDATION_SCOPES.FULL ? [\"tsc\", \"--noEmit\"] : [\"tsc\", \"--project\", configFile];\n}\n\n// =============================================================================\n// FILE-SPECIFIC VALIDATION SUPPORT\n// =============================================================================\n\n/**\n * Create a temporary TypeScript configuration file for file-specific validation.\n *\n * @param scope - Validation scope\n * @param files - Files to validate\n * @param deps - Injectable dependencies\n * @returns Config path and cleanup function\n */\nexport async function createFileSpecificTsconfig(\n scope: ValidationScope,\n files: readonly string[],\n projectRoot: string,\n deps: TypeScriptDeps = defaultTypeScriptDeps,\n): Promise<{ configPath: string; tempDir: string; cleanup: () => void }> {\n // Create temporary directory\n const tempDir = await createTemporaryTsconfigDir(projectRoot, deps);\n const configPath = join(tempDir, \"tsconfig.json\");\n\n // Get base config file\n const baseConfigFile = TSCONFIG_FILES[scope];\n\n // Ensure all file paths are absolute\n const absoluteFiles = files.map((file) => (isAbsolute(file) ? file : join(projectRoot, file)));\n\n // Create temporary tsconfig that extends the base config\n const tempConfig = {\n extends: join(projectRoot, baseConfigFile),\n files: absoluteFiles,\n include: [],\n exclude: [],\n compilerOptions: TEMPORARY_TSCONFIG_COMPILER_OPTIONS,\n };\n\n // Write temporary config\n deps.writeFileSync(configPath, JSON.stringify(tempConfig, null, 2));\n\n // Return config path and cleanup function\n const cleanup = () => {\n try {\n deps.rmSync(tempDir, { recursive: true, force: true });\n } catch {\n // Cleanup error - don't fail validation\n }\n };\n\n return { configPath, tempDir, cleanup };\n}\n\nasync function createScopeFilteredTsconfig(\n scope: ValidationScope,\n projectRoot: string,\n scopeConfig: ScopeConfig,\n deps: TypeScriptDeps = defaultTypeScriptDeps,\n): Promise<{ configPath: string; tempDir: string; cleanup: () => void }> {\n const tempDir = await createTemporaryTsconfigDir(projectRoot, deps);\n const configPath = join(tempDir, \"tsconfig.json\");\n const baseConfigFile = TSCONFIG_FILES[scope];\n const toProjectPathPattern = (pattern: string) => isAbsolute(pattern) ? pattern : join(projectRoot, pattern);\n const tempConfig = {\n extends: join(projectRoot, baseConfigFile),\n include: scopeConfig.filePatterns.map(toProjectPathPattern),\n exclude: scopeConfig.excludePatterns.map(toProjectPathPattern),\n compilerOptions: TEMPORARY_TSCONFIG_COMPILER_OPTIONS,\n };\n\n deps.writeFileSync(configPath, JSON.stringify(tempConfig, null, 2));\n\n const cleanup = () => {\n try {\n deps.rmSync(tempDir, { recursive: true, force: true });\n } catch {\n // Cleanup error - don't fail validation\n }\n };\n\n return { configPath, tempDir, cleanup };\n}\n\n// =============================================================================\n// VALIDATION FUNCTION\n// =============================================================================\n\n/**\n * Validate TypeScript using authoritative configuration.\n *\n * @param context - Validation scope, project root, files, and optional path-filtered scope\n * @param options - Injectable process runner, filesystem dependencies, and output streams\n * @returns Promise resolving to validation result\n *\n * @example\n * ```typescript\n * const result = await validateTypeScript({ scope: \"full\", projectRoot });\n * if (!result.success) {\n * console.error(\"TypeScript failed:\", result.error);\n * }\n * ```\n */\nexport async function validateTypeScript(\n context: TypeScriptValidationContext,\n options: TypeScriptValidationOptions = {},\n): Promise<{\n success: boolean;\n error?: string;\n skipped?: boolean;\n}> {\n const { scope, projectRoot, files, scopeConfig } = context;\n const {\n runner = defaultTypeScriptProcessRunner,\n deps = defaultTypeScriptDeps,\n outputStreams = defaultValidationSubprocessOutputStreams,\n } = options;\n const configFile = TSCONFIG_FILES[scope];\n\n // Determine tool and arguments based on whether specific files are provided\n let tool: string;\n let tscArgs: string[];\n\n if (files && files.length > 0) {\n // File-specific validation using custom temporary tsconfig\n const { configPath, cleanup } = await createFileSpecificTsconfig(scope, files, projectRoot, deps);\n\n try {\n return await new Promise((resolve) => {\n const tscBin = join(projectRoot, \"node_modules\", \".bin\", \"tsc\");\n const tscBinary = deps.existsSync(tscBin) ? tscBin : \"npx\";\n const tscArgs = tscBinary === \"npx\" ? [\"tsc\", \"--project\", configPath] : [\"--project\", configPath];\n const tscProcess = spawnManagedSubprocess(runner, tscBinary, tscArgs, {\n cwd: projectRoot,\n });\n forwardValidationSubprocessOutput(tscProcess, outputStreams);\n\n tscProcess.on(VALIDATION_SUBPROCESS_EVENTS.CLOSE, (code) => {\n cleanup();\n if (code === 0) {\n resolve({ success: true, skipped: false });\n } else {\n resolve({ success: false, error: `TypeScript exited with code ${code}` });\n }\n });\n\n tscProcess.on(VALIDATION_SUBPROCESS_EVENTS.ERROR, (error) => {\n cleanup();\n resolve({ success: false, error: error.message });\n });\n });\n } catch (error) {\n cleanup();\n const errorMessage = error instanceof Error ? error.message : String(error);\n return { success: false, error: `Failed to create temporary config: ${errorMessage}` };\n }\n } else if (scopeConfig?.filteredByValidationPaths) {\n if (scopeConfig.filteredByValidationPathNoMatches) {\n return { success: true, skipped: true };\n }\n if (scopeConfig.filePatterns.length === 0 && scopeConfig.directories.length === 0) {\n return { success: true, skipped: true };\n }\n const { configPath, cleanup } = await createScopeFilteredTsconfig(scope, projectRoot, scopeConfig, deps);\n const tscBin = join(projectRoot, \"node_modules\", \".bin\", \"tsc\");\n tool = deps.existsSync(tscBin) ? tscBin : \"npx\";\n tscArgs = tool === \"npx\" ? [\"tsc\", \"--project\", configPath] : [\"--project\", configPath];\n return new Promise((resolve) => {\n const tscProcess = spawnManagedSubprocess(runner, tool, tscArgs, {\n cwd: projectRoot,\n });\n forwardValidationSubprocessOutput(tscProcess, outputStreams);\n\n tscProcess.on(VALIDATION_SUBPROCESS_EVENTS.CLOSE, (code) => {\n cleanup();\n if (code === 0) {\n resolve({ success: true, skipped: false });\n } else {\n resolve({ success: false, error: `TypeScript exited with code ${code}` });\n }\n });\n\n tscProcess.on(VALIDATION_SUBPROCESS_EVENTS.ERROR, (error) => {\n cleanup();\n resolve({ success: false, error: error.message });\n });\n });\n } else {\n // Full validation using tsc\n const tscBin = join(projectRoot, \"node_modules\", \".bin\", \"tsc\");\n tool = deps.existsSync(tscBin) ? tscBin : \"npx\";\n const rawArgs = buildTypeScriptArgs({ scope, configFile });\n tscArgs = tool === \"npx\" ? rawArgs : rawArgs.slice(1);\n }\n\n return new Promise((resolve) => {\n const tscProcess = spawnManagedSubprocess(runner, tool, tscArgs, {\n cwd: projectRoot,\n });\n forwardValidationSubprocessOutput(tscProcess, outputStreams);\n\n tscProcess.on(VALIDATION_SUBPROCESS_EVENTS.CLOSE, (code) => {\n if (code === 0) {\n resolve({ success: true, skipped: false });\n } else {\n resolve({ success: false, error: `TypeScript exited with code ${code}` });\n }\n });\n\n tscProcess.on(VALIDATION_SUBPROCESS_EVENTS.ERROR, (error) => {\n resolve({ success: false, error: error.message });\n });\n });\n}\n","/**\n * TypeScript validation command.\n *\n * Runs TypeScript type checking using tsc.\n */\nimport { resolveConfig } from \"@/config/index\";\nimport {\n VALIDATION_PATH_TOOL_SUBSECTIONS,\n type ValidationConfig,\n validationConfigDescriptor,\n} from \"@/validation/config/descriptor\";\nimport {\n applyValidationPathFilterToScope,\n pathPassesValidationFilter,\n toProjectRelativeValidationPath,\n validationPathFilterForTool,\n} from \"@/validation/config/path-filter\";\nimport { getTypeScriptScope } from \"@/validation/config/scope\";\nimport { detectTypeScript, discoverTool, formatSkipMessage } from \"@/validation/discovery/index\";\nimport { validateTypeScript } from \"@/validation/steps/typescript\";\nimport {\n formatTypeScriptAbsentSkipMessage,\n formatValidationPathsNoTargetsSkipMessage,\n VALIDATION_COMMAND_OUTPUT,\n VALIDATION_STAGE_DISPLAY_NAMES,\n} from \"./messages\";\nimport type { TypeScriptCommandOptions, ValidationCommandResult } from \"./types\";\n\nexport const TYPESCRIPT_VALIDATION_MESSAGES = {\n ABSENT: formatTypeScriptAbsentSkipMessage(VALIDATION_STAGE_DISPLAY_NAMES.TYPESCRIPT),\n CONFIG_ERROR: `${VALIDATION_STAGE_DISPLAY_NAMES.TYPESCRIPT}: ✗ config error`,\n NO_VALIDATION_PATH_TARGETS: formatValidationPathsNoTargetsSkipMessage(VALIDATION_STAGE_DISPLAY_NAMES.TYPESCRIPT),\n SUCCESS: VALIDATION_COMMAND_OUTPUT.TYPESCRIPT_SUCCESS,\n TOOL_LABEL: VALIDATION_STAGE_DISPLAY_NAMES.TYPESCRIPT,\n} as const;\n\n/**\n * Run TypeScript type checking.\n *\n * Gates tsc execution on language detection: without a `tsconfig.json` in the\n * project root there is nothing to type-check, and invoking tsc regardless\n * causes it to walk up and compile an ancestor project instead.\n *\n * @param options - Command options\n * @returns Command result with exit code and output\n */\nexport async function typescriptCommand(options: TypeScriptCommandOptions): Promise<ValidationCommandResult> {\n const { cwd, scope = \"full\", files, quiet } = options;\n const startTime = Date.now();\n\n // Gate 1: language detection. No TypeScript = skip cleanly.\n const tsDetection = detectTypeScript(cwd);\n if (!tsDetection.present) {\n return {\n exitCode: 0,\n output: quiet ? \"\" : TYPESCRIPT_VALIDATION_MESSAGES.ABSENT,\n durationMs: Date.now() - startTime,\n };\n }\n\n const loaded = await resolveConfig(cwd, [validationConfigDescriptor]);\n if (!loaded.ok) {\n return {\n exitCode: 1,\n output: `${TYPESCRIPT_VALIDATION_MESSAGES.CONFIG_ERROR} — ${loaded.error}`,\n durationMs: Date.now() - startTime,\n };\n }\n const validationConfig = loaded.value[validationConfigDescriptor.section] as ValidationConfig;\n const validationPathFilter = validationPathFilterForTool(\n validationConfig.paths,\n VALIDATION_PATH_TOOL_SUBSECTIONS.TYPESCRIPT,\n );\n const scopeConfig = applyValidationPathFilterToScope(\n getTypeScriptScope(scope, cwd),\n validationPathFilter,\n );\n const filteredFiles = files\n ?.map((file) => toProjectRelativeValidationPath(cwd, file))\n .filter((file) => pathPassesValidationFilter(file, validationPathFilter));\n\n if (\n scopeConfig.filteredByValidationPathNoMatches\n || (files !== undefined && files.length > 0 && filteredFiles?.length === 0)\n ) {\n return {\n exitCode: 0,\n output: quiet ? \"\" : TYPESCRIPT_VALIDATION_MESSAGES.NO_VALIDATION_PATH_TARGETS,\n durationMs: Date.now() - startTime,\n };\n }\n\n // Gate 2: tool discovery — ensure tsc itself is available somewhere.\n const toolResult = await discoverTool(\"typescript\", { projectRoot: cwd });\n if (!toolResult.found) {\n const skipMessage = formatSkipMessage(VALIDATION_STAGE_DISPLAY_NAMES.TYPESCRIPT, toolResult);\n return { exitCode: 0, output: skipMessage, durationMs: Date.now() - startTime };\n }\n\n const result = await validateTypeScript({\n scope,\n projectRoot: cwd,\n files: filteredFiles,\n scopeConfig,\n });\n const durationMs = Date.now() - startTime;\n\n // Map result to command output\n if (result.skipped) {\n const output = quiet ? \"\" : TYPESCRIPT_VALIDATION_MESSAGES.NO_VALIDATION_PATH_TARGETS;\n return { exitCode: 0, output, durationMs };\n } else if (result.success) {\n const output = quiet ? \"\" : TYPESCRIPT_VALIDATION_MESSAGES.SUCCESS;\n return { exitCode: 0, output, durationMs };\n } else {\n const output = result.error ?? VALIDATION_COMMAND_OUTPUT.TYPESCRIPT_FAILURE;\n return { exitCode: 1, output, durationMs };\n }\n}\n","/**\n * TypeScript validation language descriptor.\n *\n * Declares the validation stages a TypeScript project contributes to the\n * pipeline: circular-dependency detection, unused-code detection, ESLint,\n * type checking, and literal-reuse detection. The registry imports this\n * descriptor with an explicit import statement; orchestration never names\n * these stages directly.\n */\nimport { circularCommand } from \"@/commands/validation/circular\";\nimport { knipCommand } from \"@/commands/validation/knip\";\nimport { lintCommand } from \"@/commands/validation/lint\";\nimport { literalCommand } from \"@/commands/validation/literal\";\nimport {\n LITERAL_SKIP_JSON_OUTPUT,\n LITERAL_SKIP_OUTPUT,\n VALIDATION_STAGE_DISPLAY_NAMES,\n} from \"@/commands/validation/messages\";\nimport type { ValidationCommandResult } from \"@/commands/validation/types\";\nimport { typescriptCommand } from \"@/commands/validation/typescript\";\nimport type { ValidationLanguageDescriptor, ValidationStageContext } from \"@/validation/languages/types\";\n\nconst TYPESCRIPT_LANGUAGE_NAME = \"typescript\";\n\n/**\n * Literal-reuse stage runner.\n *\n * A full-pipeline run may skip literal detection; the skip emits the canonical\n * skip notice (text or JSON) and reports success without invoking the detector.\n */\nasync function runLiteralStage(context: ValidationStageContext): Promise<ValidationCommandResult> {\n if (context.skipLiteral) {\n const skipOutput = context.json ? LITERAL_SKIP_JSON_OUTPUT : LITERAL_SKIP_OUTPUT;\n return { exitCode: 0, output: context.quiet ? \"\" : skipOutput };\n }\n return literalCommand({\n cwd: context.cwd,\n files: context.files,\n quiet: context.quiet,\n json: context.json,\n });\n}\n\nexport const typescriptValidationLanguage: ValidationLanguageDescriptor = {\n name: TYPESCRIPT_LANGUAGE_NAME,\n stages: [\n {\n name: VALIDATION_STAGE_DISPLAY_NAMES.CIRCULAR,\n failsPipeline: true,\n run: (context) => circularCommand({ cwd: context.cwd, quiet: context.quiet, json: context.json }),\n },\n {\n name: VALIDATION_STAGE_DISPLAY_NAMES.KNIP,\n // Knip is informational: unused-code findings never fail the pipeline.\n failsPipeline: false,\n run: (context) => knipCommand({ cwd: context.cwd, quiet: context.quiet, json: context.json }),\n },\n {\n name: VALIDATION_STAGE_DISPLAY_NAMES.ESLINT,\n failsPipeline: true,\n run: (context) =>\n lintCommand({\n cwd: context.cwd,\n scope: context.scope,\n files: context.files,\n fix: context.fix,\n quiet: context.quiet,\n json: context.json,\n }),\n },\n {\n name: VALIDATION_STAGE_DISPLAY_NAMES.TYPESCRIPT,\n failsPipeline: true,\n run: (context) =>\n typescriptCommand({\n cwd: context.cwd,\n scope: context.scope,\n files: context.files,\n quiet: context.quiet,\n json: context.json,\n }),\n },\n {\n name: VALIDATION_STAGE_DISPLAY_NAMES.LITERAL,\n failsPipeline: true,\n run: runLiteralStage,\n },\n ],\n};\n","/**\n * Validation language registry.\n *\n * Composes the validation pipeline from explicitly imported language\n * descriptors. Orchestration code iterates `validationPipelineStages`; it never\n * references a language or stage by name and never discovers descriptors through\n * filesystem scanning. Adding a language is one descriptor module plus one entry\n * here.\n */\nimport { markdownValidationLanguage } from \"@/validation/languages/markdown\";\nimport type { ValidationRegistry } from \"@/validation/languages/types\";\nimport { typescriptValidationLanguage } from \"@/validation/languages/typescript\";\n\nexport const validationRegistry: ValidationRegistry = {\n languages: [typescriptValidationLanguage, markdownValidationLanguage],\n};\n\n/** Flattened, ordered pipeline stages composed from every registered language. */\nexport const validationPipelineStages = validationRegistry.languages.flatMap(\n (language) => language.stages,\n);\n\n/** Total pipeline step count, derived from the registry rather than a constant. */\nexport const VALIDATION_PIPELINE_TOTAL_STEPS = validationPipelineStages.length;\n","/**\n * Output formatting functions for validation commands.\n *\n * Pure functions that format validation results for CLI display.\n * These functions have no side effects and are fully testable.\n */\n\n/** Threshold in milliseconds for switching from ms to seconds display */\nexport const DURATION_THRESHOLD_MS = 1000;\n\n/** Symbols used in validation output */\nexport const VALIDATION_SYMBOLS = {\n SUCCESS: \"✓\",\n FAILURE: \"✗\",\n} as const;\n\nexport const VALIDATION_SUMMARY_STATUS = {\n PASSED: \"passed\",\n FAILED: \"failed\",\n} as const;\n\n/**\n * Format a duration in milliseconds for display.\n *\n * @param ms - Duration in milliseconds\n * @returns Formatted string (e.g., \"500ms\" or \"1.5s\")\n */\nexport function formatDuration(ms: number): string {\n if (ms < DURATION_THRESHOLD_MS) {\n return `${ms}ms`;\n }\n const seconds = ms / 1000;\n return `${seconds.toFixed(1)}s`;\n}\n\n/** Options for formatting a validation step output */\nexport interface FormatStepOptions {\n /** Current step number (1-indexed) */\n stepNumber: number;\n /** Total number of steps */\n totalSteps: number;\n /** Name of the validation step */\n name: string;\n /** Result message (e.g., \"✓ No errors found\") */\n result: string;\n /** Duration in milliseconds */\n durationMs: number;\n}\n\n/**\n * Format a validation step result for display.\n *\n * @param options - Step formatting options\n * @returns Formatted string (e.g., \"[1/4] ESLint: ✓ No errors found (0.8s)\")\n */\nexport function formatStepOutput(options: FormatStepOptions): string {\n const { stepNumber, totalSteps, name, result, durationMs } = options;\n const duration = formatDuration(durationMs);\n return `[${stepNumber}/${totalSteps}] ${name}: ${result} (${duration})`;\n}\n\n/** Options for formatting the validation summary */\nexport interface FormatSummaryOptions {\n /** Whether all required validations passed */\n success: boolean;\n /** Total duration in milliseconds */\n totalDurationMs: number;\n}\n\n/**\n * Format the final validation summary.\n *\n * @param options - Summary formatting options\n * @returns Formatted string (e.g., \"✓ Validation passed (2.7s total)\")\n */\nexport function formatSummary(options: FormatSummaryOptions): string {\n const { success, totalDurationMs } = options;\n const symbol = success ? VALIDATION_SYMBOLS.SUCCESS : VALIDATION_SYMBOLS.FAILURE;\n const status = success ? VALIDATION_SUMMARY_STATUS.PASSED : VALIDATION_SUMMARY_STATUS.FAILED;\n const duration = formatDuration(totalDurationMs);\n return `${symbol} Validation ${status} (${duration} total)`;\n}\n","/**\n * Run all validations command.\n *\n * Iterates the language registry, executing each composed validation stage in\n * registry order and reporting every stage's result. Stage participation and\n * step count derive entirely from the registry — no stage is dispatched by name.\n */\nimport { VALIDATION_PIPELINE_TOTAL_STEPS, validationPipelineStages } from \"@/validation/registry\";\nimport { formatDuration, formatSummary } from \"./format\";\nimport type { AllCommandOptions, ValidationCommandResult } from \"./types\";\n\n/**\n * Format step output with step number and timing.\n *\n * @param stepNumber - Current step number (1-indexed)\n * @param result - Validation result\n * @param quiet - Whether to suppress output\n * @returns Formatted output string\n */\nfunction formatStepWithTiming(\n stepNumber: number,\n result: ValidationCommandResult,\n quiet: boolean,\n): string {\n if (quiet || !result.output) return \"\";\n\n const timing = result.durationMs === undefined ? \"\" : ` (${formatDuration(result.durationMs)})`;\n return `[${stepNumber}/${VALIDATION_PIPELINE_TOTAL_STEPS}] ${result.output}${timing}`;\n}\n\n/**\n * Run all validation steps.\n *\n * @param options - Command options\n * @returns Command result with exit code and output\n */\nexport async function allCommand(options: AllCommandOptions): Promise<ValidationCommandResult> {\n const { cwd, scope, files, fix, quiet = false, json, skipLiteral = false } = options;\n const startTime = Date.now();\n const outputs: string[] = [];\n let hasFailure = false;\n\n const context = { cwd, scope, files, fix, quiet, json, skipLiteral };\n\n let stepNumber = 0;\n for (const stage of validationPipelineStages) {\n stepNumber += 1;\n const result = await stage.run(context);\n const stepOutput = formatStepWithTiming(stepNumber, result, quiet);\n if (stepOutput) outputs.push(stepOutput);\n if (stage.failsPipeline && result.exitCode !== 0) hasFailure = true;\n }\n\n // Calculate total duration\n const totalDurationMs = Date.now() - startTime;\n\n // Add summary line\n if (!quiet) {\n const summary = formatSummary({ success: !hasFailure, totalDurationMs });\n outputs.push(\"\", summary); // Empty line before summary\n }\n\n return {\n exitCode: hasFailure ? 1 : 0,\n output: outputs.join(\"\\n\"),\n durationMs: totalDurationMs,\n };\n}\n","export const MAX_CLI_ARGUMENT_DISPLAY_LENGTH = 120;\nexport const ELLIPSIS_TOKEN = \"...\";\n\nexport const SENTINEL_UNDEFINED = \"<undefined>\";\nexport const SENTINEL_NULL = \"<null>\";\nexport const SENTINEL_EMPTY = \"<empty>\";\n\nexport const CONTROL_CHAR_UPPER_BOUND = 0x1f;\nexport const DEL_CHAR_CODE = 0x7f;\nexport const FIRST_PRINTABLE_CHAR_CODE = 0x20;\n\nexport const HEX_RADIX = 16;\nexport const HEX_PAD = 2;\n\nexport function formatHexEscape(code: number): string {\n return `\\\\x${code.toString(HEX_RADIX).padStart(HEX_PAD, \"0\")}`;\n}\n\nexport function nonStringSentinel(type: string): string {\n return `<non-string:${type}>`;\n}\n\nexport function sanitizeCliArgument(input: unknown): string {\n if (input === undefined) return SENTINEL_UNDEFINED;\n if (input === null) return SENTINEL_NULL;\n if (typeof input !== \"string\") return nonStringSentinel(typeof input);\n if (input.length === 0) return SENTINEL_EMPTY;\n\n const escaped = escapeControlCharacters(input);\n return truncate(escaped);\n}\n\nfunction escapeControlCharacters(value: string): string {\n let out = \"\";\n for (const char of value) {\n const code = char.codePointAt(0);\n if (code === undefined) continue;\n if (code <= CONTROL_CHAR_UPPER_BOUND || code === DEL_CHAR_CODE) {\n out += formatHexEscape(code);\n } else {\n out += char;\n }\n }\n return out;\n}\n\nfunction truncate(value: string): string {\n if (value.length <= MAX_CLI_ARGUMENT_DISPLAY_LENGTH) return value;\n return value.slice(0, MAX_CLI_ARGUMENT_DISPLAY_LENGTH - ELLIPSIS_TOKEN.length) + ELLIPSIS_TOKEN;\n}\n","import { rename, writeFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\n\nimport {\n type ConfigFile,\n configFileForFormat,\n type ConfigFileReadResult,\n DEFAULT_CONFIG_FILE_FORMAT,\n formatConfigFileAmbiguityError,\n parseConfigFileSections,\n readProductConfigFile,\n serializeConfigFileSectionsWithSetIn,\n} from \"@/config/index\";\nimport type { Result } from \"@/config/types\";\nimport {\n VALIDATION_LITERAL_SUBSECTION,\n VALIDATION_LITERAL_VALUES_SUBSECTION,\n VALIDATION_SECTION,\n} from \"@/validation/config/descriptor\";\n\nimport { type LiteralConfig, literalConfigDescriptor } from \"./config\";\nimport { validateLiteralReuse } from \"./index\";\n\nexport interface ConfigReader {\n read(productDir: string): Promise<Result<ConfigFileReadResult>>;\n}\n\nexport interface ConfigWriter {\n write(filePath: string, content: string): Promise<void>;\n}\n\nexport interface AllowlistExistingOptions {\n readonly productDir: string;\n readonly reader?: ConfigReader;\n readonly writer?: ConfigWriter;\n}\n\nexport interface AllowlistExistingResult {\n readonly exitCode: number;\n readonly output: string;\n}\n\nconst EXIT_OK = 0;\nconst EXIT_ERROR = 1;\nconst INCLUDE_FIELD = \"include\";\nconst ALLOWLIST_INCLUDE_PATH = [\n VALIDATION_SECTION,\n VALIDATION_LITERAL_SUBSECTION,\n VALIDATION_LITERAL_VALUES_SUBSECTION,\n INCLUDE_FIELD,\n] as const;\nconst TEMP_FILE_PREFIX = \".spx-allowlist-existing-\";\nconst TEMP_FILE_SUFFIX = \".tmp\";\nconst RANDOM_BASE = 36;\nconst RANDOM_PREFIX_SLICE = 2;\nconst RANDOM_TOKEN_LENGTH = 10;\n\nexport const productionReader: ConfigReader = {\n read: readProductConfigFile,\n};\n\nexport const productionWriter: ConfigWriter = {\n async write(filePath: string, content: string): Promise<void> {\n const dir = dirname(filePath);\n const random = Math.random()\n .toString(RANDOM_BASE)\n .slice(RANDOM_PREFIX_SLICE, RANDOM_PREFIX_SLICE + RANDOM_TOKEN_LENGTH);\n const tmpPath = join(dir, `${TEMP_FILE_PREFIX}${random}${TEMP_FILE_SUFFIX}`);\n await writeFile(tmpPath, content, \"utf8\");\n await rename(tmpPath, filePath);\n },\n};\n\nexport async function allowlistExisting(\n options: AllowlistExistingOptions,\n): Promise<AllowlistExistingResult> {\n const reader = options.reader ?? productionReader;\n const writer = options.writer ?? productionWriter;\n\n const readResult = await reader.read(options.productDir);\n if (!readResult.ok) {\n return { exitCode: EXIT_ERROR, output: readResult.error };\n }\n\n const configRead = readResult.value;\n if (configRead.kind === \"ambiguous\") {\n return { exitCode: EXIT_ERROR, output: formatConfigFileAmbiguityError(configRead.detected) };\n }\n\n const currentLiteralConfig = readCurrentLiteralConfig(configRead);\n if (!currentLiteralConfig.ok) {\n return { exitCode: EXIT_ERROR, output: currentLiteralConfig.error };\n }\n\n const detection = await validateLiteralReuse({\n productDir: options.productDir,\n config: currentLiteralConfig.value,\n });\n\n const findingValues = collectFindingValues(detection.findings);\n const updatedInclude = computeUpdatedInclude(\n currentLiteralConfig.value.include,\n findingValues,\n );\n\n const target: ConfigFile = configRead.kind === \"ok\"\n ? configRead.file\n : configFileForFormat(options.productDir, DEFAULT_CONFIG_FILE_FORMAT);\n\n const serialized = serializeWithUpdatedInclude(target, updatedInclude);\n if (!serialized.ok) {\n return { exitCode: EXIT_ERROR, output: serialized.error };\n }\n await writer.write(target.path, serialized.value);\n\n return { exitCode: EXIT_OK, output: \"\" };\n}\n\nfunction readCurrentLiteralConfig(read: ConfigFileReadResult): Result<LiteralConfig> {\n if (read.kind !== \"ok\") return { ok: true, value: literalConfigDescriptor.defaults };\n const sections = parseConfigFileSections(read.file);\n if (!sections.ok) return sections;\n const validationRaw = sections.value[VALIDATION_SECTION];\n if (typeof validationRaw !== \"object\" || validationRaw === null) {\n return { ok: true, value: literalConfigDescriptor.defaults };\n }\n const literalRaw = (validationRaw as Record<string, unknown>)[VALIDATION_LITERAL_SUBSECTION];\n if (typeof literalRaw !== \"object\" || literalRaw === null) {\n return { ok: true, value: literalConfigDescriptor.defaults };\n }\n const valuesRaw = (literalRaw as Record<string, unknown>)[VALIDATION_LITERAL_VALUES_SUBSECTION];\n if (valuesRaw === undefined) {\n return { ok: true, value: literalConfigDescriptor.defaults };\n }\n const validated = literalConfigDescriptor.validate(valuesRaw);\n return validated.ok ? validated : { ok: true, value: literalConfigDescriptor.defaults };\n}\n\nfunction collectFindingValues(\n findings: {\n readonly srcReuse: readonly { readonly value: string }[];\n readonly testDupe: readonly { readonly value: string }[];\n },\n): readonly string[] {\n const values = new Set<string>();\n for (const finding of findings.srcReuse) values.add(finding.value);\n for (const finding of findings.testDupe) values.add(finding.value);\n return [...values];\n}\n\nfunction computeUpdatedInclude(\n existing: readonly string[] | undefined,\n findingValues: readonly string[],\n): readonly string[] {\n const existingArr = existing ?? [];\n const existingSet = new Set(existingArr);\n const additions = findingValues.filter((value) => !existingSet.has(value)).sort();\n return [...existingArr, ...additions];\n}\n\nfunction serializeWithUpdatedInclude(target: ConfigFile, include: readonly string[]): Result<string> {\n return serializeConfigFileSectionsWithSetIn(target, ALLOWLIST_INCLUDE_PATH, [...include]);\n}\n","import type { Command } from \"commander\";\n\nimport {\n allCommand,\n circularCommand,\n knipCommand,\n lintCommand,\n LITERAL_PROBLEM_KIND,\n literalCommand,\n type LiteralProblemKind,\n markdownCommand,\n typescriptCommand,\n} from \"@/commands/validation\";\nimport type { Domain } from \"@/domains/types\";\nimport { sanitizeCliArgument } from \"@/interfaces/cli/sanitize\";\nimport { allowlistExisting } from \"@/validation/literal/allowlist-existing\";\nimport type { ValidationScope } from \"@/validation/types\";\n\ninterface ValidationDomainCommandDefinition {\n readonly commandName: string;\n readonly alias: string;\n readonly description: string;\n}\n\ninterface ValidationSubcommandDefinition {\n readonly commandName: string;\n readonly alias?: string;\n readonly description: string;\n}\n\ninterface ValidationCliDefinition {\n readonly domain: ValidationDomainCommandDefinition;\n readonly subcommands: {\n readonly typescript: ValidationSubcommandDefinition;\n readonly lint: ValidationSubcommandDefinition;\n readonly circular: ValidationSubcommandDefinition;\n readonly knip: ValidationSubcommandDefinition;\n readonly literal: ValidationSubcommandDefinition;\n readonly markdown: ValidationSubcommandDefinition;\n readonly all: ValidationSubcommandDefinition;\n };\n readonly commanderHelpOperands: {\n readonly subcommand: string;\n readonly longFlag: string;\n readonly shortFlag: string;\n };\n readonly diagnostics: {\n readonly unknownSubcommand: {\n readonly messageLabel: string;\n readonly exitCode: number;\n };\n readonly unknownLiteralProblemKind: {\n readonly messageLabel: string;\n readonly exitCode: number;\n };\n };\n}\n\nexport const validationCliDefinition: ValidationCliDefinition = {\n domain: {\n commandName: \"validation\",\n alias: \"v\",\n description: \"Run code validation tools\",\n },\n subcommands: {\n typescript: {\n commandName: \"typescript\",\n alias: \"ts\",\n description: \"Run TypeScript type checking\",\n },\n lint: {\n commandName: \"lint\",\n description: \"Run ESLint\",\n },\n circular: {\n commandName: \"circular\",\n description: \"Check for circular dependencies\",\n },\n knip: {\n commandName: \"knip\",\n description: \"Detect unused code\",\n },\n literal: {\n commandName: \"literal\",\n description: \"Detect cross-file literal reuse between source and tests\",\n },\n markdown: {\n commandName: \"markdown\",\n alias: \"md\",\n description: \"Validate markdown link integrity and structure\",\n },\n all: {\n commandName: \"all\",\n description: \"Run all validations\",\n },\n },\n commanderHelpOperands: {\n subcommand: \"help\",\n longFlag: \"--help\",\n shortFlag: \"-h\",\n },\n diagnostics: {\n unknownSubcommand: {\n messageLabel: \"unknown subcommand\",\n exitCode: 1,\n },\n unknownLiteralProblemKind: {\n messageLabel: \"unknown problem kind\",\n exitCode: 1,\n },\n },\n} as const;\n\nexport const literalValidationCliOptions = {\n allowlistExisting: {\n flag: \"--allowlist-existing\",\n description: \"Append every current problem's value to validation.literal.values.include and exit\",\n },\n kind: {\n flag: \"--kind <kind>\",\n description: \"Only report one problem kind (reuse|dupe)\",\n },\n filesWithProblems: {\n flag: \"--files-with-problems\",\n description: \"Print each affected file path once\",\n },\n literals: {\n flag: \"--literals\",\n description: \"Print each affected literal value once\",\n },\n verbose: {\n flag: \"--verbose\",\n description: \"Print grouped problem details\",\n },\n} as const;\n\nexport const allValidationCliOptions = {\n skipLiteral: {\n flag: \"--skip-literal\",\n description: \"Skip literal reuse detection for this validation all run\",\n },\n} as const;\n\nconst validationSubcommandOperands = Object.values(validationCliDefinition.subcommands).flatMap(\n (subcommand) => {\n const operands = [subcommand.commandName];\n if (subcommand.alias !== undefined) operands.push(subcommand.alias);\n return operands;\n },\n);\n\nexport const validationKnownOperands: ReadonlySet<string> = new Set([\n ...validationSubcommandOperands,\n ...Object.values(validationCliDefinition.commanderHelpOperands),\n]);\nexport const validationOptionPrefix = validationCliDefinition.commanderHelpOperands.longFlag.slice(0, 1);\n\n/** Common options for all validation commands */\ninterface CommonOptions {\n scope?: ValidationScope;\n files?: string[];\n quiet?: boolean;\n json?: boolean;\n}\n\n/** Options for lint command */\ninterface LintOptions extends CommonOptions {\n fix?: boolean;\n}\n\ninterface LiteralOptions extends CommonOptions {\n allowlistExisting?: boolean;\n kind?: string;\n filesWithProblems?: boolean;\n literals?: boolean;\n verbose?: boolean;\n}\n\ninterface AllOptions extends CommonOptions {\n fix?: boolean;\n skipLiteral?: boolean;\n}\n\n/**\n * Add common options to a command\n */\nfunction addCommonOptions(cmd: Command): Command {\n return cmd\n .option(\"--scope <scope>\", \"Validation scope (full|production)\", \"full\")\n .option(\"--files <paths...>\", \"Specific files/directories to validate\")\n .option(\"--quiet\", \"Suppress progress output\")\n .option(\"--json\", \"Output results as JSON\");\n}\n\nfunction addValidationSubcommand(\n validationCmd: Command,\n definition: ValidationSubcommandDefinition,\n): Command {\n let subcommand = validationCmd\n .command(definition.commandName)\n .description(definition.description);\n\n if (definition.alias !== undefined) {\n subcommand = subcommand.alias(definition.alias);\n }\n\n return subcommand;\n}\n\n/**\n * Register validation domain commands\n */\nfunction registerValidationCommands(validationCmd: Command): void {\n const { subcommands } = validationCliDefinition;\n\n // typescript command\n const tsCmd = addValidationSubcommand(validationCmd, subcommands.typescript)\n .action(async (options: CommonOptions) => {\n const result = await typescriptCommand({\n cwd: process.cwd(),\n scope: options.scope,\n files: options.files,\n quiet: options.quiet,\n json: options.json,\n });\n if (result.output) console.log(result.output);\n process.exit(result.exitCode);\n });\n addCommonOptions(tsCmd);\n\n // lint command\n const lintCmd = addValidationSubcommand(validationCmd, subcommands.lint)\n .option(\"--fix\", \"Auto-fix issues\")\n .action(async (options: LintOptions) => {\n const result = await lintCommand({\n cwd: process.cwd(),\n scope: options.scope,\n files: options.files,\n fix: options.fix,\n quiet: options.quiet,\n json: options.json,\n });\n if (result.output) console.log(result.output);\n process.exit(result.exitCode);\n });\n addCommonOptions(lintCmd);\n\n // circular command\n const circularCmd = addValidationSubcommand(validationCmd, subcommands.circular)\n .action(async (options: CommonOptions) => {\n const result = await circularCommand({\n cwd: process.cwd(),\n quiet: options.quiet,\n json: options.json,\n });\n if (result.output) console.log(result.output);\n process.exit(result.exitCode);\n });\n addCommonOptions(circularCmd);\n\n // knip command\n const knipCmd = addValidationSubcommand(validationCmd, subcommands.knip)\n .action(async (options: CommonOptions) => {\n const result = await knipCommand({\n cwd: process.cwd(),\n quiet: options.quiet,\n json: options.json,\n });\n if (result.output) console.log(result.output);\n process.exit(result.exitCode);\n });\n addCommonOptions(knipCmd);\n\n // literal command (cross-file literal-reuse detector)\n const literalCmd = addValidationSubcommand(validationCmd, subcommands.literal)\n .option(\n literalValidationCliOptions.allowlistExisting.flag,\n literalValidationCliOptions.allowlistExisting.description,\n )\n .option(literalValidationCliOptions.kind.flag, literalValidationCliOptions.kind.description)\n .option(\n literalValidationCliOptions.filesWithProblems.flag,\n literalValidationCliOptions.filesWithProblems.description,\n )\n .option(literalValidationCliOptions.literals.flag, literalValidationCliOptions.literals.description)\n .option(literalValidationCliOptions.verbose.flag, literalValidationCliOptions.verbose.description)\n .addHelpText(\n \"after\",\n \"\\nEnabled for TypeScript projects by default. Set validation.literal.enabled=false\\n\"\n + \"in spx.config.* to skip during migration.\",\n )\n .action(async (options: LiteralOptions) => {\n if (options.allowlistExisting) {\n const result = await allowlistExisting({ productDir: process.cwd() });\n if (result.output) console.log(result.output);\n process.exit(result.exitCode);\n }\n let kind: LiteralProblemKind | undefined;\n if (options.kind !== undefined) {\n kind = parseLiteralProblemKind(options.kind);\n if (kind === undefined) {\n const { unknownLiteralProblemKind } = validationCliDefinition.diagnostics;\n process.stderr.write(\n `spx validation literal: ${unknownLiteralProblemKind.messageLabel}: ${sanitizeCliArgument(options.kind)}\\n`,\n );\n process.exit(unknownLiteralProblemKind.exitCode);\n }\n }\n const result = await literalCommand({\n cwd: process.cwd(),\n files: options.files,\n kind,\n filesWithProblems: options.filesWithProblems,\n literals: options.literals,\n verbose: options.verbose,\n quiet: options.quiet,\n json: options.json,\n });\n if (result.output) console.log(result.output);\n process.exit(result.exitCode);\n });\n addCommonOptions(literalCmd);\n\n // markdown command\n const markdownCmd = addValidationSubcommand(validationCmd, subcommands.markdown)\n .addHelpText(\n \"after\",\n \"\\nValidates spx/ and docs/ by default. Nodes listed in spx/EXCLUDE are\\n\"\n + \"skipped — use this for declared-state nodes whose [test] links point\\n\"\n + \"to files that do not exist yet.\",\n )\n .action(async (options: CommonOptions) => {\n const result = await markdownCommand({\n cwd: process.cwd(),\n files: options.files,\n quiet: options.quiet,\n });\n if (result.output) console.log(result.output);\n process.exit(result.exitCode);\n });\n addCommonOptions(markdownCmd);\n\n // all command\n const allCmd = addValidationSubcommand(validationCmd, subcommands.all)\n .option(\"--fix\", \"Auto-fix ESLint issues\")\n .option(allValidationCliOptions.skipLiteral.flag, allValidationCliOptions.skipLiteral.description)\n .action(async (options: AllOptions) => {\n const result = await allCommand({\n cwd: process.cwd(),\n scope: options.scope,\n files: options.files,\n fix: options.fix,\n skipLiteral: options.skipLiteral,\n quiet: options.quiet,\n json: options.json,\n });\n if (result.output) console.log(result.output);\n process.exit(result.exitCode);\n });\n addCommonOptions(allCmd);\n}\n\nfunction parseLiteralProblemKind(value: string): LiteralProblemKind | undefined {\n if (value === LITERAL_PROBLEM_KIND.REUSE || value === LITERAL_PROBLEM_KIND.DUPE) {\n return value;\n }\n return undefined;\n}\n\nfunction handleUnknownSubcommand(operands: readonly string[]): never {\n const [first] = operands;\n const sanitized = sanitizeCliArgument(first);\n const { domain, diagnostics } = validationCliDefinition;\n const { unknownSubcommand } = diagnostics;\n process.stderr.write(`spx ${domain.commandName}: ${unknownSubcommand.messageLabel}: ${sanitized}\\n`);\n process.exit(unknownSubcommand.exitCode);\n}\n\nexport const validationDomain: Domain = {\n name: validationCliDefinition.domain.commandName,\n description: validationCliDefinition.domain.description,\n register: (program: Command) => {\n const { domain } = validationCliDefinition;\n const validationCmd = program\n .command(domain.commandName)\n .alias(domain.alias)\n .description(domain.description);\n\n validationCmd.on(\"command:*\", (operands: readonly string[]) => {\n handleUnknownSubcommand(operands);\n });\n\n registerValidationCommands(validationCmd);\n },\n};\n","/**\n * Controlling-process resolution — finds the holding agent process whose\n * liveness means the worktree is held: an explicit pid override, else the\n * nearest ancestor whose command names a known agent runtime, else the\n * immediate parent. Pure over an injected process table.\n *\n * @module domains/worktree/controlling-process\n */\n\nimport type { Result } from \"@/config/types\";\n\nimport type { ProcessTable } from \"./process-table\";\n\nexport const CONTROLLING_PID_ENV = \"SPX_WORKTREE_CONTROLLING_PID\";\nexport const AGENT_RUNTIME_NAMES = [\"claude\", \"codex\"] as const;\nexport const AGENT_COMMAND_PATTERN = new RegExp(`\\\\b(?:${AGENT_RUNTIME_NAMES.join(\"|\")})\\\\b`, \"i\");\n\nexport const CONTROLLING_PROCESS_ERROR = {\n UNRESOLVED: \"worktree controlling process could not be resolved\",\n} as const;\n\nconst MAX_ANCESTRY_DEPTH = 64;\nconst PID_RADIX = 10;\n\n/** The holding agent process recorded in a worktree claim. */\nexport interface ControllingProcess {\n readonly pid: number;\n readonly startedAt: string;\n readonly host: string;\n}\n\nexport type ControllingProcessEnv = { readonly [key: string]: string | undefined };\n\n/**\n * Resolves the controlling process for `selfPid` (spx's own pid): an explicit\n * `SPX_WORKTREE_CONTROLLING_PID` override, else the nearest ancestor whose\n * command names a known agent runtime, else the immediate parent. The first\n * candidate whose start time resolves is recorded.\n */\nexport function resolveControllingProcess(\n selfPid: number,\n table: ProcessTable,\n env: ControllingProcessEnv,\n): Result<ControllingProcess> {\n const host = table.currentHost();\n for (const pid of controllingPidCandidates(selfPid, table, env)) {\n const startedAt = table.startTimeOf(pid);\n if (startedAt !== undefined) return { ok: true, value: { pid, startedAt, host } };\n }\n return { ok: false, error: CONTROLLING_PROCESS_ERROR.UNRESOLVED };\n}\n\nfunction* controllingPidCandidates(\n selfPid: number,\n table: ProcessTable,\n env: ControllingProcessEnv,\n): Generator<number> {\n const override = parsePid(env[CONTROLLING_PID_ENV]);\n if (override !== undefined) yield override;\n\n const agent = findAgentAncestor(selfPid, table);\n if (agent !== undefined) yield agent;\n\n const parent = table.parentOf(selfPid);\n if (parent !== undefined) yield parent;\n}\n\nfunction findAgentAncestor(selfPid: number, table: ProcessTable): number | undefined {\n let pid = table.parentOf(selfPid);\n for (let depth = 0; pid !== undefined && depth < MAX_ANCESTRY_DEPTH; depth += 1) {\n const command = table.commandOf(pid);\n if (command !== undefined && AGENT_COMMAND_PATTERN.test(command)) return pid;\n pid = table.parentOf(pid);\n }\n return undefined;\n}\n\nfunction parsePid(value: string | undefined): number | undefined {\n if (value === undefined || value.length === 0) return undefined;\n const parsed = Number.parseInt(value, PID_RADIX);\n return Number.isInteger(parsed) && parsed > 0 ? parsed : undefined;\n}\n","/**\n * Worktree-occupancy claim store — atomic claim-record I/O at\n * `.spx/worktrees/<name>.claim` and the on-demand process-liveness\n * classification. The filesystem and the process probe are injected so\n * classification verifies over controlled inputs.\n *\n * @module domains/worktree/occupancy-store\n */\n\nimport {\n mkdir as nodeMkdir,\n readFile as nodeReadFile,\n rename as nodeRename,\n rm as nodeRm,\n writeFile as nodeWriteFile,\n} from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport type { Result } from \"@/config/types\";\nimport { ERROR_CODE_NOT_FOUND, hasErrorCode, validateScopeToken } from \"@/lib/state-store\";\n\nexport const OCCUPANCY_STATUS = {\n UNCLAIMED: \"unclaimed\",\n OCCUPIED: \"occupied\",\n STALE: \"stale\",\n} as const;\n\nexport type OccupancyStatus = (typeof OCCUPANCY_STATUS)[keyof typeof OCCUPANCY_STATUS];\n\nexport const OCCUPANCY_CLAIM = {\n FILE_EXTENSION: \".claim\",\n TEMP_EXTENSION: \".tmp\",\n} as const;\n\nexport const OCCUPANCY_ERROR = {\n INVALID_NAME: \"worktree occupancy claim name must be a safe path segment\",\n CLAIM_WRITE_FAILED: \"worktree occupancy claim write failed\",\n CLAIM_READ_FAILED: \"worktree occupancy claim read failed\",\n CLAIM_REMOVE_FAILED: \"worktree occupancy claim remove failed\",\n CLAIM_MALFORMED: \"worktree occupancy claim record is malformed\",\n} as const;\n\nexport type OccupancyErrorCode = (typeof OCCUPANCY_ERROR)[keyof typeof OCCUPANCY_ERROR];\n\nconst ERROR_DETAIL_SEPARATOR = \": \";\n\n/** The four-field claim record written to `.spx/worktrees/<name>.claim`. */\nexport interface WorktreeClaimRecord {\n readonly sessionId: string;\n readonly host: string;\n readonly pid: number;\n readonly startedAt: string;\n}\n\n/** Injected filesystem boundary the claim store performs all I/O through. */\nexport interface OccupancyFileSystem {\n mkdir(path: string, options?: { readonly recursive?: boolean }): Promise<void>;\n writeFile(path: string, data: string): Promise<void>;\n rename(from: string, to: string): Promise<void>;\n readFile(path: string, encoding: \"utf8\"): Promise<string>;\n rm(path: string, options?: { readonly force?: boolean }): Promise<void>;\n}\n\n/**\n * Injected process-table probe. `currentHost` names the host the check runs on,\n * `isAlive` reads `kill(pid, 0)`, and `startTimeOf` returns the live process's\n * start time so a recycled pid is distinguished from the original holder.\n */\nexport interface ProcessProbe {\n currentHost(): string;\n isAlive(pid: number): boolean;\n startTimeOf(pid: number): string | undefined;\n}\n\nexport interface OccupancyFsOptions {\n readonly fs?: OccupancyFileSystem;\n}\n\nexport const defaultOccupancyFileSystem: OccupancyFileSystem = {\n mkdir: async (path, options) => {\n await nodeMkdir(path, options);\n },\n writeFile: async (path, data) => {\n await nodeWriteFile(path, data);\n },\n rename: nodeRename,\n readFile: nodeReadFile,\n rm: async (path, options) => {\n await nodeRm(path, options);\n },\n};\n\n/** The claim filename for a worktree `name` — `<name>.claim`. */\nexport function claimFileName(name: string): string {\n return `${name}${OCCUPANCY_CLAIM.FILE_EXTENSION}`;\n}\n\n/** Composes the `.claim` path for `name` under `worktreesDir`, rejecting unsafe names. */\nexport function claimFilePath(worktreesDir: string, name: string): Result<string> {\n const validated = validateScopeToken(name);\n if (!validated.ok) return { ok: false, error: OCCUPANCY_ERROR.INVALID_NAME };\n return { ok: true, value: join(worktreesDir, claimFileName(validated.value)) };\n}\n\n/**\n * Classifies a worktree's occupancy from its claim and the process table: no\n * claim is unclaimed; a different host or a dead process is stale and therefore\n * free; a live same-host process whose start time is readable and differs is a\n * recycled pid and reads stale. A live same-host process whose start time\n * matches — or cannot be read at all — reads occupied: a live holder is never\n * reported free on the strength of an unreadable start time, the conservative\n * choice that keeps one agent out of another live agent's worktree. The\n * decision reads no clock, so a live holder never ages out.\n */\nexport function classifyOccupancy(\n claim: WorktreeClaimRecord | undefined,\n probe: ProcessProbe,\n): OccupancyStatus {\n if (claim === undefined) return OCCUPANCY_STATUS.UNCLAIMED;\n if (claim.host !== probe.currentHost()) return OCCUPANCY_STATUS.STALE;\n if (!probe.isAlive(claim.pid)) return OCCUPANCY_STATUS.STALE;\n const liveStartTime = probe.startTimeOf(claim.pid);\n if (liveStartTime !== undefined && liveStartTime !== claim.startedAt) return OCCUPANCY_STATUS.STALE;\n return OCCUPANCY_STATUS.OCCUPIED;\n}\n\n/**\n * Writes the claim atomically: the record serializes to a temp file that is\n * renamed onto the claim path, so a concurrent read observes either no claim or\n * the complete record.\n */\nexport async function writeClaim(\n worktreesDir: string,\n name: string,\n record: WorktreeClaimRecord,\n options: OccupancyFsOptions = {},\n): Promise<Result<string>> {\n const fs = options.fs ?? defaultOccupancyFileSystem;\n const pathResult = claimFilePath(worktreesDir, name);\n if (!pathResult.ok) return pathResult;\n const claimPath = pathResult.value;\n const tempPath = `${claimPath}${OCCUPANCY_CLAIM.TEMP_EXTENSION}`;\n\n try {\n await fs.mkdir(worktreesDir, { recursive: true });\n await fs.writeFile(tempPath, serializeClaim(record));\n await fs.rename(tempPath, claimPath);\n return { ok: true, value: claimPath };\n } catch (error) {\n return { ok: false, error: formatOccupancyError(OCCUPANCY_ERROR.CLAIM_WRITE_FAILED, toErrorMessage(error)) };\n }\n}\n\n/** Reads and parses the claim for `name`, returning `undefined` when no claim exists. */\nexport async function readClaim(\n worktreesDir: string,\n name: string,\n options: OccupancyFsOptions = {},\n): Promise<Result<WorktreeClaimRecord | undefined>> {\n const fs = options.fs ?? defaultOccupancyFileSystem;\n const pathResult = claimFilePath(worktreesDir, name);\n if (!pathResult.ok) return pathResult;\n\n let content: string;\n try {\n content = await fs.readFile(pathResult.value, \"utf8\");\n } catch (error) {\n if (hasErrorCode(error, ERROR_CODE_NOT_FOUND)) return { ok: true, value: undefined };\n return { ok: false, error: formatOccupancyError(OCCUPANCY_ERROR.CLAIM_READ_FAILED, toErrorMessage(error)) };\n }\n\n return parseClaim(content);\n}\n\n/** Removes the claim for `name`. Idempotent — a missing claim is not an error. */\nexport async function removeClaim(\n worktreesDir: string,\n name: string,\n options: OccupancyFsOptions = {},\n): Promise<Result<void>> {\n const fs = options.fs ?? defaultOccupancyFileSystem;\n const pathResult = claimFilePath(worktreesDir, name);\n if (!pathResult.ok) return pathResult;\n\n try {\n await fs.rm(pathResult.value, { force: true });\n return { ok: true, value: undefined };\n } catch (error) {\n return { ok: false, error: formatOccupancyError(OCCUPANCY_ERROR.CLAIM_REMOVE_FAILED, toErrorMessage(error)) };\n }\n}\n\n/** Reads the claim for `name` and classifies its occupancy against the process probe. */\nexport async function readOccupancy(\n worktreesDir: string,\n name: string,\n probe: ProcessProbe,\n options: OccupancyFsOptions = {},\n): Promise<Result<OccupancyStatus>> {\n const claimResult = await readClaim(worktreesDir, name, options);\n if (!claimResult.ok) return claimResult;\n return { ok: true, value: classifyOccupancy(claimResult.value, probe) };\n}\n\nfunction serializeClaim(record: WorktreeClaimRecord): string {\n return JSON.stringify({\n sessionId: record.sessionId,\n host: record.host,\n pid: record.pid,\n startedAt: record.startedAt,\n });\n}\n\nfunction parseClaim(content: string): Result<WorktreeClaimRecord> {\n let parsed: unknown;\n try {\n parsed = JSON.parse(content);\n } catch {\n return { ok: false, error: OCCUPANCY_ERROR.CLAIM_MALFORMED };\n }\n if (!isWorktreeClaimRecord(parsed)) return { ok: false, error: OCCUPANCY_ERROR.CLAIM_MALFORMED };\n return { ok: true, value: parsed };\n}\n\nfunction isWorktreeClaimRecord(value: unknown): value is WorktreeClaimRecord {\n if (typeof value !== \"object\" || value === null) return false;\n const candidate = value as Record<string, unknown>;\n return (\n typeof candidate.sessionId === \"string\"\n && typeof candidate.host === \"string\"\n && typeof candidate.pid === \"number\"\n && typeof candidate.startedAt === \"string\"\n );\n}\n\nfunction formatOccupancyError(code: OccupancyErrorCode, detail: string): string {\n return `${code}${ERROR_DETAIL_SEPARATOR}${detail}`;\n}\n\nfunction toErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n","/**\n * Worktree process table — the injected boundary the worktree commands read the\n * OS process table through: liveness (`kill -0`), a process's start time and\n * parent for the controlling-process walk, and its command for agent-runtime\n * recognition. The default binding reads the real process table; tests inject a\n * controlled table.\n *\n * @module domains/worktree/process-table\n */\n\nimport { spawnSync } from \"node:child_process\";\nimport { hostname } from \"node:os\";\n\nimport { hasErrorCode } from \"@/lib/state-store\";\n\nimport type { ProcessProbe } from \"./occupancy-store\";\n\n/** The process-table reads the controlling-process resolution and liveness need. */\nexport interface ProcessTable extends ProcessProbe {\n parentOf(pid: number): number | undefined;\n commandOf(pid: number): string | undefined;\n}\n\n// Absolute path to a fixed, unwriteable location so PATH cannot shadow `ps`.\n// Where `/bin/ps` is absent, `startTimeOf` returns undefined; classification\n// treats a live same-host process with an unreadable start time as occupied\n// (see classifyOccupancy), so a live holder is never freed by a missing `ps`.\nconst PS_COMMAND = \"/bin/ps\";\nconst PS_FIELD = {\n START_TIME: \"lstart\",\n PARENT_PID: \"ppid\",\n // The full command line, not `comm` — `comm` reports only the executable\n // basename, so a shebang-installed agent run through an interpreter reads as\n // the interpreter (e.g. `node`) and the agent-runtime match misses it. `args`\n // carries the script path, so both native and interpreted agents are matched.\n COMMAND: \"args\",\n} as const;\nconst SIGNAL_LIVENESS_PROBE = 0;\nconst PROCESS_EXISTS_NO_PERMISSION = \"EPERM\";\nconst PID_RADIX = 10;\n// A fixed timezone and locale so a formatted start time (`lstart`) is identical\n// across callers. The claim and a later status read run in different agent\n// environments; without this the same process's start time would format\n// differently and a live holder would compare unequal and read stale.\nconst STABLE_PS_ENV = { ...process.env, TZ: \"UTC\", LC_ALL: \"C\" } as const;\n\nfunction psField(pid: number, field: string): string | undefined {\n const result = spawnSync(PS_COMMAND, [\"-o\", `${field}=`, \"-p\", String(pid)], {\n encoding: \"utf8\",\n env: STABLE_PS_ENV,\n });\n if (result.status !== 0 || typeof result.stdout !== \"string\") return undefined;\n const value = result.stdout.trim();\n return value.length > 0 ? value : undefined;\n}\n\nexport const defaultProcessTable: ProcessTable = {\n currentHost: () => hostname(),\n isAlive: (pid) => {\n try {\n process.kill(pid, SIGNAL_LIVENESS_PROBE);\n return true;\n } catch (error) {\n return hasErrorCode(error, PROCESS_EXISTS_NO_PERMISSION);\n }\n },\n startTimeOf: (pid) => psField(pid, PS_FIELD.START_TIME),\n parentOf: (pid) => {\n const value = psField(pid, PS_FIELD.PARENT_PID);\n if (value === undefined) return undefined;\n const parsed = Number.parseInt(value, PID_RADIX);\n return Number.isInteger(parsed) ? parsed : undefined;\n },\n commandOf: (pid) => psField(pid, PS_FIELD.COMMAND),\n};\n","/**\n * Shared worktree-command resolution: the `.spx/worktrees` scope directory and\n * the running worktree's claim name.\n *\n * @module commands/worktree/resolve\n */\n\nimport { stat } from \"node:fs/promises\";\nimport { dirname, resolve } from \"node:path\";\n\nimport type { Result } from \"@/config/types\";\nimport { worktreeClaimName } from \"@/domains/worktree/worktree-name\";\nimport { detectWorktreeProductRoot, type GitDependencies } from \"@/git/root\";\nimport { resolveWorktreesScopeDir } from \"@/lib/state-store\";\n\nexport const WORKTREE_RESOLVE_ERROR = {\n NOT_A_WORKTREE: \"path resolves to no worktree\",\n} as const;\n\n/** Receives a non-git-repo diagnostic for the descriptor to surface to stderr. */\nexport type WorktreeWarningHandler = (warning: string | undefined) => void;\n\nexport interface WorktreeScopeOptions {\n /** Working directory the resolution runs from. Defaults to the process cwd. */\n readonly cwd?: string;\n /** Explicit `.spx/worktrees` directory; bypasses git resolution when provided. */\n readonly worktreesDir?: string;\n /** Injected git runner for resolution. */\n readonly gitDeps?: GitDependencies;\n /** Receives the non-git-repo diagnostic the shared-root resolution surfaces. */\n readonly onWarning?: WorktreeWarningHandler;\n}\n\n/** The shared `.spx/worktrees` scope directory — the explicit override or the git-resolved root. */\nexport async function resolveWorktreesDir(options: WorktreeScopeOptions): Promise<string> {\n if (options.worktreesDir !== undefined) return options.worktreesDir;\n const resolved = await resolveWorktreesScopeDir({ cwd: options.cwd, deps: options.gitDeps });\n options.onWarning?.(resolved.warning);\n return resolved.worktreesDir;\n}\n\n/** The claim name for the worktree the command runs in. */\nexport async function resolveCurrentWorktreeName(options: WorktreeScopeOptions): Promise<string> {\n const worktree = await detectWorktreeProductRoot(options.cwd, options.gitDeps);\n return worktreeClaimName(worktree.productDir);\n}\n\n/** A status target's claim name and the worktree root both its name and its `.spx/worktrees` scope derive from. */\nexport interface ResolvedTargetWorktree {\n readonly name: string;\n readonly worktreeRoot: string;\n}\n\n/**\n * The worktree a status target denotes. The target is the `worktree` path\n * resolved against the running directory, or the running directory itself when\n * omitted; its worktree root is resolved through the same git resolution claim\n * and release use, so any path inside a worktree — the root, `.`, or a path\n * within — names the same claim. The resolved root is returned so the claim\n * scope resolves from the same worktree the name does, never from the caller's\n * unrelated working directory. A target that resolves to no worktree is refused\n * rather than keyed on a bare path segment.\n */\nexport async function resolveTargetWorktree(\n options: WorktreeScopeOptions & { readonly worktree?: string },\n): Promise<Result<ResolvedTargetWorktree>> {\n const base = options.cwd ?? process.cwd();\n const targetPath = options.worktree === undefined ? base : resolve(base, options.worktree);\n const targetGitPath = (await isExistingNonDirectory(targetPath)) ? dirname(targetPath) : targetPath;\n const worktree = await detectWorktreeProductRoot(targetGitPath, options.gitDeps);\n if (!worktree.isGitRepo) {\n return { ok: false, error: `${WORKTREE_RESOLVE_ERROR.NOT_A_WORKTREE}: ${options.worktree ?? base}` };\n }\n return { ok: true, value: { name: worktreeClaimName(worktree.productDir), worktreeRoot: worktree.productDir } };\n}\n\nasync function isExistingNonDirectory(path: string): Promise<boolean> {\n try {\n const pathStats = await stat(path);\n return !pathStats.isDirectory();\n } catch {\n return false;\n }\n}\n","/**\n * Worktree claim-name derivation — the `<name>` keying a worktree's claim file\n * is the worktree directory's basename reduced to a safe scope token.\n *\n * @module domains/worktree/worktree-name\n */\n\nimport { basename } from \"node:path\";\n\n// A separator is anything outside the kept set — letters, digits, and\n// underscore. Hyphen is a separator, not kept, so a leading, trailing, or\n// repeated hyphen never survives into the claim name.\nconst SEPARATOR_CHARACTER = /[^a-z0-9_]/;\nconst NAME_SEPARATOR = \"-\";\n\n/**\n * The claim name for a worktree root path: its basename lowercased, then split\n * on each separator character and the non-empty segments rejoined with a single\n * hyphen. Splitting on the separator collapses runs and drops edge separators\n * without a quantified pattern, so the result is a safe scope token.\n */\nexport function worktreeClaimName(worktreeRoot: string): string {\n return basename(worktreeRoot)\n .toLowerCase()\n .split(SEPARATOR_CHARACTER)\n .filter((segment) => segment.length > 0)\n .join(NAME_SEPARATOR);\n}\n","/**\n * `spx worktree claim` handler — records a worktree-occupancy claim for the\n * running worktree keyed on its controlling agent process.\n *\n * @module commands/worktree/claim\n */\n\nimport type { Result } from \"@/config/types\";\nimport { type ControllingProcessEnv, resolveControllingProcess } from \"@/domains/worktree/controlling-process\";\nimport { type OccupancyFileSystem, writeClaim } from \"@/domains/worktree/occupancy-store\";\nimport { defaultProcessTable, type ProcessTable } from \"@/domains/worktree/process-table\";\n\nimport { resolveCurrentWorktreeName, resolveWorktreesDir, type WorktreeScopeOptions } from \"./resolve\";\n\nexport interface ClaimCommandOptions extends WorktreeScopeOptions {\n /** The claiming agent's session id. */\n readonly sessionId: string;\n /** Environment read for the controlling-pid override. Defaults to `process.env`. */\n readonly env?: ControllingProcessEnv;\n /** Injected process table. Defaults to the real process table. */\n readonly processTable?: ProcessTable;\n /** spx's own pid, the ancestry walk starts above. Defaults to `process.pid`. */\n readonly selfPid?: number;\n /** Injected claim filesystem. */\n readonly fs?: OccupancyFileSystem;\n}\n\n/** Records a claim for the running worktree; returns the written claim path. */\nexport async function claimCommand(options: ClaimCommandOptions): Promise<Result<string>> {\n const table = options.processTable ?? defaultProcessTable;\n const controlling = resolveControllingProcess(options.selfPid ?? process.pid, table, options.env ?? process.env);\n if (!controlling.ok) return controlling;\n\n const worktreesDir = await resolveWorktreesDir(options);\n const name = await resolveCurrentWorktreeName(options);\n return writeClaim(\n worktreesDir,\n name,\n {\n sessionId: options.sessionId,\n host: controlling.value.host,\n pid: controlling.value.pid,\n startedAt: controlling.value.startedAt,\n },\n { fs: options.fs },\n );\n}\n","/**\n * `spx worktree release` handler — removes the running worktree's claim.\n *\n * @module commands/worktree/release\n */\n\nimport type { Result } from \"@/config/types\";\nimport { type OccupancyFileSystem, removeClaim } from \"@/domains/worktree/occupancy-store\";\n\nimport { resolveCurrentWorktreeName, resolveWorktreesDir, type WorktreeScopeOptions } from \"./resolve\";\n\nexport interface ReleaseCommandOptions extends WorktreeScopeOptions {\n /** Injected claim filesystem. */\n readonly fs?: OccupancyFileSystem;\n}\n\n/** Removes the running worktree's claim. Idempotent — a missing claim is success. */\nexport async function releaseCommand(options: ReleaseCommandOptions): Promise<Result<void>> {\n const worktreesDir = await resolveWorktreesDir(options);\n const name = await resolveCurrentWorktreeName(options);\n return removeClaim(worktreesDir, name, { fs: options.fs });\n}\n","/**\n * `spx worktree status` handler — reports worktree occupancy as rendered text\n * lines or machine-parseable JSON.\n *\n * @module commands/worktree/status\n */\n\nimport type { Result } from \"@/config/types\";\nimport { type OccupancyFileSystem, type OccupancyStatus, readOccupancy } from \"@/domains/worktree/occupancy-store\";\nimport { defaultProcessTable, type ProcessTable } from \"@/domains/worktree/process-table\";\n\nimport { resolveTargetWorktree, resolveWorktreesDir, type ResolvedTargetWorktree, type WorktreeScopeOptions } from \"./resolve\";\n\nexport const WORKTREE_STATUS_FORMAT = {\n JSON: \"json\",\n TEXT: \"text\",\n} as const;\n\nexport type WorktreeStatusFormat = (typeof WORKTREE_STATUS_FORMAT)[keyof typeof WORKTREE_STATUS_FORMAT];\n\nexport interface StatusCommandOptions extends WorktreeScopeOptions {\n /** The worktrees to query — paths inside them; defaults to the running directory when omitted. */\n readonly worktrees?: readonly string[];\n /** Output format; defaults to text. */\n readonly format?: string;\n /** Injected process table. Defaults to the real process table. */\n readonly processTable?: ProcessTable;\n /** Injected claim filesystem. */\n readonly fs?: OccupancyFileSystem;\n}\n\ninterface WorktreeStatusRecord {\n readonly worktree: string;\n readonly status: OccupancyStatus;\n}\n\n/** Reads target worktree occupancy and renders it in the requested format. */\nexport async function statusCommand(options: StatusCommandOptions): Promise<Result<string>> {\n const table = options.processTable ?? defaultProcessTable;\n const multiTargetRequest = options.worktrees !== undefined && options.worktrees.length > 1;\n const targets = await resolveStatusTargets(options);\n if (!targets.ok) return targets;\n\n const records: WorktreeStatusRecord[] = [];\n for (const target of targets.value) {\n const worktreesDir = await resolveWorktreesDir({ ...options, cwd: target.worktreeRoot });\n const occupancy = await readOccupancy(worktreesDir, target.name, table, { fs: options.fs });\n if (!occupancy.ok) return occupancy;\n records.push({ worktree: target.name, status: occupancy.value });\n }\n\n return { ok: true, value: renderStatus(records, options.format, multiTargetRequest) };\n}\n\nasync function resolveStatusTargets(options: StatusCommandOptions): Promise<Result<readonly ResolvedTargetWorktree[]>> {\n const requested = options.worktrees;\n if (requested === undefined || requested.length === 0) {\n const target = await resolveTargetWorktree(options);\n if (!target.ok) return target;\n return { ok: true, value: [target.value] };\n }\n\n const targets: ResolvedTargetWorktree[] = [];\n let firstError: string | undefined;\n for (const worktree of requested) {\n const target = await resolveTargetWorktree({ ...options, worktree });\n if (target.ok) {\n targets.push(target.value);\n } else {\n firstError ??= target.error;\n }\n }\n\n if (targets.length === 0) {\n return { ok: false, error: firstError ?? \"no worktree status targets resolved\" };\n }\n\n return { ok: true, value: targets };\n}\n\nfunction renderStatus(records: readonly WorktreeStatusRecord[], format: string | undefined, multiTargetRequest: boolean): string {\n if (format === WORKTREE_STATUS_FORMAT.JSON) {\n return JSON.stringify(multiTargetRequest ? records : records[0]);\n }\n return records.map(renderTextStatus).join(\"\\n\");\n}\n\nfunction renderTextStatus(record: WorktreeStatusRecord): string {\n return `${record.worktree} ${record.status}`;\n}\n","/**\n * Worktree CLI — Commander registration descriptor for the `spx worktree`\n * occupancy subcommands (claim, status, release).\n */\nimport type { Command } from \"commander\";\n\nimport { claimCommand, releaseCommand, statusCommand, WORKTREE_STATUS_FORMAT } from \"@/commands/worktree/index\";\nimport type { Domain } from \"@/domains/types\";\n\nimport { writeWarning } from \"./write-warning\";\n\n/** Source-owned `spx worktree` command and flag vocabulary, shared with the CLI tests. */\nexport const WORKTREE_CLI = {\n COMMAND: \"worktree\",\n CLAIM: \"claim\",\n STATUS: \"status\",\n RELEASE: \"release\",\n WORKTREE_ARGUMENT: \"[worktrees...]\",\n SESSION_ID_FLAG: \"--session-id\",\n FORMAT_FLAG: \"--format\",\n WORKTREES_DIR_FLAG: \"--worktrees-dir\",\n} as const;\n\nconst WORKTREE_DOMAIN_DESCRIPTION = \"Coordinate worktree occupancy across a bare-repository pool\";\n\nfunction handleError(error: string): never {\n console.error(\"Error:\", error);\n process.exit(1);\n}\n\nfunction registerWorktreeCommands(worktreeCmd: Command): void {\n worktreeCmd\n .command(WORKTREE_CLI.CLAIM)\n .description(\"Record a worktree-occupancy claim for the running worktree\")\n .requiredOption(`${WORKTREE_CLI.SESSION_ID_FLAG} <id>`, \"Claiming agent session id\")\n .option(`${WORKTREE_CLI.WORKTREES_DIR_FLAG} <path>`, \"Explicit .spx/worktrees directory\")\n .action(async (options: { sessionId: string; worktreesDir?: string }) => {\n const result = await claimCommand({\n sessionId: options.sessionId,\n worktreesDir: options.worktreesDir,\n onWarning: writeWarning,\n });\n if (!result.ok) handleError(result.error);\n // A successful claim writes nothing to stdout — the SessionStart hook\n // injects a command's stdout into the agent's context.\n });\n\n worktreeCmd\n .command(`${WORKTREE_CLI.STATUS} ${WORKTREE_CLI.WORKTREE_ARGUMENT}`)\n .description(\"Report a worktree's occupancy (occupied | unclaimed | stale)\")\n .option(`${WORKTREE_CLI.FORMAT_FLAG} <format>`, \"Output format (text|json)\", WORKTREE_STATUS_FORMAT.TEXT)\n .option(`${WORKTREE_CLI.WORKTREES_DIR_FLAG} <path>`, \"Explicit .spx/worktrees directory\")\n .action(async (worktrees: string[] | undefined, options: { format?: string; worktreesDir?: string }) => {\n const result = await statusCommand({\n worktrees,\n format: options.format,\n worktreesDir: options.worktreesDir,\n onWarning: writeWarning,\n });\n if (!result.ok) handleError(result.error);\n console.log(result.value);\n });\n\n worktreeCmd\n .command(WORKTREE_CLI.RELEASE)\n .description(\"Release the running worktree's occupancy claim\")\n .option(`${WORKTREE_CLI.WORKTREES_DIR_FLAG} <path>`, \"Explicit .spx/worktrees directory\")\n .action(async (options: { worktreesDir?: string }) => {\n const result = await releaseCommand({ worktreesDir: options.worktreesDir, onWarning: writeWarning });\n if (!result.ok) handleError(result.error);\n });\n}\n\n/**\n * Worktree CLI — Commander registration descriptor for the worktree subcommands.\n */\nexport const worktreeDomain: Domain = {\n name: WORKTREE_CLI.COMMAND,\n description: WORKTREE_DOMAIN_DESCRIPTION,\n register: (program: Command) => {\n const worktreeCmd = program\n .command(WORKTREE_CLI.COMMAND)\n .description(WORKTREE_DOMAIN_DESCRIPTION);\n\n registerWorktreeCommands(worktreeCmd);\n },\n};\n","import type { Domain } from \"@/domains/types\";\n\nimport { claudeDomain } from \"./claude\";\nimport { compactDomain } from \"./compact\";\nimport { configDomain } from \"./config\";\nimport { sessionDomain } from \"./session\";\nimport { specDomain } from \"./spec\";\nimport { testingDomain } from \"./testing\";\nimport { validationDomain } from \"./validation\";\nimport { worktreeDomain } from \"./worktree\";\n\nexport const CLI_DOMAINS: readonly Domain[] = [\n claudeDomain,\n compactDomain,\n configDomain,\n sessionDomain,\n specDomain,\n testingDomain,\n validationDomain,\n worktreeDomain,\n];\n"],"mappings":"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;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,GAAG,IAAI;AAC5C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,GAAG,IAAI,EAAE,IAAI;AAC3C,EAAAA,gBAAeA,gBAAe,UAAU,IAAI,EAAE,IAAI;AAClD,EAAAA,gBAAeA,gBAAe,WAAW,IAAI,EAAE,IAAI;AACnD,EAAAA,gBAAeA,gBAAe,YAAY,IAAI,GAAG,IAAI;AACrD,EAAAA,gBAAeA,gBAAe,cAAc,IAAI,EAAE,IAAI;AACtD,EAAAA,gBAAeA,gBAAe,OAAO,IAAI,EAAE,IAAI;AAC/C,EAAAA,gBAAeA,gBAAe,OAAO,IAAI,EAAE,IAAI;AAC/C,EAAAA,gBAAeA,gBAAe,KAAK,IAAI,EAAE,IAAI;AAC7C,EAAAA,gBAAeA,gBAAe,aAAa,IAAI,EAAE,IAAI;AACrD,EAAAA,gBAAeA,gBAAe,OAAO,IAAI,EAAE,IAAI;AAC/C,EAAAA,gBAAeA,gBAAe,WAAW,IAAI,GAAG,IAAI;AACpD,EAAAA,gBAAeA,gBAAe,aAAa,IAAI,EAAE,IAAI;AACrD,EAAAA,gBAAeA,gBAAe,MAAM,IAAI,EAAE,IAAI;AAC9C,EAAAA,gBAAeA,gBAAe,OAAO,IAAI,EAAE,IAAI;AAC/C,EAAAA,gBAAeA,gBAAe,UAAU,IAAI,EAAE,IAAI;AAClD,EAAAA,gBAAeA,gBAAe,KAAK,IAAI,CAAC,IAAI;AAChD,GAAG,mBAAmB,iBAAiB,CAAC,EAAE;;;AC1bnC,IAAM,eAAe,IAAI,MAAM,EAAE,EAAE,KAAK,CAAC,EAAE,IAAI,CAAC,GAAG,UAAU;AAChE,SAAO,IAAI,OAAO,KAAK;AAC3B,CAAC;AACD,IAAM,kBAAkB;AACjB,IAAM,6BAA6B;AAAA,EACtC,KAAK;AAAA,IACD,MAAM,IAAI,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,IAAI,CAAC,GAAG,UAAU;AACvD,aAAO,OAAO,IAAI,OAAO,KAAK;AAAA,IAClC,CAAC;AAAA,IACD,MAAM,IAAI,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,IAAI,CAAC,GAAG,UAAU;AACvD,aAAO,OAAO,IAAI,OAAO,KAAK;AAAA,IAClC,CAAC;AAAA,IACD,QAAQ,IAAI,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,IAAI,CAAC,GAAG,UAAU;AACzD,aAAO,SAAS,IAAI,OAAO,KAAK;AAAA,IACpC,CAAC;AAAA,EACL;AAAA,EACA,KAAM;AAAA,IACF,MAAM,IAAI,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,IAAI,CAAC,GAAG,UAAU;AACvD,aAAO,OAAO,IAAK,OAAO,KAAK;AAAA,IACnC,CAAC;AAAA,IACD,MAAM,IAAI,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,IAAI,CAAC,GAAG,UAAU;AACvD,aAAO,OAAO,IAAK,OAAO,KAAK;AAAA,IACnC,CAAC;AAAA,IACD,QAAQ,IAAI,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,IAAI,CAAC,GAAG,UAAU;AACzD,aAAO,SAAS,IAAK,OAAO,KAAK;AAAA,IACrC,CAAC;AAAA,EACL;AACJ;;;ACrBA,IAAI;AAAA,CACH,SAAUC,eAAc;AACrB,EAAAA,cAAa,UAAU;AAAA,IACnB,oBAAoB;AAAA,EACxB;AACJ,GAAG,iBAAiB,eAAe,CAAC,EAAE;AA4H/B,SAAS,MAAM,MAAM,SAAS,CAAC,GAAG,UAAU,aAAa,SAAS;AACrE,MAAI,kBAAkB;AACtB,MAAI,gBAAgB,CAAC;AACrB,QAAM,kBAAkB,CAAC;AACzB,WAAS,QAAQ,OAAO;AACpB,QAAI,MAAM,QAAQ,aAAa,GAAG;AAC9B,oBAAc,KAAK,KAAK;AAAA,IAC5B,WACS,oBAAoB,MAAM;AAC/B,oBAAc,eAAe,IAAI;AAAA,IACrC;AAAA,EACJ;AACA,QAAM,UAAU;AAAA,IACZ,eAAe,MAAM;AACjB,YAAM,SAAS,CAAC;AAChB,cAAQ,MAAM;AACd,sBAAgB,KAAK,aAAa;AAClC,sBAAgB;AAChB,wBAAkB;AAAA,IACtB;AAAA,IACA,kBAAkB,CAAC,SAAS;AACxB,wBAAkB;AAAA,IACtB;AAAA,IACA,aAAa,MAAM;AACf,sBAAgB,gBAAgB,IAAI;AAAA,IACxC;AAAA,IACA,cAAc,MAAM;AAChB,YAAM,QAAQ,CAAC;AACf,cAAQ,KAAK;AACb,sBAAgB,KAAK,aAAa;AAClC,sBAAgB;AAChB,wBAAkB;AAAA,IACtB;AAAA,IACA,YAAY,MAAM;AACd,sBAAgB,gBAAgB,IAAI;AAAA,IACxC;AAAA,IACA,gBAAgB;AAAA,IAChB,SAAS,CAAC,OAAO,QAAQ,WAAW;AAChC,aAAO,KAAK,EAAE,OAAO,QAAQ,OAAO,CAAC;AAAA,IACzC;AAAA,EACJ;AACA,QAAM,MAAM,SAAS,OAAO;AAC5B,SAAO,cAAc,CAAC;AAC1B;AAuKO,SAAS,MAAM,MAAM,SAAS,UAAU,aAAa,SAAS;AACjE,QAAM,WAAW,cAAc,MAAM,KAAK;AAG1C,QAAM,YAAY,CAAC;AAGnB,MAAI,sBAAsB;AAC1B,WAAS,aAAa,eAAe;AACjC,WAAO,gBAAgB,MAAM,wBAAwB,KAAK,cAAc,SAAS,eAAe,GAAG,SAAS,eAAe,GAAG,SAAS,kBAAkB,GAAG,SAAS,uBAAuB,CAAC,IAAI,MAAM;AAAA,EAC3M;AACA,WAAS,cAAc,eAAe;AAClC,WAAO,gBAAgB,CAAC,QAAQ,wBAAwB,KAAK,cAAc,KAAK,SAAS,eAAe,GAAG,SAAS,eAAe,GAAG,SAAS,kBAAkB,GAAG,SAAS,uBAAuB,CAAC,IAAI,MAAM;AAAA,EACnN;AACA,WAAS,sBAAsB,eAAe;AAC1C,WAAO,gBAAgB,CAAC,QAAQ,wBAAwB,KAAK,cAAc,KAAK,SAAS,eAAe,GAAG,SAAS,eAAe,GAAG,SAAS,kBAAkB,GAAG,SAAS,uBAAuB,GAAG,MAAM,UAAU,MAAM,CAAC,IAAI,MAAM;AAAA,EAC5O;AACA,WAAS,aAAa,eAAe;AACjC,WAAO,gBACH,MAAM;AACF,UAAI,sBAAsB,GAAG;AACzB;AAAA,MACJ,OACK;AACD,YAAI,WAAW,cAAc,SAAS,eAAe,GAAG,SAAS,eAAe,GAAG,SAAS,kBAAkB,GAAG,SAAS,uBAAuB,GAAG,MAAM,UAAU,MAAM,CAAC;AAC3K,YAAI,aAAa,OAAO;AACpB,gCAAsB;AAAA,QAC1B;AAAA,MACJ;AAAA,IACJ,IACE,MAAM;AAAA,EAChB;AACA,WAAS,WAAW,eAAe;AAC/B,WAAO,gBACH,MAAM;AACF,UAAI,sBAAsB,GAAG;AACzB;AAAA,MACJ;AACA,UAAI,wBAAwB,GAAG;AAC3B,sBAAc,SAAS,eAAe,GAAG,SAAS,eAAe,GAAG,SAAS,kBAAkB,GAAG,SAAS,uBAAuB,CAAC;AAAA,MACvI;AAAA,IACJ,IACE,MAAM;AAAA,EAChB;AACA,QAAM,gBAAgB,aAAa,QAAQ,aAAa,GAAG,mBAAmB,sBAAsB,QAAQ,gBAAgB,GAAG,cAAc,WAAW,QAAQ,WAAW,GAAG,eAAe,aAAa,QAAQ,YAAY,GAAG,aAAa,WAAW,QAAQ,UAAU,GAAG,iBAAiB,sBAAsB,QAAQ,cAAc,GAAG,cAAc,cAAc,QAAQ,WAAW,GAAG,YAAY,aAAa,QAAQ,SAAS,GAAG,UAAU,cAAc,QAAQ,OAAO;AACpd,QAAM,mBAAmB,WAAW,QAAQ;AAC5C,QAAM,qBAAqB,WAAW,QAAQ;AAC9C,WAAS,WAAW;AAChB,WAAO,MAAM;AACT,YAAM,QAAQ,SAAS,KAAK;AAC5B,cAAQ,SAAS,cAAc,GAAG;AAAA,QAC9B,KAAK;AACD,UAAAC;AAAA,YAAY;AAAA;AAAA,UAAsC;AAClD;AAAA,QACJ,KAAK;AACD,UAAAA;AAAA,YAAY;AAAA;AAAA,UAA8C;AAC1D;AAAA,QACJ,KAAK;AACD,UAAAA;AAAA,YAAY;AAAA;AAAA,UAA6C;AACzD;AAAA,QACJ,KAAK;AACD,cAAI,CAAC,kBAAkB;AACnB,YAAAA;AAAA,cAAY;AAAA;AAAA,YAA8C;AAAA,UAC9D;AACA;AAAA,QACJ,KAAK;AACD,UAAAA;AAAA,YAAY;AAAA;AAAA,UAA6C;AACzD;AAAA,QACJ,KAAK;AACD,UAAAA;AAAA,YAAY;AAAA;AAAA,UAAwC;AACpD;AAAA,MACR;AACA,cAAQ,OAAO;AAAA,QACX,KAAK;AAAA,QACL,KAAK;AACD,cAAI,kBAAkB;AAClB,YAAAA;AAAA,cAAY;AAAA;AAAA,YAA2C;AAAA,UAC3D,OACK;AACD,sBAAU;AAAA,UACd;AACA;AAAA,QACJ,KAAK;AACD,UAAAA;AAAA,YAAY;AAAA;AAAA,UAAoC;AAChD;AAAA,QACJ,KAAK;AAAA,QACL,KAAK;AACD;AAAA,QACJ;AACI,iBAAO;AAAA,MACf;AAAA,IACJ;AAAA,EACJ;AACA,WAASA,aAAY,OAAO,iBAAiB,CAAC,GAAG,YAAY,CAAC,GAAG;AAC7D,YAAQ,KAAK;AACb,QAAI,eAAe,SAAS,UAAU,SAAS,GAAG;AAC9C,UAAI,QAAQ,SAAS,SAAS;AAC9B,aAAO,UAAU,IAAyB;AACtC,YAAI,eAAe,QAAQ,KAAK,MAAM,IAAI;AACtC,mBAAS;AACT;AAAA,QACJ,WACS,UAAU,QAAQ,KAAK,MAAM,IAAI;AACtC;AAAA,QACJ;AACA,gBAAQ,SAAS;AAAA,MACrB;AAAA,IACJ;AAAA,EACJ;AACA,WAAS,YAAY,SAAS;AAC1B,UAAM,QAAQ,SAAS,cAAc;AACrC,QAAI,SAAS;AACT,qBAAe,KAAK;AAAA,IACxB,OACK;AACD,uBAAiB,KAAK;AAEtB,gBAAU,KAAK,KAAK;AAAA,IACxB;AACA,aAAS;AACT,WAAO;AAAA,EACX;AACA,WAAS,eAAe;AACpB,YAAQ,SAAS,SAAS,GAAG;AAAA,MACzB,KAAK;AACD,cAAM,aAAa,SAAS,cAAc;AAC1C,YAAI,QAAQ,OAAO,UAAU;AAC7B,YAAI,MAAM,KAAK,GAAG;AACd,UAAAA;AAAA,YAAY;AAAA;AAAA,UAA0C;AACtD,kBAAQ;AAAA,QACZ;AACA,uBAAe,KAAK;AACpB;AAAA,MACJ,KAAK;AACD,uBAAe,IAAI;AACnB;AAAA,MACJ,KAAK;AACD,uBAAe,IAAI;AACnB;AAAA,MACJ,KAAK;AACD,uBAAe,KAAK;AACpB;AAAA,MACJ;AACI,eAAO;AAAA,IACf;AACA,aAAS;AACT,WAAO;AAAA,EACX;AACA,WAAS,gBAAgB;AACrB,QAAI,SAAS,SAAS,MAAM,IAAmC;AAC3D,MAAAA,aAAY,GAA6C,CAAC,GAAG;AAAA,QAAC;AAAA,QAAoC;AAAA;AAAA,MAA6B,CAAC;AAChI,aAAO;AAAA,IACX;AACA,gBAAY,KAAK;AACjB,QAAI,SAAS,SAAS,MAAM,GAA+B;AACvD,kBAAY,GAAG;AACf,eAAS;AACT,UAAI,CAAC,WAAW,GAAG;AACf,QAAAA,aAAY,GAAsC,CAAC,GAAG;AAAA,UAAC;AAAA,UAAoC;AAAA;AAAA,QAA6B,CAAC;AAAA,MAC7H;AAAA,IACJ,OACK;AACD,MAAAA,aAAY,GAAsC,CAAC,GAAG;AAAA,QAAC;AAAA,QAAoC;AAAA;AAAA,MAA6B,CAAC;AAAA,IAC7H;AACA,cAAU,IAAI;AACd,WAAO;AAAA,EACX;AACA,WAAS,cAAc;AACnB,kBAAc;AACd,aAAS;AACT,QAAI,aAAa;AACjB,WAAO,SAAS,SAAS,MAAM,KAAsC,SAAS,SAAS,MAAM,IAAyB;AAClH,UAAI,SAAS,SAAS,MAAM,GAA+B;AACvD,YAAI,CAAC,YAAY;AACb,UAAAA,aAAY,GAAsC,CAAC,GAAG,CAAC,CAAC;AAAA,QAC5D;AACA,oBAAY,GAAG;AACf,iBAAS;AACT,YAAI,SAAS,SAAS,MAAM,KAAsC,oBAAoB;AAClF;AAAA,QACJ;AAAA,MACJ,WACS,YAAY;AACjB,QAAAA,aAAY,GAAsC,CAAC,GAAG,CAAC,CAAC;AAAA,MAC5D;AACA,UAAI,CAAC,cAAc,GAAG;AAClB,QAAAA,aAAY,GAAsC,CAAC,GAAG;AAAA,UAAC;AAAA,UAAoC;AAAA;AAAA,QAA6B,CAAC;AAAA,MAC7H;AACA,mBAAa;AAAA,IACjB;AACA,gBAAY;AACZ,QAAI,SAAS,SAAS,MAAM,GAAoC;AAC5D,MAAAA,aAAY,GAA2C;AAAA,QAAC;AAAA;AAAA,MAAkC,GAAG,CAAC,CAAC;AAAA,IACnG,OACK;AACD,eAAS;AAAA,IACb;AACA,WAAO;AAAA,EACX;AACA,WAAS,aAAa;AAClB,iBAAa;AACb,aAAS;AACT,QAAI,iBAAiB;AACrB,QAAI,aAAa;AACjB,WAAO,SAAS,SAAS,MAAM,KAAwC,SAAS,SAAS,MAAM,IAAyB;AACpH,UAAI,SAAS,SAAS,MAAM,GAA+B;AACvD,YAAI,CAAC,YAAY;AACb,UAAAA,aAAY,GAAsC,CAAC,GAAG,CAAC,CAAC;AAAA,QAC5D;AACA,oBAAY,GAAG;AACf,iBAAS;AACT,YAAI,SAAS,SAAS,MAAM,KAAwC,oBAAoB;AACpF;AAAA,QACJ;AAAA,MACJ,WACS,YAAY;AACjB,QAAAA,aAAY,GAAsC,CAAC,GAAG,CAAC,CAAC;AAAA,MAC5D;AACA,UAAI,gBAAgB;AAChB,kBAAU,KAAK,CAAC;AAChB,yBAAiB;AAAA,MACrB,OACK;AACD,kBAAU,UAAU,SAAS,CAAC;AAAA,MAClC;AACA,UAAI,CAAC,WAAW,GAAG;AACf,QAAAA,aAAY,GAAsC,CAAC,GAAG;AAAA,UAAC;AAAA,UAAsC;AAAA;AAAA,QAA6B,CAAC;AAAA,MAC/H;AACA,mBAAa;AAAA,IACjB;AACA,eAAW;AACX,QAAI,CAAC,gBAAgB;AACjB,gBAAU,IAAI;AAAA,IAClB;AACA,QAAI,SAAS,SAAS,MAAM,GAAsC;AAC9D,MAAAA,aAAY,GAA6C;AAAA,QAAC;AAAA;AAAA,MAAoC,GAAG,CAAC,CAAC;AAAA,IACvG,OACK;AACD,eAAS;AAAA,IACb;AACA,WAAO;AAAA,EACX;AACA,WAAS,aAAa;AAClB,YAAQ,SAAS,SAAS,GAAG;AAAA,MACzB,KAAK;AACD,eAAO,WAAW;AAAA,MACtB,KAAK;AACD,eAAO,YAAY;AAAA,MACvB,KAAK;AACD,eAAO,YAAY,IAAI;AAAA,MAC3B;AACI,eAAO,aAAa;AAAA,IAC5B;AAAA,EACJ;AACA,WAAS;AACT,MAAI,SAAS,SAAS,MAAM,IAAyB;AACjD,QAAI,QAAQ,mBAAmB;AAC3B,aAAO;AAAA,IACX;AACA,IAAAA,aAAY,GAAsC,CAAC,GAAG,CAAC,CAAC;AACxD,WAAO;AAAA,EACX;AACA,MAAI,CAAC,WAAW,GAAG;AACf,IAAAA,aAAY,GAAsC,CAAC,GAAG,CAAC,CAAC;AACxD,WAAO;AAAA,EACX;AACA,MAAI,SAAS,SAAS,MAAM,IAAyB;AACjD,IAAAA,aAAY,GAA0C,CAAC,GAAG,CAAC,CAAC;AAAA,EAChE;AACA,SAAO;AACX;;;ACzlBO,IAAI;AAAA,CACV,SAAUC,YAAW;AAClB,EAAAA,WAAUA,WAAU,MAAM,IAAI,CAAC,IAAI;AACnC,EAAAA,WAAUA,WAAU,wBAAwB,IAAI,CAAC,IAAI;AACrD,EAAAA,WAAUA,WAAU,uBAAuB,IAAI,CAAC,IAAI;AACpD,EAAAA,WAAUA,WAAU,uBAAuB,IAAI,CAAC,IAAI;AACpD,EAAAA,WAAUA,WAAU,gBAAgB,IAAI,CAAC,IAAI;AAC7C,EAAAA,WAAUA,WAAU,wBAAwB,IAAI,CAAC,IAAI;AACrD,EAAAA,WAAUA,WAAU,kBAAkB,IAAI,CAAC,IAAI;AACnD,GAAG,cAAc,YAAY,CAAC,EAAE;AACzB,IAAI;AAAA,CACV,SAAUC,aAAY;AACnB,EAAAA,YAAWA,YAAW,gBAAgB,IAAI,CAAC,IAAI;AAC/C,EAAAA,YAAWA,YAAW,iBAAiB,IAAI,CAAC,IAAI;AAChD,EAAAA,YAAWA,YAAW,kBAAkB,IAAI,CAAC,IAAI;AACjD,EAAAA,YAAWA,YAAW,mBAAmB,IAAI,CAAC,IAAI;AAClD,EAAAA,YAAWA,YAAW,YAAY,IAAI,CAAC,IAAI;AAC3C,EAAAA,YAAWA,YAAW,YAAY,IAAI,CAAC,IAAI;AAC3C,EAAAA,YAAWA,YAAW,aAAa,IAAI,CAAC,IAAI;AAC5C,EAAAA,YAAWA,YAAW,aAAa,IAAI,CAAC,IAAI;AAC5C,EAAAA,YAAWA,YAAW,cAAc,IAAI,CAAC,IAAI;AAC7C,EAAAA,YAAWA,YAAW,eAAe,IAAI,EAAE,IAAI;AAC/C,EAAAA,YAAWA,YAAW,gBAAgB,IAAI,EAAE,IAAI;AAChD,EAAAA,YAAWA,YAAW,mBAAmB,IAAI,EAAE,IAAI;AACnD,EAAAA,YAAWA,YAAW,oBAAoB,IAAI,EAAE,IAAI;AACpD,EAAAA,YAAWA,YAAW,iBAAiB,IAAI,EAAE,IAAI;AACjD,EAAAA,YAAWA,YAAW,QAAQ,IAAI,EAAE,IAAI;AACxC,EAAAA,YAAWA,YAAW,SAAS,IAAI,EAAE,IAAI;AACzC,EAAAA,YAAWA,YAAW,KAAK,IAAI,EAAE,IAAI;AACzC,GAAG,eAAe,aAAa,CAAC,EAAE;AAS3B,IAAMC,SAAe;AA+BrB,IAAI;AAAA,CACV,SAAUC,iBAAgB;AACvB,EAAAA,gBAAeA,gBAAe,eAAe,IAAI,CAAC,IAAI;AACtD,EAAAA,gBAAeA,gBAAe,qBAAqB,IAAI,CAAC,IAAI;AAC5D,EAAAA,gBAAeA,gBAAe,sBAAsB,IAAI,CAAC,IAAI;AAC7D,EAAAA,gBAAeA,gBAAe,eAAe,IAAI,CAAC,IAAI;AACtD,EAAAA,gBAAeA,gBAAe,eAAe,IAAI,CAAC,IAAI;AACtD,EAAAA,gBAAeA,gBAAe,eAAe,IAAI,CAAC,IAAI;AACtD,EAAAA,gBAAeA,gBAAe,oBAAoB,IAAI,CAAC,IAAI;AAC3D,EAAAA,gBAAeA,gBAAe,sBAAsB,IAAI,CAAC,IAAI;AAC7D,EAAAA,gBAAeA,gBAAe,mBAAmB,IAAI,CAAC,IAAI;AAC1D,EAAAA,gBAAeA,gBAAe,qBAAqB,IAAI,EAAE,IAAI;AAC7D,EAAAA,gBAAeA,gBAAe,wBAAwB,IAAI,EAAE,IAAI;AAChE,EAAAA,gBAAeA,gBAAe,uBAAuB,IAAI,EAAE,IAAI;AAC/D,EAAAA,gBAAeA,gBAAe,uBAAuB,IAAI,EAAE,IAAI;AAC/D,EAAAA,gBAAeA,gBAAe,gBAAgB,IAAI,EAAE,IAAI;AACxD,EAAAA,gBAAeA,gBAAe,wBAAwB,IAAI,EAAE,IAAI;AAChE,EAAAA,gBAAeA,gBAAe,kBAAkB,IAAI,EAAE,IAAI;AAC9D,GAAG,mBAAmB,iBAAiB,CAAC,EAAE;;;AC1F1C,SAAS,cAAAC,aAAY,aAAa,gBAAAC,qBAAoB;AACtD,SAAS,cAAAC,aAAY,QAAAC,cAAY;AAY1B,IAAM,iBAAiB;AAAA,EAC5B,MAAM;AAAA,EACN,YAAY;AACd;AACA,IAAMC,0BAAyB;AAC/B,IAAM,cAAc;AACpB,IAAM,qBAAqB;AAoBpB,IAAM,mBAA8B;AAAA,EACzC,cAAAC;AAAA,EACA,YAAAC;AAAA,EACA;AACF;AAYA,SAAS,mBAAmB,aAAqBC,OAAsB;AACrE,SAAOC,YAAWD,KAAI,IAAIA,QAAOE,OAAK,aAAaF,KAAI;AACzD;AAaO,SAAS,sBACd,YACA,OAAkB,kBACA;AAClB,MAAI;AACF,UAAM,gBAAgB,KAAK,aAAa,YAAY,OAAO;AAC3D,UAAM,SAAeG,OAAM,aAAa;AACxC,WAAO;AAAA,EACT,QAAQ;AAEN,WAAO;AAAA,MACL,SAAS,CAAC,WAAW,UAAU;AAAA,MAC/B,SAAS,CAAC,mBAAmB,kBAAkB,SAAS;AAAA,IAC1D;AAAA,EACF;AACF;AASO,SAAS,wBACd,OACA,aACA,OAAkB,kBACA;AAClB,QAAM,aAAa,eAAe,KAAK;AACvC,QAAM,SAAS,sBAAsB,mBAAmB,aAAa,UAAU,GAAG,IAAI;AAEtF,MAAI,OAAO,SAAS;AAClB,UAAM,cAAc,iBAAiB,OAAO,OAAO,EAChD,IAAI,CAAC,mBAAmB,sBAAsB,mBAAmB,aAAa,cAAc,GAAG,IAAI,CAAC;AAIvG,UAAM,mBAAmB,CAAC,GAAG,WAAW,EAAE,QAAQ,EAAE,KAAK,CAAC,eAAe,WAAW,YAAY,MAAS,GAAG,WACvG,CAAC;AACN,UAAM,mBAAmB,CAAC,GAAG,WAAW,EAAE,QAAQ,EAAE,KAAK,CAAC,eAAe,WAAW,YAAY,MAAS,GAAG,WACvG,CAAC;AACN,WAAO;AAAA,MACL,SAAS,OAAO,WAAW;AAAA,MAC3B,SAAS,OAAO,WAAW;AAAA,IAC7B;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW,CAAC;AAAA,IAC5B,SAAS,OAAO,WAAW,CAAC;AAAA,EAC9B;AACF;AAEA,SAAS,iBAAiB,eAAqD;AAC7E,SAAO,MAAM,QAAQ,aAAa,IAAI,gBAAgB,CAAC,aAAa;AACtE;AAUO,SAAS,4BACd,SACA,WAAmB,GACnB,OAAkB,kBACT;AACT,MAAI,YAAY,EAAG,QAAO;AAE1B,MAAI;AACF,UAAM,QAAQ,KAAK,YAAY,SAAS,EAAE,eAAe,KAAK,CAAC;AAG/D,UAAM,mBAAmB,MAAM;AAAA,MAC7B,CAAC,SAAS,KAAK,OAAO,MAAM,KAAK,KAAK,SAAS,KAAK,KAAK,KAAK,KAAK,SAAS,MAAM;AAAA,IACpF;AAEA,QAAI,iBAAkB,QAAO;AAG7B,UAAM,UAAU,MAAM,OAAO,CAAC,SAAS,KAAK,YAAY,KAAK,CAAC,KAAK,KAAK,WAAW,GAAG,CAAC;AACvF,eAAW,UAAU,QAAQ,MAAM,GAAG,CAAC,GAAG;AAExC,UAAI,4BAA4BD,OAAK,SAAS,OAAO,IAAI,GAAG,WAAW,GAAG,IAAI,GAAG;AAC/E,eAAO;AAAA,MACT;AAAA,IACF;AAEA,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AASO,SAAS,qCACd,QACA,aACA,OAAkB,kBACR;AACV,QAAM,mBAAmB,KAAK,YAAY,aAAa,EAAE,eAAe,KAAK,CAAC;AAC9E,QAAM,cAAc,oBAAI,IAAY;AAGpC,QAAM,eAAe,iBAClB,OAAO,CAAC,SAAS,KAAK,YAAY,CAAC,EACnC,IAAI,CAAC,SAAS,KAAK,IAAI,EACvB,OAAO,CAAC,SAAS,CAAC,KAAK,WAAW,GAAG,CAAC;AAGzC,aAAW,OAAO,cAAc;AAE9B,UAAM,aAAa,OAAO,SAAS,KAAK,CAAC,YAAY;AAEnD,UAAI,QAAQ,SAAS,KAAK,GAAG;AAC3B,cAAM,aAAa,QAAQ,MAAM,KAAK,EAAE,CAAC;AACzC,eAAO,eAAe;AAAA,MACxB;AAEA,aAAO,YAAY,OAAO,QAAQ,WAAW,MAAM,GAAG,KAAK,YAAY,MAAM;AAAA,IAC/E,CAAC;AAED,QAAI,CAAC,YAAY;AAEf,UAAI;AACF,cAAM,qBAAqB,4BAA4BA,OAAK,aAAa,GAAG,GAAG,GAAG,IAAI;AACtF,YAAI,oBAAoB;AACtB,sBAAY,IAAI,GAAG;AAAA,QACrB;AAAA,MACF,QAAQ;AAEN;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,MAAI,OAAO,SAAS;AAClB,eAAW,WAAW,OAAO,SAAS;AAEpC,UAAI,QAAQ,SAASL,uBAAsB,GAAG;AAC5C,cAAM,cAAc,mCAAmC,OAAO;AAC9D,YAAI,aAAa;AACf,sBAAY,IAAI,WAAW;AAAA,QAC7B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,WAAW,EAAE,KAAK;AACtC;AAEA,SAAS,mCAAmC,SAAgC;AAC1E,QAAM,cAAc,QAAQ,MAAMA,uBAAsB,EAAE,CAAC;AAC3D,MAAI,CAAC,eAAe,YAAY,SAAS,WAAW,KAAK,YAAY,WAAW,kBAAkB,GAAG;AACnG,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,4BACP,UACA,iBACA,aACA,MACU;AACV,SAAO,SACJ,OAAO,CAAC,YAAY;AACnB,UAAM,cAAc,mCAAmC,OAAO;AAC9D,WAAO,gBAAgB,QAAQ,KAAK,WAAWK,OAAK,aAAa,WAAW,CAAC;AAAA,EAC/E,CAAC,EACA,OAAO,CAAC,YAAY,2BAA2B,SAAS,EAAE,SAAS,gBAAgB,CAAC,CAAC;AAC1F;AASO,SAAS,yBACd,OACA,aACA,OAAkB,kBACR;AAEV,QAAM,SAAS,wBAAwB,OAAO,aAAa,IAAI;AAG/D,QAAM,oBAAoB,qCAAqC,QAAQ,aAAa,IAAI;AAGxF,QAAM,sBAAsB,kBAAkB,OAAO,CAAC,QAAQ,KAAK,WAAWA,OAAK,aAAa,GAAG,CAAC,CAAC;AAErG,SAAO;AACT;AAkBO,SAAS,mBACd,OACA,aACA,OAAkB,kBACL;AAEb,QAAM,cAAc,yBAAyB,OAAO,aAAa,IAAI;AAGrE,QAAM,SAAS,wBAAwB,OAAO,aAAa,IAAI;AAE/D,SAAO;AAAA,IACL;AAAA,IACA,cAAc,4BAA4B,OAAO,WAAW,CAAC,GAAG,OAAO,WAAW,CAAC,GAAG,aAAa,IAAI;AAAA,IACvG,iBAAiB,OAAO,WAAW,CAAC;AAAA,EACtC;AACF;;;ACxTA,SAAS,YAAAE,iBAAgB;AACzB,OAAOC,SAAQ;AACf,SAAS,qBAAqB;AAC9B,OAAOC,WAAU;;;ACHV,IAAM,iBAAiB;AAAA;AAAA,EAE5B,SAAS;AAAA;AAAA,IAEP,SAAS;AAAA;AAAA,IAET,SAAS;AAAA;AAAA,IAET,QAAQ;AAAA,EACV;AAAA;AAAA,EAGA,UAAU;AAAA;AAAA,IAER,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAKb,kBAAkB,CAAC,SACjB,GAAG,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMT,aAAa,CAAC,MAAc,SAC1B,GAAG,eAAe,SAAS,WAAW,aAAa,IAAI,KAAK,IAAI;AAAA,EACpE;AACF;;;ADoCA,IAAMC,WAAU,cAAc,YAAY,GAAG;AAKtC,IAAM,2BAA8C;AAAA,EACzD,eAAe,CAAC,eAAsC;AACpD,QAAI;AACF,aAAOA,SAAQ,QAAQ,UAAU;AAAA,IACnC,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,YAAYC,IAAG;AAAA,EAEf,WAAW,CAAC,SAAgC;AAC1C,QAAI;AACF,YAAM,SAASC,UAAS,SAAS,IAAI,IAAI;AAAA,QACvC,UAAU;AAAA,QACV,OAAO,CAAC,QAAQ,QAAQ,MAAM;AAAA,MAChC,CAAC;AACD,aAAO,OAAO,KAAK,KAAK;AAAA,IAC1B,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACF;AA0CA,eAAsB,aACpB,MACA,UAA+B,CAAC,GACF;AAC9B,QAAM,EAAE,cAAc,QAAQ,IAAI,GAAG,OAAO,yBAAyB,IAAI;AAGzE,QAAM,cAAc,KAAK,cAAc,GAAG,IAAI,eAAe;AAC7D,MAAI,aAAa;AACf,WAAO;AAAA,MACL,OAAO;AAAA,MACP,UAAU;AAAA,QACR;AAAA,QACA,MAAMC,MAAK,QAAQ,WAAW;AAAA,QAC9B,QAAQ,eAAe,QAAQ;AAAA,MACjC;AAAA,IACF;AAAA,EACF;AAGA,QAAM,iBAAiBA,MAAK,KAAK,aAAa,gBAAgB,QAAQ,IAAI;AAC1E,MAAI,KAAK,WAAW,cAAc,GAAG;AACnC,WAAO;AAAA,MACL,OAAO;AAAA,MACP,UAAU;AAAA,QACR;AAAA,QACA,MAAM;AAAA,QACN,QAAQ,eAAe,QAAQ;AAAA,MACjC;AAAA,IACF;AAAA,EACF;AAGA,QAAM,aAAa,KAAK,UAAU,IAAI;AACtC,MAAI,YAAY;AACd,WAAO;AAAA,MACL,OAAO;AAAA,MACP,UAAU;AAAA,QACR;AAAA,QACA,MAAM;AAAA,QACN,QAAQ,eAAe,QAAQ;AAAA,MACjC;AAAA,IACF;AAAA,EACF;AAGA,SAAO;AAAA,IACL,OAAO;AAAA,IACP,UAAU;AAAA,MACR;AAAA,MACA,QAAQ,eAAe,SAAS,iBAAiB,IAAI;AAAA,IACvD;AAAA,EACF;AACF;AAgBO,SAAS,kBACd,UACA,QACQ;AACR,MAAI,OAAO,OAAO;AAChB,WAAO;AAAA,EACT;AACA,SAAO,eAAe,SAAS,YAAY,UAAU,OAAO,SAAS,IAAI;AAC3E;;;AEpNA,OAAO,WAAW;AAClB,SAAS,QAAAC,cAAY;AAkBd,IAAM,qBAAqB;AAAA,EAChC,OAAO;AACT;AAOO,IAAM,sBAAoC;AAAA,EAC/C,CAAC,mBAAmB,KAAK,GAAG;AAC9B;AAuBA,eAAsB,6BACpB,OACA,iBACA,aACA,OAAqB,qBACc;AACnC,MAAI;AAEF,UAAM,qBAAqB,gBAAgB,YAAY,IAAI,CAAC,cAAcC,OAAK,aAAa,SAAS,CAAC;AAEtG,QAAI,mBAAmB,WAAW,GAAG;AACnC,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AAGA,UAAM,eAAeA,OAAK,aAAa,eAAe,KAAK,CAAC;AAG5D,UAAM,iBAAiB,gBAAgB,gBAAgB,IAAI,CAAC,YAAY;AAEtE,YAAM,eAAe,QAAQ,QAAQ,gBAAgB,EAAE;AAEvD,YAAM,UAAU,aAAa,QAAQ,uBAAuB,MAAM;AAClE,aAAO,IAAI,OAAO,OAAO;AAAA,IAC3B,CAAC;AAED,UAAM,SAAS,MAAM,KAAK,MAAM,oBAAoB;AAAA,MAClD,SAAS;AAAA,MACT,gBAAgB,CAAC,MAAM,KAAK;AAAA,MAC5B,UAAU;AAAA,MACV,eAAe;AAAA,IACjB,CAAC;AAED,UAAM,WAAW,OAAO,SAAS;AAEjC,QAAI,SAAS,WAAW,GAAG;AACzB,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB,OAAO;AACL,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,SAAS,SAAS,MAAM;AAAA,QAC/B,sBAAsB;AAAA,MACxB;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AACd,UAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC1E,WAAO,EAAE,SAAS,OAAO,OAAO,aAAa;AAAA,EAC/C;AACF;;;ACvFA,IAAM,4BAA4B,kCAAkC,+BAA+B,QAAQ;AAC3G,IAAM,gCAAgC,GAAG,+BAA+B,QAAQ;AACzE,IAAM,6BAA6B;AAAA,EACxC,OAAO,0BAA0B;AACnC;AAYA,eAAsB,gBAAgB,SAAmE;AACvG,QAAM,EAAE,KAAK,MAAM,IAAI;AACvB,QAAM,YAAY,KAAK,IAAI;AAG3B,QAAM,cAAc,iBAAiB,GAAG;AACxC,MAAI,CAAC,YAAY,SAAS;AACxB,WAAO;AAAA,MACL,UAAU;AAAA,MACV,QAAQ,QAAQ,KAAK;AAAA,MACrB,YAAY,KAAK,IAAI,IAAI;AAAA,IAC3B;AAAA,EACF;AAGA,QAAM,aAAa,MAAM,aAAa,SAAS,EAAE,aAAa,IAAI,CAAC;AACnE,MAAI,CAAC,WAAW,OAAO;AACrB,UAAM,cAAc,kBAAkB,6BAA6B,UAAU;AAC7E,WAAO,EAAE,UAAU,GAAG,QAAQ,aAAa,YAAY,KAAK,IAAI,IAAI,UAAU;AAAA,EAChF;AAEA,QAAM,SAAS,MAAM,cAAc,KAAK,CAAC,0BAA0B,CAAC;AACpE,MAAI,CAAC,OAAO,IAAI;AACd,WAAO;AAAA,MACL,UAAU;AAAA,MACV,QAAQ,GAAG,6BAA6B,WAAM,OAAO,KAAK;AAAA,MAC1D,YAAY,KAAK,IAAI,IAAI;AAAA,IAC3B;AAAA,EACF;AACA,QAAM,mBAAmB,OAAO,MAAM,2BAA2B,OAAO;AACxE,QAAM,cAAc;AAAA,IAClB,mBAAmB,QAAQ,GAAG;AAAA,IAC9B,4BAA4B,iBAAiB,OAAO,iCAAiC,QAAQ;AAAA,EAC/F;AAGA,QAAM,SAAS,MAAM,6BAA6B,QAAQ,aAAa,GAAG;AAC1E,QAAM,aAAa,KAAK,IAAI,IAAI;AAGhC,MAAI,OAAO,SAAS;AAClB,UAAM,SAAS,QAAQ,KAAK,0BAA0B;AACtD,WAAO,EAAE,UAAU,GAAG,QAAQ,WAAW;AAAA,EAC3C,OAAO;AAEL,QAAI,SAAS,OAAO,SAAS,2BAA2B;AACxD,QAAI,OAAO,wBAAwB,OAAO,qBAAqB,SAAS,GAAG;AACzE,YAAM,SAAS,OAAO,qBACnB,IAAI,CAAC,UAAU,KAAK,MAAM,KAAK,UAAK,CAAC,EAAE,EACvC,KAAK,IAAI;AACZ,eAAS,GAAG,2BAA2B,KAAK;AAAA,EAAM,MAAM;AAAA,IAC1D;AACA,WAAO,EAAE,UAAU,GAAG,QAAQ,WAAW;AAAA,EAC3C;AACF;;;ACpFA,SAAS,cAAAC,mBAAkB;AAC3B,SAAS,SAAS,IAAI,aAAAC,kBAAiB;AACvC,SAAS,cAAc;AACvB,SAAS,cAAAC,aAAY,QAAAC,cAAY;AAa1B,IAAM,2BAA0C;AAChD,IAAM,sBAAsB;AAAA,EACjC,SAAS;AAAA,EACT,eAAe;AAAA,EACf,yBAAyB;AAC3B;AASA,IAAM,kBAA4B;AAAA,EAChC,YAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAAC;AACF;AA0BA,eAAsBC,cACpB,SACA,SAAwB,0BACxB,OAAiB,iBAIhB;AACD,MAAI;AACF,UAAM,EAAE,aAAa,gBAAgB,IAAI;AAEzC,UAAM,qBAAqB,gBAAgB;AAE3C,QAAI,mBAAmB,WAAW,GAAG;AACnC,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB;AAEA,WAAO,MAAM,kBAAkB,aAAa,iBAAiB,QAAQ,IAAI;AAAA,EAC3E,SAAS,OAAO;AACd,UAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC1E,WAAO,EAAE,SAAS,OAAO,OAAO,aAAa;AAAA,EAC/C;AACF;AAEA,eAAe,kBACb,aACA,iBACA,QACA,MAC+C;AAC/C,QAAM,iBAAiB,gBAAgB,4BACnC,MAAM,yBAAyB,aAAa,iBAAiB,IAAI,IACjE;AACJ,QAAM,WAAWC,OAAK,aAAa,gBAAgB,QAAQ,MAAM;AACjE,QAAM,SAAS,KAAK,WAAW,QAAQ,IAAI,WAAW;AACtD,QAAM,WAAW,mBAAmB,SAChC,CAAC,IACD;AAAA,IACA,oBAAoB;AAAA,IACpB,oBAAoB;AAAA,IACpB,eAAe;AAAA,EACjB;AACF,QAAM,OAAO,WAAW,QAAQ,CAAC,oBAAoB,SAAS,GAAG,QAAQ,IAAI;AAC7E,QAAM,cAAc,uBAAuB,QAAQ,QAAQ,MAAM;AAAA,IAC/D,KAAK;AAAA,EACP,CAAC;AACD,QAAM,UAAU,gBAAgB,YAAY,YAAY;AAAA,EAAC;AACzD,MAAI,iBAAiB;AACrB,MAAI,iBAAiB;AAErB,QAAM,cAAc,YAAY;AAC9B,QAAI,gBAAgB;AAClB;AAAA,IACF;AACA,qBAAiB;AACjB,UAAM,QAAQ;AAAA,EAChB;AAEA,MAAI,aAAa;AACjB,MAAI,YAAY;AAEhB,cAAY,QAAQ,GAAG,QAAQ,CAAC,SAAiB;AAC/C,kBAAc,KAAK,SAAS;AAAA,EAC9B,CAAC;AAED,cAAY,QAAQ,GAAG,QAAQ,CAAC,SAAiB;AAC/C,iBAAa,KAAK,SAAS;AAAA,EAC7B,CAAC;AAED,SAAO,IAAI,QAAQ,CAACC,aAAY;AAC9B,UAAM,sBAAsB,CAAC,WAAiD;AAC5E,UAAI,gBAAgB;AAClB;AAAA,MACF;AACA,uBAAiB;AACjB,WAAK,YAAY,EAAE,QAAQ,MAAMA,SAAQ,MAAM,CAAC;AAAA,IAClD;AAEA,gBAAY,GAAG,SAAS,CAAC,SAAS;AAChC,UAAI,SAAS,GAAG;AACd,4BAAoB,EAAE,SAAS,KAAK,CAAC;AAAA,MACvC,OAAO;AACL,cAAM,cAAc,cAAc,aAAa;AAC/C,4BAAoB;AAAA,UAClB,SAAS;AAAA,UACT,OAAO;AAAA,QACT,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAED,gBAAY,GAAG,SAAS,CAAC,UAAU;AACjC,0BAAoB,EAAE,SAAS,OAAO,OAAO,MAAM,QAAQ,CAAC;AAAA,IAC9D,CAAC;AAAA,EACH,CAAC;AACH;AAEA,eAAe,yBACb,aACA,iBACA,MAC+D;AAC/D,QAAM,UAAU,MAAM,KAAK,QAAQD,OAAK,OAAO,GAAG,gBAAgB,CAAC;AACnE,QAAM,aAAaA,OAAK,SAAS,eAAe,IAAI;AACpD,QAAM,uBAAuB,CAAC,YAAoBE,YAAW,OAAO,IAAI,UAAUF,OAAK,aAAa,OAAO;AAC3G,QAAM,UAAU,gBAAgB,aAAa,SAAS,IAClD,gBAAgB,eAChB,gBAAgB,YAAY,IAAI,CAAC,cAAc,GAAG,SAAS,mBAAmB;AAClF,QAAM,SAAS;AAAA,IACb,SAASA,OAAK,aAAa,eAAe,IAAI;AAAA,IAC9C,SAAS,QAAQ,IAAI,oBAAoB;AAAA,IACzC,SAAS,gBAAgB,gBAAgB,IAAI,oBAAoB;AAAA,EACnE;AACA,QAAM,KAAK,UAAU,YAAY,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAChE,SAAO;AAAA,IACL;AAAA,IACA,SAAS,MAAM,KAAK,GAAG,SAAS,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,EAClE;AACF;;;AClKA,eAAsB,YAAY,SAA+D;AAC/F,QAAM,EAAE,KAAK,MAAM,IAAI;AACvB,QAAM,YAAY,KAAK,IAAI;AAE3B,QAAM,SAAS,MAAM,cAAc,KAAK,CAAC,0BAA0B,CAAC;AACpE,MAAI,CAAC,OAAO,IAAI;AACd,WAAO;AAAA,MACL,UAAU;AAAA,MACV,QAAQ,GAAG,0BAA0B,iBAAiB,WAAM,OAAO,KAAK;AAAA,MACxE,YAAY,KAAK,IAAI,IAAI;AAAA,IAC3B;AAAA,EACF;AACA,QAAM,mBAAmB,OAAO,MAAM,2BAA2B,OAAO;AAExE,MAAI,CAAC,iBAAiB,KAAK,SAAS;AAClC,UAAM,SAAS,QAAQ,KAAK,0BAA0B;AACtD,WAAO,EAAE,UAAU,GAAG,QAAQ,YAAY,KAAK,IAAI,IAAI,UAAU;AAAA,EACnE;AAGA,QAAM,aAAa,MAAM,aAAa,QAAQ,EAAE,aAAa,IAAI,CAAC;AAClE,MAAI,CAAC,WAAW,OAAO;AACrB,UAAM,cAAc,kBAAkB,yBAAyB,UAAU;AACzE,WAAO,EAAE,UAAU,GAAG,QAAQ,aAAa,YAAY,KAAK,IAAI,IAAI,UAAU;AAAA,EAChF;AAEA,QAAM,cAAc;AAAA,IAClB,mBAAmB,QAAQ,GAAG;AAAA,IAC9B,4BAA4B,iBAAiB,OAAO,iCAAiC,IAAI;AAAA,EAC3F;AAGA,QAAM,SAAS,MAAMG,cAAa,EAAE,aAAa,KAAK,iBAAiB,YAAY,CAAC;AACpF,QAAM,aAAa,KAAK,IAAI,IAAI;AAGhC,MAAI,OAAO,SAAS;AAClB,UAAM,SAAS,QAAQ,KAAK,0BAA0B;AACtD,WAAO,EAAE,UAAU,GAAG,QAAQ,WAAW;AAAA,EAC3C,OAAO;AACL,UAAM,SAAS,OAAO,SAAS,0BAA0B;AACzD,WAAO,EAAE,UAAU,GAAG,QAAQ,WAAW;AAAA,EAC3C;AACF;;;AC3DA,SAAS,cAAAC,mBAAkB;AAC3B,SAAS,QAAAC,cAAY;;;ACTrB,SAAS,oBAAoB;AAC7B,SAAS,cAAAC,aAAY,eAAAC,cAAa,gBAAAC,eAAc,YAAAC,iBAAgB;AAChE,SAAS,QAAAC,cAAY;;;ACAd,IAAM,wBAAwB;AAAA,EACnC,sBAAsB;AAAA,IACpB,MAAM;AAAA,IACN,KAAK;AAAA,EACP;AAAA,EACA,gCAAgC;AAAA,IAC9B,MAAM;AAAA,IACN,KAAK;AAAA,EACP;AACF;AAEO,IAAM,wBAAwB;AAAA,EACnC,aAAa;AAAA,EACb,YAAY;AACd;AAIA,SAAS,aAAa,OAAqC;AACzD,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAEO,SAAS,wBAAwB,SAAiB,QAAgB,KAAuB;AAC9F,QAAM,SAAeC,OAAM,OAAO;AAElC,MAAI,CAAC,aAAa,MAAM,GAAG;AACzB,UAAM,IAAI,MAAM,GAAG,MAAM,6BAA6B;AAAA,EACxD;AAEA,QAAM,UAAU,OAAO,GAAG;AAE1B,MAAI,CAAC,MAAM,QAAQ,OAAO,GAAG;AAC3B,UAAM,IAAI,MAAM,GAAG,MAAM,mBAAmB,GAAG,QAAQ;AAAA,EACzD;AAEA,QAAM,iBAAiB,QAAQ,OAAO,CAAC,UAAU,OAAO,UAAU,QAAQ;AAE1E,MAAI,eAAe,SAAS,GAAG;AAC7B,UAAM,IAAI,MAAM,GAAG,MAAM,IAAI,GAAG,0BAA0B;AAAA,EAC5D;AAEA,SAAO;AACT;;;ADnCA,IAAM,oCAAoC,sBAAsB,qBAAqB;AACrF,IAAM,mCAAmC,sBAAsB,qBAAqB;AACpF,IAAM,8CAA8C,sBAAsB,+BAA+B;AACzG,IAAM,6CAA6C,sBAAsB,+BAA+B;AACxG,IAAM,iBAAiB,iBAAiB;AACxC,IAAM,mBAAmB,CAAC,sBAAsB,aAAa,sBAAsB,UAAU;AAE7F,SAAS,mBAAmB,OAAwB;AAClD,SAAO,cAAc,KAAK,CAAC,WAAW,MAAM,SAAS,MAAM,CAAC;AAC9D;AAMA,SAAS,aAAa,YAAoB,MAAc,KAAuB;AAC7E,SAAO;AAAA,IACLC,cAAaC,OAAK,YAAY,IAAI,GAAG,OAAO;AAAA,IAC5C;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,eAAe,YAAoB,MAAuB;AACjE,SAAOC,YAAWD,OAAK,YAAY,IAAI,CAAC;AAC1C;AAEA,SAAS,2BAA2B,YAAwC;AAC1E,WAASE,OAAM,mBAA+C;AAC5D,UAAM,oBAAoBF,OAAK,YAAY,iBAAiB;AAC5D,eAAW,SAASG,aAAY,mBAAmB,EAAE,eAAe,KAAK,CAAC,GAAG;AAC3E,UAAI,CAAC,MAAM,YAAY,GAAG;AACxB;AAAA,MACF;AAEA,YAAM,YAAY,GAAG,iBAAiB,IAAI,MAAM,IAAI;AAEpD,UAAI,mCAAmC,KAAK,CAAC,WAAW,MAAM,KAAK,SAAS,MAAM,CAAC,GAAG;AACpF,eAAO;AAAA,MACT;AAEA,YAAM,uBAAuBD,OAAM,SAAS;AAC5C,UAAI,yBAAyB,QAAW;AACtC,eAAO;AAAA,MACT;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAEA,QAAM,mBAAmBF,OAAK,YAAY,cAAc;AACxD,MAAI,CAACC,YAAW,gBAAgB,GAAG;AACjC,WAAO;AAAA,EACT;AAEA,SAAOC,OAAM,cAAc;AAC7B;AAEA,SAAS,sBACP,YACA,MACA,SACA,iBACA,mBACM;AACN,QAAM,aAAa,QAAQ,OAAO,CAAC,OAAO,UAAU,QAAQ,QAAQ,KAAK,MAAM,KAAK;AAEpF,MAAI,WAAW,SAAS,GAAG;AACzB,UAAM,IAAI;AAAA,MACR,GAAG,IAAI,gCAAgC,WAAW,KAAK,IAAI,CAAC;AAAA,IAC9D;AAAA,EACF;AAEA,aAAW,SAAS,SAAS;AAC3B,QAAI,UAAU,MAAM,KAAK,GAAG;AAC1B,YAAM,IAAI,MAAM,GAAG,IAAI,sCAAsC,KAAK,EAAE;AAAA,IACtE;AAEA,QAAI,CAAC,MAAM,WAAW,GAAG,cAAc,GAAG,GAAG;AAC3C,YAAM,IAAI,MAAM,GAAG,IAAI,wBAAwB,cAAc,MAAM,KAAK,EAAE;AAAA,IAC5E;AAEA,QAAI,MAAM,SAAS,IAAI,GAAG;AACxB,YAAM,IAAI,MAAM,GAAG,IAAI,iCAAiC,KAAK,EAAE;AAAA,IACjE;AAEA,QAAI,CAAC,gBAAgB,KAAK,GAAG;AAC3B,YAAM,IAAI,MAAM,GAAG,IAAI,eAAe,iBAAiB,KAAK,KAAK,EAAE;AAAA,IACrE;AAEA,UAAM,gBAAgBF,OAAK,YAAY,KAAK;AAC5C,QAAI,CAACC,YAAW,aAAa,KAAK,CAACG,UAAS,aAAa,EAAE,YAAY,GAAG;AACxE,YAAM,IAAI,MAAM,GAAG,IAAI,yCAAyC,KAAK,EAAE;AAAA,IACzE;AAAA,EACF;AACF;AAEA,SAAS,qBAAqB,YAAoB,MAAc,KAAmC;AACjG,QAAM,cAAc,gBAAgB,UAAU;AAC9C,MAAI,gBAAgB,QAAW;AAC7B,WAAO;AAAA,EACT;AAEA,MAAI;AACJ,MAAI;AACF,cAAU,aAAa,OAAO,CAAC,QAAQ,GAAG,WAAW,IAAI,IAAI,EAAE,GAAG;AAAA,MAChE,KAAK;AAAA,MACL,UAAU;AAAA,MACV,KAAK,sBAAsB,QAAQ,GAAG;AAAA,MACtC,OAAO,CAAC,UAAU,QAAQ,QAAQ;AAAA,IACpC,CAAC;AAAA,EACH,QAAQ;AACN,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL;AAAA,IACA,GAAG,WAAW,IAAI,IAAI;AAAA,IACtB;AAAA,EACF;AACF;AAEA,SAAS,gBAAgB,YAAwC;AAC/D,QAAM,yBAAyB,2BAA2B,UAAU;AACpE,MAAI,2BAA2B,QAAW;AACxC,WAAO;AAAA,EACT;AAEA,aAAW,iBAAiB,kBAAkB;AAC5C,UAAM,YAAY,cAAc,YAAY,aAAa;AACzD,QAAI,cAAc,QAAW;AAC3B,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,2BAA2B,YAAwC;AAC1E,QAAM,eAAe,WAAW,YAAY,CAAC,aAAa,YAAY,QAAQ,CAAC;AAC/E,MAAI,iBAAiB,QAAW;AAC9B,WAAO;AAAA,EACT;AACA,SAAO,WAAW,YAAY,CAAC,aAAa,YAAY,QAAQ,CAAC;AACnE;AAEA,SAAS,cAAc,YAAoB,eAA2C;AACpF,SAAO,WAAW,YAAY,CAAC,cAAc,QAAQ,aAAa,CAAC;AACrE;AAEA,SAAS,WAAW,YAAoB,MAA6C;AACnF,MAAI;AACF,UAAM,SAAS,aAAa,OAAO,CAAC,GAAG,IAAI,GAAG;AAAA,MAC5C,KAAK;AAAA,MACL,UAAU;AAAA,MACV,KAAK,sBAAsB,QAAQ,GAAG;AAAA,MACtC,OAAO,CAAC,UAAU,QAAQ,QAAQ;AAAA,IACpC,CAAC;AACD,WAAO,OAAO,KAAK,KAAK;AAAA,EAC1B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,0BACP,YACA,MACA,KACA,SACM;AACN,QAAM,kBAAkB,qBAAqB,YAAY,MAAM,GAAG;AAElE,MAAI,oBAAoB,QAAW;AACjC;AAAA,EACF;AAEA,QAAM,mBAAmB,IAAI,IAAI,eAAe;AAChD,QAAM,YAAY,QAAQ,OAAO,CAAC,UAAU,CAAC,iBAAiB,IAAI,KAAK,CAAC;AAExE,MAAI,UAAU,SAAS,GAAG;AACxB,UAAM,IAAI;AAAA,MACR,GAAG,IAAI,sEAAsE,UAAU,KAAK,IAAI,CAAC;AAAA,IACnG;AAAA,EACF;AACF;AAEA,SAAS,iCAAiC,YAA0B;AAClE,QAAM,yBAAyB,2BAA2B,UAAU;AACpE,MAAI,2BAA2B,QAAW;AACxC,UAAM,IAAI;AAAA,MACR,mDAAmD,sBAAsB;AAAA,IAC3E;AAAA,EACF;AACF;AAEA,SAAS,iCAAiC,YAAoB,SAAyB;AACrF;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,0CAA0C,YAAoB,SAAyB;AAC9F;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,mBAAmB,YAAsC;AACvE,MAAI;AACF,qCAAiC,UAAU;AAE3C,UAAM,oBAAoB;AAAA,MACxB,eAAe,YAAY,iCAAiC;AAAA,MAC5D,eAAe,YAAY,2CAA2C;AAAA,IACxE;AACA,QAAI,kBAAkB,MAAM,CAAC,WAAW,CAAC,MAAM,GAAG;AAChD,aAAO,EAAE,IAAI,KAAK;AAAA,IACpB;AACA,QAAI,CAAC,kBAAkB,MAAM,OAAO,GAAG;AACrC,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,OAAO;AAAA,MACT;AAAA,IACF;AAEA;AAAA,MACE;AAAA,MACA,aAAa,YAAY,mCAAmC,gCAAgC;AAAA,IAC9F;AACA;AAAA,MACE;AAAA,MACA;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,WAAO,EAAE,IAAI,KAAK;AAAA,EACpB,SAAS,OAAO;AACd,WAAO,EAAE,IAAI,OAAO,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE;AAAA,EACpF;AACF;;;AExPO,IAAM,oBAAoB;AAAA;AAAA,EAE/B,MAAM;AAAA;AAAA,EAEN,YAAY;AACd;AAiCO,IAAM,kBAAkB;AAAA;AAAA,EAE7B,MAAM;AAAA;AAAA,EAEN,OAAO;AACT;;;ACtDO,IAAM,+BAA+B;AAAA,EAC1C,OAAO;AAAA,EACP,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AACT;AAiBO,IAAM,2CAA8E;AAAA,EACzF,QAAQ,QAAQ;AAAA,EAChB,QAAQ,QAAQ;AAClB;AAEO,SAAS,kCACd,OACA,UAA6C,0CACvC;AACN,QAAM,QAAQ,GAAG,6BAA6B,MAAM,CAAC,UAA+B;AAClF,iCAA6B,MAAM,QAAQ,QAAQ,QAAQ,KAAK;AAAA,EAClE,CAAC;AAED,QAAM,QAAQ,GAAG,6BAA6B,MAAM,CAAC,UAA+B;AAClF,iCAA6B,MAAM,QAAQ,QAAQ,QAAQ,KAAK;AAAA,EAClE,CAAC;AACH;AAEA,SAAS,6BACP,QACA,QACA,OACM;AACN,QAAM,QAAQ,OAAO,MAAM,KAAK;AAChC,MAAI,SAAS,OAAO,SAAS,UAAa,WAAW,QAAQ,WAAW,QAAW;AACjF;AAAA,EACF;AAEA,SAAO,MAAM;AACb,SAAO,KAAK,6BAA6B,OAAO,MAAM;AACpD,WAAO,OAAO;AAAA,EAChB,CAAC;AACH;;;AJpCO,IAAM,6BAA4C;AAWlD,IAAM,6BAA6B;AACnC,IAAM,wBAAwB;AAAA,EACnC,SAAS;AAAA,EACT,aAAa;AAAA,EACb,mBAAmB;AAAA,EACnB,gBAAgB;AAAA,EAChB,UAAU;AAAA,EACV,qBAAqB;AACvB;AACO,IAAM,4BAA4B,CAAC,gBAAgB,QAAQ,sBAAsB,OAAO;AAoBxF,SAAS,gBAAgB,SAMnB;AACX,QAAM,EAAE,gBAAgB,MAAM,aAAa,4BAA4B,OAAO,YAAY,IAAI;AAC9F,QAAM,SAAS,SAAS,gBAAgB,QAAQ,CAAC,sBAAsB,QAAQ,IAAI,CAAC;AAEpF,MAAI,kBAAkB,eAAe,SAAS,GAAG;AAG/C,WAAO;AAAA,MACL,sBAAsB;AAAA,MACtB,sBAAsB;AAAA,MACtB;AAAA,MACA,GAAG;AAAA,MACH,sBAAsB;AAAA,MACtB,GAAG;AAAA,IACL;AAAA,EACF;AACA,QAAM,aAAa,UAAU,kBAAkB,cAAc,aAAa,mCACtE,0BAA0B,WAAW,IACrC,gCAAgC,WAAW;AAC/C,SAAO;AAAA,IACL,sBAAsB;AAAA,IACtB,GAAG;AAAA,IACH,sBAAsB;AAAA,IACtB;AAAA,IACA,GAAG;AAAA,EACL;AACF;AAEA,SAAS,gCAAgC,aAAgD;AACvF,SAAO;AAAA,IACL,sBAAsB;AAAA,IACtB,GAAI,aAAa,4BAA4B,uBAAuB,YAAY,eAAe,IAAI,CAAC;AAAA,EACtG;AACF;AAEA,SAAS,0BAA0B,aAAgD;AACjF,QAAM,iBAAiB,aAAa,aAAa,SAC7C,YAAY,eACZ,CAAC,sBAAsB,iBAAiB;AAC5C,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAG,uBAAuB,aAAa,mBAAmB,CAAC,CAAC;AAAA,EAC9D;AACF;AAEA,SAAS,uBAAuB,UAAuC;AACrE,SAAO,SAAS,QAAQ,CAAC,YAAY,CAAC,sBAAsB,qBAAqB,OAAO,CAAC;AAC3F;AAqBA,eAAsB,eACpB,SACA,SAAwB,4BACxB,gBAAmD,0CAKlD;AACD,QAAM,EAAE,aAAa,OAAO,gBAAgB,MAAM,iBAAiB,IAAI;AACvE,QAAM,aAAa,mBAAmB,WAAW;AAEjD,MAAI,CAAC,WAAW,IAAI;AAClB,WAAO,EAAE,SAAS,OAAO,OAAO,WAAW,MAAM;AAAA,EACnD;AAEA,MAAI,QAAQ,YAAY,mCAAmC;AACzD,WAAO,EAAE,SAAS,MAAM,SAAS,KAAK;AAAA,EACxC;AAEA,QAAM,aAAa,gBAAgB;AAAA,IACjC;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ;AAAA,IACA,aAAa,QAAQ;AAAA,EACvB,CAAC;AAED,SAAO,IAAI,QAAQ,CAACC,aAAY;AAC9B,UAAM,WAAWC,OAAK,aAAa,GAAG,yBAAyB;AAC/D,UAAM,SAASC,YAAW,QAAQ,IAAI,WAAW;AACjD,UAAM,YAAY,WAAW,QAAQ,aAAa,WAAW,MAAM,CAAC;AACpE,UAAM,gBAAgB,uBAAuB,QAAQ,QAAQ,WAAW;AAAA,MACtE,KAAK;AAAA,IACP,CAAC;AACD,sCAAkC,eAAe,aAAa;AAE9D,kBAAc,GAAG,6BAA6B,OAAO,CAAC,SAAS;AAC7D,UAAI,SAAS,GAAG;AACd,QAAAF,SAAQ,EAAE,SAAS,KAAK,CAAC;AAAA,MAC3B,OAAO;AACL,QAAAA,SAAQ,EAAE,SAAS,OAAO,OAAO,2BAA2B,IAAI,GAAG,CAAC;AAAA,MACtE;AAAA,IACF,CAAC;AAED,kBAAc,GAAG,6BAA6B,OAAO,CAAC,UAAU;AAC9D,MAAAA,SAAQ,EAAE,SAAS,OAAO,OAAO,MAAM,QAAQ,CAAC;AAAA,IAClD,CAAC;AAAA,EACH,CAAC;AACH;;;AKnKA,IAAMG,6BAA4B,kCAAkC,+BAA+B,MAAM;AACzG,IAAM,yBAAyB,0BAA0B;AACzD,IAAM,8BAA8B,GAAG,+BAA+B,MAAM;AAC5E,IAAM,sCAAsC;AAAA,EAC1C,+BAA+B;AACjC;AAaA,eAAsB,YAAY,SAA+D;AAC/F,QAAM,EAAE,KAAK,QAAQ,QAAQ,OAAO,KAAK,eAAe,MAAM,IAAI;AAClE,QAAM,YAAY,KAAK,IAAI;AAG3B,QAAM,cAAc,iBAAiB,GAAG;AACxC,MAAI,CAAC,YAAY,SAAS;AACxB,WAAO;AAAA,MACL,UAAU;AAAA,MACV,QAAQ,QAAQ,KAAKA;AAAA,MACrB,YAAY,KAAK,IAAI,IAAI;AAAA,IAC3B;AAAA,EACF;AAEA,QAAM,mBAAmB,UAAU,kBAAkB,aACjD,YAAY,8BAA8B,YAAY,mBACtD,YAAY;AAGhB,MAAI,qBAAqB,QAAW;AAClC,WAAO;AAAA,MACL,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,YAAY,KAAK,IAAI,IAAI;AAAA,IAC3B;AAAA,EACF;AAEA,QAAM,SAAS,MAAM,cAAc,KAAK,CAAC,0BAA0B,CAAC;AACpE,MAAI,CAAC,OAAO,IAAI;AACd,WAAO;AAAA,MACL,UAAU;AAAA,MACV,QAAQ,GAAG,2BAA2B,WAAM,OAAO,KAAK;AAAA,MACxD,YAAY,KAAK,IAAI,IAAI;AAAA,IAC3B;AAAA,EACF;AACA,QAAM,mBAAmB,OAAO,MAAM,2BAA2B,OAAO;AACxE,QAAM,uBAAuB;AAAA,IAC3B,iBAAiB;AAAA,IACjB,iCAAiC;AAAA,EACnC;AACA,QAAM,cAAc;AAAA,IAClB,mBAAmB,OAAO,GAAG;AAAA,IAC7B;AAAA,EACF;AACA,QAAM,iBAAiB,OACnB,IAAI,CAAC,SAAS,gCAAgC,KAAK,IAAI,CAAC,EACzD,OAAO,CAAC,SAAS,2BAA2B,MAAM,oBAAoB,CAAC;AAE1E,MACE,YAAY,qCACR,UAAU,UAAa,MAAM,SAAS,KAAK,gBAAgB,WAAW,GAC1E;AACA,WAAO;AAAA,MACL,UAAU;AAAA,MACV,QAAQ,QAAQ,KAAK;AAAA,MACrB,YAAY,KAAK,IAAI,IAAI;AAAA,IAC3B;AAAA,EACF;AAGA,QAAM,aAAa,MAAM,aAAa,UAAU,EAAE,aAAa,IAAI,CAAC;AACpE,MAAI,CAAC,WAAW,OAAO;AACrB,UAAM,cAAc,kBAAkB,+BAA+B,QAAQ,UAAU;AACvF,WAAO,EAAE,UAAU,GAAG,QAAQ,aAAa,YAAY,KAAK,IAAI,IAAI,UAAU;AAAA,EAChF;AAGA,QAAM,UAA6B;AAAA,IACjC,aAAa;AAAA,IACb;AAAA,IACA;AAAA,IACA,MAAM,MAAM,UAAU;AAAA,IACtB,oBAAoB,EAAE,QAAQ,KAAK;AAAA,IACnC;AAAA,IACA,oBAAoB,QAAQ,kBAAkB,eAAe,SAAS,CAAC;AAAA,IACvE;AAAA,EACF;AAGA,QAAM,SAAS,MAAM,eAAe,SAAS,QAAW,aAAa;AACrE,QAAM,aAAa,KAAK,IAAI,IAAI;AAGhC,MAAI,OAAO,SAAS;AAClB,UAAM,SAAS,QAAQ,KAAK;AAC5B,WAAO,EAAE,UAAU,GAAG,QAAQ,WAAW;AAAA,EAC3C,WAAW,OAAO,SAAS;AACzB,UAAM,SAAS,QAAQ,KAAK,0BAA0B;AACtD,WAAO,EAAE,UAAU,GAAG,QAAQ,WAAW;AAAA,EAC3C,OAAO;AACL,UAAM,SAAS,OAAO,SAAS,0BAA0B;AACzD,WAAO,EAAE,UAAU,GAAG,QAAQ,WAAW;AAAA,EAC3C;AACF;;;AC5IA,SAAS,YAAAC,iBAAgB;AACzB,SAAS,cAAAC,aAAY,YAAAC,WAAU,WAAAC,gBAAe;;;ACCvC,IAAM,sBAAsB;AACnC,IAAMC,SAAQ;AAEP,SAAS,sBACdC,OACA,QACe;AACf,QAAM,QAAQ,OAAO,OAAO,aAAaA,KAAI;AAC7C,MAAI,UAAU,QAAW;AACvB,WAAO,EAAE,SAAS,OAAO,OAAOD,OAAM;AAAA,EACxC;AACA,SAAO,EAAE,SAAS,MAAM,OAAOA,QAAO,QAAQ,MAAM,QAAQ;AAC9D;;;ACRA,SAAS,UACP,eACA,WACY;AACZ,SAAO;AAAA,IACL;AAAA,IACA,WAAW,CAACE,OAAM,WAAW,UAAUA,OAAM,MAAW;AAAA,EAC1D;AACF;AAEO,IAAM,yBAAqC;AAAA,EAChD,CAAC,SAAkC,EAAE,qBAAqB,IAAI,OAAO,oBAAoB;AAAA,EACzF;AACF;AAEO,IAAM,oBAAgC;AAAA,EAC3C,CAAC,SAA6B,EAAE,cAAc,IAAI,OAAO,aAAa;AAAA,EACtE;AACF;AAEO,IAAM,oBAAgC;AAAA,EAC3C,CAAC,SAAsC,EAAE,QAAQ,IAAI,aAAa;AAAA,EAClE;AACF;;;AC5BA,SAAS,WAAAC,gBAAe;AACxB,SAAS,QAAAC,QAAM,YAAAC,WAAU,OAAAC,YAAW;AAkB7B,IAAM,0BAA0B;AAEvC,SAASC,aAAY,KAA4C;AAC/D,SAAO,eAAe,SAAS,UAAU;AAC3C;AAEA,eAAe,aACb,aACA,aACA,QACA,cACe;AACf,MAAI;AACJ,MAAI;AACF,iBAAa,MAAMC,SAAQ,aAAa,EAAE,eAAe,KAAK,CAAC;AAAA,EACjE,SAAS,KAAK;AACZ,QAAID,aAAY,GAAG,MAAM,IAAI,SAAS,YAAY,IAAI,SAAS,YAAY;AACzE;AAAA,IACF;AACA,UAAM;AAAA,EACR;AACA,aAAW,SAAS,YAAY;AAC9B,QAAI,MAAM,YAAY,GAAG;AACvB,UAAI,aAAa,IAAI,MAAM,IAAI,EAAG;AAClC,YAAM,eAAeE,OAAK,aAAa,MAAM,IAAI;AACjD,YAAM,aAAa,cAAc,aAAa,QAAQ,YAAY;AAAA,IACpE,WAAW,MAAM,OAAO,GAAG;AACzB,YAAM,eAAeA,OAAK,aAAa,MAAM,IAAI;AACjD,YAAM,MAAMC,UAAS,aAAa,YAAY;AAC9C,aAAO,KAAKC,SAAQ,MAAM,MAAM,IAAI,MAAMA,IAAG,EAAE,KAAK,GAAG,CAAC;AAAA,IAC1D;AAAA,EACF;AACF;AAcA,eAAsB,YACpB,UACA,aACA,SACA,QACA,cACsB;AACtB,QAAM,WAAyB,EAAE,QAAQ,aAAa;AACtD,QAAM,aAAa,SAAS,IAAI,CAAC,WAAW;AAAA,IAC1C;AAAA,IACA,aAAa,MAAM,cAAc,QAAQ;AAAA,EAC3C,EAAE;AAEF,QAAM,WAAyB,CAAC;AAChC,QAAM,WAAyB,CAAC;AAEhC,QAAM,gBAAgB,QAAQ,YAAY,CAAC;AAC3C,QAAM,kBAAkB,IAAI,IAAY,aAAa;AAErD,aAAWC,SAAQ,eAAe;AAChC,aAAS,KAAK;AAAA,MACZ,MAAAA;AAAA,MACA,eAAe,CAAC,EAAE,SAAS,MAAM,OAAO,wBAAwB,CAAC;AAAA,IACnE,CAAC;AAAA,EACH;AAEA,MAAI,QAAQ,aAAa,QAAW;AAClC,UAAM,eAAe,IAAI,IAAI,OAAO,mBAAmB;AACvD,UAAM,WAAqB,CAAC;AAC5B,UAAM,aAAa,QAAQ,UAAU,aAAa,UAAU,YAAY;AAExE,eAAWA,SAAQ,UAAU;AAC3B,UAAI,gBAAgB,IAAIA,KAAI,EAAG;AAE/B,YAAM,QAAyB,CAAC;AAChC,iBAAW,EAAE,OAAO,YAAY,KAAK,YAAY;AAC/C,cAAM,WAAW,MAAM,UAAUA,OAAM,WAAW;AAClD,YAAI,SAAS,SAAS;AACpB,gBAAM,KAAK,QAAQ;AAAA,QACrB;AAAA,MACF;AAEA,UAAI,MAAM,SAAS,GAAG;AACpB,iBAAS,KAAK,EAAE,MAAAA,OAAM,eAAe,MAAM,CAAC;AAAA,MAC9C,OAAO;AACL,iBAAS,KAAK,EAAE,MAAAA,OAAM,eAAe,CAAC,EAAE,CAAC;AAAA,MAC3C;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,UAAU,SAAS;AAC9B;;;ACrHA,SAAS,SAAS,uBAAuB;AACzC,SAAS,eAAe,6BAA6B;;;ACC9C,IAAM,sCAAsC;AAAA,EACjD,UAAU;AAAA,EACV,MAAM;AAAA,EACN,KAAK;AACP;AAKO,IAAM,uCAAuC;AAAA,EAClD,oCAAoC;AAAA,EACpC,oCAAoC;AAAA,EACpC,oCAAoC;AACtC;;;ADYO,IAAM,cAAc;AAAA,EACzB,oBAAoB;AAAA,EACpB,iCAAiC;AACnC;AAqCO,IAAM,qBAAqC;AAE3C,IAAM,qBAA0D;AAAA,EACrE,mBAAmB,oBAAI,IAAI,CAAC,QAAQ,CAAC;AAAA,EACrC,wBAAwB,oBAAI,IAAI,CAAC,QAAQ,CAAC;AAAA,EAC1C,sBAAsB,oBAAI,IAAI,CAAC,QAAQ,CAAC;AAAA,EACxC,kBAAkB,oBAAI,IAAI,CAAC,QAAQ,CAAC;AAAA,EACpC,cAAc,oBAAI,IAAI,CAAC,UAAU,UAAU,CAAC;AAAA,EAC5C,2BAA2B,oBAAI,IAAI,CAAC,YAAY,CAAC;AACnD;AAEA,IAAM,aAAkC,oBAAI,IAAI;AAChD,IAAM,oBAAoB;AAC1B,IAAM,4BAA4B;AAClC,IAAM,mBAAmB;AACzB,IAAM,uBAAuB;AAC7B,IAAM,2BAA2B;AACjC,IAAM,kBAAkB;AACxB,IAAM,eAAe;AACrB,IAAM,yBAAyB;AAC/B,IAAM,wBAAwB;AAC9B,IAAM,sBAA2C,oBAAI,IAAI;AAAA,EACvD;AAAA,EACA;AAAA,EACA;AACF,CAAC;AACM,IAAM,uBAA4C,IAAI;AAAA,EAC3D;AACF;AACA,IAAM,+BAAoD,oBAAI,IAAI,CAAC,WAAW,SAAS,CAAC;AACxF,IAAM,6BAAkD,oBAAI,IAAI;AAAA,EAC9D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AACD,IAAM,gCAAqD,oBAAI,IAAI,CAAC,QAAQ,MAAM,CAAC;AAEnF,IAAM,6BAA6B;AAmB5B,SAAS,gBACd,QACA,UACA,SACqB;AACrB,QAAM,MAAM,gBAAgB,QAAQ;AAAA,IAClC,KAAK;AAAA,IACL,OAAO;AAAA,IACP,SAAS;AAAA,IACT,KAAK;AAAA,IACL,aAAa;AAAA,IACb,YAAY;AAAA,EACd,CAAC;AACD,QAAM,MAA2B,CAAC;AAClC,QAAM,YAA4B,CAAC;AACnC,OAAK,KAAK,EAAE,UAAU,mBAAmB,eAAe,QAAQ,EAAE,GAAG,WAAW,SAAS,GAAG;AAC5F,SAAO;AACT;AAEA,SAAS,KACP,MACA,SACA,WACA,SACA,KACM;AACN,cAAY,MAAM,SAAS,WAAW,SAAS,GAAG;AAElD,QAAM,OAAO,QAAQ,YAAY,KAAK,IAAI;AAC1C,MAAI,CAAC,MAAM;AACT;AAAA,EACF;AACA,QAAM,OAAO,mBAAmB,KAAK,IAAI,KAAK;AAC9C,aAAW,OAAO,MAAM;AACtB,QAAI,KAAK,IAAI,GAAG,EAAG;AACnB,UAAM,QAAQ,KAAK,GAAG;AACtB,QAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,iBAAW,QAAQ,OAAO;AACxB,YAAI,OAAO,IAAI,EAAG,WAAU,MAAM,MAAM,SAAS,WAAW,SAAS,GAAG;AAAA,MAC1E;AAAA,IACF,WAAW,OAAO,KAAK,GAAG;AACxB,gBAAU,OAAO,MAAM,SAAS,WAAW,SAAS,GAAG;AAAA,IACzD;AAAA,EACF;AACF;AAEA,SAAS,UACP,MACA,QACA,SACA,WACA,SACA,KACM;AAEN,YAAU,KAAK,EAAE,MAAM,OAAO,CAAC;AAC/B,MAAI;AACF,SAAK,MAAM,SAAS,WAAW,SAAS,GAAG;AAAA,EAC7C,UAAE;AACA,cAAU,IAAI;AAAA,EAChB;AACF;AAEA,SAAS,OAAO,OAA+B;AAC7C,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,OAAQ,MAAe,SAAS;AACxF;AAEA,SAAS,YACP,MACA,SACA,WACA,SACA,KACM;AACN,MAAI,KAAK,SAAS,gBAAgB,KAAK,SAAS,uBAAuB;AACrE;AAAA,EACF;AACA,MAAI,qBAAqB,SAAS,SAAS,GAAG;AAC5C;AAAA,EACF;AACA,QAAM,OAAO,KAAK,KAAK,OAAO,QAAQ;AAEtC,MAAI,KAAK,SAAS,cAAc;AAC9B,QAAI,OAAO,KAAK,UAAU,UAAU;AAClC,UAAI,KAAK,MAAM,UAAU,QAAQ,iBAAiB;AAChD,YAAI,KAAK,EAAE,MAAM,UAAU,OAAO,KAAK,OAAO,KAAK,EAAE,MAAM,QAAQ,UAAU,KAAK,EAAE,CAAC;AAAA,MACvF;AAAA,IACF,WAAW,OAAO,KAAK,UAAU,UAAU;AACzC,YAAM,MAAM,OAAO,KAAK,QAAQ,WAAW,KAAK,MAAM,OAAO,KAAK,KAAK;AACvE,UAAI,mBAAmB,KAAK,QAAQ,eAAe,GAAG;AACpD,YAAI,KAAK,EAAE,MAAM,UAAU,OAAO,OAAO,KAAK,KAAK,GAAG,KAAK,EAAE,MAAM,QAAQ,UAAU,KAAK,EAAE,CAAC;AAAA,MAC/F;AAAA,IACF;AACA;AAAA,EACF;AAEA,MAAI,KAAK,SAAS,uBAAuB;AACvC,UAAM,QAAQ,KAAK;AACnB,UAAM,SAAS,OAAO,UAAU;AAChC,QAAI,OAAO,UAAU,QAAQ,iBAAiB;AAC5C,UAAI,KAAK,EAAE,MAAM,UAAU,OAAO,QAAQ,KAAK,EAAE,MAAM,QAAQ,UAAU,KAAK,EAAE,CAAC;AAAA,IACnF;AAAA,EACF;AACF;AAEA,SAAS,eAAe,UAA2B;AACjD,SAAO,SAAS,SAAS,iBAAiB,KACrC,SAAS,SAAS,yBAAyB,KAC3C,SAAS,SAAS,gBAAgB;AACzC;AAEA,SAAS,qBACP,SACA,WACS;AACT,MAAI,CAAC,QAAQ,mBAAmB;AAC9B,WAAO;AAAA,EACT;AACA,SAAO,8BAA8B,SAAS,KAAK,4BAA4B,SAAS;AAC1F;AAEA,SAAS,8BAA8B,WAA6C;AAGlF,WAAS,QAAQ,UAAU,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG;AAC7D,UAAM,WAAW,UAAU,KAAK;AAChC,QAAI,SAAS,KAAK,SAAS,sBAAsB;AAC/C;AAAA,IACF;AACA,UAAM,WAAW,YAAY,SAAS,IAAI;AAC1C,QAAI,aAAa,UAAa,CAAC,oBAAoB,QAAQ,GAAG;AAC5D;AAAA,IACF;AACA,QAAI,yBAAyB,WAAW,KAAK,GAAG;AAC9C;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,oBAAoB,UAA2B;AACtD,SAAO,qBAAqB,IAAI,QAAQ;AAC1C;AAEA,SAAS,4BAA4B,WAA6C;AAChF,WAAS,QAAQ,UAAU,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG;AAC7D,UAAM,WAAW,UAAU,KAAK;AAChC,QAAI,SAAS,KAAK,SAAS,0BAA0B;AACnD;AAAA,IACF;AACA,QAAI,yBAAyB,WAAW,KAAK,GAAG;AAC9C;AAAA,IACF;AACA,UAAM,eAAe,6BAA6B,SAAS,IAAI;AAC/D,QAAI,iBAAiB,UAAa,0BAA0B,YAAY,GAAG;AACzE,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,yBACP,WACA,eACS;AAET,WAAS,QAAQ,gBAAgB,GAAG,QAAQ,UAAU,QAAQ,SAAS,GAAG;AACxE,QAAI,oBAAoB,IAAI,UAAU,KAAK,EAAE,KAAK,IAAI,GAAG;AACvD,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,6BAA6B,MAAgC;AACpE,QAAM,cAAc,kBAAkB,KAAK,EAAE;AAC7C,MAAI,gBAAgB,QAAW;AAC7B,WAAO;AAAA,EACT;AAGA,SAAO,kBAAkB,KAAK,IAAI;AACpC;AAEA,SAAS,0BAA0B,cAA+B;AAChE,QAAM,WAAW,oBAAoB,YAAY;AACjD,MAAI,SAAS,WAAW,GAAG;AACzB,WAAO;AAAA,EACT;AAEA,MAAI,SAAS,KAAK,CAAC,YAAY,6BAA6B,IAAI,OAAO,CAAC,GAAG;AACzE,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,SAAS,KAAK,CAAC,YAAY,2BAA2B,IAAI,OAAO,CAAC,GAAG;AACxE,WAAO;AAAA,EACT;AAEA,MAAI,SAAS,MAAM,CAAC,YAAY,2BAA2B,IAAI,OAAO,CAAC,GAAG;AACxE,WAAO;AAAA,EACT;AAEA,QAAM,eAAe,SAAS,SAAS,SAAS,CAAC;AACjD,SAAO,iBAAiB,UAAa,8BAA8B,IAAI,YAAY;AACrF;AAEA,SAAS,oBAAoB,cAAyC;AACpE,SAAO,aACJ,MAAM,GAAG,EACT,QAAQ,CAAC,SAAS,KAAK,MAAM,0BAA0B,KAAK,CAAC,CAAC,EAC9D,IAAI,CAAC,YAAY,QAAQ,YAAY,CAAC;AAC3C;AAEA,SAAS,YAAY,MAAgC;AACnD,QAAM,SAAS,KAAK;AACpB,MAAI,CAAC,OAAO,MAAM,GAAG;AACnB,WAAO;AAAA,EACT;AACA,MAAI,OAAO,SAAS,iBAAiB;AACnC,WAAO,kBAAkB,MAAM;AAAA,EACjC;AACA,MAAI,OAAO,SAAS,wBAAwB;AAC1C,WAAO;AAAA,EACT;AACA,QAAM,WAAW,OAAO;AACxB,MAAI,OAAO,QAAQ,GAAG;AACpB,WAAO,SAAS,SAAS,kBAAkB,kBAAkB,QAAQ,IAAI,iBAAiB,QAAQ;AAAA,EACpG;AACA,SAAO;AACT;AAEA,SAAS,kBAAkB,OAAoC;AAC7D,MAAI,CAAC,OAAO,KAAK,KAAK,MAAM,SAAS,iBAAiB;AACpD,WAAO;AAAA,EACT;AACA,SAAO,OAAO,MAAM,SAAS,WAAW,MAAM,OAAO;AACvD;AAEA,SAAS,iBAAiB,OAAoC;AAC5D,MAAI,CAAC,OAAO,KAAK,KAAK,MAAM,SAAS,cAAc;AACjD,WAAO;AAAA,EACT;AACA,SAAO,OAAO,MAAM,UAAU,WAAW,MAAM,QAAQ;AACzD;AAEA,SAAS,mBAAmB,KAAa,WAA4B;AACnE,QAAM,SAAS,IAAI,QAAQ,WAAW,EAAE;AACxC,SAAO,OAAO,UAAU;AAC1B;AAEO,SAAS,WACd,aACc;AACd,QAAM,MAAM,oBAAI,IAA+B;AAC/C,aAAW,OAAO,aAAa;AAC7B,UAAM,MAAM,QAAQ,IAAI,MAAM,IAAI,KAAK;AACvC,UAAM,WAAW,IAAI,IAAI,GAAG;AAC5B,QAAI,UAAU;AACZ,eAAS,KAAK,IAAI,GAAG;AAAA,IACvB,OAAO;AACL,UAAI,IAAI,KAAK,CAAC,IAAI,GAAG,CAAC;AAAA,IACxB;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,QAAQ,MAAmB,OAAuB;AACzD,SAAO,GAAG,IAAI,KAAK,KAAK;AAC1B;AAEA,SAAS,SAAS,KAAmD;AACnE,QAAM,MAAM,IAAI,QAAQ,IAAI;AAC5B,SAAO,EAAE,MAAM,IAAI,MAAM,GAAG,GAAG,GAAkB,OAAO,IAAI,MAAM,MAAM,CAAC,EAAE;AAC7E;AAEO,SAAS,YAAY,OAA0C;AACpE,QAAM,WAA2B,CAAC;AAClC,QAAM,WAA0B,CAAC;AAEjC,QAAM,YAAY,oBAAI,IAA4C;AAClE,aAAW,CAAC,MAAM,WAAW,KAAK,MAAM,uBAAuB;AAC7D,eAAW,OAAO,aAAa;AAC7B,UAAI,MAAM,UAAU,IAAI,IAAI,KAAK,EAAG;AACpC,YAAM,MAAM,QAAQ,IAAI,MAAM,IAAI,KAAK;AACvC,UAAI,SAAS,UAAU,IAAI,GAAG;AAC9B,UAAI,CAAC,QAAQ;AACX,iBAAS,oBAAI,IAA+B;AAC5C,kBAAU,IAAI,KAAK,MAAM;AAAA,MAC3B;AACA,YAAM,aAAa,OAAO,IAAI,IAAI;AAClC,UAAI,WAAY,YAAW,KAAK,IAAI,GAAG;AAAA,UAClC,QAAO,IAAI,MAAM,CAAC,IAAI,GAAG,CAAC;AAAA,IACjC;AAAA,EACF;AAEA,aAAW,CAAC,KAAK,MAAM,KAAK,WAAW;AACrC,UAAM,EAAE,MAAM,MAAM,IAAI,SAAS,GAAG;AACpC,UAAM,UAAU,MAAM,SAAS,IAAI,GAAG;AACtC,UAAM,cAAiC,CAAC;AACxC,eAAW,QAAQ,OAAO,OAAO,EAAG,aAAY,KAAK,GAAG,IAAI;AAE5D,QAAI,WAAW,QAAQ,SAAS,GAAG;AACjC,iBAAW,WAAW,aAAa;AACjC,iBAAS,KAAK;AAAA,UACZ,MAAM;AAAA,UACN;AAAA,UACA;AAAA,UACA,KAAK;AAAA,UACL,aAAa,YAAY;AAAA,QAC3B,CAAC;AAAA,MACH;AAAA,IACF,WAAW,OAAO,QAAQ,GAAG;AAC3B,eAAS,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK,GAAG;AAC9C,cAAM,aAAa,CAAC,GAAG,YAAY,MAAM,GAAG,CAAC,GAAG,GAAG,YAAY,MAAM,IAAI,CAAC,CAAC;AAC3E,iBAAS,KAAK;AAAA,UACZ,MAAM,YAAY,CAAC;AAAA,UACnB;AAAA,UACA;AAAA,UACA;AAAA,UACA,aAAa,YAAY;AAAA,QAC3B,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,UAAU,SAAS;AAC9B;;;AEtcA,IAAM,wBAA6C,oBAAI,IAAI,CAAC,OAAO,MAAM,CAAC;AAC1E,IAAM,qBAAqB;AAEpB,SAAS,mBAAmBC,OAAuB;AACxD,MAAIA,MAAK,SAAS,kBAAkB,EAAG,QAAO;AAC9C,QAAM,MAAM,YAAYA,KAAI;AAC5B,SAAO,sBAAsB,IAAI,GAAG;AACtC;AAEA,SAAS,YAAY,MAAsB;AACzC,QAAM,MAAM,KAAK,YAAY,GAAG;AAChC,SAAO,QAAQ,KAAK,KAAK,KAAK,MAAM,GAAG;AACzC;AAEO,SAAS,WAAW,SAA0B;AACnD,SAAO,gBAAgB,KAAK,OAAO;AACrC;;;AN0CA,IAAMC,yBAAwB;AAEvB,IAAM,kCAAkC;AAAA,EAC7C,aAAa;AAAA,EACb,iBAAiB,wBAAwB,SAAS;AAAA,EAClD,iBAAiB,wBAAwB,SAAS;AACpD;AAMA,SAASC,qBAAoB,QAAwB;AACnD,QAAM,QAAQ,OAAO,MAAM,QAAQ,EAAE,KAAKC,sBAAqB;AAC/D,SAAO,MAAM,SAASA,sBAAqB,IAAI,QAAQ,GAAG,KAAK,GAAGA,sBAAqB;AACzF;AAEA,SAASC,iBACP,SACA,YACuB;AACvB,MAAI,eAAe,QAAW;AAC5B,WAAO;AAAA,EACT;AACA,QAAM,mBAAmB,WAAW,WAAW,CAAC,GAAG,IAAIF,oBAAmB;AAC1E,QAAM,mBAAmB,WAAW,WAAW,CAAC,GAAG,IAAIA,oBAAmB;AAC1E,SAAO,QAAQ,OAAO,CAAC,UAAU;AAC/B,QACE,gBAAgB,SAAS,KACtB,CAAC,gBAAgB,KAAK,CAAC,MAAM,MAAM,KAAK,WAAW,CAAC,CAAC,GACxD;AACA,aAAO;AAAA,IACT;AACA,QAAI,gBAAgB,KAAK,CAAC,MAAM,MAAM,KAAK,WAAW,CAAC,CAAC,GAAG;AACzD,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT,CAAC;AACH;AAEA,eAAsB,qBACpB,OACqC;AACrC,QAAM,SAAS,MAAM,UAAU,wBAAwB;AAEvD,QAAM,UAAU,MAAM,QAClB;AAAA,IACA,UAAU,MAAM,MAAM,IAAI,CAAC,MAAM;AAC/B,YAAM,MAAMG,YAAW,CAAC,IAAI,IAAIC,SAAQ,MAAM,YAAY,CAAC;AAC3D,aAAOC,UAAS,MAAM,YAAY,GAAG,EAAE,MAAM,QAAQ,EAAE,KAAK,GAAG;AAAA,IACjE,CAAC;AAAA,EACH,IACE,EAAE,UAAU,MAAM,WAAW;AAEjC,QAAM,QAAQ,MAAM;AAAA,IAClB,CAAC,wBAAwB,iBAAiB;AAAA,IAC1C,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,QAAM,WAAWH,iBAAgB,MAAM,UAAU,MAAM,UAAU;AAEjE,QAAM,iBAAiB,SACpB,OAAO,CAAC,UAAU,mBAAmB,MAAM,IAAI,CAAC,EAChD,IAAI,CAAC,UAAUE,SAAQ,MAAM,YAAY,MAAM,IAAI,CAAC;AAEvD,QAAM,iBAAiB;AAAA,IACrB,aAAa;AAAA,IACb,iBAAiB,OAAO;AAAA,IACxB,iBAAiB,OAAO;AAAA,EAC1B;AAEA,QAAM,iBAAsC,CAAC;AAC7C,QAAM,wBAAwB,oBAAI,IAA0C;AAC5E,QAAM,2BAA2B,oBAAI,IAA0C;AAE/E,aAAW,OAAO,gBAAgB;AAChC,UAAM,MAAMC,UAAS,MAAM,YAAY,GAAG,EAAE,MAAM,QAAQ,EAAE,KAAK,GAAG;AAEpE,UAAM,UAAU,MAAM,SAAS,GAAG;AAClC,QAAI,YAAY,KAAM;AAEtB,UAAM,cAAc,gBAAgB,SAAS,KAAK,cAAc;AAChE,6BAAyB,IAAI,KAAK,WAAW;AAC7C,QAAI,WAAW,GAAG,GAAG;AACnB,4BAAsB,IAAI,KAAK,WAAW;AAAA,IAC5C,OAAO;AACL,qBAAe,KAAK,GAAG,WAAW;AAAA,IACpC;AAAA,EACF;AAEA,QAAM,WAAW,WAAW,cAAc;AAC1C,QAAM,WAAW,YAAY;AAAA,IAC3B;AAAA,IACA;AAAA,IACA,WAAW,iBAAiB,MAAM;AAAA,EACpC,CAAC;AAED,SAAO,EAAE,UAAU,yBAAyB;AAC9C;AAEA,eAAe,SAASC,OAAsC;AAC5D,MAAI;AACF,WAAO,MAAMC,UAASD,OAAM,MAAM;AAAA,EACpC,SAAS,KAAc;AACrB,QAAI,OAAO,QAAQ,YAAY,QAAQ,QAAQ,UAAU,KAAK;AAC5D,YAAM,OAAQ,IAA8B;AAC5C,UAAI,SAAS,YAAY,SAAS,SAAU,QAAO;AAAA,IACrD;AACA,UAAM;AAAA,EACR;AACF;;;AOxJO,IAAM,uBAAuB;AAAA,EAClC,OAAO;AAAA,EACP,MAAM;AACR;AAIO,IAAM,mBAAmB;AAAA,EAC9B,MAAM;AAAA,EACN,SAAS;AAAA,EACT,qBAAqB;AAAA,EACrB,UAAU;AAAA,EACV,MAAM;AACR;AAEO,IAAM,oBAAoB,OAAO,OAAO,gBAAgB;AAyBxD,IAAM,qBAAqB;AAAA,EAChC,IAAI;AAAA,EACJ,UAAU;AAAA,EACV,cAAc;AAChB;AACA,IAAME,6BAA4B;AAC3B,IAAM,2BAA2B;AACjC,IAAM,sBAAsB;AAE5B,SAAS,uBAAuB,MAAkC;AACvE,SAAO,gCAAgC,IAAI;AAC7C;AAUA,eAAsB,eACpB,SACkC;AAClC,QAAM,QAAQ,KAAK,IAAI;AAEvB,QAAM,cAAc,iBAAiB,QAAQ,GAAG;AAChD,MAAI,CAAC,YAAY,SAAS;AACxB,WAAO;AAAA,MACL,UAAU,mBAAmB;AAAA,MAC7B,QAAQ,QAAQ,QAAQ,KAAKA;AAAA,MAC7B,YAAY,KAAK,IAAI,IAAI;AAAA,IAC3B;AAAA,EACF;AAEA,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI,QAAQ,WAAW,QAAW;AAChC,sBAAkB,QAAQ,WAAW,2BAA2B,SAAS,QAAQ;AACjF,4BAAwB,QAAQ;AAChC,yBAAqB,QAAQ,cAAc,2BAA2B,SAAS;AAAA,EACjF,OAAO;AACL,UAAM,SAAS,MAAM,cAAc,QAAQ,KAAK,CAAC,0BAA0B,CAAC;AAC5E,QAAI,CAAC,OAAO,IAAI;AACd,aAAO;AAAA,QACL,UAAU,mBAAmB;AAAA,QAC7B,QAAQ,uCAA6B,OAAO,KAAK;AAAA,QACjD,YAAY,KAAK,IAAI,IAAI;AAAA,MAC3B;AAAA,IACF;AACA,UAAM,mBAAmB,OAAO,MAAM,2BAA2B,OAAO;AACxE,sBAAkB,iBAAiB,QAAQ;AAC3C,4BAAwB,iBAAiB,QAAQ;AACjD,yBAAqB;AAAA,MACnB,iBAAiB;AAAA,MACjB,iCAAiC;AAAA,IACnC;AAAA,EACF;AAEA,MAAI,CAAC,iBAAiB;AACpB,WAAO;AAAA,MACL,UAAU,mBAAmB;AAAA,MAC7B,QAAQ,QAAQ,QAAQ,KAAK;AAAA,MAC7B,YAAY,KAAK,IAAI,IAAI;AAAA,IAC3B;AAAA,EACF;AAEA,QAAM,SAAS,MAAM,qBAAqB;AAAA,IACxC,YAAY,QAAQ;AAAA,IACpB,OAAO,QAAQ;AAAA,IACf,QAAQ;AAAA,IACR,YAAY;AAAA,EACd,CAAC;AAED,QAAM,mBAAmB,sBAAsB,OAAO,UAAU,QAAQ,IAAI;AAC5E,QAAM,gBAAgB,qBAAqB,gBAAgB;AAC3D,QAAM,WAAW,kBAAkB,IAAI,mBAAmB,KAAK,mBAAmB;AAElF,QAAM,SAAS,QAAQ,OACnB,KAAK,UAAU,gBAAgB,IAC/B,QAAQ,QACR,KACA,2BAA2B,kBAAkB,OAAO;AAExD,SAAO,EAAE,UAAU,QAAQ,YAAY,KAAK,IAAI,IAAI,MAAM;AAC5D;AAEO,SAAS,sBACd,UACA,MACiB;AACjB,SAAO;AAAA,IACL,UAAU,SAAS,qBAAqB,OAAO,CAAC,IAAI,kBAAkB,SAAS,QAAQ;AAAA,IACvF,UAAU,SAAS,qBAAqB,QAAQ,CAAC,IAAI,iBAAiB,SAAS,QAAQ;AAAA,EACzF;AACF;AAEO,SAAS,qBAAqB,UAAmC;AACtE,SAAO,SAAS,SAAS,SAAS,SAAS,SAAS;AACtD;AAEO,SAAS,6BAA6B,UAAmC;AAC9E,SAAO,kBAAkB,QAAQ,EAC9B;AAAA,IAAI,CAAC,YACJ,IAAI,QAAQ,WAAW,KAAK,mBAAmB,QAAQ,aAAa,QAAQ,KAAK,CAAC,IAAI,UAAU,QAAQ,IAAI,CAAC;AAAA,EAC/G,EACC,KAAK,IAAI;AACd;AAEO,SAAS,6BAA6B,UAAmC;AAC9E,QAAM,QAAQ;AAAA,IACZ,YACE,qBAAqB,QAAQ,CAC/B,qBAAqB,SAAS,SAAS,MAAM,WAAW,SAAS,SAAS,MAAM;AAAA,EAClF;AAEA;AAAA,IACE;AAAA,IACA;AAAA,IACA,SAAS,SAAS,IAAI,CAAC,aAA6B;AAAA,MAClD,aAAa,qBAAqB;AAAA,MAClC,aAAa,QAAQ;AAAA,MACrB,OAAO,QAAQ;AAAA,MACf,MAAM,QAAQ;AAAA,MACd,SAAS,QAAQ;AAAA,IACnB,EAAE;AAAA,EACJ;AACA;AAAA,IACE;AAAA,IACA;AAAA,IACA,SAAS,SAAS,IAAI,CAAC,aAA6B;AAAA,MAClD,aAAa,qBAAqB;AAAA,MAClC,aAAa,QAAQ;AAAA,MACrB,OAAO,QAAQ;AAAA,MACf,MAAM,QAAQ;AAAA,MACd,SAAS,QAAQ;AAAA,IACnB,EAAE;AAAA,EACJ;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAEO,SAAS,wBAAwB,UAAmC;AACzE,SAAO,CAAC,GAAG,IAAI,IAAI,kBAAkB,QAAQ,EAAE,IAAI,CAAC,YAAY,QAAQ,KAAK,IAAI,CAAC,CAAC,EAChF,KAAK,EACL,KAAK,IAAI;AACd;AAEO,SAAS,oBAAoB,UAAmC;AACrE,QAAM,SAAS,oBAAI,IAAoE;AACvF,aAAW,WAAW,kBAAkB,QAAQ,GAAG;AACjD,WAAO,IAAI,GAAG,QAAQ,WAAW,KAAK,QAAQ,KAAK,IAAI;AAAA,MACrD,MAAM,QAAQ;AAAA,MACd,OAAO,QAAQ;AAAA,IACjB,CAAC;AAAA,EACH;AACA,SAAO,CAAC,GAAG,OAAO,OAAO,CAAC,EACvB,KAAK,CAAC,MAAM,UAAU,KAAK,MAAM,cAAc,MAAM,KAAK,KAAK,KAAK,KAAK,cAAc,MAAM,IAAI,CAAC,EAClG,IAAI,CAAC,UAAU,mBAAmB,MAAM,MAAM,MAAM,KAAK,CAAC,EAC1D,KAAK,IAAI;AACd;AAEA,SAAS,2BACP,UACA,SACQ;AACR,QAAM,gBAAgB,qBAAqB,QAAQ;AAEnD,MAAI,kBAAkB,KAAK,QAAQ,SAAS,QAAW;AACrD,WAAO,uBAAuB,QAAQ,IAAI;AAAA,EAC5C;AAEA,MAAI,kBAAkB,GAAG;AACvB,WAAO,QAAQ,qBAAqB,QAAQ,YAAY,QAAQ,UAAU,KAAK;AAAA,EACjF;AAEA,MAAI,QAAQ,kBAAmB,QAAO,wBAAwB,QAAQ;AACtE,MAAI,QAAQ,SAAU,QAAO,oBAAoB,QAAQ;AACzD,MAAI,QAAQ,QAAS,QAAO,6BAA6B,QAAQ;AACjE,SAAO,6BAA6B,QAAQ;AAC9C;AAEA,SAAS,kBAAkB,UAAsD;AAC/E,SAAO;AAAA,IACL,GAAG,kBAAkB,SAAS,QAAQ,EAAE,IAAI,CAAC,aAA6B;AAAA,MACxE,aAAa,qBAAqB;AAAA,MAClC,aAAa,QAAQ;AAAA,MACrB,OAAO,QAAQ;AAAA,MACf,MAAM,QAAQ;AAAA,MACd,SAAS,QAAQ;AAAA,IACnB,EAAE;AAAA,IACF,GAAG,iBAAiB,SAAS,QAAQ,EAAE,IAAI,CAAC,aAA6B;AAAA,MACvE,aAAa,qBAAqB;AAAA,MAClC,aAAa,QAAQ;AAAA,MACrB,OAAO,QAAQ;AAAA,MACf,MAAM,QAAQ;AAAA,MACd,SAAS,QAAQ;AAAA,IACnB,EAAE;AAAA,EACJ;AACF;AAEA,SAAS,qBACP,OACA,SACA,UACM;AACN,QAAM,iBAAiB,CAAC,GAAG,QAAQ,EAAE,KAAK,sBAAsB;AAChE,MAAI,eAAe,WAAW,EAAG;AAEjC,QAAM,KAAK,OAAO;AAClB,MAAI;AACJ,aAAW,WAAW,gBAAgB;AACpC,QAAI,QAAQ,KAAK,SAAS,aAAa;AACrC,YAAM,KAAK,QAAQ,KAAK,IAAI;AAC5B,oBAAc,QAAQ,KAAK;AAAA,IAC7B;AACA,UAAM;AAAA,MACJ,UAAU,QAAQ,KAAK,IAAI,KAAK,mBAAmB,QAAQ,aAAa,QAAQ,KAAK,CAAC,YACpF,QAAQ,QAAQ,IAAI,SAAS,EAAE,KAAK,IAAI,CAC1C;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,kBAAkB,UAA4D;AACrF,SAAO,CAAC,GAAG,QAAQ,EAAE,KAAK,eAAe;AAC3C;AAEA,SAAS,iBAAiB,UAA0D;AAClF,SAAO,CAAC,GAAG,QAAQ,EAAE,KAAK,eAAe;AAC3C;AAEA,SAAS,gBACP,MACA,OACQ;AACR,SACE,KAAK,KAAK,KAAK,cAAc,MAAM,KAAK,IAAI,KACzC,KAAK,KAAK,OAAO,MAAM,KAAK,QAC5B,KAAK,KAAK,cAAc,MAAM,IAAI,KAClC,KAAK,MAAM,cAAc,MAAM,KAAK;AAE3C;AAEA,SAAS,uBAAuB,MAAsB,OAA+B;AACnF,SACE,KAAK,KAAK,KAAK,cAAc,MAAM,KAAK,IAAI,KACzC,KAAK,KAAK,OAAO,MAAM,KAAK,QAC5B,KAAK,YAAY,cAAc,MAAM,WAAW,KAChD,KAAK,MAAM,cAAc,MAAM,KAAK;AAE3C;AAEA,SAAS,mBAAmB,MAAmB,OAAuB;AACpE,SAAO,SAAS,WAAW,IAAI,KAAK,MAAM;AAC5C;AAEA,SAAS,UAAU,KAA8B;AAC/C,SAAO,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI;AAChC;;;ACvTA,SAAS,cAAAC,aAAY,WAAW,QAAQ,qBAAqB;AAC7D,SAAS,WAAAC,gBAAe;AACxB,SAAS,cAAAC,aAAY,QAAAC,cAAY;AAoB1B,IAAM,iCAAgD;AAgBtD,IAAM,wBAAwC;AAAA,EACnD,SAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAAC;AACF;AAkBA,IAAM,sCAAsC,EAAE,QAAQ,KAAK;AAKpD,IAAM,qCAAqC,CAAC,gBAAgB,UAAU,KAAK;AAKlF,IAAM,gCAAgC;AAKtC,eAAe,2BAA2B,aAAqB,MAAuC;AACpG,QAAM,SAASC,OAAK,aAAa,GAAG,kCAAkC;AACtE,OAAK,UAAU,QAAQ,EAAE,WAAW,KAAK,CAAC;AAC1C,SAAO,KAAK,QAAQA,OAAK,QAAQ,6BAA6B,CAAC;AACjE;AAoBO,SAAS,oBAAoB,SAAmE;AACrG,QAAM,EAAE,OAAO,WAAW,IAAI;AAC9B,SAAO,UAAU,kBAAkB,OAAO,CAAC,OAAO,UAAU,IAAI,CAAC,OAAO,aAAa,UAAU;AACjG;AAcA,eAAsB,2BACpB,OACA,OACA,aACA,OAAuB,uBACgD;AAEvE,QAAM,UAAU,MAAM,2BAA2B,aAAa,IAAI;AAClE,QAAM,aAAaA,OAAK,SAAS,eAAe;AAGhD,QAAM,iBAAiB,eAAe,KAAK;AAG3C,QAAM,gBAAgB,MAAM,IAAI,CAAC,SAAUC,YAAW,IAAI,IAAI,OAAOD,OAAK,aAAa,IAAI,CAAE;AAG7F,QAAM,aAAa;AAAA,IACjB,SAASA,OAAK,aAAa,cAAc;AAAA,IACzC,OAAO;AAAA,IACP,SAAS,CAAC;AAAA,IACV,SAAS,CAAC;AAAA,IACV,iBAAiB;AAAA,EACnB;AAGA,OAAK,cAAc,YAAY,KAAK,UAAU,YAAY,MAAM,CAAC,CAAC;AAGlE,QAAM,UAAU,MAAM;AACpB,QAAI;AACF,WAAK,OAAO,SAAS,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,IACvD,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,SAAO,EAAE,YAAY,SAAS,QAAQ;AACxC;AAEA,eAAe,4BACb,OACA,aACA,aACA,OAAuB,uBACgD;AACvE,QAAM,UAAU,MAAM,2BAA2B,aAAa,IAAI;AAClE,QAAM,aAAaA,OAAK,SAAS,eAAe;AAChD,QAAM,iBAAiB,eAAe,KAAK;AAC3C,QAAM,uBAAuB,CAAC,YAAoBC,YAAW,OAAO,IAAI,UAAUD,OAAK,aAAa,OAAO;AAC3G,QAAM,aAAa;AAAA,IACjB,SAASA,OAAK,aAAa,cAAc;AAAA,IACzC,SAAS,YAAY,aAAa,IAAI,oBAAoB;AAAA,IAC1D,SAAS,YAAY,gBAAgB,IAAI,oBAAoB;AAAA,IAC7D,iBAAiB;AAAA,EACnB;AAEA,OAAK,cAAc,YAAY,KAAK,UAAU,YAAY,MAAM,CAAC,CAAC;AAElE,QAAM,UAAU,MAAM;AACpB,QAAI;AACF,WAAK,OAAO,SAAS,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,IACvD,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,SAAO,EAAE,YAAY,SAAS,QAAQ;AACxC;AAqBA,eAAsB,mBACpB,SACA,UAAuC,CAAC,GAKvC;AACD,QAAM,EAAE,OAAO,aAAa,OAAO,YAAY,IAAI;AACnD,QAAM;AAAA,IACJ,SAAS;AAAA,IACT,OAAO;AAAA,IACP,gBAAgB;AAAA,EAClB,IAAI;AACJ,QAAM,aAAa,eAAe,KAAK;AAGvC,MAAI;AACJ,MAAI;AAEJ,MAAI,SAAS,MAAM,SAAS,GAAG;AAE7B,UAAM,EAAE,YAAY,QAAQ,IAAI,MAAM,2BAA2B,OAAO,OAAO,aAAa,IAAI;AAEhG,QAAI;AACF,aAAO,MAAM,IAAI,QAAQ,CAACE,aAAY;AACpC,cAAM,SAASF,OAAK,aAAa,gBAAgB,QAAQ,KAAK;AAC9D,cAAM,YAAY,KAAK,WAAW,MAAM,IAAI,SAAS;AACrD,cAAMG,WAAU,cAAc,QAAQ,CAAC,OAAO,aAAa,UAAU,IAAI,CAAC,aAAa,UAAU;AACjG,cAAM,aAAa,uBAAuB,QAAQ,WAAWA,UAAS;AAAA,UACpE,KAAK;AAAA,QACP,CAAC;AACD,0CAAkC,YAAY,aAAa;AAE3D,mBAAW,GAAG,6BAA6B,OAAO,CAAC,SAAS;AAC1D,kBAAQ;AACR,cAAI,SAAS,GAAG;AACd,YAAAD,SAAQ,EAAE,SAAS,MAAM,SAAS,MAAM,CAAC;AAAA,UAC3C,OAAO;AACL,YAAAA,SAAQ,EAAE,SAAS,OAAO,OAAO,+BAA+B,IAAI,GAAG,CAAC;AAAA,UAC1E;AAAA,QACF,CAAC;AAED,mBAAW,GAAG,6BAA6B,OAAO,CAAC,UAAU;AAC3D,kBAAQ;AACR,UAAAA,SAAQ,EAAE,SAAS,OAAO,OAAO,MAAM,QAAQ,CAAC;AAAA,QAClD,CAAC;AAAA,MACH,CAAC;AAAA,IACH,SAAS,OAAO;AACd,cAAQ;AACR,YAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC1E,aAAO,EAAE,SAAS,OAAO,OAAO,sCAAsC,YAAY,GAAG;AAAA,IACvF;AAAA,EACF,WAAW,aAAa,2BAA2B;AACjD,QAAI,YAAY,mCAAmC;AACjD,aAAO,EAAE,SAAS,MAAM,SAAS,KAAK;AAAA,IACxC;AACA,QAAI,YAAY,aAAa,WAAW,KAAK,YAAY,YAAY,WAAW,GAAG;AACjF,aAAO,EAAE,SAAS,MAAM,SAAS,KAAK;AAAA,IACxC;AACA,UAAM,EAAE,YAAY,QAAQ,IAAI,MAAM,4BAA4B,OAAO,aAAa,aAAa,IAAI;AACvG,UAAM,SAASF,OAAK,aAAa,gBAAgB,QAAQ,KAAK;AAC9D,WAAO,KAAK,WAAW,MAAM,IAAI,SAAS;AAC1C,cAAU,SAAS,QAAQ,CAAC,OAAO,aAAa,UAAU,IAAI,CAAC,aAAa,UAAU;AACtF,WAAO,IAAI,QAAQ,CAACE,aAAY;AAC9B,YAAM,aAAa,uBAAuB,QAAQ,MAAM,SAAS;AAAA,QAC/D,KAAK;AAAA,MACP,CAAC;AACD,wCAAkC,YAAY,aAAa;AAE3D,iBAAW,GAAG,6BAA6B,OAAO,CAAC,SAAS;AAC1D,gBAAQ;AACR,YAAI,SAAS,GAAG;AACd,UAAAA,SAAQ,EAAE,SAAS,MAAM,SAAS,MAAM,CAAC;AAAA,QAC3C,OAAO;AACL,UAAAA,SAAQ,EAAE,SAAS,OAAO,OAAO,+BAA+B,IAAI,GAAG,CAAC;AAAA,QAC1E;AAAA,MACF,CAAC;AAED,iBAAW,GAAG,6BAA6B,OAAO,CAAC,UAAU;AAC3D,gBAAQ;AACR,QAAAA,SAAQ,EAAE,SAAS,OAAO,OAAO,MAAM,QAAQ,CAAC;AAAA,MAClD,CAAC;AAAA,IACH,CAAC;AAAA,EACH,OAAO;AAEL,UAAM,SAASF,OAAK,aAAa,gBAAgB,QAAQ,KAAK;AAC9D,WAAO,KAAK,WAAW,MAAM,IAAI,SAAS;AAC1C,UAAM,UAAU,oBAAoB,EAAE,OAAO,WAAW,CAAC;AACzD,cAAU,SAAS,QAAQ,UAAU,QAAQ,MAAM,CAAC;AAAA,EACtD;AAEA,SAAO,IAAI,QAAQ,CAACE,aAAY;AAC9B,UAAM,aAAa,uBAAuB,QAAQ,MAAM,SAAS;AAAA,MAC/D,KAAK;AAAA,IACP,CAAC;AACD,sCAAkC,YAAY,aAAa;AAE3D,eAAW,GAAG,6BAA6B,OAAO,CAAC,SAAS;AAC1D,UAAI,SAAS,GAAG;AACd,QAAAA,SAAQ,EAAE,SAAS,MAAM,SAAS,MAAM,CAAC;AAAA,MAC3C,OAAO;AACL,QAAAA,SAAQ,EAAE,SAAS,OAAO,OAAO,+BAA+B,IAAI,GAAG,CAAC;AAAA,MAC1E;AAAA,IACF,CAAC;AAED,eAAW,GAAG,6BAA6B,OAAO,CAAC,UAAU;AAC3D,MAAAA,SAAQ,EAAE,SAAS,OAAO,OAAO,MAAM,QAAQ,CAAC;AAAA,IAClD,CAAC;AAAA,EACH,CAAC;AACH;;;ACzSO,IAAM,iCAAiC;AAAA,EAC5C,QAAQ,kCAAkC,+BAA+B,UAAU;AAAA,EACnF,cAAc,GAAG,+BAA+B,UAAU;AAAA,EAC1D,4BAA4B,0CAA0C,+BAA+B,UAAU;AAAA,EAC/G,SAAS,0BAA0B;AAAA,EACnC,YAAY,+BAA+B;AAC7C;AAYA,eAAsB,kBAAkB,SAAqE;AAC3G,QAAM,EAAE,KAAK,QAAQ,QAAQ,OAAO,MAAM,IAAI;AAC9C,QAAM,YAAY,KAAK,IAAI;AAG3B,QAAM,cAAc,iBAAiB,GAAG;AACxC,MAAI,CAAC,YAAY,SAAS;AACxB,WAAO;AAAA,MACL,UAAU;AAAA,MACV,QAAQ,QAAQ,KAAK,+BAA+B;AAAA,MACpD,YAAY,KAAK,IAAI,IAAI;AAAA,IAC3B;AAAA,EACF;AAEA,QAAM,SAAS,MAAM,cAAc,KAAK,CAAC,0BAA0B,CAAC;AACpE,MAAI,CAAC,OAAO,IAAI;AACd,WAAO;AAAA,MACL,UAAU;AAAA,MACV,QAAQ,GAAG,+BAA+B,YAAY,WAAM,OAAO,KAAK;AAAA,MACxE,YAAY,KAAK,IAAI,IAAI;AAAA,IAC3B;AAAA,EACF;AACA,QAAM,mBAAmB,OAAO,MAAM,2BAA2B,OAAO;AACxE,QAAM,uBAAuB;AAAA,IAC3B,iBAAiB;AAAA,IACjB,iCAAiC;AAAA,EACnC;AACA,QAAM,cAAc;AAAA,IAClB,mBAAmB,OAAO,GAAG;AAAA,IAC7B;AAAA,EACF;AACA,QAAM,gBAAgB,OAClB,IAAI,CAAC,SAAS,gCAAgC,KAAK,IAAI,CAAC,EACzD,OAAO,CAAC,SAAS,2BAA2B,MAAM,oBAAoB,CAAC;AAE1E,MACE,YAAY,qCACR,UAAU,UAAa,MAAM,SAAS,KAAK,eAAe,WAAW,GACzE;AACA,WAAO;AAAA,MACL,UAAU;AAAA,MACV,QAAQ,QAAQ,KAAK,+BAA+B;AAAA,MACpD,YAAY,KAAK,IAAI,IAAI;AAAA,IAC3B;AAAA,EACF;AAGA,QAAM,aAAa,MAAM,aAAa,cAAc,EAAE,aAAa,IAAI,CAAC;AACxE,MAAI,CAAC,WAAW,OAAO;AACrB,UAAM,cAAc,kBAAkB,+BAA+B,YAAY,UAAU;AAC3F,WAAO,EAAE,UAAU,GAAG,QAAQ,aAAa,YAAY,KAAK,IAAI,IAAI,UAAU;AAAA,EAChF;AAEA,QAAM,SAAS,MAAM,mBAAmB;AAAA,IACtC;AAAA,IACA,aAAa;AAAA,IACb,OAAO;AAAA,IACP;AAAA,EACF,CAAC;AACD,QAAM,aAAa,KAAK,IAAI,IAAI;AAGhC,MAAI,OAAO,SAAS;AAClB,UAAM,SAAS,QAAQ,KAAK,+BAA+B;AAC3D,WAAO,EAAE,UAAU,GAAG,QAAQ,WAAW;AAAA,EAC3C,WAAW,OAAO,SAAS;AACzB,UAAM,SAAS,QAAQ,KAAK,+BAA+B;AAC3D,WAAO,EAAE,UAAU,GAAG,QAAQ,WAAW;AAAA,EAC3C,OAAO;AACL,UAAM,SAAS,OAAO,SAAS,0BAA0B;AACzD,WAAO,EAAE,UAAU,GAAG,QAAQ,WAAW;AAAA,EAC3C;AACF;;;AChGA,IAAM,2BAA2B;AAQjC,eAAe,gBAAgB,SAAmE;AAChG,MAAI,QAAQ,aAAa;AACvB,UAAM,aAAa,QAAQ,OAAO,2BAA2B;AAC7D,WAAO,EAAE,UAAU,GAAG,QAAQ,QAAQ,QAAQ,KAAK,WAAW;AAAA,EAChE;AACA,SAAO,eAAe;AAAA,IACpB,KAAK,QAAQ;AAAA,IACb,OAAO,QAAQ;AAAA,IACf,OAAO,QAAQ;AAAA,IACf,MAAM,QAAQ;AAAA,EAChB,CAAC;AACH;AAEO,IAAM,+BAA6D;AAAA,EACxE,MAAM;AAAA,EACN,QAAQ;AAAA,IACN;AAAA,MACE,MAAM,+BAA+B;AAAA,MACrC,eAAe;AAAA,MACf,KAAK,CAAC,YAAY,gBAAgB,EAAE,KAAK,QAAQ,KAAK,OAAO,QAAQ,OAAO,MAAM,QAAQ,KAAK,CAAC;AAAA,IAClG;AAAA,IACA;AAAA,MACE,MAAM,+BAA+B;AAAA;AAAA,MAErC,eAAe;AAAA,MACf,KAAK,CAAC,YAAY,YAAY,EAAE,KAAK,QAAQ,KAAK,OAAO,QAAQ,OAAO,MAAM,QAAQ,KAAK,CAAC;AAAA,IAC9F;AAAA,IACA;AAAA,MACE,MAAM,+BAA+B;AAAA,MACrC,eAAe;AAAA,MACf,KAAK,CAAC,YACJ,YAAY;AAAA,QACV,KAAK,QAAQ;AAAA,QACb,OAAO,QAAQ;AAAA,QACf,OAAO,QAAQ;AAAA,QACf,KAAK,QAAQ;AAAA,QACb,OAAO,QAAQ;AAAA,QACf,MAAM,QAAQ;AAAA,MAChB,CAAC;AAAA,IACL;AAAA,IACA;AAAA,MACE,MAAM,+BAA+B;AAAA,MACrC,eAAe;AAAA,MACf,KAAK,CAAC,YACJ,kBAAkB;AAAA,QAChB,KAAK,QAAQ;AAAA,QACb,OAAO,QAAQ;AAAA,QACf,OAAO,QAAQ;AAAA,QACf,OAAO,QAAQ;AAAA,QACf,MAAM,QAAQ;AAAA,MAChB,CAAC;AAAA,IACL;AAAA,IACA;AAAA,MACE,MAAM,+BAA+B;AAAA,MACrC,eAAe;AAAA,MACf,KAAK;AAAA,IACP;AAAA,EACF;AACF;;;AC3EO,IAAM,qBAAyC;AAAA,EACpD,WAAW,CAAC,8BAA8B,0BAA0B;AACtE;AAGO,IAAM,2BAA2B,mBAAmB,UAAU;AAAA,EACnE,CAAC,aAAa,SAAS;AACzB;AAGO,IAAM,kCAAkC,yBAAyB;;;ACfjE,IAAM,wBAAwB;AAG9B,IAAM,qBAAqB;AAAA,EAChC,SAAS;AAAA,EACT,SAAS;AACX;AAEO,IAAM,4BAA4B;AAAA,EACvC,QAAQ;AAAA,EACR,QAAQ;AACV;AAQO,SAAS,eAAe,IAAoB;AACjD,MAAI,KAAK,uBAAuB;AAC9B,WAAO,GAAG,EAAE;AAAA,EACd;AACA,QAAM,UAAU,KAAK;AACrB,SAAO,GAAG,QAAQ,QAAQ,CAAC,CAAC;AAC9B;AA0CO,SAAS,cAAc,SAAuC;AACnE,QAAM,EAAE,SAAS,gBAAgB,IAAI;AACrC,QAAM,SAAS,UAAU,mBAAmB,UAAU,mBAAmB;AACzE,QAAM,SAAS,UAAU,0BAA0B,SAAS,0BAA0B;AACtF,QAAM,WAAW,eAAe,eAAe;AAC/C,SAAO,GAAG,MAAM,eAAe,MAAM,KAAK,QAAQ;AACpD;;;AC9DA,SAAS,qBACP,YACA,QACA,OACQ;AACR,MAAI,SAAS,CAAC,OAAO,OAAQ,QAAO;AAEpC,QAAM,SAAS,OAAO,eAAe,SAAY,KAAK,KAAK,eAAe,OAAO,UAAU,CAAC;AAC5F,SAAO,IAAI,UAAU,IAAI,+BAA+B,KAAK,OAAO,MAAM,GAAG,MAAM;AACrF;AAQA,eAAsB,WAAW,SAA8D;AAC7F,QAAM,EAAE,KAAK,OAAO,OAAO,KAAK,QAAQ,OAAO,MAAM,cAAc,MAAM,IAAI;AAC7E,QAAM,YAAY,KAAK,IAAI;AAC3B,QAAM,UAAoB,CAAC;AAC3B,MAAI,aAAa;AAEjB,QAAM,UAAU,EAAE,KAAK,OAAO,OAAO,KAAK,OAAO,MAAM,YAAY;AAEnE,MAAI,aAAa;AACjB,aAAW,SAAS,0BAA0B;AAC5C,kBAAc;AACd,UAAM,SAAS,MAAM,MAAM,IAAI,OAAO;AACtC,UAAM,aAAa,qBAAqB,YAAY,QAAQ,KAAK;AACjE,QAAI,WAAY,SAAQ,KAAK,UAAU;AACvC,QAAI,MAAM,iBAAiB,OAAO,aAAa,EAAG,cAAa;AAAA,EACjE;AAGA,QAAM,kBAAkB,KAAK,IAAI,IAAI;AAGrC,MAAI,CAAC,OAAO;AACV,UAAM,UAAU,cAAc,EAAE,SAAS,CAAC,YAAY,gBAAgB,CAAC;AACvE,YAAQ,KAAK,IAAI,OAAO;AAAA,EAC1B;AAEA,SAAO;AAAA,IACL,UAAU,aAAa,IAAI;AAAA,IAC3B,QAAQ,QAAQ,KAAK,IAAI;AAAA,IACzB,YAAY;AAAA,EACd;AACF;;;ACnEO,IAAM,kCAAkC;AACxC,IAAM,iBAAiB;AAEvB,IAAM,qBAAqB;AAC3B,IAAM,gBAAgB;AACtB,IAAM,iBAAiB;AAEvB,IAAM,2BAA2B;AACjC,IAAM,gBAAgB;AAGtB,IAAM,YAAY;AAClB,IAAM,UAAU;AAEhB,SAAS,gBAAgB,MAAsB;AACpD,SAAO,MAAM,KAAK,SAAS,SAAS,EAAE,SAAS,SAAS,GAAG,CAAC;AAC9D;AAEO,SAAS,kBAAkB,MAAsB;AACtD,SAAO,eAAe,IAAI;AAC5B;AAEO,SAAS,oBAAoB,OAAwB;AAC1D,MAAI,UAAU,OAAW,QAAO;AAChC,MAAI,UAAU,KAAM,QAAO;AAC3B,MAAI,OAAO,UAAU,SAAU,QAAO,kBAAkB,OAAO,KAAK;AACpE,MAAI,MAAM,WAAW,EAAG,QAAO;AAE/B,QAAM,UAAU,wBAAwB,KAAK;AAC7C,SAAO,SAAS,OAAO;AACzB;AAEA,SAAS,wBAAwB,OAAuB;AACtD,MAAI,MAAM;AACV,aAAW,QAAQ,OAAO;AACxB,UAAM,OAAO,KAAK,YAAY,CAAC;AAC/B,QAAI,SAAS,OAAW;AACxB,QAAI,QAAQ,4BAA4B,SAAS,eAAe;AAC9D,aAAO,gBAAgB,IAAI;AAAA,IAC7B,OAAO;AACL,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,SAAS,OAAuB;AACvC,MAAI,MAAM,UAAU,gCAAiC,QAAO;AAC5D,SAAO,MAAM,MAAM,GAAG,kCAAkC,eAAe,MAAM,IAAI;AACnF;;;ACjDA,SAAS,UAAAE,SAAQ,aAAAC,kBAAiB;AAClC,SAAS,WAAAC,UAAS,QAAAC,cAAY;AAyC9B,IAAM,UAAU;AAChB,IAAM,aAAa;AACnB,IAAM,gBAAgB;AACtB,IAAM,yBAAyB;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AACA,IAAM,mBAAmB;AACzB,IAAM,mBAAmB;AACzB,IAAM,cAAc;AACpB,IAAM,sBAAsB;AAC5B,IAAM,sBAAsB;AAErB,IAAM,mBAAiC;AAAA,EAC5C,MAAM;AACR;AAEO,IAAM,mBAAiC;AAAA,EAC5C,MAAM,MAAM,UAAkB,SAAgC;AAC5D,UAAM,MAAMC,SAAQ,QAAQ;AAC5B,UAAM,SAAS,KAAK,OAAO,EACxB,SAAS,WAAW,EACpB,MAAM,qBAAqB,sBAAsB,mBAAmB;AACvE,UAAM,UAAUC,OAAK,KAAK,GAAG,gBAAgB,GAAG,MAAM,GAAG,gBAAgB,EAAE;AAC3E,UAAMC,WAAU,SAAS,SAAS,MAAM;AACxC,UAAMC,QAAO,SAAS,QAAQ;AAAA,EAChC;AACF;AAEA,eAAsB,kBACpB,SACkC;AAClC,QAAM,SAAS,QAAQ,UAAU;AACjC,QAAM,SAAS,QAAQ,UAAU;AAEjC,QAAM,aAAa,MAAM,OAAO,KAAK,QAAQ,UAAU;AACvD,MAAI,CAAC,WAAW,IAAI;AAClB,WAAO,EAAE,UAAU,YAAY,QAAQ,WAAW,MAAM;AAAA,EAC1D;AAEA,QAAM,aAAa,WAAW;AAC9B,MAAI,WAAW,SAAS,aAAa;AACnC,WAAO,EAAE,UAAU,YAAY,QAAQ,+BAA+B,WAAW,QAAQ,EAAE;AAAA,EAC7F;AAEA,QAAM,uBAAuB,yBAAyB,UAAU;AAChE,MAAI,CAAC,qBAAqB,IAAI;AAC5B,WAAO,EAAE,UAAU,YAAY,QAAQ,qBAAqB,MAAM;AAAA,EACpE;AAEA,QAAM,YAAY,MAAM,qBAAqB;AAAA,IAC3C,YAAY,QAAQ;AAAA,IACpB,QAAQ,qBAAqB;AAAA,EAC/B,CAAC;AAED,QAAM,gBAAgB,qBAAqB,UAAU,QAAQ;AAC7D,QAAM,iBAAiB;AAAA,IACrB,qBAAqB,MAAM;AAAA,IAC3B;AAAA,EACF;AAEA,QAAM,SAAqB,WAAW,SAAS,OAC3C,WAAW,OACX,oBAAoB,QAAQ,YAAY,0BAA0B;AAEtE,QAAM,aAAa,4BAA4B,QAAQ,cAAc;AACrE,MAAI,CAAC,WAAW,IAAI;AAClB,WAAO,EAAE,UAAU,YAAY,QAAQ,WAAW,MAAM;AAAA,EAC1D;AACA,QAAM,OAAO,MAAM,OAAO,MAAM,WAAW,KAAK;AAEhD,SAAO,EAAE,UAAU,SAAS,QAAQ,GAAG;AACzC;AAEA,SAAS,yBAAyB,MAAmD;AACnF,MAAI,KAAK,SAAS,KAAM,QAAO,EAAE,IAAI,MAAM,OAAO,wBAAwB,SAAS;AACnF,QAAM,WAAW,wBAAwB,KAAK,IAAI;AAClD,MAAI,CAAC,SAAS,GAAI,QAAO;AACzB,QAAM,gBAAgB,SAAS,MAAM,kBAAkB;AACvD,MAAI,OAAO,kBAAkB,YAAY,kBAAkB,MAAM;AAC/D,WAAO,EAAE,IAAI,MAAM,OAAO,wBAAwB,SAAS;AAAA,EAC7D;AACA,QAAM,aAAc,cAA0C,6BAA6B;AAC3F,MAAI,OAAO,eAAe,YAAY,eAAe,MAAM;AACzD,WAAO,EAAE,IAAI,MAAM,OAAO,wBAAwB,SAAS;AAAA,EAC7D;AACA,QAAM,YAAa,WAAuC,oCAAoC;AAC9F,MAAI,cAAc,QAAW;AAC3B,WAAO,EAAE,IAAI,MAAM,OAAO,wBAAwB,SAAS;AAAA,EAC7D;AACA,QAAM,YAAY,wBAAwB,SAAS,SAAS;AAC5D,SAAO,UAAU,KAAK,YAAY,EAAE,IAAI,MAAM,OAAO,wBAAwB,SAAS;AACxF;AAEA,SAAS,qBACP,UAImB;AACnB,QAAM,SAAS,oBAAI,IAAY;AAC/B,aAAW,WAAW,SAAS,SAAU,QAAO,IAAI,QAAQ,KAAK;AACjE,aAAW,WAAW,SAAS,SAAU,QAAO,IAAI,QAAQ,KAAK;AACjE,SAAO,CAAC,GAAG,MAAM;AACnB;AAEA,SAAS,sBACP,UACA,eACmB;AACnB,QAAM,cAAc,YAAY,CAAC;AACjC,QAAM,cAAc,IAAI,IAAI,WAAW;AACvC,QAAM,YAAY,cAAc,OAAO,CAAC,UAAU,CAAC,YAAY,IAAI,KAAK,CAAC,EAAE,KAAK;AAChF,SAAO,CAAC,GAAG,aAAa,GAAG,SAAS;AACtC;AAEA,SAAS,4BAA4B,QAAoB,SAA4C;AACnG,SAAO,qCAAqC,QAAQ,wBAAwB,CAAC,GAAG,OAAO,CAAC;AAC1F;;;ACxGO,IAAM,0BAAmD;AAAA,EAC9D,QAAQ;AAAA,IACN,aAAa;AAAA,IACb,OAAO;AAAA,IACP,aAAa;AAAA,EACf;AAAA,EACA,aAAa;AAAA,IACX,YAAY;AAAA,MACV,aAAa;AAAA,MACb,OAAO;AAAA,MACP,aAAa;AAAA,IACf;AAAA,IACA,MAAM;AAAA,MACJ,aAAa;AAAA,MACb,aAAa;AAAA,IACf;AAAA,IACA,UAAU;AAAA,MACR,aAAa;AAAA,MACb,aAAa;AAAA,IACf;AAAA,IACA,MAAM;AAAA,MACJ,aAAa;AAAA,MACb,aAAa;AAAA,IACf;AAAA,IACA,SAAS;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,IACf;AAAA,IACA,UAAU;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,aAAa;AAAA,IACf;AAAA,IACA,KAAK;AAAA,MACH,aAAa;AAAA,MACb,aAAa;AAAA,IACf;AAAA,EACF;AAAA,EACA,uBAAuB;AAAA,IACrB,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,WAAW;AAAA,EACb;AAAA,EACA,aAAa;AAAA,IACX,mBAAmB;AAAA,MACjB,cAAc;AAAA,MACd,UAAU;AAAA,IACZ;AAAA,IACA,2BAA2B;AAAA,MACzB,cAAc;AAAA,MACd,UAAU;AAAA,IACZ;AAAA,EACF;AACF;AAEO,IAAM,8BAA8B;AAAA,EACzC,mBAAmB;AAAA,IACjB,MAAM;AAAA,IACN,aAAa;AAAA,EACf;AAAA,EACA,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,EACf;AAAA,EACA,mBAAmB;AAAA,IACjB,MAAM;AAAA,IACN,aAAa;AAAA,EACf;AAAA,EACA,UAAU;AAAA,IACR,MAAM;AAAA,IACN,aAAa;AAAA,EACf;AAAA,EACA,SAAS;AAAA,IACP,MAAM;AAAA,IACN,aAAa;AAAA,EACf;AACF;AAEO,IAAM,0BAA0B;AAAA,EACrC,aAAa;AAAA,IACX,MAAM;AAAA,IACN,aAAa;AAAA,EACf;AACF;AAEA,IAAM,+BAA+B,OAAO,OAAO,wBAAwB,WAAW,EAAE;AAAA,EACtF,CAAC,eAAe;AACd,UAAM,WAAW,CAAC,WAAW,WAAW;AACxC,QAAI,WAAW,UAAU,OAAW,UAAS,KAAK,WAAW,KAAK;AAClE,WAAO;AAAA,EACT;AACF;AAEO,IAAM,0BAA+C,oBAAI,IAAI;AAAA,EAClE,GAAG;AAAA,EACH,GAAG,OAAO,OAAO,wBAAwB,qBAAqB;AAChE,CAAC;AACM,IAAM,yBAAyB,wBAAwB,sBAAsB,SAAS,MAAM,GAAG,CAAC;AA+BvG,SAAS,iBAAiB,KAAuB;AAC/C,SAAO,IACJ,OAAO,mBAAmB,sCAAsC,MAAM,EACtE,OAAO,sBAAsB,wCAAwC,EACrE,OAAO,WAAW,0BAA0B,EAC5C,OAAO,UAAU,wBAAwB;AAC9C;AAEA,SAAS,wBACP,eACA,YACS;AACT,MAAI,aAAa,cACd,QAAQ,WAAW,WAAW,EAC9B,YAAY,WAAW,WAAW;AAErC,MAAI,WAAW,UAAU,QAAW;AAClC,iBAAa,WAAW,MAAM,WAAW,KAAK;AAAA,EAChD;AAEA,SAAO;AACT;AAKA,SAAS,2BAA2B,eAA8B;AAChE,QAAM,EAAE,YAAY,IAAI;AAGxB,QAAM,QAAQ,wBAAwB,eAAe,YAAY,UAAU,EACxE,OAAO,OAAO,YAA2B;AACxC,UAAM,SAAS,MAAM,kBAAkB;AAAA,MACrC,KAAK,QAAQ,IAAI;AAAA,MACjB,OAAO,QAAQ;AAAA,MACf,OAAO,QAAQ;AAAA,MACf,OAAO,QAAQ;AAAA,MACf,MAAM,QAAQ;AAAA,IAChB,CAAC;AACD,QAAI,OAAO,OAAQ,SAAQ,IAAI,OAAO,MAAM;AAC5C,YAAQ,KAAK,OAAO,QAAQ;AAAA,EAC9B,CAAC;AACH,mBAAiB,KAAK;AAGtB,QAAM,UAAU,wBAAwB,eAAe,YAAY,IAAI,EACpE,OAAO,SAAS,iBAAiB,EACjC,OAAO,OAAO,YAAyB;AACtC,UAAM,SAAS,MAAM,YAAY;AAAA,MAC/B,KAAK,QAAQ,IAAI;AAAA,MACjB,OAAO,QAAQ;AAAA,MACf,OAAO,QAAQ;AAAA,MACf,KAAK,QAAQ;AAAA,MACb,OAAO,QAAQ;AAAA,MACf,MAAM,QAAQ;AAAA,IAChB,CAAC;AACD,QAAI,OAAO,OAAQ,SAAQ,IAAI,OAAO,MAAM;AAC5C,YAAQ,KAAK,OAAO,QAAQ;AAAA,EAC9B,CAAC;AACH,mBAAiB,OAAO;AAGxB,QAAM,cAAc,wBAAwB,eAAe,YAAY,QAAQ,EAC5E,OAAO,OAAO,YAA2B;AACxC,UAAM,SAAS,MAAM,gBAAgB;AAAA,MACnC,KAAK,QAAQ,IAAI;AAAA,MACjB,OAAO,QAAQ;AAAA,MACf,MAAM,QAAQ;AAAA,IAChB,CAAC;AACD,QAAI,OAAO,OAAQ,SAAQ,IAAI,OAAO,MAAM;AAC5C,YAAQ,KAAK,OAAO,QAAQ;AAAA,EAC9B,CAAC;AACH,mBAAiB,WAAW;AAG5B,QAAM,UAAU,wBAAwB,eAAe,YAAY,IAAI,EACpE,OAAO,OAAO,YAA2B;AACxC,UAAM,SAAS,MAAM,YAAY;AAAA,MAC/B,KAAK,QAAQ,IAAI;AAAA,MACjB,OAAO,QAAQ;AAAA,MACf,MAAM,QAAQ;AAAA,IAChB,CAAC;AACD,QAAI,OAAO,OAAQ,SAAQ,IAAI,OAAO,MAAM;AAC5C,YAAQ,KAAK,OAAO,QAAQ;AAAA,EAC9B,CAAC;AACH,mBAAiB,OAAO;AAGxB,QAAM,aAAa,wBAAwB,eAAe,YAAY,OAAO,EAC1E;AAAA,IACC,4BAA4B,kBAAkB;AAAA,IAC9C,4BAA4B,kBAAkB;AAAA,EAChD,EACC,OAAO,4BAA4B,KAAK,MAAM,4BAA4B,KAAK,WAAW,EAC1F;AAAA,IACC,4BAA4B,kBAAkB;AAAA,IAC9C,4BAA4B,kBAAkB;AAAA,EAChD,EACC,OAAO,4BAA4B,SAAS,MAAM,4BAA4B,SAAS,WAAW,EAClG,OAAO,4BAA4B,QAAQ,MAAM,4BAA4B,QAAQ,WAAW,EAChG;AAAA,IACC;AAAA,IACA;AAAA,EAEF,EACC,OAAO,OAAO,YAA4B;AACzC,QAAI,QAAQ,mBAAmB;AAC7B,YAAMC,UAAS,MAAM,kBAAkB,EAAE,YAAY,QAAQ,IAAI,EAAE,CAAC;AACpE,UAAIA,QAAO,OAAQ,SAAQ,IAAIA,QAAO,MAAM;AAC5C,cAAQ,KAAKA,QAAO,QAAQ;AAAA,IAC9B;AACA,QAAI;AACJ,QAAI,QAAQ,SAAS,QAAW;AAC9B,aAAO,wBAAwB,QAAQ,IAAI;AAC3C,UAAI,SAAS,QAAW;AACtB,cAAM,EAAE,0BAA0B,IAAI,wBAAwB;AAC9D,gBAAQ,OAAO;AAAA,UACb,2BAA2B,0BAA0B,YAAY,KAAK,oBAAoB,QAAQ,IAAI,CAAC;AAAA;AAAA,QACzG;AACA,gBAAQ,KAAK,0BAA0B,QAAQ;AAAA,MACjD;AAAA,IACF;AACA,UAAM,SAAS,MAAM,eAAe;AAAA,MAClC,KAAK,QAAQ,IAAI;AAAA,MACjB,OAAO,QAAQ;AAAA,MACf;AAAA,MACA,mBAAmB,QAAQ;AAAA,MAC3B,UAAU,QAAQ;AAAA,MAClB,SAAS,QAAQ;AAAA,MACjB,OAAO,QAAQ;AAAA,MACf,MAAM,QAAQ;AAAA,IAChB,CAAC;AACD,QAAI,OAAO,OAAQ,SAAQ,IAAI,OAAO,MAAM;AAC5C,YAAQ,KAAK,OAAO,QAAQ;AAAA,EAC9B,CAAC;AACH,mBAAiB,UAAU;AAG3B,QAAM,cAAc,wBAAwB,eAAe,YAAY,QAAQ,EAC5E;AAAA,IACC;AAAA,IACA;AAAA,EAGF,EACC,OAAO,OAAO,YAA2B;AACxC,UAAM,SAAS,MAAM,gBAAgB;AAAA,MACnC,KAAK,QAAQ,IAAI;AAAA,MACjB,OAAO,QAAQ;AAAA,MACf,OAAO,QAAQ;AAAA,IACjB,CAAC;AACD,QAAI,OAAO,OAAQ,SAAQ,IAAI,OAAO,MAAM;AAC5C,YAAQ,KAAK,OAAO,QAAQ;AAAA,EAC9B,CAAC;AACH,mBAAiB,WAAW;AAG5B,QAAM,SAAS,wBAAwB,eAAe,YAAY,GAAG,EAClE,OAAO,SAAS,wBAAwB,EACxC,OAAO,wBAAwB,YAAY,MAAM,wBAAwB,YAAY,WAAW,EAChG,OAAO,OAAO,YAAwB;AACrC,UAAM,SAAS,MAAM,WAAW;AAAA,MAC9B,KAAK,QAAQ,IAAI;AAAA,MACjB,OAAO,QAAQ;AAAA,MACf,OAAO,QAAQ;AAAA,MACf,KAAK,QAAQ;AAAA,MACb,aAAa,QAAQ;AAAA,MACrB,OAAO,QAAQ;AAAA,MACf,MAAM,QAAQ;AAAA,IAChB,CAAC;AACD,QAAI,OAAO,OAAQ,SAAQ,IAAI,OAAO,MAAM;AAC5C,YAAQ,KAAK,OAAO,QAAQ;AAAA,EAC9B,CAAC;AACH,mBAAiB,MAAM;AACzB;AAEA,SAAS,wBAAwB,OAA+C;AAC9E,MAAI,UAAU,qBAAqB,SAAS,UAAU,qBAAqB,MAAM;AAC/E,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,wBAAwB,UAAoC;AACnE,QAAM,CAAC,KAAK,IAAI;AAChB,QAAM,YAAY,oBAAoB,KAAK;AAC3C,QAAM,EAAE,QAAQ,YAAY,IAAI;AAChC,QAAM,EAAE,kBAAkB,IAAI;AAC9B,UAAQ,OAAO,MAAM,OAAO,OAAO,WAAW,KAAK,kBAAkB,YAAY,KAAK,SAAS;AAAA,CAAI;AACnG,UAAQ,KAAK,kBAAkB,QAAQ;AACzC;AAEO,IAAM,mBAA2B;AAAA,EACtC,MAAM,wBAAwB,OAAO;AAAA,EACrC,aAAa,wBAAwB,OAAO;AAAA,EAC5C,UAAU,CAACC,aAAqB;AAC9B,UAAM,EAAE,OAAO,IAAI;AACnB,UAAM,gBAAgBA,SACnB,QAAQ,OAAO,WAAW,EAC1B,MAAM,OAAO,KAAK,EAClB,YAAY,OAAO,WAAW;AAEjC,kBAAc,GAAG,aAAa,CAAC,aAAgC;AAC7D,8BAAwB,QAAQ;AAAA,IAClC,CAAC;AAED,+BAA2B,aAAa;AAAA,EAC1C;AACF;;;AC7XO,IAAM,sBAAsB;AAC5B,IAAM,sBAAsB,CAAC,UAAU,OAAO;AAC9C,IAAM,wBAAwB,IAAI,OAAO,SAAS,oBAAoB,KAAK,GAAG,CAAC,QAAQ,GAAG;AAE1F,IAAM,4BAA4B;AAAA,EACvC,YAAY;AACd;AAEA,IAAM,qBAAqB;AAC3B,IAAM,YAAY;AAiBX,SAAS,0BACd,SACA,OACA,KAC4B;AAC5B,QAAM,OAAO,MAAM,YAAY;AAC/B,aAAW,OAAO,yBAAyB,SAAS,OAAO,GAAG,GAAG;AAC/D,UAAM,YAAY,MAAM,YAAY,GAAG;AACvC,QAAI,cAAc,OAAW,QAAO,EAAE,IAAI,MAAM,OAAO,EAAE,KAAK,WAAW,KAAK,EAAE;AAAA,EAClF;AACA,SAAO,EAAE,IAAI,OAAO,OAAO,0BAA0B,WAAW;AAClE;AAEA,UAAU,yBACR,SACA,OACA,KACmB;AACnB,QAAM,WAAW,SAAS,IAAI,mBAAmB,CAAC;AAClD,MAAI,aAAa,OAAW,OAAM;AAElC,QAAM,QAAQ,kBAAkB,SAAS,KAAK;AAC9C,MAAI,UAAU,OAAW,OAAM;AAE/B,QAAM,SAAS,MAAM,SAAS,OAAO;AACrC,MAAI,WAAW,OAAW,OAAM;AAClC;AAEA,SAAS,kBAAkB,SAAiB,OAAyC;AACnF,MAAI,MAAM,MAAM,SAAS,OAAO;AAChC,WAAS,QAAQ,GAAG,QAAQ,UAAa,QAAQ,oBAAoB,SAAS,GAAG;AAC/E,UAAM,UAAU,MAAM,UAAU,GAAG;AACnC,QAAI,YAAY,UAAa,sBAAsB,KAAK,OAAO,EAAG,QAAO;AACzE,UAAM,MAAM,SAAS,GAAG;AAAA,EAC1B;AACA,SAAO;AACT;AAEA,SAAS,SAAS,OAA+C;AAC/D,MAAI,UAAU,UAAa,MAAM,WAAW,EAAG,QAAO;AACtD,QAAM,SAAS,OAAO,SAAS,OAAO,SAAS;AAC/C,SAAO,OAAO,UAAU,MAAM,KAAK,SAAS,IAAI,SAAS;AAC3D;;;ACxEA;AAAA,EACE,SAASC;AAAA,EACT,YAAYC;AAAA,EACZ,UAAU;AAAA,EACV,MAAM;AAAA,EACN,aAAaC;AAAA,OACR;AACP,SAAS,QAAAC,cAAY;AAKd,IAAM,mBAAmB;AAAA,EAC9B,WAAW;AAAA,EACX,UAAU;AAAA,EACV,OAAO;AACT;AAIO,IAAM,kBAAkB;AAAA,EAC7B,gBAAgB;AAAA,EAChB,gBAAgB;AAClB;AAEO,IAAM,kBAAkB;AAAA,EAC7B,cAAc;AAAA,EACd,oBAAoB;AAAA,EACpB,mBAAmB;AAAA,EACnB,qBAAqB;AAAA,EACrB,iBAAiB;AACnB;AAIA,IAAMC,0BAAyB;AAkCxB,IAAM,6BAAkD;AAAA,EAC7D,OAAO,OAAOC,OAAM,YAAY;AAC9B,UAAMC,WAAUD,OAAM,OAAO;AAAA,EAC/B;AAAA,EACA,WAAW,OAAOA,OAAM,SAAS;AAC/B,UAAME,eAAcF,OAAM,IAAI;AAAA,EAChC;AAAA,EACA,QAAQ;AAAA,EACR,UAAUG;AAAA,EACV,IAAI,OAAOH,OAAM,YAAY;AAC3B,UAAM,OAAOA,OAAM,OAAO;AAAA,EAC5B;AACF;AAGO,SAAS,cAAc,MAAsB;AAClD,SAAO,GAAG,IAAI,GAAG,gBAAgB,cAAc;AACjD;AAGO,SAAS,cAAc,cAAsB,MAA8B;AAChF,QAAM,YAAY,mBAAmB,IAAI;AACzC,MAAI,CAAC,UAAU,GAAI,QAAO,EAAE,IAAI,OAAO,OAAO,gBAAgB,aAAa;AAC3E,SAAO,EAAE,IAAI,MAAM,OAAOI,OAAK,cAAc,cAAc,UAAU,KAAK,CAAC,EAAE;AAC/E;AAYO,SAAS,kBACd,OACA,OACiB;AACjB,MAAI,UAAU,OAAW,QAAO,iBAAiB;AACjD,MAAI,MAAM,SAAS,MAAM,YAAY,EAAG,QAAO,iBAAiB;AAChE,MAAI,CAAC,MAAM,QAAQ,MAAM,GAAG,EAAG,QAAO,iBAAiB;AACvD,QAAM,gBAAgB,MAAM,YAAY,MAAM,GAAG;AACjD,MAAI,kBAAkB,UAAa,kBAAkB,MAAM,UAAW,QAAO,iBAAiB;AAC9F,SAAO,iBAAiB;AAC1B;AAOA,eAAsB,WACpB,cACA,MACA,QACA,UAA8B,CAAC,GACN;AACzB,QAAMC,MAAK,QAAQ,MAAM;AACzB,QAAM,aAAa,cAAc,cAAc,IAAI;AACnD,MAAI,CAAC,WAAW,GAAI,QAAO;AAC3B,QAAM,YAAY,WAAW;AAC7B,QAAM,WAAW,GAAG,SAAS,GAAG,gBAAgB,cAAc;AAE9D,MAAI;AACF,UAAMA,IAAG,MAAM,cAAc,EAAE,WAAW,KAAK,CAAC;AAChD,UAAMA,IAAG,UAAU,UAAU,eAAe,MAAM,CAAC;AACnD,UAAMA,IAAG,OAAO,UAAU,SAAS;AACnC,WAAO,EAAE,IAAI,MAAM,OAAO,UAAU;AAAA,EACtC,SAAS,OAAO;AACd,WAAO,EAAE,IAAI,OAAO,OAAO,qBAAqB,gBAAgB,oBAAoBC,gBAAe,KAAK,CAAC,EAAE;AAAA,EAC7G;AACF;AAGA,eAAsB,UACpB,cACA,MACA,UAA8B,CAAC,GACmB;AAClD,QAAMD,MAAK,QAAQ,MAAM;AACzB,QAAM,aAAa,cAAc,cAAc,IAAI;AACnD,MAAI,CAAC,WAAW,GAAI,QAAO;AAE3B,MAAI;AACJ,MAAI;AACF,cAAU,MAAMA,IAAG,SAAS,WAAW,OAAO,MAAM;AAAA,EACtD,SAAS,OAAO;AACd,QAAI,aAAa,OAAO,oBAAoB,EAAG,QAAO,EAAE,IAAI,MAAM,OAAO,OAAU;AACnF,WAAO,EAAE,IAAI,OAAO,OAAO,qBAAqB,gBAAgB,mBAAmBC,gBAAe,KAAK,CAAC,EAAE;AAAA,EAC5G;AAEA,SAAO,WAAW,OAAO;AAC3B;AAGA,eAAsB,YACpB,cACA,MACA,UAA8B,CAAC,GACR;AACvB,QAAMD,MAAK,QAAQ,MAAM;AACzB,QAAM,aAAa,cAAc,cAAc,IAAI;AACnD,MAAI,CAAC,WAAW,GAAI,QAAO;AAE3B,MAAI;AACF,UAAMA,IAAG,GAAG,WAAW,OAAO,EAAE,OAAO,KAAK,CAAC;AAC7C,WAAO,EAAE,IAAI,MAAM,OAAO,OAAU;AAAA,EACtC,SAAS,OAAO;AACd,WAAO,EAAE,IAAI,OAAO,OAAO,qBAAqB,gBAAgB,qBAAqBC,gBAAe,KAAK,CAAC,EAAE;AAAA,EAC9G;AACF;AAGA,eAAsB,cACpB,cACA,MACA,OACA,UAA8B,CAAC,GACG;AAClC,QAAM,cAAc,MAAM,UAAU,cAAc,MAAM,OAAO;AAC/D,MAAI,CAAC,YAAY,GAAI,QAAO;AAC5B,SAAO,EAAE,IAAI,MAAM,OAAO,kBAAkB,YAAY,OAAO,KAAK,EAAE;AACxE;AAEA,SAAS,eAAe,QAAqC;AAC3D,SAAO,KAAK,UAAU;AAAA,IACpB,WAAW,OAAO;AAAA,IAClB,MAAM,OAAO;AAAA,IACb,KAAK,OAAO;AAAA,IACZ,WAAW,OAAO;AAAA,EACpB,CAAC;AACH;AAEA,SAAS,WAAW,SAA8C;AAChE,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,OAAO;AAAA,EAC7B,QAAQ;AACN,WAAO,EAAE,IAAI,OAAO,OAAO,gBAAgB,gBAAgB;AAAA,EAC7D;AACA,MAAI,CAAC,sBAAsB,MAAM,EAAG,QAAO,EAAE,IAAI,OAAO,OAAO,gBAAgB,gBAAgB;AAC/F,SAAO,EAAE,IAAI,MAAM,OAAO,OAAO;AACnC;AAEA,SAAS,sBAAsB,OAA8C;AAC3E,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,QAAM,YAAY;AAClB,SACE,OAAO,UAAU,cAAc,YAC5B,OAAO,UAAU,SAAS,YAC1B,OAAO,UAAU,QAAQ,YACzB,OAAO,UAAU,cAAc;AAEtC;AAEA,SAAS,qBAAqB,MAA0B,QAAwB;AAC9E,SAAO,GAAG,IAAI,GAAGP,uBAAsB,GAAG,MAAM;AAClD;AAEA,SAASO,gBAAe,OAAwB;AAC9C,SAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC9D;;;ACvOA,SAAS,iBAAiB;AAC1B,SAAS,gBAAgB;AAgBzB,IAAM,aAAa;AACnB,IAAM,WAAW;AAAA,EACf,YAAY;AAAA,EACZ,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA,EAKZ,SAAS;AACX;AACA,IAAM,wBAAwB;AAC9B,IAAM,+BAA+B;AACrC,IAAMC,aAAY;AAKlB,IAAM,gBAAgB,EAAE,GAAG,QAAQ,KAAK,IAAI,OAAO,QAAQ,IAAI;AAE/D,SAAS,QAAQ,KAAa,OAAmC;AAC/D,QAAM,SAAS,UAAU,YAAY,CAAC,MAAM,GAAG,KAAK,KAAK,MAAM,OAAO,GAAG,CAAC,GAAG;AAAA,IAC3E,UAAU;AAAA,IACV,KAAK;AAAA,EACP,CAAC;AACD,MAAI,OAAO,WAAW,KAAK,OAAO,OAAO,WAAW,SAAU,QAAO;AACrE,QAAM,QAAQ,OAAO,OAAO,KAAK;AACjC,SAAO,MAAM,SAAS,IAAI,QAAQ;AACpC;AAEO,IAAM,sBAAoC;AAAA,EAC/C,aAAa,MAAM,SAAS;AAAA,EAC5B,SAAS,CAAC,QAAQ;AAChB,QAAI;AACF,cAAQ,KAAK,KAAK,qBAAqB;AACvC,aAAO;AAAA,IACT,SAAS,OAAO;AACd,aAAO,aAAa,OAAO,4BAA4B;AAAA,IACzD;AAAA,EACF;AAAA,EACA,aAAa,CAAC,QAAQ,QAAQ,KAAK,SAAS,UAAU;AAAA,EACtD,UAAU,CAAC,QAAQ;AACjB,UAAM,QAAQ,QAAQ,KAAK,SAAS,UAAU;AAC9C,QAAI,UAAU,OAAW,QAAO;AAChC,UAAM,SAAS,OAAO,SAAS,OAAOA,UAAS;AAC/C,WAAO,OAAO,UAAU,MAAM,IAAI,SAAS;AAAA,EAC7C;AAAA,EACA,WAAW,CAAC,QAAQ,QAAQ,KAAK,SAAS,OAAO;AACnD;;;ACnEA,SAAS,QAAAC,aAAY;AACrB,SAAS,WAAAC,UAAS,WAAAC,gBAAe;;;ACDjC,SAAS,YAAAC,iBAAgB;AAKzB,IAAM,sBAAsB;AAC5B,IAAM,iBAAiB;AAQhB,SAAS,kBAAkB,cAA8B;AAC9D,SAAOA,UAAS,YAAY,EACzB,YAAY,EACZ,MAAM,mBAAmB,EACzB,OAAO,CAAC,YAAY,QAAQ,SAAS,CAAC,EACtC,KAAK,cAAc;AACxB;;;ADZO,IAAM,yBAAyB;AAAA,EACpC,gBAAgB;AAClB;AAiBA,eAAsB,oBAAoB,SAAgD;AACxF,MAAI,QAAQ,iBAAiB,OAAW,QAAO,QAAQ;AACvD,QAAM,WAAW,MAAM,yBAAyB,EAAE,KAAK,QAAQ,KAAK,MAAM,QAAQ,QAAQ,CAAC;AAC3F,UAAQ,YAAY,SAAS,OAAO;AACpC,SAAO,SAAS;AAClB;AAGA,eAAsB,2BAA2B,SAAgD;AAC/F,QAAM,WAAW,MAAM,0BAA0B,QAAQ,KAAK,QAAQ,OAAO;AAC7E,SAAO,kBAAkB,SAAS,UAAU;AAC9C;AAkBA,eAAsB,sBACpB,SACyC;AACzC,QAAM,OAAO,QAAQ,OAAO,QAAQ,IAAI;AACxC,QAAM,aAAa,QAAQ,aAAa,SAAY,OAAOC,SAAQ,MAAM,QAAQ,QAAQ;AACzF,QAAM,gBAAiB,MAAM,uBAAuB,UAAU,IAAKC,SAAQ,UAAU,IAAI;AACzF,QAAM,WAAW,MAAM,0BAA0B,eAAe,QAAQ,OAAO;AAC/E,MAAI,CAAC,SAAS,WAAW;AACvB,WAAO,EAAE,IAAI,OAAO,OAAO,GAAG,uBAAuB,cAAc,KAAK,QAAQ,YAAY,IAAI,GAAG;AAAA,EACrG;AACA,SAAO,EAAE,IAAI,MAAM,OAAO,EAAE,MAAM,kBAAkB,SAAS,UAAU,GAAG,cAAc,SAAS,WAAW,EAAE;AAChH;AAEA,eAAe,uBAAuBC,OAAgC;AACpE,MAAI;AACF,UAAM,YAAY,MAAMC,MAAKD,KAAI;AACjC,WAAO,CAAC,UAAU,YAAY;AAAA,EAChC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;AEvDA,eAAsB,aAAa,SAAuD;AACxF,QAAM,QAAQ,QAAQ,gBAAgB;AACtC,QAAM,cAAc,0BAA0B,QAAQ,WAAW,QAAQ,KAAK,OAAO,QAAQ,OAAO,QAAQ,GAAG;AAC/G,MAAI,CAAC,YAAY,GAAI,QAAO;AAE5B,QAAM,eAAe,MAAM,oBAAoB,OAAO;AACtD,QAAM,OAAO,MAAM,2BAA2B,OAAO;AACrD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,MACE,WAAW,QAAQ;AAAA,MACnB,MAAM,YAAY,MAAM;AAAA,MACxB,KAAK,YAAY,MAAM;AAAA,MACvB,WAAW,YAAY,MAAM;AAAA,IAC/B;AAAA,IACA,EAAE,IAAI,QAAQ,GAAG;AAAA,EACnB;AACF;;;AC7BA,eAAsBE,gBAAe,SAAuD;AAC1F,QAAM,eAAe,MAAM,oBAAoB,OAAO;AACtD,QAAM,OAAO,MAAM,2BAA2B,OAAO;AACrD,SAAO,YAAY,cAAc,MAAM,EAAE,IAAI,QAAQ,GAAG,CAAC;AAC3D;;;ACRO,IAAM,yBAAyB;AAAA,EACpC,MAAM;AAAA,EACN,MAAM;AACR;AAqBA,eAAsBC,eAAc,SAAwD;AAC1F,QAAM,QAAQ,QAAQ,gBAAgB;AACtC,QAAM,qBAAqB,QAAQ,cAAc,UAAa,QAAQ,UAAU,SAAS;AACzF,QAAM,UAAU,MAAM,qBAAqB,OAAO;AAClD,MAAI,CAAC,QAAQ,GAAI,QAAO;AAExB,QAAM,UAAkC,CAAC;AACzC,aAAW,UAAU,QAAQ,OAAO;AAClC,UAAM,eAAe,MAAM,oBAAoB,EAAE,GAAG,SAAS,KAAK,OAAO,aAAa,CAAC;AACvF,UAAM,YAAY,MAAM,cAAc,cAAc,OAAO,MAAM,OAAO,EAAE,IAAI,QAAQ,GAAG,CAAC;AAC1F,QAAI,CAAC,UAAU,GAAI,QAAO;AAC1B,YAAQ,KAAK,EAAE,UAAU,OAAO,MAAM,QAAQ,UAAU,MAAM,CAAC;AAAA,EACjE;AAEA,SAAO,EAAE,IAAI,MAAM,OAAO,aAAa,SAAS,QAAQ,QAAQ,kBAAkB,EAAE;AACtF;AAEA,eAAe,qBAAqB,SAAmF;AACrH,QAAM,YAAY,QAAQ;AAC1B,MAAI,cAAc,UAAa,UAAU,WAAW,GAAG;AACrD,UAAM,SAAS,MAAM,sBAAsB,OAAO;AAClD,QAAI,CAAC,OAAO,GAAI,QAAO;AACvB,WAAO,EAAE,IAAI,MAAM,OAAO,CAAC,OAAO,KAAK,EAAE;AAAA,EAC3C;AAEA,QAAM,UAAoC,CAAC;AAC3C,MAAI;AACJ,aAAW,YAAY,WAAW;AAChC,UAAM,SAAS,MAAM,sBAAsB,EAAE,GAAG,SAAS,SAAS,CAAC;AACnE,QAAI,OAAO,IAAI;AACb,cAAQ,KAAK,OAAO,KAAK;AAAA,IAC3B,OAAO;AACL,qBAAe,OAAO;AAAA,IACxB;AAAA,EACF;AAEA,MAAI,QAAQ,WAAW,GAAG;AACxB,WAAO,EAAE,IAAI,OAAO,OAAO,cAAc,sCAAsC;AAAA,EACjF;AAEA,SAAO,EAAE,IAAI,MAAM,OAAO,QAAQ;AACpC;AAEA,SAAS,aAAa,SAA0CC,SAA4B,oBAAqC;AAC/H,MAAIA,YAAW,uBAAuB,MAAM;AAC1C,WAAO,KAAK,UAAU,qBAAqB,UAAU,QAAQ,CAAC,CAAC;AAAA,EACjE;AACA,SAAO,QAAQ,IAAI,gBAAgB,EAAE,KAAK,IAAI;AAChD;AAEA,SAAS,iBAAiB,QAAsC;AAC9D,SAAO,GAAG,OAAO,QAAQ,IAAI,OAAO,MAAM;AAC5C;;;AC7EO,IAAM,eAAe;AAAA,EAC1B,SAAS;AAAA,EACT,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,mBAAmB;AAAA,EACnB,iBAAiB;AAAA,EACjB,aAAa;AAAA,EACb,oBAAoB;AACtB;AAEA,IAAM,8BAA8B;AAEpC,SAASC,aAAY,OAAsB;AACzC,UAAQ,MAAM,UAAU,KAAK;AAC7B,UAAQ,KAAK,CAAC;AAChB;AAEA,SAAS,yBAAyB,aAA4B;AAC5D,cACG,QAAQ,aAAa,KAAK,EAC1B,YAAY,4DAA4D,EACxE,eAAe,GAAG,aAAa,eAAe,SAAS,2BAA2B,EAClF,OAAO,GAAG,aAAa,kBAAkB,WAAW,mCAAmC,EACvF,OAAO,OAAO,YAA0D;AACvE,UAAM,SAAS,MAAM,aAAa;AAAA,MAChC,WAAW,QAAQ;AAAA,MACnB,cAAc,QAAQ;AAAA,MACtB,WAAW;AAAA,IACb,CAAC;AACD,QAAI,CAAC,OAAO,GAAI,CAAAA,aAAY,OAAO,KAAK;AAAA,EAG1C,CAAC;AAEH,cACG,QAAQ,GAAG,aAAa,MAAM,IAAI,aAAa,iBAAiB,EAAE,EAClE,YAAY,8DAA8D,EAC1E,OAAO,GAAG,aAAa,WAAW,aAAa,6BAA6B,uBAAuB,IAAI,EACvG,OAAO,GAAG,aAAa,kBAAkB,WAAW,mCAAmC,EACvF,OAAO,OAAO,WAAiC,YAAwD;AACtG,UAAM,SAAS,MAAMC,eAAc;AAAA,MACjC;AAAA,MACA,QAAQ,QAAQ;AAAA,MAChB,cAAc,QAAQ;AAAA,MACtB,WAAW;AAAA,IACb,CAAC;AACD,QAAI,CAAC,OAAO,GAAI,CAAAD,aAAY,OAAO,KAAK;AACxC,YAAQ,IAAI,OAAO,KAAK;AAAA,EAC1B,CAAC;AAEH,cACG,QAAQ,aAAa,OAAO,EAC5B,YAAY,gDAAgD,EAC5D,OAAO,GAAG,aAAa,kBAAkB,WAAW,mCAAmC,EACvF,OAAO,OAAO,YAAuC;AACpD,UAAM,SAAS,MAAME,gBAAe,EAAE,cAAc,QAAQ,cAAc,WAAW,aAAa,CAAC;AACnG,QAAI,CAAC,OAAO,GAAI,CAAAF,aAAY,OAAO,KAAK;AAAA,EAC1C,CAAC;AACL;AAKO,IAAM,iBAAyB;AAAA,EACpC,MAAM,aAAa;AAAA,EACnB,aAAa;AAAA,EACb,UAAU,CAACG,aAAqB;AAC9B,UAAM,cAAcA,SACjB,QAAQ,aAAa,OAAO,EAC5B,YAAY,2BAA2B;AAE1C,6BAAyB,WAAW;AAAA,EACtC;AACF;;;AC3EO,IAAM,cAAiC;AAAA,EAC5C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;AzJXA,iBAAiB;AAEjB,IAAMC,WAAUC,eAAc,YAAY,GAAG;AAC7C,IAAM,EAAE,QAAQ,IAAID,SAAQ,iBAAiB;AAE7C,IAAM,UAAU,IAAI,QAAQ;AAE5B,QACG,KAAK,KAAK,EACV,YAAY,2DAA2D,EACvE,QAAQ,OAAO;AAElB,WAAW,UAAU,aAAa;AAChC,SAAO,SAAS,OAAO;AACzB;AAEA,QAAQ,MAAM;","names":["createRequire","fs","fs","fs","path","os","path","program","join","createHash","dirname","join","execa","execa","path","path","join","fs","path","dirname","JSONL_LINE_SEPARATOR","worktreeScopeDir","join","program","readFile","join","path","defaults","validateEntry","version","path","value","isRecord","rejectUnknownFields","validateNonEmptyString","path","version","validate","join","path","LAYER","path","basename","isRecord","rejectUnknownFields","validate","validate","defaults","validate","validate","defaults","validate","createHash","UTF8_ENCODING","HEX_ENCODING","path","format","path","join","readFile","format","formatConfig","format","resolve","program","dirname","join","output","join","statusDirs","join","path","join","dirname","stat","path","join","parseYaml","parseYaml","join","path","stat","mkdir","join","resolve","stringifyYaml","stringifyYaml","SESSION_PRIORITY_VALUES","stringifyYaml","join","resolve","mkdir","readFile","join","join","readFile","mkdir","readdir","readFile","rename","join","readdir","join","readFile","mkdir","rename","readdir","readFile","unlink","join","readdir","join","readFile","lines","unlink","readdir","rename","readdir","rename","readFile","stat","stat","readFile","showCommand","resolve","showCommand","program","readdir","readFile","join","readFile","join","version","readdir","isFileNotFound","path","snapshot","readdir","join","ERROR_CODE_NOT_FOUND","join","readdir","hasErrorCode","join","createHash","join","SHA256_ALGORITHM","HEX_ENCODING","defaultFileSystem","fs","defaultFileSystem","runsDir","toErrorMessage","join","path","fs","toErrorMessage","isRecord","productInputDigests","createHash","SHA256_ALGORITHM","HEX_ENCODING","defaultFileSystem","fs","path","join","path","join","readFileSync","join","isNodeError","join","readFileSync","join","mkdir","writeFile","dirname","join","join","mkdir","dirname","writeFile","format","basename","dirname","join","fs","path","basename","coveredTestPaths","dirname","join","runTests","matchesTestFile","excludeFlag","detect","runTests","format","program","program","relative","isAbsolute","relative","normalizePathPrefix","pathMatchesPrefix","path","basename","dirname","join","join","path","basename","join","dirname","path","relative","value","CharacterCodes","ParseOptions","handleError","ScanError","SyntaxKind","parse","ParseErrorCode","existsSync","readFileSync","isAbsolute","join","PATH_SEGMENT_SEPARATOR","readFileSync","existsSync","path","isAbsolute","join","parse","execSync","fs","path","require","fs","execSync","path","join","join","existsSync","writeFile","isAbsolute","join","existsSync","writeFile","validateKnip","join","resolve","isAbsolute","validateKnip","existsSync","join","existsSync","readdirSync","readFileSync","statSync","join","parse","readFileSync","join","existsSync","visit","readdirSync","statSync","resolve","join","existsSync","TYPESCRIPT_ABSENT_MESSAGE","readFile","isAbsolute","relative","resolve","LAYER","path","path","readdir","join","relative","sep","isNodeError","readdir","join","relative","sep","path","path","PATH_PREFIX_SEPARATOR","normalizePathPrefix","PATH_PREFIX_SEPARATOR","applyPathFilter","isAbsolute","resolve","relative","path","readFile","TYPESCRIPT_ABSENT_MESSAGE","existsSync","mkdtemp","isAbsolute","join","mkdtemp","existsSync","join","isAbsolute","resolve","tscArgs","rename","writeFile","dirname","join","dirname","join","writeFile","rename","result","program","nodeMkdir","nodeReadFile","nodeWriteFile","join","ERROR_DETAIL_SEPARATOR","path","nodeMkdir","nodeWriteFile","nodeReadFile","join","fs","toErrorMessage","PID_RADIX","stat","dirname","resolve","basename","resolve","dirname","path","stat","releaseCommand","statusCommand","format","handleError","statusCommand","releaseCommand","program","require","createRequire"]}
|