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.)
69e0ea6 to
2e8dc11
Compare
There was a problem hiding this comment.
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 that removal, applied my change (dropretired, leave the ownership comment).model-catalog.ts— upstream reworked the call (relayModelProfiles→modelOverrides, plus a newsavedModelIdsderivation). Kept upstream's logic verbatim, changed onlydefaults.retired === true→isRetiredProvider(connection.providerType).
Re-verified after the rebase: typecheck of both files clean (exit 0); compiled to a temp dir and ran the emitted JavaScript, 5/5. Swept again for defaults.retired / retired: true on ProviderDefaults — none left. Both commits keep their Generated-by trailer.
I have also corrected my PR description. It claimed model-metadata.generated.ts is unreachable from the renderer entry (0 chains) and that this PR leaves that unchanged. The second half is right; 0 chains was wrong. model-metadata.generated.ts is produced by scripts/sync-model-metadata.mjs and gitignored, so a fresh checkout does not have it, and my tracer resolves specifiers against files on disk — in a tree where that file is absent it reports zero chains. With the generated file copied into a pristine main worktree, main reports 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 does not mention. That is upstream state, not something this PR changes. I have fixed 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 this PR is about does hold after the rebase: 0 chains, was 1. It does not 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, format (this environment cannot npm ci). CI still shows action_required, pending a maintainer approving the run for a first-time fork PR.
…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)
Main added a connection-test gate that reads ProviderDefaults.retired. Use the extracted retirement predicate now that the registry flag is gone. Cover all three retired providers and assert that connection tests make no network requests. Verified core build/typecheck and 884 core tests; runtime build/typecheck and 14 retirement-related tests. Lint and formatting pass for the changed files. Generated-by: Claude (claude-opus-4-8)
2e8dc11 to
966f4a5
Compare
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.