Activity exits: the corpus moves its routing into the workflows that own it - #500
Merged
Conversation
Every activity declares exits — named outcomes with the inline predicate that selects each — and every workflow.yaml declares the graph binding those exits to destinations. A checkpoint option selects an exit rather than an activity. The 176 route declarations the activity files carried are now 163 exits bound in 17 workflow files, and the count carried by an activity file is zero. Nine decision branches named no destination, so they answered nothing about where next and are retired outright rather than renamed. A checkpoint option whose destination an exit already reaches selects that exit instead of naming the same outcome twice. remediate-vuln binds the fourteen activities it borrows from work-package in its own file, so it can run them in a different order without editing them. Five abort exits are immediate: selecting one ends the activity where the user chose it. Four of them are followed by steps that run today, one after a decision to abort a submission and one after a decision to abort a repository binding.
The orchestrator's own protocol resolves an exit and reads its destination from the workflow graph: evaluate-transition takes the exit a checkpoint option named, else the first whose predicate holds, else the default, and finalize-activity carries the exit taken in its envelope for next_activity to report. The construct inventory pairs the activity-level exit with the workflow-level graph binding and states that no activity file names another activity. The anti-pattern catalogue, format and conformance conventions, elicitation guide, impact-analysis techniques and work-package's review-mode notes name exits and the graph where they named transitions and decisions.
This was referenced Aug 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Every activity in this corpus named the activity that ran next, in its own file. So a workflow file
did not describe its own shape, and an activity could not be borrowed and rearranged.
This moves the routing to the workflows that own it. Each activity now declares exits — named
outcomes with the predicate that selects each — and each
workflow.yamldeclares the graphbinding those exits to destinations.
The corpus half of #496. Paired with the server change in #501, which defines the schema this
depends on; the tooling on this branch is red until that merges, so it was verified locally against
the server branch.
What moved
117 activity files across 17 workflows carried 176 route declarations: 127
transitions[]entries (48 with a condition), 15 decision branches, and 34 checkpoint options with a
transitionTo. After this change, the count carried by an activity file is zero, and the routingis 163 exits bound in 17 workflow files.
The count falls by 13, every case a route that named nothing:
transitionTo; the other 9 answered nothing about where next — the activity's transitions decided,and the branch merely labelled which case had been reached. They are retired rather than renamed.
outcome twice, the option selects the existing exit. Five are the "proceed" half of a confirmation
gate in
work-packages; the sixth isworkflow-design's pair of review dispositions, which differin what they set and not in where they go.
meta/04-end-workflowandmidnight-system-review/05-verdict-and-reportended the run by falling off the end of theirroutes. That ending is a real outcome, so it is named (
completed,report-only) and bound to__terminal__— which is also what makes a dismissed checkpoint at either site resolve to a namedexit.
What an activity looks like now
Instead of seven conditional transitions naming seven activities,
prism/00-select-modedeclaresseven outcomes:
and
prism/workflow.yamlsays where each one goes:Exit names come from what the route already said: a comparison against a value gives the value, a
comparison against
truegives the variable, a decision branch gives its branch id, a checkpointoption gives its option id, and an activity with one unconditional route exits by
done. Thirtyroutes had no name to derive — a compound predicate, or a default standing for the case its siblings
do not cover — and were named by hand; the table is in the investigation record.
Borrowing without mirroring
remediate-vulnruns 14 ofwork-package's activity files. It now binds their exits in its ownworkflow.yaml, so it can place them in a different order — insert a stage, drop one, swap two —without editing files it borrows but does not own. Today's bindings mirror
work-package's, which iswhat the corpus does; the difference is that the mirroring is now a choice recorded in one file
rather than a constraint imposed by fourteen.
Aborts that end the activity
An exit may be declared
immediate, and selecting one at a checkpoint ends the step sequence there.Five abort exits carry it. Four are followed by steps that run today: aborting a repository binding
in
meta/00-discover-sessionwas followed by eleven steps, five of them ungated; aborting asubmission in
work-package/13-submit-for-reviewby eleven, one of which announces the pull requestis ready for review; aborting in
prism-audit/01-prompt-generationby five, all ungated; andprism-update/01-review-changesby one. The fifth,prism-update/03-verify, has no tail and takesthe flag so the abort vocabulary is uniform.
Every other site keeps the timing it has now, so the move is not a behaviour rewrite. The two review
dispositions in
workflow-design/08-quality-reviewandworkflow-authoring/09-validate-and-commitare where an author wrote a gate onto all 20 and 13 following steps by hand to simulate an early
exit; replacing those gates with an immediate exit is a behaviour change at a site that already
behaves correctly, so it is left for separate work.
The canon and the engine protocol
The orchestrator's own protocol changes with the corpus.
evaluate-transitiontakes the exit acheckpoint option named, else the first whose predicate holds, else the default, then reads the
destination from the workflow graph;
finalize-activitycarries the exit taken in its envelope fornext_activityto report.The authoring canon follows: the construct inventory pairs the activity-level exit with the
workflow-level graph binding and states that no activity file names another activity, and the
anti-pattern catalogue, format and conformance conventions, elicitation guide, impact-analysis
techniques and
work-package/REVIEW-MODE.mdname exits and the graph where they named transitionsand decisions.
Verification
Verified locally against the paired server branch: all 17 workflows load, all 117 activity files
validate, the 30-guard suite passes, and the end-to-end walk snapshots are byte-identical — every
workflow walks the same path it walked when its activities carried the routing.
Investigation detail
Route counts per workflow before and after, the exit naming table, and the tail measured after every
routed checkpoint option:
.engineering/artifacts/planning/2026-08-24-activity-exits/.🤖 Generated with Claude Code