Skip to content

feat(packs): verified typescript 5 to 6 and express 4 to 5 packs - #160

Merged
lucasbraum merged 3 commits into
mainfrom
lucasbraum/promote-verified-packs
Oct 16, 2026
Merged

lucasbraum merged 3 commits into
mainfrom
lucasbraum/promote-verified-packs

Conversation

@lucasbraum

@lucasbraum lucasbraum commented Oct 15, 2026 •

Copy link
Copy Markdown
Collaborator

What

uptide pack test <pack> --write on main (530f90c, UPT-48's gate), typescript then express, one at a time, each with its own UPTIDE_CACHE_DIR. Both measure verified, so both records now say verified. Ground truth unchanged (same digests). RESEARCH.md for each states the numbers and the unexercised rules; README table regenerated (docs:packs); changeset added.

Pack Repos (≥2) Real breaking sites (≥5) Breaking FP (0) Breaking P / R Behavior-note P / R Unexercised
typescript 5→6 7 1,399 0 100% / 17% 20% / 50% downlevel-iteration, import-assertions, module-keyword
express 4→5 4 86 0 100% / 85% n/a / 0% none
  • typescript recall is 17% because the types: [] errors fold into one changed-defaults finding per tsconfig while the truth lists each error line; its 8 note FPs are those anchors at tsconfig*.json:1. Its three unexercised rewrites run assisted.
  • express: the http-proxy-middleware peer conflict (netlify) and fixture-only rules are kept as stated gaps in RESEARCH.md.

redis: not promoted

pack test redis (no --write) on the same main: measures verified (5 repos, 20 real breaking sites, 0 breaking FP), recorded candidate.

  • Breaking recall 61% (11 of 18 sites).
  • Behavior-note precision 50% (2 TP, 2 FP). The client-defaults FPs are mcp-coordinator and blog, which kept the RESP3 default without pinning it.
  • Unexercised rewrites: keep-alive, quit-disconnect, scan-iterators, unstable-resp3 (only renamed-exports' rewrite has a real site). The core 4→5 API rules (command-options, legacy-mode, number-replies) have no real site.
  • Engine gaps from feat(packs): candidate redis (node-redis) 4 → 5 and 5 → 6 pack (UPT-58) #151:
    1. Compile errors in files that use the client without importing redis are not reported. All 7 breaking misses come from this (blog 5, FCM 2 scan-cursor sites through a local wrapper).
    2. Errors that already exist at the installed version are probably subtracted by location, which hides a new error on the same line (client-type at FCM and tacocat 5→6). In this run those 4 lines do surface, but under another rule: client-defaults at tacocat, generic at FCM. So client-type recall is 33%.

Recommendation: don't promote yet. The gate passes, but the 4→5 half rests on one 4→5 repo, and the main API changes there were never met in real code. Promote once a scorable 4→5 upgrade that exercises command-options or legacy-mode is added (truth committed before scoring), or once gap 1 is fixed.

🤖 Generated with Claude Code

lucasbraum and others added 2 commits October 15, 2026 18:42
pack test --write on main under UPT-48's gate, one pack at a time, each with
its own cache. Ground truth unchanged.

- typescript: 7 repos, 1,399 real breaking sites, 0 breaking FP; unexercised
  downlevel-iteration, import-assertions, module-keyword (run assisted).
- express: 4 repos, 86 real breaking sites, 0 breaking FP; none unexercised.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Lucas Braum <lucasbraum@gmail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Lucas Braum <lucasbraum@gmail.com>
… covered (#165)

Stacked on #160 (base is its branch; retarget to main once #160 merges).

## What

`predictedSites` (packs/tooling/pack-test.ts) now takes the repository's
expected sites. When an anchored finding lists one as `downstream`
evidence, that site counts as covered, at the truth's own rule and
severity. Examples: TypeScript 6 `types: []` errors folded into one
`changed-defaults` finding per tsconfig, and #136's TS7006 option
cascades. So covered sites add true positives to the breaking and
overall tallies and to their own rule. They don't inflate the
behavior-note tally. Evidence the truth doesn't name stays unscored, as
before. No ground-truth changes.

## Re-score: typescript (`--write`, once)

| | Before | After |
|---|---|---|
| Breaking precision | 100% | 100% |
| Breaking recall | 17% (240 / 1,399) | **99% (1,379 / 1,399)** |
| Breaking FP | 0 | 0 |
| Behavior notes P / R | 20% / 50% | 20% / 50% (unchanged) |
| Gate | verified | verified |

The 20 remaining breaking misses are the second-round and same-change
lines RESEARCH.md already lists. README table, RESEARCH.md and
verification.json are updated; the change to docs/packs.md is one
sentence. Packs whose records include anchored evidence may show changed
numbers on the next run. The scorer only adds true positives, so no
false positive count or gate verdict can change.

## Checks

- `vitest run` in core: 1,857 passed. The `predictedSites` evidence test
now also covers a named evidence site.
- `pnpm lint` (pre-existing warnings only), `typecheck`, `docs:packs
--check`, `public:check` pass.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: Lucas Braum <lucasbraum@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@lucasbraum
lucasbraum merged commit 2062939 into main Oct 16, 2026
28 checks passed
@lucasbraum
lucasbraum deleted the lucasbraum/promote-verified-packs branch October 16, 2026 03:30
@uptide-release uptide-release Bot mentioned this pull request Oct 16, 2026
lucasbraum added a commit that referenced this pull request Oct 16, 2026
…ocal module (UPT-66) (#168)

Linear: UPT-66. Redis gap 1 from #151/#160.

## What

- **Finder.** `scan-cursor` also reads files that never import redis but
import a value from a repository module that depends on it
(`getRedisClient` from `../config/redis`, `redisClient` from
`~/utils/redis.server`), resolved the way the compiler does it (tsconfig
`paths`, `export *` chains). This is the #127 approach. zod's resolver
moves to `check/importers.ts` as `packageImports` and `projectFiles`,
parameterized by package; zod's behavior is unchanged. `scan(cursor)`
after `let cursor = 0` counts as a numeric cursor (fixture `scan-cursor`
line 9 marked).
- **Promotion.** `pack test redis --write` on this branch measures
verified under UPT-48's gate, so `verification.json` now says
`verified`. README table regenerated. Ground truth is unchanged: the
record's digest matches the committed file, and the old candidate
record's digest was stale.
- Tests came first (e2904cb): the FCM layout (getter typed off
`createClient`, relative import) and the blog layout (`~/` alias, file
not among the usages).

## Score

| | before (#151/#160) | after |
|---|---|---|
| breaking P / R | 100% / 61% (11/18) | 100% / 83% (15/18) |
| scan-cursor recall | 30% | 70% |
| behavior notes P / R | 50% / 50% | 50% / 50% |

5 repos, 20 real breaking sites, 0 breaking false positives.
`keep-alive`, `quit-disconnect`, `scan-iterators` and `unstable-resp3`
have no real site and run as assisted.

## Remaining misses (3, blog)

- `refresh-cache.ts:204`, `:206`: compile errors only. The importer
memory cap (`IMPORTER_GROWTH` 0.2) leaves the file out of the program;
the run reports it as not analyzed. 0.5 would include it. The cap is not
changed here.
- `utils.ts:106`: a helper with a local structural client type and no
redis-related import. Following imports can't reach it.

## Checks

Core suite: one failure, in `fix/assisted.test.ts` (a known timeout
flake); it passes on its own (24/24). Lint and typecheck are clean (the
one lint warning is already on main). `public:check` is clean.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Signed-off-by: Lucas Braum <lucasbraum@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
lucasbraum pushed a commit that referenced this pull request Oct 16, 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.14.0

### Minor Changes

- [#160](#160)
[`2062939`](2062939)
Thanks [@lucasbraum](https://github.com/lucasbraum)! - The typescript 5
to 6 and express 4 to 5 packs are now verified, so `check`, `list` and
`fix` use them by default. Both measure verified under the stricter gate
on unchanged ground truth: typescript across 7 public repositories
(1,399 real breaking sites, no breaking false positive; its
`downlevel-iteration`, `import-assertions` and `module-keyword` rewrites
stay assisted until a real site exercises them), express across 4 (86
real breaking sites, no breaking false positive).

### Patch Changes

- [#168](#168)
[`7c14ad0`](7c14ad0)
Thanks [@lucasbraum](https://github.com/lucasbraum)! - The redis
(node-redis) 4 to 5 and 5 to 6 pack is verified: 5 public upgrades, 20
real breaking sites, breaking precision 100% and recall 83%; its four
rewrites no real site exercises (`keepAlive`, `quit`/`disconnect`, scan
iterators, `unstableResp3`) run as assisted. It now reports numeric SCAN
cursors in files that use the client through the repository's own module
(`getRedisClient` from `../config/redis`, `redisClient` from
`~/utils/redis.server`) without importing redis, including files the
compile scope left out under the importer memory cap, and treats
`scan(cursor)` after `let cursor = 0` as a numeric cursor. The resolver
behind it, shared with the zod pack's form-error rule, moves to
`check/importers.ts` as `packageImports`.

- [#160](#160)
[`2062939`](2062939)
Thanks [@lucasbraum](https://github.com/lucasbraum)! - `uptide pack
test` counts a ground-truth site that a folded finding lists as its
evidence as covered by that finding, so recall reflects what `check`
reports. The typescript pack's breaking recall goes from 17% to 99% on
unchanged ground truth: its TypeScript 6 `types` default errors fold
into one tsconfig finding each.

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