Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 60 additions & 21 deletions specs/t27f/reel_t27_basics.t27
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,23 @@
; 10-18 (tests and functions, inside a function, your own types), 19-27 (modules and rules, the
; compiler and tri, errors and what next). The test lenses_are_whole_modules holds that.

; STATUS is measured, not chosen. On 2026-10-17:
; - page: GET https://t27.ai/learn/<lesson-id>/ returned 200 with the title "<lesson>: t27 basics
; course, lesson N of 27" for all 27; a made-up id returned 404, so 200 is not a catch-all.
; STATUS is earned through the topic engine (specs/t27f/topic_engine.t27, earned_status), not
; chosen here. The engine routes the course brief (its TITLE and DESCRIPTION at SOURCE_COMMIT) by
; KEYWORD_MATCH: spec, compiler, fpga are 3 engineering hits and no other list is hit, so the domain
; is DOMAIN_ENGINEERING. What was measured, per lesson, on 2026-10-17:
; - grounded: every lesson has its text in the source spec, so every one has a source link.
; - spec: t27c test-report on the Railway lab passed every test of all 27 lesson specs
; (apps/website/public/t27/files/specs/basics/*.t27 at SOURCE_COMMIT). 23 of them report their
; passes as vacuous because every assert is on constants and is checked when compiled; planting
; a wrong one (lesson 11, HOURS == 25) turned that test red, so the checks are real.
; A cell is PUBLISHED only when both hold, VERIFIED when only the spec passes, DRAFT otherwise.
; - review: neither trinity PR that wrote the course (#1463, #1472) has a review, so no lesson does.
; - page: GET https://t27.ai/learn/<lesson-id>/ returned 200 with the title "<lesson>: t27 basics
; course, lesson N of 27" for all 27; a made-up id returned 404, so 200 is not a catch-all.
; The engine asks a LEARN step for a source link and an engineering PRACTICE step for a passing test,
; so lessons in those stages are VERIFIED, and their live pages make them PUBLISHED: 18 of 27. An
; engineering DELIVER step asks for a review, which no lesson has, and a live page does not stand in
; for one: lessons 7-9, 16-18 and 25-27 stay DRAFT although their pages are live. Until 2026-10-17
; this file used its own rule (live page and passing spec -> published) and drew all 27 as published.

; SCENES: the t27f_view host draws the reel.t27 demo camera (overview, lens 0, focus on cell 10,
; evidence, call), so this reel uses that camera; the test the_camera_is_the_demo_camera holds it.
Expand All @@ -29,7 +38,7 @@

; TWO COMPILERS: this file, reel.t27 and deck.t27 run under t27c (the Zig backend) and under t27b
; (t27's own AArch64 backend, `t27b test --check`, qemu-aarch64 on the lab). On 2026-10-17 the two
; agreed on every test (6 + 20 + 15 pass), and each planted fault above failed the same test in both.
; agreed on every test, and each planted fault failed the same test in both (see the PRs).
; t27b also refused the first draft of this file: it compared a str's u64 `.len` with an i32, which
; t27c accepted; every length is now cast to i32 before it is compared.

Expand Down Expand Up @@ -61,6 +70,13 @@ use t27f::deck::text_fits;
use t27f::deck::chars_per_line;
use t27f::deck::card_inner_w;
use t27f::deck::region_w;
use t27f::topic_engine::STATUS_DRAFT;
use t27f::topic_engine::STATUS_PUBLISHED;
use t27f::topic_engine::STAGE_DELIVER;
use t27f::topic_engine::DOMAIN_ENGINEERING;
use t27f::topic_engine::route;
use t27f::topic_engine::step_stage;
use t27f::topic_engine::earned_status;

pub const TOPIC_ID : str = "t27-basics";
pub const SOURCE_REPO : str = "gHashTag/trinity";
Expand All @@ -72,17 +88,18 @@ pub const MEASURED_ON : str = "2026-10-17";
pub const LESSONS_PER_MODULE : i32 = 3;
pub const MODULES_PER_LENS : i32 = 3;

/// Lesson statuses, the T27fTopicEngine codes reel.t27 reads.
pub const STATUS_DRAFT : u8 = 3;
pub const STATUS_VERIFIED : u8 = 4;
pub const STATUS_PUBLISHED : u8 = 5;
/// The domain the engine routes the course brief to, and the hits it counted (see the header).
pub const DOMAIN : u8 = 2;
pub const ENGINEERING_HITS : u32 = 3;

/// The two measurements per lesson, in lesson order (see the header for how each was taken).
/// The measurements per lesson, in lesson order (see the header for how each was taken).
pub const GROUNDED : [27]bool = [true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true];
pub const PAGE_LIVE : [27]bool = [true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true];
pub const SPEC_PASSES : [27]bool = [true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true];
pub const REVIEWED : [27]bool = [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false];

/// What a host passes the viewer, per cell: the status code and the lesson number as a label.
pub const STATUS : [27]u8 = [5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5];
pub const STATUS : [27]u8 = [5, 5, 5, 5, 5, 5, 3, 3, 3, 5, 5, 5, 5, 5, 5, 3, 3, 3, 5, 5, 5, 5, 5, 5, 3, 3, 3];
pub const LABELS : [27]str = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27"];

pub const LENS_TITLES : [3]str = ["values", "logic", "tools"];
Expand All @@ -107,7 +124,7 @@ pub const ROWS : [20]str = [
"Try: break one, the other two still pass",
"27 of 27 lesson pages live on t27.ai",
"27 of 27 lesson specs pass on the lab",
"A planted wrong assert turns it red",
"18 published; 9 wait for a review",
"Measured 2026-10-17",
"t27.ai/learn/what-a-spec-is/",
"Progress stays in this browser",
Expand All @@ -123,17 +140,22 @@ pub fn module_of(cell: i32) -> i32 {
return @divTrunc(cell, LESSONS_PER_MODULE);
}

/// The status a cell has earned from its two measurements.
/// The status the engine says a cell has earned from its measurements.
pub fn measured_status(cell: i32) -> u8 {
const live : bool = PAGE_LIVE[@intCast(cell)];
const pass : bool = SPEC_PASSES[@intCast(cell)];
if (live and pass) {
return STATUS_PUBLISHED;
}
if (pass) {
return STATUS_VERIFIED;
const i : usize = @intCast(cell);
return earned_status(@intCast(cell), DOMAIN, GROUNDED[i], SPEC_PASSES[i], REVIEWED[i], PAGE_LIVE[i]);
}

pub fn count_status(status: u8) -> i32 {
var n : i32 = 0;
var c : i32 = 0;
while (c < CELL_COUNT) {
if (STATUS[@intCast(c)] == status) {
n = n + 1;
}
c = c + 1;
}
return STATUS_DRAFT;
return n;
}

pub fn count_true(xs: [27]bool) -> i32 {
Expand Down Expand Up @@ -208,12 +230,29 @@ test a_status_is_earned_not_chosen {
assert STATUS[@intCast(c)] == measured_status(c);
c = c + 1;
}
assert count_true(GROUNDED) == 27;
assert count_true(PAGE_LIVE) == 27;
assert count_true(SPEC_PASSES) == 27;
assert count_true(REVIEWED) == 0;
// the evidence slide's "18 published; 9 wait for a review"
assert count_status(STATUS_PUBLISHED) == 18;
assert count_status(STATUS_DRAFT) == 9;
// the drafts are exactly the DELIVER lessons, whose pages are live all the same
var d : i32 = 0;
while (d < CELL_COUNT) {
const deliver : bool = step_stage(@intCast(d)) == STAGE_DELIVER;
assert (STATUS[@intCast(d)] == STATUS_DRAFT) == deliver;
d = d + 1;
}
// a published cell wears the published style, never a gap or a draft
assert cell_style(STATUS[0]) == STYLE_PUBLISHED;
}

test the_domain_is_routed_not_chosen {
assert DOMAIN == DOMAIN_ENGINEERING;
assert route(0, ENGINEERING_HITS, 0, 0) == DOMAIN;
}

test the_camera_is_the_demo_camera {
assert DEMO_COUNT == 5;
// scene 1 shows lens 0, the row HEAD[1] calls "Lessons 1-9"
Expand Down
45 changes: 45 additions & 0 deletions specs/t27f/topic_engine.t27
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,29 @@ pub fn after_action(status: u8, action: u8, approved: bool) -> u8 {
return status;
}

/// The status a step has earned from what was measured about it, walked through the gates above
/// and nothing else: a step with no source is a GAP; a grounded one starts as a DRAFT; each piece of
/// evidence goes through verify(); a step that is live counts as published only if it was VERIFIED
/// first, so a live page with too little evidence stays a DRAFT. `live` means the item already
/// reached its audience, so whoever put it there approved that.
pub fn earned_status(step: u8, domain: u8, grounded: bool, test_pass: bool, reviewed: bool, live: bool) -> u8 {
if (grounded == false) {
return STATUS_GAP;
}
const stage : u8 = step_stage(step);
var status : u8 = verify(STATUS_DRAFT, stage, domain, EVIDENCE_SOURCE_LINK);
if (test_pass) {
status = verify(status, stage, domain, EVIDENCE_TEST_PASS);
}
if (reviewed) {
status = verify(status, stage, domain, EVIDENCE_REVIEW);
}
if (live) {
status = after_action(status, ACTION_PUBLISH, true);
}
return status;
}

test shape_is_three_lenses_of_nine {
assert LENS_COUNT * STEPS_PER_LENS == LESSON_COUNT;
assert STAGE_COUNT * STEPS_PER_STAGE == STEPS_PER_LENS;
Expand Down Expand Up @@ -452,6 +475,28 @@ test engineering_practice_needs_a_test {
assert evidence_accepted(STAGE_PRACTICE, DOMAIN_ENGINEERING, EVIDENCE_TEST_PASS);
}

test a_live_page_does_not_verify_a_step {
const e : u8 = DOMAIN_ENGINEERING;
// steps 0, 3 and 6 are the first LEARN, PRACTICE and DELIVER steps of lens 0
assert step_stage(0) == STAGE_LEARN;
assert step_stage(3) == STAGE_PRACTICE;
assert step_stage(6) == STAGE_DELIVER;
// no source: a gap, whatever else was measured
assert earned_status(0, e, false, true, true, true) == STATUS_GAP;
// LEARN: the source link is its evidence
assert earned_status(0, e, true, false, false, false) == STATUS_VERIFIED;
assert earned_status(0, e, true, false, false, true) == STATUS_PUBLISHED;
// PRACTICE in engineering: only a passing test verifies it
assert earned_status(3, e, true, false, true, true) == STATUS_DRAFT;
assert earned_status(3, e, true, true, false, true) == STATUS_PUBLISHED;
// DELIVER in engineering: a passing test and a live page are not a review
assert earned_status(6, e, true, true, false, true) == STATUS_DRAFT;
assert earned_status(6, e, true, true, true, false) == STATUS_VERIFIED;
assert earned_status(6, e, true, false, true, true) == STATUS_PUBLISHED;
// the stage repeats in every lens: step 26 is the last DELIVER step
assert earned_status(26, e, true, true, false, true) == STATUS_DRAFT;
}

test progress_only_after_verification {
assert opens_next(STATUS_OPEN) == false;
assert opens_next(STATUS_DRAFT);
Expand Down
Loading