@nlaprell/shipit 1.0.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 (160) hide show
  1. package/.cursor/commands/create_intent_from_issue.md +28 -0
  2. package/.cursor/commands/create_pr.md +28 -0
  3. package/.cursor/commands/dashboard.md +39 -0
  4. package/.cursor/commands/deploy.md +152 -0
  5. package/.cursor/commands/drift_check.md +36 -0
  6. package/.cursor/commands/fix.md +39 -0
  7. package/.cursor/commands/generate_release_plan.md +31 -0
  8. package/.cursor/commands/generate_roadmap.md +38 -0
  9. package/.cursor/commands/help.md +37 -0
  10. package/.cursor/commands/init_project.md +26 -0
  11. package/.cursor/commands/kill.md +72 -0
  12. package/.cursor/commands/new_intent.md +68 -0
  13. package/.cursor/commands/pr.md +77 -0
  14. package/.cursor/commands/revert-plan.md +58 -0
  15. package/.cursor/commands/risk.md +64 -0
  16. package/.cursor/commands/rollback.md +43 -0
  17. package/.cursor/commands/scope_project.md +53 -0
  18. package/.cursor/commands/ship.md +345 -0
  19. package/.cursor/commands/status.md +71 -0
  20. package/.cursor/commands/suggest.md +44 -0
  21. package/.cursor/commands/test_shipit.md +197 -0
  22. package/.cursor/commands/verify.md +50 -0
  23. package/.cursor/rules/architect.mdc +84 -0
  24. package/.cursor/rules/assumption-extractor.mdc +95 -0
  25. package/.cursor/rules/docs.mdc +66 -0
  26. package/.cursor/rules/implementer.mdc +112 -0
  27. package/.cursor/rules/pm.mdc +136 -0
  28. package/.cursor/rules/qa.mdc +97 -0
  29. package/.cursor/rules/security.mdc +90 -0
  30. package/.cursor/rules/steward.mdc +99 -0
  31. package/.cursor/rules/test-runner.mdc +196 -0
  32. package/AGENTS.md +121 -0
  33. package/README.md +264 -0
  34. package/_system/architecture/CANON.md +159 -0
  35. package/_system/architecture/invariants.yml +87 -0
  36. package/_system/architecture/project-schema.json +98 -0
  37. package/_system/architecture/workflow-state-layout.md +68 -0
  38. package/_system/artifacts/SYSTEM_STATE.md +43 -0
  39. package/_system/artifacts/confidence-calibration.json +16 -0
  40. package/_system/artifacts/dependencies.md +46 -0
  41. package/_system/artifacts/framework-files-manifest.json +179 -0
  42. package/_system/artifacts/usage.json +1 -0
  43. package/_system/behaviors/DO_RELEASE.md +371 -0
  44. package/_system/behaviors/DO_RELEASE_AI.md +329 -0
  45. package/_system/behaviors/PREPARE_RELEASE.md +373 -0
  46. package/_system/behaviors/PREPARE_RELEASE_AI.md +234 -0
  47. package/_system/behaviors/WORK_ROOT_PLATFORM_ISSUES.md +140 -0
  48. package/_system/behaviors/WORK_TEST_PLAN_ISSUES.md +380 -0
  49. package/_system/do-not-repeat/abandoned-designs.md +18 -0
  50. package/_system/do-not-repeat/bad-patterns.md +19 -0
  51. package/_system/do-not-repeat/failed-experiments.md +18 -0
  52. package/_system/do-not-repeat/rejected-libraries.md +19 -0
  53. package/_system/drift/baselines.md +49 -0
  54. package/_system/drift/metrics.md +33 -0
  55. package/_system/golden-data/.gitkeep +0 -0
  56. package/_system/golden-data/README.md +47 -0
  57. package/_system/reports/mutation/mutation.html +492 -0
  58. package/_system/security/audit-allowlist.json +4 -0
  59. package/bin/create-shipit-app +29 -0
  60. package/bin/shipit +183 -0
  61. package/cli/src/commands/check.js +82 -0
  62. package/cli/src/commands/create.js +195 -0
  63. package/cli/src/commands/init.js +267 -0
  64. package/cli/src/commands/upgrade.js +196 -0
  65. package/cli/src/utils/config.js +27 -0
  66. package/cli/src/utils/file-copy.js +144 -0
  67. package/cli/src/utils/gitignore-merge.js +44 -0
  68. package/cli/src/utils/manifest.js +105 -0
  69. package/cli/src/utils/package-json-merge.js +163 -0
  70. package/cli/src/utils/project-json-merge.js +57 -0
  71. package/cli/src/utils/prompts.js +30 -0
  72. package/cli/src/utils/stack-detection.js +56 -0
  73. package/cli/src/utils/stack-files.js +364 -0
  74. package/cli/src/utils/upgrade-backup.js +159 -0
  75. package/cli/src/utils/version.js +64 -0
  76. package/dashboard-app/README.md +73 -0
  77. package/dashboard-app/eslint.config.js +23 -0
  78. package/dashboard-app/index.html +13 -0
  79. package/dashboard-app/package.json +30 -0
  80. package/dashboard-app/pnpm-lock.yaml +2721 -0
  81. package/dashboard-app/public/dashboard.json +66 -0
  82. package/dashboard-app/public/vite.svg +1 -0
  83. package/dashboard-app/src/App.css +141 -0
  84. package/dashboard-app/src/App.tsx +155 -0
  85. package/dashboard-app/src/assets/react.svg +1 -0
  86. package/dashboard-app/src/index.css +68 -0
  87. package/dashboard-app/src/main.tsx +10 -0
  88. package/dashboard-app/tsconfig.app.json +28 -0
  89. package/dashboard-app/tsconfig.json +4 -0
  90. package/dashboard-app/tsconfig.node.json +26 -0
  91. package/dashboard-app/vite.config.ts +7 -0
  92. package/package.json +116 -0
  93. package/scripts/README.md +70 -0
  94. package/scripts/audit-check.sh +125 -0
  95. package/scripts/calibration-report.sh +198 -0
  96. package/scripts/check-readiness.sh +155 -0
  97. package/scripts/collect-metrics.sh +116 -0
  98. package/scripts/command-manifest.yml +131 -0
  99. package/scripts/create-test-plan-issue.sh +110 -0
  100. package/scripts/dashboard-start.sh +16 -0
  101. package/scripts/deploy.sh +170 -0
  102. package/scripts/drift-check.sh +93 -0
  103. package/scripts/execute-rollback.sh +177 -0
  104. package/scripts/export-dashboard-json.js +208 -0
  105. package/scripts/fix-intents.sh +239 -0
  106. package/scripts/generate-dashboard.sh +136 -0
  107. package/scripts/generate-docs.sh +279 -0
  108. package/scripts/generate-project-context.sh +142 -0
  109. package/scripts/generate-release-plan.sh +443 -0
  110. package/scripts/generate-roadmap.sh +189 -0
  111. package/scripts/generate-system-state.sh +95 -0
  112. package/scripts/gh/create-intent-from-issue.sh +82 -0
  113. package/scripts/gh/create-issue-from-intent.sh +59 -0
  114. package/scripts/gh/create-pr.sh +41 -0
  115. package/scripts/gh/link-issue.sh +44 -0
  116. package/scripts/gh/on-ship-update-issue.sh +42 -0
  117. package/scripts/headless/README.md +8 -0
  118. package/scripts/headless/call-llm.js +109 -0
  119. package/scripts/headless/run-phase.sh +99 -0
  120. package/scripts/help.sh +271 -0
  121. package/scripts/init-project.sh +976 -0
  122. package/scripts/kill-intent.sh +125 -0
  123. package/scripts/lib/common.sh +29 -0
  124. package/scripts/lib/intent.sh +61 -0
  125. package/scripts/lib/progress.sh +57 -0
  126. package/scripts/lib/suggest-next.sh +131 -0
  127. package/scripts/lib/validate-intents.sh +240 -0
  128. package/scripts/lib/verify-outputs.sh +55 -0
  129. package/scripts/lib/workflow_state.sh +201 -0
  130. package/scripts/new-intent.sh +271 -0
  131. package/scripts/publish-npm.sh +28 -0
  132. package/scripts/scope-project.sh +380 -0
  133. package/scripts/setup-worktrees.sh +125 -0
  134. package/scripts/status.sh +278 -0
  135. package/scripts/suggest.sh +173 -0
  136. package/scripts/test-headless.sh +47 -0
  137. package/scripts/test-shipit.sh +52 -0
  138. package/scripts/test-workflow-state.sh +49 -0
  139. package/scripts/usage-report.sh +47 -0
  140. package/scripts/usage.sh +58 -0
  141. package/scripts/validate-cursor.sh +151 -0
  142. package/scripts/validate-project.sh +71 -0
  143. package/scripts/validate-vscode.sh +146 -0
  144. package/scripts/verify.sh +153 -0
  145. package/scripts/workflow-orchestrator.sh +97 -0
  146. package/scripts/workflow-templates/01_analysis.md.tpl +25 -0
  147. package/scripts/workflow-templates/02_plan.md.tpl +30 -0
  148. package/scripts/workflow-templates/03_implementation.md.tpl +25 -0
  149. package/scripts/workflow-templates/04_verification.md.tpl +29 -0
  150. package/scripts/workflow-templates/05_release_notes.md.tpl +16 -0
  151. package/scripts/workflow-templates/05_verification_legacy.md.tpl +6 -0
  152. package/scripts/workflow-templates/active.md.tpl +18 -0
  153. package/scripts/workflow-templates/phases.yml +39 -0
  154. package/stryker.conf.json +8 -0
  155. package/work/intent/templates/api-endpoint.md +124 -0
  156. package/work/intent/templates/bugfix.md +116 -0
  157. package/work/intent/templates/frontend-feature.md +115 -0
  158. package/work/intent/templates/generic.md +122 -0
  159. package/work/intent/templates/infra-change.md +121 -0
  160. package/work/intent/templates/refactor.md +116 -0
@@ -0,0 +1,380 @@
1
+ #!/bin/bash
2
+
3
+ # AI-Assisted Project Scoping Script
4
+ # Breaks down project into features and generates initial intents
5
+
6
+ set -euo pipefail
7
+
8
+ error_exit() {
9
+ echo "ERROR: $1" >&2
10
+ exit "${2:-1}"
11
+ }
12
+
13
+ # Colors
14
+ GREEN='\033[0;32m'
15
+ YELLOW='\033[1;33m'
16
+ BLUE='\033[0;34m'
17
+ CYAN='\033[0;36m'
18
+ NC='\033[0m'
19
+
20
+ # Check if project.json exists
21
+ if [ ! -f "project.json" ]; then
22
+ error_exit "project.json not found. Run /init-project first." 1
23
+ fi
24
+
25
+ # Get project description
26
+ PROJECT_DESC="${1:-}"
27
+ if [ -z "$PROJECT_DESC" ]; then
28
+ read -p "Project description: " PROJECT_DESC
29
+ if [ -z "$PROJECT_DESC" ]; then
30
+ error_exit "Project description is required" 1
31
+ fi
32
+ fi
33
+
34
+ echo -e "${BLUE}Scoping project: $PROJECT_DESC${NC}"
35
+ echo ""
36
+
37
+ # Read project metadata (prefer jq, fallback to node; avoid hard dependency on jq)
38
+ read_project_json_field() {
39
+ local expr="$1"
40
+ local fallback="$2"
41
+
42
+ if command -v jq >/dev/null 2>&1; then
43
+ local v
44
+ v="$(jq -r "$expr" project.json 2>/dev/null || true)"
45
+ if [ -z "$v" ] || [ "$v" = "null" ]; then
46
+ echo "$fallback"
47
+ else
48
+ echo "$v"
49
+ fi
50
+ return 0
51
+ fi
52
+
53
+ if command -v node >/dev/null 2>&1; then
54
+ node -e "
55
+ const fs = require('fs');
56
+ try {
57
+ const p = JSON.parse(fs.readFileSync('project.json','utf8'));
58
+ const v = (function(){
59
+ // supported expr values: .name, .techStack, .highRiskDomains
60
+ if ('$expr' === '.name') return p.name;
61
+ if ('$expr' === '.techStack') return p.techStack;
62
+ if ('$expr' === '.highRiskDomains | join(\", \")') return Array.isArray(p.highRiskDomains) ? p.highRiskDomains.join(', ') : undefined;
63
+ return undefined;
64
+ })();
65
+ process.stdout.write((v === undefined || v === null || v === '') ? '$fallback' : String(v));
66
+ } catch {
67
+ process.stdout.write('$fallback');
68
+ }
69
+ " 2>/dev/null || echo "$fallback"
70
+ return 0
71
+ fi
72
+
73
+ echo "$fallback"
74
+ }
75
+
76
+ PROJECT_NAME="$(read_project_json_field '.name' 'project')"
77
+ TECH_STACK="$(read_project_json_field '.techStack' 'typescript-nodejs')"
78
+ HIGH_RISK="$(read_project_json_field '.highRiskDomains | join(", ")' 'none')"
79
+
80
+ echo -e "${YELLOW}Project Context:${NC}"
81
+ echo " Name: $PROJECT_NAME"
82
+ echo " Tech Stack: $TECH_STACK"
83
+ echo " High-Risk Domains: $HIGH_RISK"
84
+ echo ""
85
+
86
+ # Interactive follow-up questions with defaults (bash 3.2 compatible: no associative arrays)
87
+ FOLLOW_UP_QUESTIONS=(
88
+ "Is a UI required (API-only, CLI, Web)?"
89
+ "What persistence should be used (JSON file, SQLite, etc.)?"
90
+ "Single-user or multi-user?"
91
+ "Authentication required (none, API key, full auth)?"
92
+ "Any non-functional requirements (performance, scaling, etc.)?"
93
+ )
94
+
95
+ FOLLOW_UP_DEFAULTS=(
96
+ "Web"
97
+ "JSON file"
98
+ "Single-user"
99
+ "none"
100
+ "Fast for typical use cases"
101
+ )
102
+
103
+ FOLLOW_UP_ANSWERS=()
104
+
105
+ # Batch prompt: show all questions with defaults
106
+ echo -e "${YELLOW}Follow-Up Questions (required):${NC}"
107
+ echo ""
108
+ echo "Review and edit answers below. Press Enter to accept default, or type new answer."
109
+ echo ""
110
+
111
+ for i in "${!FOLLOW_UP_QUESTIONS[@]}"; do
112
+ question="${FOLLOW_UP_QUESTIONS[$i]}"
113
+ default="${FOLLOW_UP_DEFAULTS[$i]}"
114
+
115
+ # Show question with default
116
+ echo -e "${CYAN}Q$((i + 1)):${NC} $question"
117
+ echo -e " ${YELLOW}Default:${NC} $default"
118
+ read -p " Your answer [$default]: " answer
119
+
120
+ # Use default if empty, otherwise use provided answer
121
+ if [ -z "$answer" ]; then
122
+ answer="$default"
123
+ fi
124
+
125
+ FOLLOW_UP_ANSWERS+=("$answer")
126
+ echo ""
127
+ done
128
+
129
+ echo -e "${YELLOW}Review your answers:${NC}"
130
+ for i in "${!FOLLOW_UP_QUESTIONS[@]}"; do
131
+ echo " Q$((i + 1)): ${FOLLOW_UP_QUESTIONS[$i]}"
132
+ echo " A: ${FOLLOW_UP_ANSWERS[$i]}"
133
+ done
134
+ echo ""
135
+ read -p "Confirm answers? (y/n) [y]: " confirm
136
+ confirm="${confirm:-y}"
137
+
138
+ if [ "$confirm" != "y" ] && [ "$confirm" != "Y" ]; then
139
+ error_exit "Scoping cancelled. Re-run /scope-project to start over." 1
140
+ fi
141
+ echo ""
142
+
143
+ # Open questions (optional)
144
+ OPEN_QUESTIONS=()
145
+ echo -e "${YELLOW}Open Questions (optional, type 'done' when finished):${NC}"
146
+ while IFS= read -r line; do
147
+ [ "$line" = "done" ] && break
148
+ [ -z "$line" ] && continue
149
+ OPEN_QUESTIONS+=("$line")
150
+ done
151
+ echo ""
152
+
153
+ # Feature candidates (required)
154
+ FEATURES=()
155
+ echo -e "${YELLOW}Feature Candidates (required, one per line, type 'done' when finished):${NC}"
156
+ while IFS= read -r line; do
157
+ [ "$line" = "done" ] && break
158
+ [ -z "$line" ] && continue
159
+ FEATURES+=("$line")
160
+ done
161
+
162
+ if [ ${#FEATURES[@]} -eq 0 ]; then
163
+ error_exit "At least one feature candidate is required." 1
164
+ fi
165
+ echo ""
166
+
167
+ # Intent selection
168
+ echo -e "${YELLOW}Select features to generate intents:${NC}"
169
+ for i in "${!FEATURES[@]}"; do
170
+ idx=$((i + 1))
171
+ echo " $idx) ${FEATURES[$i]}"
172
+ done
173
+ read -p "Enter selection (all, none, or comma-separated numbers): " selection
174
+
175
+ SELECTED_FEATURES=()
176
+ case "$selection" in
177
+ all)
178
+ SELECTED_FEATURES=("${FEATURES[@]}")
179
+ ;;
180
+ none)
181
+ SELECTED_FEATURES=()
182
+ ;;
183
+ *)
184
+ IFS=',' read -r -a selected_indices <<< "$selection"
185
+ for raw_idx in "${selected_indices[@]}"; do
186
+ idx="$(echo "$raw_idx" | tr -d '[:space:]')"
187
+ if [[ "$idx" =~ ^[0-9]+$ ]] && [ "$idx" -ge 1 ] && [ "$idx" -le ${#FEATURES[@]} ]; then
188
+ SELECTED_FEATURES+=("${FEATURES[$((idx - 1))]}")
189
+ fi
190
+ done
191
+ ;;
192
+ esac
193
+
194
+ # Create project-scope.md
195
+ SCOPE_FILE="project-scope.md"
196
+ {
197
+ echo "# Project Scope: $PROJECT_NAME"
198
+ echo ""
199
+ echo "**Generated:** $(date -u +"%Y-%m-%dT%H:%M:%SZ")"
200
+ echo "**Description:** $PROJECT_DESC"
201
+ echo ""
202
+ echo "## Follow-Up Questions (with answers)"
203
+ echo ""
204
+ for i in "${!FOLLOW_UP_QUESTIONS[@]}"; do
205
+ echo "- Q: ${FOLLOW_UP_QUESTIONS[$i]}"
206
+ echo " A: ${FOLLOW_UP_ANSWERS[$i]}"
207
+ done
208
+ echo ""
209
+ echo "## Open Questions (unanswered)"
210
+ echo ""
211
+ if [ ${#OPEN_QUESTIONS[@]} -eq 0 ]; then
212
+ echo "(none)"
213
+ else
214
+ for q in "${OPEN_QUESTIONS[@]}"; do
215
+ echo "- $q"
216
+ done
217
+ fi
218
+ echo ""
219
+ echo "## Feature Candidates"
220
+ echo ""
221
+ for feature in "${FEATURES[@]}"; do
222
+ echo "- $feature"
223
+ done
224
+ echo ""
225
+ echo "## Intent Selection"
226
+ echo ""
227
+ if [ ${#SELECTED_FEATURES[@]} -eq 0 ]; then
228
+ echo "(none selected)"
229
+ else
230
+ for feature in "${SELECTED_FEATURES[@]}"; do
231
+ echo "- $feature"
232
+ done
233
+ fi
234
+ echo ""
235
+ echo "## Generated Intents"
236
+ echo ""
237
+ } > "$SCOPE_FILE" || error_exit "Failed to create project-scope.md"
238
+
239
+ echo -e "${GREEN}✓ Created $SCOPE_FILE${NC}"
240
+
241
+ # Create release plan stub if missing
242
+ RELEASE_DIR="work/release"
243
+ RELEASE_PLAN="$RELEASE_DIR/plan.md"
244
+ if [ ! -f "$RELEASE_PLAN" ]; then
245
+ mkdir -p "$RELEASE_DIR" || error_exit "Failed to create release directory"
246
+ cat > "$RELEASE_PLAN" << EOF || error_exit "Failed to create work/release/plan.md"
247
+ # Release Plan
248
+
249
+ **Generated:** $(date -u +"%Y-%m-%dT%H:%M:%SZ")
250
+
251
+ ## Summary
252
+
253
+ - Total intents: 0
254
+ - Planned intents: 0
255
+ - Releases: 0
256
+
257
+ EOF
258
+ echo -e "${GREEN}✓ Created $RELEASE_PLAN${NC}"
259
+ fi
260
+
261
+ # Best-effort release plan generation if available
262
+ INTENT_BASE_DIR="work/intent"
263
+ INTENT_DIR="$INTENT_BASE_DIR/features"
264
+ TEMPLATE_FILE="$INTENT_BASE_DIR/_TEMPLATE.md"
265
+
266
+ if [ ${#SELECTED_FEATURES[@]} -gt 0 ]; then
267
+ if [ ! -f "$TEMPLATE_FILE" ]; then
268
+ error_exit "Template file not found: $TEMPLATE_FILE" 1
269
+ fi
270
+ mkdir -p "$INTENT_DIR" || error_exit "Failed to create intent directory: $INTENT_DIR"
271
+
272
+ LAST_INTENT=0
273
+ while IFS= read -r file; do
274
+ [ -e "$file" ] || continue
275
+ base="$(basename "$file")"
276
+ if [[ "$base" =~ ^F-([0-9]+)\.md$ ]]; then
277
+ num="${BASH_REMATCH[1]}"
278
+ if ((10#$num > LAST_INTENT)); then
279
+ LAST_INTENT=$((10#$num))
280
+ fi
281
+ fi
282
+ done < <(find "$INTENT_BASE_DIR" -type f -name 'F-*.md' 2>/dev/null)
283
+ NEXT_NUM=$((LAST_INTENT + 1))
284
+
285
+ GENERATED_INTENTS=()
286
+ for feature in "${SELECTED_FEATURES[@]}"; do
287
+ INTENT_ID="F-$(printf "%03d" $NEXT_NUM)"
288
+ NEXT_NUM=$((NEXT_NUM + 1))
289
+
290
+ read -p "Dependencies for $INTENT_ID (comma-separated or 'none'): " deps_input
291
+ deps_input="${deps_input:-none}"
292
+ DEP_LINES=()
293
+ if [ "$deps_input" != "none" ]; then
294
+ IFS=',' read -r -a dep_items <<< "$deps_input"
295
+ for dep in "${dep_items[@]}"; do
296
+ dep_trim="$(echo "$dep" | tr -d '[:space:]')"
297
+ [ -z "$dep_trim" ] && continue
298
+ DEP_LINES+=("- ${dep_trim}")
299
+ done
300
+ fi
301
+ if [ ${#DEP_LINES[@]} -eq 0 ]; then
302
+ DEP_LINES+=("- (none)")
303
+ fi
304
+
305
+ INTENT_FILE="$INTENT_DIR/$INTENT_ID.md"
306
+ TEMP_FILE="$(mktemp)"
307
+ MOTIVATION_FILE="$(mktemp)"
308
+ DEP_FILE="$(mktemp)"
309
+
310
+ sed -e "s/# F-###: Title/# $INTENT_ID: $feature/" \
311
+ -e "s/feature | bug | tech-debt/feature/" \
312
+ -e "s/planned | active | blocked | validating | shipped | killed/planned/" \
313
+ -e "s/p0 | p1 | p2 | p3/p2/" \
314
+ -e "s/s | m | l/m/" \
315
+ -e "s/R1 | R2 | R3 | R4/R2/" \
316
+ "$TEMPLATE_FILE" > "$TEMP_FILE" || error_exit "Failed to create intent template"
317
+
318
+ printf "%s\n" "- ${feature}" > "$MOTIVATION_FILE"
319
+ printf "%s\n" "${DEP_LINES[@]}" > "$DEP_FILE"
320
+
321
+ awk -v motivation_file="$MOTIVATION_FILE" -v deps_file="$DEP_FILE" '
322
+ $0 == "(Why it exists, 1–3 bullets)" {
323
+ while ((getline line < motivation_file) > 0) print line;
324
+ close(motivation_file);
325
+ next;
326
+ }
327
+ /^- \(Other intent IDs that must ship first\)$/ {
328
+ # Replace placeholder dependency lines with actual deps
329
+ # Ensure dependencies are written at column 0 (no leading whitespace)
330
+ while ((getline line < deps_file) > 0) {
331
+ # Remove any leading whitespace and ensure line starts with "- "
332
+ sub(/^[[:space:]]+/, "", line);
333
+ if (line !~ /^- /) {
334
+ line = "- " line;
335
+ }
336
+ print line;
337
+ }
338
+ close(deps_file);
339
+ # Skip remaining placeholder dependency lines
340
+ while (getline > 0) {
341
+ if (/^## / || /^$/) {
342
+ print;
343
+ break;
344
+ }
345
+ # Skip placeholder lines (lines starting with "- (")
346
+ if (!/^- \(/) {
347
+ print;
348
+ }
349
+ }
350
+ next;
351
+ }
352
+ { print }
353
+ ' "$TEMP_FILE" > "$INTENT_FILE" || error_exit "Failed to create intent file"
354
+
355
+ rm -f "$TEMP_FILE" "$MOTIVATION_FILE" "$DEP_FILE"
356
+
357
+ GENERATED_INTENTS+=("$INTENT_ID")
358
+ done
359
+
360
+ {
361
+ echo ""
362
+ for id in "${GENERATED_INTENTS[@]}"; do
363
+ echo "- \`work/intent/features/${id}.md\`"
364
+ done
365
+ } >> "$SCOPE_FILE"
366
+ fi
367
+
368
+ if [ -x "./scripts/generate-release-plan.sh" ]; then
369
+ ./scripts/generate-release-plan.sh || echo "WARNING: release plan generation failed"
370
+ fi
371
+
372
+ if [ -x "./scripts/generate-roadmap.sh" ]; then
373
+ ./scripts/generate-roadmap.sh || echo "WARNING: roadmap generation failed"
374
+ fi
375
+ # Show next-step suggestions
376
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
377
+ if [ -f "$SCRIPT_DIR/lib/suggest-next.sh" ]; then
378
+ source "$SCRIPT_DIR/lib/suggest-next.sh"
379
+ display_suggestions "scoping"
380
+ fi
@@ -0,0 +1,125 @@
1
+ #!/bin/bash
2
+
3
+ # Setup Parallel Worktrees Script
4
+ # Creates isolated worktrees for parallel agent work
5
+
6
+ set -euo pipefail
7
+
8
+ # Error handling
9
+ error_exit() {
10
+ echo "ERROR: $1" >&2
11
+ exit "${2:-1}"
12
+ }
13
+
14
+ # Validate prerequisites
15
+ command -v git >/dev/null 2>&1 || error_exit "git is required but not installed"
16
+
17
+ # Validate inputs
18
+ INTENT_ID="${1:-}"
19
+ if [ -z "$INTENT_ID" ]; then
20
+ error_exit "Usage: $0 <intent-id> [task-count]" 1
21
+ fi
22
+
23
+ TASK_COUNT="${2:-3}"
24
+ if ! [[ "$TASK_COUNT" =~ ^[0-9]+$ ]] || [ "$TASK_COUNT" -lt 1 ] || [ "$TASK_COUNT" -gt 10 ]; then
25
+ error_exit "Task count must be between 1 and 10" 1
26
+ fi
27
+
28
+ BASE_DIR="$(pwd)"
29
+ WORKTREE_BASE="../worktree"
30
+
31
+ # Validate we're in a git repo
32
+ if ! git rev-parse --git-dir > /dev/null 2>&1; then
33
+ error_exit "Not a git repository. Run this from the repository root." 1
34
+ fi
35
+
36
+ echo "Setting up $TASK_COUNT worktrees for intent $INTENT_ID"
37
+
38
+ # Create worktrees.json
39
+ WORKTREES_FILE="worktrees.json"
40
+ if [ -f "$WORKTREES_FILE" ]; then
41
+ echo "WARNING: $WORKTREES_FILE already exists. Backing up to ${WORKTREES_FILE}.bak"
42
+ cp "$WORKTREES_FILE" "${WORKTREES_FILE}.bak" || error_exit "Failed to backup existing worktrees.json"
43
+ fi
44
+
45
+ cat > "$WORKTREES_FILE" << EOF || error_exit "Failed to create worktrees.json"
46
+ {
47
+ "intent_id": "$INTENT_ID",
48
+ "created": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")",
49
+ "tasks": [
50
+ EOF
51
+
52
+ for i in $(seq 1 $TASK_COUNT); do
53
+ WORKTREE_DIR="$WORKTREE_BASE-$i"
54
+ BRANCH="feature/$INTENT_ID-task-$i"
55
+
56
+ echo "Creating worktree $i: $WORKTREE_DIR"
57
+
58
+ # Check if worktree already exists
59
+ if [ -d "$WORKTREE_DIR" ]; then
60
+ echo "WARNING: Worktree $i already exists at $WORKTREE_DIR. Skipping..."
61
+ continue
62
+ fi
63
+
64
+ # Create worktree
65
+ if ! git worktree add "$WORKTREE_DIR" -b "$BRANCH" 2>/dev/null; then
66
+ echo "ERROR: Failed to create worktree $i. Branch $BRANCH may already exist."
67
+ echo "Try: git branch -D $BRANCH (if safe to delete)"
68
+ continue
69
+ fi
70
+
71
+ # Create .agent-id file with unique integer per worktree
72
+ if ! echo "$i" > "$WORKTREE_DIR/.agent-id"; then
73
+ error_exit "Failed to create .agent-id in worktree $i"
74
+ fi
75
+
76
+ # Register agent in coordination system
77
+ if [ -f "experimental/agent-coordinator.sh" ]; then
78
+ AGENT_ID="agent-$i"
79
+ # Agent will be registered when first task is assigned
80
+ fi
81
+
82
+ # Add to worktrees.json
83
+ if [ $i -gt 1 ]; then
84
+ echo "," >> worktrees.json
85
+ fi
86
+ cat >> worktrees.json << EOF
87
+ {
88
+ "id": $i,
89
+ "description": "Task $i for $INTENT_ID",
90
+ "worktree": "$WORKTREE_DIR",
91
+ "branch": "$BRANCH",
92
+ "status": "pending",
93
+ "assigned_at": null,
94
+ "completed_at": null
95
+ }
96
+ EOF
97
+ done
98
+
99
+ cat >> "$WORKTREES_FILE" << EOF || error_exit "Failed to complete worktrees.json"
100
+ ]
101
+ }
102
+ EOF
103
+
104
+ echo ""
105
+ echo "✓ Successfully created worktrees.json"
106
+
107
+ echo ""
108
+ echo "Worktrees created:"
109
+ for i in $(seq 1 $TASK_COUNT); do
110
+ echo " - $WORKTREE_BASE-$i (branch: feature/$INTENT_ID-task-$i)"
111
+ done
112
+ echo ""
113
+ echo "Next steps:"
114
+ echo "1. Open each worktree in a separate Cursor window"
115
+ echo "2. Each agent reads .agent-id to get their task number:"
116
+ echo " - Read the file: cat .agent-id (or read .agent-id in Cursor)"
117
+ echo " - The number in .agent-id corresponds to your task ID in worktrees.json"
118
+ echo " - Only work on the task matching your agent ID"
119
+ echo "3. Agents coordinate via worktrees.json in main repo"
120
+ echo ""
121
+ echo "Agent coordination:"
122
+ echo " - Each worktree has a .agent-id file containing a unique integer (1, 2, 3, etc.)"
123
+ echo " - Read your agent ID: AGENT_ID=\$(cat .agent-id)"
124
+ echo " - Find your task in worktrees.json where id == AGENT_ID"
125
+ echo " - Update your task status in worktrees.json as you progress"