shipwright-cli 3.2.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.
Files changed (279) hide show
  1. package/.claude/agents/code-reviewer.md +2 -0
  2. package/.claude/agents/devops-engineer.md +2 -0
  3. package/.claude/agents/doc-fleet-agent.md +2 -0
  4. package/.claude/agents/pipeline-agent.md +2 -0
  5. package/.claude/agents/shell-script-specialist.md +2 -0
  6. package/.claude/agents/test-specialist.md +2 -0
  7. package/.claude/hooks/agent-crash-capture.sh +32 -0
  8. package/.claude/hooks/post-tool-use.sh +3 -2
  9. package/.claude/hooks/pre-tool-use.sh +35 -3
  10. package/README.md +4 -4
  11. package/claude-code/hooks/config-change.sh +18 -0
  12. package/claude-code/hooks/instructions-reloaded.sh +7 -0
  13. package/claude-code/hooks/worktree-create.sh +25 -0
  14. package/claude-code/hooks/worktree-remove.sh +20 -0
  15. package/config/code-constitution.json +130 -0
  16. package/dashboard/middleware/auth.ts +134 -0
  17. package/dashboard/middleware/constants.ts +21 -0
  18. package/dashboard/public/index.html +2 -6
  19. package/dashboard/public/styles.css +100 -97
  20. package/dashboard/routes/auth.ts +38 -0
  21. package/dashboard/server.ts +66 -25
  22. package/dashboard/services/config.ts +26 -0
  23. package/dashboard/services/db.ts +118 -0
  24. package/dashboard/src/canvas/pixel-agent.ts +298 -0
  25. package/dashboard/src/canvas/pixel-sprites.ts +440 -0
  26. package/dashboard/src/canvas/shipyard-effects.ts +367 -0
  27. package/dashboard/src/canvas/shipyard-scene.ts +616 -0
  28. package/dashboard/src/canvas/submarine-layout.ts +267 -0
  29. package/dashboard/src/components/header.ts +8 -7
  30. package/dashboard/src/core/router.ts +1 -0
  31. package/dashboard/src/design/submarine-theme.ts +253 -0
  32. package/dashboard/src/main.ts +2 -0
  33. package/dashboard/src/types/api.ts +2 -1
  34. package/dashboard/src/views/activity.ts +2 -1
  35. package/dashboard/src/views/shipyard.ts +39 -0
  36. package/dashboard/types/index.ts +166 -0
  37. package/docs/plans/2026-02-28-compound-audit-and-shipyard-design.md +186 -0
  38. package/docs/plans/2026-02-28-skipper-shipwright-implementation-plan.md +1182 -0
  39. package/docs/plans/2026-02-28-skipper-shipwright-integration-design.md +531 -0
  40. package/docs/plans/2026-03-01-ai-powered-skill-injection-design.md +298 -0
  41. package/docs/plans/2026-03-01-ai-powered-skill-injection-plan.md +1109 -0
  42. package/docs/plans/2026-03-01-capabilities-cleanup-plan.md +658 -0
  43. package/docs/plans/2026-03-01-clean-architecture-plan.md +924 -0
  44. package/docs/plans/2026-03-01-compound-audit-cascade-design.md +191 -0
  45. package/docs/plans/2026-03-01-compound-audit-cascade-plan.md +921 -0
  46. package/docs/plans/2026-03-01-deep-integration-plan.md +851 -0
  47. package/docs/plans/2026-03-01-pipeline-audit-trail-design.md +145 -0
  48. package/docs/plans/2026-03-01-pipeline-audit-trail-plan.md +770 -0
  49. package/docs/plans/2026-03-01-refined-depths-brand-design.md +382 -0
  50. package/docs/plans/2026-03-01-refined-depths-implementation.md +599 -0
  51. package/docs/plans/2026-03-01-skipper-kernel-integration-design.md +203 -0
  52. package/docs/plans/2026-03-01-unified-platform-design.md +272 -0
  53. package/docs/plans/2026-03-07-claude-code-feature-integration-design.md +189 -0
  54. package/docs/plans/2026-03-07-claude-code-feature-integration-plan.md +1165 -0
  55. package/docs/research/BACKLOG_QUICK_REFERENCE.md +352 -0
  56. package/docs/research/CUTTING_EDGE_RESEARCH_2026.md +546 -0
  57. package/docs/research/RESEARCH_INDEX.md +439 -0
  58. package/docs/research/RESEARCH_SOURCES.md +440 -0
  59. package/docs/research/RESEARCH_SUMMARY.txt +275 -0
  60. package/docs/superpowers/specs/2026-03-10-pipeline-quality-revolution-design.md +341 -0
  61. package/package.json +2 -2
  62. package/scripts/lib/adaptive-model.sh +427 -0
  63. package/scripts/lib/adaptive-timeout.sh +316 -0
  64. package/scripts/lib/audit-trail.sh +309 -0
  65. package/scripts/lib/auto-recovery.sh +471 -0
  66. package/scripts/lib/bandit-selector.sh +431 -0
  67. package/scripts/lib/bootstrap.sh +104 -2
  68. package/scripts/lib/causal-graph.sh +455 -0
  69. package/scripts/lib/compat.sh +126 -0
  70. package/scripts/lib/compound-audit.sh +337 -0
  71. package/scripts/lib/constitutional.sh +454 -0
  72. package/scripts/lib/context-budget.sh +359 -0
  73. package/scripts/lib/convergence.sh +594 -0
  74. package/scripts/lib/cost-optimizer.sh +634 -0
  75. package/scripts/lib/daemon-adaptive.sh +10 -0
  76. package/scripts/lib/daemon-dispatch.sh +106 -17
  77. package/scripts/lib/daemon-failure.sh +34 -4
  78. package/scripts/lib/daemon-patrol.sh +23 -2
  79. package/scripts/lib/daemon-poll-github.sh +361 -0
  80. package/scripts/lib/daemon-poll-health.sh +299 -0
  81. package/scripts/lib/daemon-poll.sh +27 -611
  82. package/scripts/lib/daemon-state.sh +112 -66
  83. package/scripts/lib/daemon-triage.sh +10 -0
  84. package/scripts/lib/dod-scorecard.sh +442 -0
  85. package/scripts/lib/error-actionability.sh +300 -0
  86. package/scripts/lib/formal-spec.sh +461 -0
  87. package/scripts/lib/helpers.sh +177 -4
  88. package/scripts/lib/intent-analysis.sh +409 -0
  89. package/scripts/lib/loop-convergence.sh +350 -0
  90. package/scripts/lib/loop-iteration.sh +682 -0
  91. package/scripts/lib/loop-progress.sh +48 -0
  92. package/scripts/lib/loop-restart.sh +185 -0
  93. package/scripts/lib/memory-effectiveness.sh +506 -0
  94. package/scripts/lib/mutation-executor.sh +352 -0
  95. package/scripts/lib/outcome-feedback.sh +521 -0
  96. package/scripts/lib/pipeline-cli.sh +336 -0
  97. package/scripts/lib/pipeline-commands.sh +1216 -0
  98. package/scripts/lib/pipeline-detection.sh +100 -2
  99. package/scripts/lib/pipeline-execution.sh +897 -0
  100. package/scripts/lib/pipeline-github.sh +28 -3
  101. package/scripts/lib/pipeline-intelligence-compound.sh +431 -0
  102. package/scripts/lib/pipeline-intelligence-scoring.sh +407 -0
  103. package/scripts/lib/pipeline-intelligence-skip.sh +181 -0
  104. package/scripts/lib/pipeline-intelligence.sh +100 -1136
  105. package/scripts/lib/pipeline-quality-bash-compat.sh +182 -0
  106. package/scripts/lib/pipeline-quality-checks.sh +17 -715
  107. package/scripts/lib/pipeline-quality-gates.sh +563 -0
  108. package/scripts/lib/pipeline-stages-build.sh +730 -0
  109. package/scripts/lib/pipeline-stages-delivery.sh +965 -0
  110. package/scripts/lib/pipeline-stages-intake.sh +1133 -0
  111. package/scripts/lib/pipeline-stages-monitor.sh +407 -0
  112. package/scripts/lib/pipeline-stages-review.sh +1022 -0
  113. package/scripts/lib/pipeline-stages.sh +59 -2929
  114. package/scripts/lib/pipeline-state.sh +36 -5
  115. package/scripts/lib/pipeline-util.sh +487 -0
  116. package/scripts/lib/policy-learner.sh +438 -0
  117. package/scripts/lib/process-reward.sh +493 -0
  118. package/scripts/lib/project-detect.sh +649 -0
  119. package/scripts/lib/quality-profile.sh +334 -0
  120. package/scripts/lib/recruit-commands.sh +885 -0
  121. package/scripts/lib/recruit-learning.sh +739 -0
  122. package/scripts/lib/recruit-roles.sh +648 -0
  123. package/scripts/lib/reward-aggregator.sh +458 -0
  124. package/scripts/lib/rl-optimizer.sh +362 -0
  125. package/scripts/lib/root-cause.sh +427 -0
  126. package/scripts/lib/scope-enforcement.sh +445 -0
  127. package/scripts/lib/session-restart.sh +493 -0
  128. package/scripts/lib/skill-memory.sh +300 -0
  129. package/scripts/lib/skill-registry.sh +775 -0
  130. package/scripts/lib/spec-driven.sh +476 -0
  131. package/scripts/lib/test-helpers.sh +18 -7
  132. package/scripts/lib/test-holdout.sh +429 -0
  133. package/scripts/lib/test-optimizer.sh +511 -0
  134. package/scripts/shipwright-file-suggest.sh +45 -0
  135. package/scripts/skills/adversarial-quality.md +61 -0
  136. package/scripts/skills/api-design.md +44 -0
  137. package/scripts/skills/architecture-design.md +50 -0
  138. package/scripts/skills/brainstorming.md +43 -0
  139. package/scripts/skills/data-pipeline.md +44 -0
  140. package/scripts/skills/deploy-safety.md +64 -0
  141. package/scripts/skills/documentation.md +38 -0
  142. package/scripts/skills/frontend-design.md +45 -0
  143. package/scripts/skills/generated/.gitkeep +0 -0
  144. package/scripts/skills/generated/_refinements/.gitkeep +0 -0
  145. package/scripts/skills/generated/_refinements/adversarial-quality.patch.md +3 -0
  146. package/scripts/skills/generated/_refinements/architecture-design.patch.md +3 -0
  147. package/scripts/skills/generated/_refinements/brainstorming.patch.md +3 -0
  148. package/scripts/skills/generated/cli-version-management.md +29 -0
  149. package/scripts/skills/generated/collection-system-validation.md +99 -0
  150. package/scripts/skills/generated/large-scale-c-refactoring-coordination.md +97 -0
  151. package/scripts/skills/generated/pattern-matching-similarity-scoring.md +195 -0
  152. package/scripts/skills/generated/test-parallelization-detection.md +65 -0
  153. package/scripts/skills/observability.md +79 -0
  154. package/scripts/skills/performance.md +48 -0
  155. package/scripts/skills/pr-quality.md +49 -0
  156. package/scripts/skills/product-thinking.md +43 -0
  157. package/scripts/skills/security-audit.md +49 -0
  158. package/scripts/skills/systematic-debugging.md +40 -0
  159. package/scripts/skills/testing-strategy.md +47 -0
  160. package/scripts/skills/two-stage-review.md +52 -0
  161. package/scripts/skills/validation-thoroughness.md +55 -0
  162. package/scripts/sw +9 -3
  163. package/scripts/sw-activity.sh +9 -2
  164. package/scripts/sw-adaptive.sh +2 -1
  165. package/scripts/sw-adversarial.sh +2 -1
  166. package/scripts/sw-architecture-enforcer.sh +3 -1
  167. package/scripts/sw-auth.sh +12 -2
  168. package/scripts/sw-autonomous.sh +5 -1
  169. package/scripts/sw-changelog.sh +4 -1
  170. package/scripts/sw-checkpoint.sh +2 -1
  171. package/scripts/sw-ci.sh +5 -1
  172. package/scripts/sw-cleanup.sh +4 -26
  173. package/scripts/sw-code-review.sh +10 -4
  174. package/scripts/sw-connect.sh +2 -1
  175. package/scripts/sw-context.sh +2 -1
  176. package/scripts/sw-cost.sh +48 -3
  177. package/scripts/sw-daemon.sh +66 -9
  178. package/scripts/sw-dashboard.sh +3 -1
  179. package/scripts/sw-db.sh +59 -16
  180. package/scripts/sw-decide.sh +8 -2
  181. package/scripts/sw-decompose.sh +360 -17
  182. package/scripts/sw-deps.sh +4 -1
  183. package/scripts/sw-developer-simulation.sh +4 -1
  184. package/scripts/sw-discovery.sh +325 -2
  185. package/scripts/sw-doc-fleet.sh +4 -1
  186. package/scripts/sw-docs-agent.sh +3 -1
  187. package/scripts/sw-docs.sh +2 -1
  188. package/scripts/sw-doctor.sh +453 -2
  189. package/scripts/sw-dora.sh +4 -1
  190. package/scripts/sw-durable.sh +4 -3
  191. package/scripts/sw-e2e-orchestrator.sh +17 -16
  192. package/scripts/sw-eventbus.sh +7 -1
  193. package/scripts/sw-evidence.sh +364 -12
  194. package/scripts/sw-feedback.sh +550 -9
  195. package/scripts/sw-fix.sh +20 -1
  196. package/scripts/sw-fleet-discover.sh +6 -2
  197. package/scripts/sw-fleet-viz.sh +4 -1
  198. package/scripts/sw-fleet.sh +5 -1
  199. package/scripts/sw-github-app.sh +16 -3
  200. package/scripts/sw-github-checks.sh +3 -2
  201. package/scripts/sw-github-deploy.sh +3 -2
  202. package/scripts/sw-github-graphql.sh +18 -7
  203. package/scripts/sw-guild.sh +5 -1
  204. package/scripts/sw-heartbeat.sh +5 -30
  205. package/scripts/sw-hello.sh +67 -0
  206. package/scripts/sw-hygiene.sh +6 -1
  207. package/scripts/sw-incident.sh +265 -1
  208. package/scripts/sw-init.sh +18 -2
  209. package/scripts/sw-instrument.sh +10 -2
  210. package/scripts/sw-intelligence.sh +42 -6
  211. package/scripts/sw-jira.sh +5 -1
  212. package/scripts/sw-launchd.sh +2 -1
  213. package/scripts/sw-linear.sh +4 -1
  214. package/scripts/sw-logs.sh +4 -1
  215. package/scripts/sw-loop.sh +432 -1128
  216. package/scripts/sw-memory.sh +356 -2
  217. package/scripts/sw-mission-control.sh +6 -1
  218. package/scripts/sw-model-router.sh +481 -26
  219. package/scripts/sw-otel.sh +13 -4
  220. package/scripts/sw-oversight.sh +14 -5
  221. package/scripts/sw-patrol-meta.sh +334 -0
  222. package/scripts/sw-pipeline-composer.sh +5 -1
  223. package/scripts/sw-pipeline-vitals.sh +2 -1
  224. package/scripts/sw-pipeline.sh +53 -2664
  225. package/scripts/sw-pm.sh +12 -5
  226. package/scripts/sw-pr-lifecycle.sh +2 -1
  227. package/scripts/sw-predictive.sh +7 -1
  228. package/scripts/sw-prep.sh +185 -2
  229. package/scripts/sw-ps.sh +5 -25
  230. package/scripts/sw-public-dashboard.sh +15 -3
  231. package/scripts/sw-quality.sh +2 -1
  232. package/scripts/sw-reaper.sh +8 -25
  233. package/scripts/sw-recruit.sh +156 -2303
  234. package/scripts/sw-regression.sh +19 -12
  235. package/scripts/sw-release-manager.sh +3 -1
  236. package/scripts/sw-release.sh +4 -1
  237. package/scripts/sw-remote.sh +3 -1
  238. package/scripts/sw-replay.sh +7 -1
  239. package/scripts/sw-retro.sh +158 -1
  240. package/scripts/sw-review-rerun.sh +3 -1
  241. package/scripts/sw-scale.sh +10 -3
  242. package/scripts/sw-security-audit.sh +6 -1
  243. package/scripts/sw-self-optimize.sh +6 -3
  244. package/scripts/sw-session.sh +9 -3
  245. package/scripts/sw-setup.sh +3 -1
  246. package/scripts/sw-stall-detector.sh +406 -0
  247. package/scripts/sw-standup.sh +15 -7
  248. package/scripts/sw-status.sh +3 -1
  249. package/scripts/sw-strategic.sh +4 -1
  250. package/scripts/sw-stream.sh +7 -1
  251. package/scripts/sw-swarm.sh +18 -6
  252. package/scripts/sw-team-stages.sh +13 -6
  253. package/scripts/sw-templates.sh +5 -29
  254. package/scripts/sw-testgen.sh +7 -1
  255. package/scripts/sw-tmux-pipeline.sh +4 -1
  256. package/scripts/sw-tmux-role-color.sh +2 -0
  257. package/scripts/sw-tmux-status.sh +1 -1
  258. package/scripts/sw-tmux.sh +3 -1
  259. package/scripts/sw-trace.sh +3 -1
  260. package/scripts/sw-tracker-github.sh +3 -0
  261. package/scripts/sw-tracker-jira.sh +3 -0
  262. package/scripts/sw-tracker-linear.sh +3 -0
  263. package/scripts/sw-tracker.sh +3 -1
  264. package/scripts/sw-triage.sh +2 -1
  265. package/scripts/sw-upgrade.sh +3 -1
  266. package/scripts/sw-ux.sh +5 -2
  267. package/scripts/sw-webhook.sh +3 -1
  268. package/scripts/sw-widgets.sh +3 -1
  269. package/scripts/sw-worktree.sh +15 -3
  270. package/scripts/test-skill-injection.sh +1233 -0
  271. package/templates/pipelines/autonomous.json +27 -3
  272. package/templates/pipelines/cost-aware.json +34 -8
  273. package/templates/pipelines/deployed.json +12 -0
  274. package/templates/pipelines/enterprise.json +12 -0
  275. package/templates/pipelines/fast.json +6 -0
  276. package/templates/pipelines/full.json +27 -3
  277. package/templates/pipelines/hotfix.json +6 -0
  278. package/templates/pipelines/standard.json +12 -0
  279. package/templates/pipelines/tdd.json +12 -0
@@ -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.2.0"
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,23 +61,27 @@ 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
 
78
83
  # Parse events.jsonl
79
84
  if [[ -f "$EVENTS_FILE" ]]; then
80
- {
81
85
  while IFS= read -r line; do
82
86
  [[ -z "$line" ]] && continue
83
87
 
@@ -217,11 +221,13 @@ EOF
217
221
  # ─── OpenTelemetry Traces ────────────────────────────────────────────────────
218
222
 
219
223
  cmd_trace() {
224
+ # shellcheck disable=SC2034
220
225
  local pipeline_id="${1:-latest}"
221
226
 
222
227
  ensure_otel_dir
223
228
 
224
229
  # Build trace from events
230
+ # shellcheck disable=SC2034
225
231
  local traces='[]'
226
232
  local spans='[]'
227
233
  local root_span=""
@@ -263,7 +269,7 @@ EOF
263
269
  ;;
264
270
  stage_start)
265
271
  stage=$(echo "$line" | jq -r '.stage // "unknown"' 2>/dev/null || true)
266
- 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)))"
267
273
  spans=$(echo "$spans" | jq --arg span_id "$span_id" --arg stage "$stage" --arg ts "$ts" \
268
274
  '. += [{
269
275
  "traceId": "'${pipeline:0:16}'",
@@ -317,6 +323,7 @@ cmd_export() {
317
323
  local auth_header=""
318
324
 
319
325
  if [[ -n "${OTEL_EXPORTER_OTLP_HEADERS:-}" ]]; then
326
+ # shellcheck disable=SC2089
320
327
  auth_header="-H '${OTEL_EXPORTER_OTLP_HEADERS}'"
321
328
  fi
322
329
 
@@ -326,6 +333,7 @@ cmd_export() {
326
333
  if [[ "$format" == "trace" ]]; then
327
334
  payload=$(cmd_trace)
328
335
  local response
336
+ # shellcheck disable=SC2090
329
337
  response=$(curl -s --connect-timeout 10 --max-time 30 -X POST \
330
338
  "$endpoint/v1/traces" \
331
339
  -H "Content-Type: application/json" \
@@ -341,6 +349,7 @@ cmd_export() {
341
349
  else
342
350
  payload=$(cmd_metrics text)
343
351
  local response
352
+ # shellcheck disable=SC2090
344
353
  response=$(curl -s --connect-timeout 10 --max-time 30 -X POST \
345
354
  "$endpoint/metrics" \
346
355
  -H "Content-Type: text/plain" \
@@ -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
- VERSION="3.2.0"
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="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
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
- jq --arg message "$message" '.appeals += [{"message": $message, "appealed_at": "'$(now_iso)'"}]' "$review_file" > "$tmp_file"
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
- VERSION="3.2.0"
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
 
@@ -31,6 +32,7 @@ fi
31
32
  if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
32
33
  emit_event() {
33
34
  local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
35
+ # shellcheck disable=SC2155
34
36
  local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
35
37
  while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
36
38
  echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
@@ -116,6 +118,7 @@ composer_create_pipeline() {
116
118
  # Atomic write
117
119
  local tmp_file
118
120
  tmp_file=$(mktemp "${output_file}.XXXXXX")
121
+ # shellcheck disable=SC2064
119
122
  trap "rm -f '$tmp_file'" RETURN
120
123
  echo "$composed" | jq '.' > "$tmp_file"
121
124
  mv "$tmp_file" "$output_file"
@@ -145,6 +148,7 @@ composer_create_pipeline() {
145
148
  info "Using fallback template: standard" >&2
146
149
  local tmp_file
147
150
  tmp_file=$(mktemp "${output_file}.XXXXXX")
151
+ # shellcheck disable=SC2064
148
152
  trap "rm -f '$tmp_file'" RETURN
149
153
  cp "$fallback_template" "$tmp_file"
150
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.2.0"
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"