shipwright-cli 3.1.0 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (283) 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 +22 -8
  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/config/defaults.json +25 -2
  17. package/config/policy.json +1 -1
  18. package/dashboard/middleware/auth.ts +134 -0
  19. package/dashboard/middleware/constants.ts +21 -0
  20. package/dashboard/public/index.html +8 -6
  21. package/dashboard/public/styles.css +176 -97
  22. package/dashboard/routes/auth.ts +38 -0
  23. package/dashboard/server.ts +117 -25
  24. package/dashboard/services/config.ts +26 -0
  25. package/dashboard/services/db.ts +118 -0
  26. package/dashboard/src/canvas/pixel-agent.ts +298 -0
  27. package/dashboard/src/canvas/pixel-sprites.ts +440 -0
  28. package/dashboard/src/canvas/shipyard-effects.ts +367 -0
  29. package/dashboard/src/canvas/shipyard-scene.ts +616 -0
  30. package/dashboard/src/canvas/submarine-layout.ts +267 -0
  31. package/dashboard/src/components/header.ts +8 -7
  32. package/dashboard/src/core/api.ts +5 -0
  33. package/dashboard/src/core/router.ts +1 -0
  34. package/dashboard/src/design/submarine-theme.ts +253 -0
  35. package/dashboard/src/main.ts +2 -0
  36. package/dashboard/src/types/api.ts +12 -1
  37. package/dashboard/src/views/activity.ts +2 -1
  38. package/dashboard/src/views/metrics.ts +69 -1
  39. package/dashboard/src/views/shipyard.ts +39 -0
  40. package/dashboard/types/index.ts +166 -0
  41. package/docs/plans/2026-02-28-compound-audit-and-shipyard-design.md +186 -0
  42. package/docs/plans/2026-02-28-skipper-shipwright-implementation-plan.md +1182 -0
  43. package/docs/plans/2026-02-28-skipper-shipwright-integration-design.md +531 -0
  44. package/docs/plans/2026-03-01-ai-powered-skill-injection-design.md +298 -0
  45. package/docs/plans/2026-03-01-ai-powered-skill-injection-plan.md +1109 -0
  46. package/docs/plans/2026-03-01-capabilities-cleanup-plan.md +658 -0
  47. package/docs/plans/2026-03-01-clean-architecture-plan.md +924 -0
  48. package/docs/plans/2026-03-01-compound-audit-cascade-design.md +191 -0
  49. package/docs/plans/2026-03-01-compound-audit-cascade-plan.md +921 -0
  50. package/docs/plans/2026-03-01-deep-integration-plan.md +851 -0
  51. package/docs/plans/2026-03-01-pipeline-audit-trail-design.md +145 -0
  52. package/docs/plans/2026-03-01-pipeline-audit-trail-plan.md +770 -0
  53. package/docs/plans/2026-03-01-refined-depths-brand-design.md +382 -0
  54. package/docs/plans/2026-03-01-refined-depths-implementation.md +599 -0
  55. package/docs/plans/2026-03-01-skipper-kernel-integration-design.md +203 -0
  56. package/docs/plans/2026-03-01-unified-platform-design.md +272 -0
  57. package/docs/plans/2026-03-07-claude-code-feature-integration-design.md +189 -0
  58. package/docs/plans/2026-03-07-claude-code-feature-integration-plan.md +1165 -0
  59. package/docs/research/BACKLOG_QUICK_REFERENCE.md +352 -0
  60. package/docs/research/CUTTING_EDGE_RESEARCH_2026.md +546 -0
  61. package/docs/research/RESEARCH_INDEX.md +439 -0
  62. package/docs/research/RESEARCH_SOURCES.md +440 -0
  63. package/docs/research/RESEARCH_SUMMARY.txt +275 -0
  64. package/docs/superpowers/specs/2026-03-10-pipeline-quality-revolution-design.md +341 -0
  65. package/package.json +2 -2
  66. package/scripts/lib/adaptive-model.sh +427 -0
  67. package/scripts/lib/adaptive-timeout.sh +316 -0
  68. package/scripts/lib/audit-trail.sh +309 -0
  69. package/scripts/lib/auto-recovery.sh +471 -0
  70. package/scripts/lib/bandit-selector.sh +431 -0
  71. package/scripts/lib/bootstrap.sh +104 -2
  72. package/scripts/lib/causal-graph.sh +455 -0
  73. package/scripts/lib/compat.sh +126 -0
  74. package/scripts/lib/compound-audit.sh +337 -0
  75. package/scripts/lib/constitutional.sh +454 -0
  76. package/scripts/lib/context-budget.sh +359 -0
  77. package/scripts/lib/convergence.sh +594 -0
  78. package/scripts/lib/cost-optimizer.sh +634 -0
  79. package/scripts/lib/daemon-adaptive.sh +14 -2
  80. package/scripts/lib/daemon-dispatch.sh +106 -17
  81. package/scripts/lib/daemon-failure.sh +34 -4
  82. package/scripts/lib/daemon-patrol.sh +25 -4
  83. package/scripts/lib/daemon-poll-github.sh +361 -0
  84. package/scripts/lib/daemon-poll-health.sh +299 -0
  85. package/scripts/lib/daemon-poll.sh +27 -611
  86. package/scripts/lib/daemon-state.sh +119 -66
  87. package/scripts/lib/daemon-triage.sh +10 -0
  88. package/scripts/lib/dod-scorecard.sh +442 -0
  89. package/scripts/lib/error-actionability.sh +300 -0
  90. package/scripts/lib/formal-spec.sh +461 -0
  91. package/scripts/lib/helpers.sh +180 -5
  92. package/scripts/lib/intent-analysis.sh +409 -0
  93. package/scripts/lib/loop-convergence.sh +350 -0
  94. package/scripts/lib/loop-iteration.sh +682 -0
  95. package/scripts/lib/loop-progress.sh +48 -0
  96. package/scripts/lib/loop-restart.sh +185 -0
  97. package/scripts/lib/memory-effectiveness.sh +506 -0
  98. package/scripts/lib/mutation-executor.sh +352 -0
  99. package/scripts/lib/outcome-feedback.sh +521 -0
  100. package/scripts/lib/pipeline-cli.sh +336 -0
  101. package/scripts/lib/pipeline-commands.sh +1216 -0
  102. package/scripts/lib/pipeline-detection.sh +101 -3
  103. package/scripts/lib/pipeline-execution.sh +897 -0
  104. package/scripts/lib/pipeline-github.sh +28 -3
  105. package/scripts/lib/pipeline-intelligence-compound.sh +431 -0
  106. package/scripts/lib/pipeline-intelligence-scoring.sh +407 -0
  107. package/scripts/lib/pipeline-intelligence-skip.sh +181 -0
  108. package/scripts/lib/pipeline-intelligence.sh +104 -1138
  109. package/scripts/lib/pipeline-quality-bash-compat.sh +182 -0
  110. package/scripts/lib/pipeline-quality-checks.sh +17 -711
  111. package/scripts/lib/pipeline-quality-gates.sh +563 -0
  112. package/scripts/lib/pipeline-stages-build.sh +730 -0
  113. package/scripts/lib/pipeline-stages-delivery.sh +965 -0
  114. package/scripts/lib/pipeline-stages-intake.sh +1133 -0
  115. package/scripts/lib/pipeline-stages-monitor.sh +407 -0
  116. package/scripts/lib/pipeline-stages-review.sh +1022 -0
  117. package/scripts/lib/pipeline-stages.sh +161 -2901
  118. package/scripts/lib/pipeline-state.sh +36 -5
  119. package/scripts/lib/pipeline-util.sh +487 -0
  120. package/scripts/lib/policy-learner.sh +438 -0
  121. package/scripts/lib/process-reward.sh +493 -0
  122. package/scripts/lib/project-detect.sh +649 -0
  123. package/scripts/lib/quality-profile.sh +334 -0
  124. package/scripts/lib/recruit-commands.sh +885 -0
  125. package/scripts/lib/recruit-learning.sh +739 -0
  126. package/scripts/lib/recruit-roles.sh +648 -0
  127. package/scripts/lib/reward-aggregator.sh +458 -0
  128. package/scripts/lib/rl-optimizer.sh +362 -0
  129. package/scripts/lib/root-cause.sh +427 -0
  130. package/scripts/lib/scope-enforcement.sh +445 -0
  131. package/scripts/lib/session-restart.sh +493 -0
  132. package/scripts/lib/skill-memory.sh +300 -0
  133. package/scripts/lib/skill-registry.sh +775 -0
  134. package/scripts/lib/spec-driven.sh +476 -0
  135. package/scripts/lib/test-helpers.sh +18 -7
  136. package/scripts/lib/test-holdout.sh +429 -0
  137. package/scripts/lib/test-optimizer.sh +511 -0
  138. package/scripts/shipwright-file-suggest.sh +45 -0
  139. package/scripts/skills/adversarial-quality.md +61 -0
  140. package/scripts/skills/api-design.md +44 -0
  141. package/scripts/skills/architecture-design.md +50 -0
  142. package/scripts/skills/brainstorming.md +43 -0
  143. package/scripts/skills/data-pipeline.md +44 -0
  144. package/scripts/skills/deploy-safety.md +64 -0
  145. package/scripts/skills/documentation.md +38 -0
  146. package/scripts/skills/frontend-design.md +45 -0
  147. package/scripts/skills/generated/.gitkeep +0 -0
  148. package/scripts/skills/generated/_refinements/.gitkeep +0 -0
  149. package/scripts/skills/generated/_refinements/adversarial-quality.patch.md +3 -0
  150. package/scripts/skills/generated/_refinements/architecture-design.patch.md +3 -0
  151. package/scripts/skills/generated/_refinements/brainstorming.patch.md +3 -0
  152. package/scripts/skills/generated/cli-version-management.md +29 -0
  153. package/scripts/skills/generated/collection-system-validation.md +99 -0
  154. package/scripts/skills/generated/large-scale-c-refactoring-coordination.md +97 -0
  155. package/scripts/skills/generated/pattern-matching-similarity-scoring.md +195 -0
  156. package/scripts/skills/generated/test-parallelization-detection.md +65 -0
  157. package/scripts/skills/observability.md +79 -0
  158. package/scripts/skills/performance.md +48 -0
  159. package/scripts/skills/pr-quality.md +49 -0
  160. package/scripts/skills/product-thinking.md +43 -0
  161. package/scripts/skills/security-audit.md +49 -0
  162. package/scripts/skills/systematic-debugging.md +40 -0
  163. package/scripts/skills/testing-strategy.md +47 -0
  164. package/scripts/skills/two-stage-review.md +52 -0
  165. package/scripts/skills/validation-thoroughness.md +55 -0
  166. package/scripts/sw +9 -3
  167. package/scripts/sw-activity.sh +9 -8
  168. package/scripts/sw-adaptive.sh +8 -7
  169. package/scripts/sw-adversarial.sh +2 -1
  170. package/scripts/sw-architecture-enforcer.sh +3 -1
  171. package/scripts/sw-auth.sh +12 -2
  172. package/scripts/sw-autonomous.sh +5 -1
  173. package/scripts/sw-changelog.sh +4 -1
  174. package/scripts/sw-checkpoint.sh +2 -1
  175. package/scripts/sw-ci.sh +15 -6
  176. package/scripts/sw-cleanup.sh +4 -26
  177. package/scripts/sw-code-review.sh +45 -20
  178. package/scripts/sw-connect.sh +2 -1
  179. package/scripts/sw-context.sh +2 -1
  180. package/scripts/sw-cost.sh +107 -5
  181. package/scripts/sw-daemon.sh +71 -11
  182. package/scripts/sw-dashboard.sh +3 -1
  183. package/scripts/sw-db.sh +71 -20
  184. package/scripts/sw-decide.sh +8 -2
  185. package/scripts/sw-decompose.sh +360 -17
  186. package/scripts/sw-deps.sh +4 -1
  187. package/scripts/sw-developer-simulation.sh +4 -1
  188. package/scripts/sw-discovery.sh +378 -5
  189. package/scripts/sw-doc-fleet.sh +4 -1
  190. package/scripts/sw-docs-agent.sh +3 -1
  191. package/scripts/sw-docs.sh +2 -1
  192. package/scripts/sw-doctor.sh +453 -2
  193. package/scripts/sw-dora.sh +4 -1
  194. package/scripts/sw-durable.sh +12 -7
  195. package/scripts/sw-e2e-orchestrator.sh +17 -16
  196. package/scripts/sw-eventbus.sh +13 -4
  197. package/scripts/sw-evidence.sh +364 -12
  198. package/scripts/sw-feedback.sh +550 -9
  199. package/scripts/sw-fix.sh +20 -1
  200. package/scripts/sw-fleet-discover.sh +6 -2
  201. package/scripts/sw-fleet-viz.sh +9 -4
  202. package/scripts/sw-fleet.sh +5 -1
  203. package/scripts/sw-github-app.sh +18 -4
  204. package/scripts/sw-github-checks.sh +3 -2
  205. package/scripts/sw-github-deploy.sh +3 -2
  206. package/scripts/sw-github-graphql.sh +18 -7
  207. package/scripts/sw-guild.sh +5 -1
  208. package/scripts/sw-heartbeat.sh +5 -30
  209. package/scripts/sw-hello.sh +67 -0
  210. package/scripts/sw-hygiene.sh +10 -3
  211. package/scripts/sw-incident.sh +273 -5
  212. package/scripts/sw-init.sh +18 -2
  213. package/scripts/sw-instrument.sh +10 -2
  214. package/scripts/sw-intelligence.sh +44 -7
  215. package/scripts/sw-jira.sh +5 -1
  216. package/scripts/sw-launchd.sh +2 -1
  217. package/scripts/sw-linear.sh +4 -1
  218. package/scripts/sw-logs.sh +4 -1
  219. package/scripts/sw-loop.sh +436 -1076
  220. package/scripts/sw-memory.sh +357 -3
  221. package/scripts/sw-mission-control.sh +6 -1
  222. package/scripts/sw-model-router.sh +483 -27
  223. package/scripts/sw-otel.sh +15 -4
  224. package/scripts/sw-oversight.sh +14 -5
  225. package/scripts/sw-patrol-meta.sh +334 -0
  226. package/scripts/sw-pipeline-composer.sh +7 -1
  227. package/scripts/sw-pipeline-vitals.sh +12 -6
  228. package/scripts/sw-pipeline.sh +54 -2653
  229. package/scripts/sw-pm.sh +16 -8
  230. package/scripts/sw-pr-lifecycle.sh +2 -1
  231. package/scripts/sw-predictive.sh +17 -5
  232. package/scripts/sw-prep.sh +185 -2
  233. package/scripts/sw-ps.sh +5 -25
  234. package/scripts/sw-public-dashboard.sh +17 -4
  235. package/scripts/sw-quality.sh +14 -6
  236. package/scripts/sw-reaper.sh +8 -25
  237. package/scripts/sw-recruit.sh +156 -2303
  238. package/scripts/sw-regression.sh +19 -12
  239. package/scripts/sw-release-manager.sh +3 -1
  240. package/scripts/sw-release.sh +4 -1
  241. package/scripts/sw-remote.sh +3 -1
  242. package/scripts/sw-replay.sh +7 -1
  243. package/scripts/sw-retro.sh +158 -1
  244. package/scripts/sw-review-rerun.sh +3 -1
  245. package/scripts/sw-scale.sh +14 -5
  246. package/scripts/sw-security-audit.sh +6 -1
  247. package/scripts/sw-self-optimize.sh +173 -6
  248. package/scripts/sw-session.sh +9 -3
  249. package/scripts/sw-setup.sh +3 -1
  250. package/scripts/sw-stall-detector.sh +406 -0
  251. package/scripts/sw-standup.sh +15 -7
  252. package/scripts/sw-status.sh +3 -1
  253. package/scripts/sw-strategic.sh +14 -6
  254. package/scripts/sw-stream.sh +13 -4
  255. package/scripts/sw-swarm.sh +20 -7
  256. package/scripts/sw-team-stages.sh +13 -6
  257. package/scripts/sw-templates.sh +7 -31
  258. package/scripts/sw-testgen.sh +17 -6
  259. package/scripts/sw-tmux-pipeline.sh +4 -1
  260. package/scripts/sw-tmux-role-color.sh +2 -0
  261. package/scripts/sw-tmux-status.sh +1 -1
  262. package/scripts/sw-tmux.sh +37 -1
  263. package/scripts/sw-trace.sh +3 -1
  264. package/scripts/sw-tracker-github.sh +3 -0
  265. package/scripts/sw-tracker-jira.sh +3 -0
  266. package/scripts/sw-tracker-linear.sh +3 -0
  267. package/scripts/sw-tracker.sh +3 -1
  268. package/scripts/sw-triage.sh +3 -2
  269. package/scripts/sw-upgrade.sh +3 -1
  270. package/scripts/sw-ux.sh +5 -2
  271. package/scripts/sw-webhook.sh +5 -2
  272. package/scripts/sw-widgets.sh +9 -4
  273. package/scripts/sw-worktree.sh +15 -3
  274. package/scripts/test-skill-injection.sh +1233 -0
  275. package/templates/pipelines/autonomous.json +27 -3
  276. package/templates/pipelines/cost-aware.json +34 -8
  277. package/templates/pipelines/deployed.json +12 -0
  278. package/templates/pipelines/enterprise.json +12 -0
  279. package/templates/pipelines/fast.json +6 -0
  280. package/templates/pipelines/full.json +27 -3
  281. package/templates/pipelines/hotfix.json +6 -0
  282. package/templates/pipelines/standard.json +12 -0
  283. package/templates/pipelines/tdd.json +12 -0
@@ -0,0 +1,300 @@
1
+ #!/usr/bin/env bash
2
+ # ╔═══════════════════════════════════════════════════════════════════════════╗
3
+ # ║ error-actionability — Score and enhance error messages for clarity ║
4
+ # ║ ║
5
+ # ║ Scores errors 0-100 based on actionability cues: ║
6
+ # ║ - File path present (25 pts) ║
7
+ # ║ - Line number present (20 pts) ║
8
+ # ║ - Specific error type (20 pts) ║
9
+ # ║ - Actionable detail (20 pts) ║
10
+ # ║ - Fix suggestion (15 pts) ║
11
+ # ║ ║
12
+ # ║ Auto-enhances low-scoring errors (<70) with context. ║
13
+ # ║ Provides error extraction, deduplication, and classification. ║
14
+ # ╚═══════════════════════════════════════════════════════════════════════════╝
15
+ set -euo pipefail
16
+
17
+ # Module guard
18
+ [[ -n "${_MODULE_ERROR_ACTIONABILITY_LOADED:-}" ]] && return 0
19
+ _MODULE_ERROR_ACTIONABILITY_LOADED=1
20
+
21
+ VERSION="3.3.0"
22
+
23
+ # Score an error message for actionability
24
+ # Input: error message (string)
25
+ # Output: JSON with score, breakdown, and suggestions
26
+ score_error_actionability() {
27
+ local error_msg="$1"
28
+ local score=0
29
+ local has_filepath=0
30
+ local has_line_number=0
31
+ local has_error_type=0
32
+ local has_actionable_detail=0
33
+ local has_fix_suggestion=0
34
+
35
+ # Check for file path (e.g., /path/to/file.sh, ./scripts/file.sh, scripts/file.sh)
36
+ if [[ $error_msg =~ (/[a-zA-Z0-9._/-]+\.[a-zA-Z]+|\./(scripts|src|lib)/[a-zA-Z0-9._/-]+|scripts/[a-zA-Z0-9._/-]+) ]]; then
37
+ has_filepath=1
38
+ score=$((score + 25))
39
+ fi
40
+
41
+ # Check for line number (e.g., :123, line 123, at line 456)
42
+ if [[ $error_msg =~ (:[0-9]+|line [0-9]+|at line [0-9]+) ]]; then
43
+ has_line_number=1
44
+ score=$((score + 20))
45
+ fi
46
+
47
+ # Check for specific error types (e.g., TypeError, SyntaxError, ENOENT, EACCES, etc.)
48
+ if [[ $error_msg =~ (Error|Exception|ENOENT|EACCES|EAGAIN|EPERM|EEXIST|EISDIR|TypeError|SyntaxError|ReferenceError|RangeError|AssertionError) ]]; then
49
+ has_error_type=1
50
+ score=$((score + 20))
51
+ fi
52
+
53
+ # Check for actionable details (e.g., "cannot read property", "is not a function", "does not exist", "permission denied", "not found")
54
+ if [[ $error_msg =~ (cannot|not found|does not exist|permission denied|not a function|is undefined|is null|unexpected token|invalid|failed to) ]]; then
55
+ has_actionable_detail=1
56
+ score=$((score + 20))
57
+ fi
58
+
59
+ # Check for fix suggestions (e.g., "try", "check", "ensure", "verify", "install", "add", "remove")
60
+ if [[ $error_msg =~ (try |check |ensure |verify |install |add |remove |run |use |export |define ) ]]; then
61
+ has_fix_suggestion=1
62
+ score=$((score + 15))
63
+ fi
64
+
65
+ # Cap score at 100
66
+ if [[ $score -gt 100 ]]; then
67
+ score=100
68
+ fi
69
+
70
+ # Output as JSON
71
+ local json="{
72
+ \"score\": $score,
73
+ \"breakdown\": {
74
+ \"filepath\": $has_filepath,
75
+ \"line_number\": $has_line_number,
76
+ \"error_type\": $has_error_type,
77
+ \"actionable_detail\": $has_actionable_detail,
78
+ \"fix_suggestion\": $has_fix_suggestion
79
+ },
80
+ \"threshold_met\": $([ $score -lt 70 ] && echo "false" || echo "true")
81
+ }"
82
+
83
+ echo "$json"
84
+ }
85
+
86
+ # Enhance a low-scoring error with category labels and file context
87
+ # Input: error message, optionally the file path and line number
88
+ # Output: enhanced error message
89
+ enhance_error_message() {
90
+ local error_msg="$1"
91
+ local filepath="${2:-}"
92
+ local line_number="${3:-}"
93
+ local category=""
94
+
95
+ # Determine error category
96
+ if [[ $error_msg =~ (cannot read|cannot access|no such file|ENOENT|EACCES|permission denied) ]]; then
97
+ category="FILE_ACCESS"
98
+ elif [[ $error_msg =~ (is not a function|is undefined|cannot call|is not callable) ]]; then
99
+ category="FUNCTION_ERROR"
100
+ elif [[ $error_msg =~ (unexpected token|syntax error|parse error) ]]; then
101
+ category="SYNTAX_ERROR"
102
+ elif [[ $error_msg =~ (type error|is not|expected) ]]; then
103
+ category="TYPE_ERROR"
104
+ elif [[ $error_msg =~ (assertion|assert|expected|failed) ]]; then
105
+ category="ASSERTION_FAILURE"
106
+ elif [[ $error_msg =~ (timeout|timed out|hang|deadlock) ]]; then
107
+ category="TIMEOUT"
108
+ elif [[ $error_msg =~ (out of memory|OOM|memory|stack) ]]; then
109
+ category="MEMORY_ERROR"
110
+ elif [[ $error_msg =~ (network|socket|ECONNREFUSED|ECONNRESET|ETIMEDOUT) ]]; then
111
+ category="NETWORK_ERROR"
112
+ else
113
+ category="UNKNOWN"
114
+ fi
115
+
116
+ # Extract file path and line number from error if not provided
117
+ local extracted_filepath=""
118
+ local extracted_line=""
119
+
120
+ if [[ -z "$filepath" && $error_msg =~ (/[a-zA-Z0-9._/-]+\.[a-zA-Z]+|\./(scripts|src|lib)/[a-zA-Z0-9._/-]+) ]]; then
121
+ extracted_filepath="${BASH_REMATCH[0]}"
122
+ else
123
+ extracted_filepath="$filepath"
124
+ fi
125
+
126
+ if [[ -z "$line_number" && $error_msg =~ (:[0-9]+) ]]; then
127
+ extracted_line="${BASH_REMATCH[1]#:}"
128
+ else
129
+ extracted_line="$line_number"
130
+ fi
131
+
132
+ # Build enhanced message
133
+ local enhanced="[${category}] ${error_msg}"
134
+
135
+ # Add file context if available
136
+ if [[ -n "$extracted_filepath" ]] && [[ -f "$extracted_filepath" ]]; then
137
+ if [[ -n "$extracted_line" ]] && [[ $extracted_line =~ ^[0-9]+$ ]]; then
138
+ # Show context around the line (2 lines before and after)
139
+ local start_line=$((extracted_line - 2))
140
+ local end_line=$((extracted_line + 2))
141
+ [[ $start_line -lt 1 ]] && start_line=1
142
+
143
+ enhanced+=$'\n Context: '
144
+ if command -v sed &>/dev/null; then
145
+ enhanced+=$(sed -n "${start_line},${end_line}p" "$extracted_filepath" 2>/dev/null | \
146
+ awk -v target_line="$extracted_line" 'NR==target_line-start+1 {print " > " $0; next} {print " " $0}' \
147
+ -v start="$start_line" || echo "")
148
+ fi
149
+ fi
150
+ fi
151
+
152
+ echo "$enhanced"
153
+ }
154
+
155
+ # Main entry point: Score and optionally enhance an error
156
+ # Usage: eval_error_message "error message" [filepath] [line_number]
157
+ eval_error_message() {
158
+ local error_msg="$1"
159
+ local filepath="${2:-}"
160
+ local line_number="${3:-}"
161
+
162
+ # Score the error
163
+ local score_json
164
+ score_json=$(score_error_actionability "$error_msg")
165
+ local score
166
+ score=$(echo "$score_json" | grep -o '"score": [0-9]*' | cut -d: -f2 | tr -d ' ')
167
+
168
+ # Output score info
169
+ echo "$score_json"
170
+
171
+ # If score < 70, enhance the message
172
+ if [[ $score -lt 70 ]]; then
173
+ echo "---ENHANCEMENT---"
174
+ enhance_error_message "$error_msg" "$filepath" "$line_number"
175
+ fi
176
+ }
177
+
178
+ # For simple cases: just get the score
179
+ get_error_score() {
180
+ local error_msg="$1"
181
+ local score_json
182
+ score_json=$(score_error_actionability "$error_msg")
183
+ echo "$score_json" | grep -o '"score": [0-9]*' | cut -d: -f2 | tr -d ' '
184
+ }
185
+
186
+ # For testing: check if error needs enhancement
187
+ needs_enhancement() {
188
+ local error_msg="$1"
189
+ local score
190
+ score=$(get_error_score "$error_msg")
191
+ [[ $score -lt 70 ]] && return 0 || return 1
192
+ }
193
+
194
+ # ─── Additional Functions for Issue #187 ──────────────────────────────────
195
+
196
+ # Extract file and line number from error message
197
+ # Output: JSON with file and line fields, or empty if not found
198
+ erract_extract_location() {
199
+ local error_msg="$1"
200
+ local file=""
201
+ local line=""
202
+
203
+ # Pattern 1: file.sh:123
204
+ if [[ $error_msg =~ ([a-zA-Z0-9._/-]+\.[a-zA-Z]+):([0-9]+) ]]; then
205
+ file="${BASH_REMATCH[1]}"
206
+ line="${BASH_REMATCH[2]}"
207
+ # Pattern 2: at line 123
208
+ elif [[ $error_msg =~ at[[:space:]]+line[[:space:]]+([0-9]+) ]]; then
209
+ line="${BASH_REMATCH[1]}"
210
+ # Pattern 3: File "file.py", line 123
211
+ elif [[ $error_msg =~ File[[:space:]]+\"([^\"]+)\",[[:space:]]+line[[:space:]]+([0-9]+) ]]; then
212
+ file="${BASH_REMATCH[1]}"
213
+ line="${BASH_REMATCH[2]}"
214
+ fi
215
+
216
+ # Output JSON
217
+ if [[ -n "$file" ]] || [[ -n "$line" ]]; then
218
+ jq -n \
219
+ --arg file "$file" \
220
+ --arg line "$line" \
221
+ '{file: $file, line: ($line | tonumber? // empty)}'
222
+ else
223
+ echo "{}"
224
+ fi
225
+ }
226
+
227
+ # Remove duplicate error lines and ANSI codes
228
+ # Collapses repeated lines into "... (repeated N times)"
229
+ # Output: cleaned error output (max 50 lines by default)
230
+ erract_deduplicate() {
231
+ local error_output="$1"
232
+ local max_lines="${2:-50}"
233
+ local prev_line=""
234
+ local repeat_count=0
235
+ local line_num=0
236
+
237
+ while IFS= read -r line; do
238
+ line_num=$((line_num + 1))
239
+
240
+ # Strip ANSI color codes using sed (bash 3.2 compatible)
241
+ local clean_line
242
+ clean_line=$(printf '%s' "$line" | sed 's/\x1b\[[0-9;]*m//g')
243
+
244
+ # Skip empty lines
245
+ [[ -z "$clean_line" ]] && continue
246
+
247
+ # Check if this line is same as previous
248
+ if [[ "$clean_line" == "$prev_line" ]]; then
249
+ repeat_count=$((repeat_count + 1))
250
+ else
251
+ # Output previous line (if there was repetition)
252
+ if [[ $repeat_count -gt 0 ]]; then
253
+ printf '%s (repeated %d times)\n' "$prev_line" "$repeat_count"
254
+ elif [[ -n "$prev_line" ]]; then
255
+ printf '%s\n' "$prev_line"
256
+ fi
257
+
258
+ prev_line="$clean_line"
259
+ repeat_count=0
260
+
261
+ # Stop if we've output max_lines
262
+ if [[ $line_num -gt $max_lines ]]; then
263
+ break
264
+ fi
265
+ fi
266
+ done <<< "$error_output"
267
+
268
+ # Output final line
269
+ if [[ -n "$prev_line" ]]; then
270
+ if [[ $repeat_count -gt 0 ]]; then
271
+ printf '%s (repeated %d times)\n' "$prev_line" "$repeat_count"
272
+ else
273
+ printf '%s\n' "$prev_line"
274
+ fi
275
+ fi
276
+ }
277
+
278
+ # Classify error into one of: syntax, type, assertion, runtime, dependency, permission, network, unknown
279
+ # Output: error type string
280
+ erract_classify() {
281
+ local error_msg="$1"
282
+
283
+ if [[ $error_msg =~ (SyntaxError|parse error|unexpected token|invalid syntax) ]]; then
284
+ echo "syntax"
285
+ elif [[ $error_msg =~ (TypeError|type mismatch|wrong.*type|is not.*type|expected.*but got) ]]; then
286
+ echo "type"
287
+ elif [[ $error_msg =~ (AssertionError|assert|expect|should|test.*failed) ]]; then
288
+ echo "assertion"
289
+ elif [[ $error_msg =~ (segfault|Segmentation fault|OOM|out of memory|SIGKILL|signal 9|Killed|timeout|timed out) ]]; then
290
+ echo "runtime"
291
+ elif [[ $error_msg =~ (module not found|cannot find|import error|no such package|ENOENT|not found) ]]; then
292
+ echo "dependency"
293
+ elif [[ $error_msg =~ (EACCES|permission denied|permission.*denied|Access denied) ]]; then
294
+ echo "permission"
295
+ elif [[ $error_msg =~ (ECONNREFUSED|ECONNRESET|timeout|network|socket|DNS) ]]; then
296
+ echo "network"
297
+ else
298
+ echo "unknown"
299
+ fi
300
+ }