shipwright-cli 2.2.0 → 2.2.2
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 +15 -16
- package/config/policy.schema.json +104 -29
- package/docs/AGI-PLATFORM-PLAN.md +11 -7
- package/docs/AGI-WHATS-NEXT.md +26 -20
- package/docs/README.md +2 -0
- package/package.json +1 -1
- package/scripts/check-version-consistency.sh +72 -0
- package/scripts/lib/daemon-adaptive.sh +610 -0
- package/scripts/lib/daemon-dispatch.sh +489 -0
- package/scripts/lib/daemon-failure.sh +387 -0
- package/scripts/lib/daemon-patrol.sh +1113 -0
- package/scripts/lib/daemon-poll.sh +1202 -0
- package/scripts/lib/daemon-state.sh +550 -0
- package/scripts/lib/daemon-triage.sh +490 -0
- package/scripts/lib/helpers.sh +81 -1
- package/scripts/lib/pipeline-detection.sh +278 -0
- package/scripts/lib/pipeline-github.sh +196 -0
- package/scripts/lib/pipeline-intelligence.sh +1706 -0
- package/scripts/lib/pipeline-quality-checks.sh +1054 -0
- package/scripts/lib/pipeline-quality.sh +11 -0
- package/scripts/lib/pipeline-stages.sh +2508 -0
- package/scripts/lib/pipeline-state.sh +529 -0
- package/scripts/sw +26 -4
- package/scripts/sw-activity.sh +1 -1
- package/scripts/sw-adaptive.sh +2 -2
- 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 +1 -1
- package/scripts/sw-daemon.sh +52 -4816
- package/scripts/sw-dashboard.sh +1 -1
- package/scripts/sw-db.sh +1 -1
- 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 +1 -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 +42 -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-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 +3 -3
- 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 +1 -1
- 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 +1 -1
- package/scripts/sw-memory.sh +1 -1
- package/scripts/sw-mission-control.sh +1 -1
- package/scripts/sw-model-router.sh +1 -1
- package/scripts/sw-otel.sh +4 -4
- 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 +23 -56
- package/scripts/sw-pipeline.sh.mock +7 -0
- package/scripts/sw-pm.sh +1 -1
- package/scripts/sw-pr-lifecycle.sh +1 -1
- 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 +1 -1
- package/scripts/sw-reaper.sh +1 -1
- package/scripts/sw-recruit.sh +9 -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-scale.sh +8 -5
- package/scripts/sw-security-audit.sh +1 -1
- package/scripts/sw-self-optimize.sh +158 -7
- package/scripts/sw-session.sh +1 -1
- package/scripts/sw-setup.sh +1 -1
- package/scripts/sw-standup.sh +3 -3
- package/scripts/sw-status.sh +1 -1
- package/scripts/sw-strategic.sh +1 -1
- package/scripts/sw-stream.sh +8 -2
- package/scripts/sw-swarm.sh +7 -10
- 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 +24 -6
- package/scripts/sw-triage.sh +1 -1
- 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/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="2.2.
|
|
9
|
+
VERSION="2.2.2"
|
|
10
10
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
|
|
12
12
|
# ─── Cross-platform compatibility ──────────────────────────────────────────
|
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="2.2.
|
|
9
|
+
VERSION="2.2.2"
|
|
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="2.2.
|
|
8
|
+
VERSION="2.2.2"
|
|
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
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="2.2.
|
|
14
|
+
VERSION="2.2.2"
|
|
15
15
|
set -euo pipefail
|
|
16
16
|
trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
|
|
17
17
|
|
package/scripts/sw-recruit.sh
CHANGED
|
@@ -284,7 +284,15 @@ initialize_builtin_roles() {
|
|
|
284
284
|
}
|
|
285
285
|
EOF
|
|
286
286
|
)
|
|
287
|
-
|
|
287
|
+
local _tmp_roles
|
|
288
|
+
_tmp_roles=$(mktemp)
|
|
289
|
+
if echo "$roles_json" | jq '.' > "$_tmp_roles" 2>/dev/null && [[ -s "$_tmp_roles" ]]; then
|
|
290
|
+
mv "$_tmp_roles" "$ROLES_DB"
|
|
291
|
+
else
|
|
292
|
+
rm -f "$_tmp_roles"
|
|
293
|
+
error "Failed to initialize roles DB"
|
|
294
|
+
return 1
|
|
295
|
+
fi
|
|
288
296
|
success "Initialized 10 built-in agent roles"
|
|
289
297
|
}
|
|
290
298
|
|
package/scripts/sw-regression.sh
CHANGED
package/scripts/sw-release.sh
CHANGED
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="2.2.
|
|
9
|
+
VERSION="2.2.2"
|
|
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="2.2.
|
|
9
|
+
VERSION="2.2.2"
|
|
10
10
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
|
|
12
12
|
# ─── Dependency check ─────────────────────────────────────────────────────────
|
|
@@ -108,7 +108,11 @@ update_scale_state() {
|
|
|
108
108
|
|
|
109
109
|
if [[ -f "$SCALE_STATE_FILE" ]]; then
|
|
110
110
|
# Update existing state
|
|
111
|
-
jq --arg now "$(now_epoch)" '.last_scale_time = ($now | tonumber)' "$SCALE_STATE_FILE" > "$tmp_file"
|
|
111
|
+
if ! jq --arg now "$(now_epoch)" '.last_scale_time = ($now | tonumber)' "$SCALE_STATE_FILE" > "$tmp_file" 2>/dev/null || [[ ! -s "$tmp_file" ]]; then
|
|
112
|
+
rm -f "$tmp_file"
|
|
113
|
+
warn "Failed to update scale state"
|
|
114
|
+
return 1
|
|
115
|
+
fi
|
|
112
116
|
else
|
|
113
117
|
# Create new state
|
|
114
118
|
cat > "$tmp_file" << JSON
|
|
@@ -243,9 +247,8 @@ cmd_rules() {
|
|
|
243
247
|
.[$key] = ($value | tonumber)
|
|
244
248
|
else
|
|
245
249
|
.[$key] = $value
|
|
246
|
-
end' "$SCALE_RULES_FILE" > "$tmp_file"
|
|
247
|
-
|
|
248
|
-
mv "$tmp_file" "$SCALE_RULES_FILE"
|
|
250
|
+
end' "$SCALE_RULES_FILE" > "$tmp_file" && [[ -s "$tmp_file" ]] && \
|
|
251
|
+
mv "$tmp_file" "$SCALE_RULES_FILE" || { rm -f "$tmp_file"; error "Failed to update config"; return 1; }
|
|
249
252
|
success "Updated: ${key} = ${value}"
|
|
250
253
|
;;
|
|
251
254
|
reset)
|
|
@@ -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="2.2.
|
|
9
|
+
VERSION="2.2.2"
|
|
10
10
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
12
12
|
|
|
@@ -485,7 +485,7 @@ optimize_learn_iterations() {
|
|
|
485
485
|
med_stats=$(calc_stats "$tmp_med")
|
|
486
486
|
high_stats=$(calc_stats "$tmp_high")
|
|
487
487
|
|
|
488
|
-
# Build iteration model
|
|
488
|
+
# Build iteration model (flat format for readers: .low, .medium, .high)
|
|
489
489
|
local tmp_model
|
|
490
490
|
tmp_model=$(mktemp "${ITERATION_MODEL_FILE}.tmp.XXXXXX")
|
|
491
491
|
jq -n \
|
|
@@ -494,11 +494,9 @@ optimize_learn_iterations() {
|
|
|
494
494
|
--argjson high "$high_stats" \
|
|
495
495
|
--arg updated "$(now_iso)" \
|
|
496
496
|
'{
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
high: {max_iterations: (if $high.mean > 0 then (($high.mean + $high.stddev) | floor | if . < 15 then 15 else . end) else 30 end), confidence: (if $high.samples >= 10 then 0.8 elif $high.samples >= 5 then 0.6 else 0.4 end), mean: $high.mean, stddev: $high.stddev, samples: $high.samples}
|
|
501
|
-
},
|
|
497
|
+
low: {max_iterations: (if $low.mean > 0 then (($low.mean + $low.stddev) | floor | if . < 5 then 5 else . end) else 10 end), confidence: (if $low.samples >= 10 then 0.8 elif $low.samples >= 5 then 0.6 else 0.4 end), mean: $low.mean, stddev: $low.stddev, samples: $low.samples},
|
|
498
|
+
medium: {max_iterations: (if $medium.mean > 0 then (($medium.mean + $medium.stddev) | floor | if . < 10 then 10 else . end) else 20 end), confidence: (if $medium.samples >= 10 then 0.8 elif $medium.samples >= 5 then 0.6 else 0.4 end), mean: $medium.mean, stddev: $medium.stddev, samples: $medium.samples},
|
|
499
|
+
high: {max_iterations: (if $high.mean > 0 then (($high.mean + $high.stddev) | floor | if . < 15 then 15 else . end) else 30 end), confidence: (if $high.samples >= 10 then 0.8 elif $high.samples >= 5 then 0.6 else 0.4 end), mean: $high.mean, stddev: $high.stddev, samples: $high.samples},
|
|
502
500
|
updated_at: $updated
|
|
503
501
|
}' \
|
|
504
502
|
> "$tmp_model" && mv "$tmp_model" "$ITERATION_MODEL_FILE" || rm -f "$tmp_model"
|
|
@@ -506,6 +504,80 @@ optimize_learn_iterations() {
|
|
|
506
504
|
rm -f "$tmp_low" "$tmp_med" "$tmp_high" 2>/dev/null || true
|
|
507
505
|
|
|
508
506
|
success "Iteration model updated"
|
|
507
|
+
|
|
508
|
+
# Apply prediction error bias correction from validation data
|
|
509
|
+
_optimize_apply_prediction_bias
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
# _optimize_apply_prediction_bias
|
|
513
|
+
# Reads prediction-validation.jsonl and applies bias correction to iteration model.
|
|
514
|
+
# If predictions consistently over/under-estimate, shift the model's means.
|
|
515
|
+
_optimize_apply_prediction_bias() {
|
|
516
|
+
local validation_file="${HOME}/.shipwright/optimization/prediction-validation.jsonl"
|
|
517
|
+
[[ ! -f "$validation_file" ]] && return 0
|
|
518
|
+
|
|
519
|
+
local model_file="$ITERATION_MODEL_FILE"
|
|
520
|
+
[[ ! -f "$model_file" ]] && return 0
|
|
521
|
+
|
|
522
|
+
# Compute mean delta (predicted - actual) from recent validations
|
|
523
|
+
local recent_count=50
|
|
524
|
+
local bias_data
|
|
525
|
+
bias_data=$(tail -n "$recent_count" "$validation_file" | jq -s '
|
|
526
|
+
if length == 0 then empty
|
|
527
|
+
else
|
|
528
|
+
group_by(
|
|
529
|
+
if .predicted_complexity <= 3 then "low"
|
|
530
|
+
elif .predicted_complexity <= 6 then "medium"
|
|
531
|
+
else "high" end
|
|
532
|
+
) | map({
|
|
533
|
+
bucket: (.[0] | if .predicted_complexity <= 3 then "low" elif .predicted_complexity <= 6 then "medium" else "high" end),
|
|
534
|
+
mean_delta: ([.[].delta] | add / length),
|
|
535
|
+
count: length
|
|
536
|
+
})
|
|
537
|
+
end' 2>/dev/null || true)
|
|
538
|
+
|
|
539
|
+
[[ -z "$bias_data" || "$bias_data" == "null" ]] && return 0
|
|
540
|
+
|
|
541
|
+
# Apply bias correction: if mean_delta > 0, predictions are too high → increase model mean
|
|
542
|
+
# (model mean drives estimates, and positive delta = predicted > actual = model underestimates actual iterations needed)
|
|
543
|
+
local updated_model
|
|
544
|
+
updated_model=$(cat "$model_file")
|
|
545
|
+
local changed=false
|
|
546
|
+
|
|
547
|
+
for bucket in low medium high; do
|
|
548
|
+
local bucket_bias count
|
|
549
|
+
bucket_bias=$(echo "$bias_data" | jq -r --arg b "$bucket" '.[] | select(.bucket == $b) | .mean_delta // 0' 2>/dev/null || echo "0")
|
|
550
|
+
count=$(echo "$bias_data" | jq -r --arg b "$bucket" '.[] | select(.bucket == $b) | .count // 0' 2>/dev/null || echo "0")
|
|
551
|
+
|
|
552
|
+
# Only correct if enough samples and significant bias (|delta| > 1)
|
|
553
|
+
if [[ "${count:-0}" -ge 5 ]]; then
|
|
554
|
+
local abs_bias
|
|
555
|
+
abs_bias=$(awk -v b="$bucket_bias" 'BEGIN { v = b < 0 ? -b : b; printf "%.1f", v }')
|
|
556
|
+
if awk -v ab="$abs_bias" 'BEGIN { exit !(ab > 1.0) }' 2>/dev/null; then
|
|
557
|
+
# Correction = -delta * 0.3 (partial correction to avoid overshooting)
|
|
558
|
+
local correction
|
|
559
|
+
correction=$(awk -v d="$bucket_bias" 'BEGIN { printf "%.2f", -d * 0.3 }')
|
|
560
|
+
updated_model=$(echo "$updated_model" | jq --arg b "$bucket" --argjson c "$correction" \
|
|
561
|
+
'.[$b].mean = ((.[$b].mean // 0) + $c) | .[$b].bias_correction = $c' 2>/dev/null || echo "$updated_model")
|
|
562
|
+
changed=true
|
|
563
|
+
info "Prediction bias correction for $bucket: delta=${bucket_bias}, correction=${correction} (${count} samples)"
|
|
564
|
+
fi
|
|
565
|
+
fi
|
|
566
|
+
done
|
|
567
|
+
|
|
568
|
+
if [[ "$changed" == true ]]; then
|
|
569
|
+
local tmp_model
|
|
570
|
+
tmp_model=$(mktemp)
|
|
571
|
+
if echo "$updated_model" | jq '.' > "$tmp_model" 2>/dev/null && [[ -s "$tmp_model" ]]; then
|
|
572
|
+
mv "$tmp_model" "$model_file"
|
|
573
|
+
emit_event "optimize.prediction_bias_corrected"
|
|
574
|
+
else
|
|
575
|
+
rm -f "$tmp_model"
|
|
576
|
+
fi
|
|
577
|
+
fi
|
|
578
|
+
|
|
579
|
+
# Rotate validation file
|
|
580
|
+
type rotate_jsonl &>/dev/null 2>&1 && rotate_jsonl "$validation_file" 5000
|
|
509
581
|
}
|
|
510
582
|
|
|
511
583
|
# ═════════════════════════════════════════════════════════════════════════════
|
|
@@ -659,6 +731,84 @@ optimize_route_models() {
|
|
|
659
731
|
success "Model routing updated"
|
|
660
732
|
}
|
|
661
733
|
|
|
734
|
+
# ═════════════════════════════════════════════════════════════════════════════
|
|
735
|
+
# RISK KEYWORD LEARNING
|
|
736
|
+
# ═════════════════════════════════════════════════════════════════════════════
|
|
737
|
+
|
|
738
|
+
# optimize_learn_risk_keywords [outcomes_file]
|
|
739
|
+
# Learns keyword→risk-weight mapping from pipeline outcomes for predictive risk scoring.
|
|
740
|
+
# Failed pipelines with labels/keywords get positive weights; successful ones get negative.
|
|
741
|
+
optimize_learn_risk_keywords() {
|
|
742
|
+
local outcomes_file="${1:-$OUTCOMES_FILE}"
|
|
743
|
+
|
|
744
|
+
if [[ ! -f "$outcomes_file" ]]; then
|
|
745
|
+
return 0
|
|
746
|
+
fi
|
|
747
|
+
|
|
748
|
+
ensure_optimization_dir
|
|
749
|
+
|
|
750
|
+
info "Learning risk keywords from outcomes..."
|
|
751
|
+
|
|
752
|
+
local risk_file="${OPTIMIZATION_DIR}/risk-keywords.json"
|
|
753
|
+
local keywords='{}'
|
|
754
|
+
if [[ -f "$risk_file" ]]; then
|
|
755
|
+
keywords=$(jq '.' "$risk_file" 2>/dev/null || echo '{}')
|
|
756
|
+
fi
|
|
757
|
+
|
|
758
|
+
local decay=0.95
|
|
759
|
+
local learn_rate=5
|
|
760
|
+
|
|
761
|
+
# Read outcomes and extract keywords from labels
|
|
762
|
+
local updated=false
|
|
763
|
+
while IFS= read -r line; do
|
|
764
|
+
local result labels
|
|
765
|
+
result=$(echo "$line" | jq -r '.result // "unknown"' 2>/dev/null) || continue
|
|
766
|
+
labels=$(echo "$line" | jq -r '.labels // ""' 2>/dev/null) || continue
|
|
767
|
+
[[ -z "$labels" || "$labels" == "null" ]] && continue
|
|
768
|
+
|
|
769
|
+
# Split labels on comma/space and learn from each keyword
|
|
770
|
+
local IFS=', '
|
|
771
|
+
for kw in $labels; do
|
|
772
|
+
kw=$(echo "$kw" | tr '[:upper:]' '[:lower:]' | tr -cd '[:alnum:]-')
|
|
773
|
+
[[ -z "$kw" || ${#kw} -lt 3 ]] && continue
|
|
774
|
+
|
|
775
|
+
local current_weight
|
|
776
|
+
current_weight=$(echo "$keywords" | jq -r --arg k "$kw" '.[$k] // 0' 2>/dev/null || echo "0")
|
|
777
|
+
|
|
778
|
+
local delta=0
|
|
779
|
+
if [[ "$result" == "failed" || "$result" == "error" ]]; then
|
|
780
|
+
delta=$learn_rate
|
|
781
|
+
elif [[ "$result" == "success" || "$result" == "complete" ]]; then
|
|
782
|
+
delta=$((-learn_rate / 2))
|
|
783
|
+
fi
|
|
784
|
+
|
|
785
|
+
if [[ "$delta" -ne 0 ]]; then
|
|
786
|
+
local new_weight
|
|
787
|
+
new_weight=$(awk -v cw="$current_weight" -v d="$decay" -v dw="$delta" 'BEGIN { printf "%.0f", (cw * d) + dw }')
|
|
788
|
+
# Clamp to -50..50
|
|
789
|
+
new_weight=$(awk -v w="$new_weight" 'BEGIN { if(w>50) w=50; if(w<-50) w=-50; printf "%.0f", w }')
|
|
790
|
+
keywords=$(echo "$keywords" | jq --arg k "$kw" --argjson w "$new_weight" '.[$k] = $w' 2>/dev/null || echo "$keywords")
|
|
791
|
+
updated=true
|
|
792
|
+
fi
|
|
793
|
+
done
|
|
794
|
+
done < "$outcomes_file"
|
|
795
|
+
|
|
796
|
+
if [[ "$updated" == true ]]; then
|
|
797
|
+
# Prune zero-weight keywords
|
|
798
|
+
keywords=$(echo "$keywords" | jq 'to_entries | map(select(.value != 0)) | from_entries' 2>/dev/null || echo "$keywords")
|
|
799
|
+
local tmp_risk
|
|
800
|
+
tmp_risk=$(mktemp)
|
|
801
|
+
if echo "$keywords" | jq '.' > "$tmp_risk" 2>/dev/null && [[ -s "$tmp_risk" ]]; then
|
|
802
|
+
mv "$tmp_risk" "$risk_file"
|
|
803
|
+
success "Risk keywords updated ($(echo "$keywords" | jq 'length' 2>/dev/null || echo '?') keywords)"
|
|
804
|
+
else
|
|
805
|
+
rm -f "$tmp_risk"
|
|
806
|
+
fi
|
|
807
|
+
else
|
|
808
|
+
info "No label data in outcomes — risk keywords unchanged"
|
|
809
|
+
fi
|
|
810
|
+
}
|
|
811
|
+
|
|
662
812
|
# ═════════════════════════════════════════════════════════════════════════════
|
|
663
813
|
# MEMORY EVOLUTION
|
|
664
814
|
# ═════════════════════════════════════════════════════════════════════════════
|
|
@@ -821,6 +971,7 @@ optimize_full_analysis() {
|
|
|
821
971
|
optimize_tune_templates
|
|
822
972
|
optimize_learn_iterations
|
|
823
973
|
optimize_route_models
|
|
974
|
+
optimize_learn_risk_keywords
|
|
824
975
|
optimize_evolve_memory
|
|
825
976
|
optimize_report >> "${OPTIMIZATION_DIR}/last-report.txt" 2>/dev/null || true
|
|
826
977
|
optimize_adjust_audit_intensity 2>/dev/null || true
|
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="2.2.
|
|
11
|
+
VERSION="2.2.2"
|
|
12
12
|
set -euo pipefail
|
|
13
13
|
trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
|
|
14
14
|
|
package/scripts/sw-setup.sh
CHANGED
package/scripts/sw-standup.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="2.2.
|
|
9
|
+
VERSION="2.2.2"
|
|
10
10
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
12
12
|
|
|
@@ -302,14 +302,14 @@ cmd_velocity() {
|
|
|
302
302
|
if [[ "$ts_epoch" -ge "$cutoff" ]]; then
|
|
303
303
|
local event_type
|
|
304
304
|
event_type=$(echo "$line" | jq -r '.type // ""' 2>/dev/null || true)
|
|
305
|
-
if [[ "$event_type" == "pipeline_completed" ]]; then
|
|
305
|
+
if [[ "$event_type" == "pipeline.completed" || "$event_type" == "pipeline_completed" ]]; then
|
|
306
306
|
completed_24h=$((completed_24h + 1))
|
|
307
307
|
fi
|
|
308
308
|
fi
|
|
309
309
|
|
|
310
310
|
local event_type
|
|
311
311
|
event_type=$(echo "$line" | jq -r '.type // ""' 2>/dev/null || true)
|
|
312
|
-
if [[ "$event_type" == "pipeline_completed" ]]; then
|
|
312
|
+
if [[ "$event_type" == "pipeline.completed" || "$event_type" == "pipeline_completed" ]]; then
|
|
313
313
|
total_completed=$((total_completed + 1))
|
|
314
314
|
fi
|
|
315
315
|
done < "$EVENTS_FILE"
|
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="2.2.
|
|
7
|
+
VERSION="2.2.2"
|
|
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="2.2.
|
|
10
|
+
VERSION="2.2.2"
|
|
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="2.2.
|
|
8
|
+
VERSION="2.2.2"
|
|
9
9
|
set -euo pipefail
|
|
10
10
|
trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
|
|
11
11
|
|
|
@@ -374,7 +374,13 @@ stream_config() {
|
|
|
374
374
|
;;
|
|
375
375
|
esac
|
|
376
376
|
|
|
377
|
-
|
|
377
|
+
if [[ -s "$tmp_file" ]]; then
|
|
378
|
+
mv "$tmp_file" "$STREAM_CONFIG"
|
|
379
|
+
else
|
|
380
|
+
rm -f "$tmp_file"
|
|
381
|
+
error "Failed to update stream config"
|
|
382
|
+
return 1
|
|
383
|
+
fi
|
|
378
384
|
success "Config updated: $key = $value"
|
|
379
385
|
emit_event "stream.config_updated" "key=$key" "value=$value"
|
|
380
386
|
}
|
package/scripts/sw-swarm.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="2.2.
|
|
9
|
+
VERSION="2.2.2"
|
|
10
10
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
12
12
|
|
|
@@ -190,9 +190,8 @@ cmd_spawn() {
|
|
|
190
190
|
resource_usage: {cpu: 0, memory: 0},
|
|
191
191
|
last_heartbeat: "'$(now_iso)'"
|
|
192
192
|
}] | .active_count += 1 | .last_updated = "'$(now_iso)'"' \
|
|
193
|
-
"$REGISTRY_FILE" > "$tmp_file"
|
|
194
|
-
|
|
195
|
-
mv "$tmp_file" "$REGISTRY_FILE"
|
|
193
|
+
"$REGISTRY_FILE" > "$tmp_file" && [[ -s "$tmp_file" ]] && \
|
|
194
|
+
mv "$tmp_file" "$REGISTRY_FILE" || { rm -f "$tmp_file"; error "Failed to update registry"; return 1; }
|
|
196
195
|
record_metric "$agent_id" "spawn" "1" "$agent_type"
|
|
197
196
|
|
|
198
197
|
# Create real tmux session for the agent (so scale/loop can send commands)
|
|
@@ -258,9 +257,8 @@ cmd_retire() {
|
|
|
258
257
|
|
|
259
258
|
jq --arg aid "$agent_id" \
|
|
260
259
|
'.agents |= map(select(.id != $aid)) | .active_count = ([.agents[] | select(.status == "active")] | length) | .last_updated = "'$(now_iso)'"' \
|
|
261
|
-
"$REGISTRY_FILE" > "$tmp_file"
|
|
262
|
-
|
|
263
|
-
mv "$tmp_file" "$REGISTRY_FILE"
|
|
260
|
+
"$REGISTRY_FILE" > "$tmp_file" && [[ -s "$tmp_file" ]] && \
|
|
261
|
+
mv "$tmp_file" "$REGISTRY_FILE" || { rm -f "$tmp_file"; error "Failed to update registry"; return 1; }
|
|
264
262
|
record_metric "$agent_id" "retire" "1" "graceful_shutdown"
|
|
265
263
|
|
|
266
264
|
success "Retired agent: ${CYAN}${agent_id}${RESET}"
|
|
@@ -492,9 +490,8 @@ cmd_config() {
|
|
|
492
490
|
.[$key] = ($value | fromjson)
|
|
493
491
|
else
|
|
494
492
|
.[$key] = $value
|
|
495
|
-
end' "$CONFIG_FILE" > "$tmp_file"
|
|
496
|
-
|
|
497
|
-
mv "$tmp_file" "$CONFIG_FILE"
|
|
493
|
+
end' "$CONFIG_FILE" > "$tmp_file" && [[ -s "$tmp_file" ]] && \
|
|
494
|
+
mv "$tmp_file" "$CONFIG_FILE" || { rm -f "$tmp_file"; error "Failed to update config"; return 1; }
|
|
498
495
|
success "Updated: ${key} = ${value}"
|
|
499
496
|
;;
|
|
500
497
|
reset)
|
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="2.2.
|
|
8
|
+
VERSION="2.2.2"
|
|
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="2.2.
|
|
9
|
+
VERSION="2.2.2"
|
|
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="2.2.
|
|
14
|
+
VERSION="2.2.2"
|
|
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