shipwright-cli 3.1.0 → 3.3.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/.claude/agents/code-reviewer.md +2 -0
- package/.claude/agents/devops-engineer.md +2 -0
- package/.claude/agents/doc-fleet-agent.md +2 -0
- package/.claude/agents/pipeline-agent.md +2 -0
- package/.claude/agents/shell-script-specialist.md +2 -0
- package/.claude/agents/test-specialist.md +2 -0
- package/.claude/hooks/agent-crash-capture.sh +32 -0
- package/.claude/hooks/post-tool-use.sh +3 -2
- package/.claude/hooks/pre-tool-use.sh +35 -3
- package/README.md +22 -8
- package/claude-code/hooks/config-change.sh +18 -0
- package/claude-code/hooks/instructions-reloaded.sh +7 -0
- package/claude-code/hooks/worktree-create.sh +25 -0
- package/claude-code/hooks/worktree-remove.sh +20 -0
- package/config/code-constitution.json +130 -0
- package/config/defaults.json +25 -2
- package/config/policy.json +1 -1
- package/dashboard/middleware/auth.ts +134 -0
- package/dashboard/middleware/constants.ts +21 -0
- package/dashboard/public/index.html +8 -6
- package/dashboard/public/styles.css +176 -97
- package/dashboard/routes/auth.ts +38 -0
- package/dashboard/server.ts +117 -25
- package/dashboard/services/config.ts +26 -0
- package/dashboard/services/db.ts +118 -0
- package/dashboard/src/canvas/pixel-agent.ts +298 -0
- package/dashboard/src/canvas/pixel-sprites.ts +440 -0
- package/dashboard/src/canvas/shipyard-effects.ts +367 -0
- package/dashboard/src/canvas/shipyard-scene.ts +616 -0
- package/dashboard/src/canvas/submarine-layout.ts +267 -0
- package/dashboard/src/components/header.ts +8 -7
- package/dashboard/src/core/api.ts +5 -0
- package/dashboard/src/core/router.ts +1 -0
- package/dashboard/src/design/submarine-theme.ts +253 -0
- package/dashboard/src/main.ts +2 -0
- package/dashboard/src/types/api.ts +12 -1
- package/dashboard/src/views/activity.ts +2 -1
- package/dashboard/src/views/metrics.ts +69 -1
- package/dashboard/src/views/shipyard.ts +39 -0
- package/dashboard/types/index.ts +166 -0
- package/docs/plans/2026-02-28-compound-audit-and-shipyard-design.md +186 -0
- package/docs/plans/2026-02-28-skipper-shipwright-implementation-plan.md +1182 -0
- package/docs/plans/2026-02-28-skipper-shipwright-integration-design.md +531 -0
- package/docs/plans/2026-03-01-ai-powered-skill-injection-design.md +298 -0
- package/docs/plans/2026-03-01-ai-powered-skill-injection-plan.md +1109 -0
- package/docs/plans/2026-03-01-capabilities-cleanup-plan.md +658 -0
- package/docs/plans/2026-03-01-clean-architecture-plan.md +924 -0
- package/docs/plans/2026-03-01-compound-audit-cascade-design.md +191 -0
- package/docs/plans/2026-03-01-compound-audit-cascade-plan.md +921 -0
- package/docs/plans/2026-03-01-deep-integration-plan.md +851 -0
- package/docs/plans/2026-03-01-pipeline-audit-trail-design.md +145 -0
- package/docs/plans/2026-03-01-pipeline-audit-trail-plan.md +770 -0
- package/docs/plans/2026-03-01-refined-depths-brand-design.md +382 -0
- package/docs/plans/2026-03-01-refined-depths-implementation.md +599 -0
- package/docs/plans/2026-03-01-skipper-kernel-integration-design.md +203 -0
- package/docs/plans/2026-03-01-unified-platform-design.md +272 -0
- package/docs/plans/2026-03-07-claude-code-feature-integration-design.md +189 -0
- package/docs/plans/2026-03-07-claude-code-feature-integration-plan.md +1165 -0
- package/docs/research/BACKLOG_QUICK_REFERENCE.md +352 -0
- package/docs/research/CUTTING_EDGE_RESEARCH_2026.md +546 -0
- package/docs/research/RESEARCH_INDEX.md +439 -0
- package/docs/research/RESEARCH_SOURCES.md +440 -0
- package/docs/research/RESEARCH_SUMMARY.txt +275 -0
- package/docs/superpowers/specs/2026-03-10-pipeline-quality-revolution-design.md +341 -0
- package/package.json +2 -2
- package/scripts/lib/adaptive-model.sh +427 -0
- package/scripts/lib/adaptive-timeout.sh +316 -0
- package/scripts/lib/audit-trail.sh +309 -0
- package/scripts/lib/auto-recovery.sh +471 -0
- package/scripts/lib/bandit-selector.sh +431 -0
- package/scripts/lib/bootstrap.sh +104 -2
- package/scripts/lib/causal-graph.sh +455 -0
- package/scripts/lib/compat.sh +126 -0
- package/scripts/lib/compound-audit.sh +337 -0
- package/scripts/lib/constitutional.sh +454 -0
- package/scripts/lib/context-budget.sh +359 -0
- package/scripts/lib/convergence.sh +594 -0
- package/scripts/lib/cost-optimizer.sh +634 -0
- package/scripts/lib/daemon-adaptive.sh +14 -2
- package/scripts/lib/daemon-dispatch.sh +106 -17
- package/scripts/lib/daemon-failure.sh +34 -4
- package/scripts/lib/daemon-patrol.sh +25 -4
- package/scripts/lib/daemon-poll-github.sh +361 -0
- package/scripts/lib/daemon-poll-health.sh +299 -0
- package/scripts/lib/daemon-poll.sh +27 -611
- package/scripts/lib/daemon-state.sh +119 -66
- package/scripts/lib/daemon-triage.sh +10 -0
- package/scripts/lib/dod-scorecard.sh +442 -0
- package/scripts/lib/error-actionability.sh +300 -0
- package/scripts/lib/formal-spec.sh +461 -0
- package/scripts/lib/helpers.sh +180 -5
- package/scripts/lib/intent-analysis.sh +409 -0
- package/scripts/lib/loop-convergence.sh +350 -0
- package/scripts/lib/loop-iteration.sh +682 -0
- package/scripts/lib/loop-progress.sh +48 -0
- package/scripts/lib/loop-restart.sh +185 -0
- package/scripts/lib/memory-effectiveness.sh +506 -0
- package/scripts/lib/mutation-executor.sh +352 -0
- package/scripts/lib/outcome-feedback.sh +521 -0
- package/scripts/lib/pipeline-cli.sh +336 -0
- package/scripts/lib/pipeline-commands.sh +1216 -0
- package/scripts/lib/pipeline-detection.sh +101 -3
- package/scripts/lib/pipeline-execution.sh +897 -0
- package/scripts/lib/pipeline-github.sh +28 -3
- package/scripts/lib/pipeline-intelligence-compound.sh +431 -0
- package/scripts/lib/pipeline-intelligence-scoring.sh +407 -0
- package/scripts/lib/pipeline-intelligence-skip.sh +181 -0
- package/scripts/lib/pipeline-intelligence.sh +104 -1138
- package/scripts/lib/pipeline-quality-bash-compat.sh +182 -0
- package/scripts/lib/pipeline-quality-checks.sh +17 -711
- package/scripts/lib/pipeline-quality-gates.sh +563 -0
- package/scripts/lib/pipeline-stages-build.sh +730 -0
- package/scripts/lib/pipeline-stages-delivery.sh +965 -0
- package/scripts/lib/pipeline-stages-intake.sh +1133 -0
- package/scripts/lib/pipeline-stages-monitor.sh +407 -0
- package/scripts/lib/pipeline-stages-review.sh +1022 -0
- package/scripts/lib/pipeline-stages.sh +161 -2901
- package/scripts/lib/pipeline-state.sh +36 -5
- package/scripts/lib/pipeline-util.sh +487 -0
- package/scripts/lib/policy-learner.sh +438 -0
- package/scripts/lib/process-reward.sh +493 -0
- package/scripts/lib/project-detect.sh +649 -0
- package/scripts/lib/quality-profile.sh +334 -0
- package/scripts/lib/recruit-commands.sh +885 -0
- package/scripts/lib/recruit-learning.sh +739 -0
- package/scripts/lib/recruit-roles.sh +648 -0
- package/scripts/lib/reward-aggregator.sh +458 -0
- package/scripts/lib/rl-optimizer.sh +362 -0
- package/scripts/lib/root-cause.sh +427 -0
- package/scripts/lib/scope-enforcement.sh +445 -0
- package/scripts/lib/session-restart.sh +493 -0
- package/scripts/lib/skill-memory.sh +300 -0
- package/scripts/lib/skill-registry.sh +775 -0
- package/scripts/lib/spec-driven.sh +476 -0
- package/scripts/lib/test-helpers.sh +18 -7
- package/scripts/lib/test-holdout.sh +429 -0
- package/scripts/lib/test-optimizer.sh +511 -0
- package/scripts/shipwright-file-suggest.sh +45 -0
- package/scripts/skills/adversarial-quality.md +61 -0
- package/scripts/skills/api-design.md +44 -0
- package/scripts/skills/architecture-design.md +50 -0
- package/scripts/skills/brainstorming.md +43 -0
- package/scripts/skills/data-pipeline.md +44 -0
- package/scripts/skills/deploy-safety.md +64 -0
- package/scripts/skills/documentation.md +38 -0
- package/scripts/skills/frontend-design.md +45 -0
- package/scripts/skills/generated/.gitkeep +0 -0
- package/scripts/skills/generated/_refinements/.gitkeep +0 -0
- package/scripts/skills/generated/_refinements/adversarial-quality.patch.md +3 -0
- package/scripts/skills/generated/_refinements/architecture-design.patch.md +3 -0
- package/scripts/skills/generated/_refinements/brainstorming.patch.md +3 -0
- package/scripts/skills/generated/cli-version-management.md +29 -0
- package/scripts/skills/generated/collection-system-validation.md +99 -0
- package/scripts/skills/generated/large-scale-c-refactoring-coordination.md +97 -0
- package/scripts/skills/generated/pattern-matching-similarity-scoring.md +195 -0
- package/scripts/skills/generated/test-parallelization-detection.md +65 -0
- package/scripts/skills/observability.md +79 -0
- package/scripts/skills/performance.md +48 -0
- package/scripts/skills/pr-quality.md +49 -0
- package/scripts/skills/product-thinking.md +43 -0
- package/scripts/skills/security-audit.md +49 -0
- package/scripts/skills/systematic-debugging.md +40 -0
- package/scripts/skills/testing-strategy.md +47 -0
- package/scripts/skills/two-stage-review.md +52 -0
- package/scripts/skills/validation-thoroughness.md +55 -0
- package/scripts/sw +9 -3
- package/scripts/sw-activity.sh +9 -8
- package/scripts/sw-adaptive.sh +8 -7
- package/scripts/sw-adversarial.sh +2 -1
- package/scripts/sw-architecture-enforcer.sh +3 -1
- package/scripts/sw-auth.sh +12 -2
- package/scripts/sw-autonomous.sh +5 -1
- package/scripts/sw-changelog.sh +4 -1
- package/scripts/sw-checkpoint.sh +2 -1
- package/scripts/sw-ci.sh +15 -6
- package/scripts/sw-cleanup.sh +4 -26
- package/scripts/sw-code-review.sh +45 -20
- package/scripts/sw-connect.sh +2 -1
- package/scripts/sw-context.sh +2 -1
- package/scripts/sw-cost.sh +107 -5
- package/scripts/sw-daemon.sh +71 -11
- package/scripts/sw-dashboard.sh +3 -1
- package/scripts/sw-db.sh +71 -20
- package/scripts/sw-decide.sh +8 -2
- package/scripts/sw-decompose.sh +360 -17
- package/scripts/sw-deps.sh +4 -1
- package/scripts/sw-developer-simulation.sh +4 -1
- package/scripts/sw-discovery.sh +378 -5
- package/scripts/sw-doc-fleet.sh +4 -1
- package/scripts/sw-docs-agent.sh +3 -1
- package/scripts/sw-docs.sh +2 -1
- package/scripts/sw-doctor.sh +453 -2
- package/scripts/sw-dora.sh +4 -1
- package/scripts/sw-durable.sh +12 -7
- package/scripts/sw-e2e-orchestrator.sh +17 -16
- package/scripts/sw-eventbus.sh +13 -4
- package/scripts/sw-evidence.sh +364 -12
- package/scripts/sw-feedback.sh +550 -9
- package/scripts/sw-fix.sh +20 -1
- package/scripts/sw-fleet-discover.sh +6 -2
- package/scripts/sw-fleet-viz.sh +9 -4
- package/scripts/sw-fleet.sh +5 -1
- package/scripts/sw-github-app.sh +18 -4
- package/scripts/sw-github-checks.sh +3 -2
- package/scripts/sw-github-deploy.sh +3 -2
- package/scripts/sw-github-graphql.sh +18 -7
- package/scripts/sw-guild.sh +5 -1
- package/scripts/sw-heartbeat.sh +5 -30
- package/scripts/sw-hello.sh +67 -0
- package/scripts/sw-hygiene.sh +10 -3
- package/scripts/sw-incident.sh +273 -5
- package/scripts/sw-init.sh +18 -2
- package/scripts/sw-instrument.sh +10 -2
- package/scripts/sw-intelligence.sh +44 -7
- package/scripts/sw-jira.sh +5 -1
- package/scripts/sw-launchd.sh +2 -1
- package/scripts/sw-linear.sh +4 -1
- package/scripts/sw-logs.sh +4 -1
- package/scripts/sw-loop.sh +436 -1076
- package/scripts/sw-memory.sh +357 -3
- package/scripts/sw-mission-control.sh +6 -1
- package/scripts/sw-model-router.sh +483 -27
- package/scripts/sw-otel.sh +15 -4
- package/scripts/sw-oversight.sh +14 -5
- package/scripts/sw-patrol-meta.sh +334 -0
- package/scripts/sw-pipeline-composer.sh +7 -1
- package/scripts/sw-pipeline-vitals.sh +12 -6
- package/scripts/sw-pipeline.sh +54 -2653
- package/scripts/sw-pm.sh +16 -8
- package/scripts/sw-pr-lifecycle.sh +2 -1
- package/scripts/sw-predictive.sh +17 -5
- package/scripts/sw-prep.sh +185 -2
- package/scripts/sw-ps.sh +5 -25
- package/scripts/sw-public-dashboard.sh +17 -4
- package/scripts/sw-quality.sh +14 -6
- package/scripts/sw-reaper.sh +8 -25
- package/scripts/sw-recruit.sh +156 -2303
- package/scripts/sw-regression.sh +19 -12
- package/scripts/sw-release-manager.sh +3 -1
- package/scripts/sw-release.sh +4 -1
- package/scripts/sw-remote.sh +3 -1
- package/scripts/sw-replay.sh +7 -1
- package/scripts/sw-retro.sh +158 -1
- package/scripts/sw-review-rerun.sh +3 -1
- package/scripts/sw-scale.sh +14 -5
- package/scripts/sw-security-audit.sh +6 -1
- package/scripts/sw-self-optimize.sh +173 -6
- package/scripts/sw-session.sh +9 -3
- package/scripts/sw-setup.sh +3 -1
- package/scripts/sw-stall-detector.sh +406 -0
- package/scripts/sw-standup.sh +15 -7
- package/scripts/sw-status.sh +3 -1
- package/scripts/sw-strategic.sh +14 -6
- package/scripts/sw-stream.sh +13 -4
- package/scripts/sw-swarm.sh +20 -7
- package/scripts/sw-team-stages.sh +13 -6
- package/scripts/sw-templates.sh +7 -31
- package/scripts/sw-testgen.sh +17 -6
- package/scripts/sw-tmux-pipeline.sh +4 -1
- package/scripts/sw-tmux-role-color.sh +2 -0
- package/scripts/sw-tmux-status.sh +1 -1
- package/scripts/sw-tmux.sh +37 -1
- package/scripts/sw-trace.sh +3 -1
- package/scripts/sw-tracker-github.sh +3 -0
- package/scripts/sw-tracker-jira.sh +3 -0
- package/scripts/sw-tracker-linear.sh +3 -0
- package/scripts/sw-tracker.sh +3 -1
- package/scripts/sw-triage.sh +3 -2
- package/scripts/sw-upgrade.sh +3 -1
- package/scripts/sw-ux.sh +5 -2
- package/scripts/sw-webhook.sh +5 -2
- package/scripts/sw-widgets.sh +9 -4
- package/scripts/sw-worktree.sh +15 -3
- package/scripts/test-skill-injection.sh +1233 -0
- package/templates/pipelines/autonomous.json +27 -3
- package/templates/pipelines/cost-aware.json +34 -8
- package/templates/pipelines/deployed.json +12 -0
- package/templates/pipelines/enterprise.json +12 -0
- package/templates/pipelines/fast.json +6 -0
- package/templates/pipelines/full.json +27 -3
- package/templates/pipelines/hotfix.json +6 -0
- package/templates/pipelines/standard.json +12 -0
- package/templates/pipelines/tdd.json +12 -0
package/scripts/sw-otel.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.3.0"
|
|
10
10
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
12
12
|
|
|
@@ -29,7 +29,7 @@ fi
|
|
|
29
29
|
if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
|
|
30
30
|
emit_event() {
|
|
31
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\""
|
|
32
|
+
local payload; payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
|
|
33
33
|
while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
|
|
34
34
|
echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
|
|
35
35
|
}
|
|
@@ -61,17 +61,22 @@ cmd_metrics() {
|
|
|
61
61
|
# Status breakdown
|
|
62
62
|
local status_success=0
|
|
63
63
|
local status_failed=0
|
|
64
|
+
# shellcheck disable=SC2034
|
|
64
65
|
local status_running=0
|
|
65
66
|
|
|
66
67
|
# Template counts
|
|
68
|
+
# shellcheck disable=SC2034
|
|
67
69
|
declare -a templates
|
|
70
|
+
# shellcheck disable=SC2034
|
|
68
71
|
declare -a template_counts
|
|
69
72
|
|
|
70
73
|
# Stage timing
|
|
74
|
+
# shellcheck disable=SC2034
|
|
71
75
|
declare -a stages
|
|
72
76
|
declare -a stage_durations
|
|
73
77
|
|
|
74
78
|
# Model costs
|
|
79
|
+
# shellcheck disable=SC2034
|
|
75
80
|
declare -a models
|
|
76
81
|
declare -a model_costs
|
|
77
82
|
|
|
@@ -216,11 +221,13 @@ EOF
|
|
|
216
221
|
# ─── OpenTelemetry Traces ────────────────────────────────────────────────────
|
|
217
222
|
|
|
218
223
|
cmd_trace() {
|
|
224
|
+
# shellcheck disable=SC2034
|
|
219
225
|
local pipeline_id="${1:-latest}"
|
|
220
226
|
|
|
221
227
|
ensure_otel_dir
|
|
222
228
|
|
|
223
229
|
# Build trace from events
|
|
230
|
+
# shellcheck disable=SC2034
|
|
224
231
|
local traces='[]'
|
|
225
232
|
local spans='[]'
|
|
226
233
|
local root_span=""
|
|
@@ -262,7 +269,7 @@ EOF
|
|
|
262
269
|
;;
|
|
263
270
|
stage_start)
|
|
264
271
|
stage=$(echo "$line" | jq -r '.stage // "unknown"' 2>/dev/null || true)
|
|
265
|
-
local span_id="${stage:0:8}$(printf '%08x' $((RANDOM * 256 + RANDOM)))"
|
|
272
|
+
local span_id; span_id="${stage:0:8}$(printf '%08x' $((RANDOM * 256 + RANDOM)))"
|
|
266
273
|
spans=$(echo "$spans" | jq --arg span_id "$span_id" --arg stage "$stage" --arg ts "$ts" \
|
|
267
274
|
'. += [{
|
|
268
275
|
"traceId": "'${pipeline:0:16}'",
|
|
@@ -316,6 +323,7 @@ cmd_export() {
|
|
|
316
323
|
local auth_header=""
|
|
317
324
|
|
|
318
325
|
if [[ -n "${OTEL_EXPORTER_OTLP_HEADERS:-}" ]]; then
|
|
326
|
+
# shellcheck disable=SC2089
|
|
319
327
|
auth_header="-H '${OTEL_EXPORTER_OTLP_HEADERS}'"
|
|
320
328
|
fi
|
|
321
329
|
|
|
@@ -325,6 +333,7 @@ cmd_export() {
|
|
|
325
333
|
if [[ "$format" == "trace" ]]; then
|
|
326
334
|
payload=$(cmd_trace)
|
|
327
335
|
local response
|
|
336
|
+
# shellcheck disable=SC2090
|
|
328
337
|
response=$(curl -s --connect-timeout 10 --max-time 30 -X POST \
|
|
329
338
|
"$endpoint/v1/traces" \
|
|
330
339
|
-H "Content-Type: application/json" \
|
|
@@ -340,6 +349,7 @@ cmd_export() {
|
|
|
340
349
|
else
|
|
341
350
|
payload=$(cmd_metrics text)
|
|
342
351
|
local response
|
|
352
|
+
# shellcheck disable=SC2090
|
|
343
353
|
response=$(curl -s --connect-timeout 10 --max-time 30 -X POST \
|
|
344
354
|
"$endpoint/metrics" \
|
|
345
355
|
-H "Content-Type: text/plain" \
|
|
@@ -462,7 +472,8 @@ cmd_report() {
|
|
|
462
472
|
local last_event_ts=""
|
|
463
473
|
|
|
464
474
|
if [[ -f "$EVENTS_FILE" ]]; then
|
|
465
|
-
event_count=$(wc -l < "$EVENTS_FILE" ||
|
|
475
|
+
event_count=$(wc -l < "$EVENTS_FILE" || true)
|
|
476
|
+
event_count="${event_count:-0}"
|
|
466
477
|
export_count=$(grep -c '"type":"otel_export"' "$EVENTS_FILE" 2>/dev/null || true)
|
|
467
478
|
export_count="${export_count:-0}"
|
|
468
479
|
webhook_count=$(grep -c '"type":"webhook_sent"' "$EVENTS_FILE" 2>/dev/null || true)
|
package/scripts/sw-oversight.sh
CHANGED
|
@@ -7,8 +7,10 @@
|
|
|
7
7
|
set -euo pipefail
|
|
8
8
|
trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
# shellcheck disable=SC2034
|
|
11
|
+
VERSION="3.3.0"
|
|
11
12
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
13
|
+
# shellcheck disable=SC2034
|
|
12
14
|
REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
13
15
|
|
|
14
16
|
# ─── Cross-platform compatibility ──────────────────────────────────────────
|
|
@@ -29,17 +31,20 @@ fi
|
|
|
29
31
|
if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
|
|
30
32
|
emit_event() {
|
|
31
33
|
local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
|
|
32
|
-
local payload
|
|
34
|
+
local payload
|
|
35
|
+
payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
|
|
33
36
|
while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
|
|
34
37
|
echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
|
|
35
38
|
}
|
|
36
39
|
fi
|
|
37
40
|
# ─── Structured Event Log ────────────────────────────────────────────────
|
|
41
|
+
# shellcheck disable=SC2034
|
|
38
42
|
EVENTS_FILE="${HOME}/.shipwright/events.jsonl"
|
|
39
43
|
|
|
40
44
|
# ─── State & Configuration ────────────────────────────────────────────────
|
|
41
45
|
OVERSIGHT_ROOT="${HOME}/.shipwright/oversight"
|
|
42
46
|
BOARD_CONFIG="${OVERSIGHT_ROOT}/config.json"
|
|
47
|
+
# shellcheck disable=SC2034
|
|
43
48
|
REVIEW_LOG="${OVERSIGHT_ROOT}/reviews.jsonl"
|
|
44
49
|
HISTORY_DIR="${OVERSIGHT_ROOT}/history"
|
|
45
50
|
MEMBERS_FILE="${OVERSIGHT_ROOT}/members.json"
|
|
@@ -206,6 +211,7 @@ cmd_vote() {
|
|
|
206
211
|
|
|
207
212
|
# Update review with vote
|
|
208
213
|
local tmp_file="${review_file}.tmp"
|
|
214
|
+
# shellcheck disable=SC2046
|
|
209
215
|
jq --arg reviewer "$reviewer" \
|
|
210
216
|
--arg decision "$decision" \
|
|
211
217
|
--arg reasoning "${reasoning//\"/\\\"}" \
|
|
@@ -214,7 +220,7 @@ cmd_vote() {
|
|
|
214
220
|
"decision": $decision,
|
|
215
221
|
"reasoning": $reasoning,
|
|
216
222
|
"confidence": ($confidence | tonumber),
|
|
217
|
-
"voted_at": "'$(now_iso)'"
|
|
223
|
+
"voted_at": "'"$(now_iso)"'"
|
|
218
224
|
}' "$review_file" > "$tmp_file"
|
|
219
225
|
mv "$tmp_file" "$review_file"
|
|
220
226
|
|
|
@@ -278,9 +284,11 @@ _update_verdict() {
|
|
|
278
284
|
approve_ratio=$(echo "$approve_count / $active_votes" | bc -l 2>/dev/null || echo "0")
|
|
279
285
|
|
|
280
286
|
local quorum_num
|
|
287
|
+
# shellcheck disable=SC2034
|
|
281
288
|
quorum_num=$(echo "$quorum * 100" | bc 2>/dev/null || echo "50")
|
|
282
289
|
|
|
283
290
|
local approve_pct
|
|
291
|
+
# shellcheck disable=SC2034
|
|
284
292
|
approve_pct=$(echo "$approve_ratio * 100" | bc 2>/dev/null || echo "0")
|
|
285
293
|
|
|
286
294
|
# Check if quorum met and decision reached
|
|
@@ -375,7 +383,7 @@ cmd_gate() {
|
|
|
375
383
|
"decision": $decision,
|
|
376
384
|
"reasoning": $reasoning,
|
|
377
385
|
"confidence": ($confidence | tonumber),
|
|
378
|
-
"voted_at": "'$(now_iso)'"
|
|
386
|
+
"voted_at": "'"$(now_iso)"'"
|
|
379
387
|
}' "$review_file" > "$tmp_file"
|
|
380
388
|
mv "$tmp_file" "$review_file"
|
|
381
389
|
|
|
@@ -626,7 +634,8 @@ cmd_appeal() {
|
|
|
626
634
|
fi
|
|
627
635
|
|
|
628
636
|
local tmp_file="${review_file}.tmp"
|
|
629
|
-
|
|
637
|
+
# shellcheck disable=SC2046
|
|
638
|
+
jq --arg message "$message" '.appeals += [{"message": $message, "appealed_at": "'"$(now_iso)"'"}]' "$review_file" > "$tmp_file"
|
|
630
639
|
mv "$tmp_file" "$review_file"
|
|
631
640
|
|
|
632
641
|
success "Appeal submitted ($((appeal_count + 1))/$max_appeals)"
|
|
@@ -22,6 +22,7 @@ fi
|
|
|
22
22
|
if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
|
|
23
23
|
emit_event() {
|
|
24
24
|
local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
|
|
25
|
+
# shellcheck disable=SC2155
|
|
25
26
|
local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
|
|
26
27
|
while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
|
|
27
28
|
echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
|
|
@@ -174,6 +175,7 @@ _Auto-generated by Shipwright meta-patrol_"
|
|
|
174
175
|
# ─── Check 3: VERSION Sync ─────────────────────────────────────────────────
|
|
175
176
|
patrol_meta_version_sync() {
|
|
176
177
|
info " Checking VERSION consistency..."
|
|
178
|
+
# shellcheck disable=SC2034
|
|
177
179
|
local versions=""
|
|
178
180
|
local mismatches=""
|
|
179
181
|
local reference_version=""
|
|
@@ -297,6 +299,7 @@ patrol_meta_template_effectiveness() {
|
|
|
297
299
|
local best_template best_rate worst_template worst_rate
|
|
298
300
|
best_template=$(echo "$template_stats" | jq -r '.[0].template' 2>/dev/null || echo "unknown")
|
|
299
301
|
best_rate=$(echo "$template_stats" | jq -r '.[0].rate' 2>/dev/null || echo "0")
|
|
302
|
+
# shellcheck disable=SC2034
|
|
300
303
|
worst_template=$(echo "$template_stats" | jq -r '.[-1].template' 2>/dev/null || echo "unknown")
|
|
301
304
|
worst_rate=$(echo "$template_stats" | jq -r '.[-1].rate' 2>/dev/null || echo "0")
|
|
302
305
|
|
|
@@ -426,6 +429,337 @@ _Auto-generated by Shipwright meta-patrol_"
|
|
|
426
429
|
fi
|
|
427
430
|
}
|
|
428
431
|
|
|
432
|
+
# ─── Score Impact: Estimate DORA Metric Impact ────────────────────────────
|
|
433
|
+
patrol_meta_score_impact() {
|
|
434
|
+
local title="$1"
|
|
435
|
+
local category="${2:-general}"
|
|
436
|
+
|
|
437
|
+
# Assign impact scores (0-100) based on category and title keywords
|
|
438
|
+
local score=50 # Default
|
|
439
|
+
|
|
440
|
+
case "$category" in
|
|
441
|
+
bash-compat)
|
|
442
|
+
# Bash compatibility affects reliability
|
|
443
|
+
score=65
|
|
444
|
+
;;
|
|
445
|
+
version-sync)
|
|
446
|
+
# Version inconsistencies affect deployment
|
|
447
|
+
score=55
|
|
448
|
+
;;
|
|
449
|
+
untested-scripts)
|
|
450
|
+
# Test coverage directly affects change failure rate
|
|
451
|
+
score=75
|
|
452
|
+
;;
|
|
453
|
+
dora-regression)
|
|
454
|
+
# DORA regressions are critical
|
|
455
|
+
score=85
|
|
456
|
+
;;
|
|
457
|
+
template-effectiveness)
|
|
458
|
+
# Template improvements affect lead time
|
|
459
|
+
score=70
|
|
460
|
+
;;
|
|
461
|
+
memory-pruning)
|
|
462
|
+
# Memory cleanup affects reliability
|
|
463
|
+
score=45
|
|
464
|
+
;;
|
|
465
|
+
recurring-failures)
|
|
466
|
+
# Recurring failures directly affect MTTR and CFR
|
|
467
|
+
score=80
|
|
468
|
+
;;
|
|
469
|
+
esac
|
|
470
|
+
|
|
471
|
+
# Adjust based on title keywords
|
|
472
|
+
if echo "$title" | grep -qi "critical\|regression\|failure"; then
|
|
473
|
+
score=$((score + 15))
|
|
474
|
+
fi
|
|
475
|
+
if echo "$title" | grep -qi "lead.*time\|deployment"; then
|
|
476
|
+
score=$((score + 10))
|
|
477
|
+
fi
|
|
478
|
+
|
|
479
|
+
# Cap at 100
|
|
480
|
+
[[ $score -gt 100 ]] && score=100
|
|
481
|
+
|
|
482
|
+
echo "$score"
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
# ─── Execute Fix: Trigger Pipeline for Improvement Issue ──────────────────
|
|
486
|
+
patrol_meta_execute_fix() {
|
|
487
|
+
local issue_number="$1"
|
|
488
|
+
local title="$2"
|
|
489
|
+
|
|
490
|
+
if [[ "${NO_GITHUB:-false}" == "true" ]]; then
|
|
491
|
+
info " [dry-run] Would start pipeline for issue #${issue_number}"
|
|
492
|
+
return 0
|
|
493
|
+
fi
|
|
494
|
+
|
|
495
|
+
if ! command -v shipwright >/dev/null 2>&1 && ! command -v sw >/dev/null 2>&1; then
|
|
496
|
+
warn " shipwright CLI not available, skipping pipeline execution"
|
|
497
|
+
return 1
|
|
498
|
+
fi
|
|
499
|
+
|
|
500
|
+
info " Starting pipeline for issue #${issue_number}: ${title}"
|
|
501
|
+
|
|
502
|
+
# Run pipeline in isolated worktree to avoid conflicts
|
|
503
|
+
if shipwright pipeline start --issue "$issue_number" --worktree 2>/dev/null; then
|
|
504
|
+
emit_event "patrol.meta_pipeline_started" "issue=$issue_number" "title=$title"
|
|
505
|
+
return 0
|
|
506
|
+
else
|
|
507
|
+
warn " Failed to start pipeline for issue #${issue_number}"
|
|
508
|
+
return 1
|
|
509
|
+
fi
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
# ─── Verify Fix: Re-run Relevant Check After Fix ──────────────────────────
|
|
513
|
+
patrol_meta_verify_fix() {
|
|
514
|
+
local category="$1"
|
|
515
|
+
local issue_number="$2"
|
|
516
|
+
|
|
517
|
+
if [[ "${NO_GITHUB:-false}" == "true" ]]; then
|
|
518
|
+
info " [dry-run] Would verify fix for issue #${issue_number}"
|
|
519
|
+
return 0
|
|
520
|
+
fi
|
|
521
|
+
|
|
522
|
+
info " Verifying fix for issue #${issue_number} (category: ${category})"
|
|
523
|
+
|
|
524
|
+
case "$category" in
|
|
525
|
+
untested-scripts)
|
|
526
|
+
patrol_meta_untested_scripts > /dev/null 2>&1
|
|
527
|
+
;;
|
|
528
|
+
bash-compat)
|
|
529
|
+
patrol_meta_bash_compat > /dev/null 2>&1
|
|
530
|
+
;;
|
|
531
|
+
version-sync)
|
|
532
|
+
patrol_meta_version_sync > /dev/null 2>&1
|
|
533
|
+
;;
|
|
534
|
+
dora-regression)
|
|
535
|
+
patrol_meta_dora_trends > /dev/null 2>&1
|
|
536
|
+
;;
|
|
537
|
+
template-effectiveness)
|
|
538
|
+
patrol_meta_template_effectiveness > /dev/null 2>&1
|
|
539
|
+
;;
|
|
540
|
+
memory-pruning)
|
|
541
|
+
patrol_meta_memory_pruning > /dev/null 2>&1
|
|
542
|
+
;;
|
|
543
|
+
recurring-failures)
|
|
544
|
+
patrol_meta_event_analysis > /dev/null 2>&1
|
|
545
|
+
;;
|
|
546
|
+
*)
|
|
547
|
+
warn " Unknown category: ${category}"
|
|
548
|
+
return 1
|
|
549
|
+
;;
|
|
550
|
+
esac
|
|
551
|
+
|
|
552
|
+
emit_event "patrol.meta_verified" "issue=$issue_number" "category=$category"
|
|
553
|
+
return 0
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
# ─── Rollback on Regression: Auto-revert if Metrics Regress ────────────────
|
|
557
|
+
patrol_meta_rollback() {
|
|
558
|
+
local issue_number="$1"
|
|
559
|
+
|
|
560
|
+
if [[ "${NO_GITHUB:-false}" == "true" ]]; then
|
|
561
|
+
info " [dry-run] Would rollback issue #${issue_number}"
|
|
562
|
+
return 0
|
|
563
|
+
fi
|
|
564
|
+
|
|
565
|
+
warn " Metrics regression detected for issue #${issue_number}"
|
|
566
|
+
|
|
567
|
+
# Get the PR associated with this issue
|
|
568
|
+
local pr_number
|
|
569
|
+
pr_number=$(gh issue view "$issue_number" --json "pullRequests" --jq ".pullRequests[0].number" 2>/dev/null || echo "")
|
|
570
|
+
|
|
571
|
+
if [[ -n "$pr_number" ]]; then
|
|
572
|
+
info " Reverting PR #${pr_number} due to metric regression"
|
|
573
|
+
|
|
574
|
+
# Check out the branch, revert the PR commit, force push
|
|
575
|
+
local branch
|
|
576
|
+
branch=$(gh pr view "$pr_number" --json "headRefName" --jq ".headRefName" 2>/dev/null || echo "")
|
|
577
|
+
|
|
578
|
+
if [[ -n "$branch" ]]; then
|
|
579
|
+
(
|
|
580
|
+
git fetch origin "$branch" 2>/dev/null || true
|
|
581
|
+
git checkout "$branch" 2>/dev/null || return 1
|
|
582
|
+
git revert HEAD --no-edit 2>/dev/null || return 1
|
|
583
|
+
git push origin "$branch" --force 2>/dev/null || return 1
|
|
584
|
+
emit_event "patrol.meta_rollback" "issue=$issue_number" "pr=$pr_number"
|
|
585
|
+
) || {
|
|
586
|
+
warn " Failed to rollback PR #${pr_number}"
|
|
587
|
+
return 1
|
|
588
|
+
}
|
|
589
|
+
fi
|
|
590
|
+
fi
|
|
591
|
+
|
|
592
|
+
return 0
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
# ─── Learn: Record Outcome in Memory System ────────────────────────────────
|
|
596
|
+
patrol_meta_learn() {
|
|
597
|
+
local issue_number="$1"
|
|
598
|
+
local category="$2"
|
|
599
|
+
local success="$3"
|
|
600
|
+
local metrics_change="${4:-}"
|
|
601
|
+
|
|
602
|
+
local memory_dir="$HOME/.shipwright/memory"
|
|
603
|
+
mkdir -p "$memory_dir"
|
|
604
|
+
|
|
605
|
+
local learning_file="$memory_dir/self-improvements.jsonl"
|
|
606
|
+
local ts
|
|
607
|
+
ts=$(now_iso)
|
|
608
|
+
|
|
609
|
+
local outcome="success"
|
|
610
|
+
[[ "$success" != "true" ]] && outcome="failure"
|
|
611
|
+
|
|
612
|
+
# Append to learning log
|
|
613
|
+
local entry
|
|
614
|
+
entry=$(jq -n \
|
|
615
|
+
--arg issue "$issue_number" \
|
|
616
|
+
--arg category "$category" \
|
|
617
|
+
--arg outcome "$outcome" \
|
|
618
|
+
--arg metrics "$metrics_change" \
|
|
619
|
+
--arg ts "$ts" \
|
|
620
|
+
'{issue:$issue, category:$category, outcome:$outcome, metrics_impact:$metrics, timestamp:$ts}')
|
|
621
|
+
|
|
622
|
+
echo "$entry" >> "$learning_file"
|
|
623
|
+
emit_event "patrol.meta_learned" "issue=$issue_number" "category=$category" "outcome=$outcome"
|
|
624
|
+
|
|
625
|
+
success " Recorded learning: issue #${issue_number} ${outcome}"
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
# ─── Batch Improve: Process Multiple Issues in Parallel ─────────────────────
|
|
629
|
+
patrol_meta_batch_improve() {
|
|
630
|
+
local -a issues_to_fix
|
|
631
|
+
local count=0
|
|
632
|
+
|
|
633
|
+
info " Collecting recent meta-patrol issues to fix..."
|
|
634
|
+
|
|
635
|
+
if [[ "${NO_GITHUB:-false}" == "true" ]]; then
|
|
636
|
+
info " [dry-run] Would process batch improvements"
|
|
637
|
+
return 0
|
|
638
|
+
fi
|
|
639
|
+
|
|
640
|
+
# Find recent open meta-improvement issues
|
|
641
|
+
while IFS= read -r line; do
|
|
642
|
+
if [[ -z "$line" ]]; then continue; fi
|
|
643
|
+
local issue_num category title
|
|
644
|
+
issue_num=$(echo "$line" | jq -r '.number' 2>/dev/null || echo "")
|
|
645
|
+
title=$(echo "$line" | jq -r '.title' 2>/dev/null || echo "")
|
|
646
|
+
|
|
647
|
+
if [[ -n "$issue_num" && -n "$title" ]]; then
|
|
648
|
+
# Determine category from title
|
|
649
|
+
if echo "$title" | grep -qi "test"; then
|
|
650
|
+
category="untested-scripts"
|
|
651
|
+
elif echo "$title" | grep -qi "bash"; then
|
|
652
|
+
category="bash-compat"
|
|
653
|
+
elif echo "$title" | grep -qi "version"; then
|
|
654
|
+
category="version-sync"
|
|
655
|
+
elif echo "$title" | grep -qi "lead.*time\|regression"; then
|
|
656
|
+
category="dora-regression"
|
|
657
|
+
elif echo "$title" | grep -qi "template"; then
|
|
658
|
+
category="template-effectiveness"
|
|
659
|
+
elif echo "$title" | grep -qi "memory"; then
|
|
660
|
+
category="memory-pruning"
|
|
661
|
+
else
|
|
662
|
+
category="recurring-failures"
|
|
663
|
+
fi
|
|
664
|
+
|
|
665
|
+
issues_to_fix+=("$issue_num|$category|$title")
|
|
666
|
+
count=$((count + 1))
|
|
667
|
+
fi
|
|
668
|
+
done < <(gh issue list --label "meta-improvement" --state open --json "number,title" --jq ".[]" 2>/dev/null || echo "")
|
|
669
|
+
|
|
670
|
+
if [[ $count -eq 0 ]]; then
|
|
671
|
+
info " No meta-improvement issues to process"
|
|
672
|
+
return 0
|
|
673
|
+
fi
|
|
674
|
+
|
|
675
|
+
info " Found ${count} issue(s) to process, executing in parallel..."
|
|
676
|
+
|
|
677
|
+
# Sort by impact score (descending) - use temp file for Bash 3.2 compat
|
|
678
|
+
local scored_file
|
|
679
|
+
scored_file=$(mktemp)
|
|
680
|
+
|
|
681
|
+
for issue_spec in "${issues_to_fix[@]}"; do
|
|
682
|
+
local issue_num category title
|
|
683
|
+
issue_num="${issue_spec%%|*}"
|
|
684
|
+
category="${issue_spec#*|}"
|
|
685
|
+
category="${category%%|*}"
|
|
686
|
+
title="${issue_spec##*|}"
|
|
687
|
+
|
|
688
|
+
local score
|
|
689
|
+
score=$(patrol_meta_score_impact "$title" "$category")
|
|
690
|
+
echo "$score|$issue_num|$category|$title" >> "$scored_file"
|
|
691
|
+
done
|
|
692
|
+
|
|
693
|
+
# Sort by score (highest first) using temp file (Bash 3.2 compatible)
|
|
694
|
+
local sorted_file
|
|
695
|
+
sorted_file=$(mktemp)
|
|
696
|
+
printf '%s\n' "${scored_issues[@]}" | sort -rn > "$sorted_file"
|
|
697
|
+
|
|
698
|
+
# Process in parallel (limit to 3 concurrent pipelines)
|
|
699
|
+
local active_count=0
|
|
700
|
+
local max_parallel=3
|
|
701
|
+
|
|
702
|
+
while IFS= read -r item; do
|
|
703
|
+
local score issue_num category title
|
|
704
|
+
score="${item%%|*}"
|
|
705
|
+
issue_num="${item#*|}"
|
|
706
|
+
issue_num="${issue_num%%|*}"
|
|
707
|
+
category="${issue_num#*|}"
|
|
708
|
+
category="${category%%|*}"
|
|
709
|
+
title="${item##*|}"
|
|
710
|
+
|
|
711
|
+
# Wait if we have max_parallel active jobs
|
|
712
|
+
while [[ $active_count -ge $max_parallel ]]; do
|
|
713
|
+
# Count running background jobs
|
|
714
|
+
active_count=$(jobs -r 2>/dev/null | wc -l)
|
|
715
|
+
[[ $active_count -ge $max_parallel ]] && sleep 2
|
|
716
|
+
done
|
|
717
|
+
|
|
718
|
+
# Start pipeline in background
|
|
719
|
+
(
|
|
720
|
+
patrol_meta_execute_fix "$issue_num" "$title"
|
|
721
|
+
sleep 2
|
|
722
|
+
patrol_meta_verify_fix "$category" "$issue_num"
|
|
723
|
+
) &
|
|
724
|
+
|
|
725
|
+
active_count=$((active_count + 1))
|
|
726
|
+
done < "$sorted_file"
|
|
727
|
+
|
|
728
|
+
rm -f "$sorted_file"
|
|
729
|
+
|
|
730
|
+
# Wait for all to complete
|
|
731
|
+
wait
|
|
732
|
+
|
|
733
|
+
success " Batch processing complete"
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
# ─── Main Autonomous Loop: Detect → Score → Fix → Verify → Learn ──────────
|
|
737
|
+
patrol_meta_auto() {
|
|
738
|
+
echo -e "\n ${BOLD}Meta Self-Improvement Autonomous Loop${RESET}"
|
|
739
|
+
|
|
740
|
+
info "Stage 1: Detection"
|
|
741
|
+
patrol_meta_untested_scripts
|
|
742
|
+
patrol_meta_bash_compat
|
|
743
|
+
patrol_meta_version_sync
|
|
744
|
+
patrol_meta_dora_trends
|
|
745
|
+
patrol_meta_template_effectiveness
|
|
746
|
+
patrol_meta_memory_pruning
|
|
747
|
+
patrol_meta_event_analysis
|
|
748
|
+
|
|
749
|
+
echo ""
|
|
750
|
+
info "Stage 2: Impact Scoring & Batch Processing"
|
|
751
|
+
patrol_meta_batch_improve
|
|
752
|
+
|
|
753
|
+
echo ""
|
|
754
|
+
info "Stage 3: Learning from Outcomes"
|
|
755
|
+
# This would be populated by results from batch_improve
|
|
756
|
+
# For now, log that autonomous loop completed
|
|
757
|
+
emit_event "patrol.meta_autonomous_complete" "timestamp=$(now_iso)"
|
|
758
|
+
|
|
759
|
+
success "Autonomous self-improvement loop completed"
|
|
760
|
+
echo ""
|
|
761
|
+
}
|
|
762
|
+
|
|
429
763
|
# ─── Main Entry Point ──────────────────────────────────────────────────────
|
|
430
764
|
patrol_meta_run() {
|
|
431
765
|
echo -e "\n ${BOLD}Meta Self-Improvement Checks${RESET}"
|
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
set -euo pipefail
|
|
7
7
|
trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
# shellcheck disable=SC2034
|
|
10
|
+
VERSION="3.3.0"
|
|
10
11
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
12
|
REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
12
13
|
|
|
@@ -17,6 +18,8 @@ REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
|
17
18
|
# Canonical helpers (colors, output, events)
|
|
18
19
|
# shellcheck source=lib/helpers.sh
|
|
19
20
|
[[ -f "$SCRIPT_DIR/lib/helpers.sh" ]] && source "$SCRIPT_DIR/lib/helpers.sh"
|
|
21
|
+
# shellcheck source=lib/config.sh
|
|
22
|
+
[[ -f "$SCRIPT_DIR/lib/config.sh" ]] && source "$SCRIPT_DIR/lib/config.sh"
|
|
20
23
|
# Fallbacks when helpers not loaded (e.g. test env with overridden SCRIPT_DIR)
|
|
21
24
|
[[ "$(type -t info 2>/dev/null)" == "function" ]] || info() { echo -e "\033[38;2;0;212;255m\033[1m▸\033[0m $*"; }
|
|
22
25
|
[[ "$(type -t success 2>/dev/null)" == "function" ]] || success() { echo -e "\033[38;2;74;222;128m\033[1m✓\033[0m $*"; }
|
|
@@ -29,6 +32,7 @@ fi
|
|
|
29
32
|
if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
|
|
30
33
|
emit_event() {
|
|
31
34
|
local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
|
|
35
|
+
# shellcheck disable=SC2155
|
|
32
36
|
local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
|
|
33
37
|
while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
|
|
34
38
|
echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
|
|
@@ -114,6 +118,7 @@ composer_create_pipeline() {
|
|
|
114
118
|
# Atomic write
|
|
115
119
|
local tmp_file
|
|
116
120
|
tmp_file=$(mktemp "${output_file}.XXXXXX")
|
|
121
|
+
# shellcheck disable=SC2064
|
|
117
122
|
trap "rm -f '$tmp_file'" RETURN
|
|
118
123
|
echo "$composed" | jq '.' > "$tmp_file"
|
|
119
124
|
mv "$tmp_file" "$output_file"
|
|
@@ -143,6 +148,7 @@ composer_create_pipeline() {
|
|
|
143
148
|
info "Using fallback template: standard" >&2
|
|
144
149
|
local tmp_file
|
|
145
150
|
tmp_file=$(mktemp "${output_file}.XXXXXX")
|
|
151
|
+
# shellcheck disable=SC2064
|
|
146
152
|
trap "rm -f '$tmp_file'" RETURN
|
|
147
153
|
cp "$fallback_template" "$tmp_file"
|
|
148
154
|
mv "$tmp_file" "$output_file"
|
|
@@ -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.3.0"
|
|
10
10
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
12
12
|
|
|
@@ -29,6 +29,7 @@ fi
|
|
|
29
29
|
if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
|
|
30
30
|
emit_event() {
|
|
31
31
|
local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
|
|
32
|
+
# shellcheck disable=SC2155
|
|
32
33
|
local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
|
|
33
34
|
while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
|
|
34
35
|
echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
|
|
@@ -150,7 +151,8 @@ _compute_convergence() {
|
|
|
150
151
|
fi
|
|
151
152
|
|
|
152
153
|
local total_errors
|
|
153
|
-
total_errors=$(wc -l < "$error_log" 2>/dev/null | tr -d ' ' ||
|
|
154
|
+
total_errors=$(wc -l < "$error_log" 2>/dev/null | tr -d ' ' || true)
|
|
155
|
+
total_errors="${total_errors:-0}"
|
|
154
156
|
total_errors=$(_safe_num "$total_errors")
|
|
155
157
|
|
|
156
158
|
if [[ "$total_errors" -eq 0 ]]; then
|
|
@@ -270,7 +272,8 @@ _compute_error_maturity() {
|
|
|
270
272
|
fi
|
|
271
273
|
|
|
272
274
|
local total_errors
|
|
273
|
-
total_errors=$(wc -l < "$error_log" 2>/dev/null | tr -d ' ' ||
|
|
275
|
+
total_errors=$(wc -l < "$error_log" 2>/dev/null | tr -d ' ' || true)
|
|
276
|
+
total_errors="${total_errors:-0}"
|
|
274
277
|
total_errors=$(_safe_num "$total_errors")
|
|
275
278
|
|
|
276
279
|
if [[ "$total_errors" -eq 0 ]]; then
|
|
@@ -280,7 +283,8 @@ _compute_error_maturity() {
|
|
|
280
283
|
|
|
281
284
|
# Count unique error signatures
|
|
282
285
|
local unique_errors
|
|
283
|
-
unique_errors=$(jq -r '.signature // "unknown"' "$error_log" 2>/dev/null | sort -u | wc -l | tr -d ' ' ||
|
|
286
|
+
unique_errors=$(jq -r '.signature // "unknown"' "$error_log" 2>/dev/null | sort -u | wc -l | tr -d ' ' || true)
|
|
287
|
+
unique_errors="${unique_errors:-0}"
|
|
284
288
|
unique_errors=$(_safe_num "$unique_errors")
|
|
285
289
|
|
|
286
290
|
if [[ "$unique_errors" -eq 0 ]]; then
|
|
@@ -507,8 +511,10 @@ pipeline_compute_vitals() {
|
|
|
507
511
|
# ── Error counts ──
|
|
508
512
|
local total_errors=0 unique_errors=0
|
|
509
513
|
if [[ -f "$error_log" ]]; then
|
|
510
|
-
total_errors=$(wc -l < "$error_log" 2>/dev/null | tr -d ' ' ||
|
|
511
|
-
|
|
514
|
+
total_errors=$(wc -l < "$error_log" 2>/dev/null | tr -d ' ' || true)
|
|
515
|
+
total_errors="${total_errors:-0}"
|
|
516
|
+
unique_errors=$(jq -r '.signature // "unknown"' "$error_log" 2>/dev/null | sort -u | wc -l | tr -d ' ' || true)
|
|
517
|
+
unique_errors="${unique_errors:-0}"
|
|
512
518
|
fi
|
|
513
519
|
|
|
514
520
|
# ── Output JSON ──
|