Repository navigation
Remove every human-ruled STATE: a human decision is a transition, not a bucket - #247
Conversation
`CcGate::HumanRuled` parked every flagged subject carrying a `human:*` ruling label: skipped on every state-load, counted under `humanRuled`, transitioning nowhere, while the label kept the issue out of the producer's backlog AND `record_close_candidate_verdict` refused to judge the flag because a human had ruled. The PR side deleted its equivalent park; the issue side still stood. The arm is deleted and `TornHumanClose` generalised to `TornHumanRuling`, which is what the pair actually is — a torn write. `human-rule-issue keep-open` retires `ai:close-candidate` in the same call, so the pair can only exist where that call tore between its label write and its label clear; the state-load now COMPLETES it (retire the flag, or execute a recorded close) instead of counting it. Ordering is the whole fix: the park dominated the completion, so the self-heal could never fire. `humanRuled` is gone from the counts, and the partition invariant is still asserted over the reduced set — that assertion is what proves the deleted bucket's rows were re-homed rather than absorbed. Closes #244 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Warning Review limit reached
Next review available in: 6 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (5)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Reviewed 10d405a: pass Verified against the PR head blob rather than the report. Rulings-conformance: checked against CLAUDE.md's rulings section and every ruling the human stated for this work.
CI: every check passes. The single non-pass is Merging with |
Closes #244
human-ruled is not a state. A human decision is a transition INTO a state, so no bucket may mean "a human already ruled here". The PR side had already finished this argument; the issue side still parked, and this deletes that park.
What
cc_gatelooks like nowNo
HumanRuledvariant, nohuman_ruledparameter, no"human-ruled"name, no"skip-human-decided"action.RepoArchivedstays first — an archived repo refuses every write, and deciding writability before deciding what to write is deliberate and documented.The ordering is the fix:
RepoArchived → HumanRuled → TornHumanClosemeant the park dominated the self-heal by arm order alone, so the completion could never fire.The six items
CcGate::HumanRuleddeleted — variant, name, action, parameter, arm. Downstream of the action's deletion, the vetter state-load's"skip-human-decided" => n_human += 1arm and itsskipHumanDecidedkey go too: with nothing producing the action, the key would be a constant zero, which is the deleted bucket wearing a number. (VetAction::SkipHumanon the PR lane is untouched — different lane, retained by the issue.)Already true, and now pinned as a property. CLAUDE.md's claim holds in code exactly as written. On an issue with a live producer flag,
human_issue_rule_planconsultsFLAG_DISPOSING_RULINGS = ["close-candidate", "keep-open"]:needs-work/design→HumanRulePlan::StrandsFlag, refused outright, nothing written;keep-open→ lands, andclears: match (ruling, live_flag.is_some()) { ("keep-open", true) => vec!["ai:close-candidate"] };human-close→ lands, andhuman_close_planpushesPENDING_CLOSE_FLAGintoclears.So no issue ruling can land while leaving a live flag — the property was total already. No production change was made here. What was missing was the total statement: each verb had its own test, nothing asserted there was no third side.
no_issue_ruling_lands_while_leaving_a_live_flagnow drives the vocabulary table plushuman-close's plan word and asserts every verb is on one of the two sides.TornHumanClose→TornHumanRuling. The state now covers both ways a ruling lands half-written: a recorded👤 humanclose on a still-open subject (human:close-candidate splits decide-from-do, a phase no other state models: fuse close rulings into human-close, machinery completes tears #213), and a sacredhuman:*label standing beside the liveai:close-candidateit was supposed to retire. Both are torn writes; the state-load COMPLETES them. Which write is owed is a typed, pure decision —TornRulingCompletion::{CloseThenRetireFlag, RetireFlag}— extracted precisely because getting it backwards would CLOSE an issue a human ruledkeep-open, and a branch inside the network call is a branch no test can reach.The label half is asked only of a live flag, which is load-bearing twice: a ruling label with no producer claim under it is already
NoFlag, whose close-candidate flags can reach two states with no transition that clears them #179 clearance consumes it; and on a PR the un-flagged label isVetterClose, a verdict in force that nothing here may retire (Close-candidate vetting misses PR-shaped flags: gh search issues scopes to type:issue #211). Reading a strayhuman:*as a tear there would erase the vetter's own judgement.Where both marks somehow coexist, the close wins — not a new precedent, but the one
human_close_planalready writes down by superseding every standinghuman:*ruling.Counts bucket removed, invariant kept. Field,
"humanRuled"emission, increment arm, key-list entry, doc line, and both test fixtures.tornHumanClose→tornHumanRuling;completedHumanClose/humanCloseCompletionFailedand their arrays follow the rename (no consumer outsidemain.rs— checked across the whole repo). The partition assertion survives in reduced form and is what proves the deleted rows were re-homed rather than dropped:The fixture's
o/ruledrow (ai:close-candidate+human:keep-open+ a live flag) is the row that used to sit inhuman_ruled; the tuple assert is what names where it went. Strengthened on the wire side too:countsmust not emithumanRuledat all, and the emitted key count is asserted against the partition list rather than trusted to have been kept in step.README fossil deleted.
humanRulednamed a bucket with no code —DesignQueueCountshas no such field,DesignHithas three arms,nd_hit_classnever reads labels. Since Carry next_design's split on the human-queue design lane, so the dashboard can show the inbox apart from the defect #243 emits the design breakdown for the dashboard, it would have had someone wiring a field that never arrives./nddstale sentence deleted. There is noexcludedkey; replaced with the shape that is actually emitted (counts.draft, listed inwithheld).human-fsmbumped 0.16.0 → 0.16.1 in both the manifest and the marketplace listing, per the version-hygiene gate.Retained exactly as the issue directs:
pr_human_sacred/human_ruled_at_head/humanSacred/humanRuledAtHead,has_human_rulingin the flag-refusal path (and as thehumanSacredrow field), andTornHumanCloseas a concept. Nothing needed to be raised — no retained item had to move for the rest to cohere.QA
Discriminating tests:
queue_tests::a_human_ruling_beside_a_live_flag_is_a_torn_write_the_state_load_completes(the issue's stated acceptance case),human_rule_tests::the_completion_closes_only_where_a_close_was_actually_ruled,human_rule_tests::no_issue_ruling_lands_while_leaving_a_live_flag,next_close_candidate_tests::{a_torn_human_ruling_dominates_the_flag_lifecycle, a_torn_ruling_dominates_and_a_flagless_label_is_stranded, the_flag_counts_partition_the_whole_population_after_the_fan_out, the_envelope_states_what_the_page_left_behind, a_pr_close_verdict_is_human_owned_not_stranded_and_not_cleared},human_rule_tests::every_tear_point_lands_where_machinery_can_finish_it. Fails on base — verified as mutant M1, which restores the deleted park as its owncc_gatearm and is therefore literally the pre-change behaviour: it kills 4 tests including the acceptance test. A base checkout cannot be used directly here because the change alterscc_gate's arity, so the new tests do not compile against it; M1 is the same proof without that confound. Suite: 1084 passed, 0 failed.Mutations applied (15 applied, 15 killed, 0 survivors; each run is the WHOLE suite with the number of tests actually run asserted non-zero — a name filter that matches nothing exits 0 and reads as "survived", which is how the first pass of this harness lied about M1–M6/M9/M12):
cc_gatetorn arm → the old park (pre-change behaviour)a_human_ruling_beside_a_live_flag_is_a_torn_write_…(+3)cc_gatetorn arm deletedevery_tear_point_lands_where_machinery_can_finish_it(+5)cc_gatetorn arm demoted below the lifecyclea_torn_human_ruling_dominates_the_flag_lifecycle(+5)torn_human_rulingdrops the recorded-close halfevery_tear_point_lands_where_machinery_can_finish_ittorn_human_rulingdrops the ruling-label half (Remove every human-ruled STATE: a human decision is a transition, not a bucket #244's half)the_completion_closes_only_where_a_close_was_actually_ruled(+3)torn_human_rulingdrops the live-flag guarda_pr_close_verdict_is_human_owned_not_stranded_and_not_clearedtorn_ruling_completionbranch invertedthe_completion_closes_only_where_a_close_was_actually_ruledtorn_ruling_completionnever closesthe_completion_closes_only_where_a_close_was_actually_ruledcc_rowreports the torn state as an ordinary skipa_human_ruling_beside_a_live_flag_is_a_torn_write_…(+1)unvetted(sum still holds)the_flag_counts_partition_the_whole_population_after_the_fan_outhumanRuledre-emitted as a constant zerothe_envelope_states_what_the_page_left_behind(+1)a_clearance_comment_is_not_a_flag_a_verdict_or_a_prior_note(+2)keep-openstops clearing the flag it contradictsno_issue_ruling_lands_while_leaving_a_live_flag(+1)FLAG_DISPOSING_RULINGSwidened to letneeds-worklandno_issue_ruling_lands_while_leaving_a_live_flag(+2)human_close_planstops retiring the pending flagno_issue_ruling_lands_while_leaving_a_live_flag(+1)M10 is the one that matters most for item 4: it preserves the partition sum, so only the per-bucket assertion can catch a bucket quietly absorbing the deleted one's rows — and it does.
Oracle: the issue's own ruling text (thedavidmeister, 2026-08-09) — "human decisions are transitions to a state, not a separate state, so nothing may sit in a bucket whose meaning is 'a human already ruled here'" — plus
CcGate::TornHumanClose's pre-existing doc, which already stated the target posture verbatim ("the vetter's state-load EXECUTES the recorded close … and the human's queue never sees the subject"). Expected values are derived from those statements and from the write ORDERhuman_rule_steps/human_close_stepsalready pin, never recomputed with the classifier under test.Category check: issue enumerates six items; all six covered (1 delete, 2 verified-already-true + property pinned, 3 generalise+rename, 4 counts+invariant, 5 README, 6
/ndddoc). The three explicitly-retained items are untouched, verified by reading each rather than by grep.Verification:
nix develop .#rust -c cargo test(1084 passed),cargo fmt --all -- --check(clean — confirmed clean onmainfirst, so no reformat is included), and CI's exact static invocationcargo clippy --all-targets --all-features -- -D warnings -D clippy::allafter touching the file so a warm target cannot mask a lint.pre-commitis not wired in this repo (no.pre-commit-config.yaml).🤖 Generated with Claude Code