shipwright-cli 2.2.1 → 2.3.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 (156) hide show
  1. package/README.md +19 -19
  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.ts +381 -0
  18. package/dashboard/src/core/helpers.ts +118 -0
  19. package/dashboard/src/core/router.ts +190 -0
  20. package/dashboard/src/core/sse.ts +38 -0
  21. package/dashboard/src/core/state.ts +150 -0
  22. package/dashboard/src/core/ws.ts +143 -0
  23. package/dashboard/src/design/icons.ts +131 -0
  24. package/dashboard/src/design/tokens.ts +160 -0
  25. package/dashboard/src/main.ts +68 -0
  26. package/dashboard/src/types/api.ts +337 -0
  27. package/dashboard/src/views/activity.ts +185 -0
  28. package/dashboard/src/views/agent-cockpit.ts +236 -0
  29. package/dashboard/src/views/agents.ts +72 -0
  30. package/dashboard/src/views/fleet-map.ts +299 -0
  31. package/dashboard/src/views/insights.ts +298 -0
  32. package/dashboard/src/views/machines.ts +162 -0
  33. package/dashboard/src/views/metrics.ts +420 -0
  34. package/dashboard/src/views/overview.ts +409 -0
  35. package/dashboard/src/views/pipeline-theater.ts +219 -0
  36. package/dashboard/src/views/pipelines.ts +595 -0
  37. package/dashboard/src/views/team.ts +362 -0
  38. package/dashboard/src/views/timeline.ts +389 -0
  39. package/dashboard/tsconfig.json +21 -0
  40. package/docs/AGI-PLATFORM-PLAN.md +5 -5
  41. package/docs/AGI-WHATS-NEXT.md +19 -16
  42. package/docs/README.md +2 -0
  43. package/package.json +8 -1
  44. package/scripts/check-version-consistency.sh +72 -0
  45. package/scripts/lib/daemon-adaptive.sh +610 -0
  46. package/scripts/lib/daemon-dispatch.sh +489 -0
  47. package/scripts/lib/daemon-failure.sh +387 -0
  48. package/scripts/lib/daemon-patrol.sh +1113 -0
  49. package/scripts/lib/daemon-poll.sh +1202 -0
  50. package/scripts/lib/daemon-state.sh +550 -0
  51. package/scripts/lib/daemon-triage.sh +490 -0
  52. package/scripts/lib/helpers.sh +81 -0
  53. package/scripts/lib/pipeline-intelligence.sh +0 -6
  54. package/scripts/lib/pipeline-quality-checks.sh +3 -1
  55. package/scripts/lib/pipeline-stages.sh +20 -0
  56. package/scripts/sw +109 -168
  57. package/scripts/sw-activity.sh +1 -1
  58. package/scripts/sw-adaptive.sh +2 -2
  59. package/scripts/sw-adversarial.sh +1 -1
  60. package/scripts/sw-architecture-enforcer.sh +1 -1
  61. package/scripts/sw-auth.sh +14 -6
  62. package/scripts/sw-autonomous.sh +1 -1
  63. package/scripts/sw-changelog.sh +2 -2
  64. package/scripts/sw-checkpoint.sh +1 -1
  65. package/scripts/sw-ci.sh +1 -1
  66. package/scripts/sw-cleanup.sh +1 -1
  67. package/scripts/sw-code-review.sh +1 -1
  68. package/scripts/sw-connect.sh +1 -1
  69. package/scripts/sw-context.sh +1 -1
  70. package/scripts/sw-cost.sh +1 -1
  71. package/scripts/sw-daemon.sh +53 -4817
  72. package/scripts/sw-dashboard.sh +1 -1
  73. package/scripts/sw-db.sh +1 -1
  74. package/scripts/sw-decompose.sh +1 -1
  75. package/scripts/sw-deps.sh +1 -1
  76. package/scripts/sw-developer-simulation.sh +1 -1
  77. package/scripts/sw-discovery.sh +1 -1
  78. package/scripts/sw-doc-fleet.sh +1 -1
  79. package/scripts/sw-docs-agent.sh +1 -1
  80. package/scripts/sw-docs.sh +1 -1
  81. package/scripts/sw-doctor.sh +49 -1
  82. package/scripts/sw-dora.sh +1 -1
  83. package/scripts/sw-durable.sh +1 -1
  84. package/scripts/sw-e2e-orchestrator.sh +1 -1
  85. package/scripts/sw-eventbus.sh +1 -1
  86. package/scripts/sw-feedback.sh +1 -1
  87. package/scripts/sw-fix.sh +6 -5
  88. package/scripts/sw-fleet-discover.sh +1 -1
  89. package/scripts/sw-fleet-viz.sh +3 -3
  90. package/scripts/sw-fleet.sh +1 -1
  91. package/scripts/sw-github-app.sh +5 -2
  92. package/scripts/sw-github-checks.sh +1 -1
  93. package/scripts/sw-github-deploy.sh +1 -1
  94. package/scripts/sw-github-graphql.sh +1 -1
  95. package/scripts/sw-guild.sh +1 -1
  96. package/scripts/sw-heartbeat.sh +1 -1
  97. package/scripts/sw-hygiene.sh +1 -1
  98. package/scripts/sw-incident.sh +1 -1
  99. package/scripts/sw-init.sh +112 -9
  100. package/scripts/sw-instrument.sh +6 -1
  101. package/scripts/sw-intelligence.sh +5 -1
  102. package/scripts/sw-jira.sh +1 -1
  103. package/scripts/sw-launchd.sh +1 -1
  104. package/scripts/sw-linear.sh +20 -9
  105. package/scripts/sw-logs.sh +1 -1
  106. package/scripts/sw-loop.sh +2 -1
  107. package/scripts/sw-memory.sh +10 -1
  108. package/scripts/sw-mission-control.sh +1 -1
  109. package/scripts/sw-model-router.sh +4 -1
  110. package/scripts/sw-otel.sh +4 -4
  111. package/scripts/sw-oversight.sh +1 -1
  112. package/scripts/sw-pipeline-composer.sh +3 -1
  113. package/scripts/sw-pipeline-vitals.sh +4 -6
  114. package/scripts/sw-pipeline.sh +19 -56
  115. package/scripts/sw-pipeline.sh.mock +7 -0
  116. package/scripts/sw-pm.sh +5 -2
  117. package/scripts/sw-pr-lifecycle.sh +1 -1
  118. package/scripts/sw-predictive.sh +4 -1
  119. package/scripts/sw-prep.sh +3 -2
  120. package/scripts/sw-ps.sh +1 -1
  121. package/scripts/sw-public-dashboard.sh +10 -4
  122. package/scripts/sw-quality.sh +1 -1
  123. package/scripts/sw-reaper.sh +1 -1
  124. package/scripts/sw-recruit.sh +25 -1
  125. package/scripts/sw-regression.sh +2 -1
  126. package/scripts/sw-release-manager.sh +1 -1
  127. package/scripts/sw-release.sh +7 -5
  128. package/scripts/sw-remote.sh +1 -1
  129. package/scripts/sw-replay.sh +1 -1
  130. package/scripts/sw-retro.sh +1 -1
  131. package/scripts/sw-scale.sh +11 -5
  132. package/scripts/sw-security-audit.sh +1 -1
  133. package/scripts/sw-self-optimize.sh +172 -7
  134. package/scripts/sw-session.sh +1 -1
  135. package/scripts/sw-setup.sh +1 -1
  136. package/scripts/sw-standup.sh +4 -3
  137. package/scripts/sw-status.sh +1 -1
  138. package/scripts/sw-strategic.sh +2 -1
  139. package/scripts/sw-stream.sh +8 -2
  140. package/scripts/sw-swarm.sh +12 -10
  141. package/scripts/sw-team-stages.sh +1 -1
  142. package/scripts/sw-templates.sh +1 -1
  143. package/scripts/sw-testgen.sh +3 -2
  144. package/scripts/sw-tmux-pipeline.sh +2 -1
  145. package/scripts/sw-tmux.sh +1 -1
  146. package/scripts/sw-trace.sh +1 -1
  147. package/scripts/sw-tracker-jira.sh +1 -0
  148. package/scripts/sw-tracker-linear.sh +1 -0
  149. package/scripts/sw-tracker.sh +24 -6
  150. package/scripts/sw-triage.sh +1 -1
  151. package/scripts/sw-upgrade.sh +1 -1
  152. package/scripts/sw-ux.sh +1 -1
  153. package/scripts/sw-webhook.sh +1 -1
  154. package/scripts/sw-widgets.sh +2 -2
  155. package/scripts/sw-worktree.sh +1 -1
  156. 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.1"
9
+ VERSION="2.3.0"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
12
12
 
@@ -302,14 +302,14 @@ cmd_velocity() {
302
302
  if [[ "$ts_epoch" -ge "$cutoff" ]]; then
303
303
  local event_type
304
304
  event_type=$(echo "$line" | jq -r '.type // ""' 2>/dev/null || true)
305
- if [[ "$event_type" == "pipeline_completed" ]]; then
305
+ if [[ "$event_type" == "pipeline.completed" || "$event_type" == "pipeline_completed" ]]; then
306
306
  completed_24h=$((completed_24h + 1))
307
307
  fi
308
308
  fi
309
309
 
310
310
  local event_type
311
311
  event_type=$(echo "$line" | jq -r '.type // ""' 2>/dev/null || true)
312
- if [[ "$event_type" == "pipeline_completed" ]]; then
312
+ if [[ "$event_type" == "pipeline.completed" || "$event_type" == "pipeline_completed" ]]; then
313
313
  total_completed=$((total_completed + 1))
314
314
  fi
315
315
  done < "$EVENTS_FILE"
@@ -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.1"
7
+ VERSION="2.3.0"
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.1"
10
+ VERSION="2.3.0"
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.1"
8
+ VERSION="2.3.0"
9
9
  set -euo pipefail
10
10
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
11
11
 
@@ -374,7 +374,13 @@ stream_config() {
374
374
  ;;
375
375
  esac
376
376
 
377
- mv "$tmp_file" "$STREAM_CONFIG"
377
+ if [[ -s "$tmp_file" ]]; then
378
+ mv "$tmp_file" "$STREAM_CONFIG"
379
+ else
380
+ rm -f "$tmp_file"
381
+ error "Failed to update stream config"
382
+ return 1
383
+ fi
378
384
  success "Config updated: $key = $value"
379
385
  emit_event "stream.config_updated" "key=$key" "value=$value"
380
386
  }
@@ -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.1"
9
+ VERSION="2.3.0"
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" \
@@ -190,9 +193,8 @@ cmd_spawn() {
190
193
  resource_usage: {cpu: 0, memory: 0},
191
194
  last_heartbeat: "'$(now_iso)'"
192
195
  }] | .active_count += 1 | .last_updated = "'$(now_iso)'"' \
193
- "$REGISTRY_FILE" > "$tmp_file"
194
-
195
- mv "$tmp_file" "$REGISTRY_FILE"
196
+ "$REGISTRY_FILE" > "$tmp_file" && [[ -s "$tmp_file" ]] && \
197
+ mv "$tmp_file" "$REGISTRY_FILE" || { rm -f "$tmp_file"; error "Failed to update registry"; return 1; }
196
198
  record_metric "$agent_id" "spawn" "1" "$agent_type"
197
199
 
198
200
  # Create real tmux session for the agent (so scale/loop can send commands)
@@ -255,12 +257,12 @@ cmd_retire() {
255
257
  # Mark as retiring / remove from registry
256
258
  local tmp_file
257
259
  tmp_file=$(mktemp)
260
+ trap "rm -f '$tmp_file'" RETURN
258
261
 
259
262
  jq --arg aid "$agent_id" \
260
263
  '.agents |= map(select(.id != $aid)) | .active_count = ([.agents[] | select(.status == "active")] | length) | .last_updated = "'$(now_iso)'"' \
261
- "$REGISTRY_FILE" > "$tmp_file"
262
-
263
- mv "$tmp_file" "$REGISTRY_FILE"
264
+ "$REGISTRY_FILE" > "$tmp_file" && [[ -s "$tmp_file" ]] && \
265
+ mv "$tmp_file" "$REGISTRY_FILE" || { rm -f "$tmp_file"; error "Failed to update registry"; return 1; }
264
266
  record_metric "$agent_id" "retire" "1" "graceful_shutdown"
265
267
 
266
268
  success "Retired agent: ${CYAN}${agent_id}${RESET}"
@@ -484,6 +486,7 @@ cmd_config() {
484
486
 
485
487
  local tmp_file
486
488
  tmp_file=$(mktemp)
489
+ trap "rm -f '$tmp_file'" RETURN
487
490
 
488
491
  jq --arg key "$key" --arg value "$value" \
489
492
  'if ($value | test("^[0-9]+$")) then
@@ -492,9 +495,8 @@ cmd_config() {
492
495
  .[$key] = ($value | fromjson)
493
496
  else
494
497
  .[$key] = $value
495
- end' "$CONFIG_FILE" > "$tmp_file"
496
-
497
- mv "$tmp_file" "$CONFIG_FILE"
498
+ end' "$CONFIG_FILE" > "$tmp_file" && [[ -s "$tmp_file" ]] && \
499
+ mv "$tmp_file" "$CONFIG_FILE" || { rm -f "$tmp_file"; error "Failed to update config"; return 1; }
498
500
  success "Updated: ${key} = ${value}"
499
501
  ;;
500
502
  reset)
@@ -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.1"
9
+ VERSION="2.3.0"
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.1"
8
+ VERSION="2.3.0"
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.1"
9
+ VERSION="2.3.0"
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.1"
9
+ VERSION="2.3.0"
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.1"
14
+ VERSION="2.3.0"
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.1"
9
+ VERSION="2.3.0"
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.1"
9
+ VERSION="2.3.0"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
12
12
 
@@ -260,7 +260,13 @@ cmd_init() {
260
260
  local tmp_config="${TRACKER_CONFIG}.tmp"
261
261
  jq -n --arg provider "none" --arg updated "$(now_iso)" \
262
262
  '{provider: $provider, updated_at: $updated}' > "$tmp_config"
263
- mv "$tmp_config" "$TRACKER_CONFIG"
263
+ if [[ -s "$tmp_config" ]]; then
264
+ mv "$tmp_config" "$TRACKER_CONFIG"
265
+ else
266
+ rm -f "$tmp_config"
267
+ error "Failed to write tracker config"
268
+ return 1
269
+ fi
264
270
  success "Tracker disabled"
265
271
  return 0
266
272
  fi
@@ -307,8 +313,14 @@ _init_linear() {
307
313
  },
308
314
  updated_at: $updated
309
315
  }' > "$tmp_config"
310
- mv "$tmp_config" "$TRACKER_CONFIG"
311
- chmod 600 "$TRACKER_CONFIG"
316
+ if [[ -s "$tmp_config" ]]; then
317
+ mv "$tmp_config" "$TRACKER_CONFIG"
318
+ chmod 600 "$TRACKER_CONFIG"
319
+ else
320
+ rm -f "$tmp_config"
321
+ error "Failed to write tracker config"
322
+ return 1
323
+ fi
312
324
 
313
325
  success "Linear tracker configured"
314
326
  echo ""
@@ -376,8 +388,14 @@ _init_jira() {
376
388
  },
377
389
  updated_at: $updated
378
390
  }' > "$tmp_config"
379
- mv "$tmp_config" "$TRACKER_CONFIG"
380
- chmod 600 "$TRACKER_CONFIG"
391
+ if [[ -s "$tmp_config" ]]; then
392
+ mv "$tmp_config" "$TRACKER_CONFIG"
393
+ chmod 600 "$TRACKER_CONFIG"
394
+ else
395
+ rm -f "$tmp_config"
396
+ error "Failed to write tracker config"
397
+ return 1
398
+ fi
381
399
 
382
400
  success "Jira tracker configured"
383
401
  echo ""
@@ -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.1"
9
+ VERSION="2.3.0"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
12
12
 
@@ -2,7 +2,7 @@
2
2
  # ╔═══════════════════════════════════════════════════════════════════════════╗
3
3
  # ║ sw upgrade — Detect and apply updates from the repo ║
4
4
  # ╚═══════════════════════════════════════════════════════════════════════════╝
5
- VERSION="2.2.1"
5
+ VERSION="2.3.0"
6
6
  set -euo pipefail
7
7
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
8
8
 
package/scripts/sw-ux.sh CHANGED
@@ -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.1"
9
+ VERSION="2.3.0"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
 
12
12
  # ─── Cross-platform compatibility ──────────────────────────────────────────
@@ -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.1"
9
+ VERSION="2.3.0"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
 
12
12
  # ─── Cross-platform compatibility ──────────────────────────────────────────
@@ -8,7 +8,7 @@
8
8
  set -euo pipefail
9
9
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
10
10
 
11
- VERSION="2.2.1"
11
+ VERSION="2.3.0"
12
12
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
13
13
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
14
14
 
@@ -357,7 +357,7 @@ To add these badges to your README.md:
357
357
  \`\`\`
358
358
 
359
359
  ---
360
- Generated by [Shipwright](https://github.com/sethdford/shipwright)
360
+ Generated by [Shipwright]($(_sw_github_url))
361
361
  EOF
362
362
  }
363
363
 
@@ -5,7 +5,7 @@
5
5
  # ║ Each agent gets its own worktree so parallel agents don't clobber ║
6
6
  # ║ each other's files. Worktrees live in .worktrees/ relative to root. ║
7
7
  # ╚═══════════════════════════════════════════════════════════════════════════╝
8
- VERSION="2.2.1"
8
+ VERSION="2.3.0"
9
9
  set -euo pipefail
10
10
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
11
11