diff --git a/.trinity/seals/queen_QueenDispatch.json b/.trinity/seals/queen_QueenDispatch.json index d9b50ef3e2..541c1f4503 100644 --- a/.trinity/seals/queen_QueenDispatch.json +++ b/.trinity/seals/queen_QueenDispatch.json @@ -1,17 +1,17 @@ { - "built_by": "t27c-bootstrap@0.5.2+0bc75496f", + "built_by": "t27c-bootstrap@0.5.2+cd8a65666", "closure": [], "config": "gen=c,rust,verilog,zig;tests=zig", - "gen_hash_c": "sha256:701a7f17bd239bbdce3e4f59439dcc1a1dc3fe67117c668a2b71416ac92ea3a4", + "gen_hash_c": "sha256:569ee0da3c4ac2216fdd639840a059a119376bb09bfa08c01d21e43dac19066e", "gen_hash_rust": "sha256:6d3d23f0b154c24eb7a7be981bd4e86102cf3b4c7d0e8c9d1abc7a3ccb4ae3c4", "gen_hash_verilog": "sha256:777365a370267d026113c4fca91848328f24347719f7bc971119d1f41e2abc43", - "gen_hash_zig": "sha256:e9cdf5547bd9e9d576fb53dc29f9471a266f5d18509fd1d34e60aa26ebf5a77b", + "gen_hash_zig": "sha256:c7489368d1352dfa04dc4fc8ad044fe301e2ed14a42167d50a348d076e93c3df", "module": "QueenDispatch", "ring": 12, "seal_schema": 2, - "sealed_at": "2026-10-11T14:04:06Z", + "sealed_at": "2026-10-17T14:18:25Z", "sealed_by": "t27c-bootstrap@0.5.2", - "spec_hash": "sha256:a894dc6f0a7f41f0665ac48b6435365ee25e9fdae44b7d3b3e8a367880dbed45", + "spec_hash": "sha256:e71997bc00e5e3c6fffc1d92d0ea1e73c09326215533f7bdec6a27ed9fffd7fe", "spec_path": "specs/queen/dispatch.t27", "tests": { "failed": 0, @@ -19,7 +19,7 @@ "forced": false, "passed": 13, "total": 13, - "vacuous": 1 + "vacuous": 0 }, "toolchain": { "test_runner": "sha256:1982ae948e24d00c5d221ccec12dfce1eb01204b53e37b0f857f93b16d64629d", diff --git a/specs/queen/dispatch.t27 b/specs/queen/dispatch.t27 index ff39a4363c..42911bfbb6 100644 --- a/specs/queen/dispatch.t27 +++ b/specs/queen/dispatch.t27 @@ -392,6 +392,28 @@ test the_table_moves_only_along_its_guards { assert next_state(S_REAPED, E_CRITERIA_CHANGED) == ILLEGAL; assert next_state(S_STALE, E_REDISPATCH) == S_RUNNING; assert next_state(S_RUNNING, E_END_OTHER_TURN) == ILLEGAL; + // Every legal transition, once each: a guard no assert reaches can be dropped unnoticed (#9886). + assert next_state(S_NONE, E_REFUSE) == S_REFUSED; + assert next_state(S_NONE, E_END) == ILLEGAL; + assert next_state(S_RUNNING, E_REAP_STALL) == S_REAPED; + assert next_state(S_RUNNING, E_REAP_BOOT) == S_REAPED; + assert next_state(S_ENDED, E_VERDICT_ACCEPT) == S_ACCEPT; + assert next_state(S_ENDED, E_VERDICT_SENDBACK) == S_SENDBACK; + assert next_state(S_ENDED, E_VERDICT_ESCALATE) == S_ESCALATE; + assert next_state(S_ENDED, E_VERDICT_WAIT) == S_WAIT; + assert next_state(S_ENDED, E_VERDICT_EMPTY) == S_EMPTY; + assert next_state(S_ENDED, E_CRITERIA_CHANGED) == S_STALE; + assert next_state(S_ENDED, E_FLOOR_PASSED) == S_RELEASED; + assert next_state(S_WAIT, E_VERDICT_ACCEPT) == S_ACCEPT; + assert next_state(S_ACCEPT, E_CI_RED_UNDER_CEILING) == S_SENDBACK; + assert next_state(S_SENDBACK, E_CRITERIA_CHANGED) == S_STALE; + assert next_state(S_SENDBACK, E_FLOOR_PASSED) == S_RELEASED; + assert next_state(S_EMPTY, E_CRITERIA_CHANGED) == S_STALE; + assert next_state(S_SENDBACK, E_START) == ILLEGAL; + assert next_state(S_ESCALATE, E_CRITERIA_CHANGED) == S_STALE; + assert next_state(S_REAPED, E_REDISPATCH) == S_RUNNING; + assert next_state(S_REFUSED, E_REDISPATCH) == S_RUNNING; + assert next_state(S_RELEASED, E_REDISPATCH) == S_RUNNING; } test a_claim_follows_the_verdict_and_three_clocks { @@ -404,6 +426,16 @@ test a_claim_follows_the_verdict_and_three_clocks { assert claim_of(true, V_SENDBACK, 3600000, 2, releases_read_by_round(1)) == C_FAILED; assert claim_of(true, V_WAIT, 21600000, 0, 0) == C_FAILED; assert claim_of(true, V_ESCALATE, 999999999, 0, 0) == C_AWAITING_REVIEW; + // #9886: each verdict that frees the issue, the send-back floor at its edge with a release + // already spent, and the wait floor's two edges. + assert claim_of(true, V_FAILED, 0, 0, 0) == C_FAILED; + assert claim_of(true, V_CANCELLED, 0, 0, 0) == C_FAILED; + assert claim_of(true, V_STALE, 0, 0, 0) == C_FAILED; + assert claim_of(true, V_SENDBACK, 3600000, 1, 1) == C_FAILED; + assert claim_of(true, V_NONE, 21600000, 0, 0) == C_FAILED; + assert claim_of(true, V_BLANK, 21600000, 0, 0) == C_FAILED; + assert claim_of(true, V_WAIT, 21599999, 0, 0) == C_AWAITING_REVIEW; + assert claim_of(true, V_WAIT, 21600000, 2, 0) == C_AWAITING_REVIEW; } test a_closed_issue_is_drawn_done_whatever_its_verdict { @@ -411,12 +443,16 @@ test a_closed_issue_is_drawn_done_whatever_its_verdict { assert column_of(C_AWAITING_REVIEW, true, true) == COL_REVIEW; assert column_of(C_RUNNING, false, true) == COL_RUNNING; assert column_of(C_FAILED, true, true) == COL_DROPPED; + assert column_of(C_ACCEPTED, true, true) == COL_DONE; } test the_first_eligible_wins_in_any_order { assert chosen_of(false, false, true, true, false) == 2; assert chosen_of(false, true, false, false, true) == 1; assert chosen_of(false, false, false, false, false) == NONE_CHOSEN; + assert chosen_of(true, true, false, false, false) == 0; + assert chosen_of(false, false, false, true, true) == 3; + assert chosen_of(false, false, false, false, true) == 4; assert can_start(3, DEFAULT_WORKER_LIMIT) == true; assert can_start(4, DEFAULT_WORKER_LIMIT) == false; } @@ -432,6 +468,7 @@ test review_escalates_without_work_and_after_two_send_backs { assert retry_allowed(1) == true; assert retry_allowed(2) == false; assert counts_against_issue(true) == false; + assert counts_against_issue(false) == true; } test one_lease_one_owner_and_age_alone_reaps { @@ -442,7 +479,10 @@ test one_lease_one_owner_and_age_alone_reaps { assert owners_per_term() == 1; assert stall_reapable(121) == true; assert stall_reapable(119) == false; + // The comparison is strict: 120 is not reapable. f58 measured 119 and 121, not 120 itself. + assert stall_reapable(120) == false; assert followup_rounds(5) == 1; + assert followup_rounds(0) == 0; assert accept_requires_pull_request() == false; assert writer_enforces_table() == false; } @@ -458,6 +498,10 @@ test end_reason_constants_are_correct { assert R_PUSH_FAILED == 5; assert R_UNKNOWN == 6; assert END_REASON_COUNT == 7; + // The lines above fold at comptime, so this test ran 0 runtime asserts (#9886); these two + // call the functions that read the constants: the last reason is named, one past it is not. + assert end_reason_to_name(END_REASON_COUNT - 1) == "unknown"; + assert is_valid_end_reason(END_REASON_COUNT) == false; } test end_reason_names_array_matches_constants {