Commit dots-dev skill into repo for cross-machine portability

Move the dots-dev skill from machine-local ~/.claude/skills/ into the
repo at .claude/skills/dots-dev/ so it travels with a clone. Update the
CLAUDE.md per-machine setup note to reflect that the skill no longer
needs manual placement; unity-mcp-skill and native memory/ stay local.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Luis Gonzalez
2026-06-01 11:58:37 -07:00
parent e851d5f8e9
commit a5af81c8a8
6 changed files with 470 additions and 2 deletions
+210
View File
@@ -0,0 +1,210 @@
---
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 <game>", "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.
---
# /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**.
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.
> **One-line reminder**: set max reasoning before invoking a Feature-track session. `/dots-dev` Feature track is heavy by design.
## 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 `<repo>/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.
## 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.
**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.
## Adaptive track selection (do this first)
Size the goal, then run the matching track. Plan-approval and the doc/memory update are mandatory in **all** tracks.
| Track | When | Phases run |
|---|---|---|
| **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 09 below. |
When unsure, ask the operator with one `AskUserQuestion` ("Treat this as a quick edit or a full feature pass?") rather than guessing big.
## Phase 0 — Pre-flight + intake gate
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 24 ambiguities into a single `AskUserQuestion` before spawning anything. If the prompt is already specific, skip the gate.
## Phase 0b — Plan-mode entry + Documentation Protocol scan
Declare plan mode active for phases 15: 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`.
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 (`<repo>/Docs/Vault/00_Home/Home.md`) and the latest session log under `07_Sessions/<year>/`.
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.
## Phase 1 — Project & doc context swarm (≤3 agents, Explore)
- **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).
Synthesize into a **≤400-word Project Brief**. Discard raw dumps.
## Phase 2 — Goal-understanding swarm (≤3 agents)
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 3 — Research swarm (context7-FIRST)
- **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.
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 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<T>`, 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 (35 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, 34 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 → `<repo>/Docs/Vault/07_Sessions/<year>/<YYYY-MM-DD>_<Topic>.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
```
## /dots-dev session complete — <Topic>
**Summary**: ≤4 sentences — goal, what was delivered, did it land cleanly.
**What changed**:
- Unity: <repo-relative path> — <one line> (repeat)
- Vault: <repo-relative path> — <one line> (repeat)
**Validation**: Tests <X/Y>, console clean, <netcode/determinism check result>.
**Suggested next step**: <one concrete next action, from the session log's Next-session intent>.
```
Stop. Do not auto-loop into a fresh session.
## DOTS conventions (authoritative file)
`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<T>` + 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.
## MCP cheat sheet
| 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=[...])` | 10100× 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 |
## Error recovery
| 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 |
### UnityMCP "not connected" — diagnostic protocol (subagents MUST follow before reporting it down)
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 25s 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__<name>")` then retry (tool-loading, not connection).
Escalate only after 13 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 `<repo>` / `${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.
- Auto-commit to git (the operator commits manually). 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.
@@ -0,0 +1,98 @@
# 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<T>`, 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 12 agent fix sub-swarm, re-running only the affected validator.
---
## Phase 8 — Doc + memory (general-purpose)
**A — Session log**
> Write `<repo>/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.
@@ -0,0 +1,44 @@
# context7 — 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.
## Flow
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.
## 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.
## Seed library IDs (re-resolve if installed version differs)
| 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). |
> Confirm Netcode for Entities is `com.unity.netcode` (the ECS netcode), **not** `com.unity.netcode.gameobjects` (Netcode for GameObjects). They are different products.
## Query patterns that work (examples)
- "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<T>` 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."
## When NOT to use context7
- Genre/design precedent ("how do other games pace waves") → `WebSearch`/`WebFetch`.
- Pure C#/algorithm questions unrelated to a library → reason directly.
- The project's own conventions/design → `CLAUDE.md` + the vault.
@@ -0,0 +1,68 @@
# 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.
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.
## 1. Code structure
- **`struct : IComponentData`** — the default. Unmanaged, blittable, Burst- and job-friendly. Use for nearly all data.
- **`class : IComponentData`** — managed component. Only for genuine managed refs (a `GameObject`, `Material`). Main-thread only, no Burst, no jobs. Keep out of hot paths.
- **`IBufferElementData`** — per-entity dynamic array (`DynamicBuffer<T>`): inventory, path points, command history.
- **`ISharedComponentData`** — groups entities into chunks by shared value; changing it is a **structural change**. Use sparingly; prefer unmanaged shared components.
- **`IEnableableComponent`** — toggle a component on/off **without a structural change**. Prefer over add/remove tag components for frequently-flipped state. Enabled by default.
- **Systems**: `ISystem` (struct, Burst-compatible — **default**) vs `SystemBase` (class, managed, main-thread, no Burst — only when you must touch managed objects). Tag system methods `[BurstCompile]`.
- **`SystemAPI`** is the entry point inside systems: `SystemAPI.Query<...>()`, `.GetComponent`, `.Time`, `.GetSingleton`. Source-generated; valid only inside `ISystem`/`SystemBase`.
- **Aspects (`IAspect`) are DEPRECATED as of Entities 1.4 — do not author new ones.** Use components + `SystemAPI.Query`/`IJobEntity` directly. `Entities.ForEach` is legacy; avoid. **[verify]** the current recommended replacement.
- **Naming**: components are nouns/adjectives (`Health`, `Velocity`, `MoveSpeed`); tags suffix-free or `…Tag`; authoring MonoBehaviours suffix `Authoring`; systems suffix `System`; buffer elements often `…Element`/`…BufferElement`.
## 2. Jobs & Burst
- **`IJobEntity`** — preferred per-entity job (source-generated `Execute` over a query). **`IJobChunk`** — lower-level, chunk-wide/manual iteration. **`SystemAPI.Query`** — main-thread iteration.
- **Scheduling** — `Schedule()` / `ScheduleParallel()`; thread the returned `JobHandle` through `state.Dependency`. Avoid manual `.Complete()` unless you need results now (it's a sync point).
- **Burst breaks on** — managed types, `try/catch`/exceptions, `typeof`/reflection, virtual calls, `string` ops, GC allocation, most of `System.*`. Keep job code `unmanaged`.
- **Collections** — `NativeArray/List/HashMap`, `NativeQueue`, etc. Allocators: `Allocator.Temp` (frame/scope, auto-freed, **not** across job boundaries), `Allocator.TempJob` (one job, must dispose), `Allocator.Persistent` (long-lived, must dispose). **Always dispose** non-Temp, or `.Dispose(jobHandle)`.
- Mark inputs `[ReadOnly]` to allow parallel access; write-aliasing across parallel jobs is a safety error.
## 3. Baking (authoring → entities)
- **Why**: authoring data is converted **offline at edit/import time** into entities — no runtime conversion cost, deterministic, streamable.
- **Pattern**: a `MonoBehaviour` named `…Authoring` + `class FooBaker : Baker<FooAuthoring>` whose `Bake()` calls `GetEntity(...)` then `AddComponent(entity, new Foo{...})`.
- **Subscenes** hold baked entities and stream in/out asynchronously — entities are **not present the instant a subscene reference exists**; gate logic on load state.
- **Mistakes**: referencing other entities without `GetEntity(authoring, TransformUsageFlags.…)`; not declaring `DependsOn` (so bake doesn't re-run on asset change); doing runtime-only work in `Bake()`; forgetting `TransformUsageFlags` (→ missing `LocalTransform`).
## 4. Netcode for Entities
- **Ghosts** = replicated entities. Mark a prefab with **`GhostAuthoringComponent`**; mark replicated fields with **`[GhostField]`**; tune per-component replication with **`[GhostComponent]`** (e.g. `SendToOwner`). Variants via **`IGhostComponentVariation`**. **[verify]** attribute parameters.
- **Predicted vs interpolated ghosts**: predicted = simulated locally + rolled back (player-controlled, fast reaction). Interpolated = smoothed display of past server state (remote/non-critical).
- **Prediction & rollback**: core sim runs in **`PredictedSimulationSystemGroup`**, a **fixed-step** group on **both client and server**. On each new snapshot the client re-simulates from the oldest received tick → systems run **multiple times per frame**; sim code must be idempotent/deterministic. Filter queries with **`.WithAll<Simulate>()`** so only currently-simulated entities run. **[verify]** group internals/names.
- **Server-authoritative**: server is truth; clients send **input**, not state.
- **Input**: prefer **`IInputComponentData`** (auto-buffered to `InputBufferData<T>`); `ICommandData` is the lower-level command-buffer form. Don't read raw `UnityEngine.Input` in sim systems. **[verify]** helper signatures.
- **RPCs**: `struct : IRpcCommand` for one-off events (connect, requests). Not for per-tick state.
- **Determinism**: no `Time.deltaTime`/wall-clock in sim — use the netcode fixed tick. Avoid non-deterministic float sources, `System.Random`, ordering by hash. Cross-machine float determinism is fragile — keep predicted sim simple and consistent.
- **Worlds & bootstrap**: separate **client** and **server** `World`s; subclass **`ClientServerBootstrap`** (`CreateClientWorld`/`CreateServerWorld`) to customize. Annotate systems with `[WorldSystemFilter(...)]` to target client/server/thin. **[verify]** bootstrap method names + `WorldSystemFilterFlags`.
## 5. Common footguns
- **Structural changes** (add/remove component, create/destroy entity, set shared component) **invalidate `Entity`/component handles & references** and cause sync points. Batch via **ECB**.
- **ECB (`EntityCommandBuffer`)**: record now, play back later. Use built-in `Begin/EndSimulationEntityCommandBufferSystem` (and `BeginInitialization…`). One ECB per job; in parallel jobs use `.AsParallelWriter()`. Don't read back values you just recorded.
- **System order**: `[UpdateInGroup]`, `[UpdateBefore/After]`. Key groups: `InitializationSystemGroup`, `SimulationSystemGroup`, `PresentationSystemGroup`; netcode adds `PredictedSimulationSystemGroup`, `GhostSimulationSystemGroup`. **[verify]** netcode group set.
- **Main-thread-only**: managed components, `EntityManager` structural ops, most `World`/managed access. Keep out of Burst jobs.
- **No managed refs in unmanaged components** — won't compile / breaks Burst. Use a managed `IComponentData`, a `BlobAssetReference`, or an `Entity` reference instead.
- **Subscene timing & GO↔entity mixing**: entities may not exist yet; bridging GameObjects↔entities is manual and a known pain point — design around it, don't sprinkle hybrid links.
## 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).
- 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)
- Aspect deprecation status & the recommended replacement.
- Exact **system group names/order** and netcode prediction-group internals.
- **Input** API (`IInputComponentData` vs `ICommandData`) helper signatures.
- Ghost attribute options (`[GhostField]`/`[GhostComponent]` parameters, variants).
- Bootstrap/world-creation method names and `WorldSystemFilterFlags`.
- ECB system names + allocator/Collections API surface.
@@ -0,0 +1,48 @@
# 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.
## The four layers
| Layer | Holds | Interface | Crosses machines? |
|---|---|---|---|
| **In-repo Obsidian vault** `<repo>/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.
## Session bookends (non-negotiable for non-trivial work)
**Start — scan (read-only):**
1. `CLAUDE.md` (repo root).
2. Vault map of content + latest session log (`07_Sessions/<year>/`).
3. Open decision records (`_Decisions/` `status: proposed`) + roadmap/backlog.
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.
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`.
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 `<repo>/Docs/Vault/**` (it's plain markdown; Obsidian/basic-memory pick up changes on next index).
- **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.
## 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.
+2 -2
View File
@@ -95,7 +95,7 @@ Full rules: `~/.claude/skills/dots-dev/references/dots-conventions.md` (Windows:
## Per-machine setup (NOT in git — redo on each machine)
`.mcp.json` is committed and portable (`${CLAUDE_PROJECT_DIR}` only). But each machine still needs:
1. `uv`/`uvx`, the Obsidian app + `obsidian-cli`, and the `dots-dev` skill in `~/.claude/skills/`.
`.mcp.json` is committed and portable (`${CLAUDE_PROJECT_DIR}` only). The **`dots-dev` skill now travels with the repo** at `.claude/skills/dots-dev/` (project-level, auto-discovered by Claude Code on clone — no manual `~/.claude/skills/` copy needed). But each machine still needs:
1. `uv`/`uvx`, the Obsidian app + `obsidian-cli`. (The `unity-mcp-skill` and native `memory/` notes remain machine-local and do **not** sync — re-install / re-create them per machine if wanted.)
2. **basic-memory project registration** (machine-local config): `uvx basic-memory project add gamevault "<repo>/Docs/Vault" --default`, then `uvx basic-memory reindex --full --search --embeddings --project gamevault`.
3. Unity 6.4 opens the project and the CoplayDev Unity-MCP bridge connects (`mcpforunity://editor/state``ready_for_tools`).