Skip to content

fix: reading line is a conversation, not a lesson (translations click/hover-only)#48

Merged
mergify[bot] merged 3 commits into
mainfrom
fix/conversation-not-lesson
Jul 4, 2026
Merged

fix: reading line is a conversation, not a lesson (translations click/hover-only)#48
mergify[bot] merged 3 commits into
mainfrom
fix/conversation-not-lesson

Conversation

@julianken

Copy link
Copy Markdown
Owner

Diagrams

The reading line stops teaching inline; the romanization moves to the click card.

flowchart LR
    subgraph Before["Before — violates the law"]
        b_word["Arabic word سُوق"] --> b_line["reading line: script + INLINE romanization sūq"]
        b_word -.click.-> b_card["word card: meaning only"]
        b_fix["fixture scaffold: 'the neighborhood market', '— that means: can.'"] --> b_line
    end
    subgraph After["After — conversation, not lesson"]
        a_word["Arabic word سُوق"] --> a_line["reading line: SCRIPT ONLY (wash + ḥarakāt fade)"]
        a_word -- click/hover --> a_card["word card: root · pattern · PRONUNCIATION sūq · gloss"]
        a_fix["fixture scaffold: pure-context prose, no translation"] --> a_line
    end
    Before ==>|fix| After
Loading

Summary

  • Fixes a reading-pedagogy DESIGN violation: the conversation is a conversation, not a lesson, so the reading line must teach nothing inline. The shipped build (feat(ar): transliteration sub-label + gentle-blend demo (to Figma frame 77:2) #46) stacked a Latin romanization sub-label under each new/learning Arabic word, and the demo fixtures spelled meanings out inline ("the neighborhood market", "— that means: can."). Both are undone.
  • The romanized pronunciation is not deleted — it moves to the only sanctioned surface: the click/hover word-card. ArBreakdownPanel gains a pronunciation row (root · pattern · pronunciation · gloss) fed by the unchanged translit annotation; the reading line now renders each token as script only (its <bdi> + ḥarakāt fade + status wash + click).
  • DESIGN.md was already corrected in this branch (the new ### Reading pedagogy — the binding law subsection + the reworked Tokens / word-card / known-gaps entries); this PR is the code + fixtures catching up to that binding law. Committed as the first commit here.

Screenshots

Local Playwright render of /?fixture=ar-blend-intro&delayMs=0 against a locally-built site + fixtures server (no deploy). Not committing PNGs (per screenshot policy); the DOM evidence from the drive:

  • Reading line (script only): Let's ease in. Picture a slow morning — you slip into the سُوق before the stalls fill up, order a small قَهوة from the first vendor who's awake, and sip it on a step while the rest of the مدينة stirs. — no data-translit, no lang="ar-Latn" sub-label, and no sūq/qahwa or market/coffee/city gloss text anywhere inline. (قَهوة / مدينة show fewer ḥarakāt than their diacritized form — the expected learning/known fade, not a regression.)

  • Click سُوق → card: panel row order is exactly root(س و ق) · pattern(فُعْل) · pronunciation(sūq — lang="ar-Latn", JetBrains Mono, muted-soft rgb(180,172,157)) · gloss(market · NOUN).

  • browser_console_messages(error): only a pre-existing favicon.ico 404 — no app errors/warnings.

  • Local Playwright drive at desktop viewport (default); mobile not separately captured (removal-only UI change, no new responsive surface)

  • Matches the design language in DESIGN.md — the reading-pedagogy binding law; pronunciation styled with the transliteration type tokens

  • No Figma update needed — canonical frame 77:2 already shows the card-reveal model; the shipped build was what diverged, so this PR reconverges the build to the existing frame (no visible delta to push back)

Test plan

  • pnpm run build && pnpm run typecheck && pnpm run test — all green (build 8/8; typecheck 8/8; tests: lang-ar 47, web 39, server 54 + 9 skipped, plus lang-fake / lang-zh / conformance — all pass)
  • pnpm run boundary:renderer-neutrality + pnpm run boundary:lang-conditional — PASS
  • pnpm run spec:generate:node then git diff --exit-code on ar-annotations.schema.jsonclean (schema untouched; the translit field stays, it now feeds the card)
  • New/updated unit tests: ar-word-token.test.tsx flipped to assert no inline romanization for any status + that ArBreakdownPanel shows the pronunciation row when opened (and omits it when translit absent); base-direction tests untouched
  • New Playwright e2e spec — N/A: the built-UI click/panel path stays covered by the existing renderer.spec.ts (on the untouched ar-mixed-line fixture); the ar-blend-intro behavior was verified via a local MCP smoke drive (above)
  • Drift-prone docs: DESIGN.md updated (the binding law, committed here); tokens.json untouched — the pronunciation row reuses existing --la-font-mono / --la-type-annotation-size / --la-color-muted-soft tokens (no new/changed token); No Figma update needed (frame 77:2 already shows the card-reveal model). AGENTS.md / CLAUDE.md not touched — shim check N/A.

Plan / issue reference

Out of plan — corrective fix for the reading-pedagogy violation shipped in #46, reconverging the build to DESIGN.md's new binding law (conversation-not-lesson; translation is click/hover-only).


🤖 Generated with Claude Code

julianken and others added 3 commits July 4, 2026 08:00
The reading line teaches nothing inline: no inline romanization, no inline
gloss, no "means: X". A word's romanized pronunciation and meaning are
revealed only on demand in the click word-card popover. Removes the
`token-translit` inline sub-label from the Tokens spec, adds the romanized
pronunciation to the word-card, and adds the "Reading pedagogy — the binding
law" subsection as the governing rule the ar/zh corpora and renderers follow.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… card

Undoes the inline transliteration sub-label that violated the reading-pedagogy
binding law (DESIGN.md §Components): ArWordToken no longer stacks a Latin
romanization beneath a new/learning Arabic word — the token renders script
only (its `<bdi>` with ḥarakāt fade + status wash + click), same as before the
sub-label landed. The romanized pronunciation now surfaces only on click, in a
new `data-breakdown-pronunciation` row of ArBreakdownPanel (root · pattern ·
pronunciation · gloss), styled with the `transliteration` type tokens
(--la-font-mono / --la-type-annotation-size / --la-color-muted-soft) and
omitted when the token carries no `translit`. The `translit` annotation field
is unchanged — it now feeds the card instead of the line. RED withholding, the
`<bdi dir="auto">` isolate + ambiguous-first fallback, and the ḥarakāt fade are
untouched. Unit test flipped to assert no inline romanization for any status
and that the panel shows the pronunciation row when opened.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…lation)

The demo fixtures spelled a target word's meaning out inline — "the
neighborhood market" after سُوق, and "— that means: can." after 可以 — which
the reading-pedagogy binding law forbids (the reading line never translates a
target word). Rewrites both English scaffolds into natural, pure-context prose
where the surrounding sentence carries the sense: the learner meets سُوق /
قَهْوَة / مَدِينَة inside a slow-morning scene, and 可以 inside "take the window
seat if you'd like." The Arabic and Chinese word tokens and every one of their
gate-verified annotations (diac/skeleton/vowelState/morphology/translit/gloss;
perCharacter/citationPinyin/surfacePinyin/etc.) are kept exactly — only the
surrounding English `text` tokens change, and the meaning-stating tokens are
dropped. ar blend.ratio stays 0.2 (arWords 3/12 = 0.25, under the fixture
test's 0.34 ceiling). Fixture-test comment reworded: the translit annotation
now feeds the click card, not an inline sub-label.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@cursor

cursor Bot commented Jul 4, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@julianken-bot julianken-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: APPROVE

Design-correctness fix: the /ar reading line stops teaching inline; romanization moves to the click card. The central risk — does any inline romanization or meaning-gloss survive in the reading line or fixtures? — verified NO, at the code, fixture, test, and doc level.

Verification ledger (all run this turn, worktree @ 4e69ec3)

  • pnpm install --frozen-lockfile → OK; pnpm run build8/8 green.
  • pnpm run testall green: lang-ar 47, lang-zh 64, lang-fake 66, lang-conformance 20, web 39, server 54 (+9 skipped).
  • pnpm run boundary:renderer-neutralityPASS (both gates, exit 0).
  • pnpm run spec:generate:node + git diffar-annotations.schema.json CLEAN (no drift; translit field retained, now feeds the card).
  • Mermaid render check → 1 block, ok: true (R15 pass).
  • ArWordToken.tsx inline render: <bdi> script only + click-panel. Grep for data-translit / lang="ar-Latn" / transliterationStyle in the token/shell → none in any inline render path; the only ar-Latn in a render position is the card's new pronunciation row. Tests assert its inline absence for every status (new/learning/known/RED).
  • ArBreakdownPanel.tsx: gains a data-breakdown-pronunciation row (root · pattern · pronunciation · gloss); data-breakdown-gloss row intact. Schema: morphology is required, translit optional, and both come from the same parsed ann — so the pronunciation row's nesting under {morphology ? …} has no "translit-without-morphology" hole.
  • Fixtures: Arabic word tokens in ar-blend-intro.json and the zh 可以 token in zh-mixed-line.json are byte-identical to base (only English scaffold text tokens changed; the meaning-stating tokens dropped). ar fixture still validates against ArAnnotationsSchema (server test green).
  • Base-direction (LTR gentle blend): ar-message-container.test.tsx untouched by this PR — the correct feature is preserved.
  • Doc-currency: DESIGN.md carries the new binding law; grep confirms no surviving "in-text romanization ships" / token-translit sub-label claim (the line-9/128 "training wheels" is the FADE metaphor, not romanization). tokens.json untouched (reuses --la-font-mono / --la-type-annotation-size / --la-color-muted-soft). AGENTS.md/CLAUDE.md not touched (shim check N/A). No Figma update needed is coherent (frame 77:2 already shows the card-reveal model).

Findings

SUGGESTION — no rendered before/after screenshot for a UI-visible change. The PR touches UI source (ArWordToken.tsx, ArBreakdownPanel.tsx) and, beyond removing the inline sub-label, adds a new visible surface (the card's pronunciation row) — so "removal-only UI change" in the body slightly undersells it. The body carries DOM-text evidence + a clean-console report but no user-attachments image. Given the change is removal-dominant, the panel-open path is covered by renderer.spec.ts, and the structure/token-binding is unit-pinned, this is polish, not a blocker — but a before/after of (a) the script-only reading line and (b) the click card's new pronunciation row would harden the per-HEAD screenshot record and visually confirm RTL/ḥarakāt still render. Not merge-blocking.

Bottom line

The build obeys the binding law: reading line = script only, romanization = card-only, gate-verified annotations preserved, base-direction feature intact, docs reconciled, all gates green. Clean APPROVE.

@julianken-bot (opus). Same-tier note: implementer was Claude Opus 4.8 (same tier as this reviewer); I ran the full build/test/boundary/spec suite myself rather than trusting the reported "all green," and did a mandatory second pass — the strongest candidate defect (pronunciation row gated behind morphology) dissolved under the schema's required-morphology invariant.

@julianken

Copy link
Copy Markdown
Owner Author

@Mergifyio queue

@mergify

mergify Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Queued — the merge queue status continues in this comment ↓.

@mergify

mergify Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Merge Queue Status

  • Entered queue2026-07-04 15:10 UTC · Rule: default · triggered by @julianken with the @mergifyio queue command
  • Checks skipped · PR is already up-to-date
  • Merged2026-07-04 15:10 UTC · at 4e69ec3540d74cf1ec48af47bb14b71c5fba5ba9 · squash

This pull request spent 8 seconds in the queue, including 1 second running CI.

Required conditions to merge
  • github-review-approved [🛡 GitHub repository ruleset rule main]
  • any of [🛡 GitHub repository ruleset rule main]:
    • check-success = validate
    • check-neutral = validate
    • check-skipped = validate
  • any of [🛡 GitHub repository ruleset rule main]:
    • check-success = build
    • check-neutral = build
    • check-skipped = build
  • any of [🛡 GitHub repository ruleset rule main]:
    • check-success = sidecar-ar
    • check-neutral = sidecar-ar
    • check-skipped = sidecar-ar
  • any of [🛡 GitHub repository ruleset rule main]:
    • check-success = sidecar-zh
    • check-neutral = sidecar-zh
    • check-skipped = sidecar-zh
  • any of [🛡 GitHub repository ruleset rule main]:
    • check-success = conformance (fake)
    • check-neutral = conformance (fake)
    • check-skipped = conformance (fake)
  • any of [🛡 GitHub repository ruleset rule main]:
    • check-success = e2e
    • check-neutral = e2e
    • check-skipped = e2e
  • any of [🛡 GitHub repository ruleset rule main]:
    • check-success = conformance (ar)
    • check-neutral = conformance (ar)
    • check-skipped = conformance (ar)
  • any of [🛡 GitHub repository ruleset rule main]:
    • check-success = conformance (zh)
    • check-neutral = conformance (zh)
    • check-skipped = conformance (zh)

@mergify mergify Bot added the queued label Jul 4, 2026
@mergify mergify Bot merged commit be9ce57 into main Jul 4, 2026
17 checks passed
@mergify mergify Bot deleted the fix/conversation-not-lesson branch July 4, 2026 15:10
@mergify mergify Bot removed the queued label Jul 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants