From 5575cfa687a1a53aeeb65f21101bdfcd51161685 Mon Sep 17 00:00:00 2001 From: Pierre Brisorgueil Date: Fri, 31 Jul 2026 09:21:10 +0200 Subject: [PATCH 1/2] docs(skills): add the minimal-code decision ladder to /feature Phase 0 Challenge every mechanism a change would introduce before proposing an implementation, stopping at the first rung that holds: product decision -> reuse -> stdlib -> native platform -> installed dependency -> one-liner -> minimal code. Persisted state gets its own rule: state encoding a policy is not a code choice, since code is deleted while data has to be migrated, so it requires explicit user confirmation before it is built. The ladder outcome is carried into the "present plan" step as one line per rejected mechanism. Guardrails stay non-negotiable: understanding the problem, trust-boundary validation, data-loss handling, security, accessibility, and anything the user explicitly asked for are never traded away. Claude-Session: https://claude.ai/code/session_019Cow7oT71FcBKpD5brmwBs --- .claude/skills/feature/SKILL.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.claude/skills/feature/SKILL.md b/.claude/skills/feature/SKILL.md index 1b89ecea5..a1ac94ab8 100644 --- a/.claude/skills/feature/SKILL.md +++ b/.claude/skills/feature/SKILL.md @@ -117,11 +117,28 @@ For each user-facing flow this feature creates or modifies, identify: - Works WITHOUT organizations enabled? - No hard dependency on external services for core flow? +### 4b. Minimal-code ladder (run before presenting) + +Challenge every **mechanism** this change would introduce — a schema field, a flag, a collection, an abstraction, a scheduled job. Stop at the first rung that holds: + +0. **Does a product decision remove it?** — accept the cost, accept the failure, do nothing, or surface it to the user. +1. **Already in this codebase?** — reuse the helper, service or pattern. +2. **In the standard library?** — use it. +3. **A native platform feature?** (DB constraint/index, framework built-in) — use it. +4. **An already-installed dependency?** — use it. +5. **One line, a constant, or config?** — make it that. +6. Only then: build it, minimal. + +**Persisted state is the expensive rung.** A schema field, collection or flag encoding a *policy* (a known-bad marker, a cap, a memo of a past failure) is not a code choice — code is deleted, data is migrated. Rung 0 is mandatory for it, and it needs **explicit user confirmation in §5** before it is built. + +**Never traded away** (lazy ≠ negligent): understanding the problem before picking a rung, validation at trust boundaries, error handling that prevents data loss, security, and anything the user explicitly asked for. + ### 5. Present plan & ask questions **STOP and present to the user:** - Flows identified (happy + error + edge cases) - Users impacted + notification plan +- **Ladder outcome (§4b)** — one line per rejected mechanism (` — simpler option rejected because `), plus any persisted state awaiting confirmation. A change that adds a mechanism and rejects nothing means nobody looked. - Open questions or scope decisions **Wait for user validation before coding.** (Non-interactive runs: Phase 0.0 From adc0972cbdef6b310218486ac217e7f3be379da9 Mon Sep 17 00:00:00 2001 From: Pierre Brisorgueil Date: Fri, 31 Jul 2026 09:44:57 +0200 Subject: [PATCH 2/2] docs(skills): tighten the ladder rung-0 exit and the persisted-state confirmation Address review feedback on the minimal-code ladder: Rung 0 now holds only when the mechanism actually disappears. "Accept the cost" or "surface it to the user" can leave the mechanism required, and the stop-at-the-first-rung rule would then skip reuse, stdlib, platform features and the one-liner rung. Persisted state needs a blocking yes on that specific state, stated both in the ladder and in the present-plan step, so it is never covered by a general "plan validated". On the frontend side the rule is scoped to state that is actually retained or restored: a transient request or response field is not persisted state. The presented plan now reports the selected rung, not only the rejected options, so the decision that was made survives into the implementation. Claude-Session: https://claude.ai/code/session_019Cow7oT71FcBKpD5brmwBs --- .claude/skills/feature/SKILL.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.claude/skills/feature/SKILL.md b/.claude/skills/feature/SKILL.md index a1ac94ab8..f17422da6 100644 --- a/.claude/skills/feature/SKILL.md +++ b/.claude/skills/feature/SKILL.md @@ -121,7 +121,7 @@ For each user-facing flow this feature creates or modifies, identify: Challenge every **mechanism** this change would introduce — a schema field, a flag, a collection, an abstraction, a scheduled job. Stop at the first rung that holds: -0. **Does a product decision remove it?** — accept the cost, accept the failure, do nothing, or surface it to the user. +0. **Does a product decision remove it?** — accept the cost, accept the failure, do nothing, or surface it to the user. This rung holds **only if the mechanism then disappears**; if the product still needs it, keep going down the ladder. 1. **Already in this codebase?** — reuse the helper, service or pattern. 2. **In the standard library?** — use it. 3. **A native platform feature?** (DB constraint/index, framework built-in) — use it. @@ -129,7 +129,7 @@ Challenge every **mechanism** this change would introduce — a schema field, a 5. **One line, a constant, or config?** — make it that. 6. Only then: build it, minimal. -**Persisted state is the expensive rung.** A schema field, collection or flag encoding a *policy* (a known-bad marker, a cap, a memo of a past failure) is not a code choice — code is deleted, data is migrated. Rung 0 is mandatory for it, and it needs **explicit user confirmation in §5** before it is built. +**Persisted state is the expensive rung.** A schema field, collection or flag encoding a *policy* (a known-bad marker, a cap, a memo of a past failure) is not a code choice — code is deleted, data is migrated. Rung 0 is mandatory for it, and it needs an **explicit, blocking user confirmation in §5** before it is built — a yes on that specific state, never implied by the general plan validation. **Never traded away** (lazy ≠ negligent): understanding the problem before picking a rung, validation at trust boundaries, error handling that prevents data loss, security, and anything the user explicitly asked for. @@ -138,7 +138,8 @@ Challenge every **mechanism** this change would introduce — a schema field, a **STOP and present to the user:** - Flows identified (happy + error + edge cases) - Users impacted + notification plan -- **Ladder outcome (§4b)** — one line per rejected mechanism (` — simpler option rejected because `), plus any persisted state awaiting confirmation. A change that adds a mechanism and rejects nothing means nobody looked. +- **Ladder outcome (§4b)** — the **selected rung** first (``, e.g. `1 reuse — existing users service`), then one line per rejected mechanism (` — simpler option rejected because `). A change that adds a mechanism and rejects nothing means nobody looked. +- **Persisted state, if any** — name it and **wait for an explicit yes on it**; a general "plan validated" does not cover it, and it is not built without that yes. - Open questions or scope decisions **Wait for user validation before coding.** (Non-interactive runs: Phase 0.0