@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.
- package/README.md +107 -14
- package/bin/bootspring.js +166 -27
- package/cli/agent.js +189 -17
- package/cli/analyze.js +499 -0
- package/cli/audit.js +557 -0
- package/cli/auth.js +495 -38
- package/cli/billing.js +302 -0
- package/cli/build.js +695 -0
- package/cli/business.js +109 -26
- package/cli/checkpoint-utils.js +168 -0
- package/cli/checkpoint.js +639 -0
- package/cli/cloud-sync.js +447 -0
- package/cli/content.js +198 -0
- package/cli/context.js +1 -1
- package/cli/deploy.js +543 -0
- package/cli/fundraise.js +112 -50
- package/cli/github-cmd.js +435 -0
- package/cli/health.js +477 -0
- package/cli/init.js +84 -13
- package/cli/legal.js +107 -95
- package/cli/log.js +2 -2
- package/cli/loop.js +976 -73
- package/cli/manager.js +711 -0
- package/cli/metrics.js +480 -0
- package/cli/monitor.js +812 -0
- package/cli/onboard.js +521 -0
- package/cli/orchestrator.js +12 -24
- package/cli/prd.js +594 -0
- package/cli/preseed-start.js +1483 -0
- package/cli/preseed.js +2302 -0
- package/cli/project.js +436 -0
- package/cli/quality.js +233 -0
- package/cli/security.js +913 -0
- package/cli/seed.js +1441 -5
- package/cli/skill.js +273 -211
- package/cli/suggest.js +989 -0
- package/cli/switch.js +453 -0
- package/cli/visualize.js +527 -0
- package/cli/watch.js +769 -0
- package/cli/workspace.js +607 -0
- package/core/analyze-workflow.js +1134 -0
- package/core/api-client.js +535 -22
- package/core/audit-workflow.js +1350 -0
- package/core/build-orchestrator.js +480 -0
- package/core/build-state.js +577 -0
- package/core/checkpoint-engine.js +408 -0
- package/core/config.js +1109 -26
- package/core/context-loader.js +21 -1
- package/core/deploy-workflow.js +836 -0
- package/core/entitlements.js +93 -22
- package/core/github-sync.js +610 -0
- package/core/index.js +8 -1
- package/core/ingest.js +1111 -0
- package/core/metrics-engine.js +768 -0
- package/core/onboard-workflow.js +1007 -0
- package/core/preseed-workflow.js +934 -0
- package/core/preseed.js +1617 -0
- package/core/project-context.js +325 -0
- package/core/project-state.js +694 -0
- package/core/r2-sync.js +583 -0
- package/core/scaffold.js +525 -7
- package/core/session.js +258 -0
- package/core/task-extractor.js +758 -0
- package/core/telemetry.js +28 -6
- package/core/tier-enforcement.js +737 -0
- package/core/utils.js +38 -14
- package/generators/questionnaire.js +15 -12
- package/generators/sections/ai.js +7 -7
- package/generators/sections/content.js +300 -0
- package/generators/sections/index.js +3 -0
- package/generators/sections/plugins.js +7 -6
- package/generators/templates/build-planning.template.js +596 -0
- package/generators/templates/content.template.js +819 -0
- package/generators/templates/index.js +2 -1
- package/hooks/git-autopilot.js +1250 -0
- package/hooks/index.js +9 -0
- package/intelligence/agent-collab.js +2057 -0
- package/intelligence/auto-suggest.js +634 -0
- package/intelligence/content-gen.js +1589 -0
- package/intelligence/cross-project.js +1647 -0
- package/intelligence/index.js +184 -0
- package/intelligence/learning/insights.json +517 -7
- package/intelligence/learning/pattern-learner.js +1008 -14
- package/intelligence/memory/decision-tracker.js +1431 -31
- package/intelligence/memory/decisions.jsonl +0 -0
- package/intelligence/orchestrator.js +2896 -1
- package/intelligence/prd.js +92 -1
- package/intelligence/recommendation-weights.json +14 -2
- package/intelligence/recommendations.js +463 -9
- package/intelligence/workflow-composer.js +1451 -0
- package/marketplace/index.d.ts +324 -0
- package/marketplace/index.js +1921 -0
- package/mcp/contracts/mcp-contract.v1.json +342 -4
- package/mcp/registry.js +680 -3
- package/mcp/response-formatter.js +23 -0
- package/mcp/tools/assist-tool.js +78 -4
- package/mcp/tools/autopilot-tool.js +408 -0
- package/mcp/tools/content-tool.js +571 -0
- package/mcp/tools/dashboard-tool.js +251 -5
- package/mcp/tools/mvp-tool.js +344 -0
- package/mcp/tools/plugin-tool.js +23 -1
- package/mcp/tools/prd-tool.js +579 -0
- package/mcp/tools/seed-tool.js +447 -0
- package/mcp/tools/skill-tool.js +43 -14
- package/mcp/tools/suggest-tool.js +147 -0
- package/package.json +15 -6
- package/agents/README.md +0 -93
- package/agents/ai-integration-expert/context.md +0 -386
- package/agents/api-expert/context.md +0 -416
- package/agents/architecture-expert/context.md +0 -454
- package/agents/auth-expert/context.md +0 -399
- package/agents/backend-expert/context.md +0 -483
- package/agents/business-strategy-expert/context.md +0 -180
- package/agents/code-review-expert/context.md +0 -365
- package/agents/competitive-analysis-expert/context.md +0 -239
- package/agents/data-modeling-expert/context.md +0 -352
- package/agents/database-expert/context.md +0 -250
- package/agents/devops-expert/context.md +0 -446
- package/agents/email-expert/context.md +0 -379
- package/agents/financial-expert/context.md +0 -213
- package/agents/frontend-expert/context.md +0 -364
- package/agents/fundraising-expert/context.md +0 -257
- package/agents/growth-expert/context.md +0 -249
- package/agents/index.js +0 -140
- package/agents/investor-relations-expert/context.md +0 -266
- package/agents/legal-expert/context.md +0 -284
- package/agents/marketing-expert/context.md +0 -236
- package/agents/monitoring-expert/context.md +0 -362
- package/agents/operations-expert/context.md +0 -279
- package/agents/partnerships-expert/context.md +0 -286
- package/agents/payment-expert/context.md +0 -340
- package/agents/performance-expert/context.md +0 -377
- package/agents/private-equity-expert/context.md +0 -246
- package/agents/railway-expert/context.md +0 -284
- package/agents/research-expert/context.md +0 -245
- package/agents/sales-expert/context.md +0 -241
- package/agents/security-expert/context.md +0 -343
- package/agents/testing-expert/context.md +0 -414
- package/agents/ui-ux-expert/context.md +0 -448
- package/agents/vercel-expert/context.md +0 -426
- package/skills/index.js +0 -787
- package/skills/patterns/README.md +0 -163
- package/skills/patterns/ai/agents.md +0 -281
- package/skills/patterns/ai/claude.md +0 -138
- package/skills/patterns/ai/embeddings.md +0 -150
- package/skills/patterns/ai/rag.md +0 -266
- package/skills/patterns/ai/streaming.md +0 -170
- package/skills/patterns/ai/structured-output.md +0 -162
- package/skills/patterns/ai/tools.md +0 -154
- package/skills/patterns/analytics/tracking.md +0 -220
- package/skills/patterns/api/errors.md +0 -296
- package/skills/patterns/api/graphql.md +0 -440
- package/skills/patterns/api/middleware.md +0 -279
- package/skills/patterns/api/openapi.md +0 -285
- package/skills/patterns/api/rate-limiting.md +0 -231
- package/skills/patterns/api/route-handler.md +0 -217
- package/skills/patterns/api/server-action.md +0 -249
- package/skills/patterns/api/versioning.md +0 -443
- package/skills/patterns/api/webhooks.md +0 -247
- package/skills/patterns/auth/clerk.md +0 -132
- package/skills/patterns/auth/mfa.md +0 -313
- package/skills/patterns/auth/nextauth.md +0 -140
- package/skills/patterns/auth/oauth.md +0 -237
- package/skills/patterns/auth/rbac.md +0 -152
- package/skills/patterns/auth/session-management.md +0 -367
- package/skills/patterns/auth/session.md +0 -120
- package/skills/patterns/database/audit.md +0 -177
- package/skills/patterns/database/migrations.md +0 -177
- package/skills/patterns/database/pagination.md +0 -230
- package/skills/patterns/database/pooling.md +0 -357
- package/skills/patterns/database/prisma.md +0 -180
- package/skills/patterns/database/relations.md +0 -187
- package/skills/patterns/database/seeding.md +0 -246
- package/skills/patterns/database/soft-delete.md +0 -153
- package/skills/patterns/database/transactions.md +0 -162
- package/skills/patterns/deployment/ci-cd.md +0 -231
- package/skills/patterns/deployment/docker.md +0 -188
- package/skills/patterns/deployment/monitoring.md +0 -387
- package/skills/patterns/deployment/vercel.md +0 -160
- package/skills/patterns/email/resend.md +0 -143
- package/skills/patterns/email/templates.md +0 -245
- package/skills/patterns/email/transactional.md +0 -503
- package/skills/patterns/email/verification.md +0 -176
- package/skills/patterns/files/download.md +0 -243
- package/skills/patterns/files/upload.md +0 -239
- package/skills/patterns/i18n/nextintl.md +0 -188
- package/skills/patterns/logging/structured.md +0 -292
- package/skills/patterns/notifications/email-queue.md +0 -248
- package/skills/patterns/notifications/push.md +0 -279
- package/skills/patterns/payments/checkout.md +0 -303
- package/skills/patterns/payments/invoices.md +0 -287
- package/skills/patterns/payments/portal.md +0 -245
- package/skills/patterns/payments/stripe.md +0 -272
- package/skills/patterns/payments/subscriptions.md +0 -300
- package/skills/patterns/payments/usage.md +0 -279
- package/skills/patterns/performance/caching.md +0 -276
- package/skills/patterns/performance/code-splitting.md +0 -233
- package/skills/patterns/performance/edge.md +0 -254
- package/skills/patterns/performance/isr.md +0 -266
- package/skills/patterns/performance/lazy-loading.md +0 -281
- package/skills/patterns/realtime/sse.md +0 -327
- package/skills/patterns/realtime/websockets.md +0 -336
- package/skills/patterns/search/filtering.md +0 -329
- package/skills/patterns/search/fulltext.md +0 -260
- package/skills/patterns/security/audit-logging.md +0 -444
- package/skills/patterns/security/csrf.md +0 -234
- package/skills/patterns/security/headers.md +0 -252
- package/skills/patterns/security/sanitization.md +0 -258
- package/skills/patterns/security/secrets.md +0 -261
- package/skills/patterns/security/validation.md +0 -268
- package/skills/patterns/security/xss.md +0 -229
- package/skills/patterns/seo/metadata.md +0 -252
- package/skills/patterns/state/context.md +0 -349
- package/skills/patterns/state/react-query.md +0 -313
- package/skills/patterns/state/url-state.md +0 -482
- package/skills/patterns/state/zustand.md +0 -262
- package/skills/patterns/testing/api.md +0 -259
- package/skills/patterns/testing/component.md +0 -233
- package/skills/patterns/testing/coverage.md +0 -207
- package/skills/patterns/testing/fixtures.md +0 -225
- package/skills/patterns/testing/integration.md +0 -436
- package/skills/patterns/testing/mocking.md +0 -177
- package/skills/patterns/testing/playwright.md +0 -162
- package/skills/patterns/testing/snapshot.md +0 -175
- package/skills/patterns/testing/vitest.md +0 -307
- package/skills/patterns/ui/accordions.md +0 -395
- package/skills/patterns/ui/cards.md +0 -299
- package/skills/patterns/ui/dropdowns.md +0 -476
- package/skills/patterns/ui/empty-states.md +0 -320
- package/skills/patterns/ui/forms.md +0 -405
- package/skills/patterns/ui/inputs.md +0 -319
- package/skills/patterns/ui/layouts.md +0 -282
- package/skills/patterns/ui/loading.md +0 -291
- package/skills/patterns/ui/modals.md +0 -338
- package/skills/patterns/ui/navigation.md +0 -374
- package/skills/patterns/ui/tables.md +0 -407
- package/skills/patterns/ui/toasts.md +0 -300
- package/skills/patterns/ui/tooltips.md +0 -396
- package/skills/patterns/utils/dates.md +0 -435
- package/skills/patterns/utils/errors.md +0 -451
- package/skills/patterns/utils/formatting.md +0 -345
- package/skills/patterns/utils/validation.md +0 -434
- package/templates/bootspring.config.js +0 -83
- package/templates/business/business-model-canvas.md +0 -246
- package/templates/business/business-plan.md +0 -266
- package/templates/business/competitive-analysis.md +0 -312
- package/templates/fundraising/data-room-checklist.md +0 -300
- package/templates/fundraising/investor-research.md +0 -243
- package/templates/fundraising/pitch-deck-outline.md +0 -253
- package/templates/legal/gdpr-checklist.md +0 -339
- package/templates/legal/privacy-policy.md +0 -285
- package/templates/legal/terms-of-service.md +0 -222
- package/templates/mcp.json +0 -9
package/intelligence/prd.js
CHANGED
|
@@ -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
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
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
|
},
|