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
This commit is contained in:
@@ -0,0 +1,198 @@
|
||||
# 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 |
|
||||
| **F9–F11 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 9–4) 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.last10` — **ten 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.
|
||||
Reference in New Issue
Block a user