Every chain artifact lives in git — except the /goal
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/2026-05/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. Every link in the empirical chain is supposed to be inspectable.
There is one artifact in the chain that isn't.
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.

#The drama, concretely
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:
PR #42 dropped the
:ownersegment from/GIT/URLs. The/goalspecified one regex (anti-fudge), defined the 301 redirect contract, listed all 49 references to be rewritten, and forbade alias mode. The plan post cites those constraints. The postmortem scores plan vs actual against them. Yet the/goaltext itself is gone — overwritten the next time someone (me) wrote a new/goal.PR #40 built
/sitemap.xmlas a pure Layer 1 helper. The/goalenumerated 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 explains them. The/goaltext itself: gone.PR #38 redesigned the
sama-layersimage per five explicit feedback points from the user. The/goal-equivalent was a conversational instruction. Gone the moment the next instruction arrived.
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.
#Why this is a SAMA v2 self-violation
The SAMA v2 spec at /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:
rule (the spec)
→ verifier (the program)
→ codebase (passing the program)
→ measurement (the §5 numbers)
→ blog post (the argument)
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?
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).
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 called out: the spec applies to the discipline itself, or it doesn't apply.
Today it doesn't apply. Today the chain has a hole.
#What the partial alternatives look like
It's not that nothing survives. Let's enumerate what does:
- PR descriptions — sometimes contain the full
/goalbody (when I remember to paste it), sometimes a summary, sometimes neither.gh pr view 42 --json bodyfor one recent PR shows ~80% recovery; older ones show ~30%. - Commit messages — describe what changed, never carry the
/goaltext. They sit at the wrong layer. - Blog posts — paraphrase the
/goalin human-readable prose ("the post said the design spec was X"). Lossy by design — posts are for readers, not for audit. - Conversation transcripts — the agent's session logs contain the original
/goalverbatim. But conversations are not in git, not live-served, and they get summarized when context fills up. Highest-fidelity, lowest-durability.
None of these alone is auditable. Together they're a forensic exercise.
#Three candidate fixes
There are three reasonable ways to integrate /goal commands into git. They all solve "we lose them"; they differ in shape:
| Option | Naming | Pros | Cons |
|---|---|---|---|
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 |
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) |
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 |
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.
#The fix, sketched

Three layers, identical shape to /blog and /sama:
- Layer 0 —
src/a31_goals.tsregistry.ALL_GOALS: GoalEntry[]withslug, title, date, branch, prNumber, mergeSha, status, relatedPosts. Same shape asALL_POSTS. - Layer 1 —
src/b32_goals_meta.tspure helper. Parses YAML frontmatter from goal bodies; looks up a goal bymerge_shaprefix (so/GIT/tdd.md/commit/968890fcan find the goal that drove it). Sibling test covers the parser + the lookup. - 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).
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 makes: when a feature matches a layered codebase's existing patterns, the new feature absorbs into the existing shape.
#The workflow lock-in
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:
- User fires
/goal. - Agent's FIRST action — before reading any source files, before running any commands — is to write the
/goalbody verbatim togoals/<slug>.mdwith frontmatterstatus: pending, merge_sha: null. - Agent commits this goal file on a new branch.
- Then the implementation work begins — the rest of the PR builds on this initial commit.
- After merge, the agent updates
merge_shaand flipsstatus: shippedin the same file as the final commit before deploy.
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/.
#What about the historical goals
About seven recent /goal commands produced shippable work and have plan/postmortem posts that cite them. Recovering them is mostly mechanical:
flatpak-spawn --host gh pr list --limit 20 --state merged \
--json number,title,body,headRefName,mergedAt,mergeCommit
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.
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.
#What this closes
After both /goals ship:
/sama/v2/verifystill reports 7/7 ✓.- The empirical chain has one more node:
/goals/<slug>for every PR driven by a/goal. - A reader auditing a commit can run
grep -l "merge_sha: 968890f" goals/and find the contract the work was held against. - Every future plan post and postmortem post can link to its source
/goalat/goals/<slug>— closing the citation loop. - 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.
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.
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.