Repository navigation
feat(vale): Vale 3.22.0 — reject BasedOnStyles in rule configs, migrate installed rules, pin the contract - #372
Merged
Conversation
The pin bump in #368 left VALE_VERSION at 3.21.0, which is what engine-version-consistency fails on. The vocabulary re-derived against the 3.22.0 binary changes only in its version stamp: no operand, prefix or divergence moved. The v3.21.0...v3.22.0 tree adds no internal/lint/<format>.go, so no tier row moves either; the docblock on the tier table records the check and points at what did change.
…ed rules
Vale 3.22.0 gives an empty BasedOnStyles a meaning (upstream c2d62437):
it clears every setting a file inherited from an earlier matcher. The
assembled run config is every rule's matchers in id order, and the
recipe wrote BasedOnStyles = into every one of them, so on 3.22.0 a rule
under [docs/**] silences every alphabetically earlier rule under docs/,
and [*.md] beside another rule's [*.{md,markdown}] silences the first on
every .md file. Measured on both binaries against the exact layout
assembleValeConfig writes; only byte-identical globs, which Vale merges,
escape, which is why this repository's own five rules did not notice.
The schema now refuses the key with any value under
vale-config-no-based-on-styles (renamed from -based-on-styles-empty,
never released), and migration 0008 deletes the line from every
installed .taskless/rules/vale/*/.vale.ini, touching no other byte.
check and verify already refuse a scaffold behind the current version
and name init, which applies it. This repository's own .taskless/ is
migrated here by pnpm cli init.
The three isolating configs stop writing the line too. Their docblocks
claimed it kept Vale.Spelling from firing on a fixture; measured on both
binaries with a baited document, nothing fires without the key and the
control naming Vale fires all of it. No bundled style loads unless a
run-level BasedOnStyles names one.
A Vale 3.22.0 block in the vendor contract, every case run against 3.21.0 as well with that answer in the comment: the BasedOnStyles table (identical globs survive, any other overlap silences the earlier rule, id order decides, a NO matcher carrying the key reaches every rule), UNSET as a rule value and at the style level, that no bundled style loads without the key, negated inline scopes blanking the element's text with positions held, the release note's dotted spellings being inert, [formats] by file name and glob against a fenced-block discriminator, front-matter placement reporting every occurrence in a field, a rule file's message and description being its only prose, a one-line MDX element, and split: true. Corpus rows for ~link and ~strong & ~emphasis (accepted; the control proves the paragraph is still reached) and for text.raw and paragraph.link (ignored, as the dotted forms the release note uses). The timeout fixtures re-timed on 3.22.0 land within noise of 3.21.0.
create-vale-rule (topic v11): the config template is three lines, a paragraph says why BasedOnStyles is rejected with any value, and a paragraph documents inline-element negation and warns off the release note's text.raw and paragraph.link spellings. update (topic v9): the 0.11.3 entry gains the migration, the negation change, and the additions a rule can use. The changeset grows in place, still patch. The OpenSpec change restates the two modified requirements in full and adds the migration-8 requirement; archived on this PR.
Dry-run counted first: cli-vale-rule-engine 33 to 37 scenarios, cli-rule-validation 31 to 32, cli-taskless-bootstrap 29 to 33 and 9 to 10 requirements, nothing dropped.
Member
Author
|
@claude /review |
|
Claude finished @theCodeDrift's task in 3m 31s —— View job Review completeReview mode: incremental — read 1 prior review thread(s) before reviewing. The
AssessmentI found nothing NEW to flag as a correctness, security, or clarity problem. This is a well-scoped, carefully measured change and it holds together:
Nothing here needed an inline comment — I didn't find a defect to anchor one to. |
theCodeDrift
added this pull request to stack #373
September 21, 2026 23:09
theCodeDrift
removed this pull request from stack #373
September 21, 2026 23:33
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):
#368 moves the six
@taskless/vale-*pins to Vale 3.22.0. That commit alone does not land green (VALE_VERSIONstill says 3.21.0), and it would ship something worse than a red test: on 3.22.0 theBasedOnStyles =line every rule's.vale.inicarries, because the recipe told every author to write it, silences other rules. This PR is what makes the upgrade correct, measured against both binaries side by side, and it merges down intovendor/vale/upgradeso pin, schema rejection and migration reachmaintogether.What
BasedOnStylesin a rule's config with any value, undervale-config-no-based-on-styles(renamed fromvale-config-based-on-styles-empty, which accepted the empty form and was never in a release). The message for the empty form says what 3.22.0 does with it and to delete the line..taskless/rules/vale/<id>/.vale.iniand touches no other byte (a line edit anchored on the key, so a comment naming it survives; idempotent; a file without the line is not written). This repository's own five rules are migrated here bypnpm cli init.buildIsolatingConfig, the generator'sprobe(),runOnein the schema contract test) stop writing the line. Their docblocks said it keptVale.Spellingfrom firing on a fixture; measured, it never did (see the table).example/config and the recipe template drop the line.VALE_VERSION→ 3.22.0; the vocabulary re-derived against 3.22.0 changes only in its stamp; the tier table's docblock records the source check (nointernal/lint/<format>.goadded, so no tier moved).Vale 3.22.0block invale-vendor-contract.test.ts, onedescribeper release-note item, measured on the exact layoutassembleValeConfigwrites.Measured
Both binaries, invoked directly. The C1 rows use two rules
a-rule/b-ruleon the assembled layout (StylesPath = rules/vale, breadcrumbs, id order), a fixture reading "Just alpha and bravo here." atdoc.md,docs/inner.md,doc.markdown.[*.md], b[*.md], bothBasedOnStyles =[*.md], b[*.{md,markdown}], bothBasedOnStyles =.md.md[*.md], b[**/*.md], bothBasedOnStyles =[*.md], b[docs/**], bothBasedOnStyles =docs/inner.md: a+bdocs/inner.md: b only[docs/**]first, b[*.md], bothBasedOnStyles =docs/inner.md: a+bdocs/inner.md: b only (the later section wins, so id order decides who survives)[*.md], b[docs/**], neither writes the key[*.md]YES, then[docs/**]with onlyBasedOnStyles =[*.md], then a[docs/**]NO carryingBasedOnStyles =[docs/**]a-rule.a-rule = UNSET[docs/**]a-rule = UNSET(style level)BasedOnStylesanywhere, document baited forVale.Spelling/Repetition/TermsBasedOnStyles = Valecontrol fires all of themscope: ~linkover prose with a link~strong & ~emphasis~codetext.raw,paragraph.link(release-note spellings)[formats]NOTES = md/*.special = md, fixture with a fenced blockfrontmatterrule, token twice in one field.ymlas a lint target, bait in every field<Note>bogus</Note>split: truespelling ongetHTTPResponsze_v2andrecieveDatarecieveDatawhole; the identifier missedResponszeandrecieve, each at its own spanThis repository's own five rules use byte-identical globs across rules, so 3.21.0 and 3.22.0 agreed on its assembled config. That is a coincidence, not a defence.
Migration
0008-drop-based-on-styles.ts,LATEST_SCHEMA_VERSION7 → 8. Which commands run migrations:init,demo,onboard, the bare-invocation wizard, and rule delivery (writeRule/ingest paths inrules/files.ts) callensureTasklessDirectoryand migrate.checkandverifycallrequireCurrentSchemaand refuse a scaffold behind the CLI withSCAFFOLD_MIGRATION_REQUIRED, naminginit. So an upgraded project's firstchecksays "run init",initdeletes the lines, andcheckruns; a project already at 8 is untouched. The 0007 test pinnedmanifest.versionto 7 after a runner pass and broke the day 8 existed; both it and the new 0008 test assertLATEST_SCHEMA_VERSIONnow.Ledger
update.mdgets a 3.22.0 addition to the existing "Migrating to 0.11.3" entry (topic v9), because two installed behaviours change:BasedOnStyles =is deleted byinitand rejected byverifyafterwards, and a rule whose scope negateslink/strong/emphasis/codeno longer sees that element's text. The additions ([formats], front matter, rule-file linting, MDX,split,UNSET) are listed with what they touch.create-vale-rule.md(topic v11) drops the line from its template, explains the rejection, and documents inline-element negation..changeset/vale-3-22-0.mdgrown in place, stillpatch.OpenSpec
vale-3-22-basedonstyles, single PR, archived here. Dry-run counted:cli-vale-rule-engine33 → 37 scenarios,cli-rule-validation31 → 32,cli-taskless-bootstrap29 → 33 (9 → 10 requirements), nothing dropped.Not pinned
split: true.VocabandVale.<Name>.Terms: needs a<StylesPath>/config/vocabularies/tree the rule layout has no home for, the same reason TextFSM Views were not pinned for 3.21.0.lint.go's walk now skips theStylesPathtree unless a path inside it is named.checkalready excludes.taskless/before Vale runs, so nothing this CLI does can observe it.Stacked on #368, merges down into
vendor/vale/upgrade. The bot branch already sits onorigin/main(af9d00b→d04b14f), so no rebase was needed and the bot's tip is an ancestor of this branch.