Files
vyndr/specs/HANDOFF-2026-08-08.md
T
builtbykev 387ae4d54e Handoff doc: ground-truth build state at 71d3b7b
Written from the repo, not summary -- every claim grep- or run-verified,
UNKNOWN where the repo cannot say.

State: HEAD and gitea main in sync at 71d3b7b, tree clean, 4,539 tests
passing, web build exit 0. Push remote is gitea, never origin.

DONE this arc, existence-verified: E1 movement strip, F9-F11 offseason hub
shell, E10 Report template, E12 /report archive, content engine + studio
API + preview, Wave-D1 motion primitives, honest served grade, archetype
doctrine. Also verified done and previously mis-boarded: D1 glyphs (39 of
83 -- every one that maps to a real archetype), A1 card token, B1 boundary
channel, book comparison, THE WIRE.

GATED with each gate named and each absence verified by 0-file grep: F5
article media and E16/F8 on the card-system reconciliation, in-season hub
IA on the content formula, E9/E15 on model accrual, E2/E6 on licensing,
E3 crown on measurement, E13 on another order. NO UNGATED WAVE-2 TARGETS
REMAIN -- the next move is a decision, not a build.

The two open decisions are stated with what each unblocks. Card-system
reconciliation is the cheapest: it frees F5 and E16/F8 together, and it
exists because I built a 1080x1350 renderer without checking whether a
designed card system existed. It did.

Accrual clock recorded at 0 eligible dates on all four items, with the
first trigger (10 calibration dates) and the attempt-floor-not-trust-floor
caveat carried forward.

Standing doctrine carried: Truth Law including designer samples and the
inverse Number(null) breach (zero is a real fact); the 83-glyph taxonomy
with 44 dormant slots; the repaired champion and the standing flag that
every prior factor verdict was measured against the broken baseline;
calibration withdrawn; unissuable A with a B+ 0.663 ceiling; both CI
guards; and compose-don't-fork, which this arc failed three times and
caught twice.

Both parallel workstreams written as seed prompts.

specs/HANDOFF-2026-08-08.md

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

9.3 KiB
Raw Blame History

VYNDR build handoff — 2026-08-08

Written from the repo, not from summary. Every claim below was grep- or run-verified at 71d3b7b. Where something could not be verified from the repo it says UNKNOWN.

Repo state

HEAD        71d3b7b78692c31ba0596ec88874986ff1b58116
gitea main  71d3b7b78692c31ba0596ec88874986ff1b58116   (in sync)
tree        clean — 0 modified/untracked
tests       4,539 passing / 4 skipped
web build   exit 0

Push remote is gitea, not origin. origin is GitHub and has no credential on this machine; every push must be git push gitea main. This cost twenty commits of false "no credentials" diagnosis — see docs/GIT-PUSH-DIAGNOSIS.md.


BUILD STATE per surface

DONE this arc — verified present

surface file lines
E1 movement strip web/src/components/vyndr/MovementStrip.tsx 113
F9F11 offseason hub shell web/src/app/offseason/page.tsx + components/vyndr/OffseasonHub.tsx 21 + hub
E10 Report issue template src/services/report/reportTemplate.js 169
E12 /report archive web/src/app/report/page.tsx + components/vyndr/ReportArchive.tsx + src/routes/report.js 17 + comp + route
Content engine src/services/content/contentEngine.js + 3 templates + cardRenderer.js 172 +
Content studio API + preview src/routes/contentStudio.js + web/src/app/studio/page.tsx 175 + 131
Wave-D1 motion primitives web/src/lib/motion.js (E17/E18/E27/E28) 100
Honest served grade src/services/model/servedGrade.js 142
Archetype doctrine specs/ARCHETYPE-TAXONOMY-DOCTRINE.md 53

Also DONE and verified: D1 glyph library (39 of 83 wired — every glyph that maps to a real archetype; colours match the registry exactly), A1 card token (--bg-1, 32 consumers), B1 boundary channel (--priced-out, 4 consumers), book comparison (mounted via GradeResultCard → scan/page), THE WIRE (vyndr/Ticker).

GATED — verified absent, with the gate named

surface gate verified
F5 article media card-system reconciliation ArticleHero/StatCallout/PullQuote = 0 files
E16/F8 share cards + crops card-system reconciliation and the resolution tail has no share-card generation step ShareCard.tsx has 0 importers
In-season hub IA the content formula (social chat) no spec exists anywhere
E9 calibration curve model accrual — 0 eligible dates CalibrationCurve = 0 files
E15 Price Triplet MODEL leg model — EV layer renders honest NO_MODEL
E2 BookChip tiles / E6 push-to-book licensing / affiliate approval every book enabled:false
E3 best-number crown measurement — measured flat CrownBadge = 0 files
E13 Scanner S6 another build order

There are no ungated Wave-2 targets left. The next move is a decision, not a build.


THE TWO OPEN DECISIONS

1. Card-system reconciliation — unblocks F5 and E16/F8 together

The content engine emits 1080×1350 SVG cards (src/services/content/cardRenderer.js). The design package defines five master sizes with layouts and rasterised PNGs in specs/design-reference/exports/: settle 1080×1350, story 1080×1920, square 1080, X 1200×675, record 1080×1350, article OG 1200×630.

I built the renderer without checking whether a designed card system existed. It did. They are a parallel invention — not wrong, but they must become one visual language before F5 (whose hero graphics are generated data visuals) or E16 can proceed.

The decision: does the content engine conform to the E16 masters, or do the masters absorb the engine's generator? Cheapest unblock on the board — it frees two gated items at once.

2. In-season hub information architecture

Vyndr Offseason.dc.html specifies an offseason hub, and its shell is built. Nothing specifies what that surface is in-season, or how content, articles, wire and the live slate share year-round navigation. Every component exists; the composition does not.

The spec is explicit that sport state lives in the sport tab (NFL · CAMP 5D) and never in a separate offseason tab — so this is not a new route, it is a mode. Gated on the social chat's content formula, which determines the recurring slots.


ACCRUAL CLOCK

champion marker: engine1@2026-08-07-fullwindow

  calibration_refit        0/10  WAITING     (~2 weeks)
  hits_factor_lift         0/10  WAITING     (~2 weeks)
  prior_verdict_reaudit    0/14  WAITING     (3+ weeks)
  rbi_lineup_slot_gate     0/14  WAITING     (3+ weeks)

blocked: no settled rows yet carry the repaired champion marker

FIRST TRIGGER: 10 eligible calibration dates → calibration re-fit. Then, in order: hits factor lift → prior verdict re-audit → rbi lineup-slot gate.

Thresholds are ATTEMPT floors, not TRUST floors. Reaching 10 dates means the re-fit can be measured, not that it is trustworthy. A 10-date map is thin, deploys PROVISIONAL with auto-demotion, and its interval will be wide.

No measurement on reconstructions of the retired forecast. Anything requiring settled data waits. src/services/model/reAuditEligibility.js enforces it — eligibility is a version marker, counted in DATES not rows, and a mixed table counts only the repaired rows.


STANDING DOCTRINE

Truth Law. No fabricated data anywhere — including designer sample data. The design files' numbers (Nabers 1,120.5, Wembanyama +420→+330, Nº 128, DAY RECORD 94) are a spec for what a live feed renders, never content to paste. Tests assert none of it ships. Number(null) === 0 is the classic breach; note its inverse also bites — zero is a real fact ("0 cleared B+" is our most honest post).

83-glyph four-sport taxonomy. A glyph renders ONLY where its archetype is modeled and proven. 39 wired; 44 dormant slots for WNBA/NBA/Soccer. Wiring them would mean inventing 44 archetypes to consume artwork — decoration presented as classification, forbidden. DUAL THREAT and PAINT BOSS are modeled archetypes with no mark: the mirror gap, flagged to design.

Repaired champion. The forecaster read res.last10ten games — as its season rate. Fixed to the full season log with recency weight 0.40 → 0.20. Resolution: hits 0.00251 → 0.00817. Every factor verdict in the programme was measured against the broken baseline and may deserve re-audit — direction unknown, not pre-priced.

Calibration is WITHDRAWN. CALIBRATION_DEPLOYED = []. The maps were fitted on the retired forecast; refitting today would refit it again. Served p_win is repaired-champion raw.

Grade doctrine. A+, A, A- are unissuable — structurally, not rarely. Ceiling is B+ at 0.663 realized against a 0.6005 baseline. Bands that cannot be separated from the baseline SAY so. The served letter derives from p_win; engine1.grade is preserved as engine_grade and read by no serving code.

Two guards, both in CI:

  • renderReachability.test.js — a promised field must trace payload → adapter → component → mounted. Built-but-unread killed three surfaces before this.
  • baseRateWindow.test.js — no fixed N may stand in for a season. Six paths across two sports fell to that class.

Compose, don't fork. The recurring failure this arc: building beside an existing thing instead of on it (cards vs E16, MovementStrip nearly vs gradeShift, reportTemplate nearly vs newsletterService). Check for the existing implementation first — twice it was already there.


PARALLEL WORKSTREAM SEEDS

A. Social strategy chat

VYNDR's content engine ships posts from real data (src/services/content/, three templates, Truth-Law enforced — an unbacked token refuses to render). Review /studio output and specs/CONTENT-ENGINE.md. Produce: the content formula/calendar (what posts recur, on what cadence), and the card-format decision — the engine's 1080×1350 renderer vs the five designed masters in specs/design-reference/exports/. That decision unblocks F5 article media and E16/F8 on the build side. Voice: specs/VOICE.md governs; the engine templates encode a sharper register — decide whether that becomes the house voice.

B. Multi-sport archetype build

VYNDR has archetype registries for MLB (15), NBA (15), Soccer (6), WNBA (5) — but only MLB batters is MODELED; the rest have no proven factor model, so their glyphs stay dormant per specs/ARCHETYPE-TAXONOMY-DOCTRINE.md. 44 of 83 designed glyphs await their sport. Pick a sport, build its archetype classifier from real features, and take it through the two-part gate (src/services/model/factorGate.js — must MOVE the prediction and improve out-of-sample Brier, cumulative-Bonferroni corrected). Prerequisite: that sport needs settled outcomes. WNBA settles via ESPN box scores; NBA and Soccer do not settle at all yet, which is the real first task there.


Where to start in the next chat

  1. Take one of the two open decisions (card system is cheapest — unblocks two).
  2. Or run a parallel workstream seed above.
  3. Do not start model work — it is date-blocked and will stay so for ~2 weeks.
  4. Verify before building: this arc corrected its own board four times. git grep beats any summary, including this one.