@girardmedia/bootspring 1.2.0 → 2.0.3

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 (253) hide show
  1. package/README.md +107 -14
  2. package/bin/bootspring.js +166 -27
  3. package/cli/agent.js +189 -17
  4. package/cli/analyze.js +499 -0
  5. package/cli/audit.js +557 -0
  6. package/cli/auth.js +495 -38
  7. package/cli/billing.js +302 -0
  8. package/cli/build.js +695 -0
  9. package/cli/business.js +109 -26
  10. package/cli/checkpoint-utils.js +168 -0
  11. package/cli/checkpoint.js +639 -0
  12. package/cli/cloud-sync.js +447 -0
  13. package/cli/content.js +198 -0
  14. package/cli/context.js +1 -1
  15. package/cli/deploy.js +543 -0
  16. package/cli/fundraise.js +112 -50
  17. package/cli/github-cmd.js +435 -0
  18. package/cli/health.js +477 -0
  19. package/cli/init.js +84 -13
  20. package/cli/legal.js +107 -95
  21. package/cli/log.js +2 -2
  22. package/cli/loop.js +976 -73
  23. package/cli/manager.js +711 -0
  24. package/cli/metrics.js +480 -0
  25. package/cli/monitor.js +812 -0
  26. package/cli/onboard.js +521 -0
  27. package/cli/orchestrator.js +12 -24
  28. package/cli/prd.js +594 -0
  29. package/cli/preseed-start.js +1483 -0
  30. package/cli/preseed.js +2302 -0
  31. package/cli/project.js +436 -0
  32. package/cli/quality.js +233 -0
  33. package/cli/security.js +913 -0
  34. package/cli/seed.js +1441 -5
  35. package/cli/skill.js +273 -211
  36. package/cli/suggest.js +989 -0
  37. package/cli/switch.js +453 -0
  38. package/cli/visualize.js +527 -0
  39. package/cli/watch.js +769 -0
  40. package/cli/workspace.js +607 -0
  41. package/core/analyze-workflow.js +1134 -0
  42. package/core/api-client.js +535 -22
  43. package/core/audit-workflow.js +1350 -0
  44. package/core/build-orchestrator.js +480 -0
  45. package/core/build-state.js +577 -0
  46. package/core/checkpoint-engine.js +408 -0
  47. package/core/config.js +1109 -26
  48. package/core/context-loader.js +21 -1
  49. package/core/deploy-workflow.js +836 -0
  50. package/core/entitlements.js +93 -22
  51. package/core/github-sync.js +610 -0
  52. package/core/index.js +8 -1
  53. package/core/ingest.js +1111 -0
  54. package/core/metrics-engine.js +768 -0
  55. package/core/onboard-workflow.js +1007 -0
  56. package/core/preseed-workflow.js +934 -0
  57. package/core/preseed.js +1617 -0
  58. package/core/project-context.js +325 -0
  59. package/core/project-state.js +694 -0
  60. package/core/r2-sync.js +583 -0
  61. package/core/scaffold.js +525 -7
  62. package/core/session.js +258 -0
  63. package/core/task-extractor.js +758 -0
  64. package/core/telemetry.js +28 -6
  65. package/core/tier-enforcement.js +737 -0
  66. package/core/utils.js +38 -14
  67. package/generators/questionnaire.js +15 -12
  68. package/generators/sections/ai.js +7 -7
  69. package/generators/sections/content.js +300 -0
  70. package/generators/sections/index.js +3 -0
  71. package/generators/sections/plugins.js +7 -6
  72. package/generators/templates/build-planning.template.js +596 -0
  73. package/generators/templates/content.template.js +819 -0
  74. package/generators/templates/index.js +2 -1
  75. package/hooks/git-autopilot.js +1250 -0
  76. package/hooks/index.js +9 -0
  77. package/intelligence/agent-collab.js +2057 -0
  78. package/intelligence/auto-suggest.js +634 -0
  79. package/intelligence/content-gen.js +1589 -0
  80. package/intelligence/cross-project.js +1647 -0
  81. package/intelligence/index.js +184 -0
  82. package/intelligence/learning/insights.json +517 -7
  83. package/intelligence/learning/pattern-learner.js +1008 -14
  84. package/intelligence/memory/decision-tracker.js +1431 -31
  85. package/intelligence/memory/decisions.jsonl +0 -0
  86. package/intelligence/orchestrator.js +2896 -1
  87. package/intelligence/prd.js +92 -1
  88. package/intelligence/recommendation-weights.json +14 -2
  89. package/intelligence/recommendations.js +463 -9
  90. package/intelligence/workflow-composer.js +1451 -0
  91. package/marketplace/index.d.ts +324 -0
  92. package/marketplace/index.js +1921 -0
  93. package/mcp/contracts/mcp-contract.v1.json +342 -4
  94. package/mcp/registry.js +680 -3
  95. package/mcp/response-formatter.js +23 -0
  96. package/mcp/tools/assist-tool.js +78 -4
  97. package/mcp/tools/autopilot-tool.js +408 -0
  98. package/mcp/tools/content-tool.js +571 -0
  99. package/mcp/tools/dashboard-tool.js +251 -5
  100. package/mcp/tools/mvp-tool.js +344 -0
  101. package/mcp/tools/plugin-tool.js +23 -1
  102. package/mcp/tools/prd-tool.js +579 -0
  103. package/mcp/tools/seed-tool.js +447 -0
  104. package/mcp/tools/skill-tool.js +43 -14
  105. package/mcp/tools/suggest-tool.js +147 -0
  106. package/package.json +15 -6
  107. package/agents/README.md +0 -93
  108. package/agents/ai-integration-expert/context.md +0 -386
  109. package/agents/api-expert/context.md +0 -416
  110. package/agents/architecture-expert/context.md +0 -454
  111. package/agents/auth-expert/context.md +0 -399
  112. package/agents/backend-expert/context.md +0 -483
  113. package/agents/business-strategy-expert/context.md +0 -180
  114. package/agents/code-review-expert/context.md +0 -365
  115. package/agents/competitive-analysis-expert/context.md +0 -239
  116. package/agents/data-modeling-expert/context.md +0 -352
  117. package/agents/database-expert/context.md +0 -250
  118. package/agents/devops-expert/context.md +0 -446
  119. package/agents/email-expert/context.md +0 -379
  120. package/agents/financial-expert/context.md +0 -213
  121. package/agents/frontend-expert/context.md +0 -364
  122. package/agents/fundraising-expert/context.md +0 -257
  123. package/agents/growth-expert/context.md +0 -249
  124. package/agents/index.js +0 -140
  125. package/agents/investor-relations-expert/context.md +0 -266
  126. package/agents/legal-expert/context.md +0 -284
  127. package/agents/marketing-expert/context.md +0 -236
  128. package/agents/monitoring-expert/context.md +0 -362
  129. package/agents/operations-expert/context.md +0 -279
  130. package/agents/partnerships-expert/context.md +0 -286
  131. package/agents/payment-expert/context.md +0 -340
  132. package/agents/performance-expert/context.md +0 -377
  133. package/agents/private-equity-expert/context.md +0 -246
  134. package/agents/railway-expert/context.md +0 -284
  135. package/agents/research-expert/context.md +0 -245
  136. package/agents/sales-expert/context.md +0 -241
  137. package/agents/security-expert/context.md +0 -343
  138. package/agents/testing-expert/context.md +0 -414
  139. package/agents/ui-ux-expert/context.md +0 -448
  140. package/agents/vercel-expert/context.md +0 -426
  141. package/skills/index.js +0 -787
  142. package/skills/patterns/README.md +0 -163
  143. package/skills/patterns/ai/agents.md +0 -281
  144. package/skills/patterns/ai/claude.md +0 -138
  145. package/skills/patterns/ai/embeddings.md +0 -150
  146. package/skills/patterns/ai/rag.md +0 -266
  147. package/skills/patterns/ai/streaming.md +0 -170
  148. package/skills/patterns/ai/structured-output.md +0 -162
  149. package/skills/patterns/ai/tools.md +0 -154
  150. package/skills/patterns/analytics/tracking.md +0 -220
  151. package/skills/patterns/api/errors.md +0 -296
  152. package/skills/patterns/api/graphql.md +0 -440
  153. package/skills/patterns/api/middleware.md +0 -279
  154. package/skills/patterns/api/openapi.md +0 -285
  155. package/skills/patterns/api/rate-limiting.md +0 -231
  156. package/skills/patterns/api/route-handler.md +0 -217
  157. package/skills/patterns/api/server-action.md +0 -249
  158. package/skills/patterns/api/versioning.md +0 -443
  159. package/skills/patterns/api/webhooks.md +0 -247
  160. package/skills/patterns/auth/clerk.md +0 -132
  161. package/skills/patterns/auth/mfa.md +0 -313
  162. package/skills/patterns/auth/nextauth.md +0 -140
  163. package/skills/patterns/auth/oauth.md +0 -237
  164. package/skills/patterns/auth/rbac.md +0 -152
  165. package/skills/patterns/auth/session-management.md +0 -367
  166. package/skills/patterns/auth/session.md +0 -120
  167. package/skills/patterns/database/audit.md +0 -177
  168. package/skills/patterns/database/migrations.md +0 -177
  169. package/skills/patterns/database/pagination.md +0 -230
  170. package/skills/patterns/database/pooling.md +0 -357
  171. package/skills/patterns/database/prisma.md +0 -180
  172. package/skills/patterns/database/relations.md +0 -187
  173. package/skills/patterns/database/seeding.md +0 -246
  174. package/skills/patterns/database/soft-delete.md +0 -153
  175. package/skills/patterns/database/transactions.md +0 -162
  176. package/skills/patterns/deployment/ci-cd.md +0 -231
  177. package/skills/patterns/deployment/docker.md +0 -188
  178. package/skills/patterns/deployment/monitoring.md +0 -387
  179. package/skills/patterns/deployment/vercel.md +0 -160
  180. package/skills/patterns/email/resend.md +0 -143
  181. package/skills/patterns/email/templates.md +0 -245
  182. package/skills/patterns/email/transactional.md +0 -503
  183. package/skills/patterns/email/verification.md +0 -176
  184. package/skills/patterns/files/download.md +0 -243
  185. package/skills/patterns/files/upload.md +0 -239
  186. package/skills/patterns/i18n/nextintl.md +0 -188
  187. package/skills/patterns/logging/structured.md +0 -292
  188. package/skills/patterns/notifications/email-queue.md +0 -248
  189. package/skills/patterns/notifications/push.md +0 -279
  190. package/skills/patterns/payments/checkout.md +0 -303
  191. package/skills/patterns/payments/invoices.md +0 -287
  192. package/skills/patterns/payments/portal.md +0 -245
  193. package/skills/patterns/payments/stripe.md +0 -272
  194. package/skills/patterns/payments/subscriptions.md +0 -300
  195. package/skills/patterns/payments/usage.md +0 -279
  196. package/skills/patterns/performance/caching.md +0 -276
  197. package/skills/patterns/performance/code-splitting.md +0 -233
  198. package/skills/patterns/performance/edge.md +0 -254
  199. package/skills/patterns/performance/isr.md +0 -266
  200. package/skills/patterns/performance/lazy-loading.md +0 -281
  201. package/skills/patterns/realtime/sse.md +0 -327
  202. package/skills/patterns/realtime/websockets.md +0 -336
  203. package/skills/patterns/search/filtering.md +0 -329
  204. package/skills/patterns/search/fulltext.md +0 -260
  205. package/skills/patterns/security/audit-logging.md +0 -444
  206. package/skills/patterns/security/csrf.md +0 -234
  207. package/skills/patterns/security/headers.md +0 -252
  208. package/skills/patterns/security/sanitization.md +0 -258
  209. package/skills/patterns/security/secrets.md +0 -261
  210. package/skills/patterns/security/validation.md +0 -268
  211. package/skills/patterns/security/xss.md +0 -229
  212. package/skills/patterns/seo/metadata.md +0 -252
  213. package/skills/patterns/state/context.md +0 -349
  214. package/skills/patterns/state/react-query.md +0 -313
  215. package/skills/patterns/state/url-state.md +0 -482
  216. package/skills/patterns/state/zustand.md +0 -262
  217. package/skills/patterns/testing/api.md +0 -259
  218. package/skills/patterns/testing/component.md +0 -233
  219. package/skills/patterns/testing/coverage.md +0 -207
  220. package/skills/patterns/testing/fixtures.md +0 -225
  221. package/skills/patterns/testing/integration.md +0 -436
  222. package/skills/patterns/testing/mocking.md +0 -177
  223. package/skills/patterns/testing/playwright.md +0 -162
  224. package/skills/patterns/testing/snapshot.md +0 -175
  225. package/skills/patterns/testing/vitest.md +0 -307
  226. package/skills/patterns/ui/accordions.md +0 -395
  227. package/skills/patterns/ui/cards.md +0 -299
  228. package/skills/patterns/ui/dropdowns.md +0 -476
  229. package/skills/patterns/ui/empty-states.md +0 -320
  230. package/skills/patterns/ui/forms.md +0 -405
  231. package/skills/patterns/ui/inputs.md +0 -319
  232. package/skills/patterns/ui/layouts.md +0 -282
  233. package/skills/patterns/ui/loading.md +0 -291
  234. package/skills/patterns/ui/modals.md +0 -338
  235. package/skills/patterns/ui/navigation.md +0 -374
  236. package/skills/patterns/ui/tables.md +0 -407
  237. package/skills/patterns/ui/toasts.md +0 -300
  238. package/skills/patterns/ui/tooltips.md +0 -396
  239. package/skills/patterns/utils/dates.md +0 -435
  240. package/skills/patterns/utils/errors.md +0 -451
  241. package/skills/patterns/utils/formatting.md +0 -345
  242. package/skills/patterns/utils/validation.md +0 -434
  243. package/templates/bootspring.config.js +0 -83
  244. package/templates/business/business-model-canvas.md +0 -246
  245. package/templates/business/business-plan.md +0 -266
  246. package/templates/business/competitive-analysis.md +0 -312
  247. package/templates/fundraising/data-room-checklist.md +0 -300
  248. package/templates/fundraising/investor-research.md +0 -243
  249. package/templates/fundraising/pitch-deck-outline.md +0 -253
  250. package/templates/legal/gdpr-checklist.md +0 -339
  251. package/templates/legal/privacy-policy.md +0 -285
  252. package/templates/legal/terms-of-service.md +0 -222
  253. package/templates/mcp.json +0 -9
@@ -103,7 +103,7 @@ function getNextStory(prd) {
103
103
  /**
104
104
  * Update story status
105
105
  */
106
- function updateStoryStatus(prd, storyId, status) {
106
+ function updateStoryStatus(prd, storyId, status, options = {}) {
107
107
  const story = prd.stories.find(s => s.id === storyId);
108
108
  if (!story) {
109
109
  throw new Error(`Story not found: ${storyId}`);
@@ -112,11 +112,95 @@ function updateStoryStatus(prd, storyId, status) {
112
112
  story.status = status;
113
113
  if (status === 'complete') {
114
114
  story.completedAt = new Date().toISOString();
115
+
116
+ // Notify workflow system if integrated
117
+ if (options.notifyWorkflow !== false) {
118
+ try {
119
+ const orchestrator = require('./orchestrator');
120
+ orchestrator.onPrdStoryComplete(prd.name, storyId);
121
+ } catch {
122
+ // Orchestrator not available or PRD not linked
123
+ }
124
+ }
115
125
  }
116
126
 
117
127
  return prd;
118
128
  }
119
129
 
130
+ /**
131
+ * Link this PRD to a workflow for automatic progress tracking
132
+ * @param {object} prd - The PRD object
133
+ * @param {string} workflowName - Name of the workflow to link
134
+ * @param {object} options - Optional configuration
135
+ * @param {object} options.manualMapping - Manual story->phase mapping { storyId: phaseIndex }
136
+ * @param {boolean} options.autoAdvance - Auto-advance workflow on phase completion (default: true)
137
+ */
138
+ function linkToWorkflow(prd, workflowName, options = {}) {
139
+ const orchestrator = require('./orchestrator');
140
+ return orchestrator.linkPrdToWorkflow(prd, workflowName, options);
141
+ }
142
+
143
+ /**
144
+ * Get workflow link status for this PRD
145
+ * @param {string} prdName - Name of the PRD
146
+ */
147
+ function getWorkflowStatus(prdName) {
148
+ const orchestrator = require('./orchestrator');
149
+ return orchestrator.getPrdWorkflowStatus(prdName);
150
+ }
151
+
152
+ /**
153
+ * Get stories assigned to a specific workflow phase
154
+ * @param {string} prdName - Name of the PRD
155
+ * @param {number} phaseIndex - Index of the workflow phase
156
+ */
157
+ function getStoriesForPhase(prdName, phaseIndex) {
158
+ const orchestrator = require('./orchestrator');
159
+ return orchestrator.getPhaseStories(prdName, phaseIndex);
160
+ }
161
+
162
+ /**
163
+ * Reassign a story to a different workflow phase
164
+ * @param {string} prdName - Name of the PRD
165
+ * @param {string} storyId - ID of the story
166
+ * @param {number} newPhaseIndex - New phase index to assign
167
+ */
168
+ function reassignStoryPhase(prdName, storyId, newPhaseIndex) {
169
+ const orchestrator = require('./orchestrator');
170
+ return orchestrator.reassignStoryToPhase(prdName, storyId, newPhaseIndex);
171
+ }
172
+
173
+ /**
174
+ * Unlink a PRD from its workflow
175
+ * @param {string} prdName - Name of the PRD
176
+ */
177
+ function unlinkFromWorkflow(prdName) {
178
+ const orchestrator = require('./orchestrator');
179
+ return orchestrator.unlinkPrdFromWorkflow(prdName);
180
+ }
181
+
182
+ /**
183
+ * Get combined PRD and workflow progress
184
+ * @param {object} prd - The PRD object
185
+ */
186
+ function getFullProgress(prd) {
187
+ const prdProgress = getProgress(prd);
188
+ const workflowStatus = getWorkflowStatus(prd.name);
189
+
190
+ return {
191
+ prd: prdProgress,
192
+ workflow: workflowStatus ? {
193
+ linked: true,
194
+ workflowName: workflowStatus.workflowName,
195
+ currentPhase: workflowStatus.currentPhaseName,
196
+ phaseProgress: workflowStatus.phaseProgress,
197
+ autoAdvance: workflowStatus.autoAdvance
198
+ } : {
199
+ linked: false
200
+ }
201
+ };
202
+ }
203
+
120
204
  /**
121
205
  * Get PRD progress summary
122
206
  */
@@ -442,6 +526,13 @@ module.exports = {
442
526
  parseMarkdownPRD,
443
527
  toMarkdown,
444
528
  validateStorySize,
529
+ // Workflow integration
530
+ linkToWorkflow,
531
+ getWorkflowStatus,
532
+ getStoriesForPhase,
533
+ reassignStoryPhase,
534
+ unlinkFromWorkflow,
535
+ getFullProgress,
445
536
  DEFAULT_PRD_DIR,
446
537
  DEFAULT_PRD_FILE
447
538
  };
@@ -7,12 +7,24 @@
7
7
  "completionRateMultiplier": 20,
8
8
  "contextMatch": 12,
9
9
  "packBonus": 3,
10
- "premiumUnlock": 4
10
+ "premiumUnlock": 4,
11
+ "learningBonus": 8,
12
+ "learningSuccessRateMultiplier": 15,
13
+ "correlationBonus": 6,
14
+ "antiPatternPenalty": 12
11
15
  },
12
16
  "skill": {
13
17
  "base": 25,
14
18
  "usage": 4,
15
- "premiumUnlock": 3
19
+ "premiumUnlock": 3,
20
+ "learningSuccessRateMultiplier": 10,
21
+ "antiPatternPenalty": 8
22
+ },
23
+ "learning": {
24
+ "minConfidence": 0.5,
25
+ "minSampleSize": 3,
26
+ "successRateThreshold": 0.7,
27
+ "antiPatternFailureThreshold": 0.6
16
28
  },
17
29
  "eventWindowLimit": 1000
18
30
  }
@@ -1,10 +1,19 @@
1
1
  /**
2
2
  * Recommendation engine v1
3
3
  * Ranks workflows and skills from context + telemetry outcomes.
4
+ * Enhanced with pattern learning insights.
5
+ *
6
+ * Learning Integration:
7
+ * - Boosts recommendations based on type/phase success rates
8
+ * - Penalizes workflows/skills associated with anti-patterns
9
+ * - Leverages correlations to recommend related successful patterns
10
+ * - Weighs recommendations by confidence from sample size
4
11
  */
5
12
 
6
13
  const fs = require('fs');
7
14
  const path = require('path');
15
+ const patternLearner = require('./learning/pattern-learner');
16
+ const decisionTracker = require('./memory/decision-tracker');
8
17
 
9
18
  const DEFAULT_WEIGHTS_PATH = path.join(__dirname, 'recommendation-weights.json');
10
19
 
@@ -59,6 +68,333 @@ function buildSkillUsage(events) {
59
68
  return { usage, premiumUnlocks };
60
69
  }
61
70
 
71
+ /**
72
+ * Calculate impact-based score adjustment for a workflow
73
+ * Uses decision tracker's impact scoring to boost high-impact patterns
74
+ * @param {Object} workflow - The workflow being scored
75
+ * @param {Object} weights - Resolved weights configuration
76
+ * @returns {Object} - { scoreAdjustment, reasons }
77
+ */
78
+ function calculateImpactBoost(workflow, weights) {
79
+ const adjustment = { score: 0, reasons: [] };
80
+
81
+ try {
82
+ // Get impact-boosted patterns from decision tracker
83
+ const impactPatterns = decisionTracker.getImpactBoostedPatterns({
84
+ minScore: weights.impact?.minScore || 3.0,
85
+ minSuccessRate: weights.impact?.minSuccessRate || 0.6
86
+ });
87
+
88
+ if (!impactPatterns || impactPatterns.length === 0) {
89
+ return adjustment;
90
+ }
91
+
92
+ // Find patterns that match this workflow
93
+ const workflowKey = (workflow.key || '').toLowerCase();
94
+ const workflowName = (workflow.name || '').toLowerCase();
95
+ const combined = `${workflowKey} ${workflowName}`;
96
+
97
+ for (const pattern of impactPatterns) {
98
+ const patternDecision = (pattern.decision || '').toLowerCase();
99
+ const patternType = (pattern.type || '').toLowerCase();
100
+
101
+ // Check if workflow matches the high-impact pattern
102
+ const matchesDecision = combined.includes(patternDecision.slice(0, 20)) ||
103
+ patternDecision.includes(workflowKey);
104
+ const matchesType = inferWorkflowType(workflow) === patternType;
105
+
106
+ if (matchesDecision || matchesType) {
107
+ // Calculate boost based on pattern's boost factor
108
+ const boost = Math.round(
109
+ pattern.boostFactor * Number(weights.impact?.impactBoostMultiplier || 10)
110
+ );
111
+ adjustment.score += boost;
112
+ adjustment.reasons.push(
113
+ `matches high-impact pattern: ${pattern.type} (${(pattern.successRate * 100).toFixed(0)}% success, ` +
114
+ `${pattern.averageImpactScore.toFixed(1)} impact score)`
115
+ );
116
+
117
+ // Only apply one impact boost per workflow
118
+ break;
119
+ }
120
+ }
121
+ } catch {
122
+ // Impact scoring not available, skip silently
123
+ }
124
+
125
+ return adjustment;
126
+ }
127
+
128
+ /**
129
+ * Calculate learning-based score adjustment for a workflow
130
+ * @param {Object} workflow - The workflow being scored
131
+ * @param {Object} learningInsights - Insights from pattern learner
132
+ * @param {Object} analysis - Context analysis with phase info
133
+ * @param {Object} weights - Resolved weights configuration
134
+ * @returns {Object} - { scoreAdjustment, reasons }
135
+ */
136
+ function calculateLearningBoost(workflow, learningInsights, analysis, weights) {
137
+ const adjustment = { score: 0, reasons: [] };
138
+
139
+ if (!learningInsights || learningInsights.using_defaults) {
140
+ return adjustment;
141
+ }
142
+
143
+ const learningWeights = weights.learning || {};
144
+ const minConfidence = learningWeights.minConfidence || 0.5;
145
+ const minSampleSize = learningWeights.minSampleSize || 3;
146
+ const successRateThreshold = learningWeights.successRateThreshold || 0.7;
147
+
148
+ // 1. Phase-based boost: If current phase has high success rate, boost matching workflows
149
+ const currentPhase = analysis.phase;
150
+ const phaseRec = learningInsights.recommendations?.by_phase?.[currentPhase];
151
+ if (phaseRec && !phaseRec.is_default && phaseRec.sample_size >= minSampleSize) {
152
+ if (phaseRec.success_rate >= successRateThreshold) {
153
+ const boost = Math.round(
154
+ phaseRec.success_rate * Number(weights.workflow?.learningSuccessRateMultiplier || 15)
155
+ );
156
+ adjustment.score += boost;
157
+ adjustment.reasons.push(`phase "${currentPhase}" has ${(phaseRec.success_rate * 100).toFixed(0)}% success rate`);
158
+ }
159
+ }
160
+
161
+ // 2. Type-based boost: Match workflow tags/type with learned type success rates
162
+ const workflowType = workflow.type || inferWorkflowType(workflow);
163
+ const typeRec = learningInsights.recommendations?.by_type?.[workflowType];
164
+ if (typeRec && !typeRec.is_default && typeRec.sample_size >= minSampleSize) {
165
+ if (typeRec.success_rate >= successRateThreshold) {
166
+ const boost = Math.round(
167
+ typeRec.success_rate * Number(weights.workflow?.learningSuccessRateMultiplier || 15)
168
+ );
169
+ adjustment.score += boost;
170
+ adjustment.reasons.push(`type "${workflowType}" has ${(typeRec.success_rate * 100).toFixed(0)}% success rate`);
171
+ } else if (typeRec.success_rate < 0.4) {
172
+ // Penalty for consistently failing types
173
+ const penalty = Math.round(
174
+ (1 - typeRec.success_rate) * Number(weights.workflow?.antiPatternPenalty || 12) * 0.5
175
+ );
176
+ adjustment.score -= penalty;
177
+ adjustment.reasons.push(`type "${workflowType}" has low success rate (${(typeRec.success_rate * 100).toFixed(0)}%)`);
178
+ }
179
+ }
180
+
181
+ // 3. Correlation boost: If workflow relates to recently successful patterns
182
+ const correlations = learningInsights.correlations || [];
183
+ for (const corr of correlations) {
184
+ const workflowMatches = workflow.key?.includes(corr.type_a) ||
185
+ workflow.key?.includes(corr.type_b) ||
186
+ workflow.name?.toLowerCase().includes(corr.decision_a?.toLowerCase()) ||
187
+ workflow.name?.toLowerCase().includes(corr.decision_b?.toLowerCase());
188
+
189
+ if (workflowMatches && corr.occurrences >= 2) {
190
+ adjustment.score += Number(weights.workflow?.correlationBonus || 6);
191
+ adjustment.reasons.push(`correlates with successful pattern: ${corr.decision_a} → ${corr.decision_b}`);
192
+ break; // Only apply one correlation bonus
193
+ }
194
+ }
195
+
196
+ // 4. Anti-pattern penalty: Penalize workflows matching known anti-patterns
197
+ const antiPatterns = learningInsights.anti_patterns || [];
198
+ for (const ap of antiPatterns) {
199
+ if (ap.is_default) continue; // Skip default anti-patterns
200
+ const matchesAntiPattern = workflow.key?.toLowerCase().includes(ap.decision?.toLowerCase()) ||
201
+ workflow.name?.toLowerCase().includes(ap.decision?.toLowerCase());
202
+
203
+ if (matchesAntiPattern && ap.failure_rate >= (learningWeights.antiPatternFailureThreshold || 0.6)) {
204
+ const penalty = Math.round(
205
+ ap.failure_rate * Number(weights.workflow?.antiPatternPenalty || 12)
206
+ );
207
+ adjustment.score -= penalty;
208
+ adjustment.reasons.push(`matches anti-pattern: "${ap.decision}" (${(ap.failure_rate * 100).toFixed(0)}% failure rate)`);
209
+ }
210
+ }
211
+
212
+ // 5. Insight-based adjustments from high-confidence insights
213
+ const insights = learningInsights.insights || [];
214
+ for (const insight of insights) {
215
+ if (insight.confidence < minConfidence) continue;
216
+
217
+ if (insight.type === 'type_performance' && insight.level === 'positive') {
218
+ if (workflowType === insight.subject) {
219
+ adjustment.score += Number(weights.workflow?.learningBonus || 8);
220
+ adjustment.reasons.push(`high-performing type: ${insight.message}`);
221
+ }
222
+ }
223
+ }
224
+
225
+ return adjustment;
226
+ }
227
+
228
+ /**
229
+ * Calculate impact-based score adjustment for a skill
230
+ * Uses decision tracker's impact scoring to boost high-impact skill patterns
231
+ * @param {string} skillId - The skill ID
232
+ * @param {Object} metadata - Skill metadata
233
+ * @param {Object} weights - Resolved weights configuration
234
+ * @returns {Object} - { scoreAdjustment, reasons }
235
+ */
236
+ function calculateSkillImpactBoost(skillId, metadata, weights) {
237
+ const adjustment = { score: 0, reasons: [] };
238
+
239
+ try {
240
+ // Get impact-boosted patterns from decision tracker
241
+ const impactPatterns = decisionTracker.getImpactBoostedPatterns({
242
+ minScore: weights.impact?.minScore || 3.0,
243
+ minSuccessRate: weights.impact?.minSuccessRate || 0.6
244
+ });
245
+
246
+ if (!impactPatterns || impactPatterns.length === 0) {
247
+ return adjustment;
248
+ }
249
+
250
+ // Find patterns that match this skill
251
+ const skillIdLower = (skillId || '').toLowerCase();
252
+ const skillName = (metadata?.name || '').toLowerCase();
253
+ const skillType = inferSkillType(skillId);
254
+
255
+ for (const pattern of impactPatterns) {
256
+ const patternDecision = (pattern.decision || '').toLowerCase();
257
+ const patternType = (pattern.type || '').toLowerCase();
258
+
259
+ // Check if skill matches the high-impact pattern
260
+ const matchesDecision = skillIdLower.includes(patternDecision.slice(0, 15)) ||
261
+ patternDecision.includes(skillIdLower.slice(0, 15)) ||
262
+ skillName.includes(patternDecision.slice(0, 15));
263
+ const matchesType = skillType === patternType;
264
+
265
+ if (matchesDecision || matchesType) {
266
+ // Calculate boost based on pattern's boost factor (slightly lower for skills)
267
+ const boost = Math.round(
268
+ pattern.boostFactor * Number(weights.impact?.skillImpactBoostMultiplier || 7)
269
+ );
270
+ adjustment.score += boost;
271
+ adjustment.reasons.push(
272
+ `matches high-impact pattern: ${pattern.type} (${(pattern.successRate * 100).toFixed(0)}% success)`
273
+ );
274
+
275
+ // Only apply one impact boost per skill
276
+ break;
277
+ }
278
+ }
279
+ } catch {
280
+ // Impact scoring not available, skip silently
281
+ }
282
+
283
+ return adjustment;
284
+ }
285
+
286
+ /**
287
+ * Calculate learning-based score adjustment for a skill
288
+ * @param {string} skillId - The skill ID
289
+ * @param {Object} metadata - Skill metadata
290
+ * @param {Object} learningInsights - Insights from pattern learner
291
+ * @param {Object} weights - Resolved weights configuration
292
+ * @returns {Object} - { scoreAdjustment, reasons }
293
+ */
294
+ function calculateSkillLearningBoost(skillId, metadata, learningInsights, weights) {
295
+ const adjustment = { score: 0, reasons: [] };
296
+
297
+ if (!learningInsights || learningInsights.using_defaults) {
298
+ return adjustment;
299
+ }
300
+
301
+ const learningWeights = weights.learning || {};
302
+ const minSampleSize = learningWeights.minSampleSize || 3;
303
+ const successRateThreshold = learningWeights.successRateThreshold || 0.7;
304
+
305
+ // Infer skill type from id/metadata
306
+ const skillType = metadata?.type || inferSkillType(skillId);
307
+
308
+ // Type-based boost for skills
309
+ const typeRec = learningInsights.recommendations?.by_type?.[skillType];
310
+ if (typeRec && !typeRec.is_default && typeRec.sample_size >= minSampleSize) {
311
+ if (typeRec.success_rate >= successRateThreshold) {
312
+ const boost = Math.round(
313
+ typeRec.success_rate * Number(weights.skill?.learningSuccessRateMultiplier || 10)
314
+ );
315
+ adjustment.score += boost;
316
+ adjustment.reasons.push(`skill type "${skillType}" has ${(typeRec.success_rate * 100).toFixed(0)}% success rate`);
317
+ }
318
+ }
319
+
320
+ // Anti-pattern penalty for skills
321
+ const antiPatterns = learningInsights.anti_patterns || [];
322
+ for (const ap of antiPatterns) {
323
+ if (ap.is_default) continue;
324
+ const matchesAntiPattern = skillId.toLowerCase().includes(ap.decision?.toLowerCase()) ||
325
+ (metadata?.name || '').toLowerCase().includes(ap.decision?.toLowerCase());
326
+
327
+ if (matchesAntiPattern && ap.failure_rate >= (learningWeights.antiPatternFailureThreshold || 0.6)) {
328
+ const penalty = Math.round(
329
+ ap.failure_rate * Number(weights.skill?.antiPatternPenalty || 8)
330
+ );
331
+ adjustment.score -= penalty;
332
+ adjustment.reasons.push(`skill matches anti-pattern: "${ap.decision}"`);
333
+ }
334
+ }
335
+
336
+ return adjustment;
337
+ }
338
+
339
+ /**
340
+ * Infer workflow type from workflow metadata
341
+ */
342
+ function inferWorkflowType(workflow) {
343
+ const key = (workflow.key || '').toLowerCase();
344
+ const name = (workflow.name || '').toLowerCase();
345
+ const combined = `${key} ${name}`;
346
+
347
+ if (combined.includes('database') || combined.includes('db') || combined.includes('migration')) {
348
+ return 'database';
349
+ }
350
+ if (combined.includes('api') || combined.includes('endpoint') || combined.includes('route')) {
351
+ return 'api';
352
+ }
353
+ if (combined.includes('ui') || combined.includes('component') || combined.includes('style')) {
354
+ return 'ui';
355
+ }
356
+ if (combined.includes('test') || combined.includes('spec')) {
357
+ return 'testing';
358
+ }
359
+ if (combined.includes('security') || combined.includes('auth') || combined.includes('permission')) {
360
+ return 'security';
361
+ }
362
+ if (combined.includes('deploy') || combined.includes('release') || combined.includes('ci')) {
363
+ return 'deployment';
364
+ }
365
+ if (combined.includes('architecture') || combined.includes('design') || combined.includes('refactor')) {
366
+ return 'architecture';
367
+ }
368
+ return 'general';
369
+ }
370
+
371
+ /**
372
+ * Infer skill type from skill ID
373
+ */
374
+ function inferSkillType(skillId) {
375
+ const id = (skillId || '').toLowerCase();
376
+
377
+ if (id.includes('database') || id.includes('db') || id.includes('prisma') || id.includes('sql')) {
378
+ return 'database';
379
+ }
380
+ if (id.includes('api') || id.includes('rest') || id.includes('graphql')) {
381
+ return 'api';
382
+ }
383
+ if (id.includes('component') || id.includes('style') || id.includes('css') || id.includes('ui')) {
384
+ return 'ui';
385
+ }
386
+ if (id.includes('test') || id.includes('spec') || id.includes('jest') || id.includes('vitest')) {
387
+ return 'testing';
388
+ }
389
+ if (id.includes('security') || id.includes('auth') || id.includes('encrypt')) {
390
+ return 'security';
391
+ }
392
+ if (id.includes('deploy') || id.includes('docker') || id.includes('ci')) {
393
+ return 'deployment';
394
+ }
395
+ return 'general';
396
+ }
397
+
62
398
  function workflowMatchesContext(workflow, tokens) {
63
399
  if (tokens.length === 0) return false;
64
400
  const haystack = [
@@ -91,6 +427,19 @@ function mergeWeights(overrides = {}) {
91
427
  ...(base.skill || {}),
92
428
  ...((overrides.skill) || {})
93
429
  },
430
+ learning: {
431
+ ...(base.learning || {}),
432
+ ...((overrides.learning) || {})
433
+ },
434
+ impact: {
435
+ // Default impact scoring configuration
436
+ minScore: 3.0, // Minimum impact score for boosting
437
+ minSuccessRate: 0.6, // Minimum success rate for boosting
438
+ impactBoostMultiplier: 10, // Multiplier for workflow impact boost
439
+ skillImpactBoostMultiplier: 7, // Multiplier for skill impact boost
440
+ ...(base.impact || {}),
441
+ ...((overrides.impact) || {})
442
+ },
94
443
  eventWindowLimit: Number(overrides.eventWindowLimit || base.eventWindowLimit || 1000)
95
444
  };
96
445
  }
@@ -126,6 +475,15 @@ function createRecommendationsEngine({ intelligence, telemetry, skills, entitlem
126
475
  const workflowStats = buildWorkflowStats(events);
127
476
  const skillStats = buildSkillUsage(events);
128
477
 
478
+ // Get learning insights
479
+ let learningInsights = null;
480
+ try {
481
+ learningInsights = patternLearner.analyze();
482
+ } catch {
483
+ // Learning not available yet
484
+ learningInsights = patternLearner.getDefaults();
485
+ }
486
+
129
487
  const available = intelligence.listWorkflows();
130
488
  const accessible = entitlements.filterAccessibleWorkflows(available, accessOptions).allowed;
131
489
  const workflows = accessible
@@ -162,6 +520,20 @@ function createRecommendationsEngine({ intelligence, telemetry, skills, entitlem
162
520
  reasons.push(`premium unlocks ${stats.premiumUnlocks}`);
163
521
  }
164
522
 
523
+ // Apply comprehensive learning insights
524
+ const learningBoost = calculateLearningBoost(workflow, learningInsights, analysis, resolvedWeights);
525
+ score += learningBoost.score;
526
+ reasons.push(...learningBoost.reasons);
527
+
528
+ // Apply impact-based boost from decision tracking
529
+ const impactBoost = calculateImpactBoost(workflow, resolvedWeights);
530
+ score += impactBoost.score;
531
+ reasons.push(...impactBoost.reasons);
532
+
533
+ // Combine learning and impact adjustments
534
+ const totalLearningAdjustment = learningBoost.score + impactBoost.score;
535
+ const allFactors = [...learningBoost.reasons, ...impactBoost.reasons];
536
+
165
537
  return {
166
538
  key: workflow.key,
167
539
  name: workflow.name,
@@ -175,7 +547,15 @@ function createRecommendationsEngine({ intelligence, telemetry, skills, entitlem
175
547
  checkpoints: stats.checkpoints,
176
548
  premiumUnlocks: stats.premiumUnlocks,
177
549
  completionRate
178
- }
550
+ },
551
+ learningImpact: totalLearningAdjustment !== 0 ? {
552
+ adjustment: totalLearningAdjustment,
553
+ factors: allFactors,
554
+ breakdown: {
555
+ learningBoost: learningBoost.score,
556
+ impactBoost: impactBoost.score
557
+ }
558
+ } : null
179
559
  };
180
560
  })
181
561
  .sort((a, b) => b.score - a.score)
@@ -192,24 +572,97 @@ function createRecommendationsEngine({ intelligence, telemetry, skills, entitlem
192
572
  const metadata = skills.getSkillMetadata(skillId) || {};
193
573
  const usage = skillStats.usage.get(skillId) || 0;
194
574
  const premiumUnlocks = skillStats.premiumUnlocks.get(skillId) || 0;
575
+
576
+ let score = Number(resolvedWeights.skill.base || 25)
577
+ + (usage * Number(resolvedWeights.skill.usage || 4))
578
+ + (premiumUnlocks * Number(resolvedWeights.skill.premiumUnlock || 3));
579
+
580
+ const reasons = [
581
+ 'suggested by context analysis',
582
+ ...(usage > 0 ? [`used ${usage} time(s) in prior sessions`] : []),
583
+ ...(premiumUnlocks > 0 ? [`premium unlocks ${premiumUnlocks}`] : [])
584
+ ];
585
+
586
+ // Apply learning-based adjustments for skills
587
+ const skillLearningBoost = calculateSkillLearningBoost(skillId, metadata, learningInsights, resolvedWeights);
588
+ score += skillLearningBoost.score;
589
+ reasons.push(...skillLearningBoost.reasons);
590
+
591
+ // Apply impact-based boost for skills
592
+ const skillImpactBoost = calculateSkillImpactBoost(skillId, metadata, resolvedWeights);
593
+ score += skillImpactBoost.score;
594
+ reasons.push(...skillImpactBoost.reasons);
595
+
596
+ // Combine learning and impact adjustments
597
+ const totalSkillAdjustment = skillLearningBoost.score + skillImpactBoost.score;
598
+ const allSkillFactors = [...skillLearningBoost.reasons, ...skillImpactBoost.reasons];
599
+
195
600
  return {
196
601
  id: skillId,
197
602
  name: metadata.name || skillId,
198
603
  description: metadata.description || '',
199
604
  source: metadata.source || 'built-in',
200
- score: Number(resolvedWeights.skill.base || 25)
201
- + (usage * Number(resolvedWeights.skill.usage || 4))
202
- + (premiumUnlocks * Number(resolvedWeights.skill.premiumUnlock || 3)),
203
- reasons: [
204
- 'suggested by context analysis',
205
- ...(usage > 0 ? [`used ${usage} time(s) in prior sessions`] : []),
206
- ...(premiumUnlocks > 0 ? [`premium unlocks ${premiumUnlocks}`] : [])
207
- ]
605
+ score,
606
+ reasons,
607
+ learningImpact: totalSkillAdjustment !== 0 ? {
608
+ adjustment: totalSkillAdjustment,
609
+ factors: allSkillFactors,
610
+ breakdown: {
611
+ learningBoost: skillLearningBoost.score,
612
+ impactBoost: skillImpactBoost.score
613
+ }
614
+ } : null
208
615
  };
209
616
  })
210
617
  .sort((a, b) => b.score - a.score)
211
618
  .slice(0, maxItems);
212
619
 
620
+ // Extract relevant learning data with enhanced context
621
+ const currentPhase = analysis.phase;
622
+
623
+ // Get impact statistics and patterns
624
+ let impactStats = null;
625
+ let impactBoostedPatterns = [];
626
+ try {
627
+ impactStats = decisionTracker.getImpactStats();
628
+ impactBoostedPatterns = decisionTracker.getImpactBoostedPatterns({
629
+ minScore: resolvedWeights.impact?.minScore || 3.0,
630
+ minSuccessRate: resolvedWeights.impact?.minSuccessRate || 0.6
631
+ }).slice(0, 5);
632
+ } catch {
633
+ // Impact tracking not available yet
634
+ }
635
+
636
+ const learningData = {
637
+ // Anti-patterns to avoid (filtered to non-defaults if real data exists)
638
+ antiPatterns: (learningInsights?.anti_patterns || [])
639
+ .filter(ap => !learningInsights?.using_defaults || ap.is_default)
640
+ .slice(0, 5),
641
+ // Top insights sorted by confidence
642
+ insights: (learningInsights?.insights || [])
643
+ .sort((a, b) => (b.confidence || 0) - (a.confidence || 0))
644
+ .slice(0, 5),
645
+ // Phase-specific recommendation for current context
646
+ phaseRecommendation: learningInsights?.recommendations?.by_phase?.[currentPhase] || null,
647
+ // General recommendations
648
+ generalRecommendations: learningInsights?.recommendations?.general?.slice(0, 3) || [],
649
+ // Relevant correlations that might inform workflow sequencing
650
+ correlations: (learningInsights?.correlations || [])
651
+ .filter(c => c.occurrences >= 2)
652
+ .slice(0, 3),
653
+ // Summary metrics
654
+ summary: learningInsights?.analysis_summary || null,
655
+ // Status flags
656
+ usingDefaults: learningInsights?.using_defaults || false,
657
+ lastAnalysis: learningInsights?.last_analysis || null,
658
+ // Impact-based insights (from decision tracking)
659
+ impact: {
660
+ stats: impactStats,
661
+ boostedPatterns: impactBoostedPatterns,
662
+ recentTrend: impactStats?.recentTrend || null
663
+ }
664
+ };
665
+
213
666
  return {
214
667
  context: {
215
668
  phase: analysis.phase,
@@ -218,6 +671,7 @@ function createRecommendationsEngine({ intelligence, telemetry, skills, entitlem
218
671
  },
219
672
  workflows,
220
673
  skills: skillsRanked,
674
+ learning: learningData,
221
675
  telemetryWindow: {
222
676
  eventsAnalyzed: events.length
223
677
  },