aped-method 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,229 @@
1
+ # APED Method
2
+
3
+ Zero-dependency CLI that scaffolds a complete dev pipeline into any [Claude Code](https://claude.ai/download) project.
4
+
5
+ ```
6
+ npx aped-method
7
+ ```
8
+
9
+ ```
10
+ █████╗ ██████╗ ███████╗██████╗
11
+ ██╔══██╗██╔══██╗██╔════╝██╔══██╗
12
+ ███████║██████╔╝█████╗ ██║ ██║
13
+ ██╔══██║██╔═══╝ ██╔══╝ ██║ ██║
14
+ ██║ ██║██║ ███████╗██████╔╝
15
+ ╚═╝ ╚═╝╚═╝ ╚══════╝╚═════╝
16
+ M E T H O D
17
+
18
+ Analyze → PRD → UX → Epics → Dev → Review
19
+ ```
20
+
21
+ ## What it does
22
+
23
+ APED turns Claude Code into a disciplined dev pipeline. Instead of "code me an app", you get:
24
+
25
+ 1. **Analyze** — 3 parallel research agents (market, domain, technical) produce a product brief
26
+ 2. **PRD** — Autonomous generation with numbered FRs, validation scripts, domain detection
27
+ 3. **UX** — ANF framework: Assemble design DNA, Normalize with a live React prototype, Fill all screens with user validation
28
+ 4. **Epics** — Stories with ACs in Given/When/Then, FR coverage validation, ticket system integration
29
+ 5. **Dev** — TDD red-green-refactor with 5-condition gate, parallel agents for context gathering
30
+ 6. **Review** — Adversarial code review with minimum 3 findings, parallel agents (code-explorer + code-reviewer)
31
+
32
+ A guardrail hook blocks you from skipping steps. A state machine tracks progress. Everything chains automatically.
33
+
34
+ ## Quick start
35
+
36
+ ```bash
37
+ cd your-project
38
+ npx aped-method
39
+ ```
40
+
41
+ Interactive prompts ask for project name, author, languages, ticket system, and git provider. Or go non-interactive:
42
+
43
+ ```bash
44
+ npx aped-method --yes --project=my-app --author=Jane --lang=french --tickets=linear --git=github
45
+ ```
46
+
47
+ Then open Claude Code:
48
+
49
+ ```
50
+ /aped-a # Start with analysis
51
+ /aped-all # Or run the full pipeline
52
+ ```
53
+
54
+ ## Pipeline commands
55
+
56
+ | Command | Phase | What it produces |
57
+ |---------|-------|-----------------|
58
+ | `/aped-a` | Analyze | Product brief from 3 parallel research agents |
59
+ | `/aped-p` | PRD | PRD with numbered FRs/NFRs, validated by script |
60
+ | `/aped-ux` | UX | Live React prototype (Vite), design spec, component catalog |
61
+ | `/aped-e` | Epics | Stories with ACs, tasks, FR coverage map |
62
+ | `/aped-d` | Dev | TDD implementation with 5-condition gate |
63
+ | `/aped-r` | Review | Adversarial review, minimum 3 findings |
64
+
65
+ ## Utility commands
66
+
67
+ | Command | What it does |
68
+ |---------|-------------|
69
+ | `/aped-s` | Sprint status dashboard — progress, blockers, next actions |
70
+ | `/aped-c` | Correct course — manage scope changes with impact analysis |
71
+ | `/aped-ctx` | Brownfield analysis — generate project context from existing code |
72
+ | `/aped-qa` | Generate E2E and integration tests from acceptance criteria |
73
+ | `/aped-quick` | Quick fix/feature bypassing the full pipeline |
74
+ | `/aped-all` | Run the full pipeline A→P→UX→E→D→R with auto-resume |
75
+
76
+ ## What gets scaffolded
77
+
78
+ ```
79
+ .aped/ # Engine (immutable after install)
80
+ ├── config.yaml # Project settings, integrations
81
+ ├── hooks/guardrail.sh # Pipeline coherence hook
82
+ ├── templates/ # Document templates (brief, PRD, epics, story, quick-spec)
83
+ ├── aped-a/ # Analyze skill
84
+ │ ├── SKILL.md
85
+ │ ├── scripts/validate-brief.sh
86
+ │ └── references/research-prompts.md
87
+ ├── aped-p/ # PRD skill
88
+ │ ├── SKILL.md
89
+ │ ├── scripts/validate-prd.sh
90
+ │ └── references/fr-rules.md, *.csv
91
+ ├── aped-ux/ # UX skill (ANF framework)
92
+ │ ├── SKILL.md
93
+ │ ├── scripts/validate-ux.sh
94
+ │ └── references/ux-patterns.md # 99 priority-ranked UX rules
95
+ ├── aped-e/ # Epics skill
96
+ │ ├── SKILL.md
97
+ │ ├── scripts/validate-coverage.sh
98
+ │ └── references/epic-rules.md
99
+ ├── aped-d/ # Dev skill
100
+ │ ├── SKILL.md
101
+ │ ├── scripts/run-tests.sh
102
+ │ └── references/tdd-engine.md, ticket-git-workflow.md
103
+ ├── aped-r/ # Review skill
104
+ │ ├── SKILL.md
105
+ │ ├── scripts/git-audit.sh
106
+ │ └── references/review-criteria.md
107
+ ├── aped-s/ # Status dashboard
108
+ │ ├── SKILL.md
109
+ │ └── references/status-format.md
110
+ ├── aped-c/ # Correct course
111
+ │ ├── SKILL.md
112
+ │ └── references/scope-change-guide.md
113
+ ├── aped-ctx/ # Brownfield context
114
+ │ ├── SKILL.md
115
+ │ └── references/analysis-checklist.md
116
+ ├── aped-qa/ # QA tests
117
+ │ ├── SKILL.md
118
+ │ └── references/test-patterns.md
119
+ ├── aped-quick/SKILL.md # Quick fix
120
+ └── aped-all/SKILL.md # Orchestrator
121
+
122
+ docs/aped/ # Output (evolves during project)
123
+ ├── state.yaml # Pipeline state machine
124
+ ├── product-brief.md # From /aped-a
125
+ ├── prd.md # From /aped-p
126
+ ├── ux/ # From /aped-ux
127
+ │ ├── design-spec.md
128
+ │ ├── screen-inventory.md
129
+ │ ├── components.md
130
+ │ └── flows.md
131
+ ├── epics.md # From /aped-e
132
+ ├── stories/ # One file per story
133
+ └── quick-specs/ # From /aped-quick
134
+
135
+ .claude/
136
+ ├── commands/aped-*.md # 12 slash commands
137
+ └── settings.local.json # Guardrail hook config
138
+ ```
139
+
140
+ ## Integrations
141
+
142
+ ### Ticket systems
143
+
144
+ Configure during install or via `--tickets=`:
145
+
146
+ | Provider | Commit format | Auto-link |
147
+ |----------|--------------|-----------|
148
+ | `linear` | `feat(TEAM-XX): description` | `Part of TEAM-XX` / `Fixes TEAM-XX` |
149
+ | `jira` | `feat(PROJ-XX): description` | Smart commits |
150
+ | `github-issues` | `feat(#XX): description` | `Closes #XX` / `Fixes #XX` |
151
+ | `gitlab-issues` | `feat(#XX): description` | `Closes #XX` |
152
+ | `none` | `feat: description` | — |
153
+
154
+ ### Git providers
155
+
156
+ Configure via `--git=`:
157
+
158
+ | Provider | PR/MR creation | Branch strategy |
159
+ |----------|---------------|-----------------|
160
+ | `github` | `gh pr create` | `feature/{ticket}-{slug}` |
161
+ | `gitlab` | `glab mr create` | `feature/{ticket}-{slug}` |
162
+ | `bitbucket` | Web UI | `feature/{ticket}-{slug}` |
163
+
164
+ ## UX phase — ANF framework
165
+
166
+ The `/aped-ux` skill produces a live React prototype, not wireframes:
167
+
168
+ - **Assemble** — Collect design DNA: user inspirations, UI library (shadcn, MUI, Radix...), design tokens, branding
169
+ - **Normalize** — Scaffold Vite+React app with real PRD content (no lorem ipsum), working navigation, all screens
170
+ - **Fill** — Complete interaction states, responsive (3 breakpoints), dark mode, accessibility, then user review cycles until approved
171
+
172
+ The approved prototype becomes the UX spec that `/aped-e` consumes. Includes 99 priority-ranked UX rules and a pre-delivery checklist.
173
+
174
+ ## Guardrail hook
175
+
176
+ Every prompt is intercepted by `guardrail.sh` which checks pipeline coherence:
177
+
178
+ | Situation | Reaction |
179
+ |-----------|----------|
180
+ | Coding without epics | Warns: run A→P→E first |
181
+ | PRD without brief | Warns: run /aped-a first |
182
+ | Modifying PRD during dev | Warns: use /aped-c for scope changes |
183
+ | Quick fix request | Bypasses (that's what /aped-quick is for) |
184
+
185
+ The hook injects context — it doesn't block. Claude explains the issue and asks for confirmation.
186
+
187
+ ## Install / Update / Fresh
188
+
189
+ ```bash
190
+ # First install
191
+ npx aped-method
192
+
193
+ # Re-run on existing project → auto-detects, offers:
194
+ # 1. Update engine (preserve config + artifacts)
195
+ # 2. Fresh install (delete everything, start over)
196
+ # 3. Cancel
197
+
198
+ # Non-interactive
199
+ npx aped-method --yes # Auto-update if exists
200
+ npx aped-method --yes --update # Explicit update
201
+ npx aped-method --yes --fresh # Nuke and redo
202
+
203
+ # Version check
204
+ npx aped-method --version # Shows current version
205
+ # If installed version < CLI version → "Upgrade available: v1.x → v2.x"
206
+ ```
207
+
208
+ ## Anthropic Skills Guide compliance
209
+
210
+ All 12 skills follow the [Complete Guide to Building Skills for Claude](https://www.anthropic.com/engineering/claude-skills-guide):
211
+
212
+ - YAML frontmatter with name, description (WHAT + WHEN + negative triggers), license, metadata
213
+ - Progressive disclosure: frontmatter → SKILL.md body → references/
214
+ - `disable-model-invocation: true` on side-effect skills (dev, review, correct, all)
215
+ - `allowed-tools` restrictions on read-only skills (status, context)
216
+ - Critical Rules section at top of pipeline skills
217
+ - Examples and Common Issues in every skill
218
+ - Validation scripts with clear exit codes
219
+ - Skill tool chaining (not slash notation)
220
+ - Third-person descriptions, <1024 chars, no XML tags
221
+
222
+ ## Requirements
223
+
224
+ - [Claude Code](https://claude.ai/download)
225
+ - Node.js 18+
226
+
227
+ ## License
228
+
229
+ MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aped-method",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "type": "module",
5
5
  "description": "Scaffold the APED pipeline (Analyze, PRD, Epics, Dev, Review) into any Claude Code project",
6
6
  "bin": {
@@ -7,85 +7,86 @@ export function guardrail(c) {
7
7
  executable: true,
8
8
  content: `#!/usr/bin/env bash
9
9
  # APED Guardrail — UserPromptSubmit hook
10
- # Validates prompt coherence against pipeline state, existing artifacts, and memories.
11
- # Returns JSON with "decision" and optionally "addToPrompt" to inject context.
10
+ # Uses the official Claude Code hook output format.
11
+ # See: https://code.claude.com/docs/hooks
12
12
 
13
- set -euo pipefail
13
+ # NOT using set -e or pipefail — grep returns exit 1 on no match
14
+ # which would kill the script. We handle errors explicitly.
14
15
 
15
- PROJECT_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
16
- STATE_FILE="$PROJECT_ROOT/${o}/state.yaml"
17
- CONFIG_FILE="$PROJECT_ROOT/${a}/config.yaml"
18
- OUTPUT_DIR="$PROJECT_ROOT/${o}"
16
+ # ── Read stdin JSON ──
17
+ INPUT=$(cat < /dev/stdin)
19
18
 
20
- # Read stdin (JSON: {"session_id":"...","prompt":"..."})
21
- INPUT=$(cat)
22
- PROMPT=$(echo "$INPUT" | grep -o '"prompt":"[^"]*"' | sed 's/"prompt":"//;s/"$//' || echo "")
19
+ # Extract prompt using simple string parsing (no jq dependency)
20
+ PROMPT=""
21
+ if command -v jq &>/dev/null; then
22
+ PROMPT=$(echo "$INPUT" | jq -r '.prompt // empty' 2>/dev/null || echo "")
23
+ else
24
+ PROMPT=$(echo "$INPUT" | grep -o '"prompt":"[^"]*"' | sed 's/"prompt":"//;s/"$//' 2>/dev/null || echo "")
25
+ fi
23
26
 
24
27
  # If no prompt or empty, allow
25
28
  if [[ -z "$PROMPT" ]]; then
26
29
  exit 0
27
30
  fi
28
31
 
32
+ # ── Resolve paths ──
33
+ PROJECT_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
34
+ STATE_FILE="$PROJECT_ROOT/${o}/state.yaml"
35
+ CONFIG_FILE="$PROJECT_ROOT/${a}/config.yaml"
36
+ OUTPUT_DIR="$PROJECT_ROOT/${o}"
37
+
29
38
  # ── Read current phase from state.yaml ──
30
39
  CURRENT_PHASE="none"
31
40
  if [[ -f "$STATE_FILE" ]]; then
32
- CURRENT_PHASE=$(grep 'current_phase:' "$STATE_FILE" | sed 's/.*current_phase:[[:space:]]*"\\{0,1\\}\\([^"]*\\)"\\{0,1\\}/\\1/' | tr -d ' ' || echo "none")
41
+ PHASE_LINE=$(grep 'current_phase:' "$STATE_FILE" 2>/dev/null || echo "")
42
+ if [[ -n "$PHASE_LINE" ]]; then
43
+ CURRENT_PHASE=$(echo "$PHASE_LINE" | sed 's/.*current_phase:[[:space:]]*//;s/"//g;s/^[[:space:]]*//;s/[[:space:]]*$//' || echo "none")
44
+ fi
33
45
  fi
34
46
 
35
47
  # ── Read communication language from config ──
36
- LANG="english"
48
+ COMM_LANG="english"
37
49
  if [[ -f "$CONFIG_FILE" ]]; then
38
- LANG=$(grep 'communication_language:' "$CONFIG_FILE" | sed 's/.*communication_language:[[:space:]]*//' | tr -d ' ' || echo "english")
50
+ LANG_LINE=$(grep 'communication_language:' "$CONFIG_FILE" 2>/dev/null || echo "")
51
+ if [[ -n "$LANG_LINE" ]]; then
52
+ COMM_LANG=$(echo "$LANG_LINE" | sed 's/.*communication_language:[[:space:]]*//' | tr -d ' ' || echo "english")
53
+ fi
39
54
  fi
40
55
 
41
- # ── Detect what the user is trying to do ──
56
+ # ── Detect intent from prompt ──
42
57
  PROMPT_LOWER=$(echo "$PROMPT" | tr '[:upper:]' '[:lower:]')
43
58
 
44
- # Detect APED command invocations
45
59
  WANTS_ANALYZE=false
46
60
  WANTS_PRD=false
47
61
  WANTS_EPICS=false
48
62
  WANTS_DEV=false
49
63
  WANTS_REVIEW=false
50
64
  WANTS_ALL=false
51
- WANTS_CODE=false
52
-
53
- [[ "$PROMPT_LOWER" =~ (aped-a|/aped-a|analyze|analyse|research) ]] && WANTS_ANALYZE=true
54
- [[ "$PROMPT_LOWER" =~ (aped-p|/aped-p|prd|product.req) ]] && WANTS_PRD=true
55
- [[ "$PROMPT_LOWER" =~ (aped-e|/aped-e|epic|stories|story) ]] && WANTS_EPICS=true
56
- [[ "$PROMPT_LOWER" =~ (aped-d|/aped-d|dev|implement|code|build|create.*component|create.*service) ]] && WANTS_DEV=true
57
- [[ "$PROMPT_LOWER" =~ (aped-r|/aped-r|review|audit) ]] && WANTS_REVIEW=true
58
- [[ "$PROMPT_LOWER" =~ (aped-all|/aped-all|full.pipeline|start.from.scratch) ]] && WANTS_ALL=true
59
65
  WANTS_QUICK=false
66
+ WANTS_CODE=false
60
67
 
61
- [[ "$PROMPT_LOWER" =~ (aped-quick|/aped-quick|quick.fix|quick.feature|hotfix) ]] && WANTS_QUICK=true
62
- [[ "$PROMPT_LOWER" =~ (code|implement|write.*function|create.*file|add.*feature|fix.*bug|refactor) ]] && WANTS_CODE=true
68
+ echo "$PROMPT_LOWER" | grep -qE '(aped-a|/aped-a|analyze|analyse|research)' && WANTS_ANALYZE=true
69
+ echo "$PROMPT_LOWER" | grep -qE '(aped-p|/aped-p|prd|product.req)' && WANTS_PRD=true
70
+ echo "$PROMPT_LOWER" | grep -qE '(aped-e|/aped-e|epic|stories|story)' && WANTS_EPICS=true
71
+ echo "$PROMPT_LOWER" | grep -qE '(aped-d|/aped-d|dev|implement|build|create.*component|create.*service)' && WANTS_DEV=true
72
+ echo "$PROMPT_LOWER" | grep -qE '(aped-r|/aped-r|review|audit)' && WANTS_REVIEW=true
73
+ echo "$PROMPT_LOWER" | grep -qE '(aped-all|/aped-all|full.pipeline|start.from.scratch)' && WANTS_ALL=true
74
+ echo "$PROMPT_LOWER" | grep -qE '(aped-quick|/aped-quick|quick.fix|quick.feature|hotfix)' && WANTS_QUICK=true
75
+ echo "$PROMPT_LOWER" | grep -qE '(code|implement|write.*function|create.*file|add.*feature|fix.*bug|refactor)' && WANTS_CODE=true
63
76
 
64
77
  # ── Check artifact existence ──
65
78
  HAS_BRIEF=false
66
79
  HAS_PRD=false
67
80
  HAS_EPICS=false
68
81
 
69
- [[ -n "$(find "$OUTPUT_DIR" -name '*brief*' -o -name '*product-brief*' 2>/dev/null | head -1)" ]] && HAS_BRIEF=true
70
- [[ -n "$(find "$OUTPUT_DIR" -name '*prd*' 2>/dev/null | head -1)" ]] && HAS_PRD=true
71
- [[ -n "$(find "$OUTPUT_DIR" -name '*epic*' 2>/dev/null | head -1)" ]] && HAS_EPICS=true
82
+ if [[ -d "$OUTPUT_DIR" ]]; then
83
+ test -n "$(find "$OUTPUT_DIR" -maxdepth 1 -name '*brief*' 2>/dev/null | head -1)" && HAS_BRIEF=true
84
+ test -n "$(find "$OUTPUT_DIR" -maxdepth 1 -name '*prd*' 2>/dev/null | head -1)" && HAS_PRD=true
85
+ test -n "$(find "$OUTPUT_DIR" -maxdepth 1 -name '*epic*' 2>/dev/null | head -1)" && HAS_EPICS=true
86
+ fi
72
87
 
73
88
  # ── Phase-aware guardrail logic ──
74
- WARNINGS=()
75
-
76
- # Phase transition map: none → analyze → prd → ux → epics → dev ↔ review → done
77
- PHASE_ORDER="none analyze prd ux epics dev review done"
78
-
79
- phase_index() {
80
- local i=0
81
- for p in $PHASE_ORDER; do
82
- [[ "$p" == "$1" ]] && echo "$i" && return
83
- i=$((i + 1))
84
- done
85
- echo "0"
86
- }
87
-
88
- CURRENT_IDX=$(phase_index "$CURRENT_PHASE")
89
+ WARNINGS=""
89
90
 
90
91
  # Rule 0: Quick mode bypasses pipeline checks
91
92
  if [[ "$WANTS_QUICK" == "true" ]]; then
@@ -95,65 +96,66 @@ fi
95
96
  # Rule 1: Trying to code without epics/stories
96
97
  if [[ "$WANTS_CODE" == "true" || "$WANTS_DEV" == "true" ]] && [[ "$CURRENT_PHASE" != "dev" && "$CURRENT_PHASE" != "review" ]]; then
97
98
  if [[ "$HAS_EPICS" == "false" ]]; then
98
- WARNINGS+=("SKIP_DETECTED: Attempting dev/code without epics. Current phase: $CURRENT_PHASE. Run /aped-a /aped-p /aped-e first.")
99
+ WARNINGS="$WARNINGS\\nSKIP_DETECTED: Attempting dev/code without epics. Current phase: $CURRENT_PHASE. Run /aped-a, /aped-p, /aped-e first."
99
100
  elif [[ "$HAS_PRD" == "false" ]]; then
100
- WARNINGS+=("SKIP_DETECTED: Attempting dev/code without PRD. Current phase: $CURRENT_PHASE. Run /aped-a /aped-p first.")
101
+ WARNINGS="$WARNINGS\\nSKIP_DETECTED: Attempting dev/code without PRD. Current phase: $CURRENT_PHASE. Run /aped-a, /aped-p first."
101
102
  fi
102
103
  fi
103
104
 
104
105
  # Rule 2: PRD without brief
105
106
  if [[ "$WANTS_PRD" == "true" ]] && [[ "$HAS_BRIEF" == "false" ]] && [[ "$CURRENT_PHASE" != "prd" ]]; then
106
- WARNINGS+=("MISSING_ARTIFACT: No product brief found. Run /aped-a first to generate the brief.")
107
+ WARNINGS="$WARNINGS\\nMISSING_ARTIFACT: No product brief found. Run /aped-a first."
107
108
  fi
108
109
 
109
110
  # Rule 3: Epics without PRD
110
111
  if [[ "$WANTS_EPICS" == "true" ]] && [[ "$HAS_PRD" == "false" ]]; then
111
- WARNINGS+=("MISSING_ARTIFACT: No PRD found. Run /aped-p first to generate the PRD.")
112
+ WARNINGS="$WARNINGS\\nMISSING_ARTIFACT: No PRD found. Run /aped-p first."
112
113
  fi
113
114
 
114
115
  # Rule 4: Review without dev
115
116
  if [[ "$WANTS_REVIEW" == "true" ]] && [[ "$CURRENT_PHASE" != "dev" && "$CURRENT_PHASE" != "review" ]]; then
116
- WARNINGS+=("PREMATURE_REVIEW: No story has been developed yet. Run /aped-d first.")
117
+ WARNINGS="$WARNINGS\\nPREMATURE_REVIEW: No story developed yet. Run /aped-d first."
117
118
  fi
118
119
 
119
- # Rule 5: Trying to modify upstream artifacts during dev
120
+ # Rule 5: Modifying upstream during dev
120
121
  if [[ "$CURRENT_PHASE" == "dev" || "$CURRENT_PHASE" == "review" ]]; then
121
122
  if [[ "$WANTS_PRD" == "true" || "$WANTS_ANALYZE" == "true" ]]; then
122
- WARNINGS+=("SCOPE_CHANGE: You are in phase '$CURRENT_PHASE'. Modifying the PRD/brief now will invalidate existing epics and stories. Use /aped-r with correct-course protocol instead.")
123
+ WARNINGS="$WARNINGS\\nSCOPE_CHANGE: Phase is '$CURRENT_PHASE'. Modifying PRD/brief invalidates epics and stories. Use /aped-c instead."
123
124
  fi
124
125
  fi
125
126
 
126
127
  # Rule 6: Skipping phases
127
- if [[ "$WANTS_DEV" == "true" ]] && [[ "$CURRENT_IDX" -lt 3 ]] && [[ "$WANTS_ALL" == "false" ]]; then
128
+ if [[ "$WANTS_DEV" == "true" ]] && [[ "$WANTS_ALL" == "false" ]]; then
128
129
  if [[ "$CURRENT_PHASE" == "none" || "$CURRENT_PHASE" == "analyze" ]]; then
129
- WARNINGS+=("PHASE_SKIP: Jumping from '$CURRENT_PHASE' to dev skips critical pipeline steps. The pipeline ensures quality: Analyze PRD Epics Dev.")
130
+ WARNINGS="$WARNINGS\\nPHASE_SKIP: Jumping from '$CURRENT_PHASE' to dev skips critical steps. Pipeline: Analyze -> PRD -> Epics -> Dev."
130
131
  fi
131
132
  fi
132
133
 
133
- # ── Build response ──
134
- if [[ \${#WARNINGS[@]} -eq 0 ]]; then
135
- # No issues, allow silently
134
+ # ── No warnings = allow silently ──
135
+ if [[ -z "$WARNINGS" ]]; then
136
136
  exit 0
137
137
  fi
138
138
 
139
- # Build the addToPrompt context
140
- CONTEXT="[APED GUARDRAIL Pipeline Coherence Check]\\n"
141
- CONTEXT+="Current phase: $CURRENT_PHASE\\n"
142
- CONTEXT+="Artifacts: brief=\${HAS_BRIEF}, prd=\${HAS_PRD}, epics=\${HAS_EPICS}\\n"
143
- CONTEXT+="\\nWarnings detected:\\n"
144
-
145
- for w in "\${WARNINGS[@]}"; do
146
- CONTEXT+=" ⚠ $w\\n"
147
- done
139
+ # ── Build context for Claude ──
140
+ CONTEXT="[APED GUARDRAIL] Pipeline coherence check.\\nCurrent phase: $CURRENT_PHASE | Artifacts: brief=$HAS_BRIEF, prd=$HAS_PRD, epics=$HAS_EPICS\\nWarnings:$WARNINGS"
148
141
 
149
- if [[ "$LANG" == "french" ]] || [[ "$LANG" == "français" ]]; then
150
- CONTEXT+="\\nINSTRUCTION: Signale ces avertissements à l'utilisateur en français AVANT d'exécuter quoi que ce soit. Explique le problème et propose le chemin correct dans le pipeline. Demande confirmation si l'utilisateur veut quand même continuer."
142
+ if [[ "$COMM_LANG" == "french" ]] || [[ "$COMM_LANG" == "français" ]]; then
143
+ CONTEXT="$CONTEXT\\n\\nINSTRUCTION: Signale ces avertissements a l utilisateur en francais AVANT d executer quoi que ce soit. Explique le probleme et propose le chemin correct. Demande confirmation pour continuer."
151
144
  else
152
- CONTEXT+="\\nINSTRUCTION: Report these warnings to the user BEFORE executing anything. Explain the issue and suggest the correct pipeline path. Ask for confirmation if the user wants to proceed anyway."
145
+ CONTEXT="$CONTEXT\\n\\nINSTRUCTION: Report these warnings to the user BEFORE executing anything. Explain the issue and suggest the correct pipeline path. Ask for confirmation to proceed."
153
146
  fi
154
147
 
155
- # Output JSON with addToPrompt does not block, but injects context
156
- printf '{"addToPrompt": "%s"}' "$CONTEXT"
148
+ # ── Output using official Claude Code hook format ──
149
+ # UserPromptSubmit: use hookSpecificOutput.additionalContext to inject context
150
+ # Does NOT block — injects context so Claude warns the user
151
+ cat << HOOKEOF
152
+ {
153
+ "hookSpecificOutput": {
154
+ "hookEventName": "UserPromptSubmit",
155
+ "additionalContext": "$(echo "$CONTEXT" | sed 's/"/\\\\"/g')"
156
+ }
157
+ }
158
+ HOOKEOF
157
159
  `,
158
160
  },
159
161
  {
@@ -92,8 +92,8 @@ for section in "\${REQUIRED_SECTIONS[@]}"; do
92
92
  fi
93
93
  done
94
94
 
95
- # Check FR format
96
- FR_LINES=$(grep -E '^FR[0-9]+:' "$FILE" 2>/dev/null || true)
95
+ # Check FR format — accepts: FR1:, - FR1:, **FR1:**, * FR1:, etc.
96
+ FR_LINES=$(grep -E '(^|[-*>[:space:]])\\*{0,2}FR[0-9]+\\*{0,2}\\s*:' "$FILE" 2>/dev/null || true)
97
97
  FR_COUNT=0
98
98
  if [[ -n "$FR_LINES" ]]; then
99
99
  FR_COUNT=$(echo "$FR_LINES" | wc -l | tr -d ' ')
@@ -111,7 +111,7 @@ fi
111
111
  ANTI_PATTERNS=("easy" "intuitive" "fast" "responsive" "simple" "multiple" "several" "various")
112
112
 
113
113
  for pattern in "\${ANTI_PATTERNS[@]}"; do
114
- MATCHES=$(grep -inE "^FR[0-9]+:.*\\b\${pattern}\\b" "$FILE" 2>/dev/null || true)
114
+ MATCHES=$(grep -inE 'FR[0-9]+.*:.*\\b\${pattern}\\b' "$FILE" 2>/dev/null || true)
115
115
  if [[ -n "$MATCHES" ]]; then
116
116
  ISSUES+=("ANTI-PATTERN '$pattern' found in FR: $MATCHES")
117
117
  fi