# Sprint 3d — Animation Intelligence (Synthesized Spec)

## What We're Building

Two new MCP tools for GodotIQ that give AI agents complete understanding of animations in Godot 4 projects:

1. **`godotiq_animation_info`** — Returns all animation data for a scene (inline, code-referenced, AnimationTree states)
2. **`godotiq_animation_audit`** — Finds animation problems (broken tracks, orphans, missing references)

## Why

No existing Godot MCP tool can answer "what animations exist?" or "what's broken?" — especially in 3D projects where most animations live inside GLB files and are referenced only through code patterns like `ANIM_MAP` dicts and `.play()` calls.

## Context

- GodotIQ MCP server, Python 3.10+, FastMCP API
- Sprint 3c complete: 371 tests, 11 tools
- Real project (Print Farm Tycoon): 78 scripts, 37 scenes, ZERO inline .tscn animations — all via GLB + code

## Animation Sources (4)

1. **Inline .tscn** — SubResource type="Animation" with resource_name, length, loop_mode, tracks
2. **Code-referenced (GLB)** — .play() calls, ANIM_MAP dicts, LOOPING_ANIMS arrays in .gd files
3. **.tres resources** — Standalone Animation files (same text format as .tscn sub_resources)
4. **AnimationTree state machines** — AnimationNodeStateMachine with states and transitions

## Key Decisions (from interview)

- **Fixture format:** Use real Godot serialization format (flat transitions array, not indexed)
- **.tres parsing:** Include in this sprint
- **Regex scope:** Aggressive — match any dict/array with "anim" in var name
- **Broken track validation:** Immediate scene nodes only (no resolver dependency)
- **Test fixtures:** New self-contained `tests/fixtures/anim_project/` directory

## Research Findings

- AnimationNodeStateMachine serializes as: `states/NAME/node = SubResource("id")` + `transitions = ["from", "to", SubResource("id"), ...]`
- AnimationNodeAnimation: `animation = &"name"` (StringName syntax)
- Our TSCN parser stores sub_resource properties as dict with string keys
- Existing tool pattern: private `_build_*()` helper + public `@mcp.tool()` async wrapper

## Constraints

- DO NOT modify existing parsers, tests, tools, or session.py
- No external dependencies
- Must not break existing 371 tests
