Repository navigation
[Swagger Linter Migration][Superseded by #5652] XMSLongRunningOperationProperty -> lro-missing-polling-metadata - #5709
Conversation
Promote XMSLongRunningOperationProperty as lro-missing-polling-metadata from reviewed source 2f7e1d5 (PR #5704). Preserve the native predicate and targets while removing mixed-runner isolation. Register the official ARM rule as disabled by default. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 8e9d80e2-2e85-4bd4-9baa-eb937b5c60f1
|
All changed packages have been documented.
Show changes
|
commit: |
📦 Package size report✅ No notable package size changes compared to the base branch. 14 package(s) with no notable change
Packed = gzipped |
There was a problem hiding this comment.
🟢 Approval recommended
The implementation matches the documented scope, is disabled by default, and has comprehensive targeted coverage.
0 open findings
What changed in this PR
Adds an opt-in ARM lint rule requiring native polling metadata when polling headers are present.
Changes:
- Implements and registers
lro-missing-polling-metadata. - Adds comprehensive tests and documentation.
- Registers the rule as disabled by default with Chronus entries.
| File | Description |
|---|---|
.chronus/changes/lro-missing-polling-metadata.md |
Records the ARM package feature. |
.chronus/changes/register-lro-missing-polling-metadata.md |
Records disabled ruleset registration. |
packages/typespec-azure-resource-manager/README.md |
Lists the new rule. |
packages/typespec-azure-resource-manager/src/linter.ts |
Registers the rule. |
packages/typespec-azure-resource-manager/src/rules/lro-missing-polling-metadata.md |
Documents behavior and examples. |
packages/typespec-azure-resource-manager/src/rules/lro-missing-polling-metadata.ts |
Implements polling-header validation. |
packages/typespec-azure-resource-manager/test/rules/lro-missing-polling-metadata.test.ts |
Covers qualifying, excluded, template, and deduplication cases. |
packages/typespec-azure-rulesets/src/rulesets/resource-manager.ts |
Keeps the rule opt-in. |
website/src/content/docs/docs/howtos/ARM/arm-rules.md |
Adds the Swagger-linter mapping. |
website/src/content/docs/docs/libraries/azure-resource-manager/reference/linter.md |
Adds the generated rule reference. |
🧠 Review effort: Balanced
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
You can try these changes here
|
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
## Summary - Record verified absolute focused-fixture source paths during queue preparation and reuse them in workers. - Identify the pinned specs common-types source as `specification\common-types`. - Guard optional corpus archive progress directories and use exact process status for inventory progress. - Accept CRLF and LF fences when native tests extract actual authored documentation snippets. - Hash receipt captures after their producing commands complete; exclude an inventory command's own live output. ## Observed evidence The XMSLongRunningOperationProperty queue reused its existing development and specs worktrees. Fixture import readiness passed, but a worker guessed a root-level common-types source. That command failed before validation because the actual source is `specification\common-types`. The same run completed its native suite, 52 focused fixture cases, and a full corpus run. During cleanup-plan inventory, a progress probe enumerated `plan\objects` before the archive directory existed. The probe failed, the worker stopped the plan, and exhausted finite command-correction budgets prevented unattended continuation. The user later explicitly accepted the named request for one additional corrective attempt. The coordinator preserved the original failures and counters, verified the retained state, and authorized that one cleanup correction. Cleanup restored the corpus baseline, and the unchanged rule inputs completed their remaining required publication and review gates. User-wait time remained separate from active execution. This recovery does not grant future unattended retries. During promotion, an LF-only Markdown fence reader found no examples in a CRLF checkout: 20 focused tests passed and two failed. A test-reader-only correction accepted both line endings. The original 22 tests, exact final documentation snippets, and all 496 ARM package tests then passed. An evidence inventory also hashed its own live stdout capture before its final output was written. A quiescent audit found exactly one mismatch among 27 receipts. Reprocessing the same completed receipt set restored zero mismatches without changing any of the ten frozen promotion files or the index. Development draft #5704 and promotion draft #5709 now exist with independently verified clean Copilot reviews. This PR remains separate from both rule changes and preserves all retry, validation, publication, and immutable-source requirements. ## Scope and validation Only five Markdown instruction files under `.github/skills` changed. The existing canonical branch and PR are retained; no second process-improvement PR was created. The base remains `Azure/typespec-azure:feature/lintdiff-migration-new`. Before the final additions, the coordinator fetched the current migration base and inspected newer edits in both affected instructions. The added requirements are not already present and do not replace those incoming edits. Focused Prettier write/check and `git diff --check` passed. A formatter attempt with the uninitialized worktree's configuration could not load its config-relative TypeSpec plugin and made no changes. The corrected invocation used the existing built formatter and its source configuration, whose bytes match the process worktree's configuration. No dependency installation, submodule initialization, builds, package tests, generated output, or release metadata were required for this documentation-only update. --------- Copilot-Session: 8e9d80e2-2e85-4bd4-9baa-eb937b5c60f1
Retain literal rule fixtures and package-isolation regressions. Published examples were independently executed and recorded as one-time session evidence; no continuous Markdown coverage is claimed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
lgtm. Some potential test additions for greater test coverage that can be done at a later time in a follow up PR:
A couple of smaller addition would strengthen the edge coverage:
- The most useful missing regression is the intentional difference from Swagger: an operation with plain polling headers and
@extension("x-ms-long-running-operation", true)should still warn. The implementation currently ignores that override, but no test locks down this explicitly advertised behavior. - A qualifying header later in a header map, after an unrelated header, to guard against accidentally stopping at the first nonmatching header.
There was a problem hiding this comment.
Before merging need to check if this rule is the same name/similar logic as: #5652
|
Following up on your coverage suggestions: thanks! Both regressions are now in the canonical rule suite in #5652: an output-only LRO extension does not satisfy native polling metadata, and a qualifying polling header is recognized even after an unrelated header. Included in the consolidation commit. |
|
Thanks for flagging the overlap with #5652. I consolidated both migrations into #5652 under the existing |
Superseded by the combined proposal in #5652
The official-destination policy and unique regression coverage from this PR at
c5e07710are now incorporated into #5652 in 3ca178be4.The combined PR is titled [Swagger Linter Migration] LroExtension + XMSLongRunningOperationProperty -> lro-missing-polling-metadata. Please continue review of both policies there rather than introducing a second public rule with the same name.
#5652 preserves the union: explicit
202for PATCH/marked provider-or-collection POST, or qualifying Location/Azure-AsyncOperation headers on PUT/PATCH/POST/DELETE200/201/202/204responses. It performs one metadata lookup and emits at most one ARM warning per eligible operation, including operations matching both triggers. The combined warning and approved suppression target the authored operation, replacing this PR's proposed header-property target.The immutable source remains #5704 at
2f7e1d5c. No source repair, branch deletion or wholesale branch merge was performed. The combined rule retains one disabled central resource-manager entry; ARM libraryallincludes the registered rule.Fresh combined local validation passed 543 tests across 73 ARM/rulesets files, affected builds, repository format/lint and one-time published-snippet compilation. These results do not claim new GitHub CI or maintainer approval.
This PR remains open but superseded, preserving its branch and review history. No review thread was resolved. Acceptance and merging of the combined proposal are still required; supersession does not mark either migration Done.
Historical #5709 promotion notes before consolidation (superseded where the combined contract above differs)
Summary
Add the opt-in ARM rule
lro-missing-polling-metadata. A polling URL alone does not establish a polling contract: ARM operations with qualifyingLocationorAzure-AsyncOperationresponse headers need native polling metadata so generated clients can recognize asynchronous behavior.This promotes the reviewed development outcome in #5704. The resource manager ruleset registers the new rule as
false, so this PR does not enable new diagnostics for existing specs.Original Swagger linter
The original check, associated with
RPC-Async-V1-15, performs these checks:x-ms-long-running-operationvalue is exactlytrue.200,201,202, and204.LocationorAzure-AsyncOperationresponse header.How the Swagger linter works
For each selected operation object, the function checks the operation-level extension and traverses the listed response objects and their header maps. A finding points to the qualifying header's JSON path, not the operation as a whole. The legacy ARM check is an error; the reviewed native source uses a warning, which this promotion preserves.
The native implementation must not reproduce extension-only compliance. An output-only
x-ms-long-running-operation: trueoverride can satisfy the Swagger check without supplying supported TypeSpec polling metadata. That is an intentional parity difference, not a reason to read emitted OpenAPI or infer emitter behavior in production.Source TypeSpec lintdiff rule
XMSLongRunningOperationProperty.xms-long-running-operation-property.xms-long-running-operation-property.Azure/typespec-azure.feature/lintdiff-xms-long-running-operation-property.2f7e1d5c3d04230666f7524235bd25eff364eaa8.C:\dev\worktrees\lintdiff-xms-long-running-operation-property.The source was assumed done for this promotion and its development GitHub review terminated clean on the exact SHA above. Its index and working tree were clean. No source rule, fixture, snapshot, package manifest, or migration document was modified during promotion.
Destination analysis
The agent-selected destination is
@azure-tools/typespec-azure-resource-manager. The catalog applicability is ARM, the policy comes from ARM RPC guidance, and the selected polling headers are the ARM header set.Azure Core is a plausible alternative for a general LRO rule, but its
long-running-polling-operation-requiredcheck concernsOperation-Locationand a linked polling operation. It does not cover this ARM response-header predicate. ARM's existinglro-location-headerchecks the other direction: a 202 response must include a Location header. It does not require metadata when a header exists.The implementation uses the existing ARM-to-Azure-Core dependency direction. It adds no TCGC, emitter, or OpenAPI dependency.
How the promoted TypeSpec linter works
The public rule name is
lro-missing-polling-metadata.listServicesandgetHttpServiceexpose the program's HTTP operations.200,201,202,204.LocationorAzure-AsyncOperationheader property, ignoring header-name casing.getLroMetadatadetermines whether the operation has supported native polling semantics.The diagnostic unit is the operation. A visited-operation set prevents duplicate findings through overlapping services. Different operations sharing the same header declaration can each produce a finding there. The rule uses the current program's native metadata; it does not introduce version projection or claim all-version Swagger parity.
The only behavioral audience adaptation removes the source's documented provider-namespace guard. That guard isolates ARM from data-plane services in lintdiff's mixed runner; it is not a polling requirement. Explicitly selecting this official ARM rule supplies its intended audience. The new no-provider-metadata regression proves this adaptation. Neighboring ARM rules use the same direct native HTTP approach.
Other adaptations are destination metadata, the concise official name/export, linter registration, native docs/tests, and the disabled ruleset entry. The qualifying predicate, status/header ordering, diagnostic target/unit, warning message/severity, and visited-operation deduplication match the pinned source. No source defect was found.
Standard ARM examples and final snippet proof
These are the exact final authored rule examples, compiled by native tests in a configured ARM service with the package's existing tester setup.
Incorrect: plain polling URL on a synchronous provider action
The enabled rule reports exactly one warning on
Response.location.Correct: preserve semantic polling headers from the asynchronous template
The enabled rule reports no warning. Tests read both examples directly from the final authored Markdown and check the incorrect diagnostic code, message, count, and exact property position. Both use supported standard ARM templates; no handwritten-route fallback or template limitation is needed.
Fixture-to-native test mapping
The links below resolve to original source
main.tspfiles on the recorded canonical source branch. Native case strings are exact test titles, not snapshot equivalence claims. The immutable source for all mappings remains2f7e1d5c3d04230666f7524235bd25eff364eaa8.it("reports a synchronous resource action with a Location header")it("reports a synchronous resource action with an Azure-AsyncOperation header")it("accepts a synchronous ARM action without polling headers")it("accepts standard asynchronous resource operations")it("rejects an async template whose semantic headers were replaced with plain headers")it("accepts the corrected documentation example")it("reports qualifying headers without provider metadata")it("reports each operation sharing a header declaration")it("reports overlapping services only once per operation")it("reports only the first qualifying header in success-code order")it("reports the incorrect documentation example")The source's nested-provider traversal/isolation cases are not copied mechanically: ordinary HTTP traversal is framework-owned after the isolation guard is removed, and mixed ARM/data-plane filtering does not belong in this explicitly selected ARM rule. The native no-provider regression covers the intentional adaptation instead. No validator snapshots, emitted OpenAPI, or corpus artifacts are copied.
The native parameterized matrix also covers all four qualifying verbs/statuses, casing, excluded methods/statuses/headers, and semantic header customizations in both directions.
Migration evidence
See the immutable migration evidence and its raw document for the declared focused comparisons, real-service findings, full corpus populations, selected-version attribution, all compile exclusions, and intentional native/Swagger differences.
That evidence belongs to the reviewed source, not a fresh promotion corpus run. Matching observed project counts do not prove universal equivalence. In particular, a true output-only Swagger extension is deliberately not accepted as native polling metadata.
Validation
All required targeted checks passed on the exact reviewed promotion inputs:
Per-test timeout and hook defaults were not changed. The first focused attempt exposed a CRLF-only documentation-reader mismatch; the test-only portable-reader correction passed the original22 scope, final-doc22, and full496. A later evidence catalog self-capture hash was reconciled after producer quiescence; all27 raw receipt hashes and all10 frozen file hashes were independently reverified. No required failure remains unresolved.
Validation limitations
Validation and independent review occurred on 2026-10-14, bound to prepared promotion base
e0140fa5ad88b34dddd69b4042040f12639432f6, core62f1d298cac7ee3360ec0f6ba84f2bf1e299dba0, and the exact approved inputs.Canonical main was fetched at
d5ea3d93c264b5bed837d670b5a792f859a5217cbut was not integrated. The only task-file intersection adds an unrelated Coreno-fixed-enum-discriminatormatrix row, separate from the new ARM row. The reviewer also checked the incoming HTTP membership-scan-to-Set change and found equivalent behavior, with no relevant API/predicate change or additional required gate. This is not a claim of validation against an integrated current-main/newer-core tree.No supplemental monorepo wrapper or website build was warranted for this isolated rule scope. CI's dedicated Website job remains authoritative for the Astro build. Existing diagnostic-documentation warnings from regen-docs are retained in the validation receipts; the new rule page and references were generated successfully.
Promotion sync policy
The reviewed source SHA remains immutable during promotion. A confirmed source-semantic gap blocks promotion and returns to the queue's bounded authorized source-repair flow. Only a newly clean source review can authorize refreshing this promotion's provenance and native copy. Promotion-only adaptation fixes must not hide a source-semantic change.
Review follow-up: documentation-test scope (2026-10-16)
Removed the bespoke Markdown-parsing test in cf9785b, without moving or replacing the parser. All 22 retained literal tests pass, preserving the rule-owned positive/negative and exact authored-target controls. The dependency-closure build and repository format/lint passed.
The actual published incorrect/correct snippets were separately compiled once, with exactly one expected warning versus zero diagnostics and hash/target receipts. Literal tests do not continuously validate Markdown. This supersedes historical description claims about direct Markdown coverage; a standard documentation-testing system is outside this promotion.