You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Turn-end model review is now async-first: the Stop hook's deterministic
gates decide whether a turn warrants review and, if so, launch exactly ONE
detached background job (POSIX and Windows) that runs the correctness,
duplication, and idiom lenses, verifies every finding with an independent
refuter, persists survivors to a canonical Finding-lifecycle ledger with a
severity surface bar, and pre-renders a delivery payload — Stop itself
never waits on it, so a model review never delays turn end.
Findings deliver at the next UserPromptSubmit (multi-root aware), the next
Stop (an unaddressed HIGH resurfaces once), or SessionStart (dead
sessions) — never in the same turn that triggered the review, unless CHAMELEON_JUDGE_WAIT=1 makes Stop poll the job and render in-turn (for
harnesses/CI, which have no next turn to deliver into).
A finding whose cited file changed since review now renders [stale]
instead of being silently dropped.
Idiom review is now one lens of the turn-end review job, scoped by diff
hunks and citing the violated idiom's slug and lines, instead of a
once-per-session Stop-hook self-review interrupt; enforcement.idiom_review
still gates it, and a compliant turn shows nothing at all.
Fixed
The turn-end resurface re-check (an unaddressed HIGH finding "resurfaces
once") was never wired into the live Stop pipeline: stop_gates still
called the pre-cutover drift.db-backed helper, which had no findings to
read since the review job persists to the new canonical ledger instead. It
now calls that ledger's own recheck_and_resurface directly, and a
resurfaced finding is a TERMINAL delivery status, so the one-shot re-nag
can no longer loop back through ordinary delivery and re-arm itself.
The reviewer model ladder (CHAMELEON_JUDGE_MODEL_HIGH, escalating to a
stronger model on a risk_high/intent_forced route) never actually
escalated: it short-circuited to the base model unless a flag only the
now-deleted detached async-judge child ever set. Since every review now
runs detached by construction, the ladder escalates unconditionally.
Removed
The synchronous correctness-judge spawn, the route/gate choreography
(_correctness_judge_route/_gate, _multi_lens_review_lines, _duplication_advisory_lines), lens_runner.py, lens_synthesis.py, judge_async.py, and the once-per-session idiom-review interrupt
(_idiom_review_gate) — all absorbed by the new stop/scheduler.py, stop/job.py, stop/lenses/, and stop/verify.py.
The pre-cutover drift.db-backed finding->fix ledger (_ledger_persist / _ledger_recheck_and_resurface in stop/gates.py, record_judge_finding
/ open_judge_findings / mark_judge_finding in drift/observations.py),
superseded by review_ledger.py's canonical finding-lifecycle ledger. Any
HIGH finding it was still holding open from before the cutover is not
migrated (low impact, unlike the .judge_pending.<session>.json queue,
which is migrated).