Skip to content

Store host profile: shared_buffers no longer reads stale on a 4 GB host (#5716) - #5720

Merged
erikdarlingdata merged 2 commits into
devfrom
fix/5716-shared-buffers-verdict
Oct 12, 2026
Merged

erikdarlingdata merged 2 commits into
devfrom
fix/5716-shared-buffers-verdict

Conversation

@erikdarlingdata

@erikdarlingdata erikdarlingdata commented Oct 12, 2026 •

Copy link
Copy Markdown
Owner

Claude posting for Erik Darling.

Closes #5716.

Why

The v5 block writes shared_buffers once, from the raw RAM reading (min of 25% of RAM and 1 GB), and the v8 block never re-states it. The host profile derives its target from the quantized reading, so a 4 GB host that the OS reports as about 4092 MB has 1023 MB in force against a 1024 MB target and reads stale_after_hardware_change on every start.

What changes

DarlingStoreHostProfile.ApplySharedBuffersRawReadingTolerance (same shape as ApplyWalDriftTolerance, but a band, as the review asked): for shared_buffers only, the value in force reads Matches when some raw reading that quantizes to the same GB as the current reading derives it. That is the definition of "no hardware change" the v8 fingerprint already uses (same quantized RAM). In practice: the value lies between DeriveMemorySettings of the bucket's lowest and highest raw readings, inclusive. When it is forgiven, the derived figure reported is the value in force. Otherwise the quantized target stands.

  • The bucket rule lives in one place: a new helper DarlingManagedPostgres.QuantizedRamBucket, next to QuantizeRam, returns the lowest and highest raw reading (half a GB either side of the quantized value, inclusive). The tolerance computes both ends through DeriveMemorySettings; no formula is re-implemented.
  • Why a band: a guest's raw reading drifts with no resize (see QuantizeRam's notes). A host whose v5 block wrote 1023 MB from 4092 MB and now reads 4088 MB (derivation 1022) is the same host and now reads Matches. For a 4 GB reading the band is 896 to 1024 MB.

It is applied in both places that build verdicts, right before ClassifyVerdict:

  • GatherSettingProfilesAsync: builds the startup profile (GatherStartupProfileAsync calls it, and DarlingWorker logs one warning per stale row from that result), and serves the first table of --check-settings and get_store_host.
  • ComputeAndStoreManagedConfVerdictsAsync: writes the stored collect.managed_conf_verdicts rows. The viewer and MCP roles read those rows and cannot recompute them, and the second table of --check-settings reads them.

No self-alert consumes a stale verdict: the alert read keeps only RejectedValue rows, and ApplyStoreSettingsAsync documents that StaleAfterHardwareChange does not fire it. So this change affects reporting only, never an alert.

The startup log line, the MCP tool and the CLI table print the profile's own derived figure, so they show the one the verdict matched (never "1023 in force, 1024 derived, Matches").

Verdicts now, on a 4 GB host (quantized target 1024 MB):

  1. 1023 MB in force from a raw reading of 4092 MB: Matches (derived shown as 1023).
  2. 1023 MB in force, raw reading drifted to 4088 MB: Matches (derived shown as 1023).
  3. 1024 MB in force: Matches.
  4. 768 MB in force (written by a 3 GB host): StaleAfterHardwareChange, derived 1024.
  5. 512 MB in force (written by a 2 GB host): StaleAfterHardwareChange, derived 1024.

Every other setting is untouched: the method returns the derived value unchanged for any name other than shared_buffers, and for an unreadable current value.

Test plan

  • Unit tests in DarlingStoreHostProfileTests: the original three cases and the "other settings and unreadable value untouched" check, plus the review round's drift case (4088 MB, 1023 in force), the 3 GB to 4 GB case (768 stale), and the bucket edges (the 3.5 GB and 4.5 GB minus one byte readings match their own derivation; one byte past either end is a neighbouring bucket and the figure is stale). The source pin that both verdict producers call the tolerance before ClassifyVerdict is kept.
  • Revert check: with the band reverted to exact equality against today's raw derivation, SharedBuffersVerdict_RawReadingDriftedWithNoResize_1023InForceStillMatches fails (1023 against 1022); the other 80 pass either way. Restored afterwards. (Round 1's check, a no-op body, failed the 4092 MB case.)
  • DarlingStoreHostProfileTests: 81 passed.
  • Every class matching *Census* and *Ratchet*: 560 total, 0 failed, 1 skipped.
  • -trait Stage=Guard: 1584 total, 0 failed.
  • Build: 0 errors; 1 warning (xUnit2013 in DarlingOperatorGroupScriptTests.cs, a file this PR does not touch).
  • Live PostgreSQL classes not run (no cluster started); CI decides.
  • Full suite and Installer.Tests not run on this laptop.

Review round 1

  • Blocking, prose: the body and changelog said ComputeAndStoreManagedConfVerdictsAsync feeds the startup profile and that the self-alert flagged this. Fixed in this body, the changelog entry below, and the test doc comment on the source pin (commit 1fd53d0). Each producer-to-surface claim above was checked against the code: GatherStartupProfileAsync calls GatherSettingProfilesAsync (DarlingStoreHostProfile.cs), and DarlingWorker calls GatherStartupProfileAsync for the startup log and ComputeAndStoreManagedConfVerdictsAsync for the stored rows.
  • Non-blocking, exact match versus band: widened to the same-quantized-RAM band, with QuantizedRamBucket as the one home of the bucket rule (commit 1fd53d0).

Changelog

SECTION: Fixed
ENTRY: - A store host with about 4 GB of RAM no longer reports shared_buffers as stale when its hardware has not changed ([#5720]) - The setting is written once from the raw RAM reading (1023 MB on a host the OS reports as about 4092 MB), but the host profile compared it with a target derived from the rounded reading (1024 MB), so the startup profile log, --check-settings, get_store_host and the stored settings verdicts showed it as stale on every start. A value that any raw reading rounding to the same whole GB would have produced now reads Matches, so a reading that drifts without a resize does not bring the warning back, and the derived figure shown is the value in force. A real resize, such as 512 MB or 768 MB left over from a 2 GB or 3 GB host on a 4 GB host, still reads stale.
REF:
[#5720]: #5720

@erikdarlingdata
erikdarlingdata marked this pull request as ready for review October 12, 2026 22:34
Comment on lines +406 to +407
/// <summary>#5716: both verdict producers (--check-settings / get_store_host, and the startup profile that
/// feeds the self-alert) must route their derived target through the tolerance before ClassifyVerdict.</summary>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parenthetical maps the two producers backwards, and the self-alert half is not true of this verdict at all.

  • GatherSettingProfilesAsync is the one that builds the startup profile: GatherStartupProfileAsync calls it at DarlingStoreHostProfile.cs:1105, and DarlingWorker.LogStoreHostProfileAsync logs one LogWarning per StaleAfterHardwareChange row off that result (DarlingWorker.cs:2569, 2575-2583). It also serves --check-settings' first table and get_store_host via GatherAsync (:1063).
  • ComputeAndStoreManagedConfVerdictsAsync is the one that writes the stored collect.managed_conf_verdicts rows, read back by --check-settings' second table (DarlingCliCommands.cs:963), the MCP self-store reader (Mcp/DarlingStoreMetricsReader.cs:2314) and the alert read.
  • Nothing feeds the self-alert from a stale verdict. DarlingWorker.ReadRejectedManagedConfSettingNamesAsync filters the stored rows to Verdict == HostSettingVerdict.RejectedValue only (DarlingWorker.cs:9463-9466), and ApplyStoreSettingsAsync's own contract says so in its words: "PendingRestart and StaleAfterHardwareChange do NOT fire this" (DarlingSelfAlertEvaluator.cs:5450-5452).

The test itself is right and the pin is the useful one here — both producers do need the tolerance, and both have it. It is the comment (and the same sentence in the PR body and the changelog entry) that names a consumer this verdict never reaches.

return derivedValueMb;
}

return DarlingManagedPostgres.DeriveMemorySettings(ramBytesForDerivation).SharedBuffersMb == current

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking, but worth recording next to the ApplyWalDriftTolerance comparison this is modelled on: the sibling chose a band (IsWalSizeWithinDriftOf), this one is exact equality against the raw reading as read right now.

That is tight enough for the stores that re-render darling-managed.conf every start — WriteManagedConfFile re-derives shared_buffers from GatherManagedConfRenderInputs' fresh GetTotalPhysicalMemoryBytes() (DarlingManagedPostgres.cs:4209, ManagedConfFile.cs:188), so the file and this check read the same number within one start. It is not tight enough for a store still on the marker-gated postgresql.conf path, where the v5 block was written once in the cluster's life (DarlingManagedPostgres.cs:3864): there the stored figure is frozen at whatever ullTotalPhys said then, and QuantizeRam's own remarks are explicit that the reading is not stable — "ullTotalPhys is not guaranteed bit-identical across reboots — a balloon/Dynamic-Memory guest can report a different current total with no operator resize — and these ARE cloud VMs" (:1378-1382).

shared_buffers is ram / 4, so a 4 MB wobble in the reported total moves the derivation by 1 MB. On the issue's own host class that is 4092 → 4088 MB, derivation 1023 → 1022, in force still 1023, and the row goes back to reading stale-after-hardware-change forever — the same complaint one wobble step over. Only reachable below 4 GB (at or above it the 1 GB cap makes both derivations 1024), which is exactly the host #5716 was filed about.

If you want the band, the ingredients are already here: forgive when current equals the derivation for any raw reading that quantizes to the same GB, i.e. compare DeriveMemorySettings over the quantized reading and over the raw reading and accept either, or accept any current within 1 MB of the raw derivation. Fine to leave as-is and let a second report decide.

@claude

claude Bot commented Oct 12, 2026

Copy link
Copy Markdown

The changelog entry names a surface this verdict never reached

The ENTRY: line ships to users:

The setting is written once from the raw RAM reading (1023 MB on a host the OS reports as about 4092 MB), but the host profile compared it with a target derived from the rounded reading (1024 MB), so the startup profile, --check-settings, get_store_host and the self-alert flagged it on every start.

The first three are right. The self-alert is not, and the code says so in its own words rather than by inference:

  • DarlingWorker.ReadRejectedManagedConfSettingNamesAsync is the store-settings self-alert's one read of the stored verdict rows, and it filters to Verdict == HostSettingVerdict.RejectedValue — nothing else (DarlingWorker.cs:9463-9466).
  • DarlingSelfAlertEvaluator.ApplyStoreSettingsAsync's contract: "PendingRestart and StaleAfterHardwareChange do NOT fire this — a value waiting on a restart it will cleanly apply, or one merely different from what today's hardware would now derive, is not evidence anything is WRONG" (DarlingSelfAlertEvaluator.cs:5450-5452). That is a deliberate design decision, pinned in DarlingSelfAlertTests' rejected: ["shared_buffers"] cases, not an oversight this PR is quietly repairing.

So an operator on a ~4 GB store was seeing this on the startup profile line, in --check-settings and in get_store_host, and was not getting a self-alert card or e-mail about it. The entry as written tells them they were.

Same sentence appears twice more, with the producers additionally swapped — in the PR body's "What changes" bullet list, and in the new test's doc comment (commented inline at DarlingStoreHostProfileTests.cs:406). The accurate mapping is:

producer surfaces
GatherSettingProfilesAsync the startup profile log and its per-setting stale LogWarning (DarlingWorker.cs:2569, 2575-2583), --check-settings' first table, get_store_host (DarlingStoreHostProfile.cs:1063, 1105)
ComputeAndStoreManagedConfVerdictsAsync the stored collect.managed_conf_verdicts rows, read back by --check-settings' second table (DarlingCliCommands.cs:963), the MCP self-store reader (Mcp/DarlingStoreMetricsReader.cs:2314), and the self-alert's RejectedValue-only condition

Dropping "and the self-alert" from the entry (and from the body bullet) is the whole fix. The code change itself is correct and complete — both producers genuinely needed the tolerance and both got it, before ClassifyVerdict, with the source pin to hold them there. The only thing I am asking to change is the prose.

claude[bot]
claude Bot previously requested changes Oct 12, 2026

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: CHANGES REQUESTED

The code change is correct and complete. What I am requesting is a prose fix: the changelog entry, a shipped artifact, names a surface this verdict never reached. Detail in the two inline comments and the top-level note.

Claims

  • VERIFIED — v5 writes shared_buffers from the raw reading and v8 never re-states it — DarlingManagedPostgres.cs:3864-3868 → :1020-1027 (unquantized); BuildHardwareSizingConfAppend:1565-1580 emits the other four keys only, its bullet at :1538 saying "EXCLUDED STRUCTURALLY". Same on the darling-managed.conf path: ManagedConfFile.cs:188 raw to v5, :204 quantized only for v8, over GatherManagedConfRenderInputs:4209.
  • VERIFIED — the profile derives its target from the quantized reading — DarlingStoreHostProfile.cs:932, the one source of all eight targets.
  • VERIFIED — a ~4092 MB host has 1023 MB in force against 1024 — DeriveMemorySettings:1119-1148 is min(ram / 4, 1 GB), QuantizeRam:1387-1392 rounds 4092 to 4096 MB; the new test asserts both as preconditions.
  • VERIFIED — same shape as ApplyWalDriftTolerance, no formula re-implemented — :914-925 vs :894-902, comparison routed through DeriveMemorySettings.
  • VERIFIED — applied in both verdict builders right before ClassifyVerdict — :1043/:1045, :1508/:1510; ClassifyVerdict has exactly those two callers (ClassifyValueVerdict:795 is the string twin, no numeric target).
  • VERIFIED — the three verdicts (1023 → Matches derived 1023; 1024 → Matches; 512 on 4 GB → stale derived 1024) — walked through :932 → :922 → :777. Cannot forgive falsely: 1023 MB pins the raw reading to 4092-4095 MB, so a forgiven value is a legitimate value for this host.
  • VERIFIED — other settings and an unreadable current value untouched — :917; the other three memory keys do not need it because v8 re-states them from the quantized reading (:1572-1574).
  • VERIFIED — the startup log, MCP tool and CLI table print the profile's own derived figure — DarlingWorker.cs:2580, Mcp/DarlingMcpStoreHostTools.cs:171, :1186/1270/1303/1315. Nothing uses the derived figure to WRITE a conf value, so this changes reporting only.
  • VERIFIED — the revert check's shape, deducible from the pure functions: a no-op body fails case 1 only; cases 2 and 3 land identically either way; the source pin still finds the call sites, which the claim correctly does not list.
  • UNVERIFIED — 78 passed; 1146 / 0 failed; 1584 Stage=Guard — need a test run, no .NET SDK here. I did read that no existing test asserts the old stale reading, and ManagedConfVerdictsLiveTests:167-173' 256 MB plant is unaffected (the pg_file_settings arm at :1512-1520 overrides outright).
  • UNVERIFIED — build: 0 warnings, 0 errors. CSharpSourceWalker and SerialLoopMemberBody both live in Darling.Tests, already called from siblings, so the references resolve on inspection.
  • UNVERIFIED — "Closes #5716": the issue text is not readable from the tree, so the 4092 MB host class is taken from the diff's own arithmetic rather than the report.
  • REFUTED — ComputeAndStoreManagedConfVerdictsAsync is "the startup profile … and DarlingSelfAlertEvaluator" — the startup profile is the OTHER producer (GatherStartupProfileAsync → GatherSettingProfilesAsync at :1105; warning logged at DarlingWorker.cs:2575-2583), and no self-alert consumes a stale verdict (DarlingWorker.cs:9463-9466 filters to RejectedValue; DarlingSelfAlertEvaluator.cs:5450-5452 says stale does NOT fire). Same two errors in the test doc comment at DarlingStoreHostProfileTests.cs:406-407.
  • REFUTED — the changelog's "and the self-alert flagged it on every start" — same two citations.

Riskiest lines

  1. Darling/PerformanceMonitor.Darling.Service/DarlingStoreHostProfile.cs:922 — the comparison deciding whether a mismatch is forgiven — pinned by SharedBuffersVerdict_RawReadingGave1023_QuantizedGives1024_1023InForceMatches and SharedBuffersVerdict_FourGbHostWith512FromATwoGbHost_IsStale
  2. Darling/PerformanceMonitor.Darling.Service/DarlingStoreHostProfile.cs:1508 — the call site feeding the persisted rows the mcp/viewer roles cannot recompute — pinned by SharedBuffersTolerance_IsAppliedBeforeClassifyVerdictByBothVerdictProducers
  3. Darling/PerformanceMonitor.Darling.Service/DarlingStoreHostProfile.cs:917 — the name/null guard; a slip forgives every setting on every host, in the Matches direction — pinned by SharedBuffersTolerance_LeavesEveryOtherSettingAndAnUnreadableValueAlone

Traps near this diff

  • "Two copies of one definition pinned EQUAL to each other fail only after BOTH have drifted (#3684). Alias, do not copy." — does not apply — :922 calls DeriveMemorySettings and the tests derive expectations the same way (DarlingStoreHostProfileTests.cs:352-353).
  • "Lite and Darling ship in parity (CONTRIBUTING's two-store rule): a fix to one SKU's reader, tool, alert or description without the counterpart's is a finding, not a nit" — does not apply — grep -rln "HostSettingVerdict\|shared_buffers" Lite/ Lite.Tests/ returns nothing; this subsystem is Darling-only, behind [SupportedOSPlatform("windows")].
  • "A pin that encodes the lie … Ask what a pin would fail ON." (#3699) — does not apply — the behavioural tests re-compose the pipeline at :349-360 and would pass without the call sites, which is why the source pin exists; together, dropping the tolerance from either producer fails a test.
  • "An expression-bodied member holding a { } property pattern is read SHORT by the T-SQL convention guard's member walk (#3667; the #3607 precedent)" — does not apply — the new member is block-bodied and so are both members the source scan walks; a short read returns -1 and fails tolerance >= 0 loudly rather than passing vacuously.

Divergence (blind read vs PR body)

Two places, one sentence, and the code is not where they disagree. The body inverts the producers (the startup profile is GatherSettingProfilesAsync, :1105), and both the body and the changelog list the self-alert among the surfaces that flagged this — it never did, by deliberate design (DarlingSelfAlertEvaluator.cs:5450-5452). Nothing in the diff goes unmentioned by the body.

Non-blocking, raised by neither account (inline at :922): the tolerance is exact equality against the raw reading as read right now, where #5459's sibling chose a band. On the marker-gated postgresql.conf path v5 was written once in the cluster's life (DarlingManagedPostgres.cs:3864), and QuantizeRam:1378-1382 says the reading drifts on balloon guests "with no operator resize — and these ARE cloud VMs". A 4 MB drift moves ram / 4 by 1 MB and the row reads stale again, below 4 GB only — #5716's own host class.

Reviewer checklist

  • Run the reported suites and the 0-warning build; none is checkable from a read-only tree without an SDK.
  • On a real ~4 GB managed store: --check-settings should show shared_buffers as matches with the derived column at the value in force, and the startup profile log should stop warning on it.
  • Confirm the persisted collect.managed_conf_verdicts row is rewritten to matches on the next service start — the mcp/viewer roles read that table and cannot recompute it.
  • Decide whether the tolerance should become a band; that needs the fleet's real ullTotalPhys stability on sub-4 GB hosts.

@claude

claude Bot commented Oct 12, 2026

Copy link
Copy Markdown

Follow-up review of commit 1fd53d0 (band widening + producer-comment fix)

This commit does exactly what round 1 asked for and nothing more.

Prose fix. The changelog ENTRY: in the current PR body no longer credits the self-alert: it now lists "the startup profile log, --check-settings, get_store_host and the stored settings verdicts" — the self-alert is gone from the sentence, matching DarlingWorker.cs's RejectedValue-only filter and DarlingSelfAlertEvaluator's documented contract that StaleAfterHardwareChange never fires it. The test doc comment at DarlingStoreHostProfileTests.cs:470-474 was corrected the same way (GatherSettingProfilesAsync → startup profile/--check-settings/get_store_host, ComputeAndStoreManagedConfVerdictsAsync → the stored collect.managed_conf_verdicts rows).

Band widening. DarlingManagedPostgres.QuantizedRamBucket (DarlingManagedPostgres.cs:1401) is the single new home for "half a GB either side of the quantized value, inclusive" — the same rule QuantizeRam already implements for its own rounding, so the two cannot drift (QuantizedRamBucket calls QuantizeRam directly rather than restating the arithmetic). ApplySharedBuffersRawReadingTolerance (DarlingStoreHostProfile.cs:919-932) runs both bucket ends through DeriveMemorySettings — same formula, no second copy — and forgives any stored value between them.

I worked through the arithmetic by hand (no SDK available to run the suite in this environment):

  • 4 GB bucket: lowest = 3.5 GB → 896 MB, highest = 4.5 GB − 1 byte → 1024 MB (capped). Band [896, 1024] matches the PR body's claim and the new SharedBuffersVerdict_BucketEdges_AreInsideTheBandAndOneBytePastIsNot test.
  • The balloon-drift case (wrote 1023 MB from 4092 MB, now reads 4088 MB → raw derivation 1022) lands inside that same band, so it still reads Matches — fixing exactly the non-blocking gap round 1 flagged.
  • A real resize (2 GB→4 GB keeps 512; 3 GB→4 GB keeps 768) still lands below the bucket's lowest end (896) and correctly reads stale. For hosts ≥~4.5 GB raw, both ends of the band are already capped at 1024 MB, so the band collapses to a single value there — no false "Matches" window opens up at the high end either.

No new bugs found. Full verdict below.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: LGTM

Claims

  • VERIFIED — the changelog entry no longer credits the self-alert, listing only the startup profile log, --check-settings, get_store_host and the stored settings verdicts — current gh pr view 5720 body's ENTRY: line; cross-checked against DarlingWorker.cs's RejectedValue-only alert filter and DarlingSelfAlertEvaluator's documented StaleAfterHardwareChange-never-fires contract (established last round, unchanged this round).
  • VERIFIED — "For a 4 GB reading the band is 896 to 1024 MB" — DarlingStoreHostProfileTests.cs's SharedBuffersVerdict_BucketEdges_AreInsideTheBandAndOneBytePastIsNot asserts lowestMb == 896, highestMb == 1024.
  • VERIFIED — the bucket rule lives in one place and both ends go through DeriveMemorySettings, no formula re-implemented — DarlingManagedPostgres.cs:1401 (QuantizedRamBucket calls QuantizeRam directly) and DarlingStoreHostProfile.cs:927-931 (both ends through DeriveMemorySettings, then a plain range check).
  • VERIFIED — a real resize (2 GB or 3 GB host moved to 4 GB) still reads stale — SharedBuffersVerdict_FourGbHostWith512FromATwoGbHost_IsStale and the new SharedBuffersVerdict_FourGbHostWith768FromAThreeGbHost_IsStale.
  • VERIFIED — every other setting and an unreadable current value are untouched — the name/null guard at DarlingStoreHostProfile.cs:921-924 is unchanged by this commit; only the body after it was widened from exact equality to the band.
  • UNVERIFIED — the reported run counts (81 passed, 560 Census/Ratchet 0 failed, 1584 Stage=Guard 0 failed, 0-error/1-warning build) and the revert check (reverting the band makes the drift test fail 1023≠1022, "the other 80 pass either way") — no .NET SDK/build available in this read-only environment; I verified the drift scenario's arithmetic by hand instead (4088 MB raw derives to 1022 MB, but 4088 MB's bucket is [3584 MB, 4607 MB] whose DeriveMemorySettings ends are 896/1024, so 1023 falls inside the band under the new code), which is consistent with the claim but not a substitute for actually running the suite.

Riskiest lines

  1. Darling/PerformanceMonitor.Darling.Service/DarlingStoreHostProfile.cs:931 — the widened range check deciding whether a mismatch is forgiven — pinned by SharedBuffersVerdict_BucketEdges_AreInsideTheBandAndOneBytePastIsNot
  2. Darling/PerformanceMonitor.Darling.Service/DarlingManagedPostgres.cs:1403-1406 — QuantizedRamBucket's half-GB offset and the Math.Max(..., 1) clamp at the bottom of the RAM scale — pinned by the same bucket-edges test (asserts both ends and the one-byte-past-either-end flip)
  3. Darling/PerformanceMonitor.Darling.Service/DarlingManagedPostgres.cs:1126 — Math.Min(ram / 4, oneGb), the cap the band's monotonicity assumption rests on (both bucket ends must derive through the same non-decreasing function for the range check to be sound) — pinned by the bucket-edges test's highest-end assertion (1024, capped)

Traps near this diff

  • "Two copies of one definition pinned EQUAL to each other fail only after BOTH have drifted (#3684). Alias, do not copy." — does not apply — the new tests assert QuantizedRamBucket/DeriveMemorySettings output against independently-written golden arithmetic (4 * gb - gb / 2, etc.), not against a second production copy of the formula, and DarlingStoreHostProfile.cs:927 is the only production consumer of QuantizedRamBucket.
  • "Lite and Darling ship in parity (CONTRIBUTING's two-store rule): a fix to one SKU's reader, tool, alert or description without the counterpart's is a finding, not a nit" — does not apply — shared_buffers tolerance and HostSettingVerdict are managed-PostgreSQL concepts; Lite has no managed PostgreSQL store to size (grep -rln "HostSettingVerdict\|QuantizedRamBucket" Lite/ Lite.Tests/ returns nothing).
  • "An expression-bodied member holding a { } property pattern is read SHORT by the T-SQL convention guard's member walk (#3667)" — does not apply — QuantizedRamBucket (DarlingManagedPostgres.cs:1401) is block-bodied.

Divergence (blind read vs PR body)

None — the body's account matches the diff on every claim graded above. Both issues round 1 raised (the mislabeled producer/self-alert prose, and the exact-match-vs-band request) are resolved exactly as the body describes, and the new tests (drift, 3 GB→4 GB resize, bucket edges) pin the behavior the body claims.

Reviewer checklist

  • Run DarlingStoreHostProfileTests plus the *Census*/*Ratchet* and Stage=Guard suites and confirm the counts in the test plan (81 passed; 560 total, 0 failed, 1 skipped; 1584 total, 0 failed) and the 0-error/1-pre-existing-warning build.
  • On a real ~4 GB managed store with a raw reading that has drifted a few MB since its shared_buffers was written: confirm --check-settings and get_store_host show matches rather than flipping back to stale.

@erikdarlingdata
erikdarlingdata dismissed claude[bot]’s stale review October 12, 2026 23:38

Addressed in 1fd53d0; the newest automated verdict on that head is LGTM.

@erikdarlingdata
erikdarlingdata merged commit b3bacbe into dev Oct 12, 2026
25 of 26 checks passed
@erikdarlingdata
erikdarlingdata deleted the fix/5716-shared-buffers-verdict branch October 12, 2026 23:39
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