Skip to content

course: #/course, 27 lessons from zero to a chip, orchestrated by .t27 specs - #1420

Merged
gHashTag merged 6 commits into
mainfrom
feat/course
Oct 5, 2026
Merged

gHashTag merged 6 commits into
mainfrom
feat/course

Conversation

@gHashTag

@gHashTag gHashTag commented Oct 5, 2026 •

Copy link
Copy Markdown
Owner

A course at #/course: 27 lessons from "what is an FPGA" to a bitstream on a real board, one working widget per lesson, for people who have never written hardware. The course is a t27 program: specs/course/course.t27 holds the order, the widget each lesson opens and every English word; the Russian words live in i18n/course.ru.json under the contract specs/course/course-ru.t27 (L3 keeps .t27 ASCII).

Stacked on #1413 (the nine widgets the course embeds and the main typecheck fix); this PR will be rebased when that one lands.

Shape. 9 modules x 3 lessons: the chip, numbers in hardware, your t27 program, the compiler (t27c and t27b), from spec to logic, reading synthesis, place and route, the bitstream, on the board. All 42 gallery widgets are used; each lesson has its own main widget, and 10 lessons also open their tutorial spec in the player.

Page. Pure black, no green fields. A 9 x 3 map where a finished lesson is a white cell (progress in localStorage, nothing sent), and a lesson page with goal, text, a task, the widget in a relative iframe, chips that swap in the also-try widgets or the lesson's spec, prev/next. EN and RU follow the site's language button; widgets keep their own English words.

Checks. scripts/course-from-spec.mjs compiles both specs with the wasm t27c and runs their test blocks; fails on a widget id not in the gallery, a gallery widget left unused, a repeated main widget, a lesson spec that does not compile clean on all 7 backends, an RU string whose digits or placeholders differ from the EN one, a missing or orphan RU key, or a superlative in either language. website-checks runs it with --check plus its 15 tests.

The paid FPGA training that lived at #/course moves to #/fpga-training; the nav note and the two Verification links follow.

Closes #1414
Closes #1415
Closes #1416
Closes #1417
Closes #1418
Closes #1419
Closes #1395

{
  "version": 1,
  "head_sha": "d4fad37373c83cf76c5e0aca6dd94f64959fca38",
  "summary": "A 27-lesson course at #/course, from what an FPGA is to a bitstream on a board, orchestrated by specs/course/course.t27 and rendered on a black page in English and Russian, one gallery widget per lesson.",
  "changes": [
    "specs/course/course.t27: 9 modules, 27 lessons, the widget, also-try widgets and tutorial spec of each lesson, every English word, 4 test blocks.",
    "specs/course/course-ru.t27 and i18n/course.ru.json: the Russian words under a contract that requires full coverage and no orphan keys.",
    "scripts/course-from-spec.mjs (+15 tests) writes src/lib/course.generated.ts and public/learn/course.t27; wired into prebuild, prebuild:ci and website-checks.",
    "src/pages/Course.tsx and Course.css: the map and the lesson page; the old paid course page becomes src/pages/FpgaTraining.tsx at #/fpga-training.",
    "Two widgets the course needed: lut-treemap (yosys stat hierarchy as a treemap) and t27c-stages (the wasm compiler's stages on a real spec); the gallery holds 42.",
    "Three more widgets, each from its own spec under specs/widgets/: t27-cell, t27-vs-nvfp4 and uart-bucket; the course grows to 30 lessons in 10 modules and the gallery to 45.",
    "qa/browser-audit.mjs visits #/course/hello-t27 so the language audits see a lesson page as well as the map."
  ],
  "tests": [
    {"command": "node scripts/course-from-spec.mjs --check", "result": "30 lessons in 10 modules, 45 widgets, 10 lesson specs compile clean; locales en, ru; spec tests 6, asserts 24, all hold", "status": "passed", "evidence": "Local run on this branch."},
    {"command": "node --test scripts/course-from-spec.test.mjs", "result": "15 pass, 0 fail", "status": "passed", "evidence": "Local run on this branch."},
    {"command": "node scripts/widgets-from-spec.mjs --check && node scripts/widget-pages-from-spec.mjs --check", "result": "45 widgets, spec tests 7 / asserts 22; 27 tool pages, spec tests 140 / asserts 740, all hold", "status": "passed", "evidence": "Local run on this branch."},
    {"command": "npm run typecheck:ratchet", "result": "179 errors across 26 files; baseline 179 across 26; no file gained", "status": "passed", "evidence": "Local run on this branch."},
    {"command": "npm run check:subpath-urls", "result": "409 source files, 2 message files and public/manifest.json, 8 known exceptions -- ok", "status": "passed", "evidence": "Local run on this branch."},
    {"command": "vite dev, #/course and lessons 5, 11, 27 at 1280 px and 375 px, EN and RU", "result": "black page, widget and spec player load in the iframe, mark-done persists across reload, no sideways scroll at 375 px, no English-only line in RU on the four routes checked", "status": "passed", "evidence": "Local preview; Chrome is not installed on this Mac, so qa/ru_audit.mjs itself runs only in CI."}
  ],
  "limitations": [
    "Widgets inside the iframes keep their own English words; only the course's own text is bilingual.",
    "Progress is per browser; there is no account and nothing is sent.",
    "A crawler fetching t27.ai/#/course gets the home page's preview: per-route og pages live in the apex repository and are not part of this PR.",
    "The t27c-stages builder found seven compiler defects (the HIR Verilog backend emits no adder logic, typecheck errors do not stop the backends, an undeclared name passes typecheck, among others); they are reported as t27 issues, not fixed here."
  ],
  "tags": ["t27", "FPGA", "Course", "Widgets"],
  "blog": {
    "title": "From zero to a chip: a 27-lesson FPGA course written as a t27 spec",
    "summary": "Every lesson opens a real tool built from runs on our bench, and the course itself is a .t27 file the compiler checks.",
    "outline": [
      "Why a course for people who have never written hardware starts at the chip, not at Verilog.",
      "The 9 x 3 shape: chip, numbers, your program, the compiler, logic, synthesis, place and route, bitstream, board.",
      "The course as a program: test blocks that fail the build on an unused widget or a translated number that changed.",
      "What building the compiler lesson found in t27c itself: seven defects, from a Verilog backend with no adder logic to typecheck errors that do not stop codegen."
    ]
  }
}

🤖 Generated with Claude Code

@github-actions github-actions Bot added the status:in-progress 🔵 Agent working label Oct 5, 2026
gHashTag and others added 2 commits October 5, 2026 12:57
lut-treemap draws yosys stat -json hierarchy as a treemap: which submodule
eats the LUTs. t27c-stages runs the wasm t27c on a real spec in the reader's
browser and shows each stage (lex, parse, typecheck, the seven backends).
Both are gallery entries 28 and 35; the gallery now holds 42 widgets.

Closes #1395
Closes #1418

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…cs/course/course.t27

The course is a t27 program. specs/course/course.t27 orders 9 modules x 3
lessons, names the widget each lesson embeds, its also-try widgets and its
tutorial spec, and holds every English word; specs/course/course-ru.t27 is
the contract for the Russian bundle i18n/course.ru.json (L3 keeps .t27
ASCII). scripts/course-from-spec.mjs compiles both, runs their test blocks,
requires every gallery widget to be used, every lesson spec to compile clean
on all 7 backends, and every RU string to keep the EN digits and
placeholders; it writes src/lib/course.generated.ts and public/learn/course.t27.

src/pages/Course.tsx only draws the generated file: pure black, a 9 x 3
map with progress in localStorage (nothing is sent), and a lesson page with
the widget in a relative iframe, chips to swap in the also-try widgets or the
lesson's spec in the player, prev/next. EN and RU follow the site's language.

The paid FPGA training that lived at #/course moves to #/fpga-training.
CI: website-checks runs check:course and test:course; the language audits
visit #/course/hello-t27 as well as #/course.

Closes #1414
Closes #1415
Closes #1416
Closes #1417

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

X Brain Health Check

Score: 100.0/100
Status: 🟢 HEALTHY
Threshold: 80/100

X Brain is above merge threshold

…ap, outlined numerals

Owner, 2026-10-05: large type and headlines as in a men's glossy. Pure black
stays; no green. The serif is the reader's system Didot/Bodoni (Georgia
fallback, which also carries Cyrillic); nothing is downloaded. Long Russian
words hyphenate and the minimum size drops so 375 px has no overflow
(scrollWidth 459 -> 375).

Closes #1417

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Outfit 800 for every headline, cover numeral, drop cap and pull quote;
JetBrains Mono for lesson numbers and spec paths; no serif, no italics.
Long Russian words hyphenate instead of breaking mid-air. Checked at
1440 px and 375 px (scrollWidth 375 on the map and three lessons).

Closes #1417

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

🧪 Brain Stress Test Results

Tests: 261/261 passed, 0 leaked
Status: 🟢 PASS
Gate: every test in zig build test-brain-stress passes and none leaks

gHashTag and others added 2 commits October 5, 2026 13:15
var(--font) instead of var(--font, ...) so qa/queen-fallback-parity.mjs
sees one font stack (it failed 230/233 on the previous push). The
progress bar takes its column count from the generated lesson list
instead of a hard-coded 27.

Closes #1417

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-vs-nvfp4, uart-bucket)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@gHashTag
gHashTag merged commit 8da219c into main Oct 5, 2026
33 of 35 checks passed
@github-actions github-actions Bot added status:completed Done and removed status:in-progress 🔵 Agent working labels Oct 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment