Skip to content

feat(zod): refine messages, deprecated type names, errorMap (UPT-92) - #209

Merged
lucasbraum merged 1 commit into
mainfrom
lucasbraum/upt-92-zod-pack-remaining-misses
Oct 17, 2026
Merged

lucasbraum merged 1 commit into
mainfrom
lucasbraum/upt-92-zod-pack-remaining-misses

Conversation

@lucasbraum

Copy link
Copy Markdown
Collaborator

UPT-92, follow-up to #200. Three source rules, all deprecated severity, with fixtures (incl. keep cases): refine-message (.refine(fn, { message })), deprecated-names (ZodTypeAny, ZodIssue, ZodSchema, ZodErrorMap, … also import('zod').X), error-map (errorMap option, ctx.defaultError). removed-exports.ts is generalised so the new rules reuse its walker.

Same pinned ground truth, no truth or threshold changes. Baseline is the CI pack-test-zod artifact of run 39057357503 (the pre-squash code of #200; packs/zod is unchanged on main since). After is a local pack test zod --write on the warm cache.

before after
breaking FN 30 17
breaking TP / FP 55 / 0 55 / 0
breaking recall 65% 76%
gate verified verified

Breaking TP stays 55 because the scorer counts a deprecated-severity hit on a breaking site as a removed miss, not a TP, so the recall gain is partly that.

Unverified FP change: +28 deprecated false positives (refine-message 13, deprecated-names 15, error-map 2 minus 1 matched). They are real deprecated uses the truth does not list, not wrong hits.

Dropped: a typename-literals rule (name === "ZodArray") found 3 truth sites but also a breaking FP at PATH wire-step-plugins.ts:90 (a comparison the upgrade left alone), so it was removed, not relabelled. error-map is deprecated for the same reason: AwesomeIntune tool-submission.ts:100 is a real site the truth anchors one line earlier.

Compiler-only group (10): not attributable from syntax; reasons and the other leftovers are in packages/core/src/packs/zod/RESEARCH.md. prompt/index.ts:41 (single-arg z.record) was not investigated.

verification.json, README and docs/compatibility.md regenerated. Not run: full CI.

🤖 Generated with Claude Code

… (UPT-92)

Three source rules for zod 3 code that zod 4 deprecates: .refine(fn, { message }),
ZodTypeAny and the other deprecated root aliases, and errorMap / ctx.defaultError.
Breaking recall 65% -> 76% on the pinned ground truth, 0 breaking false positives.
The compiler-only misses and the dropped typeName rule are in zod/RESEARCH.md.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Lucas Braum <lucasbraum@gmail.com>
@lucasbraum
lucasbraum merged commit 48df030 into main Oct 17, 2026
28 checks passed
@lucasbraum
lucasbraum deleted the lucasbraum/upt-92-zod-pack-remaining-misses branch October 17, 2026 20:25
@uptide-release uptide-release Bot mentioned this pull request Oct 17, 2026
lucasbraum pushed a commit that referenced this pull request Oct 17, 2026
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and publish to npm
yourself or [setup this action to publish
automatically](https://github.com/changesets/action#with-publishing). If
you're not ready to do a release yet, that's fine, whenever you add more
changesets to main, this PR will be updated.


# Releases
## uptide@0.15.0

### Minor Changes

- [#203](#203)
[`19dd649`](19dd649)
Thanks [@lucasbraum](https://github.com/lucasbraum)! - `fix` estimates
what the agent's sites will cost and prints the estimate before its
first call. When the estimate is above the limit (`--max-cost`, default
$1), it stops before spending anything and exits 2: `estimated $3.00 for
50 sites; limit $1.00. Run again with --max-cost 3.00`. Action and App
runs never stop on the estimate: they work within `maxCost`, and the
summary and the pull request name the sites left and the `maxCost` in
`uptide.yml` that finishes them. When the agent stops at the limit, the
summary and the pull request name the estimate and the limit that
continues. The summary (`Phases`), the pull request's run details and
`report.json` (`phases`) give wall time and agent spend per phase.

- [#207](#207)
[`4a90e9f`](4a90e9f)
Thanks [@lucasbraum](https://github.com/lucasbraum)! - `fix` names the
first major of a peer blocker that accepts the target (`no 1.x accepts
react 19; 2.2.0 does`) and suggests adding it to the command instead of
`--allow-peer`. When a verified pack covers that major, the blocker
moves as a companion and its pack runs in the same fix: its rules, its
detect-based findings and its inventory, each at the companion's own
versions. When no pack covers it, the PR says the major needs its own
migration and the risk is High. `--allow-peer` stays the suggestion only
when no release accepts the target. A group member that the target's own
range already accepts (`@casl/ability` under `@casl/react` 5) is no
longer reported as a conflict.

### Patch Changes

- [#208](#208)
[`5fdb60e`](5fdb60e)
Thanks [@lucasbraum](https://github.com/lucasbraum)! - The express pack
reports the `const { id } = req.params` line as a site when the compiler
reports a `string | string[]` error on one of its names, because that
line is where the guide types the values once.

- [#211](#211)
[`213e1a5`](213e1a5)
Thanks [@lucasbraum](https://github.com/lucasbraum)! - fix runs prisma
generate / graphql-codegen in its verification clone before the baseline
and after the upgrade; check names the missing generator step

- [#204](#204)
[`65b7edb`](65b7edb)
Thanks [@lucasbraum](https://github.com/lucasbraum)! - `check` and `fix`
now measure how many of the files that use the upgraded package the
repository actually type-checks (TypeScript, plus JavaScript under
`checkJs` or `// @ts-check`). When that is under half, the summaries say
`types cover N of M affected files` and no longer present a clean
compile as proof: `fix` passes only when a test run or a build passed,
and says the verdict rests on them.

- [#205](#205)
[`c0332eb`](c0332eb)
Thanks [@lucasbraum](https://github.com/lucasbraum)! - `fix` no longer
fails on npm repositories whose lockfile carries optional platform
packages such as sharp's `@emnapi/*`. npm 11.6 drops them on the first
lock-only install and writes a lockfile its own `npm ci` rejects; `fix`
now runs the lock-only install twice, at the upgrade and at the parent
commit alike, so the lockfile it validates is one `npm ci` accepts.

- [#201](#201)
[`4550da5`](4550da5)
Thanks [@lucasbraum](https://github.com/lucasbraum)! - The react pack
now reports `RefObject<HTMLElement>` annotations that need `| null` at
the declaration, including in files that type a prop with the global
`React.RefObject` and never import react. The compiler reports these
where a ref is passed in, so the declaration to edit was missed.

- [#216](#216)
[`95a3bf5`](95a3bf5)
Thanks [@lucasbraum](https://github.com/lucasbraum)! - setup PRs pin
Action v0.14.3

- [#209](#209)
[`48df030`](48df030)
Thanks [@lucasbraum](https://github.com/lucasbraum)! - The zod pack
reports `.refine(check, { message })`, the type names zod 4 marks
deprecated (`ZodTypeAny`, `ZodIssue`, `ZodSchema`, `ZodErrorMap` and the
others, including `import('zod').ZodTypeAny`) and `errorMap` options
with `ctx.defaultError`, as deprecated findings.

- [#200](#200)
[`4e4cc3e`](4e4cc3e)
Thanks [@lucasbraum](https://github.com/lucasbraum)! - The zod pack
reports names zod 3 exported from its root and zod 4 exports only from
`zod/v3` (`SafeParseReturnType`, `ZodTypeDef`, `ZodEffects`, the
`Zod*Def` interfaces), which the surface diff counted as unchanged, and
`fix` now rewrites `z.string().uuid()` to `z.guid()` instead of
`z.uuid()`, so ids that zod 3 accepted still validate.

Co-authored-by: uptide-release[bot] <338861287+uptide-release[bot]@users.noreply.github.com>
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