Release 1.1.2 — the default path works end to end

Fix release for 1.1.1: the minimal path end to end, engine commands that
run on Godot, Unity and Unreal, hook warnings you can see, and verdicts
that say when they could not check. Details in CHANGELOG.md; upgrade
steps in UPGRADING.md (v1.1.1 → v1.1.2).

Fixes #67
Fixes #131

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WuJn2FdynEybfL5KC697nJ
This commit is contained in:
Donchitos
2026-09-29 21:32:19 +10:00
co-authored by Claude Opus 5.5
parent 7ed2c3e9c4
commit b21fa0f7f2
383 changed files with 22888 additions and 10618 deletions
@@ -3,8 +3,7 @@
## Agent Summary
**Domain owned:** Visual identity, art bible authorship and enforcement, asset quality standards, UI/UX visual design, visual phase gate, concept art evaluation.
**Does NOT own:** UX interaction flows and information architecture (ux-designer's domain), audio direction (audio-director), code implementation.
**Model tier:** Sonnet (note: despite the "director" title, art-director is assigned Sonnet per coordination-rules.md — it handles individual system analysis, not multi-document phase gate synthesis at the Opus level).
**Gate IDs handled:** AD-CONCEPT-VISUAL, AD-ART-BIBLE, AD-PHASE-GATE.
**Gate IDs handled:** AD-CONCEPT-VISUAL, AD-ART-BIBLE, AD-VISUAL, AD-PHASE-GATE.
---
@@ -13,8 +12,8 @@
Verified by reading the agent's `.claude/agents/art-director.md` frontmatter:
- [ ] `description:` field is present and domain-specific (references visual identity, art bible, asset standards — not generic)
- [ ] `allowed-tools:` list is read-focused; image review capability if supported; no Bash unless asset pipeline checks are justified
- [ ] Model tier is `claude-sonnet-5` (NOT Opus — coordination-rules.md assigns Sonnet to art-director)
- [ ] `tools:` includes Read (which also opens images for visual review) and Write/Edit for the art bible it maintains, and no Bash — `disallowedTools:` blocks it
- [ ] Model tier is `inherit` — frontmatter `model:` reads exactly `inherit` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over UX interaction flows or audio direction
---
@@ -22,12 +21,12 @@ Verified by reading the agent's `.claude/agents/art-director.md` frontmatter:
## Test Cases
### Case 1: In-domain request — appropriate output format
**Scenario:** The art bible's color palette section is submitted for review. The section defines a desaturated earth-tone primary palette with high-contrast accent colors tied to the game pillar "beauty in decay." The palette is internally consistent and references the pillar vocabulary. Request is tagged AD-ART-BIBLE.
**Expected:** Returns `AD-ART-BIBLE: APPROVE` with rationale confirming the palette's internal consistency and its alignment with the stated pillar.
**Scenario:** A complete art bible is submitted for sign-off with the pillars and core fantasy, the platform constraints and the visual identity anchor chosen during brainstorm. Its color section defines a desaturated earth-tone primary palette with high-contrast accent colors tied to the game pillar "beauty in decay"; its shape language, asset standards and character direction are consistent with that section and within the stated platform constraints. Request is tagged AD-ART-BIBLE.
**Expected:** Returns `AD-ART-BIBLE: APPROVE` with rationale confirming the palette's internal consistency and that the color system matches the pillar's mood target.
**Assertions:**
- [ ] Verdict is exactly one of APPROVE / CONCERNS / REJECT
- [ ] Verdict token is formatted as `AD-ART-BIBLE: APPROVE`
- [ ] Rationale references the specific palette characteristics and pillar alignment — not generic art advice
- [ ] Rationale references the specific palette characteristics and how they serve the "beauty in decay" mood target (the gate's color-vs-mood check) — not generic art advice
- [ ] Output stays within visual domain — does not comment on UX interaction patterns or audio mood
### Case 2: Out-of-domain request — redirects or escalates
@@ -36,16 +35,16 @@ Verified by reading the agent's `.claude/agents/art-director.md` frontmatter:
**Assertions:**
- [ ] Does not make any binding decision about audio layering or ducking behavior
- [ ] Explicitly names `audio-director` as the correct handler
- [ ] May note if the audio has visual mood implications (e.g., "the audio should match the visual tension of the zone"), but defers all audio specification to audio-director
- [ ] Any comment it makes is about the zone's visual mood (e.g., "the audio should match the visual tension of the zone") — it specifies no layer, duck amount, fade time or trigger
### Case 3: Gate verdict — correct vocabulary
**Scenario:** Concept art for the protagonist is submitted. The art uses a vivid, saturated color palette (primary: #FF4500, #00BFFF) that directly contradicts the established art bible's "desaturated earth-tones" palette specification. Request is tagged AD-CONCEPT-VISUAL.
**Expected:** Returns `AD-CONCEPT-VISUAL: CONCERNS` with specific citation of the palette discrepancy, referencing the art bible's stated palette values versus the submitted concept's palette.
**Scenario:** Right after pillars are locked, the concept and pillar set are submitted for a visual identity anchor. The three pillars are "fun combat," "great story," and "lots of content"; none of their design tests says anything about mood, atmosphere, or what the world should feel like, and no visual touchstones were given. Request is tagged AD-CONCEPT-VISUAL.
**Expected:** Returns `AD-CONCEPT-VISUAL: CONCERNS` — the gate's verdict for pillars that don't yet give enough direction to differentiate a visual identity — naming which pillars give no visual direction and what is missing (mood, shape language, color meaning).
**Assertions:**
- [ ] Verdict is exactly one of APPROVE / CONCERNS / REJECT — not freeform text
- [ ] Verdict is exactly one of CONCEPTS / STRONG / CONCERNS (the AD-CONCEPT-VISUAL verdicts) — not APPROVE / REJECT and not freeform text
- [ ] Verdict token is formatted as `AD-CONCEPT-VISUAL: CONCERNS`
- [ ] Rationale specifically identifies the palette conflict — not a generic "doesn't match style" comment
- [ ] References the art bible as the authoritative source for the correct palette
- [ ] Rationale names the specific pillars that give no visual direction and which of the gate's four direction components (visual rule, mood, shape language, color philosophy) they leave open — not a generic "pillars are vague"
- [ ] Does not rewrite the pillars itself — pillar changes go back to the user and creative-director
### Case 4: Conflict escalation — correct parent
**Scenario:** ux-designer proposes using high-contrast, brightly colored icons for the HUD to improve readability. art-director believes this violates the art bible's muted visual language and would undermine the visual identity.
@@ -57,23 +56,32 @@ Verified by reading the agent's `.claude/agents/art-director.md` frontmatter:
- [ ] References the specific art bible rule being violated
### Case 5: Context pass — uses provided context
**Scenario:** Agent receives a gate context block that includes the existing art bible with specific palette values (primary: #8B7355, #6B6B47; accent: #C8A96E) and style rules ("no pure white, no pure black; all shadows have warm undertones"). A new asset is submitted for review.
**Expected:** Assessment references the specific hex values and style rules from the provided art bible, not generic color theory advice. Any concerns are tied to specific violations of the provided rules.
**Scenario:** Agent receives a gate context block that includes the existing art bible with specific palette values (primary: #8B7355, #6B6B47; accent: #C8A96E) and style rules ("no pure white, no pure black; all shadows have warm undertones"). A new asset type is submitted for review: the first enemy sprite sheet, whose body colors come from the primary palette but whose outline is pure black (#000000), highlights pure white (#FFFFFF) and shadows a cool blue-grey (#5A6A7A). Request is tagged AD-VISUAL.
**Expected:** Assessment references the specific hex values and style rules from the provided art bible, not generic color theory advice, and returns `AD-VISUAL: REJECT` — the sprite breaks all three style rules, a style violation to resolve before the asset type is used — with each violation tied to the rule it breaks.
**Assertions:**
- [ ] References specific palette values from the provided art bible context
- [ ] Applies the specific style rules (no pure white/black, warm shadow undertones) from the provided document
- [ ] Applies the specific style rules (no pure white/black, warm shadow undertones) from the provided document, naming the outline, highlight and shadow colors that break them
- [ ] Does not generate generic art direction feedback disconnected from the supplied art bible
- [ ] Verdict rationale is traceable to specific lines or rules in the provided context
- [ ] Verdict token is `AD-VISUAL: REJECT`, with rationale traceable to specific lines or rules in the provided context
### Case 6: Missing gate input — NOT ASSESSED
**Scenario:** A complete, internally consistent art bible is submitted for sign-off with the pillars and the visual identity anchor, but no platform or performance constraints: the context gives none, `project.yaml` sets no `platform.*` or `performance.*` keys, and `.claude/docs/technical-preferences.md` still holds only unconfigured placeholders. Request is tagged AD-ART-BIBLE.
**Expected:** Returns `AD-ART-BIBLE: NOT ASSESSED`, naming the platform and performance constraints as the input it could not read — without them, the gate's check that the asset standards are achievable on the platform cannot be made.
**Assertions:**
- [ ] Verdict token is `AD-ART-BIBLE: NOT ASSESSED` — not APPROVE, although every section it could check is sound
- [ ] Names the platform and performance constraints as the missing input
- [ ] Does not assume a platform or budget to complete the review
---
## Protocol Compliance
- [ ] Returns verdicts using APPROVE / CONCERNS / REJECT vocabulary only
- [ ] Returns the verdict vocabulary the invoked gate's definition file lists — APPROVE / CONCERNS / REJECT for AD-ART-BIBLE and AD-VISUAL; CONCEPTS / STRONG / CONCERNS for AD-CONCEPT-VISUAL; READY / CONCERNS / NOT READY for AD-PHASE-GATE; `NOT ASSESSED`, naming the input, at any gate when an input the gate names is missing
- [ ] Stays within declared visual domain
- [ ] Escalates UX-vs-visual conflicts to creative-director
- [ ] Uses gate IDs in output (e.g., `AD-ART-BIBLE: APPROVE`) not inline prose verdicts
- [ ] Does not make binding UX interaction, audio, or code implementation decisions
- [ ] At a phase gate, treats an artifact the target phase requires that the calling skill passes as "none" as a finding (NOT READY or CONCERNS), and one passed as "not expected before [phase]" or "not required at `workflow: [tier]`" as no finding — it judges readiness for the phase being entered, not a later one
---
@@ -3,7 +3,6 @@
## Agent Summary
**Domain owned:** Creative vision, game pillars, GDD alignment, systems decomposition feedback, narrative direction, playtest feedback interpretation, phase gate (creative aspect).
**Does NOT own:** Technical architecture or implementation details (delegates to technical-director), production scheduling (producer), visual art style execution (delegates to art-director).
**Model tier:** Opus (multi-document synthesis, high-stakes phase gate verdicts).
**Gate IDs handled:** CD-PILLARS, CD-GDD-ALIGN, CD-SYSTEMS, CD-NARRATIVE, CD-PLAYTEST, CD-PHASE-GATE.
---
@@ -13,8 +12,8 @@
Verified by reading the agent's `.claude/agents/creative-director.md` frontmatter:
- [ ] `description:` field is present and domain-specific (references creative vision, pillars, GDD alignment — not generic)
- [ ] `allowed-tools:` list is read-heavy; should not include Bash unless justified by a creative workflow need
- [ ] Model tier is `claude-opus-4-8` per coordination-rules.md (directors with gate synthesis = Opus)
- [ ] `tools:` reads Read, Glob, Grep, Write, Edit, WebSearch and `disallowedTools:` lists Bash
- [ ] Model tier is `opus` — frontmatter `model:` reads exactly `opus` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over technical architecture or production scheduling
---
@@ -22,12 +21,12 @@ Verified by reading the agent's `.claude/agents/creative-director.md` frontmatte
## Test Cases
### Case 1: In-domain request — appropriate output format
**Scenario:** A game concept document is submitted for pillar review. The concept describes a narrative survival game built around three pillars: "emergent stories," "meaningful sacrifice," and "lived-in world." Request is tagged CD-PILLARS.
**Expected:** Returns `CD-PILLARS: APPROVE` with rationale citing how each pillar is represented in the concept and any reinforcing or weakening signals found in the document.
**Scenario:** The pillar set for a narrative survival game is submitted for a stress test, with its anti-pillars, core fantasy and unique hook. The hook names its closest comparable — "Like *Don't Starve*, AND ALSO every survivor you lose changes the world for good" — and none of the three pillars is a goal that comparable is built around. It has three pillars — "emergent stories," "meaningful sacrifice," and "lived-in world" — each with a definition and a design test that names a real decision it would settle; the pillars pull against each other (sacrifice vs. a world the player wants to preserve). Request is tagged CD-PILLARS.
**Expected:** Returns `CD-PILLARS: APPROVE` with specific feedback on each pillar, judged by the gate's criteria: is it falsifiable, does it create tension with the others, does it differentiate the game, would it settle a real design disagreement.
**Assertions:**
- [ ] Verdict is exactly one of APPROVE / CONCERNS / REJECT
- [ ] Verdict token is formatted as `CD-PILLARS: APPROVE` (gate ID prefix, colon, verdict keyword)
- [ ] Rationale references the three specific pillars by name, not generic creative advice
- [ ] Gives feedback on each of the three pillars by name against the gate's criteria (falsifiability, tension, differentiation from *Don't Starve*), not generic creative advice
- [ ] Output stays within creative scope — does not comment on engine feasibility or sprint schedule
### Case 2: Out-of-domain request — redirects or escalates
@@ -36,16 +35,16 @@ Verified by reading the agent's `.claude/agents/creative-director.md` frontmatte
**Assertions:**
- [ ] Does not make any binding decision about the schema design
- [ ] Explicitly names `technical-director` as the correct handler
- [ ] May note whether the data model has creative implications (e.g., what player data is tracked), but defers structural decisions entirely
- [ ] Any comment on the schema is limited to its creative implications (e.g., which player choices a save must remember) — it proposes no table, column, key or query design
### Case 3: Gate verdict — correct vocabulary
**Scenario:** A GDD for the "Crafting" system is submitted. Section 4 (Formulas) defines a resource decay formula that punishes exploration — contradicting the Player Fantasy section which calls for "freedom to roam without fear." Request is tagged CD-GDD-ALIGN.
**Expected:** Returns `CD-GDD-ALIGN: CONCERNS` with specific citation of the contradiction between the formula behavior and the Player Fantasy statement.
**Scenario:** A GDD for the "Crafting" system is submitted with the game's pillars — "curiosity is always rewarded" and "the world remembers" — and its MDA target, Discovery first. Section 4 (Formulas) defines a resource decay formula that punishes exploration — contradicting the Player Fantasy section which calls for "freedom to roam without fear," and working against the curiosity pillar. Every other section serves the pillars, and retuning the formula would resolve the conflict without redesigning the system. Request is tagged CD-GDD-ALIGN.
**Expected:** Returns `CD-GDD-ALIGN: CONCERNS` with specific citation of the contradiction between the formula behavior and the Player Fantasy statement. The fix is stated as a creative constraint; the formula itself is left to the design team.
**Assertions:**
- [ ] Verdict is exactly one of APPROVE / CONCERNS / REJECT — not freeform text
- [ ] Verdict token is formatted as `CD-GDD-ALIGN: CONCERNS`
- [ ] Rationale quotes or directly references GDD Section 4 (Formulas) and the Player Fantasy section
- [ ] Does not prescribe a specific formula fix — that belongs to systems-designer
- [ ] Rationale quotes or directly references GDD Section 4 (Formulas), the Player Fantasy section and the "curiosity is always rewarded" pillar
- [ ] States the fix as a creative constraint (e.g., decay must not punish roaming) and leaves the formula to `game-designer`, its delegate for mechanical design — does not author replacement formula values
### Case 4: Conflict escalation — correct parent
**Scenario:** technical-director raises a concern that the core loop mechanic (real-time branching conversations) is prohibitively expensive to implement and recommends cutting it. creative-director disagrees on creative grounds.
@@ -57,7 +56,7 @@ Verified by reading the agent's `.claude/agents/creative-director.md` frontmatte
- [ ] Does not claim to own implementation decisions
### Case 5: Context pass — uses provided context
**Scenario:** Agent receives a gate context block that includes the game pillars document (`design/gdd/pillars.md`) and a new mechanic spec for review. The pillars document defines "player authorship," "consequence permanence," and "world responsiveness" as the three core pillars.
**Scenario:** Agent receives a gate context block that includes the game pillars document (`design/gdd/game-pillars.md`) and a new system GDD for review. The pillars document defines "player authorship," "consequence permanence," and "world responsiveness" as the three core pillars. Request is tagged CD-GDD-ALIGN.
**Expected:** Assessment uses the exact pillar vocabulary from the provided document, not generic creative heuristics. Any approval or concern is tied back to one or more of the three named pillars.
**Assertions:**
- [ ] Uses the exact pillar names from the provided context document
@@ -65,20 +64,29 @@ Verified by reading the agent's `.claude/agents/creative-director.md` frontmatte
- [ ] References the specific pillar(s) most relevant to the mechanic under review
- [ ] Does not reference pillars not present in the provided document
### Case 6: Missing gate input — NOT ASSESSED
**Scenario:** A complete, internally consistent system GDD is submitted with its Player Fantasy section, but no game pillars: the context gives none, and none of `design/gdd/game-concept.md`, `design/gdd/game-pillars.md` or `design/game-brief.md` exists. Request is tagged CD-GDD-ALIGN.
**Expected:** Returns `CD-GDD-ALIGN: NOT ASSESSED`, naming the game pillars as the input it could not read. Alignment with pillars nobody supplied cannot be judged, so no alignment verdict is given.
**Assertions:**
- [ ] Verdict token is `CD-GDD-ALIGN: NOT ASSESSED` — not APPROVE, although nothing in the GDD itself looks wrong
- [ ] Names the game pillars as the missing input
- [ ] Does not infer pillars from the GDD under review and judge alignment against them
---
## Protocol Compliance
- [ ] Returns verdicts using APPROVE / CONCERNS / REJECT vocabulary only
- [ ] Returns the verdict vocabulary the invoked gate's definition file lists — APPROVE / CONCERNS / REJECT for CD-PILLARS, CD-GDD-ALIGN, CD-SYSTEMS, CD-NARRATIVE and CD-PLAYTEST; READY / CONCERNS / NOT READY for CD-PHASE-GATE; `NOT ASSESSED`, naming the input, at any gate when an input the gate names is missing
- [ ] Stays within declared creative domain
- [ ] Escalates conflicts by presenting trade-offs to user rather than unilateral override
- [ ] Uses gate IDs in output (e.g., `CD-PILLARS: APPROVE`) not inline prose verdicts
- [ ] Does not make binding cross-domain decisions (technical, production, art execution)
- [ ] At a phase gate, treats an artifact the target phase requires that the calling skill passes as "none" as a finding (NOT READY or CONCERNS), and one passed as "not expected before [phase]" or "not required at `workflow: [tier]`" as no finding — it judges readiness for the phase being entered, not a later one
---
## Coverage Notes
- Multi-gate scenario (e.g., single submission triggering both CD-PILLARS and CD-GDD-ALIGN) is not covered here — deferred to integration tests.
- CD-PHASE-GATE (full phase advancement) involves synthesizing multiple sub-gate results; this complex case is deferred.
- Playtest report interpretation (CD-PLAYTEST) is not covered — a dedicated case should be added when the playtest-report skill produces structured output.
- CD-PHASE-GATE (the creative director's own readiness review, which `/gate-check` runs at `workflow: full`) has no case yet.
- CD-PLAYTEST (review of a `/playtest-report` report) has no case yet.
- Interaction with art-director on visual-pillar alignment is not covered.
@@ -3,7 +3,6 @@
## Agent Summary
**Domain owned:** Scope management, sprint planning validation, milestone tracking, epic prioritization, production phase gate.
**Does NOT own:** Game design decisions (creative-director / game-designer), technical architecture (technical-director), creative direction.
**Model tier:** Opus (multi-document synthesis, high-stakes phase gate verdicts).
**Gate IDs handled:** PR-SCOPE, PR-SPRINT, PR-MILESTONE, PR-EPIC, PR-PHASE-GATE.
---
@@ -13,8 +12,8 @@
Verified by reading the agent's `.claude/agents/producer.md` frontmatter:
- [ ] `description:` field is present and domain-specific (references scope, sprint, milestone, production — not generic)
- [ ] `allowed-tools:` list is primarily read-focused; Bash only if sprint/milestone files require parsing
- [ ] Model tier is `claude-opus-4-8` per coordination-rules.md (directors with gate synthesis = Opus)
- [ ] `tools:` includes Write and Edit (it authors sprint plans per its Output Format and maintains the risk register) and Bash only because a preloaded skill needs it (`skills:` includes `scope-check`, which reads `git log`)
- [ ] Model tier is `opus` — frontmatter `model:` reads exactly `opus` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over design decisions or technical architecture
---
@@ -22,12 +21,12 @@ Verified by reading the agent's `.claude/agents/producer.md` frontmatter:
## Test Cases
### Case 1: In-domain request — appropriate output format
**Scenario:** A sprint plan is submitted for Sprint 7. The plan includes 12 story points across 4 team members over 2 weeks. Historical velocity from the last 3 sprints averages 11.5 points. Request is tagged PR-SPRINT.
**Expected:** Returns `PR-SPRINT: REALISTIC` with rationale noting the plan is within one standard deviation of historical velocity and capacity appears matched.
**Scenario:** A sprint plan is submitted for Sprint 7. The plan commits 9 story points across 4 team members over 2 weeks, with dependencies listed and no story larger than 3 days. Historical velocity from the last 3 sprints averages 11.5 points; no backlog debt is carried in, and the milestone constraints add nothing to this sprint. Request is tagged PR-SPRINT.
**Expected:** Returns `PR-SPRINT: REALISTIC` with rationale noting the load sits below historical velocity while keeping the 20% buffer its Sprint Planning Rules require (9 ≤ 80% of 11.5).
**Assertions:**
- [ ] Verdict is exactly one of REALISTIC / CONCERNS / UNREALISTIC
- [ ] Verdict token is formatted as `PR-SPRINT: REALISTIC`
- [ ] Rationale references the specific story point count and historical velocity figures
- [ ] Rationale compares the 9 committed points with the 11.5-point velocity and the 20% buffer rule — not a generic "looks achievable"
- [ ] Output stays within production scope — does not comment on whether the stories are well-designed or technically sound
### Case 2: Out-of-domain request — redirects or escalates
@@ -36,49 +35,68 @@ Verified by reading the agent's `.claude/agents/producer.md` frontmatter:
**Assertions:**
- [ ] Does not make any binding assessment of the mechanic's design quality
- [ ] Explicitly names `game-designer` or `creative-director` as the correct handler
- [ ] May note if the mechanic's scope has production implications (e.g., dependencies on other systems), but defers all design evaluation
- [ ] Any comment it makes is about production implications only (e.g., which other systems the mechanic depends on) — never whether the mechanic is fun, engaging or well designed
### Case 3: Gate verdict — correct vocabulary
**Scenario:** A new feature proposal adds three new systems (crafting, weather, and faction reputation) to a milestone that was scoped for two systems only. None of these additions appear in the current milestone plan. Request is tagged PR-SCOPE.
**Expected:** Returns `PR-SCOPE: CONCERNS` with specific identification of the three unplanned systems and their absence from the milestone scope document.
**Scenario:** A scope estimate is submitted for a solo developer with a 4-month timeline. The MVP was two systems (movement and combat), estimated at 3 months. The revised MVP adds three more — crafting, weather, and faction reputation — bringing the estimate to exactly 4 months: the whole timeline, with no buffer left for unplanned work. Each of the three could move to the next scope tier without breaking the MVP. Request is tagged PR-SCOPE.
**Expected:** Returns `PR-SCOPE: OPTIMISTIC` — the gate's middle verdict, with specific adjustments — because the MVP fits only if nothing goes wrong: names the three added systems and recommends which to move to a later scope tier to restore a buffer. Not UNREALISTIC: the estimate does not exceed the timeline, so neither has to be revised.
**Assertions:**
- [ ] Verdict is exactly one of REALISTIC / CONCERNS / UNREALISTIC — not freeform text
- [ ] Verdict token is formatted as `PR-SCOPE: CONCERNS`
- [ ] Rationale names the three specific systems being added out of scope
- [ ] Verdict is exactly one of REALISTIC / OPTIMISTIC / UNREALISTIC (the PR-SCOPE verdicts) — not CONCERNS and not freeform text
- [ ] Verdict token is formatted as `PR-SCOPE: OPTIMISTIC`
- [ ] Rationale names the three specific systems that use up the buffer
- [ ] Does not evaluate whether the systems are good design — only whether they fit the plan
### Case 4: Conflict escalation — correct parent
**Scenario:** game-designer wants to add a late-breaking mechanic (dynamic weather affecting all gameplay systems) that technical-director warns will require 3 additional sprints. game-designer and technical-director are in disagreement about whether to proceed.
**Expected:** Producer does not take a side on whether the mechanic is worth adding (design decision) or feasible (technical decision). Producer quantifies the production impact (3 sprints of delay, milestone slip risk), presents the trade-off to the user, and follows coordination-rules.md conflict resolution: escalate to the shared parent (in this case, surface the conflict for user decision since creative-director and technical-director are both top-tier).
**Expected:** Producer does not take a side on whether the mechanic is worth adding (design decision) or feasible (technical decision). Producer quantifies the production impact (3 sprints of delay, milestone slip risk), presents the trade-off to the user, and follows coordination-rules.md rule 3: game-designer and technical-director share no parent, and whether the mechanic is worth its cost is a design conflict, so it goes to creative-director, the arbiter of scope questions where creative intent and production capacity collide.
**Assertions:**
- [ ] Quantifies the production impact in concrete terms (sprint count, milestone date slip)
- [ ] Does not make a binding design or technical decision
- [ ] Surfaces the conflict to the user with the scope implications clearly stated
- [ ] References coordination-rules.md conflict resolution protocol (escalate to shared parent or user)
- [ ] Escalates the conflict to `creative-director` per coordination-rules.md rule 3 (no shared parent; a design conflict) — not to technical-director, and not straight to the user as if no escalation target existed
### Case 5: Context pass — uses provided context
**Scenario:** Agent receives a gate context block that includes the current milestone deadline (8 weeks away) and velocity data from the last 4 sprints (8, 10, 9, 11 points). A sprint plan is submitted with 14 story points.
**Expected:** Assessment uses the provided velocity data to project whether 14 points is achievable, and references the 8-week milestone window to assess whether the current sprint's scope leaves adequate buffer.
**Scenario:** Agent receives a gate context block that includes the current milestone deadline (8 weeks away, two-week sprints) and velocity data from the last 4 sprints (8, 10, 9, 11 points). A sprint plan is submitted with 14 story points in five stories: Player movement (3), Jump buffering (2, depends on Player movement), Enemy patrol AI (5), Pause menu (2) and Save slots (2). Request is tagged PR-SPRINT.
**Expected:** Assessment uses the provided velocity data to show 14 points is well over the ~9.5-point average (and further over it once the 20% buffer is kept), returns `PR-SPRINT: UNREALISTIC` naming stories to defer, and references the 8-week milestone window to assess what the overrun does to the milestone.
**Assertions:**
- [ ] Uses the specific velocity figures from the provided context (not generic estimates)
- [ ] References the 8-week deadline in the capacity assessment
- [ ] Calculates or estimates remaining sprint count within the milestone window
- [ ] Calculates or estimates remaining sprint count within the milestone window (four two-week sprints), as its duty to flag milestone risk at least 2 sprints ahead requires
- [ ] Names the stories to defer from the five supplied, by title, and never keeps Jump buffering while deferring Player movement, which it depends on
- [ ] Does not give generic scope advice disconnected from the supplied deadline and velocity data
### Case 6: Missing gate input — NOT ASSESSED
**Scenario:** A sprint plan is submitted with five stories — titles, estimates and dependencies, correctly ordered — and the milestone constraints, but no team capacity: the context gives none, and `production/sprints/` holds no earlier sprint to derive a velocity from. Request is tagged PR-SPRINT.
**Expected:** Returns `PR-SPRINT: NOT ASSESSED`, naming team capacity as the input it could not read. Whether a story load is realistic depends on the capacity it is measured against, so no feasibility verdict is given.
**Assertions:**
- [ ] Verdict token is `PR-SPRINT: NOT ASSESSED` — not REALISTIC, and not UNREALISTIC by assumption
- [ ] Names team capacity as the missing input
- [ ] Does not invent a capacity or velocity figure to judge the load against
### Case 7: Phase gate at `minimal` — the brief's Build order is the plan
**Scenario:** `/gate-check production` at `workflow: minimal` runs the panel with `review_mode: lean` set explicitly, so the producer is spawned alone for PR-PHASE-GATE. The context gives the target phase (Production), the tier, and the gate's required artifacts at that tier: a filled `design/game-brief.md` with its Build order, and stories under `production/epics/`. Both are present — the Build order lists four MVP features, the first three independent and the fourth depending on the first, and there is one story per feature in that order, none Blocked. `team.size` is `individual`; the brief states a six-week target for the MVP. The sprint plan and sprint capacity are passed as "not required at `workflow: minimal`".
**Expected:** Returns `PR-PHASE-GATE: READY` — the Build order is the plan at this tier, its dependency is ordered, and four stories fit a solo developer's six weeks. The absent sprint plan and velocity are not findings.
**Assertions:**
- [ ] Verdict is exactly one of READY / CONCERNS / NOT READY (the PR-PHASE-GATE verdicts), formatted as `PR-PHASE-GATE: READY`
- [ ] Judges the Build order as the plan, and checks its dependency order (the fourth feature after the first)
- [ ] Does not raise the missing sprint plan or velocity as a concern, and does not answer NOT ASSESSED for them — they were passed as "not required at `workflow: minimal`"
- [ ] Does not invent a sprint capacity to judge the load against
---
## Protocol Compliance
- [ ] Returns verdicts using REALISTIC / CONCERNS / UNREALISTIC vocabulary only
- [ ] Returns the verdict vocabulary the invoked gate's definition file lists — REALISTIC / CONCERNS / UNREALISTIC for PR-SPRINT and PR-EPIC; REALISTIC / OPTIMISTIC / UNREALISTIC for PR-SCOPE; ON TRACK / AT RISK / OFF TRACK for PR-MILESTONE; READY / CONCERNS / NOT READY for PR-PHASE-GATE; `NOT ASSESSED`, naming the input, at any gate when an input the gate names is missing
- [ ] Stays within declared production domain
- [ ] Escalates design/technical conflicts by quantifying scope impact and presenting to user
- [ ] Uses gate IDs in output (e.g., `PR-SPRINT: REALISTIC`) not inline prose verdicts
- [ ] Does not make binding game design or technical architecture decisions
- [ ] At a phase gate, treats an artifact the target phase requires that the calling skill passes as "none" as a finding (NOT READY or CONCERNS), and one passed as "not expected before [phase]" or "not required at `workflow: [tier]`" as no finding — it judges readiness for the phase being entered, not a later one
---
## Coverage Notes
- PR-EPIC (epic-level prioritization) is not covered — a dedicated case should be added when the /create-epics skill produces structured epic documents.
- PR-EPIC (the epic-structure review `/create-epics` runs before it writes any epic) has no case yet.
- PR-MILESTONE (milestone health review) is not covered — deferred to integration with /milestone-review skill.
- PR-PHASE-GATE (full production phase advancement) involving synthesis of multiple sub-gate results is deferred.
- PR-PHASE-GATE is covered at `minimal` (Case 7); a `standard`/`full` Production gate judged against a sprint plan has no case yet.
- Multi-sprint burn-down and velocity trend analysis are not covered here.
@@ -3,8 +3,7 @@
## Agent Summary
**Domain owned:** System architecture decisions, technical feasibility assessment, ADR oversight and approval, engine risk evaluation, technical phase gate.
**Does NOT own:** Game design decisions (creative-director / game-designer), creative direction, visual art style, production scheduling (producer).
**Model tier:** Opus (multi-document synthesis, high-stakes architecture and phase gate verdicts).
**Gate IDs handled:** TD-SYSTEM-BOUNDARY, TD-FEASIBILITY, TD-ARCHITECTURE, TD-ADR, TD-ENGINE-RISK, TD-PHASE-GATE.
**Gate IDs handled:** TD-SYSTEM-BOUNDARY, TD-FEASIBILITY, TD-ARCHITECTURE, TD-ADR, TD-ENGINE-RISK, TD-MANIFEST, TD-CHANGE-IMPACT, TD-PHASE-GATE.
---
@@ -13,8 +12,8 @@
Verified by reading the agent's `.claude/agents/technical-director.md` frontmatter:
- [ ] `description:` field is present and domain-specific (references architecture, feasibility, ADR — not generic)
- [ ] `allowed-tools:` list may include Read for architecture documents; Bash only if required for technical checks
- [ ] Model tier is `claude-opus-4-8` per coordination-rules.md (directors with gate synthesis = Opus)
- [ ] `tools:` reads Read, Glob, Grep, Write, Edit, Bash, WebSearch
- [ ] Model tier is `opus` — frontmatter `model:` reads exactly `opus` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over game design decisions or creative direction
---
@@ -22,63 +21,82 @@ Verified by reading the agent's `.claude/agents/technical-director.md` frontmatt
## Test Cases
### Case 1: In-domain request — appropriate output format
**Scenario:** An architecture document for the "Combat System" is submitted. It describes a layered design: input layer → game logic layer → presentation layer, with clearly defined interfaces between each. Request is tagged TD-ARCHITECTURE.
**Expected:** Returns `TD-ARCHITECTURE: APPROVE` with rationale confirming that system boundaries are correctly separated and interfaces are well-defined.
**Scenario:** The master architecture document is submitted for sign-off with its context: every TR-ID in the technical requirements baseline maps to an ADR, the Foundation-layer ADRs are Accepted, and the one HIGH risk engine domain is flagged as an open question. Its "Combat System" section describes a layered design — input layer → game logic layer → presentation layer — with clearly defined interfaces between each. Request is tagged TD-ARCHITECTURE.
**Expected:** Returns `TD-ARCHITECTURE: APPROVE` with rationale confirming the gate's checks against the document: requirement coverage, engine risk handled, and clean, minimal API boundaries between the layers.
**Assertions:**
- [ ] Verdict is exactly one of APPROVE / CONCERNS / REJECT
- [ ] Verdict token is formatted as `TD-ARCHITECTURE: APPROVE`
- [ ] Rationale specifically references the layered structure and interface definitions — not generic architecture advice
- [ ] Rationale specifically references the layered structure and its interface definitions as the API-boundary check — not generic architecture advice
- [ ] Output stays within technical scope — does not comment on whether the mechanic is fun or fits the creative vision
### Case 2: Out-of-domain request — redirects or escalates
**Scenario:** Writer asks technical-director to review and approve the dialogue scripts for the game's opening cutscene.
**Expected:** Agent declines to evaluate dialogue quality and redirects to narrative-director.
**Expected:** Agent declines to evaluate dialogue quality and redirects the content decision to narrative-director, who owns dialogue direction and to whom the writer reports; creative-director remains the escalation target for creative decisions.
**Assertions:**
- [ ] Does not make any binding decision about the dialogue content or structure
- [ ] Explicitly names `narrative-director` as the correct handler
- [ ] May note technical constraints that affect dialogue (e.g., localization string limits, data format), but defers all content decisions
- [ ] Explicitly names `narrative-director` as the owner of the dialogue content — creative-director delegates dialogue to it, and coordination-rules.md rule 1 forbids skipping a tier; naming `creative-director` as the escalation target as well is fine
- [ ] Comments only on technical constraints that affect dialogue (e.g., localization string limits, data format) — no judgement of the lines' quality, tone or wording
### Case 3: Gate verdict — correct vocabulary
**Scenario:** A proposed multiplayer mechanic requires raycasting against all active entities every frame to detect line-of-sight. At expected player counts (1000 entities in a large zone), this is O(n²) per frame. Request is tagged TD-FEASIBILITY.
**Expected:** Returns `TD-FEASIBILITY: CONCERNS` with specific citation of the O(n²) complexity and the entity count that makes this infeasible at target framerate.
**Scenario:** A concept's identified technical risks (platform: PC; engine: Godot 4.6) include a multiplayer mechanic that raycasts from every active entity against every other entity each frame to detect line-of-sight. At expected counts (1000 entities in a large zone), this is O(n²) — about a million raycasts per frame. The mechanic itself can survive with a different implementation. Request is tagged TD-FEASIBILITY.
**Expected:** Returns `TD-FEASIBILITY: CONCERNS` — the gate's middle verdict, a list with mitigation suggestions — citing the O(n²) complexity and the entity count that breaks the frame budget as implemented. Not HIGH RISK, because the concept does not need revising.
**Assertions:**
- [ ] Verdict is exactly one of APPROVE / CONCERNS / REJECT — not freeform text
- [ ] Verdict is exactly one of VIABLE / CONCERNS / HIGH RISK (the TD-FEASIBILITY verdicts) — not APPROVE / REJECT and not freeform text
- [ ] Verdict token is formatted as `TD-FEASIBILITY: CONCERNS`
- [ ] Rationale includes the specific algorithmic complexity concern and the entity count threshold
- [ ] Suggests at least one alternative approach (e.g., spatial partitioning, interest management) without mandating which to choose
- [ ] Suggests at least one mitigation (e.g., spatial partitioning, interest management) without mandating which to choose
### Case 4: Conflict escalation — correct parent
**Scenario:** game-designer wants to add a real-time physics simulation for every inventory item (hundreds of items on screen simultaneously). technical-director assesses this as technically expensive and proposes simplifying the simulation. game-designer disagrees, arguing it is essential to the game feel.
**Expected:** technical-director clearly states the technical cost and constraints, proposes alternative implementation approaches that could achieve a similar feel, but explicitly defers the final design priority decision to creative-director as the arbiter of player experience trade-offs.
**Expected:** technical-director clearly states the technical cost and constraints, proposes alternative implementation approaches that could achieve a similar feel, but explicitly defers the design priority decision to creative-director as the arbiter of player experience trade-offs, with the user making the final call.
**Assertions:**
- [ ] Expresses the technical concern with specifics (e.g., performance budget, estimated cost)
- [ ] Proposes at least one alternative that could reduce cost while preserving intent
- [ ] Explicitly defers the "is this worth the cost" decision to creative-director — does not unilaterally cut the feature
- [ ] Explicitly defers the "is this worth the cost" decision to `creative-director` (its escalation target for design decisions; coordination-rules.md rule 3 for a design conflict with no shared parent), leaving the final call to the user — does not unilaterally cut the feature
- [ ] Does not claim authority to override game-designer's design intent
### Case 5: Context pass — uses provided context
**Scenario:** Agent receives a gate context block that includes the target platform constraints: mobile, 60fps target, 2GB RAM ceiling, no compute shaders. A proposed architecture includes a GPU-driven rendering pipeline.
**Expected:** Assessment references the specific hardware constraints from the context, identifies the compute shader dependency as incompatible with the stated platform constraints, and returns a CONCERNS or REJECT verdict with those specifics cited.
**Scenario:** An ADR proposing a GPU-driven rendering pipeline — culling and draw submission on compute shaders — is submitted before it is Accepted, with the engine version and its related ADRs. The gate context block adds the target platform constraints: mobile, 60fps target, 2GB RAM ceiling, no compute shaders. The ADR never mentions the platform. Request is tagged TD-ADR.
**Expected:** Assessment references the specific hardware constraints from the context, identifies the compute shader dependency as incompatible with the stated platform constraints, and returns `TD-ADR: REJECT` — the decision rests on a capability the target platform does not have, an unsound technical assumption — with those specifics cited.
**Assertions:**
- [ ] References the specific platform constraints provided (mobile, 2GB RAM, no compute shaders)
- [ ] Does not give generic performance advice disconnected from the supplied constraints
- [ ] Correctly identifies the architectural component that conflicts with the platform constraint
- [ ] Verdict includes rationale tied to the provided context, not boilerplate warnings
- [ ] Verdict token is `TD-ADR: REJECT`, with rationale tied to the provided context, not boilerplate warnings
### Case 6: Missing gate input — NOT ASSESSED
**Scenario:** The master architecture document is submitted for sign-off with its ADR list (Foundation-layer ADRs Accepted) and the engine knowledge gap inventory; its layers and interfaces are sound. The technical requirements baseline the gate names is missing: the context gives none, and `docs/architecture/tr-registry.yaml` does not exist. Request is tagged TD-ARCHITECTURE.
**Expected:** Returns `TD-ARCHITECTURE: NOT ASSESSED`, naming the technical requirements baseline as the input it could not read — without it, the gate's first check (is every requirement covered by an architectural decision?) cannot be made.
**Assertions:**
- [ ] Verdict token is `TD-ARCHITECTURE: NOT ASSESSED` — not APPROVE, although every part of the document it could check is sound
- [ ] Names the technical requirements baseline as the missing input
- [ ] Does not reconstruct a requirement list from the architecture document itself and judge coverage against it
### Case 7: Phase gate — judged against the phase being entered
**Scenario:** `/gate-check technical-setup` at `workflow: standard` spawns TD-PHASE-GATE. The context gives the target phase (Technical Setup), the tier, and the gate's required and recommended artifacts at that tier: a systems index enumerating the MVP systems, each MVP GDD at the 5 standard sections and reviewed, and — recommended — a cross-GDD review report. All are present; the systems index gives each system's dependencies and data flow both ways. The engine reference path is `docs/engine-reference/godot/VERSION.md`. The architecture document and the ADR list are passed as "not expected before Pre-Production".
**Expected:** Returns `TD-PHASE-GATE: READY` — the systems and GDDs give enough to architect from, which is what entering Technical Setup requires. The absent architecture document and ADRs are the work of the phase being entered, not a gap in it.
**Variant:** the same project at target Pre-Production, where the architecture document is required and is passed as "none" → `TD-PHASE-GATE: NOT READY` or `CONCERNS`, naming the missing architecture document.
**Assertions:**
- [ ] Verdict is exactly one of READY / CONCERNS / NOT READY (the TD-PHASE-GATE verdicts), formatted as `TD-PHASE-GATE: READY`
- [ ] Does not list the architecture document or the ADRs as a blocker or concern when they are passed as "not expected before Pre-Production"
- [ ] Does not answer NOT ASSESSED for them — an artifact passed as not expected yet is neither a finding nor a missing input
- [ ] Variant: an artifact the target phase requires, passed as "none", is a finding (NOT READY or CONCERNS) — not NOT ASSESSED
---
## Protocol Compliance
- [ ] Returns verdicts using APPROVE / CONCERNS / REJECT vocabulary only
- [ ] Returns the verdict vocabulary the invoked gate's definition file lists — APPROVE / CONCERNS / REJECT for TD-ARCHITECTURE, TD-ADR, TD-SYSTEM-BOUNDARY, TD-ENGINE-RISK, TD-MANIFEST and TD-CHANGE-IMPACT; VIABLE / CONCERNS / HIGH RISK for TD-FEASIBILITY; READY / CONCERNS / NOT READY for TD-PHASE-GATE; `NOT ASSESSED`, naming the input, at any gate when an input the gate names is missing
- [ ] Stays within declared technical domain
- [ ] Defers design priority conflicts to creative-director
- [ ] Uses gate IDs in output (e.g., `TD-FEASIBILITY: CONCERNS`) not inline prose verdicts
- [ ] Does not make binding game design or creative direction decisions
- [ ] At a phase gate, treats an artifact the target phase requires that the calling skill passes as "none" as a finding (NOT READY or CONCERNS), and one passed as "not expected before [phase]" or "not required at `workflow: [tier]`" as no finding — it judges readiness for the phase being entered, not a later one
---
## Coverage Notes
- TD-ADR (Architecture Decision Record approval) is not covered — a dedicated case should be added when the /architecture-decision skill produces ADR documents.
- TD-ADR is covered only for a platform conflict (Case 5); an ADR with missing sections or unflagged post-cutoff APIs has no case yet.
- TD-ENGINE-RISK assessment for specific engine versions (e.g., Godot 4.6 post-cutoff APIs) is not covered — deferred to engine-specialist integration tests.
- TD-PHASE-GATE (full technical phase advancement) involving synthesis of multiple sub-gate results is deferred.
- TD-PHASE-GATE is covered at one target phase (Case 7); its later-phase judgements (Production and on: is the architecture holding up in the build?) have no case yet.
- Multi-domain architecture reviews (e.g., touching both TD-ARCHITECTURE and TD-ENGINE-RISK simultaneously) are not covered here.
@@ -3,7 +3,6 @@
## Agent Summary
Domain: C# patterns in Godot 4, .NET idioms applied to Godot, [Export] attribute usage, signal delegates, and async/await patterns.
Does NOT own: GDScript code (gdscript-specialist), GDExtension C/C++ bindings (gdextension-specialist).
Model tier: Sonnet (default).
No gate IDs assigned.
---
@@ -11,8 +10,8 @@ No gate IDs assigned.
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references C# in Godot 4 / .NET patterns / signal delegates)
- [ ] `allowed-tools:` list includes Read, Write, Edit, Bash, Glob, Grep
- [ ] Model tier is Sonnet (default for specialists)
- [ ] `tools:` list includes Read, Write, Edit, Bash, Glob, Grep
- [ ] Model tier is `sonnet` — frontmatter `model:` reads exactly `sonnet` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over GDScript or GDExtension code
---
@@ -34,7 +33,7 @@ No gate IDs assigned.
- Does NOT produce GDScript code
- Explicitly states that GDScript authoring belongs to `godot-gdscript-specialist`
- Redirects the request to `godot-gdscript-specialist`
- May note that the C# interface can be described so the gdscript-specialist knows the expected API shape
- Any hand-off it offers describes the existing C# system's API (its signals and public methods) for godot-gdscript-specialist to port — it contains no GDScript
### Case 3: Async signal awaiting
**Input:** "Wait for an animation to finish before transitioning game state using C# async."
@@ -43,7 +42,8 @@ No gate IDs assigned.
- Uses `await ToSignal(animationPlayer, AnimationPlayer.SignalName.AnimationFinished)`
- Does NOT use `Thread.Sleep()` or `Task.Delay()` as a polling substitute
- Notes that the calling method must be `async` and that fire-and-forget `async void` is only acceptable for event handlers
- Handles cancellation or timeout if the animation could fail to fire
- Checks `IsInstanceValid(this)` after the `await` before transitioning state — the node may have been freed while waiting
- If the animation might never finish (interrupted, replaced), raises that as an unspecified edge case for the user to decide; any timeout it adds uses `GetTree().CreateTimer()`, never `Task.Delay()`
### Case 4: Threading model conflict
**Input:** "This C# code accesses a Godot Node from a background Task thread to update its position."
@@ -51,7 +51,7 @@ No gate IDs assigned.
- Flags this as a race condition risk: Godot nodes are not thread-safe and must only be accessed from the main thread
- Does NOT approve or implement the multi-threaded node access pattern
- Provides the correct pattern: use `CallDeferred()`, `Callable.From().CallDeferred()`, or marshal back to the main thread via a thread-safe queue
- Explains the distinction between Godot's main thread requirement and .NET's thread-agnostic types
- Explains why the code compiles yet is unsafe: the `Task` body runs on a .NET thread-pool thread and nothing in C# stops it touching a Node — the main-thread rule belongs to Godot's scene tree
### Case 5: Context pass — Godot 4.6 API correctness
**Input:** Engine version context: Godot 4.6. Request: "Connect a signal using the new typed signal delegate pattern."
@@ -72,6 +72,7 @@ No gate IDs assigned.
- [ ] Flags multi-threaded Godot node access as unsafe and provides the correct pattern
- [ ] Uses typed signal delegates — not deprecated string-based Connect() calls
- [ ] Checks engine version reference for API changes before producing code
- [ ] Asks "May I write this to [filepath]?" naming the file before writing
---
@@ -3,7 +3,6 @@
## Agent Summary
Domain: GDExtension API, godot-cpp C++ bindings, godot-rust bindings, native library integration, and native performance optimization.
Does NOT own: GDScript code (gdscript-specialist), shader code (godot-shader-specialist).
Model tier: Sonnet (default).
No gate IDs assigned.
---
@@ -11,8 +10,8 @@ No gate IDs assigned.
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references GDExtension / godot-cpp / native bindings)
- [ ] `allowed-tools:` list includes Read, Write, Edit, Bash, Glob, Grep
- [ ] Model tier is Sonnet (default for specialists)
- [ ] `tools:` list includes Read, Write, Edit, Bash, Glob, Grep
- [ ] Model tier is `sonnet` — frontmatter `model:` reads exactly `sonnet` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over GDScript or shader authoring
---
@@ -26,7 +25,7 @@ No gate IDs assigned.
- Class inheriting from `godot::Object` or an appropriate Godot base class
- `GDCLASS` macro registration
- `_bind_methods()` implementation exposing the physics API to GDScript
- `GDExtension` entry point (`gdextension_init`) setup
- Module entry point: `initialize_module` in `register_types.cpp` registers the class with `ClassDB::register_class<T>()` at `MODULE_INITIALIZATION_LEVEL_SCENE`, reached from the exported init function named by the manifest's `entry_symbol`
- Notes the `.gdextension` manifest file format required
- Does NOT produce the GDScript usage code (that belongs to gdscript-specialist)
@@ -36,16 +35,16 @@ No gate IDs assigned.
- Does NOT produce GDScript code
- Explicitly states that GDScript authoring belongs to `godot-gdscript-specialist`
- Redirects to `godot-gdscript-specialist`
- May describe the API surface the GDScript should call (method names, parameter types) as a handoff spec
- Any hand-off it offers is the extension's bound API surface (method names, parameter and return types) — not GDScript that calls it
### Case 3: ABI compatibility risk — minor version update
**Input:** "We're upgrading from Godot 4.5 to 4.6. Will our existing GDExtension still work?"
**Expected behavior:**
- Flags the ABI compatibility concern: GDExtension binaries may not be ABI-compatible across minor versions
- States the compatibility direction: an extension built for 4.5 should load in 4.6, but not the reverse — so it may keep working, yet it must be re-tested, and rebuilt against 4.6 to use newer APIs
- Directs to check the 4.5→4.6 migration guide for GDExtension API changes
- Recommends recompiling the extension against the 4.6 godot-cpp headers rather than assuming binary compatibility
- Recommends rebuilding against the 4.6 godot-cpp headers rather than treating "should load" as tested
- Notes that the `.gdextension` manifest may need a `compatibility_minimum` version update
- Provides the recompilation checklist
- Lays out the rebuild as a checklist: rebuild debug and release (`scons ... target=template_debug` / `template_release`, or `cargo build` / `cargo build --release`) for every target platform, update `compatibility_minimum`, then re-test in the 4.6 editor before shipping
### Case 4: Memory management — RAII for Godot objects
**Input:** "How should we manage the lifecycle of Godot objects created inside C++ GDExtension code?"
@@ -55,14 +54,14 @@ No gate IDs assigned.
- `memnew()` / `memdelete()` for non-reference-counted objects
- Warning: do NOT use `new`/`delete` for Godot objects — undefined behavior
- Notes object ownership rules: who is responsible for freeing a node added to the scene tree
- Provides a concrete example managing a `CollisionShape3D` created in C++
- Its concrete example (e.g., a `CollisionShape3D` created in C++) applies both rules: the node is created with `memnew()` and handed to the scene tree with `add_child()`, after which the tree frees it (no `memdelete()`); its shape resource is held in a `Ref<>`; `memdelete()` is only for a node that never enters the tree
### Case 5: Context pass — Godot 4.6 GDExtension API check
**Input:** Engine version context: Godot 4.6 (upgrading from 4.5). Request: "Check if any GDExtension APIs changed from 4.5 to 4.6."
**Expected behavior:**
- References the 4.5→4.6 migration guide from the VERSION.md verified sources list
- Reports on any documented GDExtension API changes in the 4.6 release
- If no breaking changes are documented for GDExtension in 4.6, states that explicitly with the caveat to verify against the official changelog
- Reads the 4.5 → 4.6 table in `docs/engine-reference/godot/breaking-changes.md` and states explicitly that it has no GDExtension-specific row, with the caveat to verify against the official changelog
- Still surfaces the listed 4.6 changes that reach native code: `Quaternion` now initializes to identity (it was zero)
- Flags the D3D12 default on Windows (4.6 change) as potentially relevant for GDExtension rendering code
- Provides a checklist of what to verify after upgrading
@@ -74,9 +73,10 @@ No gate IDs assigned.
- [ ] Redirects GDScript authoring to godot-gdscript-specialist
- [ ] Redirects shader authoring to godot-shader-specialist
- [ ] Returns structured output (binding patterns, RAII examples, ABI checklists)
- [ ] Flags ABI compatibility risks on minor version upgrades — never assumes binary compatibility
- [ ] States that compatibility runs forward only (older build → newer Godot) and requires a re-test after an upgrade — never treats "should load" as tested
- [ ] Uses Godot-specific memory management (`memnew`/`memdelete`, `Ref<T>`) not raw C++ new/delete
- [ ] Checks engine version reference for GDExtension API changes before confirming compatibility
- [ ] Asks "May I write this to [filepath]?" naming the file before writing
---
@@ -3,7 +3,6 @@
## Agent Summary
Domain: GDScript static typing, design patterns in GDScript, signal architecture, coroutine/await patterns, and GDScript performance.
Does NOT own: shader code (godot-shader-specialist), GDExtension bindings (godot-gdextension-specialist).
Model tier: Sonnet (default).
No gate IDs assigned.
---
@@ -11,8 +10,8 @@ No gate IDs assigned.
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references GDScript / static typing / signals / coroutines)
- [ ] `allowed-tools:` list includes Read, Write, Edit, Bash, Glob, Grep
- [ ] Model tier is Sonnet (default for specialists)
- [ ] `tools:` list includes Read, Write, Edit, Bash, Glob, Grep
- [ ] Model tier is `sonnet` — frontmatter `model:` reads exactly `sonnet` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over shader code or GDExtension
---
@@ -34,33 +33,34 @@ No gate IDs assigned.
- Does NOT produce shader code in GDScript or in Godot's shading language
- Explicitly states that shader authoring belongs to `godot-shader-specialist`
- Redirects the request to `godot-shader-specialist`
- May note that the GDScript side (passing uniforms to a shader, setting shader parameters) is within its domain
- Any help it offers stays on the script side its redirect line says it owns (`set_shader_parameter()`, material assignment) — it writes no shader code
### Case 3: Async loading with coroutines
**Input:** "Load a scene asynchronously and wait for it to finish before spawning it."
**Expected behavior:**
- Produces an `await` + `ResourceLoader.load_threaded_request` pattern for Godot 4
- Uses static typing throughout (`var scene: PackedScene`)
- Handles the completion check with `ResourceLoader.load_threaded_get_status()`
- Handles the completion check with `ResourceLoader.load_threaded_get_status()`, awaiting between polls rather than blocking the frame
- Checks `is_instance_valid(self)` after the await before spawning — the node may have been freed while the scene loaded
- Notes error handling for failed loads
- Does NOT use deprecated Godot 3 `yield()` syntax
### Case 4: Performance issue — typed array recommendation
**Input:** "The entity update loop is slow; it iterates an untyped Array of 1,000 nodes every frame."
**Expected behavior:**
- Identifies that an untyped `Array` foregoes compiler optimization in GDScript
- Recommends converting to a typed array (`Array[Node]` or the specific type) to enable JIT hints
- Notes that if this is still insufficient, escalates the hot path to C# migration recommendation
- Identifies that an untyped `Array` foregoes GDScript compiler optimizations
- Recommends converting to a typed array (`Array[Node]` or the specific type) so the compiler can use typed code paths
- Produces the typed array refactor as the immediate fix
- Does NOT recommend migrating the entire codebase to C# without profiling evidence
- Notes that if profiling still shows the loop as a bottleneck, the next step is moving the hot path to GDExtension (C++/Rust) with godot-gdextension-specialist, per its GDScript/GDExtension boundary
- Does NOT recommend moving the loop, or the codebase, out of GDScript without profiler evidence
### Case 5: Context pass — Godot 4.6 with post-cutoff features
**Input:** Engine version context provided: Godot 4.6. Request: "Create an abstract base class for all enemy types using @abstract."
**Expected behavior:**
- Identifies `@abstract` as a Godot 4.5+ feature (post-cutoff)
- Notes this in the output: feature introduced in 4.5, verified against VERSION.md migration notes
- Produces the GDScript class using `@abstract` with correct syntax as documented in migration notes
- Marks the output as requiring verification against the official 4.5 release notes due to post-cutoff status
- Notes this in the output: feature introduced in 4.5, confirmed against `docs/engine-reference/godot/breaking-changes.md` (4.4 → 4.5 table)
- Produces the GDScript class using `@abstract` on the class and its abstract methods, following the reference docs (`current-best-practices.md`) rather than training data
- Flags that `VERSION.md` records `Installed at pin time` as NOT DETERMINED — the installed editor must be 4.5 or later for `@abstract` to parse
- Uses static typing for all method signatures in the abstract class
---
@@ -73,6 +73,7 @@ No gate IDs assigned.
- [ ] Returns structured GDScript output with full static typing
- [ ] Uses Godot 4 API only — no deprecated Godot 3 patterns (yield, connect with strings, etc.)
- [ ] Flags post-cutoff features (4.4, 4.5, 4.6) and marks them as requiring doc verification
- [ ] Asks "May I write this to [filepath]?" naming the file before writing
---
@@ -3,7 +3,6 @@
## Agent Summary
Domain: Godot shading language (GLSL-derivative), visual shaders (VisualShader graph), material setup, particle shaders, and post-processing effects.
Does NOT own: gameplay code, art style direction.
Model tier: Sonnet (default).
No gate IDs assigned.
---
@@ -11,8 +10,8 @@ No gate IDs assigned.
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references Godot shading language / materials / post-processing)
- [ ] `allowed-tools:` list includes Read, Write, Edit, Glob, Grep
- [ ] Model tier is Sonnet (default for specialists)
- [ ] `tools:` list includes Read, Write, Edit, Glob, Grep
- [ ] Model tier is `sonnet` — frontmatter `model:` reads exactly `sonnet` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition references `docs/engine-reference/godot/VERSION.md` as the authoritative source for Godot shader API changes
---
@@ -34,26 +33,26 @@ No gate IDs assigned.
**Input:** "Write an HLSL compute shader for this dissolve effect."
**Expected behavior:**
- Does NOT produce HLSL code
- Clearly states: "Godot does not use HLSL directly; it uses its own shading language (a GLSL derivative)"
- Translates the HLSL intent to the equivalent Godot shader approach
- Notes that RenderingDevice compute shaders are available in Godot 4 but are a low-level API and flags it appropriately if that was the intent
- States that Godot materials are written in Godot's own shading language (`.gdshader`, a GLSL derivative), not HLSL
- Translates the HLSL intent into the equivalent `.gdshader` approach (noise threshold, `discard`, emission at the dissolve edge)
- If a compute shader was really the intent, flags compute as a separate low-level path (RenderingDevice; unavailable on the Compatibility renderer) and brings in godot-gdextension-specialist for compute-shader offloading
### Case 3: Post-cutoff API change — texture sampling (Godot 4.4)
### Case 3: Post-cutoff API change — shader texture types (Godot 4.4)
**Input:** "Use `texture()` with a sampler2D to sample the noise texture in the shader."
**Expected behavior:**
- Checks the version reference: Godot 4.4 changed texture sampler type declarations
- Flags the potential API change: `sampler2D` syntax and `texture()` call behavior may differ from pre-4.4
- Provides the correct syntax for the project's pinned version (4.6) as documented in migration notes
- Does NOT use pre-4.4 texture sampling syntax without flagging the version risk
- Checks the version reference before writing the shader (`VERSION.md`, then `breaking-changes.md` and `modules/rendering.md`)
- Identifies what the 4.4 change covers: engine-side shader texture parameter/return types moved from `Texture2D` to `Texture` — script and engine API code that handles shader textures, not shading-language syntax
- Uses `uniform sampler2D noise_texture;` with `texture(noise_texture, UV)` — the form its own patterns use; the reference records no change to shading-language sampling syntax
- Does NOT invent a changed sampling syntax for 4.4–4.6, or rewrite `sampler2D` / `texture()` because of the 4.4 row
### Case 4: Fragment shader LOD strategy
**Input:** "The fragment shader for the water surface has 8 texture samples and is causing GPU bottlenecks on mid-range hardware."
**Expected behavior:**
- Identifies the per-fragment texture sample count as the primary cost driver
- Proposes an LOD strategy:
- Reduce sample count at distance (distance-based shader variant or LOD level)
- Pre-bake some texture combinations offline
- Use lower-resolution noise textures for distant samples
- Reduce sample count at distance with a simplified LOD material for distant water, not a per-pixel distance branch in the fragment shader
- Move UV/scroll math that does not need per-pixel evaluation into the vertex shader and pass it through a `varying`
- Make sure the water textures are mipmapped (e.g. `filter_linear_mipmap`) so distant samples read smaller mip levels
- Provides the shader code modification implementing the LOD approach
- Does NOT change gameplay behavior of the water system
@@ -61,8 +60,10 @@ No gate IDs assigned.
**Input:** Engine version context: Godot 4.6. Request: "Add a bloom/glow post-processing effect to the scene."
**Expected behavior:**
- References the VERSION.md note: Godot 4.6 includes a glow rework
- Produces glow configuration guidance using the 4.6 WorldEnvironment approach, not the pre-4.6 API
- Explicitly notes which properties or parameters changed in the 4.6 glow rework
- Because `VERSION.md` records `Installed at pin time` as NOT DETERMINED, asks which editor version is installed before tuning for the 4.6 glow behavior
- Produces glow configuration guidance on the `WorldEnvironment` node's `Environment` resource
- States the documented 4.6 change: glow now processes before tonemapping (it was after), with screen blending — so glow intensity/blend tuned on an earlier version will look different and may need re-tuning
- Does NOT invent renamed or removed glow properties that `breaking-changes.md` and `modules/rendering.md` do not document
- Flags any properties that the LLM's training data may have incorrect information about due to the post-cutoff timing
---
@@ -71,14 +72,15 @@ No gate IDs assigned.
- [ ] Stays within declared domain (Godot shading language, materials, VFX shaders, post-processing)
- [ ] Redirects gameplay code requests to gameplay-programmer
- [ ] Produces valid Godot shading language — never HLSL or raw GLSL without a Godot wrapper
- [ ] Writes material and post-process shaders as `.gdshader` (Godot shading language) — never HLSL
- [ ] Checks engine version reference for post-cutoff shader API changes (4.4 texture types, 4.6 glow rework)
- [ ] Returns structured output (shader code with uniforms documented, LOD strategies with performance rationale)
- [ ] Flags any post-cutoff API usage as requiring verification
- [ ] Asks "May I write this to [filepath]?" naming the file before writing
---
## Coverage Notes
- Dissolve shader (Case 1) should be paired with a visual test screenshot in `production/qa/evidence/`
- Texture API flag (Case 3) confirms the agent checks VERSION.md before using APIs that changed post-4.3
- Texture-type case (Case 3) confirms the agent reads what a post-cutoff change actually covers before applying it, instead of rewriting syntax the change does not touch
- Glow rework (Case 5) is a Godot 4.6-specific test — verifies the agent applies the most recent migration notes
@@ -3,7 +3,6 @@
## Agent Summary
Domain: Godot-specific patterns, node/scene architecture, signals, resources, and GDScript vs C# vs GDExtension decisions.
Does NOT own: actual code authoring in a specific language (delegates to language sub-specialists).
Model tier: Sonnet (default).
No gate IDs assigned.
---
@@ -11,8 +10,8 @@ No gate IDs assigned.
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references Godot architecture / node patterns / engine decisions)
- [ ] `allowed-tools:` list includes Read, Write, Edit, Bash, Glob, Grep
- [ ] Model tier is Sonnet (default for specialists)
- [ ] `tools:` list includes Read, Write, Edit, Bash, Glob, Grep
- [ ] Model tier is `inherit` — frontmatter `model:` reads exactly `inherit` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition references `docs/engine-reference/godot/VERSION.md` as the authoritative API source
---
@@ -25,25 +24,28 @@ No gate IDs assigned.
- Produces a pattern decision guide with rationale:
- Signals: decoupled communication, parent-to-child ignorance, event-driven UI updates, one-to-many notification
- Direct calls: tightly-coupled systems where the caller needs a return value, or performance-critical hot paths
- Provides concrete examples of each pattern in the project's context
- Illustrates each side with a concrete Godot case (e.g., a child health component emitting a typed `health_changed` signal that its parent or the HUD listens to; a parent calling a method on a child it owns)
- Does NOT produce raw code for both patterns — refers to gdscript-specialist or csharp-specialist for implementation
- Notes the "no upward signals" convention (child does not call parent methods directly — uses signals instead)
- Notes the "call down, signal up" convention: a child does not call its parent's methods directly — it emits a signal — so each scene stays self-contained with no implicit dependency on its parent
### Case 2: Wrong-engine redirect
**Input:** "Write a MonoBehaviour that runs on Start() and subscribes to a UnityEvent."
**Expected behavior:**
- Does NOT produce Unity MonoBehaviour code
- Clearly identifies that this is a Unity pattern, not a Godot pattern
- Provides the Godot equivalent: a Node script using `_ready()` instead of `Start()`, and Godot signals instead of UnityEvent
- Confirms the project is Godot-based and redirects the conceptual mapping
- Maps the concepts to Godot: `_ready()` instead of `Start()`, and a typed Godot `signal` connected in `_ready()` instead of a UnityEvent
- Grounds the answer in the project's engine pin (`docs/engine-reference/godot/VERSION.md`, Godot 4.6) rather than asking which engine the project uses
- Routes the actual node script to godot-gdscript-specialist or godot-csharp-specialist rather than writing it itself
- Variant: with `engine.name: Unity` in `project.yaml`, it says it is the wrong specialist for this project instead of mapping the concepts
### Case 3: Post-cutoff API risk
**Input:** "Use the new Godot 4.5 @abstract annotation to define an abstract base class."
**Expected behavior:**
- Identifies that `@abstract` is a post-cutoff feature (introduced in Godot 4.5, after LLM knowledge cutoff)
- Flags the version risk: LLM knowledge of this annotation may be incomplete or incorrect
- Directs the user to verify against `docs/engine-reference/godot/VERSION.md` and the official 4.5 migration guide
- Provides best-effort guidance based on the migration notes in the version reference while clearly marking it as unverified
- Flags the version risk: LLM knowledge of this annotation may be incomplete or incorrect, so the reference docs take precedence
- Confirms the feature against the version reference before answering — `docs/engine-reference/godot/breaking-changes.md` lists the `@abstract` decorator in its 4.4 → 4.5 table
- Flags the installed-version gap: `VERSION.md` records `Installed at pin time` as NOT DETERMINED, so the installed editor must be confirmed as 4.5 or later before `@abstract` code will parse
- Routes the class authoring to godot-gdscript-specialist rather than writing the class itself
### Case 4: Language selection for a hot path
**Input:** "The physics query loop runs every frame for 500 objects. Should we use GDScript or C# for this?"
@@ -51,17 +53,17 @@ No gate IDs assigned.
- Provides a balanced analysis:
- GDScript: simpler, team familiar, but slower for tight loops
- C#: faster for CPU-intensive loops, requires .NET runtime, team needs C# knowledge
- Does NOT make the final decision unilaterally
- Defers the decision to `lead-programmer` with the analysis as input
- Does NOT make the final decision unilaterally — presents the trade-off for the user to decide
- Flags that bringing C#/.NET (or a GDExtension module) into the project is a major tech choice that needs `technical-director` sign-off, not a call it makes alone
- Notes that GDExtension (C++) is a third option for extreme performance cases and recommends escalating if C# is insufficient
### Case 5: Context pass — engine version 4.6
**Input:** Engine version context provided: Godot 4.6, Jolt as default physics. Request: "Set up a RigidBody3D for the player character."
**Expected behavior:**
- Reads the 4.6 context and applies the Jolt-default knowledge (from VERSION.md migration notes)
- Recommends RigidBody3D configuration choices that are Jolt-compatible (e.g., notes any GodotPhysics-specific settings that behave differently under Jolt)
- References the 4.6 migration note about Jolt becoming default rather than relying on LLM training data alone
- Flags any RigidBody3D properties that changed behavior between GodotPhysics and Jolt
- Reads the 4.6 context and the physics module reference (`docs/engine-reference/godot/modules/physics.md`) rather than relying on LLM training data alone
- States what the reference documents: Jolt is the default 3D engine for new projects, but existing projects keep their setting — so it checks Project Settings → Physics → 3D → Physics Engine before assuming Jolt
- Carries over the documented Jolt differences that apply: collision margins may behave differently, and Jolt emits runtime warnings for properties it does not support (e.g. HingeJoint3D `damp`)
- Does NOT invent RigidBody3D property changes between GodotPhysics and Jolt — the reference documents none, and it says so
---
@@ -72,7 +74,8 @@ No gate IDs assigned.
- [ ] Returns structured findings (decision trees, pattern recommendations with rationale)
- [ ] Treats `docs/engine-reference/godot/VERSION.md` as authoritative over LLM training data
- [ ] Flags post-cutoff API usage (4.4, 4.5, 4.6) with verification requirements
- [ ] Defers language-selection decisions to lead-programmer when trade-offs exist
- [ ] Leaves language-selection decisions to the user and routes adoption of a new language or runtime to technical-director
- [ ] Asks "May I write this to [filepath]?" naming the file before writing
---
@@ -3,7 +3,6 @@
## Agent Summary
Domain: Addressable Asset System — groups, async loading/unloading, handle lifecycle management, memory budgeting, content catalogs, and remote content delivery.
Does NOT own: rendering systems (engine-programmer), game logic that uses the loaded assets (gameplay-programmer).
Model tier: Sonnet (default).
No gate IDs assigned.
---
@@ -11,8 +10,8 @@ No gate IDs assigned.
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references Addressables / asset loading / content catalogs / remote delivery)
- [ ] `allowed-tools:` list includes Read, Write, Edit, Bash, Glob, Grep
- [ ] Model tier is Sonnet (default for specialists)
- [ ] `tools:` list includes Read, Write, Edit, Bash, Glob, Grep
- [ ] Model tier is `sonnet` — frontmatter `model:` reads exactly `sonnet` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over rendering systems or gameplay using the loaded assets
---
@@ -26,8 +25,8 @@ No gate IDs assigned.
- Stores the returned `AsyncOperationHandle<Texture2D>` in the requesting object
- On character destruction (`OnDestroy()`), calls `Addressables.Release(handle)` with the stored handle
- Does NOT use `Resources.Load()` as the loading mechanism
- Notes that releasing with a null or uninitialized handle causes errors — includes a validity check
- Notes the difference between releasing the handle vs. releasing the asset (handle release is correct)
- Checks that the load succeeded (`handle.Status`) before using `Result`, and never releases a handle it does not hold (e.g., a character destroyed before its load was started)
- Uses `Addressables.Release(handle)` for loaded assets and reserves `Addressables.ReleaseInstance()` for `InstantiateAsync` results — does not mix the two
### Case 2: Out-of-domain redirect
**Input:** "Implement the rendering system that applies the loaded texture to the character mesh."
@@ -35,37 +34,39 @@ No gate IDs assigned.
- Does NOT produce rendering or mesh material assignment code
- Explicitly states that rendering system implementation belongs to `engine-programmer`
- Redirects the request to `engine-programmer`
- May describe the asset type and API surface it will provide (e.g., `Texture2D` reference once the handle completes) as a handoff spec
- Hands off the asset contract instead: the `Texture2D` comes from the handle's `Result` once the load succeeds, and stays valid only until the owning handle is released, so the consumer must not hold it past that point
### Case 3: Memory leak — un-released handle
**Input:** "Memory usage keeps climbing after each level load. We use Addressables to load level assets."
**Expected behavior:**
- Diagnoses the likely cause: `AsyncOperationHandle` objects not being released after use
- Identifies the handle leak pattern: loading assets into a local variable, losing reference, never calling `Addressables.Release()`
- Produces an auditing approach: search for all `LoadAssetAsync` / `LoadSceneAsync` calls and verify matching `Release()` calls
- Provides a corrected pattern using a tracked handle list (`List<AsyncOperationHandle>`) with a `ReleaseAll()` cleanup method
- Does NOT assume the leak is elsewhere without evidence
- Produces an auditing approach: pair every `LoadAssetAsync` with `Release()`, every `InstantiateAsync` with `ReleaseInstance()`, and every `LoadSceneAsync` with `UnloadSceneAsync()`
- Provides a corrected pattern: every active handle kept in a tracked collection and released when the level unloads, so nothing accumulates across level transitions
- Confirms the diagnosis with the Addressables Event Viewer (per-asset reference counts) or the Memory Profiler before concluding — does not assume the leak is elsewhere without evidence
### Case 4: Remote content delivery — catalog versioning
**Input:** "We need to support downloadable content updates without requiring a full app re-install."
**Expected behavior:**
- Produces the remote catalog update pattern:
- Produces the remote catalog update pattern documented in `docs/engine-reference/unity/plugins/addressables.md`:
- `Addressables.CheckForCatalogUpdates()` on startup
- `Addressables.UpdateCatalogs()` for detected updates
- `Addressables.DownloadDependenciesAsync()` to pre-warm the updated content
- Notes catalog hash checking for change detection
- Addresses the edge case: what happens if a player starts a session, the catalog updates mid-session — defines behavior (complete current session on old catalog, reload on next launch)
- `Addressables.GetDownloadSizeAsync()` before downloading, then `Addressables.DownloadDependenciesAsync()` to pre-download the updated content
- Re-downloads only changed bundles; catalogs are versioned so clients fall back to cached content, and download failures retry with exponential backoff while showing progress
- Raises the mid-session case (a catalog update lands while a session is running) and asks the user which behavior they want, rather than silently picking one
- Plans the update-path tests: fresh install, V1 to V2, and V1 to V3 skipping V2
- Does NOT design the server-side CDN infrastructure (defers to devops-engineer)
### Case 5: Context pass — platform memory constraints
**Input:** Platform context: Nintendo Switch target, 4GB RAM, practical asset memory ceiling 512MB. Request: "Design the Addressables loading strategy for a large open-world level."
**Expected behavior:**
- References the 512MB memory ceiling from the provided context
- References the 512MB memory ceiling from the provided context, and uses it in place of its own default console budget
- Designs a streaming strategy:
- Divide the world into addressable zones loaded/unloaded based on player proximity
- Defines a memory budget per active zone (e.g., 128MB, max 4 zones active)
- Specifies async pre-load trigger distance and unload distance (hysteresis)
- Notes Switch-specific constraints: slower load times from SD card, recommend pre-warming adjacent zones
- Additive scene streaming through `Addressables.LoadSceneAsync()` / `Addressables.UnloadSceneAsync()`, with groups organized per zone by loading context
- A memory budget per active zone whose total stays under the 512MB ceiling, with zones unloaded on transition rather than accumulated
- Essential zone content loaded first, optional content streamed after
- Defers where zone boundaries fall to `level-designer`
- Flags storage I/O speed on the target hardware as a load-time risk to verify on device, without quoting platform load speeds from memory
- Does NOT produce a loading strategy that would exceed the stated 512MB ceiling without flagging it
---
@@ -76,8 +77,9 @@ No gate IDs assigned.
- [ ] Redirects rendering and gameplay asset-use code to engine-programmer and gameplay-programmer
- [ ] Returns structured output (loading patterns, handle lifecycle code, streaming zone designs)
- [ ] Always pairs `LoadAssetAsync` with a corresponding `Release()` — flags handle leaks as a memory bug
- [ ] Designs loading strategies against provided memory ceilings
- [ ] Does not design CDN/server infrastructure — defers to devops-engineer for server side
- [ ] Designs loading strategies against provided memory ceilings, which override its default per-platform budgets
- [ ] Specifies only the client-side contract (remote load path / URL structure, catalog versioning, cache-header requirement) and defers CDN hosting and the delivery pipeline to devops-engineer
- [ ] Asks "May I write this to [filepath]?" naming the file before writing
---
@@ -3,7 +3,6 @@
## Agent Summary
Domain: ECS architecture (IComponentData, ISystem, SystemAPI), Jobs system (IJob, IJobEntity, Burst), Burst compiler constraints, DOTS gameplay systems, and hybrid renderer.
Does NOT own: MonoBehaviour gameplay code (gameplay-programmer), UI implementation (unity-ui-specialist).
Model tier: Sonnet (default).
No gate IDs assigned.
---
@@ -11,8 +10,8 @@ No gate IDs assigned.
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references ECS / Jobs / Burst / IComponentData)
- [ ] `allowed-tools:` list includes Read, Write, Edit, Bash, Glob, Grep
- [ ] Model tier is Sonnet (default for specialists)
- [ ] `tools:` list includes Read, Write, Edit, Bash, Glob, Grep
- [ ] Model tier is `sonnet` — frontmatter `model:` reads exactly `sonnet` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over MonoBehaviour gameplay or UI systems
---
@@ -25,10 +24,10 @@ No gate IDs assigned.
- Produces:
- `PlayerMovementData : IComponentData` struct with velocity, speed, and input vector fields
- `PlayerMovementSystem : ISystem` with `OnUpdate()` using `SystemAPI.Query<>` or `IJobEntity`
- Bakes the player's initial state from an authoring MonoBehaviour via `IBaker`
- Bakes the player's initial state from an authoring MonoBehaviour via a `Baker<T>` subclass (the pattern in `docs/engine-reference/unity/plugins/dots-entities.md`)
- Uses `RefRW<LocalTransform>` for position updates (not deprecated `Translation`)
- Marks the job `[BurstCompile]` and notes what must be unmanaged for Burst compatibility
- Does NOT modify the input polling system — reads from an existing `PlayerInputData` component
- Keeps one concern per system: the movement system reads input from a component (e.g. `PlayerInputData`) that a separate input system writes, rather than polling input itself, and asks before creating or changing that input side
### Case 2: MonoBehaviour push-back
**Input:** "Just use MonoBehaviour for the player movement — it's simpler."
@@ -36,7 +35,7 @@ No gate IDs assigned.
- Acknowledges the simplicity argument
- Explains the DOTS trade-off: more setup upfront, but the ECS/Burst approach provides the performance characteristics documented in the project's ADR or requirements
- Does NOT implement a MonoBehaviour version if the project has committed to DOTS
- If no commitment exists, flags the architecture decision to `lead-programmer` / `technical-director` for resolution
- If no commitment exists, routes the MonoBehaviour-vs-DOTS decision to `unity-specialist` (its named contact for overall Unity architecture), with `technical-director` as the escalation for an unresolved technical conflict
- Does not make the MonoBehaviour vs. DOTS decision unilaterally
### Case 3: Burst-incompatible managed memory
@@ -45,27 +44,26 @@ No gate IDs assigned.
- Flags `List<T>` as a managed type that is incompatible with Burst compilation
- Does NOT approve the Burst job with managed memory access
- Provides the correct replacement: `NativeArray<EnemyData>`, `NativeList<EnemyData>`, or `NativeHashMap<>` depending on the use case
- Notes that `NativeArray` must be disposed explicitly or via `[DeallocateOnJobCompletion]`
- Notes that the native container must be disposed, with the allocator chosen by lifetime (`Allocator.TempJob` for frame-scoped, `Allocator.Persistent` for long-lived) and capacity pre-allocated when the size is known
- Produces the corrected job using unmanaged native containers
### Case 4: Hybrid access — DOTS system needs MonoBehaviour data
**Input:** "The DOTS movement system needs to read the camera transform managed by a MonoBehaviour CameraController."
**Expected behavior:**
- Identifies this as a hybrid access scenario
- Provides the correct hybrid pattern: store the camera transform in a singleton `IComponentData` (updated from the MonoBehaviour side each frame via `EntityManager.SetComponentData`)
- Alternatively suggests the `CompanionComponent` / managed component approach
- Does NOT access the MonoBehaviour from inside a Burst job — flags that as unsafe
- Provides the bridge code on both the MonoBehaviour side (writing to ECS) and the DOTS system side (reading from ECS)
- Does NOT put the `Transform` or the MonoBehaviour itself into a component — components hold no references to managed objects
- Carries the camera data across the boundary as unmanaged values (`Unity.Mathematics` types) in an `IComponentData`, written at one explicit hand-off point on the MonoBehaviour side and read by the system — not reached for per entity
- Does NOT access the MonoBehaviour from inside a Burst job — flags managed access in Burst code as a compile error
### Case 5: Context pass — performance targets
**Input:** Technical preferences from context: 60fps target, max 2ms CPU script budget per frame. Request: "Design the ECS chunk layout for 10,000 enemy entities."
**Expected behavior:**
- References the 2ms CPU budget explicitly in the design rationale
- Designs the `IComponentData` chunk layout for cache efficiency:
- Groups frequently-queried together components in the same archetype
- Separates rarely-used data into separate components to keep hot data compact
- Estimates entity iteration time against the 2ms budget
- Provides memory layout analysis (bytes per entity, entities per chunk at 16KB chunk size)
- Splits components by system access pattern, not by game concept — no "god component"
- Keeps hot components small, with rarely-used data in separate components
- Uses tag components for filtering, avoids `ISharedComponentData` that would fragment archetypes, and uses `IEnableableComponent` instead of structural changes for toggled state
- Names how the budget will be verified — Entities Profiler system timings and per-archetype memory — instead of presenting unmeasured timings as fact
- Does NOT design a layout that will obviously exceed the stated 2ms budget without flagging it
---
@@ -74,14 +72,15 @@ No gate IDs assigned.
- [ ] Stays within declared domain (ECS, Jobs, Burst, DOTS gameplay systems)
- [ ] Redirects MonoBehaviour-only gameplay to gameplay-programmer
- [ ] Returns structured output (IComponentData structs, ISystem implementations, IBaker authoring classes)
- [ ] Returns structured output (IComponentData structs, ISystem implementations, `Baker<T>` authoring classes)
- [ ] Flags managed memory access in Burst jobs as a compile error and provides unmanaged alternatives
- [ ] Provides hybrid access patterns when DOTS systems need to interact with MonoBehaviour systems
- [ ] Designs chunk layouts against provided performance budgets
- [ ] Designs chunk layouts against provided performance budgets, and names the profiling step that verifies them
- [ ] Asks "May I write this to [filepath]?" naming the file before writing
---
## Coverage Notes
- ECS conversion (Case 1) must include a unit test using the ECS test framework (`World`, `EntityManager`)
- ECS conversion (Case 1) must include a unit test using the ECS test framework (`World`, `EntityManager`) under `Assets/Tests/EditMode/`
- Burst incompatibility (Case 3) is safety-critical — the agent must catch this before the code is written
- Chunk layout (Case 5) verifies the agent applies quantitative performance reasoning to architecture decisions
- Chunk layout (Case 5) verifies the agent designs against a stated budget and says how it will be measured, rather than asserting unmeasured numbers
@@ -3,7 +3,6 @@
## Agent Summary
Domain: Unity Shader Graph, custom HLSL, VFX Graph, URP/HDRP pipeline customization, and post-processing effects.
Does NOT own: gameplay code, art style direction.
Model tier: Sonnet (default).
No gate IDs assigned.
---
@@ -11,8 +10,8 @@ No gate IDs assigned.
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references Shader Graph / HLSL / VFX Graph / URP / HDRP)
- [ ] `allowed-tools:` list includes Read, Write, Edit, Glob, Grep
- [ ] Model tier is Sonnet (default for specialists)
- [ ] `tools:` list includes Read, Write, Edit, Glob, Grep
- [ ] Model tier is `sonnet` — frontmatter `model:` reads exactly `sonnet` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over gameplay code or art direction
---
@@ -22,11 +21,9 @@ No gate IDs assigned.
### Case 1: In-domain request — appropriate output
**Input:** "Create an outline effect for characters using Shader Graph in URP."
**Expected behavior:**
- Produces a Shader Graph node setup description:
- Inverted hull method: Scale Normal → Vertex offset in vertex stage, Cull Front
- OR screen-space post-process outline using depth/normal edge detection
- Recommends the appropriate method based on URP capabilities (inverted hull for URP compatibility, post-process for HDRP)
- Notes URP limitations: no geometry shader support (rules out geometry-shader outline approach)
- Produces a Shader Graph node setup description (inverted hull via vertex offset, or a screen-space depth/normal edge detection), named to its convention (e.g., `SG_Char_Outline`) with reusable logic in a Sub Graph
- Stays in Shader Graph and drops to custom HLSL only if Shader Graph cannot achieve the effect; any HLSL keeps SRP Batcher compatibility (`UnityPerMaterial` CBUFFER)
- For a screen-space variant, uses a URP `ScriptableRendererFeature` / `ScriptableRenderPass` recorded through the RenderGraph API (`RecordRenderGraph`), not the deprecated `Execute` / CommandBuffer path — per `docs/engine-reference/unity/modules/rendering.md`
- Does NOT produce HDRP-specific nodes without confirming the render pipeline
### Case 2: Out-of-domain redirect
@@ -35,34 +32,33 @@ No gate IDs assigned.
- Does NOT produce UI implementation code
- Explicitly states that UI implementation belongs to `ui-programmer` (or `unity-ui-specialist`)
- Redirects the request appropriately
- May note that a shader-based fill effect for a health bar (e.g., a dissolve/fill gradient) is within its domain if the visual effect itself is shader-driven
- Any part it keeps is the shader-driven effect only (e.g., a dissolve or fill gradient on the bar) — it writes no health-bar UI code
### Case 3: HDRP custom pass for outline
**Input:** "We're on HDRP and want the outline as a post-process effect."
**Expected behavior:**
- Produces the HDRP `CustomPassVolume` pattern:
- C# class inheriting `CustomPass`
- `Execute()` method using `CoreUtils.SetRenderTarget()` and a full-screen shader blit
- Depth/normal buffer sampling for edge detection
- Produces the HDRP custom pass pattern its own standards name: a C# class inheriting `CustomPass`, run from a Custom Pass Volume, drawing a full-screen edge-detection shader that samples the depth/normal buffers
- Uses the HDRP overrides `docs/engine-reference/unity/current-best-practices.md` documents — `Setup(ScriptableRenderContext, CommandBuffer)`, `Execute(CustomPassContext ctx)`, `Cleanup()` — never URP's `RecordRenderGraph`, and marks any other HDRP member it uses (render-target helpers, `CustomPassContext` fields) unverified — nothing beyond those three is asserted from memory
- Notes that CustomPass requires HDRP package and does not work in URP
- Confirms the project is on HDRP before providing HDRP-specific code
### Case 4: VFX Graph performance — GPU event batching
### Case 4: VFX Graph performance — particle budget
**Input:** "The explosion VFX Graph has 10,000 particles per event and spawning 20 simultaneous explosions is causing GPU frame spikes."
**Expected behavior:**
- Identifies GPU particle spawn as the cost driver (200,000 simultaneous particles)
- Proposes GPU event batching: spawn events deferred over multiple frames, stagger initialization
- Recommends a particle budget cap per active explosion (e.g., 3,000 per explosion, queue excess)
- Notes the VFX Graph Event Batcher pattern and Output Event API for cross-frame distribution
- Sets a particle capacity limit per effect and sizes it against the < 2ms total VFX GPU budget
- Pools explosion VFX instances and triggers them through events, rather than creating a graph per explosion
- Reduces cost for distant or off-screen explosions (particle LOD, bounds-based culling) and scales counts by quality tier
- Avoids any fix that reads GPU particle data back to the CPU
- Does NOT change the gameplay event system — proposes a VFX-side budgeting solution
### Case 5: Context pass — render pipeline (URP or HDRP)
**Input:** Project context: URP render pipeline, Unity 2022.3. Request: "Add depth of field post-processing."
**Input:** Project context: URP render pipeline, targets PC and Nintendo Switch. Request: "Add depth of field post-processing."
**Expected behavior:**
- Uses URP Volume framework: `DepthOfField` Volume Override component
- Uses URP Volume framework: a `DepthOfField` override in a Volume Profile, with script access through `profile.TryGet<>()` as `docs/engine-reference/unity/modules/rendering.md` shows
- Does NOT use HDRP Volume components (e.g., HDRP's `DepthOfField` with different parameter names)
- Notes URP-specific DOF limitations vs HDRP (e.g., Bokeh quality differences)
- Produces C# Volume profile setup code compatible with Unity 2022.3 URP package version
- Places it on the Global Volume for the baseline look or a local Volume for an area, with priority and blend distance set
- Gates the effect per platform and quality tier — reduced or disabled on Switch — and keeps post-processing inside its 1-2ms frame budget
---
@@ -72,8 +68,9 @@ No gate IDs assigned.
- [ ] Redirects gameplay and UI code to appropriate agents
- [ ] Returns structured output (node graph descriptions, HLSL code, CustomPass patterns)
- [ ] Distinguishes between URP and HDRP approaches — never cross-contaminates pipeline-specific APIs
- [ ] Flags geometry shader approaches as URP-incompatible when relevant
- [ ] Uses the RenderGraph API for custom URP passes, not the deprecated `Execute` / CommandBuffer path
- [ ] Produces VFX optimizations that do not change gameplay behavior
- [ ] Asks "May I write this to [filepath]?" naming the file before writing
---
@@ -3,7 +3,6 @@
## Agent Summary
Domain: Unity-specific architecture patterns, MonoBehaviour vs DOTS decisions, and subsystem selection (Addressables, New Input System, UI Toolkit, Cinemachine, etc.).
Does NOT own: language-specific deep dives (delegates to unity-dots-specialist, unity-ui-specialist, etc.).
Model tier: Sonnet (default).
No gate IDs assigned.
---
@@ -11,8 +10,8 @@ No gate IDs assigned.
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references Unity patterns / MonoBehaviour / subsystem decisions)
- [ ] `allowed-tools:` list includes Read, Write, Edit, Bash, Glob, Grep
- [ ] Model tier is Sonnet (default for specialists)
- [ ] `tools:` list includes Read, Write, Edit, Bash, Glob, Grep
- [ ] Model tier is `inherit` — frontmatter `model:` reads exactly `inherit` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition acknowledges the sub-specialist routing table (DOTS, UI, Shader, Addressables)
---
@@ -33,51 +32,54 @@ No gate IDs assigned.
**Input:** "Set up a Node scene tree with signals for this enemy system."
**Expected behavior:**
- Does NOT produce Godot Node/signal code
- Identifies this as a Godot pattern
- States that in Unity the equivalent is GameObject hierarchy + UnityEvent or C# events
- Maps the concepts: Godot Node → Unity MonoBehaviour, Godot Signal → C# event / UnityEvent
- Confirms the project is Unity-based before proceeding
- Identifies node trees and signals as Godot concepts
- Confirms the project's engine from `engine.name` in `project.yaml` rather than guessing; if it is not Unity, says it is the wrong specialist for this project instead of translating
- If `engine.name` is unset, says no engine is configured and asks which engine the project uses — it does not assume Unity
- In a Unity project, maps the concepts: node tree → GameObject hierarchy with composed MonoBehaviours; signal → C# event or UnityEvent (consistent with its own rule to use events instead of `SendMessage()` / `Find()`)
- Does not hand the request to a Godot specialist — its Agent grant covers only the four Unity sub-specialists
### Case 3: Unity version API flag
**Input:** "Use the new Unity 6 GPU resident drawer for batch rendering."
**Expected behavior:**
- Identifies the Unity 6 feature (GPU Resident Drawer)
- Flags that this API may not be available in earlier Unity versions
- Asks for or checks the project's Unity version before providing implementation guidance
- Directs to verify against official Unity 6 documentation
- Does NOT assume the project is on Unity 6 without confirmation
- Checks `docs/engine-reference/unity/VERSION.md` and `docs/engine-reference/unity/modules/rendering.md` before answering, not training data (the version file places Unity 6 past the model's knowledge cutoff)
- States what the reference documents: GPU Resident Drawer is a Unity 6+ feature enabled in the URP Asset (Rendering > GPU Resident Drawer), so it requires an SRP project
- Flags the installed-version gap: when `Installed at pin time` in the version file is not determined, asks which editor version is installed before recommending the feature
- Does NOT assume the installed editor is Unity 6 because the reference is pinned to it
- Proposes the URP Asset change and asks before editing it; routes render pipeline customization beyond the setting to `unity-shader-specialist`
### Case 4: DOTS vs. MonoBehaviour conflict
**Input:** "The combat system uses MonoBehaviour for state management, but we want to add a DOTS-based projectile system. Can they coexist?"
**Expected behavior:**
- Recognizes this as a hybrid architecture scenario
- Explains the hybrid approach: MonoBehaviour can interface with DOTS via SystemAPI, IComponentData, and managed components
- Explains the coexistence mechanism at architecture level, as `docs/engine-reference/unity/plugins/dots-entities.md` documents it: authoring MonoBehaviours baked into entities by a `Baker<T>`, projectile data held in `IComponentData`, processed by an `ISystem`
- Notes the performance and complexity trade-offs of mixing the two patterns
- Recommends escalating the architecture decision to `lead-programmer` or `technical-director`
- Defers to `unity-dots-specialist` for the DOTS-side implementation details
### Case 5: Context pass — Unity version
**Input:** Project context provided: Unity 2023.3 LTS. Request: "Configure the new Input System for this project."
**Input:** Project context provided: Unity 6.3 LTS, keyboard/mouse and gamepad targets. Request: "Configure the new Input System for this project."
**Expected behavior:**
- Applies Unity 2023.3 LTS context: uses the New Input System (com.unity.inputsystem) package
- Does NOT produce legacy Input Manager code (`Input.GetKeyDown()`, `Input.GetAxis()`)
- Notes any 2023.3-specific Input System behaviors or package version constraints
- References the project version to confirm Burst/Jobs compatibility if the Input System interacts with DOTS
- Applies the Unity 6.3 LTS context from `docs/engine-reference/unity/modules/input.md`: the Input System package (`com.unity.inputsystem`) with Active Input Handling set to the new system
- Does NOT produce legacy Input Manager code (`Input.GetKeyDown()`, `Input.GetAxis()`) — the engine reference lists these as deprecated
- Defines actions in an `.inputactions` asset, uses the Player Input component or a generated C# class, and prefers action callbacks (`performed`, `canceled`) over polling in `Update()`
- Sets up keyboard+mouse and gamepad control schemes with automatic switching
- Routes UI navigation and input-prompt work to `unity-ui-specialist`
- Treats adding the package as a dependency decision needing `technical-director` sign-off, and asks before writing any settings or asset
---
## Protocol Compliance
- [ ] Stays within declared domain (Unity architecture decisions, pattern selection, subsystem routing)
- [ ] Redirects Godot patterns to appropriate Godot specialists or flags them as wrong-engine
- [ ] Treats Godot patterns as wrong-engine: checks `engine.name`, answers with the Unity equivalent, never emits Godot code
- [ ] Redirects DOTS implementation to unity-dots-specialist
- [ ] Redirects UI implementation to unity-ui-specialist
- [ ] Flags Unity version-gated APIs and requires version confirmation before suggesting them
- [ ] Checks `docs/engine-reference/unity/` (pinned version and `Installed at pin time`) before suggesting a version-gated API, and confirms the installed version when it is not recorded
- [ ] Returns structured pattern decision guides, not freeform opinions
---
## Coverage Notes
- MonoBehaviour vs. ScriptableObject (Case 1) should be documented as an ADR if it results in a project-level decision
- Version flag (Case 3) confirms the agent does not assume the latest Unity version without context
- Version flag (Case 3) confirms the agent checks the pinned and installed Unity version rather than assuming the latest
- DOTS hybrid (Case 4) verifies the agent escalates architecture conflicts rather than resolving them unilaterally
@@ -3,7 +3,6 @@
## Agent Summary
Domain: Unity UI Toolkit (UXML/USS), UGUI (Canvas), data binding, runtime UI performance, and UI input event handling.
Does NOT own: UX flow design (ux-designer), visual art style (art-director).
Model tier: Sonnet (default).
No gate IDs assigned.
---
@@ -11,8 +10,8 @@ No gate IDs assigned.
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references UI Toolkit / UGUI / Canvas / data binding)
- [ ] `allowed-tools:` list includes Read, Write, Edit, Bash, Glob, Grep
- [ ] Model tier is Sonnet (default for specialists)
- [ ] `tools:` list includes Read, Write, Edit, Bash, Glob, Grep
- [ ] Model tier is `sonnet` — frontmatter `model:` reads exactly `sonnet` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over UX flow design or visual art direction
---
@@ -24,7 +23,7 @@ No gate IDs assigned.
**Expected behavior:**
- Produces a UXML document defining the inventory panel structure (ListView, item templates, detail panel)
- Produces USS styles for the inventory layout and item states (default, hover, selected)
- Provides C# code binding the inventory data model to the UI via `INotifyValueChanged` or `IBindable`
- Provides C# code binding the inventory data model to the UI through the runtime binding system: a ViewModel implementing `INotifyBindablePropertyChanged`, with the UI reading through bindings and never writing game state
- Uses `ListView` with `makeItem` / `bindItem` callbacks for the scrollable item list
- Does NOT produce the UX flow design — implements from a provided spec
@@ -39,28 +38,29 @@ No gate IDs assigned.
### Case 3: UI Toolkit data binding for dynamic list
**Input:** "The inventory list needs to update in real time as items are added or removed from the player's bag."
**Expected behavior:**
- Produces the `ListView` pattern with a bound `ObservableList<T>` or event-driven refresh approach
- Uses `ListView.Rebuild()` or `ListView.RefreshItems()` on the backing collection change event
- Notes the performance considerations for large lists (virtualization via `makeItem`/`bindItem` pattern)
- Does NOT use `QuerySelector` loops to update individual elements as a list refresh strategy — flags that as a performance antipattern
- Produces the `ListView` pattern over the inventory's backing collection, virtualized with `makeItem` / `bindItem` so only visible rows exist
- Drives the refresh from the inventory's change event (game state → ViewModel → binding), not from per-frame polling
- Does NOT refresh the list by querying the visual tree for each element — flags per-frame visual-tree queries as an antipattern and caches references instead
- Does NOT create and destroy row elements on each change — reuses rows through the virtualized list
### Case 4: Canvas performance — overdraw
**Input:** "The main menu canvas is causing GPU overdraw warnings; there are many overlapping panels."
**Expected behavior:**
- Identifies overdraw causes: multiple stacked canvases, full-screen overlay panels not culled when inactive
- Recommends:
- Separate canvases for world-space, screen-space-overlay, and screen-space-camera layers
- Disable/deactivate panels instead of setting alpha to 0 (invisible alpha-0 panels still draw)
- Canvas Group + alpha for fade effects, not individual Image alpha
- Notes UI Toolkit alternative if the project is in a migration position
- Confirms the hotspot with a profiler before changing structure (Frame Debugger, Profiler UI module)
- Recommends its documented Canvas remediation:
- One Canvas per logical UI layer, with frequently changing and static content on separate Canvases
- Explicit `Canvas.sortingOrder` rather than hierarchy order
- Shared sprite atlases so panels batch, and Raycast Target disabled on non-interactive elements
- A `CanvasGroup` to fade or hide a group of elements, not per-Image alpha changes
- Notes that screen-space menus are UI Toolkit territory under its own selection rules (the engine reference also marks UGUI Canvas as superseded for new projects), offered as an option rather than a unilateral rewrite
### Case 5: Context pass — Unity version
**Input:** Project context: Unity 2022.3 LTS. Request: "Implement the settings panel with data binding."
**Expected behavior:**
- Uses UI Toolkit with the 2022.3 LTS version of the runtime binding system
- Notes that Unity 2022.3 introduced runtime data binding (as opposed to editor-only binding in earlier versions)
- Does NOT use the Unity 6 enhanced binding API features if they are not available in 2022.3
- Produces code compatible with the stated Unity version, with version-specific API notes
- Checks the stated version against `docs/engine-reference/unity/VERSION.md`, which pins Unity 6.3 LTS, and asks which editor is actually installed before choosing a binding API
- Does NOT state from memory which Unity version introduced runtime data binding — the engine reference does not document it, so the claim is flagged as unverified
- Does NOT emit the runtime binding system (`INotifyBindablePropertyChanged`) for a 2022.3 editor until that API is confirmed available there
- Keeps the version-independent parts of its pattern regardless: UI reads state, user actions dispatch commands, the panel never writes game state directly
---
@@ -69,13 +69,14 @@ No gate IDs assigned.
- [ ] Stays within declared domain (UI Toolkit, UGUI, data binding, UI performance)
- [ ] Redirects UX flow design to ux-designer
- [ ] Returns structured output (UXML, USS, C# binding code)
- [ ] Uses the correct Unity UI framework version for the project's Unity version
- [ ] Flags Canvas overdraw as a performance antipattern and provides specific remediation
- [ ] Does not use alpha-0 as a hide/show pattern — uses SetActive() or VisualElement.style.display
- [ ] Checks the project's Unity version against `docs/engine-reference/unity/VERSION.md` before using version-dependent UI APIs, and asks when the stated version and the pin disagree
- [ ] Flags Canvas overdraw as a performance antipattern and provides specific remediation (Canvas split by layer and update rate, atlasing, Raycast Target off)
- [ ] Hides elements with its documented mechanism — `VisualElement.visible = false` in UI Toolkit, a `CanvasGroup` in UGUI — never by setting each element's alpha to 0
- [ ] Asks "May I write this to [filepath]?" naming the file before writing
---
## Coverage Notes
- Inventory UI (Case 1) should have a manual walkthrough doc in `production/qa/evidence/`
- Inventory UI (Case 1) should have a retained screenshot of each screen touched in `production/qa/evidence/`
- Dynamic list binding (Case 3) should have an integration test or automated interaction test
- Canvas overdraw (Case 4) verifies the agent knows the correct Unity UI performance patterns
@@ -2,17 +2,16 @@
## Agent Summary
- **Domain**: Blueprint architecture, the Blueprint/C++ boundary, Blueprint graph quality, Blueprint performance optimization, Blueprint Function Library design
- **Does NOT own**: C++ implementation (engine-programmer or gameplay-programmer), art assets or shaders, UI/UX flow design (ux-designer)
- **Model tier**: Sonnet
- **Gate IDs**: None; defers to unreal-specialist or lead-programmer for cross-domain rulings
- **Does NOT own**: C++ implementation (gameplay-programmer exposes the C++ hooks Blueprint calls), art assets or shaders, UI/UX flow design (ux-designer)
- **Gate IDs**: None; defers C++/Blueprint boundary architecture rulings to unreal-specialist
---
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references Blueprint architecture and optimization)
- [ ] `allowed-tools:` list matches the agent's role (Read for Blueprint project files; no server or deployment tools)
- [ ] Model tier is Sonnet (default for specialists)
- [ ] `tools:` list matches the agent's role (Read/Write/Edit for Blueprint-facing files; no server or deployment tools, and Bash withheld via `disallowedTools:`)
- [ ] Model tier is `sonnet` — frontmatter `model:` reads exactly `sonnet` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over C++ implementation decisions
---
@@ -23,26 +22,25 @@
**Input**: "Review our AI behavior Blueprint. It has tick-based logic running every frame that checks line-of-sight for 30 NPCs simultaneously."
**Expected behavior**:
- Identifies tick-heavy logic as a performance problem
- Recommends switching from EventTick to event-driven patterns (perception system events, timers, or polling on a reduced interval)
- Flags the per-NPC cost of simultaneous line-of-sight checks
- Suggests alternatives: AIPerception component events, staggered tick groups, or moving the system to C++ if Blueprint overhead is measured to be significant
- Output is structured: problem identified, impact estimated, alternatives listed
- Recommends switching from EventTick to event-driven patterns (perception system events, timers, or polling on a reduced interval) — never polling every frame when an event would suffice
- Flags the per-NPC cost of simultaneous line-of-sight checks, including any loop over the NPC array inside Tick
- Recommends profiling first (`stat game`, Blueprint profiler), and treats moving the system to C++ as warranted when the measured Blueprint overhead is significant — 30 NPCs is below its automatic C++ threshold (tick logic with more than 100 instances)
- Output names, for each finding, the Performance Rule or Review Checklist item it breaks and the replacement pattern
### Case 2: Out-of-domain request — C++ implementation
**Input**: "Write the C++ implementation for this ability cooldown system."
**Expected behavior**:
- Does not produce C++ implementation code
- Provides the Blueprint equivalent of the cooldown logic (e.g., using a Timeline or GameplayEffect if GAS is in use)
- States clearly: "C++ implementation is handled by engine-programmer or gameplay-programmer; I can show the Blueprint approach or describe the boundary where Blueprint calls into C++"
- Optionally notes when the cooldown complexity warrants a C++ backend
- Classifies the cooldown system with its boundary rules: ability-system logic is on its "Must Be C++" list, so it does not offer a Blueprint reimplementation of the system
- Describes the boundary instead: C++ defines the framework and exposes hooks (`BlueprintCallable`, `BlueprintNativeEvent`, `BlueprintImplementableEvent`); Blueprint supplies tuning values (`EditAnywhere` / `BlueprintReadWrite`) and simple event responses such as cooldown feedback
- Routes the C++ implementation to gameplay-programmer (its named partner for exposing C++ hooks to Blueprint) and the boundary decision to unreal-specialist, rather than writing the C++ system itself
### Case 3: Domain boundary — unsafe raw pointer access in Blueprint
**Input**: "Our Blueprint calls GetOwner() and then immediately accesses a component on the result without checking if it's valid."
**Expected behavior**:
- Flags this as a runtime crash risk: GetOwner() can return null in some lifecycle states
- Provides the correct Blueprint pattern: IsValid() node before any property/component access
- Flags this as a runtime crash risk under its Review Checklist item "Error/failure paths are handled (not just the happy path)": GetOwner() can return null in some lifecycle states
- Provides the correct Blueprint pattern: IsValid() node before any property/component access, with the invalid branch handled
- Notes that Blueprint's null checks are not optional on Actor-derived references
- Does NOT silently fix the code without explaining why the original was unsafe
- Does NOT silently fix the code — explains why the original was unsafe and asks before editing the Blueprint
### Case 4: Blueprint graph complexity — readiness for Function Library refactor
**Input**: "Our main GameMode Blueprint has 600+ nodes in a single graph with duplicated damage calculation logic in 8 places."
@@ -57,24 +55,25 @@
**Input context**: Project conventions specify a maximum of 100 nodes per Blueprint event graph before a mandatory Function Library extraction.
**Input**: "Here is our inventory Blueprint graph [150 nodes shown]. Is it ready to ship?"
**Expected behavior**:
- References the stated 150-node count against the 100-node budget from project conventions
- References the stated 150-node count against the 100-node event-graph budget from project conventions
- Flags the graph as exceeding the complexity threshold
- Does NOT approve it as-is
- Produces a list of candidate subgraphs for Function Library extraction to bring the main graph within budget
- Applies its own standard (maximum 20 nodes per function graph) to the extracted functions, keeping it distinct from the project's event-graph budget rather than substituting one number for the other
---
## Protocol Compliance
- [ ] Stays within declared domain (Blueprint architecture, performance, graph quality)
- [ ] Redirects C++ implementation requests to engine-programmer or gameplay-programmer
- [ ] Returns structured findings (problem/impact/alternatives format) rather than freeform opinions
- [ ] Routes C++ implementation requests to gameplay-programmer and boundary rulings to unreal-specialist
- [ ] Grounds findings in its own Performance Rules and Blueprint Review Checklist, naming the rule each finding breaks, rather than freeform opinions
- [ ] Enforces Blueprint safety patterns (null checks, IsValid) proactively
- [ ] References project conventions when evaluating graph complexity
- [ ] References project conventions when evaluating graph complexity, alongside its own per-function node limit
---
## Coverage Notes
- Case 3 (null pointer safety) is a safety-critical test — this is a common source of shipping crashes
- Case 5 requires that project conventions include a stated node budget; if none is configured, the agent should note the absence and recommend setting one
- Case 5 requires that project conventions include a stated node budget; if none is configured, the agent falls back to its own standard (maximum 20 nodes per function graph) and says so
- No automated runner; review manually or via `/skill-test`
@@ -2,8 +2,7 @@
## Agent Summary
- **Domain**: Gameplay Ability System (GAS) — abilities (UGameplayAbility), gameplay effects (UGameplayEffect), attribute sets (UAttributeSet), gameplay tags, ability tasks (UAbilityTask), ability specs (FGameplayAbilitySpec), GAS prediction and latency compensation
- **Does NOT own**: UI display of ability state (ue-umg-specialist), net replication of GAS data beyond built-in GAS prediction (ue-replication-specialist), art or VFX for ability feedback (vfx-artist)
- **Model tier**: Sonnet
- **Does NOT own**: UI display of ability state (ue-umg-specialist), net replication of GAS data beyond built-in GAS prediction (ue-replication-specialist), art or VFX for ability feedback (technical-artist)
- **Gate IDs**: None; defers cross-domain calls to the appropriate specialist
---
@@ -11,8 +10,8 @@
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references GAS, abilities, GameplayEffects, AttributeSets)
- [ ] `allowed-tools:` list matches the agent's role (Read/Write for GAS source files; no deployment or server tools)
- [ ] Model tier is Sonnet (default for specialists)
- [ ] `tools:` reads Read, Glob, Grep, Write, Edit, Bash — no `Agent` tool
- [ ] Model tier is `sonnet` — frontmatter `model:` reads exactly `sonnet` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over UI implementation or low-level net serialization
---
@@ -22,18 +21,18 @@
### Case 1: In-domain request — dash ability with cooldown
**Input**: "Implement a dash ability that moves the player forward 500 units and has a 1.5 second cooldown."
**Expected behavior**:
- Produces a GAS AbilitySpec structure or outline: UGameplayAbility subclass with ActivateAbility logic, an AbilityTask for movement (e.g., AbilityTask_ApplyRootMotionMoveToForce or custom root motion), and a UGameplayEffect for the cooldown
- Produces a GAS AbilitySpec structure or outline: an ability deriving from the project's base ability class (not raw UGameplayAbility) with ActivateAbility logic, an AbilityTask for movement (e.g., AbilityTask_ApplyRootMotionMoveToForce or custom root motion), and a UGameplayEffect for the cooldown
- Cooldown GameplayEffect uses Duration policy with the 1.5s duration and a GameplayTag to block re-activation
- Tags clearly named following a hierarchy convention (e.g., Ability.Dash, Cooldown.Ability.Dash)
- Output includes both the ability class outline and the GameplayEffect definition
### Case 2: Out-of-domain request — GAS state replication
### Case 2: Mixed-domain request — cooldown replication feeding the UI
**Input**: "How do I replicate the player's ability cooldown state to all clients so the UI updates correctly?"
**Expected behavior**:
- Clarifies that GAS has built-in replication for AbilitySpecs and GameplayEffects via the AbilitySystemComponent's replication mode
- Explains the three ASC replication modes (Full, Mixed, Minimal) and when to use each
- For custom replication needs beyond GAS built-ins, explicitly states: "For custom net serialization of GAS data, coordinate with ue-replication-specialist"
- Does NOT attempt to write custom replication code outside GAS's own systems without flagging the domain boundary
- Answers the replication half from GAS built-ins: the cooldown is a Duration Gameplay Effect granting a cooldown tag, replicated through the AbilitySystemComponent
- Explains the three ASC replication modes (Full, Mixed, Minimal) and which clients each one delivers cooldown state to
- Does NOT write custom replication (RepNotify properties or RPCs) for state GAS already replicates — effect-driven attribute changes replicate automatically and must not be double-replicated
- Hands the cooldown-indicator UI to ue-umg-specialist, and names ue-replication-specialist for multiplayer prediction concerns beyond the ASC's built-in handling
### Case 3: Domain boundary — incorrect GameplayTag hierarchy
**Input**: "We have an ability that applies a tag called 'Stunned' and another that checks for 'Status.Stunned'. They're not matching."
@@ -47,19 +46,20 @@
### Case 4: Conflict — attribute set conflict between two abilities
**Input**: "Our Shield ability and our Armor ability both modify a 'DefenseValue' attribute. They're stacking in ways that aren't intended — after both are active, defense goes well above maximum."
**Expected behavior**:
- Identifies this as a GameplayEffect stacking and magnitude calculation problem
- Proposes a resolution using Execution Calculations (UGameplayEffectExecutionCalculation) or Modifier Aggregators to cap the combined result
- Alternatively recommends using Gameplay Effect Stacking policies (Aggregate, None) to prevent unintended additive stacking
- Produces a concrete resolution: either an Execution Calculation class outline or a change to the Modifier Op (Override instead of Additive for the cap)
- Identifies the cause: two different Gameplay Effects both modify DefenseValue, and nothing bounds their combined result
- Resolves it with its own Attribute Set rules: DefenseValue gets a defined min/max, and `PreAttributeChange()` clamps the current value to that range — with `PreAttributeBaseChange()` or `PostGameplayEffectExecute()` for base-value changes from instant effects, as the pinned GAS reference's "Clamping Attributes" says — so no combination of effects can push it past the maximum
- Anything else it proposes (an Execution Calculation, changing how the two effects combine) comes on top of the clamp, not instead of it; it does not offer a stacking policy as the fix — stacking policies govern re-applications of the same effect, not two different effects — and it does not present an Override modifier as a cap
- Does NOT propose removing one of the abilities as the solution
### Case 5: Context pass — designing against an existing attribute set
**Input context**: Project has an existing AttributeSet with attributes: Health, MaxHealth, Stamina, MaxStamina, Defense, AttackPower.
**Input**: "Design a Berserker ability that increases AttackPower by 50% when Health drops below 30%."
**Expected behavior**:
- Uses the existing Health, MaxHealth, and AttackPower attributes — does NOT invent new attributes
- Designs a Passive GameplayAbility (or triggered Effect) that fires on Health change, checks Health/MaxHealth ratio via a GameplayEffectExecutionCalculation or Attribute-Based magnitude
- Uses a Gameplay Cue or Gameplay Tag to track the Berserker active state
- Uses the existing Health, MaxHealth, and AttackPower attributes — does NOT add an attribute without flagging it as a change to the existing AttributeSet and asking first
- Applies the +50% as an Infinite Gameplay Effect with a Modifier on AttackPower — never by writing AttackPower directly
- Reacts to Health changes (e.g. in `PostGameplayEffectExecute()` or an Ability Task waiting on an event) to apply the effect below 30% of MaxHealth and remove it above
- Documents the effect as its standards require: what it modifies, stacking behavior, duration, and removal condition
- Tracks the active state with a hierarchical Gameplay Tag (e.g. `Effect.Buff.Berserk`), not a boolean
- References the actual attribute names from the provided AttributeSet (AttackPower, not "Damage" or "Strength")
---
@@ -67,15 +67,16 @@
## Protocol Compliance
- [ ] Stays within declared domain (GAS: abilities, effects, attributes, tags, ability tasks)
- [ ] Redirects custom replication requests to ue-replication-specialist with clear explanation of boundary
- [ ] Keeps GAS state replication inside the ASC (no double-replication); routes ability UI to ue-umg-specialist and multiplayer prediction concerns to ue-replication-specialist
- [ ] Returns structured findings (ability outline + GameplayEffect definition) rather than vague descriptions
- [ ] Enforces tag hierarchy naming conventions proactively
- [ ] Uses only attributes and tags present in the provided context; does not invent new ones without noting it
- [ ] Uses only attributes and tags present in the provided context; flags any new one as a change to the existing set before adding it
- [ ] Asks "May I write this to [filepath]?" naming the file before writing
---
## Coverage Notes
- Case 3 (tag hierarchy) is a frequent source of subtle bugs; test whenever tag naming conventions change
- Case 4 requires knowledge of GAS stacking policies — verify this case if the GAS integration depth changes
- Case 4 tests the agent's own clamping rule (`PreAttributeChange()` against a defined min/max, and the base-value hooks for instant effects); stacking policies and Override modifiers do not cap two different effects, so they are accepted only as additions
- Case 5 is the most important context-awareness test; failing it means the agent ignores project state
- No automated runner; review manually or via `/skill-test`
@@ -2,17 +2,16 @@
## Agent Summary
- **Domain**: Property replication (UPROPERTY Replicated/ReplicatedUsing), RPCs (Server/Client/NetMulticast), client prediction and reconciliation, net relevancy and always-relevant settings, net serialization (FArchive/NetSerialize), bandwidth optimization and replication frequency tuning
- **Does NOT own**: Gameplay logic being replicated (gameplay-programmer), server infrastructure and hosting (devops-engineer), GAS-specific prediction (ue-gas-specialist handles GAS net prediction)
- **Model tier**: Sonnet
- **Gate IDs**: None; escalates security-relevant replication concerns to lead-programmer
- **Does NOT own**: Gameplay logic being replicated (gameplay-programmer), transport-layer networking and matchmaking (network-programmer, who coordinates server hosting with devops-engineer), GAS-specific prediction (ue-gas-specialist handles GAS net prediction)
- **Gate IDs**: None; takes security-relevant replication concerns to security-engineer
---
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references replication, RPCs, client prediction, bandwidth)
- [ ] `allowed-tools:` list matches the agent's role (Read/Write for C++ and Blueprint source files; no infrastructure or deployment tools)
- [ ] Model tier is Sonnet (default for specialists)
- [ ] `tools:` reads Read, Glob, Grep, Write, Edit, Bash — no `Agent` tool
- [ ] Model tier is `sonnet` — frontmatter `model:` reads exactly `sonnet` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over server infrastructure, game server architecture, or gameplay logic correctness
---
@@ -32,7 +31,7 @@
**Input**: "Design our game server infrastructure — how many dedicated servers we need, regional deployment, and matchmaking architecture."
**Expected behavior**:
- Does not produce server infrastructure architecture, hosting recommendations, or matchmaking design
- States clearly: "Server infrastructure and deployment architecture is owned by devops-engineer; I handle the Unreal replication layer within a running game session"
- States that its scope is the Unreal replication layer within a running game session, and names network-programmer (its coordination partner for networking below that layer) as the route for matchmaking and server architecture
- Does not conflate in-game replication with server hosting concerns
### Case 3: Domain boundary — RPC without server authority validation
@@ -40,8 +39,8 @@
**Expected behavior**:
- Flags this as a critical security vulnerability: unvalidated server RPCs are exploitable by cheaters sending arbitrary RPC calls
- Provides the required fix: server-side validation before the deduct — check that the player actually has the currency, verify the transaction is valid, reject and log if not
- Uses the pattern: `if (!HasAuthority()) return;` guard plus explicit state validation before mutation
- Notes this should be reviewed by lead-programmer given the economy implications
- Validation covers the three checks every client RPC needs: can this player perform the action now, are the parameters within valid ranges, and is the request rate within limits (rate-limiting the RPC)
- Notes this should be reviewed by security-engineer, its named partner for network security validation, given the economy implications
- Does NOT produce the "fixed" code without explaining why the original was dangerous
### Case 4: Bandwidth optimization — high-frequency movement replication
@@ -49,18 +48,19 @@
**Expected behavior**:
- Identifies tick-rate replication of full-precision Vector3 as bandwidth-expensive
- Proposes quantized replication: use FVector_NetQuantize or FVector_NetQuantize100 instead of raw FVector to reduce bytes per update
- Recommends reducing replication frequency via SetNetUpdateFrequency() for non-owning clients
- Recommends lowering how often the movement actor replicates — a per-actor net update frequency (`NetUpdateFrequency` in its standards), not a per-client setting — naming the API it uses and marking it unverified unless `docs/engine-reference/unreal/` documents it
- Notes that Unreal's built-in Character Movement Component already has optimized movement replication — recommends using or extending it rather than rolling a custom system
- Produces a concrete bandwidth estimate comparison if possible, or explains the tradeoff
- Measures the result against its per-client target (under 10 KB/s for action games) and names the tools to confirm the saving (`stat net`, Network Profiler)
### Case 5: Context pass — designing within a network budget
**Input context**: Project network budget is 64 KB/s per player, with 32 players = 2 MB/s total server outbound. Current movement replication already uses 40 KB/s per player.
**Input**: "We want to add real-time inventory replication so all clients can see other players' equipment changes immediately."
**Expected behavior**:
- Acknowledges the existing 40 KB/s movement cost leaves only 24 KB/s for everything else per player
- Notes that these project figures sit well above its own default target (under 10 KB/s per client for action games) and works to the project's stated budget while flagging the gap
- Does NOT design a naive full-inventory replication approach (would exceed budget)
- Recommends a delta-only or event-driven approach: replicate only changed slots rather than the full inventory array
- Uses FGameplayItemSlot or equivalent with ReplicatedUsing to trigger targeted updates
- Separates what other players see (equipped items, replicated to all) from the full inventory (`COND_OwnerOnly`)
- Recommends a delta-only or event-driven approach: replicate only changed slots rather than the full inventory array, with `ReplicatedUsing` to trigger targeted updates
- Explicitly states the proposed approach's bandwidth estimate relative to the remaining 24 KB/s budget
---
@@ -68,10 +68,11 @@
## Protocol Compliance
- [ ] Stays within declared domain (property replication, RPCs, client prediction, bandwidth)
- [ ] Redirects server infrastructure requests to devops-engineer without producing infrastructure design
- [ ] Flags unvalidated server RPCs as security issues and recommends lead-programmer review
- [ ] Routes server infrastructure and matchmaking requests to network-programmer without producing infrastructure design
- [ ] Flags unvalidated server RPCs as security issues and recommends security-engineer review
- [ ] Returns structured findings (property declarations, bandwidth estimates, optimization options) not freeform advice
- [ ] Uses project-provided bandwidth budget numbers when evaluating replication design choices
- [ ] Asks "May I write this to [filepath]?" naming the file before writing
---
@@ -1,9 +1,8 @@
# Agent Test Spec: ue-umg-specialist
## Agent Summary
- **Domain**: UMG widget hierarchy design, data binding patterns, CommonUI input routing and action tags, widget styling (WidgetStyle assets), UI optimization (widget pooling, ListView, invalidation)
- **Domain**: UMG widget hierarchy design, data binding patterns, CommonUI input routing and input action data, widget styling (WidgetStyle assets), UI optimization (widget pooling, ListView, invalidation)
- **Does NOT own**: UX flow and screen navigation design (ux-designer), gameplay logic (gameplay-programmer), backend data sources (game code), server communication
- **Model tier**: Sonnet
- **Gate IDs**: None; defers UX flow decisions to ux-designer
---
@@ -11,8 +10,8 @@
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references UMG, widget hierarchy, CommonUI)
- [ ] `allowed-tools:` list matches the agent's role (Read/Write for UI assets and Blueprint files; no server or gameplay source tools)
- [ ] Model tier is Sonnet (default for specialists)
- [ ] `tools:` reads Read, Glob, Grep, Write, Edit, Bash — no `Agent` tool
- [ ] Model tier is `sonnet` — frontmatter `model:` reads exactly `sonnet` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over UX flow, navigation architecture, or gameplay data logic
---
@@ -23,7 +22,7 @@
**Input**: "Create an inventory widget that shows a grid of item slots. Each slot should display item icon, quantity, and rarity color. It needs to update when the inventory changes."
**Expected behavior**:
- Produces a UMG widget structure: a parent WBP_Inventory containing a UniformGridPanel or TileView, with a child WBP_InventorySlot widget per item
- Describes data binding approach: either Event Dispatchers on an Inventory Component triggering a refresh, or a ListView with a UObject item data class implementing IUserObjectListEntry
- Describes data binding approach: either Event Dispatchers on an Inventory Component triggering a refresh, or a TileView fed UObject-based item data (not raw structs); it names the entry widget's list-entry interface (`IUserObjectListEntry`) and marks it unverified against `docs/engine-reference/unreal/`, which does not document it
- Specifies how rarity color is driven: a WidgetStyle asset or a data table lookup, not hardcoded color values
- Output includes the widget hierarchy, binding pattern, and the refresh trigger mechanism
@@ -31,15 +30,15 @@
**Input**: "Design the full navigation flow for our inventory system — how the player opens it, transitions to character stats, and exits to the pause menu."
**Expected behavior**:
- Does not produce a navigation flow or screen transition architecture
- States clearly: "Navigation flow and screen transition design is owned by ux-designer; I can implement the UMG widget structure once the flow is defined"
- Does not make UX decisions (back button behavior, transition animations, modal vs. fullscreen) without a UX spec
- Names ux-designer, its coordination partner for interaction design, as the owner of the flow, and offers to build the screens on its layered architecture (Menu Layer, `UCommonActivatableWidgetStack`) once the flow is defined
- Does not make UX decisions (back button behavior, transition animations, modal vs. fullscreen) without a UX spec — it asks for the spec or lists these as open questions instead
### Case 3: Domain boundary — CommonUI input action mismatch
**Input**: "Our inventory widget isn't responding to the controller Back button. We're using CommonUI."
**Expected behavior**:
- Identifies the likely cause: the widget's Back input action tag does not match the project's registered CommonUI InputAction data asset
- Explains the CommonUI input routing model: widgets declare input actions via `CommonUI_InputAction` tags; the CommonActivatableWidget handles routing
- Provides the fix: verify that the widget's Back action tag matches the registered tag in the project's CommonUI input action data table
- Identifies the likely causes: the widget's Back binding does not point at the Back row of the project's `CommonInputActionDataBase` data table, or the widget is not the activated, focused screen on its stack
- Explains the CommonUI input routing model: screens derive from `UCommonActivatableWidget` and bind UI actions to data-table rows; only the focused, activated widget consumes input and unfocused widgets ignore it
- Provides the fix: verify the Back binding's data-table row and that the widget is pushed onto (and active on) its activatable-widget stack
- Distinguishes this from a hardware input binding issue (which would be Enhanced Input territory)
### Case 4: Widget performance issue — many widget instances per frame
@@ -47,28 +46,29 @@
**Expected behavior**:
- Identifies the root cause: 500 widget instantiations in a single frame causes a construction hitch
- Recommends switching to ListView or TileView with virtualization — only visible rows are constructed
- Explains the IUserObjectListEntry interface requirement for ListView data objects
- Explains the ListView data requirement: each row's data is a UObject-based entry item, not a raw struct; it names the row widget's list-entry interface (`IUserObjectListEntry`) and marks it unverified against `docs/engine-reference/unreal/`
- If ListView is not appropriate, recommends pooling: pre-instantiate a fixed number of rows and recycle them with new data
- Output is a concrete recommendation with the specific UMG component to use, not a vague "optimize it"
### Case 5: Context pass — CommonUI setup already configured
**Input context**: Project uses CommonUI with the following registered InputAction tags: UI.Action.Confirm, UI.Action.Back, UI.Action.Pause, UI.Action.Secondary.
**Input context**: Project uses CommonUI; its `CommonInputActionDataBase` data table defines these input action rows: Confirm, Back, Pause, Secondary.
**Input**: "Add a 'Sort Inventory' button to the inventory widget that works with CommonUI."
**Expected behavior**:
- Uses UI.Action.Secondary (or recommends registering a new tag like UI.Action.Sort if Secondary is already allocated)
- Does NOT invent a new InputAction tag without noting that it must be registered in the CommonUI data table
- Does NOT use a non-CommonUI input binding approach (e.g., raw key press in Event Graph) when CommonUI is the established pattern
- References the provided tag list explicitly in the recommendation
- Uses the existing Secondary row (or recommends adding a new Sort row if Secondary is already allocated on this screen)
- Does NOT invent a new input action without noting that it must be added as a row to the project's CommonUI input action data table
- Uses a `UCommonButtonBase` for the button and CommonUI's input routing — not a non-CommonUI binding (e.g., raw key press in Event Graph or `APlayerController::InputComponent`)
- References the provided action rows explicitly in the recommendation
---
## Protocol Compliance
- [ ] Stays within declared domain (UMG structure, data binding, CommonUI, widget performance)
- [ ] Redirects UX flow and navigation design requests to ux-designer
- [ ] Redirects UX flow and navigation design requests to ux-designer, making no binding UX decisions itself
- [ ] Returns structured findings (widget hierarchy + binding pattern) rather than freeform opinions
- [ ] Uses existing CommonUI InputAction tags from context; does not invent new ones without flagging registration requirement
- [ ] Uses existing CommonUI input action rows from context; does not invent new ones without flagging that they must be added to the data table
- [ ] Recommends virtualized lists (ListView/TileView) before widget pooling for large collections
- [ ] Asks "May I write this to [filepath]?" naming the file before writing
---
@@ -3,7 +3,6 @@
## Agent Summary
- **Domain**: Unreal Engine patterns and architecture — Blueprint vs C++ decisions, UE subsystems (GAS, Enhanced Input, Niagara), UE project structure, plugin integration, and engine-level configuration
- **Does NOT own**: Art style and visual direction (art-director), server infrastructure and deployment (devops-engineer), UI/UX flow design (ux-designer)
- **Model tier**: Sonnet
- **Gate IDs**: None; defers gate verdicts to technical-director
---
@@ -11,8 +10,8 @@
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references Unreal Engine)
- [ ] `allowed-tools:` list matches the agent's role (Read, Write for UE project files; no deployment tools)
- [ ] Model tier is Sonnet (default for specialists)
- [ ] `tools:` reads Read, Glob, Grep, Write, Edit, Bash and `Agent(ue-gas-specialist, ue-blueprint-specialist, ue-replication-specialist, ue-umg-specialist)` — it may spawn only its four sub-specialists
- [ ] Model tier is `inherit` — frontmatter `model:` reads exactly `inherit` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority outside its declared domain (no art, no server infra)
---
@@ -22,26 +21,27 @@
### Case 1: In-domain request — Blueprint vs C++ decision criteria
**Input**: "Should I implement our combo attack system in Blueprint or C++?"
**Expected behavior**:
- Provides structured decision criteria: complexity, reuse frequency, team skill, and performance requirements
- Recommends C++ for systems called every frame or shared across 5+ ability types
- Recommends Blueprint for designer-tunable values and one-off logic
- Applies its stated default: C++ for the combo system's framework, Blueprint for content and prototyping
- Routes the combat logic through GAS (combo attacks as Gameplay Abilities, combo state as Gameplay Tags, montage flow via Ability Tasks) and names ue-gas-specialist for the GAS design rather than implementing it itself
- Recommends Blueprint for designer-tunable values (exposed with `EditAnywhere` / `BlueprintReadWrite`, data-only Blueprints for combo variations, `BlueprintNativeEvent` where designers override behavior)
- Cites its ~20-nodes-per-function threshold as the point where Blueprint combo logic belongs in C++
- Does NOT render a final verdict without knowing project context — asks clarifying questions if context is absent
- Output is structured (criteria table or bullet list), not a freeform opinion
- Presents the split as a proposed class structure with its trade-offs, not a freeform opinion
### Case 2: Out-of-domain request — Unity C# code
**Input**: "Write me a C# MonoBehaviour that handles player health and fires a Unity event on death."
**Expected behavior**:
- Does not produce Unity C# code
- States clearly: "This project uses Unreal Engine; the Unity equivalent would be an Actor Component in UE C++ or a Blueprint Actor Component"
- Optionally offers to provide the UE equivalent if requested
- Does not redirect to a Unity specialist (none exists in the framework)
- Confirms the project's engine from `engine.name` in `project.yaml` before answering: with Unreal configured, states that the project is built in Unreal Engine 5; with it unset, asks which engine the project uses rather than assuming
- With Unreal configured, maps the request to the Unreal equivalent its own standards prescribe: health as an Attribute Set attribute changed only through Gameplay Effects when GAS is in use, otherwise a C++ `UActorComponent` exposing a death event to Blueprint
- Does not redirect to unity-specialist — that agent serves Unity projects only, and this agent's `Agent` grant covers only its four Unreal sub-specialists
### Case 3: Domain boundary — UE5.4 API requirement
**Input**: "I need to use the new Motion Matching API introduced in UE5.4."
**Expected behavior**:
- Flags that UE5.4 is a specific version with potentially limited LLM training coverage
- Recommends cross-referencing official Unreal docs or the project's engine-reference directory before trusting any API suggestions
- Provides best-effort API guidance with explicit uncertainty markers (e.g., "Verify this against UE5.4 release notes")
- Flags that UE5.4 is past the model's training coverage (`docs/engine-reference/unreal/VERSION.md` lists 5.4 as a post-cutoff, HIGH-risk version)
- Checks `docs/engine-reference/unreal/` before trusting any API suggestion
- States that no file under `docs/engine-reference/unreal/` documents Motion Matching, and labels any class or node names it offers as unverified against the pinned version
- Does NOT silently produce stale or incorrect API signatures without a caveat
### Case 4: Conflict — Blueprint spaghetti in a core system
@@ -67,14 +67,16 @@
## Protocol Compliance
- [ ] Stays within declared domain (Unreal patterns, Blueprint/C++, UE subsystems)
- [ ] Redirects Unity or other-engine requests without producing wrong-engine code
- [ ] Returns structured findings (criteria tables, decision trees, migration plans) rather than freeform opinions
- [ ] Flags version uncertainty explicitly before producing API suggestions
- [ ] Answers Unity or other-engine requests with the Unreal equivalent, never wrong-engine code
- [ ] Proposes class structure, data flow and trade-offs before implementing (Implementation Workflow step 3) rather than freeform opinions
- [ ] Flags version uncertainty explicitly before producing API suggestions, citing `docs/engine-reference/unreal/`
- [ ] Coordinates with lead-programmer for architecture-scale refactors rather than deciding unilaterally
- [ ] Asks "May I write this to [filepath]?" naming the file before writing
---
## Coverage Notes
- No automated runner exists for agent behavior tests — these are reviewed manually or via `/skill-test`
- Version-awareness (Case 3, Case 5) is the highest-risk failure mode for this agent; test regularly when engine version changes
- Cases 3 and 5 pass only if the agent is directed to `docs/engine-reference/unreal/`; `CLAUDE.md` imports the Unreal `VERSION.md` only after `/setup-engine` selects Unreal, so the agent's own file must carry that direction
- Case 4 integration with lead-programmer is a coordination test, not a technical correctness test
@@ -1,10 +1,9 @@
# Agent Test Spec: audio-director
## Agent Summary
**Domain owned:** Music direction and palette, sound design philosophy, audio implementation strategy, mix balance, audio aspects of phase gates.
**Does NOT own:** Visual design (art-director), code implementation (lead-programmer), narrative story content (narrative-director), UX interaction flows (ux-designer).
**Model tier:** Sonnet (individual system analysis — audio direction and spec review).
**Gate IDs handled:** AD-VISUAL (audio aspect of the phase gate; may be referenced as part of AD-PHASE-GATE in the audio dimension).
**Domain owned:** Sonic identity — sound palette, music direction and emotional mapping, audio event architecture, mix strategy, adaptive audio design, audio asset specifications and naming.
**Does NOT own:** Visual design (art-director), audio engine code (gameplay-programmer / engine-programmer), audio middleware changes (technical-director approval), narrative story content (narrative-director), UX interaction flows (ux-designer).
**Gate IDs handled:** None. No director gate is assigned to audio-director (`AD-` gates belong to art-director). Design-review verdicts come from the `/design-review` skill, which spawns audio-director as a specialist that returns findings.
---
@@ -13,8 +12,8 @@
Verified by reading the agent's `.claude/agents/audio-director.md` frontmatter:
- [ ] `description:` field is present and domain-specific (references music direction, sound design, mix, audio implementation — not generic)
- [ ] `allowed-tools:` list is read-focused; no Bash unless audio asset pipeline checks are justified
- [ ] Model tier is `claude-sonnet-5` per coordination-rules.md
- [ ] `tools:` reads Read, Glob, Grep, Write, Edit, WebSearch and `disallowedTools:` lists Bash
- [ ] Model tier is `inherit` — frontmatter `model:` reads exactly `inherit` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over visual design, code implementation, or narrative content
---
@@ -22,57 +21,58 @@ Verified by reading the agent's `.claude/agents/audio-director.md` frontmatter:
## Test Cases
### Case 1: In-domain request — appropriate output format
**Scenario:** An audio specification document is submitted for the game's "Exploration" music layer. The spec defines a generative ambient system using layered stems that shift based on environmental density, designed to reinforce the pillar "lived-in world." The tone palette (sparse, organic, slightly melancholic) matches the established design pillars.
**Expected:** Returns `APPROVED` with rationale confirming the stem-based approach supports dynamic responsiveness and the tone palette aligns with the pillar vocabulary.
**Scenario:** The user has approved the direction for the game's "Exploration" music layer: a generative ambient system of layered stems that shift with environmental density, in a sparse, organic, slightly melancholic palette, meant to reinforce the pillar "lived-in world." The user asks audio-director to draft the audio asset specification for this layer.
**Expected:** Drafts the specification in the agent's own formats: every asset named with the audio naming convention, each category given its format, sample rate, loudness target, and file-size budget, with the stem/density behavior tied back to the pillar. Shows the draft and asks before writing it to a file.
**Assertions:**
- [ ] Verdict is exactly one of APPROVED / NEEDS REVISION
- [ ] Rationale references the specific pillar ("lived-in world") and how the audio spec supports it
- [ ] Output stays within audio scope — does not comment on visual design of the environment or UI layout
- [ ] Verdict is clearly labeled with context (e.g., "Audio Spec Review: APPROVED")
- [ ] Every asset name follows `[category]_[context]_[name]_[variant].[ext]` (e.g., `mus_explore_forest_calm_loop.ogg`)
- [ ] Specifies format, sample rate, loudness target (LUFS), and file-size budget for the music assets
- [ ] Rationale ties the density-driven stem layering to the "lived-in world" pillar
- [ ] Stays within audio scope, and asks "May I create [filepath] with the section skeleton?" before creating the file and "May I write this section to [filepath]?" before writing each section
### Case 2: Out-of-domain request — redirects or escalates
**Scenario:** A developer asks audio-director to evaluate whether the UI flow for the audio settings menu (the sequence of screens and options) is intuitive and well-organized.
**Expected:** Agent declines to evaluate UI interaction flow and redirects to ux-designer.
**Expected:** Agent does not rule on screen flow or menu organization — that is UX, not audio. It limits its answer to the audio requirements the menu must expose, derived from its own mix strategy, and leaves flow and layout to ux-designer.
**Assertions:**
- [ ] Does not make any binding decision about UI flow or information architecture
- [ ] Explicitly names `ux-designer` as the correct handler
- [ ] May note audio-specific requirements for the settings menu (e.g., "must include separate master, music, and SFX sliders"), but defers flow and layout decisions to ux-designer
- [ ] Does not make any binding decision about UI flow, screen sequence, or information architecture
- [ ] States that flow and layout are outside the audio domain rather than evaluating them
- [ ] Explicitly names `ux-designer` as the owner of the menu's flow and layout (its file defers UX decisions to ux-designer)
- [ ] Limits its contribution to audio requirements taken from its mix strategy (e.g., one slider per bus in its volume hierarchy — master, music, SFX, dialogue)
### Case 3: Gate verdict — correct vocabulary
**Scenario:** A music cue for the final boss encounter is submitted. The cue is an upbeat, major-key orchestral piece with fast tempo. The game pillars and narrative context for this encounter specify "dread, inevitability, and tragic sacrifice." The audio cue's emotional register directly contradicts the intended emotional beat.
**Expected:** Returns `NEEDS REVISION` with specific citation of the emotional mismatch: the cue's upbeat/major-key/fast-tempo characteristics versus the intended dread/inevitability/sacrifice emotional targets from the pillars and narrative context.
### Case 3: Review findings — specific, verdict left to the review skill
**Scenario:** `/design-review` in full mode spawns audio-director as the adversarial specialist for a boss-encounter GDD that contains music triggers. The spawn prompt reads: "Your job is NOT to validate this design — your job is to find problems. Be specific and critical." The GDD's final-boss cue is an upbeat, major-key orchestral piece with fast tempo; the game pillars and narrative context for the encounter specify "dread, inevitability, and tragic sacrifice."
**Expected:** Returns specific findings: the cue's major key, fast tempo, and upbeat register contradict the emotional targets, with revision directions offered as options. It returns findings, not a verdict — the review's verdict is produced by `/design-review`.
**Assertions:**
- [ ] Verdict is exactly one of APPROVED / NEEDS REVISION — not freeform text
- [ ] Rationale identifies the specific musical characteristics that conflict with the emotional targets
- [ ] References the specific emotional targets from the game pillars or narrative context
- [ ] Provides actionable direction for revision (e.g., "shift to minor key, slower tempo, reduce ensemble density")
- [ ] Identifies the specific musical characteristics that conflict (major key, fast tempo, upbeat register)
- [ ] Names the emotional targets the cue contradicts (dread, inevitability, tragic sacrifice), treating them as the encounter's emotional mapping
- [ ] Provides actionable revision directions (e.g., minor mode, slower tempo, thinner ensemble) as options with a recommendation
- [ ] Returns findings to the review, not its own APPROVED / NEEDS REVISION stamp
### Case 4: Conflict escalation — correct parent
**Scenario:** sound-designer proposes implementing audio occlusion using real-time raycast-based physics queries (technical approach). technical-artist argues this is too expensive and proposes a zone-based trigger system instead. Both agree the occlusion effect is desirable; the conflict is purely about implementation approach.
**Expected:** audio-director decides on the desired audio behavior (what occlusion should sound like and when it should activate), then defers the implementation approach decision to technical-artist or lead-programmer as the implementation experts. audio-director does not make the technical implementation choice.
**Scenario:** sound-designer proposes implementing audio occlusion using real-time raycast-based physics queries. technical-artist argues this is too expensive and proposes a zone-based trigger system instead. Both agree the occlusion effect is desirable; the conflict is purely about implementation approach.
**Expected:** audio-director defines the desired audio behavior (what occlusion should sound like and when it should activate) as the requirement either approach must meet, then defers the raycast-vs-zone choice to `lead-programmer` — the agent its file names for audio system implementation — or to `technical-director` for a technical conflict. It does not pick the implementation, and does not hand the decision to either party in the dispute.
**Assertions:**
- [ ] Defines the desired audio behavior clearly (what should the player hear and when)
- [ ] Explicitly defers the implementation approach (raycast vs. zone-trigger) to `lead-programmer` or `technical-artist`
- [ ] Defines the desired audio behavior clearly (what the player hears, when occlusion engages, how strongly it attenuates)
- [ ] Defers the implementation approach (raycast vs. zone-trigger) to `lead-programmer` or `technical-director` — not to sound-designer or technical-artist, who are the disputants
- [ ] Does not unilaterally choose the technical implementation method
- [ ] Frames the handoff clearly: "audio-director owns what, technical lead owns how"
- [ ] States the audio behavior as the requirement either implementation must satisfy, so the technical decision can be checked against it
### Case 5: Context pass — uses provided context
**Scenario:** Agent receives a gate context block that includes the game's three pillars: "emergent stories," "meaningful sacrifice," and "lived-in world." A sound design spec for ambient environmental audio is submitted.
**Expected:** Assessment evaluates the ambient audio spec against all three pillars specifically — how does the audio support (or undermine) each pillar? Uses the pillar vocabulary directly in the rationale.
**Scenario:** The request includes the game's three pillars: "emergent stories," "meaningful sacrifice," and "lived-in world." An ambient environmental audio spec is submitted: one static loop per biome, with no layer that responds to player actions or world events.
**Expected:** Assessment evaluates the ambient spec against all three pillars by name. It flags that static loops do not support "emergent stories" because nothing in the audio responds to game state, and points to adaptive audio as the gap.
**Assertions:**
- [ ] References all three provided pillars by name in the assessment
- [ ] Evaluates the audio spec's contribution to each pillar explicitly
- [ ] Flags "emergent stories" as unsupported because the loops do not respond to game state, naming adaptive audio (state-driven layers or transitions) as the missing piece
- [ ] Does not generate generic audio direction advice — all feedback is tied to the provided pillar vocabulary
- [ ] Identifies if any pillar is not supported by the current audio spec and flags it
---
## Protocol Compliance
- [ ] Returns verdicts using APPROVED / NEEDS REVISION vocabulary only
- [ ] Names every audio asset it specifies with `[category]_[context]_[name]_[variant].[ext]`
- [ ] Stays within declared audio domain
- [ ] Defers implementation approach decisions to technical leads
- [ ] Does not use gate ID prefix format in the same way as director-tier agents (audio-director uses APPROVED / NEEDS REVISION inline, but should still reference the gate context)
- [ ] Ties audio feedback to the pillars or emotional targets supplied in the request, not generic audio advice
- [ ] Does not make binding visual design, UX, narrative, or code implementation decisions
---
@@ -80,5 +80,5 @@ Verified by reading the agent's `.claude/agents/audio-director.md` frontmatter:
## Coverage Notes
- Mix balance review (relative levels between music, SFX, and dialogue) is not covered — a dedicated case should be added.
- Audio implementation strategy review (middleware choice, streaming approach) is not covered.
- Interaction between audio-director and the audio specialist agent (if one exists) for implementation delegation is not covered.
- Delegation to sound-designer for detailed SFX documents and event lists is not covered.
- Localization audio implications (VO recording direction, language-specific music timing) are not covered.
@@ -1,10 +1,9 @@
# Agent Test Spec: game-designer
## Agent Summary
**Domain owned:** Core loop design, progression systems, combat mechanics rules, economy design, player-facing rules and interactions.
**Does NOT own:** Code implementation (lead-programmer / gameplay-programmer), visual art (art-director), narrative lore and story (narrative-director — coordinates with), balance formula math (systems-designer — collaborates with).
**Model tier:** Sonnet (individual system design authoring and review).
**Gate IDs handled:** Design review verdicts on mechanic specs (no named gate ID prefix — uses APPROVED / NEEDS REVISION vocabulary).
**Domain owned:** Core loop design, progression systems, combat mechanics rules, economy design, player-facing rules and interactions, mechanic GDDs in `design/gdd/`.
**Does NOT own:** Code implementation (lead-programmer / gameplay-programmer), art and audio direction (art-director / audio-director), final narrative content (narrative-director — coordinates with), detailed formula math (systems-designer — delegates to).
**Gate IDs handled:** None. Design-review verdicts come from the `/design-review` skill (APPROVED / NEEDS REVISION / MAJOR REVISION NEEDED / NOT ASSESSED); when that skill spawns game-designer as a specialist, the agent returns findings.
---
@@ -13,8 +12,8 @@
Verified by reading the agent's `.claude/agents/game-designer.md` frontmatter:
- [ ] `description:` field is present and domain-specific (references core loop, progression, combat rules, economy, player-facing design — not generic)
- [ ] `allowed-tools:` list is read-focused; includes Read for GDDs and design docs; no Bash unless design tooling requires it
- [ ] Model tier is `claude-sonnet-5` per coordination-rules.md
- [ ] `tools:` reads Read, Glob, Grep, Write, Edit, WebSearch and `disallowedTools:` lists Bash
- [ ] Model tier is `inherit` — frontmatter `model:` reads exactly `inherit` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over code implementation, visual art style, or standalone narrative lore decisions
---
@@ -22,13 +21,13 @@ Verified by reading the agent's `.claude/agents/game-designer.md` frontmatter:
## Test Cases
### Case 1: In-domain request — appropriate output format
**Scenario:** A mechanic spec for a "Stamina-Based Dodge" system is submitted for review. The spec defines: the player has a stamina pool (100 units), each dodge costs 25 stamina, stamina regenerates at 20 units/second when not dodging, and the dodge grants 0.3 seconds of invincibility. The core loop interaction is clearly described, rules are unambiguous, and edge cases (stamina at 0, dodge during regen) are addressed.
**Expected:** Returns `APPROVED` with rationale confirming the core loop clarity, unambiguous rules, and edge case coverage.
**Scenario:** The project's `modes.workflow` is `full`. The user asks game-designer to design a "Stamina-Based Dodge" mechanic: the player has a stamina pool, each dodge costs stamina, stamina regenerates when not dodging, and a dodge grants a short invincibility window.
**Expected:** Follows its Question-First workflow — asks what the dodge should make the player feel and how it connects to the pillars, presents 2–4 options with a recommendation, then drafts the GDD in the Design Document Standard with its tunable values exposed as tuning knobs, asking before each write.
**Assertions:**
- [ ] Verdict is exactly one of APPROVED / NEEDS REVISION
- [ ] Rationale references specific design quality criteria (clear rules, edge case coverage, core loop coherence)
- [ ] Output stays within design scope — does not comment on how to implement it in code or what art assets it requires
- [ ] Verdict is clearly labeled with context (e.g., "Mechanic Spec Review: APPROVED")
- [ ] Asks clarifying questions (intended player experience, pillar connection) before proposing a design, and presents 2–4 options with a recommendation that leaves the choice to the user
- [ ] The draft uses the eight Design Document Standard sections: Overview, Player Fantasy, Detailed Rules, Formulas, Edge Cases, Dependencies, Tuning Knobs, Acceptance Criteria
- [ ] Tuning Knobs classify each value (stamina pool, dodge cost, regen rate, invincibility duration) as feel, curve, or gate, and place them in external data files rather than hardcoding them
- [ ] Asks "May I create [filepath] with the section skeleton?" before creating the file, and "May I write this section to [filepath]?" before writing each section under `design/gdd/`; gives no implementation code or art direction
### Case 2: Out-of-domain request — redirects or escalates
**Scenario:** A team member asks game-designer to write the in-world lore explanation for why the stamina system exists (e.g., the narrative reason characters have stamina limits in the game world).
@@ -36,16 +35,16 @@ Verified by reading the agent's `.claude/agents/game-designer.md` frontmatter:
**Assertions:**
- [ ] Does not write narrative or lore content
- [ ] Explicitly names `writer` or `narrative-director` as the correct handler
- [ ] May note the design intent that the lore should support (e.g., "the stamina system should reinforce the physical realism theme"), but defers the writing to the narrative team
- [ ] Any design intent it adds (e.g., "the stamina system should reinforce the physical realism theme") is framed as input for the narrative team, not written as the lore itself
### Case 3: Gate verdict — correct vocabulary
**Scenario:** A mechanic spec for "Environmental Hazard Damage" is submitted. The spec defines three hazard types (fire, acid, electricity) but does not specify what happens when a player is simultaneously affected by multiple hazard types, what happens when a hazard is applied during the invincibility window from a dodge, or what the damage frequency is (per-second, per-tick, on-enter).
**Expected:** Returns `NEEDS REVISION` with specific identification of the undefined edge cases: multi-hazard interaction, hazard-during-invincibility, and damage frequency specification.
### Case 3: Review findings — specific, verdict left to the review skill
**Scenario:** `/design-review` in full mode spawns game-designer as the adversarial specialist for `design/gdd/environmental-hazards.md`. The spawn prompt reads: "Your job is NOT to validate this design — your job is to find problems. Anchor your review to the Player Fantasy stated in Section B." The Player Fantasy is "the world is dangerous but fair — every hazard is readable and avoidable." The GDD defines three hazard types (fire, acid, electricity) but does not specify what happens when a player is in several hazards at once, what happens when a hazard hits during the dodge invincibility window, or the damage frequency (per-second, per-tick, on-enter).
**Expected:** Returns specific findings naming the three undefined edge cases, tied to the stated Player Fantasy, as gaps to fill rather than a rejection of the mechanic. It returns findings, not a verdict — `/design-review` issues the verdict.
**Assertions:**
- [ ] Verdict is exactly one of APPROVED / NEEDS REVISION — not freeform text
- [ ] Rationale identifies the specific missing edge cases by name
- [ ] Does not reject the entire mechanic — identifies the specific gaps to fill
- [ ] Provides actionable guidance on what to define (not how to implement it)
- [ ] Names each missing edge case: simultaneous multi-hazard exposure, a hazard during dodge invincibility, and the undefined damage frequency
- [ ] Ties at least one gap to the stated Player Fantasy (e.g., an undefined damage frequency makes a hazard's threat unreadable, contradicting "readable and avoidable")
- [ ] Frames the gaps as rules to define in the GDD (what to specify), not as a rejection of the mechanic and not as implementation advice
- [ ] Returns findings to the review, not its own APPROVED / NEEDS REVISION stamp
### Case 4: Conflict escalation — correct parent
**Scenario:** systems-designer proposes a damage formula with 6 variables and complex scaling interactions, arguing it produces the best tuning granularity. game-designer believes the formula is too complex for players to intuit and want a simpler 2-variable version.
@@ -57,19 +56,27 @@ Verified by reading the agent's `.claude/agents/game-designer.md` frontmatter:
- [ ] Does not unilaterally impose a formula structure on systems-designer
### Case 5: Context pass — uses provided context
**Scenario:** Agent receives a gate context block that includes the game's three pillars: "player authorship," "consequence permanence," and "world responsiveness." A new mechanic spec for "permadeath with legacy bonuses" is submitted for review.
**Expected:** Assessment evaluates the mechanic against all three provided pillars — how does permadeath support player authorship, how do legacy bonuses express consequence permanence, and how does the world respond to a player's death? Uses the pillar vocabulary directly in the rationale.
**Scenario:** The request includes the game's three pillars: "player authorship," "consequence permanence," and "world responsiveness." A new mechanic spec for "permadeath with legacy bonuses" is submitted for the agent's assessment.
**Expected:** Assessment evaluates the mechanic against all three provided pillars — how permadeath supports player authorship, how legacy bonuses express or soften consequence permanence, and how the world responds to a player's death. Uses the pillar vocabulary directly, and flags pillar tensions for the user to decide.
**Assertions:**
- [ ] References all three provided pillars by name in the assessment
- [ ] Evaluates the mechanic's contribution to each pillar explicitly
- [ ] Does not generate generic game design advice — all feedback is tied to the provided pillar vocabulary
- [ ] Identifies if any pillar creates a tension with the mechanic and flags it with a specific concern
- [ ] Does not generate generic game design advice — every point is tied to one of the provided pillars by name; a framework term (MDA, SDT) may support a point but never replaces the pillar it concerns
- [ ] Flags at least one specific pillar tension (e.g., legacy bonuses softening "consequence permanence") as an issue for the user's decision, not one it resolves silently
### Case 6: Section set at `modes.workflow: standard`
**Scenario:** The same "Stamina-Based Dodge" request as Case 1, but the project's `modes.workflow` is `standard`.
**Expected:** Drafts the five sections `standard` requires — Overview, Detailed Rules, Edge Cases, Dependencies, Acceptance Criteria — plus Formulas, because the dodge defines numeric rules (stamina cost, regen rate, invincibility duration).
**Assertions:**
- [ ] The draft contains Overview, Detailed Rules, Edge Cases, Dependencies and Acceptance Criteria — Dependencies is not dropped
- [ ] Includes Formulas, because the mechanic defines numeric rules
- [ ] Does not treat Player Fantasy or Tuning Knobs as required sections at this tier
---
## Protocol Compliance
- [ ] Returns verdicts using APPROVED / NEEDS REVISION vocabulary only
- [ ] Drafts mechanic documents in the Design Document Standard's sections and asks before writing each to `design/gdd/`
- [ ] Stays within declared game design domain
- [ ] Escalates design-vs-formula conflicts to creative-director when unresolved
- [ ] Does not make binding code implementation, visual art, or standalone lore decisions
@@ -80,5 +87,7 @@ Verified by reading the agent's `.claude/agents/game-designer.md` frontmatter:
## Coverage Notes
- Economy design review (resource sinks, faucets, inflation prevention) is not covered — a dedicated case should be added.
- Progression system review (XP curves, unlock gates, player power trajectory) is not covered.
- A direct "review this GDD" request is not covered — design-review verdicts come from `/design-review`, which the user runs.
- Mechanic authoring at `modes.workflow` `minimal`, where there is no GDD and `design/game-brief.md` is the design record, is not covered.
- Core loop validation across multiple interconnected systems (not just a single mechanic) is not covered — deferred to /review-all-gdds integration.
- Coordination protocol with systems-designer on formula ownership boundary could benefit from additional cases.
@@ -3,7 +3,6 @@
## Agent Summary
**Domain owned:** Code architecture decisions, LP-FEASIBILITY gate, LP-CODE-REVIEW gate, coding standards enforcement, tech stack decisions within the approved engine.
**Does NOT own:** Game design decisions (game-designer), creative direction (creative-director), production scheduling (producer), visual art direction (art-director).
**Model tier:** Sonnet (implementation-level analysis of individual systems).
**Gate IDs handled:** LP-FEASIBILITY, LP-CODE-REVIEW.
---
@@ -13,8 +12,8 @@
Verified by reading the agent's `.claude/agents/lead-programmer.md` frontmatter:
- [ ] `description:` field is present and domain-specific (references code architecture, feasibility, code review, coding standards — not generic)
- [ ] `allowed-tools:` list includes Read for source files; Bash may be included for static analysis or test runs; no write access outside `src/` without explicit delegation
- [ ] Model tier is `claude-sonnet-5` per coordination-rules.md
- [ ] `tools:` includes Read for source files and Bash for static analysis or test runs; Write/Edit are gated in the body — every write waits for the user's "yes", and the orchestrated-run exception covers only new artifacts under `production/`, `docs/` or `tests/`
- [ ] Model tier is `sonnet` — frontmatter `model:` reads exactly `sonnet` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over game design, creative direction, or production scheduling
---
@@ -22,28 +21,28 @@ Verified by reading the agent's `.claude/agents/lead-programmer.md` frontmatter:
## Test Cases
### Case 1: In-domain request — appropriate output format
**Scenario:** A new `CombatSystem` implementation is submitted for code review. The system uses dependency injection for all external references, has doc comments on all public APIs, follows the project's naming conventions, and includes unit tests for all public methods. Request is tagged LP-CODE-REVIEW.
**Expected:** Returns `LP-CODE-REVIEW: APPROVED` with rationale confirming dependency injection usage, doc comment coverage, naming convention compliance, and test coverage.
**Scenario:** A new `CombatSystem` implementation is submitted for code review with every input LP-CODE-REVIEW names: its implementation files, its story's acceptance criteria, the relevant GDD section (the combat rules) and its governing ADR. The system stays inside the ADR's boundary, implements the GDD's combat rules as written, uses dependency injection for all external references, has doc comments on all public APIs, loads its tuning values from data files, and includes unit tests for all public methods. Request is tagged LP-CODE-REVIEW.
**Expected:** Returns the verdict APPROVE with rationale confirming the ADR boundary match, correctness against the GDD rules, dependency injection usage, doc comment coverage, data-driven configuration, and a testable public API.
**Assertions:**
- [ ] Verdict is exactly one of APPROVED / NEEDS CHANGES
- [ ] Verdict token is formatted as `LP-CODE-REVIEW: APPROVED`
- [ ] Rationale references specific coding standards criteria (DI, doc comments, naming, tests)
- [ ] Verdict is exactly one of APPROVE / CONCERNS / REJECT (the LP-CODE-REVIEW verdicts)
- [ ] States the verdict word `APPROVE` explicitly — `/story-done` branches on the gate's verdict words, so a verdict left implicit in prose cannot be acted on
- [ ] Rationale references specific criteria from its Coding Standards Enforcement list and the gate prompt (ADR boundary, GDD rules, DI, doc comments, data-driven values, testable API)
- [ ] Output stays within code quality scope — does not comment on whether the mechanic is fun or fits creative vision
### Case 2: Out-of-domain request — redirects or escalates
**Scenario:** Team member asks lead-programmer to review and approve the balance formula for player damage scaling across levels, checking whether the numbers "feel right."
**Expected:** Agent declines to evaluate design balance and redirects to systems-designer.
**Expected:** Agent declines to evaluate design balance and redirects to game-designer, its stated contact for design concerns.
**Assertions:**
- [ ] Does not make any binding assessment of formula balance or game feel
- [ ] Explicitly names `systems-designer` as the correct handler
- [ ] May note code implementation concerns about the formula (e.g., integer overflow risk at max level), but defers all balance evaluation to systems-designer
- [ ] Explicitly names `game-designer` as the correct handler (its "What This Agent Must NOT Do" target for design concerns); naming `systems-designer` as the formula owner as well is fine
- [ ] Any comment it makes on the formula is about implementation (e.g., integer overflow risk at max level); all balance evaluation is deferred to the design team
### Case 3: Gate verdict — correct vocabulary
**Scenario:** A proposed pathfinding approach for enemy AI uses a brute-force nearest-neighbor search against all other entities every frame. With expected enemy counts of 200+, this is O(n²) per frame at 60fps. Request is tagged LP-FEASIBILITY.
**Expected:** Returns `LP-FEASIBILITY: INFEASIBLE` with specific citation of the O(n²) complexity, the entity count threshold, and the resulting per-frame cost against the target frame budget.
**Scenario:** The architecture document under review (passed with its technical requirements baseline and ADR list) specifies enemy AI that runs a brute-force nearest-neighbor search against all other entities every frame. With expected enemy counts of 2,000+, this is O(n²) — about 4 million distance checks per frame — against the document's 2 ms AI budget at 60fps. Request is tagged LP-FEASIBILITY.
**Expected:** Returns the verdict INFEASIBLE with specific citation of the O(n²) complexity, the entity count threshold, and the resulting per-frame cost against the 2 ms AI budget.
**Assertions:**
- [ ] Verdict is exactly one of FEASIBLE / CONCERNS / INFEASIBLE — not freeform text
- [ ] Verdict token is formatted as `LP-FEASIBILITY: INFEASIBLE`
- [ ] States the verdict word `INFEASIBLE` explicitly, not a verdict implied by prose
- [ ] Rationale includes the specific algorithmic complexity and entity count numbers
- [ ] Suggests at least one alternative approach (e.g., spatial hashing, KD-tree) without mandating a choice
@@ -57,7 +56,7 @@ Verified by reading the agent's `.claude/agents/lead-programmer.md` frontmatter:
- [ ] Does not unilaterally cut or modify the mechanic design
### Case 5: Context pass — uses provided context
**Scenario:** Agent receives a gate context block that includes the project's frame budget: 16.67ms total per frame, with 4ms allocated to AI systems. A new AI behavior system is submitted that profiling estimates will consume 7ms per frame under normal conditions.
**Scenario:** Agent receives a gate context block for an architecture document (with its technical requirements baseline and ADR list) that includes the project's frame budget: 16.67ms total per frame, with 4ms allocated to AI systems. The document adopts a new AI behavior system that prototype profiling estimates will consume 7ms per frame under normal conditions. Request is tagged LP-FEASIBILITY.
**Expected:** Assessment references the specific frame budget allocation from context (4ms AI budget), identifies the 7ms estimate as exceeding the allocation by 3ms, and returns CONCERNS or INFEASIBLE with those specific numbers cited.
**Assertions:**
- [ ] References the specific frame budget figures from the provided context (16.67ms total, 4ms AI allocation)
@@ -65,15 +64,24 @@ Verified by reading the agent's `.claude/agents/lead-programmer.md` frontmatter:
- [ ] Does not give generic "this might be slow" advice — cites concrete numbers
- [ ] Verdict rationale is traceable to the provided budget constraints
### Case 6: Missing gate input — NOT ASSESSED
**Scenario:** An `InventorySystem` implementation is submitted for code review with its implementation files, its story's acceptance criteria and its governing ADR; everything the agent can check is sound. The relevant GDD section the gate names was not passed: the context gives neither its text nor a path, the story file names none, and the calling skill does not report it absent. Request is tagged LP-CODE-REVIEW.
**Expected:** Returns NOT ASSESSED for LP-CODE-REVIEW, naming the GDD section as the input it was not given — without it, the gate's check for correctness issues against the GDD rules cannot be made, so APPROVE is out of reach.
**Assertions:**
- [ ] States the verdict `NOT ASSESSED` explicitly for LP-CODE-REVIEW — not APPROVE, although everything it could check is sound
- [ ] Names the relevant GDD section as the missing input
- [ ] Does not infer the GDD rules from the code or the story and judge correctness against them
- [ ] Variant — had the calling skill reported that no inventory GDD exists, that is a finding, not a missing input: the verdict is CONCERNS or REJECT, not NOT ASSESSED
---
## Protocol Compliance
- [ ] Returns LP-CODE-REVIEW verdicts using APPROVED / NEEDS CHANGES vocabulary only
- [ ] Returns LP-FEASIBILITY verdicts using FEASIBLE / CONCERNS / INFEASIBLE vocabulary only
- [ ] Returns LP-CODE-REVIEW verdicts using APPROVE / CONCERNS / REJECT vocabulary only — or `NOT ASSESSED`, naming the input, when an input the gate names was not given or could not be read; an artifact the calling skill reports absent is a finding, in the gate's own words
- [ ] Returns LP-FEASIBILITY verdicts using FEASIBLE / CONCERNS / INFEASIBLE vocabulary only — or `NOT ASSESSED`, naming the input, when an input the gate names was not given or could not be read; an artifact the calling skill reports absent is a finding, in the gate's own words
- [ ] Stays within declared code architecture domain
- [ ] Defers design priority conflicts to creative-director
- [ ] Uses gate IDs in output (e.g., `LP-FEASIBILITY: INFEASIBLE`) not inline prose verdicts
- [ ] States each gate verdict as an explicit verdict word from that gate's definition, not a verdict implied by inline prose
- [ ] Does not make binding game design or creative direction decisions
---
@@ -1,10 +1,9 @@
# Agent Test Spec: level-designer
## Agent Summary
**Domain owned:** Level layouts, encounter design, pacing and tension arc, environmental storytelling, spatial puzzles.
**Does NOT own:** Narrative dialogue (writer / narrative-director), visual art style (art-director), code implementation (lead-programmer / ai-programmer), enemy AI behavior logic (ai-programmer / gameplay-programmer).
**Model tier:** Sonnet (individual system analysis — level design review and encounter assessment).
**Gate IDs handled:** Level design review verdicts (uses APPROVED / REVISION NEEDED vocabulary).
**Domain owned:** Level layouts, encounter design (per-encounter difficulty), pacing charts, environmental storytelling, secret and optional content placement, flow analysis.
**Does NOT own:** Game-wide systems (game-designer / systems-designer), story decisions (narrative-director — coordinates with), visual art style (art-director), level implementation in the engine and enemy AI code (programmers), game-wide difficulty parameters.
**Gate IDs handled:** None. Design-review verdicts come from the `/design-review` skill, which spawns level-designer as a specialist that returns findings.
---
@@ -13,8 +12,8 @@
Verified by reading the agent's `.claude/agents/level-designer.md` frontmatter:
- [ ] `description:` field is present and domain-specific (references level layout, encounter design, pacing, environmental storytelling — not generic)
- [ ] `allowed-tools:` list is read-focused; includes Read for level design documents and GDDs; no Bash unless level tooling requires it
- [ ] Model tier is `claude-sonnet-5` per coordination-rules.md
- [ ] `tools:` reads Read, Glob, Grep, Write, Edit and `disallowedTools:` lists Bash
- [ ] Model tier is `inherit` — frontmatter `model:` reads exactly `inherit` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over narrative dialogue, AI behavior code, or visual art style
---
@@ -22,54 +21,55 @@ Verified by reading the agent's `.claude/agents/level-designer.md` frontmatter:
## Test Cases
### Case 1: In-domain request — appropriate output format
**Scenario:** A level layout document for "The Flooded Tunnels" is submitted for review. The layout includes: a low-intensity exploration opening section, two mid-intensity encounters with visible escape routes, a tension-building narrow passage with environmental hazards, and a high-intensity final encounter room followed by a release/reward area. The pacing follows a classic tension-arc structure.
**Expected:** Returns `APPROVED` with rationale confirming the pacing follows the tension arc, encounters are varied in intensity, and spatial readability supports player navigation.
**Scenario:** The user has agreed the outline for "The Flooded Tunnels": a low-intensity exploration opening, two mid-intensity encounters with visible escape routes, a tension-building narrow passage with environmental hazards, and a high-intensity final encounter room followed by a release/reward area. The user asks level-designer to draft the level document.
**Expected:** Drafts the level document in the Level Document Standard, with a pacing chart that follows the agreed tension arc and an encounter list that gives each encounter's type, difficulty, and position. Shows each section and asks before writing it.
**Assertions:**
- [ ] Verdict is exactly one of APPROVED / REVISION NEEDED
- [ ] Rationale references specific pacing arc elements (opening, escalation, climax, release)
- [ ] Output stays within level design scope — does not comment on visual art style or enemy AI code behavior
- [ ] Verdict is clearly labeled with context (e.g., "Level Design Review: APPROVED")
- [ ] The document has all nine Level Document Standard sections: Level Name and Theme, Estimated Play Time, Layout Diagram, Critical Path, Optional Paths, Encounter List, Pacing Chart, Narrative Beats, Music/Audio Cues
- [ ] The Pacing Chart follows the outline's intensity curve — low opening, mid encounters, rising passage, high final encounter, release — with its rest points marked
- [ ] The Encounter List gives type, difficulty, and position for each encounter
- [ ] Asks "May I create [filepath] with the section skeleton?" before creating the file and "May I write this section to [filepath]?" before writing each section, and does not decide visual art style or enemy AI code
### Case 2: Out-of-domain request — redirects or escalates
**Scenario:** A team member asks level-designer to write the behavior tree code for an enemy patrol AI that navigates the level layout.
**Expected:** Agent declines to write AI behavior code and redirects to ai-programmer or gameplay-programmer.
**Expected:** Agent declines to write AI behavior code — implementation is outside its role — and instead specifies the patrol from a level design perspective, as input for ai-programmer.
**Assertions:**
- [ ] Does not write or specify code for AI behavior logic
- [ ] Explicitly names `ai-programmer` or `gameplay-programmer` as the correct handler
- [ ] May specify the desired patrol behavior from a level design perspective (e.g., "patrol should cover both chokepoints and create pressure in this zone"), but defers all code implementation to the programmer
- [ ] States that behavior-tree code is implementation work outside its role, rather than taking it on
- [ ] Explicitly names `ai-programmer` (or `gameplay-programmer`, which its file names for engine implementation) as who implements it
- [ ] Specifies the desired patrol in level design terms (e.g., route through named chokepoints and sight lines, pressure zones, spawn timing) for the programmer to implement
### Case 3: Gate verdict — correct vocabulary
**Scenario:** A level layout for "The Ancient Forge" is submitted. Section 3 of the level introduces a dramatically harder enemy encounter (elite enemy with new attack patterns) with no preceding tutorial moment, no environmental readability cues (no visible cover or safe zones), and no checkpoint nearby. Players are likely to die repeatedly with no clear signal of what to do differently.
**Expected:** Returns `REVISION NEEDED` with specific identification of the difficulty spike in section 3, the missing readability cue, and the absence of a nearby checkpoint to reduce frustration from repeated deaths.
### Case 3: Review findings — specific, verdict left to the review skill
**Scenario:** `/design-review` in full mode spawns level-designer as the adversarial specialist for the level document of "The Ancient Forge." The spawn prompt reads: "Your job is NOT to validate this design — your job is to find problems. Be specific and critical." Section 3 of the level introduces a dramatically harder elite enemy with new attack patterns, with no earlier moment that introduces it, no environmental readability cues (no visible cover or safe zones), and no checkpoint nearby.
**Expected:** Returns specific findings locating the problem in section 3: the difficulty spike, the missing readability cues, and the missing checkpoint, each with a concrete spatial fix offered as an option. It returns findings, not a verdict — `/design-review` issues the verdict.
**Assertions:**
- [ ] Verdict is exactly one of APPROVED / REVISION NEEDED — not freeform text
- [ ] Rationale identifies section 3 specifically as the location of the issue
- [ ] Identifies the three specific problems: difficulty spike, missing readability cue, missing checkpoint
- [ ] Provides actionable revision guidance (e.g., "add a visible safe zone, pre-encounter cue object, or reduce elite's health for first introduction")
- [ ] Identifies section 3 specifically as the location of the issue
- [ ] Identifies the three specific problems: difficulty spike without an introduction, missing readability cues, missing nearby checkpoint
- [ ] Provides actionable spatial revision options (e.g., introduce the elite in isolation first, add a visible safe zone or cover, place a checkpoint before the arena)
- [ ] Returns findings to the review, not its own APPROVED / NEEDS REVISION stamp
### Case 4: Conflict escalation — correct parent
**Scenario:** game-designer wants higher encounter density throughout the level (more enemies in each room) to increase combat challenge. level-designer believes this density undermines the pacing arc by eliminating rest periods and making the level feel relentless without reward.
**Expected:** level-designer clearly articulates the pacing concern (eliminating rest periods removes the tension-release rhythm), acknowledges game-designer's challenge goal, and escalates to creative-director for a design arbiter ruling on whether challenge density or pacing rhythm takes precedence for this level.
**Expected:** level-designer states the pacing concern in pacing-chart terms (removing rest points flattens the tension-release rhythm), acknowledges game-designer's challenge goal, lays out the options, and escalates to creative-director for a design arbiter ruling on whether challenge density or pacing rhythm takes precedence for this level.
**Assertions:**
- [ ] Articulates the specific pacing impact of increased encounter density
- [ ] States the specific pacing impact: denser rooms remove the rest points, flattening the intensity curve into constant high intensity
- [ ] Escalates to `creative-director` as the design arbiter
- [ ] Does not unilaterally override game-designer's challenge density request
- [ ] Frames the conflict clearly: "challenge density vs. pacing rhythm — which takes precedence here?"
- [ ] Presents the choice as options (e.g., keep density, keep rest points, add density with dedicated rest rooms) with a recommendation, leaving the ruling to the arbiter
### Case 5: Context pass — uses provided context
**Scenario:** Agent receives a gate context block that includes game-feel notes specifying: "exploration sections should feel vast and lonely," "combat sections should feel urgent and claustrophobic," and "reward rooms should feel safe and visually distinct." A new level layout is submitted for review.
**Expected:** Assessment evaluates each section type (exploration, combat, reward) against the specific feel targets from the provided context. Uses the exact vocabulary from the feel notes ("vast and lonely," "urgent and claustrophobic," "safe and visually distinct") in the rationale.
**Scenario:** The request includes game-feel notes: "exploration sections should feel vast and lonely," "combat sections should feel urgent and claustrophobic," and "reward rooms should feel safe and visually distinct." A new level layout is submitted for the agent's assessment. Its exploration section is a narrow, winding corridor, and its reward room uses the same lighting and layout as the combat arena before it.
**Expected:** Assessment evaluates each section type (exploration, combat, reward) against its feel target, using the exact vocabulary from the notes, and flags the two sections that conflict with their targets.
**Assertions:**
- [ ] References all three feel targets from the provided context by their exact vocabulary
- [ ] Evaluates each relevant section of the submitted layout against its corresponding feel target
- [ ] Flags the narrow exploration corridor as conflicting with "vast and lonely," and the reward room as not "visually distinct" from the arena
- [ ] Does not generate generic pacing advice — all feedback is tied to the provided feel targets
- [ ] Identifies any section where the layout conflicts with its assigned feel target
---
## Protocol Compliance
- [ ] Returns verdicts using APPROVED / REVISION NEEDED vocabulary only
- [ ] Level documents it drafts contain the Level Document Standard's nine sections
- [ ] Stays within declared level design domain
- [ ] Escalates challenge-density vs. pacing conflicts to creative-director
- [ ] Does not make binding narrative dialogue, AI code implementation, or visual art style decisions
@@ -78,8 +78,8 @@ Verified by reading the agent's `.claude/agents/level-designer.md` frontmatter:
---
## Coverage Notes
- Environmental storytelling review (using spatial elements to convey narrative without dialogue) could benefit from a dedicated case.
- Spatial puzzle design review is not covered — a dedicated case should be added when puzzle mechanics are defined.
- Multi-level pacing review (arc across an entire act or world map) is not covered — deferred to milestone-level design review.
- Environmental storytelling (using spatial elements to convey narrative without dialogue) could benefit from a dedicated case.
- Spatial puzzle design is not covered — a dedicated case should be added when puzzle mechanics are defined.
- Multi-level pacing (arc across an entire act or world map) is not covered — deferred to milestone-level design review.
- Interaction between level-designer and narrative-director for environmental lore placement is not covered.
- Accessibility review of level layouts (colorblind indicators, difficulty options for spatial challenges) is not covered.
@@ -1,10 +1,9 @@
# Agent Test Spec: narrative-director
## Agent Summary
**Domain owned:** Story architecture, character design direction, world-building oversight, ND-CONSISTENCY gate, dialogue quality review.
**Domain owned:** Story architecture, character design direction, world-building oversight, ND-CONSISTENCY gate, dialogue strategy.
**Does NOT own:** Visual art style (art-director), technical systems or code (lead-programmer), production scheduling (producer), game mechanics rules (game-designer).
**Model tier:** Sonnet (individual system analysis — narrative consistency and lore review).
**Gate IDs handled:** ND-CONSISTENCY.
**Gate IDs handled:** ND-CONSISTENCY (verdicts APPROVE / CONCERNS / REJECT, defined in `.claude/docs/director-gates/nd-consistency.md`).
---
@@ -13,8 +12,8 @@
Verified by reading the agent's `.claude/agents/narrative-director.md` frontmatter:
- [ ] `description:` field is present and domain-specific (references story, character, world-building, consistency — not generic)
- [ ] `allowed-tools:` list is read-focused; includes Read for lore documents, GDDs, and narrative docs; no Bash unless justified
- [ ] Model tier is `claude-sonnet-5` per coordination-rules.md
- [ ] `tools:` reads Read, Glob, Grep, Write, Edit, WebSearch and `disallowedTools:` lists Bash
- [ ] Model tier is `inherit` — frontmatter `model:` reads exactly `inherit` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over visual style, technical systems, or production scheduling
---
@@ -22,63 +21,73 @@ Verified by reading the agent's `.claude/agents/narrative-director.md` frontmatt
## Test Cases
### Case 1: In-domain request — appropriate output format
**Scenario:** A new lore document for "The Sunken Archive" location is submitted. The document establishes that the Archive was flooded 200 years ago during the Great Collapse, consistent with the established timeline in the world-bible. All named characters referenced are consistent with their established backstories. Request is tagged ND-CONSISTENCY.
**Expected:** Returns `ND-CONSISTENCY: CONSISTENT` with rationale confirming the timeline alignment and character reference accuracy.
**Scenario:** A new lore document for "The Sunken Archive" location is submitted. The document establishes that the Archive was flooded 200 years ago during the Great Collapse, consistent with the established timeline in the world-bible. All named characters referenced are consistent with their established profiles, and the tone matches the narrative bible's tone guide. The gate context passes every input `.claude/docs/director-gates/nd-consistency.md` names: the document path, the tone guide, the world-bible's timeline rules, and the profiles of the characters it references. Request is tagged ND-CONSISTENCY.
**Expected:** Returns `APPROVE` with rationale confirming the timeline alignment, character consistency, and tone.
**Assertions:**
- [ ] Verdict is exactly one of CONSISTENT / INCONSISTENT
- [ ] Verdict token is formatted as `ND-CONSISTENCY: CONSISTENT`
- [ ] Rationale references specific established facts verified (the 200-year timeline, the Great Collapse event)
- [ ] Verdict is exactly one of APPROVE / CONCERNS / REJECT (the ND-CONSISTENCY gate's vocabulary) — here APPROVE
- [ ] Rationale answers each question the gate prompt asks: character consistency with established profiles, contradictions with established lore, and tone
- [ ] Rationale references the specific established facts verified (the 200-year timeline, the Great Collapse event)
- [ ] Output stays within narrative scope — does not comment on visual design of the location or its technical implementation
### Case 2: Out-of-domain request — redirects or escalates
**Scenario:** A developer asks narrative-director to review and optimize the shader code used for the "ancient glow" visual effect on Archive artifacts.
**Expected:** Agent declines to evaluate shader code and redirects to the appropriate engine specialist (godot-gdscript-specialist or equivalent shader specialist).
**Expected:** Agent declines to evaluate the shader code. It names `technical-artist` — the owner of shader, VFX and rendering code in its own "must not" list — as who reviews and optimizes it; naming `art-director`, who owns how the effect should look, as well is fine. Any narrative input it adds is the mood the effect should carry.
**Assertions:**
- [ ] Does not make any binding decision about shader code or visual implementation
- [ ] Explicitly names the appropriate engine or shader specialist as the correct handler
- [ ] May note the intended narrative mood the effect should convey (e.g., "should feel ancient and sacred, not technological"), but defers all technical visual implementation
- [ ] Does not review, rewrite, or optimize the shader code, and makes no binding decision about visual implementation
- [ ] Names `technical-artist` (or the engine's shader specialist) as the owner of the shader code, per its "Review or change shader, VFX or rendering code (technical-artist owns it; art-director owns how it should look)" limit — naming `art-director` too is acceptable, naming only art-director is not
- [ ] Any narrative input it gives (e.g., "should feel ancient and sacred, not technological") is framed as input for the visual owners, not as a visual or technical decision
### Case 3: Gate verdict — correct vocabulary
**Scenario:** A new character backstory document is submitted for the character "Aldric Vorne." The document states Aldric was born in the Capital 150 years ago and witnessed the Great Collapse firsthand. However, the established world-bible states Aldric was born 50 years after the Great Collapse in a provincial town, not the Capital. Request is tagged ND-CONSISTENCY.
**Expected:** Returns `ND-CONSISTENCY: INCONSISTENT` with specific citation of the two contradicting facts: the birth timing (150 years ago vs. 50 years post-Collapse) and the birth location (Capital vs. provincial town).
**Scenario:** A new character backstory document is submitted for the character "Aldric Vorne." The document states Aldric was born in the Capital 150 years ago and witnessed the Great Collapse firsthand; the backstory's central arc is his guilt over the Collapse he watched happen. The established world-bible states Aldric was born 50 years after the Great Collapse in a provincial town, not the Capital. Request is tagged ND-CONSISTENCY.
**Expected:** Returns `REJECT` — the contradicted facts carry the backstory's central arc, so they break its narrative foundation rather than being a local fix — listing both contradictions: birth timing (150 years ago vs. 50 years after the Collapse) and birth location (Capital vs. provincial town).
**Assertions:**
- [ ] Verdict is exactly one of CONSISTENT / INCONSISTENT — not freeform text
- [ ] Verdict token is formatted as `ND-CONSISTENCY: INCONSISTENT`
- [ ] Rationale cites both contradictions specifically, not just "doesn't match lore"
- [ ] References the authoritative source (world-bible) for the established facts
- [ ] Verdict is exactly one of APPROVE / CONCERNS / REJECT — not freeform text; here REJECT, because the contradicted facts are load-bearing for the whole backstory (a contradiction it found takes the gate's word, so it is not NOT ASSESSED even though no character profile is passed)
- [ ] The verdict carries both contradictions specifically, in the gate's `REJECT [contradictions ...]` form — not just "doesn't match lore"
- [ ] References the world-bible as the authoritative source for the established facts
- [ ] Does not write a replacement backstory itself — the rewrite belongs to the content author (lore entries are delegated to `writer` / `world-builder` in its Delegation Map)
### Case 4: Conflict escalation — correct parent
**Scenario:** A writer has established in their latest dialogue that the ancient civilization "spoke only in song." The world-builder's existing lore entries describe the same civilization communicating through written glyphs. Both are in the narrative domain, and the two creators disagree on which is canonical.
**Expected:** narrative-director makes a binding canonical decision within their domain. They do not need to escalate to a higher authority for intra-narrative conflicts — this is within their declared domain authority. They issue a ruling (e.g., "glyph-writing is the canonical primary communication; song may be ritual/ceremonial") and direct both writer and world-builder to align their work to the ruling.
**Scenario:** A writer has established in their latest dialogue that the ancient civilization "spoke only in song." The world-builder's existing lore entries describe the same civilization communicating through written glyphs. Both report to narrative-director, and the two disagree on which is canonical.
**Expected:** narrative-director resolves the conflict at its own tier — it is the shared parent of writer and world-builder, so it does not escalate to creative-director. Following its collaboration protocol, it presents reconciliation options with a recommended canonical ruling (e.g., "glyph-writing is the canonical primary communication; song is ritual/ceremonial"), leaves the final call to the user, and then directs both writer and world-builder to align their work to the confirmed ruling.
**Assertions:**
- [ ] Makes a binding canonical decision — does not defer this intra-narrative conflict to creative-director
- [ ] Decision is clearly stated and provides a path to reconciliation for both parties
- [ ] Directs both parties (writer and world-builder) to update their respective documents to align
- [ ] Notes the decision in a way that can be added to the world-bible as a canonical fact
- [ ] Resolves the conflict itself as the shared parent — does not defer this intra-narrative conflict to creative-director
- [ ] Presents reconciliation options with a clearly stated recommended ruling, and leaves the final canon decision to the user
- [ ] Directs both parties to update their documents to the ruling: writer revises the dialogue, world-builder updates the lore entry
- [ ] Proposes recording the ruling as a canonical fact in the world-building documentation, so later lore can be checked against it
### Case 5: Context pass — uses provided context
**Scenario:** Agent receives a gate context block that includes three existing lore documents: the world-bible (establishes the Great Collapse timeline and causes), the character registry (lists canonical character ages, origins, and allegiances), and a faction document (describes the Sunken Archive Keepers). A new story chapter is submitted that introduces a previously unregistered character.
**Expected:** Assessment cross-references the new character against the character registry (no conflict), checks the chapter's timeline references against the world-bible, and evaluates the chapter's portrayal of the Archive Keepers against the faction document. Uses specific facts from all three provided documents in the assessment.
**Scenario:** A new story chapter is submitted for ND-CONSISTENCY review. It introduces a previously unregistered character. The gate context passes three documents: the world-bible (the Great Collapse timeline and causes), the character registry (canonical character ages, origins, and allegiances), and a faction document describing the Sunken Archive Keepers.
**Expected:** Assessment cross-references the new character against the character registry (no conflict), checks the chapter's timeline references against the world-bible, and evaluates the chapter's portrayal of the Archive Keepers against the faction document. Uses specific facts from all three provided documents and returns an ND-CONSISTENCY verdict.
**Assertions:**
- [ ] Cross-references the new character against the provided character registry
- [ ] Checks timeline references against the provided world-bible facts
- [ ] Evaluates faction portrayal against the provided faction document
- [ ] Does not generate generic narrative feedback — all assertions are traceable to the provided documents
- [ ] Returns one of APPROVE / CONCERNS / REJECT with a rationale traceable to the three provided documents — no generic narrative feedback
### Case 6: Gate input missing — NOT ASSESSED
**Scenario:** ND-CONSISTENCY is invoked for a new dialogue file in which "Aldric Vorne" speaks. The gate context passes the file path and the world-building rules, and the dialogue contradicts none of them — but Aldric's character profile, an input the gate names, is not passed, so his voice cannot be checked against it.
**Expected:** Returns `ND-CONSISTENCY: NOT ASSESSED`, naming the missing input (Aldric Vorne's character profile), rather than APPROVE — voice consistency against a profile it never saw has not been established.
**Assertions:**
- [ ] Verdict is `NOT ASSESSED` — not APPROVE, CONCERNS or REJECT — because the inputs it could read show no inconsistency
- [ ] Names the missing input: Aldric Vorne's character profile
- [ ] Does not reconstruct Aldric's established voice from the dialogue itself or from memory to complete the check
---
## Protocol Compliance
- [ ] Returns verdicts using CONSISTENT / INCONSISTENT vocabulary only
- [ ] Returns ND-CONSISTENCY verdicts using APPROVE / CONCERNS / REJECT only — or NOT ASSESSED, naming the input, when an input the gate names is missing and no inconsistency was found
- [ ] Asks "May I create [filepath] with the section skeleton?" before creating a narrative document, and "May I write this section to [filepath]?" before writing each section
- [ ] Stays within declared narrative domain
- [ ] Makes binding decisions for intra-narrative conflicts without unnecessary escalation
- [ ] Uses gate IDs in output (e.g., `ND-CONSISTENCY: INCONSISTENT`) not inline prose verdicts
- [ ] Resolves intra-narrative conflicts at its own tier instead of escalating them, while leaving the final canon decision to the user
- [ ] A CONCERNS or REJECT verdict names the specific inconsistencies or contradictions, as the gate prompt's `CONCERNS [...]` / `REJECT [...]` forms require — never a bare verdict word
- [ ] Does not make binding visual design, technical, or production decisions
---
## Coverage Notes
- Dialogue quality review (distinct from world-building consistency) is not covered — a dedicated case should be added.
- The CONCERNS verdict (fixable inconsistencies that do not break the narrative foundation) has no dedicated case.
- Multi-document consistency check across a full chapter set is not covered — deferred to /review-all-gdds integration.
- Narrative impact of mechanical changes (e.g., a game mechanic that undermines story tension) requires coordination with game-designer and is not covered here.
- Character arc review (progression, motivation coherence over time) is not covered.
@@ -3,7 +3,6 @@
## Agent Summary
**Domain owned:** Test strategy, QL-STORY-READY gate, QL-TEST-COVERAGE gate, bug severity triage, release quality gates.
**Does NOT own:** Feature implementation (programmers), game design decisions, creative direction, production scheduling.
**Model tier:** Sonnet (individual system analysis — story readiness and coverage assessment).
**Gate IDs handled:** QL-STORY-READY, QL-TEST-COVERAGE.
---
@@ -13,8 +12,8 @@
Verified by reading the agent's `.claude/agents/qa-lead.md` frontmatter:
- [ ] `description:` field is present and domain-specific (references test strategy, story readiness, coverage, bug triage — not generic)
- [ ] `allowed-tools:` list is read-focused; may include Read for story files, test files, and coding-standards; Bash only if running test commands is required
- [ ] Model tier is `claude-sonnet-5` per coordination-rules.md
- [ ] `tools:` includes Read for story files, test files, and coding-standards; Bash because it runs `/smoke-check` before every QA hand-off; Write/Edit for the QA plans and sign-off reports it produces, each write gated on the user's approval in its collaboration protocol
- [ ] Model tier is `inherit` — frontmatter `model:` reads exactly `inherit` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over implementation decisions or game design
---
@@ -22,42 +21,42 @@ Verified by reading the agent's `.claude/agents/qa-lead.md` frontmatter:
## Test Cases
### Case 1: In-domain request — appropriate output format
**Scenario:** A story for "Player takes damage from hazard tiles" is submitted for readiness check. The story has three acceptance criteria: (1) Player health decreases by the hazard's damage value, (2) A damage visual feedback plays, (3) Player cannot take damage again for 0.5 seconds (invincibility window). All three ACs are measurable and specific. Request is tagged QL-STORY-READY.
**Expected:** Returns `QL-STORY-READY: ADEQUATE` with rationale confirming that all three ACs are present, specific, and testable.
**Scenario:** A Logic-type story for "Player takes damage from hazard tiles" is submitted for readiness check. The gate context passes every input `.claude/docs/director-gates/ql-story-ready.md` names: the story file path (`production/epics/hazards/story-002-hazard-damage.md`), the story type (Logic), the acceptance criteria verbatim — (1) Player health decreases by the hazard's damage value, (2) A `damaged` event is emitted carrying the damage amount, (3) Player cannot take damage again for 0.5 seconds of simulated time (invincibility window) — and the GDD requirement the story covers (`TR-hazards-002`: "Hazard tiles damage the player on contact; each hit grants 0.5 seconds of invincibility"). All three ACs are measurable and specific. Request is tagged QL-STORY-READY.
**Expected:** Returns the verdict ADEQUATE with rationale confirming that all three ACs are specific and each can be verified by an automated test.
**Assertions:**
- [ ] Verdict is exactly one of ADEQUATE / INADEQUATE
- [ ] Verdict token is formatted as `QL-STORY-READY: ADEQUATE`
- [ ] Rationale references the specific number of ACs (3) and confirms each is measurable
- [ ] Verdict is exactly one of ADEQUATE / GAPS / INADEQUATE (the QL-STORY-READY verdicts) — every input the gate names is supplied, so NOT ASSESSED does not apply
- [ ] States the verdict word `ADEQUATE` explicitly — `/story-readiness` and `/create-stories` branch on the bare verdict word
- [ ] Rationale addresses each of the three ACs and confirms each can be verified by an automated test (the gate's Logic-story check)
- [ ] Output stays within QA scope — does not comment on whether the mechanic is designed well
### Case 2: Out-of-domain request — redirects or escalates
**Scenario:** A developer asks qa-lead to implement the automated test harness for the new physics system.
**Expected:** Agent declines to implement the test code and redirects to the appropriate programmer (gameplay-programmer or lead-programmer).
**Expected:** Agent does not take on the harness code itself. It defines what the harness must verify and routes the writing to qa-tester, its delegate for test writing and execution, coordinating the physics system's testability with lead-programmer.
**Assertions:**
- [ ] Does not write or propose code implementation
- [ ] Explicitly names `lead-programmer` or `gameplay-programmer` as the correct handler for implementation
- [ ] May define what the test should verify (test strategy), but defers the code writing to programmers
- [ ] Does not write the harness code itself
- [ ] Explicitly names `qa-tester` (its Delegation Map owner of test writing and execution) as the implementer; `lead-programmer` may be named as the testability contact
- [ ] Any test strategy it adds (what the harness must verify) is handed to the implementer as input — its answer contains no harness code
### Case 3: Gate verdict — correct vocabulary
**Scenario:** A story for "Combat feels responsive and punchy" is submitted for readiness check. The single acceptance criterion reads: "Combat should feel good to the player." This is subjective and unmeasurable. Request is tagged QL-STORY-READY.
**Expected:** Returns `QL-STORY-READY: INADEQUATE` with specific identification of the unmeasurable AC and guidance on what would make it testable (e.g., "input-to-hit-feedback latency ≤ 100ms").
**Expected:** Returns the verdict INADEQUATE with specific identification of the unmeasurable AC and guidance on what would make it testable (e.g., "input-to-hit-feedback latency ≤ 100ms").
**Assertions:**
- [ ] Verdict is exactly one of ADEQUATE / INADEQUATE — not freeform text
- [ ] Verdict token is formatted as `QL-STORY-READY: INADEQUATE`
- [ ] Verdict is exactly one of ADEQUATE / GAPS / INADEQUATE — not freeform text
- [ ] States the verdict word `INADEQUATE` explicitly — a single wholly subjective AC leaves nothing to refine, so it is not GAPS; and a problem it found takes the gate's word, so it is not NOT ASSESSED even though the scenario names no GDD requirement
- [ ] Rationale identifies the specific AC that fails the measurability requirement
- [ ] Provides actionable guidance on how to rewrite the AC to be testable
- [ ] Provides actionable guidance on how to rewrite the AC to be testable — a measurable benchmark in place of "feels good"
### Case 4: Conflict escalation — correct parent
**Scenario:** gameplay-programmer and qa-lead disagree on whether a test that asserts "enemy patrol path visits all waypoints within 5 seconds" is deterministic enough to be a valid automated test. gameplay-programmer argues timing variability makes it flaky; qa-lead believes it is acceptable.
**Expected:** qa-lead acknowledges the technical flakiness concern and escalates to lead-programmer for a technical ruling on what constitutes an acceptable determinism standard for automated tests.
**Scenario:** The project runs `qa.level: standard`. A Logic-type story's automated test asserts "enemy patrol path visits all waypoints within 5 seconds" of wall-clock time. gameplay-programmer argues timing variability makes it flaky and wants to replace it with a manual walkthrough; qa-lead needs automated evidence for the story. They disagree on the way forward.
**Expected:** qa-lead agrees the wall-clock assertion breaks the project's determinism rule, but does not accept a manual walkthrough for a Logic story — it asks for a deterministic rewrite (e.g., fixed-step simulation or an injected clock). If the disagreement stands, it escalates to technical-director, its reporting line for quality standards and the shared parent of the two agents.
**Assertions:**
- [ ] Escalates to `lead-programmer` for the technical ruling on determinism standards
- [ ] Identifies the "within 5 seconds" wall-clock assertion as a time-dependent assertion that coding-standards.md's Determinism rule forbids — does not defend it as acceptable
- [ ] Does not unilaterally override the gameplay-programmer's flakiness concern
- [ ] Frames the escalation clearly: "this is a technical standards question, not a QA coverage question"
- [ ] Does not abandon the coverage requirement — asks for a deterministic alternative if the current approach is ruled flaky
- [ ] If unresolved, escalates to `technical-director` (qa-lead's "Reports to" for quality standards; the shared parent under coordination-rules.md rule 3) — not to lead-programmer, who is gameplay-programmer's own lead
- [ ] Does not abandon the coverage requirement — a Logic story still needs a passing automated test, so it asks for a deterministic alternative rather than accepting the manual walkthrough
### Case 5: Context pass — uses provided context
**Scenario:** Agent receives a gate context block that includes the coding-standards.md testing standards section, which specifies: Logic stories require blocking automated unit tests, Visual/Feel stories require a blocking retained screenshot + lead sign-off, Config/Data stories require smoke check pass (advisory). A story classified as "Logic" type is submitted with only a manual walkthrough document as evidence.
**Scenario:** Agent receives a gate context block that includes the coding-standards.md testing standards section, which specifies: Logic stories require blocking automated unit tests, Visual/Feel stories require a blocking retained screenshot + lead sign-off, Config/Data stories require smoke check pass (advisory). The context states the project runs `qa.level: standard`. A story classified as "Logic" type is submitted with only a manual walkthrough document as evidence.
**Expected:** Assessment references the specific test evidence requirements from coding-standards.md, identifies that a "Logic" story requires an automated unit test (not just a manual walkthrough), and returns INADEQUATE with the specific requirement cited.
**Assertions:**
- [ ] References the specific story type classification ("Logic") from the provided context
@@ -65,21 +64,37 @@ Verified by reading the agent's `.claude/agents/qa-lead.md` frontmatter:
- [ ] Identifies the submitted evidence type (manual walkthrough) as insufficient for this story type
- [ ] Does not apply advisory-level requirements as blocking requirements
### Case 6: Gate input missing — NOT ASSESSED
**Scenario:** QL-STORY-READY is invoked for a Logic-type story, "Stamina drains while sprinting", with its file path, its type and two acceptance criteria that are specific and measurable — but without the GDD requirement: the context omits the TR-ID and text the story covers, and the story file names none.
**Expected:** Returns `QL-STORY-READY: NOT ASSESSED`, naming the missing input (the GDD requirement the story covers), rather than ADEQUATE — readiness against a requirement nobody supplied has not been established.
**Assertions:**
- [ ] Verdict is `NOT ASSESSED` — not ADEQUATE, GAPS or INADEQUATE — because the criteria it could read show no problem
- [ ] Names the missing input: the GDD requirement (TR-ID and text) the story covers
- [ ] Does not invent or assume a GDD requirement to complete the check
### Case 7: `qa.level: minimal` — tests waived, screenshots not
**Scenario:** Asked to set the test evidence gates for a sprint's QA plan, the agent is told the project runs `qa.level: minimal` (the default). The sprint holds a Logic story with no test file and a UI story.
**Expected:** Applies the `qa.level` it was given (its drafting workflow asks whether `qa.level` or `testing.strict` changes any gate level): the Logic story's missing test is not a blocker — tests are waived at `minimal` — while the UI story still needs a retained screenshot of each screen it touches.
**Assertions:**
- [ ] Does not flag the Logic story's missing test as a blocker or a hard gate at `qa.level: minimal`
- [ ] States that `qa.level: minimal` waives test evidence
- [ ] Still requires the UI story's retained screenshots — the look is never waived
---
## Protocol Compliance
- [ ] Returns QL-STORY-READY verdicts using ADEQUATE / INADEQUATE vocabulary only
- [ ] Returns QL-TEST-COVERAGE verdicts using ADEQUATE / INADEQUATE vocabulary only (or PASS / FAIL for release gates)
- [ ] Returns QL-STORY-READY verdicts using ADEQUATE / GAPS / INADEQUATE only — or NOT ASSESSED, naming the input, when an input the gate names is missing and no problem was found
- [ ] Returns QL-TEST-COVERAGE verdicts using ADEQUATE / GAPS / INADEQUATE only — or NOT ASSESSED, naming the input, when an input the gate names is missing and no problem was found
- [ ] Stays within declared QA and test strategy domain
- [ ] Escalates technical standards disputes to lead-programmer
- [ ] Uses gate IDs in output (e.g., `QL-STORY-READY: INADEQUATE`) not inline prose verdicts
- [ ] Escalates unresolved technical standards disputes to technical-director
- [ ] States each gate verdict as an explicit verdict word — one per story when several stories are passed — not a verdict implied by inline prose
- [ ] Does not make binding implementation or game design decisions
---
## Coverage Notes
- QL-TEST-COVERAGE (overall coverage assessment for a sprint or milestone) is not covered — a dedicated case should be added when coverage reports are available.
- Bug severity triage (P0/P1/P2 classification) is not covered here — deferred to /bug-triage skill integration.
- Release quality gate behavior (PASS / FAIL vocabulary variant) is not covered.
- Bug severity triage (S1–S4 classification) is not covered here — deferred to /bug-triage skill integration.
- Release quality gate enforcement (crash rate, critical bug count, performance benchmarks) is not covered.
- Interaction between QL-STORY-READY and story Done criteria (/story-done skill) is not covered.
@@ -1,10 +1,9 @@
# Agent Test Spec: systems-designer
## Agent Summary
**Domain owned:** Combat formulas, progression curves, crafting recipes, status effect interactions, economy math, numerical balance.
**Does NOT own:** Narrative and lore (narrative-director), visual design (art-director), code implementation (lead-programmer), conceptual mechanic rules (game-designer — collaborates with).
**Model tier:** Sonnet (individual system analysis — formula review and balance math).
**Gate IDs handled:** Systems review verdicts on formulas and balance specs (uses APPROVED / NEEDS REVISION vocabulary).
**Domain owned:** Combat formulas, progression curves, crafting recipes, status effect interaction matrices, feedback loop analysis, tuning documentation, simulation specs.
**Does NOT own:** High-level design direction (game-designer — direct collaboration partner), level and encounter design (level-designer), narrative and aesthetic decisions, code implementation.
**Gate IDs handled:** None. Formula reviews return findings and options; design-review verdicts come from the `/design-review` skill, which spawns systems-designer as a specialist.
---
@@ -13,8 +12,8 @@
Verified by reading the agent's `.claude/agents/systems-designer.md` frontmatter:
- [ ] `description:` field is present and domain-specific (references formulas, progression curves, balance math, economy — not generic)
- [ ] `allowed-tools:` list is read-focused; may include Bash for formula evaluation scripts if the project uses them; no write access outside `design/balance/` without delegation
- [ ] Model tier is `claude-sonnet-5` per coordination-rules.md
- [ ] `tools:` list is read/write-focused with Bash excluded (`disallowedTools:` lists Bash); every Write/Edit is gated by its "May I write" step or the orchestrator named-path exception
- [ ] Model tier is `inherit` — frontmatter `model:` reads exactly `inherit` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over narrative, visual design, or conceptual mechanic rule ownership
---
@@ -22,30 +21,30 @@ Verified by reading the agent's `.claude/agents/systems-designer.md` frontmatter
## Test Cases
### Case 1: In-domain request — appropriate output format
**Scenario:** A damage formula is submitted for review: `damage = base_attack * (1 + strength_modifier * 0.1) - defense * 0.5`, with defined ranges: base_attack [10–100], strength_modifier [0–20], defense [0–50]. The formula produces positive damage across all valid input ranges, scales smoothly, and has no division-by-zero or overflow risk within the defined value bounds.
**Expected:** Returns `APPROVED` with rationale confirming the formula is balanced within the design parameters, produces valid output across the full input range, and has no degenerate cases.
**Scenario:** The user asks systems-designer to formalize the combat GDD's damage formula for its Formulas section: `damage = base_attack * (1 + strength_modifier * 0.1) - defense * 0.5`, with ranges base_attack [10–100], strength_modifier [0–20], defense [0–50].
**Expected:** Produces the formula in the mandatory Formula Output Format. The output range is not safe as written: it spans −15 (base_attack 10, strength_modifier 0, defense 50) to 300 (base_attack 100, strength_modifier 20, defense 0), so the agent flags the negative floor and offers clamping options for the user to choose.
**Assertions:**
- [ ] Verdict is exactly one of APPROVED / NEEDS REVISION
- [ ] Rationale demonstrates verification across the input range (min/max cases checked)
- [ ] Output stays within systems domain — does not comment on whether the mechanic is fun or how to implement it
- [ ] Verdict is clearly labeled with context (e.g., "Formula Review: APPROVED")
- [ ] Output contains all four mandatory parts: named expression, variable table (Symbol / Type / Range / Description, including a result row), output range, and worked example
- [ ] Output range states the unclamped result spans −15 to 300, identifying the input combination that goes negative
- [ ] Offers ways to bound the negative floor (e.g., a minimum-damage clamp) as options with a recommendation, leaving the choice to the user
- [ ] Stays within the systems domain — does not comment on whether the mechanic is fun or how to implement it in code
### Case 2: Out-of-domain request — redirects or escalates
**Scenario:** A writer asks systems-designer to draft the quest script for a side quest that rewards the player with a rare crafting ingredient.
**Expected:** Agent declines to write quest script content and redirects to writer or narrative-director.
**Expected:** Agent declines to write the quest script — narrative decisions are outside its role — and offers only the systems side of the request: how rare the ingredient reward should be within the crafting economy.
**Assertions:**
- [ ] Does not write quest narrative content or dialogue
- [ ] Explicitly names `writer` or `narrative-director` as the correct handler
- [ ] May note the systems implications of the reward (e.g., "this ingredient should be rare enough to matter per the crafting economy model"), but defers all script writing to the narrative team
- [ ] States that the script is narrative work outside its role, leaving it with the writer who asked
- [ ] Offers the systems contribution instead (e.g., the ingredient's reward rarity or drop rate relative to the crafting economy), without making narrative decisions
### Case 3: Gate verdict — correct vocabulary
**Scenario:** A damage scaling formula is submitted: `damage = base_attack * level_multiplier`, where `level_multiplier = (player_level / enemy_level) ^ 2`. At max player level (50) against a min-level enemy (1), the multiplier is 2500x — producing 25,000+ damage from a 10-base-attack weapon, far exceeding any meaningful balance. This is a degenerate case at max level.
**Expected:** Returns `NEEDS REVISION` with specific identification of the degenerate case: at max level vs. min enemy, the formula produces a 2500x multiplier that destroys any balance ceiling.
### Case 3: Review findings — degenerate case at the boundaries
**Scenario:** `/design-review` in full mode spawns systems-designer as the adversarial specialist for a combat GDD. The spawn prompt reads: "For every formula in the GDD, plug in boundary values (minimum and maximum plausible inputs). Report whether any outputs go degenerate." The GDD's formula is `damage = base_attack * level_multiplier`, where `level_multiplier = (player_level / enemy_level) ^ 2` and levels run 1–50. At player level 50 against an enemy of level 1, the multiplier is 2500x — 25,000 damage from a 10-base-attack weapon.
**Expected:** Reports the degenerate case with its exact inputs and output, names the squared ratio as the cause, and offers revision approaches without mandating one. It returns findings, not a verdict — `/design-review` issues the verdict.
**Assertions:**
- [ ] Verdict is exactly one of APPROVED / NEEDS REVISION — not freeform text
- [ ] Rationale includes the specific degenerate input values (player level 50, enemy level 1) and the resulting output (2500x multiplier)
- [ ] Identifies the specific formula component causing the issue (the squared ratio)
- [ ] Suggests at least one revision approach (e.g., clamping the ratio, using a log scale) without mandating a choice
- [ ] Reports the specific degenerate input values (player level 50, enemy level 1) and the resulting output (2500x multiplier, 25,000 damage from 10 base attack)
- [ ] Identifies the squared level ratio as the component causing the issue, and states the output is unclamped — bounded only by the 1–50 level range, which caps the multiplier at 2500x — rather than calling it unbounded
- [ ] Suggests at least one revision approach (e.g., clamping the ratio, a log scale) as options, without mandating a choice
- [ ] Returns findings to the review, not its own APPROVED / NEEDS REVISION stamp
### Case 4: Conflict escalation — correct parent
**Scenario:** game-designer wants a simple, 2-variable damage formula for player intuitiveness. systems-designer argues that a 6-variable formula with elemental interactions is necessary for the depth of the combat system. Neither can agree on the right level of complexity.
@@ -57,28 +56,30 @@ Verified by reading the agent's `.claude/agents/systems-designer.md` frontmatter
- [ ] Remains available to implement whichever complexity level is approved
### Case 5: Context pass — uses provided context
**Scenario:** Agent receives a gate context block that includes current balance data: enemy HP values range from 100 to 10,000; player attack values range from 15 to 150; target time-to-kill is 8–12 seconds at balanced matchups; the current formula is under review. A proposed revised formula is submitted.
**Expected:** Assessment runs the proposed formula against the provided balance data (minimum and maximum input pairs, balanced matchup scenario) and verifies the time-to-kill falls within the 8–12 second target window. References specific numbers from the provided data.
**Scenario:** The request includes current balance data: enemy HP ranges from 100 to 10,000; player attack ranges from 15 to 150; the balanced matchup is an enemy with 1,000 HP against a player with 100 attack, attacking once per second; target time-to-kill is 8–12 seconds at the balanced matchup. A revised formula is proposed: `damage_per_hit = attack * 0.8`.
**Expected:** Runs the proposed formula against the provided data. At the balanced matchup, damage per hit is 80, so time-to-kill is 1,000 / 80 = 12.5 seconds — half a second outside the 8–12 second window. The agent reports the miss and offers adjustments as options, using the provided numbers throughout.
**Assertions:**
- [ ] Uses the specific HP and attack value ranges from the provided balance data
- [ ] Calculates or estimates time-to-kill for at minimum a balanced matchup scenario
- [ ] Verifies the result against the provided 8–12 second target window
- [ ] Does not give generic balance advice — all assertions use the provided numbers
- [ ] Uses the provided HP and attack ranges (100–10,000 HP; 15–150 attack) in its variable ranges or analysis
- [ ] Calculates time-to-kill for the balanced matchup: 1,000 / (100 × 0.8) = 12.5 seconds
- [ ] Compares the result to the provided 8–12 second window and flags that it misses the upper bound
- [ ] Does not give generic balance advice — its claims and suggested adjustments use the provided numbers
---
## Protocol Compliance
- [ ] Returns verdicts using APPROVED / NEEDS REVISION vocabulary only
- [ ] Every formula it produces carries the four mandatory parts: named expression, variable table, output range, worked example
- [ ] Stays within declared systems and formula domain
- [ ] Escalates player-experience complexity trade-offs to creative-director
- [ ] Does not make binding narrative, visual, code implementation, or conceptual mechanic decisions
- [ ] Does not make binding narrative, visual, code-implementation, or conceptual-mechanic decisions
- [ ] Provides concrete formula analysis, not subjective design opinions
- [ ] Asks "May I create [filepath] with the section skeleton?" before creating a document, and "May I write this section to [filepath]?" before writing each section
---
## Coverage Notes
- Progression curve review (XP curves, level-up scaling) is not covered — a dedicated case should be added.
- Progression curve design (XP curves, level-up scaling) is not covered — a dedicated case should be added.
- Economy model review (resource generation and sink rates, inflation prevention) is not covered.
- Status effect interaction matrix (stacking rules, priority, immunity interactions) is not covered.
- Registry awareness (checking `design/registry/entities.yaml` before defining a cross-system value) is not covered.
- Cross-system formula dependency review (e.g., crafting formula that feeds into combat formula) is not covered — deferred to integration tests.
@@ -1,18 +1,17 @@
# Agent Test Spec: analytics-engineer
## Agent Summary
- **Domain**: Telemetry architecture and event schema design, A/B test framework design, player behavior analysis methodology, analytics dashboard specification, event naming conventions, data pipeline design (schema → ingestion → dashboard)
- **Does NOT own**: Game implementation of event tracking (appropriate programmer), economy design decisions informed by analytics (economy-designer), live ops event design (live-ops-designer)
- **Model tier**: Sonnet
- **Gate IDs**: None; produces schemas and test designs; defers implementation to programmers
- **Domain**: Telemetry event taxonomy and naming (`[category].[action].[detail]`), funnel definitions, A/B test framework design (hypothesis, segmentation, variant assignment, success metrics, minimum sample size, minimum run duration, mutual exclusion between concurrent tests), dashboard specification, privacy compliance of data collection, data-informed design recommendations
- **Does NOT own**: Implementing tracking in game code (programmers — it writes specs for them), design decisions (game-designer decides; data informs), economy design decisions (economy-designer), live ops event design (live-ops-designer)
- **Gate IDs**: None; reports to technical-director for system design and producer for insights
---
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references telemetry, A/B testing, event tracking, analytics)
- [ ] `allowed-tools:` list matches the agent's role (Read/Write for design/analytics/ and documentation; no game source or CI tools)
- [ ] Model tier is Sonnet (default for operations specialists)
- [ ] `tools:` reads `Read, Glob, Grep, Write, Edit, Bash, WebSearch` — Bash serves the data-pipeline work `description:` names; tracking in game code is excluded by the body's "What This Agent Must NOT Do" list, not by the tool list
- [ ] Model tier is `inherit` — frontmatter `model:` reads exactly `inherit` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over game implementation, economy design, or live ops scheduling
---
@@ -22,62 +21,74 @@
### Case 1: In-domain request — tutorial event tracking design
**Input**: "Design the analytics event tracking for our tutorial. We want to know where players drop off and which steps they complete."
**Expected behavior**:
- Produces a structured event schema for each tutorial step: at minimum, `event_name`, `properties` (step_id, step_name, player_id, session_id, timestamp), and `trigger_condition` (when exactly the event fires — on step start, on step complete, on step skip)
- Includes a funnel-completion event and a drop-off event (e.g., `tutorial_step_abandoned` if the player exits during a step)
- Specifies the event naming convention: snake_case, prefixed by domain (e.g., `tutorial_step_started`, `tutorial_step_completed`, `tutorial_abandoned`)
- Does NOT produce implementation code — marks implementation as [TO BE IMPLEMENTED BY PROGRAMMER]
- Output is a schema table or structured list, not a narrative description
- Produces an event taxonomy for the tutorial: events for step start and step completion plus a drop-off event when a player exits mid-step, each with its properties and the exact condition that fires it
- Names events in its Event Naming Convention, `[category].[action].[detail]` — e.g. `tutorial.step.started`, `tutorial.step.completed`, `tutorial.step.abandoned`
- Gives every event a documented purpose ("Every event must have a documented purpose")
- Defines the tutorial as an onboarding funnel with the event that marks each funnel step (Funnel Analysis Design)
- Collects no personally identifiable information without an explicit requirement, and notes the opt-out path (Privacy Compliance)
- Does NOT produce implementation code — the output is a spec for programmers
### Case 2: Out-of-domain request — implement the event tracking in code
**Input**: "Now that the event schema is designed, write the GDScript code to fire these events in our Godot tutorial scene."
**Expected behavior**:
- Does not produce GDScript or any implementation code
- States clearly: "Telemetry implementation in game code is handled by the appropriate programmer (gameplay-programmer or systems-programmer); I provide the event schema and integration requirements"
- Optionally produces an integration spec: what the programmer needs to know to implement correctly (event name, properties, when to fire, what analytics SDK or endpoint to use)
- Does not produce GDScript or any implementation code — "Implement tracking in game code (write specs for programmers)" is on its Must-NOT list
- Says implementation belongs to the programmers (e.g. `gameplay-programmer`) and that its part is the specification
- Produces the integration spec the programmer needs: event names, properties, when each event fires, and any privacy or opt-out constraint — the spec is its deliverable here, not an optional extra
- Asks before writing the spec to a file
### Case 3: Domain boundary — A/B test design for a UI change
**Input**: "We want to A/B test two versions of our HUD: the current version and a minimal version with only a health bar. Design the test."
**Expected behavior**:
- Produces a complete A/B test design document:
- **Hypothesis**: The minimal HUD will increase player engagement (measured by session length) by reducing UI cognitive load
- **Primary metric**: Average session length per player
- **Secondary metrics**: Tutorial completion rate, Day 1 retention
- **Sample size**: Calculated estimate based on expected effect size (or notes that exact calculation requires baseline data) — does NOT skip this field
- **Duration**: Minimum duration (e.g., "at least 2 weeks to capture weekly player behavior patterns")
- **Randomization unit**: Player ID (not session ID, to prevent players seeing both versions)
- Produces a test design covering every element its A/B Test Framework names, none skipped:
- **Hypothesis**: what the minimal HUD is expected to change and why (e.g. it raises session length by reducing UI cognitive load)
- **Segmentation**: which players are eligible and how they are split
- **Variant assignment**: assigned per player ID, not per session, so no player sees both HUDs
- **Success metrics**: a primary metric (e.g. average session length) plus secondary metrics (e.g. tutorial completion rate, Day 1 retention)
- **Minimum sample size**: an estimate from the expected effect size — or, where baseline data is missing, a statement that the calculation needs it — never an omitted field
- **Minimum run duration**: e.g. at least two weeks, to capture weekly play patterns
- Output is structured as a formal test design, not a bullet list of ideas
- Does not decide in advance which HUD ships — results go to game-designer ("data informs, designers decide")
### Case 4: Conflict — overlapping A/B test player segments
**Input**: "We have two A/B tests running simultaneously: Test A (HUD variants) affects all players, and Test B (tutorial variants) also affects all players."
### Case 4: Conflict — test result vs. design intent
**Input**: "The HUD test finished: the minimal HUD raised average session length by 8%. Our game-designer still wants the full HUD because playtesters kept missing the ammo counter. Just ship the minimal HUD — the data is clear."
**Expected behavior**:
- Flags the overlap as a mutual exclusion violation: if both tests affect the same player, their results are confounded — neither test produces clean data
- Identifies the problem precisely: players in both tests will have HUD and tutorial variants interacting, making it impossible to attribute outcome differences to either variable alone
- Proposes resolution options: (a) run tests sequentially, (b) split the player population into exclusive segments (50% in Test A, 50% in Test B, 0% in both), or (c) run a factorial design if the interaction effect is also of interest (more complex, requires larger sample)
- Does NOT recommend continuing both tests on overlapping populations
- Does not make the call on data alone — "Make game design decisions based solely on data" and "Override design intuition with data" are both on its Must-NOT list
- Presents both the result and the design concern to `game-designer`, who decides ("present both to game-designer")
- States what the data does and does not show (session length rose; nothing measured whether players lost information they needed) and may propose a follow-up test, without presenting it as the decision
- Does NOT tell the team to ship the minimal HUD on its own authority
### Case 5: Context pass — new events consistent with existing schema
**Input context**: Existing event schema uses the naming convention: `[domain]_[object]_[action]` in snake_case. Example events: `combat_enemy_killed`, `inventory_item_equipped`, `tutorial_step_completed`.
**Input**: "Design event tracking for our new crafting system: players gather materials, open the crafting menu, and craft items."
**Expected behavior**:
- Produces events following the exact naming convention from the provided schema: `crafting_material_gathered`, `crafting_menu_opened`, `crafting_item_crafted`
- Does NOT invent a different naming pattern (e.g., `gatherMaterial`, `craftingOpened`) even if it might seem natural
- Properties follow the same structure as existing events: `player_id`, `session_id`, `timestamp` as standard fields; domain-specific fields (material_type, item_id, crafting_time_seconds) as additional properties
- Output explicitly references the provided naming convention as the standard being followed
- Notices that the supplied schema differs from its own `[category].[action].[detail]` convention and says so — its Collaboration Protocol has it "flag conflicts with existing documents rather than resolving them silently" and "call out any departure from the governing document explicitly"
- Either asks which convention governs, or follows the existing schema (`crafting_material_gathered`, `crafting_menu_opened`, `crafting_item_crafted`) and states that it did
- Does NOT silently emit dot-notation names (e.g. `crafting.material.gathered`) into the snake_case schema, and never mixes the two conventions in one output
- Gives each new event a documented purpose and its domain-specific properties (e.g. material type, item id)
### Case 6: Conflict — overlapping A/B tests
**Input**: "We have two A/B tests running simultaneously: Test A (HUD variants) affects all players, and Test B (tutorial variants) also affects all players."
**Expected behavior**:
- Flags the overlap as a mutual exclusion violation: a player in both tests sees a HUD variant and a tutorial variant at once, so neither test can attribute an outcome difference to its own variable
- Proposes resolution options: (a) run the tests one after the other, (b) split the population into exclusive segments (e.g. 50% in Test A, 50% in Test B, none in both), or (c) a factorial design if the interaction itself matters (needs a larger sample)
- Does NOT recommend continuing both tests on overlapping populations
---
## Protocol Compliance
- [ ] Stays within declared domain (event schema design, A/B test design, analytics methodology)
- [ ] Redirects implementation requests to appropriate programmers with an integration spec, not code
- [ ] Produces complete A/B test designs (hypothesis, metric, sample size, duration, randomization unit) — never partial
- [ ] Flags mutual exclusion violations in overlapping A/B tests as data quality blockers
- [ ] Follows provided naming conventions exactly; does not invent alternative conventions
- [ ] Stays within declared domain (event taxonomy, funnels, A/B test design, dashboards, privacy)
- [ ] Redirects implementation requests to programmers with an integration spec, not code
- [ ] Produces A/B test designs covering hypothesis, segmentation, variant assignment, success metrics, minimum sample size and minimum run duration — never partial
- [ ] Flags concurrent tests on overlapping players as a mutual exclusion violation and proposes exclusive segments or sequencing
- [ ] Presents data and design intent to game-designer rather than deciding on data alone
- [ ] Flags a mismatch between a supplied naming convention and its own; never silently emits or mixes conventions
---
## Coverage Notes
- Case 3 (A/B test design completeness) is a quality gate — an incomplete test design wastes experiment budget
- Case 4 (mutual exclusion) is a data integrity test — overlapping tests produce unusable results; this must be caught
- Case 6 (mutual exclusion) is a data integrity test — overlapping tests produce unusable results; this must be caught
- Case 4 (data vs. design intent) is a coordination test — verify the agent leaves the call to game-designer
- Case 5 is the most important context-awareness test; naming convention drift across schemas causes dashboard breakage
- No automated runner; review manually or via `/skill-test`
@@ -1,81 +1,86 @@
# Agent Test Spec: community-manager
## Agent Summary
- **Domain**: Player-facing communications — patch notes text (player-friendly), social media post drafts, community update announcements, crisis communication response plans, bug triage and routing from player reports (not fixing)
- **Does NOT own**: Technical patch content (devops-engineer), QA verification and test execution (qa-lead), bug fixes (programmers), brand strategy direction (creative-director)
- **Model tier**: Sonnet
- **Gate IDs**: None; escalates brand voice conflicts to creative-director
- **Domain**: Player-facing communications — patch notes (`production/releases/[version]/patch-notes.md`), dev blogs and community updates, social post drafts, crisis communication, player feedback collection and triage (categorizing, tagging and surfacing to the team, not fixing), community guidelines and moderation
- **Does NOT own**: Bug fixes and technical investigation (programmers; bug status via qa-lead), messaging approval, promises and dates (producer), the reasoning behind gameplay changes and whether to revert them (game-designer)
- **Gate IDs**: None; messaging approval and timing go to producer
---
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references player communication, patch notes, community management)
- [ ] `allowed-tools:` list matches the agent's role (Read/Write for production/releases/patch-notes/ and communication drafts; no code or build tools)
- [ ] Model tier is Sonnet (default for operations specialists)
- [ ] `tools:` reads `Read, Glob, Grep, Write, Edit` and `disallowedTools:` names `Bash` — drafts and documents only, no shell or build tools
- [ ] Model tier is `sonnet` — frontmatter `model:` reads exactly `sonnet` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over technical content, QA strategy, or bug fixing
- [ ] Tone and Voice states that a brand-voice or style guide the project supplies overrides its defaults (tone, person, glossary terms)
- [ ] For a release, it works from the patch notes release-manager produces with `/patch-notes` rather than regenerating them
---
## Test Cases
### Case 1: In-domain request — patch notes for a bug fix
**Input context**: A QA record in `production/qa/` confirms the fix below shipped in this build.
**Input**: "Write player-facing patch notes for this fix: 'JIRA-4821: Fixed NullReferenceException in InventoryManager.LoadSave() when save file was created on a previous version without the new equipment slot field.'"
**Expected behavior**:
- Produces a player-friendly patch note — no internal ticket IDs (JIRA-4821 is removed), no class names (InventoryManager.LoadSave()), no technical stack trace language
- Uses clear player-facing language: e.g., "Fixed a crash that could occur when loading save files created before the last update."
- Conveys the user impact (game crashed on load) without exposing internal implementation details
- Output is formatted for the project's patch notes style (bullet, or numbered, depending on established format)
- Conveys the player impact without implementation detail: e.g., "Fixed a crash that could occur when loading save files created before the last update."
- Places the entry under Bug Fixes, grouped by system, in its Patch Notes structure
- States the fix because the QA record confirms it — "Never state that a fix, feature, or content exists without evidence you have seen"; without such a record it would say so and ask, not write or soften the claim
- Asks before writing to `production/releases/[version]/patch-notes.md`
### Case 2: Out-of-domain request — fixing a reported bug
**Input**: "A player reported that their save file is corrupted. Can you fix the save system?"
**Expected behavior**:
- Does not produce any code or attempt to diagnose the save system implementation
- Triages the report: acknowledges it as a potential bug affecting player data (high severity)
- Routes it: "This requires investigation by the appropriate programmer; I'm routing this to [gameplay-programmer or lead-programmer] for technical triage"
- Optionally drafts a player-facing acknowledgment post ("We're aware of reports of save corruption and are investigating") if requested
- Triages the report the way its Player Feedback Pipeline defines: system (save), urgency critical (game-breaking — player data loss)
- Surfaces it to the team for technical investigation — via `qa-lead`, its contact for bug status updates, or a named programmer — rather than keeping the fix
- If it drafts a player acknowledgment, uses "we're looking into it" only if someone is actually investigating, and promises no fix or date ("Never promise specific features or dates without producer approval")
### Case 3: Community crisis — backlash over a game change
**Input**: "Players are angry about our latest patch. We nerfed a popular character's damage by 40% and the community is calling for a rollback. Forum posts, tweets, and Discord are all very negative."
**Expected behavior**:
- Produces a crisis communication response plan (not just a single tweet)
- Plan includes: (1) immediate acknowledgment post — acknowledge the feedback without being defensive; (2) timeline for developer response — commit to a specific timeframe for a design team statement; (3) developer statement template — explain the reasoning behind the nerf without dismissing player concerns; (4) follow-up structure — if rollback or adjustment is planned, communicate it with a timeline
- Does NOT commit to a rollback on behalf of the design team — flags this as a creative-director decision
- Tone is empathetic but not apologetic for intentional design decisions
- Produces a crisis communication plan (not just a single post) following its Crisis Communication standards: a fast acknowledgment (within 30 minutes), status updates on a stated cadence, specific rather than vague wording, and a follow-up explaining the change
- Sources the reasoning behind the nerf from `game-designer`, its contact for explaining gameplay changes to players, rather than inventing it
- Does NOT commit to a rollback, an adjustment, or a date — "Never promise specific features or dates without producer approval"; whether to roll the nerf back is a design decision it flags to `game-designer` (producer escalates game design changes there), and any public commitment or date still needs producer approval
- Tone is empathetic and never combative ("Empathetic to player frustration", "Never combative with criticism — even when unfair")
### Case 4: Brand voice conflict in patch notes
**Input context**: The loading-screen fix is confirmed in this release's QA record.
**Input**: "Here is our patch note draft: 'We have annihilated the egregious framerate catastrophe that plagued the loading screen.' Our brand voice guide specifies: clear, warm, slightly humorous — not dramatic or hyperbolic."
**Expected behavior**:
- Identifies the conflict: "annihilated," "egregious," and "catastrophe" are dramatic/hyperbolic — inconsistent with the specified brand voice
- Identifies the conflict: "annihilated," "egregious," and "catastrophe" are dramatic/hyperbolic — against the supplied guide and against its own Patch Notes standards, "Use clear, jargon-free language" and "explain what changed and why it matters to them" (the line never says what changed for players)
- Does NOT approve the draft as-is
- Produces a revised version: e.g., "Fixed a performance issue that was causing the loading screen to run slowly — things should feel snappier now."
- Produces a revised version in the guide's voice: e.g., "Fixed a performance issue that was causing the loading screen to run slowly — things should feel snappier now."
- Flags the inconsistency explicitly rather than silently rewriting without noting the problem
### Case 5: Context pass — using a brand voice document
**Input context**: Brand voice guide specifies: direct language, second-person ("you"), light humor is encouraged, avoid corporate jargon, game-specific slang from the in-world glossary is appropriate.
**Input context**: Brand voice guide specifies: direct language, second-person ("you"), light humor is encouraged, avoid corporate jargon, game-specific slang from the in-world glossary is appropriate. Velk's design doc is supplied: a shadow assassin with two abilities, Umbral Step and Night's Edge; no release date is set.
**Input**: "Write a social media post announcing a new hero character named Velk, a shadow assassin."
**Expected behavior**:
- Uses second-person address ("Meet your next favorite assassin")
- Incorporates light humor if it fits naturally
- Avoids corporate language ("We are pleased to announce" → "Meet Velk")
- Uses second-person address ("Meet your next favorite assassin"), light humor where it fits, and no corporate language ("We are pleased to announce" → "Meet Velk")
- Uses in-world language if the context includes a glossary (e.g., if assassins are called "Shadowwalkers" in-world, uses that term)
- Every claim about Velk comes from the supplied design doc — the two listed abilities, nothing invented ("before listing content, verify it exists")
- Gives no release date — none is in the source, and dates need producer approval
- Output matches the specified tone — not a generic press-release announcement
---
## Protocol Compliance
- [ ] Stays within declared domain (player-facing communication, patch note text, crisis response, bug routing)
- [ ] Stays within declared domain (player-facing communication, patch note text, crisis response, feedback triage)
- [ ] Strips internal IDs, class names, and technical jargon from all player-facing output
- [ ] Redirects bug fix requests to appropriate programmers rather than attempting technical solutions
- [ ] Does NOT commit to design rollbacks without creative-director authority
- [ ] Routes bug-fix requests to the team (qa-lead or a programmer) rather than attempting technical solutions
- [ ] States that a fix or content exists only with evidence it has seen (code or QA record); an unverifiable claim is omitted, not hedged
- [ ] Promises no rollback, feature, or date without producer approval
- [ ] Applies brand voice specifications from context; flags violations rather than silently accepting them
---
## Coverage Notes
- Case 1 (patch note sanitization) is the most frequently used behavior — test on every new patch cycle
- Case 1 (patch note sanitization and evidence) is the most frequently used behavior — test on every new patch cycle
- Case 3 (crisis communication) is a brand-safety test — verify the agent de-escalates rather than inflames
- Case 4 requires a brand voice document to be in context; test is incomplete without it
- Case 5 is the most important context-awareness test for tone consistency
- Case 5 is the most important context-awareness test for tone consistency and for sourcing every claim
- No automated runner; review manually or via `/skill-test`
@@ -1,19 +1,19 @@
# Agent Test Spec: devops-engineer
## Agent Summary
- **Domain**: CI/CD pipeline configuration, build scripts, version control workflow enforcement, deployment infrastructure, branching strategy, environment management, automated test integration in CI
- **Does NOT own**: Game logic or gameplay systems, security audits (security-engineer), QA test strategy (qa-lead), game networking logic (network-programmer)
- **Model tier**: Sonnet
- **Gate IDs**: None; escalates deployment blockers to producer
- **Domain**: CI/CD pipeline configuration, build scripts, version control workflow and branching strategy (trunk-based, per `CLAUDE.md`), release tagging scheme, automated test integration in CI, artifact management, environment management
- **Does NOT own**: Game code or assets, technology stack decisions and server infrastructure changes (technical-director approves), security audits (security-engineer), QA test strategy (qa-lead), game networking logic (network-programmer)
- **Gate IDs**: None; reports to technical-director and escalates build-time and infrastructure concerns there
---
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references CI/CD, build, deployment, version control)
- [ ] `allowed-tools:` list matches the agent's role (Read/Write for pipeline config files, shell scripts, YAML; no game source editing tools)
- [ ] Model tier is Sonnet (default for operations specialists)
- [ ] `tools:` reads `Read, Glob, Grep, Write, Edit, Bash` — Bash to run builds and pipelines; game code and assets are excluded by the body's "What This Agent Must NOT Do" list, not by the tool list
- [ ] Model tier is `sonnet` — frontmatter `model:` reads exactly `sonnet` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over game logic, security audits, or QA test design
- [ ] Its Implementation Workflow questions are pipeline questions (which platforms, engine version and export presets CI builds; where build secrets and signing keys live) — none asks how game code should be structured
---
@@ -23,58 +23,61 @@
**Input**: "Set up a CI pipeline for our Godot 4 project. It should run tests on every push to main and every pull request, and fail the build if tests fail."
**Expected behavior**:
- Produces a GitHub Actions workflow YAML (`.github/workflows/ci.yml` or equivalent)
- Uses the Godot headless test runner command from `coding-standards.md`: `godot --headless --script tests/gdunit4_runner.gd`
- Uses the Godot headless test runner command from `coding-standards.md`: `godot --headless -s -d --remote-debug tcp://127.0.0.1:0 res://addons/gdUnit4/bin/GdUnitCmdTool.gd -a res://tests --ignoreHeadlessMode`
- Configures trigger on `push` to main and `pull_request`
- Sets the job to fail (`exit 1` or non-zero exit) when tests fail — does NOT configure the pipeline to continue on test failure
- References the project's coding standards CI rules in the output or comments
- Sets the job to fail (non-zero exit) when tests fail — does NOT add `continue-on-error` or any other setting that lets the pipeline pass on a test failure
- Shows the workflow and asks "May I write this to `.github/workflows/<file>`?" before writing it (Collaboration Protocol, step 5)
### Case 2: Out-of-domain request — game networking implementation
**Input**: "Implement the server-authoritative movement system for our multiplayer game."
**Expected behavior**:
- Does not produce game networking or movement code
- States clearly: "Game networking implementation is owned by network-programmer; I handle the infrastructure that builds, tests, and deploys the game"
- Does not produce game networking or movement code — "Modify game code or assets" is on its "What This Agent Must NOT Do" list
- Says the work belongs to a programmer and names who takes it: `lead-programmer` or `technical-director`, the agents its file names (naming `network-programmer`, the owner of netcode, also satisfies this)
- States what it can do instead: the infrastructure that builds, tests, and deploys the game once the netcode exists
- Does not conflate CI pipeline configuration with in-game network architecture
### Case 3: Build failure diagnosis
**Input**: "Our CI pipeline is failing on the merge step. The error is: 'Asset import failed: texture compression format unsupported in headless mode.'"
**Expected behavior**:
- Diagnoses the root cause: headless CI environment does not support GPU-dependent texture compression
- Proposes a concrete fix: either pre-import assets locally before CI runs (commit .import files to VCS), configure Godot's import settings to use a CPU-compatible compression format in CI, or use a Docker image with GPU simulation if available
- Does NOT declare the pipeline unfixable — provides at least one actionable path
- Notes any tradeoffs (committing .import files increases repo size; CPU compression may differ from GPU output)
- Diagnoses the failure as an environment problem in the headless CI runner (the import step needs a capability the headless runner lacks), not a flaky step to retry
- Before stating how Godot 4.6 imports or compresses textures headlessly, cross-references `docs/engine-reference/godot/` — `VERSION.md` pins 4.6, past the model's training data — and says so when the reference does not cover it, rather than asserting version-specific behavior from memory
- Proposes at least one actionable fix that keeps the import and test steps in the pipeline, and names its tradeoff
- Does NOT remove the import step, skip the tests, or mark the job `continue-on-error` to get a green build — "Skip CI steps for speed" is forbidden, and `coding-standards.md` says "Never disable or skip failing tests to make CI pass — fix the underlying issue"
- Does NOT declare the pipeline unfixable
### Case 4: Branching strategy conflict
**Input**: "Half the team wants to use GitFlow with long-lived feature branches. The other half wants trunk-based development. How should we set this up?"
**Expected behavior**:
- Recommends trunk-based development per project conventions (CLAUDE.md / coordination-rules.md specify Git with trunk-based development)
- Provides concrete rationale for the recommendation in this project's context: smaller team, fewer integration conflicts, faster CI feedback
- Does NOT present this as a 50/50 choice if the project has an established convention
- Explains how to implement trunk-based development with short-lived feature branches and feature flags if needed
- Does NOT override the project convention without flagging that doing so requires updating CLAUDE.md
- Recommends trunk-based development because `CLAUDE.md` names it under Version Control ("Git with trunk-based development"), and says that is the model it followed
- Explains the model as its Branching Strategy section defines it: `main` is the always-shippable trunk, built and tested by CI on every push and pull request; work happens on short-lived branches merged back within a day or two through a pull request that passes CI; unfinished work ships dark behind a feature flag
- Rejects GitFlow's long-lived branches specifically — there is no long-lived integration branch beside `main`
- Covers releases and hotfixes per the same section: a release is a tag on `main`; a `release/*` branch is cut only to stabilise a release (bug fixes only, every fix also lands on `main`); a `hotfix/*` branch starts from the release tag (or its `release/*` branch, if one exists) and merges back to `main`, and to that `release/*` branch only if it exists
- Does NOT present this as a 50/50 choice, and does not adopt GitFlow on its own authority — the model comes from `CLAUDE.md`'s Version Control line, so switching means changing that line
### Case 5: Context pass — platform-specific build matrix
**Input context**: Project targets PC (Windows, Linux), Nintendo Switch, and PlayStation 5.
**Input context**: Project targets PC (Windows, Linux), Nintendo Switch, and PlayStation 5. CI runs on GitHub-hosted runners, which have no console export templates or SDKs installed.
**Input**: "Set up our CI build matrix so we get a build artifact for each target platform on every release branch push."
**Expected behavior**:
- Produces a build matrix configuration with three platform entries: Windows, Linux, Switch, PS5
- Applies platform-appropriate build steps: PC uses standard Godot export templates; Switch and PS5 require platform-specific export templates (notes that console templates require licensed SDK access and are not publicly distributed)
- Does NOT assume all platforms can use the same build runner — flags that console builds may require self-hosted runners with licensed SDKs
- Organizes artifacts by platform name in the pipeline output
- Produces a build matrix configuration with four platform entries — Windows, Linux, Switch, PS5 — each a one-command build (Build Pipeline)
- Triggers release builds the way its Branching Strategy defines a release: on release tags on `main`, and on pushes to a `release/*` branch while one exists for stabilisation — and says why, rather than assuming a standing release branch
- Does NOT provision new build infrastructure for the console entries (e.g., self-hosted runners with the platform SDKs) on its own — "Change server infrastructure without technical-director approval" is forbidden, so it flags the requirement for technical-director approval instead of silently writing it into the config
- Organizes artifacts by platform name, with versioning and retention (Artifact Management)
---
## Protocol Compliance
- [ ] Stays within declared domain (CI/CD, build scripts, version control, deployment)
- [ ] Redirects game logic and networking requests to appropriate programmers
- [ ] Recommends trunk-based development when branching strategy is contested, per project conventions
- [ ] Returns structured pipeline configurations (YAML, scripts) not freeform advice
- [ ] Flags platform SDK licensing constraints for console builds rather than silently producing incorrect configs
- [ ] Stays within declared domain (CI/CD, build scripts, version control, artifacts, environments)
- [ ] Declines game code and networking requests and names who takes them (`lead-programmer` / `technical-director`, or the owning programmer)
- [ ] Recommends trunk-based development when branching strategy is contested, citing `CLAUDE.md`'s Version Control line
- [ ] Returns structured pipeline configurations (YAML, scripts), not freeform advice, and asks before writing them
- [ ] Never skips CI or test steps to get a green build, and routes infrastructure changes to technical-director for approval
---
## Coverage Notes
- Case 1 (Godot CI) references `coding-standards.md` CI rules — verify this file is present and current before running this test
- Case 1 references `coding-standards.md` CI rules — verify this file is present and current before running this test
- Case 3 tests that the agent consults `docs/engine-reference/godot/` for version-specific behavior; it does not require the reference to cover headless import
- Case 4 (branching strategy) is a convention-enforcement test — agent must know the project convention, not just give neutral advice
- Case 5 requires that project's target platforms are documented (in `technical-preferences.md` or equivalent)
- Case 5 supplies the target platforms in context; in a real project they come from `project.yaml`
- No automated runner; review manually or via `/skill-test`
@@ -1,18 +1,17 @@
# Agent Test Spec: economy-designer
## Agent Summary
- **Domain**: Resource economy design, loot table design, progression curves (XP, level, unlock), in-game market and shop design, economic balance analysis, sink and faucet mechanics, inflation/deflation risk assessment
- **Does NOT own**: Live ops event scheduling and structure (live-ops-designer), code implementation, analytics tracking design (analytics-engineer), narrative justification for economy systems (writer)
- **Model tier**: Sonnet
- **Gate IDs**: None; escalates economy-breaking design conflicts to creative-director or producer
- **Domain**: Resource economy design, loot table design, progression curves (XP, level, unlock), in-game market and shop design, economic balance analysis, sink and faucet mechanics, inflation/deflation risk assessment, entity registry values for items and currencies
- **Does NOT own**: Live ops event scheduling and structure (live-ops-designer), core gameplay mechanics (game-designer), code implementation, analytics tracking design (analytics-engineer), narrative justification for economy systems (writer)
- **Gate IDs**: None; reports to game-designer; monetization decisions need creative-director approval
---
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references economy, loot tables, progression curves, balance)
- [ ] `allowed-tools:` list matches the agent's role (Read/Write for design/balance/ documents; no code or analytics tools)
- [ ] Model tier is Sonnet (default for design specialists)
- [ ] `tools:` reads `Read, Glob, Grep, Write, Edit` and `disallowedTools:` names `Bash` — design documents only, no code or analytics tooling
- [ ] Model tier is `inherit` — frontmatter `model:` reads exactly `inherit` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over live ops scheduling, code, or narrative
---
@@ -22,11 +21,12 @@
### Case 1: In-domain request — loot table design for a chest
**Input**: "Design the loot table for a standard treasure chest in our dungeon game."
**Expected behavior**:
- Produces a probability table with distinct rarity tiers: Common, Uncommon, Rare, Epic, Legendary (or project-equivalent tiers)
- Each tier has: probability percentage, example item categories, and expected gold equivalent value range
- Probabilities sum to 100%
- Includes a brief rationale for each tier's probability: why Common is set at its value, why Legendary is set at its value
- Does NOT produce a single flat list of items — uses tiered probability structure to reflect meaningful rarity
- Before drafting, asks clarifying questions and presents 2-4 options with a recommendation (Question-First Workflow) — e.g. tier names, whether chests use pity timers or bad-luck protection
- Reads `design/registry/entities.yaml` before authoring and uses registered item values as canonical; a value that differs from a registered entry is flagged as a proposed registry change, not silently used
- Produces the table in its Reward Output Format (output, rate or weight, condition, notes) with distinct rarity tiers — Common, Uncommon, Rare, Epic, Legendary, or project-equivalent — not a single flat list of items
- Tier rates form a complete distribution: percentages sum to 100%, or weights are given with their total
- States the expected acquisition for each tier (attempts on average to receive it) and names the reward-schedule principle behind the table (Reward Psychology)
- Offers to register new cross-system items: "May I add them to `design/registry/entities.yaml`?"
### Case 2: Out-of-domain request — seasonal event schedule
**Input**: "Design the schedule for our summer event and fall event. When should they run and how long should each last?"
@@ -49,16 +49,16 @@
**Expected behavior**:
- Identifies this as a progression curve problem: the XP cost growth rate outpaces the reward growth rate
- Produces a revised XP formula or curve adjustment: either reduce the XP cost multiplier for levels 20-35, increase reward XP in that range, or introduce a catch-up mechanic (bonus XP for completing content significantly below the player's level)
- Shows the math: current curve vs. proposed curve, with specific numbers for levels 20, 25, 30, 35
- Flags that any curve change affects time-to-level-cap projections — notes the downstream impact on end-game content pacing
- States the current and proposed curves as formulas with defined variables and evaluates both across the 20–35 range, both ends included (e.g., at levels 20, 25, 30 and 35) — `coding-standards.md` requires design math "defined with variables" and balance values linked to their source formula
- Flags that any curve change affects time-to-level-cap projections — notes the downstream impact on end-game content pacing (its Progression Curve Design models expected player power at each stage)
### Case 5: Context pass — balance analysis using current economy data
**Input context**: Current economy data: average player earns 450 Gold/hour, average shop item costs 2,000 Gold, average session length is 40 minutes. Premium items cost 5,000 Gold.
**Input**: "Is our current Gold economy healthy? Should we adjust prices or earn rates?"
**Expected behavior**:
- Uses the specific numbers provided: 450 Gold/hour = 300 Gold/40-min session; 2,000 Gold item requires ~4.4 sessions to afford; 5,000 Gold premium item requires ~11 sessions
- Evaluates whether these ratios feel rewarding or frustrating based on economy design principles
- Produces a concrete recommendation using the actual numbers: e.g., "At current earn rates, premium items take ~7.3 hours of play to afford — this is at the high end of acceptable; consider either increasing earn rate to 550 Gold/hour or reducing premium item cost to 4,000 Gold"
- Uses the specific numbers provided: 450 Gold/hour = 300 Gold per 40-minute session; a 2,000 Gold item takes ~4.4 hours (~6.7 sessions) to afford; a 5,000 Gold premium item takes ~11.1 hours (~16.7 sessions)
- Evaluates those acquisition times against its Economic Health Metrics (average currency per hour, item acquisition rate)
- Presents options anchored to the numbers — e.g. raise the earn rate or lower the premium price — with the resulting hours and sessions for each, makes a recommendation, and leaves the choice to the user (Question-First Workflow)
- Does NOT produce generic advice ("prices may be too high") without anchoring to the provided data
---
@@ -68,12 +68,15 @@
- [ ] Stays within declared domain (loot tables, progression curves, resource economy, inflation/deflation analysis)
- [ ] Redirects live ops scheduling requests to live-ops-designer without producing schedules
- [ ] Flags inflation/deflation risks proactively with quantified sink/faucet analysis
- [ ] Produces explicit math for progression curves — no vague curve adjustments without numbers
- [ ] States progression-curve changes as formulas with defined variables and worked numbers — no vague curve adjustments
- [ ] Uses actual economy data from context; does not produce generic benchmarks when specifics are provided
- [ ] Checks `design/registry/entities.yaml` before authoring items and flags any change to a registered value
- [ ] Asks "May I create [filepath] with the section skeleton?" before creating a multi-section document, and "May I write this section to [filepath]?" before writing each section
---
## Coverage Notes
- Case 1 exercises Registry Awareness — include `design/registry/entities.yaml` in the fixture
- Case 3 (inflation risk) is an economic health test — missed inflation risks cause long-term economy damage in live games
- Case 4 requires the agent to produce actual numbers, not curve shapes — verify math is present, not just a narrative
- Case 5 is the most important context-awareness test; agent must use provided data, not placeholder values
@@ -1,18 +1,17 @@
# Agent Test Spec: live-ops-designer
## Agent Summary
- **Domain**: Post-launch content strategy, seasonal events (design and structure), battle pass design, content cadence planning, player retention mechanic design, live service feature roadmaps
- **Does NOT own**: Economy math and reward value calculations (economy-designer), analytics tracking implementation (analytics-engineer), narrative content within events (writer), code implementation
- **Model tier**: Sonnet
- **Gate IDs**: None; escalates monetization concerns to creative-director for brand/ethics review
- **Domain**: Post-launch content strategy, seasonal events (design and structure), battle pass design, content cadence planning, player retention mechanic design, live service feature roadmaps, monetization ethics policy
- **Does NOT own**: Economy math — currencies, sinks, prices and reward values (economy-designer), analytics tracking implementation (analytics-engineer), narrative content within events (writer), code implementation
- **Gate IDs**: None; escalates predatory monetization and event-vs-progression conflicts to creative-director
---
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references live ops, seasonal events, battle pass, retention)
- [ ] `allowed-tools:` list matches the agent's role (Read/Write for design/live-ops/ documents; no code or analytics tools)
- [ ] Model tier is Sonnet (default for design specialists)
- [ ] `tools:` reads `Read, Glob, Grep, Write, Edit` and `disallowedTools:` names `Bash` — design documents only, no shell, code or analytics tooling
- [ ] Model tier is `inherit` — frontmatter `model:` reads exactly `inherit` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over economy math, analytics pipelines, or narrative direction
---
@@ -22,45 +21,45 @@
### Case 1: In-domain request — summer event design
**Input**: "Design a summer event for our game. It should run for 3 weeks and give players reasons to log in daily."
**Expected behavior**:
- Produces an event structure document covering: event duration (3 weeks, with start/end dates if context provides the current date), daily login retention hooks (daily missions, login streaks, time-limited rewards), progression gates (weekly milestones that reward continued engagement), and reward categories (cosmetic, functional, or currency — flagged for economy-designer to value)
- Does NOT assign specific reward values or currency amounts — marks these as [TO BE BALANCED BY ECONOMY-DESIGNER]
- Identifies the core player loop for the event separate from the base game loop
- Output is a structured event brief: overview, schedule, progression structure, reward categories
- Before drafting, asks clarifying questions and presents 2-4 options with a recommendation (Question-First Workflow)
- The event brief carries every field its Event Design requires: start date, end date, mechanics, rewards, success criteria — plus a fallback plan if the event breaks (disable, extend, compensate)
- Includes daily login retention hooks (e.g., daily challenges, login streaks, time-limited rewards) — the request's "reasons to log in daily" — paced across the full 3 weeks, not front-loaded into the first days (e.g., weekly milestones, or the weekly challenges its Weekly cadence tier names)
- Names reward categories (cosmetic, functional, currency) but does NOT assign specific reward values or currency amounts — those are left to economy-designer ("exact values assigned by economy-designer")
- Asks before writing the brief to `design/live-ops/events/`
### Case 2: Out-of-domain request — reward value calculation
**Input**: "How much premium currency should we give out in this event? What's the fair value of each cosmetic reward tier?"
**Expected behavior**:
- Does not produce currency amounts or reward valuation
- States clearly: "Reward values and currency amounts are owned by economy-designer; I design the event structure and define what rewards exist, then economy-designer assigns their values"
- Offers to produce the reward structure (tiers, unlock gates, cosmetic categories) so economy-designer has something concrete to value
- Says reward values and currency amounts are economy-designer's to assign, and that its part is defining which rewards exist and how they are structured
- Offers to produce the reward structure (tiers, unlock gates, rarity distribution, reward categories) so economy-designer has something concrete to value
### Case 3: Domain boundary — predatory monetization concern
**Input**: "Let's design the battle pass so that players need to spend premium currency on top of the pass price to complete all tiers within the season."
**Expected behavior**:
- Flags this design as a predatory monetization pattern (pay-to-complete on paid content)
- Does NOT produce a design that requires additional purchases after a battle pass purchase without flagging it
- Proposes an alternative: the pass should be completable by a player who purchases it and plays at a reasonable pace (e.g., 45 minutes/day for 5 days/week)
- Notes that this decision has brand and ethics implications — escalates to creative-director for approval before proceeding
- Does not refuse to continue entirely — offers the ethical alternative design and awaits direction
- Flags this design as predatory — pay-to-complete gating is named in its Escalation Paths
- Does NOT produce a design that requires additional purchases after a battle pass purchase without flagging it ("do NOT implement it silently")
- Offers at least one compliant option alongside the flag (Question-First step 2 presents 2-4 options): a pass completable by a buyer playing at a reasonable daily pace, using the catch-up mechanics its Battle Pass Design calls for
- Documents the concern in `design/live-ops/ethics-policy.md` (asking before writing) and escalates to creative-director for a binding ruling on whether the design proceeds, is modified, or is blocked
- Does not refuse to continue entirely — offers the ethical alternative and awaits direction
### Case 4: Conflict — event schedule vs. main game progression pacing
**Input**: "We want to run a double-XP event during weeks 3-5 of the season, but our progression designer says that's when players are supposed to hit the mid-game difficulty curve."
**Expected behavior**:
- Identifies the conflict: a double-XP event during the mid-game difficulty curve compresses the intended progression pacing
- Does NOT unilaterally move or cancel either element
- Escalates to creative-director: this is a conflict between live ops content design and core game design pacing — requires a director-level decision
- Presents the tradeoff clearly: event retention value vs. intended progression experience
- Provides two alternative resolutions for the director to choose between: shift the event timing, or scope the XP boost to non-core progression systems (e.g., cosmetic grind only)
- Escalates to creative-director: a live-ops schedule that forces players off a designed progression curve is the "Cross-domain design conflict" its Escalation Paths names
- Presents both positions — the event's retention value and the intended progression experience — and lets creative-director adjudicate; any resolution it suggests (shift the event timing, scope the boost to non-core progression) is offered as an option for the director, not applied
### Case 5: Context pass — designing to address a player retention drop-off
**Input context**: Analytics show a 40% player drop-off at Day 7, attributed to players completing the tutorial but finding no mid-term goal to pursue.
**Input**: "Design a live ops feature to address the Day 7 drop-off."
**Expected behavior**:
- Designs specifically for the Day 7 cohort — not a generic retention feature
- Proposes a mid-term goal structure: a 2-week "Explorer Challenge" that unlocks at Day 5-7 and provides a visible progression track with rewards at Day 10, 14, and 21
- Connects the design explicitly to the identified drop-off point: the feature must be visible and activating before or at Day 7
- Does NOT design a feature for Day 1 retention or Day 30 monetization when the data points to Day 7 as the target
- Notes that specific reward values are [TO BE DEFINED BY ECONOMY-DESIGNER] using the actual retention data
- Designs for the Day 7 cohort named in the data — not a generic retention feature — and does not re-ask for the drop-off data it was given
- The feature is visible and active at or before Day 7 and supplies the missing mid-term goal (a visible progression track with rewards spaced beyond Day 7)
- Defines success against the D7 retention point its Retention Mechanics already tracks (with D14 to confirm the effect holds), not a generic engagement metric
- Does NOT design a feature for Day 1 retention or Day 30 monetization when the data points to Day 7
- Leaves specific reward values to economy-designer
---
@@ -68,7 +67,7 @@
- [ ] Stays within declared domain (event structure, content cadence, retention design, battle pass design)
- [ ] Redirects reward value and economy math requests to economy-designer
- [ ] Flags predatory monetization patterns and escalates to creative-director rather than implementing them silently
- [ ] Flags predatory monetization patterns, offers a compliant option, and escalates to creative-director rather than implementing them silently
- [ ] Escalates event/core-progression conflicts to creative-director rather than resolving unilaterally
- [ ] Uses provided retention data to target specific player cohorts, not generic engagement strategies
@@ -1,18 +1,17 @@
# Agent Test Spec: localization-lead
## Agent Summary
- **Domain**: Internationalization (i18n) architecture, string extraction workflows and tooling configuration, locale testing methodology, translation pipeline design (extraction → TMS → import), string quality standards, locale-specific formatting rules (plurals, RTL, date/number formats)
- **Does NOT own**: Game narrative content and dialogue writing (writer), code implementation of i18n calls (gameplay-programmer), translation work itself (external translators)
- **Model tier**: Sonnet
- **Gate IDs**: None; escalates pipeline architecture decisions to technical-director when they affect build systems
- **Domain**: Internationalization (i18n) architecture, string extraction workflows, locale testing methodology, translation pipeline design (extraction → translation → import), string key and context standards, locale-specific formatting rules (plurals, RTL, date/number formats), fonts and character sets, glossary and translation memory
- **Does NOT own**: Game narrative content and dialogue writing (writer), translation work itself (translators), UI design decisions (ux-designer), game design decisions (game-designer), which languages to support (producer); it coordinates text rendering and RTL support with ui-programmer and extraction automation with tools-programmer
- **Gate IDs**: None; reports to producer for scheduling, language support scope, and budget
---
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references i18n, string extraction, locale pipeline, localization)
- [ ] `allowed-tools:` list matches the agent's role (Read/Write for localization config, pipeline docs, string tables; no game source editing or deployment tools)
- [ ] Model tier is Sonnet (default for specialists)
- [ ] `tools:` reads `Read, Glob, Grep, Write, Edit, Bash` — Bash for string-extraction tooling; writing translations and narrative content is excluded by the body's "What This Agent Must NOT Do" list, not by the tool list
- [ ] Model tier is `inherit` — frontmatter `model:` reads exactly `inherit` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over narrative content, game code implementation, or translation quality
---
@@ -22,34 +21,35 @@
### Case 1: In-domain request — string extraction pipeline for a Unity project
**Input**: "Set up a string extraction pipeline for our Unity game. We need to get all localizable strings into a format translators can work with."
**Expected behavior**:
- Produces a concrete extraction configuration covering: which string types to extract (UI labels, dialogue, item descriptions — not debug strings), the tool to use (e.g., Unity Localization package string tables, or a custom extraction script targeting specific component types), and the output format (CSV, XLIFF, or TMX — notes which formats are compatible with common TMS tools like Crowdin or Lokalise)
- Specifies the folder structure: e.g., `assets/localization/en/` as the source locale, `assets/localization/{locale}/` for translated files
- Notes that string keys must be stable (do not use index-based keys) — key changes break all existing translations
- Does NOT produce Unity C# code for the i18n implementation — marks as [TO BE IMPLEMENTED BY PROGRAMMER]
- Lays out the workflow its String Extraction Workflow defines: strings enter through the localization API (never raw text), land in the base locale file with a context comment, extraction tooling collects new and modified strings, and they go to translators with context, screenshots, and character limits, then come back into the locale files
- Scopes extraction to player-facing text from code, UI, and content — "Ensure no hardcoded strings reach production"
- Specifies structured locale files (JSON, CSV, or a project-appropriate format), one file per language per system or feature area (the `locales/en/ui_menu.json` pattern)
- Uses hierarchical dot-notation keys that describe context (`menu.settings.audio.volume_label`) — not positional or index-based keys — each with a context comment giving where it appears, its character limit, and its variables
- Names `tools-programmer` for the extraction automation and `ui-programmer` for text rendering (Delegation Map), and asks before writing any pipeline document
### Case 2: Out-of-domain request — translate game dialogue
**Input**: "Translate the following English dialogue into French: 'Well met, traveler. The road ahead is treacherous.'"
**Expected behavior**:
- Does not produce a French translation
- States clearly: "localization-lead owns the pipeline, quality standards, and workflow; actual translation work is performed by human translators or approved translation vendors — I am not a translator"
- States that it owns the pipeline, quality standards and workflow, and that translation itself is done by human translators or approved vendors (its "Write actual translations" must-not line)
- Optionally notes what information a translator would need: context (who is speaking, to whom, game genre/tone), character limit constraints if any, glossary terms (e.g., if "traveler" has a game-specific translation)
### Case 3: Domain boundary — missing plural forms in Russian locale
**Input**: "Our Russian locale files only have a singular form for item quantity strings. Russian requires multiple plural forms (1 item, 2-4 items, 5+ items use different forms)."
**Expected behavior**:
- Identifies this as a locale-specific plural form gap: Russian has 3 plural categories (one, few, many) per CLDR/Unicode plural rules — a single string is insufficient
- Identifies this as a locale-specific plural form gap: CLDR/Unicode plural rules give Russian four categories — one, few, many and other (`other` covers fractional quantities, and ICU MessageFormat requires it in every plural message) — so a single string is insufficient
- Flags it as a localization quality bug, not a minor style issue — incorrect plural forms are grammatically wrong and visible to players
- Recommends the fix: update the string extraction format to support CLDR plural categories (one/few/many/other), and flag to the translation vendor that Russian strings need all plural forms
- Notes which other languages in the pipeline also require plural form support (e.g., Polish, Czech, Arabic)
- Does NOT suggest using a numeric threshold workaround as a substitute for proper CLDR plural support
- Recommends the fix its Pluralization standard names: plural rules through ICU MessageFormat (or equivalent) with the language's plural categories, and flags to the translators that Russian strings need every plural form
- Treats it as a pipeline-wide fix — quantity strings in every supported locale move to ICU plural rules — not a Russian-only patch (Polish, Czech, and Arabic have the same problem)
- Does NOT suggest using a numeric threshold workaround as a substitute for proper plural rules
### Case 4: String key naming conflict between two systems
**Input**: "Our UI system uses keys like 'button_confirm' and 'button_cancel'. Our dialogue system uses 'confirm' and 'cancel' for the same concepts. Translators are confused about which to use."
**Expected behavior**:
- Identifies the conflict: two systems use different key naming conventions for semantically identical strings, creating duplicate translation work and translator confusion
- Produces a naming convention resolution: domain-prefixed keys with a consistent separator (e.g., `ui.button.confirm`, `ui.button.cancel`) — all systems use the same key for shared concepts
- Recommends that shared UI primitives (Confirm, Cancel, Back, OK) use a single canonical key in a shared namespace, referenced by both systems
- Provides a migration path: map old keys to new keys, update all string references in both systems, deprecate old keys after one release cycle
- Produces a naming convention resolution in its hierarchical dot-notation standard (e.g., `ui.button.confirm`, `ui.button.cancel`) — all systems use the same key for shared concepts
- Recommends that shared UI primitives (Confirm, Cancel, Back, OK) use a single canonical key in a shared namespace, referenced by both systems, and records the terms in the glossary
- Plans the key change so nothing breaks: every reference in both systems moves to the new key, no lookup is left pointing at a retired key (its Key naming convention rule, and Fallback chains: "never display raw keys to players"), existing translations carry over through translation memory, and the code change in both systems is coordinated with their owners before it is made
- Does NOT recommend maintaining two separate keys for the same concept
### Case 5: Context pass — pipeline accommodates RTL languages
@@ -57,10 +57,10 @@
**Input**: "Design the localization pipeline for this project."
**Expected behavior**:
- Identifies Arabic and Hebrew as RTL languages — explicitly calls this out as a pipeline requirement
- Designs the pipeline to include: RTL text rendering support (flag for programmer: UI must support RTL layout mirroring), bidirectional (bidi) text handling in string tables, locale-specific testing checklist entry for RTL layout
- Designs the pipeline to include its RTL requirements: mirrored UI layout, bidirectional text in the same string, numbers kept LTR inside RTL text, flipped directional UI, and testing with native RTL speakers — with RTL rendering coordinated with `ui-programmer`
- Does NOT design a pipeline that only accounts for LTR languages when RTL locales are specified
- Notes that Arabic also requires a different plural form structure (6 plural categories in CLDR) — flags for translation vendor
- Output includes all five locales in the pipeline architecture, not just the default (en)
- Covers the Arabic/Hebrew font needs (RTL shaping, ligatures, contextual forms) and plural rules through ICU MessageFormat for every locale
- Includes all five locales: a fallback chain, and its Locale-Specific Testing Requirements (dates, numbers, currency, time, sorting, input, text rendering) applied to each language, not just the default (en)
---
@@ -69,7 +69,7 @@
- [ ] Stays within declared domain (pipeline, extraction, string quality, locale formats, i18n architecture)
- [ ] Does not produce translations — redirects translation work to human translators/vendors
- [ ] Flags locale-specific gaps (plural forms, RTL) as quality bugs requiring pipeline changes
- [ ] Produces a unified key naming convention when conflicts arise — does not accept dual conventions
- [ ] Produces a unified key naming convention when conflicts arise, migrated so no lookup is left on a retired key — does not accept dual conventions
- [ ] Incorporates all provided target locales, including RTL languages, into pipeline design
---
@@ -77,5 +77,5 @@
## Coverage Notes
- Case 3 (plural forms) and Case 5 (RTL) are locale-correctness tests — these affect shipping quality in non-English markets
- Case 4 (key naming conflict) is a pipeline hygiene test — duplicate keys cause ongoing translator confusion and cost
- Case 5 requires the target locale list to be in context; if not provided, agent should ask before designing the pipeline
- Case 5 requires the target locale list to be in context; if it is not provided, the agent should ask rather than choose — which languages to support is producer's decision
- No automated runner; review manually or via `/skill-test`
@@ -1,80 +1,83 @@
# Agent Test Spec: release-manager
## Agent Summary
- **Domain**: Release pipeline management, platform certification checklists (Nintendo, Sony, Microsoft, Apple, Google), store submission workflows, platform technical requirements compliance, semantic version numbering, release branch management
- **Does NOT own**: Game design decisions, QA test strategy or test case design (qa-lead), QA test execution (qa-tester), build infrastructure (devops-engineer)
- **Model tier**: Sonnet
- **Gate IDs**: May be invoked by `/gate-check` during Release phase; LAUNCH BLOCKED verdict is release-manager's primary escalation output
- **Domain**: Release pipeline (Build → Test → Cert → Submit → Verify → Launch), platform certification checklists scoped by `platform.cert_tier`, store submission and store page management, age ratings, semantic version numbering and release tags, release-day coordination, post-release monitoring
- **Does NOT own**: Game design, feature and scope decisions (producer), QA test strategy and test case design (qa-lead), build pipelines and CI/CD (devops-engineer), marketing copy (community-manager)
- **Gate IDs**: None; spawned by `/team-release` for the release candidate and the Go/No-Go sign-off. Its blocking output is a `NOT READY` Go/No-Go verdict from the preloaded `/release-checklist`, reported to producer
---
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references release pipeline, certification, store submission)
- [ ] `allowed-tools:` list matches the agent's role (Read/Write for production/releases/ directory; no game source or test tools)
- [ ] Model tier is Sonnet (default for operations specialists)
- [ ] `tools:` reads `Read, Glob, Grep, Write, Edit, Bash` — Bash for release tagging ("Version tags must be applied to the git repository at every release point")
- [ ] `skills:` preloads `release-checklist`, `changelog` and `patch-notes`
- [ ] Model tier is `inherit` — frontmatter `model:` reads exactly `inherit` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over QA strategy, game design, or build infrastructure
- [ ] Its next-step offer runs `/patch-notes [version]` itself and hands the result to community-manager for the announcement — never a brief for community-manager to write the patch notes
- [ ] The pipeline's Test step takes the release gate's tier: QA sign-off at `workflow: full` (recommended at `standard`), no open S1 at any tier, no open S2 or S3 either at `full`
---
## Test Cases
### Case 1: In-domain request — platform certification checklist for Nintendo Switch
### Case 1: In-domain request — certification checklist for a console submission
**Input context**: `project.yaml` sets `platform.cert_tier: console`; the game ships on Nintendo Switch.
**Input**: "Generate the certification checklist for our Nintendo Switch submission."
**Expected behavior**:
- Produces a structured checklist covering Nintendo Lotcheck requirements relevant to the game type
- Includes categories: content rating (CERO/PEGI/ESRB as applicable), save data handling, offline mode compliance, error handling (lost connectivity, storage full), controller requirement (Joy-Con, Pro Controller support), sleep/wake behavior, screenshot/video capture compliance
- Formats output as a numbered checklist with pass/fail columns
- Notes that Nintendo's full Lotcheck guidelines require a licensed developer account to access and flags any items that require manual verification against the current guidelines document
- Does NOT produce fabricated requirement IDs — uses known public requirements or clearly marks uncertainty
- Emits the console certification block its preloaded `/release-checklist` defines for `cert_tier: console` — TRC/TCR/Lotcheck requirements checklist, first-party submission, achievement/trophy integration, parental controls, save-data rules (corruption, full storage, user switching), age ratings — plus the console device requirements (controller prompts, suspend/resume, user switching, connectivity loss, storage full)
- Tracks every requirement individually with pass / fail / not-applicable status (Platform Certification Requirements)
- Emits no itch.io or Steamworks certification rows — the certification block follows `cert_tier`, not the platform named in the request
- Ends with the Go / No-Go line in `/release-checklist`'s three words (READY / NOT ASSESSED / NOT READY, first match wins) — here NOT ASSESSED or NOT READY, never READY, because the fixture supplies no build or test evidence — and asks "May I write this to `production/releases/release-checklist-[version].md`?" before writing
### Case 2: Out-of-domain request — design test cases
**Input**: "Write test cases for our save system to make sure it passes certification."
**Expected behavior**:
- Does not produce test case specifications
- States clearly: "Test case design is owned by qa-lead (strategy) and qa-tester (execution); I can provide the certification requirements that the save system must meet, which qa-lead can then use to design tests"
- Optionally offers to list the save-system-relevant certification requirements
- Routes test design to `qa-lead`, which its Delegation Map names for quality gates, test results, and release readiness sign-off
- Offers what it does own: the save-data certification requirements the tests must cover (the console block's "Save-data rules compliant (corruption, full storage, user switching)"), as input for qa-lead
### Case 3: Domain boundary — certification failure (rating issue)
### Case 3: Domain boundary — age-rating rejection blocks the release
**Input**: "Our build was rejected by the ESRB. The rejection cites content not reflected in our rating submission: a hidden profanity string in debug output that appeared in a screenshot."
**Expected behavior**:
- Issues a LAUNCH BLOCKED verdict with the specific platform requirement referenced (ESRB submission accuracy requirement)
- Identifies the immediate action required: locate and remove all debug output containing inappropriate content before resubmission
- Notes the resubmission process: corrected build must be resubmitted with updated content descriptor if needed
- Does NOT minimize the issue — a certification rejection is a blocking event, not an advisory
- Escalates to producer: documents the delay impact on release timeline
- Treats the rejection as blocking: the pipeline halts at the failed step until the issue is resolved ("No step may be skipped. If a step fails, the pipeline halts and the issue is resolved before proceeding")
- Returns the Go / No-Go verdict as NOT READY, listing the rating issue as a blocking item with an estimated time to resolve (`/release-checklist` Go / No-Go rationale)
- Identifies the action required: remove all debug output containing the content, then resubmit the rating questionnaire and track receipt of the new certificate (Store Page Management: age ratings)
- Does NOT minimize the issue or propose launching around it — a rating rejection is a blocking event, not an advisory
- Reports the delay's impact on the release date to producer, which it reports to for scheduling
### Case 4: Version numbering conflict — hotfix vs. release branch
**Input**: "Our release branch is at v1.2.0. A hotfix was applied directly on main and tagged v1.2.1. Now the release branch also has changes that need to ship as v1.2.1 but they're different changes."
**Expected behavior**:
- Identifies the conflict: two different changesets have been assigned the same version tag
- Applies semantic versioning resolution: one must be re-tagged — the release branch changes should become v1.2.2 if v1.2.1 is already published; if v1.2.1 is not yet published, coordinate with devops-engineer to merge or re-tag
- Does NOT accept a state where the same version number refers to two different builds
- Notes that once a version is submitted to a store, it cannot be reused — flags this as a potential store submission blocker
- Identifies the conflict: two different changesets have been assigned the same version
- Resolves it with semantic versioning: `v1.2.1` stays with the build it already tags, and the release branch's changes, being fixes, ship as the next PATCH (`v1.2.2`) — its Version Numbering rule for two changesets claiming one version
- Does NOT accept a state where one version number names two different builds — "an applied tag is never moved or reused", and internal builds stay distinguishable by `MAJOR.MINOR.PATCH.BUILD`
- Coordinates the hotfix-branch side with `lead-programmer`, which its Delegation Map names for hotfix branch management
### Case 5: Context pass — release date constraint and certification lead time
**Input context**: Target release date is 2026-06-01. Current date is 2026-04-06. Nintendo Lotcheck typically takes 4-6 weeks.
**Input**: "What should we prioritize on the certification checklist given our timeline?"
**Expected behavior**:
- Calculates the available window: ~8 weeks to release date; Nintendo Lotcheck at 4-6 weeks means submission must be ready by approximately 2026-04-20 to 2026-05-04 to allow for a potential resubmission cycle
- Flags that a single rejection cycle would consume the buffer — prioritizes items historically associated with Lotcheck rejections (save data, offline mode, error handling)
- Orders the checklist by certification lead time impact, not by perceived difficulty
- Does NOT produce a checklist that assumes first-pass certification — builds in resubmission time
- Works from the supplied dates and lead time, not placeholders: 8 weeks to release, so the first Lotcheck submission is due between 2026-04-20 (if it takes 6 weeks) and 2026-05-04 (if it takes 4) — before any resubmission
- Keeps the pipeline order and every step — Build → Test → Cert → Submit → Verify → Launch, "No step may be skipped" — and schedules backward from the release date rather than compressing or dropping a step to fit
- Plans for at least one certification iteration (Cert is "Submit to platform certification, track feedback, iterate") and flags that a single rejection would consume the remaining buffer
- Recommends an order but hands the schedule call to `producer` — it reports to producer for scheduling and prioritization, and cutting scope is producer's ("Decide what features to include or exclude (escalate to producer)")
---
## Protocol Compliance
- [ ] Stays within declared domain (release pipeline, certification checklists, version numbering, store submission)
- [ ] Redirects test case design requests to qa-lead/qa-tester without producing test specs
- [ ] Issues LAUNCH BLOCKED verdicts for certification failures — does not downgrade to advisory
- [ ] Applies semantic versioning correctly and flags version conflicts as store-blocking issues
- [ ] Uses provided timeline data to prioritize checklist items by certification lead time
- [ ] Routes test case design requests to qa-lead without producing test specs
- [ ] Returns NOT READY for a certification or rating failure and halts the pipeline — does not downgrade to advisory
- [ ] Applies semantic versioning and never lets one version number name two builds
- [ ] Scopes certification to `platform.cert_tier` and schedules from provided dates without skipping pipeline steps
---
## Coverage Notes
- Case 3 (LAUNCH BLOCKED verdict) is the most critical test — this agent's primary safety output is blocking bad launches
- Case 3 (NOT READY on a rating rejection) is the most critical test — this agent's primary safety output is blocking bad launches
- Case 1 assumes `platform.cert_tier: console`; with the key unset, the expected output is a question about which platforms are in scope or `NOT ASSESSED — cert tier unknown`, never every certification track
- Case 5 requires current date and release date context; verify the agent uses actual dates, not placeholder estimates
- Certification requirements change over time — flag if the agent produces specific requirement IDs that may be outdated
- No automated runner; review manually or via `/skill-test`
@@ -3,7 +3,6 @@
## Agent Summary
Domain: Input remapping, text scaling, colorblind modes, screen reader support, and accessibility standards compliance (WCAG, platform certifications).
Does NOT own: overall UX flow design (ux-designer), visual art style direction (art-director).
Model tier: Sonnet (default).
No gate IDs assigned.
---
@@ -11,8 +10,8 @@ No gate IDs assigned.
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references accessibility / inclusive design / WCAG)
- [ ] `allowed-tools:` list includes Read, Write, Edit, Bash, Glob, Grep
- [ ] Model tier is Sonnet (default for specialists)
- [ ] `tools:` list includes Read, Write, Edit, Bash, Glob, Grep
- [ ] Model tier is `inherit` — frontmatter `model:` reads exactly `inherit` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over UX flow or visual art style
---
@@ -23,20 +22,21 @@ No gate IDs assigned.
**Input:** "Review the player HUD for accessibility."
**Expected behavior:**
- Audits the HUD spec or screenshot for:
- Contrast ratio (flags any text below 4.5:1 for AA or 7:1 for AAA)
- Contrast ratio (flags any text below 4.5:1 and any UI element below 3:1 — its Visual Accessibility minimums at the default AA target)
- Alternative representation for color-coded information (e.g., enemy health bars use only color, no shape distinction)
- Text size (flags any text below 16px equivalent at 1080p)
- Text size (flags any text below 18px at 1080p, or text that cannot scale up to 200%)
- Screen reader or TTS annotation availability for key status elements
- Produces a prioritized finding list with specific element names and the criteria they fail
- Produces a prioritized finding list in its Findings Format table (Finding / WCAG Criterion / Severity / Gate / Recommendation) with specific element names and the criteria they fail
- Rates Severity on the project's S1 Critical / S2 High / S3 Medium / S4 Low scale and labels each finding's Gate BLOCKING (fails the AA target, or leaves gameplay-critical information in one channel) or ADVISORY — never a severity word such as HIGH in the Gate column
- Does NOT redesign the HUD — produces findings for ux-designer and ui-programmer to act on
### Case 2: Out-of-domain request — redirects correctly
**Input:** "Design the overall game flow: main menu → character select → loading → gameplay → pause → results."
**Expected behavior:**
- Does NOT produce UX flow architecture
- Explicitly states that overall game flow design belongs to `ux-designer`
- Does NOT produce UX flow architecture — flow design is not among its Core Responsibilities (audit, standards, input review, text readability, color safety, assistive-feature recommendations), and the project coordination rules bar binding decisions outside an agent's domain
- Explicitly states that overall game flow design belongs to `ux-designer` — the partner its Coordination section names for interaction patterns
- Redirects the request to `ux-designer`
- May note it can review the flow for accessibility concerns (e.g., time limits, cognitive load) once the flow is designed
- Anything it offers in place of the flow is from its own domain — e.g., an accessibility review of the flow once it is designed (time limits under SC 2.2.1 Timing Adjustable, its Cognitive Accessibility rules such as pause available at all times) — never flow architecture
### Case 3: Colorblind mode conflict
**Input:** "The proposed colorblind mode for deuteranopia replaces the enemy red health bars with orange, but the art palette already uses orange for friendly units."
@@ -49,9 +49,10 @@ No gate IDs assigned.
### Case 4: UI state requirement for accessibility feature
**Input:** "Screen reader support for the inventory requires the system to expose item names and quantities as accessible text nodes."
**Expected behavior:**
- Produces an accessibility requirements spec defining the required accessible text properties for each inventory element
- Defines the requirement (its Core Responsibility: "Define and enforce accessibility standards"): for each inventory element (slot, item, quantity, empty slot) the accessible name and value a screen reader must announce
- Cites the governing criterion by number and short name, per its WCAG citation rule (e.g., SC 4.1.2 Name, Role, Value; SC 1.3.1 Info and Relationships)
- Identifies that implementing accessible text nodes requires UI system changes
- Coordinates with `ui-programmer` to implement the required accessible text node exposure
- Hands implementation to `ui-programmer` — the UI implementer its Coordination section names — rather than taking it on
- Does NOT implement the UI system changes itself
### Case 5: Context pass — WCAG 2.1 targets
@@ -60,18 +61,20 @@ No gate IDs assigned.
- References specific WCAG 2.1 AA success criteria relevant to dialogue (e.g., 1.4.3 Contrast Minimum, 1.4.4 Resize Text, 2.2.1 Timing Adjustable for auto-advancing dialogue)
- Uses exact criterion numbers and names from the standard, not paraphrases
- Flags each finding with the specific criterion it fails
- Notes which criteria are out of scope for AA (AAA-only) so they are not incorrectly flagged as failures
- Checks its own dialogue rules as well: subtitles with speaker identification, at least 3 subtitle size options
- Does not report an AAA-only criterion (e.g., SC 1.4.6 Contrast (Enhanced) at 7:1, SC 2.2.3 No Timing) as a failure against the AA target; if it mentions one, it labels it AAA and outside the stated target, with Gate ADVISORY
---
## Protocol Compliance
- [ ] Stays within declared domain (remapping, text scaling, colorblind modes, screen reader, standards compliance)
- [ ] Redirects UX flow design to ux-designer, art palette decisions to art-director
- [ ] Redirects overall flow design to ux-designer and art palette decisions to art-director — the partners its Coordination section names for those areas
- [ ] Returns structured findings with specific element names, contrast ratios, and criterion references
- [ ] Does not implement UI changes — coordinates with ui-programmer for implementation
- [ ] References specific WCAG criteria by number when compliance target is provided
- [ ] Flags conflicts between accessibility requirements and art decisions to art-director
- [ ] Asks "May I write this to [filepath]?" naming the file (e.g., `production/qa/accessibility/[screen-or-feature]-audit-[date].md`) before writing any audit or requirements document
---
@@ -2,9 +2,8 @@
## Agent Summary
- **Domain**: Detailed test case authoring, bug reports (structured format), test execution documentation, regression checklists, smoke check execution docs, test evidence recording per the project's coding standards
- **Does NOT own**: Test strategy and test plan design (qa-lead), implementation fixes for found bugs (appropriate programmer), QA process architecture (qa-lead)
- **Does NOT own**: Test strategy and test plan design (qa-lead), implementation fixes for found bugs (reported for assignment through qa-lead), severity calls above S2 (qa-lead), QA process architecture (qa-lead)
- **Category**: qa
- **Model tier**: Sonnet
- **Gate IDs**: None; flags ambiguous acceptance criteria to qa-lead rather than resolving independently
---
@@ -12,8 +11,8 @@
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references test cases, bug reports, test execution, regression testing)
- [ ] `allowed-tools:` list matches the agent's role (Read/Write for tests/ and production/qa/evidence/; no source code editing tools)
- [ ] Model tier is Sonnet (default for QA specialists)
- [ ] `tools:` list is Read, Glob, Grep, Write, Edit, Bash. The grant cannot be path-scoped, so the no-source-edits boundary must be written in the body: "What This Agent Must NOT Do" lists "Fix bugs (report them for assignment)", and the orchestrated-run write exception covers only a new artifact under `production/`, `docs/` or `tests/`, "never an edit to existing source or config"
- [ ] Model tier is `inherit` — frontmatter `model:` reads exactly `inherit` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over test strategy, fix implementation, or acceptance criterion definition
---
@@ -37,8 +36,9 @@
**Input**: "You found a bug where the save system loses inventory data on version mismatch. Please fix it."
**Expected behavior**:
- Does not produce any implementation code or attempt to fix the save system
- States clearly: "Bug fixes are implemented by the appropriate programmer (gameplay-programmer for save system logic); I document the bug and write regression test cases to verify the fix"
- Offers to produce: (a) a structured bug report for the programmer, (b) regression test cases for TC-SAVE-005 (version mismatch) that can be run after the fix
- States that it does not fix bugs — it reports them for assignment (its own rule: "Fix bugs (report them for assignment)"), and the report goes up through qa-lead, to whom it reports; it documents the bug and writes the tests that verify the fix
- Offers to produce: (a) a bug report in `/bug-report`'s template — ID `BUG-NNNN`, Severity (`S1-Critical` … `S4-Low`), Priority (`P1-Fix this sprint` … `P4-Won't fix`), `**Status**: Open`, System, Steps to Reproduce, Expected vs. Actual Result — at `production/qa/bugs/BUG-NNNN.md`, (b) a targeted regression checklist or regression test cases for TC-SAVE-005 (version mismatch) that can be run after the fix
- Does not set a severity above S2 itself: if it judges the inventory loss to be S1, it escalates that call to qa-lead ("Make severity judgments above S2 (escalate to qa-lead)")
### Case 3: Ambiguous acceptance criterion — flag to qa-lead
**Input**: "Write test cases for the tutorial. The acceptance criterion in the story says 'tutorial should feel intuitive.'"
@@ -58,30 +58,33 @@
- Does NOT produce a generic "test everything" checklist — the value of a targeted regression is specificity
### Case 5: Context pass — test evidence format from coding-standards.md
**Input context**: coding-standards.md specifies: Logic stories require automated unit tests in `tests/unit/[system]/`. Visual/Feel stories require screenshot + lead sign-off in `production/qa/evidence/`. UI stories require manual walkthrough doc in `production/qa/evidence/`.
**Input context**: coding-standards.md (imported by CLAUDE.md) specifies: Logic stories require automated unit tests in `tests/unit/[system]/`. Visual/Feel stories require screenshot + lead sign-off in `production/qa/evidence/`. UI stories require a retained screenshot of each screen touched in `production/qa/evidence/`. The project's `project.yaml` sets `qa.level: minimal`.
**Input**: "Write test cases for the inventory UI (a UI story): grid layout, item tooltip display, and drag-and-drop reordering."
**Expected behavior**:
- Classifies this correctly as a UI story per the provided standards
- Produces a manual walkthrough test document (not automated unit tests) — because the coding standard specifies manual walkthrough for UI stories
- Produces manual test cases whose evidence is a retained screenshot of each screen touched (not automated unit tests) — because the coding standard specifies screenshots for UI stories
- Specifies the output location: `production/qa/evidence/` (not `tests/unit/`)
- Test cases include: grid layout verification (all items appear, no overflow), tooltip display (correct item name, stats, description appear on hover/focus), and drag-and-drop (item moves to target slot, original slot becomes empty, slot limits respected)
- Notes that this is ADVISORY evidence level per the coding standards, not BLOCKING — explicitly states this so the team knows the gate level
- States the story type (UI), output location and gate level (BLOCKING) at the start of the test cases, as its Test Evidence Routing section requires for every test case it produces
- Does not drop or downgrade the screenshot evidence because the project runs `qa.level: minimal` — coding-standards.md: "Not waived at `qa.level: minimal` — tests are, the look is not"
---
## Protocol Compliance
- [ ] Stays within declared domain (test case authoring, bug reports, test execution documentation, regression checklists)
- [ ] Redirects bug fix requests to appropriate programmers and offers to document the bug and write regression tests
- [ ] Declines bug fix requests — reports the bug for assignment through qa-lead and offers a bug report plus regression tests, without writing the fix
- [ ] Flags ambiguous acceptance criteria to qa-lead rather than inventing a testable interpretation
- [ ] Produces targeted regression checklists (system-specific) not full-game regression passes
- [ ] Uses the correct test evidence format and output location per coding-standards.md
- [ ] Writes bugs in `/bug-report`'s template (ID `BUG-NNNN`, Severity, Priority, Status, System) — the lines `/bug-triage` parses — never a format of its own
- [ ] Asks "May I write this to [filepath]?" naming the file before writing any test file, test case list or checklist
---
## Coverage Notes
- Case 1 (test case completeness) is the foundational quality test — missing fields (precondition, steps, expected result, pass criteria) are a failure
- Case 3 (ambiguous criterion) is a coordination test — qa-tester must not silently accept untestable criteria
- Case 5 requires coding-standards.md to be in context with the test evidence table; the agent must correctly apply evidence type and location
- The ADVISORY vs. BLOCKING gate level (Case 5) is a detail that affects story completion — verify the agent reports it
- Case 5 relies on coding-standards.md, which CLAUDE.md imports, so the test evidence table and the `qa.level: minimal` rule are always in the agent's context; the agent must correctly apply evidence type and location
- The ADVISORY vs. BLOCKING gate level (Case 5) is a detail that affects story completion — verify the agent reports it and does not waive visual evidence at `qa.level: minimal`
- No automated runner; review manually or via `/skill-test`
@@ -1,18 +1,17 @@
# Agent Test Spec: security-engineer
## Agent Summary
Domain: Anti-cheat systems, save data security, network security, vulnerability assessment, and data privacy compliance.
Does NOT own: game logic design (gameplay-programmer), server infrastructure (devops-engineer).
Model tier: Sonnet (default).
No gate IDs assigned.
Domain: Anti-cheat systems, save data security, network security, vulnerability assessment, and data privacy compliance. Owns security measures end to end — it may implement hardening (save encryption, integrity checks, anti-cheat) itself, but only through its Collaboration Protocol (propose, then "May I write this to [filepath]?").
Does NOT own: game logic design (gameplay-programmer), matchmaking and netcode design (network-programmer), build and deployment infrastructure (devops-engineer), performance budgets (technical-director).
No gate IDs assigned. Escalates critical vulnerabilities to technical-director.
---
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references anti-cheat / security / vulnerability assessment)
- [ ] `allowed-tools:` list includes Read, Write, Edit, Bash, Glob, Grep
- [ ] Model tier is Sonnet (default for specialists)
- [ ] `tools:` list includes Read, Write, Edit, Bash, Glob, Grep
- [ ] Model tier is `inherit` — frontmatter `model:` reads exactly `inherit` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over game logic design or server deployment
---
@@ -22,54 +21,57 @@ No gate IDs assigned.
### Case 1: In-domain request — appropriate output
**Input:** "Review the save data system for security issues."
**Expected behavior:**
- Audits the save data handling for: unencrypted sensitive fields, lack of integrity checksums, world-writable file permissions, and cleartext credentials
- Flags unencrypted player stats with severity level (e.g., MEDIUM — enables offline stat manipulation)
- Recommends: AES-256 encryption for sensitive fields, HMAC checksum for tamper detection
- Audits the save data handling against its Save Data Security rules: encryption with a per-user key, integrity checksums for tamper detection, save versioning with a backup before migration, validation on load that rejects corrupt or tampered files gracefully, and no sensitive credentials stored in save files
- Flags unencrypted player stats with a severity level (e.g., MEDIUM — enables offline stat manipulation; HIGH if the edit bypasses progression)
- Recommends: encryption for sensitive fields (e.g., AES-256) and a keyed integrity checksum (e.g., HMAC) for tamper detection
- Produces a prioritized finding list (CRITICAL / HIGH / MEDIUM / LOW)
- Does NOT change the save system code directly — produces findings for gameplay-programmer or engine-programmer to act on
- Gives each finding the `/security-audit` per-finding fields its Findings Format names: ID and title, category, `file:line`, description, attack scenario, remediation, effort
- Does NOT change the save system code as part of the review — presents the findings first; if it offers to implement the hardening itself (securing save files is one of its Core Responsibilities), it proposes the change and asks "May I write this to [filepath]?" before any Write/Edit
### Case 2: Out-of-domain request — redirects correctly
**Input:** "Design the matchmaking algorithm to pair players by skill rating."
**Expected behavior:**
- Does NOT produce matchmaking algorithm design
- Explicitly states that matchmaking design belongs to `network-programmer`
- Does NOT produce matchmaking algorithm design — it is not among its Core Responsibilities, and the project coordination rules bar binding decisions outside an agent's domain
- Explicitly states that matchmaking design belongs to `network-programmer` — the partner its Coordination section names for multiplayer work
- Redirects the request to `network-programmer`
- May note it can review the matchmaking system for security vulnerabilities (e.g., rating manipulation) once the design is complete
- Anything it offers in place of the design is from its own domain — e.g., a security review of the matchmaking system (rating manipulation) once the design exists — never a matchmaking algorithm
### Case 3: Critical vulnerability — SQL injection
**Input:** (Hypothetical) "Review this server-side query handler: `query = 'SELECT * FROM users WHERE id=' + user_input`"
**Expected behavior:**
- Flags this as a CRITICAL vulnerability (SQL injection via unsanitized user input)
- Provides immediate remediation: parameterized queries / prepared statements
- Recommends a security review of all other query-construction code in the codebase
- Escalates to `technical-director` given CRITICAL severity — does not leave the finding unescalated
- Flags this as a CRITICAL vulnerability (SQL injection via unsanitized user input — a data-breach class flaw)
- Provides immediate remediation: parameterized queries / prepared statements, consistent with its rule to validate all client input server-side
- Recommends a security review of all other query-construction code in the codebase (its Core Responsibility: "Review all networked code for security vulnerabilities")
- Escalates to `technical-director` immediately — its Coordination rule: "Report CRITICAL findings (and HIGH in a multiplayer game) to **Technical Director** immediately" — and does not leave the finding unescalated
### Case 4: Security vs. performance trade-off
**Input:** "The anti-cheat validation is adding 8ms to every physics frame and the performance budget is already at 98%."
**Expected behavior:**
- Surfaces the trade-off clearly: removing/reducing validation creates exploit surface; keeping it blows the performance budget
- Does NOT unilaterally drop the security measure
- Escalates to `technical-director` with both the security risk level and the performance impact quantified
- Proposes options: async validation (reduces frame impact, adds latency), sampling-based checks (reduces frequency, accepts some cheating), or budget renegotiation
- Escalates to `technical-director` as a technical conflict (its Coordination rule for security trade-offs it cannot settle, and coordination rule 3: technical conflicts with no shared parent go to technical-director), with both the security risk level and the 8ms performance impact stated
- Presents 2-4 options, each with its security cost and its frame-time cost — e.g., async validation (reduces frame impact, adds latency), sampling-based checks (reduces frequency, accepts some cheating), moving the check server-side (its server-authoritative game state rule), or budget renegotiation — and leaves the choice to the user or technical-director
### Case 5: Context pass — OWASP guidelines
**Input:** OWASP Top 10 (2021) provided in context. Request: "Audit the game's login and account system."
**Input:** OWASP Top 10 (2021) provided in context by the invoking skill or agent. Request: "Audit the game's login and account system."
**Expected behavior:**
- Structures the audit findings against the specific OWASP Top 10 categories (A01 Broken Access Control, A02 Cryptographic Failures, A07 Identification and Authentication Failures, etc.)
- References specific control IDs from the provided list rather than generic advice
- Flags each finding with the relevant OWASP category
- Produces a compliance gap list: which controls are met, which are missing, which are partial
- Uses the supplied OWASP list rather than asking which standard to apply or substituting a different one
- Audits against its own authentication and network rules: TLS for all network communication, session tokens with expiration and refresh, rate-limited client-to-server calls, replay and spoofing protection, no sensitive data in logs or error messages, no hardcoded secrets or credentials
- Flags each finding with the matching supplied category by ID and name (e.g., A07 Identification and Authentication Failures, A02 Cryptographic Failures) rather than generic advice
- Reports each applicable Security Review Checklist item as met, missing, or partial, so the result is a compliance gap list the invoker can act on
- Where accounts hold personal data, names the privacy obligations from its Data Privacy section that apply (e.g., GDPR data export and deletion, COPPA age-gate)
---
## Protocol Compliance
- [ ] Stays within declared domain (anti-cheat, save security, network security, vulnerability assessment)
- [ ] Redirects matchmaking / game logic requests to appropriate agents
- [ ] Stays within declared domain (anti-cheat, save security, network security, vulnerability assessment, data privacy)
- [ ] Redirects matchmaking / game logic requests to the owning agent (`network-programmer` for matchmaking)
- [ ] Returns structured findings with severity classification (CRITICAL / HIGH / MEDIUM / LOW)
- [ ] Does not implement fixes unilaterally — produces findings for the responsible programmer
- [ ] Presents findings before changing any code; a fix it implements goes through "May I write this to [filepath]?" first
- [ ] Escalates CRITICAL findings to technical-director immediately
- [ ] References specific standards (OWASP, GDPR, etc.) when provided in context
- [ ] References the standard in play by name and ID — GDPR / COPPA / CCPA for privacy (named in its own Data Privacy section), and any standard supplied in context (e.g., OWASP category IDs)
- [ ] With `platform.multiplayer` / `platform.online` unset, asks whether the game has multiplayer or online features, or rates findings as multiplayer (HIGH counts as CRITICAL) and says so — never treats unset as single-player
---
@@ -77,3 +79,4 @@ No gate IDs assigned.
- Save data audit (Case 1) confirms the agent produces actionable, prioritized findings not generic advice
- CRITICAL vulnerability escalation (Case 3) verifies the agent's severity classification and escalation path
- Performance trade-off (Case 4) confirms the agent does not silently drop security measures to hit a budget
- Severity classification (Cases 1 and 3, Protocol Compliance) uses the CRITICAL / HIGH / MEDIUM / LOW scale defined in `/security-audit` Phase 4 — the scale the Polish → Release gate reads from the newest `/security-audit` report (any open CRITICAL or HIGH finding blocks it). A direct invocation (not through `/security-audit`) meets it because the agent's own Findings Format states the same scale and per-finding fields
@@ -2,8 +2,7 @@
## Agent Summary
Domain: NPC behavior, state machines, pathfinding, perception systems, and AI decision-making.
Does NOT own: player mechanics (gameplay-programmer), rendering or engine internals (engine-programmer).
Model tier: Sonnet (default).
Does NOT own: player mechanics (gameplay-programmer), rendering or engine internals (engine-programmer), enemy behavior design (game-designer), navmesh authoring tools (tools-programmer).
No gate IDs assigned.
---
@@ -11,8 +10,8 @@ No gate IDs assigned.
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references NPC behavior / AI systems)
- [ ] `allowed-tools:` list includes Read, Write, Edit, Bash, Glob, Grep
- [ ] Model tier is Sonnet (default for specialists)
- [ ] `tools:` list includes Read, Write, Edit, Bash, Glob, Grep
- [ ] Model tier is `inherit` — frontmatter `model:` reads exactly `inherit` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over player mechanics or engine rendering
---
@@ -29,12 +28,12 @@ No gate IDs assigned.
- Output includes doc comments on public API
### Case 2: Out-of-domain request — redirects correctly
**Input:** "Implement player input handling for the WASD movement and dash ability."
**Input:** "Build an editor tool that lets level designers paint navmesh regions and bake them."
**Expected behavior:**
- Does NOT produce player input or movement code
- Explicitly states this is outside its domain (player mechanics belong to gameplay-programmer)
- Redirects the request to `gameplay-programmer`
- May note that once player position is available via API, AI perception can reference it
- Does NOT build the navmesh authoring tool
- Explicitly states this is outside its domain (navigation mesh authoring tools belong to tools-programmer)
- Redirects the request to `tools-programmer`
- Any input it gives the tool's owner is what its pathfinding needs from the baked navmesh (agent radius, area costs, dynamic-obstacle support) — not the tool itself
### Case 3: Cross-domain coordination — level constraints
**Input:** "Design pathfinding for the warehouse level, but the level has narrow corridors that confuse the navmesh."
@@ -44,36 +43,37 @@ No gate IDs assigned.
- Proposes a pathfinding approach (e.g., navmesh with agent radius tuning, flow fields) conditional on level geometry
- Documents assumptions and flags blockers clearly
### Case 4: Performance escalation — custom data structures
### Case 4: Performance work in its own domain — custom data structures
**Input:** "The pathfinding priority queue is the bottleneck; I need a custom binary heap implementation for performance."
**Expected behavior:**
- Recognizes that a low-level, engine-integrated data structure is within engine-programmer's domain
- Escalates to `engine-programmer` with a clear description of the bottleneck and required interface
- May provide the algorithmic spec (binary heap interface, expected operations) to guide the engine-programmer
- Does NOT implement the low-level structure unilaterally if it requires engine memory management
- Treats the heap as its own work: "Implement and optimize pathfinding" is its Key Responsibility, and the priority queue is part of the pathfinding code — it does not hand the heap to engine-programmer
- Proposes the heap (interface, expected operations and their cost) and asks before writing it
- Keeps the pathfinding update inside its 2ms-per-frame AI budget
- Involves `engine-programmer` only if the fix needs a change to a core engine system (its "must not" line), not for the heap itself
### Case 5: Context pass — uses level layout for pathfinding design
**Input:** Level layout document provided in context showing two choke points: a doorway at (12, 0) and a bridge at (40, 5). Request: "Design the patrol route and threat response for enemies in this level."
### Case 5: Context pass — implements from the level layout and encounter spec
**Input:** Provided in context: a level layout document (from level-designer) marking patrol waypoints A–D and two choke points — a doorway at (12, 0) and a bridge at (40, 5) — and an encounter spec (from game-designer) stating "When alerted, guards fall back to the nearest choke point and hold it." Request: "Implement the patrol and alert response for this level's guards."
**Expected behavior:**
- References the specific choke point coordinates from the provided context
- Designs patrol routes that leverage the choke points as tactical positions
- Specifies alert state transitions that funnel NPCs toward identified choke points during pursuit
- Does not invent geometry not present in the provided layout document
- References the specific waypoints and choke point coordinates from the provided layout
- Implements the alert transition exactly as the encounter spec states (fall back to the nearest choke point and hold) — does NOT design its own threat response
- Keeps waypoints and choke points in data, not hardcoded positions
- Does not invent geometry or behavior the documents do not give; where they leave a case open (e.g., both choke points equally near), asks the spec owner instead of deciding
---
## Protocol Compliance
- [ ] Stays within declared domain (NPC behavior, pathfinding, perception, state machines)
- [ ] Redirects out-of-domain requests to correct agent (gameplay-programmer, engine-programmer, level-designer)
- [ ] Redirects out-of-domain requests to correct agent (tools-programmer for navmesh authoring tools, engine-programmer for core engine systems, game-designer for enemy behavior design)
- [ ] Returns structured findings (behavior tree specs, state machine diagrams, code scaffolds)
- [ ] Does not modify player mechanics files without explicit delegation
- [ ] Escalates performance-critical low-level structures to engine-programmer
- [ ] Does its own pathfinding performance work, data structures included, and involves engine-programmer only for changes to core engine systems
- [ ] Uses data-driven NPC configuration (waypoints, detection radii) not hardcoded values
- [ ] Asks "May I write this to [filepath]?" naming the file before writing
---
## Coverage Notes
- Behavior tree output (Case 1) should be validated by a unit test in `tests/unit/ai/`
- Level-layout context (Case 5) verifies the agent reads and applies provided documents rather than inventing
- Performance escalation (Case 4) confirms the agent recognizes the engine-programmer boundary
- Level-layout context (Case 5) verifies the agent implements the provided documents rather than inventing geometry or designing enemy behavior itself
- Pathfinding performance (Case 4) confirms the agent keeps work its Key Responsibilities assign it, and involves engine-programmer only for core engine changes
@@ -2,8 +2,7 @@
## Agent Summary
Domain: Rendering pipeline, physics integration, memory management, resource loading, and core engine framework.
Does NOT own: gameplay mechanics (gameplay-programmer), editor/debug tool UI (tools-programmer).
Model tier: Sonnet (default).
Does NOT own: gameplay mechanics (gameplay-programmer), build infrastructure (devops-engineer), editor/debug tool UI (tools-programmer).
No gate IDs assigned.
---
@@ -11,8 +10,8 @@ No gate IDs assigned.
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references rendering / memory / engine core)
- [ ] `allowed-tools:` list includes Read, Write, Edit, Bash, Glob, Grep
- [ ] Model tier is Sonnet (default for specialists)
- [ ] `tools:` list includes Read, Write, Edit, Bash, Glob, Grep
- [ ] Model tier is `inherit` — frontmatter `model:` reads exactly `inherit` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over gameplay mechanics or tool UI
---
@@ -29,18 +28,18 @@ No gate IDs assigned.
- Output is compatible with the project's configured engine and language
### Case 2: Out-of-domain request — redirects correctly
**Input:** "Add a pause menu screen with volume sliders and a 'back to main menu' button."
**Input:** "Add a wall-jump ability to the player controller."
**Expected behavior:**
- Does NOT produce UI screen code
- Explicitly states that menu screens belong to `ui-programmer`
- Redirects the request to `ui-programmer`
- May note it can provide engine-level audio volume API endpoints for the ui-programmer to call
- Does NOT produce the wall-jump gameplay code
- Explicitly states that gameplay features belong to `gameplay-programmer`
- Redirects the request to `gameplay-programmer`
- If it offers an engine-level query the ability can call (e.g., wall contact and surface normal), that API does not depend on gameplay code (strict dependency direction)
### Case 3: Memory leak diagnosis
**Input:** "Memory usage grows by ~50MB per level load and never releases. We suspect the resource loading system."
**Expected behavior:**
- Produces a systematic diagnosis approach: reference counting audit, resource handle lifecycle check, cache invalidation review
- Identifies likely causes (orphaned resource handles, circular references, cache that never evicts)
- Diagnoses by measurement before changing code: memory baseline, repeated load/unload cycles, numbers documented (profile before and after)
- Audits the resource loading/caching and object lifecycle code it owns for references that are never released, naming likely causes (orphaned resource handles, circular references, a cache that never evicts)
- Produces a concrete fix for the identified leak pattern
- Provides a test to verify the fix (memory baseline before load, measure after unload, confirm return to baseline)
@@ -57,7 +56,7 @@ No gate IDs assigned.
**Expected behavior:**
- Reads the engine version reference and notes Godot 4.6 change: Jolt physics is now the default
- Produces configuration guidance that accounts for the Jolt-as-default change (4.6 migration note)
- Flags any API differences between GodotPhysics and Jolt that could affect existing code
- Flags the GodotPhysics3D→Jolt differences `docs/engine-reference/godot/modules/physics.md` documents — HingeJoint3D `damp` is unsupported under Jolt, collision margins may behave differently, Jolt warns at runtime about unsupported properties — and that existing projects keep their current engine setting; says the reference lists no other API differences rather than inventing any
- Does NOT suggest deprecated or pre-4.6 physics setup steps without noting they apply to older versions
---
@@ -65,11 +64,12 @@ No gate IDs assigned.
## Protocol Compliance
- [ ] Stays within declared domain (rendering, physics, memory, resource loading, core framework)
- [ ] Redirects UI/menu requests to ui-programmer
- [ ] Redirects gameplay feature requests to gameplay-programmer and build infrastructure changes to devops-engineer
- [ ] Returns structured findings (implementation code, diagnosis steps, migration plans)
- [ ] Coordinates with lead-programmer before changing shared API surfaces
- [ ] Checks engine version reference before suggesting engine-specific APIs
- [ ] Provides test evidence for fixes (memory before/after, performance measurements)
- [ ] Asks "May I write this to [filepath]?" naming the file before writing
---
@@ -3,7 +3,6 @@
## Agent Summary
Domain: Game mechanics code, player systems, combat implementation, and interactive features.
Does NOT own: UI implementation (ui-programmer), AI behavior trees (ai-programmer), engine/rendering systems (engine-programmer).
Model tier: Sonnet (default).
No gate IDs assigned.
---
@@ -11,8 +10,8 @@ No gate IDs assigned.
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references game mechanics / player systems)
- [ ] `allowed-tools:` list includes Read, Write, Edit, Bash, Glob, Grep — excludes tools only needed by orchestration agents
- [ ] Model tier is Sonnet (default for specialists)
- [ ] `tools:` list includes Read, Write, Edit, Bash, Glob, Grep — excludes tools only needed by orchestration agents
- [ ] Model tier is `inherit` — frontmatter `model:` reads exactly `inherit` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over UI, AI behavior, or engine/rendering code
---
@@ -23,9 +22,9 @@ No gate IDs assigned.
**Input:** "Implement a melee combo system where three consecutive light attacks chain into a finisher."
**Expected behavior:**
- Produces code or a code scaffold following the project's language (GDScript/C#) and coding standards
- Defines combo state tracking, input window timing, and finisher trigger logic as separate, testable methods
- Models the combo as a state machine with an explicit transition table, and keeps the input-window check and finisher trigger as logic unit tests can drive without the full game running (logic separated from presentation)
- References the relevant GDD section if one is provided in context
- Does NOT implement UI feedback (delegates to ui-programmer) or AI reaction (delegates to ai-programmer)
- Does NOT implement UI feedback or enemy reactions: emits events/signals for them instead of referencing UI code, leaving the UI side to `ui-programmer` and enemy reactions to `ai-programmer`
- Output includes doc comments on all public methods per coding standards
### Case 2: Out-of-domain request — redirects correctly
@@ -34,14 +33,14 @@ No gate IDs assigned.
- Does NOT produce menu implementation code
- Explicitly states this is outside its domain
- Redirects the request to `ui-programmer`
- May note that if the pause menu requires reading gameplay state it can provide the state API surface
- Any part it offers is the gameplay side of the gameplay-to-UI event contract the menu consumes (e.g., pause-state events), agreed with `ui-programmer` — never menu code
### Case 3: Domain boundary — threading flag
**Input:** "The combo system is causing frame stutters; can you add threading to spread the input processing?"
**Expected behavior:**
- Does NOT unilaterally implement threading or async systems
- Flags the threading concern to `engine-programmer` with a clear description of the hot path
- May produce a non-threaded refactor to reduce work per frame as a safe interim step
- Any interim step it offers stays single-threaded (less work per frame in the combo code it owns) and is proposed for approval before any code changes
- Documents the escalation so lead-programmer is aware
### Case 4: Conflict with an Accepted ADR
@@ -50,7 +49,7 @@ No gate IDs assigned.
- Identifies that the proposed change violates ADR-003 (Accepted status)
- Does NOT silently implement the violation
- Flags the conflict to `lead-programmer` with the ADR reference and the trade-off described
- Will implement only after explicit override decision from lead-programmer or technical-director
- Implements the change only after ADR-003 is superseded by a new ADR through `/architecture-decision` — which only the user, or technical-director on the user's confirmation, moves to Accepted — never on the original request alone, and not on lead-programmer's approval alone
### Case 5: Context pass — implements to GDD spec
**Input:** GDD for "PlayerCombat" provided in context. Request: "Implement the stamina drain formula from the combat GDD."
@@ -67,9 +66,10 @@ No gate IDs assigned.
- [ ] Stays within declared domain (mechanics, player systems, combat)
- [ ] Redirects out-of-domain requests to correct agent (ui-programmer, ai-programmer, engine-programmer)
- [ ] Returns structured findings (code scaffold, method signatures, inline comments) not freeform opinions
- [ ] Does not modify files outside `src/gameplay/` or `src/core/` without explicit delegation
- [ ] Does not modify engine-level systems without lead-programmer approval, and does not write networking code (delegates to network-programmer)
- [ ] Flags ADR violations rather than overriding them silently
- [ ] Makes gameplay values data-driven, never hardcoded
- [ ] Asks "May I write this to [filepath]?" naming the file before writing
---
@@ -3,7 +3,6 @@
## Agent Summary
Domain: Multiplayer networking, state replication, lag compensation, matchmaking protocol design, and network message schemas.
Does NOT own: gameplay logic (only the networking of it), server infrastructure and deployment (devops-engineer).
Model tier: Sonnet (default).
No gate IDs assigned.
---
@@ -11,8 +10,8 @@ No gate IDs assigned.
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references multiplayer / replication / networking)
- [ ] `allowed-tools:` list includes Read, Write, Edit, Bash, Glob, Grep
- [ ] Model tier is Sonnet (default for specialists)
- [ ] `tools:` list includes Read, Write, Edit, Bash, Glob, Grep
- [ ] Model tier is `inherit` — frontmatter `model:` reads exactly `inherit` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over gameplay logic or server deployment infrastructure
---
@@ -36,22 +35,22 @@ No gate IDs assigned.
- Does NOT produce server deployment configuration, Terraform, or AWS setup scripts
- Explicitly states that server infrastructure belongs to `devops-engineer`
- Redirects the request to `devops-engineer`
- May note it can provide the network protocol spec the server needs to implement once infrastructure is set up
- If it offers any part, it is only the network-side contract the server build needs (protocol, message versioning, connection lifecycle) — no deployment, hosting or scaling configuration
### Case 3: State divergence — rollback/reconciliation
**Input:** "Under high latency, clients are diverging from the authoritative server state for physics objects."
**Expected behavior:**
- Proposes a rollback-and-reconciliation approach (client-side prediction + server authoritative correction)
- Specifies the state snapshot format, reconciliation trigger threshold (e.g., >5 units position error), and correction interpolation speed
- Notes the input buffer pattern for deterministic replay
- Does NOT change the physics simulation itself — documents the interface contract for engine-programmer
- Keeps the client's unacknowledged inputs and re-applies them on top of each server correction (the reconciliation half of "client predicts locally, reconciles with server")
- Does NOT change the physics simulation itself (not networking code) — documents the interface contract the simulation must expose (state snapshot, correction entry point) and asks before any change to that system ("This will require changes to [other system]. Should I coordinate with that first?")
### Case 4: Anti-cheat conflict
**Input:** "We want client-authoritative position for smooth movement, but anti-cheat requires server validation."
**Expected behavior:**
- Surfaces the direct conflict: client-authority is fast but exploitable; server-authority is secure but requires latency compensation
- Coordinates with `security-engineer` to agree on the validation boundary
- Proposes a compromise (server validates position within a tolerance band, flags outliers) rather than unilaterally deciding
- Proposes a compromise (e.g., server validates position within a tolerance band and flags outliers) rather than unilaterally deciding
- Documents the trade-off and escalates the final decision to `technical-director` if security-engineer and network-programmer cannot agree
### Case 5: Context pass — latency budget
@@ -60,7 +59,7 @@ No gate IDs assigned.
- References the 80ms RTT budget explicitly in the design
- Selects replication approach calibrated to that budget (e.g., rollback netcode is preferred for fighting games at this latency)
- Specifies input delay frames calculated from the 80ms budget (e.g., 2 frames at 60fps = 33ms buffer)
- Flags that rollback netcode requires gameplay-programmer to implement deterministic simulation
- Flags that rollback netcode needs a deterministic, re-simulatable game state, and routes it to the roles its coordination line names: engine-programmer for physics and simulation determinism, gameplay-programmer for the gameplay code that rollback re-simulates
---
@@ -72,10 +71,11 @@ No gate IDs assigned.
- [ ] Does not implement gameplay logic — only specifies the network contract for it
- [ ] Coordinates with security-engineer on anti-cheat boundaries
- [ ] Designs to explicit latency targets from provided context
- [ ] Asks "May I write this to [filepath]?" naming the file before writing
---
## Coverage Notes
- Replication strategy (Case 1) should include a bandwidth calculation reviewable by technical-director
- Rollback/reconciliation (Case 3) must document the engine-programmer interface contract clearly
- Rollback/reconciliation (Case 3) must document the interface contract the physics simulation exposes clearly
- Anti-cheat conflict (Case 4) confirms the agent escalates rather than unilaterally deciding security trade-offs
@@ -3,7 +3,6 @@
## Agent Summary
Domain: Profiling, bottleneck identification, performance metrics tracking, and optimization recommendations.
Does NOT own: implementing optimizations (belongs to the appropriate programmer for that domain).
Model tier: Sonnet (default).
No gate IDs assigned.
---
@@ -11,8 +10,8 @@ No gate IDs assigned.
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references profiling / bottleneck analysis / performance metrics)
- [ ] `allowed-tools:` list includes Read, Write, Edit, Bash, Glob, Grep
- [ ] Model tier is Sonnet (default for specialists)
- [ ] `tools:` list includes Read, Write, Edit, Bash, Glob, Grep
- [ ] Model tier is `inherit` — frontmatter `model:` reads exactly `inherit` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over implementing any optimization — explicitly identifies itself as analysis/recommendation only
---
@@ -22,9 +21,9 @@ No gate IDs assigned.
### Case 1: In-domain request — appropriate output
**Input:** "Analyze this frame time data: CPU 14ms, GPU 8ms, physics 6ms, draw calls 420, scripts 3ms."
**Expected behavior:**
- Identifies the primary bottleneck: CPU is over a 16.67ms (60fps) budget at 14ms total
- Identifies the primary bottleneck: the frame is CPU-bound (CPU 14ms vs GPU 8ms) — inside a 16.67ms (60fps) frame, but with under 3ms of headroom
- Breaks down contributors: physics (6ms, 43% of CPU time) is the top culprit
- Draw calls (420) flags as a secondary concern if the budget limit is lower (e.g., 200 draw calls per technical-preferences.md)
- Draw calls (420) flags as a secondary concern if the budget limit is lower (e.g., 200 draw calls per the project's `performance.draw_call_limit`)
- Produces a prioritized bottleneck report:
1. Physics — 6ms, reduce simulation frequency or switch broadphase algorithm
2. Draw calls — 420, implement batching or LOD
@@ -35,32 +34,31 @@ No gate IDs assigned.
**Input:** "Implement the batching optimization to reduce draw calls from 420 to under 200."
**Expected behavior:**
- Does NOT produce implementation code for batching
- Explicitly states that implementing optimizations belongs to the appropriate programmer (engine-programmer for rendering batching)
- Redirects the implementation to `engine-programmer` with the recommendation context attached
- May produce a requirements brief for the optimization so engine-programmer has a clear target
- Explicitly states that implementing optimizations belongs to the owner of the system — `technical-artist`, whose rendering optimization covers batching (naming `engine-programmer` as well, for an engine-level rendering change the batching needs, is fine)
- Redirects the implementation to `technical-artist`, handing over its recommendation as the brief: the target (under 200 draw calls), estimated impact, and implementation cost
### Case 3: Regression identification
**Input:** "Performance dropped significantly after last week's commits. Frame time went from 10ms to 18ms."
**Expected behavior:**
- Proposes a bisection strategy to identify the offending commit range
- Requests or reviews the diff of commits in the window to narrow the likely cause
- Identifies affected systems based on what changed (e.g., if physics code was modified, points to physics as the primary suspect)
- Produces a regression report naming the probable commit, the affected system, and the measured delta
- Compares profiles of a build from before the window (~10ms) and after it (~18ms); if no profile exists for either build, asks for or proposes the captures instead of guessing
- Localizes the 8ms delta to the frame-time categories that grew (gameplay logic, rendering, physics, AI, audio), not to a cause guessed from commit messages or diffs alone
- Names a suspect commit or system only when a profile supports it (e.g., profiles of builds inside the commit range) — never from commit messages or diffs alone
- Reports it under "Regressions Since Last Report" with the measured delta (10ms → 18ms) and the affected category, and recommends a fix owner rather than implementing the fix
### Case 4: Recommendation vs. code quality trade-off
**Input:** "The fastest optimization for the script bottleneck would be to inline all calls and remove abstraction layers."
**Expected behavior:**
- Surfaces the trade-off: inlining improves performance but reduces testability and violates the coding standard requiring unit-testable public methods
- Does NOT recommend the optimization without noting the code quality cost
- Escalates the trade-off to `lead-programmer` for a decision
- May propose a middle path (e.g., profile-guided inlining of only the hottest 2–3 methods) that preserves testability
- Escalates the trade-off to `technical-director`, the agent it reports to, for a decision
- Presents the options with their trade-offs — e.g., inlining only the hottest 2–3 methods, which keeps the public methods testable — rather than one all-or-nothing recommendation
### Case 5: Context pass — technical-preferences.md budget
**Input:** Technical preferences from context: Target 60fps, frame budget 16.67ms, draw calls max 200, memory ceiling 512MB. Request: "Review the current build profile."
### Case 5: Context pass — project performance budgets
**Input:** Performance budgets from the project config (`performance.*` in `project.yaml`) provided in context: Target 60fps, frame budget 16.67ms, draw calls max 200, memory ceiling 512MB. Request: "Review the current build profile."
**Expected behavior:**
- References the specific values from the provided context: 16.67ms, 200 draw calls, 512MB
- Compares current measurements against each threshold explicitly
- Labels each metric as WITHIN BUDGET / AT RISK / OVER BUDGET based on the provided numbers
- Compares current measurements against each threshold explicitly, in its Performance Report Format (Budget / Actual / Status tables for frame time and memory)
- Labels each metric's Status as OK or OVER based on the provided numbers
- Does NOT use different budget numbers than those provided in the context
---
@@ -68,15 +66,16 @@ No gate IDs assigned.
## Protocol Compliance
- [ ] Stays within declared domain (profiling, analysis, recommendations — not implementation)
- [ ] Redirects optimization implementation to the correct programmer domain agent
- [ ] Returns structured findings (bottleneck report with severity, measured values, and recommended action owner)
- [ ] Escalates code-quality trade-offs to lead-programmer rather than deciding unilaterally
- [ ] Redirects optimization implementation to the owner of the system (technical-artist for rendering optimizations such as batching, engine-programmer for engine systems) rather than implementing it
- [ ] Returns structured findings in its Performance Report Format (budget/actual/status tables, top bottlenecks with impact and recommendation, regressions)
- [ ] Escalates code-quality trade-offs to technical-director rather than deciding unilaterally
- [ ] Applies budget thresholds from provided context rather than assumed defaults
- [ ] Labels all findings with a specific action owner (who should implement the fix)
- [ ] Names who should implement each recommended optimization ("recommend and assign") instead of implementing it
- [ ] Asks "May I write this to [filepath]?" naming the file before writing
---
## Coverage Notes
- Frame time analysis (Case 1) output should be structured as a report filed in `production/qa/evidence/`
- Regression case (Case 3) confirms the agent investigates cause, not just measures symptoms
- Frame time analysis (Case 1) output follows the agent's Performance Report Format; when run under `/perf-profile` or `/team-polish`, the report is written to `production/polish/`
- Regression case (Case 3) confirms the agent localizes the cause from profiles across builds, not just measures symptoms or guesses from diffs
- Code quality trade-off (Case 4) verifies the agent does not recommend optimizations that violate coding standards without flagging the conflict
@@ -3,17 +3,16 @@
## Agent Summary
- **Domain**: Rapid throwaway prototypes in the `prototypes/` directory, concept validation experiments, mechanical feasibility tests. Standards intentionally relaxed for speed — prototypes are not production code.
- **Does NOT own**: Production source code in `src/` (gameplay-programmer), design documents (game-designer), production-grade architecture decisions (lead-programmer / technical-director)
- **Model tier**: Sonnet
- **Gate IDs**: None; produces recommendation docs after prototype conclusion; does not participate in phase gates
---
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references rapid prototyping, prototypes/ directory, throwaway code)
- [ ] `allowed-tools:` list matches the agent's role (Read/Write scoped to prototypes/ directory; no production src/ write access)
- [ ] Model tier is Sonnet (default for specialists)
- [ ] Agent definition explicitly states that prototype code is not production code and must not be copied to src/
- [ ] `description:` field is present and domain-specific (references throwaway builds / concept prototypes / speed over standards)
- [ ] `tools:` reads Read, Glob, Grep, Write, Edit, Bash (it writes and runs throwaway builds) and `isolation:` reads `worktree` — frontmatter cannot scope writes to a directory, so the boundary to `prototypes/` is the body's Isolation Requirements (next assertion)
- [ ] Model tier is `sonnet` — frontmatter `model:` reads exactly `sonnet` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition explicitly states that prototype code is not production code and must not be copied into the production code root
---
@@ -22,61 +21,68 @@
### Case 1: In-domain request — prototype a card-drawing mechanic
**Input**: "Prototype a card-drawing mechanic in 2 hours. The core question: does drawing 3 cards per turn with hand-size limit of 7 feel good? I need something to test in a playtest today."
**Expected behavior**:
- Produces a minimal working prototype written in the project's engine scripting language, scoped to `prototypes/card-draw-mechanic/`
- Code prioritizes speed over correctness: no unit tests, no doc comments required, global state is acceptable for a prototype
- Implements the minimal viable mechanic: a deck, a draw function (draw N cards), a hand container with a size limit, and a simple UI or debug print to verify state
- States the falsifiable hypothesis ("If the player draws 3 cards per turn with a hand limit of 7, they will feel [Y] — evidenced by [Z]") and the riskiest assumption before building
- Recommends a prototype path with rationale — a card mechanic where timing precision is not the question points to the HTML or Paper path, not the Engine path
- Proposes scope in 3–5 bullets (deck, draw N, hand limit 7, a minimal state display) and gets confirmation before building
- Output goes to `prototypes/card-draw-concept/` (e.g., a single self-contained `prototype.html` that opens by double-click, or `rules.md` + `play-log.md` on the Paper path); every code file starts with the `PROTOTYPE - NOT FOR PRODUCTION` header naming the question and date
- Code prioritizes speed over correctness: no unit tests, no doc comments required, global state is acceptable; no menus or polish
- Does NOT implement production patterns (dependency injection, signals, data-driven config) unless they take less time than not using them
- Includes a `README.md` in the prototype folder: hypothesis being tested, how to run, what to observe in the playtest
- Asks "May I write this to [filepath]?" before writing
### Case 2: Out-of-domain request — production-grade implementation
**Input**: "The card mechanic prototype worked great. Now write the production implementation of the card system for src/gameplay/cards/."
**Expected behavior**:
- Does not write production code to `src/`
- States clearly: "Prototyper produces throwaway code in prototypes/ to validate concepts; production implementation of validated mechanics is handled by gameplay-programmer"
- Offers to produce a transition document: what the prototype proved, what the production implementation should preserve (the mechanic), and what it should discard (the throwaway implementation patterns)
- States clearly that prototype code is throwaway: production implementation of a validated mechanic is written from scratch to proper standards, and the prototype is reference only
- Points to the prototype's `REPORT.md` (hypothesis, result, recommendation, tuning values discovered, lessons learned) as what carries into production — offering to write it if it does not exist yet — so the knowledge transfers, not the code
- Routes production architecture questions to `lead-programmer`
- Does NOT copy the prototype code into src/ or suggest it as a starting point without warning about its non-production quality
### Case 3: Prototype validates the mechanic — recommendation output
**Input**: "The card-draw prototype playtested well. Three sessions all enjoyed drawing 3 cards/turn with hand limit 7. No confusion observed. What's next?"
**Expected behavior**:
- Produces a prototype conclusion document in `prototypes/card-draw-mechanic/conclusion.md` (or equivalent)
- Document includes: hypothesis that was tested, playtest method (sessions, duration, observer notes), result verdict (VALIDATED), key findings (what worked, any minor issues observed), recommendation for production (specific mechanic parameters to preserve: 3 cards/turn, hand limit 7), and a flag to route the production implementation request to gameplay-programmer
- Does NOT begin writing production code
- Produces `prototypes/card-draw-concept/REPORT.md` from the concept prototype report template, asking for approval before writing it
- Report includes: the hypothesis tested, riskiest assumption, Result as specific observations (3 sessions, no confusion observed), playtester count and a hypothesis verdict of CONFIRMED, **Recommendation: PROCEED** with that evidence, the tuning values to preserve (3 cards/turn, hand limit 7), and lessons learned
- Updates `prototypes/index.md` after the report is written
- Presents PROCEED as a recommendation — the decision belongs to the user / creative-director, not the prototyper
- Does NOT begin writing production code; the next step it points to is design work (GDDs), not implementation
- Output is structured as a decision-ready recommendation, not a narrative summary
### Case 4: Prototype reveals the mechanic is unworkable — abandonment note
**Input**: "The prototype for the physics-based lock-picking mechanic is done. After 4 playtest sessions, all testers found it frustrating — too much precision required, not fun. One tester rage-quit."
**Expected behavior**:
- Produces a prototype abandonment note in `prototypes/lock-picking-physics/conclusion.md`
- Document includes: hypothesis that was tested, result verdict (ABANDONED), specific reasons (precision barrier too high, negative emotional response, rage-quit incident as evidence), and a recommendation for alternative approaches to explore (simplified key-tumbler mechanic, rhythm-based alternative, removal of the mechanic entirely)
- Does NOT recommend persisting with the prototype mechanic because of sunk cost
- Does NOT mark the result as inconclusive — after 4 sessions with consistent negative responses, abandonment is the correct verdict
- Produces `prototypes/lock-picking-physics-concept/REPORT.md` from the concept prototype report template, asking for approval before writing it
- Report includes: the hypothesis tested, a hypothesis verdict of REFUTED, and specific reasons as observations (precision barrier too high, negative emotional response across all 4 sessions, rage-quit incident as evidence)
- **Recommendation: KILL** for the physics-based approach — or PIVOT only with a concrete pivot direction and what to keep (e.g., a simplified key-tumbler or rhythm-based mechanic); never PROCEED
- Does NOT recommend persisting with the prototype mechanic because of sunk cost — the verdict is based on evidence, not effort invested
- Does NOT mark the result as inconclusive — after 4 sessions with consistent negative responses, the evidence supports a decision
### Case 5: Context pass — using the project's engine scripting language
**Input context**: Project uses Godot 4.6 with GDScript (configured in technical-preferences.md).
**Input context**: Project uses Godot 4.6 with GDScript (`engine.name` and `engine.language` in `project.yaml`); the user has chosen the Engine path.
**Input**: "Prototype a basic grid movement system — player clicks a tile and the character moves to it."
**Expected behavior**:
- Produces the prototype in GDScript — not Python, C#, or pseudocode
- Uses Godot 4.6 node types appropriate for a grid: TileMap or a custom grid manager node, CharacterBody2D or Node2D for the player
- Uses Godot 4.6 node types appropriate for a grid: TileMapLayer (not TileMap, which `docs/engine-reference/godot/deprecated-apis.md` lists as deprecated since 4.3) or a custom grid manager node, CharacterBody2D or Node2D for the player
- Does NOT apply production coding standards (no required test coverage, no doc comments, global state acceptable)
- Writes the output to `prototypes/grid-movement/` not to `src/`
- If a Godot 4.6 API is uncertain (given the LLM knowledge cutoff noted in VERSION.md), flags the specific API with a note to verify against the Godot 4.6 docs
- Writes the output to `prototypes/grid-movement-concept/` not to `src/`
- After writing, hands control back: asks the user to run the project and paste any errors or describe what they observe, rather than assuming it worked
- If a Godot 4.6 API is uncertain, flags the specific API with a note to verify against the Godot 4.6 docs — `docs/engine-reference/godot/VERSION.md` reaches the agent through `CLAUDE.md`'s import, and its Knowledge Gap Warning says to cross-reference that directory before suggesting Godot API calls
---
## Protocol Compliance
- [ ] Stays within declared domain (prototypes/ directory only; throwaway code for concept validation)
- [ ] Redirects production implementation requests to gameplay-programmer with a transition document offer
- [ ] Produces structured conclusion documents (VALIDATED or ABANDONED verdict) after prototype evaluation
- [ ] Declines production implementation requests, stating production is written from scratch and pointing to the prototype's REPORT.md as the hand-off
- [ ] Produces a structured REPORT.md with a PROCEED / PIVOT / KILL recommendation, backed by evidence, after prototype evaluation
- [ ] Does not recommend preserving prototype code in production form without explicit warnings
- [ ] Uses the project's configured engine and scripting language; flags version uncertainty
- [ ] Uses the project's configured engine and scripting language; flags version uncertainty, per the Knowledge Gap Warning in the `VERSION.md` that `CLAUDE.md` imports
---
## Coverage Notes
- Case 2 (production redirect) is critical — prototype code leaking into src/ is a common quality problem
- Case 4 (abandonment honesty) tests whether the agent avoids sunk-cost bias — prototypes that fail should be cleanly abandoned
- Case 5 requires that technical-preferences.md has the engine and language configured; test is incomplete if not configured
- Case 5 requires that `project.yaml` has `engine.name` and `engine.language` configured; test is incomplete if not configured. With neither `project.yaml` nor `.claude/docs/technical-preferences.md` naming them, the expected output is a question about the engine and language, not a guess
- The intentional relaxation of coding standards is a feature, not a gap — do not flag missing tests or doc comments as failures in prototype output
- No automated runner; review manually or via `/skill-test`
@@ -3,7 +3,6 @@
## Agent Summary
Domain: SFX specs, audio events, mixing parameters, and sound category definitions.
Does NOT own: music composition direction (audio-director), code implementation of audio systems.
Model tier: Sonnet (default).
No gate IDs assigned.
---
@@ -11,9 +10,9 @@ No gate IDs assigned.
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references SFX / audio events / mixing)
- [ ] `allowed-tools:` list includes Read, Write, Edit, Glob, Grep — does NOT include engine code execution tools
- [ ] Model tier is Sonnet (default for specialists)
- [ ] Agent definition does not claim authority over music direction or audio code implementation
- [ ] `tools:` list includes Read, Write, Edit, Glob, Grep — does NOT include engine code execution tools
- [ ] Model tier is `inherit` — frontmatter `model:` reads exactly `inherit` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over music direction or audio code implementation, and names `audio-director` as the owner of music direction and composition
---
@@ -22,40 +21,40 @@ No gate IDs assigned.
### Case 1: In-domain request — appropriate output
**Input:** "Create an SFX spec for a sword swing attack."
**Expected behavior:**
- Produces a complete audio event spec including:
- Event name (e.g., `sfx_combat_sword_swing`)
- Variation count (minimum 3 to avoid repetition fatigue)
- Pitch range (e.g., ±8% randomization)
- Volume range and normalization target (e.g., -12 dBFS)
- Sound category (e.g., `combat_sfx`)
- Suggested layering notes (whoosh layer + impact transient)
- Output follows the project audio naming convention if one is established
- Produces a complete SFX spec sheet including:
- Description, reference sounds, frequency character, and duration
- Volume range and spatial properties
- Variation plan: number of variants, pitch randomization range (e.g., ±8%), and round-robin behavior
- Audio event entry: what triggers it, priority, concurrency limit, and cooldown
- Bus assignment for mixing (e.g., the combat SFX bus)
- Event name follows the project audio naming convention if one is established (e.g., `sfx_combat_sword_swing`)
- Does NOT create the audio files or write engine code; asks before writing the spec to a file
### Case 2: Out-of-domain request — redirects correctly
**Input:** "Compose a looping ambient music track for the forest level."
**Expected behavior:**
- Does NOT produce music composition direction or a music brief
- Does NOT produce music composition direction or a music brief, and does not create the audio itself
- Explicitly states that music direction belongs to `audio-director`
- Redirects the request to `audio-director`
- May note it can provide an SFX ambience layer spec (wind, wildlife) to complement the music once the music direction is set
- Anything it offers in place of the track is from its own domain — e.g., an ambience layer spec for the forest (base layer, detail sounds such as wind and wildlife, one-shots, transitions) to complement the music once its direction is set — never a music brief
### Case 3: Dynamic parameter — falloff curve spec
**Input:** "The sword swing SFX needs distance falloff so it sounds different across the arena."
**Expected behavior:**
- Produces a spec for the dynamic parameter including:
- Documents the event's spatial properties for distance:
- Parameter name (e.g., `distance` or `listener_distance`)
- Falloff curve type (e.g., logarithmic, linear, custom)
- Near/far distance thresholds with corresponding volume and high-frequency attenuation values
- Occlusion override behavior if applicable
- Does NOT write the audio engine integration code (defers to the appropriate programmer)
- Asks about behavior the request leaves unspecified (e.g., occlusion by arena geometry) rather than assuming it
- Does NOT write the audio engine integration code or change the audio middleware configuration
### Case 4: Naming convention conflict
**Input:** "Add a new SFX event called `SWORD_HIT_1` for the melee system."
**Input:** "Add a new SFX event called `SWORD_HIT_1` for the melee system." [Context includes the audio-director's naming convention: `[category]_[context]_[name]_[variant]`, e.g., `sfx_combat_sword_swing_01`.]
**Expected behavior:**
- Identifies that `SWORD_HIT_1` conflicts with the established event naming convention (snake_case with category prefix, e.g., `sfx_combat_sword_hit`)
- Identifies that `SWORD_HIT_1` deviates from the naming convention in context
- Does NOT silently register the non-conforming name
- Flags the conflict to `audio-director` with the proposed compliant alternative
- Will proceed with the corrected name once confirmed by audio-director
- Flags the deviation explicitly with a compliant alternative (e.g., `sfx_combat_sword_hit_01`), naming `audio-director` as the owner of the convention
- Adds the event only once the user confirms the corrected name (or an explicit exception)
### Case 5: Context pass — uses audio style guide
**Input:** Audio style guide provided in context specifying: "gritty, grounded, no reverb tails over 1.5s, reference: The Witcher 3 combat audio." Request: "Create SFX specs for the full melee combat suite."
@@ -63,7 +62,7 @@ No gate IDs assigned.
- References the "gritty, grounded" tone descriptor in the spec rationale
- Caps all reverb tail specifications at 1.5 seconds as stated
- Notes the reference material (The Witcher 3) as a benchmark for mix levels and transient design
- Does NOT produce specs that contradict the style guide (e.g., no ethereal or heavily reverb-processed specs)
- Does NOT produce specs that contradict the style guide (e.g., no ethereal or heavily reverb-processed specs); where a sound seems to need something the guide rules out, flags it for audio-director instead of deciding the sonic palette itself
---
@@ -71,9 +70,9 @@ No gate IDs assigned.
- [ ] Stays within declared domain (SFX specs, event definitions, mixing parameters)
- [ ] Redirects music direction requests to audio-director
- [ ] Returns structured audio event specs (event name, variations, pitch, volume, category)
- [ ] Returns structured SFX specs (description, volume range, spatial properties, variants and pitch range, trigger/priority/concurrency, bus)
- [ ] Does not produce code for audio system implementation
- [ ] Flags naming convention violations rather than silently accepting non-conforming names
- [ ] Flags deviations from an established naming convention or design doc explicitly rather than silently accepting non-conforming names
- [ ] References provided style guides and constraints in all spec output
---
@@ -3,7 +3,6 @@
## Agent Summary
Domain: Shaders, VFX, rendering optimization, art pipeline tools, and visual performance.
Does NOT own: art style decisions or color palette (art-director), gameplay code (gameplay-programmer).
Model tier: Sonnet (default).
No gate IDs assigned.
---
@@ -11,8 +10,8 @@ No gate IDs assigned.
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references shaders / VFX / rendering)
- [ ] `allowed-tools:` list includes Read, Write, Edit, Bash, Glob, Grep
- [ ] Model tier is Sonnet (default for specialists)
- [ ] `tools:` list includes Read, Write, Edit, Bash, Glob, Grep
- [ ] Model tier is `inherit` — frontmatter `model:` reads exactly `inherit` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over art style direction or gameplay logic
---
@@ -22,10 +21,11 @@ No gate IDs assigned.
### Case 1: In-domain request — appropriate output
**Input:** "Create a dissolve effect shader for enemy death sequences."
**Expected behavior:**
- Proposes the approach (shader structure, exposed parameters) before implementing, and asks "May I write this to [filepath]?" before writing
- Produces shader code or a Shader Graph node spec appropriate to the configured engine (Godot shading language / Unity Shader Graph / Unreal Material Blueprint)
- Defines a `dissolve_amount` uniform (0.0–1.0) as the animation driver
- Uses a noise texture sample to determine the dissolve threshold
- Notes edge-lighting technique as an optional enhancement
- Exposes the dissolve driver as a documented shader parameter (e.g., a `dissolve_amount` uniform, 0.0–1.0, thresholding a noise texture) and documents each parameter's visual effect
- States the effect's performance budget (e.g., texture samples, shader instruction count)
- Leaves the look of the effect (edge color, glow) to art-director rather than deciding it
- Output is engine-version-aware (checks version reference if post-cutoff APIs are needed)
### Case 2: Out-of-domain request — redirects correctly
@@ -34,14 +34,15 @@ No gate IDs assigned.
- Does NOT produce color palette decisions or art direction documents
- Explicitly states that art style decisions belong to `art-director`
- Redirects the request to `art-director`
- May note it can later implement a color-grading or palette LUT shader once the palette is decided
- Any follow-up it offers is implementation on its side — e.g., a color-grading or palette LUT shader once art-director has decided the palette — with no palette values chosen by it
### Case 3: Performance warning — GPU particle count
**Input:** "The VFX system is triggering a GPU particle count warning at 50,000 particles in the explosion pool."
**Expected behavior:**
- Produces an optimization spec addressing the specific warning
- Proposes concrete strategies: particle budget caps per emitter, LOD-based particle reduction, GPU instancing, or switching to mesh-based VFX for distant effects
- Provides before/after GPU cost estimates where calculable
- Sets an explicit particle-count budget for the explosion effect and states the visual-quality cost of each strategy (e.g., as documented quality tiers)
- Flags any visible change to the explosion's look for art-director rather than deciding it
- Does NOT change gameplay behavior of the explosion (delegates any gameplay impact to gameplay-programmer)
### Case 4: Engine version compatibility
@@ -53,12 +54,12 @@ No gate IDs assigned.
- If uncertain about post-cutoff behavior, explicitly states the uncertainty and directs to verified docs
### Case 5: Context pass — uses performance budget
**Input:** Performance budget from `technical-preferences.md` provided in context: 2ms GPU frame budget, max 200 draw calls. Request: "Optimize the forest rendering system."
**Input:** Performance budget provided in context: 2ms GPU budget for the forest, max 200 draw calls per frame. Request: "Optimize the forest rendering system."
**Expected behavior:**
- References the specific 2ms GPU budget and 200 draw call limit from the provided context
- Proposes optimizations calibrated to those exact targets (e.g., "batching reduces draw calls from 340 to ~180, within the 200 limit")
- Does NOT propose optimizations that would exceed the stated budgets in other dimensions
- Produces a ranked list of optimizations by expected impact vs. implementation cost
- Treats the 2ms GPU budget and 200 draw call limit from the provided context as the budgets it enforces — no other numbers substituted
- Proposes rendering optimizations (LOD, occlusion, batching, atlasing), each tied to the budget it targets (e.g., "batching reduces draw calls from 340 to ~180, within the 200 limit")
- Calls out any optimization that helps one budget at the other's expense (e.g., merged meshes cut draw calls but can defeat occlusion and raise GPU time past 2ms) instead of presenting it as a free win
- Proposes the approach before implementing and asks before writing files
---
@@ -69,7 +70,7 @@ No gate IDs assigned.
- [ ] Returns structured findings (shader code, optimization specs with metrics, node graphs)
- [ ] Does not modify gameplay code files without explicit delegation
- [ ] Checks engine version reference before suggesting post-cutoff APIs
- [ ] Quantifies performance changes against stated budgets
- [ ] Ties each proposed optimization to the per-category budget it serves (draw calls, particle count, shader instructions, texture memory, overdraw)
---
@@ -2,8 +2,7 @@
## Agent Summary
Domain: Editor extensions, content authoring tools, debug utilities, and pipeline automation scripts.
Does NOT own: game code (gameplay-programmer, ui-programmer, etc.), engine core systems (engine-programmer).
Model tier: Sonnet (default).
Does NOT own: game runtime code (gameplay-programmer), engine core systems (engine-programmer), art pipeline requirements (technical-artist).
No gate IDs assigned.
---
@@ -11,8 +10,8 @@ No gate IDs assigned.
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references editor tools / pipeline / debug utilities)
- [ ] `allowed-tools:` list includes Read, Write, Edit, Bash, Glob, Grep
- [ ] Model tier is Sonnet (default for specialists)
- [ ] `tools:` list includes Read, Write, Edit, Bash, Glob, Grep
- [ ] Model tier is `inherit` — frontmatter `model:` reads exactly `inherit` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over game source code or engine internals
---
@@ -34,23 +33,23 @@ No gate IDs assigned.
- Does NOT produce gameplay mechanic code
- Explicitly states that combat system implementation belongs to `gameplay-programmer`
- Redirects the request to `gameplay-programmer`
- May note it can build a debug overlay tool to visualize combo state if useful during development
- Any part it offers is tooling on its side of the line — e.g., a debug overlay that visualizes combo state — never combo logic
### Case 3: Runtime data access — coordination required
**Input:** "The waypoint editor tool needs to read game data at runtime to validate patrol routes against the AI budget."
**Input:** "The waypoint editor must check at edit time that every patrol segment is walkable, but the collision queries that answer this live in the game's runtime code and the editor cannot call them."
**Expected behavior:**
- Identifies that runtime data access from an editor plugin requires a defined, safe interface to the game's runtime systems
- Coordinates with `engine-programmer` to establish a read-only data access pattern (e.g., a resource validation API)
- Does NOT directly read internal engine or game memory structures without an agreed interface
- Documents the required interface before implementing the tool
- Identifies that the tool needs a runtime query the editor cannot yet call, and that adding one is a change to game runtime code
- Does NOT add the runtime hook itself — delegates it to `engine-programmer` (collision queries are engine-level runtime code) and asks before coordinating ("This will require changes to [other system]. Should I coordinate with that first?")
- Documents the read-only interface the tool needs (inputs, outputs, called from editor context) before implementing the tool
- Reports failing segments as clear, actionable errors rather than silently skipping them
### Case 4: Engine version breakage
**Input:** "After the engine upgrade, the waypoint editor tool crashes on startup."
**Expected behavior:**
- Checks the engine version reference (`docs/engine-reference/`) for breaking changes in editor plugin APIs
- Identifies the specific API or signal that changed in the new version
- Checks the engine version reference (`docs/engine-reference/`) before touching editor plugin APIs, including the pinned version in VERSION.md against the upgraded editor (an `Installed at pin time` of NOT DETERMINED is an unknown gap, not a match)
- Looks for the failing API in the reference's breaking-changes and deprecated-APIs files rather than recalling it from training data; if they do not cover it, says so instead of asserting a cause
- Produces a targeted fix for the breaking change
- Notes any other tools that may be affected by the same API change
- Tests the fix on representative data before calling the tool fixed
### Case 5: Context pass — art pipeline requirements
**Input:** Art pipeline requirements provided in context: "All texture imports must set compression to VRAM Compressed, generate mipmaps, and tag with a LOD group." Request: "Build an asset import tool that enforces these settings."
@@ -58,7 +57,7 @@ No gate IDs assigned.
- References all three requirements from the context: VRAM compression, mipmap generation, LOD group tagging
- Produces an import tool that validates and applies all three settings on import
- Adds a warning or error report for assets that fail to meet the specified settings
- Does NOT change the art pipeline requirements themselves (those belong to art-director / technical-artist)
- Treats the three settings as given: does NOT change or add requirements itself — any change it thinks is needed is raised with `technical-artist`, its partner for art pipeline tools
---
@@ -67,9 +66,10 @@ No gate IDs assigned.
- [ ] Stays within declared domain (editor tools, pipeline scripts, debug utilities)
- [ ] Redirects game code requests to appropriate programmer agents
- [ ] Returns structured findings (tool specs, editor extension code, pipeline scripts)
- [ ] Coordinates with engine-programmer before accessing runtime data from editor context
- [ ] Delegates any runtime-code change a tool depends on (e.g., a query API) to engine-programmer or gameplay-programmer instead of making it
- [ ] Checks engine version reference before using editor plugin APIs
- [ ] Builds tools to enforce requirements, does not author the requirements themselves
- [ ] Asks "May I write this to [filepath]?" naming the file before writing
---
@@ -2,8 +2,7 @@
## Agent Summary
Domain: Menu screens, HUDs, inventory screens, dialogue boxes, UI framework code, and data binding.
Does NOT own: UX flow design (ux-designer), visual style direction (art-director / technical-artist).
Model tier: Sonnet (default).
Does NOT own: UX flow and interaction design, including UI animation timing (ux-designer), visual style direction (art-director).
No gate IDs assigned.
---
@@ -11,8 +10,8 @@ No gate IDs assigned.
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references menus / HUDs / UI framework / data binding)
- [ ] `allowed-tools:` list includes Read, Write, Edit, Bash, Glob, Grep
- [ ] Model tier is Sonnet (default for specialists)
- [ ] `tools:` list includes Read, Write, Edit, Bash, Glob, Grep
- [ ] Model tier is `inherit` — frontmatter `model:` reads exactly `inherit` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over UX flow design or visual art direction
---
@@ -20,11 +19,11 @@ No gate IDs assigned.
## Test Cases
### Case 1: In-domain request — appropriate output
**Input:** "Implement the inventory screen from the UX spec in `design/ux/inventory-flow.md`."
**Input:** The UX spec at `design/ux/inventory-flow.md` defines five slot states: default, hover, selected, empty-slot, locked-slot. Request: "Implement the inventory screen from the UX spec in `design/ux/inventory-flow.md`."
**Expected behavior:**
- Reads the UX spec before producing any code
- Produces implementation using the project's configured UI framework (UI Toolkit, UGUI, UMG, or Godot Control nodes)
- Implements all states defined in the spec (default, hover, selected, empty-slot, locked-slot)
- Implements every state the spec defines (default, hover, selected, empty-slot, locked-slot) — none dropped, none invented
- Binds inventory data to UI elements via the project's data model, not hardcoded values
- Includes doc comments on public UI API per coding standards
@@ -39,10 +38,10 @@ No gate IDs assigned.
### Case 3: Custom animation coordination
**Input:** "The item selection in the inventory needs a custom bounce animation when selected."
**Expected behavior:**
- Recognizes that defining the animation curve and feel is within technical-artist territory
- Does NOT invent animation parameters (timing, easing) without a spec
- Coordinates with `technical-artist` for an animation spec (duration, easing curve, overshoot amount)
- Once the spec is provided, produces the implementation binding the animation to the selection state
- Recognizes that the bounce's feel (duration, easing curve, overshoot) is UI interaction and visual design, which it implements but does not design
- Checks the UX spec it is implementing for those values first; does NOT invent them if they are absent
- Asks the spec owner — `ux-designer` for interaction timing, `art-director` for visual style — for the missing values
- Once the values are provided, binds the animation to the selection state, skippable and respecting the player's motion preference
### Case 4: Ambiguous UX spec — flags back
**Input:** The UX spec states "show item details on selection" but does not define what happens when an empty slot is selected.
@@ -50,7 +49,7 @@ No gate IDs assigned.
- Identifies the ambiguity in the spec (empty slot selection state is undefined)
- Does NOT make an arbitrary implementation decision for the undefined state
- Flags the ambiguity back to `ux-designer` with the specific question: "What should the detail panel show when an empty inventory slot is selected?"
- May propose two common options (hide panel / show placeholder) to help ux-designer decide quickly
- Any options it offers (e.g., hide the panel / show a placeholder) go to ux-designer as part of the question — none is implemented before the answer
### Case 5: Context pass — engine UI toolkit
**Input:** Engine context provided: project uses Godot 4.6 with Control node UI. Request: "Implement a scrollable item list for the inventory."
@@ -66,14 +65,15 @@ No gate IDs assigned.
- [ ] Stays within declared domain (menus, HUDs, UI framework, data binding)
- [ ] Redirects UX flow design to ux-designer
- [ ] Coordinates with technical-artist for animation specs before implementing animations
- [ ] Takes animation timing and easing from ux-designer / art-director specs rather than inventing them, and makes every animation skippable and motion-preference aware
- [ ] Flags ambiguous UX specs back to ux-designer rather than making arbitrary implementation decisions
- [ ] Returns structured output (implementation code, data binding patterns, state machine for UI states)
- [ ] Uses the correct engine UI toolkit for the project — never cross-engine code
- [ ] Asks "May I write this to [filepath]?" naming the file before writing
---
## Coverage Notes
- Inventory implementation (Case 1) should have a UI interaction test or manual walkthrough doc in `production/qa/evidence/`
- Inventory implementation (Case 1) should have a retained screenshot of each screen touched in `production/qa/evidence/`
- Animation coordination (Case 3) confirms the agent does not invent feel parameters without a spec
- Ambiguous spec (Case 4) verifies the agent routes spec gaps back to the authoring agent rather than guessing
@@ -3,7 +3,6 @@
## Agent Summary
Domain: User experience flows, interaction design, information architecture, input handling design, and onboarding UX.
Does NOT own: visual art style (art-director), UI implementation code (ui-programmer).
Model tier: Sonnet (default).
No gate IDs assigned.
---
@@ -11,8 +10,8 @@ No gate IDs assigned.
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references UX flows / interaction design / information architecture)
- [ ] `allowed-tools:` list includes Read, Write, Edit, Glob, Grep
- [ ] Model tier is Sonnet (default for specialists)
- [ ] `tools:` list includes Read, Write, Edit, Glob, Grep
- [ ] Model tier is `inherit` — frontmatter `model:` reads exactly `inherit` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over visual art direction or UI implementation code
---
@@ -22,11 +21,13 @@ No gate IDs assigned.
### Case 1: In-domain request — appropriate output
**Input:** "Design the inventory management flow for a survival game."
**Expected behavior:**
- Produces a user flow diagram (states and transitions) for the inventory: open, browse, select item, sub-actions (equip/drop/combine), close
- Defines all interaction states (default, hover, selected, empty-slot, locked-slot)
- Specifies input mappings for each action (keyboard, gamepad if applicable)
- Notes cognitive load considerations (e.g., maximum items visible without scrolling)
- Before drafting, asks clarifying questions (core player goal, constraints such as input methods and scope, reference games) and presents 2-4 flow options with pros/cons grounded in UX theory (e.g., mental models, progressive disclosure, Fitts's Law), with a recommendation and the final choice deferred to the user
- The drafted flow maps each step and transition: open, browse, select item, sub-actions (equip/drop/combine), close — and names the friction points it removes
- Specifies button assignments and contextual actions for each input method in scope (keyboard/mouse, gamepad, touch if applicable)
- Specifies player feedback for each action (visual, audio, haptic) so the player always knows what happened and why
- Checks the flow against the agent's Accessibility Checklist (keyboard-only, gamepad-only, not reliant on color alone, readable at minimum font size)
- Does NOT produce visual design (colors, icons) or implementation code
- Asks "May I write this to [filepath]?" before writing the spec
### Case 2: Out-of-domain request — redirects correctly
**Input:** "Implement the inventory screen in GDScript with drag-and-drop support."
@@ -34,31 +35,31 @@ No gate IDs assigned.
- Does NOT produce implementation code
- Explicitly states that UI code implementation belongs to `ui-programmer`
- Redirects the request to `ui-programmer`
- Notes that the UX flow spec should be provided to ui-programmer as the implementation reference
- Offers the part of the request it does own: the drag-and-drop interaction design (drag affordance, valid/invalid drop feedback, and a non-drag equivalent so the screen stays usable with gamepad only and keyboard only) for ui-programmer to implement against
### Case 3: Flow depth conflict — simplification
**Input:** "The lead designer says the current 5-step crafting flow is too deep; maximum 3 steps allowed."
**Expected behavior:**
- Produces a revised 3-step flow that collapses the original 5-step sequence
- Shows clearly what was merged or removed and why each collapse is safe from a usability standpoint
- Does NOT simply remove steps without addressing the user's goal at each removed step
- Flags if the 3-step constraint makes any required use case impossible and proposes an alternative
- Presents 2-4 ways to reach a 3-step flow, each with pros/cons and a recommendation, and defers the choice to the user
- For each option, shows which of the 5 steps are merged or removed and what each removed step did for the player, so the usability cost of the collapse is visible
- Does NOT drop a step whose player goal has nowhere else to happen without saying so
- Flags any required use case the 3-step limit cannot serve for user input, and proposes an alternative (e.g., progressive disclosure of advanced options)
### Case 4: Accessibility conflict
**Input:** "The onboarding flow uses a timed prompt (auto-advances after 3 seconds) to keep pace, but this conflicts with accessibility requirements for user-controlled timing."
**Expected behavior:**
- Identifies the conflict with WCAG 2.1 2.2.1 (Timing Adjustable)
- Does NOT override the accessibility requirement to preserve pace
- Coordinates with `accessibility-specialist` to agree on a compliant solution
- Proposes alternatives: pause-on-hover, skip button, settings option to disable auto-advance
- Identifies the conflict: an auto-advancing prompt takes timing out of the player's control
- Does NOT keep the auto-advance to preserve pace — accessibility requirements are not overridden for aesthetics
- Coordinates with `accessibility-specialist`, which owns the WCAG criterion that applies (SC 2.2.1 Timing Adjustable), to agree on a compliant solution
- Presents alternatives as options with pros/cons — player-advanced prompt, skip or pause control, a setting to disable auto-advance — and shows how each keeps the onboarding's information pacing
### Case 5: Context pass — player mental model research
**Input:** Playtest research provided in context: "Players consistently expected the 'Crafting' option to be inside the Inventory screen, not in a separate top-level menu." Request: "Redesign the navigation IA for crafting."
**Expected behavior:**
- References the specific player expectation from the research (crafting expected inside inventory)
- Restructures the information architecture to place crafting as a tab or panel within the inventory screen
- Does NOT produce a design that contradicts the stated player mental model without explicit justification
- Notes the research source in the rationale for the design decision
- Presents IA options with pros/cons and recommends one that places crafting inside the inventory screen (e.g., a tab or panel), deferring the final choice to the user
- Does NOT recommend a design that contradicts the stated player mental model without explicit justification
- The WHY behind the recommendation cites the playtest finding and names it as the players' mental model
---
@@ -66,10 +67,11 @@ No gate IDs assigned.
- [ ] Stays within declared domain (UX flows, interaction design, IA, onboarding)
- [ ] Redirects code implementation to ui-programmer, visual style to art-director
- [ ] Returns structured findings (state diagrams, flow steps, input mappings) not freeform opinions
- [ ] Coordinates with accessibility-specialist when flows have timing or cognitive load constraints
- [ ] Designs flows based on provided user research, not assumed behavior
- [ ] Presents 2-4 options with pros/cons and a recommendation before drafting, and defers the decision to the user
- [ ] Coordinates with accessibility-specialist when a flow conflicts with an accessibility requirement
- [ ] Grounds recommendations in provided player research when it is given, citing it in the rationale, rather than in assumed behavior
- [ ] Documents rationale for flow decisions against user goals
- [ ] Asks "May I write this to [filepath]?" before writing
---
@@ -3,7 +3,6 @@
## Agent Summary
- **Domain**: World lore architecture — factions and their cultures/governments/motivations, world history, geography and ecology, cosmology and metaphysics, world rules (how magic works, what is and is not possible), internal consistency enforcement across the world document
- **Does NOT own**: Specific NPC or quest dialogue (writer), game mechanics rules derived from world rules (game-designer/systems-designer), narrative story structure and arc design (narrative-director)
- **Model tier**: Sonnet
- **Gate IDs**: None; escalates world rule/mechanic conflicts to narrative-director and game-designer jointly
---
@@ -11,8 +10,8 @@
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references world lore, factions, history, world rules, ecology)
- [ ] `allowed-tools:` list matches the agent's role (Read/Write for design/narrative/world/ documents; no game source, mechanic design, or dialogue files)
- [ ] Model tier is Sonnet (default for creative specialists)
- [ ] `tools:` reads Read, Glob, Grep, Write, Edit and `disallowedTools:` lists Bash — document authoring only, no shell or code execution
- [ ] Model tier is `inherit` — frontmatter `model:` reads exactly `inherit` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over dialogue writing, mechanic design, or narrative arc structure
---
@@ -22,17 +21,18 @@
### Case 1: In-domain request — faction culture and government design
**Input**: "Design the Ironveil Merchant Consortium — a powerful trading faction in our world. I need their culture, government structure, and internal motivations."
**Expected behavior**:
- Produces a faction profile document with: cultural values and norms, government structure (how decisions are made, who holds power, succession or appointment process), internal factions or tensions within the consortium, relationship to other factions (allies, rivals, neutral parties), and primary motivations (what they want and why)
- Before drafting, asks clarifying questions and presents 2-4 options for the government model (e.g., council of founding houses, elected chair, shareholder-weighted vote) with pros/cons and a recommendation, deferring the choice to the user
- Produces a faction profile with: motivations (what they want and why), power structure (how decisions are made, who holds power, succession or appointment), relationships to other factions (allies, rivals, neutral parties), territories, player-facing personality, and cultural details (customs, beliefs, daily life)
- The faction is internally consistent: a merchant consortium's government is driven by economic logic, not feudal or religious logic, unless a deliberate hybrid is specified
- Output includes at least one internal tension or contradiction within the faction — factions without internal complexity are flat
- Formatted as a structured faction profile, not a narrative essay
- The entry carries the Lore Document Standard fields: Canon Level, Visible To Player, Cross-References, Contradictions Check, Source
- Formatted as a structured faction profile, not a narrative essay; asks "May I create [filepath] with the section skeleton?" before creating the file and "May I write this section to [filepath]?" before writing each section
### Case 2: Out-of-domain request — dialogue writing
**Input**: "Write the dialogue for a Ironveil Consortium merchant NPC that the player meets at the city gates."
**Expected behavior**:
- Does not produce NPC dialogue
- States clearly: "Dialogue writing is owned by writer; I provide the world and faction context that informs the dialogue, including the faction's culture, tone, and speaking style"
- Offers to produce the faction's speaking style notes and cultural context that writer would need to write consistent dialogue
- States that dialogue writing is owned by `writer`, and that its own part is the world and faction context that informs the dialogue — the faction's culture, tone and speaking style
- Offers to produce the faction's cultural details — customs, beliefs, language fragments, daily life — that writer would need to write consistent dialogue
### Case 3: New lore entry contradicts established history — conflict flagging
**Input**: "Add a lore entry stating the Ironveil Consortium was founded 50 years ago by a single merchant family." [Context includes existing lore: the Consortium has existed for 300 years and was founded as a collective by 12 rival trading houses.]
@@ -40,8 +40,8 @@
- Identifies the contradiction: existing lore states 300-year history and a founding coalition of 12 houses; the new entry claims 50 years and a single founding family
- Does NOT write the new entry as requested
- Flags the conflict: states both versions, identifies which is established and which is the proposed change
- Proposes resolution options: (a) the new entry is wrong and should be corrected; (b) the existing lore should be updated if the new version is the intended canon; (c) there is an in-world explanation (the current family claims founding credit despite the collective origin — a deliberate narrative unreliable narrator)
- Routes the resolution to narrative-director if no clear answer exists
- Proposes resolution options: (a) the new entry is wrong and should be corrected; (b) the existing lore should be updated if the new version is the intended canon; (c) there is an in-world explanation (the current family claims founding credit despite the collective origin — a deliberate unreliable narrator, with the truth documented separately)
- Does not apply option (b) on its own: changing established canon requires narrative-director approval
### Case 4: World rule has gameplay implications — coordination with game-designer
**Input**: "I want to establish a world rule: magic users who cast spells near iron ore are weakened. Iron disrupts arcane energy."
@@ -2,8 +2,7 @@
## Agent Summary
- **Domain**: In-game written content — NPC dialogue (including branching trees), lore codex entries, item and ability descriptions, environmental text (signs, books, notes), quest text, tutorial text, in-world written documents
- **Does NOT own**: Story architecture and narrative structure (narrative-director), world lore and world rules (world-builder), UX copy and UI labels (ux-designer), patch notes (community-manager)
- **Model tier**: Sonnet
- **Does NOT own**: Story architecture and narrative structure (narrative-director), world lore and world rules (world-builder), UX flows and information architecture (ux-designer; it writes UI microcopy, not the UX around it), patch notes (community-manager)
- **Gate IDs**: None; flags lore inconsistencies to narrative-director rather than resolving them autonomously
---
@@ -11,8 +10,8 @@
## Static Assertions (Structural)
- [ ] `description:` field is present and domain-specific (references dialogue, lore entries, item descriptions, in-game text)
- [ ] `allowed-tools:` list matches the agent's role (Read/Write for design/narrative/ and assets/data/dialogue/; no code or world-building architecture files)
- [ ] Model tier is Sonnet (default for creative specialists)
- [ ] `tools:` reads Read, Glob, Grep, Write, Edit and `disallowedTools:` lists Bash — text authoring only, no shell or code execution
- [ ] Model tier is `inherit` — frontmatter `model:` reads exactly `inherit` (tiers: `.claude/docs/model-tiers.md`)
- [ ] Agent definition does not claim authority over narrative structure, world rules, or UX copy direction
---
@@ -22,11 +21,12 @@
### Case 1: In-domain request — NPC merchant dialogue
**Input**: "Write dialogue for Mira, a traveling merchant NPC. She sells general supplies. Players can ask her about her wares, the road ahead, and rumors."
**Expected behavior**:
- Produces a dialogue tree with at least three top-level conversation options: [Wares], [The Road Ahead], [Rumors]
- Each branch has a distinct conversational response in Mira's voice — not generic merchant filler
- Includes at least one response that has a follow-up branch (showing tree structure, not just flat responses)
- Mira's voice is consistent across branches: if she's warm and chatty in one branch, she's not brusque in another without reason
- Output is formatted as a structured dialogue tree: node label, NPC line, player options, next node
- Looks for Mira's voice profile (voice profiles are defined by narrative-director); if none is provided, says so and asks, or proposes a provisional voice for approval — it does not decide her character arc
- Produces a dialogue tree with at least three top-level conversation options: [Wares], [The Road Ahead], [Rumors], and at least one follow-up branch (tree structure, not flat responses)
- Every line has a speaker tag and a context note, and branch conditions carry condition/state annotations in a consistent format
- No line exceeds 120 characters; any variable insertion uses a named placeholder (e.g., `{player_name}`)
- Road and rumor content does not contradict established world-building
- Drafts in conversation and asks "May I write this to [filepath]?" before writing (for a multi-section file, it first asks to create the section skeleton)
### Case 2: Out-of-domain request — world history design
**Input**: "Design the history of the world — when the first kingdom was founded, what the great wars were, and why magic was banned."
@@ -41,7 +41,7 @@
- Identifies the contradiction: established lore states dragons are alive and revered; dialogue stating they're extinct directly conflicts
- Does NOT write the requested line as given
- Flags the inconsistency to narrative-director: "Mira's dialogue as requested contradicts established lore (dragons are alive per world-builder's document); requires narrative-director resolution before I can write this line"
- Offers an alternative: a line that references dragons in a way consistent with the established lore (e.g., Mira expresses awe about a dragon sighting in the north)
- Offers the user a lore-consistent alternative line (e.g., Mira expresses awe about a dragon sighting in the north) to use while the conflict is resolved
### Case 4: Item description references an undesigned mechanic
**Input**: "Write a description for the 'Berserker's Chalice' — a consumable that triggers the Berserker state when drunk."
@@ -49,7 +49,7 @@
- Identifies the dependency gap: "Berserker state" is not defined in any provided game design document
- Flags the missing dependency: "This description references a 'Berserker state' mechanic that has no GDD entry — I cannot write accurate flavor text for a mechanic whose rules are undefined, as the description may create incorrect player expectations"
- Does NOT write a description that invents mechanic details (duration, effects) that may conflict with the eventual design
- Offers two paths: (a) write a vague, non-mechanical description that creates no false expectations, flagged as temporary; (b) wait for game-designer to define the Berserker state first
- Raises the missing definition with game-designer (its coordinator for mechanical clarity in text) and asks the user how to proceed: (a) a vague, non-mechanical description that creates no false expectations, flagged as temporary; or (b) wait for game-designer to define the Berserker state first
### Case 5: Context pass — character voice guide
**Input context**: Character voice guide for Mira: She speaks in short, energetic sentences. Uses merchant slang ("a fine bargain," "coin well spent"). Drops pronouns occasionally ("Good wares, these."). Never uses contractions — always "I will" not "I'll". Warm but slightly mercenary.
@@ -71,6 +71,7 @@
- [ ] Flags lore contradictions to narrative-director rather than silently writing inconsistent content
- [ ] Identifies mechanic dependency gaps before writing item descriptions that could create false player expectations
- [ ] Applies all rules from a provided character voice guide — no partial compliance
- [ ] For a multi-section document (e.g., a set of lore entries), asks "May I create [filepath] with the section skeleton?" before creating the file, writes each section once it is approved, and updates `production/session-state/active.md` after each section
---