@exaudeus/workrail 0.1.10 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -34,6 +34,8 @@ export declare class DefaultWorkflowService implements WorkflowService {
|
|
|
34
34
|
context?: ConditionContext;
|
|
35
35
|
}>;
|
|
36
36
|
private buildStepPrompt;
|
|
37
|
+
private collectConditionVars;
|
|
38
|
+
private collectEqualsValues;
|
|
37
39
|
private findLoopStepById;
|
|
38
40
|
validateStepOutput(workflowId: string, stepId: string, output: string): Promise<{
|
|
39
41
|
valid: boolean;
|
|
@@ -189,6 +189,61 @@ class DefaultWorkflowService {
|
|
|
189
189
|
}
|
|
190
190
|
return this.getNextStep(workflowId, completedSteps, loopStartSizeCheck.context);
|
|
191
191
|
}
|
|
192
|
+
if (!nextStep) {
|
|
193
|
+
const remainingConditionalSteps = workflow.steps.filter((step) => {
|
|
194
|
+
if (completed.includes(step.id))
|
|
195
|
+
return false;
|
|
196
|
+
if (loopBodySteps.has(step.id))
|
|
197
|
+
return false;
|
|
198
|
+
return !!step.runCondition;
|
|
199
|
+
});
|
|
200
|
+
if (remainingConditionalSteps.length > 0) {
|
|
201
|
+
const requiredVars = new Set();
|
|
202
|
+
const allowedValues = {};
|
|
203
|
+
for (const step of remainingConditionalSteps) {
|
|
204
|
+
const condition = step.runCondition;
|
|
205
|
+
this.collectConditionVars(condition, requiredVars);
|
|
206
|
+
this.collectEqualsValues(condition, allowedValues);
|
|
207
|
+
}
|
|
208
|
+
const issues = [];
|
|
209
|
+
for (const variableName of requiredVars) {
|
|
210
|
+
const currentValue = enhancedContext[variableName];
|
|
211
|
+
const allowed = allowedValues[variableName]
|
|
212
|
+
? Array.from(allowedValues[variableName])
|
|
213
|
+
: [];
|
|
214
|
+
if (currentValue === undefined || currentValue === null || currentValue === '') {
|
|
215
|
+
if (allowed.length > 0) {
|
|
216
|
+
issues.push(`Set '${variableName}' to one of: ${allowed.map(v => `'${v}'`).join(', ')}`);
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
issues.push(`Provide a value for '${variableName}'`);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
else if (allowed.length > 0) {
|
|
223
|
+
const matchesExactly = allowed.some(v => v === String(currentValue));
|
|
224
|
+
const matchesCaseInsensitive = allowed.some(v => v.toLowerCase() === String(currentValue).toLowerCase());
|
|
225
|
+
if (!matchesExactly) {
|
|
226
|
+
if (matchesCaseInsensitive) {
|
|
227
|
+
issues.push(`Normalize casing for '${variableName}': use one of ${allowed.map(v => `'${v}'`).join(', ')} (current '${currentValue}')`);
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
issues.push(`Adjust '${variableName}' to one of: ${allowed.map(v => `'${v}'`).join(', ')} (current '${currentValue}')`);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
if (issues.length > 0) {
|
|
236
|
+
return {
|
|
237
|
+
step: null,
|
|
238
|
+
guidance: {
|
|
239
|
+
prompt: `No eligible step due to unmet conditions. Please update context:\n- ${issues.join('\n- ')}`
|
|
240
|
+
},
|
|
241
|
+
isComplete: false,
|
|
242
|
+
context: enhancedContext
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
192
247
|
const isComplete = !nextStep;
|
|
193
248
|
let finalPrompt = 'Workflow complete.';
|
|
194
249
|
if (nextStep) {
|
|
@@ -232,6 +287,46 @@ class DefaultWorkflowService {
|
|
|
232
287
|
}
|
|
233
288
|
return finalPrompt;
|
|
234
289
|
}
|
|
290
|
+
collectConditionVars(condition, sink) {
|
|
291
|
+
if (!condition || typeof condition !== 'object')
|
|
292
|
+
return;
|
|
293
|
+
if (typeof condition.var === 'string' && condition.var.length > 0) {
|
|
294
|
+
sink.add(condition.var);
|
|
295
|
+
}
|
|
296
|
+
if (Array.isArray(condition.and)) {
|
|
297
|
+
for (const sub of condition.and)
|
|
298
|
+
this.collectConditionVars(sub, sink);
|
|
299
|
+
}
|
|
300
|
+
if (Array.isArray(condition.or)) {
|
|
301
|
+
for (const sub of condition.or)
|
|
302
|
+
this.collectConditionVars(sub, sink);
|
|
303
|
+
}
|
|
304
|
+
if (condition.not)
|
|
305
|
+
this.collectConditionVars(condition.not, sink);
|
|
306
|
+
}
|
|
307
|
+
collectEqualsValues(condition, sink) {
|
|
308
|
+
if (!condition || typeof condition !== 'object')
|
|
309
|
+
return;
|
|
310
|
+
if (typeof condition.var === 'string' && Object.prototype.hasOwnProperty.call(condition, 'equals')) {
|
|
311
|
+
const variableName = condition.var;
|
|
312
|
+
const value = condition.equals;
|
|
313
|
+
if (value !== undefined && value !== null) {
|
|
314
|
+
if (!sink[variableName])
|
|
315
|
+
sink[variableName] = new Set();
|
|
316
|
+
sink[variableName].add(String(value));
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
if (Array.isArray(condition.and)) {
|
|
320
|
+
for (const sub of condition.and)
|
|
321
|
+
this.collectEqualsValues(sub, sink);
|
|
322
|
+
}
|
|
323
|
+
if (Array.isArray(condition.or)) {
|
|
324
|
+
for (const sub of condition.or)
|
|
325
|
+
this.collectEqualsValues(sub, sink);
|
|
326
|
+
}
|
|
327
|
+
if (condition.not)
|
|
328
|
+
this.collectEqualsValues(condition.not, sink);
|
|
329
|
+
}
|
|
235
330
|
findLoopStepById(workflow, stepId) {
|
|
236
331
|
const step = workflow.steps.find(s => s.id === stepId);
|
|
237
332
|
return step && (0, workflow_types_1.isLoopStep)(step) ? step : null;
|
package/package.json
CHANGED
|
@@ -431,7 +431,7 @@
|
|
|
431
431
|
{
|
|
432
432
|
"id": "phase-6-prep",
|
|
433
433
|
"title": "PREP: Prepare for Step {{currentStepNumber + 1}}",
|
|
434
|
-
"prompt": "**PREPARATION PHASE for Step {{currentStepNumber + 1}}/{{totalImplementationSteps}}**\n\nBefore implementing this step, you must first PREPARE:\n\n1. **Read implementation_plan.md** and locate step #{{currentStepNumber + 1}}\n2. **Extract step details**: Note the title, description, and expected outputs\n3. **Confirm prerequisites**: Verify the previous step (if any) was completed correctly\n4. **Validate current state**: Ensure the plan for this step is still valid in the current codebase\n5. **List requirements**: Identify all required inputs, files, or dependencies\n\n**BRANCH SETUP (first iteration only):** If this is the first implementation step ({{currentStepNumber}} === 0):\n- Check git availability with 'git status'\n- If available, create feature branch: 'git checkout -b wip-[unique-task-id]'\n- Track the featureBranch variable for later use\n- If git unavailable: Skip branching, log in CONTEXT.md\n\n**
|
|
434
|
+
"prompt": "**PREPARATION PHASE for Step {{currentStepNumber + 1}}/{{totalImplementationSteps}}**\n\nBefore implementing this step, you must first PREPARE:\n\n1. **Read implementation_plan.md** and locate step #{{currentStepNumber + 1}}\n2. **Extract step details**: Note the title, description, and expected outputs\n3. **Confirm prerequisites**: Verify the previous step (if any) was completed correctly\n4. **Validate current state**: Ensure the plan for this step is still valid in the current codebase\n5. **List requirements**: Identify all required inputs, files, or dependencies\n\n**BRANCH SETUP (first iteration only):** If this is the first implementation step ({{currentStepNumber}} === 0):\n- Check git availability with 'git status'\n- If available, create feature branch: 'git checkout -b wip-[unique-task-id]'\n- Track the featureBranch variable for later use\n- If git unavailable: Skip branching, log in CONTEXT.md\n\n**Do not proceed if anything is unclear or missing.**",
|
|
435
435
|
"agentRole": "You are preparing to implement a specific step from the plan. Be meticulous in verifying all prerequisites are met before proceeding.",
|
|
436
436
|
"guidance": [
|
|
437
437
|
"This is step {{currentStepNumber + 1}} of {{totalImplementationSteps}} total implementation steps",
|
|
@@ -444,7 +444,7 @@
|
|
|
444
444
|
{
|
|
445
445
|
"id": "phase-6-implement",
|
|
446
446
|
"title": "IMPLEMENT: Execute Step {{currentStepNumber + 1}}",
|
|
447
|
-
"prompt": "**IMPLEMENTATION PHASE for Step {{currentStepNumber + 1}}/{{totalImplementationSteps}}**\n\nNow implement the step you just prepared for:\n\n**Instructions:**\n1. Re-read step #{{currentStepNumber + 1}} from implementation_plan.md\n2. Focus only on this single step\n3. useTools() to make code changes\n4. Follow quality standards\n5. Adapt to unexpected discoveries\n6. createFile() for ALL code changes\n\n**Remember:** applyUserRules() and matchPatterns() throughout.\n\n**Progress Tracking:**\n- This is step {{currentStepNumber + 1}} of {{totalImplementationSteps}}\n- If we've done > 20 steps total, pause for user intervention\n\n**CONTEXT UPDATES:** If this is every 3rd step ({{currentStepNumber + 1}} % 3 === 0):\n- Update CONTEXT.md\n- addResumptionJson(phase-6-implement)\n- updateDecisionLog()\n- List files modified with line ranges\n\n
|
|
447
|
+
"prompt": "**IMPLEMENTATION PHASE for Step {{currentStepNumber + 1}}/{{totalImplementationSteps}}**\n\nNow implement the step you just prepared for:\n\n**Instructions:**\n1. Re-read step #{{currentStepNumber + 1}} from implementation_plan.md\n2. Focus only on this single step\n3. useTools() to make code changes\n4. Follow quality standards\n5. Adapt to unexpected discoveries\n6. createFile() for ALL code changes\n\n**Remember:** applyUserRules() and matchPatterns() throughout.\n\n**Progress Tracking:**\n- This is step {{currentStepNumber + 1}} of {{totalImplementationSteps}}\n- If we've done > 20 steps total, pause for user intervention\n\n**CONTEXT UPDATES:** If this is every 3rd step ({{currentStepNumber + 1}} % 3 === 0):\n- Update CONTEXT.md\n- addResumptionJson(phase-6-implement)\n- updateDecisionLog()\n- List files modified with line ranges\n\n",
|
|
448
448
|
"agentRole": "You are implementing a specific step from the approved plan. Focus on precise execution while maintaining code quality.",
|
|
449
449
|
"guidance": [
|
|
450
450
|
"Implement only what this step requires",
|
|
@@ -456,7 +456,7 @@
|
|
|
456
456
|
{
|
|
457
457
|
"id": "phase-6-verify",
|
|
458
458
|
"title": "VERIFY: Validate Step {{currentStepNumber + 1}}",
|
|
459
|
-
"prompt": "**VERIFICATION PHASE for Step {{currentStepNumber + 1}}/{{totalImplementationSteps}}**\n\nVerify the implementation is complete and correct:\n\n**Required:** verifyImplementation()\n\n**COMMIT Decision (if all passes):**\n- checkAutomation(commit)\n- gitCommit(type, scope: description)\n- If git unavailable: Log in CONTEXT.md\n\n**FAILURE PROTOCOL:** If verification fails after 2 attempts:\n1. Do not try a third time\n2. Fall back to alternative tools\n3. updateDecisionLog() with failure details\n4. Present summary and recommendations\n5. Set 'verificationFailed' context variable to true\n\n
|
|
459
|
+
"prompt": "**VERIFICATION PHASE for Step {{currentStepNumber + 1}}/{{totalImplementationSteps}}**\n\nVerify the implementation is complete and correct:\n\n**Required:** verifyImplementation()\n\n**COMMIT Decision (if all passes):**\n- checkAutomation(commit)\n- gitCommit(type, scope: description)\n- If git unavailable: Log in CONTEXT.md\n\n**FAILURE PROTOCOL:** If verification fails after 2 attempts:\n1. Do not try a third time\n2. Fall back to alternative tools\n3. updateDecisionLog() with failure details\n4. Present summary and recommendations\n5. Set 'verificationFailed' context variable to true\n\n",
|
|
460
460
|
"agentRole": "You are verifying the implementation meets all quality standards. Be thorough but respect failure bounds.",
|
|
461
461
|
"guidance": [
|
|
462
462
|
"All three verification steps must pass",
|