syntaxai/tdd.md · commit 7bd481f

Blog post: every artifact has a URL — the on-ramp doesn't

Drama post framing the upcoming CONTRIBUTING.md /goal. Same pattern as
sama-v2-goal-chain-gap: argues that one level above the /goal artifact,
the workflow itself is the next missing piece — the authoring path
isn't auditable from the site, only the outputs are.

Concrete 10-step thought experiment of what a new contributor adding
their first blog post would actually have to do (ends in "give up").
Sketches the fix: one CONTRIBUTING.md, two surfaces (root + /contributing),
single source of truth (links don't restate), dogfooded (own creation is
/goal-driven), drift-detectable (test grep-checks references not
restatements).

Two watermarked images in public/images/: the gap (artifact-vs-path
table with the dramatic "How do I contribute? — MISSING" row) and the
fix (CONTRIBUTING.md section → canonical source → synthesis table).

Co-Authored-By: Claude Opus 4.7 <[email protected]>
author
syntaxai <[email protected]>
date
2026-05-25 15:18:22 +01:00
parent
9fe7178
commit
7bd481f96213d45cac751b3f1b1af4f9efc612b8

6 files changed · +254 −0

added content/blog/sama-v2-on-ramp-gap.md +97 −0
@@ -0,0 +1,97 @@
1+# Every artifact has a URL. The on-ramp doesn't.
2+
3+Open `https://tdd.md` in a fresh browser. Count the entry points:
4+
5+- [/sama/v2](/sama/v2) — the spec
6+- [/sama/v2/verify](/sama/v2/verify) — the live verifier
7+- [/blog](/blog) — the narrative
8+- [/goals](/goals) — the contracts that drove every PR
9+- [/GIT/tdd.md/tree/main](/GIT/tdd.md/tree/main) — the source
10+- [/sitemap.xml](/sitemap.xml) — every URL on the site
11+
12+Six entry points. Each one is its own auditable artifact. Each one has been the subject of at least one blog post. Each one is what the empirical-chain argument rests on.
13+
14+Now ask the question the entire site exists to answer for a reader: **"How do I contribute?"**
15+
16+There is no answer. There is no front door. There is no document at `/contributing` or `CONTRIBUTING.md` or anywhere else that says *"here is how you add a feature to this codebase."* You are expected to read 5+ blog posts, browse the goals registry, skim PR bodies for patterns, and reverse-engineer the file-naming convention from the source tree. The site that has been preaching auditability for forty PRs has been failing the most basic on-ramp test the entire time.
17+
18+![Every artifact has a URL — the path to authoring them doesn't](/images/contributing-onramp-gap.png?v=1)
19+
20+## The artifacts vs the path
21+
22+The table above splits cleanly into two halves. Above the line: every *output* the codebase produces is in git, on the site, and grep-able. Below the line, in amber and red: the *authoring path* — how those outputs come into being — is scattered or missing entirely.
23+
24+Specifically:
25+
26+- **The `/goal` workflow rule** lives at `/var/home/scri/.claude/projects/-var-home-scri-Documents-tdd-md/memory/feedback_goal_authoring_workflow.md` — an agent-private memory file. A human contributor literally cannot read it. The rule that determines how every PR on this site is authored is preserved for the agent and invisible to everyone else.
27+
28+- **The layer-prefix convention** (`a31_*` = Layer 0, `b32_*` = Layer 1, `c14_*` = Layer 2, `d21_*` = Layer 3) is partially documented in [/sama/v2 §1.1](/sama/v2#11-layers), partially in the `/sama/sorted` discipline page, and partially encoded in the source code itself. A new contributor has to triangulate.
29+
30+- **The branch-PR-deploy flow** (branch → `gh pr create` → merge → push p620 → `flatpak-spawn --host scripts/p620/deploy-tdd-md.sh` → live-verify) is in *zero* blog posts as a standalone procedure. It's mentioned as a constraint inside individual `/goal` bodies, embedded in PR commit messages, scattered across the recent /goals archive. Never collected.
31+
32+- **The test discipline** (sibling `.test.ts`, 402+ stays green, /sama/v2/verify must stay 7/7 ✓) is the load-bearing anti-fudge rule for the entire codebase. It appears in §4.3 of the spec, in every PR body, in every /goal's anti-fudge constraints. Never in one document.
33+
34+- **The image convention** (live under `public/images/`, `https://tdd.md` watermark, served via `/images/<name>.<ext>` wildcard) was added in [PR #44](/GIT/tdd.md/commit/db83746) and lives only in memory + scattered references. There is no public document a contributor can read to learn it.
35+
36+- **The Containerfile gotcha** (every new top-level directory needs a `COPY <dir> ./<dir>` line, surfaced by PR #46 when `/goals/<slug>` returned 404 in production) is captured in *one PR's commit message* and the postmortem section of the goals registry implementation. A new contributor who adds a top-level directory will hit the same 404 in production and have to discover the rule themselves.
37+
38+Each of these rules is real, enforced, and load-bearing. None of them is in a canonical-doc-shaped place.
39+
40+## What a new contributor actually sees
41+
42+Pretend you've just landed on tdd.md and want to add a blog post. The literal steps required to know how:
43+
44+1. Open `/sama/v2` to learn the layer convention. Realize blog posts aren't a layer-thing — they're content.
45+2. Open `/blog` and click around — notice the URL pattern `/blog/<slug>`.
46+3. Browse `/GIT/tdd.md/tree/main/content/blog` — find that posts are markdown files.
47+4. Open `/GIT/tdd.md/blob/main/src/a31_blog.ts` — discover `ALL_POSTS` and realize new posts need to be registered.
48+5. Look at `/blog/sama-v2-sitemap-implementation-plan` to see the pattern for *how* posts are authored — but that's about sitemap.xml, not about the blog post itself.
49+6. Hunt for a recent merged PR — find `gh pr view 44` — see the branch-merge-deploy flow in *the commit messages*, not in any document.
50+7. Try to figure out images. Read `/blog/sama-v2-goal-chain-gap` looking for image conventions. Find a passing mention. Open a recent PR with images. Reverse-engineer.
51+8. Realize you don't know whether your blog post needs sibling tests. Read `/sama/v2 §4.3`. Determine: no — only source files need siblings. Content files don't.
52+9. Realize you might break `/sama/v2/verify`. Run it locally? There's no instruction. Push to `main` and pray? That breaks the workflow. Fork the repo? The verifier doesn't run on forks.
53+10. Give up. Open an issue saying "how do I contribute?"
54+
55+This is the experience the site currently delivers. The empirical chain is intact for every artifact *except* the one that brings new contributors in.
56+
57+## Why this is a SAMA v2 self-violation
58+
59+The [chain-gap drama post](/blog/sama-v2-goal-chain-gap) argued that the `/goal` command was a SAMA v2 self-violation because the contract driving every PR wasn't in the chain. The fix shipped — `/goals/<slug>.md` files are in git, the workflow memory is locked in, every future `/goal` lands in the registry by construction.
60+
61+This post argues the same shape, one level up: **the workflow itself is the next missing artifact**. The `/goal` is now in git; the rule for how to *write* a `/goal` is not. The branch flow is encoded in memory; the rule for how to *run* the branch flow is not on the site. The image convention is enforced by code; the rule that a contributor needs to know about the convention is nowhere a contributor would think to look.
62+
63+It's the same structural failure as before, applied to procedure instead of contract. The empirical chain has always had this hole; we just shipped the patch one level too shallow.
64+
65+The SAMA v2 §0 auditability clause says *"the verifier is a deterministic program; that claim is only auditable if a human can reproduce it from the data."* By the same logic: *the authoring process is a discipline; that claim is only auditable if a human can reproduce it from the published material.* They can't. Not because we hid anything — because we never wrote the on-ramp down in one place.
66+
67+## The fix
68+
69+![CONTRIBUTING.md — synthesis, not duplication](/images/contributing-onramp-fix.png?v=1)
70+
71+One markdown file. Two surfaces:
72+
73+- **`./CONTRIBUTING.md` at repo root** — GitHub auto-detects this and surfaces it in the contribute UI. A reader on `github.com/syntaxai/tdd.md` gets pointed at it immediately.
74+- **`/contributing` on tdd.md** — the canonical permalink, served from the same markdown body. Sitemap entry, nav link, navigable like every other page.
75+
76+One file, two URLs. Same pattern as the sitemap (one source, two delivery mechanisms — registry + URL endpoint).
77+
78+**Three load-bearing properties** the document must satisfy to be 100% SAMA v2:
79+
80+1. **Single source of truth.** Every rule is owned by exactly one canonical artifact. `CONTRIBUTING.md` **links**, doesn't restate. The layer convention lives at `/sama/v2 §1.1`; CONTRIBUTING.md says "see §1.1" and never copies the table. If a future PR changes the spec, CONTRIBUTING.md doesn't drift because there's nothing in it to drift.
81+
82+2. **Dogfooded.** Its own creation is `/goal`-driven. `goals/contributing-md.md` lands as the first commit of the PR per the [workflow memory](https://tdd.md/blog/sama-v2-goal-chain-gap); the merge SHA flips to shipped at deploy time. The artifact that documents the workflow is itself produced by the workflow.
83+
84+3. **Drift-detectable.** A test grep-checks that `CONTRIBUTING.md` only contains *references* to canonical sources — no rule restatements. If someone adds "the SAMA layers are a31/b32/c14/d21" as a paragraph instead of a link, the test fails. This is the same anti-fudge shape the verifier uses for source files.
85+
86+## What lands when this ships
87+
88+After the `/goal` that fires next:
89+
90+- A reader on `github.com/syntaxai/tdd.md` lands on `CONTRIBUTING.md` and can produce their first PR in a single read.
91+- A reader on `tdd.md/contributing` gets the same content, navigable from the main nav.
92+- An agent context-loaded with this site no longer has to assemble the workflow from scattered sources — one document is the entry point, with links out to the canonical artifacts for the details.
93+- The empirical chain gains its final missing link: the procedural one. Every artifact has a URL. The path to authoring them now also has a URL.
94+
95+The `/goal` that drives this work follows immediately after this post — same pattern as every other plan-then-execute cycle on this site. After merge, the postmortem post compares the plan to what landed.
96+
97+The drama ends quietly. The chain closes. A new contributor lands on tdd.md and finds the front door right where they expected it.
added public/images/contributing-onramp-fix.png +0 −0
added public/images/contributing-onramp-fix.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 fix — CONTRIBUTING.md synthesizes existing artifacts, no new abstractions</text>
7+ <text x="80" y="92" font-size="32" font-weight="700" fill="#e8e8e8">Each section links to its canonical source. No duplication.</text>
8+ <text x="80" y="120" font-size="14" fill="#7a7a7a">Two surfaces: ./CONTRIBUTING.md at repo root (GitHub-native) + /contributing on the site. One file, two URLs.</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">CONTRIBUTING.md SECTION</text>
14+ <text x="640" y="172" fill="#909090">CANONICAL SOURCE (linked)</text>
15+ <text x="1000" y="172" fill="#909090">SYNTHESIS</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="14">
21+
22+ <text x="100" y="216" fill="#c8c8c8" font-weight="600">Before you start</text>
23+ <text x="640" y="216" fill="#6a8db5">/sama/v2 · /blog/sama-v2-goal-chain-gap</text>
24+ <text x="1000" y="216" fill="#8a8a8a">3 links</text>
25+
26+ <text x="100" y="246" fill="#c8c8c8" font-weight="600">The /goal workflow</text>
27+ <text x="640" y="246" fill="#6a8db5">/goals/migrate-historical-goals</text>
28+ <text x="1000" y="246" fill="#8a8a8a">7-line summary</text>
29+
30+ <text x="100" y="276" fill="#c8c8c8" font-weight="600">SAMA layer convention</text>
31+ <text x="640" y="276" fill="#6a8db5">/sama/v2 §1.1 + /sama/sorted</text>
32+ <text x="1000" y="276" fill="#8a8a8a">aXX/bXX/cXX/dXX table</text>
33+
34+ <text x="100" y="306" fill="#c8c8c8" font-weight="600">How to add a blog post</text>
35+ <text x="640" y="306" fill="#6a8db5">content/blog/&lt;slug&gt;.md + ALL_POSTS</text>
36+ <text x="1000" y="306" fill="#8a8a8a">recipe</text>
37+
38+ <text x="100" y="336" fill="#c8c8c8" font-weight="600">How to add a /goal</text>
39+ <text x="640" y="336" fill="#6a8db5">workflow memory + /goals registry</text>
40+ <text x="1000" y="336" fill="#8a8a8a">recipe</text>
41+
42+ <text x="100" y="366" fill="#c8c8c8" font-weight="600">How to add an image</text>
43+ <text x="640" y="366" fill="#6a8db5">public/images/ + watermark convention</text>
44+ <text x="1000" y="366" fill="#8a8a8a">recipe</text>
45+
46+ <text x="100" y="396" fill="#c8c8c8" font-weight="600">How to add a Layer-1 helper</text>
47+ <text x="640" y="396" fill="#6a8db5">b32_&lt;name&gt;.ts + b32_&lt;name&gt;.test.ts</text>
48+ <text x="1000" y="396" fill="#8a8a8a">recipe</text>
49+
50+ <text x="100" y="426" fill="#c8c8c8" font-weight="600">How to add a top-level directory</text>
51+ <text x="640" y="426" fill="#6a8db5">Containerfile COPY line (gotcha PR #46)</text>
52+ <text x="1000" y="426" fill="#8a8a8a">recipe + warning</text>
53+
54+ <text x="100" y="456" fill="#c8c8c8" font-weight="600">Anti-fudge defaults</text>
55+ <text x="640" y="456" fill="#6a8db5">/sama/v2/verify (must stay 7/7 ✓)</text>
56+ <text x="1000" y="456" fill="#8a8a8a">5-bullet checklist</text>
57+
58+ <text x="100" y="486" fill="#c8c8c8" font-weight="600">Branch / deploy flow</text>
59+ <text x="640" y="486" fill="#6a8db5">scripts/p620/deploy-tdd-md.sh + gh CLI</text>
60+ <text x="1000" y="486" fill="#8a8a8a">5-step sequence</text>
61+ </g>
62+
63+ <!-- Bottom callout -->
64+ <rect x="80" y="520" width="1040" height="140" fill="#101a10" stroke="#1f3f1f" stroke-width="1" rx="6"/>
65+ <g font-family="ui-monospace, 'SF Mono', 'JetBrains Mono', Menlo, Consolas, monospace">
66+ <text x="100" y="552" font-size="16" font-weight="600" fill="#7ec77e">Three load-bearing properties:</text>
67+ <text x="100" y="578" font-size="14" fill="#c8c8c8">1. SINGLE SOURCE OF TRUTH — every rule is owned by exactly one canonical artifact; CONTRIBUTING.md links, doesn't restate.</text>
68+ <text x="100" y="602" font-size="14" fill="#c8c8c8">2. TWO SURFACES — ./CONTRIBUTING.md (GitHub auto-detects it) + /contributing (site canonical) read from ONE markdown file.</text>
69+ <text x="100" y="626" font-size="14" fill="#c8c8c8">3. DOGFOODED — its own creation is a /goal-driven artifact at /goals/contributing-md, with merge_sha in frontmatter.</text>
70+ <text x="100" y="648" font-size="13" fill="#8a8a8a">Drift detection follow-up: a test grep-checks that CONTRIBUTING.md only contains references to canonical sources (no rule restatements).</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>
added public/images/contributing-onramp-gap.png +0 −0
added public/images/contributing-onramp-gap.svg +76 −0
@@ -0,0 +1,76 @@
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 — every output has a URL, the on-ramp doesn't</text>
7+ <text x="80" y="92" font-size="30" font-weight="700" fill="#e8e8e8">Every artifact has a URL. The path to authoring them doesn't.</text>
8+ <text x="80" y="120" font-size="14" fill="#7a7a7a">A new contributor must read 5+ blog posts + the spec + agent-private memory files to assemble "how to add a feature".</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="600" y="172" fill="#909090">WHERE IT LIVES</text>
15+ <text x="980" y="172" fill="#909090">CANONICAL DOC?</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">SAMA spec (rules + profile + verifier)</text>
23+ <text x="600" y="216" fill="#8a8a8a">/sama/v2</text>
24+ <text x="980" y="216" fill="#7ec77e">✓ on-site</text>
25+
26+ <text x="100" y="246" fill="#c8c8c8">§4 verifier verdict (live proof)</text>
27+ <text x="600" y="246" fill="#8a8a8a">/sama/v2/verify</text>
28+ <text x="980" y="246" fill="#7ec77e">✓ live · auditable</text>
29+
30+ <text x="100" y="276" fill="#c8c8c8">§5 metric definitions + measurements</text>
31+ <text x="600" y="276" fill="#8a8a8a">/sama/v2 §5 · /blog</text>
32+ <text x="980" y="276" fill="#7ec77e">✓ on-site</text>
33+
34+ <text x="100" y="306" fill="#c8c8c8">/goal contracts (post PR #47)</text>
35+ <text x="600" y="306" fill="#8a8a8a">/goals · /goals/&lt;slug&gt;</text>
36+ <text x="980" y="306" fill="#7ec77e">✓ archived</text>
37+
38+ <text x="100" y="336" fill="#c8c8c8">Source code (every file)</text>
39+ <text x="600" y="336" fill="#8a8a8a">/GIT/tdd.md/tree/main</text>
40+ <text x="980" y="336" fill="#7ec77e">✓ browseable</text>
41+
42+ <text x="100" y="366" fill="#c8c8c8">Discoverability (every URL)</text>
43+ <text x="600" y="366" fill="#8a8a8a">/sitemap.xml</text>
44+ <text x="980" y="366" fill="#7ec77e">✓ generated</text>
45+
46+ <text x="100" y="396" fill="#c8c8c8">Blog narrative (every decision)</text>
47+ <text x="600" y="396" fill="#8a8a8a">/blog</text>
48+ <text x="980" y="396" fill="#7ec77e">✓ indexed</text>
49+
50+ <text x="100" y="426" fill="#c8c8c8">Authoring workflow (the /goal rule)</text>
51+ <text x="600" y="426" fill="#8a8a8a">agent-private memory file</text>
52+ <text x="980" y="426" fill="#c89a3a">~ not on site</text>
53+
54+ <text x="100" y="456" fill="#c8c8c8">Layer / test / branch / deploy patterns</text>
55+ <text x="600" y="456" fill="#8a8a8a">scattered across PRs + posts</text>
56+ <text x="980" y="456" fill="#c89a3a">~ no canonical doc</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">"How do I contribute?" — the on-ramp</text>
61+ <text x="600" y="502" fill="#c87070">nowhere — assemble from 11+ sources</text>
62+ <text x="980" y="502" fill="#e85050" font-weight="700">✗ MISSING</text>
63+ </g>
64+
65+ <!-- Bottom callout -->
66+ <rect x="80" y="552" width="1040" height="104" 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">"Every artifact is auditable" — yes, every OUTPUT is. The path to producing the outputs requires reverse-engineering</text>
70+ <text x="100" y="628" font-size="14" fill="#c8c8c8">across blog posts + memory files (which humans can't even read) + commit history. A new contributor lands on tdd.md</text>
71+ <text x="100" y="648" font-size="14" fill="#c8c8c8">with six entry points and no front door. The chain has all its links — except the one that brings a contributor in.</text>
72+ </g>
73+
74+ <!-- Watermark -->
75+ <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>
76+</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-on-ramp-gap",
17+ title: "Every artifact has a URL. The on-ramp doesn't.",
18+ description: "Open tdd.md in a fresh browser. Count the entry points — /sama/v2 (spec), /sama/v2/verify (live), /blog (narrative), /goals (contracts), /GIT/tdd.md (source), /sitemap.xml (every URL). Six artifacts, each auditable, each its own blog post subject. Now ask the question the site exists to answer for a reader: 'how do I contribute?' There is no answer. No CONTRIBUTING.md, no /contributing URL, no canonical on-ramp anywhere. Forty PRs of preaching auditability — and the most basic on-ramp test failing the entire time. This post is the drama. Walks the artifact-vs-path table: every OUTPUT lives in a canonical place (✓), every authoring rule lives somewhere a contributor wouldn't think to look (the /goal workflow rule is in an agent-private memory file that humans literally cannot read; the layer convention is in /sama/v2 §1.1 + /sama/sorted + the source tree; the branch-PR-deploy flow is scattered across PR commit messages and individual /goal bodies; the image convention lives in memory only; the Containerfile gotcha lives in one PR's commit message). Concrete 10-step thought experiment of what a new contributor adding their first blog post would actually have to do — ends in 'give up, open an issue saying how do I contribute'. Frames this as a SAMA v2 self-violation parallel to /blog/sama-v2-goal-chain-gap one level up: that post fixed the /goal in the chain; this post argues the workflow itself is the next missing artifact, same structural failure applied to procedure instead of contract. Sketches the fix: one CONTRIBUTING.md, two surfaces (./CONTRIBUTING.md at repo root + /contributing on the site, same markdown source), with three load-bearing properties — single source of truth (links don't restate), dogfooded (its own creation is /goal-driven at /goals/contributing-md), drift-detectable (a test that grep-checks CONTRIBUTING.md contains only references not restatements). The /goal that drives the implementation follows this post per the plan-execute-postmortem pattern.",
19+ date: "2026-05-25",
20+ },
1521 {
1622 slug: "sama-v2-goal-chain-gap",
1723 title: "Every chain artifact lives in git — except the /goal",