@arvorco/relentless 0.1.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.analyze.md +20 -0
- package/.claude/commands/relentless.checklist.md +15 -0
- package/.claude/commands/relentless.clarify.md +19 -0
- package/.claude/commands/relentless.constitution.md +78 -0
- package/.claude/commands/relentless.implement.md +15 -0
- package/.claude/commands/relentless.plan.md +22 -0
- package/.claude/commands/relentless.plan.old.md +89 -0
- package/.claude/commands/relentless.specify.md +254 -0
- package/.claude/commands/relentless.tasks.md +25 -0
- package/.claude/commands/relentless.taskstoissues.md +15 -0
- package/.claude/settings.local.json +23 -0
- package/.claude/skills/analyze/SKILL.md +149 -0
- package/.claude/skills/checklist/SKILL.md +173 -0
- package/.claude/skills/checklist/templates/checklist-template.md +40 -0
- package/.claude/skills/clarify/SKILL.md +174 -0
- package/.claude/skills/constitution/SKILL.md +150 -0
- package/.claude/skills/constitution/templates/constitution-template.md +228 -0
- package/.claude/skills/implement/SKILL.md +141 -0
- package/.claude/skills/plan/SKILL.md +179 -0
- package/.claude/skills/plan/templates/plan-template.md +104 -0
- package/.claude/skills/prd/SKILL.md +242 -0
- package/.claude/skills/relentless/SKILL.md +265 -0
- package/.claude/skills/specify/SKILL.md +220 -0
- package/.claude/skills/specify/scripts/bash/check-prerequisites.sh +166 -0
- package/.claude/skills/specify/scripts/bash/common.sh +156 -0
- package/.claude/skills/specify/scripts/bash/create-new-feature.sh +305 -0
- package/.claude/skills/specify/scripts/bash/setup-plan.sh +61 -0
- package/.claude/skills/specify/scripts/bash/update-agent-context.sh +799 -0
- package/.claude/skills/specify/templates/spec-template.md +115 -0
- package/.claude/skills/tasks/SKILL.md +202 -0
- package/.claude/skills/tasks/templates/tasks-template.md +251 -0
- package/.claude/skills/taskstoissues/SKILL.md +97 -0
- package/.specify/memory/constitution.md +50 -0
- package/.specify/scripts/bash/check-prerequisites.sh +166 -0
- package/.specify/scripts/bash/common.sh +156 -0
- package/.specify/scripts/bash/create-new-feature.sh +297 -0
- package/.specify/scripts/bash/setup-plan.sh +61 -0
- package/.specify/scripts/bash/update-agent-context.sh +799 -0
- package/.specify/templates/agent-file-template.md +28 -0
- package/.specify/templates/checklist-template.md +40 -0
- package/.specify/templates/plan-template.md +104 -0
- package/.specify/templates/spec-template.md +115 -0
- package/.specify/templates/tasks-template.md +251 -0
- package/CHANGES_SUMMARY.md +255 -0
- package/CLAUDE.md +92 -0
- package/GEMINI_SETUP.md +256 -0
- package/LICENSE +21 -0
- package/README.md +1171 -0
- package/REFACTOR_SUMMARY.md +267 -0
- package/bin/relentless.ts +536 -0
- package/bun.lock +352 -0
- package/eslint.config.js +37 -0
- package/package.json +61 -0
- package/prd.json.example +64 -0
- package/prompt.md +108 -0
- package/ralph.sh +80 -0
- package/relentless/config.json +38 -0
- package/relentless/features/.gitkeep +0 -0
- package/relentless/features/ghsk-ideas/prd.json +229 -0
- package/relentless/features/ghsk-ideas/prd.md +191 -0
- package/relentless/features/ghsk-ideas/progress.txt +408 -0
- package/relentless/prompt.md +79 -0
- package/skills/checklist/SKILL.md +349 -0
- package/skills/clarify/SKILL.md +476 -0
- package/skills/prd/SKILL.md +242 -0
- package/skills/relentless/SKILL.md +268 -0
- package/skills/tasks/SKILL.md +577 -0
- package/src/agents/amp.ts +115 -0
- package/src/agents/claude.ts +185 -0
- package/src/agents/codex.ts +89 -0
- package/src/agents/droid.ts +90 -0
- package/src/agents/gemini.ts +109 -0
- package/src/agents/index.ts +16 -0
- package/src/agents/opencode.ts +88 -0
- package/src/agents/registry.ts +95 -0
- package/src/agents/types.ts +101 -0
- package/src/config/index.ts +8 -0
- package/src/config/loader.ts +237 -0
- package/src/config/schema.ts +115 -0
- package/src/execution/index.ts +8 -0
- package/src/execution/router.ts +49 -0
- package/src/execution/runner.ts +512 -0
- package/src/index.ts +11 -0
- package/src/init/index.ts +7 -0
- package/src/init/scaffolder.ts +377 -0
- package/src/prd/analyzer.ts +512 -0
- package/src/prd/index.ts +11 -0
- package/src/prd/issues.ts +249 -0
- package/src/prd/parser.ts +281 -0
- package/src/prd/progress.ts +198 -0
- package/src/prd/types.ts +170 -0
- package/src/tui/App.tsx +85 -0
- package/src/tui/TUIRunner.tsx +400 -0
- package/src/tui/components/AgentOutput.tsx +45 -0
- package/src/tui/components/AgentStatus.tsx +64 -0
- package/src/tui/components/CurrentStory.tsx +66 -0
- package/src/tui/components/Header.tsx +49 -0
- package/src/tui/components/ProgressBar.tsx +39 -0
- package/src/tui/components/StoryGrid.tsx +86 -0
- package/src/tui/hooks/useTUI.ts +147 -0
- package/src/tui/hooks/useTimer.ts +51 -0
- package/src/tui/index.tsx +17 -0
- package/src/tui/theme.ts +41 -0
- package/src/tui/types.ts +77 -0
- package/templates/constitution.md +228 -0
- package/templates/plan.md +273 -0
- package/tsconfig.json +27 -0
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: specify
|
|
3
|
+
description: "Create feature specification from natural language description. Use when starting a new feature or creating a spec. Triggers on: create spec, specify feature, new feature spec."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Feature Specification Generator
|
|
7
|
+
|
|
8
|
+
Create structured feature specifications from natural language descriptions.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## The Job
|
|
13
|
+
|
|
14
|
+
1. Receive feature description from user
|
|
15
|
+
2. Generate short name and feature number
|
|
16
|
+
3. Create branch and feature directory in `relentless/features/NNN-feature-name/`
|
|
17
|
+
4. Generate specification using template
|
|
18
|
+
5. Validate specification quality
|
|
19
|
+
6. Save to `spec.md`
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Step 1: Create Feature Structure
|
|
24
|
+
|
|
25
|
+
Run the create-new-feature script to set up the branch and directory:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
.claude/skills/specify/scripts/bash/create-new-feature.sh --json "FEATURE_DESCRIPTION"
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
This will output JSON with:
|
|
32
|
+
- `BRANCH_NAME`: e.g., "003-user-auth"
|
|
33
|
+
- `SPEC_FILE`: Full path to spec.md
|
|
34
|
+
- `FEATURE_DIR`: Full path to feature directory
|
|
35
|
+
- `FEATURE_NUM`: e.g., "003"
|
|
36
|
+
|
|
37
|
+
**Important:** Parse this JSON and use these paths for all subsequent operations.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Step 2: Load Constitution & Context
|
|
42
|
+
|
|
43
|
+
1. Read `relentless/constitution.md` for project governance
|
|
44
|
+
2. Note any MUST/SHOULD rules that apply to specifications
|
|
45
|
+
3. Keep these principles in mind while generating the spec
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Step 3: Generate Specification
|
|
50
|
+
|
|
51
|
+
Using the template at `templates/spec-template.md`, create a specification with:
|
|
52
|
+
|
|
53
|
+
### Required Sections:
|
|
54
|
+
|
|
55
|
+
**1. Feature Overview**
|
|
56
|
+
- One-paragraph summary
|
|
57
|
+
- User value proposition
|
|
58
|
+
- Problem being solved
|
|
59
|
+
|
|
60
|
+
**2. User Scenarios & Testing**
|
|
61
|
+
- Concrete user stories
|
|
62
|
+
- Step-by-step flows
|
|
63
|
+
- Expected outcomes
|
|
64
|
+
|
|
65
|
+
**3. Functional Requirements**
|
|
66
|
+
- What the system must do
|
|
67
|
+
- Testable requirements (no implementation details)
|
|
68
|
+
- Clear success criteria
|
|
69
|
+
|
|
70
|
+
**4. Success Criteria**
|
|
71
|
+
- Measurable, technology-agnostic outcomes
|
|
72
|
+
- Quantitative metrics (time, performance, volume)
|
|
73
|
+
- Qualitative measures (user satisfaction, task completion)
|
|
74
|
+
|
|
75
|
+
**5. Key Entities (if applicable)**
|
|
76
|
+
- Data models and relationships
|
|
77
|
+
- Fields and types (logical, not implementation)
|
|
78
|
+
|
|
79
|
+
**6. Dependencies & Assumptions**
|
|
80
|
+
- External systems required
|
|
81
|
+
- Prerequisites
|
|
82
|
+
- Assumptions made
|
|
83
|
+
|
|
84
|
+
**7. Out of Scope**
|
|
85
|
+
- What this feature explicitly does NOT include
|
|
86
|
+
- Future considerations
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Step 4: Handle Ambiguities
|
|
91
|
+
|
|
92
|
+
If aspects are unclear:
|
|
93
|
+
- Make informed guesses based on context
|
|
94
|
+
- Only mark `[NEEDS CLARIFICATION: specific question]` if:
|
|
95
|
+
- Choice significantly impacts scope or UX
|
|
96
|
+
- Multiple reasonable interpretations exist
|
|
97
|
+
- No reasonable default exists
|
|
98
|
+
- **LIMIT: Maximum 3 clarifications**
|
|
99
|
+
|
|
100
|
+
If clarifications needed, present to user:
|
|
101
|
+
|
|
102
|
+
```markdown
|
|
103
|
+
## Clarification Needed
|
|
104
|
+
|
|
105
|
+
**Q1: [Topic]**
|
|
106
|
+
Context: [Quote spec section]
|
|
107
|
+
Question: [Specific question]
|
|
108
|
+
|
|
109
|
+
Options:
|
|
110
|
+
A. [Option 1] - [Implications]
|
|
111
|
+
B. [Option 2] - [Implications]
|
|
112
|
+
C. Custom - [Your answer]
|
|
113
|
+
|
|
114
|
+
Your choice: _
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Step 5: Validate Quality
|
|
120
|
+
|
|
121
|
+
Check the specification against:
|
|
122
|
+
|
|
123
|
+
- [ ] No implementation details (languages, frameworks, APIs)
|
|
124
|
+
- [ ] Focused on user value and business needs
|
|
125
|
+
- [ ] All requirements are testable
|
|
126
|
+
- [ ] Success criteria are measurable
|
|
127
|
+
- [ ] User scenarios cover primary flows
|
|
128
|
+
- [ ] Dependencies identified
|
|
129
|
+
- [ ] Scope clearly bounded
|
|
130
|
+
- [ ] No more than 3 `[NEEDS CLARIFICATION]` markers
|
|
131
|
+
|
|
132
|
+
If validation fails, revise and re-check (max 3 iterations).
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Step 6: Save & Report
|
|
137
|
+
|
|
138
|
+
1. Write complete specification to `SPEC_FILE` from JSON output
|
|
139
|
+
2. Create progress.txt if it doesn't exist:
|
|
140
|
+
```markdown
|
|
141
|
+
---
|
|
142
|
+
feature: FEATURE_NAME
|
|
143
|
+
started: DATE
|
|
144
|
+
last_updated: DATE
|
|
145
|
+
stories_completed: 0
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
# Progress Log: FEATURE_NAME
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
3. Report to user:
|
|
152
|
+
- Branch created: `BRANCH_NAME`
|
|
153
|
+
- Spec saved: `SPEC_FILE`
|
|
154
|
+
- Quality validation: PASSED/FAILED
|
|
155
|
+
- Next step: `/relentless.plan` or `/relentless.clarify`
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## Example Output
|
|
160
|
+
|
|
161
|
+
```markdown
|
|
162
|
+
# Feature: User Authentication
|
|
163
|
+
|
|
164
|
+
## Overview
|
|
165
|
+
Enable users to create accounts and log in securely using email/password.
|
|
166
|
+
|
|
167
|
+
## User Scenarios
|
|
168
|
+
|
|
169
|
+
### Scenario 1: New User Registration
|
|
170
|
+
1. User visits signup page
|
|
171
|
+
2. Enters email and password
|
|
172
|
+
3. Submits form
|
|
173
|
+
4. Receives confirmation email
|
|
174
|
+
5. Clicks confirmation link
|
|
175
|
+
6. Account is activated
|
|
176
|
+
|
|
177
|
+
**Expected Outcome:** User has active account and can log in.
|
|
178
|
+
|
|
179
|
+
## Functional Requirements
|
|
180
|
+
|
|
181
|
+
**REQ-1:** System must validate email format
|
|
182
|
+
**REQ-2:** System must require passwords ≥ 8 characters
|
|
183
|
+
**REQ-3:** System must send confirmation email within 1 minute
|
|
184
|
+
**REQ-4:** System must hash passwords before storage
|
|
185
|
+
|
|
186
|
+
## Success Criteria
|
|
187
|
+
|
|
188
|
+
1. 95% of signups complete within 60 seconds
|
|
189
|
+
2. Zero plaintext passwords in database
|
|
190
|
+
3. Email confirmation rate > 80%
|
|
191
|
+
|
|
192
|
+
## Key Entities
|
|
193
|
+
|
|
194
|
+
**User**
|
|
195
|
+
- email: string (unique)
|
|
196
|
+
- password_hash: string
|
|
197
|
+
- confirmed: boolean
|
|
198
|
+
- created_at: timestamp
|
|
199
|
+
|
|
200
|
+
## Dependencies
|
|
201
|
+
|
|
202
|
+
- Email service provider (e.g., SendGrid, Mailgun)
|
|
203
|
+
- Session management system
|
|
204
|
+
|
|
205
|
+
## Out of Scope
|
|
206
|
+
|
|
207
|
+
- Social login (OAuth)
|
|
208
|
+
- Two-factor authentication
|
|
209
|
+
- Password reset (separate feature)
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## Notes
|
|
215
|
+
|
|
216
|
+
- Always run the script first to get proper paths
|
|
217
|
+
- Use absolute paths from JSON output
|
|
218
|
+
- Validate before marking complete
|
|
219
|
+
- Keep specification technology-agnostic
|
|
220
|
+
- Focus on WHAT, not HOW
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
# Consolidated prerequisite checking script
|
|
4
|
+
#
|
|
5
|
+
# This script provides unified prerequisite checking for Spec-Driven Development workflow.
|
|
6
|
+
# It replaces the functionality previously spread across multiple scripts.
|
|
7
|
+
#
|
|
8
|
+
# Usage: ./check-prerequisites.sh [OPTIONS]
|
|
9
|
+
#
|
|
10
|
+
# OPTIONS:
|
|
11
|
+
# --json Output in JSON format
|
|
12
|
+
# --require-tasks Require tasks.md to exist (for implementation phase)
|
|
13
|
+
# --include-tasks Include tasks.md in AVAILABLE_DOCS list
|
|
14
|
+
# --paths-only Only output path variables (no validation)
|
|
15
|
+
# --help, -h Show help message
|
|
16
|
+
#
|
|
17
|
+
# OUTPUTS:
|
|
18
|
+
# JSON mode: {"FEATURE_DIR":"...", "AVAILABLE_DOCS":["..."]}
|
|
19
|
+
# Text mode: FEATURE_DIR:... \n AVAILABLE_DOCS: \n ✓/✗ file.md
|
|
20
|
+
# Paths only: REPO_ROOT: ... \n BRANCH: ... \n FEATURE_DIR: ... etc.
|
|
21
|
+
|
|
22
|
+
set -e
|
|
23
|
+
|
|
24
|
+
# Parse command line arguments
|
|
25
|
+
JSON_MODE=false
|
|
26
|
+
REQUIRE_TASKS=false
|
|
27
|
+
INCLUDE_TASKS=false
|
|
28
|
+
PATHS_ONLY=false
|
|
29
|
+
|
|
30
|
+
for arg in "$@"; do
|
|
31
|
+
case "$arg" in
|
|
32
|
+
--json)
|
|
33
|
+
JSON_MODE=true
|
|
34
|
+
;;
|
|
35
|
+
--require-tasks)
|
|
36
|
+
REQUIRE_TASKS=true
|
|
37
|
+
;;
|
|
38
|
+
--include-tasks)
|
|
39
|
+
INCLUDE_TASKS=true
|
|
40
|
+
;;
|
|
41
|
+
--paths-only)
|
|
42
|
+
PATHS_ONLY=true
|
|
43
|
+
;;
|
|
44
|
+
--help|-h)
|
|
45
|
+
cat << 'EOF'
|
|
46
|
+
Usage: check-prerequisites.sh [OPTIONS]
|
|
47
|
+
|
|
48
|
+
Consolidated prerequisite checking for Spec-Driven Development workflow.
|
|
49
|
+
|
|
50
|
+
OPTIONS:
|
|
51
|
+
--json Output in JSON format
|
|
52
|
+
--require-tasks Require tasks.md to exist (for implementation phase)
|
|
53
|
+
--include-tasks Include tasks.md in AVAILABLE_DOCS list
|
|
54
|
+
--paths-only Only output path variables (no prerequisite validation)
|
|
55
|
+
--help, -h Show this help message
|
|
56
|
+
|
|
57
|
+
EXAMPLES:
|
|
58
|
+
# Check task prerequisites (plan.md required)
|
|
59
|
+
./check-prerequisites.sh --json
|
|
60
|
+
|
|
61
|
+
# Check implementation prerequisites (plan.md + tasks.md required)
|
|
62
|
+
./check-prerequisites.sh --json --require-tasks --include-tasks
|
|
63
|
+
|
|
64
|
+
# Get feature paths only (no validation)
|
|
65
|
+
./check-prerequisites.sh --paths-only
|
|
66
|
+
|
|
67
|
+
EOF
|
|
68
|
+
exit 0
|
|
69
|
+
;;
|
|
70
|
+
*)
|
|
71
|
+
echo "ERROR: Unknown option '$arg'. Use --help for usage information." >&2
|
|
72
|
+
exit 1
|
|
73
|
+
;;
|
|
74
|
+
esac
|
|
75
|
+
done
|
|
76
|
+
|
|
77
|
+
# Source common functions
|
|
78
|
+
SCRIPT_DIR="$(CDPATH="" cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
79
|
+
source "$SCRIPT_DIR/common.sh"
|
|
80
|
+
|
|
81
|
+
# Get feature paths and validate branch
|
|
82
|
+
eval $(get_feature_paths)
|
|
83
|
+
check_feature_branch "$CURRENT_BRANCH" "$HAS_GIT" || exit 1
|
|
84
|
+
|
|
85
|
+
# If paths-only mode, output paths and exit (support JSON + paths-only combined)
|
|
86
|
+
if $PATHS_ONLY; then
|
|
87
|
+
if $JSON_MODE; then
|
|
88
|
+
# Minimal JSON paths payload (no validation performed)
|
|
89
|
+
printf '{"REPO_ROOT":"%s","BRANCH":"%s","FEATURE_DIR":"%s","FEATURE_SPEC":"%s","IMPL_PLAN":"%s","TASKS":"%s"}\n' \
|
|
90
|
+
"$REPO_ROOT" "$CURRENT_BRANCH" "$FEATURE_DIR" "$FEATURE_SPEC" "$IMPL_PLAN" "$TASKS"
|
|
91
|
+
else
|
|
92
|
+
echo "REPO_ROOT: $REPO_ROOT"
|
|
93
|
+
echo "BRANCH: $CURRENT_BRANCH"
|
|
94
|
+
echo "FEATURE_DIR: $FEATURE_DIR"
|
|
95
|
+
echo "FEATURE_SPEC: $FEATURE_SPEC"
|
|
96
|
+
echo "IMPL_PLAN: $IMPL_PLAN"
|
|
97
|
+
echo "TASKS: $TASKS"
|
|
98
|
+
fi
|
|
99
|
+
exit 0
|
|
100
|
+
fi
|
|
101
|
+
|
|
102
|
+
# Validate required directories and files
|
|
103
|
+
if [[ ! -d "$FEATURE_DIR" ]]; then
|
|
104
|
+
echo "ERROR: Feature directory not found: $FEATURE_DIR" >&2
|
|
105
|
+
echo "Run /relentless.specify first to create the feature structure." >&2
|
|
106
|
+
exit 1
|
|
107
|
+
fi
|
|
108
|
+
|
|
109
|
+
if [[ ! -f "$IMPL_PLAN" ]]; then
|
|
110
|
+
echo "ERROR: plan.md not found in $FEATURE_DIR" >&2
|
|
111
|
+
echo "Run /relentless.plan first to create the implementation plan." >&2
|
|
112
|
+
exit 1
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
# Check for tasks.md if required
|
|
116
|
+
if $REQUIRE_TASKS && [[ ! -f "$TASKS" ]]; then
|
|
117
|
+
echo "ERROR: tasks.md not found in $FEATURE_DIR" >&2
|
|
118
|
+
echo "Run /relentless.tasks first to create the task list." >&2
|
|
119
|
+
exit 1
|
|
120
|
+
fi
|
|
121
|
+
|
|
122
|
+
# Build list of available documents
|
|
123
|
+
docs=()
|
|
124
|
+
|
|
125
|
+
# Always check these optional docs
|
|
126
|
+
[[ -f "$RESEARCH" ]] && docs+=("research.md")
|
|
127
|
+
[[ -f "$DATA_MODEL" ]] && docs+=("data-model.md")
|
|
128
|
+
|
|
129
|
+
# Check contracts directory (only if it exists and has files)
|
|
130
|
+
if [[ -d "$CONTRACTS_DIR" ]] && [[ -n "$(ls -A "$CONTRACTS_DIR" 2>/dev/null)" ]]; then
|
|
131
|
+
docs+=("contracts/")
|
|
132
|
+
fi
|
|
133
|
+
|
|
134
|
+
[[ -f "$QUICKSTART" ]] && docs+=("quickstart.md")
|
|
135
|
+
|
|
136
|
+
# Include tasks.md if requested and it exists
|
|
137
|
+
if $INCLUDE_TASKS && [[ -f "$TASKS" ]]; then
|
|
138
|
+
docs+=("tasks.md")
|
|
139
|
+
fi
|
|
140
|
+
|
|
141
|
+
# Output results
|
|
142
|
+
if $JSON_MODE; then
|
|
143
|
+
# Build JSON array of documents
|
|
144
|
+
if [[ ${#docs[@]} -eq 0 ]]; then
|
|
145
|
+
json_docs="[]"
|
|
146
|
+
else
|
|
147
|
+
json_docs=$(printf '"%s",' "${docs[@]}")
|
|
148
|
+
json_docs="[${json_docs%,}]"
|
|
149
|
+
fi
|
|
150
|
+
|
|
151
|
+
printf '{"FEATURE_DIR":"%s","AVAILABLE_DOCS":%s}\n' "$FEATURE_DIR" "$json_docs"
|
|
152
|
+
else
|
|
153
|
+
# Text output
|
|
154
|
+
echo "FEATURE_DIR:$FEATURE_DIR"
|
|
155
|
+
echo "AVAILABLE_DOCS:"
|
|
156
|
+
|
|
157
|
+
# Show status of each potential document
|
|
158
|
+
check_file "$RESEARCH" "research.md"
|
|
159
|
+
check_file "$DATA_MODEL" "data-model.md"
|
|
160
|
+
check_dir "$CONTRACTS_DIR" "contracts/"
|
|
161
|
+
check_file "$QUICKSTART" "quickstart.md"
|
|
162
|
+
|
|
163
|
+
if $INCLUDE_TASKS; then
|
|
164
|
+
check_file "$TASKS" "tasks.md"
|
|
165
|
+
fi
|
|
166
|
+
fi
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Common functions and variables for all scripts
|
|
3
|
+
|
|
4
|
+
# Get repository root, with fallback for non-git repositories
|
|
5
|
+
get_repo_root() {
|
|
6
|
+
if git rev-parse --show-toplevel >/dev/null 2>&1; then
|
|
7
|
+
git rev-parse --show-toplevel
|
|
8
|
+
else
|
|
9
|
+
# Fall back to script location for non-git repos
|
|
10
|
+
local script_dir="$(CDPATH="" cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
|
+
(cd "$script_dir/../../.." && pwd)
|
|
12
|
+
fi
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
# Get current branch, with fallback for non-git repositories
|
|
16
|
+
get_current_branch() {
|
|
17
|
+
# First check if SPECIFY_FEATURE environment variable is set
|
|
18
|
+
if [[ -n "${SPECIFY_FEATURE:-}" ]]; then
|
|
19
|
+
echo "$SPECIFY_FEATURE"
|
|
20
|
+
return
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
# Then check git if available
|
|
24
|
+
if git rev-parse --abbrev-ref HEAD >/dev/null 2>&1; then
|
|
25
|
+
git rev-parse --abbrev-ref HEAD
|
|
26
|
+
return
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
# For non-git repos, try to find the latest feature directory
|
|
30
|
+
local repo_root=$(get_repo_root)
|
|
31
|
+
local specs_dir="$repo_root/specs"
|
|
32
|
+
|
|
33
|
+
if [[ -d "$specs_dir" ]]; then
|
|
34
|
+
local latest_feature=""
|
|
35
|
+
local highest=0
|
|
36
|
+
|
|
37
|
+
for dir in "$specs_dir"/*; do
|
|
38
|
+
if [[ -d "$dir" ]]; then
|
|
39
|
+
local dirname=$(basename "$dir")
|
|
40
|
+
if [[ "$dirname" =~ ^([0-9]{3})- ]]; then
|
|
41
|
+
local number=${BASH_REMATCH[1]}
|
|
42
|
+
number=$((10#$number))
|
|
43
|
+
if [[ "$number" -gt "$highest" ]]; then
|
|
44
|
+
highest=$number
|
|
45
|
+
latest_feature=$dirname
|
|
46
|
+
fi
|
|
47
|
+
fi
|
|
48
|
+
fi
|
|
49
|
+
done
|
|
50
|
+
|
|
51
|
+
if [[ -n "$latest_feature" ]]; then
|
|
52
|
+
echo "$latest_feature"
|
|
53
|
+
return
|
|
54
|
+
fi
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
echo "main" # Final fallback
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
# Check if we have git available
|
|
61
|
+
has_git() {
|
|
62
|
+
git rev-parse --show-toplevel >/dev/null 2>&1
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
check_feature_branch() {
|
|
66
|
+
local branch="$1"
|
|
67
|
+
local has_git_repo="$2"
|
|
68
|
+
|
|
69
|
+
# For non-git repos, we can't enforce branch naming but still provide output
|
|
70
|
+
if [[ "$has_git_repo" != "true" ]]; then
|
|
71
|
+
echo "[specify] Warning: Git repository not detected; skipped branch validation" >&2
|
|
72
|
+
return 0
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
if [[ ! "$branch" =~ ^[0-9]{3}- ]]; then
|
|
76
|
+
echo "ERROR: Not on a feature branch. Current branch: $branch" >&2
|
|
77
|
+
echo "Feature branches should be named like: 001-feature-name" >&2
|
|
78
|
+
return 1
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
return 0
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
get_feature_dir() { echo "$1/relentless/features/$2"; }
|
|
85
|
+
|
|
86
|
+
# Find feature directory by numeric prefix instead of exact branch match
|
|
87
|
+
# This allows multiple branches to work on the same spec (e.g., 004-fix-bug, 004-add-feature)
|
|
88
|
+
find_feature_dir_by_prefix() {
|
|
89
|
+
local repo_root="$1"
|
|
90
|
+
local branch_name="$2"
|
|
91
|
+
local specs_dir="$repo_root/specs"
|
|
92
|
+
|
|
93
|
+
# Extract numeric prefix from branch (e.g., "004" from "004-whatever")
|
|
94
|
+
if [[ ! "$branch_name" =~ ^([0-9]{3})- ]]; then
|
|
95
|
+
# If branch doesn't have numeric prefix, fall back to exact match
|
|
96
|
+
echo "$specs_dir/$branch_name"
|
|
97
|
+
return
|
|
98
|
+
fi
|
|
99
|
+
|
|
100
|
+
local prefix="${BASH_REMATCH[1]}"
|
|
101
|
+
|
|
102
|
+
# Search for directories in specs/ that start with this prefix
|
|
103
|
+
local matches=()
|
|
104
|
+
if [[ -d "$specs_dir" ]]; then
|
|
105
|
+
for dir in "$specs_dir"/"$prefix"-*; do
|
|
106
|
+
if [[ -d "$dir" ]]; then
|
|
107
|
+
matches+=("$(basename "$dir")")
|
|
108
|
+
fi
|
|
109
|
+
done
|
|
110
|
+
fi
|
|
111
|
+
|
|
112
|
+
# Handle results
|
|
113
|
+
if [[ ${#matches[@]} -eq 0 ]]; then
|
|
114
|
+
# No match found - return the branch name path (will fail later with clear error)
|
|
115
|
+
echo "$specs_dir/$branch_name"
|
|
116
|
+
elif [[ ${#matches[@]} -eq 1 ]]; then
|
|
117
|
+
# Exactly one match - perfect!
|
|
118
|
+
echo "$specs_dir/${matches[0]}"
|
|
119
|
+
else
|
|
120
|
+
# Multiple matches - this shouldn't happen with proper naming convention
|
|
121
|
+
echo "ERROR: Multiple spec directories found with prefix '$prefix': ${matches[*]}" >&2
|
|
122
|
+
echo "Please ensure only one spec directory exists per numeric prefix." >&2
|
|
123
|
+
echo "$specs_dir/$branch_name" # Return something to avoid breaking the script
|
|
124
|
+
fi
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
get_feature_paths() {
|
|
128
|
+
local repo_root=$(get_repo_root)
|
|
129
|
+
local current_branch=$(get_current_branch)
|
|
130
|
+
local has_git_repo="false"
|
|
131
|
+
|
|
132
|
+
if has_git; then
|
|
133
|
+
has_git_repo="true"
|
|
134
|
+
fi
|
|
135
|
+
|
|
136
|
+
# Use prefix-based lookup to support multiple branches per spec
|
|
137
|
+
local feature_dir=$(find_feature_dir_by_prefix "$repo_root" "$current_branch")
|
|
138
|
+
|
|
139
|
+
cat <<EOF
|
|
140
|
+
REPO_ROOT='$repo_root'
|
|
141
|
+
CURRENT_BRANCH='$current_branch'
|
|
142
|
+
HAS_GIT='$has_git_repo'
|
|
143
|
+
FEATURE_DIR='$feature_dir'
|
|
144
|
+
FEATURE_SPEC='$feature_dir/spec.md'
|
|
145
|
+
IMPL_PLAN='$feature_dir/plan.md'
|
|
146
|
+
TASKS='$feature_dir/tasks.md'
|
|
147
|
+
RESEARCH='$feature_dir/research.md'
|
|
148
|
+
DATA_MODEL='$feature_dir/data-model.md'
|
|
149
|
+
QUICKSTART='$feature_dir/quickstart.md'
|
|
150
|
+
CONTRACTS_DIR='$feature_dir/contracts'
|
|
151
|
+
EOF
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
check_file() { [[ -f "$1" ]] && echo " ✓ $2" || echo " ✗ $2"; }
|
|
155
|
+
check_dir() { [[ -d "$1" && -n $(ls -A "$1" 2>/dev/null) ]] && echo " ✓ $2" || echo " ✗ $2"; }
|
|
156
|
+
|