shipwright-cli 2.2.2 → 2.3.1
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 +12 -11
- package/dashboard/public/index.html +224 -8
- package/dashboard/public/styles.css +1078 -4
- package/dashboard/server.ts +1100 -15
- package/dashboard/src/canvas/interactions.ts +74 -0
- package/dashboard/src/canvas/layout.ts +85 -0
- package/dashboard/src/canvas/overlays.ts +117 -0
- package/dashboard/src/canvas/particles.ts +105 -0
- package/dashboard/src/canvas/renderer.ts +191 -0
- package/dashboard/src/components/charts/bar.ts +54 -0
- package/dashboard/src/components/charts/donut.ts +25 -0
- package/dashboard/src/components/charts/pipeline-rail.ts +105 -0
- package/dashboard/src/components/charts/sparkline.ts +82 -0
- package/dashboard/src/components/header.ts +616 -0
- package/dashboard/src/components/modal.ts +413 -0
- package/dashboard/src/components/terminal.ts +144 -0
- package/dashboard/src/core/api.test.ts +362 -0
- package/dashboard/src/core/api.ts +381 -0
- package/dashboard/src/core/helpers.ts +118 -0
- package/dashboard/src/core/router.test.ts +266 -0
- package/dashboard/src/core/router.ts +190 -0
- package/dashboard/src/core/sse.ts +38 -0
- package/dashboard/src/core/state.test.ts +235 -0
- package/dashboard/src/core/state.ts +150 -0
- package/dashboard/src/core/ws.test.ts +216 -0
- package/dashboard/src/core/ws.ts +143 -0
- package/dashboard/src/design/icons.test.ts +105 -0
- package/dashboard/src/design/icons.ts +131 -0
- package/dashboard/src/design/tokens.test.ts +204 -0
- package/dashboard/src/design/tokens.ts +160 -0
- package/dashboard/src/main.ts +68 -0
- package/dashboard/src/types/api.ts +337 -0
- package/dashboard/src/views/activity.ts +185 -0
- package/dashboard/src/views/agent-cockpit.ts +236 -0
- package/dashboard/src/views/agents.ts +72 -0
- package/dashboard/src/views/fleet-map.ts +299 -0
- package/dashboard/src/views/insights.ts +298 -0
- package/dashboard/src/views/machines.ts +162 -0
- package/dashboard/src/views/metrics.ts +420 -0
- package/dashboard/src/views/overview.ts +409 -0
- package/dashboard/src/views/pipeline-theater.ts +219 -0
- package/dashboard/src/views/pipelines.ts +595 -0
- package/dashboard/src/views/team.ts +362 -0
- package/dashboard/src/views/timeline.ts +389 -0
- package/dashboard/tsconfig.json +21 -0
- package/dashboard/vitest.config.ts +27 -0
- package/docs/AGI-WHATS-NEXT.md +15 -15
- package/package.json +16 -2
- package/scripts/lib/helpers.sh +30 -0
- package/scripts/lib/pipeline-quality-checks.sh +1 -1
- package/scripts/lib/pipeline-stages.sh +59 -0
- package/scripts/sw +86 -167
- 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 +14 -6
- package/scripts/sw-autonomous.sh +230 -13
- package/scripts/sw-changelog.sh +2 -2
- 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 +2 -2
- 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 +8 -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 +6 -5
- 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 +5 -2
- 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 +112 -9
- package/scripts/sw-instrument.sh +6 -1
- package/scripts/sw-intelligence.sh +5 -1
- package/scripts/sw-jira.sh +1 -1
- package/scripts/sw-launchd.sh +1 -1
- package/scripts/sw-linear.sh +20 -9
- package/scripts/sw-logs.sh +1 -1
- package/scripts/sw-loop.sh +2 -1
- package/scripts/sw-memory.sh +10 -1
- package/scripts/sw-mission-control.sh +1 -1
- package/scripts/sw-model-router.sh +4 -1
- package/scripts/sw-otel.sh +1 -1
- package/scripts/sw-oversight.sh +1 -1
- package/scripts/sw-pipeline-composer.sh +3 -1
- package/scripts/sw-pipeline-vitals.sh +4 -6
- package/scripts/sw-pipeline.sh +4 -1
- package/scripts/sw-pm.sh +5 -2
- package/scripts/sw-pr-lifecycle.sh +1 -1
- package/scripts/sw-predictive.sh +4 -1
- package/scripts/sw-prep.sh +3 -2
- package/scripts/sw-ps.sh +1 -1
- package/scripts/sw-public-dashboard.sh +10 -4
- package/scripts/sw-quality.sh +1 -1
- package/scripts/sw-reaper.sh +1 -1
- package/scripts/sw-recruit.sh +16 -0
- package/scripts/sw-regression.sh +2 -1
- package/scripts/sw-release-manager.sh +1 -1
- package/scripts/sw-release.sh +7 -5
- package/scripts/sw-remote.sh +1 -1
- package/scripts/sw-replay.sh +1 -1
- package/scripts/sw-retro.sh +4 -1
- package/scripts/sw-scale.sh +4 -1
- package/scripts/sw-security-audit.sh +1 -1
- package/scripts/sw-self-optimize.sh +113 -1
- package/scripts/sw-session.sh +1 -1
- package/scripts/sw-setup.sh +1 -1
- package/scripts/sw-standup.sh +2 -1
- package/scripts/sw-status.sh +1 -1
- package/scripts/sw-strategic.sh +2 -1
- package/scripts/sw-stream.sh +1 -1
- package/scripts/sw-swarm.sh +6 -1
- package/scripts/sw-team-stages.sh +1 -1
- package/scripts/sw-templates.sh +1 -1
- package/scripts/sw-testgen.sh +3 -2
- package/scripts/sw-tmux-pipeline.sh +2 -1
- package/scripts/sw-tmux.sh +1 -1
- package/scripts/sw-trace.sh +1 -1
- package/scripts/sw-tracker-jira.sh +1 -0
- package/scripts/sw-tracker-linear.sh +1 -0
- package/scripts/sw-tracker.sh +1 -1
- package/scripts/sw-triage.sh +198 -11
- 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 +2 -2
- package/scripts/sw-worktree.sh +1 -1
- package/dashboard/public/app.js +0 -4422
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
set -euo pipefail
|
|
8
8
|
trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
|
|
9
9
|
|
|
10
|
-
VERSION="2.
|
|
10
|
+
VERSION="2.3.1"
|
|
11
11
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
12
12
|
REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
13
13
|
|
|
@@ -204,6 +204,7 @@ set_config() {
|
|
|
204
204
|
# Use jq to safely update the config
|
|
205
205
|
local tmp_config
|
|
206
206
|
tmp_config=$(mktemp)
|
|
207
|
+
trap "rm -f '$tmp_config'" RETURN
|
|
207
208
|
|
|
208
209
|
if [[ "$value" == "true" ]] || [[ "$value" == "false" ]]; then
|
|
209
210
|
jq ".${key} = ${value}" "$MODEL_ROUTING_CONFIG" > "$tmp_config"
|
|
@@ -336,6 +337,7 @@ configure_ab_test() {
|
|
|
336
337
|
|
|
337
338
|
local tmp_config
|
|
338
339
|
tmp_config=$(mktemp)
|
|
340
|
+
trap "rm -f '$tmp_config'" RETURN
|
|
339
341
|
|
|
340
342
|
jq ".a_b_test = {\"enabled\": true, \"percentage\": $percentage, \"variant\": \"$variant\"}" \
|
|
341
343
|
"$MODEL_ROUTING_CONFIG" > "$tmp_config"
|
|
@@ -521,6 +523,7 @@ main() {
|
|
|
521
523
|
if command -v jq &>/dev/null; then
|
|
522
524
|
local tmp_config
|
|
523
525
|
tmp_config=$(mktemp)
|
|
526
|
+
trap "rm -f '$tmp_config'" RETURN
|
|
524
527
|
jq ".a_b_test.enabled = false" "$MODEL_ROUTING_CONFIG" > "$tmp_config"
|
|
525
528
|
mv "$tmp_config" "$MODEL_ROUTING_CONFIG"
|
|
526
529
|
success "Disabled A/B testing"
|
package/scripts/sw-otel.sh
CHANGED
package/scripts/sw-oversight.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.
|
|
9
|
+
VERSION="2.3.1"
|
|
10
10
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
12
12
|
|
|
@@ -124,6 +124,7 @@ composer_create_pipeline() {
|
|
|
124
124
|
# Atomic write
|
|
125
125
|
local tmp_file
|
|
126
126
|
tmp_file=$(mktemp "${output_file}.XXXXXX")
|
|
127
|
+
trap "rm -f '$tmp_file'" RETURN
|
|
127
128
|
echo "$composed" | jq '.' > "$tmp_file"
|
|
128
129
|
mv "$tmp_file" "$output_file"
|
|
129
130
|
|
|
@@ -152,6 +153,7 @@ composer_create_pipeline() {
|
|
|
152
153
|
info "Using fallback template: standard" >&2
|
|
153
154
|
local tmp_file
|
|
154
155
|
tmp_file=$(mktemp "${output_file}.XXXXXX")
|
|
156
|
+
trap "rm -f '$tmp_file'" RETURN
|
|
155
157
|
cp "$fallback_template" "$tmp_file"
|
|
156
158
|
mv "$tmp_file" "$output_file"
|
|
157
159
|
|
|
@@ -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.
|
|
9
|
+
VERSION="2.3.1"
|
|
10
10
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
12
12
|
|
|
@@ -316,13 +316,11 @@ _compute_error_maturity() {
|
|
|
316
316
|
# ─── File Locking Helpers ──────────────────────────────────────────────────
|
|
317
317
|
_vitals_acquire_lock() {
|
|
318
318
|
local lockfile="$1.lock"
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
flock -w 5 "$fd" || { warn "Vitals lock timeout"; return 1; }
|
|
319
|
+
exec 200>"$lockfile"
|
|
320
|
+
flock -w 5 200 || { warn "Vitals lock timeout"; return 1; }
|
|
322
321
|
}
|
|
323
322
|
_vitals_release_lock() {
|
|
324
|
-
|
|
325
|
-
flock -u "$fd" 2>/dev/null || true
|
|
323
|
+
flock -u 200 2>/dev/null || true
|
|
326
324
|
}
|
|
327
325
|
|
|
328
326
|
# ═══════════════════════════════════════════════════════════════════════════
|
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="2.
|
|
14
|
+
VERSION="2.3.1"
|
|
15
15
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
16
16
|
REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
17
17
|
|
|
@@ -850,6 +850,7 @@ Reply with ONLY the classification word, nothing else." --model haiku < /dev/nul
|
|
|
850
850
|
mkdir -p "$class_dir" 2>/dev/null || true
|
|
851
851
|
local tmp_class
|
|
852
852
|
tmp_class="$(mktemp)"
|
|
853
|
+
trap "rm -f '$tmp_class'" RETURN
|
|
853
854
|
if [[ -f "$class_history" ]]; then
|
|
854
855
|
jq --arg sig "$error_sig" --arg cls "$classification" --arg canon "$canonical_category" --arg stage "$stage_id" \
|
|
855
856
|
'.[$sig] = {"classification": $cls, "canonical": $canon, "stage": $stage, "recorded_at": now}' \
|
|
@@ -1269,6 +1270,7 @@ run_pipeline() {
|
|
|
1269
1270
|
# Remove this stage from the skip file
|
|
1270
1271
|
local tmp_skip
|
|
1271
1272
|
tmp_skip="$(mktemp)"
|
|
1273
|
+
trap "rm -f '$tmp_skip'" RETURN
|
|
1272
1274
|
grep -vx "$id" "$ARTIFACTS_DIR/skip-stage.txt" > "$tmp_skip" 2>/dev/null || true
|
|
1273
1275
|
mv "$tmp_skip" "$ARTIFACTS_DIR/skip-stage.txt"
|
|
1274
1276
|
continue
|
|
@@ -1600,6 +1602,7 @@ pipeline_post_completion_cleanup() {
|
|
|
1600
1602
|
# Reset status to idle (preserves the file for reference but unblocks new runs)
|
|
1601
1603
|
local tmp_state
|
|
1602
1604
|
tmp_state=$(mktemp)
|
|
1605
|
+
trap "rm -f '$tmp_state'" RETURN
|
|
1603
1606
|
sed 's/^status: .*/status: idle/' "$STATE_FILE" > "$tmp_state" 2>/dev/null || true
|
|
1604
1607
|
mv "$tmp_state" "$STATE_FILE"
|
|
1605
1608
|
fi
|
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.
|
|
9
|
+
VERSION="2.3.1"
|
|
10
10
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
|
|
12
12
|
# ─── Cross-platform compatibility ──────────────────────────────────────────
|
|
@@ -77,7 +77,7 @@ show_help() {
|
|
|
77
77
|
echo -e " ${DIM}shipwright pm history${RESET} # Show past decisions"
|
|
78
78
|
echo -e " ${DIM}shipwright pm history --pattern${RESET} # Show success patterns"
|
|
79
79
|
echo ""
|
|
80
|
-
echo -e "${DIM}Docs:
|
|
80
|
+
echo -e "${DIM}Docs: $(_sw_docs_url) | GitHub: $(_sw_github_url)${RESET}"
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
# ─── analyze_issue <issue_num> ───────────────────────────────────────────────
|
|
@@ -522,6 +522,7 @@ cmd_recommend() {
|
|
|
522
522
|
ensure_pm_history
|
|
523
523
|
local tmp_hist
|
|
524
524
|
tmp_hist=$(mktemp)
|
|
525
|
+
trap "rm -f '$tmp_hist'" RETURN
|
|
525
526
|
jq --argjson rec "$recommendation" '.decisions += [$rec]' "$PM_HISTORY" > "$tmp_hist" && mv "$tmp_hist" "$PM_HISTORY"
|
|
526
527
|
emit_event "pm.recommend" "issue=${issue_num}"
|
|
527
528
|
return 0
|
|
@@ -549,6 +550,7 @@ cmd_recommend() {
|
|
|
549
550
|
ensure_pm_history
|
|
550
551
|
local tmp_hist
|
|
551
552
|
tmp_hist=$(mktemp)
|
|
553
|
+
trap "rm -f '$tmp_hist'" RETURN
|
|
552
554
|
jq --argjson rec "$recommendation" '.decisions += [$rec]' "$PM_HISTORY" > "$tmp_hist" && mv "$tmp_hist" "$PM_HISTORY"
|
|
553
555
|
|
|
554
556
|
success "Recommendation saved to history"
|
|
@@ -612,6 +614,7 @@ cmd_learn() {
|
|
|
612
614
|
# Save to history
|
|
613
615
|
local tmp_hist
|
|
614
616
|
tmp_hist=$(mktemp)
|
|
617
|
+
trap "rm -f '$tmp_hist'" RETURN
|
|
615
618
|
jq --argjson outcome "$outcome_record" '.outcomes += [$outcome]' "$PM_HISTORY" > "$tmp_hist" && mv "$tmp_hist" "$PM_HISTORY"
|
|
616
619
|
|
|
617
620
|
success "Recorded ${outcome} outcome for issue #${issue_num}"
|
package/scripts/sw-predictive.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.
|
|
9
|
+
VERSION="2.3.1"
|
|
10
10
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
12
12
|
|
|
@@ -188,6 +188,7 @@ predictive_confirm_anomaly() {
|
|
|
188
188
|
# Find the most recent unconfirmed anomaly for this stage+metric
|
|
189
189
|
local tmp_file
|
|
190
190
|
tmp_file=$(mktemp "${TMPDIR:-/tmp}/sw-anomaly-confirm.XXXXXX")
|
|
191
|
+
trap "rm -f '$tmp_file'" RETURN
|
|
191
192
|
local found=false
|
|
192
193
|
|
|
193
194
|
# Process file in reverse to find most recent unconfirmed
|
|
@@ -283,6 +284,7 @@ _predictive_update_alarm_rates() {
|
|
|
283
284
|
# Atomic write
|
|
284
285
|
local tmp_file
|
|
285
286
|
tmp_file=$(mktemp "${TMPDIR:-/tmp}/sw-anomaly-thresh.XXXXXX")
|
|
287
|
+
trap "rm -f '$tmp_file'" RETURN
|
|
286
288
|
jq --arg m "$metric_name" \
|
|
287
289
|
--argjson crit "$new_critical" \
|
|
288
290
|
--argjson warn "$new_warning" \
|
|
@@ -755,6 +757,7 @@ predict_update_baseline() {
|
|
|
755
757
|
# Atomic write
|
|
756
758
|
local tmp_file
|
|
757
759
|
tmp_file=$(mktemp)
|
|
760
|
+
trap "rm -f '$tmp_file'" RETURN
|
|
758
761
|
jq --arg key "$key" \
|
|
759
762
|
--argjson val "$new_value" \
|
|
760
763
|
--argjson cnt "$new_count" \
|
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.
|
|
9
|
+
VERSION="2.3.1"
|
|
10
10
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
|
|
12
12
|
# ─── Handle subcommands ───────────────────────────────────────────────────────
|
|
@@ -129,7 +129,7 @@ show_help() {
|
|
|
129
129
|
echo -e " ${DIM}.claude/hooks/*.sh${RESET} Pre/post action hooks"
|
|
130
130
|
echo -e " ${DIM}.github/ISSUE_TEMPLATE/agent-task.md${RESET} Agent task template"
|
|
131
131
|
echo ""
|
|
132
|
-
echo -e "${DIM}Docs:
|
|
132
|
+
echo -e "${DIM}Docs: $(_sw_docs_url) | GitHub: $(_sw_github_url)${RESET}"
|
|
133
133
|
}
|
|
134
134
|
|
|
135
135
|
# ─── CLI Argument Parsing ───────────────────────────────────────────────────
|
|
@@ -828,6 +828,7 @@ prep_learn_patterns() {
|
|
|
828
828
|
# Write patterns file atomically
|
|
829
829
|
local tmp_patterns
|
|
830
830
|
tmp_patterns=$(mktemp)
|
|
831
|
+
trap "rm -f '$tmp_patterns'" RETURN
|
|
831
832
|
jq -n \
|
|
832
833
|
--arg ts "$(date -u +"%Y-%m-%dT%H:%M:%SZ")" \
|
|
833
834
|
--arg lang "${LANG_DETECTED:-}" \
|
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.
|
|
8
|
+
VERSION="2.3.1"
|
|
9
9
|
set -euo pipefail
|
|
10
10
|
trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
|
|
11
11
|
|
|
@@ -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.
|
|
9
|
+
VERSION="2.3.1"
|
|
10
10
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
12
12
|
|
|
@@ -323,7 +323,7 @@ generate_html() {
|
|
|
323
323
|
</div>
|
|
324
324
|
|
|
325
325
|
<div class="footer">
|
|
326
|
-
<p>Generated by <a href="
|
|
326
|
+
<p>Generated by <a href="GITHUB_URL_PLACEHOLDER">Shipwright</a> v1.13.0</p>
|
|
327
327
|
<p style="margin-top: 8px; color: #555;">Dashboard auto-refreshes every 30s when served from dashboard server</p>
|
|
328
328
|
<p style="margin-top: 8px;" id="footer-timestamp">Generated: —</p>
|
|
329
329
|
</div>
|
|
@@ -384,7 +384,12 @@ generate_html() {
|
|
|
384
384
|
const newDoc = parser.parseFromString(html, 'text/html');
|
|
385
385
|
const newScript = newDoc.querySelector('script');
|
|
386
386
|
if (newScript) {
|
|
387
|
-
eval
|
|
387
|
+
// Use DOM script insertion instead of eval: script comes from same-origin
|
|
388
|
+
// fetch of this page; DOM insertion executes in global scope without eval
|
|
389
|
+
const s = document.createElement('script');
|
|
390
|
+
s.textContent = newScript.textContent;
|
|
391
|
+
document.body.appendChild(s);
|
|
392
|
+
s.remove();
|
|
388
393
|
renderDashboard();
|
|
389
394
|
}
|
|
390
395
|
})
|
|
@@ -417,6 +422,7 @@ cmd_export() {
|
|
|
417
422
|
html="${html//TITLE_PLACEHOLDER/$title}"
|
|
418
423
|
html="${html//PRIVACY_PLACEHOLDER/$privacy}"
|
|
419
424
|
html="${html//\{DATA_PLACEHOLDER\}/$state_data}"
|
|
425
|
+
html="${html//GITHUB_URL_PLACEHOLDER/$(_sw_github_url)}"
|
|
420
426
|
|
|
421
427
|
# Atomic write
|
|
422
428
|
local tmp_file
|
|
@@ -736,7 +742,7 @@ ${BOLD}SHARE LINKS${RESET}
|
|
|
736
742
|
Share links require a running dashboard server to serve the public endpoint.
|
|
737
743
|
By default, requires dashboard to serve at: https://your-domain.com/public-dashboard/<token>
|
|
738
744
|
|
|
739
|
-
${DIM}Docs:
|
|
745
|
+
${DIM}Docs: $(_sw_docs_url)${RESET}
|
|
740
746
|
EOF
|
|
741
747
|
}
|
|
742
748
|
|
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.
|
|
14
|
+
VERSION="2.3.1"
|
|
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
|
@@ -286,6 +286,7 @@ EOF
|
|
|
286
286
|
)
|
|
287
287
|
local _tmp_roles
|
|
288
288
|
_tmp_roles=$(mktemp)
|
|
289
|
+
trap "rm -f '$_tmp_roles'" RETURN
|
|
289
290
|
if echo "$roles_json" | jq '.' > "$_tmp_roles" 2>/dev/null && [[ -s "$_tmp_roles" ]]; then
|
|
290
291
|
mv "$_tmp_roles" "$ROLES_DB"
|
|
291
292
|
else
|
|
@@ -426,6 +427,7 @@ _recruit_record_match() {
|
|
|
426
427
|
if [[ "$current_lines" -gt "$max_history" ]]; then
|
|
427
428
|
local tmp_trunc
|
|
428
429
|
tmp_trunc=$(mktemp)
|
|
430
|
+
trap "rm -f '$tmp_trunc'" RETURN
|
|
429
431
|
tail -n "$max_history" "$MATCH_HISTORY" > "$tmp_trunc" && _recruit_locked_write "$MATCH_HISTORY" "$tmp_trunc" || rm -f "$tmp_trunc"
|
|
430
432
|
fi
|
|
431
433
|
|
|
@@ -492,6 +494,7 @@ Return JSON only."
|
|
|
492
494
|
# Persist to roles DB
|
|
493
495
|
local tmp_file
|
|
494
496
|
tmp_file=$(mktemp)
|
|
497
|
+
trap "rm -f '$tmp_file'" RETURN
|
|
495
498
|
if jq --arg key "$role_key" --argjson role "$(echo "$result" | jq 'del(.key)')" '.[$key] = $role' "$ROLES_DB" > "$tmp_file"; then
|
|
496
499
|
_recruit_locked_write "$ROLES_DB" "$tmp_file"
|
|
497
500
|
else
|
|
@@ -544,6 +547,7 @@ Return JSON only."
|
|
|
544
547
|
|
|
545
548
|
local tmp_file
|
|
546
549
|
tmp_file=$(mktemp)
|
|
550
|
+
trap "rm -f '$tmp_file'" RETURN
|
|
547
551
|
if jq --arg key "$role_key" --argjson role "$role_json" '.[$key] = $role' "$ROLES_DB" > "$tmp_file"; then
|
|
548
552
|
_recruit_locked_write "$ROLES_DB" "$tmp_file"
|
|
549
553
|
else
|
|
@@ -622,6 +626,7 @@ cmd_record_outcome() {
|
|
|
622
626
|
|
|
623
627
|
local tmp_file
|
|
624
628
|
tmp_file=$(mktemp)
|
|
629
|
+
trap "rm -f '$tmp_file'" RETURN
|
|
625
630
|
jq --arg id "$agent_id" \
|
|
626
631
|
--argjson tc "$tasks_completed" \
|
|
627
632
|
--argjson sc "$success_count" \
|
|
@@ -659,6 +664,7 @@ cmd_record_outcome() {
|
|
|
659
664
|
if [[ -f "$MATCH_HISTORY" ]]; then
|
|
660
665
|
local tmp_mh
|
|
661
666
|
tmp_mh=$(mktemp)
|
|
667
|
+
trap "rm -f '$tmp_mh'" RETURN
|
|
662
668
|
# Find the most recent match for this agent_id with null outcome, and backfill
|
|
663
669
|
awk -v agent="$agent_id" -v outcome="$outcome" '
|
|
664
670
|
BEGIN { found = 0 }
|
|
@@ -753,6 +759,7 @@ _recruit_track_role_usage() {
|
|
|
753
759
|
|
|
754
760
|
local tmp_file
|
|
755
761
|
tmp_file=$(mktemp)
|
|
762
|
+
trap "rm -f '$tmp_file'" RETURN
|
|
756
763
|
jq --arg role "$role" --arg event "$event" --arg ts "$(now_iso)" '
|
|
757
764
|
.[$role] = (.[$role] // {matches: 0, successes: 0, failures: 0, last_used: ""}) |
|
|
758
765
|
.[$role].last_used = $ts |
|
|
@@ -1221,6 +1228,7 @@ _recruit_meta_learning_check() {
|
|
|
1221
1228
|
|
|
1222
1229
|
local tmp_file
|
|
1223
1230
|
tmp_file=$(mktemp)
|
|
1231
|
+
trap "rm -f '$tmp_file'" RETURN
|
|
1224
1232
|
jq --argjson corr "$correction" '
|
|
1225
1233
|
.corrections = ((.corrections // []) + [$corr] | .[-100:])
|
|
1226
1234
|
' "$META_LEARNING_DB" > "$tmp_file" && _recruit_locked_write "$META_LEARNING_DB" "$tmp_file" || rm -f "$tmp_file"
|
|
@@ -1267,6 +1275,7 @@ _recruit_reflect() {
|
|
|
1267
1275
|
# Track accuracy trend
|
|
1268
1276
|
local tmp_file
|
|
1269
1277
|
tmp_file=$(mktemp)
|
|
1278
|
+
trap "rm -f '$tmp_file'" RETURN
|
|
1270
1279
|
jq --argjson acc "$accuracy" --arg ts "$(now_iso)" '
|
|
1271
1280
|
.accuracy_trend = ((.accuracy_trend // []) + [{accuracy: $acc, ts: $ts}] | .[-50:]) |
|
|
1272
1281
|
.last_reflection = $ts
|
|
@@ -1355,6 +1364,7 @@ _recruit_meta_validate_self_tune() {
|
|
|
1355
1364
|
# Reset heuristics to empty (forces fallback to keyword_match defaults)
|
|
1356
1365
|
local tmp_heur
|
|
1357
1366
|
tmp_heur=$(mktemp)
|
|
1367
|
+
trap "rm -f '$tmp_heur'" RETURN
|
|
1358
1368
|
echo '{"keyword_weights": {}, "meta_reverted_at": "'"$(now_iso)"'", "revert_reason": "accuracy_below_floor"}' > "$tmp_heur"
|
|
1359
1369
|
_recruit_locked_write "$HEURISTICS_DB" "$tmp_heur" || rm -f "$tmp_heur"
|
|
1360
1370
|
emit_event "recruit_meta_revert" "accuracy=${current_accuracy}" "floor=${accuracy_floor}" "reason=declining_below_floor"
|
|
@@ -1454,6 +1464,7 @@ Return JSON only."
|
|
|
1454
1464
|
|
|
1455
1465
|
local tmp_file
|
|
1456
1466
|
tmp_file=$(mktemp)
|
|
1467
|
+
trap "rm -f '$tmp_file'" RETURN
|
|
1457
1468
|
jq --arg key "$role_key" --argjson role "$role_json" '.[$key] = $role' "$ROLES_DB" > "$tmp_file" && _recruit_locked_write "$ROLES_DB" "$tmp_file" || rm -f "$tmp_file"
|
|
1458
1469
|
|
|
1459
1470
|
# Update heuristics with trigger keywords
|
|
@@ -1462,6 +1473,7 @@ Return JSON only."
|
|
|
1462
1473
|
if [[ -n "$keywords" ]]; then
|
|
1463
1474
|
local heur_tmp
|
|
1464
1475
|
heur_tmp=$(mktemp)
|
|
1476
|
+
trap "rm -f '$heur_tmp'" RETURN
|
|
1465
1477
|
while IFS= read -r kw; do
|
|
1466
1478
|
[[ -z "$kw" ]] && continue
|
|
1467
1479
|
jq --arg kw "$kw" --arg role "$role_key" \
|
|
@@ -1588,6 +1600,7 @@ Return JSON only."
|
|
|
1588
1600
|
# Save the LLM-generated mind profile
|
|
1589
1601
|
local tmp_file
|
|
1590
1602
|
tmp_file=$(mktemp)
|
|
1603
|
+
trap "rm -f '$tmp_file'" RETURN
|
|
1591
1604
|
jq --arg id "$agent_id" --argjson mind "$result" '.[$id] = ($mind + {updated: (now | todate)})' "$AGENT_MINDS_DB" > "$tmp_file" && _recruit_locked_write "$AGENT_MINDS_DB" "$tmp_file" || rm -f "$tmp_file"
|
|
1592
1605
|
|
|
1593
1606
|
success "Mind profile generated:"
|
|
@@ -1629,6 +1642,7 @@ Return JSON only."
|
|
|
1629
1642
|
|
|
1630
1643
|
local tmp_file
|
|
1631
1644
|
tmp_file=$(mktemp)
|
|
1645
|
+
trap "rm -f '$tmp_file'" RETURN
|
|
1632
1646
|
jq --arg id "$agent_id" --argjson mind "$mind_json" '.[$id] = $mind' "$AGENT_MINDS_DB" > "$tmp_file" && _recruit_locked_write "$AGENT_MINDS_DB" "$tmp_file" || rm -f "$tmp_file"
|
|
1633
1647
|
|
|
1634
1648
|
local strengths_display="none detected"
|
|
@@ -1815,6 +1829,7 @@ cmd_self_tune() {
|
|
|
1815
1829
|
|
|
1816
1830
|
local tmp_heuristics
|
|
1817
1831
|
tmp_heuristics=$(mktemp)
|
|
1832
|
+
trap "rm -f '$tmp_heuristics'" RETURN
|
|
1818
1833
|
cp "$HEURISTICS_DB" "$tmp_heuristics"
|
|
1819
1834
|
|
|
1820
1835
|
local i=0
|
|
@@ -2561,6 +2576,7 @@ cmd_audit() {
|
|
|
2561
2576
|
if [[ -f "$META_LEARNING_DB" ]]; then
|
|
2562
2577
|
local tmp_audit
|
|
2563
2578
|
tmp_audit=$(mktemp)
|
|
2579
|
+
trap "rm -f '$tmp_audit'" RETURN
|
|
2564
2580
|
jq --argjson score "$score" --arg ts "$(now_iso)" --argjson fails "$fail_count" '
|
|
2565
2581
|
.audit_trend = ((.audit_trend // []) + [{score: $score, ts: $ts, failures: $fails}] | .[-50:])
|
|
2566
2582
|
' "$META_LEARNING_DB" > "$tmp_audit" && _recruit_locked_write "$META_LEARNING_DB" "$tmp_audit" || rm -f "$tmp_audit"
|
package/scripts/sw-regression.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.
|
|
9
|
+
VERSION="2.3.1"
|
|
10
10
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
12
12
|
|
|
@@ -198,6 +198,7 @@ cmd_baseline() {
|
|
|
198
198
|
|
|
199
199
|
local tmp_file
|
|
200
200
|
tmp_file=$(mktemp "${baseline_file}.tmp.XXXXXX")
|
|
201
|
+
trap "rm -f '$tmp_file'" RETURN
|
|
201
202
|
|
|
202
203
|
echo "$metrics" > "$tmp_file"
|
|
203
204
|
mv "$tmp_file" "$baseline_file"
|
package/scripts/sw-release.sh
CHANGED
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
# ╚═══════════════════════════════════════════════════════════════════════════╝
|
|
6
6
|
set -euo pipefail
|
|
7
7
|
trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
|
|
8
|
+
trap 'rm -f "${tmp_file:-}"' EXIT
|
|
8
9
|
|
|
9
|
-
VERSION="2.
|
|
10
|
+
VERSION="2.3.1"
|
|
10
11
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
12
|
REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
12
13
|
|
|
@@ -258,7 +259,7 @@ generate_changelog_md() {
|
|
|
258
259
|
echo ""
|
|
259
260
|
echo "$breaking_commits" | while IFS='|' read -r hash subject; do
|
|
260
261
|
[[ -z "$hash" ]] && continue
|
|
261
|
-
echo "- $subject ([\`$hash\`](
|
|
262
|
+
echo "- $subject ([\`$hash\`]($(_sw_github_url)/commit/$hash))"
|
|
262
263
|
done
|
|
263
264
|
echo ""
|
|
264
265
|
fi
|
|
@@ -269,7 +270,7 @@ generate_changelog_md() {
|
|
|
269
270
|
echo ""
|
|
270
271
|
echo "$features_commits" | while IFS='|' read -r hash subject; do
|
|
271
272
|
[[ -z "$hash" ]] && continue
|
|
272
|
-
echo "- $subject ([\`$hash\`](
|
|
273
|
+
echo "- $subject ([\`$hash\`]($(_sw_github_url)/commit/$hash))"
|
|
273
274
|
done
|
|
274
275
|
echo ""
|
|
275
276
|
fi
|
|
@@ -280,7 +281,7 @@ generate_changelog_md() {
|
|
|
280
281
|
echo ""
|
|
281
282
|
echo "$fixes_commits" | while IFS='|' read -r hash subject; do
|
|
282
283
|
[[ -z "$hash" ]] && continue
|
|
283
|
-
echo "- $subject ([\`$hash\`](
|
|
284
|
+
echo "- $subject ([\`$hash\`]($(_sw_github_url)/commit/$hash))"
|
|
284
285
|
done
|
|
285
286
|
echo ""
|
|
286
287
|
fi
|
|
@@ -291,7 +292,7 @@ generate_changelog_md() {
|
|
|
291
292
|
echo ""
|
|
292
293
|
echo "$docs_commits" | while IFS='|' read -r hash subject; do
|
|
293
294
|
[[ -z "$hash" ]] && continue
|
|
294
|
-
echo "- $subject ([\`$hash\`](
|
|
295
|
+
echo "- $subject ([\`$hash\`]($(_sw_github_url)/commit/$hash))"
|
|
295
296
|
done
|
|
296
297
|
echo ""
|
|
297
298
|
fi
|
|
@@ -346,6 +347,7 @@ update_version_in_files() {
|
|
|
346
347
|
# This is shell-safe: VERSION="1.11.0" → VERSION="1.12.0"
|
|
347
348
|
local tmp_file
|
|
348
349
|
tmp_file=$(mktemp)
|
|
350
|
+
trap "rm -f '$tmp_file'" RETURN
|
|
349
351
|
sed 's/^VERSION="[^"]*"$/VERSION="'"$version_num"'"/' "$file" > "$tmp_file"
|
|
350
352
|
mv "$tmp_file" "$file"
|
|
351
353
|
success "Updated VERSION in $(basename "$file")"
|
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.
|
|
9
|
+
VERSION="2.3.1"
|
|
10
10
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
|
|
12
12
|
# ─── Cross-platform compatibility ──────────────────────────────────────────
|
|
@@ -465,6 +465,9 @@ cmd_run() {
|
|
|
465
465
|
# Generate report
|
|
466
466
|
generate_retro_report "$from_date" "$to_date" "$analysis" "$agent_perf" "$velocity"
|
|
467
467
|
|
|
468
|
+
# Feed retro into self-optimization loop (|| true to avoid breaking retro if optimization unavailable)
|
|
469
|
+
[[ -f "$SCRIPT_DIR/sw-self-optimize.sh" ]] && "$SCRIPT_DIR/sw-self-optimize.sh" ingest-retro || true
|
|
470
|
+
|
|
468
471
|
# Offer to create issues
|
|
469
472
|
if command -v gh &>/dev/null; then
|
|
470
473
|
echo ""
|
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.
|
|
9
|
+
VERSION="2.3.1"
|
|
10
10
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
|
|
12
12
|
# ─── Dependency check ─────────────────────────────────────────────────────────
|
|
@@ -64,6 +64,7 @@ init_rules() {
|
|
|
64
64
|
if [[ ! -f "$SCALE_RULES_FILE" ]]; then
|
|
65
65
|
local tmp_file
|
|
66
66
|
tmp_file=$(mktemp)
|
|
67
|
+
trap "rm -f '$tmp_file'" RETURN
|
|
67
68
|
cat > "$tmp_file" << 'JSON'
|
|
68
69
|
{
|
|
69
70
|
"iteration_threshold": 3,
|
|
@@ -105,6 +106,7 @@ in_cooldown() {
|
|
|
105
106
|
update_scale_state() {
|
|
106
107
|
local tmp_file
|
|
107
108
|
tmp_file=$(mktemp)
|
|
109
|
+
trap "rm -f '$tmp_file'" RETURN
|
|
108
110
|
|
|
109
111
|
if [[ -f "$SCALE_STATE_FILE" ]]; then
|
|
110
112
|
# Update existing state
|
|
@@ -241,6 +243,7 @@ cmd_rules() {
|
|
|
241
243
|
|
|
242
244
|
local tmp_file
|
|
243
245
|
tmp_file=$(mktemp)
|
|
246
|
+
trap "rm -f '$tmp_file'" RETURN
|
|
244
247
|
|
|
245
248
|
jq --arg key "$key" --arg value "$value" \
|
|
246
249
|
'if ($value | test("^[0-9]+$")) then
|