diff --git a/.claude/skills/dots-dev/SKILL.md b/.claude/skills/dots-dev/SKILL.md index ef2ac00d5..f880afc3f 100644 --- a/.claude/skills/dots-dev/SKILL.md +++ b/.claude/skills/dots-dev/SKILL.md @@ -1,221 +1,131 @@ --- name: dots-dev -description: Run an adaptive Unity DOTS + Netcode for Entities dev session — sizes the task (trivial / small / feature), then orchestrates context7-led research, plan-mode-gated design, parallel agent swarms, DOTS-correct implementation, DOTS-aware validation, and a mandatory vault + memory update. Use when the operator types /dots-dev, "dots-dev", or opens a session on a Unity DOTS / ECS / Netcode-for-Entities project (anything like "let's work on ", "dots-dev: implement X", "design Y system", or other dev-session openings). Use as the default driver for any non-trivial DOTS work. Defaults all API/code research to context7. Detects a missing DOTS foundation and defers to the one-time project setup task rather than setting up inline. +description: Orchestrates a Unity DOTS (Entities) + Netcode-for-Entities dev session — grounding, design-review, plan-gated implementation, validation, and a doc bookend. Use when the operator types /dots-dev or opens DOTS/ECS/Netcode work ("let's work on ", "implement X", "design Y system"). The default driver for non-trivial DOTS work; defers a missing DOTS foundation to the one-time setup task. --- # /dots-dev — Adaptive Unity DOTS / Netcode Dev Session Orchestrator -Drives an end-to-end Unity 6 development session for a **DOTS (Entities) + Netcode for Entities** game. The genre is project-specific (read it from `CLAUDE.md` + the vault); the constant is the tech stack: **data-oriented ECS, Burst, jobs, baking, server-authoritative netcode with client prediction**. +Drives a Unity 6.5 **DOTS (Entities) + Netcode for Entities** session. **`CLAUDE.md` (always-loaded) is authoritative** for conventions, build gotchas, the MCP cheat-sheet, anti-patterns, the memory layers, git rules, and the bootstrap/world model — this skill does not re-teach them; it carries the **orchestration process** CLAUDE.md lacks, and inlines only the few highest-recurrence gates it directly depends on (flagged ★). When the two disagree, `CLAUDE.md` wins. -This skill is **adaptive**: it sizes the task first, then runs only the phases that size needs. It is **reusable and path-portable** — it hardcodes no machine-specific absolute paths and works identically on macOS and Windows. It defaults every API / best-practice question to **context7** (Unity's DOTS APIs move fast). It keeps two things non-negotiable at every size: the **plan-approval gate** (`ExitPlanMode` before any state change) and the **doc + memory update** at session end. +The spine: **size by blast-radius → ground → (design-review) → plan-gate → serial implement → verify-ladder → (diff-review) → doc/memory bookend → offer commit.** Two adversarial reviews bookend the code; everything else flexes by size. -> **One-line reminder**: set max reasoning before invoking a Feature-track session. `/dots-dev` Feature track is heavy by design. +## Non-negotiables (every track) -## Core principles (read first) - -1. **context7-first for anything DOTS.** Any API name, signature, pattern, or "current best practice" for Entities / Netcode / Physics / Burst / Collections is resolved through **context7** (`resolve-library-id` → `query-docs`) before it is written, and cross-checked against the official ECS Samples repo. Do not trust training-data recall for these — they change between minor versions. See [`references/context7-libraries.md`](references/context7-libraries.md). -2. **DOTS-correct, not MonoBehaviour-correct.** The conventions are ECS conventions. `ISystem`+Burst by default, `IComponentData`/buffers/enableable, baking, jobs, `EntityCommandBuffer`, determinism. The classic-Unity rules (MonoBehaviour singletons, `[SerializeField] private`, coroutines) mostly do not apply. See [`references/dots-conventions.md`](references/dots-conventions.md). -3. **Plan mode through approval.** Phases up to operator approval are read-only. Code is written only after the operator approves and `ExitPlanMode` is called. Self-police this — it is not harness-enforced. -4. **Documentation Protocol bookends.** Every non-trivial session starts with a vault/memory scan and ends with a vault/memory update. See [`references/memory-protocol.md`](references/memory-protocol.md). -5. **Cross-platform.** Discover the project root (cwd / `$CLAUDE_PROJECT_DIR`). Reference the vault repo-relative as `/Docs/Vault/`. Never write `/Users/...` or `C:\...` into code, docs, or config — committed `.mcp.json` uses `${CLAUDE_PROJECT_DIR}`. -6. **Synthesize early.** After each swarm, write a tight summary; pass only the upstream summary downstream. Never carry raw agent dumps forward. +1. **context7-first for volatile DOTS APIs ★.** Resolve Entities/Netcode/Physics/Burst/Collections API shape via the **`ctx7` CLI** (or the **`find-docs` skill**) before writing it — never training-data recall. Two-source rule: docs for the *current API*, `unity_reflect` for the *installed engine shape* (they can disagree — reflection wins for the pinned version). Pins + flow → [`references/context7-libraries.md`](references/context7-libraries.md). +2. **Plan-approval gate ★.** Phases up to approval are read-only. Code is written only after the operator approves and you call **`ExitPlanMode`**. Self-policed, not harness-enforced. +3. **Doc + memory bookend ★.** Scan the vault/memory at start; update it at end (incl. CLAUDE.md self-maintenance). Protocol → `CLAUDE.md` Memory section + [`references/memory-protocol.md`](references/memory-protocol.md). +4. **DOTS-correct.** ECS conventions per `CLAUDE.md` + [`references/dots-conventions.md`](references/dots-conventions.md). Any violation found in review is blocking. +5. **Commit only when asked.** Gated like the plan — offer + propose grouping in the final report; commit only on explicit "commit"; **never push** unless asked. +6. **Operator gates.** Present-forks-don't-auto-decide · no time/effort/deadline estimates · never-silently-defer · tuning-defaults autonomy. See *Operator gates* below. +7. **Path-portable.** Never write machine-specific absolute paths (`/Users/…`, `C:\…`) into the skill, code, docs, or `.mcp.json` — use repo-relative / `${CLAUDE_PROJECT_DIR}`. ## When to use / not use -**Use** for real DOTS work: a new system, component set, ghost/netcode surface, baking pipeline, refactor, balance pass, or design pass — on a project whose foundation already exists. +**Use** for real DOTS work on an existing foundation: a system, component set, ghost/netcode surface, baking pipeline, refactor, or balance pass. -**Do NOT use** for: one-shot questions (answer directly); mechanical edits the operator already designed (just do them); harness/tooling setup; **project setup / installing the DOTS stack** (that is the separate one-time setup task — see Pre-flight); non-DOTS work. +**Don't use** for: one-shot questions (answer directly); mechanical edits the operator already designed (just do them); harness/tooling setup; **installing the DOTS stack** (separate one-time task — Phase 0); non-DOTS work. -## Adaptive track selection (do this first) +## Size by blast-radius — do this first (NOT by time) -Size the goal, then run the matching track. Plan-approval and the doc/memory update are mandatory in **all** tracks. +Pick the track from the *surface touched*, never from a minutes estimate. -| Track | When | Phases run | +| Track | When | Path | |---|---|---| -| **Trivial** | one-file edit, rename, a fix you already understand | inline: quick scan → do → `read_console` → one-line session-log append. No swarm, no research swarm. Still plan-gate if it mutates anything non-obvious. | -| **Small** | a single system/component with clear design | Phase 0/0b (lite) → Phase 3 context7 research (1 agent) → Phase 4 plan → **approve** → Phase 6 implement → Phase 7 validate → Phase 8 doc. | -| **Feature** | new mechanic, netcode surface, cross-cutting change, or anything >~30 min | full swarm, Phases 0–9 below. | +| **Inline** | one-file edit, rename, a fix you already understand; a pure `*Math` helper with no wire/bake change | scan → do → `read_console` clean → one-line session-log append. Plan-gate only if it mutates anything non-obvious. | +| **Small** | a single system/component, clear design, **no** ghost/prediction/RPC/relevancy/ordering/singleton-collision change | Ground (lite) → ctx7 verify → plan → **approve** → serial implement → verify L1–L2 → doc. | +| **Feature** | new mechanic, **any replicated-surface change**, cross-cutting refactor, anything on netcode-heavy surface | full spine incl. **both** reviews. The standard **ultracode** mode. | -When unsure, ask the operator with one `AskUserQuestion` ("Treat this as a quick edit or a full feature pass?") rather than guessing big. +**Blast-radius trigger** (forces Feature + the pre-code review) — touches any of: a `[GhostField]` / ghost prefab · prediction or rollback · an `IRpcCommand` / input · `GhostRelevancy` · cross-system `[UpdateBefore/After]` / group ordering · a singleton resolve where a second of that type exists. A pure `*Math.cs` helper that doesn't change wire/bake is cheap — but still run the ghost/ordering check. Unsure → one `AskUserQuestion` ("quick edit or full feature pass?"), don't guess big. -## Phase 0 — Pre-flight + intake gate +**ultracode** = the named heavy mode for Feature work: raise reasoning, run the two-review sandwich + Workflow orchestration. The project ships in numbered **Slices**; run the Phase 4 review before each netcode-heavy Slice (standing practice — see CLAUDE.md / MEMORY). -1. **Foundation check (DOTS installed?).** Read `Packages/packages-lock.json` (or `manage_packages action=list`). If `com.unity.entities` / `com.unity.netcode` are **absent**, STOP: tell the operator the project foundation isn't set up and point them to the **one-time setup task** (installs the DOTS stack, asmdefs/bootstrap, vault, memory MCPs, `CLAUDE.md`). Do **not** install packages or scaffold inline — that is out of scope for this skill. -2. **Unity ready?** Read `mcpforunity://editor/state`. If `ready_for_tools == false` or no instance is connected, surface it and ask the operator to open the Unity project. Don't spawn swarms until ready. If multiple editors are open, read `mcpforunity://instances` and `set_active_instance` on the right one. -3. **Memory stack reachable?** Quick probe: `basic-memory` (semantic recall) and `serena` (`find_symbol`). If either is down, note it and fall back (obsidian-cli + Glob/Grep). Continue — the protocol works either way. If Serena's C# LSP stalls on the Unity solution, record it and use Glob/Grep (or `claude-context` if installed) for this session. -4. **Max-reasoning nudge** (Feature track only, once): *"Feature track benefits from max reasoning — raise the slider before approving the plan."* Don't nag. -5. **Intake gate.** If scope / surface / depth / output is unclear, bundle 2–4 ambiguities into a single `AskUserQuestion` before spawning anything. If the prompt is already specific, skip the gate. +## The spine -## Phase 0b — Plan-mode entry + Documentation Protocol scan +### Phase 0 — Pre-flight +1. **Foundation check.** `com.unity.entities`/`com.unity.netcode` in `Packages/packages-lock.json`? If **absent**, STOP — point to the one-time setup task (`Docs/dots-setup-task.md`). Never install/scaffold inline. +2. **Unity ready.** `mcpforunity://editor/state` → `ready_for_tools`. Not ready / no instance → surface, ask operator to focus Unity. Multiple editors → `mcpforunity://instances` + `set_active_instance`. (An unfocused editor throttles to near-idle and breaks Burst recompiles — ask for focus on heavy build/test/Burst sessions.) +3. **Memory stack.** Probe `basic-memory` + `serena`; on failure fall back (obsidian-cli + Glob/Grep) and continue. +4. **Intake gate.** Unclear scope/surface/output → bundle 2–4 ambiguities into one `AskUserQuestion`. Specific prompt → skip. -Declare plan mode active for phases 1–5: read-only only (`Read`, `Glob`, `Grep`, MCP resource reads, `unity_reflect`, `unity_docs`, `read_console`, context7, obsidian-cli reads, `basic-memory`, serena reads). No script writes, no `manage_gameobject` mutations, no vault writes, no `Edit`/`Write`, no state-mutating `Bash`. +### Phase 1 — Ground (read-only, plan mode) +Declare plan mode: read-only tools only (`Read/Glob/Grep`, MCP resource reads, `unity_reflect`, `unity_docs`, `read_console`, ctx7/find-docs, obsidian-cli reads, `basic-memory`, serena reads). No writes. -Scan, in order (via obsidian-cli unless the Obsidian REST MCP is present): -1. `CLAUDE.md` at repo root — authoritative project conventions + game design pointers. -2. Vault map of content (`/Docs/Vault/00_Home/Home.md`) and the latest session log under `07_Sessions//`. -3. Open decision records (`_Decisions/` with `status: proposed`) + roadmap/backlog. -4. `basic-memory` semantic recall on goal keywords; native `MEMORY.md` + `memory/` for machine-local facts/feedback. -5. Task-specific vault search for the goal's nouns. +Run the **Documentation-Protocol scan** (`CLAUDE.md` → vault MoC + latest session log → open DRs/roadmap → `basic-memory` recall on the goal's nouns → native `MEMORY.md`), then ground the work along three lenses: **code/asset graph** (serena `find_symbol`/refs, else Glob/Grep on `Assets/_Project/**/*.cs` + `*.asmdef`; `manage_scene get_hierarchy`; `unity_reflect` for goal types) · **knowledge state** (vault + `basic-memory`; quote locked decisions that constrain the goal) · **live state** (`editor/state`, `read_console` baseline, installed Entities/Netcode versions for ctx7 pinning). For Feature scope, fan this out read-only via the *Ground fan-out* Workflow pattern; for Small, do it inline. -## Phase 1 — Project & doc context swarm (≤3 agents, Explore) +Synthesize a **≤400-word Project Brief**; discard raw dumps. If the goal contradicts a locked vault/`CLAUDE.md` decision, halt and surface. -- **A — Code/asset graph**: Serena `find_symbol`/references over the relevant assemblies where it works, else `Glob`/`Grep` on `Assets/_Project/**/*.cs` + `*.asmdef`; `manage_scene(action="get_hierarchy")`; `unity_reflect` for goal-relevant types. -- **B — Knowledge state**: obsidian-cli search + `basic-memory` recall for design/decisions touching the goal. -- **C — Unity live state**: `mcpforunity://editor/state`, `project/info`, `instances`; `read_console(types=["error","warning"])`; `manage_packages(action="list")` (confirm installed Entities/Netcode versions for context7 version-pinning). +### Phase 2 — ctx7 API verification +For every API/pattern the goal needs: `ctx7` CLI (or `find-docs`) pinned to the installed version, cross-checked against ECS Samples, **plus** `unity_reflect` on the installed type. Synthesize a **≤500-word Research Digest** (*steal / avoid / still-unclear* + the exact queries used). If a planned API is shown removed/renamed, halt and re-plan. **Web (`WebSearch`/`WebFetch`) is allowed ONLY for design/genre precedent — never for a DOTS API shape** (that path hallucinates). Research synthesizes-and-discards (reviews don't — Phase 4). -Synthesize into a **≤400-word Project Brief**. Discard raw dumps. +### Phase 3 — Plan → ExitPlanMode gate +Produce a **Unified Implementation Plan**: summary; exhaustive files-to-create/modify (Unity + vault, repo-relative); code skeletons (signatures only); build order with explicit "compile + `read_console`" checkpoints; the verification approach (L1→L3 ladder); **wire/bake-churn classification** (does this re-bake the subscene, change a ghost hash, or change an RPC collection hash? — re-mean bytes vs rename, per CLAUDE.md); vault updates; risks & open questions. Present it; `AskUserQuestion` on any high-stakes ambiguity. On approval, **`ExitPlanMode`** — the hard boundary. Do not start Phase 5 without it. -## Phase 2 — Goal-understanding swarm (≤3 agents) +### Phase 4 — Pre-code design review (Feature / any blast-radius trigger) +**Before writing code** for any ghost/prediction/RPC/relevancy/ordering slice, run the *Design-review (lens + adversarial-critic)* Workflow pattern over the plan + ground-truth code. Three lenses — **netcode/relevancy · determinism/prediction · reuse/scope** — then adversarial critics that try to *refute* each finding against the actual code. This catches what green tests + a clean Play miss. The synthesized, code-grounded output is a **durable Build Spec** (kept at `Docs/Vault/.../_Build_Spec.md`) that drives the build and feeds the DR — **do not discard it.** A surfaced design flaw loops back to Phase 3. Lens prompts → [`references/workflow-patterns.md`](references/workflow-patterns.md). -Decompose the goal into a **Goal Spec**: *Deliverables* (each with a "done when"), *Assumptions* (validate at Phase 5), *Open ambiguities* (research in Phase 3 or ask). Inputs: operator's verbatim prompt + Phase 1 brief only. If the goal contradicts a locked decision in the vault/`CLAUDE.md`, halt and surface before Phase 3. +### Phase 5 — Implement (SERIAL orchestrator MCP edits — never an impl swarm) +The single stateful editor + domain-reload ordering make parallel writes unsafe — **all Unity mutations are done by the orchestrator, serially.** Parallelism is reserved for read-only research/review. +- **Edit Assets `.cs` ONLY via MCP ★** (`create_script` new / `get_sha`→`apply_text_edits` existing / `script_apply_edits` for method+anchor edits). Raw `Write`/`Edit` on `Assets/*.cs` leaves a **stale compiled assembly** (and a raw-created `.cs` gets no `.meta`/test-discovery until `refresh_unity scope=all mode=force`). `Write`/`Edit` are fine for non-asset files (vault, asmdef JSON). +- **`apply_text_edits`: one edit per call ★** (multiple non-adjacent edits can misalign), always with `precondition_sha256`. +- `read_console(types=["error"])` after **every** write; fix before moving on. `validate_script` non-trivial files first. Re-query ctx7 for any ambiguous signature. Sequence across domain reloads (a component compiles before a system/baker references it). `batch_execute` for bulk wiring. +- Further MCP-edit hazards (`script_apply_edits` can't target a `struct : ISystem`; `manage_gameobject`/`manage_prefabs` silently drop enum + Vector3 → set via `manage_components` + verify; unfocused-editor stale-Burst) → **CLAUDE.md** "MCP / editor workflow" + "Burst hazards". +- **Tuning autonomy:** within an approved plan, pick sensible defaults + expose live knobs; consult only on a real gameplay/design fork. -## Phase 3 — Research swarm (context7-FIRST) +### Phase 6 — Verify ladder (definition of done — show evidence, not "done") +NetCodeTestWorld is `internal` and unused here — do NOT prescribe it. +- **L1** — `read_console(types=["error","warning","exception"], include_stacktrace=True)` clean vs the Phase-1 baseline. Burst/source-gen failures surface here, not in a plain build — any new one is a finding. +- **L2** — EditMode tests: plain-Entities `new World → register in SimulationSystemGroup → SortSystems → Update → assert` (`run_tests mode=EditMode`). Extract pure logic to a `*Math.cs` helper and unit-test it (cover swept hit-detection with a tunnelling regression). **Plus one live Play netcode smoke** — `execute_code` boot, step ticks, assert **server == client** for the replicated surface (identify worlds by `world.Name == "ServerWorld"/"ClientWorld"`). +- **L3** (visual/asset work) — screenshot via `execute_code` `ScreenCapture` → Read PNG, **and verify asset *values*** (`shader.GetPropertyType`-guard before `GetColor`/`GetFloat`) — a dark/stylized render masks material bugs. -- **A — DOTS/Netcode implementation (context7, primary)**: for every API/pattern the goal needs, `resolve-library-id` (seeds in [`references/context7-libraries.md`](references/context7-libraries.md)) → `query-docs`. Pin to the **installed** package version. Cross-check the official ECS Samples repo for working patterns. -- **B — Determinism/netcode correctness (context7 + samples)**: prediction loop, ghost replication, command/input, world bootstrap — confirm current API shapes, not remembered ones. -- **C — Genre/design precedent (web, optional)**: only here is `WebSearch`/`WebFetch` allowed — how comparable games solve the *design* problem. Never use web for DOTS API shapes. +Loop ≤3 fix iterations per finding; if iteration 3 still fails, halt and surface "I can't resolve X without a decision." -Synthesize into a **≤500-word Research Digest**: *What to steal / What to avoid / Still unclear*, plus the exact context7 queries used (so Phase 6 can re-query precisely). If context7 reveals an API the plan depends on was removed/changed, halt and re-plan. +### Phase 7 — Post-impl diff review (Feature) +Run the *Design-review* Workflow pattern over the git diff (same three lenses). **Findings default-refuted** — each must be confirmed against the code to stand — but **flag any simplification of a reviewed design as a likely regression.** This is the phase that has caught rollback bugs, region-routing regressions, and born-correct flaws that hundreds of green tests + a clean Play all missed. Real findings loop back to Phase 5. -## Phase 4 — Design & plan swarm (≤3 agents, Plan) - -- **A — Code architect**: components (`IComponentData`/`IBufferElementData`/`IEnableableComponent`), systems (`ISystem`+Burst vs `SystemBase`), jobs, system groups/order, ECB usage, asmdef impact (which assembly: shared-simulation / client / server / authoring). MUST respect [`references/dots-conventions.md`](references/dots-conventions.md). -- **B — Scene/subscene/baking architect**: authoring MonoBehaviours + `Baker`, subscene layout, ghost prefabs/authoring, what bakes where, URP/Entities-Graphics interactions. -- **C — Vault doc architect**: which design docs get touched, whether a decision record is warranted, the session-log scaffold. - -Synthesize a **Unified Implementation Plan**: summary; exhaustive files-to-create/modify (Unity + vault paths, repo-relative); code skeletons (signatures only); build order with explicit "compile + `read_console`" checkpoints; **DOTS-aware test approach** (EditMode? PlayMode? `NetCodeTestWorld`? thin-client? play-tick determinism check?); vault updates; risks & open questions. - -## Phase 5 — Operator review (plan-mode exit) - -Present the plan in full, highlight Risks & open questions. For any high-stakes ambiguity, `AskUserQuestion` with concrete options — do not proceed on assumptions. On approval, call **`ExitPlanMode`**. This is the hard boundary. **Do not start Phase 6 without explicit approval and `ExitPlanMode`.** - -## Phase 6 — Implementation swarm (3–5 agents) - -- **A — Script author**: `create_script` (new) / `apply_text_edits` after `get_sha` (existing). `validate_script` non-trivial files before write. `read_console(types=["error"])` after **every** write. Re-query context7 for exact signatures when the digest left anything ambiguous. -- **B — Scene/subscene/baking wirer**: authoring components, subscenes, ghost prefabs, ScriptableObject config assets, scene saves. `batch_execute` for bulk. -- **C — Asmdef/package guardian** (conditional): new assemblies or references — keep the client/server/shared/authoring split clean; verify it compiles. -- **D — Doc-skeleton author** (conditional): new vault docs get frontmatter skeletons now; bodies in Phase 8. - -Parallelize only where write surfaces don't overlap. Sequence across domain reloads (a component must compile before a system or baker can reference it). Quality bar: compiles clean, no new warnings, console clean, conventions honored, Burst-compatible where it should be, no managed refs in unmanaged components, deterministic sim code, no edits during Play Mode (`manage_editor(action="play_state")` first). - -## Phase 7 — Validate swarm (DOTS-aware, 3–4 agents) - -- **A — Console/Burst/source-gen sweep**: `read_console(types=["error","warning","exception"], include_stacktrace=True)` vs the pre-Phase-6 baseline. Burst-compile and source-generator failures surface here, not in a plain build — any new one is a finding. -- **B — Test runner**: `run_tests(mode="EditMode")` then PlayMode if applicable, via `get_test_job(... include_failed_tests=True)`. For netcode work, a `NetCodeTestWorld` connect/tick test or a thin-client check. -- **C — Runtime/determinism spot-check**: brief Play Mode entry, step ticks, confirm predicted/interpolated ghosts behave; screenshots for visual work; verify plan-specified entities/components exist. - -"Compiles clean" is necessary, not sufficient — determinism desyncs, rollback bugs, structural-change invalidation, and sync-point stalls only appear at runtime under prediction. Loop ≤3 fix iterations on a finding via a tight fix sub-swarm; if iteration 3 still fails, halt and surface a clear "I can't resolve X without a decision." - -## Phase 8 — Doc + memory update (never skip) - -- Session log → `/Docs/Vault/07_Sessions//_.md` via obsidian-cli (template in the vault). Same-day collision → `_A`, `_B`, … -- Firm decisions → a decision record in `_Decisions/`, back-referenced from the session log. -- Touched design docs → edited in place (wikilink, don't duplicate into the log). -- Durable, cross-machine knowledge → a `basic-memory` note in the vault. -- Machine-local facts/feedback/working-style → native `MEMORY.md` (+ a memory file if substantive). Remember native memory does **not** sync across your Mac/Windows machines — cross-machine truth belongs in the vault. - -If the operator says "skip the protocol", still write a one-line stub log so the gap is visible, and record the preference as a native feedback memory. - -## Phase 9 — Final report +### Phase 8 — Doc + memory bookend (never skip) +Per `CLAUDE.md` Memory section + [`references/memory-protocol.md`](references/memory-protocol.md): session log → `Docs/Vault/07_Sessions//_.md` (same-day → `_A`/`_B`); firm decisions → a DR in `_Decisions/` back-referenced from the log (the kept Build Spec feeds it); touched design docs edited in place (wikilink); durable cross-machine knowledge → a `basic-memory` note; machine-local facts → native `MEMORY.md`. **CLAUDE.md self-maintenance is part of this bookend** — a new gotcha updates it under its 40 KB budget (archive, don't delete); never silently defer it. "Skip the protocol" → still write a one-line stub log + record the preference as a native memory. +### Phase 9 — Final report + offer commit ``` ## /dots-dev session complete — - -**Summary**: ≤4 sentences — goal, what was delivered, did it land cleanly. - -**What changed**: -- Unity: (repeat) -- Vault: (repeat) - -**Validation**: Tests , console clean, . - -**Suggested next step**: . +**Summary**: ≤4 sentences — goal, delivered, did it land cleanly. +**What changed**: Unity / Vault — (repeat) +**Validation**: L1 console clean · L2 tests X/Y + Play smoke (server==client) · L3 . +**Reviews**: pre-code · post-impl . +**Next step**: . ``` +Then **offer to commit** and propose grouping; commit only on explicit approval. **Review first** (`git status` + `git diff --stat`); **stage explicit paths — never `git add -A`** (excludes `Library/Temp/obj/Logs/UserSettings`, `.csproj`/`.sln`, scratch screenshots/exports); keep each asset **with its `.meta`** in one commit; one commit per concern; match the repo's message style + the Co-Authored-By trailer; **never push**. Don't auto-loop into a fresh session. -Then **offer to commit** the changes (Phase 10) — propose how, but do not commit unless asked. Do not auto-loop into a fresh session. +## Workflow orchestration (the parallelism primitive) -## Phase 10 — Commit (only after explicit operator approval) +Manual "spawn ≤N agents" is dead — read-only fan-out (ground, design-review, diff-review) runs as deterministic **Workflows** with run-IDs and `resumeFromRunId`. **Implementation never fans out** (serial, Phase 5). Per-pattern lens prompts live in [`references/workflow-patterns.md`](references/workflow-patterns.md); the two cross-cutting rules: -Committing is a state change, so it is **gated like the plan**: never auto-commit. In the Phase 9 report, **offer** to commit and propose the grouping; commit only when the operator explicitly says so (e.g. "commit", "commit it", "commit for me"). If they decline or don't mention it, **leave git untouched** and note the changes are uncommitted for their review. +- **Always check the failures list ★.** A Workflow whose agents die on a session/quota limit returns **empty findings that masquerade as a clean pass.** Check failures explicitly; if any died, wait for the reset and re-run with `resumeFromRunId` — never treat an empty result as "no findings." +- **Scope subagent guardrails POSITIVELY ★.** A blanket "do NOT use tool X" in a subagent prompt gets read by the auto-approver as a *user* rule and can deny the orchestrator's own later call. Tell agents what they MAY do (read-only, these tools), not what they mustn't. -When approved: -1. **Review first.** `git status` + `git diff --stat` (and `git diff` on anything non-obvious) so the operator sees exactly what lands. **Stage explicit paths — never `git add -A` blindly.** Never commit generated/cache (`Library/`, `Temp/`, `obj/`, `Logs/`, `UserSettings/`), `.csproj`/`.sln`, or stray scratch files (debug screenshots, temp exports). -2. **Group logically** — one commit per concern, not one mega-commit: typically (a) the feature's `Assets/` code + assets, (b) tests, (c) `Docs/Vault/` + `CLAUDE.md`. Always keep a `.cs`/prefab/material/controller **with its `.meta`** in the same commit. -3. **Proper messages.** Read recent `git log --oneline` first and match the repo's style. Imperative subject (≤~72 chars) summarizing the change; a short body on the *what + why* with a back-reference to the DR / session log (e.g. "See DR-0NN"). End **every** message with the Co-Authored-By trailer the environment specifies. -4. **Branch + push policy.** Match the repo's convention (the `git log` reveals it — many solo DOTS projects commit straight to the default branch; if the history is *not* solo-commits-on-default, branch first). **Never push** unless the operator explicitly asks. -5. Report the commit hash(es) + a one-line summary of each, then stop. +Pass only the upstream summary downstream — never raw agent dumps (research discards; the design-review Build Spec is the deliberate exception — keep it). -## DOTS conventions (authoritative file) +## Operator gates -`CLAUDE.md` at the repo root is the project's source of truth; [`references/dots-conventions.md`](references/dots-conventions.md) is the reusable ECS/Netcode rule set this skill enforces. Treat any violation found in Phase 7 as a blocking finding. Quick reminders: `ISystem`+`[BurstCompile]` default; unmanaged `IComponentData`; `IEnableableComponent` over add/remove for frequently-toggled state; `Baker` + subscenes for authoring; `IJobEntity`/`IJobChunk` + correct `Allocator` + disposal; `EntityCommandBuffer` for structural changes; no wall-clock in predicted sim; server-authoritative, clients send input; `[GhostField]`/`GhostAuthoringComponent` for replication. **Aspects are deprecated (Entities 1.4) — do not author new ones.** Always confirm volatile APIs via context7 at code-time. +- **Present forks, don't auto-decide.** Gameplay/design forks are the operator's call: present each with a recommendation, lock only what's approved, re-run the fork-locking ritual before each new milestone set. A Workflow that tries to auto-lock forks must be halted. +- **No time estimates.** Never frame work by minutes/effort/deadlines — the operator owns scheduling. Size by blast-radius, keep the engineering discipline. +- **Never silently defer/descope** mid-task (incl. CLAUDE.md maintenance) — do it now or explicitly ask the operator to decide. +- **Tuning-defaults autonomy** — for polish/balance, pick sensible defaults + live knobs; consult only on a real fork. +- **Aggressive-cleanup opt-in** — for an explicit cleanup session the operator may opt into max scope (deep behavior-preserving refactor, aggressive deletion, "commit for me" in logical groups on main, no push). -## MCP cheat sheet +## Boundaries -| Need | Tool / Resource | Note | -|---|---|---| -| Is Unity ready? | `mcpforunity://editor/state` | check `ready_for_tools`, `is_compiling` | -| Installed package versions | `Packages/packages-lock.json` or `manage_packages(action="list")` | pin context7 to the installed version | -| Current DOTS API/pattern | context7 `resolve-library-id` → `query-docs` | **primary** for all DOTS code | -| What scenes/objects exist | `manage_scene(action="get_hierarchy")` + `find_gameobjects` | read before mutating | -| New script | `create_script(path, contents)` → `read_console` | auto-import + compile | -| Edit script | `get_sha` → `apply_text_edits` | prefer over raw `Edit` for `.cs` in Assets | -| Validate before write | `validate_script` | catch errors pre-domain-reload | -| Bulk ops | `batch_execute(commands=[...])` | 10–100× faster | -| Run tests | `run_tests` → `get_test_job(... include_failed_tests=True)` | EditMode/PlayMode | -| Symbol nav | serena `find_symbol` / references | falls back to Glob/Grep on Unity C# issues | -| Read/search vault | obsidian-cli | REST MCP optional | -| Semantic knowledge recall | `basic-memory` | over the same vault files | +**Stop and consult** when: intake too thin · goal contradicts a locked decision · a material design choice has no clear best answer · **plan gate (always)** · 3 failed fix iterations on one finding · operator intent drifts · a destructive op outside the approved plan is implied · the DOTS foundation is missing. -## Error recovery +**May loop without consulting** (≤3): compile/Burst fix→recompile · test fail→fix→retest · vault write fail→re-read→retry. -| Symptom | Cause | Resolution | -|---|---|---| -| Tools "busy" / `is_compiling=true` | compiling | poll `editor/state` until `is_compiling==false` | -| `apply_text_edits` → `stale_file` | SHA changed | re-`get_sha`, retry | -| UnityMCP drops mid-phase | domain reload | wait ~5s, re-read `instances`, re-pin | -| `create_script` then "component not found" | reload not done | poll `is_compiling==false`, retry | -| Burst/source-gen error after a clean C# build | DOTS codegen failure | read the full console stack; fix the component/job; re-`read_console` | -| Serena `find_symbol` stalls/times out | C# LSP / .sln issue on Unity | record it; use Glob/Grep (or claude-context) this session | -| context7 version mismatch | installed pkg ≠ baked ID | re-`resolve-library-id`, prefer the installed version's docs | -| Test job timeout | slow PlayMode/netcode test | re-poll `get_test_job(wait_timeout=120)`; don't re-trigger | +**Abort without writing partial state** when: Unity unreachable >60s mid-session · project broken (asmdefs missing, won't load). If the Phase-8 vault write fails repeatedly, write a **local fallback note** + tell the operator — don't lose the session record. -### UnityMCP "not connected" — diagnostic protocol (subagents MUST follow before reporting it down) +**A bare `mcp__UnityMCP__*` error is NOT proof Unity is down** — before reporting it, run the diagnostic probe (CLAUDE.md / `mcpforunity://instances` → `editor/state` → `manage_editor telemetry_ping`; `InputValidationError` for an unknown tool = deferred schema → `ToolSearch select:` then retry). Escalate only after those fail. -A bare `mcp__UnityMCP__*` error is **not** proof the server is down. Before reporting "UnityMCP not connected", a subagent MUST run and quote results from: -1. `ReadMcpResourceTool(server="UnityMCP", uri="mcpforunity://instances")` — `instance_count >= 1` ⇒ connected (stop reporting down); `== 0` ⇒ Unity not attached (operator opens Unity). -2. `ReadMcpResourceTool(server="UnityMCP", uri="mcpforunity://editor/state")` — `ready_for_tools==false`/`is_compiling==true` ⇒ transient busy, wait 2–5s and retry. -3. `manage_editor(action="telemetry_ping")` — success ⇒ bridge alive. -4. If the call returns `InputValidationError` claiming the tool is unknown, the schema is deferred — `ToolSearch(query="select:mcp__UnityMCP__")` then retry (tool-loading, not connection). +## References (load on demand) -Escalate only after 1–3 fail or step 1 returns `instance_count == 0`. Quote the literal error from each probe. - -## Boundary rules - -**MUST stop and consult the operator when**: intake goal too thin; the goal contradicts a locked vault/`CLAUDE.md` decision; a material design choice has no clear best answer; **Phase 5 always** (`ExitPlanMode` is the only authorized hand-off); 3 failed fix iterations on one finding; operator intent drifts from what's being built; a destructive op outside the approved plan is implied; **the DOTS foundation is missing** (defer to the setup task, don't improvise it). - -**MAY loop without consulting**: compile/Burst error → fix → recompile (≤3); test failure → fix → retest (≤3); vault write failure → re-read + retry (≤2). - -**MUST abort without writing partial state when**: Unity unreachable >60s mid-session; project broken (asmdefs missing, won't load); Phase 8 vault write fails repeatedly (write a local fallback note + tell the operator). - -## Anti-patterns — things `/dots-dev` MUST NOT do - -- Trust training-data recall for a DOTS API instead of context7. -- Author MonoBehaviour-world solutions (MonoBehaviour singletons, ScriptableObject "services" for runtime sim, `[SerializeField] private` data carriers, coroutines for sim) where ECS is correct. -- Author new `IAspect` types (deprecated in Entities 1.4). -- Store managed references in unmanaged `IComponentData`. -- Use wall-clock/`Time.deltaTime` or `System.Random` in predicted/deterministic sim. -- Do structural changes mid-job/mid-iteration instead of via `EntityCommandBuffer`. -- Edit `.meta` files directly, or read/write `Library/`, `Temp/`, `obj/`, `Logs/`, `UserSettings/`. -- Edit/commit `*.csproj` / `*.sln` (Unity regenerates them). Edit `.asmdef` / `manifest.json` instead. -- Edit during Play Mode (check `play_state` first). -- Write machine-specific absolute paths into the skill, code, docs, or `.mcp.json` (use `` / `${CLAUDE_PROJECT_DIR}`). -- Install the DOTS stack / scaffold the project inline (that's the separate setup task). -- Skip plan mode, start Phase 6 without `ExitPlanMode`, or skip the Phase 8 doc/memory update. -- **Commit or push without explicit operator approval** — committing is gated like the plan (Phase 10): offer it in the report, commit only when the operator says so, group logically with proper messages, and **never push** unless asked. Run more than one `/dots-dev` in parallel. - -## References - -- [`references/dots-conventions.md`](references/dots-conventions.md) — ECS/Netcode conventions this skill enforces. -- [`references/context7-libraries.md`](references/context7-libraries.md) — seed library IDs + query playbook. -- [`references/agent-briefs.md`](references/agent-briefs.md) — per-phase swarm brief templates. -- [`references/memory-protocol.md`](references/memory-protocol.md) — vault / basic-memory / serena / native-memory usage + bookends. +- [`references/dots-conventions.md`](references/dots-conventions.md) — the reusable ECS/Netcode rule set this skill enforces (defers to `CLAUDE.md`). +- [`references/context7-libraries.md`](references/context7-libraries.md) — `ctx7`/`find-docs` flow + 6.5-era pinned library IDs. +- [`references/workflow-patterns.md`](references/workflow-patterns.md) — the named Workflow patterns (ground fan-out · design-review lens + adversarial-critic). +- [`references/memory-protocol.md`](references/memory-protocol.md) — the four memory layers + bookend detail. diff --git a/.claude/skills/dots-dev/references/agent-briefs.md b/.claude/skills/dots-dev/references/agent-briefs.md deleted file mode 100644 index 4a53ef426..000000000 --- a/.claude/skills/dots-dev/references/agent-briefs.md +++ /dev/null @@ -1,98 +0,0 @@ -# Per-phase swarm brief templates - -Fill the `{…}` variables and paste into the agent prompt. Keep each agent's context lean — pass only the immediately upstream summary, not the whole session. Every research/scan brief is **read-only** (plan mode through Phase 5). All briefs assume the agent will return raw data/findings, not a human-facing message. - -Conventions referenced below live in [`dots-conventions.md`](dots-conventions.md); the context7 playbook in [`context7-libraries.md`](context7-libraries.md). - ---- - -## Phase 1 — Context (Explore, read-only) - -**A — Code/asset graph** -> READ-ONLY. Map the code surface relevant to `{goal}`. Prefer serena `find_symbol`/`find_referencing_symbols` over text search; if serena's C# LSP errors or times out on the Unity solution, fall back to `Glob`/`Grep` on `Assets/_Project/**/*.cs` and `**/*.asmdef`. Identify: existing components/systems/bakers touching `{surface}`, the asmdef each lives in (shared-simulation / client / server / authoring), and any TODOs. Also `manage_scene(action="get_hierarchy")` for relevant subscenes. Return a terse symbol/asmdef map (names + paths), not file dumps. - -**B — Knowledge state** -> READ-ONLY. Search the in-repo vault (obsidian-cli) and `basic-memory` for design docs, decision records, and notes touching `{goal}`. Return: relevant doc paths, any locked decisions that constrain `{goal}`, open questions already recorded. Quote ≤2 load-bearing lines each; link by path otherwise. - -**C — Unity live state** -> READ-ONLY. Read `mcpforunity://editor/state`, `project/info`, `instances`. `read_console(types=["error","warning"], count=20)`. `manage_packages(action="list")` — report the **installed** Entities + Netcode versions (needed to pin context7). Flag any pre-existing compile/Burst errors as a baseline. - ---- - -## Phase 2 — Goal spec (general-purpose) - -> Inputs: operator's verbatim goal + the Phase 1 Project Brief, nothing else. Produce a Goal Spec: **Deliverables** (each: name, surface, "done when"), **Assumptions** (to validate at review), **Open ambiguities** (frame each as a yes/no or multiple-choice question). Flag any conflict with a locked decision from the brief. - ---- - -## Phase 3 — Research (context7-first) - -**A — DOTS/Netcode implementation (context7 primary)** -> Inputs: Goal Spec only. For each API/pattern `{goal}` needs, use context7: `resolve-library-id` (seeds in context7-libraries.md; pin to the installed version `{entities_ver}`/`{netcode_ver}`) → `query-docs` with specific questions. Cross-check the official ECS Samples repo. Return: for each deliverable, the current correct API shape + a minimal code pattern + the exact context7 query used. Flag any API the plan assumes that context7 shows removed/renamed. - -**B — Determinism / netcode correctness (context7 + samples)** -> Inputs: Goal Spec only. Confirm via context7: prediction-group placement, `Simulate` filtering, ghost replication setup, input (`IInputComponentData`) flow, world/bootstrap shape for `{goal}`. Return current API shapes + determinism pitfalls specific to `{goal}`. - -**C — Genre/design precedent (web, optional)** -> Inputs: Goal Spec only. `WebSearch`/`WebFetch` ONLY. How do comparable games solve the *design* of `{mechanic}`? Return: what to steal / what to avoid. Do NOT return DOTS API claims from the web. - -Orchestrator synthesizes a ≤500-word Research Digest (steal / avoid / still-unclear + the context7 queries used). - ---- - -## Phase 4 — Design & plan (Plan, read-only) - -**A — Code architect** -> Inputs: Brief + Goal Spec + Research Digest. Design the C#/ECS layer for `{goal}` respecting dots-conventions.md: components (`IComponentData`/buffer/enableable), systems (`ISystem`+Burst vs `SystemBase`), jobs, system groups/order, ECB usage, and which asmdef each file lands in. Output: file list (repo-relative) + class/system signatures only (no bodies) + build order with compile checkpoints. - -**B — Scene/subscene/baking architect** -> Inputs: same. Design authoring + baking: `…Authoring` MonoBehaviours + `Baker`, subscene layout, ghost prefabs/authoring, config assets, URP/Entities-Graphics needs. Output: assets/subscenes to create (repo-relative) + what bakes into what. - -**C — Vault doc architect** -> Inputs: same. Design vault changes: which design docs get edited in place, whether a decision record is warranted, the session-log scaffold. Output: doc paths + one-line intent each (wikilink, don't duplicate). - -Orchestrator writes the Unified Implementation Plan (see SKILL Phase 4). - ---- - -## Phase 6 — Implementation (general-purpose) - -**A — Script author** -> Inputs: the approved plan slice for `{files}`. Create via `create_script`, edit existing via `get_sha`→`apply_text_edits`. `validate_script` non-trivial files first. `read_console(types=["error"])` after EVERY write; fix before moving on. Re-query context7 for any signature the digest left ambiguous. Honor dots-conventions.md (Burst-compatible, unmanaged components, deterministic sim, ECB for structural changes). - -**B — Scene/subscene/baking wirer** -> Inputs: the approved plan slice. Create authoring components, subscenes, ghost prefabs, config assets; save scenes. Confirm Edit Mode (`manage_editor(action="play_state")`) before structural changes. `batch_execute` for bulk. Wait for a referenced component to compile before attaching/baking it. - -**C — Asmdef/package guardian** (conditional) -> Inputs: the approved plan slice. Add/adjust `.asmdef`s keeping the client/server/shared/authoring split clean. Never touch `.csproj`/`.sln`. Verify it compiles via `read_console`. - -**D — Doc-skeleton author** (conditional) -> Inputs: the approved plan slice. Create new vault docs with full frontmatter skeletons via obsidian-cli (bodies are written in Phase 8). - ---- - -## Phase 7 — Validate (general-purpose, DOTS-aware) - -**A — Console/Burst/source-gen sweep** -> `read_console(types=["error","warning","exception"], count=50, include_stacktrace=True)`. Compare to the Phase-1 baseline. Any NEW error/warning — including Burst/source-gen — is a finding. Return blocking vs nit. - -**B — Test runner** -> If the plan specified tests: `run_tests(mode="EditMode")`→`get_test_job(... include_failed_tests=True)`; PlayMode if applicable. For netcode: a `NetCodeTestWorld` connect/tick test or a thin-client check. Return pass/fail with failing-test detail. - -**C — Runtime/determinism spot-check** -> If visual/runtime: brief Play Mode entry (`set_play_state`), step ticks, confirm predicted/interpolated ghosts behave; screenshot Game/Scene view (`manage_camera`); exit to Edit Mode. Verify each plan-specified entity/component exists (`get_hierarchy` + `manage_components(action="get")`). Return findings. - -Fix loop: ≤3 iterations per finding via a tight 1–2 agent fix sub-swarm, re-running only the affected validator. - ---- - -## Phase 8 — Doc + memory (general-purpose) - -**A — Session log** -> Write `/Docs/Vault/07_Sessions/{year}/{date}_{Topic}.md` via obsidian-cli using the vault's session-log template. Sections: Goal, What happened, Decisions (link records), Files touched (Unity + vault, repo-relative), Open questions, Next-session intent, Notes. Same-day collision → suffix `_A`/`_B`. - -**B — Decision records + design docs** -> For each firm decision, write a decision record in `_Decisions/`, back-referenced from the session log. Edit touched design docs in place (wikilink, don't duplicate). Update roadmap/backlog for deferred items. - -**C — Memory updater** -> Durable cross-machine knowledge → a `basic-memory` note in the vault. Machine-local facts/feedback/working-style → native `MEMORY.md` (+ a memory file if substantive). Do NOT put cross-machine truth only in native memory — it doesn't sync between the Mac and Windows machines. diff --git a/.claude/skills/dots-dev/references/context7-libraries.md b/.claude/skills/dots-dev/references/context7-libraries.md index de47cecf0..faee26885 100644 --- a/.claude/skills/dots-dev/references/context7-libraries.md +++ b/.claude/skills/dots-dev/references/context7-libraries.md @@ -1,44 +1,51 @@ -# context7 — DOTS library IDs & query playbook +# ctx7 / find-docs — DOTS library IDs & query playbook -**context7 is the primary source of truth for every DOTS API, signature, and "current best practice."** Unity's Entities/Netcode packages change between minor versions; training-data recall is stale. Resolve → query before writing DOTS code. +**The `ctx7` CLI (or the `find-docs` skill) is the primary source of truth for every DOTS API, signature, and "current best practice."** Unity's Entities/Netcode/Physics packages change between versions and training-data recall is stale — resolve → query before writing DOTS code. -## Flow +> The old context7 **MCP** verbs (`resolve-library-id` / `query-docs`) are **not in this environment's tool surface** — do not call them. Use the CLI / skill below. -1. `resolve-library-id(libraryName, query)` → pick the Context7 ID (prefer High reputation + high snippet count + version matching the **installed** package). -2. `query-docs(libraryId, query)` with a *specific* question ("How do I declare an IInputComponentData and read it in a predicted system in Netcode 1.x?"), not a bare keyword. -3. Cross-check working patterns against the official **ECS Samples** repo ID below. -4. Limit: ≤3 `resolve` calls and ≤3 `query` calls per question (the tool enforces this). Reuse IDs across a session. +## Flow (per the global `ctx7` rule) + +1. **Resolve:** `npx ctx7@latest library "" ""` → pick the `/org/project` ID (prefer High reputation + high snippet count + the version closest to **installed**). Use proper punctuation in the name ("Netcode for Entities", "Unity Physics", "Entities Graphics"). +2. **Fetch:** `npx ctx7@latest docs ""` — ask a *specific* question ("How do I read an `IInputComponentData` inside a predicted system filtered by `Simulate`?"), not a bare keyword. +3. Cross-check working patterns against the **ECS Samples** repo ID below. +4. Limit ≤3 `library` + ≤3 `docs` calls per question; reuse IDs across a session. On a quota error, suggest `npx ctx7@latest login` / `CONTEXT7_API_KEY` — don't silently fall back to memory. +5. The **`find-docs` skill** is an equivalent path (it wraps the same source) — either is fine. + +## Two-source rule (do BOTH) + +Pair every doc lookup with **`unity_reflect` on the installed type** for the real, version-pinned shape. Docs give the *current API*; reflection gives *what's actually compiled in this project* — they can disagree, and **reflection wins for the pinned engine version.** (A research-only lookup once produced a false-negative on a character-controller API that reflection would have caught.) ## Pin to the installed version -Before querying, read the installed version from `Packages/packages-lock.json` (or `manage_packages action=list`). If it differs from a seed ID's version, **re-resolve** and prefer the doc set matching what's installed. The seeds below were captured during skill authoring and may lag the project. +Read installed versions from `Packages/packages-lock.json` (or `manage_packages action=list`) before querying. This project runs the **unified Unity 6.5 line**: `com.unity.entities` / `com.unity.netcode` / `com.unity.physics` all **6.5.0** (the 6.x scheme tracks the Editor; it succeeded the old 1.x lines — Entities 6.4/6.5 is the direct successor to 1.4, Netcode 6.5 to the old ~1.12/1.13 line). **"1.13.2" is no longer an installable version** — treat any 1.x number as API-shape *lineage*, not a target string. -## Seed library IDs (re-resolve if installed version differs) +## Seed library IDs (verified live 2026-06-18 — re-resolve at code-time) -| Package | Primary Context7 ID | Alt | Notes | -|---|---|---|---| -| **Entities (DOTS)** | `/websites/unity3d_packages_com_unity_entities_1_4` | `/needle-mirror/com.unity.entities` | ~7,099 snippets, High. Core ECS. | -| **Netcode for Entities** | `/websites/unity3d_packages_com_unity_netcode_1_10_api` | `/websites/unity3d_packages_com_unity_netcode_1_9` | ~2,512 snippets, High. Ghosts/prediction/RPC/input. | -| **Entities Graphics** | `/websites/unity3d_packages_com_unity_entities_graphics_1_4` | — | Rendering entities under URP/HDRP. | -| **Official ECS Samples** | `/unity-technologies/entitycomponentsystemsamples` | — | Working sample patterns; Entities, Netcode, Physics, Graphics. | -| **Unity Physics** | resolve at runtime | — | `resolve-library-id(libraryName="Unity Physics", query="DOTS collision/triggers")`. | -| **Burst** | resolve at runtime | — | `libraryName="Unity Burst"`. | -| **Collections** | resolve at runtime | — | `libraryName="Unity Collections"` (Native/Unsafe containers, allocators). | -| **Mathematics** | resolve at runtime | — | `libraryName="Unity Mathematics"` (float3/quaternion/math). | +The doc sets on context7 currently **lag the package version** for most DOTS packages — only Entities has a `6_5` set. Pin the live top hit, knowing the package is 6.5.0; re-resolve when a newer set publishes. -> Confirm Netcode for Entities is `com.unity.netcode` (the ECS netcode), **not** `com.unity.netcode.gameobjects` (Netcode for GameObjects). They are different products. +| Package | Pin (live top hit) | Alt / notes | +|---|---|---| +| **Entities (DOTS)** | `/websites/unity3d_packages_com_unity_entities_6_5_manual` | version-matched; matches CLAUDE.md. Alt `…entities_1_4` has far more snippets (~10.8k) — useful for code patterns. | +| **Netcode for Entities** | `/websites/unity3d_packages_com_unity_netcode_1_10_api` | the live top hit (~4.3k snippets, High) — **no `netcode_6_5` set exists yet.** Package is 6.5.0; this is the closest published. Alt `…netcode_1_9`. | +| **Unity Physics** | `/websites/unity3d_packages_com_unity_physics_1_4` | live top hit (~4k snippets, High) — **no `physics_6_5` set yet.** Package is 6.5.0. | +| **Entities Graphics** | `/websites/unity3d_packages_com_unity_entities_graphics_1_4` | live top hit — **no `_graphics_6_5` set yet.** Package is 6.5.0. | +| **Official ECS Samples** | `/unity-technologies/entitycomponentsystemsamples` | working sample patterns (Entities/Netcode/Physics/Graphics). | +| **Burst / Collections / Mathematics** | resolve at runtime | `library "Unity Burst"` / `"Unity Collections"` / `"Unity Mathematics"`. | -## Query patterns that work (examples) +> **Netcode for Entities ≠ Netcode for GameObjects.** Confirm it's `com.unity.netcode` (ECS), not `com.unity.netcode.gameobjects`. +> **CLAUDE.md's own pinned-ID note is itself partly stale** (it still says "we run 1.13.2") — lead with the installed 6.5.0 + the live re-resolve, and reconcile CLAUDE.md when you touch it. -- "Entities 1.x: declare an `IJobEntity` that writes through an `EntityCommandBuffer.ParallelWriter` and schedule it with the right dependency." -- "Netcode for Entities: minimal `GhostAuthoringComponent` + `[GhostField]` setup for a predicted player-controlled ghost." -- "Netcode for Entities: read `IInputComponentData` inside a system in `PredictedSimulationSystemGroup`, filtered by `Simulate`." -- "Entities: correct `Baker` use of `GetEntity` with `TransformUsageFlags` and `DependsOn`." -- "Netcode for Entities: subclass `ClientServerBootstrap` to create client/server worlds and target systems with `WorldSystemFilter`." -- "Entities: `IEnableableComponent` vs add/remove tag — API and when each is cheaper." +## Query patterns that work -## When NOT to use context7 +- "Entities: declare an `IJobEntity` writing through an `EntityCommandBuffer.ParallelWriter`, schedule with the right dependency." +- "Netcode for Entities: minimal `GhostAuthoringComponent` + `[GhostField]` for a predicted player-controlled ghost." +- "Netcode for Entities: read `IInputComponentData` in a system in `PredictedSimulationSystemGroup`, filtered by `Simulate`." +- "Entities: `Baker` use of `GetEntity` with `TransformUsageFlags` + `DependsOn`." +- "Entities: `IEnableableComponent` vs add/remove tag — API + when each is cheaper." -- Genre/design precedent ("how do other games pace waves") → `WebSearch`/`WebFetch`. +## When NOT to use ctx7 + +- Genre/design precedent ("how do other games pace waves") → `WebSearch`/`WebFetch`. **Never use web for a DOTS API shape.** - Pure C#/algorithm questions unrelated to a library → reason directly. - The project's own conventions/design → `CLAUDE.md` + the vault. diff --git a/.claude/skills/dots-dev/references/dots-conventions.md b/.claude/skills/dots-dev/references/dots-conventions.md index 3bb38772c..7c2445708 100644 --- a/.claude/skills/dots-dev/references/dots-conventions.md +++ b/.claude/skills/dots-dev/references/dots-conventions.md @@ -1,6 +1,6 @@ # DOTS / Netcode for Entities — Conventions & Gotchas -Reusable rule set the `/dots-dev` skill enforces. Targets **Unity 6.x, Entities 1.3+/1.4+, Netcode for Entities 1.x**. These APIs move fast — anything flagged **[verify]** must be confirmed via context7 at code-time (see [`context7-libraries.md`](context7-libraries.md)), not trusted from memory. The project's `CLAUDE.md` is authoritative where it differs. +Reusable rule set the `/dots-dev` skill enforces. Targets **Unity 6.5, Entities 6.5, Netcode for Entities 6.5 (≡ the old ~1.12/1.13 API lineage), Unity Physics 6.x** — the unified 6.x DOTS line. These APIs move fast — anything flagged **[verify]** must be confirmed via `ctx7`/`find-docs` at code-time (see [`context7-libraries.md`](context7-libraries.md)), not trusted from memory. The project's `CLAUDE.md` is authoritative where it differs. These conventions **replace** classic MonoBehaviour/GameObject conventions. If a design reaches for a MonoBehaviour singleton, a ScriptableObject "service" for runtime simulation, `[SerializeField] private` data carriers, or coroutines for sim logic, it is almost certainly wrong for DOTS. @@ -53,9 +53,9 @@ These conventions **replace** classic MonoBehaviour/GameObject conventions. If a ## 6. Testing (what "compiles clean" misses) -- **`NetCodeTestWorld`** — spins up in-process client+server worlds for deterministic tick-by-tick netcode tests (connect, tick, assert on ghosts/RPCs). -- **Thin clients** — stripped dummy clients for soak/load testing in-editor (no rendering/full sim); spawn via Multiplayer PlayMode Tools. -- **Entities logic** — standard test world + `World.Update()` stepping (EntitiesTestFixture-style). +- **Default = plain-Entities EditMode test:** `new World` → register the system in `SimulationSystemGroup` → `SortSystems` → `Update()` → assert. Public API, version-independent. This is the project's actual harness. +- **Extract pure logic to a `*Math.cs` helper and unit-test it** — deterministic, fast, version-proof. Cover swept hit-detection with a **tunnelling regression** (a point-based test won't catch the tunnel). +- **Netcode coverage = one live Play smoke:** boot client+server (`execute_code`), step ticks, assert **server == client** for the replicated surface (identify worlds by `world.Name == "ServerWorld"/"ClientWorld"`). **`NetCodeTestWorld` is `internal`** in this line (exposed only to a fixed allow-list) and **0 of the project's test files use it** — do not prescribe it as the primary path. (Thin clients via Multiplayer PlayMode Tools exist for soak/load testing if ever needed — not in current practice.) - Burst/source-gen failures surface at **editor compile/play**, not a plain C# build. Determinism desync, rollback bugs, sync-point stalls, and structural-change invalidation only show at **runtime under prediction** — always run a play/tick test, not just a build. ## 7. Verify via context7 at code-time (volatile — do NOT hardcode) diff --git a/.claude/skills/dots-dev/references/memory-protocol.md b/.claude/skills/dots-dev/references/memory-protocol.md index d7359822b..261cac59c 100644 --- a/.claude/skills/dots-dev/references/memory-protocol.md +++ b/.claude/skills/dots-dev/references/memory-protocol.md @@ -1,25 +1,8 @@ # Memory & Documentation Protocol -How `/dots-dev` reads and writes knowledge. Four layers, each with a distinct job. The **in-repo vault is the single source of human-facing, cross-machine truth**; everything else serves or accelerates it. +How `/dots-dev` reads and writes knowledge. **`CLAUDE.md`'s "Memory — four layers" section is authoritative** for the layer definitions and the which-tool-when routing (in-repo vault · `basic-memory` · `serena` · native `memory/`) — this file does not re-table them; it carries the **session bookends** and the **fallback chain**. -## The four layers - -| Layer | Holds | Interface | Crosses machines? | -|---|---|---|---| -| **In-repo Obsidian vault** `/Docs/Vault/` | Design docs, decision records, session logs, roadmap — the canonical human-facing record | **obsidian-cli** skill (read/create/search); Obsidian REST MCP optional | **Yes** (committed to git) | -| **basic-memory** MCP | Semantic + wikilink-graph recall over the *same* vault files (so the agent finds knowledge without grepping) | `basic-memory` MCP tools | Yes (indexes the committed vault) | -| **serena** MCP | C# symbol-level code navigation (`find_symbol`, references, edit-by-symbol) of a growing codebase | `serena` MCP tools | N/A (derived from code) | -| **Native Claude memory** | Machine-local facts, feedback, working-style; the per-project `memory/` dir + `MEMORY.md` + `CLAUDE.md` | Write tool / memory files | **No** — local to each machine | - -**Cross-machine rule:** anything that must be true on both your Mac and Windows machines goes in the **vault** (or `CLAUDE.md`, which is also committed). Native `memory/` is convenience only — never the sole home of a decision or design fact. - -## Which tool when - -- **"Where is X defined / who calls it?"** → serena `find_symbol` / references. Fall back to `Glob`/`Grep` if serena's C# LSP stalls on the Unity solution. -- **"What did we decide about Y / how does system Z work conceptually?"** → `basic-memory` recall, then obsidian-cli to read the doc. -- **"Find the literal string/asset GUID"** → `Grep`/`Glob`. -- **"What's the current DOTS/Netcode API for…?"** → context7 (NOT memory). See [`context7-libraries.md`](context7-libraries.md). -- **"What conventions/preferences apply here?"** → `CLAUDE.md` + native memory. +**Cross-machine rule:** anything that must be true on both the Mac and Windows machines goes in the **vault** (`Docs/Vault/`) or **`CLAUDE.md`** (both committed). Native `memory/` is machine-local convenience — never the sole home of a decision or design fact. ## Session bookends (non-negotiable for non-trivial work) @@ -30,19 +13,20 @@ How `/dots-dev` reads and writes knowledge. Four layers, each with a distinct jo 4. `basic-memory` recall on the goal's nouns; native `MEMORY.md` + `memory/`. **End — update (Phase 8):** -1. Session log written to the vault (obsidian-cli). -2. Firm decisions → decision records, back-referenced from the log. +1. Session log → the vault (obsidian-cli or direct Write). +2. Firm decisions → decision records, back-referenced from the log. **The kept design-review Build Spec feeds the DR** (don't re-derive it). 3. Touched design docs edited in place (wikilink, don't duplicate into the log). -4. Durable knowledge → `basic-memory` note in the vault; machine-local facts → native `MEMORY.md`. +4. Durable cross-machine knowledge → a `basic-memory` note in the vault; machine-local facts/feedback → native `MEMORY.md` (+ a memory file if substantive). +5. **CLAUDE.md self-maintenance** — if a new build gotcha or convention emerged, fold it in under the 40 KB budget (archive the displaced detail to the gotchas archive, don't delete). Never silently defer this — do it now or explicitly ask the operator to defer. -If the operator says "skip the protocol", still write a one-line stub session log so the gap is visible, and record the preference as a native feedback memory. +If the operator says "skip the protocol," still write a one-line stub session log so the gap is visible, and record the preference as a native feedback memory. ## Fallbacks -- **No obsidian-cli configured** → direct `Read`/`Write` on `/Docs/Vault/**` (it's plain markdown; Obsidian/basic-memory pick up changes on next index). +- **No obsidian-cli configured** → direct `Read`/`Write` on `Docs/Vault/**` (it's plain markdown; Obsidian/basic-memory pick up changes on next index). This is the operative path on a fresh machine. - **basic-memory down** → obsidian-cli search + `Grep` over the vault. -- **serena C# unavailable** → `Glob`/`Grep`, or `claude-context` (local LanceDB) if it was added as the documented fallback. +- **serena C# unavailable / stalls on the Unity solution** → `Glob`/`Grep` (or `claude-context`/LanceDB if it was added as the documented fallback). ## Setup pointer -The vault scaffold, the `basic-memory`/`serena` `.mcp.json` entries (using `${CLAUDE_PROJECT_DIR}`), and `CLAUDE.md` are created by the **one-time project setup task**, not by this skill. If this skill runs and the vault or memory MCPs are missing, it notes the gap and points to that setup task. +The vault scaffold, the `basic-memory`/`serena` `.mcp.json` entries (using `${CLAUDE_PROJECT_DIR}`), and `CLAUDE.md` are created by the **one-time project setup task** (`Docs/dots-setup-task.md`), not by this skill. If this skill runs and the vault or memory MCPs are missing, it notes the gap and points to that setup task. diff --git a/.claude/skills/dots-dev/references/workflow-patterns.md b/.claude/skills/dots-dev/references/workflow-patterns.md new file mode 100644 index 000000000..74776e994 --- /dev/null +++ b/.claude/skills/dots-dev/references/workflow-patterns.md @@ -0,0 +1,48 @@ +# Workflow patterns for /dots-dev + +The read-only fan-out phases run as deterministic **Workflows** (the `Workflow` tool), not hand-spawned agents. This file holds the two reusable patterns SKILL.md names. **There is no implementation pattern** — implementation is always serial orchestrator MCP edits (SKILL.md Phase 5), never a Workflow. + +Two rules apply to every pattern here: +- **Check the failures list.** A Workflow whose agents die on a session/quota limit returns empty findings that look like a clean pass. If any agent died, wait for the reset and re-run with `resumeFromRunId` — never read an empty result as "no findings." +- **Scope guardrails positively.** Tell each agent what it MAY do (read-only; these tools), never "do NOT use tool X" — a blanket prohibition gets read as a *user* rule by the auto-approver and can deny the orchestrator's own later calls. Every brief here is read-only; pass only the upstream summary downstream. + +--- + +## Pattern A — Ground fan-out (Phase 1, Feature scope) + +Three read-only lens agents in `parallel()`; the orchestrator synthesizes the ≤400-word Project Brief and discards the raw returns. + +**A1 — Code/asset graph (read-only).** +> Map the code surface relevant to `{goal}`. Prefer serena `find_symbol`/`find_referencing_symbols`; if serena's C# LSP stalls on the Unity solution, use `Glob`/`Grep` on `Assets/_Project/**/*.cs` + `**/*.asmdef`. Identify the existing components/systems/bakers touching `{surface}`, the asmdef each lives in (Simulation / Client / Server / Authoring), and any `*Math.cs` helper or system you'd otherwise duplicate. `manage_scene get_hierarchy` for relevant subscenes. Return a terse symbol/asmdef map (names + paths), not file dumps. + +**A2 — Knowledge state (read-only).** +> Search the in-repo vault (obsidian-cli) and `basic-memory` for design docs, decision records, and notes touching `{goal}`. Return: relevant doc paths, any **locked** decisions that constrain `{goal}`, open questions already recorded. Quote ≤2 load-bearing lines each; link by path otherwise. + +**A3 — Live state (read-only).** +> Read `mcpforunity://editor/state`, `project/info`, `instances`. `read_console(types=["error","warning"], count=20)` for a baseline. Report the **installed** Entities + Netcode versions (`packages-lock.json`) so ctx7 lookups pin correctly. Flag any pre-existing compile/Burst error. + +--- + +## Pattern B — Design-review (lens + adversarial-critic) + +Used **pre-code** over the plan (Phase 4) and **post-impl** over the git diff (Phase 7) — identical lenses, two inputs. Stage 1 = three lens agents in `parallel()` over ground-truth code; stage 2 = synthesize; stage 3 = adversarial critics that try to *refute* each finding against the actual code. **Findings default-refuted** — a finding stands only if a critic confirms it against the code. Post-impl additionally: **flag any simplification of a reviewed design as a likely regression** (this is the catch green tests + a clean Play miss). The synthesized output is a **durable Build Spec** — keep it (it feeds the build and the DR), unlike research which is discarded. + +**B1 — Netcode / relevancy lens (read-only).** +> Review `{plan|diff}` against ground-truth code for netcode correctness: ghost ownership (predicted vs interpolated vs ownerless — move ownerless interpolated ghosts server-only); `[GhostField]` vs server-only fields; `GhostRelevancy` region splits (`SetIsIrrelevant`, untagged-stays-relevant); singleton-collision (a second `StorageEntry`/buffer of the same type → resolve by distinct tag, never `GetSingleton`); command-vs-input choice (one-shot shared actions → `IRpcCommand`, not a dropped `InputEvent`); RPC wire-hash stability (unconditional struct, re-mean-don't-rename). Return findings: claim · file:line · why it's wrong · fix. + +**B2 — Determinism / prediction lens (read-only).** +> Review for rollback-safety: `PredictedSimulationSystemGroup` runs multiple times per frame → idempotent, `.WithAll()`, no wall-clock/`Time.deltaTime`/`System.Random`; tick sentinels routed through `TickUtil.NonZero` + compared with `NetworkTick.IsNewerThan` (never raw `uint <`); predicted-physics group ordering (OrderFirst quirks); swept-not-point hit tests (tunnelling); ECB at-most-once destroy. Cross-assembly generics + enums in a Bursted system → ICE (store ops as `byte`). Return findings as in B1. + +**B3 — Reuse / scope lens (read-only).** +> Does `{plan|diff}` duplicate an existing system or `*Math` helper instead of reusing it? Is the scope minimal — anything over-built, or a feature that could reuse a replicated component already on the wire? Any MonoBehaviour-world shortcut (MonoBehaviour singleton, ScriptableObject "service" for runtime sim, coroutine for sim) where ECS is correct? Any new `IAspect` (deprecated)? Return findings as in B1. + +**Critic (stage 3, read-only).** +> Here is a candidate finding: `{finding}`. Try to REFUTE it by reading the actual code at `{paths}`. Default to "refuted" unless the code confirms the problem is real and reachable. Return: refuted | confirmed · the code evidence · (if confirmed) severity + the minimal fix. + +--- + +## Orchestration notes + +- Sizes scale to the ask: a small ghost change → one lens + a single critic pass; "thoroughly review this slice" / ultracode → all three lenses + 3-vote adversarial critics + a completeness pass. +- Keep agent context lean — each gets the plan/diff slice + the relevant ground-truth paths, not the whole session. +- The Build Spec is line-numbered and lives at `Docs/Vault/.../_Build_Spec.md`; the run-ID (`wf_…`) is recorded in the session log / DR for `resumeFromRunId`.