# Agent Test Spec: godot-csharp-specialist ## Agent Summary Domain: C# patterns in Godot 4, .NET idioms applied to Godot, [Export] attribute usage, signal delegates, and async/await patterns. Does NOT own: GDScript code (gdscript-specialist), GDExtension C/C++ bindings (gdextension-specialist). Model tier: Sonnet (default). No gate IDs assigned. --- ## Static Assertions (Structural) - [ ] `description:` field is present and domain-specific (references C# in Godot 4 / .NET patterns / signal delegates) - [ ] `allowed-tools:` list includes Read, Write, Edit, Bash, Glob, Grep - [ ] Model tier is Sonnet (default for specialists) - [ ] Agent definition does not claim authority over GDScript or GDExtension code --- ## Test Cases ### Case 1: In-domain request — appropriate output **Input:** "Create an export property for enemy health with validation that clamps it between 1 and 1000." **Expected behavior:** - Produces a C# property with `[Export]` attribute - Uses a backing field with a property getter/setter that clamps the value in the setter - Does NOT use a raw `[Export]` public field without validation - Follows Godot 4 C# naming conventions (PascalCase for properties, fields private with underscore prefix) - Includes XML doc comment on the property per coding standards ### Case 2: Out-of-domain request — redirects correctly **Input:** "Rewrite this enemy health system in GDScript." **Expected behavior:** - Does NOT produce GDScript code - Explicitly states that GDScript authoring belongs to `godot-gdscript-specialist` - Redirects the request to `godot-gdscript-specialist` - May note that the C# interface can be described so the gdscript-specialist knows the expected API shape ### Case 3: Async signal awaiting **Input:** "Wait for an animation to finish before transitioning game state using C# async." **Expected behavior:** - Produces a proper `async Task` pattern using `ToSignal()` to await a Godot signal - Uses `await ToSignal(animationPlayer, AnimationPlayer.SignalName.AnimationFinished)` - Does NOT use `Thread.Sleep()` or `Task.Delay()` as a polling substitute - Notes that the calling method must be `async` and that fire-and-forget `async void` is only acceptable for event handlers - Handles cancellation or timeout if the animation could fail to fire ### Case 4: Threading model conflict **Input:** "This C# code accesses a Godot Node from a background Task thread to update its position." **Expected behavior:** - Flags this as a race condition risk: Godot nodes are not thread-safe and must only be accessed from the main thread - Does NOT approve or implement the multi-threaded node access pattern - Provides the correct pattern: use `CallDeferred()`, `Callable.From().CallDeferred()`, or marshal back to the main thread via a thread-safe queue - Explains the distinction between Godot's main thread requirement and .NET's thread-agnostic types ### Case 5: Context pass — Godot 4.6 API correctness **Input:** Engine version context: Godot 4.6. Request: "Connect a signal using the new typed signal delegate pattern." **Expected behavior:** - Produces C# signal connection using the typed delegate pattern introduced in Godot 4 C# (`+=` operator on typed signal) - Checks the 4.6 context to confirm no breaking changes to the signal delegate API in 4.4, 4.5, or 4.6 - Does NOT use the old string-based `Connect("signal_name", callable)` pattern (deprecated in Godot 4 C#) - Produces code compatible with the project's pinned 4.6 version as documented in VERSION.md --- ## Protocol Compliance - [ ] Stays within declared domain (C# in Godot 4 — patterns, exports, signals, async) - [ ] Redirects GDScript requests to godot-gdscript-specialist - [ ] Redirects GDExtension requests to godot-gdextension-specialist - [ ] Returns C# code following Godot 4 conventions (not Unity MonoBehaviour patterns) - [ ] Flags multi-threaded Godot node access as unsafe and provides the correct pattern - [ ] Uses typed signal delegates — not deprecated string-based Connect() calls - [ ] Checks engine version reference for API changes before producing code --- ## Coverage Notes - Export property with validation (Case 1) should have a unit test verifying the clamp behavior - Threading conflict (Case 4) is safety-critical: the agent must identify and fix this without prompting - Async signal (Case 3) verifies the agent applies .NET idioms correctly within Godot's single-thread constraint