Files
cleveragents-core/tools/controller/master
drew 337af855f3 feat(controller): Phase 1d-3b — per-workflow scheduler + static escalation
When the state machine transitions a workflow into a state that
needs a worker (ANALYZING / IMPLEMENTING / REVIEWING /
CONFLICT_RESOLVING), the scheduler enqueues a fresh pending
workflow_attempts row with the input_payload prefetched.

tools/controller/master/scheduler.py:

- schedule_next_attempts(engine, prefetch=...) — finds workflows
  in worker-needing states without a matching pending/in_progress
  attempt; enqueues one fresh attempt per. Skips:
  - workflows already with pending/in_progress attempt for the role
  - ESCALATING at MAX_TIER → resolved to ABANDONED (no enqueue)
  - prefetch raised → per-workflow isolated failure

- Static escalation policy resolved inline: ESCALATING + current_tier
  → IMPLEMENTING(min(tier+1, MAX_TIER)) OR ABANDONED. Both produce
  controller_events transition rows with the appropriate v9 event
  name (escalate_next_tier_available / escalate_max_tier_exhausted).

- State→role table: ANALYZING → estimator, IMPLEMENTING → implementer,
  REVIEWING → reviewer, CONFLICT_RESOLVING → conflict_resolver.

- PrefetchCallback is parameterized; production wires it to the
  Forgejo prefetch (Phase 1d-3c), tests inject a fake.

- attempt_number monotonically increments via COALESCE(MAX, 0) + 1.

- DEFERRED to Phase 1d-3c: actual Forgejo prefetch implementation
  (this commit ships the scheduler skeleton + the prefetch callback
  contract).

20 new tests:
- state→role parametrization (4 states × matching role)
- no-double-enqueue (3 cases: pending blocks, in_progress blocks,
  different-role doesn't block)
- escalation (4 cases: tier 0→1, 1→2, MAX→ABANDONED, event row content)
- prefetch raises → per-workflow skip
- non-schedulable states parametrized (7 cases: DISCOVERED,
  AWAITING_CI, MERGING, MERGED, ABANDONED, STUCK, CREATED_PR)
- attempt_number monotonicity (uses MAX+1)

Total: 298 controller tests; full auto_agents suite 2660 pass.
2026-05-18 13:44:38 -04:00
..