syntaxai/tdd.md · commit a422881

Blog post: every chain artifact lives in git — except the /goal

The drama post that frames the next two /goals. Traces the concrete
loss across PRs #38/#40/#42 (the most-cited empirical-chain work)
where the /goal text is only forensically reconstructible. Argues
this is a SAMA v2 self-violation against §0's auditability clause.
Walks the three candidate fixes — git notes, goals/<sha>.goal,
goals/<slug>.md with merge_sha frontmatter — and picks the third
because it mirrors /blog + /sama exactly without new abstractions.
Two visualisations: the chain-with-hole and the chain-with-fix,
both watermarked.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
author
syntaxai <[email protected]>
date
2026-05-25 14:04:34 +01:00
parent
968890f
commit
a4228811512980c01381a3eb0b2ca7a7156ea182

6 files changed · +280 −0

added content/blog/sama-v2-goal-chain-gap.md +115 −0
@@ -0,0 +1,115 @@
1+# Every chain artifact lives in git — except the `/goal`
2+
3+This site's load-bearing claim is **auditability**. The `/sama/v2/verify` page makes a structural assertion about the source tree and reports 7/7 ✓ against it, live, every time you reload. The `/blog/sama-v2-workingset-cross-repo-baseline` post measures eight repositories at pinned SHAs and asks you to clone them yourself if you want to double-check. The sitemap is generated from the registries, the verifier reads the profile, the profile is in the repo, the repo is browseable at [`/GIT/tdd.md/tree/main`](/GIT/tdd.md/tree/main). Every link in the empirical chain is supposed to be inspectable.
4+
5+There is one artifact in the chain that isn't.
6+
7+The `/goal` command — the structured spec that drives every PR on this site, that pins the *Done when* clauses, that lists the *Constraints (anti-fudge)*, that names the *Load-bearing files to read FIRST* — gets typed into a scratch file called `goal.md` at the repo root, read by the agent, and then **overwritten by the next `/goal`**. The careful contract that produced the verifier, the metrics emitter, the cross-repo measurements, the sitemap, the URL refactor — gone. The thing that started every chain link is the only thing not in the chain.
8+
9+![Every chain artifact lives in git — except the /goal](/images/goal-chain-gap.png?v=1)
10+
11+## The drama, concretely
12+
13+This site has shipped roughly 40 PRs over the last month. The recent ones — the ones the empirical-chain posts cite — were all `/goal`-driven. To pick the highest-profile examples:
14+
15+- **PR #42** dropped the `:owner` segment from `/GIT/` URLs. The `/goal` specified one regex (anti-fudge), defined the 301 redirect contract, listed all 49 references to be rewritten, and forbade alias mode. The [plan post](/blog/sama-v2-git-url-refactor-plan) cites those constraints. The [postmortem](/blog/sama-v2-git-url-refactor-postmortem) scores plan vs actual against them. Yet the `/goal` text itself is **gone** — overwritten the next time someone (me) wrote a new `/goal`.
16+
17+- **PR #40** built `/sitemap.xml` as a pure Layer 1 helper. The `/goal` enumerated five test cases (empty list, single URL with/without lastmod, order preservation, XML-escape), three anti-fudge clauses (no second URL list, no static commit, no string-concat XML), and one "load-bearing automatic property" claim. The [plan post](/blog/sama-v2-sitemap-implementation-plan) explains them. The `/goal` text itself: **gone**.
18+
19+- **PR #38** redesigned the `sama-layers` image per five explicit feedback points from the user. The `/goal`-equivalent was a conversational instruction. **Gone the moment the next instruction arrived.**
20+
21+You can reconstruct *what* the goal was from the resulting PR description, the commit message, and the blog posts — partially. You **cannot** reconstruct the *contract* the agent was held against without the original text. The auditability claim has a hole, and the hole is shaped exactly like one file: `goal.md`.
22+
23+## Why this is a SAMA v2 self-violation
24+
25+The SAMA v2 spec at [`/sama/v2`](/sama/v2) §0 declares the verifier is "a deterministic program; that claim is only auditable if a human can reproduce it from the data." Every empirical-chain blog post on this site cites this clause when handing-tracing measurements. The chain of trust is:
26+
27+```
28+rule (the spec)
29+ → verifier (the program)
30+ → codebase (passing the program)
31+ → measurement (the §5 numbers)
32+ → blog post (the argument)
33+```
34+
35+Each link is auditable because each link is in git or live-served from git. Now ask: **what produced the rule, the verifier, the codebase, the measurement, the blog post?**
36+
37+A `/goal` did. Every single one of them. And the `/goal` is not in the chain. Not in git, not live-served, not even reliably preserved in the PR description (some PRs have it, most have only summary bullets that lose the *Constraints* and *Load-bearing files* sections).
38+
39+The site has been making a structural claim — "every artifact in the empirical chain is auditable" — while the artifact that authors every other artifact is the one we lose. It's exactly the kind of self-inconsistency the [verifier-rename post](/blog/sama-v2-verifier-and-the-rename) called out: the spec applies to the discipline itself, or it doesn't apply.
40+
41+Today it doesn't apply. Today the chain has a hole.
42+
43+## What the partial alternatives look like
44+
45+It's not that *nothing* survives. Let's enumerate what does:
46+
47+- **PR descriptions** — sometimes contain the full `/goal` body (when I remember to paste it), sometimes a summary, sometimes neither. `gh pr view 42 --json body` for one recent PR shows ~80% recovery; older ones show ~30%.
48+- **Commit messages** — describe what changed, never carry the `/goal` text. They sit at the wrong layer.
49+- **Blog posts** — paraphrase the `/goal` in human-readable prose ("the post said the design spec was X"). Lossy by design — posts are for readers, not for audit.
50+- **Conversation transcripts** — the agent's session logs contain the original `/goal` verbatim. But conversations are not in git, not live-served, and they get summarized when context fills up. **Highest-fidelity, lowest-durability.**
51+
52+None of these alone is auditable. Together they're a forensic exercise.
53+
54+## Three candidate fixes
55+
56+There are three reasonable ways to integrate `/goal` commands into git. They all solve "we lose them"; they differ in shape:
57+
58+| Option | Naming | Pros | Cons |
59+|---|---|---|---|
60+| **Git notes** (`git notes --ref=goals add <sha>`) | literally keyed to commit SHA | attaches the `/goal` text to its exact commit; no chicken-and-egg with the SHA | invisible on GitHub/Forgejo by default; no native render path on tdd.md; refs/notes must be pushed separately; most devs don't know they exist |
61+| **`goals/<sha>.goal`** (post-merge rename) | filename = the merge SHA | filename carries the commit identifier exactly; the user's instinctive suggestion | chicken-and-egg: the SHA doesn't exist when the `/goal` is written; requires post-merge rename or follow-up commit; SHAs are unreadable in nav (`/goals/968890f`) |
62+| **`goals/<slug>.md` + `merge_sha:` frontmatter** | filename = slug, SHA in metadata | identical pattern to `/blog` and `/sama` (registry → handler → route); readable URLs; no chicken-and-egg; SHA lookup via one grep; renderable on tdd.md without new abstractions | filename isn't literally the SHA — the user's instinctive suggestion isn't honoured byte-for-byte |
63+
64+The third option wins on every axis except the literal filename-equals-SHA property. Compromise: filename is the slug, frontmatter carries `merge_sha: 968890f`, lookup by SHA is `grep -l "merge_sha: 968890f" goals/` and the canonical permalink is `/goals/<slug>`. The user's "filename = SHA" intuition is honoured in spirit (every goal IS keyed to its merge SHA in git-searchable metadata) without paying the chicken-and-egg cost.
65+
66+## The fix, sketched
67+
68+![/goals as a first-class registry, mirroring /blog and /sama](/images/goal-chain-fix.png?v=1)
69+
70+Three layers, identical shape to `/blog` and `/sama`:
71+
72+- **Layer 0** — `src/a31_goals.ts` registry. `ALL_GOALS: GoalEntry[]` with `slug, title, date, branch, prNumber, mergeSha, status, relatedPosts`. Same shape as `ALL_POSTS`.
73+- **Layer 1** — `src/b32_goals_meta.ts` pure helper. Parses YAML frontmatter from goal bodies; looks up a goal by `merge_sha` prefix (so `/GIT/tdd.md/commit/968890f` can find the goal that drove it). Sibling test covers the parser + the lookup.
74+- **Layer 3** — `src/d21_handlers_goals.ts`. Index handler at `/goals` (table of every goal sorted by date), detail handler at `/goals/<slug>` (rendered markdown body + frontmatter badges + links to PR + merge commit + related blog posts).
75+
76+Plus the boring wiring: `/goals` link in the nav strip, `ALL_GOALS` entries added to the sitemap handler, `"/goals"` added to `STATIC_PATHS`. Every layer is a copy-paste of the `/blog` and `/sama` patterns. No new abstractions, no new conventions. This is the SAMA v2 prediction the [layer-decomposition image](/sitemap-layers.png) makes: when a feature matches a layered codebase's existing patterns, the new feature absorbs into the existing shape.
77+
78+## The workflow lock-in
79+
80+Persisting the goals isn't enough on its own. **The authoring workflow has to change** so a `/goal` lands as a committed file *before* any code is written:
81+
82+1. User fires `/goal`.
83+2. Agent's FIRST action — before reading any source files, before running any commands — is to write the `/goal` body verbatim to `goals/<slug>.md` with frontmatter `status: pending, merge_sha: null`.
84+3. Agent commits this goal file on a new branch.
85+4. Then the implementation work begins — the rest of the PR builds on this initial commit.
86+5. After merge, the agent updates `merge_sha` and flips `status: shipped` in the same file as the final commit before deploy.
87+
88+The goal file is in the chain by *construction*, not by remembering. That's the load-bearing property — the same way the sitemap absorbs new blog posts because they land in `ALL_POSTS`, the goals archive absorbs new `/goal` commands because they land in `goals/`.
89+
90+## What about the historical goals
91+
92+About seven recent `/goal` commands produced shippable work and have plan/postmortem posts that cite them. Recovering them is mostly mechanical:
93+
94+```
95+flatpak-spawn --host gh pr list --limit 20 --state merged \
96+ --json number,title,body,headRefName,mergedAt,mergeCommit
97+```
98+
99+The PR body for `/goal`-driven PRs starts with "Goal:" and has the *Done when* / *Constraints* / *Load-bearing files* structure. Filter PRs by that shape, parse the body, populate `goals/<slug>.md` files with `status: shipped` and the merge SHA from the JSON output. Goals that can't be fully recovered (because the PR description summarized rather than quoted) get marked `status: lossy` with a note — never `status: shipped` if we don't have the verbatim text.
100+
101+This is the second `/goal` in the upcoming series. The first builds the infrastructure (`a31_goals.ts`, handlers, routes, sitemap wiring). The second backfills the seven recoverable goals + locks in the workflow.
102+
103+## What this closes
104+
105+After both `/goal`s ship:
106+
107+- `/sama/v2/verify` still reports **7/7 ✓**.
108+- The empirical chain has one more node: `/goals/<slug>` for every PR driven by a `/goal`.
109+- A reader audit­ing a commit can run `grep -l "merge_sha: 968890f" goals/` and find the contract the work was held against.
110+- Every future plan post and postmortem post can link to its source `/goal` at `/goals/<slug>` — closing the citation loop.
111+- The site's auditability claim becomes byte-for-byte true: every artifact in the chain, including the one that drives all the others, is in git.
112+
113+The drama ends quietly. The hole closes. The next refactor's plan post can open with "the `/goal` that drove this work is at `/goals/<this-slug>`," and that link will be a 200 forever.
114+
115+The two `/goal` commands that execute this fix follow. The first builds the infrastructure. The second migrates the seven historical goals and locks in the workflow. Together they make the auditability claim that this site has been making the entire time finally, mechanically, true.
added public/images/goal-chain-fix.png +0 −0
added public/images/goal-chain-fix.svg +84 −0
@@ -0,0 +1,84 @@
1+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 680" width="1200" height="680">
2+ <rect width="1200" height="680" fill="#0a0a0a"/>
3+
4+ <!-- Header -->
5+ <g font-family="ui-monospace, 'SF Mono', 'JetBrains Mono', Menlo, Consolas, monospace">
6+ <text x="80" y="46" font-size="20" font-weight="600" fill="#909090">The fix — /goals as a first-class registry, mirroring /blog and /sama</text>
7+ <text x="80" y="92" font-size="32" font-weight="700" fill="#e8e8e8">Same shape. Same pattern. No new abstractions.</text>
8+ <text x="80" y="120" font-size="14" fill="#7a7a7a">Each /goal lands as goals/&lt;slug&gt;.md, registered in ALL_GOALS, served at /goals/&lt;slug&gt;.</text>
9+ </g>
10+
11+ <!-- Three parallel registries side by side -->
12+ <g font-family="ui-monospace, 'SF Mono', 'JetBrains Mono', Menlo, Consolas, monospace">
13+ <!-- /blog column -->
14+ <rect x="80" y="156" width="340" height="380" fill="#1a1a1a" stroke="#2a2a2a" stroke-width="1.5" rx="6"/>
15+ <text x="100" y="186" font-size="18" font-weight="600" fill="#7ec77e">/blog (existing)</text>
16+ <text x="100" y="212" font-size="13" fill="#8a8a8a">— the empirical chain's narrative —</text>
17+
18+ <text x="100" y="252" font-size="13" fill="#909090" letter-spacing="1">FILES</text>
19+ <text x="100" y="276" font-size="13" fill="#c8c8c8">content/blog/&lt;slug&gt;.md</text>
20+
21+ <text x="100" y="312" font-size="13" fill="#909090" letter-spacing="1">REGISTRY</text>
22+ <text x="100" y="336" font-size="13" fill="#c8c8c8">src/a31_blog.ts</text>
23+ <text x="100" y="354" font-size="12" fill="#8a8a8a">ALL_POSTS: BlogEntry[]</text>
24+
25+ <text x="100" y="392" font-size="13" fill="#909090" letter-spacing="1">ROUTES</text>
26+ <text x="100" y="416" font-size="13" fill="#c8c8c8">/blog</text>
27+ <text x="100" y="434" font-size="13" fill="#c8c8c8">/blog/&lt;slug&gt;</text>
28+
29+ <text x="100" y="472" font-size="13" fill="#909090" letter-spacing="1">IN SITEMAP</text>
30+ <text x="100" y="496" font-size="13" fill="#7ec77e">✓ ALL_POSTS → /blog/&lt;slug&gt;</text>
31+ <text x="100" y="514" font-size="12" fill="#8a8a8a">with lastmod = post.date</text>
32+
33+ <!-- /sama column -->
34+ <rect x="430" y="156" width="340" height="380" fill="#1a1a1a" stroke="#2a2a2a" stroke-width="1.5" rx="6"/>
35+ <text x="450" y="186" font-size="18" font-weight="600" fill="#4a8a8a">/sama (existing)</text>
36+ <text x="450" y="212" font-size="13" fill="#8a8a8a">— the discipline pages —</text>
37+
38+ <text x="450" y="252" font-size="13" fill="#909090" letter-spacing="1">FILES</text>
39+ <text x="450" y="276" font-size="13" fill="#c8c8c8">content/sama/&lt;slug&gt;.md</text>
40+
41+ <text x="450" y="312" font-size="13" fill="#909090" letter-spacing="1">REGISTRY</text>
42+ <text x="450" y="336" font-size="13" fill="#c8c8c8">src/a31_sama.ts</text>
43+ <text x="450" y="354" font-size="12" fill="#8a8a8a">ALL_SAMA: SamaDiscipline[]</text>
44+
45+ <text x="450" y="392" font-size="13" fill="#909090" letter-spacing="1">ROUTES</text>
46+ <text x="450" y="416" font-size="13" fill="#c8c8c8">/sama</text>
47+ <text x="450" y="434" font-size="13" fill="#c8c8c8">/sama/&lt;slug&gt;</text>
48+
49+ <text x="450" y="472" font-size="13" fill="#909090" letter-spacing="1">IN SITEMAP</text>
50+ <text x="450" y="496" font-size="13" fill="#7ec77e">✓ ALL_SAMA → /sama/&lt;slug&gt;</text>
51+
52+ <!-- /goals column (NEW, highlighted) -->
53+ <rect x="780" y="156" width="340" height="380" fill="#1a1a1a" stroke="#c89a3a" stroke-width="2" rx="6"/>
54+ <text x="800" y="186" font-size="18" font-weight="600" fill="#c89a3a">/goals (NEW)</text>
55+ <text x="800" y="212" font-size="13" fill="#8a8a8a">— what produced everything —</text>
56+
57+ <text x="800" y="252" font-size="13" fill="#909090" letter-spacing="1">FILES</text>
58+ <text x="800" y="276" font-size="13" fill="#c8c8c8">goals/&lt;slug&gt;.md</text>
59+ <text x="800" y="294" font-size="12" fill="#8a8a8a">+ YAML frontmatter</text>
60+
61+ <text x="800" y="320" font-size="13" fill="#909090" letter-spacing="1">REGISTRY</text>
62+ <text x="800" y="344" font-size="13" fill="#c8c8c8">src/a31_goals.ts</text>
63+ <text x="800" y="362" font-size="12" fill="#8a8a8a">ALL_GOALS: GoalEntry[]</text>
64+
65+ <text x="800" y="392" font-size="13" fill="#909090" letter-spacing="1">ROUTES</text>
66+ <text x="800" y="416" font-size="13" fill="#c8c8c8">/goals</text>
67+ <text x="800" y="434" font-size="13" fill="#c8c8c8">/goals/&lt;slug&gt;</text>
68+
69+ <text x="800" y="472" font-size="13" fill="#909090" letter-spacing="1">IN SITEMAP</text>
70+ <text x="800" y="496" font-size="13" fill="#7ec77e">✓ ALL_GOALS → /goals/&lt;slug&gt;</text>
71+ <text x="800" y="514" font-size="12" fill="#8a8a8a">merge_sha for git-SHA lookup</text>
72+ </g>
73+
74+ <!-- Bottom callout -->
75+ <rect x="80" y="556" width="1040" height="84" fill="#101a10" stroke="#1f3f1f" stroke-width="1" rx="6"/>
76+ <g font-family="ui-monospace, 'SF Mono', 'JetBrains Mono', Menlo, Consolas, monospace">
77+ <text x="100" y="586" font-size="16" font-weight="600" fill="#7ec77e">Why this is mechanically SAMA v2:</text>
78+ <text x="100" y="608" font-size="14" fill="#c8c8c8">Identical shape to /blog and /sama — same Layer 0 (registry), Layer 1 (frontmatter parser), Layer 3 (handler + routes).</text>
79+ <text x="100" y="626" font-size="14" fill="#c8c8c8">No new abstractions. No new conventions. The empirical chain absorbs the /goal artifact without growing.</text>
80+ </g>
81+
82+ <!-- Watermark -->
83+ <text x="1120" y="664" text-anchor="end" font-family="ui-monospace, 'SF Mono', 'JetBrains Mono', Menlo, Consolas, monospace" font-size="12" fill="#5a5a5a">https://tdd.md</text>
84+</svg>
added public/images/goal-chain-gap.png +0 −0
added public/images/goal-chain-gap.svg +75 −0
@@ -0,0 +1,75 @@
1+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 700" width="1200" height="700">
2+ <rect width="1200" height="700" fill="#0a0a0a"/>
3+
4+ <!-- Header -->
5+ <g font-family="ui-monospace, 'SF Mono', 'JetBrains Mono', Menlo, Consolas, monospace">
6+ <text x="80" y="46" font-size="20" font-weight="600" fill="#909090">The empirical chain — auditable artifacts vs the missing piece</text>
7+ <text x="80" y="92" font-size="30" font-weight="700" fill="#e8e8e8">Every chain artifact lives in git — except the /goal.</text>
8+ <text x="80" y="120" font-size="14" fill="#7a7a7a">tdd.md's argument rests on every artifact being inspectable. The /goal that drives every PR isn't.</text>
9+ </g>
10+
11+ <!-- Column headers -->
12+ <g font-family="ui-monospace, 'SF Mono', 'JetBrains Mono', Menlo, Consolas, monospace" font-size="13" font-weight="600" letter-spacing="2">
13+ <text x="100" y="172" fill="#909090">ARTIFACT</text>
14+ <text x="640" y="172" fill="#909090">LOCATION</text>
15+ <text x="1020" y="172" fill="#909090">IN GIT?</text>
16+ </g>
17+ <line x1="80" y1="184" x2="1120" y2="184" stroke="#2a2a2a" stroke-width="1"/>
18+
19+ <!-- Rows -->
20+ <g font-family="ui-monospace, 'SF Mono', 'JetBrains Mono', Menlo, Consolas, monospace" font-size="15">
21+
22+ <text x="100" y="216" fill="#c8c8c8">source code (the implementation)</text>
23+ <text x="640" y="216" fill="#8a8a8a">src/*.ts</text>
24+ <text x="1020" y="216" fill="#7ec77e">✓ committed</text>
25+
26+ <text x="100" y="246" fill="#c8c8c8">sibling tests (the spec)</text>
27+ <text x="640" y="246" fill="#8a8a8a">src/*.test.ts</text>
28+ <text x="1020" y="246" fill="#7ec77e">✓ committed</text>
29+
30+ <text x="100" y="276" fill="#c8c8c8">SAMA profile (the contract)</text>
31+ <text x="640" y="276" fill="#8a8a8a">sama.profile.toml</text>
32+ <text x="1020" y="276" fill="#7ec77e">✓ committed</text>
33+
34+ <text x="100" y="306" fill="#c8c8c8">§4 verifier verdict (the gate)</text>
35+ <text x="640" y="306" fill="#8a8a8a">tdd.md/sama/v2/verify</text>
36+ <text x="1020" y="306" fill="#7ec77e">✓ live, auditable</text>
37+
38+ <text x="100" y="336" fill="#c8c8c8">§5 cross-repo measurements</text>
39+ <text x="640" y="336" fill="#8a8a8a">scripts/measure-*.ts + blog posts</text>
40+ <text x="1020" y="336" fill="#7ec77e">✓ pinned SHAs</text>
41+
42+ <text x="100" y="366" fill="#c8c8c8">blog posts (the argument)</text>
43+ <text x="640" y="366" fill="#8a8a8a">content/blog/*.md</text>
44+ <text x="1020" y="366" fill="#7ec77e">✓ committed</text>
45+
46+ <text x="100" y="396" fill="#c8c8c8">sitemap (the discoverability)</text>
47+ <text x="640" y="396" fill="#8a8a8a">/sitemap.xml (generated)</text>
48+ <text x="1020" y="396" fill="#7ec77e">✓ from registries</text>
49+
50+ <text x="100" y="426" fill="#c8c8c8">commit messages (the why)</text>
51+ <text x="640" y="426" fill="#8a8a8a">git log</text>
52+ <text x="1020" y="426" fill="#7ec77e">✓ committed</text>
53+
54+ <text x="100" y="456" fill="#c8c8c8">PR descriptions (the summary)</text>
55+ <text x="640" y="456" fill="#8a8a8a">gh pr view &lt;num&gt;</text>
56+ <text x="1020" y="456" fill="#c89a3a">~ partial only</text>
57+
58+ <!-- The dramatic row -->
59+ <rect x="80" y="476" width="1040" height="40" fill="#2a1010" stroke="#7c2020" stroke-width="1.5" rx="4"/>
60+ <text x="100" y="502" fill="#e88080" font-weight="700">/goal commands (the spec that drove EVERY row above)</text>
61+ <text x="640" y="502" fill="#c87070">goal.md → overwritten next turn</text>
62+ <text x="1020" y="502" fill="#e85050" font-weight="700">✗ LOST</text>
63+ </g>
64+
65+ <!-- Bottom callout -->
66+ <rect x="80" y="552" width="1040" height="100" fill="#1a1010" stroke="#3a2020" stroke-width="1" rx="6"/>
67+ <g font-family="ui-monospace, 'SF Mono', 'JetBrains Mono', Menlo, Consolas, monospace">
68+ <text x="100" y="584" font-size="16" font-weight="600" fill="#e88080">The self-violation:</text>
69+ <text x="100" y="608" font-size="14" fill="#c8c8c8">The site's load-bearing claim is "every artifact is auditable — here is the URL where the verifier runs."</text>
70+ <text x="100" y="628" font-size="14" fill="#c8c8c8">But the /goal that produced that codebase vanishes the moment the next /goal is typed. The chain has a hole.</text>
71+ </g>
72+
73+ <!-- Watermark -->
74+ <text x="1120" y="684" text-anchor="end" font-family="ui-monospace, 'SF Mono', 'JetBrains Mono', Menlo, Consolas, monospace" font-size="12" fill="#5a5a5a">https://tdd.md</text>
75+</svg>
modified src/a31_blog.ts +6 −0
@@ -12,6 +12,12 @@ export interface BlogEntry {
1212 }
1313
1414 export const ALL_POSTS: BlogEntry[] = [
15+ {
16+ slug: "sama-v2-goal-chain-gap",
17+ title: "Every chain artifact lives in git — except the /goal",
18+ description: "This site's load-bearing claim is auditability. /sama/v2/verify reports 7/7 ✓ live against the source tree. Cross-repo §5 measurements pinned at SHAs you can re-clone. The sitemap is generated from registries that live in git. Every link in the empirical chain is supposed to be inspectable — and one isn't. The /goal command — the structured spec that drives every PR on this site, that pins the Done-when clauses + Constraints (anti-fudge) + Load-bearing files — gets typed into goal.md and overwritten the next time someone writes a /goal. The careful contract that produced the verifier, the metrics emitter, the cross-repo measurements, the sitemap, the URL refactor: gone. The thing that started every chain link is the only thing not in the chain. This post is the drama: traces the concrete losses across PRs #38/#40/#42 (the visible empirical-chain work) where the /goal text is recoverable only from forensic reconstruction (PR descriptions: partial, commit messages: wrong layer, blog posts: lossy paraphrase, conversation transcripts: not in git). Argues this is a SAMA v2 self-violation against §0's deterministic-program auditability clause. Walks the three candidate fixes — git notes (no native render, invisible by default), goals/<sha>.goal (filename = SHA but chicken-and-egg + unreadable), goals/<slug>.md with merge_sha in frontmatter (mirrors /blog + /sama exactly, SHA lookup via one grep, no new abstractions). The third wins; the user's filename-equals-SHA intuition is honoured in spirit via the frontmatter field. Sketches the SAMA-native fix: a31_goals.ts (Layer 0 registry) + b32_goals_meta.ts (Layer 1 frontmatter parser + SHA lookup) + d21_handlers_goals.ts (Layer 3 index + detail) + the boring wiring (nav link, sitemap entries). Plus the workflow lock-in: agent's FIRST action when /goal fires is to write the body verbatim to goals/<slug>.md and commit it BEFORE any code work, so the goal is in the chain by construction not by remembering. Two /goal commands follow in the next two posts/PRs — one builds the infrastructure, one migrates the seven historical goals + locks the workflow. After both ship, /grep -l 'merge_sha: 968890f' goals/ resolves the contract that produced commit 968890f, and the site's auditability claim becomes byte-for-byte true: every artifact in the chain, including the one that drives all the others, is in git.",
19+ date: "2026-05-25",
20+ },
1521 {
1622 slug: "sama-v2-git-url-refactor-postmortem",
1723 title: "The /GIT/ URL refactor shipped — plan vs actual",