@arvorco/relentless 0.4.4 → 0.5.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.
- package/.claude/skills/constitution/templates/prompt.md +35 -45
- package/.claude/skills/convert/SKILL.md +62 -9
- package/.claude/skills/tasks/SKILL.md +39 -6
- package/CHANGELOG.md +39 -2
- package/bin/relentless.ts +124 -2
- package/package.json +1 -1
- package/src/execution/context-builder.ts +417 -0
- package/src/execution/index.ts +1 -0
- package/src/execution/runner.ts +61 -16
- package/src/prd/index.ts +1 -0
- package/src/prd/parser.ts +305 -13
- package/src/prd/validator.ts +553 -0
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
<!-- TEMPLATE_VERSION: 2.1.0 -->
|
|
2
|
-
<!-- LAST_UPDATED: 2026-01-20 -->
|
|
3
|
-
|
|
4
1
|
# Relentless Agent Instructions
|
|
5
2
|
|
|
6
3
|
You are an autonomous coding agent orchestrated by Relentless. Follow these instructions exactly.
|
|
@@ -12,34 +9,47 @@ You are an autonomous coding agent orchestrated by Relentless. Follow these inst
|
|
|
12
9
|
|
|
13
10
|
---
|
|
14
11
|
|
|
15
|
-
##
|
|
12
|
+
## Context Already Provided
|
|
13
|
+
|
|
14
|
+
The orchestrator sends you optimized context in each prompt:
|
|
15
|
+
|
|
16
|
+
- **Constitution** - Project principles and governance (full)
|
|
17
|
+
- **spec.md** - Feature specification (full)
|
|
18
|
+
- **plan.md** - Technical implementation plan (full)
|
|
19
|
+
- **Current story** - Your assigned story from tasks.md with dependencies
|
|
20
|
+
- **Relevant checklist** - Filtered checklist items for your story
|
|
21
|
+
|
|
22
|
+
**You do NOT need to read these files separately** - they're already in your context.
|
|
23
|
+
|
|
24
|
+
Only read files if you need additional details not provided (e.g., examining existing code patterns).
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## ONE Story Per Iteration (CRITICAL)
|
|
16
29
|
|
|
17
|
-
**
|
|
30
|
+
**You MUST work on exactly ONE user story per iteration.**
|
|
18
31
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
4. **`checklist.md`** - Review quality criteria you must satisfy
|
|
23
|
-
5. **`prd.json`** - Find your story and check routing metadata
|
|
32
|
+
- Do NOT try to complete multiple stories in a single pass
|
|
33
|
+
- Do NOT batch stories together for "efficiency"
|
|
34
|
+
- Do NOT skip ahead to other stories after completing one
|
|
24
35
|
|
|
25
|
-
|
|
36
|
+
After completing ONE story, end your turn. The orchestrator will assign the next story.
|
|
26
37
|
|
|
27
38
|
---
|
|
28
39
|
|
|
29
40
|
## Your Task (Per Iteration)
|
|
30
41
|
|
|
31
42
|
1. Check you're on the correct branch from PRD `branchName`
|
|
32
|
-
2.
|
|
33
|
-
3.
|
|
34
|
-
4.
|
|
35
|
-
5.
|
|
36
|
-
6.
|
|
37
|
-
7.
|
|
38
|
-
8.
|
|
39
|
-
9.
|
|
40
|
-
10.
|
|
41
|
-
11.
|
|
42
|
-
12. Append progress to `progress.txt`
|
|
43
|
+
2. Review the story context already provided in this prompt
|
|
44
|
+
3. Review existing code to understand patterns
|
|
45
|
+
4. **Write tests FIRST** (TDD is mandatory)
|
|
46
|
+
5. Verify tests FAIL before implementation
|
|
47
|
+
6. Implement the story to make tests PASS
|
|
48
|
+
7. Run ALL quality checks (typecheck, lint, test)
|
|
49
|
+
8. If ALL checks pass, commit: `feat: [Story ID] - [Story Title]`
|
|
50
|
+
9. Update prd.json: set `passes: true`
|
|
51
|
+
10. Append progress to `progress.txt`
|
|
52
|
+
11. **STOP** - Do not continue to next story
|
|
43
53
|
|
|
44
54
|
---
|
|
45
55
|
|
|
@@ -140,9 +150,6 @@ APPEND to `progress.txt` after each story:
|
|
|
140
150
|
- Patterns discovered
|
|
141
151
|
- Gotchas for future iterations
|
|
142
152
|
|
|
143
|
-
---
|
|
144
|
-
```
|
|
145
|
-
|
|
146
153
|
---
|
|
147
154
|
|
|
148
155
|
## Stop Condition
|
|
@@ -158,26 +165,9 @@ Otherwise, end normally (next iteration continues with next story).
|
|
|
158
165
|
|
|
159
166
|
---
|
|
160
167
|
|
|
161
|
-
## SpecKit Workflow Reference
|
|
162
|
-
|
|
163
|
-
The full Relentless workflow is:
|
|
164
|
-
|
|
165
|
-
```
|
|
166
|
-
/relentless.specify → /relentless.plan → /relentless.tasks → /relentless.convert → /relentless.analyze → /relentless.implement
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
Each step generates an artifact in `relentless/features/<feature>/`:
|
|
170
|
-
- `spec.md` - Feature specification
|
|
171
|
-
- `plan.md` - Technical implementation plan
|
|
172
|
-
- `tasks.md` - User stories with acceptance criteria
|
|
173
|
-
- `checklist.md` - Quality validation checklist
|
|
174
|
-
- `prd.json` - Machine-readable PRD with routing
|
|
175
|
-
|
|
176
|
-
---
|
|
177
|
-
|
|
178
168
|
## Common Mistakes to Avoid
|
|
179
169
|
|
|
180
|
-
1. **
|
|
170
|
+
1. **Doing multiple stories** - Complete exactly ONE story, then STOP
|
|
181
171
|
2. **Writing code before tests** - TDD is mandatory, tests come FIRST
|
|
182
172
|
3. **Ignoring lint warnings** - Zero warnings required, not just zero errors
|
|
183
173
|
4. **Marking incomplete stories done** - Only mark `passes: true` when ALL criteria met
|
|
@@ -198,5 +188,5 @@ Run `/relentless.constitution` to generate a personalized prompt.
|
|
|
198
188
|
|
|
199
189
|
---
|
|
200
190
|
|
|
201
|
-
**Template Version:** 2.
|
|
202
|
-
**Compatible with:** Relentless v0.
|
|
191
|
+
**Template Version:** 2.1.0
|
|
192
|
+
**Compatible with:** Relentless v0.5.0+
|
|
@@ -14,10 +14,12 @@ Convert user stories from tasks.md into prd.json format WITH automatic routing c
|
|
|
14
14
|
|
|
15
15
|
## The Job
|
|
16
16
|
|
|
17
|
+
**⚠️ CRITICAL: This skill requires executing the `relentless convert` CLI command. Do NOT generate prd.json manually!**
|
|
18
|
+
|
|
17
19
|
1. Locate tasks.md in the current feature directory
|
|
18
20
|
2. Validate story structure, dependencies, and TDD compliance
|
|
19
21
|
3. Preview conversion (show story count, dependency chain)
|
|
20
|
-
4.
|
|
22
|
+
4. **EXECUTE the CLI command:** `relentless convert relentless/features/NNN-feature/tasks.md --feature <feature-name>`
|
|
21
23
|
5. Validate the generated prd.json HAS routing metadata
|
|
22
24
|
6. Display routing summary (cost estimates per story)
|
|
23
25
|
7. Report next step
|
|
@@ -56,16 +58,27 @@ If tasks.md doesn't exist, suggest running `/relentless.tasks` first.
|
|
|
56
58
|
|
|
57
59
|
## Step 2: Validate tasks.md Structure
|
|
58
60
|
|
|
59
|
-
|
|
61
|
+
The CLI now **automatically validates** tasks.md before conversion. You can also validate manually:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
relentless validate relentless/features/NNN-feature/tasks.md
|
|
65
|
+
```
|
|
60
66
|
|
|
61
|
-
###
|
|
67
|
+
### Validation Checks
|
|
62
68
|
|
|
69
|
+
The validator checks for:
|
|
63
70
|
- [ ] Each story has unique ID (US-XXX format)
|
|
64
|
-
- [ ] Each story has acceptance criteria
|
|
65
|
-
- [ ]
|
|
66
|
-
- [ ] Dependencies reference valid story IDs
|
|
71
|
+
- [ ] Each story has acceptance criteria (after filtering)
|
|
72
|
+
- [ ] Dependencies reference existing stories
|
|
67
73
|
- [ ] No circular dependencies
|
|
68
|
-
- [ ]
|
|
74
|
+
- [ ] No underscore format in dependencies (US_001 should be US-001)
|
|
75
|
+
|
|
76
|
+
### Automatic Filtering (with Warnings)
|
|
77
|
+
|
|
78
|
+
The following criteria are automatically filtered during conversion:
|
|
79
|
+
- **Standalone file paths**: `` `src/file.ts` `` → Add context: "`src/file.ts` contains X"
|
|
80
|
+
- **Section markers**: `**Files:**` → Move outside acceptance criteria section
|
|
81
|
+
- **Short text**: Less than 3 characters
|
|
69
82
|
|
|
70
83
|
### Example Valid Story
|
|
71
84
|
|
|
@@ -78,6 +91,7 @@ Before conversion, validate the tasks.md file:
|
|
|
78
91
|
- [ ] POST /api/register endpoint exists
|
|
79
92
|
- [ ] Email validation works
|
|
80
93
|
- [ ] Password is hashed
|
|
94
|
+
- [ ] `src/auth/register.ts` contains the registration handler
|
|
81
95
|
- [ ] Unit tests pass
|
|
82
96
|
- [ ] Integration test passes
|
|
83
97
|
|
|
@@ -86,16 +100,32 @@ Before conversion, validate the tasks.md file:
|
|
|
86
100
|
**Priority:** 1
|
|
87
101
|
```
|
|
88
102
|
|
|
103
|
+
### Example Validation Output
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
Validating tasks.md...
|
|
107
|
+
|
|
108
|
+
⚠️ 2 validation warning(s):
|
|
109
|
+
[FILTERED_CRITERIA]
|
|
110
|
+
2 acceptance criteria will be filtered during conversion
|
|
111
|
+
|
|
112
|
+
📝 2 criteria will be filtered during conversion
|
|
113
|
+
US-003: "`src/queue/types.ts`"
|
|
114
|
+
US-004: "**"
|
|
115
|
+
```
|
|
116
|
+
|
|
89
117
|
---
|
|
90
118
|
|
|
91
119
|
## Step 3: Run Conversion (with Routing)
|
|
92
120
|
|
|
93
|
-
Execute the
|
|
121
|
+
**⚠️ IMPORTANT: Execute this bash command using the Bash tool. Do NOT generate prd.json manually!**
|
|
94
122
|
|
|
95
123
|
```bash
|
|
96
|
-
relentless convert relentless/features
|
|
124
|
+
relentless convert relentless/features/NNN-feature/tasks.md --feature <feature-name>
|
|
97
125
|
```
|
|
98
126
|
|
|
127
|
+
Replace `NNN-feature` with the actual feature directory name (e.g., `001-user-auth`).
|
|
128
|
+
|
|
99
129
|
### Options
|
|
100
130
|
|
|
101
131
|
| Flag | Description |
|
|
@@ -228,6 +258,25 @@ The conversion was run with `--skip-routing`. Re-run:
|
|
|
228
258
|
relentless convert relentless/features/<feature>/tasks.md --feature <feature-name>
|
|
229
259
|
```
|
|
230
260
|
|
|
261
|
+
### "Validation failed"
|
|
262
|
+
|
|
263
|
+
The tasks.md has format issues. Run validation to see details:
|
|
264
|
+
```bash
|
|
265
|
+
relentless validate relentless/features/<feature>/tasks.md
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Common issues:
|
|
269
|
+
- **DUPLICATE_STORY_ID**: Two stories have the same ID
|
|
270
|
+
- **MISSING_DEPENDENCY**: A story depends on non-existent story ID
|
|
271
|
+
- **CIRCULAR_DEPENDENCY**: Stories form a dependency loop
|
|
272
|
+
|
|
273
|
+
### "Criteria will be filtered"
|
|
274
|
+
|
|
275
|
+
Some acceptance criteria don't meet format requirements. Fix by:
|
|
276
|
+
- Adding context to file paths: `` `src/file.ts` `` → "`src/file.ts` contains X"
|
|
277
|
+
- Moving section markers outside acceptance criteria
|
|
278
|
+
- Writing longer, more descriptive criteria
|
|
279
|
+
|
|
231
280
|
### "Invalid dependency"
|
|
232
281
|
|
|
233
282
|
A story references a non-existent story ID. Check the `Dependencies:` line.
|
|
@@ -236,6 +285,10 @@ A story references a non-existent story ID. Check the `Dependencies:` line.
|
|
|
236
285
|
|
|
237
286
|
Stories reference each other in a cycle. Example: US-001 depends on US-002, and US-002 depends on US-001.
|
|
238
287
|
|
|
288
|
+
### "Dependency uses underscore format"
|
|
289
|
+
|
|
290
|
+
Use dashes in story IDs: `US-001` not `US_001`.
|
|
291
|
+
|
|
239
292
|
---
|
|
240
293
|
|
|
241
294
|
## Notes
|
|
@@ -182,6 +182,32 @@ Check that:
|
|
|
182
182
|
|
|
183
183
|
---
|
|
184
184
|
|
|
185
|
+
## Step 6.5: Pre-Conversion Validation
|
|
186
|
+
|
|
187
|
+
Before saving and converting, validate the format manually:
|
|
188
|
+
|
|
189
|
+
**Story ID Format:**
|
|
190
|
+
- [ ] Every story uses `US-XXX` format (e.g., `US-001`, not `Story 1`)
|
|
191
|
+
- [ ] Story IDs are unique and sequential
|
|
192
|
+
|
|
193
|
+
**Acceptance Criteria Format:**
|
|
194
|
+
- [ ] Criteria are full sentences, not just file paths
|
|
195
|
+
- [ ] File paths include context (e.g., "`src/queue/types.ts` contains Zod schemas")
|
|
196
|
+
- [ ] No standalone file paths like `` `src/file.ts` ``
|
|
197
|
+
|
|
198
|
+
**Dependencies Format:**
|
|
199
|
+
- [ ] Dependencies use `US-XXX` with dashes, not underscores
|
|
200
|
+
- [ ] Example: `**Dependencies:** US-001, US-002` (correct)
|
|
201
|
+
- [ ] Example: `**Dependencies:** US_001` (incorrect - will warn)
|
|
202
|
+
|
|
203
|
+
**Common Mistakes to Avoid:**
|
|
204
|
+
- ❌ `- [ ] \`src/file.ts\`` (file path only - will be filtered)
|
|
205
|
+
- ✅ `- [ ] \`src/file.ts\` contains the queue interface`
|
|
206
|
+
- ❌ `**Files:**` inside acceptance criteria (will end criteria parsing)
|
|
207
|
+
- ✅ Put **Files:** section after acceptance criteria
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
185
211
|
## Step 7: Save & Report
|
|
186
212
|
|
|
187
213
|
1. Save to `relentless/features/NNN-feature/tasks.md`
|
|
@@ -195,23 +221,30 @@ Check that:
|
|
|
195
221
|
|
|
196
222
|
## Step 8: Auto-Convert to prd.json
|
|
197
223
|
|
|
198
|
-
|
|
224
|
+
**CRITICAL: You MUST execute the CLI command below. Do NOT generate prd.json manually.**
|
|
225
|
+
|
|
226
|
+
After tasks.md is saved, run this command to convert to prd.json with routing:
|
|
199
227
|
|
|
200
228
|
```bash
|
|
201
229
|
relentless convert relentless/features/NNN-feature/tasks.md --feature <feature-name>
|
|
202
230
|
```
|
|
203
231
|
|
|
204
|
-
|
|
232
|
+
**⚠️ IMPORTANT:** Execute this bash command using the Bash tool. Do NOT:
|
|
233
|
+
- Generate the prd.json file yourself
|
|
234
|
+
- Skip this step
|
|
235
|
+
- Use any other method
|
|
236
|
+
|
|
237
|
+
The CLI will:
|
|
205
238
|
1. Parse tasks.md and validate structure
|
|
206
239
|
2. Classify complexity for each story
|
|
207
240
|
3. Route to optimal harness/model per story
|
|
208
241
|
4. Generate prd.json with routing metadata
|
|
209
242
|
5. Copy to prd.md for reference
|
|
210
243
|
|
|
211
|
-
**
|
|
212
|
-
-
|
|
213
|
-
-
|
|
214
|
-
- Confirm prd.json
|
|
244
|
+
**After running the command, report:**
|
|
245
|
+
- The routing table from CLI output (story → complexity → harness/model → cost)
|
|
246
|
+
- Total estimated cost
|
|
247
|
+
- Confirm prd.json was created
|
|
215
248
|
|
|
216
249
|
**Optional but Recommended:** `/relentless.checklist`
|
|
217
250
|
- Generates validation checklist with quality gates
|
package/CHANGELOG.md
CHANGED
|
@@ -5,7 +5,42 @@ All notable changes to Relentless will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
-
## [
|
|
8
|
+
## [0.5.0](https://github.com/ArvorCo/Relentless/releases/tag/v0.5.0) - 2026-01-23
|
|
9
|
+
|
|
10
|
+
### Major Features
|
|
11
|
+
|
|
12
|
+
#### Optimized Context Builder - Save ~40% Tokens Per Iteration
|
|
13
|
+
- **Task-specific context extraction**: Instead of sending entire files, now extracts only relevant content
|
|
14
|
+
- `tasks.md`: Only current story + dependency sections (~84% reduction)
|
|
15
|
+
- `checklist.md`: Only story-specific + Constitution + general items (~80% reduction)
|
|
16
|
+
- **New module**: `src/execution/context-builder.ts` with extraction functions:
|
|
17
|
+
- `extractStoryFromTasks()` - Extract current story and dependencies
|
|
18
|
+
- `filterChecklistForStory()` - Filter checklist by story ID
|
|
19
|
+
- `extractStoryMetadata()` - Extract story metadata from PRD
|
|
20
|
+
- `buildProgressSummary()` - Build concise progress summary
|
|
21
|
+
- `formatStoryContext()` / `formatFilteredChecklist()` - Formatters for prompt
|
|
22
|
+
- **Token savings**: ~40% reduction in prompt size (from ~7,600 to ~4,500 tokens)
|
|
23
|
+
- **Backward compatible**: Falls back to full file loading when no story context available
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
- **prompt.md template v2.1.0**: Updated to reflect optimized context delivery
|
|
27
|
+
- Added "Context Already Provided" section explaining what's sent in prompts
|
|
28
|
+
- Added "ONE Story Per Iteration" critical rule to prevent over-eager agents
|
|
29
|
+
- Removed redundant "read these files" instructions (context is pre-loaded)
|
|
30
|
+
- Updated task workflow to emphasize STOP after one story
|
|
31
|
+
|
|
32
|
+
### Added
|
|
33
|
+
- 23 new unit tests for context-builder module
|
|
34
|
+
- Integration with existing runner for seamless optimization
|
|
35
|
+
|
|
36
|
+
## [0.4.5](https://github.com/ArvorCo/Relentless/releases/tag/v0.4.5) - 2026-01-21
|
|
37
|
+
|
|
38
|
+
### Fixed
|
|
39
|
+
- **Registry**: Corrected Claude Sonnet 4.5 model ID from `claude-sonnet-4-5-20251020` to `claude-sonnet-4-5-20250929`
|
|
40
|
+
- This was causing 404 errors when using the default model
|
|
41
|
+
- **Skills**: Fixed `relentless.tasks` and `relentless.convert` to enforce CLI execution
|
|
42
|
+
- Skills now explicitly instruct to run `relentless convert` command via Bash
|
|
43
|
+
- Prevents LLM from generating prd.json manually instead of using the CLI
|
|
9
44
|
|
|
10
45
|
## [0.4.3] - 2026-01-20
|
|
11
46
|
|
|
@@ -411,7 +446,9 @@ Relentless evolved from the [Ralph Wiggum Pattern](https://ghuntley.com/ralph/)
|
|
|
411
446
|
- **License**: MIT
|
|
412
447
|
- **Inspiration**: [Ralph Wiggum Pattern](https://ghuntley.com/ralph/) by Geoffrey Huntley
|
|
413
448
|
|
|
414
|
-
[Unreleased]: https://github.com/ArvorCo/Relentless/compare/v0.
|
|
449
|
+
[Unreleased]: https://github.com/ArvorCo/Relentless/compare/v0.5.0...HEAD
|
|
450
|
+
[0.5.0]: https://github.com/ArvorCo/Relentless/compare/v0.4.5...v0.5.0
|
|
451
|
+
[0.4.5]: https://github.com/ArvorCo/Relentless/compare/v0.4.3...v0.4.5
|
|
415
452
|
[0.4.3]: https://github.com/ArvorCo/Relentless/compare/v0.4.2...v0.4.3
|
|
416
453
|
[0.4.2]: https://github.com/ArvorCo/Relentless/compare/v0.4.0...v0.4.2
|
|
417
454
|
[0.4.0]: https://github.com/ArvorCo/Relentless/compare/v0.3.0...v0.4.0
|
package/bin/relentless.ts
CHANGED
|
@@ -220,6 +220,7 @@ program
|
|
|
220
220
|
.option("--auto-number", "Auto-number the feature directory (e.g., 001-feature-name)", false)
|
|
221
221
|
.option("--with-checklist", "Merge checklist items into acceptance criteria", false)
|
|
222
222
|
.option("--skip-routing", "Skip automatic routing classification (not recommended)", false)
|
|
223
|
+
.option("--skip-validation", "Skip validation before conversion (advanced users only)", false)
|
|
223
224
|
.option("--mode <mode>", `Cost optimization mode for routing (${VALID_MODES.join(", ")})`, "good")
|
|
224
225
|
.action(async (tasksMd, options) => {
|
|
225
226
|
if (!existsSync(tasksMd)) {
|
|
@@ -233,6 +234,62 @@ program
|
|
|
233
234
|
process.exit(1);
|
|
234
235
|
}
|
|
235
236
|
|
|
237
|
+
// Read tasks.md content first (needed for validation)
|
|
238
|
+
const tasksContent = await Bun.file(tasksMd).text();
|
|
239
|
+
|
|
240
|
+
// VALIDATION PHASE (unless --skip-validation is set)
|
|
241
|
+
if (!options.skipValidation) {
|
|
242
|
+
const { validateTasksMarkdown } = await import("../src/prd/validator");
|
|
243
|
+
|
|
244
|
+
console.log(chalk.dim(`Validating ${tasksMd}...`));
|
|
245
|
+
const validationResult = validateTasksMarkdown(tasksContent);
|
|
246
|
+
|
|
247
|
+
// Show validation errors and abort if any
|
|
248
|
+
if (validationResult.errors.length > 0) {
|
|
249
|
+
console.log(chalk.red("\n❌ Validation failed:\n"));
|
|
250
|
+
for (const error of validationResult.errors) {
|
|
251
|
+
const location = error.line ? ` (line ${error.line})` : "";
|
|
252
|
+
console.log(chalk.red(` [${error.code}]${location}`));
|
|
253
|
+
console.log(chalk.red(` ${error.message}`));
|
|
254
|
+
if (error.suggestion) {
|
|
255
|
+
console.log(chalk.dim(` 💡 ${error.suggestion}`));
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
console.log("");
|
|
259
|
+
console.log(chalk.dim("Fix the errors above and try again."));
|
|
260
|
+
console.log(chalk.dim("Use --skip-validation to bypass (not recommended)."));
|
|
261
|
+
process.exit(1);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Show warnings but continue
|
|
265
|
+
if (validationResult.warnings.length > 0) {
|
|
266
|
+
console.log(chalk.yellow(`\n⚠️ ${validationResult.warnings.length} validation warning(s):`));
|
|
267
|
+
for (const warning of validationResult.warnings) {
|
|
268
|
+
const location = warning.line ? ` (line ${warning.line})` : "";
|
|
269
|
+
console.log(chalk.yellow(` [${warning.code}]${location}`));
|
|
270
|
+
console.log(chalk.dim(` ${warning.message}`));
|
|
271
|
+
}
|
|
272
|
+
console.log("");
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Show filtered criteria summary
|
|
276
|
+
if (validationResult.filteredCriteria.length > 0) {
|
|
277
|
+
console.log(chalk.dim(` 📝 ${validationResult.filteredCriteria.length} criteria will be filtered during conversion`));
|
|
278
|
+
if (validationResult.filteredCriteria.length <= 5) {
|
|
279
|
+
for (const fc of validationResult.filteredCriteria) {
|
|
280
|
+
console.log(chalk.dim(` ${fc.storyId}: "${fc.text.substring(0, 50)}${fc.text.length > 50 ? "..." : ""}"`));
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
console.log("");
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Show stories with no criteria warning
|
|
287
|
+
if (validationResult.summary.storiesWithNoCriteria.length > 0) {
|
|
288
|
+
console.log(chalk.yellow(` ⚠️ Stories with no valid criteria: ${validationResult.summary.storiesWithNoCriteria.join(", ")}`));
|
|
289
|
+
console.log("");
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
236
293
|
// Determine final feature name (with auto-number if requested)
|
|
237
294
|
let finalFeatureName = options.feature;
|
|
238
295
|
if (options.autoNumber) {
|
|
@@ -261,8 +318,7 @@ program
|
|
|
261
318
|
|
|
262
319
|
console.log(chalk.dim(`Converting ${tasksMd}...`));
|
|
263
320
|
|
|
264
|
-
//
|
|
265
|
-
const tasksContent = await Bun.file(tasksMd).text();
|
|
321
|
+
// Parse the markdown (content already read above)
|
|
266
322
|
const parsed = parsePRDMarkdown(tasksContent);
|
|
267
323
|
|
|
268
324
|
// Optionally merge checklist items
|
|
@@ -725,6 +781,72 @@ program
|
|
|
725
781
|
}
|
|
726
782
|
});
|
|
727
783
|
|
|
784
|
+
// Validate command - validate tasks.md before conversion
|
|
785
|
+
program
|
|
786
|
+
.command("validate <tasksMd>")
|
|
787
|
+
.description("Validate tasks.md file before conversion to prd.json")
|
|
788
|
+
.option("-d, --dir <path>", "Project directory", process.cwd())
|
|
789
|
+
.option("--json", "Output validation results as JSON", false)
|
|
790
|
+
.option("--strict", "Treat warnings as errors", false)
|
|
791
|
+
.option("--verbose", "Show all filtered criteria details", false)
|
|
792
|
+
.action(async (tasksMd, options) => {
|
|
793
|
+
const { validateTasksMarkdown, formatValidationResult, formatValidationResultJSON } = await import("../src/prd/validator");
|
|
794
|
+
|
|
795
|
+
if (!existsSync(tasksMd)) {
|
|
796
|
+
console.error(chalk.red(`File not found: ${tasksMd}`));
|
|
797
|
+
process.exit(1);
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
const content = await Bun.file(tasksMd).text();
|
|
801
|
+
const result = validateTasksMarkdown(content);
|
|
802
|
+
|
|
803
|
+
// Check strict mode
|
|
804
|
+
const hasIssues = result.errors.length > 0 || (options.strict && result.warnings.length > 0);
|
|
805
|
+
|
|
806
|
+
if (options.json) {
|
|
807
|
+
console.log(formatValidationResultJSON(result));
|
|
808
|
+
} else {
|
|
809
|
+
console.log(chalk.bold("\n📋 Tasks.md Validation\n"));
|
|
810
|
+
console.log(chalk.dim(`File: ${tasksMd}`));
|
|
811
|
+
console.log("");
|
|
812
|
+
|
|
813
|
+
console.log(formatValidationResult(result));
|
|
814
|
+
|
|
815
|
+
// Show verbose filtered criteria if requested
|
|
816
|
+
if (options.verbose && result.filteredCriteria.length > 10) {
|
|
817
|
+
console.log("ALL FILTERED CRITERIA:");
|
|
818
|
+
for (const fc of result.filteredCriteria) {
|
|
819
|
+
const location = fc.line ? ` (line ${fc.line})` : "";
|
|
820
|
+
console.log(` ${fc.storyId}${location}: "${fc.text}"`);
|
|
821
|
+
console.log(` Reason: ${fc.reason}`);
|
|
822
|
+
if (fc.suggestion) {
|
|
823
|
+
console.log(` 💡 ${fc.suggestion}`);
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
console.log("");
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
// Final summary
|
|
830
|
+
if (hasIssues) {
|
|
831
|
+
if (options.strict && result.warnings.length > 0 && result.errors.length === 0) {
|
|
832
|
+
console.log(chalk.red(`❌ Validation failed (strict mode: ${result.warnings.length} warnings treated as errors)\n`));
|
|
833
|
+
} else {
|
|
834
|
+
console.log(chalk.red(`❌ Validation failed with ${result.errors.length} error(s)\n`));
|
|
835
|
+
}
|
|
836
|
+
console.log(chalk.dim("Fix the errors above before running: relentless convert"));
|
|
837
|
+
} else if (result.warnings.length > 0) {
|
|
838
|
+
console.log(chalk.yellow(`⚠️ Validation passed with ${result.warnings.length} warning(s)\n`));
|
|
839
|
+
console.log(chalk.dim("Warnings won't block conversion, but consider addressing them."));
|
|
840
|
+
console.log(chalk.dim("Next step: relentless convert " + tasksMd + " --feature <name>"));
|
|
841
|
+
} else {
|
|
842
|
+
console.log(chalk.green("✅ Validation passed - ready to convert\n"));
|
|
843
|
+
console.log(chalk.dim("Next step: relentless convert " + tasksMd + " --feature <name>"));
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
process.exit(hasIssues ? 1 : 0);
|
|
848
|
+
});
|
|
849
|
+
|
|
728
850
|
// Issues command
|
|
729
851
|
program
|
|
730
852
|
.command("issues")
|