mindsystem-cc 3.20.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.
Files changed (79) hide show
  1. package/README.md +5 -6
  2. package/agents/ms-mockup-designer.md +1 -1
  3. package/agents/ms-product-researcher.md +69 -0
  4. package/agents/ms-research-synthesizer.md +1 -1
  5. package/agents/ms-researcher.md +8 -8
  6. package/agents/ms-roadmapper.md +9 -13
  7. package/bin/install.js +68 -5
  8. package/commands/ms/add-phase.md +4 -4
  9. package/commands/ms/adhoc.md +1 -1
  10. package/commands/ms/audit-milestone.md +12 -12
  11. package/commands/ms/complete-milestone.md +25 -22
  12. package/commands/ms/config.md +202 -0
  13. package/commands/ms/design-phase.md +3 -8
  14. package/commands/ms/discuss-phase.md +26 -22
  15. package/commands/ms/doctor.md +22 -202
  16. package/commands/ms/execute-phase.md +18 -7
  17. package/commands/ms/help.md +46 -39
  18. package/commands/ms/insert-phase.md +3 -3
  19. package/commands/ms/new-milestone.md +40 -16
  20. package/commands/ms/new-project.md +53 -42
  21. package/commands/ms/plan-milestone-gaps.md +4 -5
  22. package/commands/ms/plan-phase.md +2 -2
  23. package/commands/ms/progress.md +2 -4
  24. package/commands/ms/research-phase.md +7 -12
  25. package/commands/ms/research-project.md +12 -12
  26. package/mindsystem/references/continuation-format.md +3 -3
  27. package/mindsystem/references/principles.md +1 -1
  28. package/mindsystem/references/routing/audit-result-routing.md +12 -11
  29. package/mindsystem/references/routing/between-milestones-routing.md +2 -2
  30. package/mindsystem/references/routing/milestone-complete-routing.md +1 -1
  31. package/mindsystem/references/routing/next-phase-routing.md +4 -2
  32. package/mindsystem/templates/context.md +7 -6
  33. package/mindsystem/templates/milestone-archive.md +5 -5
  34. package/mindsystem/templates/milestone-context.md +1 -1
  35. package/mindsystem/templates/milestone.md +9 -9
  36. package/mindsystem/templates/project.md +2 -2
  37. package/mindsystem/templates/research-subagent-prompt.md +3 -3
  38. package/mindsystem/templates/roadmap-milestone.md +14 -14
  39. package/mindsystem/templates/roadmap.md +9 -7
  40. package/mindsystem/workflows/adhoc.md +1 -1
  41. package/mindsystem/workflows/complete-milestone.md +40 -75
  42. package/mindsystem/workflows/discuss-phase.md +137 -65
  43. package/mindsystem/workflows/doctor-fixes.md +273 -0
  44. package/mindsystem/workflows/execute-phase.md +7 -3
  45. package/mindsystem/workflows/execute-plan.md +3 -0
  46. package/mindsystem/workflows/map-codebase.md +2 -2
  47. package/mindsystem/workflows/mockup-generation.md +1 -1
  48. package/mindsystem/workflows/plan-phase.md +1 -1
  49. package/mindsystem/workflows/transition.md +2 -2
  50. package/mindsystem/workflows/verify-work.md +1 -1
  51. package/package.json +1 -1
  52. package/scripts/__pycache__/ms-tools.cpython-314.pyc +0 -0
  53. package/scripts/__pycache__/test_ms_tools.cpython-314-pytest-9.0.2.pyc +0 -0
  54. package/scripts/fixtures/scan-context/.planning/ROADMAP.md +16 -0
  55. package/scripts/fixtures/scan-context/.planning/adhoc/20260220-fix-token-SUMMARY.md +12 -0
  56. package/scripts/fixtures/scan-context/.planning/config.json +3 -0
  57. package/scripts/fixtures/scan-context/.planning/debug/resolved/token-bug.md +11 -0
  58. package/scripts/fixtures/scan-context/.planning/knowledge/auth.md +11 -0
  59. package/scripts/fixtures/scan-context/.planning/phases/02-infra/02-1-SUMMARY.md +20 -0
  60. package/scripts/fixtures/scan-context/.planning/phases/04-setup/04-1-SUMMARY.md +21 -0
  61. package/scripts/fixtures/scan-context/.planning/phases/05-auth/05-1-SUMMARY.md +28 -0
  62. package/scripts/fixtures/scan-context/.planning/todos/done/setup-db.md +10 -0
  63. package/scripts/fixtures/scan-context/.planning/todos/pending/add-logout.md +10 -0
  64. package/scripts/fixtures/scan-context/expected-output.json +257 -0
  65. package/scripts/ms-tools.py +2139 -0
  66. package/scripts/test_ms_tools.py +836 -0
  67. package/commands/ms/list-phase-assumptions.md +0 -56
  68. package/mindsystem/workflows/list-phase-assumptions.md +0 -178
  69. package/scripts/__pycache__/compare_mockups.cpython-314.pyc +0 -0
  70. package/scripts/archive-milestone-files.sh +0 -68
  71. package/scripts/archive-milestone-phases.sh +0 -138
  72. package/scripts/doctor-scan.sh +0 -402
  73. package/scripts/gather-milestone-stats.sh +0 -179
  74. package/scripts/generate-adhoc-patch.sh +0 -79
  75. package/scripts/generate-phase-patch.sh +0 -169
  76. package/scripts/scan-artifact-subsystems.sh +0 -55
  77. package/scripts/scan-planning-context.py +0 -839
  78. package/scripts/update-state.sh +0 -59
  79. package/scripts/validate-execution-order.sh +0 -104
@@ -1,402 +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
- # --- Helper: parse phase numbers from a "Phases completed" line ---
57
- # Outputs one phase number per line. Handles:
58
- # - Range format: "1-6" → 1 2 3 4 5 6
59
- # - Comma-separated: "8, 8.3, 9, 10" → 8 8.3 9 10
60
- # - Mixed (multiple milestone entries each handled independently)
61
- parse_phase_numbers() {
62
- local line="$1"
63
- local range
64
- range=$(echo "$line" | grep -o '[0-9]\+-[0-9]\+' || true)
65
- if [ -n "$range" ]; then
66
- local range_start range_end
67
- range_start=$(echo "$range" | cut -d'-' -f1)
68
- range_end=$(echo "$range" | cut -d'-' -f2)
69
- seq "$range_start" "$range_end"
70
- else
71
- echo "$line" | sed 's/.*://' | grep -oE '[0-9]+(\.[0-9]+)?' || true
72
- fi
73
- }
74
-
75
- # --- Helper: format phase number as zero-padded directory prefix ---
76
- # Integer (9) → "09", Decimal (8.3) → "08.3"
77
- format_phase_prefix() {
78
- local phase="$1"
79
- if echo "$phase" | grep -q '\.'; then
80
- local int_part dec_part
81
- int_part=$(echo "$phase" | cut -d'.' -f1)
82
- dec_part=$(echo "$phase" | cut -d'.' -f2)
83
- printf "%02d.%s" "$int_part" "$dec_part"
84
- else
85
- printf "%02d" "$phase"
86
- fi
87
- }
88
-
89
- # ============================================================
90
- # CHECK 1: Subsystem Vocabulary
91
- # ============================================================
92
- echo "=== Subsystem Vocabulary ==="
93
-
94
- SUBSYSTEM_COUNT=$(jq -r '.subsystems // [] | length' "$CONFIG" 2>/dev/null || echo "0")
95
-
96
- if [ "$SUBSYSTEM_COUNT" -eq 0 ]; then
97
- echo "Status: FAIL"
98
- echo "No subsystems array in config.json (or empty)"
99
- record_result "FAIL" "Subsystem Vocabulary"
100
- else
101
- echo "Subsystems: $SUBSYSTEM_COUNT configured"
102
- jq -r '.subsystems[]' "$CONFIG" 2>/dev/null | sed 's/^/ - /'
103
-
104
- # Run artifact scan to check for mismatches
105
- SCAN_SCRIPT="$(dirname "$0")/scan-artifact-subsystems.sh"
106
- if [ -x "$SCAN_SCRIPT" ]; then
107
- CANONICAL=$(jq -r '.subsystems[]' "$CONFIG" 2>/dev/null)
108
- ARTIFACT_VALUES=$("$SCAN_SCRIPT" --values-only 2>/dev/null | grep -v '^===' | sort -u)
109
- MISMATCHES=""
110
- while IFS= read -r val; do
111
- [ -z "$val" ] && continue
112
- if ! echo "$CANONICAL" | grep -qx "$val"; then
113
- MISMATCHES="$MISMATCHES $val"
114
- fi
115
- done <<< "$ARTIFACT_VALUES"
116
-
117
- if [ -n "$MISMATCHES" ]; then
118
- echo "Status: FAIL"
119
- echo "Artifact values not in canonical list:$MISMATCHES"
120
- record_result "FAIL" "Subsystem Vocabulary"
121
- else
122
- ARTIFACT_COUNT=$("$SCAN_SCRIPT" --values-only 2>/dev/null | grep -v '^===' | wc -l | tr -d ' ')
123
- echo "Artifacts scanned: $ARTIFACT_COUNT (all OK)"
124
- echo "Status: PASS"
125
- record_result "PASS" "Subsystem Vocabulary"
126
- fi
127
- else
128
- echo "Status: PASS"
129
- echo "(scan-artifact-subsystems.sh not found — skipped artifact validation)"
130
- record_result "PASS" "Subsystem Vocabulary"
131
- fi
132
- fi
133
- echo ""
134
-
135
- # ============================================================
136
- # CHECK 2: Milestone Directory Structure
137
- # ============================================================
138
- echo "=== Milestone Directory Structure ==="
139
-
140
- if [ ! -d "$MILESTONES_DIR" ]; then
141
- # No milestones directory at all — check if MILESTONES.md has entries
142
- if [ -f "$MILESTONES_FILE" ] && grep -q "^## " "$MILESTONES_FILE" 2>/dev/null; then
143
- echo "Status: FAIL"
144
- echo "MILESTONES.md has entries but no milestones/ directory"
145
- record_result "FAIL" "Milestone Directory Structure"
146
- else
147
- echo "Status: SKIP"
148
- echo "No completed milestones"
149
- record_result "SKIP" "Milestone Directory Structure"
150
- fi
151
- else
152
- # Look for flat files matching v*-*.md directly in milestones/
153
- FLAT_FILES=""
154
- FLAT_COUNT=0
155
- for f in "$MILESTONES_DIR"/v*-*.md; do
156
- [ -f "$f" ] || continue
157
- FLAT_FILES="$FLAT_FILES $(basename "$f")"$'\n'
158
- FLAT_COUNT=$((FLAT_COUNT + 1))
159
- done
160
-
161
- if [ "$FLAT_COUNT" -gt 0 ]; then
162
- echo "Status: FAIL"
163
- echo "Found $FLAT_COUNT flat file(s) in milestones/ (old format):"
164
- echo "$FLAT_FILES"
165
- # Check if corresponding versioned directories exist
166
- for f in "$MILESTONES_DIR"/v*-*.md; do
167
- [ -f "$f" ] || continue
168
- fname=$(basename "$f")
169
- # Extract version prefix: v0.1-ROADMAP.md -> v0.1
170
- version=$(echo "$fname" | sed 's/^\(v[0-9.]*\)-.*/\1/')
171
- if [ -d "$MILESTONES_DIR/$version" ]; then
172
- echo " $fname → directory $version/ exists (can restructure)"
173
- else
174
- echo " $fname → directory $version/ missing (need to create)"
175
- fi
176
- done
177
- record_result "FAIL" "Milestone Directory Structure"
178
- else
179
- # Count versioned directories
180
- DIR_COUNT=0
181
- for d in "$MILESTONES_DIR"/v*/; do
182
- [ -d "$d" ] || continue
183
- DIR_COUNT=$((DIR_COUNT + 1))
184
- done
185
-
186
- if [ "$DIR_COUNT" -eq 0 ]; then
187
- echo "Status: SKIP"
188
- echo "No completed milestones"
189
- record_result "SKIP" "Milestone Directory Structure"
190
- else
191
- echo "Status: PASS"
192
- echo "$DIR_COUNT versioned milestone directories"
193
- record_result "PASS" "Milestone Directory Structure"
194
- fi
195
- fi
196
- fi
197
- echo ""
198
-
199
- # ============================================================
200
- # CHECK 3: Phase Archival
201
- # ============================================================
202
- echo "=== Phase Archival ==="
203
-
204
- if [ ! -f "$MILESTONES_FILE" ] || ! grep -q "Phases completed" "$MILESTONES_FILE" 2>/dev/null; then
205
- echo "Status: SKIP"
206
- echo "No completed milestones with phase ranges in MILESTONES.md"
207
- record_result "SKIP" "Phase Archival"
208
- else
209
- ORPHAN_COUNT=0
210
- ORPHAN_LIST=""
211
-
212
- # Parse each milestone's completed phases from MILESTONES.md
213
- while IFS= read -r line; do
214
- while IFS= read -r phase_num; do
215
- [ -z "$phase_num" ] && continue
216
- prefix=$(format_phase_prefix "$phase_num")
217
- for dir in "$PHASES_DIR"/${prefix}-*/; do
218
- [ -d "$dir" ] || continue
219
- dirname=$(basename "$dir")
220
- ORPHAN_COUNT=$((ORPHAN_COUNT + 1))
221
- ORPHAN_LIST="$ORPHAN_LIST $dirname (should be archived)"$'\n'
222
- done
223
- done < <(parse_phase_numbers "$line")
224
- done < <(grep "Phases completed" "$MILESTONES_FILE")
225
-
226
- if [ "$ORPHAN_COUNT" -gt 0 ]; then
227
- echo "Status: FAIL"
228
- echo "Found $ORPHAN_COUNT orphaned phase directories from completed milestones:"
229
- echo "$ORPHAN_LIST"
230
- record_result "FAIL" "Phase Archival"
231
- else
232
- echo "Status: PASS"
233
- echo "All completed milestone phases are archived"
234
- record_result "PASS" "Phase Archival"
235
- fi
236
- fi
237
- echo ""
238
-
239
- # ============================================================
240
- # CHECK 4: Knowledge Files
241
- # ============================================================
242
- echo "=== Knowledge Files ==="
243
-
244
- if [ "$SUBSYSTEM_COUNT" -eq 0 ]; then
245
- echo "Status: SKIP"
246
- echo "No subsystems configured — knowledge check requires subsystem vocabulary"
247
- record_result "SKIP" "Knowledge Files"
248
- elif [ ! -d "$KNOWLEDGE_DIR" ]; then
249
- echo "Status: FAIL"
250
- echo "Knowledge directory missing: .planning/knowledge/"
251
- echo "Expected files for $SUBSYSTEM_COUNT subsystems"
252
- record_result "FAIL" "Knowledge Files"
253
- else
254
- MISSING_KNOWLEDGE=""
255
- MISSING_COUNT=0
256
- PRESENT_COUNT=0
257
- while IFS= read -r subsystem; do
258
- [ -z "$subsystem" ] && continue
259
- if [ -f "$KNOWLEDGE_DIR/$subsystem.md" ]; then
260
- PRESENT_COUNT=$((PRESENT_COUNT + 1))
261
- else
262
- MISSING_COUNT=$((MISSING_COUNT + 1))
263
- MISSING_KNOWLEDGE="$MISSING_KNOWLEDGE $subsystem.md"$'\n'
264
- fi
265
- done < <(jq -r '.subsystems[]' "$CONFIG" 2>/dev/null)
266
-
267
- # Check for orphaned knowledge files (not in subsystem list)
268
- ORPHAN_KNOWLEDGE=""
269
- ORPHAN_K_COUNT=0
270
- for f in "$KNOWLEDGE_DIR"/*.md; do
271
- [ -f "$f" ] || continue
272
- fname=$(basename "$f" .md)
273
- if ! jq -r '.subsystems[]' "$CONFIG" 2>/dev/null | grep -qx "$fname"; then
274
- ORPHAN_K_COUNT=$((ORPHAN_K_COUNT + 1))
275
- ORPHAN_KNOWLEDGE="$ORPHAN_KNOWLEDGE $fname.md (not in subsystems list)"$'\n'
276
- fi
277
- done
278
-
279
- if [ "$MISSING_COUNT" -gt 0 ] || [ "$ORPHAN_K_COUNT" -gt 0 ]; then
280
- echo "Status: FAIL"
281
- echo "Coverage: $PRESENT_COUNT/$SUBSYSTEM_COUNT subsystems have knowledge files"
282
- if [ "$MISSING_COUNT" -gt 0 ]; then
283
- echo "Missing:"
284
- echo "$MISSING_KNOWLEDGE"
285
- fi
286
- if [ "$ORPHAN_K_COUNT" -gt 0 ]; then
287
- echo "Orphaned:"
288
- echo "$ORPHAN_KNOWLEDGE"
289
- fi
290
- record_result "FAIL" "Knowledge Files"
291
- else
292
- echo "Status: PASS"
293
- echo "All $SUBSYSTEM_COUNT subsystems have knowledge files"
294
- record_result "PASS" "Knowledge Files"
295
- fi
296
- fi
297
- echo ""
298
-
299
- # ============================================================
300
- # CHECK 5: Phase Summaries
301
- # ============================================================
302
- echo "=== Phase Summaries ==="
303
-
304
- if [ ! -d "$MILESTONES_DIR" ]; then
305
- echo "Status: SKIP"
306
- echo "No milestones directory"
307
- record_result "SKIP" "Phase Summaries"
308
- else
309
- MISSING_SUMMARIES=""
310
- MISSING_S_COUNT=0
311
- CHECKED=0
312
-
313
- for d in "$MILESTONES_DIR"/v*/; do
314
- [ -d "$d" ] || continue
315
- CHECKED=$((CHECKED + 1))
316
- version=$(basename "$d")
317
- if [ ! -f "$d/PHASE-SUMMARIES.md" ]; then
318
- MISSING_S_COUNT=$((MISSING_S_COUNT + 1))
319
- MISSING_SUMMARIES="$MISSING_SUMMARIES $version/PHASE-SUMMARIES.md"$'\n'
320
- fi
321
- done
322
-
323
- if [ "$CHECKED" -eq 0 ]; then
324
- echo "Status: SKIP"
325
- echo "No versioned milestone directories"
326
- record_result "SKIP" "Phase Summaries"
327
- elif [ "$MISSING_S_COUNT" -gt 0 ]; then
328
- echo "Status: FAIL"
329
- echo "Missing PHASE-SUMMARIES.md in $MISSING_S_COUNT milestone(s):"
330
- echo "$MISSING_SUMMARIES"
331
- record_result "FAIL" "Phase Summaries"
332
- else
333
- echo "Status: PASS"
334
- echo "All $CHECKED milestones have PHASE-SUMMARIES.md"
335
- record_result "PASS" "Phase Summaries"
336
- fi
337
- fi
338
- echo ""
339
-
340
- # ============================================================
341
- # CHECK 6: PLAN Cleanup
342
- # ============================================================
343
- echo "=== PLAN Cleanup ==="
344
-
345
- if [ ! -f "$MILESTONES_FILE" ] || ! grep -q "Phases completed" "$MILESTONES_FILE" 2>/dev/null; then
346
- echo "Status: SKIP"
347
- echo "No completed milestones — active phase PLANs are expected"
348
- record_result "SKIP" "PLAN Cleanup"
349
- else
350
- LEFTOVER_PLANS=""
351
- LEFTOVER_COUNT=0
352
-
353
- # Check phases/ for PLANs belonging to completed milestones
354
- while IFS= read -r line; do
355
- while IFS= read -r phase_num; do
356
- [ -z "$phase_num" ] && continue
357
- prefix=$(format_phase_prefix "$phase_num")
358
- for plan in "$PHASES_DIR"/${prefix}-*/*-PLAN.md; do
359
- [ -f "$plan" ] || continue
360
- LEFTOVER_COUNT=$((LEFTOVER_COUNT + 1))
361
- LEFTOVER_PLANS="$LEFTOVER_PLANS $(echo "$plan" | sed "s|$GIT_ROOT/.planning/||")"$'\n'
362
- done
363
- done < <(parse_phase_numbers "$line")
364
- done < <(grep "Phases completed" "$MILESTONES_FILE")
365
-
366
- # Check archived milestone phase directories for leftover PLANs
367
- for d in "$MILESTONES_DIR"/v*/phases/*/; do
368
- [ -d "$d" ] || continue
369
- for plan in "$d"*-PLAN.md; do
370
- [ -f "$plan" ] || continue
371
- LEFTOVER_COUNT=$((LEFTOVER_COUNT + 1))
372
- LEFTOVER_PLANS="$LEFTOVER_PLANS $(echo "$plan" | sed "s|$GIT_ROOT/.planning/||")"$'\n'
373
- done
374
- done
375
-
376
- if [ "$LEFTOVER_COUNT" -gt 0 ]; then
377
- echo "Status: FAIL"
378
- echo "Found $LEFTOVER_COUNT leftover PLAN file(s) in completed phases:"
379
- echo "$LEFTOVER_PLANS"
380
- record_result "FAIL" "PLAN Cleanup"
381
- else
382
- echo "Status: PASS"
383
- echo "No leftover PLAN files in completed phases"
384
- record_result "PASS" "PLAN Cleanup"
385
- fi
386
- fi
387
- echo ""
388
-
389
- # ============================================================
390
- # SUMMARY
391
- # ============================================================
392
- TOTAL=$((PASS_COUNT + FAIL_COUNT + SKIP_COUNT))
393
- echo "=== Summary ==="
394
- echo "Checks: $TOTAL total, $PASS_COUNT passed, $FAIL_COUNT failed, $SKIP_COUNT skipped"
395
-
396
- if [ "$FAIL_COUNT" -gt 0 ]; then
397
- echo "Issues:$FAILED_CHECKS"
398
- exit 1
399
- else
400
- echo "All checks passed"
401
- exit 0
402
- 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)"