Rewrite /dots-dev skill: Workflow-first, two-review sandwich, 6.5 pins

Realigns the skill with how sessions actually run now — it predated the
Workflow tool and the ultracode two-review practice. Driven by an analysis
of the full session history + the 26-file memory corpus + skill-authoring
research, adversarially reviewed.

Key changes:
- Workflow-first orchestration: drop the dead manual "swarm (<=N agents)"
  model and the impossible 3-5-agent impl swarm; implementation is serial
  orchestrator MCP edits. New references/workflow-patterns.md (ground
  fan-out + design-review lens/critic) replaces agent-briefs.md.
- Pre-code design-review + post-impl diff-review are now first-class gated
  phases (the spine that catches what green tests + a clean Play miss).
- Size by blast-radius / netcode-heaviness, not time estimates.
- Lean SKILL.md (222 -> 131 lines, -25% KB): leans on CLAUDE.md instead of
  duplicating its MCP cheat-sheet / anti-patterns / error-recovery.
- ctx7 CLI / find-docs mechanism (the MCP verbs are gone); live-verified
  6.5-era library pins; kill the dead NetCodeTestWorld test path.
- Encode operator gates (no-time-estimates, present-forks, never-defer,
  tuning-autonomy) + the highest-recurrence MCP-edit / Workflow gotchas.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-18 21:19:49 -07:00
parent 6b368d1a29
commit 4ac1ae5a2e
6 changed files with 180 additions and 329 deletions
+82 -172
View File
@@ -1,221 +1,131 @@
--- ---
name: dots-dev 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. 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 <game>", "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 # /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 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.
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). 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).
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). 4. **DOTS-correct.** ECS conventions per `CLAUDE.md` + [`references/dots-conventions.md`](references/dots-conventions.md). Any violation found in review is blocking.
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. 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.
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). 6. **Operator gates.** Present-forks-don't-auto-decide · no time/effort/deadline estimates · never-silently-defer · tuning-defaults autonomy. See *Operator gates* below.
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}`. 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}`.
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 ## 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. | | **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 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. | | **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 L1L2 → doc. |
| **Feature** | new mechanic, netcode surface, cross-cutting change, or anything >~30 min | full swarm, Phases 09 below. | | **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. ## The spine
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 ### 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 24 ambiguities into one `AskUserQuestion`. Specific prompt → skip.
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`. ### 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): 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.
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) 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. ### Phase 2 — ctx7 API verification
- **B — Knowledge state**: obsidian-cli search + `basic-memory` recall for design/decisions touching the goal. 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).
- **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 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 2Goal-understanding swarm (≤3 agents) ### Phase 4Pre-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/.../<Slice>_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 3Research swarm (context7-FIRST) ### Phase 6Verify 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. Loop ≤3 fix iterations per finding; if iteration 3 still fails, halt and surface "I can't resolve X without a decision."
- **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 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) ### 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/<year>/<YYYY-MM-DD>_<Topic>.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.
- **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
### Phase 9 — Final report + offer commit
``` ```
## /dots-dev session complete — <Topic> ## /dots-dev session complete — <Topic>
**Summary**: ≤4 sentences — goal, delivered, did it land cleanly.
**Summary**: ≤4 sentences — goal, what was delivered, did it land cleanly. **What changed**: Unity / Vault — <repo-relative path> — <one line> (repeat)
**Validation**: L1 console clean · L2 tests X/Y + Play smoke (server==client) · L3 <if visual>.
**What changed**: **Reviews**: pre-code <result> · post-impl <result>.
- Unity: <repo-relative path> — <one line> (repeat) **Next step**: <one concrete next action from the log's Next-session intent>.
- 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** 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: Pass only the upstream summary downstream — never raw agent dumps (research discards; the design-review Build Spec is the deliberate exception — keep it).
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.
## 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<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. - **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 | **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.
|---|---|---|
| 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 **May loop without consulting** (≤3): compile/Burst fix→recompile · test fail→fix→retest · vault write fail→re-read→retry.
| Symptom | Cause | Resolution | **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.
|---|---|---|
| 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 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: ## References (load on demand)
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. - [`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.
## Boundary rules - [`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.
**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.
- **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.
@@ -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<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.
@@ -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). ## Flow (per the global `ctx7` rule)
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. 1. **Resolve:** `npx ctx7@latest library "<official name>" "<your specific question>"` → 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").
4. Limit: ≤3 `resolve` calls and ≤3 `query` calls per question (the tool enforces this). Reuse IDs across a session. 2. **Fetch:** `npx ctx7@latest docs <libraryId> "<your specific question>"` — 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 ## 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 | 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.
|---|---|---|---|
| **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. | 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." ## Query patterns that work
- "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 - "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<T>` 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. - Pure C#/algorithm questions unrelated to a library → reason directly.
- The project's own conventions/design → `CLAUDE.md` + the vault. - The project's own conventions/design → `CLAUDE.md` + the vault.
@@ -1,6 +1,6 @@
# DOTS / Netcode for Entities — Conventions & Gotchas # 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. 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) ## 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). - **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.
- **Thin clients** — stripped dummy clients for soak/load testing in-editor (no rendering/full sim); spawn via Multiplayer PlayMode Tools. - **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).
- **Entities logic** — standard test world + `World.Update()` stepping (EntitiesTestFixture-style). - **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. - 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) ## 7. Verify via context7 at code-time (volatile — do NOT hardcode)
@@ -1,25 +1,8 @@
# Memory & Documentation Protocol # 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 **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.
| 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) ## 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/`. 4. `basic-memory` recall on the goal's nouns; native `MEMORY.md` + `memory/`.
**End — update (Phase 8):** **End — update (Phase 8):**
1. Session log written to the vault (obsidian-cli). 1. Session log the vault (obsidian-cli or direct Write).
2. Firm decisions → decision records, back-referenced from the log. 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). 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 ## 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). - **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. - **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 ## 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.
@@ -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<T>`); 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<Simulate>()`, 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/.../<Slice>_Build_Spec.md`; the run-ID (`wf_…`) is recorded in the session log / DR for `resumeFromRunId`.