shipwright-cli 3.0.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 +3 -3
- package/completions/_shipwright +247 -93
- package/completions/shipwright.bash +69 -15
- package/completions/shipwright.fish +309 -41
- package/config/decision-tiers.json +55 -0
- package/config/event-schema.json +142 -5
- package/config/policy.json +8 -0
- package/package.json +3 -3
- package/scripts/lib/architecture.sh +2 -1
- package/scripts/lib/bootstrap.sh +0 -0
- package/scripts/lib/config.sh +0 -0
- package/scripts/lib/daemon-adaptive.sh +0 -0
- package/scripts/lib/daemon-dispatch.sh +24 -1
- package/scripts/lib/daemon-failure.sh +0 -0
- package/scripts/lib/daemon-health.sh +0 -0
- package/scripts/lib/daemon-patrol.sh +40 -5
- package/scripts/lib/daemon-poll.sh +17 -0
- package/scripts/lib/daemon-state.sh +10 -0
- package/scripts/lib/daemon-triage.sh +1 -1
- 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 +0 -0
- package/scripts/lib/helpers.sh +16 -17
- package/scripts/lib/pipeline-detection.sh +0 -0
- package/scripts/lib/pipeline-github.sh +0 -0
- package/scripts/lib/pipeline-intelligence.sh +20 -3
- package/scripts/lib/pipeline-quality-checks.sh +3 -2
- package/scripts/lib/pipeline-quality.sh +0 -0
- package/scripts/lib/pipeline-stages.sh +199 -32
- package/scripts/lib/pipeline-state.sh +14 -0
- package/scripts/lib/policy.sh +0 -0
- package/scripts/lib/test-helpers.sh +0 -0
- package/scripts/postinstall.mjs +75 -1
- package/scripts/signals/example-collector.sh +36 -0
- package/scripts/sw +8 -4
- package/scripts/sw-activity.sh +1 -1
- package/scripts/sw-adaptive.sh +1 -1
- package/scripts/sw-adversarial.sh +1 -1
- package/scripts/sw-architecture-enforcer.sh +1 -1
- package/scripts/sw-auth.sh +1 -1
- package/scripts/sw-autonomous.sh +1 -1
- package/scripts/sw-changelog.sh +1 -1
- package/scripts/sw-checkpoint.sh +1 -1
- package/scripts/sw-ci.sh +1 -1
- package/scripts/sw-cleanup.sh +1 -1
- package/scripts/sw-code-review.sh +1 -1
- package/scripts/sw-connect.sh +1 -1
- package/scripts/sw-context.sh +1 -1
- package/scripts/sw-cost.sh +12 -3
- package/scripts/sw-daemon.sh +2 -2
- package/scripts/sw-dashboard.sh +1 -1
- package/scripts/sw-db.sh +41 -34
- package/scripts/sw-decide.sh +685 -0
- package/scripts/sw-decompose.sh +1 -1
- package/scripts/sw-deps.sh +1 -1
- package/scripts/sw-developer-simulation.sh +1 -1
- package/scripts/sw-discovery.sh +27 -1
- package/scripts/sw-doc-fleet.sh +1 -1
- package/scripts/sw-docs-agent.sh +1 -1
- package/scripts/sw-docs.sh +1 -1
- package/scripts/sw-doctor.sh +1 -1
- package/scripts/sw-dora.sh +1 -1
- package/scripts/sw-durable.sh +1 -1
- package/scripts/sw-e2e-orchestrator.sh +1 -1
- package/scripts/sw-eventbus.sh +1 -1
- package/scripts/sw-evidence.sh +1 -1
- package/scripts/sw-feedback.sh +1 -1
- package/scripts/sw-fix.sh +1 -1
- package/scripts/sw-fleet-discover.sh +1 -1
- package/scripts/sw-fleet-viz.sh +1 -1
- package/scripts/sw-fleet.sh +1 -1
- package/scripts/sw-github-app.sh +1 -1
- package/scripts/sw-github-checks.sh +1 -1
- package/scripts/sw-github-deploy.sh +1 -1
- package/scripts/sw-github-graphql.sh +1 -1
- package/scripts/sw-guild.sh +1 -1
- package/scripts/sw-heartbeat.sh +1 -1
- package/scripts/sw-hygiene.sh +1 -1
- package/scripts/sw-incident.sh +1 -1
- package/scripts/sw-init.sh +1 -1
- package/scripts/sw-instrument.sh +1 -1
- package/scripts/sw-intelligence.sh +9 -5
- package/scripts/sw-jira.sh +1 -1
- package/scripts/sw-launchd.sh +1 -1
- package/scripts/sw-linear.sh +1 -1
- package/scripts/sw-logs.sh +1 -1
- package/scripts/sw-loop.sh +267 -17
- package/scripts/sw-memory.sh +22 -5
- package/scripts/sw-mission-control.sh +1 -1
- package/scripts/sw-model-router.sh +1 -1
- package/scripts/sw-otel.sh +5 -3
- package/scripts/sw-oversight.sh +1 -1
- package/scripts/sw-pipeline-composer.sh +1 -1
- package/scripts/sw-pipeline-vitals.sh +1 -1
- package/scripts/sw-pipeline.sh +73 -1
- package/scripts/sw-pm.sh +1 -1
- package/scripts/sw-pr-lifecycle.sh +7 -4
- package/scripts/sw-predictive.sh +1 -1
- package/scripts/sw-prep.sh +1 -1
- package/scripts/sw-ps.sh +1 -1
- package/scripts/sw-public-dashboard.sh +1 -1
- package/scripts/sw-quality.sh +9 -5
- package/scripts/sw-reaper.sh +1 -1
- package/scripts/sw-regression.sh +1 -1
- package/scripts/sw-release-manager.sh +1 -1
- package/scripts/sw-release.sh +1 -1
- package/scripts/sw-remote.sh +1 -1
- package/scripts/sw-replay.sh +1 -1
- package/scripts/sw-retro.sh +1 -1
- package/scripts/sw-review-rerun.sh +1 -1
- package/scripts/sw-scale.sh +66 -10
- package/scripts/sw-security-audit.sh +1 -1
- package/scripts/sw-self-optimize.sh +1 -1
- package/scripts/sw-session.sh +3 -3
- package/scripts/sw-setup.sh +1 -1
- package/scripts/sw-standup.sh +1 -1
- package/scripts/sw-status.sh +1 -1
- package/scripts/sw-strategic.sh +1 -1
- package/scripts/sw-stream.sh +1 -1
- package/scripts/sw-swarm.sh +1 -1
- package/scripts/sw-team-stages.sh +1 -1
- package/scripts/sw-templates.sh +1 -1
- package/scripts/sw-testgen.sh +1 -1
- package/scripts/sw-tmux-pipeline.sh +1 -1
- package/scripts/sw-tmux.sh +1 -1
- package/scripts/sw-trace.sh +1 -1
- package/scripts/sw-tracker.sh +1 -1
- package/scripts/sw-triage.sh +6 -6
- package/scripts/sw-upgrade.sh +1 -1
- package/scripts/sw-ux.sh +1 -1
- package/scripts/sw-webhook.sh +1 -1
- package/scripts/sw-widgets.sh +1 -1
- package/scripts/sw-worktree.sh +1 -1
- package/scripts/update-homebrew-sha.sh +21 -15
package/scripts/sw-pipeline.sh
CHANGED
|
@@ -11,7 +11,7 @@ unset CLAUDECODE 2>/dev/null || true
|
|
|
11
11
|
# Ignore SIGHUP so tmux attach/detach doesn't kill long-running plan/design/review stages
|
|
12
12
|
trap '' HUP
|
|
13
13
|
|
|
14
|
-
VERSION="3.
|
|
14
|
+
VERSION="3.1.0"
|
|
15
15
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
16
16
|
REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
17
17
|
|
|
@@ -93,6 +93,12 @@ if [[ -f "$SCRIPT_DIR/sw-durable.sh" ]]; then
|
|
|
93
93
|
fi
|
|
94
94
|
# shellcheck source=sw-db.sh — for db_save_checkpoint/db_load_checkpoint (durable workflows)
|
|
95
95
|
[[ -f "$SCRIPT_DIR/sw-db.sh" ]] && source "$SCRIPT_DIR/sw-db.sh"
|
|
96
|
+
# Ensure DB schema exists so emit_event → db_add_event can write rows (CREATE IF NOT EXISTS is idempotent)
|
|
97
|
+
if type init_schema >/dev/null 2>&1 && type check_sqlite3 >/dev/null 2>&1 && check_sqlite3 2>/dev/null; then
|
|
98
|
+
init_schema 2>/dev/null || true
|
|
99
|
+
fi
|
|
100
|
+
# shellcheck source=sw-cost.sh — for cost_record persistence to costs.json + DB
|
|
101
|
+
[[ -f "$SCRIPT_DIR/sw-cost.sh" ]] && source "$SCRIPT_DIR/sw-cost.sh"
|
|
96
102
|
|
|
97
103
|
# ─── GitHub API Modules (optional) ─────────────────────────────────────────
|
|
98
104
|
# shellcheck source=sw-github-graphql.sh
|
|
@@ -633,6 +639,11 @@ cleanup_on_exit() {
|
|
|
633
639
|
git stash pop --quiet 2>/dev/null || true
|
|
634
640
|
fi
|
|
635
641
|
|
|
642
|
+
# Release durable pipeline lock
|
|
643
|
+
if [[ -n "${_PIPELINE_LOCK_ID:-}" ]] && type release_lock >/dev/null 2>&1; then
|
|
644
|
+
release_lock "$_PIPELINE_LOCK_ID" 2>/dev/null || true
|
|
645
|
+
fi
|
|
646
|
+
|
|
636
647
|
# Cancel lingering in_progress GitHub Check Runs
|
|
637
648
|
pipeline_cancel_check_runs 2>/dev/null || true
|
|
638
649
|
|
|
@@ -1550,6 +1561,10 @@ run_pipeline() {
|
|
|
1550
1561
|
stage_dur_s=$(( $(now_epoch) - stage_start_epoch ))
|
|
1551
1562
|
success "Stage ${BOLD}$id${RESET} complete ${DIM}(${timing})${RESET}"
|
|
1552
1563
|
emit_event "stage.completed" "issue=${ISSUE_NUMBER:-0}" "stage=$id" "duration_s=$stage_dur_s" "result=success"
|
|
1564
|
+
# Emit vitals snapshot on every stage transition (not just build/test)
|
|
1565
|
+
if type pipeline_emit_progress_snapshot >/dev/null 2>&1 && [[ -n "${ISSUE_NUMBER:-}" ]]; then
|
|
1566
|
+
pipeline_emit_progress_snapshot "${ISSUE_NUMBER}" "$id" "0" "0" "0" "" 2>/dev/null || true
|
|
1567
|
+
fi
|
|
1553
1568
|
# Record model outcome for UCB1 learning
|
|
1554
1569
|
type record_model_outcome >/dev/null 2>&1 && record_model_outcome "$stage_model_used" "$id" 1 "$stage_dur_s" 0 2>/dev/null || true
|
|
1555
1570
|
# Broadcast discovery for cross-pipeline learning
|
|
@@ -1580,6 +1595,10 @@ run_pipeline() {
|
|
|
1580
1595
|
"duration_s=$stage_dur_s" \
|
|
1581
1596
|
"error=${LAST_STAGE_ERROR:-unknown}" \
|
|
1582
1597
|
"error_class=${LAST_STAGE_ERROR_CLASS:-unknown}"
|
|
1598
|
+
# Emit vitals snapshot on failure too
|
|
1599
|
+
if type pipeline_emit_progress_snapshot >/dev/null 2>&1 && [[ -n "${ISSUE_NUMBER:-}" ]]; then
|
|
1600
|
+
pipeline_emit_progress_snapshot "${ISSUE_NUMBER}" "$id" "0" "0" "0" "${LAST_STAGE_ERROR:-unknown}" 2>/dev/null || true
|
|
1601
|
+
fi
|
|
1583
1602
|
# Log model used for prediction feedback
|
|
1584
1603
|
echo "${id}|${stage_model_used}|false" >> "${ARTIFACTS_DIR}/model-routing.log"
|
|
1585
1604
|
# Record model outcome for UCB1 learning
|
|
@@ -2103,6 +2122,19 @@ pipeline_start() {
|
|
|
2103
2122
|
|
|
2104
2123
|
setup_dirs
|
|
2105
2124
|
|
|
2125
|
+
# Acquire durable lock to prevent concurrent pipelines on the same issue/goal
|
|
2126
|
+
_PIPELINE_LOCK_ID=""
|
|
2127
|
+
if type acquire_lock >/dev/null 2>&1; then
|
|
2128
|
+
_PIPELINE_LOCK_ID="pipeline-${ISSUE_NUMBER:-goal-$$}"
|
|
2129
|
+
if ! acquire_lock "$_PIPELINE_LOCK_ID" 5 2>/dev/null; then
|
|
2130
|
+
error "Another pipeline is already running for this issue/goal"
|
|
2131
|
+
echo -e " Wait for it to finish, or remove stale lock:"
|
|
2132
|
+
echo -e " ${DIM}rm -rf ~/.shipwright/durable/locks/${_PIPELINE_LOCK_ID}.lock${RESET}"
|
|
2133
|
+
_PIPELINE_LOCK_ID=""
|
|
2134
|
+
exit 1
|
|
2135
|
+
fi
|
|
2136
|
+
fi
|
|
2137
|
+
|
|
2106
2138
|
# Generate reasoning trace (complexity analysis, template selection, failure predictions)
|
|
2107
2139
|
local user_specified_pipeline="$PIPELINE_NAME"
|
|
2108
2140
|
generate_reasoning_trace 2>/dev/null || true
|
|
@@ -2339,6 +2371,11 @@ pipeline_start() {
|
|
|
2339
2371
|
"model=${MODEL:-opus}" \
|
|
2340
2372
|
"goal=${GOAL}"
|
|
2341
2373
|
|
|
2374
|
+
# Record pipeline run in SQLite for dashboard visibility
|
|
2375
|
+
if type add_pipeline_run >/dev/null 2>&1; then
|
|
2376
|
+
add_pipeline_run "${SHIPWRIGHT_PIPELINE_ID}" "${ISSUE_NUMBER:-0}" "${GOAL}" "${BRANCH:-}" "${PIPELINE_NAME}" 2>/dev/null || true
|
|
2377
|
+
fi
|
|
2378
|
+
|
|
2342
2379
|
# Durable WAL: publish pipeline start event
|
|
2343
2380
|
if type publish_event >/dev/null 2>&1; then
|
|
2344
2381
|
publish_event "pipeline.started" "{\"issue\":\"${ISSUE_NUMBER:-0}\",\"pipeline\":\"${PIPELINE_NAME}\",\"goal\":\"${GOAL:0:200}\"}" 2>/dev/null || true
|
|
@@ -2385,10 +2422,35 @@ pipeline_start() {
|
|
|
2385
2422
|
"total_cost=$total_cost" \
|
|
2386
2423
|
"self_heal_count=$SELF_HEAL_COUNT"
|
|
2387
2424
|
|
|
2425
|
+
# Update pipeline run status in SQLite
|
|
2426
|
+
if type update_pipeline_status >/dev/null 2>&1; then
|
|
2427
|
+
update_pipeline_status "${SHIPWRIGHT_PIPELINE_ID}" "completed" "${PIPELINE_SLOWEST_STAGE:-}" "complete" "${total_dur_s:-0}" 2>/dev/null || true
|
|
2428
|
+
fi
|
|
2429
|
+
|
|
2388
2430
|
# Auto-ingest pipeline outcome into recruit profiles
|
|
2389
2431
|
if [[ -x "$SCRIPT_DIR/sw-recruit.sh" ]]; then
|
|
2390
2432
|
bash "$SCRIPT_DIR/sw-recruit.sh" ingest-pipeline 1 2>/dev/null || true
|
|
2391
2433
|
fi
|
|
2434
|
+
|
|
2435
|
+
# Capture success patterns to memory (learn what works — parallel the failure path)
|
|
2436
|
+
if [[ -x "$SCRIPT_DIR/sw-memory.sh" ]]; then
|
|
2437
|
+
bash "$SCRIPT_DIR/sw-memory.sh" capture "$STATE_FILE" "$ARTIFACTS_DIR" 2>/dev/null || true
|
|
2438
|
+
fi
|
|
2439
|
+
# Update memory baselines with successful run metrics
|
|
2440
|
+
if type memory_update_metrics >/dev/null 2>&1; then
|
|
2441
|
+
memory_update_metrics "build_duration_s" "${total_dur_s:-0}" 2>/dev/null || true
|
|
2442
|
+
memory_update_metrics "total_cost_usd" "${total_cost:-0}" 2>/dev/null || true
|
|
2443
|
+
memory_update_metrics "iterations" "$((SELF_HEAL_COUNT + 1))" 2>/dev/null || true
|
|
2444
|
+
fi
|
|
2445
|
+
|
|
2446
|
+
# Record positive fix outcome if self-healing succeeded
|
|
2447
|
+
if [[ "$SELF_HEAL_COUNT" -gt 0 && -x "$SCRIPT_DIR/sw-memory.sh" ]]; then
|
|
2448
|
+
local _success_sig
|
|
2449
|
+
_success_sig=$(tail -30 "$ARTIFACTS_DIR/test-results.log" 2>/dev/null | head -3 | tr '\n' ' ' | sed 's/^ *//;s/ *$//' || true)
|
|
2450
|
+
if [[ -n "$_success_sig" ]]; then
|
|
2451
|
+
bash "$SCRIPT_DIR/sw-memory.sh" fix-outcome "$_success_sig" "true" "true" 2>/dev/null || true
|
|
2452
|
+
fi
|
|
2453
|
+
fi
|
|
2392
2454
|
else
|
|
2393
2455
|
notify "Pipeline Failed" "Goal: ${GOAL}\nFailed at: ${CURRENT_STAGE_ID:-unknown}" "error"
|
|
2394
2456
|
emit_event "pipeline.completed" \
|
|
@@ -2406,6 +2468,11 @@ pipeline_start() {
|
|
|
2406
2468
|
"total_cost=$total_cost" \
|
|
2407
2469
|
"self_heal_count=$SELF_HEAL_COUNT"
|
|
2408
2470
|
|
|
2471
|
+
# Update pipeline run status in SQLite
|
|
2472
|
+
if type update_pipeline_status >/dev/null 2>&1; then
|
|
2473
|
+
update_pipeline_status "${SHIPWRIGHT_PIPELINE_ID}" "failed" "${CURRENT_STAGE_ID:-unknown}" "failed" "${total_dur_s:-0}" 2>/dev/null || true
|
|
2474
|
+
fi
|
|
2475
|
+
|
|
2409
2476
|
# Auto-ingest pipeline outcome into recruit profiles
|
|
2410
2477
|
if [[ -x "$SCRIPT_DIR/sw-recruit.sh" ]]; then
|
|
2411
2478
|
bash "$SCRIPT_DIR/sw-recruit.sh" ingest-pipeline 1 2>/dev/null || true
|
|
@@ -2542,6 +2609,11 @@ pipeline_start() {
|
|
|
2542
2609
|
"model=$model_key" \
|
|
2543
2610
|
"cost_usd=$total_cost"
|
|
2544
2611
|
|
|
2612
|
+
# Persist cost entry to costs.json + SQLite (was missing — tokens accumulated but never written)
|
|
2613
|
+
if type cost_record >/dev/null 2>&1; then
|
|
2614
|
+
cost_record "$TOTAL_INPUT_TOKENS" "$TOTAL_OUTPUT_TOKENS" "$model_key" "pipeline" "${ISSUE_NUMBER:-}" 2>/dev/null || true
|
|
2615
|
+
fi
|
|
2616
|
+
|
|
2545
2617
|
# Record pipeline outcome for Thompson sampling / outcome-based learning
|
|
2546
2618
|
if type db_record_outcome >/dev/null 2>&1; then
|
|
2547
2619
|
local _outcome_success=0
|
package/scripts/sw-pm.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="3.
|
|
9
|
+
VERSION="3.1.0"
|
|
10
10
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
|
|
12
12
|
# ─── Cross-platform compatibility ──────────────────────────────────────────
|
|
@@ -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="3.
|
|
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
|
|
|
@@ -274,13 +274,16 @@ pr_review() {
|
|
|
274
274
|
# Evaluate quality criteria
|
|
275
275
|
local issues_found=0
|
|
276
276
|
local file_count
|
|
277
|
-
file_count=$(echo "$diff_output" | grep -c '^diff --git' ||
|
|
277
|
+
file_count=$(echo "$diff_output" | grep -c '^diff --git' || true)
|
|
278
|
+
file_count="${file_count:-0}"
|
|
278
279
|
|
|
279
280
|
local line_additions
|
|
280
|
-
line_additions=$(echo "$diff_output" | grep -c '^+' ||
|
|
281
|
+
line_additions=$(echo "$diff_output" | grep -c '^+' || true)
|
|
282
|
+
line_additions="${line_additions:-0}"
|
|
281
283
|
|
|
282
284
|
local line_deletions
|
|
283
|
-
line_deletions=$(echo "$diff_output" | grep -c '^-' ||
|
|
285
|
+
line_deletions=$(echo "$diff_output" | grep -c '^-' || true)
|
|
286
|
+
line_deletions="${line_deletions:-0}"
|
|
284
287
|
|
|
285
288
|
info "Diff analysis: ${file_count} files, +${line_additions}/-${line_deletions} lines"
|
|
286
289
|
|
package/scripts/sw-predictive.sh
CHANGED
package/scripts/sw-prep.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="3.
|
|
9
|
+
VERSION="3.1.0"
|
|
10
10
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
|
|
12
12
|
# ─── Handle subcommands ───────────────────────────────────────────────────────
|
package/scripts/sw-ps.sh
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
# ║ Displays a table of agents running in claude-* tmux windows with ║
|
|
6
6
|
# ║ PID, status, idle time, and pane references. ║
|
|
7
7
|
# ╚═══════════════════════════════════════════════════════════════════════════╝
|
|
8
|
-
VERSION="3.
|
|
8
|
+
VERSION="3.1.0"
|
|
9
9
|
set -euo pipefail
|
|
10
10
|
trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
|
|
11
11
|
|
package/scripts/sw-quality.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="3.
|
|
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
|
|
|
@@ -93,7 +93,8 @@ validate_quality() {
|
|
|
93
93
|
local todos_pass=true
|
|
94
94
|
if [[ -d "$REPO_DIR/.git" ]]; then
|
|
95
95
|
local todo_count
|
|
96
|
-
todo_count=$(cd "$REPO_DIR" && git diff --cached 2>/dev/null | grep -cE '^\+.*(TODO|FIXME)' ||
|
|
96
|
+
todo_count=$(cd "$REPO_DIR" && git diff --cached 2>/dev/null | grep -cE '^\+.*(TODO|FIXME)' || true)
|
|
97
|
+
todo_count="${todo_count:-0}"
|
|
97
98
|
if [[ "$todo_count" -gt 0 ]]; then
|
|
98
99
|
todos_pass=false
|
|
99
100
|
all_pass=false
|
|
@@ -106,7 +107,8 @@ validate_quality() {
|
|
|
106
107
|
local secret_patterns="(password|secret|token|api[_-]?key|aws_access|private_key)"
|
|
107
108
|
if [[ -d "$REPO_DIR/.git" ]]; then
|
|
108
109
|
local secret_count
|
|
109
|
-
secret_count=$(cd "$REPO_DIR" && git diff --cached 2>/dev/null | grep -ciE "$secret_patterns" ||
|
|
110
|
+
secret_count=$(cd "$REPO_DIR" && git diff --cached 2>/dev/null | grep -ciE "$secret_patterns" || true)
|
|
111
|
+
secret_count="${secret_count:-0}"
|
|
110
112
|
if [[ "$secret_count" -gt 3 ]]; then
|
|
111
113
|
secrets_pass=false
|
|
112
114
|
all_pass=false
|
|
@@ -322,7 +324,8 @@ completion_detection() {
|
|
|
322
324
|
# Check diminishing returns: < 10 lines changed in last 3 iterations
|
|
323
325
|
local recent_changes=0
|
|
324
326
|
if [[ -f "$ARTIFACTS_DIR/progress.md" ]]; then
|
|
325
|
-
recent_changes=$(grep -c "^### Iteration" "$ARTIFACTS_DIR/progress.md" ||
|
|
327
|
+
recent_changes=$(grep -c "^### Iteration" "$ARTIFACTS_DIR/progress.md" || true)
|
|
328
|
+
recent_changes="${recent_changes:-0}"
|
|
326
329
|
fi
|
|
327
330
|
|
|
328
331
|
# Check if tests went from failing to passing
|
|
@@ -339,7 +342,8 @@ completion_detection() {
|
|
|
339
342
|
local subtasks_done=true
|
|
340
343
|
if [[ -f ".claude/goal.md" ]]; then
|
|
341
344
|
local unchecked_count
|
|
342
|
-
unchecked_count=$(grep -c "^- \[ \]" ".claude/goal.md" 2>/dev/null ||
|
|
345
|
+
unchecked_count=$(grep -c "^- \[ \]" ".claude/goal.md" 2>/dev/null || true)
|
|
346
|
+
unchecked_count="${unchecked_count:-0}"
|
|
343
347
|
if [[ "$unchecked_count" -gt 0 ]]; then
|
|
344
348
|
subtasks_done=false
|
|
345
349
|
fi
|
package/scripts/sw-reaper.sh
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
# ║ shipwright reaper --watch Continuous loop (default: 5s) ║
|
|
12
12
|
# ║ shipwright reaper --dry-run Preview what would be reaped ║
|
|
13
13
|
# ╚═══════════════════════════════════════════════════════════════════════════╝
|
|
14
|
-
VERSION="3.
|
|
14
|
+
VERSION="3.1.0"
|
|
15
15
|
set -euo pipefail
|
|
16
16
|
trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
|
|
17
17
|
|
package/scripts/sw-regression.sh
CHANGED
package/scripts/sw-release.sh
CHANGED
|
@@ -7,7 +7,7 @@ set -euo pipefail
|
|
|
7
7
|
trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
|
|
8
8
|
trap 'rm -f "${tmp_file:-}" "${tmp_changelog:-}"' EXIT
|
|
9
9
|
|
|
10
|
-
VERSION="3.
|
|
10
|
+
VERSION="3.1.0"
|
|
11
11
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
12
12
|
REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
13
13
|
|
package/scripts/sw-remote.sh
CHANGED
package/scripts/sw-replay.sh
CHANGED
package/scripts/sw-retro.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="3.
|
|
9
|
+
VERSION="3.1.0"
|
|
10
10
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
|
|
12
12
|
# ─── Cross-platform compatibility ──────────────────────────────────────────
|
package/scripts/sw-scale.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="3.
|
|
9
|
+
VERSION="3.1.0"
|
|
10
10
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
|
|
12
12
|
# ─── Dependency check ─────────────────────────────────────────────────────────
|
|
@@ -424,16 +424,72 @@ cmd_recommend() {
|
|
|
424
424
|
echo -e " Modules changed: ${CYAN}${module_threshold}${RESET} (add reviewer above this)"
|
|
425
425
|
echo ""
|
|
426
426
|
|
|
427
|
-
#
|
|
428
|
-
|
|
429
|
-
|
|
427
|
+
# Read pipeline context from env or pipeline-state.md
|
|
428
|
+
local actual_iterations="${ACTUAL_ITERATIONS:-0}"
|
|
429
|
+
local test_coverage="${TEST_COVERAGE:-0}"
|
|
430
|
+
local module_count="${MODULE_COUNT:-0}"
|
|
431
|
+
|
|
432
|
+
# Try to extract from pipeline-state.md if env vars not set
|
|
433
|
+
local state_file=".claude/pipeline-state.md"
|
|
434
|
+
if [[ "$actual_iterations" == "0" && -f "$state_file" ]]; then
|
|
435
|
+
actual_iterations=$(grep -oE 'iterations?[: ]+([0-9]+)' "$state_file" 2>/dev/null | grep -oE '[0-9]+' | tail -1 || echo "0")
|
|
436
|
+
actual_iterations="${actual_iterations:-0}"
|
|
437
|
+
fi
|
|
438
|
+
if [[ "$test_coverage" == "0" && -f "$state_file" ]]; then
|
|
439
|
+
test_coverage=$(grep -oE 'coverage[: ]+([0-9]+)' "$state_file" 2>/dev/null | grep -oE '[0-9]+' | tail -1 || echo "0")
|
|
440
|
+
test_coverage="${test_coverage:-0}"
|
|
441
|
+
fi
|
|
442
|
+
|
|
443
|
+
# Count changed modules via git diff
|
|
444
|
+
if [[ "$module_count" == "0" ]] && command -v git >/dev/null 2>&1; then
|
|
445
|
+
local base_branch="${BASE_BRANCH:-main}"
|
|
446
|
+
if git rev-parse --verify "$base_branch" >/dev/null 2>&1; then
|
|
447
|
+
module_count=$(git diff --name-only "${base_branch}..HEAD" 2>/dev/null \
|
|
448
|
+
| sed 's|/[^/]*$||' | sort -u | wc -l | xargs || echo "0")
|
|
449
|
+
fi
|
|
450
|
+
module_count="${module_count:-0}"
|
|
451
|
+
fi
|
|
452
|
+
|
|
453
|
+
local has_recommendations=false
|
|
454
|
+
|
|
455
|
+
# Check iterations against threshold
|
|
456
|
+
if [[ "$actual_iterations" -gt 0 && "$actual_iterations" -ge "$iteration_threshold" ]]; then
|
|
457
|
+
echo -e " ${YELLOW}⚠${RESET} Failed ${actual_iterations} iterations (threshold: ${iteration_threshold})"
|
|
458
|
+
echo -e " ${CYAN}→ Recommend adding: tester${RESET}"
|
|
459
|
+
echo ""
|
|
460
|
+
has_recommendations=true
|
|
461
|
+
fi
|
|
462
|
+
|
|
463
|
+
# Check coverage against threshold
|
|
464
|
+
if [[ "$test_coverage" -gt 0 && "$test_coverage" -lt "$coverage_threshold" ]]; then
|
|
465
|
+
echo -e " ${YELLOW}⚠${RESET} Coverage at ${test_coverage}% (threshold: ${coverage_threshold}%)"
|
|
466
|
+
echo -e " ${CYAN}→ Recommend adding: tester${RESET}"
|
|
467
|
+
echo ""
|
|
468
|
+
has_recommendations=true
|
|
469
|
+
fi
|
|
470
|
+
|
|
471
|
+
# Check module count against threshold
|
|
472
|
+
if [[ "$module_count" -gt 0 && "$module_count" -ge "$module_threshold" ]]; then
|
|
473
|
+
echo -e " ${YELLOW}⚠${RESET} ${module_count} modules changed (threshold: ${module_threshold})"
|
|
474
|
+
echo -e " ${CYAN}→ Recommend adding: reviewer${RESET}"
|
|
475
|
+
echo ""
|
|
476
|
+
has_recommendations=true
|
|
477
|
+
fi
|
|
478
|
+
|
|
479
|
+
if [[ "$has_recommendations" == "false" ]]; then
|
|
480
|
+
if [[ "$actual_iterations" == "0" && "$test_coverage" == "0" && "$module_count" == "0" ]]; then
|
|
481
|
+
echo -e " ${DIM}No pipeline context available — run during an active pipeline or set ACTUAL_ITERATIONS, TEST_COVERAGE, MODULE_COUNT${RESET}"
|
|
482
|
+
else
|
|
483
|
+
success "All metrics within thresholds — no scaling changes needed"
|
|
484
|
+
fi
|
|
485
|
+
echo ""
|
|
486
|
+
fi
|
|
430
487
|
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
# echo -e " ${CYAN}→ Recommend adding: tester${RESET}"
|
|
488
|
+
emit_event "scale.recommendation" \
|
|
489
|
+
"iterations=$actual_iterations" \
|
|
490
|
+
"coverage=$test_coverage" \
|
|
491
|
+
"modules=$module_count" \
|
|
492
|
+
"has_recommendations=$has_recommendations"
|
|
437
493
|
}
|
|
438
494
|
|
|
439
495
|
# ─── Help message ────────────────────────────────────────────────────────
|
package/scripts/sw-session.sh
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
# ║ Supports --template to scaffold from a team template and --terminal ║
|
|
9
9
|
# ║ to select a terminal adapter (tmux, iterm2, wezterm). ║
|
|
10
10
|
# ╚═══════════════════════════════════════════════════════════════════════════╝
|
|
11
|
-
VERSION="3.
|
|
11
|
+
VERSION="3.1.0"
|
|
12
12
|
set -euo pipefail
|
|
13
13
|
trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
|
|
14
14
|
|
|
@@ -355,7 +355,7 @@ if [[ "$DRY_RUN" == true ]]; then
|
|
|
355
355
|
cat << EOF
|
|
356
356
|
#!/usr/bin/env bash
|
|
357
357
|
# Auto-generated by shipwright session — safe to delete
|
|
358
|
-
cd ${PROJECT_DIR} || exit 1
|
|
358
|
+
cd "${PROJECT_DIR}" || exit 1
|
|
359
359
|
printf '\\033]2;${TEAM_NAME}-lead\\033\\\\'
|
|
360
360
|
PROMPT=\$(cat <prompt-file>)
|
|
361
361
|
rm -f <prompt-file> "\$0"
|
|
@@ -367,7 +367,7 @@ EOF
|
|
|
367
367
|
else
|
|
368
368
|
cat << EOF
|
|
369
369
|
#!/usr/bin/env bash
|
|
370
|
-
cd ${PROJECT_DIR} || exit 1
|
|
370
|
+
cd "${PROJECT_DIR}" || exit 1
|
|
371
371
|
printf '\\033]2;${TEAM_NAME}-lead\\033\\\\'
|
|
372
372
|
rm -f "\$0"
|
|
373
373
|
claude${DRY_RUN_FLAGS}
|
package/scripts/sw-setup.sh
CHANGED
package/scripts/sw-standup.sh
CHANGED
package/scripts/sw-status.sh
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# ║ ║
|
|
5
5
|
# ║ Shows running teams, agent windows, and task progress. ║
|
|
6
6
|
# ╚═══════════════════════════════════════════════════════════════════════════╝
|
|
7
|
-
VERSION="3.
|
|
7
|
+
VERSION="3.1.0"
|
|
8
8
|
set -euo pipefail
|
|
9
9
|
trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
|
|
10
10
|
|
package/scripts/sw-strategic.sh
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
# When sourced, do NOT add set -euo pipefail — the parent handles that.
|
|
8
8
|
# When run directly, main() sets up the error handling.
|
|
9
9
|
|
|
10
|
-
VERSION="3.
|
|
10
|
+
VERSION="3.1.0"
|
|
11
11
|
|
|
12
12
|
# ─── Paths (set defaults if not provided by parent) ──────────────────────────
|
|
13
13
|
SCRIPT_DIR="${SCRIPT_DIR:-$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)}"
|
package/scripts/sw-stream.sh
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
# ║ Streams tmux pane output in real-time to the dashboard or CLI. ║
|
|
6
6
|
# ║ Captures output periodically, tags by agent/team, supports replay. ║
|
|
7
7
|
# ╚═══════════════════════════════════════════════════════════════════════════╝
|
|
8
|
-
VERSION="3.
|
|
8
|
+
VERSION="3.1.0"
|
|
9
9
|
set -euo pipefail
|
|
10
10
|
trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
|
|
11
11
|
|
package/scripts/sw-swarm.sh
CHANGED
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="3.
|
|
8
|
+
VERSION="3.1.0"
|
|
9
9
|
set -euo pipefail
|
|
10
10
|
trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
|
|
11
11
|
|
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="3.
|
|
9
|
+
VERSION="3.1.0"
|
|
10
10
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
|
|
12
12
|
# ─── Handle subcommands ───────────────────────────────────────────────────────
|
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="3.
|
|
14
|
+
VERSION="3.1.0"
|
|
15
15
|
set -euo pipefail
|
|
16
16
|
trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
|
|
17
17
|
|
package/scripts/sw-trace.sh
CHANGED
package/scripts/sw-tracker.sh
CHANGED