{"record":{"id":"97edac53375cdc5b","repo":"pbakaus/impeccable","slug":"unsupported-live-copy-edit-ai-runner-provider-97edac","errorCode":null,"errorMessage":"Unsupported live copy-edit AI runner: ${provider}","messagePattern":"Unsupported live copy-edit AI runner: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"skill/scripts/live-copy-edit-agent.mjs","lineNumber":128,"sourceCode":"    const raw = await opts.applyBatchToSource(batch, { repair: batch?.repair || null });\n    return normalizeBatchResult(raw || {});\n  }\n  if (!provider) {\n    throw new Error(describeNoProviderError({ env }));\n  }\n\n  const prompt = buildCopyEditBatchPrompt(batch, { cwd });\n  const outDir = opts.outDir || fs.mkdtempSync(path.join(os.tmpdir(), 'impeccable-copy-batch-'));\n  fs.mkdirSync(outDir, { recursive: true });\n  const resultPath = path.join(outDir, 'result.json');\n  const logPath = path.join(outDir, 'agent.log');\n\n  if (provider === 'codex') {\n    await runCodex(prompt, { cwd, env, resultPath, logPath, timeoutMs: opts.timeoutMs });\n  } else if (provider === 'claude') {\n    await runClaude(prompt, { cwd, env, resultPath, logPath, timeoutMs: opts.timeoutMs });\n  } else {\n    throw new Error(`Unsupported live copy-edit AI runner: ${provider}`);\n  }\n\n  const output = fs.existsSync(resultPath) ? fs.readFileSync(resultPath, 'utf-8') : '';\n  const parsed = parseCopyEditBatchResult(output);\n  if (parsed) return parsed;\n\n  const tail = fs.existsSync(logPath) ? fs.readFileSync(logPath, 'utf-8').slice(-1200) : output.slice(-1200);\n  throw new Error('AI copy-edit batch did not return a valid completion payload. ' + tail.trim());\n}\n\nexport function runCopyEditPostApplyChecks({ cwd = process.cwd(), files = [] } = {}) {\n  const failures = [];\n  const warnings = [];\n  const uniqueFiles = [...new Set((files || []).filter((file) => typeof file === 'string' && file.trim()))];\n  for (const relativeFile of uniqueFiles) {\n    const file = path.resolve(cwd, relativeFile);\n    if (!isPathInsideOrEqual(cwd, file) || !fs.existsSync(file)) {\n      warnings.push({ file: relativeFile, reason: 'file_missing_or_outside_cwd' });","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/pbakaus/impeccable/blob/d14711ae3d1a1dd62dee61a358d27f107c51ccd0/skill/scripts/live-copy-edit-agent.mjs#L110-L146","documentation":"Thrown by runCopyEditBatchAgent() when provider is truthy but not one of mock/chat/codex/claude. In practice this is unreachable through chooseCopyEditAgent() (which only returns those four or null), so it is only hit when a caller passes opts.provider directly with an unsupported string. It guards against a typo'd or future provider name silently running nothing.","triggerScenarios":"Calling runCopyEditBatchAgent(batch, { provider: 'gpt' }) or any non-null string other than mock/chat/codex/claude. Programmatic callers that hard-code a provider name are the realistic source.","commonSituations":"A fork or integration that passes a custom provider string without updating the dispatch branch; a typo when forwarding opts.provider.","solutions":["Pass one of the supported providers: 'mock', 'chat', 'codex', or 'claude'.","Omit opts.provider to let chooseCopyEditAgent() pick automatically based on env/auth.","If you are extending the runner, add the new branch in runCopyEditBatchAgent and a matching case in chooseCopyEditAgent."],"exampleFix":"// before\nrunCopyEditBatchAgent(batch, { provider: 'gpt' });\n// after\nrunCopyEditBatchAgent(batch, { provider: 'claude' });","handlingStrategy":"type-guard","validationCode":"const SUPPORTED = new Set(['mock', 'chat', 'codex', 'claude']);\nif (!SUPPORTED.has(provider)) {\n  throw new Error('Unsupported provider: ' + provider + '. Use one of ' + [...SUPPORTED].join(', '));\n}","typeGuard":"function isSupportedCopyEditProvider(p) {\n  return ['mock', 'chat', 'codex', 'claude'].includes(p);\n}","tryCatchPattern":null,"preventionTips":["Do not hard-code provider names from outside the supported set.","Omit opts.provider to use auto-selection."],"tags":["live-copy-edit","provider","validation","agent-runner"],"backgroundTag":null,"analyzedSha":"d14711ae3d1a1dd62dee61a358d27f107c51ccd0","analyzedAt":"2026-08-13T00:52:25.771Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}