From 6e46e5537809d225182be67af47146f0f784c91f Mon Sep 17 00:00:00 2001 From: emeraldleaf Date: Fri, 5 Jun 2026 15:54:07 -0600 Subject: [PATCH] chore(claude): encode 10 borrowings from IDSD series + The Trap + Iron Triangle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Net result of auditing all 5 articles in Kapil Viren Ahuja's IDSD vs SDD series (Activated Thinker, March–May 2026). 10 method additions across 3 surfaces. One originally-proposed change (Connections section) dropped after re-audit — Ahuja himself walked it back in "The Anatomy of Intent." CLAUDE.md "Debugging Discipline" (+ 2 rules, 4 lines net): - Presence in the loop, not approval at the gate — distinguishes pattern-conforming features (gate review fine) from non-pattern-conforming features (stay present during build). Tied to `/feature-spec` Significance Check. - Continue is the verb that gets you in trouble. Build is not. — prototypes need token budget + stop-time, set up front. From The Trap: "Nobody approves that. Nobody ever approves that. It approves itself, one month at a time." .claude/commands/feature-spec.md (6 additions): - Step 1 prepended with Value gate (3 CXO questions): who needs this, would we still build it at engineering-time cost, who owns saying no. From The Trap. - Goal section: two-implementations test — if only one implementation can satisfy this, you wrote a spec disguised as a goal. From IDSD. - Acceptance criteria: constraints-vs-failure-conditions decision rule callout. From IDSD. - Affects: Upstream dependencies (assumptions that could shift) — names the load-bearing context the spec depends on, so the AI flags during build if any of it moves. From "SDD Will Collapse." - New Non-functional constraints section (optional, 5-7 lines max, business language, not implementation patterns). From IDSD's anatomy of Intent. - Step 5 added: Hole-test — final completeness check before shipping spec. From IDSD. - Existing Closing the loop renumbered to step 6. docs/dev-loop.md (2 additions): - "This is a method, not a harness" section after At a glance — encoding loop is the method; Claude Code, CodeRabbit, GitHub Actions, Spec Kit, BMAD, Kiro, Garura are harnesses. Adopting a harness without a method is the default failure mode today. - "Lineage and grounding" section before Source links — Larman/Basili 2003, Ostroff/Makalsky/Paige 2004 XP, METR 2025, Anthropic Sept 2025 postmortem, OpenAI Symphony April 2026, Uber 2026 budget burn, Ahuja's IDSD series. Includes the decay-warning rule and the encoding loop's contribution to the lineage (cross-feature compounding). Also corrected stale "six destinations" in At a glance → "five surfaces" to match the 5-surface encoding model we shipped in #114. Verification: - wc -l CLAUDE.md: 305 (was 301; soft cap 400, hard 500 — comfortably under) - broken-link audit on full repo: exit 0 - All rule headlines linkable via /check-rules Co-Authored-By: Claude Opus 4.7 --- .claude/commands/feature-spec.md | 94 +++++++++++++++++++++++++++++++- CLAUDE.md | 6 +- docs/dev-loop.md | 52 +++++++++++++++++- 3 files changed, 147 insertions(+), 5 deletions(-) diff --git a/.claude/commands/feature-spec.md b/.claude/commands/feature-spec.md index 66d57b81..68dab989 100644 --- a/.claude/commands/feature-spec.md +++ b/.claude/commands/feature-spec.md @@ -23,9 +23,28 @@ The pattern is: spec → code → encode lessons → smarter next session. ## What to do -### 1. Clarify the scope (2–4 targeted questions) +### 1. Value gate (before drafting anything) -Lock in the things the spec needs but the user's one-liner didn't say: +Three questions to answer honestly **before** the spec is drafted. If the +answers don't land, this isn't a feature spec — it's an experiment, and the +right output is a token budget + a stop-time, not a spec. + +1. **Who needs this, and what breaks for them if it never exists?** + If the honest answer is "no one," this is an experiment. Treat it as one. +2. **Would we still build it if it cost a week of engineering time instead + of an afternoon of tokens?** + This is the cost question, asked deliberately now that generation is cheap. + Most feature inflation will not survive it. +3. **Who owns saying no to this?** + A decision with no owner is a trap. Name the person whose job is the + refusal. (For solo work: you. For team work: a named role.) + +If question 1 surfaces "no one," propose running it as a time-boxed experiment +(token budget + stop-time) instead of drafting a full spec. If question 3 +surfaces "nobody, really," go find the owner first. + +Once the value gate passes, lock in the things the spec needs that the user's +one-liner didn't say (2–4 targeted scoping questions): - Which service(s)? (Catalog / Order / Payment / Shipping / Notification — or new) - New endpoint, modifying existing behavior, or a saga step? @@ -40,12 +59,30 @@ Produce markdown with these sections: **Goal** — one sentence: the user-facing outcome. +> **Two-implementations test for the goal.** Apply this test: *"Can two +> completely different implementations both satisfy this goal?"* If yes, +> you wrote a goal. If only one implementation could possibly satisfy it, +> you wrote a spec disguised as a goal — and demoted the agent from +> decision-maker to typist. Counter-example: *"Build a Go microservice +> using gRPC, with Postgres for storage and Redis for state, behind an +> Envoy sidecar"* is a spec in goal's clothes. *"Build a microservice +> that handles the user-facing product catalog"* is a goal. + **Acceptance criteria** — bullets, externally observable: - API contract (request shape, response shape, status codes) - Saga progression (events fired, events consumed) - Side effects (DB rows written, events emitted, cache invalidations) - Failure modes (invalid input, race, downstream unavailable) +> **Constraints vs failure conditions — decision rule.** For each line you're +> about to write, ask: *"Would knowing this change how the builder writes +> code?"* If yes → it's a constraint and goes in the constraints/affects +> section (the builder needs it to make a design call). If no → it's a +> failure condition that goes in acceptance (the validator catches it after +> the code exists). Example: *"Must not introduce a new runtime dependency"* +> → constraint. *"Unit test coverage must stay above 90%"* → failure +> condition. Mixing them invites coverage gaming and reward-hacking. + **Affects** — surfaces this touches: - New / changed endpoints - New / changed aggregates @@ -53,6 +90,36 @@ Produce markdown with these sections: - New / changed gRPC contracts - New external dependencies +**Upstream dependencies (assumptions that could shift)** — list the +load-bearing assumptions this spec depends on. If any of these change +mid-build, the spec becomes invalid and the AI should flag it: + +- Deployment target (Fly.io / Aspire local / future Hetzner) +- DB engine version (Postgres major bumps, SQL Server provider quirks) +- External API contracts (Stripe, ASB protocol versions) +- Auth model (JWT claim shape, Keycloak realm structure) +- gRPC contracts shared with other services +- CLAUDE.md rules that are themselves in flux (see open `rule-encoding-deferred` issues) + +Naming these inline lets the AI flag *during build* if it notices any of them +shifting (e.g., "you bumped EF Core; this spec assumed the old behavior of X"). +Closes the failure mode of *"every downstream task inheriting assumptions that +no longer held."* + +**Non-functional constraints** (optional — include only when relevant) — +*qualities the outcome must carry*, in business language, **5–7 lines maximum**: + +- ✅ "Support 1,000 concurrent users at peak" +- ✅ "p99 latency under 200ms on read endpoints" +- ✅ "99.99% uptime against the published SLO" +- ❌ "Use Wolverine with the standard outbox setup" (this is Context — already + in CLAUDE.md / `docs/architecture.md`) +- ❌ "Wrap the handler with PolicyExecutor.Standard" (this is implementation) + +When the constraints list grows past a handful, stop — something on it doesn't +belong. It's either Context (what the canon has already standardized) or a +failure condition (validator-checkable after). + **Constraints from CLAUDE.md** — auto-reference the rules that apply, pulled from the *current* CLAUDE.md (read it; don't reconstruct from memory). For each constraint name the rule + link to the section. Common candidates: @@ -129,7 +196,28 @@ Produce: - Note any DI registration that needs adding to `AddXInfrastructure` - Note any new aggregate that needs migration + factory method -### 5. Closing the loop +### 5. Hole-test — close the gaps before shipping + +Before the user opens the GitHub issue or runs `/new-feature-slice`, run one +final completeness check: + +> *"Imagine handing this spec to someone who was not in your head — or to the +> AI implementing it next session. Where would they have to guess?"* + +Walk through each section and mark every place an implementer (human or AI) +would infer rather than read. Common holes: + +- Acceptance criteria that don't name failure modes (just success paths) +- Affects that name "OrderService" without naming which endpoints or events +- Constraints that say "follow IDOR pattern" without naming the predicate site +- Upstream dependencies that mention "Postgres version" without specifying which behavior the spec assumes +- Connections to other features that say "this touches the cart" without naming the cart endpoint contract + +Every guess-point is a hole the agent will fill with its own assumption. +Close them in the spec before implementation starts. Per Kapil Viren Ahuja's +ICE framing: *"Every place they point is a hole you were about to let fill."* + +### 6. Closing the loop End with this prompt to the user (verbatim, so the loop-close is consistent): diff --git a/CLAUDE.md b/CLAUDE.md index 595fbd8d..fa619455 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -182,7 +182,11 @@ The bar isn't "document every bug fix." It's: **if the failure mode would surpri Diagrams are always paired: every `docs/*.excalidraw` ships with a sibling `docs/*.svg`. The `.excalidraw` is the authoritative editable source; the `.svg` is what github.com renders inline (so reviewers see it on the PR page). Editing one without re-rendering the other breaks the pairing — the source no longer matches what reviewers actually see. The render pipeline lives in `.claude/scripts/rebuild-diagrams.sh` (Playwright-driven; reads `.excalidraw`, writes `.svg` + `.png`). Enforcement is layered: (a) the CI `Diagram-pair audit` step fails the build if any `.excalidraw` lacks its `.svg` (or vice versa), (b) the `.coderabbit.yaml` path_instructions for topology-touching files flag missing doc/diagram pairs at review time, (c) this rule documents the discipline. The "is the rendered SVG still in sync with the source?" deeper check isn't mechanically enforced yet (would require the Playwright render in CI); for now, when you edit a `.excalidraw`, run `.claude/scripts/rebuild-diagrams.sh` before committing. -All three rules are for everyone working in this repo (humans, AI assistants, future-you). Don't wait to be asked. +**Presence in the loop, not approval at the gate.** Reviewing the AI's finished diff is not presence — by the time you see it, the agent has already filled gaps you didn't notice. For *non-pattern-conforming* features (new bounded context, novel transport, security model change, multi-step refactor), stay present during implementation: check intermediate state, push back on inferred decisions, course-correct before the diff is too large to read honestly. For *pattern-conforming* features (CRUD endpoint following existing shape, new saga handler matching the canonical pattern), the canon + CodeRabbit + tier-3 mechanical catches do the work — gate review is sufficient. **Rule of thumb: if `/feature-spec` flagged the change as architecturally significant in its Significance Check, treat it as non-pattern-conforming and stay present.** Naming the distinction matters because "I'll review when it's done" is how three days of rework happens. + +**Continue is the verb that gets you in trouble. Build is not.** Prototyping is encouraged — cheap building lets you run more experiments, which is genuine leverage. The discipline is the *stop*, not the *start*: the moment a prototype stops being how you find a return and becomes the whole job (build after build, no return you can point to), it's the stop that matters. For experiments, set a token budget and a stop-time up front. When either runs out, the default answer is "we learned what we needed; we don't continue." Per Kapil Viren Ahuja: *"Nobody approves that. Nobody ever approves that. It approves itself, one month at a time."* The mechanical floor: every experimental branch ends at a defined sunset, even if the work was technically interesting. Carry-debt (maintained, secured code that nobody needed) is real. + +All five rules are for everyone working in this repo (humans, AI assistants, future-you). Don't wait to be asked. ## Continuous Rule Encoding (the compounding loop) diff --git a/docs/dev-loop.md b/docs/dev-loop.md index e9a4945a..6fc4b63f 100644 --- a/docs/dev-loop.md +++ b/docs/dev-loop.md @@ -29,12 +29,33 @@ Last updated: 2026-05-29. Five forward stages — *Edit → Build → Test → PR → Merge/Runtime* — closed by a sixth, **reflexive** step: every non-obvious finding gets encoded across the -six destinations described under "The reflexive step" so the next instance is +five surfaces described under "The reflexive step" so the next instance is caught earlier, not re-derived. The reflexive step is what makes the loop compound. Without it, the same findings recur every PR cycle. --- +## This is a method, not a harness + +Claude Code, CodeRabbit, GitHub Actions, Excalidraw, the `dotnet-performance` skill — these are **harnesses** that carry out work. The encoding loop is the **method** that defines what the work is, where rules live, and how findings turn into durable encoded knowledge. + +- Harness without method → agents fill gaps the human never thought through; the "spec was good but the model strayed" failure mode +- Method without harness → well-defined rules nobody runs +- Method paired with the right harnesses → the encoding loop + +When comparing the loop to Spec Kit, BMAD, Kiro, Tessl, Agent OS, Kapil Viren Ahuja's Garura: **those are harnesses**. The encoding loop is the method. Adopting a harness without a method is the default failure mode today because the harness is the part with a download button. + +The encoding loop's method consists of: +- **`CLAUDE.md` + the `.claude/` folder** (the canon + agents + skills + commands + hooks) +- **The 5 encoding surfaces** (where rules live — see next section) +- **The 3-tier enforcement spectrum** (how rules get caught — see [The enforcement spectrum](#the-enforcement-spectrum)) +- **Continuous Rule Encoding** (how lessons compound — see [The reflexive step](#the-reflexive-step-continuous-rule-encoding)) +- **`/feature-spec`** (the per-feature handoff that ties intent + canon together) + +Claude Code, CodeRabbit, the GitHub Actions runner — those are the harnesses that carry it out. + +--- + ## The reflexive step: Continuous Rule Encoding Per [CLAUDE.md "Continuous Rule Encoding"](../CLAUDE.md#continuous-rule-encoding-the-compounding-loop), @@ -547,6 +568,35 @@ for the curation rationale.) --- +## Lineage and grounding + +The encoding loop isn't a new idea. It's the latest iteration of a long lineage of iterative + invariant-encoding methodologies: + +- **Larman & Basili 2003 (IEEE Computer)** — iterative development goes back to the 1950s; the single-pass document-driven ideal was doubted from the start, even by Royce +- **Ostroff, Makalsky, Paige 2004 (XP)** — *"Agile Specification-Driven Development"* argued *"a 'complete' specification is a flawed ideal"* and specs should emerge as tests and contracts +- **METR 2025 controlled trial** — experienced developers were measurably slower with AI but felt faster. *"Being wrong while feeling fast is the whole failure in one sentence"* +- **Anthropic September 2025 postmortem** — ~30% of Claude Code users hit at least one degraded response over a five-week period; most never noticed (the Dependence Debt example) +- **OpenAI Symphony (April 2026)** — 2,169-line RFC-grade formal spec was distilled FROM software built first (Codex generated every line). *"The deep, RFC-grade spec is retrospective documentation of software that already ran."* The industry sells the output of that process as if it were the method +- **Uber 2026** — burned through annual AI coding budget in ~4 months, $500-$2,000/engineer/month at 84% Claude Code adoption. CTO publicly said the team was "back to the drawing board." Cost meter pricing upward, value link *"not there yet"* +- **Kapil Viren Ahuja's IDSD series (Activated Thinker, March–May 2026)** — the most thoroughly worked-out parallel: Intent + Context + Expectations (ICE), with the **Agentic Iron Triangle** reshape — Speed → table stakes, Quality → floor held by evals, Cost → split into **tokens + cognition**. Per-feature methodology. The encoding loop's contribution is the cross-feature compounding IDSD doesn't address + +### The decay warning (every method eventually decays toward what it replaced) + +Per Ahuja's own admission about IDSD: *"Maybe IDD decays into a thirty-field intent form, and we land right back here, a new name on the door."* Agile decayed into spec-process-with-shorter-cycles. SDD started as goal-direction and decayed into 1,300-line specs. TDD decayed into coverage-gaming. + +The encoding loop's defense against decay: + +1. **Lean-CLAUDE.md discipline + CI size budget** (soft 400, hard 500) — prevents the canon itself from bloating into the spec it was meant to replace +2. **`/check-rules` audit** — paraphrases stay aligned with the canonical source +3. **The explicit Continuous Rule Encoding compounding step** — keeps "lessons from this feature" distinct from "what this feature must do," so the rule-set never collapses into per-feature ceremony +4. **The enforcement spectrum** — promotes rules from convention → automation → mechanical, so high-value rules become loud failures, not silent conventions + +### The encoding loop's contribution to the lineage + +Explicit **cross-feature compounding** via the 5 encoding surfaces + the enforcement spectrum + the disciplines that catch drift (file-move, doc-and-diagram, lean-CLAUDE.md, presence-in-loop, continue-is-the-verb, broken-link audit). Every feature makes the next one start smarter — which is the only thing that scales when generation cost falls to zero and cognition stays finite. + +--- + ## Source links - [CLAUDE.md](../CLAUDE.md) — canonical project rules