syntaxai/tdd.md · commit df9d41a

Drop redundant :owner segment from /GIT/ URLs — single regex 301

Single-tenant is already enforced by isAllowedRepo() — the owner is
always "syntaxai" or the handler 404s. The URL segment was policy
overhead, not data. Now:

  before:  /GIT/syntaxai/tdd.md/blob/main/src/b32_sama_v2_verify.ts
  after:   /GIT/tdd.md/blob/main/src/b32_sama_v2_verify.ts

Inbound links survive via one regex 301 redirect in the fallback
handler — the new Layer 1 helper b32_git_url_redirect.ts owns the
pure pathname transform, the fallback wraps it in a Response. Sibling
test covers all four URL kinds (tree/blob/raw/commit), .diff variant,
and the non-match paths (other-org, already-new, non-/GIT/).

Changes:
- Layer 1: b32_git_url_redirect.ts (new) — rewriteOldGitUrl(pathname).
- Layer 3 handlers: repoBrowseHandler + commitViewHandler drop owner
  from their signatures; isAllowedRepo collapses to (repo) — owner is
  implicit (LIVE_REPO_OWNER, still exported for c14_git + Forgejo
  proxy callers).
- Bun route in d21_app.ts: /GIT/:owner/:repo/commit/:sha →
  /GIT/:repo/commit/:sha.
- Fallback handler: 301 redirect block placed BEFORE gitBrowseMatch
  so legacy URLs never reach the browse handler; gitBrowseMatch regex
  drops the owner capture.
- Link builders: 8 sites in b51_render_repo.ts, 2 sites in
  b51_render_commit.ts (the bare /<owner>/<repo> breadcrumb stays —
  bare-repo view is out of scope), 1 site in b51_render_edit.ts.
- Content rewrite: 7 blog + spec markdown files + 1 embedded markdown
  in d21_handlers_sama.ts. Plan post keeps its BEFORE/AFTER example
  + curl docs literal (they document the redirect itself).

LIVE_REPO_OWNER stays exported in a31_site_config.ts — used by the
renderer call sites for the "syntaxai/tdd.md" breadcrumb header, and
by c14_git operations that talk to the bare repo.

Tests: 388/388 pass (379 → 388, +9 redirect-helper cases).
Git protocol URLs (/syntaxai/tdd.md.git, /<owner>/<repo> bare repo
view) are unchanged — agents and humans have those copy-pasted into
clone commands and CI configs, scope-out per /goal.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
author
syntaxai <[email protected]>
date
2026-05-25 13:36:28 +01:00
parent
9fb5b29
commit
df9d41adb35da5aed775a8b857592a958cc0bf47

19 files changed · +153 −69

modified content/blog/sama-v2-git-url-refactor-plan.md +2 −2
@@ -15,7 +15,7 @@ Nine characters shorter. The change is small but the workflow it sits inside is
1515
1616 ## Why dropping the owner is safe
1717
18-The relevant code is twenty-one lines down [`src/d21_handlers_repo_browse.ts`](/GIT/syntaxai/tdd.md/blob/main/src/d21_handlers_repo_browse.ts):
18+The relevant code is twenty-one lines down [`src/d21_handlers_repo_browse.ts`](/GIT/tdd.md/blob/main/src/d21_handlers_repo_browse.ts):
1919
2020 ```ts
2121 const isAllowedRepo = (owner: string, repo: string): boolean =>
@@ -77,7 +77,7 @@ The plan deliberately doesn't do these things, even though each is locally appea
7777
7878 - **No hand-maintained list of redirects.** One regex pattern covers all 49 current references and every future one. If the regex grows into "a list", the anti-fudge clause has been violated.
7979 - **No removal of `LIVE_REPO_OWNER`.** The constant has callers beyond URL construction (the live-reports view, the Forgejo proxy hostname). Removing it from `a31_site_config.ts` would be a different, larger refactor that the URL change shouldn't drag in.
80-- **No touching of git-protocol URLs.** `/syntaxai/tdd.md.git` and the bare-repo view at `/syntaxai/tdd.md` go through `isGitProtocol` + `repoMatch` in [`d21_handlers_fallback.ts`](/GIT/syntaxai/tdd.md/blob/main/src/d21_handlers_fallback.ts). Those URLs are git-client-facing — agents and humans have copy-pasted them into clone commands, into CI configs, into other agents' system prompts. Changing them risks breakage for cosmetics. They stay.
80+- **No touching of git-protocol URLs.** `/syntaxai/tdd.md.git` and the bare-repo view at `/syntaxai/tdd.md` go through `isGitProtocol` + `repoMatch` in [`d21_handlers_fallback.ts`](/GIT/tdd.md/blob/main/src/d21_handlers_fallback.ts). Those URLs are git-client-facing — agents and humans have copy-pasted them into clone commands, into CI configs, into other agents' system prompts. Changing them risks breakage for cosmetics. They stay.
8181 - **No alias.** Both URL forms working forever creates two canonical URLs and lets the old one quietly remain in new code. The 301 is what forces consolidation — search engines update, internal code paths rewrite themselves, and a year from now the old form is just a redirect line in one file.
8282 - **No verifier change.** `/sama/v2/verify` stays at 7/7 ✓ across the merge. The §4 check logic is frozen; if a structural choice the refactor wants to make would fail the verifier, the choice changes — not the verifier.
8383
modified content/blog/sama-v2-go-project-dive.md +3 −3
@@ -153,7 +153,7 @@ Derives from Law. No file's declared layer is contradicted by what it imports.
153153
154154 **The `workingSetFit` is the metric I most expected to land near tdd.md's 80%** — two engineered codebases, both with linters and conventions. The measurement says otherwise.
155155
156-**Hand-trace** (auditable per [/sama/v2 §0](/sama/v2)): running `find /tmp/dive -name '*.go' -not -name '*_test.go' -not -path '*/.git/*' -not -path '*/vendor/*' | wc -l` returns **92 source .go files**. Of those, **48** fall in [50, 500] LOC inclusive (matching `WORKING_SET_MIN_LOC` and `WORKING_SET_MAX_LOC` in [`src/a31_sama_v2.ts`](/GIT/syntaxai/tdd.md/blob/main/src/a31_sama_v2.ts)). 48 ÷ 92 = 0.5217 ≈ 52.17%. The polyglot §5 emitter at [`scripts/measure-working-set.ts`](/GIT/syntaxai/tdd.md/blob/main/scripts/measure-working-set.ts) produces the same number from the same source tree.
156+**Hand-trace** (auditable per [/sama/v2 §0](/sama/v2)): running `find /tmp/dive -name '*.go' -not -name '*_test.go' -not -path '*/.git/*' -not -path '*/vendor/*' | wc -l` returns **92 source .go files**. Of those, **48** fall in [50, 500] LOC inclusive (matching `WORKING_SET_MIN_LOC` and `WORKING_SET_MAX_LOC` in [`src/a31_sama_v2.ts`](/GIT/tdd.md/blob/main/src/a31_sama_v2.ts)). 48 ÷ 92 = 0.5217 ≈ 52.17%. The polyglot §5 emitter at [`scripts/measure-working-set.ts`](/GIT/tdd.md/blob/main/scripts/measure-working-set.ts) produces the same number from the same source tree.
157157
158158 The distribution explains it: **44 files under 50 LOC** (mostly small type-only modules, single-helper files, and platform-shim stubs like `dive/image/docker/docker_host_windows.go` at 6 LOC), **48 in band**, and — strikingly — **0 over 500 LOC**. `dive`'s working-set miss is not god-classes (the §4.5 Atomic check passes outright); it's the *opposite* failure mode: many files small enough to fall below the substantive-module threshold.
159159
@@ -161,13 +161,13 @@ The original ~80% estimate was wrong, and wrong in a direction casual eyeballing
161161
162162 ### graphDepth, measured: 12 (originally estimated ~5)
163163
164-The polyglot graphDepth emitter at [`scripts/measure-graph-depth.ts`](/GIT/syntaxai/tdd.md/blob/main/scripts/measure-graph-depth.ts) walks `dive`'s [`go.mod`](https://github.com/wagoodman/dive/blob/d6c691947f8fda635c952a17ee3b7555379d58f0/go.mod), collects every `.go` file's imports, filters to intra-module imports (those starting with `github.com/wagoodman/dive/`), aggregates them per-package-directory, and computes the longest path. The result for `dive@d6c69194`: **27 package directories, 80 internal edges, longest dependency chain of depth 12**.
164+The polyglot graphDepth emitter at [`scripts/measure-graph-depth.ts`](/GIT/tdd.md/blob/main/scripts/measure-graph-depth.ts) walks `dive`'s [`go.mod`](https://github.com/wagoodman/dive/blob/d6c691947f8fda635c952a17ee3b7555379d58f0/go.mod), collects every `.go` file's imports, filters to intra-module imports (those starting with `github.com/wagoodman/dive/`), aggregates them per-package-directory, and computes the longest path. The result for `dive@d6c69194`: **27 package directories, 80 internal edges, longest dependency chain of depth 12**.
165165
166166 A 12-deep import chain is more than twice the audit's eyeball estimate of ~5. The estimate was wrong because I was thinking in *top-level package categories* (`cmd`, `command`, `ui`, `dive`, `filetree`, `internal/utils` — six things), but the actual Go package graph treats each subdirectory as its own package. `cmd/dive/cli/internal/ui/v1/viewmodel` is a different package from `cmd/dive/cli/internal/ui/v1/view`, even though they read like one category to a human; the import graph sees them as distinct hops. The 12-deep chain weaves through subdirectories the human-readable description folded into one bullet.
167167
168168 This is the same shape of finding as the workingSetFit one above: the *metric* sees the structure; the *eye* sees the categories. Both are useful, but only the metric is mechanically comparable across repos.
169169
170-Module-granularity note: the polyglot graphDepth metric counts at the Go package-directory level — multiple `.go` files in one directory share their package and therefore their imports. This is the natural Go analog to the TS file-level metric (TS one module ≈ one file; Go one package ≈ one directory). The semantic is documented in [`src/b32_graph_depth_polyglot.ts`](/GIT/syntaxai/tdd.md/blob/main/src/b32_graph_depth_polyglot.ts).
170+Module-granularity note: the polyglot graphDepth metric counts at the Go package-directory level — multiple `.go` files in one directory share their package and therefore their imports. This is the natural Go analog to the TS file-level metric (TS one module ≈ one file; Go one package ≈ one directory). The semantic is documented in [`src/b32_graph_depth_polyglot.ts`](/GIT/tdd.md/blob/main/src/b32_graph_depth_polyglot.ts).
171171
172172 ## What `dive` would look like at 7/7 — the last 30%
173173
modified content/blog/sama-v2-metrics-emitter.md +3 −3
@@ -116,7 +116,7 @@ verifier can say "0 violations" while the metric says "30% of
116116 boundaries are in Layer 1" — contradictory pictures of the same code.
117117
118118 So the detector now lives in one place — `findParseBoundaryCallSites`
119-in [`src/a31_sama_v2.ts`](/GIT/syntaxai/tdd.md/blob/main/src/a31_sama_v2.ts)
119+in [`src/a31_sama_v2.ts`](/GIT/tdd.md/blob/main/src/a31_sama_v2.ts)
120120 (Layer 0, pure). The verifier consumes it. The metric consumes it.
121121 They share the regex, the comment/string-literal stripping, the file
122122 iteration. The two cannot diverge — if a future commit changes what
@@ -139,10 +139,10 @@ I picked `boundaryRatio`. A raw grep of `src/*.ts` (non-test) for
139139 `JSON.parse(` and `new URL(` returns eleven hits. Four of them are
140140 inside comments or string literals — *"`JSON.parse()` constructors
141141 must not appear in..."* in the docstring of
142-[`c14_request_parse.ts`](/GIT/syntaxai/tdd.md/blob/main/src/c14_request_parse.ts),
142+[`c14_request_parse.ts`](/GIT/tdd.md/blob/main/src/c14_request_parse.ts),
143143 *"parsing as `JSON.parse(` of arbitrary input..."* in the comment
144144 header of
145-[`b32_sama_v2_verify.ts`](/GIT/syntaxai/tdd.md/blob/main/src/b32_sama_v2_verify.ts).
145+[`b32_sama_v2_verify.ts`](/GIT/tdd.md/blob/main/src/b32_sama_v2_verify.ts).
146146 The detector strips comments and quoted literals first, so those
147147 four drop out. Seven real call sites remain:
148148
modified content/blog/sama-v2-rust-project-ripgrep.md +3 −3
@@ -155,7 +155,7 @@ Derives from Law on the same edge set.
155155 | **workingSetFit (50–500 LOC)** | **54.00% (measured, [ripgrep@4519153e](https://github.com/BurntSushi/ripgrep/commit/4519153e5e461527f4bca45b042fff45c4ec6fb9))** — originally estimated ~60% | **52.17% (measured, [dive@d6c69194](https://github.com/wagoodman/dive/commit/d6c691947f8fda635c952a17ee3b7555379d58f0))** — originally estimated ~80% | 80% | ~47% |
156156 | violationCounts (sum) | ~50 estimated (Atomic + Modeled-tests under sibling-rule) | ~30 (estimated) | 0 | 17+ |
157157
158-ripgrep's `workingSetFit` measures 54.00% (from the polyglot §5 emitter at [`scripts/measure-working-set.ts`](/GIT/syntaxai/tdd.md/blob/main/scripts/measure-working-set.ts), inclusive bounds [50, 500] LOC). The distribution: **100 .rs files** total, **16 under 50 LOC**, **54 in band**, **30 over 500 LOC** — appreciably more than the "19 big files" I eyeballed in the original audit. The over-cap list ranges from the textbook declarative-exempt catalog (`crates/core/flags/defs.rs` at 7,780 LOC) down to genuinely borderline files at 500–800 LOC like `crates/pcre2/src/matcher.rs` (506) and `crates/cli/src/decompress.rs` (533).
158+ripgrep's `workingSetFit` measures 54.00% (from the polyglot §5 emitter at [`scripts/measure-working-set.ts`](/GIT/tdd.md/blob/main/scripts/measure-working-set.ts), inclusive bounds [50, 500] LOC). The distribution: **100 .rs files** total, **16 under 50 LOC**, **54 in band**, **30 over 500 LOC** — appreciably more than the "19 big files" I eyeballed in the original audit. The over-cap list ranges from the textbook declarative-exempt catalog (`crates/core/flags/defs.rs` at 7,780 LOC) down to genuinely borderline files at 500–800 LOC like `crates/pcre2/src/matcher.rs` (506) and `crates/cli/src/decompress.rs` (533).
159159
160160 **And yet most of those files are appropriate to their content.** workingSetFit by itself doesn't say which side of the line each file falls on — that's what the [declarative-exemption dialect](/sama/v2#63-declarative-exemption-dialect) is for. The metric surfaces the property; the policy decides what to do with it.
161161
@@ -165,7 +165,7 @@ This is exactly the §5 intent. The metric surfaces a property; whether that pro
165165
166166 ### graphDepth, measured: 5 (originally estimated ~5 — confirmed exactly)
167167
168-The polyglot graphDepth emitter at [`scripts/measure-graph-depth.ts`](/GIT/syntaxai/tdd.md/blob/main/scripts/measure-graph-depth.ts) reads `ripgrep`'s root [`Cargo.toml`](https://github.com/BurntSushi/ripgrep/blob/4519153e5e461527f4bca45b042fff45c4ec6fb9/Cargo.toml), identifies workspace members + the root crate, parses each member's `[dependencies]` section (production deps only — `[dev-dependencies]` excluded from the runtime DAG), filters to workspace-internal deps (`path = "../foo"` or `workspace = true` cross-referenced against `[workspace.dependencies]`), and computes the longest crate-level chain. The result for `ripgrep@4519153e`: **10 workspace crates, 15 internal edges, longest dependency chain of depth 5**.
168+The polyglot graphDepth emitter at [`scripts/measure-graph-depth.ts`](/GIT/tdd.md/blob/main/scripts/measure-graph-depth.ts) reads `ripgrep`'s root [`Cargo.toml`](https://github.com/BurntSushi/ripgrep/blob/4519153e5e461527f4bca45b042fff45c4ec6fb9/Cargo.toml), identifies workspace members + the root crate, parses each member's `[dependencies]` section (production deps only — `[dev-dependencies]` excluded from the runtime DAG), filters to workspace-internal deps (`path = "../foo"` or `workspace = true` cross-referenced against `[workspace.dependencies]`), and computes the longest crate-level chain. The result for `ripgrep@4519153e`: **10 workspace crates, 15 internal edges, longest dependency chain of depth 5**.
169169
170170 **Hand-trace** (auditable per [/sama/v2 §0](/sama/v2)). The 10 workspace crates and their internal edges, extracted from `crates/*/Cargo.toml`:
171171
@@ -186,7 +186,7 @@ The polyglot graphDepth emitter at [`scripts/measure-graph-depth.ts`](/GIT/synta
186186
187187 The longest path: **`ripgrep → grep → grep-printer → grep-searcher → grep-matcher`** — five crates, depth 5. Multiple paths reach depth 5 (e.g. `ripgrep → grep → grep-pcre2 → grep-matcher` is only depth 4; `ripgrep → grep → grep-searcher → grep-matcher` is depth 4; the printer-via-searcher chain is what wins). The audit's original estimate "(matcher → engine → searcher → printer → core)" turns out to describe the same chain reading bottom-up: `matcher ← searcher ← printer ← grep ← ripgrep`. Same five nodes, same depth, confirmed by measurement.
188188
189-Module-granularity note: the polyglot graphDepth metric counts at the Rust crate level — each Cargo workspace member is one node. This is the natural Rust analog to the TS file-level metric (TS one module ≈ one file; Rust one module ≈ one crate). Semantic documented in [`src/b32_graph_depth_polyglot.ts`](/GIT/syntaxai/tdd.md/blob/main/src/b32_graph_depth_polyglot.ts).
189+Module-granularity note: the polyglot graphDepth metric counts at the Rust crate level — each Cargo workspace member is one node. This is the natural Rust analog to the TS file-level metric (TS one module ≈ one file; Rust one module ≈ one crate). Semantic documented in [`src/b32_graph_depth_polyglot.ts`](/GIT/tdd.md/blob/main/src/b32_graph_depth_polyglot.ts).
190190
191191 The contrast with `dive`'s measured depth 12 is itself interesting: ripgrep's crate-level graph is *flatter* than dive's package-directory graph, even though both are mature CLI codebases. Some of that is genuine — ripgrep's workspace is 10 crates organized as a clean DAG; dive's 27 package directories include many subdirectory hops that drive the chain longer. Some is granularity: a Rust crate often contains what a Go developer would split into multiple package directories. The two depths aren't directly comparable for "which codebase is deeper"; they ARE directly comparable as "graphDepth at each language's natural module unit," which is the spec's intent.
192192
modified content/blog/sama-v2-sitemap-implementation-plan.md +3 −3
@@ -4,7 +4,7 @@ This site has 23 blog posts, 4 SAMA discipline pages, a `/sama/v2` spec, a verif
44
55 This post is the **implementation plan** for `/sitemap.xml`, written *before* the code lands. The plan itself uses two artifacts worth pointing at:
66
7-1. **The `/goal` slash command in Claude Code.** The 38-line spec I'm working from is checked in at [`goal.md`](/GIT/syntaxai/tdd.md/blob/main/goal.md) — that's the exact `/goal` text fed to the agent. It declares *Done when*, *Constraints (anti-fudge)*, and *Load-bearing files to read FIRST*. The agent has to read those files before writing any code, and it has to satisfy every *Done when* clause before declaring done.
7+1. **The `/goal` slash command in Claude Code.** The 38-line spec I'm working from is checked in at [`goal.md`](/GIT/tdd.md/blob/main/goal.md) — that's the exact `/goal` text fed to the agent. It declares *Done when*, *Constraints (anti-fudge)*, and *Load-bearing files to read FIRST*. The agent has to read those files before writing any code, and it has to satisfy every *Done when* clause before declaring done.
88 2. **SAMA v2 itself.** The feature has to land conformant — `/sama/v2/verify` reports 7/7 ✓ on the live site, and breaking it on the way in is what the verifier catches. Every architectural decision below traces to a §4 check.
99
1010 The combination is what this post is really about. The `/goal` is the *what*; SAMA v2 is the *how*; the verifier is the *anti-fudge gate*. Each constrains the other in a way that turns "add a feature" into a mechanical exercise.
@@ -57,7 +57,7 @@ Load-bearing files to read FIRST: …
5757
5858 The shape is what makes it useful. *Goal* is the human-readable intent. *Done when* is a checklist the agent will be evaluated against — and "all tests pass" is one bullet among many, not the only one. *Constraints* are the things the agent might be tempted to short-circuit (in this case: "URLs MUST come from existing registries — no second source of truth that can drift"). *Load-bearing files to read FIRST* prevents the agent from inventing structure that already exists — every existing helper, registry, and pattern is one Read tool call away, but only if the agent is told to look.
5959
60-The full text of this feature's `/goal` is in [`goal.md`](/GIT/syntaxai/tdd.md/blob/main/goal.md). Cherry-picking the most load-bearing bullets:
60+The full text of this feature's `/goal` is in [`goal.md`](/GIT/tdd.md/blob/main/goal.md). Cherry-picking the most load-bearing bullets:
6161
6262 - *"URLs are derived from the registries (no hand-maintained slug list)"* — fixes the source-of-truth violation that would otherwise emerge over time.
6363 - *"Sibling test covers: empty list → valid urlset with no `<url>` children; single URL with lastmod; single URL without lastmod; multiple URLs preserve order; XML-escape any `&` or `<` in URLs"* — fixes the Modeled-tests check (§4.3) before it gets a chance to fail.
@@ -80,7 +80,7 @@ Each of the seven [§4 conformance checks](/sama/v2#4-conformance) applies. The
8080 | §4.6 The Law (§1.2) | d21 → b32 → a31. Strictly downward. No upward edge — the helper doesn't know what the handler does with its output. |
8181 | §4.7 Consistency | The `b32_` prefix matches what the file actually contains: Layer 1 pure logic. No misnamed file, no logic at the wrong layer. |
8282
83-That table isn't decorative. It's what the agent's `Done when` bullet *"`/sama/v2/verify` still reports 7/7 ✓"* expands into when run against the live site. Each row corresponds to one line in [`b32_sama_v2_verify.ts`](/GIT/syntaxai/tdd.md/blob/main/src/b32_sama_v2_verify.ts) that the agent doesn't get to touch.
83+That table isn't decorative. It's what the agent's `Done when` bullet *"`/sama/v2/verify` still reports 7/7 ✓"* expands into when run against the live site. Each row corresponds to one line in [`b32_sama_v2_verify.ts`](/GIT/tdd.md/blob/main/src/b32_sama_v2_verify.ts) that the agent doesn't get to touch.
8484
8585 ## Anti-fudge — the things this plan deliberately does NOT do
8686
modified content/blog/sama-v2-workingset-cross-repo-baseline.md +1 −1
@@ -24,7 +24,7 @@ Corpus criteria: each project is a CLI tool, widely used (10k+ stars), mature (5
2424
2525 ## Methodology
2626
27-The [polyglot §5 emitter](/GIT/syntaxai/tdd.md/blob/main/scripts/measure-working-set.ts) at `scripts/measure-working-set.ts` was used unchanged. The bounds **[50, 500] LOC inclusive** are imported from `WORKING_SET_MIN_LOC` and `WORKING_SET_MAX_LOC` in [`src/a31_sama_v2.ts`](/GIT/syntaxai/tdd.md/blob/main/src/a31_sama_v2.ts) — the same constants the `/sama/v2/verify` page uses against this site's own source. Single source of truth: the cross-repo numbers are computed against the *exact* band the spec defines.
27+The [polyglot §5 emitter](/GIT/tdd.md/blob/main/scripts/measure-working-set.ts) at `scripts/measure-working-set.ts` was used unchanged. The bounds **[50, 500] LOC inclusive** are imported from `WORKING_SET_MIN_LOC` and `WORKING_SET_MAX_LOC` in [`src/a31_sama_v2.ts`](/GIT/tdd.md/blob/main/src/a31_sama_v2.ts) — the same constants the `/sama/v2/verify` page uses against this site's own source. Single source of truth: the cross-repo numbers are computed against the *exact* band the spec defines.
2828
2929 LOC for each file = `content.split("\n").length`, matching the TS reference implementation byte-for-byte. Test-file exclusion rule: Go excludes `*_test.go` (mirroring TS's `*.test.ts` exclusion); Rust includes all `.rs` files because Rust's convention is inline `#[cfg(test)] mod tests` — formalised at [/sama/v2 §6.2 inline-tests dialect](/sama/v2#62-inline-tests-dialect). Skipped directories: `.git/`, `target/`, `vendor/`, `node_modules/`, all dotdirs.
3030
modified content/home.md +1 −1
@@ -58,7 +58,7 @@ SAMA bundles those findings into four constraints a CI job can enforce. *Sorted*
5858
5959 ## Datapoints on the same axes
6060
61-Empirical baseline so far. The §4 score for this site is [computed live](/sama/v2/verify); the §4 scores for the other repos are hand-estimated. The **workingSetFit** column is now measured for the SAMA dogfood (this site) and seven non-SAMA mature compiled-language CLI tools by the polyglot §5 emitter at [`scripts/measure-working-set.ts`](/GIT/syntaxai/tdd.md/blob/main/scripts/measure-working-set.ts) — see the [seven-datapoint baseline post](/blog/sama-v2-workingset-cross-repo-baseline) for the full table, distribution, and hand-trace.
61+Empirical baseline so far. The §4 score for this site is [computed live](/sama/v2/verify); the §4 scores for the other repos are hand-estimated. The **workingSetFit** column is now measured for the SAMA dogfood (this site) and seven non-SAMA mature compiled-language CLI tools by the polyglot §5 emitter at [`scripts/measure-working-set.ts`](/GIT/tdd.md/blob/main/scripts/measure-working-set.ts) — see the [seven-datapoint baseline post](/blog/sama-v2-workingset-cross-repo-baseline) for the full table, distribution, and hand-trace.
6262
6363 | project | language | §4 score | workingSetFit | boundaryRatio | graphDepth |
6464 |---|---|---|---|---|---|
modified content/sama/v2.md +2 −2
@@ -157,7 +157,7 @@ This subsection pins how the §5 metrics are computed by the verifier at [/sama/
157157 - **Upper 500** — comfortably below the §4.5 Atomic 700-LOC cap, leaving headroom before a file approaches "split soon" territory.
158158 - **Lower 50** — below this, a file is too small to be a substantive module; it is usually a type-only file, a stub, or a single helper that would read better inlined into a sibling. Type-only files (Layer 0 model shards) and minimal test fixtures fall here by design. They are acceptable but counted as "not in the working-set sweet spot" because they are not load-bearing modules.
159159
160- Bounds are hard-coded constants `WORKING_SET_MIN_LOC = 50` and `WORKING_SET_MAX_LOC = 500` in [`src/a31_sama_v2.ts`](/GIT/syntaxai/tdd.md/blob/main/src/a31_sama_v2.ts) for v1 of the metrics emitter. Making them profile-configurable is a deliberate later step (requires extending the TOML subset parser to handle integer values).
160+ Bounds are hard-coded constants `WORKING_SET_MIN_LOC = 50` and `WORKING_SET_MAX_LOC = 500` in [`src/a31_sama_v2.ts`](/GIT/tdd.md/blob/main/src/a31_sama_v2.ts) for v1 of the metrics emitter. Making them profile-configurable is a deliberate later step (requires extending the TOML subset parser to handle integer values).
161161
162162 - **violationCounts** = a record keyed by the seven §4 checks (`sorted`, `architecture`, `modeledTests`, `modeledBoundary`, `atomic`, `law`, `consistency`), each holding the integer count of violations that check produced on this run. Reported even when a check passes (value = 0) — this is §5's "trailing signal: which rules agents *almost* break." The verifier enumerates **all** violations per check (no short-circuit on first failure within a check), so the count is meaningful — not "1 if failed, 0 if passed".
163163
@@ -179,7 +179,7 @@ A raw grep across non-test `src/*.ts` finds seven hits matching `JSON.parse(` an
179179
180180 Total: 7 parse-boundary call sites; all 7 fall under prefixes the profile maps to Layer 2.
181181
182-`boundaryRatio = 7 / 7 = 1.0 = 100.0%` — which is exactly what [/sama/v2/verify](/sama/v2/verify) reports under §5 Core metrics. The hand count and the verifier's count match by construction: both consume `findParseBoundaryCallSites` in [`src/a31_sama_v2.ts`](/GIT/syntaxai/tdd.md/blob/main/src/a31_sama_v2.ts), and the Modeled-boundary check (#4) uses the same source of truth — so it cannot diverge.
182+`boundaryRatio = 7 / 7 = 1.0 = 100.0%` — which is exactly what [/sama/v2/verify](/sama/v2/verify) reports under §5 Core metrics. The hand count and the verifier's count match by construction: both consume `findParseBoundaryCallSites` in [`src/a31_sama_v2.ts`](/GIT/tdd.md/blob/main/src/a31_sama_v2.ts), and the Modeled-boundary check (#4) uses the same source of truth — so it cannot diverge.
183183
184184 ---
185185
added src/b32_git_url_redirect.test.ts +54 −0
@@ -0,0 +1,54 @@
1+import { describe, expect, test } from "bun:test";
2+import { rewriteOldGitUrl } from "./b32_git_url_redirect.ts";
3+
4+describe("rewriteOldGitUrl", () => {
5+ test("rewrites old-form blob URL", () => {
6+ expect(
7+ rewriteOldGitUrl(
8+ "/GIT/syntaxai/tdd.md/blob/main/src/b32_sama_v2_verify.ts",
9+ ),
10+ ).toBe("/GIT/tdd.md/blob/main/src/b32_sama_v2_verify.ts");
11+ });
12+
13+ test("rewrites old-form tree URL", () => {
14+ expect(rewriteOldGitUrl("/GIT/syntaxai/tdd.md/tree/main")).toBe(
15+ "/GIT/tdd.md/tree/main",
16+ );
17+ });
18+
19+ test("rewrites old-form raw URL", () => {
20+ expect(
21+ rewriteOldGitUrl("/GIT/syntaxai/tdd.md/raw/main/sama.profile.toml"),
22+ ).toBe("/GIT/tdd.md/raw/main/sama.profile.toml");
23+ });
24+
25+ test("rewrites old-form commit URL", () => {
26+ expect(
27+ rewriteOldGitUrl("/GIT/syntaxai/tdd.md/commit/abc1234"),
28+ ).toBe("/GIT/tdd.md/commit/abc1234");
29+ });
30+
31+ test("rewrites old-form .diff URL (sha trailing .diff)", () => {
32+ expect(
33+ rewriteOldGitUrl("/GIT/syntaxai/tdd.md/commit/abc1234.diff"),
34+ ).toBe("/GIT/tdd.md/commit/abc1234.diff");
35+ });
36+
37+ test("returns null for already-new URLs", () => {
38+ expect(rewriteOldGitUrl("/GIT/tdd.md/blob/main/x.ts")).toBe(null);
39+ });
40+
41+ test("returns null for other-org URLs", () => {
42+ expect(rewriteOldGitUrl("/GIT/otherorg/repo/blob/main/x.ts")).toBe(null);
43+ });
44+
45+ test("returns null for non-/GIT/ paths", () => {
46+ expect(rewriteOldGitUrl("/blog/some-post")).toBe(null);
47+ expect(rewriteOldGitUrl("/")).toBe(null);
48+ });
49+
50+ test("returns null for incomplete old-form (just /GIT/syntaxai/tdd.md)", () => {
51+ expect(rewriteOldGitUrl("/GIT/syntaxai/tdd.md")).toBe(null);
52+ expect(rewriteOldGitUrl("/GIT/syntaxai/tdd.md/")).toBe(null);
53+ });
54+});
added src/b32_git_url_redirect.ts +13 −0
@@ -0,0 +1,13 @@
1+// b32 — Layer 1 pure helper: rewrite the legacy
2+// /GIT/syntaxai/tdd.md/<suffix> URL shape to /GIT/tdd.md/<suffix>.
3+// Pure: takes a pathname string, returns the new pathname or null
4+// when the input doesn't match the legacy shape. Called by the
5+// fallback handler to emit a 301 before the browse handler runs.
6+
7+const OLD_GIT_URL_PATTERN = /^\/GIT\/syntaxai\/tdd\.md\/(.+)$/;
8+
9+export const rewriteOldGitUrl = (pathname: string): string | null => {
10+ const m = OLD_GIT_URL_PATTERN.exec(pathname);
11+ if (m === null) return null;
12+ return `/GIT/tdd.md/${m[1]}`;
13+};
modified src/b51_render_commit.ts +2 −2
@@ -89,7 +89,7 @@ export const renderCommitView = async (params: {
8989 const parentLinks = detail.parents.length === 0
9090 ? `<span class="commit-meta-empty">no parent (root commit)</span>`
9191 : detail.parents.map((p) =>
92- `<a class="commit-parent" href="/GIT/${escape(owner)}/${escape(repo)}/commit/${escape(p)}"><code>${escape(shortSha(p))}</code></a>`,
92+ `<a class="commit-parent" href="/GIT/${escape(repo)}/commit/${escape(p)}"><code>${escape(shortSha(p))}</code></a>`,
9393 ).join(" · ");
9494
9595 const totalAdded = diff.files.reduce((s, f) => s + f.added, 0);
@@ -113,7 +113,7 @@ export const renderCommitView = async (params: {
113113 ${filesSummary}
114114 ${diff.files.map(renderFile).join("")}
115115 <p class="commit-footer">
116- <a href="/GIT/${escape(owner)}/${escape(repo)}/commit/${escape(detail.sha)}.diff">raw .diff</a>
116+ <a href="/GIT/${escape(repo)}/commit/${escape(detail.sha)}.diff">raw .diff</a>
117117 </p>
118118 </main>`;
119119
modified src/b51_render_edit.ts +1 −1
@@ -24,7 +24,7 @@ const shortSha = (sha: string): string => sha.slice(0, 7);
2424 // renders it through tdd.md's chrome — visitor never leaves the main
2525 // domain.
2626 const tddCommitUrl = (sha: string): string =>
27- `/GIT/syntaxai/tdd.md/commit/${sha}`;
27+ `/GIT/tdd.md/commit/${sha}`;
2828
2929 // -------- /edit/:section/:slug — form for the admin --------
3030
modified src/b51_render_repo.test.ts +1 −1
@@ -1,5 +1,5 @@
11 // Sibling test for c51_render_repo.ts (Layer 1, render). End-to-end
2-// shape covered by /GIT/syntaxai/tdd.md/tree|blob/main e2e specs.
2+// shape covered by /GIT/tdd.md/tree|blob/main e2e specs.
33 // This pins the export surface.
44
55 import { describe, test, expect } from "bun:test";
modified src/b51_render_repo.ts +9 −9
@@ -1,5 +1,5 @@
11 // c51 — UI: tree listing + blob viewer for the local bare repo.
2-// Visited at /GIT/:owner/:repo/tree/:ref/<path> and /blob/:ref/<path>.
2+// Visited at /GIT/:repo/tree/:ref/<path> and /blob/:ref/<path>.
33 // Renders through tdd.md's chrome (renderPage with bodyHtml). Markdown
44 // blobs get parsed via marked; everything else is rendered as
55 // preformatted source.
@@ -20,8 +20,8 @@ const renderBreadcrumb = (params: {
2020 asBlob?: boolean;
2121 }): string => {
2222 const { owner, repo, ref, path, asBlob } = params;
23- const repoLink = `<a href="/GIT/${escape(owner)}/${escape(repo)}/tree/${escape(ref)}"><strong>${escape(owner)}/${escape(repo)}</strong></a>`;
24- const refLink = `<a class="commit-meta-pill" href="/GIT/${escape(owner)}/${escape(repo)}/tree/${escape(ref)}"><code>${escape(ref)}</code></a>`;
23+ const repoLink = `<a href="/GIT/${escape(repo)}/tree/${escape(ref)}"><strong>${escape(owner)}/${escape(repo)}</strong></a>`;
24+ const refLink = `<a class="commit-meta-pill" href="/GIT/${escape(repo)}/tree/${escape(ref)}"><code>${escape(ref)}</code></a>`;
2525 if (path === "") return `<p class="commit-breadcrumb">${repoLink} · ${refLink}</p>`;
2626
2727 const segments = path.split("/");
@@ -33,7 +33,7 @@ const renderBreadcrumb = (params: {
3333 // For tree view, every segment links to the tree at that depth.
3434 const isLastFile = asBlob && i === lastIdx;
3535 if (isLastFile) return `<code>${escape(seg)}</code>`;
36- return `<a href="/GIT/${escape(owner)}/${escape(repo)}/tree/${escape(ref)}/${escape(so_far)}"><code>${escape(seg)}</code></a>`;
36+ return `<a href="/GIT/${escape(repo)}/tree/${escape(ref)}/${escape(so_far)}"><code>${escape(seg)}</code></a>`;
3737 })
3838 .join(" / ");
3939 return `<p class="commit-breadcrumb">${repoLink} · ${refLink} · ${links}</p>`;
@@ -62,7 +62,7 @@ const renderTreeRow = (params: {
6262 entry.type === "commit" ? "🔗" : // submodule
6363 "📄";
6464 const kind = entry.type === "tree" ? "tree" : "blob";
65- const href = `/GIT/${escape(owner)}/${escape(repo)}/${kind}/${escape(ref)}/${escape(childPath)}`;
65+ const href = `/GIT/${escape(repo)}/${kind}/${escape(ref)}/${escape(childPath)}`;
6666 return `<tr class="repo-tree-row repo-tree-row-${entry.type}">
6767 <td class="repo-tree-icon">${icon}</td>
6868 <td class="repo-tree-name"><a href="${href}">${escape(entry.name)}</a></td>
@@ -84,8 +84,8 @@ export const renderRepoTree = async (params: {
8484 : (() => {
8585 const parentPath = path.includes("/") ? path.slice(0, path.lastIndexOf("/")) : "";
8686 const upHref = parentPath === ""
87- ? `/GIT/${escape(owner)}/${escape(repo)}/tree/${escape(ref)}`
88- : `/GIT/${escape(owner)}/${escape(repo)}/tree/${escape(ref)}/${escape(parentPath)}`;
87+ ? `/GIT/${escape(repo)}/tree/${escape(ref)}`
88+ : `/GIT/${escape(repo)}/tree/${escape(ref)}/${escape(parentPath)}`;
8989 return `<tr class="repo-tree-row repo-tree-row-up"><td class="repo-tree-icon">⬆</td><td class="repo-tree-name"><a href="${upHref}">..</a></td><td></td></tr>`;
9090 })();
9191 const rows = entries.length === 0
@@ -135,8 +135,8 @@ export const renderRepoBlob = async (params: {
135135 <code class="repo-blob-path">${escape(filename)}</code>
136136 <span class="repo-blob-meta">${content.split("\n").length} lines · ${content.length} bytes</span>
137137 <span class="repo-blob-actions">
138- <a href="/GIT/${escape(owner)}/${escape(repo)}/raw/${escape(ref)}/${escape(path)}">raw</a>
139- ${isMarkdown(path) ? `· <a href="/GIT/${escape(owner)}/${escape(repo)}/blob/${escape(ref)}/${escape(path)}?source=1">source</a>` : ""}
138+ <a href="/GIT/${escape(repo)}/raw/${escape(ref)}/${escape(path)}">raw</a>
139+ ${isMarkdown(path) ? `· <a href="/GIT/${escape(repo)}/blob/${escape(ref)}/${escape(path)}?source=1">source</a>` : ""}
140140 </span>
141141 </header>
142142 ${bodyHtml}
modified src/d21_app.ts +1 −1
@@ -483,7 +483,7 @@ ${rows}
483483 // SAMA-native commit view — Bun-rendered alternative to Forgejo's
484484 // /<owner>/<repo>/commit/<sha> page. The :sha param may carry a
485485 // trailing ".diff" which the handler handles inline.
486- "/GIT/:owner/:repo/commit/:sha": commitViewHandler,
486+ "/GIT/:repo/commit/:sha": commitViewHandler,
487487
488488 "/auth/github/start": (req) => startGithubOauth(req),
489489
modified src/d21_handlers_commit_view.ts +24 −20
@@ -1,13 +1,13 @@
11 // c21 — handler: SAMA-native commit view at
2-// GET /GIT/:owner/:repo/commit/:sha
2+// GET /GIT/:repo/commit/:sha
33 // and a raw-diff sibling at
4-// GET /GIT/:owner/:repo/commit/:sha.diff
4+// GET /GIT/:repo/commit/:sha.diff
55 //
66 // Composes c14 (Forgejo HTTP), c31 (diff parser), c51 (render). The
77 // route prefix is uppercase /GIT/ to make it visually distinct from
8-// the markdown content sections (/sama, /blog, /guides). Visitors who
9-// land on git.tdd.md are bounced here by the deploy-time tunnel rule
10-// (out of scope for this handler — handler just owns the rendering).
8+// the markdown content sections (/sama, /blog, /guides). Owner is
9+// implicit (single-tenant — LIVE_REPO_OWNER) and never appears in
10+// the URL surface.
1111
1212 import { renderNotFound, htmlResponse } from "./b51_render_layout.ts";
1313 import { getCommit, getCommitDiff } from "./c14_git.ts";
@@ -15,38 +15,37 @@ import { LIVE_REPO_OWNER, LIVE_REPO_NAME } from "./a31_site_config.ts";
1515 import { parseUnifiedDiff } from "./a31_diff_parse.ts";
1616 import { renderCommitView } from "./b51_render_commit.ts";
1717
18-// Owner/repo + sha shape — paranoid because these go straight into a
19-// Forgejo URL. Owner/repo allow letters/digits/hyphens/underscores/dots;
18+// Repo + sha shape — paranoid because these go straight into a
19+// Forgejo URL. Repo allows letters/digits/hyphens/underscores/dots;
2020 // sha is hex 7-64 (Forgejo accepts shortened SHAs but our render assumes
2121 // full ones because we use them in URLs).
2222 const SAFE_OWNER_REPO = /^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$/;
2323 const SAFE_SHA = /^[a-f0-9]{7,64}$/;
2424
25-const isValid = (owner: string, repo: string, sha: string): boolean =>
26- SAFE_OWNER_REPO.test(owner) && SAFE_OWNER_REPO.test(repo) && SAFE_SHA.test(sha);
25+const isValid = (repo: string, sha: string): boolean =>
26+ SAFE_OWNER_REPO.test(repo) && SAFE_SHA.test(sha);
2727
2828 export const commitViewHandler = async (
29- req: Request & { params: { owner: string; repo: string; sha: string } },
29+ req: Request & { params: { repo: string; sha: string } },
3030 ): Promise<Response> => {
31- const { owner, repo } = req.params;
31+ const { repo } = req.params;
3232 // The :sha param may carry a trailing ".diff" because the route
3333 // pattern doesn't have a separate one. Normalise + branch.
3434 const rawSha = req.params.sha;
3535 const wantsDiff = rawSha.endsWith(".diff");
3636 const sha = wantsDiff ? rawSha.slice(0, -5) : rawSha;
37- const fullPath = `/GIT/${owner}/${repo}/commit/${rawSha}`;
37+ const fullPath = `/GIT/${repo}/commit/${rawSha}`;
3838
39- if (!isValid(owner, repo, sha)) {
39+ if (!isValid(repo, sha)) {
4040 const html = await renderNotFound(fullPath);
4141 return htmlResponse(html, 404);
4242 }
4343
44- // /GIT/ now serves only syntaxai/tdd.md (our local bare repo via
45- // c14_git). Other (owner, repo) pairs would historically have been
46- // proxied to Forgejo for agent katas — that's a separate concern
47- // and currently 404s. If we want it back, add a Forgejo fallback
48- // branch here keyed on the owner/repo pair.
49- if (owner !== LIVE_REPO_OWNER || repo !== LIVE_REPO_NAME) {
44+ // /GIT/ now serves only the local bare repo (LIVE_REPO_NAME via
45+ // c14_git). Other repos would historically have been proxied to
46+ // Forgejo for agent katas — that's a separate concern and
47+ // currently 404s.
48+ if (repo !== LIVE_REPO_NAME) {
5049 const html = await renderNotFound(fullPath);
5150 return htmlResponse(html, 404);
5251 }
@@ -85,6 +84,11 @@ export const commitViewHandler = async (
8584 committerDate: commit.committerDate,
8685 message: commit.message,
8786 };
88- const html = await renderCommitView({ owner, repo, detail, diff });
87+ const html = await renderCommitView({
88+ owner: LIVE_REPO_OWNER,
89+ repo,
90+ detail,
91+ diff,
92+ });
8993 return htmlResponse(html);
9094 };
modified src/d21_handlers_fallback.ts +21 −6
@@ -22,6 +22,7 @@ import {
2222 parseRepoBrowsePath,
2323 repoBrowseHandler,
2424 } from "./d21_handlers_repo_browse.ts";
25+import { rewriteOldGitUrl } from "./b32_git_url_redirect.ts";
2526
2627 const isGitProtocol = (pathname: string, search: URLSearchParams): boolean => {
2728 if (pathname.includes(".git/") || pathname.endsWith(".git")) return true;
@@ -122,22 +123,36 @@ export const appFetch = async (req: Request): Promise<Response> => {
122123 });
123124 }
124125
125- // SAMA-native repo browse at /GIT/:owner/:repo/{tree,blob,raw}/:ref/<path>.
126+ // Legacy /GIT/syntaxai/tdd.md/<suffix> URLs permanent-redirect to
127+ // the new owner-less shape. MUST sit before the browse-match below
128+ // so the legacy URL never reaches the browse handler. One regex
129+ // covers every kind (tree/blob/raw/commit) + every future path.
130+ const newGitPath = rewriteOldGitUrl(url.pathname);
131+ if (newGitPath !== null) {
132+ return new Response(null, {
133+ status: 301,
134+ headers: {
135+ Location: newGitPath,
136+ "Cache-Control": "public, max-age=86400",
137+ },
138+ });
139+ }
140+
141+ // SAMA-native repo browse at /GIT/:repo/{tree,blob,raw}/:ref/<path>.
126142 // The wildcard path needs more flexibility than Bun's :param routes
127143 // give us (no slashes), so we match in the fallback fetch instead.
128144 const gitBrowseMatch = url.pathname.match(
129- /^\/GIT\/([A-Za-z0-9][A-Za-z0-9._-]+)\/([A-Za-z0-9][A-Za-z0-9._-]+)\/(.+)$/,
145+ /^\/GIT\/([A-Za-z0-9][A-Za-z0-9._-]+)\/(.+)$/,
130146 );
131147 if (gitBrowseMatch) {
132- const owner = gitBrowseMatch[1]!;
133- const repo = gitBrowseMatch[2]!;
134- const suffix = gitBrowseMatch[3]!;
148+ const repo = gitBrowseMatch[1]!;
149+ const suffix = gitBrowseMatch[2]!;
135150 // Skip the commit/<sha> shape — that's c21_handlers_commit_view's
136151 // turf and lives as an explicit Bun.serve route in c21_app.
137152 if (!suffix.startsWith("commit/")) {
138153 const target = parseRepoBrowsePath(suffix);
139154 if (target !== null) {
140- return repoBrowseHandler(req, owner, repo, target);
155+ return repoBrowseHandler(req, repo, target);
141156 }
142157 }
143158 }
modified src/d21_handlers_repo_browse.ts +8 −10
@@ -23,11 +23,10 @@ const SAFE_OWNER_REPO = /^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$/;
2323 // would clash with the wildcard path matching).
2424 const SAFE_REF = /^[A-Za-z0-9][A-Za-z0-9._-]{0,49}$/;
2525
26-const isAllowedRepo = (owner: string, repo: string): boolean =>
27- owner === LIVE_REPO_OWNER &&
28- repo === LIVE_REPO_NAME &&
29- SAFE_OWNER_REPO.test(owner) &&
30- SAFE_OWNER_REPO.test(repo);
26+// Single-tenant: the only allowed repo is LIVE_REPO_NAME. Owner is
27+// implicit (LIVE_REPO_OWNER) and no longer carried in the URL.
28+const isAllowedRepo = (repo: string): boolean =>
29+ repo === LIVE_REPO_NAME && SAFE_OWNER_REPO.test(repo);
3130
3231 // Only allow paths that look like ordinary repo entries — letters,
3332 // digits, hyphens, underscores, dots, slashes. Reject anything with
@@ -68,13 +67,12 @@ export const parseRepoBrowsePath = (suffix: string): RepoBrowseTarget | null =>
6867
6968 export const repoBrowseHandler = async (
7069 req: Request,
71- owner: string,
7270 repo: string,
7371 target: RepoBrowseTarget,
7472 ): Promise<Response> => {
75- const fullPath = `/GIT/${owner}/${repo}/${target.kind}/${target.ref}${target.path ? "/" + target.path : ""}`;
73+ const fullPath = `/GIT/${repo}/${target.kind}/${target.ref}${target.path ? "/" + target.path : ""}`;
7674
77- if (!isAllowedRepo(owner, repo)) {
75+ if (!isAllowedRepo(repo)) {
7876 const html = await renderNotFound(fullPath);
7977 return htmlResponse(html, 404);
8078 }
@@ -86,7 +84,7 @@ export const repoBrowseHandler = async (
8684 return htmlResponse(html, 404);
8785 }
8886 const html = await renderRepoTree({
89- owner,
87+ owner: LIVE_REPO_OWNER,
9088 repo,
9189 ref: target.ref,
9290 path: target.path,
@@ -102,7 +100,7 @@ export const repoBrowseHandler = async (
102100 return htmlResponse(html, 404);
103101 }
104102 const html = await renderRepoBlob({
105- owner,
103+ owner: LIVE_REPO_OWNER,
106104 repo,
107105 ref: target.ref,
108106 path: target.path,
modified src/d21_handlers_sama.ts +1 −1
@@ -134,7 +134,7 @@ const renderV2Report = (report: SamaV2Report, metrics: SamaV2Metrics): string =>
134134
135135 > ${summary}
136136
137-The verifier in [\`src/b32_sama_v2_verify.ts\`](/GIT/syntaxai/tdd.md/blob/main/src/b32_sama_v2_verify.ts) ingests [\`sama.profile.toml\`](/GIT/syntaxai/tdd.md/blob/main/sama.profile.toml) and runs the seven §4 conformance checks against the current source tree on this server. No clone, no token; the server reads its own \`src/\` and the committed profile, runs the same logic the sibling unit tests cover, and renders the verdict below. The §5 core metrics emitter ([\`src/b32_sama_v2_metrics.ts\`](/GIT/syntaxai/tdd.md/blob/main/src/b32_sama_v2_metrics.ts)) runs on the same input and shares the parse-boundary detector with the Modeled-boundary check.
137+The verifier in [\`src/b32_sama_v2_verify.ts\`](/GIT/tdd.md/blob/main/src/b32_sama_v2_verify.ts) ingests [\`sama.profile.toml\`](/GIT/tdd.md/blob/main/sama.profile.toml) and runs the seven §4 conformance checks against the current source tree on this server. No clone, no token; the server reads its own \`src/\` and the committed profile, runs the same logic the sibling unit tests cover, and renders the verdict below. The §5 core metrics emitter ([\`src/b32_sama_v2_metrics.ts\`](/GIT/tdd.md/blob/main/src/b32_sama_v2_metrics.ts)) runs on the same input and shares the parse-boundary detector with the Modeled-boundary check.
138138
139139 | check | verdict | examined |
140140 |---|---|---|