Repository navigation
The issue Lifecycle as data, checked for termination - #59
Conversation
Slice 0 declares the issue Lifecycle of design section 4.1, merged by the pull request "Design the issue Lifecycle: triage, Readiness, the hand-over to a pull request, and its bounds" (number 22), and proves that it terminates. - lifecycle/issue.json: nine States, two terminal, 65 transitions. The 32 arrows drawn, two of them made by the Factory or a person alike; every arrow the prose under the diagram declares; and five the derivation table allows that the text does not state, named in the pull request as open questions. - Bounds: max_attempts on ready to in_progress and back; max_unmerged_closes on in_progress or in_review back to ready or triage; max_runs_per_item on triage to ready. The Lifecycle schema accepts max_unmerged_closes, and its number, one, is in config/defaults.json beside the others. - tools/check_lifecycle.py: run(root) checks every file under lifecycle/, requires one for each Work item the schema names, and requires each bound to be a limit in config/defaults.json. check(lc) checks one Lifecycle. - The counter-example: with max_attempts taken off, the Factory can cycle from ready to in_progress and back, and the check says so. The same for max_unmerged_closes. Not here: the Kernel's derivation and Admission for an issue, and issues in the simulator. The check still cannot see max_runs_per_item, whose cycle passes through an edit. make verify: 121 tests (5 expected to fail), 7 checks. python3 -m tools.mutants: 20 of 20 killed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… bad data From the review of the previous commit, which found no blocker. - An issue's not_served is not terminal, and nothing stopped the Factory leaving it: a transition from not_served to ready by the Factory passed. The States only a person, or the platform acting for one, may leave are now data: person_only_exits in each Lifecycle, accepted by the schema. The pull request's lists held; the issue's lists held and not_served. The check refuses a Lifecycle that has held and does not list it. - tools/check_lifecycle.py validates each Lifecycle against its schema before checking it, and reports a file that is not a Lifecycle, a transition with a field missing, or a configuration or schema it cannot use, instead of raising. Unchanged: only a transition by the Factory counts toward an unbounded cycle. That is the story "Lifecycle check: bounds in the data for every cycle with no person in it". make verify: 124 tests (5 expected to fail), 7 checks. python3 -m tools.mutants: 20 of 20 killed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 14 minutes. View limit details
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 |
|


Part of the epic "Epic: slice 0, foundations. The repo holds the line, its context is tested, and the platform facts are recorded".
Declares the issue Lifecycle of design §4.1 as data beside the pull request's, and proves that it terminates. The design merged in the pull request "Design the issue Lifecycle: triage, Readiness, the hand-over to a pull request, and its bounds", through the merge queue, after a third, narrow check that found no blocker.
What changes
lifecycle/issue.json: nine States (new,triage,ready,in_progress,in_review,held,not_served,done,declined), withdoneanddeclinedterminal, and 65 transitions. The 32 arrows drawn, two of them made by the Factory or a person alike; every arrow the prose under the diagram declares ("Any State butdonemay move todeclined…"); and eight the derivation table allows that neither the diagram nor the prose states, listed below.max_attemptsonreadytoin_progressand back;max_unmerged_closesonin_progressorin_reviewback toreadyortriage;max_runs_per_itemontriagetoready. The Lifecycle schema acceptsmax_unmerged_closes, and its number, one ("starting at one"), is inconfig/defaults.jsonbeside the other limits.person_only_exits, accepted by the schema. The pull request's Lifecycle listsheld; the issue's listsheldandnot_served, which for an issue is not terminal. The check refuses a transition out of one of them by the Factory or a Lens, and a Lifecycle that hasheldand does not list it. "Only a person, or the platform acting for one" is kept: the pull request's Lifecycle releases a Hold toverifyingby the platform.tools/check_lifecycle.py:run(root)checks every Lifecycle underlifecycle/, requires one for each Work item the schema names, and requires each bound to be a limit inconfig/defaults.json. It validates each against the Lifecycle schema first, and reports malformed data rather than raising.check(lc)checks one. Until nowmake verifyloaded the pull request's alone.max_attemptstaken off, the Factory can cycle fromreadytoin_progressand back, and the check rejects it. The same holds formax_unmerged_closes. It is a test of the check, as the pull request's Lifecycle counter-examples are, because a Lifecycle with no bound is still valid against the schema.Not here: the Kernel's derivation and Admission for an issue, and issues in the simulator. Those are the three stories that follow.
A known gap. Deleting
max_runs_per_itemfromtriagetoreadypasses every check today. Its cycle goes back throughreadytotriage, which a person makes, and the check counts only cycles made wholly by the Factory. That belongs to the story "Lifecycle check: bounds in the data for every cycle with no person in it" (number 38).Open questions
new,triage,ready,heldandnot_servedtodone, by a person: row 1 ranks first, so merging a linked pull request ends the issue from any State.readytoin_review, by a person who opens their own pull request that is not a draft (rows 6 and 8).triagetoheldby the Factory when the Run ceiling is reached (row 4, "The Kernel holds the issue"). The design drawstriagetoheldonly as a person's act.newtotriageby a person with write access who addsfactory:triage(I-41).in_reviewis stale "as its pull request". The schema takes one number, soin_review: 30borrows the stale time ofverifying, the State a pull request enters when marked ready.human. So is the content change behindreadytotriage, which is made by a writer, since an outsider's edit lapses acceptance. The trial script usedplatformfor it; no check result depends on the choice.human, as in the pull request's Lifecycle, though GitHub carries out a commit's closing keyword.For the Kernel stories
in_progresstoreadyby the Factory is declared twice, with different bounds:max_attemptswhen an opening Run ends having opened nothing, andmax_unmerged_closeswhen a linked pull request closes unmerged. The Kernel must tell the two causes apart from the facts, and count each against its own bound.heldfrom conditions that can clear with no person acting: the Run ceiling is counted over a window, soheldcan end when Runs age out of it. That contradictsheldinperson_only_exits. It needs a simulator test in the story for issues in the simulator (number 43).Verification
make verify: 124 tests (5 expected to fail), 7 checks, all ok.python3 -m tools.mutants: 20 of 20 killed.tests/test_tools.pyfailed before the change it tests: the counter-example formax_attempts, the planted transition fromnot_servedtoreadyby the Factory, and a Lifecycle that is a JSON list or has a transition missingby.Closes #18
🤖 Generated with Claude Code