Repository navigation
Description
Problem
Two paths of the flow break when their parts meet, and no scenario plays them whole. After the autopilot stops, an edit of the PRD and a new acceptance leave needs-human on, and the G2 "Acceptance withdrawn" comment hides the stop from review-reply.yml, so a maintainer's answer is ignored (#694, 2026-11-08). The autopilot also asks again what a maintainer answered in a comment, because it reads the PRD alone. The release lane covers workflow events one by one, not the paths docs/model.md describes, so these combinations reach people instead of failing the lane.
Scope
- review-reply.yml finds the autopilot's stop past any later comment of the bot (a G2 "Acceptance withdrawn", a board), not only past the mention.
- An
acceptedadded again after a stop takesneeds-humanoff and the autopilot goes on. - The autopilot reads the answers of those who decide in the issue's comments together with the PRD, and does not ask again what they settled.
- A table in docs/ maps every path docs/model.md describes (a person's bug to its merge, a reproduced bug merged by policy, a feature accepted and built, a claim and its release, a stop answered, an edit after acceptance and the new acceptance, the release and its watch) and each setting that changes it (acceptance by policy,
who-decides, a claim, merge on its own or by a person, itsceiling) to the scenario that plays it, with the scenarios that are missing added.
Out of scope
The release lane's isolation, timing, formats and cost (#695).
Acceptance criteria
C1: Given an issue whose autopilot stopped, when its PRD is edited, accepted again and a person who decides answers in a comment, then the autopilot goes on without autopilot:continue and does not ask again what the answer settled; a scenario plays it.
C2: Given the table of paths in docs/, when release-scenarios.py --test runs, then every path and setting in it names a scenario of tests/release/scenarios.yml, and every one of those scenarios exists.
Criticality
Critical
🤖 AI-assisted · Claude Opus 5.5 (Anthropic)
Spec: approach
-
review-reply.yml finds the stop past the bot's other comments. The answer job no longer takes the bot's last comment (its mentions aside) and asks whether it is a stop. A new pure function in scripts/autopilot.py,
run_end(comments)(exposed asautopilot.py run-end, reading the comments as JSON on stdin), returns the bot's last comment that ends a run with a person: a stop (STOP), a silent end (SILENT), or a cap end. Any other comment of the bot is skipped: the G2 "Acceptance withdrawn" comment, the board (itsdx-boardmarker), its mention, a review record, and the rest. The cap ends (runs cap, rounds cap in autopilot.yml) get a marker of their own,dx-autopilot-cap, written likeSTOP. Without it a cap end could not be told apart and would not hide an older stop. They still stay with a person, as today. The job brings the autopilot back only whenrun-endsaysstoporsilent. Labels, who decides and the opinions path stay as they are. -
A new
acceptedafter a stop takesneeds-humanoff. In autopilot.yml, the run that a person'sacceptedstarts (start mode, once the seal matches and the acceptor may accept, i.e. after the checks it runs today) takesneeds-humanoff beforenext-step. It takes it off the issue and off the issue's open autopilot pull request, and only whenrun-endon that one's comments saysstoporsilent. A cap end keeps it, because the PRD's "stop" is the agent's stop, not a spent cap.next_stepthen decides as for any run: the Spec, the draft, or the work on the existing draft. Noautopilot:continueis needed. issue-accepted.yml is left alone: it keeps the seal and the board. -
The autopilot reads the deciders' answers with the PRD. In start mode, autopilot.yml now collects the issue's comments and their deciders (
deciders.py list answer) the same way it already does for the work.prompt_specgets anansweredargument, fenced like the work's<answer>. The Spec prompt drops "Read nothing else from the issue (not its comments…)" and says instead: the maintainers' answers below settle what they answer; do not ask again about it; where an answer and the PRD differ, the PRD wins, since it was sealed later. The work prompt says the same. Which comments count is a choice a maintainer would care about:- Option A: what
answers()keeps today, i.e. the deciders' comments after the bot's last question, stop, silent or unfinished end. It is small, but an answer to an earlier question is lost once a later question is asked, so that earlier question can be asked again. - Option B (recommended): every comment by a decider on the issue and its pull request since the first
accepted, in order, with/commands left out. Nothing they settled is lost across stops, edits and new acceptances, which is exactly C1's path. The prompt grows by those comments only, and anyone else's words still never reach it (the opinions' summary stays as it is). It would be a new pure functionsettled(comments, deciders, since)besideanswers().answers()stays what brings the autopilot back.
- Option A: what
-
The test repository's fixed change can ask. The test repository calls no model, so today no scenario ever stops. The pack gets
fixed-change.ask: "<phrase>"(kinds/engine-test/pack.yml). When the PRD carries that phrase and the deciders' answers (step 3) are empty, the fixed Spec step stops through the agent's helper (finish stop "…"), as a model would. With an answer, it goes on. Every scenario that does not use the phrase behaves exactly as before. With this,stop-hint-continuereally stops, and a C1 scenario that asks again fails. -
Scenarios and the table of paths. tests/release/scenarios.yml gets a
bodies:entryasking-feature(with the phrase) and its edited twin. It also gets these new scenarios (serial: they draft):stop-edited-reaccepted-answered(C1): accepted, wait, the Spec stops, the PRD is edited (G2), a decider answers in a comment, accepted again. Expected:needs-humanandautopilot:continueabsent, a pull request that closes it, and the stop marker exactly once. That last check is a newexpect.count: {marker: n}, which release-scenarios.py'spreconditionsandrunlearn.stop-answered: a stop answered in a comment alone, with no label.bug-by-person-merges: a bug a maintainer accepts, to its merge.stop-hint-continuekeeps its label and moves toasking-feature.
A new page, docs/paths.md, holds one table: path or setting → scenario ids. It covers every path docs/model.md describes:
- a person's bug to its merge
- a reproduced bug merged by policy
- a feature accepted and built
- a claim and its release
- a stop answered
- an edit after acceptance and the new acceptance
- the release and its watch
And every setting that changes them:
- acceptance by policy
who-decides- a claim
- merge on its own or by a person
- its
ceiling
The engine's own watch (release-lane.py watch) is not a test-repository scenario. Its row names
release-issue, and the page says the watch is held byrelease-lane.py --test. release-scenarios.py getspaths(table_text, scenario_ids): every row names at least one id, every id named exists, and every required path and setting has a row (the list lives in the script, from docs/model.md). It runs incoverage(the scripts job) and in--test, with fixtures for a missing row, an unknown id and an empty cell. docs/model.md links the page.
Nothing widens a permission, secret, lane or limit. In autopilot.yml, the start job's existing token removes needs-human, a label it already adds.
Spec: files
.github/workflows/review-reply.yml.github/workflows/autopilot.ymlscripts/autopilot.pyscripts/release-scenarios.pytests/release/scenarios.ymlkinds/engine-test/pack.ymldocs/paths.md(new)docs/model.md(the link to the page)docs/workflows.md,docs/versioning.md(where they describe the answer, the re-acceptance and the scenarios)
Spec: tests
- C1 → tests/release/scenarios.yml (
stop-edited-reaccepted-answered), with scripts/autopilot.py --test (run_endpast a G2 comment, a board and a cap end;needs-humantaken off on re-acceptance only after a stop; the Spec prompt carries the deciders' answers and no one else's; the fixed change stops only without an answer) - C2 → scripts/release-scenarios.py --test (
pathsagainst docs/paths.md and tests/release/scenarios.yml, with fixtures for a missing row, an unknown scenario and an empty cell)
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsNo status
Activity
dilux-bot commentedon Nov 8, 2026
The issue's board
f82fd3c6f94d🤖 AI-generated · Claude Opus 5.5 (Anthropic)
Seal #696's PRD
dilux-bot commentedon Nov 8, 2026
You wrote this Bug with the maintain or admin role, so it is accepted with its writing: no triage classifies it and no reproduction runs, and its PRD is sealed in your name. The autopilot codes it now in the organisation's runners, starting from a failing test.
🤖 AI-generated · Claude Opus 5.5 (Anthropic)
dilux-bot commentedon Nov 8, 2026
The autopilot waits for #689: that open autopilot pull request already changes the engine's core (org.yml
core), which this issue's Spec touches too, and two changes to the core at once keep putting each other in conflict. It starts this one on its own once #689 merges or closes.🤖 AI-generated · Claude Opus 5.5 (Anthropic)