feat(udg): anchors carry intent — -rule holds weight, -band holds proportion #157

Merged
peterswimm merged 1 commit from feat/udg-anchor-intent into main 2026-09-16 21:23:25 +00:00
Owner

Closes #156. An anchored pull is one of two things and they want opposite defaults, so the anchor now says which.

fill          covers the element (unchanged)
<edge>-rule   a divider          — constant WEIGHT
<edge>-band   a decorative strip — constant PROPORTION

anchor intent: rule vs band

extent is unchanged and still overrides either — the suffix only chooses the default. The two knobs stay orthogonal, which is precisely what made a single default arbitrary rather than wrong.

Scope

Measured with the same probe that gated #154, not asserted:

@360 @1024
bottom-band 10.69px 30.42px proportion holds, weight drifts
top-rule 3.00px 3.00px weight holds, proportion goes

A rule's default weight is var(--border-width-emphasis) — a token, not a number I picked. A hand-drawn rule is an emphasis border, and emitting the var keeps it designer-editable rather than baked, per TOKEN_GAP_PROPOSALS.md. It is also a double var indirection (--pN-h → --border-width-emphasis), which is exactly the shape that has bitten this tier four times — so it was rendered before it was believed.

The bare edges (anchor: bottom) are gone rather than aliased. Keeping one would have left an ambiguous default, which is the thing this change exists to remove — and the tier is days old with no external consumer, so this is the cheapest it will ever be. Both shipped presses migrate and now demonstrate one default each.

I argued for a fixed-px default and was overruled with the tradeoffs on the table. This implements the choice that was made, not the one I preferred — worth recording, because the reasoning now in the docs is the decision's rather than mine.

Testing

just check green, 4 presses · 270 tests · self-check 0 failures · rendered at three real widths with numbers read from getComputedStyle.

Two bugs caught on the way, both by things written earlier in this effort:

  • The landscape guard still matched bare edge names, so extent: auto on left-band silently stopped being rejected. Its own test caught it — the regression existed for about four minutes.
  • Section 05 of the review artifact was lying. It labelled three equal grid columns 360/640/1024 and claimed they showed the band scaling. They showed nothing — all three were the same width. Now rendered at their real widths, so the caption and the picture agree. That is the same "the artifact ville reviews is wrong" class of defect #153 existed to fix, which is a good argument for the self-check growing a geometry assertion later.

Impact Statement

Breaking, deliberately, and at the cheapest possible moment. anchor: bottom is no longer valid — it is bottom-rule or bottom-band. The only presses in existence are the four in spelwork/press.json, all migrated here; udgPressMap is emitted for no consumer (rituals declares no press), so nothing downstream moves. An invalid anchor fails by name with the full list.

The vocabulary grows 5 → 9 anchor values, which #156 named as the cost. In exchange the default is right for both uses instead of right for one and surprising for the other.

Interaction with #151: this lands on a vocabulary ville has not signed off yet. If the press terms change, these do too — but rule/band are ordinary print words and orthogonal to the plate/pigment/substrate set under review.

Reversibility: high. The intent suffix maps to one dict; collapsing back to bare edges is a small change plus a migration of four pulls.

Closes #156. An anchored pull is one of two things and they want **opposite** defaults, so the anchor now says which. ``` fill covers the element (unchanged) <edge>-rule a divider — constant WEIGHT <edge>-band a decorative strip — constant PROPORTION ``` ![anchor intent: rule vs band](https://git.toilville.dev/Toilville/toilville-design/raw/commit/5288693/scratchpad/press-review/05-anchor.png) `extent` is unchanged and still overrides either — the suffix only chooses the *default*. The two knobs stay orthogonal, which is precisely what made a single default arbitrary rather than wrong. ## Scope Measured with the same probe that gated #154, not asserted: | | @360 | @1024 | | |---|---|---|---| | `bottom-band` | 10.69px | 30.42px | proportion holds, weight drifts | | `top-rule` | 3.00px | 3.00px | weight holds, proportion goes | **A rule's default weight is `var(--border-width-emphasis)` — a token, not a number I picked.** A hand-drawn rule *is* an emphasis border, and emitting the var keeps it designer-editable rather than baked, per `TOKEN_GAP_PROPOSALS.md`. It is also a **double var indirection** (`--pN-h` → `--border-width-emphasis`), which is exactly the shape that has bitten this tier four times — so it was rendered before it was believed. **The bare edges (`anchor: bottom`) are gone rather than aliased.** Keeping one would have left an ambiguous default, which is the thing this change exists to remove — and the tier is days old with no external consumer, so this is the cheapest it will ever be. Both shipped presses migrate and now demonstrate one default each. > I argued for a fixed-px default and was overruled with the tradeoffs on the table. This implements the choice that was made, not the one I preferred — worth recording, because the reasoning now in the docs is the decision's rather than mine. ## Testing `just check` green, 4 presses · **270 tests** · self-check **0 failures** · rendered at three real widths with numbers read from `getComputedStyle`. **Two bugs caught on the way, both by things written earlier in this effort:** - The **landscape guard** still matched bare edge names, so `extent: auto` on `left-band` silently stopped being rejected. Its own test caught it — the regression existed for about four minutes. - **Section 05 of the review artifact was lying.** It labelled three *equal grid columns* 360/640/1024 and claimed they showed the band scaling. They showed nothing — all three were the same width. Now rendered at their real widths, so the caption and the picture agree. That is the same "the artifact ville reviews is wrong" class of defect #153 existed to fix, which is a good argument for the self-check growing a geometry assertion later. ## Impact Statement **Breaking, deliberately, and at the cheapest possible moment.** `anchor: bottom` is no longer valid — it is `bottom-rule` or `bottom-band`. The only presses in existence are the four in `spelwork/press.json`, all migrated here; `udgPressMap` is emitted for no consumer (rituals declares no press), so nothing downstream moves. An invalid anchor fails by name with the full list. **The vocabulary grows 5 → 9 anchor values**, which #156 named as the cost. In exchange the default is right for both uses instead of right for one and surprising for the other. **Interaction with #151:** this lands on a vocabulary ville has not signed off yet. If the press terms change, these do too — but `rule`/`band` are ordinary print words and orthogonal to the `plate`/`pigment`/`substrate` set under review. **Reversibility:** high. The intent suffix maps to one dict; collapsing back to bare edges is a small change plus a migration of four pulls.
feat(udg): anchors carry intent — -rule holds weight, -band holds proportion
All checks were successful
PR policy check / policy-gate (pull_request) Successful in 0s
Test Generator / lint-workflows (pull_request) Successful in 23s
Security Scans / Gitleaks secret scan (pull_request) Successful in 27s
Test Generator / lint-prose (pull_request) Successful in 26s
Security Scans / Trivy filesystem scan (pull_request) Successful in 33s
UDG dist drift gate / dist/ matches dtcg + udg sources (pull_request) Successful in 14s
Copy coverage / Design copy reaching rendered HTML (pull_request) Successful in 27s
Block Validation / validate (pull_request) Successful in 58s
Test Generator / test (pull_request) Successful in 3m33s
52886932ea
An anchored pull is one of two things and they want opposite defaults, so the
anchor now says which:

  fill                       covers the element (unchanged)
  <edge>-rule                a divider   — constant WEIGHT
  <edge>-band                a decorative strip — constant PROPORTION

`extent` is unchanged and still overrides either; the suffix only chooses the
default. The two knobs stay orthogonal, which is what made the previous single
default arbitrary rather than wrong.

Measured, not asserted — the same probe that gated #154:

  bottom-band   10.69px @360   30.42px @1024   proportion holds, weight drifts
  top-rule       3.00px @360    3.00px @1024   weight holds, proportion goes

A rule's default weight is `var(--border-width-emphasis)` — a TOKEN, because a
hand-drawn rule is an emphasis border, and emitting the var keeps it
designer-editable rather than baked (udg/products/TOKEN_GAP_PROPOSALS.md). It is
also a double var indirection (--pN-h -> --border-width-emphasis), which is
exactly the shape that has bitten this tier four times, so it was rendered before
being believed.

The bare edges (anchor: bottom) are GONE rather than aliased. Keeping one would
have left an ambiguous default, which is the thing this change exists to remove —
and the tier is days old with no external consumer, so this is the cheapest it
will ever be. Both shipped presses migrate and now demonstrate one default each.

I argued for a fixed-px default and was overruled with the tradeoffs on the table;
this implements the choice made, not the one I preferred. Recording that because
the reasoning in the docs is now the decision's, not mine.

Two bugs caught on the way, both by things written earlier in this effort:
  - the landscape guard still matched bare edge names, so extent:auto on
    left-band stopped being rejected. Its test caught it.
  - section 05 of the review artifact labelled three EQUAL grid columns
    360/640/1024 and claimed they showed the band scaling. They showed nothing.
    Now rendered at their real widths — the same "the artifact ville reviews is
    wrong" class of defect that #153 existed to fix.

Verified: just check green, 4 presses; 270 tests; self-check 0 failures;
rendered at three real widths with the numbers read from getComputedStyle.
peterswimm deleted branch feat/udg-anchor-intent 2026-09-16 21:23:26 +00:00
Sign in to join this conversation.
No description provided.