@mrciphersmith/keryx 0.2.163 → 0.3.0
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.
- package/dist/cli.js +87904 -56917
- package/dist/core.js +28418 -18708
- package/package.json +2 -2
- package/src/gdgraph/affected-report.ts +141 -0
- package/src/gdgraph/build.ts +170 -23
- package/src/gdgraph/service.ts +6 -0
- package/src/gdgraph/staleness.ts +253 -45
- package/src/gdskills/bundled/agents/codebase-navigator.md +55 -0
- package/src/gdskills/bundled/agents/design-advisor.md +64 -0
- package/src/gdskills/bundled/agents/docs-maintainer.md +56 -0
- package/src/gdskills/bundled/agents/end-to-end-tester.md +56 -0
- package/src/gdskills/bundled/agents/error-path-auditor.md +57 -0
- package/src/gdskills/bundled/agents/go-build-fixer.md +52 -0
- package/src/gdskills/bundled/agents/go-code-auditor.md +49 -0
- package/src/gdskills/bundled/agents/performance-auditor.md +63 -0
- package/src/gdskills/bundled/agents/python-build-fixer.md +52 -0
- package/src/gdskills/bundled/agents/python-code-auditor.md +49 -0
- package/src/gdskills/bundled/agents/refactoring-steward.md +61 -0
- package/src/gdskills/bundled/agents/security-auditor.md +62 -0
- package/src/gdskills/bundled/agents/test-first-driver.md +61 -0
- package/src/gdskills/bundled/agents/work-planner.md +62 -0
- package/src/gdskills/bundled/install-manifest.json +530 -0
- package/src/gdskills/bundled/rules/core/skill-lifecycle.mdc +29 -1
- package/src/gdskills/bundled/rules/core/skills-storage-workflow.mdc +2 -2
- package/src/gdskills/bundled/skills/review/code-style-review/SKILL.md +1 -1
- package/src/gdskills/bundled/skills/review/review-orchestrator/SKILL.md +74 -246
- package/src/gdskills/bundled/skills/review/review-orchestrator/output-contract.schema.json +19 -0
- package/src/gdskills/bundled/skills/review/review-orchestrator/reviewer-finding.schema.json +10 -0
- package/src/gdskills/bundled/skills/review/review-orchestrator/reviewer-input.schema.json +5 -0
- package/src/gdskills/bundled/skills/review/review-orchestrator/templates/pr-comment-backend.md +50 -0
- package/src/gdskills/bundled/skills/review/review-orchestrator/templates/pr-comment-frontend.md +52 -0
- package/src/gdskills/bundled/skills/review/review-orchestrator/templates/review-report.md +143 -0
- package/src/gdskills/bundled/stacks/go/agent-refs.json +3 -0
- package/src/gdskills/bundled/stacks/go/governance/eval.json +1745 -0
- package/src/gdskills/bundled/stacks/go/governance/scout.json +31 -0
- package/src/gdskills/bundled/stacks/go/pack.json +41 -0
- package/src/gdskills/bundled/stacks/go/rules/coding-style.mdc +85 -0
- package/src/gdskills/bundled/stacks/go/rules/patterns.mdc +65 -0
- package/src/gdskills/bundled/stacks/go/rules/security.mdc +73 -0
- package/src/gdskills/bundled/stacks/go/rules/testing.mdc +68 -0
- package/src/gdskills/bundled/stacks/go/skills/go-build-fix/SKILL.md +138 -0
- package/src/gdskills/bundled/stacks/go/skills/go-build-fix/evals.json +75 -0
- package/src/gdskills/bundled/stacks/go/skills/go-code-review/SKILL.md +121 -0
- package/src/gdskills/bundled/stacks/go/skills/go-code-review/evals.json +72 -0
- package/src/gdskills/bundled/stacks/go/skills/go-implementation/SKILL.md +122 -0
- package/src/gdskills/bundled/stacks/go/skills/go-implementation/evals.json +76 -0
- package/src/gdskills/bundled/stacks/go/skills/go-testing/SKILL.md +126 -0
- package/src/gdskills/bundled/stacks/go/skills/go-testing/evals.json +73 -0
- package/src/gdskills/bundled/stacks/python/agent-refs.json +3 -0
- package/src/gdskills/bundled/stacks/python/governance/eval.json +1758 -0
- package/src/gdskills/bundled/stacks/python/governance/scout.json +34 -0
- package/src/gdskills/bundled/stacks/python/pack.json +41 -0
- package/src/gdskills/bundled/stacks/python/rules/coding-style.mdc +63 -0
- package/src/gdskills/bundled/stacks/python/rules/patterns.mdc +88 -0
- package/src/gdskills/bundled/stacks/python/rules/security.mdc +84 -0
- package/src/gdskills/bundled/stacks/python/rules/testing.mdc +77 -0
- package/src/gdskills/bundled/stacks/python/skills/python-build-fix/SKILL.md +144 -0
- package/src/gdskills/bundled/stacks/python/skills/python-build-fix/evals.json +74 -0
- package/src/gdskills/bundled/stacks/python/skills/python-code-review/SKILL.md +155 -0
- package/src/gdskills/bundled/stacks/python/skills/python-code-review/evals.json +72 -0
- package/src/gdskills/bundled/stacks/python/skills/python-implementation/SKILL.md +143 -0
- package/src/gdskills/bundled/stacks/python/skills/python-implementation/evals.json +78 -0
- package/src/gdskills/bundled/stacks/python/skills/python-testing/SKILL.md +132 -0
- package/src/gdskills/bundled/stacks/python/skills/python-testing/evals.json +73 -0
- package/src/gdskills/bundled/stacks/react/agent-refs.json +4 -0
- package/src/gdskills/bundled/stacks/react/governance/eval.json +2188 -0
- package/src/gdskills/bundled/stacks/react/governance/scout.json +40 -0
- package/src/gdskills/bundled/stacks/react/pack.json +42 -0
- package/src/gdskills/bundled/stacks/react/rules/coding-style.mdc +58 -0
- package/src/gdskills/bundled/stacks/react/rules/patterns.mdc +79 -0
- package/src/gdskills/bundled/stacks/react/rules/security.mdc +70 -0
- package/src/gdskills/bundled/stacks/react/rules/testing.mdc +60 -0
- package/src/gdskills/bundled/stacks/react/skills/react-build-fix/SKILL.md +139 -0
- package/src/gdskills/bundled/stacks/react/skills/react-build-fix/evals.json +72 -0
- package/src/gdskills/bundled/stacks/react/skills/react-code-review/SKILL.md +148 -0
- package/src/gdskills/bundled/stacks/react/skills/react-code-review/evals.json +74 -0
- package/src/gdskills/bundled/stacks/react/skills/react-implementation/SKILL.md +140 -0
- package/src/gdskills/bundled/stacks/react/skills/react-implementation/evals.json +74 -0
- package/src/gdskills/bundled/stacks/react/skills/react-testing/SKILL.md +142 -0
- package/src/gdskills/bundled/stacks/react/skills/react-testing/evals.json +83 -0
- package/src/gdskills/bundled/stacks/react/skills/react-upgrade-migration/SKILL.md +155 -0
- package/src/gdskills/bundled/stacks/react/skills/react-upgrade-migration/evals.json +74 -0
- package/src/gdskills/bundled/stacks/ts-js-node/agent-refs.json +4 -0
- package/src/gdskills/bundled/stacks/ts-js-node/governance/eval.json +2155 -0
- package/src/gdskills/bundled/stacks/ts-js-node/governance/scout.json +40 -0
- package/src/gdskills/bundled/stacks/ts-js-node/pack.json +41 -0
- package/src/gdskills/bundled/stacks/ts-js-node/rules/coding-style.mdc +73 -0
- package/src/gdskills/bundled/stacks/ts-js-node/rules/patterns.mdc +61 -0
- package/src/gdskills/bundled/stacks/ts-js-node/rules/security.mdc +71 -0
- package/src/gdskills/bundled/stacks/ts-js-node/rules/testing.mdc +63 -0
- package/src/gdskills/bundled/stacks/ts-js-node/skills/nodejs-build-fix/SKILL.md +137 -0
- package/src/gdskills/bundled/stacks/ts-js-node/skills/nodejs-build-fix/evals.json +73 -0
- package/src/gdskills/bundled/stacks/ts-js-node/skills/nodejs-code-review/SKILL.md +124 -0
- package/src/gdskills/bundled/stacks/ts-js-node/skills/nodejs-code-review/evals.json +74 -0
- package/src/gdskills/bundled/stacks/ts-js-node/skills/nodejs-esm-migration/SKILL.md +152 -0
- package/src/gdskills/bundled/stacks/ts-js-node/skills/nodejs-esm-migration/evals.json +71 -0
- package/src/gdskills/bundled/stacks/ts-js-node/skills/nodejs-implementation/SKILL.md +127 -0
- package/src/gdskills/bundled/stacks/ts-js-node/skills/nodejs-implementation/evals.json +72 -0
- package/src/gdskills/bundled/stacks/ts-js-node/skills/nodejs-testing/SKILL.md +134 -0
- package/src/gdskills/bundled/stacks/ts-js-node/skills/nodejs-testing/evals.json +70 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"query": "Use when building or changing a React component, hook, or form in a .tsx/.jsx file -- covers function components, deriving state instead of syncing it with effects, Suspense and error boundaries, form Actions (useActionState, useOptimistic, useTransition), ref-as-prop, and React Compiler-aware memoization.",
|
|
4
|
+
"decision": "fork",
|
|
5
|
+
"topMatch": "react/react-build-fix",
|
|
6
|
+
"recordedAt": "2026-09-24T12:00:07.391Z",
|
|
7
|
+
"skillName": "react-implementation",
|
|
8
|
+
"justification": "top match react/react-build-fix (0.32) is a build/lint/type-error fix skill for already-broken code, not an authoring workflow for new component/hook code; react-code-review (0.24) is read-only review; react-testing (0.18) is test authoring, not component authoring. Below use threshold 0.55; none is a substitute for a React component-authoring skill, so create."
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"query": "Use when a React component's test suite needs writing, extending, or fixing with React Testing Library -- covers query-by-role/label, user-event interaction, async findBy/waitFor, network mocking at the request boundary, and act warnings, on top of the project's Vitest or Jest runner.",
|
|
12
|
+
"decision": "fork",
|
|
13
|
+
"topMatch": "ts-js-node/nodejs-testing",
|
|
14
|
+
"recordedAt": "2026-09-24T12:00:14.111Z",
|
|
15
|
+
"skillName": "react-testing",
|
|
16
|
+
"justification": "top match ts-js-node/nodejs-testing (0.46) is the generic TS/Node testing skill with no React component, JSX rendering, or React Testing Library query/interaction guidance; review-testing-practices (0.29) is read-only review, not authoring. Below use threshold 0.55; neither is a substitute for a React-specific RTL authoring skill, so create."
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"query": "Use when reviewing changed React component or hook code (.tsx/.jsx) for Rules of Hooks violations, effect dependency bugs, stale closures, key misuse, in-place state mutation, re-render hot spots, accessibility gaps, and dangerouslySetInnerHTML/URL XSS sinks -- read-only, no MobX store review and no repository convention-doc lookup.",
|
|
20
|
+
"decision": "create",
|
|
21
|
+
"topMatch": "react/react-implementation",
|
|
22
|
+
"recordedAt": "2026-09-24T12:00:23.775Z",
|
|
23
|
+
"skillName": "react-code-review"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"query": "Use when a React component fails to type-check, lint, or build -- JSX/TSX prop and children typing errors, event handler and ref types after the React 19 types changes, eslint-plugin-react-hooks failures, and Vite/webpack/Next.js bundler build failures or hydration mismatches. Fixes the root cause, never disables the hooks lint rule or casts to any.",
|
|
27
|
+
"decision": "fork",
|
|
28
|
+
"topMatch": "ts-js-node/nodejs-build-fix",
|
|
29
|
+
"recordedAt": "2026-09-24T12:00:23.917Z",
|
|
30
|
+
"skillName": "react-build-fix",
|
|
31
|
+
"justification": "top match ts-js-node/nodejs-build-fix (0.32) is the generic TS/Node build-fix skill with no JSX/TSX prop typing, react-hooks lint, or hydration-mismatch guidance; react-implementation (0.25) is an authoring skill, not a fix skill. Below use threshold 0.55; neither is a substitute for a React-specific build-fix skill, so create."
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"query": "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.",
|
|
35
|
+
"decision": "create",
|
|
36
|
+
"topMatch": "react/react-build-fix",
|
|
37
|
+
"recordedAt": "2026-09-24T12:00:24.073Z",
|
|
38
|
+
"skillName": "react-upgrade-migration"
|
|
39
|
+
}
|
|
40
|
+
]
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "react",
|
|
3
|
+
"family": "framework",
|
|
4
|
+
"extends": "ts-js-node",
|
|
5
|
+
"modules": ["react-rules", "react-skills"],
|
|
6
|
+
"detectionMarkers": ["react"],
|
|
7
|
+
"provenance": {
|
|
8
|
+
"origin": "authored",
|
|
9
|
+
"sourceRef": "flow 314, Wave 4 batch 1"
|
|
10
|
+
},
|
|
11
|
+
"stability": "experimental",
|
|
12
|
+
"skills": {
|
|
13
|
+
"implement": ["react-implementation"],
|
|
14
|
+
"test": ["react-testing"],
|
|
15
|
+
"review": ["react-code-review"],
|
|
16
|
+
"build-fix": ["react-build-fix"],
|
|
17
|
+
"migrate": ["react-upgrade-migration"]
|
|
18
|
+
},
|
|
19
|
+
"agentProfile": {
|
|
20
|
+
"displayName": "React",
|
|
21
|
+
"auditFocus": [
|
|
22
|
+
"Rules of Hooks violations and conditional/loop-nested hook calls",
|
|
23
|
+
"effect dependency arrays that are wrong, missing, or paper over a needed effect",
|
|
24
|
+
"state or props mutated in place instead of replaced",
|
|
25
|
+
"keys on list items that are array index or missing where order can change",
|
|
26
|
+
"accessibility of interactive elements: semantic tags, labels, focus management",
|
|
27
|
+
"dangerouslySetInnerHTML or unsanitized user data reaching a DOM sink"
|
|
28
|
+
],
|
|
29
|
+
"buildCommands": [
|
|
30
|
+
"the project's type-check script (e.g. tsc --noEmit, or its package.json equivalent)",
|
|
31
|
+
"the project's lint script with the react-hooks plugin enabled",
|
|
32
|
+
"the project's test script (Vitest/Jest run of React Testing Library suites)",
|
|
33
|
+
"the project's bundler build (Vite/webpack/Next.js production build)"
|
|
34
|
+
],
|
|
35
|
+
"fixGuardrails": [
|
|
36
|
+
"never disable or downgrade an eslint-plugin-react-hooks rule to silence a warning",
|
|
37
|
+
"never cast a component's props, ref, or event handler to any to satisfy the type checker",
|
|
38
|
+
"never delete or loosen a failing assertion in a React Testing Library test to make it pass",
|
|
39
|
+
"never wrap a component in unnecessary memo/useMemo/useCallback as a build-fix when the project runs the React Compiler"
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
---
|
|
2
|
+
extends: common
|
|
3
|
+
paths: ["**/*.tsx", "**/*.jsx"]
|
|
4
|
+
metadata:
|
|
5
|
+
origin: authored
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# React coding style
|
|
9
|
+
|
|
10
|
+
Narrows `ts-js-node`'s coding style to React component files. Applies only
|
|
11
|
+
to `*.tsx`/`*.jsx` — non-component TypeScript/JavaScript still
|
|
12
|
+
comes from `ts-js-node`'s own coding-style rule, not this file.
|
|
13
|
+
|
|
14
|
+
## Components
|
|
15
|
+
|
|
16
|
+
- Write function components; a class component is a maintenance
|
|
17
|
+
regression unless the project has no alternative (e.g. an error boundary,
|
|
18
|
+
which still requires a class in current React).
|
|
19
|
+
- One component per file for anything exported and reused; a small private
|
|
20
|
+
helper component used only inside its parent file can stay local.
|
|
21
|
+
- Name a component file after the component it exports (`UserCard.tsx`
|
|
22
|
+
exports `UserCard`), `PascalCase` for the component, `camelCase` for
|
|
23
|
+
hooks (`useUserCard`) and plain functions.
|
|
24
|
+
- Destructure props in the function signature; do not thread a whole
|
|
25
|
+
`props` object through the body when only a few fields are used.
|
|
26
|
+
- Type props with an explicit `interface`/`type`, not `React.FC` — `FC`'s
|
|
27
|
+
implicit `children` and weaker generic inference are a known footgun the
|
|
28
|
+
current React types intentionally do not paper over.
|
|
29
|
+
|
|
30
|
+
## Hooks and state
|
|
31
|
+
|
|
32
|
+
- Call hooks only at the top level of a component or another hook, never
|
|
33
|
+
inside a condition, loop, or nested function — the react-hooks lint rule
|
|
34
|
+
enforces this; do not add an eslint-disable line to route around it (see
|
|
35
|
+
`rules/security.mdc` and `react-build-fix`'s guardrails).
|
|
36
|
+
- Order hooks so the same hooks run in the same order on every render;
|
|
37
|
+
branch inside a hook's own logic (`if (x) return early` after the hook
|
|
38
|
+
call), not around the hook call itself.
|
|
39
|
+
- Prefer several focused `useState` calls over one large state object when
|
|
40
|
+
the fields update independently; group into one state (or `useReducer`)
|
|
41
|
+
only when fields change together.
|
|
42
|
+
- Name a custom hook's return values by what they mean in the caller
|
|
43
|
+
(`{ data, isLoading, error }`), not by the hook's internal variable
|
|
44
|
+
names.
|
|
45
|
+
|
|
46
|
+
## Imports and structure
|
|
47
|
+
|
|
48
|
+
- Group imports: React/framework, third-party, then local — the same
|
|
49
|
+
ordering `ts-js-node`'s coding-style rule already asks for; nothing
|
|
50
|
+
React-specific changes the grouping itself.
|
|
51
|
+
- Import hooks and utilities by name (`import { useState } from "react"`);
|
|
52
|
+
do not import the whole `React` namespace unless the project's JSX
|
|
53
|
+
transform requires it (check the project's `tsconfig`/bundler config —
|
|
54
|
+
the classic transform needs `import React from "react"` in scope, the
|
|
55
|
+
automatic transform introduced in React 17 does not).
|
|
56
|
+
- Co-locate a component's own styles, tests, and small subcomponents next
|
|
57
|
+
to it under one directory when the project already uses that layout;
|
|
58
|
+
match the existing convention rather than introducing a new one.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
---
|
|
2
|
+
extends: common
|
|
3
|
+
paths: ["**/*.tsx", "**/*.jsx"]
|
|
4
|
+
metadata:
|
|
5
|
+
origin: authored
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# React patterns
|
|
9
|
+
|
|
10
|
+
Idiomatic component design and anti-patterns for React 19-era code,
|
|
11
|
+
narrowed to `*.tsx`/`*.jsx`.
|
|
12
|
+
|
|
13
|
+
## Derive, don't sync
|
|
14
|
+
|
|
15
|
+
- If a value can be computed from existing props/state during render,
|
|
16
|
+
compute it during render — do not `useState` + `useEffect` to mirror one
|
|
17
|
+
piece of state into another. A `useEffect` that only calls `setState`
|
|
18
|
+
from a change in props/state is almost always replaceable by a plain
|
|
19
|
+
computed value (optionally memoized with `useMemo` when the computation
|
|
20
|
+
is expensive).
|
|
21
|
+
- Reset local state on a prop change by giving the component a `key` tied
|
|
22
|
+
to that prop (React unmounts and remounts a fresh component), not by
|
|
23
|
+
watching the prop in an effect and calling a setter.
|
|
24
|
+
- Effects are for synchronizing with something outside React: the DOM,
|
|
25
|
+
a subscription, a network request, browser storage, a third-party widget.
|
|
26
|
+
An effect with no external system on the other end is a sign the logic
|
|
27
|
+
belongs in an event handler or in render itself.
|
|
28
|
+
|
|
29
|
+
## Lists and keys
|
|
30
|
+
|
|
31
|
+
- Every element in a list rendered with `.map` gets a stable `key` drawn
|
|
32
|
+
from the data (an id), never the array index, unless the list is
|
|
33
|
+
provably static and never reordered/filtered/inserted into.
|
|
34
|
+
- Do not use `key` as a prop for anything other than list identity inside
|
|
35
|
+
the component receiving it — reading `props.key` returns `undefined`.
|
|
36
|
+
|
|
37
|
+
## Forms and events
|
|
38
|
+
|
|
39
|
+
- Prefer a controlled input (`value` + `onChange`) for anything the
|
|
40
|
+
component needs to validate, transform, or react to as the user types;
|
|
41
|
+
use an uncontrolled input (`defaultValue` + a ref) only for simple
|
|
42
|
+
fire-and-forget fields where per-keystroke reactivity is not needed.
|
|
43
|
+
- For form submission with a pending/error/optimistic result, prefer an
|
|
44
|
+
Action (a function passed to a `<form action={...}>`,
|
|
45
|
+
`useActionState`, and `useOptimistic` for the optimistic update) over
|
|
46
|
+
hand-rolled `isSubmitting`/`error` state plus a submit handler that calls
|
|
47
|
+
`preventDefault` — the Actions API already tracks pending and error state
|
|
48
|
+
and integrates with Suspense.
|
|
49
|
+
- Reach for `useTransition` to mark a state update as non-urgent (keeps the
|
|
50
|
+
UI responsive during an expensive re-render) rather than debouncing or
|
|
51
|
+
deferring the update by hand.
|
|
52
|
+
|
|
53
|
+
## Refs, Suspense, and composition
|
|
54
|
+
|
|
55
|
+
- In React 19, `ref` is an ordinary prop on function components — no
|
|
56
|
+
`forwardRef` wrapper is needed for a new component that accepts a ref.
|
|
57
|
+
Keep `forwardRef` only in code that must still support pre-19 React.
|
|
58
|
+
- Read an async resource inside render with the `use` API (for a promise
|
|
59
|
+
or a context) instead of stuffing the result into state via an effect;
|
|
60
|
+
pair it with a `Suspense` boundary for the pending state and an error
|
|
61
|
+
boundary for the rejected state.
|
|
62
|
+
- Prefer composition (children, render props, or a small set of focused
|
|
63
|
+
components) over one component branching on a `type`/`variant` prop into
|
|
64
|
+
unrelated render trees.
|
|
65
|
+
- In a framework that supports server and client components, keep data
|
|
66
|
+
fetching and secrets in server components; a component needs
|
|
67
|
+
`"use client"` only once it uses state, effects, refs, or browser-only
|
|
68
|
+
APIs — do not mark a whole subtree client just because one leaf needs it.
|
|
69
|
+
|
|
70
|
+
## Compiler awareness
|
|
71
|
+
|
|
72
|
+
- When the project has the React Compiler enabled (check its babel/swc
|
|
73
|
+
config or `babel-plugin-react-compiler`/`react-compiler` dependency),
|
|
74
|
+
do not hand-add `memo`, `useMemo`, or `useCallback` purely to prevent
|
|
75
|
+
re-renders — the compiler already memoizes automatically, and manual
|
|
76
|
+
memoization on compiled code is dead weight that can also mask a bug the
|
|
77
|
+
compiler would otherwise have caught. Without the compiler, manual
|
|
78
|
+
memoization is still a valid, deliberate optimization for a measured
|
|
79
|
+
re-render cost.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
extends: common
|
|
3
|
+
paths: ["**/*.tsx", "**/*.jsx"]
|
|
4
|
+
metadata:
|
|
5
|
+
origin: authored
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# React security
|
|
9
|
+
|
|
10
|
+
Stack-specific risks for React component files (`*.tsx`/`*.jsx`),
|
|
11
|
+
narrowing `ts-js-node`'s generic security rule. Not a general OWASP list —
|
|
12
|
+
only the sinks React's rendering model makes reachable.
|
|
13
|
+
|
|
14
|
+
## `dangerouslySetInnerHTML`
|
|
15
|
+
|
|
16
|
+
- Treat `dangerouslySetInnerHTML` as the default XSS sink: any user-, API-,
|
|
17
|
+
or CMS-sourced string passed to it renders as live HTML/JS. Avoid it —
|
|
18
|
+
render the content as text/JSX instead — unless the project genuinely
|
|
19
|
+
needs to render rich HTML (e.g. a CMS body).
|
|
20
|
+
- When it is unavoidable, sanitize the string through the project's own
|
|
21
|
+
sanitizer (e.g. DOMPurify) immediately before the prop is built, not
|
|
22
|
+
earlier in the pipeline where a later edit could drop the sanitize step;
|
|
23
|
+
never pass a raw string straight through.
|
|
24
|
+
- Never build the `__html` value by concatenating user input into a
|
|
25
|
+
template string of markup — that is the same sink with extra steps.
|
|
26
|
+
|
|
27
|
+
## URLs from user data
|
|
28
|
+
|
|
29
|
+
- Reject or scheme-allowlist a URL that becomes an `href`/`src` when it
|
|
30
|
+
comes from user input, a query param, or an API response —
|
|
31
|
+
`javascript:`, `data:`, and `vbscript:` schemes execute on click/load.
|
|
32
|
+
Validate against an allowlist (`http:`, `https:`, `mailto:`) before
|
|
33
|
+
binding it to the element.
|
|
34
|
+
- The same applies to a dynamic `src` on `<img>`, `<iframe>`, or `<script>`
|
|
35
|
+
built from anything not fully controlled by the app.
|
|
36
|
+
|
|
37
|
+
## Secrets and client bundles
|
|
38
|
+
|
|
39
|
+
- Anything read via the framework's public-env convention (e.g. a
|
|
40
|
+
`NEXT_PUBLIC_`/`VITE_`/`REACT_APP_`-prefixed variable, or any value the
|
|
41
|
+
bundler inlines into client output) ships in the browser bundle in plain
|
|
42
|
+
text — never put an API secret, private key, or unscoped token behind
|
|
43
|
+
one of these prefixes. A value that must stay server-only belongs in a
|
|
44
|
+
server component, a route handler/API route, or a server function/
|
|
45
|
+
action, never a client component or a plain (non-prefixed-and-still-
|
|
46
|
+
bundled) constant imported into client code.
|
|
47
|
+
- Grep a diff for the project's public-env prefix before approving a new
|
|
48
|
+
environment variable used inside a client component.
|
|
49
|
+
- A Server Function/Action is not merely a safe home for a server-only
|
|
50
|
+
value — calling it from the client turns it into a public, directly
|
|
51
|
+
reachable HTTP endpoint (its own route, invocable by anything that can
|
|
52
|
+
reach the app, not only through the form/button that references it in
|
|
53
|
+
the source). It gets none of the caller-identity or authorization
|
|
54
|
+
checks a UI-only flow implies; each Server Function/Action must
|
|
55
|
+
authenticate the caller, authorize the specific operation, and validate
|
|
56
|
+
every argument itself, exactly as a hand-written API route would,
|
|
57
|
+
before it touches data or a mutation.
|
|
58
|
+
|
|
59
|
+
## Third-party scripts and client-side auth
|
|
60
|
+
|
|
61
|
+
- Loading a third-party script by injecting a `<script>` tag with a
|
|
62
|
+
dynamic or user-influenced `src` is the same class of risk as an
|
|
63
|
+
unvalidated `href`/`src` above; pin third-party script URLs to a fixed,
|
|
64
|
+
reviewed list.
|
|
65
|
+
- Do not gate a protected view purely on client-side state (a store flag,
|
|
66
|
+
a decoded-but-unverified JWT, a route guard component) — a client
|
|
67
|
+
component can always be bypassed by disabling JavaScript or calling the
|
|
68
|
+
underlying API directly. Client-side checks are UX only; the real
|
|
69
|
+
authorization check must happen server-side (server component, route
|
|
70
|
+
handler, or backend).
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
extends: common
|
|
3
|
+
paths: ["**/*.tsx", "**/*.jsx"]
|
|
4
|
+
metadata:
|
|
5
|
+
origin: authored
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# React testing
|
|
9
|
+
|
|
10
|
+
Test layout, runner, and assertion conventions for React component files
|
|
11
|
+
(`*.tsx`/`*.jsx`), narrowing `ts-js-node`'s generic testing rule.
|
|
12
|
+
|
|
13
|
+
## Layout and runner
|
|
14
|
+
|
|
15
|
+
- Use the project's already-configured runner (Vitest or Jest) and React
|
|
16
|
+
Testing Library (`@testing-library/react` + `@testing-library/user-event`)
|
|
17
|
+
— do not introduce Enzyme or a shallow-render helper into a project that
|
|
18
|
+
does not already use one.
|
|
19
|
+
- Co-locate a component's test next to it (`UserCard.test.tsx`) when the
|
|
20
|
+
project already follows that layout, or under a mirrored `__tests__`
|
|
21
|
+
tree when that is the existing convention; match, do not introduce.
|
|
22
|
+
|
|
23
|
+
## Queries and interaction
|
|
24
|
+
|
|
25
|
+
- Query by role/label/text the way a user or assistive technology would
|
|
26
|
+
(`getByRole`, `getByLabelText`, `getByText`) — reach for `data-testid`
|
|
27
|
+
only when no accessible query exists, and treat that as a sign the
|
|
28
|
+
markup itself may be missing an accessible name.
|
|
29
|
+
- Never assert on a component's internal state, instance fields, or
|
|
30
|
+
implementation details (no reaching into a ref's internals, no snapshot
|
|
31
|
+
of a component's private props) — assert on rendered output and
|
|
32
|
+
behavior only.
|
|
33
|
+
- Drive interaction through `@testing-library/user-event`
|
|
34
|
+
(`userEvent.click`/`.type`/`.tab`), not `fireEvent`, unless the project
|
|
35
|
+
is pinned to an older `user-event` major that cannot express the
|
|
36
|
+
interaction — `user-event` fires the fuller sequence of browser events a
|
|
37
|
+
real interaction would.
|
|
38
|
+
|
|
39
|
+
## Async and network
|
|
40
|
+
|
|
41
|
+
- Wait for async UI with `findBy*` queries or `waitFor`, never a manual
|
|
42
|
+
`setTimeout`/`sleep` — an arbitrary delay is both slow and flaky under
|
|
43
|
+
load.
|
|
44
|
+
- Mock network calls at the request boundary (an MSW handler, or the
|
|
45
|
+
project's existing equivalent) rather than mocking the component's own
|
|
46
|
+
data-fetching function — a boundary mock still exercises the real
|
|
47
|
+
fetch/parse/error-handling code path.
|
|
48
|
+
- Wrap a state update triggered outside React Testing Library's own query
|
|
49
|
+
helpers (e.g. a manually invoked callback) in `act` only when RTL's
|
|
50
|
+
built-in wrapping does not already cover it; an `act` warning is a
|
|
51
|
+
signal to await the right query, not to silence the console.
|
|
52
|
+
|
|
53
|
+
## Coverage expectations
|
|
54
|
+
|
|
55
|
+
- Cover the rendered states a component can be in: initial/loading,
|
|
56
|
+
success, error, and empty, plus any conditional branch a prop or piece
|
|
57
|
+
of state gates.
|
|
58
|
+
- For a custom hook with logic worth testing on its own, use
|
|
59
|
+
`renderHook` from `@testing-library/react` rather than mounting a
|
|
60
|
+
throwaway component to exercise it.
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: react-build-fix
|
|
3
|
+
description: "Use when a React component fails to type-check, lint, or build -- JSX/TSX prop and children typing errors, event handler and ref types after the React 19 types changes, eslint-plugin-react-hooks failures, and Vite/webpack/Next.js bundler build failures or hydration mismatches. Fixes the root cause, never disables the hooks lint rule or casts to any."
|
|
4
|
+
triggers:
|
|
5
|
+
- "fix this tsx type error"
|
|
6
|
+
- "react-hooks lint is failing"
|
|
7
|
+
- "vite build is failing on this component"
|
|
8
|
+
- "hydration mismatch error"
|
|
9
|
+
- "ref type error after upgrading react types"
|
|
10
|
+
- "children prop type error"
|
|
11
|
+
metadata:
|
|
12
|
+
origin: authored
|
|
13
|
+
category: build-fix
|
|
14
|
+
version: "1.0.0"
|
|
15
|
+
compatible_harnesses: "claude,codex,cursor,zed,opencode"
|
|
16
|
+
license: "MIT"
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
# React build fix
|
|
20
|
+
|
|
21
|
+
Fix a failing type-check, lint, or bundler build caused by React component
|
|
22
|
+
code. Scoped to failures that originate in `.tsx`/`.jsx` component code or
|
|
23
|
+
its JSX/hooks typing — a failure with no React-specific cause (a plain
|
|
24
|
+
module import error, a Node config issue) is `ts-js-node`'s build-fix
|
|
25
|
+
skill, not this one.
|
|
26
|
+
|
|
27
|
+
## Workflow
|
|
28
|
+
|
|
29
|
+
### Step 1: Reproduce and classify
|
|
30
|
+
|
|
31
|
+
Run, in order, until one fails (use `agentProfile.buildCommands` from
|
|
32
|
+
`pack.json` as the starting point, adjusted to the project's actual
|
|
33
|
+
scripts):
|
|
34
|
+
|
|
35
|
+
1. Type-check (`tsc --noEmit` or the project's script).
|
|
36
|
+
2. Lint, with `eslint-plugin-react-hooks` enabled.
|
|
37
|
+
3. Test run.
|
|
38
|
+
4. Bundler build (Vite/webpack/Next.js).
|
|
39
|
+
|
|
40
|
+
Read the first failure's full message — do not guess from the file name.
|
|
41
|
+
Classify it as: JSX/TSX typing (props, children, events, refs), hooks-lint
|
|
42
|
+
(`react-hooks/rules-of-hooks`, `react-hooks/exhaustive-deps`), or bundler/
|
|
43
|
+
hydration.
|
|
44
|
+
|
|
45
|
+
### Step 2: Fix JSX/TSX typing errors
|
|
46
|
+
|
|
47
|
+
- Props typing error: fix the `interface`/`type` to match how the
|
|
48
|
+
component is actually used, or fix the call site — do not widen the
|
|
49
|
+
prop type to `any`/`unknown` to make the error disappear.
|
|
50
|
+
- Children typing: type `children` explicitly (`React.ReactNode` for
|
|
51
|
+
arbitrary children, a narrower type when only specific children are
|
|
52
|
+
valid) rather than accepting `any`.
|
|
53
|
+
- Event handler typing: use the specific React event type for the element
|
|
54
|
+
and event (`React.ChangeEvent<HTMLInputElement>`,
|
|
55
|
+
`React.MouseEvent<HTMLButtonElement>`), not a hand-rolled loose type.
|
|
56
|
+
- Ref typing after the React 19 types change (`ref` as an ordinary prop
|
|
57
|
+
on function components): type it as
|
|
58
|
+
`React.Ref<ElementType>`/`React.RefObject<ElementType>` matching what
|
|
59
|
+
the component actually forwards; if the project is still on
|
|
60
|
+
`forwardRef`, match `forwardRef`'s own generic signature instead of
|
|
61
|
+
mixing the two patterns in one component.
|
|
62
|
+
|
|
63
|
+
### Step 3: Fix hooks-lint errors
|
|
64
|
+
|
|
65
|
+
- `rules-of-hooks` violation: restructure so the hook call is
|
|
66
|
+
unconditional and top-level — move the condition inside the hook's own
|
|
67
|
+
logic, or split into two components/hooks. Never add an
|
|
68
|
+
`eslint-disable-next-line react-hooks/rules-of-hooks` comment.
|
|
69
|
+
- `exhaustive-deps` violation: add the missing reactive dependency, or, if
|
|
70
|
+
the value is intentionally stable (a ref, a dispatch function, a value
|
|
71
|
+
the author has confirmed never needs to trigger the effect), use the
|
|
72
|
+
lint rule's own escape hatch documented for that case rather than a
|
|
73
|
+
blanket disable comment — and only after confirming the value truly
|
|
74
|
+
cannot change in a way the effect needs to react to.
|
|
75
|
+
|
|
76
|
+
### Step 4: Fix bundler and hydration failures
|
|
77
|
+
|
|
78
|
+
- Bundler build failure: read the actual bundler error (missing export,
|
|
79
|
+
bad dynamic import, unsupported syntax for the configured target) and
|
|
80
|
+
fix the source or import, not the bundler config, unless the config
|
|
81
|
+
itself is provably wrong for the project's stated target.
|
|
82
|
+
- Hydration mismatch: find what differs between server and client render
|
|
83
|
+
— a `Date`/`Math.random`/`typeof window` branch evaluated during render,
|
|
84
|
+
locale/timezone-dependent formatting, or state initialized differently
|
|
85
|
+
on each side. Fix by making the server and first client render produce
|
|
86
|
+
identical output (move the divergent value into an effect that runs
|
|
87
|
+
post-hydration, or pass it down as a prop already resolved server-side)
|
|
88
|
+
— do not silence the warning by wrapping the whole tree in a
|
|
89
|
+
client-only guard unless the divergent content is genuinely
|
|
90
|
+
client-only.
|
|
91
|
+
|
|
92
|
+
### Step 5: Verify and report
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
keryx test run --changed --strict
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Re-run the exact command that failed in Step 1 and confirm it now exits 0,
|
|
99
|
+
then re-run the full chain (type-check, lint, test, build) once to confirm
|
|
100
|
+
the fix did not break an earlier step.
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
Fixed: src/components/UserCard.tsx:18 — onSave typed as
|
|
104
|
+
React.MouseEvent<HTMLButtonElement> to match the actual click handler
|
|
105
|
+
signature; tsc --noEmit now passes.
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Rules
|
|
109
|
+
|
|
110
|
+
- ALWAYS fix the root cause with the smallest change that resolves it.
|
|
111
|
+
- NEVER disable or downgrade `eslint-plugin-react-hooks` rules to make a
|
|
112
|
+
lint failure disappear.
|
|
113
|
+
- NEVER cast a prop, ref, or event to `any`/`as any` to silence a type
|
|
114
|
+
error.
|
|
115
|
+
- NEVER delete or loosen a failing test assertion to make a build/test
|
|
116
|
+
step pass.
|
|
117
|
+
- Stop after 3 fix iterations on the same failure and report what remains,
|
|
118
|
+
rather than escalating to a disable/cast/deletion.
|
|
119
|
+
|
|
120
|
+
## Red Flags
|
|
121
|
+
|
|
122
|
+
| Rationalization | Why it is wrong |
|
|
123
|
+
|---|---|
|
|
124
|
+
| "I'll add eslint-disable-next-line to get lint green" | Silences a rule designed to catch a real class of runtime bug (stale closures, hook-order crashes); fix the dependency or hook placement instead |
|
|
125
|
+
| "This type error is annoying, I'll cast to any" | Removes the type check entirely at that point, including for the next person's edit; fix the actual type mismatch |
|
|
126
|
+
| "The hydration warning is harmless, I'll wrap everything in a client-only check" | Over-broad client-only guards flash empty/loading content for content that could have rendered on the server; find the actual server/client divergence first |
|
|
127
|
+
| "Test's failing after my fix, I'll just skip it" | Skipping hides a real regression the build-fix may have introduced; investigate before moving on |
|
|
128
|
+
|
|
129
|
+
## Verification
|
|
130
|
+
|
|
131
|
+
Do not report the work done until all of the following hold:
|
|
132
|
+
|
|
133
|
+
- The exact command that failed in Step 1 now exits 0.
|
|
134
|
+
- The full chain (type-check, lint, test, build) still passes after the
|
|
135
|
+
fix — a fix to one step did not regress an earlier one.
|
|
136
|
+
- No `eslint-disable` comment was added for a hooks rule, and no `as any`/
|
|
137
|
+
`: any` was added to route around a type error.
|
|
138
|
+
- `git status` shows only the files whose failure was being fixed (plus
|
|
139
|
+
their types, if the fix was a type definition change).
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"triggers": {
|
|
3
|
+
"positive": [
|
|
4
|
+
"This component's ref prop is throwing a TSX type error after the React 19 upgrade, fix it",
|
|
5
|
+
"eslint-plugin-react-hooks is failing on exhaustive-deps in this file",
|
|
6
|
+
"The Vite build fails with a JSX syntax error in this component",
|
|
7
|
+
"I'm getting a hydration mismatch warning on this page, fix it",
|
|
8
|
+
"Fix this children prop type error in the component",
|
|
9
|
+
"The tsc build fails because this event handler's type doesn't match onChange"
|
|
10
|
+
],
|
|
11
|
+
"negative": [
|
|
12
|
+
"Write a new test for this component's error state",
|
|
13
|
+
"Review this component for Rules of Hooks violations",
|
|
14
|
+
"Migrate this codebase from React 18 to React 19",
|
|
15
|
+
"Build a new dashboard component with charts",
|
|
16
|
+
"Fix a Node.js module resolution error unrelated to any component",
|
|
17
|
+
"This component re-renders too often, help me optimize it"
|
|
18
|
+
]
|
|
19
|
+
},
|
|
20
|
+
"scenarios": [
|
|
21
|
+
{
|
|
22
|
+
"id": "no-disable-hooks-lint",
|
|
23
|
+
"prompt": "react-hooks/exhaustive-deps is failing on my useEffect because it's missing a dependency. What should I do to fix the build?",
|
|
24
|
+
"strictness": "high",
|
|
25
|
+
"expected_behavior": [
|
|
26
|
+
{
|
|
27
|
+
"grader": "judge",
|
|
28
|
+
"rubric": "A correct answer fixes the exhaustive-deps failure by adding the missing reactive dependency to the effect's dependency array, or, if the value is genuinely stable (a ref, a dispatch function, a value confirmed never to change in a way the effect needs), uses the lint rule's own documented escape hatch after explaining why the value is stable. It treats the failure as a real staleness bug to fix, not noise to silence.",
|
|
29
|
+
"pass_criteria": [
|
|
30
|
+
"Names the specific missing dependency the effect reads and shows the corrected code — either the completed dependency array including it or a useCallback/useRef restructuring so the value no longer needs to be listed. When the prompt itself shows no code (as here), a concrete illustrative example of such a corrected effect/dependency array satisfies this requirement. A plain 'add the dependency' with no named value and no code shown does not satisfy this.",
|
|
31
|
+
"Explains the staleness consequence of the missing dependency (the effect would keep using an old/stale value from an earlier render instead of reacting to the current one), not just that the fix 'resolves the issue' or 'stops the build complaining'."
|
|
32
|
+
],
|
|
33
|
+
"fail_criteria": [
|
|
34
|
+
"Recommends disabling or suppressing the exhaustive-deps rule (for example an eslint-disable-next-line comment) as the fix, instead of adding the missing dependency or justifying a stability-based exception; this includes mentioning eslint-disable only as a caveat or aside without a concrete named-dependency fix alongside it."
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
],
|
|
38
|
+
"calibration": {
|
|
39
|
+
"known_right": "Add the dependency the effect actually reads to its dependency array — that's what exhaustive-deps is flagging, and it's usually a real staleness bug, not a false positive. For example, if the effect fetches data using a prop:\n\nuseEffect(() => {\n fetchUser(userId);\n}, [userId]);\n\nWithout userId in the array, the effect only runs once and keeps using whatever userId was passed on the first render — if the prop changes later, the effect won't re-fire and fetchUser keeps being called with a stale id instead of the current one, which is exactly the staleness bug the rule exists to catch. If adding the value would cause the effect to re-run on every render because it's a function or object recreated each render, wrap that value in useCallback/useMemo in its own definition rather than dropping it from the array:\n\nconst fetchUser = useCallback((id: string) => { /* ... */ }, []);\nuseEffect(() => {\n fetchUser(userId);\n}, [userId, fetchUser]);\n\nOnly omit a value from the array when you've confirmed it's genuinely stable across renders — a ref, a setState/dispatch function, or a value you've verified never changes in a way this effect cares about — and in that case use the rule's documented per-line justification rather than a blanket eslint-disable-next-line comment. Don't just silence the rule; an eslint-disable comment here would hide the bug instead of fixing it.",
|
|
40
|
+
"known_wrong": "Easiest fix: add `// eslint-disable-next-line react-hooks/exhaustive-deps` right above the useEffect line. That silences the warning so your build/lint step goes green immediately, and you don't need to touch the dependency array or worry about extra re-renders. Just drop that comment in and move on — the effect will keep working the same way it does now, the lint rule just won't complain anymore.",
|
|
41
|
+
"vague": "Add what's missing to the dependency array, or otherwise adjust the effect so the lint rule stops flagging it. That should clear the build.",
|
|
42
|
+
"subtle_wrong": "Add the missing value to the dependency array — that's the general fix here. Once you do that, if you notice the effect re-running more than you'd like because of it, you can always wrap the eslint-disable-next-line comment around just that specific line as a targeted exception rather than disabling the whole rule file-wide; that keeps the rest of the codebase's exhaustive-deps checking intact while unblocking this one build failure quickly."
|
|
43
|
+
},
|
|
44
|
+
"anti_patterns": ["eslint-disable"]
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"id": "no-any-cast",
|
|
48
|
+
"prompt": "I have a TSX prop type error on an event handler and the build is failing. Should I just cast it to any to unblock the build?",
|
|
49
|
+
"strictness": "high",
|
|
50
|
+
"expected_behavior": [
|
|
51
|
+
{
|
|
52
|
+
"grader": "judge",
|
|
53
|
+
"rubric": "A correct answer says no, casting to any is not the fix, and instead resolves the actual type mismatch by typing the event handler parameter with the specific React event type that matches the element and event in use (for example React.ChangeEvent<HTMLInputElement> or React.MouseEvent<HTMLButtonElement>), so the type check reflects reality instead of being bypassed.",
|
|
54
|
+
"pass_criteria": [
|
|
55
|
+
"States that casting to any is not the right fix for this prop type error.",
|
|
56
|
+
"Names the specific React event type that matches the element/event in use (for example React.ChangeEvent<HTMLInputElement> or React.MouseEvent<HTMLButtonElement>), not just 'the correct event type' in the abstract."
|
|
57
|
+
],
|
|
58
|
+
"fail_criteria": [
|
|
59
|
+
"Recommends casting the prop/event to any (or `as any`) as the way to unblock the build, including as a temporary/fallback suggestion alongside the real fix."
|
|
60
|
+
]
|
|
61
|
+
}
|
|
62
|
+
],
|
|
63
|
+
"calibration": {
|
|
64
|
+
"known_right": "No — casting to any would remove type checking at that call site entirely, including for whatever the next person changes there, and it doesn't actually fix anything, it just hides the mismatch. Look at what element and event you're actually handling: for an <input> onChange it's React.ChangeEvent<HTMLInputElement>, for a button click it's React.MouseEvent<HTMLButtonElement>, for a form submit it's React.FormEvent<HTMLFormElement>. Update the handler's parameter type to match the specific element/event combination instead of whatever loose or generic type it currently has. If you're not sure which one applies, check how the handler is wired up in JSX (onChange, onClick, onSubmit) — that tells you the event type. Once the parameter type matches what's actually being passed, the type error goes away because the code is now honestly described, not suppressed. Re-run the build after the change to confirm it's green.",
|
|
65
|
+
"known_wrong": "Yeah, just cast it `as any` for now — `(e as any).target.value` or type the handler param `(e: any) => { ... }` — and the type error will go away so your build unblocks. You can always circle back and add the proper React.ChangeEvent type later if it becomes an issue; for now the `as any` cast gets you moving without having to dig into exactly which event type the handler needs.",
|
|
66
|
+
"vague": "No, don't cast to any — fix the event handler's type instead so it matches what's actually being passed in.",
|
|
67
|
+
"subtle_wrong": "Casting to any isn't great long-term, so instead give the parameter a narrower type than any, like `(e: React.SyntheticEvent) => { const target = e.target as HTMLInputElement; ... }`. That keeps some type safety at the boundary while letting you unblock the build now; you can tighten it to the exact ChangeEvent/MouseEvent generic later once you've confirmed which element this handler actually attaches to."
|
|
68
|
+
},
|
|
69
|
+
"anti_patterns": ["as any"]
|
|
70
|
+
}
|
|
71
|
+
]
|
|
72
|
+
}
|