* chore(#604): rename get-shit-done/ runtime directory to gsd-core/ Renames the installed runtime directory `get-shit-done/` to `gsd-core/` so the on-disk name matches the package (`@opengsd/gsd-core`), repo, and binary (`gsd-tools`). The npm package name and binary are unchanged; npx/npm consumers are unaffected. Mechanical (bulk, ~90% of the diff): - `git mv get-shit-done gsd-core` - Swept path/identifier references across the repo via `perl -pe 's/get-shit-done(?!-\w)/gsd-core/g'`. The negative lookahead preserves the five legitimate slug variants that are NOT the directory: get-shit-done-{OLD,cc,classic,cli,redux} (old package/repo names). - Build/manifest wiring: package.json (bin, files, coverage globs), tsconfig.build.json (outDir), ~86 .gitignore build-output entries, stryker.config.mjs, scan-ignore files, install.js path strings. - Frozen (not rewritten): CHANGELOG.md history; translated docs (README.<locale>.md and docs/{ja-JP,ko-KR,pt-BR,zh-CN}/). New logic (review here): - src/installer-migrations/003-rename-get-shit-done-to-gsd-core.cts: a proper ADR-0008 installer migration. On upgrade it walks the legacy `~/.claude/get-shit-done/` tree, classifies each file via the prior install manifest, and emits remove-managed / backup-and-remove for managed files while PRESERVING unknown user-added files. Symlink-safe (skips a symlinked root and symlinked entries; bounds-checks every path under configDir). The framework rolls back on install failure. Emptied dirs may remain (framework has no recursive dir-removal primitive) — documented. - scripts/lint-legacy-dir-name.cjs: CI regression guard forbidding the bare `get-shit-done` directory token (split token to avoid self-match; case- insensitive; `(?!-\w)` lookahead allows the slug variants; allowlists CHANGELOG, translated docs, and `gsd-allow-legacy-name` marker lines). Wired into the lint-tests CI job. - Restored scripts/lint-package-identity-drift.cjs detection regexes (the mechanical sweep had wrongly rewritten the old-name patterns it exists to detect) and marked them as intentional legacy references. - TDD tests for the migration and the guard; do.md slash-command guard regex tightened so a `/gsd-core/bin` path segment is not mistaken for a command; changeset + docs/installer-migrations.md row added. Breaking: the installed runtime path moves `~/.claude/get-shit-done/` -> `~/.claude/gsd-core/`. Migration 003 removes the stale legacy dir's managed files (preserving user files) on upgrade. Users with custom hooks/configs hardcoding the old path must update them. Closes #604 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): unsweep pending changesets + allowlist injection-example docs CI fixes for the rename PR: - Do not sweep pending .changeset/*.md (ephemeral release-note fragments, like CHANGELOG); reverted those body edits so 5 pre-existing malformed fragments (missing type/pr) no longer enter the PR diff and trip docs-lint. Allowlisted .changeset/ in the legacy-name guard accordingly. - Allowlisted TEST-EXAMPLES.md and docs/explanation/security-model.md in prompt-injection-scan.sh: they contain intentional injection examples / security-model prose; the path-reference rewrites are kept. CodeQL alerts on this PR are pre-existing (alert lines unchanged by this PR; none in the new migration/guard) and are out of scope for the rename. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): resolve CodeQL alerts surfaced on this PR The rename diff touched files carrying pre-existing CodeQL findings; per the no-pre-existing-dismissal rule, fixing every surfaced alert rather than waving them off. All behavior-preserving: - scripts/ci-test-scope.cjs: build the config-path match from string .includes() instead of a RegExp over an arg-derived value (js/regex-injection). - src/profile-output.cts: escape backslashes before pipe-escaping desc/safeName so the table-cell escape is complete (js/incomplete-sanitization). - tests/{bug-2643,bug-2808,docs-parity-live-registry}: two-pass HTML-comment strip so a bare/unclosed `<!--` cannot survive (js/incomplete-multi-character-sanitization). - tests/inline-plan-threshold: drop the no-op `\s`->`\s` identity replace, keep the meaningful POSIX-class conversion (js/identity-replacement). Verified: build:lib green; the touched test files + ci-test-scope + profile-output suites pass; lint:legacy-name clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): correctly resolve remaining CodeQL alerts (regex-injection + sanitization) The prior commit's fixes for two alerts were ineffective: - ci-test-scope.cjs js/regex-injection: the alert is the CLI-arg-derived `file` reaching static regex `.test(file)` calls (not the config rule). Removed ALL regex over file/t — startsWith/includes/=== string checks + an isWindowsHint helper — so there is no regex sink for the tainted value. - js/incomplete-multi-character-sanitization (3 test files): a single `.replace(/<!--...-->/g,'')` can let `<!--` re-form. Replaced with a fixpoint loop (replace until stable) plus a final bare-opener strip. Verified: no regex over file/t remains; ci-test-scope + the 3 test suites pass; lint:legacy-name clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): make ci-test-scope + comment-strippers regex-free to clear CodeQL CodeQL flags the regex PATTERNS syntactically (regex-injection on the --files arg split; incomplete-multi-character-sanitization on the <!--...--> replace), so loop fixes do not satisfy it. Made these paths regex-free: - ci-test-scope.cjs splitFiles: char-by-char separator tokenizer (no /[,\\s]+/). - 3 test files: indexOf/slice HTML-comment stripper (no .replace(/<!--/)). Behavior preserved; ci-test-scope + the 3 suites pass; guard clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): unblock security base64 scan on the large rename diff The security job hit its 10m timeout: base64-scan.sh choked on the binary test fixture tests/feat-3594-parser-property-style.test.cjs (embedded NUL/ non-UTF8 bytes -> thousands of bogus blobs + "ignored null byte" warnings), and the ~800-file rename diff is slow to scan regardless. - scripts/base64-scan.sh: skip binary-by-content files (grep -Iq .) — they can't carry base64-obfuscated *text* and feeding NUL bytes through the per-line scanner is pathologically slow. collect_files already filtered binary *extensions*; this catches binary *content* in text extensions. - .github/workflows/security-scan.yml: raise the security job timeout 10m->30m to accommodate very large diffs (the scan itself is unchanged). Verified locally: scan skips the fixture, 0 "ignored null byte" warnings, 0 findings, exit 0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): sweep get-shit-done refs introduced by merging next The branch was updated with next (#614/#384/#618 etc.), which reference the get-shit-done/ dir (still named that on next). Swept the stale references in the merged files to gsd-core so the rename stays consistent and lint:legacy-name passes: - commands/gsd/discuss-phase.md (runtime-launcher shim paths) - src/core.cts (getAgentsDir layout comments) - tests/bug-384-agents-runtime-aware.test.cjs (require path to runtime lib) Verified: guard 0 violations; build green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): exclude gsd-core/ path segments from bug-3683 command cross-ref invariant The #614 runtime-launcher shim added to discuss-phase.md references `${_GSD_RUNTIME_ROOT}/gsd-core/bin/...`. bug-3683's REF_PATTERN excluded path-y refs only via lookbehind, but `}` precedes `/gsd-core/` in the shim, so it mis-read the directory path as a dangling `/gsd-core` command ref (same class as the #604 bug-2954 fix). Added a trailing `(?![\w-]*\/)` so `/gsd-<x>/...` path segments are not treated as slash-command references. Verified locally on BOTH platforms before pushing: - mac (node 26) full suite: 0 failures - gsd-test-runner (linux, node22 image) full suite: 0 failures - bug-3683 + bug-2954 pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): lazily resolve findProjectRoot in gsd-tools (harden flaky CI) CI intermittently failed state.test's gsd-tools subprocess with "findProjectRoot is not a function" (flip-flopping across legs; not reproducible on mac full suite, gsd-test linux full suite, test:unit, or state.test x8). findProjectRoot is a re-export from core.cjs (sourced from project-root.cjs); binding it via destructure at module-load can be undefined under a load-ordering edge. Resolve it lazily at call time via a small wrapper so the lookup happens after core.cjs is fully initialized. Verified green on BOTH platforms before pushing: - mac (node 26) full suite: 0 failures - gsd-test-runner (linux, node22) full suite: 0 failures - state.test.cjs: 106/106; gsd-tools loads cleanly. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): allowlist verification-patterns.md placeholder examples in secret scan The rename git-mv'd references/verification-patterns.md into gsd-core/, pulling it into the secret-scan diff. It documents stub/placeholder RED-FLAG env-var examples (illustrative Stripe test-key / database-URL / API-key placeholders) — not real credentials. Added it to .secretscanignore with the strict annotation, mirroring the existing gsd-core/workflows/plan-phase.md exception. Verified locally: secret-scan-lint --strict OK; secret-scan --diff origin/next exits 0 with 0 findings. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
18 KiB
Research Template
Template for .planning/phases/XX-name/{phase_num}-RESEARCH.md - comprehensive ecosystem research before planning.
Purpose: Document what Claude needs to know to implement a phase well - not just "which library" but "how do experts build this."
File Template
# Phase [X]: [Name] - Research
**Researched:** [date]
**Domain:** [primary technology/problem domain]
**Confidence:** [HIGH/MEDIUM/LOW]
<user_constraints>
## User Constraints (from CONTEXT.md)
**CRITICAL:** If CONTEXT.md exists from /gsd:discuss-phase, copy locked decisions here verbatim. These MUST be honored by the planner.
### Locked Decisions
[Copy from CONTEXT.md `## Decisions` section - these are NON-NEGOTIABLE]
- [Decision 1]
- [Decision 2]
### Claude's Discretion
[Copy from CONTEXT.md - areas where researcher/planner can choose]
- [Area 1]
- [Area 2]
### Deferred Ideas (OUT OF SCOPE)
[Copy from CONTEXT.md - do NOT research or plan these]
- [Deferred 1]
- [Deferred 2]
**If no CONTEXT.md exists:** Write "No user constraints - all decisions at Claude's discretion"
</user_constraints>
<architectural_responsibility_map>
## Architectural Responsibility Map
Map each phase capability to its standard architectural tier owner before diving into framework research. This prevents tier misassignment from propagating into plans.
| Capability | Primary Tier | Secondary Tier | Rationale |
|------------|-------------|----------------|-----------|
| [capability from phase description] | [Browser/Client, Frontend Server, API/Backend, CDN/Static, or Database/Storage] | [secondary tier or —] | [why this tier owns it] |
**If single-tier application:** Write "Single-tier application — all capabilities reside in [tier]" and omit the table.
</architectural_responsibility_map>
<research_summary>
## Summary
[2-3 paragraph executive summary]
- What was researched
- What the standard approach is
- Key recommendations
**Primary recommendation:** [one-liner actionable guidance]
</research_summary>
<standard_stack>
## Standard Stack
The established libraries/tools for this domain:
### Core
| Library | Version | Purpose | Why Standard |
|---------|---------|---------|--------------|
| [name] | [ver] | [what it does] | [why experts use it] |
| [name] | [ver] | [what it does] | [why experts use it] |
### Supporting
| Library | Version | Purpose | When to Use |
|---------|---------|---------|-------------|
| [name] | [ver] | [what it does] | [use case] |
| [name] | [ver] | [what it does] | [use case] |
### Alternatives Considered
| Instead of | Could Use | Tradeoff |
|------------|-----------|----------|
| [standard] | [alternative] | [when alternative makes sense] |
**Installation:**
```bash
npm install [packages]
# or
yarn add [packages]
</standard_stack>
<architecture_patterns>
Architecture Patterns
System Architecture Diagram
Architecture diagrams MUST show data flow through conceptual components, not file listings.
Requirements:
- Show entry points (how data/requests enter the system)
- Show processing stages (what transformations happen, in what order)
- Show decision points and branching paths
- Show external dependencies and service boundaries
- Use arrows to indicate data flow direction
- A reader should be able to trace the primary use case from input to output by following the arrows
File-to-implementation mapping belongs in the Component Responsibilities table, not in the diagram.
Recommended Project Structure
src/
├── [folder]/ # [purpose]
├── [folder]/ # [purpose]
└── [folder]/ # [purpose]
Pattern 1: [Pattern Name]
What: [description] When to use: [conditions] Example:
// [code example from Context7/official docs]
Pattern 2: [Pattern Name]
What: [description] When to use: [conditions] Example:
// [code example]
Anti-Patterns to Avoid
- [Anti-pattern]: [why it's bad, what to do instead]
- [Anti-pattern]: [why it's bad, what to do instead] </architecture_patterns>
<dont_hand_roll>
Don't Hand-Roll
Problems that look simple but have existing solutions:
| Problem | Don't Build | Use Instead | Why |
|---|---|---|---|
| [problem] | [what you'd build] | [library] | [edge cases, complexity] |
| [problem] | [what you'd build] | [library] | [edge cases, complexity] |
| [problem] | [what you'd build] | [library] | [edge cases, complexity] |
Key insight: [why custom solutions are worse in this domain] </dont_hand_roll>
<common_pitfalls>
Common Pitfalls
Pitfall 1: [Name]
What goes wrong: [description] Why it happens: [root cause] How to avoid: [prevention strategy] Warning signs: [how to detect early]
Pitfall 2: [Name]
What goes wrong: [description] Why it happens: [root cause] How to avoid: [prevention strategy] Warning signs: [how to detect early]
Pitfall 3: [Name]
What goes wrong: [description] Why it happens: [root cause] How to avoid: [prevention strategy] Warning signs: [how to detect early] </common_pitfalls>
<code_examples>
Code Examples
Verified patterns from official sources:
[Common Operation 1]
// Source: [Context7/official docs URL]
[code]
[Common Operation 2]
// Source: [Context7/official docs URL]
[code]
[Common Operation 3]
// Source: [Context7/official docs URL]
[code]
</code_examples>
<sota_updates>
State of the Art (2024-2025)
What's changed recently:
| Old Approach | Current Approach | When Changed | Impact |
|---|---|---|---|
| [old] | [new] | [date/version] | [what it means for implementation] |
New tools/patterns to consider:
- [Tool/Pattern]: [what it enables, when to use]
- [Tool/Pattern]: [what it enables, when to use]
Deprecated/outdated:
- [Thing]: [why it's outdated, what replaced it] </sota_updates>
<open_questions>
Open Questions
Things that couldn't be fully resolved:
-
[Question]
- What we know: [partial info]
- What's unclear: [the gap]
- Recommendation: [how to handle during planning/execution]
-
[Question]
- What we know: [partial info]
- What's unclear: [the gap]
- Recommendation: [how to handle] </open_questions>
Primary (HIGH confidence)
- [Context7 library ID] - [topics fetched]
- [Official docs URL] - [what was checked]
Secondary (MEDIUM confidence)
- [WebSearch verified with official source] - [finding + verification]
Tertiary (LOW confidence - needs validation)
- [WebSearch only] - [finding, marked for validation during implementation]
Research scope:
- Core technology: [what]
- Ecosystem: [libraries explored]
- Patterns: [patterns researched]
- Pitfalls: [areas checked]
Confidence breakdown:
- Standard stack: [HIGH/MEDIUM/LOW] - [reason]
- Architecture: [HIGH/MEDIUM/LOW] - [reason]
- Pitfalls: [HIGH/MEDIUM/LOW] - [reason]
- Code examples: [HIGH/MEDIUM/LOW] - [reason]
Research date: [date] Valid until: [estimate - 30 days for stable tech, 7 days for fast-moving]
Phase: XX-name Research completed: [date] Ready for planning: [yes/no]
---
## Good Example
```markdown
# Phase 3: 3D City Driving - Research
**Researched:** 2025-01-20
**Domain:** Three.js 3D web game with driving mechanics
**Confidence:** HIGH
<research_summary>
## Summary
Researched the Three.js ecosystem for building a 3D city driving game. The standard approach uses Three.js with React Three Fiber for component architecture, Rapier for physics, and drei for common helpers.
Key finding: Don't hand-roll physics or collision detection. Rapier (via @react-three/rapier) handles vehicle physics, terrain collision, and city object interactions efficiently. Custom physics code leads to bugs and performance issues.
**Primary recommendation:** Use R3F + Rapier + drei stack. Start with vehicle controller from drei, add Rapier vehicle physics, build city with instanced meshes for performance.
</research_summary>
<standard_stack>
## Standard Stack
### Core
| Library | Version | Purpose | Why Standard |
|---------|---------|---------|--------------|
| three | 0.160.0 | 3D rendering | The standard for web 3D |
| @react-three/fiber | 8.15.0 | React renderer for Three.js | Declarative 3D, better DX |
| @react-three/drei | 9.92.0 | Helpers and abstractions | Solves common problems |
| @react-three/rapier | 1.2.1 | Physics engine bindings | Best physics for R3F |
### Supporting
| Library | Version | Purpose | When to Use |
|---------|---------|---------|-------------|
| @react-three/postprocessing | 2.16.0 | Visual effects | Bloom, DOF, motion blur |
| leva | 0.9.35 | Debug UI | Tweaking parameters |
| zustand | 4.4.7 | State management | Game state, UI state |
| use-sound | 4.0.1 | Audio | Engine sounds, ambient |
### Alternatives Considered
| Instead of | Could Use | Tradeoff |
|------------|-----------|----------|
| Rapier | Cannon.js | Cannon simpler but less performant for vehicles |
| R3F | Vanilla Three | Vanilla if no React, but R3F DX is much better |
| drei | Custom helpers | drei is battle-tested, don't reinvent |
**Installation:**
```bash
npm install three @react-three/fiber @react-three/drei @react-three/rapier zustand
</standard_stack>
<architecture_patterns>
Architecture Patterns
System Architecture Diagram
Architecture diagrams MUST show data flow through conceptual components, not file listings.
Requirements:
- Show entry points (how data/requests enter the system)
- Show processing stages (what transformations happen, in what order)
- Show decision points and branching paths
- Show external dependencies and service boundaries
- Use arrows to indicate data flow direction
- A reader should be able to trace the primary use case from input to output by following the arrows
File-to-implementation mapping belongs in the Component Responsibilities table, not in the diagram.
Recommended Project Structure
src/
├── components/
│ ├── Vehicle/ # Player car with physics
│ ├── City/ # City generation and buildings
│ ├── Road/ # Road network
│ └── Environment/ # Sky, lighting, fog
├── hooks/
│ ├── useVehicleControls.ts
│ └── useGameState.ts
├── stores/
│ └── gameStore.ts # Zustand state
└── utils/
└── cityGenerator.ts # Procedural generation helpers
Pattern 1: Vehicle with Rapier Physics
What: Use RigidBody with vehicle-specific settings, not custom physics When to use: Any ground vehicle Example:
// Source: @react-three/rapier docs
import { RigidBody, useRapier } from '@react-three/rapier'
function Vehicle() {
const rigidBody = useRef()
return (
<RigidBody
ref={rigidBody}
type="dynamic"
colliders="hull"
mass={1500}
linearDamping={0.5}
angularDamping={0.5}
>
<mesh>
<boxGeometry args={[2, 1, 4]} />
<meshStandardMaterial />
</mesh>
</RigidBody>
)
}
Pattern 2: Instanced Meshes for City
What: Use InstancedMesh for repeated objects (buildings, trees, props) When to use: >100 similar objects Example:
// Source: drei docs
import { Instances, Instance } from '@react-three/drei'
function Buildings({ positions }) {
return (
<Instances limit={1000}>
<boxGeometry />
<meshStandardMaterial />
{positions.map((pos, i) => (
<Instance key={i} position={pos} scale={[1, Math.random() * 5 + 1, 1]} />
))}
</Instances>
)
}
Anti-Patterns to Avoid
- Creating meshes in render loop: Create once, update transforms only
- Not using InstancedMesh: Individual meshes for buildings kills performance
- Custom physics math: Rapier handles it better, every time </architecture_patterns>
<dont_hand_roll>
Don't Hand-Roll
| Problem | Don't Build | Use Instead | Why |
|---|---|---|---|
| Vehicle physics | Custom velocity/acceleration | Rapier RigidBody | Wheel friction, suspension, collisions are complex |
| Collision detection | Raycasting everything | Rapier colliders | Performance, edge cases, tunneling |
| Camera follow | Manual lerp | drei CameraControls or custom with useFrame | Smooth interpolation, bounds |
| City generation | Pure random placement | Grid-based with noise for variation | Random looks wrong, grid is predictable |
| LOD | Manual distance checks | drei | Handles transitions, hysteresis |
Key insight: 3D game development has 40+ years of solved problems. Rapier implements proper physics simulation. drei implements proper 3D helpers. Fighting these leads to bugs that look like "game feel" issues but are actually physics edge cases. </dont_hand_roll>
<common_pitfalls>
Common Pitfalls
Pitfall 1: Physics Tunneling
What goes wrong: Fast objects pass through walls Why it happens: Default physics step too large for velocity How to avoid: Use CCD (Continuous Collision Detection) in Rapier Warning signs: Objects randomly appearing outside buildings
Pitfall 2: Performance Death by Draw Calls
What goes wrong: Game stutters with many buildings Why it happens: Each mesh = 1 draw call, hundreds of buildings = hundreds of calls How to avoid: InstancedMesh for similar objects, merge static geometry Warning signs: GPU bound, low FPS despite simple scene
Pitfall 3: Vehicle "Floaty" Feel
What goes wrong: Car doesn't feel grounded Why it happens: Missing proper wheel/suspension simulation How to avoid: Use Rapier vehicle controller or tune mass/damping carefully Warning signs: Car bounces oddly, doesn't grip corners </common_pitfalls>
<code_examples>
Code Examples
Basic R3F + Rapier Setup
// Source: @react-three/rapier getting started
import { Canvas } from '@react-three/fiber'
import { Physics } from '@react-three/rapier'
function Game() {
return (
<Canvas>
<Physics gravity={[0, -9.81, 0]}>
<Vehicle />
<City />
<Ground />
</Physics>
</Canvas>
)
}
Vehicle Controls Hook
// Source: Community pattern, verified with drei docs
import { useFrame } from '@react-three/fiber'
import { useKeyboardControls } from '@react-three/drei'
function useVehicleControls(rigidBodyRef) {
const [, getKeys] = useKeyboardControls()
useFrame(() => {
const { forward, back, left, right } = getKeys()
const body = rigidBodyRef.current
if (!body) return
const impulse = { x: 0, y: 0, z: 0 }
if (forward) impulse.z -= 10
if (back) impulse.z += 5
body.applyImpulse(impulse, true)
if (left) body.applyTorqueImpulse({ x: 0, y: 2, z: 0 }, true)
if (right) body.applyTorqueImpulse({ x: 0, y: -2, z: 0 }, true)
})
}
</code_examples>
<sota_updates>
State of the Art (2024-2025)
| Old Approach | Current Approach | When Changed | Impact |
|---|---|---|---|
| cannon-es | Rapier | 2023 | Rapier is faster, better maintained |
| vanilla Three.js | React Three Fiber | 2020+ | R3F is now standard for React apps |
| Manual InstancedMesh | drei | 2022 | Simpler API, handles updates |
New tools/patterns to consider:
- WebGPU: Coming but not production-ready for games yet (2025)
- drei Gltf helpers: <useGLTF.preload> for loading screens
Deprecated/outdated:
- cannon.js (original): Use cannon-es fork or better, Rapier
- Manual raycasting for physics: Just use Rapier colliders </sota_updates>
Primary (HIGH confidence)
- /pmndrs/react-three-fiber - getting started, hooks, performance
- /pmndrs/drei - instances, controls, helpers
- /dimforge/rapier-js - physics setup, vehicle physics
Secondary (MEDIUM confidence)
- Three.js discourse "city driving game" threads - verified patterns against docs
- R3F examples repository - verified code works
Tertiary (LOW confidence - needs validation)
- None - all findings verified
Research scope:
- Core technology: Three.js + React Three Fiber
- Ecosystem: Rapier, drei, zustand
- Patterns: Vehicle physics, instancing, city generation
- Pitfalls: Performance, physics, feel
Confidence breakdown:
- Standard stack: HIGH - verified with Context7, widely used
- Architecture: HIGH - from official examples
- Pitfalls: HIGH - documented in discourse, verified in docs
- Code examples: HIGH - from Context7/official sources
Research date: 2025-01-20 Valid until: 2025-02-20 (30 days - R3F ecosystem stable)
Phase: 03-city-driving Research completed: 2025-01-20 Ready for planning: yes
---
## Guidelines
**When to create:**
- Before planning phases in niche/complex domains
- When Claude's training data is likely stale or sparse
- When "how do experts do this" matters more than "which library"
**Structure:**
- Use XML tags for section markers (matches GSD templates)
- Seven core sections: summary, standard_stack, architecture_patterns, dont_hand_roll, common_pitfalls, code_examples, sources
- All sections required (drives comprehensive research)
**Content quality:**
- Standard stack: Specific versions, not just names
- Architecture: Include actual code examples from authoritative sources
- Don't hand-roll: Be explicit about what problems to NOT solve yourself
- Pitfalls: Include warning signs, not just "don't do this"
- Sources: Mark confidence levels honestly
**Integration with planning:**
- RESEARCH.md loaded as @context reference in PLAN.md
- Standard stack informs library choices
- Don't hand-roll prevents custom solutions
- Pitfalls inform verification criteria
- Code examples can be referenced in task actions
**After creation:**
- File lives in phase directory: `.planning/phases/XX-name/{phase_num}-RESEARCH.md`
- Referenced during planning workflow
- plan-phase loads it automatically when present