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
+ # skill-memory.sh — Records pipeline outcomes per skill combination
3
+ # Stores data in ~/.shipwright/skill-memory.json
4
+ # Provides functions to query success rates and get recommendations
5
+ [[ -n "${_SKILL_MEMORY_LOADED:-}" ]] && return 0
6
+ _SKILL_MEMORY_LOADED=1
7
+
8
+ SKILL_MEMORY_FILE="${HOME}/.shipwright/skill-memory.json"
9
+ SKILL_MEMORY_MAX_RECORDS=200
10
+
11
+ # ─── Initialization ─────────────────────────────────────────────────────────
12
+
13
+ # _skill_memory_ensure_file — Create memory file if it doesn't exist or is empty
14
+ _skill_memory_ensure_file() {
15
+ if [[ ! -f "$SKILL_MEMORY_FILE" ]] || [[ ! -s "$SKILL_MEMORY_FILE" ]]; then
16
+ mkdir -p "$(dirname "$SKILL_MEMORY_FILE")"
17
+ printf '{"records":[]}\n' > "$SKILL_MEMORY_FILE"
18
+ fi
19
+ }
20
+
21
+ # ─── Core API ───────────────────────────────────────────────────────────────
22
+
23
+ # skill_memory_record — Record outcome for a skill+stage combination
24
+ # $1: issue_type (frontend|backend|api|database|infrastructure|documentation|security|performance|refactor|testing)
25
+ # $2: stage (plan|design|build|test|review|compound_quality|pr|deploy|validate|monitor)
26
+ # $3: skills_used (comma-separated skill names, not paths)
27
+ # $4: outcome (success|failure|retry)
28
+ # $5: attempt_number (1, 2, 3...)
29
+ # $6: verdict (optional — "effective"|"partially_effective"|"ineffective")
30
+ # $7: evidence (optional — why this verdict)
31
+ # $8: learning (optional — one-sentence takeaway)
32
+ # Returns: 0 on success, 1 on error
33
+ skill_memory_record() {
34
+ local issue_type="${1:-backend}"
35
+ local stage="${2:-plan}"
36
+ local skills_used="${3:-}"
37
+ local outcome="${4:-success}"
38
+ local attempt="${5:-1}"
39
+ local verdict="${6:-}"
40
+ local evidence="${7:-}"
41
+ local learning="${8:-}"
42
+
43
+ [[ -z "$skills_used" ]] && return 1
44
+
45
+ _skill_memory_ensure_file
46
+
47
+ # Build JSON record
48
+ local timestamp
49
+ timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
50
+
51
+ local record
52
+ record=$(jq -n \
53
+ --arg it "$issue_type" --arg st "$stage" --arg sk "$skills_used" \
54
+ --arg oc "$outcome" --argjson at "$attempt" --arg ts "$timestamp" \
55
+ --arg vd "$verdict" --arg ev "$evidence" --arg lr "$learning" \
56
+ '{issue_type:$it, stage:$st, skills:$sk, outcome:$oc, attempt:$at, timestamp:$ts, verdict:$vd, evidence:$ev, learning:$lr}')
57
+
58
+ # Append to records array, handling potential jq unavailability
59
+ if ! command -v jq &>/dev/null; then
60
+ return 1
61
+ fi
62
+
63
+ # Use portable file locking (flock on Linux, simple wait on macOS)
64
+ local lockfile="${SKILL_MEMORY_FILE}.lock"
65
+ local lock_attempts=0
66
+ local max_lock_attempts=50 # ~5 seconds with 100ms waits
67
+
68
+ # Acquire lock
69
+ while [[ -f "$lockfile" ]] && [[ $lock_attempts -lt $max_lock_attempts ]]; do
70
+ lock_attempts=$((lock_attempts + 1))
71
+ sleep 0.1
72
+ done
73
+
74
+ if [[ $lock_attempts -ge $max_lock_attempts ]]; then
75
+ return 1 # Lock timeout
76
+ fi
77
+
78
+ # Create lock file
79
+ echo "$$" > "$lockfile"
80
+
81
+ # Read current records (don't use subshell to preserve variables)
82
+ local current_records
83
+ current_records=$(jq '.records' "$SKILL_MEMORY_FILE" 2>/dev/null || printf '[]')
84
+
85
+ # Add new record and trim to max
86
+ local updated
87
+ updated=$(printf '%s' "$current_records" | jq \
88
+ --argjson rec "$record" \
89
+ --argjson max "$SKILL_MEMORY_MAX_RECORDS" \
90
+ '(. + [$rec]) | sort_by(.timestamp) | .[-$max:]'
91
+ )
92
+
93
+ # Write back atomically
94
+ printf '{"records":%s}\n' "$updated" > "$SKILL_MEMORY_FILE"
95
+
96
+ # Release lock
97
+ rm -f "$lockfile"
98
+
99
+ return 0
100
+ }
101
+
102
+ # skill_memory_get_success_rate — Get success rate for a skill combo
103
+ # $1: issue_type
104
+ # $2: stage
105
+ # $3: skill_name
106
+ # Returns: success rate as percentage (0-100), or empty if no data
107
+ skill_memory_get_success_rate() {
108
+ local issue_type="${1:-backend}"
109
+ local stage="${2:-plan}"
110
+ local skill_name="${3:-}"
111
+
112
+ [[ -z "$skill_name" ]] && return 1
113
+ [[ ! -f "$SKILL_MEMORY_FILE" ]] && return 1
114
+
115
+ if ! command -v jq &>/dev/null; then
116
+ return 1
117
+ fi
118
+
119
+ local success_count fail_count
120
+ success_count=$(jq --arg it "$issue_type" --arg st "$stage" --arg sk "$skill_name" '[.records[] | select(.issue_type == $it and .stage == $st and (.skills | split(",") | contains([$sk])))] | map(select(.outcome == "success")) | length' "$SKILL_MEMORY_FILE" 2>/dev/null || printf '0')
121
+
122
+ fail_count=$(jq --arg it "$issue_type" --arg st "$stage" --arg sk "$skill_name" '[.records[] | select(.issue_type == $it and .stage == $st and (.skills | split(",") | contains([$sk])))] | map(select(.outcome != "success")) | length' "$SKILL_MEMORY_FILE" 2>/dev/null || printf '0')
123
+
124
+ local total=$((success_count + fail_count))
125
+ [[ "$total" -eq 0 ]] && return 1
126
+
127
+ local rate=$((success_count * 100 / total))
128
+ printf '%d' "$rate"
129
+ }
130
+
131
+ # skill_memory_get_recommendations — Get recommended skills based on history
132
+ # $1: issue_type
133
+ # $2: stage
134
+ # Returns: comma-separated skill names sorted by success rate (highest first)
135
+ skill_memory_get_recommendations() {
136
+ local issue_type="${1:-backend}"
137
+ local stage="${2:-plan}"
138
+
139
+ [[ ! -f "$SKILL_MEMORY_FILE" ]] && return 0
140
+
141
+ if ! command -v jq &>/dev/null; then
142
+ return 0
143
+ fi
144
+
145
+ # Get all skills used in this (issue_type, stage) and their success rates
146
+ local skills_json
147
+ skills_json=$(jq --arg it "$issue_type" --arg st "$stage" '
148
+ .records as $original_records |
149
+ [.records[] | select(.issue_type == $it and .stage == $st)] |
150
+ map(.skills | split(",") | .[]) |
151
+ unique |
152
+ map({
153
+ name: .,
154
+ total: [$original_records[] | select(.issue_type == $it and .stage == $st and (.skills | split(",") | contains([.])))] | length
155
+ })
156
+ ' "$SKILL_MEMORY_FILE" 2>/dev/null || printf '[]')
157
+
158
+ # For each skill, calculate success rate and output
159
+ local recommendations
160
+ recommendations=$(printf '%s' "$skills_json" | jq -r '.[] | .name' 2>/dev/null | while read -r skill; do
161
+ local rate
162
+ rate=$(skill_memory_get_success_rate "$issue_type" "$stage" "$skill" 2>/dev/null || printf '0')
163
+ printf '%d,%s\n' "$rate" "$skill"
164
+ done | sort -rn | awk -F, '{print $2}' | tr '\n' ',' | sed 's/,$//')
165
+
166
+ printf '%s' "$recommendations"
167
+ }
168
+
169
+ # skill_memory_stats — Get statistics for a skill/stage combo
170
+ # $1: issue_type
171
+ # $2: stage (optional)
172
+ # $3: skill_name (optional)
173
+ # Returns: JSON with success_count, failure_count, retry_count, success_rate
174
+ skill_memory_stats() {
175
+ local issue_type="${1:-backend}"
176
+ local stage="${2:-}"
177
+ local skill_name="${3:-}"
178
+
179
+ [[ ! -f "$SKILL_MEMORY_FILE" ]] && return 1
180
+
181
+ if ! command -v jq &>/dev/null; then
182
+ return 1
183
+ fi
184
+
185
+ local filter='.issue_type == "'$issue_type'"'
186
+ [[ -n "$stage" ]] && filter="$filter and .stage == \"$stage\""
187
+ [[ -n "$skill_name" ]] && filter="$filter and (.skills | split(\",\") | contains([\"$skill_name\"]))"
188
+
189
+ jq --arg it "$issue_type" --arg st "$stage" --arg sk "$skill_name" '
190
+ [.records[] | select($it != "" and .issue_type == $it) | select(($st == "" or .stage == $st)) | select(($sk == "" or (.skills | split(",") | contains([$sk]))))] |
191
+ {
192
+ success_count: map(select(.outcome == "success")) | length,
193
+ failure_count: map(select(.outcome == "failure")) | length,
194
+ retry_count: map(select(.outcome == "retry")) | length,
195
+ success_rate: (
196
+ (map(select(.outcome == "success")) | length) as $success |
197
+ if (. | length) == 0 then 0
198
+ else ($success * 100 / (. | length) | floor)
199
+ end
200
+ ),
201
+ total_records: (. | length)
202
+ }
203
+ ' "$SKILL_MEMORY_FILE" 2>/dev/null || printf '{"error":"unable to compute stats"}'
204
+ }
205
+
206
+ # skill_memory_clear — Clear all memory (useful for testing)
207
+ skill_memory_clear() {
208
+ if [[ -f "$SKILL_MEMORY_FILE" ]]; then
209
+ rm -f "$SKILL_MEMORY_FILE" "${SKILL_MEMORY_FILE}.lock"
210
+ fi
211
+ _skill_memory_ensure_file
212
+ }
213
+
214
+ # skill_memory_export — Export records as JSON (useful for analysis)
215
+ skill_memory_export() {
216
+ [[ ! -f "$SKILL_MEMORY_FILE" ]] && printf '{"records":[]}\n' && return 0
217
+ cat "$SKILL_MEMORY_FILE"
218
+ }
219
+
220
+ # skill_memory_import — Import records from JSON file
221
+ # $1: path to JSON file with {"records": [...]} structure
222
+ skill_memory_import() {
223
+ local import_file="${1:-}"
224
+ [[ -z "$import_file" || ! -f "$import_file" ]] && return 1
225
+
226
+ if ! command -v jq &>/dev/null; then
227
+ return 1
228
+ fi
229
+
230
+ local lockfile="${SKILL_MEMORY_FILE}.lock"
231
+ local lock_attempts=0
232
+ local max_lock_attempts=50
233
+
234
+ while [[ -f "$lockfile" ]] && [[ $lock_attempts -lt $max_lock_attempts ]]; do
235
+ lock_attempts=$((lock_attempts + 1))
236
+ sleep 0.1
237
+ done
238
+
239
+ if [[ $lock_attempts -ge $max_lock_attempts ]]; then
240
+ return 1
241
+ fi
242
+
243
+ echo "$$" > "$lockfile"
244
+
245
+ # Merge records, dedup by timestamp, keep newest
246
+ local merged
247
+ merged=$(jq -s \
248
+ --argjson max "$SKILL_MEMORY_MAX_RECORDS" \
249
+ '[.[0].records, .[1].records] | flatten |
250
+ unique_by(.timestamp + .issue_type + .stage + .skills) |
251
+ sort_by(.timestamp) |
252
+ .[-$max:]' \
253
+ "$SKILL_MEMORY_FILE" "$import_file")
254
+
255
+ printf '{"records":%s}\n' "$merged" > "$SKILL_MEMORY_FILE"
256
+
257
+ rm -f "$lockfile"
258
+
259
+ return 0
260
+ }
261
+
262
+ # skill_memory_prune — Keep only N most recent records
263
+ # $1: max_records (default 200)
264
+ skill_memory_prune() {
265
+ local max_records="${1:-200}"
266
+ [[ ! -f "$SKILL_MEMORY_FILE" ]] && return 0
267
+
268
+ if ! command -v jq &>/dev/null; then
269
+ return 1
270
+ fi
271
+
272
+ local lockfile="${SKILL_MEMORY_FILE}.lock"
273
+ local lock_attempts=0
274
+ local max_lock_attempts=50
275
+
276
+ while [[ -f "$lockfile" ]] && [[ $lock_attempts -lt $max_lock_attempts ]]; do
277
+ lock_attempts=$((lock_attempts + 1))
278
+ sleep 0.1
279
+ done
280
+
281
+ if [[ $lock_attempts -ge $max_lock_attempts ]]; then
282
+ return 1
283
+ fi
284
+
285
+ echo "$$" > "$lockfile"
286
+
287
+ local pruned
288
+ pruned=$(jq --argjson max "$max_records" \
289
+ '.records |= sort_by(.timestamp) | .records |= .[-$max:]' \
290
+ "$SKILL_MEMORY_FILE")
291
+
292
+ printf '%s\n' "$pruned" > "$SKILL_MEMORY_FILE"
293
+
294
+ rm -f "$lockfile"
295
+
296
+ return 0
297
+ }
298
+
299
+ # Initialize on load
300
+ _skill_memory_ensure_file