feat(coder): orchestrator advanced flow patterns
- TriggerRule type (all_success/one_success/all_done) for parallel deps - Variable substitution ($stepId.output.field) in agent step prompts - Approval gate step kind (pauses flow via permission frames) - flow_step_events table for append-only event-sourced step log - evaluateTriggerRule pure function in flow-runner-decisions
This commit is contained in:
@@ -22,7 +22,7 @@
|
||||
* "Settled" = done ∪ skipped ∪ excluded. Only settled deps unblock a step;
|
||||
* an inFlight dep does NOT (the runner waits for its terminal callback).
|
||||
*/
|
||||
import type { Flow, Step, StepContext } from '../conductor/types.js';
|
||||
import type { Flow, Step, StepContext, TriggerRule } from '../conductor/types.js';
|
||||
|
||||
export interface SchedulerState {
|
||||
/** step ids that completed successfully (results available) */
|
||||
@@ -62,7 +62,7 @@ export function readySteps(flow: Flow, state: SchedulerState): Step[] {
|
||||
!state.skipped.has(s.id) &&
|
||||
!state.inFlight.has(s.id) &&
|
||||
!state.excluded.has(s.id) &&
|
||||
(s.deps ?? []).every((d) => isSatisfied(state, d)),
|
||||
((s.deps ?? []).length === 0 || evaluateTriggerRule(s.deps ?? [], state.done, state.skipped, state.excluded, s.trigger_rule)),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -167,6 +167,32 @@ export function shouldFailOnMissingAgent(agent: string, modeId: string | null):
|
||||
return agent === 'qwen' && modeId === 'plan';
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate a trigger rule against dependency results.
|
||||
* - all_success: every dep must be done (not skipped/failed)
|
||||
* - one_success: at least one dep must be done
|
||||
* - all_done: every dep must be settled regardless of outcome
|
||||
*/
|
||||
export function evaluateTriggerRule(
|
||||
deps: string[],
|
||||
done: ReadonlySet<string>,
|
||||
skipped: ReadonlySet<string>,
|
||||
excluded: ReadonlySet<string>,
|
||||
rule?: TriggerRule,
|
||||
): boolean {
|
||||
if (deps.length === 0) return true;
|
||||
const satisfied = new Set([...done, ...skipped, ...excluded]);
|
||||
|
||||
switch (rule ?? 'all_success') {
|
||||
case 'all_success':
|
||||
return deps.every((d) => done.has(d) || skipped.has(d) || excluded.has(d));
|
||||
case 'one_success':
|
||||
return deps.some((d) => done.has(d));
|
||||
case 'all_done':
|
||||
return deps.every((d) => satisfied.has(d));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reconcile every step of an in-flight run for startup resume. Returns one
|
||||
* decision per step. Pure — no IO.
|
||||
|
||||
Reference in New Issue
Block a user