Each queue act is a dispatched Run of the queue workflow, once it is named (queue step, part 1)
Merged
DO
7d ago+416+416+012345678901234567890123456789-68-68-01234567890123456789
Part of #381, "A narrow queue App, combsmith-sf-queue, enqueues and dequeues with contents and pull-request write alone (P-2)": the queue step's first part of three. Record 0128, on the Factory Builder's word. Part of #182.
Each of the queue App's acts, an enqueue, a dequeue and a resolution, becomes a dispatched Run of the queue workflow, as an approval is a Run of the approval workflow. Nothing changes live yet. workflows.queue stays null, so each act is still recorded not_built until parts 2 and 3 land the step and its workflow. accounts.queue must also be set, which waits on P-39's re-read.
For the Maintainer's review: protected paths edited
kernel/brakes.py:- A landed enqueue or dequeue Run is outside the Run ceiling, as a landed approval is, since the timeline already counts both among the acts.
- A failing enqueue is held by its own jobs alone: its attempts, then its own Runs at
max_runs_per_item. An existing rule (FR-39) lets an approved item's enqueue go ahead at the Run ceiling, so this is not the shared ceiling a failing resolution meets. - A dequeue's own jobs that keep failing hold the item at the Run ceiling, for the Maintainer to stop the merge.
config/controller.json:workflows.queue: null.
What changes
| Where | What changed |
|---|---|
kernel/terms.py, adapters/records.py | Intents enqueue-merge and dequeue-merge, read as a pull request's Runs, which ask for no contract |
kernel/decide.py | A dequeue waits on its own job in flight, and is never sent beside it; another Intent's Run in flight still never delays it |
controller/writes.py | QUEUE_INTENTS; queue_workflow, the queue file only when its account is set beside it; the plan's dispatch_queue writes |
controller/pass_.py | Once the queue workflow is named, a Run id is minted for each queue act and it is dispatched under its Intent's run-name |
adapters/effects.py | The pass job's token may dispatch the queue file once it is named, with the three inputs a Run takes; expected holds the plan to its record |
adapters/facts.py, controller/__main__.py, harness/read.py, harness/reread.py | run_files_of: every Run list reads the queue file once it is named |
controller/reconcile.py | A queue act's dispatch is matched to its pass's record |
schemas/, examples/invalid/ | controller/1's workflows.queue; dispatch_queue in writes/1 and written/1 |
tools/mutants.py | 43 mutants this story touches, each killed by its test when run alone on the final tree |
| Records and docs | 0128 is new; the design's line that enqueue and dequeue have no run record, and that the Controller's App dequeues, now says the queue App's Runs |
Declined
- An unidentified Run deferring queue acts (security #4). Record 0036 lets an unidentified Run stop no enqueue. A second queue Run sent while the first is unnamed is answered by the queue step in part 2, which reads the item again and sends nothing it finds done.
Parts 2 and 3
- Part 2, the harness:
harness/queue_step.pymints fromQUEUE_APP_KEY, finds the Decision by Run id, reads the item again, asksstill_wanted, makes the one write and reads it back, and recordsapplied/1andoutcome/1. The enqueue is bound to the decided head byexpectedHeadOid, which is owed to a trial the Release lane is recording. Reconciliation will match the queue App's writes to that record. - Part 3, the workflow:
queue.ymlandqueue-job.ymlinfactory-queue, thecheck_workflowsrules for them, and namingworkflows.queue.
Verify
make verifyon an export of 9dbc8af: 1,526 tests, all OK but one.tests.test_hooks.Identity.test_the_spellings_that_ran_long_are_read_in_linear_time, which times the identity hook's CPU and which this change does not touch, failed under load (3.23 s against 1.31 s at half). It then passed alone three times of three.make verifyon an export of the merged head c0313fa: 1,526 tests OK (8 expected failures), the timing test among them. CI is green there.- The 43 mutants this story touches were each run on their own on the final tree and killed; every mutant's text appears once and compiles, and no two share a name. The full mutant run is CI's.
Reviews
All four read 8f1b73e. The fix round is 9dbc8af; nothing has re-read it.
| Reviewer | Head | Unread parts | Blocking | Major | Minor | Info |
|---|---|---|---|---|---|---|
| claude-review | 8f1b73e | none | 0 | 3 | 2 | 0 |
| claude-security | 8f1b73e | none | 0 | 1 | 3 | 0 |
| agy (parts 1, 3, 4 and 5: high; part 2: medium fallback) | 8f1b73e | none | 0 | 5 | 2 | 0 |
| muse | 8f1b73e | none | 0 | 3 | 0 | 0 |
| Finding | Severity | Criterion | Where | What | Disposition |
|---|---|---|---|---|---|
| claude-review#1 | major | PR-3 | controller/pass_.py:292 | A dequeue is minted and dispatched again every pass while its own Run is still in flight, and after any number of failures | fixed in 9dbc8af: the Kernel waits on a dequeue's own job in flight, and its jobs that keep failing hold the item at the Run ceiling |
| claude-review#2 | major | PR-3 | controller/reconcile.py:41 | dispatch_queue in reconcile's DISPATCHES has no test; the mutant that drops it survives | fixed in 9dbc8af: a reconcile case and a mutant |
| claude-review#3 | major | none | docs/decisions/0128-each-queue-act-is-a-dispatched-run-of-the-queue-workflow-once-it-is-named.md:12 | A landed enqueue or dequeue counts nowhere when workflows.queue is named before accounts.queue | fixed in 9dbc8af: the queue file is used only once accounts.queue is set too, so a landed enqueue or dequeue is counted among the acts |
| claude-review#4 | minor | none | controller/AGENTS.md:12 | Rule 'A Run id is minted for an admission or an approval alone' is now false once workflows.queue is named, and is not updated | fixed in 9dbc8af: controller/AGENTS.md, the design and pass/1's title name the queue acts |
| claude-review#5 | minor | PR-3 | kernel/brakes.py:122 | A cancelled or never-started enqueue Run counting toward the Run ceiling is not held by a test | fixed in 9dbc8af: cancelled enqueue jobs reach the Run ceiling; a case |
| claude-security#1 | major | PR-3 | controller/pass_.py:268 | Naming workflows.queue while accounts.queue is null leaves landed enqueues and dequeues counted by neither ceiling | fixed in 9dbc8af: as claude-review#3 |
| claude-security#2 | minor | PR-3 | controller/pass_.py:292 | A dequeue is now an unbounded Run, dispatched again on every pass even while an earlier dequeue Run is in flight | fixed in 9dbc8af: as claude-review#1 |
| claude-security#3 | minor | PR-3 | controller/reconcile.py:41 | Reconciliation of a dispatch_queue write has no test: a mutant dropping it from DISPATCHES survives | fixed in 9dbc8af: as claude-review#2 |
| claude-security#4 | minor | none | kernel/decide.py:97 | Enqueue and resolution are now Runs but skip the unidentified-Run deferral that decision 0036 gives every Run | declined: record 0036 lets an unidentified Run stop no enqueue, and changing it would hold every enqueue; the queue step (part 2) reads the item again and sends nothing it finds done, which answers a second Run sent while the first is unnamed. Record 0128 says so |
| agy#1 | major | PR-3 | docs/decisions/0128-each-queue-act-is-a-dispatched-run-of-the-queue-workflow-once-it-is-named.md:14 | Failing dequeue-merge Runs are unbraked and dispatch without bound once workflows.queue is named | fixed in 9dbc8af: as claude-review#1 |
| agy#2 | major | PR-3 | tools/mutants.py:4754 | Mutant "an approval's failed attempts stop an enqueue" is a no-op once "enqueue" is in run_acts | declined: enqueue is not in run_acts at this head (its ceiling is enqueue_ceilings), so the repointed mutant is not equivalent; it is killed |
| agy#3 | major | PR-3 | tools/mutants.py:11826 | Six new kernel/brakes.py mutants name test_each_landed_resolution_counts_toward_the_act_ceiling instead of enqueue/dequeue tests | fixed in 9dbc8af: the enqueue and dequeue cases have a test of their own, which those mutants name |
| agy#4 | major | PR-3 | tools/mutants.py:11835 | kernel/brakes.py enqueue ceiling mutants omit >= boundary mutants and since/unlanded filter mutants | fixed in 9dbc8af: the >= boundary mutants for the enqueue's attempts and Run ceiling and the dequeue's Run ceiling |
| agy#5 | major | PR-3 | tools/mutants.py:11862 | No mutant holds dequeue / DEQUEUE_MERGE in adapters/records.py, controller/writes.py, controller/pass_.py, or adapters/effects.py | fixed in 9dbc8af: twins for the dequeue in the records port and the intent map |
| agy#6 | minor | PR-3 | docs/architecture/software-factory-design.md:1256 | An in-progress dequeue-merge Run does not defer subsequent passes from dispatching duplicate dequeue-merge Runs | fixed in 9dbc8af: as claude-review#1 |
| agy#7 | minor | PR-3 | tools/mutants.py:11857 | No mutant flips workflows['queue'] is not None to True in adapters/effects.py or controller/main.py | fixed in 9dbc8af: a mutant that permits the queue file with nothing named |
| muse#1 | major | PR-3 | controller/pass_.py:324 | A dequeue is re-dispatched as a new Run while its own dequeue-merge Run is still in flight | fixed in 9dbc8af: as claude-review#1 |
| muse#2 | major | PR-3 | controller/reconcile.py:41 | Reconciliation of a queue dispatch is unheld: dropping dispatch_queue from DISPATCHES survives every relevant test | fixed in 9dbc8af: as claude-review#2 |
| muse#3 | major | PR-3 | harness/reread.py:22 | The approving act's re-read never lists the queue workflow, so its Kernel re-ask is blind to queue Runs | fixed in 9dbc8af: the Run's read and the approving act's read again list the queue file too, through adapters/facts.py's run_files_of |
š¤ Generated with Claude Code