feat(TASK-032): review-gauntlet incomplete-review machine line + ×N attempt details
verdict_gate.py now names every incomplete review on a machine line the done template renders immediately after the verdict: `GAUNTLET_REVIEW_INCOMPLETE: <name>[, <name>]` (sorted). Names are the lanes retry_gate gave up on (`review_incomplete`) plus the `pipeline` pseudo-lane whenever `signals_error` carries a `PIPELINE-FAULT:` — parse death, builder / retry-gate / default-lanes crash guards — and the gate's own crash guard emits the `pipeline` line too. The report gains a `## Review incomplete` section (after the signals_error blockquote, immediately before `## Full lane reports`) and the three PIPELINE-FAULT lane rows carry ` ×N` when the lane was re-run (N = 1 texts unchanged). retry_gate.py stands in a synthetic `PIPELINE-FAULT: <lane> lane produced no report` marker for a lane that ran but collected nothing, so it is stashed, classified FAULTED and never renders SKIPPED downstream. MAX_RETRY_ELAPSED_SECS trimmed 45600 → 45000 for margin slack. graph.yaml: `gauntlet_incomplete_line` seeded in initial_state and spliced into the done output. README + mermaid document retry_gate, the dotted _next back-edge, the 3-attempt / wall-clock budget, that retry never narrows selection, the crash-guard append semantics, and the machine-line contract (present whenever any lane or the pipeline was incomplete; it can accompany real findings). Tests: ×N on all three branches (N>1, N=1 byte-identical, no leak onto non-fault rows), exact incomplete line / section placement, pipeline pseudo-lane alone and alongside real lanes (via default_lanes.py's real crash guard), mixed finding+fault, crash-guard chaining from build_items / retry_gate / parse_fault / verdict_gate, synthetic no-report marker, done-template wiring, README pins (positive + stale negative).
This commit is contained in:
5 files changed
+568
-31
No files matched your search
@@ -10,7 +10,9 @@ hard rules:
|
||||
and faulted alike, and a lane whose map ran nothing this pass gets
|
||||
its stashed report restored — the verdict gate always sees each
|
||||
lane's LAST report;
|
||||
- a lane is FAULTED only when its report is missing, non-string, the
|
||||
- a lane is FAULTED only when its report is missing (the map ran but
|
||||
collected nothing — replaced by a synthetic PIPELINE-FAULT marker so
|
||||
the verdict gate never reads it as SKIPPED), non-string, the
|
||||
lane_fault.py marker, sentinel-less, or carries the nested graph's own
|
||||
degraded-run wording; a real verdict (DIVERGES, FAIL, INCONCLUSIVE,
|
||||
NEEDS-HUMAN, …) is never re-run — the review's judgment stands;
|
||||
@@ -27,7 +29,9 @@ import os
|
||||
import re
|
||||
import time
|
||||
|
||||
MAX_RETRY_ELAPSED_SECS = 45600
|
||||
# 69600 (graph timeout) − 2 × 11400 (largest lane envelope) − 1200 (script stages)
|
||||
# = 45600; 600 s of slack below that.
|
||||
MAX_RETRY_ELAPSED_SECS = 45000
|
||||
MAX_ATTEMPTS = 3
|
||||
|
||||
# lane name -> (items key, results key)
|
||||
@@ -114,8 +118,10 @@ def main():
|
||||
out[results_key] = [kept[lane]]
|
||||
continue
|
||||
report = results[0] if results else None
|
||||
if report is not None:
|
||||
kept[lane] = report
|
||||
if report is None:
|
||||
report = f"PIPELINE-FAULT: {lane} lane produced no report"
|
||||
out[results_key] = [report]
|
||||
kept[lane] = report
|
||||
if is_faulted(lane, report):
|
||||
faulted.append(lane)
|
||||
attempts[lane] = int(attempts.get(lane) or 0) + 1
|
||||
|
||||
Reference in new issue
Block a user