Repository navigation
fix(check): breaking means confirmed, compile coverage, @types and lockstep companions, root causes at the edit - #46
Merged
Conversation
…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>
Merged
7 tasks done
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>
6 of 8 tasks
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>
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.
What and why
The react pack's ground truth (#45) scored
checkat 4% precision / 1% recall on breaking findings:checkdid not move@types/reactorreact-domwithreact, 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, withpack test reacton #45 as the acceptance test.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;preparediffs 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-domfollowsreact-dom, which followsreact), every workspace's dependencies are candidates (the root's hoisted@types/reactserves the app that declaresreact), and the plan is carried by every report of the package and kept by the merged entry.check react18 → 19 moves react, react-dom, @types/react and @types/react-dom together, andfixinstalls them together. A workspace that only peer-depends on a package (excalidraw'spackages/excalidraw) resolved it through its types and then looked for the runtime copy in its ownnode_modulesalone; it now finds the hoisted copy, as Node does.Compile coverage. Why most files were not compiled, found and fixed:
workspace:*under Yarn Berry (lockfile0.0.0-use.local) and npm were never mapped to their source, and the bundled compiler does not resolve amainpointing at a.tsfile fromnode_modules: the declared specifier is now what the engine reads, hoisted links are found from ancestornode_modules, and the mapping follows the linked packages' own links (@tldraw/editor→@tldraw/utils);.d.tsfiles (vite-env.d.ts,css.d.ts), so every*.module.cssimport failed; they are added;stricton, 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'spackages/excalidrawwent 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 saystypes partly verified: ...instead ofcompiled against <version>when not every file was (CompileSignal.coverage,PackageReport.compile.coverage,src/check/verdict.ts).Breaking means confirmed, in every tier.
confirmBreaking(wasconfirmGeneric) runs for the verified tier too: a finding is breaking only with evidence (compiler, runtime probe, module format, removed export, or the pack's owndetect). 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.One finding for a root cause that is one edit. Two new anchors, marked
anchorOnly(one site, the diagnostics as evidence;fix, the plan,sitesOfandpack testcount one):JSXnamespace and the workspace's"jsx": "preserve"/"react"reads it (nojsxImportSource), the TS7026/TS2602 diagnostics are anchored at thejsxline of the tsconfig that sets it, throughextends(src/adapters/typescript/config-cause.ts);parameterCauseincause.ts):usePassThroughWheelEvents(ref: RefObject<HTMLElement>)inpackages/editor, tripped at eleven call sites across tldraw's packages onceuseRefreturnsRefObject<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).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/clientare 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, withverification.jsonrecorded 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/react18.3.23 for a dependency pinned to16 || 17 || 18, beside@types/react19; with one copy (what the overlay links)"jsx": "preserve"resolves element types through the UMDReactnamespace and nothing errors.checkdoes not model the package manager keeping a nested copy, so it does not predict that site (the oneglobal-jsx-namespacefalse 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.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 stripeonfixtures/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 nosite/on main.A package with possible impact prints, under its rules:
The 11 remaining react false positives (breaking,
pack test reactafter; for #45, not fixed here):packages/excalidraw/components/ButtonIconSelect.tsx:52,IconPicker.tsx:140,JSONExportDialog.tsx:90,LayerUI.tsx:346,MobileMenu.tsx:92,Stats/index.tsx:231(6): TS2322Type '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.dev-docs/src/components/Homepage/index.tsx:52: the same TS2322 in dev-docs, where the truth lists only line 1 (theimport Reactthe upgrade removed).examples/excalidraw/with-script-in-browser/index.tsx:16:createRoot(rootElement), react-dom'screateRootcontainer parameter changed; the example's one file cannot resolve@excalidraw/excalidraw(unbuiltdist), 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.apps/examples/src/examples/custom-components/CustomComponentsExample.tsx:11andpackages/tldraw/src/lib/canvas/TldrawSelectionForeground.tsx:59:useTransform(rSvg, ...), TS2345RefObject<SVGSVGElement | null>not assignable to the hook'sRefObject<HTMLElement | SVGElement>. The truth expects the parameter (packages/editor/src/lib/hooks/useTransform.ts:6), whichcheckalso 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.apps/docs/components/content/index.tsx:18: TS2307Cannot 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-starterpinspnpm@12.10.1. It failed to install here only because this machine runs pnpm through a corepack shim (corepack 0.34 looks forbin/pnpm.cjs, which pnpm 12 no longer ships). The Packs job installs pnpm withpnpm/action-setup, not corepack, andpack testsetsnpm_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 sameMODULE_NOT_FOUNDforbin/pnpm.cjs.Coverage, from
check reactwith the built CLI: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/excalidrawnot analyzed at all);apps/dotcom/client:compiled 164 of 164 files in 1 workspace(before:130 of 163 files cannot resolve their imports);listoutput byte-identical to main;check reactprintscompiled 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/studiois 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 reported0 breaking · compiled against 19.3.0: 0 new type errorsfor the same upgrade with that workspace unanalyzed.compiled 616 of 616 files in 18 workspaces, 2m42s (before: 7m, most workspaces skipped).pnpm lint,pnpm typecheck,pnpm testpass (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:
checklinks one copy of a target's types; an install that keeps a nested older copy (tldraw's@types/react18 beside 19) is not modeled.Checklist
pnpm lint && pnpm typecheck && pnpm testpassdocs/architecture.md,docs/cli.md, README sample and tier table)pnpm changeset): minor, "What changed in check"🤖 Generated with Claude Code
https://claude.ai/code/session_018u9b3Pp5H68DdYZGp5Qg1U