@kyubiware/commit-mint 0.8.0 → 0.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.d.mts +6 -1
- package/dist/cli.d.mts.map +1 -0
- package/dist/cli.mjs +1193 -406
- package/dist/cli.mjs.map +1 -1
- package/package.json +1 -1
package/dist/cli.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.mjs","names":["cachePath","pkg"],"sources":["../package.json","../src/utils/debug.ts","../src/services/provider.ts","../src/services/ai.ts","../src/services/hooks.ts","../src/services/checks.ts","../src/services/config.ts","../src/services/hook-progress.ts","../src/services/git.ts","../src/services/grouping-parser.ts","../src/services/grouping-reunite.ts","../src/services/grouping.ts","../src/utils/agent.ts","../src/utils/cache.ts","../src/services/clipboard.ts","../src/ui/check-failure-menu.ts","../src/ui/check-summary.ts","../src/ui/grouping.ts","../src/ui/recovery-menu.ts","../src/ui/review-message.ts","../src/commands/auto-group.ts","../src/commands/agent.ts","../src/services/update-check.ts","../src/commands/commit-utils.ts","../src/commands/retry.ts","../src/commands/setup.ts","../src/ui/staging-menu.ts","../src/commands/staging.ts","../src/commands/commit.ts","../src/commands/config.ts","../src/commands/logs.ts","../src/services/updater.ts","../src/commands/update.ts","../src/cli.ts"],"sourcesContent":["","import { appendFileSync, mkdirSync, writeFileSync } from \"node:fs\"\nimport os from \"node:os\"\nimport { join } from \"node:path\"\nimport { dim } from \"kolorist\"\n\nlet enabled = false\nlet dirEnsured = false\nlet sessionWritten = false\nlet logFile = join(os.homedir(), \".cache\", \"commit-mint\", \"debug.log\")\n\nconst LOG_DIR = join(os.homedir(), \".cache\", \"commit-mint\")\n\nfunction ensureLogDir(): void {\n\tif (dirEnsured) return\n\tmkdirSync(LOG_DIR, { recursive: true })\n\tdirEnsured = true\n}\n\nexport function setDebug(value: boolean): void {\n\tenabled = value\n}\n\nexport function isDebug(): boolean {\n\treturn enabled\n}\n\nexport function getLogFilePath(): string {\n\treturn logFile\n}\n\n/** Override log file path (used by tests to avoid polluting real logs) */\nexport function setLogFilePath(path: string): void {\n\tlogFile = path\n}\n\nexport function writeSessionHeader(): void {\n\tif (sessionWritten) return\n\tensureLogDir()\n\twriteFileSync(logFile, `--- session ${new Date().toISOString()} ---\\n`, \"utf8\")\n\tsessionWritten = true\n}\n\nexport function debug(...args: unknown[]): void {\n\tconst timestamp = new Date().toISOString().slice(11, 23)\n\tconst prefix = `[debug ${timestamp}]`\n\tensureLogDir()\n\tappendFileSync(logFile, `${prefix} ${args.map(String).join(\" \")}\\n`, \"utf8\")\n\tif (!enabled) return\n\tconsole.error(dim(prefix), ...args)\n}\n","import Groq from \"groq-sdk\"\nimport { debug } from \"../utils/debug.js\"\n\nexport type ProviderName = \"groq\" | \"cerebras\" | \"mistral\"\n\nexport interface ProviderConfig {\n\tbaseURL: string\n\tdefaultModel: string\n}\n\nexport const PROVIDER_CONFIGS: Record<ProviderName, ProviderConfig> = {\n\tgroq: {\n\t\tbaseURL: \"https://api.groq.com\",\n\t\tdefaultModel: \"openai/gpt-oss-20b\",\n\t},\n\tcerebras: {\n\t\tbaseURL: \"https://api.cerebras.ai/v1\",\n\t\tdefaultModel: \"gpt-oss-120b\",\n\t},\n\tmistral: {\n\t\tbaseURL: \"https://api.mistral.ai/v1\",\n\t\tdefaultModel: \"mistral-small\",\n\t},\n}\n\nexport const ALLOWED_PROVIDERS = Object.keys(PROVIDER_CONFIGS) as ProviderName[]\nexport const DEFAULT_PROVIDER: ProviderName = \"groq\"\n\nexport const PROVIDER_ENV_KEYS: Record<ProviderName, string> = {\n\tgroq: \"GROQ_API_KEY\",\n\tcerebras: \"CEREBRAS_API_KEY\",\n\tmistral: \"MISTRAL_API_KEY\",\n}\n\nexport function formatProviderName(provider: string): string {\n\treturn provider.charAt(0).toUpperCase() + provider.slice(1)\n}\n\nexport function isValidProvider(name: string): name is ProviderName {\n\treturn ALLOWED_PROVIDERS.includes(name as ProviderName)\n}\n\n/**\n * Generic OpenAI-compatible chat completions client using fetch.\n * Used for non-Groq providers where the Groq SDK's hardcoded `/openai/v1/` path\n * prefix doesn't match the provider's actual API path.\n */\nfunction createFetchClient(baseURL: string, apiKey: string, timeout: number) {\n\treturn {\n\t\tchat: {\n\t\t\tcompletions: {\n\t\t\t\tasync create(params: {\n\t\t\t\t\tmessages: Array<{\n\t\t\t\t\t\trole: string\n\t\t\t\t\t\tcontent: string | Array<{ type: string; text?: string }>\n\t\t\t\t\t}>\n\t\t\t\t\tmodel: string\n\t\t\t\t\ttemperature?: number\n\t\t\t\t\tmax_tokens?: number\n\t\t\t\t\tmax_completion_tokens?: number\n\t\t\t\t\treasoning_format?: string\n\t\t\t\t}) {\n\t\t\t\t\tconst url = `${baseURL}/chat/completions`\n\t\t\t\t\tdebug(\"fetchClient: POST %s, model=%s\", url, params.model)\n\t\t\t\t\tconst controller = new AbortController()\n\t\t\t\t\tconst timer = setTimeout(() => controller.abort(), timeout)\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst response = await fetch(url, {\n\t\t\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\t\t\t\tAuthorization: `Bearer ${apiKey}`,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbody: JSON.stringify(params),\n\t\t\t\t\t\t\tsignal: controller.signal,\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\tif (!response.ok) {\n\t\t\t\t\t\t\tconst text = await response.text().catch(() => \"\")\n\t\t\t\t\t\t\tthrow new Error(`${response.status} ${text}`)\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn (await response.json()) as {\n\t\t\t\t\t\t\tchoices: Array<{\n\t\t\t\t\t\t\t\tmessage?: {\n\t\t\t\t\t\t\t\t\tcontent?: string | Array<{ type: string; text?: string }>\n\t\t\t\t\t\t\t\t\treasoning?: string\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tfinish_reason?: string\n\t\t\t\t\t\t\t}>\n\t\t\t\t\t\t}\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tclearTimeout(timer)\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n}\n\nexport type ChatClient = Pick<Groq, \"chat\">\n\nexport function createProvider(options: {\n\tprovider: ProviderName\n\tapiKey: string\n\tmodelOverride?: string\n\ttimeout?: number\n\tbaseURLOverride?: string\n}): { client: ChatClient; model: string } {\n\tif (!isValidProvider(options.provider)) {\n\t\tthrow new Error(\n\t\t\t`Invalid provider \"${options.provider}\". Allowed values: ${ALLOWED_PROVIDERS.join(\", \")}`,\n\t\t)\n\t}\n\n\tconst providerConfig = PROVIDER_CONFIGS[options.provider]\n\tconst model = options.modelOverride ?? providerConfig.defaultModel\n\tconst baseURL = options.baseURLOverride ?? providerConfig.baseURL\n\tconst timeout = options.timeout ?? 60000\n\n\tlet client: ChatClient\n\tif (options.provider === \"groq\") {\n\t\tclient = new Groq({\n\t\t\tapiKey: options.apiKey,\n\t\t\tbaseURL,\n\t\t\ttimeout,\n\t\t})\n\t} else {\n\t\tclient = createFetchClient(baseURL, options.apiKey, timeout) as unknown as ChatClient\n\t}\n\n\treturn { client, model }\n}\n","import Groq from \"groq-sdk\"\nimport { debug } from \"../utils/debug.js\"\nimport { createProvider, formatProviderName, type ProviderName } from \"./provider.js\"\n\nconst MAX_DIFF_CHARS = 20000\n\nexport function mapGroqError(error: unknown, providerLabel?: string): Error {\n\tconst label = providerLabel ?? \"Groq\"\n\tif (error instanceof Groq.AuthenticationError) {\n\t\treturn new Error(\n\t\t\t`Invalid API key for ${label}. Run: cmint config set ${label.toUpperCase()}_API_KEY=<key>`,\n\t\t)\n\t}\n\tif (error instanceof Groq.RateLimitError) {\n\t\treturn new Error(`Rate limited by ${label}. Please wait and try again.`)\n\t}\n\tif (error instanceof Groq.APIConnectionTimeoutError) {\n\t\treturn new Error(\"Request timed out. Check your network or try a smaller diff.\")\n\t}\n\tif (error instanceof Groq.APIError) {\n\t\treturn new Error(`${label} API error: ${error.message}`)\n\t}\n\t// Handle errors from the generic fetch client (non-Groq providers)\n\tif (error instanceof Error && /^4\\d{2}\\s/.test(error.message)) {\n\t\treturn new Error(`${label} API error: ${error.message}`)\n\t}\n\treturn new Error(`Unexpected error: ${error instanceof Error ? error.message : String(error)}`)\n}\n\nconst CONVENTIONAL_COMMIT_REGEX =\n\t/^(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test)(\\(.+\\))?!?: .+$/\n\nexport function stripThinkTags(text: string): string {\n\treturn text.replace(/<think[\\s\\S]*?<\\/think>/gi, \"\").trim()\n}\n\nexport function deriveMessageFromReasoning(reasoning: string): string | null {\n\tconst match = reasoning.match(\n\t\t/(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test)(\\(.+\\))?!?: .+/i,\n\t)\n\tif (match) return match[0].trim()\n\n\tconst sentences = reasoning.split(/[.!?]/)\n\tconst first = sentences.find((s) => s.trim().length >= 10)\n\treturn first ? first.trim() : null\n}\n\nfunction stripContextLines(diff: string): string {\n\treturn diff\n\t\t.split(\"\\n\")\n\t\t.filter((line) => !line.startsWith(\" \"))\n\t\t.join(\"\\n\")\n}\n\nexport function compressDiff(diff: string): string {\n\t// Tier 0 — Full diff\n\tif (diff.length <= MAX_DIFF_CHARS) {\n\t\treturn diff\n\t}\n\n\t// Tier 1 — Strip context lines\n\tlet result = stripContextLines(diff)\n\tif (result.length <= MAX_DIFF_CHARS) {\n\t\treturn result\n\t}\n\n\t// Tier 2 — Per-hunk line cap\n\tconst fileDiffs = result.split(/(?=diff --git)/).filter(Boolean)\n\tconst cappedFiles = fileDiffs.map((fd) => {\n\t\tconst parts = fd.split(/(?=\\n@@)/)\n\t\tconst cappedParts = parts.map((part, idx) => {\n\t\t\tif (idx === 0) return part // Keep file header\n\t\t\tconst lines = part.split(\"\\n\")\n\t\t\tconst header = lines[0] // @@ line\n\t\t\tconst changedLines = lines.slice(1).filter((l) => l.startsWith(\"+\") || l.startsWith(\"-\"))\n\t\t\tconst keptLines = changedLines.slice(0, 10)\n\t\t\treturn [header, ...keptLines].join(\"\\n\")\n\t\t})\n\t\treturn cappedParts.join(\"\")\n\t})\n\tresult = cappedFiles.join(\"\")\n\tif (result.length <= MAX_DIFF_CHARS) {\n\t\treturn result\n\t}\n\n\t// Tier 3 — File summary\n\tconst fileMatches = diff.match(/^diff --git a\\/(.+) b\\/(.+)$/gm) || []\n\tconst summary = fileMatches\n\t\t.map((f) => {\n\t\t\tconst match = f.match(/^diff --git a\\/(.+) b\\/(.+)$/)\n\t\t\treturn match && match[1] === match[2] ? `${match[1]} | changed` : \"\"\n\t\t})\n\t\t.filter(Boolean)\n\treturn `Summary of changes:\\n${summary.join(\"\\n\")}`\n}\n\nexport function buildStatSummary(diff: string): string {\n\tconst files: { name: string; adds: number; dels: number }[] = []\n\tlet currentFile = \"\"\n\tlet adds = 0\n\tlet dels = 0\n\n\tfor (const line of diff.split(\"\\n\")) {\n\t\tconst match = line.match(/^diff --git a\\/.+ b\\/(.+)$/)\n\t\tif (match) {\n\t\t\tif (currentFile) files.push({ name: currentFile, adds, dels })\n\t\t\tcurrentFile = match[1]\n\t\t\tadds = 0\n\t\t\tdels = 0\n\t\t} else if (line.startsWith(\"+\") && !line.startsWith(\"+++\")) {\n\t\t\tadds++\n\t\t} else if (line.startsWith(\"-\") && !line.startsWith(\"---\")) {\n\t\t\tdels++\n\t\t}\n\t}\n\tif (currentFile) files.push({ name: currentFile, adds, dels })\n\n\tconst totalAdds = files.reduce((s, f) => s + f.adds, 0)\n\tconst totalDels = files.reduce((s, f) => s + f.dels, 0)\n\n\tconst lines = files.map((f) => ` ${f.name} | +${f.adds} -${f.dels}`)\n\tlines.push(\n\t\t` ${files.length} files changed, ${totalAdds} insertions(+), ${totalDels} deletions(-)`,\n\t)\n\n\treturn lines.join(\"\\n\")\n}\n\nfunction buildSystemPrompt(type?: string): string {\n\tlet prompt =\n\t\t\"You are a commit message generator. Follow the Conventional Commits specification.\\n\" +\n\t\t\"Valid types: build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test.\\n\" +\n\t\t\"Format: type(scope): description\\n\" +\n\t\t\"Use imperative mood, lowercase, no trailing period.\\n\" +\n\t\t\"Output ONLY the commit message, no markdown fences, no explanation.\"\n\n\tif (type && type.trim().length > 0) {\n\t\tprompt += `\\nYou MUST use type: ${type}`\n\t}\n\n\treturn prompt\n}\n\nfunction buildUserPrompt(diff: string, hint?: string, statSummary?: string): string {\n\tconst parts: string[] = []\n\tif (hint) parts.push(`Context: ${hint}`)\n\tif (statSummary) parts.push(`Change summary:\\n${statSummary}`)\n\tparts.push(`Generate a conventional commit for:\\n\\n${diff}`)\n\treturn parts.join(\"\\n\\n\")\n}\n\nfunction isValidConventionalCommit(message: string): boolean {\n\treturn CONVENTIONAL_COMMIT_REGEX.test(message)\n}\n\nexport function extractContentText(\n\tcontent: string | Array<{ type: string; text?: string }> | null | undefined,\n): string {\n\tif (content == null) return \"\"\n\tif (typeof content === \"string\") return content.trim()\n\tif (Array.isArray(content)) {\n\t\treturn content\n\t\t\t.filter((part) => part.type === \"text\" && typeof part.text === \"string\")\n\t\t\t.map((part) => stripThinkTags(part.text as string))\n\t\t\t.join(\"\")\n\t\t\t.trim()\n\t}\n\treturn \"\"\n}\n\n// biome-ignore lint/complexity/noExcessiveLinesPerFunction: AI pipeline — prompt build, call, validate, retry, error mapping\nexport async function generateCommitMessage(\n\tdiff: string,\n\toptions: {\n\t\tapiKey: string\n\t\tmodel?: string\n\t\ttype?: string\n\t\ttimeout?: number\n\t\thint?: string\n\t\tprovider?: ProviderName\n\t\tproxy?: string\n\t},\n): Promise<string> {\n\tconst timeoutMs = options.timeout ?? 60000\n\tdebug(\"Timeout: %d ms\", timeoutMs)\n\n\tconst { client, model } = createProvider({\n\t\tprovider: options.provider ?? \"groq\",\n\t\tapiKey: options.apiKey,\n\t\tmodelOverride: options.model,\n\t\ttimeout: timeoutMs,\n\t\tbaseURLOverride: options.proxy,\n\t})\n\n\tdebug(\n\t\t\"generateCommitMessage: model=%s, type=%s, hint=%s\",\n\t\tmodel,\n\t\toptions.type ?? \"none\",\n\t\toptions.hint ?? \"none\",\n\t)\n\n\tconst compressedDiff = compressDiff(diff)\n\tconst statSummary = buildStatSummary(diff)\n\tconst systemPrompt = buildSystemPrompt(options.type)\n\tconst userPrompt = buildUserPrompt(compressedDiff, options.hint, statSummary)\n\n\tdebug(\"Diff: %d chars → compressed to %d chars\", diff.length, compressedDiff.length)\n\tdebug(\"Stat summary:\\n%s\", statSummary)\n\tdebug(\"User prompt length: %d chars\", userPrompt.length)\n\n\t// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Error class instanceof chain for API error mapping\n\t// biome-ignore lint/complexity/noExcessiveLinesPerFunction: API call with streaming, error handling, and retry\n\tasync function callAI(strictSystemPrompt?: string): Promise<string> {\n\t\tconst callStart = Date.now()\n\t\tconst isRetry = !!strictSystemPrompt\n\t\tdebug(\n\t\t\t\"callAI: %s — model=%s, promptLen=%d, systemLen=%d\",\n\t\t\tisRetry ? \"RETRY (strict)\" : \"INITIAL\",\n\t\t\tmodel,\n\t\t\tuserPrompt.length,\n\t\t\t(strictSystemPrompt ?? systemPrompt).length,\n\t\t)\n\t\ttry {\n\t\t\tconst isReasoningModel = /^(o[1-9]|.*gpt-oss.*|.*gpt-5.*)/i.test(model)\n\t\t\tconst isGroq = (options.provider ?? \"groq\") === \"groq\"\n\t\t\tconst completion = await client.chat.completions.create({\n\t\t\t\tmessages: [\n\t\t\t\t\t{ role: \"system\", content: strictSystemPrompt ?? systemPrompt },\n\t\t\t\t\t{ role: \"user\", content: userPrompt },\n\t\t\t\t],\n\t\t\t\tmodel,\n\t\t\t\ttemperature: 0.3,\n\t\t\t\t...(isReasoningModel ? { max_completion_tokens: 1024 } : { max_tokens: 1024 }),\n\t\t\t\t...(isGroq && isReasoningModel ? { reasoning_format: \"parsed\" } : {}),\n\t\t\t})\n\n\t\t\tconst elapsed = Date.now() - callStart\n\t\t\tconst rawContent = completion.choices[0]?.message?.content\n\t\t\tconst processedContent =\n\t\t\t\ttypeof rawContent === \"string\" ? stripThinkTags(rawContent) : rawContent\n\t\t\tconst content = extractContentText(processedContent)\n\t\t\tdebug(\n\t\t\t\t\"callAI response (%d ms): choices=%d, finishReason=%s, contentLen=%d, rawType=%s\",\n\t\t\t\telapsed,\n\t\t\t\tcompletion.choices.length,\n\t\t\t\tcompletion.choices[0]?.finish_reason ?? \"(none)\",\n\t\t\t\tcontent.length,\n\t\t\t\ttypeof rawContent,\n\t\t\t)\n\t\t\tdebug(\"callAI raw content: %s\", content.slice(0, 300) || \"(empty)\")\n\t\t\tif (!content) {\n\t\t\t\tconst reasoning = completion.choices[0]?.message?.reasoning\n\t\t\t\tdebug(\n\t\t\t\t\t\"callAI: content empty, attempting reasoning fallback (reasoningLen=%d)\",\n\t\t\t\t\treasoning?.length ?? 0,\n\t\t\t\t)\n\t\t\t\tif (reasoning) {\n\t\t\t\t\tconst derived = deriveMessageFromReasoning(reasoning)\n\t\t\t\t\tif (derived) {\n\t\t\t\t\t\tdebug(\"callAI: derived message from reasoning: %s\", derived.slice(0, 100))\n\t\t\t\t\t\treturn stripThinkTags(derived)\n\t\t\t\t\t}\n\t\t\t\t\tdebug(\"callAI: could not derive message from reasoning\")\n\t\t\t\t}\n\t\t\t\tthrow new Error(\"AI returned an empty commit message\")\n\t\t\t}\n\t\t\treturn content\n\t\t} catch (error) {\n\t\t\tconst elapsed = Date.now() - callStart\n\t\t\tdebug(\n\t\t\t\t\"callAI FAILED after %d ms: %s\",\n\t\t\t\telapsed,\n\t\t\t\terror instanceof Error ? `${error.name}: ${error.message}` : String(error),\n\t\t\t)\n\t\t\tthrow error\n\t\t}\n\t}\n\n\ttry {\n\t\tconst totalStart = Date.now()\n\t\tlet message = await callAI()\n\t\tdebug(\n\t\t\t\"Validation: message=%s, isValid=%s\",\n\t\t\tmessage.slice(0, 100),\n\t\t\tisValidConventionalCommit(message),\n\t\t)\n\n\t\tif (!isValidConventionalCommit(message)) {\n\t\t\tdebug(\n\t\t\t\t\"Initial message failed conventional commit validation, retrying with strict prompt (elapsed: %d ms)\",\n\t\t\t\tDate.now() - totalStart,\n\t\t\t)\n\t\t\tconst retryMessage = await callAI(\n\t\t\t\t\"You MUST output ONLY a valid conventional commit message. \" +\n\t\t\t\t\t\"Format: type(scope): description. \" +\n\t\t\t\t\t\"If you output anything else your response will be rejected.\\n\" +\n\t\t\t\t\t\"Valid types: build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test.\",\n\t\t\t)\n\t\t\tdebug(\n\t\t\t\t\"Retry validation: message=%s, isValid=%s\",\n\t\t\t\tretryMessage.slice(0, 100),\n\t\t\t\tisValidConventionalCommit(retryMessage),\n\t\t\t)\n\t\t\tif (isValidConventionalCommit(retryMessage)) {\n\t\t\t\tdebug(\"Retry produced valid conventional commit\")\n\t\t\t\tmessage = retryMessage\n\t\t\t} else {\n\t\t\t\tdebug(\"Retry also failed validation, using original message\")\n\t\t\t}\n\t\t}\n\n\t\tdebug(\"Final message (%d ms total): %s\", Date.now() - totalStart, message)\n\t\treturn message\n\t} catch (error) {\n\t\tdebug(\"AI error: %s\", error instanceof Error ? error.message : String(error))\n\t\tconst providerLabel = options.provider ? formatProviderName(options.provider) : undefined\n\t\tthrow mapGroqError(error, providerLabel)\n\t}\n}\n","import { debug } from \"../utils/debug.js\"\n\nexport interface HookError {\n\ttool: string\n\tmessage: string\n\traw: string\n}\n\n/**\n * Parse git hook error output into structured, human-readable errors.\n * Handles output from lint-staged, biome, eslint, tsc, vitest, jest.\n */\nexport function parseHookErrors(stderr: string): HookError[] {\n\tif (!stderr) return []\n\n\tdebug(\"parseHookErrors: stderr length=%d\", stderr.length)\n\tconst errors: HookError[] = []\n\n\t// Detect lint-staged task failures\n\tif (stderr.includes(\"lint-staged\") || stderr.includes(\"[FAILED]\")) {\n\t\terrors.push(...parseLintStagedErrors(stderr))\n\t}\n\n\t// Detect biome errors\n\tif (stderr.includes(\"biome\") || stderr.includes(\"Biome\")) {\n\t\terrors.push(...parseBiomeErrors(stderr))\n\t}\n\n\t// Detect TypeScript errors\n\tif (stderr.includes(\"error TS\") || stderr.includes(\"tsc\")) {\n\t\terrors.push(...parseTscErrors(stderr))\n\t}\n\n\t// Detect vitest/jest test failures\n\tif (\n\t\tstderr.includes(\"vitest\") ||\n\t\tstderr.includes(\"jest\") ||\n\t\tstderr.includes(\"FAIL\") ||\n\t\tstderr.includes(\"test failed\")\n\t) {\n\t\terrors.push(...parseTestErrors(stderr))\n\t}\n\n\t// Detect ESLint errors\n\tif (stderr.includes(\"eslint\") || stderr.includes(\"ESLint\")) {\n\t\terrors.push(...parseEslintErrors(stderr))\n\t}\n\n\t// Fallback: if nothing parsed, return the raw output\n\tif (errors.length === 0) {\n\t\tdebug(\"parseHookErrors: no patterns matched, using raw fallback\")\n\t\terrors.push({\n\t\t\ttool: \"git hooks\",\n\t\t\tmessage: stderr.trim(),\n\t\t\traw: stderr,\n\t\t})\n\t}\n\n\tdebug(\"parseHookErrors: found %d errors\", errors.length)\n\treturn errors\n}\n\nfunction parseLintStagedErrors(output: string): HookError[] {\n\tconst errors: HookError[] = []\n\tfor (const match of output.matchAll(/\\[FAILED\\]\\s+(.+?)\\s+\\[FAILED\\]/g)) {\n\t\tconst task = match[1].trim()\n\t\terrors.push({\n\t\t\ttool: \"lint-staged\",\n\t\t\tmessage: `Task failed: ${task}`,\n\t\t\traw: match[0],\n\t\t})\n\t}\n\n\treturn errors\n}\n\nfunction parseBiomeErrors(output: string): HookError[] {\n\tconst errors: HookError[] = []\n\tfor (const match of output.matchAll(/^(.+?):(\\d+):(\\d+)\\s+(.+)$/gm)) {\n\t\terrors.push({\n\t\t\ttool: \"biome\",\n\t\t\tmessage: `${match[1]}:${match[2]}:${match[3]} — ${match[4]}`,\n\t\t\traw: match[0],\n\t\t})\n\t}\n\n\tif (errors.length === 0 && output.includes(\"biome\")) {\n\t\terrors.push({\n\t\t\ttool: \"biome\",\n\t\t\tmessage: \"Biome check failed. See raw output for details.\",\n\t\t\traw: output,\n\t\t})\n\t}\n\n\treturn errors\n}\n\nfunction parseTscErrors(output: string): HookError[] {\n\tconst errors: HookError[] = []\n\tfor (const match of output.matchAll(/^(.+?)\\((\\d+),(\\d+)\\):\\s+error\\s+(TS\\d+):\\s+(.+)$/gm)) {\n\t\terrors.push({\n\t\t\ttool: \"tsc\",\n\t\t\tmessage: `${match[1]}:${match[2]}:${match[3]} — ${match[4]}: ${match[5]}`,\n\t\t\traw: match[0],\n\t\t})\n\t}\n\n\treturn errors\n}\n\nfunction parseTestErrors(output: string): HookError[] {\n\tconst errors: HookError[] = []\n\tconst failPattern = /FAIL\\s+(.+\\.(test|spec)\\..+)/\n\tconst match = failPattern.exec(output)\n\n\tif (match) {\n\t\terrors.push({\n\t\t\ttool: output.includes(\"vitest\") ? \"vitest\" : \"jest\",\n\t\t\tmessage: `Test file failed: ${match[1]}`,\n\t\t\traw: output,\n\t\t})\n\t}\n\n\tif (errors.length === 0 && (output.includes(\"vitest\") || output.includes(\"jest\"))) {\n\t\terrors.push({\n\t\t\ttool: output.includes(\"vitest\") ? \"vitest\" : \"jest\",\n\t\t\tmessage: \"Tests failed. See raw output for details.\",\n\t\t\traw: output,\n\t\t})\n\t}\n\n\treturn errors\n}\n\nfunction parseEslintErrors(output: string): HookError[] {\n\tconst errors: HookError[] = []\n\tconst lines = output.split(\"\\n\")\n\tlet currentFile = \"\"\n\n\tfor (const line of lines) {\n\t\t// ESLint file path line: not indented, contains a path separator\n\t\tif (!/^\\s/.test(line) && line.includes(\"/\")) {\n\t\t\tcurrentFile = line.trim()\n\t\t\tcontinue\n\t\t}\n\n\t\t// ESLint error/warning detail: <line>:<col> <severity> <message> <rule>\n\t\t// Message and rule are separated by 2+ spaces\n\t\tconst match = line.match(/^\\s*(\\d+):(\\d+)\\s+(error|warning)\\s+(.+)\\s{2,}(\\S+)\\s*$/)\n\t\tif (match) {\n\t\t\tconst [, lineNum, col, severity, message, rule] = match\n\t\t\tconst file = currentFile || \"unknown\"\n\t\t\terrors.push({\n\t\t\t\ttool: \"eslint\",\n\t\t\t\tmessage: `${file}:${lineNum}:${col} ${severity}: ${message} (${rule})`,\n\t\t\t\traw: line.trim(),\n\t\t\t})\n\t\t}\n\t}\n\n\treturn errors\n}\n\nexport function formatErrorReport(errors: HookError[]): string {\n\tif (errors.length === 0) return \"\"\n\n\tconst sections = errors.map((e) => `[${e.tool}]\\n${e.message}`)\n\treturn sections.join(\"\\n\\n\")\n}\n\n/**\n * Parse cmint check output into structured errors.\n * Check output uses [tool] prefix format (built by callers in auto-group.ts / staging.ts).\n * This is distinct from parseHookErrors which handles raw git hook stderr.\n */\nexport function parseCheckErrors(output: string): HookError[] {\n\tif (!output.trim()) return []\n\n\tconst errors: HookError[] = []\n\tconst lines = output.split(\"\\n\")\n\n\tlet currentTool = \"\"\n\tlet currentLines: string[] = []\n\n\tconst flush = () => {\n\t\tif (currentTool && currentLines.length > 0) {\n\t\t\tconst message = currentLines.join(\"\\n\").trim()\n\t\t\tif (message) {\n\t\t\t\terrors.push({ tool: currentTool, message, raw: currentLines.join(\"\\n\") })\n\t\t\t}\n\t\t}\n\t\tcurrentTool = \"\"\n\t\tcurrentLines = []\n\t}\n\n\tfor (const line of lines) {\n\t\tconst match = line.match(/^\\[(\\S+)\\]\\s*(.*)/)\n\t\tif (match) {\n\t\t\t// New [tool] block — flush previous\n\t\t\tflush()\n\t\t\tcurrentTool = match[1]\n\t\t\tconst rest = match[2].trim()\n\t\t\tif (rest) {\n\t\t\t\tcurrentLines.push(rest)\n\t\t\t}\n\t\t} else if (currentTool) {\n\t\t\t// Continuation line for current [tool] block\n\t\t\tcurrentLines.push(line)\n\t\t} else {\n\t\t\t// No [tool] prefix — accumulate as raw\n\t\t\tcurrentLines.push(line)\n\t\t}\n\t}\n\n\tflush()\n\n\t// If no [tool] prefixed blocks found, fall back to single raw error\n\tif (errors.length === 0) {\n\t\tconst trimmed = output.trim()\n\t\tif (trimmed) {\n\t\t\terrors.push({ tool: \"checks\", message: trimmed, raw: output })\n\t\t}\n\t}\n\n\treturn errors\n}\n\n// ── Tool check parsing (success case) ──────────────────────────────\n\nexport interface ToolCheck {\n\ttool: string\n\tok: boolean\n}\n\n/**\n * Parse lint-staged/hook stderr output to discover which tools ran\n * and whether they succeeded. Used for clean post-commit summary.\n */\nexport function parseToolChecks(stderr: string): ToolCheck[] {\n\tif (!stderr) return []\n\n\tconst checks: ToolCheck[] = []\n\t// Match [COMPLETED] and [FAILED] status lines from lint-staged\n\tfor (const match of stderr.matchAll(/\\[(COMPLETED|FAILED)\\]\\s+(.+)/g)) {\n\t\tconst status = match[1]\n\t\tconst command = match[2].trim()\n\n\t\tif (isLintStagedMeta(command)) continue\n\n\t\tconst tool = extractToolName(command)\n\t\tif (!tool) continue\n\n\t\tchecks.push({ tool, ok: status === \"COMPLETED\" })\n\t}\n\n\t// Deduplicate by tool name (keep last occurrence — final status)\n\tconst seen = new Map<string, ToolCheck>()\n\tfor (const c of checks) {\n\t\tseen.set(c.tool, c)\n\t}\n\n\treturn [...seen.values()]\n}\n\n/** Heuristic: skip lint-staged internal metadata lines */\nexport function isLintStagedMeta(command: string): boolean {\n\t// Glob patterns in task labels\n\tif (/[*{}[\\]]/.test(command)) return true\n\t// Task count labels: \"src/ — 3 files\", \"src/ — no files\"\n\t// The dash can be em-dash (—), en-dash (–), or plain hyphen (-)\n\tif (/\\s[-–—]\\s(\\d+\\s)?files?$/.test(command)) return true\n\tif (/\\s[-–—]\\sno\\s files$/.test(command)) return true\n\t// Internal lint-staged lifecycle messages\n\tif (\n\t\t/^(Running tasks|Applying modifications|Cleaning up|Backing up|Backed up|Updating Git)/.test(\n\t\t\tcommand,\n\t\t)\n\t)\n\t\treturn true\n\t// Ends with ellipsis (e.g. \"Backing up original state...\")\n\tif (/\\.{3}$/.test(command)) return true\n\treturn false\n}\n\n/** Extract a display-friendly tool name from a lint-staged command */\nexport function extractToolName(command: string): string | null {\n\t// Step 1: Unwrap sh -c '...' wrapper\n\tconst unwrapped = unwrapShC(command)\n\tif (unwrapped !== null) command = unwrapped\n\n\t// Step 2: Find the meaningful command in a && chain (skip cd segments)\n\tcommand = findMeaningfulCommand(command)\n\n\treturn parseToolFromTokens(command.split(/\\s+/))\n}\n\n/** Map common script names to their underlying tool */\nconst SCRIPT_MAP: Record<string, string> = {\n\ttypecheck: \"tsc\",\n\tlint: \"eslint\",\n\tformat: \"prettier\",\n}\n\n/** Package managers that use [run|exec] <script|tool> pattern */\nconst PKG_MANAGERS = [\"npm\", \"yarn\", \"pnpm\", \"bun\"]\n\n/** Parse tool name from a tokenized command */\nfunction parseToolFromTokens(tokens: string[]): string | null {\n\tconst first = tokens[0]\n\n\t// Safety: don't return the shell itself as a tool name\n\tif (first === \"sh\" || first === \"bash\" || first === \"zsh\") return null\n\n\t// npm/yarn/pnpm/bun [run|exec] <script/tool>\n\tif (PKG_MANAGERS.includes(first)) {\n\t\treturn parsePackageManagerTool(tokens)\n\t}\n\n\t// npx <tool>\n\tif (first === \"npx\") return tokens[1] ?? null\n\n\t// uv run <tool> / uv tool run <tool>\n\tif (first === \"uv\") return parseUvTool(tokens)\n\n\t// Direct tool invocation (biome, eslint, tsc, vitest, jest, prettier)\n\treturn first\n}\n\n/** Extract tool name from npm/yarn/pnpm/bun commands */\nfunction parsePackageManagerTool(tokens: string[]): string | null {\n\tconst sub = tokens[1]\n\t// pnpm exec <tool>\n\tif (sub === \"exec\") return tokens[2] ?? null\n\t// npm/yarn/pnpm [run] <script>\n\tconst scriptIdx = sub === \"run\" ? 2 : 1\n\tconst script = tokens[scriptIdx]\n\tif (!script) return null\n\treturn SCRIPT_MAP[script] ?? script\n}\n\n/** Extract tool name from uv commands */\nfunction parseUvTool(tokens: string[]): string | null {\n\tif (tokens[1] === \"run\") return tokens[2] ?? null\n\tif (tokens[1] === \"tool\" && tokens[2] === \"run\") return tokens[3] ?? null\n\treturn null\n}\n\n/** Unwrap sh -c 'command' or sh -c \"command\" wrappers */\nfunction unwrapShC(command: string): string | null {\n\t// sh/bash -c 'body' or sh/bash -c \"body\"\n\tconst quoted = command.match(/^(?:sh|bash|zsh)\\s+-c\\s+(['\"])([\\s\\S]*)\\1$/)\n\tif (quoted) return quoted[2]\n\t// sh/bash -c body (no quotes, single word — rare)\n\tconst bare = command.match(/^(?:sh|bash|zsh)\\s+-c\\s+(\\S+)$/)\n\tif (bare) return bare[1]\n\treturn null\n}\n\n/** Find the meaningful command in a && chain, skipping cd segments */\nfunction findMeaningfulCommand(command: string): string {\n\tconst segments = command\n\t\t.split(/\\s*&&\\s*/)\n\t\t.map((s) => s.trim())\n\t\t.filter(Boolean)\n\tfor (const seg of segments) {\n\t\tif (/^cd\\s/.test(seg)) continue\n\t\treturn seg\n\t}\n\treturn segments[segments.length - 1] || command\n}\n","import { readFileSync } from \"node:fs\"\nimport { access, constants } from \"node:fs/promises\"\nimport { extname, join } from \"node:path\"\nimport { execa } from \"execa\"\nimport picomatch from \"picomatch\"\nimport { debug } from \"../utils/debug.js\"\nimport { extractToolName } from \"./hooks.js\"\n\n/** Config file names, checked in priority order (matches lint-staged naming conventions) */\nconst CONFIG_FILES = [\n\t\".cmintrc\",\n\t\".cmintrc.json\",\n\t\".cmintrc.mjs\",\n\t\".cmintrc.mts\",\n\t\".cmintrc.js\",\n\t\".cmintrc.ts\",\n\t\".cmintrc.cjs\",\n\t\".cmintrc.cts\",\n\t\"cmint.config.mjs\",\n\t\"cmint.config.mts\",\n\t\"cmint.config.js\",\n\t\"cmint.config.ts\",\n\t\"cmint.config.cjs\",\n\t\"cmint.config.cts\",\n] as const\n\n/** Config shape from .cmintrc — glob keys map to command strings, string arrays, or functions */\nexport interface CheckConfig {\n\t[glob: string]: string | string[] | ((filenames: string[]) => string | string[])\n}\n\n/** Result of a single check command execution */\nexport interface CheckResult {\n\tok: boolean\n\ttool: string\n\tcommand: string\n\tstdout: string\n\tstderr: string\n\tfiles: string[]\n}\n\n/** Aggregate result from running all checks */\nexport interface CheckResults {\n\tok: boolean\n\tresults: CheckResult[]\n}\n\n/**\n * Detect whether the repo has a cmint config file.\n * Returns the config file path, or null if none found.\n */\nexport async function detectConfig(repoRoot: string): Promise<string | null> {\n\tdebug(\"detectConfig: checking for config in %s\", repoRoot)\n\tfor (const name of CONFIG_FILES) {\n\t\ttry {\n\t\t\tawait access(join(repoRoot, name), constants.R_OK)\n\t\t\tdebug(\"detectConfig: found %s\", name)\n\t\t\treturn join(repoRoot, name)\n\t\t} catch {\n\t\t\t// try next config file name\n\t\t}\n\t}\n\tdebug(\"detectConfig: no config file found\")\n\treturn null\n}\n\n/**\n * Load and validate the cmint config from a repo root.\n * Throws if the loaded value is missing or not a non-null object.\n */\nexport async function loadConfig(repoRoot: string): Promise<CheckConfig> {\n\tconst configPath = await detectConfig(repoRoot)\n\tif (!configPath) throw new Error(\"No cmint config file found\")\n\n\tdebug(\"loadConfig: loading %s\", configPath)\n\tconst ext = extname(configPath)\n\tconst isJSON = ext === \".json\"\n\tconst isTS = ext === \".ts\" || ext === \".mts\" || ext === \".cts\"\n\tconst isCJS = ext === \".cjs\"\n\tconst needsJiti = isTS || isCJS\n\n\tlet config: unknown\n\n\tif (isJSON) {\n\t\tconst raw = readFileSync(configPath, \"utf-8\")\n\t\tconfig = JSON.parse(raw)\n\t} else if (needsJiti) {\n\t\tconst { createJiti } = await import(\"jiti\")\n\t\tconst jiti = createJiti(import.meta.url, {})\n\t\tconst mod = await jiti.import(configPath)\n\t\tconfig = (mod as { default?: unknown }).default ?? mod\n\t} else {\n\t\t// .js, .mjs, or no extension\n\t\tconst imported = (await import(configPath)) as { default?: unknown }\n\t\tconfig = imported.default\n\t}\n\n\tif (!config || typeof config !== \"object\" || Array.isArray(config)) {\n\t\tthrow new Error(\"cmint config must export a non-null object with glob\\u2192command mappings\")\n\t}\n\tdebug(\n\t\t\"loadConfig: loaded %d glob patterns\",\n\t\tObject.keys(config as Record<string, unknown>).length,\n\t)\n\treturn config as CheckConfig\n}\n\n/**\n * Run a shell command and capture its output.\n * Returns a CheckResult with ok=true on success (exit 0), ok=false on failure.\n * Handles ENOENT (command not found) and timeout errors gracefully.\n */\nexport async function runCommand(\n\tcommand: string,\n\ttimeout: number,\n\trepoRoot?: string,\n): Promise<CheckResult> {\n\tdebug(\"runCommand: %s (timeout: %dms)\", command, timeout)\n\tconst tool = extractToolName(command) ?? command.split(\" \")[0]\n\n\ttry {\n\t\tconst result = await execa(command, {\n\t\t\tshell: true,\n\t\t\treject: false,\n\t\t\ttimeout,\n\t\t\tall: true,\n\t\t\tpreferLocal: true,\n\t\t\t...(repoRoot ? { localDir: repoRoot } : {}),\n\t\t})\n\t\tconst ok = !result.failed\n\t\tdebug(\"runCommand: %s \\u2014 ok=%s\", tool, ok)\n\t\treturn {\n\t\t\tok,\n\t\t\ttool: tool,\n\t\t\tcommand,\n\t\t\tstdout: result.stdout ?? \"\",\n\t\t\tstderr: result.stderr ?? \"\",\n\t\t\tfiles: [],\n\t\t}\n\t} catch (err) {\n\t\tconst msg = err instanceof Error ? err.message : String(err)\n\t\tconst isTimedOut = msg.toLowerCase().includes(\"timed out\")\n\t\tconst isNotFound =\n\t\t\tmsg.toLowerCase().includes(\"enoent\") || msg.toLowerCase().includes(\"not found\")\n\n\t\tdebug(\"runCommand: %s \\u2014 error: %s\", tool, msg)\n\t\treturn {\n\t\t\tok: false,\n\t\t\ttool: tool,\n\t\t\tcommand,\n\t\t\tstdout: \"\",\n\t\t\tstderr: isTimedOut\n\t\t\t\t? `Check timed out after ${timeout}ms`\n\t\t\t\t: isNotFound\n\t\t\t\t\t? `Command not found: ${tool}`\n\t\t\t\t\t: msg,\n\t\t\tfiles: [],\n\t\t}\n\t}\n}\n\n/**\n * Filter a list of file paths by a picomatch glob pattern.\n * When the pattern contains no `/`, files are matched at any depth (matchBase).\n * Dotfiles are included (dot: true).\n */\nexport function matchFiles(pattern: string, files: string[]): string[] {\n\tif (!pattern) return []\n\tconst matchBase = !pattern.includes(\"/\")\n\tconst isMatch = picomatch(pattern, {\n\t\tdot: true,\n\t\tposixSlashes: true,\n\t\tstrictBrackets: true,\n\t})\n\treturn files.filter((f) => {\n\t\tconst parts = f.split(\"/\")\n\t\tconst target = matchBase ? parts[parts.length - 1] : f\n\t\treturn isMatch(target)\n\t})\n}\n\n/**\n * Build a shell command string from a base command and a list of file paths.\n * File paths containing spaces are wrapped in double quotes.\n * If no files are provided, the base command is returned as-is.\n */\nexport function buildCommand(command: string, files: string[]): string {\n\tif (files.length === 0) return command\n\tconst quotedFiles = files.map((f) => (f.includes(\" \") ? `\"${f}\"` : f))\n\treturn `${command} ${quotedFiles.join(\" \")}`\n}\n\n/**\n * A resolved command string paired with whether it originated from a function.\n * Function-originated commands are run as-is; string commands get matched files appended.\n */\ninterface ResolvedCommand {\n\tcommand: string\n\tfromFunction: boolean\n}\n\n/**\n * Call a function command with matched files and normalize the result to ResolvedCommand[].\n */\nfunction resolveFunction(\n\tfn: (files: string[]) => string | string[],\n\tmatchedFiles: string[],\n): ResolvedCommand[] {\n\tconst resolved = fn(matchedFiles)\n\tconst items = Array.isArray(resolved) ? resolved : [resolved]\n\treturn items.map((command) => ({ command, fromFunction: true }))\n}\n\n/**\n * Resolve config commands for a glob entry into an array of resolved commands.\n * Function commands are called with matched filenames; string commands are kept as-is.\n * Each resolved entry tracks whether it came from a function (for file-append behavior).\n */\nfunction resolveCommands(\n\tcommands: string | string[] | ((filenames: string[]) => string | string[]),\n\tmatchedFiles: string[],\n): ResolvedCommand[] {\n\tif (typeof commands === \"function\") {\n\t\treturn resolveFunction(commands as (files: string[]) => string | string[], matchedFiles)\n\t}\n\tif (Array.isArray(commands)) {\n\t\tconst result: ResolvedCommand[] = []\n\t\tfor (const cmd of commands) {\n\t\t\tif (typeof cmd === \"function\") {\n\t\t\t\tresult.push(...resolveFunction(cmd, matchedFiles))\n\t\t\t} else {\n\t\t\t\tresult.push({ command: cmd, fromFunction: false })\n\t\t\t}\n\t\t}\n\t\treturn result\n\t}\n\treturn [{ command: commands as string, fromFunction: false }]\n}\n\n/**\n * Run resolved commands for a single glob entry, appending results.\n * Function-originated commands run as-is; string commands get matched files appended.\n * Returns false if any command fails (for fail-fast signaling).\n */\nasync function runCommandsForGlob(\n\tcmds: ResolvedCommand[],\n\tmatchedFiles: string[],\n\ttimeout: number,\n\tresults: CheckResult[],\n\trepoRoot: string,\n): Promise<boolean> {\n\tfor (const { command, fromFunction } of cmds) {\n\t\tconst fullCommand = fromFunction ? command : buildCommand(command, matchedFiles)\n\t\tdebug(\"runCommandsForGlob: running '%s'\", fullCommand)\n\t\tconst result = await runCommand(fullCommand, timeout, repoRoot)\n\t\tresults.push({ ...result, files: matchedFiles })\n\t\tif (!result.ok) {\n\t\t\tdebug(\"runCommandsForGlob: check failed, stopping (fail-fast)\")\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n/**\n * Run all user-defined checks from .cmintrc against staged files.\n * Returns a no-op result when no config exists.\n * Fail-fast: stops on first error.\n */\nexport async function runAllChecks(\n\trepoRoot: string,\n\tstagedFiles: string[],\n\ttimeout: number,\n): Promise<CheckResults> {\n\tdebug(\"runAllChecks: %d staged files, checking for config in %s\", stagedFiles.length, repoRoot)\n\n\tconst configPath = await detectConfig(repoRoot)\n\tif (!configPath) {\n\t\tdebug(\"runAllChecks: no config found, skipping checks\")\n\t\treturn { ok: true, results: [] }\n\t}\n\n\tconst config = await loadConfig(repoRoot)\n\tdebug(\"runAllChecks: loaded config with %d patterns\", Object.keys(config).length)\n\n\tconst results: CheckResult[] = []\n\n\tfor (const [glob, commands] of Object.entries(config)) {\n\t\tconst matchedFiles = matchFiles(glob, stagedFiles)\n\n\t\tif (matchedFiles.length === 0) {\n\t\t\tdebug(\"runAllChecks: no files matched pattern '%s'\", glob)\n\t\t\tcontinue\n\t\t}\n\t\tdebug(\"runAllChecks: pattern '%s' matched %d files\", glob, matchedFiles.length)\n\n\t\tconst cmds = resolveCommands(commands, matchedFiles)\n\t\tconst ok = await runCommandsForGlob(cmds, matchedFiles, timeout, results, repoRoot)\n\t\tif (!ok) return { ok: false, results }\n\t}\n\n\tconst ok = results.every((r) => r.ok)\n\tdebug(\"runAllChecks: complete \\u2014 ok=%s, %d results\", ok, results.length)\n\treturn { ok, results }\n}\n","import { readFile, writeFile } from \"node:fs/promises\"\nimport os from \"node:os\"\nimport { join } from \"node:path\"\nimport ini from \"ini\"\nimport { debug } from \"../utils/debug.js\"\nimport {\n\tformatProviderName,\n\tPROVIDER_CONFIGS,\n\tPROVIDER_ENV_KEYS,\n\ttype ProviderName,\n} from \"./provider.js\"\n\nconst CONFIG_PATH = join(os.homedir(), \".commit-mint\")\n\nexport interface Config {\n\tGROQ_API_KEY?: string\n\tCEREBRAS_API_KEY?: string\n\tMISTRAL_API_KEY?: string\n\tprovider?: string\n\tmodel?: string\n\tmodel_groq?: string\n\tmodel_cerebras?: string\n\tmodel_mistral?: string\n\tlocale?: string\n\t\"max-length\"?: string\n\ttype?: string\n\tproxy?: string\n\ttimeout?: string\n}\n\nconst defaults: Config = {\n\tprovider: \"groq\",\n\tmodel: \"openai/gpt-oss-20b\",\n\tlocale: \"en\",\n\t\"max-length\": \"100\",\n\ttype: \"\",\n\ttimeout: \"10000\",\n}\n\nexport async function readConfig(): Promise<Config> {\n\tdebug(\"readConfig: loading from %s\", CONFIG_PATH)\n\ttry {\n\t\tconst raw = await readFile(CONFIG_PATH, \"utf8\")\n\t\tconst parsed = ini.parse(raw)\n\t\tconst merged = { ...defaults, ...parsed }\n\t\tdebug(\"readConfig: loaded keys: %s\", Object.keys(merged).join(\", \"))\n\t\treturn merged\n\t} catch {\n\t\tdebug(\"readConfig: no config file, using defaults\")\n\t\treturn { ...defaults }\n\t}\n}\n\nexport async function writeConfig(updates: Record<string, string>) {\n\tconst existing = await readConfig()\n\tObject.assign(existing, updates)\n\tawait writeFile(CONFIG_PATH, ini.stringify(existing), \"utf8\")\n}\n\nexport async function getConfigValue(key: string): Promise<string | undefined> {\n\tconst config = await readConfig()\n\treturn config[key as keyof Config]\n}\n\nexport async function setConfigValue(key: string, value: string) {\n\tawait writeConfig({ [key]: value })\n}\n\nexport async function getApiKey(): Promise<string> {\n\tconst envKey = process.env.GROQ_API_KEY\n\tif (envKey) {\n\t\tdebug(\"getApiKey: found in env\")\n\t\treturn envKey\n\t}\n\n\tconst config = await readConfig()\n\tif (config.GROQ_API_KEY) {\n\t\tdebug(\"getApiKey: found in config\")\n\t\treturn config.GROQ_API_KEY\n\t}\n\n\tdebug(\"getApiKey: not found\")\n\tthrow new Error(\n\t\t\"Please set your Groq API key via `cmint config set GROQ_API_KEY=<your token>`. \" +\n\t\t\t\"Multi-provider: set `cmint config set provider=cerebras` for Cerebras, or `cmint config set provider=mistral` for Mistral.\",\n\t)\n}\n\nexport async function getProviderApiKey(provider: string): Promise<string> {\n\tconst envVar = PROVIDER_ENV_KEYS[provider as ProviderName]\n\tif (envVar) {\n\t\tconst envValue = process.env[envVar]\n\t\tif (envValue) {\n\t\t\tdebug(\"getProviderApiKey(%s): found in env\", provider)\n\t\t\treturn envValue\n\t\t}\n\t}\n\n\tconst config = await readConfig()\n\tconst configKey = PROVIDER_ENV_KEYS[provider as ProviderName]\n\tif (configKey && (config as Record<string, string | undefined>)[configKey]) {\n\t\tdebug(\"getProviderApiKey(%s): found in config\", provider)\n\t\tconst val = (config as Record<string, string | undefined>)[configKey]\n\t\treturn val as string\n\t}\n\n\tdebug(\"getProviderApiKey(%s): not found\", provider)\n\tthrow new Error(\n\t\t`Please set your ${formatProviderName(provider)} API key via \\`cmint config set ${envVar}=<your token>\\``,\n\t)\n}\n\n/** Check if a model name is the default for a provider OTHER than the given one. */\nfunction isOtherProviderDefault(model: string, provider: string): boolean {\n\tfor (const [name, config] of Object.entries(PROVIDER_CONFIGS)) {\n\t\tif (name !== provider && config.defaultModel === model) return true\n\t}\n\treturn false\n}\n\nexport function getModelForProvider(\n\tconfig: Config,\n\tprovider: string,\n\tdefaultModel: string,\n): string {\n\tconst modelKey = `model_${provider}` as keyof Config\n\tconst providerModel = config[modelKey]\n\tif (providerModel) return providerModel\n\n\tconst globalModel = config.model\n\t// Skip global model if it's another provider's default (cross-provider leak)\n\tif (globalModel && !isOtherProviderDefault(globalModel, provider)) return globalModel\n\n\treturn defaultModel\n}\n","import type { SpinnerResult } from \"@clack/prompts\"\nimport { extractToolName, isLintStagedMeta } from \"./hooks.js\"\n\nexport interface HookStep {\n\tstatus: \"started\" | \"completed\" | \"failed\"\n\tcommand: string\n\ttool: string\n}\n\nexport type ProgressHandler = (step: HookStep) => void\n\nconst ansiRe = new RegExp(`${String.fromCharCode(0x1b)}\\\\[[0-9;]*m`, \"g\")\n\nexport function createStderrParser(): (chunk: string) => HookStep[] {\n\tlet buffer = \"\"\n\treturn (chunk: string): HookStep[] => {\n\t\tbuffer += chunk\n\t\tconst steps: HookStep[] = []\n\t\tconst lines = buffer.split(\"\\n\")\n\t\tbuffer = lines.pop() ?? \"\"\n\t\tfor (const line of lines) {\n\t\t\t// Strip ANSI escape codes before matching (lint-staged wraps markers in color codes)\n\t\t\tconst clean = line.replace(ansiRe, \"\")\n\t\t\tconst match = clean.match(/\\[(STARTED|COMPLETED|FAILED)\\]\\s+(.+)/)\n\t\t\tif (!match) continue\n\t\t\tconst status = match[1].toLowerCase() as HookStep[\"status\"]\n\t\t\tconst command = match[2].trim()\n\t\t\tif (isLintStagedMeta(command)) continue\n\t\t\tconst tool = extractToolName(command) ?? command\n\t\t\tsteps.push({ status, command, tool })\n\t\t}\n\t\treturn steps\n\t}\n}\n\nexport function createProgressHandler(s: SpinnerResult): ProgressHandler {\n\treturn (step: HookStep) => {\n\t\tif (step.status === \"started\") {\n\t\t\ts.message(step.command)\n\t\t} else if (step.status === \"failed\") {\n\t\t\ts.message(step.command)\n\t\t}\n\t\t// completed: no action — post-commit parseToolChecks summary handles display\n\t}\n}\n","import type { ExecaError } from \"execa\"\nimport { execa } from \"execa\"\nimport { debug } from \"../utils/debug.js\"\nimport { createStderrParser, type ProgressHandler } from \"./hook-progress.js\"\n\nexport class KnownError extends Error {}\n\nexport async function assertGitRepo() {\n\tdebug(\"assertGitRepo\")\n\tconst { failed } = await execa(\"git\", [\"rev-parse\", \"--show-toplevel\"], {\n\t\treject: false,\n\t})\n\tif (failed) {\n\t\tthrow new KnownError(\"The current directory must be a Git repository!\")\n\t}\n}\n\nexport async function getRepoRoot() {\n\tconst { stdout } = await execa(\"git\", [\"rev-parse\", \"--show-toplevel\"])\n\tdebug(\"getRepoRoot:\", stdout.trim())\n\treturn stdout.trim()\n}\n\nexport interface StagedDiffResult {\n\tfiles: string[]\n\tdiff: string\n}\n\nexport interface ExcludedFilesResult {\n\texcludedFiles: string[]\n}\n\nexport type DiffResult = StagedDiffResult | ExcludedFilesResult | null\n\nexport interface ChangedFile {\n\tpath: string\n\tstatus: string\n\tstaged: boolean\n}\n\nconst DEFAULT_EXCLUDES = [\n\t\"package-lock.json\",\n\t\"node_modules/**\",\n\t\"dist/**\",\n\t\"build/**\",\n\t\".next/**\",\n\t\"coverage/**\",\n\t\"*.log\",\n\t\"*.min.js\",\n\t\"*.min.css\",\n\t\"*.lock\",\n\t\".DS_Store\",\n]\n\nexport function getDefaultExcludes(): string[] {\n\treturn [...DEFAULT_EXCLUDES]\n}\n\nexport async function getStagedDiff(exclude?: string[]): Promise<DiffResult> {\n\tconst excludeArgs = (exclude ?? []).map((e) => `:(exclude)${e}`)\n\tconst defaultExcludeArgs = DEFAULT_EXCLUDES.map((e) => `:(exclude)${e}`)\n\n\t// Check all staged files without excludes to detect \"all excluded\" case\n\tconst { stdout: allFiles } = await execa(\"git\", [\"diff\", \"--cached\", \"--name-only\"])\n\tif (!allFiles) {\n\t\tdebug(\"getStagedDiff: no staged files\")\n\t\treturn null\n\t}\n\n\t// Check staged files with excludes applied\n\tconst { stdout: files } = await execa(\"git\", [\n\t\t\"diff\",\n\t\t\"--cached\",\n\t\t\"--name-only\",\n\t\t...defaultExcludeArgs,\n\t\t...excludeArgs,\n\t])\n\n\tif (!files) {\n\t\t// All staged files were excluded\n\t\tconst excludedFiles = allFiles.split(\"\\n\").filter(Boolean)\n\t\tdebug(\"getStagedDiff: all files excluded:\", excludedFiles)\n\t\treturn { excludedFiles }\n\t}\n\n\tconst { stdout: diff } = await execa(\"git\", [\n\t\t\"diff\",\n\t\t\"--cached\",\n\t\t\"--diff-algorithm=minimal\",\n\t\t...defaultExcludeArgs,\n\t\t...excludeArgs,\n\t])\n\n\tdebug(\"getStagedDiff:\", files.split(\"\\n\").filter(Boolean).length, \"files,\", diff.length, \"chars\")\n\treturn { files: files.split(\"\\n\").filter(Boolean), diff }\n}\n\nexport async function stageAll() {\n\tdebug(\"stageAll: git add -A\")\n\tawait execa(\"git\", [\"add\", \"-A\"])\n}\n\nexport async function resetStaging() {\n\t// On a repo with no commits, `git reset HEAD` fails because HEAD doesn't\n\t// resolve yet (exit 128, \"ambiguous argument 'HEAD'\"). Fall back to clearing\n\t// the index without referencing HEAD so the first commit can proceed.\n\ttry {\n\t\tdebug(\"resetStaging: git reset HEAD\")\n\t\tawait execa(\"git\", [\"reset\", \"HEAD\"])\n\t} catch {\n\t\tdebug(\"resetStaging: HEAD missing, falling back to git rm --cached\")\n\t\tawait execa(\"git\", [\"rm\", \"-r\", \"--cached\", \"--quiet\", \".\"])\n\t}\n}\n\nexport async function getHead(): Promise<string | null> {\n\t// Returns null on a repo with no commits — `git rev-parse HEAD` exits 128\n\t// on a fresh repo. Callers treat \"headBefore === headAfter === null\" as\n\t// \"commit failed\" and \"null → SHA\" as \"first commit succeeded.\"\n\ttry {\n\t\tconst { stdout } = await execa(\"git\", [\"rev-parse\", \"HEAD\"])\n\t\treturn stdout.trim()\n\t} catch {\n\t\tdebug(\"getHead: HEAD does not exist (fresh repo)\")\n\t\treturn null\n\t}\n}\n\nexport async function getStatusShort() {\n\tconst { stdout } = await execa(\"git\", [\"status\", \"--short\"])\n\treturn stdout.trim()\n}\n\nexport async function getChangedFiles(): Promise<ChangedFile[]> {\n\tconst { stdout } = await execa(\"git\", [\"status\", \"--short\", \"--untracked-files=all\"])\n\tif (!stdout.trim()) return []\n\tconst files = stdout\n\t\t.split(\"\\n\")\n\t\t.filter(Boolean)\n\t\t.map((line) => {\n\t\t\tconst indexStatus = line[0]\n\t\t\treturn {\n\t\t\t\tstatus: line.slice(0, 2).trim(),\n\t\t\t\tpath: line.slice(3),\n\t\t\t\tstaged: indexStatus !== \" \" && indexStatus !== \"?\",\n\t\t\t}\n\t\t})\n\tdebug(\"getChangedFiles:\", files.length, \"files\")\n\treturn files\n}\n\nexport async function stageFiles(paths: string[]): Promise<void> {\n\tdebug(\"stageFiles:\", paths)\n\tawait execa(\"git\", [\"add\", ...paths])\n}\n\nexport interface CommitResult {\n\tok: boolean\n\terror?: string\n\t/** Collected stderr from hooks/lint-staged — set on both success and failure */\n\tstderr?: string\n}\n\nexport async function attemptCommit(\n\tmessage: string,\n\textraArgs: string[] = [],\n\tonProgress?: ProgressHandler,\n): Promise<CommitResult> {\n\tdebug(\"attemptCommit:\", message, extraArgs.length ? extraArgs : \"(no extra args)\")\n\ttry {\n\t\tconst subprocess = execa(\"git\", [\"commit\", \"-m\", message, ...extraArgs])\n\n\t\t// Collect hook output (lint-staged, biome, etc.) for post-commit display\n\t\tconst stderrChunks: string[] = []\n\t\tconst parser = onProgress ? createStderrParser() : null\n\t\tsubprocess.stderr?.on(\"data\", (chunk: Buffer) => {\n\t\t\tconst text = chunk.toString()\n\t\t\tstderrChunks.push(text)\n\t\t\tif (parser && onProgress) {\n\t\t\t\tfor (const step of parser(text)) {\n\t\t\t\t\tonProgress(step)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\n\t\tawait subprocess\n\t\tdebug(\"attemptCommit: success\")\n\t\treturn { ok: true, stderr: stderrChunks.join(\"\") }\n\t} catch (error) {\n\t\tconst e = error as ExecaError\n\t\tdebug(\"attemptCommit: failed —\", e.message?.slice(0, 200))\n\t\treturn {\n\t\t\tok: false,\n\t\t\terror: e.message,\n\t\t\tstderr: typeof e.stderr === \"string\" ? e.stderr : \"\",\n\t\t}\n\t}\n}\n\nexport async function attemptCommitNoVerify(\n\tmessage: string,\n\tonProgress?: ProgressHandler,\n): Promise<CommitResult> {\n\tdebug(\"attemptCommitNoVerify:\", message)\n\treturn attemptCommit(message, [\"--no-verify\"], onProgress)\n}\n","export interface CommitGroup {\n\tname: string\n\tdescription: string\n\tfiles: string[]\n}\n\ninterface ScanState {\n\tobjects: unknown[]\n\tdepth: number\n\tstart: number\n}\n\n/** Coerce a parsed value into a CommitGroup, or null if it doesn't match the shape. */\nfunction coerceGroup(item: unknown): CommitGroup | null {\n\tif (\n\t\ttypeof item === \"object\" &&\n\t\titem !== null &&\n\t\t\"name\" in item &&\n\t\t\"description\" in item &&\n\t\t\"files\" in item &&\n\t\tArray.isArray((item as Record<string, unknown>).files)\n\t) {\n\t\tconst obj = item as Record<string, unknown>\n\t\treturn {\n\t\t\tname: String(obj.name),\n\t\t\tdescription: String(obj.description),\n\t\t\tfiles: (obj.files as unknown[]).filter((f) => typeof f === \"string\") as string[],\n\t\t}\n\t}\n\treturn null\n}\n\n/** Return the index of the closing quote of a string starting at text[start] === '\"'. */\nfunction skipString(text: string, start: number): number {\n\tlet i = start + 1\n\twhile (i < text.length) {\n\t\tconst ch = text[i]\n\t\tif (ch === \"\\\\\") {\n\t\t\ti += 2\n\t\t\tcontinue\n\t\t}\n\t\tif (ch === '\"') return i\n\t\ti++\n\t}\n\treturn i\n}\n\nfunction openBrace(state: ScanState, index: number): void {\n\tif (state.depth === 0) state.start = index\n\tstate.depth++\n}\n\nfunction pushParsedObject(objects: unknown[], candidate: string): void {\n\ttry {\n\t\tobjects.push(JSON.parse(candidate))\n\t} catch {\n\t\t// Not valid JSON — skip this candidate.\n\t}\n}\n\nfunction closeBrace(state: ScanState, text: string, index: number): void {\n\tif (state.depth === 0) return\n\tstate.depth--\n\tif (state.depth === 0 && state.start !== -1) {\n\t\tpushParsedObject(state.objects, text.slice(state.start, index + 1))\n\t\tstate.start = -1\n\t}\n}\n\n/**\n * Scan for top-level `{...}` objects, respecting string literals and escapes.\n * Used to recover groups when the model emits a single object or concatenated\n * objects instead of the requested JSON array.\n */\nfunction extractTopLevelObjects(text: string): unknown[] {\n\tconst state: ScanState = { objects: [], depth: 0, start: -1 }\n\tfor (let i = 0; i < text.length; i++) {\n\t\tconst ch = text[i]\n\t\t// Skip string literals so braces/quotes inside them don't affect depth.\n\t\tif (ch === '\"') {\n\t\t\ti = skipString(text, i)\n\t\t\tcontinue\n\t\t}\n\t\tif (ch === \"{\") {\n\t\t\topenBrace(state, i)\n\t\t\tcontinue\n\t\t}\n\t\tif (ch === \"}\") {\n\t\t\tcloseBrace(state, text, i)\n\t\t}\n\t}\n\treturn state.objects\n}\n\nexport function parseGroupingResponse(content: string): CommitGroup[] {\n\t// Strip think tags from reasoning models\n\tlet cleaned = content.replace(/<think[\\s\\S]*?<\\/think>/gi, \"\").trim()\n\t// Strip markdown code fences\n\tcleaned = cleaned\n\t\t.replace(/^```(?:json)?\\s*/i, \"\")\n\t\t.replace(/\\s*```$/i, \"\")\n\t\t.trim()\n\n\t// Path 1: extract the outermost JSON array — handles text before/after the array,\n\t// markdown fences, and trailing explanation prose. A truly empty array (\"[]\")\n\t// returns [] — the caller treats that as a low-quality result that triggers a\n\t// retry. If the array had items but none coerced to groups, fall through to\n\t// Path 2 so the object scan can attempt recovery.\n\tconst start = cleaned.indexOf(\"[\")\n\tconst end = cleaned.lastIndexOf(\"]\")\n\tif (start !== -1 && end !== -1 && end > start) {\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(cleaned.slice(start, end + 1)) as unknown\n\t\t\tif (Array.isArray(parsed)) {\n\t\t\t\tif (parsed.length === 0) return []\n\t\t\t\tconst groups = parsed.map(coerceGroup).filter((g): g is CommitGroup => g !== null)\n\t\t\t\tif (groups.length > 0) return groups\n\t\t\t}\n\t\t} catch {\n\t\t\t// Array span didn't parse (e.g. concatenated objects confuse the [ ] slice).\n\t\t\t// Fall through to the object scan.\n\t\t}\n\t}\n\n\t// Path 2: model emitted a single object or concatenated objects instead of an\n\t// array. Scan for top-level {...} objects and collect those that look like groups.\n\tconst groups = extractTopLevelObjects(cleaned)\n\t\t.map(coerceGroup)\n\t\t.filter((g): g is CommitGroup => g !== null)\n\tif (groups.length > 0) {\n\t\treturn groups\n\t}\n\n\tthrow new Error(\"AI response did not contain a JSON array\")\n}\n","import type { CommitGroup } from \"./grouping-parser.js\"\n\n/**\n * # Test/source reunification\n *\n * AI grouping prompts ask the model to keep a source file and its tests in the\n * same commit group, but the model frequently ignores that instruction (it\n * split `git.ts` from `git.test.ts` in the bug report that motivated this\n * module). The functions here provide a deterministic post-processing pass\n * that moves misplaced test files back into the group already containing\n * their source counterpart, regardless of what the model decided.\n *\n * Supported layouts (in priority order):\n * 1. Co-located: `src/foo.ts` ↔ `src/foo.test.ts`\n * 2. `__tests__/` mirror: `src/foo.ts` ↔ `src/__tests__/foo.test.ts`\n * 3. `tests/` or `test/` mirror: `src/foo.ts` ↔ `tests/foo.test.ts`\n *\n * Reunification runs inside `validateGroups()` (see `grouping.ts`) after\n * hallucinated-path filtering so only real files participate.\n */\n\n/** Suffixes that mark a file as a test companion of a same-name source. */\nconst TEST_SUFFIXES = [\".test\", \".spec\"] as const\n\n/**\n * Extensions tried when looking for a source counterpart for a test file. The\n * test file's own extension is usually the right one, but we also try common\n * alternates (a `.test.tsx` may back a `.tsx` or a `.ts`).\n */\nconst SOURCE_EXTENSIONS = [\".ts\", \".tsx\", \".js\", \".jsx\", \".mjs\", \".cjs\", \".mts\", \".cts\"] as const\n\n/** Matches a test file by extension regardless of which suffix it uses. */\nconst TEST_FILE_PATTERN = /\\.(?:test|spec)\\.(?:ts|tsx|js|jsx|mjs|cjs|mts|cts)$/\n\n/** Directory prefixes/segments that mirror source layout for non-co-located tests. */\nconst TEST_DIR_PREFIXES = [\"tests/\", \"test/\"] as const\n\n/** Marker segment for co-located `__tests__/` directories. */\nconst TESTS_DIR_SEGMENT = \"/__tests__/\"\n\nfunction stripTestSuffix(filename: string): string | null {\n\tfor (const suffix of TEST_SUFFIXES) {\n\t\tconst marker = `${suffix}.`\n\t\tconst idx = filename.lastIndexOf(marker)\n\t\tif (idx > 0) return filename.slice(0, idx)\n\t}\n\treturn null\n}\n\nfunction withEachExtension(base: string): string[] {\n\treturn SOURCE_EXTENSIONS.map((ext) => `${base}${ext}`)\n}\n\n/** Co-located: `dir/foo.test.ts` → `dir/foo.{ts,tsx,...}` */\nfunction colocatedCandidates(testPath: string): string[] {\n\tconst base = stripTestSuffix(testPath)\n\treturn base === null ? [] : withEachExtension(base)\n}\n\n/** `__tests__` mirror: `src/__tests__/foo.test.ts` → `src/foo.{ts,tsx,...}` */\nfunction testsDirCandidates(testPath: string): string[] {\n\tconst segmentIdx = testPath.indexOf(TESTS_DIR_SEGMENT)\n\tif (segmentIdx < 0) return []\n\tconst parentDir = testPath.slice(0, segmentIdx)\n\tconst filename = testPath.slice(segmentIdx + TESTS_DIR_SEGMENT.length)\n\tconst base = stripTestSuffix(filename)\n\tif (base === null) return []\n\treturn withEachExtension(`${parentDir}/${base}`)\n}\n\n/** `tests/` or `test/` mirror: `tests/services/foo.test.ts` → `src/services/foo.{ts,tsx,...}` */\nfunction prefixedDirCandidates(testPath: string): string[] {\n\tfor (const prefix of TEST_DIR_PREFIXES) {\n\t\tif (!testPath.startsWith(prefix)) continue\n\t\tconst rest = testPath.slice(prefix.length)\n\t\tconst base = stripTestSuffix(rest)\n\t\tif (base === null) return []\n\t\treturn withEachExtension(`src/${base}`)\n\t}\n\treturn []\n}\n\n/**\n * Compute candidate source paths for a test file in priority order: co-located\n * first, then `__tests__/` mirror, then `tests/`/`test/` mirror. Each mirror\n * emits one entry per `SOURCE_EXTENSIONS` candidate so the caller can match\n * against any of them.\n */\nexport function candidateSourcePaths(testPath: string): string[] {\n\treturn [\n\t\t...colocatedCandidates(testPath),\n\t\t...testsDirCandidates(testPath),\n\t\t...prefixedDirCandidates(testPath),\n\t]\n}\n\n/**\n * Resolve the unambiguous target group for a single test file, or `null` when\n * no source counterpart exists / matches more than one group (ambiguous). A\n * test whose candidates span multiple groups (e.g. `foo.ts` and `foo.tsx` in\n * different groups) is intentionally left alone rather than guessed.\n */\nfunction findTargetGroup(\n\ttestFile: string,\n\tcurrentGi: number,\n\tfileToGroup: Map<string, number>,\n): number | null {\n\tconst targetGroups = new Set<number>()\n\tfor (const candidate of candidateSourcePaths(testFile)) {\n\t\tconst targetGi = fileToGroup.get(candidate)\n\t\tif (targetGi !== undefined && targetGi !== currentGi) {\n\t\t\ttargetGroups.add(targetGi)\n\t\t}\n\t}\n\treturn targetGroups.size === 1 ? [...targetGroups][0] : null\n}\n\n/**\n * Find the unambiguous target group for each misplaced test file.\n *\n * Returns a map of `testFile → targetGroupIndex`. A test is only moved when\n * its candidate source matches exactly one other group; ambiguous matches are\n * skipped (see {@link findTargetGroup}).\n */\nfunction findMoves(groups: CommitGroup[], fileToGroup: Map<string, number>): Map<string, number> {\n\tconst moves = new Map<string, number>()\n\n\tfor (let gi = 0; gi < groups.length; gi++) {\n\t\tfor (const file of groups[gi].files) {\n\t\t\tif (moves.has(file) || !TEST_FILE_PATTERN.test(file)) continue\n\t\t\tconst target = findTargetGroup(file, gi, fileToGroup)\n\t\t\tif (target !== null) moves.set(file, target)\n\t\t}\n\t}\n\n\treturn moves\n}\n\n/**\n * Apply queued moves to a fresh copy of the groups array. Tests are removed\n * from their original group and appended to the target group. Groups left\n * empty by moves are dropped.\n */\nfunction applyMoves(groups: CommitGroup[], moves: Map<string, number>): CommitGroup[] {\n\tconst result = groups.map((g) => ({ ...g, files: [...g.files] }))\n\tconst movedFiles = new Set(moves.keys())\n\n\tconst additionsByGroup = new Map<number, string[]>()\n\tfor (const [file, toGroup] of moves) {\n\t\tconst bucket = additionsByGroup.get(toGroup) ?? []\n\t\tbucket.push(file)\n\t\tadditionsByGroup.set(toGroup, bucket)\n\t}\n\n\tfor (let gi = 0; gi < result.length; gi++) {\n\t\tif (movedFiles.size > 0) {\n\t\t\tresult[gi].files = result[gi].files.filter((f) => !movedFiles.has(f))\n\t\t}\n\t\tconst additions = additionsByGroup.get(gi)\n\t\tif (!additions) continue\n\t\tconst existing = new Set(result[gi].files)\n\t\tfor (const file of additions) {\n\t\t\t// Additions come from other groups so they should always be new; the\n\t\t\t// de-dupe guard exists to keep the invariant explicit.\n\t\t\tif (!existing.has(file)) result[gi].files.push(file)\n\t\t}\n\t}\n\n\treturn result.filter((g) => g.files.length > 0)\n}\n\n/**\n * Move test files (`.test.*` / `.spec.*`) into the group that already contains\n * their source counterpart. Returns the same array reference if no moves were\n * needed; otherwise returns a fresh array of new group objects.\n *\n * See module doc for the matching algorithm.\n */\nexport function reuniteTestsWithSources(groups: CommitGroup[]): CommitGroup[] {\n\tif (groups.length === 0) return groups\n\n\tconst fileToGroup = new Map<string, number>()\n\tfor (let gi = 0; gi < groups.length; gi++) {\n\t\tfor (const file of groups[gi].files) fileToGroup.set(file, gi)\n\t}\n\n\tconst moves = findMoves(groups, fileToGroup)\n\tif (moves.size === 0) return groups\n\n\treturn applyMoves(groups, moves)\n}\n","import { debug } from \"../utils/debug.js\"\nimport { mapGroqError } from \"./ai.js\"\nimport type { ChangedFile } from \"./git.js\"\nimport { getDefaultExcludes } from \"./git.js\"\nimport { type CommitGroup, parseGroupingResponse } from \"./grouping-parser.js\"\nimport { reuniteTestsWithSources } from \"./grouping-reunite.js\"\nimport {\n\ttype ChatClient,\n\tcreateProvider,\n\tformatProviderName,\n\ttype ProviderName,\n} from \"./provider.js\"\n\nexport type { CommitGroup } from \"./grouping-parser.js\"\nexport { reuniteTestsWithSources } from \"./grouping-reunite.js\"\n\nexport interface GroupingResult {\n\tgroups: CommitGroup[]\n\texcluded: string[]\n}\n\nfunction matchesExcludePattern(filePath: string, pattern: string): boolean {\n\tif (pattern === filePath) return true\n\tif (pattern.endsWith(\"/**\")) {\n\t\tconst prefix = pattern.slice(0, -3)\n\t\treturn filePath === prefix || filePath.startsWith(`${prefix}/`)\n\t}\n\tif (pattern.startsWith(\"*.\")) {\n\t\tconst suffix = pattern.slice(1)\n\t\treturn filePath.endsWith(suffix)\n\t}\n\treturn false\n}\n\n/** Lockfiles that should be kept when their companion manifest is present */\nconst LOCKFILE_COMPANIONS: Record<string, string> = {\n\t\"package-lock.json\": \"package.json\",\n\t\"pnpm-lock.yaml\": \"package.json\",\n\t\"yarn.lock\": \"package.json\",\n\t\"bun.lock\": \"package.json\",\n\t\"bun.lockb\": \"package.json\",\n}\n\nexport function filterExcludedFiles(files: ChangedFile[]): {\n\tincluded: ChangedFile[]\n\texcluded: string[]\n} {\n\tconst patterns = getDefaultExcludes()\n\tconst included: ChangedFile[] = []\n\tconst excluded: ChangedFile[] = []\n\tconst filePaths = new Set(files.map((f) => f.path))\n\n\tfor (const file of files) {\n\t\tconst isExcluded = patterns.some((pattern) => matchesExcludePattern(file.path, pattern))\n\t\tif (isExcluded) {\n\t\t\texcluded.push(file)\n\t\t} else {\n\t\t\tincluded.push(file)\n\t\t}\n\t}\n\n\t// Promote lockfiles whose companion manifest is present\n\tconst stillExcluded: string[] = []\n\tfor (const file of excluded) {\n\t\tconst companion = LOCKFILE_COMPANIONS[file.path]\n\t\tif (companion && filePaths.has(companion)) {\n\t\t\tincluded.push(file)\n\t\t} else {\n\t\t\tstillExcluded.push(file.path)\n\t\t}\n\t}\n\n\tdebug(\"filterExcludedFiles: %d included, %d excluded\", included.length, stillExcluded.length)\n\treturn { included, excluded: stillExcluded }\n}\n\nfunction statusIndicator(status: string): string {\n\tswitch (status) {\n\t\tcase \"M\":\n\t\t\treturn \"modified\"\n\t\tcase \"A\":\n\t\t\treturn \"added\"\n\t\tcase \"D\":\n\t\t\treturn \"deleted\"\n\t\tcase \"R\":\n\t\t\treturn \"renamed\"\n\t\tcase \"C\":\n\t\t\treturn \"copied\"\n\t\tcase \"?\":\n\t\tcase \"??\":\n\t\t\treturn \"untracked\"\n\t\tdefault:\n\t\t\treturn \"changed\"\n\t}\n}\n\nexport function buildFileSummary(files: ChangedFile[]): string {\n\treturn files.map((f) => `${f.path} (${statusIndicator(f.status)})`).join(\"\\n\")\n}\n\nexport function buildGroupingSystemPrompt(): string {\n\treturn [\n\t\t\"You are analyzing changed files in a git repository. Group them into logical commits based on what changed and why. Each group should be a coherent unit of work.\",\n\t\t\"\",\n\t\t\"Rules:\",\n\t\t\"- ALWAYS keep a test file in the same group as the source file it tests. Examples: `foo.test.ts` stays with `foo.ts`; `__tests__/foo.test.ts` stays with `foo.ts` in the parent directory; `tests/foo.test.ts` stays with `src/foo.ts`. Never put source and its tests in separate groups.\",\n\t\t\"- Group by feature, fix, or concern (e.g., 'Frontend refactor', 'API changes')\",\n\t\t\"- Keep related files together (e.g., a component + its test, a model + its migration)\",\n\t\t\"- Separate documentation changes (*.md files, docs/) from code changes — put docs in their own group\",\n\t\t\"- Do not split a single logical change across multiple groups\",\n\t\t\"- If a file does not clearly belong to any group, include it anyway — do not omit files\",\n\t\t\"\",\n\t\t\"Output format: JSON array of objects with keys 'name', 'description', 'files'.\",\n\t\t\"name: short label (3-5 words)\",\n\t\t\"description: 1-2 sentences explaining what this group changes\",\n\t\t\"files: array of exact file paths from the input\",\n\t\t\"\",\n\t\t\"Output ONLY valid JSON. No markdown fences, no explanation.\",\n\t].join(\"\\n\")\n}\n\nfunction buildGroupingUserPrompt(summary: string): string {\n\treturn [\"Group the following changed files into logical commits:\", \"\", summary].join(\"\\n\")\n}\n\nexport function buildRetryGroupingPrompt(): string {\n\treturn [\n\t\t\"PREVIOUS ATTEMPT FAILED: You grouped all files into a single group.\",\n\t\t\"\",\n\t\t\"You MUST split the files into at least 2 groups based on what changed and why.\",\n\t\t\"\",\n\t\t\"Look for these natural split points:\",\n\t\t\"- Different features or modules (e.g., different directories)\",\n\t\t\"- New files vs modified files vs deleted files\",\n\t\t\"- Configuration changes vs code changes\",\n\t\t\"- Documentation vs implementation\",\n\t\t\"\",\n\t\t\"Do NOT split a source file from its tests — keep `foo.ts` and `foo.test.ts` in the same group.\",\n\t\t\"\",\n\t\t\"If unsure, err on the side of MORE groups, not fewer.\",\n\t\t\"\",\n\t\t\"Output format: JSON array of objects with keys 'name', 'description', 'files'.\",\n\t\t\"name: short label (3-5 words)\",\n\t\t\"description: 1-2 sentences explaining what this group changes\",\n\t\t\"files: array of exact file paths from the input\",\n\t\t\"\",\n\t\t\"Output ONLY valid JSON. No markdown fences, no explanation.\",\n\t].join(\"\\n\")\n}\n\nexport async function generateGroups(\n\tfiles: ChangedFile[],\n\tapiKey: string,\n\tmodel?: string,\n\ttimeout?: number,\n\tprovider?: ProviderName,\n\tproxy?: string,\n): Promise<GroupingResult> {\n\tdebug(\"generateGroups: %d files, model=%s\", files.length, model ?? \"default\")\n\n\tconst { included, excluded } = filterExcludedFiles(files)\n\n\tif (included.length === 0) {\n\t\tdebug(\"generateGroups: no files to group after exclusion\")\n\t\treturn { groups: [], excluded }\n\t}\n\n\tconst summary = buildFileSummary(included)\n\tconst systemPrompt = buildGroupingSystemPrompt()\n\tconst userPrompt = buildGroupingUserPrompt(summary)\n\n\tdebug(\"File summary:\\n%s\", summary)\n\tdebug(\"User prompt length: %d chars\", userPrompt.length)\n\n\tconst timeoutMs = timeout ?? 60000\n\tconst { client, model: resolvedModel } = createProvider({\n\t\tprovider: provider ?? \"groq\",\n\t\tapiKey,\n\t\tmodelOverride: model,\n\t\ttimeout: timeoutMs,\n\t\tbaseURLOverride: proxy,\n\t})\n\n\ttry {\n\t\tlet rawGroups = await callGroupingAI(client, resolvedModel, systemPrompt, userPrompt)\n\t\tdebug(\"generateGroups: parsed %d raw groups\", rawGroups.length)\n\t\tlet validated = validateGroups(rawGroups, included)\n\t\tdebug(\"generateGroups: %d validated groups\", validated.length)\n\n\t\t// Retry once if grouping quality is low. Evaluate against the raw AI result:\n\t\t// validateGroups() silently adds an \"Other changes\" group for any ungrouped\n\t\t// files, which would mask an empty model response (turning [] into a single\n\t\t// catch-all) and skip the retry the user needs.\n\t\tif (isLowQualityGrouping(rawGroups, included)) {\n\t\t\tdebug(\"generateGroups: low quality result, retrying with stricter prompt\")\n\t\t\tconst retryPrompt = buildRetryGroupingPrompt()\n\t\t\trawGroups = await callGroupingAI(client, resolvedModel, retryPrompt, userPrompt)\n\t\t\tdebug(\"generateGroups retry: parsed %d raw groups\", rawGroups.length)\n\t\t\tvalidated = validateGroups(rawGroups, included)\n\t\t\tdebug(\"generateGroups retry: %d validated groups\", validated.length)\n\t\t}\n\n\t\treturn { groups: validated, excluded }\n\t} catch (error) {\n\t\tdebug(\"generateGroups error: %s\", error instanceof Error ? error.message : String(error))\n\t\tconst providerLabel = provider ? formatProviderName(provider) : undefined\n\t\tthrow mapGroqError(error, providerLabel)\n\t}\n}\n\nasync function callGroupingAI(\n\tclient: ChatClient,\n\tmodel: string,\n\tsystemPrompt: string,\n\tuserPrompt: string,\n): Promise<CommitGroup[]> {\n\tconst completion = (await client.chat.completions.create({\n\t\tmessages: [\n\t\t\t{ role: \"system\", content: systemPrompt },\n\t\t\t{ role: \"user\", content: userPrompt },\n\t\t],\n\t\tmodel,\n\t\ttemperature: 0.3,\n\t\tmax_tokens: 2048,\n\t})) as { choices: { message?: { content?: string }; finish_reason?: string }[] }\n\n\tconst rawContent = completion.choices[0]?.message?.content\n\tconst content = typeof rawContent === \"string\" ? rawContent.trim() : \"\"\n\n\tdebug(\n\t\t\"callGroupingAI response: choices=%d, finishReason=%s, contentLen=%d\",\n\t\tcompletion.choices.length,\n\t\tcompletion.choices[0]?.finish_reason ?? \"(none)\",\n\t\tcontent.length,\n\t)\n\tdebug(\"callGroupingAI raw content: %s\", content.slice(0, 500) || \"(empty)\")\n\n\tif (!content) {\n\t\tthrow new Error(\"AI returned an empty grouping response\")\n\t}\n\n\treturn parseGroupingResponse(content)\n}\n\n/** Minimum file count where a single-group result is considered low quality */\nconst MIN_FILES_FOR_QUALITY_CHECK = 5\n\nexport function isLowQualityGrouping(groups: CommitGroup[], allFiles: ChangedFile[]): boolean {\n\t// No files to group → empty grouping is the correct result, not low quality.\n\tif (allFiles.length === 0) return false\n\t// Files were provided but the model returned no groups — retry once before\n\t// falling back to \"Other changes\" so the user still gets a sensible commit.\n\tif (groups.length === 0) return true\n\tif (allFiles.length < MIN_FILES_FOR_QUALITY_CHECK) return false\n\treturn groups.length === 1\n}\n\nexport function validateGroups(groups: CommitGroup[], allFiles: ChangedFile[]): CommitGroup[] {\n\tconst validPaths = new Set(allFiles.map((f) => f.path))\n\tconst seen = new Set<string>()\n\tconst validated: CommitGroup[] = []\n\n\tfor (const group of groups) {\n\t\tconst uniqueFiles = group.files.filter((f) => {\n\t\t\tif (!validPaths.has(f)) return false // AI-hallucinated path\n\t\t\tif (seen.has(f)) return false // duplicate across groups\n\t\t\tseen.add(f)\n\t\t\treturn true\n\t\t})\n\n\t\tif (uniqueFiles.length > 0) {\n\t\t\tvalidated.push({\n\t\t\t\tname: group.name,\n\t\t\t\tdescription: group.description,\n\t\t\t\tfiles: uniqueFiles,\n\t\t\t})\n\t\t}\n\t}\n\n\t// Move misplaced test files back into their source file's group. Done after\n\t// path filtering (so hallucinated tests don't trigger moves) and before\n\t// orphan bucketing (so a source-less test still gets caught by \"Other\n\t// changes\"). `seen` is unaffected by inter-group moves.\n\tconst reunited = reuniteTestsWithSources(validated)\n\tif (reunited !== validated) {\n\t\tdebug(\"validateGroups: reunited %d groups after test/source merge\", reunited.length)\n\t}\n\n\t// Find files not in any group\n\tconst ungrouped = allFiles.filter((f) => !seen.has(f.path))\n\n\tif (ungrouped.length > 0) {\n\t\tdebug(\"validateGroups: %d ungrouped files added to 'Other changes'\", ungrouped.length)\n\t\treunited.push({\n\t\t\tname: \"Other changes\",\n\t\t\tdescription: \"Miscellaneous changes that did not fit into other groups\",\n\t\t\tfiles: ungrouped.map((f) => f.path),\n\t\t})\n\t}\n\n\treturn reunited\n}\n","let agentMode = false\n\nexport function setAgentMode(value: boolean): void {\n\tagentMode = value\n}\n\nexport function isAgentMode(): boolean {\n\treturn agentMode\n}\n\nexport interface AgentCommit {\n\tmessage: string\n\thash: string\n\tfiles: string[]\n\tgroupName?: string\n}\n\nexport interface AgentResult {\n\tstatus: \"success\" | \"failure\" | \"no_changes\" | \"cancelled\"\n\tcommits: AgentCommit[]\n\terrors?: string[]\n}\n\nexport const EXIT_CODES = {\n\tSUCCESS: 0,\n\tGENERIC: 1,\n\tNO_CHANGES: 2,\n\tGIT: 3,\n\tAI: 4,\n\tCHECK: 5,\n\tHOOK: 6,\n} as const\n\nexport function writeAgentResult(result: AgentResult): void {\n\tprocess.stdout.write(`${JSON.stringify(result)}\\n`)\n}\n","import { createHash } from \"node:crypto\"\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\"\nimport os from \"node:os\"\nimport { join } from \"node:path\"\nimport { debug } from \"./debug.js\"\n\nconst CACHE_DIR = join(os.homedir(), \".cache\", \"commit-mint\")\n\nfunction repoHash(repoPath: string): string {\n\treturn createHash(\"sha256\").update(repoPath).digest(\"hex\").slice(0, 12)\n}\n\nfunction cachePath(repoPath: string): string {\n\treturn join(CACHE_DIR, `${repoHash(repoPath)}.json`)\n}\n\nexport interface CachedCommit {\n\tmessage: string\n\ttimestamp: number\n\trepoPath: string\n}\n\nexport async function saveCachedCommit(repoPath: string, message: string) {\n\tawait mkdir(CACHE_DIR, { recursive: true })\n\tconst data: CachedCommit = {\n\t\tmessage,\n\t\ttimestamp: Date.now(),\n\t\trepoPath,\n\t}\n\tconst path = cachePath(repoPath)\n\tdebug(\"saveCachedCommit: saving to %s\", path)\n\tawait writeFile(path, JSON.stringify(data, null, 2), \"utf8\")\n}\n\nexport async function loadCachedCommit(repoPath: string): Promise<CachedCommit | null> {\n\tconst path = cachePath(repoPath)\n\tdebug(\"loadCachedCommit: loading from %s\", path)\n\ttry {\n\t\tconst raw = await readFile(path, \"utf8\")\n\t\tconst data = JSON.parse(raw) as CachedCommit\n\t\tdebug(\"loadCachedCommit: found message from %s\", new Date(data.timestamp).toISOString())\n\t\treturn data\n\t} catch {\n\t\tdebug(\"loadCachedCommit: no cached commit found\")\n\t\treturn null\n\t}\n}\n","import { spawn } from \"node:child_process\"\nimport { debug } from \"../utils/debug.js\"\n\n/** Milliseconds to wait after stdin closes for quick exit failures. */\nconst GRACE_PERIOD_MS = 150\n\nexport async function copyToClipboard(content: string): Promise<boolean> {\n\tconst commands: [string, string[]][] = [\n\t\t[\"wl-copy\", []],\n\t\t[\"xclip\", [\"-selection\", \"clipboard\"]],\n\t\t[\"xsel\", [\"--clipboard\", \"--input\"]],\n\t\t[\"pbcopy\", []],\n\t]\n\n\tfor (const [cmd, args] of commands) {\n\t\ttry {\n\t\t\tconst success = await tryCopy(cmd, args, content)\n\t\t\tif (success) return true\n\t\t} catch {}\n\t}\n\treturn false\n}\n\n/**\n * Try to copy content using a single clipboard tool.\n *\n * Waits a short grace period after stdin closes to detect quick failures\n * (e.g. wl-copy on non-Wayland, missing display). If the tool survives\n * the grace period, assumes success — clipboard tools like xclip and\n * wl-copy hold the selection open indefinitely, so we can't wait for exit.\n */\n/**\n * Evaluate clipboard tool status after the grace period.\n * If the child already exited, report based on exit code.\n * If still alive, assume success (clipboard tools hold selection open).\n */\nfunction handleGracePeriod(\n\tsettled: boolean,\n\texitCode: number | null,\n\tstderrChunks: Buffer[],\n\tchild: ReturnType<typeof spawn>,\n\tdone: (result: boolean, reason?: string) => void,\n) {\n\tif (settled) return\n\n\tif (exitCode !== null) {\n\t\tif (exitCode === 0) {\n\t\t\tdone(true, \"exited 0\")\n\t\t} else {\n\t\t\tconst stderr = Buffer.concat(stderrChunks).toString().trim()\n\t\t\tdone(false, `exit ${exitCode}${stderr ? `: ${stderr}` : \"\"}`)\n\t\t}\n\t\treturn\n\t}\n\n\t// Child still alive — assume success. Clipboard tools\n\t// (xclip, wl-copy) hold the selection open, so they\n\t// don't exit until something else takes the clipboard.\n\tchild.unref()\n\tdone(true)\n}\n\nfunction tryCopy(cmd: string, args: string[], content: string): Promise<boolean> {\n\treturn new Promise<boolean>((resolve) => {\n\t\tdebug(\"clipboard: trying %s\", cmd)\n\n\t\tconst child = spawn(cmd, args, {\n\t\t\tstdio: [\"pipe\", \"ignore\", \"pipe\"],\n\t\t})\n\n\t\tlet settled = false\n\t\tconst stderrChunks: Buffer[] = []\n\n\t\tchild.stderr?.on(\"data\", (chunk: Buffer) => {\n\t\t\tstderrChunks.push(chunk)\n\t\t})\n\n\t\tconst done = (result: boolean, reason?: string) => {\n\t\t\tif (settled) return\n\t\t\tsettled = true\n\t\t\tdebug(\"clipboard: %s %s%s\", cmd, result ? \"ok\" : \"failed\", reason ? ` (${reason})` : \"\")\n\t\t\tresolve(result)\n\t\t}\n\n\t\t// Command not found (ENOENT)\n\t\tchild.on(\"error\", (err) => {\n\t\t\tdone(false, err.message)\n\t\t})\n\n\t\t// Track exit for grace-period detection\n\t\tlet exitCode: number | null = null\n\t\tchild.on(\"exit\", (code) => {\n\t\t\texitCode = code\n\t\t})\n\n\t\tchild.stdin.write(content, (err) => {\n\t\t\tif (err) {\n\t\t\t\tdone(false, \"stdin write error\")\n\t\t\t\treturn\n\t\t\t}\n\t\t\tchild.stdin.end(() => {\n\t\t\t\t// stdin closed — start grace period to detect quick failures\n\t\t\t\tsetTimeout(\n\t\t\t\t\t() => handleGracePeriod(settled, exitCode, stderrChunks, child, done),\n\t\t\t\t\tGRACE_PERIOD_MS,\n\t\t\t\t)\n\t\t\t})\n\t\t})\n\t})\n}\n","import * as p from \"@clack/prompts\"\nimport { dim, green, red } from \"kolorist\"\nimport { copyToClipboard } from \"../services/clipboard.js\"\nimport type { HookError } from \"../services/hooks.js\"\nimport { debug } from \"../utils/debug.js\"\n\nconst MAX_TSC_DIAGNOSTICS = 3\nconst MAX_ESLINT_DIAGNOSTICS = 3\nconst MAX_TEST_FAILURES = 3\nconst MAX_SUMMARY_LINE_LENGTH = 120\nconst TSC_DIAGNOSTIC =\n\t/^(.+?\\.(?:ts|tsx|mts|cts|js|jsx|mjs|cjs))\\((\\d+),(\\d+)\\):\\s+error\\s+(TS\\d+):\\s+(.+)$/\n// ESLint stylish format: <whitespace><line>:<col> <severity> <message> <rule>\nconst ESLINT_ERROR_LINE = /^\\s*(\\d+):(\\d+)\\s+(error|warning)\\s+(.+)\\s{2,}(\\S+)\\s*$/\n// vitest/jest \"Failed Tests\" block: optional indent, FAIL, file path, \">\", test path\nconst TEST_FILE_FAIL = /^\\s*FAIL\\s+(.+?\\.(?:test|spec)\\.[^\\s>]+)\\s*>\\s*(.+)$/\n\ninterface TscDiagnostic {\n\tfile: string\n\tline: string\n\tcolumn: string\n\tcode: string\n\tmessage: string\n}\n\ninterface EslintDiagnostic {\n\tfile: string\n\tline: string\n\tcolumn: string\n\tseverity: string\n\tmessage: string\n\trule: string\n}\n\ninterface TestFailure {\n\tfile: string\n\tname: string\n}\n\nfunction formatCheckFailureSummary(errors: HookError[]): string {\n\tif (errors.length === 0) {\n\t\treturn \"No check error details were parsed. View full output for details.\"\n\t}\n\n\treturn errors.map((error) => formatCheckErrorSummary(error)).join(\"\\n\")\n}\n\nfunction formatCheckErrorSummary(error: HookError): string {\n\tif (error.tool === \"tsc\") {\n\t\tconst diagnostics = extractTscDiagnostics(error.raw || error.message)\n\t\tif (diagnostics.length > 0) {\n\t\t\treturn formatTscSummary(diagnostics)\n\t\t}\n\t}\n\n\tif (error.tool === \"eslint\") {\n\t\tconst diagnostics = extractEslintDiagnostics(error.raw || error.message)\n\t\tif (diagnostics.length > 0) {\n\t\t\treturn formatEslintSummary(diagnostics)\n\t\t}\n\t}\n\n\tif (error.tool === \"vitest\" || error.tool === \"jest\") {\n\t\tconst failures = extractTestFailures(error.raw || error.message)\n\t\tif (failures.length > 0) {\n\t\t\treturn formatTestFailureSummary(failures, error.tool)\n\t\t}\n\t}\n\n\tconst message = firstMeaningfulLine(error.message || error.raw)\n\treturn ` ${red(\"•\")} [${error.tool}] ${truncate(message, MAX_SUMMARY_LINE_LENGTH)}`\n}\n\nfunction extractTscDiagnostics(raw: string): TscDiagnostic[] {\n\treturn raw\n\t\t.split(\"\\n\")\n\t\t.map((line) => line.trim())\n\t\t.map((line) => {\n\t\t\tconst match = TSC_DIAGNOSTIC.exec(line)\n\t\t\tif (!match) return null\n\t\t\treturn {\n\t\t\t\tfile: match[1] ?? \"\",\n\t\t\t\tline: match[2] ?? \"\",\n\t\t\t\tcolumn: match[3] ?? \"\",\n\t\t\t\tcode: match[4] ?? \"\",\n\t\t\t\tmessage: match[5] ?? \"\",\n\t\t\t}\n\t\t})\n\t\t.filter((diagnostic): diagnostic is TscDiagnostic => diagnostic !== null)\n}\n\nfunction formatTscSummary(diagnostics: TscDiagnostic[]): string {\n\tconst visible = diagnostics.slice(0, MAX_TSC_DIAGNOSTICS)\n\tconst hidden = diagnostics.length - visible.length\n\tconst lines = [\n\t\t` ${red(\"•\")} [tsc] ${diagnostics.length} TypeScript error${diagnostics.length !== 1 ? \"s\" : \"\"}`,\n\t\t...visible.map(\n\t\t\t(diagnostic) =>\n\t\t\t\t`${diagnostic.file}:${diagnostic.line}:${diagnostic.column} — error ${diagnostic.code}: ${truncate(diagnostic.message, MAX_SUMMARY_LINE_LENGTH)}`,\n\t\t),\n\t]\n\n\tif (hidden > 0) {\n\t\tlines.push(\n\t\t\tdim(\n\t\t\t\t` +${hidden} more TypeScript error${hidden !== 1 ? \"s\" : \"\"}. View full output for details.`,\n\t\t\t),\n\t\t)\n\t}\n\n\treturn lines.join(\"\\n\")\n}\n\nfunction extractEslintDiagnostics(raw: string): EslintDiagnostic[] {\n\tconst diagnostics: EslintDiagnostic[] = []\n\tconst lines = raw.split(\"\\n\")\n\tlet currentFile = \"\"\n\n\tfor (const line of lines) {\n\t\t// File path line: not indented, contains a path separator, not an error detail line\n\t\tif (!/^\\s/.test(line) && line.includes(\"/\") && !ESLINT_ERROR_LINE.test(line)) {\n\t\t\tcurrentFile = line.trim()\n\t\t\tcontinue\n\t\t}\n\n\t\tconst match = ESLINT_ERROR_LINE.exec(line)\n\t\tif (match) {\n\t\t\tdiagnostics.push({\n\t\t\t\tfile: currentFile || \"unknown\",\n\t\t\t\tline: match[1] ?? \"\",\n\t\t\t\tcolumn: match[2] ?? \"\",\n\t\t\t\tseverity: match[3] ?? \"\",\n\t\t\t\tmessage: (match[4] ?? \"\").trim(),\n\t\t\t\trule: match[5] ?? \"\",\n\t\t\t})\n\t\t}\n\t}\n\n\treturn diagnostics\n}\n\nfunction extractTestFailures(raw: string): TestFailure[] {\n\tconst failures: TestFailure[] = []\n\tconst seen = new Set<string>()\n\tfor (const line of raw.split(\"\\n\")) {\n\t\tconst match = TEST_FILE_FAIL.exec(line)\n\t\tif (!match) continue\n\t\tconst file = (match[1] ?? \"\").trim()\n\t\tconst name = (match[2] ?? \"\").trim()\n\t\tif (!file || !name) continue\n\t\tconst key = `${file}\\u0000${name}`\n\t\t// Dedupe — vitest can repeat the same FAIL line across reruns captured in one block\n\t\tif (seen.has(key)) continue\n\t\tseen.add(key)\n\t\tfailures.push({ file, name })\n\t}\n\treturn failures\n}\n\nfunction formatTestFailureSummary(failures: TestFailure[], tool: string): string {\n\tconst total = failures.length\n\tconst visible = failures.slice(0, MAX_TEST_FAILURES)\n\tconst hidden = total - visible.length\n\tconst fileCount = new Set(failures.map((f) => f.file)).size\n\tconst testNoun = total === 1 ? \"test\" : \"tests\"\n\tconst fileNoun = fileCount === 1 ? \"file\" : \"files\"\n\n\tconst lines = [` ${red(\"•\")} [${tool}] ${total} failed ${testNoun} in ${fileCount} ${fileNoun}`]\n\n\t// Group visible failures by file to avoid repeating the file path\n\tconst byFile = new Map<string, string[]>()\n\tfor (const failure of visible) {\n\t\tconst names = byFile.get(failure.file) ?? []\n\t\tnames.push(failure.name)\n\t\tbyFile.set(failure.file, names)\n\t}\n\n\tfor (const [file, names] of byFile) {\n\t\tlines.push(` ${truncate(file, MAX_SUMMARY_LINE_LENGTH)}`)\n\t\tfor (const name of names) {\n\t\t\tlines.push(` ${red(\"×\")} ${truncate(name, MAX_SUMMARY_LINE_LENGTH)}`)\n\t\t}\n\t}\n\n\tif (hidden > 0) {\n\t\tlines.push(\n\t\t\tdim(\n\t\t\t\t` +${hidden} more failed ${hidden === 1 ? \"test\" : \"tests\"}. View full output for details.`,\n\t\t\t),\n\t\t)\n\t}\n\n\treturn lines.join(\"\\n\")\n}\n\nfunction formatEslintSummary(diagnostics: EslintDiagnostic[]): string {\n\tconst visible = diagnostics.slice(0, MAX_ESLINT_DIAGNOSTICS)\n\tconst hidden = diagnostics.length - visible.length\n\tconst count = diagnostics.length\n\tconst noun = count === 1 ? \"problem\" : \"problems\"\n\tconst lines = [\n\t\t` ${red(\"•\")} [eslint] ${count} ESLint ${noun}`,\n\t\t...visible.map(\n\t\t\t(diagnostic) =>\n\t\t\t\t`${diagnostic.file}:${diagnostic.line}:${diagnostic.column} ${diagnostic.severity} ${diagnostic.rule} — ${truncate(diagnostic.message, MAX_SUMMARY_LINE_LENGTH)}`,\n\t\t),\n\t]\n\n\tif (hidden > 0) {\n\t\tlines.push(\n\t\t\tdim(\n\t\t\t\t` +${hidden} more ESLint ${hidden === 1 ? \"problem\" : \"problems\"}. View full output for details.`,\n\t\t\t),\n\t\t)\n\t}\n\n\treturn lines.join(\"\\n\")\n}\n\nfunction firstMeaningfulLine(message: string): string {\n\tconst line = message\n\t\t.split(\"\\n\")\n\t\t.map((l) => l.trim())\n\t\t.find((l) => l.length > 0 && !l.startsWith(\">\") && !l.startsWith(\"ELIFECYCLE\"))\n\treturn line ?? message\n}\n\nfunction truncate(message: string, maxLength: number): string {\n\tconst collapsed = message.replace(/\\s+/g, \" \").trim()\n\tif (collapsed.length <= maxLength) return collapsed\n\treturn `${collapsed.slice(0, Math.max(0, maxLength - 1))}…`\n}\n\n// biome-ignore lint/complexity/noExcessiveLinesPerFunction: Check failure menu with retry option\nexport async function showCheckFailureMenu(\n\terrors: HookError[],\n\trawStderr: string,\n\tonRetry?: () => Promise<boolean>,\n): Promise<\"skipped\" | \"cancelled\" | \"retried\"> {\n\tdebug(\"showCheckFailureMenu: %d errors\", errors.length)\n\n\tlet clipboardCopied = false\n\n\tp.note(formatCheckFailureSummary(errors), red(\"Pre-commit check failed\"))\n\n\twhile (true) {\n\t\tconst choice = await p.select({\n\t\t\tmessage: \"What do you want to do?\",\n\t\t\toptions: [\n\t\t\t\t{\n\t\t\t\t\tlabel: clipboardCopied\n\t\t\t\t\t\t? `${green(\"✓\")} Copy error report to clipboard`\n\t\t\t\t\t\t: \"Copy error report to clipboard\",\n\t\t\t\t\tvalue: \"copy\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: \"View full error output\",\n\t\t\t\t\tvalue: \"view\",\n\t\t\t\t\thint: \"Show the raw stderr from checks\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: \"Retry checks\",\n\t\t\t\t\tvalue: \"retry\",\n\t\t\t\t\thint: \"Re-run checks after fixing errors\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: \"Skip checks and commit\",\n\t\t\t\t\tvalue: \"skip\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: \"Cancel\",\n\t\t\t\t\tvalue: \"cancel\",\n\t\t\t\t},\n\t\t\t],\n\t\t})\n\n\t\tif (p.isCancel(choice)) {\n\t\t\tdebug(\"showCheckFailureMenu: user cancelled\")\n\t\t\treturn \"cancelled\"\n\t\t}\n\n\t\tdebug(\"showCheckFailureMenu: user chose %s\", choice)\n\n\t\tswitch (choice) {\n\t\t\tcase \"copy\": {\n\t\t\t\tconst ok = await copyToClipboard(rawStderr)\n\t\t\t\tif (ok) {\n\t\t\t\t\tclipboardCopied = true\n\t\t\t\t\tp.log.step(green(\"Copied to clipboard.\"))\n\t\t\t\t} else {\n\t\t\t\t\tp.log.warn(red(\"No clipboard tool found. Install xclip, wl-copy, or xsel.\"))\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tcase \"view\": {\n\t\t\t\tp.note(rawStderr.trim() || \"(no raw output)\", \"Full error output\")\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tcase \"retry\": {\n\t\t\t\tif (onRetry) {\n\t\t\t\t\treturn \"retried\"\n\t\t\t\t}\n\t\t\t\t// No retry callback — return retried so caller can handle the loop\n\t\t\t\treturn \"retried\"\n\t\t\t}\n\t\t\tcase \"skip\": {\n\t\t\t\tp.log.info(\"Skipping checks and proceeding with commit...\")\n\t\t\t\treturn \"skipped\"\n\t\t\t}\n\t\t\tcase \"cancel\": {\n\t\t\t\tp.outro(dim(\"Cancelled.\"))\n\t\t\t\treturn \"cancelled\"\n\t\t\t}\n\t\t}\n\t}\n}\n","import { log } from \"@clack/prompts\"\nimport { green } from \"kolorist\"\nimport type { CheckResults } from \"../services/checks.js\"\n\n/** Minimal spinner contract — only the `stop` method is needed. */\ntype SpinnerStop = { stop: (message: string) => void }\n\n/**\n * Stop a check spinner with a per-tool summary of the check results.\n *\n * - On success: stops with \"All checks passed\" and prints a `✓ tool` line\n * for each result.\n * - On failure: stops with \"N checks failed\" (pluralized). Raw error output\n * is intentionally NOT printed here — callers handle failure display\n * (menu, raw print, etc.).\n */\nexport function stopCheckSpinner(spinner: SpinnerStop, results: CheckResults): void {\n\tif (results.ok) {\n\t\tspinner.stop(\"All checks passed\")\n\t\tif (results.results.length > 0) {\n\t\t\tlog.info(results.results.map((r) => ` ${green(\"✓\")} ${r.tool}`).join(\"\\n\"))\n\t\t}\n\t} else {\n\t\tconst failed = results.results.filter((r) => !r.ok)\n\t\tspinner.stop(`${failed.length} check${failed.length !== 1 ? \"s\" : \"\"} failed`)\n\t}\n}\n","import * as p from \"@clack/prompts\"\nimport { bold, cyan, dim, green, red, yellow } from \"kolorist\"\nimport type { ChangedFile } from \"../services/git.js\"\nimport type { CommitGroup } from \"../services/grouping.js\"\nimport { debug } from \"../utils/debug.js\"\n\nexport async function showGroupingConfirmation(\n\tgroups: CommitGroup[],\n\texcluded: string[],\n): Promise<boolean> {\n\tdebug(\"showGroupingConfirmation: %d groups, %d excluded\", groups.length, excluded.length)\n\n\tconst lines: string[] = []\n\n\tfor (const group of groups) {\n\t\tlines.push(bold(group.name))\n\t\tlines.push(` ${dim(group.description)}`)\n\t\tlines.push(` ${green(String(group.files.length))} file${group.files.length !== 1 ? \"s\" : \"\"}`)\n\t\tfor (const file of group.files) {\n\t\t\tlines.push(` ${dim(\"•\")} ${file}`)\n\t\t}\n\t\tlines.push(\"\")\n\t}\n\n\tif (excluded.length > 0) {\n\t\tlines.push(dim(`Excluded: ${excluded.length} file${excluded.length !== 1 ? \"s\" : \"\"}`))\n\t\tfor (const file of excluded) {\n\t\t\tlines.push(` ${dim(\"•\")} ${dim(file)}`)\n\t\t}\n\t}\n\n\tp.note(lines.join(\"\\n\"), \"Proposed commit groups\")\n\n\tconst choice = await p.select({\n\t\tmessage: \"Proceed with these groupings?\",\n\t\toptions: [\n\t\t\t{ label: \"Yes, commit all groups\", value: \"yes\" },\n\t\t\t{ label: \"No, cancel\", value: \"no\" },\n\t\t],\n\t})\n\n\tif (p.isCancel(choice) || choice === \"no\") {\n\t\tdebug(\"showGroupingConfirmation: user cancelled\")\n\t\treturn false\n\t}\n\n\tdebug(\"showGroupingConfirmation: user confirmed\")\n\treturn true\n}\n\nexport function showGroupProgress(current: number, total: number, groupName: string): void {\n\tp.log.info(`Commit group ${current} of ${total}: ${cyan(`\"${groupName}\"`)}`)\n}\n\nconst statusLabel = (status: string): string => {\n\tswitch (status) {\n\t\tcase \"M\":\n\t\t\treturn yellow(\"M\")\n\t\tcase \"A\":\n\t\t\treturn green(\"A\")\n\t\tcase \"D\":\n\t\t\treturn red(\"D\")\n\t\tcase \"?\":\n\t\tcase \"??\":\n\t\t\treturn cyan(\"?\")\n\t\tdefault:\n\t\t\treturn dim(status)\n\t}\n}\n\n/** Display a table of changed files with status indicators */\nexport function showChangedFilesTable(files: ChangedFile[]): void {\n\tif (files.length === 0) return\n\n\tconst lines = files.map((f) => ` ${statusLabel(f.status)} ${f.path}`)\n\tp.note(lines.join(\"\\n\"), `${files.length} file${files.length !== 1 ? \"s\" : \"\"} changed`)\n}\n\n/** Display a compact grouping summary (only shown when >1 group) */\nexport function showGroupingSummary(groups: CommitGroup[]): void {\n\tif (groups.length <= 1) return\n\n\tconst lines = groups.map(\n\t\t(g) => `${bold(g.name)} ${dim(\"—\")} ${g.files.length} file${g.files.length !== 1 ? \"s\" : \"\"}`,\n\t)\n\tp.note(lines.join(\"\\n\"), \"Commit groups\")\n}\n\n/** Display combined view: files with status indicators grouped by commit group */\nexport function showGroupedFiles(groups: CommitGroup[], changedFiles: ChangedFile[]): void {\n\tconst statusMap = new Map(changedFiles.map((f) => [f.path, f.status]))\n\n\tconst lines: string[] = []\n\n\tfor (let i = 0; i < groups.length; i++) {\n\t\tconst group = groups[i]\n\t\tlines.push(\n\t\t\t`${bold(group.name)} ${dim(\"—\")} ${group.files.length} file${group.files.length !== 1 ? \"s\" : \"\"}`,\n\t\t)\n\t\tfor (const file of group.files) {\n\t\t\tconst status = statusMap.get(file) ?? \"M\"\n\t\t\tlines.push(` ${statusLabel(status)} ${file}`)\n\t\t}\n\t\tif (i < groups.length - 1) {\n\t\t\tlines.push(\"\")\n\t\t}\n\t}\n\n\tp.note(lines.join(\"\\n\"), \"Commit groups\")\n}\n","import * as p from \"@clack/prompts\"\nimport { bold, cyan, dim, green, red, yellow } from \"kolorist\"\nimport { copyToClipboard } from \"../services/clipboard.js\"\nimport type { HookError } from \"../services/hooks.js\"\nimport { debug } from \"../utils/debug.js\"\n\nexport type RecoveryResult = \"committed\" | \"cancelled\" | \"failed\"\n\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Recovery menu with recursive retry path\n// biome-ignore lint/complexity/noExcessiveLinesPerFunction: Interactive TUI — format errors, handle 5 menu actions, recursive retry\nexport async function showRecoveryMenu(\n\terrors: HookError[],\n\tonRetry: () => Promise<boolean>,\n\tonSkipHooks: (message: string) => Promise<boolean>,\n\tonRestage: () => Promise<boolean>,\n\tmessage: string,\n\trawStderr: string,\n): Promise<RecoveryResult> {\n\tdebug(\"showRecoveryMenu: %d errors\", errors.length)\n\n\tlet clipboardCopied = false\n\tlet showNote = true\n\n\twhile (true) {\n\t\tif (showNote) {\n\t\t\tp.note(\n\t\t\t\terrors.map((e) => ` ${red(\"•\")} [${e.tool}] ${e.message}`).join(\"\\n\"),\n\t\t\t\tred(bold(\"Pre-commit hook failed\")),\n\t\t\t)\n\t\t\tshowNote = false\n\t\t}\n\n\t\tconst choice = await p.select({\n\t\t\tmessage: \"What do you want to do?\",\n\t\t\toptions: [\n\t\t\t\t{\n\t\t\t\t\tlabel: clipboardCopied\n\t\t\t\t\t\t? `${green(\"✓\")} Copy error report to clipboard`\n\t\t\t\t\t\t: \"Copy error report to clipboard\",\n\t\t\t\t\tvalue: \"clipboard\",\n\t\t\t\t\thint: clipboardCopied ? \"Copied!\" : \"Paste into another terminal for an AI agent\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: \"View full error output\",\n\t\t\t\t\tvalue: \"view\",\n\t\t\t\t\thint: \"Show the raw stderr from hooks\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: \"Skip hooks and commit (--no-verify)\",\n\t\t\t\t\tvalue: \"skip\",\n\t\t\t\t\thint: \"Commit anyway, fix later\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: \"Re-stage files and retry\",\n\t\t\t\t\tvalue: \"restage\",\n\t\t\t\t\thint: \"Pick up fixes from another terminal\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: \"Edit commit message\",\n\t\t\t\t\tvalue: \"edit\",\n\t\t\t\t\thint: \"Modify the message before retrying\",\n\t\t\t\t},\n\t\t\t\t{ label: \"Cancel\", value: \"cancel\" },\n\t\t\t],\n\t\t})\n\n\t\tif (p.isCancel(choice)) {\n\t\t\tdebug(\"showRecoveryMenu: user cancelled\")\n\t\t\tp.outro(yellow(\"Cancelled. Message cached for --retry.\"))\n\t\t\treturn \"cancelled\"\n\t\t}\n\n\t\tdebug(\"showRecoveryMenu: user chose %s\", choice)\n\n\t\tswitch (choice) {\n\t\t\tcase \"clipboard\": {\n\t\t\t\tconst ok = await copyToClipboard(rawStderr)\n\t\t\t\tif (ok) {\n\t\t\t\t\tclipboardCopied = true\n\t\t\t\t\tp.log.step(green(\"Copied to clipboard.\"))\n\t\t\t\t} else {\n\t\t\t\t\tp.log.warn(red(\"No clipboard tool found. Install xclip, wl-copy, or xsel.\"))\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tcase \"view\": {\n\t\t\t\tp.note(rawStderr.trim() || \"(no raw output)\", \"Full error output\")\n\t\t\t\tshowNote = true\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tcase \"skip\": {\n\t\t\t\tp.log.info(yellow(\"Committing with --no-verify...\"))\n\t\t\t\tconst ok = await onSkipHooks(message)\n\t\t\t\tif (ok) {\n\t\t\t\t\tp.outro(green(\"Committed (hooks skipped).\"))\n\t\t\t\t\treturn \"committed\"\n\t\t\t\t} else {\n\t\t\t\t\tp.outro(red(\"Commit failed even with --no-verify.\"))\n\t\t\t\t\treturn \"failed\"\n\t\t\t\t}\n\t\t\t}\n\t\t\tcase \"restage\": {\n\t\t\t\tp.log.info(cyan(\"Re-staging and retrying...\"))\n\t\t\t\tconst ok = await onRestage()\n\t\t\t\tif (ok) {\n\t\t\t\t\tp.outro(green(\"Committed successfully.\"))\n\t\t\t\t\treturn \"committed\"\n\t\t\t\t}\n\t\t\t\t// Re-show errors after failed restage for context\n\t\t\t\tshowNote = true\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tcase \"edit\": {\n\t\t\t\tconst edited = await p.text({\n\t\t\t\t\tmessage: \"Edit commit message:\",\n\t\t\t\t\tinitialValue: message,\n\t\t\t\t\tvalidate: (v) => (v?.trim() ? undefined : \"Message cannot be empty\"),\n\t\t\t\t})\n\t\t\t\tif (p.isCancel(edited)) {\n\t\t\t\t\tp.outro(yellow(\"Cancelled. Message cached for --retry.\"))\n\t\t\t\t\treturn \"cancelled\"\n\t\t\t\t}\n\t\t\t\tconst ok = await onRetry()\n\t\t\t\tif (ok) {\n\t\t\t\t\tp.outro(green(\"Committed successfully.\"))\n\t\t\t\t\treturn \"committed\"\n\t\t\t\t} else {\n\t\t\t\t\tp.outro(red(\"Commit failed again.\"))\n\t\t\t\t\treturn \"failed\"\n\t\t\t\t}\n\t\t\t}\n\t\t\tcase \"cancel\": {\n\t\t\t\tp.outro(dim(\"Message cached for --retry.\"))\n\t\t\t\treturn \"cancelled\"\n\t\t\t}\n\t\t}\n\t}\n}\n","import { isCancel } from \"@clack/prompts\"\nimport { bold, red } from \"kolorist\"\nimport { debug } from \"../utils/debug.js\"\n\nexport interface ReviewCommitMessageOptions {\n\t/**\n\t * If provided, adds a \"Regenerate with hint\" option to the menu.\n\t * Called with the user-entered hint; should return a new commit message.\n\t * Thrown errors are caught and surfaced inline so the user can retry.\n\t */\n\tregenerate?: (hint: string) => Promise<string>\n}\n\nasync function handleEdit(message: string): Promise<string | null> {\n\tconst { text } = await import(\"@clack/prompts\")\n\tconst edited = await text({\n\t\tmessage: \"Edit commit message:\",\n\t\tinitialValue: message,\n\t\tvalidate: (v) => (v?.trim() ? undefined : \"Message cannot be empty\"),\n\t})\n\tif (isCancel(edited)) {\n\t\tdebug(\"User cancelled edit, returning to review menu\")\n\t\treturn null\n\t}\n\tconst newMessage = String(edited).trim()\n\tdebug(\"Edited message:\", newMessage)\n\treturn newMessage\n}\n\nasync function handleRegenerate(\n\tregenerate: (hint: string) => Promise<string>,\n): Promise<string | null> {\n\tconst { log, text } = await import(\"@clack/prompts\")\n\tconst hint = await text({\n\t\tmessage: \"Describe what this commit is about to guide regeneration:\",\n\t\tvalidate: (v) => (v?.trim() ? undefined : \"Hint cannot be empty\"),\n\t})\n\tif (isCancel(hint)) {\n\t\tdebug(\"User cancelled hint entry, returning to review menu\")\n\t\treturn null\n\t}\n\tconst hintValue = String(hint).trim()\n\tdebug(\"Regenerating with hint:\", hintValue)\n\ttry {\n\t\tconst newMessage = await regenerate(hintValue)\n\t\tdebug(\"Regenerated message:\", newMessage)\n\t\treturn newMessage\n\t} catch (err) {\n\t\tconst errMsg = err instanceof Error ? err.message : String(err)\n\t\tdebug(\"Regeneration failed:\", errMsg)\n\t\tlog.warn(red(`Regeneration failed: ${errMsg}`))\n\t\treturn null\n\t}\n}\n\nexport async function reviewCommitMessage(\n\tmessage: string,\n\toptions?: ReviewCommitMessageOptions,\n): Promise<string | null> {\n\tconst { select } = await import(\"@clack/prompts\")\n\twhile (true) {\n\t\tconst reviewOptions: { label: string; value: string }[] = [\n\t\t\t{ label: \"Use as-is\", value: \"use\" },\n\t\t\t{ label: \"Edit\", value: \"edit\" },\n\t\t]\n\t\tif (options?.regenerate) {\n\t\t\treviewOptions.push({ label: \"Regenerate with hint\", value: \"regenerate\" })\n\t\t}\n\t\treviewOptions.push({ label: \"Cancel\", value: \"cancel\" })\n\n\t\tconst review = await select({\n\t\t\tmessage: `Review commit message:\\n\\n ${bold(message)}\\n`,\n\t\t\toptions: reviewOptions,\n\t\t})\n\n\t\tif (isCancel(review) || review === \"cancel\") {\n\t\t\tdebug(\"User cancelled at review step\")\n\t\t\treturn null\n\t\t}\n\n\t\tif (review === \"use\") {\n\t\t\tdebug(\"User accepted message\")\n\t\t\treturn message\n\t\t}\n\n\t\tif (review === \"edit\") {\n\t\t\tmessage = (await handleEdit(message)) ?? message\n\t\t}\n\n\t\tif (review === \"regenerate\" && options?.regenerate) {\n\t\t\tmessage = (await handleRegenerate(options.regenerate)) ?? message\n\t\t}\n\t}\n}\n","import { isCancel, log, outro, spinner } from \"@clack/prompts\"\nimport { dim, green, red } from \"kolorist\"\nimport { generateCommitMessage } from \"../services/ai.js\"\nimport { detectConfig, runAllChecks } from \"../services/checks.js\"\nimport {\n\tgetModelForProvider,\n\tgetProviderApiKey,\n\treadConfig,\n\tsetConfigValue,\n} from \"../services/config.js\"\nimport {\n\tattemptCommit,\n\tattemptCommitNoVerify,\n\ttype ChangedFile,\n\tgetDefaultExcludes,\n\tgetHead,\n\tgetStagedDiff,\n\tresetStaging,\n\tstageFiles,\n} from \"../services/git.js\"\nimport { filterExcludedFiles, generateGroups, validateGroups } from \"../services/grouping.js\"\nimport { createProgressHandler } from \"../services/hook-progress.js\"\nimport { parseCheckErrors, parseHookErrors, parseToolChecks } from \"../services/hooks.js\"\nimport {\n\tformatProviderName,\n\tisValidProvider,\n\tPROVIDER_CONFIGS,\n\tPROVIDER_ENV_KEYS,\n\ttype ProviderName,\n} from \"../services/provider.js\"\nimport { showCheckFailureMenu } from \"../ui/check-failure-menu.js\"\nimport { stopCheckSpinner } from \"../ui/check-summary.js\"\nimport { showGroupedFiles, showGroupingConfirmation, showGroupProgress } from \"../ui/grouping.js\"\nimport { type RecoveryResult, showRecoveryMenu } from \"../ui/recovery-menu.js\"\nimport { reviewCommitMessage } from \"../ui/review-message.js\"\nimport { saveCachedCommit } from \"../utils/cache.js\"\nimport { debug } from \"../utils/debug.js\"\n\nexport interface CommitFlags {\n\tretry: boolean\n\tauto: boolean\n\tagent: boolean\n\tmessage?: string\n\thint?: string\n\tnoCheck?: boolean\n}\n\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Multi-step auto-group flow with sequential commits, review, and recovery\n// biome-ignore lint/complexity/noExcessiveLinesPerFunction: Sequential multi-commit loop with review, cache, and recovery\nexport async function runAutoGroupFlow(\n\tchangedFiles: ChangedFile[],\n\tflags: CommitFlags,\n): Promise<RecoveryResult> {\n\t// Step 1: Filter excluded files\n\tconst { included, excluded } = filterExcludedFiles(changedFiles)\n\n\t// Step 1b: Commit excluded files with hardcoded message before grouping\n\tif (excluded.length > 0) {\n\t\tdebug(\"Committing %d excluded files upfront:\", excluded.length, excluded)\n\t\tconst message = buildExcludedFilesMessage(excluded)\n\n\t\tlog.info(excluded.map((f) => ` ${f}`).join(\"\\n\"))\n\n\t\tawait resetStaging()\n\t\tawait stageFiles(excluded)\n\n\t\tconst headBefore = await getHead()\n\t\tconst commitResult = await attemptCommit(message)\n\t\tconst headAfter = await getHead()\n\n\t\tif (commitResult.ok || headBefore !== headAfter) {\n\t\t\tdebug(\"Excluded files committed:\", message)\n\t\t\tlog.success(dim(message))\n\t\t} else {\n\t\t\tdebug(\"Excluded files commit failed, continuing without them\")\n\t\t\tlog.warn(red(\"Failed to commit excluded files.\"))\n\t\t}\n\t}\n\n\t// If only excluded files existed, we're done\n\tif (included.length === 0) {\n\t\tdebug(\"No included files to group, done\")\n\t\tif (excluded.length > 0) {\n\t\t\toutro(green(\"Committed excluded files. No other changes to group.\"))\n\t\t} else {\n\t\t\toutro(dim(\"Nothing to commit.\"))\n\t\t}\n\t\treturn \"committed\"\n\t}\n\n\t// Run user-defined pre-commit checks upfront on all files (before AI grouping)\n\tif (!flags.noCheck) {\n\t\tconst { getRepoRoot } = await import(\"../services/git.js\")\n\t\tconst repoRoot = await getRepoRoot()\n\t\tconst allFiles = included.filter((f) => f.status !== \"D\").map((f) => f.path)\n\t\t// Only show check UI when a cmintrc config actually exists\n\t\tconst configPath = await detectConfig(repoRoot)\n\t\tif (configPath) {\n\t\t\tdebug(\"Running user checks on %d files...\", allFiles.length)\n\t\t\tconst ck = spinner()\n\t\t\tck.start(\"Running checks...\")\n\t\t\tlet checkResults = await runAllChecks(repoRoot, allFiles, 60000)\n\t\t\tdebug(\"Check results: ok=%s, count=%d\", checkResults.ok, checkResults.results.length)\n\n\t\t\twhile (!checkResults.ok) {\n\t\t\t\tconst failed = checkResults.results.filter((r) => !r.ok)\n\t\t\t\tck.stop(`${failed.length} check(s) failed`)\n\t\t\t\tconst rawOutput = failed\n\t\t\t\t\t.map((r) => `[${r.tool}]\\n${r.stdout}\\n${r.stderr}`.trim())\n\t\t\t\t\t.join(\"\\n\\n\")\n\t\t\t\tconst checkErrors = parseCheckErrors(rawOutput)\n\t\t\t\tconst menuResult = await showCheckFailureMenu(checkErrors, rawOutput, async () => {\n\t\t\t\t\tconst retryResult = await runAllChecks(repoRoot, allFiles, 60000)\n\t\t\t\t\treturn retryResult.ok\n\t\t\t\t})\n\t\t\t\tif (menuResult === \"cancelled\") {\n\t\t\t\t\treturn \"cancelled\"\n\t\t\t\t}\n\t\t\t\tif (menuResult === \"retried\") {\n\t\t\t\t\tdebug(\"Re-running checks after retry...\")\n\t\t\t\t\tck.start(\"Running checks...\")\n\t\t\t\t\tcheckResults = await runAllChecks(repoRoot, allFiles, 60000)\n\t\t\t\t\tdebug(\n\t\t\t\t\t\t\"Retry check results: ok=%s, count=%d\",\n\t\t\t\t\t\tcheckResults.ok,\n\t\t\t\t\t\tcheckResults.results.length,\n\t\t\t\t\t)\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\t// \"skipped\" → continue to grouping and commits\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tif (checkResults.ok) {\n\t\t\t\tstopCheckSpinner(ck, checkResults)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Step 2: Read config and determine provider\n\tconst config = await readConfig()\n\tconst resolvedProvider = config.provider ?? \"groq\"\n\tconst provider: ProviderName = isValidProvider(resolvedProvider) ? resolvedProvider : \"groq\"\n\n\t// Step 3: Ensure API key\n\ttry {\n\t\tawait getProviderApiKey(provider)\n\t\tdebug(\"API key found\")\n\t} catch {\n\t\tdebug(\"No API key found, prompting user\")\n\t\tconst { text: promptText } = await import(\"@clack/prompts\")\n\t\tconst key = await promptText({\n\t\t\tmessage: `Enter your ${formatProviderName(provider)} API key:`,\n\t\t\tplaceholder: provider === \"groq\" ? \"gsk_...\" : \"...\",\n\t\t\tvalidate: (v) => (v?.trim() ? undefined : \"API key is required\"),\n\t\t})\n\t\tif (isCancel(key)) {\n\t\t\toutro(dim(\"Cancelled.\"))\n\t\t\treturn \"cancelled\"\n\t\t}\n\t\tconst configKey = PROVIDER_ENV_KEYS[provider]\n\t\tawait setConfigValue(configKey, String(key).trim())\n\t\tdebug(\"API key saved to config\")\n\t}\n\n\t// Step 4: Call grouping service\n\tconst s = spinner()\n\ts.start(\"Analyzing files...\")\n\tconst apiKey = await getProviderApiKey(provider)\n\tconst result = await generateGroups(\n\t\tincluded,\n\t\tapiKey,\n\t\tgetModelForProvider(config, provider, PROVIDER_CONFIGS[provider].defaultModel),\n\t\tconfig.timeout ? parseInt(config.timeout, 10) : undefined,\n\t\tprovider,\n\t\tconfig.proxy,\n\t)\n\tconst validatedGroups = validateGroups(result.groups, included)\n\ts.stop(\"Files analyzed\")\n\n\tshowGroupedFiles(validatedGroups, included)\n\n\t// Step 5: Show grouping confirmation (skip in auto mode)\n\tif (flags.auto) {\n\t\tdebug(\"Auto mode: skipping grouping confirmation\")\n\t} else {\n\t\tconst confirmed = await showGroupingConfirmation(validatedGroups, excluded)\n\t\tif (!confirmed) {\n\t\t\toutro(dim(\"Cancelled.\"))\n\t\t\treturn \"cancelled\"\n\t\t}\n\t}\n\n\t// Step 6: Sequential multi-commit loop\n\tfor (let i = 0; i < validatedGroups.length; i++) {\n\t\tconst group = validatedGroups[i]\n\t\tshowGroupProgress(i + 1, validatedGroups.length, group.name)\n\n\t\t// Unstage everything first, then stage only this group's files\n\t\tawait resetStaging()\n\t\tawait stageFiles(group.files)\n\n\t\t// Get diff for this group\n\t\tconst diffResult = await getStagedDiff()\n\t\tif (!diffResult || \"excludedFiles\" in diffResult) {\n\t\t\tlog.warn(red(`No changes found for group \"${group.name}\" — skipping.`))\n\t\t\tcontinue\n\t\t}\n\n\t\t// Generate message\n\t\ts.start(\"Generating commit message...\")\n\t\tlet message: string\n\t\ttry {\n\t\t\tmessage = await generateMessage(diffResult.diff, flags.hint)\n\t\t} catch (err) {\n\t\t\ts.stop(red(\"Failed to generate message.\"))\n\t\t\toutro(red(err instanceof Error ? err.message : String(err)))\n\t\t\treturn \"cancelled\"\n\t\t}\n\t\ts.stop(\"Message generated\")\n\t\tlog.info(dim(message))\n\n\t\t// Review message (skip in auto mode)\n\t\tif (flags.auto) {\n\t\t\tdebug(\"Auto mode: accepting generated message\")\n\t\t} else {\n\t\t\tconst reviewed = await reviewCommitMessage(message, {\n\t\t\t\tregenerate: async (hint) => {\n\t\t\t\t\tconst combinedHint = flags.hint ? `${flags.hint}\\n${hint}` : hint\n\t\t\t\t\tdebug(\"Regenerating with combined hint:\", combinedHint)\n\t\t\t\t\ts.start(\"Regenerating commit message...\")\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst newMessage = await generateMessage(diffResult.diff, combinedHint)\n\t\t\t\t\t\ts.stop(\"Message regenerated\")\n\t\t\t\t\t\treturn newMessage\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\ts.stop(red(\"Regeneration failed\"))\n\t\t\t\t\t\tthrow err\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t})\n\t\t\tif (reviewed === null) {\n\t\t\t\toutro(dim(\"Cancelled.\"))\n\t\t\t\treturn \"cancelled\"\n\t\t\t}\n\t\t\tmessage = reviewed\n\t\t}\n\n\t\t// Cache message\n\t\tconst { getRepoRoot } = await import(\"../services/git.js\")\n\t\tconst repoRoot = await getRepoRoot()\n\t\tawait saveCachedCommit(repoRoot, message)\n\n\t\t// Attempt commit\n\t\ts.start(\"Running pre-commit hooks...\")\n\t\tconst headBefore = await getHead()\n\t\tconst commitResult = await attemptCommit(message, [], createProgressHandler(s))\n\t\tconst headAfter = await getHead()\n\n\t\tif (commitResult.ok || headBefore !== headAfter) {\n\t\t\ts.stop(\"Committed successfully.\")\n\t\t\tconst checks = parseToolChecks(commitResult.stderr ?? \"\")\n\t\t\tif (checks.length > 0) {\n\t\t\t\tconst lines = checks.map((c) => ` ${c.ok ? green(\"✓\") : red(\"✗\")} ${c.tool}`)\n\t\t\t\tlog.info(lines.join(\"\\n\"))\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\t// Hook failure — stop sequence, show recovery menu\n\t\ts.stop(\"Commit failed.\")\n\t\tconst errors = parseHookErrors(commitResult.stderr ?? \"\")\n\t\tconst recoveryResult = await showRecoveryMenu(\n\t\t\terrors,\n\t\t\tasync () => (await attemptCommit(message)).ok,\n\t\t\tasync (msg) => (await attemptCommitNoVerify(msg)).ok,\n\t\t\tasync () => {\n\t\t\t\tawait stageFiles(group.files)\n\t\t\t\treturn (await attemptCommit(message)).ok\n\t\t\t},\n\t\t\tmessage,\n\t\t\tcommitResult.stderr ?? \"\",\n\t\t)\n\t\tif (recoveryResult === \"committed\") {\n\t\t\tif (i < validatedGroups.length - 1) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn \"committed\"\n\t\t}\n\t\treturn recoveryResult\n\t}\n\n\toutro(green(\"All groups committed.\"))\n\treturn \"committed\"\n}\n\nexport async function generateMessage(diff: string, hint?: string): Promise<string> {\n\tconst config = await readConfig()\n\tconst resolvedProvider = config.provider ?? \"groq\"\n\tconst provider: ProviderName = isValidProvider(resolvedProvider) ? resolvedProvider : \"groq\"\n\tconst apiKey = await getProviderApiKey(provider)\n\tconst model = getModelForProvider(config, provider, PROVIDER_CONFIGS[provider].defaultModel)\n\tdebug(\"Generating message with provider:\", provider, \"model:\", model, \"type:\", config.type)\n\n\treturn generateCommitMessage(diff, {\n\t\tapiKey,\n\t\tmodel,\n\t\ttype: config.type,\n\t\ttimeout: config.timeout ? parseInt(config.timeout, 10) : undefined,\n\t\thint,\n\t\tprovider,\n\t\tproxy: config.proxy,\n\t})\n}\n\nexport function buildExcludedFilesMessage(files: string[]): string {\n\tconst excludes = getDefaultExcludes()\n\tconst isLockfile = (f: string) =>\n\t\texcludes.some((pattern) => {\n\t\t\tif (pattern.endsWith(\".lock\") || pattern.endsWith(\".json\")) {\n\t\t\t\treturn f === pattern || f.endsWith(pattern.replace(\"*.\", \".\"))\n\t\t\t}\n\t\t\treturn false\n\t\t})\n\n\tif (files.every(isLockfile)) {\n\t\treturn \"chore: update lockfile\"\n\t}\n\n\treturn \"chore: update generated files\"\n}\n","import { generateCommitMessage } from \"../services/ai.js\"\nimport { detectConfig, runAllChecks } from \"../services/checks.js\"\nimport { getModelForProvider, getProviderApiKey, readConfig } from \"../services/config.js\"\nimport {\n\tassertGitRepo,\n\tattemptCommit,\n\tgetChangedFiles,\n\tgetHead,\n\tgetRepoRoot,\n\tgetStagedDiff,\n\tgetStatusShort,\n\tresetStaging,\n\tstageFiles,\n} from \"../services/git.js\"\nimport {\n\ttype CommitGroup,\n\tfilterExcludedFiles,\n\tgenerateGroups,\n\tvalidateGroups,\n} from \"../services/grouping.js\"\nimport { parseCheckErrors, parseHookErrors } from \"../services/hooks.js\"\nimport {\n\tisValidProvider,\n\tPROVIDER_CONFIGS,\n\tPROVIDER_ENV_KEYS,\n\ttype ProviderName,\n} from \"../services/provider.js\"\nimport { type AgentCommit, EXIT_CODES, writeAgentResult } from \"../utils/agent.js\"\nimport { saveCachedCommit } from \"../utils/cache.js\"\nimport { debug } from \"../utils/debug.js\"\nimport { buildExcludedFilesMessage, type CommitFlags } from \"./auto-group.js\"\n\n/**\n * Headless agent command — orchestrates the entire commit flow without any TUI\n * interaction. Emits structured JSON results to stdout, one per line. Returns\n * control to the caller with `process.exitCode` set to one of the 7 documented\n * exit codes (0=success, 1=generic, 2=no_changes, 3=git, 4=ai, 5=check, 6=hook).\n */\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Multi-phase state machine (validate→stage→diff→exclude→message→check→group→commit)\n// biome-ignore lint/complexity/noExcessiveLinesPerFunction: Sequential orchestration with no helper extraction (per task spec)\nexport async function agentCommand(flags: CommitFlags): Promise<void> {\n\tdebug(\"agentCommand called\", { flags })\n\n\t// 1. Validate flags\n\tif (flags.retry) {\n\t\tprocess.exitCode = EXIT_CODES.GENERIC\n\t\twriteAgentResult({\n\t\t\tstatus: \"failure\",\n\t\t\tcommits: [],\n\t\t\terrors: [\"--agent is not compatible with --retry\"],\n\t\t})\n\t\treturn\n\t}\n\n\t// 2. Assert git repo\n\ttry {\n\t\tawait assertGitRepo()\n\t} catch (err) {\n\t\tprocess.exitCode = EXIT_CODES.GIT\n\t\twriteAgentResult({\n\t\t\tstatus: \"failure\",\n\t\t\tcommits: [],\n\t\t\terrors: [err instanceof Error ? err.message : String(err)],\n\t\t})\n\t\treturn\n\t}\n\n\t// 3. Check status\n\tconst status = await getStatusShort()\n\tdebug(\"Git status:\", status || \"(empty)\")\n\tif (!status) {\n\t\tprocess.exitCode = EXIT_CODES.NO_CHANGES\n\t\twriteAgentResult({ status: \"no_changes\", commits: [] })\n\t\treturn\n\t}\n\n\t// 4. Auto-stage all changed files\n\tconst changedFiles = await getChangedFiles()\n\tdebug(\"Changed files:\", changedFiles.length)\n\tawait stageFiles(changedFiles.map((f) => f.path))\n\n\t// 5. Get diff (3-way union: StagedDiffResult | ExcludedFilesResult | null)\n\tconst diffResult = await getStagedDiff()\n\tif (!diffResult) {\n\t\tprocess.exitCode = EXIT_CODES.NO_CHANGES\n\t\twriteAgentResult({ status: \"no_changes\", commits: [] })\n\t\treturn\n\t}\n\n\t// Handle ExcludedFilesResult (all staged files are excluded) — hardcoded message\n\tif (\"excludedFiles\" in diffResult) {\n\t\tdebug(\"All staged files are excluded:\", diffResult.excludedFiles)\n\t\tconst message = buildExcludedFilesMessage(diffResult.excludedFiles)\n\n\t\tconst headBefore = await getHead()\n\t\tconst result = await attemptCommit(message)\n\t\tconst headAfter = await getHead()\n\n\t\tif (result.ok || headBefore !== headAfter) {\n\t\t\tprocess.exitCode = EXIT_CODES.SUCCESS\n\t\t\twriteAgentResult({\n\t\t\t\tstatus: \"success\",\n\t\t\t\tcommits: [{ message, hash: headAfter ?? \"\", files: diffResult.excludedFiles }],\n\t\t\t})\n\t\t} else {\n\t\t\tprocess.exitCode = EXIT_CODES.HOOK\n\t\t\tconst errors = parseHookErrors(result.stderr ?? \"\")\n\t\t\twriteAgentResult({\n\t\t\t\tstatus: \"failure\",\n\t\t\t\tcommits: [],\n\t\t\t\terrors: errors.map((e) => `[${e.tool}] ${e.message}`),\n\t\t\t})\n\t\t}\n\t\treturn\n\t}\n\n\t// 6. Handle --message (single-commit mode: skip AI + auto-group)\n\tif (flags.message) {\n\t\tdebug(\"Using provided message:\", flags.message)\n\t\tconst headBefore = await getHead()\n\t\tconst result = await attemptCommit(flags.message)\n\t\tconst headAfter = await getHead()\n\n\t\tif (result.ok || headBefore !== headAfter) {\n\t\t\tprocess.exitCode = EXIT_CODES.SUCCESS\n\t\t\twriteAgentResult({\n\t\t\t\tstatus: \"success\",\n\t\t\t\tcommits: [{ message: flags.message, hash: headAfter ?? \"\", files: diffResult.files }],\n\t\t\t})\n\t\t} else {\n\t\t\tprocess.exitCode = EXIT_CODES.HOOK\n\t\t\tconst errors = parseHookErrors(result.stderr ?? \"\")\n\t\t\twriteAgentResult({\n\t\t\t\tstatus: \"failure\",\n\t\t\t\tcommits: [],\n\t\t\t\terrors: errors.map((e) => `[${e.tool}] ${e.message}`),\n\t\t\t})\n\t\t}\n\t\treturn\n\t}\n\n\t// 7. Run user-defined pre-commit checks (unless --noCheck)\n\tif (!flags.noCheck) {\n\t\tconst repoRoot = await getRepoRoot()\n\t\tconst configPath = await detectConfig(repoRoot)\n\t\tif (configPath) {\n\t\t\tdebug(\"Running user checks on changed files...\")\n\t\t\tconst allFiles = changedFiles.filter((f) => f.status !== \"D\").map((f) => f.path)\n\t\t\tconst checkResults = await runAllChecks(repoRoot, allFiles, 60000)\n\t\t\tif (!checkResults.ok) {\n\t\t\t\tconst failed = checkResults.results.filter((r) => !r.ok)\n\t\t\t\tconst errorMessages = failed\n\t\t\t\t\t.map((r) => `[${r.tool}]\\n${r.stdout}\\n${r.stderr}`.trim())\n\t\t\t\t\t.filter(Boolean)\n\t\t\t\tconst parsed = parseCheckErrors(errorMessages.join(\"\\n\\n\"))\n\t\t\t\tconst errors =\n\t\t\t\t\tparsed.length > 0 ? parsed.map((e) => `[${e.tool}] ${e.message}`) : errorMessages\n\t\t\t\tprocess.exitCode = EXIT_CODES.CHECK\n\t\t\t\twriteAgentResult({ status: \"failure\", commits: [], errors })\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n\n\t// 8. Auto-group flow\n\t// Step 8a: Filter and commit excluded files\n\tconst { included, excluded } = filterExcludedFiles(changedFiles)\n\tdebug(\"Auto-group: %d included, %d excluded\", included.length, excluded.length)\n\n\tif (excluded.length > 0) {\n\t\tconst message = buildExcludedFilesMessage(excluded)\n\t\tdebug(\"Committing %d excluded files:\", excluded.length, excluded)\n\t\tawait resetStaging()\n\t\tawait stageFiles(excluded)\n\n\t\tconst headBefore = await getHead()\n\t\tconst result = await attemptCommit(message)\n\t\tconst headAfter = await getHead()\n\t\tif (!result.ok && headBefore === headAfter) {\n\t\t\tdebug(\"Excluded files commit failed, continuing without them\")\n\t\t}\n\t}\n\n\t// If only excluded files existed, we're done\n\tif (included.length === 0) {\n\t\tprocess.exitCode = EXIT_CODES.SUCCESS\n\t\twriteAgentResult({ status: \"success\", commits: [] })\n\t\treturn\n\t}\n\n\t// Step 8b: Read config and resolve provider\n\tconst config = await readConfig()\n\tconst provider: ProviderName = isValidProvider(config.provider ?? \"groq\")\n\t\t? (config.provider as ProviderName)\n\t\t: \"groq\"\n\n\t// Step 8c: Get API key (fail with AI exit code if missing)\n\tlet apiKey: string\n\ttry {\n\t\tapiKey = await getProviderApiKey(provider)\n\t} catch {\n\t\tprocess.exitCode = EXIT_CODES.AI\n\t\twriteAgentResult({\n\t\t\tstatus: \"failure\",\n\t\t\tcommits: [],\n\t\t\terrors: [\n\t\t\t\t`No API key found for ${provider}. Set ${PROVIDER_ENV_KEYS[provider]} env var or run 'cmint config'`,\n\t\t\t],\n\t\t})\n\t\treturn\n\t}\n\n\tconst model = getModelForProvider(config, provider, PROVIDER_CONFIGS[provider].defaultModel)\n\tconst timeout = config.timeout ? parseInt(config.timeout, 10) : undefined\n\n\t// Step 8d: Generate groups via AI\n\tlet groups: CommitGroup[]\n\ttry {\n\t\tconst result = await generateGroups(included, apiKey, model, timeout, provider, config.proxy)\n\t\tgroups = validateGroups(result.groups, included)\n\t} catch (err) {\n\t\tprocess.exitCode = EXIT_CODES.AI\n\t\twriteAgentResult({\n\t\t\tstatus: \"failure\",\n\t\t\tcommits: [],\n\t\t\terrors: [err instanceof Error ? err.message : String(err)],\n\t\t})\n\t\treturn\n\t}\n\n\t// Step 8e: Sequential per-group commits\n\tconst commits: AgentCommit[] = []\n\tfor (const group of groups) {\n\t\tdebug(\"Processing group %d/%d: %s\", commits.length + 1, groups.length, group.name)\n\n\t\t// Unstage everything first, then stage only this group's files\n\t\tawait resetStaging()\n\t\tawait stageFiles(group.files)\n\n\t\t// Get diff for this group\n\t\tconst groupDiff = await getStagedDiff()\n\t\tif (!groupDiff || \"excludedFiles\" in groupDiff) {\n\t\t\tdebug(`Skipping group \"${group.name}\" — no diff`)\n\t\t\tcontinue\n\t\t}\n\n\t\t// Generate message (auto-accept — no review step in agent mode)\n\t\tlet message: string\n\t\ttry {\n\t\t\tmessage = await generateCommitMessage(groupDiff.diff, {\n\t\t\t\tapiKey,\n\t\t\t\tmodel,\n\t\t\t\ttype: config.type,\n\t\t\t\ttimeout,\n\t\t\t\thint: flags.hint,\n\t\t\t\tprovider,\n\t\t\t\tproxy: config.proxy,\n\t\t\t})\n\t\t} catch (err) {\n\t\t\tprocess.exitCode = EXIT_CODES.AI\n\t\t\twriteAgentResult({\n\t\t\t\tstatus: \"failure\",\n\t\t\t\tcommits,\n\t\t\t\terrors: [err instanceof Error ? err.message : String(err)],\n\t\t\t})\n\t\t\treturn\n\t\t}\n\n\t\t// Cache message\n\t\tconst repoRoot = await getRepoRoot()\n\t\tawait saveCachedCommit(repoRoot, message)\n\n\t\t// Attempt commit (no recovery menu in agent mode)\n\t\tconst headBefore = await getHead()\n\t\tconst result = await attemptCommit(message)\n\t\tconst headAfter = await getHead()\n\n\t\tif (result.ok || headBefore !== headAfter) {\n\t\t\tcommits.push({ message, hash: headAfter ?? \"\", files: group.files, groupName: group.name })\n\t\t\tcontinue\n\t\t}\n\n\t\t// Hook failure — cancel sequence (no skip, no recovery)\n\t\tprocess.exitCode = EXIT_CODES.HOOK\n\t\tconst errors = parseHookErrors(result.stderr ?? \"\")\n\t\twriteAgentResult({\n\t\t\tstatus: \"failure\",\n\t\t\tcommits,\n\t\t\terrors: errors.map((e) => `[${e.tool}] ${e.message}`),\n\t\t})\n\t\treturn\n\t}\n\n\t// 9. Success\n\tprocess.exitCode = EXIT_CODES.SUCCESS\n\twriteAgentResult({ status: \"success\", commits })\n}\n","import { mkdirSync, readFileSync, writeFileSync } from \"node:fs\"\nimport os from \"node:os\"\nimport { dirname, join } from \"node:path\"\nimport { log, spinner } from \"@clack/prompts\"\nimport { cyan, green, yellow } from \"kolorist\"\nimport semver from \"semver\"\nimport { debug } from \"../utils/debug.js\"\n\n// Dist-tags endpoint returns `{\"latest\":\"X.Y.Z\",\"next\":\"...\", ...}` — the only\n// npm registry URL whose body actually contains a `latest` field. The\n// `/<package>/latest` endpoint returns the full package manifest (which has\n// `version`, not `latest`), so it can't be used here without changing the\n// parser. The `/-/package/` prefix works for both scoped and unscoped names.\nconst REGISTRY_URL = \"https://registry.npmjs.org/-/package/@kyubiware/commit-mint/dist-tags\"\nconst _PACKAGE_NAME = \"@kyubiware/commit-mint\"\nconst FRESH_MS = 60 * 60 * 1000\nconst STALE_MS = 24 * 60 * 60 * 1000\nconst FETCH_TIMEOUT_MS = 5000\n\ninterface CacheEntry {\n\tlatest: string\n\tcheckedAt: number\n}\n\nlet cachePath = join(os.homedir(), \".cache\", \"commit-mint\", \"update-check.json\")\nlet fetchImpl: typeof fetch = globalThis.fetch\n\n/** Override cache file path (used by tests to avoid polluting real cache). */\nexport function setCachePath(path: string): void {\n\tcachePath = path\n}\n\n/** Override fetch implementation (used by tests to avoid real network). */\nexport function setFetchImpl(fn: typeof fetch): void {\n\tfetchImpl = fn\n}\n\n/**\n * Returns true when the notifier must not run: env opt-out, CI, test env,\n * non-TTY stderr, or an invalid/missing current version.\n */\nexport function shouldSkip(currentVersion: string): boolean {\n\tconst noUpdate = process.env.NO_UPDATE_NOTIFIER\n\tif (noUpdate !== undefined && noUpdate !== \"\") {\n\t\treturn true\n\t}\n\tconst ci = process.env.CI\n\tif (ci !== undefined && ci !== \"\" && ci !== \"0\") {\n\t\treturn true\n\t}\n\tif (process.env.NODE_ENV === \"test\") {\n\t\treturn true\n\t}\n\tif (process.stderr.isTTY !== true) {\n\t\treturn true\n\t}\n\tif (currentVersion === undefined) {\n\t\treturn true\n\t}\n\tif (currentVersion === \"\") {\n\t\treturn true\n\t}\n\tif (semver.valid(currentVersion) === null) {\n\t\treturn true\n\t}\n\treturn false\n}\n\nfunction loadCache(): Promise<CacheEntry | null> {\n\ttry {\n\t\tconst raw = readFileSync(cachePath, \"utf8\")\n\t\tconst parsed: unknown = JSON.parse(raw)\n\t\tif (\n\t\t\tparsed !== null &&\n\t\t\ttypeof parsed === \"object\" &&\n\t\t\ttypeof (parsed as CacheEntry).latest === \"string\" &&\n\t\t\ttypeof (parsed as CacheEntry).checkedAt === \"number\"\n\t\t) {\n\t\t\tconst entry = parsed as CacheEntry\n\t\t\tconst ageH = ((Date.now() - entry.checkedAt) / 3_600_000).toFixed(2)\n\t\t\tdebug(\"loadCache: hit — latest=%s, age=%sh\", entry.latest, ageH)\n\t\t\treturn Promise.resolve(entry)\n\t\t}\n\t\tdebug(\"loadCache: miss — malformed entry\")\n\t\treturn Promise.resolve(null)\n\t} catch {\n\t\tdebug(\"loadCache: miss — %s does not exist\", cachePath)\n\t\treturn Promise.resolve(null)\n\t}\n}\n\nfunction saveCache(entry: CacheEntry): Promise<void> {\n\ttry {\n\t\tmkdirSync(dirname(cachePath), { recursive: true })\n\t\twriteFileSync(cachePath, JSON.stringify(entry), \"utf8\")\n\t\tdebug(\"saveCache: wrote latest=%s to %s\", entry.latest, cachePath)\n\t} catch (err) {\n\t\tdebug(\"saveCache: failed — %s\", err instanceof Error ? err.message : String(err))\n\t\t// Silently ignore: EACCES, ENOSPC, etc. The nag is best-effort.\n\t}\n\treturn Promise.resolve()\n}\n\n/**\n * Fetch latest version from the registry. Aborts on FETCH_TIMEOUT_MS or when\n * `parentSignal` aborts (user keypress). Returns null on any failure so the\n * caller can degrade silently.\n */\nasync function fetchLatest(parentSignal?: AbortSignal): Promise<string | null> {\n\tdebug(\"fetchLatest: GET %s (timeout=%dms)\", REGISTRY_URL, FETCH_TIMEOUT_MS)\n\ttry {\n\t\tconst controller = new AbortController()\n\t\tconst timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS)\n\n\t\t// Wire parent abort (user keypress) → fetch abort.\n\t\tconst onParentAbort = () => controller.abort()\n\t\tif (parentSignal) {\n\t\t\tif (parentSignal.aborted) {\n\t\t\t\tcontroller.abort()\n\t\t\t} else {\n\t\t\t\tparentSignal.addEventListener(\"abort\", onParentAbort, { once: true })\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\tconst response = await fetchImpl(REGISTRY_URL, { signal: controller.signal })\n\t\t\tif (!response.ok) {\n\t\t\t\tdebug(\"fetchLatest: HTTP %d — returning null\", response.status)\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst data = (await response.json()) as { latest?: unknown }\n\t\t\tif (typeof data.latest !== \"string\") {\n\t\t\t\tdebug(\"fetchLatest: response missing 'latest' field — returning null\")\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tdebug(\"fetchLatest: ok — latest=%s\", data.latest)\n\t\t\treturn data.latest\n\t\t} finally {\n\t\t\tclearTimeout(timer)\n\t\t\tif (parentSignal) parentSignal.removeEventListener(\"abort\", onParentAbort)\n\t\t}\n\t} catch (err) {\n\t\tconst msg = err instanceof Error ? err.message : String(err)\n\t\tdebug(\"fetchLatest: error — %s\", msg)\n\t\treturn null\n\t}\n}\n\nfunction displayNag(current: string, latest: string): void {\n\tdebug(\"displayNag: %s → %s\", current, latest)\n\tconst message =\n\t\t`Update available: ${yellow(current)} → ${green(latest)}\\n` +\n\t\t`Run ${cyan(\"cmint update\")} to update`\n\tlog.warn(message)\n}\n\n/**\n * Fire-and-forget cache refresh used by the stale-while-revalidate (SWR) band\n * (cache age in [FRESH_MS, STALE_MS)). Runs the registry fetch and writes a\n * fresh cache entry without awaiting — the caller returns immediately with\n * the cached `latest` so the nag decision is fast.\n *\n * Wrapped in try/catch and `void`-ed so the floating promise NEVER rejects\n * (vitest fails the suite on unhandled rejections). On any failure (network,\n * HTTP non-ok, malformed JSON, fs write error) the cache file is left\n * unchanged and the failure is logged via {@link debug} only.\n *\n * No abort signal is wired here — the cancellable spinner only runs on the\n * STALE blocking-fetch path, and FRESH/SWR callers explicitly want this to\n * complete in the background regardless of user keystrokes.\n */\nfunction refreshCacheInBackground(): void {\n\tdebug(\"refreshCacheInBackground: starting fire-and-forget refresh\")\n\tvoid (async () => {\n\t\ttry {\n\t\t\tconst latest = await fetchLatest()\n\t\t\tif (latest === null) {\n\t\t\t\tdebug(\"refreshCacheInBackground: fetch returned null, leaving cache unchanged\")\n\t\t\t\treturn\n\t\t\t}\n\t\t\tawait saveCache({ latest, checkedAt: Date.now() })\n\t\t\tdebug(\"refreshCacheInBackground: refreshed cache to latest=%s\", latest)\n\t\t} catch (err) {\n\t\t\tconst msg = err instanceof Error ? err.message : String(err)\n\t\t\tdebug(\"refreshCacheInBackground: failed — %s\", msg)\n\t\t}\n\t})()\n}\n\n/**\n * Outcome of an update check. Callers use this to decide which (if any)\n * non-nag message to show — e.g. \"You are on the latest version\" is only\n * appropriate after a real fetch, not on a cache hit.\n */\nexport type UpdateCheckStatus =\n\t| \"skipped\"\n\t| \"cache-update\"\n\t| \"cache-current\"\n\t| \"fetch-update\"\n\t| \"fetch-current\"\n\t| \"fetch-failed-or-aborted\"\n\t| \"error\"\n\n/**\n * Resolve the cache-hit branch (FRESH / SWR / stale-or-missing). Returns\n * `null` when the caller must fall through to the blocking-fetch path; returns\n * a {@link UpdateCheckStatus} when the cache hit is terminal.\n *\n * Side effect: kicks off a fire-and-forget {@link refreshCacheInBackground}\n * when age is in the SWR band [FRESH_MS, STALE_MS).\n */\nfunction resolveCacheHit(\n\tcached: CacheEntry | null,\n\tcurrentVersion: string,\n\tonNag: (current: string, latest: string) => void,\n): UpdateCheckStatus | null {\n\tif (cached === null) {\n\t\tdebug(\"runUpdateCheck: no cache, fetching\")\n\t\treturn null\n\t}\n\tconst age = Date.now() - cached.checkedAt\n\tif (age >= STALE_MS) {\n\t\tdebug(\"runUpdateCheck: cache stale (>=%dh), refetching\", STALE_MS / 3_600_000)\n\t\treturn null\n\t}\n\t// Cache-hit band: FRESH (<1h) → silent; SWR (1h–24h) → serve +\n\t// fire-and-forget background refresh for the next invocation.\n\tif (age < FRESH_MS) {\n\t\tdebug(\"runUpdateCheck: cache fresh (<%dh), serving from cache\", FRESH_MS / 3_600_000)\n\t} else {\n\t\tdebug(\n\t\t\t\"runUpdateCheck: cache in SWR band (<%dh), serving + background refresh\",\n\t\t\tSTALE_MS / 3_600_000,\n\t\t)\n\t\trefreshCacheInBackground()\n\t}\n\tif (semver.gt(cached.latest, currentVersion)) {\n\t\tonNag(currentVersion, cached.latest)\n\t\treturn \"cache-update\"\n\t}\n\tdebug(\"runUpdateCheck: current >= latest, no nag\")\n\treturn \"cache-current\"\n}\n\n/**\n * Run the full update check. Exported for tests; the public surface is\n * {@link checkForUpdatesUpfront}. Accepts an optional AbortSignal that\n * propagates to the underlying fetch — used by the cancellable spinner.\n *\n * When an update is available, {@link onNag} is invoked (defaulting to\n * {@link displayNag}). The cancellable spinner path passes a capturing\n * callback so it can stop the spinner BEFORE the nag prints — otherwise\n * `log.warn` interleaves with the spinner line and leaves it on screen.\n *\n * Returns an {@link UpdateCheckStatus} so the caller can distinguish a\n * real fetch that found the user current (eligible for \"You are on the\n * latest version\" feedback) from a silent cache hit.\n */\nexport async function runUpdateCheck(\n\tcurrentVersion: string,\n\tparentSignal?: AbortSignal,\n\tonNag: (current: string, latest: string) => void = displayNag,\n): Promise<UpdateCheckStatus> {\n\tdebug(\"runUpdateCheck: currentVersion=%s\", currentVersion)\n\tif (shouldSkip(currentVersion)) {\n\t\tdebug(\n\t\t\t\"runUpdateCheck: skipped (NO_UPDATE_NOTIFIER / CI / NODE_ENV=test / non-TTY / invalid version)\",\n\t\t)\n\t\treturn \"skipped\"\n\t}\n\ttry {\n\t\tconst cached = await loadCache()\n\t\tconst cacheStatus = resolveCacheHit(cached, currentVersion, onNag)\n\t\tif (cacheStatus !== null) {\n\t\t\treturn cacheStatus\n\t\t}\n\t\tconst latest = await fetchLatest(parentSignal)\n\t\tif (latest === null) {\n\t\t\tdebug(\"runUpdateCheck: fetch returned null, not saving cache\")\n\t\t\treturn \"fetch-failed-or-aborted\"\n\t\t}\n\t\tawait saveCache({ latest, checkedAt: Date.now() })\n\t\tif (semver.gt(latest, currentVersion)) {\n\t\t\tonNag(currentVersion, latest)\n\t\t\treturn \"fetch-update\"\n\t\t}\n\t\tdebug(\"runUpdateCheck: current >= latest, no nag\")\n\t\treturn \"fetch-current\"\n\t} catch (err) {\n\t\t// Silently swallow: update check must never surface errors to the user.\n\t\tdebug(\"runUpdateCheck: unexpected error — %s\", err instanceof Error ? err.message : String(err))\n\t\treturn \"error\"\n\t}\n}\n\n/**\n * Run the update check at startup. Silent when:\n * - skip conditions match (CI, NO_UPDATE_NOTIFIER, NODE_ENV=test, non-TTY\n * stderr, invalid version)\n * - cache is fresh (< 24h old) — only displays nag if update available.\n * A cache-hit-current result produces NO output (no \"latest version\"\n * message), because no actual check was performed.\n * - stdin is non-interactive (piped) — runs silently without spinner, but\n * still shows \"You are on the latest version\" after a successful fetch\n *\n * On a stale/missing cache with interactive stdin, shows a spinner that the\n * user can dismiss by pressing any key. Ctrl+C restores the terminal and\n * exits with conventional code 130.\n */\nexport async function checkForUpdatesUpfront(currentVersion: string): Promise<void> {\n\tdebug(\"checkForUpdatesUpfront: currentVersion=%s\", currentVersion)\n\tif (shouldSkip(currentVersion)) {\n\t\tdebug(\n\t\t\t\"checkForUpdatesUpfront: skipped (NO_UPDATE_NOTIFIER / CI / NODE_ENV=test / non-TTY / invalid version)\",\n\t\t)\n\t\treturn\n\t}\n\n\t// Fast path: cache hit (FRESH or SWR band). Delegate entirely to\n\t// runUpdateCheck so nag + fire-and-forget refresh share one code path.\n\t// The returned status is ignored — \"latest version\" feedback is reserved\n\t// for actual fetches via reportFetchCurrent on the slow path below.\n\tconst cached = await loadCache()\n\tif (cached && Date.now() - cached.checkedAt < STALE_MS) {\n\t\tawait runUpdateCheck(currentVersion)\n\t\treturn\n\t}\n\n\tif (cached) {\n\t\tdebug(\"checkForUpdatesUpfront: cache stale (>=%dh), refetching\", STALE_MS / 3_600_000)\n\t} else {\n\t\tdebug(\"checkForUpdatesUpfront: no cache, fetching\")\n\t}\n\n\t// Slow path: cancellable spinner if stdin is interactive.\n\tconst stdin = process.stdin\n\tif (stdin.isTTY !== true || typeof stdin.setRawMode !== \"function\") {\n\t\tdebug(\"checkForUpdatesUpfront: stdin not interactive, running silent check\")\n\t\tconst status = await runUpdateCheck(currentVersion)\n\t\treportFetchCurrent(status)\n\t\treturn\n\t}\n\n\tawait runCheckWithSpinner(currentVersion)\n}\n\n/**\n * Surface \"You are on the latest version\" feedback only when the check\n * actually performed a fetch and the user is current. Silent on cache hits,\n * skips, failures, and aborts.\n */\nfunction reportFetchCurrent(status: UpdateCheckStatus): void {\n\tif (status === \"fetch-current\") {\n\t\tlog.info(green(\"You are on the latest version\"))\n\t}\n}\n\n/**\n * Attach a \"press any key to skip\" listener to stdin. Returns a cleanup\n * function that restores raw mode + pauses stdin; safe to call multiple times.\n * Returns `failed: true` if raw mode could not be enabled (caller should fall\n * back to a silent check).\n *\n * On any keypress: aborts `controller`. On Ctrl+C (byte 0x03): runs cleanup,\n * stops the spinner with `spinnerMsg`, and exits with conventional code 130.\n */\nfunction attachStdinSkip(\n\tcontroller: AbortController,\n\tspinner: { stop: (msg: string) => void },\n\tspinnerMsg: string,\n): { cleanup: () => void; failed: boolean } {\n\tconst stdin = process.stdin\n\tlet cleanedUp = false\n\n\tconst cleanup = (): void => {\n\t\tif (cleanedUp) return\n\t\tcleanedUp = true\n\t\tstdin.off(\"data\", onData)\n\t\ttry {\n\t\t\tstdin.setRawMode(false)\n\t\t} catch (err) {\n\t\t\tdebug(\n\t\t\t\t\"attachStdinSkip: setRawMode(false) failed — %s\",\n\t\t\t\terr instanceof Error ? err.message : String(err),\n\t\t\t)\n\t\t}\n\t\ttry {\n\t\t\tstdin.pause()\n\t\t} catch {\n\t\t\t// ignore — already paused\n\t\t}\n\t}\n\n\tfunction onData(buffer: Buffer): void {\n\t\tconst byte = buffer[0]\n\t\tdebug(\"attachStdinSkip: stdin byte=0x%s\", byte.toString(16).padStart(2, \"0\"))\n\t\tif (byte === 0x03) {\n\t\t\t// Ctrl+C in raw mode does not auto-generate SIGINT. Restore the\n\t\t\t// terminal before exiting so the user's shell isn't left in raw mode.\n\t\t\tdebug(\"attachStdinSkip: Ctrl+C (0x03), exiting\")\n\t\t\tcleanup()\n\t\t\tspinner.stop(spinnerMsg)\n\t\t\tprocess.exit(130)\n\t\t}\n\t\tdebug(\"attachStdinSkip: user pressed key, aborting check\")\n\t\tcontroller.abort()\n\t}\n\n\ttry {\n\t\tstdin.setRawMode(true)\n\t\tstdin.resume()\n\t\tstdin.on(\"data\", onData)\n\t\treturn { cleanup, failed: false }\n\t} catch (err) {\n\t\tdebug(\n\t\t\t\"attachStdinSkip: setRawMode failed — %s\",\n\t\t\terr instanceof Error ? err.message : String(err),\n\t\t)\n\t\treturn { cleanup: () => {}, failed: true }\n\t}\n}\n\n/**\n * Show a cancellable spinner while the check runs. Puts stdin in raw mode to\n * capture individual keypresses via {@link attachStdinSkip}.\n */\nasync function runCheckWithSpinner(currentVersion: string): Promise<void> {\n\tdebug(\"runCheckWithSpinner: showing cancellable spinner\")\n\tconst s = spinner()\n\ts.start(\"Checking for updates (press any key to skip)\")\n\n\tconst controller = new AbortController()\n\tconst handler = attachStdinSkip(controller, s, \"Cancelled\")\n\n\tif (handler.failed) {\n\t\ts.stop(\"\")\n\t\tconst status = await runUpdateCheck(currentVersion)\n\t\treportFetchCurrent(status)\n\t\treturn\n\t}\n\n\t// Capture the nag instead of printing it immediately. The spinner MUST be\n\t// stopped before any log output, otherwise clack leaves the spinner line\n\t// on screen (log.warn interleaves with the animated spinner). Wrapped in\n\t// a const object so TS doesn't narrow through the callback closure.\n\tconst captured: { nag: { current: string; latest: string } | null } = { nag: null }\n\tlet status: UpdateCheckStatus\n\ttry {\n\t\tstatus = await runUpdateCheck(currentVersion, controller.signal, (current, latest) => {\n\t\t\tcaptured.nag = { current, latest }\n\t\t})\n\t} finally {\n\t\thandler.cleanup()\n\t}\n\n\tif (controller.signal.aborted) {\n\t\tdebug(\"runCheckWithSpinner: spinner dismissed by user\")\n\t\ts.stop(\"Skipped\")\n\t} else if (status === \"fetch-current\") {\n\t\ts.stop(green(\"You are on the latest version\"))\n\t} else if (status === \"fetch-update\" || status === \"cache-update\") {\n\t\ts.stop(\"\")\n\t\tif (captured.nag) displayNag(captured.nag.current, captured.nag.latest)\n\t} else if (status === \"fetch-failed-or-aborted\") {\n\t\ts.stop(\"Update check failed\")\n\t} else {\n\t\ts.stop(\"\")\n\t}\n}\n","import { log, type spinner } from \"@clack/prompts\"\nimport { green, red } from \"kolorist\"\nimport { attemptCommit, attemptCommitNoVerify, getHead, stageAll } from \"../services/git.js\"\nimport { createProgressHandler } from \"../services/hook-progress.js\"\nimport { parseHookErrors, parseToolChecks } from \"../services/hooks.js\"\nimport { showRecoveryMenu } from \"../ui/recovery-menu.js\"\n\n/** Shared recovery menu factory — avoids repeating the same callback set */\nexport function makeRecoveryCallbacks(message: string) {\n\treturn {\n\t\tretry: async () => (await attemptCommit(message)).ok,\n\t\tskipHooks: async (msg: string) => (await attemptCommitNoVerify(msg)).ok,\n\t\trestage: async () => {\n\t\t\tawait stageAll()\n\t\t\treturn (await attemptCommit(message)).ok\n\t\t},\n\t\tmessage,\n\t}\n}\n\n/**\n * Attempt commit with automatic recovery flow.\n * Handles the attempt → HEAD check → success (tool checks display)\n * / failure (recovery menu) pattern.\n * Caller is responsible for starting the spinner and showing the final outro.\n */\nexport async function commitWithRecovery(\n\tmessage: string,\n\ts: ReturnType<typeof spinner>,\n\theadBefore: string | null,\n): Promise<\"committed\" | \"cancelled\"> {\n\tconst result = await attemptCommit(message, [], createProgressHandler(s))\n\tconst headAfter = await getHead()\n\n\tif (result.ok || headBefore !== headAfter) {\n\t\ts.stop(\"Committed successfully.\")\n\n\t\tconst checks = parseToolChecks(result.stderr ?? \"\")\n\t\tif (checks.length > 0) {\n\t\t\tconst lines = checks.map((c) => ` ${c.ok ? green(\"✓\") : red(\"✗\")} ${c.tool}`)\n\t\t\tlog.info(lines.join(\"\\n\"))\n\t\t}\n\n\t\treturn \"committed\"\n\t}\n\n\ts.stop(\"Commit failed.\")\n\tconst errors = parseHookErrors(result.stderr ?? \"\")\n\tconst cb = makeRecoveryCallbacks(message)\n\tconst recoveryResult = await showRecoveryMenu(\n\t\terrors,\n\t\tcb.retry,\n\t\tcb.skipHooks,\n\t\tcb.restage,\n\t\tcb.message,\n\t\tresult.stderr ?? \"\",\n\t)\n\n\tif (recoveryResult === \"cancelled\") {\n\t\treturn \"cancelled\"\n\t}\n\n\treturn \"committed\"\n}\n","import { intro, outro, spinner } from \"@clack/prompts\"\nimport { green, red } from \"kolorist\"\nimport { getHead, getRepoRoot } from \"../services/git.js\"\nimport { loadCachedCommit } from \"../utils/cache.js\"\nimport { debug } from \"../utils/debug.js\"\nimport { commitWithRecovery } from \"./commit-utils.js\"\n\n/** Handle --retry mode: load cached message and re-attempt commit */\nexport async function handleRetry(): Promise<void> {\n\tdebug(\"Entering retry mode\")\n\tconst repoRoot = await getRepoRoot()\n\tconst cached = await loadCachedCommit(repoRoot)\n\tif (!cached) {\n\t\toutro(red(\"No cached commit message found. Run cmint without --retry first.\"))\n\t\tprocess.exit(1)\n\t}\n\tintro(\"🌿 commit-mint — retry\")\n\tconst s = spinner()\n\tconst headBefore = await getHead()\n\ts.start(\"Running pre-commit hooks...\")\n\tconst result = await commitWithRecovery(cached.message, s, headBefore)\n\tif (result === \"committed\") {\n\t\toutro(green(\"Committed successfully.\"))\n\t} else {\n\t\tprocess.exit(1)\n\t}\n}\n","import { access, constants, writeFile } from \"node:fs/promises\"\nimport { join } from \"node:path\"\nimport * as p from \"@clack/prompts\"\nimport { bold, dim, green, yellow } from \"kolorist\"\nimport { detectConfig } from \"../services/checks.js\"\nimport { debug } from \"../utils/debug.js\"\n\n/** Marker files for each tool. First match wins per tool. */\nconst TOOL_MARKERS: Record<ToolName, readonly string[]> = {\n\tbiome: [\"biome.json\", \"biome.jsonc\"],\n\teslint: [\n\t\t\"eslint.config.js\",\n\t\t\"eslint.config.mjs\",\n\t\t\"eslint.config.ts\",\n\t\t\"eslint.config.cjs\",\n\t\t\".eslintrc.js\",\n\t\t\".eslintrc.cjs\",\n\t\t\".eslintrc.json\",\n\t\t\".eslintrc.yml\",\n\t\t\".eslintrc.yaml\",\n\t\t\".eslintrc\",\n\t],\n\ttypescript: [\"tsconfig.json\"],\n\tvitest: [\"vitest.config.js\", \"vitest.config.mts\", \"vitest.config.ts\", \"vitest.config.mjs\"],\n} as const\n\nexport type ToolName = \"biome\" | \"eslint\" | \"typescript\" | \"vitest\"\n\nexport type DetectedTools = Record<ToolName, boolean>\n\n/** Indent for generated config — matches biome.json `indentStyle: \"tab\"`. */\nconst TAB = \"\\t\"\n\nasync function exists(path: string): Promise<boolean> {\n\ttry {\n\t\tawait access(path, constants.R_OK)\n\t\treturn true\n\t} catch {\n\t\treturn false\n\t}\n}\n\n/**\n * Scan a directory for marker files that indicate which tools the project uses.\n * Returns a map of tool name to detected status. Order within each tool's list\n * is priority order (first match wins).\n */\nexport async function detectTools(cwd: string): Promise<DetectedTools> {\n\tconst result: DetectedTools = { biome: false, eslint: false, typescript: false, vitest: false }\n\tfor (const [tool, files] of Object.entries(TOOL_MARKERS) as [ToolName, readonly string[]][]) {\n\t\tfor (const file of files) {\n\t\t\tif (await exists(join(cwd, file))) {\n\t\t\t\tresult[tool] = true\n\t\t\t\tdebug(\"setup: detected %s via %s\", tool, file)\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\tdebug(\"setup: detection result %o\", result)\n\treturn result\n}\n\n/**\n * Build the string content of a .cmintrc file from a detection result.\n * Returns tabs-indented TS/JS object literal with trailing commas. Biome is\n * preferred when both biome and eslint are present — overlapping globs would\n * cause both tools to run on the same files, which is wasteful and noisy.\n */\nexport function buildCmintrcContent(tools: DetectedTools): string {\n\tconst entries: string[] = []\n\n\tconst linter = tools.biome || tools.eslint\n\tif (linter) {\n\t\tconst cmd = tools.biome\n\t\t\t? \"biome check --write --no-errors-on-unmatched --error-on-warnings\"\n\t\t\t: \"eslint --fix\"\n\t\tconst ext = tools.biome ? \"{js,ts,json}\" : \"{js,ts}\"\n\t\tentries.push(`${TAB}\"*.${ext}\": \"${cmd}\",`)\n\t}\n\n\tconst tsChecks: string[] = []\n\tif (tools.typescript) tsChecks.push(\"tsc --noEmit\")\n\tif (tools.vitest) tsChecks.push(\"vitest run --passWithNoTests\")\n\tif (tsChecks.length > 0) {\n\t\tconst body = tsChecks.map((c) => `\"${c}\"`).join(\", \")\n\t\tconst fn = tsChecks.length === 1 ? `() => ${body}` : `() => [${body}]`\n\t\tentries.push(`${TAB}\"*.ts\": ${fn},`)\n\t}\n\n\tif (entries.length === 0) {\n\t\treturn `export default {\\n};\\n`\n\t}\n\n\treturn `export default {\\n${entries.join(\"\\n\")}\\n};\\n`\n}\n\n/** Choose the file extension based on whether the project uses TypeScript. */\nexport function pickFileName(tools: DetectedTools): string {\n\treturn tools.typescript ? \".cmintrc.ts\" : \".cmintrc\"\n}\n\nfunction formatDetection(tools: DetectedTools): string {\n\treturn (Object.entries(tools) as [ToolName, boolean][])\n\t\t.map(([tool, found]) => ` ${found ? green(\"✓\") : dim(\"✗\")} ${tool}`)\n\t\t.join(\"\\n\")\n}\n\n/**\n * Interactive setup for `.cmintrc`. Detects biome/eslint/typescript/vitest in\n * the given directory, previews the generated config, and writes the file\n * after confirmation. Refuses to overwrite without explicit consent. Defaults\n * to `process.cwd()` when called from the `cmint config` menu; the preflight\n * caller passes the repo root explicitly.\n */\nexport async function setupCmintrcCommand(cwd: string = process.cwd()): Promise<void> {\n\tdebug(\"setupCmintrcCommand: starting in %s\", cwd)\n\tconst tools = await detectTools(cwd)\n\n\tp.log.info(`Detected tools in ${bold(cwd)}:`)\n\tp.log.message(formatDetection(tools))\n\n\tconst foundAny = Object.values(tools).some(Boolean)\n\tif (!foundAny) {\n\t\tp.log.warn(\"No recognized tools found. Writing an empty config to fill in manually.\")\n\t} else if (tools.biome && tools.eslint) {\n\t\tp.log.warn(yellow(\"Both biome and eslint detected — using biome (remove this line to switch).\"))\n\t}\n\n\tconst fileName = pickFileName(tools)\n\tconst filePath = join(cwd, fileName)\n\n\tif (await exists(filePath)) {\n\t\tconst overwrite = await p.confirm({\n\t\t\tmessage: `${fileName} already exists. Overwrite?`,\n\t\t})\n\t\tif (p.isCancel(overwrite) || !overwrite) {\n\t\t\tp.log.info(dim(\"Cancelled — existing file left untouched.\"))\n\t\t\treturn\n\t\t}\n\t}\n\n\tconst content = buildCmintrcContent(tools)\n\tp.log.info(dim(`\\nPreview of ${fileName}:`))\n\tp.log.message(dim(content))\n\n\tconst confirm = await p.confirm({\n\t\tmessage: `Write ${fileName}?`,\n\t})\n\tif (p.isCancel(confirm) || !confirm) {\n\t\tp.log.info(dim(\"Cancelled.\"))\n\t\treturn\n\t}\n\n\tawait writeFile(filePath, content, \"utf-8\")\n\tdebug(\"setupCmintrcCommand: wrote %s\", filePath)\n\tp.log.success(green(`Wrote ${fileName}`))\n}\n\n// ── Preflight prompt ──────────────────────────────────────────────────────\n\n/** Project-local marker file that suppresses the preflight prompt forever. */\nexport const SKIP_SETUP_MARKER = \".cmint-skip-setup\"\n\n/** True if at least one of biome/eslint/typescript/vitest is present. */\nexport function isAutoConfigurable(tools: DetectedTools): boolean {\n\treturn Object.values(tools).some(Boolean)\n}\n\n/** True if the skip-setup marker exists in `cwd`. */\nexport async function hasSkipSetupMarker(cwd: string): Promise<boolean> {\n\treturn exists(join(cwd, SKIP_SETUP_MARKER))\n}\n\n/** Write the skip-setup marker to `cwd`. The file is empty by design. */\nexport async function writeSkipSetupMarker(cwd: string): Promise<void> {\n\tconst filePath = join(cwd, SKIP_SETUP_MARKER)\n\tawait writeFile(filePath, \"\", \"utf-8\")\n\tdebug(\"preflight: wrote skip-setup marker to %s\", filePath)\n}\n\n/**\n * One-shot prompt run at the start of `cmint`. Skips silently if the user\n * already has a `.cmintrc` or has previously opted out (`.cmint-skip-setup`).\n * If the project is auto-configurable, asks the user whether to run setup\n * now. Choices: `yes` runs the standard setup flow; `no` proceeds without\n * setup and re-prompts next time; `never` writes a marker to suppress the\n * prompt for this project forever.\n */\nexport async function runPreflightSetupPrompt(cwd: string): Promise<void> {\n\tdebug(\"preflight: checking %s\", cwd)\n\n\tif (await hasSkipSetupMarker(cwd)) {\n\t\tdebug(\"preflight: skip-setup marker present, skipping prompt\")\n\t\treturn\n\t}\n\n\tconst existingConfig = await detectConfig(cwd)\n\tif (existingConfig) {\n\t\tdebug(\"preflight: .cmintrc present at %s, skipping prompt\", existingConfig)\n\t\treturn\n\t}\n\n\tconst tools = await detectTools(cwd)\n\tif (!isAutoConfigurable(tools)) {\n\t\tdebug(\"preflight: project not auto-configurable, skipping prompt\")\n\t\treturn\n\t}\n\n\tconst choice = await p.select({\n\t\tmessage: \"No .cmintrc found. Run setup to create one from detected tools?\",\n\t\toptions: [\n\t\t\t{ label: \"Yes, set up .cmintrc\", value: \"yes\" },\n\t\t\t{ label: \"No, skip for now\", value: \"no\" },\n\t\t\t{ label: \"No, don't ask again\", value: \"never\" },\n\t\t],\n\t})\n\n\tif (p.isCancel(choice)) {\n\t\tdebug(\"preflight: user cancelled prompt\")\n\t\treturn\n\t}\n\n\tif (choice === \"never\") {\n\t\tawait writeSkipSetupMarker(cwd)\n\t\tp.log.info(dim(`Won't ask again. Delete ${SKIP_SETUP_MARKER} to re-enable.`))\n\t\treturn\n\t}\n\n\tif (choice === \"no\") {\n\t\tp.log.info(dim(\"Skipping .cmintrc setup.\"))\n\t\treturn\n\t}\n\n\t// \"yes\" — run the standard setup flow (with its own confirmations).\n\tdebug(\"preflight: user chose yes, running setup\")\n\tawait setupCmintrcCommand(cwd)\n}\n","import * as p from \"@clack/prompts\"\nimport { bold, cyan, dim, green, red, yellow } from \"kolorist\"\nimport type { ChangedFile } from \"../services/git.js\"\nimport { debug } from \"../utils/debug.js\"\n\nexport interface StagingChoice {\n\tfiles: string[] // selected file paths to stage\n\tall: boolean // whether user chose \"Stage all\"\n}\n\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Staging menu with conditional options + multiselect fallback\n// biome-ignore lint/complexity/noExcessiveLinesPerFunction: Staging menu with file list display + multiselect fallback\nexport async function showStagingMenu(\n\tfiles: ChangedFile[],\n\thasChecks: boolean,\n): Promise<StagingChoice | \"autogroup\" | \"checks\" | \"staged\" | null> {\n\tdebug(\"showStagingMenu: %d files\", files.length)\n\n\t// Build status labels with kolorist colors\n\tconst statusLabel = (status: string): string => {\n\t\tswitch (status) {\n\t\t\tcase \"M\":\n\t\t\t\treturn yellow(\"M\")\n\t\t\tcase \"A\":\n\t\t\t\treturn green(\"A\")\n\t\t\tcase \"D\":\n\t\t\t\treturn red(\"D\")\n\t\t\tcase \"?\":\n\t\t\tcase \"??\":\n\t\t\t\treturn cyan(\"?\")\n\t\t\tdefault:\n\t\t\t\treturn dim(status)\n\t\t}\n\t}\n\n\t// Sort: staged files first, then unstaged\n\tconst sorted = [...files].sort((a, b) => {\n\t\tif (a.staged !== b.staged) return a.staged ? -1 : 1\n\t\treturn a.path.localeCompare(b.path)\n\t})\n\n\t// Show file list grouped by staged status\n\tconst stagedFiles = sorted.filter((f) => f.staged)\n\tconst unstagedFiles = sorted.filter((f) => !f.staged)\n\tconst lines: string[] = []\n\tif (stagedFiles.length > 0) {\n\t\tlines.push(\n\t\t\tgreen(bold(\"Staged:\")),\n\t\t\t...stagedFiles.map((f) => ` ${statusLabel(f.status)} ${f.path}`),\n\t\t)\n\t}\n\tif (unstagedFiles.length > 0) {\n\t\tif (lines.length > 0) lines.push(\"\")\n\t\tlines.push(\n\t\t\tyellow(bold(\"Changed:\")),\n\t\t\t...unstagedFiles.map((f) => ` ${statusLabel(f.status)} ${f.path}`),\n\t\t)\n\t}\n\tp.note(lines.join(\"\\n\"), `${files.length} file${files.length !== 1 ? \"s\" : \"\"}`)\n\n\tconst choice = await p.select({\n\t\tmessage: \"Stage files for commit:\",\n\t\toptions: [\n\t\t\t{\n\t\t\t\tlabel: \"Auto-group into commits\",\n\t\t\t\tvalue: \"autogroup\",\n\t\t\t\thint: \"LLM groups files into logical commits\",\n\t\t\t},\n\t\t\t...(stagedFiles.length > 0\n\t\t\t\t? [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlabel: \"Commit staged files only\",\n\t\t\t\t\t\t\tvalue: \"staged\" as const,\n\t\t\t\t\t\t\thint: `${stagedFiles.length} file${stagedFiles.length !== 1 ? \"s\" : \"\"} already staged`,\n\t\t\t\t\t\t},\n\t\t\t\t\t]\n\t\t\t\t: []),\n\t\t\t{\n\t\t\t\tlabel: \"Stage all files\",\n\t\t\t\tvalue: \"all\",\n\t\t\t\thint: `${files.length} file${files.length !== 1 ? \"s\" : \"\"}`,\n\t\t\t},\n\t\t\t...(hasChecks\n\t\t\t\t? [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlabel: \"Run checks\",\n\t\t\t\t\t\t\tvalue: \"checks\" as const,\n\t\t\t\t\t\t\thint: \"Pre-flight checks from cmint config\",\n\t\t\t\t\t\t},\n\t\t\t\t\t]\n\t\t\t\t: []),\n\t\t\t{ label: \"Select files...\", value: \"select\" },\n\t\t\t{ label: \"Cancel\", value: \"cancel\" },\n\t\t],\n\t})\n\n\tif (p.isCancel(choice) || choice === \"cancel\") {\n\t\treturn null\n\t}\n\n\tif (choice === \"autogroup\") {\n\t\treturn \"autogroup\"\n\t}\n\n\tif (choice === \"checks\") {\n\t\treturn \"checks\"\n\t}\n\n\tif (choice === \"staged\") {\n\t\treturn \"staged\"\n\t}\n\n\tif (choice === \"all\") {\n\t\treturn { files: files.map((f) => f.path), all: true }\n\t}\n\n\t// Multi-select\n\tconst selected = await p.multiselect({\n\t\tmessage: \"Select files to stage:\",\n\t\toptions: sorted.map((f) => ({\n\t\t\tlabel: `${statusLabel(f.status)} ${f.path}`,\n\t\t\tvalue: f.path,\n\t\t})),\n\t\trequired: true,\n\t})\n\n\tif (p.isCancel(selected)) {\n\t\treturn null\n\t}\n\n\treturn { files: selected as string[], all: false }\n}\n","import { log, outro, spinner } from \"@clack/prompts\"\nimport { dim, red } from \"kolorist\"\nimport { detectConfig, runAllChecks } from \"../services/checks.js\"\nimport { getChangedFiles, getRepoRoot, stageAll, stageFiles } from \"../services/git.js\"\nimport { parseCheckErrors } from \"../services/hooks.js\"\nimport { showCheckFailureMenu } from \"../ui/check-failure-menu.js\"\nimport { stopCheckSpinner } from \"../ui/check-summary.js\"\nimport { showStagingMenu } from \"../ui/staging-menu.js\"\nimport { debug } from \"../utils/debug.js\"\nimport { type CommitFlags, runAutoGroupFlow } from \"./auto-group.js\"\n\n/** Interactive staging loop for multiple changed files */\n// biome-ignore lint/complexity/noExcessiveLinesPerFunction: Interactive staging loop with conditional branches\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Multi-branch TUI with autogroup, checks, staging options\nexport async function handleStaging(\n\tchangedFiles: Awaited<ReturnType<typeof getChangedFiles>>,\n\tflags: CommitFlags,\n): Promise<{\n\tchangedFiles: Awaited<ReturnType<typeof getChangedFiles>>\n\tskipStaging: boolean\n} | null> {\n\tconst repoRoot = await getRepoRoot()\n\tconst checksAvailable = (await detectConfig(repoRoot)) !== null\n\tdebug(\"checks available:\", checksAvailable)\n\n\tlet stagingResult: Awaited<ReturnType<typeof showStagingMenu>> = null\n\tlet filesToStage: string[] = []\n\tlet stageAllFlag = false\n\tlet skipStaging = false\n\tlet currentFiles = changedFiles\n\n\twhile (true) {\n\t\tstagingResult = await showStagingMenu(currentFiles, checksAvailable)\n\n\t\tif (stagingResult === \"autogroup\") {\n\t\t\tif (flags.message) {\n\t\t\t\toutro(red(\"--message flag is not compatible with auto-group mode.\"))\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst agResult = await runAutoGroupFlow(currentFiles, flags)\n\t\t\tif (agResult !== \"committed\") {\n\t\t\t\tprocess.exit(1)\n\t\t\t}\n\t\t\treturn null\n\t\t}\n\n\t\tif (stagingResult === \"checks\") {\n\t\t\tawait stageAll()\n\t\t\tconst allFiles = currentFiles.filter((f) => f.status !== \"D\").map((f) => f.path)\n\t\t\tconst configPath = await detectConfig(repoRoot)\n\t\t\tif (configPath) {\n\t\t\t\tconst ckSpinner = spinner()\n\t\t\t\tckSpinner.start(\"Running checks...\")\n\t\t\t\tconst ckResult = await runAllChecks(repoRoot, allFiles, 60000)\n\t\t\t\tstopCheckSpinner(ckSpinner, ckResult)\n\t\t\t\tif (!ckResult.ok) {\n\t\t\t\t\tfor (const r of ckResult.results.filter((r) => !r.ok))\n\t\t\t\t\t\tlog.info(r.stderr?.trim() || r.stdout?.trim() || `Check failed: ${r.command}`)\n\t\t\t\t}\n\t\t\t}\n\t\t\tcurrentFiles = await getChangedFiles()\n\t\t\tcontinue\n\t\t}\n\n\t\tif (stagingResult === \"staged\") {\n\t\t\tskipStaging = true\n\t\t\tbreak\n\t\t}\n\n\t\tif (!stagingResult) {\n\t\t\toutro(dim(\"Cancelled.\"))\n\t\t\treturn null\n\t\t}\n\n\t\tfilesToStage = stagingResult.files\n\t\tstageAllFlag = stagingResult.all\n\t\tbreak\n\t}\n\n\tif (!skipStaging) {\n\t\tconst s = spinner()\n\t\ts.start(`Staging ${filesToStage.length} file${filesToStage.length !== 1 ? \"s\" : \"\"}...`)\n\t\tif (stageAllFlag) {\n\t\t\tawait stageAll()\n\t\t} else {\n\t\t\tawait stageFiles(filesToStage)\n\t\t}\n\t\ts.stop(\"Files staged\")\n\t}\n\n\treturn { changedFiles: currentFiles, skipStaging }\n}\n\n/** Run user-defined pre-commit checks from cmint config */\nexport async function runPreCommitChecks(\n\tchangedFiles: Awaited<ReturnType<typeof getChangedFiles>>,\n\tnoCheck?: boolean,\n): Promise<void> {\n\tif (noCheck) return\n\tconst checkRoot = await getRepoRoot()\n\tconst stagedFileList = changedFiles.filter((f) => f.staged && f.status !== \"D\").map((f) => f.path)\n\tif (stagedFileList.length === 0) return\n\n\tdebug(\"Running user checks on %d staged files...\", stagedFileList.length)\n\tconst ckSpinner = spinner()\n\tckSpinner.start(\"Running checks...\")\n\tlet checkResults = await runAllChecks(checkRoot, stagedFileList, 60000)\n\tstopCheckSpinner(ckSpinner, checkResults)\n\tdebug(\"Check results: ok=%s, count=%d\", checkResults.ok, checkResults.results.length)\n\n\twhile (!checkResults.ok) {\n\t\tconst failed = checkResults.results.filter((r) => !r.ok)\n\t\tconst rawOutput = failed.map((r) => `[${r.tool}]\\n${r.stdout}\\n${r.stderr}`.trim()).join(\"\\n\\n\")\n\t\tconst checkErrors = parseCheckErrors(rawOutput)\n\t\tconst menuResult = await showCheckFailureMenu(checkErrors, rawOutput, async () => {\n\t\t\tconst retryResult = await runAllChecks(checkRoot, stagedFileList, 60000)\n\t\t\treturn retryResult.ok\n\t\t})\n\t\tif (menuResult === \"cancelled\") {\n\t\t\tprocess.exit(1)\n\t\t}\n\t\tif (menuResult === \"retried\") {\n\t\t\tdebug(\"Re-staging files and re-running checks after retry...\")\n\t\t\tawait stageAll()\n\t\t\tconst ckSpinner = spinner()\n\t\t\tckSpinner.start(\"Running checks...\")\n\t\t\tcheckResults = await runAllChecks(checkRoot, stagedFileList, 60000)\n\t\t\tdebug(\"Retry check results: ok=%s, count=%d\", checkResults.ok, checkResults.results.length)\n\t\t\tstopCheckSpinner(ckSpinner, checkResults)\n\t\t\tcontinue\n\t\t}\n\t\t// \"skipped\" — break out of loop\n\t\tbreak\n\t}\n\n\t// Formatters (prettier --write, eslint --fix, etc.) modify files on disk during checks.\n\t// Re-stage those modifications so getStagedDiff() captures the formatted content —\n\t// otherwise the commit lands with pre-format content and the changes dangle in the WT.\n\tawait restageFormatterModifications(stagedFileList)\n}\n\n/**\n * Re-stage staged files whose working-tree content diverged from the index after checks ran.\n * Signals (git status --short, 2-char XY code):\n * \"MM\" — tracked file staged-modified, then reformatted on disk\n * \"AM\" — newly-added file staged, then reformatted on disk\n */\nasync function restageFormatterModifications(stagedFileList: string[]): Promise<void> {\n\tconst checkedSet = new Set(stagedFileList)\n\tconst postCheckFiles = await getChangedFiles()\n\tconst modifiedByChecks = postCheckFiles\n\t\t.filter((f) => checkedSet.has(f.path) && f.staged && (f.status === \"MM\" || f.status === \"AM\"))\n\t\t.map((f) => f.path)\n\tif (modifiedByChecks.length === 0) return\n\tdebug(\"Re-staging %d file(s) modified by checks\", modifiedByChecks.length)\n\tawait stageFiles(modifiedByChecks)\n\tlog.info(\n\t\t`Re-staged ${modifiedByChecks.length} file${modifiedByChecks.length !== 1 ? \"s\" : \"\"} modified by checks`,\n\t)\n}\n","import { intro, isCancel, log, outro, spinner } from \"@clack/prompts\"\nimport { dim, green, red } from \"kolorist\"\nimport { getProviderApiKey, readConfig, setConfigValue } from \"../services/config.js\"\nimport {\n\tassertGitRepo,\n\tgetChangedFiles,\n\tgetHead,\n\tgetRepoRoot,\n\tgetStagedDiff,\n\tgetStatusShort,\n\tstageFiles,\n} from \"../services/git.js\"\nimport {\n\tformatProviderName,\n\tisValidProvider,\n\tPROVIDER_ENV_KEYS,\n\ttype ProviderName,\n} from \"../services/provider.js\"\nimport { checkForUpdatesUpfront } from \"../services/update-check.js\"\nimport { reviewCommitMessage } from \"../ui/review-message.js\"\nimport { saveCachedCommit } from \"../utils/cache.js\"\nimport { debug } from \"../utils/debug.js\"\nimport {\n\tbuildExcludedFilesMessage,\n\ttype CommitFlags,\n\tgenerateMessage,\n\trunAutoGroupFlow,\n} from \"./auto-group.js\"\nimport { commitWithRecovery } from \"./commit-utils.js\"\nimport { handleRetry } from \"./retry.js\"\nimport { runPreflightSetupPrompt } from \"./setup.js\"\nimport { handleStaging, runPreCommitChecks } from \"./staging.js\"\n\n// biome-ignore lint/complexity/noExcessiveLinesPerFunction: Sequential CLI lifecycle orchestrator\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Multi-branch state machine (retry/normal, staging, review, recovery)\nexport async function commitCommand(flags: CommitFlags, version: string) {\n\tdebug(\"commitCommand called\", { flags })\n\tawait assertGitRepo()\n\n\t// ── Retry mode ──────────────────────────────────────────────────\n\tif (flags.retry) {\n\t\treturn handleRetry()\n\t}\n\n\t// ── Preflight: nudge the user to set up .cmintrc if it's missing ─\n\tconst repoRoot = await getRepoRoot()\n\tawait runPreflightSetupPrompt(repoRoot)\n\n\t// ── Normal mode ─────────────────────────────────────────────────\n\tintro(\"🌿 commit-mint\")\n\n\t// ── Update check (after header, silent on cache hit) ────────────\n\tawait checkForUpdatesUpfront(version)\n\n\tconst status = await getStatusShort()\n\tdebug(\"Git status:\", status || \"(empty)\")\n\tif (!status) {\n\t\toutro(dim(\"Nothing to commit.\"))\n\t\treturn\n\t}\n\n\t// Stage changes\n\tlet changedFiles = await getChangedFiles()\n\tdebug(\"Changed files:\", changedFiles.length)\n\tconst s = spinner()\n\n\ttry {\n\t\tif (flags.auto) {\n\t\t\tif (flags.message) {\n\t\t\t\toutro(red(\"--message flag is not compatible with auto-group mode.\"))\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst agResult = await runAutoGroupFlow(changedFiles, flags)\n\t\t\tif (agResult !== \"committed\") {\n\t\t\t\tprocess.exit(1)\n\t\t\t}\n\t\t\treturn\n\t\t} else if (changedFiles.length === 1) {\n\t\t\ts.start(`Staging ${changedFiles[0].path}...`)\n\t\t\tawait stageFiles([changedFiles[0].path])\n\t\t\ts.stop(\"File staged\")\n\t\t} else {\n\t\t\tconst result = await handleStaging(changedFiles, flags)\n\t\t\tif (!result) return\n\t\t\tchangedFiles = result.changedFiles\n\t\t}\n\t} catch (err) {\n\t\ts.stop(red(\"Staging failed.\"))\n\t\tconst msg = err instanceof Error ? err.message : String(err)\n\t\tdebug(\"Staging error:\", msg)\n\t\toutro(red(`Failed to stage files: ${msg}`))\n\t\tprocess.exit(1)\n\t}\n\n\t// Refresh file list after staging so staged state is accurate\n\tchangedFiles = await getChangedFiles()\n\n\t// Run user-defined pre-commit checks (before AI message generation)\n\tawait runPreCommitChecks(changedFiles, flags.noCheck)\n\n\t// Get diff for AI\n\tconst diffResult = await getStagedDiff()\n\tif (!diffResult) {\n\t\tdebug(\"No staged changes found after staging\")\n\t\toutro(red(\"No staged changes found.\"))\n\t\tprocess.exit(1)\n\t}\n\n\t// Handle all-staged-files-are-excluded case with hardcoded message\n\tif (\"excludedFiles\" in diffResult) {\n\t\tdebug(\"All staged files are excluded:\", diffResult.excludedFiles)\n\t\tconst message = buildExcludedFilesMessage(diffResult.excludedFiles)\n\n\t\tlog.info(diffResult.excludedFiles.map((f) => ` ${f}`).join(\"\\n\"))\n\n\t\tawait saveCachedCommit(repoRoot, message)\n\n\t\ts.start(\"Running pre-commit hooks...\")\n\t\tconst headBefore = await getHead()\n\t\tconst result = await commitWithRecovery(message, s, headBefore)\n\t\tif (result === \"committed\") {\n\t\t\toutro(green(\"Done.\"))\n\t\t\treturn\n\t\t}\n\t\tif (result === \"cancelled\") {\n\t\t\tprocess.exit(1)\n\t\t}\n\t\treturn\n\t}\n\n\tdebug(\"Staged files:\", diffResult.files)\n\tdebug(\"Diff length:\", diffResult.diff.length, \"chars\")\n\n\tlog.info(diffResult.files.map((f) => ` ${f}`).join(\"\\n\"))\n\n\t// Generate or use provided message\n\tlet message: string\n\n\tif (flags.message) {\n\t\tdebug(\"Using provided message:\", flags.message)\n\t\tmessage = flags.message\n\t} else {\n\t\tconst config = await readConfig()\n\t\tconst provider: ProviderName = isValidProvider(config.provider ?? \"groq\")\n\t\t\t? (config.provider as ProviderName)\n\t\t\t: \"groq\"\n\t\ttry {\n\t\t\tawait getProviderApiKey(provider)\n\t\t\tdebug(\"API key found\")\n\t\t} catch {\n\t\t\tdebug(\"No API key found, prompting user\")\n\t\t\tconst { text: promptText } = await import(\"@clack/prompts\")\n\t\t\tconst configKey = PROVIDER_ENV_KEYS[provider]\n\t\t\tconst key = await promptText({\n\t\t\t\tmessage: `Enter your ${formatProviderName(provider)} API key:`,\n\t\t\t\tplaceholder: provider === \"groq\" ? \"gsk_...\" : \"...\",\n\t\t\t\tvalidate: (v) => (v?.trim() ? undefined : \"API key is required\"),\n\t\t\t})\n\t\t\tif (isCancel(key)) {\n\t\t\t\toutro(dim(\"Cancelled.\"))\n\t\t\t\treturn\n\t\t\t}\n\t\t\tawait setConfigValue(configKey, String(key).trim())\n\t\t\tdebug(\"API key saved to config\")\n\t\t}\n\n\t\ts.start(\"Generating commit message...\")\n\t\ttry {\n\t\t\tconst genStart = Date.now()\n\t\t\tmessage = await generateMessage(diffResult.diff, flags.hint)\n\t\t\tdebug(\"generateMessage took %d ms\", Date.now() - genStart)\n\t\t\tdebug(\"Generated message:\", message)\n\t\t} catch (err) {\n\t\t\ts.stop(red(\"Failed to generate message.\"))\n\t\t\tdebug(\"Message generation failed:\", err instanceof Error ? err.message : String(err))\n\t\t\toutro(red(err instanceof Error ? err.message : String(err)))\n\t\t\treturn\n\t\t}\n\t\ts.stop(\"Message generated\")\n\t}\n\n\t// Review message (with optional code review)\n\tconst reviewed = await reviewCommitMessage(message, {\n\t\tregenerate: async (hint) => {\n\t\t\tconst combinedHint = flags.hint ? `${flags.hint}\\n${hint}` : hint\n\t\t\tdebug(\"Regenerating with combined hint:\", combinedHint)\n\t\t\ts.start(\"Regenerating commit message...\")\n\t\t\ttry {\n\t\t\t\tconst newMessage = await generateMessage(diffResult.diff, combinedHint)\n\t\t\t\ts.stop(\"Message regenerated\")\n\t\t\t\treturn newMessage\n\t\t\t} catch (err) {\n\t\t\t\ts.stop(red(\"Regeneration failed\"))\n\t\t\t\tthrow err\n\t\t\t}\n\t\t},\n\t})\n\tif (reviewed === null) {\n\t\toutro(dim(\"Cancelled.\"))\n\t\treturn\n\t}\n\tmessage = reviewed\n\n\t// Cache message before attempting commit\n\tawait saveCachedCommit(repoRoot, message)\n\tdebug(\"Message cached for repo:\", repoRoot)\n\n\t// Attempt commit\n\ts.start(\"Running pre-commit hooks...\")\n\tconst headBefore = await getHead()\n\tdebug(\"HEAD before commit:\", headBefore)\n\tconst result = await commitWithRecovery(message, s, headBefore)\n\tdebug(\"Commit result:\", result)\n\n\tif (result === \"committed\") {\n\t\toutro(green(\"Done.\"))\n\t\treturn\n\t}\n\tif (result === \"cancelled\") {\n\t\tprocess.exit(1)\n\t}\n}\n","import * as p from \"@clack/prompts\"\nimport { bold, dim, green } from \"kolorist\"\nimport { getModelForProvider, readConfig, writeConfig } from \"../services/config.js\"\nimport {\n\tformatProviderName,\n\tisValidProvider,\n\tPROVIDER_CONFIGS,\n\tPROVIDER_ENV_KEYS,\n\ttype ProviderName,\n} from \"../services/provider.js\"\nimport { debug } from \"../utils/debug.js\"\nimport { setupCmintrcCommand } from \"./setup.js\"\n\nfunction maskKey(key: string | undefined): string {\n\tif (!key) return dim(\"not set\")\n\tif (key.length <= 8) return \"****\"\n\treturn `${key.slice(0, 4)}${\"*\".repeat(Math.min(key.length - 8, 20))}${key.slice(-4)}`\n}\n\nfunction buildConfigDisplay(config: Record<string, string | undefined>): string {\n\tconst provider: ProviderName = isValidProvider(config.provider ?? \"groq\")\n\t\t? (config.provider as ProviderName)\n\t\t: \"groq\"\n\tconst keyName = PROVIDER_ENV_KEYS[provider]\n\tconst apiKey = config[keyName]\n\tconst effectiveModel = getModelForProvider(\n\t\tconfig as import(\"../services/config.js\").Config,\n\t\tprovider,\n\t\tPROVIDER_CONFIGS[provider].defaultModel,\n\t)\n\n\tconst lines = [\n\t\t`Provider: ${bold(formatProviderName(provider))}`,\n\t\t`API Key: ${maskKey(apiKey)}`,\n\t\t`Model: ${effectiveModel}`,\n\t\t`Locale: ${config.locale ?? \"en\"}`,\n\t\t`Max Length: ${config[\"max-length\"] ?? \"100\"}`,\n\t\t`Commit Type: ${config.type || dim(\"(none)\")}`,\n\t\t`Timeout: ${config.timeout ?? \"10000\"}ms`,\n\t\t`Proxy: ${config.proxy || dim(\"(none)\")}`,\n\t]\n\n\treturn lines.join(\"\\n\")\n}\n\nfunction getProvider(config: Record<string, string | undefined>): ProviderName {\n\treturn isValidProvider(config.provider ?? \"groq\") ? (config.provider as ProviderName) : \"groq\"\n}\n\nasync function promptProvider(): Promise<string | symbol> {\n\treturn p.select({\n\t\tmessage: \"Select LLM provider:\",\n\t\toptions: [\n\t\t\t{ label: \"Groq\", value: \"groq\", hint: PROVIDER_CONFIGS.groq.defaultModel },\n\t\t\t{ label: \"Cerebras\", value: \"cerebras\", hint: PROVIDER_CONFIGS.cerebras.defaultModel },\n\t\t\t{ label: \"Mistral\", value: \"mistral\", hint: PROVIDER_CONFIGS.mistral.defaultModel },\n\t\t],\n\t})\n}\n\nasync function promptApiKey(provider: ProviderName): Promise<string | symbol> {\n\tconst keyName = PROVIDER_ENV_KEYS[provider]\n\tconst result = await p.text({\n\t\tmessage: `${formatProviderName(provider)} API key:`,\n\t\tplaceholder: \"Paste your API key\",\n\t\tvalidate: (v) => (!v?.trim() ? \"API key cannot be empty\" : undefined),\n\t})\n\tif (p.isCancel(result)) return result\n\tawait writeConfig({ [keyName]: result.toString().trim() })\n\tdebug(\"config: %s set\", keyName)\n\treturn result\n}\n\nasync function promptTextSetting(\n\tlabel: string,\n\tconfigKey: string,\n\tcurrentValue: string | undefined,\n\tvalidate?: (v: string | undefined) => string | undefined,\n): Promise<string | symbol> {\n\tconst result = await p.text({\n\t\tmessage: label,\n\t\tplaceholder: currentValue ?? \"\",\n\t\tinitialValue: currentValue ?? \"\",\n\t\tvalidate,\n\t})\n\tif (p.isCancel(result)) return result\n\tawait writeConfig({ [configKey]: result.toString().trim() })\n\tdebug(\"config: %s set to %s\", configKey, result)\n\treturn result\n}\n\nconst requireNumber = (v: string | undefined) => {\n\tif (!v?.trim()) return \"Value cannot be empty\"\n\treturn Number.isNaN(Number(v)) ? \"Must be a number\" : undefined\n}\n\ntype SettingHandler = () => Promise<string | symbol | undefined>\n\nfunction getSettingHandlers(\n\tconfig: Record<string, string | undefined>,\n): Record<string, SettingHandler> {\n\tconst provider = getProvider(config)\n\treturn {\n\t\tprovider: async () => {\n\t\t\tconst result = await promptProvider()\n\t\t\tif (p.isCancel(result)) return result\n\t\t\tconst newProvider = result as ProviderName\n\t\t\tconst newDefaultModel = PROVIDER_CONFIGS[newProvider].defaultModel\n\t\t\tawait writeConfig({ provider: newProvider, model: newDefaultModel })\n\t\t\tdebug(\"config: provider set to %s, model set to %s\", newProvider, newDefaultModel)\n\n\t\t\t// Prompt for API key if not set for the new provider\n\t\t\tconst keyName = PROVIDER_ENV_KEYS[newProvider]\n\t\t\tconst updatedConfig = (await readConfig()) as Record<string, string | undefined>\n\t\t\tif (!updatedConfig[keyName]) {\n\t\t\t\tconst keyResult = await promptApiKey(newProvider)\n\t\t\t\tif (p.isCancel(keyResult)) return keyResult\n\t\t\t}\n\t\t},\n\t\tapikey: async () => promptApiKey(provider),\n\t\tmodel: async () => {\n\t\t\tconst effectiveModel = getModelForProvider(\n\t\t\t\tconfig as import(\"../services/config.js\").Config,\n\t\t\t\tprovider,\n\t\t\t\tPROVIDER_CONFIGS[provider].defaultModel,\n\t\t\t)\n\t\t\treturn promptTextSetting(\"Model ID:\", \"model\", effectiveModel)\n\t\t},\n\t\tlocale: async () => promptTextSetting(\"Locale (e.g. en, ja, ko):\", \"locale\", config.locale),\n\t\tmaxlen: async () =>\n\t\t\tpromptTextSetting(\n\t\t\t\t\"Max commit message length:\",\n\t\t\t\t\"max-length\",\n\t\t\t\tconfig[\"max-length\"],\n\t\t\t\trequireNumber,\n\t\t\t),\n\t\ttype: async () =>\n\t\t\tpromptTextSetting(\"Commit type prefix (e.g. conventional):\", \"type\", config.type),\n\t\ttimeout: async () =>\n\t\t\tpromptTextSetting(\"Timeout (ms):\", \"timeout\", config.timeout, requireNumber),\n\t\tproxy: async () => promptTextSetting(\"Proxy URL:\", \"proxy\", config.proxy),\n\t}\n}\n\nasync function handleEditSetting(\n\tsetting: string,\n\tconfig: Record<string, string | undefined>,\n): Promise<boolean> {\n\tconst handlers = getSettingHandlers(config)\n\tconst handler = handlers[setting]\n\tif (!handler) return false\n\tconst result = await handler()\n\treturn !p.isCancel(result)\n}\n\nasync function editSettingsLoop(initialConfig: Record<string, string | undefined>): Promise<void> {\n\tlet config = initialConfig\n\n\twhile (true) {\n\t\t// Re-read config to reflect changes from previous edits\n\t\tconfig = (await readConfig()) as Record<string, string | undefined>\n\t\tconst provider = getProvider(config)\n\t\tconst effectiveModel = getModelForProvider(\n\t\t\tconfig as import(\"../services/config.js\").Config,\n\t\t\tprovider,\n\t\t\tPROVIDER_CONFIGS[provider].defaultModel,\n\t\t)\n\n\t\tconst setting = await p.select({\n\t\t\tmessage: \"Select a setting to edit:\",\n\t\t\toptions: [\n\t\t\t\t{\n\t\t\t\t\tlabel: `LLM Provider ${dim(`(${formatProviderName(provider)})`)}`,\n\t\t\t\t\tvalue: \"provider\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: `API Key ${dim(`(for ${formatProviderName(provider)})`)}`,\n\t\t\t\t\tvalue: \"apikey\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: `Model ${dim(`(${effectiveModel})`)}`,\n\t\t\t\t\tvalue: \"model\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: `Locale ${dim(`(${config.locale ?? \"en\"})`)}`,\n\t\t\t\t\tvalue: \"locale\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: `Max commit length ${dim(`(${config[\"max-length\"] ?? \"100\"})`)}`,\n\t\t\t\t\tvalue: \"maxlen\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: `Commit type prefix ${dim(`(${config.type || \"(none)\"})`)}`,\n\t\t\t\t\tvalue: \"type\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: `Timeout (ms) ${dim(`(${config.timeout ?? \"10000\"})`)}`,\n\t\t\t\t\tvalue: \"timeout\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: `Proxy URL ${dim(`(${config.proxy || \"(none)\"})`)}`,\n\t\t\t\t\tvalue: \"proxy\",\n\t\t\t\t},\n\t\t\t\t{ label: \"Done editing\", value: \"done\" },\n\t\t\t],\n\t\t})\n\n\t\tif (p.isCancel(setting) || setting === \"done\") break\n\n\t\tconst updated = await handleEditSetting(setting as string, config)\n\t\tif (updated) {\n\t\t\tp.log.success(green(\"Updated.\"))\n\t\t}\n\t}\n}\n\nexport async function configCommand(): Promise<void> {\n\tdebug(\"configCommand: starting\")\n\tp.intro(bold(\"🌿 commit-mint config\"))\n\n\twhile (true) {\n\t\tconst config = (await readConfig()) as Record<string, string | undefined>\n\n\t\tp.note(buildConfigDisplay(config), \"commit-mint config\")\n\n\t\tconst action = await p.select({\n\t\t\tmessage: \"What would you like to do?\",\n\t\t\toptions: [\n\t\t\t\t{ label: \"Edit settings\", value: \"edit\" },\n\t\t\t\t{ label: \"Setup .cmintrc\", value: \"setup\" },\n\t\t\t\t{ label: \"Done\", value: \"done\" },\n\t\t\t],\n\t\t})\n\n\t\tif (p.isCancel(action)) {\n\t\t\tdebug(\"configCommand: cancelled at main menu\")\n\t\t\tp.outro(dim(\"Cancelled.\"))\n\t\t\treturn\n\t\t}\n\n\t\tif (action === \"done\") {\n\t\t\tdebug(\"configCommand: done\")\n\t\t\tp.outro(\"Config saved.\")\n\t\t\treturn\n\t\t}\n\n\t\tif (action === \"setup\") {\n\t\t\tdebug(\"configCommand: starting .cmintrc setup\")\n\t\t\tawait setupCmintrcCommand()\n\t\t\tcontinue\n\t\t}\n\n\t\tawait editSettingsLoop(config)\n\t}\n}\n","import { readFile } from \"node:fs/promises\"\nimport os from \"node:os\"\nimport { join } from \"node:path\"\n\nconst LOG_PATH = join(os.homedir(), \".cache\", \"commit-mint\", \"debug.log\")\nconst SESSION_SEPARATOR = /^--- session .+ ---$/\n\nexport async function logsCommand(flags: { lines?: number }): Promise<void> {\n\tlet content: string\n\ttry {\n\t\tcontent = await readFile(LOG_PATH, \"utf8\")\n\t} catch (err) {\n\t\tif ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n\t\t\tconsole.error(\"No debug logs found. Run cmint with any command first.\")\n\t\t\tprocess.exit(1)\n\t\t}\n\t\tthrow err\n\t}\n\n\tif (content.trim() === \"\") {\n\t\tconsole.error(\"No debug logs found. Run cmint with any command first.\")\n\t\tprocess.exit(1)\n\t}\n\n\tconst allLines = content.split(\"\\n\")\n\tlet lastSessionIndex = -1\n\tfor (let i = allLines.length - 1; i >= 0; i--) {\n\t\tif (SESSION_SEPARATOR.test(allLines[i])) {\n\t\t\tlastSessionIndex = i\n\t\t\tbreak\n\t\t}\n\t}\n\n\tconst sessionLines = lastSessionIndex === -1 ? allLines : allLines.slice(lastSessionIndex + 1)\n\tconst filtered = sessionLines.filter(\n\t\t(line) => line.length > 0 || sessionLines.indexOf(line) === 0,\n\t)\n\n\tif (filtered.length === 0) {\n\t\tconsole.error(\"No debug logs found. Run cmint with any command first.\")\n\t\tprocess.exit(1)\n\t}\n\n\tconst lines =\n\t\tflags.lines !== undefined && flags.lines > 0 ? filtered.slice(-flags.lines) : filtered\n\n\tfor (const line of lines) {\n\t\tconsole.log(line)\n\t}\n}\n","import { execa } from \"execa\"\nimport semver from \"semver\"\nimport { debug } from \"../utils/debug.js\"\n\nexport type PackageManager = \"npm\" | \"pnpm\" | \"yarn\" | \"bun\"\n\nexport const PACKAGE_NAME = \"@kyubiware/commit-mint\"\n\n/**\n * Detect the active package manager from the `npm_config_user_agent` env var.\n * Format: \"<pm>/<version> <...>\" — e.g. \"npm/10.2.0 node/v20.10.0\".\n * Empty/undefined input and unrecognized prefixes fall back to \"npm\".\n */\nexport function detectPackageManager(userAgent: string | undefined): PackageManager {\n\tif (!userAgent) {\n\t\tdebug(\"updater: empty userAgent, defaulting to npm\")\n\t\treturn \"npm\"\n\t}\n\tconst prefix = userAgent.split(\"/\")[0]\n\tswitch (prefix) {\n\t\tcase \"pnpm\":\n\t\t\treturn \"pnpm\"\n\t\tcase \"yarn\":\n\t\t\treturn \"yarn\"\n\t\tcase \"bun\":\n\t\t\treturn \"bun\"\n\t\tcase \"npm\":\n\t\t\treturn \"npm\"\n\t\tdefault:\n\t\t\tdebug(\"updater: unknown userAgent prefix '%s', defaulting to npm\", prefix)\n\t\t\treturn \"npm\"\n\t}\n}\n\n/**\n * Build the global install shell command for the given package manager.\n * Returned as a single string suitable for `execa(cmd, [], { shell: true })`.\n */\nexport function buildUpdateCommand(pm: PackageManager, packageName: string = PACKAGE_NAME): string {\n\tswitch (pm) {\n\t\tcase \"npm\":\n\t\t\treturn `npm install -g ${packageName}@latest`\n\t\tcase \"pnpm\":\n\t\t\treturn `pnpm add -g ${packageName}@latest`\n\t\tcase \"yarn\":\n\t\t\treturn `yarn global add ${packageName}@latest`\n\t\tcase \"bun\":\n\t\t\treturn `bun add -g ${packageName}@latest`\n\t}\n}\n\n/**\n * Fetch the latest version from the npm registry via `npm view <pkg> version`.\n * Returns the trimmed version string on success, or null on any failure\n * (non-zero exit, empty stdout, thrown error). Never throws.\n */\nexport async function fetchLatestVersion(\n\tpackageName: string = PACKAGE_NAME,\n): Promise<string | null> {\n\tdebug(\"updater: fetching latest version for %s\", packageName)\n\ttry {\n\t\tconst result = await execa(\"npm\", [\"view\", packageName, \"version\"], { reject: false })\n\t\tif (result.exitCode !== 0) {\n\t\t\tdebug(\"updater: npm view exited %d\", result.exitCode)\n\t\t\treturn null\n\t\t}\n\t\tconst trimmed = result.stdout.trim()\n\t\tif (!trimmed) {\n\t\t\tdebug(\"updater: npm view returned empty stdout\")\n\t\t\treturn null\n\t\t}\n\t\tdebug(\"updater: latest=%s\", trimmed)\n\t\treturn trimmed\n\t} catch (err) {\n\t\tdebug(\n\t\t\t\"updater: fetchLatestVersion error — %s\",\n\t\t\terr instanceof Error ? err.message : String(err),\n\t\t)\n\t\treturn null\n\t}\n}\n\n/**\n * True iff `latest` is strictly greater than `current` per semver. Returns\n * false on invalid semver input rather than throwing.\n */\nexport function isUpdateAvailable(current: string, latest: string): boolean {\n\ttry {\n\t\treturn semver.gt(latest, current)\n\t} catch (err) {\n\t\tdebug(\"updater: isUpdateAvailable error — %s\", err instanceof Error ? err.message : String(err))\n\t\treturn false\n\t}\n}\n\n/**\n * Run the global install command for the given package manager. Streams\n * the installer's live output to the user's terminal via `stdio: \"inherit\"`.\n * Returns true iff the install exits with code 0.\n */\nexport async function runUpdate(\n\tpm: PackageManager,\n\tpackageName: string = PACKAGE_NAME,\n): Promise<boolean> {\n\tconst command = buildUpdateCommand(pm, packageName)\n\tdebug(\"updater: running %s\", command)\n\ttry {\n\t\tconst result = await execa(command, [], {\n\t\t\tshell: true,\n\t\t\treject: false,\n\t\t\tstdio: \"inherit\",\n\t\t})\n\t\treturn result.exitCode === 0\n\t} catch (err) {\n\t\tdebug(\"updater: runUpdate error — %s\", err instanceof Error ? err.message : String(err))\n\t\treturn false\n\t}\n}\n","import * as p from \"@clack/prompts\"\nimport { cyan, dim, green, red } from \"kolorist\"\nimport {\n\tbuildUpdateCommand,\n\tdetectPackageManager,\n\tfetchLatestVersion,\n\tisUpdateAvailable,\n\trunUpdate,\n} from \"../services/updater.js\"\n\nexport interface UpdateFlags {\n\tyes?: boolean\n}\n\n/**\n * Self-update flow for the installed `cmint` package. Detects the active\n * package manager from `npm_config_user_agent`, asks the npm registry for the\n * latest published version, and — if newer — runs the equivalent global\n * install command after a confirmation prompt (skippable with `--yes`).\n *\n * Never throws. Registry failures and install failures are reported through\n * `p.outro(...)` and `process.exit(1)`; cancellation and \"already current\"\n * resolve normally so the CLI exits cleanly.\n */\nexport async function updateCommand(currentVersion: string, flags?: UpdateFlags): Promise<void> {\n\tp.intro(\"cmint update\")\n\n\tconst pm = detectPackageManager(process.env.npm_config_user_agent)\n\tp.log.info(`Package manager: ${pm}`)\n\n\tp.log.message(\"Checking latest version...\")\n\tconst latest = await fetchLatestVersion()\n\n\tif (latest === null) {\n\t\tp.outro(red(\"Could not reach the npm registry. Check your connection and try again.\"))\n\t\tprocess.exit(1)\n\t\treturn\n\t}\n\n\tif (!isUpdateAvailable(currentVersion, latest)) {\n\t\tp.outro(`Already up-to-date: v${currentVersion}`)\n\t\treturn\n\t}\n\n\tp.log.step(`${dim(currentVersion)} → ${green(latest)}`)\n\n\tconst cmd = buildUpdateCommand(pm)\n\n\tif (flags?.yes !== true) {\n\t\tconst confirmed = await p.confirm({ message: `Run \\`${cmd}\\`?`, initialValue: true })\n\t\tif (p.isCancel(confirmed) || !confirmed) {\n\t\t\tp.outro(\"Update cancelled.\")\n\t\t\treturn\n\t\t}\n\t}\n\n\tp.log.message(`Running ${cyan(cmd)}...`)\n\tconst ok = await runUpdate(pm)\n\n\tif (ok) {\n\t\tp.outro(green(`Updated to v${latest}`))\n\t\treturn\n\t}\n\n\tp.outro(red(\"Update failed. See output above.\"))\n\tprocess.exit(1)\n}\n","#!/usr/bin/env node\nimport { cli, command } from \"cleye\"\nimport pkg from \"../package.json\" with { type: \"json\" }\n\nconst { version } = pkg\n\nimport { agentCommand } from \"./commands/agent.js\"\nimport { commitCommand } from \"./commands/commit.js\"\nimport { configCommand } from \"./commands/config.js\"\nimport { logsCommand } from \"./commands/logs.js\"\nimport { updateCommand } from \"./commands/update.js\"\nimport { setAgentMode } from \"./utils/agent.js\"\nimport { setDebug, writeSessionHeader } from \"./utils/debug.js\"\n\ncli(\n\t{\n\t\tname: \"cmint\",\n\t\tversion,\n\t\tdescription:\n\t\t\t\"AI-powered git commit tool — auto-group changed files, generate messages, run pre-commit checks\",\n\t\tflags: {\n\t\t\tretry: {\n\t\t\t\ttype: Boolean,\n\t\t\t\tdescription: \"Retry the last failed commit\",\n\t\t\t\talias: \"r\",\n\t\t\t\tdefault: false,\n\t\t\t},\n\t\t\tauto: {\n\t\t\t\ttype: Boolean,\n\t\t\t\tdescription: \"Auto-group files into commits and accept messages (no prompts)\",\n\t\t\t\talias: \"a\",\n\t\t\t\tdefault: false,\n\t\t\t},\n\t\t\tmessage: {\n\t\t\t\ttype: String,\n\t\t\t\tdescription: \"Provide a commit message directly (skip AI generation)\",\n\t\t\t\talias: \"m\",\n\t\t\t},\n\t\t\thint: {\n\t\t\t\ttype: String,\n\t\t\t\tdescription: \"Add context hint for AI commit message generation\",\n\t\t\t\talias: \"H\",\n\t\t\t},\n\t\t\tdebug: {\n\t\t\t\ttype: Boolean,\n\t\t\t\tdescription: \"Enable debug output\",\n\t\t\t\talias: \"d\",\n\t\t\t\tdefault: false,\n\t\t\t},\n\t\t\tnoCheck: {\n\t\t\t\ttype: Boolean,\n\t\t\t\tdescription: \"Skip user-defined pre-commit checks\",\n\t\t\t\talias: \"N\",\n\t\t\t\tdefault: false,\n\t\t\t},\n\t\t\tagent: {\n\t\t\t\ttype: Boolean,\n\t\t\t\tdescription: \"AI agent mode: non-interactive auto-group with JSON output\",\n\t\t\t\tdefault: false,\n\t\t\t},\n\t\t},\n\t\tcommands: [\n\t\t\tcommand(\n\t\t\t\t{\n\t\t\t\t\tname: \"logs\",\n\t\t\t\t\tdescription: \"Show debug logs from the last cmint run\",\n\t\t\t\t\tflags: {\n\t\t\t\t\t\tlines: {\n\t\t\t\t\t\t\ttype: Number,\n\t\t\t\t\t\t\tdescription: \"Number of lines to show from the end\",\n\t\t\t\t\t\t\talias: \"n\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tasync (argv) => {\n\t\t\t\t\tawait logsCommand(argv.flags)\n\t\t\t\t},\n\t\t\t),\n\t\t\tcommand({ name: \"config\" }, async () => {\n\t\t\t\tawait configCommand()\n\t\t\t}),\n\t\t\tcommand(\n\t\t\t\t{\n\t\t\t\t\tname: \"update\",\n\t\t\t\t\tdescription: \"Update cmint to the latest published version\",\n\t\t\t\t\tflags: {\n\t\t\t\t\t\tyes: {\n\t\t\t\t\t\t\ttype: Boolean,\n\t\t\t\t\t\t\tdescription: \"Skip confirmation prompt\",\n\t\t\t\t\t\t\talias: \"y\",\n\t\t\t\t\t\t\tdefault: false,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tasync (argv) => {\n\t\t\t\t\tawait updateCommand(version, argv.flags)\n\t\t\t\t},\n\t\t\t),\n\t\t],\n\t},\n\t(argv) => {\n\t\twriteSessionHeader()\n\t\tsetDebug(argv.flags.debug)\n\t\tif (argv.flags.agent) {\n\t\t\tsetAgentMode(true)\n\t\t\tagentCommand(argv.flags)\n\t\t} else {\n\t\t\tvoid commitCommand(argv.flags, version)\n\t\t}\n\t},\n)\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.mjs","names":["cachePath","p","p","p","p","NO_TRUNCATION","fastStringTruncatedWidth","stringWidth","D","x","p","M","V","SelectPrompt","isClackCancel","p","p","p","pkg"],"sources":["../package.json","../src/utils/debug.ts","../src/services/provider.ts","../src/services/ai.ts","../src/services/hooks.ts","../src/services/checks.ts","../src/services/config.ts","../src/services/hook-progress.ts","../src/services/git.ts","../src/services/grouping-parser.ts","../src/services/grouping-reunite.ts","../src/services/grouping.ts","../src/utils/agent.ts","../src/utils/cache.ts","../src/services/auto-accept.ts","../src/ui/grouping.ts","../src/services/clipboard.ts","../src/ui/recovery-menu.ts","../src/ui/review-message.ts","../src/ui/check-failure-menu.ts","../src/ui/check-summary.ts","../src/commands/check-phase.ts","../src/commands/auto-group.ts","../src/commands/agent.ts","../src/services/update-check.ts","../src/commands/commit-utils.ts","../src/commands/retry.ts","../src/commands/setup.ts","../node_modules/fast-string-truncated-width/dist/utils.js","../node_modules/fast-string-truncated-width/dist/index.js","../node_modules/fast-string-width/dist/index.js","../node_modules/fast-wrap-ansi/lib/main.js","../node_modules/sisteransi/src/index.js","../node_modules/@clack/core/dist/index.mjs","../src/ui/auto-accept-select.ts","../src/ui/staging-menu.ts","../src/commands/staging.ts","../src/commands/commit.ts","../src/commands/config.ts","../src/commands/logs.ts","../src/services/updater.ts","../src/commands/update.ts","../src/cli.ts"],"sourcesContent":["","import { appendFileSync, mkdirSync, writeFileSync } from \"node:fs\"\nimport os from \"node:os\"\nimport { join } from \"node:path\"\nimport { dim } from \"kolorist\"\n\nlet enabled = false\nlet dirEnsured = false\nlet sessionWritten = false\nlet logFile = join(os.homedir(), \".cache\", \"commit-mint\", \"debug.log\")\n\nconst LOG_DIR = join(os.homedir(), \".cache\", \"commit-mint\")\n\nfunction ensureLogDir(): void {\n\tif (dirEnsured) return\n\tmkdirSync(LOG_DIR, { recursive: true })\n\tdirEnsured = true\n}\n\nexport function setDebug(value: boolean): void {\n\tenabled = value\n}\n\nexport function isDebug(): boolean {\n\treturn enabled\n}\n\nexport function getLogFilePath(): string {\n\treturn logFile\n}\n\n/** Override log file path (used by tests to avoid polluting real logs) */\nexport function setLogFilePath(path: string): void {\n\tlogFile = path\n}\n\nexport function writeSessionHeader(): void {\n\tif (sessionWritten) return\n\tensureLogDir()\n\twriteFileSync(logFile, `--- session ${new Date().toISOString()} ---\\n`, \"utf8\")\n\tsessionWritten = true\n}\n\nexport function debug(...args: unknown[]): void {\n\tconst timestamp = new Date().toISOString().slice(11, 23)\n\tconst prefix = `[debug ${timestamp}]`\n\tensureLogDir()\n\tappendFileSync(logFile, `${prefix} ${args.map(String).join(\" \")}\\n`, \"utf8\")\n\tif (!enabled) return\n\tconsole.error(dim(prefix), ...args)\n}\n","import Groq from \"groq-sdk\"\nimport { debug } from \"../utils/debug.js\"\n\nexport type ProviderName = \"groq\" | \"cerebras\" | \"mistral\"\n\nexport interface ProviderConfig {\n\tbaseURL: string\n\tdefaultModel: string\n}\n\nexport const PROVIDER_CONFIGS: Record<ProviderName, ProviderConfig> = {\n\tgroq: {\n\t\tbaseURL: \"https://api.groq.com\",\n\t\tdefaultModel: \"openai/gpt-oss-20b\",\n\t},\n\tcerebras: {\n\t\tbaseURL: \"https://api.cerebras.ai/v1\",\n\t\tdefaultModel: \"gpt-oss-120b\",\n\t},\n\tmistral: {\n\t\tbaseURL: \"https://api.mistral.ai/v1\",\n\t\tdefaultModel: \"mistral-small\",\n\t},\n}\n\nexport const ALLOWED_PROVIDERS = Object.keys(PROVIDER_CONFIGS) as ProviderName[]\nexport const DEFAULT_PROVIDER: ProviderName = \"groq\"\n\nexport const PROVIDER_ENV_KEYS: Record<ProviderName, string> = {\n\tgroq: \"GROQ_API_KEY\",\n\tcerebras: \"CEREBRAS_API_KEY\",\n\tmistral: \"MISTRAL_API_KEY\",\n}\n\nexport function formatProviderName(provider: string): string {\n\treturn provider.charAt(0).toUpperCase() + provider.slice(1)\n}\n\nexport function isValidProvider(name: string): name is ProviderName {\n\treturn ALLOWED_PROVIDERS.includes(name as ProviderName)\n}\n\n/**\n * Generic OpenAI-compatible chat completions client using fetch.\n * Used for non-Groq providers where the Groq SDK's hardcoded `/openai/v1/` path\n * prefix doesn't match the provider's actual API path.\n */\nfunction createFetchClient(baseURL: string, apiKey: string, timeout: number) {\n\treturn {\n\t\tchat: {\n\t\t\tcompletions: {\n\t\t\t\tasync create(params: {\n\t\t\t\t\tmessages: Array<{\n\t\t\t\t\t\trole: string\n\t\t\t\t\t\tcontent: string | Array<{ type: string; text?: string }>\n\t\t\t\t\t}>\n\t\t\t\t\tmodel: string\n\t\t\t\t\ttemperature?: number\n\t\t\t\t\tmax_tokens?: number\n\t\t\t\t\tmax_completion_tokens?: number\n\t\t\t\t\treasoning_format?: string\n\t\t\t\t}) {\n\t\t\t\t\tconst url = `${baseURL}/chat/completions`\n\t\t\t\t\tdebug(\"fetchClient: POST %s, model=%s\", url, params.model)\n\t\t\t\t\tconst controller = new AbortController()\n\t\t\t\t\tconst timer = setTimeout(() => controller.abort(), timeout)\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst response = await fetch(url, {\n\t\t\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\t\t\t\tAuthorization: `Bearer ${apiKey}`,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbody: JSON.stringify(params),\n\t\t\t\t\t\t\tsignal: controller.signal,\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\tif (!response.ok) {\n\t\t\t\t\t\t\tconst text = await response.text().catch(() => \"\")\n\t\t\t\t\t\t\tthrow new Error(`${response.status} ${text}`)\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn (await response.json()) as {\n\t\t\t\t\t\t\tchoices: Array<{\n\t\t\t\t\t\t\t\tmessage?: {\n\t\t\t\t\t\t\t\t\tcontent?: string | Array<{ type: string; text?: string }>\n\t\t\t\t\t\t\t\t\treasoning?: string\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tfinish_reason?: string\n\t\t\t\t\t\t\t}>\n\t\t\t\t\t\t}\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tclearTimeout(timer)\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n}\n\nexport type ChatClient = Pick<Groq, \"chat\">\n\nexport function createProvider(options: {\n\tprovider: ProviderName\n\tapiKey: string\n\tmodelOverride?: string\n\ttimeout?: number\n\tbaseURLOverride?: string\n}): { client: ChatClient; model: string } {\n\tif (!isValidProvider(options.provider)) {\n\t\tthrow new Error(\n\t\t\t`Invalid provider \"${options.provider}\". Allowed values: ${ALLOWED_PROVIDERS.join(\", \")}`,\n\t\t)\n\t}\n\n\tconst providerConfig = PROVIDER_CONFIGS[options.provider]\n\tconst model = options.modelOverride ?? providerConfig.defaultModel\n\tconst baseURL = options.baseURLOverride ?? providerConfig.baseURL\n\tconst timeout = options.timeout ?? 60000\n\n\tlet client: ChatClient\n\tif (options.provider === \"groq\") {\n\t\tclient = new Groq({\n\t\t\tapiKey: options.apiKey,\n\t\t\tbaseURL,\n\t\t\ttimeout,\n\t\t})\n\t} else {\n\t\tclient = createFetchClient(baseURL, options.apiKey, timeout) as unknown as ChatClient\n\t}\n\n\treturn { client, model }\n}\n","import Groq from \"groq-sdk\"\nimport { debug } from \"../utils/debug.js\"\nimport { createProvider, formatProviderName, type ProviderName } from \"./provider.js\"\n\nconst MAX_DIFF_CHARS = 20000\n\nexport function mapGroqError(error: unknown, providerLabel?: string): Error {\n\tconst label = providerLabel ?? \"Groq\"\n\tif (error instanceof Groq.AuthenticationError) {\n\t\treturn new Error(\n\t\t\t`Invalid API key for ${label}. Run: cmint config set ${label.toUpperCase()}_API_KEY=<key>`,\n\t\t)\n\t}\n\tif (error instanceof Groq.RateLimitError) {\n\t\treturn new Error(`Rate limited by ${label}. Please wait and try again.`)\n\t}\n\tif (error instanceof Groq.APIConnectionTimeoutError) {\n\t\treturn new Error(\"Request timed out. Check your network or try a smaller diff.\")\n\t}\n\tif (error instanceof Groq.APIError) {\n\t\treturn new Error(`${label} API error: ${error.message}`)\n\t}\n\t// Handle errors from the generic fetch client (non-Groq providers)\n\tif (error instanceof Error && /^4\\d{2}\\s/.test(error.message)) {\n\t\treturn new Error(`${label} API error: ${error.message}`)\n\t}\n\treturn new Error(`Unexpected error: ${error instanceof Error ? error.message : String(error)}`)\n}\n\nconst CONVENTIONAL_COMMIT_REGEX =\n\t/^(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test)(\\(.+\\))?!?: .+$/\n\nexport function stripThinkTags(text: string): string {\n\treturn text.replace(/<think[\\s\\S]*?<\\/think>/gi, \"\").trim()\n}\n\nexport function deriveMessageFromReasoning(reasoning: string): string | null {\n\tconst match = reasoning.match(\n\t\t/(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test)(\\(.+\\))?!?: .+/i,\n\t)\n\tif (match) return match[0].trim()\n\n\tconst sentences = reasoning.split(/[.!?]/)\n\tconst first = sentences.find((s) => s.trim().length >= 10)\n\treturn first ? first.trim() : null\n}\n\nfunction stripContextLines(diff: string): string {\n\treturn diff\n\t\t.split(\"\\n\")\n\t\t.filter((line) => !line.startsWith(\" \"))\n\t\t.join(\"\\n\")\n}\n\nexport function compressDiff(diff: string): string {\n\t// Tier 0 — Full diff\n\tif (diff.length <= MAX_DIFF_CHARS) {\n\t\treturn diff\n\t}\n\n\t// Tier 1 — Strip context lines\n\tlet result = stripContextLines(diff)\n\tif (result.length <= MAX_DIFF_CHARS) {\n\t\treturn result\n\t}\n\n\t// Tier 2 — Per-hunk line cap\n\tconst fileDiffs = result.split(/(?=diff --git)/).filter(Boolean)\n\tconst cappedFiles = fileDiffs.map((fd) => {\n\t\tconst parts = fd.split(/(?=\\n@@)/)\n\t\tconst cappedParts = parts.map((part, idx) => {\n\t\t\tif (idx === 0) return part // Keep file header\n\t\t\tconst lines = part.split(\"\\n\")\n\t\t\tconst header = lines[0] // @@ line\n\t\t\tconst changedLines = lines.slice(1).filter((l) => l.startsWith(\"+\") || l.startsWith(\"-\"))\n\t\t\tconst keptLines = changedLines.slice(0, 10)\n\t\t\treturn [header, ...keptLines].join(\"\\n\")\n\t\t})\n\t\treturn cappedParts.join(\"\")\n\t})\n\tresult = cappedFiles.join(\"\")\n\tif (result.length <= MAX_DIFF_CHARS) {\n\t\treturn result\n\t}\n\n\t// Tier 3 — File summary\n\tconst fileMatches = diff.match(/^diff --git a\\/(.+) b\\/(.+)$/gm) || []\n\tconst summary = fileMatches\n\t\t.map((f) => {\n\t\t\tconst match = f.match(/^diff --git a\\/(.+) b\\/(.+)$/)\n\t\t\treturn match && match[1] === match[2] ? `${match[1]} | changed` : \"\"\n\t\t})\n\t\t.filter(Boolean)\n\treturn `Summary of changes:\\n${summary.join(\"\\n\")}`\n}\n\nexport function buildStatSummary(diff: string): string {\n\tconst files: { name: string; adds: number; dels: number }[] = []\n\tlet currentFile = \"\"\n\tlet adds = 0\n\tlet dels = 0\n\n\tfor (const line of diff.split(\"\\n\")) {\n\t\tconst match = line.match(/^diff --git a\\/.+ b\\/(.+)$/)\n\t\tif (match) {\n\t\t\tif (currentFile) files.push({ name: currentFile, adds, dels })\n\t\t\tcurrentFile = match[1]\n\t\t\tadds = 0\n\t\t\tdels = 0\n\t\t} else if (line.startsWith(\"+\") && !line.startsWith(\"+++\")) {\n\t\t\tadds++\n\t\t} else if (line.startsWith(\"-\") && !line.startsWith(\"---\")) {\n\t\t\tdels++\n\t\t}\n\t}\n\tif (currentFile) files.push({ name: currentFile, adds, dels })\n\n\tconst totalAdds = files.reduce((s, f) => s + f.adds, 0)\n\tconst totalDels = files.reduce((s, f) => s + f.dels, 0)\n\n\tconst lines = files.map((f) => ` ${f.name} | +${f.adds} -${f.dels}`)\n\tlines.push(\n\t\t` ${files.length} files changed, ${totalAdds} insertions(+), ${totalDels} deletions(-)`,\n\t)\n\n\treturn lines.join(\"\\n\")\n}\n\nfunction buildSystemPrompt(type?: string): string {\n\tlet prompt =\n\t\t\"You are a commit message generator. Follow the Conventional Commits specification.\\n\" +\n\t\t\"Valid types: build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test.\\n\" +\n\t\t\"Format: type(scope): description\\n\" +\n\t\t\"Use imperative mood, lowercase, no trailing period.\\n\" +\n\t\t\"Output ONLY the commit message, no markdown fences, no explanation.\"\n\n\tif (type && type.trim().length > 0) {\n\t\tprompt += `\\nYou MUST use type: ${type}`\n\t}\n\n\treturn prompt\n}\n\nfunction buildUserPrompt(diff: string, hint?: string, statSummary?: string): string {\n\tconst parts: string[] = []\n\tif (hint) parts.push(`Context: ${hint}`)\n\tif (statSummary) parts.push(`Change summary:\\n${statSummary}`)\n\tparts.push(`Generate a conventional commit for:\\n\\n${diff}`)\n\treturn parts.join(\"\\n\\n\")\n}\n\nfunction isValidConventionalCommit(message: string): boolean {\n\treturn CONVENTIONAL_COMMIT_REGEX.test(message)\n}\n\nexport function extractContentText(\n\tcontent: string | Array<{ type: string; text?: string }> | null | undefined,\n): string {\n\tif (content == null) return \"\"\n\tif (typeof content === \"string\") return content.trim()\n\tif (Array.isArray(content)) {\n\t\treturn content\n\t\t\t.filter((part) => part.type === \"text\" && typeof part.text === \"string\")\n\t\t\t.map((part) => stripThinkTags(part.text as string))\n\t\t\t.join(\"\")\n\t\t\t.trim()\n\t}\n\treturn \"\"\n}\n\n// biome-ignore lint/complexity/noExcessiveLinesPerFunction: AI pipeline — prompt build, call, validate, retry, error mapping\nexport async function generateCommitMessage(\n\tdiff: string,\n\toptions: {\n\t\tapiKey: string\n\t\tmodel?: string\n\t\ttype?: string\n\t\ttimeout?: number\n\t\thint?: string\n\t\tprovider?: ProviderName\n\t\tproxy?: string\n\t},\n): Promise<string> {\n\tconst timeoutMs = options.timeout ?? 60000\n\tdebug(\"Timeout: %d ms\", timeoutMs)\n\n\tconst { client, model } = createProvider({\n\t\tprovider: options.provider ?? \"groq\",\n\t\tapiKey: options.apiKey,\n\t\tmodelOverride: options.model,\n\t\ttimeout: timeoutMs,\n\t\tbaseURLOverride: options.proxy,\n\t})\n\n\tdebug(\n\t\t\"generateCommitMessage: model=%s, type=%s, hint=%s\",\n\t\tmodel,\n\t\toptions.type ?? \"none\",\n\t\toptions.hint ?? \"none\",\n\t)\n\n\tconst compressedDiff = compressDiff(diff)\n\tconst statSummary = buildStatSummary(diff)\n\tconst systemPrompt = buildSystemPrompt(options.type)\n\tconst userPrompt = buildUserPrompt(compressedDiff, options.hint, statSummary)\n\n\tdebug(\"Diff: %d chars → compressed to %d chars\", diff.length, compressedDiff.length)\n\tdebug(\"Stat summary:\\n%s\", statSummary)\n\tdebug(\"User prompt length: %d chars\", userPrompt.length)\n\n\t// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Error class instanceof chain for API error mapping\n\t// biome-ignore lint/complexity/noExcessiveLinesPerFunction: API call with streaming, error handling, and retry\n\tasync function callAI(strictSystemPrompt?: string): Promise<string> {\n\t\tconst callStart = Date.now()\n\t\tconst isRetry = !!strictSystemPrompt\n\t\tdebug(\n\t\t\t\"callAI: %s — model=%s, promptLen=%d, systemLen=%d\",\n\t\t\tisRetry ? \"RETRY (strict)\" : \"INITIAL\",\n\t\t\tmodel,\n\t\t\tuserPrompt.length,\n\t\t\t(strictSystemPrompt ?? systemPrompt).length,\n\t\t)\n\t\ttry {\n\t\t\tconst isReasoningModel = /^(o[1-9]|.*gpt-oss.*|.*gpt-5.*)/i.test(model)\n\t\t\tconst isGroq = (options.provider ?? \"groq\") === \"groq\"\n\t\t\tconst completion = await client.chat.completions.create({\n\t\t\t\tmessages: [\n\t\t\t\t\t{ role: \"system\", content: strictSystemPrompt ?? systemPrompt },\n\t\t\t\t\t{ role: \"user\", content: userPrompt },\n\t\t\t\t],\n\t\t\t\tmodel,\n\t\t\t\ttemperature: 0.3,\n\t\t\t\t...(isReasoningModel ? { max_completion_tokens: 1024 } : { max_tokens: 1024 }),\n\t\t\t\t...(isGroq && isReasoningModel ? { reasoning_format: \"parsed\" } : {}),\n\t\t\t})\n\n\t\t\tconst elapsed = Date.now() - callStart\n\t\t\tconst rawContent = completion.choices[0]?.message?.content\n\t\t\tconst processedContent =\n\t\t\t\ttypeof rawContent === \"string\" ? stripThinkTags(rawContent) : rawContent\n\t\t\tconst content = extractContentText(processedContent)\n\t\t\tdebug(\n\t\t\t\t\"callAI response (%d ms): choices=%d, finishReason=%s, contentLen=%d, rawType=%s\",\n\t\t\t\telapsed,\n\t\t\t\tcompletion.choices.length,\n\t\t\t\tcompletion.choices[0]?.finish_reason ?? \"(none)\",\n\t\t\t\tcontent.length,\n\t\t\t\ttypeof rawContent,\n\t\t\t)\n\t\t\tdebug(\"callAI raw content: %s\", content.slice(0, 300) || \"(empty)\")\n\t\t\tif (!content) {\n\t\t\t\tconst reasoning = completion.choices[0]?.message?.reasoning\n\t\t\t\tdebug(\n\t\t\t\t\t\"callAI: content empty, attempting reasoning fallback (reasoningLen=%d)\",\n\t\t\t\t\treasoning?.length ?? 0,\n\t\t\t\t)\n\t\t\t\tif (reasoning) {\n\t\t\t\t\tconst derived = deriveMessageFromReasoning(reasoning)\n\t\t\t\t\tif (derived) {\n\t\t\t\t\t\tdebug(\"callAI: derived message from reasoning: %s\", derived.slice(0, 100))\n\t\t\t\t\t\treturn stripThinkTags(derived)\n\t\t\t\t\t}\n\t\t\t\t\tdebug(\"callAI: could not derive message from reasoning\")\n\t\t\t\t}\n\t\t\t\tthrow new Error(\"AI returned an empty commit message\")\n\t\t\t}\n\t\t\treturn content\n\t\t} catch (error) {\n\t\t\tconst elapsed = Date.now() - callStart\n\t\t\tdebug(\n\t\t\t\t\"callAI FAILED after %d ms: %s\",\n\t\t\t\telapsed,\n\t\t\t\terror instanceof Error ? `${error.name}: ${error.message}` : String(error),\n\t\t\t)\n\t\t\tthrow error\n\t\t}\n\t}\n\n\ttry {\n\t\tconst totalStart = Date.now()\n\t\tlet message = await callAI()\n\t\tdebug(\n\t\t\t\"Validation: message=%s, isValid=%s\",\n\t\t\tmessage.slice(0, 100),\n\t\t\tisValidConventionalCommit(message),\n\t\t)\n\n\t\tif (!isValidConventionalCommit(message)) {\n\t\t\tdebug(\n\t\t\t\t\"Initial message failed conventional commit validation, retrying with strict prompt (elapsed: %d ms)\",\n\t\t\t\tDate.now() - totalStart,\n\t\t\t)\n\t\t\tconst retryMessage = await callAI(\n\t\t\t\t\"You MUST output ONLY a valid conventional commit message. \" +\n\t\t\t\t\t\"Format: type(scope): description. \" +\n\t\t\t\t\t\"If you output anything else your response will be rejected.\\n\" +\n\t\t\t\t\t\"Valid types: build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test.\",\n\t\t\t)\n\t\t\tdebug(\n\t\t\t\t\"Retry validation: message=%s, isValid=%s\",\n\t\t\t\tretryMessage.slice(0, 100),\n\t\t\t\tisValidConventionalCommit(retryMessage),\n\t\t\t)\n\t\t\tif (isValidConventionalCommit(retryMessage)) {\n\t\t\t\tdebug(\"Retry produced valid conventional commit\")\n\t\t\t\tmessage = retryMessage\n\t\t\t} else {\n\t\t\t\tdebug(\"Retry also failed validation, using original message\")\n\t\t\t}\n\t\t}\n\n\t\tdebug(\"Final message (%d ms total): %s\", Date.now() - totalStart, message)\n\t\treturn message\n\t} catch (error) {\n\t\tdebug(\"AI error: %s\", error instanceof Error ? error.message : String(error))\n\t\tconst providerLabel = options.provider ? formatProviderName(options.provider) : undefined\n\t\tthrow mapGroqError(error, providerLabel)\n\t}\n}\n","import { debug } from \"../utils/debug.js\"\n\nexport interface HookError {\n\ttool: string\n\tmessage: string\n\traw: string\n}\n\n/**\n * Parse git hook error output into structured, human-readable errors.\n * Handles output from lint-staged, biome, eslint, tsc, vitest, jest.\n */\nexport function parseHookErrors(stderr: string): HookError[] {\n\tif (!stderr) return []\n\n\tdebug(\"parseHookErrors: stderr length=%d\", stderr.length)\n\tconst errors: HookError[] = []\n\n\t// Detect lint-staged task failures\n\tif (stderr.includes(\"lint-staged\") || stderr.includes(\"[FAILED]\")) {\n\t\terrors.push(...parseLintStagedErrors(stderr))\n\t}\n\n\t// Detect biome errors\n\tif (stderr.includes(\"biome\") || stderr.includes(\"Biome\")) {\n\t\terrors.push(...parseBiomeErrors(stderr))\n\t}\n\n\t// Detect TypeScript errors\n\tif (stderr.includes(\"error TS\") || stderr.includes(\"tsc\")) {\n\t\terrors.push(...parseTscErrors(stderr))\n\t}\n\n\t// Detect vitest/jest test failures\n\tif (\n\t\tstderr.includes(\"vitest\") ||\n\t\tstderr.includes(\"jest\") ||\n\t\tstderr.includes(\"FAIL\") ||\n\t\tstderr.includes(\"test failed\")\n\t) {\n\t\terrors.push(...parseTestErrors(stderr))\n\t}\n\n\t// Detect ESLint errors\n\tif (stderr.includes(\"eslint\") || stderr.includes(\"ESLint\")) {\n\t\terrors.push(...parseEslintErrors(stderr))\n\t}\n\n\t// Fallback: if nothing parsed, return the raw output\n\tif (errors.length === 0) {\n\t\tdebug(\"parseHookErrors: no patterns matched, using raw fallback\")\n\t\terrors.push({\n\t\t\ttool: \"git hooks\",\n\t\t\tmessage: stderr.trim(),\n\t\t\traw: stderr,\n\t\t})\n\t}\n\n\tdebug(\"parseHookErrors: found %d errors\", errors.length)\n\treturn errors\n}\n\nfunction parseLintStagedErrors(output: string): HookError[] {\n\tconst errors: HookError[] = []\n\tfor (const match of output.matchAll(/\\[FAILED\\]\\s+(.+?)\\s+\\[FAILED\\]/g)) {\n\t\tconst task = match[1].trim()\n\t\terrors.push({\n\t\t\ttool: \"lint-staged\",\n\t\t\tmessage: `Task failed: ${task}`,\n\t\t\traw: match[0],\n\t\t})\n\t}\n\n\treturn errors\n}\n\nfunction parseBiomeErrors(output: string): HookError[] {\n\tconst errors: HookError[] = []\n\tfor (const match of output.matchAll(/^(.+?):(\\d+):(\\d+)\\s+(.+)$/gm)) {\n\t\terrors.push({\n\t\t\ttool: \"biome\",\n\t\t\tmessage: `${match[1]}:${match[2]}:${match[3]} — ${match[4]}`,\n\t\t\traw: match[0],\n\t\t})\n\t}\n\n\tif (errors.length === 0 && output.includes(\"biome\")) {\n\t\terrors.push({\n\t\t\ttool: \"biome\",\n\t\t\tmessage: \"Biome check failed. See raw output for details.\",\n\t\t\traw: output,\n\t\t})\n\t}\n\n\treturn errors\n}\n\nfunction parseTscErrors(output: string): HookError[] {\n\tconst errors: HookError[] = []\n\tfor (const match of output.matchAll(/^(.+?)\\((\\d+),(\\d+)\\):\\s+error\\s+(TS\\d+):\\s+(.+)$/gm)) {\n\t\terrors.push({\n\t\t\ttool: \"tsc\",\n\t\t\tmessage: `${match[1]}:${match[2]}:${match[3]} — ${match[4]}: ${match[5]}`,\n\t\t\traw: match[0],\n\t\t})\n\t}\n\n\treturn errors\n}\n\nfunction parseTestErrors(output: string): HookError[] {\n\tconst errors: HookError[] = []\n\tconst failPattern = /FAIL\\s+(.+\\.(test|spec)\\..+)/\n\tconst match = failPattern.exec(output)\n\n\tif (match) {\n\t\terrors.push({\n\t\t\ttool: output.includes(\"vitest\") ? \"vitest\" : \"jest\",\n\t\t\tmessage: `Test file failed: ${match[1]}`,\n\t\t\traw: output,\n\t\t})\n\t}\n\n\tif (errors.length === 0 && (output.includes(\"vitest\") || output.includes(\"jest\"))) {\n\t\terrors.push({\n\t\t\ttool: output.includes(\"vitest\") ? \"vitest\" : \"jest\",\n\t\t\tmessage: \"Tests failed. See raw output for details.\",\n\t\t\traw: output,\n\t\t})\n\t}\n\n\treturn errors\n}\n\nfunction parseEslintErrors(output: string): HookError[] {\n\tconst errors: HookError[] = []\n\tconst lines = output.split(\"\\n\")\n\tlet currentFile = \"\"\n\n\tfor (const line of lines) {\n\t\t// ESLint file path line: not indented, contains a path separator\n\t\tif (!/^\\s/.test(line) && line.includes(\"/\")) {\n\t\t\tcurrentFile = line.trim()\n\t\t\tcontinue\n\t\t}\n\n\t\t// ESLint error/warning detail: <line>:<col> <severity> <message> <rule>\n\t\t// Message and rule are separated by 2+ spaces\n\t\tconst match = line.match(/^\\s*(\\d+):(\\d+)\\s+(error|warning)\\s+(.+)\\s{2,}(\\S+)\\s*$/)\n\t\tif (match) {\n\t\t\tconst [, lineNum, col, severity, message, rule] = match\n\t\t\tconst file = currentFile || \"unknown\"\n\t\t\terrors.push({\n\t\t\t\ttool: \"eslint\",\n\t\t\t\tmessage: `${file}:${lineNum}:${col} ${severity}: ${message} (${rule})`,\n\t\t\t\traw: line.trim(),\n\t\t\t})\n\t\t}\n\t}\n\n\treturn errors\n}\n\nexport function formatErrorReport(errors: HookError[]): string {\n\tif (errors.length === 0) return \"\"\n\n\tconst sections = errors.map((e) => `[${e.tool}]\\n${e.message}`)\n\treturn sections.join(\"\\n\\n\")\n}\n\n/**\n * Parse cmint check output into structured errors.\n * Check output uses [tool] prefix format (built by callers in auto-group.ts / staging.ts).\n * This is distinct from parseHookErrors which handles raw git hook stderr.\n */\nexport function parseCheckErrors(output: string): HookError[] {\n\tif (!output.trim()) return []\n\n\tconst errors: HookError[] = []\n\tconst lines = output.split(\"\\n\")\n\n\tlet currentTool = \"\"\n\tlet currentLines: string[] = []\n\n\tconst flush = () => {\n\t\tif (currentTool && currentLines.length > 0) {\n\t\t\tconst message = currentLines.join(\"\\n\").trim()\n\t\t\tif (message) {\n\t\t\t\terrors.push({ tool: currentTool, message, raw: currentLines.join(\"\\n\") })\n\t\t\t}\n\t\t}\n\t\tcurrentTool = \"\"\n\t\tcurrentLines = []\n\t}\n\n\tfor (const line of lines) {\n\t\tconst match = line.match(/^\\[(\\S+)\\]\\s*(.*)/)\n\t\tif (match) {\n\t\t\t// New [tool] block — flush previous\n\t\t\tflush()\n\t\t\tcurrentTool = match[1]\n\t\t\tconst rest = match[2].trim()\n\t\t\tif (rest) {\n\t\t\t\tcurrentLines.push(rest)\n\t\t\t}\n\t\t} else if (currentTool) {\n\t\t\t// Continuation line for current [tool] block\n\t\t\tcurrentLines.push(line)\n\t\t} else {\n\t\t\t// No [tool] prefix — accumulate as raw\n\t\t\tcurrentLines.push(line)\n\t\t}\n\t}\n\n\tflush()\n\n\t// If no [tool] prefixed blocks found, fall back to single raw error\n\tif (errors.length === 0) {\n\t\tconst trimmed = output.trim()\n\t\tif (trimmed) {\n\t\t\terrors.push({ tool: \"checks\", message: trimmed, raw: output })\n\t\t}\n\t}\n\n\treturn errors\n}\n\n// ── Tool check parsing (success case) ──────────────────────────────\n\nexport interface ToolCheck {\n\ttool: string\n\tok: boolean\n}\n\n/**\n * Parse lint-staged/hook stderr output to discover which tools ran\n * and whether they succeeded. Used for clean post-commit summary.\n */\nexport function parseToolChecks(stderr: string): ToolCheck[] {\n\tif (!stderr) return []\n\n\tconst checks: ToolCheck[] = []\n\t// Match [COMPLETED] and [FAILED] status lines from lint-staged\n\tfor (const match of stderr.matchAll(/\\[(COMPLETED|FAILED)\\]\\s+(.+)/g)) {\n\t\tconst status = match[1]\n\t\tconst command = match[2].trim()\n\n\t\tif (isLintStagedMeta(command)) continue\n\n\t\tconst tool = extractToolName(command)\n\t\tif (!tool) continue\n\n\t\tchecks.push({ tool, ok: status === \"COMPLETED\" })\n\t}\n\n\t// Deduplicate by tool name (keep last occurrence — final status)\n\tconst seen = new Map<string, ToolCheck>()\n\tfor (const c of checks) {\n\t\tseen.set(c.tool, c)\n\t}\n\n\treturn [...seen.values()]\n}\n\n/** Heuristic: skip lint-staged internal metadata lines */\nexport function isLintStagedMeta(command: string): boolean {\n\t// Glob patterns in task labels\n\tif (/[*{}[\\]]/.test(command)) return true\n\t// Task count labels: \"src/ — 3 files\", \"src/ — no files\"\n\t// The dash can be em-dash (—), en-dash (–), or plain hyphen (-)\n\tif (/\\s[-–—]\\s(\\d+\\s)?files?$/.test(command)) return true\n\tif (/\\s[-–—]\\sno\\s files$/.test(command)) return true\n\t// Internal lint-staged lifecycle messages\n\tif (\n\t\t/^(Running tasks|Applying modifications|Cleaning up|Backing up|Backed up|Updating Git)/.test(\n\t\t\tcommand,\n\t\t)\n\t)\n\t\treturn true\n\t// Ends with ellipsis (e.g. \"Backing up original state...\")\n\tif (/\\.{3}$/.test(command)) return true\n\treturn false\n}\n\n/** Extract a display-friendly tool name from a lint-staged command */\nexport function extractToolName(command: string): string | null {\n\t// Step 1: Unwrap sh -c '...' wrapper\n\tconst unwrapped = unwrapShC(command)\n\tif (unwrapped !== null) command = unwrapped\n\n\t// Step 2: Find the meaningful command in a && chain (skip cd segments)\n\tcommand = findMeaningfulCommand(command)\n\n\treturn parseToolFromTokens(command.split(/\\s+/))\n}\n\n/** Map common script names to their underlying tool */\nconst SCRIPT_MAP: Record<string, string> = {\n\ttypecheck: \"tsc\",\n\tlint: \"eslint\",\n\tformat: \"prettier\",\n}\n\n/** Package managers that use [run|exec] <script|tool> pattern */\nconst PKG_MANAGERS = [\"npm\", \"yarn\", \"pnpm\", \"bun\"]\n\n/** Parse tool name from a tokenized command */\nfunction parseToolFromTokens(tokens: string[]): string | null {\n\tconst first = tokens[0]\n\n\t// Safety: don't return the shell itself as a tool name\n\tif (first === \"sh\" || first === \"bash\" || first === \"zsh\") return null\n\n\t// npm/yarn/pnpm/bun [run|exec] <script/tool>\n\tif (PKG_MANAGERS.includes(first)) {\n\t\treturn parsePackageManagerTool(tokens)\n\t}\n\n\t// npx <tool>\n\tif (first === \"npx\") return tokens[1] ?? null\n\n\t// uv run <tool> / uv tool run <tool>\n\tif (first === \"uv\") return parseUvTool(tokens)\n\n\t// Direct tool invocation (biome, eslint, tsc, vitest, jest, prettier)\n\treturn first\n}\n\n/** Extract tool name from npm/yarn/pnpm/bun commands */\nfunction parsePackageManagerTool(tokens: string[]): string | null {\n\tconst sub = tokens[1]\n\t// pnpm exec <tool>\n\tif (sub === \"exec\") return tokens[2] ?? null\n\t// npm/yarn/pnpm [run] <script>\n\tconst scriptIdx = sub === \"run\" ? 2 : 1\n\tconst script = tokens[scriptIdx]\n\tif (!script) return null\n\treturn SCRIPT_MAP[script] ?? script\n}\n\n/** Extract tool name from uv commands */\nfunction parseUvTool(tokens: string[]): string | null {\n\tif (tokens[1] === \"run\") return tokens[2] ?? null\n\tif (tokens[1] === \"tool\" && tokens[2] === \"run\") return tokens[3] ?? null\n\treturn null\n}\n\n/** Unwrap sh -c 'command' or sh -c \"command\" wrappers */\nfunction unwrapShC(command: string): string | null {\n\t// sh/bash -c 'body' or sh/bash -c \"body\"\n\tconst quoted = command.match(/^(?:sh|bash|zsh)\\s+-c\\s+(['\"])([\\s\\S]*)\\1$/)\n\tif (quoted) return quoted[2]\n\t// sh/bash -c body (no quotes, single word — rare)\n\tconst bare = command.match(/^(?:sh|bash|zsh)\\s+-c\\s+(\\S+)$/)\n\tif (bare) return bare[1]\n\treturn null\n}\n\n/** Find the meaningful command in a && chain, skipping cd segments */\nfunction findMeaningfulCommand(command: string): string {\n\tconst segments = command\n\t\t.split(/\\s*&&\\s*/)\n\t\t.map((s) => s.trim())\n\t\t.filter(Boolean)\n\tfor (const seg of segments) {\n\t\tif (/^cd\\s/.test(seg)) continue\n\t\treturn seg\n\t}\n\treturn segments[segments.length - 1] || command\n}\n","import { readFileSync } from \"node:fs\"\nimport { access, constants } from \"node:fs/promises\"\nimport { extname, join } from \"node:path\"\nimport { execa } from \"execa\"\nimport picomatch from \"picomatch\"\nimport { debug } from \"../utils/debug.js\"\nimport { extractToolName } from \"./hooks.js\"\n\n/** Config file names, checked in priority order (matches lint-staged naming conventions) */\nconst CONFIG_FILES = [\n\t\".cmintrc\",\n\t\".cmintrc.json\",\n\t\".cmintrc.mjs\",\n\t\".cmintrc.mts\",\n\t\".cmintrc.js\",\n\t\".cmintrc.ts\",\n\t\".cmintrc.cjs\",\n\t\".cmintrc.cts\",\n\t\"cmint.config.mjs\",\n\t\"cmint.config.mts\",\n\t\"cmint.config.js\",\n\t\"cmint.config.ts\",\n\t\"cmint.config.cjs\",\n\t\"cmint.config.cts\",\n] as const\n\n/** Config shape from .cmintrc — glob keys map to command strings, string arrays, or functions */\nexport interface CheckConfig {\n\t[glob: string]: string | string[] | ((filenames: string[]) => string | string[])\n}\n\n/** Result of a single check command execution */\nexport interface CheckResult {\n\tok: boolean\n\ttool: string\n\tcommand: string\n\tstdout: string\n\tstderr: string\n\tfiles: string[]\n}\n\n/** Aggregate result from running all checks */\nexport interface CheckResults {\n\tok: boolean\n\tresults: CheckResult[]\n}\n\n/**\n * Detect whether the repo has a cmint config file.\n * Returns the config file path, or null if none found.\n */\nexport async function detectConfig(repoRoot: string): Promise<string | null> {\n\tdebug(\"detectConfig: checking for config in %s\", repoRoot)\n\tfor (const name of CONFIG_FILES) {\n\t\ttry {\n\t\t\tawait access(join(repoRoot, name), constants.R_OK)\n\t\t\tdebug(\"detectConfig: found %s\", name)\n\t\t\treturn join(repoRoot, name)\n\t\t} catch {\n\t\t\t// try next config file name\n\t\t}\n\t}\n\tdebug(\"detectConfig: no config file found\")\n\treturn null\n}\n\n/**\n * Load and validate the cmint config from a repo root.\n * Throws if the loaded value is missing or not a non-null object.\n */\nexport async function loadConfig(repoRoot: string): Promise<CheckConfig> {\n\tconst configPath = await detectConfig(repoRoot)\n\tif (!configPath) throw new Error(\"No cmint config file found\")\n\n\tdebug(\"loadConfig: loading %s\", configPath)\n\tconst ext = extname(configPath)\n\tconst isJSON = ext === \".json\"\n\tconst isTS = ext === \".ts\" || ext === \".mts\" || ext === \".cts\"\n\tconst isCJS = ext === \".cjs\"\n\tconst needsJiti = isTS || isCJS\n\n\tlet config: unknown\n\n\tif (isJSON) {\n\t\tconst raw = readFileSync(configPath, \"utf-8\")\n\t\tconfig = JSON.parse(raw)\n\t} else if (needsJiti) {\n\t\tconst { createJiti } = await import(\"jiti\")\n\t\tconst jiti = createJiti(import.meta.url, {})\n\t\tconst mod = await jiti.import(configPath)\n\t\tconfig = (mod as { default?: unknown }).default ?? mod\n\t} else {\n\t\t// .js, .mjs, or no extension\n\t\tconst imported = (await import(configPath)) as { default?: unknown }\n\t\tconfig = imported.default\n\t}\n\n\tif (!config || typeof config !== \"object\" || Array.isArray(config)) {\n\t\tthrow new Error(\"cmint config must export a non-null object with glob\\u2192command mappings\")\n\t}\n\tdebug(\n\t\t\"loadConfig: loaded %d glob patterns\",\n\t\tObject.keys(config as Record<string, unknown>).length,\n\t)\n\treturn config as CheckConfig\n}\n\n/**\n * Run a shell command and capture its output.\n * Returns a CheckResult with ok=true on success (exit 0), ok=false on failure.\n * Handles ENOENT (command not found) and timeout errors gracefully.\n */\nexport async function runCommand(\n\tcommand: string,\n\ttimeout: number,\n\trepoRoot?: string,\n): Promise<CheckResult> {\n\tdebug(\"runCommand: %s (timeout: %dms)\", command, timeout)\n\tconst tool = extractToolName(command) ?? command.split(\" \")[0]\n\n\ttry {\n\t\tconst result = await execa(command, {\n\t\t\tshell: true,\n\t\t\treject: false,\n\t\t\ttimeout,\n\t\t\tall: true,\n\t\t\tpreferLocal: true,\n\t\t\t// Run from repo root so repo-root-relative file paths (used by\n\t\t\t// .cmintrc globs and `git diff --cached`) resolve correctly even when\n\t\t\t// cmint is invoked from a subdirectory.\n\t\t\t...(repoRoot ? { localDir: repoRoot, cwd: repoRoot } : {}),\n\t\t})\n\t\tconst ok = !result.failed\n\t\tdebug(\"runCommand: %s \\u2014 ok=%s\", tool, ok)\n\t\treturn {\n\t\t\tok,\n\t\t\ttool: tool,\n\t\t\tcommand,\n\t\t\tstdout: result.stdout ?? \"\",\n\t\t\tstderr: result.stderr ?? \"\",\n\t\t\tfiles: [],\n\t\t}\n\t} catch (err) {\n\t\tconst msg = err instanceof Error ? err.message : String(err)\n\t\tconst isTimedOut = msg.toLowerCase().includes(\"timed out\")\n\t\tconst isNotFound =\n\t\t\tmsg.toLowerCase().includes(\"enoent\") || msg.toLowerCase().includes(\"not found\")\n\n\t\tdebug(\"runCommand: %s \\u2014 error: %s\", tool, msg)\n\t\treturn {\n\t\t\tok: false,\n\t\t\ttool: tool,\n\t\t\tcommand,\n\t\t\tstdout: \"\",\n\t\t\tstderr: isTimedOut\n\t\t\t\t? `Check timed out after ${timeout}ms`\n\t\t\t\t: isNotFound\n\t\t\t\t\t? `Command not found: ${tool}`\n\t\t\t\t\t: msg,\n\t\t\tfiles: [],\n\t\t}\n\t}\n}\n\n/**\n * Filter a list of file paths by a picomatch glob pattern.\n * When the pattern contains no `/`, files are matched at any depth (matchBase).\n * Dotfiles are included (dot: true).\n */\nexport function matchFiles(pattern: string, files: string[]): string[] {\n\tif (!pattern) return []\n\tconst matchBase = !pattern.includes(\"/\")\n\tconst isMatch = picomatch(pattern, {\n\t\tdot: true,\n\t\tposixSlashes: true,\n\t\tstrictBrackets: true,\n\t})\n\treturn files.filter((f) => {\n\t\tconst parts = f.split(\"/\")\n\t\tconst target = matchBase ? parts[parts.length - 1] : f\n\t\treturn isMatch(target)\n\t})\n}\n\n/**\n * Build a shell command string from a base command and a list of file paths.\n * File paths containing spaces are wrapped in double quotes.\n * If no files are provided, the base command is returned as-is.\n */\nexport function buildCommand(command: string, files: string[]): string {\n\tif (files.length === 0) return command\n\tconst quotedFiles = files.map((f) => (f.includes(\" \") ? `\"${f}\"` : f))\n\treturn `${command} ${quotedFiles.join(\" \")}`\n}\n\n/**\n * A resolved command string paired with whether it originated from a function.\n * Function-originated commands are run as-is; string commands get matched files appended.\n */\ninterface ResolvedCommand {\n\tcommand: string\n\tfromFunction: boolean\n}\n\n/**\n * Call a function command with matched files and normalize the result to ResolvedCommand[].\n */\nfunction resolveFunction(\n\tfn: (files: string[]) => string | string[],\n\tmatchedFiles: string[],\n): ResolvedCommand[] {\n\tconst resolved = fn(matchedFiles)\n\tconst items = Array.isArray(resolved) ? resolved : [resolved]\n\treturn items.map((command) => ({ command, fromFunction: true }))\n}\n\n/**\n * Resolve config commands for a glob entry into an array of resolved commands.\n * Function commands are called with matched filenames; string commands are kept as-is.\n * Each resolved entry tracks whether it came from a function (for file-append behavior).\n */\nfunction resolveCommands(\n\tcommands: string | string[] | ((filenames: string[]) => string | string[]),\n\tmatchedFiles: string[],\n): ResolvedCommand[] {\n\tif (typeof commands === \"function\") {\n\t\treturn resolveFunction(commands as (files: string[]) => string | string[], matchedFiles)\n\t}\n\tif (Array.isArray(commands)) {\n\t\tconst result: ResolvedCommand[] = []\n\t\tfor (const cmd of commands) {\n\t\t\tif (typeof cmd === \"function\") {\n\t\t\t\tresult.push(...resolveFunction(cmd, matchedFiles))\n\t\t\t} else {\n\t\t\t\tresult.push({ command: cmd, fromFunction: false })\n\t\t\t}\n\t\t}\n\t\treturn result\n\t}\n\treturn [{ command: commands as string, fromFunction: false }]\n}\n\n/**\n * Run resolved commands for a single glob entry, appending results.\n * Function-originated commands run as-is; string commands get matched files appended.\n * Returns false if any command fails (for fail-fast signaling).\n */\nasync function runCommandsForGlob(\n\tcmds: ResolvedCommand[],\n\tmatchedFiles: string[],\n\ttimeout: number,\n\tresults: CheckResult[],\n\trepoRoot: string,\n): Promise<boolean> {\n\tfor (const { command, fromFunction } of cmds) {\n\t\tconst fullCommand = fromFunction ? command : buildCommand(command, matchedFiles)\n\t\tdebug(\"runCommandsForGlob: running '%s'\", fullCommand)\n\t\tconst result = await runCommand(fullCommand, timeout, repoRoot)\n\t\tresults.push({ ...result, files: matchedFiles })\n\t\tif (!result.ok) {\n\t\t\tdebug(\"runCommandsForGlob: check failed, stopping (fail-fast)\")\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n/**\n * Run all user-defined checks from .cmintrc against staged files.\n * Returns a no-op result when no config exists.\n * Fail-fast: stops on first error.\n */\nexport async function runAllChecks(\n\trepoRoot: string,\n\tstagedFiles: string[],\n\ttimeout: number,\n): Promise<CheckResults> {\n\tdebug(\"runAllChecks: %d staged files, checking for config in %s\", stagedFiles.length, repoRoot)\n\n\tconst configPath = await detectConfig(repoRoot)\n\tif (!configPath) {\n\t\tdebug(\"runAllChecks: no config found, skipping checks\")\n\t\treturn { ok: true, results: [] }\n\t}\n\n\tconst config = await loadConfig(repoRoot)\n\tdebug(\"runAllChecks: loaded config with %d patterns\", Object.keys(config).length)\n\n\tconst results: CheckResult[] = []\n\n\tfor (const [glob, commands] of Object.entries(config)) {\n\t\tconst matchedFiles = matchFiles(glob, stagedFiles)\n\n\t\tif (matchedFiles.length === 0) {\n\t\t\tdebug(\"runAllChecks: no files matched pattern '%s'\", glob)\n\t\t\tcontinue\n\t\t}\n\t\tdebug(\"runAllChecks: pattern '%s' matched %d files\", glob, matchedFiles.length)\n\n\t\tconst cmds = resolveCommands(commands, matchedFiles)\n\t\tconst ok = await runCommandsForGlob(cmds, matchedFiles, timeout, results, repoRoot)\n\t\tif (!ok) return { ok: false, results }\n\t}\n\n\tconst ok = results.every((r) => r.ok)\n\tdebug(\"runAllChecks: complete \\u2014 ok=%s, %d results\", ok, results.length)\n\treturn { ok, results }\n}\n","import { readFile, writeFile } from \"node:fs/promises\"\nimport os from \"node:os\"\nimport { join } from \"node:path\"\nimport ini from \"ini\"\nimport { debug } from \"../utils/debug.js\"\nimport {\n\tformatProviderName,\n\tPROVIDER_CONFIGS,\n\tPROVIDER_ENV_KEYS,\n\ttype ProviderName,\n} from \"./provider.js\"\n\nconst CONFIG_PATH = join(os.homedir(), \".commit-mint\")\n\nexport interface Config {\n\tGROQ_API_KEY?: string\n\tCEREBRAS_API_KEY?: string\n\tMISTRAL_API_KEY?: string\n\tprovider?: string\n\tmodel?: string\n\tmodel_groq?: string\n\tmodel_cerebras?: string\n\tmodel_mistral?: string\n\tlocale?: string\n\t\"max-length\"?: string\n\ttype?: string\n\tproxy?: string\n\ttimeout?: string\n\t\"auto-accept\"?: string\n}\n\nconst defaults: Config = {\n\tprovider: \"groq\",\n\tmodel: \"openai/gpt-oss-20b\",\n\tlocale: \"en\",\n\t\"max-length\": \"100\",\n\ttype: \"\",\n\ttimeout: \"10000\",\n}\n\nexport async function readConfig(): Promise<Config> {\n\tdebug(\"readConfig: loading from %s\", CONFIG_PATH)\n\ttry {\n\t\tconst raw = await readFile(CONFIG_PATH, \"utf8\")\n\t\tconst parsed = ini.parse(raw)\n\t\tconst merged = { ...defaults, ...parsed }\n\t\tdebug(\"readConfig: loaded keys: %s\", Object.keys(merged).join(\", \"))\n\t\treturn merged\n\t} catch {\n\t\tdebug(\"readConfig: no config file, using defaults\")\n\t\treturn { ...defaults }\n\t}\n}\n\nexport async function writeConfig(updates: Record<string, string>) {\n\tconst existing = await readConfig()\n\tObject.assign(existing, updates)\n\tawait writeFile(CONFIG_PATH, ini.stringify(existing), \"utf8\")\n}\n\nexport async function getConfigValue(key: string): Promise<string | undefined> {\n\tconst config = await readConfig()\n\treturn config[key as keyof Config]\n}\n\nexport async function setConfigValue(key: string, value: string) {\n\tawait writeConfig({ [key]: value })\n}\n\nexport async function getApiKey(): Promise<string> {\n\tconst envKey = process.env.GROQ_API_KEY\n\tif (envKey) {\n\t\tdebug(\"getApiKey: found in env\")\n\t\treturn envKey\n\t}\n\n\tconst config = await readConfig()\n\tif (config.GROQ_API_KEY) {\n\t\tdebug(\"getApiKey: found in config\")\n\t\treturn config.GROQ_API_KEY\n\t}\n\n\tdebug(\"getApiKey: not found\")\n\tthrow new Error(\n\t\t\"Please set your Groq API key via `cmint config set GROQ_API_KEY=<your token>`. \" +\n\t\t\t\"Multi-provider: set `cmint config set provider=cerebras` for Cerebras, or `cmint config set provider=mistral` for Mistral.\",\n\t)\n}\n\nexport async function getProviderApiKey(provider: string): Promise<string> {\n\tconst envVar = PROVIDER_ENV_KEYS[provider as ProviderName]\n\tif (envVar) {\n\t\tconst envValue = process.env[envVar]\n\t\tif (envValue) {\n\t\t\tdebug(\"getProviderApiKey(%s): found in env\", provider)\n\t\t\treturn envValue\n\t\t}\n\t}\n\n\tconst config = await readConfig()\n\tconst configKey = PROVIDER_ENV_KEYS[provider as ProviderName]\n\tif (configKey && (config as Record<string, string | undefined>)[configKey]) {\n\t\tdebug(\"getProviderApiKey(%s): found in config\", provider)\n\t\tconst val = (config as Record<string, string | undefined>)[configKey]\n\t\treturn val as string\n\t}\n\n\tdebug(\"getProviderApiKey(%s): not found\", provider)\n\tthrow new Error(\n\t\t`Please set your ${formatProviderName(provider)} API key via \\`cmint config set ${envVar}=<your token>\\``,\n\t)\n}\n\n/** Check if a model name is the default for a provider OTHER than the given one. */\nfunction isOtherProviderDefault(model: string, provider: string): boolean {\n\tfor (const [name, config] of Object.entries(PROVIDER_CONFIGS)) {\n\t\tif (name !== provider && config.defaultModel === model) return true\n\t}\n\treturn false\n}\n\nexport function getModelForProvider(\n\tconfig: Config,\n\tprovider: string,\n\tdefaultModel: string,\n): string {\n\tconst modelKey = `model_${provider}` as keyof Config\n\tconst providerModel = config[modelKey]\n\tif (providerModel) return providerModel\n\n\tconst globalModel = config.model\n\t// Skip global model if it's another provider's default (cross-provider leak)\n\tif (globalModel && !isOtherProviderDefault(globalModel, provider)) return globalModel\n\n\treturn defaultModel\n}\n","import type { SpinnerResult } from \"@clack/prompts\"\nimport { extractToolName, isLintStagedMeta } from \"./hooks.js\"\n\nexport interface HookStep {\n\tstatus: \"started\" | \"completed\" | \"failed\"\n\tcommand: string\n\ttool: string\n}\n\nexport type ProgressHandler = (step: HookStep) => void\n\nconst ansiRe = new RegExp(`${String.fromCharCode(0x1b)}\\\\[[0-9;]*m`, \"g\")\n\nexport function createStderrParser(): (chunk: string) => HookStep[] {\n\tlet buffer = \"\"\n\treturn (chunk: string): HookStep[] => {\n\t\tbuffer += chunk\n\t\tconst steps: HookStep[] = []\n\t\tconst lines = buffer.split(\"\\n\")\n\t\tbuffer = lines.pop() ?? \"\"\n\t\tfor (const line of lines) {\n\t\t\t// Strip ANSI escape codes before matching (lint-staged wraps markers in color codes)\n\t\t\tconst clean = line.replace(ansiRe, \"\")\n\t\t\tconst match = clean.match(/\\[(STARTED|COMPLETED|FAILED)\\]\\s+(.+)/)\n\t\t\tif (!match) continue\n\t\t\tconst status = match[1].toLowerCase() as HookStep[\"status\"]\n\t\t\tconst command = match[2].trim()\n\t\t\tif (isLintStagedMeta(command)) continue\n\t\t\tconst tool = extractToolName(command) ?? command\n\t\t\tsteps.push({ status, command, tool })\n\t\t}\n\t\treturn steps\n\t}\n}\n\nexport function createProgressHandler(s: SpinnerResult): ProgressHandler {\n\treturn (step: HookStep) => {\n\t\tif (step.status === \"started\") {\n\t\t\ts.message(step.command)\n\t\t} else if (step.status === \"failed\") {\n\t\t\ts.message(step.command)\n\t\t}\n\t\t// completed: no action — post-commit parseToolChecks summary handles display\n\t}\n}\n","import type { ExecaError } from \"execa\"\nimport { execa } from \"execa\"\nimport { debug } from \"../utils/debug.js\"\nimport { createStderrParser, type ProgressHandler } from \"./hook-progress.js\"\n\nexport class KnownError extends Error {}\n\nexport async function assertGitRepo() {\n\tdebug(\"assertGitRepo\")\n\tconst { failed } = await execa(\"git\", [\"rev-parse\", \"--show-toplevel\"], {\n\t\treject: false,\n\t})\n\tif (failed) {\n\t\tthrow new KnownError(\"The current directory must be a Git repository!\")\n\t}\n}\n\nexport async function getRepoRoot() {\n\tconst { stdout } = await execa(\"git\", [\"rev-parse\", \"--show-toplevel\"])\n\tdebug(\"getRepoRoot:\", stdout.trim())\n\treturn stdout.trim()\n}\n\nexport interface StagedDiffResult {\n\tfiles: string[]\n\tdiff: string\n}\n\nexport interface ExcludedFilesResult {\n\texcludedFiles: string[]\n}\n\nexport type DiffResult = StagedDiffResult | ExcludedFilesResult | null\n\nexport interface ChangedFile {\n\tpath: string\n\tstatus: string\n\tstaged: boolean\n}\n\nconst DEFAULT_EXCLUDES = [\n\t\"package-lock.json\",\n\t\"node_modules/**\",\n\t\"dist/**\",\n\t\"build/**\",\n\t\".next/**\",\n\t\"coverage/**\",\n\t\"*.log\",\n\t\"*.min.js\",\n\t\"*.min.css\",\n\t\"*.lock\",\n\t\".DS_Store\",\n]\n\nexport function getDefaultExcludes(): string[] {\n\treturn [...DEFAULT_EXCLUDES]\n}\n\nexport async function getStagedDiff(exclude?: string[]): Promise<DiffResult> {\n\tconst excludeArgs = (exclude ?? []).map((e) => `:(exclude)${e}`)\n\tconst defaultExcludeArgs = DEFAULT_EXCLUDES.map((e) => `:(exclude)${e}`)\n\n\t// Check all staged files without excludes to detect \"all excluded\" case\n\tconst { stdout: allFiles } = await execa(\"git\", [\"diff\", \"--cached\", \"--name-only\"])\n\tif (!allFiles) {\n\t\tdebug(\"getStagedDiff: no staged files\")\n\t\treturn null\n\t}\n\n\t// Check staged files with excludes applied\n\tconst { stdout: files } = await execa(\"git\", [\n\t\t\"diff\",\n\t\t\"--cached\",\n\t\t\"--name-only\",\n\t\t...defaultExcludeArgs,\n\t\t...excludeArgs,\n\t])\n\n\tif (!files) {\n\t\t// All staged files were excluded\n\t\tconst excludedFiles = allFiles.split(\"\\n\").filter(Boolean)\n\t\tdebug(\"getStagedDiff: all files excluded:\", excludedFiles)\n\t\treturn { excludedFiles }\n\t}\n\n\tconst { stdout: diff } = await execa(\"git\", [\n\t\t\"diff\",\n\t\t\"--cached\",\n\t\t\"--diff-algorithm=minimal\",\n\t\t...defaultExcludeArgs,\n\t\t...excludeArgs,\n\t])\n\n\tdebug(\"getStagedDiff:\", files.split(\"\\n\").filter(Boolean).length, \"files,\", diff.length, \"chars\")\n\treturn { files: files.split(\"\\n\").filter(Boolean), diff }\n}\n\nexport async function stageAll() {\n\tdebug(\"stageAll: git add -A\")\n\tawait execa(\"git\", [\"add\", \"-A\"])\n}\n\nexport async function resetStaging() {\n\t// On a repo with no commits, `git reset HEAD` fails because HEAD doesn't\n\t// resolve yet (exit 128, \"ambiguous argument 'HEAD'\"). Fall back to clearing\n\t// the index without referencing HEAD so the first commit can proceed.\n\ttry {\n\t\tdebug(\"resetStaging: git reset HEAD\")\n\t\tawait execa(\"git\", [\"reset\", \"HEAD\"])\n\t} catch {\n\t\tdebug(\"resetStaging: HEAD missing, falling back to git rm --cached\")\n\t\tawait execa(\"git\", [\"rm\", \"-r\", \"--cached\", \"--quiet\", \".\"])\n\t}\n}\n\nexport async function getHead(): Promise<string | null> {\n\t// Returns null on a repo with no commits — `git rev-parse HEAD` exits 128\n\t// on a fresh repo. Callers treat \"headBefore === headAfter === null\" as\n\t// \"commit failed\" and \"null → SHA\" as \"first commit succeeded.\"\n\ttry {\n\t\tconst { stdout } = await execa(\"git\", [\"rev-parse\", \"HEAD\"])\n\t\treturn stdout.trim()\n\t} catch {\n\t\tdebug(\"getHead: HEAD does not exist (fresh repo)\")\n\t\treturn null\n\t}\n}\n\nexport async function getStatusShort() {\n\tconst { stdout } = await execa(\"git\", [\"status\", \"--short\"])\n\treturn stdout.trim()\n}\n\nexport async function getChangedFiles(): Promise<ChangedFile[]> {\n\tconst { stdout } = await execa(\"git\", [\"status\", \"--short\", \"--untracked-files=all\"])\n\tif (!stdout.trim()) return []\n\tconst files = stdout\n\t\t.split(\"\\n\")\n\t\t.filter(Boolean)\n\t\t.map((line) => {\n\t\t\tconst indexStatus = line[0]\n\t\t\treturn {\n\t\t\t\tstatus: line.slice(0, 2).trim(),\n\t\t\t\tpath: line.slice(3),\n\t\t\t\tstaged: indexStatus !== \" \" && indexStatus !== \"?\",\n\t\t\t}\n\t\t})\n\tdebug(\"getChangedFiles:\", files.length, \"files\")\n\treturn files\n}\n\n/**\n * Return staged file paths relative to the repository root, excluding deletions.\n *\n * `git status --short` reports paths relative to the current working directory,\n * but `.cmintrc` globs are written from the repo root (matching lint-staged\n * conventions). Use this helper whenever staged paths need to match repo-root\n * globs. `--diff-filter=d` excludes staged deletions so check commands don't\n * receive paths whose content no longer exists.\n */\nexport async function getStagedFiles(): Promise<string[]> {\n\tconst { stdout } = await execa(\"git\", [\"diff\", \"--cached\", \"--name-only\", \"--diff-filter=d\"])\n\tconst files = stdout\n\t\t.split(\"\\n\")\n\t\t.map((line) => line.trim())\n\t\t.filter(Boolean)\n\tdebug(\"getStagedFiles:\", files.length, \"files\")\n\treturn files\n}\n\n/**\n * Convert cwd-relative file paths to repo-root-relative paths.\n *\n * Uses `git rev-parse --show-prefix` to discover the prefix of the current\n * working directory relative to the repo root (e.g. `\"extension/\"` when cwd\n * is `<repo>/extension`, or `\"\"` when at the repo root). Useful when a caller\n * has cwd-relative paths from `getChangedFiles()` but needs to match them\n * against repo-root-relative `.cmintrc` globs (e.g. the auto-group flow,\n * which runs checks BEFORE files are staged — so `getStagedFiles()` can't be\n * used because the index doesn't yet contain those paths).\n */\nexport async function resolveToRepoRoot(cwdRelativePaths: string[]): Promise<string[]> {\n\tif (cwdRelativePaths.length === 0) return []\n\tconst { stdout } = await execa(\"git\", [\"rev-parse\", \"--show-prefix\"])\n\tconst prefix = stdout.trim()\n\tif (!prefix) return [...cwdRelativePaths]\n\treturn cwdRelativePaths.map((p) => `${prefix}${p}`)\n}\n\nexport async function stageFiles(paths: string[]): Promise<void> {\n\tdebug(\"stageFiles:\", paths)\n\tawait execa(\"git\", [\"add\", ...paths])\n}\n\nexport interface CommitResult {\n\tok: boolean\n\terror?: string\n\t/** Collected stderr from hooks/lint-staged — set on both success and failure */\n\tstderr?: string\n}\n\nexport async function attemptCommit(\n\tmessage: string,\n\textraArgs: string[] = [],\n\tonProgress?: ProgressHandler,\n): Promise<CommitResult> {\n\tdebug(\"attemptCommit:\", message, extraArgs.length ? extraArgs : \"(no extra args)\")\n\ttry {\n\t\tconst subprocess = execa(\"git\", [\"commit\", \"-m\", message, ...extraArgs])\n\n\t\t// Collect hook output (lint-staged, biome, etc.) for post-commit display\n\t\tconst stderrChunks: string[] = []\n\t\tconst parser = onProgress ? createStderrParser() : null\n\t\tsubprocess.stderr?.on(\"data\", (chunk: Buffer) => {\n\t\t\tconst text = chunk.toString()\n\t\t\tstderrChunks.push(text)\n\t\t\tif (parser && onProgress) {\n\t\t\t\tfor (const step of parser(text)) {\n\t\t\t\t\tonProgress(step)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\n\t\tawait subprocess\n\t\tdebug(\"attemptCommit: success\")\n\t\treturn { ok: true, stderr: stderrChunks.join(\"\") }\n\t} catch (error) {\n\t\tconst e = error as ExecaError\n\t\tdebug(\"attemptCommit: failed —\", e.message?.slice(0, 200))\n\t\treturn {\n\t\t\tok: false,\n\t\t\terror: e.message,\n\t\t\tstderr: typeof e.stderr === \"string\" ? e.stderr : \"\",\n\t\t}\n\t}\n}\n\nexport async function attemptCommitNoVerify(\n\tmessage: string,\n\tonProgress?: ProgressHandler,\n): Promise<CommitResult> {\n\tdebug(\"attemptCommitNoVerify:\", message)\n\treturn attemptCommit(message, [\"--no-verify\"], onProgress)\n}\n","export interface CommitGroup {\n\tname: string\n\tdescription: string\n\tfiles: string[]\n}\n\ninterface ScanState {\n\tobjects: unknown[]\n\tdepth: number\n\tstart: number\n}\n\n/** Coerce a parsed value into a CommitGroup, or null if it doesn't match the shape. */\nfunction coerceGroup(item: unknown): CommitGroup | null {\n\tif (\n\t\ttypeof item === \"object\" &&\n\t\titem !== null &&\n\t\t\"name\" in item &&\n\t\t\"description\" in item &&\n\t\t\"files\" in item &&\n\t\tArray.isArray((item as Record<string, unknown>).files)\n\t) {\n\t\tconst obj = item as Record<string, unknown>\n\t\treturn {\n\t\t\tname: String(obj.name),\n\t\t\tdescription: String(obj.description),\n\t\t\tfiles: (obj.files as unknown[]).filter((f) => typeof f === \"string\") as string[],\n\t\t}\n\t}\n\treturn null\n}\n\n/** Return the index of the closing quote of a string starting at text[start] === '\"'. */\nfunction skipString(text: string, start: number): number {\n\tlet i = start + 1\n\twhile (i < text.length) {\n\t\tconst ch = text[i]\n\t\tif (ch === \"\\\\\") {\n\t\t\ti += 2\n\t\t\tcontinue\n\t\t}\n\t\tif (ch === '\"') return i\n\t\ti++\n\t}\n\treturn i\n}\n\nfunction openBrace(state: ScanState, index: number): void {\n\tif (state.depth === 0) state.start = index\n\tstate.depth++\n}\n\nfunction pushParsedObject(objects: unknown[], candidate: string): void {\n\ttry {\n\t\tobjects.push(JSON.parse(candidate))\n\t} catch {\n\t\t// Not valid JSON — skip this candidate.\n\t}\n}\n\nfunction closeBrace(state: ScanState, text: string, index: number): void {\n\tif (state.depth === 0) return\n\tstate.depth--\n\tif (state.depth === 0 && state.start !== -1) {\n\t\tpushParsedObject(state.objects, text.slice(state.start, index + 1))\n\t\tstate.start = -1\n\t}\n}\n\n/**\n * Scan for top-level `{...}` objects, respecting string literals and escapes.\n * Used to recover groups when the model emits a single object or concatenated\n * objects instead of the requested JSON array.\n */\nfunction extractTopLevelObjects(text: string): unknown[] {\n\tconst state: ScanState = { objects: [], depth: 0, start: -1 }\n\tfor (let i = 0; i < text.length; i++) {\n\t\tconst ch = text[i]\n\t\t// Skip string literals so braces/quotes inside them don't affect depth.\n\t\tif (ch === '\"') {\n\t\t\ti = skipString(text, i)\n\t\t\tcontinue\n\t\t}\n\t\tif (ch === \"{\") {\n\t\t\topenBrace(state, i)\n\t\t\tcontinue\n\t\t}\n\t\tif (ch === \"}\") {\n\t\t\tcloseBrace(state, text, i)\n\t\t}\n\t}\n\treturn state.objects\n}\n\nexport function parseGroupingResponse(content: string): CommitGroup[] {\n\t// Strip think tags from reasoning models\n\tlet cleaned = content.replace(/<think[\\s\\S]*?<\\/think>/gi, \"\").trim()\n\t// Strip markdown code fences\n\tcleaned = cleaned\n\t\t.replace(/^```(?:json)?\\s*/i, \"\")\n\t\t.replace(/\\s*```$/i, \"\")\n\t\t.trim()\n\n\t// Path 1: extract the outermost JSON array — handles text before/after the array,\n\t// markdown fences, and trailing explanation prose. A truly empty array (\"[]\")\n\t// returns [] — the caller treats that as a low-quality result that triggers a\n\t// retry. If the array had items but none coerced to groups, fall through to\n\t// Path 2 so the object scan can attempt recovery.\n\tconst start = cleaned.indexOf(\"[\")\n\tconst end = cleaned.lastIndexOf(\"]\")\n\tif (start !== -1 && end !== -1 && end > start) {\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(cleaned.slice(start, end + 1)) as unknown\n\t\t\tif (Array.isArray(parsed)) {\n\t\t\t\tif (parsed.length === 0) return []\n\t\t\t\tconst groups = parsed.map(coerceGroup).filter((g): g is CommitGroup => g !== null)\n\t\t\t\tif (groups.length > 0) return groups\n\t\t\t}\n\t\t} catch {\n\t\t\t// Array span didn't parse (e.g. concatenated objects confuse the [ ] slice).\n\t\t\t// Fall through to the object scan.\n\t\t}\n\t}\n\n\t// Path 2: model emitted a single object or concatenated objects instead of an\n\t// array. Scan for top-level {...} objects and collect those that look like groups.\n\tconst groups = extractTopLevelObjects(cleaned)\n\t\t.map(coerceGroup)\n\t\t.filter((g): g is CommitGroup => g !== null)\n\tif (groups.length > 0) {\n\t\treturn groups\n\t}\n\n\tthrow new Error(\"AI response did not contain a JSON array\")\n}\n","import type { CommitGroup } from \"./grouping-parser.js\"\n\n/**\n * # Test/source reunification\n *\n * AI grouping prompts ask the model to keep a source file and its tests in the\n * same commit group, but the model frequently ignores that instruction (it\n * split `git.ts` from `git.test.ts` in the bug report that motivated this\n * module). The functions here provide a deterministic post-processing pass\n * that moves misplaced test files back into the group already containing\n * their source counterpart, regardless of what the model decided.\n *\n * Supported layouts (in priority order):\n * 1. Co-located: `src/foo.ts` ↔ `src/foo.test.ts`\n * 2. `__tests__/` mirror: `src/foo.ts` ↔ `src/__tests__/foo.test.ts`\n * 3. `tests/` or `test/` mirror: `src/foo.ts` ↔ `tests/foo.test.ts`\n *\n * Reunification runs inside `validateGroups()` (see `grouping.ts`) after\n * hallucinated-path filtering so only real files participate.\n */\n\n/** Suffixes that mark a file as a test companion of a same-name source. */\nconst TEST_SUFFIXES = [\".test\", \".spec\"] as const\n\n/**\n * Extensions tried when looking for a source counterpart for a test file. The\n * test file's own extension is usually the right one, but we also try common\n * alternates (a `.test.tsx` may back a `.tsx` or a `.ts`).\n */\nconst SOURCE_EXTENSIONS = [\".ts\", \".tsx\", \".js\", \".jsx\", \".mjs\", \".cjs\", \".mts\", \".cts\"] as const\n\n/** Matches a test file by extension regardless of which suffix it uses. */\nconst TEST_FILE_PATTERN = /\\.(?:test|spec)\\.(?:ts|tsx|js|jsx|mjs|cjs|mts|cts)$/\n\n/** Directory prefixes/segments that mirror source layout for non-co-located tests. */\nconst TEST_DIR_PREFIXES = [\"tests/\", \"test/\"] as const\n\n/** Marker segment for co-located `__tests__/` directories. */\nconst TESTS_DIR_SEGMENT = \"/__tests__/\"\n\nfunction stripTestSuffix(filename: string): string | null {\n\tfor (const suffix of TEST_SUFFIXES) {\n\t\tconst marker = `${suffix}.`\n\t\tconst idx = filename.lastIndexOf(marker)\n\t\tif (idx > 0) return filename.slice(0, idx)\n\t}\n\treturn null\n}\n\nfunction withEachExtension(base: string): string[] {\n\treturn SOURCE_EXTENSIONS.map((ext) => `${base}${ext}`)\n}\n\n/** Co-located: `dir/foo.test.ts` → `dir/foo.{ts,tsx,...}` */\nfunction colocatedCandidates(testPath: string): string[] {\n\tconst base = stripTestSuffix(testPath)\n\treturn base === null ? [] : withEachExtension(base)\n}\n\n/** `__tests__` mirror: `src/__tests__/foo.test.ts` → `src/foo.{ts,tsx,...}` */\nfunction testsDirCandidates(testPath: string): string[] {\n\tconst segmentIdx = testPath.indexOf(TESTS_DIR_SEGMENT)\n\tif (segmentIdx < 0) return []\n\tconst parentDir = testPath.slice(0, segmentIdx)\n\tconst filename = testPath.slice(segmentIdx + TESTS_DIR_SEGMENT.length)\n\tconst base = stripTestSuffix(filename)\n\tif (base === null) return []\n\treturn withEachExtension(`${parentDir}/${base}`)\n}\n\n/** `tests/` or `test/` mirror: `tests/services/foo.test.ts` → `src/services/foo.{ts,tsx,...}` */\nfunction prefixedDirCandidates(testPath: string): string[] {\n\tfor (const prefix of TEST_DIR_PREFIXES) {\n\t\tif (!testPath.startsWith(prefix)) continue\n\t\tconst rest = testPath.slice(prefix.length)\n\t\tconst base = stripTestSuffix(rest)\n\t\tif (base === null) return []\n\t\treturn withEachExtension(`src/${base}`)\n\t}\n\treturn []\n}\n\n/**\n * Compute candidate source paths for a test file in priority order: co-located\n * first, then `__tests__/` mirror, then `tests/`/`test/` mirror. Each mirror\n * emits one entry per `SOURCE_EXTENSIONS` candidate so the caller can match\n * against any of them.\n */\nexport function candidateSourcePaths(testPath: string): string[] {\n\treturn [\n\t\t...colocatedCandidates(testPath),\n\t\t...testsDirCandidates(testPath),\n\t\t...prefixedDirCandidates(testPath),\n\t]\n}\n\n/**\n * Resolve the unambiguous target group for a single test file, or `null` when\n * no source counterpart exists / matches more than one group (ambiguous). A\n * test whose candidates span multiple groups (e.g. `foo.ts` and `foo.tsx` in\n * different groups) is intentionally left alone rather than guessed.\n */\nfunction findTargetGroup(\n\ttestFile: string,\n\tcurrentGi: number,\n\tfileToGroup: Map<string, number>,\n): number | null {\n\tconst targetGroups = new Set<number>()\n\tfor (const candidate of candidateSourcePaths(testFile)) {\n\t\tconst targetGi = fileToGroup.get(candidate)\n\t\tif (targetGi !== undefined && targetGi !== currentGi) {\n\t\t\ttargetGroups.add(targetGi)\n\t\t}\n\t}\n\treturn targetGroups.size === 1 ? [...targetGroups][0] : null\n}\n\n/**\n * Find the unambiguous target group for each misplaced test file.\n *\n * Returns a map of `testFile → targetGroupIndex`. A test is only moved when\n * its candidate source matches exactly one other group; ambiguous matches are\n * skipped (see {@link findTargetGroup}).\n */\nfunction findMoves(groups: CommitGroup[], fileToGroup: Map<string, number>): Map<string, number> {\n\tconst moves = new Map<string, number>()\n\n\tfor (let gi = 0; gi < groups.length; gi++) {\n\t\tfor (const file of groups[gi].files) {\n\t\t\tif (moves.has(file) || !TEST_FILE_PATTERN.test(file)) continue\n\t\t\tconst target = findTargetGroup(file, gi, fileToGroup)\n\t\t\tif (target !== null) moves.set(file, target)\n\t\t}\n\t}\n\n\treturn moves\n}\n\n/**\n * Apply queued moves to a fresh copy of the groups array. Tests are removed\n * from their original group and appended to the target group. Groups left\n * empty by moves are dropped.\n */\nfunction applyMoves(groups: CommitGroup[], moves: Map<string, number>): CommitGroup[] {\n\tconst result = groups.map((g) => ({ ...g, files: [...g.files] }))\n\tconst movedFiles = new Set(moves.keys())\n\n\tconst additionsByGroup = new Map<number, string[]>()\n\tfor (const [file, toGroup] of moves) {\n\t\tconst bucket = additionsByGroup.get(toGroup) ?? []\n\t\tbucket.push(file)\n\t\tadditionsByGroup.set(toGroup, bucket)\n\t}\n\n\tfor (let gi = 0; gi < result.length; gi++) {\n\t\tif (movedFiles.size > 0) {\n\t\t\tresult[gi].files = result[gi].files.filter((f) => !movedFiles.has(f))\n\t\t}\n\t\tconst additions = additionsByGroup.get(gi)\n\t\tif (!additions) continue\n\t\tconst existing = new Set(result[gi].files)\n\t\tfor (const file of additions) {\n\t\t\t// Additions come from other groups so they should always be new; the\n\t\t\t// de-dupe guard exists to keep the invariant explicit.\n\t\t\tif (!existing.has(file)) result[gi].files.push(file)\n\t\t}\n\t}\n\n\treturn result.filter((g) => g.files.length > 0)\n}\n\n/**\n * Move test files (`.test.*` / `.spec.*`) into the group that already contains\n * their source counterpart. Returns the same array reference if no moves were\n * needed; otherwise returns a fresh array of new group objects.\n *\n * See module doc for the matching algorithm.\n */\nexport function reuniteTestsWithSources(groups: CommitGroup[]): CommitGroup[] {\n\tif (groups.length === 0) return groups\n\n\tconst fileToGroup = new Map<string, number>()\n\tfor (let gi = 0; gi < groups.length; gi++) {\n\t\tfor (const file of groups[gi].files) fileToGroup.set(file, gi)\n\t}\n\n\tconst moves = findMoves(groups, fileToGroup)\n\tif (moves.size === 0) return groups\n\n\treturn applyMoves(groups, moves)\n}\n","import { debug } from \"../utils/debug.js\"\nimport { mapGroqError } from \"./ai.js\"\nimport type { ChangedFile } from \"./git.js\"\nimport { getDefaultExcludes } from \"./git.js\"\nimport { type CommitGroup, parseGroupingResponse } from \"./grouping-parser.js\"\nimport { reuniteTestsWithSources } from \"./grouping-reunite.js\"\nimport {\n\ttype ChatClient,\n\tcreateProvider,\n\tformatProviderName,\n\ttype ProviderName,\n} from \"./provider.js\"\n\nexport type { CommitGroup } from \"./grouping-parser.js\"\nexport { reuniteTestsWithSources } from \"./grouping-reunite.js\"\n\nexport interface GroupingResult {\n\tgroups: CommitGroup[]\n\texcluded: string[]\n}\n\nfunction matchesExcludePattern(filePath: string, pattern: string): boolean {\n\tif (pattern === filePath) return true\n\tif (pattern.endsWith(\"/**\")) {\n\t\tconst prefix = pattern.slice(0, -3)\n\t\treturn filePath === prefix || filePath.startsWith(`${prefix}/`)\n\t}\n\tif (pattern.startsWith(\"*.\")) {\n\t\tconst suffix = pattern.slice(1)\n\t\treturn filePath.endsWith(suffix)\n\t}\n\treturn false\n}\n\n/** Lockfiles that should be kept when their companion manifest is present */\nconst LOCKFILE_COMPANIONS: Record<string, string> = {\n\t\"package-lock.json\": \"package.json\",\n\t\"pnpm-lock.yaml\": \"package.json\",\n\t\"yarn.lock\": \"package.json\",\n\t\"bun.lock\": \"package.json\",\n\t\"bun.lockb\": \"package.json\",\n}\n\nexport function filterExcludedFiles(files: ChangedFile[]): {\n\tincluded: ChangedFile[]\n\texcluded: string[]\n} {\n\tconst patterns = getDefaultExcludes()\n\tconst included: ChangedFile[] = []\n\tconst excluded: ChangedFile[] = []\n\tconst filePaths = new Set(files.map((f) => f.path))\n\n\tfor (const file of files) {\n\t\tconst isExcluded = patterns.some((pattern) => matchesExcludePattern(file.path, pattern))\n\t\tif (isExcluded) {\n\t\t\texcluded.push(file)\n\t\t} else {\n\t\t\tincluded.push(file)\n\t\t}\n\t}\n\n\t// Promote lockfiles whose companion manifest is present\n\tconst stillExcluded: string[] = []\n\tfor (const file of excluded) {\n\t\tconst companion = LOCKFILE_COMPANIONS[file.path]\n\t\tif (companion && filePaths.has(companion)) {\n\t\t\tincluded.push(file)\n\t\t} else {\n\t\t\tstillExcluded.push(file.path)\n\t\t}\n\t}\n\n\tdebug(\"filterExcludedFiles: %d included, %d excluded\", included.length, stillExcluded.length)\n\treturn { included, excluded: stillExcluded }\n}\n\nfunction statusIndicator(status: string): string {\n\tswitch (status) {\n\t\tcase \"M\":\n\t\t\treturn \"modified\"\n\t\tcase \"A\":\n\t\t\treturn \"added\"\n\t\tcase \"D\":\n\t\t\treturn \"deleted\"\n\t\tcase \"R\":\n\t\t\treturn \"renamed\"\n\t\tcase \"C\":\n\t\t\treturn \"copied\"\n\t\tcase \"?\":\n\t\tcase \"??\":\n\t\t\treturn \"untracked\"\n\t\tdefault:\n\t\t\treturn \"changed\"\n\t}\n}\n\nexport function buildFileSummary(files: ChangedFile[]): string {\n\treturn files.map((f) => `${f.path} (${statusIndicator(f.status)})`).join(\"\\n\")\n}\n\nexport function buildGroupingSystemPrompt(): string {\n\treturn [\n\t\t\"You are analyzing changed files in a git repository. Group them into logical commits based on what changed and why. Each group should be a coherent unit of work.\",\n\t\t\"\",\n\t\t\"Rules:\",\n\t\t\"- ALWAYS keep a test file in the same group as the source file it tests. Examples: `foo.test.ts` stays with `foo.ts`; `__tests__/foo.test.ts` stays with `foo.ts` in the parent directory; `tests/foo.test.ts` stays with `src/foo.ts`. Never put source and its tests in separate groups.\",\n\t\t\"- Group by feature, fix, or concern (e.g., 'Frontend refactor', 'API changes')\",\n\t\t\"- Keep related files together (e.g., a component + its test, a model + its migration)\",\n\t\t\"- Separate documentation changes (*.md files, docs/) from code changes — put docs in their own group\",\n\t\t\"- Do not split a single logical change across multiple groups\",\n\t\t\"- If a file does not clearly belong to any group, include it anyway — do not omit files\",\n\t\t\"\",\n\t\t\"Output format: JSON array of objects with keys 'name', 'description', 'files'.\",\n\t\t\"name: short label (3-5 words)\",\n\t\t\"description: 1-2 sentences explaining what this group changes\",\n\t\t\"files: array of exact file paths from the input\",\n\t\t\"\",\n\t\t\"Output ONLY valid JSON. No markdown fences, no explanation.\",\n\t].join(\"\\n\")\n}\n\nfunction buildGroupingUserPrompt(summary: string): string {\n\treturn [\"Group the following changed files into logical commits:\", \"\", summary].join(\"\\n\")\n}\n\nexport function buildRetryGroupingPrompt(): string {\n\treturn [\n\t\t\"PREVIOUS ATTEMPT FAILED: You grouped all files into a single group.\",\n\t\t\"\",\n\t\t\"You MUST split the files into at least 2 groups based on what changed and why.\",\n\t\t\"\",\n\t\t\"Look for these natural split points:\",\n\t\t\"- Different features or modules (e.g., different directories)\",\n\t\t\"- New files vs modified files vs deleted files\",\n\t\t\"- Configuration changes vs code changes\",\n\t\t\"- Documentation vs implementation\",\n\t\t\"\",\n\t\t\"Do NOT split a source file from its tests — keep `foo.ts` and `foo.test.ts` in the same group.\",\n\t\t\"\",\n\t\t\"If unsure, err on the side of MORE groups, not fewer.\",\n\t\t\"\",\n\t\t\"Output format: JSON array of objects with keys 'name', 'description', 'files'.\",\n\t\t\"name: short label (3-5 words)\",\n\t\t\"description: 1-2 sentences explaining what this group changes\",\n\t\t\"files: array of exact file paths from the input\",\n\t\t\"\",\n\t\t\"Output ONLY valid JSON. No markdown fences, no explanation.\",\n\t].join(\"\\n\")\n}\n\nexport async function generateGroups(\n\tfiles: ChangedFile[],\n\tapiKey: string,\n\tmodel?: string,\n\ttimeout?: number,\n\tprovider?: ProviderName,\n\tproxy?: string,\n): Promise<GroupingResult> {\n\tdebug(\"generateGroups: %d files, model=%s\", files.length, model ?? \"default\")\n\n\tconst { included, excluded } = filterExcludedFiles(files)\n\n\tif (included.length === 0) {\n\t\tdebug(\"generateGroups: no files to group after exclusion\")\n\t\treturn { groups: [], excluded }\n\t}\n\n\tconst summary = buildFileSummary(included)\n\tconst systemPrompt = buildGroupingSystemPrompt()\n\tconst userPrompt = buildGroupingUserPrompt(summary)\n\n\tdebug(\"File summary:\\n%s\", summary)\n\tdebug(\"User prompt length: %d chars\", userPrompt.length)\n\n\tconst timeoutMs = timeout ?? 60000\n\tconst { client, model: resolvedModel } = createProvider({\n\t\tprovider: provider ?? \"groq\",\n\t\tapiKey,\n\t\tmodelOverride: model,\n\t\ttimeout: timeoutMs,\n\t\tbaseURLOverride: proxy,\n\t})\n\n\ttry {\n\t\tlet rawGroups = await callGroupingAI(client, resolvedModel, systemPrompt, userPrompt)\n\t\tdebug(\"generateGroups: parsed %d raw groups\", rawGroups.length)\n\t\tlet validated = validateGroups(rawGroups, included)\n\t\tdebug(\"generateGroups: %d validated groups\", validated.length)\n\n\t\t// Retry once if grouping quality is low. Evaluate against the raw AI result:\n\t\t// validateGroups() silently adds an \"Other changes\" group for any ungrouped\n\t\t// files, which would mask an empty model response (turning [] into a single\n\t\t// catch-all) and skip the retry the user needs.\n\t\tif (isLowQualityGrouping(rawGroups, included)) {\n\t\t\tdebug(\"generateGroups: low quality result, retrying with stricter prompt\")\n\t\t\tconst retryPrompt = buildRetryGroupingPrompt()\n\t\t\trawGroups = await callGroupingAI(client, resolvedModel, retryPrompt, userPrompt)\n\t\t\tdebug(\"generateGroups retry: parsed %d raw groups\", rawGroups.length)\n\t\t\tvalidated = validateGroups(rawGroups, included)\n\t\t\tdebug(\"generateGroups retry: %d validated groups\", validated.length)\n\t\t}\n\n\t\treturn { groups: validated, excluded }\n\t} catch (error) {\n\t\tdebug(\"generateGroups error: %s\", error instanceof Error ? error.message : String(error))\n\t\tconst providerLabel = provider ? formatProviderName(provider) : undefined\n\t\tthrow mapGroqError(error, providerLabel)\n\t}\n}\n\nasync function callGroupingAI(\n\tclient: ChatClient,\n\tmodel: string,\n\tsystemPrompt: string,\n\tuserPrompt: string,\n): Promise<CommitGroup[]> {\n\tconst completion = (await client.chat.completions.create({\n\t\tmessages: [\n\t\t\t{ role: \"system\", content: systemPrompt },\n\t\t\t{ role: \"user\", content: userPrompt },\n\t\t],\n\t\tmodel,\n\t\ttemperature: 0.3,\n\t\tmax_tokens: 2048,\n\t})) as { choices: { message?: { content?: string }; finish_reason?: string }[] }\n\n\tconst rawContent = completion.choices[0]?.message?.content\n\tconst content = typeof rawContent === \"string\" ? rawContent.trim() : \"\"\n\n\tdebug(\n\t\t\"callGroupingAI response: choices=%d, finishReason=%s, contentLen=%d\",\n\t\tcompletion.choices.length,\n\t\tcompletion.choices[0]?.finish_reason ?? \"(none)\",\n\t\tcontent.length,\n\t)\n\tdebug(\"callGroupingAI raw content: %s\", content.slice(0, 500) || \"(empty)\")\n\n\tif (!content) {\n\t\tthrow new Error(\"AI returned an empty grouping response\")\n\t}\n\n\treturn parseGroupingResponse(content)\n}\n\n/** Minimum file count where a single-group result is considered low quality */\nconst MIN_FILES_FOR_QUALITY_CHECK = 5\n\nexport function isLowQualityGrouping(groups: CommitGroup[], allFiles: ChangedFile[]): boolean {\n\t// No files to group → empty grouping is the correct result, not low quality.\n\tif (allFiles.length === 0) return false\n\t// Files were provided but the model returned no groups — retry once before\n\t// falling back to \"Other changes\" so the user still gets a sensible commit.\n\tif (groups.length === 0) return true\n\tif (allFiles.length < MIN_FILES_FOR_QUALITY_CHECK) return false\n\treturn groups.length === 1\n}\n\nexport function validateGroups(groups: CommitGroup[], allFiles: ChangedFile[]): CommitGroup[] {\n\tconst validPaths = new Set(allFiles.map((f) => f.path))\n\tconst seen = new Set<string>()\n\tconst validated: CommitGroup[] = []\n\n\tfor (const group of groups) {\n\t\tconst uniqueFiles = group.files.filter((f) => {\n\t\t\tif (!validPaths.has(f)) return false // AI-hallucinated path\n\t\t\tif (seen.has(f)) return false // duplicate across groups\n\t\t\tseen.add(f)\n\t\t\treturn true\n\t\t})\n\n\t\tif (uniqueFiles.length > 0) {\n\t\t\tvalidated.push({\n\t\t\t\tname: group.name,\n\t\t\t\tdescription: group.description,\n\t\t\t\tfiles: uniqueFiles,\n\t\t\t})\n\t\t}\n\t}\n\n\t// Move misplaced test files back into their source file's group. Done after\n\t// path filtering (so hallucinated tests don't trigger moves) and before\n\t// orphan bucketing (so a source-less test still gets caught by \"Other\n\t// changes\"). `seen` is unaffected by inter-group moves.\n\tconst reunited = reuniteTestsWithSources(validated)\n\tif (reunited !== validated) {\n\t\tdebug(\"validateGroups: reunited %d groups after test/source merge\", reunited.length)\n\t}\n\n\t// Find files not in any group\n\tconst ungrouped = allFiles.filter((f) => !seen.has(f.path))\n\n\tif (ungrouped.length > 0) {\n\t\tdebug(\"validateGroups: %d ungrouped files added to 'Other changes'\", ungrouped.length)\n\t\treunited.push({\n\t\t\tname: \"Other changes\",\n\t\t\tdescription: \"Miscellaneous changes that did not fit into other groups\",\n\t\t\tfiles: ungrouped.map((f) => f.path),\n\t\t})\n\t}\n\n\treturn reunited\n}\n","let agentMode = false\n\nexport function setAgentMode(value: boolean): void {\n\tagentMode = value\n}\n\nexport function isAgentMode(): boolean {\n\treturn agentMode\n}\n\nexport interface AgentCommit {\n\tmessage: string\n\thash: string\n\tfiles: string[]\n\tgroupName?: string\n}\n\nexport interface AgentResult {\n\tstatus: \"success\" | \"failure\" | \"no_changes\" | \"cancelled\"\n\tcommits: AgentCommit[]\n\terrors?: string[]\n}\n\nexport const EXIT_CODES = {\n\tSUCCESS: 0,\n\tGENERIC: 1,\n\tNO_CHANGES: 2,\n\tGIT: 3,\n\tAI: 4,\n\tCHECK: 5,\n\tHOOK: 6,\n} as const\n\nexport function writeAgentResult(result: AgentResult): void {\n\tprocess.stdout.write(`${JSON.stringify(result)}\\n`)\n}\n","import { createHash } from \"node:crypto\"\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\"\nimport os from \"node:os\"\nimport { join } from \"node:path\"\nimport { debug } from \"./debug.js\"\n\nconst CACHE_DIR = join(os.homedir(), \".cache\", \"commit-mint\")\n\nfunction repoHash(repoPath: string): string {\n\treturn createHash(\"sha256\").update(repoPath).digest(\"hex\").slice(0, 12)\n}\n\nfunction cachePath(repoPath: string): string {\n\treturn join(CACHE_DIR, `${repoHash(repoPath)}.json`)\n}\n\nexport interface CachedCommit {\n\tmessage: string\n\ttimestamp: number\n\trepoPath: string\n}\n\nexport async function saveCachedCommit(repoPath: string, message: string) {\n\tawait mkdir(CACHE_DIR, { recursive: true })\n\tconst data: CachedCommit = {\n\t\tmessage,\n\t\ttimestamp: Date.now(),\n\t\trepoPath,\n\t}\n\tconst path = cachePath(repoPath)\n\tdebug(\"saveCachedCommit: saving to %s\", path)\n\tawait writeFile(path, JSON.stringify(data, null, 2), \"utf8\")\n}\n\nexport async function loadCachedCommit(repoPath: string): Promise<CachedCommit | null> {\n\tconst path = cachePath(repoPath)\n\tdebug(\"loadCachedCommit: loading from %s\", path)\n\ttry {\n\t\tconst raw = await readFile(path, \"utf8\")\n\t\tconst data = JSON.parse(raw) as CachedCommit\n\t\tdebug(\"loadCachedCommit: found message from %s\", new Date(data.timestamp).toISOString())\n\t\treturn data\n\t} catch {\n\t\tdebug(\"loadCachedCommit: no cached commit found\")\n\t\treturn null\n\t}\n}\n","import { debug } from \"../utils/debug.js\"\nimport { readConfig, writeConfig } from \"./config.js\"\n\n/** Parse a stored `auto-accept` INI value into a boolean.\n * Accepts true variants (\"true\", \"1\", \"yes\" — case-insensitive).\n * Handles boolean values from ini.parse (which converts unquoted\n * `true`/`false` to actual booleans).\n * Everything else (including undefined) returns false. */\nexport function parseAutoAcceptValue(value: unknown): boolean {\n\tif (typeof value === \"boolean\") return value\n\tif (typeof value !== \"string\" || !value) return false\n\treturn [\"true\", \"1\", \"yes\"].includes(value.toLowerCase())\n}\n\n/** Read the persisted auto-accept preference from `~/.commit-mint`. */\nexport async function getAutoAccept(): Promise<boolean> {\n\tconst config = await readConfig()\n\tconst raw = config[\"auto-accept\"]\n\tconst enabled = parseAutoAcceptValue(raw)\n\tdebug(\"getAutoAccept: raw=%s enabled=%s\", raw, enabled)\n\treturn enabled\n}\n\n/** Persist the auto-accept preference to `~/.commit-mint`. */\nexport async function setAutoAccept(enabled: boolean): Promise<void> {\n\tconst value = enabled ? \"true\" : \"false\"\n\tdebug(\"setAutoAccept: %s\", value)\n\tawait writeConfig({ \"auto-accept\": value })\n}\n","import * as p from \"@clack/prompts\"\nimport { bold, cyan, dim, green, red, yellow } from \"kolorist\"\nimport type { ChangedFile } from \"../services/git.js\"\nimport type { CommitGroup } from \"../services/grouping.js\"\nimport { debug } from \"../utils/debug.js\"\n\nexport async function showGroupingConfirmation(\n\tgroups: CommitGroup[],\n\texcluded: string[],\n): Promise<boolean> {\n\tdebug(\"showGroupingConfirmation: %d groups, %d excluded\", groups.length, excluded.length)\n\n\tconst lines: string[] = []\n\n\tfor (const group of groups) {\n\t\tlines.push(bold(group.name))\n\t\tlines.push(` ${dim(group.description)}`)\n\t\tlines.push(` ${green(String(group.files.length))} file${group.files.length !== 1 ? \"s\" : \"\"}`)\n\t\tfor (const file of group.files) {\n\t\t\tlines.push(` ${dim(\"•\")} ${file}`)\n\t\t}\n\t\tlines.push(\"\")\n\t}\n\n\tif (excluded.length > 0) {\n\t\tlines.push(dim(`Excluded: ${excluded.length} file${excluded.length !== 1 ? \"s\" : \"\"}`))\n\t\tfor (const file of excluded) {\n\t\t\tlines.push(` ${dim(\"•\")} ${dim(file)}`)\n\t\t}\n\t}\n\n\tp.note(lines.join(\"\\n\"), \"Proposed commit groups\")\n\n\tconst choice = await p.select({\n\t\tmessage: \"Proceed with these groupings?\",\n\t\toptions: [\n\t\t\t{ label: \"Yes, commit all groups\", value: \"yes\" },\n\t\t\t{ label: \"No, cancel\", value: \"no\" },\n\t\t],\n\t})\n\n\tif (p.isCancel(choice) || choice === \"no\") {\n\t\tdebug(\"showGroupingConfirmation: user cancelled\")\n\t\treturn false\n\t}\n\n\tdebug(\"showGroupingConfirmation: user confirmed\")\n\treturn true\n}\n\nexport function showGroupProgress(current: number, total: number, groupName: string): void {\n\tp.log.info(`Commit group ${current} of ${total}: ${cyan(`\"${groupName}\"`)}`)\n}\n\nconst statusLabel = (status: string): string => {\n\tswitch (status) {\n\t\tcase \"M\":\n\t\t\treturn yellow(\"M\")\n\t\tcase \"A\":\n\t\t\treturn green(\"A\")\n\t\tcase \"D\":\n\t\t\treturn red(\"D\")\n\t\tcase \"?\":\n\t\tcase \"??\":\n\t\t\treturn cyan(\"?\")\n\t\tdefault:\n\t\t\treturn dim(status)\n\t}\n}\n\n/** Display a table of changed files with status indicators */\nexport function showChangedFilesTable(files: ChangedFile[]): void {\n\tif (files.length === 0) return\n\n\tconst lines = files.map((f) => ` ${statusLabel(f.status)} ${f.path}`)\n\tp.note(lines.join(\"\\n\"), `${files.length} file${files.length !== 1 ? \"s\" : \"\"} changed`)\n}\n\n/** Display a compact grouping summary (only shown when >1 group) */\nexport function showGroupingSummary(groups: CommitGroup[]): void {\n\tif (groups.length <= 1) return\n\n\tconst lines = groups.map(\n\t\t(g) => `${bold(g.name)} ${dim(\"—\")} ${g.files.length} file${g.files.length !== 1 ? \"s\" : \"\"}`,\n\t)\n\tp.note(lines.join(\"\\n\"), \"Commit groups\")\n}\n\n/** Display combined view: files with status indicators grouped by commit group */\nexport function showGroupedFiles(groups: CommitGroup[], changedFiles: ChangedFile[]): void {\n\tconst statusMap = new Map(changedFiles.map((f) => [f.path, f.status]))\n\n\tconst lines: string[] = []\n\n\tfor (let i = 0; i < groups.length; i++) {\n\t\tconst group = groups[i]\n\t\tlines.push(\n\t\t\t`${bold(group.name)} ${dim(\"—\")} ${group.files.length} file${group.files.length !== 1 ? \"s\" : \"\"}`,\n\t\t)\n\t\tfor (const file of group.files) {\n\t\t\tconst status = statusMap.get(file) ?? \"M\"\n\t\t\tlines.push(` ${statusLabel(status)} ${file}`)\n\t\t}\n\t\tif (i < groups.length - 1) {\n\t\t\tlines.push(\"\")\n\t\t}\n\t}\n\n\tp.note(lines.join(\"\\n\"), \"Commit groups\")\n}\n","import { spawn } from \"node:child_process\"\nimport { debug } from \"../utils/debug.js\"\n\n/** Milliseconds to wait after stdin closes for quick exit failures. */\nconst GRACE_PERIOD_MS = 150\n\nexport async function copyToClipboard(content: string): Promise<boolean> {\n\tconst commands: [string, string[]][] = [\n\t\t[\"wl-copy\", []],\n\t\t[\"xclip\", [\"-selection\", \"clipboard\"]],\n\t\t[\"xsel\", [\"--clipboard\", \"--input\"]],\n\t\t[\"pbcopy\", []],\n\t]\n\n\tfor (const [cmd, args] of commands) {\n\t\ttry {\n\t\t\tconst success = await tryCopy(cmd, args, content)\n\t\t\tif (success) return true\n\t\t} catch {}\n\t}\n\treturn false\n}\n\n/**\n * Try to copy content using a single clipboard tool.\n *\n * Waits a short grace period after stdin closes to detect quick failures\n * (e.g. wl-copy on non-Wayland, missing display). If the tool survives\n * the grace period, assumes success — clipboard tools like xclip and\n * wl-copy hold the selection open indefinitely, so we can't wait for exit.\n */\n/**\n * Evaluate clipboard tool status after the grace period.\n * If the child already exited, report based on exit code.\n * If still alive, assume success (clipboard tools hold selection open).\n */\nfunction handleGracePeriod(\n\tsettled: boolean,\n\texitCode: number | null,\n\tstderrChunks: Buffer[],\n\tchild: ReturnType<typeof spawn>,\n\tdone: (result: boolean, reason?: string) => void,\n) {\n\tif (settled) return\n\n\tif (exitCode !== null) {\n\t\tif (exitCode === 0) {\n\t\t\tdone(true, \"exited 0\")\n\t\t} else {\n\t\t\tconst stderr = Buffer.concat(stderrChunks).toString().trim()\n\t\t\tdone(false, `exit ${exitCode}${stderr ? `: ${stderr}` : \"\"}`)\n\t\t}\n\t\treturn\n\t}\n\n\t// Child still alive — assume success. Clipboard tools\n\t// (xclip, wl-copy) hold the selection open, so they\n\t// don't exit until something else takes the clipboard.\n\tchild.unref()\n\tdone(true)\n}\n\nfunction tryCopy(cmd: string, args: string[], content: string): Promise<boolean> {\n\treturn new Promise<boolean>((resolve) => {\n\t\tdebug(\"clipboard: trying %s\", cmd)\n\n\t\tconst child = spawn(cmd, args, {\n\t\t\tstdio: [\"pipe\", \"ignore\", \"pipe\"],\n\t\t})\n\n\t\tlet settled = false\n\t\tconst stderrChunks: Buffer[] = []\n\n\t\tchild.stderr?.on(\"data\", (chunk: Buffer) => {\n\t\t\tstderrChunks.push(chunk)\n\t\t})\n\n\t\tconst done = (result: boolean, reason?: string) => {\n\t\t\tif (settled) return\n\t\t\tsettled = true\n\t\t\tdebug(\"clipboard: %s %s%s\", cmd, result ? \"ok\" : \"failed\", reason ? ` (${reason})` : \"\")\n\t\t\tresolve(result)\n\t\t}\n\n\t\t// Command not found (ENOENT)\n\t\tchild.on(\"error\", (err) => {\n\t\t\tdone(false, err.message)\n\t\t})\n\n\t\t// Track exit for grace-period detection\n\t\tlet exitCode: number | null = null\n\t\tchild.on(\"exit\", (code) => {\n\t\t\texitCode = code\n\t\t})\n\n\t\tchild.stdin.write(content, (err) => {\n\t\t\tif (err) {\n\t\t\t\tdone(false, \"stdin write error\")\n\t\t\t\treturn\n\t\t\t}\n\t\t\tchild.stdin.end(() => {\n\t\t\t\t// stdin closed — start grace period to detect quick failures\n\t\t\t\tsetTimeout(\n\t\t\t\t\t() => handleGracePeriod(settled, exitCode, stderrChunks, child, done),\n\t\t\t\t\tGRACE_PERIOD_MS,\n\t\t\t\t)\n\t\t\t})\n\t\t})\n\t})\n}\n","import * as p from \"@clack/prompts\"\nimport { bold, cyan, dim, green, red, yellow } from \"kolorist\"\nimport { copyToClipboard } from \"../services/clipboard.js\"\nimport type { HookError } from \"../services/hooks.js\"\nimport { debug } from \"../utils/debug.js\"\n\nexport type RecoveryResult = \"committed\" | \"cancelled\" | \"failed\"\n\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Recovery menu with recursive retry path\n// biome-ignore lint/complexity/noExcessiveLinesPerFunction: Interactive TUI — format errors, handle 5 menu actions, recursive retry\nexport async function showRecoveryMenu(\n\terrors: HookError[],\n\tonRetry: () => Promise<boolean>,\n\tonSkipHooks: (message: string) => Promise<boolean>,\n\tonRestage: () => Promise<boolean>,\n\tmessage: string,\n\trawStderr: string,\n): Promise<RecoveryResult> {\n\tdebug(\"showRecoveryMenu: %d errors\", errors.length)\n\n\tlet clipboardCopied = false\n\tlet showNote = true\n\n\twhile (true) {\n\t\tif (showNote) {\n\t\t\tp.note(\n\t\t\t\terrors.map((e) => ` ${red(\"•\")} [${e.tool}] ${e.message}`).join(\"\\n\"),\n\t\t\t\tred(bold(\"Pre-commit hook failed\")),\n\t\t\t)\n\t\t\tshowNote = false\n\t\t}\n\n\t\tconst choice = await p.select({\n\t\t\tmessage: \"What do you want to do?\",\n\t\t\toptions: [\n\t\t\t\t{\n\t\t\t\t\tlabel: clipboardCopied\n\t\t\t\t\t\t? `${green(\"✓\")} Copy error report to clipboard`\n\t\t\t\t\t\t: \"Copy error report to clipboard\",\n\t\t\t\t\tvalue: \"clipboard\",\n\t\t\t\t\thint: clipboardCopied ? \"Copied!\" : \"Paste into another terminal for an AI agent\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: \"View full error output\",\n\t\t\t\t\tvalue: \"view\",\n\t\t\t\t\thint: \"Show the raw stderr from hooks\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: \"Skip hooks and commit (--no-verify)\",\n\t\t\t\t\tvalue: \"skip\",\n\t\t\t\t\thint: \"Commit anyway, fix later\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: \"Re-stage files and retry\",\n\t\t\t\t\tvalue: \"restage\",\n\t\t\t\t\thint: \"Pick up fixes from another terminal\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: \"Edit commit message\",\n\t\t\t\t\tvalue: \"edit\",\n\t\t\t\t\thint: \"Modify the message before retrying\",\n\t\t\t\t},\n\t\t\t\t{ label: \"Cancel\", value: \"cancel\" },\n\t\t\t],\n\t\t})\n\n\t\tif (p.isCancel(choice)) {\n\t\t\tdebug(\"showRecoveryMenu: user cancelled\")\n\t\t\tp.outro(yellow(\"Cancelled. Message cached for --retry.\"))\n\t\t\treturn \"cancelled\"\n\t\t}\n\n\t\tdebug(\"showRecoveryMenu: user chose %s\", choice)\n\n\t\tswitch (choice) {\n\t\t\tcase \"clipboard\": {\n\t\t\t\tconst ok = await copyToClipboard(rawStderr)\n\t\t\t\tif (ok) {\n\t\t\t\t\tclipboardCopied = true\n\t\t\t\t\tp.log.step(green(\"Copied to clipboard.\"))\n\t\t\t\t} else {\n\t\t\t\t\tp.log.warn(red(\"No clipboard tool found. Install xclip, wl-copy, or xsel.\"))\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tcase \"view\": {\n\t\t\t\tp.note(rawStderr.trim() || \"(no raw output)\", \"Full error output\")\n\t\t\t\tshowNote = true\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tcase \"skip\": {\n\t\t\t\tp.log.info(yellow(\"Committing with --no-verify...\"))\n\t\t\t\tconst ok = await onSkipHooks(message)\n\t\t\t\tif (ok) {\n\t\t\t\t\tp.outro(green(\"Committed (hooks skipped).\"))\n\t\t\t\t\treturn \"committed\"\n\t\t\t\t} else {\n\t\t\t\t\tp.outro(red(\"Commit failed even with --no-verify.\"))\n\t\t\t\t\treturn \"failed\"\n\t\t\t\t}\n\t\t\t}\n\t\t\tcase \"restage\": {\n\t\t\t\tp.log.info(cyan(\"Re-staging and retrying...\"))\n\t\t\t\tconst ok = await onRestage()\n\t\t\t\tif (ok) {\n\t\t\t\t\tp.outro(green(\"Committed successfully.\"))\n\t\t\t\t\treturn \"committed\"\n\t\t\t\t}\n\t\t\t\t// Re-show errors after failed restage for context\n\t\t\t\tshowNote = true\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tcase \"edit\": {\n\t\t\t\tconst edited = await p.text({\n\t\t\t\t\tmessage: \"Edit commit message:\",\n\t\t\t\t\tinitialValue: message,\n\t\t\t\t\tvalidate: (v) => (v?.trim() ? undefined : \"Message cannot be empty\"),\n\t\t\t\t})\n\t\t\t\tif (p.isCancel(edited)) {\n\t\t\t\t\tp.outro(yellow(\"Cancelled. Message cached for --retry.\"))\n\t\t\t\t\treturn \"cancelled\"\n\t\t\t\t}\n\t\t\t\tconst ok = await onRetry()\n\t\t\t\tif (ok) {\n\t\t\t\t\tp.outro(green(\"Committed successfully.\"))\n\t\t\t\t\treturn \"committed\"\n\t\t\t\t} else {\n\t\t\t\t\tp.outro(red(\"Commit failed again.\"))\n\t\t\t\t\treturn \"failed\"\n\t\t\t\t}\n\t\t\t}\n\t\t\tcase \"cancel\": {\n\t\t\t\tp.outro(dim(\"Message cached for --retry.\"))\n\t\t\t\treturn \"cancelled\"\n\t\t\t}\n\t\t}\n\t}\n}\n","import { isCancel } from \"@clack/prompts\"\nimport { bold, red } from \"kolorist\"\nimport { debug } from \"../utils/debug.js\"\n\nexport interface ReviewCommitMessageOptions {\n\t/**\n\t * If provided, adds a \"Regenerate with hint\" option to the menu.\n\t * Called with the user-entered hint; should return a new commit message.\n\t * Thrown errors are caught and surfaced inline so the user can retry.\n\t */\n\tregenerate?: (hint: string) => Promise<string>\n}\n\nasync function handleEdit(message: string): Promise<string | null> {\n\tconst { text } = await import(\"@clack/prompts\")\n\tconst edited = await text({\n\t\tmessage: \"Edit commit message:\",\n\t\tinitialValue: message,\n\t\tvalidate: (v) => (v?.trim() ? undefined : \"Message cannot be empty\"),\n\t})\n\tif (isCancel(edited)) {\n\t\tdebug(\"User cancelled edit, returning to review menu\")\n\t\treturn null\n\t}\n\tconst newMessage = String(edited).trim()\n\tdebug(\"Edited message:\", newMessage)\n\treturn newMessage\n}\n\nasync function handleRegenerate(\n\tregenerate: (hint: string) => Promise<string>,\n): Promise<string | null> {\n\tconst { log, text } = await import(\"@clack/prompts\")\n\tconst hint = await text({\n\t\tmessage: \"Describe what this commit is about to guide regeneration:\",\n\t\tvalidate: (v) => (v?.trim() ? undefined : \"Hint cannot be empty\"),\n\t})\n\tif (isCancel(hint)) {\n\t\tdebug(\"User cancelled hint entry, returning to review menu\")\n\t\treturn null\n\t}\n\tconst hintValue = String(hint).trim()\n\tdebug(\"Regenerating with hint:\", hintValue)\n\ttry {\n\t\tconst newMessage = await regenerate(hintValue)\n\t\tdebug(\"Regenerated message:\", newMessage)\n\t\treturn newMessage\n\t} catch (err) {\n\t\tconst errMsg = err instanceof Error ? err.message : String(err)\n\t\tdebug(\"Regeneration failed:\", errMsg)\n\t\tlog.warn(red(`Regeneration failed: ${errMsg}`))\n\t\treturn null\n\t}\n}\n\nexport async function reviewCommitMessage(\n\tmessage: string,\n\toptions?: ReviewCommitMessageOptions,\n): Promise<string | null> {\n\tconst { select } = await import(\"@clack/prompts\")\n\twhile (true) {\n\t\tconst reviewOptions: { label: string; value: string }[] = [\n\t\t\t{ label: \"Use as-is\", value: \"use\" },\n\t\t\t{ label: \"Edit\", value: \"edit\" },\n\t\t]\n\t\tif (options?.regenerate) {\n\t\t\treviewOptions.push({ label: \"Regenerate with hint\", value: \"regenerate\" })\n\t\t}\n\t\treviewOptions.push({ label: \"Cancel\", value: \"cancel\" })\n\n\t\tconst review = await select({\n\t\t\tmessage: `Review commit message:\\n\\n ${bold(message)}\\n`,\n\t\t\toptions: reviewOptions,\n\t\t})\n\n\t\tif (isCancel(review) || review === \"cancel\") {\n\t\t\tdebug(\"User cancelled at review step\")\n\t\t\treturn null\n\t\t}\n\n\t\tif (review === \"use\") {\n\t\t\tdebug(\"User accepted message\")\n\t\t\treturn message\n\t\t}\n\n\t\tif (review === \"edit\") {\n\t\t\tmessage = (await handleEdit(message)) ?? message\n\t\t}\n\n\t\tif (review === \"regenerate\" && options?.regenerate) {\n\t\t\tmessage = (await handleRegenerate(options.regenerate)) ?? message\n\t\t}\n\t}\n}\n","import * as p from \"@clack/prompts\"\nimport { dim, green, red } from \"kolorist\"\nimport { copyToClipboard } from \"../services/clipboard.js\"\nimport type { HookError } from \"../services/hooks.js\"\nimport { debug } from \"../utils/debug.js\"\n\nconst MAX_TSC_DIAGNOSTICS = 3\nconst MAX_ESLINT_DIAGNOSTICS = 3\nconst MAX_TEST_FAILURES = 3\nconst MAX_SUMMARY_LINE_LENGTH = 120\nconst TSC_DIAGNOSTIC =\n\t/^(.+?\\.(?:ts|tsx|mts|cts|js|jsx|mjs|cjs))\\((\\d+),(\\d+)\\):\\s+error\\s+(TS\\d+):\\s+(.+)$/\n// ESLint stylish format: <whitespace><line>:<col> <severity> <message> <rule>\nconst ESLINT_ERROR_LINE = /^\\s*(\\d+):(\\d+)\\s+(error|warning)\\s+(.+)\\s{2,}(\\S+)\\s*$/\n// vitest/jest \"Failed Tests\" block: optional indent, FAIL, file path, \">\", test path\nconst TEST_FILE_FAIL = /^\\s*FAIL\\s+(.+?\\.(?:test|spec)\\.[^\\s>]+)\\s*>\\s*(.+)$/\n\ninterface TscDiagnostic {\n\tfile: string\n\tline: string\n\tcolumn: string\n\tcode: string\n\tmessage: string\n}\n\ninterface EslintDiagnostic {\n\tfile: string\n\tline: string\n\tcolumn: string\n\tseverity: string\n\tmessage: string\n\trule: string\n}\n\ninterface TestFailure {\n\tfile: string\n\tname: string\n}\n\nfunction formatCheckFailureSummary(errors: HookError[]): string {\n\tif (errors.length === 0) {\n\t\treturn \"No check error details were parsed. View full output for details.\"\n\t}\n\n\treturn errors.map((error) => formatCheckErrorSummary(error)).join(\"\\n\")\n}\n\nfunction formatCheckErrorSummary(error: HookError): string {\n\tif (error.tool === \"tsc\") {\n\t\tconst diagnostics = extractTscDiagnostics(error.raw || error.message)\n\t\tif (diagnostics.length > 0) {\n\t\t\treturn formatTscSummary(diagnostics)\n\t\t}\n\t}\n\n\tif (error.tool === \"eslint\") {\n\t\tconst diagnostics = extractEslintDiagnostics(error.raw || error.message)\n\t\tif (diagnostics.length > 0) {\n\t\t\treturn formatEslintSummary(diagnostics)\n\t\t}\n\t}\n\n\tif (error.tool === \"vitest\" || error.tool === \"jest\") {\n\t\tconst failures = extractTestFailures(error.raw || error.message)\n\t\tif (failures.length > 0) {\n\t\t\treturn formatTestFailureSummary(failures, error.tool)\n\t\t}\n\t}\n\n\tconst message = firstMeaningfulLine(error.message || error.raw)\n\treturn ` ${red(\"•\")} [${error.tool}] ${truncate(message, MAX_SUMMARY_LINE_LENGTH)}`\n}\n\nfunction extractTscDiagnostics(raw: string): TscDiagnostic[] {\n\treturn raw\n\t\t.split(\"\\n\")\n\t\t.map((line) => line.trim())\n\t\t.map((line) => {\n\t\t\tconst match = TSC_DIAGNOSTIC.exec(line)\n\t\t\tif (!match) return null\n\t\t\treturn {\n\t\t\t\tfile: match[1] ?? \"\",\n\t\t\t\tline: match[2] ?? \"\",\n\t\t\t\tcolumn: match[3] ?? \"\",\n\t\t\t\tcode: match[4] ?? \"\",\n\t\t\t\tmessage: match[5] ?? \"\",\n\t\t\t}\n\t\t})\n\t\t.filter((diagnostic): diagnostic is TscDiagnostic => diagnostic !== null)\n}\n\nfunction formatTscSummary(diagnostics: TscDiagnostic[]): string {\n\tconst visible = diagnostics.slice(0, MAX_TSC_DIAGNOSTICS)\n\tconst hidden = diagnostics.length - visible.length\n\tconst lines = [\n\t\t` ${red(\"•\")} [tsc] ${diagnostics.length} TypeScript error${diagnostics.length !== 1 ? \"s\" : \"\"}`,\n\t\t...visible.map(\n\t\t\t(diagnostic) =>\n\t\t\t\t`${diagnostic.file}:${diagnostic.line}:${diagnostic.column} — error ${diagnostic.code}: ${truncate(diagnostic.message, MAX_SUMMARY_LINE_LENGTH)}`,\n\t\t),\n\t]\n\n\tif (hidden > 0) {\n\t\tlines.push(\n\t\t\tdim(\n\t\t\t\t` +${hidden} more TypeScript error${hidden !== 1 ? \"s\" : \"\"}. View full output for details.`,\n\t\t\t),\n\t\t)\n\t}\n\n\treturn lines.join(\"\\n\")\n}\n\nfunction extractEslintDiagnostics(raw: string): EslintDiagnostic[] {\n\tconst diagnostics: EslintDiagnostic[] = []\n\tconst lines = raw.split(\"\\n\")\n\tlet currentFile = \"\"\n\n\tfor (const line of lines) {\n\t\t// File path line: not indented, contains a path separator, not an error detail line\n\t\tif (!/^\\s/.test(line) && line.includes(\"/\") && !ESLINT_ERROR_LINE.test(line)) {\n\t\t\tcurrentFile = line.trim()\n\t\t\tcontinue\n\t\t}\n\n\t\tconst match = ESLINT_ERROR_LINE.exec(line)\n\t\tif (match) {\n\t\t\tdiagnostics.push({\n\t\t\t\tfile: currentFile || \"unknown\",\n\t\t\t\tline: match[1] ?? \"\",\n\t\t\t\tcolumn: match[2] ?? \"\",\n\t\t\t\tseverity: match[3] ?? \"\",\n\t\t\t\tmessage: (match[4] ?? \"\").trim(),\n\t\t\t\trule: match[5] ?? \"\",\n\t\t\t})\n\t\t}\n\t}\n\n\treturn diagnostics\n}\n\nfunction extractTestFailures(raw: string): TestFailure[] {\n\tconst failures: TestFailure[] = []\n\tconst seen = new Set<string>()\n\tfor (const line of raw.split(\"\\n\")) {\n\t\tconst match = TEST_FILE_FAIL.exec(line)\n\t\tif (!match) continue\n\t\tconst file = (match[1] ?? \"\").trim()\n\t\tconst name = (match[2] ?? \"\").trim()\n\t\tif (!file || !name) continue\n\t\tconst key = `${file}\\u0000${name}`\n\t\t// Dedupe — vitest can repeat the same FAIL line across reruns captured in one block\n\t\tif (seen.has(key)) continue\n\t\tseen.add(key)\n\t\tfailures.push({ file, name })\n\t}\n\treturn failures\n}\n\nfunction formatTestFailureSummary(failures: TestFailure[], tool: string): string {\n\tconst total = failures.length\n\tconst visible = failures.slice(0, MAX_TEST_FAILURES)\n\tconst hidden = total - visible.length\n\tconst fileCount = new Set(failures.map((f) => f.file)).size\n\tconst testNoun = total === 1 ? \"test\" : \"tests\"\n\tconst fileNoun = fileCount === 1 ? \"file\" : \"files\"\n\n\tconst lines = [` ${red(\"•\")} [${tool}] ${total} failed ${testNoun} in ${fileCount} ${fileNoun}`]\n\n\t// Group visible failures by file to avoid repeating the file path\n\tconst byFile = new Map<string, string[]>()\n\tfor (const failure of visible) {\n\t\tconst names = byFile.get(failure.file) ?? []\n\t\tnames.push(failure.name)\n\t\tbyFile.set(failure.file, names)\n\t}\n\n\tfor (const [file, names] of byFile) {\n\t\tlines.push(` ${truncate(file, MAX_SUMMARY_LINE_LENGTH)}`)\n\t\tfor (const name of names) {\n\t\t\tlines.push(` ${red(\"×\")} ${truncate(name, MAX_SUMMARY_LINE_LENGTH)}`)\n\t\t}\n\t}\n\n\tif (hidden > 0) {\n\t\tlines.push(\n\t\t\tdim(\n\t\t\t\t` +${hidden} more failed ${hidden === 1 ? \"test\" : \"tests\"}. View full output for details.`,\n\t\t\t),\n\t\t)\n\t}\n\n\treturn lines.join(\"\\n\")\n}\n\nfunction formatEslintSummary(diagnostics: EslintDiagnostic[]): string {\n\tconst visible = diagnostics.slice(0, MAX_ESLINT_DIAGNOSTICS)\n\tconst hidden = diagnostics.length - visible.length\n\tconst count = diagnostics.length\n\tconst noun = count === 1 ? \"problem\" : \"problems\"\n\tconst lines = [\n\t\t` ${red(\"•\")} [eslint] ${count} ESLint ${noun}`,\n\t\t...visible.map(\n\t\t\t(diagnostic) =>\n\t\t\t\t`${diagnostic.file}:${diagnostic.line}:${diagnostic.column} ${diagnostic.severity} ${diagnostic.rule} — ${truncate(diagnostic.message, MAX_SUMMARY_LINE_LENGTH)}`,\n\t\t),\n\t]\n\n\tif (hidden > 0) {\n\t\tlines.push(\n\t\t\tdim(\n\t\t\t\t` +${hidden} more ESLint ${hidden === 1 ? \"problem\" : \"problems\"}. View full output for details.`,\n\t\t\t),\n\t\t)\n\t}\n\n\treturn lines.join(\"\\n\")\n}\n\nfunction firstMeaningfulLine(message: string): string {\n\tconst line = message\n\t\t.split(\"\\n\")\n\t\t.map((l) => l.trim())\n\t\t.find((l) => l.length > 0 && !l.startsWith(\">\") && !l.startsWith(\"ELIFECYCLE\"))\n\treturn line ?? message\n}\n\nfunction truncate(message: string, maxLength: number): string {\n\tconst collapsed = message.replace(/\\s+/g, \" \").trim()\n\tif (collapsed.length <= maxLength) return collapsed\n\treturn `${collapsed.slice(0, Math.max(0, maxLength - 1))}…`\n}\n\n// biome-ignore lint/complexity/noExcessiveLinesPerFunction: Check failure menu with retry option\nexport async function showCheckFailureMenu(\n\terrors: HookError[],\n\trawStderr: string,\n\tonRetry?: () => Promise<boolean>,\n): Promise<\"skipped\" | \"cancelled\" | \"retried\"> {\n\tdebug(\"showCheckFailureMenu: %d errors\", errors.length)\n\n\tlet clipboardCopied = false\n\n\tp.note(formatCheckFailureSummary(errors), red(\"Pre-commit check failed\"))\n\n\twhile (true) {\n\t\tconst choice = await p.select({\n\t\t\tmessage: \"What do you want to do?\",\n\t\t\toptions: [\n\t\t\t\t{\n\t\t\t\t\tlabel: clipboardCopied\n\t\t\t\t\t\t? `${green(\"✓\")} Copy error report to clipboard`\n\t\t\t\t\t\t: \"Copy error report to clipboard\",\n\t\t\t\t\tvalue: \"copy\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: \"View full error output\",\n\t\t\t\t\tvalue: \"view\",\n\t\t\t\t\thint: \"Show the raw stderr from checks\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: \"Retry checks\",\n\t\t\t\t\tvalue: \"retry\",\n\t\t\t\t\thint: \"Re-run checks after fixing errors\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: \"Skip checks and commit\",\n\t\t\t\t\tvalue: \"skip\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: \"Cancel\",\n\t\t\t\t\tvalue: \"cancel\",\n\t\t\t\t},\n\t\t\t],\n\t\t})\n\n\t\tif (p.isCancel(choice)) {\n\t\t\tdebug(\"showCheckFailureMenu: user cancelled\")\n\t\t\treturn \"cancelled\"\n\t\t}\n\n\t\tdebug(\"showCheckFailureMenu: user chose %s\", choice)\n\n\t\tswitch (choice) {\n\t\t\tcase \"copy\": {\n\t\t\t\tconst ok = await copyToClipboard(rawStderr)\n\t\t\t\tif (ok) {\n\t\t\t\t\tclipboardCopied = true\n\t\t\t\t\tp.log.step(green(\"Copied to clipboard.\"))\n\t\t\t\t} else {\n\t\t\t\t\tp.log.warn(red(\"No clipboard tool found. Install xclip, wl-copy, or xsel.\"))\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tcase \"view\": {\n\t\t\t\tp.note(rawStderr.trim() || \"(no raw output)\", \"Full error output\")\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tcase \"retry\": {\n\t\t\t\tif (onRetry) {\n\t\t\t\t\treturn \"retried\"\n\t\t\t\t}\n\t\t\t\t// No retry callback — return retried so caller can handle the loop\n\t\t\t\treturn \"retried\"\n\t\t\t}\n\t\t\tcase \"skip\": {\n\t\t\t\tp.log.info(\"Skipping checks and proceeding with commit...\")\n\t\t\t\treturn \"skipped\"\n\t\t\t}\n\t\t\tcase \"cancel\": {\n\t\t\t\tp.outro(dim(\"Cancelled.\"))\n\t\t\t\treturn \"cancelled\"\n\t\t\t}\n\t\t}\n\t}\n}\n","import { log } from \"@clack/prompts\"\nimport { green } from \"kolorist\"\nimport type { CheckResults } from \"../services/checks.js\"\n\n/** Minimal spinner contract — only the `stop` method is needed. */\ntype SpinnerStop = { stop: (message: string) => void }\n\n/**\n * Stop a check spinner with a per-tool summary of the check results.\n *\n * - On success: stops with \"All checks passed\" and prints a `✓ tool` line\n * for each result.\n * - On failure: stops with \"N checks failed\" (pluralized). Raw error output\n * is intentionally NOT printed here — callers handle failure display\n * (menu, raw print, etc.).\n */\nexport function stopCheckSpinner(spinner: SpinnerStop, results: CheckResults): void {\n\tif (results.ok) {\n\t\tspinner.stop(\"All checks passed\")\n\t\tif (results.results.length > 0) {\n\t\t\tlog.info(results.results.map((r) => ` ${green(\"✓\")} ${r.tool}`).join(\"\\n\"))\n\t\t}\n\t} else {\n\t\tconst failed = results.results.filter((r) => !r.ok)\n\t\tspinner.stop(`${failed.length} check${failed.length !== 1 ? \"s\" : \"\"} failed`)\n\t}\n}\n","import { spinner } from \"@clack/prompts\"\nimport { detectConfig, runAllChecks } from \"../services/checks.js\"\nimport { parseCheckErrors } from \"../services/hooks.js\"\nimport { showCheckFailureMenu } from \"../ui/check-failure-menu.js\"\nimport { stopCheckSpinner } from \"../ui/check-summary.js\"\nimport { debug } from \"../utils/debug.js\"\n\n/**\n * Outcome of an interactive check phase.\n *\n * - `\"passed\"` — checks ran and passed (or no `.cmintrc` exists, which is treated as a pass)\n * - `\"skipped\"` — checks failed but the user chose to skip and proceed anyway\n * - `\"cancelled\"` — the user chose cancel from the failure menu (caller should abort)\n */\nexport type CheckPhaseOutcome = \"passed\" | \"skipped\" | \"cancelled\"\n\n/**\n * Optional callback invoked before each retry after the user picks \"Retry checks\"\n * from the failure menu. Use this to refresh staged state (e.g. `stageAll()` to\n * pick up fixes made in another terminal between the original run and the retry).\n *\n * Not invoked on the initial check run — only on retries triggered by the menu.\n */\nexport type CheckRetryCallback = () => Promise<void>\n\n/**\n * Run user-defined pre-commit checks with an interactive failure menu.\n *\n * Single entry point for the check-execution pipeline shared by `runPreCommitChecks`\n * (post-staging, normal commit flow) and `runAutoGroupFlow` (pre-staging, auto-group\n * flow). Encapsulates: detectConfig guard → spinner → runAllChecks → retry loop with\n * `showCheckFailureMenu`.\n *\n * Caller responsibilities:\n * - Skip when `noCheck` is set (caller's policy).\n * - Skip when there are no files to check (caller has the file list context).\n * - Derive `files` in **repo-root-relative** form so they match `.cmintrc` globs.\n * Post-staging callers should use `getStagedFiles()`; pre-staging callers should\n * use `resolveToRepoRoot()` since the index doesn't yet contain those paths.\n *\n * Returns the outcome so the caller can decide how to handle cancellation\n * (`process.exit(1)` in the commit flow, `return \"cancelled\"` in auto-group).\n */\nexport async function runCheckPhaseInteractive(\n\trepoRoot: string,\n\tfiles: string[],\n\ttimeout: number,\n\tonRetry?: CheckRetryCallback,\n): Promise<CheckPhaseOutcome> {\n\t// No-op when no `.cmintrc` config exists. Checking here (rather than relying\n\t// on runAllChecks's internal no-op) lets us skip the spinner entirely, which\n\t// is the reason auto-group had its own `detectConfig` guard before extraction.\n\tconst configPath = await detectConfig(repoRoot)\n\tif (!configPath) return \"passed\"\n\n\tdebug(\"Running user checks on %d files...\", files.length)\n\tconst ck = spinner()\n\tck.start(\"Running checks...\")\n\tlet checkResults = await runAllChecks(repoRoot, files, timeout)\n\tstopCheckSpinner(ck, checkResults)\n\tdebug(\"Check results: ok=%s, count=%d\", checkResults.ok, checkResults.results.length)\n\n\twhile (!checkResults.ok) {\n\t\tconst failed = checkResults.results.filter((r) => !r.ok)\n\t\tconst rawOutput = failed.map((r) => `[${r.tool}]\\n${r.stdout}\\n${r.stderr}`.trim()).join(\"\\n\\n\")\n\t\tconst checkErrors = parseCheckErrors(rawOutput)\n\t\tconst menuResult = await showCheckFailureMenu(checkErrors, rawOutput, async () => {\n\t\t\tconst retryResult = await runAllChecks(repoRoot, files, timeout)\n\t\t\treturn retryResult.ok\n\t\t})\n\t\tif (menuResult === \"cancelled\") {\n\t\t\treturn \"cancelled\"\n\t\t}\n\t\tif (menuResult === \"retried\") {\n\t\t\tdebug(\"Re-running checks after retry...\")\n\t\t\tif (onRetry) await onRetry()\n\t\t\tck.start(\"Running checks...\")\n\t\t\tcheckResults = await runAllChecks(repoRoot, files, timeout)\n\t\t\tstopCheckSpinner(ck, checkResults)\n\t\t\tdebug(\"Retry check results: ok=%s, count=%d\", checkResults.ok, checkResults.results.length)\n\t\t\tcontinue\n\t\t}\n\t\t// \"skipped\" — break out of the loop; caller proceeds despite the failure\n\t\tbreak\n\t}\n\n\treturn checkResults.ok ? \"passed\" : \"skipped\"\n}\n","import { isCancel, log, outro, spinner } from \"@clack/prompts\"\nimport { dim, green, red } from \"kolorist\"\nimport { generateCommitMessage } from \"../services/ai.js\"\nimport { getAutoAccept } from \"../services/auto-accept.js\"\nimport {\n\tgetModelForProvider,\n\tgetProviderApiKey,\n\treadConfig,\n\tsetConfigValue,\n} from \"../services/config.js\"\nimport {\n\tattemptCommit,\n\tattemptCommitNoVerify,\n\ttype ChangedFile,\n\tgetDefaultExcludes,\n\tgetHead,\n\tgetStagedDiff,\n\tresetStaging,\n\tresolveToRepoRoot,\n\tstageFiles,\n} from \"../services/git.js\"\nimport { filterExcludedFiles, generateGroups, validateGroups } from \"../services/grouping.js\"\nimport { createProgressHandler } from \"../services/hook-progress.js\"\nimport { parseHookErrors, parseToolChecks } from \"../services/hooks.js\"\nimport {\n\tformatProviderName,\n\tisValidProvider,\n\tPROVIDER_CONFIGS,\n\tPROVIDER_ENV_KEYS,\n\ttype ProviderName,\n} from \"../services/provider.js\"\nimport { showGroupedFiles, showGroupingConfirmation, showGroupProgress } from \"../ui/grouping.js\"\nimport { type RecoveryResult, showRecoveryMenu } from \"../ui/recovery-menu.js\"\nimport { reviewCommitMessage } from \"../ui/review-message.js\"\nimport { saveCachedCommit } from \"../utils/cache.js\"\nimport { debug } from \"../utils/debug.js\"\nimport { runCheckPhaseInteractive } from \"./check-phase.js\"\n\nexport interface CommitFlags {\n\tretry: boolean\n\tauto: boolean\n\tagent: boolean\n\tmessage?: string\n\thint?: string\n\tnoCheck?: boolean\n}\n\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Multi-step auto-group flow with sequential commits, review, and recovery\n// biome-ignore lint/complexity/noExcessiveLinesPerFunction: Sequential multi-commit loop with review, cache, and recovery\nexport async function runAutoGroupFlow(\n\tchangedFiles: ChangedFile[],\n\tflags: CommitFlags,\n): Promise<RecoveryResult> {\n\t// Step 1: Filter excluded files\n\tconst { included, excluded } = filterExcludedFiles(changedFiles)\n\n\t// Step 1b: Commit excluded files with hardcoded message before grouping\n\tif (excluded.length > 0) {\n\t\tdebug(\"Committing %d excluded files upfront:\", excluded.length, excluded)\n\t\tconst message = buildExcludedFilesMessage(excluded)\n\n\t\tlog.info(excluded.map((f) => ` ${f}`).join(\"\\n\"))\n\n\t\tawait resetStaging()\n\t\tawait stageFiles(excluded)\n\n\t\tconst headBefore = await getHead()\n\t\tconst commitResult = await attemptCommit(message)\n\t\tconst headAfter = await getHead()\n\n\t\tif (commitResult.ok || headBefore !== headAfter) {\n\t\t\tdebug(\"Excluded files committed:\", message)\n\t\t\tlog.success(dim(message))\n\t\t} else {\n\t\t\tdebug(\"Excluded files commit failed, continuing without them\")\n\t\t\tlog.warn(red(\"Failed to commit excluded files.\"))\n\t\t}\n\t}\n\n\t// If only excluded files existed, we're done\n\tif (included.length === 0) {\n\t\tdebug(\"No included files to group, done\")\n\t\tif (excluded.length > 0) {\n\t\t\toutro(green(\"Committed excluded files. No other changes to group.\"))\n\t\t} else {\n\t\t\toutro(dim(\"Nothing to commit.\"))\n\t\t}\n\t\treturn \"committed\"\n\t}\n\n\t// Run user-defined pre-commit checks upfront on all files (before AI grouping)\n\tif (!flags.noCheck) {\n\t\tconst { getRepoRoot } = await import(\"../services/git.js\")\n\t\tconst repoRoot = await getRepoRoot()\n\t\t// Convert cwd-relative paths from `filterExcludedFiles` to repo-root-relative\n\t\t// so they line up with .cmintrc globs (which are written from the repo root,\n\t\t// matching lint-staged conventions). Checks run BEFORE per-group staging,\n\t\t// so we can't use `getStagedFiles()` here — the index doesn't yet contain\n\t\t// these files.\n\t\tconst cwdRelativeIncluded = included.filter((f) => f.status !== \"D\").map((f) => f.path)\n\t\tconst allFiles = await resolveToRepoRoot(cwdRelativeIncluded)\n\t\t// No onRetry callback: files aren't staged yet, so `stageAll()` would be\n\t\t// inappropriate here. The check commands read from the working tree, so\n\t\t// external fixes are picked up directly on the next `runAllChecks` call.\n\t\tconst outcome = await runCheckPhaseInteractive(repoRoot, allFiles, 60000)\n\t\tif (outcome === \"cancelled\") {\n\t\t\treturn \"cancelled\"\n\t\t}\n\t}\n\n\t// Step 2: Read config and determine provider\n\tconst config = await readConfig()\n\tconst resolvedProvider = config.provider ?? \"groq\"\n\tconst provider: ProviderName = isValidProvider(resolvedProvider) ? resolvedProvider : \"groq\"\n\n\t// Step 3: Ensure API key\n\ttry {\n\t\tawait getProviderApiKey(provider)\n\t\tdebug(\"API key found\")\n\t} catch {\n\t\tdebug(\"No API key found, prompting user\")\n\t\tconst { text: promptText } = await import(\"@clack/prompts\")\n\t\tconst key = await promptText({\n\t\t\tmessage: `Enter your ${formatProviderName(provider)} API key:`,\n\t\t\tplaceholder: provider === \"groq\" ? \"gsk_...\" : \"...\",\n\t\t\tvalidate: (v) => (v?.trim() ? undefined : \"API key is required\"),\n\t\t})\n\t\tif (isCancel(key)) {\n\t\t\toutro(dim(\"Cancelled.\"))\n\t\t\treturn \"cancelled\"\n\t\t}\n\t\tconst configKey = PROVIDER_ENV_KEYS[provider]\n\t\tawait setConfigValue(configKey, String(key).trim())\n\t\tdebug(\"API key saved to config\")\n\t}\n\n\t// Step 4: Call grouping service\n\tconst s = spinner()\n\ts.start(\"Analyzing files...\")\n\tconst apiKey = await getProviderApiKey(provider)\n\tconst result = await generateGroups(\n\t\tincluded,\n\t\tapiKey,\n\t\tgetModelForProvider(config, provider, PROVIDER_CONFIGS[provider].defaultModel),\n\t\tconfig.timeout ? parseInt(config.timeout, 10) : undefined,\n\t\tprovider,\n\t\tconfig.proxy,\n\t)\n\tconst validatedGroups = validateGroups(result.groups, included)\n\ts.stop(\"Files analyzed\")\n\n\tshowGroupedFiles(validatedGroups, included)\n\n\t// Auto-accept mode: skip both grouping confirmation and per-group review.\n\t// Read once here so a single toggle in the staging menu is honored for the\n\t// entire flow. `flags.auto` already skips both; auto-accept extends that\n\t// to interactive (non-`--auto`) runs.\n\tconst autoAccept = await getAutoAccept()\n\tconst skipPrompts = flags.auto || autoAccept\n\n\t// Step 5: Show grouping confirmation (skip in auto mode or auto-accept)\n\tif (skipPrompts) {\n\t\tdebug(\"Skipping grouping confirmation (auto=%s autoAccept=%s)\", flags.auto, autoAccept)\n\t} else {\n\t\tconst confirmed = await showGroupingConfirmation(validatedGroups, excluded)\n\t\tif (!confirmed) {\n\t\t\toutro(dim(\"Cancelled.\"))\n\t\t\treturn \"cancelled\"\n\t\t}\n\t}\n\n\t// Step 6: Sequential multi-commit loop\n\tfor (let i = 0; i < validatedGroups.length; i++) {\n\t\tconst group = validatedGroups[i]\n\t\tshowGroupProgress(i + 1, validatedGroups.length, group.name)\n\n\t\t// Unstage everything first, then stage only this group's files\n\t\tawait resetStaging()\n\t\tawait stageFiles(group.files)\n\n\t\t// Get diff for this group\n\t\tconst diffResult = await getStagedDiff()\n\t\tif (!diffResult || \"excludedFiles\" in diffResult) {\n\t\t\tlog.warn(red(`No changes found for group \"${group.name}\" — skipping.`))\n\t\t\tcontinue\n\t\t}\n\n\t\t// Generate message\n\t\ts.start(\"Generating commit message...\")\n\t\tlet message: string\n\t\ttry {\n\t\t\tmessage = await generateMessage(diffResult.diff, flags.hint)\n\t\t} catch (err) {\n\t\t\ts.stop(red(\"Failed to generate message.\"))\n\t\t\toutro(red(err instanceof Error ? err.message : String(err)))\n\t\t\treturn \"cancelled\"\n\t\t}\n\t\ts.stop(\"Message generated\")\n\t\tlog.info(dim(message))\n\n\t\t// Review message (skip in auto mode or auto-accept)\n\t\tif (skipPrompts) {\n\t\t\tdebug(\"Accepting generated message (auto=%s autoAccept=%s)\", flags.auto, autoAccept)\n\t\t} else {\n\t\t\tconst reviewed = await reviewCommitMessage(message, {\n\t\t\t\tregenerate: async (hint) => {\n\t\t\t\t\tconst combinedHint = flags.hint ? `${flags.hint}\\n${hint}` : hint\n\t\t\t\t\tdebug(\"Regenerating with combined hint:\", combinedHint)\n\t\t\t\t\ts.start(\"Regenerating commit message...\")\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst newMessage = await generateMessage(diffResult.diff, combinedHint)\n\t\t\t\t\t\ts.stop(\"Message regenerated\")\n\t\t\t\t\t\treturn newMessage\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\ts.stop(red(\"Regeneration failed\"))\n\t\t\t\t\t\tthrow err\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t})\n\t\t\tif (reviewed === null) {\n\t\t\t\toutro(dim(\"Cancelled.\"))\n\t\t\t\treturn \"cancelled\"\n\t\t\t}\n\t\t\tmessage = reviewed\n\t\t}\n\n\t\t// Cache message\n\t\tconst { getRepoRoot } = await import(\"../services/git.js\")\n\t\tconst repoRoot = await getRepoRoot()\n\t\tawait saveCachedCommit(repoRoot, message)\n\n\t\t// Attempt commit\n\t\ts.start(\"Running pre-commit hooks...\")\n\t\tconst headBefore = await getHead()\n\t\tconst commitResult = await attemptCommit(message, [], createProgressHandler(s))\n\t\tconst headAfter = await getHead()\n\n\t\tif (commitResult.ok || headBefore !== headAfter) {\n\t\t\ts.stop(\"Committed successfully.\")\n\t\t\tconst checks = parseToolChecks(commitResult.stderr ?? \"\")\n\t\t\tif (checks.length > 0) {\n\t\t\t\tconst lines = checks.map((c) => ` ${c.ok ? green(\"✓\") : red(\"✗\")} ${c.tool}`)\n\t\t\t\tlog.info(lines.join(\"\\n\"))\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\t// Hook failure — stop sequence, show recovery menu\n\t\ts.stop(\"Commit failed.\")\n\t\tconst errors = parseHookErrors(commitResult.stderr ?? \"\")\n\t\tconst recoveryResult = await showRecoveryMenu(\n\t\t\terrors,\n\t\t\tasync () => (await attemptCommit(message)).ok,\n\t\t\tasync (msg) => (await attemptCommitNoVerify(msg)).ok,\n\t\t\tasync () => {\n\t\t\t\tawait stageFiles(group.files)\n\t\t\t\treturn (await attemptCommit(message)).ok\n\t\t\t},\n\t\t\tmessage,\n\t\t\tcommitResult.stderr ?? \"\",\n\t\t)\n\t\tif (recoveryResult === \"committed\") {\n\t\t\tif (i < validatedGroups.length - 1) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn \"committed\"\n\t\t}\n\t\treturn recoveryResult\n\t}\n\n\toutro(green(\"All groups committed.\"))\n\treturn \"committed\"\n}\n\nexport async function generateMessage(diff: string, hint?: string): Promise<string> {\n\tconst config = await readConfig()\n\tconst resolvedProvider = config.provider ?? \"groq\"\n\tconst provider: ProviderName = isValidProvider(resolvedProvider) ? resolvedProvider : \"groq\"\n\tconst apiKey = await getProviderApiKey(provider)\n\tconst model = getModelForProvider(config, provider, PROVIDER_CONFIGS[provider].defaultModel)\n\tdebug(\"Generating message with provider:\", provider, \"model:\", model, \"type:\", config.type)\n\n\treturn generateCommitMessage(diff, {\n\t\tapiKey,\n\t\tmodel,\n\t\ttype: config.type,\n\t\ttimeout: config.timeout ? parseInt(config.timeout, 10) : undefined,\n\t\thint,\n\t\tprovider,\n\t\tproxy: config.proxy,\n\t})\n}\n\nexport function buildExcludedFilesMessage(files: string[]): string {\n\tconst excludes = getDefaultExcludes()\n\tconst isLockfile = (f: string) =>\n\t\texcludes.some((pattern) => {\n\t\t\tif (pattern.endsWith(\".lock\") || pattern.endsWith(\".json\")) {\n\t\t\t\treturn f === pattern || f.endsWith(pattern.replace(\"*.\", \".\"))\n\t\t\t}\n\t\t\treturn false\n\t\t})\n\n\tif (files.every(isLockfile)) {\n\t\treturn \"chore: update lockfile\"\n\t}\n\n\treturn \"chore: update generated files\"\n}\n","import { generateCommitMessage } from \"../services/ai.js\"\nimport { detectConfig, runAllChecks } from \"../services/checks.js\"\nimport { getModelForProvider, getProviderApiKey, readConfig } from \"../services/config.js\"\nimport {\n\tassertGitRepo,\n\tattemptCommit,\n\tgetChangedFiles,\n\tgetHead,\n\tgetRepoRoot,\n\tgetStagedDiff,\n\tgetStatusShort,\n\tresetStaging,\n\tresolveToRepoRoot,\n\tstageFiles,\n} from \"../services/git.js\"\nimport {\n\ttype CommitGroup,\n\tfilterExcludedFiles,\n\tgenerateGroups,\n\tvalidateGroups,\n} from \"../services/grouping.js\"\nimport { parseCheckErrors, parseHookErrors } from \"../services/hooks.js\"\nimport {\n\tisValidProvider,\n\tPROVIDER_CONFIGS,\n\tPROVIDER_ENV_KEYS,\n\ttype ProviderName,\n} from \"../services/provider.js\"\nimport { type AgentCommit, EXIT_CODES, writeAgentResult } from \"../utils/agent.js\"\nimport { saveCachedCommit } from \"../utils/cache.js\"\nimport { debug } from \"../utils/debug.js\"\nimport { buildExcludedFilesMessage, type CommitFlags } from \"./auto-group.js\"\n\n/**\n * Headless agent command — orchestrates the entire commit flow without any TUI\n * interaction. Emits structured JSON results to stdout, one per line. Returns\n * control to the caller with `process.exitCode` set to one of the 7 documented\n * exit codes (0=success, 1=generic, 2=no_changes, 3=git, 4=ai, 5=check, 6=hook).\n */\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Multi-phase state machine (validate→stage→diff→exclude→message→check→group→commit)\n// biome-ignore lint/complexity/noExcessiveLinesPerFunction: Sequential orchestration with no helper extraction (per task spec)\nexport async function agentCommand(flags: CommitFlags): Promise<void> {\n\tdebug(\"agentCommand called\", { flags })\n\n\t// 1. Validate flags\n\tif (flags.retry) {\n\t\tprocess.exitCode = EXIT_CODES.GENERIC\n\t\twriteAgentResult({\n\t\t\tstatus: \"failure\",\n\t\t\tcommits: [],\n\t\t\terrors: [\"--agent is not compatible with --retry\"],\n\t\t})\n\t\treturn\n\t}\n\n\t// 2. Assert git repo\n\ttry {\n\t\tawait assertGitRepo()\n\t} catch (err) {\n\t\tprocess.exitCode = EXIT_CODES.GIT\n\t\twriteAgentResult({\n\t\t\tstatus: \"failure\",\n\t\t\tcommits: [],\n\t\t\terrors: [err instanceof Error ? err.message : String(err)],\n\t\t})\n\t\treturn\n\t}\n\n\t// 3. Check status\n\tconst status = await getStatusShort()\n\tdebug(\"Git status:\", status || \"(empty)\")\n\tif (!status) {\n\t\tprocess.exitCode = EXIT_CODES.NO_CHANGES\n\t\twriteAgentResult({ status: \"no_changes\", commits: [] })\n\t\treturn\n\t}\n\n\t// 4. Auto-stage all changed files\n\tconst changedFiles = await getChangedFiles()\n\tdebug(\"Changed files:\", changedFiles.length)\n\tawait stageFiles(changedFiles.map((f) => f.path))\n\n\t// 5. Get diff (3-way union: StagedDiffResult | ExcludedFilesResult | null)\n\tconst diffResult = await getStagedDiff()\n\tif (!diffResult) {\n\t\tprocess.exitCode = EXIT_CODES.NO_CHANGES\n\t\twriteAgentResult({ status: \"no_changes\", commits: [] })\n\t\treturn\n\t}\n\n\t// Handle ExcludedFilesResult (all staged files are excluded) — hardcoded message\n\tif (\"excludedFiles\" in diffResult) {\n\t\tdebug(\"All staged files are excluded:\", diffResult.excludedFiles)\n\t\tconst message = buildExcludedFilesMessage(diffResult.excludedFiles)\n\n\t\tconst headBefore = await getHead()\n\t\tconst result = await attemptCommit(message)\n\t\tconst headAfter = await getHead()\n\n\t\tif (result.ok || headBefore !== headAfter) {\n\t\t\tprocess.exitCode = EXIT_CODES.SUCCESS\n\t\t\twriteAgentResult({\n\t\t\t\tstatus: \"success\",\n\t\t\t\tcommits: [{ message, hash: headAfter ?? \"\", files: diffResult.excludedFiles }],\n\t\t\t})\n\t\t} else {\n\t\t\tprocess.exitCode = EXIT_CODES.HOOK\n\t\t\tconst errors = parseHookErrors(result.stderr ?? \"\")\n\t\t\twriteAgentResult({\n\t\t\t\tstatus: \"failure\",\n\t\t\t\tcommits: [],\n\t\t\t\terrors: errors.map((e) => `[${e.tool}] ${e.message}`),\n\t\t\t})\n\t\t}\n\t\treturn\n\t}\n\n\t// 6. Handle --message (single-commit mode: skip AI + auto-group)\n\tif (flags.message) {\n\t\tdebug(\"Using provided message:\", flags.message)\n\t\tconst headBefore = await getHead()\n\t\tconst result = await attemptCommit(flags.message)\n\t\tconst headAfter = await getHead()\n\n\t\tif (result.ok || headBefore !== headAfter) {\n\t\t\tprocess.exitCode = EXIT_CODES.SUCCESS\n\t\t\twriteAgentResult({\n\t\t\t\tstatus: \"success\",\n\t\t\t\tcommits: [{ message: flags.message, hash: headAfter ?? \"\", files: diffResult.files }],\n\t\t\t})\n\t\t} else {\n\t\t\tprocess.exitCode = EXIT_CODES.HOOK\n\t\t\tconst errors = parseHookErrors(result.stderr ?? \"\")\n\t\t\twriteAgentResult({\n\t\t\t\tstatus: \"failure\",\n\t\t\t\tcommits: [],\n\t\t\t\terrors: errors.map((e) => `[${e.tool}] ${e.message}`),\n\t\t\t})\n\t\t}\n\t\treturn\n\t}\n\n\t// 7. Run user-defined pre-commit checks (unless --noCheck)\n\tif (!flags.noCheck) {\n\t\tconst repoRoot = await getRepoRoot()\n\t\tconst configPath = await detectConfig(repoRoot)\n\t\tif (configPath) {\n\t\t\tdebug(\"Running user checks on changed files...\")\n\t\t\t// Convert cwd-relative paths from getChangedFiles to repo-root-relative\n\t\t\t// so they match .cmintrc globs (lint-staged convention). Checks run\n\t\t\t// BEFORE per-group staging, so we can't use getStagedFiles() here.\n\t\t\tconst cwdRelativeIncluded = changedFiles.filter((f) => f.status !== \"D\").map((f) => f.path)\n\t\t\tconst allFiles = await resolveToRepoRoot(cwdRelativeIncluded)\n\t\t\tconst checkResults = await runAllChecks(repoRoot, allFiles, 60000)\n\t\t\tif (!checkResults.ok) {\n\t\t\t\tconst failed = checkResults.results.filter((r) => !r.ok)\n\t\t\t\tconst errorMessages = failed\n\t\t\t\t\t.map((r) => `[${r.tool}]\\n${r.stdout}\\n${r.stderr}`.trim())\n\t\t\t\t\t.filter(Boolean)\n\t\t\t\tconst parsed = parseCheckErrors(errorMessages.join(\"\\n\\n\"))\n\t\t\t\tconst errors =\n\t\t\t\t\tparsed.length > 0 ? parsed.map((e) => `[${e.tool}] ${e.message}`) : errorMessages\n\t\t\t\tprocess.exitCode = EXIT_CODES.CHECK\n\t\t\t\twriteAgentResult({ status: \"failure\", commits: [], errors })\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n\n\t// 8. Auto-group flow\n\t// Step 8a: Filter and commit excluded files\n\tconst { included, excluded } = filterExcludedFiles(changedFiles)\n\tdebug(\"Auto-group: %d included, %d excluded\", included.length, excluded.length)\n\n\tif (excluded.length > 0) {\n\t\tconst message = buildExcludedFilesMessage(excluded)\n\t\tdebug(\"Committing %d excluded files:\", excluded.length, excluded)\n\t\tawait resetStaging()\n\t\tawait stageFiles(excluded)\n\n\t\tconst headBefore = await getHead()\n\t\tconst result = await attemptCommit(message)\n\t\tconst headAfter = await getHead()\n\t\tif (!result.ok && headBefore === headAfter) {\n\t\t\tdebug(\"Excluded files commit failed, continuing without them\")\n\t\t}\n\t}\n\n\t// If only excluded files existed, we're done\n\tif (included.length === 0) {\n\t\tprocess.exitCode = EXIT_CODES.SUCCESS\n\t\twriteAgentResult({ status: \"success\", commits: [] })\n\t\treturn\n\t}\n\n\t// Step 8b: Read config and resolve provider\n\tconst config = await readConfig()\n\tconst provider: ProviderName = isValidProvider(config.provider ?? \"groq\")\n\t\t? (config.provider as ProviderName)\n\t\t: \"groq\"\n\n\t// Step 8c: Get API key (fail with AI exit code if missing)\n\tlet apiKey: string\n\ttry {\n\t\tapiKey = await getProviderApiKey(provider)\n\t} catch {\n\t\tprocess.exitCode = EXIT_CODES.AI\n\t\twriteAgentResult({\n\t\t\tstatus: \"failure\",\n\t\t\tcommits: [],\n\t\t\terrors: [\n\t\t\t\t`No API key found for ${provider}. Set ${PROVIDER_ENV_KEYS[provider]} env var or run 'cmint config'`,\n\t\t\t],\n\t\t})\n\t\treturn\n\t}\n\n\tconst model = getModelForProvider(config, provider, PROVIDER_CONFIGS[provider].defaultModel)\n\tconst timeout = config.timeout ? parseInt(config.timeout, 10) : undefined\n\n\t// Step 8d: Generate groups via AI\n\tlet groups: CommitGroup[]\n\ttry {\n\t\tconst result = await generateGroups(included, apiKey, model, timeout, provider, config.proxy)\n\t\tgroups = validateGroups(result.groups, included)\n\t} catch (err) {\n\t\tprocess.exitCode = EXIT_CODES.AI\n\t\twriteAgentResult({\n\t\t\tstatus: \"failure\",\n\t\t\tcommits: [],\n\t\t\terrors: [err instanceof Error ? err.message : String(err)],\n\t\t})\n\t\treturn\n\t}\n\n\t// Step 8e: Sequential per-group commits\n\tconst commits: AgentCommit[] = []\n\tfor (const group of groups) {\n\t\tdebug(\"Processing group %d/%d: %s\", commits.length + 1, groups.length, group.name)\n\n\t\t// Unstage everything first, then stage only this group's files\n\t\tawait resetStaging()\n\t\tawait stageFiles(group.files)\n\n\t\t// Get diff for this group\n\t\tconst groupDiff = await getStagedDiff()\n\t\tif (!groupDiff || \"excludedFiles\" in groupDiff) {\n\t\t\tdebug(`Skipping group \"${group.name}\" — no diff`)\n\t\t\tcontinue\n\t\t}\n\n\t\t// Generate message (auto-accept — no review step in agent mode)\n\t\tlet message: string\n\t\ttry {\n\t\t\tmessage = await generateCommitMessage(groupDiff.diff, {\n\t\t\t\tapiKey,\n\t\t\t\tmodel,\n\t\t\t\ttype: config.type,\n\t\t\t\ttimeout,\n\t\t\t\thint: flags.hint,\n\t\t\t\tprovider,\n\t\t\t\tproxy: config.proxy,\n\t\t\t})\n\t\t} catch (err) {\n\t\t\tprocess.exitCode = EXIT_CODES.AI\n\t\t\twriteAgentResult({\n\t\t\t\tstatus: \"failure\",\n\t\t\t\tcommits,\n\t\t\t\terrors: [err instanceof Error ? err.message : String(err)],\n\t\t\t})\n\t\t\treturn\n\t\t}\n\n\t\t// Cache message\n\t\tconst repoRoot = await getRepoRoot()\n\t\tawait saveCachedCommit(repoRoot, message)\n\n\t\t// Attempt commit (no recovery menu in agent mode)\n\t\tconst headBefore = await getHead()\n\t\tconst result = await attemptCommit(message)\n\t\tconst headAfter = await getHead()\n\n\t\tif (result.ok || headBefore !== headAfter) {\n\t\t\tcommits.push({ message, hash: headAfter ?? \"\", files: group.files, groupName: group.name })\n\t\t\tcontinue\n\t\t}\n\n\t\t// Hook failure — cancel sequence (no skip, no recovery)\n\t\tprocess.exitCode = EXIT_CODES.HOOK\n\t\tconst errors = parseHookErrors(result.stderr ?? \"\")\n\t\twriteAgentResult({\n\t\t\tstatus: \"failure\",\n\t\t\tcommits,\n\t\t\terrors: errors.map((e) => `[${e.tool}] ${e.message}`),\n\t\t})\n\t\treturn\n\t}\n\n\t// 9. Success\n\tprocess.exitCode = EXIT_CODES.SUCCESS\n\twriteAgentResult({ status: \"success\", commits })\n}\n","import { mkdirSync, readFileSync, writeFileSync } from \"node:fs\"\nimport os from \"node:os\"\nimport { dirname, join } from \"node:path\"\nimport { log, spinner } from \"@clack/prompts\"\nimport { cyan, green, yellow } from \"kolorist\"\nimport semver from \"semver\"\nimport { debug } from \"../utils/debug.js\"\n\n// Dist-tags endpoint returns `{\"latest\":\"X.Y.Z\",\"next\":\"...\", ...}` — the only\n// npm registry URL whose body actually contains a `latest` field. The\n// `/<package>/latest` endpoint returns the full package manifest (which has\n// `version`, not `latest`), so it can't be used here without changing the\n// parser. The `/-/package/` prefix works for both scoped and unscoped names.\nconst REGISTRY_URL = \"https://registry.npmjs.org/-/package/@kyubiware/commit-mint/dist-tags\"\nconst _PACKAGE_NAME = \"@kyubiware/commit-mint\"\nconst FRESH_MS = 60 * 60 * 1000\nconst STALE_MS = 24 * 60 * 60 * 1000\nconst FETCH_TIMEOUT_MS = 5000\n\ninterface CacheEntry {\n\tlatest: string\n\tcheckedAt: number\n}\n\nlet cachePath = join(os.homedir(), \".cache\", \"commit-mint\", \"update-check.json\")\nlet fetchImpl: typeof fetch = globalThis.fetch\n\n/** Override cache file path (used by tests to avoid polluting real cache). */\nexport function setCachePath(path: string): void {\n\tcachePath = path\n}\n\n/** Override fetch implementation (used by tests to avoid real network). */\nexport function setFetchImpl(fn: typeof fetch): void {\n\tfetchImpl = fn\n}\n\n/**\n * Returns true when the notifier must not run: env opt-out, CI, test env,\n * non-TTY stderr, or an invalid/missing current version.\n */\nexport function shouldSkip(currentVersion: string): boolean {\n\tconst noUpdate = process.env.NO_UPDATE_NOTIFIER\n\tif (noUpdate !== undefined && noUpdate !== \"\") {\n\t\treturn true\n\t}\n\tconst ci = process.env.CI\n\tif (ci !== undefined && ci !== \"\" && ci !== \"0\") {\n\t\treturn true\n\t}\n\tif (process.env.NODE_ENV === \"test\") {\n\t\treturn true\n\t}\n\tif (process.stderr.isTTY !== true) {\n\t\treturn true\n\t}\n\tif (currentVersion === undefined) {\n\t\treturn true\n\t}\n\tif (currentVersion === \"\") {\n\t\treturn true\n\t}\n\tif (semver.valid(currentVersion) === null) {\n\t\treturn true\n\t}\n\treturn false\n}\n\nfunction loadCache(): Promise<CacheEntry | null> {\n\ttry {\n\t\tconst raw = readFileSync(cachePath, \"utf8\")\n\t\tconst parsed: unknown = JSON.parse(raw)\n\t\tif (\n\t\t\tparsed !== null &&\n\t\t\ttypeof parsed === \"object\" &&\n\t\t\ttypeof (parsed as CacheEntry).latest === \"string\" &&\n\t\t\ttypeof (parsed as CacheEntry).checkedAt === \"number\"\n\t\t) {\n\t\t\tconst entry = parsed as CacheEntry\n\t\t\tconst ageH = ((Date.now() - entry.checkedAt) / 3_600_000).toFixed(2)\n\t\t\tdebug(\"loadCache: hit — latest=%s, age=%sh\", entry.latest, ageH)\n\t\t\treturn Promise.resolve(entry)\n\t\t}\n\t\tdebug(\"loadCache: miss — malformed entry\")\n\t\treturn Promise.resolve(null)\n\t} catch {\n\t\tdebug(\"loadCache: miss — %s does not exist\", cachePath)\n\t\treturn Promise.resolve(null)\n\t}\n}\n\nfunction saveCache(entry: CacheEntry): Promise<void> {\n\ttry {\n\t\tmkdirSync(dirname(cachePath), { recursive: true })\n\t\twriteFileSync(cachePath, JSON.stringify(entry), \"utf8\")\n\t\tdebug(\"saveCache: wrote latest=%s to %s\", entry.latest, cachePath)\n\t} catch (err) {\n\t\tdebug(\"saveCache: failed — %s\", err instanceof Error ? err.message : String(err))\n\t\t// Silently ignore: EACCES, ENOSPC, etc. The nag is best-effort.\n\t}\n\treturn Promise.resolve()\n}\n\n/**\n * Fetch latest version from the registry. Aborts on FETCH_TIMEOUT_MS or when\n * `parentSignal` aborts (user keypress). Returns null on any failure so the\n * caller can degrade silently.\n */\nasync function fetchLatest(parentSignal?: AbortSignal): Promise<string | null> {\n\tdebug(\"fetchLatest: GET %s (timeout=%dms)\", REGISTRY_URL, FETCH_TIMEOUT_MS)\n\ttry {\n\t\tconst controller = new AbortController()\n\t\tconst timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS)\n\n\t\t// Wire parent abort (user keypress) → fetch abort.\n\t\tconst onParentAbort = () => controller.abort()\n\t\tif (parentSignal) {\n\t\t\tif (parentSignal.aborted) {\n\t\t\t\tcontroller.abort()\n\t\t\t} else {\n\t\t\t\tparentSignal.addEventListener(\"abort\", onParentAbort, { once: true })\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\tconst response = await fetchImpl(REGISTRY_URL, { signal: controller.signal })\n\t\t\tif (!response.ok) {\n\t\t\t\tdebug(\"fetchLatest: HTTP %d — returning null\", response.status)\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst data = (await response.json()) as { latest?: unknown }\n\t\t\tif (typeof data.latest !== \"string\") {\n\t\t\t\tdebug(\"fetchLatest: response missing 'latest' field — returning null\")\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tdebug(\"fetchLatest: ok — latest=%s\", data.latest)\n\t\t\treturn data.latest\n\t\t} finally {\n\t\t\tclearTimeout(timer)\n\t\t\tif (parentSignal) parentSignal.removeEventListener(\"abort\", onParentAbort)\n\t\t}\n\t} catch (err) {\n\t\tconst msg = err instanceof Error ? err.message : String(err)\n\t\tdebug(\"fetchLatest: error — %s\", msg)\n\t\treturn null\n\t}\n}\n\nfunction displayNag(current: string, latest: string): void {\n\tdebug(\"displayNag: %s → %s\", current, latest)\n\tconst message =\n\t\t`Update available: ${yellow(current)} → ${green(latest)}\\n` +\n\t\t`Run ${cyan(\"cmint update\")} to update`\n\tlog.warn(message)\n}\n\n/**\n * Fire-and-forget cache refresh used by the stale-while-revalidate (SWR) band\n * (cache age in [FRESH_MS, STALE_MS)). Runs the registry fetch and writes a\n * fresh cache entry without awaiting — the caller returns immediately with\n * the cached `latest` so the nag decision is fast.\n *\n * Wrapped in try/catch and `void`-ed so the floating promise NEVER rejects\n * (vitest fails the suite on unhandled rejections). On any failure (network,\n * HTTP non-ok, malformed JSON, fs write error) the cache file is left\n * unchanged and the failure is logged via {@link debug} only.\n *\n * No abort signal is wired here — the cancellable spinner only runs on the\n * STALE blocking-fetch path, and FRESH/SWR callers explicitly want this to\n * complete in the background regardless of user keystrokes.\n */\nfunction refreshCacheInBackground(): void {\n\tdebug(\"refreshCacheInBackground: starting fire-and-forget refresh\")\n\tvoid (async () => {\n\t\ttry {\n\t\t\tconst latest = await fetchLatest()\n\t\t\tif (latest === null) {\n\t\t\t\tdebug(\"refreshCacheInBackground: fetch returned null, leaving cache unchanged\")\n\t\t\t\treturn\n\t\t\t}\n\t\t\tawait saveCache({ latest, checkedAt: Date.now() })\n\t\t\tdebug(\"refreshCacheInBackground: refreshed cache to latest=%s\", latest)\n\t\t} catch (err) {\n\t\t\tconst msg = err instanceof Error ? err.message : String(err)\n\t\t\tdebug(\"refreshCacheInBackground: failed — %s\", msg)\n\t\t}\n\t})()\n}\n\n/**\n * Outcome of an update check. Callers use this to decide which (if any)\n * non-nag message to show — e.g. \"You are on the latest version\" is only\n * appropriate after a real fetch, not on a cache hit.\n */\nexport type UpdateCheckStatus =\n\t| \"skipped\"\n\t| \"cache-update\"\n\t| \"cache-current\"\n\t| \"fetch-update\"\n\t| \"fetch-current\"\n\t| \"fetch-failed-or-aborted\"\n\t| \"error\"\n\n/**\n * Resolve the cache-hit branch (FRESH / SWR / stale-or-missing). Returns\n * `null` when the caller must fall through to the blocking-fetch path; returns\n * a {@link UpdateCheckStatus} when the cache hit is terminal.\n *\n * Side effect: kicks off a fire-and-forget {@link refreshCacheInBackground}\n * when age is in the SWR band [FRESH_MS, STALE_MS).\n */\nfunction resolveCacheHit(\n\tcached: CacheEntry | null,\n\tcurrentVersion: string,\n\tonNag: (current: string, latest: string) => void,\n): UpdateCheckStatus | null {\n\tif (cached === null) {\n\t\tdebug(\"runUpdateCheck: no cache, fetching\")\n\t\treturn null\n\t}\n\tconst age = Date.now() - cached.checkedAt\n\tif (age >= STALE_MS) {\n\t\tdebug(\"runUpdateCheck: cache stale (>=%dh), refetching\", STALE_MS / 3_600_000)\n\t\treturn null\n\t}\n\t// Cache-hit band: FRESH (<1h) → silent; SWR (1h–24h) → serve +\n\t// fire-and-forget background refresh for the next invocation.\n\tif (age < FRESH_MS) {\n\t\tdebug(\"runUpdateCheck: cache fresh (<%dh), serving from cache\", FRESH_MS / 3_600_000)\n\t} else {\n\t\tdebug(\n\t\t\t\"runUpdateCheck: cache in SWR band (<%dh), serving + background refresh\",\n\t\t\tSTALE_MS / 3_600_000,\n\t\t)\n\t\trefreshCacheInBackground()\n\t}\n\tif (semver.gt(cached.latest, currentVersion)) {\n\t\tonNag(currentVersion, cached.latest)\n\t\treturn \"cache-update\"\n\t}\n\tdebug(\"runUpdateCheck: current >= latest, no nag\")\n\treturn \"cache-current\"\n}\n\n/**\n * Run the full update check. Exported for tests; the public surface is\n * {@link checkForUpdatesUpfront}. Accepts an optional AbortSignal that\n * propagates to the underlying fetch — used by the cancellable spinner.\n *\n * When an update is available, {@link onNag} is invoked (defaulting to\n * {@link displayNag}). The cancellable spinner path passes a capturing\n * callback so it can stop the spinner BEFORE the nag prints — otherwise\n * `log.warn` interleaves with the spinner line and leaves it on screen.\n *\n * Returns an {@link UpdateCheckStatus} so the caller can distinguish a\n * real fetch that found the user current (eligible for \"You are on the\n * latest version\" feedback) from a silent cache hit.\n */\nexport async function runUpdateCheck(\n\tcurrentVersion: string,\n\tparentSignal?: AbortSignal,\n\tonNag: (current: string, latest: string) => void = displayNag,\n): Promise<UpdateCheckStatus> {\n\tdebug(\"runUpdateCheck: currentVersion=%s\", currentVersion)\n\tif (shouldSkip(currentVersion)) {\n\t\tdebug(\n\t\t\t\"runUpdateCheck: skipped (NO_UPDATE_NOTIFIER / CI / NODE_ENV=test / non-TTY / invalid version)\",\n\t\t)\n\t\treturn \"skipped\"\n\t}\n\ttry {\n\t\tconst cached = await loadCache()\n\t\tconst cacheStatus = resolveCacheHit(cached, currentVersion, onNag)\n\t\tif (cacheStatus !== null) {\n\t\t\treturn cacheStatus\n\t\t}\n\t\tconst latest = await fetchLatest(parentSignal)\n\t\tif (latest === null) {\n\t\t\tdebug(\"runUpdateCheck: fetch returned null, not saving cache\")\n\t\t\treturn \"fetch-failed-or-aborted\"\n\t\t}\n\t\tawait saveCache({ latest, checkedAt: Date.now() })\n\t\tif (semver.gt(latest, currentVersion)) {\n\t\t\tonNag(currentVersion, latest)\n\t\t\treturn \"fetch-update\"\n\t\t}\n\t\tdebug(\"runUpdateCheck: current >= latest, no nag\")\n\t\treturn \"fetch-current\"\n\t} catch (err) {\n\t\t// Silently swallow: update check must never surface errors to the user.\n\t\tdebug(\"runUpdateCheck: unexpected error — %s\", err instanceof Error ? err.message : String(err))\n\t\treturn \"error\"\n\t}\n}\n\n/**\n * Run the update check at startup. Silent when:\n * - skip conditions match (CI, NO_UPDATE_NOTIFIER, NODE_ENV=test, non-TTY\n * stderr, invalid version)\n * - cache is fresh (< 24h old) — only displays nag if update available.\n * A cache-hit-current result produces NO output (no \"latest version\"\n * message), because no actual check was performed.\n * - stdin is non-interactive (piped) — runs silently without spinner, but\n * still shows \"You are on the latest version\" after a successful fetch\n *\n * On a stale/missing cache with interactive stdin, shows a spinner that the\n * user can dismiss by pressing any key. Ctrl+C restores the terminal and\n * exits with conventional code 130.\n */\nexport async function checkForUpdatesUpfront(currentVersion: string): Promise<void> {\n\tdebug(\"checkForUpdatesUpfront: currentVersion=%s\", currentVersion)\n\tif (shouldSkip(currentVersion)) {\n\t\tdebug(\n\t\t\t\"checkForUpdatesUpfront: skipped (NO_UPDATE_NOTIFIER / CI / NODE_ENV=test / non-TTY / invalid version)\",\n\t\t)\n\t\treturn\n\t}\n\n\t// Fast path: cache hit (FRESH or SWR band). Delegate entirely to\n\t// runUpdateCheck so nag + fire-and-forget refresh share one code path.\n\t// The returned status is ignored — \"latest version\" feedback is reserved\n\t// for actual fetches via reportFetchCurrent on the slow path below.\n\tconst cached = await loadCache()\n\tif (cached && Date.now() - cached.checkedAt < STALE_MS) {\n\t\tawait runUpdateCheck(currentVersion)\n\t\treturn\n\t}\n\n\tif (cached) {\n\t\tdebug(\"checkForUpdatesUpfront: cache stale (>=%dh), refetching\", STALE_MS / 3_600_000)\n\t} else {\n\t\tdebug(\"checkForUpdatesUpfront: no cache, fetching\")\n\t}\n\n\t// Slow path: cancellable spinner if stdin is interactive.\n\tconst stdin = process.stdin\n\tif (stdin.isTTY !== true || typeof stdin.setRawMode !== \"function\") {\n\t\tdebug(\"checkForUpdatesUpfront: stdin not interactive, running silent check\")\n\t\tconst status = await runUpdateCheck(currentVersion)\n\t\treportFetchCurrent(status)\n\t\treturn\n\t}\n\n\tawait runCheckWithSpinner(currentVersion)\n}\n\n/**\n * Surface \"You are on the latest version\" feedback only when the check\n * actually performed a fetch and the user is current. Silent on cache hits,\n * skips, failures, and aborts.\n */\nfunction reportFetchCurrent(status: UpdateCheckStatus): void {\n\tif (status === \"fetch-current\") {\n\t\tlog.info(green(\"You are on the latest version\"))\n\t}\n}\n\n/**\n * Attach a \"press any key to skip\" listener to stdin. Returns a cleanup\n * function that restores raw mode + pauses stdin; safe to call multiple times.\n * Returns `failed: true` if raw mode could not be enabled (caller should fall\n * back to a silent check).\n *\n * On any keypress: aborts `controller`. On Ctrl+C (byte 0x03): runs cleanup,\n * stops the spinner with `spinnerMsg`, and exits with conventional code 130.\n */\nfunction attachStdinSkip(\n\tcontroller: AbortController,\n\tspinner: { stop: (msg: string) => void },\n\tspinnerMsg: string,\n): { cleanup: () => void; failed: boolean } {\n\tconst stdin = process.stdin\n\tlet cleanedUp = false\n\n\tconst cleanup = (): void => {\n\t\tif (cleanedUp) return\n\t\tcleanedUp = true\n\t\tstdin.off(\"data\", onData)\n\t\ttry {\n\t\t\tstdin.setRawMode(false)\n\t\t} catch (err) {\n\t\t\tdebug(\n\t\t\t\t\"attachStdinSkip: setRawMode(false) failed — %s\",\n\t\t\t\terr instanceof Error ? err.message : String(err),\n\t\t\t)\n\t\t}\n\t\ttry {\n\t\t\tstdin.pause()\n\t\t} catch {\n\t\t\t// ignore — already paused\n\t\t}\n\t}\n\n\tfunction onData(buffer: Buffer): void {\n\t\tconst byte = buffer[0]\n\t\tdebug(\"attachStdinSkip: stdin byte=0x%s\", byte.toString(16).padStart(2, \"0\"))\n\t\tif (byte === 0x03) {\n\t\t\t// Ctrl+C in raw mode does not auto-generate SIGINT. Restore the\n\t\t\t// terminal before exiting so the user's shell isn't left in raw mode.\n\t\t\tdebug(\"attachStdinSkip: Ctrl+C (0x03), exiting\")\n\t\t\tcleanup()\n\t\t\tspinner.stop(spinnerMsg)\n\t\t\tprocess.exit(130)\n\t\t}\n\t\tdebug(\"attachStdinSkip: user pressed key, aborting check\")\n\t\tcontroller.abort()\n\t}\n\n\ttry {\n\t\tstdin.setRawMode(true)\n\t\tstdin.resume()\n\t\tstdin.on(\"data\", onData)\n\t\treturn { cleanup, failed: false }\n\t} catch (err) {\n\t\tdebug(\n\t\t\t\"attachStdinSkip: setRawMode failed — %s\",\n\t\t\terr instanceof Error ? err.message : String(err),\n\t\t)\n\t\treturn { cleanup: () => {}, failed: true }\n\t}\n}\n\n/**\n * Show a cancellable spinner while the check runs. Puts stdin in raw mode to\n * capture individual keypresses via {@link attachStdinSkip}.\n */\nasync function runCheckWithSpinner(currentVersion: string): Promise<void> {\n\tdebug(\"runCheckWithSpinner: showing cancellable spinner\")\n\tconst s = spinner()\n\ts.start(\"Checking for updates (press any key to skip)\")\n\n\tconst controller = new AbortController()\n\tconst handler = attachStdinSkip(controller, s, \"Cancelled\")\n\n\tif (handler.failed) {\n\t\ts.stop(\"\")\n\t\tconst status = await runUpdateCheck(currentVersion)\n\t\treportFetchCurrent(status)\n\t\treturn\n\t}\n\n\t// Capture the nag instead of printing it immediately. The spinner MUST be\n\t// stopped before any log output, otherwise clack leaves the spinner line\n\t// on screen (log.warn interleaves with the animated spinner). Wrapped in\n\t// a const object so TS doesn't narrow through the callback closure.\n\tconst captured: { nag: { current: string; latest: string } | null } = { nag: null }\n\tlet status: UpdateCheckStatus\n\ttry {\n\t\tstatus = await runUpdateCheck(currentVersion, controller.signal, (current, latest) => {\n\t\t\tcaptured.nag = { current, latest }\n\t\t})\n\t} finally {\n\t\thandler.cleanup()\n\t}\n\n\tif (controller.signal.aborted) {\n\t\tdebug(\"runCheckWithSpinner: spinner dismissed by user\")\n\t\ts.stop(\"Skipped\")\n\t} else if (status === \"fetch-current\") {\n\t\ts.stop(green(\"You are on the latest version\"))\n\t} else if (status === \"fetch-update\" || status === \"cache-update\") {\n\t\ts.stop(\"\")\n\t\tif (captured.nag) displayNag(captured.nag.current, captured.nag.latest)\n\t} else if (status === \"fetch-failed-or-aborted\") {\n\t\ts.stop(\"Update check failed\")\n\t} else {\n\t\ts.stop(\"\")\n\t}\n}\n","import { log, type spinner } from \"@clack/prompts\"\nimport { green, red } from \"kolorist\"\nimport { attemptCommit, attemptCommitNoVerify, getHead, stageAll } from \"../services/git.js\"\nimport { createProgressHandler } from \"../services/hook-progress.js\"\nimport { parseHookErrors, parseToolChecks } from \"../services/hooks.js\"\nimport { showRecoveryMenu } from \"../ui/recovery-menu.js\"\n\n/** Shared recovery menu factory — avoids repeating the same callback set */\nexport function makeRecoveryCallbacks(message: string) {\n\treturn {\n\t\tretry: async () => (await attemptCommit(message)).ok,\n\t\tskipHooks: async (msg: string) => (await attemptCommitNoVerify(msg)).ok,\n\t\trestage: async () => {\n\t\t\tawait stageAll()\n\t\t\treturn (await attemptCommit(message)).ok\n\t\t},\n\t\tmessage,\n\t}\n}\n\n/**\n * Attempt commit with automatic recovery flow.\n * Handles the attempt → HEAD check → success (tool checks display)\n * / failure (recovery menu) pattern.\n * Caller is responsible for starting the spinner and showing the final outro.\n */\nexport async function commitWithRecovery(\n\tmessage: string,\n\ts: ReturnType<typeof spinner>,\n\theadBefore: string | null,\n): Promise<\"committed\" | \"cancelled\"> {\n\tconst result = await attemptCommit(message, [], createProgressHandler(s))\n\tconst headAfter = await getHead()\n\n\tif (result.ok || headBefore !== headAfter) {\n\t\ts.stop(\"Committed successfully.\")\n\n\t\tconst checks = parseToolChecks(result.stderr ?? \"\")\n\t\tif (checks.length > 0) {\n\t\t\tconst lines = checks.map((c) => ` ${c.ok ? green(\"✓\") : red(\"✗\")} ${c.tool}`)\n\t\t\tlog.info(lines.join(\"\\n\"))\n\t\t}\n\n\t\treturn \"committed\"\n\t}\n\n\ts.stop(\"Commit failed.\")\n\tconst errors = parseHookErrors(result.stderr ?? \"\")\n\tconst cb = makeRecoveryCallbacks(message)\n\tconst recoveryResult = await showRecoveryMenu(\n\t\terrors,\n\t\tcb.retry,\n\t\tcb.skipHooks,\n\t\tcb.restage,\n\t\tcb.message,\n\t\tresult.stderr ?? \"\",\n\t)\n\n\tif (recoveryResult === \"cancelled\") {\n\t\treturn \"cancelled\"\n\t}\n\n\treturn \"committed\"\n}\n","import { intro, outro, spinner } from \"@clack/prompts\"\nimport { green, red } from \"kolorist\"\nimport { getHead, getRepoRoot } from \"../services/git.js\"\nimport { loadCachedCommit } from \"../utils/cache.js\"\nimport { debug } from \"../utils/debug.js\"\nimport { commitWithRecovery } from \"./commit-utils.js\"\n\n/** Handle --retry mode: load cached message and re-attempt commit */\nexport async function handleRetry(): Promise<void> {\n\tdebug(\"Entering retry mode\")\n\tconst repoRoot = await getRepoRoot()\n\tconst cached = await loadCachedCommit(repoRoot)\n\tif (!cached) {\n\t\toutro(red(\"No cached commit message found. Run cmint without --retry first.\"))\n\t\tprocess.exit(1)\n\t}\n\tintro(\"🌿 commit-mint — retry\")\n\tconst s = spinner()\n\tconst headBefore = await getHead()\n\ts.start(\"Running pre-commit hooks...\")\n\tconst result = await commitWithRecovery(cached.message, s, headBefore)\n\tif (result === \"committed\") {\n\t\toutro(green(\"Committed successfully.\"))\n\t} else {\n\t\tprocess.exit(1)\n\t}\n}\n","import { access, constants, writeFile } from \"node:fs/promises\"\nimport { join } from \"node:path\"\nimport * as p from \"@clack/prompts\"\nimport { bold, dim, green, yellow } from \"kolorist\"\nimport { detectConfig } from \"../services/checks.js\"\nimport { debug } from \"../utils/debug.js\"\n\n/** Marker files for each tool. First match wins per tool. */\nconst TOOL_MARKERS: Record<ToolName, readonly string[]> = {\n\tbiome: [\"biome.json\", \"biome.jsonc\"],\n\teslint: [\n\t\t\"eslint.config.js\",\n\t\t\"eslint.config.mjs\",\n\t\t\"eslint.config.ts\",\n\t\t\"eslint.config.cjs\",\n\t\t\".eslintrc.js\",\n\t\t\".eslintrc.cjs\",\n\t\t\".eslintrc.json\",\n\t\t\".eslintrc.yml\",\n\t\t\".eslintrc.yaml\",\n\t\t\".eslintrc\",\n\t],\n\ttypescript: [\"tsconfig.json\"],\n\tvitest: [\"vitest.config.js\", \"vitest.config.mts\", \"vitest.config.ts\", \"vitest.config.mjs\"],\n} as const\n\nexport type ToolName = \"biome\" | \"eslint\" | \"typescript\" | \"vitest\"\n\nexport type DetectedTools = Record<ToolName, boolean>\n\n/** Indent for generated config — matches biome.json `indentStyle: \"tab\"`. */\nconst TAB = \"\\t\"\n\nasync function exists(path: string): Promise<boolean> {\n\ttry {\n\t\tawait access(path, constants.R_OK)\n\t\treturn true\n\t} catch {\n\t\treturn false\n\t}\n}\n\n/**\n * Scan a directory for marker files that indicate which tools the project uses.\n * Returns a map of tool name to detected status. Order within each tool's list\n * is priority order (first match wins).\n */\nexport async function detectTools(cwd: string): Promise<DetectedTools> {\n\tconst result: DetectedTools = { biome: false, eslint: false, typescript: false, vitest: false }\n\tfor (const [tool, files] of Object.entries(TOOL_MARKERS) as [ToolName, readonly string[]][]) {\n\t\tfor (const file of files) {\n\t\t\tif (await exists(join(cwd, file))) {\n\t\t\t\tresult[tool] = true\n\t\t\t\tdebug(\"setup: detected %s via %s\", tool, file)\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\tdebug(\"setup: detection result %o\", result)\n\treturn result\n}\n\n/**\n * Build the string content of a .cmintrc file from a detection result.\n * Returns tabs-indented TS/JS object literal with trailing commas. Biome is\n * preferred when both biome and eslint are present — overlapping globs would\n * cause both tools to run on the same files, which is wasteful and noisy.\n */\nexport function buildCmintrcContent(tools: DetectedTools): string {\n\tconst entries: string[] = []\n\n\tconst linter = tools.biome || tools.eslint\n\tif (linter) {\n\t\tconst cmd = tools.biome\n\t\t\t? \"biome check --write --no-errors-on-unmatched --error-on-warnings\"\n\t\t\t: \"eslint --fix\"\n\t\tconst ext = tools.biome ? \"{js,ts,json}\" : \"{js,ts}\"\n\t\tentries.push(`${TAB}\"*.${ext}\": \"${cmd}\",`)\n\t}\n\n\tconst tsChecks: string[] = []\n\tif (tools.typescript) tsChecks.push(\"tsc --noEmit\")\n\tif (tools.vitest) tsChecks.push(\"vitest run --passWithNoTests\")\n\tif (tsChecks.length > 0) {\n\t\tconst body = tsChecks.map((c) => `\"${c}\"`).join(\", \")\n\t\tconst fn = tsChecks.length === 1 ? `() => ${body}` : `() => [${body}]`\n\t\tentries.push(`${TAB}\"*.ts\": ${fn},`)\n\t}\n\n\tif (entries.length === 0) {\n\t\treturn `export default {\\n};\\n`\n\t}\n\n\treturn `export default {\\n${entries.join(\"\\n\")}\\n};\\n`\n}\n\n/** Choose the file extension based on whether the project uses TypeScript. */\nexport function pickFileName(tools: DetectedTools): string {\n\treturn tools.typescript ? \".cmintrc.ts\" : \".cmintrc\"\n}\n\nfunction formatDetection(tools: DetectedTools): string {\n\treturn (Object.entries(tools) as [ToolName, boolean][])\n\t\t.map(([tool, found]) => ` ${found ? green(\"✓\") : dim(\"✗\")} ${tool}`)\n\t\t.join(\"\\n\")\n}\n\n/**\n * Interactive setup for `.cmintrc`. Detects biome/eslint/typescript/vitest in\n * the given directory, previews the generated config, and writes the file\n * after confirmation. Refuses to overwrite without explicit consent. Defaults\n * to `process.cwd()` when called from the `cmint config` menu; the preflight\n * caller passes the repo root explicitly.\n */\nexport async function setupCmintrcCommand(cwd: string = process.cwd()): Promise<void> {\n\tdebug(\"setupCmintrcCommand: starting in %s\", cwd)\n\tconst tools = await detectTools(cwd)\n\n\tp.log.info(`Detected tools in ${bold(cwd)}:`)\n\tp.log.message(formatDetection(tools))\n\n\tconst foundAny = Object.values(tools).some(Boolean)\n\tif (!foundAny) {\n\t\tp.log.warn(\"No recognized tools found. Writing an empty config to fill in manually.\")\n\t} else if (tools.biome && tools.eslint) {\n\t\tp.log.warn(yellow(\"Both biome and eslint detected — using biome (remove this line to switch).\"))\n\t}\n\n\tconst fileName = pickFileName(tools)\n\tconst filePath = join(cwd, fileName)\n\n\tif (await exists(filePath)) {\n\t\tconst overwrite = await p.confirm({\n\t\t\tmessage: `${fileName} already exists. Overwrite?`,\n\t\t})\n\t\tif (p.isCancel(overwrite) || !overwrite) {\n\t\t\tp.log.info(dim(\"Cancelled — existing file left untouched.\"))\n\t\t\treturn\n\t\t}\n\t}\n\n\tconst content = buildCmintrcContent(tools)\n\tp.log.info(dim(`\\nPreview of ${fileName}:`))\n\tp.log.message(dim(content))\n\n\tconst confirm = await p.confirm({\n\t\tmessage: `Write ${fileName}?`,\n\t})\n\tif (p.isCancel(confirm) || !confirm) {\n\t\tp.log.info(dim(\"Cancelled.\"))\n\t\treturn\n\t}\n\n\tawait writeFile(filePath, content, \"utf-8\")\n\tdebug(\"setupCmintrcCommand: wrote %s\", filePath)\n\tp.log.success(green(`Wrote ${fileName}`))\n}\n\n// ── Preflight prompt ──────────────────────────────────────────────────────\n\n/** Project-local marker file that suppresses the preflight prompt forever. */\nexport const SKIP_SETUP_MARKER = \".cmint-skip-setup\"\n\n/** True if at least one of biome/eslint/typescript/vitest is present. */\nexport function isAutoConfigurable(tools: DetectedTools): boolean {\n\treturn Object.values(tools).some(Boolean)\n}\n\n/** True if the skip-setup marker exists in `cwd`. */\nexport async function hasSkipSetupMarker(cwd: string): Promise<boolean> {\n\treturn exists(join(cwd, SKIP_SETUP_MARKER))\n}\n\n/** Write the skip-setup marker to `cwd`. The file is empty by design. */\nexport async function writeSkipSetupMarker(cwd: string): Promise<void> {\n\tconst filePath = join(cwd, SKIP_SETUP_MARKER)\n\tawait writeFile(filePath, \"\", \"utf-8\")\n\tdebug(\"preflight: wrote skip-setup marker to %s\", filePath)\n}\n\n/**\n * One-shot prompt run at the start of `cmint`. Skips silently if the user\n * already has a `.cmintrc` or has previously opted out (`.cmint-skip-setup`).\n * If the project is auto-configurable, asks the user whether to run setup\n * now. Choices: `yes` runs the standard setup flow; `no` proceeds without\n * setup and re-prompts next time; `never` writes a marker to suppress the\n * prompt for this project forever.\n */\nexport async function runPreflightSetupPrompt(cwd: string): Promise<void> {\n\tdebug(\"preflight: checking %s\", cwd)\n\n\tif (await hasSkipSetupMarker(cwd)) {\n\t\tdebug(\"preflight: skip-setup marker present, skipping prompt\")\n\t\treturn\n\t}\n\n\tconst existingConfig = await detectConfig(cwd)\n\tif (existingConfig) {\n\t\tdebug(\"preflight: .cmintrc present at %s, skipping prompt\", existingConfig)\n\t\treturn\n\t}\n\n\tconst tools = await detectTools(cwd)\n\tif (!isAutoConfigurable(tools)) {\n\t\tdebug(\"preflight: project not auto-configurable, skipping prompt\")\n\t\treturn\n\t}\n\n\tconst choice = await p.select({\n\t\tmessage: \"No .cmintrc found. Run setup to create one from detected tools?\",\n\t\toptions: [\n\t\t\t{ label: \"Yes, set up .cmintrc\", value: \"yes\" },\n\t\t\t{ label: \"No, skip for now\", value: \"no\" },\n\t\t\t{ label: \"No, don't ask again\", value: \"never\" },\n\t\t],\n\t})\n\n\tif (p.isCancel(choice)) {\n\t\tdebug(\"preflight: user cancelled prompt\")\n\t\treturn\n\t}\n\n\tif (choice === \"never\") {\n\t\tawait writeSkipSetupMarker(cwd)\n\t\tp.log.info(dim(`Won't ask again. Delete ${SKIP_SETUP_MARKER} to re-enable.`))\n\t\treturn\n\t}\n\n\tif (choice === \"no\") {\n\t\tp.log.info(dim(\"Skipping .cmintrc setup.\"))\n\t\treturn\n\t}\n\n\t// \"yes\" — run the standard setup flow (with its own confirmations).\n\tdebug(\"preflight: user chose yes, running setup\")\n\tawait setupCmintrcCommand(cwd)\n}\n","/* MAIN */\nconst getCodePointsLength = (() => {\n const SURROGATE_PAIR_RE = /[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]/g;\n return (input) => {\n let surrogatePairsNr = 0;\n SURROGATE_PAIR_RE.lastIndex = 0;\n while (SURROGATE_PAIR_RE.test(input)) {\n surrogatePairsNr += 1;\n }\n return input.length - surrogatePairsNr;\n };\n})();\nconst isFullWidth = (x) => {\n return x === 0x3000 || x >= 0xFF01 && x <= 0xFF60 || x >= 0xFFE0 && x <= 0xFFE6;\n};\nconst isWideNotCJKTNotEmoji = (x) => {\n return x === 0x231B || x === 0x2329 || x >= 0x2FF0 && x <= 0x2FFF || x >= 0x3001 && x <= 0x303E || x >= 0x3099 && x <= 0x30FF || x >= 0x3105 && x <= 0x312F || x >= 0x3131 && x <= 0x318E || x >= 0x3190 && x <= 0x31E3 || x >= 0x31EF && x <= 0x321E || x >= 0x3220 && x <= 0x3247 || x >= 0x3250 && x <= 0x4DBF || x >= 0xFE10 && x <= 0xFE19 || x >= 0xFE30 && x <= 0xFE52 || x >= 0xFE54 && x <= 0xFE66 || x >= 0xFE68 && x <= 0xFE6B || x >= 0x1F200 && x <= 0x1F202 || x >= 0x1F210 && x <= 0x1F23B || x >= 0x1F240 && x <= 0x1F248 || x >= 0x20000 && x <= 0x2FFFD || x >= 0x30000 && x <= 0x3FFFD;\n};\n/* EXPORT */\nexport { getCodePointsLength, isFullWidth, isWideNotCJKTNotEmoji };\n","/* IMPORT */\nimport { getCodePointsLength, isFullWidth, isWideNotCJKTNotEmoji } from './utils.js';\n/* HELPERS */\nconst ANSI_RE = /[\\u001b\\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\\u001b\\]8;[^;]*;.*?(?:\\u0007|\\u001b\\u005c)/y;\nconst CONTROL_RE = /[\\x00-\\x08\\x0A-\\x1F\\x7F-\\x9F]{1,1000}/y;\nconst CJKT_WIDE_RE = /(?:(?![\\uFF61-\\uFF9F\\uFF00-\\uFFEF])[\\p{Script=Han}\\p{Script=Hiragana}\\p{Script=Katakana}\\p{Script=Hangul}\\p{Script=Tangut}]){1,1000}/yu;\nconst TAB_RE = /\\t{1,1000}/y;\nconst EMOJI_RE = /[\\u{1F1E6}-\\u{1F1FF}]{2}|\\u{1F3F4}[\\u{E0061}-\\u{E007A}]{2}[\\u{E0030}-\\u{E0039}\\u{E0061}-\\u{E007A}]{1,3}\\u{E007F}|(?:\\p{Emoji}\\uFE0F\\u20E3?|\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|\\p{Emoji_Presentation})(?:\\u200D(?:\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|\\p{Emoji_Presentation}|\\p{Emoji}\\uFE0F\\u20E3?))*/yu;\nconst LATIN_RE = /(?:[\\x20-\\x7E\\xA0-\\xFF](?!\\uFE0F)){1,1000}/y;\nconst MODIFIER_RE = /\\p{M}+/gu;\nconst NO_TRUNCATION = { limit: Infinity, ellipsis: '' };\n/* MAIN */\nconst getStringTruncatedWidth = (input, truncationOptions = {}, widthOptions = {}) => {\n /* CONSTANTS */\n const LIMIT = truncationOptions.limit ?? Infinity;\n const ELLIPSIS = truncationOptions.ellipsis ?? '';\n const ELLIPSIS_WIDTH = truncationOptions?.ellipsisWidth ?? (ELLIPSIS ? getStringTruncatedWidth(ELLIPSIS, NO_TRUNCATION, widthOptions).width : 0);\n const ANSI_WIDTH = 0;\n const CONTROL_WIDTH = widthOptions.controlWidth ?? 0;\n const TAB_WIDTH = widthOptions.tabWidth ?? 8;\n const EMOJI_WIDTH = widthOptions.emojiWidth ?? 2;\n const FULL_WIDTH_WIDTH = 2;\n const REGULAR_WIDTH = widthOptions.regularWidth ?? 1;\n const WIDE_WIDTH = widthOptions.wideWidth ?? FULL_WIDTH_WIDTH;\n const PARSE_BLOCKS = [\n [LATIN_RE, REGULAR_WIDTH],\n [ANSI_RE, ANSI_WIDTH],\n [CONTROL_RE, CONTROL_WIDTH],\n [TAB_RE, TAB_WIDTH],\n [EMOJI_RE, EMOJI_WIDTH],\n [CJKT_WIDE_RE, WIDE_WIDTH],\n ];\n /* STATE */\n let indexPrev = 0;\n let index = 0;\n let length = input.length;\n let lengthExtra = 0;\n let truncationEnabled = false;\n let truncationIndex = length;\n let truncationLimit = Math.max(0, LIMIT - ELLIPSIS_WIDTH);\n let unmatchedStart = 0;\n let unmatchedEnd = 0;\n let width = 0;\n let widthExtra = 0;\n /* PARSE LOOP */\n outer: while (true) {\n /* UNMATCHED */\n if ((unmatchedEnd > unmatchedStart) || (index >= length && index > indexPrev)) {\n const unmatched = input.slice(unmatchedStart, unmatchedEnd) || input.slice(indexPrev, index);\n lengthExtra = 0;\n for (const char of unmatched.replaceAll(MODIFIER_RE, '')) {\n const codePoint = char.codePointAt(0) || 0;\n if (isFullWidth(codePoint)) {\n widthExtra = FULL_WIDTH_WIDTH;\n }\n else if (isWideNotCJKTNotEmoji(codePoint)) {\n widthExtra = WIDE_WIDTH;\n }\n else {\n widthExtra = REGULAR_WIDTH;\n }\n if ((width + widthExtra) > truncationLimit) {\n truncationIndex = Math.min(truncationIndex, Math.max(unmatchedStart, indexPrev) + lengthExtra);\n }\n if ((width + widthExtra) > LIMIT) {\n truncationEnabled = true;\n break outer;\n }\n lengthExtra += char.length;\n width += widthExtra;\n }\n unmatchedStart = unmatchedEnd = 0;\n }\n /* EXITING */\n if (index >= length) {\n break outer;\n }\n /* PARSE BLOCKS */\n for (let i = 0, l = PARSE_BLOCKS.length; i < l; i++) {\n const [BLOCK_RE, BLOCK_WIDTH] = PARSE_BLOCKS[i];\n BLOCK_RE.lastIndex = index;\n if (BLOCK_RE.test(input)) {\n lengthExtra = BLOCK_RE === CJKT_WIDE_RE ? getCodePointsLength(input.slice(index, BLOCK_RE.lastIndex)) : BLOCK_RE === EMOJI_RE ? 1 : BLOCK_RE.lastIndex - index;\n widthExtra = lengthExtra * BLOCK_WIDTH;\n if ((width + widthExtra) > truncationLimit) {\n truncationIndex = Math.min(truncationIndex, index + Math.floor((truncationLimit - width) / BLOCK_WIDTH));\n }\n if ((width + widthExtra) > LIMIT) {\n truncationEnabled = true;\n break outer;\n }\n width += widthExtra;\n unmatchedStart = indexPrev;\n unmatchedEnd = index;\n index = indexPrev = BLOCK_RE.lastIndex;\n continue outer;\n }\n }\n /* UNMATCHED INDEX */\n index += 1;\n }\n /* RETURN */\n return {\n width: truncationEnabled ? truncationLimit : width,\n index: truncationEnabled ? truncationIndex : length,\n truncated: truncationEnabled,\n ellipsed: truncationEnabled && LIMIT >= ELLIPSIS_WIDTH\n };\n};\n/* EXPORT */\nexport default getStringTruncatedWidth;\n","/* IMPORT */\nimport fastStringTruncatedWidth from 'fast-string-truncated-width';\n/* HELPERS */\nconst NO_TRUNCATION = {\n limit: Infinity,\n ellipsis: '',\n ellipsisWidth: 0,\n};\n/* MAIN */\nconst fastStringWidth = (input, options = {}) => {\n return fastStringTruncatedWidth(input, NO_TRUNCATION, options).width;\n};\n/* EXPORT */\nexport default fastStringWidth;\n","import stringWidth from 'fast-string-width';\nconst ESC = '\\x1B';\nconst CSI = '\\x9B';\nconst END_CODE = 39;\nconst ANSI_ESCAPE_BELL = '\\u0007';\nconst ANSI_CSI = '[';\nconst ANSI_OSC = ']';\nconst ANSI_SGR_TERMINATOR = 'm';\nconst ANSI_ESCAPE_LINK = `${ANSI_OSC}8;;`;\nconst GROUP_REGEX = new RegExp(`(?:\\\\${ANSI_CSI}(?<code>\\\\d+)m|\\\\${ANSI_ESCAPE_LINK}(?<uri>.*)${ANSI_ESCAPE_BELL})`, 'y');\nconst getClosingCode = (openingCode) => {\n if (openingCode >= 30 && openingCode <= 37)\n return 39;\n if (openingCode >= 90 && openingCode <= 97)\n return 39;\n if (openingCode >= 40 && openingCode <= 47)\n return 49;\n if (openingCode >= 100 && openingCode <= 107)\n return 49;\n if (openingCode === 1 || openingCode === 2)\n return 22;\n if (openingCode === 3)\n return 23;\n if (openingCode === 4)\n return 24;\n if (openingCode === 7)\n return 27;\n if (openingCode === 8)\n return 28;\n if (openingCode === 9)\n return 29;\n if (openingCode === 0)\n return 0;\n return undefined;\n};\nconst wrapAnsiCode = (code) => `${ESC}${ANSI_CSI}${code}${ANSI_SGR_TERMINATOR}`;\nconst wrapAnsiHyperlink = (url) => `${ESC}${ANSI_ESCAPE_LINK}${url}${ANSI_ESCAPE_BELL}`;\nconst wrapWord = (rows, word, columns) => {\n const characters = word[Symbol.iterator]();\n let isInsideEscape = false;\n let isInsideLinkEscape = false;\n let lastRow = rows.at(-1);\n let visible = lastRow === undefined ? 0 : stringWidth(lastRow);\n let currentCharacter = characters.next();\n let nextCharacter = characters.next();\n let rawCharacterIndex = 0;\n while (!currentCharacter.done) {\n const character = currentCharacter.value;\n const characterLength = stringWidth(character);\n if (visible + characterLength <= columns) {\n rows[rows.length - 1] += character;\n }\n else {\n rows.push(character);\n visible = 0;\n }\n if (character === ESC || character === CSI) {\n isInsideEscape = true;\n isInsideLinkEscape = word.startsWith(ANSI_ESCAPE_LINK, rawCharacterIndex + 1);\n }\n if (isInsideEscape) {\n if (isInsideLinkEscape) {\n if (character === ANSI_ESCAPE_BELL) {\n isInsideEscape = false;\n isInsideLinkEscape = false;\n }\n }\n else if (character === ANSI_SGR_TERMINATOR) {\n isInsideEscape = false;\n }\n }\n else {\n visible += characterLength;\n if (visible === columns && !nextCharacter.done) {\n rows.push('');\n visible = 0;\n }\n }\n currentCharacter = nextCharacter;\n nextCharacter = characters.next();\n rawCharacterIndex += character.length;\n }\n lastRow = rows.at(-1);\n if (!visible && lastRow !== undefined && lastRow.length && rows.length > 1) {\n rows[rows.length - 2] += rows.pop();\n }\n};\nconst stringVisibleTrimSpacesRight = (string) => {\n const words = string.split(' ');\n let last = words.length;\n while (last) {\n if (stringWidth(words[last - 1])) {\n break;\n }\n last--;\n }\n if (last === words.length) {\n return string;\n }\n return words.slice(0, last).join(' ') + words.slice(last).join('');\n};\nconst exec = (string, columns, options = {}) => {\n if (options.trim !== false && string.trim() === '') {\n return '';\n }\n let returnValue = '';\n let escapeCode;\n let escapeUrl;\n const words = string.split(' ');\n let rows = [''];\n let rowLength = 0;\n for (let index = 0; index < words.length; index++) {\n const word = words[index];\n if (options.trim !== false) {\n const row = rows.at(-1) ?? '';\n const trimmed = row.trimStart();\n if (row.length !== trimmed.length) {\n rows[rows.length - 1] = trimmed;\n rowLength = stringWidth(trimmed);\n }\n }\n if (index !== 0) {\n if (rowLength >= columns &&\n (options.wordWrap === false || options.trim === false)) {\n rows.push('');\n rowLength = 0;\n }\n if (rowLength || options.trim === false) {\n rows[rows.length - 1] += ' ';\n rowLength++;\n }\n }\n const wordLength = stringWidth(word);\n if (options.hard && wordLength > columns) {\n const remainingColumns = columns - rowLength;\n const breaksStartingThisLine = 1 + Math.floor((wordLength - remainingColumns - 1) / columns);\n const breaksStartingNextLine = Math.floor((wordLength - 1) / columns);\n if (breaksStartingNextLine < breaksStartingThisLine) {\n rows.push('');\n }\n wrapWord(rows, word, columns);\n rowLength = stringWidth(rows.at(-1) ?? '');\n continue;\n }\n if (rowLength + wordLength > columns && rowLength && wordLength) {\n if (options.wordWrap === false && rowLength < columns) {\n wrapWord(rows, word, columns);\n rowLength = stringWidth(rows.at(-1) ?? '');\n continue;\n }\n rows.push('');\n rowLength = 0;\n }\n if (rowLength + wordLength > columns && options.wordWrap === false) {\n wrapWord(rows, word, columns);\n rowLength = stringWidth(rows.at(-1) ?? '');\n continue;\n }\n rows[rows.length - 1] += word;\n rowLength += wordLength;\n }\n if (options.trim !== false) {\n rows = rows.map((row) => stringVisibleTrimSpacesRight(row));\n }\n const preString = rows.join('\\n');\n let inSurrogate = false;\n for (let i = 0; i < preString.length; i++) {\n const character = preString[i];\n returnValue += character;\n if (!inSurrogate) {\n inSurrogate = character >= '\\ud800' && character <= '\\udbff';\n if (inSurrogate) {\n continue;\n }\n }\n else {\n inSurrogate = false;\n }\n if (character === ESC || character === CSI) {\n GROUP_REGEX.lastIndex = i + 1;\n const groupsResult = GROUP_REGEX.exec(preString);\n const groups = groupsResult?.groups;\n if (groups?.code !== undefined) {\n const code = Number.parseFloat(groups.code);\n escapeCode = code === END_CODE ? undefined : code;\n }\n else if (groups?.uri !== undefined) {\n escapeUrl = groups.uri.length === 0 ? undefined : groups.uri;\n }\n }\n if (preString[i + 1] === '\\n') {\n if (escapeUrl) {\n returnValue += wrapAnsiHyperlink('');\n }\n const closingCode = escapeCode ? getClosingCode(escapeCode) : undefined;\n if (escapeCode && closingCode) {\n returnValue += wrapAnsiCode(closingCode);\n }\n }\n else if (character === '\\n') {\n if (escapeCode && getClosingCode(escapeCode)) {\n returnValue += wrapAnsiCode(escapeCode);\n }\n if (escapeUrl) {\n returnValue += wrapAnsiHyperlink(escapeUrl);\n }\n }\n }\n return returnValue;\n};\nconst CRLF_OR_LF = /\\r?\\n/;\nexport function wrapAnsi(string, columns, options) {\n return String(string)\n .normalize()\n .split(CRLF_OR_LF)\n .map((line) => exec(line, columns, options))\n .join('\\n');\n}\n","'use strict';\n\nconst ESC = '\\x1B';\nconst CSI = `${ESC}[`;\nconst beep = '\\u0007';\n\nconst cursor = {\n to(x, y) {\n if (!y) return `${CSI}${x + 1}G`;\n return `${CSI}${y + 1};${x + 1}H`;\n },\n move(x, y) {\n let ret = '';\n\n if (x < 0) ret += `${CSI}${-x}D`;\n else if (x > 0) ret += `${CSI}${x}C`;\n\n if (y < 0) ret += `${CSI}${-y}A`;\n else if (y > 0) ret += `${CSI}${y}B`;\n\n return ret;\n },\n up: (count = 1) => `${CSI}${count}A`,\n down: (count = 1) => `${CSI}${count}B`,\n forward: (count = 1) => `${CSI}${count}C`,\n backward: (count = 1) => `${CSI}${count}D`,\n nextLine: (count = 1) => `${CSI}E`.repeat(count),\n prevLine: (count = 1) => `${CSI}F`.repeat(count),\n left: `${CSI}G`,\n hide: `${CSI}?25l`,\n show: `${CSI}?25h`,\n save: `${ESC}7`,\n restore: `${ESC}8`\n}\n\nconst scroll = {\n up: (count = 1) => `${CSI}S`.repeat(count),\n down: (count = 1) => `${CSI}T`.repeat(count)\n}\n\nconst erase = {\n screen: `${CSI}2J`,\n up: (count = 1) => `${CSI}1J`.repeat(count),\n down: (count = 1) => `${CSI}J`.repeat(count),\n line: `${CSI}2K`,\n lineEnd: `${CSI}K`,\n lineStart: `${CSI}1K`,\n lines(count) {\n let clear = '';\n for (let i = 0; i < count; i++)\n clear += this.line + (i < count - 1 ? cursor.up() : '');\n if (count)\n clear += cursor.left;\n return clear;\n }\n}\n\nmodule.exports = { cursor, scroll, erase, beep };\n","import{styleText as v}from\"node:util\";import{stdout as x,stdin as D}from\"node:process\";import*as b from\"node:readline\";import E from\"node:readline\";import{wrapAnsi as M}from\"fast-wrap-ansi\";import{cursor as p,erase as V}from\"sisteransi\";import{ReadStream as O}from\"node:tty\";function f(r,t,s){if(!s.some(o=>!o.disabled))return r;const e=r+t,i=Math.max(s.length-1,0),n=e<0?i:e>i?0:e;return s[n].disabled?f(n,t<0?-1:1,s):n}function I(r,t,s,e){const i=e.split(`\n`);let n=0,o=r;for(const a of i){if(o<=a.length)break;o-=a.length+1,n++}for(n=Math.max(0,Math.min(i.length-1,n+s)),o=Math.min(o,i[n].length)+t;o<0&&n>0;)n--,o+=i[n].length+1;for(;o>i[n].length&&n<i.length-1;)o-=i[n].length+1,n++;o=Math.max(0,Math.min(i[n].length,o));let u=0;for(let a=0;a<n;a++)u+=i[a].length+1;return u+o}const G=[\"up\",\"down\",\"left\",\"right\",\"space\",\"enter\",\"cancel\"],K=[\"January\",\"February\",\"March\",\"April\",\"May\",\"June\",\"July\",\"August\",\"September\",\"October\",\"November\",\"December\"],h={actions:new Set(G),aliases:new Map([[\"k\",\"up\"],[\"j\",\"down\"],[\"h\",\"left\"],[\"l\",\"right\"],[\"\u0003\",\"cancel\"],[\"escape\",\"cancel\"]]),messages:{cancel:\"Canceled\",error:\"Something went wrong\"},withGuide:!0,date:{monthNames:[...K],messages:{required:\"Please enter a valid date\",invalidMonth:\"There are only 12 months in a year\",invalidDay:(r,t)=>`There are only ${r} days in ${t}`,afterMin:r=>`Date must be on or after ${r.toISOString().slice(0,10)}`,beforeMax:r=>`Date must be on or before ${r.toISOString().slice(0,10)}`}}};function j(r){if(r.aliases!==void 0){const t=r.aliases;for(const s in t){if(!Object.hasOwn(t,s))continue;const e=t[s];h.actions.has(e)&&(h.aliases.has(s)||h.aliases.set(s,e))}}if(r.messages!==void 0){const t=r.messages;t.cancel!==void 0&&(h.messages.cancel=t.cancel),t.error!==void 0&&(h.messages.error=t.error)}if(r.withGuide!==void 0&&(h.withGuide=r.withGuide!==!1),r.date!==void 0){const t=r.date;t.monthNames!==void 0&&(h.date.monthNames=[...t.monthNames]),t.messages!==void 0&&(t.messages.required!==void 0&&(h.date.messages.required=t.messages.required),t.messages.invalidMonth!==void 0&&(h.date.messages.invalidMonth=t.messages.invalidMonth),t.messages.invalidDay!==void 0&&(h.date.messages.invalidDay=t.messages.invalidDay),t.messages.afterMin!==void 0&&(h.date.messages.afterMin=t.messages.afterMin),t.messages.beforeMax!==void 0&&(h.date.messages.beforeMax=t.messages.beforeMax))}}function C(r,t){if(typeof r==\"string\")return h.aliases.get(r)===t;for(const s of r)if(s!==void 0&&C(s,t))return!0;return!1}function z(r,t){if(r===t)return;const s=r.split(`\n`),e=t.split(`\n`),i=Math.max(s.length,e.length),n=[];for(let o=0;o<i;o++)s[o]!==e[o]&&n.push(o);return{lines:n,numLinesBefore:s.length,numLinesAfter:e.length,numLines:i}}const Y=globalThis.process.platform.startsWith(\"win\"),k=Symbol(\"clack:cancel\");function q(r){return r===k}function w(r,t){const s=r;s.isTTY&&s.setRawMode(t)}function R({input:r=D,output:t=x,overwrite:s=!0,hideCursor:e=!0}={}){const i=b.createInterface({input:r,output:t,prompt:\"\",tabSize:1});b.emitKeypressEvents(r,i),r instanceof O&&r.isTTY&&r.setRawMode(!0);const n=(o,{name:u,sequence:a})=>{const l=String(o);if(C([l,u,a],\"cancel\")){e&&t.write(p.show),process.exit(0);return}if(!s)return;const c=u===\"return\"?0:-1,y=u===\"return\"?-1:0;b.moveCursor(t,c,y,()=>{b.clearLine(t,1,()=>{r.once(\"keypress\",n)})})};return e&&t.write(p.hide),r.once(\"keypress\",n),()=>{r.off(\"keypress\",n),e&&t.write(p.show),r instanceof O&&r.isTTY&&!Y&&r.setRawMode(!1),i.terminal=!1,i.close()}}const A=r=>\"columns\"in r&&typeof r.columns==\"number\"?r.columns:80,L=r=>\"rows\"in r&&typeof r.rows==\"number\"?r.rows:20;function W(r,t,s,e=s,i=s,n){const o=A(r??x);return M(t,o-s.length,{hard:!0,trim:!1}).split(`\n`).map((u,a,l)=>{const c=n?n(u,a):u;return a===0?`${e}${c}`:a===l.length-1?`${i}${c}`:`${s}${c}`}).join(`\n`)}let m=class{input;output;_abortSignal;rl;opts;_render;_track=!1;_prevFrame=\"\";_subscribers=new Map;_cursor=0;state=\"initial\";error=\"\";value;userInput=\"\";constructor(t,s=!0){const{input:e=D,output:i=x,render:n,signal:o,...u}=t;this.opts=u,this.onKeypress=this.onKeypress.bind(this),this.close=this.close.bind(this),this.render=this.render.bind(this),this._render=n.bind(this),this._track=s,this._abortSignal=o,this.input=e,this.output=i}unsubscribe(){this._subscribers.clear()}setSubscriber(t,s){const e=this._subscribers.get(t)??[];e.push(s),this._subscribers.set(t,e)}on(t,s){this.setSubscriber(t,{cb:s})}once(t,s){this.setSubscriber(t,{cb:s,once:!0})}emit(t,...s){const e=this._subscribers.get(t)??[],i=[];for(const n of e)n.cb(...s),n.once&&i.push(()=>e.splice(e.indexOf(n),1));for(const n of i)n()}prompt(){return new Promise(t=>{if(this._abortSignal){if(this._abortSignal.aborted)return this.state=\"cancel\",this.close(),t(k);this._abortSignal.addEventListener(\"abort\",()=>{this.state=\"cancel\",this.close()},{once:!0})}this.rl=E.createInterface({input:this.input,tabSize:2,prompt:\"\",escapeCodeTimeout:50,terminal:!0}),this.rl.prompt(),this.opts.initialUserInput!==void 0&&this._setUserInput(this.opts.initialUserInput,!0),this.input.on(\"keypress\",this.onKeypress),w(this.input,!0),this.output.on(\"resize\",this.render),this.render(),this.once(\"submit\",()=>{this.output.write(p.show),this.output.off(\"resize\",this.render),w(this.input,!1),t(this.value)}),this.once(\"cancel\",()=>{this.output.write(p.show),this.output.off(\"resize\",this.render),w(this.input,!1),t(k)})})}_isActionKey(t,s){return t===\"\t\"}_shouldSubmit(t,s){return!0}_setValue(t){this.value=t,this.emit(\"value\",this.value)}_setUserInput(t,s){this.userInput=t??\"\",this.emit(\"userInput\",this.userInput),s&&this._track&&this.rl&&(this.rl.write(this.userInput),this._cursor=this.rl.cursor)}_clearUserInput(){this.rl?.write(null,{ctrl:!0,name:\"u\"}),this._setUserInput(\"\")}onKeypress(t,s){if(this._track&&s.name!==\"return\"&&(s.name&&this._isActionKey(t,s)&&this.rl?.write(null,{ctrl:!0,name:\"h\"}),this._cursor=this.rl?.cursor??0,this._setUserInput(this.rl?.line)),this.state===\"error\"&&(this.state=\"active\"),s?.name&&(!this._track&&h.aliases.has(s.name)&&this.emit(\"cursor\",h.aliases.get(s.name)),h.actions.has(s.name)&&this.emit(\"cursor\",s.name)),t&&(t.toLowerCase()===\"y\"||t.toLowerCase()===\"n\")&&this.emit(\"confirm\",t.toLowerCase()===\"y\"),this.emit(\"key\",t?.toLowerCase(),s),s?.name===\"return\"&&this._shouldSubmit(t,s)){if(this.opts.validate){const e=this.opts.validate(this.value);e&&(this.error=e instanceof Error?e.message:e,this.state=\"error\",this.rl?.write(this.userInput))}this.state!==\"error\"&&(this.state=\"submit\")}C([t,s?.name,s?.sequence],\"cancel\")&&(this.state=\"cancel\"),(this.state===\"submit\"||this.state===\"cancel\")&&this.emit(\"finalize\"),this.render(),(this.state===\"submit\"||this.state===\"cancel\")&&this.close()}close(){this.input.unpipe(),this.input.removeListener(\"keypress\",this.onKeypress),this.output.write(`\n`),w(this.input,!1),this.rl?.close(),this.rl=void 0,this.emit(`${this.state}`,this.value),this.unsubscribe()}restoreCursor(){const t=M(this._prevFrame,process.stdout.columns,{hard:!0,trim:!1}).split(`\n`).length-1;this.output.write(p.move(-999,t*-1))}render(){const t=M(this._render(this)??\"\",process.stdout.columns,{hard:!0,trim:!1});if(t!==this._prevFrame){if(this.state===\"initial\")this.output.write(p.hide);else{const s=z(this._prevFrame,t),e=L(this.output);if(this.restoreCursor(),s){const i=Math.max(0,s.numLinesAfter-e),n=Math.max(0,s.numLinesBefore-e);let o=s.lines.find(u=>u>=i);if(o===void 0){this._prevFrame=t;return}if(s.lines.length===1){this.output.write(p.move(0,o-n)),this.output.write(V.lines(1));const u=t.split(`\n`);this.output.write(u[o]),this._prevFrame=t,this.output.write(p.move(0,u.length-o-1));return}else if(s.lines.length>1){if(i<n)o=i;else{const a=o-n;a>0&&this.output.write(p.move(0,a))}this.output.write(V.down());const u=t.split(`\n`).slice(o);this.output.write(u.join(`\n`)),this._prevFrame=t;return}}this.output.write(V.down())}this.output.write(t),this.state===\"initial\"&&(this.state=\"active\"),this._prevFrame=t}}};function B(r,t){if(r===void 0||t.length===0)return 0;const s=t.findIndex(e=>e.value===r);return s!==-1?s:0}function J(r,t){return(t.label??String(t.value)).toLowerCase().includes(r.toLowerCase())}function H(r,t){if(t)return r?t:t[0]}let Q=class extends m{filteredOptions;multiple;isNavigating=!1;selectedValues=[];focusedValue;#s=0;#r=\"\";#t;#n;#u;get cursor(){return this.#s}get userInputWithCursor(){if(!this.userInput)return v([\"inverse\",\"hidden\"],\"_\");if(this._cursor>=this.userInput.length)return`${this.userInput}\\u2588`;const t=this.userInput.slice(0,this._cursor),[s,...e]=this.userInput.slice(this._cursor);return`${t}${v(\"inverse\",s)}${e.join(\"\")}`}get options(){return typeof this.#n==\"function\"?this.#n():this.#n}constructor(t){super(t),this.#n=t.options,this.#u=t.placeholder;const s=this.options;this.filteredOptions=[...s],this.multiple=t.multiple===!0,this.#t=typeof t.options==\"function\"?t.filter:t.filter??J;let e;if(t.initialValue&&Array.isArray(t.initialValue)?this.multiple?e=t.initialValue:e=t.initialValue.slice(0,1):!this.multiple&&this.options.length>0&&(e=[this.options[0].value]),e)for(const i of e){const n=s.findIndex(o=>o.value===i);n!==-1&&(this.toggleSelected(i),this.#s=n)}this.focusedValue=this.options[this.#s]?.value,this.on(\"key\",(i,n)=>this.#e(i,n)),this.on(\"userInput\",i=>this.#i(i))}_isActionKey(t,s){return t===\"\t\"||this.multiple&&this.isNavigating&&s.name===\"space\"&&t!==void 0&&t!==\"\"}#e(t,s){const e=s.name===\"up\",i=s.name===\"down\",n=s.name===\"return\",o=this.userInput===\"\"||this.userInput===\"\t\",u=this.#u,a=this.options,l=u!==void 0&&u!==\"\"&&a.some(c=>!c.disabled&&(this.#t?this.#t(u,c):!0));if(s.name===\"tab\"&&o&&l){this.userInput===\"\t\"&&this._clearUserInput(),this._setUserInput(u,!0),this.isNavigating=!1;return}e||i?(this.#s=f(this.#s,e?-1:1,this.filteredOptions),this.focusedValue=this.filteredOptions[this.#s]?.value,this.multiple||(this.selectedValues=[this.focusedValue]),this.isNavigating=!0):n?this.value=H(this.multiple,this.selectedValues):this.multiple?this.focusedValue!==void 0&&(s.name===\"tab\"||this.isNavigating&&s.name===\"space\")?this.toggleSelected(this.focusedValue):this.isNavigating=!1:(this.focusedValue&&(this.selectedValues=[this.focusedValue]),this.isNavigating=!1)}deselectAll(){this.selectedValues=[]}toggleSelected(t){this.filteredOptions.length!==0&&(this.multiple?this.selectedValues.includes(t)?this.selectedValues=this.selectedValues.filter(s=>s!==t):this.selectedValues=[...this.selectedValues,t]:this.selectedValues=[t])}#i(t){if(t!==this.#r){this.#r=t;const s=this.options;t&&this.#t?this.filteredOptions=s.filter(n=>this.#t?.(t,n)):this.filteredOptions=[...s];const e=B(this.focusedValue,this.filteredOptions);this.#s=f(e,0,this.filteredOptions);const i=this.filteredOptions[this.#s];i&&!i.disabled?this.focusedValue=i.value:this.focusedValue=void 0,this.multiple||(this.focusedValue!==void 0?this.toggleSelected(this.focusedValue):this.deselectAll())}}};class X extends m{get cursor(){return this.value?0:1}get _value(){return this.cursor===0}constructor(t){super(t,!1),this.value=!!t.initialValue,this.on(\"userInput\",()=>{this.value=this._value}),this.on(\"confirm\",s=>{this.output.write(p.move(0,-1)),this.value=s,this.state=\"submit\",this.close()}),this.on(\"cursor\",()=>{this.value=!this.value})}}const Z={Y:{type:\"year\",len:4},M:{type:\"month\",len:2},D:{type:\"day\",len:2}};function P(r){return[...r].map(t=>Z[t])}function tt(r){const t=new Intl.DateTimeFormat(r,{year:\"numeric\",month:\"2-digit\",day:\"2-digit\"}).formatToParts(new Date(2e3,0,15)),s=[];let e=\"/\";for(const i of t)i.type===\"literal\"?e=i.value.trim()||i.value:(i.type===\"year\"||i.type===\"month\"||i.type===\"day\")&&s.push({type:i.type,len:i.type===\"year\"?4:2});return{segments:s,separator:e}}function $(r){return Number.parseInt((r||\"0\").replace(/_/g,\"0\"),10)||0}function S(r){return{year:$(r.year),month:$(r.month),day:$(r.day)}}function U(r,t){return new Date(r||2001,t||1,0).getDate()}function F(r){const{year:t,month:s,day:e}=S(r);if(!t||t<0||t>9999||!s||s<1||s>12||!e||e<1)return;const i=new Date(Date.UTC(t,s-1,e));if(!(i.getUTCFullYear()!==t||i.getUTCMonth()!==s-1||i.getUTCDate()!==e))return{year:t,month:s,day:e}}function N(r){const t=F(r);return t?new Date(Date.UTC(t.year,t.month-1,t.day)):void 0}function st(r,t,s,e){const i=s?{year:s.getUTCFullYear(),month:s.getUTCMonth()+1,day:s.getUTCDate()}:null,n=e?{year:e.getUTCFullYear(),month:e.getUTCMonth()+1,day:e.getUTCDate()}:null;return r===\"year\"?{min:i?.year??1,max:n?.year??9999}:r===\"month\"?{min:i&&t.year===i.year?i.month:1,max:n&&t.year===n.year?n.month:12}:{min:i&&t.year===i.year&&t.month===i.month?i.day:1,max:n&&t.year===n.year&&t.month===n.month?n.day:U(t.year,t.month)}}class et extends m{#s;#r;#t;#n;#u;#e={segmentIndex:0,positionInSegment:0};#i=!0;#o=null;inlineError=\"\";get segmentCursor(){return{...this.#e}}get segmentValues(){return{...this.#t}}get segments(){return this.#s}get separator(){return this.#r}get formattedValue(){return this.#c(this.#t)}#c(t){return this.#s.map(s=>t[s.type]).join(this.#r)}#a(){this._setUserInput(this.#c(this.#t)),this._setValue(N(this.#t)??void 0)}constructor(t){const s=t.format?{segments:P(t.format),separator:t.separator??\"/\"}:tt(t.locale),e=t.separator??s.separator,i=t.format?P(t.format):s.segments,n=t.initialValue??t.defaultValue,o=n?{year:String(n.getUTCFullYear()).padStart(4,\"0\"),month:String(n.getUTCMonth()+1).padStart(2,\"0\"),day:String(n.getUTCDate()).padStart(2,\"0\")}:{year:\"____\",month:\"__\",day:\"__\"},u=i.map(a=>o[a.type]).join(e);super({...t,initialUserInput:u},!1),this.#s=i,this.#r=e,this.#t=o,this.#n=t.minDate,this.#u=t.maxDate,this.#a(),this.on(\"cursor\",a=>this.#d(a)),this.on(\"key\",(a,l)=>this.#f(a,l)),this.on(\"finalize\",()=>this.#g(t))}#h(){const t=Math.max(0,Math.min(this.#e.segmentIndex,this.#s.length-1)),s=this.#s[t];if(s)return this.#e.positionInSegment=Math.max(0,Math.min(this.#e.positionInSegment,s.len-1)),{segment:s,index:t}}#l(t){this.inlineError=\"\",this.#o=null;const s=this.#h();s&&(this.#e.segmentIndex=Math.max(0,Math.min(this.#s.length-1,s.index+t)),this.#e.positionInSegment=0,this.#i=!0)}#p(t){const s=this.#h();if(!s)return;const{segment:e}=s,i=this.#t[e.type],n=!i||i.replace(/_/g,\"\")===\"\",o=Number.parseInt((i||\"0\").replace(/_/g,\"0\"),10)||0,u=st(e.type,S(this.#t),this.#n,this.#u);let a;n?a=t===1?u.min:u.max:a=Math.max(Math.min(u.max,o+t),u.min),this.#t={...this.#t,[e.type]:a.toString().padStart(e.len,\"0\")},this.#i=!0,this.#o=null,this.#a()}#d(t){if(t)switch(t){case\"right\":return this.#l(1);case\"left\":return this.#l(-1);case\"up\":return this.#p(1);case\"down\":return this.#p(-1)}}#f(t,s){if(s?.name===\"backspace\"||s?.sequence===\"\\x7F\"||s?.sequence===\"\\b\"||t===\"\\x7F\"||t===\"\\b\"){this.inlineError=\"\";const e=this.#h();if(!e)return;if(!this.#t[e.segment.type].replace(/_/g,\"\")){this.#l(-1);return}this.#t[e.segment.type]=\"_\".repeat(e.segment.len),this.#i=!0,this.#e.positionInSegment=0,this.#a();return}if(s?.name===\"tab\"){this.inlineError=\"\";const e=this.#h();if(!e)return;const i=s.shift?-1:1,n=e.index+i;n>=0&&n<this.#s.length&&(this.#e.segmentIndex=n,this.#e.positionInSegment=0,this.#i=!0);return}if(t&&/^[0-9]$/.test(t)){const e=this.#h();if(!e)return;const{segment:i}=e,n=!this.#t[i.type].replace(/_/g,\"\");if(this.#i&&this.#o!==null&&!n){const d=this.#o+t,g={...this.#t,[i.type]:d},_=this.#m(g,i);if(_){this.inlineError=_,this.#o=null,this.#i=!1;return}this.inlineError=\"\",this.#t[i.type]=d,this.#o=null,this.#i=!1,this.#a(),e.index<this.#s.length-1&&(this.#e.segmentIndex=e.index+1,this.#e.positionInSegment=0,this.#i=!0);return}this.#i&&!n&&(this.#t[i.type]=\"_\".repeat(i.len),this.#e.positionInSegment=0),this.#i=!1,this.#o=null;const o=this.#t[i.type],u=o.indexOf(\"_\"),a=u>=0?u:Math.min(this.#e.positionInSegment,i.len-1);if(a<0||a>=i.len)return;let l=o.slice(0,a)+t+o.slice(a+1),c=!1;if(a===0&&o===\"__\"&&(i.type===\"month\"||i.type===\"day\")){const d=Number.parseInt(t,10);l=`0${t}`,c=d<=(i.type===\"month\"?1:2)}if(i.type===\"year\"&&(l=(o.replace(/_/g,\"\")+t).padStart(i.len,\"_\")),!l.includes(\"_\")){const d={...this.#t,[i.type]:l},g=this.#m(d,i);if(g){this.inlineError=g;return}}this.inlineError=\"\",this.#t[i.type]=l;const y=l.includes(\"_\")?void 0:F(this.#t);if(y){const{year:d,month:g}=y,_=U(d,g);this.#t={year:String(Math.max(0,Math.min(9999,d))).padStart(4,\"0\"),month:String(Math.max(1,Math.min(12,g))).padStart(2,\"0\"),day:String(Math.max(1,Math.min(_,y.day))).padStart(2,\"0\")}}this.#a();const T=l.indexOf(\"_\");c?(this.#i=!0,this.#o=t):T>=0?this.#e.positionInSegment=T:u>=0&&e.index<this.#s.length-1?(this.#e.segmentIndex=e.index+1,this.#e.positionInSegment=0,this.#i=!0):this.#e.positionInSegment=Math.min(a+1,i.len-1)}}#m(t,s){const{month:e,day:i}=S(t);if(s.type===\"month\"&&(e<0||e>12))return h.date.messages.invalidMonth;if(s.type===\"day\"&&(i<0||i>31))return h.date.messages.invalidDay(31,\"any month\")}#g(t){const{year:s,month:e,day:i}=S(this.#t);if(s&&e&&i){const n=U(s,e);this.#t={...this.#t,day:String(Math.min(i,n)).padStart(2,\"0\")}}this.value=N(this.#t)??t.defaultValue??void 0}}class it extends m{options;cursor=0;#s;getGroupItems(t){return this.options.filter(s=>s.group===t)}isGroupSelected(t){const s=this.getGroupItems(t),e=this.value;return e===void 0?!1:s.every(i=>e.includes(i.value))}toggleValue(){const t=this.options[this.cursor];if(this.value===void 0&&(this.value=[]),t.group===!0){const s=t.value,e=this.getGroupItems(s);this.isGroupSelected(s)?this.value=this.value.filter(i=>e.findIndex(n=>n.value===i)===-1):this.value=[...this.value,...e.map(i=>i.value)],this.value=Array.from(new Set(this.value))}else{const s=this.value.includes(t.value);this.value=s?this.value.filter(e=>e!==t.value):[...this.value,t.value]}}constructor(t){super(t,!1);const{options:s}=t;this.#s=t.selectableGroups!==!1,this.options=Object.entries(s).flatMap(([e,i])=>[{value:e,group:!0,label:e},...i.map(n=>({...n,group:e}))]),this.value=[...t.initialValues??[]],this.cursor=Math.max(this.options.findIndex(({value:e})=>e===t.cursorAt),this.#s?0:1),this.on(\"cursor\",e=>{switch(e){case\"left\":case\"up\":{this.cursor=this.cursor===0?this.options.length-1:this.cursor-1;const i=this.options[this.cursor]?.group===!0;!this.#s&&i&&(this.cursor=this.cursor===0?this.options.length-1:this.cursor-1);break}case\"down\":case\"right\":{this.cursor=this.cursor===this.options.length-1?0:this.cursor+1;const i=this.options[this.cursor]?.group===!0;!this.#s&&i&&(this.cursor=this.cursor===this.options.length-1?0:this.cursor+1);break}case\"space\":this.toggleValue();break}})}}class rt extends m{#s=!1;#r;focused=\"editor\";get userInputWithCursor(){if(this.state===\"submit\")return this.userInput;const t=this.userInput;if(this.cursor>=t.length)return`${t}\\u2588`;const s=t.slice(0,this.cursor),e=t[this.cursor],i=t.slice(this.cursor+1);return e===`\n`?`${s}\\u2588\n${i}`:`${s}${v(\"inverse\",e)}${i}`}get cursor(){return this._cursor}#t(t){if(this.userInput.length===0){this._setUserInput(t);return}this._setUserInput(this.userInput.slice(0,this.cursor)+t+this.userInput.slice(this.cursor))}#n(t){const s=this.value??\"\";switch(t){case\"up\":this._cursor=I(this._cursor,0,-1,s);return;case\"down\":this._cursor=I(this._cursor,0,1,s);return;case\"left\":this._cursor=I(this._cursor,-1,0,s);return;case\"right\":this._cursor=I(this._cursor,1,0,s);return}}_shouldSubmit(t,s){if(this.#r)return this.focused===\"submit\"?!0:(this.#t(`\n`),this._cursor++,!1);const e=this.#s;return this.#s=!0,e?(this.userInput[this.cursor-1]===`\n`&&(this._setUserInput(this.userInput.slice(0,this.cursor-1)+this.userInput.slice(this.cursor)),this._cursor--),!0):(this.#t(`\n`),this._cursor++,!1)}constructor(t){super(t,!1),this.#r=t.showSubmit??!1,this.on(\"key\",(s,e)=>{if(e?.name&&h.actions.has(e.name)){this.#n(e.name);return}if(s===\"\t\"&&this.#r){this.focused=this.focused===\"editor\"?\"submit\":\"editor\";return}if(e?.name!==\"return\"){if(this.#s=!1,e?.name===\"backspace\"&&this.cursor>0){this._setUserInput(this.userInput.slice(0,this.cursor-1)+this.userInput.slice(this.cursor)),this._cursor--;return}if(e?.name===\"delete\"&&this.cursor<this.userInput.length){this._setUserInput(this.userInput.slice(0,this.cursor)+this.userInput.slice(this.cursor+1));return}s&&(this.#r&&this.focused===\"submit\"&&(this.focused=\"editor\"),this.#t(s??\"\"),this._cursor++)}}),this.on(\"userInput\",s=>{this._setValue(s)}),this.on(\"finalize\",()=>{this.value||(this.value=t.defaultValue),this.value===void 0&&(this.value=\"\")})}}let nt=class extends m{options;cursor=0;get _value(){return this.options[this.cursor].value}get _enabledOptions(){return this.options.filter(t=>t.disabled!==!0)}toggleAll(){const t=this._enabledOptions,s=this.value!==void 0&&this.value.length===t.length;this.value=s?[]:t.map(e=>e.value)}toggleInvert(){const t=this.value;if(!t)return;const s=this._enabledOptions.filter(e=>!t.includes(e.value));this.value=s.map(e=>e.value)}toggleValue(){this.value===void 0&&(this.value=[]);const t=this.value.includes(this._value);this.value=t?this.value.filter(s=>s!==this._value):[...this.value,this._value]}constructor(t){super(t,!1),this.options=t.options,this.value=[...t.initialValues??[]];const s=Math.max(this.options.findIndex(({value:e})=>e===t.cursorAt),0);this.cursor=this.options[s].disabled?f(s,1,this.options):s,this.on(\"key\",e=>{e===\"a\"&&this.toggleAll(),e===\"i\"&&this.toggleInvert()}),this.on(\"cursor\",e=>{switch(e){case\"left\":case\"up\":this.cursor=f(this.cursor,-1,this.options);break;case\"down\":case\"right\":this.cursor=f(this.cursor,1,this.options);break;case\"space\":this.toggleValue();break}})}};class ot extends m{_mask=\"\\u2022\";get cursor(){return this._cursor}get masked(){return this.userInput.replaceAll(/./g,this._mask)}get userInputWithCursor(){if(this.state===\"submit\"||this.state===\"cancel\")return this.masked;const t=this.userInput;if(this.cursor>=t.length)return`${this.masked}${v([\"inverse\",\"hidden\"],\"_\")}`;const s=this.masked,e=s.slice(0,this.cursor),i=s.slice(this.cursor);return`${e}${v(\"inverse\",i[0])}${i.slice(1)}`}clear(){this._clearUserInput()}constructor({mask:t,...s}){super(s),this._mask=t??\"\\u2022\",this.on(\"userInput\",e=>{this._setValue(e)})}}class ut extends m{options;cursor=0;get _selectedValue(){return this.options[this.cursor]}changeValue(){this.value=this._selectedValue.value}constructor(t){super(t,!1),this.options=t.options;const s=this.options.findIndex(({value:i})=>i===t.initialValue),e=s===-1?0:s;this.cursor=this.options[e].disabled?f(e,1,this.options):e,this.changeValue(),this.on(\"cursor\",i=>{switch(i){case\"left\":case\"up\":this.cursor=f(this.cursor,-1,this.options);break;case\"down\":case\"right\":this.cursor=f(this.cursor,1,this.options);break}this.changeValue()})}}class at extends m{options;cursor=0;constructor(t){super(t,!1),this.options=t.options;const s=t.caseSensitive===!0,e=this.options.map(({value:[i]})=>s?i:i?.toLowerCase());this.cursor=Math.max(e.indexOf(t.initialValue),0),this.on(\"key\",(i,n)=>{if(!i)return;const o=s&&n.shift?i.toUpperCase():i;if(!e.includes(o))return;const u=this.options.find(({value:[a]})=>s?a===o:a?.toLowerCase()===i);u&&(this.value=u.value,this.state=\"submit\",this.emit(\"submit\"))})}}class ht extends m{get userInputWithCursor(){if(this.state===\"submit\")return this.userInput;const t=this.userInput;if(this.cursor>=t.length)return`${this.userInput}\\u2588`;const s=t.slice(0,this.cursor),[e,...i]=t.slice(this.cursor);return`${s}${v(\"inverse\",e)}${i.join(\"\")}`}get cursor(){return this._cursor}constructor(t){super({...t,initialUserInput:t.initialUserInput??t.initialValue}),this.on(\"userInput\",s=>{this._setValue(s)}),this.on(\"finalize\",()=>{this.value||(this.value=t.defaultValue),this.value===void 0&&(this.value=\"\")})}}export{Q as AutocompletePrompt,X as ConfirmPrompt,et as DatePrompt,it as GroupMultiSelectPrompt,rt as MultiLinePrompt,nt as MultiSelectPrompt,ot as PasswordPrompt,m as Prompt,at as SelectKeyPrompt,ut as SelectPrompt,ht as TextPrompt,R as block,A as getColumns,L as getRows,q as isCancel,h as settings,j as updateSettings,W as wrapTextWithPrefix};\n//# sourceMappingURL=index.mjs.map\n","import type { Readable, Writable } from \"node:stream\"\nimport { styleText } from \"node:util\"\nimport { isCancel as isClackCancel, SelectPrompt } from \"@clack/core\"\nimport {\n\tlimitOptions,\n\tS_BAR,\n\tS_BAR_END,\n\tS_RADIO_ACTIVE,\n\tS_RADIO_INACTIVE,\n\tsymbol,\n} from \"@clack/prompts\"\nimport { dim, green } from \"kolorist\"\nimport { debug } from \"../utils/debug.js\"\n\nexport interface AutoAcceptOption<T> {\n\tvalue: T\n\tlabel?: string\n\thint?: string\n\tdisabled?: boolean\n}\n\nexport interface AutoAcceptSelectOptions<T> {\n\tmessage: string\n\toptions: Array<AutoAcceptOption<T>>\n\tinitialAutoAccept: boolean\n\t/** Fired whenever the user toggles auto-accept via the `a` hotkey. */\n\tonToggle?: (next: boolean) => void | Promise<void>\n\tinput?: Readable\n\toutput?: Writable\n}\n\nexport interface AutoAcceptResult<T> {\n\tvalue: T\n\tautoAccept: boolean\n}\n\nconst ON_LABEL = styleText(\"green\", \"ON\")\nconst OFF_LABEL = styleText(\"dim\", \"OFF\")\nconst HOTKEY_HINT = dim(\"(press `a` to toggle)\")\n\nfunction renderStatus(autoAccept: boolean): string {\n\tconst label = autoAccept ? ON_LABEL : OFF_LABEL\n\treturn `${dim(\"⚡ Auto-accept:\")} ${label} ${HOTKEY_HINT}`\n}\n\n/** Render a single select option line. */\nfunction renderOption<T>(opt: AutoAcceptOption<T>, active: boolean): string {\n\tconst text = opt.label ?? String(opt.value)\n\tif (opt.disabled) {\n\t\treturn `${dim(S_RADIO_INACTIVE)} ${styleText([\"strikethrough\", \"dim\"], text)}`\n\t}\n\tif (active) {\n\t\tconst hint = opt.hint ? ` ${dim(`(${opt.hint})`)}` : \"\"\n\t\treturn `${green(S_RADIO_ACTIVE)} ${text}${hint}`\n\t}\n\treturn `${dim(S_RADIO_INACTIVE)} ${dim(text)}`\n}\n\n/**\n * Select prompt with an inline `a`-hotkey toggle for auto-accept mode.\n *\n * Renders a normal select list plus a status line showing the current\n * auto-accept state. Pressing `a` flips the state in-place (the menu\n * re-renders) and fires `onToggle` so callers can persist the change.\n *\n * Returns `{ value, autoAccept }` on submit, or the clack cancel symbol\n * on cancel.\n */\nexport async function selectWithAutoAccept<T>(\n\topts: AutoAcceptSelectOptions<T>,\n): Promise<AutoAcceptResult<T> | symbol> {\n\tlet autoAccept = opts.initialAutoAccept\n\n\tconst prompt = new SelectPrompt({\n\t\toptions: opts.options,\n\t\tinput: opts.input,\n\t\toutput: opts.output,\n\t\trender() {\n\t\t\tconst sym = symbol(this.state)\n\t\t\tconst statusLine = renderStatus(autoAccept)\n\t\t\tconst header = `${sym} ${opts.message}\\n${dim(S_BAR)} ${statusLine}`\n\n\t\t\tswitch (this.state) {\n\t\t\t\tcase \"submit\": {\n\t\t\t\t\tconst selected = this.options[this.cursor]\n\t\t\t\t\tconst text = selected.label ?? String(selected.value)\n\t\t\t\t\treturn `${header}\\n${dim(S_BAR)} ${dim(text)}`\n\t\t\t\t}\n\t\t\t\tcase \"cancel\": {\n\t\t\t\t\tconst selected = this.options[this.cursor]\n\t\t\t\t\tconst text = selected.label ?? String(selected.value)\n\t\t\t\t\treturn `${header}\\n${dim(S_BAR)} ${styleText([\"strikethrough\", \"dim\"], text)}\\n${dim(S_BAR_END)}`\n\t\t\t\t}\n\t\t\t\tdefault: {\n\t\t\t\t\tconst visible = limitOptions({\n\t\t\t\t\t\tcursor: this.cursor,\n\t\t\t\t\t\toptions: this.options,\n\t\t\t\t\t\tstyle: (opt: AutoAcceptOption<T>, active: boolean) => renderOption(opt, active),\n\t\t\t\t\t\tmaxItems: 7,\n\t\t\t\t\t\toutput: opts.output ?? process.stdout,\n\t\t\t\t\t})\n\t\t\t\t\tconst lines = visible.map((line: string) => `${dim(S_BAR)} ${line}`)\n\t\t\t\t\treturn [\n\t\t\t\t\t\theader,\n\t\t\t\t\t\t...lines,\n\t\t\t\t\t\t`${dim(S_BAR_END)} ${dim(\"↑/↓ navigate • Enter confirm • `a` toggle auto-accept\")}`,\n\t\t\t\t\t].join(\"\\n\")\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t})\n\n\tprompt.on(\"key\", async (char: string | undefined) => {\n\t\tif (char === \"a\") {\n\t\t\tautoAccept = !autoAccept\n\t\t\tdebug(\"auto-accept toggled to %s\", autoAccept)\n\t\t\ttry {\n\t\t\t\tawait opts.onToggle?.(autoAccept)\n\t\t\t} catch (err) {\n\t\t\t\tdebug(\"onToggle threw (ignored): %s\", err instanceof Error ? err.message : String(err))\n\t\t\t}\n\t\t}\n\t})\n\n\tconst result = await prompt.prompt()\n\n\tif (isClackCancel(result)) {\n\t\treturn result\n\t}\n\n\treturn { value: result as T, autoAccept }\n}\n\n/** Convenience guard for callers. */\nexport function isAutoAcceptCancel<_T>(value: unknown): value is symbol {\n\treturn isClackCancel(value)\n}\n","import * as p from \"@clack/prompts\"\nimport { bold, cyan, dim, green, red, yellow } from \"kolorist\"\nimport { getAutoAccept, setAutoAccept } from \"../services/auto-accept.js\"\nimport type { ChangedFile } from \"../services/git.js\"\nimport { debug } from \"../utils/debug.js\"\nimport { selectWithAutoAccept } from \"./auto-accept-select.js\"\n\nexport interface StagingChoice {\n\tfiles: string[] // selected file paths to stage\n\tall: boolean // whether user chose \"Stage all\"\n}\n\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Staging menu with conditional options + multiselect fallback\n// biome-ignore lint/complexity/noExcessiveLinesPerFunction: Staging menu with file list display + multiselect fallback\nexport async function showStagingMenu(\n\tfiles: ChangedFile[],\n\thasChecks: boolean,\n): Promise<StagingChoice | \"autogroup\" | \"checks\" | \"staged\" | null> {\n\tdebug(\"showStagingMenu: %d files\", files.length)\n\n\t// Build status labels with kolorist colors\n\tconst statusLabel = (status: string): string => {\n\t\tswitch (status) {\n\t\t\tcase \"M\":\n\t\t\t\treturn yellow(\"M\")\n\t\t\tcase \"A\":\n\t\t\t\treturn green(\"A\")\n\t\t\tcase \"D\":\n\t\t\t\treturn red(\"D\")\n\t\t\tcase \"?\":\n\t\t\tcase \"??\":\n\t\t\t\treturn cyan(\"?\")\n\t\t\tdefault:\n\t\t\t\treturn dim(status)\n\t\t}\n\t}\n\n\t// Sort: staged files first, then unstaged\n\tconst sorted = [...files].sort((a, b) => {\n\t\tif (a.staged !== b.staged) return a.staged ? -1 : 1\n\t\treturn a.path.localeCompare(b.path)\n\t})\n\n\t// Show file list grouped by staged status\n\tconst stagedFiles = sorted.filter((f) => f.staged)\n\tconst unstagedFiles = sorted.filter((f) => !f.staged)\n\tconst lines: string[] = []\n\tif (stagedFiles.length > 0) {\n\t\tlines.push(\n\t\t\tgreen(bold(\"Staged:\")),\n\t\t\t...stagedFiles.map((f) => ` ${statusLabel(f.status)} ${f.path}`),\n\t\t)\n\t}\n\tif (unstagedFiles.length > 0) {\n\t\tif (lines.length > 0) lines.push(\"\")\n\t\tlines.push(\n\t\t\tyellow(bold(\"Changed:\")),\n\t\t\t...unstagedFiles.map((f) => ` ${statusLabel(f.status)} ${f.path}`),\n\t\t)\n\t}\n\tp.note(lines.join(\"\\n\"), `${files.length} file${files.length !== 1 ? \"s\" : \"\"}`)\n\n\tconst initialAutoAccept = await getAutoAccept()\n\tdebug(\"showStagingMenu: initial auto-accept=%s\", initialAutoAccept)\n\n\tconst selectResult = await selectWithAutoAccept<\n\t\t\"autogroup\" | \"all\" | \"checks\" | \"staged\" | \"select\" | \"cancel\"\n\t>({\n\t\tmessage: \"Stage files for commit:\",\n\t\tinitialAutoAccept,\n\t\tonToggle: async (next) => {\n\t\t\tawait setAutoAccept(next)\n\t\t},\n\t\toptions: [\n\t\t\t{\n\t\t\t\tlabel: \"Auto-group into commits\",\n\t\t\t\tvalue: \"autogroup\",\n\t\t\t\thint: \"LLM groups files into logical commits\",\n\t\t\t},\n\t\t\t...(stagedFiles.length > 0\n\t\t\t\t? [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlabel: \"Commit staged files only\",\n\t\t\t\t\t\t\tvalue: \"staged\" as const,\n\t\t\t\t\t\t\thint: `${stagedFiles.length} file${stagedFiles.length !== 1 ? \"s\" : \"\"} already staged`,\n\t\t\t\t\t\t},\n\t\t\t\t\t]\n\t\t\t\t: []),\n\t\t\t{\n\t\t\t\tlabel: \"Stage all files\",\n\t\t\t\tvalue: \"all\",\n\t\t\t\thint: `${files.length} file${files.length !== 1 ? \"s\" : \"\"}`,\n\t\t\t},\n\t\t\t...(hasChecks\n\t\t\t\t? [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlabel: \"Run checks\",\n\t\t\t\t\t\t\tvalue: \"checks\" as const,\n\t\t\t\t\t\t\thint: \"Pre-flight checks from cmint config\",\n\t\t\t\t\t\t},\n\t\t\t\t\t]\n\t\t\t\t: []),\n\t\t\t{ label: \"Select files...\", value: \"select\" },\n\t\t\t{ label: \"Cancel\", value: \"cancel\" },\n\t\t],\n\t})\n\n\tif (typeof selectResult === \"symbol\") {\n\t\tdebug(\"showStagingMenu: user cancelled (clack cancel symbol)\")\n\t\treturn null\n\t}\n\n\tconst choice = selectResult.value\n\tdebug(\"showStagingMenu: choice=%s autoAccept=%s\", choice, selectResult.autoAccept)\n\n\tif (p.isCancel(choice) || choice === \"cancel\") {\n\t\treturn null\n\t}\n\n\tif (choice === \"autogroup\") {\n\t\treturn \"autogroup\"\n\t}\n\n\tif (choice === \"checks\") {\n\t\treturn \"checks\"\n\t}\n\n\tif (choice === \"staged\") {\n\t\treturn \"staged\"\n\t}\n\n\tif (choice === \"all\") {\n\t\treturn { files: files.map((f) => f.path), all: true }\n\t}\n\n\t// Multi-select\n\tconst selected = await p.multiselect({\n\t\tmessage: \"Select files to stage:\",\n\t\toptions: sorted.map((f) => ({\n\t\t\tlabel: `${statusLabel(f.status)} ${f.path}`,\n\t\t\tvalue: f.path,\n\t\t})),\n\t\trequired: true,\n\t})\n\n\tif (p.isCancel(selected)) {\n\t\treturn null\n\t}\n\n\treturn { files: selected as string[], all: false }\n}\n","import { log, outro, spinner } from \"@clack/prompts\"\nimport { dim, red } from \"kolorist\"\nimport { detectConfig, runAllChecks } from \"../services/checks.js\"\nimport {\n\tgetChangedFiles,\n\tgetRepoRoot,\n\tgetStagedFiles,\n\tstageAll,\n\tstageFiles,\n} from \"../services/git.js\"\nimport { stopCheckSpinner } from \"../ui/check-summary.js\"\nimport { showStagingMenu } from \"../ui/staging-menu.js\"\nimport { debug } from \"../utils/debug.js\"\nimport { type CommitFlags, runAutoGroupFlow } from \"./auto-group.js\"\nimport { runCheckPhaseInteractive } from \"./check-phase.js\"\n\n/** Interactive staging loop for multiple changed files */\n// biome-ignore lint/complexity/noExcessiveLinesPerFunction: Interactive staging loop with conditional branches\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Multi-branch TUI with autogroup, checks, staging options\nexport async function handleStaging(\n\tchangedFiles: Awaited<ReturnType<typeof getChangedFiles>>,\n\tflags: CommitFlags,\n): Promise<{\n\tchangedFiles: Awaited<ReturnType<typeof getChangedFiles>>\n\tskipStaging: boolean\n} | null> {\n\tconst repoRoot = await getRepoRoot()\n\tconst checksAvailable = (await detectConfig(repoRoot)) !== null\n\tdebug(\"checks available:\", checksAvailable)\n\n\tlet stagingResult: Awaited<ReturnType<typeof showStagingMenu>> = null\n\tlet filesToStage: string[] = []\n\tlet stageAllFlag = false\n\tlet skipStaging = false\n\tlet currentFiles = changedFiles\n\n\twhile (true) {\n\t\tstagingResult = await showStagingMenu(currentFiles, checksAvailable)\n\n\t\tif (stagingResult === \"autogroup\") {\n\t\t\tif (flags.message) {\n\t\t\t\toutro(red(\"--message flag is not compatible with auto-group mode.\"))\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst agResult = await runAutoGroupFlow(currentFiles, flags)\n\t\t\tif (agResult !== \"committed\") {\n\t\t\t\tprocess.exit(1)\n\t\t\t}\n\t\t\treturn null\n\t\t}\n\n\t\tif (stagingResult === \"checks\") {\n\t\t\tawait stageAll()\n\t\t\t// Repo-root-relative paths line up with .cmintrc globs (lint-staged convention).\n\t\t\tconst allFiles = await getStagedFiles()\n\t\t\tconst configPath = await detectConfig(repoRoot)\n\t\t\tif (configPath) {\n\t\t\t\tconst ckSpinner = spinner()\n\t\t\t\tckSpinner.start(\"Running checks...\")\n\t\t\t\tconst ckResult = await runAllChecks(repoRoot, allFiles, 60000)\n\t\t\t\tstopCheckSpinner(ckSpinner, ckResult)\n\t\t\t\tif (!ckResult.ok) {\n\t\t\t\t\tfor (const r of ckResult.results.filter((r) => !r.ok))\n\t\t\t\t\t\tlog.info(r.stderr?.trim() || r.stdout?.trim() || `Check failed: ${r.command}`)\n\t\t\t\t}\n\t\t\t}\n\t\t\tcurrentFiles = await getChangedFiles()\n\t\t\tcontinue\n\t\t}\n\n\t\tif (stagingResult === \"staged\") {\n\t\t\tskipStaging = true\n\t\t\tbreak\n\t\t}\n\n\t\tif (!stagingResult) {\n\t\t\toutro(dim(\"Cancelled.\"))\n\t\t\treturn null\n\t\t}\n\n\t\tfilesToStage = stagingResult.files\n\t\tstageAllFlag = stagingResult.all\n\t\tbreak\n\t}\n\n\tif (!skipStaging) {\n\t\tconst s = spinner()\n\t\ts.start(`Staging ${filesToStage.length} file${filesToStage.length !== 1 ? \"s\" : \"\"}...`)\n\t\tif (stageAllFlag) {\n\t\t\tawait stageAll()\n\t\t} else {\n\t\t\tawait stageFiles(filesToStage)\n\t\t}\n\t\ts.stop(\"Files staged\")\n\t}\n\n\treturn { changedFiles: currentFiles, skipStaging }\n}\n\n/** Run user-defined pre-commit checks from cmint config */\nexport async function runPreCommitChecks(\n\tchangedFiles: Awaited<ReturnType<typeof getChangedFiles>>,\n\tnoCheck?: boolean,\n): Promise<void> {\n\tif (noCheck) return\n\tconst checkRoot = await getRepoRoot()\n\t// Repo-root-relative paths line up with .cmintrc globs (which are written\n\t// from the repo root, matching lint-staged conventions). `getChangedFiles()`\n\t// returns cwd-relative paths, which silently fail to match globs when cmint\n\t// is run from a subdirectory.\n\tconst stagedFileList = await getStagedFiles()\n\tif (stagedFileList.length === 0) return\n\n\t// Delegate the check pipeline (detectConfig → spinner → runAllChecks →\n\t// retry loop with failure menu) to the shared check-phase module. On retry,\n\t// re-stage files so fixes made in another terminal between the original run\n\t// and the retry land in the index before checks re-run.\n\tconst outcome = await runCheckPhaseInteractive(checkRoot, stagedFileList, 60000, async () => {\n\t\tdebug(\"Re-staging files before retry...\")\n\t\tawait stageAll()\n\t})\n\tif (outcome === \"cancelled\") {\n\t\tprocess.exit(1)\n\t}\n\n\t// Formatters (prettier --write, eslint --fix, etc.) modify files on disk during checks.\n\t// Re-stage those modifications so getStagedDiff() captures the formatted content —\n\t// otherwise the commit lands with pre-format content and the changes dangle in the WT.\n\t// Use cwd-relative paths here: restageFormatterModifications compares against\n\t// getChangedFiles() (also cwd-relative) and writes via stageFiles() (git add from cwd).\n\tconst cwdRelativeStaged = changedFiles\n\t\t.filter((f) => f.staged && f.status !== \"D\")\n\t\t.map((f) => f.path)\n\tawait restageFormatterModifications(cwdRelativeStaged)\n}\n\n/**\n * Re-stage staged files whose working-tree content diverged from the index after checks ran.\n * Signals (git status --short, 2-char XY code):\n * \"MM\" — tracked file staged-modified, then reformatted on disk\n * \"AM\" — newly-added file staged, then reformatted on disk\n */\nasync function restageFormatterModifications(stagedFileList: string[]): Promise<void> {\n\tconst checkedSet = new Set(stagedFileList)\n\tconst postCheckFiles = await getChangedFiles()\n\tconst modifiedByChecks = postCheckFiles\n\t\t.filter((f) => checkedSet.has(f.path) && f.staged && (f.status === \"MM\" || f.status === \"AM\"))\n\t\t.map((f) => f.path)\n\tif (modifiedByChecks.length === 0) return\n\tdebug(\"Re-staging %d file(s) modified by checks\", modifiedByChecks.length)\n\tawait stageFiles(modifiedByChecks)\n\tlog.info(\n\t\t`Re-staged ${modifiedByChecks.length} file${modifiedByChecks.length !== 1 ? \"s\" : \"\"} modified by checks`,\n\t)\n}\n","import { intro, isCancel, log, outro, spinner } from \"@clack/prompts\"\nimport { dim, green, red } from \"kolorist\"\nimport { getAutoAccept } from \"../services/auto-accept.js\"\nimport { getProviderApiKey, readConfig, setConfigValue } from \"../services/config.js\"\nimport {\n\tassertGitRepo,\n\tgetChangedFiles,\n\tgetHead,\n\tgetRepoRoot,\n\tgetStagedDiff,\n\tgetStatusShort,\n\tstageFiles,\n} from \"../services/git.js\"\nimport {\n\tformatProviderName,\n\tisValidProvider,\n\tPROVIDER_ENV_KEYS,\n\ttype ProviderName,\n} from \"../services/provider.js\"\nimport { checkForUpdatesUpfront } from \"../services/update-check.js\"\nimport { reviewCommitMessage } from \"../ui/review-message.js\"\nimport { saveCachedCommit } from \"../utils/cache.js\"\nimport { debug } from \"../utils/debug.js\"\nimport {\n\tbuildExcludedFilesMessage,\n\ttype CommitFlags,\n\tgenerateMessage,\n\trunAutoGroupFlow,\n} from \"./auto-group.js\"\nimport { commitWithRecovery } from \"./commit-utils.js\"\nimport { handleRetry } from \"./retry.js\"\nimport { runPreflightSetupPrompt } from \"./setup.js\"\nimport { handleStaging, runPreCommitChecks } from \"./staging.js\"\n\n// biome-ignore lint/complexity/noExcessiveLinesPerFunction: Sequential CLI lifecycle orchestrator\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Multi-branch state machine (retry/normal, staging, review, recovery)\nexport async function commitCommand(flags: CommitFlags, version: string) {\n\tdebug(\"commitCommand called\", { flags })\n\tawait assertGitRepo()\n\n\t// ── Retry mode ──────────────────────────────────────────────────\n\tif (flags.retry) {\n\t\treturn handleRetry()\n\t}\n\n\t// ── Preflight: nudge the user to set up .cmintrc if it's missing ─\n\tconst repoRoot = await getRepoRoot()\n\tawait runPreflightSetupPrompt(repoRoot)\n\n\t// ── Normal mode ─────────────────────────────────────────────────\n\tintro(\"🌿 commit-mint\")\n\n\t// ── Update check (after header, silent on cache hit) ────────────\n\tawait checkForUpdatesUpfront(version)\n\n\tconst status = await getStatusShort()\n\tdebug(\"Git status:\", status || \"(empty)\")\n\tif (!status) {\n\t\toutro(dim(\"Nothing to commit.\"))\n\t\treturn\n\t}\n\n\t// Stage changes\n\tlet changedFiles = await getChangedFiles()\n\tdebug(\"Changed files:\", changedFiles.length)\n\tconst s = spinner()\n\n\ttry {\n\t\tif (flags.auto) {\n\t\t\tif (flags.message) {\n\t\t\t\toutro(red(\"--message flag is not compatible with auto-group mode.\"))\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst agResult = await runAutoGroupFlow(changedFiles, flags)\n\t\t\tif (agResult !== \"committed\") {\n\t\t\t\tprocess.exit(1)\n\t\t\t}\n\t\t\treturn\n\t\t} else if (changedFiles.length === 1) {\n\t\t\ts.start(`Staging ${changedFiles[0].path}...`)\n\t\t\tawait stageFiles([changedFiles[0].path])\n\t\t\ts.stop(\"File staged\")\n\t\t} else {\n\t\t\tconst result = await handleStaging(changedFiles, flags)\n\t\t\tif (!result) return\n\t\t\tchangedFiles = result.changedFiles\n\t\t}\n\t} catch (err) {\n\t\ts.stop(red(\"Staging failed.\"))\n\t\tconst msg = err instanceof Error ? err.message : String(err)\n\t\tdebug(\"Staging error:\", msg)\n\t\toutro(red(`Failed to stage files: ${msg}`))\n\t\tprocess.exit(1)\n\t}\n\n\t// Refresh file list after staging so staged state is accurate\n\tchangedFiles = await getChangedFiles()\n\n\t// Run user-defined pre-commit checks (before AI message generation)\n\tawait runPreCommitChecks(changedFiles, flags.noCheck)\n\n\t// Get diff for AI\n\tconst diffResult = await getStagedDiff()\n\tif (!diffResult) {\n\t\tdebug(\"No staged changes found after staging\")\n\t\toutro(red(\"No staged changes found.\"))\n\t\tprocess.exit(1)\n\t}\n\n\t// Handle all-staged-files-are-excluded case with hardcoded message\n\tif (\"excludedFiles\" in diffResult) {\n\t\tdebug(\"All staged files are excluded:\", diffResult.excludedFiles)\n\t\tconst message = buildExcludedFilesMessage(diffResult.excludedFiles)\n\n\t\tlog.info(diffResult.excludedFiles.map((f) => ` ${f}`).join(\"\\n\"))\n\n\t\tawait saveCachedCommit(repoRoot, message)\n\n\t\ts.start(\"Running pre-commit hooks...\")\n\t\tconst headBefore = await getHead()\n\t\tconst result = await commitWithRecovery(message, s, headBefore)\n\t\tif (result === \"committed\") {\n\t\t\toutro(green(\"Done.\"))\n\t\t\treturn\n\t\t}\n\t\tif (result === \"cancelled\") {\n\t\t\tprocess.exit(1)\n\t\t}\n\t\treturn\n\t}\n\n\tdebug(\"Staged files:\", diffResult.files)\n\tdebug(\"Diff length:\", diffResult.diff.length, \"chars\")\n\n\tlog.info(diffResult.files.map((f) => ` ${f}`).join(\"\\n\"))\n\n\t// Generate or use provided message\n\tlet message: string\n\n\tif (flags.message) {\n\t\tdebug(\"Using provided message:\", flags.message)\n\t\tmessage = flags.message\n\t} else {\n\t\tconst config = await readConfig()\n\t\tconst provider: ProviderName = isValidProvider(config.provider ?? \"groq\")\n\t\t\t? (config.provider as ProviderName)\n\t\t\t: \"groq\"\n\t\ttry {\n\t\t\tawait getProviderApiKey(provider)\n\t\t\tdebug(\"API key found\")\n\t\t} catch {\n\t\t\tdebug(\"No API key found, prompting user\")\n\t\t\tconst { text: promptText } = await import(\"@clack/prompts\")\n\t\t\tconst configKey = PROVIDER_ENV_KEYS[provider]\n\t\t\tconst key = await promptText({\n\t\t\t\tmessage: `Enter your ${formatProviderName(provider)} API key:`,\n\t\t\t\tplaceholder: provider === \"groq\" ? \"gsk_...\" : \"...\",\n\t\t\t\tvalidate: (v) => (v?.trim() ? undefined : \"API key is required\"),\n\t\t\t})\n\t\t\tif (isCancel(key)) {\n\t\t\t\toutro(dim(\"Cancelled.\"))\n\t\t\t\treturn\n\t\t\t}\n\t\t\tawait setConfigValue(configKey, String(key).trim())\n\t\t\tdebug(\"API key saved to config\")\n\t\t}\n\n\t\ts.start(\"Generating commit message...\")\n\t\ttry {\n\t\t\tconst genStart = Date.now()\n\t\t\tmessage = await generateMessage(diffResult.diff, flags.hint)\n\t\t\tdebug(\"generateMessage took %d ms\", Date.now() - genStart)\n\t\t\tdebug(\"Generated message:\", message)\n\t\t} catch (err) {\n\t\t\ts.stop(red(\"Failed to generate message.\"))\n\t\t\tdebug(\"Message generation failed:\", err instanceof Error ? err.message : String(err))\n\t\t\toutro(red(err instanceof Error ? err.message : String(err)))\n\t\t\treturn\n\t\t}\n\t\ts.stop(\"Message generated\")\n\t}\n\n\t// Review message (with optional code review) — skipped when auto-accept is ON\n\tconst autoAccept = await getAutoAccept()\n\tif (autoAccept) {\n\t\tdebug(\"Auto-accept ON: skipping review step\")\n\t\tlog.info(message)\n\t} else {\n\t\tconst reviewed = await reviewCommitMessage(message, {\n\t\t\tregenerate: async (hint) => {\n\t\t\t\tconst combinedHint = flags.hint ? `${flags.hint}\\n${hint}` : hint\n\t\t\t\tdebug(\"Regenerating with combined hint:\", combinedHint)\n\t\t\t\ts.start(\"Regenerating commit message...\")\n\t\t\t\ttry {\n\t\t\t\t\tconst newMessage = await generateMessage(diffResult.diff, combinedHint)\n\t\t\t\t\ts.stop(\"Message regenerated\")\n\t\t\t\t\treturn newMessage\n\t\t\t\t} catch (err) {\n\t\t\t\t\ts.stop(red(\"Regeneration failed\"))\n\t\t\t\t\tthrow err\n\t\t\t\t}\n\t\t\t},\n\t\t})\n\t\tif (reviewed === null) {\n\t\t\toutro(dim(\"Cancelled.\"))\n\t\t\treturn\n\t\t}\n\t\tmessage = reviewed\n\t}\n\n\t// Cache message before attempting commit\n\tawait saveCachedCommit(repoRoot, message)\n\tdebug(\"Message cached for repo:\", repoRoot)\n\n\t// Attempt commit\n\ts.start(\"Running pre-commit hooks...\")\n\tconst headBefore = await getHead()\n\tdebug(\"HEAD before commit:\", headBefore)\n\tconst result = await commitWithRecovery(message, s, headBefore)\n\tdebug(\"Commit result:\", result)\n\n\tif (result === \"committed\") {\n\t\toutro(green(\"Done.\"))\n\t\treturn\n\t}\n\tif (result === \"cancelled\") {\n\t\tprocess.exit(1)\n\t}\n}\n","import * as p from \"@clack/prompts\"\nimport { bold, dim, green } from \"kolorist\"\nimport { getModelForProvider, readConfig, writeConfig } from \"../services/config.js\"\nimport {\n\tformatProviderName,\n\tisValidProvider,\n\tPROVIDER_CONFIGS,\n\tPROVIDER_ENV_KEYS,\n\ttype ProviderName,\n} from \"../services/provider.js\"\nimport { debug } from \"../utils/debug.js\"\nimport { setupCmintrcCommand } from \"./setup.js\"\n\nfunction maskKey(key: string | undefined): string {\n\tif (!key) return dim(\"not set\")\n\tif (key.length <= 8) return \"****\"\n\treturn `${key.slice(0, 4)}${\"*\".repeat(Math.min(key.length - 8, 20))}${key.slice(-4)}`\n}\n\nfunction buildConfigDisplay(config: Record<string, string | undefined>): string {\n\tconst provider: ProviderName = isValidProvider(config.provider ?? \"groq\")\n\t\t? (config.provider as ProviderName)\n\t\t: \"groq\"\n\tconst keyName = PROVIDER_ENV_KEYS[provider]\n\tconst apiKey = config[keyName]\n\tconst effectiveModel = getModelForProvider(\n\t\tconfig as import(\"../services/config.js\").Config,\n\t\tprovider,\n\t\tPROVIDER_CONFIGS[provider].defaultModel,\n\t)\n\n\tconst lines = [\n\t\t`Provider: ${bold(formatProviderName(provider))}`,\n\t\t`API Key: ${maskKey(apiKey)}`,\n\t\t`Model: ${effectiveModel}`,\n\t\t`Locale: ${config.locale ?? \"en\"}`,\n\t\t`Max Length: ${config[\"max-length\"] ?? \"100\"}`,\n\t\t`Commit Type: ${config.type || dim(\"(none)\")}`,\n\t\t`Timeout: ${config.timeout ?? \"10000\"}ms`,\n\t\t`Proxy: ${config.proxy || dim(\"(none)\")}`,\n\t]\n\n\treturn lines.join(\"\\n\")\n}\n\nfunction getProvider(config: Record<string, string | undefined>): ProviderName {\n\treturn isValidProvider(config.provider ?? \"groq\") ? (config.provider as ProviderName) : \"groq\"\n}\n\nasync function promptProvider(): Promise<string | symbol> {\n\treturn p.select({\n\t\tmessage: \"Select LLM provider:\",\n\t\toptions: [\n\t\t\t{ label: \"Groq\", value: \"groq\", hint: PROVIDER_CONFIGS.groq.defaultModel },\n\t\t\t{ label: \"Cerebras\", value: \"cerebras\", hint: PROVIDER_CONFIGS.cerebras.defaultModel },\n\t\t\t{ label: \"Mistral\", value: \"mistral\", hint: PROVIDER_CONFIGS.mistral.defaultModel },\n\t\t],\n\t})\n}\n\nasync function promptApiKey(provider: ProviderName): Promise<string | symbol> {\n\tconst keyName = PROVIDER_ENV_KEYS[provider]\n\tconst result = await p.text({\n\t\tmessage: `${formatProviderName(provider)} API key:`,\n\t\tplaceholder: \"Paste your API key\",\n\t\tvalidate: (v) => (!v?.trim() ? \"API key cannot be empty\" : undefined),\n\t})\n\tif (p.isCancel(result)) return result\n\tawait writeConfig({ [keyName]: result.toString().trim() })\n\tdebug(\"config: %s set\", keyName)\n\treturn result\n}\n\nasync function promptTextSetting(\n\tlabel: string,\n\tconfigKey: string,\n\tcurrentValue: string | undefined,\n\tvalidate?: (v: string | undefined) => string | undefined,\n): Promise<string | symbol> {\n\tconst result = await p.text({\n\t\tmessage: label,\n\t\tplaceholder: currentValue ?? \"\",\n\t\tinitialValue: currentValue ?? \"\",\n\t\tvalidate,\n\t})\n\tif (p.isCancel(result)) return result\n\tawait writeConfig({ [configKey]: result.toString().trim() })\n\tdebug(\"config: %s set to %s\", configKey, result)\n\treturn result\n}\n\nconst requireNumber = (v: string | undefined) => {\n\tif (!v?.trim()) return \"Value cannot be empty\"\n\treturn Number.isNaN(Number(v)) ? \"Must be a number\" : undefined\n}\n\ntype SettingHandler = () => Promise<string | symbol | undefined>\n\nfunction getSettingHandlers(\n\tconfig: Record<string, string | undefined>,\n): Record<string, SettingHandler> {\n\tconst provider = getProvider(config)\n\treturn {\n\t\tprovider: async () => {\n\t\t\tconst result = await promptProvider()\n\t\t\tif (p.isCancel(result)) return result\n\t\t\tconst newProvider = result as ProviderName\n\t\t\tconst newDefaultModel = PROVIDER_CONFIGS[newProvider].defaultModel\n\t\t\tawait writeConfig({ provider: newProvider, model: newDefaultModel })\n\t\t\tdebug(\"config: provider set to %s, model set to %s\", newProvider, newDefaultModel)\n\n\t\t\t// Prompt for API key if not set for the new provider\n\t\t\tconst keyName = PROVIDER_ENV_KEYS[newProvider]\n\t\t\tconst updatedConfig = (await readConfig()) as Record<string, string | undefined>\n\t\t\tif (!updatedConfig[keyName]) {\n\t\t\t\tconst keyResult = await promptApiKey(newProvider)\n\t\t\t\tif (p.isCancel(keyResult)) return keyResult\n\t\t\t}\n\t\t},\n\t\tapikey: async () => promptApiKey(provider),\n\t\tmodel: async () => {\n\t\t\tconst effectiveModel = getModelForProvider(\n\t\t\t\tconfig as import(\"../services/config.js\").Config,\n\t\t\t\tprovider,\n\t\t\t\tPROVIDER_CONFIGS[provider].defaultModel,\n\t\t\t)\n\t\t\treturn promptTextSetting(\"Model ID:\", \"model\", effectiveModel)\n\t\t},\n\t\tlocale: async () => promptTextSetting(\"Locale (e.g. en, ja, ko):\", \"locale\", config.locale),\n\t\tmaxlen: async () =>\n\t\t\tpromptTextSetting(\n\t\t\t\t\"Max commit message length:\",\n\t\t\t\t\"max-length\",\n\t\t\t\tconfig[\"max-length\"],\n\t\t\t\trequireNumber,\n\t\t\t),\n\t\ttype: async () =>\n\t\t\tpromptTextSetting(\"Commit type prefix (e.g. conventional):\", \"type\", config.type),\n\t\ttimeout: async () =>\n\t\t\tpromptTextSetting(\"Timeout (ms):\", \"timeout\", config.timeout, requireNumber),\n\t\tproxy: async () => promptTextSetting(\"Proxy URL:\", \"proxy\", config.proxy),\n\t}\n}\n\nasync function handleEditSetting(\n\tsetting: string,\n\tconfig: Record<string, string | undefined>,\n): Promise<boolean> {\n\tconst handlers = getSettingHandlers(config)\n\tconst handler = handlers[setting]\n\tif (!handler) return false\n\tconst result = await handler()\n\treturn !p.isCancel(result)\n}\n\nasync function editSettingsLoop(initialConfig: Record<string, string | undefined>): Promise<void> {\n\tlet config = initialConfig\n\n\twhile (true) {\n\t\t// Re-read config to reflect changes from previous edits\n\t\tconfig = (await readConfig()) as Record<string, string | undefined>\n\t\tconst provider = getProvider(config)\n\t\tconst effectiveModel = getModelForProvider(\n\t\t\tconfig as import(\"../services/config.js\").Config,\n\t\t\tprovider,\n\t\t\tPROVIDER_CONFIGS[provider].defaultModel,\n\t\t)\n\n\t\tconst setting = await p.select({\n\t\t\tmessage: \"Select a setting to edit:\",\n\t\t\toptions: [\n\t\t\t\t{\n\t\t\t\t\tlabel: `LLM Provider ${dim(`(${formatProviderName(provider)})`)}`,\n\t\t\t\t\tvalue: \"provider\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: `API Key ${dim(`(for ${formatProviderName(provider)})`)}`,\n\t\t\t\t\tvalue: \"apikey\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: `Model ${dim(`(${effectiveModel})`)}`,\n\t\t\t\t\tvalue: \"model\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: `Locale ${dim(`(${config.locale ?? \"en\"})`)}`,\n\t\t\t\t\tvalue: \"locale\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: `Max commit length ${dim(`(${config[\"max-length\"] ?? \"100\"})`)}`,\n\t\t\t\t\tvalue: \"maxlen\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: `Commit type prefix ${dim(`(${config.type || \"(none)\"})`)}`,\n\t\t\t\t\tvalue: \"type\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: `Timeout (ms) ${dim(`(${config.timeout ?? \"10000\"})`)}`,\n\t\t\t\t\tvalue: \"timeout\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: `Proxy URL ${dim(`(${config.proxy || \"(none)\"})`)}`,\n\t\t\t\t\tvalue: \"proxy\",\n\t\t\t\t},\n\t\t\t\t{ label: \"Done editing\", value: \"done\" },\n\t\t\t],\n\t\t})\n\n\t\tif (p.isCancel(setting) || setting === \"done\") break\n\n\t\tconst updated = await handleEditSetting(setting as string, config)\n\t\tif (updated) {\n\t\t\tp.log.success(green(\"Updated.\"))\n\t\t}\n\t}\n}\n\nexport async function configCommand(): Promise<void> {\n\tdebug(\"configCommand: starting\")\n\tp.intro(bold(\"🌿 commit-mint config\"))\n\n\twhile (true) {\n\t\tconst config = (await readConfig()) as Record<string, string | undefined>\n\n\t\tp.note(buildConfigDisplay(config), \"commit-mint config\")\n\n\t\tconst action = await p.select({\n\t\t\tmessage: \"What would you like to do?\",\n\t\t\toptions: [\n\t\t\t\t{ label: \"Edit settings\", value: \"edit\" },\n\t\t\t\t{ label: \"Setup .cmintrc\", value: \"setup\" },\n\t\t\t\t{ label: \"Done\", value: \"done\" },\n\t\t\t],\n\t\t})\n\n\t\tif (p.isCancel(action)) {\n\t\t\tdebug(\"configCommand: cancelled at main menu\")\n\t\t\tp.outro(dim(\"Cancelled.\"))\n\t\t\treturn\n\t\t}\n\n\t\tif (action === \"done\") {\n\t\t\tdebug(\"configCommand: done\")\n\t\t\tp.outro(\"Config saved.\")\n\t\t\treturn\n\t\t}\n\n\t\tif (action === \"setup\") {\n\t\t\tdebug(\"configCommand: starting .cmintrc setup\")\n\t\t\tawait setupCmintrcCommand()\n\t\t\tcontinue\n\t\t}\n\n\t\tawait editSettingsLoop(config)\n\t}\n}\n","import { readFile } from \"node:fs/promises\"\nimport os from \"node:os\"\nimport { join } from \"node:path\"\n\nconst LOG_PATH = join(os.homedir(), \".cache\", \"commit-mint\", \"debug.log\")\nconst SESSION_SEPARATOR = /^--- session .+ ---$/\n\nexport async function logsCommand(flags: { lines?: number }): Promise<void> {\n\tlet content: string\n\ttry {\n\t\tcontent = await readFile(LOG_PATH, \"utf8\")\n\t} catch (err) {\n\t\tif ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n\t\t\tconsole.error(\"No debug logs found. Run cmint with any command first.\")\n\t\t\tprocess.exit(1)\n\t\t}\n\t\tthrow err\n\t}\n\n\tif (content.trim() === \"\") {\n\t\tconsole.error(\"No debug logs found. Run cmint with any command first.\")\n\t\tprocess.exit(1)\n\t}\n\n\tconst allLines = content.split(\"\\n\")\n\tlet lastSessionIndex = -1\n\tfor (let i = allLines.length - 1; i >= 0; i--) {\n\t\tif (SESSION_SEPARATOR.test(allLines[i])) {\n\t\t\tlastSessionIndex = i\n\t\t\tbreak\n\t\t}\n\t}\n\n\tconst sessionLines = lastSessionIndex === -1 ? allLines : allLines.slice(lastSessionIndex + 1)\n\tconst filtered = sessionLines.filter(\n\t\t(line) => line.length > 0 || sessionLines.indexOf(line) === 0,\n\t)\n\n\tif (filtered.length === 0) {\n\t\tconsole.error(\"No debug logs found. Run cmint with any command first.\")\n\t\tprocess.exit(1)\n\t}\n\n\tconst lines =\n\t\tflags.lines !== undefined && flags.lines > 0 ? filtered.slice(-flags.lines) : filtered\n\n\tfor (const line of lines) {\n\t\tconsole.log(line)\n\t}\n}\n","import { execa } from \"execa\"\nimport semver from \"semver\"\nimport { debug } from \"../utils/debug.js\"\n\nexport type PackageManager = \"npm\" | \"pnpm\" | \"yarn\" | \"bun\"\n\nexport const PACKAGE_NAME = \"@kyubiware/commit-mint\"\n\n/**\n * Detect the active package manager from the `npm_config_user_agent` env var.\n * Format: \"<pm>/<version> <...>\" — e.g. \"npm/10.2.0 node/v20.10.0\".\n * Empty/undefined input and unrecognized prefixes fall back to \"npm\".\n */\nexport function detectPackageManager(userAgent: string | undefined): PackageManager {\n\tif (!userAgent) {\n\t\tdebug(\"updater: empty userAgent, defaulting to npm\")\n\t\treturn \"npm\"\n\t}\n\tconst prefix = userAgent.split(\"/\")[0]\n\tswitch (prefix) {\n\t\tcase \"pnpm\":\n\t\t\treturn \"pnpm\"\n\t\tcase \"yarn\":\n\t\t\treturn \"yarn\"\n\t\tcase \"bun\":\n\t\t\treturn \"bun\"\n\t\tcase \"npm\":\n\t\t\treturn \"npm\"\n\t\tdefault:\n\t\t\tdebug(\"updater: unknown userAgent prefix '%s', defaulting to npm\", prefix)\n\t\t\treturn \"npm\"\n\t}\n}\n\n/**\n * Build the global install shell command for the given package manager.\n * Returned as a single string suitable for `execa(cmd, [], { shell: true })`.\n */\nexport function buildUpdateCommand(pm: PackageManager, packageName: string = PACKAGE_NAME): string {\n\tswitch (pm) {\n\t\tcase \"npm\":\n\t\t\treturn `npm install -g ${packageName}@latest`\n\t\tcase \"pnpm\":\n\t\t\treturn `pnpm add -g ${packageName}@latest`\n\t\tcase \"yarn\":\n\t\t\treturn `yarn global add ${packageName}@latest`\n\t\tcase \"bun\":\n\t\t\treturn `bun add -g ${packageName}@latest`\n\t}\n}\n\n/**\n * Fetch the latest version from the npm registry via `npm view <pkg> version`.\n * Returns the trimmed version string on success, or null on any failure\n * (non-zero exit, empty stdout, thrown error). Never throws.\n */\nexport async function fetchLatestVersion(\n\tpackageName: string = PACKAGE_NAME,\n): Promise<string | null> {\n\tdebug(\"updater: fetching latest version for %s\", packageName)\n\ttry {\n\t\tconst result = await execa(\"npm\", [\"view\", packageName, \"version\"], { reject: false })\n\t\tif (result.exitCode !== 0) {\n\t\t\tdebug(\"updater: npm view exited %d\", result.exitCode)\n\t\t\treturn null\n\t\t}\n\t\tconst trimmed = result.stdout.trim()\n\t\tif (!trimmed) {\n\t\t\tdebug(\"updater: npm view returned empty stdout\")\n\t\t\treturn null\n\t\t}\n\t\tdebug(\"updater: latest=%s\", trimmed)\n\t\treturn trimmed\n\t} catch (err) {\n\t\tdebug(\n\t\t\t\"updater: fetchLatestVersion error — %s\",\n\t\t\terr instanceof Error ? err.message : String(err),\n\t\t)\n\t\treturn null\n\t}\n}\n\n/**\n * True iff `latest` is strictly greater than `current` per semver. Returns\n * false on invalid semver input rather than throwing.\n */\nexport function isUpdateAvailable(current: string, latest: string): boolean {\n\ttry {\n\t\treturn semver.gt(latest, current)\n\t} catch (err) {\n\t\tdebug(\"updater: isUpdateAvailable error — %s\", err instanceof Error ? err.message : String(err))\n\t\treturn false\n\t}\n}\n\n/**\n * Run the global install command for the given package manager. Streams\n * the installer's live output to the user's terminal via `stdio: \"inherit\"`.\n * Returns true iff the install exits with code 0.\n */\nexport async function runUpdate(\n\tpm: PackageManager,\n\tpackageName: string = PACKAGE_NAME,\n): Promise<boolean> {\n\tconst command = buildUpdateCommand(pm, packageName)\n\tdebug(\"updater: running %s\", command)\n\ttry {\n\t\tconst result = await execa(command, [], {\n\t\t\tshell: true,\n\t\t\treject: false,\n\t\t\tstdio: \"inherit\",\n\t\t})\n\t\treturn result.exitCode === 0\n\t} catch (err) {\n\t\tdebug(\"updater: runUpdate error — %s\", err instanceof Error ? err.message : String(err))\n\t\treturn false\n\t}\n}\n","import * as p from \"@clack/prompts\"\nimport { cyan, dim, green, red } from \"kolorist\"\nimport {\n\tbuildUpdateCommand,\n\tdetectPackageManager,\n\tfetchLatestVersion,\n\tisUpdateAvailable,\n\trunUpdate,\n} from \"../services/updater.js\"\n\nexport interface UpdateFlags {\n\tyes?: boolean\n}\n\n/**\n * Self-update flow for the installed `cmint` package. Detects the active\n * package manager from `npm_config_user_agent`, asks the npm registry for the\n * latest published version, and — if newer — runs the equivalent global\n * install command after a confirmation prompt (skippable with `--yes`).\n *\n * Never throws. Registry failures and install failures are reported through\n * `p.outro(...)` and `process.exit(1)`; cancellation and \"already current\"\n * resolve normally so the CLI exits cleanly.\n */\nexport async function updateCommand(currentVersion: string, flags?: UpdateFlags): Promise<void> {\n\tp.intro(\"cmint update\")\n\n\tconst pm = detectPackageManager(process.env.npm_config_user_agent)\n\tp.log.info(`Package manager: ${pm}`)\n\n\tp.log.message(\"Checking latest version...\")\n\tconst latest = await fetchLatestVersion()\n\n\tif (latest === null) {\n\t\tp.outro(red(\"Could not reach the npm registry. Check your connection and try again.\"))\n\t\tprocess.exit(1)\n\t\treturn\n\t}\n\n\tif (!isUpdateAvailable(currentVersion, latest)) {\n\t\tp.outro(`Already up-to-date: v${currentVersion}`)\n\t\treturn\n\t}\n\n\tp.log.step(`${dim(currentVersion)} → ${green(latest)}`)\n\n\tconst cmd = buildUpdateCommand(pm)\n\n\tif (flags?.yes !== true) {\n\t\tconst confirmed = await p.confirm({ message: `Run \\`${cmd}\\`?`, initialValue: true })\n\t\tif (p.isCancel(confirmed) || !confirmed) {\n\t\t\tp.outro(\"Update cancelled.\")\n\t\t\treturn\n\t\t}\n\t}\n\n\tp.log.message(`Running ${cyan(cmd)}...`)\n\tconst ok = await runUpdate(pm)\n\n\tif (ok) {\n\t\tp.outro(green(`Updated to v${latest}`))\n\t\treturn\n\t}\n\n\tp.outro(red(\"Update failed. See output above.\"))\n\tprocess.exit(1)\n}\n","#!/usr/bin/env node\nimport { cli, command } from \"cleye\"\nimport pkg from \"../package.json\" with { type: \"json\" }\n\nconst { version } = pkg\n\nimport { agentCommand } from \"./commands/agent.js\"\nimport { commitCommand } from \"./commands/commit.js\"\nimport { configCommand } from \"./commands/config.js\"\nimport { logsCommand } from \"./commands/logs.js\"\nimport { updateCommand } from \"./commands/update.js\"\nimport { setAgentMode } from \"./utils/agent.js\"\nimport { setDebug, writeSessionHeader } from \"./utils/debug.js\"\n\n/** `cmint auto` subcommand handler — equivalent to `cmint --auto`. */\nexport async function handleAutoSubcommand(version: string) {\n\twriteSessionHeader()\n\tsetDebug(false)\n\tvoid commitCommand({ auto: true, retry: false, agent: false }, version)\n}\n\ncli(\n\t{\n\t\tname: \"cmint\",\n\t\tversion,\n\t\tdescription:\n\t\t\t\"AI-powered git commit tool — auto-group changed files, generate messages, run pre-commit checks\",\n\t\tflags: {\n\t\t\tretry: {\n\t\t\t\ttype: Boolean,\n\t\t\t\tdescription: \"Retry the last failed commit\",\n\t\t\t\talias: \"r\",\n\t\t\t\tdefault: false,\n\t\t\t},\n\t\t\tauto: {\n\t\t\t\ttype: Boolean,\n\t\t\t\tdescription: \"Auto-group files into commits and accept messages (no prompts)\",\n\t\t\t\talias: \"a\",\n\t\t\t\tdefault: false,\n\t\t\t},\n\t\t\tmessage: {\n\t\t\t\ttype: String,\n\t\t\t\tdescription: \"Provide a commit message directly (skip AI generation)\",\n\t\t\t\talias: \"m\",\n\t\t\t},\n\t\t\thint: {\n\t\t\t\ttype: String,\n\t\t\t\tdescription: \"Add context hint for AI commit message generation\",\n\t\t\t\talias: \"H\",\n\t\t\t},\n\t\t\tdebug: {\n\t\t\t\ttype: Boolean,\n\t\t\t\tdescription: \"Enable debug output\",\n\t\t\t\talias: \"d\",\n\t\t\t\tdefault: false,\n\t\t\t},\n\t\t\tnoCheck: {\n\t\t\t\ttype: Boolean,\n\t\t\t\tdescription: \"Skip user-defined pre-commit checks\",\n\t\t\t\talias: \"N\",\n\t\t\t\tdefault: false,\n\t\t\t},\n\t\t\tagent: {\n\t\t\t\ttype: Boolean,\n\t\t\t\tdescription: \"AI agent mode: non-interactive auto-group with JSON output\",\n\t\t\t\tdefault: false,\n\t\t\t},\n\t\t},\n\t\tcommands: [\n\t\t\tcommand(\n\t\t\t\t{\n\t\t\t\t\tname: \"logs\",\n\t\t\t\t\tdescription: \"Show debug logs from the last cmint run\",\n\t\t\t\t\tflags: {\n\t\t\t\t\t\tlines: {\n\t\t\t\t\t\t\ttype: Number,\n\t\t\t\t\t\t\tdescription: \"Number of lines to show from the end\",\n\t\t\t\t\t\t\talias: \"n\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tasync (argv) => {\n\t\t\t\t\tawait logsCommand(argv.flags)\n\t\t\t\t},\n\t\t\t),\n\t\t\tcommand(\n\t\t\t\t{\n\t\t\t\t\tname: \"auto\",\n\t\t\t\t\tdescription: \"Auto-group files into logical commits (alias for --auto)\",\n\t\t\t\t},\n\t\t\t\tasync () => {\n\t\t\t\t\tawait handleAutoSubcommand(version)\n\t\t\t\t},\n\t\t\t),\n\t\t\tcommand({ name: \"config\" }, async () => {\n\t\t\t\tawait configCommand()\n\t\t\t}),\n\t\t\tcommand(\n\t\t\t\t{\n\t\t\t\t\tname: \"update\",\n\t\t\t\t\tdescription: \"Update cmint to the latest published version\",\n\t\t\t\t\tflags: {\n\t\t\t\t\t\tyes: {\n\t\t\t\t\t\t\ttype: Boolean,\n\t\t\t\t\t\t\tdescription: \"Skip confirmation prompt\",\n\t\t\t\t\t\t\talias: \"y\",\n\t\t\t\t\t\t\tdefault: false,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tasync (argv) => {\n\t\t\t\t\tawait updateCommand(version, argv.flags)\n\t\t\t\t},\n\t\t\t),\n\t\t],\n\t},\n\t(argv) => {\n\t\twriteSessionHeader()\n\t\tsetDebug(argv.flags.debug)\n\t\tif (argv.flags.agent) {\n\t\t\tsetAgentMode(true)\n\t\t\tagentCommand(argv.flags)\n\t\t} else {\n\t\t\tvoid commitCommand(argv.flags, version)\n\t\t}\n\t},\n)\n"],"x_google_ignoreList":[28,29,30,31,32,33],"mappings":"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"}
|