fix: fail closed on unavailable llm review - #614
Conversation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit b094d5b. Configure here.
| }); | ||
| } finally { | ||
| try { fs.rmSync(tmpDir, { recursive: true, force: true }); } catch (_) {} | ||
| } |
There was a problem hiding this comment.
Temp dir leaks on write failure
Low Severity
mkdtempSync creates evolver-review-* before the try/finally, and writeFileSync also sits outside that block. If the prompt write throws, the new directory is never removed, unlike the execFileSync path which always cleans up in finally.
Reviewed by Cursor Bugbot for commit b094d5b. Configure here.
There was a problem hiding this comment.
Left a non-blocking comment and did not approve because the present Cursor Bugbot check completed as skipped. Human review is needed; one reviewer was assigned from the changed GEP review path. Cursor Security Agent was not running after the first poll, so that signal was skipped.
Sent by Cursor Approval Agent: Pull Request Router and Approver




Summary
Harden the
llmReviewtrust boundary so malformed, empty, partial, timed-out, or failed review execution can never approve a solidification candidate. Preserve valid approval/rejection compatibility fields while adding typed recoverable status, retry metadata, and attempt traces.What changed
malformed_output,empty_output,partial_response,runner_error, ortimeoutand made each fail closed withapproved: false.How to test
node --test test/llmReview.test.jsPATH=/opt/homebrew/opt/node@22/bin:$PATH npm test(runs all 3,299 project tests locally; 3,259 passed and 40 unrelated black-box CLI/proxy timing tests hit their fixed local 10–20 second deadlines;llmReviewpassed inside the full run; hosted CI is the clean-environment full-suite authority)node --test test/solidify-helpers.test.js test/solidifyLearning.test.js(68/68 pass)node --check src/gep/llmReview.js && node --check test/llmReview.test.js && git diff --checknode index.js --helpnode scripts/harness-governance-check.js --body <this-pr-body> --changed <changed-files>Expected: focused and adjacent suites pass;
llmReviewpasses in the full test run; static checks and CLI sanity exit zero; governance gate reportsPASSED. Hosted CI must pass the complete suite before merge.Risk
Medium -- this intentionally changes enabled
llmReviewinfrastructure failures from approval to a recoverable fail-closed rejection. The default placeholder success path, explicit model approval/rejection, disabled-modenull, and legacy compatibility fields remain unchanged.Harness/evaluator governance
Upstream governance surface:
src/gep/llmReview.jsreview parsing, execution, retry, and approval invariant only.Downstream EvoX impact: Enabled review failures now return
approved: falsewith typed recoverable metadata; no bridge schema or runtime API changes outside the existing review result object.Rollout-local scope: Applies only when
EVOLVER_LLM_REVIEW=true; disabled mode remains unchanged.Promotion boundary: Merge makes the fail-closed invariant the default only inside the opt-in llmReview path; no live promotion is performed by this PR.
Evaluator mismatch sets: Observation adds typed failure reasons and attempt traces; action changes only unverifiable failures from approval to rejection; repair adds bounded retry; verification covers malformed, empty, partial, runner error, timeout, success, rejection, idempotency, and real subprocess trace; evidence is the focused/full test output; belief changes from fail-open to fail-closed for unavailable reviews.
Non-regression evidence: Focused
test/llmReview.test.js(11/11), adjacent solidify tests (68/68), full Node 22 run (3,299 executed; 3,259 passed; 40 unrelated local black-box timing failures; llmReview passed), syntax/whitespace checks, CLI sanity, before/after failure probe, and harness governance gate. Hosted CI is required before merge.Fix-severity review: high
Owner approval: GEP llmReview/evaluator owner review required.
Security boundary: No new data, network, host, tool, or secrets access; temporary prompts remain local and are removed after each attempt. Trust is tightened because unverified output cannot authorize a candidate.
Rollback: Revert this commit to restore prior behavior; operationally disable the opt-in path with
EVOLVER_LLM_REVIEW=falsewhile investigating.Live promotion: no
Autonomous evaluator self-editing: no
Self-check
Related
N/A
🤖 Generated with Claude Code
Note
Medium Risk
Changes behavior on the evolution trust boundary when LLM review is enabled: unverifiable review outcomes flip from fail-open approval to fail-closed rejection, which can block candidates that previously slipped through.
Overview
Hardens the opt-in
llmReviewgate so infrastructure or bad output can no longer implicitly approve solidification candidates whenEVOLVER_LLM_REVIEW=true.Previously, parse failures, runner errors, and timeouts could still yield
approved: truewith low confidence. The flow now validates the full JSON contract (approved, boundedconfidence,concerns, non-emptysummary), retries once by default, and on exhaustion returnsapproved: falsewithstatus: 'unavailable', typedreason(malformed_output,empty_output,partial_response,runner_error,timeout),retryable: true, and per-attempt trace. Valid explicit approve/reject paths keep the legacy fields plusstatus/reason. Execution is injectable for tests; default subprocess temp dirs usemkdtempand are removed after each attempt.Adds
test/llmReview.test.jscovering fail-closed cases, retry recovery, rejection, idempotency, disabled mode, and subprocess cleanup.Reviewed by Cursor Bugbot for commit b094d5b. Bugbot is set up for automated code reviews on this repo. Configure here.