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,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
 
@@ -29,7 +30,8 @@ fi
29
30
  if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
30
31
  emit_event() {
31
32
  local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
32
- local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
33
+ local payload
34
+ payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
33
35
  while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
34
36
  echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
35
37
  }
@@ -46,6 +48,7 @@ format_duration() {
46
48
  }
47
49
 
48
50
  # ─── Structured Event Log ──────────────────────────────────────────────────
51
+ # shellcheck disable=SC2034
49
52
  EVENTS_FILE="${HOME}/.shipwright/events.jsonl"
50
53
 
51
54
  # ─── Regression Storage ────────────────────────────────────────────────────
@@ -116,10 +119,10 @@ collect_script_metrics() {
116
119
  script_count=$(find "$REPO_DIR/scripts" -maxdepth 1 -name "*.sh" -type f 2>/dev/null | wc -l)
117
120
 
118
121
  # Count total lines in all scripts
119
- total_lines=$(find "$REPO_DIR/scripts" -maxdepth 1 -name "*.sh" -type f 2>/dev/null -exec wc -l {} + | awk '{sum+=$1} END {print sum}')
122
+ total_lines=$(find "$REPO_DIR/scripts" -maxdepth 1 -name "*.sh" -type f -exec wc -l {} + 2>/dev/null | awk '{sum+=$1} END {print sum}')
120
123
 
121
124
  # Count functions (grep for function definitions)
122
- function_count=$(find "$REPO_DIR/scripts" -maxdepth 1 -name "*.sh" -type f 2>/dev/null -exec grep -h "^[a-z_][a-z0-9_]*() {" {} + 2>/dev/null | wc -l)
125
+ function_count=$(find "$REPO_DIR/scripts" -maxdepth 1 -name "*.sh" -type f -exec grep -h "^[a-z_][a-z0-9_]*() {" {} + 2>/dev/null | wc -l)
123
126
 
124
127
  # Check for syntax errors
125
128
  while IFS= read -r script; do
@@ -138,17 +141,17 @@ collect_script_metrics() {
138
141
  collect_all_metrics() {
139
142
  local test_data
140
143
  test_data=$(collect_test_metrics)
141
- local test_count=$(echo "$test_data" | sed -n '1p')
142
- local pass_count=$(echo "$test_data" | sed -n '2p')
143
- local fail_count=$(echo "$test_data" | sed -n '3p')
144
- local pass_rate=$(echo "$test_data" | sed -n '4p')
144
+ local test_count; test_count=$(echo "$test_data" | sed -n '1p')
145
+ local pass_count; pass_count=$(echo "$test_data" | sed -n '2p')
146
+ local fail_count; fail_count=$(echo "$test_data" | sed -n '3p')
147
+ local pass_rate; pass_rate=$(echo "$test_data" | sed -n '4p')
145
148
 
146
149
  local script_data
147
150
  script_data=$(collect_script_metrics)
148
- local script_count=$(echo "$script_data" | sed -n '1p')
149
- local total_lines=$(echo "$script_data" | sed -n '2p')
150
- local function_count=$(echo "$script_data" | sed -n '3p')
151
- local syntax_errors=$(echo "$script_data" | sed -n '4p')
151
+ local script_count; script_count=$(echo "$script_data" | sed -n '1p')
152
+ local total_lines; total_lines=$(echo "$script_data" | sed -n '2p')
153
+ local function_count; function_count=$(echo "$script_data" | sed -n '3p')
154
+ local syntax_errors; syntax_errors=$(echo "$script_data" | sed -n '4p')
152
155
 
153
156
  cat <<METRICS
154
157
  {
@@ -180,6 +183,7 @@ cmd_baseline() {
180
183
  local timestamp
181
184
  timestamp=$(echo "$metrics" | jq -r '.timestamp')
182
185
  local epoch
186
+ # shellcheck disable=SC2034
183
187
  epoch=$(echo "$metrics" | jq -r '.epoch')
184
188
 
185
189
  # Create timestamped baseline file
@@ -188,6 +192,7 @@ cmd_baseline() {
188
192
 
189
193
  local tmp_file
190
194
  tmp_file=$(mktemp "${baseline_file}.tmp.XXXXXX")
195
+ # shellcheck disable=SC2064
191
196
  trap "rm -f '$tmp_file'" RETURN
192
197
 
193
198
  echo "$metrics" > "$tmp_file"
@@ -260,6 +265,7 @@ cmd_check() {
260
265
  local name="$1"
261
266
  local baseline_val="$2"
262
267
  local current_val="$3"
268
+ # shellcheck disable=SC2034
263
269
  local threshold_key="$4"
264
270
  local threshold_val="$5"
265
271
  local direction="${6:-decrease}" # decrease or increase
@@ -271,6 +277,7 @@ cmd_check() {
271
277
  return
272
278
  fi
273
279
 
280
+ # shellcheck disable=SC2034
274
281
  local diff
275
282
  local pct_diff=0
276
283
  if [[ "$baseline_val_num" != "0" ]]; then
@@ -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
 
@@ -27,6 +28,7 @@ if [[ "$(type -t now_iso 2>/dev/null)" != "function" ]]; then
27
28
  now_epoch() { date +%s; }
28
29
  fi
29
30
  # ─── Structured Event Log ──────────────────────────────────────────────────
31
+ # shellcheck disable=SC2034
30
32
  EVENTS_FILE="${HOME}/.shipwright/events.jsonl"
31
33
 
32
34
  # ─── Release State Storage ─────────────────────────────────────────────────
@@ -7,7 +7,8 @@ set -euo pipefail
7
7
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
8
8
  trap 'rm -f "${tmp_file:-}" "${tmp_changelog:-}"' EXIT
9
9
 
10
- VERSION="3.2.0"
10
+ # shellcheck disable=SC2034
11
+ VERSION="3.3.0"
11
12
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
12
13
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
13
14
 
@@ -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"
@@ -338,6 +340,7 @@ update_version_in_files() {
338
340
  # This is shell-safe: VERSION="1.11.0" → VERSION="1.12.0"
339
341
  local tmp_file
340
342
  tmp_file=$(mktemp)
343
+ # shellcheck disable=SC2064
341
344
  trap "rm -f '$tmp_file'" RETURN
342
345
  sed 's/^VERSION="[^"]*"$/VERSION="'"$version_num"'"/' "$file" > "$tmp_file"
343
346
  mv "$tmp_file" "$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"
@@ -496,6 +497,7 @@ HEALTHEOF
496
497
  [[ ! "$hb_val" =~ ^[0-9]+$ ]] && hb_val=0
497
498
  [[ ! "$active_val" =~ ^[0-9]+$ ]] && active_val=0
498
499
  heartbeat_count="$hb_val"
500
+ # shellcheck disable=SC2034
499
501
  active_workers="$active_val"
500
502
 
501
503
  if [[ "$daemon_pid" == "error" ]]; then
@@ -6,8 +6,10 @@
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)"
12
+ # shellcheck disable=SC2034
11
13
  EVENTS_FILE="${HOME}/.shipwright/events.jsonl"
12
14
 
13
15
  # ─── Cross-platform compatibility ──────────────────────────────────────────
@@ -32,6 +34,7 @@ fi
32
34
  if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
33
35
  emit_event() {
34
36
  local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
37
+ # shellcheck disable=SC2155
35
38
  local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
36
39
  while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
37
40
  echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
@@ -89,6 +92,7 @@ cmd_list() {
89
92
  echo ""
90
93
 
91
94
  # Extract unique pipeline runs, sorted by start time
95
+ # shellcheck disable=SC2034
92
96
  echo "$events_json" | jq -r '.[] | select(.type == "pipeline.started") | [.ts, .issue, .pipeline, .model, .goal] | @tsv' 2>/dev/null | \
93
97
  sort -r | \
94
98
  while IFS=$'\t' read -r ts issue pipeline model goal; do
@@ -444,11 +448,13 @@ cmd_compare() {
444
448
 
445
449
  # Extract details
446
450
  local goal1 type1 model1
451
+ # shellcheck disable=SC2034
447
452
  goal1=$(echo "$run1" | cut -f1)
448
453
  type1=$(echo "$run1" | cut -f2)
449
454
  model1=$(echo "$run1" | cut -f3)
450
455
 
451
456
  local goal2 type2 model2
457
+ # shellcheck disable=SC2034
452
458
  goal2=$(echo "$run2" | cut -f1)
453
459
  type2=$(echo "$run2" | cut -f2)
454
460
  model2=$(echo "$run2" | cut -f3)
@@ -6,11 +6,13 @@
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
 
12
13
  # ─── Cross-platform compatibility ──────────────────────────────────────────
13
14
  _COMPAT="$SCRIPT_DIR/lib/compat.sh"
15
+ # shellcheck disable=SC1090
14
16
  [[ -f "$_COMPAT" ]] && source "$_COMPAT"
15
17
 
16
18
  # Canonical helpers (colors, output, events)
@@ -356,6 +358,7 @@ generate_retro_report() {
356
358
  } >> "$report_file"
357
359
 
358
360
  # Capture full analysis to JSON
361
+ # shellcheck disable=SC2046
359
362
  jq -n \
360
363
  --argjson analysis "$analysis_json" \
361
364
  --argjson agents "$agent_json" \
@@ -582,6 +585,155 @@ cmd_history() {
582
585
  done
583
586
  }
584
587
 
588
+ # ─── Negative-Critical Retrospective ───────────────────────────────────────
589
+ # Analyze pipelines for silent failures and quality gate skipping
590
+ cmd_negative_audit() {
591
+ local from_date="${1:-}"
592
+ local to_date="${2:-}"
593
+
594
+ if [[ -z "$from_date" ]]; then
595
+ to_date=$(date -u +"%Y-%m-%d")
596
+ from_date=$(date_days_ago 7 2>/dev/null || python3 -c "from datetime import datetime, timedelta; print((datetime.utcnow() - timedelta(days=7)).strftime('%Y-%m-%d'))")
597
+ elif [[ -z "$to_date" ]]; then
598
+ to_date=$(date -u +"%Y-%m-%d")
599
+ fi
600
+
601
+ info "Negative Audit for ${from_date} to ${to_date}"
602
+ echo ""
603
+
604
+ if ! command -v jq >/dev/null 2>&1; then
605
+ error "jq required for negative audit"
606
+ return 1
607
+ fi
608
+
609
+ local from_epoch to_epoch
610
+ from_epoch=$(date_to_epoch "${from_date}T00:00:00Z")
611
+ to_epoch=$(date_to_epoch "${to_date}T23:59:59Z")
612
+
613
+ local findings='{"issues":[]}'
614
+ local issue_count=0
615
+
616
+ # Check for empty artifacts (silent stage failures)
617
+ echo ""
618
+ echo -e "${BOLD}1. Empty Artifacts Detection${RESET}"
619
+ local empty_count=0
620
+ if [[ -d ".claude/pipeline-artifacts" ]]; then
621
+ while IFS= read -r artifact_file; do
622
+ if [[ -f "$artifact_file" && ! -s "$artifact_file" ]]; then
623
+ local basename
624
+ basename=$(basename "$artifact_file")
625
+ warn "Empty artifact: $basename"
626
+ findings=$(echo "$findings" | jq --arg msg "Empty artifact: $basename" '.issues += [{"type": "empty_artifact", "message": $msg}]')
627
+ empty_count=$((empty_count + 1))
628
+ issue_count=$((issue_count + 1))
629
+ fi
630
+ done < <(find ".claude/pipeline-artifacts" -type f 2>/dev/null)
631
+ fi
632
+ [[ $empty_count -eq 0 ]] && echo " ✓ No empty artifacts found"
633
+
634
+ # Check for skipped quality gates
635
+ echo ""
636
+ echo -e "${BOLD}2. Skipped Quality Gates${RESET}"
637
+ local skipped_count=0
638
+ if [[ -f ".claude/pipeline-artifacts/compound-quality.log" ]]; then
639
+ local skip_lines
640
+ skip_lines=$(grep -c "skipped\|SKIP" ".claude/pipeline-artifacts/compound-quality.log" 2>/dev/null || echo "0")
641
+ if [[ "$skip_lines" -gt 0 ]]; then
642
+ warn "Found $skip_lines skipped quality checks"
643
+ findings=$(echo "$findings" | jq --arg msg "Skipped $skip_lines quality gates" '.issues += [{"type": "skipped_gates", "message": $msg}]')
644
+ skipped_count=$skip_lines
645
+ issue_count=$((issue_count + skipped_count))
646
+ fi
647
+ fi
648
+ [[ $skipped_count -eq 0 ]] && echo " ✓ No skipped quality gates"
649
+
650
+ # Check cost vs predicted
651
+ echo ""
652
+ echo -e "${BOLD}3. Cost Prediction Accuracy${RESET}"
653
+ if [[ -f ".claude/intelligence-cache.json" ]]; then
654
+ local predicted_cost actual_cost
655
+ predicted_cost=$(jq -r '.cost_estimate // 0' ".claude/intelligence-cache.json" 2>/dev/null)
656
+ if [[ -f ".claude/pipeline-artifacts/pipeline-state.md" ]]; then
657
+ actual_cost=$(grep -oP "Cost: \K[0-9]+" ".claude/pipeline-artifacts/pipeline-state.md" | tail -1 || echo "0")
658
+ if [[ -n "$predicted_cost" && "$predicted_cost" != "0" ]]; then
659
+ local cost_delta
660
+ cost_delta=$((actual_cost - predicted_cost))
661
+ local percent_error
662
+ percent_error=$((cost_delta * 100 / predicted_cost))
663
+ if [[ $percent_error -gt 30 || $percent_error -lt -30 ]]; then
664
+ warn "Cost prediction off by ${percent_error}% (predicted: $predicted_cost, actual: $actual_cost)"
665
+ findings=$(echo "$findings" | jq --arg msg "Cost off by ${percent_error}%" '.issues += [{"type": "cost_prediction", "message": $msg}]')
666
+ issue_count=$((issue_count + 1))
667
+ fi
668
+ fi
669
+ fi
670
+ fi
671
+ [[ $issue_count -lt 4 ]] && echo " ✓ Cost predictions accurate"
672
+
673
+ # Check loop iteration limit exhaustion
674
+ echo ""
675
+ echo -e "${BOLD}4. Loop Convergence Status${RESET}"
676
+ if [[ -f ".claude/pipeline-artifacts/pipeline-state.md" ]]; then
677
+ local loop_iter loop_limit
678
+ loop_iter=$(grep -oP "Iteration: \K[0-9]+" ".claude/pipeline-artifacts/pipeline-state.md" | tail -1 || echo "0")
679
+ loop_limit=$(grep -oP "Limit: \K[0-9]+" ".claude/pipeline-artifacts/pipeline-state.md" | tail -1 || echo "20")
680
+ if [[ "$loop_iter" -ge "$loop_limit" ]]; then
681
+ warn "Loop exhausted iterations ($loop_iter/$loop_limit)"
682
+ findings=$(echo "$findings" | jq --arg msg "Loop iteration limit exhausted: $loop_iter/$loop_limit" '.issues += [{"type": "loop_exhaustion", "message": $msg}]')
683
+ issue_count=$((issue_count + 1))
684
+ fi
685
+ fi
686
+ [[ $issue_count -lt 5 ]] && echo " ✓ Loop convergence normal"
687
+
688
+ # Check for || true errors
689
+ echo ""
690
+ echo -e "${BOLD}5. Unsafe Error Suppression${RESET}"
691
+ if [[ -f ".claude/pipeline-artifacts/error-log.jsonl" ]]; then
692
+ local true_errors
693
+ true_errors=$(grep -c "|| true" ".claude/pipeline-artifacts/error-log.jsonl" 2>/dev/null || echo "0")
694
+ if [[ "$true_errors" -gt 0 ]]; then
695
+ warn "Found $true_errors errors suppressed with || true"
696
+ findings=$(echo "$findings" | jq --arg msg "Found $true_errors unsuppressed || true errors" '.issues += [{"type": "error_suppression", "message": $msg}]')
697
+ issue_count=$((issue_count + 1))
698
+ fi
699
+ fi
700
+ [[ $true_errors -eq 0 ]] && echo " ✓ No unsafe error suppression"
701
+
702
+ # Summary
703
+ echo ""
704
+ echo -e "${PURPLE}${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}"
705
+ echo ""
706
+
707
+ if [[ $issue_count -eq 0 ]]; then
708
+ success "Negative audit passed: no critical issues detected"
709
+ else
710
+ warn "Negative audit found $issue_count issue(s)"
711
+ echo "$findings" | jq '.issues[] | "\(.type): \(.message)"' -r
712
+ fi
713
+
714
+ # Store in memory as retrospective pattern
715
+ if type memory_capture_pattern >/dev/null 2>&1; then
716
+ local pattern_data
717
+ pattern_data=$(echo "$findings" | jq -n \
718
+ --argjson findings "$(echo "$findings" | jq '.issues | length')" \
719
+ --arg from_date "$from_date" \
720
+ --arg to_date "$to_date" \
721
+ '{
722
+ type: "negative_audit",
723
+ date_range: ($from_date + " to " + $to_date),
724
+ issues_found: $findings
725
+ }')
726
+ memory_capture_pattern "negative_audit" "$pattern_data" 2>/dev/null || true
727
+ fi
728
+
729
+ emit_event "retro.negative_audit" \
730
+ "from_date=$from_date" \
731
+ "to_date=$to_date" \
732
+ "issues=$issue_count"
733
+
734
+ echo ""
735
+ }
736
+
585
737
  cmd_help() {
586
738
  cat << 'EOF'
587
739
  Usage: shipwright retro <subcommand> [options]
@@ -595,6 +747,7 @@ Subcommands:
595
747
  compare DATE1 DATE2 Compare two sprint periods
596
748
  history Show past retrospective reports
597
749
  quality Show quality index trend (longitudinal)
750
+ negative [--from DATE] [--to] Negative audit: detect silent failures, skipped gates
598
751
  help Show this help message
599
752
 
600
753
  Options:
@@ -608,6 +761,7 @@ Examples:
608
761
  shipwright retro trends
609
762
  shipwright retro agents
610
763
  shipwright retro compare 2025-02-01 2025-01-25
764
+ shipwright retro negative # Last 7 days audit
611
765
 
612
766
  EOF
613
767
  }
@@ -651,6 +805,9 @@ if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
651
805
  exit 1
652
806
  fi
653
807
  ;;
808
+ negative)
809
+ cmd_negative_audit "$@"
810
+ ;;
654
811
  help|--help|-h)
655
812
  cmd_help
656
813
  ;;
@@ -7,7 +7,8 @@
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)"
12
13
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
13
14
 
@@ -22,6 +23,7 @@ REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
22
23
  if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
23
24
  emit_event() {
24
25
  local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
26
+ # shellcheck disable=SC2155
25
27
  local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
26
28
  while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
27
29
  echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
@@ -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
 
12
13
  # ─── Dependency check ─────────────────────────────────────────────────────────
@@ -34,7 +35,8 @@ fi
34
35
  if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
35
36
  emit_event() {
36
37
  local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
37
- local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
38
+ local payload
39
+ payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
38
40
  while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
39
41
  echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
40
42
  }
@@ -54,6 +56,7 @@ init_rules() {
54
56
  if [[ ! -f "$SCALE_RULES_FILE" ]]; then
55
57
  local tmp_file
56
58
  tmp_file=$(mktemp)
59
+ # shellcheck disable=SC2064
57
60
  trap "rm -f '$tmp_file'" RETURN
58
61
  cat > "$tmp_file" << 'JSON'
59
62
  {
@@ -96,6 +99,7 @@ in_cooldown() {
96
99
  update_scale_state() {
97
100
  local tmp_file
98
101
  tmp_file=$(mktemp)
102
+ # shellcheck disable=SC2064
99
103
  trap "rm -f '$tmp_file'" RETURN
100
104
 
101
105
  if [[ -f "$SCALE_STATE_FILE" ]]; then
@@ -194,7 +198,8 @@ cmd_up() {
194
198
  fi
195
199
 
196
200
  for i in $(seq 1 "$count"); do
197
- local agent_name="sw-agent-${role}-$(date +%s)-${i}"
201
+ local agent_name
202
+ agent_name="sw-agent-${role}-$(date +%s)-${i}"
198
203
  local session_name="shipwright-${agent_name}"
199
204
 
200
205
  # Spawn a real agent in a tmux session
@@ -231,6 +236,7 @@ cmd_down() {
231
236
  # Backward compat: "down agent-42" -> treat as session/agent identifier
232
237
  if [[ -n "$count" ]] && [[ "$count" != *[0-9]* ]] || [[ "$count" == agent-* ]]; then
233
238
  # Specific agent/session id
239
+ # shellcheck disable=SC2034
234
240
  local session_pattern="*${count}*"
235
241
  local sessions
236
242
  sessions=$(tmux list-sessions -F '#{session_name}' 2>/dev/null | grep -E "shipwright|swarm" | grep -i "$count" || true)
@@ -320,6 +326,7 @@ cmd_rules() {
320
326
 
321
327
  local tmp_file
322
328
  tmp_file=$(mktemp)
329
+ # shellcheck disable=SC2064
323
330
  trap "rm -f '$tmp_file'" RETURN
324
331
 
325
332
  jq --arg key "$key" --arg value "$value" \
@@ -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
 
@@ -28,6 +28,7 @@ fi
28
28
  if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
29
29
  emit_event() {
30
30
  local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
31
+ # shellcheck disable=SC2155
31
32
  local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
32
33
  while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
33
34
  echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
@@ -118,8 +119,11 @@ scan_licenses() {
118
119
  local has_npm=false has_pip=false has_go=false has_cargo=false
119
120
 
120
121
  [[ -f "$REPO_DIR/package.json" ]] && has_npm=true
122
+ # shellcheck disable=SC2034
121
123
  [[ -f "$REPO_DIR/requirements.txt" || -f "$REPO_DIR/setup.py" ]] && has_pip=true
124
+ # shellcheck disable=SC2034
122
125
  [[ -f "$REPO_DIR/go.mod" ]] && has_go=true
126
+ # shellcheck disable=SC2034
123
127
  [[ -f "$REPO_DIR/Cargo.toml" ]] && has_cargo=true
124
128
 
125
129
  # Check npm licenses
@@ -202,6 +206,7 @@ generate_sbom() {
202
206
  # Add npm packages
203
207
  if [[ -f "$REPO_DIR/package.json" ]] && command -v npm >/dev/null 2>&1; then
204
208
  local npm_list
209
+ # shellcheck disable=SC2034
205
210
  npm_list=$(npm list --json 2>/dev/null || echo '{"dependencies":{}}')
206
211
  while IFS='=' read -r name version; do
207
212
  [[ -z "$name" || -z "$version" ]] && continue
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env bash
2
+ # shellcheck disable=SC2034,SC2064 # config vars used by sourced scripts; traps expand at definition time
2
3
  # ╔═══════════════════════════════════════════════════════════════════════════╗
3
4
  # ║ shipwright self-optimize — Learning & Self-Tuning System ║
4
5
  # ║ Outcome analysis · Template tuning · Model routing · Memory evolution ║
@@ -6,7 +7,7 @@
6
7
  set -euo pipefail
7
8
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
8
9
 
9
- VERSION="3.2.0"
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
 
@@ -29,7 +30,8 @@ fi
29
30
  if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
30
31
  emit_event() {
31
32
  local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
32
- local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
33
+ local payload
34
+ payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
33
35
  while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
34
36
  echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
35
37
  }
@@ -1389,7 +1391,8 @@ optimize_track_quality_index() {
1389
1391
  local quality_index
1390
1392
  quality_index=$(awk "BEGIN{printf \"%.0f\", ($success_rate * 0.4) + ($efficiency * 0.3) + ($avg_quality * 0.3)}" 2>/dev/null || echo "0")
1391
1393
 
1392
- local entry="{\"timestamp\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"window\":$window,\"total\":$total,\"success_rate\":$success_rate,\"avg_iterations\":$avg_iterations,\"avg_quality\":$avg_quality,\"efficiency\":$efficiency,\"quality_index\":$quality_index}"
1394
+ local entry
1395
+ entry="{\"timestamp\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"window\":$window,\"total\":$total,\"success_rate\":$success_rate,\"avg_iterations\":$avg_iterations,\"avg_quality\":$avg_quality,\"efficiency\":$efficiency,\"quality_index\":$quality_index}"
1393
1396
  echo "$entry" >> "$quality_file"
1394
1397
 
1395
1398
  # Detect trend
@@ -8,7 +8,8 @@
8
8
  # ║ Supports --template to scaffold from a team template and --terminal ║
9
9
  # ║ to select a terminal adapter (tmux, iterm2, wezterm). ║
10
10
  # ╚═══════════════════════════════════════════════════════════════════════════╝
11
- VERSION="3.2.0"
11
+ # shellcheck disable=SC2034
12
+ VERSION="3.3.0"
12
13
  set -euo pipefail
13
14
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
14
15
 
@@ -33,6 +34,7 @@ fi
33
34
  if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
34
35
  emit_event() {
35
36
  local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
37
+ # shellcheck disable=SC2155
36
38
  local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
37
39
  while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
38
40
  echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
@@ -206,8 +208,12 @@ if [[ -n "$TEMPLATE_NAME" ]]; then
206
208
  case "$key" in
207
209
  description) TEMPLATE_DESC="$value" ;;
208
210
  layout) TEMPLATE_LAYOUT="$value" ;;
209
- layout_style) TEMPLATE_LAYOUT_STYLE="$value" ;;
210
- main_pane_percent) TEMPLATE_MAIN_PANE_PERCENT="$value" ;;
211
+ layout_style)
212
+ # shellcheck disable=SC2034
213
+ TEMPLATE_LAYOUT_STYLE="$value" ;;
214
+ main_pane_percent)
215
+ # shellcheck disable=SC2034
216
+ TEMPLATE_MAIN_PANE_PERCENT="$value" ;;
211
217
  esac
212
218
  ;;
213
219
  AGENT) [[ -n "$key" ]] && TEMPLATE_AGENTS+=("$key") ;;
@@ -10,9 +10,10 @@
10
10
  set -euo pipefail
11
11
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
12
12
 
13
- VERSION="3.2.0"
13
+ VERSION="3.3.0"
14
14
 
15
15
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
16
+ # shellcheck disable=SC2034
16
17
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
17
18
 
18
19
  # ─── Cross-platform compatibility ──────────────────────────────────────────
@@ -34,6 +35,7 @@ fi
34
35
  if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
35
36
  emit_event() {
36
37
  local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
38
+ # shellcheck disable=SC2155
37
39
  local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
38
40
  while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
39
41
  echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"