Retry structurally invalid planner candidates #246

Merged
lost-rob0t merged 2 commits from rage/245-planner-structural-retry into main 2026-08-27 03:51:05 +00:00
lost-rob0t commented 2026-08-26 14:01:12 +00:00 (Migrated from github.com)

Fixes #245. Blocks behavioral acceptance #183 / PR #242.

RAGE baseline

Branch starts from exact canonical main 267697bef10a3fffff7c093e1435ece770e7444b. The TDD classifier head 37637cab5b2be4f04cf4458744e9037fe915d9a7 proved the original defect with green expected-failure assertions; current realization candidate is 39d8e1ff030e011e8e0c37619c0c2ba053d83c47.

The live #183 gate exposed a generic retry asymmetry: planner_attempts/1 retries plan_parse/2 failures, but a parseable candidate that fails canonical structural validation exited the planner loop and was rejected later by plan_run/5, so no configured repair attempt occurred.

TDD-first defect contract

The deterministic classifier established from canonical main proved:

  • attempt 1 returns a parseable plan with a model step plus duplicate finals;
  • planner_attempts(2) is configured;
  • completion originally returned phase:validate / kind:invalid_plan / detail:final_must_be_unique_and_last;
  • the injected planner was called exactly once;
  • the invalid candidate executed zero model operations.

No intentional-red CI, xfail, skip, swallowed failure, or validation weakening is used.

Analyze / adversarial correction

rlm_plan:plan_validate/4 is non-executing but mixes structural validation with capability and plan-budget checks. Retrying every validation error would incorrectly teach the planner to repair around host policy or budget denial.

A structural-only duplicate validator/refactor was considered, but the realized candidate found a smaller safe reuse boundary: call canonical plan_validate/4, then classify its structured result instead of retrying every error.

Realization

Current candidate 39d8e1ff... classifies canonical validation outcomes before any candidate plan operation runs:

  • phase:validate, kind:invalid_plan => bounded planner-repair candidate;
  • capability denial => preserve/defer to the existing authoritative path, no planner retry;
  • plan-budget denial => preserve/defer to the existing authoritative path, no planner retry;
  • other errors remain explicit failures.

plan_run/5 still validates again before execution as defense in depth. No plan is auto-edited or partially executed.

The deterministic realization matrix covers:

  • structurally invalid attempt 1 followed by valid attempt 2 recovers;
  • two structurally invalid attempts return explicit planner-validation failure with aggregate usage;
  • invalid candidates execute zero operations;
  • a parseable capability-denied candidate gets one planner call and is not converted into repair/retry;
  • planner usage across attempts remains aggregate and bounded.

No second validator, authority layer, provider-specific special case, or downstream product logic is introduced.

Adversarial decision

Implementation design: GO. Exact-head verification: HOLD.

The current head itself is mergeable and has no submitted reviews, PR conversation comments, or unresolved review threads, but its repository-native Actions state is not a valid green gate:

  • Nix flake: success;
  • CI: startup_failure;
  • Clean SWI pack install: startup_failure;
  • Paid OpenRouter run: marked failure while its only returned job remains queued with no executed steps;
  • Tree-sitter FFI: still queued.

GitHub rejected an attempted exact-run CI retry with HTTP 403 (This workflow run cannot be retried). This is currently runner/workflow-state evidence, not evidence that the implementation passed. Do not reuse the older green TDD-head results for this changed candidate and do not change code merely to manufacture a new SHA.

Keep draft until the exact realization head gets normal completed deterministic, REAL/Paid OpenRouter, Nix, clean-pack, and Tree-sitter evidence. If a real test/provider failure appears, preserve it and repair the root cause.

Fixes #245. Blocks behavioral acceptance #183 / PR #242. ## RAGE baseline Branch starts from exact canonical `main` `267697bef10a3fffff7c093e1435ece770e7444b`. The TDD classifier head `37637cab5b2be4f04cf4458744e9037fe915d9a7` proved the original defect with green expected-failure assertions; current realization candidate is `39d8e1ff030e011e8e0c37619c0c2ba053d83c47`. The live #183 gate exposed a generic retry asymmetry: `planner_attempts/1` retries `plan_parse/2` failures, but a parseable candidate that fails canonical structural validation exited the planner loop and was rejected later by `plan_run/5`, so no configured repair attempt occurred. ## TDD-first defect contract The deterministic classifier established from canonical `main` proved: - attempt 1 returns a parseable plan with a model step plus duplicate finals; - `planner_attempts(2)` is configured; - completion originally returned `phase:validate / kind:invalid_plan / detail:final_must_be_unique_and_last`; - the injected planner was called exactly once; - the invalid candidate executed zero model operations. No intentional-red CI, xfail, skip, swallowed failure, or validation weakening is used. ## Analyze / adversarial correction `rlm_plan:plan_validate/4` is non-executing but mixes structural validation with capability and plan-budget checks. Retrying every validation error would incorrectly teach the planner to repair around host policy or budget denial. A structural-only duplicate validator/refactor was considered, but the realized candidate found a smaller safe reuse boundary: call canonical `plan_validate/4`, then classify its structured result instead of retrying every error. ## Realization Current candidate `39d8e1ff...` classifies canonical validation outcomes before any candidate plan operation runs: - `phase:validate, kind:invalid_plan` => bounded planner-repair candidate; - capability denial => preserve/defer to the existing authoritative path, **no planner retry**; - plan-budget denial => preserve/defer to the existing authoritative path, **no planner retry**; - other errors remain explicit failures. `plan_run/5` still validates again before execution as defense in depth. No plan is auto-edited or partially executed. The deterministic realization matrix covers: - structurally invalid attempt 1 followed by valid attempt 2 recovers; - two structurally invalid attempts return explicit planner-validation failure with aggregate usage; - invalid candidates execute zero operations; - a parseable capability-denied candidate gets one planner call and is not converted into repair/retry; - planner usage across attempts remains aggregate and bounded. No second validator, authority layer, provider-specific special case, or downstream product logic is introduced. ## Adversarial decision **Implementation design: GO. Exact-head verification: HOLD.** The current head itself is mergeable and has no submitted reviews, PR conversation comments, or unresolved review threads, but its repository-native Actions state is not a valid green gate: - Nix flake: success; - CI: `startup_failure`; - Clean SWI pack install: `startup_failure`; - Paid OpenRouter run: marked `failure` while its only returned job remains `queued` with no executed steps; - Tree-sitter FFI: still queued. GitHub rejected an attempted exact-run CI retry with HTTP 403 (`This workflow run cannot be retried`). This is currently runner/workflow-state evidence, not evidence that the implementation passed. Do not reuse the older green TDD-head results for this changed candidate and do not change code merely to manufacture a new SHA. Keep draft until the exact realization head gets normal completed deterministic, REAL/Paid OpenRouter, Nix, clean-pack, and Tree-sitter evidence. If a real test/provider failure appears, preserve it and repair the root cause.
Sign in to join this conversation.
No description provided.