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)