A-104: an optional step still waiting does not hold a pipeline's end
Only a required step still waiting or running holds endPipeline; a code review nobody gave on an optional policy no longer keeps the pipeline open. The review verb itself is not built: see the report. Builds: design 47 G §22, §70, §482, A-104 Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
This commit is contained in:
@@ -272,8 +272,8 @@ func stepOfAsk(p seat.Pipeline, id string) int {
|
||||
}
|
||||
|
||||
// endPipeline ends a pipeline whose every step ended: passed when every required step passed or was carried, else
|
||||
// failed, naming each required step that held it (ADR 0666 §7, §9; design 47 G §24, §26). A failed optional step holds
|
||||
// nothing. An approval step still waiting when a required step did not pass is `not asked` (§26). It says whether the
|
||||
// failed, naming each required step that held it (ADR 0666 §7, §9; design 47 G §24, §26). A failed optional step, and an optional step
|
||||
// still waiting, hold nothing. An approval step still waiting when a required step did not pass is `not asked` (§26). It says whether the
|
||||
// pipeline ended now, its end count one higher.
|
||||
func endPipeline(p *seat.Pipeline, now time.Time) bool {
|
||||
if p.Outcome != seat.PipelineOutcomeRunning {
|
||||
@@ -286,6 +286,10 @@ func endPipeline(p *seat.Pipeline, now time.Time) bool {
|
||||
case s.Step == seat.StepResultStepApproval && s.Outcome == seat.StepResultOutcomeWaiting:
|
||||
notAsked = i
|
||||
continue
|
||||
case s.Outcome == seat.StepResultOutcomeWaiting && s.Status != seat.StepResultStatusRequired:
|
||||
// An optional step still waiting (a code review nobody has given) holds nothing: only a required one holds the
|
||||
// pipeline's end (A-104).
|
||||
continue
|
||||
case s.Outcome == seat.StepResultOutcomeWaiting, s.Outcome == seat.StepResultOutcomeRunning:
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -276,3 +276,25 @@ func TestApprovalEnds(t *testing.T) {
|
||||
t.Errorf("asked %d; %+v", len(asker.asked), p)
|
||||
}
|
||||
}
|
||||
|
||||
// An optional step still waiting (a code review nobody has given) does not hold a pipeline's end; a required one does
|
||||
// (design 47 G A-104).
|
||||
func TestAnOptionalStepStillWaitingHoldsNoEnd(t *testing.T) {
|
||||
now := time.Date(2026, 11, 11, 12, 0, 0, 0, time.UTC)
|
||||
for name, c := range map[string]struct {
|
||||
review string
|
||||
ends bool
|
||||
}{"optional review waiting": {seat.StepResultStatusOptional, true}, "required review waiting": {seat.StepResultStatusRequired, false}} {
|
||||
p := seat.Pipeline{Outcome: seat.PipelineOutcomeRunning, Steps: []seat.StepResult{
|
||||
{Step: seat.StepResultStepBuild, Status: seat.StepResultStatusRequired, Outcome: seat.StepResultOutcomePassed},
|
||||
{Step: seat.StepResultStepReview, Status: c.review, Outcome: seat.StepResultOutcomeWaiting},
|
||||
{Step: seat.StepResultStepApproval, Status: seat.StepResultStatusRequired, Outcome: seat.StepResultOutcomePassed},
|
||||
}}
|
||||
if got := endPipeline(&p, now); got != c.ends {
|
||||
t.Errorf("%s: ended = %v, want %v", name, got, c.ends)
|
||||
}
|
||||
if c.ends && p.Outcome != seat.PipelineOutcomePassed {
|
||||
t.Errorf("%s: outcome %s", name, p.Outcome)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user