@arvorco/relentless 0.7.0 → 0.8.0

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.
Files changed (32) hide show
  1. package/.claude/commands/relentless.learn.md +52 -0
  2. package/.claude/skills/checklist/SKILL.md +9 -2
  3. package/.claude/skills/constitution/SKILL.md +11 -0
  4. package/.claude/skills/constitution/templates/constitution.md +0 -3
  5. package/.claude/skills/learn/SKILL.md +361 -0
  6. package/.claude/skills/learn/scripts/common.sh +46 -0
  7. package/.claude/skills/learn/scripts/extract-costs.sh +48 -0
  8. package/.claude/skills/learn/scripts/extract-errors.sh +47 -0
  9. package/.claude/skills/learn/scripts/extract-failures.sh +47 -0
  10. package/.claude/skills/learn/scripts/extract-learnings.sh +66 -0
  11. package/.claude/skills/learn/scripts/extract-patterns.sh +72 -0
  12. package/.claude/skills/learn/scripts/extract-session-context.sh +77 -0
  13. package/.claude/skills/learn/scripts/generate-stats.sh +129 -0
  14. package/.claude/skills/learn/templates/learning-proposal.md +105 -0
  15. package/.claude/skills/learn/templates/stats.md +69 -0
  16. package/.claude/skills/plan/SKILL.md +10 -3
  17. package/.claude/skills/specify/SKILL.md +9 -3
  18. package/.claude/skills/tasks/SKILL.md +10 -3
  19. package/.claude/skills/validators/SKILL.md +174 -0
  20. package/.claude/skills/validators/scripts/common.sh +182 -0
  21. package/.claude/skills/validators/scripts/validate-checklist.sh +190 -0
  22. package/.claude/skills/validators/scripts/validate-constitution.sh +111 -0
  23. package/.claude/skills/validators/scripts/validate-plan.sh +163 -0
  24. package/.claude/skills/validators/scripts/validate-prompt.sh +125 -0
  25. package/.claude/skills/validators/scripts/validate-spec.sh +214 -0
  26. package/.claude/skills/validators/scripts/validate-tasks.sh +179 -0
  27. package/.claude/skills/validators/scripts/validate.sh +295 -0
  28. package/CHANGELOG.md +53 -1
  29. package/package.json +1 -1
  30. package/relentless/constitution.md +0 -3
  31. package/src/execution/runner.ts +4 -0
  32. package/src/init/scaffolder.ts +2 -0
@@ -0,0 +1,52 @@
1
+ ---
2
+ description: Distill learnings from completed feature and propose amendments to constitution.md or prompt.md.
3
+ ---
4
+
5
+ Load the learn skill (`[skills_path]/learn/SKILL.md`) and follow its workflow.
6
+
7
+ **Usage:** `/relentless.learn [feature-name]`
8
+
9
+ **Context:** $ARGUMENTS
10
+
11
+ The learn skill will guide you through:
12
+
13
+ 1. **Extract Learnings** - Run CLI scripts to extract patterns, costs, failures, errors
14
+ 2. **Classify** - Categorize as Constitutional (governance) or Tactical (tech-specific)
15
+ 3. **Generate Proposals** - Create max 5 constitutional + 5 tactical proposals
16
+ 4. **Human Approval** - Present proposals for user review
17
+ 5. **Apply Amendments** - Update constitution.md or prompt.md with approved changes
18
+ 6. **Update Stats** - Regenerate aggregate stats
19
+
20
+ ## Quick Start
21
+
22
+ 1. Complete a feature (all stories `passes: true`)
23
+ 2. Run `/relentless.learn <feature-name>` to capture learnings
24
+ 3. Review and approve/modify/reject proposals
25
+ 4. Approved amendments are applied automatically
26
+
27
+ ## What Gets Updated
28
+
29
+ After approval:
30
+ - `constitution.md` - New MUST/SHOULD rules (version bumped)
31
+ - `prompt.md` - New patterns or tips
32
+ - `relentless/features/<feature>/learnings.md` - Learning log
33
+ - `relentless/stats.md` - Aggregate statistics
34
+
35
+ ## Prerequisites
36
+
37
+ - Feature must be complete (all stories done or skipped)
38
+ - `progress.txt` must exist with iteration learnings
39
+ - `constitution.md` and/or `prompt.md` must exist
40
+
41
+ ## Version Bumping
42
+
43
+ | Rule Type | Version Bump |
44
+ |-----------|--------------|
45
+ | MUST rule | MINOR (e.g., 2.0.0 → 2.1.0) |
46
+ | SHOULD rule | PATCH (e.g., 2.0.0 → 2.0.1) |
47
+
48
+ ## See Also
49
+
50
+ - `/relentless.constitution` - Create or update project governance
51
+ - `/relentless.implement` - Implement feature stories
52
+ - `relentless/stats.md` - View aggregate statistics
@@ -152,15 +152,22 @@ Ensure checklist includes items for constitution MUST rules:
152
152
 
153
153
  ---
154
154
 
155
- ## Step 6: Save & Report
155
+ ## Step 6: Save & Validate
156
156
 
157
157
  1. Save to `relentless/features/NNN-feature/checklist.md`
158
- 2. Report:
158
+ 2. **Run the validator to ensure checklist.md is correctly formatted:**
159
+ ```bash
160
+ .claude/skills/validators/scripts/validate-checklist.sh "relentless/features/NNN-feature/checklist.md"
161
+ ```
162
+ - If validation fails, fix the errors and re-run
163
+ - Warnings are acceptable but should be reviewed
164
+ 3. Report:
159
165
  - Total checklist items: N
160
166
  - Items per category
161
167
  - Mandatory items included: TDD ✓, Quality Gates ✓, Routing ✓
162
168
  - Constitution compliance items: N
163
169
  - Gaps identified: N
170
+ - Validation: PASS/FAIL
164
171
  - Next step: `/relentless.convert` (if not done) or `/relentless.analyze`
165
172
 
166
173
  ---
@@ -222,6 +222,17 @@ Save both files:
222
222
  - `relentless/constitution.md`
223
223
  - `relentless/prompt.md`
224
224
 
225
+ **Run the validators to ensure both files are correctly formatted:**
226
+ ```bash
227
+ # Validate constitution.md
228
+ .claude/skills/validators/scripts/validate-constitution.sh "relentless/constitution.md"
229
+
230
+ # Validate prompt.md
231
+ .claude/skills/validators/scripts/validate-prompt.sh "relentless/prompt.md"
232
+ ```
233
+ - If validation fails, fix the errors and re-run
234
+ - Warnings are acceptable but should be reviewed
235
+
225
236
  ---
226
237
 
227
238
  ## Step 6: Report
@@ -1,6 +1,3 @@
1
- <!-- TEMPLATE_VERSION: 2.1.0 -->
2
- <!-- LAST_UPDATED: 2026-01-20 -->
3
-
4
1
  # Project Constitution
5
2
 
6
3
  **Version:** 1.0.0
@@ -0,0 +1,361 @@
1
+ ---
2
+ name: learn
3
+ description: "Distill learnings from completed features and propose amendments to constitution.md or prompt.md. Use after feature completion. Triggers on: capture learnings, learn from feature, distill learnings, relentless learn."
4
+ ---
5
+
6
+ # Relentless Learning System
7
+
8
+ Capture learnings from completed features and propose amendments to improve future runs.
9
+
10
+ **Philosophy**: "Loop Ralph" - Create a feedback loop where each feature execution improves the system for future features.
11
+
12
+ ---
13
+
14
+ ## SpecKit Workflow
15
+
16
+ This skill is **optional** and runs after feature completion:
17
+
18
+ specify → plan → tasks → convert → analyze → implement → **(optional) learn**
19
+
20
+ Prerequisites:
21
+ - Feature must be complete (all stories `passes: true` or `skipped: true`)
22
+ - `progress.txt` must exist with iteration learnings
23
+ - `prd.json` must exist with execution data
24
+ - `constitution.md` and/or `prompt.md` must exist in `relentless/`
25
+
26
+ ---
27
+
28
+ ## The Job
29
+
30
+ 1. Extract learnings from completed feature (using CLI scripts)
31
+ 2. Classify each learning (Constitutional / Tactical / Discard)
32
+ 3. Generate proposals for human approval
33
+ 4. Apply approved amendments to constitution.md or prompt.md
34
+ 5. Save learning log to feature directory
35
+ 6. Update aggregate stats
36
+
37
+ ---
38
+
39
+ ## Step 0: Run Extraction Scripts
40
+
41
+ **IMPORTANT**: Use CLI scripts for extraction - do NOT read entire files into context.
42
+
43
+ Run the extraction scripts from `.claude/skills/learn/scripts/`:
44
+
45
+ ```bash
46
+ # Main extraction - runs all extractors
47
+ bash .claude/skills/learn/scripts/extract-learnings.sh relentless/features/<feature-name>
48
+
49
+ # Individual extractors (run by main script):
50
+ # - extract-patterns.sh - Patterns from progress.txt
51
+ # - extract-costs.sh - Cost accuracy from prd.json
52
+ # - extract-failures.sh - Failed checks from checklist.md
53
+ # - extract-errors.sh - Error patterns from progress.txt
54
+ ```
55
+
56
+ The output is compact JSON (~500 tokens max):
57
+
58
+ ```json
59
+ {
60
+ "patterns": ["Pattern 1: description", "Pattern 2: description"],
61
+ "costs": {"feature": "name", "estimated": 0.45, "actual": 0.52},
62
+ "failures": ["Unchecked item 1", "Unchecked item 2"],
63
+ "errors": ["Error context 1", "Error context 2"]
64
+ }
65
+ ```
66
+
67
+ **If more context is needed for a specific story:**
68
+
69
+ ```bash
70
+ # Extract session context for deeper investigation
71
+ bash .claude/skills/learn/scripts/extract-session-context.sh relentless/features/<feature-name> US-XXX
72
+ ```
73
+
74
+ ---
75
+
76
+ ## Step 1: Parse Extracted Data
77
+
78
+ Parse the JSON output from the extraction scripts:
79
+
80
+ 1. **Patterns**: Reusable learnings discovered during implementation
81
+ 2. **Costs**: Cost accuracy metrics (estimated vs actual)
82
+ 3. **Failures**: Unchecked checklist items (potential gaps)
83
+ 4. **Errors**: Error patterns that were fixed (potential rules)
84
+
85
+ Count and categorize:
86
+ - How many patterns were discovered?
87
+ - Was cost estimation accurate (>80%)?
88
+ - Are there unchecked checklist items (quality gaps)?
89
+ - What error patterns emerged?
90
+
91
+ ---
92
+
93
+ ## Step 2: Classify Learnings
94
+
95
+ For each learning, classify as:
96
+
97
+ | Type | Target | Criteria | Example |
98
+ |------|--------|----------|---------|
99
+ | **Constitutional** | constitution.md | Applies to ALL features, governance/quality/process, prevents significant issues | "Always export new types with implementation" |
100
+ | **Tactical** | prompt.md | Specific to task types or tech stack, workflow tips, common pitfalls | "Mock CLI calls in adapter tests" |
101
+ | **Discard** | None | One-time edge case, already covered, too specific | "Fixed typo in variable name" |
102
+
103
+ **Constitutional criteria** (becomes a MUST or SHOULD rule):
104
+ - Applies universally to all features
105
+ - Related to governance, quality, or process
106
+ - Prevents significant issues if violated
107
+ - Not already covered in constitution
108
+
109
+ **Tactical criteria** (becomes a prompt.md pattern):
110
+ - Specific to certain task types or tech stack
111
+ - Workflow tip or common pitfall
112
+ - Helps agents avoid repeated mistakes
113
+ - Not governance-level
114
+
115
+ **Discard criteria** (do not propose):
116
+ - One-time edge case
117
+ - Already covered by existing rules
118
+ - Too specific to be reusable
119
+ - Subjective preference
120
+
121
+ ---
122
+
123
+ ## Step 3: Generate Proposals
124
+
125
+ Generate **maximum 5 constitutional + 5 tactical proposals** per feature.
126
+
127
+ ### Constitutional Proposal Format:
128
+
129
+ ```markdown
130
+ ### PROP-C01: [Short Title]
131
+
132
+ **Target:** constitution.md > Principle [N] > [MUST|SHOULD]
133
+
134
+ **Amendment:**
135
+ > [1-2 sentence rule in imperative form]
136
+
137
+ **Evidence:**
138
+ > [Quote from progress.txt showing the issue]
139
+
140
+ **Classification:** Constitutional - [Rationale why this applies to all features]
141
+ ```
142
+
143
+ ### Tactical Proposal Format:
144
+
145
+ ```markdown
146
+ ### PROP-T01: [Short Title]
147
+
148
+ **Target:** prompt.md > [Section Name]
149
+
150
+ **Amendment:**
151
+ > [1-2 sentence tip or pattern]
152
+
153
+ **Evidence:**
154
+ > [Quote from progress.txt showing the context]
155
+
156
+ **Classification:** Tactical - [Rationale why this is task-specific]
157
+ ```
158
+
159
+ ### Discarded Learnings (include for transparency):
160
+
161
+ ```markdown
162
+ ### Discarded Learnings
163
+
164
+ | Learning | Reason |
165
+ |----------|--------|
166
+ | Fixed typo in variable name | One-time edge case |
167
+ | Used specific API endpoint | Already covered in docs |
168
+ ```
169
+
170
+ ---
171
+
172
+ ## Step 4: Present for Human Approval
173
+
174
+ Use the proposal template from `templates/learning-proposal.md` to format the output.
175
+
176
+ The proposal should include:
177
+ 1. **Feature Summary**: Name, stories, escalations, cost accuracy
178
+ 2. **Constitutional Proposals**: PROP-C01, PROP-C02, etc.
179
+ 3. **Tactical Proposals**: PROP-T01, PROP-T02, etc.
180
+ 4. **Discarded Learnings**: With reasons
181
+ 5. **Approval Request**: Ask user to approve, modify, or reject each proposal
182
+
183
+ **Ask the user:**
184
+ ```
185
+ Please review the proposals above. For each one:
186
+ - APPROVE: Apply as written
187
+ - MODIFY: Suggest changes
188
+ - REJECT: Do not apply
189
+
190
+ Which proposals do you approve?
191
+ ```
192
+
193
+ ---
194
+
195
+ ## Step 5: Apply Approved Amendments
196
+
197
+ For each approved proposal:
198
+
199
+ ### Constitutional Amendments (constitution.md):
200
+
201
+ 1. Read current version from constitution.md frontmatter
202
+ 2. Find the appropriate Principle section
203
+ 3. Add the new rule under MUST or SHOULD
204
+ 4. Update version number:
205
+ - **MUST rules**: Bump MINOR version (e.g., 2.0.0 → 2.1.0)
206
+ - **SHOULD rules**: Bump PATCH version (e.g., 2.0.0 → 2.0.1)
207
+ 5. Update `LAST_AMENDED_DATE` to today
208
+ 6. Add amendment note at top of file
209
+
210
+ **Amendment note format:**
211
+ ```markdown
212
+ <!-- Amendment: v2.1.0 - Added [rule title] from feature [feature-name] -->
213
+ ```
214
+
215
+ ### Tactical Amendments (prompt.md):
216
+
217
+ 1. Find the appropriate section in prompt.md
218
+ 2. Add the new pattern or tip
219
+ 3. Update "Generated" date at bottom
220
+ 4. If no appropriate section exists, create a new "## Learned Patterns" section
221
+
222
+ ---
223
+
224
+ ## Step 6: Save Learning Log
225
+
226
+ Create a learning log file in the feature directory:
227
+
228
+ **Path:** `relentless/features/<feature-name>/learnings.md`
229
+
230
+ ```markdown
231
+ # Learnings: [Feature Name]
232
+
233
+ **Extracted:** [date]
234
+ **Proposals Generated:** [count]
235
+ **Approved:** [count]
236
+ **Applied:** [count]
237
+
238
+ ## Constitutional Amendments Applied
239
+
240
+ - PROP-C01: [Title] → constitution.md v[version]
241
+
242
+ ## Tactical Amendments Applied
243
+
244
+ - PROP-T01: [Title] → prompt.md
245
+
246
+ ## Discarded Learnings
247
+
248
+ - [Learning] - [Reason]
249
+
250
+ ---
251
+
252
+ *Generated by /relentless.learn*
253
+ ```
254
+
255
+ ---
256
+
257
+ ## Step 7: Update Aggregate Stats
258
+
259
+ Run the stats generator to update `relentless/stats.md`:
260
+
261
+ ```bash
262
+ bash .claude/skills/learn/scripts/generate-stats.sh relentless
263
+ ```
264
+
265
+ This generates a human-readable report with:
266
+ - Total features, stories, completion rate
267
+ - Cost summary (estimated vs actual)
268
+ - Token usage
269
+ - Complexity distribution
270
+ - Escalation rate
271
+ - Model usage breakdown
272
+
273
+ The stats file is for human review, NOT loaded into agent context.
274
+
275
+ ---
276
+
277
+ ## Version Bumping Rules
278
+
279
+ | Amendment Type | Version Bump | Example |
280
+ |----------------|--------------|---------|
281
+ | MUST rule | MINOR | 2.0.0 → 2.1.0 |
282
+ | SHOULD rule | PATCH | 2.0.0 → 2.0.1 |
283
+ | Multiple rules | Highest bump applies | 2.0.0 → 2.1.0 if any MUST |
284
+
285
+ **Never bump MAJOR** - only `/relentless.constitution` can do that (for breaking governance changes).
286
+
287
+ ---
288
+
289
+ ## Common Patterns to Look For
290
+
291
+ ### Constitutional-Level Patterns:
292
+ - Type safety rules (export types with implementation)
293
+ - Testing patterns (TDD workflow, test structure)
294
+ - Error handling patterns (graceful degradation)
295
+ - Documentation requirements (JSDoc, README updates)
296
+ - Code quality patterns (zero-lint, typecheck)
297
+
298
+ ### Tactical-Level Patterns:
299
+ - Schema naming conventions (XxxSchema for Zod)
300
+ - Mock patterns for testing (mock CLI, mock adapters)
301
+ - File organization patterns (where to put new files)
302
+ - Common pitfalls for specific tech stack
303
+ - Performance optimizations
304
+
305
+ ### Patterns to Discard:
306
+ - Typo fixes
307
+ - One-time debugging steps
308
+ - Temporary workarounds (already removed)
309
+ - Personal preferences (formatting choices)
310
+ - Already documented patterns
311
+
312
+ ---
313
+
314
+ ## Example Session
315
+
316
+ **Input:**
317
+ ```
318
+ /relentless.learn 001-queued-prompts
319
+ ```
320
+
321
+ **Extraction Output:**
322
+ ```json
323
+ {
324
+ "patterns": [
325
+ "Atomic writes: Use temp file + rename for safety",
326
+ "Zod naming: Use XxxSchema to avoid no-redeclare"
327
+ ],
328
+ "costs": {"estimated": 0.45, "actual": 0.52, "accuracy": "87%"},
329
+ "failures": [],
330
+ "errors": ["ESLint no-redeclare on UserStory type - fixed with XxxSchema pattern"]
331
+ }
332
+ ```
333
+
334
+ **Generated Proposals:**
335
+ ```markdown
336
+ ### PROP-C01: Atomic Write Pattern
337
+
338
+ **Target:** constitution.md > Principle 11 (Data Safety) > SHOULD
339
+ **Amendment:**
340
+ > Use atomic writes (temp file + rename) when modifying files to prevent corruption.
341
+
342
+ **Evidence:**
343
+ > "Uses atomic writes (temp file + rename) to prevent corruption" - progress.txt
344
+
345
+ **Classification:** Constitutional - Applies to all file-modifying operations across features
346
+ ```
347
+
348
+ **User Response:** "APPROVE PROP-C01"
349
+
350
+ **Applied:** constitution.md v2.0.1 updated with new SHOULD rule
351
+
352
+ ---
353
+
354
+ ## Notes
355
+
356
+ - This skill is **opt-in** - only run after user decides to capture learnings
357
+ - Maximum 10 proposals per feature to avoid overwhelming the user
358
+ - Use extraction scripts to minimize context usage
359
+ - Human approval required for all amendments
360
+ - Stats file is for transparency, not agent context
361
+ - Session context extraction is available for deeper investigation when needed
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env bash
2
+ # common.sh - Shared functions for learning extraction scripts
3
+
4
+ # Detect available search tool (prefer ripgrep for speed)
5
+ detect_grep() {
6
+ if command -v rg >/dev/null 2>&1; then
7
+ echo "rg"
8
+ else
9
+ echo "grep"
10
+ fi
11
+ }
12
+
13
+ # Escape string for JSON
14
+ json_escape() {
15
+ local str="$1"
16
+ # Escape backslashes, quotes, and control characters
17
+ printf '%s' "$str" | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g' -e 's/\t/\\t/g' | tr '\n' ' '
18
+ }
19
+
20
+ # Convert array of strings to JSON array
21
+ to_json_array() {
22
+ local first=true
23
+ echo -n "["
24
+ while IFS= read -r line; do
25
+ [[ -z "$line" ]] && continue
26
+ if [[ "$first" == "true" ]]; then
27
+ first=false
28
+ else
29
+ echo -n ","
30
+ fi
31
+ echo -n "\"$(json_escape "$line")\""
32
+ done
33
+ echo "]"
34
+ }
35
+
36
+ # Extract feature name from path
37
+ get_feature_name() {
38
+ local path="$1"
39
+ basename "$path"
40
+ }
41
+
42
+ # Check if file exists and is readable
43
+ check_file() {
44
+ local path="$1"
45
+ [[ -f "$path" && -r "$path" ]]
46
+ }
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env bash
2
+ # extract-costs.sh - Extract cost data from prd.json
3
+ # Output: JSON object with cost statistics
4
+
5
+ set -euo pipefail
6
+
7
+ FEATURE_PATH="${1:-}"
8
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
9
+
10
+ source "$SCRIPT_DIR/common.sh"
11
+
12
+ if [[ -z "$FEATURE_PATH" ]]; then
13
+ echo "{}"
14
+ exit 0
15
+ fi
16
+
17
+ PRD_FILE="$FEATURE_PATH/prd.json"
18
+
19
+ if ! check_file "$PRD_FILE"; then
20
+ echo "{}"
21
+ exit 0
22
+ fi
23
+
24
+ # Check if jq is available
25
+ if ! command -v jq >/dev/null 2>&1; then
26
+ # Minimal fallback without jq
27
+ FEATURE_NAME=$(get_feature_name "$FEATURE_PATH")
28
+ echo "{\"feature\": \"$FEATURE_NAME\", \"note\": \"jq not available for detailed extraction\"}"
29
+ exit 0
30
+ fi
31
+
32
+ # Extract cost data using jq
33
+ jq '{
34
+ feature: (.branchName // .project // "unknown"),
35
+ totalStories: (.userStories | length),
36
+ completedStories: ([.userStories[] | select(.passes == true)] | length),
37
+ skippedStories: ([.userStories[] | select(.skipped == true)] | length),
38
+ storiesWithRouting: ([.userStories[] | select(.routing != null)] | length),
39
+ estimatedCost: ([.userStories[].routing.estimatedCost // 0] | add),
40
+ actualCost: ([.userStories[].execution.actualCost // 0] | add),
41
+ escalations: ([.userStories[] | select(.execution.attempts != null and .execution.attempts > 1)] | length),
42
+ complexityBreakdown: {
43
+ simple: ([.userStories[] | select(.routing.complexity == "simple")] | length),
44
+ medium: ([.userStories[] | select(.routing.complexity == "medium")] | length),
45
+ complex: ([.userStories[] | select(.routing.complexity == "complex")] | length),
46
+ expert: ([.userStories[] | select(.routing.complexity == "expert")] | length)
47
+ }
48
+ }' "$PRD_FILE" 2>/dev/null || echo "{}"
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env bash
2
+ # extract-errors.sh - Extract error patterns from progress.txt
3
+ # Output: JSON array of error-related lines
4
+
5
+ set -euo pipefail
6
+
7
+ FEATURE_PATH="${1:-}"
8
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
9
+
10
+ source "$SCRIPT_DIR/common.sh"
11
+
12
+ if [[ -z "$FEATURE_PATH" ]]; then
13
+ echo "[]"
14
+ exit 0
15
+ fi
16
+
17
+ PROGRESS_FILE="$FEATURE_PATH/progress.txt"
18
+
19
+ if ! check_file "$PROGRESS_FILE"; then
20
+ echo "[]"
21
+ exit 0
22
+ fi
23
+
24
+ GREP_CMD=$(detect_grep)
25
+
26
+ # Extract error-related lines (case-insensitive)
27
+ errors=()
28
+
29
+ if [[ "$GREP_CMD" == "rg" ]]; then
30
+ while IFS= read -r line; do
31
+ # Clean up the line
32
+ cleaned=$(echo "$line" | sed -E 's/^\s*[-*]\s*//' | tr -s ' ')
33
+ [[ -n "$cleaned" ]] && errors+=("$cleaned")
34
+ done < <(rg -i --no-filename '(error|failed|bug|fix|issue|problem|warning)' "$PROGRESS_FILE" 2>/dev/null | head -15)
35
+ else
36
+ while IFS= read -r line; do
37
+ cleaned=$(echo "$line" | sed -E 's/^\s*[-*]\s*//' | tr -s ' ')
38
+ [[ -n "$cleaned" ]] && errors+=("$cleaned")
39
+ done < <(grep -i -E '(error|failed|bug|fix|issue|problem|warning)' "$PROGRESS_FILE" 2>/dev/null | head -15)
40
+ fi
41
+
42
+ # Deduplicate and output as JSON array
43
+ if [[ ${#errors[@]} -eq 0 ]]; then
44
+ echo "[]"
45
+ else
46
+ printf '%s\n' "${errors[@]}" | sort -u | head -10 | to_json_array
47
+ fi
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env bash
2
+ # extract-failures.sh - Extract failed checks from checklist.md
3
+ # Output: JSON array of unchecked items
4
+
5
+ set -euo pipefail
6
+
7
+ FEATURE_PATH="${1:-}"
8
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
9
+
10
+ source "$SCRIPT_DIR/common.sh"
11
+
12
+ if [[ -z "$FEATURE_PATH" ]]; then
13
+ echo "[]"
14
+ exit 0
15
+ fi
16
+
17
+ CHECKLIST_FILE="$FEATURE_PATH/checklist.md"
18
+
19
+ if ! check_file "$CHECKLIST_FILE"; then
20
+ echo "[]"
21
+ exit 0
22
+ fi
23
+
24
+ GREP_CMD=$(detect_grep)
25
+
26
+ # Extract unchecked items (- [ ] or * [ ])
27
+ failures=()
28
+
29
+ if [[ "$GREP_CMD" == "rg" ]]; then
30
+ while IFS= read -r line; do
31
+ # Clean up the line (remove checkbox prefix)
32
+ cleaned=$(echo "$line" | sed -E 's/^\s*[-*]\s*\[ \]\s*//')
33
+ [[ -n "$cleaned" ]] && failures+=("$cleaned")
34
+ done < <(rg --no-filename '^\s*[-*]\s*\[ \]' "$CHECKLIST_FILE" 2>/dev/null | head -10)
35
+ else
36
+ while IFS= read -r line; do
37
+ cleaned=$(echo "$line" | sed -E 's/^\s*[-*]\s*\[ \]\s*//')
38
+ [[ -n "$cleaned" ]] && failures+=("$cleaned")
39
+ done < <(grep -E '^\s*[-*]\s*\[ \]' "$CHECKLIST_FILE" 2>/dev/null | head -10)
40
+ fi
41
+
42
+ # Output as JSON array
43
+ if [[ ${#failures[@]} -eq 0 ]]; then
44
+ echo "[]"
45
+ else
46
+ printf '%s\n' "${failures[@]}" | to_json_array
47
+ fi