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'
"))
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("