shipwright-cli 2.4.0 → 3.1.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 +16 -11
- package/completions/_shipwright +248 -94
- package/completions/shipwright.bash +68 -19
- package/completions/shipwright.fish +310 -42
- package/config/decision-tiers.json +55 -0
- package/config/defaults.json +111 -0
- package/config/event-schema.json +218 -0
- package/config/policy.json +21 -18
- 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 +7 -9
- 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 +127 -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 +63 -17
- package/scripts/lib/daemon-failure.sh +0 -0
- package/scripts/lib/daemon-health.sh +1 -1
- package/scripts/lib/daemon-patrol.sh +64 -17
- package/scripts/lib/daemon-poll.sh +54 -25
- package/scripts/lib/daemon-state.sh +125 -23
- package/scripts/lib/daemon-triage.sh +31 -9
- package/scripts/lib/decide-autonomy.sh +295 -0
- package/scripts/lib/decide-scoring.sh +228 -0
- package/scripts/lib/decide-signals.sh +462 -0
- package/scripts/lib/fleet-failover.sh +63 -0
- package/scripts/lib/helpers.sh +29 -6
- package/scripts/lib/pipeline-detection.sh +2 -2
- package/scripts/lib/pipeline-github.sh +9 -9
- package/scripts/lib/pipeline-intelligence.sh +105 -38
- package/scripts/lib/pipeline-quality-checks.sh +17 -16
- package/scripts/lib/pipeline-quality.sh +1 -1
- package/scripts/lib/pipeline-stages.sh +440 -59
- package/scripts/lib/pipeline-state.sh +54 -4
- package/scripts/lib/policy.sh +0 -0
- package/scripts/lib/test-helpers.sh +247 -0
- package/scripts/postinstall.mjs +78 -12
- package/scripts/signals/example-collector.sh +36 -0
- package/scripts/sw +17 -7
- 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 +17 -18
- package/scripts/sw-daemon.sh +76 -71
- package/scripts/sw-dashboard.sh +57 -17
- package/scripts/sw-db.sh +524 -26
- package/scripts/sw-decide.sh +685 -0
- 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 +138 -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 +114 -30
- 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 +48 -74
- package/scripts/sw-init.sh +35 -37
- package/scripts/sw-instrument.sh +1 -11
- package/scripts/sw-intelligence.sh +368 -53
- 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 +905 -104
- package/scripts/sw-memory.sh +263 -20
- package/scripts/sw-mission-control.sh +2 -12
- package/scripts/sw-model-router.sh +73 -34
- package/scripts/sw-otel.sh +15 -23
- 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 +550 -122
- package/scripts/sw-pm.sh +2 -12
- package/scripts/sw-pr-lifecycle.sh +33 -28
- 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 +85 -14
- 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 +1 -1
- package/scripts/sw-scale.sh +174 -41
- package/scripts/sw-security-audit.sh +12 -22
- package/scripts/sw-self-optimize.sh +239 -23
- package/scripts/sw-session.sh +5 -15
- 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 +29 -39
- 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 +73 -0
- package/templates/pipelines/tdd.json +72 -0
- package/scripts/sw-pipeline.sh.mock +0 -7
|
@@ -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.1.0"
|
|
10
10
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
12
12
|
|
|
@@ -21,24 +21,6 @@ REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
|
21
21
|
[[ "$(type -t success 2>/dev/null)" == "function" ]] || success() { echo -e "\033[38;2;74;222;128m\033[1m✓\033[0m $*"; }
|
|
22
22
|
[[ "$(type -t warn 2>/dev/null)" == "function" ]] || warn() { echo -e "\033[38;2;250;204;21m\033[1m⚠\033[0m $*"; }
|
|
23
23
|
[[ "$(type -t error 2>/dev/null)" == "function" ]] || error() { echo -e "\033[38;2;248;113;113m\033[1m✗\033[0m $*" >&2; }
|
|
24
|
-
if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
|
|
25
|
-
emit_event() {
|
|
26
|
-
local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
|
|
27
|
-
local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
|
|
28
|
-
while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
|
|
29
|
-
echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
|
|
30
|
-
}
|
|
31
|
-
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
24
|
# ─── Configuration ───────────────────────────────────────────────────────
|
|
43
25
|
REVIEW_CONFIG="${REPO_DIR}/.claude/code-review.json"
|
|
44
26
|
QUALITY_METRICS_FILE="${REPO_DIR}/.claude/pipeline-artifacts/quality-metrics.json"
|
|
@@ -335,17 +317,16 @@ auto_fix() {
|
|
|
335
317
|
local backup="${target_file}.review-backup"
|
|
336
318
|
cp "$target_file" "$backup"
|
|
337
319
|
|
|
338
|
-
#
|
|
339
|
-
if command -v shellcheck
|
|
340
|
-
local shellcheck_fixes=0
|
|
320
|
+
# Report shellcheck issues (informational — auto-fix is limited to whitespace)
|
|
321
|
+
if command -v shellcheck >/dev/null 2>&1; then
|
|
341
322
|
local warnings_file
|
|
342
323
|
warnings_file=$(mktemp)
|
|
343
324
|
shellcheck -f json "$target_file" > "$warnings_file" 2>/dev/null || true
|
|
344
325
|
|
|
345
326
|
if [[ -s "$warnings_file" ]]; then
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
327
|
+
local shellcheck_count
|
|
328
|
+
shellcheck_count=$(jq 'length' "$warnings_file" 2>/dev/null || echo "0")
|
|
329
|
+
[[ "$shellcheck_count" -gt 0 ]] && info "shellcheck found $shellcheck_count issues in $target_file (manual review recommended)"
|
|
349
330
|
fi
|
|
350
331
|
rm -f "$warnings_file"
|
|
351
332
|
fi
|
|
@@ -381,7 +362,7 @@ run_claude_semantic_review() {
|
|
|
381
362
|
local diff_content="$1"
|
|
382
363
|
local requirements="${2:-}"
|
|
383
364
|
[[ -z "$diff_content" ]] && return 0
|
|
384
|
-
if ! command -v claude
|
|
365
|
+
if ! command -v claude >/dev/null 2>&1; then
|
|
385
366
|
return 0
|
|
386
367
|
fi
|
|
387
368
|
|
|
@@ -437,13 +418,12 @@ review_changes() {
|
|
|
437
418
|
local review_output="{\"timestamp\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"scope\":\"$review_scope\",\"findings\":{}}"
|
|
438
419
|
local total_issues=0
|
|
439
420
|
|
|
440
|
-
# Get changed files
|
|
421
|
+
# Get changed files (Bash 3.2 compatible — no mapfile)
|
|
441
422
|
local changed_files=()
|
|
442
423
|
if [[ "$review_scope" == "staged" ]]; then
|
|
443
|
-
|
|
424
|
+
while IFS= read -r _f; do [[ -n "$_f" ]] && changed_files+=("$_f"); done < <(cd "$REPO_DIR" && git diff --cached --name-only 2>/dev/null || true)
|
|
444
425
|
else
|
|
445
|
-
|
|
446
|
-
mapfile -t changed_files < <(cd "$REPO_DIR" && git diff main...HEAD --name-only 2>/dev/null || true)
|
|
426
|
+
while IFS= read -r _f; do [[ -n "$_f" ]] && changed_files+=("$_f"); done < <(cd "$REPO_DIR" && git diff main...HEAD --name-only 2>/dev/null || true)
|
|
447
427
|
fi
|
|
448
428
|
|
|
449
429
|
[[ ${#changed_files[@]} -eq 0 ]] && { success "No changes to review"; return 0; }
|
|
@@ -456,9 +436,9 @@ review_changes() {
|
|
|
456
436
|
diff_content=$(cd "$REPO_DIR" && git diff main...HEAD 2>/dev/null || true)
|
|
457
437
|
fi
|
|
458
438
|
local semantic_issues=()
|
|
459
|
-
if [[ -n "$diff_content" ]] && command -v claude
|
|
439
|
+
if [[ -n "$diff_content" ]] && command -v claude >/dev/null 2>&1; then
|
|
460
440
|
info "Running Claude semantic review (logic, race conditions, API usage)..."
|
|
461
|
-
|
|
441
|
+
while IFS= read -r _si; do [[ -n "$_si" ]] && semantic_issues+=("$_si"); done < <(run_claude_semantic_review "$diff_content" "${REVIEW_REQUIREMENTS:-}" || true)
|
|
462
442
|
if [[ ${#semantic_issues[@]} -gt 0 ]]; then
|
|
463
443
|
total_issues=$((total_issues + ${#semantic_issues[@]}))
|
|
464
444
|
review_output=$(echo "$review_output" | jq --argjson arr "$(printf '%s\n' "${semantic_issues[@]}" | jq -R . | jq -s .)" '.semantic_findings = $arr' 2>/dev/null || echo "$review_output")
|
|
@@ -476,10 +456,10 @@ review_changes() {
|
|
|
476
456
|
local arch_issues=()
|
|
477
457
|
local style_issues=()
|
|
478
458
|
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
459
|
+
while IFS= read -r _s; do [[ -n "$_s" ]] && smells+=("$_s"); done < <(detect_code_smells "$file_path")
|
|
460
|
+
while IFS= read -r _s; do [[ -n "$_s" ]] && solids+=("$_s"); done < <(check_solid_principles "$file_path")
|
|
461
|
+
while IFS= read -r _s; do [[ -n "$_s" ]] && arch_issues+=("$_s"); done < <(check_architecture_boundaries "$file_path")
|
|
462
|
+
while IFS= read -r _s; do [[ -n "$_s" ]] && style_issues+=("$_s"); done < <(check_style_consistency "$file_path")
|
|
483
463
|
|
|
484
464
|
local file_issues=$((${#smells[@]} + ${#solids[@]} + ${#arch_issues[@]} + ${#style_issues[@]}))
|
|
485
465
|
total_issues=$((total_issues + file_issues))
|
package/scripts/sw-connect.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.1.0"
|
|
12
12
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
13
13
|
|
|
14
14
|
# ─── Cross-platform compatibility ──────────────────────────────────────────
|
|
@@ -18,8 +18,11 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
18
18
|
# Canonical helpers (colors, output, events)
|
|
19
19
|
# shellcheck source=lib/helpers.sh
|
|
20
20
|
[[ -f "$SCRIPT_DIR/lib/helpers.sh" ]] && source "$SCRIPT_DIR/lib/helpers.sh"
|
|
21
|
+
[[ -f "$SCRIPT_DIR/lib/config.sh" ]] && source "$SCRIPT_DIR/lib/config.sh"
|
|
21
22
|
# Fallbacks when helpers not loaded (e.g. test env with overridden SCRIPT_DIR)
|
|
22
23
|
[[ "$(type -t info 2>/dev/null)" == "function" ]] || info() { echo -e "\033[38;2;0;212;255m\033[1m▸\033[0m $*"; }
|
|
24
|
+
# Color fallbacks when helpers not loaded
|
|
25
|
+
: "${CYAN:=}" "${BOLD:=}" "${RESET:=}" "${DIM:=}" "${GREEN:=}" "${RED:=}" "${YELLOW:=}" "${PURPLE:=}" "${WHITE:=}" "${BLUE:=}"
|
|
23
26
|
[[ "$(type -t success 2>/dev/null)" == "function" ]] || success() { echo -e "\033[38;2;74;222;128m\033[1m✓\033[0m $*"; }
|
|
24
27
|
[[ "$(type -t warn 2>/dev/null)" == "function" ]] || warn() { echo -e "\033[38;2;250;204;21m\033[1m⚠\033[0m $*"; }
|
|
25
28
|
[[ "$(type -t error 2>/dev/null)" == "function" ]] || error() { echo -e "\033[38;2;248;113;113m\033[1m✗\033[0m $*" >&2; }
|
|
@@ -35,16 +38,6 @@ if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
|
|
|
35
38
|
echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
|
|
36
39
|
}
|
|
37
40
|
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
41
|
# ─── Constants ──────────────────────────────────────────────────────────────
|
|
49
42
|
SHIPWRIGHT_DIR="$HOME/.shipwright"
|
|
50
43
|
PID_FILE="$SHIPWRIGHT_DIR/connect.pid"
|
|
@@ -53,7 +46,7 @@ DAEMON_PID_FILE="$SHIPWRIGHT_DIR/daemon.pid"
|
|
|
53
46
|
DAEMON_STATE_FILE="$SHIPWRIGHT_DIR/daemon-state.json"
|
|
54
47
|
EVENTS_FILE="$SHIPWRIGHT_DIR/events.jsonl"
|
|
55
48
|
CONNECT_LOG="$SHIPWRIGHT_DIR/connect.log"
|
|
56
|
-
DEFAULT_URL="http://localhost
|
|
49
|
+
DEFAULT_URL="http://localhost:$(_config_get_int "dashboard.port" 8767)"
|
|
57
50
|
HEARTBEAT_INTERVAL=10
|
|
58
51
|
|
|
59
52
|
ensure_dir() {
|
package/scripts/sw-context.sh
CHANGED
|
@@ -6,9 +6,9 @@
|
|
|
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.1.0"
|
|
10
10
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
|
-
REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
11
|
+
REPO_DIR="${SHIPWRIGHT_REPO_DIR:-$(cd "$SCRIPT_DIR/.." && pwd)}"
|
|
12
12
|
|
|
13
13
|
# ─── Cross-platform compatibility ──────────────────────────────────────────
|
|
14
14
|
# shellcheck source=lib/compat.sh
|
|
@@ -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
|
# ─── Paths ────────────────────────────────────────────────────────────────
|
|
48
30
|
ARTIFACTS_DIR="${REPO_DIR}/.claude/pipeline-artifacts"
|
|
49
31
|
CONTEXT_BUNDLE="${ARTIFACTS_DIR}/context-bundle.md"
|
|
@@ -124,7 +106,7 @@ extract_recent_prs() {
|
|
|
124
106
|
return
|
|
125
107
|
fi
|
|
126
108
|
|
|
127
|
-
if ! command -v gh
|
|
109
|
+
if ! command -v gh >/dev/null 2>&1; then
|
|
128
110
|
echo "(gh CLI not available, using git log)"
|
|
129
111
|
echo ""
|
|
130
112
|
local recent_commits
|
|
@@ -405,6 +387,7 @@ gather_context() {
|
|
|
405
387
|
|
|
406
388
|
local tmp_file
|
|
407
389
|
tmp_file=$(mktemp "${TMPDIR:-/tmp}/sw-context-bundle.XXXXXX")
|
|
390
|
+
trap "rm -f '$tmp_file'" RETURN
|
|
408
391
|
|
|
409
392
|
# Write bundle header
|
|
410
393
|
{
|
|
@@ -484,9 +467,9 @@ gather_context() {
|
|
|
484
467
|
# ─── Show current bundle ───────────────────────────────────────────────────
|
|
485
468
|
show_context() {
|
|
486
469
|
if [[ ! -f "$CONTEXT_BUNDLE" ]]; then
|
|
487
|
-
|
|
488
|
-
echo "Run '${CYAN}shipwright context gather --goal \"...\" --stage plan${RESET}'
|
|
489
|
-
return
|
|
470
|
+
echo "Pipeline Context — No bundle generated yet"
|
|
471
|
+
echo "Run '${CYAN}shipwright context gather --goal \"...\" --stage plan${RESET}' to create one"
|
|
472
|
+
return 0
|
|
490
473
|
fi
|
|
491
474
|
|
|
492
475
|
cat "$CONTEXT_BUNDLE"
|
|
@@ -498,7 +481,7 @@ clear_context() {
|
|
|
498
481
|
rm -f "$CONTEXT_BUNDLE"
|
|
499
482
|
success "Context bundle cleared"
|
|
500
483
|
else
|
|
501
|
-
|
|
484
|
+
info "No context bundle to clear — already cleared"
|
|
502
485
|
fi
|
|
503
486
|
}
|
|
504
487
|
|
|
@@ -584,7 +567,7 @@ main() {
|
|
|
584
567
|
|
|
585
568
|
# If issue provided, fetch from GitHub
|
|
586
569
|
if [[ -n "$issue" ]]; then
|
|
587
|
-
if [[ "${NO_GITHUB:-}" == "true" ]] || ! command -v gh
|
|
570
|
+
if [[ "${NO_GITHUB:-}" == "true" ]] || ! command -v gh >/dev/null 2>&1; then
|
|
588
571
|
goal="GitHub issue #$issue (fetch unavailable)"
|
|
589
572
|
else
|
|
590
573
|
goal=$(gh issue view "$issue" --json title,body --template '{{.title}}: {{.body}}' 2>/dev/null || echo "GitHub issue #$issue")
|
package/scripts/sw-cost.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.1.0"
|
|
10
10
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
12
12
|
|
|
@@ -34,16 +34,6 @@ if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
|
|
|
34
34
|
echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
|
|
35
35
|
}
|
|
36
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
37
|
format_duration() {
|
|
48
38
|
local secs="$1"
|
|
49
39
|
if [[ "$secs" -ge 3600 ]]; then
|
|
@@ -152,14 +142,14 @@ cost_record() {
|
|
|
152
142
|
local cost_usd
|
|
153
143
|
cost_usd=$(cost_calculate "$input_tokens" "$output_tokens" "$model")
|
|
154
144
|
|
|
155
|
-
# Try SQLite first
|
|
156
|
-
if type db_record_cost
|
|
157
|
-
db_record_cost "$input_tokens" "$output_tokens" "$model" "$
|
|
145
|
+
# Try SQLite first (arg order must match db_record_cost signature: tokens, tokens, model, cost, stage, issue)
|
|
146
|
+
if type db_record_cost >/dev/null 2>&1; then
|
|
147
|
+
db_record_cost "$input_tokens" "$output_tokens" "$model" "$cost_usd" "$stage" "$issue" 2>/dev/null || true
|
|
158
148
|
fi
|
|
159
149
|
|
|
160
150
|
# Always write to JSON (dual-write period)
|
|
161
151
|
(
|
|
162
|
-
if command -v flock
|
|
152
|
+
if command -v flock >/dev/null 2>&1; then
|
|
163
153
|
flock -w 10 200 2>/dev/null || { warn "Cost lock timeout"; }
|
|
164
154
|
fi
|
|
165
155
|
local tmp_file
|
|
@@ -202,7 +192,7 @@ cost_check_budget() {
|
|
|
202
192
|
|
|
203
193
|
# Try DB for budget info
|
|
204
194
|
local budget_enabled budget_usd
|
|
205
|
-
if type db_get_budget
|
|
195
|
+
if type db_get_budget >/dev/null 2>&1 && type db_available >/dev/null 2>&1 && db_available 2>/dev/null; then
|
|
206
196
|
local db_budget
|
|
207
197
|
db_budget=$(db_get_budget 2>/dev/null || true)
|
|
208
198
|
if [[ -n "$db_budget" ]]; then
|
|
@@ -259,7 +249,7 @@ cost_remaining_budget() {
|
|
|
259
249
|
ensure_cost_dir
|
|
260
250
|
|
|
261
251
|
# Try DB for remaining budget (single query)
|
|
262
|
-
if type db_remaining_budget
|
|
252
|
+
if type db_remaining_budget >/dev/null 2>&1 && type db_available >/dev/null 2>&1 && db_available 2>/dev/null; then
|
|
263
253
|
local db_result
|
|
264
254
|
db_result=$(db_remaining_budget 2>/dev/null || true)
|
|
265
255
|
if [[ -n "$db_result" ]]; then
|
|
@@ -274,6 +264,11 @@ cost_remaining_budget() {
|
|
|
274
264
|
budget_usd=$(jq -r '.daily_budget_usd' "$BUDGET_FILE" 2>/dev/null || echo "0")
|
|
275
265
|
|
|
276
266
|
if [[ "$budget_enabled" != "true" || "$budget_usd" == "0" ]]; then
|
|
267
|
+
if [[ -z "${_BUDGET_UNCONFIGURED_WARNED:-}" ]]; then
|
|
268
|
+
info "Budget not configured — unlimited. Use 'shipwright cost budget set <amount>'"
|
|
269
|
+
emit_event "cost.budget_unconfigured" "status=unlimited"
|
|
270
|
+
_BUDGET_UNCONFIGURED_WARNED=1
|
|
271
|
+
fi
|
|
277
272
|
echo "unlimited"
|
|
278
273
|
return 0
|
|
279
274
|
fi
|
|
@@ -818,7 +813,7 @@ budget_set() {
|
|
|
818
813
|
ensure_cost_dir
|
|
819
814
|
|
|
820
815
|
# Write to DB if available
|
|
821
|
-
if type db_set_budget
|
|
816
|
+
if type db_set_budget >/dev/null 2>&1; then
|
|
822
817
|
db_set_budget "$amount" 2>/dev/null || true
|
|
823
818
|
fi
|
|
824
819
|
|
|
@@ -904,6 +899,8 @@ show_help() {
|
|
|
904
899
|
}
|
|
905
900
|
|
|
906
901
|
# ─── Command Router ─────────────────────────────────────────────────────────
|
|
902
|
+
# Only run CLI when executed directly (not when sourced by sw-pipeline.sh)
|
|
903
|
+
if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
|
|
907
904
|
|
|
908
905
|
SUBCOMMAND="${1:-help}"
|
|
909
906
|
shift 2>/dev/null || true
|
|
@@ -953,3 +950,5 @@ case "$SUBCOMMAND" in
|
|
|
953
950
|
exit 1
|
|
954
951
|
;;
|
|
955
952
|
esac
|
|
953
|
+
|
|
954
|
+
fi # end source guard
|