Conversation
fbed8aa to
5dc0f66
Compare
me2seeks
left a comment
There was a problem hiding this comment.
Automated review (Command Code) — not an approval
The extraction itself is sound: I checked that providerDefaultsOf(input.providerType) is the same input in both rewritten call sites (provider-auth.ts:59, model-catalog.ts:198), so defaults.retired === true → isRetiredProvider(providerType) is behavior-preserving, and the registry re-export keeps existing importers working. One problem blocks the build.
P1 (Must-Fix) — the new test file does not compile; @maka/core typecheck and build fail on this revision.
packages/core/src/__tests__/provider-retirement.test.ts:25 imports with a .ts extension:
} from '../provider-retirement.ts';The repository's compiler options do not allow that. tsconfig.base.json sets "moduleResolution": "Bundler" and does not enable allowImportingTsExtensions — which in any case requires noEmit or emitDeclarationOnly, so it cannot be turned on for a package that emits to dist/. Every other import in the tree uses the emitted .js specifier (there are zero .ts-extension imports on main).
Evidence, running the package's own configuration on the reviewed revision:
$ npx tsc -p packages/core/tsconfig.json --noEmit
packages/core/src/__tests__/provider-retirement.test.ts(25,8): error TS5097: An import path can only end with a '.ts' extension when 'allowImportingTsExtensions' is enabled.
That is the only error reported, so the rest of the package is clean. npm --workspace @maka/core run build and run typecheck therefore fail, and because test:dist runs the compiled output, the new suite cannot run. No CI check has reported on this branch, so nothing else caught it.
Smallest sound fix: use the emitted specifier, from '../provider-retirement.js'. Verified locally — with that single change npx tsc -p packages/core/tsconfig.json --noEmit exits 0.
Review-relevant risks. None identified beyond the build break: no public contract, wire shape, security boundary, dependency, licensing, or release effect was found in the diff. The new RETIRED_PROVIDER_TYPES ownership and the contract test that pins it against the registry are an improvement over the implicit retired flag.
Required conclusion.
- Optimal for the actual problem? Yes — the predicate moves to a metadata-free module and the duplicated
retiredflag is removed; that is the smallest change that cuts the static chain. - Production code that can be deleted? Done in this PR — the
retiredfield and the registry-local predicate are gone, and nothing else still reads.retired. - Low-quality tests to delete or replace?
none identified. The new suite is small but meaningful, and the contract test now ties the retired list to the registry. - Deeper refactor required? No.
- Ready to merge? No — not until the import specifier is fixed; the package does not compile as pushed.
- Residual risks / verification gaps: the doc's audit note states a second static chain remains (
main.tsx → @maka/ui → maka-uri → core/settings → … → provider-registry); that is recorded, not fixed, and is out of scope here. I did not run the full suite; the typecheck above was run directly.
Approval boundary. This is automated review; it is not an approval. Per CONTRIBUTING.md, the merge decision requires an independent human review. No approve was submitted.
bytelazy
left a comment
There was a problem hiding this comment.
Thanks — P1 confirmed and fixed in 69e0ea6.
You're right on every point, and the finding also exposes a bad verification claim in my PR description, which I want to correct explicitly rather than quietly fix.
The bug. provider-retirement.test.ts:25 imported ../provider-retirement.ts. I reproduced TS5097 under the repo's resolution mode and confirmed the fix, A/B with TypeScript 5.9.3:
.tsspecifier →error TS5097: An import path can only end with a '.ts' extension when 'allowImportingTsExtensions' is enabled.(exit 2).jsspecifier → clean (exit 0)
I also confirmed there are zero other .ts-extension imports in the tree, so this was mine alone, and that allowImportingTsExtensions is not a viable escape here since it requires noEmit/emitDeclarationOnly and @maka/core emits to dist/. Fixed to ../provider-retirement.js.
Correcting my own verification claim. My PR description said the unit test ran "5 pass, 0 fail". That was true only because of the wrong specifier: I ran node --test --experimental-strip-types, which resolves .ts directly and never invokes the compiler path build/typecheck use. With the correct .js specifier that same command actually fails with ERR_MODULE_NOT_FOUND, because the repo's suites run against compiled dist/ and I have no build in this environment. So my green signal was masking the break you found — the specifier error was load-bearing for my own evidence. That is a real gap in how I verified, not just a typo.
To verify properly this time I compiled both files to a temp directory and ran the emitted JavaScript, which is what test:dist does: compile exits 0, suite passes 5/5.
Still not run by me: the repo's own npm --workspace @maka/core run build / typecheck / test:dist, plus lint and format. This environment cannot npm ci (network-limited), so I verified with a standalone TypeScript 5.9.3 against the repo's compiler options rather than the workspace scripts. No CI has reported on this branch yet — it shows action_required, since first-time fork PRs need a maintainer to approve the workflow run. Worth having that run before anyone relies on my numbers.
The second static chain you noted (main.tsx → @maka/ui → maka-uri → core/settings → … → provider-registry) remains out of scope here and is recorded as open in the doc's audit note, as you read it.
me2seeks
left a comment
There was a problem hiding this comment.
Follow-up (Command Code) — verified resolved
I re-checked the head after your push.
The P1 build break is fixed. packages/core/src/__tests__/provider-retirement.test.ts now imports '../provider-retirement.js', which is the emitted specifier the package config requires. That was the only error npx tsc -p packages/core/tsconfig.json --noEmit reported, so the package typechecks again and the new suite can run. Nothing else in my review is outstanding.
Thanks for the quick turnaround. (Automated review; not an approval, and not a substitute for independent human review under CONTRIBUTING.md.)
…gistry `isRetiredProvider` lived in `provider-registry.ts`, which is built from the generated models.dev tables. The Desktop first screen imported it through `command-palette-commands.ts`, so the whole model-metadata snapshot stayed on the static startup path — the surviving chain flagged in the `docs/model-metadata-firstscreen-optimization.md` audit under apache#4711. Extract the predicate into a new metadata-free module, `packages/core/src/provider-retirement.ts`, backed by a small `RETIRED_PROVIDER_TYPES` list. Its only `provider-registry` import is `import type`, erased at build time, so importing it no longer pulls the generated tables. Re-point the startup-path importer (`command-palette-commands.ts`) and the two `defaults.retired` readers (`model-catalog.ts`, `provider-auth.ts`) at the new module, and drop the `retired` flag from `ProviderDefaults` and the `claude-subscription` entry. The provider-catalog contract test now pins `RETIRED_PROVIDER_TYPES` as the source of truth and asserts `isRetiredProvider` agrees with it, so a name that is retired but not registered (or vice versa) fails there rather than at send time. A focused unit test covers the predicate's purity contract. Static import-graph trace from `apps/desktop/src/renderer/main.tsx`: the `AppShellOverlays → … → command-palette-commands → provider-registry` chain no longer reaches `provider-registry` (0 chains); the separate `ui → maka-uri → settings → onboarding → llm-connections → provider-registry` chain remains and is recorded as open in the doc's audit note — that is the `buildChatModelChoices`/`modelMenuGroups` seam the "Desired outcome" section already names, not the chain this change targets. No build was run and no bundle output was measured; the verification here is static import-graph analysis plus the contract/unit tests. Generated-by: Claude (claude-opus-4-8)
The new test imported `../provider-retirement.ts`. The repo sets `moduleResolution: "Bundler"` without `allowImportingTsExtensions` (which would require `noEmit`/`emitDeclarationOnly` and so cannot be enabled for a package that emits to `dist/`), so `tsc -p packages/core/tsconfig.json` fails with TS5097 and both `build` and `typecheck` break. There are zero other `.ts`-extension imports in the tree. Use `../provider-retirement.js`, matching every other import in the repo. Verified with TypeScript 5.9.3 under the repo's resolution mode: the `.ts` specifier reproduces `TS5097` (exit 2) and the `.js` specifier typechecks clean (exit 0). Compiling both files to a temp dir and running the emitted JavaScript — what `test:dist` does — passes 5/5. My original "5 pass" claim came from `node --test --experimental-strip-types`, which resolves `.ts` directly and therefore never exercised the compiler path the build uses; the wrong specifier was the only reason it passed. Generated-by: Claude (claude-opus-4-8)
69e0ea6 to
2e8dc11
Compare
bytelazy
left a comment
There was a problem hiding this comment.
Thanks for re-checking — and noting it for the record.
Since that follow-up, main moved and this branch went to dirty, so I rebased onto f109ccde. Force-pushed as 2e8dc112; mergeable_state is back to blocked (approval only). Two conflicts, both from #5225 (refactor(models): unify connection-scoped model configuration) touching the same hunks:
provider-registry.ts— upstream removedrelayModelProfilesfromProviderDefaults. Kept upstream's removal and applied my change (dropretired, leave the ownership comment).model-catalog.ts— upstream reworked that call (relayModelProfiles→modelOverrides, and a newsavedModelIdsderivation). Kept upstream's logic verbatim and changed onlydefaults.retired === true→isRetiredProvider(connection.providerType).
Re-verified after the rebase rather than carrying the old results forward: typecheck of both files clean (exit 0), and compiling to a temp dir and running the emitted JavaScript passes 5/5. Swept again for defaults.retired / retired: true on ProviderDefaults — none left. Both commits keep their Generated-by trailer.
One correction to my PR description, which I've now fixed there. It claimed model-metadata.generated.ts is unreachable from the renderer entry (0 chains) and that this PR leaves that unchanged. The "unchanged by this PR" half is right, but 0 chains was wrong — and the way I got it is worth stating, since it's a trap in this repo: model-metadata.generated.ts is generated by scripts/sync-model-metadata.mjs and gitignored, so a fresh checkout doesn't have it. My tracer resolves specifiers against files on disk, so in any tree where that file is absent it silently reports zero chains. I briefly read that as a regression my PR had introduced; once I copied the generated file into a pristine main worktree, main reported the same 2 chains my branch does:
main.tsx → @maka/ui → maka-uri → core/settings → core/model-thinking → core/model-metadata → model-metadata.generated
main.tsx → composition/desktop-feature-services → features/connection-settings → provider-add-model-dialog → core/llm-connections → core/provider-registry → model-metadata.generated
So the pre-existing reachability is broader than the doc's audit note records — the second chain runs through connection-settings, which the note doesn't mention. That's upstream state, not something this PR changes or claims to fix; I've corrected the description to say "unchanged by this PR" without the false zero, and left the doc note alone rather than widen its scope inside a refactor PR.
The command-palette-commands → provider-registry claim — the one this PR is actually about — does still hold after the rebase: 0 chains (was 1). That one doesn't depend on the generated file, since it terminates at provider-registry.ts, which is committed.
Still not run by me: the repo's own build / typecheck / test:dist, lint, or format (this environment can't npm ci), and CI still shows action_required pending a maintainer approving the workflow run for a first-time fork PR.
Summary
isRetiredProviderlived inprovider-registry.ts, which is built from the generated models.dev tables. The Desktop first screen imported it throughcommand-palette-commands.ts, so the whole model-metadata snapshot stayed on the static startup path — the surviving chain flagged in thedocs/model-metadata-firstscreen-optimization.mdaudit under #4711.This extracts the predicate into a new metadata-free module,
packages/core/src/provider-retirement.ts, backed by a smallRETIRED_PROVIDER_TYPESlist. Its onlyprovider-registryimport isimport type(erased at build time), so importing it no longer pulls the generated tables. The startup-path importer (command-palette-commands.ts) and the twodefaults.retiredreaders (model-catalog.ts,provider-auth.ts) are re-pointed at it; theretiredflag is dropped fromProviderDefaultsand theclaude-subscriptionentry.Refs #4711
Verification
apps/desktop/src/renderer/main.tsx(value imports only;import typeerased; dynamicimport()treated as a lazy boundary): theAppShellOverlays → … → command-palette-commands → provider-registrychain no longer reachesprovider-registry— 0 chains after this change (was 1). Tracing fromcommand-palette-commands.tsitself: 0 chains toprovider-registry.model-metadata.generated.tsreachability from the renderer entry is unchanged by this PR: a pristinemainworktree and this branch both report the same 2 chains (viacore/settings → model-thinking → model-metadata, and viafeatures/connection-settings → provider-add-model-dialog → llm-connections → provider-registry). This PR neither adds nor removes any of them.provider-catalog-contract.test.tsnow pinsRETIRED_PROVIDER_TYPESas the source of truth and assertsisRetiredProvideragrees with the registry's retired set; a name that is retired but not registered (or vice versa) fails there rather than at send time.provider-retirement.test.ts(5 cases) covers the predicate's purity and the unknown/active/retired cases. Verified by compiling to a temp directory and running the emitted JavaScript (whattest:distdoes): compile exit 0, suite 5 pass / 0 fail.moduleResolution: "Bundler"— a.tsspecifier reproducesTS5097(exit 2), the.jsspecifier is clean (exit 0). This was the P1 found in review and fixed in69e0ea6.defaults.retired/retired: trueliterals onProviderDefaults— none left.Checks I did not run: the repo's own
npm --workspace @maka/core run build/typecheck/test:dist, lint, format, or the full suite. This environment cannot runnpm ci(network-limited), so verification used a standalone TypeScript 5.9.3 against the repo's compiler options plus static import-graph analysis — not byte-level bundle evidence. CI showsaction_required(first-time fork PRs need a maintainer to approve the workflow run), so no CI check has validated this branch yet.A separate static chain still reaches
provider-registryfrom the first screen (ui → maka-uri → settings → onboarding → llm-connections → provider-registry). This is intentionally not closed here and is recorded as open in the doc's audit note — it is thebuildChatModelChoices/modelMenuGroupsseam the doc's "Desired outcome" section already names, not the chain this change targets.AI use
Tool(s) and scope: Claude (claude-opus-4-8) authored the refactor, tests, and PR description. Both commits carry a
Generated-by: Claude (claude-opus-4-8)trailer.Checklist
Does this PR entail a change in behavior?
The
ProviderDefaultstype loses itsretired?: truefield. Runtime behavior is unchanged:isRetiredProviderreturns the same answers (it still resolvesclaude-subscriptionas retired), and the two readers that checkeddefaults.retirednow call the predicate. No external API beyond that type field changes.