Files
vyndr/specs/wave-d1-primitives.md
T
builtbykev 60469422af Wave D1 primitives — and the audit says E1/E9 were not Wave 1
PHASE 0 — the order proposed E1 + E9 as Wave-1 and told me to follow the
audit if it disagreed. It disagrees: E9 calibration curve is WAVE D3,
gated on MODEL work ("resolve n>=20 vs N30, accrue buckets"), and E1
movement strip is WAVE D6, a large surface build. E9's gate is live right
now -- calibration is WITHDRAWN at 0 eligible dates, so the curve could
only render its empty state today. Building it would ship a component
whose entire purpose is unavailable.

PHASE 1 — three of the five real Wave D1 items were ALREADY DONE, and the
2026-07-31 audit has aged:

  D1 glyph library  audit: 38/83 wired (46%)
                    now:   COMPLETE for everything wireable -- 39 of 83
                           designed glyphs map to a real archetype, all 39
                           are wired, colours match the registry exactly
                           (0 disagreements).
  A1 card token     audit: BUILT-BUT-DRIFTED, "in only 1 file"
                    now:   BUILT-TO-SPEC -- it IS the --bg-1 token,
                           consumed by 32 files. The audit counted literal
                           hex, which is what a correctly tokenised value
                           looks like.
  B1 boundary blue  audit: PARTIAL, hex in 2 files
                    now:   BUILT -- --priced-out/#8fb2de is a token with a
                           documented colour law, 4 consumers.

The 44 unwired glyphs are NOT a wiring gap: they have no backend
archetype, so wiring them means inventing 44 archetypes to consume
artwork -- the fabrication this programme refuses. That is the 41-vs-74
scope question and it is Kev's call. Separately, 2 registry archetypes
have NO designed glyph (DUAL THREAT, PAINT BOSS) -- a design gap.

PHASE 2 — what was genuinely absent is now built. web/src/lib/motion.js:
nudge() capped at 180ms so it reads as acknowledgement rather than
latency; bootStagger capped at 240ms because uncapped, row 40 waits 1.1s
and the stagger BECOMES the latency it exists to disguise; rowHover
returns handlers not CSS so touch cannot stick a hover state; and
revealOnIntersect returns an unobserve in every path and reveals
IMMEDIATELY when there is no IntersectionObserver or motion is reduced --
content is never hidden behind a capability check.

Reduced motion is honoured, not softened. The sharpest of the 10 tests:
bootStagger under reduced motion returns opacity 1, not merely delay 0 --
if the CSS animation supplies the opacity, skipping it leaves the row
invisible forever.

PHASE 3 — the reachability guard gains a PRIMITIVES section: a module
built to be embedded must declare its exports AND name its intended
consumers, because a primitive imported by nothing is the same
built-but-unread class as an unmounted component.

WAVE-2 UNGATED: F9-F11 offseason hub, F5 article media, E10/E12 Report,
E1 movement strip. GATED: E9 + E15 on model, E16/F8 on the resolution tail
and the card-system reconciliation, E2/E6 on licensing, E13 on another
order.

Read-only throughout; serving fingerprint unchanged; accrual clock
unchanged at 0 eligible dates.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W1sivYNqY2TS5ftykmHBU9
2026-08-07 20:31:55 -04:00

4.7 KiB
Raw Blame History

Wave D1 — and why E1/E9 were not it

PHASE 0 — the audit's actual wave order

The order proposed E1 + E9 as Wave-1 primitives and instructed me to follow the audit if it disagreed. It disagrees.

item the audit's placement
E9 calibration curve WAVE D3 — gated on MODEL work: "resolve n≥20 vs N30, accrue buckets"
E1 movement strip WAVE D6 — large surface builds, alongside crown / disagreement axis / SPLIT

Neither is Wave 1. And E9's gate is live right now: calibration is withdrawn (CALIBRATION_DEPLOYED = []) at 0 eligible dates, so a calibration curve today could only render its empty state. Building it now would produce a component whose entire purpose is unavailable.

WAVE D1, per the audit: glyph library · card token + vy-glitch naming · nudge()/boot-stagger/row-hover/IntersectionObserver · boundary-channel blue · team-gradient chips + READ-FAB.

PHASE 1 — three of the five Wave D1 items were already done

Checked rather than assumed, and the audit (2026-07-31) has aged:

item audit said measured now
D1 glyph library PARTIAL — 38 of 83 wired (46%) COMPLETE for everything wireable. 83 designed glyphs, 41 registry archetypes, 39 map — and all 39 are wired, with colours matching the registry exactly (0 disagreements).
A1 card token #0E0E14 BUILT-BUT-DRIFTED — "in only 1 file" BUILT-TO-SPEC. It is the --bg-1 token in globals.css, consumed by 32 files via var(--bg-1). The audit counted literal hex occurrences, which is what a correctly tokenised value looks like.
B1 boundary channel PARTIAL — hex in 2 files BUILT. --priced-out: #8fb2de + --priced-out-dim are tokens with a documented colour law in globals.css, consumed by 4 files.

The 44 unwired glyphs are not a wiring gap. They have no backend archetype — wiring them would mean inventing 44 archetypes to consume artwork, which is the fabrication this programme refuses. That is the 41-vs-74 scope question, and it is Kev's call, not a build task. Separately, 2 registry archetypes have no designed glyph (DUAL THREAT, PAINT BOSS) — a design gap, not a code one.

PHASE 2 — what was genuinely absent, and is now built

web/src/lib/motion.js — the four primitives, all previously 0 files:

primitive the rule it enforces
E17 nudge() ≤180ms. Confirms an action registered without claiming it finished — a long pulse reads as latency, the opposite of a perceived-speed primitive.
E18 bootStagger() capped at 240ms. Uncapped, row 40 waits 1.1s and the stagger becomes the latency it exists to disguise.
E27 rowHover() returns handlers, not CSS — so a tap on touch cannot stick a hover state that never clears.
E28 revealOnIntersect() returns an unobserve fn in every path, and reveals IMMEDIATELY without IntersectionObserver or under reduced motion. Content is never hidden behind a capability check.

Reduced motion is honoured, not softened — every primitive skips outright, and server-side assumes reduced. 10 tests, the sharpest being that bootStagger under reduced motion returns opacity: 1 and not merely delay: 0: if the CSS animation supplies the opacity, skipping the animation without forcing it leaves the row invisible forever.

PHASE 3 — guard registration and Wave-2 readiness

The reachability guard now carries a PRIMITIVES section: a module built to be embedded must declare its exports and name its intended consumers. A primitive imported by nothing is the same built-but-unread class as an unmounted component. 24 checks green.

Wave-2 readiness

Ungated — design complete, no blocker:

  • F9/F10/F11 offseason hub (Wave D6) — the largest, fully spec'd
  • F5 article media (Wave D6) — hero + figure system fully spec'd
  • E10/E12 The Report email + /report archive — design exists
  • E1 movement strip (Wave D6) — spec'd, absent, now has its motion primitives

Gated, and by what:

item gate
E9 calibration curve model — calibration withdrawn, 0 eligible dates
E15 Price Triplet MODEL leg model — EV layer
E16 share cards + F8 crops resolution tail and the card-system reconciliation
E2 BookChip tiles / E6 push-to-book licensing / affiliate approval
E13 Scanner S6 another build order

The card-system reconciliation (content-engine 1080×1350 vs E16's five masters) gates E16/F8 and should be settled with the social chat, since off-site posts and on-site share cards are one system.

Isolated throughout: read-only, no serving or model change, accrual clock unchanged at 0 eligible dates.