Skip to content

feat: expose summary-maintenance lifecycle candidates for explicit binding - #476

Open
zzylol wants to merge 2 commits into
split/462-f-physical-plannerfrom
feat/lifecycle-candidates
Open

zzylol wants to merge 2 commits into
split/462-f-physical-plannerfrom
feat/lifecycle-candidates

Conversation

@zzylol

@zzylol zzylol commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on #475 (the #462 split: #472 merged, then #473 → #474 → #475).

Why

Planner is meant to expose legal summary-maintenance lifecycle candidates and
let the deployment price them over the whole workload (see
physical-planning-and-deployment.md). Today
plan_summary_maintenance_lifecycles enumerates the alternatives but also picks
one with Planner's own cost model, so ASAPQuery-backend cannot price or bind an
alternative Planner did not prefer. The lifecycle choice is what splits summary
state between precompute (ContinuouslyMaintained/Prepared/Shared) and
query time (Ephemeral).

What

Split lifecycle planning into enumerate then select:

  • enumerate_summary_maintenance_lifecycles(...) -> SummaryMaintenanceLifecycleCandidates:
    one entry per unique SummaryAgg, with all four lifecycles, their cost or
    rejection, and nothing selected.
  • SummaryMaintenanceLifecycleCandidates::guarantee(&lifecycle): the guarantee
    (mode, schedule) a choice would carry, so a caller can price before choosing.
  • SummaryMaintenanceLifecycleCandidates::select(&[(state, lifecycle)]): turns
    an explicit choice into the SummaryMaintenanceLifecyclePlan the physical
    compiler consumes. It refuses unknown or duplicate states, missing states,
    unlisted or rejected alternatives, incompatible nested schedules, and
    combinations the cost model cannot estimate (SummaryMaintenanceLifecycleChoiceError).

plan_summary_maintenance_lifecycles and the global-selection helpers now run
enumerate + cheapest-select through the same checks. No new cost logic; unknown
cost stays unknown.

Before this PR

let plan = plan_summary_maintenance_lifecycles(root, demand, now, horizon, caps, model)?;
// deployments[i] already carries Planner's chosen lifecycle.

After this PR

let candidates = enumerate_summary_maintenance_lifecycles(root, demand, now, horizon, caps, model)?;
// price candidates.deployments() in the deployment, then bind its choice:
let plan = candidates.select(&[(state_id, SummaryMaintenanceLifecycle::Ephemeral)])?;

Choosing what Planner would choose yields an identical plan.

Open point for review

An alternative whose only issue is missing cost evidence can be bound only when
the cost model declares its whole-combination hook authoritative for lifecycle
costs (Planner's existing rule). Accepting any legal-but-unpriced alternative is
a one-line change, but the plan's cost and window framework would then be
unknown. Left as is pending review.

The window framework is decided per whole combination by the cost model, so it
appears only in the plan returned by select, not per alternative.

Validation

6 new tests in summary_maintenance_lifecycle.rs (enumeration without
selection, reproducing Planner's choice, binding a costlier legal alternative,
illegal/incomplete choices, incompatible nested schedules, one entry per unique
state). cargo fmt --check and cargo clippy --workspace --all-targets -- -D warnings
pass; cargo test --workspace --no-fail-fast passes except the pre-existing #462
failure devtools dag_export::workload_node_ids_make_smaller_topk_reuse_explicit.

🤖 Generated with Claude Code

zzylol and others added 2 commits September 30, 2026 02:08
…nding

Split plan_summary_maintenance_lifecycles into enumeration and selection so
a deployment can price every lifecycle alternative per unique summary state
and bind its own choice. Planner selection is unchanged: it now enumerates
and then selects the cheapest complete combination through the same path.

SummaryMaintenanceLifecycleCandidates::select validates that each choice is
an alternative Planner could select, enforces schedule compatibility, and
obtains window frameworks and totals from the same complete-candidate hook.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@zzylol
zzylol force-pushed the feat/lifecycle-candidates branch from 59b41bd to 4bb8c86 Compare September 30, 2026 02:14
@zzylol
zzylol changed the base branch from feat/shared-physical-operators to split/462-f-physical-planner September 30, 2026 02:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant