shipwright-cli 3.0.0 → 3.2.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 (143) hide show
  1. package/README.md +21 -7
  2. package/completions/_shipwright +247 -93
  3. package/completions/shipwright.bash +69 -15
  4. package/completions/shipwright.fish +309 -41
  5. package/config/decision-tiers.json +55 -0
  6. package/config/defaults.json +25 -2
  7. package/config/event-schema.json +142 -5
  8. package/config/policy.json +8 -0
  9. package/dashboard/public/index.html +6 -0
  10. package/dashboard/public/styles.css +76 -0
  11. package/dashboard/server.ts +51 -0
  12. package/dashboard/src/core/api.ts +5 -0
  13. package/dashboard/src/types/api.ts +10 -0
  14. package/dashboard/src/views/metrics.ts +69 -1
  15. package/package.json +3 -3
  16. package/scripts/lib/architecture.sh +2 -1
  17. package/scripts/lib/bootstrap.sh +0 -0
  18. package/scripts/lib/config.sh +0 -0
  19. package/scripts/lib/daemon-adaptive.sh +4 -2
  20. package/scripts/lib/daemon-dispatch.sh +24 -1
  21. package/scripts/lib/daemon-failure.sh +0 -0
  22. package/scripts/lib/daemon-health.sh +0 -0
  23. package/scripts/lib/daemon-patrol.sh +42 -7
  24. package/scripts/lib/daemon-poll.sh +17 -0
  25. package/scripts/lib/daemon-state.sh +17 -0
  26. package/scripts/lib/daemon-triage.sh +1 -1
  27. package/scripts/lib/decide-autonomy.sh +295 -0
  28. package/scripts/lib/decide-scoring.sh +228 -0
  29. package/scripts/lib/decide-signals.sh +462 -0
  30. package/scripts/lib/fleet-failover.sh +0 -0
  31. package/scripts/lib/helpers.sh +19 -18
  32. package/scripts/lib/pipeline-detection.sh +1 -1
  33. package/scripts/lib/pipeline-github.sh +0 -0
  34. package/scripts/lib/pipeline-intelligence.sh +23 -4
  35. package/scripts/lib/pipeline-quality-checks.sh +11 -6
  36. package/scripts/lib/pipeline-quality.sh +0 -0
  37. package/scripts/lib/pipeline-stages.sh +330 -33
  38. package/scripts/lib/pipeline-state.sh +14 -0
  39. package/scripts/lib/policy.sh +0 -0
  40. package/scripts/lib/test-helpers.sh +0 -0
  41. package/scripts/postinstall.mjs +75 -1
  42. package/scripts/signals/example-collector.sh +36 -0
  43. package/scripts/sw +8 -4
  44. package/scripts/sw-activity.sh +1 -7
  45. package/scripts/sw-adaptive.sh +7 -7
  46. package/scripts/sw-adversarial.sh +1 -1
  47. package/scripts/sw-architecture-enforcer.sh +1 -1
  48. package/scripts/sw-auth.sh +1 -1
  49. package/scripts/sw-autonomous.sh +1 -1
  50. package/scripts/sw-changelog.sh +1 -1
  51. package/scripts/sw-checkpoint.sh +1 -1
  52. package/scripts/sw-ci.sh +11 -6
  53. package/scripts/sw-cleanup.sh +1 -1
  54. package/scripts/sw-code-review.sh +36 -17
  55. package/scripts/sw-connect.sh +1 -1
  56. package/scripts/sw-context.sh +1 -1
  57. package/scripts/sw-cost.sh +71 -5
  58. package/scripts/sw-daemon.sh +6 -3
  59. package/scripts/sw-dashboard.sh +1 -1
  60. package/scripts/sw-db.sh +53 -38
  61. package/scripts/sw-decide.sh +685 -0
  62. package/scripts/sw-decompose.sh +1 -1
  63. package/scripts/sw-deps.sh +1 -1
  64. package/scripts/sw-developer-simulation.sh +1 -1
  65. package/scripts/sw-discovery.sh +80 -4
  66. package/scripts/sw-doc-fleet.sh +1 -1
  67. package/scripts/sw-docs-agent.sh +1 -1
  68. package/scripts/sw-docs.sh +1 -1
  69. package/scripts/sw-doctor.sh +1 -1
  70. package/scripts/sw-dora.sh +1 -1
  71. package/scripts/sw-durable.sh +9 -5
  72. package/scripts/sw-e2e-orchestrator.sh +1 -1
  73. package/scripts/sw-eventbus.sh +7 -4
  74. package/scripts/sw-evidence.sh +1 -1
  75. package/scripts/sw-feedback.sh +1 -1
  76. package/scripts/sw-fix.sh +1 -1
  77. package/scripts/sw-fleet-discover.sh +1 -1
  78. package/scripts/sw-fleet-viz.sh +6 -4
  79. package/scripts/sw-fleet.sh +1 -1
  80. package/scripts/sw-github-app.sh +3 -2
  81. package/scripts/sw-github-checks.sh +1 -1
  82. package/scripts/sw-github-deploy.sh +1 -1
  83. package/scripts/sw-github-graphql.sh +1 -1
  84. package/scripts/sw-guild.sh +1 -1
  85. package/scripts/sw-heartbeat.sh +1 -1
  86. package/scripts/sw-hygiene.sh +5 -3
  87. package/scripts/sw-incident.sh +9 -5
  88. package/scripts/sw-init.sh +1 -1
  89. package/scripts/sw-instrument.sh +1 -1
  90. package/scripts/sw-intelligence.sh +11 -6
  91. package/scripts/sw-jira.sh +1 -1
  92. package/scripts/sw-launchd.sh +1 -1
  93. package/scripts/sw-linear.sh +1 -1
  94. package/scripts/sw-logs.sh +1 -1
  95. package/scripts/sw-loop.sh +338 -32
  96. package/scripts/sw-memory.sh +23 -6
  97. package/scripts/sw-mission-control.sh +1 -1
  98. package/scripts/sw-model-router.sh +3 -2
  99. package/scripts/sw-otel.sh +8 -4
  100. package/scripts/sw-oversight.sh +1 -1
  101. package/scripts/sw-pipeline-composer.sh +3 -1
  102. package/scripts/sw-pipeline-vitals.sh +11 -6
  103. package/scripts/sw-pipeline.sh +92 -8
  104. package/scripts/sw-pm.sh +5 -4
  105. package/scripts/sw-pr-lifecycle.sh +7 -4
  106. package/scripts/sw-predictive.sh +11 -5
  107. package/scripts/sw-prep.sh +1 -1
  108. package/scripts/sw-ps.sh +1 -1
  109. package/scripts/sw-public-dashboard.sh +3 -2
  110. package/scripts/sw-quality.sh +21 -10
  111. package/scripts/sw-reaper.sh +1 -1
  112. package/scripts/sw-recruit.sh +1 -1
  113. package/scripts/sw-regression.sh +1 -1
  114. package/scripts/sw-release-manager.sh +1 -1
  115. package/scripts/sw-release.sh +1 -1
  116. package/scripts/sw-remote.sh +1 -1
  117. package/scripts/sw-replay.sh +1 -1
  118. package/scripts/sw-retro.sh +1 -1
  119. package/scripts/sw-review-rerun.sh +1 -1
  120. package/scripts/sw-scale.sh +69 -11
  121. package/scripts/sw-security-audit.sh +1 -1
  122. package/scripts/sw-self-optimize.sh +168 -4
  123. package/scripts/sw-session.sh +3 -3
  124. package/scripts/sw-setup.sh +1 -1
  125. package/scripts/sw-standup.sh +1 -1
  126. package/scripts/sw-status.sh +1 -1
  127. package/scripts/sw-strategic.sh +11 -6
  128. package/scripts/sw-stream.sh +7 -4
  129. package/scripts/sw-swarm.sh +3 -2
  130. package/scripts/sw-team-stages.sh +1 -1
  131. package/scripts/sw-templates.sh +3 -3
  132. package/scripts/sw-testgen.sh +11 -6
  133. package/scripts/sw-tmux-pipeline.sh +1 -1
  134. package/scripts/sw-tmux.sh +35 -1
  135. package/scripts/sw-trace.sh +1 -1
  136. package/scripts/sw-tracker.sh +1 -1
  137. package/scripts/sw-triage.sh +7 -7
  138. package/scripts/sw-upgrade.sh +1 -1
  139. package/scripts/sw-ux.sh +1 -1
  140. package/scripts/sw-webhook.sh +3 -2
  141. package/scripts/sw-widgets.sh +7 -4
  142. package/scripts/sw-worktree.sh +1 -1
  143. package/scripts/update-homebrew-sha.sh +21 -15
@@ -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="3.0.0"
9
+ VERSION="3.2.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="3.0.0"
9
+ VERSION="3.2.0"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
12
12
 
@@ -7,7 +7,7 @@
7
7
  set -euo pipefail
8
8
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
9
9
 
10
- VERSION="3.0.0"
10
+ VERSION="3.2.0"
11
11
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
12
12
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
13
13
 
@@ -46,6 +46,13 @@ DISCOVERIES_FILE="${HOME}/.shipwright/discoveries.jsonl"
46
46
  DISCOVERIES_DIR="${HOME}/.shipwright/discoveries"
47
47
  DISCOVERY_TTL_SECS=$((24 * 60 * 60)) # 24 hours default
48
48
 
49
+ # ─── Remote Discovery Server (optional) ─────────────────────────────────────
50
+ # Set via env var or daemon-config.json: "discovery_server_url"
51
+ DISCOVERY_SERVER_URL="${DISCOVERY_SERVER_URL:-}"
52
+ if [[ -z "$DISCOVERY_SERVER_URL" && -f ".claude/daemon-config.json" ]]; then
53
+ DISCOVERY_SERVER_URL=$(jq -r '.discovery_server_url // ""' ".claude/daemon-config.json" 2>/dev/null || true)
54
+ fi
55
+
49
56
  ensure_discoveries_dir() {
50
57
  mkdir -p "$DISCOVERIES_DIR"
51
58
  }
@@ -82,6 +89,15 @@ broadcast_discovery() {
82
89
 
83
90
  echo "$entry" >> "$DISCOVERIES_FILE"
84
91
  type rotate_jsonl >/dev/null 2>&1 && rotate_jsonl "$DISCOVERIES_FILE" 5000
92
+
93
+ # Fire-and-forget POST to remote discovery server if configured
94
+ if [[ -n "${DISCOVERY_SERVER_URL:-}" ]]; then
95
+ curl -sS -X POST "${DISCOVERY_SERVER_URL}/api/discoveries" \
96
+ -H "Content-Type: application/json" \
97
+ -d "$entry" \
98
+ --max-time 5 >/dev/null 2>&1 &
99
+ fi
100
+
85
101
  success "Broadcast discovery: ${category} (${file_patterns})"
86
102
  }
87
103
 
@@ -93,6 +109,16 @@ query_discoveries() {
93
109
 
94
110
  ensure_discoveries_dir
95
111
 
112
+ # Merge remote discoveries if server configured (best-effort)
113
+ if [[ -n "${DISCOVERY_SERVER_URL:-}" ]]; then
114
+ local remote_results
115
+ remote_results=$(curl -sS "${DISCOVERY_SERVER_URL}/api/discoveries?patterns=${file_patterns}" \
116
+ --max-time 5 2>/dev/null || true)
117
+ if [[ -n "$remote_results" ]] && echo "$remote_results" | jq -e '.' >/dev/null 2>&1; then
118
+ echo "$remote_results" | jq -cr '.[]' >> "$DISCOVERIES_FILE" 2>/dev/null || true
119
+ fi
120
+ fi
121
+
96
122
  [[ ! -f "$DISCOVERIES_FILE" ]] && {
97
123
  info "No discoveries yet"
98
124
  return 0
@@ -130,10 +156,60 @@ query_discoveries() {
130
156
  fi
131
157
  done < "$DISCOVERIES_FILE"
132
158
 
133
- # Optionally use Claude to rank when many candidates
159
+ # Use Claude to rank candidates by relevance when there are many
134
160
  if [[ "${INTELLIGENCE_ENABLED:-auto}" != "false" ]] && command -v claude &>/dev/null 2>&1 && [[ ${#candidates[@]} -gt 5 ]]; then
135
- # TODO: batch Claude call to rank by relevance (future enhancement)
136
- :
161
+ local ranked_json=""
162
+ local candidate_summaries=""
163
+ local idx=0
164
+ for line in "${candidates[@]+"${candidates[@]}"}"; do
165
+ local disc cat_name
166
+ disc=$(echo "$line" | jq -r '.discovery // ""' 2>/dev/null || echo "")
167
+ cat_name=$(echo "$line" | jq -r '.category // ""' 2>/dev/null || echo "")
168
+ candidate_summaries="${candidate_summaries}${idx}: [${cat_name}] ${disc}"$'\n'
169
+ idx=$((idx + 1))
170
+ done
171
+
172
+ local rank_prompt
173
+ rank_prompt="Given these discoveries and the query context '${query_context}', return a JSON array of indices sorted by relevance (most relevant first). Only return the JSON array, no explanation.
174
+
175
+ Discoveries:
176
+ ${candidate_summaries}"
177
+
178
+ local _claude_timeout
179
+ _claude_timeout=30
180
+ local _timeout_cmd=""
181
+ if command -v gtimeout >/dev/null 2>&1; then _timeout_cmd="gtimeout $_claude_timeout"
182
+ elif command -v timeout >/dev/null 2>&1; then _timeout_cmd="timeout $_claude_timeout"
183
+ fi
184
+
185
+ ranked_json=$($_timeout_cmd claude -p "$rank_prompt" 2>/dev/null || true)
186
+
187
+ # Extract array from response (handle markdown fences)
188
+ local indices_str=""
189
+ if [[ -n "$ranked_json" ]]; then
190
+ indices_str=$(echo "$ranked_json" | sed -n 's/.*\(\[[ 0-9,]*\]\).*/\1/p' | head -1)
191
+ fi
192
+
193
+ if [[ -n "$indices_str" ]] && echo "$indices_str" | jq -e 'type == "array"' >/dev/null 2>&1; then
194
+ local reordered=()
195
+ local seen=""
196
+ while IFS= read -r rank_idx; do
197
+ [[ -z "$rank_idx" ]] && continue
198
+ if [[ "$rank_idx" -ge 0 && "$rank_idx" -lt "${#candidates[@]}" ]]; then
199
+ # Avoid duplicates
200
+ case " $seen " in *" $rank_idx "*) continue ;; esac
201
+ seen="$seen $rank_idx"
202
+ reordered+=("${candidates[$rank_idx]}")
203
+ fi
204
+ done < <(echo "$indices_str" | jq -r '.[]' 2>/dev/null)
205
+ # Append any candidates not in the ranking
206
+ idx=0
207
+ for line in "${candidates[@]+"${candidates[@]}"}"; do
208
+ case " $seen " in *" $idx "*) ;; *) reordered+=("$line") ;; esac
209
+ idx=$((idx + 1))
210
+ done
211
+ candidates=("${reordered[@]+"${reordered[@]}"}")
212
+ fi
137
213
  fi
138
214
 
139
215
  # Output up to limit
@@ -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="3.0.0"
9
+ VERSION="3.2.0"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
12
12
 
@@ -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="3.0.0"
9
+ VERSION="3.2.0"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
12
12
 
@@ -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="3.0.0"
9
+ VERSION="3.2.0"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
12
12
 
@@ -4,7 +4,7 @@
4
4
  # ║ ║
5
5
  # ║ Checks prerequisites, installed files, PATH, and common issues. ║
6
6
  # ╚═══════════════════════════════════════════════════════════════════════════╝
7
- VERSION="3.0.0"
7
+ VERSION="3.2.0"
8
8
  set -euo pipefail
9
9
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
10
10
 
@@ -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="3.0.0"
11
+ VERSION="3.2.0"
12
12
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
13
13
 
14
14
  # ─── Cross-platform compatibility ──────────────────────────────────────────
@@ -7,7 +7,7 @@
7
7
  set -euo pipefail
8
8
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
9
9
 
10
- VERSION="3.0.0"
10
+ VERSION="3.2.0"
11
11
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
12
12
 
13
13
  # ─── Cross-platform compatibility ──────────────────────────────────────────
@@ -481,17 +481,21 @@ cmd_status() {
481
481
  locks_dir="${DURABLE_DIR}/locks"
482
482
 
483
483
  local log_events log_size
484
- log_events=$(wc -l < "$log_file" 2>/dev/null || echo "0")
484
+ log_events=$(wc -l < "$log_file" 2>/dev/null || true)
485
+ log_events="${log_events:-0}"
485
486
  log_size=$(du -h "$log_file" 2>/dev/null | awk '{print $1}' || echo "0")
486
487
 
487
488
  local dlq_events
488
- dlq_events=$(wc -l < "$dlq_file" 2>/dev/null || echo "0")
489
+ dlq_events=$(wc -l < "$dlq_file" 2>/dev/null || true)
490
+ dlq_events="${dlq_events:-0}"
489
491
 
490
492
  local consumer_count
491
- consumer_count=$(find "$offsets_dir" -name "consumer-*.offset" 2>/dev/null | wc -l || echo "0")
493
+ consumer_count=$(find "$offsets_dir" -name "consumer-*.offset" 2>/dev/null | wc -l || true)
494
+ consumer_count="${consumer_count:-0}"
492
495
 
493
496
  local active_locks
494
- active_locks=$(find "$locks_dir" -type d -mindepth 1 2>/dev/null | wc -l || echo "0")
497
+ active_locks=$(find "$locks_dir" -type d -mindepth 1 2>/dev/null | wc -l || true)
498
+ active_locks="${active_locks:-0}"
495
499
 
496
500
  echo ""
497
501
  echo -e "${CYAN}${BOLD} Durable Workflow Status${RESET} ${DIM}v${VERSION}${RESET}"
@@ -5,7 +5,7 @@
5
5
  # ╚═══════════════════════════════════════════════════════════════════════════╝
6
6
  set -euo pipefail
7
7
 
8
- VERSION="3.0.0"
8
+ VERSION="3.2.0"
9
9
 
10
10
  # ─── Script directory resolution ────────────────────────────────────────────
11
11
  SOURCE="${BASH_SOURCE[0]}"
@@ -7,7 +7,7 @@
7
7
  set -euo pipefail
8
8
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
9
9
 
10
- VERSION="3.0.0"
10
+ VERSION="3.2.0"
11
11
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
12
12
 
13
13
  # ─── Cross-platform compatibility ──────────────────────────────────────────
@@ -251,7 +251,8 @@ cmd_status() {
251
251
  fi
252
252
  elif [[ -f "$EVENTS_FILE" ]]; then
253
253
  local total_events last_event_ts
254
- total_events=$(wc -l < "$EVENTS_FILE" || echo 0)
254
+ total_events=$(wc -l < "$EVENTS_FILE" || true)
255
+ total_events="${total_events:-0}"
255
256
  last_event_ts=$(tail -1 "$EVENTS_FILE" | jq -r '.ts // "never"' 2>/dev/null || echo "never")
256
257
  echo -e " ${CYAN}Event Store:${RESET} $EVENTS_FILE (file fallback)"
257
258
  echo -e " ${CYAN}Total Events:${RESET} ${BOLD}${total_events}${RESET}"
@@ -290,7 +291,8 @@ cmd_clean() {
290
291
  elif [[ -f "$EVENTS_FILE" ]]; then
291
292
  info "Cleaning events older than ${ttl_days} days..."
292
293
  local old_count tmp_file new_count removed
293
- old_count=$(grep -c "ts" "$EVENTS_FILE" 2>/dev/null || echo 0)
294
+ old_count=$(grep -c "ts" "$EVENTS_FILE" 2>/dev/null || true)
295
+ old_count="${old_count:-0}"
294
296
  tmp_file="$(mktemp)"
295
297
  while IFS= read -r line; do
296
298
  [[ -z "$line" ]] && continue
@@ -299,7 +301,8 @@ cmd_clean() {
299
301
  [[ -n "$ts" && "$ts" > "$cutoff_iso" ]] && echo "$line" >> "$tmp_file"
300
302
  done < "$EVENTS_FILE"
301
303
  mv "$tmp_file" "$EVENTS_FILE"
302
- new_count=$(wc -l < "$EVENTS_FILE" || echo 0)
304
+ new_count=$(wc -l < "$EVENTS_FILE" || true)
305
+ new_count="${new_count:-0}"
303
306
  removed=$((old_count - new_count))
304
307
  success "Removed $removed old events. Remaining: $new_count"
305
308
  else
@@ -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="3.0.0"
11
+ VERSION="3.2.0"
12
12
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
13
13
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
14
14
 
@@ -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="3.0.0"
9
+ VERSION="3.2.0"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
12
12
 
package/scripts/sw-fix.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="3.0.0"
9
+ VERSION="3.2.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="3.0.0"
9
+ VERSION="3.2.0"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
12
12
 
@@ -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="3.0.0"
9
+ VERSION="3.2.0"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
12
12
 
@@ -176,7 +176,7 @@ show_workers() {
176
176
  echo -e "${BOLD}Remote Machines:${RESET}"
177
177
  echo ""
178
178
 
179
- if jq '.machines[]?' "$MACHINES_FILE" 2>/dev/null | grep -q .; then
179
+ if jq '.machines[]?' "$MACHINES_FILE" 2>/dev/null | grep -q . 2>/dev/null; then
180
180
  jq -r '.machines[]? | "\(.name) (\(.hostname)) — \(.status) — \(.active_jobs // 0) active"' "$MACHINES_FILE" 2>/dev/null | while read -r machine; do
181
181
  echo -e " ${machine}"
182
182
  done
@@ -205,8 +205,10 @@ show_insights() {
205
205
 
206
206
  # Fleet-wide success rate (last 30 days)
207
207
  local total_pipelines successful_pipelines
208
- total_pipelines=$(grep '"type":"pipeline.completed"' "$EVENTS_FILE" 2>/dev/null | tail -5000 | wc -l || echo "0")
209
- successful_pipelines=$(grep '"type":"pipeline.completed".*"status":"success"' "$EVENTS_FILE" 2>/dev/null | tail -5000 | wc -l || echo "0")
208
+ total_pipelines=$(grep '"type":"pipeline.completed"' "$EVENTS_FILE" 2>/dev/null | tail -5000 | wc -l || true)
209
+ total_pipelines="${total_pipelines:-0}"
210
+ successful_pipelines=$(grep '"type":"pipeline.completed".*"status":"success"' "$EVENTS_FILE" 2>/dev/null | tail -5000 | wc -l || true)
211
+ successful_pipelines="${successful_pipelines:-0}"
210
212
 
211
213
  local success_rate=0
212
214
  if [[ "$total_pipelines" -gt 0 ]]; 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="3.0.0"
9
+ VERSION="3.2.0"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
12
12
 
@@ -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="3.0.0"
9
+ VERSION="3.2.0"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
12
12
 
@@ -454,7 +454,8 @@ cmd_status() {
454
454
  # Show recent webhook events
455
455
  if [[ -f "$WEBHOOK_LOG" ]]; then
456
456
  local count
457
- count=$(wc -l < "$WEBHOOK_LOG" 2>/dev/null || echo 0)
457
+ count=$(wc -l < "$WEBHOOK_LOG" 2>/dev/null || true)
458
+ count="${count:-0}"
458
459
  if [[ "$count" -gt 0 ]]; then
459
460
  echo -e "${BOLD}Recent Webhook Events (last 10):${RESET}"
460
461
  tail -10 "$WEBHOOK_LOG" | jq '{timestamp, event_type}' -c
@@ -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="3.0.0"
9
+ VERSION="3.2.0"
10
10
  SCRIPT_DIR="${SCRIPT_DIR:-$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)}"
11
11
  REPO_DIR="${REPO_DIR:-$(cd "$SCRIPT_DIR/.." && pwd)}"
12
12
 
@@ -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="3.0.0"
9
+ VERSION="3.2.0"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
12
12
 
@@ -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="3.0.0"
9
+ VERSION="3.2.0"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
12
12
 
@@ -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="3.0.0"
9
+ VERSION="3.2.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="3.0.0"
9
+ VERSION="3.2.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="3.0.0"
9
+ VERSION="3.2.0"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
12
12
 
@@ -103,7 +103,8 @@ detect_dead_code() {
103
103
 
104
104
  # Check if function is used in other files (count lines with this function name)
105
105
  local usage_count
106
- usage_count=$(grep -r "$func" "$REPO_DIR/scripts" --include="*.sh" 2>/dev/null | wc -l) || usage_count="0"
106
+ usage_count=$(grep -r "$func" "$REPO_DIR/scripts" --include="*.sh" 2>/dev/null | wc -l || true)
107
+ usage_count="${usage_count:-0}"
107
108
  usage_count=$(printf '%s' "$usage_count" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
108
109
 
109
110
  # Function definition counts as 1 usage; if only 1, it's unused
@@ -417,7 +418,8 @@ scan_platform_refactor() {
417
418
  sizes_file=$(mktemp)
418
419
  find "$scripts_dir" -maxdepth 1 -name "*.sh" -type f 2>/dev/null | while read -r f; do
419
420
  local lines
420
- lines=$(wc -l < "$f" 2>/dev/null || echo 0)
421
+ lines=$(wc -l < "$f" 2>/dev/null || true)
422
+ lines="${lines:-0}"
421
423
  printf '{"script":"%s","lines":%s}\n' "$(basename "$f")" "$lines"
422
424
  done | jq -s 'sort_by(-.lines) | .[0:15]' 2>/dev/null > "$sizes_file"
423
425
  local script_sizes
@@ -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="3.0.0"
9
+ VERSION="3.2.0"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
12
12
 
@@ -133,10 +133,14 @@ analyze_root_cause() {
133
133
  local config="$2"
134
134
 
135
135
  local timeout_hits error_hits memory_hits dependency_hits
136
- timeout_hits=$(echo "$failure_log" | grep -ic "timeout\|deadline\|too slow" || echo "0")
137
- memory_hits=$(echo "$failure_log" | grep -ic "out of memory\|OOM\|heap" || echo "0")
138
- dependency_hits=$(echo "$failure_log" | grep -ic "dependency\|import\|require\|not found" || echo "0")
139
- error_hits=$(echo "$failure_log" | grep -c . || echo "0")
136
+ timeout_hits=$(echo "$failure_log" | grep -ic "timeout\|deadline\|too slow" || true)
137
+ timeout_hits="${timeout_hits:-0}"
138
+ memory_hits=$(echo "$failure_log" | grep -ic "out of memory\|OOM\|heap" || true)
139
+ memory_hits="${memory_hits:-0}"
140
+ dependency_hits=$(echo "$failure_log" | grep -ic "dependency\|import\|require\|not found" || true)
141
+ dependency_hits="${dependency_hits:-0}"
142
+ error_hits=$(echo "$failure_log" | grep -c . || true)
143
+ error_hits="${error_hits:-0}"
140
144
 
141
145
  if [[ "$timeout_hits" -gt 0 ]]; then
142
146
  echo "Performance degradation: Timeout detected (${timeout_hits} occurrences)"
@@ -8,7 +8,7 @@
8
8
  # ║ ║
9
9
  # ║ --deploy Detect platform and generate deployed.json template ║
10
10
  # ╚═══════════════════════════════════════════════════════════════════════════╝
11
- VERSION="3.0.0"
11
+ VERSION="3.2.0"
12
12
  set -euo pipefail
13
13
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
14
14
  trap 'rm -f "${tmp:-}"' EXIT
@@ -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="3.0.0"
9
+ VERSION="3.2.0"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
12
12
 
@@ -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="3.0.0"
9
+ VERSION="3.2.0"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
  REPO_DIR="${REPO_DIR:-$(cd "$SCRIPT_DIR/.." && pwd)}"
12
12
 
@@ -395,7 +395,8 @@ _intelligence_fallback_analyze() {
395
395
  local outcomes_file="$HOME/.shipwright/optimization/outcomes.jsonl"
396
396
  if [[ -f "$outcomes_file" ]] && command -v jq &>/dev/null; then
397
397
  local sample_count
398
- sample_count=$(wc -l < "$outcomes_file" 2>/dev/null || echo "0")
398
+ sample_count=$(wc -l < "$outcomes_file" 2>/dev/null || true)
399
+ sample_count="${sample_count:-0}"
399
400
 
400
401
  if [[ "$sample_count" -gt 5 ]]; then
401
402
  # Compute average complexity from past outcomes
@@ -552,7 +553,8 @@ intelligence_compose_pipeline() {
552
553
  if ! _intelligence_enabled; then
553
554
  local fallback
554
555
  fallback=$(_intelligence_fallback_compose "$issue_analysis")
555
- echo "$fallback" | jq -c '. + {error: "intelligence_disabled"}' 2>/dev/null || echo '{"error":"intelligence_disabled","stages":[]}'
556
+ echo "$fallback" | jq -c '. + {status: "disabled", error: "intelligence_disabled"}' 2>/dev/null || echo '{"status":"disabled","error":"intelligence_disabled","stages":[]}'
557
+ [[ -z "${_INTEL_DISABLED_LOGGED:-}" ]] && { info "Intelligence disabled — using data-driven fallbacks"; _INTEL_DISABLED_LOGGED=1; }
556
558
  return 0
557
559
  fi
558
560
 
@@ -615,7 +617,8 @@ intelligence_predict_cost() {
615
617
  if ! _intelligence_enabled; then
616
618
  local fallback
617
619
  fallback=$(_intelligence_fallback_cost)
618
- echo "$fallback" | jq -c '. + {error: "intelligence_disabled", estimated_iterations: 0, likely_failure_stage: "unknown"}' 2>/dev/null || echo '{"error":"intelligence_disabled","estimated_cost_usd":0,"estimated_iterations":0,"likely_failure_stage":"unknown"}'
620
+ echo "$fallback" | jq -c '. + {status: "disabled", error: "intelligence_disabled", estimated_iterations: 0, likely_failure_stage: "unknown"}' 2>/dev/null || echo '{"status":"disabled","error":"intelligence_disabled","estimated_cost_usd":0,"estimated_iterations":0,"likely_failure_stage":"unknown"}'
621
+ [[ -z "${_INTEL_DISABLED_LOGGED:-}" ]] && { info "Intelligence disabled — using data-driven fallbacks"; _INTEL_DISABLED_LOGGED=1; }
619
622
  return 0
620
623
  fi
621
624
 
@@ -671,7 +674,8 @@ intelligence_synthesize_findings() {
671
674
  local findings_json="${1:-"[]"}"
672
675
 
673
676
  if ! _intelligence_enabled; then
674
- echo '{"error":"intelligence_disabled","priority_fixes":[],"root_causes":[],"recommended_approach":""}'
677
+ echo '{"status":"disabled","error":"intelligence_disabled","priority_fixes":[],"root_causes":[],"recommended_approach":""}'
678
+ [[ -z "${_INTEL_DISABLED_LOGGED:-}" ]] && { info "Intelligence disabled — using data-driven fallbacks"; _INTEL_DISABLED_LOGGED=1; }
675
679
  return 0
676
680
  fi
677
681
 
@@ -720,7 +724,8 @@ intelligence_search_memory() {
720
724
  local top_n="${3:-5}"
721
725
 
722
726
  if ! _intelligence_enabled; then
723
- echo '{"error":"intelligence_disabled","results":[]}'
727
+ echo '{"status":"disabled","error":"intelligence_disabled","results":[]}'
728
+ [[ -z "${_INTEL_DISABLED_LOGGED:-}" ]] && { info "Intelligence disabled — using data-driven fallbacks"; _INTEL_DISABLED_LOGGED=1; }
724
729
  return 0
725
730
  fi
726
731
 
@@ -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="3.0.0"
9
+ VERSION="3.2.0"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
12
12
 
@@ -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="3.0.0"
9
+ VERSION="3.2.0"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
12
12
 
@@ -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="3.0.0"
9
+ VERSION="3.2.0"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
12
12
 
@@ -4,7 +4,7 @@
4
4
  # ║ ║
5
5
  # ║ Captures tmux pane scrollback and provides log browsing/search. ║
6
6
  # ╚═══════════════════════════════════════════════════════════════════════════╝
7
- VERSION="3.0.0"
7
+ VERSION="3.2.0"
8
8
  set -euo pipefail
9
9
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
10
10