diff --git a/AGENTS.md b/AGENTS.md index 3a9114cf1f..4d0ccad08e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -20,6 +20,57 @@ Read the blog skill before writing content. Preserve the user's img2img triptych, mandatory hashtags, truthful limitations and relevant service offer. Never omit the work report for a small, documentation-only or automation PR. +## New course to open a topic (Queen and every bee) + +When a topic needs explaining, the answer is a course: **9 modules of 3 +lessons each, 27 lessons** (owner, 2026-10-07). One topic is one course; two topics are two +courses, chained (the last lesson opens lesson 1 of the next). Live chain: +0 t27 basics -> 1 FPGA -> 2 AI numbers. + +The recipe is a t27 module, not this prose: +[specs/course_recipe/course-27.t27](specs/course_recipe/course-27.t27) (steps, +rules, gates, cast commands; its tests hold the order). Planned courses: +[specs/course_recipe/roadmap.t27](specs/course_recipe/roadmap.t27). Read both +first; this section only points at them. + +In short, so the Queen can assign it: + +1. Copy the newest course spec in `apps/website/specs/course/` with its `-ru` + twin, rename ID / ROUTE / SHARE_PATH, register it in `courses.t27`. +2. Every lesson: one widget unique across all courses, one t27 spec that + compiles in the browser, black-and-white infographic or card. +3. Run the generators from `apps/website` (all-or-nothing): + `widgets-from-spec.mjs`, `widget-pages-from-spec.mjs`, + `course-from-spec.mjs`, `course-pages.mjs`; then the `check:course*`, + `check:widgets`, `check:onboarding` gates. +4. Casts are recorded only through `tri` commands; a lesson without a recording + says "pending", never fakes one. +5. The same PR carries its blog post (`body` English + `ruBody` Russian) and the + work report above. +6. Main moved under the PR: merge `origin/main` in, never rebase/force push. + A merged trinity PR is not live: ship through the + `release(board): ship trinity ` PR in gHashTag/999-multibots-telegraf. + +Traps found by the first course built from this section alone (trinity#1470, +full list in its "Recipe gaps"): + +- Rename **ID, ROUTE, SHARE_PATH, RU_CONTRACT and GENERATED** in the copied spec. +- Code edits the recipe needs: route, starfield root and nav entry in `src/`; + blog post registered in `src/data/blog/index.ts` and `posts.ts`. +- `gallery.t27` keeps each category as one unbroken block: insert the new + widgets inside their category, then fix the index asserts in the gallery + tests; `course-from-spec.test.mjs` asserts the course count, bump it. +- Full gate list: `check:widgets`, `test:widgets-spec`, `check:widget-pages` + (run widget-pages before widgets), `check:course`, `test:course`, + `check:course-pages`, `check:course-recipe`, `check:onboarding`, + `check:play`, `tsc --noEmit`. +- A pending lesson still needs a gallery entry; ship it as a + `public/term//` placeholder with `pending`, never a fake widget. +- Russian widget words go in `i18n/widgets.ru.json` under the contract + `specs/widgets/i18n/widgets-ru.t27` (no Cyrillic in specs); the Russian text + must keep the same digits as the English. +- Work-report format: copy the `` block of trinity#1463. + **Version**: 2.0 **Date**: 2026-04-04 **Status**: Active diff --git a/apps/website/src/data/blog/bodies/the-queen-knows-how-to-build-a-course.ts b/apps/website/src/data/blog/bodies/the-queen-knows-how-to-build-a-course.ts new file mode 100644 index 0000000000..fb783c7de0 --- /dev/null +++ b/apps/website/src/data/blog/bodies/the-queen-knows-how-to-build-a-course.ts @@ -0,0 +1,19 @@ +import type { Block } from '../types' + +export const body: Block[] = [ + { "kind": "h", "text": "What changed" }, + { "kind": "p", "text": "The recipe for a t27 course used to live in one agent's private skill folder, where the Queen and her bees could not read it. It now lives in the repository as two t27 modules: specs/course_recipe/course-27.t27 (the steps, rules, gates and cast commands, with tests that hold their order) and specs/course_recipe/roadmap.t27 (the planned courses). AGENTS.md gains a short section that points at them, so any agent asked to open a topic knows the shape: 9 modules of 3 lessons, one topic per course, courses chained." }, + { "kind": "h", "text": "What is checked" }, + { "kind": "p", "text": "Both modules compile clean in the site's own wasm compiler: course-27.t27 has 7 tests with 26 asserts, roadmap.t27 has 4 tests with 30 asserts. Nothing yet runs them in CI; that is the next gap." }, + { "kind": "h", "text": "Limits" }, + { "kind": "p", "text": "A recipe is not a course. No new lessons ship with this PR, and the casts of the existing courses are still pending where the post of each course says so." } +] + +export const ruBody: Block[] = [ + { "kind": "h", "text": "Что изменилось" }, + { "kind": "p", "text": "Рецепт курса t27 жил в личной папке навыков одного агента, куда Королева и её пчёлы не могли заглянуть. Теперь он лежит в репозитории двумя модулями t27: specs/course_recipe/course-27.t27 (шаги, правила, шлюзы и команды записи, а тесты держат их порядок) и specs/course_recipe/roadmap.t27 (план курсов). В AGENTS.md появился короткий раздел со ссылкой на них, так что любой агент, которому поручили раскрыть тему, знает форму: 9 модулей по 3 урока, одна тема — один курс, курсы идут цепочкой." }, + { "kind": "h", "text": "Что проверено" }, + { "kind": "p", "text": "Оба модуля чисто собираются компилятором сайта на wasm: в course-27.t27 7 тестов и 26 проверок, в roadmap.t27 4 теста и 30 проверок. В CI их пока ничто не запускает — это следующая дыра." }, + { "kind": "h", "text": "Ограничения" }, + { "kind": "p", "text": "Рецепт — ещё не курс. Новых уроков в этом PR нет, а записи существующих курсов по-прежнему ждут там, где об этом сказано в посте каждого курса." } +] diff --git a/apps/website/src/data/blog/index.ts b/apps/website/src/data/blog/index.ts index 36fe7f4b98..a9b0f87569 100644 --- a/apps/website/src/data/blog/index.ts +++ b/apps/website/src/data/blog/index.ts @@ -253,6 +253,29 @@ export const postsIndex: PostMeta[] = [ ], }, }, + { + slug: "the-queen-knows-how-to-build-a-course", + title: "The Queen now knows how to build a course", + summary: "[a recipe, not a course; the recipe modules compile but no CI job runs their tests yet] The t27 course recipe moved from one agent's private folder into the repository as two t27 modules, and AGENTS.md points at them, so the Queen can assign a new 27-lesson course for any topic.", + date: "2026-10-07", + readingMinutes: 2, + tags: ["t27", "Course", "Agents"], + receipts: [ + { label: "The recipe, specs/course_recipe/course-27.t27", href: "https://github.com/gHashTag/trinity/blob/main/specs/course_recipe/course-27.t27" }, + { label: "The plan, specs/course_recipe/roadmap.t27", href: "https://github.com/gHashTag/trinity/blob/main/specs/course_recipe/roadmap.t27" }, + ], + openQuestions: [ + "No CI job runs the recipe's tests yet.", + ], + published: true, + ru: { + title: "Королева теперь знает, как собрать курс", + summary: "[рецепт, а не курс; модули рецепта собираются, но их тесты пока не запускает CI] Рецепт курса t27 переехал из личной папки одного агента в репозиторий двумя модулями t27, а AGENTS.md ссылается на них, так что Королева может поручить новый курс из 27 уроков на любую тему.", + openQuestions: [ + "Тесты рецепта пока не запускает ни одно задание CI.", + ], + }, + }, { slug: "a-course-pr-carries-its-post", title: "A course PR now carries its blog post", diff --git a/apps/website/src/data/blog/posts.ts b/apps/website/src/data/blog/posts.ts index a3f3618c5b..e22ed349ae 100644 --- a/apps/website/src/data/blog/posts.ts +++ b/apps/website/src/data/blog/posts.ts @@ -4,6 +4,7 @@ import { body as body_course_three_verifying_hardware, ruBody as ruBody_course_t import { body as body_course_zero_t27_basics, ruBody as ruBody_course_zero_t27_basics } from './bodies/course-zero-t27-basics' import { body as body_tri_test_now_runs_the_tests, ruBody as ruBody_tri_test_now_runs_the_tests } from './bodies/tri-test-now-runs-the-tests' import { body as body_two_courses_twenty_seven_lessons_each, ruBody as ruBody_two_courses_twenty_seven_lessons_each } from './bodies/two-courses-twenty-seven-lessons-each' +import { body as body_the_queen_knows_how_to_build_a_course, ruBody as ruBody_the_queen_knows_how_to_build_a_course } from './bodies/the-queen-knows-how-to-build-a-course' import { body as body_a_course_pr_carries_its_post, ruBody as ruBody_a_course_pr_carries_its_post } from './bodies/a-course-pr-carries-its-post' import { body as body_one_outlier_twenty_three_zeros, ruBody as ruBody_one_outlier_twenty_three_zeros } from './bodies/one-outlier-twenty-three-zeros' import { body as body_a_terminal_for_seven_backends_in_an_x_post, ruBody as ruBody_a_terminal_for_seven_backends_in_an_x_post } from './bodies/a-terminal-for-seven-backends-in-an-x-post' @@ -110,6 +111,7 @@ const bodies: Record = { 'course-zero-t27-basics': { body: body_course_zero_t27_basics, ruBody: ruBody_course_zero_t27_basics }, 'tri-test-now-runs-the-tests': { body: body_tri_test_now_runs_the_tests, ruBody: ruBody_tri_test_now_runs_the_tests }, 'two-courses-twenty-seven-lessons-each': { body: body_two_courses_twenty_seven_lessons_each, ruBody: ruBody_two_courses_twenty_seven_lessons_each }, + 'the-queen-knows-how-to-build-a-course': { body: body_the_queen_knows_how_to_build_a_course, ruBody: ruBody_the_queen_knows_how_to_build_a_course }, 'a-course-pr-carries-its-post': { body: body_a_course_pr_carries_its_post, ruBody: ruBody_a_course_pr_carries_its_post }, 'one-outlier-twenty-three-zeros': { body: body_one_outlier_twenty_three_zeros, ruBody: ruBody_one_outlier_twenty_three_zeros }, 'a-terminal-for-seven-backends-in-an-x-post': { body: body_a_terminal_for_seven_backends_in_an_x_post, ruBody: ruBody_a_terminal_for_seven_backends_in_an_x_post }, diff --git a/specs/course_recipe/course-27.t27 b/specs/course_recipe/course-27.t27 new file mode 100644 index 0000000000..641009e6aa --- /dev/null +++ b/specs/course_recipe/course-27.t27 @@ -0,0 +1,175 @@ +// SPDX-License-Identifier: Apache-2.0 +; course-27.t27 -- turn any topic into a t27 course: 9 modules of 3 lessons each +; This file IS the skill. SKILL.md next to it only points here. Every step, rule and gate +; below is a constant, and the test blocks hold the order and the shape, so a step cannot +; be dropped or moved without a red test. Compile and test it with the site's own compiler: +; any harness that calls loadCompiler (scripts/agents-from-specs.mjs) and runSpecTests (scripts/viewport-from-spec.mjs) in apps/website +; (or any harness that calls loadCompiler + runSpecTests from gHashTag/trinity +; apps/website/scripts). ASCII only, English only. + +; THE LIVING TEMPLATE is the newest course spec on the site, not a copy kept here: +; gHashTag/trinity apps/website/specs/course/ai-numbers.t27 (course 2) +; gHashTag/trinity apps/website/specs/course/courses.t27 (the catalog, the order) +; Copy the newest course spec, rename ID / ROUTE / SHARE_PATH / RU_CONTRACT, then replace +; the words. A template kept here would drift from the generator; that is the recorded +; defect of this codebase family (one rule in three files, two of them right). + +; WHAT A COURSE IS: 9 modules of 3 lessons each, 27 lessons (a TRI-27 word; +; owner's decision 2026-10-07: 9 modules of 3; a flattening to 27 modules of 1 was a +; misreading and was reverted). One course per topic. +; Two topics are two courses, chained: the last lesson of one opens lesson 1 of the next, +; and each has its own address, share pages and cards, so each can be shared on its own. +; Every lesson opens ONE main widget (unique across all courses) and ONE t27 spec that +; compiles clean in the reader's browser. +; phi^2 + 1/phi^2 = 3 | TRINITY + +module course_27; + +pub const KIND : str = "skill"; +pub const SCHEMA_VERSION : u8 = 1; +pub const LESSONS : u8 = 27; +pub const MODULES : u8 = 9; +pub const LESSONS_PER_MODULE : u8 = 3; + +; Where the course lives (gHashTag/trinity, relative to apps/website). +pub const CATALOG : str = "specs/course/courses.t27"; +pub const TEMPLATE : str = "specs/course/ai-numbers.t27"; +pub const GALLERY : str = "specs/widgets/gallery.t27"; +pub const ROADMAP : str = "specs/course_recipe/roadmap.t27"; +; The first course of the catalog (course 0, t27-basics) shares at learn/, every later course at learn//; lesson pages stay at +; learn// whatever the course, so an old lesson link never breaks. +pub const SHARE_FIRST : str = "learn/"; +pub const SHARE_NEXT : str = "learn//"; + +; --- The steps, in order ----------------------------------------------------------------- +pub const STEP_COUNT : u8 = 14; +pub const STEP_IDS : [14]str = [ + "pick", + "specs", + "shape", + "words", + "russian", + "widgets", + "catalog", + "generate", + "preview", + "post", + "land", + "ship", + "social", + "learn" +]; +pub const STEP_SAYS : [14]str = [ + "Pick the topic from the roadmap and a lower-case id; the app route is #/, the share path learn//.", + "Find 27 lesson specs that compile clean in the browser player; a missing spec is written in gHashTag/t27 first (skill t27-spec-first) and reaches the site by the world scan, never hand-copied into the site.", + "Order 9 modules of 3 lessons each so each lesson uses only what earlier lessons taught; a topic that needs more than 27 lessons is two courses.", + "Copy the newest course spec, keep every SAY_ key the other courses have, and write the words: no superlatives, every number from a spec constant, a player run or a recording.", + "Write i18n/.ru.json and specs/course/-ru.t27: every field translated, the same digits and the same {N} placeholders as the English.", + "Give every lesson its own main widget; a new widget is a recording made with tri commands only, in black and white, with one planted one-line bug that fails exactly one named test and is put back in the same recording.", + "Add the course to specs/course/courses.t27: COURSE_COUNT, COURSE_IDS, COURSE_SPECS and the order test; prev and next links follow from the order.", + "Run widgets-from-spec, course-from-spec, course-pages (static pages, black-and-white cards, sitemap, hreflang) and onboarding-from-spec (llms.txt and agents.t27 name every course).", + "Preview the dev server: the course landing, lesson 1, the last lesson's link to the next course, a lesson of the previous course, a phone width.", + "Write the blog post in the same PR: English body and Russian ruBody, receipts that link the recordings and pages, limits said out loud, an SEO title and summary, and a black-and-white image for the networks.", + "Open the issue, then the PR with Closes #N and the t27-work-report block whose head_sha is the PR head; a reviewer bee merges with --match-head-commit, never --admin or --auto.", + "Ship through the gHashTag/999-multibots-telegraf release(board) PR and prove it live by the bundle, not by a green status.", + "Hand the post to the blog-share desk: one draft per network, logged per client in the CRM; nothing goes out without the owner's yes.", + "Save what this course taught into a tri command (a new one, or the old one updated) and into this file; the next course starts from both." +]; + +; --- The rules ----------------------------------------------------------------------------- +pub const RULE_COUNT : u8 = 10; +pub const RULE_IDS : [10]str = [ + "twenty-seven", + "spec-and-widget", + "casts-through-tri", + "black-and-white", + "post-per-pr", + "seo", + "no-superlatives", + "numbers-from-runs", + "no-reddit", + "owner-says-yes" +]; +pub const RULE_SAYS : [10]str = [ + "Every course is exactly 9 modules of 3 lessons each, 27 lessons; two topics are two courses, never one course of 54.", + "Every lesson opens one main widget and one t27 spec; the main widget is used by no other lesson of any course.", + "Every recording types tri commands only (sed -n to show lines, tri test, tri mutate plant, tri mutate spec, git diff); what the commands lack is added to tri first.", + "Cards, recordings and post images are white on black like the course page: no colour fields, no glows, widget pictures in greyscale.", + "A PR that changes a course carries its blog post, English and Russian, in the same PR.", + "Every course and every lesson has a static page with its own preview card, canonical link, hreflang pair and a line in learn/sitemap.xml; no page redirects.", + "No superlative in either language: no first, only, best, unique; in Russian say lesson 1, not the first lesson.", + "A number on a page comes from a spec constant, a test the player ran, or a recording; none is typed from memory.", + "No Reddit link on the course, the player or a post: r/t27ai is banned.", + "No post, mail or message leaves without the owner's explicit yes; ASK_NEEDS_YES stays true." +]; + +; --- The gates, all of them, before the PR ------------------------------------------------- +; Run from apps/website. A course PR is not ready while any of them is red. +pub const GATE_COUNT : u8 = 8; +pub const GATES : [8]str = [ + "npm run check:widgets", + "npm run test:widgets-spec", + "npm run check:widget-pages", + "npm run check:course", + "npm run test:course", + "npm run check:course-pages", + "npm run check:onboarding", + "npx tsc --noEmit -p ." +]; + +; --- Recording a lesson: the tri commands a cast types, in order --------------------------- +pub const CAST_STEP_COUNT : u8 = 5; +pub const CAST_STEPS : [5]str = [ + "sed -n p ", + "tri test ", + "tri mutate plant --file --line --from --to --expect ", + "tri mutate spec --file --fn ", + "git diff --exit-code " +]; + +test a_course_is_three_cubed { + assert LESSONS_PER_MODULE == 3; + assert MODULES == 9; + assert MODULES * LESSONS_PER_MODULE == LESSONS; + assert LESSONS == 3 * 3 * 3; +} + +test specs_come_before_words_and_widgets { + assert STEP_IDS[0] == "pick"; + assert STEP_IDS[1] == "specs"; + assert STEP_IDS[3] == "words"; + assert STEP_IDS[5] == "widgets"; +} + +test the_catalog_follows_the_widgets_and_the_generators_follow_the_catalog { + assert STEP_IDS[6] == "catalog"; + assert STEP_IDS[7] == "generate"; + assert STEP_IDS[8] == "preview"; +} + +test the_post_is_in_the_pr_and_the_owner_posts { + assert STEP_IDS[9] == "post"; + assert STEP_IDS[10] == "land"; + assert STEP_IDS[12] == "social"; + assert RULE_IDS[4] == "post-per-pr"; + assert RULE_IDS[9] == "owner-says-yes"; +} + +test the_experience_goes_back_into_tri { + assert STEP_COUNT == 14; + assert STEP_IDS[13] == "learn"; + assert RULE_IDS[2] == "casts-through-tri"; + assert CAST_STEPS[1] == "tri test "; +} + +test the_course_gates_are_all_named { + assert GATE_COUNT == 8; + assert GATES[3] == "npm run check:course"; + assert GATES[5] == "npm run check:course-pages"; + assert GATES[6] == "npm run check:onboarding"; +} + +test every_later_course_shares_under_its_own_path { + assert SHARE_FIRST == "learn/"; + assert SHARE_NEXT == "learn//"; +} diff --git a/specs/course_recipe/roadmap.t27 b/specs/course_recipe/roadmap.t27 new file mode 100644 index 0000000000..72d350e820 --- /dev/null +++ b/specs/course_recipe/roadmap.t27 @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: Apache-2.0 +; roadmap.t27 -- the t27 courses after the three that are live, in the order they are planned +; Read with course-27.t27 next to it (the recipe). Compile and test: +; compile and test with the same harness as specs/course_recipe/course-27.t27 +; ASCII only, English only. A course moves from here to gHashTag/trinity +; apps/website/specs/course/courses.t27 when it ships; then it is deleted here, so the +; catalog stays the one home of what is live and this file the one home of what is not. + +; WHAT IS LIVE (2026-10-07): course 0 "t27-basics" (the t27 language, #/t27-basics, learn/), +; course 1 "course" (FPGA programming with t27, #/course, learn/course/) and course 2 +; "ai-numbers" (AI numbers with t27, #/ai-numbers, learn/ai-numbers/). Course 0 came in +; trinity PR stacked on #1456; making it first moved course 1's index from learn/ to +; learn/course/ (lesson pages stay at learn//). + +; WHAT A PLAN IS: an id, a title, the source it teaches from, the spec directories already +; on the site (public/t27/files/specs/) and 9 topic parts. Lessons are chosen when the +; course is built (step "specs" of the recipe), because a lesson needs a spec that compiles +; clean in the player AND its own widget; the widgets are the real cost of a course +; (course 2 needed 9 new ones), so a plan never promises a lesson list. + +; WHY THIS ORDER: each course uses what the earlier ones taught. GoldenFloat follows AI +; numbers (formats, scales); the catalog follows GoldenFloat (it measures GF beside every +; other format); the ternary computer follows the FPGA course and the ternary module of AI +; numbers; networks come last, on top of formats, trits and the machine. + +; NUMBERS ARE NOT TYPED HERE: the catalog's format count grows (read it from gHashTag/t27 +; tools/gen_formats_catalog.py, "parsed N formats"), and TNF has no arXiv id (journal +; manuscript MICPRO-D-26-00839, under review). Say neither from memory on a course page. +; phi^2 + 1/phi^2 = 3 | TRINITY + +module course_roadmap; + +pub const KIND : str = "roadmap"; +pub const SCHEMA_VERSION : u8 = 1; +pub const STATUS : str = "planned"; +pub const LIVE_COUNT : u8 = 3; +pub const LIVE_IDS : [3]str = ["t27-basics", "course", "ai-numbers"]; + +pub const PLANNED_COUNT : u8 = 4; +pub const PLANNED_IDS : [4]str = ["goldenfloat", "golden-ruler", "ternary-computer", "networks"]; +pub const PLANNED_TITLES : [4]str = [ + "GoldenFloat with t27: a floating-point family cut by phi, from GF4 to GF1024", + "Golden Ruler with t27: a numeric format catalog and its bit-exact vectors", + "A ternary computer with t27: trits, gates, a register file and the TRI-27 machine", + "Neural networks with t27: layers, losses, optimizers and attention as specs" +]; +; The paper or manuscript each course teaches from; "" = the specs are the source. +pub const PLANNED_SOURCES : [4]str = [ + "arXiv:2606.05017", + "arXiv:2606.09686", + "", + "" +]; +; Spec directories on the site each course draws its lessons from (comma separated). +pub const PLANNED_SPEC_DIRS : [4]str = [ + "numeric/gf*,numeric/gft*,numeric/phi_ratio,numeric/lucas_accumulator,numeric/goldenfloat_family,numeric/gf_competitive,numeric/pellis_verify,math/phi_split_optimality,math/radix_economy", + "numeric/formats_catalog,numeric/formats,numeric/e8m0,numeric/bnf*,numeric/posit_ladder_control,numeric/requant_boundary,numeric/trinity_numeric_surface,numeric/bigint,conformance", + "isa,vsa", + "ml/activation,ml/layers,ml/loss,ml/optimizer,ml/recurrent,ml/transformer,ml/rl,nn" +]; + +; Owner's decision 2026-10-07: a course is 9 modules of 3 lessons each. What a plan fixes now +; is the 9 modules of every planned course, course after course (course k owns [9k .. 9k+8]); +; the 3 lessons of each module are chosen when the course is built. +pub const MODULES_PER_COURSE : u8 = 9; +pub const LESSONS_PER_MODULE : u8 = 3; +pub const PARTS_PER_COURSE : u8 = 9; +pub const PLANNED_PART_COUNT : u8 = 36; +pub const PLANNED_PARTS : [36]str = [ + "phi", "split", "gf-tiny", "gf-small", "gf-half", "gf-single", "gf-wide", "lucas", "rivals", + "catalog", "ieee", "fp8", "bfloat", "posit", "block-scales", "bnf", "requant", "vectors", + "trit", "logic", "trit-math", "registers", "memory", "control", "structures", "algorithms", "hypervectors", + "activations", "layers", "losses", "optimizers", "recurrence", "reinforcement", "attention", "rope", "transformer" +]; + +; What every plan still needs before it can ship, in the recipe's own step ids. +pub const BEFORE_SHIP : [4]str = ["specs", "widgets", "russian", "post"]; + +test four_courses_are_planned_and_none_is_live { + assert STATUS == "planned"; + assert PLANNED_COUNT == 4; + assert LIVE_COUNT == 3; + assert LIVE_IDS[0] == "t27-basics"; + assert PLANNED_IDS[0] != LIVE_IDS[0]; + assert PLANNED_IDS[0] != LIVE_IDS[1]; + assert PLANNED_IDS[0] != LIVE_IDS[2]; + assert PLANNED_IDS[1] != LIVE_IDS[0]; + assert PLANNED_IDS[1] != LIVE_IDS[1]; + assert PLANNED_IDS[1] != LIVE_IDS[2]; + assert PLANNED_IDS[2] != LIVE_IDS[0]; + assert PLANNED_IDS[2] != LIVE_IDS[1]; + assert PLANNED_IDS[2] != LIVE_IDS[2]; + assert PLANNED_IDS[3] != LIVE_IDS[0]; + assert PLANNED_IDS[3] != LIVE_IDS[1]; + assert PLANNED_IDS[3] != LIVE_IDS[2]; +} + +test every_plan_is_nine_modules_of_three_lessons { + assert MODULES_PER_COURSE == 9; + assert LESSONS_PER_MODULE == 3; + assert PARTS_PER_COURSE == MODULES_PER_COURSE; + assert PLANNED_PARTS[35] == "transformer"; + assert PLANNED_PART_COUNT == PLANNED_COUNT * PARTS_PER_COURSE; + assert PLANNED_PARTS[0] == "phi"; + assert PLANNED_PARTS[9] == "catalog"; + assert PLANNED_PARTS[18] == "trit"; + assert PLANNED_PARTS[27] == "activations"; + assert PLANNED_PARTS[35] == "transformer"; +} + +test goldenfloat_comes_next_and_teaches_from_its_paper { + assert PLANNED_IDS[0] == "goldenfloat"; + assert PLANNED_SOURCES[0] == "arXiv:2606.05017"; + assert PLANNED_IDS[1] == "golden-ruler"; + assert PLANNED_SOURCES[1] == "arXiv:2606.09686"; +} + +test widgets_are_the_cost_of_a_plan { + assert BEFORE_SHIP[1] == "widgets"; + assert BEFORE_SHIP[3] == "post"; +}