WORK-583
ID:WORK-583Status:ready

Emit sequence ordinals as nodes, not CSS counters

A numbered sequence renders its ordinal through CSS:

Priority:mediumComplexity:moderateSource:ADR-029

Criteria completion

Criteria completion: 0 of 8 (0%) checked; tracking started on Sep 21, no incremental history yet0%25%50%75%100%Sep 21Oct 11

Tracking started Sep 21 — check back for trends.

Branches 1
History 4
  1. 62ca2e6
    Created (ready)by bjornolofandersson
  2. db0a158
    Content editedby Claude
    docs(plan): renumber the sequence-duplication bug to BUG-024
  3. 6f9a8d2
    Content editedby Claude
    test(transform): WORK-584 Q1 — layout does reach a child rune; ADR-029 l
  4. 4175521
    Content editedby Claude
    docs(plan): record the theme-complexity findings — SPEC-137, ADR-030, 2

Why

The governing rule, which ADR-030 rule 3 states as a semantic fact: a numbered sequence's ordinal is information. A playlist's 7 is the track number, an identifier a listener says out loud; a recipe's 3 is referenceable ("go back to step 3"). Information belongs in the document, not in a stylesheet.

The mirror case confirms the rule rather than weakening it. A connected sequence — timeline, itinerary — renders no number, because each item carries its own positional label (timeline.ts:44 emits a <time>), and a numeral there would be false information. Decorative marks stay in CSS; a dot connector or a separator is correctly generated content precisely because it must not be copied.

In the DOM if it's information. In CSS if it's ornament.

Three payoffs beyond correctness:

  • Theme rearrangement becomes possible. A parent-driven, absolutely positioned counter is orphaned the moment a theme changes the container's topology — a card grid has nowhere to put it. Once the ordinal is a named part, a layout tree can place it. This is a practical prerequisite for ADR-029's groups.
  • Accessibility and copy/paste. The number becomes real text.
  • The arrangement simplifies. [data-sequence] stops generating content and becomes pure geometry.

Scope

In: sequence: 'numbered' only.

Out: connected and plain keep no marker content — there is nothing to promote. The decorative dot on connected stays a CSS ::before.

Approach

  1. Add an ordinal node to the emitted item, named so the engine gives it a BEM element class and a layout-tree handle (e.g. data-name="ordinal", data-meta-type="quantity" for tabular-nums).
  2. Assign ordinals at transform time in the parent. track.ts:192 only emits numberMeta when the author passed number=, so playlist must number its children — the parent-retypes-children pattern the SPEC-130 D9 comment at track.ts:128 already describes.
  3. Remove counter-reset / counter-increment / content: counter(…) from sequence.css, keeping the marker's box geometry.
  4. Keep the author's explicit number= authoritative where supplied, so a playlist with a gap or a non-1-based numbering renders what the author wrote.

Interaction with BUG-024

BUG-024 removes four runes' duplicate counters and should land first. This item then changes the single remaining mechanism. Doing it in the other order means editing five counter implementations instead of one.

Blocked by

  • BUG-024

Acceptance Criteria

  • A numbered sequence emits its ordinal as a text node, not as generated content
  • The ordinal is selectable and copyable, and announced in document order
  • connected and plain sequences emit no ordinal node
  • An explicit number= on an item wins over the assigned ordinal
  • playlist assigns ordinals to tracks that carry none
  • The ordinal is addressable from a layout tree by name
  • Both copies of structures.json are regenerated together and the new node appears in each
  • npm run seo:baseline:check passes, or the baseline is regenerated and the diff reviewed — no schema change is expected, so an unexpected diff is a finding

Risks

Contract and baseline churn. A new node in every numbered sequence touches both contract copies and possibly the SEO baseline. Expected and reviewable, but it makes this a poor candidate to batch with unrelated changes.

Double-rendering during migration. If the node ships before the CSS counter is removed, items render two numbers. The two changes belong in one commit.