import copy import html import importlib.util import json import re import tempfile import unittest from html.parser import HTMLParser from pathlib import Path ROOT = Path(__file__).resolve().parents[1] SPEC = importlib.util.spec_from_file_location("build_site", ROOT / "scripts/build_site.py") build = importlib.util.module_from_spec(SPEC) SPEC.loader.exec_module(build) def slide(folder: Path, name: str, body: str) -> None: (folder / "slides").mkdir(parents=True, exist_ok=True) (folder / "slides" / f"{name}.html").write_text(f'
{body}
') def strings(value) -> list[str]: """Every string in a noun, however deeply it sits.""" if isinstance(value, str): return [value] items = value.values() if isinstance(value, dict) else value if isinstance(value, list) else [] return [found for item in items for found in strings(item)] def without_number(inner: str) -> str: """A slide's markup without the footer's slide number, which no claim needs to back.""" return re.sub(r']*>\d+', "", inner) def numbers(value) -> list[int]: """Every whole number in a noun, however deeply it sits.""" if type(value) is int: return [value] items = value.values() if isinstance(value, dict) else value if isinstance(value, list) else [] return [found for item in items for found in numbers(item)] class ShownText(HTMLParser): def __init__(self) -> None: super().__init__() self.shown: list[str] = [] def handle_data(self, data: str) -> None: if data.strip(): self.shown.append(data.strip()) def shown_text(fragment: str) -> list[str]: """The text a page shows, piece by piece, without its markup.""" parser = ShownText() parser.feed(fragment) parser.close() return parser.shown def css_tokens(css: str, selector: str) -> dict[str, str]: """The custom properties a stylesheet declares in the first block that starts with this selector.""" block = css[css.index(selector + " {"):] block = block[:block.index("}")] return dict(re.findall(r"(--[a-z0-9-]+):\s*(#[0-9A-Fa-f]{6})", block)) def contrast(a: str, b: str) -> float: def luminance(colour: str) -> float: channels = [int(colour[i:i + 2], 16) / 255 for i in (1, 3, 5)] r, g, b_ = [c / 12.92 if c <= 0.03928 else ((c + 0.055) / 1.055) ** 2.4 for c in channels] return 0.2126 * r + 0.7152 * g + 0.0722 * b_ light, dark = sorted((luminance(a), luminance(b)), reverse=True) return (light + 0.05) / (dark + 0.05) def plain_words(value: str) -> list[str]: """Words, lowercased, without punctuation: how a transcript and its captions are compared.""" value = value.lower().replace("…", " ").replace("’", "").replace("'", "").replace("\u2014", " ").replace("-", " ") return re.sub(r"[^a-z0-9% ]", "", value).split() def caption_words(vtt: str) -> list[str]: """The words a WebVTT file's cues show.""" cues = [block.split("\n") for block in vtt.strip().split("\n\n")] return plain_words(" ".join(line for cue in cues for n, line in enumerate(cue) if any("-->" in c for c in cue[:n]))) class Builder(unittest.TestCase): @classmethod def setUpClass(cls): cls.nouns = build.Nouns() cls.outputs = build.outputs_for(cls.nouns) def test_the_general_slide_loader_reads_the_frozen_v4_source_as_v4_was_built(self): source = ROOT / "site/decks/2026-10-29/v4/source" frozen = (ROOT / "site/decks/2026-10-29/v4/index.html").read_text() order = json.loads((source / "deck.json").read_text())["order"] for name in order: loaded = build.load_slide(source, name) self.assertIn(f'
\n{loaded["inner"]}\n
', frozen, name) self.assertIn(f'

{loaded["notes"]}

', frozen, name) def test_frozen_pages_are_never_written(self): self.assertEqual(6, len(self.nouns.frozen)) self.assertFalse(set(self.outputs) & self.nouns.frozen) def test_the_starting_brief_has_one_source(self): brief = build.text(build.read_brief()) roll = self.outputs[build.DECKS / "roll-your-own" / "index.html"] self.assertEqual(1, roll.count(f'
{brief}
")) self.assertEqual(build.read_brief() + "\n", (build.SITE / "agent-brief.txt").read_text(encoding="utf-8")) def test_every_page_opens_with_one_agent_banner_from_its_noun(self): # October 31 (AgentBanner, BannerSpec): one thin line above the header on every page, its words embedded # from the agent-banner noun for the shared element, with a plain line and an llms.txt # link for readers without scripts. The copied line is exactly the noun's. embedded = f'' self.assertEqual("Read https://agora.ta-amps.workers.dev/llms.txt and follow it.", self.nouns.banner["copy_text"]) for path, content in self.outputs.items(): if path.suffix != ".html": continue self.assertEqual(1, content.count("'), path) body = content[content.index("" in body: # Above the header, and the skip link stays the first thing a keyboard reaches. self.assertLess(body.index("'):home.index("")] self.assertEqual(4, main.count("", main) self.assertLess(home.index("{build.text(start['heading'])}", main) self.assertEqual(["Eranos", "Agora"], [card["name"] for card in start["cards"]]) self.assertIn('href="https://eranos.ta-amps.workers.dev/"', main) self.assertIn('href="how-it-works/"', main) self.assertEqual(5, main.count('class="deck-card"')) self.assertEqual(6, main.count('class="home-use"')) self.assertEqual(1, main.count('class="home-use-live"')) # only Eranos is live, so only it says so # The film's production page is linked only once its production trace is final. self.assertEqual(build.film_made_ready(start), start["film_made"]["href"] in main) def test_nouns_and_verbs_are_glossed_in_plain_words_the_first_time(self): # Feedback, October 30: a viewer took nouns and verbs for a model architecture. The home page, the use cases # page and the overview and roll-your-own decks say in plain words what they are the first time they name # them: verbs are tasks, and nouns are everything a task uses or makes. The overview says plainly that this # is how the work is organized, not a model architecture. The marketplace deck, written for nonprofits, # glosses its first verb once, as a task. named = re.compile(r"\b(?:nouns?|verbs?)\b", re.I) def glossed(shown: str, where: str) -> None: found = named.search(shown) self.assertIsNotNone(found, where) self.assertIn("verbs are tasks", shown[found.start():found.start() + 160].lower(), where) for path in (build.SITE / "index.html", build.SITE / "use-cases" / "index.html"): glossed(build.plain_text(build.main_of(self.outputs[path])), path.relative_to(build.ROOT).as_posix()) decks = {deck["id"]: deck for deck in self.nouns.decks} for deck_id in ("overview-and-architecture", "roll-your-own"): glossed(" ".join(build.plain_text(slide["inner"]) for slide in decks[deck_id]["slides"]), deck_id) overview = {slide["name"]: build.plain_text(slide["inner"]) for slide in decks["overview-and-architecture"]["slides"]} self.assertIn("NOT A MODEL ARCHITECTURE", overview["nouns-and-verbs"]) self.assertIn("how the work is organized", overview["nouns-and-verbs"]) market = " ".join(build.plain_text(slide["inner"]) for slide in decks["public-good-marketplace"]["slides"]) self.assertEqual(1, market.count("(a task)")) first = re.search(r"\bverbs?\b", market) self.assertEqual(" (a task)", market[first.end():first.end() + len(" (a task)")]) def test_the_worked_examples_are_illustrations_and_their_numbers_have_claims(self): # Feedback, October 30: two worked examples show nouns and verbs at work, one right after the slide that # defines them and one right after feeds. They show how the work is organized, not measured runs, so each # says so on the slide and in its notes, and every number on them has a claim. A measured precedent links to # public evidence; the memory-systems feeds are planned, and the slide says so. deck = next(deck for deck in self.nouns.decks if deck["id"] == "overview-and-architecture") order = [slide["name"] for slide in deck["slides"]] self.assertEqual(order.index("nouns-and-verbs") + 1, order.index("worked-example")) self.assertEqual(order.index("feeds") + 1, order.index("memory-systems")) slides = {slide["name"]: slide for slide in deck["slides"]} claims = deck["claims"]["claims"] # October 31: the memory-systems slide became a real scan (the feed's own data), so it is measured, and only the # worked example is still an illustration. for name in ("worked-example", "memory-systems"): shown, notes = build.plain_text(without_number(slides[name]["inner"])), build.plain_text(slides[name]["notes"]) mine = [claim for claim in claims if claim["slide"] == name] if name == "worked-example": self.assertIn("ILLUSTRATION · NOT A MEASURED RUN", shown, name) self.assertIn("illustration", notes.lower(), name) self.assertTrue(any(claim["status"] == "illustration" for claim in mine), name) else: self.assertNotIn("ILLUSTRATION", shown) self.assertNotIn("PLANNED", shown) self.assertTrue(all(claim["status"] == "measured" for claim in mine), name) listed = " ".join(claim["number"] for claim in mine) for part in (shown, notes): for number in re.findall(r"\d+(?:[.,]\d+)?", part): self.assertIn(number, listed, (name, number)) for claim in mine: if claim["status"] == "measured": # Public evidence: the source mirror's provenance address, or the page on Agora that shows it. self.assertTrue(claim["link"].startswith(("https://github.com/ta-amps/", "https://agora.ta-amps.workers.dev/")), claim["number"]) self.assertIn("0 tokens", build.plain_text(slides["worked-example"]["inner"])) self.assertIn("agora.ta-amps.workers.dev/feeds/memory-systems", build.plain_text(slides["memory-systems"]["inner"])) # Every claim status, illustration included, has its own label style in the notes. css = (build.SITE / "assets" / "viewer.css").read_text(encoding="utf-8") for status in build.CLAIM_STATUSES: self.assertIn(f".claim-status.{status} {{", css, status) def test_nonprofits_never_choose_a_kind_of_request(self): # A nonprofit types what it needs; the request's first step sorts it into a kit, public work or both. asking = re.compile(r"request(s|ing)? (a|an) (verb|agent kit|kit)\b|verb requests?\b|an agent kit or a verb", re.I) pages = {path: page for path, page in self.outputs.items() if isinstance(page, str)} self.assertIn(build.SITE / "decks" / "public-good-marketplace" / "index.html", pages) for path, page in pages.items(): self.assertIsNone(asking.search(page), path) def test_deck_pages_are_only_slides_with_sources_in_the_notes(self): for deck in self.nouns.decks: page = self.outputs[deck["page"]] main = page[page.index('
")] for leftover in ('id="claim-review"', "deck-intro", "deck-more", "print-colophon", "print-claims"): self.assertNotIn(leftover, main, deck["id"]) for claim in (deck["claims"] or {"claims": []})["claims"]: start = main.index(f'data-name="{claim["slide"]}"') notes = main[main.index('class="slide-notes"', start):main.index("", start)] self.assertIn(html.escape(claim["number"], quote=False), notes, claim["number"]) def test_the_film_offers_a_selector_only_when_it_has_more_than_one_cut(self): nouns = copy.copy(self.nouns) nouns.home = copy.deepcopy(self.nouns.home) videos = nouns.home["videos"] one = dict(videos["cuts"][0], id="one") videos["cuts"], videos["default"] = [one], "one" self.assertNotIn("data-film-cuts", build.render_home(nouns)) other = dict(one, id="other", tab="Other cut", label="The other cut") other["src"] = "video/2026-10-29/animatic-60s-v1/eranos-animatic-60s-open-captions.mp4" videos["cuts"].insert(0, other) videos["default"] = "other" page = build.render_home(nouns) self.assertEqual(1, page.count("The other cut', page) # Hunt, October 30: without JavaScript the buttons stay hidden, so every other cut is a plain link, # which site.js hides once the buttons work. Before, the short cut was unreachable without JavaScript. self.assertIn(f' · {one["tab"]}', page) self.assertNotIn(f' · ', page) videos["default"] = "missing" with self.assertRaises(build.BuildError): build.render_home(nouns) def test_slide_elements_become_html(self): endpoints = self.nouns.site["endpoints"] with tempfile.TemporaryDirectory() as directory: folder = Path(directory) slide(folder, "a", '

Title

' '' '') loaded = build.load_slide(folder, "a", brief="Use & go", endpoints=endpoints) self.assertIn('
Use <b> & go
', loaded["inner"]) self.assertEqual("slide-brief", loaded["copy"]) self.assertIn(endpoints["rows"][0]["mcp"], loaded["inner"]) self.assertIn((endpoints["rows"][0]["llms"], endpoints["rows"][0]["llms"]), loaded["links"]) self.assertEqual("Title", loaded["title"]) self.assertEqual("Notes", loaded["notes"]) for body in ('

T

', '

T

', '

T

'): slide(folder, "b", body) with self.assertRaises(build.BuildError): build.load_slide(folder, "b", brief="text", endpoints=endpoints) def test_moved_pages_point_to_places_that_exist(self): for item in self.nouns.moved["pages"]: path, _, anchor = item["to"].partition("#") target = build.SITE / path / "index.html" page = self.outputs.get(target) or target.read_text(encoding="utf-8") if anchor: self.assertIn(f'id="{anchor}"', page, item["to"]) # The not-found page lists every moved page, and says the old addresses redirect (the worker reads the # same noun), so it never sends anyone to a page that is not there. not_found = self.outputs[build.SITE / "404.html"] for item in self.nouns.moved["pages"]: self.assertIn(f'href="/{html.escape(item["to"])}"', not_found) self.assertIn("301", not_found) def test_learning_is_a_tab_of_agora_built_from_its_noun(self): # A page of Agora, not a new surface. October 31 (SiteHeader board): the header reads The film, How it works, # Use cases, Decks, Evidence, and Learning sits in the footer of every page. self.assertEqual(["The film", "How it works", "Use cases", "Decks", "Evidence"], [item["label"] for item in self.nouns.site["nav"]]) page = self.outputs[build.SITE / "learning" / "index.html"] self.assertIn('
  • Learning
  • ', page) main = build.main_of(page) # Every word the learning page shows, outside the shared header and footer, is a string of its noun. written = set(strings(self.nouns.learning)) for shown in shown_text(main): self.assertIn(shown, written) # The loop is an ordered list of its steps, in the noun's order. steps = [step["verb"] for step in self.nouns.learning["loop"]["steps"]] self.assertEqual(len(steps), main.count('
  • ')) places = [main.index(f'

    {build.text(step)}

    ') for step in steps] self.assertEqual(sorted(places), places) # Every measured result links to public evidence, and the build refuses one that doesn't. for item in self.nouns.learning["results"]["items"]: self.assertTrue(item["link"].startswith("https://github.com/ta-amps/"), item["model"]) self.assertIn(f'href="{html.escape(build.repoint(item["link"], self.nouns.links))}"', main) nouns = copy.copy(self.nouns) nouns.learning = copy.deepcopy(self.nouns.learning) nouns.learning["results"]["items"][0]["link"] = "notes.md" with self.assertRaises(build.BuildError): build.render_learning(nouns) def test_the_learning_page_and_deck_give_the_same_numbers(self): deck = next(deck for deck in self.nouns.decks if deck["id"] == "continuous-learning") claims = deck["claims"]["claims"] for item in self.nouns.learning["results"]["items"]: about = [claim for claim in claims if item["model"] in claim["number"]] exact = [claim for claim in about if item["before"] in claim["number"] and item["after"] in claim["number"]] self.assertTrue(exact, item["model"]) for claim in exact: self.assertEqual(("measured", item["link"]), (claim["status"], claim["link"]), item["model"]) listed = " ".join(claim["number"] for claim in about) for number in re.findall(r"\d+(?:\.\d+)?", item["line"]): self.assertIn(number, listed, (item["model"], number)) def test_the_library_is_a_page_of_agora_built_from_its_noun(self): library, explorer, ecosystem = self.nouns.library, self.nouns.explorer, self.nouns.ecosystem page = self.outputs[build.SITE / "library" / "index.html"] self.assertIn('
  • Library
  • ', page) main = build.main_of(page) # Every word the page shows is a string of its nouns. The rest is the measured part: numbers, the commit and # its date. sizes = {len(category["packs"]) for category in library["categories"]} measured = {f"{n:,}" for n in set(numbers(library)) | sizes | set(numbers(explorer)) | set(numbers(ecosystem))} measured |= {library["source"]["commit"][:7], build.human_date(library["source"]["committed_at"]), "·"} written = set(strings(library)) | set(strings(explorer)) | set(strings(ecosystem)) for shown in shown_text(main): self.assertIn(shown, written | measured) # One card per pack, inside its category's section and in its order, linking to its folder at the commit. packs = {pack["id"]: pack for pack in library["packs"]} self.assertEqual(len(packs), main.count('
  • ")] self.assertEqual(len(category["packs"]), section.count('
  • ') for pack_id in category["packs"]] self.assertEqual(sorted(places), places, category["id"]) for pack_id in category["packs"]: self.assertIn(f'href="{html.escape(build.repoint(packs[pack_id]["url"], self.nouns.links))}"', section) self.assertIn(f"/tree/{library['source']['commit']}/packs/{pack_id}", packs[pack_id]["url"]) # The totals shown are the noun's, and every code + tests badge but the legend's is a pack's that ships code. for key, value in library["totals"].items(): self.assertIn(f'{value:,}', main, key) self.assertEqual(library["totals"]["with_code"] + 1, main.count('')) # Every pack is a proposal, and the page says so at the top and on every card. self.assertEqual({"proposal_only"}, {pack["status"] for pack in packs.values()}) self.assertIn(build.text(library["dateline"]), main) self.assertEqual(len(packs), main.count(f'' f'{library["words"]["status"]["proposal_only"]}')) # The filter: "All", then a link per category, and the page's one style rule marks each when it is on show. nav = main[main.index('