feat(FEAT-001): add loop state columns and validator run tables for mission execution loop

This commit adds the schema migration and types for the mission execution loop validation system:
- Adds loop state tracking columns to mission_features table (loopState, implementationAttemptCount, validatorAttemptCount, lastValidatorRunId, lastValidatorStatus, generatedFromFeatureId, generatedFromRunId)
- Creates mission_validator_runs table for tracking validation runs
- Creates mission_validator_failures table for assertion failure records
- Creates mission_fix_feature_lineage table for tracking fix feature relationships
- Adds workflowStepRetries column to tasks table for retry tracking
- Adds FEATURE_LOOP_STATES and VALIDATOR_RUN_STATUSES enums
- Updates TaskStore to support workflowStepRetries field
- Updates TaskExecutor to handle workflow step failures with retry logic

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
This commit is contained in:
gsxdsm
2026-04-11 17:06:41 -07:00
parent 49ab322ebf
commit d8a07f7543
12 changed files with 658 additions and 23 deletions

View File

@@ -164,6 +164,7 @@ function createMockStore() {
getWorkflowStep: vi.fn().mockResolvedValue(undefined),
listWorkflowSteps: vi.fn().mockResolvedValue([]),
appendAgentLog: vi.fn().mockResolvedValue(undefined),
getFusionDir: vi.fn().mockReturnValue("/tmp/test/.fusion"),
};
return store as any;
}
@@ -6581,6 +6582,7 @@ describe("Workflow Steps Execution", () => {
currentStep: 0,
log: [],
enabledWorkflowSteps: ["WS-001"],
workflowStepRetries: 3, // Exhaust retries so task fails immediately
prompt: "# test\n## Steps\n### Step 0: Preflight\n- [ ] check",
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
@@ -6625,6 +6627,7 @@ describe("Workflow Steps Execution", () => {
currentStep: 0,
log: [],
enabledWorkflowSteps: ["WS-001"],
workflowStepRetries: 3, // Exhaust retries so task fails immediately
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
});
@@ -6671,6 +6674,7 @@ describe("Workflow Steps Execution", () => {
currentStep: 0,
log: [],
enabledWorkflowSteps: ["WS-001"],
workflowStepRetries: 3, // Exhaust retries so task fails immediately
prompt: "# test\n## Steps\n### Step 0: Preflight\n- [ ] check",
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
@@ -6703,6 +6707,7 @@ describe("Workflow Steps Execution", () => {
currentStep: 0,
log: [],
enabledWorkflowSteps: ["WS-001"],
workflowStepRetries: 3, // Exhaust retries so task fails immediately
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
});
@@ -9560,6 +9565,7 @@ describe("StepSessionExecutor integration", () => {
updatedAt: new Date().toISOString(),
});
// Steps succeed, but workflow step will fail
mockExecuteAll.mockResolvedValue([
{ stepIndex: 0, success: true, retries: 0 },
]);
@@ -9567,7 +9573,8 @@ describe("StepSessionExecutor integration", () => {
const onError = vi.fn();
const executor = new TaskExecutor(store, "/tmp/test", { onError });
await executor.execute(createTaskWithSteps({ steps: [{ name: "Step 0", status: "pending" }] }));
// Exhaust retries so workflow step failure is immediate
await executor.execute(createTaskWithSteps({ steps: [{ name: "Step 0", status: "pending" }], workflowStepRetries: 3, enabledWorkflowSteps: ["WS-001"] }));
// Should have called getWorkflowStep to look up the workflow step
expect(store.getWorkflowStep).toHaveBeenCalledWith("WS-001");