adr-eligibility-gate · git:20260806.b506b65 · 2026-08-06 · sha256 0de9466a9a1333e3
adr-eligibility-gate git:20260806.b506b65A
Immutable. This exact content never changes and is served at /api/v1/blob/0de9466a9a1333e3.
--- name: adr-eligibility-gate description: > Use BEFORE drafting any ADR when a story enters DESIGN phase, or when reviewing an ADR set that feels inflated. Runs a baseline-vs-decision gate: for each candidate architectural choice, determines whether it ratifies a genuine open question (→ ADR-worthy) or re-declares project baseline / skill-enforced convention (→ not ADR-worthy). Prevents ADR over-production by filtering out non-decisions before any draft is written. Triggers: "should I write an ADR for X?", "how many ADRs does this story need?", "ADR-INFLATION detected", "disambiguate baseline from decision". --- # ADR Eligibility Gate ## Overview This skill operationalizes the "When NOT to write an ADR" section of the `architecture-decisions` skill as a **pre-draft gate**. Load it when considering whether a candidate architectural choice warrants an ADR, before writing any ADR body. **Core question:** Does this choice ratify a genuine open question with real trade-offs, or does it re-declare project baseline / existing skill-enforced convention? **When to activate:** - DESIGN phase begins for a story - Architect considers documenting a choice - Reviewer flags `ADR-INFLATION` (multiple ADRs for a story where 0-1 expected) - User asks "should I write an ADR for X?" or "how many ADRs does this need?" --- ## The 5-Question Checklist For each candidate choice, answer these questions in order. The FIRST `YES` determines the verdict. ### Q1: Is this choice already enforced by a project skill or automated architecture test? **Examples of baseline (NOT ADR-worthy):** - "Pure domain service with no IO" → ADR-002 hexagonal baseline enforces this - "CQS at method level" (one handler per command/query) → `clean-architecture-*` skill - "Validation at the boundary, keep core pure" → hexagonal baseline + tactical DDD - "Convention-based DI registration" → project skill baseline - "Value Object + pure validator" → tactical DDD baseline **If YES → `NOT ELIGIBLE — <cite skill or ADR that already enforces this>`** --- ### Q2: Is this choice a "good practice" or "avoid X antipattern" framing? **Examples:** - "No hardcoded phase names" → good practice, not a decision - "Don't duplicate validation logic" → DRY principle, not a decision - "Avoid magic strings" → coding standard, not a decision **Good practices and antipattern avoidance are baseline expectations, not architectural decisions.** **If YES → `NOT ELIGIBLE — baseline good practice / antipattern avoidance`** **Exception:** If the choice is framed as a **context-mapping relationship** (e.g., "config as Published Language, guard as Conformist") rather than just "no hardcoding", proceed to Q3. --- ### Q3: Does the choice add complexity beyond the project baseline? Load `architecture-patterns` skill. Check whether the choice is one of: - Establishing or changing a layer boundary - Choosing an aggregate boundary - **Adopting** a pattern that adds complexity: CQRS+Bus, Event Sourcing, Saga, Specification, ACL, Published Language, Conformist - Establishing a bounded context boundary - Affecting a cross-cutting concern (error handling strategy, validation approach) **If NO → `NOT ELIGIBLE — no complexity addition beyond baseline`** **If YES → proceed to Q4.** --- ### Q4: Was the question actually raised by a story, AC, or measurable force in the current batch? **Silence = baseline default.** ADRs (whether `Accepted` or `Rejected`) ratify questions that were **actually asked**. A `Rejected` ADR is legitimate ONLY when a story or measurable force in the batch raised the question. **Check:** - Does an AC explicitly require evaluating this choice? - Did the event model surface this as a decision point? - Did a technical constraint (performance, security, integration) force the question? **If NO → `NOT ELIGIBLE — unraised question; non-decision artefact (G14)`** **If YES → proceed to Q5.** --- ### Q5: Does the choice have genuine trade-offs (not only upsides)? Every ADR must demonstrate **trade-off analysis**. If the choice has only benefits and no downsides, it is not a decision — it is a no-brainer that should be baseline. **Check the 5 Universal Forces** (from `architecture-decisions` skill): - Simplicity - Consistency - Performance - Evolvability - Team capability **If the choice scores high on ALL five → `NOT ELIGIBLE — no genuine trade-offs; should be baseline`** **If the choice creates tension between at least two forces → `ELIGIBLE — genuine trade-off`** --- ## Output Format For each candidate: ``` Candidate: <short description> Verdict: ELIGIBLE | NOT ELIGIBLE Reason: <1-line citation to Q1-Q5 + skill/ADR section> ``` **Example (US3 candidates):** ``` Candidate: Pure domain service with no IO Verdict: NOT ELIGIBLE Reason: Q1 YES — ADR-002 hexagonal baseline enforces purity Candidate: Fail-closed posture for dispatch gate Verdict: ELIGIBLE Reason: Q1 NO, Q2 NO, Q3 YES (cross-cutting error strategy), Q4 YES (AC-04), Q5 YES (over-blocking vs silent drift) Candidate: VO + validation at boundary Verdict: NOT ELIGIBLE Reason: Q1 YES — hexagonal baseline + tactical DDD enforce this Candidate: No hardcoded phase names Verdict: NOT ELIGIBLE (as framed) Reason: Q2 YES — "no hardcoding" is a good practice, not a decision Candidate (reframed): Config as Published Language, guard as Conformist Verdict: ELIGIBLE Reason: Q2 NO (context-mapping), Q3 YES (Published Language adoption), Q4 YES (event model), Q5 YES (coupling vs drift) ``` --- ## Integration with `architecture-decisions` Skill This gate does NOT replace `architecture-decisions` — it **precedes** it: 1. **Gate (this skill):** Determines IF an ADR is warranted. 2. **Template (architecture-decisions):** Provides HOW to write the ADR body if the gate passes. **Load order:** - `adr-eligibility-gate` → verdict per candidate - If `ELIGIBLE` → load `architecture-decisions` for template + lifecycle --- ## Anti-patterns Detected by This Gate | Anti-pattern | Description | Gate catches it via | |---|---|---| | **ADR-INFLATION** | Multiple ADRs for baseline re-declarations | Q1 | | **NON-DECISION** | ADR for a choice with no alternatives | Q5 | | **BASELINE DRIFT** | Project baseline not reflected in ADR filters | Q1 + Q3 | | **UNRAISED QUESTION** | ADR for a question nobody asked (G14) | Q4 | | **GOOD-PRACTICE ADR** | ADR for "avoid X" or "always Y" framing | Q2 | --- ## Real-World Calibration Run this gate on **existing ADRs** to verify calibration: | ADR | Expected Verdict | Actual Q-path | |---|---|---| | ADR-001 (Result type) | ELIGIBLE | Q1 NO, Q3 YES, Q4 YES (#47), Q5 YES | | ADR-002 (Hexagonal) | ELIGIBLE | Q1 NO (first in project), Q3 YES, Q4 YES (#47), Q5 YES | | ADR-003 (Config cascade) | ELIGIBLE | Q1 NO, Q3 YES, Q4 YES (#47), Q5 YES | | ADR-004 (pure service, US3) | NOT ELIGIBLE | Q1 YES — ADR-002 baseline | | ADR-005 (fail-closed, US3) | ELIGIBLE | Q1 NO, Q3 YES (cross-cutting), Q4 YES, Q5 YES | | ADR-006 (VO + validation, US3) | NOT ELIGIBLE | Q1 YES — hexagonal + DDD baseline | | ADR-007 (no hardcoding, US3) | NOT ELIGIBLE (as framed) / ELIGIBLE (reframed) | Q2 YES (good practice) / Q3 YES (Published Language) | **If the gate yields unexpected verdicts on ADR-001..003, recalibrate Q1/Q3.** --- ## Dependencies - `plugins/skills/architecture-decisions/SKILL.md` (cites "When NOT to write an ADR") - `plugins/skills/architecture-patterns/SKILL.md` (cites baseline patterns for Q3) --- ## Evals ### Content evals 1. **Candidate:** "pure domain service with no IO" **Expected:** `NOT ELIGIBLE — ADR-002 hexagonal baseline` 2. **Candidate:** "fail-closed posture for a security gate" **Expected:** `ELIGIBLE — Q3 YES (cross-cutting concern), Q5 YES` 3. **Candidate:** "no hardcoded phase names" **Expected:** `NOT ELIGIBLE — Q2 YES (good practice)` ### Trigger evals **Should-trigger (8):** - "should I write an ADR for this choice?" - "how many ADRs does story X need?" - "is this ADR-worthy?" - "ADR-INFLATION detected in DESIGN review" - "disambiguate baseline from decision" - "this feels like too many ADRs" - "evaluate candidate architectural choice" - "before drafting ADR" **Should-not-trigger (8):** - "how do I write an ADR?" → `architecture-decisions` - "what's the ADR template?" → `architecture-decisions` - "list existing ADRs" → grep / index read - "ratify ADR-005" → human gate - "event modeling for story X" → `architecture-patterns` - "which DDD pattern should I use?" → `architecture-patterns` - "write the ADR body" → `architecture-decisions` - "supersede ADR-001" → `architecture-decisions` lifecycle --- ## Version **v1.0** — 2026-06-28 — Initial release (genesis output, US3 case study)