feat(#297): harness templates by topology — TS NextJS / Python FastAPI / Go data pipeline#346
Conversation
…I / Go data pipeline
Ships v1 of `topologies/<name>/`, the path-mirrored bundle convention
adopters opt into via `/handover --topology <name>` to get a pre-curated
governance surface instead of reassembling it by hand on every onboarding.
What lands:
- **`topologies/typescript-nextjs/`, `topologies/python-fastapi/`,
`topologies/go-data-pipeline/`** — 3 starter shapes. Each ships
`VERSION`, `README.md`, curated `handbooks/{architecture,language,domain}/*.md`
(8-9 files each), a stack-appropriate `golden-paths/*.yml` CI pipeline,
and an `agdr-<stack>.md` template prompting stack-specific decisions.
- **`/handover` topology pick** — early-flow question after project
naming, defaults to "Skip / custom" (no behaviour change for adopters
who don't pick). On pick, instantiates the bundle into the project's
`handbooks/` + `.github/workflows/` + `docs/agdr/` (drafts, not
commits).
- **`/update` topology drift detection** — scans adopter-instantiated
bundles' VERSION against upstream framework's `topologies/<name>/VERSION`,
offers operator-approved per-file diff on drift. Default skip — manual sync.
- **AgDR-0048** — body-H1 only (no YAML frontmatter). Records the path-
mirroring vs frontmatter-registry vs config-block choice, the 3
starter-topology pick + Ashby's-Law variety-reduction rationale, the
VERSION-file drift detection (vs git-tag / hash comparison), the
early-flow `/handover` integration shape, and the v1 framework-curated-
only scope (adopter-authored topologies deferred to v2.1).
- **Smoke test** at `.claude/skills/handover/tests/test_topology_pick.sh` —
10 assertions covering bundle inventory (each topology has the 5
required axes), AgDR shape (body-H1 only, canonical "In the context of"
one-liner), and integration claims (`CLAUDE.md` + `/update` SKILL.md
mention topology).
- **CLAUDE.md** — adds one line to the QUICK REFERENCE table for
`topologies/`. Skill table unchanged (no new slash command — extends
existing `/handover` + `/update`).
Why this matters:
- Adopters today reassemble the same governance surface every project
onboarding — 6+ primitives wired up by hand each time. This is the
exact "reassembly fatigue" failure mode harness-engineering literature
flags.
- Committing to a topology also narrows the agent's output space
(Ashby's Law) — fewer valid actions = more achievable harness.
- v1 scope is deliberately narrow (3 framework-curated topologies, no
composition, no adopter-authored shapes) to ship something maintainable
rather than an unmaintainable registry of 50.
Closes #297
atlas-apex
left a comment
There was a problem hiding this comment.
Code Review: PR #346
Commit: ae7f982694876ed4f67fb51d4c6ac38988e5f9b6
Summary
P2/v2.0-candidate feature: ships topologies/<name>/ as a path-mirrored convention so adopters can opt into a pre-curated governance surface (handbooks + AgDR templates + CI pipeline + Rex domain knowledge) at /handover time instead of reassembling 6+ primitives by hand. v1 ships three categorically different starters — TypeScript NextJS, Python FastAPI, Go data pipeline — with /handover extended for early-flow topology pick (default-skip) and /update extended for VERSION-based drift detection. Total +3873/-1 across 42 files.
Checklist Results
- Architecture & Design: Pass
- Code Quality: Pass
- Testing: Pass
- Security: Pass
- Performance: Pass (advisory class — no runtime code)
- PR Description & Glossary: Pass (8 terms, narrative bullets)
- Technical Decisions (AgDR):Pass — AgDR-0048-topology-templates linked + comprehensive
- Adopter Handbooks: Pass —
architecture/clean-architecture-layers.md(always-load, advisory) + framework-internal handbooks would apply if relevant; no violations in the touched files
Issues Found
None blocking.
Suggestions (nits — non-blocking)
-
/updatedrift-detection prompt — per-file default phrasing is contradictory..claude/skills/update/SKILL.md§ 8c says "Default per file isn(skip — operator owns the change)" but the prompt shape immediately below shows[Y/n/d/s]with[Y]es — copy framework versionas the upper-case (canonical-default) option. Pick one: either flip the prompt to[y/N/d/s]to match the prose default, or update the prose to say "Default per file isY(copy framework version) — but the project-level default isN(skip the whole step)". The current shape will trip operators reading the prose vs reading the bracketed default. -
AgDR-0048 § Consequences off-by-one on handbook count. "The three v1 starter topologies ship with 9 handbooks total (3 architecture + 3 language + ~3-4 domain per topology — see file inventory in the PR)". The actual count is 8 per topology (2 architecture + 3 language + 3 domain) and 24 handbooks total. The parenthetical math (3+3+3=9) is right but the actual per-topology architecture count is 2, not 3 (go-data-pipeline ships
clean-architecture-layers.md+pipeline-stages.md; python-fastapi + typescript-nextjs each shipclean-architecture-layers.md+migration-safety.md). Cosmetic — doesn't affect any decision. -
AgDR-0048 minor wording — "see file inventory in the PR" is a backward reference to the originating PR. After merge, that pointer is stale. Consider phrasing it as "see each topology's README.md" (which lists the bundle contents).
Handbook Findings
None — the diff touches topologies/ (a new convention dir) + skill / AgDR / config files. None of those paths are covered by an existing public handbook's paths: glob, and there are no false-positives from the always-load architecture handbooks (this PR neither violates clean-architecture layering nor ships a migration).
Notable strengths
- AgDR-0048 quality is exemplary. Body-H1 only, canonical "In the context of..." one-liner present, six decisions (A through F) each with options + chosen + rationale. The Ashby's-Law variety-reduction framing is load-bearing for the WHY and clearly explained.
- Path-mirroring vs frontmatter / config-block / JSON manifest comparison (option A) clearly documents why the chosen layout wins — consistency with
handbooks/andcustom-templates/discovery conventions (AgDR-0023). - Handbooks are first-class. Each handbook follows the standard shape (rule → why → Rex flags → sample finding → NOT-a-violation → standard pattern). Security-critical handbooks (
migration-safety.mdfor Prisma + Alembic,jwt-validation.md,session-handling.md) correctly carry theENFORCEMENT: blockingmarker at the top. - Async-correctness handbook (python-fastapi) captures the load-bearing FastAPI gotchas — sync session inside async handler, missing
await,asyncio.runinside loop, fire-and-forget GC. The mixed-sync/async migration recipe is a real teaching moment. - Batch-size-tuning handbook (go-data-pipeline) is unusually concrete — explicit knob ranges, throughput math (Postgres COPY 200x faster, Kafka batched 500x faster), worked Go example with proper mutex + timer reset. Adopters get a real reference, not a generic platitude.
/handoverintegration is zero-regression by design. Default is "Skip / custom" (pick 4),--topology <name>CLI flag is a power-user override, instantiation step 5.5 usesrsync --ignore-existing/cp -nso adopters' edits are never overwritten. The.draft.mdextension on the seeded AgDR template avoids spurious AgDR-required hook firings./updatedrift detection is non-blocking + per-file (matches the deprecated-config-key offer's shape from AgDR-0032 and step 8b). Bulk replace was explicitly rejected for the right reason (adopters edit topology handbooks in-project).- Smoke test coverage is thorough. 10 logical assertion families × 3 topologies = ~40 individual assertions executed in the for-loop. Covers per-topology bundle inventory (VERSION/README/handbooks-by-axis/CI/template), AgDR-0048 shape (body-H1 + one-liner), CLAUDE.md integration,
/updateintegration, README cross-references, AND thepaths:frontmatter convention for every domain handbook. The semver regex^[0-9]+\.[0-9]+\.[0-9]+$rejects pre-release suffixes — fine for v1. - Wave 1 invariants preserved. Skill count unchanged at 53 (this extends
/handover+/update, no new slash command). New CLAUDE.md QUICK REFERENCE row is 12 words (cap is 25). Description frontmatter on extended skills not increased past the 200-char cap. Thetopologies/README.mdadds a fourth navigation surface (alongsidehandbooks/,templates/,golden-paths/) consistent with the framework's discovery-by-convention pattern. - MD032 fix-up at HEAD (
ae7f982) is one line (blank before list inbatch-size-tuning.md); markdownlint check is green at this SHA. No regression elsewhere. - CI all green at this SHA: Verify Ticket ID, lychee, markdownlint-cli2, site-counts drift detection.
- Forward-compatibility hooks documented. v2.1 expansion path (adopter-authored
<private_repo>/custom-topologies/<name>/) is explicit in AgDR-0048 § A's "Chosen" note and thetopologies/README.md"Out of scope" section. The 5+ adopter-request gate before adding a fourth starter topology is a sensible variety-management discipline.
Verdict
APPROVED
Ship it. The three nits above are documentation polish that can land in a follow-up. The PR delivers a coherent v1 of harness-templates-by-topology with serious thought put into the variety-reduction angle, drift handling, and zero-regression integration.
Approval marker
My sandbox blocked the marker write. Please run on Rex's behalf:
printf 'ae7f982694876ed4f67fb51d4c6ac38988e5f9b6\n' > .claude/session/reviews/346-rex.approved
(Bare 40-char SHA + newline, no labels — verified with od -c should show \n then * for the second line.)
🤖 Reviewed by Rex (Code Reviewer Agent)
📌 Reviewed commit: `ae7f982694876ed4f67fb51d4c6ac38988e5f9b6`
…I / Go data pipeline (#346) * feat(#297): harness templates by topology — TS NextJS / Python FastAPI / Go data pipeline Ships v1 of `topologies/<name>/`, the path-mirrored bundle convention adopters opt into via `/handover --topology <name>` to get a pre-curated governance surface instead of reassembling it by hand on every onboarding. What lands: - **`topologies/typescript-nextjs/`, `topologies/python-fastapi/`, `topologies/go-data-pipeline/`** — 3 starter shapes. Each ships `VERSION`, `README.md`, curated `handbooks/{architecture,language,domain}/*.md` (8-9 files each), a stack-appropriate `golden-paths/*.yml` CI pipeline, and an `agdr-<stack>.md` template prompting stack-specific decisions. - **`/handover` topology pick** — early-flow question after project naming, defaults to "Skip / custom" (no behaviour change for adopters who don't pick). On pick, instantiates the bundle into the project's `handbooks/` + `.github/workflows/` + `docs/agdr/` (drafts, not commits). - **`/update` topology drift detection** — scans adopter-instantiated bundles' VERSION against upstream framework's `topologies/<name>/VERSION`, offers operator-approved per-file diff on drift. Default skip — manual sync. - **AgDR-0048** — body-H1 only (no YAML frontmatter). Records the path- mirroring vs frontmatter-registry vs config-block choice, the 3 starter-topology pick + Ashby's-Law variety-reduction rationale, the VERSION-file drift detection (vs git-tag / hash comparison), the early-flow `/handover` integration shape, and the v1 framework-curated- only scope (adopter-authored topologies deferred to v2.1). - **Smoke test** at `.claude/skills/handover/tests/test_topology_pick.sh` — 10 assertions covering bundle inventory (each topology has the 5 required axes), AgDR shape (body-H1 only, canonical "In the context of" one-liner), and integration claims (`CLAUDE.md` + `/update` SKILL.md mention topology). - **CLAUDE.md** — adds one line to the QUICK REFERENCE table for `topologies/`. Skill table unchanged (no new slash command — extends existing `/handover` + `/update`). Why this matters: - Adopters today reassemble the same governance surface every project onboarding — 6+ primitives wired up by hand each time. This is the exact "reassembly fatigue" failure mode harness-engineering literature flags. - Committing to a topology also narrows the agent's output space (Ashby's Law) — fewer valid actions = more achievable harness. - v1 scope is deliberately narrow (3 framework-curated topologies, no composition, no adopter-authored shapes) to ship something maintainable rather than an unmaintainable registry of 50. Closes #297 * fix: add MD032 blank line before list in batch-size-tuning handbook CI markdownlint failure on initial #346 push. Line 44 introduced a bulleted list directly after "Per-record fixed costs are huge:" without a blank line separator. MD032 requires blank lines around all lists. One-line fix. Refs #297 --------- Co-authored-by: me2resh <ahmed.abdelaliem@gmail.com>
Summary
topologies/<name>/v1 ships 3 framework-curated bundles — TypeScript NextJS web app, Python FastAPI service, Go data pipeline. Each is a self-contained directory tree withVERSION,README.md, curatedhandbooks/{architecture,language,domain}/*.md, a stack-appropriategolden-paths/*.ymlCI pipeline, and a stack-specific AgDR template. Adopters pick a topology at/handovertime and get a pre-curated governance surface instead of reassembling 6+ primitives by hand on every onboarding./handovertopology pick is early-flow + default-skip — added after the project-naming step. Default is "Skip / custom" so existing/handovercallers see zero behaviour change. On pick, the bundle instantiates into the project'shandbooks/+.github/workflows/+docs/agdr/(as drafts, not commits — operator commits when satisfied). Acts as the variety-reduction lever from Ashby's Law: narrows the agent's output space to a stack the framework has opinions about, which makes the harness more achievable./updatetopology drift detection —/updatescans adopter-instantiated bundles'VERSIONagainst upstreamtopologies/<name>/VERSIONand offers operator-approved per-file diff on drift. Default is skip-manual-sync; the operator stays in control of which upstream changes apply to their already-customised bundle./handoverintegration shape, and the v1 framework-curated-only scope (adopter-authored topologies explicitly deferred to v2.1 to keep the maintenance surface honest)..claude/skills/handover/tests/test_topology_pick.sh— 10 assertions covering per-topology bundle inventory (5 required axes each), AgDR shape (body-H1, canonical "In the context of" one-liner), and the integration-claim references inCLAUDE.md+/updateSKILL.md. Wave 1 invariants all pass (skill count stays at 53 — this PR extends/handover+/update, no new slash command).topologies/so adopters discovering the framework see it in the index. The full skill table is unchanged.Testing
bash .claude/skills/handover/tests/test_topology_pick.sh— 10/10 PASSbash .claude/hooks/tests/test_token_efficiency_wave1.sh— 4/4 invariants PASS (53 skills catalogued, ≤25 words/row, ≤200 chars/description, ≤600 chars SessionStart banner)find topologies/<name> -type f | wc -lreturns the expected count (8 for go-data-pipeline, 13 for python-fastapi + typescript-nextjs)cd /tmp && mkdir test-adoption && cd test-adoption && /handover --topology typescript-nextjs— bundle should land athandbooks/+.github/workflows/nextjs-ci.yml+docs/agdr/agdr-typescript-nextjs.md(all drafts)topologies/typescript-nextjs/VERSION, run/update, the skill should flag the drift + offer per-file diffCloses #297
Glossary
/handovertimetopologies/<name>/handbooks/architecture/foo.mdlives at the path that mirrors where it'd land in an adopter's project after instantiation. No central manifest, no frontmatter; the directory layout IS the manifest./updatecompares adopter-instantiated bundles'VERSIONagainst upstreamtopologies/<name>/VERSION. On mismatch, offers operator-approved per-file re-instantiation diff. Default skip — manual sync.