Skip to content

fix(check): breaking means confirmed, compile coverage, @types and lockstep companions, root causes at the edit - #46

Merged
lucasbraum merged 6 commits into
mainfrom
fix/check-confirmed-breaking
Oct 8, 2026
Merged

lucasbraum merged 6 commits into
mainfrom
fix/check-confirmed-breaking

Conversation

@lucasbraum

@lucasbraum lucasbraum commented Oct 8, 2026 •

Copy link
Copy Markdown
Collaborator

What and why

The react pack's ground truth (#45) scored check at 4% precision / 1% recall on breaking findings: check did not move @types/react or react-dom with react, compiled almost none of the monorepos' files, and called every type-surface change at a site the compiler never saw "breaking". This fixes the engine, in five steps, with pack test react on #45 as the acceptance test.

  1. Companions. @types/<pkg> moves with <pkg> by name, to the release that types the target (newest at the target's major.minor, else its major, src/check/types-release.ts; prepare diffs the types at that version). A package whose release at the target's own version asks for the target (react-dom 19.0.0 peer-requires react ^19.0.0) is released in lockstep and moves too, even when its installed copy would accept the target. The closure is transitive (@types/react-dom follows react-dom, which follows react), every workspace's dependencies are candidates (the root's hoisted @types/react serves the app that declares react), and the plan is carried by every report of the package and kept by the merged entry. check react 18 → 19 moves react, react-dom, @types/react and @types/react-dom together, and fix installs them together. A workspace that only peer-depends on a package (excalidraw's packages/excalidraw) resolved it through its types and then looked for the runtime copy in its own node_modules alone; it now finds the hoisted copy, as Node does.

  2. Compile coverage. Why most files were not compiled, found and fixed:

    • workspace packages declared workspace:* under Yarn Berry (lockfile 0.0.0-use.local) and npm were never mapped to their source, and the bundled compiler does not resolve a main pointing at a .ts file from node_modules: the declared specifier is now what the engine reads, hoisted links are found from ancestor node_modules, and the mapping follows the linked packages' own links (@tldraw/editor → @tldraw/utils);
    • a scoped program dropped the tsconfig's ambient .d.ts files (vite-env.d.ts, css.d.ts), so every *.module.css import failed; they are added;
    • the bundled compiler is TypeScript 6, whose defaults for unset options differ from TypeScript 5's (strict on, no automatic @types, modern target/module/resolution, interop on): a repository on TypeScript 5 is now read with TypeScript 5's defaults made explicit (src/adapters/typescript/legacy-options.ts). excalidraw's packages/excalidraw went from 4,212 baseline errors (missing jest globals under strict) to 15.

    Every analyzed package prints compiled N of M files in K workspaces; skipped: <reason (count)>, and the verdict says types partly verified: ... instead of compiled against <version> when not every file was (CompileSignal.coverage, PackageReport.compile.coverage, src/check/verdict.ts).

  3. Breaking means confirmed, in every tier. confirmBreaking (was confirmGeneric) runs for the verified tier too: a finding is breaking only with evidence (compiler, runtime probe, module format, removed export, or the pack's own detect). Unconfirmed surface changes are "possible impact": counted apart in the row (✗ 3 breaking, 17 possible), listed under their own line in the package section, never counted as breaking. Packs keep their rules.

  4. One finding for a root cause that is one edit. Two new anchors, marked anchorOnly (one site, the diagnostics as evidence; fix, the plan, sitesOf and pack test count one):

    • a compiler option: when the target drops the global JSX namespace and the workspace's "jsx": "preserve"/"react" reads it (no jsxImportSource), the TS7026/TS2602 diagnostics are anchored at the jsx line of the tsconfig that sets it, through extends (src/adapters/typescript/config-cause.ts);
    • a repository parameter: an argument (TS2345) or JSX attribute (TS2322) rejected at a parameter or prop declared in the repository with a type from outside it, when two or more sites trip it (parameterCause in cause.ts): usePassThroughWheelEvents(ref: RefObject<HTMLElement>) in packages/editor, tripped at eleven call sites across tldraw's packages once useRef returns RefObject<HTMLElement | null>, is one finding at the parameter, under its repository path.

    A pack rule claims an anchor when it claims most of the errors under it (ruleFor).

  5. Ground truth of feat(packs): react 18 → 19 candidate pack (pack test fails, draft) #45. The only expectation change: tldraw's 1,745 JSX element diagnostics in apps/dotcom/client are one site, at the "jsx" line of its tsconfig (pushed to feat(packs): react 18 → 19 candidate pack (pack test fails, draft) #45 as 3180034, with verification.json recorded from this engine). What the compile showed while doing it: those errors come from two copies of the React types. tldraw's lockfile after its own upgrade still keeps @types/react 18.3.23 for a dependency pinned to 16 || 17 || 18, beside @types/react 19; with one copy (what the overlay links) "jsx": "preserve" resolves element types through the UMD React namespace and nothing errors. check does not model the package manager keeping a nested copy, so it does not predict that site (the one global-jsx-namespace false negative left in tldraw at the tsconfig). The config-cause anchor fires when the namespace really is gone from the program.

How it was verified

pnpm uptide pack test <pack> before (main + #45) and after (this branch + #45), same machine, same ground-truth cache.

pack before: breaking precision / recall after
react (#45) 4% / 1% (477 FP, 20 TP, 1854 FN); react-dom, @types/react, @types/react-dom left behind 88% / 64% (11 FP, 83 TP, 46 FN); all three moved, plus next-mdx-remote-client in tldraw
zod 100% / 71% (PASS, verified) 100% / 71% (PASS, verified), identical
stripe 100% / 90% (PASS, verified; 18 TP, 2 FN over 3 repositories) 100% / 90% (PASS, verified), identical
ai 100% / 36% (PASS, verified) 100% / 36% (PASS, verified), identical

react, per rule, after: removed-react-dom 100%/100% (18), use-ref-argument 100%/80%, ref-callback-return, mutable-ref-object, props-with-ref 100%/100%, element-props-unknown 100%/60%, ref-object-nullable 91%/37%, global-jsx-namespace 100%/36%. The 11 breaking false positives left are listed one by one below.

Storefront, before and after (check zod stripe on fixtures/repos/storefront, built CLI, main vs this branch): the rows, rules and counts are identical; the only difference is the coverage line under each package. The README sample is updated with those two lines, and the tier table now says that breaking means confirmed in both tiers and what "possible impact" is. There is no site/ on main.

zod   28 breaking · compiled against 4.6.5: 28 new type errors
  compiled 11 of 11 files in 2 workspaces
  ✗ New error API (required_error → error)   24 sites          auto-fixable
  ...
stripe   4 breaking · compiled against 23.0.0: 4 new type errors
  compiled 7 of 7 files in 1 workspace
  ✗ Test fixture casts widened                   renewal.test.ts:7   auto-fixable

A package with possible impact prints, under its rules:

  ? possible impact: 17 sites in 9 files   the types changed where this code uses them; nothing confirmed that it breaks, so these are not counted as breaking
    ? RefObject#current changed type   12 sites   needs the agent (LLM)

The 11 remaining react false positives (breaking, pack test react after; for #45, not fixed here):

  1. packages/excalidraw/components/ButtonIconSelect.tsx:52, IconPicker.tsx:140, JSONExportDialog.tsx:90, LayerUI.tsx:346, MobileMenu.tsx:92, Stats/index.tsx:231 (6): TS2322 Type 'Element' is not assignable to type 'ReactNode' at a JSX child. The same error the ground truth expects a few lines away in each file (ButtonIconSelect.tsx:40, IconPicker.tsx:117/221, JSONExportDialog.tsx:45, LayerUI.tsx:332/352, MobileMenu.tsx:76-146, Stats/index.tsx:188): the truth was drafted with the repository's TypeScript 4.9, which reports it at the element's first line, and the bundled TypeScript 6 reports it at the offending child. A line-tolerant match, or re-drafting the truth with the same compiler, resolves these.
  2. dev-docs/src/components/Homepage/index.tsx:52: the same TS2322 in dev-docs, where the truth lists only line 1 (the import React the upgrade removed).
  3. examples/excalidraw/with-script-in-browser/index.tsx:16: createRoot(rootElement), react-dom's createRoot container parameter changed; the example's one file cannot resolve @excalidraw/excalidraw (unbuilt dist), so the compiler skipped it and the finding stands on the companion's diff plus the runtime probe. The truth has no site in that example.
  4. apps/examples/src/examples/custom-components/CustomComponentsExample.tsx:11 and packages/tldraw/src/lib/canvas/TldrawSelectionForeground.tsx:59: useTransform(rSvg, ...), TS2345 RefObject<SVGSVGElement | null> not assignable to the hook's RefObject<HTMLElement | SVGElement>. The truth expects the parameter (packages/editor/src/lib/hooks/useTransform.ts:6), which check also reports where two sites in one workspace trip it; these two workspaces each trip it once, and the ≥2 rule is per workspace compile. Clustering across workspaces resolves them.
  5. apps/docs/components/content/index.tsx:18: TS2307 Cannot find module 'next-mdx-remote-client/rsc' after the companion move of next-mdx-remote-client 1.1.2 → 2.1.12 (the version the upgrade also chose). A real break of the companion, reported under react; the truth lists react's sites only.

CI and stripe's third repository. nextjs/saas-starter pins pnpm@12.10.1. It failed to install here only because this machine runs pnpm through a corepack shim (corepack 0.34 looks for bin/pnpm.cjs, which pnpm 12 no longer ships). The Packs job installs pnpm with pnpm/action-setup, not corepack, and pack test sets npm_config_manage_package_manager_versions; run that way here, pnpm 10 switches itself to 12.10.1 and the repository installs ("Done in 58s using pnpm v10.28.0"), after which stripe scores 100% / 90% over all three repositories, before and after. CI should not hit the problem; if it does, the Packs job log will show the same MODULE_NOT_FOUND for bin/pnpm.cjs.

Coverage, from check react with the built CLI:

  • excalidraw: compiled 355 of 356 files in 5 workspaces; skipped: most files cannot resolve their imports at the installed version (1) (before: 4 of 5 files cannot resolve their imports ... compile signal skipped, packages/excalidraw not analyzed at all);
  • tldraw, apps/dotcom/client: compiled 164 of 164 files in 1 workspace (before: 130 of 163 files cannot resolve their imports);
  • supabase/supabase (fixtures/corpus.json, react 19.2.6 → 19.3.0): list output byte-identical to main; check react prints compiled 1109 of 1110 files in 12 workspaces; skipped: most files cannot resolve their imports at the installed version (1) and ↑ upgrades with @types/react 19.2.14 → 19.3.0, @types/react-dom 19.2.3 → 19.3.0, react-dom 19.2.6 → 19.3.0. apps/studio is over the memory budget on this machine with main and with this branch alike; apps/www (449 files) is analyzed now, where main left it out, and reports 64 compiler-confirmed TS2322 sites against @types/react 19.3.0's SVG props. Main reported 0 breaking · compiled against 19.3.0: 0 new type errors for the same upgrade with that workspace unanalyzed.
  • tldraw, whole repository, built CLI: compiled 616 of 616 files in 18 workspaces, 2m42s (before: 7m, most workspaces skipped).

pnpm lint, pnpm typecheck, pnpm test pass (core 895, cli 346). New tests: companions (react 18 → 19, lockstep, workspace visibility), types-release, legacy-options, config-cause, parameter cause (cause.test.ts), anchor-only clusters (anchor.test.ts, unattributed.test.ts), verdict coverage, workspace-source (hoisted, transitive), readInstalled (workspace:* under Yarn Berry), CLI possible-impact and coverage lines.

Known limits, said plainly:

  • the engine thread briefly ran out of heap on tldraw and supabase while this was being built: gathering every workspace's manifests for the companion plan loaded a program per workspace; manifests are now read from disk (d82a922) and both repositories run through the built CLI again.
  • a parameter cause clusters per workspace compile; the same parameter tripped once in each of two workspaces stays two sites.
  • check links one copy of a target's types; an install that keeps a nested older copy (tldraw's @types/react 18 beside 19) is not modeled.

Checklist

  • Tests for the change (a bug fix starts with a failing test)
  • pnpm lint && pnpm typecheck && pnpm test pass
  • README and docs updated if behavior changed (docs/architecture.md, docs/cli.md, README sample and tier table)
  • Changeset added if a user would notice (pnpm changeset): minor, "What changed in check"
  • No new dependency, or it was agreed in an issue
  • No private code, names or paths in fixtures, tests or docs
  • The rules in CONTRIBUTING.md ("Rules that do not bend") still hold

🤖 Generated with Claude Code

https://claude.ai/code/session_018u9b3Pp5H68DdYZGp5Qg1U

Lucas Braum and others added 6 commits October 8, 2026 08:12
…d find hoisted packages from any workspace

A companion plan now closes over what relates to the lead and to companions
already placed: `@types/<pkg>` moves with `<pkg>` to the release that types
the target (its major.minor, else its major), and a package whose release at the
target's own version asks for the target (react-dom 19.0.0 peer-requires react
^19.0.0) moves to that version even when its installed copy would accept the
target. `check react` 18 → 19 moves react-dom, @types/react and @types/react-dom
together, and prepare() diffs the types package at the version the plan chose.

A workspace that only peer-depends on a package resolved it through its types
and then looked for the runtime copy in its own node_modules alone; a hoisting
installer keeps one copy at the root, which Node and now check find from any
workspace.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018u9b3Pp5H68DdYZGp5Qg1U
Signed-off-by: Lucas Braum <lucas.braum@deskfy.io>
…under every package, one finding for a compiler-option cause

A type-surface change is breaking only when the compiler, the runtime probe or
a pack confirms it at the site, in the verified tier as in the generic one;
what nothing confirmed is possible impact, listed apart and never counted.

Every compile says which of the files that use the package it type-checked
and why it skipped the rest; the merged entry prints `compiled N of M files in
K workspaces; skipped: ...` and its verdict says "types partly verified" when
not every file was. Monorepos compile more of their files: a workspace package
declared workspace:* under Yarn or npm resolves to its source, a scoped
program keeps the tsconfig's ambient declaration files, and a repository on
TypeScript 5 is read with TypeScript 5's defaults (strict off, automatic
@types) rather than the bundled TypeScript 6's.

The global JSX namespace @types/react 19 removes, read by "jsx": "preserve",
is one cause: the diagnostics it explains are anchored at the jsx line of the
tsconfig that sets it, as one site with the errors as evidence, and a pack
rule claims the anchor when it claims most of the errors under it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018u9b3Pp5H68DdYZGp5Qg1U
Signed-off-by: Lucas Braum <lucas.braum@deskfy.io>
…rget's types in the overlay, and one finding for a parameter several call sites trip

Workspace packages hoisted to the root (Yarn, npm) and the packages they
link themselves are mapped to their source, so a workspace that imports
@tldraw/editor compiles instead of failing on an unbuilt .tsbuild. A type
reference directive naming a package the overlay serves resolves inside the
overlay, with its node_modules/@types as the only type root, so the installed
copy of @types/react no longer sits beside the target's. An argument or JSX
attribute the compiler rejects at a repository parameter typed with a package
type is one finding at the parameter when two or more sites trip it, with the
call sites as evidence.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018u9b3Pp5H68DdYZGp5Qg1U
Signed-off-by: Lucas Braum <lucas.braum@deskfy.io>
…ry's, and its path is reported as such

The overlay links a target once; a type reference directive naming it is
left to the repository's resolution, since a real upgrade keeps the nested
copy a dependency pins (tldraw's lockfile keeps @types/react 18 for a range
of 16 || 17 || 18), and the errors that follow are the ones its own compiler
reports. The workspace job carries the repository root, so a parameter in
packages/editor that call sites in packages/tldraw trip is anchored there,
under its repository path.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018u9b3Pp5H68DdYZGp5Qg1U
Signed-off-by: Lucas Braum <lucas.braum@deskfy.io>
…r workspace

Gathering every workspace's installed manifests for a companion plan loaded a
full ts-morph program for each of them in the engine thread, which a
28-workspace repository cannot afford; the manifest is found the way Node
resolves it, node_modules/<name> in the workspace or above.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018u9b3Pp5H68DdYZGp5Qg1U
Signed-off-by: Lucas Braum <lucas.braum@deskfy.io>
…er table; changeset says what changed in check

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018u9b3Pp5H68DdYZGp5Qg1U
Signed-off-by: Lucas Braum <lucas.braum@deskfy.io>
@lucasbraum
lucasbraum merged commit 458aa14 into main Oct 8, 2026
7 checks passed
@lucasbraum
lucasbraum deleted the fix/check-confirmed-breaking branch October 8, 2026 15:24
@uptide-release uptide-release Bot mentioned this pull request Oct 8, 2026
lucasbraum added a commit that referenced this pull request Oct 8, 2026
…y as fallback (#48)

## What and why

`check`'s compile signal judged every repository with the TypeScript
ts-morph bundles (6.0.2), whatever the repository installs. A repository
on TypeScript 4.9 was read by TypeScript 6's rules and its error
positions: a JSX child "not assignable to ReactNode" sits on the
element's first line in 4.9 and on the child in 6, which alone accounted
for 7 of the react pack's 11 remaining false positives in excalidraw.

`check` now compiles with the repository's own TypeScript, found the way
`fix`'s verification has found it since #40 (`node_modules/typescript`
in the workspace or the nearest ancestor, never `NODE_PATH` or a global
folder), and falls back to the bundled compiler only when the repository
installs none. The coverage line says which one judged:

```
compiled 11 of 11 files in 2 workspaces with the repo's TypeScript 5.9.3
compiled 355 of 356 files in 5 workspaces with the repo's TypeScript 4.9.4 and 5.4.5
```

How:

- `adapters/typescript/compiler.ts` holds the resolver (moved from
`fix/verify.ts`, same behavior, same tests) plus `repositoryCompiler`
(loaded once per install directory) and `describeCompiler`.
- With the repository's compiler, a baseline program is built once per
workspace from the ts-morph program's root files and the options that
compiler reads from the tsconfig (an option a newer compiler dropped or
defaults differently is the repository's compiler's to read), with the
same workspace-source `paths`; the overlay shares that baseline. With
the bundled compiler the ts-morph program stays the baseline, as before.
Signal A (usages) still runs on ts-morph.
- The host resolver is installed both ways compilers ask:
`resolveModuleNameLiterals` (TypeScript 5+) and `resolveModuleNames`
(TypeScript 4).
- The cause tracers take the compiler with the programs: node kinds and
enum flags are the judging compiler's, not the bundled one's.
- `CompileCoverage.compilers` records which compiler judged, merged
across workspaces (one entry per distinct version); `coverageLine`
prints it.
- Found on the way: a workspace without a tsconfig of its own
(excalidraw-app, covered by the root's `include`) got synthetic options.
The bundled compiler's defaults papered over that (esModuleInterop,
JSX); TypeScript 4.9 did not, and every default import and JSX element
in that workspace errored at the target. Both programs now read the
nearest ancestor tsconfig's options (never its file list) when the
workspace has none. This also lifted excalidraw's coverage from 355 of
356 to 358 of 358 (the `with-script-in-browser` example resolves its
imports now).
- Security and privacy text: SECURITY.md, the CONTRIBUTING.md rules, the
README privacy section and the CLI's `--help` privacy statement (kept
word for word with the README) now say that `check` and `verify` load
the `typescript` package the repository installs, resolved from its
`node_modules`, to compile with, and never run the repository's scripts
or other code outside `fix`'s verification step.

Cost: a repository with its own TypeScript is parsed twice (ts-morph for
Signal A, its compiler for Signal B). The react pack test went from
about 12 to 9 minutes anyway, since the baseline is built once per
workspace and shared.

## How it was verified

New tests: `fix/compiler.test.ts` (compiler naming, bundled fallback,
one load per install directory), `check/verdict.test.ts` (coverage line
with one, several and mixed compilers), `check/check.test.ts` (compilers
merged across workspaces), `adapters/typescript/compile.test.ts`
(coverage names this repository's own TypeScript 5.9.3, which the
fixture finds above it), `adapters/typescript/repo-inherited.test.ts`
(inherited tsconfig options, own file list). `config-cause.test.ts`
passes the compiler. The whole suite runs the overlay through the native
path, since the fixtures sit under this repository's TypeScript.

`pnpm lint && pnpm typecheck && pnpm test` pass (core 900 tests, cli
346).

Storefront (`fixtures/repos/storefront`, built CLI): findings, counts
and verdicts identical to main; only the coverage lines changed, to
`compiled 11 of 11 files in 2 workspaces with the repo's TypeScript
5.9.3` and `compiled 7 of 7 files in 1 workspace with the repo's
TypeScript 5.9.3`. README sample updated accordingly.

Pack tests, before (main, same commit as #46's final numbers) and after,
breaking findings:

| pack | before | after |
|---|---|---|
| react (#45's pack, uncommitted here) | 88% precision / 64% recall, 11
FP, 46 FN | **96% / 69%, 4 FP, 40 FN** |
| zod | 100% / 71% | 100% / 71%, identical |
| stripe | 100% / 90% on 3 repos | 100% / 90%, identical |
| ai | 100% / 36% | 100% / 36%, identical |

react per repo: excalidraw 9 FP → 2 (predicted 61, expected 73), tldraw
unchanged at 9 FP / 26 FN. The 6 "TS 6 vs 4.9 location" false positives
in `packages/excalidraw` are gone, as is the `with-script-in-browser`
one. The 4 remaining breaking false positives:
`dev-docs/.../Homepage/index.tsx:52` (TS2322 at a JSX child in a
workspace on the root's 4.9, same shape as before), `tldraw
apps/docs/components/content/index.tsx:18` (`next-mdx-remote-client/rsc`
after the companion move), and the two `useTransform(rSvg)`
single-site-per-workspace `ref-object-nullable` findings. The other 7 of
the 11 are deprecated or unverified, never counted as breaking. These go
to #45.

## Checklist

- [x] Tests for the change (a bug fix starts with a failing test)
- [x] `pnpm lint && pnpm typecheck && pnpm test` pass
- [x] README and docs updated if behavior changed
- [x] Changeset added if a user would notice (`pnpm changeset`)
- [x] No new dependency, or it was agreed in an issue
- [x] No private code, names or paths in fixtures, tests or docs
- [x] The rules in CONTRIBUTING.md ("Rules that do not bend") still hold

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

https://claude.ai/code/session_018u9b3Pp5H68DdYZGp5Qg1U

---------

Signed-off-by: Lucas Braum <lucas.braum@deskfy.io>
Co-authored-by: Lucas Braum <lucas.braum@deskfy.io>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
lucasbraum pushed a commit that referenced this pull request Oct 8, 2026
…reaking precision 96%, 4 false positives)

The four breaking false positives left are engine or ground-truth-environment
issues, not rules: dev-docs/Homepage (a workspace whose tsconfig extends a
package that is not installed), two useTransform(ref) call sites in other
workspaces than the declaration that is the one cause, and
next-mdx-remote-client/rsc after a companion move the real upgrade never made.
The pack stays a candidate.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKRx4kuV6oi25MP5WguxW9
Signed-off-by: Claude <noreply@anthropic.com>
lucasbraum pushed a commit that referenced this pull request Oct 9, 2026
…reaking precision 96%, 4 false positives)

The four breaking false positives left are engine or ground-truth-environment
issues, not rules: dev-docs/Homepage (a workspace whose tsconfig extends a
package that is not installed), two useTransform(ref) call sites in other
workspaces than the declaration that is the one cause, and
next-mdx-remote-client/rsc after a companion move the real upgrade never made.
The pack stays a candidate.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AKRx4kuV6oi25MP5WguxW9
Signed-off-by: Claude <noreply@anthropic.com>
lucasbraum pushed a commit that referenced this pull request Oct 9, 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.6.0

### Minor Changes

- [#46](#46)
[`458aa14`](458aa14)
Thanks [@lucasbraum](https://github.com/lucasbraum)! - What changed in
`check`:
  
- **Breaking means confirmed.** A type-surface change is reported as
breaking only when the
compiler rejects your code against the target at that site, the runtime
probe saw the
export go, or a migration pack found it, in the verified tier as in the
generic one. What
nothing confirmed is listed as "possible impact", apart from the
breaking count.
- **Coverage, under every package.** `compiled 355 of 356 files in 5
workspaces; skipped:
<reason (count)>` says how much of the code that uses the package the
compiler judged, and
    the verdict says "types partly verified" when not every file was.
- **TypeScript-version-aware defaults.** A repository on TypeScript 5 is
read with
TypeScript 5's defaults for what its tsconfig leaves unset (`strict`
off, automatic
`@types`), not the bundled TypeScript 6's. Monorepos compile far more of
their files:
workspace packages declared `workspace:*` under Yarn and npm resolve to
their source,
scoped programs keep the tsconfig's ambient declaration files, and a
workspace that only
    peer-depends on a package finds the hoisted copy.
- **Companions.** `check` and `fix` move `@types/<pkg>` with `<pkg>`,
and a package released
in lockstep with it (react-dom with react): `check react` 18 → 19 moves
react-dom,
    @types/react and @types/react-dom together.
- **One finding for a root cause that is one edit.** A compiler option
(the global `JSX`
namespace `@types/react` 19 removes, read by `"jsx": "preserve"`) and a
repository
parameter several call sites trip are each one finding at the place to
edit, with the
    compiler errors as evidence.

- [#51](#51)
[`a18bebd`](a18bebd)
Thanks [@lucasbraum](https://github.com/lucasbraum)! - `check` reports
one breaking finding when call sites in different workspaces trace back
to
the same local declaration (a parameter or prop whose type names
something from the upgraded
package): the finding is anchored at the declaration, where the one edit
is, and the call
sites are listed under it as evidence with an `N call sites in M
workspaces` line, in the
terminal, the HTML report and the JSON report. Before, a site alone in
its workspace stayed a
finding of its own, so a hook typed `RefObject<HTMLElement>` and called
from three
workspaces was three findings plus the one that mattered. The JSON
report gains `root` on
call-site findings and `workspace` on evidence sites; nothing is renamed
or removed. The pack
test scorer counts the anchor as the predicted site and never the
evidence under it.

- [#49](#49)
[`2e5c510`](2e5c510)
Thanks [@lucasbraum](https://github.com/lucasbraum)! - Two fixes to
`check`:
  
- **A project whose tsconfig cannot be resolved is not compiled.** A
tsconfig that `extends` a
package or file that is not installed describes options the repository
never builds with, so
what a compiler reports there is not a place to change. `check` skips
it, never turns its
diagnostics into findings, and says so in the coverage line (a file
governed by such a
nested project is dropped from the workspace that happens to reach it):
`compiled 5 of 7 files in 2 workspaces; not compiled: docs/tsconfig.json
(extends "@tsconfig/docusaurus/tsconfig.json" cannot be resolved)`.
- **A package that only peers on the package is left in place when its
peer range rejects the
target.** What always moves with the package stays as before: the
release group published at
the target's own version (`react-dom`), `@types/*`, the exact pins of
the target, and the
packages a pack names in `companions` (each with the official page that
says so), even when their installed range already accepts the
target. Any other package whose installed peer range rejects the target
is not moved and not
compiled at another version; `check` lists it under possible impact,
never as breaking:
`? possible impact, peer conflict: next-mdx-remote-client 1.1.2 declares
react >= 18.3.0 < 19.0.0`.

- [#53](#53)
[`d33bdd0`](d33bdd0)
Thanks [@lucasbraum](https://github.com/lucasbraum)! - A verified
migration pack for React 18 → 19, scored against excalidraw/excalidraw
and
tldraw/tldraw at the commit before their own upgrade. Rewrites by rule:
`useRef<T>()` →
`useRef<T>(undefined)`, `ref={(el) => (x = el)}` → a block body, and
`React.MutableRefObject`
→ `React.RefObject`. `RefObject<T | null>`, the removed global `JSX`
namespace, untyped
`element.props`, the removed react-dom APIs and `PropsWithRef` go to the
agent with the guide;
what the compiler cannot see (errors no longer re-thrown, removed legacy
APIs, `act` moved to
"react", Strict Mode and Suspense changes) is listed for review. 2
public repositories, 100%
precision on breaking findings (89 sites, none false), recall 69% on
breaking sites; the
  sites it misses are listed in the pack test output.

### Patch Changes

- [#48](#48)
[`94611a9`](94611a9)
Thanks [@lucasbraum](https://github.com/lucasbraum)! - `check` compiles
your code with the repository's own TypeScript (the
`node_modules/typescript`
its build uses, found the way `fix` has found it since verification),
and falls back to the
bundled compiler only when the repository installs none. Errors and
their positions are the
ones your `tsc` would print: a repository on TypeScript 4.9 is no longer
judged by TypeScript
6's rules. The coverage line says which compiler judged: `compiled 355
of 356 files in 5
  workspaces with the repo's TypeScript 4.9.5`.
  
A workspace without a tsconfig of its own is now configured by the
nearest one above it (a
monorepo root whose `include` covers the workspace), for its options
only; synthetic defaults
  apply only when no tsconfig exists anywhere.

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