shipwright-cli 1.9.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/.claude/hooks/post-tool-use.sh +12 -5
  2. package/README.md +114 -36
  3. package/completions/_shipwright +212 -32
  4. package/completions/shipwright.bash +97 -25
  5. package/docs/strategy/01-market-research.md +619 -0
  6. package/docs/strategy/02-mission-and-brand.md +587 -0
  7. package/docs/strategy/03-gtm-and-roadmap.md +759 -0
  8. package/docs/strategy/QUICK-START.txt +289 -0
  9. package/docs/strategy/README.md +172 -0
  10. package/package.json +4 -2
  11. package/scripts/sw +217 -2
  12. package/scripts/sw-activity.sh +500 -0
  13. package/scripts/sw-adaptive.sh +925 -0
  14. package/scripts/sw-adversarial.sh +1 -1
  15. package/scripts/sw-architecture-enforcer.sh +1 -1
  16. package/scripts/sw-auth.sh +613 -0
  17. package/scripts/sw-autonomous.sh +664 -0
  18. package/scripts/sw-changelog.sh +704 -0
  19. package/scripts/sw-checkpoint.sh +79 -1
  20. package/scripts/sw-ci.sh +602 -0
  21. package/scripts/sw-cleanup.sh +192 -7
  22. package/scripts/sw-code-review.sh +637 -0
  23. package/scripts/sw-connect.sh +1 -1
  24. package/scripts/sw-context.sh +605 -0
  25. package/scripts/sw-cost.sh +1 -1
  26. package/scripts/sw-daemon.sh +812 -138
  27. package/scripts/sw-dashboard.sh +1 -1
  28. package/scripts/sw-db.sh +540 -0
  29. package/scripts/sw-decompose.sh +539 -0
  30. package/scripts/sw-deps.sh +551 -0
  31. package/scripts/sw-developer-simulation.sh +1 -1
  32. package/scripts/sw-discovery.sh +412 -0
  33. package/scripts/sw-docs-agent.sh +539 -0
  34. package/scripts/sw-docs.sh +1 -1
  35. package/scripts/sw-doctor.sh +59 -1
  36. package/scripts/sw-dora.sh +615 -0
  37. package/scripts/sw-durable.sh +710 -0
  38. package/scripts/sw-e2e-orchestrator.sh +535 -0
  39. package/scripts/sw-eventbus.sh +393 -0
  40. package/scripts/sw-feedback.sh +471 -0
  41. package/scripts/sw-fix.sh +1 -1
  42. package/scripts/sw-fleet-discover.sh +567 -0
  43. package/scripts/sw-fleet-viz.sh +404 -0
  44. package/scripts/sw-fleet.sh +8 -1
  45. package/scripts/sw-github-app.sh +596 -0
  46. package/scripts/sw-github-checks.sh +1 -1
  47. package/scripts/sw-github-deploy.sh +1 -1
  48. package/scripts/sw-github-graphql.sh +1 -1
  49. package/scripts/sw-guild.sh +569 -0
  50. package/scripts/sw-heartbeat.sh +1 -1
  51. package/scripts/sw-hygiene.sh +559 -0
  52. package/scripts/sw-incident.sh +617 -0
  53. package/scripts/sw-init.sh +88 -1
  54. package/scripts/sw-instrument.sh +699 -0
  55. package/scripts/sw-intelligence.sh +1 -1
  56. package/scripts/sw-jira.sh +1 -1
  57. package/scripts/sw-launchd.sh +366 -31
  58. package/scripts/sw-linear.sh +1 -1
  59. package/scripts/sw-logs.sh +1 -1
  60. package/scripts/sw-loop.sh +507 -51
  61. package/scripts/sw-memory.sh +198 -3
  62. package/scripts/sw-mission-control.sh +487 -0
  63. package/scripts/sw-model-router.sh +545 -0
  64. package/scripts/sw-otel.sh +596 -0
  65. package/scripts/sw-oversight.sh +689 -0
  66. package/scripts/sw-pipeline-composer.sh +8 -8
  67. package/scripts/sw-pipeline-vitals.sh +1096 -0
  68. package/scripts/sw-pipeline.sh +2451 -180
  69. package/scripts/sw-pm.sh +693 -0
  70. package/scripts/sw-pr-lifecycle.sh +522 -0
  71. package/scripts/sw-predictive.sh +1 -1
  72. package/scripts/sw-prep.sh +1 -1
  73. package/scripts/sw-ps.sh +4 -3
  74. package/scripts/sw-public-dashboard.sh +798 -0
  75. package/scripts/sw-quality.sh +595 -0
  76. package/scripts/sw-reaper.sh +5 -3
  77. package/scripts/sw-recruit.sh +573 -0
  78. package/scripts/sw-regression.sh +642 -0
  79. package/scripts/sw-release-manager.sh +736 -0
  80. package/scripts/sw-release.sh +706 -0
  81. package/scripts/sw-remote.sh +1 -1
  82. package/scripts/sw-replay.sh +520 -0
  83. package/scripts/sw-retro.sh +691 -0
  84. package/scripts/sw-scale.sh +444 -0
  85. package/scripts/sw-security-audit.sh +505 -0
  86. package/scripts/sw-self-optimize.sh +109 -8
  87. package/scripts/sw-session.sh +31 -9
  88. package/scripts/sw-setup.sh +1 -1
  89. package/scripts/sw-standup.sh +712 -0
  90. package/scripts/sw-status.sh +192 -1
  91. package/scripts/sw-strategic.sh +658 -0
  92. package/scripts/sw-stream.sh +450 -0
  93. package/scripts/sw-swarm.sh +583 -0
  94. package/scripts/sw-team-stages.sh +511 -0
  95. package/scripts/sw-templates.sh +1 -1
  96. package/scripts/sw-testgen.sh +515 -0
  97. package/scripts/sw-tmux-pipeline.sh +554 -0
  98. package/scripts/sw-tmux.sh +1 -1
  99. package/scripts/sw-trace.sh +485 -0
  100. package/scripts/sw-tracker-github.sh +188 -0
  101. package/scripts/sw-tracker-jira.sh +172 -0
  102. package/scripts/sw-tracker-linear.sh +251 -0
  103. package/scripts/sw-tracker.sh +117 -2
  104. package/scripts/sw-triage.sh +603 -0
  105. package/scripts/sw-upgrade.sh +1 -1
  106. package/scripts/sw-ux.sh +677 -0
  107. package/scripts/sw-webhook.sh +627 -0
  108. package/scripts/sw-widgets.sh +530 -0
  109. package/scripts/sw-worktree.sh +1 -1
  110. package/templates/pipelines/autonomous.json +8 -1
  111. package/templates/pipelines/cost-aware.json +21 -0
  112. package/templates/pipelines/deployed.json +40 -6
  113. package/templates/pipelines/enterprise.json +16 -2
  114. package/templates/pipelines/fast.json +19 -0
  115. package/templates/pipelines/full.json +16 -2
  116. package/templates/pipelines/hotfix.json +19 -0
  117. package/templates/pipelines/standard.json +19 -0
@@ -4,7 +4,7 @@
4
4
  # ║ ║
5
5
  # ║ Shows running teams, agent windows, and task progress. ║
6
6
  # ╚═══════════════════════════════════════════════════════════════════════════╝
7
- VERSION="1.9.0"
7
+ VERSION="2.0.0"
8
8
  set -euo pipefail
9
9
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
10
10
 
@@ -24,6 +24,197 @@ _COMPAT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/lib/compat.sh"
24
24
  # shellcheck source=lib/compat.sh
25
25
  [[ -f "$_COMPAT" ]] && source "$_COMPAT"
26
26
 
27
+ # ─── Argument Parsing ─────────────────────────────────────────────────────────
28
+ JSON_OUTPUT="false"
29
+ while [[ $# -gt 0 ]]; do
30
+ case "$1" in
31
+ --json) JSON_OUTPUT="true"; shift ;;
32
+ --help|-h)
33
+ echo "Usage: shipwright status [--json]"
34
+ echo ""
35
+ echo "Options:"
36
+ echo " --json Output structured JSON instead of formatted text"
37
+ echo " --help Show this help message"
38
+ exit 0
39
+ ;;
40
+ *) echo "Unknown option: $1" >&2; exit 1 ;;
41
+ esac
42
+ done
43
+
44
+ # ─── JSON Output Mode ─────────────────────────────────────────────────────────
45
+ if [[ "$JSON_OUTPUT" == "true" ]]; then
46
+ if ! command -v jq &>/dev/null; then
47
+ echo "Error: jq is required for --json output" >&2
48
+ exit 1
49
+ fi
50
+
51
+ # -- tmux windows --
52
+ WINDOWS_JSON="[]"
53
+ if command -v tmux &>/dev/null; then
54
+ WINDOWS_JSON=$(tmux list-windows -a -F '#{session_name}:#{window_index}|#{window_name}|#{window_panes}|#{window_active}' 2>/dev/null | \
55
+ while IFS='|' read -r sw wn pc act; do
56
+ is_claude="false"
57
+ echo "$wn" | grep -qi "claude" && is_claude="true"
58
+ is_active="false"
59
+ [[ "$act" == "1" ]] && is_active="true"
60
+ printf '%s\n' "{\"session_window\":\"$sw\",\"name\":\"$wn\",\"panes\":$pc,\"active\":$is_active,\"claude\":$is_claude}"
61
+ done | jq -s '.' 2>/dev/null) || WINDOWS_JSON="[]"
62
+ fi
63
+
64
+ # -- team configs --
65
+ TEAMS_JSON="[]"
66
+ _teams_dir="${HOME}/.claude/teams"
67
+ if [[ -d "$_teams_dir" ]]; then
68
+ TEAMS_JSON=$(find "$_teams_dir" -mindepth 1 -maxdepth 1 -type d 2>/dev/null | sort | \
69
+ while IFS= read -r td; do
70
+ [[ -z "$td" ]] && continue
71
+ tn="$(basename "$td")"
72
+ cf="${td}/config.json"
73
+ if [[ -f "$cf" ]]; then
74
+ mc=$(jq '.members | length' "$cf" 2>/dev/null || echo 0)
75
+ printf '%s\n' "{\"name\":\"$tn\",\"members\":$mc,\"has_config\":true}"
76
+ else
77
+ printf '%s\n' "{\"name\":\"$tn\",\"members\":0,\"has_config\":false}"
78
+ fi
79
+ done | jq -s '.' 2>/dev/null) || TEAMS_JSON="[]"
80
+ fi
81
+
82
+ # -- task lists --
83
+ TASKS_JSON="[]"
84
+ _tasks_dir="${HOME}/.claude/tasks"
85
+ if [[ -d "$_tasks_dir" ]]; then
86
+ _tasks_tmp=""
87
+ while IFS= read -r td; do
88
+ [[ -z "$td" ]] && continue
89
+ tn="$(basename "$td")"
90
+ _total=0; _completed=0; _in_progress=0; _pending=0
91
+ while IFS= read -r tf; do
92
+ [[ -z "$tf" ]] && continue
93
+ _total=$((_total + 1))
94
+ _st=$(jq -r '.status // "unknown"' "$tf" 2>/dev/null || echo "unknown")
95
+ case "$_st" in
96
+ completed) _completed=$((_completed + 1)) ;;
97
+ in_progress) _in_progress=$((_in_progress + 1)) ;;
98
+ pending) _pending=$((_pending + 1)) ;;
99
+ esac
100
+ done < <(find "$td" -type f -name '*.json' 2>/dev/null)
101
+ _tasks_tmp="${_tasks_tmp}{\"team\":\"$tn\",\"total\":$_total,\"completed\":$_completed,\"in_progress\":$_in_progress,\"pending\":$_pending}
102
+ "
103
+ done < <(find "$_tasks_dir" -mindepth 1 -maxdepth 1 -type d 2>/dev/null | sort)
104
+ if [[ -n "$_tasks_tmp" ]]; then
105
+ TASKS_JSON=$(printf '%s' "$_tasks_tmp" | jq -s '.' 2>/dev/null) || TASKS_JSON="[]"
106
+ fi
107
+ fi
108
+
109
+ # -- daemon --
110
+ DAEMON_JSON="null"
111
+ _state_file="${HOME}/.shipwright/daemon-state.json"
112
+ _pid_file="${HOME}/.shipwright/daemon.pid"
113
+ if [[ -f "$_state_file" ]]; then
114
+ _d_running="false"
115
+ _d_pid="null"
116
+ if [[ -f "$_pid_file" ]]; then
117
+ _d_pid_val=$(cat "$_pid_file" 2>/dev/null || true)
118
+ if [[ -n "$_d_pid_val" ]] && kill -0 "$_d_pid_val" 2>/dev/null; then
119
+ _d_running="true"
120
+ _d_pid="$_d_pid_val"
121
+ fi
122
+ fi
123
+ _active=$(jq -c '.active_jobs // []' "$_state_file" 2>/dev/null || echo "[]")
124
+ _queued=$(jq -c '.queued // []' "$_state_file" 2>/dev/null || echo "[]")
125
+ _completed=$(jq -c '[.completed // [] | reverse | .[:20][]]' "$_state_file" 2>/dev/null || echo "[]")
126
+ _started_at=$(jq -r '.started_at // null' "$_state_file" 2>/dev/null || echo "null")
127
+ _last_poll=$(jq -r '.last_poll // null' "$_state_file" 2>/dev/null || echo "null")
128
+ DAEMON_JSON=$(jq -n \
129
+ --argjson running "$_d_running" \
130
+ --argjson pid "$_d_pid" \
131
+ --argjson active_jobs "$_active" \
132
+ --argjson queued "$_queued" \
133
+ --argjson recent_completions "$_completed" \
134
+ --arg started_at "$_started_at" \
135
+ --arg last_poll "$_last_poll" \
136
+ '{running:$running, pid:$pid, started_at:$started_at, last_poll:$last_poll, active_jobs:$active_jobs, queued:$queued, recent_completions:$recent_completions}') || DAEMON_JSON="null"
137
+ fi
138
+
139
+ # -- issue tracker --
140
+ TRACKER_JSON="null"
141
+ _tracker_cfg="${HOME}/.shipwright/tracker-config.json"
142
+ if [[ -f "$_tracker_cfg" ]]; then
143
+ _provider=$(jq -r '.provider // "none"' "$_tracker_cfg" 2>/dev/null || echo "none")
144
+ if [[ "$_provider" != "none" && -n "$_provider" ]]; then
145
+ _url="null"
146
+ [[ "$_provider" == "jira" ]] && _url=$(jq -r '.jira.base_url // null' "$_tracker_cfg" 2>/dev/null || echo "null")
147
+ TRACKER_JSON=$(jq -n --arg provider "$_provider" --arg url "$_url" '{provider:$provider, url:$url}') || TRACKER_JSON="null"
148
+ fi
149
+ fi
150
+
151
+ # -- heartbeats --
152
+ HEARTBEATS_JSON="[]"
153
+ _hb_dir="${HOME}/.shipwright/heartbeats"
154
+ if [[ -d "$_hb_dir" ]]; then
155
+ HEARTBEATS_JSON=$(find "$_hb_dir" -name '*.json' -type f 2>/dev/null | \
156
+ while IFS= read -r hf; do
157
+ [[ -z "$hf" ]] && continue
158
+ _jid="$(basename "$hf" .json)"
159
+ _stage=$(jq -r '.stage // "unknown"' "$hf" 2>/dev/null || echo "unknown")
160
+ _ts=$(jq -r '.timestamp // null' "$hf" 2>/dev/null || echo "null")
161
+ _iter=$(jq -r '.iteration // 0' "$hf" 2>/dev/null || echo "0")
162
+ printf '%s\n' "{\"job_id\":\"$_jid\",\"stage\":\"$_stage\",\"timestamp\":\"$_ts\",\"iteration\":$_iter}"
163
+ done | jq -s '.' 2>/dev/null) || HEARTBEATS_JSON="[]"
164
+ fi
165
+
166
+ # -- remote machines --
167
+ MACHINES_JSON="[]"
168
+ _machines_file="${HOME}/.shipwright/machines.json"
169
+ if [[ -f "$_machines_file" ]]; then
170
+ MACHINES_JSON=$(jq -c '.machines // []' "$_machines_file" 2>/dev/null) || MACHINES_JSON="[]"
171
+ fi
172
+
173
+ # -- connected developers --
174
+ DEVELOPERS_JSON="null"
175
+ _team_cfg="${HOME}/.shipwright/team-config.json"
176
+ if [[ -f "$_team_cfg" ]]; then
177
+ _dash_url=$(jq -r '.dashboard_url // ""' "$_team_cfg" 2>/dev/null || true)
178
+ if [[ -n "$_dash_url" ]] && command -v curl &>/dev/null; then
179
+ _api_resp=$(curl -s --max-time 3 "${_dash_url}/api/status" 2>/dev/null || echo "")
180
+ if [[ -n "$_api_resp" ]] && echo "$_api_resp" | jq empty 2>/dev/null; then
181
+ _online=$(echo "$_api_resp" | jq '.total_online // 0' 2>/dev/null || echo "0")
182
+ _devs=$(echo "$_api_resp" | jq -c '.developers // []' 2>/dev/null || echo "[]")
183
+ DEVELOPERS_JSON=$(jq -n --argjson reachable true --argjson total_online "$_online" --argjson developers "$_devs" \
184
+ '{reachable:$reachable, total_online:$total_online, developers:$developers}') || DEVELOPERS_JSON="null"
185
+ else
186
+ DEVELOPERS_JSON='{"reachable":false,"total_online":0,"developers":[]}'
187
+ fi
188
+ fi
189
+ fi
190
+
191
+ # -- assemble and output --
192
+ jq -n \
193
+ --arg version "$VERSION" \
194
+ --arg timestamp "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
195
+ --argjson tmux_windows "$WINDOWS_JSON" \
196
+ --argjson teams "$TEAMS_JSON" \
197
+ --argjson task_lists "$TASKS_JSON" \
198
+ --argjson daemon "$DAEMON_JSON" \
199
+ --argjson issue_tracker "$TRACKER_JSON" \
200
+ --argjson heartbeats "$HEARTBEATS_JSON" \
201
+ --argjson remote_machines "$MACHINES_JSON" \
202
+ --argjson connected_developers "$DEVELOPERS_JSON" \
203
+ '{
204
+ version: $version,
205
+ timestamp: $timestamp,
206
+ tmux_windows: $tmux_windows,
207
+ teams: $teams,
208
+ task_lists: $task_lists,
209
+ daemon: $daemon,
210
+ issue_tracker: $issue_tracker,
211
+ heartbeats: $heartbeats,
212
+ remote_machines: $remote_machines,
213
+ connected_developers: $connected_developers
214
+ }'
215
+ exit 0
216
+ fi
217
+
27
218
  # ─── Header ──────────────────────────────────────────────────────────────────
28
219
 
29
220
  echo ""