specweave 1.0.54 → 1.0.55
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/dist/src/core/auto/circuit-breaker.d.ts +146 -0
- package/dist/src/core/auto/circuit-breaker.d.ts.map +1 -0
- package/dist/src/core/auto/circuit-breaker.js +328 -0
- package/dist/src/core/auto/circuit-breaker.js.map +1 -0
- package/dist/src/core/auto/config.d.ts +34 -0
- package/dist/src/core/auto/config.d.ts.map +1 -0
- package/dist/src/core/{autopilot → auto}/config.js +19 -19
- package/dist/src/core/auto/config.js.map +1 -0
- package/dist/src/core/auto/cost-estimator.d.ts +53 -0
- package/dist/src/core/auto/cost-estimator.d.ts.map +1 -0
- package/dist/src/core/auto/cost-estimator.js +150 -0
- package/dist/src/core/auto/cost-estimator.js.map +1 -0
- package/dist/src/core/auto/human-gate.d.ts +102 -0
- package/dist/src/core/auto/human-gate.d.ts.map +1 -0
- package/dist/src/core/auto/human-gate.js +295 -0
- package/dist/src/core/auto/human-gate.js.map +1 -0
- package/dist/src/core/auto/increment-queue.d.ts +100 -0
- package/dist/src/core/auto/increment-queue.d.ts.map +1 -0
- package/dist/src/core/auto/increment-queue.js +290 -0
- package/dist/src/core/auto/increment-queue.js.map +1 -0
- package/dist/src/core/auto/index.d.ts +19 -0
- package/dist/src/core/auto/index.d.ts.map +1 -0
- package/dist/src/core/auto/index.js +30 -0
- package/dist/src/core/auto/index.js.map +1 -0
- package/dist/src/core/{autopilot → auto}/logger.d.ts +6 -6
- package/dist/src/core/auto/logger.d.ts.map +1 -0
- package/dist/src/core/{autopilot → auto}/logger.js +8 -8
- package/dist/src/core/auto/logger.js.map +1 -0
- package/dist/src/core/auto/report-generator.d.ts +67 -0
- package/dist/src/core/auto/report-generator.d.ts.map +1 -0
- package/dist/src/core/auto/report-generator.js +287 -0
- package/dist/src/core/auto/report-generator.js.map +1 -0
- package/dist/src/core/{autopilot → auto}/session-state.d.ts +8 -8
- package/dist/src/core/auto/session-state.d.ts.map +1 -0
- package/dist/src/core/{autopilot → auto}/session-state.js +6 -6
- package/dist/src/core/auto/session-state.js.map +1 -0
- package/dist/src/core/auto/sync-checkpoint.d.ts +106 -0
- package/dist/src/core/auto/sync-checkpoint.d.ts.map +1 -0
- package/dist/src/core/auto/sync-checkpoint.js +258 -0
- package/dist/src/core/auto/sync-checkpoint.js.map +1 -0
- package/dist/src/core/auto/test-gate.d.ts +98 -0
- package/dist/src/core/auto/test-gate.d.ts.map +1 -0
- package/dist/src/core/auto/test-gate.js +258 -0
- package/dist/src/core/auto/test-gate.js.map +1 -0
- package/dist/src/core/{autopilot → auto}/types.d.ts +7 -7
- package/dist/src/core/auto/types.d.ts.map +1 -0
- package/dist/src/core/{autopilot → auto}/types.js +2 -2
- package/dist/src/core/auto/types.js.map +1 -0
- package/package.json +1 -1
- package/plugins/specweave/commands/auto-status.md +124 -0
- package/plugins/specweave/commands/auto.md +244 -0
- package/plugins/specweave/commands/cancel-auto.md +79 -0
- package/plugins/specweave/hooks/{stop-autopilot.sh → stop-auto.sh} +30 -11
- package/plugins/specweave/scripts/auto-status.sh +231 -0
- package/plugins/specweave/scripts/cancel-auto.sh +146 -0
- package/plugins/specweave/scripts/setup-auto.sh +245 -0
- package/plugins/specweave/skills/docs-updater/.!31934!SKILL.md +20 -0
- package/plugins/specweave/skills/docs-updater/.!31935!SKILL.md +20 -0
- package/plugins/specweave/skills/docs-updater/.!31936!SKILL.md +20 -0
- package/plugins/specweave-release/commands/npm.md +11 -1
- package/src/templates/CLAUDE.md.template +57 -0
- package/dist/src/core/autopilot/config.d.ts +0 -34
- package/dist/src/core/autopilot/config.d.ts.map +0 -1
- package/dist/src/core/autopilot/config.js.map +0 -1
- package/dist/src/core/autopilot/index.d.ts +0 -12
- package/dist/src/core/autopilot/index.d.ts.map +0 -1
- package/dist/src/core/autopilot/index.js +0 -16
- package/dist/src/core/autopilot/index.js.map +0 -1
- package/dist/src/core/autopilot/logger.d.ts.map +0 -1
- package/dist/src/core/autopilot/logger.js.map +0 -1
- package/dist/src/core/autopilot/session-state.d.ts.map +0 -1
- package/dist/src/core/autopilot/session-state.js.map +0 -1
- package/dist/src/core/autopilot/types.d.ts.map +0 -1
- package/dist/src/core/autopilot/types.js.map +0 -1
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Circuit Breaker Module
|
|
3
|
+
*
|
|
4
|
+
* Protects auto from external service failures.
|
|
5
|
+
* Implements the circuit breaker pattern for:
|
|
6
|
+
* - GitHub API
|
|
7
|
+
* - JIRA API
|
|
8
|
+
* - Azure DevOps API
|
|
9
|
+
* - Custom external services
|
|
10
|
+
*/
|
|
11
|
+
export type CircuitState = 'closed' | 'open' | 'half-open';
|
|
12
|
+
export interface CircuitBreakerConfig {
|
|
13
|
+
/** Number of failures before opening circuit */
|
|
14
|
+
failureThreshold: number;
|
|
15
|
+
/** Time in ms before trying half-open */
|
|
16
|
+
resetTimeout: number;
|
|
17
|
+
/** Number of successes in half-open to close */
|
|
18
|
+
successThreshold: number;
|
|
19
|
+
/** Time window for counting failures */
|
|
20
|
+
failureWindow: number;
|
|
21
|
+
}
|
|
22
|
+
export interface CircuitStatus {
|
|
23
|
+
state: CircuitState;
|
|
24
|
+
failures: number;
|
|
25
|
+
successes: number;
|
|
26
|
+
lastFailure?: string;
|
|
27
|
+
lastSuccess?: string;
|
|
28
|
+
openedAt?: string;
|
|
29
|
+
nextRetryAt?: string;
|
|
30
|
+
queuedOperations: QueuedOperation[];
|
|
31
|
+
}
|
|
32
|
+
export interface QueuedOperation {
|
|
33
|
+
id: string;
|
|
34
|
+
operation: string;
|
|
35
|
+
params: unknown;
|
|
36
|
+
queuedAt: string;
|
|
37
|
+
retryCount: number;
|
|
38
|
+
}
|
|
39
|
+
export declare class CircuitBreaker {
|
|
40
|
+
private name;
|
|
41
|
+
private config;
|
|
42
|
+
private status;
|
|
43
|
+
private failureTimestamps;
|
|
44
|
+
private projectRoot;
|
|
45
|
+
constructor(name: string, projectRoot: string, config?: Partial<CircuitBreakerConfig>);
|
|
46
|
+
/**
|
|
47
|
+
* Execute an operation with circuit breaker protection
|
|
48
|
+
*/
|
|
49
|
+
execute<T>(operation: () => Promise<T>): Promise<T>;
|
|
50
|
+
/**
|
|
51
|
+
* Check if circuit is open (blocking calls)
|
|
52
|
+
*/
|
|
53
|
+
isOpen(): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Check if circuit allows calls (closed or half-open)
|
|
56
|
+
*/
|
|
57
|
+
isCallAllowed(): boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Record a successful operation
|
|
60
|
+
*/
|
|
61
|
+
recordSuccess(): void;
|
|
62
|
+
/**
|
|
63
|
+
* Record a failed operation
|
|
64
|
+
*/
|
|
65
|
+
recordFailure(error?: unknown): void;
|
|
66
|
+
/**
|
|
67
|
+
* Transition to a new state
|
|
68
|
+
*/
|
|
69
|
+
private transitionTo;
|
|
70
|
+
/**
|
|
71
|
+
* Queue an operation for later retry
|
|
72
|
+
*/
|
|
73
|
+
queueOperation(operation: string, params: unknown): string;
|
|
74
|
+
/**
|
|
75
|
+
* Process queued operations
|
|
76
|
+
*/
|
|
77
|
+
private processQueue;
|
|
78
|
+
/**
|
|
79
|
+
* Get current status
|
|
80
|
+
*/
|
|
81
|
+
getStatus(): CircuitStatus;
|
|
82
|
+
/**
|
|
83
|
+
* Get circuit name
|
|
84
|
+
*/
|
|
85
|
+
getName(): string;
|
|
86
|
+
/**
|
|
87
|
+
* Force reset circuit (for testing/recovery)
|
|
88
|
+
*/
|
|
89
|
+
reset(): void;
|
|
90
|
+
/**
|
|
91
|
+
* Load status from session
|
|
92
|
+
*/
|
|
93
|
+
private loadStatus;
|
|
94
|
+
/**
|
|
95
|
+
* Save status to session
|
|
96
|
+
*/
|
|
97
|
+
private saveStatus;
|
|
98
|
+
/**
|
|
99
|
+
* Log state transition
|
|
100
|
+
*/
|
|
101
|
+
private logTransition;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Error thrown when circuit is open
|
|
105
|
+
*/
|
|
106
|
+
export declare class CircuitOpenError extends Error {
|
|
107
|
+
circuitName: string;
|
|
108
|
+
retryAfter: string;
|
|
109
|
+
constructor(circuitName: string, retryAfter: string);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Circuit Breaker Registry for managing multiple breakers
|
|
113
|
+
*/
|
|
114
|
+
export declare class CircuitBreakerRegistry {
|
|
115
|
+
private breakers;
|
|
116
|
+
private projectRoot;
|
|
117
|
+
constructor(projectRoot: string);
|
|
118
|
+
/**
|
|
119
|
+
* Get or create a circuit breaker
|
|
120
|
+
*/
|
|
121
|
+
getBreaker(name: string, config?: Partial<CircuitBreakerConfig>): CircuitBreaker;
|
|
122
|
+
/**
|
|
123
|
+
* Get status of all breakers
|
|
124
|
+
*/
|
|
125
|
+
getAllStatus(): Record<string, CircuitStatus>;
|
|
126
|
+
/**
|
|
127
|
+
* Check if any circuit is open
|
|
128
|
+
*/
|
|
129
|
+
hasOpenCircuit(): boolean;
|
|
130
|
+
/**
|
|
131
|
+
* Reset all circuits
|
|
132
|
+
*/
|
|
133
|
+
resetAll(): void;
|
|
134
|
+
/**
|
|
135
|
+
* Create default service breakers
|
|
136
|
+
*/
|
|
137
|
+
initializeDefaults(): void;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Parse rate limit headers and extract retry time
|
|
141
|
+
*/
|
|
142
|
+
export declare function parseRateLimitHeaders(headers: Record<string, string | undefined>): {
|
|
143
|
+
limited: boolean;
|
|
144
|
+
retryAfter: number;
|
|
145
|
+
};
|
|
146
|
+
//# sourceMappingURL=circuit-breaker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"circuit-breaker.d.ts","sourceRoot":"","sources":["../../../../src/core/auto/circuit-breaker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Circuit Breaker Module
|
|
3
|
+
*
|
|
4
|
+
* Protects auto from external service failures.
|
|
5
|
+
* Implements the circuit breaker pattern for:
|
|
6
|
+
* - GitHub API
|
|
7
|
+
* - JIRA API
|
|
8
|
+
* - Azure DevOps API
|
|
9
|
+
* - Custom external services
|
|
10
|
+
*/
|
|
11
|
+
import * as fs from 'fs';
|
|
12
|
+
import * as path from 'path';
|
|
13
|
+
const DEFAULT_CONFIG = {
|
|
14
|
+
failureThreshold: 3,
|
|
15
|
+
resetTimeout: 60000, // 1 minute
|
|
16
|
+
successThreshold: 2,
|
|
17
|
+
failureWindow: 300000, // 5 minutes
|
|
18
|
+
};
|
|
19
|
+
export class CircuitBreaker {
|
|
20
|
+
constructor(name, projectRoot, config = {}) {
|
|
21
|
+
this.failureTimestamps = [];
|
|
22
|
+
this.name = name;
|
|
23
|
+
this.projectRoot = projectRoot;
|
|
24
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
25
|
+
this.status = this.loadStatus() || {
|
|
26
|
+
state: 'closed',
|
|
27
|
+
failures: 0,
|
|
28
|
+
successes: 0,
|
|
29
|
+
queuedOperations: [],
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Execute an operation with circuit breaker protection
|
|
34
|
+
*/
|
|
35
|
+
async execute(operation) {
|
|
36
|
+
if (this.isOpen()) {
|
|
37
|
+
throw new CircuitOpenError(this.name, this.status.nextRetryAt || '');
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
const result = await operation();
|
|
41
|
+
this.recordSuccess();
|
|
42
|
+
return result;
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
this.recordFailure(error);
|
|
46
|
+
throw error;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Check if circuit is open (blocking calls)
|
|
51
|
+
*/
|
|
52
|
+
isOpen() {
|
|
53
|
+
if (this.status.state === 'open') {
|
|
54
|
+
// Check if ready for half-open
|
|
55
|
+
if (this.status.openedAt) {
|
|
56
|
+
const openedTime = new Date(this.status.openedAt).getTime();
|
|
57
|
+
const now = Date.now();
|
|
58
|
+
if (now - openedTime >= this.config.resetTimeout) {
|
|
59
|
+
this.transitionTo('half-open');
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Check if circuit allows calls (closed or half-open)
|
|
69
|
+
*/
|
|
70
|
+
isCallAllowed() {
|
|
71
|
+
return !this.isOpen();
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Record a successful operation
|
|
75
|
+
*/
|
|
76
|
+
recordSuccess() {
|
|
77
|
+
this.status.successes++;
|
|
78
|
+
this.status.lastSuccess = new Date().toISOString();
|
|
79
|
+
if (this.status.state === 'half-open') {
|
|
80
|
+
if (this.status.successes >= this.config.successThreshold) {
|
|
81
|
+
this.transitionTo('closed');
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
else if (this.status.state === 'closed') {
|
|
85
|
+
// Reset failure count on success
|
|
86
|
+
this.status.failures = 0;
|
|
87
|
+
this.failureTimestamps = [];
|
|
88
|
+
}
|
|
89
|
+
this.saveStatus();
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Record a failed operation
|
|
93
|
+
*/
|
|
94
|
+
recordFailure(error) {
|
|
95
|
+
const now = Date.now();
|
|
96
|
+
// Clean old failures outside window
|
|
97
|
+
this.failureTimestamps = this.failureTimestamps.filter((ts) => now - ts < this.config.failureWindow);
|
|
98
|
+
this.failureTimestamps.push(now);
|
|
99
|
+
this.status.failures = this.failureTimestamps.length;
|
|
100
|
+
this.status.lastFailure = new Date().toISOString();
|
|
101
|
+
// Check if should open
|
|
102
|
+
if (this.status.state === 'half-open') {
|
|
103
|
+
this.transitionTo('open');
|
|
104
|
+
}
|
|
105
|
+
else if (this.status.state === 'closed' &&
|
|
106
|
+
this.status.failures >= this.config.failureThreshold) {
|
|
107
|
+
this.transitionTo('open');
|
|
108
|
+
}
|
|
109
|
+
this.saveStatus();
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Transition to a new state
|
|
113
|
+
*/
|
|
114
|
+
transitionTo(state) {
|
|
115
|
+
const previousState = this.status.state;
|
|
116
|
+
this.status.state = state;
|
|
117
|
+
if (state === 'open') {
|
|
118
|
+
this.status.openedAt = new Date().toISOString();
|
|
119
|
+
this.status.nextRetryAt = new Date(Date.now() + this.config.resetTimeout).toISOString();
|
|
120
|
+
this.status.successes = 0;
|
|
121
|
+
}
|
|
122
|
+
else if (state === 'closed') {
|
|
123
|
+
this.status.failures = 0;
|
|
124
|
+
this.status.successes = 0;
|
|
125
|
+
this.status.openedAt = undefined;
|
|
126
|
+
this.status.nextRetryAt = undefined;
|
|
127
|
+
this.failureTimestamps = [];
|
|
128
|
+
// Process queued operations
|
|
129
|
+
this.processQueue();
|
|
130
|
+
}
|
|
131
|
+
else if (state === 'half-open') {
|
|
132
|
+
this.status.successes = 0;
|
|
133
|
+
}
|
|
134
|
+
this.logTransition(previousState, state);
|
|
135
|
+
this.saveStatus();
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Queue an operation for later retry
|
|
139
|
+
*/
|
|
140
|
+
queueOperation(operation, params) {
|
|
141
|
+
const id = `op-${Date.now()}-${Math.random().toString(36).substring(7)}`;
|
|
142
|
+
this.status.queuedOperations.push({
|
|
143
|
+
id,
|
|
144
|
+
operation,
|
|
145
|
+
params,
|
|
146
|
+
queuedAt: new Date().toISOString(),
|
|
147
|
+
retryCount: 0,
|
|
148
|
+
});
|
|
149
|
+
this.saveStatus();
|
|
150
|
+
return id;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Process queued operations
|
|
154
|
+
*/
|
|
155
|
+
processQueue() {
|
|
156
|
+
// In a real implementation, this would retry queued operations
|
|
157
|
+
// For now, we just clear the queue (operations would need to be re-triggered)
|
|
158
|
+
if (this.status.queuedOperations.length > 0) {
|
|
159
|
+
console.log(`[CircuitBreaker:${this.name}] Circuit closed. ${this.status.queuedOperations.length} queued operations need manual retry.`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Get current status
|
|
164
|
+
*/
|
|
165
|
+
getStatus() {
|
|
166
|
+
return { ...this.status };
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Get circuit name
|
|
170
|
+
*/
|
|
171
|
+
getName() {
|
|
172
|
+
return this.name;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Force reset circuit (for testing/recovery)
|
|
176
|
+
*/
|
|
177
|
+
reset() {
|
|
178
|
+
this.transitionTo('closed');
|
|
179
|
+
this.status.queuedOperations = [];
|
|
180
|
+
this.saveStatus();
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Load status from session
|
|
184
|
+
*/
|
|
185
|
+
loadStatus() {
|
|
186
|
+
const sessionPath = path.join(this.projectRoot, '.specweave', 'state', 'auto-session.json');
|
|
187
|
+
if (!fs.existsSync(sessionPath))
|
|
188
|
+
return null;
|
|
189
|
+
try {
|
|
190
|
+
const session = JSON.parse(fs.readFileSync(sessionPath, 'utf-8'));
|
|
191
|
+
return session.circuitBreakers?.[this.name] || null;
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Save status to session
|
|
199
|
+
*/
|
|
200
|
+
saveStatus() {
|
|
201
|
+
const sessionPath = path.join(this.projectRoot, '.specweave', 'state', 'auto-session.json');
|
|
202
|
+
if (!fs.existsSync(sessionPath))
|
|
203
|
+
return;
|
|
204
|
+
try {
|
|
205
|
+
const session = JSON.parse(fs.readFileSync(sessionPath, 'utf-8'));
|
|
206
|
+
session.circuitBreakers = session.circuitBreakers || {};
|
|
207
|
+
session.circuitBreakers[this.name] = this.status;
|
|
208
|
+
fs.writeFileSync(sessionPath, JSON.stringify(session, null, 2));
|
|
209
|
+
}
|
|
210
|
+
catch {
|
|
211
|
+
// Ignore errors
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Log state transition
|
|
216
|
+
*/
|
|
217
|
+
logTransition(from, to) {
|
|
218
|
+
const logsDir = path.join(this.projectRoot, '.specweave', 'logs');
|
|
219
|
+
try {
|
|
220
|
+
if (!fs.existsSync(logsDir)) {
|
|
221
|
+
fs.mkdirSync(logsDir, { recursive: true });
|
|
222
|
+
}
|
|
223
|
+
const logEntry = {
|
|
224
|
+
timestamp: new Date().toISOString(),
|
|
225
|
+
circuit: this.name,
|
|
226
|
+
event: 'state_change',
|
|
227
|
+
from,
|
|
228
|
+
to,
|
|
229
|
+
failures: this.status.failures,
|
|
230
|
+
queuedOps: this.status.queuedOperations.length,
|
|
231
|
+
};
|
|
232
|
+
fs.appendFileSync(path.join(logsDir, 'circuit-breakers.log'), JSON.stringify(logEntry) + '\n');
|
|
233
|
+
}
|
|
234
|
+
catch {
|
|
235
|
+
// Ignore logging errors
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Error thrown when circuit is open
|
|
241
|
+
*/
|
|
242
|
+
export class CircuitOpenError extends Error {
|
|
243
|
+
constructor(circuitName, retryAfter) {
|
|
244
|
+
super(`Circuit breaker '${circuitName}' is open. Retry after ${retryAfter}`);
|
|
245
|
+
this.circuitName = circuitName;
|
|
246
|
+
this.retryAfter = retryAfter;
|
|
247
|
+
this.name = 'CircuitOpenError';
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Circuit Breaker Registry for managing multiple breakers
|
|
252
|
+
*/
|
|
253
|
+
export class CircuitBreakerRegistry {
|
|
254
|
+
constructor(projectRoot) {
|
|
255
|
+
this.breakers = new Map();
|
|
256
|
+
this.projectRoot = projectRoot;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Get or create a circuit breaker
|
|
260
|
+
*/
|
|
261
|
+
getBreaker(name, config) {
|
|
262
|
+
if (!this.breakers.has(name)) {
|
|
263
|
+
this.breakers.set(name, new CircuitBreaker(name, this.projectRoot, config));
|
|
264
|
+
}
|
|
265
|
+
return this.breakers.get(name);
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Get status of all breakers
|
|
269
|
+
*/
|
|
270
|
+
getAllStatus() {
|
|
271
|
+
const status = {};
|
|
272
|
+
for (const [name, breaker] of this.breakers) {
|
|
273
|
+
status[name] = breaker.getStatus();
|
|
274
|
+
}
|
|
275
|
+
return status;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Check if any circuit is open
|
|
279
|
+
*/
|
|
280
|
+
hasOpenCircuit() {
|
|
281
|
+
for (const breaker of this.breakers.values()) {
|
|
282
|
+
if (breaker.isOpen()) {
|
|
283
|
+
return true;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return false;
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Reset all circuits
|
|
290
|
+
*/
|
|
291
|
+
resetAll() {
|
|
292
|
+
for (const breaker of this.breakers.values()) {
|
|
293
|
+
breaker.reset();
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Create default service breakers
|
|
298
|
+
*/
|
|
299
|
+
initializeDefaults() {
|
|
300
|
+
this.getBreaker('github', { failureThreshold: 3, resetTimeout: 60000 });
|
|
301
|
+
this.getBreaker('jira', { failureThreshold: 5, resetTimeout: 120000 });
|
|
302
|
+
this.getBreaker('ado', { failureThreshold: 5, resetTimeout: 120000 });
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Parse rate limit headers and extract retry time
|
|
307
|
+
*/
|
|
308
|
+
export function parseRateLimitHeaders(headers) {
|
|
309
|
+
// GitHub style
|
|
310
|
+
const remaining = parseInt(headers['x-ratelimit-remaining'] || '', 10);
|
|
311
|
+
const reset = parseInt(headers['x-ratelimit-reset'] || '', 10);
|
|
312
|
+
if (!isNaN(remaining) && remaining <= 0 && !isNaN(reset)) {
|
|
313
|
+
return {
|
|
314
|
+
limited: true,
|
|
315
|
+
retryAfter: Math.max(0, reset * 1000 - Date.now()),
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
// Standard Retry-After header
|
|
319
|
+
const retryAfter = headers['retry-after'];
|
|
320
|
+
if (retryAfter) {
|
|
321
|
+
const seconds = parseInt(retryAfter, 10);
|
|
322
|
+
if (!isNaN(seconds)) {
|
|
323
|
+
return { limited: true, retryAfter: seconds * 1000 };
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
return { limited: false, retryAfter: 0 };
|
|
327
|
+
}
|
|
328
|
+
//# sourceMappingURL=circuit-breaker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"circuit-breaker.js","sourceRoot":"","sources":["../../../../src/core/auto/circuit-breaker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto Configuration Loader
|
|
3
|
+
* Loads auto settings from .specweave/config.json with sensible defaults
|
|
4
|
+
*/
|
|
5
|
+
import { AutoConfig } from './types.js';
|
|
6
|
+
export interface ConfigLoadResult {
|
|
7
|
+
config: AutoConfig;
|
|
8
|
+
source: 'file' | 'defaults' | 'merged';
|
|
9
|
+
warnings: string[];
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Load auto configuration from project config file
|
|
13
|
+
*/
|
|
14
|
+
export declare function loadAutoConfig(projectRoot: string): ConfigLoadResult;
|
|
15
|
+
/**
|
|
16
|
+
* Save auto configuration to project config file
|
|
17
|
+
*/
|
|
18
|
+
export declare function saveAutoConfig(projectRoot: string, autoConfig: Partial<AutoConfig>): void;
|
|
19
|
+
/**
|
|
20
|
+
* Check if auto is enabled in config
|
|
21
|
+
*/
|
|
22
|
+
export declare function isAutoEnabled(projectRoot: string): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Get effective mode based on config and flags
|
|
25
|
+
*/
|
|
26
|
+
export declare function getEffectiveMode(projectRoot: string, flags: {
|
|
27
|
+
auto?: boolean;
|
|
28
|
+
manual?: boolean;
|
|
29
|
+
simple?: boolean;
|
|
30
|
+
}): {
|
|
31
|
+
mode: 'auto' | 'manual';
|
|
32
|
+
simple: boolean;
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../../src/core/auto/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,UAAU,EAAuB,MAAM,YAAY,CAAC;AAK7D,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,EAAE,MAAM,GAAG,UAAU,GAAG,QAAQ,CAAC;IACvC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,gBAAgB,CAyCpE;AAyGD;;GAEG;AACH,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,OAAO,CAAC,UAAU,CAAC,GAC9B,IAAI,CA6BN;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAO1D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAC5D;IAAE,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,CAiB9C"}
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* Loads
|
|
2
|
+
* Auto Configuration Loader
|
|
3
|
+
* Loads auto settings from .specweave/config.json with sensible defaults
|
|
4
4
|
*/
|
|
5
5
|
import * as fs from 'fs';
|
|
6
6
|
import * as path from 'path';
|
|
7
|
-
import {
|
|
7
|
+
import { DEFAULT_AUTO_CONFIG } from './types.js';
|
|
8
8
|
import { consoleLogger as logger } from '../../utils/logger.js';
|
|
9
9
|
const CONFIG_PATH = '.specweave/config.json';
|
|
10
10
|
/**
|
|
11
|
-
* Load
|
|
11
|
+
* Load auto configuration from project config file
|
|
12
12
|
*/
|
|
13
|
-
export function
|
|
13
|
+
export function loadAutoConfig(projectRoot) {
|
|
14
14
|
const configPath = path.join(projectRoot, CONFIG_PATH);
|
|
15
15
|
const warnings = [];
|
|
16
16
|
// Check if config file exists
|
|
17
17
|
if (!fs.existsSync(configPath)) {
|
|
18
18
|
logger.debug('No config file found, using defaults');
|
|
19
19
|
return {
|
|
20
|
-
config: { ...
|
|
20
|
+
config: { ...DEFAULT_AUTO_CONFIG },
|
|
21
21
|
source: 'defaults',
|
|
22
22
|
warnings: [],
|
|
23
23
|
};
|
|
@@ -29,7 +29,7 @@ export function loadAutopilotConfig(projectRoot) {
|
|
|
29
29
|
if (!fullConfig.auto) {
|
|
30
30
|
logger.debug('No auto config section, using defaults');
|
|
31
31
|
return {
|
|
32
|
-
config: { ...
|
|
32
|
+
config: { ...DEFAULT_AUTO_CONFIG },
|
|
33
33
|
source: 'defaults',
|
|
34
34
|
warnings: [],
|
|
35
35
|
};
|
|
@@ -45,14 +45,14 @@ export function loadAutopilotConfig(projectRoot) {
|
|
|
45
45
|
}
|
|
46
46
|
catch (error) {
|
|
47
47
|
const message = error instanceof Error ? error.message : String(error);
|
|
48
|
-
throw new Error(`Failed to load
|
|
48
|
+
throw new Error(`Failed to load auto config: ${message}`);
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
/**
|
|
52
52
|
* Merge user config with defaults, validating values
|
|
53
53
|
*/
|
|
54
54
|
function mergeConfig(userConfig, warnings) {
|
|
55
|
-
const config = { ...
|
|
55
|
+
const config = { ...DEFAULT_AUTO_CONFIG };
|
|
56
56
|
// Boolean fields
|
|
57
57
|
if (typeof userConfig.enabled === 'boolean') {
|
|
58
58
|
config.enabled = userConfig.enabled;
|
|
@@ -136,9 +136,9 @@ function mergeConfig(userConfig, warnings) {
|
|
|
136
136
|
return config;
|
|
137
137
|
}
|
|
138
138
|
/**
|
|
139
|
-
* Save
|
|
139
|
+
* Save auto configuration to project config file
|
|
140
140
|
*/
|
|
141
|
-
export function
|
|
141
|
+
export function saveAutoConfig(projectRoot, autoConfig) {
|
|
142
142
|
const configPath = path.join(projectRoot, CONFIG_PATH);
|
|
143
143
|
let fullConfig = {};
|
|
144
144
|
// Load existing config if present
|
|
@@ -151,10 +151,10 @@ export function saveAutopilotConfig(projectRoot, autopilotConfig) {
|
|
|
151
151
|
logger.warn('Failed to parse existing config, creating new');
|
|
152
152
|
}
|
|
153
153
|
}
|
|
154
|
-
// Merge
|
|
154
|
+
// Merge auto config
|
|
155
155
|
fullConfig.auto = {
|
|
156
156
|
...(fullConfig.auto || {}),
|
|
157
|
-
...
|
|
157
|
+
...autoConfig,
|
|
158
158
|
};
|
|
159
159
|
// Ensure directory exists
|
|
160
160
|
const configDir = path.dirname(configPath);
|
|
@@ -163,25 +163,25 @@ export function saveAutopilotConfig(projectRoot, autopilotConfig) {
|
|
|
163
163
|
}
|
|
164
164
|
// Write config
|
|
165
165
|
fs.writeFileSync(configPath, JSON.stringify(fullConfig, null, 2), 'utf-8');
|
|
166
|
-
logger.info('Saved
|
|
166
|
+
logger.info('Saved auto configuration');
|
|
167
167
|
}
|
|
168
168
|
/**
|
|
169
|
-
* Check if
|
|
169
|
+
* Check if auto is enabled in config
|
|
170
170
|
*/
|
|
171
|
-
export function
|
|
171
|
+
export function isAutoEnabled(projectRoot) {
|
|
172
172
|
try {
|
|
173
|
-
const { config } =
|
|
173
|
+
const { config } = loadAutoConfig(projectRoot);
|
|
174
174
|
return config.enabled;
|
|
175
175
|
}
|
|
176
176
|
catch {
|
|
177
|
-
return
|
|
177
|
+
return DEFAULT_AUTO_CONFIG.enabled;
|
|
178
178
|
}
|
|
179
179
|
}
|
|
180
180
|
/**
|
|
181
181
|
* Get effective mode based on config and flags
|
|
182
182
|
*/
|
|
183
183
|
export function getEffectiveMode(projectRoot, flags) {
|
|
184
|
-
const { config } =
|
|
184
|
+
const { config } = loadAutoConfig(projectRoot);
|
|
185
185
|
// Flags override config
|
|
186
186
|
if (flags.manual) {
|
|
187
187
|
return { mode: 'manual', simple: false };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../../src/core/auto/config.ts"],"names":[],"mappings":"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"}
|