@slope-dev/slope 1.35.0 → 1.37.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/cli/commands/guard.d.ts.map +1 -1
- package/dist/cli/commands/guard.js +32 -0
- package/dist/cli/commands/guard.js.map +1 -1
- package/dist/cli/commands/loop.d.ts.map +1 -1
- package/dist/cli/commands/loop.js +159 -10
- package/dist/cli/commands/loop.js.map +1 -1
- package/dist/cli/commands/org.d.ts +10 -0
- package/dist/cli/commands/org.d.ts.map +1 -0
- package/dist/cli/commands/org.js +102 -0
- package/dist/cli/commands/org.js.map +1 -0
- package/dist/cli/commands/review-state.js +2 -2
- package/dist/cli/commands/review-state.js.map +1 -1
- package/dist/cli/commands/session.d.ts.map +1 -1
- package/dist/cli/commands/session.js +251 -0
- package/dist/cli/commands/session.js.map +1 -1
- package/dist/cli/commands/sprint.d.ts.map +1 -1
- package/dist/cli/commands/sprint.js +205 -3
- package/dist/cli/commands/sprint.js.map +1 -1
- package/dist/cli/commands/transcript.d.ts.map +1 -1
- package/dist/cli/commands/transcript.js +110 -12
- package/dist/cli/commands/transcript.js.map +1 -1
- package/dist/cli/commands/workflow.d.ts +2 -0
- package/dist/cli/commands/workflow.d.ts.map +1 -0
- package/dist/cli/commands/workflow.js +165 -0
- package/dist/cli/commands/workflow.js.map +1 -0
- package/dist/cli/guards/claim-required.d.ts +1 -0
- package/dist/cli/guards/claim-required.d.ts.map +1 -1
- package/dist/cli/guards/claim-required.js +41 -2
- package/dist/cli/guards/claim-required.js.map +1 -1
- package/dist/cli/guards/hazard.d.ts +1 -0
- package/dist/cli/guards/hazard.d.ts.map +1 -1
- package/dist/cli/guards/hazard.js +61 -6
- package/dist/cli/guards/hazard.js.map +1 -1
- package/dist/cli/guards/review-tier.d.ts.map +1 -1
- package/dist/cli/guards/review-tier.js +3 -1
- package/dist/cli/guards/review-tier.js.map +1 -1
- package/dist/cli/guards/scope-drift.d.ts +1 -0
- package/dist/cli/guards/scope-drift.d.ts.map +1 -1
- package/dist/cli/guards/scope-drift.js +62 -7
- package/dist/cli/guards/scope-drift.js.map +1 -1
- package/dist/cli/guards/workflow-step-gate.d.ts +8 -0
- package/dist/cli/guards/workflow-step-gate.d.ts.map +1 -0
- package/dist/cli/guards/workflow-step-gate.js +59 -0
- package/dist/cli/guards/workflow-step-gate.js.map +1 -0
- package/dist/cli/index.js +15 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/loop/backlog.d.ts +6 -0
- package/dist/cli/loop/backlog.d.ts.map +1 -1
- package/dist/cli/loop/backlog.js +44 -1
- package/dist/cli/loop/backlog.js.map +1 -1
- package/dist/cli/loop/continuous.d.ts.map +1 -1
- package/dist/cli/loop/continuous.js +44 -8
- package/dist/cli/loop/continuous.js.map +1 -1
- package/dist/cli/loop/executor.d.ts.map +1 -1
- package/dist/cli/loop/executor.js +5 -3
- package/dist/cli/loop/executor.js.map +1 -1
- package/dist/cli/loop/model-selector.d.ts +5 -2
- package/dist/cli/loop/model-selector.d.ts.map +1 -1
- package/dist/cli/loop/model-selector.js +35 -2
- package/dist/cli/loop/model-selector.js.map +1 -1
- package/dist/cli/loop/parallel.d.ts +2 -2
- package/dist/cli/loop/parallel.d.ts.map +1 -1
- package/dist/cli/loop/parallel.js +72 -68
- package/dist/cli/loop/parallel.js.map +1 -1
- package/dist/cli/loop/types.d.ts +44 -1
- package/dist/cli/loop/types.d.ts.map +1 -1
- package/dist/cli/loop/types.js +2 -0
- package/dist/cli/loop/types.js.map +1 -1
- package/dist/cli/loop/workflow-adapter.d.ts +53 -0
- package/dist/cli/loop/workflow-adapter.d.ts.map +1 -0
- package/dist/cli/loop/workflow-adapter.js +123 -0
- package/dist/cli/loop/workflow-adapter.js.map +1 -0
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/cli/registry.js +20 -0
- package/dist/cli/registry.js.map +1 -1
- package/dist/core/analytics.d.ts +17 -0
- package/dist/core/analytics.d.ts.map +1 -1
- package/dist/core/analytics.js +59 -0
- package/dist/core/analytics.js.map +1 -1
- package/dist/core/guard.d.ts +5 -1
- package/dist/core/guard.d.ts.map +1 -1
- package/dist/core/guard.js +37 -0
- package/dist/core/guard.js.map +1 -1
- package/dist/core/index.d.ts +12 -4
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +10 -2
- package/dist/core/index.js.map +1 -1
- package/dist/core/loader.d.ts +5 -0
- package/dist/core/loader.d.ts.map +1 -1
- package/dist/core/loader.js +22 -4
- package/dist/core/loader.js.map +1 -1
- package/dist/core/org.d.ts +38 -0
- package/dist/core/org.d.ts.map +1 -0
- package/dist/core/org.js +112 -0
- package/dist/core/org.js.map +1 -0
- package/dist/core/store.d.ts +25 -1
- package/dist/core/store.d.ts.map +1 -1
- package/dist/core/types.d.ts +34 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/workflow-engine.d.ts +89 -0
- package/dist/core/workflow-engine.d.ts.map +1 -0
- package/dist/core/workflow-engine.js +223 -0
- package/dist/core/workflow-engine.js.map +1 -0
- package/dist/core/workflow-loader.d.ts +21 -0
- package/dist/core/workflow-loader.d.ts.map +1 -0
- package/dist/core/workflow-loader.js +110 -0
- package/dist/core/workflow-loader.js.map +1 -0
- package/dist/core/workflow-validator.d.ts +19 -0
- package/dist/core/workflow-validator.d.ts.map +1 -0
- package/dist/core/workflow-validator.js +166 -0
- package/dist/core/workflow-validator.js.map +1 -0
- package/dist/core/workflow.d.ts +51 -0
- package/dist/core/workflow.d.ts.map +1 -0
- package/dist/core/workflow.js +190 -0
- package/dist/core/workflow.js.map +1 -0
- package/dist/mcp/index.d.ts +1 -1
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +138 -2
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/index.test.js +10 -2
- package/dist/mcp/index.test.js.map +1 -1
- package/dist/mcp/registry.d.ts +1 -1
- package/dist/mcp/registry.d.ts.map +1 -1
- package/dist/mcp/registry.js +71 -0
- package/dist/mcp/registry.js.map +1 -1
- package/dist/store/index.d.ts +25 -1
- package/dist/store/index.d.ts.map +1 -1
- package/dist/store/index.js +144 -0
- package/dist/store/index.js.map +1 -1
- package/dist/store-pg/index.d.ts +25 -1
- package/dist/store-pg/index.d.ts.map +1 -1
- package/dist/store-pg/index.js +180 -0
- package/dist/store-pg/index.js.map +1 -1
- package/package.json +4 -2
- package/src/core/workflows/sprint-autonomous.yaml +59 -0
- package/src/core/workflows/sprint-lightweight.yaml +39 -0
- package/src/core/workflows/sprint-standard.yaml +77 -0
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
// SLOPE — Workflow Execution Engine
|
|
2
|
+
// Controls step ordering, validates state transitions, and persists execution state.
|
|
3
|
+
// --- State Machine ---
|
|
4
|
+
/** Valid status transitions for workflow executions */
|
|
5
|
+
const VALID_TRANSITIONS = {
|
|
6
|
+
running: ['paused', 'completed', 'failed'],
|
|
7
|
+
paused: ['running', 'failed'],
|
|
8
|
+
completed: [],
|
|
9
|
+
failed: [],
|
|
10
|
+
};
|
|
11
|
+
function isValidTransition(from, to) {
|
|
12
|
+
return VALID_TRANSITIONS[from]?.includes(to) ?? false;
|
|
13
|
+
}
|
|
14
|
+
// --- Engine ---
|
|
15
|
+
export class WorkflowEngine {
|
|
16
|
+
/**
|
|
17
|
+
* Start a new workflow execution.
|
|
18
|
+
* Creates a store record and positions at the first step of the first phase.
|
|
19
|
+
*/
|
|
20
|
+
async start(def, store, opts = {}) {
|
|
21
|
+
if (def.phases.length === 0) {
|
|
22
|
+
throw new Error('Workflow has no phases');
|
|
23
|
+
}
|
|
24
|
+
const firstPhase = def.phases[0];
|
|
25
|
+
if (firstPhase.steps.length === 0) {
|
|
26
|
+
throw new Error(`Phase "${firstPhase.id}" has no steps`);
|
|
27
|
+
}
|
|
28
|
+
const execution = await store.startExecution({
|
|
29
|
+
workflow_name: def.name,
|
|
30
|
+
sprint_id: opts.sprint_id,
|
|
31
|
+
variables: opts.variables,
|
|
32
|
+
session_id: opts.session_id,
|
|
33
|
+
});
|
|
34
|
+
// Position at first step
|
|
35
|
+
await store.updateExecutionState(execution.id, firstPhase.id, firstPhase.steps[0].id);
|
|
36
|
+
return {
|
|
37
|
+
...execution,
|
|
38
|
+
current_phase: firstPhase.id,
|
|
39
|
+
current_step: firstPhase.steps[0].id,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Determine what should happen next for an execution.
|
|
44
|
+
* Returns the current step to execute, or is_complete if done.
|
|
45
|
+
*/
|
|
46
|
+
async next(executionId, def, store) {
|
|
47
|
+
const execution = await this.requireExecution(executionId, store);
|
|
48
|
+
if (execution.status === 'completed') {
|
|
49
|
+
return { is_complete: true };
|
|
50
|
+
}
|
|
51
|
+
if (execution.status === 'failed') {
|
|
52
|
+
throw new Error(`Workflow execution "${executionId}" has failed`);
|
|
53
|
+
}
|
|
54
|
+
if (execution.status === 'paused') {
|
|
55
|
+
throw new Error(`Workflow execution "${executionId}" is paused — resume before calling next()`);
|
|
56
|
+
}
|
|
57
|
+
// Find the next incomplete step
|
|
58
|
+
return this.findNextStep(execution, def);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Complete a step and advance the execution.
|
|
62
|
+
* Records the step result and moves to the next step/phase.
|
|
63
|
+
*/
|
|
64
|
+
async complete(executionId, stepId, result, def, store) {
|
|
65
|
+
const execution = await this.requireExecution(executionId, store);
|
|
66
|
+
this.validateCurrentStep(execution, stepId);
|
|
67
|
+
// Determine current item for repeat_for phases
|
|
68
|
+
const currentInfo = this.findNextStep(execution, def);
|
|
69
|
+
await store.recordStepResult({
|
|
70
|
+
execution_id: executionId,
|
|
71
|
+
step_id: stepId,
|
|
72
|
+
phase: execution.current_phase,
|
|
73
|
+
status: 'completed',
|
|
74
|
+
output: result.output,
|
|
75
|
+
exit_code: result.exit_code,
|
|
76
|
+
item: currentInfo.current_item,
|
|
77
|
+
started_at: result.started_at,
|
|
78
|
+
});
|
|
79
|
+
return this.advanceToNext(executionId, execution, def, store);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Skip a step and advance. Skipped steps count as "done" for phase advancement.
|
|
83
|
+
*/
|
|
84
|
+
async skip(executionId, stepId, reason, def, store) {
|
|
85
|
+
const execution = await this.requireExecution(executionId, store);
|
|
86
|
+
this.validateCurrentStep(execution, stepId);
|
|
87
|
+
// Determine current item for repeat_for phases
|
|
88
|
+
const currentInfo = this.findNextStep(execution, def);
|
|
89
|
+
await store.recordStepResult({
|
|
90
|
+
execution_id: executionId,
|
|
91
|
+
step_id: stepId,
|
|
92
|
+
phase: execution.current_phase,
|
|
93
|
+
status: 'skipped',
|
|
94
|
+
output: { reason },
|
|
95
|
+
item: currentInfo.current_item,
|
|
96
|
+
});
|
|
97
|
+
return this.advanceToNext(executionId, execution, def, store);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Transition execution status (e.g., fail).
|
|
101
|
+
* Validates the transition against the state machine.
|
|
102
|
+
* Note: pause/resume will be added in S4 when the loop bridge needs signal handling.
|
|
103
|
+
*/
|
|
104
|
+
async fail(executionId, store) {
|
|
105
|
+
const execution = await this.requireExecution(executionId, store);
|
|
106
|
+
if (!isValidTransition(execution.status, 'failed')) {
|
|
107
|
+
throw new Error(`Invalid workflow transition: "${execution.status}" → "failed". ` +
|
|
108
|
+
`Valid transitions from "${execution.status}": ${VALID_TRANSITIONS[execution.status]?.join(', ') || 'none'}`);
|
|
109
|
+
}
|
|
110
|
+
await store.completeExecution(executionId, 'failed');
|
|
111
|
+
}
|
|
112
|
+
// --- Private helpers ---
|
|
113
|
+
async requireExecution(id, store) {
|
|
114
|
+
const execution = await store.getExecution(id);
|
|
115
|
+
if (!execution) {
|
|
116
|
+
throw new Error(`Workflow execution "${id}" not found`);
|
|
117
|
+
}
|
|
118
|
+
return execution;
|
|
119
|
+
}
|
|
120
|
+
validateCurrentStep(execution, stepId) {
|
|
121
|
+
if (execution.status !== 'running') {
|
|
122
|
+
throw new Error(`Cannot complete step on execution with status "${execution.status}" — must be "running"`);
|
|
123
|
+
}
|
|
124
|
+
if (execution.current_step !== stepId) {
|
|
125
|
+
throw new Error(`Step mismatch: execution is at "${execution.current_step}" but "${stepId}" was provided`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Find the next incomplete step in the workflow.
|
|
130
|
+
* Handles repeat_for phases by expanding the iteration.
|
|
131
|
+
*/
|
|
132
|
+
findNextStep(execution, def) {
|
|
133
|
+
const completedSet = new Set(execution.completed_steps.map((s) => `${s.phase}:${s.step_id}${s.item ? ':' + s.item : ''}`));
|
|
134
|
+
for (const phase of def.phases) {
|
|
135
|
+
if (phase.repeat_for) {
|
|
136
|
+
// Expand the repeat_for phase
|
|
137
|
+
const items = this.getRepeatItems(phase.repeat_for, execution.variables);
|
|
138
|
+
for (let itemIdx = 0; itemIdx < items.length; itemIdx++) {
|
|
139
|
+
const item = items[itemIdx];
|
|
140
|
+
for (const step of phase.steps) {
|
|
141
|
+
const key = `${phase.id}:${step.id}:${item}`;
|
|
142
|
+
if (!completedSet.has(key)) {
|
|
143
|
+
return {
|
|
144
|
+
is_complete: false,
|
|
145
|
+
phase: phase.id,
|
|
146
|
+
step,
|
|
147
|
+
current_item: item,
|
|
148
|
+
total_items: items.length,
|
|
149
|
+
item_index: itemIdx,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
for (const step of phase.steps) {
|
|
157
|
+
const key = `${phase.id}:${step.id}`;
|
|
158
|
+
if (!completedSet.has(key)) {
|
|
159
|
+
return {
|
|
160
|
+
is_complete: false,
|
|
161
|
+
phase: phase.id,
|
|
162
|
+
step,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return { is_complete: true };
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* After completing/skipping a step, advance to the next step or complete the workflow.
|
|
172
|
+
*/
|
|
173
|
+
async advanceToNext(executionId, _execution, def, store) {
|
|
174
|
+
// Re-fetch execution to get updated completed_steps
|
|
175
|
+
const updated = await this.requireExecution(executionId, store);
|
|
176
|
+
const nextInfo = this.findNextStep(updated, def);
|
|
177
|
+
if (nextInfo.is_complete) {
|
|
178
|
+
await store.completeExecution(executionId, 'completed');
|
|
179
|
+
return { is_complete: true };
|
|
180
|
+
}
|
|
181
|
+
await store.updateExecutionState(executionId, nextInfo.phase, nextInfo.step.id);
|
|
182
|
+
return {
|
|
183
|
+
advanced_to: { phase: nextInfo.phase, step: nextInfo.step.id },
|
|
184
|
+
is_complete: false,
|
|
185
|
+
next_action: this.describeStep(nextInfo.step),
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Get the items to iterate over for a repeat_for phase.
|
|
190
|
+
* Looks up the variable name and splits comma-separated values or parses JSON array.
|
|
191
|
+
*/
|
|
192
|
+
getRepeatItems(variableName, variables) {
|
|
193
|
+
const value = variables[variableName];
|
|
194
|
+
if (!value)
|
|
195
|
+
return [];
|
|
196
|
+
// Try JSON array first
|
|
197
|
+
try {
|
|
198
|
+
const parsed = JSON.parse(value);
|
|
199
|
+
if (Array.isArray(parsed))
|
|
200
|
+
return parsed.map(String);
|
|
201
|
+
}
|
|
202
|
+
catch {
|
|
203
|
+
// Not JSON — treat as comma-separated
|
|
204
|
+
}
|
|
205
|
+
return value.split(',').map(s => s.trim()).filter(Boolean);
|
|
206
|
+
}
|
|
207
|
+
/** Human-readable description of what a step expects */
|
|
208
|
+
describeStep(step) {
|
|
209
|
+
switch (step.type) {
|
|
210
|
+
case 'command':
|
|
211
|
+
return `Run command: ${step.command}`;
|
|
212
|
+
case 'validation':
|
|
213
|
+
return `Validate: ${step.conditions?.join(', ') ?? step.prompt ?? step.id}`;
|
|
214
|
+
case 'agent_input':
|
|
215
|
+
return `Provide input: ${step.required_fields?.join(', ') ?? step.prompt ?? step.id}`;
|
|
216
|
+
case 'agent_work':
|
|
217
|
+
return `${step.prompt ?? `Execute: ${step.id}`}`;
|
|
218
|
+
default:
|
|
219
|
+
return step.id;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
//# sourceMappingURL=workflow-engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-engine.js","sourceRoot":"","sources":["../../src/core/workflow-engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { WorkflowDefinition } from './workflow.js';
|
|
2
|
+
/** Summary of an available workflow */
|
|
3
|
+
export interface WorkflowSummary {
|
|
4
|
+
name: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
version: string;
|
|
7
|
+
source: 'project' | 'built-in';
|
|
8
|
+
path: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Load a workflow by name.
|
|
12
|
+
* Search order: project `.slope/workflows/<name>.yaml` → built-in defaults.
|
|
13
|
+
* Throws if not found.
|
|
14
|
+
*/
|
|
15
|
+
export declare function loadWorkflow(name: string, cwd: string): WorkflowDefinition;
|
|
16
|
+
/**
|
|
17
|
+
* List all available workflows (project + built-in).
|
|
18
|
+
* Project workflows override built-in ones with the same name.
|
|
19
|
+
*/
|
|
20
|
+
export declare function listWorkflows(cwd: string): WorkflowSummary[];
|
|
21
|
+
//# sourceMappingURL=workflow-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-loader.d.ts","sourceRoot":"","sources":["../../src/core/workflow-loader.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAIxD,uCAAuC;AACvC,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,SAAS,GAAG,UAAU,CAAC;IAC/B,IAAI,EAAE,MAAM,CAAC;CACd;AAqBD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,kBAAkB,CAuB1E;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,EAAE,CA4C5D"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
// SLOPE — Workflow Loader
|
|
2
|
+
// Loads workflow definitions from project and built-in locations.
|
|
3
|
+
import { readFileSync, existsSync, readdirSync } from 'node:fs';
|
|
4
|
+
import { join, basename, dirname } from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
import { parseWorkflow } from './workflow.js';
|
|
7
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
/** Resolve the built-in workflows directory (handles both src/ and dist/) */
|
|
9
|
+
function builtinDir() {
|
|
10
|
+
// In src/core/ → ../core/workflows
|
|
11
|
+
// In dist/core/ → ../../src/core/workflows
|
|
12
|
+
const srcPath = join(__dirname, 'workflows');
|
|
13
|
+
if (existsSync(srcPath))
|
|
14
|
+
return srcPath;
|
|
15
|
+
// If running from dist/, walk up to find src/
|
|
16
|
+
const fromDist = join(__dirname, '..', '..', 'src', 'core', 'workflows');
|
|
17
|
+
if (existsSync(fromDist))
|
|
18
|
+
return fromDist;
|
|
19
|
+
return srcPath; // fallback
|
|
20
|
+
}
|
|
21
|
+
/** Resolve the project workflows directory */
|
|
22
|
+
function projectDir(cwd) {
|
|
23
|
+
return join(cwd, '.slope', 'workflows');
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Load a workflow by name.
|
|
27
|
+
* Search order: project `.slope/workflows/<name>.yaml` → built-in defaults.
|
|
28
|
+
* Throws if not found.
|
|
29
|
+
*/
|
|
30
|
+
export function loadWorkflow(name, cwd) {
|
|
31
|
+
// Normalize: strip .yaml if provided
|
|
32
|
+
const baseName = name.replace(/\.yaml$/, '');
|
|
33
|
+
const fileName = `${baseName}.yaml`;
|
|
34
|
+
// 1. Project directory
|
|
35
|
+
const projectPath = join(projectDir(cwd), fileName);
|
|
36
|
+
if (existsSync(projectPath)) {
|
|
37
|
+
return parseYamlFile(projectPath);
|
|
38
|
+
}
|
|
39
|
+
// 2. Built-in defaults
|
|
40
|
+
const builtinPath = join(builtinDir(), fileName);
|
|
41
|
+
if (existsSync(builtinPath)) {
|
|
42
|
+
return parseYamlFile(builtinPath);
|
|
43
|
+
}
|
|
44
|
+
throw new Error(`Workflow "${baseName}" not found. Searched:\n` +
|
|
45
|
+
` - ${projectPath}\n` +
|
|
46
|
+
` - ${builtinPath}\n` +
|
|
47
|
+
`Use "slope workflow list" to see available workflows.`);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* List all available workflows (project + built-in).
|
|
51
|
+
* Project workflows override built-in ones with the same name.
|
|
52
|
+
*/
|
|
53
|
+
export function listWorkflows(cwd) {
|
|
54
|
+
const summaries = new Map();
|
|
55
|
+
// Built-in workflows (loaded first, can be overridden)
|
|
56
|
+
const builtIn = builtinDir();
|
|
57
|
+
if (existsSync(builtIn)) {
|
|
58
|
+
for (const file of listYamlFiles(builtIn)) {
|
|
59
|
+
const name = basename(file, '.yaml');
|
|
60
|
+
try {
|
|
61
|
+
const def = parseYamlFile(join(builtIn, file));
|
|
62
|
+
summaries.set(name, {
|
|
63
|
+
name: def.name,
|
|
64
|
+
description: def.description,
|
|
65
|
+
version: def.version,
|
|
66
|
+
source: 'built-in',
|
|
67
|
+
path: join(builtIn, file),
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// Skip invalid built-in files
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// Project workflows (override built-in)
|
|
76
|
+
const project = projectDir(cwd);
|
|
77
|
+
if (existsSync(project)) {
|
|
78
|
+
for (const file of listYamlFiles(project)) {
|
|
79
|
+
const name = basename(file, '.yaml');
|
|
80
|
+
try {
|
|
81
|
+
const def = parseYamlFile(join(project, file));
|
|
82
|
+
summaries.set(name, {
|
|
83
|
+
name: def.name,
|
|
84
|
+
description: def.description,
|
|
85
|
+
version: def.version,
|
|
86
|
+
source: 'project',
|
|
87
|
+
path: join(project, file),
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
// Skip invalid project files
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return [...summaries.values()].sort((a, b) => a.name.localeCompare(b.name));
|
|
96
|
+
}
|
|
97
|
+
// --- Helpers ---
|
|
98
|
+
function parseYamlFile(filePath) {
|
|
99
|
+
const content = readFileSync(filePath, 'utf8');
|
|
100
|
+
return parseWorkflow(content);
|
|
101
|
+
}
|
|
102
|
+
function listYamlFiles(dir) {
|
|
103
|
+
try {
|
|
104
|
+
return readdirSync(dir).filter(f => f.endsWith('.yaml'));
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
return [];
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=workflow-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-loader.js","sourceRoot":"","sources":["../../src/core/workflow-loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { WorkflowDefinition } from './workflow.js';
|
|
2
|
+
/** A single validation error or warning */
|
|
3
|
+
export interface ValidationIssue {
|
|
4
|
+
message: string;
|
|
5
|
+
/** Dot-path to the problematic element (e.g., "phases[0].steps[1]") */
|
|
6
|
+
path?: string;
|
|
7
|
+
}
|
|
8
|
+
/** Result of validating a workflow definition */
|
|
9
|
+
export interface WorkflowValidationResult {
|
|
10
|
+
valid: boolean;
|
|
11
|
+
errors: ValidationIssue[];
|
|
12
|
+
warnings: ValidationIssue[];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Validate a parsed WorkflowDefinition for structural issues.
|
|
16
|
+
* Does NOT re-validate YAML parsing — assumes parseWorkflow() already succeeded.
|
|
17
|
+
*/
|
|
18
|
+
export declare function validateWorkflow(def: WorkflowDefinition): WorkflowValidationResult;
|
|
19
|
+
//# sourceMappingURL=workflow-validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-validator.d.ts","sourceRoot":"","sources":["../../src/core/workflow-validator.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAgB,MAAM,eAAe,CAAC;AAGtE,2CAA2C;AAC3C,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,uEAAuE;IACvE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,iDAAiD;AACjD,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,kBAAkB,GAAG,wBAAwB,CA6HlF"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
// SLOPE — Workflow Validator
|
|
2
|
+
// Validates WorkflowDefinitions for structural correctness before execution.
|
|
3
|
+
import { VALID_STEP_TYPES } from './workflow.js';
|
|
4
|
+
/**
|
|
5
|
+
* Validate a parsed WorkflowDefinition for structural issues.
|
|
6
|
+
* Does NOT re-validate YAML parsing — assumes parseWorkflow() already succeeded.
|
|
7
|
+
*/
|
|
8
|
+
export function validateWorkflow(def) {
|
|
9
|
+
const errors = [];
|
|
10
|
+
const warnings = [];
|
|
11
|
+
// Version check
|
|
12
|
+
if (def.version !== '1') {
|
|
13
|
+
errors.push({ message: `Unsupported workflow version: "${def.version}" (expected "1")` });
|
|
14
|
+
}
|
|
15
|
+
// Name check
|
|
16
|
+
if (!def.name || def.name.trim().length === 0) {
|
|
17
|
+
errors.push({ message: 'Workflow name must be a non-empty string' });
|
|
18
|
+
}
|
|
19
|
+
// Collect all step IDs for uniqueness check
|
|
20
|
+
const allStepIds = new Map(); // step_id → phase_id
|
|
21
|
+
// Collect all variable references found in steps
|
|
22
|
+
const referencedVars = new Set();
|
|
23
|
+
const definedVars = new Set(Object.keys(def.variables ?? {}));
|
|
24
|
+
if (def.phases.length === 0) {
|
|
25
|
+
warnings.push({ message: 'Workflow has no phases' });
|
|
26
|
+
}
|
|
27
|
+
// Phase-level checks
|
|
28
|
+
const phaseIds = new Set();
|
|
29
|
+
for (let pi = 0; pi < def.phases.length; pi++) {
|
|
30
|
+
const phase = def.phases[pi];
|
|
31
|
+
const pPath = `phases[${pi}]`;
|
|
32
|
+
// Duplicate phase ID
|
|
33
|
+
if (phaseIds.has(phase.id)) {
|
|
34
|
+
errors.push({ message: `Duplicate phase ID: "${phase.id}"`, path: pPath });
|
|
35
|
+
}
|
|
36
|
+
phaseIds.add(phase.id);
|
|
37
|
+
// Empty steps
|
|
38
|
+
if (phase.steps.length === 0) {
|
|
39
|
+
warnings.push({ message: `Phase "${phase.id}" has no steps`, path: pPath });
|
|
40
|
+
}
|
|
41
|
+
// repeat_for variable reference
|
|
42
|
+
if (phase.repeat_for) {
|
|
43
|
+
referencedVars.add(phase.repeat_for);
|
|
44
|
+
if (definedVars.size > 0 && !definedVars.has(phase.repeat_for)) {
|
|
45
|
+
warnings.push({
|
|
46
|
+
message: `Phase "${phase.id}" references variable "${phase.repeat_for}" in repeat_for, but it is not defined in variables`,
|
|
47
|
+
path: `${pPath}.repeat_for`,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
// on_timeout only makes sense with repeat_for
|
|
51
|
+
if (phase.timeout_per_item && !phase.on_timeout) {
|
|
52
|
+
warnings.push({
|
|
53
|
+
message: `Phase "${phase.id}" has timeout_per_item but no on_timeout behavior`,
|
|
54
|
+
path: `${pPath}.on_timeout`,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
// on_timeout without repeat_for
|
|
60
|
+
if (phase.on_timeout) {
|
|
61
|
+
warnings.push({
|
|
62
|
+
message: `Phase "${phase.id}" has on_timeout but no repeat_for — on_timeout is ignored`,
|
|
63
|
+
path: `${pPath}.on_timeout`,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// Step-level checks
|
|
68
|
+
for (let si = 0; si < phase.steps.length; si++) {
|
|
69
|
+
const step = phase.steps[si];
|
|
70
|
+
const sPath = `${pPath}.steps[${si}]`;
|
|
71
|
+
// Duplicate step ID across all phases
|
|
72
|
+
if (allStepIds.has(step.id)) {
|
|
73
|
+
errors.push({
|
|
74
|
+
message: `Duplicate step ID: "${step.id}" (also in phase "${allStepIds.get(step.id)}")`,
|
|
75
|
+
path: sPath,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
allStepIds.set(step.id, phase.id);
|
|
79
|
+
// Valid step type
|
|
80
|
+
if (!VALID_STEP_TYPES.has(step.type)) {
|
|
81
|
+
errors.push({
|
|
82
|
+
message: `Invalid step type: "${step.type}"`,
|
|
83
|
+
path: `${sPath}.type`,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
// Type-specific validation
|
|
87
|
+
validateStepByType(step, sPath, errors, warnings);
|
|
88
|
+
// blocks_next on terminal step is redundant
|
|
89
|
+
if (step.blocks_next && si === phase.steps.length - 1) {
|
|
90
|
+
warnings.push({
|
|
91
|
+
message: `Step "${step.id}" has blocks_next but is the last step in its phase — this is redundant`,
|
|
92
|
+
path: `${sPath}.blocks_next`,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
// Collect variable references from string fields
|
|
96
|
+
collectVarRefs(step.command, referencedVars);
|
|
97
|
+
collectVarRefs(step.prompt, referencedVars);
|
|
98
|
+
if (step.rules)
|
|
99
|
+
step.rules.forEach(r => collectVarRefs(r, referencedVars));
|
|
100
|
+
if (step.conditions)
|
|
101
|
+
step.conditions.forEach(c => collectVarRefs(c, referencedVars));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
// Warn about unreferenced variables
|
|
105
|
+
for (const varName of definedVars) {
|
|
106
|
+
if (!referencedVars.has(varName)) {
|
|
107
|
+
warnings.push({
|
|
108
|
+
message: `Variable "${varName}" is defined but never referenced`,
|
|
109
|
+
path: `variables.${varName}`,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
valid: errors.length === 0,
|
|
115
|
+
errors,
|
|
116
|
+
warnings,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
/** Validate type-specific step requirements */
|
|
120
|
+
function validateStepByType(step, path, errors, warnings) {
|
|
121
|
+
switch (step.type) {
|
|
122
|
+
case 'command':
|
|
123
|
+
if (!step.command) {
|
|
124
|
+
errors.push({
|
|
125
|
+
message: `Command step "${step.id}" must have a "command" field`,
|
|
126
|
+
path: `${path}.command`,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
break;
|
|
130
|
+
case 'validation':
|
|
131
|
+
if (!step.conditions?.length && !step.command) {
|
|
132
|
+
warnings.push({
|
|
133
|
+
message: `Validation step "${step.id}" has no conditions or command — it will always pass`,
|
|
134
|
+
path,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
break;
|
|
138
|
+
case 'agent_input':
|
|
139
|
+
if (!step.required_fields?.length && !step.prompt) {
|
|
140
|
+
warnings.push({
|
|
141
|
+
message: `Agent input step "${step.id}" has no required_fields or prompt`,
|
|
142
|
+
path,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
break;
|
|
146
|
+
case 'agent_work':
|
|
147
|
+
if (!step.prompt && !step.rules?.length) {
|
|
148
|
+
warnings.push({
|
|
149
|
+
message: `Agent work step "${step.id}" has no prompt or rules — agent has no guidance`,
|
|
150
|
+
path,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/** Extract ${varName} references from a string */
|
|
157
|
+
function collectVarRefs(str, refs) {
|
|
158
|
+
if (!str)
|
|
159
|
+
return;
|
|
160
|
+
const pattern = /\$\{([a-zA-Z_][a-zA-Z0-9_]*)\}/g;
|
|
161
|
+
let match;
|
|
162
|
+
while ((match = pattern.exec(str)) !== null) {
|
|
163
|
+
refs.add(match[1]);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=workflow-validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-validator.js","sourceRoot":"","sources":["../../src/core/workflow-validator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/** Variable definition for workflow parameterization */
|
|
2
|
+
export interface WorkflowVariable {
|
|
3
|
+
required?: boolean;
|
|
4
|
+
type?: 'string' | 'integer' | 'array';
|
|
5
|
+
pattern?: string;
|
|
6
|
+
default?: string;
|
|
7
|
+
}
|
|
8
|
+
/** A single step within a workflow phase */
|
|
9
|
+
export interface WorkflowStep {
|
|
10
|
+
id: string;
|
|
11
|
+
type: 'command' | 'validation' | 'agent_input' | 'agent_work';
|
|
12
|
+
prompt?: string;
|
|
13
|
+
command?: string;
|
|
14
|
+
checkpoint?: string;
|
|
15
|
+
blocks_next?: boolean;
|
|
16
|
+
rules?: string[];
|
|
17
|
+
required_fields?: string[];
|
|
18
|
+
/** Validation conditions (for type=validation) */
|
|
19
|
+
conditions?: string[];
|
|
20
|
+
}
|
|
21
|
+
/** A phase containing ordered steps */
|
|
22
|
+
export interface WorkflowPhase {
|
|
23
|
+
id: string;
|
|
24
|
+
steps: WorkflowStep[];
|
|
25
|
+
/** Variable name containing array to iterate over */
|
|
26
|
+
repeat_for?: string;
|
|
27
|
+
/** Timeout in seconds for each repeated item */
|
|
28
|
+
timeout_per_item?: number;
|
|
29
|
+
/** Behavior when a repeated item times out */
|
|
30
|
+
on_timeout?: 'fail' | 'log_blocker_and_skip';
|
|
31
|
+
}
|
|
32
|
+
/** Top-level workflow definition */
|
|
33
|
+
export interface WorkflowDefinition {
|
|
34
|
+
name: string;
|
|
35
|
+
version: string;
|
|
36
|
+
description?: string;
|
|
37
|
+
variables?: Record<string, WorkflowVariable>;
|
|
38
|
+
phases: WorkflowPhase[];
|
|
39
|
+
}
|
|
40
|
+
/** Parse a YAML string into a WorkflowDefinition. Throws on invalid structure. */
|
|
41
|
+
export declare function parseWorkflow(yaml: string): WorkflowDefinition;
|
|
42
|
+
/** Valid step types for workflow definitions. Shared with the validator. */
|
|
43
|
+
export declare const VALID_STEP_TYPES: Set<string>;
|
|
44
|
+
/**
|
|
45
|
+
* Resolve `${varName}` references in all string values of a workflow definition.
|
|
46
|
+
* - Top-level string keys only (no nesting like `${x.y}`)
|
|
47
|
+
* - Missing variable at resolve time → error
|
|
48
|
+
* - Escaped `\${literal}` → `${literal}`
|
|
49
|
+
*/
|
|
50
|
+
export declare function resolveVariables(def: WorkflowDefinition, vars: Record<string, string>): WorkflowDefinition;
|
|
51
|
+
//# sourceMappingURL=workflow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow.d.ts","sourceRoot":"","sources":["../../src/core/workflow.ts"],"names":[],"mappings":"AAOA,wDAAwD;AACxD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,4CAA4C;AAC5C,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,SAAS,GAAG,YAAY,GAAG,aAAa,GAAG,YAAY,CAAC;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,kDAAkD;IAClD,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,uCAAuC;AACvC,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,qDAAqD;IACrD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gDAAgD;IAChD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,GAAG,sBAAsB,CAAC;CAC9C;AAED,oCAAoC;AACpC,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAC7C,MAAM,EAAE,aAAa,EAAE,CAAC;CACzB;AAID,kFAAkF;AAClF,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,CA0C9D;AAuBD,4EAA4E;AAC5E,eAAO,MAAM,gBAAgB,aAAkE,CAAC;AAoEhG;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,kBAAkB,EACvB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC3B,kBAAkB,CA0CpB"}
|