DR-022 + session log for the Rukhanka/Synty player-animation slice; CLAUDE.md stack row + Animation (Rukhanka) build gotchas + client asmdef refs; add Phase 10 (operator-approved commit) to the dots-dev skill. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
23 KiB
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.
/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-devFeature track is heavy by design.
Core principles (read first)
- 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. Seereferences/context7-libraries.md. - 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. Seereferences/dots-conventions.md. - Plan mode through approval. Phases up to operator approval are read-only. Code is written only after the operator approves and
ExitPlanModeis called. Self-police this — it is not harness-enforced. - 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. - Cross-platform. Discover the project root (cwd /
$CLAUDE_PROJECT_DIR). Reference the vault repo-relative as<repo>/Docs/Vault/. Never write/Users/...orC:\...into code, docs, or config — committed.mcp.jsonuses${CLAUDE_PROJECT_DIR}. - 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 0–9 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
- Foundation check (DOTS installed?). Read
Packages/packages-lock.json(ormanage_packages action=list). Ifcom.unity.entities/com.unity.netcodeare 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. - Unity ready? Read
mcpforunity://editor/state. Ifready_for_tools == falseor 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, readmcpforunity://instancesandset_active_instanceon the right one. - Memory stack reachable? Quick probe:
basic-memory(semantic recall) andserena(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 (orclaude-contextif installed) for this session. - Max-reasoning nudge (Feature track only, once): "Feature track benefits from max reasoning — raise the slider before approving the plan." Don't nag.
- Intake gate. If scope / surface / depth / output is unclear, bundle 2–4 ambiguities into a single
AskUserQuestionbefore 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 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.
Scan, in order (via obsidian-cli unless the Obsidian REST MCP is present):
CLAUDE.mdat repo root — authoritative project conventions + game design pointers.- Vault map of content (
<repo>/Docs/Vault/00_Home/Home.md) and the latest session log under07_Sessions/<year>/. - Open decision records (
_Decisions/withstatus: proposed) + roadmap/backlog. basic-memorysemantic recall on goal keywords; nativeMEMORY.md+memory/for machine-local facts/feedback.- 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, elseGlob/GreponAssets/_Project/**/*.cs+*.asmdef;manage_scene(action="get_hierarchy");unity_reflectfor goal-relevant types. - B — Knowledge state: obsidian-cli search +
basic-memoryrecall 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 inreferences/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/WebFetchallowed — 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 vsSystemBase), jobs, system groups/order, ECB usage, asmdef impact (which assembly: shared-simulation / client / server / authoring). MUST respectreferences/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 (3–5 agents)
- A — Script author:
create_script(new) /apply_text_editsafterget_sha(existing).validate_scriptnon-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_executefor 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, viaget_test_job(... include_failed_tests=True). For netcode work, aNetCodeTestWorldconnect/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>.mdvia 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-memorynote 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>.
Then offer to commit the changes (Phase 10) — propose how, but do not commit unless asked. Do not auto-loop into a fresh session.
Phase 10 — Commit (only after explicit operator approval)
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.
When approved:
- Review first.
git status+git diff --stat(andgit diffon anything non-obvious) so the operator sees exactly what lands. Stage explicit paths — nevergit add -Ablindly. Never commit generated/cache (Library/,Temp/,obj/,Logs/,UserSettings/),.csproj/.sln, or stray scratch files (debug screenshots, temp exports). - 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.metain the same commit. - Proper messages. Read recent
git log --onelinefirst 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. - Branch + push policy. Match the repo's convention (the
git logreveals 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. - Report the commit hash(es) + a one-line summary of each, then stop.
DOTS conventions (authoritative file)
CLAUDE.md at the repo root is the project's source of truth; 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=[...]) |
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 |
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:
ReadMcpResourceTool(server="UnityMCP", uri="mcpforunity://instances")—instance_count >= 1⇒ connected (stop reporting down);== 0⇒ Unity not attached (operator opens Unity).ReadMcpResourceTool(server="UnityMCP", uri="mcpforunity://editor/state")—ready_for_tools==false/is_compiling==true⇒ transient busy, wait 2–5s and retry.manage_editor(action="telemetry_ping")— success ⇒ bridge alive.- If the call returns
InputValidationErrorclaiming the tool is unknown, the schema is deferred —ToolSearch(query="select:mcp__UnityMCP__<name>")then retry (tool-loading, not connection).
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] privatedata carriers, coroutines for sim) where ECS is correct. - Author new
IAspecttypes (deprecated in Entities 1.4). - Store managed references in unmanaged
IComponentData. - Use wall-clock/
Time.deltaTimeorSystem.Randomin predicted/deterministic sim. - Do structural changes mid-job/mid-iteration instead of via
EntityCommandBuffer. - Edit
.metafiles directly, or read/writeLibrary/,Temp/,obj/,Logs/,UserSettings/. - Edit/commit
*.csproj/*.sln(Unity regenerates them). Edit.asmdef/manifest.jsoninstead. - Edit during Play Mode (check
play_statefirst). - 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. - 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-devin parallel.
References
references/dots-conventions.md— ECS/Netcode conventions this skill enforces.references/context7-libraries.md— seed library IDs + query playbook.references/agent-briefs.md— per-phase swarm brief templates.references/memory-protocol.md— vault / basic-memory / serena / native-memory usage + bookends.