shipwright-cli 2.3.1 → 3.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 (162) hide show
  1. package/README.md +95 -28
  2. package/completions/_shipwright +1 -1
  3. package/completions/shipwright.bash +3 -8
  4. package/completions/shipwright.fish +1 -1
  5. package/config/defaults.json +111 -0
  6. package/config/event-schema.json +81 -0
  7. package/config/policy.json +155 -2
  8. package/config/policy.schema.json +162 -1
  9. package/dashboard/coverage/coverage-summary.json +14 -0
  10. package/dashboard/public/index.html +1 -1
  11. package/dashboard/server.ts +306 -17
  12. package/dashboard/src/components/charts/bar.test.ts +79 -0
  13. package/dashboard/src/components/charts/donut.test.ts +68 -0
  14. package/dashboard/src/components/charts/pipeline-rail.test.ts +117 -0
  15. package/dashboard/src/components/charts/sparkline.test.ts +125 -0
  16. package/dashboard/src/core/api.test.ts +309 -0
  17. package/dashboard/src/core/helpers.test.ts +301 -0
  18. package/dashboard/src/core/router.test.ts +307 -0
  19. package/dashboard/src/core/router.ts +7 -0
  20. package/dashboard/src/core/sse.test.ts +144 -0
  21. package/dashboard/src/views/metrics.test.ts +186 -0
  22. package/dashboard/src/views/overview.test.ts +173 -0
  23. package/dashboard/src/views/pipelines.test.ts +183 -0
  24. package/dashboard/src/views/team.test.ts +253 -0
  25. package/dashboard/vitest.config.ts +14 -5
  26. package/docs/TIPS.md +1 -1
  27. package/docs/patterns/README.md +1 -1
  28. package/package.json +15 -5
  29. package/scripts/adapters/docker-deploy.sh +1 -1
  30. package/scripts/adapters/tmux-adapter.sh +11 -1
  31. package/scripts/adapters/wezterm-adapter.sh +1 -1
  32. package/scripts/check-version-consistency.sh +1 -1
  33. package/scripts/lib/architecture.sh +126 -0
  34. package/scripts/lib/bootstrap.sh +75 -0
  35. package/scripts/lib/compat.sh +89 -6
  36. package/scripts/lib/config.sh +91 -0
  37. package/scripts/lib/daemon-adaptive.sh +3 -3
  38. package/scripts/lib/daemon-dispatch.sh +39 -16
  39. package/scripts/lib/daemon-health.sh +1 -1
  40. package/scripts/lib/daemon-patrol.sh +24 -12
  41. package/scripts/lib/daemon-poll.sh +37 -25
  42. package/scripts/lib/daemon-state.sh +115 -23
  43. package/scripts/lib/daemon-triage.sh +30 -8
  44. package/scripts/lib/fleet-failover.sh +63 -0
  45. package/scripts/lib/helpers.sh +30 -6
  46. package/scripts/lib/pipeline-detection.sh +2 -2
  47. package/scripts/lib/pipeline-github.sh +9 -9
  48. package/scripts/lib/pipeline-intelligence.sh +85 -35
  49. package/scripts/lib/pipeline-quality-checks.sh +16 -16
  50. package/scripts/lib/pipeline-quality.sh +1 -1
  51. package/scripts/lib/pipeline-stages.sh +242 -28
  52. package/scripts/lib/pipeline-state.sh +40 -4
  53. package/scripts/lib/test-helpers.sh +247 -0
  54. package/scripts/postinstall.mjs +3 -11
  55. package/scripts/sw +10 -4
  56. package/scripts/sw-activity.sh +1 -11
  57. package/scripts/sw-adaptive.sh +109 -85
  58. package/scripts/sw-adversarial.sh +4 -14
  59. package/scripts/sw-architecture-enforcer.sh +1 -11
  60. package/scripts/sw-auth.sh +8 -17
  61. package/scripts/sw-autonomous.sh +111 -49
  62. package/scripts/sw-changelog.sh +1 -11
  63. package/scripts/sw-checkpoint.sh +144 -20
  64. package/scripts/sw-ci.sh +2 -12
  65. package/scripts/sw-cleanup.sh +13 -17
  66. package/scripts/sw-code-review.sh +16 -36
  67. package/scripts/sw-connect.sh +5 -12
  68. package/scripts/sw-context.sh +9 -26
  69. package/scripts/sw-cost.sh +6 -16
  70. package/scripts/sw-daemon.sh +75 -70
  71. package/scripts/sw-dashboard.sh +57 -17
  72. package/scripts/sw-db.sh +506 -15
  73. package/scripts/sw-decompose.sh +1 -11
  74. package/scripts/sw-deps.sh +15 -25
  75. package/scripts/sw-developer-simulation.sh +1 -11
  76. package/scripts/sw-discovery.sh +112 -30
  77. package/scripts/sw-doc-fleet.sh +7 -17
  78. package/scripts/sw-docs-agent.sh +6 -16
  79. package/scripts/sw-docs.sh +4 -12
  80. package/scripts/sw-doctor.sh +134 -43
  81. package/scripts/sw-dora.sh +11 -19
  82. package/scripts/sw-durable.sh +35 -52
  83. package/scripts/sw-e2e-orchestrator.sh +11 -27
  84. package/scripts/sw-eventbus.sh +115 -115
  85. package/scripts/sw-evidence.sh +748 -0
  86. package/scripts/sw-feedback.sh +3 -13
  87. package/scripts/sw-fix.sh +2 -20
  88. package/scripts/sw-fleet-discover.sh +1 -11
  89. package/scripts/sw-fleet-viz.sh +10 -18
  90. package/scripts/sw-fleet.sh +13 -17
  91. package/scripts/sw-github-app.sh +6 -16
  92. package/scripts/sw-github-checks.sh +1 -11
  93. package/scripts/sw-github-deploy.sh +1 -11
  94. package/scripts/sw-github-graphql.sh +2 -12
  95. package/scripts/sw-guild.sh +1 -11
  96. package/scripts/sw-heartbeat.sh +49 -12
  97. package/scripts/sw-hygiene.sh +45 -43
  98. package/scripts/sw-incident.sh +284 -67
  99. package/scripts/sw-init.sh +35 -37
  100. package/scripts/sw-instrument.sh +1 -11
  101. package/scripts/sw-intelligence.sh +362 -51
  102. package/scripts/sw-jira.sh +5 -14
  103. package/scripts/sw-launchd.sh +2 -12
  104. package/scripts/sw-linear.sh +8 -17
  105. package/scripts/sw-logs.sh +4 -12
  106. package/scripts/sw-loop.sh +641 -90
  107. package/scripts/sw-memory.sh +243 -17
  108. package/scripts/sw-mission-control.sh +2 -12
  109. package/scripts/sw-model-router.sh +73 -34
  110. package/scripts/sw-otel.sh +11 -21
  111. package/scripts/sw-oversight.sh +1 -11
  112. package/scripts/sw-patrol-meta.sh +5 -11
  113. package/scripts/sw-pipeline-composer.sh +7 -17
  114. package/scripts/sw-pipeline-vitals.sh +1 -11
  115. package/scripts/sw-pipeline.sh +478 -122
  116. package/scripts/sw-pm.sh +2 -12
  117. package/scripts/sw-pr-lifecycle.sh +203 -29
  118. package/scripts/sw-predictive.sh +16 -22
  119. package/scripts/sw-prep.sh +6 -16
  120. package/scripts/sw-ps.sh +1 -11
  121. package/scripts/sw-public-dashboard.sh +2 -12
  122. package/scripts/sw-quality.sh +77 -10
  123. package/scripts/sw-reaper.sh +1 -11
  124. package/scripts/sw-recruit.sh +15 -25
  125. package/scripts/sw-regression.sh +11 -21
  126. package/scripts/sw-release-manager.sh +19 -28
  127. package/scripts/sw-release.sh +8 -16
  128. package/scripts/sw-remote.sh +1 -11
  129. package/scripts/sw-replay.sh +48 -44
  130. package/scripts/sw-retro.sh +70 -92
  131. package/scripts/sw-review-rerun.sh +220 -0
  132. package/scripts/sw-scale.sh +109 -32
  133. package/scripts/sw-security-audit.sh +12 -22
  134. package/scripts/sw-self-optimize.sh +239 -23
  135. package/scripts/sw-session.sh +3 -13
  136. package/scripts/sw-setup.sh +8 -18
  137. package/scripts/sw-standup.sh +5 -15
  138. package/scripts/sw-status.sh +32 -23
  139. package/scripts/sw-strategic.sh +129 -13
  140. package/scripts/sw-stream.sh +1 -11
  141. package/scripts/sw-swarm.sh +76 -36
  142. package/scripts/sw-team-stages.sh +10 -20
  143. package/scripts/sw-templates.sh +4 -14
  144. package/scripts/sw-testgen.sh +3 -13
  145. package/scripts/sw-tmux-pipeline.sh +1 -19
  146. package/scripts/sw-tmux-role-color.sh +0 -10
  147. package/scripts/sw-tmux-status.sh +3 -11
  148. package/scripts/sw-tmux.sh +2 -20
  149. package/scripts/sw-trace.sh +1 -19
  150. package/scripts/sw-tracker-github.sh +0 -10
  151. package/scripts/sw-tracker-jira.sh +1 -11
  152. package/scripts/sw-tracker-linear.sh +1 -11
  153. package/scripts/sw-tracker.sh +7 -24
  154. package/scripts/sw-triage.sh +24 -34
  155. package/scripts/sw-upgrade.sh +5 -23
  156. package/scripts/sw-ux.sh +1 -19
  157. package/scripts/sw-webhook.sh +18 -32
  158. package/scripts/sw-widgets.sh +3 -21
  159. package/scripts/sw-worktree.sh +11 -27
  160. package/scripts/update-homebrew-sha.sh +67 -0
  161. package/templates/pipelines/tdd.json +72 -0
  162. package/scripts/sw-pipeline.sh.mock +0 -7
@@ -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.3.1"
8
+ VERSION="3.0.0"
9
9
  set -euo pipefail
10
10
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
11
11
 
@@ -35,16 +35,6 @@ if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
35
35
  echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
36
36
  }
37
37
  fi
38
- CYAN="${CYAN:-\033[38;2;0;212;255m}"
39
- PURPLE="${PURPLE:-\033[38;2;124;58;237m}"
40
- BLUE="${BLUE:-\033[38;2;0;102;255m}"
41
- GREEN="${GREEN:-\033[38;2;74;222;128m}"
42
- YELLOW="${YELLOW:-\033[38;2;250;204;21m}"
43
- RED="${RED:-\033[38;2;248;113;113m}"
44
- DIM="${DIM:-\033[2m}"
45
- BOLD="${BOLD:-\033[1m}"
46
- RESET="${RESET:-\033[0m}"
47
-
48
38
  # ─── Template Discovery ─────────────────────────────────────────────────────
49
39
  REPO_TEMPLATES_DIR="$(cd "$SCRIPT_DIR/../tmux/templates" 2>/dev/null && pwd)" || REPO_TEMPLATES_DIR=""
50
40
  USER_TEMPLATES_DIR="${HOME}/.shipwright/templates"
@@ -79,7 +69,7 @@ find_template() {
79
69
  # Extract a top-level string field from JSON
80
70
  json_field() {
81
71
  local file="$1" field="$2"
82
- if command -v jq &>/dev/null; then
72
+ if command -v jq >/dev/null 2>&1; then
83
73
  jq -r ".${field} // \"\"" "$file" 2>/dev/null
84
74
  else
85
75
  grep -o "\"${field}\"[[:space:]]*:[[:space:]]*\"[^\"]*\"" "$file" | head -1 | sed 's/.*: *"//;s/"$//'
@@ -89,7 +79,7 @@ json_field() {
89
79
  # Extract agent count from JSON
90
80
  json_agent_count() {
91
81
  local file="$1"
92
- if command -v jq &>/dev/null; then
82
+ if command -v jq >/dev/null 2>&1; then
93
83
  jq -r '.agents // [] | length' "$file" 2>/dev/null
94
84
  else
95
85
  grep -c '"name"' "$file" 2>/dev/null || echo "0"
@@ -99,7 +89,7 @@ json_agent_count() {
99
89
  # Print agent details from a template
100
90
  print_agents() {
101
91
  local file="$1"
102
- if command -v jq &>/dev/null; then
92
+ if command -v jq >/dev/null 2>&1; then
103
93
  jq -r '.agents // [] | .[] | "\(.name // "?")|\(.role // "")|\(.focus // "")"' "$file" 2>/dev/null
104
94
  else
105
95
  # Best-effort grep fallback for simple cases
@@ -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.3.1"
9
+ VERSION="3.0.0"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
 
12
12
  # ─── Handle subcommands ───────────────────────────────────────────────────────
@@ -38,16 +38,6 @@ if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
38
38
  echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
39
39
  }
40
40
  fi
41
- CYAN="${CYAN:-\033[38;2;0;212;255m}"
42
- PURPLE="${PURPLE:-\033[38;2;124;58;237m}"
43
- BLUE="${BLUE:-\033[38;2;0;102;255m}"
44
- GREEN="${GREEN:-\033[38;2;74;222;128m}"
45
- YELLOW="${YELLOW:-\033[38;2;250;204;21m}"
46
- RED="${RED:-\033[38;2;248;113;113m}"
47
- DIM="${DIM:-\033[2m}"
48
- BOLD="${BOLD:-\033[1m}"
49
- RESET="${RESET:-\033[0m}"
50
-
51
41
  # ─── Configuration ───────────────────────────────────────────────────────────
52
42
  PROJECT_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
53
43
  SCRIPTS_DIR="$PROJECT_ROOT/scripts"
@@ -210,7 +200,7 @@ EOF
210
200
  # Generate test template; use Claude for real assertions when available
211
201
  local test_template_file="$TESTGEN_DIR/generated-tests.sh"
212
202
  local use_claude="false"
213
- command -v claude &>/dev/null && use_claude="true"
203
+ command -v claude >/dev/null 2>&1 && use_claude="true"
214
204
  [[ "${TESTGEN_USE_CLAUDE:-true}" == "false" ]] && use_claude="false"
215
205
 
216
206
  {
@@ -468,7 +458,7 @@ detect_regressions() {
468
458
  [[ "$(basename "$test_file")" == "sw-testgen-test.sh" ]] && continue
469
459
 
470
460
  local result
471
- if bash "$test_file" &>/dev/null; then
461
+ if bash "$test_file" >/dev/null 2>&1; then
472
462
  result="PASS"
473
463
  else
474
464
  result="FAIL"
@@ -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.3.1"
9
+ VERSION="3.0.0"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
12
12
 
@@ -26,24 +26,6 @@ if [[ "$(type -t now_iso 2>/dev/null)" != "function" ]]; then
26
26
  now_iso() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
27
27
  now_epoch() { date +%s; }
28
28
  fi
29
- if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
30
- emit_event() {
31
- local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
32
- local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
33
- while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
34
- echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
35
- }
36
- fi
37
- CYAN="${CYAN:-\033[38;2;0;212;255m}"
38
- PURPLE="${PURPLE:-\033[38;2;124;58;237m}"
39
- BLUE="${BLUE:-\033[38;2;0;102;255m}"
40
- GREEN="${GREEN:-\033[38;2;74;222;128m}"
41
- YELLOW="${YELLOW:-\033[38;2;250;204;21m}"
42
- RED="${RED:-\033[38;2;248;113;113m}"
43
- DIM="${DIM:-\033[2m}"
44
- BOLD="${BOLD:-\033[1m}"
45
- RESET="${RESET:-\033[0m}"
46
-
47
29
  # Get daemon session name
48
30
  get_daemon_session() {
49
31
  echo "sw-daemon"
@@ -39,16 +39,6 @@ if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
39
39
  echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
40
40
  }
41
41
  fi
42
- CYAN="${CYAN:-\033[38;2;0;212;255m}"
43
- PURPLE="${PURPLE:-\033[38;2;124;58;237m}"
44
- BLUE="${BLUE:-\033[38;2;0;102;255m}"
45
- GREEN="${GREEN:-\033[38;2;74;222;128m}"
46
- YELLOW="${YELLOW:-\033[38;2;250;204;21m}"
47
- RED="${RED:-\033[38;2;248;113;113m}"
48
- DIM="${DIM:-\033[2m}"
49
- BOLD="${BOLD:-\033[1m}"
50
- RESET="${RESET:-\033[0m}"
51
-
52
42
  # Get the active pane's title
53
43
  PANE_TITLE="$(tmux display-message -p '#{pane_title}' 2>/dev/null || echo "")"
54
44
 
@@ -9,6 +9,8 @@
9
9
  set -euo pipefail
10
10
 
11
11
  SCRIPT_DIR="${SCRIPT_DIR:-$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)}"
12
+ # shellcheck source=lib/compat.sh
13
+ [[ -f "$SCRIPT_DIR/lib/compat.sh" ]] && source "$SCRIPT_DIR/lib/compat.sh"
12
14
  # Canonical helpers (colors, output, events)
13
15
  # shellcheck source=lib/helpers.sh
14
16
  [[ -f "$SCRIPT_DIR/lib/helpers.sh" ]] && source "$SCRIPT_DIR/lib/helpers.sh"
@@ -29,16 +31,6 @@ if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
29
31
  echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
30
32
  }
31
33
  fi
32
- CYAN="${CYAN:-\033[38;2;0;212;255m}"
33
- PURPLE="${PURPLE:-\033[38;2;124;58;237m}"
34
- BLUE="${BLUE:-\033[38;2;0;102;255m}"
35
- GREEN="${GREEN:-\033[38;2;74;222;128m}"
36
- YELLOW="${YELLOW:-\033[38;2;250;204;21m}"
37
- RED="${RED:-\033[38;2;248;113;113m}"
38
- DIM="${DIM:-\033[2m}"
39
- BOLD="${BOLD:-\033[1m}"
40
- RESET="${RESET:-\033[0m}"
41
-
42
34
  # ─── Stage colors (match Shipwright brand palette) ────────────────────────
43
35
  # Each pipeline stage gets a distinct color for instant visual recognition
44
36
  stage_color() {
@@ -128,7 +120,7 @@ agent_widget() {
128
120
  # Heartbeat is alive if updated within last 60 seconds
129
121
  local mtime
130
122
  if [[ "$(uname)" == "Darwin" ]]; then
131
- mtime="$(stat -f %m "$hb" 2>/dev/null || echo 0)"
123
+ mtime="$(file_mtime "$hb")"
132
124
  else
133
125
  mtime="$(stat -c %Y "$hb" 2>/dev/null || echo 0)"
134
126
  fi
@@ -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.3.1"
14
+ VERSION="3.0.0"
15
15
  set -euo pipefail
16
16
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
17
17
 
@@ -34,24 +34,6 @@ if [[ "$(type -t now_iso 2>/dev/null)" != "function" ]]; then
34
34
  now_iso() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
35
35
  now_epoch() { date +%s; }
36
36
  fi
37
- if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
38
- emit_event() {
39
- local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
40
- local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
41
- while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
42
- echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
43
- }
44
- fi
45
- CYAN="${CYAN:-\033[38;2;0;212;255m}"
46
- PURPLE="${PURPLE:-\033[38;2;124;58;237m}"
47
- BLUE="${BLUE:-\033[38;2;0;102;255m}"
48
- GREEN="${GREEN:-\033[38;2;74;222;128m}"
49
- YELLOW="${YELLOW:-\033[38;2;250;204;21m}"
50
- RED="${RED:-\033[38;2;248;113;113m}"
51
- DIM="${DIM:-\033[2m}"
52
- BOLD="${BOLD:-\033[1m}"
53
- RESET="${RESET:-\033[0m}"
54
-
55
37
  PASS=0
56
38
  WARN=0
57
39
  FAIL=0
@@ -73,7 +55,7 @@ tmux_doctor() {
73
55
 
74
56
  # ─── 1. tmux installed + version ─────────────────────────────────────
75
57
  echo -e "${BOLD}1. tmux Version${RESET}"
76
- if ! command -v tmux &>/dev/null; then
58
+ if ! command -v tmux >/dev/null 2>&1; then
77
59
  check_fail "tmux not installed"
78
60
  echo -e " ${DIM}brew install tmux (macOS)${RESET}"
79
61
  echo -e " ${DIM}sudo apt install tmux (Ubuntu/Debian)${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.3.1"
9
+ VERSION="3.0.0"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
12
12
 
@@ -26,24 +26,6 @@ if [[ "$(type -t now_iso 2>/dev/null)" != "function" ]]; then
26
26
  now_iso() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
27
27
  now_epoch() { date +%s; }
28
28
  fi
29
- if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
30
- emit_event() {
31
- local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
32
- local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
33
- while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
34
- echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
35
- }
36
- fi
37
- CYAN="${CYAN:-\033[38;2;0;212;255m}"
38
- PURPLE="${PURPLE:-\033[38;2;124;58;237m}"
39
- BLUE="${BLUE:-\033[38;2;0;102;255m}"
40
- GREEN="${GREEN:-\033[38;2;74;222;128m}"
41
- YELLOW="${YELLOW:-\033[38;2;250;204;21m}"
42
- RED="${RED:-\033[38;2;248;113;113m}"
43
- DIM="${DIM:-\033[2m}"
44
- BOLD="${BOLD:-\033[1m}"
45
- RESET="${RESET:-\033[0m}"
46
-
47
29
  # ─── Data Paths ─────────────────────────────────────────────────────────────
48
30
  EVENTS_FILE="${HOME}/.shipwright/events.jsonl"
49
31
  SHIPWRIGHT_DIR="${REPO_DIR}/.claude/pipeline-artifacts"
@@ -28,16 +28,6 @@ if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
28
28
  echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
29
29
  }
30
30
  fi
31
- CYAN="${CYAN:-\033[38;2;0;212;255m}"
32
- PURPLE="${PURPLE:-\033[38;2;124;58;237m}"
33
- BLUE="${BLUE:-\033[38;2;0;102;255m}"
34
- GREEN="${GREEN:-\033[38;2;74;222;128m}"
35
- YELLOW="${YELLOW:-\033[38;2;250;204;21m}"
36
- RED="${RED:-\033[38;2;248;113;113m}"
37
- DIM="${DIM:-\033[2m}"
38
- BOLD="${BOLD:-\033[1m}"
39
- RESET="${RESET:-\033[0m}"
40
-
41
31
  # ─── Discovery & CRUD Interface ────────────────────────────────────────────
42
32
  # All functions output normalized JSON (or plain text where specified).
43
33
  # Input: normalized arguments (label, state, issue_id, etc.)
@@ -28,16 +28,6 @@ if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
28
28
  echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
29
29
  }
30
30
  fi
31
- CYAN="${CYAN:-\033[38;2;0;212;255m}"
32
- PURPLE="${PURPLE:-\033[38;2;124;58;237m}"
33
- BLUE="${BLUE:-\033[38;2;0;102;255m}"
34
- GREEN="${GREEN:-\033[38;2;74;222;128m}"
35
- YELLOW="${YELLOW:-\033[38;2;250;204;21m}"
36
- RED="${RED:-\033[38;2;248;113;113m}"
37
- DIM="${DIM:-\033[2m}"
38
- BOLD="${BOLD:-\033[1m}"
39
- RESET="${RESET:-\033[0m}"
40
-
41
31
  # ─── Status Auto-Discovery ────────────────────────────────────────────────
42
32
  # Queries Jira API for project statuses and caches the transition name mapping.
43
33
  # Only fills in JIRA_TRANSITION_* values that are empty (config/env takes priority).
@@ -158,7 +148,7 @@ jira_api() {
158
148
  local auth
159
149
  auth=$(printf '%s:%s' "$JIRA_EMAIL" "$JIRA_API_TOKEN" | base64)
160
150
 
161
- local args=(-sf -X "$method" \
151
+ local args=(-sf --connect-timeout 10 --max-time 30 -X "$method" \
162
152
  -H "Authorization: Basic $auth" \
163
153
  -H "Content-Type: application/json")
164
154
 
@@ -28,16 +28,6 @@ if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
28
28
  echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
29
29
  }
30
30
  fi
31
- CYAN="${CYAN:-\033[38;2;0;212;255m}"
32
- PURPLE="${PURPLE:-\033[38;2;124;58;237m}"
33
- BLUE="${BLUE:-\033[38;2;0;102;255m}"
34
- GREEN="${GREEN:-\033[38;2;74;222;128m}"
35
- YELLOW="${YELLOW:-\033[38;2;250;204;21m}"
36
- RED="${RED:-\033[38;2;248;113;113m}"
37
- DIM="${DIM:-\033[2m}"
38
- BOLD="${BOLD:-\033[1m}"
39
- RESET="${RESET:-\033[0m}"
40
-
41
31
  # ─── Status Auto-Discovery ────────────────────────────────────────────────
42
32
  # Queries Linear API for workflow states and caches the mapping.
43
33
  # Only fills in STATUS_* values that are empty (config/env takes priority).
@@ -175,7 +165,7 @@ linear_graphql() {
175
165
  payload=$(jq -n --arg q "$query" --argjson v "$variables" '{query: $q, variables: $v}')
176
166
 
177
167
  local response
178
- response=$(curl -sf -X POST "$LINEAR_API" \
168
+ response=$(curl -sf --connect-timeout 10 --max-time 30 -X POST "$LINEAR_API" \
179
169
  -H "Authorization: $LINEAR_API_KEY" \
180
170
  -H "Content-Type: application/json" \
181
171
  -d "$payload" 2>&1) || {
@@ -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.3.1"
9
+ VERSION="3.0.0"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
12
12
 
@@ -17,6 +17,7 @@ REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
17
17
  # Canonical helpers (colors, output, events)
18
18
  # shellcheck source=lib/helpers.sh
19
19
  [[ -f "$SCRIPT_DIR/lib/helpers.sh" ]] && source "$SCRIPT_DIR/lib/helpers.sh"
20
+ [[ -f "$SCRIPT_DIR/lib/config.sh" ]] && source "$SCRIPT_DIR/lib/config.sh"
20
21
  # Fallbacks when helpers not loaded (e.g. test env with overridden SCRIPT_DIR)
21
22
  [[ "$(type -t info 2>/dev/null)" == "function" ]] || info() { echo -e "\033[38;2;0;212;255m\033[1m▸\033[0m $*"; }
22
23
  [[ "$(type -t success 2>/dev/null)" == "function" ]] || success() { echo -e "\033[38;2;74;222;128m\033[1m✓\033[0m $*"; }
@@ -26,24 +27,6 @@ if [[ "$(type -t now_iso 2>/dev/null)" != "function" ]]; then
26
27
  now_iso() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
27
28
  now_epoch() { date +%s; }
28
29
  fi
29
- if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
30
- emit_event() {
31
- local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
32
- local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
33
- while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
34
- echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
35
- }
36
- fi
37
- CYAN="${CYAN:-\033[38;2;0;212;255m}"
38
- PURPLE="${PURPLE:-\033[38;2;124;58;237m}"
39
- BLUE="${BLUE:-\033[38;2;0;102;255m}"
40
- GREEN="${GREEN:-\033[38;2;74;222;128m}"
41
- YELLOW="${YELLOW:-\033[38;2;250;204;21m}"
42
- RED="${RED:-\033[38;2;248;113;113m}"
43
- DIM="${DIM:-\033[2m}"
44
- BOLD="${BOLD:-\033[1m}"
45
- RESET="${RESET:-\033[0m}"
46
-
47
30
  # ─── Configuration ─────────────────────────────────────────────────────────
48
31
  CONFIG_DIR="${HOME}/.shipwright"
49
32
  TRACKER_CONFIG="${CONFIG_DIR}/tracker-config.json"
@@ -127,7 +110,7 @@ _dispatch_provider() {
127
110
  local provider_func="provider_${func}"
128
111
 
129
112
  # Provider scripts define provider_* functions
130
- if type "$provider_func" &>/dev/null; then
113
+ if type "$provider_func" >/dev/null 2>&1; then
131
114
  "$provider_func" "$@"
132
115
  return $?
133
116
  else
@@ -137,7 +120,7 @@ _dispatch_provider() {
137
120
  # Try GitHub provider
138
121
  if [[ -f "$SCRIPT_DIR/sw-tracker-github.sh" ]]; then
139
122
  source "$SCRIPT_DIR/sw-tracker-github.sh"
140
- if type "$provider_func" &>/dev/null; then
123
+ if type "$provider_func" >/dev/null 2>&1; then
141
124
  "$provider_func" "$@"
142
125
  return $?
143
126
  fi
@@ -221,7 +204,7 @@ tracker_notify() {
221
204
  fi
222
205
 
223
206
  # Provider scripts define provider_notify()
224
- if type provider_notify &>/dev/null; then
207
+ if type provider_notify >/dev/null 2>&1; then
225
208
  provider_notify "$event" "$gh_issue" "$detail"
226
209
  else
227
210
  warn "Provider '$TRACKER_PROVIDER' loaded but provider_notify() not defined"
@@ -330,7 +313,7 @@ _init_linear() {
330
313
  local payload
331
314
  payload=$(jq -n --arg q 'query { viewer { id name } }' '{query: $q}')
332
315
  local response
333
- response=$(curl -sf -X POST "https://api.linear.app/graphql" \
316
+ response=$(curl -sf --connect-timeout "$(_config_get_int "network.connect_timeout" 10)" --max-time "$(_config_get_int "network.max_time" 30)" -X POST "$(_config_get "urls.linear_api" "https://api.linear.app/graphql")" \
334
317
  -H "Authorization: $api_key" \
335
318
  -H "Content-Type: application/json" \
336
319
  -d "$payload" 2>&1) || {
@@ -405,7 +388,7 @@ _init_jira() {
405
388
  local auth
406
389
  auth=$(printf '%s:%s' "$email" "$api_token" | base64)
407
390
  local response
408
- response=$(curl -sf -X GET "${base_url}/rest/api/3/myself" \
391
+ response=$(curl -sf --connect-timeout "$(_config_get_int "network.connect_timeout" 10)" --max-time "$(_config_get_int "network.max_time" 30)" -X GET "${base_url}/rest/api/3/myself" \
409
392
  -H "Authorization: Basic $auth" \
410
393
  -H "Content-Type: application/json" 2>&1) || {
411
394
  warn "Could not validate connection — check your credentials"
@@ -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.3.1"
9
+ VERSION="3.0.0"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
12
12
 
@@ -16,7 +16,15 @@ REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
16
16
  # Canonical helpers (colors, output, events)
17
17
  # shellcheck source=lib/helpers.sh
18
18
  [[ -f "$SCRIPT_DIR/lib/helpers.sh" ]] && source "$SCRIPT_DIR/lib/helpers.sh"
19
+ [[ -f "$SCRIPT_DIR/lib/config.sh" ]] && source "$SCRIPT_DIR/lib/config.sh"
19
20
  # Fallbacks when helpers not loaded (e.g. test env with overridden SCRIPT_DIR)
21
+ [[ -z "${CYAN:-}" ]] && { [[ -z "${NO_COLOR:-}" ]] && CYAN='\033[38;2;0;212;255m' || CYAN=''; } || true
22
+ [[ -z "${RESET:-}" ]] && { [[ -z "${NO_COLOR:-}" ]] && RESET='\033[0m' || RESET=''; } || true
23
+ [[ -z "${BOLD:-}" ]] && { [[ -z "${NO_COLOR:-}" ]] && BOLD='\033[1m' || BOLD=''; } || true
24
+ [[ -z "${DIM:-}" ]] && { [[ -z "${NO_COLOR:-}" ]] && DIM='\033[2m' || DIM=''; } || true
25
+ [[ -z "${GREEN:-}" ]] && { [[ -z "${NO_COLOR:-}" ]] && GREEN='\033[38;2;74;222;128m' || GREEN=''; } || true
26
+ [[ -z "${RED:-}" ]] && { [[ -z "${NO_COLOR:-}" ]] && RED='\033[38;2;248;113;113m' || RED=''; } || true
27
+ [[ -z "${YELLOW:-}" ]] && { [[ -z "${NO_COLOR:-}" ]] && YELLOW='\033[38;2;250;204;21m' || YELLOW=''; } || true
20
28
  [[ "$(type -t info 2>/dev/null)" == "function" ]] || info() { echo -e "\033[38;2;0;212;255m\033[1m▸\033[0m $*"; }
21
29
  [[ "$(type -t success 2>/dev/null)" == "function" ]] || success() { echo -e "\033[38;2;74;222;128m\033[1m✓\033[0m $*"; }
22
30
  [[ "$(type -t warn 2>/dev/null)" == "function" ]] || warn() { echo -e "\033[38;2;250;204;21m\033[1m⚠\033[0m $*"; }
@@ -25,24 +33,6 @@ if [[ "$(type -t now_iso 2>/dev/null)" != "function" ]]; then
25
33
  now_iso() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
26
34
  now_epoch() { date +%s; }
27
35
  fi
28
- if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
29
- emit_event() {
30
- local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
31
- local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
32
- while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
33
- echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
34
- }
35
- fi
36
- CYAN="${CYAN:-\033[38;2;0;212;255m}"
37
- PURPLE="${PURPLE:-\033[38;2;124;58;237m}"
38
- BLUE="${BLUE:-\033[38;2;0;102;255m}"
39
- GREEN="${GREEN:-\033[38;2;74;222;128m}"
40
- YELLOW="${YELLOW:-\033[38;2;250;204;21m}"
41
- RED="${RED:-\033[38;2;248;113;113m}"
42
- DIM="${DIM:-\033[2m}"
43
- BOLD="${BOLD:-\033[1m}"
44
- RESET="${RESET:-\033[0m}"
45
-
46
36
  # ─── GitHub API (safe when NO_GITHUB set) ──────────────────────────────────
47
37
 
48
38
  check_gh() {
@@ -50,7 +40,7 @@ check_gh() {
50
40
  error "GitHub access disabled (NO_GITHUB=1)"
51
41
  exit 1
52
42
  fi
53
- if ! command -v gh &>/dev/null; then
43
+ if ! command -v gh >/dev/null 2>&1; then
54
44
  error "gh CLI not found. Install: https://cli.github.com"
55
45
  exit 1
56
46
  fi
@@ -178,7 +168,7 @@ analyze_with_ai() {
178
168
  if [[ ! -f "${SCRIPT_DIR}/sw-intelligence.sh" ]]; then
179
169
  return 1
180
170
  fi
181
- if ! command -v claude &>/dev/null; then
171
+ if ! command -v claude >/dev/null 2>&1; then
182
172
  return 1
183
173
  fi
184
174
 
@@ -210,7 +200,7 @@ Return JSON with exactly these fields:
210
200
  local result
211
201
  result=$(_intelligence_call_claude "$prompt" "$cache_key" 2>/dev/null) || true
212
202
 
213
- if [[ -z "$result" ]] || echo "$result" | jq -e '.' &>/dev/null; then
203
+ if [[ -z "$result" ]] || echo "$result" | jq -e '.' >/dev/null 2>&1; then
214
204
  : # result is empty or valid JSON
215
205
  else
216
206
  return 1
@@ -225,7 +215,7 @@ Return JSON with exactly these fields:
225
215
  labels_val=$(echo "$result" | jq -r '.labels // []' 2>/dev/null)
226
216
 
227
217
  # Reject if we got an error object
228
- if echo "$result" | jq -e '.error' &>/dev/null; then
218
+ if echo "$result" | jq -e '.error' >/dev/null 2>&1; then
229
219
  return 1
230
220
  fi
231
221
 
@@ -445,8 +435,8 @@ cmd_label() {
445
435
  labels_str=$(echo "$analysis" | jq -r '.suggested_labels | join(" ")')
446
436
 
447
437
  # Apply labels via gh CLI
448
- local label_array
449
- mapfile -t label_array <<< "$(echo "$labels_str" | tr ' ' '\n')"
438
+ local label_array=()
439
+ while IFS= read -r _l; do [[ -n "$_l" ]] && label_array+=("$_l"); done <<< "$(echo "$labels_str" | tr ' ' '\n')"
450
440
 
451
441
  for label in "${label_array[@]}"; do
452
442
  [[ -z "$label" ]] && continue
@@ -469,7 +459,7 @@ cmd_prioritize() {
469
459
 
470
460
  # Fetch all open issues
471
461
  local issues_json
472
- issues_json=$(gh issue list --state open --json number,title,body,labels,createdAt,reactions --limit 100 2>/dev/null || echo "[]")
462
+ issues_json=$(gh issue list --state open --json number,title,body,labels,createdAt,reactions --limit "$(_config_get_int "limits.triage_issues" 100)" 2>/dev/null || echo "[]")
473
463
 
474
464
  local issue_count
475
465
  issue_count=$(echo "$issues_json" | jq 'length')
@@ -540,13 +530,13 @@ cmd_prioritize() {
540
530
  echo -e "${BOLD}Prioritized Backlog${RESET}"
541
531
  echo "─────────────────────────────────────────────────────────────────"
542
532
  echo ""
543
- echo "$output_json" | jq -r '.[] | "\(.number | tostring | @json) \(.score | tostring): \(.title) [type:\(.type) complexity:\(.complexity) risk:\(.risk)]"' | while IFS= read -r line; do
533
+ echo "$output_json" | jq -r '.[] | "#\(.number) \(.score): \(.title) [type:\(.type) complexity:\(.complexity) risk:\(.risk)]"' | while IFS= read -r line; do
544
534
  local number score rest
545
- number=$(echo "$line" | jq -r 'split(" ")[0]' <<< "$line")
546
- score=$(echo "$line" | cut -d: -f2 | cut -d' ' -f1)
535
+ number=$(echo "$line" | cut -d' ' -f1)
536
+ score=$(echo "$line" | cut -d' ' -f2 | tr -d ':')
547
537
  rest=$(echo "$line" | cut -d' ' -f3-)
548
538
 
549
- echo -e " ${CYAN}#${number}${RESET} ${BOLD}${score}${RESET} ${rest}"
539
+ echo -e " ${CYAN}${number}${RESET} ${BOLD}${score}${RESET} ${rest}"
550
540
  done
551
541
 
552
542
  echo ""
@@ -565,7 +555,7 @@ cmd_team() {
565
555
 
566
556
  # Determine if GitHub is available (don't exit — allow offline fallback)
567
557
  local gh_available=false
568
- if [[ "${NO_GITHUB:-}" != "1" ]] && command -v gh &>/dev/null; then
558
+ if [[ "${NO_GITHUB:-}" != "1" ]] && command -v gh >/dev/null 2>&1; then
569
559
  gh_available=true
570
560
  fi
571
561
 
@@ -595,7 +585,7 @@ cmd_team() {
595
585
 
596
586
  local recruit_result
597
587
  recruit_result=$(bash "$SCRIPT_DIR/sw-recruit.sh" team --json "$issue_title" 2>/dev/null) || true
598
- if [[ -n "$recruit_result" ]] && echo "$recruit_result" | jq -e '.team' &>/dev/null 2>&1; then
588
+ if [[ -n "$recruit_result" ]] && echo "$recruit_result" | jq -e '.team' >/dev/null 2>&1; then
599
589
  model=$(echo "$recruit_result" | jq -r '.model // "sonnet"')
600
590
  agents=$(echo "$recruit_result" | jq -r '.agents // 2')
601
591
  template=$(echo "$recruit_result" | jq -r '.template // ""')
@@ -675,7 +665,7 @@ cmd_batch() {
675
665
 
676
666
  # Fetch unlabeled open issues
677
667
  local issues_json
678
- issues_json=$(gh issue list --state open --search "no:label" --json number --limit 50 2>/dev/null || echo "[]")
668
+ issues_json=$(gh issue list --state open --search "no:label" --json number --limit "$(_config_get_int "limits.triage_unlabeled" 50)" 2>/dev/null || echo "[]")
679
669
 
680
670
  local issue_count
681
671
  issue_count=$(echo "$issues_json" | jq 'length')
@@ -701,7 +691,7 @@ cmd_report() {
701
691
 
702
692
  # Fetch labeled issues
703
693
  local issues_json
704
- issues_json=$(gh issue list --state open --json labels,title,number --limit 100 2>/dev/null || echo "[]")
694
+ issues_json=$(gh issue list --state open --json labels,title,number --limit "$(_config_get_int "limits.triage_issues" 100)" 2>/dev/null || echo "[]")
705
695
 
706
696
  local type_counts complexity_counts priority_counts
707
697
  type_counts='{}'
@@ -2,7 +2,7 @@
2
2
  # ╔═══════════════════════════════════════════════════════════════════════════╗
3
3
  # ║ sw upgrade — Detect and apply updates from the repo ║
4
4
  # ╚═══════════════════════════════════════════════════════════════════════════╝
5
- VERSION="2.3.1"
5
+ VERSION="3.0.0"
6
6
  set -euo pipefail
7
7
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
8
8
 
@@ -25,24 +25,6 @@ if [[ "$(type -t now_iso 2>/dev/null)" != "function" ]]; then
25
25
  now_iso() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
26
26
  now_epoch() { date +%s; }
27
27
  fi
28
- if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
29
- emit_event() {
30
- local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
31
- local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
32
- while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
33
- echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
34
- }
35
- fi
36
- CYAN="${CYAN:-\033[38;2;0;212;255m}"
37
- PURPLE="${PURPLE:-\033[38;2;124;58;237m}"
38
- BLUE="${BLUE:-\033[38;2;0;102;255m}"
39
- GREEN="${GREEN:-\033[38;2;74;222;128m}"
40
- YELLOW="${YELLOW:-\033[38;2;250;204;21m}"
41
- RED="${RED:-\033[38;2;248;113;113m}"
42
- DIM="${DIM:-\033[2m}"
43
- BOLD="${BOLD:-\033[1m}"
44
- RESET="${RESET:-\033[0m}"
45
-
46
28
  # ─── Parse flags ───────────────────────────────────────────────────────────
47
29
  APPLY=false
48
30
  REPO_OVERRIDE=""
@@ -70,8 +52,8 @@ find_repo() {
70
52
  fi
71
53
 
72
54
  # 2. Environment variable
73
- if [[ -n "${CCT_REPO_PATH:-}" ]]; then
74
- echo "$CCT_REPO_PATH"
55
+ if [[ -n "${SHIPWRIGHT_REPO_PATH:-}" ]]; then
56
+ echo "$SHIPWRIGHT_REPO_PATH"
75
57
  return
76
58
  fi
77
59
 
@@ -102,7 +84,7 @@ REPO_PATH="$(find_repo)" || {
102
84
  error "Cannot locate the Shipwright repo."
103
85
  echo ""
104
86
  echo -e " Try one of:"
105
- echo -e " ${DIM}export CCT_REPO_PATH=/path/to/shipwright${RESET}"
87
+ echo -e " ${DIM}export SHIPWRIGHT_REPO_PATH=/path/to/shipwright${RESET}"
106
88
  echo -e " ${DIM}shipwright upgrade --repo-path /path/to/shipwright${RESET}"
107
89
  exit 1
108
90
  }
@@ -277,7 +259,7 @@ bootstrap_manifest() {
277
259
  IFS='|' read -r key _ dest _ _ <<< "$entry"
278
260
  if [[ -f "$dest" ]]; then
279
261
  echo -e " ${GREEN}✓${RESET} ${DIM}$key${RESET} → $dest"
280
- ((found++))
262
+ found=$((found + 1))
281
263
  fi
282
264
  done
283
265