Commit Graph

2 Commits

Author SHA1 Message Date
drew b76c5f05e7 feat(controller): wire reconciliation into master main loop
Composes reconciliation as the 4th tick layer at its own cadence.

tools/controller/master/loop.py:

- MasterConfig gains reconciliation_interval_s (default 300s per
  plan v9).
- MasterTickReport gains reconciliation: ReconciliationReport | None.
- master_main_loop gains reconciliation_args parameter — tuple of
  (owner, repo, get_pr_state_cb, get_issue_state_cb). When provided,
  runs run_reconciliation_tick every reconciliation_interval_s.
  When None, reconciliation is disabled (useful for tests + one-shot
  modes).
- Reconciliation exception is caught + logged; master keeps running.
- Iteration log line now includes reconciled=N.

tools/controller/master/__main__.py:

- Passes reconciliation_args from ForgejoCallbacks (built earlier
  in the entry point) so the production master automatically runs
  reconciliation against the configured (owner, repo).

3 new tests in test_master_loop.py:
- reconciliation_fires_when_configured: workflow with externally-
  merged state → reconciliation transitions to MERGED.
- reconciliation_skipped_when_args_none: workflows untouched +
  no reconciliation reports.
- reconciliation_exception_doesnt_break_loop: per-row fetch failures
  don't crash the master.

Total: 433 controller tests; full auto_agents suite 2795 pass.
2026-05-18 14:23:42 -04:00
drew 130bbbf3c5 feat(controller): Phase 1d-3a — master main loop (composite tick)
Long-running master orchestrator composing the deterministic
per-iteration work shipped in Phase 1d-1/1d-2. One iteration =
state-machine tick + reaper + pickup guard, in that order
(reasoning in module docstring).

tools/controller/master/loop.py:

- MasterConfig: tick_interval_s (default 30s), reaper_interval_s
  (default 60s), pickup_guard_max_pickups (default 3 per v6).
- run_master_iteration(engine): single synchronous iteration —
  composable for tests + master_main_loop.
- master_main_loop(engine): runs run_master_iteration on a loop until
  stop_event fires. Reaper runs less often than tick (every
  reaper_interval_s, not every tick_interval_s). on_iteration
  callback gets each MasterTickReport (used by tests + future
  structured logging).

7 new tests:
- run_master_iteration: empty DB no-op; tick advances state
  (blocked → STUCK); reaper + pickup guard compose (stale
  in_progress at pickup limit → reaped → STUCK in one iteration).
- master_main_loop: runs until stop; empty loop exits cleanly;
  on_iteration exception doesn't break loop; reaper runs less
  frequently than tick.

Phase 1d-3+ remains for: discovery (Forgejo poll), per-workflow
scheduling (enqueue next workflow_attempts after transition),
Forgejo writes, MERGING state's merge call, reconciliation,
backfill, operator CLI.

Total: 278 controller tests; full auto_agents suite 2640 pass.
2026-05-18 13:41:27 -04:00