Skip to content

[TCGC] Add typed LRO status metadata - #5677

Open
iscai-msft wants to merge 2 commits into
Azure:mainfrom
iscai-msft:probable-carnival
Open

iscai-msft wants to merge 2 commits into
Azure:mainfrom
iscai-msft:probable-carnival

Conversation

@iscai-msft

@iscai-msft iscai-msft commented Oct 12, 2026 •

Copy link
Copy Markdown
Member

Summary

Adds a scoped, property-level @lroStatusMetadata decorator for selecting auxiliary typed values from an LRO status-monitor response:

model AnalyzeStatus {
  id: string;
  status: OperationState;

  @lroStatusMetadata
  usage?: UsageDetails;
}

The standard status-monitor id remains an ordinary response property. Only explicitly selected auxiliary properties are exposed through this metadata contract.

SDK metadata

SdkLroServiceMetadata gains an optional status metadata collection:

interface SdkLroServiceMetadata {
  // Existing fields unchanged.
  statusMetadata?: SdkLroStatusMetadata[];
}

interface SdkLroStatusMetadata {
  property: SdkModelPropertyType;
}

Each entry returns the exact effective cached SdkModelPropertyType, preserving client and wire names, optionality, decorators, encoding, serialization, access, and type identity. Inherited non-overridden properties are supported; overridden base properties are not treated as effective metadata.

Selected property type graphs receive output usage and standard TCGC access propagation so they remain available to emitters even when they are not part of the final LRO result. Propagation is limited to selected metadata graphs and does not expose unrelated sibling properties. Existing scoped @usage remains additive and scoped property-level @access remains authoritative.

Validation

The decorator diagnoses duplicate active declarations, projected client-name conflicts, and attempts to select structural LRO fields such as status, result, error, polling location, or final location. Properties excluded by emitter scope or lifecycle visibility are also excluded from metadata and graph promotion.

This PR includes a Content Understanding-shaped Azure HTTP Specs scenario whose terminal response returns a typed nested usage value with optional numeric fields and token counts. It intentionally does not mark the normal status-monitor id as status metadata.

Validated with:

  • TCGC build and TypeSpec library lint;
  • focused status-metadata tests: 19 passed;
  • full TCGC tests: 1,737 passed, 2 skipped;
  • Azure HTTP Specs build and scenario validation;
  • mock API validation for all scenarios;
  • live CU Spector flow: POST, running GET, succeeded GET (3/3 requests);
  • regenerated TCGC definitions/reference docs and Spector summary;
  • repository format, lint, and git diff --check.

Related split

URI-derived operation ID metadata is reviewed separately in #5782. This PR supersedes the Content Understanding/status-metadata portion of #5740.

@microsoft-github-policy-service microsoft-github-policy-service Bot added lib:tcgc Issues for @azure-tools/typespec-client-generator-core library meta:website TypeSpec.io updates labels Oct 12, 2026
@github-actions

github-actions Bot commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

All changed packages have been documented.

  • ✅ @azure-tools/azure-http-specs
  • ✅ @azure-tools/typespec-client-generator-core
Show changes

@azure-tools/azure-http-specs - feature ✏️

Add a Content Understanding-shaped HTTP scenario for nested typed LRO status metadata.

@azure-tools/typespec-client-generator-core - feature ✏️

Add the scoped, property-level @lroStatusMetadata decorator with exact typed SDK metadata for auxiliary LRO status-monitor values.

@github-actions

github-actions Bot commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

📦 Package size report

2 packages changed size, +4.33 KB (+0.0%) packed overall.

Package Packed (base → head) Δ Packed Unpacked (base → head) Δ Unpacked
@azure-tools/typespec-client-generator-core 250.27 KB → 253.37 KB +3.10 KB (+1.2%) 🔴 1.33 MB → 1.35 MB +18.04 KB (+1.3%) 🔴
@azure-tools/azure-http-specs 144.22 KB → 145.45 KB +1.23 KB (+0.8%) 🔴 1.21 MB → 1.21 MB +6.21 KB (+0.5%) 🔴
12 package(s) with no notable change
Package Packed (base → head) Δ Packed Unpacked (base → head) Δ Unpacked
@azure-tools/typespec-ts 550.66 KB → 550.66 KB +1 B (+0.0%) 2.75 MB → 2.75 MB —
@azure-tools/typespec-autorest 87.87 KB → 87.87 KB — 424.17 KB → 424.17 KB —
@azure-tools/typespec-autorest-canonical 7.42 KB → 7.42 KB — 26.00 KB → 26.00 KB —
@azure-tools/typespec-azure-core 136.55 KB → 136.55 KB — 733.30 KB → 733.30 KB —
@azure-tools/typespec-azure-examples 80.15 KB → 80.15 KB — 383.36 KB → 383.36 KB —
@azure-tools/typespec-azure-portal-core 36.26 KB → 36.26 KB — 242.62 KB → 242.62 KB —
@azure-tools/typespec-azure-resource-manager 192.89 KB → 192.89 KB — 1.15 MB → 1.15 MB —
@azure-tools/typespec-azure-rulesets 6.00 KB → 6.00 KB — 35.20 KB → 35.20 KB —
@azure-tools/typespec-go 264.28 KB → 264.28 KB — 1.35 MB → 1.35 MB —
@azure-tools/typespec-java 20.22 MB → 20.22 MB — 22.52 MB → 22.52 MB —
@azure-tools/typespec-metadata 15.88 KB → 15.88 KB — 62.08 KB → 62.08 KB —
@azure-tools/typespec-python 42.58 KB → 42.58 KB — 166.02 KB → 166.02 KB —

Packed = gzipped .tgz published to npm. Unpacked = total extracted size. 🆕 added, 🗑️ removed. Packages from the core/ submodule are not included.
🔴 grew · 🟢 shrank — only changes of at least 512 B and 0.5% are marked.

@pkg-pr-new

pkg-pr-new Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@azure-tools/azure-http-specs@5677
npm i https://pkg.pr.new/@azure-tools/typespec-client-generator-core@5677

commit: b059f86

@azure-sdk-automation

Copy link
Copy Markdown
Contributor

You can try these changes here

🛝 Playground 🌐 Website

@JoshLove-msft JoshLove-msft left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Found three correctness issues in the new polling metadata paths, reproduced with native LRO specs: excluded properties are reintroduced, property-level access overrides are lost, and a body-valued polling URI is rejected.

--generated by Copilot

Comment thread packages/typespec-client-generator-core/src/lro-polling-metadata.ts Outdated
Comment thread packages/typespec-client-generator-core/src/types.ts
Comment thread packages/typespec-client-generator-core/src/lro-polling-metadata.ts Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Metadata correctness, access validation, and public-contract inconsistencies remain unresolved.

5 open issues
What changed in this PR

Adds TCGC-owned decorators for exposing long-running operation IDs and typed polling metadata without changing Azure.Core protocol semantics, supporting the L10–L11 proposal in #5432.

Changes:

  • Adds scoped decorators and optional SDK metadata fields.
  • Integrates property selection, validation, and usage/access propagation.
  • Adds tests, diagnostic guidance, reference documentation, and a release note.
File Description
website/​src/​content/​docs/​docs/​libraries/​typespec-client-generator-core/​reference/​index.mdx Lists new decorators.
website/​src/​content/​docs/​docs/​libraries/​typespec-client-generator-core/​reference/​decorators.md Documents decorator signatures.
website/​src/​content/​docs/​docs/​libraries/​typespec-client-generator-core/​guideline.md Explains emitter-facing metadata.
packages/​typespec-client-generator-core/​test/​methods/​lro-polling-metadata.test.ts Tests metadata selection and validation.
packages/​typespec-client-generator-core/​src/​types.ts Propagates selected types’ usage and access.
packages/​typespec-client-generator-core/​src/​tsp-index.ts Registers decorators.
packages/​typespec-client-generator-core/​src/​methods.ts Attaches SDK polling metadata.
packages/​typespec-client-generator-core/​src/​lro-polling-metadata.ts Resolves selections and validates links.
packages/​typespec-client-generator-core/​src/​lib.ts Defines diagnostics.
packages/​typespec-client-generator-core/​src/​internal-utils.ts Exports scope matching.
packages/​typespec-client-generator-core/​src/​interfaces.ts Defines SDK metadata fields.
packages/​typespec-client-generator-core/​src/​diagnostics/​lro-polling-metadata-name-conflict.md Explains name conflicts.
packages/​typespec-client-generator-core/​src/​diagnostics/​lro-polling-metadata-duplicate.md Explains duplicate property declarations.
packages/​typespec-client-generator-core/​src/​diagnostics/​lro-operation-id-non-lro.md Explains native-LRO requirement.
packages/​typespec-client-generator-core/​src/​diagnostics/​lro-operation-id-missing-link.md Explains missing monitor links.
packages/​typespec-client-generator-core/​src/​diagnostics/​lro-operation-id-duplicate.md Explains duplicate ID declarations.
packages/​typespec-client-generator-core/​src/​decorators.ts Stores scoped decorator declarations.
packages/​typespec-client-generator-core/​README.md Adds decorator reference documentation.
packages/​typespec-client-generator-core/​lib/​decorators.tsp Declares public decorators.
packages/​typespec-client-generator-core/​generated-defs/​Azure.ClientGenerator.Core.ts Adds generated decorator contracts.
.chronus/​changes/​lro-polling-metadata-2026-10-12.md Records the feature addition.

Review effort: Balanced

Comment thread packages/typespec-client-generator-core/lib/decorators.tsp Outdated
Comment thread packages/typespec-client-generator-core/src/lro-polling-metadata.ts Outdated
Comment thread packages/typespec-client-generator-core/src/lro-polling-metadata.ts Outdated
Comment thread packages/typespec-client-generator-core/src/methods.ts Outdated
Comment thread packages/typespec-client-generator-core/src/types.ts Outdated
@microsoft-github-policy-service microsoft-github-policy-service Bot added the lib:azure-core Issues for @azure-tools/typespec-azure-core library label Oct 19, 2026
@iscai-msft
iscai-msft requested a balanced review from Copilot October 19, 2026 18:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Unresolved metadata validation, propagation, serialization, and alternate-type compatibility issues affect correctness.

2 open issues
2 previously missed issues

In code that hasn't changed since last review

Medium severity Propagate usage from reconciled polling properties

packages/​typespec-client-generator-core/​src/​types.ts:2099

This lookup runs before hierarchy reconciliation (types.ts:2631), so it still selects an own property that the rebase later discards. When the monitor is used only for polling, Output usage reaches the discarded property's type rather than the replacement type eventually exposed in pollingMetadata; the replacement remains LroPolling-only and is skipped by TypeScript's model emission. Apply selected-property usage/access propagation to the reconciled hierarchy before access overrides and type filtering. Add a regression without a separate monitor-read operation: the current test's public getJobStatus independently supplies Output and masks this failure.

Medium severity Initialize serialization for polling metadata properties

packages/​typespec-client-generator-core/​src/​types.ts:2112

With generate-convenience-methods: false and a monitor referenced only through ResourceLocation<Monitor>, the model-wide serialization initialization at lines 2073–2089 is skipped. This call initializes only the selected property's type, leaving the polling-metadata property's serializationOptions empty even when it has @encodedName. Initialize the selected property itself as well, and cover this configuration so emitters retain its JSON wire name.

5 resolved since last review

Review effort: Balanced

Comment thread packages/typespec-client-generator-core/src/lro-polling-metadata.ts Outdated
Comment thread packages/typespec-client-generator-core/src/methods.ts Outdated

@markcowl Mark Cowlishaw (markcowl) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

A couple of comments and questions for clarification

Comment thread packages/typespec-client-generator-core/lib/decorators.tsp Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

Hierarchy reconciliation can leave selected metadata types without output usage, and referenced whole-body polling links carry an incorrect source location.

No open issues 🎉

2 previously missed issues

In code that hasn't changed since last review

Medium severity Correct polling URI location for body-based operation IDs

packages/​typespec-azure-core/​src/​lro-helpers.ts:503

For a fully bound @pollingOperation whose initial response supplies the polling URI as an @body or @bodyRoot value, lro-info.ts:410–415 labels the link ResponseBody. Copying that location here makes the new operation-ID source describe a named property rather than the entire body (Self). Use createOperationLink, which already distinguishes these cases, and add a compiled reference-plus-body regression; the current whole-body test covers only nextOperationLink.

Medium severity Propagate selected-property usage after hierarchy reconciliation

packages/​typespec-client-generator-core/​src/​types.ts:2133

This propagation runs before handleLegacyHierarchyBuilding (types.ts:2665), not against the final reconciled properties. A selected property from a removed ancestor is absent here until reconciliation lifts it; a selected own property replaced by the new base still resolves to the old property. Without a separately exposed polling operation supplying output usage, the published metadata can therefore reference types that lack Output usage, and newly lifted, otherwise-unused types are omitted from the SDK package. Apply selected-property usage/access/serialization propagation after reconciliation while preserving scoped overrides. Add link-only monitor regressions for both lifted inherited properties and replacement properties; the existing rebasing test's getJobStatus supplies independent output usage.

2 resolved since last review

Review effort: Balanced

@weidongxu-microsoft

Weidong Xu (weidongxu-microsoft) commented Oct 20, 2026 •

Copy link
Copy Markdown
Member

The example on PR description not even have a model for UsageDetails

  @lroStatusMetadata
  usage?: UsageDetails;

Even with the spec PR, I still don't get what's the difference of this usage without @lroStatusMetadata decorator.

How do we know what is this used for this lroStatusMetadata? What polling (or other process) in SDK that is affected by this decorator? What's it relationship with @lroResult or @lroStatus?


OK, seems @lroStatusMetadata not much relate to Java. It already has way to get the raw response. And user can inspect anything through this.


@operationId is because Document Intelligence directly violate guideline https://github.com/microsoft/api-guidelines/blob/vNext/azure/Guidelines.md#the-status-monitor-resource

There is no change to polling process at all.

The current Java customization adds a non-exist property to a JSON model, which is not a good practice in the first place.

@iscai-msft

Copy link
Copy Markdown
Member Author

The example on PR description not even have a model for UsageDetails

  @lroStatusMetadata
  usage?: UsageDetails;

Even with the spec PR, I still don't get what's the difference of this usage without @lroStatusMetadata decorator.

How do we know what is this used for this lroStatusMetadata? What polling (or other process) in SDK that is affected by this decorator? What's it relationship with @lroResult or @lroStatus?

OK, seems @lroStatusMetadata not much relate to Java. It already has way to get the raw response. And user can inspect anything through this.

@operationId is because Document Intelligence directly violate guideline https://github.com/microsoft/api-guidelines/blob/vNext/azure/Guidelines.md#the-status-monitor-resource

There is no change to polling process at all.

The current Java customization adds a non-exist property to a JSON model, which is not a good practice in the first place.

hey Weidong Xu (@weidongxu-microsoft), agreed, @lroStatusMetadata is more for languages that don't expose the full lro polling response to users, but also it doesn't necessarily mean the decorator is meaningless to java, it can tell the emitter which properties to bubble up. For example, in CU it appears you guys bubble up getId() and getUsage() methods.

i agree with your point on @lroOperationId actually, chatting it through with Mark Cowlishaw (@markcowl) but in the meantime, i'm goign to separate it out into a separate pr from @lroStatusMetadata

@microsoft-github-policy-service microsoft-github-policy-service Bot added the lib:azure-http-specs For issues/prs related to the @azure-tools/typespec-azure-http-specs package label Oct 20, 2026
@iscai-msft iscai-msft changed the title [TCGC] Propose LRO polling metadata decorators [TCGC] Add typed LRO status metadata Oct 20, 2026
@weidongxu-microsoft

Weidong Xu (weidongxu-microsoft) commented Oct 21, 2026 •

Copy link
Copy Markdown
Member

hey Weidong Xu (Weidong Xu (@weidongxu-microsoft)), agreed, @lroStatusMetadata is more for languages that don't expose the full lro polling response to users, but also it doesn't necessarily mean the decorator is meaningless to java, it can tell the emitter which properties to bubble up. For example, in CU it appears you guys bubble up getId() and getUsage() methods.

i agree with your point on @lroOperationId actually, chatting it through with Mark Cowlishaw (Mark Cowlishaw (@markcowl)) but in the meantime, i'm goign to separate it out into a separate pr from @lroStatusMetadata

Got it. Though Java seems didn't customize on the LRO of the CU. getUsage() is generated
https://github.com/Azure/azure-sdk-for-java/blob/main/sdk/contentunderstanding/azure-ai-contentunderstanding/src/main/java/com/azure/ai/contentunderstanding/models/ContentAnalyzerAnalyzeOperationStatus.java#L104-L112

For DI, maybe we should check response from other devs. The agent did refresh my memory on that lib (and made some investigation and confirmation), but that lib was done 1 year ago (dug up a long conversation with Sameeksha from 2024, and Java PR).

iscai-msft added 2 commits October 21, 2026 16:28
Add property-level TCGC status metadata and a Content Understanding-shaped Spector scenario for typed usage values.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 89522062-e8a5-40cb-8ec1-1f5a5426133b
Regenerate the TCGC decorator contract with inherited scope documentation and format the LRO status metadata Spector scenario.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 89522062-e8a5-40cb-8ec1-1f5a5426133b

This branch has not been deployed

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

Labels

lib:azure-core Issues for @azure-tools/typespec-azure-core library lib:azure-http-specs For issues/prs related to the @azure-tools/typespec-azure-http-specs package lib:tcgc Issues for @azure-tools/typespec-client-generator-core library meta:website TypeSpec.io updates

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants