geneseed 4.9.4 → 4.14.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/CHANGELOG.md +106 -0
- package/README.md +16 -2
- package/SHIPPED.md +1 -1
- package/docs/README.md +1 -1
- package/docs/concepts/collaboration.md +1 -1
- package/docs/concepts/enforcement-table.md +1 -1
- package/docs/concepts/foreman-mode.md +1 -1
- package/docs/concepts/kits.md +91 -0
- package/docs/concepts/loop-branch.md +1 -1
- package/docs/concepts/loop-bricks.md +1 -1
- package/docs/concepts/loop-contracts.md +1 -1
- package/docs/concepts/loop-gates.md +1 -1
- package/docs/concepts/loop-notes.md +1 -1
- package/docs/concepts/loop-risk.md +1 -1
- package/docs/concepts/loop-templates.md +1 -1
- package/docs/concepts/loops.md +1 -1
- package/docs/concepts/lsp.md +1 -1
- package/docs/concepts/skills.md +1 -1
- package/docs/extending.md +107 -4
- package/docs/guides/install-scripted.md +1 -1
- package/docs/guides/run-anywhere.md +2 -2
- package/docs/guides/upgrade.md +2 -2
- package/docs/reference/glossary.md +1 -0
- package/docs/reference/troubleshoot-install.md +1 -1
- package/docs/web-ui.md +9 -0
- package/harness.config.json +1 -1
- package/js/build/args.mjs +27 -6
- package/js/build/driver.mjs +29 -8
- package/js/build/emit-claude.mjs +3 -1
- package/js/build/generate.mjs +10 -5
- package/js/build/render.mjs +94 -11
- package/js/build/source.mjs +117 -4
- package/js/cli-table.json +15 -0
- package/js/hosts/installs.mjs +35 -2
- package/js/hosts/link.mjs +88 -1
- package/js/hosts/native.mjs +14 -4
- package/js/inspect/checks-authoring.mjs +6 -3
- package/js/inspect/checks-build.mjs +15 -3
- package/js/inspect/checks-counts.mjs +153 -6
- package/js/inspect/checks-repo.mjs +95 -20
- package/js/inspect/cost.mjs +1 -1
- package/js/inspect/diff.mjs +56 -8
- package/js/inspect/inventory.mjs +2 -0
- package/js/inspect/status.mjs +44 -3
- package/js/inspect/validate.mjs +3 -3
- package/js/lib/prompt.mjs +19 -2
- package/js/maintain/setup.mjs +111 -23
- package/js/maintain/update.mjs +3 -3
- package/js/web/actions.mjs +38 -6
- package/js/web/api.mjs +76 -17
- package/js/web/catalog.mjs +17 -2
- package/js/web/handler.mjs +1 -0
- package/js/web/routes.mjs +2 -1
- package/js/web/server.mjs +11 -5
- package/js/web/state.mjs +38 -3
- package/package.json +1 -1
- package/registry.json +91 -0
- package/src/AGENT.md.tmpl +7 -7
- package/src/agents/_self-improvement.md +11 -0
- package/src/agents/_template.md +1 -8
- package/src/agents/advocate.md +1 -8
- package/src/agents/architect.md +1 -8
- package/src/agents/developer.md +1 -8
- package/src/agents/devops-engineer.md +37 -0
- package/src/agents/docker-expert.md +37 -0
- package/src/agents/docs.md +1 -8
- package/src/agents/empiricist.md +1 -8
- package/src/agents/explorer.md +1 -8
- package/src/agents/framer.md +1 -8
- package/src/agents/historian.md +1 -8
- package/src/agents/kubernetes-specialist.md +37 -0
- package/src/agents/memory-curator.md +1 -8
- package/src/agents/operator.md +1 -8
- package/src/agents/performance.md +1 -8
- package/src/agents/pragmatist.md +1 -8
- package/src/agents/react-engineer.md +38 -0
- package/src/agents/react-reviewer.md +42 -0
- package/src/agents/researcher.md +5 -10
- package/src/agents/reviewer.md +3 -8
- package/src/agents/security.md +1 -8
- package/src/agents/skeptic.md +1 -8
- package/src/agents/spring-boot-engineer.md +40 -0
- package/src/agents/spring-reviewer.md +41 -0
- package/src/agents/spring-security.md +42 -0
- package/src/agents/steward.md +1 -8
- package/src/agents/tester.md +1 -8
- package/src/agents/user-advocate.md +1 -8
- package/src/agents/visionary.md +1 -8
- package/src/kits/react/rules.md +13 -0
- package/src/kits/react.json +18 -0
- package/src/kits/spring-boot/rules.md +10 -0
- package/src/kits/spring-boot.json +23 -0
- package/src/licenses/everything-claude-code.txt +21 -0
- package/src/licenses/mattpocock-skills.txt +21 -0
- package/src/licenses/piomin-spring-boot.txt +190 -0
- package/src/licenses/superpowers.txt +21 -0
- package/src/licenses/vibe-wise.txt +21 -0
- package/src/skills/_self-improvement.md +22 -5
- package/src/skills/brainstorm/builder-check.md +2 -0
- package/src/skills/brainstorm.md +11 -2
- package/src/skills/codebase-design.md +10 -2
- package/src/skills/daydream/VENDOR.md +7 -7
- package/src/skills/debug.md +6 -2
- package/src/skills/develop.md +6 -2
- package/src/skills/geneseed-code-review.md +6 -2
- package/src/skills/git-history.md +2 -0
- package/src/skills/handoff.md +3 -1
- package/src/skills/learn-mode.md +3 -2
- package/src/skills/parallel-agents.md +5 -1
- package/src/skills/pipeline.md +2 -0
- package/src/skills/plan.md +9 -2
- package/src/skills/prototype.md +6 -2
- package/src/skills/react/a11y.md +33 -0
- package/src/skills/react/vite.md +35 -0
- package/src/skills/react/webpack.md +40 -0
- package/src/skills/react-testing.md +68 -0
- package/src/skills/react-view-transitions/AGENTS.md +646 -221
- package/src/skills/react-view-transitions/SKILL.md +28 -16
- package/src/skills/react-view-transitions/VENDOR.md +10 -8
- package/src/skills/react-view-transitions/references/css-recipes.md +72 -2
- package/src/skills/react-view-transitions/references/implementation.md +14 -26
- package/src/skills/react-view-transitions/references/nextjs.md +94 -37
- package/src/skills/react-view-transitions/references/patterns.md +60 -48
- package/src/skills/react-view-transitions/references/troubleshooting.md +47 -0
- package/src/skills/react.md +63 -0
- package/src/skills/research.md +6 -2
- package/src/skills/review-response.md +2 -0
- package/src/skills/rule.md +6 -2
- package/src/skills/ship.md +8 -4
- package/src/skills/skill-forge.md +11 -5
- package/src/skills/spring-boot/cloud.md +103 -0
- package/src/skills/spring-boot/java-modern.md +71 -0
- package/src/skills/spring-boot/logging.md +89 -0
- package/src/skills/spring-boot/security.md +112 -0
- package/src/skills/spring-boot/web.md +112 -0
- package/src/skills/spring-boot.md +57 -0
- package/src/skills/spring-data-jpa/patterns.md +68 -0
- package/src/skills/spring-data-jpa.md +81 -0
- package/src/skills/spring-testing.md +93 -0
- package/src/skills/wayfinder.md +8 -2
- package/src/skills/wiki.md +18 -5
- package/src/upstreams.json +66 -0
- package/themes/_TEMPLATE.json +13 -0
- package/themes/biker.json +13 -0
- package/themes/commentator.json +13 -0
- package/themes/cyberpunk.json +13 -0
- package/themes/gamer.json +13 -0
- package/themes/imperial.json +13 -0
- package/themes/joker.json +13 -0
- package/themes/marvin.json +13 -0
- package/themes/mean.json +13 -0
- package/themes/military.json +13 -0
- package/themes/neutral.json +13 -0
- package/themes/pirate.json +13 -0
- package/themes/sports.json +13 -0
- package/themes/verstappen.json +13 -0
- package/themes/wizard.json +13 -0
- package/web/dist/assets/Activity-44rbWUQI.js +1 -0
- package/web/dist/assets/ActivityDetail-Dk9k893a.js +1 -0
- package/web/dist/assets/Dashboard-DCoUN60W.js +2 -0
- package/web/dist/assets/{Docs-tDW7i7mo.js → Docs-C_je2lRG.js} +3 -3
- package/web/dist/assets/FilterInput-CZREvrjX.js +1 -0
- package/web/dist/assets/GreenhouseView-BXAOIznW.js +2 -0
- package/web/dist/assets/Installs-DAXF403D.js +3 -0
- package/web/dist/assets/JournalView-DZ184wKB.js +1 -0
- package/web/dist/assets/KitApply-pjhvGha0.js +1 -0
- package/web/dist/assets/Kits-BCCKjSIY.js +1 -0
- package/web/dist/assets/{Laws-BA3CzUf5.js → Laws-BgBUpRkE.js} +1 -1
- package/web/dist/assets/Library-CW0Zl6RF.js +1 -0
- package/web/dist/assets/Loops-BvFOzjEw.js +2 -0
- package/web/dist/assets/{Markdown-iHvBrpRN.js → Markdown-zaXXXHz9.js} +13 -13
- package/web/dist/assets/OperatorHudView-Bs4unPNi.js +2 -0
- package/web/dist/assets/Personal-C23XaT-a.js +1 -0
- package/web/dist/assets/Tabs-b2XFu4OS.js +1 -0
- package/web/dist/assets/activity-Jw8XcPiP.js +1 -0
- package/web/dist/assets/api-BfpZmUMI.js +1 -0
- package/web/dist/assets/{drawable-CyLe1gtW.js → drawable-BERkKhx_.js} +1 -1
- package/web/dist/assets/index-C9R_bRw_.js +2 -0
- package/web/dist/assets/{index-BCJz4_8C.css → index-jYlWihN-.css} +1 -1
- package/web/dist/assets/{react-BOF6yL40.js → react-DlYQp10C.js} +1 -1
- package/web/dist/assets/rolldown-runtime-hePW80VL.js +1 -0
- package/web/dist/assets/sections-ChwaobfW.js +1 -0
- package/web/dist/assets/usePoll-bDFN-Hr6.js +1 -0
- package/web/dist/index.html +6 -5
- package/web/dist/assets/Activity-C8sZVIUU.js +0 -1
- package/web/dist/assets/ActivityDetail-Cc6vWUS4.js +0 -1
- package/web/dist/assets/Dashboard-C5ATa3ow.js +0 -2
- package/web/dist/assets/FilterInput-zLFXoSt6.js +0 -1
- package/web/dist/assets/GreenhouseView-zk2Uzc3A.js +0 -2
- package/web/dist/assets/Installs-CB_rvbBP.js +0 -3
- package/web/dist/assets/JournalView-Bfj27XHC.js +0 -1
- package/web/dist/assets/Library-BWwiy9Vb.js +0 -1
- package/web/dist/assets/Loops-DaPk-ckL.js +0 -2
- package/web/dist/assets/OperatorHudView-CyiGhiHk.js +0 -2
- package/web/dist/assets/Personal-Bwd27CmT.js +0 -1
- package/web/dist/assets/Tabs-BOD7Kaz1.js +0 -1
- package/web/dist/assets/activity-DvPxoS4Y.js +0 -1
- package/web/dist/assets/api-CiXlkbe0.js +0 -1
- package/web/dist/assets/index-DQXG_mqo.js +0 -2
- package/web/dist/assets/sections-BET3c1WT.js +0 -1
- package/web/dist/assets/usePoll-NSTzLOF4.js +0 -1
|
@@ -1,10 +1,23 @@
|
|
|
1
1
|
## Self-improvement
|
|
2
2
|
|
|
3
3
|
<!-- LEAN:begin -->
|
|
4
|
+
This {{SKILL}} keeps its own notes in `{{DIR_NOTEBOOK}}/skill-notes/<name>.md`,
|
|
5
|
+
`<name>` being this {{SKILL}}'s name. When that file exists, read it before the
|
|
6
|
+
first step — where it disagrees with this file, the notes win. They are yours to
|
|
7
|
+
write, and no rebuild touches them.
|
|
8
|
+
|
|
4
9
|
Close each run with one beat of reflection on the {{SKILL}} itself:
|
|
5
10
|
- A step misled, a needed step was missing, or the trigger fired wrongly — that
|
|
6
|
-
is a flaw in this file.
|
|
7
|
-
done-when)
|
|
11
|
+
is a flaw in this file. Write the exact correction (trigger, procedure, or
|
|
12
|
+
done-when) into the notes file, with the user's assent ({{LAW:one-intent-one-act}}), as one line:
|
|
13
|
+
`- [skill|general] <correction> — seen: <what happened, against what you expected> (<date>)`.
|
|
14
|
+
`seen:` is the evidence the correction is later judged by; `general` marks one
|
|
15
|
+
that would fix other {{SKILLS}} too. Never
|
|
16
|
+
edit this file: it is a rendered copy, a rebuild overwrites it, and the doctor
|
|
17
|
+
reports the edit as drift. `geneseed diff` carries the notes back to the source.
|
|
18
|
+
- Keep the notes sharp: amend or delete a line before adding one — a line with no
|
|
19
|
+
`seen:`, or whose `seen:` no longer happens, goes first — and prune past about
|
|
20
|
+
twenty lines.
|
|
8
21
|
- A lesson that is *not* a flaw in this file goes to {{MEMORY}} only if it
|
|
9
22
|
clears {{DOCTRINE:persist-insight}}'s bar: it would change how a future session behaves, and a
|
|
10
23
|
fresh read of the repo would not re-derive it. Update an existing memory over
|
|
@@ -13,7 +26,11 @@ Close each run with one beat of reflection on the {{SKILL}} itself:
|
|
|
13
26
|
runs end here.
|
|
14
27
|
<!-- LEAN:else -->
|
|
15
28
|
One beat of reflection on this {{SKILL}}: a step that misled, a missing step, or a
|
|
16
|
-
wrong trigger is a flaw in this file —
|
|
17
|
-
|
|
18
|
-
|
|
29
|
+
wrong trigger is a flaw in this file — write the exact correction, with the user's
|
|
30
|
+
assent ({{LAW:one-intent-one-act}}), into `{{DIR_NOTEBOOK}}/skill-notes/<name>.md` (`<name>` is this {{SKILL}}'s
|
|
31
|
+
name) as `- [skill|general] <correction> — seen: <what happened vs expected> (<date>)`,
|
|
32
|
+
never into this rendered file, which a rebuild overwrites. Read that notes
|
|
33
|
+
file before the first step when it exists; it wins where it disagrees. Keep it short.
|
|
34
|
+
A lesson that is not about this file goes to {{MEMORY}} only if it clears
|
|
35
|
+
{{DOCTRINE:persist-insight}}'s bar. Nothing learned — move on.
|
|
19
36
|
<!-- LEAN:end -->
|
package/src/skills/brainstorm.md
CHANGED
|
@@ -3,6 +3,12 @@
|
|
|
3
3
|
> {{DESC_BRAINSTORM}}
|
|
4
4
|
<!-- aliases: grill-me -->
|
|
5
5
|
|
|
6
|
+
{{CREDIT:superpowers:skills/brainstorming/SKILL.md}}
|
|
7
|
+
|
|
8
|
+
{{CREDIT:mattpocock-skills:skills/productivity/grilling/SKILL.md}}
|
|
9
|
+
|
|
10
|
+
{{CREDIT:mattpocock-skills:skills/productivity/to-questionnaire/SKILL.md}}
|
|
11
|
+
|
|
6
12
|
**Trigger:** a new feature, behaviour change, or project arrives without a design, or the
|
|
7
13
|
user says "brainstorm", "interview me" or "grill me". Also when goal, scope or success
|
|
8
14
|
criteria are unstated ("let's design this", "clarify this first", "stress-test this plan"),
|
|
@@ -23,8 +29,11 @@ the design is skipped.
|
|
|
23
29
|
libraries) the user wants to own. Existing work decides by default
|
|
24
30
|
({{DOCTRINE:respect-conventions}}); a choice you take goes in the ledger as **your
|
|
25
31
|
call**, never as agreed. Stop when each is unambiguous. Facts are yours to find (read
|
|
26
|
-
the code, dispatch a subagent), never the user's
|
|
27
|
-
|
|
32
|
+
the code, dispatch a subagent), never the user's; a pending lookup holds back only the
|
|
33
|
+
questions that depend on it. A decision someone else owns gets a drafted
|
|
34
|
+
`questionnaire-<slug>.md` for them — ask the user only who and what they need back. Most
|
|
35
|
+
important first (async gets one pass), one idea per question with an empty answer stub
|
|
36
|
+
under it, and say "I don't know" is a useful answer.
|
|
28
37
|
3. **Ledger the decisions.** Name every KEY DECISION the answers imply or leave open —
|
|
29
38
|
direction chosen, trade-offs accepted, load-bearing constraints, assumptions,
|
|
30
39
|
non-goals. Surface each silent assumption as a decision to ratify, not a settled
|
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
> {{DESC_CODEBASE_DESIGN}}
|
|
4
4
|
<!-- aliases: domain-modeling -->
|
|
5
5
|
|
|
6
|
+
{{CREDIT:mattpocock-skills:skills/engineering/codebase-design/SKILL.md}}
|
|
7
|
+
|
|
8
|
+
{{CREDIT:mattpocock-skills:skills/engineering/domain-modeling/SKILL.md}}
|
|
9
|
+
|
|
6
10
|
**Trigger:** the user asks "where should the seam go", how to make a module testable through
|
|
7
11
|
its interface, or for a glossary term or ADR. Also designing or reshaping a module's interface,
|
|
8
12
|
a design talk that keeps stumbling over ambiguous terms, or another {{SKILL}} needing this vocabulary.
|
|
@@ -12,7 +16,8 @@ a design talk that keeps stumbling over ambiguous terms, or another {{SKILL}} ne
|
|
|
12
16
|
`GLOSSARY-MAP.md` means several contexts — find the one in play) and the
|
|
13
17
|
area's ADRs in `docs/adr/`; use their terms verbatim in code, tests, prose.
|
|
14
18
|
When the user says how something works, check the code agrees; surface any
|
|
15
|
-
contradiction.
|
|
19
|
+
contradiction. An ADR is settled: a proposal that contradicts one says so,
|
|
20
|
+
and why the friction justifies reopening it — never silently.
|
|
16
21
|
2. Use this vocabulary exactly — **module** (anything with an interface and an
|
|
17
22
|
implementation, any scale), **interface** (all a caller must know: types,
|
|
18
23
|
invariants, ordering, error modes, performance), **depth** (behaviour per
|
|
@@ -21,7 +26,10 @@ a design talk that keeps stumbling over ambiguous terms, or another {{SKILL}} ne
|
|
|
21
26
|
"component", "service", "API", "boundary".
|
|
22
27
|
3. Aim for **deep modules** — much behaviour behind a small interface: callers
|
|
23
28
|
get leverage, maintainers get locality. To find what to deepen, start from
|
|
24
|
-
`git log` hot spots — what keeps changing.
|
|
29
|
+
`git log` hot spots — what keeps changing. Design a new or reshaped interface
|
|
30
|
+
twice before choosing: 2–3 radically different shapes (in parallel subagents
|
|
31
|
+
where the host runs them), compared on depth, locality and seam placement;
|
|
32
|
+
recommend one — a hybrid if parts combine — never a menu.
|
|
25
33
|
4. Seams sparingly: the interface is the test surface. Internal seams for the
|
|
26
34
|
module's own tests are fine but never exposed; a test that must reach past
|
|
27
35
|
the interface means the wrong shape. One adapter is a hypothesis; a second
|
|
@@ -5,14 +5,14 @@ skill. It rides along in the rendered bundle and is exempt from Geneseed's autho
|
|
|
5
5
|
gates (token, dead-link, hermeticity, skill counts) — it is listed in the
|
|
6
6
|
generator's `VENDORED_SKILL_DIRS`.
|
|
7
7
|
|
|
8
|
-
- **Upstream:**
|
|
9
|
-
- **
|
|
10
|
-
- **Author:** Gleb Kalinin
|
|
11
|
-
- **License:** MIT (declared in `.claude-plugin/plugin.json`). The text is in `LICENSE`,
|
|
12
|
-
copied from upstream's root `LICENSE` as added in 93677f479f40ab43520883e7a6c954b755ab39ef
|
|
13
|
-
(the pinned commit predates the file; its copyright line covers 2025-2026).
|
|
8
|
+
- **Upstream key:** daydream (repo, pinned commit, author and licence: `src/upstreams.json`)
|
|
9
|
+
- **Credit:** {{CREDIT:daydream:daydream}}
|
|
14
10
|
- **Inspired by:** Gwern's [LLM Daydreaming](https://gwern.net/ai-daydreaming)
|
|
15
11
|
|
|
12
|
+
The licence (MIT, declared upstream in `.claude-plugin/plugin.json`) is in `LICENSE`, copied
|
|
13
|
+
from upstream's root `LICENSE` as added in 93677f479f40ab43520883e7a6c954b755ab39ef (the
|
|
14
|
+
pinned commit predates the file; its copyright line covers 2025-2026).
|
|
15
|
+
|
|
16
16
|
## Geneseed adaptation
|
|
17
17
|
|
|
18
18
|
Vault resolution is adapted to read the harness's `geneseed-wiki.jsonc` knowledge-base
|
|
@@ -32,7 +32,7 @@ does not tell the model where a skill lives.
|
|
|
32
32
|
|
|
33
33
|
To update, re-copy the upstream folder, re-apply the geneseed-wiki.jsonc adaptation, the
|
|
34
34
|
frontmatter and the placeholder paths in `SKILL.md` / `instructions.md`, and
|
|
35
|
-
bump the commit
|
|
35
|
+
bump the `daydream` entry's `commit` in `src/upstreams.json`.
|
|
36
36
|
|
|
37
37
|
`SKILL.md`'s frontmatter also carries `disable-model-invocation: true`, which upstream lacks: the
|
|
38
38
|
skill is user-only (`/daydream`), so its description stays out of the model's always-on catalogue —
|
package/src/skills/debug.md
CHANGED
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
> {{DESC_DEBUG}}
|
|
4
4
|
<!-- aliases: ci-fix -->
|
|
5
5
|
|
|
6
|
+
{{CREDIT:superpowers:skills/systematic-debugging/SKILL.md}}
|
|
7
|
+
|
|
8
|
+
{{CREDIT:mattpocock-skills:skills/engineering/diagnosing-bugs/SKILL.md}}
|
|
9
|
+
|
|
6
10
|
**Trigger:** a test fails, code crashes or prints a stack trace, or returns the wrong result — load this FIRST. Load it before reading code or investigating, not only before proposing a fix. Also when a CI run, pipeline job or pre-merge check is red ("CI is failing", "fix the build") — then start with the CI branch.
|
|
7
11
|
|
|
8
12
|
**No fix without a root cause.** A change you cannot tie to a cause you understand is
|
|
@@ -12,7 +16,7 @@ The pressure to skip straight to a patch is highest exactly when this rule matte
|
|
|
12
16
|
faster than thrashing; do not trade it away under pressure.
|
|
13
17
|
|
|
14
18
|
## Procedure
|
|
15
|
-
1. **Build one command that goes red on *this* bug** before reading code for a theory. It asserts the user's exact symptom (not "didn't crash"), gives the same verdict every run, takes seconds and runs unattended; run it and show the output. Read the error and stack trace in full. For a flaky bug, raise the reproduction rate until it is debuggable. If you cannot build it, say so, list what you tried and ask for access or a captured artifact — no command, no hypothesis. Read `GLOSSARY.md` (or `CONTEXT.md`) and the ADRs in the area for the domain's vocabulary.
|
|
19
|
+
1. **Build one command that goes red on *this* bug** before reading code for a theory. It asserts the user's exact symptom (not "didn't crash"), gives the same verdict every run, takes seconds and runs unattended; run it and show the output. If you forced the red by mutating code or a fixture, `diff` against a pristine copy to prove the mutation landed, then revert it. Read the error and stack trace in full. For a flaky bug, raise the reproduction rate until it is debuggable. If you cannot build it, say so, list what you tried and ask for access or a captured artifact — no command, no hypothesis. Read `GLOSSARY.md` (or `CONTEXT.md`) and the ADRs in the area for the domain's vocabulary.
|
|
16
20
|
2. **Minimise, then isolate.** Cut inputs and steps one at a time until every remaining element is load-bearing. Then binary-search the cause — the code path, or for a regression the commit range with `git bisect` (the [git-history {{SKILL}}](git-history.md) carries the method). Change one variable at a time. Find the nearest working twin (a passing sibling test, the last green commit, the same call elsewhere) and list every difference, however small. For a bad value deep in the stack, trace it back caller by caller to where it was born, and fix there. In a multi-layer system (CI → build → sign, API → service → DB), instrument each boundary once to see *which* layer breaks before investigating inside it. For a performance regression, take a baseline measurement and bisect; don't log.
|
|
17
21
|
3. **Rank 3–5 falsifiable hypotheses** ("if X is the cause, changing Y removes the bug") — list them in your reply, then test the top one without waiting. Cite the evidence for each as `file:line` or the exact log line. Proceed only on one that explains ALL the evidence — else gather more evidence, don't guess.
|
|
18
22
|
4. Apply the smallest fix that addresses the root cause, not the symptom; resist fixing things the evidence doesn't implicate ({{LAW:one-intent-one-act}}). One change at a time — no bundled "while I'm here" edits.
|
|
@@ -24,6 +28,6 @@ faster than thrashing; do not trade it away under pressure.
|
|
|
24
28
|
**CI branch (a red run)** → read [debug/ci.md](debug/ci.md) and follow it.
|
|
25
29
|
|
|
26
30
|
## Done when
|
|
27
|
-
- The failure is reproduced by a command that went red on it, root-caused, fixed at the cause, and that command passes with no new breakage; every tagged probe is gone.
|
|
31
|
+
- The failure is reproduced by a command that went red on it, root-caused, fixed at the cause, and that command passes with no new breakage; every tagged probe is gone, and the step-1 repro is deleted or kept as the regression test.
|
|
28
32
|
|
|
29
33
|
<!-- INCLUDE: skills/_self-improvement.md -->
|
package/src/skills/develop.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
> {{DESC_DEVELOP}}
|
|
4
4
|
|
|
5
|
+
{{CREDIT:mattpocock-skills:skills/engineering/tdd/SKILL.md}}
|
|
6
|
+
|
|
5
7
|
**Trigger:** implementing a feature, fixing a bug, or changing code behaviour in a
|
|
6
8
|
repo that has (or should have) a test suite — before writing implementation code.
|
|
7
9
|
Covers both the test-first cycle (red → green → refactor) and the cover-alongside
|
|
@@ -31,7 +33,7 @@ case where the seam is only known once the change is made.
|
|
|
31
33
|
change ({{DOCTRINE:cover-and-verify}}), then break the implementation on purpose once to
|
|
32
34
|
see the test go red before trusting it.
|
|
33
35
|
4. Write the minimum code that makes it pass; add nothing the test doesn't demand.
|
|
34
|
-
5. Run the *affected* tests and read the output ({{LAW:verify-before-asserting}}); on failure fix the
|
|
36
|
+
5. Run the *affected* tests, and the typecheck where the project has one, and read the output ({{LAW:verify-before-asserting}}); on failure fix the
|
|
35
37
|
cause, never mask it ({{LAW:cure-the-cause}}). Dispatch the
|
|
36
38
|
[tester {{AGENT}}](../{{DIR_AGENTS}}/tester.md) for heavier or unfamiliar coverage,
|
|
37
39
|
or when the blast radius is unclear.
|
|
@@ -48,7 +50,9 @@ case where the seam is only known once the change is made.
|
|
|
48
50
|
## Anti-patterns — name the one you catch
|
|
49
51
|
- **Implementation-coupled** — mocks an internal collaborator, tests a private method,
|
|
50
52
|
or checks through a side channel (querying the database instead of the interface).
|
|
51
|
-
The tell: it breaks on a refactor that changed no behaviour.
|
|
53
|
+
The tell: it breaks on a refactor that changed no behaviour. Mock only at system
|
|
54
|
+
boundaries — external APIs, time, randomness, sometimes the database or filesystem —
|
|
55
|
+
passed in rather than built inside; never a module you control.
|
|
52
56
|
- **Tautological** — the expected value is recomputed the way the code computes it, so
|
|
53
57
|
the test passes by construction and can never disagree with the code.
|
|
54
58
|
- **Horizontal slicing** — all the tests first, then all the code: the tests pin an
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
> {{DESC_CODE_REVIEW}}
|
|
4
4
|
|
|
5
|
+
{{CREDIT:mattpocock-skills:skills/engineering/code-review/SKILL.md}}
|
|
6
|
+
|
|
7
|
+
{{CREDIT:superpowers:skills/requesting-code-review/code-reviewer.md}}
|
|
8
|
+
|
|
5
9
|
**Trigger:** reviewing changes before merge, or the user asks for a review — including "roast my code": same passes, findings unsoftened. Critiquing the user's own ask or plan is [roast-me](roast-me.md).
|
|
6
10
|
|
|
7
11
|
## Procedure
|
|
@@ -22,8 +26,8 @@
|
|
|
22
26
|
kept apart, one axis's findings never mask the other's.
|
|
23
27
|
5. Pass 1 — correctness: logic errors, edge cases, error handling, race
|
|
24
28
|
conditions. Verify suspect behaviour by running tests, not by assuming.
|
|
25
|
-
6. Pass 2 — quality: after `REVIEW.md`, the repo's documented standards
|
|
26
|
-
`CONTRIBUTING.md
|
|
29
|
+
6. Pass 2 — quality: after `REVIEW.md`, the repo's documented standards override: search the repo for every file that states how code
|
|
30
|
+
is written (`CODING_STANDARDS.md`, `CONTRIBUTING.md`, style or conventions docs), not one fixed path. Then, as judgement calls and skipping what tooling enforces:
|
|
27
31
|
mysterious name, duplication, feature envy, data clumps, primitive obsession, repeated switches, shotgun surgery, divergent change, speculative generality, message chains, middle man, refused bequest, dead code, units that do too much.
|
|
28
32
|
7. Pass 3 — spec fidelity: flag anything asked for but missing, present but never
|
|
29
33
|
asked for, or implemented wrong — quoting the spec line for each. Where the spec is silent,
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
> {{DESC_GIT_HISTORY}}
|
|
4
4
|
<!-- aliases: git-archaeology, git-rescue -->
|
|
5
5
|
|
|
6
|
+
{{CREDIT:mattpocock-skills-frozen:skills/engineering/resolving-merge-conflicts/SKILL.md}}
|
|
7
|
+
|
|
6
8
|
**Trigger:** something must be learned *from* the git history, or it needs repair.
|
|
7
9
|
Learn: when a regression came in, who last touched a line and why, where a symbol or
|
|
8
10
|
string entered. Repair: lost commits, a rebase/merge/reset gone wrong, a detached HEAD, a
|
package/src/skills/handoff.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
> {{DESC_HANDOFF}}
|
|
4
4
|
|
|
5
|
+
{{CREDIT:mattpocock-skills:skills/productivity/handoff/SKILL.md}}
|
|
6
|
+
|
|
5
7
|
**Trigger:** the context window is filling, a session is ending mid-task, or work is passing to another agent or developer.
|
|
6
8
|
|
|
7
9
|
## Procedure
|
|
@@ -9,7 +11,7 @@
|
|
|
9
11
|
2. Record open decisions, dead ends already ruled out, blockers, and any irreversible changes already made ({{DOCTRINE:plan-before-acting}}) — so the next agent neither re-derives nor repeats them.
|
|
10
12
|
3. Promote any durable fact or correction learned this session into {{MEMORY}} (§5), not just the worklog.
|
|
11
13
|
4. Point to the live artifacts: branch name, changed files, how to run the tests, and where any failure reproduces. Link specs, plans, ADRs, issues and commits by path or URL — never copy them in.
|
|
12
|
-
5. Put a one-line "resume here" pointer at the top so a fresh context picks up in a single read ({{DOCTRINE:context-economy}}), and list the {{SKILL}}s the next agent should load.
|
|
14
|
+
5. Put a one-line "resume here" pointer at the top so a fresh context picks up in a single read ({{DOCTRINE:context-economy}}), and list the {{SKILL}}s the next agent should load. When the user names what the next session is for, write toward that focus.
|
|
13
15
|
6. Redact keys, passwords and PII ({{LAW:sealed-secrets}}).
|
|
14
16
|
7. Verify it: re-read the worklog as a cold reader ({{LAW:verify-before-asserting}}) — goal, progress, next step, and blockers must be answerable from it alone. Fix what isn't.
|
|
15
17
|
|
package/src/skills/learn-mode.md
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
<!-- invocation: user -->
|
|
6
6
|
|
|
7
|
+
{{CREDIT:vibe-wise:skills/learn/behavior.md}}
|
|
8
|
+
|
|
7
9
|
**Trigger:** the user wants to *learn while building* rather than be handed finished code.
|
|
8
10
|
Phrases: "learn mode", "turn on learning", "I want to understand what we build", "let me design it,
|
|
9
11
|
you write it". Also "pause learning" / "resume learning" / "stop learn mode". To be taught a
|
|
@@ -11,8 +13,7 @@ topic outside a build, use the [teach {{SKILL}}](teach.md); to have knowledge te
|
|
|
11
13
|
[quiz {{SKILL}}](quiz.md).
|
|
12
14
|
|
|
13
15
|
The user is the engineer and owns the design; you write the code for the design they
|
|
14
|
-
chose and understand. Learning and the user's control outrank build speed.
|
|
15
|
-
from [VibeWise](https://github.com/nykooi1/vibe-wise) (MIT); this is a rewrite, not a copy.
|
|
16
|
+
chose and understand. Learning and the user's control outrank build speed.
|
|
16
17
|
|
|
17
18
|
## State — `.geneseed/learn.md`
|
|
18
19
|
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
> {{DESC_PARALLEL_AGENTS}}
|
|
4
4
|
|
|
5
|
+
{{CREDIT:superpowers:skills/subagent-driven-development/SKILL.md}}
|
|
6
|
+
|
|
7
|
+
{{CREDIT:mattpocock-skills:skills/engineering/implement-spec/SKILL.md}}
|
|
8
|
+
|
|
5
9
|
**Trigger:** two or more independent subtasks with no shared state or ordering between them — and a tool that can run subagents. The units run side by side and never see each other's work; when one agent must build on what the previous one produced, that is a relay — use [pipeline](pipeline.md).
|
|
6
10
|
|
|
7
11
|
## Procedure
|
|
@@ -10,7 +14,7 @@
|
|
|
10
14
|
3. Dispatch each unit to its own subagent in one batch, each under a handoff envelope: the unit's goal, the inputs it needs, its **write set** (edit nothing outside it; return rows for a shared file instead of writing it), the observable check that proves it done, its output contract — naming every file it changed — and the inherited constraints (no commit/push — {{DOCTRINE:consent-before-push}} stays with you; no sub-agents of its own — review comes from you; gaps reported, never invented). Hand each unit only the access its goal needs ({{LAW:least-privilege}}). Prefer the read-only [explorer {{AGENT}}](../{{DIR_AGENTS}}/explorer.md) for investigation so the heavy reading stays out of the main context ({{DOCTRINE:context-economy}}). Where no subagent capability exists, run the units sequentially as personas instead, converging the same way.
|
|
11
15
|
4. Keep the main context lean: collect each subagent's distilled result, not its working transcript.
|
|
12
16
|
5. Converge: compare each unit's changed files against its write set and against its siblings' — an edit outside the set, a file two units touched, or a file in a batch's set that never changed is a conflict you resolve before anything else — apply the shared-file rows yourself, then verify the combined outcome. A conflict or ambiguity between the plan, the findings and the code is yours to decide: decide it, record `Ruling: <choice> — <why> — <cost if wrong>` in the worklog, and continue. Stop only for what {{LAW:echo-the-intent}}, {{LAW:deletion-is-deliberate}} or {{DOCTRINE:consent-before-push}} names; every ruling goes in the final report ({{DOCTRINE:declare-the-judgment-calls}}).
|
|
13
|
-
6. **A plan with blocking edges.** To build a [plan](plan.md) file's slices — each with its `Blocked by:` line — in one run, dispatch every unblocked slice on its own branch off one integration branch, merge each into it as it returns (each merge is a commit — {{DOCTRINE:consent-before-push}} stays with you), and recompute the unblocked set from the plan after every merge — newly freed slices go out at once. When the plan names a `Spec:`, every slice reads it once; the spec outranks the plan where they conflict.
|
|
17
|
+
6. **A plan with blocking edges.** To build a [plan](plan.md) file's slices — each with its `Blocked by:` line — in one run, dispatch every unblocked slice on its own branch off one integration branch, merge each into it as it returns (each merge is a commit — {{DOCTRINE:consent-before-push}} stays with you), and recompute the unblocked set from the plan after every merge — newly freed slices go out at once. When the plan names a `Spec:`, every slice reads it once; the spec outranks the plan where they conflict. Each slice branches off the integration tip at its own dispatch (its BASE) and merges the current tip back into its branch before returning, so a conflict with a sibling resolves on the slice's branch; before re-running the proof, confirm the branch descends from BASE and the diff is non-empty — an empty diff is a failure, not a clean result. Never diff against `HEAD~1`. When the plan is exhausted, review the integration branch whole with [geneseed-code-review](geneseed-code-review.md) before reporting.
|
|
14
18
|
|
|
15
19
|
## Done when
|
|
16
20
|
- Independent units ran concurrently, each returned a distilled result, and the reconciled outcome is verified.
|
package/src/skills/pipeline.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
> {{DESC_PIPELINE}}
|
|
4
4
|
|
|
5
|
+
{{CREDIT:superpowers:skills/subagent-driven-development/SKILL.md}}
|
|
6
|
+
|
|
5
7
|
**Trigger:** [foreman mode](../modes/foreman.md) routes a triaged *substantial* task here; also directly invocable without that mode whenever the user asks to "run a pipeline" for a development, documentation, research, or review task. The crew is a relay, not a fan-out: its agents take turns in one worktree, each handed what the previous one produced — for independent subtasks run side by side, use [parallel-agents](parallel-agents.md).
|
|
6
8
|
|
|
7
9
|
## What it is
|
package/src/skills/plan.md
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
> {{DESC_PLAN}}
|
|
4
4
|
|
|
5
|
+
{{CREDIT:superpowers:skills/writing-plans/SKILL.md}}
|
|
6
|
+
|
|
7
|
+
{{CREDIT:mattpocock-skills:skills/engineering/to-tickets/SKILL.md}}
|
|
8
|
+
|
|
5
9
|
**Trigger:** a task with more than a couple of steps, or touching several files
|
|
6
10
|
({{DOCTRINE:plan-before-acting}}).
|
|
7
11
|
|
|
@@ -16,10 +20,13 @@
|
|
|
16
20
|
which the work can be verified and reviewed. Cut the steps as **vertical slices** —
|
|
17
21
|
thin end-to-end pieces, each green and verifiable on its own, never one horizontal
|
|
18
22
|
layer at a time — and give each a `Blocked by:` line naming the slices it waits on
|
|
19
|
-
(`none` when it can start now).
|
|
23
|
+
(`none` when it can start now). Size each slice to finish in one fresh context. When the
|
|
24
|
+
code fights the change, the first slice is a prefactor, behaviour unchanged, that makes
|
|
25
|
+
the change easy. Sequence a wide refactor as expand → migrate
|
|
20
26
|
callers in batches → contract, so every slice leaves the build green. A step records
|
|
21
27
|
decisions, not code: the files, the exact signatures and the spec's values, the test
|
|
22
|
-
that proves it
|
|
28
|
+
that proves it (through an existing seam, as high as possible; a new seam is a decision,
|
|
29
|
+
named as one), and the check command. Write a body only for an algorithm those leave
|
|
23
30
|
open; a plan longer than the code it describes has written the code, and "TBD",
|
|
24
31
|
"handle edge cases" or "add tests" decide nothing. The file's first line names the
|
|
25
32
|
task or branch, then `Spec: <path>` when a spec exists — the spec outranks the plan
|
package/src/skills/prototype.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
> {{DESC_PROTOTYPE}}
|
|
4
4
|
|
|
5
|
+
{{CREDIT:mattpocock-skills:skills/engineering/prototype/SKILL.md}}
|
|
6
|
+
|
|
5
7
|
**Trigger:** a design question needs a runnable answer — "does this state
|
|
6
8
|
model feel right?" or "what should this look like?" — before committing to a
|
|
7
9
|
real implementation.
|
|
@@ -18,14 +20,16 @@ real implementation.
|
|
|
18
20
|
state the assumption.
|
|
19
21
|
2. Throwaway from day one, and marked as such: place it near the code it
|
|
20
22
|
prototypes for, but name it so a casual reader sees it is not production.
|
|
21
|
-
No persistence (state lives in memory)
|
|
23
|
+
No persistence (state lives in memory) and no real mutations (a variant that must
|
|
24
|
+
write hits a stub), no tests, no error handling beyond
|
|
22
25
|
what makes it runnable, no abstractions ({{DOCTRINE:smallest-viable-diff}}).
|
|
23
26
|
3. One command to run, using the project's existing task runner — the user
|
|
24
27
|
must be able to start it without thinking.
|
|
25
28
|
4. Surface the full relevant state after every action or variant switch, so
|
|
26
29
|
the user sees exactly what changed.
|
|
27
30
|
5. When the question is answered: fold the validated decision (and a logic
|
|
28
|
-
prototype's pure module) into the real code
|
|
31
|
+
prototype's pure module) into the real code (a winning UI variant is rewritten to production standard, never
|
|
32
|
+
promoted as-is), record the verdict and the
|
|
29
33
|
question it settled (issue comment, ADR, or commit message), park the prototype on a throwaway branch, and keep the
|
|
30
34
|
main branch clean of prototype code.
|
|
31
35
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# {{SKILL}}: react — accessibility
|
|
2
|
+
|
|
3
|
+
{{CREDIT:everything-claude-code:skills/frontend-a11y/SKILL.md}}
|
|
4
|
+
|
|
5
|
+
Accessibility for React components: what to write, and what the reviewer will refuse.
|
|
6
|
+
|
|
7
|
+
## Semantic HTML first
|
|
8
|
+
- A clickable thing is a `<button>` (an action) or an `<a href>` (navigation). `<div onClick>` is not keyboard-reachable and has no role; do not add `role` and `tabIndex` to make it one.
|
|
9
|
+
- One `<main>`, landmarks (`<nav>`, `<header>`, `<footer>`), headings in order without skipped levels.
|
|
10
|
+
- `<img>` always has `alt`: a description for content, `alt=""` for decoration. An icon-only button has `aria-label`.
|
|
11
|
+
|
|
12
|
+
## Forms
|
|
13
|
+
- Every input has a label: `<label htmlFor={id}>` with `useId()` for the id, or `aria-label` when the label is visual only.
|
|
14
|
+
- Required fields carry `required` (or `aria-required`), not only a red asterisk.
|
|
15
|
+
- An error is linked with `aria-describedby`, flags the field `aria-invalid="true"`, and is announced (`role="alert"` on the message). Never signal an error by colour alone.
|
|
16
|
+
- Use a real `<form>` with `onSubmit` so Enter submits; inputs have a `name`.
|
|
17
|
+
|
|
18
|
+
## Dynamic content
|
|
19
|
+
- A status that changes without focus moving (saved, loading, results count) sits in an `aria-live="polite"` region that is present before its text changes.
|
|
20
|
+
- A disclosure (accordion, dropdown) toggles `aria-expanded` on its trigger and points `aria-controls` at the panel.
|
|
21
|
+
|
|
22
|
+
## Keyboard and focus
|
|
23
|
+
- Every interaction works with Tab, Shift+Tab, Enter, Space and Escape. A custom widget (menu, listbox, tabs) follows the WAI-ARIA Authoring Practices pattern for it, arrow keys included; prefer the project's component library over hand-rolling one.
|
|
24
|
+
- A modal moves focus into itself on open, traps it, closes on Escape and returns focus to the trigger on close. The native `<dialog>` with `showModal()` does most of this.
|
|
25
|
+
- On a client-side route change, move focus to the new page's heading or main region.
|
|
26
|
+
- Never remove the focus outline without a visible replacement (`:focus-visible`).
|
|
27
|
+
|
|
28
|
+
## Motion
|
|
29
|
+
Respect `prefers-reduced-motion`: disable or shorten non-essential animation under it.
|
|
30
|
+
|
|
31
|
+
## Checking
|
|
32
|
+
- `eslint-plugin-jsx-a11y` in the lint config.
|
|
33
|
+
- `jest-axe` in component tests for interactive components (react-testing skill). jsdom has no layout, so contrast and focus-visible need a real browser check.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# {{SKILL}}: react — Vite
|
|
2
|
+
|
|
3
|
+
{{CREDIT:everything-claude-code:skills/vite-patterns/SKILL.md}}
|
|
4
|
+
|
|
5
|
+
Configuration, environment variables and build failures for a React app on Vite. Check the Vite major in `package.json` before reaching for an option; config keys move between majors.
|
|
6
|
+
|
|
7
|
+
## Config
|
|
8
|
+
- One `vite.config.ts` (or `.js`) with `defineConfig`. React support is `@vitejs/plugin-react` or `@vitejs/plugin-react-swc`; keep whichever the project has.
|
|
9
|
+
- Path aliases are declared twice: `resolve.alias` in the Vite config and `paths` in `tsconfig.json` / `jsconfig.json` (or the `vite-tsconfig-paths` plugin reads the second). Jest needs a third copy in `moduleNameMapper` (react-testing skill).
|
|
10
|
+
- Dev API calls go through `server.proxy` (`'/api': { target: 'http://localhost:8080', changeOrigin: true }`), not a hard-coded backend URL in the code.
|
|
11
|
+
|
|
12
|
+
## Environment variables
|
|
13
|
+
- Client code reads `import.meta.env.VITE_*`. Only `VITE_`-prefixed variables reach the bundle, and they are inlined at build time: changing one means rebuilding, and every value is public.
|
|
14
|
+
- `process.env` does not exist in client code; do not add a polyfill to make it work.
|
|
15
|
+
- `.env.local` and `.env.*.local` stay out of git. A per-environment value that must change without a rebuild comes from a runtime config file (`/config.json`) fetched at start, not from `VITE_*`.
|
|
16
|
+
- TypeScript: declare the variables in `src/vite-env.d.ts` (`interface ImportMetaEnv { readonly VITE_API_URL: string }`).
|
|
17
|
+
|
|
18
|
+
## Type and lint checks
|
|
19
|
+
`vite build` transpiles but never type-checks. Keep `tsc --noEmit` (or `tsc -b`) in the build script or CI, and ESLint with `eslint-plugin-react-hooks` (`rules-of-hooks`, `exhaustive-deps`) and `eslint-plugin-jsx-a11y`.
|
|
20
|
+
|
|
21
|
+
## Build failures
|
|
22
|
+
Run the project's own `build` script, read the first error, fix only that, rebuild. One error at a time.
|
|
23
|
+
|
|
24
|
+
| Error | Cause | Fix |
|
|
25
|
+
|---|---|---|
|
|
26
|
+
| `Invalid hook call` | Two copies of React | `npm ls react` must show one; dedupe with `overrides` in `package.json` |
|
|
27
|
+
| `Element type is invalid ... got: undefined` | Default vs named import mismatch | Match the import to the component's export |
|
|
28
|
+
| `Cannot find module 'react'` types (TS) | `@types/react` missing or a different major than `react` | Install the matching `@types/react` and `@types/react-dom` |
|
|
29
|
+
| `Failed to resolve import "@/..."` | Alias in tsconfig but not in Vite | Add it to `resolve.alias` or use `vite-tsconfig-paths` |
|
|
30
|
+
| `require is not defined` / CJS-only dependency errors | CommonJS dependency in the ESM pipeline | Add it to `optimizeDeps.include`; prefer an ESM build of the library |
|
|
31
|
+
| Works in `vite dev`, broken after `vite build` | Dev serves unbundled modules | Reproduce with `vite build && vite preview`, not dev |
|
|
32
|
+
| Blank page or 404 on assets after deploy | App served from a sub-path | Set `base` to that path |
|
|
33
|
+
| Old chunk 404 after a deploy | Browser holds the previous `index.html` | Serve `index.html` with `Cache-Control: no-cache`; hashed assets can stay immutable |
|
|
34
|
+
|
|
35
|
+
Never silence a build or type error with `// @ts-ignore`, `any` or a disabled lint rule; fix the cause or stop and report it.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# {{SKILL}}: react — webpack
|
|
2
|
+
|
|
3
|
+
Configuration, client-side routing, environment variables and build failures for a React app on webpack. Check the webpack major in `package.json` first: webpack 5 removed the Node core-module polyfills and the `process` global that 4 shipped, and most config questions turn on that.
|
|
4
|
+
|
|
5
|
+
## Config
|
|
6
|
+
- The config is `webpack.config.*`, often split into `common`/`dev`/`prod` files joined with `webpack-merge`; edit the file the setting belongs to, not the merged result. Read the `build` and `start` scripts to see which file each loads.
|
|
7
|
+
- JSX and TypeScript go through `babel-loader` (`@babel/preset-react` with `runtime: 'automatic'`, `@babel/preset-typescript`), `ts-loader` or `swc-loader`; keep whichever the project has. A loader rule's `test` must match `.jsx`/`.tsx`, and `resolve.extensions` must list them.
|
|
8
|
+
- Path aliases are declared twice: `resolve.alias` in the webpack config and `paths` in `tsconfig.json` / `jsconfig.json` (or `tsconfig-paths-webpack-plugin` reads the second). Jest needs a third copy in `moduleNameMapper` (react-testing skill).
|
|
9
|
+
|
|
10
|
+
## Client-side routing
|
|
11
|
+
- With `BrowserRouter` (or any history-API router), the dev server needs `devServer.historyApiFallback: true`, or a refresh on `/users/42` is a 404. The production server needs the same fallback to `index.html`; that is server config, not webpack.
|
|
12
|
+
- Set `output.publicPath` to `'/'` (or the deploy sub-path). A relative public path makes chunks load from `/users/main.js` on a nested route.
|
|
13
|
+
- Split per route with `React.lazy(() => import('./pages/Users'))`; webpack turns each dynamic `import()` into its own chunk. Do not add an entry point per route to a single-page app.
|
|
14
|
+
- Dev API calls go through `devServer.proxy`, not a hard-coded backend URL in the code.
|
|
15
|
+
|
|
16
|
+
## Environment variables
|
|
17
|
+
- `process.env.X` in client code is not read at runtime: `DefinePlugin`, `EnvironmentPlugin` or `dotenv-webpack` replaces it with a literal at build time. Changing one means rebuilding, and every value is public. `mode` sets `process.env.NODE_ENV`.
|
|
18
|
+
- On webpack 5 an undefined `process.env.X` is `process is not defined` at runtime. Define the variable; do not add a `process` polyfill through `ProvidePlugin`.
|
|
19
|
+
- `.env.local` stays out of git. A per-environment value that must change without a rebuild comes from a runtime config file (`/config.json`) fetched at start.
|
|
20
|
+
|
|
21
|
+
## Type and lint checks
|
|
22
|
+
`babel-loader`, `swc-loader` and `ts-loader` with `transpileOnly` never type-check. Keep `tsc --noEmit` in the build script or CI (or `fork-ts-checker-webpack-plugin`), and ESLint with `eslint-plugin-react-hooks` and `eslint-plugin-jsx-a11y`.
|
|
23
|
+
|
|
24
|
+
## Build failures
|
|
25
|
+
Run the project's own `build` script, read the first error, fix only that, rebuild. One error at a time.
|
|
26
|
+
|
|
27
|
+
| Error | Cause | Fix |
|
|
28
|
+
|---|---|---|
|
|
29
|
+
| `Invalid hook call` | Two copies of React | `npm ls react` must show one; dedupe with `overrides`, or `resolve.alias` `react` to one path for a linked package. Module Federation: `shared: { react: { singleton: true }, 'react-dom': { singleton: true } }` |
|
|
30
|
+
| `Module not found: Can't resolve '@/...'` | Alias in tsconfig but not in webpack | Add it to `resolve.alias` |
|
|
31
|
+
| `Can't resolve './Button'` for a `.tsx` file | Extension not resolved | Add `.tsx`/`.jsx` to `resolve.extensions` |
|
|
32
|
+
| `Module parse failed: Unexpected token` on JSX | No loader matched the file | Widen the rule's `test`, or narrow an `exclude` that drops the folder |
|
|
33
|
+
| `BREAKING CHANGE: webpack < 5 used to include polyfills` | A dependency imports a Node core module | Prefer a browser build of the dependency; otherwise `resolve.fallback` with a named polyfill package |
|
|
34
|
+
| `process is not defined` | `process.env.X` not defined at build time | Add it to `DefinePlugin` / `EnvironmentPlugin` |
|
|
35
|
+
| 404 on refresh of a deep link | No history fallback | `devServer.historyApiFallback: true`, and the same fallback on the production server |
|
|
36
|
+
| Blank page on a nested route, chunk 404s | Relative `output.publicPath` | Set `output.publicPath: '/'` or the deploy sub-path |
|
|
37
|
+
| Works with `start`, broken after `build` | Dev and production configs differ | Build with `mode: 'production'` and serve `dist/` with a static server to reproduce |
|
|
38
|
+
| `ChunkLoadError` after a deploy | Browser holds the previous `index.html` | `[contenthash]` in chunk names, and serve `index.html` with `Cache-Control: no-cache` |
|
|
39
|
+
|
|
40
|
+
Never silence a build or type error with `// @ts-ignore`, `any` or a disabled lint rule; fix the cause or stop and report it.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# {{SKILL}}: react-testing
|
|
2
|
+
|
|
3
|
+
> {{DESC_REACT_TESTING}}
|
|
4
|
+
|
|
5
|
+
{{CREDIT:everything-claude-code:skills/react-testing/SKILL.md}}
|
|
6
|
+
|
|
7
|
+
**Trigger:** writing or fixing tests for React components, hooks or pages in a Vite or webpack project tested with Jest and React Testing Library, in TypeScript or JavaScript; or getting Jest to run at all against bundler-shaped code. React-specific; core test discipline lives in the develop skill. End-to-end flows across pages belong to the project's browser tests (Playwright, Cypress), not here.
|
|
8
|
+
|
|
9
|
+
Target stack: Jest, `@testing-library/react`, `@testing-library/user-event`, `@testing-library/jest-dom`, MSW for network mocks, `jest-axe`.
|
|
10
|
+
|
|
11
|
+
## What a test does
|
|
12
|
+
Render the component with the providers it has in production, act through `userEvent` the way a user would, assert what the user sees or what leaves the component (a callback called, a request sent). Never assert on internal state, hook calls, props passed to children, or render counts. Never mock React.
|
|
13
|
+
|
|
14
|
+
## Queries, in this order
|
|
15
|
+
1. `getByRole(..., { name })`, `getByLabelText`: what assistive technology sees. A test that cannot find the button by role has found an accessibility bug.
|
|
16
|
+
2. `getByText`, `getByDisplayValue`, `getByAltText`.
|
|
17
|
+
3. `getByTestId`: last resort.
|
|
18
|
+
|
|
19
|
+
`getBy*` throws when missing; `queryBy*` returns `null` (assert absence); `findBy*` waits (things that appear after async work). No `container.querySelector`.
|
|
20
|
+
|
|
21
|
+
## Interaction and async
|
|
22
|
+
```tsx
|
|
23
|
+
test('saves the email', async () => {
|
|
24
|
+
const user = userEvent.setup();
|
|
25
|
+
const onSave = jest.fn();
|
|
26
|
+
render(<EmailForm onSave={onSave} />);
|
|
27
|
+
|
|
28
|
+
await user.type(screen.getByLabelText('Email'), 'a@example.com');
|
|
29
|
+
await user.click(screen.getByRole('button', { name: /save/i }));
|
|
30
|
+
|
|
31
|
+
expect(onSave).toHaveBeenCalledWith('a@example.com');
|
|
32
|
+
});
|
|
33
|
+
```
|
|
34
|
+
- `userEvent.setup()` once per test, every call awaited. `fireEvent` only for an event `userEvent` cannot produce.
|
|
35
|
+
- Wait with `findBy*` or `waitFor`; never `setTimeout` or a sleep. With `jest.useFakeTimers()`, pass `userEvent.setup({ advanceTimers: jest.advanceTimersByTime })`.
|
|
36
|
+
- An `act(...)` warning is a real bug (an update after the test ended or an unawaited promise); fix it, do not silence `console.error`.
|
|
37
|
+
|
|
38
|
+
## Network with MSW
|
|
39
|
+
Mock at the network layer, so the fetch client and the server-state library run as in production. Start the server in the setup file with `onUnhandledRequest: 'error'`, `resetHandlers()` after each test, override per test with `server.use(...)`. Each test covers the error and empty responses, not only success.
|
|
40
|
+
|
|
41
|
+
## Providers
|
|
42
|
+
One `renderWithProviders` in a test-utils file wraps the router (`MemoryRouter`), the store and the query client. Create a fresh query client per test with `retry: false`, so cache and retries never leak between tests. Hooks: `renderHook` from `@testing-library/react`, with the same wrapper.
|
|
43
|
+
|
|
44
|
+
## Accessibility
|
|
45
|
+
`expect(await axe(container)).toHaveNoViolations()` (`jest-axe`) on every interactive component. jsdom has no layout: contrast and focus visibility need a browser.
|
|
46
|
+
|
|
47
|
+
## Jest beside the bundler
|
|
48
|
+
The bundler and Jest resolve code differently; each gap is configured once in `jest.config.*`. Rows marked Vite or webpack apply only to that bundler:
|
|
49
|
+
|
|
50
|
+
| Gap | Fix |
|
|
51
|
+
|---|---|
|
|
52
|
+
| No DOM | `testEnvironment: 'jsdom'` with `jest-environment-jsdom` installed; with MSW 2 use `jest-fixed-jsdom`, which keeps Node's `fetch` globals |
|
|
53
|
+
| JSX / TS not transformed | `babel-jest` with `@babel/preset-env`, `@babel/preset-react` (`runtime: 'automatic'`), `@babel/preset-typescript`; or `ts-jest` / `@swc/jest`, whichever the project has |
|
|
54
|
+
| Vite: `import.meta.env` is a syntax error | Read env in one module (`src/config/env.ts`) and replace it in tests via `moduleNameMapper` or `jest.mock`; do not scatter `import.meta.env` |
|
|
55
|
+
| Path aliases (`@/...`) | Mirror the bundler's `resolve.alias` in `moduleNameMapper` |
|
|
56
|
+
| webpack: `process.env.X` is `undefined` in tests | Jest does not run `DefinePlugin`; set the values in a `setupFiles` module |
|
|
57
|
+
| webpack: `require.context is not a function` | Jest has no `require.context`; import the modules explicitly, or mock the module that calls it |
|
|
58
|
+
| CSS and asset imports | `identity-obj-proxy` for CSS modules, a file stub for images and SVG |
|
|
59
|
+
| ESM-only package in `node_modules` | Let it through `transformIgnorePatterns: ['node_modules/(?!(pkg-a|pkg-b)/)']` |
|
|
60
|
+
| `toBeInTheDocument` undefined | `import '@testing-library/jest-dom'` in a `setupFilesAfterEnv` file |
|
|
61
|
+
|
|
62
|
+
## Snapshots
|
|
63
|
+
No snapshots of rendered components: they break on every markup change and get approved unread. Snapshot only a pure data serialiser.
|
|
64
|
+
|
|
65
|
+
## Done when
|
|
66
|
+
- The new tests fail without the change and pass with it; the project's test script passes, read from real output; no `act` warning, no unhandled MSW request, no skipped test left behind.
|
|
67
|
+
|
|
68
|
+
<!-- INCLUDE: skills/_self-improvement.md -->
|