Skip to content

app-showcase nests no control-flow construct inside another, so the QA checklist's new loop { parallel } clause can only score blocked(fixture) #16356

Description

@os-warren

Found while implementing #15230 (the runRegion tagger half of #14414). Filed unassigned; domain:*, type and priority are triage's.

What is missing

examples/app-showcase declares each ADR-0031 structured construct as its own top-level flow and nests none of them in another:

git grep -n "type: 'loop'" -- examples/ apps/
  examples/app-showcase/src/automation/flows/index.ts:868   (BatchRemindersFlow, body = one notify node)
  examples/app-todo/src/flows/task.flow.ts:29
  examples/app-todo/src/flows/task.flow.ts:83

The per-node-type map the checklist already records says the same thing explicitly — automation.flow-node-type-matrix, fixtures.requires:

loop=showcase_batch_reminders · parallel+http=showcase_fan_out_notify · try_catch=showcase_resilient_sync

Three separate flows. showcase_batch_reminders loops a single notify; showcase_fan_out_notify fans out at top level; ProjectEscalationFlow composes decision with parallel and try_catch but sits under no loop.

Why it blocks something concrete

PR for #15230 adds a loop { parallel } acceptance clause to automation.flow-run-step-nesting (item revision 3). That clause exists because the maintainer ruling of 2026-09-03 made iteration single-valued and gave the parallel branch index its own branch key, and a step inside a parallel branch that is itself inside a loop body is the only shape where both index keys are populated on one record. A run of that clause today scores blocked(fixture): there is no flow to trigger.

The clause was written anyway rather than deferred — an absent clause is exactly what let the iteration overload sit unmeasured — and the item's fixtures.requires records the gap in the open. This card is the other half.

What would close it

A showcase flow whose loop body holds a two-branch parallel, exported and added to the flow list in examples/app-showcase/src/automation/flows/index.ts, with at least two rows so the clause's (iteration, branch) pair check has something to distinguish. No gate script enumerates showcase flows by path, so the cost looks like the defineFlow plus its array entry.

Worth deciding as part of it: whether the nested-composition gap is wider than this one clause. loop { try_catch } is documented as the per-iteration containment spelling (#13681, #14394) and is the shape #14456 taught the engine to attribute to a row, and showcase demonstrates that nesting nowhere either — so a reader of the examples app cannot see the containment spelling the docs recommend.

Refs: #15230 (the engine change that makes the clause writable) · #14414 / PR #15227 (the contract half) · #14622 (the neighbouring observation that showcase_batch_reminders loops a fallible node with no containment) — none of those is addressed here.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions