Checkpoint 1 · cd-build session · 2026-07-07

Register layers, a shared position bar, and an honest Learn sheet

This is the build session that turned Frank's card-archetype-design board rulings (CD1/CD2/CD3/CD5, answered 2026-07-06) into shipped code — same day, 2026-07-07.

CD3 — register layers CD5 — position bar CD2 — Learn sheet ADR-088 accepted PLAN-178 executed
Checkpoints Latest →
CD3

Every new example sentence now says how it's said

Formal, standard, gaul (street/casual), or regional — Frank's four words exactly, locked into the glossary. The enrichment AI can no longer skip this label.

Before: every example sentence in the database quietly had a fake "neutral" tag — nobody ever actually decided what register it was, the field just defaulted to a placeholder. The AI was told to keep everything sanitized and formal-ish, and slang was banned outright.

Now: the schema forces the AI to pick one of the four real labels for every example it writes. The policy: most examples stay standard (the teaching baseline), but for any word taught at A2 level or above, at least one example must be formal and at least one must be real, authentic gaul — actual street Indonesian, not a sanitized version. A1 (the easiest level) stays gaul-free for now. A regional label only gets used when a dictionary source actually proves a word is regional — never invented.

Before

Sanitized, unlabeled

Every example looked the same register-wise — administrator Indonesian, no way to tell formal from casual, and no way for the app to ever teach the difference.

Live proof — the word "tetapi"

6 standard + 1 formal + 1 gaul

The gaul example: "Aku udah janji, tapi kayaknya nggak bisa datang" — real street Indonesian, correctly labeled, not scrubbed clean.

How it looks on the card: each labeled example gets a small icon+text tag next to it — a bank icon for formal, a chat bubble for standard, a chat-bubbles icon for gaul, a map pin for regional. Icon plus text, never color-only, so it reads clearly at a glance. Old, never-labeled examples show no tag at all — that's deliberate honesty, not a bug; we're not pretending old content is labeled when it isn't.

What stayed untouched (CD1's bound): no restyle of the card, no change to the arrow-key rating controls, no change to layout — the ONLY visible difference is the small tag next to each example.

CD5

The "N of M" position bar — built once, shared everywhere

A reality check surfaced first: this was assumed already shipped and just needing extension. It wasn't.

Built once, as a shared block that any card can opt into: a group name, "N of M" position count, and a fill bar showing progress through the group. It now leads the reveal (the answer-side of the card) on:

When a card has no group, the bar is hidden entirely — no empty "0 of 0" clutter.

CD2 / Learn parity

The Learn sheet stopped lying to non-vocabulary cards

An audit found the Intro badge was already consistent everywhere — the real gap was the Learn sheet.

The problem: the Learn sheet's mini-games were designed for vocabulary words — things like a letter-scramble game. On a grammar-rule card, that game would scramble the letters of the RULE'S TITLE, which makes no sense. On top of that, the empty-state copy always said "more learning aids as this word gets enriched" — a promise that's simply false for a rule, vow, or passage card; those will never get vocabulary-style memory aids.

The fix: non-vocabulary cards (rule, concept, passage) now only get sheet chips that actually make sense for them — right now that's the progress widget — plus copy that honestly points at that card's own lesson content instead of a vocabulary promise it can't keep. Vocabulary cards are completely unchanged, byte-for-byte.

Handoffs

Two threads handed off, not dropped

1
Rule-lesson register labels → concurrent ENR session. The same four-value register enum belongs in the grammar-rule generation code too, but that file had an in-flight, uncommitted sweep running in a parallel session. Rather than risk changing their live run's behavior mid-sweep, this was handed off as a briefing — accepted the same day, lands right after their sweep finishes.
2
A grammar_examples table deletion, requested of UI, is queued behind this work — not yet actioned, tracked so it doesn't fall through.
Decisions ledger

What was decided, and by whom

1
CD3: adopt register layers now, at the rich four-value granularity
Store the full formal/standard/gaul/regional shape always — any simpler on-screen version (like a 3-point scale) is a display choice layered on top later, never the stored truth ("store rich, render to taste").
Decided by Frank
2
CD1: the mockup gallery is structure/content reference only
No restyling the live app to match old mockups. Existing interaction patterns — including the arrow-key rating buttons — are explicitly out of scope for any of this work.
Decided by Frank
3
CD5: the position/structure block is shared, including passage cards
One shared block, not a rule-only feature copied over to passages later. This decision also surfaced the reality check that it hadn't shipped anywhere yet.
Decided by Frank
4
Learn and Intro-badge behavior should be consistent across every card archetype
Riding the same build directive as the CD-series answers — vocabulary is the reference pattern every other archetype gets measured against.
Inferred from what you said
5
Don't backfill the ~470 existing example sets this pass
Old examples stay unlabeled (shown with no tag) so the new pipeline ships clean; a cheap labeling pass is left as a deliberate later decision, not forgotten work.
Inferred from what you said
6
The A2-and-up "at least 1 formal + 1 gaul" floor is a starting default, not a locked rule
It's a single constant in the prompt code — easy to move up or down a level once real examples are reviewed.
Inferred from what you said
Worth your eye

Five things to look at or answer

🎚️
FK-A — the A2+ floor for formal+gaul examples: right band? Right now, senses taught at A2 or above are required to get at least one formal and one gaul example. A1 stays gaul-free. This is one constant in the code — easy to slide up or down a CEFR level.
🏷️
FK-B — should the "standard" tag even show? All four register values currently render a visible tag, including "standard" (the majority case). Should standard stay silent instead — like how the lifecycle badge only shows up for unusual states — so only formal/gaul/regional draw the eye?
🗃️
FK-C — the ~470 old example sets show no register tag at all. Backfill, or wait? A cheap LLM labeling pass over the existing examples is possible any time; the alternative is leaving them unlabeled until each word naturally gets re-enriched.
📊
FK-D — the position bar always leads the reveal, fully expanded. Right prominence? It's the first thing shown on the reveal side for any grouped rule/vow/passage card — group name, "N of M," fill bar. Is that the right amount of real estate, or should it be quieter?
📖
FK-E — the Learn sheet on rule/concept/passage cards is honest now, but thin. Priority on the real fix? The actual intended solution is a dedicated Rule Study Page (already named as future work in ADR-084's D4) — a proper study surface instead of a stripped-down vocabulary sheet. How high should that sit on the list?