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,1109 @@
1
+ # AI-Powered Skill Injection Implementation Plan
2
+
3
+ > **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
4
+
5
+ **Goal:** Replace static rules-based skill selection with LLM-powered intelligent routing, dynamic skill generation, and outcome learning.
6
+
7
+ **Architecture:** One haiku LLM call at intake analyzes the issue and returns a complete skill plan (selection + rationale + generated skills). Downstream stages read from the plan artifact. A second haiku call at completion analyzes outcomes and refines the skill library. Static registry remains as three-layer fallback.
8
+
9
+ **Tech Stack:** Bash, jq, Claude CLI (haiku model via `_intelligence_call_claude()`), JSON artifacts
10
+
11
+ ---
12
+
13
+ ### Task 1: Create Generated Skills Directory Structure
14
+
15
+ **Files:**
16
+ - Create: `scripts/skills/generated/.gitkeep`
17
+ - Create: `scripts/skills/generated/_refinements/.gitkeep`
18
+
19
+ **Step 1: Create directories**
20
+
21
+ ```bash
22
+ mkdir -p scripts/skills/generated/_refinements
23
+ touch scripts/skills/generated/.gitkeep
24
+ touch scripts/skills/generated/_refinements/.gitkeep
25
+ ```
26
+
27
+ **Step 2: Commit**
28
+
29
+ ```bash
30
+ git add scripts/skills/generated/
31
+ git commit -m "chore: add generated skills directory structure"
32
+ ```
33
+
34
+ ---
35
+
36
+ ### Task 2: Add `skill_build_catalog()` to skill-registry.sh
37
+
38
+ **Files:**
39
+ - Modify: `scripts/lib/skill-registry.sh` (append after line 319)
40
+ - Test: `scripts/test-skill-injection.sh`
41
+
42
+ **Step 1: Write the failing test**
43
+
44
+ Add Suite 11 to `scripts/test-skill-injection.sh`:
45
+
46
+ ```bash
47
+ echo ""
48
+ echo "═══ Suite 11: Skill Catalog Builder ═══"
49
+ echo ""
50
+
51
+ # Test: catalog includes curated skills
52
+ echo " ── Curated skills in catalog ──"
53
+ local catalog
54
+ catalog=$(skill_build_catalog 2>/dev/null || true)
55
+ assert_contains "$catalog" "brainstorming" "catalog includes brainstorming"
56
+ assert_contains "$catalog" "frontend-design" "catalog includes frontend-design"
57
+ assert_contains "$catalog" "security-audit" "catalog includes security-audit"
58
+
59
+ # Test: catalog includes one-line descriptions
60
+ assert_contains "$catalog" "Socratic" "brainstorming has description"
61
+
62
+ # Test: catalog includes generated skills when they exist
63
+ local _gen_dir="${SKILLS_DIR}/generated"
64
+ mkdir -p "$_gen_dir"
65
+ echo "## Test Generated Skill\nTest content for generated skill." > "$_gen_dir/test-gen-skill.md"
66
+ catalog=$(skill_build_catalog 2>/dev/null || true)
67
+ assert_contains "$catalog" "test-gen-skill" "catalog includes generated skill"
68
+ assert_contains "$catalog" "[generated]" "generated skill is tagged"
69
+ rm -f "$_gen_dir/test-gen-skill.md"
70
+
71
+ # Test: catalog includes memory context when available
72
+ skill_memory_clear 2>/dev/null || true
73
+ skill_memory_record "frontend" "plan" "brainstorming" "success" "1" >/dev/null 2>&1 || true
74
+ skill_memory_record "frontend" "plan" "brainstorming" "success" "1" >/dev/null 2>&1 || true
75
+ catalog=$(skill_build_catalog "frontend" "plan" 2>/dev/null || true)
76
+ assert_contains "$catalog" "success" "catalog includes memory context"
77
+ skill_memory_clear 2>/dev/null || true
78
+ ```
79
+
80
+ **Step 2: Run test to verify it fails**
81
+
82
+ Run: `bash scripts/test-skill-injection.sh 2>&1 | grep -A2 "Suite 11"`
83
+ Expected: FAIL — `skill_build_catalog: command not found`
84
+
85
+ **Step 3: Write the implementation**
86
+
87
+ Append to `scripts/lib/skill-registry.sh` after line 319:
88
+
89
+ ```bash
90
+ # ─────────────────────────────────────────────────────────────────────────────
91
+ # AI-POWERED SKILL SELECTION (Tier 1)
92
+ # ─────────────────────────────────────────────────────────────────────────────
93
+
94
+ GENERATED_SKILLS_DIR="${SKILLS_DIR}/generated"
95
+ REFINEMENTS_DIR="${GENERATED_SKILLS_DIR}/_refinements"
96
+
97
+ # skill_build_catalog — Build a compact skill index for the LLM router prompt.
98
+ # $1: issue_type (optional — for memory context)
99
+ # $2: stage (optional — for memory context)
100
+ # Returns: multi-line text, one skill per line with description and optional memory stats.
101
+ skill_build_catalog() {
102
+ local issue_type="${1:-}" stage="${2:-}"
103
+ local catalog=""
104
+
105
+ # Scan curated skills
106
+ local skill_file
107
+ for skill_file in "$SKILLS_DIR"/*.md; do
108
+ [[ ! -f "$skill_file" ]] && continue
109
+ local name
110
+ name=$(basename "$skill_file" .md)
111
+ # Extract first meaningful line as description (skip headers, blank lines)
112
+ local desc
113
+ desc=$(grep -v '^#\|^$\|^---\|^\*\*IMPORTANT' "$skill_file" 2>/dev/null | head -1 | cut -c1-120 || echo "")
114
+ [[ -z "$desc" ]] && desc=$(head -1 "$skill_file" | sed 's/^#* *//' | cut -c1-120)
115
+
116
+ local memory_hint=""
117
+ if [[ -n "$issue_type" && -n "$stage" ]] && type skill_memory_get_success_rate >/dev/null 2>&1; then
118
+ local rate
119
+ rate=$(skill_memory_get_success_rate "$issue_type" "$stage" "$name" 2>/dev/null || true)
120
+ [[ -n "$rate" ]] && memory_hint=" [${rate}% success for ${issue_type}/${stage}]"
121
+ fi
122
+
123
+ catalog="${catalog}
124
+ - ${name}: ${desc}${memory_hint}"
125
+ done
126
+
127
+ # Scan generated skills
128
+ if [[ -d "$GENERATED_SKILLS_DIR" ]]; then
129
+ for skill_file in "$GENERATED_SKILLS_DIR"/*.md; do
130
+ [[ ! -f "$skill_file" ]] && continue
131
+ local name
132
+ name=$(basename "$skill_file" .md)
133
+ local desc
134
+ desc=$(grep -v '^#\|^$\|^---\|^\*\*IMPORTANT' "$skill_file" 2>/dev/null | head -1 | cut -c1-120 || echo "")
135
+ [[ -z "$desc" ]] && desc=$(head -1 "$skill_file" | sed 's/^#* *//' | cut -c1-120)
136
+
137
+ local memory_hint=""
138
+ if [[ -n "$issue_type" && -n "$stage" ]] && type skill_memory_get_success_rate >/dev/null 2>&1; then
139
+ local rate
140
+ rate=$(skill_memory_get_success_rate "$issue_type" "$stage" "$name" 2>/dev/null || true)
141
+ [[ -n "$rate" ]] && memory_hint=" [${rate}% success for ${issue_type}/${stage}]"
142
+ fi
143
+
144
+ catalog="${catalog}
145
+ - ${name} [generated]: ${desc}${memory_hint}"
146
+ done
147
+ fi
148
+
149
+ echo "$catalog"
150
+ }
151
+ ```
152
+
153
+ **Step 4: Run test to verify it passes**
154
+
155
+ Run: `bash scripts/test-skill-injection.sh 2>&1 | tail -5`
156
+ Expected: ALL TESTS PASSED
157
+
158
+ **Step 5: Commit**
159
+
160
+ ```bash
161
+ git add scripts/lib/skill-registry.sh scripts/test-skill-injection.sh
162
+ git commit -m "feat(skills): add skill_build_catalog for LLM router prompt"
163
+ ```
164
+
165
+ ---
166
+
167
+ ### Task 3: Add `skill_analyze_issue()` — the LLM Router
168
+
169
+ **Files:**
170
+ - Modify: `scripts/lib/skill-registry.sh` (append after `skill_build_catalog`)
171
+ - Test: `scripts/test-skill-injection.sh`
172
+
173
+ **Step 1: Write the failing test**
174
+
175
+ Add to Suite 11 in `scripts/test-skill-injection.sh`:
176
+
177
+ ```bash
178
+ echo ""
179
+ echo " ── LLM skill analysis (mock) ──"
180
+
181
+ # We can't test real LLM calls in unit tests, so test the JSON parsing/artifact writing
182
+ # Mock: simulate skill_analyze_issue writing skill-plan.json
183
+ local _test_artifacts
184
+ _test_artifacts=$(mktemp -d)
185
+
186
+ local _mock_plan='{"issue_type":"frontend","confidence":0.92,"secondary_domains":["accessibility"],"complexity_assessment":{"score":6,"reasoning":"moderate"},"skill_plan":{"plan":["brainstorming","frontend-design"],"build":["frontend-design"],"review":["two-stage-review"]},"skill_rationale":{"frontend-design":"ARIA progressbar needed","brainstorming":"Task decomposition required"},"generated_skills":[],"review_focus":["accessibility"],"risk_areas":["ETA accuracy"]}'
187
+ echo "$_mock_plan" > "$_test_artifacts/skill-plan.json"
188
+
189
+ # Verify skill-plan.json is valid JSON
190
+ assert_true "jq '.' '$_test_artifacts/skill-plan.json' >/dev/null 2>&1" "skill-plan.json is valid JSON"
191
+
192
+ # Verify we can extract skills for a stage
193
+ local _plan_skills
194
+ _plan_skills=$(jq -r '.skill_plan.plan[]' "$_test_artifacts/skill-plan.json" 2>/dev/null | tr '\n' ',' | sed 's/,$//')
195
+ assert_eq "$_plan_skills" "brainstorming,frontend-design" "plan stage skills extracted correctly"
196
+
197
+ # Verify rationale extraction
198
+ local _rationale
199
+ _rationale=$(jq -r '.skill_rationale["frontend-design"]' "$_test_artifacts/skill-plan.json" 2>/dev/null)
200
+ assert_contains "$_rationale" "ARIA" "rationale extracted correctly"
201
+
202
+ rm -rf "$_test_artifacts"
203
+ ```
204
+
205
+ **Step 2: Run test to verify it fails**
206
+
207
+ Run: `bash scripts/test-skill-injection.sh 2>&1 | grep "LLM skill analysis"`
208
+ Expected: Tests should pass (testing JSON parsing, not LLM call)
209
+
210
+ **Step 3: Write the implementation**
211
+
212
+ Append to `scripts/lib/skill-registry.sh`:
213
+
214
+ ```bash
215
+ # skill_analyze_issue — LLM-powered skill selection and gap detection.
216
+ # $1: issue_title
217
+ # $2: issue_body
218
+ # $3: issue_labels
219
+ # $4: artifacts_dir (where to write skill-plan.json)
220
+ # $5: intelligence_json (optional — reuse from intelligence_analyze_issue)
221
+ # Returns: 0 on success (skill-plan.json written), 1 on failure (caller should fallback)
222
+ # Requires: _intelligence_call_claude() from sw-intelligence.sh
223
+ skill_analyze_issue() {
224
+ local title="${1:-}" body="${2:-}" labels="${3:-}"
225
+ local artifacts_dir="${4:-${ARTIFACTS_DIR:-.claude/pipeline-artifacts}}"
226
+ local intelligence_json="${5:-}"
227
+
228
+ # Verify we have the LLM call function
229
+ if ! type _intelligence_call_claude >/dev/null 2>&1; then
230
+ return 1
231
+ fi
232
+
233
+ # Build the skill catalog
234
+ local catalog
235
+ catalog=$(skill_build_catalog "" "" 2>/dev/null || true)
236
+ [[ -z "$catalog" ]] && return 1
237
+
238
+ # Build memory recommendations
239
+ local memory_context=""
240
+ if type skill_memory_get_recommendations >/dev/null 2>&1; then
241
+ local recs
242
+ recs=$(skill_memory_get_recommendations "backend" "plan" 2>/dev/null || true)
243
+ [[ -n "$recs" ]] && memory_context="Historical skill performance: $recs"
244
+ fi
245
+
246
+ # Build the prompt
247
+ local prompt
248
+ prompt="You are a pipeline skill router. Analyze this GitHub issue and select the best skills for each pipeline stage.
249
+
250
+ ## Issue
251
+ Title: ${title}
252
+ Labels: ${labels}
253
+ Body:
254
+ ${body}
255
+
256
+ ## Available Skills
257
+ ${catalog}
258
+
259
+ ${memory_context:+## Historical Context
260
+ $memory_context
261
+ }
262
+ ${intelligence_json:+## Intelligence Analysis
263
+ $intelligence_json
264
+ }
265
+ ## Pipeline Stages
266
+ Skills can be assigned to: plan, design, build, review, compound_quality, pr, deploy, validate, monitor
267
+
268
+ ## Instructions
269
+ 1. Classify the issue type (frontend|backend|api|database|infrastructure|documentation|security|performance|refactor|testing)
270
+ 2. Select 1-4 skills per stage from the catalog. Only select skills relevant to that stage.
271
+ 3. For each selected skill, write a one-sentence rationale explaining WHY this skill matters for THIS specific issue (not generic advice).
272
+ 4. If the issue needs expertise not covered by any existing skill, generate a new skill with focused, actionable content (200-400 words).
273
+ 5. Identify specific review focus areas and risk areas for this issue.
274
+
275
+ ## Response Format (JSON only, no markdown)
276
+ {
277
+ \"issue_type\": \"frontend\",
278
+ \"confidence\": 0.92,
279
+ \"secondary_domains\": [\"accessibility\", \"real-time\"],
280
+ \"complexity_assessment\": {
281
+ \"score\": 6,
282
+ \"reasoning\": \"Brief explanation\"
283
+ },
284
+ \"skill_plan\": {
285
+ \"plan\": [\"skill-name-1\", \"skill-name-2\"],
286
+ \"design\": [\"skill-name\"],
287
+ \"build\": [\"skill-name\"],
288
+ \"review\": [\"skill-name\"],
289
+ \"compound_quality\": [\"skill-name\"],
290
+ \"pr\": [\"skill-name\"],
291
+ \"deploy\": [\"skill-name\"],
292
+ \"validate\": [],
293
+ \"monitor\": []
294
+ },
295
+ \"skill_rationale\": {
296
+ \"skill-name-1\": \"Why this skill matters for this specific issue\",
297
+ \"skill-name-2\": \"Why this skill matters\"
298
+ },
299
+ \"generated_skills\": [
300
+ {
301
+ \"name\": \"new-skill-name\",
302
+ \"reason\": \"Why no existing skill covers this\",
303
+ \"content\": \"## Skill Title\\n\\nActionable guidance...\"
304
+ }
305
+ ],
306
+ \"review_focus\": [\"specific area 1\", \"specific area 2\"],
307
+ \"risk_areas\": [\"specific risk 1\"]
308
+ }"
309
+
310
+ # Call the LLM
311
+ local cache_key="skill_analysis_$(echo "${title}${body}" | md5sum 2>/dev/null | cut -c1-16 || echo "${RANDOM}")"
312
+ local result
313
+ if ! result=$(_intelligence_call_claude "$prompt" "$cache_key" 3600 "haiku"); then
314
+ return 1
315
+ fi
316
+
317
+ # Validate the response has required fields
318
+ local valid
319
+ valid=$(echo "$result" | jq 'has("issue_type") and has("skill_plan") and has("skill_rationale")' 2>/dev/null || echo "false")
320
+ if [[ "$valid" != "true" ]]; then
321
+ warn "Skill analysis returned invalid JSON — falling back to static selection"
322
+ return 1
323
+ fi
324
+
325
+ # Write skill-plan.json
326
+ mkdir -p "$artifacts_dir"
327
+ echo "$result" | jq '.' > "$artifacts_dir/skill-plan.json"
328
+
329
+ # Save any generated skills to disk
330
+ local gen_count
331
+ gen_count=$(echo "$result" | jq '.generated_skills | length' 2>/dev/null || echo "0")
332
+ if [[ "$gen_count" -gt 0 ]]; then
333
+ mkdir -p "$GENERATED_SKILLS_DIR"
334
+ local i
335
+ for i in $(seq 0 $((gen_count - 1))); do
336
+ local gen_name gen_content
337
+ gen_name=$(echo "$result" | jq -r ".generated_skills[$i].name" 2>/dev/null)
338
+ gen_content=$(echo "$result" | jq -r ".generated_skills[$i].content" 2>/dev/null)
339
+ if [[ -n "$gen_name" && "$gen_name" != "null" && -n "$gen_content" && "$gen_content" != "null" ]]; then
340
+ # Only write if doesn't already exist (don't overwrite improved versions)
341
+ if [[ ! -f "$GENERATED_SKILLS_DIR/${gen_name}.md" ]]; then
342
+ printf '%b\n' "$gen_content" > "$GENERATED_SKILLS_DIR/${gen_name}.md"
343
+ info "Generated new skill: ${gen_name}"
344
+ fi
345
+ fi
346
+ done
347
+ fi
348
+
349
+ # Update INTELLIGENCE_ISSUE_TYPE from analysis
350
+ local analyzed_type
351
+ analyzed_type=$(echo "$result" | jq -r '.issue_type // empty' 2>/dev/null)
352
+ if [[ -n "$analyzed_type" ]]; then
353
+ export INTELLIGENCE_ISSUE_TYPE="$analyzed_type"
354
+ fi
355
+
356
+ # Update INTELLIGENCE_COMPLEXITY from analysis
357
+ local analyzed_complexity
358
+ analyzed_complexity=$(echo "$result" | jq -r '.complexity_assessment.score // empty' 2>/dev/null)
359
+ if [[ -n "$analyzed_complexity" ]]; then
360
+ export INTELLIGENCE_COMPLEXITY="$analyzed_complexity"
361
+ fi
362
+
363
+ return 0
364
+ }
365
+ ```
366
+
367
+ **Step 4: Run tests**
368
+
369
+ Run: `bash scripts/test-skill-injection.sh 2>&1 | tail -5`
370
+ Expected: ALL TESTS PASSED
371
+
372
+ **Step 5: Commit**
373
+
374
+ ```bash
375
+ git add scripts/lib/skill-registry.sh scripts/test-skill-injection.sh
376
+ git commit -m "feat(skills): add skill_analyze_issue LLM router"
377
+ ```
378
+
379
+ ---
380
+
381
+ ### Task 4: Add `skill_load_from_plan()` — Plan-Based Stage Loader
382
+
383
+ **Files:**
384
+ - Modify: `scripts/lib/skill-registry.sh` (append after `skill_analyze_issue`)
385
+ - Test: `scripts/test-skill-injection.sh`
386
+
387
+ **Step 1: Write the failing test**
388
+
389
+ Add Suite 12 to `scripts/test-skill-injection.sh`:
390
+
391
+ ```bash
392
+ echo ""
393
+ echo "═══ Suite 12: Plan-Based Skill Loading ═══"
394
+ echo ""
395
+
396
+ local _test_artifacts
397
+ _test_artifacts=$(mktemp -d)
398
+
399
+ # Write a mock skill-plan.json
400
+ cat > "$_test_artifacts/skill-plan.json" << 'PLAN_EOF'
401
+ {
402
+ "issue_type": "frontend",
403
+ "skill_plan": {
404
+ "plan": ["brainstorming", "frontend-design"],
405
+ "build": ["frontend-design"],
406
+ "review": ["two-stage-review"],
407
+ "deploy": []
408
+ },
409
+ "skill_rationale": {
410
+ "brainstorming": "Task decomposition for progress bar feature",
411
+ "frontend-design": "ARIA progressbar role and responsive CSS needed",
412
+ "two-stage-review": "Spec compliance check against plan.md"
413
+ },
414
+ "generated_skills": []
415
+ }
416
+ PLAN_EOF
417
+
418
+ echo " ── Loading skills from plan ──"
419
+
420
+ # Test: load plan stage skills
421
+ local plan_content
422
+ ARTIFACTS_DIR="$_test_artifacts" plan_content=$(skill_load_from_plan "plan" 2>/dev/null || true)
423
+ assert_contains "$plan_content" "brainstorming" "plan stage loads brainstorming skill"
424
+ assert_contains "$plan_content" "frontend-design" "plan stage loads frontend-design skill content"
425
+ assert_contains "$plan_content" "ARIA progressbar" "plan stage includes rationale"
426
+ assert_contains "$plan_content" "Task decomposition" "plan stage includes brainstorming rationale"
427
+
428
+ # Test: load build stage skills
429
+ local build_content
430
+ ARTIFACTS_DIR="$_test_artifacts" build_content=$(skill_load_from_plan "build" 2>/dev/null || true)
431
+ assert_contains "$build_content" "frontend-design" "build stage loads frontend-design"
432
+ assert_not_contains "$build_content" "brainstorming" "build stage does NOT load brainstorming"
433
+
434
+ # Test: empty stage returns empty
435
+ local deploy_content
436
+ ARTIFACTS_DIR="$_test_artifacts" deploy_content=$(skill_load_from_plan "deploy" 2>/dev/null || true)
437
+ assert_eq "" "$(echo "$deploy_content" | tr -d '[:space:]')" "empty stage returns empty"
438
+
439
+ # Test: missing skill-plan.json falls back to skill_select_adaptive
440
+ local _no_plan_dir
441
+ _no_plan_dir=$(mktemp -d)
442
+ local fallback_content
443
+ ARTIFACTS_DIR="$_no_plan_dir" INTELLIGENCE_ISSUE_TYPE="frontend" fallback_content=$(skill_load_from_plan "plan" 2>/dev/null || true)
444
+ assert_contains "$fallback_content" "brainstorming\|frontend\|Socratic" "fallback to adaptive when no plan"
445
+ rm -rf "$_no_plan_dir"
446
+
447
+ # Test: refinements are appended
448
+ mkdir -p "$SKILLS_DIR/generated/_refinements"
449
+ echo "REFINEMENT: Always check stat-bar CSS pattern reuse." > "$SKILLS_DIR/generated/_refinements/frontend-design.patch.md"
450
+ ARTIFACTS_DIR="$_test_artifacts" plan_content=$(skill_load_from_plan "plan" 2>/dev/null || true)
451
+ assert_contains "$plan_content" "REFINEMENT" "refinement patch appended to skill"
452
+ rm -f "$SKILLS_DIR/generated/_refinements/frontend-design.patch.md"
453
+
454
+ rm -rf "$_test_artifacts"
455
+ ```
456
+
457
+ **Step 2: Run test to verify it fails**
458
+
459
+ Run: `bash scripts/test-skill-injection.sh 2>&1 | grep -A2 "Suite 12"`
460
+ Expected: FAIL — `skill_load_from_plan: command not found`
461
+
462
+ **Step 3: Write the implementation**
463
+
464
+ Append to `scripts/lib/skill-registry.sh`:
465
+
466
+ ```bash
467
+ # skill_load_from_plan — Load skill content for a stage from skill-plan.json artifact.
468
+ # $1: stage (plan|design|build|review|compound_quality|pr|deploy|validate|monitor)
469
+ # Reads: $ARTIFACTS_DIR/skill-plan.json
470
+ # Returns: combined prompt text with rationale + skill content + refinements.
471
+ # Falls back to skill_select_adaptive() if skill-plan.json is missing.
472
+ skill_load_from_plan() {
473
+ local stage="${1:-plan}"
474
+ local plan_file="${ARTIFACTS_DIR}/skill-plan.json"
475
+
476
+ # Fallback if no plan file
477
+ if [[ ! -f "$plan_file" ]]; then
478
+ if type skill_select_adaptive >/dev/null 2>&1; then
479
+ local _fallback_files _fallback_content
480
+ _fallback_files=$(skill_select_adaptive "${INTELLIGENCE_ISSUE_TYPE:-backend}" "$stage" "${ISSUE_BODY:-}" "${INTELLIGENCE_COMPLEXITY:-5}" 2>/dev/null || true)
481
+ if [[ -n "$_fallback_files" ]]; then
482
+ while IFS= read -r _path; do
483
+ [[ -z "$_path" || ! -f "$_path" ]] && continue
484
+ cat "$_path" 2>/dev/null
485
+ done <<< "$_fallback_files"
486
+ fi
487
+ fi
488
+ return 0
489
+ fi
490
+
491
+ # Extract skill names for this stage
492
+ local skill_names
493
+ skill_names=$(jq -r ".skill_plan.${stage}[]? // empty" "$plan_file" 2>/dev/null)
494
+ [[ -z "$skill_names" ]] && return 0
495
+
496
+ local issue_type
497
+ issue_type=$(jq -r '.issue_type // "unknown"' "$plan_file" 2>/dev/null)
498
+
499
+ # Build rationale header
500
+ local rationale_header=""
501
+ rationale_header="### Why these skills were selected (AI-analyzed):
502
+ "
503
+ while IFS= read -r skill_name; do
504
+ [[ -z "$skill_name" ]] && continue
505
+ local rat
506
+ rat=$(jq -r ".skill_rationale[\"${skill_name}\"] // empty" "$plan_file" 2>/dev/null)
507
+ [[ -n "$rat" ]] && rationale_header="${rationale_header}- **${skill_name}**: ${rat}
508
+ "
509
+ done <<< "$skill_names"
510
+
511
+ # Output rationale header
512
+ echo "$rationale_header"
513
+
514
+ # Load each skill's content
515
+ while IFS= read -r skill_name; do
516
+ [[ -z "$skill_name" ]] && continue
517
+
518
+ local skill_path=""
519
+ # Check curated directory first
520
+ if [[ -f "${SKILLS_DIR}/${skill_name}.md" ]]; then
521
+ skill_path="${SKILLS_DIR}/${skill_name}.md"
522
+ # Then check generated directory
523
+ elif [[ -f "${GENERATED_SKILLS_DIR}/${skill_name}.md" ]]; then
524
+ skill_path="${GENERATED_SKILLS_DIR}/${skill_name}.md"
525
+ fi
526
+
527
+ if [[ -n "$skill_path" ]]; then
528
+ cat "$skill_path" 2>/dev/null
529
+ echo ""
530
+
531
+ # Append refinement if exists
532
+ local refinement_path="${REFINEMENTS_DIR}/${skill_name}.patch.md"
533
+ if [[ -f "$refinement_path" ]]; then
534
+ echo ""
535
+ cat "$refinement_path" 2>/dev/null
536
+ echo ""
537
+ fi
538
+ fi
539
+ done <<< "$skill_names"
540
+ }
541
+ ```
542
+
543
+ **Step 4: Run tests**
544
+
545
+ Run: `bash scripts/test-skill-injection.sh 2>&1 | tail -5`
546
+ Expected: ALL TESTS PASSED
547
+
548
+ **Step 5: Commit**
549
+
550
+ ```bash
551
+ git add scripts/lib/skill-registry.sh scripts/test-skill-injection.sh
552
+ git commit -m "feat(skills): add skill_load_from_plan for plan-based stage loading"
553
+ ```
554
+
555
+ ---
556
+
557
+ ### Task 5: Add `skill_analyze_outcome()` — Outcome Learning Loop
558
+
559
+ **Files:**
560
+ - Modify: `scripts/lib/skill-registry.sh` (append after `skill_load_from_plan`)
561
+ - Test: `scripts/test-skill-injection.sh`
562
+
563
+ **Step 1: Write the failing test**
564
+
565
+ Add Suite 13 to `scripts/test-skill-injection.sh`:
566
+
567
+ ```bash
568
+ echo ""
569
+ echo "═══ Suite 13: Outcome Learning Loop ═══"
570
+ echo ""
571
+
572
+ local _test_artifacts
573
+ _test_artifacts=$(mktemp -d)
574
+
575
+ # Write a mock skill-plan.json
576
+ cat > "$_test_artifacts/skill-plan.json" << 'PLAN_EOF'
577
+ {
578
+ "issue_type": "frontend",
579
+ "skill_plan": {
580
+ "plan": ["brainstorming", "frontend-design"],
581
+ "build": ["frontend-design"],
582
+ "review": ["two-stage-review"]
583
+ },
584
+ "skill_rationale": {
585
+ "frontend-design": "ARIA progressbar needed"
586
+ },
587
+ "generated_skills": []
588
+ }
589
+ PLAN_EOF
590
+
591
+ echo " ── Outcome JSON parsing ──"
592
+
593
+ # Test: parse a mock outcome response
594
+ local _mock_outcome='{"skill_effectiveness":{"frontend-design":{"verdict":"effective","evidence":"ARIA section in plan","learning":"stat-bar reuse hint followed"}},"refinements":[{"skill":"frontend-design","addition":"For dashboard features, mention existing CSS patterns"}],"generated_skill_verdict":{}}'
595
+ echo "$_mock_outcome" > "$_test_artifacts/skill-outcome.json"
596
+
597
+ # Verify outcome JSON is valid
598
+ assert_true "jq '.' '$_test_artifacts/skill-outcome.json' >/dev/null 2>&1" "outcome JSON is valid"
599
+
600
+ # Verify verdict extraction
601
+ local _verdict
602
+ _verdict=$(jq -r '.skill_effectiveness["frontend-design"].verdict' "$_test_artifacts/skill-outcome.json" 2>/dev/null)
603
+ assert_eq "effective" "$_verdict" "verdict extracted correctly"
604
+
605
+ # Verify refinement extraction
606
+ local _refinement_skill
607
+ _refinement_skill=$(jq -r '.refinements[0].skill' "$_test_artifacts/skill-outcome.json" 2>/dev/null)
608
+ assert_eq "frontend-design" "$_refinement_skill" "refinement skill extracted"
609
+
610
+ echo ""
611
+ echo " ── Refinement file writing ──"
612
+
613
+ # Test: skill_apply_refinements writes patch files
614
+ local _ref_dir="${SKILLS_DIR}/generated/_refinements"
615
+ mkdir -p "$_ref_dir"
616
+ skill_apply_refinements "$_test_artifacts/skill-outcome.json" 2>/dev/null || true
617
+ assert_true "[[ -f '$_ref_dir/frontend-design.patch.md' ]]" "refinement patch file created"
618
+ local _ref_content
619
+ _ref_content=$(cat "$_ref_dir/frontend-design.patch.md" 2>/dev/null || true)
620
+ assert_contains "$_ref_content" "dashboard" "refinement content written"
621
+ rm -f "$_ref_dir/frontend-design.patch.md"
622
+
623
+ echo ""
624
+ echo " ── Generated skill lifecycle ──"
625
+
626
+ # Test: prune verdict deletes generated skill
627
+ mkdir -p "${SKILLS_DIR}/generated"
628
+ echo "## Temp Skill" > "${SKILLS_DIR}/generated/temp-skill.md"
629
+ local _prune_outcome='{"skill_effectiveness":{},"refinements":[],"generated_skill_verdict":{"temp-skill":"prune"}}'
630
+ echo "$_prune_outcome" > "$_test_artifacts/skill-outcome.json"
631
+ skill_apply_lifecycle_verdicts "$_test_artifacts/skill-outcome.json" 2>/dev/null || true
632
+ assert_true "[[ ! -f '${SKILLS_DIR}/generated/temp-skill.md' ]]" "pruned skill deleted"
633
+
634
+ rm -rf "$_test_artifacts"
635
+ ```
636
+
637
+ **Step 2: Run test to verify it fails**
638
+
639
+ Run: `bash scripts/test-skill-injection.sh 2>&1 | grep -A2 "Suite 13"`
640
+ Expected: FAIL — functions not found
641
+
642
+ **Step 3: Write the implementation**
643
+
644
+ Append to `scripts/lib/skill-registry.sh`:
645
+
646
+ ```bash
647
+ # skill_analyze_outcome — LLM-powered outcome analysis and learning.
648
+ # $1: pipeline_result ("success" or "failure")
649
+ # $2: artifacts_dir
650
+ # $3: failed_stage (optional — only for failures)
651
+ # $4: error_context (optional — last N lines of error output)
652
+ # Reads: $artifacts_dir/skill-plan.json, review artifacts
653
+ # Writes: $artifacts_dir/skill-outcome.json, refinement patches, lifecycle verdicts
654
+ # Returns: 0 on success, 1 on failure (falls back to boolean recording)
655
+ skill_analyze_outcome() {
656
+ local pipeline_result="${1:-success}"
657
+ local artifacts_dir="${2:-${ARTIFACTS_DIR:-.claude/pipeline-artifacts}}"
658
+ local failed_stage="${3:-}"
659
+ local error_context="${4:-}"
660
+
661
+ local plan_file="$artifacts_dir/skill-plan.json"
662
+ [[ ! -f "$plan_file" ]] && return 1
663
+
664
+ if ! type _intelligence_call_claude >/dev/null 2>&1; then
665
+ return 1
666
+ fi
667
+
668
+ # Gather context for analysis
669
+ local skill_plan
670
+ skill_plan=$(cat "$plan_file" 2>/dev/null)
671
+
672
+ local review_feedback=""
673
+ [[ -f "$artifacts_dir/review-results.log" ]] && review_feedback=$(tail -50 "$artifacts_dir/review-results.log" 2>/dev/null || true)
674
+
675
+ local prompt
676
+ prompt="You are a pipeline learning system. Analyze the outcome of this pipeline run and provide skill effectiveness feedback.
677
+
678
+ ## Skill Plan Used
679
+ ${skill_plan}
680
+
681
+ ## Pipeline Result: ${pipeline_result}
682
+ ${failed_stage:+Failed at stage: ${failed_stage}}
683
+ ${error_context:+Error context:
684
+ ${error_context}}
685
+ ${review_feedback:+## Review Feedback
686
+ ${review_feedback}}
687
+
688
+ ## Instructions
689
+ 1. For each skill in the plan, assess whether it was effective, partially effective, or ineffective.
690
+ 2. Provide evidence for each verdict (what in the output shows the skill helped or didn't help).
691
+ 3. Extract a one-sentence learning that would improve future use of this skill.
692
+ 4. If any skill content could be improved, provide a specific refinement (one sentence to append).
693
+ 5. For any generated skills, provide a lifecycle verdict: keep, keep_and_refine, or prune.
694
+
695
+ ## Response Format (JSON only, no markdown)
696
+ {
697
+ \"skill_effectiveness\": {
698
+ \"skill-name\": {
699
+ \"verdict\": \"effective|partially_effective|ineffective\",
700
+ \"evidence\": \"What in the output shows this\",
701
+ \"learning\": \"One-sentence takeaway for future runs\"
702
+ }
703
+ },
704
+ \"refinements\": [
705
+ {
706
+ \"skill\": \"skill-name\",
707
+ \"addition\": \"One sentence to append to this skill for future use\"
708
+ }
709
+ ],
710
+ \"generated_skill_verdict\": {
711
+ \"generated-skill-name\": \"keep|keep_and_refine|prune\"
712
+ }
713
+ }"
714
+
715
+ local cache_key="skill_outcome_$(echo "${skill_plan}${pipeline_result}" | md5sum 2>/dev/null | cut -c1-16 || echo "${RANDOM}")"
716
+ local result
717
+ if ! result=$(_intelligence_call_claude "$prompt" "$cache_key" 3600 "haiku"); then
718
+ return 1
719
+ fi
720
+
721
+ # Validate response
722
+ local valid
723
+ valid=$(echo "$result" | jq 'has("skill_effectiveness")' 2>/dev/null || echo "false")
724
+ if [[ "$valid" != "true" ]]; then
725
+ return 1
726
+ fi
727
+
728
+ # Write outcome artifact
729
+ echo "$result" | jq '.' > "$artifacts_dir/skill-outcome.json" 2>/dev/null || true
730
+
731
+ # Apply refinements
732
+ skill_apply_refinements "$artifacts_dir/skill-outcome.json" 2>/dev/null || true
733
+
734
+ # Apply lifecycle verdicts for generated skills
735
+ skill_apply_lifecycle_verdicts "$artifacts_dir/skill-outcome.json" 2>/dev/null || true
736
+
737
+ # Record enriched outcomes to skill memory
738
+ local issue_type
739
+ issue_type=$(jq -r '.issue_type // "backend"' "$plan_file" 2>/dev/null)
740
+
741
+ echo "$result" | jq -r '.skill_effectiveness | to_entries[] | "\(.key) \(.value.verdict)"' 2>/dev/null | while read -r skill_name verdict; do
742
+ [[ -z "$skill_name" ]] && continue
743
+ local outcome="success"
744
+ [[ "$verdict" == "ineffective" ]] && outcome="failure"
745
+ [[ "$verdict" == "partially_effective" ]] && outcome="retry"
746
+
747
+ # Record to all stages this skill was used in
748
+ jq -r ".skill_plan | to_entries[] | select(.value | index(\"$skill_name\")) | .key" "$plan_file" 2>/dev/null | while read -r stage; do
749
+ skill_memory_record "$issue_type" "$stage" "$skill_name" "$outcome" "1" 2>/dev/null || true
750
+ done
751
+ done
752
+
753
+ return 0
754
+ }
755
+
756
+ # skill_apply_refinements — Write refinement patches from outcome analysis.
757
+ # $1: path to skill-outcome.json
758
+ skill_apply_refinements() {
759
+ local outcome_file="${1:-}"
760
+ [[ ! -f "$outcome_file" ]] && return 1
761
+
762
+ mkdir -p "$REFINEMENTS_DIR"
763
+
764
+ local ref_count
765
+ ref_count=$(jq '.refinements | length' "$outcome_file" 2>/dev/null || echo "0")
766
+ [[ "$ref_count" -eq 0 ]] && return 0
767
+
768
+ local i
769
+ for i in $(seq 0 $((ref_count - 1))); do
770
+ local skill_name addition
771
+ skill_name=$(jq -r ".refinements[$i].skill" "$outcome_file" 2>/dev/null)
772
+ addition=$(jq -r ".refinements[$i].addition" "$outcome_file" 2>/dev/null)
773
+ if [[ -n "$skill_name" && "$skill_name" != "null" && -n "$addition" && "$addition" != "null" ]]; then
774
+ local patch_file="$REFINEMENTS_DIR/${skill_name}.patch.md"
775
+ # Append (don't overwrite) — accumulate learnings
776
+ echo "" >> "$patch_file"
777
+ echo "### Learned ($(date -u +%Y-%m-%d))" >> "$patch_file"
778
+ echo "$addition" >> "$patch_file"
779
+ fi
780
+ done
781
+ }
782
+
783
+ # skill_apply_lifecycle_verdicts — Apply keep/prune verdicts for generated skills.
784
+ # $1: path to skill-outcome.json
785
+ skill_apply_lifecycle_verdicts() {
786
+ local outcome_file="${1:-}"
787
+ [[ ! -f "$outcome_file" ]] && return 1
788
+
789
+ local verdicts
790
+ verdicts=$(jq -r '.generated_skill_verdict // {} | to_entries[] | "\(.key) \(.value)"' "$outcome_file" 2>/dev/null)
791
+ [[ -z "$verdicts" ]] && return 0
792
+
793
+ while read -r skill_name verdict; do
794
+ [[ -z "$skill_name" ]] && continue
795
+ local gen_path="$GENERATED_SKILLS_DIR/${skill_name}.md"
796
+
797
+ case "$verdict" in
798
+ prune)
799
+ if [[ -f "$gen_path" ]]; then
800
+ rm -f "$gen_path"
801
+ info "Pruned generated skill: ${skill_name}"
802
+ fi
803
+ ;;
804
+ keep)
805
+ # No action needed — skill stays
806
+ ;;
807
+ keep_and_refine)
808
+ # Refinement handled by skill_apply_refinements
809
+ ;;
810
+ esac
811
+ done <<< "$verdicts"
812
+ }
813
+ ```
814
+
815
+ **Step 4: Run tests**
816
+
817
+ Run: `bash scripts/test-skill-injection.sh 2>&1 | tail -5`
818
+ Expected: ALL TESTS PASSED
819
+
820
+ **Step 5: Commit**
821
+
822
+ ```bash
823
+ git add scripts/lib/skill-registry.sh scripts/test-skill-injection.sh
824
+ git commit -m "feat(skills): add outcome learning loop with refinements and lifecycle"
825
+ ```
826
+
827
+ ---
828
+
829
+ ### Task 6: Integrate into `stage_intake()` in pipeline-stages.sh
830
+
831
+ **Files:**
832
+ - Modify: `scripts/lib/pipeline-stages.sh` (lines 264-296, add after line 288)
833
+
834
+ **Step 1: Write the integration code**
835
+
836
+ After the existing label grep block (line 288) and before the `log_stage` call (line 290), add:
837
+
838
+ ```bash
839
+ # 8. AI-powered skill analysis (replaces static classification when available)
840
+ if type skill_analyze_issue >/dev/null 2>&1; then
841
+ local _intel_json=""
842
+ [[ -f "$ARTIFACTS_DIR/intelligence-analysis.json" ]] && _intel_json=$(cat "$ARTIFACTS_DIR/intelligence-analysis.json" 2>/dev/null || true)
843
+
844
+ if skill_analyze_issue "$GOAL" "${ISSUE_BODY:-}" "${ISSUE_LABELS:-}" "$ARTIFACTS_DIR" "$_intel_json" 2>/dev/null; then
845
+ info "Skill analysis: AI-powered skill plan written to skill-plan.json"
846
+ # INTELLIGENCE_ISSUE_TYPE and INTELLIGENCE_COMPLEXITY are updated by skill_analyze_issue
847
+ else
848
+ info "Skill analysis: LLM unavailable — using label-based classification"
849
+ fi
850
+ fi
851
+ ```
852
+
853
+ **Step 2: Verify the intake flow**
854
+
855
+ The label grep (lines 264-288) still runs first as a fallback. If `skill_analyze_issue` succeeds, it overwrites `INTELLIGENCE_ISSUE_TYPE` with the LLM's classification. If it fails, the grep-based value stands.
856
+
857
+ **Step 3: Commit**
858
+
859
+ ```bash
860
+ git add scripts/lib/pipeline-stages.sh
861
+ git commit -m "feat(intake): integrate AI-powered skill analysis into intake stage"
862
+ ```
863
+
864
+ ---
865
+
866
+ ### Task 7: Replace `skill_select_adaptive()` calls with `skill_load_from_plan()` in all stages
867
+
868
+ **Files:**
869
+ - Modify: `scripts/lib/pipeline-stages.sh` (plan ~439-469, build ~1309-1326, review ~1762-1789, and similar blocks in design, compound_quality, pr, deploy, validate, monitor)
870
+
871
+ **Step 1: Replace plan stage injection (lines 439-469)**
872
+
873
+ Replace the entire `skill_select_adaptive` / `skill_load_prompts` block with:
874
+
875
+ ```bash
876
+ # Inject skill prompts — prefer AI-powered plan, fallback to adaptive
877
+ local _skill_prompts=""
878
+ if type skill_load_from_plan >/dev/null 2>&1; then
879
+ _skill_prompts=$(skill_load_from_plan "plan" 2>/dev/null || true)
880
+ elif type skill_select_adaptive >/dev/null 2>&1; then
881
+ local _skill_files
882
+ _skill_files=$(skill_select_adaptive "${INTELLIGENCE_ISSUE_TYPE:-backend}" "plan" "${ISSUE_BODY:-}" "${INTELLIGENCE_COMPLEXITY:-5}" 2>/dev/null || true)
883
+ if [[ -n "$_skill_files" ]]; then
884
+ _skill_prompts=$(while IFS= read -r _path; do
885
+ [[ -z "$_path" || ! -f "$_path" ]] && continue
886
+ cat "$_path" 2>/dev/null
887
+ done <<< "$_skill_files")
888
+ fi
889
+ elif type skill_load_prompts >/dev/null 2>&1; then
890
+ _skill_prompts=$(skill_load_prompts "${INTELLIGENCE_ISSUE_TYPE:-backend}" "plan" 2>/dev/null || true)
891
+ fi
892
+ if [[ -n "$_skill_prompts" ]]; then
893
+ _skill_prompts=$(prune_context_section "skills" "$_skill_prompts" 8000)
894
+ plan_prompt="${plan_prompt}
895
+ ## Skill Guidance (${INTELLIGENCE_ISSUE_TYPE:-backend} issue, AI-selected)
896
+ ${_skill_prompts}
897
+ "
898
+ fi
899
+ ```
900
+
901
+ **Step 2: Apply same pattern to build, design, review, and remaining stages**
902
+
903
+ Each stage's skill injection block gets the same three-level fallback:
904
+ 1. `skill_load_from_plan "$stage"` (AI-powered)
905
+ 2. `skill_select_adaptive` (adaptive rules)
906
+ 3. `skill_load_prompts` (static registry)
907
+
908
+ The pattern is identical — only the stage name and variable names change.
909
+
910
+ **Step 3: Run existing tests**
911
+
912
+ Run: `bash scripts/test-skill-injection.sh 2>&1 | tail -5`
913
+ Expected: ALL TESTS PASSED (existing tests use static functions which still work)
914
+
915
+ **Step 4: Commit**
916
+
917
+ ```bash
918
+ git add scripts/lib/pipeline-stages.sh
919
+ git commit -m "feat(stages): replace static skill injection with plan-based loading"
920
+ ```
921
+
922
+ ---
923
+
924
+ ### Task 8: Integrate `skill_analyze_outcome()` into pipeline completion
925
+
926
+ **Files:**
927
+ - Modify: `scripts/sw-pipeline.sh` (around lines 2494-2555, the completion handler)
928
+
929
+ **Step 1: Add outcome analysis after the success/failure emit_event blocks**
930
+
931
+ After line 2543 (end of success block) and before line 2545 (start of failure block), add a shared outcome analysis call. Best location: after the entire if/else block (around line 2560):
932
+
933
+ ```bash
934
+ # AI-powered outcome learning
935
+ if type skill_analyze_outcome >/dev/null 2>&1; then
936
+ local _failed_stage=""
937
+ local _error_ctx=""
938
+ if [[ "$exit_code" -ne 0 ]]; then
939
+ _failed_stage="${CURRENT_STAGE_ID:-unknown}"
940
+ _error_ctx=$(tail -30 "$ARTIFACTS_DIR/errors-collected.json" 2>/dev/null || true)
941
+ fi
942
+ local _outcome_result="success"
943
+ [[ "$exit_code" -ne 0 ]] && _outcome_result="failure"
944
+
945
+ if skill_analyze_outcome "$_outcome_result" "$ARTIFACTS_DIR" "$_failed_stage" "$_error_ctx" 2>/dev/null; then
946
+ info "Skill outcome analysis complete — learnings recorded"
947
+ fi
948
+ fi
949
+ ```
950
+
951
+ **Step 2: Commit**
952
+
953
+ ```bash
954
+ git add scripts/sw-pipeline.sh
955
+ git commit -m "feat(pipeline): integrate outcome learning at pipeline completion"
956
+ ```
957
+
958
+ ---
959
+
960
+ ### Task 9: Upgrade `skill_memory_record()` to store rich verdicts
961
+
962
+ **Files:**
963
+ - Modify: `scripts/lib/skill-memory.sh` (lines 30-91)
964
+
965
+ **Step 1: Extend the JSON record structure**
966
+
967
+ Update `skill_memory_record()` to accept optional verdict, evidence, and learning fields:
968
+
969
+ ```bash
970
+ # Extended signature:
971
+ # $6: verdict (optional — "effective"|"partially_effective"|"ineffective")
972
+ # $7: evidence (optional — why this verdict)
973
+ # $8: learning (optional — one-sentence takeaway)
974
+ ```
975
+
976
+ Update the record JSON construction (line 46-47) to include the new fields:
977
+
978
+ ```bash
979
+ local verdict="${6:-}"
980
+ local evidence="${7:-}"
981
+ local learning="${8:-}"
982
+
983
+ local record
984
+ record=$(jq -n \
985
+ --arg it "$issue_type" --arg st "$stage" --arg sk "$skills_used" \
986
+ --arg oc "$outcome" --argjson at "$attempt" --arg ts "$timestamp" \
987
+ --arg vd "$verdict" --arg ev "$evidence" --arg lr "$learning" \
988
+ '{issue_type:$it, stage:$st, skills:$sk, outcome:$oc, attempt:$at, timestamp:$ts, verdict:$vd, evidence:$ev, learning:$lr}')
989
+ ```
990
+
991
+ This is backward compatible — existing callers pass 5 args, new fields default to empty strings.
992
+
993
+ **Step 2: Run tests**
994
+
995
+ Run: `bash scripts/test-skill-injection.sh 2>&1 | tail -5`
996
+ Expected: ALL TESTS PASSED (existing tests pass 5 args, new empty fields are fine)
997
+
998
+ **Step 3: Commit**
999
+
1000
+ ```bash
1001
+ git add scripts/lib/skill-memory.sh
1002
+ git commit -m "feat(memory): extend skill_memory_record with verdict/evidence/learning"
1003
+ ```
1004
+
1005
+ ---
1006
+
1007
+ ### Task 10: Final Integration Test
1008
+
1009
+ **Files:**
1010
+ - Modify: `scripts/test-skill-injection.sh` (add Suite 14)
1011
+
1012
+ **Step 1: Write integration tests**
1013
+
1014
+ ```bash
1015
+ echo ""
1016
+ echo "═══ Suite 14: Full AI Integration ═══"
1017
+ echo ""
1018
+
1019
+ echo " ── End-to-end skill flow ──"
1020
+
1021
+ # Test: catalog → plan → load → outcome cycle
1022
+ local _e2e_dir
1023
+ _e2e_dir=$(mktemp -d)
1024
+
1025
+ # 1. Build catalog (should include all 17 curated skills)
1026
+ local _catalog
1027
+ _catalog=$(skill_build_catalog 2>/dev/null || true)
1028
+ local _catalog_lines
1029
+ _catalog_lines=$(echo "$_catalog" | grep -c '^-' 2>/dev/null || echo "0")
1030
+ assert_true "[[ $_catalog_lines -ge 17 ]]" "catalog has at least 17 skills (got $_catalog_lines)"
1031
+
1032
+ # 2. Write a skill plan (simulating what skill_analyze_issue would produce)
1033
+ cat > "$_e2e_dir/skill-plan.json" << 'E2E_PLAN'
1034
+ {
1035
+ "issue_type": "api",
1036
+ "confidence": 0.88,
1037
+ "skill_plan": {
1038
+ "plan": ["brainstorming", "api-design"],
1039
+ "build": ["api-design"],
1040
+ "review": ["two-stage-review", "security-audit"]
1041
+ },
1042
+ "skill_rationale": {
1043
+ "api-design": "REST endpoint versioning needed",
1044
+ "brainstorming": "Multiple valid API approaches",
1045
+ "two-stage-review": "Spec compliance for API contract",
1046
+ "security-audit": "Auth endpoint requires security review"
1047
+ },
1048
+ "generated_skills": []
1049
+ }
1050
+ E2E_PLAN
1051
+
1052
+ # 3. Load from plan for each stage
1053
+ local _plan_out _build_out _review_out
1054
+ ARTIFACTS_DIR="$_e2e_dir" _plan_out=$(skill_load_from_plan "plan" 2>/dev/null || true)
1055
+ ARTIFACTS_DIR="$_e2e_dir" _build_out=$(skill_load_from_plan "build" 2>/dev/null || true)
1056
+ ARTIFACTS_DIR="$_e2e_dir" _review_out=$(skill_load_from_plan "review" 2>/dev/null || true)
1057
+
1058
+ assert_contains "$_plan_out" "api-design" "plan loads api-design skill"
1059
+ assert_contains "$_plan_out" "REST endpoint" "plan includes rationale"
1060
+ assert_contains "$_build_out" "api-design" "build loads api-design"
1061
+ assert_not_contains "$_build_out" "brainstorming" "build doesn't load plan-only skills"
1062
+ assert_contains "$_review_out" "two-stage-review" "review loads two-stage-review"
1063
+ assert_contains "$_review_out" "security-audit" "review loads security-audit"
1064
+
1065
+ # 4. Test fallback chain (no plan → adaptive → static)
1066
+ local _no_plan_dir
1067
+ _no_plan_dir=$(mktemp -d)
1068
+ ARTIFACTS_DIR="$_no_plan_dir" INTELLIGENCE_ISSUE_TYPE="api" _plan_out=$(skill_load_from_plan "plan" 2>/dev/null || true)
1069
+ assert_true "[[ -n '$_plan_out' ]]" "fallback produces output when no plan exists"
1070
+
1071
+ # 5. Verify generated skill directory structure
1072
+ assert_true "[[ -d '$SKILLS_DIR/generated' ]]" "generated skills directory exists"
1073
+ assert_true "[[ -d '$SKILLS_DIR/generated/_refinements' ]]" "refinements directory exists"
1074
+
1075
+ rm -rf "$_e2e_dir" "$_no_plan_dir"
1076
+ ```
1077
+
1078
+ **Step 2: Run the full suite**
1079
+
1080
+ Run: `bash scripts/test-skill-injection.sh 2>&1 | tail -10`
1081
+ Expected: ALL TESTS PASSED (count should be ~220+)
1082
+
1083
+ **Step 3: Commit**
1084
+
1085
+ ```bash
1086
+ git add scripts/test-skill-injection.sh
1087
+ git commit -m "test(skills): add AI-powered skill injection integration tests"
1088
+ ```
1089
+
1090
+ ---
1091
+
1092
+ ## Execution Summary
1093
+
1094
+ | Task | What | Files | Depends On |
1095
+ |---|---|---|---|
1096
+ | 1 | Directory structure | `scripts/skills/generated/` | — |
1097
+ | 2 | `skill_build_catalog()` | `skill-registry.sh` | 1 |
1098
+ | 3 | `skill_analyze_issue()` | `skill-registry.sh` | 2 |
1099
+ | 4 | `skill_load_from_plan()` | `skill-registry.sh` | 2 |
1100
+ | 5 | `skill_analyze_outcome()` | `skill-registry.sh` | 2 |
1101
+ | 6 | Intake integration | `pipeline-stages.sh` | 3 |
1102
+ | 7 | Stage integration | `pipeline-stages.sh` | 4 |
1103
+ | 8 | Completion integration | `sw-pipeline.sh` | 5 |
1104
+ | 9 | Rich memory records | `skill-memory.sh` | 5 |
1105
+ | 10 | Integration tests | `test-skill-injection.sh` | all |
1106
+
1107
+ **Parallelizable:** Tasks 3, 4, 5 are independent (all append to skill-registry.sh but different functions). Tasks 6, 7, 8 are independent (different files). Task 9 is independent.
1108
+
1109
+ **Critical path:** 1 → 2 → (3 + 4 + 5) → (6 + 7 + 8 + 9) → 10