1d22b1863885e7b119cdd614feff6bd67f50b297 diff --git a/content/blog/sama-v2-second-url-refactor-postmortem.md b/content/blog/sama-v2-second-url-refactor-postmortem.md new file mode 100644 index 0000000000000000000000000000000000000000..d96592e390aa3c96a87d9e67614900d71b051b37 --- /dev/null +++ b/content/blog/sama-v2-second-url-refactor-postmortem.md @@ -0,0 +1,91 @@ +# 8 minutes 8 seconds — the cost-flattening hypothesis is confirmed + +The [git-url-refactor postmortem](/blog/sama-v2-git-url-refactor-postmortem) closed with a single falsifiable claim: + +> *"If the second URL refactor — when it happens — lands in ~an hour, that's the data point. If it takes another evening, the pattern wasn't as portable as it looked. Either result is informative."* + +The second URL refactor happened today. It landed in **8 minutes and 8 seconds**. + +``` +T+00:00:00 git checkout -b sama-discipline-prefix (first commit) +T+00:00:30 goals/sama-discipline-prefix.md written (dogfooded /goal) +T+00:01:45 b32_sama_discipline_url_redirect.ts + test (copy of git template) +T+00:02:30 d21_handlers_fallback.ts redirect block (paste alongside existing) +T+00:02:50 d21_app.ts Bun route + sitemap handler (one edit each) +T+00:04:00 sed pass over 13 content + src files (one regex) +T+00:04:20 one sed over-rewrite caught + fixed (test failed, 30s to revert) +T+00:05:10 419/419 tests green (+12 new helper cases) +T+00:06:30 commit, push, gh pr create, gh pr merge (the GitHub-flow) +T+00:07:30 deploy script ran (rebuild + restart container) +T+00:08:08 /healthz answered, live-verify passed (all 4 new URLs 200, all 4 old URLs 301) +``` + +7.4× faster than predicted. Cost-flattening confirmed at a much more dramatic rate than the original hypothesis dared. + +![Cost-flattening hypothesis confirmed — 8m 8s vs 1h predicted](/images/cost-flattening-confirmed.png?v=1) + +## What the prediction got right + +The original postmortem named three things the pattern would carry through: + +- A 5-line Layer-1 helper with one regex +- A sibling test covering all match-cases + non-match-cases +- A Layer-3 wrapper that emits the 301 + +All three landed identically in PR #53. The helper is **13 lines** in both PRs (same code modulo identifier renaming). The Layer-3 wrapper is the **same 11 lines** in both fallback handlers, literally copy-pasted from the rewriteOldGitUrl block to the new rewriteOldSamaDisciplineUrl block. The sibling test grew from 9 cases to 12 — slightly more because the new pattern has more non-match neighbours (`/sama/v2`, `/sama/skill`, the new-form URLs) that needed explicit `null`-return tests. + +## What the prediction missed — pattern risk + +One surprise: the sed pass over-rewrote. + +The pattern `s|/sama/(sorted|architecture|modeled|atomic)|/sama/discipline/\1|g` matched **inside filesystem paths** like `content/sama/sorted.md` — turning them into the nonsensical `content/sama/discipline/sorted.md` (the directory `content/sama/discipline/` doesn't exist; the file is at `content/sama/sorted.md`). + +This bug surfaced via a test — `b32_edit_resolve.test.ts` failed when its expected `filePath: "content/sama/sorted.md"` got rewritten to `content/sama/discipline/sorted.md`. The pattern caught it in seconds, and reverting was one Edit. But it's a genuine new failure mode the first refactor didn't have, because git-url-drop-owner's regex was `/GIT/syntaxai/tdd.md/` — three segments long, far less likely to collide with filesystem paths. + +**Pattern risk added to the recipe**: when generating a sed for a URL refactor, prefer anchoring (`href="..."`, `[link](...)`) or use a more restrictive character class. The 30-second revert was cheap *this time* because a test caught it. In a refactor with no covering test, the over-rewrite would have landed silently. + +The /goal that follows the third URL refactor should include this lesson explicitly as an anti-fudge clause. + +## What lands when this pattern keeps repeating + +PR #42 took an evening. PR #53 took 8 minutes. Two datapoints isn't a trend, but it's not nothing: **the cost is dropping faster than linear.** + +The mechanism is mundane. The first time: +- You design the helper shape (`SitemapUrl`-like type, `rewrite*` function name, `null`-vs-string return for non-match) +- You design the test shape (match-all-kinds, non-match-cases, edge cases like empty input) +- You design the Layer-3 wrapper shape (Response with 301, Location header, Cache-Control) +- You discover the gotchas (regex order in the fallback, sed scope, Containerfile gotcha, breadcrumb cross-references) + +The second time, all of that is done. You **import the template, change the slug, paste**. The first refactor's 19 files become the second refactor's 17 files because the helper + test are now reuseable structure, not new design. + +The third refactor — whichever one we pick — should land in similar time *unless* the cost-flattening hits a floor at the irreducible-minimum of "type the new slugs + sed". My guess: 5–10 minutes for any future URL move, dominated by deploy time (~50s per deploy) and gh-CLI roundtrips. + +## What about /blog/<slug> → /blog/<yyyy-mm>/<slug>? + +This was the third candidate in the postmortem. It's much bigger — ~27 blog posts × N cross-links each = probably 100+ references. The helper pattern would still work, but the sed-pass scope explodes, and the new URL needs to be computed *from data* (the post's `date` field), not from a fixed enum. + +Prediction for that one: not 8 minutes. Probably 20–30 minutes, because: +- Helper signature changes (must accept date AND slug, lookup the date from ALL_POSTS by slug) +- Sed pass over content/*.md is sketchier (more risk of over-rewrite) +- Sitemap handler needs the new URL shape, but the redirect needs the old-shape regex AND a way to know each post's date + +The cost-flattening claim holds *for refactors of the same shape*. When the input expands (fixed enum → data-driven), the helper has to grow. That's a falsifiable distinction worth testing next. + +## The empirical chain ratchets + +[`/blog/sama-v2-goal-chain-gap`](/blog/sama-v2-goal-chain-gap) said *every artifact is auditable*. Now: the *time-cost* of each kind of refactor is auditable too. The git-url postmortem published a 1-hour prediction. This post publishes the 8-minute measurement against it. Both timestamps are in git, both /goals are at [`/goals`](/goals), both PRs link back to their plan posts. + +Anyone reading [/blog/sama-v2-on-ramp-gap](/blog/sama-v2-on-ramp-gap) wondering *"is this discipline actually faster than the alternative, or is it just talk?"* now has one more data point. Two URL refactors under the same pattern, second one 7.4× faster. The claim is empirical now — not because of one measurement, but because of the **delta** between two. + +The §5 spec calls this *"compliance proves the rules were followed; the delta proves they were worth following."* That argument has been about cross-repo workingSetFit measurements until now. Today the same argument lands on wall-clock time. Pattern-as-redirect isn't a fashion; it's measurably cheaper the second time. + +## What's next on the empirical chain + +The natural next step is the third datapoint. Two falsifiable subclaims to test: + +1. **A same-shape refactor stays small.** Pick another fixed-enum URL move (e.g. `/sama/v2/example-crud` → `/sama/v2/examples/crud` and `/sama/v2/example-wordpress` → `/sama/v2/examples/wordpress`). Prediction: ≤ 8 minutes, possibly faster since 2 slugs vs 4. +2. **A data-shaped refactor stays under 30 minutes.** Pick `/blog/` → `/blog//`. Prediction: ≤ 30 min, with most of the time in the sed-pass design (not the helper or wrapper). + +If subclaim 1 lands under 8 minutes, cost-flattening hits its floor. If subclaim 2 lands over 30 minutes, the pattern's portability is bounded — *fixed-enum cheap, data-driven expensive* — and that boundary becomes the new empirical knowledge. + +Either outcome is the next blog post. The chain ratchets. diff --git a/goals/sama-discipline-prefix.md b/goals/sama-discipline-prefix.md index 0db28dcbe457ef7ac15b556f5988823f23653aab..4fc79e340b9907f6060ef6fc0764066e4a21670d 100644 --- a/goals/sama-discipline-prefix.md +++ b/goals/sama-discipline-prefix.md @@ -3,9 +3,9 @@ slug: sama-discipline-prefix title: Move /sama/ → /sama/discipline/ — hypothesis test of cost-flattening date: 2026-05-25 branch: sama-discipline-prefix -pr_number: null -merge_sha: null -status: pending +pr_number: 53 +merge_sha: f806580 +status: shipped related_posts: [sama-v2-git-url-refactor-postmortem] --- diff --git a/public/images/cost-flattening-confirmed.png b/public/images/cost-flattening-confirmed.png new file mode 100644 index 0000000000000000000000000000000000000000..256856ab73dc1f2bf0467917ee40416ccbf5d4d8 Binary files /dev/null and b/public/images/cost-flattening-confirmed.png differ diff --git a/public/images/cost-flattening-confirmed.svg b/public/images/cost-flattening-confirmed.svg new file mode 100644 index 0000000000000000000000000000000000000000..974c8cfb81efca993d587931f4fcc86b78752d43 --- /dev/null +++ b/public/images/cost-flattening-confirmed.svg @@ -0,0 +1,86 @@ + + + + + + Hypothesis test — cost-flattening of pattern-as-redirect + Predicted 1 hour. Landed in 8 minutes 8 seconds. + The git-url-refactor postmortem closed with a falsifiable claim. The second URL refactor measured it. 7.4× faster than predicted. + + + + + DIMENSION + PR #42 (FIRST) + PR #53 (HYPOTHESIS TEST) + VERDICT + + + + + + + wall-clock (commit → live) + an evening + 8 min 8 sec + ✓ confirmed + + files changed + 19 + 17 + comparable + + URL references rewritten + 49 + ~22 + smaller scope + + Layer-1 helper LOC + 13 + 13 + ✓ identical + + sibling-test cases + 9 + 12 + covered + + Layer-3 wrapper + 11 lines (Response + 301) + 11 lines (copy-paste) + ✓ identical + + sed-pass over-rewrites + 0 + 1 (caught + fixed in 30s) + ~ pattern risk + + verifier verdict before + 7/7 ✓ + 7/7 ✓ + stable + + verifier verdict after + 7/7 ✓ + 7/7 ✓ + stable + + test count delta + +9 (379 → 388) + +12 (407 → 419) + net positive + + + + + + Cost-flattening hypothesis: CONFIRMED — much more dramatically than predicted. + Predicted: 1 hour. Actual: 8m 8s. Ratio: 7.4× faster. The reusable shape (b32_<old>_url_redirect + sibling test + + Layer-3 wrapper) collapses the URL-refactor wall-clock from "evening's work" to "coffee break". Same number of + structural pieces; the cost of CONNECTING them was the bulk of the original effort, and that's now zero. + One small pattern-risk surfaced: sed pattern matched inside filesystem paths (content/sama/sorted.md), caught by a unit test. + + + + https://tdd.md + diff --git a/src/a31_blog.ts b/src/a31_blog.ts index 502736f598287d9e9cbfe99d8d1d417208f89433..2252fab4e994a1471e04f447b2ff004934fcd9fe 100644 --- a/src/a31_blog.ts +++ b/src/a31_blog.ts @@ -12,6 +12,12 @@ export interface BlogEntry { } export const ALL_POSTS: BlogEntry[] = [ + { + slug: "sama-v2-second-url-refactor-postmortem", + title: "8 minutes 8 seconds — the cost-flattening hypothesis is confirmed", + description: "The git-url-refactor postmortem closed with a single falsifiable claim: 'if the second URL refactor lands in ~1 hour, cost-flattening of pattern-as-redirect is confirmed; if it takes another evening, the pattern wasn't as portable as it looked. Either is informative.' The second URL refactor happened today (moving /sama/ → /sama/discipline/). It landed in 8 minutes 8 seconds — 7.4× faster than predicted. Cost-flattening confirmed, much more dramatically than the hypothesis dared. Timeline breakdown commit-by-commit shows where each minute went: 1m45s on the helper + test (copy of git template); 30s on the fallback handler; 1m10s on the sed pass; 30s recovering from one sed over-rewrite (regex matched inside filesystem paths content/sama/sorted.md, caught by an existing edit-resolve test); 2m20s on the gh PR flow + deploy. What the prediction got right: the 13-line helper, the 11-line Layer-3 wrapper, the sibling-test structure — all landed identically. What it missed: pattern risk (sed scope on shorter URL prefixes is more collision-prone; lesson added to anti-fudge for next time). Two datapoints isn't a trend, but the mechanism is mundane: the first refactor designs the shape; the second imports the template, changes the slug, pastes. Predicts that future fixed-enum URL refactors land in ~5-10 min (deploy-time dominated), while data-driven refactors like /blog/ → /blog// probably take ~20-30 min because the helper has to grow. The empirical chain ratchets: §5 has been about cross-repo workingSetFit deltas; this post lands wall-clock time as the same kind of measurement. 'Compliance proves the rules were followed; delta proves they were worth following' — that argument now applies to wall-clock time, not just file-fit ratios.", + date: "2026-05-25", + }, { slug: "sama-v2-on-ramp-gap", title: "Every artifact has a URL. The on-ramp doesn't.", diff --git a/src/a31_goals.ts b/src/a31_goals.ts index 703669855d909ddda15fa171473e72a327df991d..f0fa88f48011832f6c03a3a10f7440a7c540cd94 100644 --- a/src/a31_goals.ts +++ b/src/a31_goals.ts @@ -38,6 +38,16 @@ export interface GoalEntry { } export const ALL_GOALS: GoalEntry[] = [ + { + slug: "sama-discipline-prefix", + title: "Move /sama/ → /sama/discipline/ — hypothesis test", + date: "2026-05-25", + branch: "sama-discipline-prefix", + prNumber: 53, + mergeSha: "f806580", + status: "shipped", + relatedPosts: ["sama-v2-git-url-refactor-postmortem"], + }, { slug: "contributing-md", title: "Build CONTRIBUTING.md as the canonical on-ramp + drift-detection test",