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-ux.sh
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
set -euo pipefail
|
|
7
7
|
trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
|
|
8
8
|
|
|
9
|
-
VERSION="
|
|
9
|
+
VERSION="3.0.0"
|
|
10
10
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
|
|
12
12
|
# ─── Cross-platform compatibility ──────────────────────────────────────────
|
|
@@ -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
|
# ─── Structured Event Log ──────────────────────────────────────────────────
|
|
48
30
|
EVENTS_FILE="${HOME}/.shipwright/events.jsonl"
|
|
49
31
|
|
package/scripts/sw-webhook.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
|
# ─── Cross-platform compatibility ──────────────────────────────────────────
|
|
@@ -16,6 +16,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && 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)
|
|
20
21
|
[[ "$(type -t info 2>/dev/null)" == "function" ]] || info() { echo -e "\033[38;2;0;212;255m\033[1m▸\033[0m $*"; }
|
|
21
22
|
[[ "$(type -t success 2>/dev/null)" == "function" ]] || success() { echo -e "\033[38;2;74;222;128m\033[1m✓\033[0m $*"; }
|
|
@@ -25,29 +26,11 @@ if [[ "$(type -t now_iso 2>/dev/null)" != "function" ]]; then
|
|
|
25
26
|
now_iso() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
|
|
26
27
|
now_epoch() { date +%s; }
|
|
27
28
|
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
29
|
# ─── Constants ──────────────────────────────────────────────────────────────
|
|
47
30
|
SHIPWRIGHT_DIR="$HOME/.shipwright"
|
|
48
31
|
WEBHOOK_SECRET_FILE="$SHIPWRIGHT_DIR/webhook-secret"
|
|
49
32
|
WEBHOOK_EVENTS_FILE="$SHIPWRIGHT_DIR/webhook-events.jsonl"
|
|
50
|
-
WEBHOOK_PORT="${WEBHOOK_PORT
|
|
33
|
+
WEBHOOK_PORT="${WEBHOOK_PORT:-$(_config_get_int "webhook.port" 8765 2>/dev/null || echo 8765)}"
|
|
51
34
|
WEBHOOK_PID_FILE="$SHIPWRIGHT_DIR/webhook.pid"
|
|
52
35
|
WEBHOOK_LOG="$SHIPWRIGHT_DIR/webhook.log"
|
|
53
36
|
|
|
@@ -141,7 +124,7 @@ process_webhook_event() {
|
|
|
141
124
|
|
|
142
125
|
# Check if nc (netcat) is available
|
|
143
126
|
check_nc() {
|
|
144
|
-
if ! command -v nc
|
|
127
|
+
if ! command -v nc >/dev/null 2>&1; then
|
|
145
128
|
error "netcat (nc) is required but not installed"
|
|
146
129
|
echo -e " ${DIM}brew install netcat${RESET} (macOS)"
|
|
147
130
|
echo -e " ${DIM}sudo apt install netcat-openbsd${RESET} (Ubuntu/Debian)"
|
|
@@ -254,17 +237,20 @@ webhook_server_bash() {
|
|
|
254
237
|
local method path protocol
|
|
255
238
|
read -r method path protocol <<< "$request_line"
|
|
256
239
|
|
|
257
|
-
# Read headers until blank line
|
|
258
|
-
local -A headers
|
|
240
|
+
# Read headers until blank line (Bash 3.2 compatible — no associative arrays)
|
|
259
241
|
local header_line content_length=0
|
|
242
|
+
local hdr_signature="" hdr_event_type=""
|
|
260
243
|
while read -r -u 3 -t 0.1 header_line; do
|
|
261
244
|
[[ -z "$header_line" || "$header_line" == $'\r' ]] && break
|
|
262
245
|
local key="${header_line%%:*}"
|
|
263
246
|
local value="${header_line#*:}"
|
|
264
247
|
value="${value#[[:space:]]}"
|
|
265
248
|
value="${value%$'\r'}"
|
|
266
|
-
|
|
267
|
-
|
|
249
|
+
local key_lower
|
|
250
|
+
key_lower=$(printf '%s' "$key" | tr '[:upper:]' '[:lower:]')
|
|
251
|
+
[[ "$key_lower" == "content-length" ]] && content_length="$value"
|
|
252
|
+
[[ "$key_lower" == "x-hub-signature-256" ]] && hdr_signature="$value"
|
|
253
|
+
[[ "$key_lower" == "x-github-event" ]] && hdr_event_type="$value"
|
|
268
254
|
done 2>/dev/null || true
|
|
269
255
|
|
|
270
256
|
# Read body if content-length > 0
|
|
@@ -275,8 +261,8 @@ webhook_server_bash() {
|
|
|
275
261
|
|
|
276
262
|
# Process webhook if method is POST
|
|
277
263
|
if [[ "$method" == "POST" && "$path" == "/webhook" ]]; then
|
|
278
|
-
local signature="$
|
|
279
|
-
local event_type="$
|
|
264
|
+
local signature="$hdr_signature"
|
|
265
|
+
local event_type="$hdr_event_type"
|
|
280
266
|
|
|
281
267
|
if validate_webhook_signature "$body" "$signature"; then
|
|
282
268
|
if process_webhook_event "$body" "$event_type"; then
|
|
@@ -331,7 +317,7 @@ cmd_setup() {
|
|
|
331
317
|
info "Webhook endpoint: http://localhost:${WEBHOOK_PORT}/webhook"
|
|
332
318
|
|
|
333
319
|
# Check if gh CLI is available
|
|
334
|
-
if ! command -v gh
|
|
320
|
+
if ! command -v gh >/dev/null 2>&1; then
|
|
335
321
|
error "GitHub CLI (gh) is required but not installed"
|
|
336
322
|
return 1
|
|
337
323
|
fi
|
|
@@ -345,7 +331,7 @@ cmd_setup() {
|
|
|
345
331
|
-f "url=http://localhost:${WEBHOOK_PORT}/webhook" \
|
|
346
332
|
-F "events=issues" \
|
|
347
333
|
-f "config[content_type]=json" \
|
|
348
|
-
-f "config[secret]=${secret}" 2>&1); then
|
|
334
|
+
-f "config[secret]=${secret}" --timeout 30 2>&1); then
|
|
349
335
|
|
|
350
336
|
local hook_id
|
|
351
337
|
hook_id=$(echo "$webhook_response" | jq -r '.id // empty' 2>/dev/null || true)
|
|
@@ -403,7 +389,7 @@ cmd_test() {
|
|
|
403
389
|
return 1
|
|
404
390
|
fi
|
|
405
391
|
|
|
406
|
-
if ! command -v gh
|
|
392
|
+
if ! command -v gh >/dev/null 2>&1; then
|
|
407
393
|
error "GitHub CLI (gh) is required"
|
|
408
394
|
return 1
|
|
409
395
|
fi
|
|
@@ -440,7 +426,7 @@ cmd_test() {
|
|
|
440
426
|
if gh api "repos/${org_repo}/hooks/tests" \
|
|
441
427
|
-H "Accept: application/vnd.github+json" \
|
|
442
428
|
-X POST \
|
|
443
|
-
2>&1 | grep -q "Test hook sent"; then
|
|
429
|
+
--timeout 30 2>&1 | grep -q "Test hook sent"; then
|
|
444
430
|
success "Test ping sent to GitHub"
|
|
445
431
|
else
|
|
446
432
|
warn "Could not send test via GitHub API, but payload is valid:"
|
|
@@ -534,7 +520,7 @@ cmd_secret() {
|
|
|
534
520
|
echo "$new_secret" > "$WEBHOOK_SECRET_FILE"
|
|
535
521
|
chmod 600 "$WEBHOOK_SECRET_FILE"
|
|
536
522
|
success "Webhook secret regenerated"
|
|
537
|
-
info "
|
|
523
|
+
info "Secret: ${new_secret:0:8}... (full value in ${WEBHOOK_SECRET_FILE})"
|
|
538
524
|
;;
|
|
539
525
|
*)
|
|
540
526
|
error "Unknown secret action: $action"
|
package/scripts/sw-widgets.sh
CHANGED
|
@@ -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="
|
|
11
|
+
VERSION="3.0.0"
|
|
12
12
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
13
13
|
REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
14
14
|
|
|
@@ -29,24 +29,6 @@ if [[ "$(type -t now_iso 2>/dev/null)" != "function" ]]; then
|
|
|
29
29
|
now_iso() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
|
|
30
30
|
now_epoch() { date +%s; }
|
|
31
31
|
fi
|
|
32
|
-
if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
|
|
33
|
-
emit_event() {
|
|
34
|
-
local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
|
|
35
|
-
local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
|
|
36
|
-
while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
|
|
37
|
-
echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
|
|
38
|
-
}
|
|
39
|
-
fi
|
|
40
|
-
CYAN="${CYAN:-\033[38;2;0;212;255m}"
|
|
41
|
-
PURPLE="${PURPLE:-\033[38;2;124;58;237m}"
|
|
42
|
-
BLUE="${BLUE:-\033[38;2;0;102;255m}"
|
|
43
|
-
GREEN="${GREEN:-\033[38;2;74;222;128m}"
|
|
44
|
-
YELLOW="${YELLOW:-\033[38;2;250;204;21m}"
|
|
45
|
-
RED="${RED:-\033[38;2;248;113;113m}"
|
|
46
|
-
DIM="${DIM:-\033[2m}"
|
|
47
|
-
BOLD="${BOLD:-\033[1m}"
|
|
48
|
-
RESET="${RESET:-\033[0m}"
|
|
49
|
-
|
|
50
32
|
# ─── Configuration ─────────────────────────────────────────────────────────
|
|
51
33
|
CONFIG_DIR="${HOME}/.shipwright"
|
|
52
34
|
CONFIG_FILE="${CONFIG_DIR}/widgets-config.json"
|
|
@@ -301,8 +283,8 @@ cmd_slack() {
|
|
|
301
283
|
)
|
|
302
284
|
|
|
303
285
|
# Send to webhook
|
|
304
|
-
if command -v curl
|
|
305
|
-
response=$(curl -s -X POST "$webhook_url" \
|
|
286
|
+
if command -v curl >/dev/null 2>&1; then
|
|
287
|
+
response=$(curl -s --connect-timeout 10 --max-time 30 -X POST "$webhook_url" \
|
|
306
288
|
-H 'Content-Type: application/json' \
|
|
307
289
|
-d "$message_json" 2>&1)
|
|
308
290
|
|
package/scripts/sw-worktree.sh
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
# ║ Each agent gets its own worktree so parallel agents don't clobber ║
|
|
6
6
|
# ║ each other's files. Worktrees live in .worktrees/ relative to root. ║
|
|
7
7
|
# ╚═══════════════════════════════════════════════════════════════════════════╝
|
|
8
|
-
VERSION="
|
|
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
|
|
|
@@ -23,24 +23,6 @@ if [[ "$(type -t now_iso 2>/dev/null)" != "function" ]]; then
|
|
|
23
23
|
now_iso() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
|
|
24
24
|
now_epoch() { date +%s; }
|
|
25
25
|
fi
|
|
26
|
-
if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
|
|
27
|
-
emit_event() {
|
|
28
|
-
local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
|
|
29
|
-
local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
|
|
30
|
-
while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
|
|
31
|
-
echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
|
|
32
|
-
}
|
|
33
|
-
fi
|
|
34
|
-
CYAN="${CYAN:-\033[38;2;0;212;255m}"
|
|
35
|
-
PURPLE="${PURPLE:-\033[38;2;124;58;237m}"
|
|
36
|
-
BLUE="${BLUE:-\033[38;2;0;102;255m}"
|
|
37
|
-
GREEN="${GREEN:-\033[38;2;74;222;128m}"
|
|
38
|
-
YELLOW="${YELLOW:-\033[38;2;250;204;21m}"
|
|
39
|
-
RED="${RED:-\033[38;2;248;113;113m}"
|
|
40
|
-
DIM="${DIM:-\033[2m}"
|
|
41
|
-
BOLD="${BOLD:-\033[1m}"
|
|
42
|
-
RESET="${RESET:-\033[0m}"
|
|
43
|
-
|
|
44
26
|
# ─── Repo root ─────────────────────────────────────────────────────────────
|
|
45
27
|
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null)" || {
|
|
46
28
|
error "Not inside a git repository."
|
|
@@ -122,7 +104,7 @@ worktree_list() {
|
|
|
122
104
|
|
|
123
105
|
printf " ${CYAN}%-16s${RESET} ${PURPLE}%-22s${RESET} %b ${DIM}.worktrees/%s/${RESET}\n" \
|
|
124
106
|
"$name" "$branch" "$status_str" "$name"
|
|
125
|
-
((found
|
|
107
|
+
found=$((found + 1))
|
|
126
108
|
done
|
|
127
109
|
|
|
128
110
|
if [[ $found -eq 0 ]]; then
|
|
@@ -167,8 +149,8 @@ worktree_sync_all() {
|
|
|
167
149
|
[[ -d "$dir" ]] || continue
|
|
168
150
|
local name
|
|
169
151
|
name="$(basename "$dir")"
|
|
170
|
-
worktree_sync "$name" || ((failed
|
|
171
|
-
((count
|
|
152
|
+
worktree_sync "$name" || failed=$((failed + 1))
|
|
153
|
+
count=$((count + 1))
|
|
172
154
|
done
|
|
173
155
|
|
|
174
156
|
echo ""
|
|
@@ -185,7 +167,7 @@ worktree_merge() {
|
|
|
185
167
|
local current_branch
|
|
186
168
|
current_branch="$(git branch --show-current)"
|
|
187
169
|
|
|
188
|
-
if ! git rev-parse --verify "$branch"
|
|
170
|
+
if ! git rev-parse --verify "$branch" >/dev/null 2>&1; then
|
|
189
171
|
error "Branch '$branch' does not exist."
|
|
190
172
|
return 1
|
|
191
173
|
fi
|
|
@@ -219,7 +201,7 @@ worktree_merge_all() {
|
|
|
219
201
|
echo -e " ${DIM}Resolve the conflict, then re-run: shipwright worktree merge-all${RESET}"
|
|
220
202
|
return 1
|
|
221
203
|
}
|
|
222
|
-
((count
|
|
204
|
+
count=$((count + 1))
|
|
223
205
|
done
|
|
224
206
|
|
|
225
207
|
echo ""
|
|
@@ -234,7 +216,9 @@ worktree_remove() {
|
|
|
234
216
|
if [[ -d "$worktree_path" ]]; then
|
|
235
217
|
git worktree remove "$worktree_path" --force 2>/dev/null || {
|
|
236
218
|
warn "Could not cleanly remove worktree $name, forcing..."
|
|
237
|
-
|
|
219
|
+
if [[ -n "$worktree_path" && "$worktree_path" == "$WORKTREE_DIR/"* ]]; then
|
|
220
|
+
rm -rf "$worktree_path"
|
|
221
|
+
fi
|
|
238
222
|
git worktree prune 2>/dev/null || true
|
|
239
223
|
}
|
|
240
224
|
fi
|
|
@@ -257,7 +241,7 @@ worktree_cleanup() {
|
|
|
257
241
|
local name
|
|
258
242
|
name="$(basename "$dir")"
|
|
259
243
|
worktree_remove "$name"
|
|
260
|
-
((count
|
|
244
|
+
count=$((count + 1))
|
|
261
245
|
done
|
|
262
246
|
|
|
263
247
|
# Prune stale worktree references
|
|
@@ -302,7 +286,7 @@ worktree_status() {
|
|
|
302
286
|
|
|
303
287
|
printf " ${CYAN}%-16s${RESET} ${PURPLE}%-22s${RESET} ${GREEN}%s ahead${RESET}, ${YELLOW}%s behind${RESET}%b\n" \
|
|
304
288
|
"$name" "$branch" "$ahead" "$behind" "$dirty"
|
|
305
|
-
((found
|
|
289
|
+
found=$((found + 1))
|
|
306
290
|
done
|
|
307
291
|
|
|
308
292
|
if [[ $found -eq 0 ]]; then
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Updates homebrew/shipwright.rb with SHA256 hashes from the release artifacts.
|
|
3
|
+
# Downloads each tarball, computes SHA256, and updates the formula in-place.
|
|
4
|
+
#
|
|
5
|
+
# Usage: scripts/update-homebrew-sha.sh <version-tag>
|
|
6
|
+
# Example: scripts/update-homebrew-sha.sh v0.4.2
|
|
7
|
+
#
|
|
8
|
+
# Run after release artifacts are uploaded to GitHub Releases.
|
|
9
|
+
set -euo pipefail
|
|
10
|
+
|
|
11
|
+
VERSION="3.0.0"
|
|
12
|
+
VERSION_NUM="${VERSION#v}"
|
|
13
|
+
REPO="${SHIPWRIGHT_GITHUB_REPO:-sethdford/shipwright}"
|
|
14
|
+
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
15
|
+
FORMULA="${REPO_ROOT}/homebrew/shipwright.rb"
|
|
16
|
+
BASE_URL="https://github.com/${REPO}/releases/download/${VERSION}"
|
|
17
|
+
|
|
18
|
+
TMPDIR="${TMPDIR:-/tmp}/shipwright-sha-$$"
|
|
19
|
+
mkdir -p "$TMPDIR"
|
|
20
|
+
trap 'rm -rf "$TMPDIR"' EXIT
|
|
21
|
+
|
|
22
|
+
# Download each artifact and compute SHA256
|
|
23
|
+
sha_darwin_arm64=""
|
|
24
|
+
sha_darwin_x86_64=""
|
|
25
|
+
sha_linux_x86_64=""
|
|
26
|
+
|
|
27
|
+
for platform in darwin-arm64 darwin-x86_64 linux-x86_64; do
|
|
28
|
+
filename="shipwright-${platform}.tar.gz"
|
|
29
|
+
url="${BASE_URL}/${filename}"
|
|
30
|
+
dest="${TMPDIR}/${filename}"
|
|
31
|
+
echo "Downloading ${url}..."
|
|
32
|
+
if ! curl -sfL -o "$dest" "$url"; then
|
|
33
|
+
echo "ERROR: Failed to download $url" >&2
|
|
34
|
+
exit 1
|
|
35
|
+
fi
|
|
36
|
+
if command -v shasum >/dev/null 2>&1; then
|
|
37
|
+
sha=$(shasum -a 256 "$dest" | awk '{print $1}')
|
|
38
|
+
else
|
|
39
|
+
sha=$(sha256sum "$dest" | awk '{print $1}')
|
|
40
|
+
fi
|
|
41
|
+
case "$platform" in
|
|
42
|
+
darwin-arm64) sha_darwin_arm64="$sha" ;;
|
|
43
|
+
darwin-x86_64) sha_darwin_x86_64="$sha" ;;
|
|
44
|
+
linux-x86_64) sha_linux_x86_64="$sha" ;;
|
|
45
|
+
esac
|
|
46
|
+
echo " ${platform}: ${sha}"
|
|
47
|
+
done
|
|
48
|
+
|
|
49
|
+
# Update formula: version and SHA256 values
|
|
50
|
+
# sed -i '' on macOS, sed -i on Linux
|
|
51
|
+
if [[ "$(uname -s)" == "Darwin" ]]; then
|
|
52
|
+
sed -i '' "s|version \"[^\"]*\"|version \"${VERSION_NUM}\"|g" "$FORMULA"
|
|
53
|
+
sed -i '' "s|sha256 \"PLACEHOLDER_DARWIN_ARM64_SHA256\"|sha256 \"${sha_darwin_arm64}\"|g" "$FORMULA"
|
|
54
|
+
sed -i '' "s|sha256 \"PLACEHOLDER_DARWIN_X86_64_SHA256\"|sha256 \"${sha_darwin_x86_64}\"|g" "$FORMULA"
|
|
55
|
+
sed -i '' "s|sha256 \"PLACEHOLDER_LINUX_X86_64_SHA256\"|sha256 \"${sha_linux_x86_64}\"|g" "$FORMULA"
|
|
56
|
+
else
|
|
57
|
+
sed -i "s|version \"[^\"]*\"|version \"${VERSION_NUM}\"|g" "$FORMULA"
|
|
58
|
+
sed -i "s|sha256 \"PLACEHOLDER_DARWIN_ARM64_SHA256\"|sha256 \"${sha_darwin_arm64}\"|g" "$FORMULA"
|
|
59
|
+
sed -i "s|sha256 \"PLACEHOLDER_DARWIN_X86_64_SHA256\"|sha256 \"${sha_darwin_x86_64}\"|g" "$FORMULA"
|
|
60
|
+
sed -i "s|sha256 \"PLACEHOLDER_LINUX_X86_64_SHA256\"|sha256 \"${sha_linux_x86_64}\"|g" "$FORMULA"
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
echo ""
|
|
64
|
+
echo "Updated $FORMULA for v${VERSION_NUM}:"
|
|
65
|
+
echo " darwin-arm64: ${sha_darwin_arm64}"
|
|
66
|
+
echo " darwin-x86_64: ${sha_darwin_x86_64}"
|
|
67
|
+
echo " linux-x86_64: ${sha_linux_x86_64}"
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "tdd",
|
|
3
|
+
"description": "Test-first pipeline: plan → design → generate tests → build → test → review → PR",
|
|
4
|
+
"defaults": { "test_cmd": "npm test", "model": "sonnet", "agents": 1 },
|
|
5
|
+
"tdd": true,
|
|
6
|
+
"intelligence": {
|
|
7
|
+
"adversarial_enabled": true,
|
|
8
|
+
"architecture_enabled": true,
|
|
9
|
+
"simulation_enabled": true
|
|
10
|
+
},
|
|
11
|
+
"stages": [
|
|
12
|
+
{ "id": "intake", "enabled": true, "gate": "auto", "config": {} },
|
|
13
|
+
{
|
|
14
|
+
"id": "plan",
|
|
15
|
+
"enabled": true,
|
|
16
|
+
"gate": "approve",
|
|
17
|
+
"config": { "model": "opus" }
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"id": "design",
|
|
21
|
+
"enabled": true,
|
|
22
|
+
"gate": "approve",
|
|
23
|
+
"config": { "model": "opus" }
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"id": "build",
|
|
27
|
+
"enabled": true,
|
|
28
|
+
"gate": "auto",
|
|
29
|
+
"config": { "max_iterations": 20, "audit": true, "quality_gates": true }
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"id": "test",
|
|
33
|
+
"enabled": true,
|
|
34
|
+
"gate": "auto",
|
|
35
|
+
"config": { "coverage_min": 80 }
|
|
36
|
+
},
|
|
37
|
+
{ "id": "review", "enabled": true, "gate": "approve", "config": {} },
|
|
38
|
+
{
|
|
39
|
+
"id": "compound_quality",
|
|
40
|
+
"enabled": true,
|
|
41
|
+
"gate": "auto",
|
|
42
|
+
"config": {
|
|
43
|
+
"adversarial": true,
|
|
44
|
+
"negative": true,
|
|
45
|
+
"e2e": true,
|
|
46
|
+
"dod_audit": true,
|
|
47
|
+
"max_cycles": 3,
|
|
48
|
+
"audit_intensity": "auto",
|
|
49
|
+
"compound_quality_blocking": true
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"id": "pr",
|
|
54
|
+
"enabled": true,
|
|
55
|
+
"gate": "approve",
|
|
56
|
+
"config": { "wait_ci": false }
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"id": "merge",
|
|
60
|
+
"enabled": true,
|
|
61
|
+
"gate": "approve",
|
|
62
|
+
"config": {
|
|
63
|
+
"merge_method": "squash",
|
|
64
|
+
"wait_ci_timeout_s": 600,
|
|
65
|
+
"auto_delete_branch": true,
|
|
66
|
+
"auto_merge": false,
|
|
67
|
+
"auto_approve": false
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
{ "id": "deploy", "enabled": false, "gate": "approve", "config": {} }
|
|
71
|
+
]
|
|
72
|
+
}
|