Skip to content

feat: confidence-gated Accept/Refine/Restart at the local_triage boundary (Closes #1339) - #1365

Merged
Lexus2016 merged 1 commit into
mainfrom
evolution/issue-1339-confidence-gate
Jul 27, 2026
Merged

feat: confidence-gated Accept/Refine/Restart at the local_triage boundary (Closes #1339)#1365
Lexus2016 merged 1 commit into
mainfrom
evolution/issue-1339-confidence-gate

Conversation

@Lexus2016

Copy link
Copy Markdown
Owner

Closes #1339 — slice B of the AREX loop (#1330), building directly on the StageResult contract merged for slice A (#1338).

The gate

evolution/lib/stage_gate.pydecide() returns a GateDecision:

Branch Condition Behaviour
Accept confidence >= tau proceed as normal
Refine below tau, trajectory recoverable carry evidence forward, re-investigate only the gaps
Restart below tau, nothing salvageable discard trajectory, reinitialize from the original problem

tau defaults to 70 — conservative, per the issue's "conservative τ prevents runaway looping" criterion.

There is a deliberate interaction with StageResult.wrap: it assigns confidence 50 when evidence exists but no self-assessment was made. That lands in Refine, not Accept — so a stage that never assessed itself is never silently trusted.

On the recoverable-vs-noisy judgement

The issue specifies this call is "produced by the model running the stage". A deterministic script has no model, so decide() takes an explicit recoverable argument for callers that do have that judgement, and falls back to a structural proxy when it is None: evidence present means something concrete to build on; no evidence is indistinguishable from noise. Both overrides are tested.

Wiring — not dead code

Wired at the same boundary slice A emits from. evolution_local_triage.py runs the tuple through the gate, records the branch in the analysis JSON as stage_gate, and prints the decision line:

[stage-gate] local_triage: RESTART (confidence=50, threshold=70) — below threshold with no salvageable evidence — discarding the trajectory and reinitializing from the original problem

Advisory at this boundary rather than aborting, because local triage is a read-only pre-pass whose output the analysis stage consumes — the branch is surfaced for the next stage to act on. The deterministic dead-code check finds three call sites in evolution_local_triage.py outside the module and its tests.

Success criteria

  • Gate wrapper implements all three branches
  • At least one stage boundary uses the gate
  • Branch decision is logged
  • Conservative τ prevents runaway looping

Deferred to slice C (#1340), as the issue specifies: stage_refine_rate / stage_restart_rate metrics and multi-boundary rollout.

50 passing across test_stage_gate.py, test_stage_result.py, test_evolution_analysis_gate.py, test_evolution_local_triage.py — with and without PYTHONPATH; ruff clean.

…dary (#1339)

Slice B of the AREX loop (#1330). Slice A (#1338) gave stages a uniform
StageResult; this is the gate that acts on the confidence it carries.

evolution/lib/stage_gate.py — decide() returns a GateDecision with one of:
- Accept  (confidence >= tau): proceed as normal
- Refine  (below tau, trajectory recoverable): carry the evidence forward and
          re-investigate only the gaps
- Restart (below tau, nothing salvageable): discard and reinitialize

tau defaults to 70, deliberately conservative per the issue's "conservative tau
prevents runaway looping" criterion. This interacts on purpose with
StageResult.wrap, which assigns confidence 50 when evidence exists but no
self-assessment was made: such a result lands in Refine, so an un-assessed stage
is never silently trusted as a confident one.

The issue specifies the recoverable-vs-noisy call comes from the model running
the stage. A deterministic script has no model, so decide() takes an explicit
`recoverable` argument for callers that have that judgement, and falls back to a
structural proxy when it is None — evidence present means there is something
concrete to build on; no evidence is indistinguishable from noise.

Wired at the same boundary slice A emits from: evolution_local_triage.py runs
the tuple through the gate, records the branch in the analysis JSON as
`stage_gate`, and prints the decision line. Advisory there rather than aborting,
because local triage is a read-only pre-pass whose output the analysis stage
consumes — the branch is surfaced for the next stage to act on. Verified not
dead code: three call sites in evolution_local_triage.py outside the module and
its tests.

Deferred to slice C (#1340) as the issue specifies: stage_refine_rate /
stage_restart_rate metrics and multi-boundary rollout.

50 passing across test_stage_gate.py, test_stage_result.py,
test_evolution_analysis_gate.py and test_evolution_local_triage.py, with and
without PYTHONPATH; ruff clean.

Closes #1339
@Lexus2016
Lexus2016 merged commit 21b7966 into main Jul 27, 2026
37 checks passed
@Lexus2016
Lexus2016 deleted the evolution/issue-1339-confidence-gate branch July 27, 2026 17:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[INCREMENT] Confidence-gated Accept/Refine/Restart wrapper at stage boundary (AREX #1330 slice B)

1 participant