Imported from MSOLab/ffc_dw_wET_2026 (
src/ffc_ddw_sum_et/orchestration/AGENTS.md). Install upstream withnpx skills add MSOLab/ffc_dw_wET_2026 --skill orchestration. Copyright stays with the author.
Orchestration
Subroutine step contract (controller.py)
Each step method on FFcDDWSubroutineController must follow these two
invariants. They are load-bearing for the per-instance _obj_log.json
aggregator (_save_obj_log in ffcddw_single_instance_runner.py), which
re-bases each step's algorithm-frame trajectory onto the controller clock
using start_time = self.timer.elapsed_sec - report.elapsed_time.
-
At most one register per step call. A step body either calls
self._register(report, sol, ...)exactly once before returning, or returns a stop-report from_make_stop_reportwithout registering. Composite steps (e.g.calc_mcf_lb_and_derive_full_sch) delegate to a pure algorithm pipeline function and callself._registerexactly once with the synthesized final report. Multiple registers per call would makesolution_manager.historyambiguous about which trajectory belongs to which step.A composite step whose inner sub-steps also register on the same controller (e.g.
incremental_job_contrib_cpwhose innerjob_contrib_cpcalls_register) must still call_registeritself exactly once after all inner work completes. The inner registrations are per-subroutine history entries; the composite's own registration adds the parent endpoint — needed so charts show a top-level marker closing the composite's flow section (matchingcoarsen_solve_reconstruct's convention). Passobj_value=self.solution_manager.best_obj_value,obj_bound=None, and the current incumbent assolution—self.solution_manager.get_incumbent().Do not pass
solution=Nonefor such a tail entry:work_status(controller_core.py) readshistory[-1]and returnsNonewhen that record carries no solution, so a successful run would be written to<instance>_instance_result.yaml/ the summary CSV as status-unknown. Re-registering the incumbent is safe — routixSolutionManager.registerswaps the incumbent only on a strictly better objective, and its consistency check comparessolution.obj_valueagainst the reportedobj_value, which match by construction. -
elapsed_timeis measuredmonotonic()from step entry to_registercall, with no work in between. Pattern:def my_step(self, ...): start_elapsed = time.monotonic() ... # all the actual work elapsed = time.monotonic() - start_elapsed # measure here report = SubroutineReport(elapsed_time=elapsed, ...) self._register(report, sol, ...) # immediately return reportWedging non-trivial work between
elapsed = ...and_registerskews the derivedstart_timeand shifts the step's obj_log timestamps. If a step needs post-work that should not count toward the trajectory, do it after_register(the controller has already captured the trajectory at that point).