shipwright-cli 2.2.2 → 2.3.1

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 (151) hide show
  1. package/README.md +12 -11
  2. package/dashboard/public/index.html +224 -8
  3. package/dashboard/public/styles.css +1078 -4
  4. package/dashboard/server.ts +1100 -15
  5. package/dashboard/src/canvas/interactions.ts +74 -0
  6. package/dashboard/src/canvas/layout.ts +85 -0
  7. package/dashboard/src/canvas/overlays.ts +117 -0
  8. package/dashboard/src/canvas/particles.ts +105 -0
  9. package/dashboard/src/canvas/renderer.ts +191 -0
  10. package/dashboard/src/components/charts/bar.ts +54 -0
  11. package/dashboard/src/components/charts/donut.ts +25 -0
  12. package/dashboard/src/components/charts/pipeline-rail.ts +105 -0
  13. package/dashboard/src/components/charts/sparkline.ts +82 -0
  14. package/dashboard/src/components/header.ts +616 -0
  15. package/dashboard/src/components/modal.ts +413 -0
  16. package/dashboard/src/components/terminal.ts +144 -0
  17. package/dashboard/src/core/api.test.ts +362 -0
  18. package/dashboard/src/core/api.ts +381 -0
  19. package/dashboard/src/core/helpers.ts +118 -0
  20. package/dashboard/src/core/router.test.ts +266 -0
  21. package/dashboard/src/core/router.ts +190 -0
  22. package/dashboard/src/core/sse.ts +38 -0
  23. package/dashboard/src/core/state.test.ts +235 -0
  24. package/dashboard/src/core/state.ts +150 -0
  25. package/dashboard/src/core/ws.test.ts +216 -0
  26. package/dashboard/src/core/ws.ts +143 -0
  27. package/dashboard/src/design/icons.test.ts +105 -0
  28. package/dashboard/src/design/icons.ts +131 -0
  29. package/dashboard/src/design/tokens.test.ts +204 -0
  30. package/dashboard/src/design/tokens.ts +160 -0
  31. package/dashboard/src/main.ts +68 -0
  32. package/dashboard/src/types/api.ts +337 -0
  33. package/dashboard/src/views/activity.ts +185 -0
  34. package/dashboard/src/views/agent-cockpit.ts +236 -0
  35. package/dashboard/src/views/agents.ts +72 -0
  36. package/dashboard/src/views/fleet-map.ts +299 -0
  37. package/dashboard/src/views/insights.ts +298 -0
  38. package/dashboard/src/views/machines.ts +162 -0
  39. package/dashboard/src/views/metrics.ts +420 -0
  40. package/dashboard/src/views/overview.ts +409 -0
  41. package/dashboard/src/views/pipeline-theater.ts +219 -0
  42. package/dashboard/src/views/pipelines.ts +595 -0
  43. package/dashboard/src/views/team.ts +362 -0
  44. package/dashboard/src/views/timeline.ts +389 -0
  45. package/dashboard/tsconfig.json +21 -0
  46. package/dashboard/vitest.config.ts +27 -0
  47. package/docs/AGI-WHATS-NEXT.md +15 -15
  48. package/package.json +16 -2
  49. package/scripts/lib/helpers.sh +30 -0
  50. package/scripts/lib/pipeline-quality-checks.sh +1 -1
  51. package/scripts/lib/pipeline-stages.sh +59 -0
  52. package/scripts/sw +86 -167
  53. package/scripts/sw-activity.sh +1 -1
  54. package/scripts/sw-adaptive.sh +1 -1
  55. package/scripts/sw-adversarial.sh +1 -1
  56. package/scripts/sw-architecture-enforcer.sh +1 -1
  57. package/scripts/sw-auth.sh +14 -6
  58. package/scripts/sw-autonomous.sh +230 -13
  59. package/scripts/sw-changelog.sh +2 -2
  60. package/scripts/sw-checkpoint.sh +1 -1
  61. package/scripts/sw-ci.sh +1 -1
  62. package/scripts/sw-cleanup.sh +1 -1
  63. package/scripts/sw-code-review.sh +1 -1
  64. package/scripts/sw-connect.sh +1 -1
  65. package/scripts/sw-context.sh +1 -1
  66. package/scripts/sw-cost.sh +1 -1
  67. package/scripts/sw-daemon.sh +2 -2
  68. package/scripts/sw-dashboard.sh +1 -1
  69. package/scripts/sw-db.sh +1 -1
  70. package/scripts/sw-decompose.sh +1 -1
  71. package/scripts/sw-deps.sh +1 -1
  72. package/scripts/sw-developer-simulation.sh +1 -1
  73. package/scripts/sw-discovery.sh +1 -1
  74. package/scripts/sw-doc-fleet.sh +1 -1
  75. package/scripts/sw-docs-agent.sh +1 -1
  76. package/scripts/sw-docs.sh +1 -1
  77. package/scripts/sw-doctor.sh +8 -1
  78. package/scripts/sw-dora.sh +1 -1
  79. package/scripts/sw-durable.sh +1 -1
  80. package/scripts/sw-e2e-orchestrator.sh +1 -1
  81. package/scripts/sw-eventbus.sh +1 -1
  82. package/scripts/sw-feedback.sh +1 -1
  83. package/scripts/sw-fix.sh +6 -5
  84. package/scripts/sw-fleet-discover.sh +1 -1
  85. package/scripts/sw-fleet-viz.sh +1 -1
  86. package/scripts/sw-fleet.sh +1 -1
  87. package/scripts/sw-github-app.sh +5 -2
  88. package/scripts/sw-github-checks.sh +1 -1
  89. package/scripts/sw-github-deploy.sh +1 -1
  90. package/scripts/sw-github-graphql.sh +1 -1
  91. package/scripts/sw-guild.sh +1 -1
  92. package/scripts/sw-heartbeat.sh +1 -1
  93. package/scripts/sw-hygiene.sh +1 -1
  94. package/scripts/sw-incident.sh +1 -1
  95. package/scripts/sw-init.sh +112 -9
  96. package/scripts/sw-instrument.sh +6 -1
  97. package/scripts/sw-intelligence.sh +5 -1
  98. package/scripts/sw-jira.sh +1 -1
  99. package/scripts/sw-launchd.sh +1 -1
  100. package/scripts/sw-linear.sh +20 -9
  101. package/scripts/sw-logs.sh +1 -1
  102. package/scripts/sw-loop.sh +2 -1
  103. package/scripts/sw-memory.sh +10 -1
  104. package/scripts/sw-mission-control.sh +1 -1
  105. package/scripts/sw-model-router.sh +4 -1
  106. package/scripts/sw-otel.sh +1 -1
  107. package/scripts/sw-oversight.sh +1 -1
  108. package/scripts/sw-pipeline-composer.sh +3 -1
  109. package/scripts/sw-pipeline-vitals.sh +4 -6
  110. package/scripts/sw-pipeline.sh +4 -1
  111. package/scripts/sw-pm.sh +5 -2
  112. package/scripts/sw-pr-lifecycle.sh +1 -1
  113. package/scripts/sw-predictive.sh +4 -1
  114. package/scripts/sw-prep.sh +3 -2
  115. package/scripts/sw-ps.sh +1 -1
  116. package/scripts/sw-public-dashboard.sh +10 -4
  117. package/scripts/sw-quality.sh +1 -1
  118. package/scripts/sw-reaper.sh +1 -1
  119. package/scripts/sw-recruit.sh +16 -0
  120. package/scripts/sw-regression.sh +2 -1
  121. package/scripts/sw-release-manager.sh +1 -1
  122. package/scripts/sw-release.sh +7 -5
  123. package/scripts/sw-remote.sh +1 -1
  124. package/scripts/sw-replay.sh +1 -1
  125. package/scripts/sw-retro.sh +4 -1
  126. package/scripts/sw-scale.sh +4 -1
  127. package/scripts/sw-security-audit.sh +1 -1
  128. package/scripts/sw-self-optimize.sh +113 -1
  129. package/scripts/sw-session.sh +1 -1
  130. package/scripts/sw-setup.sh +1 -1
  131. package/scripts/sw-standup.sh +2 -1
  132. package/scripts/sw-status.sh +1 -1
  133. package/scripts/sw-strategic.sh +2 -1
  134. package/scripts/sw-stream.sh +1 -1
  135. package/scripts/sw-swarm.sh +6 -1
  136. package/scripts/sw-team-stages.sh +1 -1
  137. package/scripts/sw-templates.sh +1 -1
  138. package/scripts/sw-testgen.sh +3 -2
  139. package/scripts/sw-tmux-pipeline.sh +2 -1
  140. package/scripts/sw-tmux.sh +1 -1
  141. package/scripts/sw-trace.sh +1 -1
  142. package/scripts/sw-tracker-jira.sh +1 -0
  143. package/scripts/sw-tracker-linear.sh +1 -0
  144. package/scripts/sw-tracker.sh +1 -1
  145. package/scripts/sw-triage.sh +198 -11
  146. package/scripts/sw-upgrade.sh +1 -1
  147. package/scripts/sw-ux.sh +1 -1
  148. package/scripts/sw-webhook.sh +1 -1
  149. package/scripts/sw-widgets.sh +2 -2
  150. package/scripts/sw-worktree.sh +1 -1
  151. package/dashboard/public/app.js +0 -4422
@@ -6,7 +6,7 @@
6
6
  set -euo pipefail
7
7
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
8
8
 
9
- VERSION="2.2.2"
9
+ VERSION="2.3.1"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
12
12
 
@@ -139,6 +139,7 @@ optimize_analyze_outcome() {
139
139
  # Build outcome record using jq for proper escaping
140
140
  local tmp_outcome
141
141
  tmp_outcome=$(mktemp)
142
+ trap "rm -f '$tmp_outcome'" RETURN
142
143
  jq -c -n \
143
144
  --arg ts "$(now_iso)" \
144
145
  --arg issue "${issue_number:-unknown}" \
@@ -205,6 +206,100 @@ optimize_analyze_outcome() {
205
206
  success "Outcome recorded for issue #${issue_number:-unknown} (${result:-unknown})"
206
207
  }
207
208
 
209
+ # ═════════════════════════════════════════════════════════════════════════════
210
+ # RETRO INGEST
211
+ # ═════════════════════════════════════════════════════════════════════════════
212
+
213
+ # optimize_ingest_retro
214
+ # Read most recent retro JSON, append summary to outcomes, adjust template weights
215
+ optimize_ingest_retro() {
216
+ local retros_dir="${HOME}/.shipwright/retros"
217
+
218
+ if [[ ! -d "$retros_dir" ]]; then
219
+ return 0
220
+ fi
221
+
222
+ local latest_retro
223
+ latest_retro=$(ls -t "$retros_dir"/retro-*.json 2>/dev/null | head -1)
224
+ [[ -z "$latest_retro" || ! -f "$latest_retro" ]] && return 0
225
+
226
+ if ! command -v jq &>/dev/null; then
227
+ warn "jq required for retro ingest — skipping"
228
+ return 0
229
+ fi
230
+
231
+ ensure_optimization_dir
232
+
233
+ # Extract metrics from retro JSON
234
+ local analysis_json
235
+ analysis_json=$(jq -r '.analysis // {}' "$latest_retro" 2>/dev/null || echo "{}")
236
+ [[ -z "$analysis_json" || "$analysis_json" == "null" ]] && return 0
237
+
238
+ local success_rate avg_duration slowest_stage quality_score retries from_date to_date
239
+ success_rate=$(echo "$analysis_json" | jq -r 'if .pipelines > 0 then ((.succeeded // 0) / .pipelines * 100) | floor else 0 end' 2>/dev/null || echo "0")
240
+ avg_duration=$(echo "$analysis_json" | jq -r '.avg_duration // 0' 2>/dev/null || echo "0")
241
+ slowest_stage=$(echo "$analysis_json" | jq -r '.slowest_stage // ""' 2>/dev/null || echo "")
242
+ quality_score=$(echo "$analysis_json" | jq -r '.quality_score // 0' 2>/dev/null || echo "0")
243
+ retries=$(echo "$analysis_json" | jq -r '.retries // 0' 2>/dev/null || echo "0")
244
+ from_date=$(jq -r '.from_date // ""' "$latest_retro" 2>/dev/null || echo "")
245
+ to_date=$(jq -r '.to_date // ""' "$latest_retro" 2>/dev/null || echo "")
246
+
247
+ # Append retro_summary to outcomes.jsonl
248
+ local retro_record
249
+ retro_record=$(jq -c -n \
250
+ --arg ts "$(now_iso)" \
251
+ --argjson success_rate "${success_rate:-0}" \
252
+ --argjson avg_duration "${avg_duration:-0}" \
253
+ --arg slowest_stage "${slowest_stage:-}" \
254
+ --argjson quality_score "${quality_score:-0}" \
255
+ --argjson retries "${retries:-0}" \
256
+ --arg from_date "${from_date:-}" \
257
+ --arg to_date "${to_date:-}" \
258
+ '{
259
+ ts: $ts,
260
+ type: "retro_summary",
261
+ success_rate: $success_rate,
262
+ avg_duration: $avg_duration,
263
+ slowest_stage: $slowest_stage,
264
+ quality_score: $quality_score,
265
+ retries: $retries,
266
+ from_date: $from_date,
267
+ to_date: $to_date
268
+ }')
269
+ echo "$retro_record" >> "$OUTCOMES_FILE"
270
+
271
+ # Adjust template weights when quality is low — boost templates with stronger performance
272
+ # (success_rate in .weights is avg weight; values > 1.0 indicate above-average success)
273
+ if [[ "${quality_score:-0}" -lt 70 ]] && [[ -f "$TEMPLATE_WEIGHTS_FILE" ]]; then
274
+ info "Quality score low (${quality_score}) — boosting templates with stronger quality gates"
275
+ local tmp_weights
276
+ tmp_weights=$(mktemp "${TEMPLATE_WEIGHTS_FILE}.tmp.XXXXXX")
277
+ trap "rm -f '$tmp_weights'" RETURN
278
+ if jq '
279
+ if .weights then
280
+ .weights |= with_entries(
281
+ if (.value.success_rate >= 1.2) and (.value.raw_weights != null) then
282
+ .value.raw_weights |= with_entries(.value = ((.value * 1.15) | if . > 2.0 then 2.0 else . end))
283
+ else . end
284
+ )
285
+ else . end
286
+ ' "$TEMPLATE_WEIGHTS_FILE" > "$tmp_weights" 2>/dev/null && [[ -s "$tmp_weights" ]]; then
287
+ mv "$tmp_weights" "$TEMPLATE_WEIGHTS_FILE"
288
+ else
289
+ rm -f "$tmp_weights"
290
+ fi
291
+ fi
292
+
293
+ type rotate_jsonl &>/dev/null 2>&1 && rotate_jsonl "$OUTCOMES_FILE" 10000
294
+
295
+ emit_event "optimize.retro_ingested" \
296
+ "success_rate=${success_rate:-0}" \
297
+ "quality_score=${quality_score:-0}" \
298
+ "slowest_stage=${slowest_stage:-}"
299
+
300
+ success "Retro ingested from $(basename "$latest_retro")"
301
+ }
302
+
208
303
  # ═════════════════════════════════════════════════════════════════════════════
209
304
  # TEMPLATE TUNING
210
305
  # ═════════════════════════════════════════════════════════════════════════════
@@ -228,9 +323,12 @@ optimize_tune_templates() {
228
323
  local tmp_stats tmp_weights
229
324
  tmp_stats=$(mktemp)
230
325
  tmp_weights=$(mktemp)
326
+ trap "rm -f '$tmp_stats' '$tmp_weights'" RETURN
231
327
 
232
328
  # Extract template, labels, result from each outcome line
233
329
  while IFS= read -r line; do
330
+ # Skip retro_summary and other non-pipeline outcome lines
331
+ [[ "$(echo "$line" | jq -r '.type // ""' 2>/dev/null)" == "retro_summary" ]] && continue
234
332
  local template result labels_str
235
333
  template=$(echo "$line" | jq -r '.template // "unknown"' 2>/dev/null) || continue
236
334
  result=$(echo "$line" | jq -r '.result // "unknown"' 2>/dev/null) || continue
@@ -334,6 +432,7 @@ optimize_tune_templates() {
334
432
  # Atomic write
335
433
  local tmp_cw
336
434
  tmp_cw=$(mktemp "${TEMPLATE_WEIGHTS_FILE}.tmp.XXXXXX")
435
+ trap "rm -f '$tmp_cw'" RETURN
337
436
  echo "$consumer_weights" > "$tmp_cw" && mv "$tmp_cw" "$TEMPLATE_WEIGHTS_FILE" || rm -f "$tmp_cw"
338
437
  fi
339
438
 
@@ -380,6 +479,7 @@ optimize_learn_iterations() {
380
479
  tmp_med=$(mktemp)
381
480
  tmp_high=$(mktemp)
382
481
  tmp_all_pairs=$(mktemp)
482
+ trap "rm -f '$tmp_low' '$tmp_med' '$tmp_high' '$tmp_all_pairs'" RETURN
383
483
 
384
484
  while IFS= read -r line; do
385
485
  local complexity iterations
@@ -440,6 +540,7 @@ optimize_learn_iterations() {
440
540
  # Write boundaries back to config (atomic)
441
541
  local tmp_clusters
442
542
  tmp_clusters=$(mktemp "${TMPDIR:-/tmp}/sw-clusters.XXXXXX")
543
+ trap "rm -f '$tmp_clusters'" RETURN
443
544
  jq -n \
444
545
  --argjson low_max "$new_low" \
445
546
  --argjson med_max "$new_med" \
@@ -488,6 +589,7 @@ optimize_learn_iterations() {
488
589
  # Build iteration model (flat format for readers: .low, .medium, .high)
489
590
  local tmp_model
490
591
  tmp_model=$(mktemp "${ITERATION_MODEL_FILE}.tmp.XXXXXX")
592
+ trap "rm -f '$tmp_model'" RETURN
491
593
  jq -n \
492
594
  --argjson low "$low_stats" \
493
595
  --argjson medium "$med_stats" \
@@ -568,6 +670,7 @@ _optimize_apply_prediction_bias() {
568
670
  if [[ "$changed" == true ]]; then
569
671
  local tmp_model
570
672
  tmp_model=$(mktemp)
673
+ trap "rm -f '$tmp_model'" RETURN
571
674
  if echo "$updated_model" | jq '.' > "$tmp_model" 2>/dev/null && [[ -s "$tmp_model" ]]; then
572
675
  mv "$tmp_model" "$model_file"
573
676
  emit_event "optimize.prediction_bias_corrected"
@@ -609,6 +712,7 @@ optimize_route_models() {
609
712
  # Collect per-stage, per-model stats
610
713
  local tmp_stage_stats
611
714
  tmp_stage_stats=$(mktemp)
715
+ trap "rm -f '$tmp_stage_stats'" RETURN
612
716
 
613
717
  while IFS= read -r line; do
614
718
  local model result stages_arr
@@ -724,6 +828,7 @@ optimize_route_models() {
724
828
  # Atomic write
725
829
  local tmp_routing
726
830
  tmp_routing=$(mktemp "${MODEL_ROUTING_FILE}.tmp.XXXXXX")
831
+ trap "rm -f '$tmp_routing'" RETURN
727
832
  echo "$consumer_routing" > "$tmp_routing" && mv "$tmp_routing" "$MODEL_ROUTING_FILE" || rm -f "$tmp_routing"
728
833
 
729
834
  rm -f "$tmp_stage_stats" 2>/dev/null || true
@@ -798,6 +903,7 @@ optimize_learn_risk_keywords() {
798
903
  keywords=$(echo "$keywords" | jq 'to_entries | map(select(.value != 0)) | from_entries' 2>/dev/null || echo "$keywords")
799
904
  local tmp_risk
800
905
  tmp_risk=$(mktemp)
906
+ trap "rm -f '$tmp_risk'" RETURN
801
907
  if echo "$keywords" | jq '.' > "$tmp_risk" 2>/dev/null && [[ -s "$tmp_risk" ]]; then
802
908
  mv "$tmp_risk" "$risk_file"
803
909
  success "Risk keywords updated ($(echo "$keywords" | jq 'length' 2>/dev/null || echo '?') keywords)"
@@ -874,6 +980,7 @@ optimize_evolve_memory() {
874
980
 
875
981
  local tmp_file
876
982
  tmp_file=$(mktemp)
983
+ trap "rm -f '$tmp_file'" RETURN
877
984
 
878
985
  # Prune entries not seen within prune window
879
986
  local pruned_json
@@ -911,6 +1018,7 @@ optimize_evolve_memory() {
911
1018
  # Collect all patterns across repos
912
1019
  local tmp_all_patterns
913
1020
  tmp_all_patterns=$(mktemp)
1021
+ trap "rm -f '$tmp_all_patterns'" RETURN
914
1022
  for repo_dir in "$memory_root"/*/; do
915
1023
  [[ -d "$repo_dir" ]] || continue
916
1024
  local failures_file="${repo_dir}failures.json"
@@ -926,6 +1034,7 @@ optimize_evolve_memory() {
926
1034
  if [[ -n "$promoted_patterns" ]]; then
927
1035
  local tmp_global
928
1036
  tmp_global=$(mktemp)
1037
+ trap "rm -f '$tmp_global'" RETURN
929
1038
  local pcount=0
930
1039
  while IFS= read -r pattern; do
931
1040
  [[ -z "$pattern" ]] && continue
@@ -1132,6 +1241,7 @@ optimize_adjust_audit_intensity() {
1132
1241
  info "Quality trend: ${trend} (avg: ${avg_quality}) — increasing audit intensity"
1133
1242
  local tmp_dc
1134
1243
  tmp_dc=$(mktemp "${daemon_config}.tmp.XXXXXX")
1244
+ trap "rm -f '$tmp_dc'" RETURN
1135
1245
  jq '.intelligence.adversarial_enabled = true | .intelligence.architecture_enabled = true' \
1136
1246
  "$daemon_config" > "$tmp_dc" 2>/dev/null && mv "$tmp_dc" "$daemon_config" || rm -f "$tmp_dc"
1137
1247
  emit_event "optimize.audit_intensity" \
@@ -1162,6 +1272,7 @@ show_help() {
1162
1272
  echo " analyze-outcome <state-file> Analyze a completed pipeline outcome"
1163
1273
  echo " tune Run full optimization analysis"
1164
1274
  echo " report Show optimization report (last 7 days)"
1275
+ echo " ingest-retro Ingest most recent retro into optimization loop"
1165
1276
  echo " evolve-memory Prune/strengthen/promote memory patterns"
1166
1277
  echo " help Show this help"
1167
1278
  echo ""
@@ -1183,6 +1294,7 @@ main() {
1183
1294
  case "$cmd" in
1184
1295
  analyze-outcome) optimize_analyze_outcome "$@" ;;
1185
1296
  tune) optimize_full_analysis ;;
1297
+ ingest-retro) optimize_ingest_retro ;;
1186
1298
  report) optimize_report ;;
1187
1299
  evolve-memory) optimize_evolve_memory ;;
1188
1300
  help|--help|-h) show_help ;;
@@ -8,7 +8,7 @@
8
8
  # ║ Supports --template to scaffold from a team template and --terminal ║
9
9
  # ║ to select a terminal adapter (tmux, iterm2, wezterm). ║
10
10
  # ╚═══════════════════════════════════════════════════════════════════════════╝
11
- VERSION="2.2.2"
11
+ VERSION="2.3.1"
12
12
  set -euo pipefail
13
13
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
14
14
 
@@ -10,7 +10,7 @@
10
10
  set -euo pipefail
11
11
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
12
12
 
13
- VERSION="2.2.2"
13
+ VERSION="2.3.1"
14
14
 
15
15
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
16
16
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
@@ -6,7 +6,7 @@
6
6
  set -euo pipefail
7
7
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
8
8
 
9
- VERSION="2.2.2"
9
+ VERSION="2.3.1"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
12
12
 
@@ -503,6 +503,7 @@ cmd_notify() {
503
503
  if [[ -z "$message_file" ]]; then
504
504
  # Generate a digest
505
505
  message_file=$(mktemp)
506
+ trap "rm -f '$message_file'" RETURN
506
507
  cmd_digest > "$message_file" 2>&1 || true
507
508
  fi
508
509
 
@@ -4,7 +4,7 @@
4
4
  # ║ ║
5
5
  # ║ Shows running teams, agent windows, and task progress. ║
6
6
  # ╚═══════════════════════════════════════════════════════════════════════════╝
7
- VERSION="2.2.2"
7
+ VERSION="2.3.1"
8
8
  set -euo pipefail
9
9
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
10
10
 
@@ -7,7 +7,7 @@
7
7
  # When sourced, do NOT add set -euo pipefail — the parent handles that.
8
8
  # When run directly, main() sets up the error handling.
9
9
 
10
- VERSION="2.2.2"
10
+ VERSION="2.3.1"
11
11
 
12
12
  # ─── Paths (set defaults if not provided by parent) ──────────────────────────
13
13
  SCRIPT_DIR="${SCRIPT_DIR:-$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)}"
@@ -423,6 +423,7 @@ strategic_call_api() {
423
423
 
424
424
  local tmp_prompt
425
425
  tmp_prompt=$(mktemp)
426
+ trap "rm -f '$tmp_prompt'" RETURN
426
427
  printf '%s' "$prompt" > "$tmp_prompt"
427
428
 
428
429
  local response_text
@@ -5,7 +5,7 @@
5
5
  # ║ Streams tmux pane output in real-time to the dashboard or CLI. ║
6
6
  # ║ Captures output periodically, tags by agent/team, supports replay. ║
7
7
  # ╚═══════════════════════════════════════════════════════════════════════════╝
8
- VERSION="2.2.2"
8
+ VERSION="2.3.1"
9
9
  set -euo pipefail
10
10
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
11
11
 
@@ -6,7 +6,7 @@
6
6
  set -euo pipefail
7
7
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
8
8
 
9
- VERSION="2.2.2"
9
+ VERSION="2.3.1"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
12
12
 
@@ -60,6 +60,7 @@ init_config() {
60
60
  if [[ ! -f "$CONFIG_FILE" ]]; then
61
61
  local tmp_file
62
62
  tmp_file=$(mktemp)
63
+ trap "rm -f '$tmp_file'" RETURN
63
64
  cat > "$tmp_file" << 'JSON'
64
65
  {
65
66
  "auto_scaling_enabled": false,
@@ -85,6 +86,7 @@ init_registry() {
85
86
  if [[ ! -f "$REGISTRY_FILE" ]]; then
86
87
  local tmp_file
87
88
  tmp_file=$(mktemp)
89
+ trap "rm -f '$tmp_file'" RETURN
88
90
  cat > "$tmp_file" << 'JSON'
89
91
  {
90
92
  "agents": [],
@@ -173,6 +175,7 @@ cmd_spawn() {
173
175
  # Add agent to registry
174
176
  local tmp_file
175
177
  tmp_file=$(mktemp)
178
+ trap "rm -f '$tmp_file'" RETURN
176
179
 
177
180
  jq --arg agent_id "$agent_id" \
178
181
  --arg agent_type "$agent_type" \
@@ -254,6 +257,7 @@ cmd_retire() {
254
257
  # Mark as retiring / remove from registry
255
258
  local tmp_file
256
259
  tmp_file=$(mktemp)
260
+ trap "rm -f '$tmp_file'" RETURN
257
261
 
258
262
  jq --arg aid "$agent_id" \
259
263
  '.agents |= map(select(.id != $aid)) | .active_count = ([.agents[] | select(.status == "active")] | length) | .last_updated = "'$(now_iso)'"' \
@@ -482,6 +486,7 @@ cmd_config() {
482
486
 
483
487
  local tmp_file
484
488
  tmp_file=$(mktemp)
489
+ trap "rm -f '$tmp_file'" RETURN
485
490
 
486
491
  jq --arg key "$key" --arg value "$value" \
487
492
  'if ($value | test("^[0-9]+$")) then
@@ -6,7 +6,7 @@
6
6
  set -euo pipefail
7
7
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
8
8
 
9
- VERSION="2.2.2"
9
+ VERSION="2.3.1"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
12
12
 
@@ -5,7 +5,7 @@
5
5
  # ║ Templates define reusable agent team configurations (roles, layout, ║
6
6
  # ║ focus areas) that shipwright session --template can use to scaffold teams. ║
7
7
  # ╚═══════════════════════════════════════════════════════════════════════════╝
8
- VERSION="2.2.2"
8
+ VERSION="2.3.1"
9
9
  set -euo pipefail
10
10
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
11
11
 
@@ -6,7 +6,7 @@
6
6
  set -euo pipefail
7
7
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
8
8
 
9
- VERSION="2.2.2"
9
+ VERSION="2.3.1"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
 
12
12
  # ─── Handle subcommands ───────────────────────────────────────────────────────
@@ -87,7 +87,7 @@ show_help() {
87
87
  echo -e " ${DIM}shipwright testgen generate --threshold 75${RESET} # Generate with threshold"
88
88
  echo -e " ${DIM}shipwright testgen quality sw-pipeline-test.sh${RESET} # Score test quality"
89
89
  echo ""
90
- echo -e "${DIM}Docs: https://sethdford.github.io/shipwright${RESET}"
90
+ echo -e "${DIM}Docs: $(_sw_docs_url)${RESET}"
91
91
  }
92
92
 
93
93
  # ═══════════════════════════════════════════════════════════════════════════════
@@ -241,6 +241,7 @@ EOF
241
241
  func_snippet=$(awk "/^${func}\(\\)/,/^[a-zA-Z_][a-zA-Z0-9_]*\(\)|^$/" "$target_script" 2>/dev/null | head -40 || true)
242
242
  local prompt_file
243
243
  prompt_file=$(mktemp "${TMPDIR:-/tmp}/sw-testgen-prompt.XXXXXX")
244
+ trap "rm -f '$prompt_file'" RETURN
244
245
  {
245
246
  echo "Generate a bash test function for the following shell function. Use real assertions (assert_equal, assert_contains, or test exit code). Test happy path and at least one edge or error case. Output only the bash function body."
246
247
  echo "Function name: ${func}"
@@ -6,7 +6,7 @@
6
6
  set -euo pipefail
7
7
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
8
8
 
9
- VERSION="2.2.2"
9
+ VERSION="2.3.1"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
12
12
 
@@ -118,6 +118,7 @@ cmd_spawn() {
118
118
 
119
119
  local tmp_file
120
120
  tmp_file=$(mktemp)
121
+ trap "rm -f '$tmp_file'" RETURN
121
122
  cat > "$tmp_file" << EOF
122
123
  {
123
124
  "job_id": "pipeline-${issue_num}",
@@ -11,7 +11,7 @@
11
11
  # ║ shipwright tmux fix — Auto-fix common issues ║
12
12
  # ║ shipwright tmux reload — Reload tmux config ║
13
13
  # ╚═══════════════════════════════════════════════════════════════════════════╝
14
- VERSION="2.2.2"
14
+ VERSION="2.3.1"
15
15
  set -euo pipefail
16
16
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
17
17
 
@@ -6,7 +6,7 @@
6
6
  set -euo pipefail
7
7
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
8
8
 
9
- VERSION="2.2.2"
9
+ VERSION="2.3.1"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
12
12
 
@@ -105,6 +105,7 @@ provider_discover_statuses() {
105
105
  mkdir -p "$cache_dir"
106
106
  local tmp_cache
107
107
  tmp_cache=$(mktemp)
108
+ trap "rm -f '$tmp_cache'" RETURN
108
109
  jq -n \
109
110
  --arg ts "$(date +%s)" \
110
111
  --arg in_progress "${discovered_in_progress:-}" \
@@ -115,6 +115,7 @@ provider_discover_statuses() {
115
115
  mkdir -p "$cache_dir"
116
116
  local tmp_cache
117
117
  tmp_cache=$(mktemp)
118
+ trap "rm -f '$tmp_cache'" RETURN
118
119
  jq -n \
119
120
  --arg ts "$(date +%s)" \
120
121
  --arg backlog "${discovered_backlog:-}" \
@@ -6,7 +6,7 @@
6
6
  set -euo pipefail
7
7
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
8
8
 
9
- VERSION="2.2.2"
9
+ VERSION="2.3.1"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
12
12