Add x_RecommendationCategory and x_RecommendationSubcategory enrichments to v1_4 Recommendations#2194
Add x_RecommendationCategory and x_RecommendationSubcategory enrichments to v1_4 Recommendations#2194flanakin wants to merge 24 commits into
Conversation
Adds IngestionSetup_v1_3.kql with Costs/Prices/CommitmentDiscountUsage/ Recommendations/Transactions transforms and final tables renamed for FOCUS 1.3. Cost and Usage gains 8 new FOCUS 1.3 columns: AllocatedMethodId/Details/ResourceId/ResourceName/Tags (data-generator split cost allocation), ContractApplied (per-row contract commitment application), ServiceProviderName + HostProviderName (replacing the deprecated ProviderName/PublisherName, with empty-fallback for back compat). Costs_raw now carries the new columns so downstream v1_2 transforms keep working and v1_3 transforms can read them directly. The v1_3 file is wired into the Bicep deployment alongside v1_0 and v1_2. The unversioned Costs() function still aliases to v1_2 — phase 2 adds Costs_v1_3() and retargets Latest. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds HubSetup_v1_3.kql with Costs_v1_3, Prices_v1_3, CommitmentDiscountUsage_v1_3, Recommendations_v1_3, and Transactions_v1_3 that union the new Costs_final_v1_3 with the existing Costs_final_v1_2 and Costs_final_v1_0 tables. For v1_2 data unioned into the v1_3 view, the 8 new FOCUS 1.3 columns default to null/empty and ServiceProviderName/HostProviderName are populated from the deprecated ProviderName/PublisherName for back compat. The same defaults apply to the v1_0 union arm on top of the existing v1_0 -> v1_2 conversion. HubSetup_Latest.kql aliases now point to *_v1_3 functions so the unversioned Costs(), Prices(), etc. return the latest schema. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the FOCUS 1.3 Contract Commitment supplemental dataset: - ContractCommitment_raw table in IngestionSetup_RawTables.kql with the 14 mandatory FOCUS 1.3 columns plus standard hubs source metadata. - ContractCommitment_transform_v1_3 + ContractCommitment_final_v1_3 in IngestionSetup_v1_3.kql, with update policy mapping raw to final. - ContractCommitment_v1_3 hub function in HubSetup_v1_3.kql that reads the final table directly (no older versions to union). - Unversioned ContractCommitment alias in HubSetup_Latest.kql. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds IngestionSetup_v1_4.kql as a preview schema for FOCUS 1.4 working_draft. Cost and Usage drops the deprecated ProviderName and PublisherName columns (removed in 1.4 per spec). Contract Commitment expands by 14 new columns: BenefitCategory, ContractCommitmentApplicability (JSON), Created, DiscountPercentage, DurationType, FulfillmentInterval, LastUpdated, LifecycleStatus, Model, OfferCategory, PaymentInterval, PaymentModel, PaymentUpfrontPercentage, PricingCurrencyContractCommitmentCost. The internal ProviderName/PublisherName fix-up logic in the Costs transform stays so HostProviderName / ServiceProviderName can fall back to those values when source data does not yet supply them. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds HubSetup_v1_4.kql with the v1_4-preview-shaped hub functions. Costs_v1_4 unions Costs_final_v1_4, Costs_final_v1_3, Costs_final_v1_2, and Costs_final_v1_0; ProviderName and PublisherName are dropped from the v1_4 project list (removed in 1.4 per spec). ContractCommitment_v1_4 unions ContractCommitment_final_v1_4 with ContractCommitment_final_v1_3 and extends v1_3 data with empty/null defaults for the 14 new FOCUS 1.4 columns. HubSetup_Latest.kql is intentionally NOT retargeted to v1_4. Per the preview convention in data-model.md, unversioned aliases stay pinned to the latest GA schema (v1_3) until v1_4 promotes from preview to GA. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Updates plugin skill files so plugin guidance reflects the new hub schemas and FOCUS columns added in this milestone: - finops-hubs.md: lists the full set of unversioned functions (CommitmentDiscountUsage, ContractCommitment included), notes the v1_0 / v1_2 / v1_3 / v1_4-preview versioned variants, and enumerates the FOCUS 1.3 column additions plus the 1.4 ProviderName / PublisherName removal. - finops-hubs-deployment.md: extends the supported FOCUS export versions to 1.0r2 / 1.2 / 1.2-preview (current Cost Management) and notes that hubs can also ingest 1.3 / 1.4-preview when Cost Management ships those exports. - ftk-database-query.md: expands from four to six analytic functions, adds CommitmentDiscountUsage and ContractCommitment sections, and surfaces the FOCUS 1.3 columns on the Costs() reference table. - ftk-output-style.md: adds FOCUS 1.3+ terminology preferences for ServiceProviderName, HostProviderName, and ContractApplied. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- HubsFocusSchemas.Tests.ps1: 108 Pester tests asserting the FOCUS 1.3 and 1.4-preview schema additions land where expected: Costs_raw additions, ContractCommitment_raw definition with both 1.3 and 1.4 columns, presence of versioned transforms and final tables in IngestionSetup_v1_3 / v1_4, presence of versioned hub functions in HubSetup_v1_3 / v1_4, the union arms in Costs_v1_3 and Costs_v1_4, the Latest aliases pinned to v1_3 (not preview v1_4), and the Bicep / build-config wiring. - changelog.md: adds v15.0.0 hub entries describing the FOCUS 1.3 GA and 1.4-preview schema additions, the new ContractCommitment dataset, the unversioned alias retarget, and the upgrade-procedure refresh. Adds a plugin entry for #2119. Updates ms.date to today. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Consolidates FOCUS 1.3 and 1.4 column additions into a single v1_4 ingestion setup file. Removes the intermediate v1_3 file, adds ContractCommitment_raw table definition, and updates app.bicep and .build.config to reference v1_4. Co-Authored-By: Claude <noreply@anthropic.com>
…cus14-phase2-hubs-1.3
Renames HubSetup_v1_3.kql to HubSetup_v1_4.kql, consolidating all hub functions (including ContractCommitment) for FOCUS 1.4 GA. Updates HubSetup_Latest.kql to alias all unversioned functions to v1_4. Updates app.bicep and .build.config to reference v1_4. Co-Authored-By: Claude <noreply@anthropic.com>
Updates all FOCUS version references from 1.3/1.4-preview to v1_4 GA. Removes intermediate v1_3 function references. Marks ContractCommitment as FOCUS 1.4+ (not 1.3+). Removes preview designations for v1_4. Co-Authored-By: Claude <noreply@anthropic.com>
Updates Pester tests to validate v1_4 (not v1_3) schema files, removes tests for the eliminated intermediate v1_3 schema, and corrects HubSetup_Latest assertions to expect _v1_4() aliases. Updates changelog to reflect FOCUS 1.4 GA release without preview designation. Co-Authored-By: Claude <noreply@anthropic.com>
- Pluralize ContractCommitments_raw / _transform_v1_4 / _final_v1_4 / mapping / update policy - Add BillingPeriods_raw + IngestionSetup_v1_4 transforms/finals/policies (FOCUS 1.4 supplemental dataset) - Add InvoiceDetails_raw + IngestionSetup_v1_4 transforms/finals/policies (FOCUS 1.4 supplemental dataset) - Add 12 ContractCommitment* per-row columns + CommitmentProgramEligibilityDetails + InvoiceDetailId to Costs_raw, Costs_final_v1_4, and Costs_transform_v1_4 - Fix x_Source* annotations on ContractCommitments_raw to Hubs v1_4+ - Update Costs_raw ProviderName/PublisherName annotations to FOCUS 0.5-1.3 (removed in 1.4; kept for back compat) - Update Costs_raw Region annotation: deprecated -> removed - File #2159 for the FOCUS 1.4 native-columns architecture research 🤖 Generated with [Claude Code](https://claude.ai/claude-code) Co-Authored-By: Michael Flanakin <flanakin@users.noreply.github.com> Co-Authored-By: Claude <noreply@anthropic.com>
…cus14-phase2-hubs-1.3
- Rename ContractCommitment_v1_4() -> ContractCommitments_v1_4() (and update folder label) - Add BillingPeriods_v1_4() and InvoiceDetails_v1_4() hub functions - Add BillingPeriods(), ContractCommitments() (renamed), and InvoiceDetails() unversioned aliases in HubSetup_Latest.kql - Add CommitmentProgramEligibilityDetails + 12 ContractCommitment* + InvoiceDetailId column defaults to Costs_final_v1_0 and Costs_final_v1_2 union arms (back-compat shims) and add them to the project list 🤖 Generated with [Claude Code](https://claude.ai/claude-code) Co-Authored-By: Michael Flanakin <flanakin@users.noreply.github.com> Co-Authored-By: Claude <noreply@anthropic.com>
…-phase6-plugin # Conflicts: # src/templates/finops-hub/.build.config # src/templates/finops-hub/modules/Microsoft.FinOpsHubs/Analytics/app.bicep # src/templates/finops-hub/modules/Microsoft.FinOpsHubs/Analytics/scripts/HubSetup_v1_4.kql # src/templates/finops-hub/modules/Microsoft.FinOpsHubs/Analytics/scripts/IngestionSetup_RawTables.kql # src/templates/finops-hub/modules/Microsoft.FinOpsHubs/Analytics/scripts/IngestionSetup_v1_4.kql
- Rename ContractCommitment() -> ContractCommitments() in skill references and agent docs - Add BillingPeriods() and InvoiceDetails() to the function list and dedicated agent doc sections - Mention the new FOCUS 1.4 per-row columns (CommitmentProgramEligibilityDetails, 12 ContractCommitment* columns, InvoiceDetailId) - Update output-style guidance to reference all three supplemental datasets 🤖 Generated with [Claude Code](https://claude.ai/claude-code) Co-Authored-By: Michael Flanakin <flanakin@users.noreply.github.com> Co-Authored-By: Claude <noreply@anthropic.com>
…hase7-tests-changelog
A merge artifact from rebasing on the v1_3 ancestry left a singular ContractCommitment() function referencing ContractCommitment_v1_3() in HubSetup_Latest.kql. v1_3 was eliminated and the dataset was pluralized to ContractCommitments_v1_4(); the orphan would fail to load on hub deployment. Remove it. Co-Authored-By: Michael Flanakin <flanakin@users.noreply.github.com> Co-Authored-By: Claude <noreply@anthropic.com>
…hase7-tests-changelog
Tests: - Pluralize ContractCommitments_raw / _final_v1_4 / _v1_4 assertions - Assert new BillingPeriods_raw + InvoiceDetails_raw datasets exist with their FOCUS 1.4 columns - Assert new BillingPeriods_v1_4(), InvoiceDetails_v1_4(), ContractCommitments_v1_4() hub functions - Assert HubSetup_Latest aliases for BillingPeriods(), ContractCommitments(), InvoiceDetails() - Assert Costs_raw and Costs_final_v1_4 include the 14 new FOCUS 1.4 columns - Assert NO singular ContractCommitment_raw / ContractCommitment_v1_4 / ContractCommitment() exists - Assert Costs_raw keeps removed ProviderName/PublisherName/Region for back compat Changelog: - Expand v15.0.0 entry with the 14 new FOCUS 1.4 columns and the three new supplemental datasets (ContractCommitments, BillingPeriods, InvoiceDetails) - Update plugin entry to list ContractCommitments() / BillingPeriods() / InvoiceDetails() 🤖 Generated with [Claude Code](https://claude.ai/claude-code) Co-Authored-By: Michael Flanakin <flanakin@users.noreply.github.com> Co-Authored-By: Claude <noreply@anthropic.com>
Adds two hub-toolkit enrichment columns to the Recommendations dataset in the FOCUS 1.4 hub schema, normalized to a fixed hub taxonomy so reports can group recommendations consistently across providers. - IngestionSetup_v1_4.kql: normalize x_RecommendationCategory into the 5 top-level values (Cost, Operational Excellence, Performance, Reliability, Security); map Azure Advisor's HighAvailability -> Reliability; derive x_RecommendationSubcategory from the documented taxonomy with 'Other' as the fallback. Add both columns to Recommendations_final_v1_4. - HubSetup_v1_4.kql: include both columns in the Recommendations_v1_4() project list. - data-model.md: document the allowed values for both columns and the normalization behavior. - HubsFocusSchemas.Tests.ps1: assert columns exist in the final table, the transform projects them, and the case() expression covers all 5 top-level categories. - changelog.md: note the new enrichment columns under FinOps hubs v15.0.0. Co-Authored-By: Michael Flanakin <flanakin@users.noreply.github.com> Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Taxonomy review — "Pick one" resolutions (Low Utilization, Idle Resources, Unused Capacity)The PR resolved both of the user's open "pick one" questions and the standalone-Unused-Capacity question. The picks are reasonable but the boundary between
Folding
Item 3 is fundamentally different from 1 and 2 — the user has already paid for it, the resource isn't actually idle from the provider's POV, and the remediation lives in commitment portfolio management, not resource cleanup. Lumping unused commitment hours under Recommendation: Either (a) keep 🤖 [AI][Claude Code] Taxonomy review |
Taxonomy review — Cross-category overlap and routing ambiguityA single subcategory list per parent category is clean, but several subcategories sit on category boundaries where ingestion will have to make a judgment call. These need either (a) tie-breaker rules documented next to the taxonomy, or (b) renames that make the boundary obvious.
Without disambiguation rules, two Hub deployments ingesting the same Advisor stream could classify identical recommendations differently depending on which 🤖 [AI][Claude Code] Taxonomy review |
Taxonomy review — Missing subcategoriesThe Cost category is the most consequential one for a FinOps Hub, and several very common cost-recommendation types have no home in the current taxonomy and would all fall into Critical gaps (would already be hit by Azure Advisor, Cost Management, and partner tools today):
Important gaps:
Cross-cloud / multi-cloud allocation — the user's question implied this is in scope. If the hub will normalize AWS Cost Explorer / GCP Recommender recs (per the FOCUS framing), categories like "Reserved Instance modification" (AWS) and "Committed Use Discount" (GCP) already map cleanly to existing Cost subcategories — that's fine. But "Savings Plans coverage gap", "Compute Optimizer rightsizing", and "GCP Recommender idle VM" need test coverage to confirm the mapping holds. Worth adding test cases. The taxonomy currently captures the FinOps Framework's "Workload Optimization" and "Rate Optimization" capabilities reasonably well but misses most of "Architecting for Cloud" (license, tier, transfer) and parts of "Allocation". 🤖 [AI][Claude Code] Taxonomy review |
Taxonomy review — Naming consistency and label hygieneThe taxonomy is mostly noun-phrased and Title-Cased, but a few inconsistencies will create friction for downstream consumers (filters, dropdowns, KQL Hyphen vs space inconsistency:
Either keep the hyphen for
This is the most jarring inconsistency. Suggest renaming to Verb vs noun phrasing: mostly noun-phrased, which is good. The two outliers worth checking:
Capitalization — "Other" placement —
🤖 [AI][Claude Code] Taxonomy review |
Taxonomy review — KQL mapping logic and default behaviorThe Asymmetric defaults — category vs subcategory:
This asymmetry is documented in the PR description, but it has a usability consequence: a row can legitimately have Suggest one of:
Reservation default to Hard-coded reservation subcategory — the fallback
If the hub ever ingests reservation utilization recs under the same
No mapping for Microsoft Defender for Cloud / Microsoft Sentinel recs — these flow through a different API and category schema ( Subcategory 🤖 [AI][Claude Code] Taxonomy review |
Taxonomy review — Documentation completeness and canonical-vs-open statusThe taxonomy is documented in Is this a closed enum or an open vocabulary? The PR description says "fixed hub taxonomy" but the docs don't explicitly say "this list is canonical and will not change without a schema version bump". Without that statement:
Suggest adding to
No queryable form — the taxonomy lives in (a) the KQL
Today, a Power BI author building a Recommendations report has to either (a) re-type the list from the docs, or (b) Mapping table to source values is missing — the docs say "Azure Advisor's
This becomes essential when you add a second source (Defender for Cloud, AWS Trusted Advisor, GCP Recommender). Changelog entry — the entry calls out the columns but not the taxonomy decisions ( 🤖 [AI][Claude Code] Taxonomy review |
Summary
Recommendationsdataset in the FOCUS 1.4 hub schema (v1_4):x_RecommendationCategoryandx_RecommendationSubcategoryCategory) are normalized into a fixed hub taxonomy on ingestion; unmapped categories become an empty string and unmapped subcategories becomeOtherHighAvailability->Reliability(the hub taxonomy usesReliabilityas the top-level category, withHigh Availabilityas one of its subcategories)docs-mslearn/toolkit/hubs/data-model.mdTaxonomy decisions
The taxonomy provided in the design notes had a few open markers; the picks below are reflected in code, docs, and tests:
Low Utilization. Clearer FinOps terminology and keeps a clean conceptual split from idle/orphaned resources.Idle Resources. More specific than "Unused", and the parenthetical already noted it covers orphaned resources.Idle Resourcesrather than kept standalone. Unused capacity is conceptually idle compute/storage; a separate bucket would have produced overlap and forced ambiguous mappings at ingestion time. Documented this in the data-model note ("Idle Resources (includes unused capacity and orphaned resources)").High Availaibility->High Availabilitytypo in the Reliability subcategory list.Files changed
src/templates/finops-hub/modules/Microsoft.FinOpsHubs/Analytics/scripts/IngestionSetup_v1_4.kql— adds normalizationcase()for both columns inRecommendations_transform_v1_4()and addsx_RecommendationSubcategorytoRecommendations_final_v1_4src/templates/finops-hub/modules/Microsoft.FinOpsHubs/Analytics/scripts/HubSetup_v1_4.kql— addsx_RecommendationSubcategoryto theRecommendations_v1_4()project list (the function uses an explicit projection, so the column must be listed for it to flow throughRecommendations())docs-mslearn/toolkit/hubs/data-model.md— documents both columns and the full taxonomysrc/powershell/Tests/Unit/HubsFocusSchemas.Tests.ps1— Pester assertions for column presence, transform projection, and taxonomy coveragedocs-mslearn/toolkit/changelog.md— entry under FinOps hubs v15.0.0Test plan
pwsh -Command "Invoke-Pester -Output Detailed -Path ./src/powershell/Tests/Unit/HubsFocusSchemas.Tests.ps1"— all 167 tests passRecommendations()returns rows withx_RecommendationCategorypopulated for reservation recommendations (=Cost) andx_RecommendationSubcategory=Commitment Discount CoverageHighAvailabilityrecommendations surface asx_RecommendationCategory = ReliabilityStacked on top of flanakin/focus14-phase7-tests-changelog; targets
flanakin/focus14.Generated with Claude Code