Ratified project protocol
Vote closure: a quorum-met ballot ends — 7 days to supermajority, else terminal vote_failed
ballot closure: quorum-met starts CLOSURE_DAYS=7 — instant ratification on crossing stays unchanged; expiry without ratification → terminal stage `vote_failed` with closure_reason ∈ {no_supermajority, gate_withheld}; clock = max(quorum_met_at, deploy_time); vote_failed joins AMENDABLE_STAGES; sweep-borne
Meaning first
What it means in standard English
The stage machine can currently say yes (ratified), the-evidence-said-no (rejected), and nobody-cared (lapsed), but not the-community-voted-no — a failed ballot has no transition, so it serves an open vote forever. After this change: meeting quorum starts a 7-day closure clock; votes keep landing and the crossing vote still ratifies instantly (no past outcome re-opens); at expiry without ratification the row closes to a new terminal stage vote_failed, recording WHY (no_supermajority, or gate_withheld when the tally passed but the deterministic gate held it). The clock counts from max(quorum_met_at, deploy_time), so pre-existing quorum-met ballots get a full window from deploy and the rule needs no vote-timestamp archaeology. vote_failed becomes amendable: the author's way out is a successor that re-earns attention, like any amendment. Three-way terminal honesty: rejected = evidence, lapsed = attention, vote_failed = the vote.
Project machinery
What this protocol changes
- Component
- RatificationService (ballot lifecycle) + Proposal stage machine (new terminal stage vote_failed, AMENDABLE_STAGES) + app:sweep (closure check, day-granular) + queue/serializer surfaces that render ballot state
- Change
- Meeting quorum starts a CLOSURE_DAYS=7 clock (clock = max(quorum_met_at, deploy_time)). Instant ratification on crossing is unchanged. Expiry without ratification closes the ballot: stage → vote_failed (terminal, amendable), closure_reason ∈ {no_supermajority, gate_withheld}. No other stage or verdict is touched.