refactor: extract readCanonicalStat and add structural guards for stat field migration#1709
Conversation
…t field migration
|
@momothemage is attempting to deploy a commit to the Amantus Machina Team on Vercel. A member of the Team first needs to authorize it. |
|
@codex review |
Greptile SummaryThis PR extracts Two P2 follow-up items: the Confidence Score: 5/5Safe to merge — pure refactor with no behavior change and correct implementation. All findings are P2: one about the uncertain effectiveness of @deprecated JSDoc in the Convex codegen pipeline, and one about pre-existing callers not yet migrated to readCanonicalStat(). Neither blocks merge. The core extraction logic is correct and the refactor faithfully preserves existing behavior. No files require special attention for merge; follow-up migration of statsMaintenance.ts and search.ts is recommended post-merge.
|
| downloads: v.number(), | ||
| /** @deprecated Use top-level `statsInstallsCurrent` instead. */ | ||
| installsCurrent: v.optional(v.number()), | ||
| /** @deprecated Use top-level `statsInstallsAllTime` instead. */ | ||
| installsAllTime: v.optional(v.number()), | ||
| /** @deprecated Use top-level `statsStars` instead. */ | ||
| stars: v.number(), | ||
| versions: v.number(), | ||
| comments: v.number(), |
There was a problem hiding this comment.
@deprecated annotations may not surface in IDE tooling
The @deprecated JSDoc tags are placed on object literal properties passed to v.object(). TypeScript/IDE strikethrough warnings for @deprecated only activate on accesses to properties whose type declarations carry the tag — for example, an interface or type field. Convex codegen generates Doc<"skills"> from the schema validators at build time, and is unlikely to carry these JSDoc comments through to the generated types in _generated/dataModel.ts.
If the generated types don't include @deprecated, developers accessing skill.stats.downloads in other files will see no strikethrough, and the AGENTS.md claim ("Any IDE access to skill.stats.downloads etc. will show a strikethrough warning") would be inaccurate. It's worth verifying against the actual generated output, and if the strikethrough doesn't propagate, updating AGENTS.md accordingly so contributors aren't confused when they don't see it.
Prompt To Fix With AI
This is a comment left during a code review.
Path: convex/schema.ts
Line: 104-112
Comment:
**`@deprecated` annotations may not surface in IDE tooling**
The `@deprecated` JSDoc tags are placed on object literal properties passed to `v.object()`. TypeScript/IDE strikethrough warnings for `@deprecated` only activate on accesses to properties whose *type declarations* carry the tag — for example, an `interface` or `type` field. Convex codegen generates `Doc<"skills">` from the schema validators at build time, and is unlikely to carry these JSDoc comments through to the generated types in `_generated/dataModel.ts`.
If the generated types don't include `@deprecated`, developers accessing `skill.stats.downloads` in other files will see no strikethrough, and the AGENTS.md claim ("Any IDE access to `skill.stats.downloads` etc. will show a strikethrough warning") would be inaccurate. It's worth verifying against the actual generated output, and if the strikethrough doesn't propagate, updating AGENTS.md accordingly so contributors aren't confused when they don't see it.
How can I resolve this? If you propose a fix, please make it concise.|
Codex Review: Didn't find any major issues. 👍 ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |
There was a problem hiding this comment.
Thanks for the follow-up PR — the readCanonicalStat extraction, @deprecated annotations, and AGENTS.md rules are exactly the structural guards we discussed. Clean work.
On second look, this PR's scope is clear: extract the helper, add deprecation annotations, document the rules. Migrating callers like statsMaintenance.ts is a natural follow-up, not a blocker here.
LGTM.
hxy91819
left a comment
There was a problem hiding this comment.
Thanks for the follow-up PR — the readCanonicalStat extraction, @deprecated annotations, and AGENTS.md rules are exactly the structural guards we discussed. Clean work.
On second look, this PR's scope is clear: extract the helper, add deprecation annotations, document the rules. Migrating callers like statsMaintenance.ts is a natural follow-up, not a blocker here.
LGTM.
|
Merged via squash.
Thanks @momothemage! |
Summary
This PR introduces
readCanonicalStat()as the single canonical way to read migrated stat fields from askillsdocument, and adds schema-level@deprecatedannotations to discourage direct access to the legacy nested fields.Background
The
skillstable is mid-migration: four stat fields (downloads,stars,installsCurrent,installsAllTime) are being promoted from the nestedstats.*object to top-level indexable fields (statsDownloads,statsStars, etc.). During the transition, both sets of fields coexist, and reads must prefer the top-level field while falling back to the nested field for pre-migration documents.Previously, this fallback logic was duplicated inline in
applySkillStatDeltas()and scattered across callers. This PR centralizes it.Changes
convex/lib/skillStats.tsreadCanonicalStat(skill, field): a typed helper that reads the top-level field when present, and falls back toskill.stats[field]for pre-migration documents.applySkillStatDeltas()to usereadCanonicalStat()internally, removing ~12 lines of duplicated fallback logic.convex/schema.tsstatsValidatorexplaining the migration context.downloads,stars,installsCurrent,installsAllTime) as@deprecatedwith pointers to their top-level replacements, so IDE tooling surfaces a strikethrough warning on direct access.AGENTS.mdreadCanonicalStat()to read, always useapplySkillStatDeltas()to write, and never access the deprecated nested fields directly.Testing
No behavior change — this is a pure refactor. The fallback logic in
readCanonicalStat()is equivalent to the inline logic it replaces.