Skip to content

The trend family's window floor is window_truncated on both SKUs, not the page dialect's truncated: get_query_trend, the duration-trend trio and get_query_store_top publish the store's reach under its own key, every consumer and description follows, and the vocabulary census holds the two facts apart (partial #3653 — item 17) - #3793

Merged
erikdarlingdata merged 1 commit into
devfrom
fix/3653-window-truncated-rename
Sep 20, 2026

Conversation

@erikdarlingdata

Copy link
Copy Markdown
Owner

One key carried two facts with opposite remedies, and the trend family's was the wrong one to be wearing the page dialect's spelling

Partial #3653 — item 17 (A15/A16), the clause the item's own text marks as NOT done: "window_truncated NOT done — ~15 consumers incl. get_query_store_top in DarlingMcpDataTools.cs, counted on the PR." #3703 found the homonym and classified it as stated residue; #3706 measured the blast radius, found it past the brief's ceiling, and stopped with a count. This is the rename, on both SKUs, with the census that keeps it renamed.

The mechanism

truncated on the MCP wire meant two things. On twenty-odd paged tools it is the page cut: the caller's limit bit, observed off a cap + 1 fetch (McpHelpers.BoundPage), published beside a *_returned count, and the remedy is a bigger limit. On the #2364 / #2353 trend family — get_query_trend, get_query_duration_trend, get_procedure_duration_trend, get_query_store_duration_trend — and on get_query_store_top, the same key was the window floor: the served series begins later than the requested start because the tier that answered no longer holds the window's head (raw dropped at four days with the rollups armed; a rollup that has not materialized the head; a store younger than the window; on Lite a retention_days purge or a server added mid-window). It rides beside effective_start / effective_hours_back, is judged off the served head against the shared ninety-minute TruncationSlack, and no limit changes it — get_query_store_top's top is a rank, and the trend tools have no cap at all. A client that had learned the first meaning read "raise the limit" off a fact no limit changes.

The window floor is now window_truncated — the <bound>_truncated dialect #3703 classified for a second bound in one payload (scan_truncated was its first member). The page cut keeps truncated. Nothing else in the disclosure block moves: the six keys are still six, in the same order, on the data path and the empty one.

What moved (the count #3706 asked for)

Before this PR, the window-floor fact under bare truncated had 4 emitters, 1 web consumer, 7 instructions rows naming the key, 0 web-catalog rows naming it, and 17 test asserts reading it. After: 0 window-floor sites spell it truncated; window_truncated has 4 emitters, 1 consumer, 9 instructions rows, 5 catalog rows, 9 tool descriptions and the same 17 asserts.

surface site what changed
emitter DarlingMcpTrendTools.GetQueryTrend initializer window_truncated = history.Truncated
emitter DarlingMcpTrendTools.TrendDisclosure.WriteTo envelope["window_truncated"] — the trio's data AND empty envelopes
emitter DarlingMcpDataTools.GetQueryStoreTop initializer window_truncated = truncated; truncation_note keeps its name (it is the prose for THIS flag; *_note is the idiom)
emitter Lite McpQueryTools.WriteDisclosure envelope["window_truncated"] — the trio + Lite's get_query_trend
consumer server-tabs.js drawQueryTrend reads trend.data.window_truncated; the notice sentence is word for word. Reading the old key would have failed SILENTLY — undefined is falsy, so the "history starts N hours back" notice would simply stop appearing under an axis that says otherwise
description 9 tools (Darling 5, Lite 4) McpHelpers.WindowTruncatedDescription, one shared constant appended to each: names the key, the reach beside it, that it is not a page cut, and the WIRE CHANGE ("spelled truncated before #3653; the old spelling is not published here any more") — the #3719 shape, per tool this time because every one of these descriptions is the surface a client learns the key from
instructions DarlingMcpInstructions.cs ×5 (get_query_store_top, get_query_trend, the trio), McpInstructions.cs ×4 say window_truncated, and where the row explains the block, why it renamed
web catalog DarlingWebEndpoints.cs ×5 one clause each
prose DarlingTrendReader.cs, DurationTrendRouting.cs, ViewerDataService.QueryTrends.cs, ViewerServerTab.QueryTrends.cs the doc comments that named the wire key name the new one; the C# members keep their names (DurationTrendResult.Truncated, QueryHistoryResult.Truncated, TruncationSlack, DescribeCoverage — ViewerTrendRoutingPortTests pins the alias signatures byte-for-byte and they are untouched)

get_query_store_top on Lite publishes no window floor at all today (no effective_start, no flag) — nothing to rename there; its description stays as it was, and the two SKUs' descriptions for that one tool now differ by the Darling clause because the facts differ. The brief's premise that #3706 made the trend descriptions byte-identical across SKUs is not what the tree says — they already differ by the tier sentence ("On the per-collection (raw) route …" vs "Lite has one tier …") and no parity pin holds them equal; the shared clause is identical by construction on the nine that carry it.

The census, which is the part that keeps this renamed

McpPayloadContractCensusTests (Darling.Tests, sweeping both SKUs' tool sources):

  • window_truncated joins SecondBoundCutKeys with the three files that emit it, and the class summary's residue sentence ("truncated carries two facts …") is gone. CutNoteKeys' truncation_note entry says which flag it sits beside on each tool.
  • The payload-key matcher now reads the ordered-envelope idiom (envelope["key"] = …) as well as initializers. Both disclosure writers use it, so while the census matched initializers only, the window floor was invisible to it — which is how the homonym survived a roster that read as complete. The only cut-ish key ever written that way is this one (verified by enumerating every ["…"] = write in both tool directories), so the widening moves no other roster.
  • TheWindowFloor_IsSpelledWindowTruncated_BesideItsReach_AndNeverBareTruncated_OnBothSkus is the fact the roster alone cannot state. A bare truncated is the page dialect and is permitted everywhere; what makes a truncated the homonym is its neighbour. So the population is every block on either SKU that writes effective_hours_back as a payload key — the innermost brace pair around it, walked over CSharpSourceWalker-strings-blanked code so a brace in a message cannot open or close it — and inside each, window_truncated and effective_start must be written and truncated must not. Offenders fail by file and line. The publisher set is an equality on (file, idiom, count): DarlingMcpDataTools.cs initializer ×1, DarlingMcpTrendTools.cs initializer ×1 + envelope ×1, McpQueryTools.cs envelope ×1.
  • The discriminator is the reach vocabulary, not window_start as the brief proposed: get_query_heatmap publishes window_start / window_end (the requested axis) beside a bare truncated that IS a page cut — its cell cap, observed off limit + 1, with first_time_bin / last_time_bin saying which bins survived. A window_start rule would flag that tool for spelling its page cut correctly.
  • TheWindowFloorChecker_FlagsTheHomonym_AndPassesAPageCut runs the checker on a synthetic offender (line-numbered), a synthetic page cut with a brace inside its message, and a synthetic envelope with a nested block — so a matcher that stopped matching reads as red, not as a clean sweep. Also executed live on the real tree: putting envelope["truncated"] back in Lite's WriteDisclosure reds the fact at McpQueryTools.cs:810 (envelope) and reds the roster equality (emitted on [DarlingMcpDataTools.cs, DarlingMcpTrendTools.cs]).
  • EveryWindowFloorTool_CarriesTheSharedClause_AndNoOtherToolDoes: the nine tools whose attributes carry McpHelpers.WindowTruncatedDescription, as an equality; the constant executed for the key, the reach, "not a page cut", and the wire-change sentence; and by reflection the Darling five publish it in the attribute a client reads.

Pins that read the key on both SKUs moved with it: DarlingPerformanceTrendsReadTests (5 asserts + the six-key order block), QueryStoreTrendRoutingLiveTests (3), QueryStoreTopWindowTests (now reads the tool's own body — the old whole-file Contains("truncated") would have passed on any of the file's page-cut neighbours), Lite PerformanceTrendsToolTests (4 + block) and TrendEmptyParityToolTests (4). New: ServerPageTabsTests.TheQueryTrendDrillDown_ReadsTheWindowFloorOffItsOwnKey.

What this PR does NOT do

  • Lite's get_query_store_top gains no window floor. It never had one (no effective_start, no flag); adding the reach probe is a feature, not a rename. Noted for the item.
  • deprecated/Dashboard is untouched and unaffected: its McpQueryTools.cs publishes neither effective_start nor the flag, and it is not an MCP client, so it neither emits nor reads the key.
  • truncation_note on get_query_store_top keeps its name. It is the prose beside the flag, the flag is now window_truncated, and the roster says so.
  • The C# members keep their names — the rename is the wire key. ViewerTrendRoutingPortTests pins DescribeCoverage's (DateTime EffectiveStartUtc, bool Truncated) tuple and TruncationSlack's alias byte-for-byte; both stand.
  • Item 17's second clause — the two stored-interval spellings — is inventoried, not renamed. Table below.
  • No schema rung, no PgTarget*, no CHANGELOG.md.

Inventory: sample_interval_seconds vs interval_seconds on the wire (item 17, second clause — NOT renamed)

The brief's whole-tree counts (git grep -c '"interval_seconds"' = 19, '"sample_interval_seconds"' = 70 at this head) are dominated by SQL column names, collector projections and test pins; the wire sites — payload keys in the two MCP tool directories — are twelve, on six tools:

SKU tool file key what the value is
Darling get_latch_stats (row + latest block) DarlingMcpLatchSpinlockTools.cs ×2 interval_seconds reader's LatestIntervalSeconds, null when unknowable (restart row)
Darling get_spinlock_stats DarlingMcpLatchSpinlockTools.cs ×1 interval_seconds same, null when unknowable
Darling get_pg_io_trend DarlingMcpPgTrendTools.cs ×1 interval_seconds derived span between DISTINCT collection times (not a stored column)
Darling get_file_io_stats DarlingMcpDataTools.cs ×1 sample_interval_seconds the raw stored column as collected (0 on a restart row is passed through)
Darling get_perfmon_trend DarlingMcpTrendTools.cs ×1 sample_interval_seconds raw stored column
Darling get_resource_semaphore DarlingMcpMemoryGrantTools.cs ×1 sample_interval_seconds is > 0 ? … : null — the null-when-unknowable fact under the raw spelling
Lite get_latch_stats, get_spinlock_stats McpLatchSpinlockTools.cs ×2 interval_seconds KnownInterval(...), null when unknowable
Lite get_file_io_stats McpIoTools.cs ×1 sample_interval_seconds raw stored column
Lite get_perfmon_trend McpPerfmonTools.cs ×1 sample_interval_seconds raw stored column
Lite get_resource_semaphore McpMemoryTools.cs ×1 sample_interval_seconds is > 0 ? … : null — null-when-unknowable under the raw spelling

Read at each site, the split is mostly clean — interval_seconds = "the seconds this rate was divided by, null when there were none", sample_interval_seconds = "the column as stored" — with one crossed pair: get_resource_semaphore on both SKUs publishes the null-when-unknowable fact under the raw spelling. The #3703-style pass would be: that pair to interval_seconds (both SKUs, one consumer sweep), and a description clause on the two raw-column tools saying 0 means the collector could not difference. The web client reads neither key (zero hits under wwwroot/js). Not done here — it is its own lane.

Executed on this Mac

Builds -c Release -p:EnableWindowsTargeting=true, 0 warnings: PerformanceMonitor.Common, Darling.Storage, Darling.Service, Darling.Viewer, PerformanceMonitorLite, Darling.Tests, Lite.Tests. node --check on server-tabs.js.

Darling.Tests through a Darling.Tests-named net10.0 harness against a throwaway timescale/timescaledb:2.28.1-pg18 (context desktop-linux, torn down): the six named censuses (RepoFileAdoptionTests, StragglerCommandTimeoutTests, LiveCleanupConversionRatchetTests, MeasurementContractCensusTests, McpPageContractTests, FactSourceRegistryTests) plus FleetIdentifierScrubTests, PgTargetMcpSurfaceTests, McpLatestSnapshotStampTests, DocCommentHygieneTests, McpPayloadContractCensusTests (67), QueryStoreTopWindowTests, ServerPageTabsTests, DarlingMcpTrendToolsTests, BaselineDiscontinuityRenderTests, DarlingWebEndpointsTests, McpZeroIsAMeasurementTests, DarlingMcpDataToolsTests — green; live: DarlingPerformanceTrendsReadTests (raw + empty envelopes), DarlingPerformanceTrendsTierRoutingLiveTests (hourly route, the unserved-head empty envelope), QueryStoreTrendRoutingLiveTests (rollup+raw, below-floor, tail-only), DarlingMcpDataToolsLivePostgresTests (get_query_store_top's envelope) — 6/6 green reading window_truncated off every route. Whole harness: 10,969 tests, 164 red = the platform baseline (159 on lane-3778's dev run) + 3 live fixture-path artefacts of the harness (Fixtures/SystemHealth/*.xml not copied) + the two #3787 dev reds #3790 has since fixed (this branch is rebased onto it). Lite through a Lite.Tests-named harness: PerformanceTrendsToolTests, TrendEmptyParityToolTests, McpMissMessageParityPinTests, McpDescriptionTruthPinTests, BaselineDiscontinuityRenderCensusTests, CrossAppMcpToolInventoryPinTests, MeasurementContractCensusTests, McpLatestSnapshotStampTests green; McpPageContractTests 19/21 with the two PresentationFramework wait-stats reds reproduced on dev by #3702 / #3703 / #3706.

First executed in CI: nothing on this surface — every changed assertion ran here.

Partial #3653 — item 17 (window_truncated)

… the page dialect's truncated: get_query_trend, the duration-trend trio and get_query_store_top publish the store's reach under its own key, every consumer and description follows, and the vocabulary census holds the two facts apart (partial #3653 — item 17)

`truncated` carried two facts on the wire. On twenty-odd paged tools it is the caller's `limit` biting — observed off a `cap + 1` fetch, beside `*_returned`, remedied by a bigger limit. On the #2364 / #2353 trend family and on get_query_store_top it was the store's REACH: the served series begins later than the requested start because the tier that answered no longer holds the window's head, beside `effective_start` / `effective_hours_back`, and no limit changes it. #3703 classified the homonym and left it as stated residue; #3706 counted the blast radius (~15) and stopped. This is that rename.

Emitters (4): DarlingMcpTrendTools get_query_trend initializer + TrendDisclosure.WriteTo (the trio, data and empty envelopes); DarlingMcpDataTools get_query_store_top (truncation_note keeps its name — it is the prose for this flag); Lite McpQueryTools.WriteDisclosure (the trio + get_query_trend). Consumers: server-tabs.js drawQueryTrend reads window_truncated (undefined is falsy — the old key would have silently dropped the notice). Descriptions: McpHelpers.WindowTruncatedDescription, one shared clause on the nine publishing tools (5 Darling, 4 Lite), naming the key, the reach beside it, and the WIRE CHANGE; nine instructions rows and five web-catalog rows say window_truncated. C# members (Truncated, TruncationSlack, DescribeCoverage) keep their names — the wire key renamed.

Census: McpPayloadContractCensusTests classifies window_truncated as the second bound it is (SecondBoundCutKeys), reads the ordered-envelope idiom (`envelope["key"] =`) the disclosure block uses so Lite's writer is in the roster, and adds TheWindowFloor_IsSpelledWindowTruncated_BesideItsReach_AndNeverBareTruncated_OnBothSkus: every block on both SKUs that writes effective_hours_back must write window_truncated and effective_start and never bare truncated — brace-walked over strings-blanked code, rostered as an equality on (file, idiom, count), checked first on a synthetic offender and a synthetic page cut. The discriminator is the reach vocabulary, not window_start: get_query_heatmap publishes window_start beside a bare truncated that IS a page cut. EveryWindowFloorTool_CarriesTheSharedClause_AndNoOtherToolDoes is the description half. The residue sentence is gone.
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