Skip to content

feat(plans): plan steps resolve real recommendations and show real counts and prices (tier B of #609) #631

Open

Description

@cristim

Tier B of #609. The tier A stopgap (#618, #616, merged) made empty plan steps fail loudly and show "No recommendations attached". It did not make plans work: until this issue lands, no plan can complete a step, and "Add Purchases" always returns 409.

Goal

A plan created from recommendations (provider, service, term, payment, target accounts, target coverage, ramp) schedules steps that purchase real recommendations, and the planned-purchases list shows real counts, resource types, upfront cost and savings instead of placeholders.

Proposed shape

  • Resolve the matching stored recommendations for the plan's provider, service, term, payment and target accounts at execution time, not at plan creation, so a step buys what is current when it runs.
  • Size each step from the ramp: PercentPerStep of the resolved set, per the target-coverage meaning chosen under D1.
  • Savings Plans steps are sized by HourlyCommitment, not instance count.
  • Store the resolved recommendations on the execution, so approval, history and retry see the same rows.
  • Planned-purchases preview: compute count, resource types, upfront and savings for pending steps from the current matching recommendations, labelled as an estimate until the step runs.
  • Reuse createPurchaseExecutionsTx (ramp lock #1861, creator stamp sec(auth): API key permission constraints are silently dropped on create #950), which tier A kept without a production caller. Re-enable "Add Purchases" through it.
  • Decide the dropped recommendations field of PlanRequest: honour it (per D2) or stop sending it from savePlan (frontend/src/plans.ts).
  • Keep the tier A guards as the fallback: a step that resolves to nothing fails once and does not advance the ramp.

Open product decisions (block the design)

  • D1. Does "target coverage 80%" mean "buy 80% of the matching recommendations" or "reach 80% account coverage"? The second needs a coverage source, which is unknown for Azure.
  • D2. Is the snapshot sent by "Plan from N selected" binding, or does the plan filter win?

Known gaps to cover

Acceptance

  • A plan like the one reported (Azure compute, 1 year, 80% target coverage, weekly 25% ramp, one target account, Auto-Purchase on) produces steps with non-zero counts and real upfront and savings figures, and a scheduled step executes against real recommendations.
  • A step with nothing to buy fails once, with one failed row, and the ramp does not advance.
  • Regression tests use the real data shape of that plan and fail on current main.

Activity

  1. 31 remaining items

  2. cristim commented on Oct 15, 2026

    @cristim
    MemberAuthor

    PR #880 normally squash merged as 64ec8b3fe12de04964837a3c68b1957a2c7dccf4, with parent 149544fe and the exact independently reviewed tree b3514bf0. All required checks were green at the reviewed PR head before merge.

    All five post-merge workflows passed: full CI, automatic deployment, frontend E2E, frontend build sentinel and pre-commit. Every CI watcher and the completed PR merge watcher has been reaped.

    Read-only deployed identity verification returned HTTP200 from /version, reporting git_sha: 64ec8b3 and build 20261015055918. The running Lambda and corresponding image digest matched the same build/source. This verifies deployed identity; no authenticated live plan or purchase was changed.

    The actual Create/Edit form preview was independently verified locally from the production bundle at desktop and phone widths, including dense schedules, keyboard interaction, focus trapping and restoration, and zero API writes. The browser APIs/authentication were fixtures. This leaf adds the disclosed no-write preview; existing Save and Add Purchases actions remain. Atomic graph scheduling and saved history integration remain tracked in #631 and are not claimed complete by this PR.

  3. cristim commented on Oct 15, 2026

    @cristim
    MemberAuthor

    Reopening per owner decision (2026-10-16) to track the remaining laddering plan-editor work end to end: M2 managed-ramp chain, ramp-ledger retention, legacy-writer guards, M3 atomic save command, preview/Save API routes, frontend Save (E4), and the end-to-end proof. PRs will say "Refs #631" and mirror this issue's labels; the final route-exposure PR closes it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions