Repository navigation
fix(vale): pin Vale 3.23.0's contract, and accept a rule's tests: key - #428
Merged
Merged
Conversation
Three contract failures on #427 had one cause: a standalone `doc(<leaf>)` scope now reads the leaf's text, where 3.21.0 and 3.22.0 matched nothing. The corpus row agrees with the schema now and drops its divergence; the 3.21.0 test keeps only the chained half, which is still true; a new 3.23.0 block pins the standalone form firing. What no test caught, measured against both binaries on the same fixtures: - `.kt` and `.kts` moved from the plaintext fallback to the comment tier (upstream adds internal/lint/code/kt.go; format.go routes both to `code`). Two new rows in VALE_FORMAT_TIERS. `.toml` did not move. - A comment addressed to a tool (`//nolint`, `# noqa`, `eslint-disable`) and a docstring's `:param:` field are no longer read. Pinned in the 3.23.0 block. - `tests:` is a field of every check, accepted by 3.22.0 as well, and was missing from the generator's candidates, so `verify` rejected it as an E201 Vale never raised. Added as a candidate and regenerated; it is common and read literally. create-vale-rule (topic v15) and update (topic v12) say all of it, and the changeset carries the release note.
theCodeDrift
added this pull request to stack #430
September 30, 2026 16:03
theCodeDrift
removed this pull request from stack #430
September 30, 2026 17:16
…rs on the upgrade PR The upgrade workflow left the contract suites to Validate, "a red check on a pull request that already carries upstream's notes". Validate does not run there: a pull_request run triggered by github-actions[bot] waits at action_required until a maintainer approves it. Every bot-opened upgrade, Vale and ast-grep alike, measured the same way, and #427 read as a pull request with no checks while three contract tests failed. The job now runs vale-schema-contract and vale-vendor-contract itself, continue-on-error so a changed verdict still proposes the upgrade, and vale-upgrade-report.cjs renders the verdict into the body. The same report lists the files upstream added under internal/lint/. That is the source check capabilities.ts asked for by hand on every bump, and the one that would have caught kt.go on 3.23.0: an extension with no VALE_FORMAT_TIERS row is never probed, so no test can. Neither half gates. A missing test report or a failed compare fetch is said in the body, so "not checked" never reads as a pass.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stack (root → tip):
#427 moves the six
@taskless/vale-*pins to Vale 3.23.0. Its Validate never ran (every workflow is sitting ataction_required), and run locally it is red: three contract failures. This PR makes the upgrade correct and pins what 3.23.0 changed. It merges down intovendor/vale/upgrade, so pin, contract, and guidance reachmaintogether.Why #427 is red
One cause, three failures. A standalone
scope: doc(<leaf>)(doc(h2)) now reads the leaf's own text, where 3.21.0 and 3.22.0 matched nothing.scope/doc-leaf-standalonein the corpus recorded that as a divergence, and the recipe taughttext & doc(h2)around it. This closes a trap rather than opening one; the test's own comment anticipated it.acceptedand carries no divergence.Vale 3.23.0block pins the standalone form firing.What changed that no test caught
Each case below was run against both binaries on the same fixture and differs between them:
.kt,.kts//nolint(Go),# noqa(Py),eslint-disable(JS):param x:fielddoc(h2)aloneThe capabilities table says a bump re-measures everything, and every existing row held, so the suite was green. The format Vale learned only shows up in the source:
v3.22.0...v3.23.0addsinternal/lint/code/kt.go, andinternal/core/format.goroutes.kt/.ktstocode..ktand.ktsare newcommentrows..tomlalso gained a grammar, but routes todata, which needs a View, so it still reads as plaintext here, and that is recorded in the table note too.tests:was already a Vale fieldverifyrejectedtests:as "an E201 that suppresses every other Vale rule". Measured: 3.22.0 and 3.23.0 both load it with any value and no diagnostic. The key was simply missing from the generator's hand-seededFIELD_CANDIDATES, which that list's own header calls the worse failure. It is added, and the regenerated vocabulary records it as a common field Vale reads literally. There is a corpus row for it.Guidance
create-vale-rule(topic v15): the leaf paragraph no longer calls the standalone form inert, and the comment-tier bullet says tool-directive comments and:param:fields are not read.update(topic v12): the 0.12.0 ledger now says 3.21.0 → 3.23.0 (by way of 3.22.0) and gains three 3.23.0 entries.patch.Checks
pnpm lint,pnpm typecheck, andpnpm test(1905 passed) are green locally on this branch, built.The PR that adds CI checks for this class of drift stacks on top of this one.
Refs #427
Contains #429
Stacks on #428, which stacks on #427. Two checks for the drift #427 slipped through. Neither one gates.
Validate never runs on the upgrade PR
vale-upgrade.ymlleft the contract suites to Validate: "left to Validate, it is a red check on a pull request that already carries upstream's notes." That red check never appears. Apull_requestrun triggered bygithub-actions[bot]waits ataction_requireduntil a maintainer approves it:Every earlier upgrade got its first Validate run when a human pushed. #427 read as a PR with no checks while three contract tests were failing.
Now: the job runs
vale-schema-contractandvale-vendor-contractitself, withcontinue-on-errorso a changed verdict still proposes the upgrade, as the header intends.vale-upgrade-report.cjsthen renders the verdict into the PR body.A format Vale learns can't be caught by a test
VALE_FORMAT_TIERSis re-probed row by row, which catches a format that moved. An extension with no row is never probed, so a format Vale learned only shows up in upstream's source. The table's header asked for that check by hand on every bump. On 3.23.0 nobody did it, andcode/kt.gomoved Kotlin to the comment tier with the suite green (#428 adds the rows).Now: the report lists the files upstream added under
internal/lint/between the pinned tag and the new one, using the compare API. It names readers, not extensions, and says to readinternal/core/format.goand probe each one before adding a row. That matters most for the dangerous case: a reader that shells out to a converter turns a missing row into a crash that takes down the whole Vale run.What #427's body would have said
Rendered from the real compare API and #427's actual test report:
Silence never reads as a pass
A missing test report renders Did not run. A failed fetch renders Could not check with the error. A comparison at the API's 300-file cap is flagged as possibly incomplete. If the report step fails outright, the body says Not measured. Each case is covered in
vale-upgrade-report.test.cjs(11 tests).Not in this PR
ast-grep-upgrade.ymlhas the sameaction_requiredexposure, as the table above shows. The contract half of this would port directly; the format-reader half is Vale-specific.pnpm lintandpnpm test:scripts(500 passed) are green locally. The workflow parses, and the new step order is contract, then report, then propose.Refs #427