{"record":{"id":"9e69a05ac4016d0f","repo":"JuliusBrussee/caveman","slug":"claude-specific-cave-build-execution-is-unavailabl","errorCode":null,"errorMessage":"Claude-specific Cave Build execution is unavailable until model, reasoning, budget, recovery, and wire selectors are enforced","messagePattern":"Claude-specific Cave Build execution is unavailable until model, reasoning, budget, recovery, and wire selectors are enforced","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/index.ts","lineNumber":5575,"sourceCode":"    env: process.env,\n    encoding: \"utf8\",\n  });\n  if (checked.error || checked.status !== 0) {\n    const detail = String(checked.stderr || checked.error?.message || \"lock check failed\").trim();\n    throw new Error(`Cave Build lock is stale or invalid; refusing Claude launch before model spend: ${detail}`);\n  }\n  const rawAfterCheck = readFileSync(lockPath, \"utf8\");\n  if (rawAfterCheck !== rawBeforeCheck) {\n    throw new Error(\"Cave Build lock changed during validation; refusing Claude launch before model spend\");\n  }\n  const lock = JSON.parse(rawAfterCheck) as { harness?: { id?: unknown } };\n  if (lock.harness?.id !== \"claude\") {\n    throw new Error(\n      \"Cave Build is Pi-specific; refusing to attach its identity to Claude Code execution\",\n    );\n  }\n  throw new Error(\n    \"Claude-specific Cave Build execution is unavailable until model, reasoning, budget, recovery, and wire selectors are enforced\",\n  );\n}\n\nfunction firstEnvSecret(env: NodeJS.ProcessEnv, keys: string[]): string | undefined {\n  for (const key of keys) {\n    const value = env[key];\n    if (typeof value === \"string\" && value.trim()) return value.trim();\n  }\n  return undefined;\n}\n\nfunction maybeWarnHermesMissingKey(agent: AgentProfile | undefined, gw = gatewayURL()) {\n  if (agent?.id !== \"hermes\") return;\n  if (wrapMode(gw) === \"local\") {\n    if (!firstEnvSecret(process.env, HERMES_LOCAL_UPSTREAM_KEY_VARS)) {\n      process.stderr.write(\"caveman: Hermes local wrap has no upstream provider key in env for the local proxy to forward; launching anyway, but provider auth may fail\\n\");\n    }\n    return;","sourceCodeStart":5557,"sourceCodeEnd":5593,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/packages/cli/src/index.ts#L5557-L5593","documentation":"This is a deliberate hard stop: even after the Cave Build lock passes validation for Claude (harness id \"claude\"), the Claude-specific execution path is not implemented yet. It throws until the model, reasoning, budget, recovery, and wire selectors are enforced for the Claude harness, so no unguarded model spend can occur.","triggerScenarios":"Any attempt to launch Claude Code through the Cave Build-gated path once the lock has fully validated (checker passed, lock unchanged, harness.id === \"claude\") — the function unconditionally throws because the feature is not enabled.","commonSituations":"A developer/test constructing a claude-id Cave Build lock and expecting the gated launcher to proceed; enabling the Cave Build gate for Claude before the supporting selector enforcement shipped; running an older CLI where the Claude Cave Build path was stubbed out.","solutions":["Do not route Claude launches through the Cave Build-gated path; launch Claude directly instead","Upgrade the CLI to a version where the model/reasoning/budget/recovery/wire selectors are enforced and this gate is lifted","Remove the Cave Build lock if the gate keeps triggering on a leftover lock","If you need this feature, track the CLI release that implements the required selector enforcement"],"exampleFix":"// before\n$ caveman-cli launch claude   # Cave Build gate active\n// after\n$ rm .cave-build.lock\n$ claude   # or launch without the Cave Build gate","handlingStrategy":"fallback","validationCode":"import { existsSync, readFileSync } from 'fs';\nfunction caveBuildGateActive(lockPath: string) {\n  if (!existsSync(lockPath)) return false;\n  try { return JSON.parse(readFileSync(lockPath, 'utf8'))?.harness?.id === 'claude'; }\n  catch { return false; }\n}\n// if gate is active, the Claude path is unimplemented — bypass it","typeGuard":null,"tryCatchPattern":"if (caveBuildGateActive(lockPath)) {\n  // Claude-specific Cave Build execution is unavailable; launch Claude directly\n  spawn('claude', args, { stdio: 'inherit' });\n} else {\n  cli.launchClaude();\n}","preventionTips":["Do not route Claude launches through the Cave Build gate until the feature ships","Remove claude-id Cave Build locks if you don't need the gate","Upgrade to a CLI version implementing model/reasoning/budget/recovery/wire selector enforcement","Keep launch scripts independent of the gated path as a fallback"],"tags":["feature-gap","cave-build","cli-gate","unimplemented"],"backgroundTag":"feature-not-enabled","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}