@ai-sdlc/orchestrator 0.4.0 → 0.6.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.
- package/dist/action-enforcement.d.ts +26 -0
- package/dist/action-enforcement.js +70 -0
- package/dist/adapters.d.ts +18 -3
- package/dist/adapters.js +92 -2
- package/dist/admission-score.d.ts +58 -0
- package/dist/admission-score.js +164 -0
- package/dist/cli/commands/init.js +4 -8
- package/dist/cli/commands/run.js +2 -2
- package/dist/config.d.ts +3 -0
- package/dist/config.js +14 -5
- package/dist/cycle-utils.d.ts +51 -0
- package/dist/cycle-utils.js +77 -0
- package/dist/defaults.d.ts +5 -0
- package/dist/defaults.js +5 -0
- package/dist/execute.d.ts +5 -2
- package/dist/execute.js +212 -62
- package/dist/fix-ci.js +45 -13
- package/dist/fix-review.d.ts +66 -0
- package/dist/fix-review.js +441 -0
- package/dist/index.d.ts +14 -4
- package/dist/index.js +18 -3
- package/dist/orchestrator.d.ts +1 -1
- package/dist/orchestrator.js +31 -9
- package/dist/pipeline-cycle-detector.d.ts +70 -0
- package/dist/pipeline-cycle-detector.js +111 -0
- package/dist/plugin.d.ts +9 -3
- package/dist/priority.d.ts +28 -0
- package/dist/priority.js +230 -0
- package/dist/review.d.ts +31 -0
- package/dist/review.js +74 -0
- package/dist/runners/claude-code.js +367 -35
- package/dist/runners/codex.js +15 -4
- package/dist/runners/copilot.js +15 -4
- package/dist/runners/cursor.js +15 -4
- package/dist/runners/generic-llm.js +1 -1
- package/dist/runners/index.d.ts +3 -1
- package/dist/runners/index.js +2 -0
- package/dist/runners/review-agent.d.ts +47 -0
- package/dist/runners/review-agent.js +220 -0
- package/dist/runners/security-triage.d.ts +43 -0
- package/dist/runners/security-triage.js +158 -0
- package/dist/runners/types.d.ts +24 -1
- package/dist/security.d.ts +8 -3
- package/dist/security.js +13 -2
- package/dist/shared.d.ts +17 -0
- package/dist/shared.js +27 -0
- package/dist/state/index.d.ts +1 -1
- package/dist/state/schema.d.ts +4 -1
- package/dist/state/schema.js +89 -1
- package/dist/state/store.d.ts +31 -1
- package/dist/state/store.js +208 -13
- package/dist/state/types.d.ts +52 -0
- package/dist/triage.d.ts +36 -0
- package/dist/triage.js +133 -0
- package/dist/types.d.ts +1 -1
- package/dist/watch.d.ts +6 -2
- package/dist/watch.js +34 -6
- package/dist/workflow-patterns/artifact-writer.d.ts +16 -0
- package/dist/workflow-patterns/artifact-writer.js +34 -0
- package/dist/workflow-patterns/classifiers.d.ts +10 -0
- package/dist/workflow-patterns/classifiers.js +72 -0
- package/dist/workflow-patterns/detector.d.ts +27 -0
- package/dist/workflow-patterns/detector.js +186 -0
- package/dist/workflow-patterns/index.d.ts +8 -0
- package/dist/workflow-patterns/index.js +7 -0
- package/dist/workflow-patterns/proposal-generator.d.ts +15 -0
- package/dist/workflow-patterns/proposal-generator.js +183 -0
- package/dist/workflow-patterns/telemetry-ingest.d.ts +27 -0
- package/dist/workflow-patterns/telemetry-ingest.js +103 -0
- package/dist/workflow-patterns/types.d.ts +61 -0
- package/dist/workflow-patterns/types.js +11 -0
- package/package.json +4 -2
package/dist/priority.js
ADDED
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Product Priority Algorithm (PPA) — composite scoring module.
|
|
3
|
+
*
|
|
4
|
+
* Implements the PPA priority function:
|
|
5
|
+
* P(w) = Sα(w) × Dπ(w) × Mφ(w) × Eρ(w) × (1 − Eτ) × (1 + HC(w)) × Cκ(w)
|
|
6
|
+
*
|
|
7
|
+
* Each dimension maps real-world product signals into a bounded numeric
|
|
8
|
+
* range and the multiplicative composite lets any single zero-score
|
|
9
|
+
* dimension veto the work item.
|
|
10
|
+
*
|
|
11
|
+
* RFC reference: PPA section (priority scoring).
|
|
12
|
+
*/
|
|
13
|
+
// ── Constants ───────────────────────────────────────────────────────
|
|
14
|
+
/** Default value used when an input signal is not provided. */
|
|
15
|
+
const DEFAULT_SIGNAL = 0.5;
|
|
16
|
+
/** Market force bounds — tighter than the paper's [0.025, 45]. */
|
|
17
|
+
const MARKET_FORCE_MIN = 0.5;
|
|
18
|
+
const MARKET_FORCE_MAX = 3.0;
|
|
19
|
+
/** Calibration coefficient bounds. */
|
|
20
|
+
const CALIBRATION_MIN = 0.7;
|
|
21
|
+
const CALIBRATION_MAX = 1.3;
|
|
22
|
+
/** Default weights for human curve sub-components. */
|
|
23
|
+
const DEFAULT_HC_WEIGHTS = { explicit: 0.5, consensus: 0.3, decision: 0.2 };
|
|
24
|
+
/**
|
|
25
|
+
* Total number of optional input fields that contribute to confidence.
|
|
26
|
+
* When all are provided confidence = 1; when none are provided confidence
|
|
27
|
+
* equals the ratio of zero provided over this count.
|
|
28
|
+
*/
|
|
29
|
+
const SCORABLE_FIELDS = [
|
|
30
|
+
'soulAlignment',
|
|
31
|
+
'customerRequestCount',
|
|
32
|
+
'demandSignal',
|
|
33
|
+
'bugSeverity',
|
|
34
|
+
'builderConviction',
|
|
35
|
+
'techInflection',
|
|
36
|
+
'competitivePressure',
|
|
37
|
+
'regulatoryUrgency',
|
|
38
|
+
'complexity',
|
|
39
|
+
'budgetUtilization',
|
|
40
|
+
'dependencyClearance',
|
|
41
|
+
'competitiveDrift',
|
|
42
|
+
'marketDivergence',
|
|
43
|
+
'explicitPriority',
|
|
44
|
+
'teamConsensus',
|
|
45
|
+
'meetingDecision',
|
|
46
|
+
];
|
|
47
|
+
// ── Helpers ─────────────────────────────────────────────────────────
|
|
48
|
+
/** Clamp a value to [min, max]. */
|
|
49
|
+
function clamp(value, min, max) {
|
|
50
|
+
return Math.min(max, Math.max(min, value));
|
|
51
|
+
}
|
|
52
|
+
// ── Dimension Computations ──────────────────────────────────────────
|
|
53
|
+
/**
|
|
54
|
+
* Sα — Soul Alignment [0, 1].
|
|
55
|
+
* How well the work item aligns with the product's core mission.
|
|
56
|
+
*/
|
|
57
|
+
function computeSoulAlignment(input) {
|
|
58
|
+
return clamp(input.soulAlignment ?? DEFAULT_SIGNAL, 0, 1);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Dπ — Demand Pressure [0, 1.5].
|
|
62
|
+
* Blends customer requests, recency-weighted demand, bug severity, and
|
|
63
|
+
* builder conviction into a single demand signal.
|
|
64
|
+
*/
|
|
65
|
+
function computeDemandPressure(input) {
|
|
66
|
+
const requestSignal = input.customerRequestCount !== undefined
|
|
67
|
+
? Math.min(1, input.customerRequestCount / 10)
|
|
68
|
+
: DEFAULT_SIGNAL;
|
|
69
|
+
const demandSignal = input.demandSignal ?? DEFAULT_SIGNAL;
|
|
70
|
+
const severitySignal = input.bugSeverity !== undefined ? input.bugSeverity / 5 : 0; // no bug severity means no bug boost
|
|
71
|
+
const conviction = input.builderConviction ?? DEFAULT_SIGNAL;
|
|
72
|
+
// Weighted blend, scaled to [0, 1.5]
|
|
73
|
+
const raw = requestSignal * 0.3 + demandSignal * 0.3 + severitySignal * 0.2 + conviction * 0.2;
|
|
74
|
+
return clamp(raw * 1.5, 0, 1.5);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Mφ — Market Force [0.5, 3.0].
|
|
78
|
+
* Captures technology inflection, competitive pressure, and regulatory
|
|
79
|
+
* urgency as a multiplicative amplifier.
|
|
80
|
+
*/
|
|
81
|
+
function computeMarketForce(input) {
|
|
82
|
+
const tech = input.techInflection ?? DEFAULT_SIGNAL;
|
|
83
|
+
const competitive = input.competitivePressure ?? DEFAULT_SIGNAL;
|
|
84
|
+
const regulatory = input.regulatoryUrgency ?? DEFAULT_SIGNAL;
|
|
85
|
+
// Average of the three signals, scaled to the bounded range
|
|
86
|
+
const avg = (tech + competitive + regulatory) / 3;
|
|
87
|
+
const scaled = MARKET_FORCE_MIN + avg * (MARKET_FORCE_MAX - MARKET_FORCE_MIN);
|
|
88
|
+
return clamp(scaled, MARKET_FORCE_MIN, MARKET_FORCE_MAX);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Eρ — Execution Reality [0, 1].
|
|
92
|
+
* Factors in complexity (inverse), budget headroom, and dependency
|
|
93
|
+
* clearance to express how feasible execution is right now.
|
|
94
|
+
*/
|
|
95
|
+
function computeExecutionReality(input) {
|
|
96
|
+
// Complexity 1-10 → inverse feasibility (1 = easy, 10 = very hard)
|
|
97
|
+
const complexityFeasibility = input.complexity !== undefined ? 1 - (input.complexity - 1) / 9 : DEFAULT_SIGNAL;
|
|
98
|
+
// Budget utilization: higher usage → less headroom → lower score
|
|
99
|
+
const budgetHeadroom = input.budgetUtilization !== undefined
|
|
100
|
+
? 1 - clamp(input.budgetUtilization / 100, 0, 1)
|
|
101
|
+
: DEFAULT_SIGNAL;
|
|
102
|
+
const depClearance = input.dependencyClearance ?? DEFAULT_SIGNAL;
|
|
103
|
+
const raw = complexityFeasibility * 0.4 + budgetHeadroom * 0.3 + depClearance * 0.3;
|
|
104
|
+
return clamp(raw, 0, 1);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Eτ — Entropy Tax [0, 1].
|
|
108
|
+
* Captures competitive drift and market divergence. Higher entropy means
|
|
109
|
+
* the work item is becoming less relevant over time.
|
|
110
|
+
*/
|
|
111
|
+
function computeEntropyTax(input) {
|
|
112
|
+
const drift = input.competitiveDrift ?? 0; // default: no drift
|
|
113
|
+
const divergence = input.marketDivergence ?? 0; // default: no divergence
|
|
114
|
+
const raw = (drift + divergence) / 2;
|
|
115
|
+
return clamp(raw, 0, 1);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* HC — Human Curve [-1, 1].
|
|
119
|
+
* Blends explicit priority, team consensus, and meeting decisions through
|
|
120
|
+
* tanh to produce a bounded human signal.
|
|
121
|
+
*/
|
|
122
|
+
function computeHumanCurve(input, weights) {
|
|
123
|
+
const explicit = input.explicitPriority ?? DEFAULT_SIGNAL;
|
|
124
|
+
const consensus = input.teamConsensus ?? DEFAULT_SIGNAL;
|
|
125
|
+
const decision = input.meetingDecision ?? DEFAULT_SIGNAL;
|
|
126
|
+
// Center around 0.5 so default inputs produce ~0 HC
|
|
127
|
+
const centered = (explicit - 0.5) * weights.explicit +
|
|
128
|
+
(consensus - 0.5) * weights.consensus +
|
|
129
|
+
(decision - 0.5) * weights.decision;
|
|
130
|
+
// Scale up so full-range inputs can reach [-1, 1] through tanh
|
|
131
|
+
return Math.tanh(centered * 2);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Cκ — Calibration Coefficient [0.7, 1.3].
|
|
135
|
+
* A tuning knob that lets operators scale the final score up or down.
|
|
136
|
+
*/
|
|
137
|
+
function computeCalibration(config) {
|
|
138
|
+
const coeff = config?.calibrationCoefficient ?? 1.0;
|
|
139
|
+
return clamp(coeff, CALIBRATION_MIN, CALIBRATION_MAX);
|
|
140
|
+
}
|
|
141
|
+
// ── Confidence ──────────────────────────────────────────────────────
|
|
142
|
+
/**
|
|
143
|
+
* Compute a confidence score [0, 1] based on the fraction of optional
|
|
144
|
+
* input fields that were explicitly provided (not defaulted).
|
|
145
|
+
*/
|
|
146
|
+
function computeConfidence(input) {
|
|
147
|
+
let provided = 0;
|
|
148
|
+
for (const field of SCORABLE_FIELDS) {
|
|
149
|
+
if (input[field] !== undefined) {
|
|
150
|
+
provided++;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return provided / SCORABLE_FIELDS.length;
|
|
154
|
+
}
|
|
155
|
+
// ── Public API ──────────────────────────────────────────────────────
|
|
156
|
+
/**
|
|
157
|
+
* Compute the PPA composite priority score for a single work item.
|
|
158
|
+
*
|
|
159
|
+
* P(w) = Sα × Dπ × Mφ × Eρ × (1 − Eτ) × (1 + HC) × Cκ
|
|
160
|
+
*/
|
|
161
|
+
export function computePriority(input, config) {
|
|
162
|
+
const timestamp = new Date().toISOString();
|
|
163
|
+
// ── Override path ──────────────────────────────────────────────
|
|
164
|
+
if (input.override) {
|
|
165
|
+
return {
|
|
166
|
+
composite: Infinity,
|
|
167
|
+
dimensions: {
|
|
168
|
+
soulAlignment: 1,
|
|
169
|
+
demandPressure: 1.5,
|
|
170
|
+
marketForce: MARKET_FORCE_MAX,
|
|
171
|
+
executionReality: 1,
|
|
172
|
+
entropyTax: 0,
|
|
173
|
+
humanCurve: 1,
|
|
174
|
+
calibration: 1,
|
|
175
|
+
},
|
|
176
|
+
confidence: 1,
|
|
177
|
+
timestamp,
|
|
178
|
+
override: {
|
|
179
|
+
reason: input.overrideReason ?? 'No reason provided',
|
|
180
|
+
expiry: input.overrideExpiry,
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
// ── Resolve HC weights ─────────────────────────────────────────
|
|
185
|
+
const hcWeights = {
|
|
186
|
+
explicit: config?.humanCurveWeights?.explicit ?? DEFAULT_HC_WEIGHTS.explicit,
|
|
187
|
+
consensus: config?.humanCurveWeights?.consensus ?? DEFAULT_HC_WEIGHTS.consensus,
|
|
188
|
+
decision: config?.humanCurveWeights?.decision ?? DEFAULT_HC_WEIGHTS.decision,
|
|
189
|
+
};
|
|
190
|
+
// ── Compute each dimension ────────────────────────────────────
|
|
191
|
+
const soulAlignment = computeSoulAlignment(input);
|
|
192
|
+
const demandPressure = computeDemandPressure(input);
|
|
193
|
+
const marketForce = computeMarketForce(input);
|
|
194
|
+
const executionReality = computeExecutionReality(input);
|
|
195
|
+
const entropyTax = computeEntropyTax(input);
|
|
196
|
+
const humanCurve = computeHumanCurve(input, hcWeights);
|
|
197
|
+
const calibration = computeCalibration(config);
|
|
198
|
+
// ── Composite ─────────────────────────────────────────────────
|
|
199
|
+
const composite = soulAlignment *
|
|
200
|
+
demandPressure *
|
|
201
|
+
marketForce *
|
|
202
|
+
executionReality *
|
|
203
|
+
(1 - entropyTax) *
|
|
204
|
+
(1 + humanCurve) *
|
|
205
|
+
calibration;
|
|
206
|
+
return {
|
|
207
|
+
composite,
|
|
208
|
+
dimensions: {
|
|
209
|
+
soulAlignment,
|
|
210
|
+
demandPressure,
|
|
211
|
+
marketForce,
|
|
212
|
+
executionReality,
|
|
213
|
+
entropyTax,
|
|
214
|
+
humanCurve,
|
|
215
|
+
calibration,
|
|
216
|
+
},
|
|
217
|
+
confidence: computeConfidence(input),
|
|
218
|
+
timestamp,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Score and rank multiple work items by descending composite priority.
|
|
223
|
+
* Override items (composite = Infinity) always sort first.
|
|
224
|
+
*/
|
|
225
|
+
export function rankWorkItems(items, config) {
|
|
226
|
+
return items
|
|
227
|
+
.map((item) => ({ ...item, score: computePriority(item, config) }))
|
|
228
|
+
.sort((a, b) => b.score.composite - a.score.composite);
|
|
229
|
+
}
|
|
230
|
+
//# sourceMappingURL=priority.js.map
|
package/dist/review.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PR Review orchestrator — thin wrapper around ReviewAgentRunner
|
|
3
|
+
* that handles context assembly and verdict extraction.
|
|
4
|
+
*/
|
|
5
|
+
import { ReviewAgentRunner, type ReviewType, type ReviewVerdict, type ReviewAgentConfig } from './runners/review-agent.js';
|
|
6
|
+
import type { Logger } from './logger.js';
|
|
7
|
+
export interface ReviewContext {
|
|
8
|
+
issueTitle: string;
|
|
9
|
+
issueBody: string;
|
|
10
|
+
acceptanceCriteria?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface ReviewOptions {
|
|
13
|
+
/** Anthropic API config overrides. */
|
|
14
|
+
apiConfig?: Omit<ReviewAgentConfig, 'reviewType'>;
|
|
15
|
+
/** Logger for diagnostic output. */
|
|
16
|
+
logger?: Logger;
|
|
17
|
+
/** Inject runner for testing. */
|
|
18
|
+
runner?: ReviewAgentRunner;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Execute a single review agent against a PR diff.
|
|
22
|
+
*
|
|
23
|
+
* @param prNumber - PR number (for logging/identification)
|
|
24
|
+
* @param diff - The full PR diff text
|
|
25
|
+
* @param reviewType - Which review perspective (testing, critic, security)
|
|
26
|
+
* @param context - Issue context for the review
|
|
27
|
+
* @param options - Optional configuration overrides
|
|
28
|
+
* @returns Review verdict with findings
|
|
29
|
+
*/
|
|
30
|
+
export declare function executeReview(prNumber: number, diff: string, reviewType: ReviewType, context: ReviewContext, options?: ReviewOptions): Promise<ReviewVerdict>;
|
|
31
|
+
//# sourceMappingURL=review.d.ts.map
|
package/dist/review.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PR Review orchestrator — thin wrapper around ReviewAgentRunner
|
|
3
|
+
* that handles context assembly and verdict extraction.
|
|
4
|
+
*/
|
|
5
|
+
import { ReviewAgentRunner, } from './runners/review-agent.js';
|
|
6
|
+
// ── Public API ───────────────────────────────────────────────────────
|
|
7
|
+
/**
|
|
8
|
+
* Execute a single review agent against a PR diff.
|
|
9
|
+
*
|
|
10
|
+
* @param prNumber - PR number (for logging/identification)
|
|
11
|
+
* @param diff - The full PR diff text
|
|
12
|
+
* @param reviewType - Which review perspective (testing, critic, security)
|
|
13
|
+
* @param context - Issue context for the review
|
|
14
|
+
* @param options - Optional configuration overrides
|
|
15
|
+
* @returns Review verdict with findings
|
|
16
|
+
*/
|
|
17
|
+
export async function executeReview(prNumber, diff, reviewType, context, options) {
|
|
18
|
+
const logger = options?.logger;
|
|
19
|
+
logger?.info?.(`Starting ${reviewType} review for PR #${prNumber}`);
|
|
20
|
+
const runner = options?.runner ??
|
|
21
|
+
new ReviewAgentRunner({
|
|
22
|
+
...options?.apiConfig,
|
|
23
|
+
reviewType,
|
|
24
|
+
});
|
|
25
|
+
const result = await runner.run({
|
|
26
|
+
issueId: `PR-${prNumber}`,
|
|
27
|
+
issueNumber: prNumber,
|
|
28
|
+
issueTitle: context.issueTitle,
|
|
29
|
+
issueBody: diff,
|
|
30
|
+
workDir: '',
|
|
31
|
+
branch: '',
|
|
32
|
+
constraints: {
|
|
33
|
+
maxFilesPerChange: 0,
|
|
34
|
+
requireTests: false,
|
|
35
|
+
blockedPaths: [],
|
|
36
|
+
},
|
|
37
|
+
// Reuse ciErrors field for acceptance criteria
|
|
38
|
+
ciErrors: context.acceptanceCriteria,
|
|
39
|
+
});
|
|
40
|
+
if (!result.success) {
|
|
41
|
+
logger?.error?.(`${reviewType} review failed: ${result.error}`);
|
|
42
|
+
return {
|
|
43
|
+
type: reviewType,
|
|
44
|
+
approved: false,
|
|
45
|
+
findings: [
|
|
46
|
+
{
|
|
47
|
+
severity: 'critical',
|
|
48
|
+
message: `Review agent failed: ${result.error ?? 'unknown error'}`,
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
summary: `${reviewType} review could not be completed`,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
const verdict = JSON.parse(result.summary);
|
|
56
|
+
logger?.info?.(`${reviewType} review complete: ${verdict.approved ? 'APPROVED' : 'CHANGES REQUESTED'} (${verdict.findings.length} findings)`);
|
|
57
|
+
return { ...verdict, type: reviewType };
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
logger?.error?.(`Failed to parse ${reviewType} verdict from runner output`);
|
|
61
|
+
return {
|
|
62
|
+
type: reviewType,
|
|
63
|
+
approved: false,
|
|
64
|
+
findings: [
|
|
65
|
+
{
|
|
66
|
+
severity: 'critical',
|
|
67
|
+
message: 'Failed to parse review verdict from runner output',
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
summary: `${reviewType} review verdict was not valid JSON`,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=review.js.map
|