Priority: P0 (review-blocking). Child of #1029.
Problem: The self-host engine silently produced ZERO AI output for 202 reviews — every ai_usage_events row was status=ok, detail="no usable output" and ai_review_cache stayed empty, so posted review comments had the signal table but no AI summary/blockers/nits. No error was logged anywhere.
Root cause: The running image was built with the default INSTALL_AI_CLIS=false (Dockerfile:33), so the claude CLI was absent. AI_PROVIDER=claude-code → spawn('claude') (src/selfhost/ai.ts:227) → ENOENT → swallowed by the bare catch in runWorkersOpinion (src/services/ai-review.ts:496-498) → advisoryReview null → no notes. Also record() logged the model as a hardcoded BEST_REVIEW_MODELS.join('+') (@cf/openai/gpt-oss-120b+...) instead of the configured reviewer, hiding the breakage.
Fixed in our deploy by rebuilding with --build-arg INSTALL_AI_CLIS=true — but the failure mode must be made impossible/visible for every self-hoster.
Requirements: A misconfigured/missing AI CLI must fail LOUD, never silently. Deliverables: (1) the published GHCR image bakes the claude-code/codex CLIs (or the Quick-Start docs require the build arg); (2) a /ready (or boot) preflight that fails/warns when AI_PROVIDER=claude-code|codex but the CLI is not on PATH; (3) log a selfhost_ai_provider_failed warning on single-provider run failure (the single path bypasses createChainAi's logging, src/selfhost/ai.ts:357); (4) fix the model attribution in record() to the actual reviewer.
Priority: P0 (review-blocking). Child of #1029.
Problem: The self-host engine silently produced ZERO AI output for 202 reviews — every
ai_usage_eventsrow wasstatus=ok, detail="no usable output"andai_review_cachestayed empty, so posted review comments had the signal table but no AI summary/blockers/nits. No error was logged anywhere.Root cause: The running image was built with the default
INSTALL_AI_CLIS=false(Dockerfile:33), so theclaudeCLI was absent.AI_PROVIDER=claude-code→spawn('claude')(src/selfhost/ai.ts:227) → ENOENT → swallowed by the bare catch inrunWorkersOpinion(src/services/ai-review.ts:496-498) → advisoryReview null → no notes. Alsorecord()logged the model as a hardcodedBEST_REVIEW_MODELS.join('+')(@cf/openai/gpt-oss-120b+...) instead of the configured reviewer, hiding the breakage.Fixed in our deploy by rebuilding with
--build-arg INSTALL_AI_CLIS=true— but the failure mode must be made impossible/visible for every self-hoster.Requirements: A misconfigured/missing AI CLI must fail LOUD, never silently. Deliverables: (1) the published GHCR image bakes the claude-code/codex CLIs (or the Quick-Start docs require the build arg); (2) a
/ready(or boot) preflight that fails/warns whenAI_PROVIDER=claude-code|codexbut the CLI is not on PATH; (3) log aselfhost_ai_provider_failedwarning on single-provider run failure (the single path bypasses createChainAi's logging, src/selfhost/ai.ts:357); (4) fix the model attribution inrecord()to the actual reviewer.