Skip to content

spec(queen): a long wait is a row in the store, not a process -- waits.t27 (Closes #8270) - #8272

Merged
gHashTag merged 1 commit into
masterfrom
spec/queen-waits
Oct 9, 2026
Merged

gHashTag merged 1 commit into
masterfrom
spec/queen-waits

Conversation

@gHashTag

@gHashTag gHashTag commented Oct 9, 2026

Copy link
Copy Markdown
Owner

Closes #8270

A long wait of the Queen becomes a row in the store, decided by a new card, specs/queen/waits.t27. The runtime (a queen_wait table, a scheduler actor, the release job's CI step) is a separate PR in gHashTag/trios on actors-next, part of gHashTag/trios#1712 (item 4).

Why (measured)

  • The swarm's first release, job feat(ring-0): frozen stage-0 + first green parse [SEED-0] #3 (t27c 0.5.2, 2026-10-09), spent about 90 of its 92 minutes at step 3, release-workflow, waiting for a runner.
  • That WAIT step is asked again by every round: one GitHub read and one entry appended to the job's log per round (a round about every 30 s), so about 180 of each for one wait. The wait moves only while a process runs rounds.
  • A Queen deploy drains for 1800 s.

What the card decides (22 pub fns)

Rule Functions
States and transitions: only a WAITING row moves; RESOLVED, EXPIRED, CANCELLED are terminal is_terminal, state_after, transition_allowed, valid_wait
Wake rule: due when the wake time passed or the key resolved (or the expiry passed); a resolution beats a late expiry; a keyed row's wake time is a CHECK wake_action, due_in_seconds (agrees with wake_action on a 72-row grid)
Who hears it: a resolution or an expiry wakes the owner, once, only through the write that landed wakes_owner, delivers_wake
Expiry cap: one day; a job's wait keeps the step's first deadline expiry_seconds, job_wait_seconds
Checking a key (a CI run): 30 s doubling to 240 s, never past the expiry check_after_seconds, recheck_in_seconds, check_event
Fencing: a claim bumps the epoch; a write at a stale epoch lands nothing epoch_after_claim, write_lands, more_now
Poll 15 s; NOTIFY is a hint and never replaces the poll poll_seconds, beat_after_seconds, pass_on_hint
A deploy writes nothing to waits; a claimed row waits out its 60 s claim pickup_after_seconds, DEPLOY_WRITES_WAITS
A job parked on a waiting row is not visited by the round round_visits_job, step_outcome

Checks

  • t27c parse, typecheck, gen-rust, gen-verilog, gen-c, gen-js: exit 0 each.
  • t27c test-report specs/queen/waits.t27: 12 tests, 12 pass, 0 FAIL; 2 invariants proved at comptime; vacuous passes 0 of 12 (runtime asserts per test: 24, 16, 4, 10, 14, 79, 11, 14, 10, 14, 5, 10).
  • t27c gen-c + zig 0.16.0 cc --target=wasm32-wasi -Oz -DNDEBUG -mexec-model=reactor, every fn exported: two builds, one hash, 5068962a983f229fb4c472a1f29a62366de8afd0b16abb50dacdcb19877ea32c.
  • t27c seal --save: .trinity/seals/queen_QueenWaits.json.

Negative controls

Each rule broken once on a copy, t27c test-report run, then restored (the committed file is untouched).

# Break Result
1 a terminal row moves (state_after drops its guard) FAIL only_a_waiting_row_moves, every_transition_the_events_make_is_allowed
2 RESOLVED -> EXPIRED allowed FAIL only_a_waiting_row_moves
3 a wait with neither key nor wake time is valid FAIL a_wait_names_what_ends_it
4 a cancel wakes the owner FAIL only_a_resolution_or_an_expiry_wakes_the_owner_and_only_once
5 a refused write still wakes FAIL only_a_resolution_..., a_stale_epoch_writes_nothing
6 expiry checked before resolution FAIL a_row_is_due_when_its_time_passed_or_its_key_resolved
7 a keyed row resolves at its wake time (no check) FAIL a_row_is_due_...
8 the due time ignores the expiry FAIL the_due_time_agrees_with_the_wake_rule
9 no expiry cap FAIL a_wait_never_outlives_the_cap
10 a job's wait restarts its deadline FAIL a_wait_never_outlives_the_cap
11 checks never back off FAIL a_keyed_row_is_checked_less_and_less_but_never_past_its_expiry
12 a re-armed check overshoots the expiry FAIL a_keyed_row_is_checked_...
13 a finished run rechecks FAIL a_keyed_row_is_checked_...
14 a claim does not bump the epoch FAIL a_stale_epoch_writes_nothing
15 a stale epoch lands FAIL a_stale_epoch_writes_nothing
16 a full batch waits a beat FAIL a_stale_epoch_writes_nothing
17 NOTIFY replaces the poll (poll_seconds(true) = 0) FAIL notify_brings_a_pass_forward_and_the_poll_stays
18 the beat ignores the nearest due row FAIL notify_brings_...
19 hints are not coalesced FAIL notify_brings_...
20 a stopping process releases its claims (pickup 0) FAIL a_deploy_leaves_waiting_rows_to_the_next_process
21 the round visits parked jobs FAIL a_job_parked_on_a_row_waits_off_the_round
22 an expired wait passes the step FAIL a_job_parked_on_a_row_waits_off_the_round
23 WAIT_POLL_SECONDS 15 -> 90 BLOCKED at comptime: invariant the_clocks_fit_inside_each_other
24 CHECK_CAP_SECONDS 240 -> 480 BLOCKED at comptime: same invariant
25 CLAIM_TTL_SECONDS 60 -> 30 BLOCKED at comptime: same invariant

Not established here: the runtime and its benchmark. They are in the gHashTag/trios PR for item 4 of trios#1712, and the numbers go on #7851.

🤖 Generated with Claude Code

…s.t27 (Closes #8270)

Measured 2026-10-09: the swarm's first release (job #3, t27c 0.5.2) spent
about 90 of 92 minutes at step 3, release-workflow, waiting for a runner.
That WAIT step is asked again by every round: one GitHub read and one log
entry per round, about 180 of each for one wait, and the wait moves only
while a process runs rounds. A Queen deploy drains for 1800 s.

New card specs/queen/waits.t27 (module QueenWaits, 22 pub fns):
- states WAITING/RESOLVED/EXPIRED/CANCELLED; state_after, transition_allowed,
  is_terminal: only a waiting row moves.
- wake rule: wake_action (resolution first, then expiry, then the wake time;
  a keyed row's wake time is a CHECK, a keyless row's is its answer) and
  due_in_seconds, which agrees with it on a 72-row grid.
- expiry cap: expiry_seconds (one day), job_wait_seconds (a job step keeps
  its first deadline).
- checks of a key: check_after_seconds 30 s doubling to 240 s,
  recheck_in_seconds never past the expiry, check_event. The 90-minute wait
  costs 24 reads instead of about 180.
- fencing: epoch_after_claim, write_lands; delivers_wake only for the write
  that landed; more_now for a full batch.
- poll and NOTIFY: poll_seconds ignores whether the host listens,
  beat_after_seconds, pass_on_hint (coalesced).
- deploy: DEPLOY_WRITES_WAITS false, pickup_after_seconds (a claimed row
  waits out its 60 s claim, any other is taken at once).
- jobs: round_visits_job (a parked job is not visited), step_outcome.

Checks (this commit):
- t27c parse, typecheck, gen-rust, gen-verilog, gen-c, gen-js: exit 0 each.
- t27c test-report: 12 tests, 12 pass, 0 FAIL, 2 invariants proved at
  comptime, vacuous passes 0 of 12.
- gen-c + zig 0.16.0 wasm32-wasi, every fn exported: two builds, one hash
  (sha256 5068962a983f229fb4c472a1f29a62366de8afd0b16abb50dacdcb19877ea32c).
- 25 negative controls (each rule broken once, then restored): 22 make a
  named test FAIL, 3 constant changes block compilation at the invariant.
- t27c seal --save: .trinity/seals/queen_QueenWaits.json.

Not established here: the runtime. It is a separate issue in gHashTag/trios
(part of trios#1712, branch actors-next).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@gHashTag
gHashTag enabled auto-merge (squash) October 9, 2026 17:14
@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-10-09 17:15:01 UTC

Summary

Status Count
Total Open PRs 50
PRs with Failing Checks 49
PRs with All Checks Green 1
READY 0
FAILING 49
PENDING 0
NO CHECKS YET 0

These columns do not partition: 0 + 49 + 0 + 0 = 49, and there are 50 open PRs. A PR is being counted twice or not at all.

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=557cd271f4e3 != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

spec(queen): long waits as rows in the store -- waits.t27

2 participants