specweave 0.3.13 → 0.4.1

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 (168) hide show
  1. package/CLAUDE.md +506 -17
  2. package/README.md +100 -58
  3. package/bin/install-all.sh +9 -2
  4. package/bin/install-hooks.sh +57 -0
  5. package/bin/specweave.js +16 -0
  6. package/dist/adapters/adapter-base.d.ts +21 -0
  7. package/dist/adapters/adapter-base.d.ts.map +1 -1
  8. package/dist/adapters/adapter-base.js +28 -0
  9. package/dist/adapters/adapter-base.js.map +1 -1
  10. package/dist/adapters/adapter-interface.d.ts +41 -0
  11. package/dist/adapters/adapter-interface.d.ts.map +1 -1
  12. package/dist/adapters/claude/adapter.d.ts +36 -0
  13. package/dist/adapters/claude/adapter.d.ts.map +1 -1
  14. package/dist/adapters/claude/adapter.js +135 -0
  15. package/dist/adapters/claude/adapter.js.map +1 -1
  16. package/dist/adapters/copilot/adapter.d.ts +25 -0
  17. package/dist/adapters/copilot/adapter.d.ts.map +1 -1
  18. package/dist/adapters/copilot/adapter.js +112 -0
  19. package/dist/adapters/copilot/adapter.js.map +1 -1
  20. package/dist/adapters/cursor/adapter.d.ts +36 -0
  21. package/dist/adapters/cursor/adapter.d.ts.map +1 -1
  22. package/dist/adapters/cursor/adapter.js +140 -0
  23. package/dist/adapters/cursor/adapter.js.map +1 -1
  24. package/dist/adapters/generic/adapter.d.ts +25 -0
  25. package/dist/adapters/generic/adapter.d.ts.map +1 -1
  26. package/dist/adapters/generic/adapter.js +111 -0
  27. package/dist/adapters/generic/adapter.js.map +1 -1
  28. package/dist/cli/commands/init.d.ts.map +1 -1
  29. package/dist/cli/commands/init.js +103 -1
  30. package/dist/cli/commands/init.js.map +1 -1
  31. package/dist/cli/commands/plugin.d.ts +37 -0
  32. package/dist/cli/commands/plugin.d.ts.map +1 -0
  33. package/dist/cli/commands/plugin.js +296 -0
  34. package/dist/cli/commands/plugin.js.map +1 -0
  35. package/dist/core/agent-model-manager.d.ts +52 -0
  36. package/dist/core/agent-model-manager.d.ts.map +1 -0
  37. package/dist/core/agent-model-manager.js +120 -0
  38. package/dist/core/agent-model-manager.js.map +1 -0
  39. package/dist/core/cost-tracker.d.ts +108 -0
  40. package/dist/core/cost-tracker.d.ts.map +1 -0
  41. package/dist/core/cost-tracker.js +281 -0
  42. package/dist/core/cost-tracker.js.map +1 -0
  43. package/dist/core/model-selector.d.ts +57 -0
  44. package/dist/core/model-selector.d.ts.map +1 -0
  45. package/dist/core/model-selector.js +115 -0
  46. package/dist/core/model-selector.js.map +1 -0
  47. package/dist/core/phase-detector.d.ts +62 -0
  48. package/dist/core/phase-detector.d.ts.map +1 -0
  49. package/dist/core/phase-detector.js +229 -0
  50. package/dist/core/phase-detector.js.map +1 -0
  51. package/dist/core/plugin-detector.d.ts +96 -0
  52. package/dist/core/plugin-detector.d.ts.map +1 -0
  53. package/dist/core/plugin-detector.js +349 -0
  54. package/dist/core/plugin-detector.js.map +1 -0
  55. package/dist/core/plugin-loader.d.ts +111 -0
  56. package/dist/core/plugin-loader.d.ts.map +1 -0
  57. package/dist/core/plugin-loader.js +319 -0
  58. package/dist/core/plugin-loader.js.map +1 -0
  59. package/dist/core/plugin-manager.d.ts +144 -0
  60. package/dist/core/plugin-manager.d.ts.map +1 -0
  61. package/dist/core/plugin-manager.js +393 -0
  62. package/dist/core/plugin-manager.js.map +1 -0
  63. package/dist/core/schemas/plugin-manifest.schema.json +253 -0
  64. package/dist/core/types/plugin.d.ts +252 -0
  65. package/dist/core/types/plugin.d.ts.map +1 -0
  66. package/dist/core/types/plugin.js +48 -0
  67. package/dist/core/types/plugin.js.map +1 -0
  68. package/dist/integrations/jira/jira-mapper.d.ts +2 -2
  69. package/dist/integrations/jira/jira-mapper.js +2 -2
  70. package/dist/types/cost-tracking.d.ts +43 -0
  71. package/dist/types/cost-tracking.d.ts.map +1 -0
  72. package/dist/types/cost-tracking.js +8 -0
  73. package/dist/types/cost-tracking.js.map +1 -0
  74. package/dist/types/model-selection.d.ts +53 -0
  75. package/dist/types/model-selection.d.ts.map +1 -0
  76. package/dist/types/model-selection.js +12 -0
  77. package/dist/types/model-selection.js.map +1 -0
  78. package/dist/utils/cost-reporter.d.ts +58 -0
  79. package/dist/utils/cost-reporter.d.ts.map +1 -0
  80. package/dist/utils/cost-reporter.js +224 -0
  81. package/dist/utils/cost-reporter.js.map +1 -0
  82. package/dist/utils/pricing-constants.d.ts +70 -0
  83. package/dist/utils/pricing-constants.d.ts.map +1 -0
  84. package/dist/utils/pricing-constants.js +71 -0
  85. package/dist/utils/pricing-constants.js.map +1 -0
  86. package/package.json +13 -9
  87. package/src/adapters/adapter-base.ts +33 -0
  88. package/src/adapters/adapter-interface.ts +46 -0
  89. package/src/adapters/claude/adapter.ts +164 -0
  90. package/src/adapters/copilot/adapter.ts +138 -0
  91. package/src/adapters/cursor/adapter.ts +170 -0
  92. package/src/adapters/generic/adapter.ts +137 -0
  93. package/src/agents/architect/AGENT.md +3 -0
  94. package/src/agents/code-reviewer.md +156 -0
  95. package/src/agents/data-scientist/AGENT.md +181 -0
  96. package/src/agents/database-optimizer/AGENT.md +147 -0
  97. package/src/agents/devops/AGENT.md +3 -0
  98. package/src/agents/diagrams-architect/AGENT.md +3 -0
  99. package/src/agents/docs-writer/AGENT.md +3 -0
  100. package/src/agents/kubernetes-architect/AGENT.md +142 -0
  101. package/src/agents/ml-engineer/AGENT.md +150 -0
  102. package/src/agents/mlops-engineer/AGENT.md +201 -0
  103. package/src/agents/network-engineer/AGENT.md +149 -0
  104. package/src/agents/observability-engineer/AGENT.md +213 -0
  105. package/src/agents/payment-integration/AGENT.md +35 -0
  106. package/src/agents/performance/AGENT.md +3 -0
  107. package/src/agents/performance-engineer/AGENT.md +153 -0
  108. package/src/agents/pm/AGENT.md +3 -0
  109. package/src/agents/qa-lead/AGENT.md +3 -0
  110. package/src/agents/security/AGENT.md +3 -0
  111. package/src/agents/sre/AGENT.md +3 -0
  112. package/src/agents/tdd-orchestrator/AGENT.md +169 -0
  113. package/src/agents/tech-lead/AGENT.md +3 -0
  114. package/src/commands/specweave.costs.md +261 -0
  115. package/src/commands/specweave.increment.md +48 -4
  116. package/src/commands/specweave.ml-pipeline.md +292 -0
  117. package/src/commands/specweave.monitor-setup.md +501 -0
  118. package/src/commands/specweave.slo-implement.md +1055 -0
  119. package/src/commands/specweave.sync-github.md +1 -1
  120. package/src/commands/specweave.tdd-cycle.md +199 -0
  121. package/src/commands/specweave.tdd-green.md +842 -0
  122. package/src/commands/specweave.tdd-red.md +135 -0
  123. package/src/commands/specweave.tdd-refactor.md +165 -0
  124. package/src/hooks/post-increment-plugin-detect.sh +142 -0
  125. package/src/hooks/post-task-completion.sh +53 -11
  126. package/src/hooks/pre-task-plugin-detect.sh +96 -0
  127. package/src/skills/SKILLS-INDEX.md +18 -10
  128. package/src/skills/billing-automation/SKILL.md +559 -0
  129. package/src/skills/distributed-tracing/SKILL.md +438 -0
  130. package/src/skills/e2e-playwright/README.md +1 -1
  131. package/src/skills/e2e-playwright/package.json +1 -1
  132. package/src/skills/gitops-workflow/SKILL.md +285 -0
  133. package/src/skills/gitops-workflow/references/argocd-setup.md +134 -0
  134. package/src/skills/gitops-workflow/references/sync-policies.md +131 -0
  135. package/src/skills/grafana-dashboards/SKILL.md +369 -0
  136. package/src/skills/helm-chart-scaffolding/SKILL.md +544 -0
  137. package/src/skills/helm-chart-scaffolding/assets/Chart.yaml.template +42 -0
  138. package/src/skills/helm-chart-scaffolding/assets/values.yaml.template +185 -0
  139. package/src/skills/helm-chart-scaffolding/references/chart-structure.md +500 -0
  140. package/src/skills/helm-chart-scaffolding/scripts/validate-chart.sh +244 -0
  141. package/src/skills/k8s-manifest-generator/SKILL.md +511 -0
  142. package/src/skills/k8s-manifest-generator/assets/configmap-template.yaml +296 -0
  143. package/src/skills/k8s-manifest-generator/assets/deployment-template.yaml +203 -0
  144. package/src/skills/k8s-manifest-generator/assets/service-template.yaml +171 -0
  145. package/src/skills/k8s-manifest-generator/references/deployment-spec.md +753 -0
  146. package/src/skills/k8s-manifest-generator/references/service-spec.md +724 -0
  147. package/src/skills/k8s-security-policies/SKILL.md +334 -0
  148. package/src/skills/k8s-security-policies/assets/network-policy-template.yaml +177 -0
  149. package/src/skills/k8s-security-policies/references/rbac-patterns.md +187 -0
  150. package/src/skills/ml-pipeline-workflow/SKILL.md +245 -0
  151. package/src/skills/paypal-integration/SKILL.md +467 -0
  152. package/src/skills/pci-compliance/SKILL.md +466 -0
  153. package/src/skills/prometheus-configuration/SKILL.md +392 -0
  154. package/src/skills/slo-implementation/SKILL.md +329 -0
  155. package/src/skills/stripe-integration/SKILL.md +442 -0
  156. package/src/skills/tdd-workflow/SKILL.md +378 -0
  157. package/src/templates/README.md.template +1 -1
  158. package/src/skills/bmad-method-expert/SKILL.md +0 -626
  159. package/src/skills/bmad-method-expert/scripts/analyze-project.js +0 -318
  160. package/src/skills/bmad-method-expert/scripts/check-setup.js +0 -208
  161. package/src/skills/bmad-method-expert/scripts/generate-template.js +0 -1149
  162. package/src/skills/bmad-method-expert/scripts/validate-documents.js +0 -340
  163. package/src/skills/context-optimizer/SKILL.md +0 -588
  164. package/src/skills/figma-designer/SKILL.md +0 -149
  165. package/src/skills/figma-implementer/SKILL.md +0 -148
  166. package/src/skills/figma-mcp-connector/SKILL.md +0 -136
  167. package/src/skills/figma-to-code/SKILL.md +0 -128
  168. package/src/skills/spec-kit-expert/SKILL.md +0 -1010
@@ -0,0 +1,281 @@
1
+ /**
2
+ * Cost Tracker Service
3
+ *
4
+ * Real-time cost tracking for agent executions. Tracks token usage, calculates
5
+ * costs, aggregates by increment, and calculates savings vs baseline (Sonnet-only).
6
+ *
7
+ * Persistence: Stores data in .specweave/logs/costs.json
8
+ */
9
+ import fs from 'fs-extra';
10
+ import path from 'path';
11
+ import { calculateCost, calculateSavings } from '../utils/pricing-constants';
12
+ const DEFAULT_LOG_PATH = '.specweave/logs/costs.json';
13
+ export class CostTracker {
14
+ constructor(config = {}) {
15
+ this.sessions = new Map();
16
+ this.currentSessionId = null;
17
+ this.logPath = config.logPath || DEFAULT_LOG_PATH;
18
+ this.autoSave = config.autoSave !== false; // Default true
19
+ }
20
+ /**
21
+ * Start a new tracking session
22
+ *
23
+ * @param agent - Agent name (e.g., 'pm', 'frontend')
24
+ * @param model - Model used ('sonnet', 'haiku', 'opus')
25
+ * @param increment - Optional increment ID (e.g., '0003')
26
+ * @param command - Optional command that triggered this (e.g., '/specweave.inc')
27
+ * @returns Session ID
28
+ */
29
+ startSession(agent, model, increment, command) {
30
+ const sessionId = this.generateSessionId();
31
+ const session = {
32
+ sessionId,
33
+ agent,
34
+ model,
35
+ increment,
36
+ command,
37
+ startedAt: new Date().toISOString(),
38
+ tokenUsage: {
39
+ inputTokens: 0,
40
+ outputTokens: 0,
41
+ totalTokens: 0,
42
+ },
43
+ cost: 0,
44
+ savings: 0,
45
+ };
46
+ this.sessions.set(sessionId, session);
47
+ this.currentSessionId = sessionId;
48
+ return sessionId;
49
+ }
50
+ /**
51
+ * Record token usage for current session
52
+ *
53
+ * @param inputTokens - Number of input tokens
54
+ * @param outputTokens - Number of output tokens
55
+ * @param sessionId - Optional session ID (defaults to current)
56
+ */
57
+ recordTokens(inputTokens, outputTokens, sessionId) {
58
+ const id = sessionId || this.currentSessionId;
59
+ if (!id) {
60
+ throw new Error('No active session. Call startSession() first.');
61
+ }
62
+ const session = this.sessions.get(id);
63
+ if (!session) {
64
+ throw new Error(`Session ${id} not found`);
65
+ }
66
+ // Update token usage
67
+ session.tokenUsage.inputTokens += inputTokens;
68
+ session.tokenUsage.outputTokens += outputTokens;
69
+ session.tokenUsage.totalTokens += inputTokens + outputTokens;
70
+ // Recalculate cost
71
+ session.cost = calculateCost(session.model, session.tokenUsage.inputTokens, session.tokenUsage.outputTokens);
72
+ // Calculate savings vs Sonnet baseline
73
+ session.savings = calculateSavings(session.model, session.tokenUsage.inputTokens, session.tokenUsage.outputTokens);
74
+ }
75
+ /**
76
+ * End current session
77
+ *
78
+ * @param sessionId - Optional session ID (defaults to current)
79
+ */
80
+ endSession(sessionId) {
81
+ const id = sessionId || this.currentSessionId;
82
+ if (!id) {
83
+ throw new Error('No active session to end');
84
+ }
85
+ const session = this.sessions.get(id);
86
+ if (!session) {
87
+ throw new Error(`Session ${id} not found`);
88
+ }
89
+ session.endedAt = new Date().toISOString();
90
+ if (this.autoSave) {
91
+ this.saveToDisk();
92
+ }
93
+ // Clear current session if it's the one we just ended
94
+ if (this.currentSessionId === id) {
95
+ this.currentSessionId = null;
96
+ }
97
+ }
98
+ /**
99
+ * Get session by ID
100
+ */
101
+ getSession(sessionId) {
102
+ return this.sessions.get(sessionId);
103
+ }
104
+ /**
105
+ * Get current session
106
+ */
107
+ getCurrentSession() {
108
+ return this.currentSessionId
109
+ ? this.sessions.get(this.currentSessionId)
110
+ : undefined;
111
+ }
112
+ /**
113
+ * Get all sessions for a specific increment
114
+ *
115
+ * @param incrementId - Increment ID (e.g., '0003')
116
+ * @returns Array of sessions for this increment
117
+ */
118
+ getIncrementSessions(incrementId) {
119
+ return Array.from(this.sessions.values()).filter((s) => s.increment === incrementId);
120
+ }
121
+ /**
122
+ * Get cost report for a specific increment
123
+ *
124
+ * @param incrementId - Increment ID (e.g., '0003')
125
+ * @returns Aggregate cost report
126
+ */
127
+ getIncrementCost(incrementId) {
128
+ const sessions = this.getIncrementSessions(incrementId);
129
+ if (sessions.length === 0) {
130
+ return {
131
+ incrementId,
132
+ totalCost: 0,
133
+ totalSavings: 0,
134
+ totalTokens: 0,
135
+ sessionCount: 0,
136
+ costByModel: {},
137
+ costByAgent: {},
138
+ };
139
+ }
140
+ const report = {
141
+ incrementId,
142
+ totalCost: 0,
143
+ totalSavings: 0,
144
+ totalTokens: 0,
145
+ sessionCount: sessions.length,
146
+ costByModel: {},
147
+ costByAgent: {},
148
+ };
149
+ for (const session of sessions) {
150
+ // Aggregate totals
151
+ report.totalCost += session.cost;
152
+ report.totalSavings += session.savings;
153
+ report.totalTokens += session.tokenUsage.totalTokens;
154
+ // Aggregate by model
155
+ if (!report.costByModel[session.model]) {
156
+ report.costByModel[session.model] = 0;
157
+ }
158
+ report.costByModel[session.model] += session.cost;
159
+ // Aggregate by agent
160
+ if (!report.costByAgent[session.agent]) {
161
+ report.costByAgent[session.agent] = 0;
162
+ }
163
+ report.costByAgent[session.agent] += session.cost;
164
+ }
165
+ return report;
166
+ }
167
+ /**
168
+ * Get total cost across all sessions
169
+ */
170
+ getTotalCost() {
171
+ return Array.from(this.sessions.values()).reduce((sum, session) => sum + session.cost, 0);
172
+ }
173
+ /**
174
+ * Get total savings across all sessions
175
+ */
176
+ getTotalSavings() {
177
+ return Array.from(this.sessions.values()).reduce((sum, session) => sum + session.savings, 0);
178
+ }
179
+ /**
180
+ * Get all sessions
181
+ */
182
+ getAllSessions() {
183
+ return Array.from(this.sessions.values());
184
+ }
185
+ /**
186
+ * Clear all sessions (useful for testing)
187
+ */
188
+ clearSessions() {
189
+ this.sessions.clear();
190
+ this.currentSessionId = null;
191
+ }
192
+ /**
193
+ * Save sessions to disk
194
+ */
195
+ async saveToDisk() {
196
+ try {
197
+ const data = {
198
+ version: '1.0',
199
+ savedAt: new Date().toISOString(),
200
+ sessions: Array.from(this.sessions.entries()).map(([id, session]) => ({
201
+ ...session,
202
+ sessionId: id,
203
+ })),
204
+ };
205
+ await fs.ensureDir(path.dirname(this.logPath));
206
+ await fs.writeJson(this.logPath, data, { spaces: 2 });
207
+ }
208
+ catch (error) {
209
+ throw new Error(`Failed to save cost data: ${error.message}`);
210
+ }
211
+ }
212
+ /**
213
+ * Load sessions from disk
214
+ */
215
+ async loadFromDisk() {
216
+ try {
217
+ if (!(await fs.pathExists(this.logPath))) {
218
+ // No data file yet, that's ok
219
+ return;
220
+ }
221
+ const data = await fs.readJson(this.logPath);
222
+ // Validate version (for future migrations)
223
+ if (data.version !== '1.0') {
224
+ throw new Error(`Unsupported cost data version: ${data.version}`);
225
+ }
226
+ // Load sessions
227
+ this.sessions.clear();
228
+ for (const session of data.sessions) {
229
+ this.sessions.set(session.sessionId, session);
230
+ }
231
+ }
232
+ catch (error) {
233
+ throw new Error(`Failed to load cost data: ${error.message}`);
234
+ }
235
+ }
236
+ /**
237
+ * Generate unique session ID
238
+ */
239
+ generateSessionId() {
240
+ const timestamp = Date.now();
241
+ const random = Math.random().toString(36).substring(2, 9);
242
+ return `session_${timestamp}_${random}`;
243
+ }
244
+ /**
245
+ * Get summary statistics
246
+ */
247
+ getSummary() {
248
+ const sessions = this.getAllSessions();
249
+ if (sessions.length === 0) {
250
+ return {
251
+ totalSessions: 0,
252
+ totalCost: 0,
253
+ totalSavings: 0,
254
+ savingsPercentage: 0,
255
+ mostExpensiveAgent: null,
256
+ cheapestAgent: null,
257
+ };
258
+ }
259
+ const totalCost = this.getTotalCost();
260
+ const totalSavings = this.getTotalSavings();
261
+ const baselineCost = totalCost + totalSavings;
262
+ // Calculate by agent
263
+ const agentCosts = {};
264
+ for (const session of sessions) {
265
+ if (!agentCosts[session.agent]) {
266
+ agentCosts[session.agent] = 0;
267
+ }
268
+ agentCosts[session.agent] += session.cost;
269
+ }
270
+ const sortedAgents = Object.entries(agentCosts).sort(([, a], [, b]) => b - a);
271
+ return {
272
+ totalSessions: sessions.length,
273
+ totalCost,
274
+ totalSavings,
275
+ savingsPercentage: baselineCost > 0 ? (totalSavings / baselineCost) * 100 : 0,
276
+ mostExpensiveAgent: sortedAgents[0]?.[0] || null,
277
+ cheapestAgent: sortedAgents[sortedAgents.length - 1]?.[0] || null,
278
+ };
279
+ }
280
+ }
281
+ //# sourceMappingURL=cost-tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost-tracker.js","sourceRoot":"","sources":["../../src/core/cost-tracker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Model Selector
3
+ *
4
+ * Decision engine that combines agent preferences + phase detection to select
5
+ * the optimal AI model for each task.
6
+ *
7
+ * Decision hierarchy:
8
+ * 1. User override (--model flag) - Always wins
9
+ * 2. Agent preference (from AGENT.md) - Used when not 'auto'
10
+ * 3. Phase detection - Used for 'auto' agents with high confidence
11
+ * 4. Safe default (Sonnet) - Used when confidence is low
12
+ *
13
+ * Achieves 60-70% cost savings by routing execution to Haiku.
14
+ */
15
+ import type { Model, ModelSelectionDecision } from '../types/model-selection';
16
+ import type { ExecutionContext } from './phase-detector';
17
+ import { AgentModelManager } from './agent-model-manager';
18
+ import { PhaseDetector } from './phase-detector';
19
+ export interface ModelSelectionConfig {
20
+ mode: 'auto' | 'balanced' | 'manual';
21
+ forceModel?: Exclude<Model, 'auto'>;
22
+ highConfidenceThreshold: number;
23
+ mediumConfidenceThreshold: number;
24
+ defaultPlanningModel: 'sonnet' | 'opus';
25
+ defaultExecutionModel: 'haiku' | 'sonnet';
26
+ defaultReviewModel: 'sonnet' | 'opus';
27
+ logDecisions: boolean;
28
+ showReasoning: boolean;
29
+ }
30
+ export declare class ModelSelector {
31
+ private agentModelManager;
32
+ private phaseDetector;
33
+ private config;
34
+ constructor(agentModelManager: AgentModelManager, phaseDetector: PhaseDetector, config?: Partial<ModelSelectionConfig>);
35
+ /**
36
+ * Select optimal model for a given task
37
+ *
38
+ * @param prompt - User's prompt/task description
39
+ * @param agent - Agent name (e.g., 'pm', 'frontend', 'architect')
40
+ * @param context - Execution context (command, increment state, etc.)
41
+ * @returns Model selection decision with reasoning
42
+ */
43
+ select(prompt: string, agent: string, context?: ExecutionContext): ModelSelectionDecision;
44
+ /**
45
+ * Log model selection decision (if logging enabled)
46
+ */
47
+ logDecision(decision: ModelSelectionDecision, agent: string): void;
48
+ /**
49
+ * Update configuration
50
+ */
51
+ updateConfig(config: Partial<ModelSelectionConfig>): void;
52
+ /**
53
+ * Get current configuration
54
+ */
55
+ getConfig(): ModelSelectionConfig;
56
+ }
57
+ //# sourceMappingURL=model-selector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-selector.d.ts","sourceRoot":"","sources":["../../src/core/model-selector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAS,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AACrF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,QAAQ,CAAC;IACrC,UAAU,CAAC,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACpC,uBAAuB,EAAE,MAAM,CAAC;IAChC,yBAAyB,EAAE,MAAM,CAAC;IAClC,oBAAoB,EAAE,QAAQ,GAAG,MAAM,CAAC;IACxC,qBAAqB,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC1C,kBAAkB,EAAE,QAAQ,GAAG,MAAM,CAAC;IACtC,YAAY,EAAE,OAAO,CAAC;IACtB,aAAa,EAAE,OAAO,CAAC;CACxB;AAsBD,qBAAa,aAAa;IACxB,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,MAAM,CAAuB;gBAGnC,iBAAiB,EAAE,iBAAiB,EACpC,aAAa,EAAE,aAAa,EAC5B,MAAM,GAAE,OAAO,CAAC,oBAAoB,CAAM;IAO5C;;;;;;;OAOG;IACH,MAAM,CACJ,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,gBAAqB,GAC7B,sBAAsB;IA8CzB;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,sBAAsB,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAalE;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,oBAAoB,CAAC,GAAG,IAAI;IAIzD;;OAEG;IACH,SAAS,IAAI,oBAAoB;CAGlC"}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Model Selector
3
+ *
4
+ * Decision engine that combines agent preferences + phase detection to select
5
+ * the optimal AI model for each task.
6
+ *
7
+ * Decision hierarchy:
8
+ * 1. User override (--model flag) - Always wins
9
+ * 2. Agent preference (from AGENT.md) - Used when not 'auto'
10
+ * 3. Phase detection - Used for 'auto' agents with high confidence
11
+ * 4. Safe default (Sonnet) - Used when confidence is low
12
+ *
13
+ * Achieves 60-70% cost savings by routing execution to Haiku.
14
+ */
15
+ const DEFAULT_CONFIG = {
16
+ mode: 'auto',
17
+ highConfidenceThreshold: 0.7,
18
+ mediumConfidenceThreshold: 0.4,
19
+ defaultPlanningModel: 'sonnet',
20
+ defaultExecutionModel: 'haiku',
21
+ defaultReviewModel: 'sonnet',
22
+ logDecisions: true,
23
+ showReasoning: true,
24
+ };
25
+ /**
26
+ * Phase-to-model mapping (when agent is 'auto')
27
+ */
28
+ const PHASE_MODEL_MAP = {
29
+ planning: 'sonnet',
30
+ execution: 'haiku',
31
+ review: 'sonnet',
32
+ };
33
+ export class ModelSelector {
34
+ constructor(agentModelManager, phaseDetector, config = {}) {
35
+ this.agentModelManager = agentModelManager;
36
+ this.phaseDetector = phaseDetector;
37
+ this.config = { ...DEFAULT_CONFIG, ...config };
38
+ }
39
+ /**
40
+ * Select optimal model for a given task
41
+ *
42
+ * @param prompt - User's prompt/task description
43
+ * @param agent - Agent name (e.g., 'pm', 'frontend', 'architect')
44
+ * @param context - Execution context (command, increment state, etc.)
45
+ * @returns Model selection decision with reasoning
46
+ */
47
+ select(prompt, agent, context = {}) {
48
+ // Step 1: Check explicit user override
49
+ if (this.config.forceModel) {
50
+ return {
51
+ model: this.config.forceModel,
52
+ reason: 'user_override',
53
+ reasoning: `User explicitly forced ${this.config.forceModel} model via --model flag`,
54
+ };
55
+ }
56
+ // Step 2: Load agent preference
57
+ const agentPref = this.agentModelManager.getPreferredModel(agent);
58
+ const costProfile = this.agentModelManager.getCostProfile(agent);
59
+ // If agent has explicit preference (not 'auto'), use it
60
+ if (agentPref !== 'auto') {
61
+ return {
62
+ model: agentPref,
63
+ reason: 'agent_preference',
64
+ reasoning: `Agent '${agent}' prefers ${agentPref} for ${costProfile} work`,
65
+ };
66
+ }
67
+ // Step 3: Detect phase (for 'auto' agents)
68
+ const phaseDetection = this.phaseDetector.detect(prompt, context);
69
+ // Step 4: Apply decision matrix based on confidence
70
+ if (phaseDetection.confidence >= this.config.highConfidenceThreshold) {
71
+ // High confidence - use phase-based model
72
+ return {
73
+ model: PHASE_MODEL_MAP[phaseDetection.phase],
74
+ reason: 'phase_detection',
75
+ confidence: phaseDetection.confidence,
76
+ reasoning: phaseDetection.reasoning,
77
+ };
78
+ }
79
+ // Step 5: Low confidence - default to Sonnet for safety
80
+ return {
81
+ model: 'sonnet',
82
+ reason: 'low_confidence_default',
83
+ confidence: phaseDetection.confidence,
84
+ reasoning: `Low confidence (${(phaseDetection.confidence * 100).toFixed(0)}%), defaulting to Sonnet for safety. Detected: ${phaseDetection.reasoning}`,
85
+ };
86
+ }
87
+ /**
88
+ * Log model selection decision (if logging enabled)
89
+ */
90
+ logDecision(decision, agent) {
91
+ if (!this.config.logDecisions)
92
+ return;
93
+ const timestamp = new Date().toISOString();
94
+ const logMessage = `[${timestamp}] [Model Selection] Agent: ${agent} → ${decision.model} (${decision.reason})`;
95
+ if (this.config.showReasoning) {
96
+ console.log(`${logMessage}\n Reasoning: ${decision.reasoning}`);
97
+ }
98
+ else {
99
+ console.log(logMessage);
100
+ }
101
+ }
102
+ /**
103
+ * Update configuration
104
+ */
105
+ updateConfig(config) {
106
+ this.config = { ...this.config, ...config };
107
+ }
108
+ /**
109
+ * Get current configuration
110
+ */
111
+ getConfig() {
112
+ return { ...this.config };
113
+ }
114
+ }
115
+ //# sourceMappingURL=model-selector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-selector.js","sourceRoot":"","sources":["../../src/core/model-selector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Phase Detector
3
+ *
4
+ * Multi-signal phase detection algorithm that analyzes user prompts and context
5
+ * to determine whether work is in planning, execution, or review phase.
6
+ *
7
+ * Uses 4 signals with weighted scoring:
8
+ * 1. Keyword analysis (40%) - Planning/execution/review keywords
9
+ * 2. Command analysis (30%) - Slash commands hint at phase
10
+ * 3. Context analysis (20%) - Increment state, file types
11
+ * 4. Explicit hints (10%) - User explicitly states phase
12
+ *
13
+ * Target accuracy: >95%
14
+ */
15
+ import type { Phase } from '../types/model-selection';
16
+ export interface PhaseDetectionResult {
17
+ phase: Phase;
18
+ confidence: number;
19
+ signals: {
20
+ keywords: string[];
21
+ command?: string;
22
+ context: string[];
23
+ };
24
+ reasoning: string;
25
+ }
26
+ export interface ExecutionContext {
27
+ command?: string;
28
+ incrementState?: 'backlog' | 'planned' | 'in-progress' | 'completed' | 'closed';
29
+ previousPhases?: Phase[];
30
+ filesModified?: string[];
31
+ }
32
+ export declare class PhaseDetector {
33
+ private readonly planningKeywords;
34
+ private readonly executionKeywords;
35
+ private readonly reviewKeywords;
36
+ private readonly commandPhaseMap;
37
+ /**
38
+ * Detect phase from user prompt and execution context
39
+ */
40
+ detect(prompt: string, context?: ExecutionContext): PhaseDetectionResult;
41
+ /**
42
+ * Analyze keywords in prompt
43
+ */
44
+ private analyzeKeywords;
45
+ /**
46
+ * Analyze command hints
47
+ */
48
+ private analyzeCommand;
49
+ /**
50
+ * Analyze execution context
51
+ */
52
+ private analyzeContext;
53
+ /**
54
+ * Analyze explicit hints in prompt
55
+ */
56
+ private analyzeHints;
57
+ /**
58
+ * Generate human-readable reasoning
59
+ */
60
+ private generateReasoning;
61
+ }
62
+ //# sourceMappingURL=phase-detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"phase-detector.d.ts","sourceRoot":"","sources":["../../src/core/phase-detector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AAEtD,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,KAAK,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE;QACP,QAAQ,EAAE,MAAM,EAAE,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,EAAE,CAAC;KACnB,CAAC;IACF,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,aAAa,GAAG,WAAW,GAAG,QAAQ,CAAC;IAChF,cAAc,CAAC,EAAE,KAAK,EAAE,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,qBAAa,aAAa;IAExB,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAK/B;IAEF,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAKhC;IAEF,OAAO,CAAC,QAAQ,CAAC,cAAc,CAI7B;IAGF,OAAO,CAAC,QAAQ,CAAC,eAAe,CAU9B;IAEF;;OAEG;IACH,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,oBAAoB;IA4C5E;;OAEG;IACH,OAAO,CAAC,eAAe;IA4CvB;;OAEG;IACH,OAAO,CAAC,cAAc;IActB;;OAEG;IACH,OAAO,CAAC,cAAc;IAuDtB;;OAEG;IACH,OAAO,CAAC,YAAY;IAwBpB;;OAEG;IACH,OAAO,CAAC,iBAAiB;CAuC1B"}