Skip to content

test(ast-grep): make the ast-grep 0.51.0 upgrade land green - #548

Merged
theCodeDrift merged 1 commit into
vendor/ast-grep/upgradefrom
vendor/ast-grep/upgrade-tests
Oct 20, 2026
Merged

theCodeDrift merged 1 commit into
vendor/ast-grep/upgradefrom
vendor/ast-grep/upgrade-tests

Conversation

@theCodeDrift

@theCodeDrift theCodeDrift commented Oct 20, 2026 •

Copy link
Copy Markdown
Member

Stack (root → tip):

#545 moves the @ast-grep/cli* pins to 0.51.0. This is what makes that bump correct, plus the deterministic rule migration it turned out to need.

What the pin bump alone left red

Measured, and not caught by any test

20 YAML edge cases were run against both binaries (duplicate keys, anchors, merge keys, tags, null relations, multi-document files, YAML 1.1 booleans, unknown keys, and others). Only error wording changed, except for one:

case 0.45.3 0.51.0
rule file ending in a stray ---, beside a second rule exit 8, neither rule reports exit 1, both rules report

That is a relaxation check users will see, so it is pinned under scan exit codes.

tree-sitter-haskell 0.23.1 → 0.24.1 renamed one kind, type_synomym → type_synonym (upstream fix!: typo). Diffed across both grammars' node-types.json: of 187 named kinds this is the only one that changed, and no field changed. A rule on the old spelling exits 8, which takes every sg rule in check down with it. Pinned both ways in a new Haskell names a type synonym block.

The rest needs nothing: the custom-language opt-in and trust policy (#2960, #2971, #2972) is unreachable because we assemble our own config with no customLanguages; null relation fields are refused identically on both versions, and our schema rejects them first; the vendored rule schema changed only its provenance comment; outline output is not exposed.

Rule migrations, keyed on engine version rather than on the scaffold

The Haskell rename is mechanical, so it is applied rather than handed to an agent. It is not a scaffold migration: 0011 already shipped, so a 0012 would move every project's scaffold to 12 and make every pinned CLI refuse its project with SCAFFOLD_VERSION_MISMATCH, for a typo that affects almost no one.

Instead, update --rules applies rule migrations keyed on rules.engines, the engine versions the rules were last reconciled against, which it records and nothing else does:

  • A migration runs when the recorded engine version is below its engineVersion and the bundled engine is at or above it; a project with no recorded engines gets all of them. Each engine is keyed on its own version.
  • They run before the stamp. A failure part-way leaves the marker where it was, and every migration is idempotent, so a rerun finishes.
  • update --json lists what is pending (ruleMigrations); update --rules names every file it wrote (migrated).
  • update --rules now refuses with SCAFFOLD_MIGRATION_REQUIRED when the layout is behind, so a rewrite never writes into an old layout.

The contract each migration must meet is stated in rule-migrate.ts: idempotent, edit bytes in place rather than parse and re-serialize, and rewrite only shapes the service never issued, or has already migrated in its own corpus. A rewritten issued rule reads as "edited since Taskless issued it", and rule restore writes the old bytes straight back; accepting other bytes client-side would be a signature bypass. The service has issued no rule naming type_synomym, confirmed on the Cloud side.

The Haskell migration touches only rules whose language resolves to Haskell (the hs alias included), rewrites only kind: values (block, flow, quoted, list item), and never reads .tests/. Vale migrations for #546 add one file and one registry line.

Ledger and changeset

update.md gains a Migrating to 0.13.3 section telling agents not to rename by hand, step 5 explains the rewrites, and the error table lists the new refusal. Topic v17 → v18. The changeset is grown in place, still patch.

Typecheck, lint, and the full CLI suite pass: 136 files, 2487 tests.

Stacked on #545. Merges down into vendor/ast-grep/upgrade.

Refs #545

The pin bump alone left two contract pins red. ast-grep 0.50.0 added Zig,
so AST_GREP_LANGUAGES gains it. 0.51.0 replaced serde_yaml with
serde-saphyr, which drops the backticks from the severity error; the pin
records the new wording. No Taskless user reads that text, since validate
rejects the severity against the schema first.

Two measured changes no test caught are now pinned. A rule file ending in
a stray `---` loads on 0.51.0, where 0.45.3 exited 8 and took every sg
rule in the config down with it. And tree-sitter-haskell 0.24.1 renamed
the kind `type_synomym` to `type_synonym`, the only kind or field that
changed across the two grammars' node-types.json; a rule on the old
spelling now exits 8.

That rename is fixed deterministically. `update --rules` now applies rule
migrations keyed on the engine versions the rules were last reconciled
against (`rules.engines`), not on the scaffold version, so a rewrite that
touches a handful of projects never bumps every project's scaffold and
breaks pinned CLIs in CI. Migrations run before the stamp, are idempotent,
edit bytes in place, and must only rewrite shapes the service never
issued; the service has issued no rule on the old Haskell kind.
`update --json` lists pending migrations, and `update --rules` refuses
with SCAFFOLD_MIGRATION_REQUIRED when the layout is behind. The ledger
gains a 0.13.3 entry and the update topic moves to v18.
@theCodeDrift
theCodeDrift merged commit 405297a into vendor/ast-grep/upgrade Oct 20, 2026
8 checks passed
@theCodeDrift
theCodeDrift deleted the vendor/ast-grep/upgrade-tests branch October 20, 2026 23:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant