specweave 1.0.2 → 1.0.6
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.md +42 -0
- package/dist/src/cli/commands/init.d.ts.map +1 -1
- package/dist/src/cli/commands/init.js +6 -3
- package/dist/src/cli/commands/init.js.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/github-multi-repo.d.ts.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/github-multi-repo.js +6 -2
- package/dist/src/cli/helpers/issue-tracker/github-multi-repo.js.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/github.d.ts +11 -2
- package/dist/src/cli/helpers/issue-tracker/github.d.ts.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/github.js +68 -2
- package/dist/src/cli/helpers/issue-tracker/github.js.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/index.js +3 -3
- package/dist/src/cli/helpers/issue-tracker/index.js.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/types.d.ts +5 -0
- package/dist/src/cli/helpers/issue-tracker/types.d.ts.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/types.js.map +1 -1
- package/dist/src/core/repo-structure/repo-structure-manager.d.ts.map +1 -1
- package/dist/src/core/repo-structure/repo-structure-manager.js +5 -2
- package/dist/src/core/repo-structure/repo-structure-manager.js.map +1 -1
- package/package.json +1 -1
- package/plugins/specweave/hooks/docs-changed.sh.backup +79 -0
- package/plugins/specweave/hooks/human-input-required.sh.backup +75 -0
- package/plugins/specweave/hooks/post-first-increment.sh.backup +61 -0
- package/plugins/specweave/hooks/post-increment-change.sh.backup +98 -0
- package/plugins/specweave/hooks/post-increment-completion.sh.backup +231 -0
- package/plugins/specweave/hooks/post-increment-planning.sh.backup +1048 -0
- package/plugins/specweave/hooks/post-increment-status-change.sh.backup +147 -0
- package/plugins/specweave/hooks/post-spec-update.sh.backup +158 -0
- package/plugins/specweave/hooks/post-user-story-complete.sh.backup +179 -0
- package/plugins/specweave/hooks/pre-command-deduplication.sh.backup +83 -0
- package/plugins/specweave/hooks/pre-implementation.sh.backup +67 -0
- package/plugins/specweave/hooks/pre-task-completion.sh.backup +194 -0
- package/plugins/specweave/hooks/pre-tool-use.sh.backup +133 -0
- package/plugins/specweave/hooks/user-prompt-submit.sh.backup +386 -0
- package/plugins/specweave/hooks/v2/dispatchers/post-tool-use.sh +13 -0
- package/plugins/specweave/hooks/v2/guards/task-ac-sync-guard.sh +357 -0
- package/plugins/specweave-ado/hooks/post-living-docs-update.sh.backup +353 -0
- package/plugins/specweave-ado/hooks/post-task-completion.sh.backup +172 -0
- package/plugins/specweave-ado/lib/enhanced-ado-sync.js +170 -0
- package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +1262 -0
- package/plugins/specweave-github/hooks/post-task-completion.sh.backup +258 -0
- package/plugins/specweave-github/lib/enhanced-github-sync.js +220 -0
- package/plugins/specweave-jira/hooks/post-task-completion.sh.backup +172 -0
- package/plugins/specweave-jira/lib/enhanced-jira-sync.js +134 -0
- package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +1254 -0
- package/plugins/specweave-release/hooks/post-task-completion.sh.backup +110 -0
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# task-ac-sync-guard.sh - Enforce Task-AC synchronization on tasks.md edits
|
|
3
|
+
#
|
|
4
|
+
# v0.35.2+: When a task is marked complete in tasks.md, this hook:
|
|
5
|
+
# 1. Marks all **Acceptance** checkboxes in the completed task as [x]
|
|
6
|
+
# 2. Extracts the AC tags from the completed task (e.g., AC-US1-01, AC-US1-02)
|
|
7
|
+
# 3. Automatically marks those ACs as complete in spec.md
|
|
8
|
+
# 4. When ALL tasks are complete → auto-transitions status to ready_for_review
|
|
9
|
+
#
|
|
10
|
+
# This implements EDA (Event-Driven Architecture) for SpecWeave task-AC sync.
|
|
11
|
+
#
|
|
12
|
+
# PostToolUse hook - runs AFTER Edit/Write tool completes on tasks.md
|
|
13
|
+
#
|
|
14
|
+
# CROSS-PLATFORM: Works on macOS, Linux, and Windows (Git Bash/WSL)
|
|
15
|
+
# - Uses portable sed syntax with fallbacks
|
|
16
|
+
# - Handles CRLF line endings (Windows)
|
|
17
|
+
# - Supports both - and * bullet formats
|
|
18
|
+
#
|
|
19
|
+
# CRITICAL: This hook must be NON-BLOCKING to prevent Claude Code crashes
|
|
20
|
+
set +e
|
|
21
|
+
|
|
22
|
+
[[ "${SPECWEAVE_DISABLE_HOOKS:-0}" == "1" ]] && exit 0
|
|
23
|
+
|
|
24
|
+
# Find project root
|
|
25
|
+
find_project_root() {
|
|
26
|
+
local dir="$PWD"
|
|
27
|
+
while [[ "$dir" != "/" ]]; do
|
|
28
|
+
if [[ -d "$dir/.specweave" ]]; then
|
|
29
|
+
echo "$dir"
|
|
30
|
+
return 0
|
|
31
|
+
fi
|
|
32
|
+
dir=$(dirname "$dir")
|
|
33
|
+
done
|
|
34
|
+
echo "$PWD"
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
PROJECT_ROOT=$(find_project_root)
|
|
38
|
+
|
|
39
|
+
# Skip if not a SpecWeave project
|
|
40
|
+
[[ ! -d "$PROJECT_ROOT/.specweave" ]] && exit 0
|
|
41
|
+
|
|
42
|
+
LOGS_DIR="$PROJECT_ROOT/.specweave/logs"
|
|
43
|
+
DEBUG_LOG="$LOGS_DIR/task-ac-sync.log"
|
|
44
|
+
mkdir -p "$LOGS_DIR" 2>/dev/null || true
|
|
45
|
+
|
|
46
|
+
# Read stdin for tool input
|
|
47
|
+
INPUT=$(cat)
|
|
48
|
+
|
|
49
|
+
# Extract file_path from tool input
|
|
50
|
+
FILE_PATH=$(echo "$INPUT" | grep -o '"file_path"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | sed 's/.*"\([^"]*\)"/\1/')
|
|
51
|
+
|
|
52
|
+
# Only care about tasks.md files in increments folder
|
|
53
|
+
if [[ "$FILE_PATH" != */.specweave/increments/*/tasks.md ]]; then
|
|
54
|
+
exit 0
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
echo "[$(date)] 📋 Task edit detected: $FILE_PATH" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
58
|
+
|
|
59
|
+
# Extract increment directory from file path
|
|
60
|
+
INCREMENT_DIR=$(dirname "$FILE_PATH")
|
|
61
|
+
SPEC_FILE="$INCREMENT_DIR/spec.md"
|
|
62
|
+
METADATA_FILE="$INCREMENT_DIR/metadata.json"
|
|
63
|
+
|
|
64
|
+
# Check if this edit marks a task as complete
|
|
65
|
+
# Look for pattern: **Status**: [x] completed
|
|
66
|
+
NEW_CONTENT=$(echo "$INPUT" | grep -o '"new_string"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1)
|
|
67
|
+
|
|
68
|
+
if ! echo "$NEW_CONTENT" | grep -qE '\[x\].*completed'; then
|
|
69
|
+
echo "[$(date)] ⏭️ Not a task completion edit, skipping" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
70
|
+
exit 0
|
|
71
|
+
fi
|
|
72
|
+
|
|
73
|
+
echo "[$(date)] ✅ Task completion detected!" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
74
|
+
|
|
75
|
+
# ============================================================================
|
|
76
|
+
# STEP 1: Mark task's **Acceptance** checkboxes as complete
|
|
77
|
+
# ============================================================================
|
|
78
|
+
# When a task is marked complete, all its Acceptance points should be checked.
|
|
79
|
+
# Format in tasks.md:
|
|
80
|
+
# ### T-001: Task Title
|
|
81
|
+
# **Acceptance**:
|
|
82
|
+
# - [ ] Point 1
|
|
83
|
+
# - [ ] Point 2
|
|
84
|
+
# **Status**: [x] completed
|
|
85
|
+
#
|
|
86
|
+
# We need to find the task that was just completed and check its Acceptance items.
|
|
87
|
+
# Strategy: Parse tasks.md, find completed tasks, mark their unchecked Acceptance items.
|
|
88
|
+
|
|
89
|
+
ACCEPTANCE_UPDATED=0
|
|
90
|
+
|
|
91
|
+
# Create a temp file for safe in-place editing
|
|
92
|
+
TASKS_EDIT_TEMP=$(mktemp)
|
|
93
|
+
cp "$FILE_PATH" "$TASKS_EDIT_TEMP" 2>/dev/null || true
|
|
94
|
+
|
|
95
|
+
# Track state while parsing
|
|
96
|
+
IN_ACCEPTANCE_SECTION=0
|
|
97
|
+
CURRENT_TASK_COMPLETED=0
|
|
98
|
+
CURRENT_TASK_ID=""
|
|
99
|
+
|
|
100
|
+
# Process line by line to identify and update Acceptance checkboxes
|
|
101
|
+
while IFS= read -r line; do
|
|
102
|
+
# Detect task header - reset state
|
|
103
|
+
if [[ "$line" =~ ^###[[:space:]]+(T-[0-9]+): ]]; then
|
|
104
|
+
IN_ACCEPTANCE_SECTION=0
|
|
105
|
+
CURRENT_TASK_COMPLETED=0
|
|
106
|
+
CURRENT_TASK_ID="${BASH_REMATCH[1]}"
|
|
107
|
+
fi
|
|
108
|
+
|
|
109
|
+
# Detect **Acceptance**: section start
|
|
110
|
+
if [[ "$line" =~ ^\*\*Acceptance\*\*: ]]; then
|
|
111
|
+
IN_ACCEPTANCE_SECTION=1
|
|
112
|
+
fi
|
|
113
|
+
|
|
114
|
+
# Detect end of Acceptance section (next section or blank line followed by **)
|
|
115
|
+
if [[ $IN_ACCEPTANCE_SECTION -eq 1 ]] && [[ "$line" =~ ^\*\*[A-Z] ]] && [[ ! "$line" =~ ^\*\*Acceptance ]]; then
|
|
116
|
+
IN_ACCEPTANCE_SECTION=0
|
|
117
|
+
fi
|
|
118
|
+
|
|
119
|
+
# Detect completion status for current task
|
|
120
|
+
if [[ "$line" =~ ^\*\*Status\*\*:[[:space:]]*\[x\] ]]; then
|
|
121
|
+
CURRENT_TASK_COMPLETED=1
|
|
122
|
+
fi
|
|
123
|
+
done < "$FILE_PATH"
|
|
124
|
+
|
|
125
|
+
# Now do the actual replacement: for completed tasks, check all Acceptance items
|
|
126
|
+
# We use awk with two-pass logic:
|
|
127
|
+
# Pass 1: Build list of completed task IDs (tasks where Status has [x])
|
|
128
|
+
# Pass 2: For those tasks, check their Acceptance items
|
|
129
|
+
#
|
|
130
|
+
# Since awk reads sequentially and Acceptance comes BEFORE Status in the file,
|
|
131
|
+
# we need to buffer the entire task block and process it when we see the next task.
|
|
132
|
+
awk '
|
|
133
|
+
BEGIN {
|
|
134
|
+
task_start = 0
|
|
135
|
+
task_lines = ""
|
|
136
|
+
task_completed = 0
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
# Task header - process previous task block first, then start new one
|
|
140
|
+
/^### T-[0-9]+:/ {
|
|
141
|
+
# Output previous task block (with modifications if completed)
|
|
142
|
+
if (task_start > 0) {
|
|
143
|
+
n = split(task_lines, lines, "\n")
|
|
144
|
+
in_acceptance = 0
|
|
145
|
+
for (i = 1; i <= n; i++) {
|
|
146
|
+
line = lines[i]
|
|
147
|
+
# Track Acceptance section
|
|
148
|
+
if (line ~ /^\*\*Acceptance\*\*:/) in_acceptance = 1
|
|
149
|
+
if (line ~ /^\*\*[A-Z]/ && line !~ /^\*\*Acceptance/) in_acceptance = 0
|
|
150
|
+
# Check unchecked items in Acceptance section of completed tasks
|
|
151
|
+
if (in_acceptance && task_completed && line ~ /^[-*] \[ \]/) {
|
|
152
|
+
sub(/\[ \]/, "[x]", line)
|
|
153
|
+
}
|
|
154
|
+
print line
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
# Start new task block
|
|
158
|
+
task_start = NR
|
|
159
|
+
task_lines = $0
|
|
160
|
+
task_completed = 0
|
|
161
|
+
next
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
# Accumulate lines and detect completion
|
|
165
|
+
{
|
|
166
|
+
if (task_start > 0) {
|
|
167
|
+
task_lines = task_lines "\n" $0
|
|
168
|
+
if ($0 ~ /^\*\*Status\*\*:[[:space:]]*\[x\]/) {
|
|
169
|
+
task_completed = 1
|
|
170
|
+
}
|
|
171
|
+
} else {
|
|
172
|
+
# Lines before first task (header content)
|
|
173
|
+
print
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
# End of file - process last task block
|
|
178
|
+
END {
|
|
179
|
+
if (task_start > 0) {
|
|
180
|
+
n = split(task_lines, lines, "\n")
|
|
181
|
+
in_acceptance = 0
|
|
182
|
+
for (i = 1; i <= n; i++) {
|
|
183
|
+
line = lines[i]
|
|
184
|
+
if (line ~ /^\*\*Acceptance\*\*:/) in_acceptance = 1
|
|
185
|
+
if (line ~ /^\*\*[A-Z]/ && line !~ /^\*\*Acceptance/) in_acceptance = 0
|
|
186
|
+
if (in_acceptance && task_completed && line ~ /^[-*] \[ \]/) {
|
|
187
|
+
sub(/\[ \]/, "[x]", line)
|
|
188
|
+
}
|
|
189
|
+
print line
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
' "$FILE_PATH" > "$TASKS_EDIT_TEMP" 2>/dev/null
|
|
194
|
+
|
|
195
|
+
# Check if changes were made
|
|
196
|
+
if ! diff -q "$FILE_PATH" "$TASKS_EDIT_TEMP" >/dev/null 2>&1; then
|
|
197
|
+
# Changes detected - update the file
|
|
198
|
+
mv "$TASKS_EDIT_TEMP" "$FILE_PATH" 2>/dev/null
|
|
199
|
+
ACCEPTANCE_UPDATED=1
|
|
200
|
+
echo "[$(date)] ✅ Updated Acceptance checkboxes for completed tasks" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
201
|
+
else
|
|
202
|
+
rm -f "$TASKS_EDIT_TEMP" 2>/dev/null || true
|
|
203
|
+
echo "[$(date)] ⏭️ No Acceptance checkboxes to update" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
204
|
+
fi
|
|
205
|
+
|
|
206
|
+
# ============================================================================
|
|
207
|
+
# STEP 2: Extract AC tags from the completed task
|
|
208
|
+
# ============================================================================
|
|
209
|
+
# The task format is:
|
|
210
|
+
# ### T-XXX: Task Title
|
|
211
|
+
# **Satisfies ACs**: AC-US1-01, AC-US1-02
|
|
212
|
+
# **Status**: [x] completed
|
|
213
|
+
|
|
214
|
+
# Read tasks.md to find completed tasks and their ACs
|
|
215
|
+
if [[ ! -f "$FILE_PATH" ]]; then
|
|
216
|
+
echo "[$(date)] ⚠️ tasks.md not found: $FILE_PATH" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
217
|
+
exit 0
|
|
218
|
+
fi
|
|
219
|
+
|
|
220
|
+
# CROSS-PLATFORM: Convert CRLF to LF for Windows compatibility
|
|
221
|
+
# Create temp file with normalized line endings
|
|
222
|
+
TASKS_TEMP=$(mktemp)
|
|
223
|
+
tr -d '\r' < "$FILE_PATH" > "$TASKS_TEMP" 2>/dev/null || cat "$FILE_PATH" > "$TASKS_TEMP"
|
|
224
|
+
|
|
225
|
+
# Find all completed tasks and their AC tags
|
|
226
|
+
COMPLETED_ACS=()
|
|
227
|
+
CURRENT_TASK=""
|
|
228
|
+
CURRENT_ACS=""
|
|
229
|
+
|
|
230
|
+
while IFS= read -r line; do
|
|
231
|
+
# Detect task header
|
|
232
|
+
if [[ "$line" =~ ^###[[:space:]]+(T-[0-9]+): ]]; then
|
|
233
|
+
CURRENT_TASK="${BASH_REMATCH[1]}"
|
|
234
|
+
CURRENT_ACS=""
|
|
235
|
+
fi
|
|
236
|
+
|
|
237
|
+
# Detect AC tags (handle optional whitespace variations)
|
|
238
|
+
if [[ "$line" =~ ^\*\*Satisfies[[:space:]]*ACs\*\*:[[:space:]]*(.*) ]]; then
|
|
239
|
+
CURRENT_ACS="${BASH_REMATCH[1]}"
|
|
240
|
+
fi
|
|
241
|
+
|
|
242
|
+
# Detect completion status
|
|
243
|
+
if [[ "$line" =~ ^\*\*Status\*\*:[[:space:]]*\[x\] ]]; then
|
|
244
|
+
if [[ -n "$CURRENT_ACS" ]]; then
|
|
245
|
+
# Split ACs by comma and add to array
|
|
246
|
+
IFS=',' read -ra AC_ARRAY <<< "$CURRENT_ACS"
|
|
247
|
+
for ac in "${AC_ARRAY[@]}"; do
|
|
248
|
+
ac=$(echo "$ac" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') # Trim whitespace
|
|
249
|
+
# Also remove any trailing \r (Windows)
|
|
250
|
+
ac="${ac%$'\r'}"
|
|
251
|
+
if [[ -n "$ac" ]]; then
|
|
252
|
+
COMPLETED_ACS+=("$ac")
|
|
253
|
+
fi
|
|
254
|
+
done
|
|
255
|
+
fi
|
|
256
|
+
fi
|
|
257
|
+
done < "$TASKS_TEMP"
|
|
258
|
+
|
|
259
|
+
# Cleanup temp file
|
|
260
|
+
rm -f "$TASKS_TEMP" 2>/dev/null || true
|
|
261
|
+
|
|
262
|
+
echo "[$(date)] 📊 Completed ACs: ${COMPLETED_ACS[*]}" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
263
|
+
|
|
264
|
+
# ============================================================================
|
|
265
|
+
# STEP 2: Mark ACs as complete in spec.md
|
|
266
|
+
# ============================================================================
|
|
267
|
+
# AC format in spec.md:
|
|
268
|
+
# - [ ] **AC-US1-01**: Description
|
|
269
|
+
# Should become:
|
|
270
|
+
# - [x] **AC-US1-01**: Description
|
|
271
|
+
|
|
272
|
+
if [[ ! -f "$SPEC_FILE" ]]; then
|
|
273
|
+
echo "[$(date)] ⚠️ spec.md not found: $SPEC_FILE" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
274
|
+
exit 0
|
|
275
|
+
fi
|
|
276
|
+
|
|
277
|
+
AC_UPDATED=0
|
|
278
|
+
for ac in "${COMPLETED_ACS[@]}"; do
|
|
279
|
+
# Check if this AC exists and is not already marked complete
|
|
280
|
+
# CROSS-PLATFORM: Support both - and * bullet formats, use # delimiter (AC names may contain /)
|
|
281
|
+
if grep -qE "^[-*] \[ \] \*\*$ac\*\*" "$SPEC_FILE" 2>/dev/null; then
|
|
282
|
+
# Update AC to complete (macOS sed -i '' vs Linux sed -i)
|
|
283
|
+
# Use # as delimiter since AC names like "AC-US1/01" would break /
|
|
284
|
+
sed -i '' "s#^[-*] \[ \] \*\*$ac\*\*#- [x] **$ac**#" "$SPEC_FILE" 2>/dev/null || \
|
|
285
|
+
sed -i "s#^[-*] \[ \] \*\*$ac\*\*#- [x] **$ac**#" "$SPEC_FILE" 2>/dev/null
|
|
286
|
+
echo "[$(date)] ✅ Marked AC complete: $ac" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
287
|
+
((AC_UPDATED++))
|
|
288
|
+
else
|
|
289
|
+
echo "[$(date)] ⏭️ AC already complete or not found: $ac" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
290
|
+
fi
|
|
291
|
+
done
|
|
292
|
+
|
|
293
|
+
if [[ $AC_UPDATED -gt 0 ]]; then
|
|
294
|
+
echo "[$(date)] 📝 Updated $AC_UPDATED ACs in spec.md" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
295
|
+
fi
|
|
296
|
+
|
|
297
|
+
# ============================================================================
|
|
298
|
+
# STEP 3: Check if ALL tasks are complete → auto-transition to ready_for_review
|
|
299
|
+
# ============================================================================
|
|
300
|
+
|
|
301
|
+
TOTAL_TASKS=$(grep -c '^\*\*Status\*\*:' "$FILE_PATH" 2>/dev/null || echo 0)
|
|
302
|
+
COMPLETED_TASKS=$(grep -c '^\*\*Status\*\*:[[:space:]]*\[x\]' "$FILE_PATH" 2>/dev/null || echo 0)
|
|
303
|
+
|
|
304
|
+
echo "[$(date)] 📊 Task progress: $COMPLETED_TASKS / $TOTAL_TASKS" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
305
|
+
|
|
306
|
+
if [[ "$TOTAL_TASKS" -gt 0 ]] && [[ "$COMPLETED_TASKS" -eq "$TOTAL_TASKS" ]]; then
|
|
307
|
+
echo "[$(date)] 🎉 ALL TASKS COMPLETE! Checking for auto-transition..." >> "$DEBUG_LOG" 2>/dev/null || true
|
|
308
|
+
|
|
309
|
+
# Check current status (requires jq for JSON manipulation)
|
|
310
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
311
|
+
echo "[$(date)] ⚠️ jq not installed - status auto-transition skipped" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
312
|
+
echo ""
|
|
313
|
+
echo "⚠️ WARNING: jq not installed. Status auto-transition to ready_for_review skipped."
|
|
314
|
+
echo " Install jq: brew install jq (macOS) | apt install jq (Linux) | choco install jq (Windows)"
|
|
315
|
+
echo ""
|
|
316
|
+
exit 0
|
|
317
|
+
fi
|
|
318
|
+
|
|
319
|
+
if [[ -f "$METADATA_FILE" ]]; then
|
|
320
|
+
CURRENT_STATUS=$(jq -r '.status // "active"' "$METADATA_FILE" 2>/dev/null)
|
|
321
|
+
|
|
322
|
+
if [[ "$CURRENT_STATUS" == "active" ]] || [[ "$CURRENT_STATUS" == "in-progress" ]]; then
|
|
323
|
+
# Auto-transition to ready_for_review (NEVER directly to completed!)
|
|
324
|
+
echo "[$(date)] 🔄 Auto-transitioning status: $CURRENT_STATUS → ready_for_review" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
325
|
+
|
|
326
|
+
# Update metadata.json
|
|
327
|
+
TMP_FILE=$(mktemp)
|
|
328
|
+
jq '.status = "ready_for_review" | .updated = (now | strftime("%Y-%m-%dT%H:%M:%S.000Z"))' "$METADATA_FILE" > "$TMP_FILE" 2>/dev/null
|
|
329
|
+
if [[ -s "$TMP_FILE" ]]; then
|
|
330
|
+
mv "$TMP_FILE" "$METADATA_FILE"
|
|
331
|
+
echo "[$(date)] ✅ Status updated to ready_for_review" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
332
|
+
|
|
333
|
+
# Output message to Claude
|
|
334
|
+
echo ""
|
|
335
|
+
echo "════════════════════════════════════════════════════════════════════"
|
|
336
|
+
echo " 🎉 ALL TASKS COMPLETED! Status → ready_for_review"
|
|
337
|
+
echo "════════════════════════════════════════════════════════════════════"
|
|
338
|
+
echo ""
|
|
339
|
+
echo " Tasks: $COMPLETED_TASKS/$TOTAL_TASKS (100%)"
|
|
340
|
+
echo " ACs synced: $AC_UPDATED"
|
|
341
|
+
echo ""
|
|
342
|
+
echo " Next step: Run /sw:done to close the increment"
|
|
343
|
+
echo " (PM validation will verify all ACs are complete)"
|
|
344
|
+
echo ""
|
|
345
|
+
echo "════════════════════════════════════════════════════════════════════"
|
|
346
|
+
else
|
|
347
|
+
rm -f "$TMP_FILE"
|
|
348
|
+
echo "[$(date)] ⚠️ Failed to update metadata.json" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
349
|
+
fi
|
|
350
|
+
else
|
|
351
|
+
echo "[$(date)] ⏭️ Status is '$CURRENT_STATUS', not auto-transitioning" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
352
|
+
fi
|
|
353
|
+
fi
|
|
354
|
+
fi
|
|
355
|
+
|
|
356
|
+
# Always exit 0 - never crash Claude Code
|
|
357
|
+
exit 0
|