# Pack AI and Enemy Roster Expansion Implementation Plan **User-requested activation, 12 October 2026:** the twelve authored composition profiles are now enabled in normal Verdant spawning. Fresh focused checks pass 18 authoring and 43 spawning cases, including saved-table automatic specialist/ordinary selection in both families. The normal development build succeeds with zero errors. This activates the feature for playtesting; broader automatic multiplayer/balance/human acceptance remains open. The earlier checkpoint below remains historical. See the [activation record](../../ENEMY_ROSTER_VALIDATION.md#automatic-composition-activation). **Roster prototype checkpoint, 11 October 2026:** tasks 6–10 runtime/assets are implemented with three primitive faction appearances, five gameplay prefabs, typed server actions and manual debug presets. Task11 profiles are authored but automatic stage composition selection remains disabled until specialist acceptance. Fresh full EditMode:1,361/1,361; full PlayMode checkpoint:209/209 followed by six affected native passes after navigation authoring corrections; two/four-peer specialist cohorts each pass23 checkpoints, including real generator break/body damage/recovery and clean rehost. Normal/debug/release builds:zero errors. Actual terrain motion, remaining combat/progression and human gates remain open. Unchecked tasks below retain their complete acceptance meaning. See [implementation, retained failures and remaining gates](../../ENEMY_ROSTER_VALIDATION.md). This adds no Natural attempts or Task5 coverage. **Prospective review amendment, 11 October 2026:** use the current [risk/review workflow](../../AGENT_WORKFLOW.md) for future generic review selection. It supersedes blanket three-perspective defaults below, not specific feature review requirements, authority/lifecycle contracts or acceptance gates. High-risk shared defense, spawn, lifecycle and broad roster changes still require all three perspectives before and after. Preserve every completed checkbox, failure, Task5 gap and cumulative campaign budget; this documentation change authorizes no new attempts. **Prospective verification amendment, 10 October 2026:** future slices select focused/integrated checks using [TESTING.md](../../TESTING.md) and the [catalogue](../../TEST_CATALOGUE.md). Run broad checks once against the integrated frozen change, then repeat only invalidated checks. Existing authority/lifecycle/release and affected two/four-player/stage requirements remain; schedule common regressions once after arena cleanup and identify compatible historical reuse explicitly. This changes future scheduling, not completed checkboxes, retained failures or acceptance. Task5 natural/human gaps stay open; this procedure authorizes no additional campaign rerolls. > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans or superpowers:subagent-driven-development at execution. Steps use checkboxes. Follow the repository's three independent implementation perspectives before each substantial slice and after integration. This document requests no agents during planning. **Status:** Implementation in progress, updated 10 October 2026. Hand-authored setup, initial AI diagnostics, dynamic-circle admission, host pack intent/guidance/member-grace data and initial unseen ingress permission are integrated and verified. The seventh debug-arena scenario and normal-menu/stage regression pass. Task3 moving formation passes native, terrain, 16-actor pressure, rendered and actual clustered/split four-player verification; the narrow entry-protocol prerequisite is repaired. Task4 actual actor contact/FSM/attack grace is implemented with1057 EditMode/65 PlayMode passes and a real two-owner stationary melee RED/GREEN. Matching two/four-player arena, ten-phase menu and23-phase full-stage regressions pass with clean cleanup. Tracer TaskT is implemented and accepted within automated/Editor/network boundaries after the user-corrected terrain-collision requirement. Task5A1 receipts and5A2 passive observer foundations are implemented and verified. Task5B owner motor input and its remote-validation prerequisite are accepted as a bounded foundation:1,238 EditMode/184 PlayMode, zero-error builds/release exclusion, strict two/four-owner movement, both-size warp settlement, four-player default-off arena and23-phase normal-stage progression all pass with clean cleanup. The bounded five-cell natural-arrival campaign is completed, with four cells still incomplete; Task5 acceptance and roster expansion remain pending. Task0 arrival/variety and Task5 acceptance remain separate gates. Jump-across navigation is disabled. Concept sheets are planning images, not current Unity captures. **Goal:** Wire the replacement hand-authored Verdant scene safely, expose AI diagnostics, implement purposeful pack behavior and revised tracer fire, and expand the ordinary roster with four distinct primitive-built enemy roles. **Architecture:** A host-owned pack intent sits above individual navigation and attack execution. Replace Explore/Search with Advance, using a soft moving gathering circle and periodically refreshed player-area guidance. Separate guidance from observed combat evidence; shared sight switches the pack to Engage, while each attacker retains personal attack checks. **Tech stack:** Pinned Unity 6000.6.4f1, existing C#/URP/NGO/AI Navigation packages, Unity Test Framework and connected Editor tools. No dependency upgrades. **Scope update — 8 October 2026:** Jump-across navigation was removed at the user's request. Keep `maxJumpAcrossDistance = 0` for both agent types and disable surface link generation. Use connected walkable ground, ramps, stairs and authored bridges. ## To-do log Unchecked items still require their complete acceptance evidence. Each numbered item maps to a task below; this is the current combined implementation queue, replacing the narrower pack-only title. - [x] **S — FIRST: Hand-authored scene setup:** preserve the replacement terrain; bind multiplayer, run/stage systems, player spawns, encounters, portal, spatial limits and navigation; validate missing/deleted references. - [ ] **D — AI debug mode:** toggle paths, groups, actual states and diagnostics; extend it as pack/archetype slices integrate. - [ ] **0 — Dynamic spawning:** map-owned distance rules, fresh circles, randomized valid members. - [x] **1 — Ingress:** prove and fix the no-target movement-permission conflict. - [x] **2 — Contact:** shared observation/grace rule APIs and stable player-area guidance; actual actor reporting/action integration is completed in task4. - [x] **3 — Navigation:** soft moving formation, simultaneous ingress, terrain and lag recovery; direct-native acceptance passed, natural selector arrivals remain Task0/5. - [x] **4 — Actions:** integrate Advance/Engage/grace with windup, bursts, lunges and controls. - [x] **T — Tracer revision:** 40% lower base damage, bounded wavy/jitter movement, and collision with terrain and obstacles for launched enemy tracer bolts. - [ ] **5 — Pack checkpoint:** existing-roster Editor/build/network acceptance before roster expansion. - [ ] **6 — Prototype foundation:** runtime/contracts and five primitive gameplay prefabs implemented; complete acceptance remains open. - [ ] **7 — Tether Keeper:** protection/replicated links/source cleanup implemented with native proof; remaining specialist gates open. - [ ] **8 — Lancer:** committed precision shot/reservation implemented with native dodge proof; remaining specialist gates open. - [ ] **9 — Bulwark:** shield/generator/weapon interception implemented with native proof; full interaction/peer/readability gates open. - [ ] **10 — Splinterbeast:** finite split/population/scaling/reward policy implemented with native proof; complete acceptance remains open. - [ ] **11 — Combined acceptance:** authored compositions, solo/two/four-player tests, rendered prototypes and cleanup. **Design packet:** [Roster designs and primitive recipes](../../Design/Enemies/2026-10-08/ROSTER_DESIGNS.md). Use the existing `ConceptArt/Enemies.png`, crawler and ranged sheets as faction references. The supplied four-enemy scope and primitive-only first pass are confirmed; all new enemy numerical tuning below is proposed until measured. **Spec:** The conversation requirements are captured in the design contract below. Read alongside `Docs/PROJECT_PLAN.md`, `Docs/VERDANT_GROUP_DECISIONS.md`, the current state/movement graphs in `Docs/Design/Enemies/`, and `TestResults/ranged-idle-investigation.txt`. This plan supersedes the earlier frozen-hint-only arrival and all-state single-ranged-reposition rules when implemented; existing validation describes the previous implementation. ## Replacement-scene and tracer amendment — 8 October The user-authored first stage is **`Assets/_Project/Scenes/VerdantRelay.unity`**. Current setup audit finds one shared encounter/projectile/run authority stack, one spatial context/group coordinator, two scoped navigation surfaces and a standalone bootstrap. Networking ownership remains in the persistent application root; stages must not duplicate it. Four pads, portal and boss positions are measured against the actual terrain. The enabled first-stage scene path and GUID must match the saved manual scene and stage sequence. Setup repairs build references through Editor APIs; preserve the manual scene GUID. **Mandatory execution order:** S → initial D → 0 → task 1 reproduction → 2 → task 1 correction → 3 → 4 → T → 5 → 6–10 → final D instrumentation/11. Do not launch combat/navigation fixtures against the partially wired replacement and mistake missing setup for an AI defect. Recheck the actual scene path/unsaved edits at execution; the user may continue terrain work or rename it before then. Use the **writing-plans** and **initialize-ai-navigation** workflows at execution. Scene setup uses supported Editor operations. The setup-only installer preserves user-authored terrain, art, obstacles and lighting; measure pads, bounds and navigation from the actual map. ## Task S: First establish the hand-authored stage infrastructure **Files:** Create `Assets/_Project/Editor/HandAuthoredStageSetup.cs`, `HandAuthoredStageValidation.cs`, `Tests/EditMode/HandAuthoredStageBindingTests.cs` and focused stage-load PlayMode fixtures. Inspect/modify only needed binding helpers in `Editor/HandAuthoredStageSetup.cs`/`PrototypeFoundationBuilder.cs`, `Features/Runs/StageSpatialDefinition.cs`, `StageSpatialContext.cs`, `StageSequenceDefinition.cs`, and the actual stage-sequence/spatial assets. Edit the replacement scene, build-scene configuration and scene-owned objects through Editor APIs, not YAML text. **Interfaces:** `HandAuthoredStageSetup.ConfigureActiveScene()` creates/repairs only setup-owned infrastructure and validates the target project/scene before mutation. `HandAuthoredStageValidation.ValidateActiveScene(out string report)` returns false with missing-reference diagnostics, never generates geometry or starts a run as repair. Both operations must be safe to repeat without duplicate NetworkObjects, callbacks or prefabs. - [x] Inventory scene/prefab bindings, build profiles, main-menu persistent objects, stage-sequence asset and all old scene/GUID references. Preserve the hand-built terrain hierarchy, meshes, ProBuilder data, materials, colliders, manual lighting and unsaved edits; record the before-state and a reversible setup-only delta. Unrelated scenes must not be required for setup or validation. - [x] Red tests for absent manager/session/spatial/nav bindings, duplicate authorities, missing player/network prefabs, deleted scene GUIDs, mismatch between scene name and stage assets, invalid pads/bounds/portal/boss locations and repeat setup. Audit `EnemyGroupCoordinator.sceneName`, `StageSpatialDefinition.sceneName`, stage sequence and enabled build scenes against the replacement's actual identity. - [x] Wire exactly one authority owner at runtime. Normal menu → stage loading reuses the established session/player/NGO lifecycle; do not add a second persistent manager. Provide the supported standalone practice bootstrap separately. Validate player movement, camera/input, combat/vitals/loadout, session/HUD bindings, settings, revive, run rewards/results, ground pickup/portal ownership, enemy and projectile materials/network prefab registrations. Existing director/service objects are inspected/repaired rather than duplicated. - [x] Add the scene's StageSpatialContext and dedicated spatial definition; measure envelope from actual playable terrain/elevations with deliberate safety margins, choose four grounded capsule-clear pads, portal position, boss position and any retained development region data on this map. Author explicit map-owned dynamic spawn limits/radius for task 0; obsolete coordinates are not defaults. Mark debug/visual proxies non-navigation geometry. - [x] Bind both normal and large NavMeshSurfaces to the intended hand terrain/obstacles and proper agent IDs. Exclude player/enemy/trigger/effect geometry from baking. Validate physics layers, solid colliders, walkable slopes/steps, height alignment and bounds with generated gap links disabled. Bake only with current user-authored geometry; terrain edits later require a fresh bake/validation, not regeneration. - [x] Verify repeat setup is idempotent, normal main-menu hosting/joining loads this scene, all four accepted spawn pads work, player controllers do not correct onto obsolete terrain, supported enemy samples resolve, ground cores/portal/checkpoints/revive function, late join/rehost cleans up, and no missing-reference/null initialization errors occur. Run focused tests and a fresh setup checkpoint build before implementing pack mechanics. **Deliverable:** The hand-built map can safely host the existing game loop; subsequent defects can be investigated against valid infrastructure. ## Task D: Read-only in-game AI debug mode **Files:** Create `Features/Enemies/Debug/EnemyAIDebugSettings.cs`, `EnemyAIDebugOverlay.cs`, `EnemyAIDebugSnapshot.cs`, `Editor/EnemyAIDebugInspector.cs`, and `Tests/EditMode/EnemyAIDebugTests.cs`; add bounded snapshot readers in existing `EnemyNavigationDiagnostics`, group coordinator/rules and actor state code as needed. UI Toolkit for controls; pooled lines/world labels for geometry. **Contract:** Debug is off by default. A development-only **F8** toggle opens a compact panel with independent Paths, Groups, States, Perception, Spawns and Combat switches; F8 must be checked against existing input bindings before authoring. Read diagnostics, never issue orders or improve AI visibility/path budgets. Host local state is authoritative. Remote debug may show normally replicated information; it must clearly label unsupported host-only fields rather than fabricate paths or add omniscient production replication. - [ ] Render selected/all enemy path corners, destination/remaining distance, pending/invalid/partial path, NavMesh agent type and traversal links; use distinct group colours, member links, spawn/gathering circles and moving centre. Show current actual state name, target, group ID and `(TargetId, Lifetime)`, HP/tier/archetype/faction, windup/recovery and per-member grace countdown. - [ ] Separate perceived player position/last real sighting and observation age from hidden-player navigation guidance. Show personal sight/firing clearance, blocked attack/movement reason, ranged exclusion rings, hold/reposition lease, status controls, lag/recovery reason, denied path-query budget and current spawn rejection reasons. Include specialist state (Keeper recipients, Lancer commitment/reservation, Bulwark generator, split lineage/reservations) as those slices land. - [ ] Create a bounded snapshot at proposed 5 Hz, with pooled visuals and a selected-enemy detail view; initially support the existing cap of 17 actors and cull distant labels. Lines/labels have no colliders, do not bake into NavMesh and cannot be hit by weapons. No console spam or per-frame reflection/hierarchy/material allocation. Use line styles/icons/text as well as colour. - [ ] Tests assert toggling/debug reads leave RNG, damage, state deadlines, paths, spawn admission and authority unchanged; inactive mode releases visual work, despawn/recycled IDs/stage change clear labels, and unavailable fields are truthful. Verify UI scaling/readability, play/build input, dense paths and incremental pack/specialist instrumentation. - [ ] Inspect actual paths/groups/states in solo-host Play Mode and a development build; document toggles, metrics and performance. Production defaults remain disabled; no public server-control/debug RPCs are added. **Deliverable:** A practical, non-interfering view of what each enemy knows, intends and is currently doing. ## Task T: Tracer damage, wavy flight and terrain collision **Files:** `Features/Enemies/EnemyDefinition.cs`, `EnemyAttackTuning.cs`, `EnemyProjectileService.cs`, `EnemyProjectileTrackingRules.cs`, `EnemyProjectileCollision.cs`, authored Ranged Drone definition through Editor APIs; create `EnemyProjectileWaveRules.cs`, `Tests/EditMode/EnemyTracerRevisionTests.cs`, `Tests/PlayMode/EnemyTracerCollisionTests.cs`. Extend captured projectile launch data only where deterministic wave/presentation settings require it. **Confirmed scope:** Existing enemy tracer/ordinary tracking bolts, including elite versions of that weapon. Reduce the owning weapon's **base damage by 40%**, currently **10 → 6**, once. Retain the separate normal 0.7 damage multiplier: normal stage-one raw bolt damage becomes **4.2**, and the existing elite 1.5 outgoing multiplier gives **9** before player defenses; stage scaling remains applied once. Do not multiply an already reduced damage value again. Lancer precision shots, bombardier shells, bosses, player guns and melee are not this weapon family. **Wavy path proposal:** Add deterministic angular wobble/jitter to authoritative travel, not just its trail. Initial editable tuning: sine amplitude **8 degrees at 2 Hz**, small smoothly interpolated seeded jitter **2 degrees at 7 Hz**. Capture a seed, launch time and validated wave parameters per bolt; never use frame-by-frame random draws. Apply the final desired direction through one steering budget so normal bolts remain **8 m/s and at most 60 degrees/s total turn**, including both target tracking and wiggle. Homing still lasts the normal full flight; elite speed/turn/tracking-window settings remain separate. No positional offset that makes actual speed exceed its setting. Validate finite values and use bounded substeps so hitches cannot skip players or obstacles, or change the wave materially. Clients reconstruct or receive the host path; existing curved trails, bright core and impact sparks stay. Proposed numbers are adjustable, not user-fixed. **Corrected collision contract — user clarification, 9 October:** Enemy tracers must stop at terrain and solid obstacles, including cover and props. The previous pass-through requirement is revoked. Sweep the actual bounded flight segment for the nearest eligible solid world contact or scoped living player; world contact ends the projectile without damaging a player behind it and produces a real impact at the obstacle. Ignore enemies, triggers and ineligible player shapes. Initial overlaps and saturated query buffers must not conceal a nearer obstacle or player. A player contact applies captured damage once and ends the flight. Preserve initial personal sight, facing, range and safe-muzzle requirements, plus CoverGrace cancellation of unlaunched attacks. Launched tracers survive source death and lost sight until their first collision or captured lifetime expiry. Shells, bosses and player-shot collision remain unchanged. **Collision method:** retain the host-owned bounded flight simulation. Check an initial sphere overlap, then sweep the bolt radius across the full travelled segment. Overlap alone can miss a thin obstacle crossed between sampled positions; a sweep alone can miss an initial overlap. Rigidbody collision callbacks with continuous detection are a valid alternative but would change the existing movement/lifetime/pooling architecture. See [Unity SphereCast behavior](https://docs.unity3d.com/6000.6/Documentation/ScriptReference/Physics.SphereCast.html). - [x] Red tests for base 10→6, normal 4.2/elite 9 before defenses at stage one, unchanged excluded families, no double scaling and captured damage after shooter despawn. - [x] Red deterministic wave tests: same seed/time/settings across frame rates and substeps, finite degenerate directions, normal speed magnitude 8, total steering ≤60 deg/s, tracking-window/tier behavior and bounded pool/reset/late-flight corrections. - [x] Restore world-blocking tracer collision under the corrected contract. Test terrain/cover before and after a player, initial world/player overlaps, multiple players/child colliders, ignored triggers/enemies/dead or foreign players, high-speed/hitch sweeps and saturated buffers. Choose the nearest valid obstacle or player; apply damage only to the first player contact. - [x] Author damage and validated wave settings through supported asset operations. Receive the authoritative path; extend presentation metadata only where needed for family, captured expiry and simulation end time. Validate IDs/timestamps/late join and preserve ownership checks. - [x] Verify actual wave motion/terrain obstruction and one damage event for an unobstructed player hit in host/remote builds, cover after launch versus before launch, normal/elite fire, source/target death, 128-slot pressure and stage/rehost cleanup. Compare deterministic path snapshots and rendered trails under existing simulated delay/jitter/loss; human dodge/readability remains acceptance work. **Deliverable:** Lower-damage enemy tracers visibly weave, maintain bounded movement, and stop on terrain and obstacles while their firing AI still respects sight/grace. **9 October user correction:** terrain/obstacle pass-through was an incorrect specification. Restore nearest-solid collision and cover absorption; prior pass-through tests/live results are historical evidence of the revoked behavior, not acceptance. Damage/wave and presentation repairs remain in scope. **9 October accepted implementation checkpoint:** corrected terrain/obstacle absorption, base6/normal4.2/elite9 and bounded wave are implemented. Native54, tracer rules18 and protocol12 pass; fresh full suites1085 EditMode/119 PlayMode. Protocol11 source identity is preserved. Bounded post-clock client presentation and local post-birth sparks repair measured hitch failures. Normal/debug/release builds0errors; matching tracer10phases,0/75real client stalls, warm close normal/elite, correlated16-flight latejoin, two/four arena11reports each, menu10phases and full-stage23phases pass with cleanup. Three final perspectives include actual wall-stop/spark/curve/latejoin render inspection. Human dodge/readability, exact gameplay HUD, representative hardware and separate-network acceptance remain unverified;128 host-cost evidence does not imply exhaustive client RPC coverage. See `Docs/TRACER_REVISION_VALIDATION.md`. **Task5 execution order:**5A1 immutable natural-admission receipts →5A2 passive arrival observer →5B opt-in owner motor input → five-cell natural-arrival campaign. Three independent design checks are reconciled in `Docs/PACK_ARRIVAL_VALIDATION.md`. The campaign adds no balance, cadence, UI or roster changes; measured navigation defects are repaired under separately reviewed contracts, and existing five-second defaults are persisted as required by Task5. - [x] **5A1 — Passive admission receipts:** immutable bounded provenance/owner proof, exact registration identities, failure isolation and explicit receipt coverage. Full1111 EditMode/128 PlayMode, zero-error builds, release exclusion and matching four-player arena/full-stage regressions pass. - [x] **5A2 — Passive arrival observer:** bounded neutral frame/transition/progress/contact/control/budget evidence, schema3 circle exports and immutable actual player/HUD captures. Full 1,160 EditMode/155 PlayMode, zero-error normal/debug/release builds and release exclusion pass. Genuine normal-menu trace supports eight Natural admissions, two personal witnesses and two fully admitted contact cohorts; missing final-member route evidence remains explicitly incomplete. Four-player default-off arena 11 reports/stage 12 phases pass. This verifies the observer foundation; five-cell qualification and arrival readability remain open. See `Docs/PACK_ARRIVAL_VALIDATION.md`. - [x] **5B — Opt-in owner motor input:** bounded scoped production movement input, lifecycle clearing and focused/manual precedence; reviewed remote-validation prerequisite conserves host-funded credit and preserves committed idle poses. Full1,238 EditMode/184 PlayMode, zero-error normal/debug/release builds, release exclusion, strict two/four-owner movement, both-size warp settlement, four-player default-off arena and23-phase stage progression pass. Three independent final perspectives approve the bounded foundation. The separate five-cell Natural-arrival campaign remains pending; see `Docs/PACK_ARRIVAL_VALIDATION.md`. ## Design contract ### Confirmed behavior - Merge Explore and Search into **Advance**. AcquireTarget remains a short decision step; rename Pursue to **Engage** to describe role-specific combat rather than constant pursuit. Preserve Windup, Attack, Recover and Dead. - Give each pack updated guidance toward a living player's general area, including while that player is hidden. This is intentionally a host-known navigation hint, not a sighting, attack target or aim solution. - A moving gathering circle follows a valid approach route. Members cohere around its centre, separate locally and navigate individually. The circle is soft: members may leave it to bypass cover, ramps and narrow passages. Never teleport or push actors through terrain to enforce cohesion. - Slow/pause the centre when members lag, but never wait indefinitely for a missing, dead, controlled or unreachable member. - When one member actually sees a player, relay the observed position and its original timestamp to the pack and switch its intent to Engage. Crawlers approach; ranged members seek useful firing lanes or hold and shoot. Combat loosens formation. - A shared Engage intent does not authorize attacks. Each actor must pass personal visibility, facing, distance, cooldown, status and firing-clearance checks. Hidden-player guidance never enters perception memory or projectile aim. - When the last member loses sight of the engaged player, each enemy holds position and watches the last sighting for its own authored **cover grace duration**. Add `EnemyDefinition.coverGraceSeconds`, default **5 seconds**, so future berserkers can have low/zero grace and snipers high grace. The duration belongs to the enemy archetype, not the group definition. Block firing through cover; that enemy cannot start a fresh chase, lunge or approach until its own grace expires. - A new genuine sighting by any member cancels members' grace and resumes engagement. The next group sight loss starts each member's full authored duration; sound, damage alerts, shared-memory imports and updated guidance cannot reset it. Preserve group contact sharing: this amendment changes each member's waiting duration, not the requirement that the last group member must lose sight to begin waiting. - Each member independently returns to Advance when its own deadline expires. A low-grace enemy may advance while a high-grace teammate remains stationary. The moving circle and cohesion must not drag holding members forward; holding members do not count as laggards and cannot indefinitely block advancing peers. Target death/disconnection invalidates the target immediately, bypassing grace. - Preserve priority for stun, root, death and immediate personally visible melee opportunities. A player walking into melee range can be attacked; this exception must not start an unseen lunge or chase. - Allow multiple ranged members to Advance simultaneously. One-at-a-time ranged repositioning remains a combat tactic, not an ingress restriction. ### Proposed initial tuning and scope The per-enemy configurable grace and its five-second default are user-fixed. The following formation/guidance defaults are starting points for measurement, not human-approved balance: | Setting | Initial value | Purpose | |---|---:|---| | Per-enemy cover grace | **5.0 s default** | `EnemyDefinition.coverGraceSeconds`; finite 0–60 s, zero means immediate Advance, invalid values fall back to 5 s | | Player-area guidance refresh | 1.0 s | Avoid frame-by-frame hidden tracking | | Guidance cell width | 8 m | Quantized area destination; no exact hidden aim | | Gathering radius, crawlers / ranged | 5 m / 6 m | Loose small-pack cohesion | | Centre speed | 0.65 × slowest eligible member's base speed | Deliberate approach, avoiding constant member sprinting | | Lag pause / resume distance | 2 × radius / 1.5 × radius | Hysteresis rather than rapid stop/start | | Lag wait before bypassing a blocker | 3 s | A single stuck member cannot halt the pack forever | | Guidance-target commitment | 4 s | Prevent nearest-player oscillation in co-op | | Combat target commitment | Existing 2 s | Preserve current observed-target policy initially | Tasks 0–5 preserve existing homogeneous cohorts (3–5 crawlers or 2–3 ranged), admission cadence, population caps, tier/weapon tuning and stage progression as the pack baseline. Tasks 6–11 deliberately add the four selected archetypes and bounded mixed composition profiles after that checkpoint. Runtime must support different grace values within one pack without waiting for its slowest member. Scope pack coordination to Verdant initially; keep legacy arenas/development baseline as comparison fixtures. Ordinary ungrouped actors use Advance with a single-member intent and their own definition's grace after personal sight loss. Bosses retain their current encounter/ability behavior; do not force them into ordinary pack formation. Lancer is now explicitly in scope; unrelated berserker/flyer/summoner types are excluded. ## Dynamic group spawn-circle amendment **User direction:** Ordinary groups select a fresh valid circle on the current map, rather than repeatedly choosing from predefined encounter regions. Members spawn at randomly selected valid points within that circle. The map owns the permitted distance limits. This replaces predefined-region selection for the new spawning path; authored boss entry remains separate. **Confirmed distance rule:** Each final spawn point is outside the map-specific minimum distance from **every living player**, and within the map-specific maximum distance of **at least one living player**. At least one player inside that maximum must have a valid approach route. No specific distance values were supplied; use proposed editable map defaults below pending actual tuning. ### Proposed spawn contract - Add finite authored `enemySpawnMinimumDistance`, `enemySpawnMaximumDistance`, and `enemySpawnCircleRadius` to `StageSpatialDefinition`, with `0 <= minimum < maximum` and a positive radius compatible with the annulus. These settings belong to each map, not each enemy or pack. Actual values must be selected during map tuning; they are not inherited silently from legacy hardcoded limits. - Proposed initial Verdant tuning: **20 m minimum, 60 m maximum, 6 m spawn-circle radius**. These are plan proposals, not user-selected final balance or changes to the existing scene. Legacy comparison arenas retain their existing rules unless deliberately opted into dynamic spawning with their own explicit values. - Choose centre candidates dynamically around living players using the map's minimum/maximum interval, active stage bounds and supported connected ground. Use horizontal X/Z distance consistently for the distance ring; require separate ground, height/agent-type and route checks so proximity across an unreachable shelf does not admit a spawn. - Store one accepted circle `(centre, radius)` per group admission lifetime. Choose member points uniformly across its disk (`radius * sqrt(random01)` and random angle), not a fixed formation or circumference. The spawn circle is an admission footprint; it is separate from the moving formation circle, which initializes from the admitted cohort and subsequently advances. - Validate sampled positions after NavMesh projection: still inside the chosen disk, inside active stage bounds, on the correct normal/elite mesh, capsule-clear, separated from already admitted enemies, and compliant with the current map distance rule. Reject projections onto the wrong disconnected surface. - Preserve ranged actor separation of at least the existing six-metre exclusion plus spawn buffer, even if map minimum is smaller. Check minimum separation against every living player's current host-accepted position before each admission, rather than only when the circle was selected. - Retain ordinary spawn visibility/cover rejection against all living players, including tier-scaled top height. A disk can intersect invalid terrain or visible ground; every admitted point must be valid. Do not require every geometric point in the circle to be spawnable, but preflight enough valid separated slots for the desired cohort and its actual admission agent types to avoid choosing a near-empty footprint. - Validate a legal approach toward a living player, including ranged spacing along the route, not merely NavMesh reachability to the player's centre. Respect the existing bounded path budget; selection failures defer admission rather than relaxing visibility, distance or geometry checks. - Recheck slots at admission time because players and enemies move. If a selected circle becomes unusable, bounded attempts may replace its footprint before any member is admitted. Once members exist, retry within that footprint or close that admission and start a fresh group at a future budget interval; never teleport/reassign already spawned members to a new distant circle. - Preserve current per-interval spawn throughput, caps and progressive cohort admission. “Group spawn circle” does not authorize an instantaneous whole-pack burst or spawn backlog. No-valid-circle results consume bounded work and retry on the normal spawn schedule. - Use a separate seeded spawn RNG for circle/member sampling so comparison tests can replay admitted circles without tactical RNG draws changing them. Random dynamic candidates provide variety; do not promise that valid terrain cannot repeat or add a permanent exclusion history that starves small maps. - Remove predefined ordinary regions from the new group's reservation and route contracts. `TryGetRoute` must obtain its approach reference from the dynamic admission/formation centre, not an obsolete region index. Preserve old region data only for explicitly retained legacy/baseline fixtures; document its consumers and remove unused wiring once migrated. ### Additional ownership and proposed interfaces Paths are relative to `Assets/_Project/`: - Modify `Features/Runs/StageSpatialDefinition.cs`: per-map spawn limits/radius and fail-closed validation for the new spawn mode. - Create `Features/Enemies/Encounters/EnemySpawnCircleRules.cs`: `EnemySpawnCircle` immutable centre/radius data and pure disk/distance validation/sampling. - Create `Features/Enemies/Encounters/EnemySpawnCircleSelector.cs`: bounded host centre/slot selection, ground/visibility/clearance/agent-type and approach-route checks. - Modify `Features/Enemies/Encounters/PrototypeEncounterDirector.cs`: dynamic ordinary admission while preserving pacing, tier selection, population and boss contracts. - Modify `Features/Enemies/Coordination/EnemyGroupRules.cs` / `EnemyGroupCoordinator.cs`: reserve a group ID/desired count and footprint without a predefined region index; roles remain stable. - Modify `Editor/HandAuthoredStageSetup.cs` and per-map spatial assets through supported Editor operations: author explicit spawn settings, preserve manual arena content and asset GUIDs. - Create `Tests/EditMode/EnemySpawnCircleTests.cs`, `Tests/PlayMode/EnemySpawnCircleAdmissionTests.cs`; extend planned `Editor/PackAdvanceLiveValidation.cs` with actual ordinary circle admissions. Interfaces planned for implementation review: - `bool EnemySpawnCircleRules.AllowsPoint(Vector3 point, EnemySpawnCircle circle, Vector3[] livingPlayerPositions, float minimumDistance, float maximumDistance)` — finite input, disk and confirmed player-reference checks; no physics. - `Vector3 EnemySpawnCircleRules.SamplePoint(EnemySpawnCircle circle, float radial01, float angle01)` — uniform-area X/Z candidate, later validated after projection. - `bool EnemySpawnCircleSelector.TrySelect(StageSpatialDefinition stage, EnemyDefinition enemy, bool elite, int desiredCount, double now, out EnemySpawnCircle circle)` — bounded host preflight, false for invalid/missing bindings or insufficient legal slots. - `bool EnemySpawnCircleSelector.TryMemberPoint(EnemySpawnCircle circle, EnemyDefinition enemy, bool elite, out Vector3 point)` — rechecks current host players/world at actual admission. - Replace `TryReserveSpawn(..., out Bounds region)` with a reviewed identity/footprint contract; no silent fixed-region fallback in the dynamic mode. Store circles under the same lifetime/run/stage cleanup guarantees as group intent. ### Task 0: Dynamic map-configured group admission Execute before the arrival/formation slices. The lead owns director/group/spatial integration; no concurrent writer owns those files. Apply the repository's three-perspective implementation gate and final diff review here as for the other substantial tasks. - [x] Author explicit per-map minimum/maximum/radius using proposed Verdant 20/60/6 m as a measured starting point; keep those values inspectable/editable, without hiding global distance constants in gameplay code. - [x] Red tests for minimum/maximum boundaries, exclusion from every living player and maximum proximity to at least one reachable player, disk containment after NavMesh projection, uniform-area sampling, nonfinite settings, correct normal/elite meshes, unreachable elevations and capsule/occupancy rejection. Minimum is exclusive (distance must be greater than minimum); maximum is inclusive (distance may equal maximum). - [x] Red lifecycle/admission tests for stable per-group circle, fresh circles on new reservations, moving-player invalidation, empty valid-slot sets, exhausted query budget, admission timeout and stage/rehost cleanup. Verify failure creates no ghost members, multiplied throughput or accumulated spawn burst. - [x] Implement pure disk rules, bounded selector and dynamic director/group reservation. Update `TryGetRoute` and formation initialization to use the accepted dynamic centre. Audit `EnemyGroupCoordinator.Active` so dynamic groups do not require a nonempty predefined-region array. - [x] Author map settings through Editor APIs, migrate only participating ordinary spawn paths, and remove unused predefined-region consumers from the dynamic path. Preserve boss and explicit comparison fixtures. - [ ] Run actual ordinary hidden spawn cohorts across map positions/elevations and clustered/split two/four players. Record circle candidates, accepted centre/radius/member positions, rejection reasons, path queries and arrival progress; compare repetition and no-valid-circle rates. - [ ] Include circle spawn acceptance in task 5's final build/network cohorts, with preserved population/cadence and cleanup assertions. Inspect actual arrival visibility and variety; random selection alone is not a human-approved improvement claim. **Deliverable:** Groups reserve fresh valid map-distance-constrained circles and admit randomized safe members within them, ready for the Advance/Engage design. **9 October admission checkpoint:** the manual stage opts into 20/60/6 through supported Editor authoring; legacy fixtures and authored boss entries retain their separate paths. Slot preflight is progressive under the shared eight-query budget, actual admission revalidates all current players and geometry, and group credit follows successful network/navigation registration. Native four-player testing exposed occupied-pad ordering and repeatedly discarding known valid preflight samples. The repaired selector retains shuffled uniform samples, consumes them only after registration, and resumes deferred member route cursors without increasing work or admission throughput. Focused spawn rules are **68/68**; the separate ninth-query starvation and truthful distance-evidence cases retain RED logs. Cached distance counts preserve evidence when a later mesh trial changes the latest rejection. Full current rules are **914/914**, including **44 pure warp-state cases not yet integrated into players**, and PlayMode **18/18**. Final built two/four-player replay and normal-run acceptance are recorded in `Docs/DEBUG_TEST_ARENA.md`; arrival behavior remains owned by tasks 1–5. ## Global constraints (applies to all slices) - Host authority over pack intent, player-area sampling, navigation, contact, timers, status and attacks. Clients render replicated motion and existing cues; no client-owned decisions. - Preserve all-player **6 m** ranged movement exclusion, complete-path checks, accepted player positions and actual-step veto. Guidance and cohesion cannot override these. - Reuse membership identity `(TargetId, Lifetime)` and stable roles; never key lifetime-sensitive records by recyclable network ID alone. - Preserve immutable observation age and personal firing permission. Existing full-flight bolt behavior remains unchanged. - Respect current per-frame path budgets, bounded member/group counts and staggered think cadence; no unbounded queues or allocations per frame. - Keep new guidance/contact/navigation data transient. No save migration or unnecessary network payload; authored tuning changes through supported Editor APIs, preserving GUIDs and manual scene content. Task T may add the captured projectile seed/wave settings required for deterministic flight; task D introduces no production debug-control RPC or omniscient replication. - No paid generation, production 3D assets, package upgrades, commits or pushes are implied. Tasks 6–11 authorize the four planned primitive prototypes and bounded composition changes only when implementation is requested. Preserve authored arena content. ## Review focus 1. All members behind different cover: one remaining sighting prevents grace; imported stale evidence never fakes visibility. Different member durations expire independently, including zero and high values. Owned by task 2/4 tests. 2. Narrow bridges, separated NavMesh islands and vertically stacked routes: circles must use connected route distance where horizontal distance is misleading. Owned by task 3 live route checks. 3. Players split or change elevation: stable reachable guidance selection, preserving all-player spacing and immediate invalid-target release. Owned by task 2/3 tests. 4. Rooted/dead/stuck member: centre does not wait indefinitely, controls are respected and lifetimes clean up. Owned by task 2/3/5 tests. 5. Sight lost during windup/burst/lunge: grace cannot be bypassed by an existing execution runtime, yet launched projectiles retain established behavior. Owned by task 4 tests. ## Evidence and responsible paths - `PrototypeEnemy.Update` applies ranged navigation before its roughly 0.15-second brain tick, which runs `AIAcquire` before the current state. - `PrototypeEnemy.FindTarget` currently releases reposition permission whenever it returns no perceived target. `AIExplore` may return with an existing path before reacquiring; `ApplyRangedNavigationServer` then clears an unleased path. Actual authored group-rule execution confirmed cancellation/peer delay, not the user's full live encounter. - `EnemyTacticalCoordinator.Choose` limits grouped selection to two candidates; failure returns the current position, rejected by `TryRangedDestination`. Geometry-dependent repeated failure remains unverified. - `DefaultEnemyStates` holds the current action transitions. `EnemyGroupRules` owns membership, observation age, target commitment, reposition fairness and path budget. `EnemyGroupCoordinator` binds those rules to scene/host actors. - `AIMove` contains firing holds. `TickLungeServer`, `TickShellBurstServer` and `TickRangedBurstServer` run before ordinary brain ticking, so changing transitions alone will not implement grace correctly. ## File ownership and proposed interfaces All paths below are relative to `Assets/_Project/` unless otherwise stated. One implementer owns shared files per slice; reviewers are read-only. Signatures below are planned interfaces, not current APIs. | File | Responsibility | |---|---| | Modify `Features/Enemies/Coordination/EnemyGroupDefinition.cs` | Validated authored guidance/cohesion defaults; no group-wide grace duration | | Modify `Features/Enemies/EnemyDefinition.cs` | `coverGraceSeconds = 5f`; validated per-archetype duration | | Modify `Features/Enemies/Coordination/EnemyGroupRules.cs` | Stable pack target, actual visual reports, phase/timer snapshots; preserve existing membership/budget rules | | Modify `Features/Enemies/Coordination/EnemyGroupCoordinator.cs` | Host guidance sampling and bounded route/circle updates, per-member intent lookup | | Create `Features/Enemies/Coordination/EnemyPackIntent.cs` | `EnemyPackPhase` enum (`Advance`, `Engage`, `CoverGrace`) and immutable snapshot | | Create `Features/Enemies/Coordination/EnemyPackAdvanceRules.cs` | Pure cohesion/lag/slot calculations, finite-input validation | | Create `Features/Enemies/Movement/EnemyPackNavigation.cs` | Per-group/per-agent-type validated centre paths and member goals; no actor teleportation | | Modify `Features/Enemies/PrototypeEnemy.cs` | Route Advance/Engage, actual visibility reports, grace gates, lifecycle cleanup and movement permissions | | Modify `Features/Enemies/Brains/DefaultEnemyStates.cs` | Advance/Engage action states, CoverGrace action state and existing attack transitions | | Modify `Features/Enemies/Coordination/EnemyTacticalCoordinator.cs` | Engage selection remains; bounded alternate candidate progress on failure | | Modify `Features/Enemies/Movement/EnemyNavigationDiagnostics.cs` | Pack phase/centre/target, stopped reason and path/permission evidence | | Modify `Editor/HandAuthoredStageSetup.cs` | Author tuning without resetting manual content; only if existing wiring needs extension | | Modify relevant existing EditMode fixtures; create focused pack fixtures | Preserve legacy proofs and add the new contract | | Create `Editor/PackAdvanceLiveValidation.cs` | Bounded diagnostic host scenarios and cleanup evidence | Snapshot: `EnemyPackIntent` contains `uint GroupId`, `EnemyPackPhase Phase`, `ulong TargetOwner`, `ulong GuidanceOwner`, `Vector3 GuidanceArea`, `Vector3 Center`, `Vector3 LastObservedPosition`, `double LastVisualAt`, `double GraceUntil`, `int Role`, `bool HasObservation`, `bool HasGuidance`. `TargetOwner` always identifies actual contact associated with the observation fields; a changed guidance owner never relabels that history. Owner zero is valid: use the availability flags. Unavailable cached fields are not usable goals or observations. Observation history may remain after grace expires. `Phase` and `GraceUntil` are resolved for the requesting member, not copied from one group-wide waiting deadline. The group retains contact/evidence and a common last-sighting time; members retain their separately resolved grace durations. `GuidanceArea` and `LastObservedPosition` remain separate. `Center` is supported seed/storage until task3 moves it. `AllowsAdvance` expresses coordination eligibility only; valid goals, native paths, living targets and status constraints remain separate. Task2 snapshots do not rename the actual FSM or grant attacks; actor integration is task4. Rule interfaces: - `bool SetGuidance(uint groupId, ulong targetOwner, Vector3 area, double now)` — navigation input only; rejects invalid/unreserved group, time or position. - `void ReportVisual(ulong id, uint lifetime, ulong targetOwner, Vector3 observed, bool visible, double now)` — actual current actor visibility; false clears that actor's visual flag, not the group's evidence. - `void SetMemberCoverGrace(ulong id, uint lifetime, float seconds)` — stores validated per-member tuning after registration; finite 0–60 s, invalid values resolve to 5 s. Capture the resolved duration for each loss episode, so an in-progress wait cannot slide indefinitely when authored tuning changes. - `bool TryPackIntent(ulong id, uint lifetime, double now, out EnemyPackIntent intent)` — evaluates member phase/deadline from group contact and that member's captured duration, preserving the real observation timestamp. - `bool UpdateCenter(uint groupId, Vector3 supportedCenter, double now)` — writes only validated host route output. - `bool AllowsAdvance(ulong id, uint lifetime, double now)` — independent of the combat reposition lease. - `Vector3 EnemyPackAdvanceRules.MemberGoal(Vector3 center, int role, ulong identity, float radius)` — stable loose slot, later sampled/validated on that member's mesh. - `float EnemyPackAdvanceRules.CenterSpeed(float baseSpeed, float lagDistance, float radius, bool waiting)` — bounded speed/hysteresis input from navigation runtime. - `bool EnemyGroupCoordinator.TryGetPackIntent(PrototypeEnemy enemy, double now, out EnemyPackIntent intent)`. - `bool EnemyPackNavigation.TryStepCenter(uint groupId, int agentType, Vector3 from, Vector3 guidance, float speed, float deltaTime, out Vector3 next)` — complete connected path, budget admission and per-frame movement limit. - `bool EnemyPackNavigation.TryMemberGoal(PrototypeEnemy enemy, EnemyPackIntent intent, out Vector3 goal)` — supports actual member agent type and all-player ranged route constraints. - `PrototypeEnemy.AIAdvance()`, `AIEngage()`, `AIHoldCoverGrace()`, and `bool CanStartApproachAttack(double now)` — preserve personal attack checks and suppress grace-period lunges. Keep movement eligibility separate from action state IDs so an active Recover/Windup cannot accidentally evade CoverGrace. Exact navigation storage layout may be refined by implementation reviews; no duplicate writers or speculative broad refactor. ## Task 1: Prove and correct the stationary-ingress permission conflict **Files:** `PrototypeEnemy.cs`, `EnemyGroupCoordinator.cs`, `Tests/EditMode/EnemyGroupTests.cs`; create `Tests/PlayMode/RangedIngressPermissionTests.cs` and its Editor-managed meta. **Interfaces:** Existing permission methods plus planned `AllowsAdvance` from task 2; first establish the current failure without relying on renamed states. **Dependency:** Run task 1's failure reproduction before task 2. Complete its permission correction after task 2 implements `AllowsAdvance`, before task 3 integrates moving formation. - [x] Add `RangedIngress_NoPerceivedTarget_DoesNotClearActiveAdvancePath`: real host actor, valid path, no personal visual/memory, living guidance target; traverse at least two brain ticks and assert useful displacement and retained movement authorization. Confirm the current call order fails for the traced reason, not missing setup. - [x] Add two/three-member variants, denied-path-budget retry and target death cleanup; capture state/permission/path at each boundary. - [x] Apply the smallest permission correction: no-target acquisition must not revoke active ingress permission; simultaneous Advance permission is independent of combat reposition leases. Preserve explicit stop/death/control cancellation. - [x] Run focused EditMode/PlayMode tests through connected Unity Test Runner; retain red/green logs in `TestResults/pack-advance-*`. Reviewers compare actual paths and permissions, not source-text assertions. **Deliverable:** Purposeful existing ingress no longer loses a valid route solely because no combat target was perceived. ## Task 2: Host pack guidance, shared contact and per-enemy grace rules **Files:** `EnemyDefinition.cs`, `EnemyGroupDefinition.cs`, `EnemyPackIntent.cs`, `EnemyGroupRules.cs`, `EnemyGroupCoordinator.cs`; create `Tests/EditMode/EnemyPackIntentTests.cs`. **Interfaces:** Implement the snapshot and guidance/visual/intent/advance interfaces above. Existing `Observe` continues importing evidence without turning it into a visual report. - [x] Red tests: `Guidance_DoesNotGrantObservationOrAttackTarget`; `AnyActualVisual_SetsEngageForEveryMember`; `LastMemberLosesSight_HoldsUntilFiveSeconds`; `PeerStillSeesTarget_DoesNotStartGrace`; `Peek_RearmsFullGraceOnNextLoss`; `SoundHitAndBorrowedEvidence_DoNotRenewGrace`; `DisconnectedTarget_InvalidatesImmediately`; `RecycledMember_DoesNotKeepVisualFlag`. - [x] Add red tests `MemberGrace_DefaultIsFiveSeconds`, `MixedGrace_ExpiresIndependently`, `ZeroGrace_AdvancesImmediately`, `HighGrace_KeepsHoldingWithoutBlockingPeers`, `InvalidGrace_UsesFiniteDefault`, `RecycledMember_DoesNotInheritGrace`, and `TuningChange_DoesNotSlideActiveDeadline`. Use test-only 0 / 0.25 / 5 / 15 s values, not newly authored enemy types. - [x] Define the timer precisely: retain the group's last actual positive visual sample time; each member's deadline is `LastVisualAt + capturedMemberCoverGraceSeconds`. The default remains CoverGrace at +4.999 and enters Advance at +5.0; a 0.25 s member advances at +0.25 while a 15 s peer holds until +15.0. At zero, skip CoverGrace. Clear visual reports and member timers on target change, disable, death, prune and despawn; an absent actor must not keep an eternal visual flag. On registration set that actor's definition-derived duration before evaluating its intent; a member joining an existing loss episode uses its own duration and the existing episode time. Actual actor visibility sampling remains task4, at the existing think cadence with at most one-tick detection uncertainty. - [x] Select a reachable living guidance target from host-accepted positions with commitment; refresh quantized guidance every second. A changed guidance cell never renews combat evidence. Personal immediate threats may still override an actor's attack target without causing pack target oscillation. - [x] Implement default validation, finite clocks/coordinates, fixed-size member flags and lifetime-safe cleanup. Clear both phases/timers and centre caches on travel, rehost and coordinator shutdown. - [x] Run focused rule tests and existing group/memory/lifetime/target-commitment fixtures; review all exact boundary values. **Deliverable:** Deterministic shared contact with independently configurable member waiting and a five-second default. ## Task 3: Moving soft circle and dependable terrain navigation **9 October implementation decision:** retain a deterministic largest-footprint canonical route and separately supported native-type anchors; never average different mesh routes through terrain. Clamp unbanked centre steps to0.05s, project typed anchors within2m and reject elevation differences above0.5m. Cached route-lag measurements are usable for0.5s; a denied refresh is unknown rather than unreachable and cannot slide an existing three-second wait. A bypassed blocker cannot rearm that episode until it catches up below the resume threshold. Stable admission slots are separate from combat roles modulo three. Arrival requires an accepted complete own route, actual endpoint distance and finite remaining distance both≤0.35m, with no pending/invalid path. These are bounded implementation tolerances, subject to measured native terrain failures; no surface rebuild or terrain generation is authorised by them. Pure1032 rules pass; six native contracts are recorded RED before runtime work. **Files:** `EnemyPackAdvanceRules.cs`, `EnemyPackNavigation.cs`, `EnemyGroupCoordinator.cs`, `EnemyTacticalCoordinator.cs`, `EnemyNavigationDiagnostics.cs`; create `Tests/EditMode/EnemyPackAdvanceTests.cs` and focused PlayMode path fixtures. **Native corrective evidence:** the original six path contracts pass after terminal native route revocation publishes `isStopped` last. Two actual-visible tactical regressions reproduced safe-path cancellation under denial and a successful-tactic deadline being armed for unfinished masked candidates; both now pass. The ten-case publication RED records eight passes and two genuine speed failures: a0.11375m deferred centre proposal was published against current allowances0.02276m and0.011385m after a member slowed. Publication now consumes cached canonical and independently proved typed corner prefixes using current speed/current elapsed, preserving unused proof without extra queries. No native path, host clock or budget counter is fabricated. Final current-map/pressure/render and actual clustered/split four-player acceptance pass (see Docs/PACK_ADVANCE_VALIDATION.md); these corrections do not claim task4 actor contact or attack grace. **Interfaces:** Implement centre stepping/member-goal/cohesion methods above. Consume task 2 snapshots and existing budget admission, complete-path checks and ranged safety routines. - [x] Red tests for stable separated member goals, speed bounds, lag pause/resume hysteresis, bounded three-second lag release, finite input rejection, lifetime cleanup and simultaneous ranged Advance eligibility. - [x] Move the virtual centre along a connected NavMesh route, with per-agent-type caches when normal/elite members require different navigation sizes. Clamp movement by speed and elapsed time; never linearly move through an obstacle between route points. After contact loss pause the centre while all members hold; resume when an eligible member enters Advance. CoverGrace members keep their own positions, receive no cohesion pull and are excluded from lag-wait calculations until their deadlines expire. (Native movement/phase eligibility implemented; actual actor contact/attack integration remains task4.) - [x] Sample and validate loose member slots individually; use agent avoidance/local separation. Route-distance lag governs waiting across bends/elevation; skip dead/controlled members and give unreachable laggards independent recovery after the bounded wait. (Native current-map/lag pressure acceptance remains below.) - [x] Use bounded progressing alternate candidates on route failure, rather than retrying the same two frozen angles forever. A budget-denied query retries without discarding an already valid safe path. Reject illegal routes without teleport/direct-player fallback. - [x] Validate actual hand-authored Verdant terrain, cover, stairs, slopes, shelves, connections and player-area cells across elevations, using task S's new measured bindings. Test both agent sizes and all-player six-metre exclusion with split players. Any future bridge requires fresh route proof after authoring. (Current-map native inventory/16-actor pressure and actual clustered/split four-player gates pass; natural selector arrival remains Task0/5.) - [x] Capture centre/member paths, separation, lag/stopped reasons and denied work; verify no unbounded allocations or query budget expansion. (Bounded measured Advance calls, fixed caches, eight-query cap, dense/selected F8 render and neutral-read proof; representative hardware performance remains human acceptance.) **Deliverable:** Cohesive multi-member arrivals around actual terrain, with bounded recovery instead of indefinite aimless holds. ## Task 4: Integrate Advance/Engage/CoverGrace with all attack runtimes **9 October implementation decision (before code):** retain existing group timer rules and add scheduled real positive/negative actor contact sampling before navigation publication, special attack updates and control returns. Retire the previously reported owner before switching; memory/sound/damage/guidance never report sight. Resolve per-member intent every frame; CoverGrace clears all melee/ranged queued paths and pending native motion, releases leases/reservations and watches the last real observation. Ordinary Advance consumes typed member routes even with memory-only targets; Engage keeps existing personal attack checks and tactical holds. Absent coordination uses a lifetime-bound single-member episode; explicit baseline mode is cached from the scene coordinator at spawn, rather than inferred from `Active == null`. Boss/custom behavior remains explicit and unknown custom state IDs are not forced. Queued windup/burst/shell and forward moving lunge stop on hidden grace; launched projectiles/effects remain paid and retain flight. Personally visible in-reach melee can strike stationary without new approach/lunge. Cancel existing preparation cues narrowly by interpreting nonpositive duration on the existing `WindupRpc` as cancellation before charge audio/animation work, with `CancelPreparation` preserving recoil/hit/trail timers. No new RPC/schema, F8 controls, audio/art or tracer tuning. Three independent reviews support this boundary; native tests must exercise production Update ordering, mixed0.25/15s grace, control/target/owner lifecycle and every attack path. Implementation now passes default FSM/fallback/cue/native lifecycle proof and real two-owner stationary melee RED/GREEN. See Docs/PACK_ACTIONS_VALIDATION.md for final full-suite/build and remaining network/human boundaries. **Files:** `DefaultEnemyStates.cs`, `PrototypeEnemy.cs`, `EnemyTacticalCoordinator.cs`, `EnemyNavigationDiagnostics.cs`; update existing explore/search/state tests and create `Tests/PlayMode/EnemyCoverGraceTests.cs`. **Interfaces:** Implement actor methods above and planned state IDs. Unspawned/unregistered normal actors use a single-member intent; bosses/legacy comparison retain explicit compatible behavior. Audit custom `EnemyBehaviorDefinition` registration rather than assuming every brain is the default. - [x] Red transition tests: Explore/Search replacement, memory-only Advance, peer-triggered Engage, sight-loss grace from Engage/Windup/Recover, +4.999/+5.0 boundary and reacquisition. Grace is evaluated before new approach/lunge decisions, not only inside an action state's Tick. - [x] Implement Advance with task 3 member routes and simultaneous ingress. Engage uses personal perception plus shared last-observed evidence, loosened formation, existing firing holds and fair single-member combat repositioning. - [x] On a member's CoverGrace entry clear its queued approach path and release its reposition lease; watch last observation. Freeze the centre only while no eligible member is advancing; high-grace peers cannot veto expired members' movement. Repeated ticks must not slide holding actors forward, restart their timers or overwrite their duration with another member's. Keep root/stun priority; controlled-member expiry cannot block others permanently. - [x] Exercise ordinary bolt windup/burst, crawler lunge and bombardier shell paths. Cancel unlaunched hidden-target attacks and stop forward lunge motion on contact loss; do not recall already launched projectiles or alter full-flight tracking. A personally visible player inside melee reach may be hit without a new approach/lunge. - [x] Assert guidance/peer sightings never grant personal fire; muzzle obstruction, rear-facing targets and all-player spacing remain enforced. During grace, no fresh attack toward a hidden player; when a valid target reappears normal checks resume. - [x] Remove obsolete runtime uses of spawn-hint/search helpers only after call-site/fixture audit. Preserve legacy fixtures behind explicit comparison behavior where needed, not dangling missing states. Update current/proposed graph documentation with accurate runtime overlays. - [x] Run focused state, perception, search/explore replacements, combat, status, projectile and spacing suites through the Editor; inspect console and actual animations/path motion. **Deliverable:** Full player-facing Advance/Engage/cover loop, including special-runtime paths that could bypass the grace. ## Task 5: Integrated validation, authored tuning and acceptance evidence **10 October continuation:** genuine five-cell observation exposed a production formation-goal height deadlock on stairs. The bounded terrain-support repair is implemented; recorded Normal/Large ordinary-brain movement tests and13 support safety cases pass. Fresh1277EditMode/194PlayMode, three zero-error builds/release exclusion and matching10menu/10arena gameplay plus failure-proof and lifecycle/23full-stage network checks pass. The linked15-attempt campaign records34captures and zero sustained-stall warnings; four-player clustered meets Normal/Large coverage, while four cells remain incomplete under their exhausted original attempt caps. Naturally observed16 pressure and full visual/human acceptance remain unverified. Earlier centre-prefix, owner-life and actual-camera repairs remain in the combined diff. The completed older13-attempt campaign and its39captures are retained as failure evidence; its coverage labels do not close movement acceptance. Current manual scene and rebaked NavMeshes are preserved. The subsequent user-requested automated-first continuation records one fourth attempt per incomplete case, at most180active seconds within original720cumulative. It adds10captures/zero sustained-stall or mechanical failures/no Large selection, retaining19attempts/44reviewed frames overall. Four coverage gaps and human acceptance remain open; bounded automated work is ready for manual playtests. See `Docs/PACK_ARRIVAL_VALIDATION.md`. **Files:** `Editor/PackAdvanceLiveValidation.cs`, existing `Editor/VerdantGroupComparisonValidation.cs` only for reusable metrics; tuning asset through Editor APIs; `Tools/Test-EncounterPolish.ps1` if assertions need extension; `Docs/PROJECT_PLAN.md`, `Docs/VERDANT_GROUP_DECISIONS.md`, new `Docs/PACK_ADVANCE_VALIDATION.md`. - [x] Before Editor mutations, verify connection, project path, pinned version, active scene and play state. Preserve manual scenes/assets and all prior uncommitted work. Run the three independent implementation perspectives at the slice gate with compact evidence/file ownership; reconcile decisions without a majority vote. - [x] Author `coverGraceSeconds = 5` on each existing ordinary enemy definition through supported asset operations, plus proposed group guidance/formation defaults; preserve GUIDs. Verify existing definitions missing the new serialized field resolve to 5 s and explicitly authored zero stays zero. Do not rebuild the entire arena; four new archetypes are added separately in tasks 6–10. - [ ] Run real unseen ordinary spawn arrival tests, not just manually placed visible actors. Measure first contact, time stationary without contact, progress around occluders, pack radius/separation, alternate-route successes and grace actual actor displacement. Require reachable cohorts to progress without repeated permission cancellation. - [ ] Cover scenarios: all members lose sight; only one loses sight; peek before five seconds; peek at expiry; player exits another side; player approaches melee range; target dies/disconnects; actor rooted/stunned during grace; stale shared report; zero living players. Add a test-only pack with 0.25 s and 15 s members: first advances while second stays stationary without being dragged by cohesion, then both immediately Engage on any new actual sighting. Assert per-member timer/phase/motion/fire separately. - [ ] Run solo/two/four-player cohorts, clustered and split, normal/elite sizes, 16-enemy pressure, control/AoE and single-target builds. Check that tighter packs do not silently imply accepted balance; record damage/attack overlap and five-second cover camping effects. - [x] Run full relevant EditMode/PlayMode suites, Windows prototype build and matching-build two/four-player delayed/lossy encounter/main-menu/travel/rehost checks using the existing configured services and tools. Record actual commands, build identity, counts, failures and cleanup. No success inferred solely from API returns. Newest stair-goal runtime gates pass1277EditMode/194PlayMode, three builds,10menu phases,10arena gameplay reports plus intentional failure proof/three lifecycle checks and23full-stage phases. - [ ] Final independent technical/gameplay/UX reviews inspect the actual diff, runtime captures and evidence; retest only affected corrections. Render normal player views to assess formation/readability, not just debug circles. - [x] Update plan status, decisions and validation report. Report automated, Editor, network and human checks separately. Human moving-player pack feel, cover grace balance and separate-network acceptance remain unverified until actually played. **Deliverable:** Reviewable integrated behavior with test/build/network evidence and explicit remaining human acceptance. ## Roster expansion contract ### Scope, identity and prototype art Add **Tether Keeper, Lancer, Bulwark and Splinterbeast** as ordinary host-controlled archetypes. The user's corrected visual request includes **Hollow Knights, Riftborn and Scrap Seraphs** versions of the same four roles. These are faction appearance variants, not twelve independently balanced AI types. Keep one shared behavior/tuning contract per role, selectable primitive presentation variants, and readable role names. The first playable pass uses only Unity cubes, capsules, spheres, cylinders, simple shared materials and existing effect tools, similar to the crawler. No generated production meshes, Meshy jobs, paid assets, skeletal-animation requirement or mass arena rebuild. Concept art is a target, not executable geometry or collision proof. Task 6 creates the four gameplay prefabs with Hollow Knights primitive visuals and prepares the equivalent Riftborn/Seraph primitive variants; task 11 exposes faction selection in encounter authoring without multiplying admissions. All variants retain the same gameplay capsule, head/body hitboxes, shield-generator location and Scan anchors for their archetype. Decorative plates/relays have no blocking colliders. Primitive generator geometry is the only additional gameplay hitbox for Bulwark. Use native Editor operations, independent visual roots and preserved existing GUIDs. New prefabs/assets receive their own GUIDs. Normal/elite palettes remain distinguishable in every faction through silhouette cues as well as colour. Proposed initial tuning (author editable assets; values are measurement defaults, not supplied by the user): | Archetype | HP / movement | Attack or special | Cover grace / role | |---|---|---|---| | Tether Keeper | 160 HP / 3 m/s | Protect up to 2 eligible nearby allies within 12 m; 30% damage reduction; no weapon in first pass | 5 s / ranged movement family | | Lancer | 120 HP / 3 m/s | 20-damage direct precision shot, range 6–40 m; 1.2 s charge, final 0.2 s aim commitment; 3.5 s start-to-start cooldown | 5 s / ranged movement family | | Bulwark | 300 HP / 2.5 m/s | 18-damage melee, 2 m range, 0.6 s windup, 2 s cooldown; shield frontal half-angle 60 degrees; 40-HP generator; 4 s broken recovery | 5 s / melee movement family | | Splinterbeast | Parent 160 HP / 3 m/s; child 40 HP / 4 m/s | Parent 15 / child 8 melee damage; 2 / 1.5 m reach; 0.6 / 0.35 s windup; 1.8 / 1.2 s cooldown; one split into 2 children | 5 s / melee movement family | Do not inherit crawler lunge, normal tracking-bolt modifiers or bombardier behavior accidentally. Lancer's attack is a separate straight precision shot, not an 8 m/s tracking bolt. Existing ordinary bolts remain **8 m/s, 60 degrees/s**, full flight, with their current effects. Tier health/damage/resistance scaling uses the existing profile once; special durations/limits do not grow with elite tier unless explicitly authored later. Existing large-agent navigation applies to elite variants; new normal actors require actual capsule and route proof before selecting a bake type. ### Counterplay and bounded composition - **Keeper:** Visible tethers identify protected allies and the vulnerable source. Require actual source-to-ally line of sight and range, same living hostile team/run/stage, and lifetime-safe identities. Reject self, Keepers, bosses and allies already claimed by another Keeper; retain at most two stable recipients. Protection never stacks with another Keeper. Combine with existing Guard through the stronger reduction, then apply tier resistance once; do not heal, grant immunity or refresh health. Stun, death, despawn, stage exit, out-of-range and solid occlusion remove protection before the next damage application. Root stops motion but does not independently cancel a valid tether. During CoverGrace retain only existing valid links, acquire none; disable all links outside an active combat phase. No hidden-player guidance becomes attack evidence. - **Lancer:** Show a charge sound, muzzle cue and thin non-damaging aim line from actual muzzle. Track a personally visible player during charge; commit a normalized direction for the final 0.2 s. Recheck living target, source, stage, range and actual visibility/cover at release; failure cancels without damage. Fire against the world at the committed direction, hitting the nearest eligible player once and respecting cover; never snap the shot to the player's new position. Stun/contact-loss grace cancels unlaunched shots. Introduce a small **Lancer-only** reservation: at most one charging Lancer per intended player, expires on cancellation/death/disconnect/stage cleanup, and denies a fresh charge rather than queuing a synchronized volley. This does not add global attack permits to ordinary enemies. - **Bulwark:** Front-facing direct weapon hits encounter an attached shield with exposed generator; side/back hits remain ordinary body damage. The generator can be damaged by any equipped primary, uses normal noncritical weapon damage and does not trigger body Scan consumption, bleed or on-hit chains. A successful generator break opens the shield for 4 s and cancels a current melee windup; reopening restores generator once, not every frame. Stun opens shield while stunned; Repulse/push and root/slow retain existing tier rules. Scan places normal temporary body points, including reachable side/back positions, but does not bypass the shield. Pierce cannot bypass a closed shield; a shield/generator stops the shot. Ability/AoE and secondary damage use ordinary body resistance and Guard, without extra directional blocking. Use the host's verified ray/hitbox impact provenance for shield interception: current `DamageContext` has hit point but no trusted incident direction, so source-player position alone is not sufficient for ricochets/secondary hits. Preserve body damage accounting and resolved overkill/proc rules. - **Splinterbeast:** Only a genuine combat-lethal parent spawns children; never split on despawn, fall recovery, disconnect, boss cleanup or stage transition. Exactly one generation: children cannot split and inherit the parent's faction/tier and captured stage scaling once. Retire the parent's population reservation before admitting children, then atomically reserve valid child slots within the existing cap. At cap, admit at most available slots; no deferred children/backlog. Each admitted child needs correct mesh, capsule clearance, grounded stage-contained position and a reachable route; otherwise omit it. Children receive fresh IDs/lifetimes and join the surviving pack without renewing shared observation timestamps or cover deadlines. Parent gives the existing single kill/loot roll and normal lethal procs; children can receive/trigger ordinary hit/death combat effects with distinct attack IDs but grant **no wave-goal credit, no elite-progression credit and no core drop**. Record child kills separately in telemetry so displayed wave progress stays truthful. Do not suppress body damage or manufacture reward health. First acceptance profile: one Keeper plus two ordinary ranged actors (three members). Second: one Lancer plus two ranged actors. Third: one Bulwark plus two crawlers. Introduce one Splinterbeast in a later composition. Preserve baseline homogeneous profiles and existing cadence, 16-wave/17-with-boss capacity, 40-kill goal and early-stage multipliers; tracer damage/path/world-collision changes are the explicit task T exception to previous weapon tuning. Proposed limits: one Keeper per pack, two live Keepers and two live Lancers globally. Keep profile selection authored; do not equate four-player mode with four times as many specialists. Dynamic spawn preflight must admit mixed role/size capsules within one disk and enforce the six-metre ranged rules per member. Unsupported mixed profiles fail closed without a fixed-region fallback. ## Task 6: Archetype contracts and primitive prototype foundation **Files:** Modify `Features/Enemies/EnemyDefinition.cs`, `PrototypeEnemy.cs` and `Editor/PrototypeEnemyBuilder.cs` only at reviewed integration hooks. Create `EnemyArchetype.cs`, `EnemySpecialDefinition.cs`, `EnemySpecialRuntime.cs`, `Editor/EnemyRosterPrototypeBuilder.cs`, and `Tests/EditMode/EnemyArchetypeTests.cs`. New definitions/components/prefabs live in `Features/Enemies/Authoring/Roster/`; presentation variants in `Features/Enemies/Presentation/Roster/`. All paths here are relative to `Assets/_Project/`. **Interfaces:** `EnemyArchetype` uses explicit stable values `Standard=0, TetherKeeper=1, Lancer=2, Bulwark=3, Splinterbeast=4, SplinterChild=5`; keep existing `EnemyRole` as navigation family. Optional `EnemyDefinition.special` references an abstract `EnemySpecialDefinition` with typed per-role definitions in tasks 7–10. `EnemySpecialRuntime.BindServer(PrototypeEnemy owner)`, `bool TryBeginAttackServer(PrototypePlayerVitals target, double now)`, `void TickServer(double now)`, `void CancelServer()` and `void ClearServer()` provide lifecycle/action hooks. Non-special actors retain their existing code path. Unknown/mismatched special bindings cannot launch ordinary attacks as fallback. Define readonly `EnemyIdentity` in `EnemyArchetype.cs` with `ulong TargetId`, `uint Lifetime` and value equality/hash semantics; it wraps existing networking identity. Define presentation-only `EnemyFaction` values `HollowKnights=0, Riftborn=1, ScrapSeraphs=2`; validate host-selected values, replicate at spawn and default existing actors to zero. Typed tuning assets remain separate from faction presentation. - [ ] Review shared-file ownership and source contracts; write failing tests for legacy null-special compatibility, explicit enum/typed binding validation, normal/elite scaling once, special attack dispatch and cancellation/death/travel/rehost cleanup. - [ ] Implement the small dispatch/lifecycle hooks without rewriting `PrototypeEnemy` or introducing a general ability framework; call cancellation ahead of attack execution when group grace/status forbids it. - [ ] Build four primitive-only prefabs and one SplinterChild through Editor APIs with correctly sized normal/elite agents, native health bars and separate body/head/Scan hitboxes. Build faction visual roots from the design packet, sharing the same gameplay root. Prototype boxes on concepts are recipes, not automatically imported meshes. - [ ] Register each gameplay prefab once with NGO; serialize faction identity on host spawn so late join sees the correct presentation. Add pooled, shadow-limited role cues rather than per-frame hierarchy searches/material allocations. Reuse existing elite palette/dissolve hooks. - [ ] Run focused tests; inspect front/side/rear silhouettes, shield generator/body separation, tether nodes, muzzle and parent/child sizes in the actual Editor. Record readable output and unverified art fit. **Deliverable:** Repeatable authoring creates inspectable primitive archetypes without changing the existing roster or arena layout. ## Task 7: Tether Keeper protection and source lifetime **Files:** Create `TetherKeeperDefinition.cs`, `TetherKeeperRuntime.cs`, `EnemyTetherRules.cs`, `EnemyTetherPresentation.cs`, `Tests/EditMode/EnemyTetherTests.cs`, `Tests/PlayMode/TetherKeeperLifetimeTests.cs`; modify `PrototypeEnemy.cs` damage resolution and only the required Guard integration. **Interfaces:** `bool EnemyTetherRules.CanBind(EnemyIdentity source, EnemyIdentity recipient, float distance, bool clear, bool eligible)` validates host candidates. `float EnemyTetherRules.ResolveGuard(float existingGuard, float keeperGuard)` selects the stronger validated reduction. `TetherKeeperRuntime.TickServer(double now)` maintains up to two records, and `ClearServer()` synchronously removes source-owned records. Identity is `(TargetId, Lifetime)`; presentation replicates only bounded accepted connections and never grants damage protection. - [ ] Red tests: two-recipient bound, self/Keeper/boss rejection, range/cover boundaries, no stacked reductions, existing Guard interaction, recycled IDs and removal before same-frame damage; assert 100 raw normal damage becomes 70 with only the proposed Keeper protection. - [ ] Implement deterministic recipient retention and budgeted 0.2 s candidate scans; damage application revalidates claimed links so stale scan data cannot protect through fresh occlusion or source death. - [ ] Integrate visible source/recipient tethers and all existing resistance/status/Scan/proc accounting; assert root versus stun and CoverGrace behavior separately. - [ ] Verify actual solo/co-op source death, target despawn, travel, late join and rehost. Run focused tests and inspect linked allies/source vulnerability from a normal player camera. **Deliverable:** Players can identify and remove bounded ally protection without immunity cycles or orphaned buffs. ## Task 8: Lancer charge, committed shot and reservation **Files:** Create `LancerDefinition.cs`, `LancerAttackState.cs`, `LancerRuntime.cs`, `LancerChargeCoordinator.cs`, `LancerPresentation.cs`, `Tests/EditMode/LancerAttackTests.cs`, `Tests/PlayMode/LancerAttackAuthorityTests.cs`; extend special action hooks only. **Interfaces:** `bool LancerChargeCoordinator.TryReserve(EnemyIdentity source, ulong targetOwner, double now, double expiry)`, `void Release(EnemyIdentity source)` and `void Clear()` bound overlapping charges. `LancerAttackState.Begin(ulong targetOwner, double now, Vector3 origin, Vector3 direction)` and `bool TryCommit(double now, Vector3 visibleDirection, out Vector3 committedDirection)` capture aim once; `bool TryRelease(double now, out Vector3 committedDirection)` releases at most once. Host runtime supplies typed settings, performs actual visibility/world-hit checks and cancels on invalid input. - [ ] Red tests: 1.0 s commitment/1.2 s release boundaries, immutable committed aim, one damage event, cover/facing/range/target-loss rejection, root/stun/grace transitions, reservation contention, expiry and recycled source IDs. - [ ] Implement the host charge/shot path and its bounded reservation; no target-position update after commitment and no post-cover burst. Use existing nearest-hit/collision conventions for direct player damage. - [ ] Author warmup/commit/fire/cancel effects distinguishable from ordinary bolts across all three factions; late join sees current charge age rather than a fresh full charge. - [ ] Run actual sideways dodge and cover tests at 6/12/24/40 m plus two/four-player split targets. Inspect overlap fairness, muzzle obstruction and delayed/lossy cues; record human dodge acceptance separately. **Deliverable:** A readable precision threat with a reliable committed dodge window and bounded coordinated pressure. ## Task 9: Bulwark shield and generator **Files:** Create `BulwarkDefinition.cs`, `BulwarkShieldState.cs`, `BulwarkRuntime.cs`, `BulwarkShieldHitbox.cs`, `BulwarkPresentation.cs`, `Tests/EditMode/BulwarkShieldTests.cs`, `Tests/PlayMode/BulwarkHitboxTests.cs`. Modify `Features/Combat/HitscanWeaponDefinition.cs`/`DamageHitbox.cs` and `PrototypeEnemy` only where actual host impact provenance/shield interception requires it. **Interfaces:** `bool BulwarkShieldState.BlocksDirectWeapon(Vector3 verifiedIncidentDirection, Vector3 shieldForward, double now)` evaluates the frontal contract; `bool DamageGeneratorServer(float resolvedWeaponDamage, double now)` breaks once; `void SetStunned(bool stunned, double now)` suppresses closed state. Shield query results explicitly distinguish Blocked/Generator/Body; only Body enters ordinary health/proc accounting. Review exact incident-direction plumbing before code because existing damage context lacks it. - [ ] Red tests at ±59.9/±60/±60.1 degrees: boundary is blocked at ≤60 when closed; verify generator 39/40 damage, four-second reopen, no body leakage/duplicate proc, rear hits and once-only break. - [ ] Implement grounded shield orientation with bounded facing; prevent melee/lunge dispatch inheritance and do not use moving shield colliders to push players or fling them off islands. Shield affects weapon queries, not terrain navigation. - [ ] Test every primary including shotgun/pierce, Scan exposed points behind shield, secondary/ability/AoE damage, Repulse, root/stun and elite resistance. Keep actual-health numbers and overkill accounting truthful. - [ ] Inspect real front/side/rear hitboxes and generator aimability at different distances; validate simultaneous peers breaking/hitting at recovery boundaries, late join, cover grace, travel and pool cleanup. **Deliverable:** A directional defender with universal weapon counterplay and explicit ability interactions. ## Task 10: Splinterbeast population-safe split **Files:** Create `SplinterbeastDefinition.cs`, `SplinterbeastRuntime.cs`, `EnemySplitRules.cs`, `EnemySplitReservation.cs`, `Tests/EditMode/EnemySplitTests.cs`, `Tests/PlayMode/SplinterbeastLifecycleTests.cs`; modify `PrototypeEncounterDirector.cs`, `PrototypeRunDirector.cs`, `PrototypeEnemy.cs` and `EnemyGroupRules.cs` at bounded death/admission/reward hooks. Shared files have one implementer for the whole slice. **Interfaces:** `bool EnemySplitRules.ShouldSplit(bool isParent, bool genuineCombatLethal, bool stageActive)`; `int EnemySplitRules.AdmissibleChildren(int capacity, int occupiedAfterParentRelease)` returns 0–2. `int EnemySplitReservation.TrySpawnChildrenServer(PrototypeEnemy parent, DamageResult lethal, double now)` is at-most-once for the parent lifetime. `EnemyKillCreditPolicy` distinguishes ordinary parent credit from reward-free split descendants, without changing ordinary enemies. - [ ] Red tests: one parent becomes at most two children, children never split, concurrent parent lethals at cap, invalid terrain and suppressed cleanup deaths, recycled IDs, tier/stage scaling once, no ghost reservations and no child backlog. - [ ] Release parent population before bounded child reservation, validate each local point/route against current players/stage and perform explicit network prefab spawning. Keep pending spawned children in the director's occupancy count before another parent can split. - [ ] Preserve faction/tier/current pack observation identity without creating a new sighting or resetting grace; independently validate immediate melee opportunities. Protect legal spawn clearance even when parent dies beside players. - [ ] Add explicit parent/child kill-credit and telemetry policy: one wave/elite-progress/core-roll event per parent; no such events for children; legitimate child damage and ordinary finite on-hit/on-kill combat effects still work. No recursive secondary attack chains or invented damage/reward attribution. - [ ] Run real normal/elite deaths with single-target/AoE/bleed/secondary kills, boss-arrival retention, boss defeat cleanup and stage/rehost. Compare population, wave progress, rewards and proc events to expected counts across two/four players. **Deliverable:** A finite splitting threat that rewards crowd control while respecting population, progression and lifecycle limits. ## Task 11: Composition, faction prototypes and full acceptance **Files:** Create `EnemyCompositionDefinition.cs`, `Tests/EditMode/EnemyCompositionTests.cs`, `Editor/EnemyRosterLiveValidation.cs`, `Docs/ENEMY_ROSTER_VALIDATION.md`; modify director/group authoring and relevant `Tools/Test-EncounterPolish.ps1` checks. Update this plan's to-do log and `Docs/PROJECT_PLAN.md` as each slice is proven. - [ ] Author the bounded profiles above, preserve homogeneous comparison packs, and bind all three primitive faction variants. Add failing tests for mixed-role slot preflight, per-agent routes, specialist caps, slowest eligible formation speed and grace differences without admission throughput growth. - [ ] Verify dynamic-circle hidden arrivals for each archetype/faction, actual stage slopes/steps/bridges and narrow cover. No teleporting, floating proxies on invalid ground or grace-driven dragging. Include split players and new child admissions at the wave/boss boundary. - [ ] Inspect actual rendered Advance, Engage, cover grace, Keeper link/cancel, Lancer charge/commit/fire, Bulwark block/break/reopen, split/death/cleanup and late join. Show both isolated shapes and the full player combat view; concepts alone do not satisfy this step. - [ ] Run focused then full relevant EditMode/PlayMode suites, fresh Windows build, matching-build delayed/lossy two/four-player runs including main menu, combat, checkpoint rewards, travel, defeat and clean rehost. Record failures and corrections rather than treating command success as gameplay evidence. - [ ] Run final independent technical/gameplay/UX reviews against the integrated diff and measured results. Lead owns shared-file integration; reviewers remain read-only. Retest affected fixes, update validation/remaining manual acceptance, and stop without unrelated refactors. **Deliverable:** All four archetypes playable as simple primitive prototypes in bounded pack compositions, with evidence and explicit human/performance limitations. ## Proposed state graph ```mermaid stateDiagram-v2 [*] --> AcquireTarget AcquireTarget --> Advance: Guidance, no actual group contact AcquireTarget --> Engage: Actual group contact Advance --> Engage: Any member sees player Engage --> CoverGrace: Last member loses sight CoverGrace --> Engage: Any member reacquires sight CoverGrace --> Advance: This enemy's grace expires, default 5 s Engage --> Windup: Personal attack checks pass Windup --> Attack: Due and personal checks still pass Attack --> Recover: Execution complete Recover --> Engage: Contact and cooldown ready Windup --> CoverGrace: Group contact lost; cancel hidden attack Recover --> CoverGrace: Group contact lost CoverGrace --> Advance: Target dies or disconnects state "Any living action" as Alive Alive --> Dead: Health reaches zero Dead --> [*]: Despawn ``` The graph summarizes one ordinary member's proposed actions. Group sightings are shared, but each member's phase/deadline remains authoritative while actors are in attack subruntimes; hidden burst/lunge cancellation and launched-projectile lifetime are specified in task 4. A zero-grace member goes directly from contact loss to Advance. AcquireTarget reselects a valid destination after an invalid target, and no-living-player runs stop actions. Guidance is continuously available, while actual contact determines attack eligibility. ## Plan self-review and execution handoff - Requirements map: replacement hand-authored scene/binding safety (S); AI paths/groups/states/diagnostics (D, extended in 2/3/6–11); tracer 40% base damage reduction/wavy flight/terrain collision (T/5/11); dynamic spawn circles/map-specific minimum-maximum/randomized members (0/5); merged states/always available area guidance (2/4); moving circle/cohesion/catch-up (3); contact sharing/personal fire (2/4); per-enemy grace with five-second default and independent expiry/reacquisition (2/3/4/5); simultaneous ingress/stationary bug (1/3/4); primitive faction silhouettes (6); Keeper/Lancer/Bulwark/Splinterbeast (7/8/9/10); terrain/four-player/lifecycle/composition proof (S/0/3/5/11). - No gameplay or dependency changes have been made by writing this plan. Numerical formation defaults remain proposals; current user-observed idling has code-level permission evidence but not a reproduced live cohort. - Recommended execution: lead implements bounded slices in this chat, with the repository-required three independent perspectives before each substantial slice and against integration. Use the latest explicit project model policy: gpt-6.1-sol with medium reasoning for complex reviews, gpt-6-luna with high reasoning for isolated lookup/mechanical work; report model unavailability before substitution. - Planning is complete when this document is saved and linked. Implementation begins only after the user requests execution; no planning-time reviewer agents, commits or pushes. ### Foundation checkpoint evidence — 8 October - Current S implementation/initial D and obsolete-level cleanup: **770/770 EditMode**, **18/18 PlayMode**; repeat setup and failed-setup Undo preservation pass without terrain changes. Local lab→manual stage checks reuse one authority and validate four accepted pads/two navigation sizes; local rehost clears old actors/groups. - Normal/debug/release builds: **0 errors**, respectively **543/640/716 warnings**; release packed assets exclude DebugTestArena and scenario authoring. Actual all-category F8 top/bottom captures and F7/F8 blocker/reset/exit flow pass at 720p125% and 1080p alongside existing lab resolution checks. - Matching-build normal-menu cohort: `TestResults/main-menu-8ad3facbfad04a5988d334d8e77b453f`, **10 phases**. Debug arena cohorts: `debug-arena-0f59dd50cfe1489babb39f2e6256a85d` (two) and `debug-arena-07e55febe5064c1a9df98405013f2f3f` (four), **18 reports each**, one deliberate expected failure each and zero cleanup failures; 75 ms endpoint delay/15 ms jitter/1% loss. - S final full-stage gate remains open: `encounter-polish-52b34a6a69354c2dbfb8400ac2f2d996` passed four two-peer combat phases then its hardcoded core-drop request was unsupported; both peers received the correct banked reward fallback, so no ground visual existed. Replace scripted drop/portal offsets with supported host layouts and rerun physical pickup/checkpoint/travel/revive assertions. Do not weaken production geometry, pickup or reward rules. - Initial D deliberately labels future pack/guidance/spawn/specialist fields uninstrumented; D remains open for later slices. Task0 red tests are separate upcoming work; no dynamic production admission yet. ### Setup acceptance closure The supported progression fixture is integrated and accepted. `stage-fixture-layout-red` **11 expected failures → 11/11 GREEN**; broader tests exposed and verified the illegal NavMeshPath initializer correction. `stage-fixture-full-green`: **781 passed, zero failed, 29 pending Task0 cases skipped**; `stage-fixture-full-playmode`: **18/18**. `Tools/Test-EncounterCommandAcknowledgement.ps1` executes the production helper against controlled stale/current reports and verifies both successful and refused acknowledgement outcomes. Fresh prototype **0 errors/543 warnings**. `Tools/Test-EncounterPolish.ps1 -VerdantInitial -DelayMs 75 -JitterMs 15 -LossPercent 1`: **23 phases passed** in `encounter-polish-7b46369be4644468b6e81e93e9bab51e`, including actual ground core appearance/removal, client refusal, stale drop refusal, four separated portal entrants, readiness removal on exit, forfeiture, rewards, two stage travels, support/revive, results and clean rehost. This supersedes the earlier unsupported-drop fixture failure; production reward/pickup/portal rules remain unchanged. Activate the pending Task0 fixture before implementing it; no dynamic admission/pack/tracer/roster implementation is claimed yet.