@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,305 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
set -e
|
|
4
|
+
|
|
5
|
+
JSON_MODE=false
|
|
6
|
+
SHORT_NAME=""
|
|
7
|
+
BRANCH_NUMBER=""
|
|
8
|
+
ARGS=()
|
|
9
|
+
i=1
|
|
10
|
+
while [ $i -le $# ]; do
|
|
11
|
+
arg="${!i}"
|
|
12
|
+
case "$arg" in
|
|
13
|
+
--json)
|
|
14
|
+
JSON_MODE=true
|
|
15
|
+
;;
|
|
16
|
+
--short-name)
|
|
17
|
+
if [ $((i + 1)) -gt $# ]; then
|
|
18
|
+
echo 'Error: --short-name requires a value' >&2
|
|
19
|
+
exit 1
|
|
20
|
+
fi
|
|
21
|
+
i=$((i + 1))
|
|
22
|
+
next_arg="${!i}"
|
|
23
|
+
# Check if the next argument is another option (starts with --)
|
|
24
|
+
if [[ "$next_arg" == --* ]]; then
|
|
25
|
+
echo 'Error: --short-name requires a value' >&2
|
|
26
|
+
exit 1
|
|
27
|
+
fi
|
|
28
|
+
SHORT_NAME="$next_arg"
|
|
29
|
+
;;
|
|
30
|
+
--number)
|
|
31
|
+
if [ $((i + 1)) -gt $# ]; then
|
|
32
|
+
echo 'Error: --number requires a value' >&2
|
|
33
|
+
exit 1
|
|
34
|
+
fi
|
|
35
|
+
i=$((i + 1))
|
|
36
|
+
next_arg="${!i}"
|
|
37
|
+
if [[ "$next_arg" == --* ]]; then
|
|
38
|
+
echo 'Error: --number requires a value' >&2
|
|
39
|
+
exit 1
|
|
40
|
+
fi
|
|
41
|
+
BRANCH_NUMBER="$next_arg"
|
|
42
|
+
;;
|
|
43
|
+
--help|-h)
|
|
44
|
+
echo "Usage: $0 [--json] [--short-name <name>] [--number N] <feature_description>"
|
|
45
|
+
echo ""
|
|
46
|
+
echo "Options:"
|
|
47
|
+
echo " --json Output in JSON format"
|
|
48
|
+
echo " --short-name <name> Provide a custom short name (2-4 words) for the branch"
|
|
49
|
+
echo " --number N Specify branch number manually (overrides auto-detection)"
|
|
50
|
+
echo " --help, -h Show this help message"
|
|
51
|
+
echo ""
|
|
52
|
+
echo "Examples:"
|
|
53
|
+
echo " $0 'Add user authentication system' --short-name 'user-auth'"
|
|
54
|
+
echo " $0 'Implement OAuth2 integration for API' --number 5"
|
|
55
|
+
exit 0
|
|
56
|
+
;;
|
|
57
|
+
*)
|
|
58
|
+
ARGS+=("$arg")
|
|
59
|
+
;;
|
|
60
|
+
esac
|
|
61
|
+
i=$((i + 1))
|
|
62
|
+
done
|
|
63
|
+
|
|
64
|
+
FEATURE_DESCRIPTION="${ARGS[*]}"
|
|
65
|
+
if [ -z "$FEATURE_DESCRIPTION" ]; then
|
|
66
|
+
echo "Usage: $0 [--json] [--short-name <name>] [--number N] <feature_description>" >&2
|
|
67
|
+
exit 1
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
# Function to find the repository root by searching for existing project markers
|
|
71
|
+
find_repo_root() {
|
|
72
|
+
local dir="$1"
|
|
73
|
+
while [ "$dir" != "/" ]; do
|
|
74
|
+
if [ -d "$dir/.git" ] || [ -d "$dir/relentless" ]; then
|
|
75
|
+
echo "$dir"
|
|
76
|
+
return 0
|
|
77
|
+
fi
|
|
78
|
+
dir="$(dirname "$dir")"
|
|
79
|
+
done
|
|
80
|
+
return 1
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
# Function to get highest number from relentless/features directory
|
|
84
|
+
get_highest_from_features() {
|
|
85
|
+
local features_dir="$1"
|
|
86
|
+
local highest=0
|
|
87
|
+
|
|
88
|
+
if [ -d "$features_dir" ]; then
|
|
89
|
+
for dir in "$features_dir"/*; do
|
|
90
|
+
[ -d "$dir" ] || continue
|
|
91
|
+
dirname=$(basename "$dir")
|
|
92
|
+
number=$(echo "$dirname" | grep -o '^[0-9]\+' || echo "0")
|
|
93
|
+
number=$((10#$number))
|
|
94
|
+
if [ "$number" -gt "$highest" ]; then
|
|
95
|
+
highest=$number
|
|
96
|
+
fi
|
|
97
|
+
done
|
|
98
|
+
fi
|
|
99
|
+
|
|
100
|
+
echo "$highest"
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
# Function to get highest number from git branches
|
|
104
|
+
get_highest_from_branches() {
|
|
105
|
+
local highest=0
|
|
106
|
+
|
|
107
|
+
# Get all branches (local and remote)
|
|
108
|
+
branches=$(git branch -a 2>/dev/null || echo "")
|
|
109
|
+
|
|
110
|
+
if [ -n "$branches" ]; then
|
|
111
|
+
while IFS= read -r branch; do
|
|
112
|
+
# Clean branch name: remove leading markers and remote prefixes
|
|
113
|
+
clean_branch=$(echo "$branch" | sed 's/^[* ]*//; s|^remotes/[^/]*/||')
|
|
114
|
+
|
|
115
|
+
# Extract feature number if branch matches pattern ###-*
|
|
116
|
+
if echo "$clean_branch" | grep -q '^[0-9]\{3\}-'; then
|
|
117
|
+
number=$(echo "$clean_branch" | grep -o '^[0-9]\{3\}' || echo "0")
|
|
118
|
+
number=$((10#$number))
|
|
119
|
+
if [ "$number" -gt "$highest" ]; then
|
|
120
|
+
highest=$number
|
|
121
|
+
fi
|
|
122
|
+
fi
|
|
123
|
+
done <<< "$branches"
|
|
124
|
+
fi
|
|
125
|
+
|
|
126
|
+
echo "$highest"
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
# Function to check existing branches (local and remote) and return next available number
|
|
130
|
+
check_existing_branches() {
|
|
131
|
+
local features_dir="$1"
|
|
132
|
+
|
|
133
|
+
# Fetch all remotes to get latest branch info (suppress errors if no remotes)
|
|
134
|
+
git fetch --all --prune 2>/dev/null || true
|
|
135
|
+
|
|
136
|
+
# Get highest number from ALL branches (not just matching short name)
|
|
137
|
+
local highest_branch=$(get_highest_from_branches)
|
|
138
|
+
|
|
139
|
+
# Get highest number from ALL features (not just matching short name)
|
|
140
|
+
local highest_feature=$(get_highest_from_features "$features_dir")
|
|
141
|
+
|
|
142
|
+
# Take the maximum of both
|
|
143
|
+
local max_num=$highest_branch
|
|
144
|
+
if [ "$highest_feature" -gt "$max_num" ]; then
|
|
145
|
+
max_num=$highest_feature
|
|
146
|
+
fi
|
|
147
|
+
|
|
148
|
+
# Return next number
|
|
149
|
+
echo $((max_num + 1))
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
# Function to clean and format a branch name
|
|
153
|
+
clean_branch_name() {
|
|
154
|
+
local name="$1"
|
|
155
|
+
echo "$name" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/-\+/-/g' | sed 's/^-//' | sed 's/-$//'
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
# Resolve repository root. Prefer git information when available, but fall back
|
|
159
|
+
# to searching for repository markers so the workflow still functions in repositories that
|
|
160
|
+
# were initialised with --no-git.
|
|
161
|
+
SCRIPT_DIR="$(CDPATH="" cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
162
|
+
|
|
163
|
+
if git rev-parse --show-toplevel >/dev/null 2>&1; then
|
|
164
|
+
REPO_ROOT=$(git rev-parse --show-toplevel)
|
|
165
|
+
HAS_GIT=true
|
|
166
|
+
else
|
|
167
|
+
REPO_ROOT="$(find_repo_root "$SCRIPT_DIR")"
|
|
168
|
+
if [ -z "$REPO_ROOT" ]; then
|
|
169
|
+
echo "Error: Could not determine repository root. Please run this script from within the repository." >&2
|
|
170
|
+
exit 1
|
|
171
|
+
fi
|
|
172
|
+
HAS_GIT=false
|
|
173
|
+
fi
|
|
174
|
+
|
|
175
|
+
cd "$REPO_ROOT"
|
|
176
|
+
|
|
177
|
+
FEATURES_DIR="$REPO_ROOT/relentless/features"
|
|
178
|
+
mkdir -p "$FEATURES_DIR"
|
|
179
|
+
|
|
180
|
+
# Function to generate branch name with stop word filtering and length filtering
|
|
181
|
+
generate_branch_name() {
|
|
182
|
+
local description="$1"
|
|
183
|
+
|
|
184
|
+
# Common stop words to filter out
|
|
185
|
+
local stop_words="^(i|a|an|the|to|for|of|in|on|at|by|with|from|is|are|was|were|be|been|being|have|has|had|do|does|did|will|would|should|could|can|may|might|must|shall|this|that|these|those|my|your|our|their|want|need|add|get|set)$"
|
|
186
|
+
|
|
187
|
+
# Convert to lowercase and split into words
|
|
188
|
+
local clean_name=$(echo "$description" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/ /g')
|
|
189
|
+
|
|
190
|
+
# Filter words: remove stop words and words shorter than 3 chars (unless they're uppercase acronyms in original)
|
|
191
|
+
local meaningful_words=()
|
|
192
|
+
for word in $clean_name; do
|
|
193
|
+
# Skip empty words
|
|
194
|
+
[ -z "$word" ] && continue
|
|
195
|
+
|
|
196
|
+
# Keep words that are NOT stop words AND (length >= 3 OR are potential acronyms)
|
|
197
|
+
if ! echo "$word" | grep -qiE "$stop_words"; then
|
|
198
|
+
if [ ${#word} -ge 3 ]; then
|
|
199
|
+
meaningful_words+=("$word")
|
|
200
|
+
elif echo "$description" | grep -q "\b${word^^}\b"; then
|
|
201
|
+
# Keep short words if they appear as uppercase in original (likely acronyms)
|
|
202
|
+
meaningful_words+=("$word")
|
|
203
|
+
fi
|
|
204
|
+
fi
|
|
205
|
+
done
|
|
206
|
+
|
|
207
|
+
# If we have meaningful words, use first 3-4 of them
|
|
208
|
+
if [ ${#meaningful_words[@]} -gt 0 ]; then
|
|
209
|
+
local max_words=3
|
|
210
|
+
if [ ${#meaningful_words[@]} -eq 4 ]; then max_words=4; fi
|
|
211
|
+
|
|
212
|
+
local result=""
|
|
213
|
+
local count=0
|
|
214
|
+
for word in "${meaningful_words[@]}"; do
|
|
215
|
+
if [ $count -ge $max_words ]; then break; fi
|
|
216
|
+
if [ -n "$result" ]; then result="$result-"; fi
|
|
217
|
+
result="$result$word"
|
|
218
|
+
count=$((count + 1))
|
|
219
|
+
done
|
|
220
|
+
echo "$result"
|
|
221
|
+
else
|
|
222
|
+
# Fallback to original logic if no meaningful words found
|
|
223
|
+
local cleaned=$(clean_branch_name "$description")
|
|
224
|
+
echo "$cleaned" | tr '-' '\n' | grep -v '^$' | head -3 | tr '\n' '-' | sed 's/-$//'
|
|
225
|
+
fi
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
# Generate branch name
|
|
229
|
+
if [ -n "$SHORT_NAME" ]; then
|
|
230
|
+
# Use provided short name, just clean it up
|
|
231
|
+
BRANCH_SUFFIX=$(clean_branch_name "$SHORT_NAME")
|
|
232
|
+
else
|
|
233
|
+
# Generate from description with smart filtering
|
|
234
|
+
BRANCH_SUFFIX=$(generate_branch_name "$FEATURE_DESCRIPTION")
|
|
235
|
+
fi
|
|
236
|
+
|
|
237
|
+
# Determine branch number
|
|
238
|
+
if [ -z "$BRANCH_NUMBER" ]; then
|
|
239
|
+
if [ "$HAS_GIT" = true ]; then
|
|
240
|
+
# Check existing branches on remotes
|
|
241
|
+
BRANCH_NUMBER=$(check_existing_branches "$FEATURES_DIR")
|
|
242
|
+
else
|
|
243
|
+
# Fall back to local directory check
|
|
244
|
+
HIGHEST=$(get_highest_from_features "$FEATURES_DIR")
|
|
245
|
+
BRANCH_NUMBER=$((HIGHEST + 1))
|
|
246
|
+
fi
|
|
247
|
+
fi
|
|
248
|
+
|
|
249
|
+
# Force base-10 interpretation to prevent octal conversion (e.g., 010 → 8 in octal, but should be 10 in decimal)
|
|
250
|
+
FEATURE_NUM=$(printf "%03d" "$((10#$BRANCH_NUMBER))")
|
|
251
|
+
BRANCH_NAME="${FEATURE_NUM}-${BRANCH_SUFFIX}"
|
|
252
|
+
|
|
253
|
+
# GitHub enforces a 244-byte limit on branch names
|
|
254
|
+
# Validate and truncate if necessary
|
|
255
|
+
MAX_BRANCH_LENGTH=244
|
|
256
|
+
if [ ${#BRANCH_NAME} -gt $MAX_BRANCH_LENGTH ]; then
|
|
257
|
+
# Calculate how much we need to trim from suffix
|
|
258
|
+
# Account for: feature number (3) + hyphen (1) = 4 chars
|
|
259
|
+
MAX_SUFFIX_LENGTH=$((MAX_BRANCH_LENGTH - 4))
|
|
260
|
+
|
|
261
|
+
# Truncate suffix at word boundary if possible
|
|
262
|
+
TRUNCATED_SUFFIX=$(echo "$BRANCH_SUFFIX" | cut -c1-$MAX_SUFFIX_LENGTH)
|
|
263
|
+
# Remove trailing hyphen if truncation created one
|
|
264
|
+
TRUNCATED_SUFFIX=$(echo "$TRUNCATED_SUFFIX" | sed 's/-$//')
|
|
265
|
+
|
|
266
|
+
ORIGINAL_BRANCH_NAME="$BRANCH_NAME"
|
|
267
|
+
BRANCH_NAME="${FEATURE_NUM}-${TRUNCATED_SUFFIX}"
|
|
268
|
+
|
|
269
|
+
>&2 echo "[specify] Warning: Branch name exceeded GitHub's 244-byte limit"
|
|
270
|
+
>&2 echo "[specify] Original: $ORIGINAL_BRANCH_NAME (${#ORIGINAL_BRANCH_NAME} bytes)"
|
|
271
|
+
>&2 echo "[specify] Truncated to: $BRANCH_NAME (${#BRANCH_NAME} bytes)"
|
|
272
|
+
fi
|
|
273
|
+
|
|
274
|
+
if [ "$HAS_GIT" = true ]; then
|
|
275
|
+
git checkout -b "$BRANCH_NAME"
|
|
276
|
+
else
|
|
277
|
+
>&2 echo "[specify] Warning: Git repository not detected; skipped branch creation for $BRANCH_NAME"
|
|
278
|
+
fi
|
|
279
|
+
|
|
280
|
+
FEATURE_DIR="$FEATURES_DIR/$BRANCH_NAME"
|
|
281
|
+
mkdir -p "$FEATURE_DIR"
|
|
282
|
+
|
|
283
|
+
# Find spec template in skills directory
|
|
284
|
+
SKILLS_DIR="$REPO_ROOT/.claude/skills/specify"
|
|
285
|
+
TEMPLATE="$SKILLS_DIR/templates/spec-template.md"
|
|
286
|
+
if [ ! -f "$TEMPLATE" ]; then
|
|
287
|
+
# Fallback to old location for compatibility
|
|
288
|
+
TEMPLATE="$REPO_ROOT/.claude/skills/templates/spec-template.md"
|
|
289
|
+
fi
|
|
290
|
+
|
|
291
|
+
SPEC_FILE="$FEATURE_DIR/spec.md"
|
|
292
|
+
if [ -f "$TEMPLATE" ]; then cp "$TEMPLATE" "$SPEC_FILE"; else touch "$SPEC_FILE"; fi
|
|
293
|
+
|
|
294
|
+
# Set the SPECIFY_FEATURE environment variable for the current session
|
|
295
|
+
export SPECIFY_FEATURE="$BRANCH_NAME"
|
|
296
|
+
|
|
297
|
+
if $JSON_MODE; then
|
|
298
|
+
printf '{"BRANCH_NAME":"%s","SPEC_FILE":"%s","FEATURE_NUM":"%s","FEATURE_DIR":"%s"}\n' "$BRANCH_NAME" "$SPEC_FILE" "$FEATURE_NUM" "$FEATURE_DIR"
|
|
299
|
+
else
|
|
300
|
+
echo "BRANCH_NAME: $BRANCH_NAME"
|
|
301
|
+
echo "SPEC_FILE: $SPEC_FILE"
|
|
302
|
+
echo "FEATURE_NUM: $FEATURE_NUM"
|
|
303
|
+
echo "FEATURE_DIR: $FEATURE_DIR"
|
|
304
|
+
echo "SPECIFY_FEATURE environment variable set to: $BRANCH_NAME"
|
|
305
|
+
fi
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
set -e
|
|
4
|
+
|
|
5
|
+
# Parse command line arguments
|
|
6
|
+
JSON_MODE=false
|
|
7
|
+
ARGS=()
|
|
8
|
+
|
|
9
|
+
for arg in "$@"; do
|
|
10
|
+
case "$arg" in
|
|
11
|
+
--json)
|
|
12
|
+
JSON_MODE=true
|
|
13
|
+
;;
|
|
14
|
+
--help|-h)
|
|
15
|
+
echo "Usage: $0 [--json]"
|
|
16
|
+
echo " --json Output results in JSON format"
|
|
17
|
+
echo " --help Show this help message"
|
|
18
|
+
exit 0
|
|
19
|
+
;;
|
|
20
|
+
*)
|
|
21
|
+
ARGS+=("$arg")
|
|
22
|
+
;;
|
|
23
|
+
esac
|
|
24
|
+
done
|
|
25
|
+
|
|
26
|
+
# Get script directory and load common functions
|
|
27
|
+
SCRIPT_DIR="$(CDPATH="" cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
28
|
+
source "$SCRIPT_DIR/common.sh"
|
|
29
|
+
|
|
30
|
+
# Get all paths and variables from common functions
|
|
31
|
+
eval $(get_feature_paths)
|
|
32
|
+
|
|
33
|
+
# Check if we're on a proper feature branch (only for git repos)
|
|
34
|
+
check_feature_branch "$CURRENT_BRANCH" "$HAS_GIT" || exit 1
|
|
35
|
+
|
|
36
|
+
# Ensure the feature directory exists
|
|
37
|
+
mkdir -p "$FEATURE_DIR"
|
|
38
|
+
|
|
39
|
+
# Copy plan template if it exists
|
|
40
|
+
TEMPLATE="$REPO_ROOT/.claude/skills/templates/plan-template.md"
|
|
41
|
+
if [[ -f "$TEMPLATE" ]]; then
|
|
42
|
+
cp "$TEMPLATE" "$IMPL_PLAN"
|
|
43
|
+
echo "Copied plan template to $IMPL_PLAN"
|
|
44
|
+
else
|
|
45
|
+
echo "Warning: Plan template not found at $TEMPLATE"
|
|
46
|
+
# Create a basic plan file if template doesn't exist
|
|
47
|
+
touch "$IMPL_PLAN"
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
# Output results
|
|
51
|
+
if $JSON_MODE; then
|
|
52
|
+
printf '{"FEATURE_SPEC":"%s","IMPL_PLAN":"%s","FEATURES_DIR":"%s","BRANCH":"%s","HAS_GIT":"%s"}\n' \
|
|
53
|
+
"$FEATURE_SPEC" "$IMPL_PLAN" "$FEATURE_DIR" "$CURRENT_BRANCH" "$HAS_GIT"
|
|
54
|
+
else
|
|
55
|
+
echo "FEATURE_SPEC: $FEATURE_SPEC"
|
|
56
|
+
echo "IMPL_PLAN: $IMPL_PLAN"
|
|
57
|
+
echo "FEATURES_DIR: $FEATURE_DIR"
|
|
58
|
+
echo "BRANCH: $CURRENT_BRANCH"
|
|
59
|
+
echo "HAS_GIT: $HAS_GIT"
|
|
60
|
+
fi
|
|
61
|
+
|