@mrciphersmith/keryx 0.2.164 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (182) hide show
  1. package/README.md +4 -1
  2. package/dist/cli.js +82540 -50300
  3. package/dist/core.js +28967 -18937
  4. package/package.json +2 -2
  5. package/src/gdgraph/affected-report.ts +141 -0
  6. package/src/gdgraph/build.ts +170 -23
  7. package/src/gdgraph/service.ts +6 -0
  8. package/src/gdgraph/staleness.ts +253 -45
  9. package/src/gdskills/bundled/agents/codebase-navigator.md +55 -0
  10. package/src/gdskills/bundled/agents/design-advisor.md +64 -0
  11. package/src/gdskills/bundled/agents/docs-maintainer.md +56 -0
  12. package/src/gdskills/bundled/agents/end-to-end-tester.md +56 -0
  13. package/src/gdskills/bundled/agents/error-path-auditor.md +57 -0
  14. package/src/gdskills/bundled/agents/go-build-fixer.md +52 -0
  15. package/src/gdskills/bundled/agents/go-code-auditor.md +49 -0
  16. package/src/gdskills/bundled/agents/performance-auditor.md +63 -0
  17. package/src/gdskills/bundled/agents/python-build-fixer.md +52 -0
  18. package/src/gdskills/bundled/agents/python-code-auditor.md +49 -0
  19. package/src/gdskills/bundled/agents/refactoring-steward.md +61 -0
  20. package/src/gdskills/bundled/agents/security-auditor.md +62 -0
  21. package/src/gdskills/bundled/agents/test-first-driver.md +61 -0
  22. package/src/gdskills/bundled/agents/work-planner.md +62 -0
  23. package/src/gdskills/bundled/install-manifest.json +797 -0
  24. package/src/gdskills/bundled/rules/core/model-selection.mdc +51 -0
  25. package/src/gdskills/bundled/rules/core/skill-lifecycle.mdc +29 -1
  26. package/src/gdskills/bundled/rules/core/skills-storage-workflow.mdc +2 -2
  27. package/src/gdskills/bundled/skills/review/code-style-review/SKILL.md +1 -1
  28. package/src/gdskills/bundled/skills/review/review-jev-rules/SKILL.md +267 -0
  29. package/src/gdskills/bundled/skills/review/review-orchestrator/SKILL.detail.md +26 -0
  30. package/src/gdskills/bundled/skills/review/review-orchestrator/SKILL.md +75 -247
  31. package/src/gdskills/bundled/skills/review/review-orchestrator/output-contract.schema.json +19 -0
  32. package/src/gdskills/bundled/skills/review/review-orchestrator/reviewer-finding.schema.json +10 -0
  33. package/src/gdskills/bundled/skills/review/review-orchestrator/reviewer-input.schema.json +5 -0
  34. package/src/gdskills/bundled/skills/review/review-orchestrator/templates/pr-comment-backend.md +50 -0
  35. package/src/gdskills/bundled/skills/review/review-orchestrator/templates/pr-comment-frontend.md +52 -0
  36. package/src/gdskills/bundled/skills/review/review-orchestrator/templates/review-report.md +143 -0
  37. package/src/gdskills/bundled/stacks/angular/agent-refs.json +4 -0
  38. package/src/gdskills/bundled/stacks/angular/governance/eval.json +1751 -0
  39. package/src/gdskills/bundled/stacks/angular/governance/scout.json +32 -0
  40. package/src/gdskills/bundled/stacks/angular/pack.json +55 -0
  41. package/src/gdskills/bundled/stacks/angular/rules/coding-style.mdc +82 -0
  42. package/src/gdskills/bundled/stacks/angular/rules/patterns.mdc +84 -0
  43. package/src/gdskills/bundled/stacks/angular/rules/security.mdc +70 -0
  44. package/src/gdskills/bundled/stacks/angular/rules/testing.mdc +73 -0
  45. package/src/gdskills/bundled/stacks/angular/skills/angular-build-fix/SKILL.md +127 -0
  46. package/src/gdskills/bundled/stacks/angular/skills/angular-build-fix/evals.json +72 -0
  47. package/src/gdskills/bundled/stacks/angular/skills/angular-code-review/SKILL.md +98 -0
  48. package/src/gdskills/bundled/stacks/angular/skills/angular-code-review/evals.json +73 -0
  49. package/src/gdskills/bundled/stacks/angular/skills/angular-implementation/SKILL.md +112 -0
  50. package/src/gdskills/bundled/stacks/angular/skills/angular-implementation/evals.json +74 -0
  51. package/src/gdskills/bundled/stacks/angular/skills/angular-testing/SKILL.md +102 -0
  52. package/src/gdskills/bundled/stacks/angular/skills/angular-testing/evals.json +71 -0
  53. package/src/gdskills/bundled/stacks/go/agent-refs.json +3 -0
  54. package/src/gdskills/bundled/stacks/go/governance/eval.json +1745 -0
  55. package/src/gdskills/bundled/stacks/go/governance/scout.json +31 -0
  56. package/src/gdskills/bundled/stacks/go/pack.json +41 -0
  57. package/src/gdskills/bundled/stacks/go/rules/coding-style.mdc +85 -0
  58. package/src/gdskills/bundled/stacks/go/rules/patterns.mdc +65 -0
  59. package/src/gdskills/bundled/stacks/go/rules/security.mdc +73 -0
  60. package/src/gdskills/bundled/stacks/go/rules/testing.mdc +68 -0
  61. package/src/gdskills/bundled/stacks/go/skills/go-build-fix/SKILL.md +138 -0
  62. package/src/gdskills/bundled/stacks/go/skills/go-build-fix/evals.json +75 -0
  63. package/src/gdskills/bundled/stacks/go/skills/go-code-review/SKILL.md +121 -0
  64. package/src/gdskills/bundled/stacks/go/skills/go-code-review/evals.json +72 -0
  65. package/src/gdskills/bundled/stacks/go/skills/go-implementation/SKILL.md +122 -0
  66. package/src/gdskills/bundled/stacks/go/skills/go-implementation/evals.json +76 -0
  67. package/src/gdskills/bundled/stacks/go/skills/go-testing/SKILL.md +126 -0
  68. package/src/gdskills/bundled/stacks/go/skills/go-testing/evals.json +73 -0
  69. package/src/gdskills/bundled/stacks/mobx/agent-refs.json +4 -0
  70. package/src/gdskills/bundled/stacks/mobx/governance/eval.json +904 -0
  71. package/src/gdskills/bundled/stacks/mobx/governance/scout.json +18 -0
  72. package/src/gdskills/bundled/stacks/mobx/pack.json +28 -0
  73. package/src/gdskills/bundled/stacks/mobx/rules/coding-style.mdc +91 -0
  74. package/src/gdskills/bundled/stacks/mobx/rules/patterns.mdc +122 -0
  75. package/src/gdskills/bundled/stacks/mobx/rules/security.mdc +56 -0
  76. package/src/gdskills/bundled/stacks/mobx/rules/testing.mdc +63 -0
  77. package/src/gdskills/bundled/stacks/mobx/skills/mobx-observable-testing/SKILL.md +124 -0
  78. package/src/gdskills/bundled/stacks/mobx/skills/mobx-observable-testing/evals.json +73 -0
  79. package/src/gdskills/bundled/stacks/mobx/skills/mobx-store-implementation/SKILL.md +149 -0
  80. package/src/gdskills/bundled/stacks/mobx/skills/mobx-store-implementation/evals.json +74 -0
  81. package/src/gdskills/bundled/stacks/nestjs/agent-refs.json +4 -0
  82. package/src/gdskills/bundled/stacks/nestjs/governance/eval.json +1308 -0
  83. package/src/gdskills/bundled/stacks/nestjs/governance/scout.json +34 -0
  84. package/src/gdskills/bundled/stacks/nestjs/pack.json +53 -0
  85. package/src/gdskills/bundled/stacks/nestjs/rules/coding-style.mdc +70 -0
  86. package/src/gdskills/bundled/stacks/nestjs/rules/patterns.mdc +83 -0
  87. package/src/gdskills/bundled/stacks/nestjs/rules/security.mdc +73 -0
  88. package/src/gdskills/bundled/stacks/nestjs/rules/testing.mdc +69 -0
  89. package/src/gdskills/bundled/stacks/nestjs/skills/nestjs-build-fix/SKILL.md +157 -0
  90. package/src/gdskills/bundled/stacks/nestjs/skills/nestjs-build-fix/evals.json +70 -0
  91. package/src/gdskills/bundled/stacks/nestjs/skills/nestjs-implementation/SKILL.md +129 -0
  92. package/src/gdskills/bundled/stacks/nestjs/skills/nestjs-implementation/evals.json +71 -0
  93. package/src/gdskills/bundled/stacks/nestjs/skills/nestjs-testing/SKILL.md +143 -0
  94. package/src/gdskills/bundled/stacks/nestjs/skills/nestjs-testing/evals.json +69 -0
  95. package/src/gdskills/bundled/stacks/nextjs-nuxt/agent-refs.json +4 -0
  96. package/src/gdskills/bundled/stacks/nextjs-nuxt/governance/eval.json +2413 -0
  97. package/src/gdskills/bundled/stacks/nextjs-nuxt/governance/scout.json +42 -0
  98. package/src/gdskills/bundled/stacks/nextjs-nuxt/pack.json +42 -0
  99. package/src/gdskills/bundled/stacks/nextjs-nuxt/rules/coding-style.mdc +69 -0
  100. package/src/gdskills/bundled/stacks/nextjs-nuxt/rules/patterns.mdc +88 -0
  101. package/src/gdskills/bundled/stacks/nextjs-nuxt/rules/security.mdc +72 -0
  102. package/src/gdskills/bundled/stacks/nextjs-nuxt/rules/testing.mdc +64 -0
  103. package/src/gdskills/bundled/stacks/nextjs-nuxt/skills/nextjs-nuxt-build-fix/SKILL.md +147 -0
  104. package/src/gdskills/bundled/stacks/nextjs-nuxt/skills/nextjs-nuxt-build-fix/evals.json +75 -0
  105. package/src/gdskills/bundled/stacks/nextjs-nuxt/skills/nextjs-nuxt-code-review/SKILL.md +118 -0
  106. package/src/gdskills/bundled/stacks/nextjs-nuxt/skills/nextjs-nuxt-code-review/evals.json +76 -0
  107. package/src/gdskills/bundled/stacks/nextjs-nuxt/skills/nextjs-nuxt-implementation/SKILL.md +135 -0
  108. package/src/gdskills/bundled/stacks/nextjs-nuxt/skills/nextjs-nuxt-implementation/evals.json +78 -0
  109. package/src/gdskills/bundled/stacks/nextjs-nuxt/skills/nextjs-nuxt-testing/SKILL.md +116 -0
  110. package/src/gdskills/bundled/stacks/nextjs-nuxt/skills/nextjs-nuxt-testing/evals.json +75 -0
  111. package/src/gdskills/bundled/stacks/nextjs-nuxt/skills/nextjs-nuxt-upgrade-migration/SKILL.md +134 -0
  112. package/src/gdskills/bundled/stacks/nextjs-nuxt/skills/nextjs-nuxt-upgrade-migration/evals.json +76 -0
  113. package/src/gdskills/bundled/stacks/python/agent-refs.json +3 -0
  114. package/src/gdskills/bundled/stacks/python/governance/eval.json +1758 -0
  115. package/src/gdskills/bundled/stacks/python/governance/scout.json +34 -0
  116. package/src/gdskills/bundled/stacks/python/pack.json +41 -0
  117. package/src/gdskills/bundled/stacks/python/rules/coding-style.mdc +63 -0
  118. package/src/gdskills/bundled/stacks/python/rules/patterns.mdc +88 -0
  119. package/src/gdskills/bundled/stacks/python/rules/security.mdc +84 -0
  120. package/src/gdskills/bundled/stacks/python/rules/testing.mdc +77 -0
  121. package/src/gdskills/bundled/stacks/python/skills/python-build-fix/SKILL.md +144 -0
  122. package/src/gdskills/bundled/stacks/python/skills/python-build-fix/evals.json +74 -0
  123. package/src/gdskills/bundled/stacks/python/skills/python-code-review/SKILL.md +155 -0
  124. package/src/gdskills/bundled/stacks/python/skills/python-code-review/evals.json +72 -0
  125. package/src/gdskills/bundled/stacks/python/skills/python-implementation/SKILL.md +143 -0
  126. package/src/gdskills/bundled/stacks/python/skills/python-implementation/evals.json +78 -0
  127. package/src/gdskills/bundled/stacks/python/skills/python-testing/SKILL.md +132 -0
  128. package/src/gdskills/bundled/stacks/python/skills/python-testing/evals.json +73 -0
  129. package/src/gdskills/bundled/stacks/react/agent-refs.json +4 -0
  130. package/src/gdskills/bundled/stacks/react/governance/eval.json +2188 -0
  131. package/src/gdskills/bundled/stacks/react/governance/scout.json +40 -0
  132. package/src/gdskills/bundled/stacks/react/pack.json +42 -0
  133. package/src/gdskills/bundled/stacks/react/rules/coding-style.mdc +58 -0
  134. package/src/gdskills/bundled/stacks/react/rules/patterns.mdc +79 -0
  135. package/src/gdskills/bundled/stacks/react/rules/security.mdc +70 -0
  136. package/src/gdskills/bundled/stacks/react/rules/testing.mdc +60 -0
  137. package/src/gdskills/bundled/stacks/react/skills/react-build-fix/SKILL.md +139 -0
  138. package/src/gdskills/bundled/stacks/react/skills/react-build-fix/evals.json +72 -0
  139. package/src/gdskills/bundled/stacks/react/skills/react-code-review/SKILL.md +148 -0
  140. package/src/gdskills/bundled/stacks/react/skills/react-code-review/evals.json +74 -0
  141. package/src/gdskills/bundled/stacks/react/skills/react-implementation/SKILL.md +140 -0
  142. package/src/gdskills/bundled/stacks/react/skills/react-implementation/evals.json +74 -0
  143. package/src/gdskills/bundled/stacks/react/skills/react-testing/SKILL.md +142 -0
  144. package/src/gdskills/bundled/stacks/react/skills/react-testing/evals.json +83 -0
  145. package/src/gdskills/bundled/stacks/react/skills/react-upgrade-migration/SKILL.md +155 -0
  146. package/src/gdskills/bundled/stacks/react/skills/react-upgrade-migration/evals.json +74 -0
  147. package/src/gdskills/bundled/stacks/ts-js-node/agent-refs.json +4 -0
  148. package/src/gdskills/bundled/stacks/ts-js-node/governance/eval.json +2155 -0
  149. package/src/gdskills/bundled/stacks/ts-js-node/governance/scout.json +40 -0
  150. package/src/gdskills/bundled/stacks/ts-js-node/pack.json +41 -0
  151. package/src/gdskills/bundled/stacks/ts-js-node/rules/coding-style.mdc +73 -0
  152. package/src/gdskills/bundled/stacks/ts-js-node/rules/patterns.mdc +61 -0
  153. package/src/gdskills/bundled/stacks/ts-js-node/rules/security.mdc +71 -0
  154. package/src/gdskills/bundled/stacks/ts-js-node/rules/testing.mdc +63 -0
  155. package/src/gdskills/bundled/stacks/ts-js-node/skills/nodejs-build-fix/SKILL.md +137 -0
  156. package/src/gdskills/bundled/stacks/ts-js-node/skills/nodejs-build-fix/evals.json +73 -0
  157. package/src/gdskills/bundled/stacks/ts-js-node/skills/nodejs-code-review/SKILL.md +124 -0
  158. package/src/gdskills/bundled/stacks/ts-js-node/skills/nodejs-code-review/evals.json +74 -0
  159. package/src/gdskills/bundled/stacks/ts-js-node/skills/nodejs-esm-migration/SKILL.md +152 -0
  160. package/src/gdskills/bundled/stacks/ts-js-node/skills/nodejs-esm-migration/evals.json +71 -0
  161. package/src/gdskills/bundled/stacks/ts-js-node/skills/nodejs-implementation/SKILL.md +127 -0
  162. package/src/gdskills/bundled/stacks/ts-js-node/skills/nodejs-implementation/evals.json +72 -0
  163. package/src/gdskills/bundled/stacks/ts-js-node/skills/nodejs-testing/SKILL.md +134 -0
  164. package/src/gdskills/bundled/stacks/ts-js-node/skills/nodejs-testing/evals.json +70 -0
  165. package/src/gdskills/bundled/stacks/vue/agent-refs.json +4 -0
  166. package/src/gdskills/bundled/stacks/vue/governance/eval.json +2215 -0
  167. package/src/gdskills/bundled/stacks/vue/governance/scout.json +42 -0
  168. package/src/gdskills/bundled/stacks/vue/pack.json +42 -0
  169. package/src/gdskills/bundled/stacks/vue/rules/coding-style.mdc +73 -0
  170. package/src/gdskills/bundled/stacks/vue/rules/patterns.mdc +84 -0
  171. package/src/gdskills/bundled/stacks/vue/rules/security.mdc +60 -0
  172. package/src/gdskills/bundled/stacks/vue/rules/testing.mdc +69 -0
  173. package/src/gdskills/bundled/stacks/vue/skills/vue-build-fix/SKILL.md +137 -0
  174. package/src/gdskills/bundled/stacks/vue/skills/vue-build-fix/evals.json +72 -0
  175. package/src/gdskills/bundled/stacks/vue/skills/vue-code-review/SKILL.md +120 -0
  176. package/src/gdskills/bundled/stacks/vue/skills/vue-code-review/evals.json +71 -0
  177. package/src/gdskills/bundled/stacks/vue/skills/vue-implementation/SKILL.md +122 -0
  178. package/src/gdskills/bundled/stacks/vue/skills/vue-implementation/evals.json +72 -0
  179. package/src/gdskills/bundled/stacks/vue/skills/vue-testing/SKILL.md +115 -0
  180. package/src/gdskills/bundled/stacks/vue/skills/vue-testing/evals.json +72 -0
  181. package/src/gdskills/bundled/stacks/vue/skills/vue2-to-vue3-migration/SKILL.md +135 -0
  182. package/src/gdskills/bundled/stacks/vue/skills/vue2-to-vue3-migration/evals.json +71 -0
@@ -0,0 +1,83 @@
1
+ {
2
+ "triggers": {
3
+ "positive": [
4
+ "Write a React Testing Library test for this UserCard component's loading, success, and error states",
5
+ "Test this custom hook with renderHook",
6
+ "This component test throws an act warning, help me fix it",
7
+ "Add an MSW request handler to mock the API call in this React component test",
8
+ "Add tests for the form's validation error and successful submit states",
9
+ "Write a user-event test that clicks the button and checks the modal opens"
10
+ ],
11
+ "negative": [
12
+ "Write pytest tests for this FastAPI endpoint",
13
+ "Build a new SearchBar React component with a debounced input",
14
+ "Review this component diff for accessibility issues",
15
+ "Set up Playwright end-to-end tests for the checkout flow",
16
+ "Fix the failing tsc type-check in this component after the react types upgrade",
17
+ "Write unit tests for this plain TypeScript date-formatting utility function"
18
+ ]
19
+ },
20
+ "scenarios": [
21
+ {
22
+ "id": "query-by-role",
23
+ "prompt": "I need a React Testing Library test that clicks the submit button on a login form and checks an error message appears when the password is empty. How should I query for the button and the error?",
24
+ "strictness": "high",
25
+ "expected_behavior": [
26
+ {
27
+ "grader": "judge",
28
+ "rubric": "A correct answer queries the submit button and error message the way a user or assistive technology would — role/label/text-based queries such as getByRole for the button and findByText/getByText for the error — rather than defaulting to data-testid, and drives the click through @testing-library/user-event rather than fireEvent.",
29
+ "pass_criteria": [
30
+ "Shows or names the concrete accessible query for the submit button, such as `getByRole('button', { name: ... })`, not data-testid, as the primary approach.",
31
+ "Shows or names the concrete accessible query for the error message (`getByText`/`findByText`/`getByRole('alert', ...)`), not data-testid.",
32
+ "Shows the click driven through `@testing-library/user-event` (`userEvent.setup()` then `.click`), not `fireEvent`."
33
+ ],
34
+ "fail_criteria": [
35
+ "Recommends data-testid as the default/primary way to find the button or the error message when an accessible query would work.",
36
+ "Uses fireEvent.click (or another fireEvent call) as the interaction mechanism instead of userEvent."
37
+ ]
38
+ },
39
+ {
40
+ "grader": "regex",
41
+ "value": "(get|find|query)(All)?ByRole"
42
+ }
43
+ ],
44
+ "calibration": {
45
+ "known_right": "Query the submit button with `screen.getByRole('button', { name: /submit|log in/i })` — that's how a user or screen reader identifies it, by its accessible role and visible label, not by an internal test id. Drive the click with user-event rather than fireEvent: `const user = userEvent.setup(); await user.click(screen.getByRole('button', { name: /submit/i }));`. For the error message, since it appears asynchronously after the click triggers validation, use `await screen.findByText(/password is required/i)` (or `findByRole('alert', ...)` if the error is rendered with an alert role) rather than a synchronous `getByText`, since `findBy*` retries until the DOM updates. Putting it together:\n```tsx\nconst user = userEvent.setup();\nrender(<LoginForm />);\nawait user.click(screen.getByRole('button', { name: /submit/i }));\nexpect(await screen.findByText(/password is required/i)).toBeInTheDocument();\n```\nOnly fall back to `data-testid` if the button or error text genuinely has no accessible role/label/text to query by.",
46
+ "known_wrong": "Easiest way: give the button and the error message their own test ids in the markup — `data-testid=\"submit-btn\"` and `data-testid=\"password-error\"` — then in the test do `fireEvent.click(screen.getByTestId('submit-btn'))` and assert with `expect(screen.getByTestId('password-error')).toBeInTheDocument()`. Test ids are reliable because they don't break when you change button text or styling later, and fireEvent.click is simpler than setting up user-event since it doesn't need the extra `userEvent.setup()` call.",
47
+ "vague": "Query for the button and the error message the way an assistive-technology user would, using accessible role- or text-based queries instead of test ids, and drive the click through the user-event library rather than firing raw DOM events.",
48
+ "subtle_wrong": "Find the button by its role and label, and drive the click with user-event — that part's straightforward. For the error message, since it's simplest, just add a `data-testid=\"password-error\"` to that element and query it that way after the click — the error text itself is inside a styled component that doesn't have stable visible copy yet, so a testid is the pragmatic choice there until the copy is finalized; getting the button query right is the part that really matters for this test."
49
+ },
50
+ "anti_patterns": [
51
+ "fireEvent",
52
+ "data-testid"
53
+ ]
54
+ },
55
+ {
56
+ "id": "mock-network-boundary",
57
+ "prompt": "My component test needs to mock an API call that the component makes on mount. Where should I put the mock?",
58
+ "strictness": "high",
59
+ "expected_behavior": [
60
+ {
61
+ "grader": "judge",
62
+ "rubric": "A correct answer mocks the network call at the request boundary (an MSW handler intercepting the actual HTTP request, or the project's existing equivalent), not by mocking the component's own data-fetching function/module directly, because a boundary mock still exercises the real fetch/parse/error-handling code path.",
63
+ "pass_criteria": [
64
+ "Names the concrete boundary mechanism (an MSW request handler for the actual HTTP endpoint, e.g. `http.get('/api/...', ...)`, or the project's existing equivalent boundary mock), not just 'mock at the boundary' in the abstract.",
65
+ "Explains or implies that mocking at the boundary keeps the real request/parse/error-handling path under test, rather than bypassing it."
66
+ ],
67
+ "fail_criteria": [
68
+ "Recommends mocking the component's own data-fetching function, fetch helper, or API client method directly (e.g. `vi.mock`/`jest.mock` on the fetch module) instead of the network boundary, even if only offered as a quicker alternative alongside the boundary approach."
69
+ ]
70
+ }
71
+ ],
72
+ "calibration": {
73
+ "known_right": "Mock it at the network boundary, not inside the component. If the project already uses MSW, add a request handler for the actual endpoint the component calls on mount (e.g. `http.get('/api/user/:id', () => HttpResponse.json({ name: 'Ada' }))`) and let the component's real fetch call run against that intercepted request. That way the test still exercises the component's actual fetch call, response parsing, and error handling — you're only replacing what's on the other end of the network, not the code that talks to it. Then in the test, render the component and use `findBy*`/`waitFor` to wait for the state that appears once the mocked response resolves, since the fetch happens asynchronously after mount. If the project doesn't have MSW set up yet, use whatever boundary-level mock it already has (a fetch/axios interceptor) rather than reaching into the component's data-fetching function and swapping it out — that would skip real parsing/error-handling logic the test should also be covering.",
74
+ "known_wrong": "Simplest approach: just mock the component's fetch helper directly. If the component imports something like `fetchUser` from an api module, do `vi.mock('../api/fetchUser')` (or jest.mock) and have it resolve with your test data. That way you skip dealing with MSW handlers or intercepting real requests — you control exactly what the function returns, and the test runs faster since there's no simulated network layer involved at all.",
75
+ "vague": "Mock it at the network boundary rather than inside the component, so the real fetch and parsing logic still runs.",
76
+ "subtle_wrong": "Set up an MSW handler for the endpoint as the primary approach — that's the right general direction. For this particular test though, since the component's fetch call is wrapped in a small `fetchUser` helper that's already unit-tested elsewhere, you can save setup time by mocking that helper directly with `vi.mock('../api/fetchUser')` instead of standing up a full MSW handler; it resolves the same test data without needing to configure the request interception for this one case."
77
+ },
78
+ "anti_patterns": [
79
+ "fetch helper"
80
+ ]
81
+ }
82
+ ]
83
+ }
@@ -0,0 +1,155 @@
1
+ ---
2
+ name: react-upgrade-migration
3
+ description: "Use when upgrading a codebase across React major versions (e.g. 18 to 19) -- removing legacy APIs (string refs, legacy context, propTypes/defaultProps on function components, ReactDOM.render/hydrate), applying official codemods, updating the @types/react package, fixing the act import, and staging the rollout."
4
+ triggers:
5
+ - "upgrade this project to react 19"
6
+ - "migrate off ReactDOM.render"
7
+ - "remove string refs"
8
+ - "fix propTypes deprecation warning"
9
+ - "run the react codemod"
10
+ - "update @types/react for the new major"
11
+ metadata:
12
+ origin: authored
13
+ category: migrate
14
+ version: "1.0.0"
15
+ compatible_harnesses: "claude,codex,cursor,zed,opencode"
16
+ license: "MIT"
17
+ ---
18
+
19
+ # React upgrade / migration
20
+
21
+ Move a codebase from one React major to a newer one (most commonly 18 to
22
+ 19), removing APIs the new major dropped and adopting its replacements.
23
+ Scoped to the React library/types/runtime upgrade itself — a related
24
+ bundler or framework major upgrade (Next.js, Vite) that happens alongside
25
+ it is out of scope unless the failure is caused by a React API removal.
26
+
27
+ ## Workflow
28
+
29
+ ### Step 1: Establish the starting point and target
30
+
31
+ 1. Read the current `react`/`react-dom`/`@types/react`/`@types/react-dom`
32
+ versions from `package.json` and the target major from the user's
33
+ request.
34
+ 2. Read the official React upgrade guide for that version range (the
35
+ project's own `CHANGELOG`/release notes if vendored, otherwise the
36
+ canonical upgrade guide) before touching code — do not rely on memory
37
+ of a prior major's migration for a different jump.
38
+ 3. Inventory usage of the APIs the target major removes or changes (grep
39
+ the codebase; see Step 2 per-API list) so the scope of the change is
40
+ known before starting, not discovered file-by-file.
41
+
42
+ ### Step 2: Remove/replace legacy APIs (18 -> 19 checklist)
43
+
44
+ - **String refs** (`ref="myRef"`): replace with `useRef`/`createRef` (or
45
+ the React 19 ref-as-prop pattern for a component receiving a ref from
46
+ its parent). String refs are removed, not deprecated-but-working.
47
+ - **Legacy context** (`contextTypes`/`getChildContext`): replace with
48
+ `createContext`/`useContext`. Legacy context is removed.
49
+ - **`propTypes`/`defaultProps` on function components**: `propTypes` no
50
+ longer has any effect at runtime in React 19+; if the project relies on
51
+ it for runtime validation, replace the validation with TypeScript types
52
+ (preferred, if the project is TS) or an explicit runtime check. Replace
53
+ `defaultProps` with a default parameter value in the function signature
54
+ (`function C({ x = 1 }: Props)`), since function-component
55
+ `defaultProps` is removed.
56
+ - **`ReactDOM.render`/`ReactDOM.hydrate`**: replace with
57
+ `createRoot(container).render(...)` and `hydrateRoot(container,
58
+ ...)` respectively from `react-dom/client`. Update the app's entry
59
+ point; this is usually a single-file change but touches every test
60
+ helper that also bootstraps a root.
61
+ - **`react-dom/test-utils`' `act`**: import `act` from `react` (or
62
+ `react-dom/test-utils`'s deprecated re-export, if the project pins an
63
+ older React Testing Library that still expects it) — check the
64
+ project's RTL version compatibility before changing the import broadly.
65
+ - **Any other removed API the upgrade guide lists for this specific
66
+ version jump** (e.g. `ReactDOM.unmountComponentAtNode` and
67
+ `ReactDOM.findDOMNode`, both fully removed in React 19, not merely
68
+ deprecated) — do not assume the 18->19 list above is exhaustive for a
69
+ different version range.
70
+
71
+ ### Step 3: Apply codemods, then hand-fix the rest
72
+
73
+ 1. Run the official `react-codemod`/`types-react-codemod` transforms
74
+ applicable to the identified APIs (e.g. the ref-as-prop and
75
+ `StrictMode`-related codemods) rather than hand-editing every call
76
+ site — codemods cover the mechanical rewrite; review their diff before
77
+ committing.
78
+ 2. Hand-fix what the codemod cannot express (usually the `propTypes` ->
79
+ TypeScript-type conversion and any app-specific wrapper around
80
+ `ReactDOM.render`).
81
+ 3. Update `@types/react`/`@types/react-dom` to the versions matching the
82
+ new React major; a mismatched types package produces type errors
83
+ unrelated to the actual runtime migration — resolve that first before
84
+ chasing other type errors.
85
+
86
+ ### Step 4: Stage the rollout
87
+
88
+ - The React/react-dom version bump itself is one atomic dependency change
89
+ — `package.json` cannot pin two React majors for different directories
90
+ at once, so there is no per-directory rollout of the runtime version.
91
+ What can be sliced by directory/feature is the code-preparation work
92
+ that precedes the bump: removing legacy APIs, running codemods, and
93
+ fixing type errors slice-by-slice with each slice green (type-check,
94
+ lint, test, build) — so that when the dependency bump itself lands, the
95
+ whole tree is already compatible and the bump is a single, low-risk
96
+ commit rather than a large flip that leaves the tree red.
97
+ - Keep the previous major's peer dependencies (libraries pinned to the old
98
+ React major) identified before starting — a library incompatible with
99
+ the new major blocks the upgrade at that dependency, not in app code;
100
+ surface this as a blocker rather than working around it with a version
101
+ override that silences a real incompatibility.
102
+
103
+ ### Step 5: Verify and report
104
+
105
+ ```bash
106
+ keryx test run --changed --strict
107
+ ```
108
+
109
+ Then the full chain: type-check, lint (with `react-hooks` plugin), test,
110
+ build — per `agentProfile.buildCommands`.
111
+
112
+ ```
113
+ Migrated: react 18.3 -> 19.0
114
+ - ReactDOM.render -> createRoot in src/main.tsx
115
+ - removed propTypes from 4 components, added TS prop types
116
+ - ran react19-ref-as-prop codemod across src/components (12 files)
117
+ - @types/react bumped to ^19.0.0
118
+ - full build chain green
119
+ ```
120
+
121
+ ## Rules
122
+
123
+ - ALWAYS read the target version's own upgrade guide before starting —
124
+ do not assume a prior migration's checklist applies unchanged to a
125
+ different version jump.
126
+ - ALWAYS run an official codemod for a mechanical rewrite it covers before
127
+ hand-editing the same pattern across many files.
128
+ - NEVER leave a mix of the old and new API for the same concern in the
129
+ same file (e.g. `ReactDOM.render` in one entry point,
130
+ `createRoot` in another) without flagging it as an inconsistency.
131
+ - NEVER silence a genuine peer-dependency incompatibility with a version
132
+ override/resolution — report it as a blocker.
133
+
134
+ ## Red Flags
135
+
136
+ | Rationalization | Why it is wrong |
137
+ |---|---|
138
+ | "I remember how the last major migration went, I'll skip re-reading the guide" | Removed/changed APIs differ per version jump; acting on a stale mental model misses this version's actual list |
139
+ | "I'll hand-edit all 40 call sites instead of running the codemod" | Slower and more error-prone than the maintained codemod for a mechanical rewrite; run the codemod, then hand-fix only what it cannot express |
140
+ | "This library isn't compatible with the new major yet, I'll force the version with a resolution override" | Hides a real incompatibility that will surface as a runtime bug instead of a clear install-time blocker; report it and let the author decide (wait, replace the library, or patch) |
141
+ | "I'll migrate everything in one big commit, staging slices takes too long" | A single large flip leaves no bisectable, independently-verifiable checkpoint if something breaks partway through a large codebase |
142
+
143
+ ## Verification
144
+
145
+ Do not report the work done until all of the following hold:
146
+
147
+ - Every API on this skill's removed-API checklist that the inventory
148
+ (Step 1) found is either migrated or explicitly listed as out of scope
149
+ with a reason.
150
+ - No file mixes the old and new form of the same migrated API.
151
+ - `@types/react`/`@types/react-dom` versions match the target React major.
152
+ - The full build chain (type-check, lint, test, build) is green after the
153
+ migration.
154
+ - `git status`/the diff reflects only the migration's intended scope —
155
+ no unrelated refactor bundled in.
@@ -0,0 +1,74 @@
1
+ {
2
+ "triggers": {
3
+ "positive": [
4
+ "Upgrade this codebase from React 18 to React 19",
5
+ "Remove all string refs from this project before the React upgrade",
6
+ "Migrate ReactDOM.render to createRoot across the app",
7
+ "Fix the propTypes deprecation warnings after upgrading React",
8
+ "Run the official React codemods for the ref-as-prop change",
9
+ "Update @types/react to match the new React major we just installed"
10
+ ],
11
+ "negative": [
12
+ "Add a settings page that lets a user update their email address",
13
+ "Write unit tests for this date-formatting utility function",
14
+ "Review this component diff for accessibility",
15
+ "The build is failing with a plain TSX syntax error, unrelated to any version upgrade",
16
+ "Bump the pinned Node.js version in package.json engines and the CI workflow",
17
+ "Fix a re-render performance issue in this list component"
18
+ ]
19
+ },
20
+ "scenarios": [
21
+ {
22
+ "id": "read-guide-first",
23
+ "prompt": "We're upgrading from React 18 to React 19. Where should I start?",
24
+ "strictness": "high",
25
+ "expected_behavior": [
26
+ {
27
+ "grader": "judge",
28
+ "rubric": "A correct answer starts by reading the official React upgrade guide/release notes for this specific 18-to-19 jump before touching code, rather than relying on memory of a prior migration, and mentions inventorying the removed/changed APIs and running the official codemods as part of the process rather than hand-editing everything from scratch.",
29
+ "pass_criteria": [
30
+ "Names reading the official React 19 upgrade guide/release notes as the concrete first step for this specific version jump, before any code change — not just 'research first' in the abstract.",
31
+ "Names a concrete mechanism for the mechanical part of the migration: inventorying removed/changed APIs and/or running the official codemods, not just 'update the code carefully'."
32
+ ],
33
+ "fail_criteria": [
34
+ "Recommends starting by just bumping the react/react-dom version and fixing whatever breaks, without first reading the upgrade guide for this specific version jump.",
35
+ "Relies on memory of a previous major-version migration instead of checking the current guide/release notes."
36
+ ]
37
+ }
38
+ ],
39
+ "calibration": {
40
+ "known_right": "Start by reading the official React 19 upgrade guide and release notes — don't rely on how the 17-to-18 jump went, since the set of removed/changed APIs is specific to this version range. From the guide, build an inventory of what this codebase actually uses that's affected: string refs, legacy context (contextTypes/getChildContext), propTypes/defaultProps on function components, ReactDOM.render/hydrate, and the react-dom/test-utils act import, plus anything else the guide calls out as removed rather than merely deprecated (ReactDOM.findDOMNode and unmountComponentAtNode, for instance). Once you know the scope, run the official react-codemod/types-react-codemod transforms for the mechanical parts (the ref-as-prop change in particular has good codemod coverage) and review their diffs before committing, then hand-fix what the codemods can't express — mainly propTypes-to-TypeScript conversions and any custom ReactDOM.render wrapper. Update @types/react/@types/react-dom to match the target major early, since a types/runtime mismatch produces confusing unrelated errors. Only bump the actual react/react-dom dependency once the codebase is already compatible, so the version bump itself is a small, low-risk commit.",
41
+ "known_wrong": "Easiest way to start: just bump react and react-dom to 19 in package.json, run `npm install`, and then run the type-check/build/test suite to see what breaks. Fix the errors as they come up one by one — that's basically what we did for the 17-to-18 upgrade and it worked fine, so the process should be similar this time. No need to read through the whole upgrade guide up front; the compiler and test failures will tell you everything you actually need to fix.",
42
+ "vague": "Start by reading up on what's changed in React 19 before making any changes, then work through the codebase fixing what needs fixing.",
43
+ "subtle_wrong": "Skim the React 19 release notes for the headline breaking changes so you have a general sense of scope, then just bump react/react-dom in package.json and run the build/type-check/test suite to see what actually breaks in this codebase — that's usually faster than working through the full guide line by line, since most projects only hit two or three of the listed changes in practice, and the compiler will point you at the rest."
44
+ }
45
+ },
46
+ {
47
+ "id": "no-forced-resolution",
48
+ "prompt": "One of our dependencies isn't compatible with React 19 yet. Should I just force the version with a package.json resolution override so the install succeeds?",
49
+ "strictness": "high",
50
+ "expected_behavior": [
51
+ {
52
+ "grader": "judge",
53
+ "rubric": "A correct answer says no — forcing the incompatible dependency's peer-dependency requirement with a version override/resolution hides a genuine incompatibility instead of fixing it. It recommends treating the incompatibility as a blocker to report, with real options such as waiting for the library to add support, replacing it, or patching it, rather than silently forcing the install.",
54
+ "pass_criteria": [
55
+ "States plainly that forcing/overriding the peer-dependency version (a package.json resolution override) is not the right fix here.",
56
+ "Names at least one concrete alternative action (wait for the library to add React 19 support, replace the dependency, or patch it via patch-package) instead of only saying 'report it as a blocker'."
57
+ ],
58
+ "fail_criteria": [
59
+ "Recommends forcing the dependency's version via a resolution override in package.json as the fix to make the install succeed, including as a stopgap suggested alongside the real fix."
60
+ ]
61
+ }
62
+ ],
63
+ "calibration": {
64
+ "known_right": "No, don't force it with a resolution override. That would silence a genuine peer-dependency incompatibility — the library may not actually work correctly against React 19's runtime behavior even if npm/yarn stops complaining about the version mismatch, and the failure would surface later as a confusing runtime bug instead of a clear install-time blocker you can act on now. Instead, treat this as a real blocker: check the library's repo/changelog for an open issue or in-progress React 19 support, and if there's a beta/RC release that adds it, that's the real fix. If there's no timeline, your options are to wait and keep the upgrade staged behind this one dependency, replace it with an alternative that already supports React 19, or (if it's small enough and you're willing to maintain it) patch the library yourself via patch-package rather than lying to the package manager about compatibility. Report which of these you're choosing and why, rather than quietly forcing the version.",
65
+ "known_wrong": "Yeah, just force the version with a resolution override in the `resolutions`/`overrides` field of package.json — most of these compatibility warnings are overly conservative peer-dependency ranges that the library maintainers just haven't bumped yet, and the actual code usually still works fine. That gets the install passing again without blocking the rest of the upgrade, and you can always revisit it later if something actually breaks at runtime.",
66
+ "vague": "I wouldn't force it with an override — better to treat the incompatibility as a real blocker and look into your options before working around it.",
67
+ "subtle_wrong": "Don't leave a blanket override in place long-term, but it's reasonable to add a scoped resolution override just for this one package as a temporary unblock so the rest of the team isn't stuck on the upgrade while you sort out a real fix — track it with a follow-up ticket to remove the override once the library ships proper React 19 support, and in the meantime keep an eye on whether anything actually breaks at runtime."
68
+ },
69
+ "anti_patterns": [
70
+ "resolution override"
71
+ ]
72
+ }
73
+ ]
74
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "agents": [],
3
+ "note": "pair removed — flow 317, trials=10 honest gate run: ts-js-node/nodejs-build-fix no-ts-ignore-suppression passRate 0.6 < 0.8 (was 4/5=0.8 at trials=5, the fragility flow 316 review round 1 (R1-14) predicted). Recorded trials named the right direction but never showed the corrected declaration/access code in 4 of 10 answers. deepseek-chat runner+judge gate run, flow 317."
4
+ }