"""Master controller — singleton orchestrator. Per plan v9: the master process is a singleton per (owner, repo). It: 1. Runs discovery (Forgejo poll) — Phase 1d-3 2. Drives the state machine: for each non-terminal workflow, advance one step based on the outcome of its latest completed attempt 3. Runs the reaper + pickup guard each tick 4. Performs Forgejo writes (status comments, labels, merges) — Phase 1d-3+ 5. Runs periodic reconciliation (DB↔Forgejo) — Phase 1d-3+ This package ships incrementally. Phase 1d-1 (already shipped) had the state machine + reaper + pickup guard. This Phase 1d-2 adds: - ``outcomes.py``: maps worker output_payload outcomes → state machine events (e.g., implementer outcome='resolved' → 'implementer_pushed'; outcome='rebase-failed' → 'implementer_rebase_failed'). - ``tick.py``: one tick handler — scans recently-completed attempts, applies events to their workflows, emits controller_events. """ from .outcomes import ( EventMapResult, map_outcome_to_event, ) from .tick import ( TickReport, run_tick, ) from .scheduler import ( MAX_TIER, PrefetchCallback, ScheduledAttempt, SchedulerReport, schedule_next_attempts, ) from .discovery import ( DiscoveredEntity, DiscoveryReport, ListIssuesCallback, ListPRsCallback, run_discovery, ) from .forgejo_writes import ( AddLabelCallback, GetLabelsCallback, LabelAdjustResult, ListCommentsCallback, PostCommentCallback, RemoveLabelCallback, StatusCommentResult, adjust_labels, build_marker, comment_has_fingerprint, compute_fingerprint, post_status_comment, ) from .merging import ( MAX_BACKOFF_S, MAX_MERGE_RETRIES, MergeCallback, MergeResponse, MergingHandlerReport, run_merging_tick, ) from .forgejo_http import ( ForgejoCallbacks, build_callbacks, ) from .backfill import ( BACKFILL_MARKER_EVENT_TYPE, BackfillReport, has_backfill_run, run_startup_backfill, ) from .ci_poll import ( CIPollExhaustionReport, DEFAULT_AWAITING_CI_TIMEOUT_S, run_ci_poll_exhaustion_tick, ) from .ci_status_poll import ( CIStatusPollReport, GetCIStatusCallback, run_ci_status_poll_tick, ) from .promote import ( PromoteDiscoveredReport, run_promote_discovered_tick, ) # Phase 1 (Path A) grooming dispatch was reverted 2026-05-25; the # implementation didn't match the controller's worker-queue pattern # and needs a re-design before re-implementation. grooming_config is # kept (env-var loading is dispatch-shape-agnostic) and re-exported # here so __main__.py's startup log line still works. from .grooming_config import ( GroomingConfig, get_grooming_config, log_effective_config, ) from .ci_summarize import ( LogFetcher, summarize_ci_status, ) from .label_gate import ( DEFAULT_OPT_IN_LABEL, count_filtered, filter_by_opt_in_label, has_opt_in_label, opt_in_label_name, ) from .prefetch import ( GetPRDetailsCallback, GetPRDiffCallback, ListPRCommentsCallback, ListPRReviewsCallback, PrefetchDataCallbacks, build_conflict_resolver_input, build_estimator_input, build_implementer_input, build_reviewer_input, make_prefetch_callback, ) from .reconciliation import ( GetIssueStateCallback, GetPRStateCallback, ReconciliationAction, ReconciliationReport, run_reconciliation_tick, ) from .loop import ( MasterConfig, MasterTickReport, master_main_loop, run_master_iteration, ) __all__ = [ # Discovery "DiscoveredEntity", "DiscoveryReport", "ListIssuesCallback", "ListPRsCallback", "run_discovery", # Outcome mapping "EventMapResult", "map_outcome_to_event", # Scheduler "MAX_TIER", "PrefetchCallback", "ScheduledAttempt", "SchedulerReport", "schedule_next_attempts", # Tick "TickReport", "run_tick", # Main loop "MasterConfig", "MasterTickReport", "master_main_loop", "run_master_iteration", # Forgejo writes "AddLabelCallback", "GetLabelsCallback", "LabelAdjustResult", "ListCommentsCallback", "PostCommentCallback", "RemoveLabelCallback", "StatusCommentResult", "adjust_labels", "build_marker", "comment_has_fingerprint", "compute_fingerprint", "post_status_comment", # MERGING handler "MAX_BACKOFF_S", "MAX_MERGE_RETRIES", "MergeCallback", "MergeResponse", "MergingHandlerReport", "run_merging_tick", # HTTP adapter (Forgejo wiring) "ForgejoCallbacks", "build_callbacks", # Backfill (master startup) "BACKFILL_MARKER_EVENT_TYPE", "BackfillReport", "has_backfill_run", "run_startup_backfill", # Reconciliation (periodic DB ↔ Forgejo sync) "GetIssueStateCallback", "GetPRStateCallback", "ReconciliationAction", "ReconciliationReport", "run_reconciliation_tick", # Prefetch (Phase 1h) "GetPRDetailsCallback", "GetPRDiffCallback", "ListPRCommentsCallback", "ListPRReviewsCallback", "PrefetchDataCallbacks", "build_conflict_resolver_input", "build_estimator_input", "build_implementer_input", "build_reviewer_input", "make_prefetch_callback", # CI summarizer (Phase 1j) "LogFetcher", "summarize_ci_status", # CI poll-exhaustion (Phase 1k++) "CIPollExhaustionReport", "DEFAULT_AWAITING_CI_TIMEOUT_S", "run_ci_poll_exhaustion_tick", # CI status poll (Phase 1k++++) "CIStatusPollReport", "GetCIStatusCallback", "run_ci_status_poll_tick", # Promote DISCOVERED → ANALYZING (Phase 1k+++) "PromoteDiscoveredReport", "run_promote_discovered_tick", # Phase 1 grooming plan: dispatch reverted 2026-05-25 (see __init__.py # import block comment). Config is kept for the startup log line. "GroomingConfig", "get_grooming_config", "log_effective_config", # Opt-in label gate (Phase 1k) "DEFAULT_OPT_IN_LABEL", "count_filtered", "filter_by_opt_in_label", "has_opt_in_label", "opt_in_label_name", ]