Skip to content

[Swagger Linter Migration] EvenSegmentedPathForPutOperation -> use-resource-path-for-put - #5550

Merged
Yuchao Yan (msyyc) merged 14 commits into
mainfrom
promote-lintdiff-even-segmented-path-for-put-operation
Oct 20, 2026
Merged

Yuchao Yan (msyyc) merged 14 commits into
mainfrom
promote-lintdiff-even-segmented-path-for-put-operation

Conversation

@msyyc

@msyyc Yuchao Yan (msyyc) commented Sep 23, 2026 •

Copy link
Copy Markdown
Member

Test-responsibility cleanup

Applied the guidance merged in #5572 from the #5507 review. Removed framework-only imported-library, unused-template-interface, and redundant namespace traversal tests. Kept the instantiated-template regression because it exercises the rule's explicit exclusion guard. No production code changed.

Current cleanup validation: mise exec -- pnpm --filter @azure-tools/typespec-azure-resource-manager exec vitest run test\rules\use-resource-path-for-put.test.ts passed 12 tests after removing the standalone compiler-suppression test. Repository pnpm format, pnpm lint, and git diff --check passed. Earlier validation counts and broad-validation limitations below remain historical; the full test suite was not rerun.

Original Swagger linter

linter code: EvenSegmentedPathForPutOperation

linter doc: even-segmented-path-for-put-operation.md

The ARM Spectral rule selects PUT path keys from paths and x-ms-paths:

  • Require a provider namespace followed by one or more resource type/name pairs.
  • Accept parameterized names and the literal singleton name default.
  • Accept nested pairs, scope prefixes, and extension-resource continuations with a matching final provider suffix.
  • Reject provider roots, collection-only paths, and action-like odd suffixes.

It applies its provider/resource suffix regular expression to each selected PUT path and reports the offending path key. It does not simply count all slash-separated segments. The official check retains this suffix contract rather than adding emitter simulation or SDK scope filtering.

Source TypeSpec lintdiff rule

  • Validator ID: EvenSegmentedPathForPutOperation
  • Local name: even-segmented-path-for-put-operation
  • Canonical validator slug: even-segmented-path-for-put-operation
  • Source repository/branch: Azure/typespec-azure:feature/lintdiff-even-segmented-path-for-put-operation
  • Reviewed immutable source commit: aa07850d69ed89b673c06115ebc392f755869858
  • Source PR: [WIP][Swagger Linter Development] EvenSegmentedPathForPutOperation #5528; clean development review completed in two rounds, final review 5264468250.
  • Source worktree: C:\dev\worktrees\lintdiff-even-segmented-path-for-put-operation, clean with no uncommitted rule changes.
  • Original lintdiff source rule

The source was assumed done for this promotion and was not modified. The prior source commit efbc4cdffce0ff1fa5ae02d64fcc3248f0101ee5 remains in history; the reviewed successor only clarifies the migration evidence.

Destination analysis

The agent selected @azure-tools/typespec-azure-resource-manager because this is ARM RPC-Put-V1-02, the predicate requires ARM provider/resource paths, and both the catalog and explicit fixture ruleset identify ARM applicability. Azure Core is not a suitable shared/data-plane home: ordinary data-plane PUT paths do not need ARM provider suffixes. No existing official rule covers this custom-PUT path condition.

Official name: use-resource-path-for-put. The rule is registered in the ARM library and explicitly disabled (false) in the resource-manager ruleset. Availability does not enable new diagnostics for existing service specs. Changes are described by a feature entry for ARM and a separate internal entry for disabled ruleset registration.

How the promoted TypeSpec linter works

The operation visitor uses getHttpOperation and checks only PUTs. It retains the reviewed source's regular expression, warning message, operation diagnostic target, template-instance exclusion, and templated-interface exclusion. There is no emission, generated OpenAPI inspection, version projection, or additional deduplication.

Intentional destination adaptations:

  • Use the existing ARM isTemplatedInterfaceOperation helper instead of duplicating it.
  • Remove the source's provider-namespace isolation check. That check isolates ARM from data-plane programs in lintdiff's mixed runner; the opt-in official ARM rule applies to project PUT declarations without requiring a provider decorator. Minimal path-predicate tests already use operations without provider metadata; namespace-traversal permutations are unnecessary.
  • Filter imported library declarations with the compiler's getLocationContext, separately from template filtering. The synthetic imported-library exclusion test was removed because diagnostic filtering is framework behavior; production logic is unchanged.
  • Add official naming, documentation URL/body, registration, native tests, and change entries.

The package already uses compiler location metadata to distinguish project targets. This rule introduces no ARM→TCGC dependency, emitter/OpenAPI API, private state lookup, or unsafe compiler mutation. It intentionally does not emulate SDK @scope; client-only operations may require a documented suppression.

Fixture-to-native test mapping

Snapshots were not copied. Fixture snippets were reduced to native HTTP authoring, removing unrelated OpenAPI decorators and neighboring-rule expectations.

Original lintdiff fixture Native vitest case Coverage note
provider-root-put it("rejects a provider-root PUT and targets the operation") Provider root violation; exact diagnostic location.
collection-level-put it("rejects a collection-level PUT") Missing resource-name segment.
odd-segment-put it("rejects an odd suffix after a resource instance") Action-like suffix after a resource instance.
compliant it("accepts standard ARM create-or-update templates") Standard resource operation template remains compliant.
singleton-default-put it("accepts a singleton default resource") Literal singleton-name allowance.
nested-resource-put it("accepts nested resource type and name pairs") Repeated nested type/name pairs.
scope-placeholder-put it("accepts a scope-prefixed resource path") Scope prefix before the constrained provider suffix.
N/A (promotion adaptation) it("rejects a provider-root PUT and targets the operation") The minimal violation already proves applicability without a provider decorator; no separate namespace-traversal test.
N/A (branch coverage) it("ignores non-PUT operations") GET and POST excluded.
N/A (framework-only coverage removed) Not ported (framework-only) Uninstantiated-template traversal belongs to the framework.
N/A (template coverage) it("ignores operation template instances while checking project declarations") Template instance plus violating project operation.
N/A (framework-only coverage removed) Not ported (framework-only) Imported-library diagnostic filtering is not the path predicate.

Migration evidence

The source migration investigation records focused fixtures, the full pinned real-service corpus, aligned project populations, one-sided project explanations, compile-failure exclusions, and remaining limitations. It also distinguishes the authored reserved URI expansion from the normalized HTTP path. Promotion relies on that evidence rather than rerunning the lintdiff harness.

Native validation

  • Destination dependency-closure build and ARM package build passed.
  • Focused native rule tests: 12 passed.
  • Full ARM package tests: 486 passed across 67 files.
  • Rulesets build and five registration tests passed.
  • ARM package lint passed.
  • ARM docs regenerated; explicit Prettier checks included the package README, authored rule, generated rule page and linter index with ignored-file override, and the manually maintained ARM rule matrix.
  • Chronus status passed with LF change files.
  • Independent local code review found no significant issues.

Validation blocker

The repository-wide best-effort TYPESPEC_SKIP_WEBSITE_BUILD=true pnpm validate:pr --verbose did not pass. Its build passed (64 tasks), but repository-wide tests completed with 10 timeout failures, 3458 passing tests, and four skips. Two Autorest failures were hook timeouts; the remaining test timeouts were in Azure Core, TCGC, and playground sample validation. These were outside the required ARM/ruleset test suites, which passed independently. This run does not establish whether the broad timeouts reproduce on baseline.

The wrapper subsequently passed repository lint and reached pnpm format:check before the original ten-minute overall deadline (2026-09-21 16:46:37–16:56:37 +08:00). Its process tree was stopped at that deadline and quiescence verified. Child output was buffered by spawnSync; no stall was inferred from wrapper silence and no natural wrapper exit code is claimed.

The user subsequently authorized exactly one full-suite retry with mise exec -- pnpm test --maxWorkers=1, preserving the same test population and checked-in timeouts. That retry completed naturally with exit code 1 after 1178.59 seconds: 347 files, 3472 tests, 3466 passed, two failed, four skipped. Both remaining failures are in packages/typespec-autorest/test/options.test.ts:16, in the beforeEach hook awaiting Tester.createInstance: 'new-line' option > emit LF line endings by default and 'new-line' option > emit CRLF when configured. Each hook timed out at the unchanged 10000 ms limit.

The root cause is not established; neither baseline reproduction nor an environmental cause is claimed. The original failures and failed one-worker retry remain unresolved broad-validation limitations. No timeout increase, test omission, further full-suite retry, or automatic timeout diagnosis was used. The supplemental retry allowance is exhausted (1/1).

This draft proceeds under the promotion workflow's original optional, best-effort broad-validation policy and the publication-only continuation authorization, not a waiver of a required native check. The required destination and rulesets checks listed above passed on the exact unchanged ten-file promotion content. The optional wrapper's remaining format/spelling/docs/change/diff stages were not completed by that wrapper; affected-file formatting, ARM docs regeneration, Chronus status and diff hygiene were checked separately. Full-repository validation is not claimed to pass. CI's dedicated Website job remains authoritative for the Astro build, which was intentionally skipped locally.

Promotion sync policy

The reviewed lintdiff source remains immutable during promotion. A confirmed source-semantic defect blocks this PR and returns to the owning queue's bounded source-repair cycle. Refresh this same promotion PR only after the repaired source passes a fresh development review. Adaptation-only fixes belong here; source semantics must not silently diverge in the official copy.

Review follow-up (2026-10-16)

Removed the compiler-owned suppression test entirely, without moving it. Rule predicate, authored-target, and concrete-template coverage remain. Current focused rule suite: 12 passed. Repository format/lint and diff check passed. Earlier full-suite failures/retry limits above remain historical limitations; no broad suite was rerun.

Promote EvenSegmentedPathForPutOperation from reviewed lintdiff source aa07850; register disabled by default.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c993dd39-3ca7-4108-b10d-4b6f418f163e
@microsoft-github-policy-service microsoft-github-policy-service Bot added int:azure-specs Run integration tests against azure-rest-api-specs lib:azure-resource-manager Issues for @azure-tools/typespec-azure-core library meta:website TypeSpec.io updates linter Issues related to linter rules labels Sep 23, 2026
@msyyc
Yuchao Yan (msyyc) requested a lite review from Copilot September 23, 2026 05:00
@github-actions

github-actions Bot commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

All changed packages have been documented.

  • ✅ @azure-tools/typespec-azure-resource-manager
  • ✅ @azure-tools/typespec-azure-rulesets
Show changes

@azure-tools/typespec-azure-resource-manager - feature ✏️

Add the use-resource-path-for-put lint rule to check that ARM PUT paths end in resource type/name pairs.

@azure-tools/typespec-azure-rulesets - internal ✏️

Register the ARM use-resource-path-for-put lint rule as disabled in the resource manager ruleset.

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.

Copilot review overview

🔵 Needs a closer look

Extension-resource continuation coverage and explicit suppression-directive documentation remain unresolved.

Review effort: Lite
Findings: None

What changed in this PR

Migrates EvenSegmentedPathForPutOperation to the ARM TypeSpec linter as the opt-in use-even-segmented-put-path rule.

Changes:

  • Adds the rule implementation and native tests.
  • Updates documentation, indexes, and ARM guidance.
  • Registers the rule as disabled by default and adds changesets.
File Summary
website/​src/​content/​docs/​docs/​libraries/​azure-resource-manager/​reference/​linter.md Updates the linter reference.
website/​src/​content/​docs/​docs/​howtos/​ARM/​arm-rules.md Adds ARM rule guidance.
packages/​typespec-azure-rulesets/​src/​rulesets/​resource-manager.ts Registers the rule as disabled by default.
packages/​typespec-azure-resource-manager/​test/​rules/​use-even-segmented-put-path.test.ts Adds native rule coverage; extension-resource continuation coverage remains needed.
packages/​typespec-azure-resource-manager/​src/​rules/​use-even-segmented-put-path.ts Implements the ARM PUT-path validation rule.
packages/​typespec-azure-resource-manager/​src/​rules/​use-even-segmented-put-path.md Documents rule behavior and suppression guidance; directive placement needs clarification.
packages/​typespec-azure-resource-manager/​src/​linter.ts Registers the rule with the ARM linter.
packages/​typespec-azure-resource-manager/​README.md Lists the new rule.
.chronus/​changes/​register-use-even-segmented-put-path.md Adds the registration changeset.
.chronus/​changes/​arm-use-even-segmented-put-path.md Adds the feature changeset.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@github-actions

github-actions Bot commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

📦 Package size report

✅ No notable package size changes compared to the base branch.

14 package(s) with no notable change
Package Packed (base → head) Δ Packed Unpacked (base → head) Δ Unpacked
@azure-tools/typespec-azure-resource-manager 186.24 KB → 186.31 KB +76 B (+0.0%) 1.12 MB → 1.12 MB +640 B (+0.1%)
@azure-tools/typespec-azure-rulesets 5.57 KB → 5.59 KB +17 B (+0.3%) 34.21 KB → 34.41 KB +201 B (+0.6%)
@azure-tools/azure-http-specs 143.52 KB → 143.52 KB — 1.20 MB → 1.20 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-client-generator-core 243.98 KB → 243.98 KB — 1.30 MB → 1.30 MB —
@azure-tools/typespec-go 263.76 KB → 263.76 KB — 1.35 MB → 1.35 MB —
@azure-tools/typespec-java 20.22 MB → 20.22 MB — 22.51 MB → 22.51 MB —
@azure-tools/typespec-metadata 15.91 KB → 15.91 KB — 62.26 KB → 62.26 KB —
@azure-tools/typespec-python 42.54 KB → 42.54 KB — 165.94 KB → 165.94 KB —
@azure-tools/typespec-ts 530.77 KB → 530.77 KB — 2.67 MB → 2.67 MB —

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 Sep 23, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@azure-tools/typespec-azure-resource-manager@5550
npm i https://pkg.pr.new/@azure-tools/typespec-azure-rulesets@5550

commit: 1c92c72

@azure-sdk-automation

Copy link
Copy Markdown
Contributor

You can try these changes here

🛝 Playground 🌐 Website

@msyyc
Yuchao Yan (msyyc) marked this pull request as ready for review September 23, 2026 05:17
Yuchao Yan (msyyc) added a commit that referenced this pull request Sep 23, 2026
## Why

The end-to-end `EvenSegmentedPathForPutOperation` run (#5528
development, #5550 promotion) repeatedly stopped even though the user
supplied no rule-design or implementation guidance. The interventions
were work-reuse authorization, a retry request, one precisely scoped
single-worker retry authorization, and a later end-to-end continuation
request.

This review traced those stops through the prior session, append-only
execution log, preserved validation manifests and current skill
instructions. It does not treat all stops as spurious or infer that
generic access overrides an explicit validation condition.

| Observed evidence | Root cause | Correction |
| --- | --- | --- |
| Initial CLI invocation found clean, pushed task-owned commit
`efbc4cdff`, canonical push permission, and no PR, but stopped for
legacy-worktree adoption. The earlier environment had refused
publication before a creation call because its app publisher lacked the
required base controls. | App-specific ownership adoption leaked into
general preparation rules; an unattempted operation was treated like a
failed publication retry. | Backend-scoped, verified explicit-target
resumption. Preserve ownership, state, history and exact-PR
reconciliation; no separate app adoption for ordinary CLI reuse. |
| Required promotion validation passed: 12 focused tests, 486 ARM tests,
five ruleset tests, builds/lint/docs/format/Chronus and independent
local review. The optional broad wrapper then failed with ten timeouts
and was stopped at its deadline. | Promotion called the broad wrapper
optional/best effort, but also included it in default command blocks and
said to run it before creation. Generic stop rules and inconsistent
`Validation blocker` wording overrode its intended gate level. |
Predeclare required versus supplemental gates, separate the optional
command from required examples, and disclose scoped supplemental
limitations without automatically stopping publication. |
| A user-authorized `--maxWorkers=1` retry took 1178.59 seconds and
still failed: 3466 passed, two Autorest setup-hook timeouts, four skips.
Later publication used exactly the same ten promotion files, not a code
fix or another successful test run. | The agent pursued full-suite
success before deciding whether that suite was necessary. The next user
intervention supplied no technical diagnosis. | Read-only coordinator
reconciliation before terminal stops or requests for renewed permission.
Never infer an environmental cause, silently promote a failed required
gate to optional, or treat a retry allowance as unlimited recovery. |
| The promotion correction budget was consumed by an ESLint probe in an
oxlint checkout, a diagnostic-marker correction, and Chronus LF
normalization. | Preventable command assumptions and Windows line-ending
work mixed with genuine draft correction. | Derive tool probes from the
target checkout. Normalize named Chronus files before validation,
without staging. Keep existing finite correction budgets; the
diagnostic-marker fix remains ordinary local correction. |
| The successful final run reported no qualifying process improvement
despite the earlier authorization-only stops. | Post-run review focused
on the successful final state rather than the transitions requiring
human intervention. | Review each stop, the actual human input, and what
enabled continuation; success does not erase a proven instruction
contradiction. |

The Autorest timeout root cause remains unknown. This PR does not claim
baseline reproduction, fix Autorest, rerun the completed rule task, or
change its PRs.

## Changes

Seven skill documents only:

- Shared recovery contract defines gate/disposition rules, a single
read-only policy-reconciliation handoff, and eight decision cases.
- Queue/preparation/publication contracts consistently distinguish
explicit-target reuse from app-session adoption and retain the current
phase owner/history.
- Promotion keeps its required native checks, removes optional broad
runs from default command blocks, and separates `Validation limitations`
from actual blockers.
- Review/fix gates consume that same classification rather than
reclassifying every nonzero exit as mandatory.
- Post-run review examines the full intervention history.

## Safeguards retained

- Required validation still blocks, including an explicitly
user-required broad check. “Publish only if this passes” cannot be
undone by a later generic “continue” or “give access.”
- Any plausible task regression remains blocking until classified, even
if a supplemental command discovered it. Required checks inside a
supplemental wrapper remain required; contradictory failures cannot be
hidden by earlier passes.
- No timeout increases, changed assertions, skips, new retry budgets,
automatic hook-timeout retries or unrelated fixes.
- No bypass of app-bound publishers, canonical repository policy, folder
containment, clean-head/provenance checks, immutable-source repair, or
independent review.
- Failed/indeterminate publication requests are not resent merely
because an absence query is empty. Historical preflight refusals before
any creation call are distinguished from API failures.
- No replacement worktrees, discarded edits, reset budgets or concurrent
owners.

## Validation

- Full seven-file diff reviewed against freshly fetched
`Azure/typespec-azure:feature/lintdiff-migration-new` at
`e3fcd29b245a5393beb448872f5018ddc8147c84`.
- Scoped Prettier write/check passed for the seven Markdown files.
Initial use of the root config failed before changes because its Astro
plugin was unavailable in the isolated dependency-free worktree. The
successful run reused installed Prettier 3.9.5 with the same root style
options and no non-Markdown plugins; no dependencies or submodules were
installed.
- Six newly added relative Markdown links/anchors resolve.
- `git diff --check` passed.
- The documented Windows normalization snippet was smoke-tested on an
isolated CRLF fixture: exact content retained, LF output, front matter
at byte zero, no BOM, no staging. The fixture was removed.
- Reviewed the eight documented decision cases for safe continuation
versus retained stops. These are policy checks, not a claim that an
end-to-end agent replay was executed.
- No package, corpus or full-suite runs: this is a Markdown-only
workflow correction.

The primary rule worktrees and the coordinator's existing branch are
unchanged.

Copilot-Session: 34113ad0-a66e-4c50-8797-6ab7e830c926
@msyyc

This comment was marked as outdated.

Strengthen template-instance exclusion coverage and document standard ARM create-or-replace authoring alongside custom PUT paths.

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

Copy link
Copy Markdown
Member Author

Addressed both nonblocking findings from the promotion review in commit c5eac47:

  • The template-instance exclusion test now uses the otherwise-invalid /providers/Microsoft.Template path and still expects only the separate project operation's diagnostic.
  • The rule docs now recommend ArmResourceCreateOrReplaceSync<Widget> with a standard ARM resource model, while retaining the incorrect and corrected custom-PUT examples. ARM docs were regenerated; the generated rule page remains ignored as intended.

Validation: all 12 focused tests passed; all three documentation examples compiled with the expected lint results; repository formatting and lint, explicit generated-document formatting checks, Chronus status, and diff checks passed.

The production rule and pinned lintdiff source are unchanged. The existing broad-suite timeout limitations remain unresolved; no full-repository test retry was performed for these test/documentation-only fixes.

Apply the test responsibility guidance from #5572; retain distinct predicate, target, and custom guard regressions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread packages/typespec-azure-resource-manager/src/rules/use-even-segmented-put-path.md Outdated
Comment thread packages/typespec-azure-resource-manager/src/rules/use-even-segmented-put-path.md Outdated
Validate the literal Markdown examples against the opt-in rule and its authored diagnostic target.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@microsoft-github-policy-service microsoft-github-policy-service Bot added the stale Mark a PR that hasn't been recently updated and will be closed. label Oct 13, 2026
@microsoft-github-policy-service

Copy link
Copy Markdown

Hi @Yuchao Yan (@msyyc). Your PR has had no update for 14 days and it is marked as a stale PR. If it is not updated within 14 days, the PR will automatically be closed. If you want to refresh the PR, please remove the stale label.

Comment thread .chronus/changes/arm-use-even-segmented-put-path.md Outdated
@msyyc Yuchao Yan (msyyc) removed the stale Mark a PR that hasn't been recently updated and will be closed. label Oct 14, 2026
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@msyyc Yuchao Yan (msyyc) changed the title [Swagger Linter Migration] EvenSegmentedPathForPutOperation -> use-even-segmented-put-path [Swagger Linter Migration] EvenSegmentedPathForPutOperation -> use-resource-path-for-put Oct 14, 2026
Keep path predicate and authored operation assertions in direct resource-path cases.

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

This comment was marked as off-topic.

Yuchao Yan (msyyc) and others added 2 commits October 16, 2026 10:06
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@msyyc
Yuchao Yan (msyyc) added this pull request to the merge queue Oct 20, 2026
Merged via the queue into main with commit d212c49 Oct 20, 2026
44 checks passed
@msyyc
Yuchao Yan (msyyc) deleted the promote-lintdiff-even-segmented-path-for-put-operation branch October 20, 2026 03:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

int:azure-specs Run integration tests against azure-rest-api-specs lib:azure-resource-manager Issues for @azure-tools/typespec-azure-core library linter Issues related to linter rules meta:website TypeSpec.io updates

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants