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.
- package/README.md +95 -28
- package/completions/_shipwright +1 -1
- package/completions/shipwright.bash +3 -8
- package/completions/shipwright.fish +1 -1
- package/config/defaults.json +111 -0
- package/config/event-schema.json +81 -0
- package/config/policy.json +155 -2
- package/config/policy.schema.json +162 -1
- package/dashboard/coverage/coverage-summary.json +14 -0
- package/dashboard/public/index.html +1 -1
- package/dashboard/server.ts +306 -17
- package/dashboard/src/components/charts/bar.test.ts +79 -0
- package/dashboard/src/components/charts/donut.test.ts +68 -0
- package/dashboard/src/components/charts/pipeline-rail.test.ts +117 -0
- package/dashboard/src/components/charts/sparkline.test.ts +125 -0
- package/dashboard/src/core/api.test.ts +309 -0
- package/dashboard/src/core/helpers.test.ts +301 -0
- package/dashboard/src/core/router.test.ts +307 -0
- package/dashboard/src/core/router.ts +7 -0
- package/dashboard/src/core/sse.test.ts +144 -0
- package/dashboard/src/views/metrics.test.ts +186 -0
- package/dashboard/src/views/overview.test.ts +173 -0
- package/dashboard/src/views/pipelines.test.ts +183 -0
- package/dashboard/src/views/team.test.ts +253 -0
- package/dashboard/vitest.config.ts +14 -5
- package/docs/TIPS.md +1 -1
- package/docs/patterns/README.md +1 -1
- package/package.json +15 -5
- package/scripts/adapters/docker-deploy.sh +1 -1
- package/scripts/adapters/tmux-adapter.sh +11 -1
- package/scripts/adapters/wezterm-adapter.sh +1 -1
- package/scripts/check-version-consistency.sh +1 -1
- package/scripts/lib/architecture.sh +126 -0
- package/scripts/lib/bootstrap.sh +75 -0
- package/scripts/lib/compat.sh +89 -6
- package/scripts/lib/config.sh +91 -0
- package/scripts/lib/daemon-adaptive.sh +3 -3
- package/scripts/lib/daemon-dispatch.sh +39 -16
- package/scripts/lib/daemon-health.sh +1 -1
- package/scripts/lib/daemon-patrol.sh +24 -12
- package/scripts/lib/daemon-poll.sh +37 -25
- package/scripts/lib/daemon-state.sh +115 -23
- package/scripts/lib/daemon-triage.sh +30 -8
- package/scripts/lib/fleet-failover.sh +63 -0
- package/scripts/lib/helpers.sh +30 -6
- package/scripts/lib/pipeline-detection.sh +2 -2
- package/scripts/lib/pipeline-github.sh +9 -9
- package/scripts/lib/pipeline-intelligence.sh +85 -35
- package/scripts/lib/pipeline-quality-checks.sh +16 -16
- package/scripts/lib/pipeline-quality.sh +1 -1
- package/scripts/lib/pipeline-stages.sh +242 -28
- package/scripts/lib/pipeline-state.sh +40 -4
- package/scripts/lib/test-helpers.sh +247 -0
- package/scripts/postinstall.mjs +3 -11
- package/scripts/sw +10 -4
- package/scripts/sw-activity.sh +1 -11
- package/scripts/sw-adaptive.sh +109 -85
- package/scripts/sw-adversarial.sh +4 -14
- package/scripts/sw-architecture-enforcer.sh +1 -11
- package/scripts/sw-auth.sh +8 -17
- package/scripts/sw-autonomous.sh +111 -49
- package/scripts/sw-changelog.sh +1 -11
- package/scripts/sw-checkpoint.sh +144 -20
- package/scripts/sw-ci.sh +2 -12
- package/scripts/sw-cleanup.sh +13 -17
- package/scripts/sw-code-review.sh +16 -36
- package/scripts/sw-connect.sh +5 -12
- package/scripts/sw-context.sh +9 -26
- package/scripts/sw-cost.sh +6 -16
- package/scripts/sw-daemon.sh +75 -70
- package/scripts/sw-dashboard.sh +57 -17
- package/scripts/sw-db.sh +506 -15
- package/scripts/sw-decompose.sh +1 -11
- package/scripts/sw-deps.sh +15 -25
- package/scripts/sw-developer-simulation.sh +1 -11
- package/scripts/sw-discovery.sh +112 -30
- package/scripts/sw-doc-fleet.sh +7 -17
- package/scripts/sw-docs-agent.sh +6 -16
- package/scripts/sw-docs.sh +4 -12
- package/scripts/sw-doctor.sh +134 -43
- package/scripts/sw-dora.sh +11 -19
- package/scripts/sw-durable.sh +35 -52
- package/scripts/sw-e2e-orchestrator.sh +11 -27
- package/scripts/sw-eventbus.sh +115 -115
- package/scripts/sw-evidence.sh +748 -0
- package/scripts/sw-feedback.sh +3 -13
- package/scripts/sw-fix.sh +2 -20
- package/scripts/sw-fleet-discover.sh +1 -11
- package/scripts/sw-fleet-viz.sh +10 -18
- package/scripts/sw-fleet.sh +13 -17
- package/scripts/sw-github-app.sh +6 -16
- package/scripts/sw-github-checks.sh +1 -11
- package/scripts/sw-github-deploy.sh +1 -11
- package/scripts/sw-github-graphql.sh +2 -12
- package/scripts/sw-guild.sh +1 -11
- package/scripts/sw-heartbeat.sh +49 -12
- package/scripts/sw-hygiene.sh +45 -43
- package/scripts/sw-incident.sh +284 -67
- package/scripts/sw-init.sh +35 -37
- package/scripts/sw-instrument.sh +1 -11
- package/scripts/sw-intelligence.sh +362 -51
- package/scripts/sw-jira.sh +5 -14
- package/scripts/sw-launchd.sh +2 -12
- package/scripts/sw-linear.sh +8 -17
- package/scripts/sw-logs.sh +4 -12
- package/scripts/sw-loop.sh +641 -90
- package/scripts/sw-memory.sh +243 -17
- package/scripts/sw-mission-control.sh +2 -12
- package/scripts/sw-model-router.sh +73 -34
- package/scripts/sw-otel.sh +11 -21
- package/scripts/sw-oversight.sh +1 -11
- package/scripts/sw-patrol-meta.sh +5 -11
- package/scripts/sw-pipeline-composer.sh +7 -17
- package/scripts/sw-pipeline-vitals.sh +1 -11
- package/scripts/sw-pipeline.sh +478 -122
- package/scripts/sw-pm.sh +2 -12
- package/scripts/sw-pr-lifecycle.sh +203 -29
- package/scripts/sw-predictive.sh +16 -22
- package/scripts/sw-prep.sh +6 -16
- package/scripts/sw-ps.sh +1 -11
- package/scripts/sw-public-dashboard.sh +2 -12
- package/scripts/sw-quality.sh +77 -10
- package/scripts/sw-reaper.sh +1 -11
- package/scripts/sw-recruit.sh +15 -25
- package/scripts/sw-regression.sh +11 -21
- package/scripts/sw-release-manager.sh +19 -28
- package/scripts/sw-release.sh +8 -16
- package/scripts/sw-remote.sh +1 -11
- package/scripts/sw-replay.sh +48 -44
- package/scripts/sw-retro.sh +70 -92
- package/scripts/sw-review-rerun.sh +220 -0
- package/scripts/sw-scale.sh +109 -32
- package/scripts/sw-security-audit.sh +12 -22
- package/scripts/sw-self-optimize.sh +239 -23
- package/scripts/sw-session.sh +3 -13
- package/scripts/sw-setup.sh +8 -18
- package/scripts/sw-standup.sh +5 -15
- package/scripts/sw-status.sh +32 -23
- package/scripts/sw-strategic.sh +129 -13
- package/scripts/sw-stream.sh +1 -11
- package/scripts/sw-swarm.sh +76 -36
- package/scripts/sw-team-stages.sh +10 -20
- package/scripts/sw-templates.sh +4 -14
- package/scripts/sw-testgen.sh +3 -13
- package/scripts/sw-tmux-pipeline.sh +1 -19
- package/scripts/sw-tmux-role-color.sh +0 -10
- package/scripts/sw-tmux-status.sh +3 -11
- package/scripts/sw-tmux.sh +2 -20
- package/scripts/sw-trace.sh +1 -19
- package/scripts/sw-tracker-github.sh +0 -10
- package/scripts/sw-tracker-jira.sh +1 -11
- package/scripts/sw-tracker-linear.sh +1 -11
- package/scripts/sw-tracker.sh +7 -24
- package/scripts/sw-triage.sh +24 -34
- package/scripts/sw-upgrade.sh +5 -23
- package/scripts/sw-ux.sh +1 -19
- package/scripts/sw-webhook.sh +18 -32
- package/scripts/sw-widgets.sh +3 -21
- package/scripts/sw-worktree.sh +11 -27
- package/scripts/update-homebrew-sha.sh +67 -0
- package/templates/pipelines/tdd.json +72 -0
- package/scripts/sw-pipeline.sh.mock +0 -7
package/scripts/sw-templates.sh
CHANGED
|
@@ -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="
|
|
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
|
|
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
|
|
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
|
|
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
|
package/scripts/sw-testgen.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="
|
|
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
|
|
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"
|
|
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="
|
|
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="$(
|
|
123
|
+
mtime="$(file_mtime "$hb")"
|
|
132
124
|
else
|
|
133
125
|
mtime="$(stat -c %Y "$hb" 2>/dev/null || echo 0)"
|
|
134
126
|
fi
|
package/scripts/sw-tmux.sh
CHANGED
|
@@ -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="
|
|
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
|
|
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}"
|
package/scripts/sw-trace.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="
|
|
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) || {
|
package/scripts/sw-tracker.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="
|
|
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"
|
|
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"
|
|
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
|
|
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"
|
package/scripts/sw-triage.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="
|
|
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
|
|
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
|
|
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 '.'
|
|
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'
|
|
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
|
-
|
|
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 '.[] | "
|
|
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" |
|
|
546
|
-
score=$(echo "$line" | cut -d
|
|
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}
|
|
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
|
|
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'
|
|
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='{}'
|
package/scripts/sw-upgrade.sh
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# ╔═══════════════════════════════════════════════════════════════════════════╗
|
|
3
3
|
# ║ sw upgrade — Detect and apply updates from the repo ║
|
|
4
4
|
# ╚═══════════════════════════════════════════════════════════════════════════╝
|
|
5
|
-
VERSION="
|
|
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 "${
|
|
74
|
-
echo "$
|
|
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
|
|
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
|
|