feat(TASK-018): review-gauntlet lane degradation + verification passthrough

- lane_fault.py + fallback on all four run_* lane nodes: an agent-node
  failure is normalized into a PIPELINE-FAULT lane result instead of
  killing the graph
- verdict_gate.py: PIPELINE-FAULT lane results block distinctly from
  SKIPPED and missing-sentinel; a PIPELINE-FAULT in signals_error blocks
  at the gauntlet level
- build_items.py: restructured into main() + fail-closed guard (crash
  emits empty lanes + PIPELINE-FAULT) and folds lanes_degraded into
  lanes_summary
- parse: state_updates/fallback -> parse_fault.py, which records the
  fault in signals_error and jumps to the verdict gate
- select_lanes: state_updates/fallback -> default_lanes.py, a
  deterministic wider-never-narrower lane fallback
- verification_commands threaded through parse into run_adversary's
  prompt (declared-only, never invented)
- run_probe prompt gains the aborted-attempt reconcile line
- 8 gauntlet_* R5 tests in src/config/request_context.rs (script harness
  + graph interpolation)
This commit is contained in:
Dark-Alex-17 committed 2026-09-14 10:50:33 -06:00
1 parent 1e46743420
commit 8407729d5a
7 files changed
+603 -80

No files matched your search

+51 -1
View File
@@ -39,6 +39,7 @@ initial_state:
security_posture: standard
probe_context: ''
extra_context: ''
verification_commands: []
forced_lanes: []
changed_files: []
file_count: 0
@@ -56,6 +57,9 @@ initial_state:
add_security: false
add_probe: false
lane_reasons: ''
parse_failure: ''
select_lanes_failure: ''
lanes_degraded: ''
code_review_items: []
adversary_items: []
security_items: []
@@ -100,6 +104,10 @@ nodes:
names). Empty array = automatic selection.
- `extra_context`: any remaining caller context reviewers should see,
condensed.
- `verification_commands`: the exact build/test/lint shell commands the
caller explicitly declares for verification (verbatim strings, in the
order given). Empty array when the caller declares none — NEVER invent,
guess, or auto-detect commands; undeclared stays undeclared.
prompt: |
Extract the review-request facts from this request:
@@ -126,11 +134,26 @@ nodes:
type: string
project_dir_in:
type: string
required: [diff_spec, plan_context, rigor, security_posture, probe_context, forced_lanes, extra_context, project_dir_in]
verification_commands:
type: array
items:
type: string
required: [diff_spec, plan_context, rigor, security_posture, probe_context, forced_lanes, extra_context, project_dir_in, verification_commands]
max_iterations: 3
max_attempts: 2
state_updates:
parse_failure: '{{output}}'
fallback: parse_fault
next: signals
parse_fault:
id: parse_fault
type: script
description: Fail-closed marker for a dead parse stage (reached only via parse's fallback) — records a PIPELINE-FAULT in signals_error and jumps straight to the verdict gate, which blocks on it. Lane item lists stay their initial [] so every lane records SKIPPED.
script: scripts/parse_fault.py
timeout: 30
next: verdict_gate
signals:
id: signals
type: script
@@ -204,6 +227,17 @@ nodes:
required: [add_code_review, add_adversary, add_security, add_probe, lane_reasons]
max_iterations: 3
max_attempts: 2
state_updates:
select_lanes_failure: '{{output}}'
fallback: default_lanes
next: build_items
default_lanes:
id: default_lanes
type: script
description: Deterministic lane-selection fallback (reached only via select_lanes' fallback) — forces code-review + adversary, plus probe when consumer_surface, when the additive LLM judgment dies. Selection degrades WIDER, never narrower; the degradation note flows into lanes_summary via build_items.
script: scripts/default_lanes.py
timeout: 30
next: build_items
build_items:
@@ -279,6 +313,7 @@ nodes:
max_attempts: 2
state_updates:
lane_out: '{{output}}'
fallback: lane_fault
run_adversary:
id: run_adversary
@@ -294,12 +329,15 @@ nodes:
The spec / plan / acceptance criteria it must satisfy:
{{plan_context}}
Verification commands (declared by the caller; empty = none declared): {{verification_commands}}
{{extra_context}}
Return your ADVERSARIAL_REVIEW verdict.
max_attempts: 2
state_updates:
lane_out: '{{output}}'
fallback: lane_fault
run_security:
id: run_security
@@ -318,6 +356,7 @@ nodes:
max_attempts: 2
state_updates:
lane_out: '{{output}}'
fallback: lane_fault
run_probe:
id: run_probe
@@ -335,12 +374,23 @@ nodes:
Plan / acceptance-criteria context:
{{plan_context}}
The workspace may contain test files from an aborted earlier attempt of
this lane; reconcile rather than duplicate.
Derive expected behaviors from the plan/contract BEFORE reading
implementation code, run existing suites first, then author spec-first
tests for the uncovered delta. Return your USAGE_PROBE verdict.
max_attempts: 2
state_updates:
lane_out: '{{output}}'
fallback: lane_fault
lane_fault:
id: lane_fault
type: script
description: Fail-closed lane fault marker (reached only via the run_* lanes' fallback routes; shared across the four map branches). Normalizes the engine's "Agent node failed" text in lane_out into a PIPELINE-FAULT lane result the map collects; verdict_gate turns it into BLOCKED — a degraded lane is never a pass.
script: scripts/lane_fault.py
timeout: 30
verdict_gate:
id: verdict_gate