4d9225e6a11d92fe8465abe39fde0022e998aee4
diff --git a/public/sama-hero.png b/public/sama-hero.png
new file mode 100644
index 0000000000000000000000000000000000000000..b0425500976fde5874f6613c9d01dddd49a6a108
Binary files /dev/null and b/public/sama-hero.png differ
diff --git a/public/sama-hero.svg b/public/sama-hero.svg
new file mode 100644
index 0000000000000000000000000000000000000000..903432f6234149e6078b1afa88e67363ffb08d46
--- /dev/null
+++ b/public/sama-hero.svg
@@ -0,0 +1,24 @@
+
diff --git a/public/sama-layers.png b/public/sama-layers.png
new file mode 100644
index 0000000000000000000000000000000000000000..f5e5d26b794bd5fc96c3469efce93f0e6b040919
Binary files /dev/null and b/public/sama-layers.png differ
diff --git a/public/sama-layers.svg b/public/sama-layers.svg
new file mode 100644
index 0000000000000000000000000000000000000000..0fefb6e93929166b83d9ff86967217bd20d2a155
--- /dev/null
+++ b/public/sama-layers.svg
@@ -0,0 +1,58 @@
+
diff --git a/public/sama-metrics.png b/public/sama-metrics.png
new file mode 100644
index 0000000000000000000000000000000000000000..cd25f4d83e99a332efc81558b1d188ed4c69153d
Binary files /dev/null and b/public/sama-metrics.png differ
diff --git a/public/sama-metrics.svg b/public/sama-metrics.svg
new file mode 100644
index 0000000000000000000000000000000000000000..fedd122bcac5afcfd1953721fa017198193a551d
--- /dev/null
+++ b/public/sama-metrics.svg
@@ -0,0 +1,86 @@
+
diff --git a/src/d21_app.ts b/src/d21_app.ts
index bca4ee3efac684049f09486ab98469218852fb7b..b8d83927cefe453543418cbf7d22629de64a9d62 100644
--- a/src/d21_app.ts
+++ b/src/d21_app.ts
@@ -231,6 +231,25 @@ ${url("https://tdd.md/leaderboard", "0.7")}
},
}),
+ "/sama-hero.svg": new Response(Bun.file("./public/sama-hero.svg"), {
+ headers: { "Content-Type": "image/svg+xml", "Cache-Control": "public, max-age=3600" },
+ }),
+ "/sama-hero.png": new Response(Bun.file("./public/sama-hero.png"), {
+ headers: { "Content-Type": "image/png", "Cache-Control": "public, max-age=3600" },
+ }),
+ "/sama-layers.svg": new Response(Bun.file("./public/sama-layers.svg"), {
+ headers: { "Content-Type": "image/svg+xml", "Cache-Control": "public, max-age=3600" },
+ }),
+ "/sama-layers.png": new Response(Bun.file("./public/sama-layers.png"), {
+ headers: { "Content-Type": "image/png", "Cache-Control": "public, max-age=3600" },
+ }),
+ "/sama-metrics.svg": new Response(Bun.file("./public/sama-metrics.svg"), {
+ headers: { "Content-Type": "image/svg+xml", "Cache-Control": "public, max-age=3600" },
+ }),
+ "/sama-metrics.png": new Response(Bun.file("./public/sama-metrics.png"), {
+ headers: { "Content-Type": "image/png", "Cache-Control": "public, max-age=3600" },
+ }),
+
"/games": htmlResponse(GAMES_INDEX_HTML),
"/blog": async () => {
diff --git a/src/d21_handlers_sama.ts b/src/d21_handlers_sama.ts
index 265019fb17e21db05a9b2fd949edf9d118f4ea23..af4430d813e99a9c9109a585a9dbf3363c81dc5e 100644
--- a/src/d21_handlers_sama.ts
+++ b/src/d21_handlers_sama.ts
@@ -380,48 +380,67 @@ export const samaVerifyHandler = async (req: { url: string }): Promise
const SAMA_LANDING_MD = `# SAMA
-> **Sorted, Architecture, Modeled, Atomic.** Four properties of a codebase that an AI agent can navigate, change, and verify without drift. The acronym is the rule set; each letter has a one-paragraph definition and a verification you can run.
+> **Architecture as code, for code AI writes.** A formal v2 specification, a deterministic verifier that runs against this very repo on every deploy, and an n=8 cross-repo measurement baseline. The v1 practitioner pages are preserved below.
-This is the file-naming and module-organisation convention this site is built on, shared across two other projects in my workspace. It exists to give an AI agent **one obvious place** for every change — and one mechanical check for every layer rule.
+
-## the four disciplines
+## the v2 specification (current)
-| letter | discipline | one-line rule |
-|---|---|---|
-%ROWS%
+The formal, normative spec — frozen core + profile mechanism, written so a deterministic verifier in any language can ingest it — lives at **[/sama/v2](/sama/v2)** (v2.0 draft). Four canonical layers, one import law, a binary §4 conformance gate, and §5 core metrics for cross-repo empirical measurement. The TypeScript verifier that implements §4 is itself checked by the verifier; the website is the spec is the verifier is the test suite.
-## reading order
+The verifier at **[/sama/v2/verify](/sama/v2/verify)** runs the seven §4 conformance checks against this very repository's source on every deploy. Right now it reports **✓ conforms · 7/7 checks pass**.
-If you're new to this:
-1. Start with **[Sorted](/sama/sorted)** — it has the verification grep that everything else is built around.
-2. Then **[Architecture](/sama/architecture)** — what each layer prefix means.
-3. Then **[Modeled](/sama/modeled)** — where types and tests live.
-4. Then **[Atomic](/sama/atomic)** — the split rule that keeps the rest honest as the codebase grows.
+
-Each page is short, opinionated, and ends with the common mistakes you'll see if the discipline lapses.
+## the empirical chain
+
+Compliance is binary. The interesting question is the *delta* — what changes when the rules are followed, measured across multiple repos. §5 of the spec defines five language-neutral core metrics so the delta can be measured rather than asserted. The polyglot \`workingSetFit\` emitter has now been run against eight projects at pinned commit SHAs:
-## the v2 specification (draft)
+
-The four discipline pages above are the practitioner-facing version. The formal, normative version — frozen core + profile mechanism, written so a deterministic verifier in any language can ingest it — lives at **[/sama/v2](/sama/v2)** (draft for v2.0). That doc defines the four canonical layers (Pure / Core / Adapter / Entry), the single import law, the binary conformance gate, and the SAMA-independent core metrics for cross-repo empirical measurement.
+- **[Seven measured workingSetFit datapoints — what the baseline distribution actually looks like](/blog/sama-v2-workingset-cross-repo-baseline)** — n=2 → n=7 across mature compiled-language CLI tools. Range 27pp, mean 60.68%, sample stddev 10.13pp.
+- **[Pointing SAMA v2 at \`dive\`](/blog/sama-v2-go-project-dive)** · **[Pointing SAMA v2 at \`ripgrep\`](/blog/sama-v2-rust-project-ripgrep)** — two non-SAMA mature CLI codebases audited and scored on two §5 axes (workingSetFit + graphDepth) at pinned SHAs.
+- **[The §5 metrics emitter post](/blog/sama-v2-metrics-emitter)** — why measurement matters more than compliance, with the original metric build-out.
+- **[The three v2.1 dialects at /sama/v2 §6.A](/sama/v2#6a-v21-dialects-provisional)** — provisional extensions (directory-layout, inline-tests, declarative-exemption) that the Rust + Go audits surfaced.
+
+**tdd.md** (the only SAMA-disciplined repo measured to date) lands at **80.00%** — 6.4pp above the top of the non-SAMA baseline. Suggestive, but n=1 vs n=7 is far from a SAMA-worth-following claim. §6 of the spec is explicit that promotion requires cross-repo deltas across multiple SAMA-disciplined repos.
## drop into your agent
-For agents that load skills from \`~/.claude/skills/\` (Claude Code, obra/superpowers, etc.), grab the SKILL.md version:
+For agents that load skills from \`~/.claude/skills/\` (Claude Code, obra/superpowers, etc.):
\`\`\`bash
mkdir -p ~/.claude/skills
curl -fsSL https://tdd.md/skills/sama.md -o ~/.claude/skills/sama.md
\`\`\`
-The skill is the same content as the four pages here, written in obra/superpowers SKILL.md format with frontmatter, an iron-rule statement, and a verification checklist your agent can run before merging. **[Read it formatted →](/sama/skill)** · **[Raw markdown →](/skills/sama.md)**
+The skill captures the load-bearing parts of the v2 spec in obra/superpowers SKILL.md format with frontmatter, an iron-rule statement, and a verification checklist your agent runs before merging. **[Read it formatted →](/sama/skill)** · **[Raw markdown →](/skills/sama.md)**
+
+---
-## verify any public repo
+## v1 practitioner pages (preserved)
-Want to know whether a repo follows SAMA without reading its source? Paste the \`owner/name\` and tdd.md will run all four checks against the default branch — *Sorted* (the import-direction grep), *Architecture* (known layer prefixes), *Modeled* (sibling tests), *Atomic* (700-line + placeholder-test detection). Pass/fail per discipline, with violation lists. **[verify a repo on the web →](/sama/verify)** · or try it on this site: [\`syntaxai/tdd.md\`](/sama/verify?repo=syntaxai/tdd.md).
+The four discipline pages below are the v1 practitioner-facing version of SAMA. They predate the v2 specification and remain accessible as background reading; the formal, normative version of every rule lives in [/sama/v2](/sama/v2). The v1 pages frame the same four properties in less spec-flavoured prose, with one-page-per-discipline depth and a working CI grep at the bottom of *Sorted*.
-## the \`sama\` CLI
+### the four disciplines
-The web verifier is good for ad-hoc checks. For CI and pre-commit, install the standalone CLI — same checks, no network needed for local repos:
+| letter | discipline | one-line rule |
+|---|---|---|
+%ROWS%
+
+### reading order
+
+If you're new to this:
+1. Start with **[Sorted](/sama/sorted)** — it has the verification grep that everything else is built around.
+2. Then **[Architecture](/sama/architecture)** — what each layer prefix means.
+3. Then **[Modeled](/sama/modeled)** — where types and tests live.
+4. Then **[Atomic](/sama/atomic)** — the split rule that keeps the rest honest as the codebase grows.
+
+Each page is short, opinionated, and ends with the common mistakes you'll see if the discipline lapses.
+
+### the v1 \`sama\` CLI
+
+For local CI and pre-commit hooks. The v1 CLI verifies the original four disciplines; the v2 verifier with the seven §4 conformance checks runs on the web at [/sama/v2/verify](/sama/v2/verify).
\`\`\`bash
mkdir -p ~/.local/bin
@@ -440,17 +459,15 @@ sama verify-repo owner/name # verify a public GitHub repo (no token)
Exit codes: \`0\` on pass, \`1\` if any check fails, \`2\` on error. The CLI is a single Bun bundle (~14 KB). [Bun](https://bun.sh) needs to be on \`PATH\`.
-### pre-commit hook
-
-Add to \`.git/hooks/pre-commit\` (or via \`husky\`, \`pre-commit\`, \`lefthook\`):
+#### pre-commit hook
\`\`\`bash
#!/usr/bin/env bash
-# Block commits that violate SAMA layer/atomic/modeled rules.
+# Block commits that violate the v1 SAMA disciplines.
exec sama check
\`\`\`
-### GitHub Action
+#### GitHub Action
\`\`\`yaml
# .github/workflows/sama.yml
@@ -468,18 +485,14 @@ jobs:
./sama check
\`\`\`
-If the rule lives in a hook or an action that fails the build, the harness can't talk the agent out of it. That is the whole point of the [corpus post](/blog/agentic-coding-corpus-three-patterns) and the next step from the [from-rules-to-checks](/blog/from-rules-to-checks) wrap-up.
+### the case behind it (v1 essays)
-## the case behind it
+Two long-form pieces that argued *why* SAMA was shaped this way, written before the v2 spec drafted:
-Two long-form pieces that argue *why* SAMA is shaped this way:
+- [**The Claude Code harness postmortem read through TDD + SAMA**](/blog/claude-code-harness-postmortem) — ThePaSch's r/ClaudeAI audit read against the iron law and the verification grep.
+- [**Three patterns ten threads converge on**](/blog/agentic-coding-corpus-three-patterns) — a six-month corpus of r/ClaudeAI, r/ClaudeCode, r/AgentsOfAI failure-mode threads with per-pattern mitigation tables.
-- [**The Claude Code harness postmortem read through TDD + SAMA**](/blog/claude-code-harness-postmortem) — ThePaSch's r/ClaudeAI audit (40+ hidden reminders, 5 gag-order sites, 158 prompt versions in 11 days) read against the iron law and the verification grep. *The harness is loud; the diff doesn't have to be.*
-- [**Three patterns ten threads converge on**](/blog/agentic-coding-corpus-three-patterns) — a six-month corpus of r/ClaudeAI, r/ClaudeCode, r/AgentsOfAI failure-mode threads. Per-pattern mitigation tables map each thread to the SAMA / iron-law rule that catches or prevents it.
-
-If you're reading these for the first time, the order to take them is harness postmortem → corpus → back here.
-
-## why these four together
+### why these four together
Each property fixes a different failure mode:
@@ -488,9 +501,7 @@ Each property fixes a different failure mode:
- *Modeled* fails when types and tests scatter → siblings are mandatory.
- *Atomic* fails when files swell → the ~700-line split keeps atoms small.
-Pick one and you'll claw back some clarity. Pick all four and the codebase becomes the kind an agent can be left alone with — there is exactly one right place for any change, and a one-line shell command that proves the layer rule.
-
-The blog post [*Red, tokens, atoms*](/blog/three-constraints-agentic-coding) argues SAMA also compounds with TDD and Claude Code's token-saving discipline; the four properties on this page are the *Atomic* / *Modeled* / *Architecture* / *Sorted* halves of that story.
+The blog post [*Red, tokens, atoms*](/blog/three-constraints-agentic-coding) argues SAMA also compounds with TDD and Claude Code's token-saving discipline.
[← back to tdd.md](/) · [the blog](/blog) · [the guides](/guides)
`;
@@ -526,7 +537,12 @@ export const samaSlugHandler = async (req: { params: { slug: string } }): Promis
const html = await renderNotFound(`/sama/${slug}`);
return htmlResponse(html, 404);
}
- const md = await file.text();
+ const rawMd = await file.text();
+ // Stripe-style "older version" banner — prepended to every v1
+ // discipline page so a reader landing directly on /sama/sorted etc.
+ // sees the v2-spec pointer before the v1 prose.
+ const v1Banner = `> **You are reading the v1 practitioner version of this property.** The formal, normative v2 specification — frozen core, profile mechanism, deterministic verifier, and §5 cross-repo measurement chain — lives at **[/sama/v2](/sama/v2)**. This page is preserved as background reading.\n\n`;
+ const md = v1Banner + rawMd;
const html = await renderDocsPage({
title: `SAMA · ${entry.letter} — ${entry.title} — tdd.md`,
description: entry.description,