@arvorco/relentless 0.4.5 → 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 +55 -6
- package/.claude/skills/tasks/SKILL.md +26 -0
- package/CHANGELOG.md +31 -3
- 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+
|
|
@@ -58,16 +58,27 @@ If tasks.md doesn't exist, suggest running `/relentless.tasks` first.
|
|
|
58
58
|
|
|
59
59
|
## Step 2: Validate tasks.md Structure
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
The CLI now **automatically validates** tasks.md before conversion. You can also validate manually:
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
```bash
|
|
64
|
+
relentless validate relentless/features/NNN-feature/tasks.md
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Validation Checks
|
|
64
68
|
|
|
69
|
+
The validator checks for:
|
|
65
70
|
- [ ] Each story has unique ID (US-XXX format)
|
|
66
|
-
- [ ] Each story has acceptance criteria
|
|
67
|
-
- [ ]
|
|
68
|
-
- [ ] Dependencies reference valid story IDs
|
|
71
|
+
- [ ] Each story has acceptance criteria (after filtering)
|
|
72
|
+
- [ ] Dependencies reference existing stories
|
|
69
73
|
- [ ] No circular dependencies
|
|
70
|
-
- [ ]
|
|
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
|
|
71
82
|
|
|
72
83
|
### Example Valid Story
|
|
73
84
|
|
|
@@ -80,6 +91,7 @@ Before conversion, validate the tasks.md file:
|
|
|
80
91
|
- [ ] POST /api/register endpoint exists
|
|
81
92
|
- [ ] Email validation works
|
|
82
93
|
- [ ] Password is hashed
|
|
94
|
+
- [ ] `src/auth/register.ts` contains the registration handler
|
|
83
95
|
- [ ] Unit tests pass
|
|
84
96
|
- [ ] Integration test passes
|
|
85
97
|
|
|
@@ -88,6 +100,20 @@ Before conversion, validate the tasks.md file:
|
|
|
88
100
|
**Priority:** 1
|
|
89
101
|
```
|
|
90
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
|
+
|
|
91
117
|
---
|
|
92
118
|
|
|
93
119
|
## Step 3: Run Conversion (with Routing)
|
|
@@ -232,6 +258,25 @@ The conversion was run with `--skip-routing`. Re-run:
|
|
|
232
258
|
relentless convert relentless/features/<feature>/tasks.md --feature <feature-name>
|
|
233
259
|
```
|
|
234
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
|
+
|
|
235
280
|
### "Invalid dependency"
|
|
236
281
|
|
|
237
282
|
A story references a non-existent story ID. Check the `Dependencies:` line.
|
|
@@ -240,6 +285,10 @@ A story references a non-existent story ID. Check the `Dependencies:` line.
|
|
|
240
285
|
|
|
241
286
|
Stories reference each other in a cycle. Example: US-001 depends on US-002, and US-002 depends on US-001.
|
|
242
287
|
|
|
288
|
+
### "Dependency uses underscore format"
|
|
289
|
+
|
|
290
|
+
Use dashes in story IDs: `US-001` not `US_001`.
|
|
291
|
+
|
|
243
292
|
---
|
|
244
293
|
|
|
245
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`
|
package/CHANGELOG.md
CHANGED
|
@@ -5,9 +5,35 @@ 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
9
|
|
|
10
|
-
|
|
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
|
|
11
37
|
|
|
12
38
|
### Fixed
|
|
13
39
|
- **Registry**: Corrected Claude Sonnet 4.5 model ID from `claude-sonnet-4-5-20251020` to `claude-sonnet-4-5-20250929`
|
|
@@ -420,7 +446,9 @@ Relentless evolved from the [Ralph Wiggum Pattern](https://ghuntley.com/ralph/)
|
|
|
420
446
|
- **License**: MIT
|
|
421
447
|
- **Inspiration**: [Ralph Wiggum Pattern](https://ghuntley.com/ralph/) by Geoffrey Huntley
|
|
422
448
|
|
|
423
|
-
[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
|
|
424
452
|
[0.4.3]: https://github.com/ArvorCo/Relentless/compare/v0.4.2...v0.4.3
|
|
425
453
|
[0.4.2]: https://github.com/ArvorCo/Relentless/compare/v0.4.0...v0.4.2
|
|
426
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")
|