shipwright-cli 1.9.0 → 2.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 (117) hide show
  1. package/.claude/hooks/post-tool-use.sh +12 -5
  2. package/README.md +114 -36
  3. package/completions/_shipwright +212 -32
  4. package/completions/shipwright.bash +97 -25
  5. package/docs/strategy/01-market-research.md +619 -0
  6. package/docs/strategy/02-mission-and-brand.md +587 -0
  7. package/docs/strategy/03-gtm-and-roadmap.md +759 -0
  8. package/docs/strategy/QUICK-START.txt +289 -0
  9. package/docs/strategy/README.md +172 -0
  10. package/package.json +4 -2
  11. package/scripts/sw +217 -2
  12. package/scripts/sw-activity.sh +500 -0
  13. package/scripts/sw-adaptive.sh +925 -0
  14. package/scripts/sw-adversarial.sh +1 -1
  15. package/scripts/sw-architecture-enforcer.sh +1 -1
  16. package/scripts/sw-auth.sh +613 -0
  17. package/scripts/sw-autonomous.sh +664 -0
  18. package/scripts/sw-changelog.sh +704 -0
  19. package/scripts/sw-checkpoint.sh +79 -1
  20. package/scripts/sw-ci.sh +602 -0
  21. package/scripts/sw-cleanup.sh +192 -7
  22. package/scripts/sw-code-review.sh +637 -0
  23. package/scripts/sw-connect.sh +1 -1
  24. package/scripts/sw-context.sh +605 -0
  25. package/scripts/sw-cost.sh +1 -1
  26. package/scripts/sw-daemon.sh +812 -138
  27. package/scripts/sw-dashboard.sh +1 -1
  28. package/scripts/sw-db.sh +540 -0
  29. package/scripts/sw-decompose.sh +539 -0
  30. package/scripts/sw-deps.sh +551 -0
  31. package/scripts/sw-developer-simulation.sh +1 -1
  32. package/scripts/sw-discovery.sh +412 -0
  33. package/scripts/sw-docs-agent.sh +539 -0
  34. package/scripts/sw-docs.sh +1 -1
  35. package/scripts/sw-doctor.sh +59 -1
  36. package/scripts/sw-dora.sh +615 -0
  37. package/scripts/sw-durable.sh +710 -0
  38. package/scripts/sw-e2e-orchestrator.sh +535 -0
  39. package/scripts/sw-eventbus.sh +393 -0
  40. package/scripts/sw-feedback.sh +471 -0
  41. package/scripts/sw-fix.sh +1 -1
  42. package/scripts/sw-fleet-discover.sh +567 -0
  43. package/scripts/sw-fleet-viz.sh +404 -0
  44. package/scripts/sw-fleet.sh +8 -1
  45. package/scripts/sw-github-app.sh +596 -0
  46. package/scripts/sw-github-checks.sh +1 -1
  47. package/scripts/sw-github-deploy.sh +1 -1
  48. package/scripts/sw-github-graphql.sh +1 -1
  49. package/scripts/sw-guild.sh +569 -0
  50. package/scripts/sw-heartbeat.sh +1 -1
  51. package/scripts/sw-hygiene.sh +559 -0
  52. package/scripts/sw-incident.sh +617 -0
  53. package/scripts/sw-init.sh +88 -1
  54. package/scripts/sw-instrument.sh +699 -0
  55. package/scripts/sw-intelligence.sh +1 -1
  56. package/scripts/sw-jira.sh +1 -1
  57. package/scripts/sw-launchd.sh +366 -31
  58. package/scripts/sw-linear.sh +1 -1
  59. package/scripts/sw-logs.sh +1 -1
  60. package/scripts/sw-loop.sh +507 -51
  61. package/scripts/sw-memory.sh +198 -3
  62. package/scripts/sw-mission-control.sh +487 -0
  63. package/scripts/sw-model-router.sh +545 -0
  64. package/scripts/sw-otel.sh +596 -0
  65. package/scripts/sw-oversight.sh +689 -0
  66. package/scripts/sw-pipeline-composer.sh +8 -8
  67. package/scripts/sw-pipeline-vitals.sh +1096 -0
  68. package/scripts/sw-pipeline.sh +2451 -180
  69. package/scripts/sw-pm.sh +693 -0
  70. package/scripts/sw-pr-lifecycle.sh +522 -0
  71. package/scripts/sw-predictive.sh +1 -1
  72. package/scripts/sw-prep.sh +1 -1
  73. package/scripts/sw-ps.sh +4 -3
  74. package/scripts/sw-public-dashboard.sh +798 -0
  75. package/scripts/sw-quality.sh +595 -0
  76. package/scripts/sw-reaper.sh +5 -3
  77. package/scripts/sw-recruit.sh +573 -0
  78. package/scripts/sw-regression.sh +642 -0
  79. package/scripts/sw-release-manager.sh +736 -0
  80. package/scripts/sw-release.sh +706 -0
  81. package/scripts/sw-remote.sh +1 -1
  82. package/scripts/sw-replay.sh +520 -0
  83. package/scripts/sw-retro.sh +691 -0
  84. package/scripts/sw-scale.sh +444 -0
  85. package/scripts/sw-security-audit.sh +505 -0
  86. package/scripts/sw-self-optimize.sh +109 -8
  87. package/scripts/sw-session.sh +31 -9
  88. package/scripts/sw-setup.sh +1 -1
  89. package/scripts/sw-standup.sh +712 -0
  90. package/scripts/sw-status.sh +192 -1
  91. package/scripts/sw-strategic.sh +658 -0
  92. package/scripts/sw-stream.sh +450 -0
  93. package/scripts/sw-swarm.sh +583 -0
  94. package/scripts/sw-team-stages.sh +511 -0
  95. package/scripts/sw-templates.sh +1 -1
  96. package/scripts/sw-testgen.sh +515 -0
  97. package/scripts/sw-tmux-pipeline.sh +554 -0
  98. package/scripts/sw-tmux.sh +1 -1
  99. package/scripts/sw-trace.sh +485 -0
  100. package/scripts/sw-tracker-github.sh +188 -0
  101. package/scripts/sw-tracker-jira.sh +172 -0
  102. package/scripts/sw-tracker-linear.sh +251 -0
  103. package/scripts/sw-tracker.sh +117 -2
  104. package/scripts/sw-triage.sh +603 -0
  105. package/scripts/sw-upgrade.sh +1 -1
  106. package/scripts/sw-ux.sh +677 -0
  107. package/scripts/sw-webhook.sh +627 -0
  108. package/scripts/sw-widgets.sh +530 -0
  109. package/scripts/sw-worktree.sh +1 -1
  110. package/templates/pipelines/autonomous.json +8 -1
  111. package/templates/pipelines/cost-aware.json +21 -0
  112. package/templates/pipelines/deployed.json +40 -6
  113. package/templates/pipelines/enterprise.json +16 -2
  114. package/templates/pipelines/fast.json +19 -0
  115. package/templates/pipelines/full.json +16 -2
  116. package/templates/pipelines/hotfix.json +19 -0
  117. package/templates/pipelines/standard.json +19 -0
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env bash
2
2
  # ╔═══════════════════════════════════════════════════════════════════════════╗
3
- # ║ sw-cleanup.sh — Clean up orphaned Claude team sessions
3
+ # ║ sw-cleanup.sh — Clean up orphaned Claude team sessions & artifacts
4
4
  # ║ ║
5
5
  # ║ Default: dry-run (shows what would be cleaned). ║
6
6
  # ║ Use --force to actually kill sessions and remove files. ║
7
7
  # ╚═══════════════════════════════════════════════════════════════════════════╝
8
- VERSION="1.9.0"
8
+ VERSION="2.0.0"
9
9
  set -euo pipefail
10
10
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
11
11
 
@@ -31,7 +31,7 @@ for arg in "$@"; do
31
31
  case "$arg" in
32
32
  --force|-f) FORCE=true ;;
33
33
  --help|-h)
34
- echo -e "${CYAN}${BOLD}shipwright cleanup${RESET} — Clean up orphaned Claude team sessions"
34
+ echo -e "${CYAN}${BOLD}shipwright cleanup${RESET} — Clean up orphaned sessions and artifacts"
35
35
  echo ""
36
36
  echo -e "${BOLD}USAGE${RESET}"
37
37
  echo -e " shipwright cleanup ${DIM}# Dry-run: show what would be cleaned${RESET}"
@@ -53,6 +53,15 @@ TEAM_DIRS_FOUND=0
53
53
  TEAM_DIRS_REMOVED=0
54
54
  TASK_DIRS_FOUND=0
55
55
  TASK_DIRS_REMOVED=0
56
+ ARTIFACTS_FOUND=0
57
+ ARTIFACTS_REMOVED=0
58
+ CHECKPOINTS_FOUND=0
59
+ CHECKPOINTS_REMOVED=0
60
+ HEARTBEATS_FOUND=0
61
+ HEARTBEATS_REMOVED=0
62
+ BRANCHES_FOUND=0
63
+ BRANCHES_REMOVED=0
64
+ STATE_RESET=0
56
65
 
57
66
  # ─── 1. Find orphaned tmux windows ──────────────────────────────────────────
58
67
 
@@ -149,17 +158,193 @@ else
149
158
  echo -e " ${DIM}No task directories found.${RESET}"
150
159
  fi
151
160
 
161
+ # ─── 4. Pipeline Artifacts ──────────────────────────────────────────────────
162
+
163
+ echo ""
164
+ echo -e "${BOLD}Pipeline Artifacts${RESET} ${DIM}.claude/pipeline-artifacts/${RESET}"
165
+ echo -e "${DIM}────────────────────────────────────────${RESET}"
166
+
167
+ PIPELINE_ARTIFACTS=".claude/pipeline-artifacts"
168
+ if [[ -d "$PIPELINE_ARTIFACTS" ]]; then
169
+ artifact_file_count=$(find "$PIPELINE_ARTIFACTS" -type f 2>/dev/null | wc -l | tr -d ' ')
170
+ if [[ "${artifact_file_count:-0}" -gt 0 ]]; then
171
+ ARTIFACTS_FOUND=$((artifact_file_count))
172
+
173
+ # Calculate total size
174
+ artifact_size=$(du -sh "$PIPELINE_ARTIFACTS" 2>/dev/null | cut -f1 || echo "unknown")
175
+
176
+ if $FORCE; then
177
+ rm -rf "$PIPELINE_ARTIFACTS"
178
+ mkdir -p "$PIPELINE_ARTIFACTS"
179
+ ARTIFACTS_REMOVED=$((artifact_file_count))
180
+ echo -e " ${RED}✗${RESET} Cleaned ${artifact_file_count} files (${artifact_size})"
181
+ else
182
+ echo -e " ${YELLOW}○${RESET} Would clean: ${artifact_file_count} files (${artifact_size})"
183
+ fi
184
+ else
185
+ echo -e " ${DIM}No pipeline artifacts found.${RESET}"
186
+ fi
187
+ else
188
+ echo -e " ${DIM}No pipeline artifacts directory.${RESET}"
189
+ fi
190
+
191
+ # ─── 5. Checkpoints ────────────────────────────────────────────────────────
192
+
193
+ echo ""
194
+ echo -e "${BOLD}Checkpoints${RESET} ${DIM}.claude/pipeline-artifacts/checkpoints/${RESET}"
195
+ echo -e "${DIM}────────────────────────────────────────${RESET}"
196
+
197
+ CHECKPOINT_DIR=".claude/pipeline-artifacts/checkpoints"
198
+ if [[ -d "$CHECKPOINT_DIR" ]]; then
199
+ cp_file_count=0
200
+ for cp_file in "${CHECKPOINT_DIR}"/*-checkpoint.json; do
201
+ [[ -f "$cp_file" ]] || continue
202
+ cp_file_count=$((cp_file_count + 1))
203
+ done
204
+
205
+ if [[ "$cp_file_count" -gt 0 ]]; then
206
+ CHECKPOINTS_FOUND=$cp_file_count
207
+
208
+ if $FORCE; then
209
+ rm -f "${CHECKPOINT_DIR}"/*-checkpoint.json
210
+ CHECKPOINTS_REMOVED=$cp_file_count
211
+ echo -e " ${RED}✗${RESET} Removed ${cp_file_count} checkpoint(s)"
212
+ else
213
+ echo -e " ${YELLOW}○${RESET} Would remove: ${cp_file_count} checkpoint(s)"
214
+ fi
215
+ else
216
+ echo -e " ${DIM}No checkpoints found.${RESET}"
217
+ fi
218
+ else
219
+ echo -e " ${DIM}No checkpoint directory.${RESET}"
220
+ fi
221
+
222
+ # ─── 6. Pipeline State ─────────────────────────────────────────────────────
223
+
224
+ echo ""
225
+ echo -e "${BOLD}Pipeline State${RESET} ${DIM}.claude/pipeline-state.md${RESET}"
226
+ echo -e "${DIM}────────────────────────────────────────${RESET}"
227
+
228
+ PIPELINE_STATE=".claude/pipeline-state.md"
229
+ if [[ -f "$PIPELINE_STATE" ]]; then
230
+ state_status=$(sed -n 's/^status: *//p' "$PIPELINE_STATE" | head -1 || true)
231
+ state_issue=$(sed -n 's/^issue: *//p' "$PIPELINE_STATE" | head -1 || true)
232
+
233
+ case "${state_status:-}" in
234
+ complete|failed|idle|"")
235
+ if $FORCE; then
236
+ rm -f "$PIPELINE_STATE"
237
+ STATE_RESET=1
238
+ echo -e " ${RED}✗${RESET} Removed stale state (was: ${state_status:-empty}${state_issue:+, issue #$state_issue})"
239
+ else
240
+ echo -e " ${YELLOW}○${RESET} Would remove: status=${state_status:-empty}${state_issue:+, issue #$state_issue}"
241
+ fi
242
+ ;;
243
+ running|paused|interrupted)
244
+ echo -e " ${CYAN}●${RESET} Active pipeline: status=${state_status}${state_issue:+, issue #$state_issue} ${DIM}(skipping)${RESET}"
245
+ ;;
246
+ *)
247
+ echo -e " ${DIM}Unknown state: ${state_status}${RESET}"
248
+ ;;
249
+ esac
250
+ else
251
+ echo -e " ${DIM}No pipeline state file.${RESET}"
252
+ fi
253
+
254
+ # ─── 7. Stale Heartbeats ───────────────────────────────────────────────────
255
+
256
+ echo ""
257
+ echo -e "${BOLD}Heartbeats${RESET} ${DIM}~/.shipwright/heartbeats/${RESET}"
258
+ echo -e "${DIM}────────────────────────────────────────${RESET}"
259
+
260
+ HEARTBEAT_DIR="${HOME}/.shipwright/heartbeats"
261
+ if [[ -d "$HEARTBEAT_DIR" ]]; then
262
+ now_e=$(date +%s)
263
+ stale_threshold=3600 # 1 hour
264
+
265
+ while IFS= read -r hb_file; do
266
+ [[ -f "$hb_file" ]] || continue
267
+ hb_mtime=$(stat -f '%m' "$hb_file" 2>/dev/null || stat -c '%Y' "$hb_file" 2>/dev/null || echo "0")
268
+ if [[ $((now_e - hb_mtime)) -gt $stale_threshold ]]; then
269
+ HEARTBEATS_FOUND=$((HEARTBEATS_FOUND + 1))
270
+ hb_name=$(basename "$hb_file" .json)
271
+
272
+ if $FORCE; then
273
+ rm -f "$hb_file"
274
+ HEARTBEATS_REMOVED=$((HEARTBEATS_REMOVED + 1))
275
+ echo -e " ${RED}✗${RESET} Removed: ${hb_name} ${DIM}(stale >1h)${RESET}"
276
+ else
277
+ age_min=$(( (now_e - hb_mtime) / 60 ))
278
+ echo -e " ${YELLOW}○${RESET} Would remove: ${hb_name} ${DIM}(${age_min}m old)${RESET}"
279
+ fi
280
+ fi
281
+ done < <(find "$HEARTBEAT_DIR" -name '*.json' -type f 2>/dev/null)
282
+
283
+ if [[ "$HEARTBEATS_FOUND" -eq 0 ]]; then
284
+ echo -e " ${DIM}No stale heartbeats.${RESET}"
285
+ fi
286
+ else
287
+ echo -e " ${DIM}No heartbeat directory.${RESET}"
288
+ fi
289
+
290
+ # ─── 8. Orphaned pipeline/* branches ───────────────────────────────────────
291
+
292
+ echo ""
293
+ echo -e "${BOLD}Orphaned Branches${RESET} ${DIM}pipeline/* and daemon/*${RESET}"
294
+ echo -e "${DIM}────────────────────────────────────────${RESET}"
295
+
296
+ if command -v git &>/dev/null && git rev-parse --is-inside-work-tree &>/dev/null; then
297
+ # Collect active worktree paths
298
+ active_worktrees=""
299
+ while IFS= read -r wt_line; do
300
+ active_worktrees="${active_worktrees} ${wt_line}"
301
+ done < <(git worktree list --porcelain 2>/dev/null | grep '^worktree ' | sed 's/^worktree //')
302
+
303
+ while IFS= read -r branch; do
304
+ [[ -z "$branch" ]] && continue
305
+ branch="${branch## }" # trim leading spaces
306
+ # Check if this branch has an active worktree
307
+ has_worktree=false
308
+ for wt in $active_worktrees; do
309
+ if echo "$wt" | grep -q "${branch##*/}" 2>/dev/null; then
310
+ has_worktree=true
311
+ break
312
+ fi
313
+ done
314
+
315
+ if [[ "$has_worktree" == "false" ]]; then
316
+ BRANCHES_FOUND=$((BRANCHES_FOUND + 1))
317
+ if $FORCE; then
318
+ git branch -D "$branch" 2>/dev/null || true
319
+ BRANCHES_REMOVED=$((BRANCHES_REMOVED + 1))
320
+ echo -e " ${RED}✗${RESET} Deleted: ${branch}"
321
+ else
322
+ echo -e " ${YELLOW}○${RESET} Would delete: ${branch}"
323
+ fi
324
+ fi
325
+ done < <(git branch --list 'pipeline/*' --list 'daemon/*' 2>/dev/null)
326
+
327
+ if [[ "$BRANCHES_FOUND" -eq 0 ]]; then
328
+ echo -e " ${DIM}No orphaned branches.${RESET}"
329
+ fi
330
+ else
331
+ echo -e " ${DIM}Not in a git repository.${RESET}"
332
+ fi
333
+
152
334
  # ─── Summary ─────────────────────────────────────────────────────────────────
153
335
 
154
336
  echo ""
155
337
  echo -e "${DIM}────────────────────────────────────────${RESET}"
156
338
 
157
- TOTAL_FOUND=$((WINDOWS_FOUND + TEAM_DIRS_FOUND + TASK_DIRS_FOUND))
339
+ TOTAL_FOUND=$((WINDOWS_FOUND + TEAM_DIRS_FOUND + TASK_DIRS_FOUND + ARTIFACTS_FOUND + CHECKPOINTS_FOUND + HEARTBEATS_FOUND + BRANCHES_FOUND + STATE_RESET))
158
340
 
159
341
  if $FORCE; then
160
- TOTAL_CLEANED=$((WINDOWS_KILLED + TEAM_DIRS_REMOVED + TASK_DIRS_REMOVED))
342
+ TOTAL_CLEANED=$((WINDOWS_KILLED + TEAM_DIRS_REMOVED + TASK_DIRS_REMOVED + ARTIFACTS_REMOVED + CHECKPOINTS_REMOVED + HEARTBEATS_REMOVED + BRANCHES_REMOVED + STATE_RESET))
161
343
  if [[ $TOTAL_CLEANED -gt 0 ]]; then
162
- success "Cleaned ${TOTAL_CLEANED} items (${WINDOWS_KILLED} windows, ${TEAM_DIRS_REMOVED} team dirs, ${TASK_DIRS_REMOVED} task dirs)"
344
+ success "Cleaned ${TOTAL_CLEANED} items"
345
+ echo -e " ${DIM}windows: ${WINDOWS_KILLED}, teams: ${TEAM_DIRS_REMOVED}, tasks: ${TASK_DIRS_REMOVED}${RESET}"
346
+ echo -e " ${DIM}artifacts: ${ARTIFACTS_REMOVED}, checkpoints: ${CHECKPOINTS_REMOVED}, heartbeats: ${HEARTBEATS_REMOVED}${RESET}"
347
+ echo -e " ${DIM}branches: ${BRANCHES_REMOVED}, state: ${STATE_RESET}${RESET}"
163
348
  else
164
349
  success "Nothing to clean up."
165
350
  fi
@@ -168,7 +353,7 @@ else
168
353
  warn "Found ${TOTAL_FOUND} items to clean. Run with ${BOLD}--force${RESET} to remove them:"
169
354
  echo -e " ${DIM}shipwright cleanup --force${RESET}"
170
355
  else
171
- success "Everything is clean. No orphaned sessions found."
356
+ success "Everything is clean. No orphaned sessions or artifacts found."
172
357
  fi
173
358
  fi
174
359
  echo ""