Repository navigation
feat(zod): report root exports that moved to zod/v3, uuid() becomes guid() (UPT-86) - #200
Merged
lucasbraum merged 2 commits intoOct 17, 2026
Conversation
…uid() (UPT-86) Breaking recall 54% -> 65% (44 -> 55 of 82 -> 85 sites), 0 breaking FP. The recorded 66 / 0 / 37 did not reproduce; CI and a clean local run measure 44 / 0 / 38 on main (see the PR for why). - removed-exports: names zod 3 exported from its root that zod 4 exports only from zod/v3 (SafeParseReturnType, ZodTypeDef, ZodEffects, ...). The surface diff counts them as unchanged because the entry point overlaps. All 15 sites land on ground-truth lines. - string-format: uuid() rewrites to z.guid(), not z.uuid(), which also checks the RFC version and variant (the calmcp case). Ground truth and thresholds unchanged. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Lucas Braum <lucasbraum@gmail.com>
…usion (UPT-86) zod's override now also runs every detect rule over the visited files, so the error-members fixtures are reported through runtimeFindings like any pack's. runtime-findings.test.ts no longer excludes zod. Ground truth unchanged: 55 / 0 / 30 breaking. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Signed-off-by: Lucas Braum <lucasbraum@gmail.com>
lucasbraum
force-pushed
the
lucasbraum/upt-86-zod-pack-reconcile-verificationjson-66-vs-44-tp-and-raise
branch
from
October 17, 2026 18:16
34a4d28 to
e49dbcd
Compare
lucasbraum
deleted the
lucasbraum/upt-86-zod-pack-reconcile-verificationjson-66-vs-44-tp-and-raise
branch
October 17, 2026 18:40
Merged
lucasbraum
added a commit
that referenced
this pull request
Oct 17, 2026
…209) 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](https://claude.com/claude-code) Signed-off-by: Lucas Braum <lucasbraum@gmail.com> Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
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>
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.
UPT-86. Breaking recall 54% → 65% (44 → 55 TP, 38 → 30 FN), 0 breaking FP. Ground truth and thresholds unchanged.
Part 1: 66 vs 44
44 / 0 / 38 is the number. A clean local run (
packs:fetch,pack test zod) and CI'spack zodjob on main (4c3dc23, run 39009240360) agree exactly. The recorded 66 / 0 / 37 does not reproduce, not even at its own commit:9039e3c(#156) scores 38 / 0 / 37 here.What I could establish: breaking TP counts only sites
checkreports atbreaking. For vzdc-artcc/website, 0 of its breaking sites are TP: its findings come backunverifiedwith "57 of 95 files cannot resolve their imports; compile signal skipped". The files import@/generated/prisma/*, whichprisma generatewrites in a postinstall, and ground-truth installs run scripts off.tscon the cached checkout confirms 234 TS2307 on those paths. #156 predicted this ("probably caused by the Prisma client"). I did not runprisma generate, so I could not show that a generated client yields 66; I believe that is the difference, but it is not demonstrated. Theunverifiedfindings cost recall, not precision.verification.jsonis regenerated from the run (--write);docs:packsupdated README and compatibility. The README's 64% → 65% looks like a one-point gain; against what CI measures, the gain is 54% → 65%.Part 2: recall
Reach first: of the 38 misses, 33 are in files that import zod directly (the scan reads them); 5 are not (
import("zod").Xonly,LessonForm.tsxreadingerror.errorswith no zod import). The misses are rule gaps, not unread files.zod/v3(SafeParseReturnType,ZodTypeDef,ZodEffects)types)exportedFromoverlaps on./v3.refine(fn, { message })→errorpost-runs,resume-run; bandserver,sse,stdio)import("zod").ZodTypeAnyandZodRawShape/_def/ZodOptionalname checks_defreadserrorMap/ctx.defaultErrortypesthere, so counted as a wrong rule)uuid()→guid()(the calmcp case):string-formatwrotez.uuid(), which in zod 4 also checks the RFC version and variant; zod 3 accepted any 8-4-4-4-12 hex id. It now writesz.guid(). Decision for you: the public upgrades in the truth mostly usez.uuid(); I chose behaviour preservation. Fixture and guide updated; line-level scores unchanged.Checks:
biomeandtscclean; pack unit tests pass exceptscaffold.test.tsandpack-test.test.ts"each companion", which fail on a clean main here too.🤖 Generated with Claude Code