mindsystem-cc 3.19.0 → 3.21.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/README.md +5 -6
- package/agents/ms-designer.md +5 -2
- package/agents/ms-mockup-designer.md +1 -1
- package/agents/ms-plan-writer.md +8 -1
- package/agents/ms-product-researcher.md +69 -0
- package/agents/ms-research-synthesizer.md +1 -1
- package/agents/ms-researcher.md +8 -8
- package/agents/ms-roadmapper.md +9 -13
- package/bin/install.js +68 -5
- package/commands/ms/add-phase.md +30 -18
- package/commands/ms/adhoc.md +1 -1
- package/commands/ms/audit-milestone.md +12 -12
- package/commands/ms/complete-milestone.md +25 -22
- package/commands/ms/config.md +202 -0
- package/commands/ms/design-phase.md +34 -29
- package/commands/ms/discuss-phase.md +26 -22
- package/commands/ms/doctor.md +22 -202
- package/commands/ms/execute-phase.md +18 -7
- package/commands/ms/help.md +46 -39
- package/commands/ms/insert-phase.md +29 -17
- package/commands/ms/new-milestone.md +42 -19
- package/commands/ms/new-project.md +88 -103
- package/commands/ms/plan-milestone-gaps.md +4 -5
- package/commands/ms/plan-phase.md +5 -3
- package/commands/ms/progress.md +2 -4
- package/commands/ms/research-phase.md +7 -12
- package/commands/ms/research-project.md +12 -12
- package/mindsystem/references/continuation-format.md +3 -3
- package/mindsystem/references/plan-format.md +11 -1
- package/mindsystem/references/principles.md +1 -1
- package/mindsystem/references/questioning.md +50 -8
- package/mindsystem/references/routing/audit-result-routing.md +12 -11
- package/mindsystem/references/routing/between-milestones-routing.md +2 -2
- package/mindsystem/references/routing/milestone-complete-routing.md +1 -1
- package/mindsystem/references/routing/next-phase-routing.md +4 -2
- package/mindsystem/templates/context.md +7 -6
- package/mindsystem/templates/milestone-archive.md +5 -5
- package/mindsystem/templates/milestone-context.md +1 -1
- package/mindsystem/templates/milestone.md +9 -9
- package/mindsystem/templates/project.md +70 -64
- package/mindsystem/templates/research-subagent-prompt.md +3 -3
- package/mindsystem/templates/roadmap-milestone.md +14 -14
- package/mindsystem/templates/roadmap.md +9 -7
- package/mindsystem/workflows/adhoc.md +1 -1
- package/mindsystem/workflows/complete-milestone.md +66 -107
- package/mindsystem/workflows/discuss-phase.md +137 -65
- package/mindsystem/workflows/doctor-fixes.md +273 -0
- package/mindsystem/workflows/execute-phase.md +7 -3
- package/mindsystem/workflows/execute-plan.md +6 -5
- package/mindsystem/workflows/map-codebase.md +2 -2
- package/mindsystem/workflows/mockup-generation.md +1 -1
- package/mindsystem/workflows/plan-phase.md +28 -3
- package/mindsystem/workflows/transition.md +20 -25
- package/mindsystem/workflows/verify-work.md +1 -1
- package/package.json +1 -1
- package/scripts/__pycache__/ms-tools.cpython-314.pyc +0 -0
- package/scripts/__pycache__/test_ms_tools.cpython-314-pytest-9.0.2.pyc +0 -0
- package/scripts/fixtures/scan-context/.planning/ROADMAP.md +16 -0
- package/scripts/fixtures/scan-context/.planning/adhoc/20260220-fix-token-SUMMARY.md +12 -0
- package/scripts/fixtures/scan-context/.planning/config.json +3 -0
- package/scripts/fixtures/scan-context/.planning/debug/resolved/token-bug.md +11 -0
- package/scripts/fixtures/scan-context/.planning/knowledge/auth.md +11 -0
- package/scripts/fixtures/scan-context/.planning/phases/02-infra/02-1-SUMMARY.md +20 -0
- package/scripts/fixtures/scan-context/.planning/phases/04-setup/04-1-SUMMARY.md +21 -0
- package/scripts/fixtures/scan-context/.planning/phases/05-auth/05-1-SUMMARY.md +28 -0
- package/scripts/fixtures/scan-context/.planning/todos/done/setup-db.md +10 -0
- package/scripts/fixtures/scan-context/.planning/todos/pending/add-logout.md +10 -0
- package/scripts/fixtures/scan-context/expected-output.json +257 -0
- package/scripts/ms-tools.py +2139 -0
- package/scripts/test_ms_tools.py +836 -0
- package/commands/ms/list-phase-assumptions.md +0 -56
- package/mindsystem/workflows/list-phase-assumptions.md +0 -178
- package/scripts/__pycache__/compare_mockups.cpython-314.pyc +0 -0
- package/scripts/archive-milestone-files.sh +0 -68
- package/scripts/archive-milestone-phases.sh +0 -138
- package/scripts/doctor-scan.sh +0 -379
- package/scripts/gather-milestone-stats.sh +0 -179
- package/scripts/generate-adhoc-patch.sh +0 -79
- package/scripts/generate-phase-patch.sh +0 -169
- package/scripts/scan-artifact-subsystems.sh +0 -55
- package/scripts/scan-planning-context.py +0 -839
- package/scripts/update-state.sh +0 -59
- package/scripts/validate-execution-order.sh +0 -104
package/scripts/doctor-scan.sh
DELETED
|
@@ -1,379 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
#
|
|
3
|
-
# doctor-scan.sh
|
|
4
|
-
# Single-pass diagnostic scan of the .planning/ tree.
|
|
5
|
-
# Reports on 6 health check categories with structured output.
|
|
6
|
-
#
|
|
7
|
-
# Usage: ./scripts/doctor-scan.sh
|
|
8
|
-
#
|
|
9
|
-
# Exit codes:
|
|
10
|
-
# 0 — all checks pass
|
|
11
|
-
# 1 — one or more checks failed
|
|
12
|
-
# 2 — .planning/ or config.json missing (cannot scan)
|
|
13
|
-
|
|
14
|
-
set -e
|
|
15
|
-
|
|
16
|
-
# --- Find .planning from git root ---
|
|
17
|
-
GIT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
|
|
18
|
-
if [ -z "$GIT_ROOT" ]; then
|
|
19
|
-
echo "Error: Not in a git repository"
|
|
20
|
-
exit 2
|
|
21
|
-
fi
|
|
22
|
-
|
|
23
|
-
PLANNING="$GIT_ROOT/.planning"
|
|
24
|
-
if [ ! -d "$PLANNING" ]; then
|
|
25
|
-
echo "Error: No .planning/ directory found"
|
|
26
|
-
exit 2
|
|
27
|
-
fi
|
|
28
|
-
|
|
29
|
-
CONFIG="$PLANNING/config.json"
|
|
30
|
-
if [ ! -f "$CONFIG" ]; then
|
|
31
|
-
echo "Error: No config.json found at $CONFIG"
|
|
32
|
-
exit 2
|
|
33
|
-
fi
|
|
34
|
-
|
|
35
|
-
MILESTONES_FILE="$PLANNING/MILESTONES.md"
|
|
36
|
-
PHASES_DIR="$PLANNING/phases"
|
|
37
|
-
MILESTONES_DIR="$PLANNING/milestones"
|
|
38
|
-
KNOWLEDGE_DIR="$PLANNING/knowledge"
|
|
39
|
-
|
|
40
|
-
PASS_COUNT=0
|
|
41
|
-
FAIL_COUNT=0
|
|
42
|
-
SKIP_COUNT=0
|
|
43
|
-
FAILED_CHECKS=""
|
|
44
|
-
|
|
45
|
-
# --- Helper: record check result ---
|
|
46
|
-
record_result() {
|
|
47
|
-
local status="$1"
|
|
48
|
-
local name="$2"
|
|
49
|
-
case "$status" in
|
|
50
|
-
PASS) PASS_COUNT=$((PASS_COUNT + 1)) ;;
|
|
51
|
-
FAIL) FAIL_COUNT=$((FAIL_COUNT + 1)); FAILED_CHECKS="$FAILED_CHECKS $name" ;;
|
|
52
|
-
SKIP) SKIP_COUNT=$((SKIP_COUNT + 1)) ;;
|
|
53
|
-
esac
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
# ============================================================
|
|
57
|
-
# CHECK 1: Subsystem Vocabulary
|
|
58
|
-
# ============================================================
|
|
59
|
-
echo "=== Subsystem Vocabulary ==="
|
|
60
|
-
|
|
61
|
-
SUBSYSTEM_COUNT=$(jq -r '.subsystems // [] | length' "$CONFIG" 2>/dev/null || echo "0")
|
|
62
|
-
|
|
63
|
-
if [ "$SUBSYSTEM_COUNT" -eq 0 ]; then
|
|
64
|
-
echo "Status: FAIL"
|
|
65
|
-
echo "No subsystems array in config.json (or empty)"
|
|
66
|
-
record_result "FAIL" "Subsystem Vocabulary"
|
|
67
|
-
else
|
|
68
|
-
echo "Subsystems: $SUBSYSTEM_COUNT configured"
|
|
69
|
-
jq -r '.subsystems[]' "$CONFIG" 2>/dev/null | sed 's/^/ - /'
|
|
70
|
-
|
|
71
|
-
# Run artifact scan to check for mismatches
|
|
72
|
-
SCAN_SCRIPT="$(dirname "$0")/scan-artifact-subsystems.sh"
|
|
73
|
-
if [ -x "$SCAN_SCRIPT" ]; then
|
|
74
|
-
CANONICAL=$(jq -r '.subsystems[]' "$CONFIG" 2>/dev/null)
|
|
75
|
-
ARTIFACT_VALUES=$("$SCAN_SCRIPT" --values-only 2>/dev/null | grep -v '^===' | sort -u)
|
|
76
|
-
MISMATCHES=""
|
|
77
|
-
while IFS= read -r val; do
|
|
78
|
-
[ -z "$val" ] && continue
|
|
79
|
-
if ! echo "$CANONICAL" | grep -qx "$val"; then
|
|
80
|
-
MISMATCHES="$MISMATCHES $val"
|
|
81
|
-
fi
|
|
82
|
-
done <<< "$ARTIFACT_VALUES"
|
|
83
|
-
|
|
84
|
-
if [ -n "$MISMATCHES" ]; then
|
|
85
|
-
echo "Status: FAIL"
|
|
86
|
-
echo "Artifact values not in canonical list:$MISMATCHES"
|
|
87
|
-
record_result "FAIL" "Subsystem Vocabulary"
|
|
88
|
-
else
|
|
89
|
-
ARTIFACT_COUNT=$("$SCAN_SCRIPT" --values-only 2>/dev/null | grep -v '^===' | wc -l | tr -d ' ')
|
|
90
|
-
echo "Artifacts scanned: $ARTIFACT_COUNT (all OK)"
|
|
91
|
-
echo "Status: PASS"
|
|
92
|
-
record_result "PASS" "Subsystem Vocabulary"
|
|
93
|
-
fi
|
|
94
|
-
else
|
|
95
|
-
echo "Status: PASS"
|
|
96
|
-
echo "(scan-artifact-subsystems.sh not found — skipped artifact validation)"
|
|
97
|
-
record_result "PASS" "Subsystem Vocabulary"
|
|
98
|
-
fi
|
|
99
|
-
fi
|
|
100
|
-
echo ""
|
|
101
|
-
|
|
102
|
-
# ============================================================
|
|
103
|
-
# CHECK 2: Milestone Directory Structure
|
|
104
|
-
# ============================================================
|
|
105
|
-
echo "=== Milestone Directory Structure ==="
|
|
106
|
-
|
|
107
|
-
if [ ! -d "$MILESTONES_DIR" ]; then
|
|
108
|
-
# No milestones directory at all — check if MILESTONES.md has entries
|
|
109
|
-
if [ -f "$MILESTONES_FILE" ] && grep -q "^## " "$MILESTONES_FILE" 2>/dev/null; then
|
|
110
|
-
echo "Status: FAIL"
|
|
111
|
-
echo "MILESTONES.md has entries but no milestones/ directory"
|
|
112
|
-
record_result "FAIL" "Milestone Directory Structure"
|
|
113
|
-
else
|
|
114
|
-
echo "Status: SKIP"
|
|
115
|
-
echo "No completed milestones"
|
|
116
|
-
record_result "SKIP" "Milestone Directory Structure"
|
|
117
|
-
fi
|
|
118
|
-
else
|
|
119
|
-
# Look for flat files matching v*-*.md directly in milestones/
|
|
120
|
-
FLAT_FILES=""
|
|
121
|
-
FLAT_COUNT=0
|
|
122
|
-
for f in "$MILESTONES_DIR"/v*-*.md; do
|
|
123
|
-
[ -f "$f" ] || continue
|
|
124
|
-
FLAT_FILES="$FLAT_FILES $(basename "$f")"$'\n'
|
|
125
|
-
FLAT_COUNT=$((FLAT_COUNT + 1))
|
|
126
|
-
done
|
|
127
|
-
|
|
128
|
-
if [ "$FLAT_COUNT" -gt 0 ]; then
|
|
129
|
-
echo "Status: FAIL"
|
|
130
|
-
echo "Found $FLAT_COUNT flat file(s) in milestones/ (old format):"
|
|
131
|
-
echo "$FLAT_FILES"
|
|
132
|
-
# Check if corresponding versioned directories exist
|
|
133
|
-
for f in "$MILESTONES_DIR"/v*-*.md; do
|
|
134
|
-
[ -f "$f" ] || continue
|
|
135
|
-
fname=$(basename "$f")
|
|
136
|
-
# Extract version prefix: v0.1-ROADMAP.md -> v0.1
|
|
137
|
-
version=$(echo "$fname" | sed 's/^\(v[0-9.]*\)-.*/\1/')
|
|
138
|
-
if [ -d "$MILESTONES_DIR/$version" ]; then
|
|
139
|
-
echo " $fname → directory $version/ exists (can restructure)"
|
|
140
|
-
else
|
|
141
|
-
echo " $fname → directory $version/ missing (need to create)"
|
|
142
|
-
fi
|
|
143
|
-
done
|
|
144
|
-
record_result "FAIL" "Milestone Directory Structure"
|
|
145
|
-
else
|
|
146
|
-
# Count versioned directories
|
|
147
|
-
DIR_COUNT=0
|
|
148
|
-
for d in "$MILESTONES_DIR"/v*/; do
|
|
149
|
-
[ -d "$d" ] || continue
|
|
150
|
-
DIR_COUNT=$((DIR_COUNT + 1))
|
|
151
|
-
done
|
|
152
|
-
|
|
153
|
-
if [ "$DIR_COUNT" -eq 0 ]; then
|
|
154
|
-
echo "Status: SKIP"
|
|
155
|
-
echo "No completed milestones"
|
|
156
|
-
record_result "SKIP" "Milestone Directory Structure"
|
|
157
|
-
else
|
|
158
|
-
echo "Status: PASS"
|
|
159
|
-
echo "$DIR_COUNT versioned milestone directories"
|
|
160
|
-
record_result "PASS" "Milestone Directory Structure"
|
|
161
|
-
fi
|
|
162
|
-
fi
|
|
163
|
-
fi
|
|
164
|
-
echo ""
|
|
165
|
-
|
|
166
|
-
# ============================================================
|
|
167
|
-
# CHECK 3: Phase Archival
|
|
168
|
-
# ============================================================
|
|
169
|
-
echo "=== Phase Archival ==="
|
|
170
|
-
|
|
171
|
-
if [ ! -f "$MILESTONES_FILE" ] || ! grep -q "Phases completed" "$MILESTONES_FILE" 2>/dev/null; then
|
|
172
|
-
echo "Status: SKIP"
|
|
173
|
-
echo "No completed milestones with phase ranges in MILESTONES.md"
|
|
174
|
-
record_result "SKIP" "Phase Archival"
|
|
175
|
-
else
|
|
176
|
-
ORPHAN_COUNT=0
|
|
177
|
-
ORPHAN_LIST=""
|
|
178
|
-
|
|
179
|
-
# Parse each milestone's phase range from MILESTONES.md
|
|
180
|
-
while IFS= read -r line; do
|
|
181
|
-
# Extract range like "1-6" or "7-8"
|
|
182
|
-
range=$(echo "$line" | grep -o '[0-9]\+-[0-9]\+')
|
|
183
|
-
[ -z "$range" ] && continue
|
|
184
|
-
range_start=$(echo "$range" | cut -d'-' -f1)
|
|
185
|
-
range_end=$(echo "$range" | cut -d'-' -f2)
|
|
186
|
-
|
|
187
|
-
# Check if any phase directories in this range still exist in phases/
|
|
188
|
-
for i in $(seq "$range_start" "$range_end"); do
|
|
189
|
-
phase_prefix=$(printf "%02d" "$i")
|
|
190
|
-
for dir in "$PHASES_DIR"/${phase_prefix}-*/; do
|
|
191
|
-
[ -d "$dir" ] || continue
|
|
192
|
-
dirname=$(basename "$dir")
|
|
193
|
-
ORPHAN_COUNT=$((ORPHAN_COUNT + 1))
|
|
194
|
-
ORPHAN_LIST="$ORPHAN_LIST $dirname (should be archived)"$'\n'
|
|
195
|
-
done
|
|
196
|
-
done
|
|
197
|
-
done < <(grep "Phases completed" "$MILESTONES_FILE")
|
|
198
|
-
|
|
199
|
-
if [ "$ORPHAN_COUNT" -gt 0 ]; then
|
|
200
|
-
echo "Status: FAIL"
|
|
201
|
-
echo "Found $ORPHAN_COUNT orphaned phase directories from completed milestones:"
|
|
202
|
-
echo "$ORPHAN_LIST"
|
|
203
|
-
record_result "FAIL" "Phase Archival"
|
|
204
|
-
else
|
|
205
|
-
echo "Status: PASS"
|
|
206
|
-
echo "All completed milestone phases are archived"
|
|
207
|
-
record_result "PASS" "Phase Archival"
|
|
208
|
-
fi
|
|
209
|
-
fi
|
|
210
|
-
echo ""
|
|
211
|
-
|
|
212
|
-
# ============================================================
|
|
213
|
-
# CHECK 4: Knowledge Files
|
|
214
|
-
# ============================================================
|
|
215
|
-
echo "=== Knowledge Files ==="
|
|
216
|
-
|
|
217
|
-
if [ "$SUBSYSTEM_COUNT" -eq 0 ]; then
|
|
218
|
-
echo "Status: SKIP"
|
|
219
|
-
echo "No subsystems configured — knowledge check requires subsystem vocabulary"
|
|
220
|
-
record_result "SKIP" "Knowledge Files"
|
|
221
|
-
elif [ ! -d "$KNOWLEDGE_DIR" ]; then
|
|
222
|
-
echo "Status: FAIL"
|
|
223
|
-
echo "Knowledge directory missing: .planning/knowledge/"
|
|
224
|
-
echo "Expected files for $SUBSYSTEM_COUNT subsystems"
|
|
225
|
-
record_result "FAIL" "Knowledge Files"
|
|
226
|
-
else
|
|
227
|
-
MISSING_KNOWLEDGE=""
|
|
228
|
-
MISSING_COUNT=0
|
|
229
|
-
PRESENT_COUNT=0
|
|
230
|
-
while IFS= read -r subsystem; do
|
|
231
|
-
[ -z "$subsystem" ] && continue
|
|
232
|
-
if [ -f "$KNOWLEDGE_DIR/$subsystem.md" ]; then
|
|
233
|
-
PRESENT_COUNT=$((PRESENT_COUNT + 1))
|
|
234
|
-
else
|
|
235
|
-
MISSING_COUNT=$((MISSING_COUNT + 1))
|
|
236
|
-
MISSING_KNOWLEDGE="$MISSING_KNOWLEDGE $subsystem.md"$'\n'
|
|
237
|
-
fi
|
|
238
|
-
done < <(jq -r '.subsystems[]' "$CONFIG" 2>/dev/null)
|
|
239
|
-
|
|
240
|
-
# Check for orphaned knowledge files (not in subsystem list)
|
|
241
|
-
ORPHAN_KNOWLEDGE=""
|
|
242
|
-
ORPHAN_K_COUNT=0
|
|
243
|
-
for f in "$KNOWLEDGE_DIR"/*.md; do
|
|
244
|
-
[ -f "$f" ] || continue
|
|
245
|
-
fname=$(basename "$f" .md)
|
|
246
|
-
if ! jq -r '.subsystems[]' "$CONFIG" 2>/dev/null | grep -qx "$fname"; then
|
|
247
|
-
ORPHAN_K_COUNT=$((ORPHAN_K_COUNT + 1))
|
|
248
|
-
ORPHAN_KNOWLEDGE="$ORPHAN_KNOWLEDGE $fname.md (not in subsystems list)"$'\n'
|
|
249
|
-
fi
|
|
250
|
-
done
|
|
251
|
-
|
|
252
|
-
if [ "$MISSING_COUNT" -gt 0 ] || [ "$ORPHAN_K_COUNT" -gt 0 ]; then
|
|
253
|
-
echo "Status: FAIL"
|
|
254
|
-
echo "Coverage: $PRESENT_COUNT/$SUBSYSTEM_COUNT subsystems have knowledge files"
|
|
255
|
-
if [ "$MISSING_COUNT" -gt 0 ]; then
|
|
256
|
-
echo "Missing:"
|
|
257
|
-
echo "$MISSING_KNOWLEDGE"
|
|
258
|
-
fi
|
|
259
|
-
if [ "$ORPHAN_K_COUNT" -gt 0 ]; then
|
|
260
|
-
echo "Orphaned:"
|
|
261
|
-
echo "$ORPHAN_KNOWLEDGE"
|
|
262
|
-
fi
|
|
263
|
-
record_result "FAIL" "Knowledge Files"
|
|
264
|
-
else
|
|
265
|
-
echo "Status: PASS"
|
|
266
|
-
echo "All $SUBSYSTEM_COUNT subsystems have knowledge files"
|
|
267
|
-
record_result "PASS" "Knowledge Files"
|
|
268
|
-
fi
|
|
269
|
-
fi
|
|
270
|
-
echo ""
|
|
271
|
-
|
|
272
|
-
# ============================================================
|
|
273
|
-
# CHECK 5: Phase Summaries
|
|
274
|
-
# ============================================================
|
|
275
|
-
echo "=== Phase Summaries ==="
|
|
276
|
-
|
|
277
|
-
if [ ! -d "$MILESTONES_DIR" ]; then
|
|
278
|
-
echo "Status: SKIP"
|
|
279
|
-
echo "No milestones directory"
|
|
280
|
-
record_result "SKIP" "Phase Summaries"
|
|
281
|
-
else
|
|
282
|
-
MISSING_SUMMARIES=""
|
|
283
|
-
MISSING_S_COUNT=0
|
|
284
|
-
CHECKED=0
|
|
285
|
-
|
|
286
|
-
for d in "$MILESTONES_DIR"/v*/; do
|
|
287
|
-
[ -d "$d" ] || continue
|
|
288
|
-
CHECKED=$((CHECKED + 1))
|
|
289
|
-
version=$(basename "$d")
|
|
290
|
-
if [ ! -f "$d/PHASE-SUMMARIES.md" ]; then
|
|
291
|
-
MISSING_S_COUNT=$((MISSING_S_COUNT + 1))
|
|
292
|
-
MISSING_SUMMARIES="$MISSING_SUMMARIES $version/PHASE-SUMMARIES.md"$'\n'
|
|
293
|
-
fi
|
|
294
|
-
done
|
|
295
|
-
|
|
296
|
-
if [ "$CHECKED" -eq 0 ]; then
|
|
297
|
-
echo "Status: SKIP"
|
|
298
|
-
echo "No versioned milestone directories"
|
|
299
|
-
record_result "SKIP" "Phase Summaries"
|
|
300
|
-
elif [ "$MISSING_S_COUNT" -gt 0 ]; then
|
|
301
|
-
echo "Status: FAIL"
|
|
302
|
-
echo "Missing PHASE-SUMMARIES.md in $MISSING_S_COUNT milestone(s):"
|
|
303
|
-
echo "$MISSING_SUMMARIES"
|
|
304
|
-
record_result "FAIL" "Phase Summaries"
|
|
305
|
-
else
|
|
306
|
-
echo "Status: PASS"
|
|
307
|
-
echo "All $CHECKED milestones have PHASE-SUMMARIES.md"
|
|
308
|
-
record_result "PASS" "Phase Summaries"
|
|
309
|
-
fi
|
|
310
|
-
fi
|
|
311
|
-
echo ""
|
|
312
|
-
|
|
313
|
-
# ============================================================
|
|
314
|
-
# CHECK 6: PLAN Cleanup
|
|
315
|
-
# ============================================================
|
|
316
|
-
echo "=== PLAN Cleanup ==="
|
|
317
|
-
|
|
318
|
-
if [ ! -f "$MILESTONES_FILE" ] || ! grep -q "Phases completed" "$MILESTONES_FILE" 2>/dev/null; then
|
|
319
|
-
echo "Status: SKIP"
|
|
320
|
-
echo "No completed milestones — active phase PLANs are expected"
|
|
321
|
-
record_result "SKIP" "PLAN Cleanup"
|
|
322
|
-
else
|
|
323
|
-
LEFTOVER_PLANS=""
|
|
324
|
-
LEFTOVER_COUNT=0
|
|
325
|
-
|
|
326
|
-
# Check phases/ for PLANs belonging to completed milestones
|
|
327
|
-
while IFS= read -r line; do
|
|
328
|
-
range=$(echo "$line" | grep -o '[0-9]\+-[0-9]\+')
|
|
329
|
-
[ -z "$range" ] && continue
|
|
330
|
-
range_start=$(echo "$range" | cut -d'-' -f1)
|
|
331
|
-
range_end=$(echo "$range" | cut -d'-' -f2)
|
|
332
|
-
|
|
333
|
-
for i in $(seq "$range_start" "$range_end"); do
|
|
334
|
-
phase_prefix=$(printf "%02d" "$i")
|
|
335
|
-
for plan in "$PHASES_DIR"/${phase_prefix}-*/*-PLAN.md; do
|
|
336
|
-
[ -f "$plan" ] || continue
|
|
337
|
-
LEFTOVER_COUNT=$((LEFTOVER_COUNT + 1))
|
|
338
|
-
LEFTOVER_PLANS="$LEFTOVER_PLANS $(echo "$plan" | sed "s|$GIT_ROOT/.planning/||")"$'\n'
|
|
339
|
-
done
|
|
340
|
-
done
|
|
341
|
-
done < <(grep "Phases completed" "$MILESTONES_FILE")
|
|
342
|
-
|
|
343
|
-
# Check archived milestone phase directories for leftover PLANs
|
|
344
|
-
for d in "$MILESTONES_DIR"/v*/phases/*/; do
|
|
345
|
-
[ -d "$d" ] || continue
|
|
346
|
-
for plan in "$d"*-PLAN.md; do
|
|
347
|
-
[ -f "$plan" ] || continue
|
|
348
|
-
LEFTOVER_COUNT=$((LEFTOVER_COUNT + 1))
|
|
349
|
-
LEFTOVER_PLANS="$LEFTOVER_PLANS $(echo "$plan" | sed "s|$GIT_ROOT/.planning/||")"$'\n'
|
|
350
|
-
done
|
|
351
|
-
done
|
|
352
|
-
|
|
353
|
-
if [ "$LEFTOVER_COUNT" -gt 0 ]; then
|
|
354
|
-
echo "Status: FAIL"
|
|
355
|
-
echo "Found $LEFTOVER_COUNT leftover PLAN file(s) in completed phases:"
|
|
356
|
-
echo "$LEFTOVER_PLANS"
|
|
357
|
-
record_result "FAIL" "PLAN Cleanup"
|
|
358
|
-
else
|
|
359
|
-
echo "Status: PASS"
|
|
360
|
-
echo "No leftover PLAN files in completed phases"
|
|
361
|
-
record_result "PASS" "PLAN Cleanup"
|
|
362
|
-
fi
|
|
363
|
-
fi
|
|
364
|
-
echo ""
|
|
365
|
-
|
|
366
|
-
# ============================================================
|
|
367
|
-
# SUMMARY
|
|
368
|
-
# ============================================================
|
|
369
|
-
TOTAL=$((PASS_COUNT + FAIL_COUNT + SKIP_COUNT))
|
|
370
|
-
echo "=== Summary ==="
|
|
371
|
-
echo "Checks: $TOTAL total, $PASS_COUNT passed, $FAIL_COUNT failed, $SKIP_COUNT skipped"
|
|
372
|
-
|
|
373
|
-
if [ "$FAIL_COUNT" -gt 0 ]; then
|
|
374
|
-
echo "Issues:$FAILED_CHECKS"
|
|
375
|
-
exit 1
|
|
376
|
-
else
|
|
377
|
-
echo "All checks passed"
|
|
378
|
-
exit 0
|
|
379
|
-
fi
|
|
@@ -1,179 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
#
|
|
3
|
-
# gather-milestone-stats.sh
|
|
4
|
-
# Gathers milestone readiness status and statistics from the filesystem
|
|
5
|
-
# and git history. Outputs structured text for the LLM to present.
|
|
6
|
-
#
|
|
7
|
-
# Usage: ./scripts/gather-milestone-stats.sh <start_phase> <end_phase>
|
|
8
|
-
# Example: ./scripts/gather-milestone-stats.sh 1 6
|
|
9
|
-
|
|
10
|
-
set -e
|
|
11
|
-
|
|
12
|
-
# --- Validation ---
|
|
13
|
-
if [ -z "$1" ] || [ -z "$2" ]; then
|
|
14
|
-
echo "Error: Two arguments required"
|
|
15
|
-
echo "Usage: $0 <start_phase> <end_phase>"
|
|
16
|
-
exit 1
|
|
17
|
-
fi
|
|
18
|
-
|
|
19
|
-
START="$1"
|
|
20
|
-
END="$2"
|
|
21
|
-
|
|
22
|
-
if ! [[ "$START" =~ ^[0-9]+$ ]] || ! [[ "$END" =~ ^[0-9]+$ ]]; then
|
|
23
|
-
echo "Error: Both arguments must be numeric"
|
|
24
|
-
echo "Usage: $0 <start_phase> <end_phase>"
|
|
25
|
-
exit 1
|
|
26
|
-
fi
|
|
27
|
-
|
|
28
|
-
if [ "$START" -gt "$END" ]; then
|
|
29
|
-
echo "Error: Start phase ($START) cannot exceed end phase ($END)"
|
|
30
|
-
exit 1
|
|
31
|
-
fi
|
|
32
|
-
|
|
33
|
-
# --- Find .planning from git root ---
|
|
34
|
-
GIT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
|
|
35
|
-
if [ -z "$GIT_ROOT" ]; then
|
|
36
|
-
echo "Error: Not in a git repository"
|
|
37
|
-
exit 1
|
|
38
|
-
fi
|
|
39
|
-
|
|
40
|
-
PHASES_DIR="$GIT_ROOT/.planning/phases"
|
|
41
|
-
if [ ! -d "$PHASES_DIR" ]; then
|
|
42
|
-
echo "Error: Phases directory not found at $PHASES_DIR"
|
|
43
|
-
exit 1
|
|
44
|
-
fi
|
|
45
|
-
|
|
46
|
-
# --- Helper: check if phase number is in range (supports decimals like 02.1) ---
|
|
47
|
-
in_range() {
|
|
48
|
-
local phase_num="$1"
|
|
49
|
-
echo "$phase_num" | awk -v s="$START" -v e="$END" '{
|
|
50
|
-
val = $1 + 0
|
|
51
|
-
if (val >= s && val <= e + 0.999) exit 0
|
|
52
|
-
else exit 1
|
|
53
|
-
}'
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
# ============================================================
|
|
57
|
-
# READINESS
|
|
58
|
-
# ============================================================
|
|
59
|
-
echo "=== Readiness ==="
|
|
60
|
-
echo ""
|
|
61
|
-
|
|
62
|
-
PHASE_COUNT=0
|
|
63
|
-
PLAN_COUNT=0
|
|
64
|
-
COMPLETE=0
|
|
65
|
-
INCOMPLETE_LIST=""
|
|
66
|
-
PHASE_DETAILS=""
|
|
67
|
-
|
|
68
|
-
for dir in "$PHASES_DIR"/*/; do
|
|
69
|
-
[ -d "$dir" ] || continue
|
|
70
|
-
dirname=$(basename "$dir")
|
|
71
|
-
phase_num="${dirname%%-*}"
|
|
72
|
-
phase_name="${dirname#*-}"
|
|
73
|
-
|
|
74
|
-
if in_range "$phase_num"; then
|
|
75
|
-
PHASE_COUNT=$((PHASE_COUNT + 1))
|
|
76
|
-
phase_plans=0
|
|
77
|
-
phase_complete=0
|
|
78
|
-
|
|
79
|
-
for plan in "$dir"/*-PLAN.md; do
|
|
80
|
-
[ -f "$plan" ] || continue
|
|
81
|
-
PLAN_COUNT=$((PLAN_COUNT + 1))
|
|
82
|
-
phase_plans=$((phase_plans + 1))
|
|
83
|
-
plan_base=$(basename "$plan" -PLAN.md)
|
|
84
|
-
summary="$dir/${plan_base}-SUMMARY.md"
|
|
85
|
-
if [ -f "$summary" ]; then
|
|
86
|
-
COMPLETE=$((COMPLETE + 1))
|
|
87
|
-
phase_complete=$((phase_complete + 1))
|
|
88
|
-
else
|
|
89
|
-
INCOMPLETE_LIST+=" $(basename "$dir")/$(basename "$plan")"$'\n'
|
|
90
|
-
fi
|
|
91
|
-
done
|
|
92
|
-
|
|
93
|
-
PHASE_DETAILS+="- Phase $phase_num: $phase_name ($phase_complete/$phase_plans plans)"$'\n'
|
|
94
|
-
fi
|
|
95
|
-
done
|
|
96
|
-
|
|
97
|
-
echo "Phases: $PHASE_COUNT (range $START-$END)"
|
|
98
|
-
echo "Plans: $PLAN_COUNT total, $COMPLETE complete"
|
|
99
|
-
echo ""
|
|
100
|
-
echo "$PHASE_DETAILS"
|
|
101
|
-
|
|
102
|
-
if [ "$COMPLETE" -eq "$PLAN_COUNT" ] && [ "$PLAN_COUNT" -gt 0 ]; then
|
|
103
|
-
echo "Status: READY"
|
|
104
|
-
else
|
|
105
|
-
INCOMPLETE=$((PLAN_COUNT - COMPLETE))
|
|
106
|
-
echo "Incomplete ($INCOMPLETE):"
|
|
107
|
-
echo "$INCOMPLETE_LIST"
|
|
108
|
-
echo "Status: NOT READY"
|
|
109
|
-
fi
|
|
110
|
-
|
|
111
|
-
# ============================================================
|
|
112
|
-
# GIT STATS
|
|
113
|
-
# ============================================================
|
|
114
|
-
echo ""
|
|
115
|
-
echo "=== Git Stats ==="
|
|
116
|
-
echo ""
|
|
117
|
-
|
|
118
|
-
# Collect commits matching Mindsystem phase convention: feat(XX-YY), fix(XX-YY), etc.
|
|
119
|
-
ALL_COMMITS=""
|
|
120
|
-
for i in $(seq "$START" "$END"); do
|
|
121
|
-
phase=$(printf "%02d" "$i")
|
|
122
|
-
commits=$(git log --all --format="%H %ai %s" --grep="($phase-" 2>/dev/null || true)
|
|
123
|
-
if [ -n "$commits" ]; then
|
|
124
|
-
ALL_COMMITS+="$commits"$'\n'
|
|
125
|
-
fi
|
|
126
|
-
done
|
|
127
|
-
|
|
128
|
-
# Also capture decimal phase commits (e.g., 02.1 inserted phases)
|
|
129
|
-
for dir in "$PHASES_DIR"/*/; do
|
|
130
|
-
[ -d "$dir" ] || continue
|
|
131
|
-
dirname=$(basename "$dir")
|
|
132
|
-
phase_num="${dirname%%-*}"
|
|
133
|
-
case "$phase_num" in
|
|
134
|
-
*.*) # Decimal phase — not captured by seq
|
|
135
|
-
if in_range "$phase_num"; then
|
|
136
|
-
commits=$(git log --all --format="%H %ai %s" --grep="($phase_num-" 2>/dev/null || true)
|
|
137
|
-
if [ -n "$commits" ]; then
|
|
138
|
-
ALL_COMMITS+="$commits"$'\n'
|
|
139
|
-
fi
|
|
140
|
-
fi
|
|
141
|
-
;;
|
|
142
|
-
esac
|
|
143
|
-
done
|
|
144
|
-
|
|
145
|
-
# Remove empty lines, deduplicate, sort by date
|
|
146
|
-
ALL_COMMITS=$(echo "$ALL_COMMITS" | grep -v '^$' | sort -u -k2,3)
|
|
147
|
-
|
|
148
|
-
if [ -n "$ALL_COMMITS" ]; then
|
|
149
|
-
COMMIT_COUNT=$(echo "$ALL_COMMITS" | wc -l | tr -d ' ')
|
|
150
|
-
FIRST_LINE=$(echo "$ALL_COMMITS" | head -1)
|
|
151
|
-
LAST_LINE=$(echo "$ALL_COMMITS" | tail -1)
|
|
152
|
-
FIRST_HASH=$(echo "$FIRST_LINE" | awk '{print $1}')
|
|
153
|
-
LAST_HASH=$(echo "$LAST_LINE" | awk '{print $1}')
|
|
154
|
-
FIRST_DATE=$(echo "$FIRST_LINE" | awk '{print $2}')
|
|
155
|
-
LAST_DATE=$(echo "$LAST_LINE" | awk '{print $2}')
|
|
156
|
-
FIRST_MSG=$(echo "$FIRST_LINE" | cut -d' ' -f4-)
|
|
157
|
-
LAST_MSG=$(echo "$LAST_LINE" | cut -d' ' -f4-)
|
|
158
|
-
|
|
159
|
-
# Calculate days
|
|
160
|
-
DAYS=$(python3 -c "from datetime import date; print((date.fromisoformat('$LAST_DATE') - date.fromisoformat('$FIRST_DATE')).days)" 2>/dev/null || echo "?")
|
|
161
|
-
|
|
162
|
-
echo "Commits: $COMMIT_COUNT"
|
|
163
|
-
echo "Git range: ${FIRST_HASH:0:7}..${LAST_HASH:0:7}"
|
|
164
|
-
echo "First: $FIRST_DATE — $FIRST_MSG"
|
|
165
|
-
echo "Last: $LAST_DATE — $LAST_MSG"
|
|
166
|
-
echo "Timeline: $DAYS days ($FIRST_DATE → $LAST_DATE)"
|
|
167
|
-
|
|
168
|
-
# Diff stats for the range
|
|
169
|
-
DIFFSTAT=$(git diff --shortstat "${FIRST_HASH}^..${LAST_HASH}" 2>/dev/null || true)
|
|
170
|
-
if [ -n "$DIFFSTAT" ]; then
|
|
171
|
-
echo "Changes:$DIFFSTAT"
|
|
172
|
-
fi
|
|
173
|
-
else
|
|
174
|
-
echo "No commits found matching phase patterns (expected 'feat(XX-YY): ...')"
|
|
175
|
-
echo "Determine git range manually from git log"
|
|
176
|
-
fi
|
|
177
|
-
|
|
178
|
-
echo ""
|
|
179
|
-
exit 0
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
#
|
|
3
|
-
# generate-adhoc-patch.sh
|
|
4
|
-
# Generates a patch file from an adhoc commit, excluding documentation and generated files.
|
|
5
|
-
#
|
|
6
|
-
# Usage: ./scripts/generate-adhoc-patch.sh <commit-hash> <output-path>
|
|
7
|
-
# Example: ./scripts/generate-adhoc-patch.sh abc123f .planning/adhoc/2026-01-26-fix-bug.patch
|
|
8
|
-
|
|
9
|
-
set -e
|
|
10
|
-
|
|
11
|
-
# --- Configuration ---
|
|
12
|
-
# Same exclusions as generate-phase-patch.sh
|
|
13
|
-
EXCLUSIONS=(
|
|
14
|
-
# Documentation
|
|
15
|
-
'.planning'
|
|
16
|
-
|
|
17
|
-
# Flutter/Dart generated
|
|
18
|
-
'*.g.dart'
|
|
19
|
-
'*.freezed.dart'
|
|
20
|
-
'*.gr.dart'
|
|
21
|
-
'generated'
|
|
22
|
-
'.dart_tool'
|
|
23
|
-
|
|
24
|
-
# Next.js/TypeScript generated
|
|
25
|
-
'node_modules'
|
|
26
|
-
'.next'
|
|
27
|
-
'dist'
|
|
28
|
-
'build'
|
|
29
|
-
'*.d.ts'
|
|
30
|
-
'.turbo'
|
|
31
|
-
|
|
32
|
-
# Common build artifacts
|
|
33
|
-
'*.lock'
|
|
34
|
-
)
|
|
35
|
-
|
|
36
|
-
# --- Parse arguments ---
|
|
37
|
-
COMMIT_HASH="$1"
|
|
38
|
-
OUTPUT_PATH="$2"
|
|
39
|
-
|
|
40
|
-
# --- Validation ---
|
|
41
|
-
if [ -z "$COMMIT_HASH" ] || [ -z "$OUTPUT_PATH" ]; then
|
|
42
|
-
echo "Error: Commit hash and output path required"
|
|
43
|
-
echo "Usage: $0 <commit-hash> <output-path>"
|
|
44
|
-
exit 1
|
|
45
|
-
fi
|
|
46
|
-
|
|
47
|
-
# --- Find git root ---
|
|
48
|
-
GIT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
|
|
49
|
-
if [ -z "$GIT_ROOT" ]; then
|
|
50
|
-
echo "Error: Not in a git repository"
|
|
51
|
-
exit 1
|
|
52
|
-
fi
|
|
53
|
-
cd "$GIT_ROOT"
|
|
54
|
-
|
|
55
|
-
# --- Verify commit exists ---
|
|
56
|
-
if ! git rev-parse "$COMMIT_HASH" >/dev/null 2>&1; then
|
|
57
|
-
echo "Error: Commit $COMMIT_HASH not found"
|
|
58
|
-
exit 1
|
|
59
|
-
fi
|
|
60
|
-
|
|
61
|
-
# --- Build exclusion arguments ---
|
|
62
|
-
EXCLUDE_ARGS=""
|
|
63
|
-
for pattern in "${EXCLUSIONS[@]}"; do
|
|
64
|
-
EXCLUDE_ARGS="$EXCLUDE_ARGS ':!$pattern'"
|
|
65
|
-
done
|
|
66
|
-
|
|
67
|
-
# --- Generate diff from parent commit to specified commit ---
|
|
68
|
-
eval "git diff \"${COMMIT_HASH}^\" \"$COMMIT_HASH\" -- . $EXCLUDE_ARGS" > "$OUTPUT_PATH"
|
|
69
|
-
|
|
70
|
-
# --- Check result ---
|
|
71
|
-
if [ ! -s "$OUTPUT_PATH" ]; then
|
|
72
|
-
rm -f "$OUTPUT_PATH"
|
|
73
|
-
echo "No implementation changes outside excluded patterns"
|
|
74
|
-
echo "Patch skipped"
|
|
75
|
-
exit 0
|
|
76
|
-
fi
|
|
77
|
-
|
|
78
|
-
PATCH_LINES=$(wc -l < "$OUTPUT_PATH" | tr -d ' ')
|
|
79
|
-
echo "Generated: $OUTPUT_PATH ($PATCH_LINES lines)"
|