Now I have all the information needed to write the section. Let me compose the complete self-contained section content.

# Section 13: PACKAGING -- Version Sync

## Background

The GodotIQ project has version numbers declared in three separate locations that must stay in sync:

1. **`/Users/salvatorefarruggio/Desktop/godotiq/pyproject.toml`** -- the single source of truth, currently `version = "0.1.3"` (line 7)
2. **`/Users/salvatorefarruggio/Desktop/godotiq/godot-addon/addons/godotiq/plugin.cfg`** -- the Godot addon metadata, currently `version="0.1.0"` (line 6)
3. **`/Users/salvatorefarruggio/Desktop/godotiq/godot-addon/addons/godotiq/godotiq_server.gd`** -- a GDScript constant, currently `const ADDON_VERSION := "0.1.0"` (line 7)

Both `plugin.cfg` and `godotiq_server.gd` are stuck at `"0.1.0"` while `pyproject.toml` has already advanced. This section creates a sync script that reads the version from `pyproject.toml` and patches the other two files.

## Dependencies

None. This section is fully independent.

Section 15 (`section-15-cli-warning`) depends on this section being complete first (the version sync script must exist before CLI version logic references it).

## Files to Create

- `/Users/salvatorefarruggio/Desktop/godotiq/scripts/sync_version.py` -- the sync script (new file)
- `/Users/salvatorefarruggio/Desktop/godotiq/tests/test_version_sync.py` -- tests (new file)

## Files to Modify

None directly. The script modifies `plugin.cfg` and `godotiq_server.gd` when run, but this section only creates the script and its tests.

---

## Tests FIRST

Create `/Users/salvatorefarruggio/Desktop/godotiq/tests/test_version_sync.py`.

There are four tests, all pure unit tests with no async or bridge dependencies. They use `tmp_path` to create temporary copies of the target files so the real files are never modified during testing.

```python
"""Tests for scripts/sync_version.py version synchronization."""

import textwrap
from pathlib import Path

import pytest


class TestSyncVersion:
    """Verify sync_version reads pyproject.toml and patches target files."""

    def test_reads_version_from_pyproject_toml(self, tmp_path):
        """sync_version extracts the correct version string from pyproject.toml."""
        # Create a minimal pyproject.toml with a known version
        # Call the extraction function and assert it returns that version

    def test_updates_plugin_cfg_version_line(self, tmp_path):
        """sync_version replaces the version= line in plugin.cfg."""
        # Create a plugin.cfg with version="0.1.0"
        # Run sync on it with version "0.1.4"
        # Assert the file now contains version="0.1.4"
        # Assert other lines (name, description, etc.) are untouched

    def test_updates_godotiq_server_gd_addon_version(self, tmp_path):
        """sync_version replaces the ADDON_VERSION const in godotiq_server.gd."""
        # Create a godotiq_server.gd stub with const ADDON_VERSION := "0.1.0"
        # Run sync on it with version "0.1.4"
        # Assert the file now contains const ADDON_VERSION := "0.1.4"
        # Assert other lines are untouched

    def test_full_sync_with_version_0_1_4(self, tmp_path):
        """End-to-end: all three files agree on "0.1.4" after sync."""
        # Create all three files in tmp_path with stale versions
        # Run the main sync function pointing at tmp_path as the project root
        # Assert plugin.cfg contains "0.1.4"
        # Assert godotiq_server.gd contains "0.1.4"
```

### Test fixture content

Each test creates temporary files with realistic content. The key patterns to match are:

- `pyproject.toml`: contains a line `version = "X.Y.Z"` (with spaces around `=` and double quotes)
- `plugin.cfg`: contains a line `version="X.Y.Z"` (no spaces around `=`, double quotes)
- `godotiq_server.gd`: contains a line `const ADDON_VERSION := "X.Y.Z"` (GDScript constant syntax)

The tests must verify that ONLY the version-bearing line is changed; all other content remains identical.

---

## Implementation

### Script: `/Users/salvatorefarruggio/Desktop/godotiq/scripts/sync_version.py`

This is a standalone script (not part of the installed package). It is run manually or as part of a release workflow before building.

#### Structure

The script should expose three public functions plus a `main()` entry point:

1. **`read_version(pyproject_path: Path) -> str`** -- Parse `pyproject.toml` and return the `version` value. Use `tomllib` (Python 3.11+) with a fallback to `tomli` for Python 3.10. If neither is available, fall back to regex extraction: match the pattern `^version\s*=\s*"([^"]+)"` against the file contents. This regex approach is acceptable because `pyproject.toml` has a simple, predictable structure.

2. **`update_plugin_cfg(cfg_path: Path, version: str) -> bool`** -- Read `plugin.cfg`, replace the line matching `version="..."` with `version="{version}"`, write back. Return `True` if the file was modified, `False` if the version was already correct.

3. **`update_server_gd(gd_path: Path, version: str) -> bool`** -- Read `godotiq_server.gd`, replace the line matching `const ADDON_VERSION := "..."` with `const ADDON_VERSION := "{version}"`, write back. Return `True` if modified, `False` if already correct.

4. **`sync_all(project_root: Path) -> None`** -- Orchestrator that calls the above three functions with the correct relative paths from project root:
   - `project_root / "pyproject.toml"`
   - `project_root / "godot-addon" / "addons" / "godotiq" / "plugin.cfg"`
   - `project_root / "godot-addon" / "addons" / "godotiq" / "godotiq_server.gd"`
   
   Prints status for each file (e.g., `"Updated plugin.cfg: 0.1.0 -> 0.1.4"` or `"plugin.cfg already at 0.1.4"`).

5. **`main()` / `if __name__ == "__main__":`** -- Determine project root (parent of the `scripts/` directory, i.e., `Path(__file__).resolve().parent.parent`), then call `sync_all(project_root)`.

#### Regex patterns

For `read_version`, the TOML regex pattern (used when `tomllib`/`tomli` are unavailable):
```
^version\s*=\s*"([^"]+)"
```
Search with `re.MULTILINE` flag so `^` matches line starts.

For `update_plugin_cfg`, the replacement regex:
```
^version="[^"]*"
```
Replace with `version="{new_version}"`. Use `re.MULTILINE`.

For `update_server_gd`, the replacement regex:
```
^const ADDON_VERSION := "[^"]*"
```
Replace with `const ADDON_VERSION := "{new_version}"`. Use `re.MULTILINE`.

#### Python version compatibility

The project supports Python 3.10+. `tomllib` was added in Python 3.11. The script should try `tomllib` first, then fall back to regex. There is no need to add `tomli` as a dependency -- the regex fallback is sufficient for this narrow use case (reading a single key from `pyproject.toml`).

```python
def read_version(pyproject_path: Path) -> str:
    """Read the version string from pyproject.toml."""
    # Try tomllib (3.11+), fall back to regex
```

#### Current file contents (for reference)

**`pyproject.toml`** line 7:
```
version = "0.1.3"
```

**`plugin.cfg`** line 6:
```
version="0.1.0"
```

**`godotiq_server.gd`** line 7:
```
const ADDON_VERSION := "0.1.0"
```

#### Error handling

- If `pyproject.toml` does not exist or cannot be read, raise `FileNotFoundError` with a clear message.
- If the version pattern is not found in `pyproject.toml`, raise `ValueError("Could not find version in pyproject.toml")`.
- If `plugin.cfg` or `godotiq_server.gd` do not exist, print a warning and skip (they might not be present in all checkout configurations).
- If the regex replacement in a target file matches zero times, print a warning (pattern may have changed).

#### Usage

After implementation, the script is invoked as:
```bash
python scripts/sync_version.py
```

This should be run before `python -m build` during a release. The script prints what was updated for visibility, for example:
```
Reading version from pyproject.toml: 0.1.4
Updated plugin.cfg: 0.1.0 -> 0.1.4
Updated godotiq_server.gd: 0.1.0 -> 0.1.4
```

Or if already synced:
```
Reading version from pyproject.toml: 0.1.4
plugin.cfg already at 0.1.4
godotiq_server.gd already at 0.1.4
```

---

## Implementation Results

### Files Created
- `scripts/__init__.py` — package marker for import support
- `scripts/sync_version.py` — version sync script with 5 public functions
- `tests/test_version_sync.py` — 5 tests (4 from plan + 1 extra no-change test)

### Deviations from Plan
1. **Tri-state return values**: `update_plugin_cfg` and `update_server_gd` return `bool | None` instead of `bool`. `None` indicates pattern not found (distinct from `False` = already correct). This was a code review fix to prevent misleading "already at" messages when the pattern is missing.
2. **Helper functions added**: `_report_update` and `_extract_current` private helpers handle status reporting and old-version extraction for the `old -> new` format.
3. **Extra test**: `test_no_change_when_already_synced` added beyond the 4 planned tests.