Skip to content

fix(ladder): hold the buffer purchase when its layer has a pending reshape - #629

Merged
cristim merged 2 commits into
mainfrom
fix/30-hold-buffer-on-reshape
Oct 26, 2026
Merged

cristim merged 2 commits into
mainfrom
fix/30-hold-buffer-on-reshape

Conversation

@cristim

@cristim cristim commented Oct 26, 2026 •

Copy link
Copy Markdown
Member

Closes #30

Change

  • buildResult (pkg/ladder/allocate.go) calls the new holdReshapedBufferAllocations right after splitGap. When a layer has a reshape and is buffer-only, its allocation becomes an informational ActionHold (rationale names the pending reshape) and the reshape still appears. Other layers and allocations are unchanged.
  • Holds in this package carry free-string rationales and there is no reason enum, so no exported enum value or signature changed.
  • A layer that also has the base role (the merged Azure reservation) is not held: its allocation is base+buffer and dropping it would also drop the base purchase. This becomes reachable when feat(ladder): phase 4 - Azure (BillingBenefits savings plans + reservation exchange) #28 (Azure ladder) lands; the follow-up is to zero only the buffer share in assembleAllocations (mergedGap = baseGap + bufferGap).
  • Two existing max-actions tests used the conflicting buffer+reshape fixture. Their expected truncation holds now exclude ConvertibleRI, which is held earlier by this change.

Tests

  • Buffer layer with a pending reshape: no buffer purchase, a Hold, the reshape, other allocations kept.
  • No reshape: buffer still bought.
  • Reshape on another layer, and the merged Azure layer: allocation kept (helper-level, since valid topologies allow one buffer layer).
  • Mutation probe: removing the conversion fails the new test and both updated max-actions tests; reverted.
  • go test -race -count=1 ./... in pkg (workspace and GOWORK=off) and providers/aws, and golangci-lint on pkg: clean.

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

  • Run on-demand review

This review includes 3 billable files and costs up to $0.75.

  • Ask an admin to make reviews automatic

Open in CodeRabbit

Reviews can continue after your included limit without a manual trigger. An admin must approve usage-based billing.

Or wait 1 minute for your next included review.

Check out review usage here.

View limit details

Limit details: You’ve used all 2 included reviews currently available. Your 59 included PR review attempts over the past 7 days set your current allowance at 2 reviews per hour.

Learn how review limits work.

Review configuration:

Run configuration
Commits

Reviewing files that changed from the base of the PR and between bdec74d and d8f389f.

Files selected for processing: 3
  • CHANGELOG.md
  • pkg/ladder/allocate.go
  • pkg/ladder/allocate_test.go
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@cristim

cristim commented Oct 26, 2026

Copy link
Copy Markdown
Member Author

Review verdicts at 4a8474c: two independent cold reviews (non-author), both APPROVE.

  • Reshapes are emitted only for buffer layers and keyed by LayerType. Validation allows at most one buffer layer, so a reshape cannot miss its buffer or hit the wrong one. In the AWS topology that layer is ConvertibleRI.
  • The hold only removes an allocation, so no layer buys above its own gap and total spend never rises. Under a binding MaxHourlyCommitPerRun the cap scale stays <= 1.
  • The changed max-actions expectations follow from the fix: the old ones truncated the very ConvertibleRI buffer purchase that feat(ladder): reconcile simultaneous buffer purchase + reshape recommendations in one run #30 describes.
  • Mutation probes: removing the call, holding merged layers, matching a reshape on any layer, and not appending the holds each fail tests. go test -race -count=1 passes in pkg (with and without the workspace) and providers/aws. Lint is clean.
  • Known limitation: a merged base+buffer layer is not held. No caller builds one today. This is tracked for the Azure ladder (feat(ladder): phase 4 - Azure (BillingBenefits savings plans + reservation exchange) #28).
  • Follow-ups, not blocking: a test that pins the hold running before the cap guardrail, and a unit label in the hold rationale.

CodeRabbit did not review (review limit reached).

[claude-cc-libs]

cristim and others added 2 commits October 26, 2026 08:59
…shape

A run could emit a buffer-layer purchase and a RESHAPE recommendation for
the same layer. buildResult now converts a buffer-only layer's allocation
into an informational Hold when that layer has a reshape, so the run buys
less instead of adding to an under-utilized layer. Layers that also carry
the base or flex role keep their allocation.

Closes #30

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rewrite the garbled docstring, remove the unreachable flex-role clause
(validation rejects flex+buffer) and make the changelog entry accurate
about cap and max-actions side effects.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cristim
cristim force-pushed the fix/30-hold-buffer-on-reshape branch from 4a8474c to d8f389f Compare October 26, 2026 08:01
@cristim
cristim merged commit 80e9b84 into main Oct 26, 2026
15 checks passed
@cristim
cristim deleted the fix/30-hold-buffer-on-reshape branch October 26, 2026 08:18
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.

feat(ladder): reconcile simultaneous buffer purchase + reshape recommendations in one run

1 participant