Good. Now I have all the context I need. Let me generate the section content.

# Section 01: Dataclasses and Helper Functions

## Overview

This section implements the foundation layer for the GDScript parser: all 9 dataclasses that define the parsed output model, all 7 helper functions used by the parser, module-level imports, logger setup, and pre-compiled regex patterns. This is the first section with no dependencies -- sections 02 (state machine) and 03 (body patterns) both build on top of it.

**File to modify:** `/Users/salvatorefarruggio/Desktop/godotiq/src/godotiq/parsers/gd_parser.py` (replace the existing stub)

No other files are created or modified in this section. The test file (`/Users/salvatorefarruggio/Desktop/godotiq/tests/test_parsers/test_gd_parser.py`) is created in section 04.

---

## Existing Stub and Backward Compatibility

The current file at `/Users/salvatorefarruggio/Desktop/godotiq/src/godotiq/parsers/gd_parser.py` contains a minimal stub with three dataclasses (`GdSignal`, `GdFunction`, `GdScript`) and a `parse_gd(content: str)` function that raises `NotImplementedError`.

Existing Sprint 0 tests import these symbols:

```python
# From tests/test_scaffolding_int.py line 90-94:
from godotiq.parsers.gd_parser import (
    GdSignal,
    GdFunction,
    GdScript,
    parse_gd,
)
```

```python
# From tests/test_server.py line 47-49:
def test_parse_gd_stub_raises(self) -> None:
    with pytest.raises(NotImplementedError):
        parse_gd("")
```

**Important:** The plan changes `parse_gd` from `parse_gd(content: str)` to `parse_gd(path: str, known_autoloads=None)`. The existing `test_parse_gd_stub_raises` test passes `""` and expects `NotImplementedError`. After section 02 implements the real function, calling `parse_gd("")` will raise `FileNotFoundError` (since `""` is not a valid file path), not `NotImplementedError`. That test will need updating -- but since section 02 handles the `parse_gd()` public function, this section only defines the dataclasses and helpers, leaving the existing `parse_gd` stub temporarily intact. Alternatively, if you replace the full file in this section, you should add a temporary `parse_gd` stub that still raises `NotImplementedError` as a placeholder until section 02 replaces it.

**Recommended approach for this section:** Replace the entire file content but keep `parse_gd` as a stub that raises `NotImplementedError` at the bottom. Section 02 will replace this stub with the real implementation.

---

## Tests for This Section

The following tests validate the dataclasses and helper functions in isolation. These tests should be written first (TDD). They will live in `/Users/salvatorefarruggio/Desktop/godotiq/tests/test_parsers/test_gd_parser.py` (created in section 04), but the test specifications are documented here so the implementer knows what the code must satisfy.

### Dataclass Default Value Tests

```python
class TestDataclassDefaults:
    """Verify all dataclasses instantiate with correct defaults."""

    # Test: GdSignal() → name="", args=[], line=0
    # Test: GdFunction() → name="", args=[], return_type="", is_static=False,
    #       is_virtual=False, is_private=False, line=0, end_line=0
    # Test: GdVariable() → name="", type_hint="", default_value="", is_const=False,
    #       is_static=False, annotation="", scope="class", line=0
    # Test: GdEnum() → name="", values={}, line=0
    # Test: GdSignalConnection() → signal_source="", target="", has_bind=False,
    #       bind_args="", line=0
    # Test: GdSignalEmission() → signal_name="", arg_count=0, line=0
    # Test: GdAutoloadRef() → autoload_name="", access="", pattern="", line=0
    # Test: GdPreloadRef() → path="", is_preload=True, line=0
    # Test: GdScript() → class_name="", extends="", all lists empty,
    #       is_instance_valid_lines=[]
```

### Dataclass Field Type Tests

```python
    # Test: GdSignal stores args as list[tuple[str, str]] — (name, type_hint) tuples
    # Test: GdFunction stores args as list[tuple[str, str, str]] — (name, type, default) triples
    # Test: GdFunction is_virtual and is_private both True for "_ready"
    # Test: GdVariable with annotation="@export" stores raw annotation text
    # Test: GdVariable is_const=True for const declarations
    # Test: GdVariable is_static=True for static var declarations
    # Test: GdEnum values dict maps str → int|None
```

### Helper Function Tests

```python
class TestStripComment:
    """Tests for _strip_comment helper."""

    # Test: "var speed: float = 5.0  # fast" → "var speed: float = 5.0"
    # Test: '# full line comment' → '# full line comment' (unchanged — full comment lines are NOT stripped)
    # Test: 'var s = "has # inside"  # real comment' → 'var s = "has # inside"'
    # Test: 'var x = 42' (no comment) → 'var x = 42' (unchanged)
    # Test: empty string → empty string


class TestSplitArgsDepthAware:
    """Tests for _split_args_depth_aware helper."""

    # Test: "a, b, c" → ["a", "b", "c"]
    # Test: "v: Vector2 = Vector2(1, 2), b: int" → ["v: Vector2 = Vector2(1, 2)", "b: int"]
    # Test: "" → [] (empty string produces empty list)
    # Test: "a" → ["a"] (single arg)
    # Test: "d: Dictionary = {\"a\": 1, \"b\": 2}" → single element (braces respected)
    # Test: "a: Array = [1, 2, 3], b" → ["a: Array = [1, 2, 3]", "b"]


class TestFindMatchingParen:
    """Tests for _find_matching_paren helper."""

    # Test: "foo(bar)" starting at index of '(' → returns index of ')'
    # Test: "foo(bar(baz))" starting at outer '(' → returns index of outer ')'
    # Test: "foo(" with no closing paren → returns -1
    # Test: "foo(a, b)" → returns correct index


class TestParseSignalArgs:
    """Tests for _parse_signal_args helper."""

    # Test: "" → []
    # Test: "amount: float, delta: float" → [("amount", "float"), ("delta", "float")]
    # Test: "a, b" (untyped) → [("a", ""), ("b", "")]
    # Test: "id: String, old: Printer.State, new: Printer.State" → custom type stored as-is


class TestParseFuncArgs:
    """Tests for _parse_func_args helper."""

    # Test: "" → []
    # Test: "amount: float" → [("amount", "float", "")]
    # Test: 'description: String = ""' → [("description", "String", '""')]
    # Test: "v: Vector2 = Vector2(1, 2)" → [("v", "Vector2", "Vector2(1, 2)")]  (depth-aware)
    # Test: "a, b" (untyped, no defaults) → [("a", "", ""), ("b", "", "")]


class TestCountEmitArgs:
    """Tests for _count_emit_args helper."""

    # Test: "" → 0
    # Test: "cash, amount" → 2
    # Test: "a" → 1
    # Test: "Vector2(1, 2), b" → 2 (nested parens not counted as separate args)


class TestParseEnumBody:
    """Tests for _parse_enum_body helper."""

    # Test: "PLAYING, PAUSED, DAILY_SUMMARY" → {"PLAYING": None, "PAUSED": None, "DAILY_SUMMARY": None}
    # Test: "A, B = 5, C" → {"A": None, "B": 5, "C": None}
    # Test: "X = -1" → {"X": -1}
    # Test: "" → {}
    # Test: "  THING_1 ,  THING_2  " → whitespace stripped correctly
```

---

## Implementation Details

### Module Structure

The file `/Users/salvatorefarruggio/Desktop/godotiq/src/godotiq/parsers/gd_parser.py` should be organized in this order:

1. Module docstring
2. Imports (`from __future__ import annotations`, `re`, `logging`, `dataclasses`)
3. Logger setup (`logger = logging.getLogger(__name__)`)
4. Pre-compiled regex patterns (module-level `re.compile()` constants)
5. All 9 dataclasses in dependency order
6. All 7 helper functions
7. Temporary `parse_gd` stub (replaced in section 02)

### Imports

```python
"""Parser for GDScript .gd files.

Extracts signals, functions, class hierarchy, and dependency information
from GDScript source files.
"""

from __future__ import annotations

import logging
import re
from dataclasses import dataclass, field

logger = logging.getLogger(__name__)
```

### Pre-Compiled Regex Patterns

All patterns are compiled at module level for performance, following the convention established by `value_parser.py`. The patterns needed by the dataclasses/helpers section are primarily those used inside the helper functions. The state machine patterns (section 02) and body patterns (section 03) will add more.

Define the following patterns in this section:

```python
# --- Class-level declarations ---
_COMBINED_CLASS_EXTENDS_RE = re.compile(r"^class_name\s+(\w+)\s+extends\s+(.+)$")
_CLASS_NAME_RE = re.compile(r"^class_name\s+(\w+)")
_EXTENDS_RE = re.compile(r"^extends\s+(.+)$")

# --- Signals ---
_SIGNAL_RE = re.compile(r"^signal\s+(\w+)(?:\(([^)]*)\))?")

# --- Functions ---
_FUNC_START_RE = re.compile(r"^(?:static\s+)?func\s+(\w+)\s*\(")

# --- Variables ---
_VAR_RE = re.compile(
    r"^(var|const)\s+(\w+)\s*(?::\s*([^=:]+?))?\s*(?:(?::=|=)\s*(.+))?$"
)

# --- Enums ---
_ENUM_SINGLE_RE = re.compile(r"^enum\s+(\w+)?\s*\{([^}]*)\}")
_ENUM_START_RE = re.compile(r"^enum\s+(\w+)?\s*\{")

# --- Inner classes ---
_INNER_CLASS_RE = re.compile(r"^class\s+(\w+)\s*(?:extends\s+[\w.]+)?\s*:")

# --- Annotations ---
_ANNOTATION_VAR_RE = re.compile(r"^(@\w+(?:\([^)]*\))?)\s+(var|const)\s+")
_STANDALONE_ANNOTATION_RE = re.compile(r"^@(\w+)(?:\(([^)]*)\))?")

# --- Body patterns (used by helpers and section 03) ---
_CONNECT_RE = re.compile(r"\.connect\(")
_EMIT_RE = re.compile(r"(\w+)\.emit\(")
_HAS_NODE_RE = re.compile(r'has_node\(\s*"(/root/[\w/]+)"\s*\)')
_GET_NODE_RE = re.compile(r'get_node\(\s*"(/root/[\w/]+)"\s*\)')
_GET_NODE_OR_NULL_RE = re.compile(r'get_node_or_null\(\s*"([^"]+)"\s*\)')
_IS_INSTANCE_VALID_RE = re.compile(r"is_instance_valid\(")
_PRELOAD_LOAD_RE = re.compile(r'(?:preload|load)\(\s*"([^"]+)"\s*\)')
_PRELOAD_RE = re.compile(r'preload\(\s*"([^"]+)"\s*\)')
```

### Dataclasses (All 9)

Define all 9 dataclasses with every field, type hint, default value, and docstring. This is the full data model.

**Important change from stub:** The existing stub has `GdSignal.args: list[str]` and `GdFunction.args: list[str]`. The plan changes these to `list[tuple[str, str]]` and `list[tuple[str, str, str]]` respectively. The existing import test (`test_scaffolding_int.py`) only checks that the classes are importable and `parse_gd` is callable -- it does not instantiate with args, so this change is safe.

The dataclasses to define (in this order):

1. **GdSignal** -- `name: str`, `args: list[tuple[str, str]]` (name, type_hint), `line: int`
2. **GdFunction** -- `name: str`, `args: list[tuple[str, str, str]]` (name, type, default), `return_type: str`, `is_static: bool`, `is_virtual: bool`, `is_private: bool`, `line: int`, `end_line: int`
3. **GdVariable** -- `name: str`, `type_hint: str`, `default_value: str`, `is_const: bool`, `is_static: bool`, `annotation: str`, `scope: str` (default "class"), `line: int`
4. **GdEnum** -- `name: str`, `values: dict[str, int | None]`, `line: int`
5. **GdSignalConnection** -- `signal_source: str`, `target: str`, `has_bind: bool`, `bind_args: str`, `line: int`
6. **GdSignalEmission** -- `signal_name: str`, `arg_count: int`, `line: int`
7. **GdAutoloadRef** -- `autoload_name: str`, `access: str`, `pattern: str` ("direct" | "has_node" | "get_node" | "get_node_or_null"), `line: int`
8. **GdPreloadRef** -- `path: str`, `is_preload: bool` (default True), `line: int`
9. **GdScript** -- top-level container with `class_name: str`, `extends: str`, and list fields for all the above types, plus `inner_classes: list[str]` and `is_instance_valid_lines: list[int]`

All mutable defaults use `field(default_factory=...)`. Every class has a docstring. See the plan section 3 for exact field definitions and semantics.

### Helper Functions (All 7)

These are internal helper functions (prefixed with `_`) used by the state machine and body pattern detection.

#### `_strip_comment(line: str) -> str`

Strip inline comments from a line, respecting string literals. Scans left-to-right, tracks whether inside `"` or `'` delimiters, strips from the first unquoted `#`. Does NOT strip lines that are entirely comments (those start with `#` after optional whitespace). Returns the line with trailing whitespace stripped after comment removal.

#### `_split_args_depth_aware(args_str: str) -> list[str]`

Split an argument string by commas, respecting nested parentheses `()`, brackets `[]`, and braces `{}`. Tracks depth for each type of bracket. Only splits on commas at depth zero. Returns stripped strings. Empty input returns empty list.

#### `_find_matching_paren(line: str, start: int) -> int`

Find the matching closing parenthesis starting from position `start` (which should point at the opening `(`). Uses depth tracking. Returns the index of the matching `)`, or `-1` if not found. This is used for depth-aware `.connect()` and `.emit()` parsing.

#### `_parse_signal_args(args_str: str) -> list[tuple[str, str]]`

Parse a signal's argument string into `(name, type_hint)` tuples. Splits by comma, then each part is checked for `: Type` pattern. Untyped args get `""` as type_hint. Empty input returns empty list. Uses simple comma splitting (signals don't have complex defaults).

#### `_parse_func_args(args_str: str) -> list[tuple[str, str, str]]`

Parse a function's argument string into `(name, type_hint, default_value)` triples. Uses `_split_args_depth_aware()` to handle defaults containing commas (like `Vector2(1, 2)`). Each arg is parsed for the pattern `name: Type = default`. Missing parts are empty strings. Empty input returns empty list.

#### `_count_emit_args(args_str: str) -> int`

Count arguments in an `.emit()` call by counting commas at depth zero (respecting nested parentheses, brackets, braces). Empty or whitespace-only input returns 0. Otherwise returns comma_count + 1.

#### `_parse_enum_body(body: str) -> dict[str, int | None]`

Parse the body of an enum (the content between `{` and `}`) into a `{name: value}` dict. Splits by comma, each entry checked for `NAME = value` pattern. Supports negative integer values. Entries without explicit values get `None`. Whitespace is stripped. Trailing commas and empty entries are handled gracefully.

### Temporary parse_gd Stub

At the bottom of the file, keep a `parse_gd` stub so existing Sprint 0 tests continue to pass:

```python
def parse_gd(path: str, known_autoloads: list[str] | None = None) -> GdScript:
    """Parse a .gd file into a structured GdScript representation.

    Args:
        path: Absolute or relative path to a .gd file.
        known_autoloads: Optional list of known autoload singleton names
                         for accurate autoload reference detection.

    Returns:
        Parsed GdScript dataclass with all extracted structural information.

    Raises:
        NotImplementedError: Parser not yet implemented (replaced in section 02).
    """
    raise NotImplementedError("gd parser not yet implemented")
```

Note: The existing test `test_parse_gd_stub_raises` calls `parse_gd("")` and expects `NotImplementedError`. This stub preserves that behavior. Section 02 will replace this stub with the real implementation, at which point that Sprint 0 test will need updating (it will get `FileNotFoundError` instead).

---

## Dependencies

- **No upstream dependencies.** This is the foundation section.
- **Downstream consumers:** Section 02 (state machine) and section 03 (body patterns) both import and use the dataclasses and helpers defined here.

---

## Checklist

1. Replace `/Users/salvatorefarruggio/Desktop/godotiq/src/godotiq/parsers/gd_parser.py` with the new content
2. Verify imports: `from __future__ import annotations`, `re`, `logging`, `dataclasses`
3. Logger: `logger = logging.getLogger(__name__)`
4. All pre-compiled regex patterns at module level
5. All 9 dataclasses with correct field types, defaults, and docstrings
6. All 7 helper functions with correct signatures, docstrings, and implementations
7. Temporary `parse_gd` stub at bottom (raises `NotImplementedError`)
8. Existing Sprint 0 tests still pass: `pytest tests/test_server.py tests/test_scaffolding_int.py -v`
9. All symbols importable: `GdSignal`, `GdFunction`, `GdScript`, `parse_gd` (backward compatible)