@arvorco/relentless 0.6.1 → 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.
- package/.claude/commands/relentless.learn.md +52 -0
- package/.claude/skills/checklist/SKILL.md +9 -2
- package/.claude/skills/constitution/SKILL.md +11 -0
- package/.claude/skills/constitution/templates/constitution.md +0 -3
- package/.claude/skills/learn/SKILL.md +361 -0
- package/.claude/skills/learn/scripts/common.sh +46 -0
- package/.claude/skills/learn/scripts/extract-costs.sh +48 -0
- package/.claude/skills/learn/scripts/extract-errors.sh +47 -0
- package/.claude/skills/learn/scripts/extract-failures.sh +47 -0
- package/.claude/skills/learn/scripts/extract-learnings.sh +66 -0
- package/.claude/skills/learn/scripts/extract-patterns.sh +72 -0
- package/.claude/skills/learn/scripts/extract-session-context.sh +77 -0
- package/.claude/skills/learn/scripts/generate-stats.sh +129 -0
- package/.claude/skills/learn/templates/learning-proposal.md +105 -0
- package/.claude/skills/learn/templates/stats.md +69 -0
- package/.claude/skills/plan/SKILL.md +10 -3
- package/.claude/skills/specify/SKILL.md +10 -4
- package/.claude/skills/tasks/SKILL.md +10 -3
- package/.claude/skills/validators/SKILL.md +174 -0
- package/.claude/skills/validators/scripts/common.sh +182 -0
- package/.claude/skills/validators/scripts/validate-checklist.sh +190 -0
- package/.claude/skills/validators/scripts/validate-constitution.sh +111 -0
- package/.claude/skills/validators/scripts/validate-plan.sh +163 -0
- package/.claude/skills/validators/scripts/validate-prompt.sh +125 -0
- package/.claude/skills/validators/scripts/validate-spec.sh +214 -0
- package/.claude/skills/validators/scripts/validate-tasks.sh +179 -0
- package/.claude/skills/validators/scripts/validate.sh +295 -0
- package/CHANGELOG.md +112 -1
- package/package.json +1 -1
- package/relentless/constitution.md +0 -3
- package/src/agents/amp.ts +3 -6
- package/src/agents/claude.ts +4 -7
- package/src/agents/codex.ts +3 -6
- package/src/agents/droid.ts +3 -6
- package/src/agents/exec.ts +56 -10
- package/src/agents/gemini.ts +3 -6
- package/src/agents/opencode.ts +3 -6
- package/src/agents/types.ts +2 -0
- package/src/config/schema.ts +2 -2
- package/src/execution/runner.ts +4 -0
- package/src/init/scaffolder.ts +2 -0
- package/src/tui/App.tsx +132 -16
- package/src/tui/TUIRunner.tsx +68 -4
- package/src/tui/components/CostBadge.tsx +59 -0
- package/src/tui/components/MessageItem.tsx +113 -0
- package/src/tui/components/MessageQueuePanel.tsx +126 -0
- package/src/tui/components/OutputPanel.tsx +270 -0
- package/src/tui/components/QueueInput.tsx +28 -11
- package/src/tui/components/RateLimitIndicator.tsx +97 -0
- package/src/tui/components/StatusBar.tsx +188 -0
- package/src/tui/components/TaskItem.tsx +131 -0
- package/src/tui/components/TaskPanel.tsx +189 -0
- package/src/tui/components/TokenCounter.tsx +48 -0
- package/src/tui/hooks/useAnimation.ts +220 -0
- package/src/tui/hooks/useCostTracking.ts +199 -0
- package/src/tui/hooks/useResponsiveLayout.ts +94 -0
- package/src/tui/hooks/useTUI.ts +57 -1
- package/src/tui/index.tsx +24 -0
- package/src/tui/layouts/LayoutSwitcher.tsx +95 -0
- package/src/tui/layouts/ThreeColumnLayout.tsx +97 -0
- package/src/tui/layouts/VerticalLayout.tsx +69 -0
- package/src/tui/layouts/index.ts +9 -0
- package/src/tui/theme.ts +152 -21
- package/src/tui/types.ts +95 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# validate-plan.sh - Validate plan.md structure
|
|
3
|
+
# Usage: validate-plan.sh <path-to-plan.md>
|
|
4
|
+
#
|
|
5
|
+
# Required structure:
|
|
6
|
+
# - Title: # Technical Plan: [Feature Name]
|
|
7
|
+
# - Technical Context section
|
|
8
|
+
# - Constitution Compliance section
|
|
9
|
+
# - Implementation Plan/Architecture
|
|
10
|
+
# - Test Specifications section
|
|
11
|
+
# - Quality Gates section
|
|
12
|
+
|
|
13
|
+
set -euo pipefail
|
|
14
|
+
|
|
15
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
16
|
+
source "$SCRIPT_DIR/common.sh"
|
|
17
|
+
|
|
18
|
+
FILE="${1:-}"
|
|
19
|
+
|
|
20
|
+
if [[ -z "$FILE" ]]; then
|
|
21
|
+
echo "Usage: validate-plan.sh <path-to-plan.md>"
|
|
22
|
+
exit 1
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
if ! check_file "$FILE"; then
|
|
26
|
+
exit 1
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
header "Validating Plan: $FILE"
|
|
30
|
+
|
|
31
|
+
# Check for proper title
|
|
32
|
+
info "Checking document structure..."
|
|
33
|
+
|
|
34
|
+
if grep -qE "^# (Technical )?(Implementation )?Plan:" "$FILE" 2>/dev/null; then
|
|
35
|
+
FEATURE=$(grep -oE "^# .+Plan: .+" "$FILE" | head -1)
|
|
36
|
+
pass "Title found: $FEATURE"
|
|
37
|
+
else
|
|
38
|
+
error "Missing title (expected: # Technical Plan: [Feature Name] or similar)"
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
# Check for mandatory sections
|
|
42
|
+
info "Checking mandatory sections..."
|
|
43
|
+
|
|
44
|
+
# Technical Context/Overview
|
|
45
|
+
if grep -qE "^## Technical Context|^## Context|^## Current State|^## Technical Overview|^## Overview" "$FILE" 2>/dev/null; then
|
|
46
|
+
pass "Technical Context/Overview section found"
|
|
47
|
+
else
|
|
48
|
+
error "Missing Technical Context section (## Technical Context or ## Technical Overview)"
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
# Constitution Compliance
|
|
52
|
+
if grep -qE "^## Constitution Compliance|^## Compliance|^## Constitution" "$FILE" 2>/dev/null; then
|
|
53
|
+
pass "Constitution Compliance section found"
|
|
54
|
+
else
|
|
55
|
+
error "Missing Constitution Compliance section (## Constitution Compliance)"
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
# Check for principle references in compliance section
|
|
59
|
+
PRINCIPLE_REFS=$(count_pattern "$FILE" "Principle [0-9]+")
|
|
60
|
+
if [[ "$PRINCIPLE_REFS" -ge 1 ]]; then
|
|
61
|
+
pass "Found $PRINCIPLE_REFS constitution principle reference(s)"
|
|
62
|
+
else
|
|
63
|
+
warning "No principle references found (should reference Principle 1, 2, etc.)"
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
# Implementation Plan/Architecture
|
|
67
|
+
if grep -qE "^## Implementation|^## Architecture|^## Design|^## Approach" "$FILE" 2>/dev/null; then
|
|
68
|
+
pass "Implementation/Architecture section found"
|
|
69
|
+
else
|
|
70
|
+
error "Missing Implementation section (## Implementation Plan or ## Architecture)"
|
|
71
|
+
fi
|
|
72
|
+
|
|
73
|
+
# Test Specifications
|
|
74
|
+
if grep -qE "^## Test|^## Testing|^## TDD" "$FILE" 2>/dev/null; then
|
|
75
|
+
pass "Test Specifications section found"
|
|
76
|
+
else
|
|
77
|
+
error "Missing Test section (## Test Specifications or ## Testing Strategy)"
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
# Quality Gates (optional - quality checks may be documented elsewhere)
|
|
81
|
+
if grep -qE "^## Quality|^## Gates|^## Validation|^### Quality" "$FILE" 2>/dev/null; then
|
|
82
|
+
pass "Quality Gates section found"
|
|
83
|
+
else
|
|
84
|
+
warning "No explicit Quality Gates section (## Quality Gates)"
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
# Check test strategy content
|
|
88
|
+
info "Checking test coverage..."
|
|
89
|
+
|
|
90
|
+
# Unit tests
|
|
91
|
+
if grep -qiE "unit test|unit-test" "$FILE" 2>/dev/null; then
|
|
92
|
+
pass "Unit testing mentioned"
|
|
93
|
+
else
|
|
94
|
+
warning "No unit testing strategy documented"
|
|
95
|
+
fi
|
|
96
|
+
|
|
97
|
+
# Integration tests
|
|
98
|
+
if grep -qiE "integration test|integration-test|e2e|end-to-end" "$FILE" 2>/dev/null; then
|
|
99
|
+
pass "Integration/E2E testing mentioned"
|
|
100
|
+
else
|
|
101
|
+
warning "No integration testing strategy documented"
|
|
102
|
+
fi
|
|
103
|
+
|
|
104
|
+
# Check quality gates content
|
|
105
|
+
info "Checking quality requirements..."
|
|
106
|
+
|
|
107
|
+
# Typecheck
|
|
108
|
+
if grep -qiE "typecheck|type-check|typescript" "$FILE" 2>/dev/null; then
|
|
109
|
+
pass "Type checking documented"
|
|
110
|
+
else
|
|
111
|
+
warning "No typecheck requirements documented"
|
|
112
|
+
fi
|
|
113
|
+
|
|
114
|
+
# Lint
|
|
115
|
+
if grep -qiE "lint|eslint" "$FILE" 2>/dev/null; then
|
|
116
|
+
pass "Linting documented"
|
|
117
|
+
else
|
|
118
|
+
warning "No linting requirements documented"
|
|
119
|
+
fi
|
|
120
|
+
|
|
121
|
+
# Check for optional but recommended sections
|
|
122
|
+
info "Checking optional sections..."
|
|
123
|
+
|
|
124
|
+
check_section_warn "$FILE" "^## Risk|^## Risks" "Risk Assessment section"
|
|
125
|
+
check_section_warn "$FILE" "^## Assumptions|^## Constraints" "Assumptions/Constraints section"
|
|
126
|
+
check_section_warn "$FILE" "^## Dependencies" "Dependencies section"
|
|
127
|
+
check_section_warn "$FILE" "^## Timeline|^## Milestones" "Timeline/Milestones section"
|
|
128
|
+
|
|
129
|
+
# Check for file change documentation
|
|
130
|
+
info "Checking implementation guidance..."
|
|
131
|
+
|
|
132
|
+
FILE_CHANGES=$(count_pattern "$FILE" "\.ts|\.tsx|\.js|\.jsx|\.md|\.json|\.sh")
|
|
133
|
+
if [[ "$FILE_CHANGES" -ge 3 ]]; then
|
|
134
|
+
pass "File references found ($FILE_CHANGES files mentioned)"
|
|
135
|
+
else
|
|
136
|
+
warning "Few file references found (plan should list files to create/modify)"
|
|
137
|
+
fi
|
|
138
|
+
|
|
139
|
+
# Check for code examples
|
|
140
|
+
CODE_BLOCKS=$(grep -c '```' "$FILE" 2>/dev/null || echo "0")
|
|
141
|
+
CODE_BLOCKS=$((CODE_BLOCKS / 2))
|
|
142
|
+
if [[ "$CODE_BLOCKS" -ge 1 ]]; then
|
|
143
|
+
pass "Found $CODE_BLOCKS code block(s)"
|
|
144
|
+
else
|
|
145
|
+
warning "No code examples found (recommended for technical plans)"
|
|
146
|
+
fi
|
|
147
|
+
|
|
148
|
+
# Check spec reference
|
|
149
|
+
info "Checking cross-references..."
|
|
150
|
+
|
|
151
|
+
if grep -qE "spec\.md|specification" "$FILE" 2>/dev/null; then
|
|
152
|
+
pass "References spec.md"
|
|
153
|
+
else
|
|
154
|
+
warning "No reference to spec.md found"
|
|
155
|
+
fi
|
|
156
|
+
|
|
157
|
+
# Check for placeholders
|
|
158
|
+
info "Checking for unfilled placeholders..."
|
|
159
|
+
check_no_placeholders "$FILE"
|
|
160
|
+
|
|
161
|
+
# Print summary
|
|
162
|
+
print_summary "plan.md"
|
|
163
|
+
exit $?
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# validate-prompt.sh - Validate prompt.md structure
|
|
3
|
+
# Usage: validate-prompt.sh <path-to-prompt.md>
|
|
4
|
+
#
|
|
5
|
+
# Required structure:
|
|
6
|
+
# - Title: # Relentless Agent Instructions or similar
|
|
7
|
+
# - Quality Gates section with bash commands
|
|
8
|
+
# - TDD Workflow section
|
|
9
|
+
# - Progress Report Format section
|
|
10
|
+
|
|
11
|
+
set -euo pipefail
|
|
12
|
+
|
|
13
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
14
|
+
source "$SCRIPT_DIR/common.sh"
|
|
15
|
+
|
|
16
|
+
FILE="${1:-}"
|
|
17
|
+
|
|
18
|
+
if [[ -z "$FILE" ]]; then
|
|
19
|
+
echo "Usage: validate-prompt.sh <path-to-prompt.md>"
|
|
20
|
+
exit 1
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
if ! check_file "$FILE"; then
|
|
24
|
+
exit 1
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
header "Validating Prompt: $FILE"
|
|
28
|
+
|
|
29
|
+
# Check for title
|
|
30
|
+
info "Checking document structure..."
|
|
31
|
+
|
|
32
|
+
if grep -qE "^# .*Agent.*Instructions|^# .*Prompt|^# Relentless" "$FILE" 2>/dev/null; then
|
|
33
|
+
TITLE=$(grep -oE "^# .*" "$FILE" | head -1)
|
|
34
|
+
pass "Title found: $TITLE"
|
|
35
|
+
else
|
|
36
|
+
error "Missing prompt title (expected: # Relentless Agent Instructions or similar)"
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
# Check for Quality Gates section
|
|
40
|
+
info "Checking required sections..."
|
|
41
|
+
|
|
42
|
+
if grep -qE "^##+ .*Quality Gates|^##+ Quality Commands" "$FILE" 2>/dev/null; then
|
|
43
|
+
pass "Quality Gates section found"
|
|
44
|
+
else
|
|
45
|
+
error "Missing Quality Gates section (expected: ## Quality Gates)"
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
# Check for actual quality commands (bash code blocks)
|
|
49
|
+
BASH_BLOCKS=$(count_pattern "$FILE" '```bash')
|
|
50
|
+
if [[ "$BASH_BLOCKS" -ge 1 ]]; then
|
|
51
|
+
pass "Found $BASH_BLOCKS bash code block(s) with quality commands"
|
|
52
|
+
else
|
|
53
|
+
warning "No bash code blocks found (expected quality commands in bash blocks)"
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
# Check for TDD Workflow section
|
|
57
|
+
if grep -qE "^##+ TDD|^##+ Test.Driven" "$FILE" 2>/dev/null; then
|
|
58
|
+
pass "TDD Workflow section found"
|
|
59
|
+
else
|
|
60
|
+
error "Missing TDD Workflow section (expected: ## TDD Workflow)"
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
# Check for Progress Report section
|
|
64
|
+
if grep -qE "^##+ Progress|progress.txt" "$FILE" 2>/dev/null; then
|
|
65
|
+
pass "Progress Report section found"
|
|
66
|
+
else
|
|
67
|
+
warning "Missing Progress Report section"
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
# Check for One Story rule
|
|
71
|
+
if grep -qE "ONE Story|one story|single story" "$FILE" 2>/dev/null; then
|
|
72
|
+
pass "One Story Per Iteration rule found"
|
|
73
|
+
else
|
|
74
|
+
warning "Missing One Story Per Iteration guidance"
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
# Check for Stop Condition / completion signal
|
|
78
|
+
if grep -qE "Stop Condition|COMPLETE|promise" "$FILE" 2>/dev/null; then
|
|
79
|
+
pass "Stop condition / completion signal documented"
|
|
80
|
+
else
|
|
81
|
+
warning "Missing stop condition or completion signal documentation"
|
|
82
|
+
fi
|
|
83
|
+
|
|
84
|
+
# Check for version metadata
|
|
85
|
+
info "Checking metadata..."
|
|
86
|
+
|
|
87
|
+
if grep -qE "Template Version|Version:|Generated:" "$FILE" 2>/dev/null; then
|
|
88
|
+
VERSION=$(grep -oE "[0-9]+\.[0-9]+\.[0-9]+" "$FILE" | head -1 || echo "unknown")
|
|
89
|
+
pass "Version/metadata found: $VERSION"
|
|
90
|
+
else
|
|
91
|
+
warning "No version metadata found"
|
|
92
|
+
fi
|
|
93
|
+
|
|
94
|
+
# Check for placeholders
|
|
95
|
+
info "Checking for unfilled placeholders..."
|
|
96
|
+
check_no_placeholders "$FILE"
|
|
97
|
+
|
|
98
|
+
# Check for common quality commands
|
|
99
|
+
info "Checking quality command patterns..."
|
|
100
|
+
|
|
101
|
+
TYPECHECK_FOUND=$(grep -c "typecheck\|tsc" "$FILE" 2>/dev/null) || true
|
|
102
|
+
LINT_FOUND=$(grep -c "lint\|eslint\|biome" "$FILE" 2>/dev/null) || true
|
|
103
|
+
TEST_FOUND=$(grep -c "test\|vitest\|jest\|bun test" "$FILE" 2>/dev/null) || true
|
|
104
|
+
|
|
105
|
+
if [[ "$TYPECHECK_FOUND" -ge 1 ]]; then
|
|
106
|
+
pass "Typecheck command reference found"
|
|
107
|
+
else
|
|
108
|
+
warning "No typecheck command mentioned"
|
|
109
|
+
fi
|
|
110
|
+
|
|
111
|
+
if [[ "$LINT_FOUND" -ge 1 ]]; then
|
|
112
|
+
pass "Lint command reference found"
|
|
113
|
+
else
|
|
114
|
+
warning "No lint command mentioned"
|
|
115
|
+
fi
|
|
116
|
+
|
|
117
|
+
if [[ "$TEST_FOUND" -ge 1 ]]; then
|
|
118
|
+
pass "Test command reference found"
|
|
119
|
+
else
|
|
120
|
+
warning "No test command mentioned"
|
|
121
|
+
fi
|
|
122
|
+
|
|
123
|
+
# Print summary
|
|
124
|
+
print_summary "prompt.md"
|
|
125
|
+
exit $?
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# validate-spec.sh - Validate spec.md structure
|
|
3
|
+
# Usage: validate-spec.sh <path-to-spec.md>
|
|
4
|
+
#
|
|
5
|
+
# Required structure:
|
|
6
|
+
# - Title: # Feature Specification: [Feature Name]
|
|
7
|
+
# - User Scenarios & Testing section (mandatory)
|
|
8
|
+
# - User stories with priorities (P1, P2, P3)
|
|
9
|
+
# - Given/When/Then acceptance scenarios
|
|
10
|
+
# - Functional Requirements section (mandatory) with FR-XXX items
|
|
11
|
+
# - Test Strategy section (mandatory)
|
|
12
|
+
# - Success Criteria section (mandatory)
|
|
13
|
+
|
|
14
|
+
set -euo pipefail
|
|
15
|
+
|
|
16
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
17
|
+
source "$SCRIPT_DIR/common.sh"
|
|
18
|
+
|
|
19
|
+
FILE="${1:-}"
|
|
20
|
+
|
|
21
|
+
if [[ -z "$FILE" ]]; then
|
|
22
|
+
echo "Usage: validate-spec.sh <path-to-spec.md>"
|
|
23
|
+
exit 1
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
if ! check_file "$FILE"; then
|
|
27
|
+
exit 1
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
header "Validating Spec: $FILE"
|
|
31
|
+
|
|
32
|
+
# Check for proper title
|
|
33
|
+
info "Checking document structure..."
|
|
34
|
+
|
|
35
|
+
if grep -qE "^# Feature Specification:|^# Specification:|^# Spec:" "$FILE" 2>/dev/null; then
|
|
36
|
+
FEATURE=$(grep -oE "^# (Feature )?Spec(ification)?: .+" "$FILE" | sed 's/^# \(Feature \)\?Spec\(ification\)\?: //')
|
|
37
|
+
pass "Title found: $FEATURE"
|
|
38
|
+
else
|
|
39
|
+
error "Missing title (expected: # Feature Specification: [Feature Name])"
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
# Check for Feature Branch
|
|
43
|
+
if grep -qE "\*\*Feature Branch\*\*:|Feature Branch:" "$FILE" 2>/dev/null; then
|
|
44
|
+
pass "Feature branch documented"
|
|
45
|
+
else
|
|
46
|
+
warning "No feature branch documented (recommended: **Feature Branch**: \`feature-name\`)"
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
# Check for Routing Preference
|
|
50
|
+
if grep -qE "\*\*Routing Preference\*\*:|Routing Preference:" "$FILE" 2>/dev/null; then
|
|
51
|
+
pass "Routing preference documented"
|
|
52
|
+
else
|
|
53
|
+
warning "No routing preference documented (affects PRD generation)"
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
# Check mandatory sections
|
|
57
|
+
info "Checking mandatory sections..."
|
|
58
|
+
|
|
59
|
+
# User Scenarios & Testing
|
|
60
|
+
if grep -qE "^## User Scenarios|^## Scenarios|^## User Stories" "$FILE" 2>/dev/null; then
|
|
61
|
+
pass "User Scenarios section found"
|
|
62
|
+
else
|
|
63
|
+
error "Missing User Scenarios section (## User Scenarios & Testing)"
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
# Functional Requirements
|
|
67
|
+
if grep -qE "^## Requirements|^## Functional Requirements|^### Functional Requirements" "$FILE" 2>/dev/null; then
|
|
68
|
+
pass "Requirements section found"
|
|
69
|
+
else
|
|
70
|
+
error "Missing Requirements section (## Requirements)"
|
|
71
|
+
fi
|
|
72
|
+
|
|
73
|
+
# Test Strategy (optional - may be in plan.md instead)
|
|
74
|
+
if grep -qE "^## Test Strategy|^## Testing Strategy|^## Test Plan" "$FILE" 2>/dev/null; then
|
|
75
|
+
pass "Test Strategy section found"
|
|
76
|
+
else
|
|
77
|
+
warning "No Test Strategy section (may be in plan.md instead)"
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
# Success Criteria
|
|
81
|
+
if grep -qE "^## Success Criteria|^## Acceptance Criteria|^## Definition of Done" "$FILE" 2>/dev/null; then
|
|
82
|
+
pass "Success Criteria section found"
|
|
83
|
+
else
|
|
84
|
+
error "Missing Success Criteria section (## Success Criteria)"
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
# Check user stories
|
|
88
|
+
info "Checking user story quality..."
|
|
89
|
+
|
|
90
|
+
# Count user stories
|
|
91
|
+
US_HEADING_COUNT=$(count_pattern "$FILE" "^### User Story [0-9]+")
|
|
92
|
+
if [[ "$US_HEADING_COUNT" -ge 1 ]]; then
|
|
93
|
+
pass "Found $US_HEADING_COUNT user story section(s)"
|
|
94
|
+
else
|
|
95
|
+
error "No user story sections found (expected: ### User Story 1 - Title)"
|
|
96
|
+
fi
|
|
97
|
+
|
|
98
|
+
# Check for priorities
|
|
99
|
+
PRIORITY_COUNT=$(count_pattern "$FILE" "\(Priority: P[0-9]+\)|\*\*Priority\*\*: P[0-9]+")
|
|
100
|
+
if [[ "$PRIORITY_COUNT" -ge 1 ]]; then
|
|
101
|
+
pass "Found $PRIORITY_COUNT priority assignment(s)"
|
|
102
|
+
else
|
|
103
|
+
error "No priorities found (user stories need Priority: P1, P2, P3, etc.)"
|
|
104
|
+
fi
|
|
105
|
+
|
|
106
|
+
# Check for P1 priority specifically
|
|
107
|
+
if grep -qE "Priority: P1|Priority\*\*: P1" "$FILE" 2>/dev/null; then
|
|
108
|
+
pass "Has P1 (highest priority) story"
|
|
109
|
+
else
|
|
110
|
+
warning "No P1 priority story found (at least one story should be P1)"
|
|
111
|
+
fi
|
|
112
|
+
|
|
113
|
+
# Check TDD format (Given/When/Then)
|
|
114
|
+
info "Checking TDD compliance..."
|
|
115
|
+
|
|
116
|
+
GIVEN_COUNT=$(count_pattern "$FILE" "\*\*Given\*\*|Given ")
|
|
117
|
+
WHEN_COUNT=$(count_pattern "$FILE" "\*\*When\*\*|When ")
|
|
118
|
+
THEN_COUNT=$(count_pattern "$FILE" "\*\*Then\*\*|Then ")
|
|
119
|
+
|
|
120
|
+
if [[ "$GIVEN_COUNT" -ge 1 && "$WHEN_COUNT" -ge 1 && "$THEN_COUNT" -ge 1 ]]; then
|
|
121
|
+
pass "Given/When/Then format used ($GIVEN_COUNT/$WHEN_COUNT/$THEN_COUNT)"
|
|
122
|
+
else
|
|
123
|
+
error "Missing Given/When/Then acceptance scenarios (TDD requirement)"
|
|
124
|
+
fi
|
|
125
|
+
|
|
126
|
+
# Check for acceptance scenarios heading
|
|
127
|
+
if grep -qE "\*\*Acceptance Scenarios\*\*:|^#### Acceptance" "$FILE" 2>/dev/null; then
|
|
128
|
+
pass "Acceptance Scenarios documented"
|
|
129
|
+
else
|
|
130
|
+
warning "No explicit 'Acceptance Scenarios' heading found"
|
|
131
|
+
fi
|
|
132
|
+
|
|
133
|
+
# Check functional requirements
|
|
134
|
+
info "Checking functional requirements..."
|
|
135
|
+
|
|
136
|
+
FR_COUNT=$(count_pattern "$FILE" "\*\*FR-[0-9]+\*\*:|FR-[0-9]+:")
|
|
137
|
+
if [[ "$FR_COUNT" -ge 3 ]]; then
|
|
138
|
+
pass "Found $FR_COUNT functional requirement(s)"
|
|
139
|
+
else
|
|
140
|
+
error "Insufficient functional requirements (expected at least 3 FR-XXX items)"
|
|
141
|
+
fi
|
|
142
|
+
|
|
143
|
+
# Check for MUST requirements
|
|
144
|
+
MUST_COUNT=$(count_pattern "$FILE" "System MUST|MUST")
|
|
145
|
+
if [[ "$MUST_COUNT" -ge 1 ]]; then
|
|
146
|
+
pass "Found $MUST_COUNT MUST requirement(s)"
|
|
147
|
+
else
|
|
148
|
+
warning "No MUST requirements found (FRs should use 'System MUST...')"
|
|
149
|
+
fi
|
|
150
|
+
|
|
151
|
+
# Check test strategy content
|
|
152
|
+
info "Checking test strategy quality..."
|
|
153
|
+
|
|
154
|
+
# Unit tests
|
|
155
|
+
if grep -qiE "^### Unit Test|unit test" "$FILE" 2>/dev/null; then
|
|
156
|
+
pass "Unit test approach documented"
|
|
157
|
+
else
|
|
158
|
+
warning "No unit test approach documented"
|
|
159
|
+
fi
|
|
160
|
+
|
|
161
|
+
# Integration tests
|
|
162
|
+
if grep -qiE "^### Integration Test|integration test" "$FILE" 2>/dev/null; then
|
|
163
|
+
pass "Integration test approach documented"
|
|
164
|
+
else
|
|
165
|
+
warning "No integration test approach documented"
|
|
166
|
+
fi
|
|
167
|
+
|
|
168
|
+
# Edge cases
|
|
169
|
+
if grep -qiE "^### Edge Case|edge case" "$FILE" 2>/dev/null; then
|
|
170
|
+
pass "Edge case tests documented"
|
|
171
|
+
else
|
|
172
|
+
warning "No edge case tests documented"
|
|
173
|
+
fi
|
|
174
|
+
|
|
175
|
+
# Check success criteria
|
|
176
|
+
info "Checking success criteria quality..."
|
|
177
|
+
|
|
178
|
+
SC_COUNT=$(count_pattern "$FILE" "\*\*SC-[0-9]+\*\*:|SC-[0-9]+:")
|
|
179
|
+
if [[ "$SC_COUNT" -ge 2 ]]; then
|
|
180
|
+
pass "Found $SC_COUNT success criteria"
|
|
181
|
+
else
|
|
182
|
+
warning "Few success criteria found (recommended at least 2 SC-XXX items)"
|
|
183
|
+
fi
|
|
184
|
+
|
|
185
|
+
# Check for measurable metrics
|
|
186
|
+
if grep -qiE "[0-9]+%|[0-9]+ seconds|[0-9]+ minutes|[0-9]+ users" "$FILE" 2>/dev/null; then
|
|
187
|
+
pass "Measurable metrics found in criteria"
|
|
188
|
+
else
|
|
189
|
+
warning "No measurable metrics found (success criteria should be quantifiable)"
|
|
190
|
+
fi
|
|
191
|
+
|
|
192
|
+
# Check for optional sections
|
|
193
|
+
info "Checking optional sections..."
|
|
194
|
+
|
|
195
|
+
check_section_warn "$FILE" "^### Edge Cases|^## Edge Cases" "Edge Cases section"
|
|
196
|
+
check_section_warn "$FILE" "^### Key Entities|^## Key Entities|^## Data Model" "Key Entities/Data Model section"
|
|
197
|
+
check_section_warn "$FILE" "^### Test Data|test data" "Test Data Requirements"
|
|
198
|
+
|
|
199
|
+
# Check for placeholders
|
|
200
|
+
info "Checking for unfilled placeholders..."
|
|
201
|
+
check_no_placeholders "$FILE"
|
|
202
|
+
|
|
203
|
+
# Check for common issues
|
|
204
|
+
info "Checking for common issues..."
|
|
205
|
+
|
|
206
|
+
# Check for [NEEDS CLARIFICATION] tags
|
|
207
|
+
CLARIFICATION_COUNT=$(count_pattern "$FILE" "\[NEEDS CLARIFICATION")
|
|
208
|
+
if [[ "$CLARIFICATION_COUNT" -gt 0 ]]; then
|
|
209
|
+
warning "Found $CLARIFICATION_COUNT unresolved [NEEDS CLARIFICATION] tag(s)"
|
|
210
|
+
fi
|
|
211
|
+
|
|
212
|
+
# Print summary
|
|
213
|
+
print_summary "spec.md"
|
|
214
|
+
exit $?
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# validate-tasks.sh - Validate tasks.md structure
|
|
3
|
+
# Usage: validate-tasks.sh <path-to-tasks.md>
|
|
4
|
+
#
|
|
5
|
+
# Required structure:
|
|
6
|
+
# - Title: # Implementation Tasks: [Feature Name]
|
|
7
|
+
# - At least one Phase section
|
|
8
|
+
# - User stories with [US-XXX] tags
|
|
9
|
+
# - Tasks under each user story
|
|
10
|
+
# - Complexity classifications
|
|
11
|
+
# - Dependencies properly formatted
|
|
12
|
+
|
|
13
|
+
set -euo pipefail
|
|
14
|
+
|
|
15
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
16
|
+
source "$SCRIPT_DIR/common.sh"
|
|
17
|
+
|
|
18
|
+
FILE="${1:-}"
|
|
19
|
+
|
|
20
|
+
if [[ -z "$FILE" ]]; then
|
|
21
|
+
echo "Usage: validate-tasks.sh <path-to-tasks.md>"
|
|
22
|
+
exit 1
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
if ! check_file "$FILE"; then
|
|
26
|
+
exit 1
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
header "Validating Tasks: $FILE"
|
|
30
|
+
|
|
31
|
+
# Check for proper title
|
|
32
|
+
info "Checking document structure..."
|
|
33
|
+
|
|
34
|
+
if grep -qE "^# (Implementation Tasks|User Stories):" "$FILE" 2>/dev/null; then
|
|
35
|
+
FEATURE=$(grep -oE "^# (Implementation Tasks|User Stories): .+" "$FILE" | head -1)
|
|
36
|
+
pass "Title found: $FEATURE"
|
|
37
|
+
else
|
|
38
|
+
error "Missing title (expected: # Implementation Tasks: [Feature Name] or # User Stories: [Feature Name])"
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
# Check for at least one Phase section
|
|
42
|
+
PHASE_COUNT=$(count_pattern "$FILE" "^## Phase [0-9]+")
|
|
43
|
+
if [[ "$PHASE_COUNT" -ge 1 ]]; then
|
|
44
|
+
pass "Found $PHASE_COUNT Phase section(s)"
|
|
45
|
+
else
|
|
46
|
+
error "No Phase sections found (expected: ## Phase 1: ..., ## Phase 2: ..., etc.)"
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
# Check for user stories
|
|
50
|
+
info "Checking user stories..."
|
|
51
|
+
|
|
52
|
+
# Support both [US-XXX] and US-XXX: formats
|
|
53
|
+
US_COUNT=$(count_pattern "$FILE" "\[US-[0-9]+\]|^### US-[0-9]+:")
|
|
54
|
+
if [[ "$US_COUNT" -ge 1 ]]; then
|
|
55
|
+
pass "Found $US_COUNT user story reference(s)"
|
|
56
|
+
else
|
|
57
|
+
error "No user story tags found (expected: [US-001] or ### US-001:)"
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
# Check for user story headings - both formats
|
|
61
|
+
US_HEADING_COUNT_BRACKET=$(count_pattern "$FILE" "^### \[US-[0-9]+\]")
|
|
62
|
+
US_HEADING_COUNT_COLON=$(count_pattern "$FILE" "^### US-[0-9]+:")
|
|
63
|
+
US_HEADING_COUNT=$((US_HEADING_COUNT_BRACKET + US_HEADING_COUNT_COLON))
|
|
64
|
+
if [[ "$US_HEADING_COUNT" -ge 1 ]]; then
|
|
65
|
+
pass "Found $US_HEADING_COUNT user story heading(s)"
|
|
66
|
+
else
|
|
67
|
+
error "No user story headings found (expected: ### [US-001] Title or ### US-001: Title)"
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
# Check for complexity classifications
|
|
71
|
+
info "Checking metadata..."
|
|
72
|
+
|
|
73
|
+
COMPLEXITY_COUNT=$(count_pattern "$FILE" "\*\*Complexity\*\*:|Complexity:")
|
|
74
|
+
if [[ "$COMPLEXITY_COUNT" -ge 1 ]]; then
|
|
75
|
+
pass "Found $COMPLEXITY_COUNT complexity classification(s)"
|
|
76
|
+
else
|
|
77
|
+
warning "No complexity classifications found (recommended: **Complexity**: simple|medium|complex|expert)"
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
# Check that complexities are valid values
|
|
81
|
+
if grep -qE "Complexity\*?\*?:\s*(simple|medium|complex|expert)" "$FILE" 2>/dev/null; then
|
|
82
|
+
pass "Complexity values are valid (simple/medium/complex/expert)"
|
|
83
|
+
else
|
|
84
|
+
if [[ "$COMPLEXITY_COUNT" -ge 1 ]]; then
|
|
85
|
+
warning "Some complexity values may be invalid (expected: simple, medium, complex, expert)"
|
|
86
|
+
fi
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
# Check for Dependencies section or references
|
|
90
|
+
DEP_COUNT=$(count_pattern "$FILE" "\*\*Dependencies\*\*:|Depends on:|←")
|
|
91
|
+
if [[ "$DEP_COUNT" -ge 1 ]]; then
|
|
92
|
+
pass "Found $DEP_COUNT dependency reference(s)"
|
|
93
|
+
else
|
|
94
|
+
warning "No dependencies documented (use **Dependencies**: or ← symbol)"
|
|
95
|
+
fi
|
|
96
|
+
|
|
97
|
+
# Check for task checkboxes
|
|
98
|
+
info "Checking task structure..."
|
|
99
|
+
|
|
100
|
+
TASK_COUNT=$(count_pattern "$FILE" "^- \[ \]|^ - \[ \]|^ - \[ \]")
|
|
101
|
+
if [[ "$TASK_COUNT" -ge 1 ]]; then
|
|
102
|
+
pass "Found $TASK_COUNT task checkbox(es)"
|
|
103
|
+
else
|
|
104
|
+
error "No task checkboxes found (expected: - [ ] Task description)"
|
|
105
|
+
fi
|
|
106
|
+
|
|
107
|
+
# Check for acceptance criteria or test mentions
|
|
108
|
+
CRITERIA_COUNT=$(count_pattern "$FILE" "\*\*Acceptance\*\*|\*\*Test\*\*|acceptance criteria|Given.*When.*Then")
|
|
109
|
+
if [[ "$CRITERIA_COUNT" -ge 1 ]]; then
|
|
110
|
+
pass "Found $CRITERIA_COUNT acceptance/test reference(s)"
|
|
111
|
+
else
|
|
112
|
+
warning "No acceptance criteria found (recommended for testability)"
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
# Check for Files to Create/Modify sections
|
|
116
|
+
info "Checking implementation guidance..."
|
|
117
|
+
|
|
118
|
+
FILES_SECTION=$(count_pattern "$FILE" "\*\*Files to|Files to Create|Files to Modify")
|
|
119
|
+
if [[ "$FILES_SECTION" -ge 1 ]]; then
|
|
120
|
+
pass "Found file change documentation"
|
|
121
|
+
else
|
|
122
|
+
warning "No 'Files to Create/Modify' documentation (recommended)"
|
|
123
|
+
fi
|
|
124
|
+
|
|
125
|
+
# Check for PRD conversion compatibility
|
|
126
|
+
info "Checking PRD conversion compatibility..."
|
|
127
|
+
|
|
128
|
+
# User stories need to have clear boundaries for prd.json conversion
|
|
129
|
+
# Looking for structured format: ### [US-XXX] Title or ### US-XXX: Title
|
|
130
|
+
if grep -qE "^### (\[US-[0-9]+\]|US-[0-9]+:)" "$FILE" 2>/dev/null; then
|
|
131
|
+
pass "User stories have PRD-convertible format"
|
|
132
|
+
else
|
|
133
|
+
error "User story format not PRD-convertible (need: ### [US-XXX] Title or ### US-XXX: Title)"
|
|
134
|
+
fi
|
|
135
|
+
|
|
136
|
+
# Check routing preference exists for prd.json
|
|
137
|
+
if grep -qE "Routing Preference|routing preference|Mode:|mode:" "$FILE" 2>/dev/null; then
|
|
138
|
+
pass "Routing preference documented"
|
|
139
|
+
else
|
|
140
|
+
warning "No routing preference found (will use defaults in prd.json)"
|
|
141
|
+
fi
|
|
142
|
+
|
|
143
|
+
# Check for placeholders
|
|
144
|
+
info "Checking for unfilled placeholders..."
|
|
145
|
+
check_no_placeholders "$FILE"
|
|
146
|
+
|
|
147
|
+
# Check for common issues
|
|
148
|
+
info "Checking for common issues..."
|
|
149
|
+
|
|
150
|
+
# Check for duplicate US numbers (handles both [US-XXX] and US-XXX: formats)
|
|
151
|
+
DUPLICATE_US=$(grep -oE "\[US-[0-9]+\]|### US-[0-9]+:" "$FILE" 2>/dev/null | grep -oE "US-[0-9]+" | sort | uniq -d)
|
|
152
|
+
if [[ -z "$DUPLICATE_US" ]]; then
|
|
153
|
+
pass "No duplicate user story IDs"
|
|
154
|
+
else
|
|
155
|
+
warning "Duplicate user story IDs found: $DUPLICATE_US"
|
|
156
|
+
fi
|
|
157
|
+
|
|
158
|
+
# Check US numbers are sequential (just a warning)
|
|
159
|
+
US_NUMBERS=$(grep -oE "US-[0-9]+" "$FILE" 2>/dev/null | grep -oE "[0-9]+" | sort -n | uniq)
|
|
160
|
+
EXPECTED_SEQ=1
|
|
161
|
+
SEQ_OK=true
|
|
162
|
+
for num in $US_NUMBERS; do
|
|
163
|
+
# Use 10# to force base 10 (avoid octal interpretation of 008, 009)
|
|
164
|
+
if [[ "$((10#$num))" -ne "$EXPECTED_SEQ" ]]; then
|
|
165
|
+
SEQ_OK=false
|
|
166
|
+
break
|
|
167
|
+
fi
|
|
168
|
+
EXPECTED_SEQ=$((EXPECTED_SEQ + 1))
|
|
169
|
+
done
|
|
170
|
+
|
|
171
|
+
if [[ "$SEQ_OK" == "true" ]]; then
|
|
172
|
+
pass "User story IDs are sequential"
|
|
173
|
+
else
|
|
174
|
+
warning "User story IDs are not sequential (gaps may exist)"
|
|
175
|
+
fi
|
|
176
|
+
|
|
177
|
+
# Print summary
|
|
178
|
+
print_summary "tasks.md"
|
|
179
|
+
exit $?
|