WORK-648
ID:WORK-648Status:done

each iterates the items of a list field

Today each iterates a list only when the field has an itemModel with an emitTag. A list whose items need no extraction, where each item's content is placed as it is, has no way in. That blocks steps, which takes its steps from headings or from an ordered list (SPEC-169 D4).

Priority:mediumComplexity:simpleMilestone:v0.42.0Source:SPEC-169

Criteria completion

Criteria completion: 4 of 4 (100%) checked; history from Oct 24 to Oct 250%25%50%75%100%Oct 24Oct 25
Branches 3
History 3
  1. 61748bf
    • ☑ `each` on a non-greedy field matching one `list` iterates its items, with the bare slot as each item's content and no `$each` bindings
    • ☑ A composed `steps` fixture renders the same steps from headings and from an ordered list, with one model and no conditional
    • ☑ An `each` over a greedy list field, or a field that can match several lists, is a construction error naming the field
    • ☑ The composed-runes guide documents list `each` beside `itemModel`, including that `itemModel` patterns consume the text they match in order (from BUG-038)
    by bjornolofandersson
  2. a0cdd51
    Created (ready)by bjornolofandersson
  3. abc833f
    Content editedby Claude
    plan: v0.41.3, v0.42.0 and v0.43.0 milestones

Acceptance Criteria

  • each on a non-greedy field matching one list iterates its items, with the bare slot as each item's content and no $each bindings
  • A composed steps fixture renders the same steps from headings and from an ordered list, with one model and no conditional
  • An each over a greedy list field, or a field that can match several lists, is a construction error naming the field
  • The composed-runes guide documents list each beside itemModel, including that itemModel patterns consume the text they match in order (from BUG-038)

Approach

  • SPEC-169's steps example places the items in {% group layout="ladder" %}. The ladder is SPEC-156's and still draft, so the fixture uses a plain container. It proves the model, not the look.
  • BUG-038 fixes itemModel patterns in the same part of the resolver. Land it first if both are in flight, so the list each tests run beside working itemModel tests.
  • D4's open question, whether rendering both a list and headings should warn, stays open. The fixture covers each input separately.

References

  • SPEC-169: D4.
  • BUG-038.

Resolution

Completed: 2026-10-25

Branch: claude/v0-42-0-planning-t31f5e

What was done

  • composition.ts: a non-greedy field whose match alternatives are all lists is listItems; each iterates the list's items, giving a tight item's inline content a paragraph, and binds no $each. A greedy field that can match a list (no emitTag) is ambiguousList, and each on it is each-on-list-ambiguous. A field that may match something other than a list stays each-on-single-field.
  • Fixture packages/runes/test/fixtures/composed/steps.md, in a plain grid until SPEC-156's ladder exists, and included in the guide beside the itemModel docs and the pattern-order note.

Notes

  • D4's open question (warn when an author writes both a list and headings) stays open.