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
@@ -0,0 +1,471 @@
1
+ #!/usr/bin/env bash
2
+ # Module guard - prevent double-sourcing
3
+ [[ -n "${_AUTO_RECOVERY_LOADED:-}" ]] && return 0
4
+ _AUTO_RECOVERY_LOADED=1
5
+
6
+ # ╔═══════════════════════════════════════════════════════════════════════════╗
7
+ # ║ shipwright auto-recovery — Autonomous Error Recovery System ║
8
+ # ║ Classify errors → match recovery patterns → apply fix → verify ║
9
+ # ║ Model escalation ladder: same model → escalate → fresh session → human ║
10
+ # ║ Integrates with loop-convergence: called BEFORE circuit breaker abort ║
11
+ # ╚═══════════════════════════════════════════════════════════════════════════╝
12
+
13
+ # shellcheck disable=SC2034
14
+ VERSION="3.3.0"
15
+
16
+ # ─── Output Helpers ──────────────────────────────────────────────────────────
17
+ [[ "$(type -t info 2>/dev/null)" == "function" ]] || info() { echo -e "\033[38;2;0;212;255m\033[1m▸\033[0m $*"; }
18
+ [[ "$(type -t success 2>/dev/null)" == "function" ]] || success() { echo -e "\033[38;2;74;222;128m\033[1m✓\033[0m $*"; }
19
+ [[ "$(type -t warn 2>/dev/null)" == "function" ]] || warn() { echo -e "\033[38;2;250;204;21m\033[1m⚠\033[0m $*"; }
20
+ [[ "$(type -t error 2>/dev/null)" == "function" ]] || error() { echo -e "\033[38;2;248;113;113m\033[1m✗\033[0m $*" >&2; }
21
+ if [[ "$(type -t now_iso 2>/dev/null)" != "function" ]]; then
22
+ now_iso() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
23
+ now_epoch() { date +%s; }
24
+ fi
25
+
26
+ # ─── Configuration ───────────────────────────────────────────────────────────
27
+
28
+ RECOVERY_MAX_ATTEMPTS="${RECOVERY_MAX_ATTEMPTS:-4}"
29
+ RECOVERY_STATE_FILE="${RECOVERY_STATE_FILE:-.claude/recovery-state.json}"
30
+ RECOVERY_PATTERNS_FILE="${RECOVERY_PATTERNS_FILE:-.claude/recovery-patterns.json}"
31
+ RECOVERY_LOG_FILE="${RECOVERY_LOG_FILE:-.claude/pipeline-artifacts/recovery-log.jsonl}"
32
+
33
+ # Model escalation ladder
34
+ RECOVERY_MODEL_LADDER="${RECOVERY_MODEL_LADDER:-haiku,sonnet,opus}"
35
+
36
+ # ─── Error Classification ───────────────────────────────────────────────────
37
+ # Classify an error into a category for pattern matching.
38
+ # Input: error text (from test output, build log, etc.)
39
+ # Output: error category string
40
+
41
+ recovery_classify_error() {
42
+ local error_text="${1:-}"
43
+
44
+ if [[ -z "$error_text" ]]; then
45
+ echo "unknown"
46
+ return 0
47
+ fi
48
+
49
+ # Normalize to lowercase for matching
50
+ local lower_text
51
+ lower_text=$(echo "$error_text" | tr '[:upper:]' '[:lower:]')
52
+
53
+ # Classification by pattern (order matters — most specific first)
54
+ if echo "$lower_text" | grep -qE '(syntax error|unexpected token|parse error|unterminated)'; then
55
+ echo "syntax_error"
56
+ elif echo "$lower_text" | grep -qE '(type error|cannot find name|is not assignable|type.*is not)'; then
57
+ echo "type_error"
58
+ elif echo "$lower_text" | grep -qE '(import|require|module not found|cannot find module|no such file)'; then
59
+ echo "import_error"
60
+ elif echo "$lower_text" | grep -qE '(timeout|timed out|deadline exceeded|took too long)'; then
61
+ echo "timeout"
62
+ elif echo "$lower_text" | grep -qE '(out of memory|heap|oom|memory limit|segfault|sigsegv|enomem)'; then
63
+ echo "resource_error"
64
+ elif echo "$lower_text" | grep -qE '(permission denied|eacces|forbidden|unauthorized|401|403)'; then
65
+ echo "permission_error"
66
+ elif echo "$lower_text" | grep -qE '(connection refused|econnrefused|network|dns|enotfound)'; then
67
+ echo "network_error"
68
+ elif echo "$lower_text" | grep -qE '(lock|deadlock|locked|busy|resource busy)'; then
69
+ echo "lock_error"
70
+ elif echo "$lower_text" | grep -qE '(assert|expect|should|to equal|to be|not equal|mismatch)'; then
71
+ echo "test_assertion"
72
+ elif echo "$lower_text" | grep -qE '(build|compile|linker|undefined reference|unresolved)'; then
73
+ echo "build_error"
74
+ elif echo "$lower_text" | grep -qE '(lint|eslint|prettier|format|style)'; then
75
+ echo "lint_error"
76
+ elif echo "$lower_text" | grep -qE '(deprecat|removed|obsolete|no longer supported)'; then
77
+ echo "deprecation_error"
78
+ elif echo "$lower_text" | grep -qE '(null|undefined|nil|none|reference error)'; then
79
+ echo "null_reference"
80
+ else
81
+ echo "unknown"
82
+ fi
83
+ }
84
+
85
+ # ─── Recovery Pattern Matching ───────────────────────────────────────────────
86
+ # Match an error category to a recovery strategy.
87
+
88
+ recovery_get_strategy() {
89
+ local error_category="${1:-unknown}"
90
+
91
+ # Check custom patterns file first
92
+ if [[ -f "$RECOVERY_PATTERNS_FILE" ]] && command -v jq >/dev/null 2>&1; then
93
+ local custom_strategy
94
+ custom_strategy=$(jq -r --arg cat "$error_category" \
95
+ '.patterns[$cat].strategy // empty' "$RECOVERY_PATTERNS_FILE" 2>/dev/null || true)
96
+ if [[ -n "$custom_strategy" ]]; then
97
+ echo "$custom_strategy"
98
+ return 0
99
+ fi
100
+ fi
101
+
102
+ # Built-in strategies
103
+ case "$error_category" in
104
+ syntax_error)
105
+ echo "retry_with_context:Focus on fixing the syntax error. Read the error line carefully and fix the exact syntax issue."
106
+ ;;
107
+ type_error)
108
+ echo "retry_with_context:Fix the type error. Add explicit type annotations, check function signatures, and ensure type compatibility."
109
+ ;;
110
+ import_error)
111
+ echo "retry_with_context:Fix the import/module error. Check file paths, verify the module exists, and fix any incorrect import statements."
112
+ ;;
113
+ timeout)
114
+ echo "adjust_config:Increase timeout values or simplify the operation that is timing out."
115
+ ;;
116
+ resource_error)
117
+ echo "escalate_model:Resource exhaustion detected. Try with a model that uses less context or break the task into smaller pieces."
118
+ ;;
119
+ permission_error)
120
+ echo "flag_human:Permission error requires human intervention to fix credentials or access."
121
+ ;;
122
+ network_error)
123
+ echo "retry_simple:Network error may be transient. Wait briefly and retry."
124
+ ;;
125
+ lock_error)
126
+ echo "retry_with_cleanup:Clean up lock files and retry. Check for orphaned processes."
127
+ ;;
128
+ test_assertion)
129
+ echo "retry_with_context:Test assertion failed. Review the test expectation and the code behavior. Fix the code to match expected behavior, not the test."
130
+ ;;
131
+ build_error)
132
+ echo "retry_with_context:Build error. Check for missing dependencies, incorrect imports, or compilation issues."
133
+ ;;
134
+ lint_error)
135
+ echo "retry_with_context:Lint/formatting error. Apply the formatter or fix the lint violations."
136
+ ;;
137
+ deprecation_error)
138
+ echo "retry_with_context:Deprecated API usage. Update to the current API version."
139
+ ;;
140
+ null_reference)
141
+ echo "retry_with_context:Null/undefined reference. Add null checks, default values, or ensure the variable is initialized."
142
+ ;;
143
+ *)
144
+ echo "retry_with_context:Unknown error. Read the error carefully and apply a targeted fix."
145
+ ;;
146
+ esac
147
+ }
148
+
149
+ # ─── Recovery State Management ───────────────────────────────────────────────
150
+
151
+ _recovery_load_state() {
152
+ if [[ -f "$RECOVERY_STATE_FILE" ]] && command -v jq >/dev/null 2>&1; then
153
+ cat "$RECOVERY_STATE_FILE"
154
+ else
155
+ echo '{"attempts":0,"history":[],"current_model":"","escalation_level":0}'
156
+ fi
157
+ }
158
+
159
+ _recovery_save_state() {
160
+ local state_json="${1:-}"
161
+ if [[ -n "$state_json" ]]; then
162
+ mkdir -p "$(dirname "$RECOVERY_STATE_FILE")"
163
+ local tmp_file
164
+ tmp_file=$(mktemp 2>/dev/null || echo "${RECOVERY_STATE_FILE}.tmp")
165
+ echo "$state_json" > "$tmp_file"
166
+ mv "$tmp_file" "$RECOVERY_STATE_FILE"
167
+ fi
168
+ }
169
+
170
+ _recovery_log_attempt() {
171
+ local category="${1:-}" strategy="${2:-}" result="${3:-}" details="${4:-}"
172
+ mkdir -p "$(dirname "$RECOVERY_LOG_FILE")"
173
+
174
+ local entry
175
+ entry=$(printf '{"timestamp":"%s","category":"%s","strategy":"%s","result":"%s","details":"%s"}' \
176
+ "$(now_iso)" "$category" "$strategy" "$result" \
177
+ "$(echo "$details" | tr '"' "'" | head -c 200)")
178
+
179
+ echo "$entry" >> "$RECOVERY_LOG_FILE"
180
+ }
181
+
182
+ # ─── Core Recovery Function ─────────────────────────────────────────────────
183
+ # Attempt autonomous recovery from an error.
184
+ # Returns 0 if recovery succeeded (caller should continue), 1 if failed.
185
+ #
186
+ # This is the main integration point with loop-convergence.sh.
187
+ # Call this BEFORE the circuit breaker trips.
188
+
189
+ recovery_attempt() {
190
+ local error_text="${1:-}"
191
+ local project_dir="${2:-.}"
192
+ local test_cmd="${3:-}"
193
+
194
+ if [[ -z "$error_text" ]]; then
195
+ warn "No error text provided for recovery"
196
+ return 1
197
+ fi
198
+
199
+ # Load state
200
+ local state
201
+ state=$(_recovery_load_state)
202
+ local attempts
203
+ attempts=$(echo "$state" | jq -r '.attempts // 0' 2>/dev/null || echo "0")
204
+
205
+ if [[ "$attempts" -ge "$RECOVERY_MAX_ATTEMPTS" ]]; then
206
+ error "Recovery exhausted: ${attempts}/${RECOVERY_MAX_ATTEMPTS} attempts used"
207
+ _recovery_log_attempt "exhausted" "none" "failed" "Max attempts reached"
208
+ if type emit_event >/dev/null 2>&1; then
209
+ emit_event "recovery_exhausted" "attempts=${attempts}"
210
+ fi
211
+ return 1
212
+ fi
213
+
214
+ # Classify error
215
+ local category
216
+ category=$(recovery_classify_error "$error_text")
217
+ info "Error classified as: ${category}"
218
+
219
+ # Get recovery strategy
220
+ local strategy_raw strategy_type strategy_hint
221
+ strategy_raw=$(recovery_get_strategy "$category")
222
+ strategy_type=$(echo "$strategy_raw" | cut -d: -f1)
223
+ strategy_hint=$(echo "$strategy_raw" | cut -d: -f2-)
224
+
225
+ info "Recovery strategy: ${strategy_type}"
226
+
227
+ # Increment attempt counter
228
+ attempts=$((attempts + 1))
229
+ local escalation_level
230
+ escalation_level=$(echo "$state" | jq -r '.escalation_level // 0' 2>/dev/null || echo "0")
231
+
232
+ # Execute strategy
233
+ local recovery_result="failed"
234
+
235
+ case "$strategy_type" in
236
+ retry_simple)
237
+ info "Retrying (attempt ${attempts}/${RECOVERY_MAX_ATTEMPTS})..."
238
+ recovery_result="retry"
239
+ ;;
240
+
241
+ retry_with_context)
242
+ info "Retrying with focused context (attempt ${attempts}/${RECOVERY_MAX_ATTEMPTS})..."
243
+ # The hint will be injected into the next iteration prompt
244
+ RECOVERY_HINT="${strategy_hint}"
245
+ recovery_result="retry_with_hint"
246
+ ;;
247
+
248
+ retry_with_cleanup)
249
+ info "Cleaning up and retrying..."
250
+ # Clean common lock/temp files
251
+ find "$project_dir" -name "*.lock" -newer "$project_dir/.git/HEAD" -delete 2>/dev/null || true
252
+ find "$project_dir" -name ".cache" -type d -newer "$project_dir/.git/HEAD" -exec rm -rf {} + 2>/dev/null || true
253
+ RECOVERY_HINT="${strategy_hint}"
254
+ recovery_result="retry_with_hint"
255
+ ;;
256
+
257
+ adjust_config)
258
+ info "Adjusting configuration..."
259
+ RECOVERY_HINT="${strategy_hint}"
260
+ recovery_result="retry_with_hint"
261
+ ;;
262
+
263
+ escalate_model)
264
+ # Move up the model ladder
265
+ escalation_level=$((escalation_level + 1))
266
+ # Count models in ladder (Bash 3.2 compat — no read -a)
267
+ local model_count=0
268
+ local m
269
+ for m in $(echo "$RECOVERY_MODEL_LADDER" | tr ',' ' '); do
270
+ model_count=$((model_count + 1))
271
+ done
272
+
273
+ if [[ "$escalation_level" -lt "$model_count" ]]; then
274
+ local target_model
275
+ target_model=$(echo "$RECOVERY_MODEL_LADDER" | cut -d',' -f$((escalation_level + 1)))
276
+ info "Escalating model to: ${target_model}"
277
+ RECOVERY_ESCALATED_MODEL="$target_model"
278
+ RECOVERY_HINT="${strategy_hint}"
279
+ recovery_result="model_escalated"
280
+
281
+ if type emit_event >/dev/null 2>&1; then
282
+ emit_event "recovery_escalated" \
283
+ "from_level=${escalation_level}" \
284
+ "to_model=${target_model}" \
285
+ "category=${category}"
286
+ fi
287
+ else
288
+ warn "No higher model available for escalation"
289
+ recovery_result="failed"
290
+ fi
291
+ ;;
292
+
293
+ flag_human)
294
+ warn "Error requires human intervention: ${category}"
295
+ RECOVERY_HINT="HUMAN INTERVENTION REQUIRED: ${strategy_hint}"
296
+ recovery_result="needs_human"
297
+
298
+ if type emit_event >/dev/null 2>&1; then
299
+ emit_event "recovery_needs_human" \
300
+ "category=${category}" \
301
+ "hint=${strategy_hint}"
302
+ fi
303
+ return 1
304
+ ;;
305
+
306
+ *)
307
+ warn "Unknown recovery strategy: ${strategy_type}"
308
+ recovery_result="failed"
309
+ ;;
310
+ esac
311
+
312
+ # Update state
313
+ local history_entry
314
+ history_entry=$(printf '{"attempt":%d,"category":"%s","strategy":"%s","result":"%s","timestamp":"%s"}' \
315
+ "$attempts" "$category" "$strategy_type" "$recovery_result" "$(now_iso)")
316
+
317
+ local new_state
318
+ new_state=$(echo "$state" | jq \
319
+ --argjson attempt "$attempts" \
320
+ --argjson level "$escalation_level" \
321
+ --argjson entry "$history_entry" \
322
+ '.attempts = $attempt | .escalation_level = $level | .history += [$entry]' \
323
+ 2>/dev/null || echo "$state")
324
+
325
+ _recovery_save_state "$new_state"
326
+ _recovery_log_attempt "$category" "$strategy_type" "$recovery_result" "$error_text"
327
+
328
+ if type emit_event >/dev/null 2>&1; then
329
+ emit_event "recovery_attempted" \
330
+ "attempt=${attempts}" \
331
+ "category=${category}" \
332
+ "strategy=${strategy_type}" \
333
+ "result=${recovery_result}"
334
+ fi
335
+
336
+ # Return based on result
337
+ case "$recovery_result" in
338
+ retry|retry_with_hint|model_escalated)
339
+ success "Recovery action applied (attempt ${attempts}/${RECOVERY_MAX_ATTEMPTS})"
340
+ return 0
341
+ ;;
342
+ *)
343
+ error "Recovery failed (attempt ${attempts}/${RECOVERY_MAX_ATTEMPTS})"
344
+ return 1
345
+ ;;
346
+ esac
347
+ }
348
+
349
+ # ─── Reset Recovery State ───────────────────────────────────────────────────
350
+ # Call when tests pass or iteration succeeds to reset the recovery counter.
351
+
352
+ recovery_reset() {
353
+ if [[ -f "$RECOVERY_STATE_FILE" ]]; then
354
+ local state
355
+ state=$(_recovery_load_state)
356
+ local prev_attempts
357
+ prev_attempts=$(echo "$state" | jq -r '.attempts // 0' 2>/dev/null || echo "0")
358
+
359
+ if [[ "$prev_attempts" -gt 0 ]]; then
360
+ success "Recovery succeeded after ${prev_attempts} attempts — resetting counter"
361
+ _recovery_log_attempt "reset" "success" "recovered" "Tests passing, resetting recovery state"
362
+ fi
363
+ fi
364
+
365
+ _recovery_save_state '{"attempts":0,"history":[],"current_model":"","escalation_level":0}'
366
+ RECOVERY_HINT=""
367
+ RECOVERY_ESCALATED_MODEL=""
368
+ }
369
+
370
+ # ─── Recovery Status ────────────────────────────────────────────────────────
371
+
372
+ recovery_status() {
373
+ if [[ -f "$RECOVERY_STATE_FILE" ]] && command -v jq >/dev/null 2>&1; then
374
+ local attempts escalation_level
375
+ attempts=$(jq -r '.attempts // 0' "$RECOVERY_STATE_FILE" 2>/dev/null || echo "0")
376
+ escalation_level=$(jq -r '.escalation_level // 0' "$RECOVERY_STATE_FILE" 2>/dev/null || echo "0")
377
+ echo "recovery_active=true attempts=${attempts}/${RECOVERY_MAX_ATTEMPTS} escalation=${escalation_level}"
378
+ else
379
+ echo "recovery_active=false"
380
+ fi
381
+ }
382
+
383
+ # ─── Recovery Success Rate ──────────────────────────────────────────────────
384
+ # Calculate historical success rate from recovery log.
385
+
386
+ recovery_success_rate() {
387
+ if [[ ! -f "$RECOVERY_LOG_FILE" ]]; then
388
+ echo "0"
389
+ return 0
390
+ fi
391
+
392
+ local total succeeded
393
+ total=$(wc -l < "$RECOVERY_LOG_FILE" 2>/dev/null | tr -d ' ') || total=0
394
+ succeeded=$(grep -c '"result":"recovered"' "$RECOVERY_LOG_FILE" 2>/dev/null) || succeeded=0
395
+
396
+ if [[ "$total" -gt 0 ]]; then
397
+ echo $(( succeeded * 100 / total ))
398
+ else
399
+ echo "0"
400
+ fi
401
+ }
402
+
403
+ # ─── Integration Point: Pre-Circuit-Breaker Hook ────────────────────────────
404
+ # Called by loop-convergence.sh before the circuit breaker trips.
405
+ # If recovery succeeds, the caller should reset the circuit breaker counter.
406
+
407
+ recovery_before_circuit_breaker() {
408
+ local error_log="${1:-}"
409
+ local project_dir="${2:-.}"
410
+ local test_cmd="${3:-}"
411
+
412
+ # Extract the most recent error
413
+ local recent_error=""
414
+ if [[ -n "$error_log" && -f "$error_log" ]]; then
415
+ recent_error=$(tail -1 "$error_log" 2>/dev/null | jq -r '.error // .message // empty' 2>/dev/null || true)
416
+ fi
417
+
418
+ if [[ -z "$recent_error" ]]; then
419
+ # Try to get error from last test output
420
+ local last_log="${LOG_DIR:-/tmp}/iteration-${ITERATION:-0}.log"
421
+ if [[ -f "$last_log" ]]; then
422
+ recent_error=$(grep -iE '(error|fail|exception)' "$last_log" 2>/dev/null | tail -5 | head -c 500 || true)
423
+ fi
424
+ fi
425
+
426
+ if [[ -z "$recent_error" ]]; then
427
+ warn "No error context available for recovery"
428
+ return 1
429
+ fi
430
+
431
+ recovery_attempt "$recent_error" "$project_dir" "$test_cmd"
432
+ }
433
+
434
+ # ─── Custom Patterns Management ─────────────────────────────────────────────
435
+ # Add a custom recovery pattern learned from experience.
436
+
437
+ recovery_add_pattern() {
438
+ local category="${1:-}"
439
+ local strategy="${2:-}"
440
+ local description="${3:-}"
441
+
442
+ if [[ -z "$category" || -z "$strategy" ]]; then
443
+ error "Usage: recovery_add_pattern <category> <strategy> [description]"
444
+ return 1
445
+ fi
446
+
447
+ mkdir -p "$(dirname "$RECOVERY_PATTERNS_FILE")"
448
+
449
+ if [[ ! -f "$RECOVERY_PATTERNS_FILE" ]]; then
450
+ echo '{"patterns":{}}' > "$RECOVERY_PATTERNS_FILE"
451
+ fi
452
+
453
+ local updated
454
+ updated=$(jq --arg cat "$category" --arg strat "$strategy" --arg desc "$description" \
455
+ '.patterns[$cat] = {"strategy": $strat, "description": $desc, "added": (now | todate)}' \
456
+ "$RECOVERY_PATTERNS_FILE" 2>/dev/null)
457
+
458
+ if [[ -n "$updated" ]]; then
459
+ echo "$updated" > "$RECOVERY_PATTERNS_FILE"
460
+ success "Recovery pattern added: ${category} → ${strategy}"
461
+ else
462
+ error "Failed to add recovery pattern"
463
+ return 1
464
+ fi
465
+ }
466
+
467
+ # ─── Exported Variables ──────────────────────────────────────────────────────
468
+ # These are set by recovery_attempt and read by the loop iteration logic.
469
+
470
+ RECOVERY_HINT="" # Injected into next iteration prompt
471
+ RECOVERY_ESCALATED_MODEL="" # Model to switch to (if escalated)