@ai-sdlc/orchestrator 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (203) hide show
  1. package/dist/adapters.d.ts +60 -0
  2. package/dist/adapters.js +160 -0
  3. package/dist/admission.d.ts +49 -0
  4. package/dist/admission.js +90 -0
  5. package/dist/analysis/analyzer.d.ts +10 -0
  6. package/dist/analysis/analyzer.js +67 -0
  7. package/dist/analysis/complexity-scorer.d.ts +24 -0
  8. package/dist/analysis/complexity-scorer.js +39 -0
  9. package/dist/analysis/context-builder.d.ts +14 -0
  10. package/dist/analysis/context-builder.js +79 -0
  11. package/dist/analysis/convention-detector.d.ts +9 -0
  12. package/dist/analysis/convention-detector.js +177 -0
  13. package/dist/analysis/dependency-parser.d.ts +17 -0
  14. package/dist/analysis/dependency-parser.js +167 -0
  15. package/dist/analysis/file-walker.d.ts +18 -0
  16. package/dist/analysis/file-walker.js +158 -0
  17. package/dist/analysis/hotspot-analyzer.d.ts +28 -0
  18. package/dist/analysis/hotspot-analyzer.js +85 -0
  19. package/dist/analysis/index.d.ts +13 -0
  20. package/dist/analysis/index.js +12 -0
  21. package/dist/analysis/pattern-detector.d.ts +10 -0
  22. package/dist/analysis/pattern-detector.js +86 -0
  23. package/dist/analysis/types.d.ts +94 -0
  24. package/dist/analysis/types.js +5 -0
  25. package/dist/audit-archival.d.ts +48 -0
  26. package/dist/audit-archival.js +72 -0
  27. package/dist/audit-export.d.ts +45 -0
  28. package/dist/audit-export.js +100 -0
  29. package/dist/audit-extended.d.ts +28 -0
  30. package/dist/audit-extended.js +38 -0
  31. package/dist/audit-scheduler.d.ts +32 -0
  32. package/dist/audit-scheduler.js +52 -0
  33. package/dist/audit-sqlite-sink.d.ts +11 -0
  34. package/dist/audit-sqlite-sink.js +51 -0
  35. package/dist/autonomy-tracker.d.ts +76 -0
  36. package/dist/autonomy-tracker.js +277 -0
  37. package/dist/check-runs.d.ts +37 -0
  38. package/dist/check-runs.js +72 -0
  39. package/dist/cli/commands/agents.d.ts +6 -0
  40. package/dist/cli/commands/agents.js +33 -0
  41. package/dist/cli/commands/complexity.d.ts +6 -0
  42. package/dist/cli/commands/complexity.js +35 -0
  43. package/dist/cli/commands/cost.d.ts +6 -0
  44. package/dist/cli/commands/cost.js +53 -0
  45. package/dist/cli/commands/dashboard.d.ts +9 -0
  46. package/dist/cli/commands/dashboard.js +50 -0
  47. package/dist/cli/commands/health.d.ts +6 -0
  48. package/dist/cli/commands/health.js +33 -0
  49. package/dist/cli/commands/init.d.ts +6 -0
  50. package/dist/cli/commands/init.js +127 -0
  51. package/dist/cli/commands/routing.d.ts +6 -0
  52. package/dist/cli/commands/routing.js +46 -0
  53. package/dist/cli/commands/run.d.ts +6 -0
  54. package/dist/cli/commands/run.js +36 -0
  55. package/dist/cli/commands/start.d.ts +6 -0
  56. package/dist/cli/commands/start.js +26 -0
  57. package/dist/cli/commands/status.d.ts +6 -0
  58. package/dist/cli/commands/status.js +34 -0
  59. package/dist/cli/dashboard-renderer.d.ts +24 -0
  60. package/dist/cli/dashboard-renderer.js +129 -0
  61. package/dist/cli/formatters/index.d.ts +6 -0
  62. package/dist/cli/formatters/index.js +18 -0
  63. package/dist/cli/formatters/json.d.ts +5 -0
  64. package/dist/cli/formatters/json.js +7 -0
  65. package/dist/cli/formatters/minimal.d.ts +5 -0
  66. package/dist/cli/formatters/minimal.js +36 -0
  67. package/dist/cli/formatters/table.d.ts +5 -0
  68. package/dist/cli/formatters/table.js +184 -0
  69. package/dist/cli/index.d.ts +6 -0
  70. package/dist/cli/index.js +35 -0
  71. package/dist/compliance-extended.d.ts +41 -0
  72. package/dist/compliance-extended.js +58 -0
  73. package/dist/config.d.ts +26 -0
  74. package/dist/config.js +66 -0
  75. package/dist/context-enrichment.d.ts +33 -0
  76. package/dist/context-enrichment.js +125 -0
  77. package/dist/cost-governance.d.ts +22 -0
  78. package/dist/cost-governance.js +106 -0
  79. package/dist/cost-tracker.d.ts +75 -0
  80. package/dist/cost-tracker.js +177 -0
  81. package/dist/defaults.d.ts +140 -0
  82. package/dist/defaults.js +218 -0
  83. package/dist/deploy/flyio-target.d.ts +19 -0
  84. package/dist/deploy/flyio-target.js +114 -0
  85. package/dist/deploy/index.d.ts +15 -0
  86. package/dist/deploy/index.js +11 -0
  87. package/dist/deploy/kubernetes-target.d.ts +25 -0
  88. package/dist/deploy/kubernetes-target.js +124 -0
  89. package/dist/deploy/metrics-collector.d.ts +31 -0
  90. package/dist/deploy/metrics-collector.js +75 -0
  91. package/dist/deploy/rollout-controller.d.ts +42 -0
  92. package/dist/deploy/rollout-controller.js +192 -0
  93. package/dist/deploy/rollout-types.d.ts +86 -0
  94. package/dist/deploy/rollout-types.js +5 -0
  95. package/dist/deploy/types.d.ts +47 -0
  96. package/dist/deploy/types.js +5 -0
  97. package/dist/deploy/vercel-target.d.ts +16 -0
  98. package/dist/deploy/vercel-target.js +115 -0
  99. package/dist/discovery.d.ts +26 -0
  100. package/dist/discovery.js +46 -0
  101. package/dist/episodic-enhanced.d.ts +88 -0
  102. package/dist/episodic-enhanced.js +212 -0
  103. package/dist/execute.d.ts +81 -0
  104. package/dist/execute.js +703 -0
  105. package/dist/fix-ci.d.ts +61 -0
  106. package/dist/fix-ci.js +380 -0
  107. package/dist/handoff-executor.d.ts +61 -0
  108. package/dist/handoff-executor.js +119 -0
  109. package/dist/index.d.ts +70 -0
  110. package/dist/index.js +87 -0
  111. package/dist/instrumented.d.ts +27 -0
  112. package/dist/instrumented.js +34 -0
  113. package/dist/logger.d.ts +17 -0
  114. package/dist/logger.js +37 -0
  115. package/dist/multi-repo/impact-analyzer.d.ts +22 -0
  116. package/dist/multi-repo/impact-analyzer.js +95 -0
  117. package/dist/multi-repo/index.d.ts +5 -0
  118. package/dist/multi-repo/index.js +4 -0
  119. package/dist/multi-repo/monorepo-detector.d.ts +16 -0
  120. package/dist/multi-repo/monorepo-detector.js +246 -0
  121. package/dist/multi-repo/service-map-builder.d.ts +24 -0
  122. package/dist/multi-repo/service-map-builder.js +235 -0
  123. package/dist/multi-repo/types.d.ts +54 -0
  124. package/dist/multi-repo/types.js +5 -0
  125. package/dist/notifications/index.d.ts +4 -0
  126. package/dist/notifications/index.js +4 -0
  127. package/dist/notifications/notification-router.d.ts +62 -0
  128. package/dist/notifications/notification-router.js +206 -0
  129. package/dist/notifications/slack-messenger.d.ts +26 -0
  130. package/dist/notifications/slack-messenger.js +69 -0
  131. package/dist/notifications/teams-messenger.d.ts +21 -0
  132. package/dist/notifications/teams-messenger.js +85 -0
  133. package/dist/notifications.d.ts +13 -0
  134. package/dist/notifications.js +15 -0
  135. package/dist/orchestration.d.ts +20 -0
  136. package/dist/orchestration.js +53 -0
  137. package/dist/orchestrator.d.ts +160 -0
  138. package/dist/orchestrator.js +372 -0
  139. package/dist/otel-exporter.d.ts +37 -0
  140. package/dist/otel-exporter.js +128 -0
  141. package/dist/plugin.d.ts +45 -0
  142. package/dist/plugin.js +8 -0
  143. package/dist/policy-evaluators.d.ts +40 -0
  144. package/dist/policy-evaluators.js +57 -0
  145. package/dist/process-escalation.d.ts +38 -0
  146. package/dist/process-escalation.js +129 -0
  147. package/dist/progressive-gates.d.ts +54 -0
  148. package/dist/progressive-gates.js +135 -0
  149. package/dist/provenance.d.ts +29 -0
  150. package/dist/provenance.js +61 -0
  151. package/dist/reconcilers.d.ts +28 -0
  152. package/dist/reconcilers.js +37 -0
  153. package/dist/runners/claude-code.d.ts +17 -0
  154. package/dist/runners/claude-code.js +200 -0
  155. package/dist/runners/codex.d.ts +19 -0
  156. package/dist/runners/codex.js +153 -0
  157. package/dist/runners/copilot-stub.d.ts +9 -0
  158. package/dist/runners/copilot-stub.js +15 -0
  159. package/dist/runners/copilot.d.ts +15 -0
  160. package/dist/runners/copilot.js +119 -0
  161. package/dist/runners/cursor-stub.d.ts +9 -0
  162. package/dist/runners/cursor-stub.js +15 -0
  163. package/dist/runners/cursor.d.ts +20 -0
  164. package/dist/runners/cursor.js +140 -0
  165. package/dist/runners/devin-stub.d.ts +9 -0
  166. package/dist/runners/devin-stub.js +15 -0
  167. package/dist/runners/generic-llm.d.ts +51 -0
  168. package/dist/runners/generic-llm.js +125 -0
  169. package/dist/runners/index.d.ts +8 -0
  170. package/dist/runners/index.js +7 -0
  171. package/dist/runners/runner-registry.d.ts +50 -0
  172. package/dist/runners/runner-registry.js +156 -0
  173. package/dist/runners/types.d.ts +59 -0
  174. package/dist/runners/types.js +7 -0
  175. package/dist/security.d.ts +51 -0
  176. package/dist/security.js +70 -0
  177. package/dist/shared.d.ts +134 -0
  178. package/dist/shared.js +284 -0
  179. package/dist/state/index.d.ts +4 -0
  180. package/dist/state/index.js +3 -0
  181. package/dist/state/schema.d.ts +16 -0
  182. package/dist/state/schema.js +264 -0
  183. package/dist/state/store.d.ts +109 -0
  184. package/dist/state/store.js +644 -0
  185. package/dist/state/types.d.ts +190 -0
  186. package/dist/state/types.js +5 -0
  187. package/dist/structured-logger.d.ts +20 -0
  188. package/dist/structured-logger.js +64 -0
  189. package/dist/task-decomposer.d.ts +61 -0
  190. package/dist/task-decomposer.js +265 -0
  191. package/dist/telemetry-extended.d.ts +24 -0
  192. package/dist/telemetry-extended.js +31 -0
  193. package/dist/types.d.ts +9 -0
  194. package/dist/types.js +7 -0
  195. package/dist/validate-agent-output.d.ts +30 -0
  196. package/dist/validate-agent-output.js +81 -0
  197. package/dist/validate-issue.d.ts +25 -0
  198. package/dist/validate-issue.js +102 -0
  199. package/dist/watch.d.ts +43 -0
  200. package/dist/watch.js +99 -0
  201. package/dist/webhook-manager.d.ts +38 -0
  202. package/dist/webhook-manager.js +66 -0
  203. package/package.json +59 -0
@@ -0,0 +1,76 @@
1
+ /**
2
+ * AutonomyTracker — computes real agent metrics from pipeline run history,
3
+ * evaluates promotion/demotion eligibility, and persists state changes.
4
+ *
5
+ * Replaces the hardcoded `totalTasksCompleted: 1` in execute.ts.
6
+ * RFC reference: Lines 264-280 (autonomy metrics).
7
+ */
8
+ import type { StateStore } from './state/store.js';
9
+ export interface AgentPerformanceMetrics {
10
+ totalTasks: number;
11
+ successCount: number;
12
+ failureCount: number;
13
+ successRate: number;
14
+ prApprovalRate: number;
15
+ rollbackCount: number;
16
+ securityIncidents: number;
17
+ avgDurationMs: number;
18
+ avgCostUsd: number;
19
+ recentFailures: number;
20
+ timeAtLevelMs: number;
21
+ }
22
+ export interface PromotionEvaluation {
23
+ eligible: boolean;
24
+ fromLevel: number;
25
+ toLevel: number;
26
+ unmetConditions: string[];
27
+ metrics: AgentPerformanceMetrics;
28
+ }
29
+ export interface DemotionEvaluation {
30
+ shouldDemote: boolean;
31
+ fromLevel: number;
32
+ toLevel: number;
33
+ reasons: string[];
34
+ metrics: AgentPerformanceMetrics;
35
+ }
36
+ export interface PromotionProximity {
37
+ currentLevel: number;
38
+ nextLevel: number;
39
+ conditionProgress: Array<{
40
+ condition: string;
41
+ current: number;
42
+ required: number;
43
+ met: boolean;
44
+ }>;
45
+ }
46
+ export declare class AutonomyTracker {
47
+ private store;
48
+ constructor(store: StateStore);
49
+ /**
50
+ * Record a task outcome and update the autonomy ledger.
51
+ */
52
+ recordTaskOutcome(agentName: string, success: boolean, opts?: {
53
+ durationMs?: number;
54
+ costUsd?: number;
55
+ prApproved?: boolean;
56
+ rollback?: boolean;
57
+ securityIncident?: boolean;
58
+ }): void;
59
+ /**
60
+ * Get computed performance metrics for an agent.
61
+ */
62
+ getAgentMetrics(agentName: string): AgentPerformanceMetrics;
63
+ /**
64
+ * Evaluate promotion eligibility and persist if promoted.
65
+ */
66
+ evaluateAndPersistPromotion(agentName: string): PromotionEvaluation;
67
+ /**
68
+ * Evaluate demotion triggers and persist if demoted.
69
+ */
70
+ evaluateAndPersistDemotion(agentName: string): DemotionEvaluation;
71
+ /**
72
+ * Get proximity to next promotion (for dashboard/reporting).
73
+ */
74
+ getPromotionProximity(agentName: string): PromotionProximity;
75
+ }
76
+ //# sourceMappingURL=autonomy-tracker.d.ts.map
@@ -0,0 +1,277 @@
1
+ /**
2
+ * AutonomyTracker — computes real agent metrics from pipeline run history,
3
+ * evaluates promotion/demotion eligibility, and persists state changes.
4
+ *
5
+ * Replaces the hardcoded `totalTasksCompleted: 1` in execute.ts.
6
+ * RFC reference: Lines 264-280 (autonomy metrics).
7
+ */
8
+ /** Minimum tasks required per level for promotion. */
9
+ const PROMOTION_TASK_THRESHOLDS = {
10
+ 0: 3,
11
+ 1: 10,
12
+ 2: 25,
13
+ 3: 50,
14
+ };
15
+ /** Minimum success rate required per level for promotion. */
16
+ const PROMOTION_SUCCESS_RATE = {
17
+ 0: 0.8,
18
+ 1: 0.85,
19
+ 2: 0.9,
20
+ 3: 0.95,
21
+ };
22
+ /** Minimum time at level (ms) before promotion. */
23
+ const MIN_TIME_AT_LEVEL_MS = 7 * 24 * 60 * 60 * 1000; // 7 days
24
+ export class AutonomyTracker {
25
+ store;
26
+ constructor(store) {
27
+ this.store = store;
28
+ }
29
+ /**
30
+ * Record a task outcome and update the autonomy ledger.
31
+ */
32
+ recordTaskOutcome(agentName, success, opts) {
33
+ const existing = this.store.getAutonomyLedger(agentName);
34
+ const now = new Date().toISOString();
35
+ const entry = {
36
+ agentName,
37
+ currentLevel: existing?.currentLevel ?? 0,
38
+ totalTasks: (existing?.totalTasks ?? 0) + 1,
39
+ successCount: (existing?.successCount ?? 0) + (success ? 1 : 0),
40
+ failureCount: (existing?.failureCount ?? 0) + (success ? 0 : 1),
41
+ lastTaskAt: now,
42
+ metrics: existing?.metrics,
43
+ prApprovalRate: existing?.prApprovalRate ?? 0,
44
+ rollbackCount: (existing?.rollbackCount ?? 0) + (opts?.rollback ? 1 : 0),
45
+ securityIncidents: (existing?.securityIncidents ?? 0) + (opts?.securityIncident ? 1 : 0),
46
+ promotedAt: existing?.promotedAt,
47
+ demotedAt: existing?.demotedAt,
48
+ timeAtLevelMs: existing?.timeAtLevelMs ?? 0,
49
+ };
50
+ // Update PR approval rate (running average)
51
+ if (opts?.prApproved !== undefined) {
52
+ const totalPRs = entry.totalTasks;
53
+ const prevApproved = Math.round((existing?.prApprovalRate ?? 0) * (existing?.totalTasks ?? 0));
54
+ const newApproved = prevApproved + (opts.prApproved ? 1 : 0);
55
+ entry.prApprovalRate = totalPRs > 0 ? newApproved / totalPRs : 0;
56
+ }
57
+ // Update time at level
58
+ if (existing?.lastTaskAt) {
59
+ const elapsed = new Date(now).getTime() - new Date(existing.lastTaskAt).getTime();
60
+ entry.timeAtLevelMs = (existing.timeAtLevelMs ?? 0) + elapsed;
61
+ }
62
+ this.store.upsertAutonomyLedger(entry);
63
+ }
64
+ /**
65
+ * Get computed performance metrics for an agent.
66
+ */
67
+ getAgentMetrics(agentName) {
68
+ const ledger = this.store.getAutonomyLedger(agentName);
69
+ if (!ledger) {
70
+ return {
71
+ totalTasks: 0,
72
+ successCount: 0,
73
+ failureCount: 0,
74
+ successRate: 0,
75
+ prApprovalRate: 0,
76
+ rollbackCount: 0,
77
+ securityIncidents: 0,
78
+ avgDurationMs: 0,
79
+ avgCostUsd: 0,
80
+ recentFailures: 0,
81
+ timeAtLevelMs: 0,
82
+ };
83
+ }
84
+ // Get recent pipeline runs for duration/cost stats
85
+ const runs = this.store
86
+ .getPipelineRuns(undefined, 100)
87
+ .filter((r) => r.agentName === agentName);
88
+ const durations = runs
89
+ .filter((r) => r.startedAt && r.completedAt)
90
+ .map((r) => new Date(r.completedAt).getTime() - new Date(r.startedAt).getTime());
91
+ const costs = runs.filter((r) => r.costUsd != null && r.costUsd > 0).map((r) => r.costUsd);
92
+ // Count recent failures (last 7 days)
93
+ const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString();
94
+ const recentFailures = runs.filter((r) => r.status === 'failed' && r.startedAt && r.startedAt >= sevenDaysAgo).length;
95
+ return {
96
+ totalTasks: ledger.totalTasks,
97
+ successCount: ledger.successCount,
98
+ failureCount: ledger.failureCount,
99
+ successRate: ledger.totalTasks > 0 ? ledger.successCount / ledger.totalTasks : 0,
100
+ prApprovalRate: ledger.prApprovalRate ?? 0,
101
+ rollbackCount: ledger.rollbackCount ?? 0,
102
+ securityIncidents: ledger.securityIncidents ?? 0,
103
+ avgDurationMs: durations.length > 0 ? durations.reduce((a, b) => a + b, 0) / durations.length : 0,
104
+ avgCostUsd: costs.length > 0 ? costs.reduce((a, b) => a + b, 0) / costs.length : 0,
105
+ recentFailures,
106
+ timeAtLevelMs: ledger.timeAtLevelMs ?? 0,
107
+ };
108
+ }
109
+ /**
110
+ * Evaluate promotion eligibility and persist if promoted.
111
+ */
112
+ evaluateAndPersistPromotion(agentName) {
113
+ const metrics = this.getAgentMetrics(agentName);
114
+ const ledger = this.store.getAutonomyLedger(agentName);
115
+ const currentLevel = ledger?.currentLevel ?? 0;
116
+ const nextLevel = currentLevel + 1;
117
+ if (nextLevel > 4) {
118
+ return {
119
+ eligible: false,
120
+ fromLevel: currentLevel,
121
+ toLevel: currentLevel,
122
+ unmetConditions: ['Already at maximum level'],
123
+ metrics,
124
+ };
125
+ }
126
+ const unmetConditions = [];
127
+ // Check task threshold
128
+ const taskThreshold = PROMOTION_TASK_THRESHOLDS[currentLevel] ?? 50;
129
+ if (metrics.totalTasks < taskThreshold) {
130
+ unmetConditions.push(`Need ${taskThreshold} tasks, have ${metrics.totalTasks}`);
131
+ }
132
+ // Check success rate
133
+ const rateThreshold = PROMOTION_SUCCESS_RATE[currentLevel] ?? 0.9;
134
+ if (metrics.successRate < rateThreshold) {
135
+ unmetConditions.push(`Need ${Math.round(rateThreshold * 100)}% success rate, have ${Math.round(metrics.successRate * 100)}%`);
136
+ }
137
+ // Check no recent security incidents
138
+ if (metrics.securityIncidents > 0) {
139
+ unmetConditions.push(`${metrics.securityIncidents} security incidents must be resolved`);
140
+ }
141
+ // Check time at level
142
+ if (metrics.timeAtLevelMs < MIN_TIME_AT_LEVEL_MS) {
143
+ const daysNeeded = Math.ceil(MIN_TIME_AT_LEVEL_MS / (24 * 60 * 60 * 1000));
144
+ const daysAt = Math.floor(metrics.timeAtLevelMs / (24 * 60 * 60 * 1000));
145
+ unmetConditions.push(`Need ${daysNeeded}d at level, have ${daysAt}d`);
146
+ }
147
+ const eligible = unmetConditions.length === 0;
148
+ if (eligible && ledger) {
149
+ // Persist promotion
150
+ const now = new Date().toISOString();
151
+ this.store.upsertAutonomyLedger({
152
+ ...ledger,
153
+ currentLevel: nextLevel,
154
+ promotedAt: now,
155
+ timeAtLevelMs: 0, // Reset time at level
156
+ });
157
+ // Record autonomy event
158
+ this.store.saveAutonomyEvent({
159
+ agentName,
160
+ eventType: 'promotion',
161
+ fromLevel: currentLevel,
162
+ toLevel: nextLevel,
163
+ trigger: 'auto-promotion',
164
+ metricsSnapshot: JSON.stringify(metrics),
165
+ });
166
+ }
167
+ return {
168
+ eligible,
169
+ fromLevel: currentLevel,
170
+ toLevel: eligible ? nextLevel : currentLevel,
171
+ unmetConditions,
172
+ metrics,
173
+ };
174
+ }
175
+ /**
176
+ * Evaluate demotion triggers and persist if demoted.
177
+ */
178
+ evaluateAndPersistDemotion(agentName) {
179
+ const metrics = this.getAgentMetrics(agentName);
180
+ const ledger = this.store.getAutonomyLedger(agentName);
181
+ const currentLevel = ledger?.currentLevel ?? 0;
182
+ if (currentLevel === 0) {
183
+ return {
184
+ shouldDemote: false,
185
+ fromLevel: 0,
186
+ toLevel: 0,
187
+ reasons: [],
188
+ metrics,
189
+ };
190
+ }
191
+ const reasons = [];
192
+ // Demotion trigger: high recent failure rate
193
+ if (metrics.recentFailures >= 3) {
194
+ reasons.push(`${metrics.recentFailures} recent failures in 7 days`);
195
+ }
196
+ // Demotion trigger: security incident
197
+ if (metrics.securityIncidents > 0) {
198
+ reasons.push(`${metrics.securityIncidents} security incident(s)`);
199
+ }
200
+ // Demotion trigger: rollbacks
201
+ if (metrics.rollbackCount >= 2) {
202
+ reasons.push(`${metrics.rollbackCount} rollbacks`);
203
+ }
204
+ // Demotion trigger: success rate dropped below threshold
205
+ if (metrics.totalTasks >= 5 && metrics.successRate < 0.6) {
206
+ reasons.push(`Success rate dropped to ${Math.round(metrics.successRate * 100)}%`);
207
+ }
208
+ const shouldDemote = reasons.length > 0;
209
+ const toLevel = shouldDemote ? Math.max(0, currentLevel - 1) : currentLevel;
210
+ if (shouldDemote && ledger) {
211
+ const now = new Date().toISOString();
212
+ this.store.upsertAutonomyLedger({
213
+ ...ledger,
214
+ currentLevel: toLevel,
215
+ demotedAt: now,
216
+ timeAtLevelMs: 0,
217
+ });
218
+ this.store.saveAutonomyEvent({
219
+ agentName,
220
+ eventType: 'demotion',
221
+ fromLevel: currentLevel,
222
+ toLevel,
223
+ trigger: reasons.join('; '),
224
+ metricsSnapshot: JSON.stringify(metrics),
225
+ });
226
+ }
227
+ return {
228
+ shouldDemote,
229
+ fromLevel: currentLevel,
230
+ toLevel,
231
+ reasons,
232
+ metrics,
233
+ };
234
+ }
235
+ /**
236
+ * Get proximity to next promotion (for dashboard/reporting).
237
+ */
238
+ getPromotionProximity(agentName) {
239
+ const metrics = this.getAgentMetrics(agentName);
240
+ const ledger = this.store.getAutonomyLedger(agentName);
241
+ const currentLevel = ledger?.currentLevel ?? 0;
242
+ const nextLevel = Math.min(currentLevel + 1, 4);
243
+ const taskThreshold = PROMOTION_TASK_THRESHOLDS[currentLevel] ?? 50;
244
+ const rateThreshold = PROMOTION_SUCCESS_RATE[currentLevel] ?? 0.9;
245
+ return {
246
+ currentLevel,
247
+ nextLevel,
248
+ conditionProgress: [
249
+ {
250
+ condition: 'Tasks completed',
251
+ current: metrics.totalTasks,
252
+ required: taskThreshold,
253
+ met: metrics.totalTasks >= taskThreshold,
254
+ },
255
+ {
256
+ condition: 'Success rate',
257
+ current: Math.round(metrics.successRate * 100),
258
+ required: Math.round(rateThreshold * 100),
259
+ met: metrics.successRate >= rateThreshold,
260
+ },
261
+ {
262
+ condition: 'No security incidents',
263
+ current: metrics.securityIncidents,
264
+ required: 0,
265
+ met: metrics.securityIncidents === 0,
266
+ },
267
+ {
268
+ condition: 'Time at level (days)',
269
+ current: Math.floor(metrics.timeAtLevelMs / (24 * 60 * 60 * 1000)),
270
+ required: Math.ceil(MIN_TIME_AT_LEVEL_MS / (24 * 60 * 60 * 1000)),
271
+ met: metrics.timeAtLevelMs >= MIN_TIME_AT_LEVEL_MS,
272
+ },
273
+ ],
274
+ };
275
+ }
276
+ }
277
+ //# sourceMappingURL=autonomy-tracker.js.map
@@ -0,0 +1,37 @@
1
+ /**
2
+ * GitHub Check Run integration via `gh` CLI.
3
+ * Creates one check run per gate result. Falls back gracefully when `gh` is unavailable.
4
+ */
5
+ export interface CheckRunInput {
6
+ name: string;
7
+ headSha: string;
8
+ status: 'queued' | 'in_progress' | 'completed';
9
+ conclusion?: 'success' | 'failure' | 'neutral' | 'skipped';
10
+ title?: string;
11
+ summary?: string;
12
+ }
13
+ /**
14
+ * Create a GitHub Check Run for a gate result.
15
+ */
16
+ export declare function createCheckRun(input: CheckRunInput): Promise<{
17
+ success: boolean;
18
+ error?: string;
19
+ }>;
20
+ /**
21
+ * Update an existing GitHub Check Run.
22
+ */
23
+ export declare function updateCheckRun(checkRunId: number, input: Partial<CheckRunInput>): Promise<{
24
+ success: boolean;
25
+ error?: string;
26
+ }>;
27
+ export interface GateResult {
28
+ gate: string;
29
+ verdict: 'pass' | 'fail' | 'skip';
30
+ message?: string;
31
+ }
32
+ /**
33
+ * Report gate results as GitHub Check Runs.
34
+ * Creates one check run per gate result. Falls back silently on failure.
35
+ */
36
+ export declare function reportGateCheckRuns(headSha: string, gateResults: GateResult[]): Promise<void>;
37
+ //# sourceMappingURL=check-runs.d.ts.map
@@ -0,0 +1,72 @@
1
+ /**
2
+ * GitHub Check Run integration via `gh` CLI.
3
+ * Creates one check run per gate result. Falls back gracefully when `gh` is unavailable.
4
+ */
5
+ import { execFile } from 'node:child_process';
6
+ import { promisify } from 'node:util';
7
+ import { DEFAULT_GH_CLI_TIMEOUT_MS } from './defaults.js';
8
+ const execFileAsync = promisify(execFile);
9
+ async function ghApiCall(method, endpoint, body) {
10
+ try {
11
+ const args = ['api', endpoint, '--method', method];
12
+ for (const [key, value] of Object.entries(body)) {
13
+ args.push('-f', `${key}=${String(value)}`);
14
+ }
15
+ await execFileAsync('gh', args, { timeout: DEFAULT_GH_CLI_TIMEOUT_MS });
16
+ return { success: true };
17
+ }
18
+ catch (err) {
19
+ const message = err instanceof Error ? err.message : String(err);
20
+ return { success: false, error: message };
21
+ }
22
+ }
23
+ /**
24
+ * Create a GitHub Check Run for a gate result.
25
+ */
26
+ export async function createCheckRun(input) {
27
+ const body = {
28
+ name: input.name,
29
+ head_sha: input.headSha,
30
+ status: input.status,
31
+ };
32
+ if (input.conclusion)
33
+ body.conclusion = input.conclusion;
34
+ if (input.title || input.summary) {
35
+ body['output[title]'] = input.title ?? input.name;
36
+ body['output[summary]'] = input.summary ?? '';
37
+ }
38
+ return ghApiCall('POST', 'repos/{owner}/{repo}/check-runs', body);
39
+ }
40
+ /**
41
+ * Update an existing GitHub Check Run.
42
+ */
43
+ export async function updateCheckRun(checkRunId, input) {
44
+ const body = {};
45
+ if (input.status)
46
+ body.status = input.status;
47
+ if (input.conclusion)
48
+ body.conclusion = input.conclusion;
49
+ if (input.title || input.summary) {
50
+ body['output[title]'] = input.title ?? '';
51
+ body['output[summary]'] = input.summary ?? '';
52
+ }
53
+ return ghApiCall('PATCH', `repos/{owner}/{repo}/check-runs/${checkRunId}`, body);
54
+ }
55
+ /**
56
+ * Report gate results as GitHub Check Runs.
57
+ * Creates one check run per gate result. Falls back silently on failure.
58
+ */
59
+ export async function reportGateCheckRuns(headSha, gateResults) {
60
+ for (const result of gateResults) {
61
+ const conclusion = result.verdict === 'pass' ? 'success' : result.verdict === 'fail' ? 'failure' : 'neutral';
62
+ await createCheckRun({
63
+ name: `AI-SDLC: ${result.gate}`,
64
+ headSha,
65
+ status: 'completed',
66
+ conclusion,
67
+ title: `Gate: ${result.gate}`,
68
+ summary: result.message ?? `Gate ${result.gate}: ${result.verdict}`,
69
+ });
70
+ }
71
+ }
72
+ //# sourceMappingURL=check-runs.js.map
@@ -0,0 +1,6 @@
1
+ /**
2
+ * ai-sdlc agents [name] — show agent roster, autonomy levels, performance.
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare const agentsCommand: Command;
6
+ //# sourceMappingURL=agents.d.ts.map
@@ -0,0 +1,33 @@
1
+ /**
2
+ * ai-sdlc agents [name] — show agent roster, autonomy levels, performance.
3
+ */
4
+ import { Command } from 'commander';
5
+ import { Orchestrator } from '../../orchestrator.js';
6
+ import { formatOutput } from '../formatters/index.js';
7
+ export const agentsCommand = new Command('agents')
8
+ .description('Show agent roster with autonomy levels and performance')
9
+ .argument('[name]', 'Filter by agent name')
10
+ .option('--state <path>', 'SQLite state database path')
11
+ .action(async (name, opts, cmd) => {
12
+ const globalOpts = cmd.parent?.opts() ?? {};
13
+ const format = globalOpts.format ?? 'table';
14
+ const orchestrator = new Orchestrator({
15
+ configDir: globalOpts.config,
16
+ statePath: opts.state,
17
+ });
18
+ try {
19
+ let agents = await orchestrator.agents();
20
+ if (name) {
21
+ agents = agents.filter((a) => a.agentName === name);
22
+ }
23
+ console.log(formatOutput(format, { type: 'agents', agents }));
24
+ }
25
+ catch (err) {
26
+ console.error(err instanceof Error ? err.message : String(err));
27
+ process.exitCode = 1;
28
+ }
29
+ finally {
30
+ orchestrator.close();
31
+ }
32
+ });
33
+ //# sourceMappingURL=agents.js.map
@@ -0,0 +1,6 @@
1
+ /**
2
+ * ai-sdlc complexity [--analyze] — show codebase complexity profile.
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare const complexityCommand: Command;
6
+ //# sourceMappingURL=complexity.d.ts.map
@@ -0,0 +1,35 @@
1
+ /**
2
+ * ai-sdlc complexity [--analyze] — show codebase complexity profile.
3
+ */
4
+ import { Command } from 'commander';
5
+ import { Orchestrator } from '../../orchestrator.js';
6
+ import { formatOutput } from '../formatters/index.js';
7
+ export const complexityCommand = new Command('complexity')
8
+ .description('Show codebase complexity profile')
9
+ .option('--analyze', 'Force a fresh analysis (skip cache)')
10
+ .option('--state <path>', 'SQLite state database path')
11
+ .action(async (opts, cmd) => {
12
+ const globalOpts = cmd.parent?.opts() ?? {};
13
+ const format = globalOpts.format ?? 'table';
14
+ const orchestrator = new Orchestrator({
15
+ configDir: globalOpts.config,
16
+ statePath: opts.state,
17
+ workDir: process.cwd(),
18
+ });
19
+ try {
20
+ const { profile, context } = await orchestrator.complexity({ analyze: opts.analyze });
21
+ console.log(formatOutput(format, {
22
+ type: 'complexity',
23
+ profile,
24
+ context,
25
+ }));
26
+ }
27
+ catch (err) {
28
+ console.error(err instanceof Error ? err.message : String(err));
29
+ process.exitCode = 1;
30
+ }
31
+ finally {
32
+ orchestrator.close();
33
+ }
34
+ });
35
+ //# sourceMappingURL=complexity.js.map
@@ -0,0 +1,6 @@
1
+ /**
2
+ * ai-sdlc cost [--last <dur>] [--agent <name>] [--budget <usd>]
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare const costCommand: Command;
6
+ //# sourceMappingURL=cost.d.ts.map
@@ -0,0 +1,53 @@
1
+ /**
2
+ * ai-sdlc cost [--last <dur>] [--agent <name>] [--budget <usd>]
3
+ */
4
+ import { Command } from 'commander';
5
+ import { Orchestrator } from '../../orchestrator.js';
6
+ import { formatOutput } from '../formatters/index.js';
7
+ export const costCommand = new Command('cost')
8
+ .description('Show cost summary and budget status')
9
+ .option('--last <duration>', 'Time range (e.g., 7d, 30d, 1h)')
10
+ .option('--agent <name>', 'Filter by agent name')
11
+ .option('--budget <usd>', 'Budget in USD', parseFloat)
12
+ .option('--state <path>', 'SQLite state database path')
13
+ .action(async (opts, cmd) => {
14
+ const globalOpts = cmd.parent?.parent?.opts() ?? {};
15
+ const format = globalOpts.format ?? 'table';
16
+ const orchestrator = new Orchestrator({
17
+ configDir: globalOpts.config,
18
+ statePath: opts.state,
19
+ });
20
+ try {
21
+ const since = opts.last ? computeSince(opts.last) : undefined;
22
+ const { summary, budget } = await orchestrator.cost({ since, budget: opts.budget });
23
+ const data = {
24
+ type: 'cost',
25
+ summary,
26
+ budget,
27
+ agent: opts.agent,
28
+ period: opts.last ?? 'all-time',
29
+ };
30
+ // Filter by agent if requested
31
+ if (opts.agent && summary.costByAgent) {
32
+ data.filteredCost = summary.costByAgent[opts.agent] ?? 0;
33
+ }
34
+ console.log(formatOutput(format, data));
35
+ }
36
+ catch (err) {
37
+ console.error(err instanceof Error ? err.message : String(err));
38
+ process.exitCode = 1;
39
+ }
40
+ finally {
41
+ orchestrator.close();
42
+ }
43
+ });
44
+ function computeSince(duration) {
45
+ const match = duration.match(/^(\d+)([dhm])$/);
46
+ if (!match)
47
+ return new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString();
48
+ const value = parseInt(match[1], 10);
49
+ const unit = match[2];
50
+ const ms = unit === 'd' ? value * 86400000 : unit === 'h' ? value * 3600000 : value * 60000;
51
+ return new Date(Date.now() - ms).toISOString();
52
+ }
53
+ //# sourceMappingURL=cost.js.map
@@ -0,0 +1,9 @@
1
+ /**
2
+ * ai-sdlc dashboard — live TUI monitoring dashboard.
3
+ *
4
+ * Uses setInterval + ANSI repainting. Ctrl-C to exit.
5
+ * D1: Zero dependencies — pure ANSI escape codes.
6
+ */
7
+ import { Command } from 'commander';
8
+ export declare const dashboardCommand: Command;
9
+ //# sourceMappingURL=dashboard.d.ts.map
@@ -0,0 +1,50 @@
1
+ /**
2
+ * ai-sdlc dashboard — live TUI monitoring dashboard.
3
+ *
4
+ * Uses setInterval + ANSI repainting. Ctrl-C to exit.
5
+ * D1: Zero dependencies — pure ANSI escape codes.
6
+ */
7
+ import { Command } from 'commander';
8
+ import { Orchestrator } from '../../orchestrator.js';
9
+ import { renderDashboardFrame } from '../dashboard-renderer.js';
10
+ import { DEFAULT_DASHBOARD_REFRESH_MS } from '../../defaults.js';
11
+ export const dashboardCommand = new Command('dashboard')
12
+ .description('Live monitoring dashboard (Ctrl-C to exit)')
13
+ .option('--refresh <ms>', 'Refresh interval in ms', String(DEFAULT_DASHBOARD_REFRESH_MS))
14
+ .option('--state <path>', 'SQLite state database path')
15
+ .action(async (opts, cmd) => {
16
+ const globalOpts = cmd.parent?.parent?.opts() ?? {};
17
+ const refreshMs = parseInt(opts.refresh, 10) || DEFAULT_DASHBOARD_REFRESH_MS;
18
+ const orchestrator = new Orchestrator({
19
+ configDir: globalOpts.config,
20
+ statePath: opts.state,
21
+ });
22
+ // Clear screen and hide cursor
23
+ process.stdout.write('\x1B[?25l\x1B[2J\x1B[H');
24
+ const render = async () => {
25
+ try {
26
+ const data = await orchestrator.dashboard();
27
+ const width = process.stdout.columns || 80;
28
+ const frame = renderDashboardFrame(data, width);
29
+ // Move cursor to top-left and write frame
30
+ process.stdout.write('\x1B[H' + frame);
31
+ }
32
+ catch {
33
+ // Dashboard rendering is best-effort
34
+ }
35
+ };
36
+ // Initial render
37
+ await render();
38
+ // Polling loop
39
+ const interval = setInterval(render, refreshMs);
40
+ // Graceful shutdown
41
+ const cleanup = () => {
42
+ clearInterval(interval);
43
+ process.stdout.write('\x1B[?25h\n'); // Show cursor
44
+ orchestrator.close();
45
+ process.exit(0);
46
+ };
47
+ process.on('SIGINT', cleanup);
48
+ process.on('SIGTERM', cleanup);
49
+ });
50
+ //# sourceMappingURL=dashboard.js.map
@@ -0,0 +1,6 @@
1
+ /**
2
+ * ai-sdlc health — validate config, state store, and adapter connectivity.
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare const healthCommand: Command;
6
+ //# sourceMappingURL=health.d.ts.map